diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 5e54a0f6aced..d286056af0da 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -28,7 +28,7 @@ on: env: __1K_CXXSTD: '${{ inputs.cxxstd }}' -run-name: 'build@c++${{ inputs.cxxstd || 20 }}' +run-name: 'build@c++${{ inputs.cxxstd || 23 }}' jobs: win32: @@ -180,3 +180,12 @@ jobs: token: ${{ secrets.AX_TRIGGER_SITE_TOKEN }} repository: axmolengine/axmol.dev event-type: forward-push + wasm64: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + with: + submodules: 'recursive' + - name: Build + shell: pwsh + run: ./tools/cmdline/axmol -p wasm64 -xc '-DAX_ENABLE_EXT_EFFEKSEER=ON,-DAX_WASM_THREADS=8' -j2 -t 'cpp-tests,fairygui-tests,lua-tests' diff --git a/.gitignore b/.gitignore index 695db45212ac..dea82700d141 100644 --- a/.gitignore +++ b/.gitignore @@ -51,8 +51,8 @@ gen/ assets/ local.properties -/core/axmolver.h -/core/renderer/RenderConsts.h +/axmol/axmolver.h +/axmol/renderer/RenderConsts.h # Ignore python compiled files *.pyc diff --git a/1k/1kiss.ps1 b/1k/1kiss.ps1 index 638bc402f033..fce1328547a1 100644 --- a/1k/1kiss.ps1 +++ b/1k/1kiss.ps1 @@ -772,7 +772,7 @@ function download_and_expand($url, $out, $dest) { $1k.mkdirs($dest) if ($out.EndsWith('.zip')) { if ($IsWin) { - Expand-Archive -Path $out -DestinationPath $dest + Expand-Archive -Path $out -DestinationPath $dest -Force } else { unzip -d $dest $out | Out-Null @@ -995,6 +995,11 @@ function setup_axslcc() { return $axslcc_prog } + $axslcc_prog = (Join-Path $axslcc_bin "axslcc$EXE_SUFFIX") + if($1k.isfile($axslcc_prog)) { + $1k.del($axslcc_prog) + } + $suffix = @('win64.zip', 'linux.tar.gz', 'osx{0}.tar.gz')[$HOST_OS_INT] if ($IsMacOS) { if ([System.VersionEx]$axslcc_ver -ge [System.VersionEx]'1.9.4.1') { @@ -1008,7 +1013,6 @@ function setup_axslcc() { $glscc_base_url = $mirror_current.axslcc fetch_pkg "$mirror_url_base$glscc_base_url/v$axslcc_ver/axslcc-$axslcc_ver-$suffix" -exrep "axslcc" - $axslcc_prog = (Join-Path $axslcc_bin "axslcc$EXE_SUFFIX") if ($1k.isfile($axslcc_prog)) { $1k.println("Using axslcc: $axslcc_prog, version: $axslcc_ver") } else { @@ -1211,7 +1215,7 @@ function setup_unzip() { $unzip_cmd_info = Get-Command 'unzip' -ErrorAction SilentlyContinue if (!$unzip_cmd_info) { if ($IsLinux) { - if ($(which dpkg)) { + if ($(which dpkg)) { sudo apt install unzip } elseif($(which pacman)) { @@ -1323,7 +1327,7 @@ function setup_android_sdk() { return $null } $1k.println("Looking require $ndk_ver$IsGraterThan in $sdk_dir") - + $ndk_major = ($ndk_ver -replace '[^0-9]', '') $ndk_minor_off = "$ndk_major".Length + 1 $ndk_minor = if ($ndk_minor_off -lt $ndk_ver.Length) { "$([int][char]$ndk_ver.Substring($ndk_minor_off) - $ndk_minor_base)" } else { '0' } @@ -1367,7 +1371,7 @@ function setup_android_sdk() { } $ndk_root = &$find_ndk_in $selected_sdk_root - + $sdk_comps = @() ### cmdline-tools ### diff --git a/1k/build.profiles b/1k/build.profiles index 1e305619c1f0..8c022737d793 100644 --- a/1k/build.profiles +++ b/1k/build.profiles @@ -5,8 +5,10 @@ # --- region platfom:common -# The axmol shader compiler, legacy name is 'glslcc' before axmol-2.3.0 -axslcc=1.9.6+ +# The axmol shader compiler, +# before axmol-2.3.0, it's 'glslcc' +# before axmol-3.0.0, it's 'axslcc' +axslcc=1.11.0+ # The cmake, @gradle @axmol-cmdline # as latest as possible @@ -27,7 +29,7 @@ nuget=5.5.1.* vs=17.0+ # as stable and latest as possible, @axmol-cmdline @genbindings.ps1 -llvm=19.0.0~19.1.7+ +llvm=20.1.8+ # --- endregion @@ -46,7 +48,7 @@ cmdlinetools=19.0 # - https://developer.android.google.cn/about/versions/15/behavior-changes-all?hl=zh-cn#16-kb # In China Mainland, please download from https://pan.baidu.com/s/1neJydxOGTT7aCQvLLwbicw?pwd=qqiq # to $AX_ROOT/cache/, then run `setup.ps1 -p android` -ndk=r23d +ndk=r27d # The android target sdk version, @gradle # as latest as possible @@ -54,7 +56,7 @@ target_sdk=36 # The android min sdk version, @gradle # as min as possible -min_sdk=17 +min_sdk=21 # The gradle version, @setup.ps1 # as latest as possible diff --git a/1k/ios.cmake b/1k/ios.cmake index 5b72761df405..eaa3630621d9 100644 --- a/1k/ios.cmake +++ b/1k/ios.cmake @@ -35,7 +35,7 @@ if(NOT DEFINED DEPLOYMENT_TARGET) if(XCODE_VERSION LESS "14.3.0") set(DEPLOYMENT_TARGET "11.0" CACHE STRING "" FORCE) else() # xcode 14.3+ require 12.0 for c++ std::get - set(DEPLOYMENT_TARGET "12.0" CACHE STRING "" FORCE) + set(DEPLOYMENT_TARGET "13.0" CACHE STRING "" FORCE) endif() endif() elseif(PLAT STREQUAL "tvOS") diff --git a/1k/manifest.ps1 b/1k/manifest.ps1 index a0aa249ace3e..5c30752d8506 100644 --- a/1k/manifest.ps1 +++ b/1k/manifest.ps1 @@ -25,7 +25,7 @@ $manifest['cmdlinetools'] = $build_profiles['cmdlinetools'] $Global:build_profiles = $build_profiles $Global:download_path = $1k.realpath("$PSScriptRoot/../cache") - + # add or overwrite tool version like follow if ($Global:is_axmol_app -or $Global:is_axmol_engine) { $manifest['axslcc'] = $build_profiles['axslcc'] diff --git a/3rdparty/CMakeLists.txt b/3rdparty/CMakeLists.txt index fef8e0984e8c..9dc9ad513439 100644 --- a/3rdparty/CMakeLists.txt +++ b/3rdparty/CMakeLists.txt @@ -162,22 +162,6 @@ if(AX_ENABLE_PHYSICS) ax_add_3rd(box2d OPTIONS ${box2d_opts}) endif() -if(AX_ENABLE_PHYSICS) - ax_add_3rd(chipmunk OPTIONS - "CP_BUILD_SHARED OFF" - "CP_BUILD_STATIC ON" - "CP_BUILD_DEMOS OFF" - "CP_INSTALL_STATIC OFF" - ) - set_target_properties(chipmunk PROPERTIES - INTERFACE_INCLUDE_DIRECTORIES "${CMAKE_CURRENT_SOURCE_DIR}/chipmunk/include" - ) - - # !important axmol not use double precision - target_compile_definitions(chipmunk PUBLIC CP_USE_CGTYPES=0) - target_compile_definitions(chipmunk PUBLIC CP_USE_DOUBLES=0) -endif() - ax_add_3rd(freetype OPTIONS "DISABLE_FORCE_DEBUG_POSTFIX ON" "SKIP_INSTALL_ALL TRUE" @@ -301,11 +285,11 @@ if(AX_ENABLE_AUDIO) set(ALSOFT_CPPWINRT_VERSION ${AX_CPPWINRT_VERSION} CACHE STRING "" FORCE) endif() - ax_add_3rd(openal EXCLUDE_FROM_ALL TARGETS alcommon;OpenAL OPTIONS ${alsoft_opts}) + ax_add_3rd(openal EXCLUDE_FROM_ALL TARGETS OpenAL;alsoft.common OPTIONS ${alsoft_opts}) target_include_directories(3rdparty INTERFACE openal) target_compile_definitions(3rdparty INTERFACE AX_USE_ALSOFT=1) - set_target_properties(OpenAL alcommon PROPERTIES CXX_STANDARD ${_AX_CXX_STD}) + set_target_properties(OpenAL alsoft.common PROPERTIES CXX_STANDARD ${_AX_CXX_STD}) if(AX_USE_ALSOFT_STATIC) target_compile_definitions(3rdparty INTERFACE AL_LIBTYPE_STATIC=1) diff --git a/3rdparty/README.md b/3rdparty/README.md index b9f902302f84..9730d4d3de93 100644 --- a/3rdparty/README.md +++ b/3rdparty/README.md @@ -11,7 +11,7 @@ ## Box2D - [![Upstream](https://img.shields.io/github/v/release/erincatto/box2d?label=Upstream)](https://github.com/erincatto/box2d) -- Version: 2.4.2 +- Version: 3.1.1 - License: MIT ## Bullet @@ -25,11 +25,6 @@ - Version: 1.34.5 - License: MIT -## Chipmunk2D -- [![Upstream](https://img.shields.io/github/v/tag/slembcke/Chipmunk2D?label=Upstream)](https://github.com/slembcke/Chipmunk2D) -- Version: git 7.0.3-0cb05e7 {until Dec 16, 2021} -- License: MIT - ## Clipper2 - [![Upstream](https://img.shields.io/github/v/tag/AngusJohnson/Clipper2?label=Upstream)](https://github.com/AngusJohnson/Clipper2) - Version: 1.5.4 @@ -60,6 +55,11 @@ - Version: git 344eb40 (121) - License: MIT +## fast_float +- [![Upstream](https://img.shields.io/github/v/release/fastfloat/fast_float?label=Upstream)](https://github.com/fastfloat/fast_float) +- Version: 8.0.2 +- License: MIT + ## flatbuffers - [![Upstream](https://img.shields.io/github/v/release/google/flatbuffers?label=Upstream)](https://github.com/google/flatbuffers) - Version: 25.2.10 @@ -86,7 +86,7 @@ - Version: 3.4 with modified for create as win32 child window support - License: zlib -## GHC (iOS devices only) +## ghc (iOS < 13 ONLY) - [![Upstream](https://img.shields.io/github/v/release/gulrak/filesystem?label=Upstream)](https://github.com/gulrak/filesystem) - Version: 1.5.14 - License: MIT @@ -180,7 +180,11 @@ ## OpenAL Soft - [![Upstream](https://img.shields.io/github/v/tag/kcat/openal-soft?label=Upstream)](https://github.com/kcat/openal-soft) -- Version: 1.23.1-e714c8f (8659) +- Version: 1.24.3 +- Modifications: + - Remove `-Werror=undef` + - Linking `fmt::fmt` instead `alsoft::fmt` + - Exclude target `alsoft::excommon` - License: LGPL-2.1 ## OpenSSL @@ -225,7 +229,7 @@ ## simdjson - [![Upstream](https://img.shields.io/github/v/tag/simdjson/simdjson?label=Upstream)](https://github.com/simdjson/simdjson) -- Version: 3.10.1 +- Version: 3.13.0 - License: Apache-2.0 ## stb (stb_image) diff --git a/3rdparty/box2d/CMakeLists.txt b/3rdparty/box2d/CMakeLists.txt index fa8be6a69162..421d97bc5676 100644 --- a/3rdparty/box2d/CMakeLists.txt +++ b/3rdparty/box2d/CMakeLists.txt @@ -4,105 +4,31 @@ set(target_name ${lib_name}) project(${lib_name}) -set(BOX2D_SOURCE_FILES - src/collision/b2_broad_phase.cpp - src/collision/b2_chain_shape.cpp - src/collision/b2_circle_shape.cpp - src/collision/b2_collide_circle.cpp - src/collision/b2_collide_edge.cpp - src/collision/b2_collide_polygon.cpp - src/collision/b2_collision.cpp - src/collision/b2_distance.cpp - src/collision/b2_dynamic_tree.cpp - src/collision/b2_edge_shape.cpp - src/collision/b2_polygon_shape.cpp - src/collision/b2_time_of_impact.cpp - src/common/b2_block_allocator.cpp - src/common/b2_draw.cpp - src/common/b2_math.cpp - src/common/b2_settings.cpp - src/common/b2_stack_allocator.cpp - src/common/b2_timer.cpp - src/dynamics/b2_body.cpp - src/dynamics/b2_chain_circle_contact.cpp - src/dynamics/b2_chain_circle_contact.h - src/dynamics/b2_chain_polygon_contact.cpp - src/dynamics/b2_chain_polygon_contact.h - src/dynamics/b2_circle_contact.cpp - src/dynamics/b2_circle_contact.h - src/dynamics/b2_contact.cpp - src/dynamics/b2_contact_manager.cpp - src/dynamics/b2_contact_solver.cpp - src/dynamics/b2_contact_solver.h - src/dynamics/b2_distance_joint.cpp - src/dynamics/b2_edge_circle_contact.cpp - src/dynamics/b2_edge_circle_contact.h - src/dynamics/b2_edge_polygon_contact.cpp - src/dynamics/b2_edge_polygon_contact.h - src/dynamics/b2_fixture.cpp - src/dynamics/b2_friction_joint.cpp - src/dynamics/b2_gear_joint.cpp - src/dynamics/b2_island.cpp - src/dynamics/b2_island.h - src/dynamics/b2_joint.cpp - src/dynamics/b2_motor_joint.cpp - src/dynamics/b2_mouse_joint.cpp - src/dynamics/b2_polygon_circle_contact.cpp - src/dynamics/b2_polygon_circle_contact.h - src/dynamics/b2_polygon_contact.cpp - src/dynamics/b2_polygon_contact.h - src/dynamics/b2_prismatic_joint.cpp - src/dynamics/b2_pulley_joint.cpp - src/dynamics/b2_revolute_joint.cpp - src/dynamics/b2_weld_joint.cpp - src/dynamics/b2_wheel_joint.cpp - src/dynamics/b2_world.cpp - src/dynamics/b2_world_callbacks.cpp - src/rope/b2_rope.cpp) +file(GLOB_RECURSE box2d_sources *.h;*.c) -set(BOX2D_HEADER_FILES - include/box2d/b2_api.h - include/box2d/b2_block_allocator.h - include/box2d/b2_body.h - include/box2d/b2_broad_phase.h - include/box2d/b2_chain_shape.h - include/box2d/b2_circle_shape.h - include/box2d/b2_collision.h - include/box2d/b2_common.h - include/box2d/b2_contact.h - include/box2d/b2_contact_manager.h - include/box2d/b2_distance.h - include/box2d/b2_distance_joint.h - include/box2d/b2_draw.h - include/box2d/b2_dynamic_tree.h - include/box2d/b2_edge_shape.h - include/box2d/b2_fixture.h - include/box2d/b2_friction_joint.h - include/box2d/b2_gear_joint.h - include/box2d/b2_growable_stack.h - include/box2d/b2_joint.h - include/box2d/b2_math.h - include/box2d/b2_motor_joint.h - include/box2d/b2_mouse_joint.h - include/box2d/b2_polygon_shape.h - include/box2d/b2_prismatic_joint.h - include/box2d/b2_pulley_joint.h - include/box2d/b2_revolute_joint.h - include/box2d/b2_rope.h - include/box2d/b2_settings.h - include/box2d/b2_shape.h - include/box2d/b2_stack_allocator.h - include/box2d/b2_time_of_impact.h - include/box2d/b2_timer.h - include/box2d/b2_time_step.h - include/box2d/b2_types.h - include/box2d/b2_weld_joint.h - include/box2d/b2_wheel_joint.h - include/box2d/b2_world.h - include/box2d/b2_world_callbacks.h - include/box2d/box2d.h) +add_library(${target_name} ${box2d_sources}) -add_library(${target_name} STATIC ${BOX2D_SOURCE_FILES} ${BOX2D_HEADER_FILES}) +if(MSVC) + if(BUILD_SHARED_LIBS) + # this is needed by DLL users to import Box2D symbols + target_compile_definitions(box2d INTERFACE BOX2D_DLL) + endif() +endif() + +# Atomics are still considered experimental in Visual Studio 17.8 +if(FULL_MSVC) + target_compile_options(box2d PRIVATE /experimental:c11atomics) +endif() + +set_target_properties(${target_name} PROPERTIES C_STANDARD 17 C_STANDARD_REQUIRED TRUE) + +if(_simdc_defines) + target_compile_definitions(${target_name} PRIVATE ${_simdc_defines}) + + if(_simdc_options) + target_compile_options(${target_name} PRIVATE ${_simdc_options}) + endif() +endif() target_include_directories(${target_name} PUBLIC "${CMAKE_CURRENT_SOURCE_DIR}/include" diff --git a/3rdparty/box2d/include/box2d/b2_api.h b/3rdparty/box2d/include/box2d/b2_api.h deleted file mode 100644 index 6730203c64b1..000000000000 --- a/3rdparty/box2d/include/box2d/b2_api.h +++ /dev/null @@ -1,52 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_API_H -#define B2_API_H - -#ifdef B2_SHARED - #if defined _WIN32 || defined __CYGWIN__ - #ifdef box2d_EXPORTS - #ifdef __GNUC__ - #define B2_API __attribute__ ((dllexport)) - #else - #define B2_API __declspec(dllexport) - #endif - #else - #ifdef __GNUC__ - #define B2_API __attribute__ ((dllimport)) - #else - #define B2_API __declspec(dllimport) - #endif - #endif - #else - #if __GNUC__ >= 4 - #define B2_API __attribute__ ((visibility ("default"))) - #else - #define B2_API - #endif - #endif -#else - #define B2_API -#endif - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_block_allocator.h b/3rdparty/box2d/include/box2d/b2_block_allocator.h deleted file mode 100644 index 95c12de89cd8..000000000000 --- a/3rdparty/box2d/include/box2d/b2_block_allocator.h +++ /dev/null @@ -1,60 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_BLOCK_ALLOCATOR_H -#define B2_BLOCK_ALLOCATOR_H - -#include "b2_api.h" -#include "b2_settings.h" - -const int32 b2_blockSizeCount = 14; - -struct b2Block; -struct b2Chunk; - -/// This is a small object allocator used for allocating small -/// objects that persist for more than one time step. -/// See: http://www.codeproject.com/useritems/Small_Block_Allocator.asp -class B2_API b2BlockAllocator -{ -public: - b2BlockAllocator(); - ~b2BlockAllocator(); - - /// Allocate memory. This will use b2Alloc if the size is larger than b2_maxBlockSize. - void* Allocate(int32 size); - - /// Free memory. This will use b2Free if the size is larger than b2_maxBlockSize. - void Free(void* p, int32 size); - - void Clear(); - -private: - - b2Chunk* m_chunks; - int32 m_chunkCount; - int32 m_chunkSpace; - - b2Block* m_freeLists[b2_blockSizeCount]; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_body.h b/3rdparty/box2d/include/box2d/b2_body.h deleted file mode 100644 index 16b2bb002c78..000000000000 --- a/3rdparty/box2d/include/box2d/b2_body.h +++ /dev/null @@ -1,885 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_BODY_H -#define B2_BODY_H - -#include "b2_api.h" -#include "b2_math.h" -#include "b2_shape.h" - -class b2Fixture; -class b2Joint; -class b2Contact; -class b2Controller; -class b2World; -struct b2FixtureDef; -struct b2JointEdge; -struct b2ContactEdge; - -/// The body type. -/// static: zero mass, zero velocity, may be manually moved -/// kinematic: zero mass, non-zero velocity set by user, moved by solver -/// dynamic: positive mass, non-zero velocity determined by forces, moved by solver -enum b2BodyType -{ - b2_staticBody = 0, - b2_kinematicBody, - b2_dynamicBody -}; - -/// A body definition holds all the data needed to construct a rigid body. -/// You can safely re-use body definitions. Shapes are added to a body after construction. -struct B2_API b2BodyDef -{ - /// This constructor sets the body definition default values. - b2BodyDef() - { - position.Set(0.0f, 0.0f); - angle = 0.0f; - linearVelocity.Set(0.0f, 0.0f); - angularVelocity = 0.0f; - linearDamping = 0.0f; - angularDamping = 0.0f; - allowSleep = true; - awake = true; - fixedRotation = false; - bullet = false; - type = b2_staticBody; - enabled = true; - gravityScale = 1.0f; - } - - /// The body type: static, kinematic, or dynamic. - /// Note: if a dynamic body would have zero mass, the mass is set to one. - b2BodyType type; - - /// The world position of the body. Avoid creating bodies at the origin - /// since this can lead to many overlapping shapes. - b2Vec2 position; - - /// The world angle of the body in radians. - float angle; - - /// The linear velocity of the body's origin in world co-ordinates. - b2Vec2 linearVelocity; - - /// The angular velocity of the body. - float angularVelocity; - - /// Linear damping is use to reduce the linear velocity. The damping parameter - /// can be larger than 1.0f but the damping effect becomes sensitive to the - /// time step when the damping parameter is large. - /// Units are 1/time - float linearDamping; - - /// Angular damping is use to reduce the angular velocity. The damping parameter - /// can be larger than 1.0f but the damping effect becomes sensitive to the - /// time step when the damping parameter is large. - /// Units are 1/time - float angularDamping; - - /// Set this flag to false if this body should never fall asleep. Note that - /// this increases CPU usage. - bool allowSleep; - - /// Is this body initially awake or sleeping? - bool awake; - - /// Should this body be prevented from rotating? Useful for characters. - bool fixedRotation; - - /// Is this a fast moving body that should be prevented from tunneling through - /// other moving bodies? Note that all bodies are prevented from tunneling through - /// kinematic and static bodies. This setting is only considered on dynamic bodies. - /// @warning You should use this flag sparingly since it increases processing time. - bool bullet; - - /// Does this body start out enabled? - bool enabled; - - /// Use this to store application specific body data. - b2BodyUserData userData; - - /// Scale the gravity applied to this body. - float gravityScale; -}; - -/// A rigid body. These are created via b2World::CreateBody. -class B2_API b2Body -{ -public: - /// Creates a fixture and attach it to this body. Use this function if you need - /// to set some fixture parameters, like friction. Otherwise you can create the - /// fixture directly from a shape. - /// If the density is non-zero, this function automatically updates the mass of the body. - /// Contacts are not created until the next time step. - /// @param def the fixture definition. - /// @warning This function is locked during callbacks. - b2Fixture* CreateFixture(const b2FixtureDef* def); - - /// Creates a fixture from a shape and attach it to this body. - /// This is a convenience function. Use b2FixtureDef if you need to set parameters - /// like friction, restitution, user data, or filtering. - /// If the density is non-zero, this function automatically updates the mass of the body. - /// @param shape the shape to be cloned. - /// @param density the shape density (set to zero for static bodies). - /// @warning This function is locked during callbacks. - b2Fixture* CreateFixture(const b2Shape* shape, float density); - - /// Destroy a fixture. This removes the fixture from the broad-phase and - /// destroys all contacts associated with this fixture. This will - /// automatically adjust the mass of the body if the body is dynamic and the - /// fixture has positive density. - /// All fixtures attached to a body are implicitly destroyed when the body is destroyed. - /// @param fixture the fixture to be removed. - /// @warning This function is locked during callbacks. - void DestroyFixture(b2Fixture* fixture); - - /// Set the position of the body's origin and rotation. - /// Manipulating a body's transform may cause non-physical behavior. - /// Note: contacts are updated on the next call to b2World::Step. - /// @param position the world position of the body's local origin. - /// @param angle the world rotation in radians. - void SetTransform(const b2Vec2& position, float angle); - - /// Get the body transform for the body's origin. - /// @return the world transform of the body's origin. - const b2Transform& GetTransform() const; - - /// Get the world body origin position. - /// @return the world position of the body's origin. - const b2Vec2& GetPosition() const; - - /// Get the angle in radians. - /// @return the current world rotation angle in radians. - float GetAngle() const; - - /// Get the world position of the center of mass. - const b2Vec2& GetWorldCenter() const; - - /// Get the local position of the center of mass. - const b2Vec2& GetLocalCenter() const; - - /// Set the linear velocity of the center of mass. - /// @param v the new linear velocity of the center of mass. - void SetLinearVelocity(const b2Vec2& v); - - /// Get the linear velocity of the center of mass. - /// @return the linear velocity of the center of mass. - const b2Vec2& GetLinearVelocity() const; - - /// Set the angular velocity. - /// @param omega the new angular velocity in radians/second. - void SetAngularVelocity(float omega); - - /// Get the angular velocity. - /// @return the angular velocity in radians/second. - float GetAngularVelocity() const; - - /// Apply a force at a world point. If the force is not - /// applied at the center of mass, it will generate a torque and - /// affect the angular velocity. This wakes up the body. - /// @param force the world force vector, usually in Newtons (N). - /// @param point the world position of the point of application. - /// @param wake also wake up the body - void ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake); - - /// Apply a force to the center of mass. This wakes up the body. - /// @param force the world force vector, usually in Newtons (N). - /// @param wake also wake up the body - void ApplyForceToCenter(const b2Vec2& force, bool wake); - - /// Apply a torque. This affects the angular velocity - /// without affecting the linear velocity of the center of mass. - /// @param torque about the z-axis (out of the screen), usually in N-m. - /// @param wake also wake up the body - void ApplyTorque(float torque, bool wake); - - /// Apply an impulse at a point. This immediately modifies the velocity. - /// It also modifies the angular velocity if the point of application - /// is not at the center of mass. This wakes up the body. - /// @param impulse the world impulse vector, usually in N-seconds or kg-m/s. - /// @param point the world position of the point of application. - /// @param wake also wake up the body - void ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake); - - /// Apply an impulse to the center of mass. This immediately modifies the velocity. - /// @param impulse the world impulse vector, usually in N-seconds or kg-m/s. - /// @param wake also wake up the body - void ApplyLinearImpulseToCenter(const b2Vec2& impulse, bool wake); - - /// Apply an angular impulse. - /// @param impulse the angular impulse in units of kg*m*m/s - /// @param wake also wake up the body - void ApplyAngularImpulse(float impulse, bool wake); - - /// Get the total mass of the body. - /// @return the mass, usually in kilograms (kg). - float GetMass() const; - - /// Get the rotational inertia of the body about the local origin. - /// @return the rotational inertia, usually in kg-m^2. - float GetInertia() const; - - /// Get the mass data of the body. - /// @return a struct containing the mass, inertia and center of the body. - b2MassData GetMassData() const; - - /// Set the mass properties to override the mass properties of the fixtures. - /// Note that this changes the center of mass position. - /// Note that creating or destroying fixtures can also alter the mass. - /// This function has no effect if the body isn't dynamic. - /// @param data the mass properties. - void SetMassData(const b2MassData* data); - - /// This resets the mass properties to the sum of the mass properties of the fixtures. - /// This normally does not need to be called unless you called SetMassData to override - /// the mass and you later want to reset the mass. - void ResetMassData(); - - /// Get the world coordinates of a point given the local coordinates. - /// @param localPoint a point on the body measured relative the the body's origin. - /// @return the same point expressed in world coordinates. - b2Vec2 GetWorldPoint(const b2Vec2& localPoint) const; - - /// Get the world coordinates of a vector given the local coordinates. - /// @param localVector a vector fixed in the body. - /// @return the same vector expressed in world coordinates. - b2Vec2 GetWorldVector(const b2Vec2& localVector) const; - - /// Gets a local point relative to the body's origin given a world point. - /// @param worldPoint a point in world coordinates. - /// @return the corresponding local point relative to the body's origin. - b2Vec2 GetLocalPoint(const b2Vec2& worldPoint) const; - - /// Gets a local vector given a world vector. - /// @param worldVector a vector in world coordinates. - /// @return the corresponding local vector. - b2Vec2 GetLocalVector(const b2Vec2& worldVector) const; - - /// Get the world linear velocity of a world point attached to this body. - /// @param worldPoint a point in world coordinates. - /// @return the world velocity of a point. - b2Vec2 GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const; - - /// Get the world velocity of a local point. - /// @param localPoint a point in local coordinates. - /// @return the world velocity of a point. - b2Vec2 GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const; - - /// Get the linear damping of the body. - float GetLinearDamping() const; - - /// Set the linear damping of the body. - void SetLinearDamping(float linearDamping); - - /// Get the angular damping of the body. - float GetAngularDamping() const; - - /// Set the angular damping of the body. - void SetAngularDamping(float angularDamping); - - /// Get the gravity scale of the body. - float GetGravityScale() const; - - /// Set the gravity scale of the body. - void SetGravityScale(float scale); - - /// Set the type of this body. This may alter the mass and velocity. - void SetType(b2BodyType type); - - /// Get the type of this body. - b2BodyType GetType() const; - - /// Should this body be treated like a bullet for continuous collision detection? - void SetBullet(bool flag); - - /// Is this body treated like a bullet for continuous collision detection? - bool IsBullet() const; - - /// You can disable sleeping on this body. If you disable sleeping, the - /// body will be woken. - void SetSleepingAllowed(bool flag); - - /// Is this body allowed to sleep - bool IsSleepingAllowed() const; - - /// Set the sleep state of the body. A sleeping body has very - /// low CPU cost. - /// @param flag set to true to wake the body, false to put it to sleep. - void SetAwake(bool flag); - - /// Get the sleeping state of this body. - /// @return true if the body is awake. - bool IsAwake() const; - - /// Allow a body to be disabled. A disabled body is not simulated and cannot - /// be collided with or woken up. - /// If you pass a flag of true, all fixtures will be added to the broad-phase. - /// If you pass a flag of false, all fixtures will be removed from the - /// broad-phase and all contacts will be destroyed. - /// Fixtures and joints are otherwise unaffected. You may continue - /// to create/destroy fixtures and joints on disabled bodies. - /// Fixtures on a disabled body are implicitly disabled and will - /// not participate in collisions, ray-casts, or queries. - /// Joints connected to a disabled body are implicitly disabled. - /// An diabled body is still owned by a b2World object and remains - /// in the body list. - void SetEnabled(bool flag); - - /// Get the active state of the body. - bool IsEnabled() const; - - /// Set this body to have fixed rotation. This causes the mass - /// to be reset. - void SetFixedRotation(bool flag); - - /// Does this body have fixed rotation? - bool IsFixedRotation() const; - - /// Get the list of all fixtures attached to this body. - b2Fixture* GetFixtureList(); - const b2Fixture* GetFixtureList() const; - - /// Get the list of all joints attached to this body. - b2JointEdge* GetJointList(); - const b2JointEdge* GetJointList() const; - - /// Get the list of all contacts attached to this body. - /// @warning this list changes during the time step and you may - /// miss some collisions if you don't use b2ContactListener. - b2ContactEdge* GetContactList(); - const b2ContactEdge* GetContactList() const; - - /// Get the next body in the world's body list. - b2Body* GetNext(); - const b2Body* GetNext() const; - - /// Get the user data pointer that was provided in the body definition. - b2BodyUserData& GetUserData(); - const b2BodyUserData& GetUserData() const; - - /// Get the parent world of this body. - b2World* GetWorld(); - const b2World* GetWorld() const; - - /// Dump this body to a file - void Dump(); - -private: - - friend class b2World; - friend class b2Island; - friend class b2ContactManager; - friend class b2ContactSolver; - friend class b2Contact; - - friend class b2DistanceJoint; - friend class b2FrictionJoint; - friend class b2GearJoint; - friend class b2MotorJoint; - friend class b2MouseJoint; - friend class b2PrismaticJoint; - friend class b2PulleyJoint; - friend class b2RevoluteJoint; - friend class b2WeldJoint; - friend class b2WheelJoint; - - // m_flags - enum - { - e_islandFlag = 0x0001, - e_awakeFlag = 0x0002, - e_autoSleepFlag = 0x0004, - e_bulletFlag = 0x0008, - e_fixedRotationFlag = 0x0010, - e_enabledFlag = 0x0020, - e_toiFlag = 0x0040 - }; - - b2Body(const b2BodyDef* bd, b2World* world); - ~b2Body(); - - void SynchronizeFixtures(); - void SynchronizeTransform(); - - // This is used to prevent connected bodies from colliding. - // It may lie, depending on the collideConnected flag. - bool ShouldCollide(const b2Body* other) const; - - void Advance(float t); - - b2BodyType m_type; - - uint16 m_flags; - - int32 m_islandIndex; - - b2Transform m_xf; // the body origin transform - b2Sweep m_sweep; // the swept motion for CCD - - b2Vec2 m_linearVelocity; - float m_angularVelocity; - - b2Vec2 m_force; - float m_torque; - - b2World* m_world; - b2Body* m_prev; - b2Body* m_next; - - b2Fixture* m_fixtureList; - int32 m_fixtureCount; - - b2JointEdge* m_jointList; - b2ContactEdge* m_contactList; - - float m_mass, m_invMass; - - // Rotational inertia about the center of mass. - float m_I, m_invI; - - float m_linearDamping; - float m_angularDamping; - float m_gravityScale; - - float m_sleepTime; - - b2BodyUserData m_userData; -}; - -inline b2BodyType b2Body::GetType() const -{ - return m_type; -} - -inline const b2Transform& b2Body::GetTransform() const -{ - return m_xf; -} - -inline const b2Vec2& b2Body::GetPosition() const -{ - return m_xf.p; -} - -inline float b2Body::GetAngle() const -{ - return m_sweep.a; -} - -inline const b2Vec2& b2Body::GetWorldCenter() const -{ - return m_sweep.c; -} - -inline const b2Vec2& b2Body::GetLocalCenter() const -{ - return m_sweep.localCenter; -} - -inline void b2Body::SetLinearVelocity(const b2Vec2& v) -{ - if (m_type == b2_staticBody) - { - return; - } - - if (b2Dot(v,v) > 0.0f) - { - SetAwake(true); - } - - m_linearVelocity = v; -} - -inline const b2Vec2& b2Body::GetLinearVelocity() const -{ - return m_linearVelocity; -} - -inline void b2Body::SetAngularVelocity(float w) -{ - if (m_type == b2_staticBody) - { - return; - } - - if (w * w > 0.0f) - { - SetAwake(true); - } - - m_angularVelocity = w; -} - -inline float b2Body::GetAngularVelocity() const -{ - return m_angularVelocity; -} - -inline float b2Body::GetMass() const -{ - return m_mass; -} - -inline float b2Body::GetInertia() const -{ - return m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); -} - -inline b2MassData b2Body::GetMassData() const -{ - b2MassData data; - data.mass = m_mass; - data.I = m_I + m_mass * b2Dot(m_sweep.localCenter, m_sweep.localCenter); - data.center = m_sweep.localCenter; - return data; -} - -inline b2Vec2 b2Body::GetWorldPoint(const b2Vec2& localPoint) const -{ - return b2Mul(m_xf, localPoint); -} - -inline b2Vec2 b2Body::GetWorldVector(const b2Vec2& localVector) const -{ - return b2Mul(m_xf.q, localVector); -} - -inline b2Vec2 b2Body::GetLocalPoint(const b2Vec2& worldPoint) const -{ - return b2MulT(m_xf, worldPoint); -} - -inline b2Vec2 b2Body::GetLocalVector(const b2Vec2& worldVector) const -{ - return b2MulT(m_xf.q, worldVector); -} - -inline b2Vec2 b2Body::GetLinearVelocityFromWorldPoint(const b2Vec2& worldPoint) const -{ - return m_linearVelocity + b2Cross(m_angularVelocity, worldPoint - m_sweep.c); -} - -inline b2Vec2 b2Body::GetLinearVelocityFromLocalPoint(const b2Vec2& localPoint) const -{ - return GetLinearVelocityFromWorldPoint(GetWorldPoint(localPoint)); -} - -inline float b2Body::GetLinearDamping() const -{ - return m_linearDamping; -} - -inline void b2Body::SetLinearDamping(float linearDamping) -{ - m_linearDamping = linearDamping; -} - -inline float b2Body::GetAngularDamping() const -{ - return m_angularDamping; -} - -inline void b2Body::SetAngularDamping(float angularDamping) -{ - m_angularDamping = angularDamping; -} - -inline float b2Body::GetGravityScale() const -{ - return m_gravityScale; -} - -inline void b2Body::SetGravityScale(float scale) -{ - m_gravityScale = scale; -} - -inline void b2Body::SetBullet(bool flag) -{ - if (flag) - { - m_flags |= e_bulletFlag; - } - else - { - m_flags &= ~e_bulletFlag; - } -} - -inline bool b2Body::IsBullet() const -{ - return (m_flags & e_bulletFlag) == e_bulletFlag; -} - -inline void b2Body::SetAwake(bool flag) -{ - if (m_type == b2_staticBody) - { - return; - } - - if (flag) - { - m_flags |= e_awakeFlag; - m_sleepTime = 0.0f; - } - else - { - m_flags &= ~e_awakeFlag; - m_sleepTime = 0.0f; - m_linearVelocity.SetZero(); - m_angularVelocity = 0.0f; - m_force.SetZero(); - m_torque = 0.0f; - } -} - -inline bool b2Body::IsAwake() const -{ - return (m_flags & e_awakeFlag) == e_awakeFlag; -} - -inline bool b2Body::IsEnabled() const -{ - return (m_flags & e_enabledFlag) == e_enabledFlag; -} - -inline bool b2Body::IsFixedRotation() const -{ - return (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag; -} - -inline void b2Body::SetSleepingAllowed(bool flag) -{ - if (flag) - { - m_flags |= e_autoSleepFlag; - } - else - { - m_flags &= ~e_autoSleepFlag; - SetAwake(true); - } -} - -inline bool b2Body::IsSleepingAllowed() const -{ - return (m_flags & e_autoSleepFlag) == e_autoSleepFlag; -} - -inline b2Fixture* b2Body::GetFixtureList() -{ - return m_fixtureList; -} - -inline const b2Fixture* b2Body::GetFixtureList() const -{ - return m_fixtureList; -} - -inline b2JointEdge* b2Body::GetJointList() -{ - return m_jointList; -} - -inline const b2JointEdge* b2Body::GetJointList() const -{ - return m_jointList; -} - -inline b2ContactEdge* b2Body::GetContactList() -{ - return m_contactList; -} - -inline const b2ContactEdge* b2Body::GetContactList() const -{ - return m_contactList; -} - -inline b2Body* b2Body::GetNext() -{ - return m_next; -} - -inline const b2Body* b2Body::GetNext() const -{ - return m_next; -} - -inline b2BodyUserData& b2Body::GetUserData() -{ - return m_userData; -} - -inline const b2BodyUserData& b2Body::GetUserData() const -{ - return m_userData; -} - -inline void b2Body::ApplyForce(const b2Vec2& force, const b2Vec2& point, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate a force if the body is sleeping. - if (m_flags & e_awakeFlag) - { - m_force += force; - m_torque += b2Cross(point - m_sweep.c, force); - } -} - -inline void b2Body::ApplyForceToCenter(const b2Vec2& force, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate a force if the body is sleeping - if (m_flags & e_awakeFlag) - { - m_force += force; - } -} - -inline void b2Body::ApplyTorque(float torque, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate a force if the body is sleeping - if (m_flags & e_awakeFlag) - { - m_torque += torque; - } -} - -inline void b2Body::ApplyLinearImpulse(const b2Vec2& impulse, const b2Vec2& point, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate velocity if the body is sleeping - if (m_flags & e_awakeFlag) - { - m_linearVelocity += m_invMass * impulse; - m_angularVelocity += m_invI * b2Cross(point - m_sweep.c, impulse); - } -} - -inline void b2Body::ApplyLinearImpulseToCenter(const b2Vec2& impulse, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate velocity if the body is sleeping - if (m_flags & e_awakeFlag) - { - m_linearVelocity += m_invMass * impulse; - } -} - -inline void b2Body::ApplyAngularImpulse(float impulse, bool wake) -{ - if (m_type != b2_dynamicBody) - { - return; - } - - if (wake && (m_flags & e_awakeFlag) == 0) - { - SetAwake(true); - } - - // Don't accumulate velocity if the body is sleeping - if (m_flags & e_awakeFlag) - { - m_angularVelocity += m_invI * impulse; - } -} - -inline void b2Body::SynchronizeTransform() -{ - m_xf.q.Set(m_sweep.a); - m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter); -} - -inline void b2Body::Advance(float alpha) -{ - // Advance to the new safe time. This doesn't sync the broad-phase. - m_sweep.Advance(alpha); - m_sweep.c = m_sweep.c0; - m_sweep.a = m_sweep.a0; - m_xf.q.Set(m_sweep.a); - m_xf.p = m_sweep.c - b2Mul(m_xf.q, m_sweep.localCenter); -} - -inline b2World* b2Body::GetWorld() -{ - return m_world; -} - -inline const b2World* b2Body::GetWorld() const -{ - return m_world; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_broad_phase.h b/3rdparty/box2d/include/box2d/b2_broad_phase.h deleted file mode 100644 index cc882ab477ce..000000000000 --- a/3rdparty/box2d/include/box2d/b2_broad_phase.h +++ /dev/null @@ -1,238 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_BROAD_PHASE_H -#define B2_BROAD_PHASE_H - -#include "b2_api.h" -#include "b2_settings.h" -#include "b2_collision.h" -#include "b2_dynamic_tree.h" - -struct B2_API b2Pair -{ - int32 proxyIdA; - int32 proxyIdB; -}; - -/// The broad-phase is used for computing pairs and performing volume queries and ray casts. -/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. -/// It is up to the client to consume the new pairs and to track subsequent overlap. -class B2_API b2BroadPhase -{ -public: - - enum - { - e_nullProxy = -1 - }; - - b2BroadPhase(); - ~b2BroadPhase(); - - /// Create a proxy with an initial AABB. Pairs are not reported until - /// UpdatePairs is called. - int32 CreateProxy(const b2AABB& aabb, void* userData); - - /// Destroy a proxy. It is up to the client to remove any pairs. - void DestroyProxy(int32 proxyId); - - /// Call MoveProxy as many times as you like, then when you are done - /// call UpdatePairs to finalized the proxy pairs (for your time step). - void MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement); - - /// Call to trigger a re-processing of it's pairs on the next call to UpdatePairs. - void TouchProxy(int32 proxyId); - - /// Get the fat AABB for a proxy. - const b2AABB& GetFatAABB(int32 proxyId) const; - - /// Get user data from a proxy. Returns nullptr if the id is invalid. - void* GetUserData(int32 proxyId) const; - - /// Test overlap of fat AABBs. - bool TestOverlap(int32 proxyIdA, int32 proxyIdB) const; - - /// Get the number of proxies. - int32 GetProxyCount() const; - - /// Update the pairs. This results in pair callbacks. This can only add pairs. - template - void UpdatePairs(T* callback); - - /// Query an AABB for overlapping proxies. The callback class - /// is called for each proxy that overlaps the supplied AABB. - template - void Query(T* callback, const b2AABB& aabb) const; - - /// Ray-cast against the proxies in the tree. This relies on the callback - /// to perform a exact ray-cast in the case were the proxy contains a shape. - /// The callback also performs the any collision filtering. This has performance - /// roughly equal to k * log(n), where k is the number of collisions and n is the - /// number of proxies in the tree. - /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). - /// @param callback a callback class that is called for each proxy that is hit by the ray. - template - void RayCast(T* callback, const b2RayCastInput& input) const; - - /// Get the height of the embedded tree. - int32 GetTreeHeight() const; - - /// Get the balance of the embedded tree. - int32 GetTreeBalance() const; - - /// Get the quality metric of the embedded tree. - float GetTreeQuality() const; - - /// Shift the world origin. Useful for large worlds. - /// The shift formula is: position -= newOrigin - /// @param newOrigin the new origin with respect to the old origin - void ShiftOrigin(const b2Vec2& newOrigin); - -private: - - friend class b2DynamicTree; - - void BufferMove(int32 proxyId); - void UnBufferMove(int32 proxyId); - - bool QueryCallback(int32 proxyId); - - b2DynamicTree m_tree; - - int32 m_proxyCount; - - int32* m_moveBuffer; - int32 m_moveCapacity; - int32 m_moveCount; - - b2Pair* m_pairBuffer; - int32 m_pairCapacity; - int32 m_pairCount; - - int32 m_queryProxyId; -}; - -inline void* b2BroadPhase::GetUserData(int32 proxyId) const -{ - return m_tree.GetUserData(proxyId); -} - -inline bool b2BroadPhase::TestOverlap(int32 proxyIdA, int32 proxyIdB) const -{ - const b2AABB& aabbA = m_tree.GetFatAABB(proxyIdA); - const b2AABB& aabbB = m_tree.GetFatAABB(proxyIdB); - return b2TestOverlap(aabbA, aabbB); -} - -inline const b2AABB& b2BroadPhase::GetFatAABB(int32 proxyId) const -{ - return m_tree.GetFatAABB(proxyId); -} - -inline int32 b2BroadPhase::GetProxyCount() const -{ - return m_proxyCount; -} - -inline int32 b2BroadPhase::GetTreeHeight() const -{ - return m_tree.GetHeight(); -} - -inline int32 b2BroadPhase::GetTreeBalance() const -{ - return m_tree.GetMaxBalance(); -} - -inline float b2BroadPhase::GetTreeQuality() const -{ - return m_tree.GetAreaRatio(); -} - -template -void b2BroadPhase::UpdatePairs(T* callback) -{ - // Reset pair buffer - m_pairCount = 0; - - // Perform tree queries for all moving proxies. - for (int32 i = 0; i < m_moveCount; ++i) - { - m_queryProxyId = m_moveBuffer[i]; - if (m_queryProxyId == e_nullProxy) - { - continue; - } - - // We have to query the tree with the fat AABB so that - // we don't fail to create a pair that may touch later. - const b2AABB& fatAABB = m_tree.GetFatAABB(m_queryProxyId); - - // Query tree, create pairs and add them pair buffer. - m_tree.Query(this, fatAABB); - } - - // Send pairs to caller - for (int32 i = 0; i < m_pairCount; ++i) - { - b2Pair* primaryPair = m_pairBuffer + i; - void* userDataA = m_tree.GetUserData(primaryPair->proxyIdA); - void* userDataB = m_tree.GetUserData(primaryPair->proxyIdB); - - callback->AddPair(userDataA, userDataB); - } - - // Clear move flags - for (int32 i = 0; i < m_moveCount; ++i) - { - int32 proxyId = m_moveBuffer[i]; - if (proxyId == e_nullProxy) - { - continue; - } - - m_tree.ClearMoved(proxyId); - } - - // Reset move buffer - m_moveCount = 0; -} - -template -inline void b2BroadPhase::Query(T* callback, const b2AABB& aabb) const -{ - m_tree.Query(callback, aabb); -} - -template -inline void b2BroadPhase::RayCast(T* callback, const b2RayCastInput& input) const -{ - m_tree.RayCast(callback, input); -} - -inline void b2BroadPhase::ShiftOrigin(const b2Vec2& newOrigin) -{ - m_tree.ShiftOrigin(newOrigin); -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_chain_shape.h b/3rdparty/box2d/include/box2d/b2_chain_shape.h deleted file mode 100644 index da2605d6233b..000000000000 --- a/3rdparty/box2d/include/box2d/b2_chain_shape.h +++ /dev/null @@ -1,101 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CHAIN_SHAPE_H -#define B2_CHAIN_SHAPE_H - -#include "b2_api.h" -#include "b2_shape.h" - -class b2EdgeShape; - -/// A chain shape is a free form sequence of line segments. -/// The chain has one-sided collision, with the surface normal pointing to the right of the edge. -/// This provides a counter-clockwise winding like the polygon shape. -/// Connectivity information is used to create smooth collisions. -/// @warning the chain will not collide properly if there are self-intersections. -class B2_API b2ChainShape : public b2Shape -{ -public: - b2ChainShape(); - - /// The destructor frees the vertices using b2Free. - ~b2ChainShape(); - - /// Clear all data. - void Clear(); - - /// Create a loop. This automatically adjusts connectivity. - /// @param vertices an array of vertices, these are copied - /// @param count the vertex count - void CreateLoop(const b2Vec2* vertices, int32 count); - - /// Create a chain with ghost vertices to connect multiple chains together. - /// @param vertices an array of vertices, these are copied - /// @param count the vertex count - /// @param prevVertex previous vertex from chain that connects to the start - /// @param nextVertex next vertex from chain that connects to the end - void CreateChain(const b2Vec2* vertices, int32 count, - const b2Vec2& prevVertex, const b2Vec2& nextVertex); - - /// Implement b2Shape. Vertices are cloned using b2Alloc. - b2Shape* Clone(b2BlockAllocator* allocator) const override; - - /// @see b2Shape::GetChildCount - int32 GetChildCount() const override; - - /// Get a child edge. - void GetChildEdge(b2EdgeShape* edge, int32 index) const; - - /// This always return false. - /// @see b2Shape::TestPoint - bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override; - - /// Implement b2Shape. - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeAABB - void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override; - - /// Chains have zero mass. - /// @see b2Shape::ComputeMass - void ComputeMass(b2MassData* massData, float density) const override; - - /// The vertices. Owned by this class. - b2Vec2* m_vertices; - - /// The vertex count. - int32 m_count; - - b2Vec2 m_prevVertex, m_nextVertex; -}; - -inline b2ChainShape::b2ChainShape() -{ - m_type = e_chain; - m_radius = b2_polygonRadius; - m_vertices = nullptr; - m_count = 0; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_circle_shape.h b/3rdparty/box2d/include/box2d/b2_circle_shape.h deleted file mode 100644 index 5e330f5a7ea3..000000000000 --- a/3rdparty/box2d/include/box2d/b2_circle_shape.h +++ /dev/null @@ -1,67 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CIRCLE_SHAPE_H -#define B2_CIRCLE_SHAPE_H - -#include "b2_api.h" -#include "b2_shape.h" - -/// A solid circle shape -class B2_API b2CircleShape : public b2Shape -{ -public: - b2CircleShape(); - - /// Implement b2Shape. - b2Shape* Clone(b2BlockAllocator* allocator) const override; - - /// @see b2Shape::GetChildCount - int32 GetChildCount() const override; - - /// Implement b2Shape. - bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override; - - /// Implement b2Shape. - /// @note because the circle is solid, rays that start inside do not hit because the normal is - /// not defined. - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeAABB - void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeMass - void ComputeMass(b2MassData* massData, float density) const override; - - /// Position - b2Vec2 m_p; -}; - -inline b2CircleShape::b2CircleShape() -{ - m_type = e_circle; - m_radius = 0.0f; - m_p.SetZero(); -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_collision.h b/3rdparty/box2d/include/box2d/b2_collision.h deleted file mode 100644 index 055704e7c8d6..000000000000 --- a/3rdparty/box2d/include/box2d/b2_collision.h +++ /dev/null @@ -1,306 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_COLLISION_H -#define B2_COLLISION_H - -#include - -#include "b2_api.h" -#include "b2_math.h" - -/// @file -/// Structures and functions used for computing contact points, distance -/// queries, and TOI queries. - -class b2Shape; -class b2CircleShape; -class b2EdgeShape; -class b2PolygonShape; - -const uint8 b2_nullFeature = UCHAR_MAX; - -/// The features that intersect to form the contact point -/// This must be 4 bytes or less. -struct B2_API b2ContactFeature -{ - enum Type - { - e_vertex = 0, - e_face = 1 - }; - - uint8 indexA; ///< Feature index on shapeA - uint8 indexB; ///< Feature index on shapeB - uint8 typeA; ///< The feature type on shapeA - uint8 typeB; ///< The feature type on shapeB -}; - -/// Contact ids to facilitate warm starting. -union B2_API b2ContactID -{ - b2ContactFeature cf; - uint32 key; ///< Used to quickly compare contact ids. -}; - -/// A manifold point is a contact point belonging to a contact -/// manifold. It holds details related to the geometry and dynamics -/// of the contact points. -/// The local point usage depends on the manifold type: -/// -e_circles: the local center of circleB -/// -e_faceA: the local center of cirlceB or the clip point of polygonB -/// -e_faceB: the clip point of polygonA -/// This structure is stored across time steps, so we keep it small. -/// Note: the impulses are used for internal caching and may not -/// provide reliable contact forces, especially for high speed collisions. -struct B2_API b2ManifoldPoint -{ - b2Vec2 localPoint; ///< usage depends on manifold type - float normalImpulse; ///< the non-penetration impulse - float tangentImpulse; ///< the friction impulse - b2ContactID id; ///< uniquely identifies a contact point between two shapes -}; - -/// A manifold for two touching convex shapes. -/// Box2D supports multiple types of contact: -/// - clip point versus plane with radius -/// - point versus point with radius (circles) -/// The local point usage depends on the manifold type: -/// -e_circles: the local center of circleA -/// -e_faceA: the center of faceA -/// -e_faceB: the center of faceB -/// Similarly the local normal usage: -/// -e_circles: not used -/// -e_faceA: the normal on polygonA -/// -e_faceB: the normal on polygonB -/// We store contacts in this way so that position correction can -/// account for movement, which is critical for continuous physics. -/// All contact scenarios must be expressed in one of these types. -/// This structure is stored across time steps, so we keep it small. -struct B2_API b2Manifold -{ - enum Type - { - e_circles, - e_faceA, - e_faceB - }; - - b2ManifoldPoint points[b2_maxManifoldPoints]; ///< the points of contact - b2Vec2 localNormal; ///< not use for Type::e_points - b2Vec2 localPoint; ///< usage depends on manifold type - Type type; - int32 pointCount; ///< the number of manifold points -}; - -/// This is used to compute the current state of a contact manifold. -struct B2_API b2WorldManifold -{ - /// Evaluate the manifold with supplied transforms. This assumes - /// modest motion from the original state. This does not change the - /// point count, impulses, etc. The radii must come from the shapes - /// that generated the manifold. - void Initialize(const b2Manifold* manifold, - const b2Transform& xfA, float radiusA, - const b2Transform& xfB, float radiusB); - - b2Vec2 normal; ///< world vector pointing from A to B - b2Vec2 points[b2_maxManifoldPoints]; ///< world contact point (point of intersection) - float separations[b2_maxManifoldPoints]; ///< a negative value indicates overlap, in meters -}; - -/// This is used for determining the state of contact points. -enum b2PointState -{ - b2_nullState, ///< point does not exist - b2_addState, ///< point was added in the update - b2_persistState, ///< point persisted across the update - b2_removeState ///< point was removed in the update -}; - -/// Compute the point states given two manifolds. The states pertain to the transition from manifold1 -/// to manifold2. So state1 is either persist or remove while state2 is either add or persist. -B2_API void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], - const b2Manifold* manifold1, const b2Manifold* manifold2); - -/// Used for computing contact manifolds. -struct B2_API b2ClipVertex -{ - b2Vec2 v; - b2ContactID id; -}; - -/// Ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). -struct B2_API b2RayCastInput -{ - b2Vec2 p1, p2; - float maxFraction; -}; - -/// Ray-cast output data. The ray hits at p1 + fraction * (p2 - p1), where p1 and p2 -/// come from b2RayCastInput. -struct B2_API b2RayCastOutput -{ - b2Vec2 normal; - float fraction; -}; - -/// An axis aligned bounding box. -struct B2_API b2AABB -{ - /// Verify that the bounds are sorted. - bool IsValid() const; - - /// Get the center of the AABB. - b2Vec2 GetCenter() const - { - return 0.5f * (lowerBound + upperBound); - } - - /// Get the extents of the AABB (half-widths). - b2Vec2 GetExtents() const - { - return 0.5f * (upperBound - lowerBound); - } - - /// Get the perimeter length - float GetPerimeter() const - { - float wx = upperBound.x - lowerBound.x; - float wy = upperBound.y - lowerBound.y; - return 2.0f * (wx + wy); - } - - /// Combine an AABB into this one. - void Combine(const b2AABB& aabb) - { - lowerBound = b2Min(lowerBound, aabb.lowerBound); - upperBound = b2Max(upperBound, aabb.upperBound); - } - - /// Combine two AABBs into this one. - void Combine(const b2AABB& aabb1, const b2AABB& aabb2) - { - lowerBound = b2Min(aabb1.lowerBound, aabb2.lowerBound); - upperBound = b2Max(aabb1.upperBound, aabb2.upperBound); - } - - /// Does this aabb contain the provided AABB. - bool Contains(const b2AABB& aabb) const - { - bool result = true; - result = result && lowerBound.x <= aabb.lowerBound.x; - result = result && lowerBound.y <= aabb.lowerBound.y; - result = result && aabb.upperBound.x <= upperBound.x; - result = result && aabb.upperBound.y <= upperBound.y; - return result; - } - - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const; - - b2Vec2 lowerBound; ///< the lower vertex - b2Vec2 upperBound; ///< the upper vertex -}; - -/// Compute the collision manifold between two circles. -B2_API void b2CollideCircles(b2Manifold* manifold, - const b2CircleShape* circleA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB); - -/// Compute the collision manifold between a polygon and a circle. -B2_API void b2CollidePolygonAndCircle(b2Manifold* manifold, - const b2PolygonShape* polygonA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB); - -/// Compute the collision manifold between two polygons. -B2_API void b2CollidePolygons(b2Manifold* manifold, - const b2PolygonShape* polygonA, const b2Transform& xfA, - const b2PolygonShape* polygonB, const b2Transform& xfB); - -/// Compute the collision manifold between an edge and a circle. -B2_API void b2CollideEdgeAndCircle(b2Manifold* manifold, - const b2EdgeShape* polygonA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB); - -/// Compute the collision manifold between an edge and a polygon. -B2_API void b2CollideEdgeAndPolygon(b2Manifold* manifold, - const b2EdgeShape* edgeA, const b2Transform& xfA, - const b2PolygonShape* polygonB, const b2Transform& xfB); - -/// Clipping for contact manifolds. -B2_API int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], - const b2Vec2& normal, float offset, int32 vertexIndexA); - -/// Determine if two generic shapes overlap. -B2_API bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, - const b2Shape* shapeB, int32 indexB, - const b2Transform& xfA, const b2Transform& xfB); - -/// Convex hull used for polygon collision -struct b2Hull -{ - b2Vec2 points[b2_maxPolygonVertices]; - int32 count; -}; - -/// Compute the convex hull of a set of points. Returns an empty hull if it fails. -/// Some failure cases: -/// - all points very close together -/// - all points on a line -/// - less than 3 points -/// - more than b2_maxPolygonVertices points -/// This welds close points and removes collinear points. -b2Hull b2ComputeHull(const b2Vec2* points, int32 count); - -/// This determines if a hull is valid. Checks for: -/// - convexity -/// - collinear points -/// This is expensive and should not be called at runtime. -bool b2ValidateHull(const b2Hull& hull); - - -// ---------------- Inline Functions ------------------------------------------ - -inline bool b2AABB::IsValid() const -{ - b2Vec2 d = upperBound - lowerBound; - bool valid = d.x >= 0.0f && d.y >= 0.0f; - valid = valid && lowerBound.IsValid() && upperBound.IsValid(); - return valid; -} - -inline bool b2TestOverlap(const b2AABB& a, const b2AABB& b) -{ - b2Vec2 d1, d2; - d1 = b.lowerBound - a.upperBound; - d2 = a.lowerBound - b.upperBound; - - if (d1.x > 0.0f || d1.y > 0.0f) - return false; - - if (d2.x > 0.0f || d2.y > 0.0f) - return false; - - return true; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_common.h b/3rdparty/box2d/include/box2d/b2_common.h deleted file mode 100644 index dfca8af1bf9d..000000000000 --- a/3rdparty/box2d/include/box2d/b2_common.h +++ /dev/null @@ -1,138 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_COMMON_H -#define B2_COMMON_H - -#include "b2_settings.h" - -#include -#include -#include - -#if !defined(NDEBUG) - #define b2DEBUG -#endif - -#define B2_NOT_USED(x) ((void)(x)) -#define b2Assert(A) assert(A) - -#define b2_maxFloat FLT_MAX -#define b2_epsilon FLT_EPSILON -#define b2_pi 3.14159265359f - -/// @file -/// Global tuning constants based on meters-kilograms-seconds (MKS) units. -/// - -// Collision - -/// The maximum number of contact points between two convex shapes. Do -/// not change this value. -#define b2_maxManifoldPoints 2 - -/// This is used to fatten AABBs in the dynamic tree. This allows proxies -/// to move by a small amount without triggering a tree adjustment. -/// This is in meters. -#define b2_aabbExtension (0.1f * b2_lengthUnitsPerMeter) - -/// This is used to fatten AABBs in the dynamic tree. This is used to predict -/// the future position based on the current displacement. -/// This is a dimensionless multiplier. -#define b2_aabbMultiplier 4.0f - -/// A small length used as a collision and constraint tolerance. Usually it is -/// chosen to be numerically significant, but visually insignificant. In meters. -#define b2_linearSlop (0.005f * b2_lengthUnitsPerMeter) - -/// A small angle used as a collision and constraint tolerance. Usually it is -/// chosen to be numerically significant, but visually insignificant. -#define b2_angularSlop (2.0f / 180.0f * b2_pi) - -/// The radius of the polygon/edge shape skin. This should not be modified. Making -/// this smaller means polygons will have an insufficient buffer for continuous collision. -/// Making it larger may create artifacts for vertex collision. -#define b2_polygonRadius (2.0f * b2_linearSlop) - -/// Maximum number of sub-steps per contact in continuous physics simulation. -#define b2_maxSubSteps 8 - - -// Dynamics - -/// Maximum number of contacts to be handled to solve a TOI impact. -#define b2_maxTOIContacts 32 - -/// The maximum linear position correction used when solving constraints. This helps to -/// prevent overshoot. Meters. -#define b2_maxLinearCorrection (0.2f * b2_lengthUnitsPerMeter) - -/// The maximum angular position correction used when solving constraints. This helps to -/// prevent overshoot. -#define b2_maxAngularCorrection (8.0f / 180.0f * b2_pi) - -/// The maximum linear translation of a body per step. This limit is very large and is used -/// to prevent numerical problems. You shouldn't need to adjust this. Meters. -#define b2_maxTranslation (2.0f * b2_lengthUnitsPerMeter) -#define b2_maxTranslationSquared (b2_maxTranslation * b2_maxTranslation) - -/// The maximum angular velocity of a body. This limit is very large and is used -/// to prevent numerical problems. You shouldn't need to adjust this. -#define b2_maxRotation (0.5f * b2_pi) -#define b2_maxRotationSquared (b2_maxRotation * b2_maxRotation) - -/// This scale factor controls how fast overlap is resolved. Ideally this would be 1 so -/// that overlap is removed in one time step. However using values close to 1 often lead -/// to overshoot. -#define b2_baumgarte 0.2f -#define b2_toiBaumgarte 0.75f - - -// Sleep - -/// The time that a body must be still before it will go to sleep. -#define b2_timeToSleep 0.5f - -/// A body cannot sleep if its linear velocity is above this tolerance. -#define b2_linearSleepTolerance (0.01f * b2_lengthUnitsPerMeter) - -/// A body cannot sleep if its angular velocity is above this tolerance. -#define b2_angularSleepTolerance (2.0f / 180.0f * b2_pi) - -/// Dump to a file. Only one dump file allowed at a time. -void b2OpenDump(const char* fileName); -void b2Dump(const char* string, ...); -void b2CloseDump(); - -/// Version numbering scheme. -/// See http://en.wikipedia.org/wiki/Software_versioning -struct b2Version -{ - int32 major; ///< significant changes - int32 minor; ///< incremental changes - int32 revision; ///< bug fixes -}; - -/// Current version. -extern B2_API b2Version b2_version; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_contact.h b/3rdparty/box2d/include/box2d/b2_contact.h deleted file mode 100644 index de7541f1350b..000000000000 --- a/3rdparty/box2d/include/box2d/b2_contact.h +++ /dev/null @@ -1,386 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CONTACT_H -#define B2_CONTACT_H - -#include "b2_api.h" -#include "b2_collision.h" -#include "b2_fixture.h" -#include "b2_math.h" -#include "b2_shape.h" - -class b2Body; -class b2Contact; -class b2Fixture; -class b2World; -class b2BlockAllocator; -class b2StackAllocator; -class b2ContactListener; - -/// Friction mixing law. The idea is to allow either fixture to drive the friction to zero. -/// For example, anything slides on ice. -inline float b2MixFriction(float friction1, float friction2) -{ - return b2Sqrt(friction1 * friction2); -} - -/// Restitution mixing law. The idea is allow for anything to bounce off an inelastic surface. -/// For example, a superball bounces on anything. -inline float b2MixRestitution(float restitution1, float restitution2) -{ - return restitution1 > restitution2 ? restitution1 : restitution2; -} - -/// Restitution mixing law. This picks the lowest value. -inline float b2MixRestitutionThreshold(float threshold1, float threshold2) -{ - return threshold1 < threshold2 ? threshold1 : threshold2; -} - -typedef b2Contact* b2ContactCreateFcn( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, - b2BlockAllocator* allocator); -typedef void b2ContactDestroyFcn(b2Contact* contact, b2BlockAllocator* allocator); - -struct B2_API b2ContactRegister -{ - b2ContactCreateFcn* createFcn; - b2ContactDestroyFcn* destroyFcn; - bool primary; -}; - -/// A contact edge is used to connect bodies and contacts together -/// in a contact graph where each body is a node and each contact -/// is an edge. A contact edge belongs to a doubly linked list -/// maintained in each attached body. Each contact has two contact -/// nodes, one for each attached body. -struct B2_API b2ContactEdge -{ - b2Body* other; ///< provides quick access to the other body attached. - b2Contact* contact; ///< the contact - b2ContactEdge* prev; ///< the previous contact edge in the body's contact list - b2ContactEdge* next; ///< the next contact edge in the body's contact list -}; - -/// The class manages contact between two shapes. A contact exists for each overlapping -/// AABB in the broad-phase (except if filtered). Therefore a contact object may exist -/// that has no contact points. -class B2_API b2Contact -{ -public: - - /// Get the contact manifold. Do not modify the manifold unless you understand the - /// internals of Box2D. - b2Manifold* GetManifold(); - const b2Manifold* GetManifold() const; - - /// Get the world manifold. - void GetWorldManifold(b2WorldManifold* worldManifold) const; - - /// Is this contact touching? - bool IsTouching() const; - - /// Enable/disable this contact. This can be used inside the pre-solve - /// contact listener. The contact is only disabled for the current - /// time step (or sub-step in continuous collisions). - void SetEnabled(bool flag); - - /// Has this contact been disabled? - bool IsEnabled() const; - - /// Get the next contact in the world's contact list. - b2Contact* GetNext(); - const b2Contact* GetNext() const; - - /// Get fixture A in this contact. - b2Fixture* GetFixtureA(); - const b2Fixture* GetFixtureA() const; - - /// Get the child primitive index for fixture A. - int32 GetChildIndexA() const; - - /// Get fixture B in this contact. - b2Fixture* GetFixtureB(); - const b2Fixture* GetFixtureB() const; - - /// Get the child primitive index for fixture B. - int32 GetChildIndexB() const; - - /// Override the default friction mixture. You can call this in b2ContactListener::PreSolve. - /// This value persists until set or reset. - void SetFriction(float friction); - - /// Get the friction. - float GetFriction() const; - - /// Reset the friction mixture to the default value. - void ResetFriction(); - - /// Override the default restitution mixture. You can call this in b2ContactListener::PreSolve. - /// The value persists until you set or reset. - void SetRestitution(float restitution); - - /// Get the restitution. - float GetRestitution() const; - - /// Reset the restitution to the default value. - void ResetRestitution(); - - /// Override the default restitution velocity threshold mixture. You can call this in b2ContactListener::PreSolve. - /// The value persists until you set or reset. - void SetRestitutionThreshold(float threshold); - - /// Get the restitution threshold. - float GetRestitutionThreshold() const; - - /// Reset the restitution threshold to the default value. - void ResetRestitutionThreshold(); - - /// Set the desired tangent speed for a conveyor belt behavior. In meters per second. - void SetTangentSpeed(float speed); - - /// Get the desired tangent speed. In meters per second. - float GetTangentSpeed() const; - - /// Evaluate this contact with your own manifold and transforms. - virtual void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) = 0; - -protected: - friend class b2ContactManager; - friend class b2World; - friend class b2ContactSolver; - friend class b2Body; - friend class b2Fixture; - - // Flags stored in m_flags - enum - { - // Used when crawling contact graph when forming islands. - e_islandFlag = 0x0001, - - // Set when the shapes are touching. - e_touchingFlag = 0x0002, - - // This contact can be disabled (by user) - e_enabledFlag = 0x0004, - - // This contact needs filtering because a fixture filter was changed. - e_filterFlag = 0x0008, - - // This bullet contact had a TOI event - e_bulletHitFlag = 0x0010, - - // This contact has a valid TOI in m_toi - e_toiFlag = 0x0020 - }; - - /// Flag this contact for filtering. Filtering will occur the next time step. - void FlagForFiltering(); - - static void AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destroyFcn, - b2Shape::Type typeA, b2Shape::Type typeB); - static void InitializeRegisters(); - static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2Shape::Type typeA, b2Shape::Type typeB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2Contact() : m_fixtureA(nullptr), m_fixtureB(nullptr) {} - b2Contact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); - virtual ~b2Contact() {} - - void Update(b2ContactListener* listener); - - static b2ContactRegister s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; - static bool s_initialized; - - uint32 m_flags; - - // World pool and list pointers. - b2Contact* m_prev; - b2Contact* m_next; - - // Nodes for connecting bodies. - b2ContactEdge m_nodeA; - b2ContactEdge m_nodeB; - - b2Fixture* m_fixtureA; - b2Fixture* m_fixtureB; - - int32 m_indexA; - int32 m_indexB; - - b2Manifold m_manifold; - - int32 m_toiCount; - float m_toi; - - float m_friction; - float m_restitution; - float m_restitutionThreshold; - - float m_tangentSpeed; -}; - -inline b2Manifold* b2Contact::GetManifold() -{ - return &m_manifold; -} - -inline const b2Manifold* b2Contact::GetManifold() const -{ - return &m_manifold; -} - -inline void b2Contact::GetWorldManifold(b2WorldManifold* worldManifold) const -{ - const b2Body* bodyA = m_fixtureA->GetBody(); - const b2Body* bodyB = m_fixtureB->GetBody(); - const b2Shape* shapeA = m_fixtureA->GetShape(); - const b2Shape* shapeB = m_fixtureB->GetShape(); - - worldManifold->Initialize(&m_manifold, bodyA->GetTransform(), shapeA->m_radius, bodyB->GetTransform(), shapeB->m_radius); -} - -inline void b2Contact::SetEnabled(bool flag) -{ - if (flag) - { - m_flags |= e_enabledFlag; - } - else - { - m_flags &= ~e_enabledFlag; - } -} - -inline bool b2Contact::IsEnabled() const -{ - return (m_flags & e_enabledFlag) == e_enabledFlag; -} - -inline bool b2Contact::IsTouching() const -{ - return (m_flags & e_touchingFlag) == e_touchingFlag; -} - -inline b2Contact* b2Contact::GetNext() -{ - return m_next; -} - -inline const b2Contact* b2Contact::GetNext() const -{ - return m_next; -} - -inline b2Fixture* b2Contact::GetFixtureA() -{ - return m_fixtureA; -} - -inline const b2Fixture* b2Contact::GetFixtureA() const -{ - return m_fixtureA; -} - -inline b2Fixture* b2Contact::GetFixtureB() -{ - return m_fixtureB; -} - -inline int32 b2Contact::GetChildIndexA() const -{ - return m_indexA; -} - -inline const b2Fixture* b2Contact::GetFixtureB() const -{ - return m_fixtureB; -} - -inline int32 b2Contact::GetChildIndexB() const -{ - return m_indexB; -} - -inline void b2Contact::FlagForFiltering() -{ - m_flags |= e_filterFlag; -} - -inline void b2Contact::SetFriction(float friction) -{ - m_friction = friction; -} - -inline float b2Contact::GetFriction() const -{ - return m_friction; -} - -inline void b2Contact::ResetFriction() -{ - m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); -} - -inline void b2Contact::SetRestitution(float restitution) -{ - m_restitution = restitution; -} - -inline float b2Contact::GetRestitution() const -{ - return m_restitution; -} - -inline void b2Contact::ResetRestitution() -{ - m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); -} - -inline void b2Contact::SetRestitutionThreshold(float threshold) -{ - m_restitutionThreshold = threshold; -} - -inline float b2Contact::GetRestitutionThreshold() const -{ - return m_restitutionThreshold; -} - -inline void b2Contact::ResetRestitutionThreshold() -{ - m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold); -} - -inline void b2Contact::SetTangentSpeed(float speed) -{ - m_tangentSpeed = speed; -} - -inline float b2Contact::GetTangentSpeed() const -{ - return m_tangentSpeed; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_contact_manager.h b/3rdparty/box2d/include/box2d/b2_contact_manager.h deleted file mode 100644 index fbd3b4d401be..000000000000 --- a/3rdparty/box2d/include/box2d/b2_contact_manager.h +++ /dev/null @@ -1,57 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CONTACT_MANAGER_H -#define B2_CONTACT_MANAGER_H - -#include "b2_api.h" -#include "b2_broad_phase.h" - -class b2Contact; -class b2ContactFilter; -class b2ContactListener; -class b2BlockAllocator; - -// Delegate of b2World. -class B2_API b2ContactManager -{ -public: - b2ContactManager(); - - // Broad-phase callback. - void AddPair(void* proxyUserDataA, void* proxyUserDataB); - - void FindNewContacts(); - - void Destroy(b2Contact* c); - - void Collide(); - - b2BroadPhase m_broadPhase; - b2Contact* m_contactList; - int32 m_contactCount; - b2ContactFilter* m_contactFilter; - b2ContactListener* m_contactListener; - b2BlockAllocator* m_allocator; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_distance.h b/3rdparty/box2d/include/box2d/b2_distance.h deleted file mode 100644 index 3e05773de339..000000000000 --- a/3rdparty/box2d/include/box2d/b2_distance.h +++ /dev/null @@ -1,171 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_DISTANCE_H -#define B2_DISTANCE_H - -#include "b2_api.h" -#include "b2_math.h" - -class b2Shape; - -/// A distance proxy is used by the GJK algorithm. -/// It encapsulates any shape. -struct B2_API b2DistanceProxy -{ - b2DistanceProxy() : m_vertices(nullptr), m_count(0), m_radius(0.0f) {} - - /// Initialize the proxy using the given shape. The shape - /// must remain in scope while the proxy is in use. - void Set(const b2Shape* shape, int32 index); - - /// Initialize the proxy using a vertex cloud and radius. The vertices - /// must remain in scope while the proxy is in use. - void Set(const b2Vec2* vertices, int32 count, float radius); - - /// Get the supporting vertex index in the given direction. - int32 GetSupport(const b2Vec2& d) const; - - /// Get the supporting vertex in the given direction. - const b2Vec2& GetSupportVertex(const b2Vec2& d) const; - - /// Get the vertex count. - int32 GetVertexCount() const; - - /// Get a vertex by index. Used by b2Distance. - const b2Vec2& GetVertex(int32 index) const; - - b2Vec2 m_buffer[2]; - const b2Vec2* m_vertices; - int32 m_count; - float m_radius; -}; - -/// Used to warm start b2Distance. -/// Set count to zero on first call. -struct B2_API b2SimplexCache -{ - float metric; ///< length or area - uint16 count; - uint8 indexA[3]; ///< vertices on shape A - uint8 indexB[3]; ///< vertices on shape B -}; - -/// Input for b2Distance. -/// You have to option to use the shape radii -/// in the computation. Even -struct B2_API b2DistanceInput -{ - b2DistanceProxy proxyA; - b2DistanceProxy proxyB; - b2Transform transformA; - b2Transform transformB; - bool useRadii; -}; - -/// Output for b2Distance. -struct B2_API b2DistanceOutput -{ - b2Vec2 pointA; ///< closest point on shapeA - b2Vec2 pointB; ///< closest point on shapeB - float distance; - int32 iterations; ///< number of GJK iterations used -}; - -/// Compute the closest points between two shapes. Supports any combination of: -/// b2CircleShape, b2PolygonShape, b2EdgeShape. The simplex cache is input/output. -/// On the first call set b2SimplexCache.count to zero. -B2_API void b2Distance(b2DistanceOutput* output, - b2SimplexCache* cache, - const b2DistanceInput* input); - -/// Input parameters for b2ShapeCast -struct B2_API b2ShapeCastInput -{ - b2DistanceProxy proxyA; - b2DistanceProxy proxyB; - b2Transform transformA; - b2Transform transformB; - b2Vec2 translationB; -}; - -/// Output results for b2ShapeCast -struct B2_API b2ShapeCastOutput -{ - b2Vec2 point; - b2Vec2 normal; - float lambda; - int32 iterations; -}; - -/// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. -/// @returns true if hit, false if there is no hit or an initial overlap -B2_API bool b2ShapeCast(b2ShapeCastOutput* output, const b2ShapeCastInput* input); - -////////////////////////////////////////////////////////////////////////// - -inline int32 b2DistanceProxy::GetVertexCount() const -{ - return m_count; -} - -inline const b2Vec2& b2DistanceProxy::GetVertex(int32 index) const -{ - b2Assert(0 <= index && index < m_count); - return m_vertices[index]; -} - -inline int32 b2DistanceProxy::GetSupport(const b2Vec2& d) const -{ - int32 bestIndex = 0; - float bestValue = b2Dot(m_vertices[0], d); - for (int32 i = 1; i < m_count; ++i) - { - float value = b2Dot(m_vertices[i], d); - if (value > bestValue) - { - bestIndex = i; - bestValue = value; - } - } - - return bestIndex; -} - -inline const b2Vec2& b2DistanceProxy::GetSupportVertex(const b2Vec2& d) const -{ - int32 bestIndex = 0; - float bestValue = b2Dot(m_vertices[0], d); - for (int32 i = 1; i < m_count; ++i) - { - float value = b2Dot(m_vertices[i], d); - if (value > bestValue) - { - bestIndex = i; - bestValue = value; - } - } - - return m_vertices[bestIndex]; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_distance_joint.h b/3rdparty/box2d/include/box2d/b2_distance_joint.h deleted file mode 100644 index cfc75fefba4e..000000000000 --- a/3rdparty/box2d/include/box2d/b2_distance_joint.h +++ /dev/null @@ -1,176 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_DISTANCE_JOINT_H -#define B2_DISTANCE_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Distance joint definition. This requires defining an anchor point on both -/// bodies and the non-zero distance of the distance joint. The definition uses -/// local anchor points so that the initial configuration can violate the -/// constraint slightly. This helps when saving and loading a game. -struct B2_API b2DistanceJointDef : public b2JointDef -{ - b2DistanceJointDef() - { - type = e_distanceJoint; - localAnchorA.Set(0.0f, 0.0f); - localAnchorB.Set(0.0f, 0.0f); - length = 1.0f; - minLength = 0.0f; - maxLength = FLT_MAX; - stiffness = 0.0f; - damping = 0.0f; - } - - /// Initialize the bodies, anchors, and rest length using world space anchors. - /// The minimum and maximum lengths are set to the rest length. - void Initialize(b2Body* bodyA, b2Body* bodyB, - const b2Vec2& anchorA, const b2Vec2& anchorB); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The rest length of this joint. Clamped to a stable minimum value. - float length; - - /// Minimum length. Clamped to a stable minimum value. - float minLength; - - /// Maximum length. Must be greater than or equal to the minimum length. - float maxLength; - - /// The linear stiffness in N/m. - float stiffness; - - /// The linear damping in N*s/m. - float damping; -}; - -/// A distance joint constrains two points on two bodies to remain at a fixed -/// distance from each other. You can view this as a massless, rigid rod. -class B2_API b2DistanceJoint : public b2Joint -{ -public: - - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - /// Get the reaction force given the inverse time step. - /// Unit is N. - b2Vec2 GetReactionForce(float inv_dt) const override; - - /// Get the reaction torque given the inverse time step. - /// Unit is N*m. This is always zero for a distance joint. - float GetReactionTorque(float inv_dt) const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// Get the rest length - float GetLength() const { return m_length; } - - /// Set the rest length - /// @returns clamped rest length - float SetLength(float length); - - /// Get the minimum length - float GetMinLength() const { return m_minLength; } - - /// Set the minimum length - /// @returns the clamped minimum length - float SetMinLength(float minLength); - - /// Get the maximum length - float GetMaxLength() const { return m_maxLength; } - - /// Set the maximum length - /// @returns the clamped maximum length - float SetMaxLength(float maxLength); - - /// Get the current length - float GetCurrentLength() const; - - /// Set/get the linear stiffness in N/m - void SetStiffness(float stiffness) { m_stiffness = stiffness; } - float GetStiffness() const { return m_stiffness; } - - /// Set/get linear damping in N*s/m - void SetDamping(float damping) { m_damping = damping; } - float GetDamping() const { return m_damping; } - - /// Dump joint to dmLog - void Dump() override; - - /// - void Draw(b2Draw* draw) const override; - -protected: - - friend class b2Joint; - b2DistanceJoint(const b2DistanceJointDef* data); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - float m_stiffness; - float m_damping; - float m_bias; - float m_length; - float m_minLength; - float m_maxLength; - - // Solver shared - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - float m_gamma; - float m_impulse; - float m_lowerImpulse; - float m_upperImpulse; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_u; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_currentLength; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - float m_softMass; - float m_mass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_draw.h b/3rdparty/box2d/include/box2d/b2_draw.h deleted file mode 100644 index a4d17118781b..000000000000 --- a/3rdparty/box2d/include/box2d/b2_draw.h +++ /dev/null @@ -1,102 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_DRAW_H -#define B2_DRAW_H - -#include "b2_api.h" -#include "b2_math.h" - -/// Color for debug drawing. Each value has the range [0,1]. -struct B2_API b2Color -{ - b2Color() {} - b2Color(float rIn, float gIn, float bIn, float aIn = 1.0f) - { - r = rIn; g = gIn; b = bIn; a = aIn; - } - - void Set(float rIn, float gIn, float bIn, float aIn = 1.0f) - { - r = rIn; g = gIn; b = bIn; a = aIn; - } - - float r, g, b, a; -}; - -/// Implement and register this class with a b2World to provide debug drawing of physics -/// entities in your game. -class B2_API b2Draw -{ -public: - b2Draw(); - - virtual ~b2Draw() {} - - enum - { - e_shapeBit = 0x0001, ///< draw shapes - e_jointBit = 0x0002, ///< draw joint connections - e_aabbBit = 0x0004, ///< draw axis aligned bounding boxes - e_pairBit = 0x0008, ///< draw broad-phase pairs - e_centerOfMassBit = 0x0010 ///< draw center of mass frame - }; - - /// Set the drawing flags. - void SetFlags(uint32 flags); - - /// Get the drawing flags. - uint32 GetFlags() const; - - /// Append flags to the current flags. - void AppendFlags(uint32 flags); - - /// Clear flags from the current flags. - void ClearFlags(uint32 flags); - - /// Draw a closed polygon provided in CCW order. - virtual void DrawPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0; - - /// Draw a solid closed polygon provided in CCW order. - virtual void DrawSolidPolygon(const b2Vec2* vertices, int32 vertexCount, const b2Color& color) = 0; - - /// Draw a circle. - virtual void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) = 0; - - /// Draw a solid circle. - virtual void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) = 0; - - /// Draw a line segment. - virtual void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) = 0; - - /// Draw a transform. Choose your own length scale. - /// @param xf a transform. - virtual void DrawTransform(const b2Transform& xf) = 0; - - /// Draw a point. - virtual void DrawPoint(const b2Vec2& p, float size, const b2Color& color) = 0; - -protected: - uint32 m_drawFlags; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_dynamic_tree.h b/3rdparty/box2d/include/box2d/b2_dynamic_tree.h deleted file mode 100644 index b85491915d92..000000000000 --- a/3rdparty/box2d/include/box2d/b2_dynamic_tree.h +++ /dev/null @@ -1,308 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_DYNAMIC_TREE_H -#define B2_DYNAMIC_TREE_H - -#include "b2_api.h" -#include "b2_collision.h" -#include "b2_growable_stack.h" - -#define b2_nullNode (-1) - -/// A node in the dynamic tree. The client does not interact with this directly. -struct B2_API b2TreeNode -{ - bool IsLeaf() const - { - return child1 == b2_nullNode; - } - - /// Enlarged AABB - b2AABB aabb; - - void* userData; - - union - { - int32 parent; - int32 next; - }; - - int32 child1; - int32 child2; - - // leaf = 0, free node = -1 - int32 height; - - bool moved; -}; - -/// A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. -/// A dynamic tree arranges data in a binary tree to accelerate -/// queries such as volume queries and ray casts. Leafs are proxies -/// with an AABB. In the tree we expand the proxy AABB by b2_fatAABBFactor -/// so that the proxy AABB is bigger than the client object. This allows the client -/// object to move by small amounts without triggering a tree update. -/// -/// Nodes are pooled and relocatable, so we use node indices rather than pointers. -class B2_API b2DynamicTree -{ -public: - /// Constructing the tree initializes the node pool. - b2DynamicTree(); - - /// Destroy the tree, freeing the node pool. - ~b2DynamicTree(); - - /// Create a proxy. Provide a tight fitting AABB and a userData pointer. - int32 CreateProxy(const b2AABB& aabb, void* userData); - - /// Destroy a proxy. This asserts if the id is invalid. - void DestroyProxy(int32 proxyId); - - /// Move a proxy with a swepted AABB. If the proxy has moved outside of its fattened AABB, - /// then the proxy is removed from the tree and re-inserted. Otherwise - /// the function returns immediately. - /// @return true if the proxy was re-inserted. - bool MoveProxy(int32 proxyId, const b2AABB& aabb1, const b2Vec2& displacement); - - /// Get proxy user data. - /// @return the proxy user data or 0 if the id is invalid. - void* GetUserData(int32 proxyId) const; - - bool WasMoved(int32 proxyId) const; - void ClearMoved(int32 proxyId); - - /// Get the fat AABB for a proxy. - const b2AABB& GetFatAABB(int32 proxyId) const; - - /// Query an AABB for overlapping proxies. The callback class - /// is called for each proxy that overlaps the supplied AABB. - template - void Query(T* callback, const b2AABB& aabb) const; - - /// Ray-cast against the proxies in the tree. This relies on the callback - /// to perform a exact ray-cast in the case were the proxy contains a shape. - /// The callback also performs the any collision filtering. This has performance - /// roughly equal to k * log(n), where k is the number of collisions and n is the - /// number of proxies in the tree. - /// @param input the ray-cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). - /// @param callback a callback class that is called for each proxy that is hit by the ray. - template - void RayCast(T* callback, const b2RayCastInput& input) const; - - /// Validate this tree. For testing. - void Validate() const; - - /// Compute the height of the binary tree in O(N) time. Should not be - /// called often. - int32 GetHeight() const; - - /// Get the maximum balance of an node in the tree. The balance is the difference - /// in height of the two children of a node. - int32 GetMaxBalance() const; - - /// Get the ratio of the sum of the node areas to the root area. - float GetAreaRatio() const; - - /// Build an optimal tree. Very expensive. For testing. - void RebuildBottomUp(); - - /// Shift the world origin. Useful for large worlds. - /// The shift formula is: position -= newOrigin - /// @param newOrigin the new origin with respect to the old origin - void ShiftOrigin(const b2Vec2& newOrigin); - -private: - - int32 AllocateNode(); - void FreeNode(int32 node); - - void InsertLeaf(int32 node); - void RemoveLeaf(int32 node); - - int32 Balance(int32 index); - - int32 ComputeHeight() const; - int32 ComputeHeight(int32 nodeId) const; - - void ValidateStructure(int32 index) const; - void ValidateMetrics(int32 index) const; - - int32 m_root; - - b2TreeNode* m_nodes; - int32 m_nodeCount; - int32 m_nodeCapacity; - - int32 m_freeList; - - int32 m_insertionCount; -}; - -inline void* b2DynamicTree::GetUserData(int32 proxyId) const -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - return m_nodes[proxyId].userData; -} - -inline bool b2DynamicTree::WasMoved(int32 proxyId) const -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - return m_nodes[proxyId].moved; -} - -inline void b2DynamicTree::ClearMoved(int32 proxyId) -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - m_nodes[proxyId].moved = false; -} - -inline const b2AABB& b2DynamicTree::GetFatAABB(int32 proxyId) const -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - return m_nodes[proxyId].aabb; -} - -template -inline void b2DynamicTree::Query(T* callback, const b2AABB& aabb) const -{ - b2GrowableStack stack; - stack.Push(m_root); - - while (stack.GetCount() > 0) - { - int32 nodeId = stack.Pop(); - if (nodeId == b2_nullNode) - { - continue; - } - - const b2TreeNode* node = m_nodes + nodeId; - - if (b2TestOverlap(node->aabb, aabb)) - { - if (node->IsLeaf()) - { - bool proceed = callback->QueryCallback(nodeId); - if (proceed == false) - { - return; - } - } - else - { - stack.Push(node->child1); - stack.Push(node->child2); - } - } - } -} - -template -inline void b2DynamicTree::RayCast(T* callback, const b2RayCastInput& input) const -{ - b2Vec2 p1 = input.p1; - b2Vec2 p2 = input.p2; - b2Vec2 r = p2 - p1; - b2Assert(r.LengthSquared() > 0.0f); - r.Normalize(); - - // v is perpendicular to the segment. - b2Vec2 v = b2Cross(1.0f, r); - b2Vec2 abs_v = b2Abs(v); - - // Separating axis for segment (Gino, p80). - // |dot(v, p1 - c)| > dot(|v|, h) - - float maxFraction = input.maxFraction; - - // Build a bounding box for the segment. - b2AABB segmentAABB; - { - b2Vec2 t = p1 + maxFraction * (p2 - p1); - segmentAABB.lowerBound = b2Min(p1, t); - segmentAABB.upperBound = b2Max(p1, t); - } - - b2GrowableStack stack; - stack.Push(m_root); - - while (stack.GetCount() > 0) - { - int32 nodeId = stack.Pop(); - if (nodeId == b2_nullNode) - { - continue; - } - - const b2TreeNode* node = m_nodes + nodeId; - - if (b2TestOverlap(node->aabb, segmentAABB) == false) - { - continue; - } - - // Separating axis for segment (Gino, p80). - // |dot(v, p1 - c)| > dot(|v|, h) - b2Vec2 c = node->aabb.GetCenter(); - b2Vec2 h = node->aabb.GetExtents(); - float separation = b2Abs(b2Dot(v, p1 - c)) - b2Dot(abs_v, h); - if (separation > 0.0f) - { - continue; - } - - if (node->IsLeaf()) - { - b2RayCastInput subInput; - subInput.p1 = input.p1; - subInput.p2 = input.p2; - subInput.maxFraction = maxFraction; - - float value = callback->RayCastCallback(subInput, nodeId); - - if (value == 0.0f) - { - // The client has terminated the ray cast. - return; - } - - if (value > 0.0f) - { - // Update segment bounding box. - maxFraction = value; - b2Vec2 t = p1 + maxFraction * (p2 - p1); - segmentAABB.lowerBound = b2Min(p1, t); - segmentAABB.upperBound = b2Max(p1, t); - } - } - else - { - stack.Push(node->child1); - stack.Push(node->child2); - } - } -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_edge_shape.h b/3rdparty/box2d/include/box2d/b2_edge_shape.h deleted file mode 100644 index b930ee87281d..000000000000 --- a/3rdparty/box2d/include/box2d/b2_edge_shape.h +++ /dev/null @@ -1,86 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_EDGE_SHAPE_H -#define B2_EDGE_SHAPE_H - -#include "b2_api.h" -#include "b2_shape.h" - -/// A line segment (edge) shape. These can be connected in chains or loops -/// to other edge shapes. Edges created independently are two-sided and do -/// no provide smooth movement across junctions. -class B2_API b2EdgeShape : public b2Shape -{ -public: - b2EdgeShape(); - - /// Set this as a part of a sequence. Vertex v0 precedes the edge and vertex v3 - /// follows. These extra vertices are used to provide smooth movement - /// across junctions. This also makes the collision one-sided. The edge - /// normal points to the right looking from v1 to v2. - void SetOneSided(const b2Vec2& v0, const b2Vec2& v1,const b2Vec2& v2, const b2Vec2& v3); - - /// Set this as an isolated edge. Collision is two-sided. - void SetTwoSided(const b2Vec2& v1, const b2Vec2& v2); - - /// Implement b2Shape. - b2Shape* Clone(b2BlockAllocator* allocator) const override; - - /// @see b2Shape::GetChildCount - int32 GetChildCount() const override; - - /// @see b2Shape::TestPoint - bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override; - - /// Implement b2Shape. - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeAABB - void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeMass - void ComputeMass(b2MassData* massData, float density) const override; - - /// These are the edge vertices - b2Vec2 m_vertex1, m_vertex2; - - /// Optional adjacent vertices. These are used for smooth collision. - b2Vec2 m_vertex0, m_vertex3; - - /// Uses m_vertex0 and m_vertex3 to create smooth collision. - bool m_oneSided; -}; - -inline b2EdgeShape::b2EdgeShape() -{ - m_type = e_edge; - m_radius = b2_polygonRadius; - m_vertex0.x = 0.0f; - m_vertex0.y = 0.0f; - m_vertex3.x = 0.0f; - m_vertex3.y = 0.0f; - m_oneSided = false; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_fixture.h b/3rdparty/box2d/include/box2d/b2_fixture.h deleted file mode 100644 index 47d321df5ec1..000000000000 --- a/3rdparty/box2d/include/box2d/b2_fixture.h +++ /dev/null @@ -1,371 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_FIXTURE_H -#define B2_FIXTURE_H - -#include "b2_api.h" -#include "b2_body.h" -#include "b2_collision.h" -#include "b2_shape.h" - -class b2BlockAllocator; -class b2Body; -class b2BroadPhase; -class b2Fixture; - -/// This holds contact filtering data. -struct B2_API b2Filter -{ - b2Filter() - { - categoryBits = 0x0001; - maskBits = 0xFFFF; - groupIndex = 0; - } - - /// The collision category bits. Normally you would just set one bit. - uint16 categoryBits; - - /// The collision mask bits. This states the categories that this - /// shape would accept for collision. - uint16 maskBits; - - /// Collision groups allow a certain group of objects to never collide (negative) - /// or always collide (positive). Zero means no collision group. Non-zero group - /// filtering always wins against the mask bits. - int16 groupIndex; -}; - -/// A fixture definition is used to create a fixture. This class defines an -/// abstract fixture definition. You can reuse fixture definitions safely. -struct B2_API b2FixtureDef -{ - /// The constructor sets the default fixture definition values. - b2FixtureDef() - { - shape = nullptr; - friction = 0.2f; - restitution = 0.0f; - restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter; - density = 0.0f; - isSensor = false; - } - - /// The shape, this must be set. The shape will be cloned, so you - /// can create the shape on the stack. - const b2Shape* shape; - - /// Use this to store application specific fixture data. - b2FixtureUserData userData; - - /// The friction coefficient, usually in the range [0,1]. - float friction; - - /// The restitution (elasticity) usually in the range [0,1]. - float restitution; - - /// Restitution velocity threshold, usually in m/s. Collisions above this - /// speed have restitution applied (will bounce). - float restitutionThreshold; - - /// The density, usually in kg/m^2. - float density; - - /// A sensor shape collects contact information but never generates a collision - /// response. - bool isSensor; - - /// Contact filtering data. - b2Filter filter; -}; - -/// This proxy is used internally to connect fixtures to the broad-phase. -struct B2_API b2FixtureProxy -{ - b2AABB aabb; - b2Fixture* fixture; - int32 childIndex; - int32 proxyId; -}; - -/// A fixture is used to attach a shape to a body for collision detection. A fixture -/// inherits its transform from its parent. Fixtures hold additional non-geometric data -/// such as friction, collision filters, etc. -/// Fixtures are created via b2Body::CreateFixture. -/// @warning you cannot reuse fixtures. -class B2_API b2Fixture -{ -public: - /// Get the type of the child shape. You can use this to down cast to the concrete shape. - /// @return the shape type. - b2Shape::Type GetType() const; - - /// Get the child shape. You can modify the child shape, however you should not change the - /// number of vertices because this will crash some collision caching mechanisms. - /// Manipulating the shape may lead to non-physical behavior. - b2Shape* GetShape(); - const b2Shape* GetShape() const; - - /// Set if this fixture is a sensor. - void SetSensor(bool sensor); - - /// Is this fixture a sensor (non-solid)? - /// @return the true if the shape is a sensor. - bool IsSensor() const; - - /// Set the contact filtering data. This will not update contacts until the next time - /// step when either parent body is active and awake. - /// This automatically calls Refilter. - void SetFilterData(const b2Filter& filter); - - /// Get the contact filtering data. - const b2Filter& GetFilterData() const; - - /// Call this if you want to establish collision that was previously disabled by b2ContactFilter::ShouldCollide. - void Refilter(); - - /// Get the parent body of this fixture. This is nullptr if the fixture is not attached. - /// @return the parent body. - b2Body* GetBody(); - const b2Body* GetBody() const; - - /// Get the next fixture in the parent body's fixture list. - /// @return the next shape. - b2Fixture* GetNext(); - const b2Fixture* GetNext() const; - - /// Get the user data that was assigned in the fixture definition. Use this to - /// store your application specific data. - b2FixtureUserData& GetUserData(); - const b2FixtureUserData& GetUserData() const; - - /// Test a point for containment in this fixture. - /// @param p a point in world coordinates. - bool TestPoint(const b2Vec2& p) const; - - /// Cast a ray against this shape. - /// @param output the ray-cast results. - /// @param input the ray-cast input parameters. - /// @param childIndex the child shape index (e.g. edge index) - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const; - - /// Get the mass data for this fixture. The mass data is based on the density and - /// the shape. The rotational inertia is about the shape's origin. This operation - /// may be expensive. - void GetMassData(b2MassData* massData) const; - - /// Set the density of this fixture. This will _not_ automatically adjust the mass - /// of the body. You must call b2Body::ResetMassData to update the body's mass. - void SetDensity(float density); - - /// Get the density of this fixture. - float GetDensity() const; - - /// Get the coefficient of friction. - float GetFriction() const; - - /// Set the coefficient of friction. This will _not_ change the friction of - /// existing contacts. - void SetFriction(float friction); - - /// Get the coefficient of restitution. - float GetRestitution() const; - - /// Set the coefficient of restitution. This will _not_ change the restitution of - /// existing contacts. - void SetRestitution(float restitution); - - /// Get the restitution velocity threshold. - float GetRestitutionThreshold() const; - - /// Set the restitution threshold. This will _not_ change the restitution threshold of - /// existing contacts. - void SetRestitutionThreshold(float threshold); - - /// Get the fixture's AABB. This AABB may be enlarge and/or stale. - /// If you need a more accurate AABB, compute it using the shape and - /// the body transform. - const b2AABB& GetAABB(int32 childIndex) const; - - /// Dump this fixture to the log file. - void Dump(int32 bodyIndex); - -protected: - - friend class b2Body; - friend class b2World; - friend class b2Contact; - friend class b2ContactManager; - - b2Fixture(); - - // We need separation create/destroy functions from the constructor/destructor because - // the destructor cannot access the allocator (no destructor arguments allowed by C++). - void Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def); - void Destroy(b2BlockAllocator* allocator); - - // These support body activation/deactivation. - void CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf); - void DestroyProxies(b2BroadPhase* broadPhase); - - void Synchronize(b2BroadPhase* broadPhase, const b2Transform& xf1, const b2Transform& xf2); - - float m_density; - - b2Fixture* m_next; - b2Body* m_body; - - b2Shape* m_shape; - - float m_friction; - float m_restitution; - float m_restitutionThreshold; - - b2FixtureProxy* m_proxies; - int32 m_proxyCount; - - b2Filter m_filter; - - bool m_isSensor; - - b2FixtureUserData m_userData; -}; - -inline b2Shape::Type b2Fixture::GetType() const -{ - return m_shape->GetType(); -} - -inline b2Shape* b2Fixture::GetShape() -{ - return m_shape; -} - -inline const b2Shape* b2Fixture::GetShape() const -{ - return m_shape; -} - -inline bool b2Fixture::IsSensor() const -{ - return m_isSensor; -} - -inline const b2Filter& b2Fixture::GetFilterData() const -{ - return m_filter; -} - -inline b2FixtureUserData& b2Fixture::GetUserData() -{ - return m_userData; -} - -inline const b2FixtureUserData& b2Fixture::GetUserData() const -{ - return m_userData; -} - -inline b2Body* b2Fixture::GetBody() -{ - return m_body; -} - -inline const b2Body* b2Fixture::GetBody() const -{ - return m_body; -} - -inline b2Fixture* b2Fixture::GetNext() -{ - return m_next; -} - -inline const b2Fixture* b2Fixture::GetNext() const -{ - return m_next; -} - -inline void b2Fixture::SetDensity(float density) -{ - b2Assert(b2IsValid(density) && density >= 0.0f); - m_density = density; -} - -inline float b2Fixture::GetDensity() const -{ - return m_density; -} - -inline float b2Fixture::GetFriction() const -{ - return m_friction; -} - -inline void b2Fixture::SetFriction(float friction) -{ - m_friction = friction; -} - -inline float b2Fixture::GetRestitution() const -{ - return m_restitution; -} - -inline void b2Fixture::SetRestitution(float restitution) -{ - m_restitution = restitution; -} - -inline float b2Fixture::GetRestitutionThreshold() const -{ - return m_restitutionThreshold; -} - -inline void b2Fixture::SetRestitutionThreshold(float threshold) -{ - m_restitutionThreshold = threshold; -} - -inline bool b2Fixture::TestPoint(const b2Vec2& p) const -{ - return m_shape->TestPoint(m_body->GetTransform(), p); -} - -inline bool b2Fixture::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, int32 childIndex) const -{ - return m_shape->RayCast(output, input, m_body->GetTransform(), childIndex); -} - -inline void b2Fixture::GetMassData(b2MassData* massData) const -{ - m_shape->ComputeMass(massData, m_density); -} - -inline const b2AABB& b2Fixture::GetAABB(int32 childIndex) const -{ - b2Assert(0 <= childIndex && childIndex < m_proxyCount); - return m_proxies[childIndex].aabb; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_friction_joint.h b/3rdparty/box2d/include/box2d/b2_friction_joint.h deleted file mode 100644 index 99922c3a375f..000000000000 --- a/3rdparty/box2d/include/box2d/b2_friction_joint.h +++ /dev/null @@ -1,124 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_FRICTION_JOINT_H -#define B2_FRICTION_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Friction joint definition. -struct B2_API b2FrictionJointDef : public b2JointDef -{ - b2FrictionJointDef() - { - type = e_frictionJoint; - localAnchorA.SetZero(); - localAnchorB.SetZero(); - maxForce = 0.0f; - maxTorque = 0.0f; - } - - /// Initialize the bodies, anchors, axis, and reference angle using the world - /// anchor and world axis. - void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The maximum friction force in N. - float maxForce; - - /// The maximum friction torque in N-m. - float maxTorque; -}; - -/// Friction joint. This is used for top-down friction. -/// It provides 2D translational friction and angular friction. -class B2_API b2FrictionJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// Set the maximum friction force in N. - void SetMaxForce(float force); - - /// Get the maximum friction force in N. - float GetMaxForce() const; - - /// Set the maximum friction torque in N*m. - void SetMaxTorque(float torque); - - /// Get the maximum friction torque in N*m. - float GetMaxTorque() const; - - /// Dump joint to dmLog - void Dump() override; - -protected: - - friend class b2Joint; - - b2FrictionJoint(const b2FrictionJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - - // Solver shared - b2Vec2 m_linearImpulse; - float m_angularImpulse; - float m_maxForce; - float m_maxTorque; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - b2Mat22 m_linearMass; - float m_angularMass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_gear_joint.h b/3rdparty/box2d/include/box2d/b2_gear_joint.h deleted file mode 100644 index a7e4fa5197d7..000000000000 --- a/3rdparty/box2d/include/box2d/b2_gear_joint.h +++ /dev/null @@ -1,131 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_GEAR_JOINT_H -#define B2_GEAR_JOINT_H - -#include "b2_joint.h" - -/// Gear joint definition. This definition requires two existing -/// revolute or prismatic joints (any combination will work). -/// @warning bodyB on the input joints must both be dynamic -struct B2_API b2GearJointDef : public b2JointDef -{ - b2GearJointDef() - { - type = e_gearJoint; - joint1 = nullptr; - joint2 = nullptr; - ratio = 1.0f; - } - - /// The first revolute/prismatic joint attached to the gear joint. - b2Joint* joint1; - - /// The second revolute/prismatic joint attached to the gear joint. - b2Joint* joint2; - - /// The gear ratio. - /// @see b2GearJoint for explanation. - float ratio; -}; - -/// A gear joint is used to connect two joints together. Either joint -/// can be a revolute or prismatic joint. You specify a gear ratio -/// to bind the motions together: -/// coordinate1 + ratio * coordinate2 = constant -/// The ratio can be negative or positive. If one joint is a revolute joint -/// and the other joint is a prismatic joint, then the ratio will have units -/// of length or units of 1/length. -/// @warning You have to manually destroy the gear joint if joint1 or joint2 -/// is destroyed. -class B2_API b2GearJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// Get the first joint. - b2Joint* GetJoint1() { return m_joint1; } - - /// Get the second joint. - b2Joint* GetJoint2() { return m_joint2; } - - /// Set/Get the gear ratio. - void SetRatio(float ratio); - float GetRatio() const; - - /// Dump joint to dmLog - void Dump() override; - -protected: - - friend class b2Joint; - b2GearJoint(const b2GearJointDef* data); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Joint* m_joint1; - b2Joint* m_joint2; - - b2JointType m_typeA; - b2JointType m_typeB; - - // Body A is connected to body C - // Body B is connected to body D - b2Body* m_bodyC; - b2Body* m_bodyD; - - // Solver shared - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - b2Vec2 m_localAnchorC; - b2Vec2 m_localAnchorD; - - b2Vec2 m_localAxisC; - b2Vec2 m_localAxisD; - - float m_referenceAngleA; - float m_referenceAngleB; - - float m_constant; - float m_ratio; - float m_tolerance; - - float m_impulse; - - // Solver temp - int32 m_indexA, m_indexB, m_indexC, m_indexD; - b2Vec2 m_lcA, m_lcB, m_lcC, m_lcD; - float m_mA, m_mB, m_mC, m_mD; - float m_iA, m_iB, m_iC, m_iD; - b2Vec2 m_JvAC, m_JvBD; - float m_JwA, m_JwB, m_JwC, m_JwD; - float m_mass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_growable_stack.h b/3rdparty/box2d/include/box2d/b2_growable_stack.h deleted file mode 100644 index ec42e5e9e2d7..000000000000 --- a/3rdparty/box2d/include/box2d/b2_growable_stack.h +++ /dev/null @@ -1,91 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_GROWABLE_STACK_H -#define B2_GROWABLE_STACK_H - -#include - -#include "b2_settings.h" - -/// This is a growable LIFO stack with an initial capacity of N. -/// If the stack size exceeds the initial capacity, the heap is used -/// to increase the size of the stack. -template -class b2GrowableStack -{ -public: - b2GrowableStack() - { - m_stack = m_array; - m_count = 0; - m_capacity = N; - } - - ~b2GrowableStack() - { - if (m_stack != m_array) - { - b2Free(m_stack); - m_stack = nullptr; - } - } - - void Push(const T& element) - { - if (m_count == m_capacity) - { - T* old = m_stack; - m_capacity *= 2; - m_stack = (T*)b2Alloc(m_capacity * sizeof(T)); - memcpy(m_stack, old, m_count * sizeof(T)); - if (old != m_array) - { - b2Free(old); - } - } - - m_stack[m_count] = element; - ++m_count; - } - - T Pop() - { - b2Assert(m_count > 0); - --m_count; - return m_stack[m_count]; - } - - int32 GetCount() - { - return m_count; - } - -private: - T* m_stack; - T m_array[N]; - int32 m_count; - int32 m_capacity; -}; - - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_joint.h b/3rdparty/box2d/include/box2d/b2_joint.h deleted file mode 100644 index 586b13ad1866..000000000000 --- a/3rdparty/box2d/include/box2d/b2_joint.h +++ /dev/null @@ -1,233 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_JOINT_H -#define B2_JOINT_H - -#include "b2_api.h" -#include "b2_math.h" - -class b2Body; -class b2Draw; -class b2Joint; -struct b2SolverData; -class b2BlockAllocator; - -enum b2JointType -{ - e_unknownJoint, - e_revoluteJoint, - e_prismaticJoint, - e_distanceJoint, - e_pulleyJoint, - e_mouseJoint, - e_gearJoint, - e_wheelJoint, - e_weldJoint, - e_frictionJoint, - e_motorJoint -}; - -struct B2_API b2Jacobian -{ - b2Vec2 linear; - float angularA; - float angularB; -}; - -/// A joint edge is used to connect bodies and joints together -/// in a joint graph where each body is a node and each joint -/// is an edge. A joint edge belongs to a doubly linked list -/// maintained in each attached body. Each joint has two joint -/// nodes, one for each attached body. -struct B2_API b2JointEdge -{ - b2Body* other; ///< provides quick access to the other body attached. - b2Joint* joint; ///< the joint - b2JointEdge* prev; ///< the previous joint edge in the body's joint list - b2JointEdge* next; ///< the next joint edge in the body's joint list -}; - -/// Joint definitions are used to construct joints. -struct B2_API b2JointDef -{ - b2JointDef() - { - type = e_unknownJoint; - bodyA = nullptr; - bodyB = nullptr; - collideConnected = false; - } - - /// The joint type is set automatically for concrete joint types. - b2JointType type; - - /// Use this to attach application specific data to your joints. - b2JointUserData userData; - - /// The first attached body. - b2Body* bodyA; - - /// The second attached body. - b2Body* bodyB; - - /// Set this flag to true if the attached bodies should collide. - bool collideConnected; -}; - -/// Utility to compute linear stiffness values from frequency and damping ratio -B2_API void b2LinearStiffness(float& stiffness, float& damping, - float frequencyHertz, float dampingRatio, - const b2Body* bodyA, const b2Body* bodyB); - -/// Utility to compute rotational stiffness values frequency and damping ratio -B2_API void b2AngularStiffness(float& stiffness, float& damping, - float frequencyHertz, float dampingRatio, - const b2Body* bodyA, const b2Body* bodyB); - -/// The base joint class. Joints are used to constraint two bodies together in -/// various fashions. Some joints also feature limits and motors. -class B2_API b2Joint -{ -public: - - /// Get the type of the concrete joint. - b2JointType GetType() const; - - /// Get the first body attached to this joint. - b2Body* GetBodyA(); - - /// Get the second body attached to this joint. - b2Body* GetBodyB(); - - /// Get the anchor point on bodyA in world coordinates. - virtual b2Vec2 GetAnchorA() const = 0; - - /// Get the anchor point on bodyB in world coordinates. - virtual b2Vec2 GetAnchorB() const = 0; - - /// Get the reaction force on bodyB at the joint anchor in Newtons. - virtual b2Vec2 GetReactionForce(float inv_dt) const = 0; - - /// Get the reaction torque on bodyB in N*m. - virtual float GetReactionTorque(float inv_dt) const = 0; - - /// Get the next joint the world joint list. - b2Joint* GetNext(); - const b2Joint* GetNext() const; - - /// Get the user data pointer. - b2JointUserData& GetUserData(); - const b2JointUserData& GetUserData() const; - - /// Short-cut function to determine if either body is enabled. - bool IsEnabled() const; - - /// Get collide connected. - /// Note: modifying the collide connect flag won't work correctly because - /// the flag is only checked when fixture AABBs begin to overlap. - bool GetCollideConnected() const; - - /// Dump this joint to the log file. - virtual void Dump() { b2Dump("// Dump is not supported for this joint type.\n"); } - - /// Shift the origin for any points stored in world coordinates. - virtual void ShiftOrigin(const b2Vec2& newOrigin) { B2_NOT_USED(newOrigin); } - - /// Debug draw this joint - virtual void Draw(b2Draw* draw) const; - -protected: - friend class b2World; - friend class b2Body; - friend class b2Island; - friend class b2GearJoint; - - static b2Joint* Create(const b2JointDef* def, b2BlockAllocator* allocator); - static void Destroy(b2Joint* joint, b2BlockAllocator* allocator); - - b2Joint(const b2JointDef* def); - virtual ~b2Joint() {} - - virtual void InitVelocityConstraints(const b2SolverData& data) = 0; - virtual void SolveVelocityConstraints(const b2SolverData& data) = 0; - - // This returns true if the position errors are within tolerance. - virtual bool SolvePositionConstraints(const b2SolverData& data) = 0; - - b2JointType m_type; - b2Joint* m_prev; - b2Joint* m_next; - b2JointEdge m_edgeA; - b2JointEdge m_edgeB; - b2Body* m_bodyA; - b2Body* m_bodyB; - - int32 m_index; - - bool m_islandFlag; - bool m_collideConnected; - - b2JointUserData m_userData; -}; - -inline b2JointType b2Joint::GetType() const -{ - return m_type; -} - -inline b2Body* b2Joint::GetBodyA() -{ - return m_bodyA; -} - -inline b2Body* b2Joint::GetBodyB() -{ - return m_bodyB; -} - -inline b2Joint* b2Joint::GetNext() -{ - return m_next; -} - -inline const b2Joint* b2Joint::GetNext() const -{ - return m_next; -} - -inline b2JointUserData& b2Joint::GetUserData() -{ - return m_userData; -} - -inline const b2JointUserData& b2Joint::GetUserData() const -{ - return m_userData; -} - -inline bool b2Joint::GetCollideConnected() const -{ - return m_collideConnected; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_math.h b/3rdparty/box2d/include/box2d/b2_math.h deleted file mode 100644 index c98cf35dfcb2..000000000000 --- a/3rdparty/box2d/include/box2d/b2_math.h +++ /dev/null @@ -1,717 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_MATH_H -#define B2_MATH_H - -#include - -#include "b2_api.h" -#include "b2_settings.h" - -/// This function is used to ensure that a floating point number is not a NaN or infinity. -inline bool b2IsValid(float x) -{ - return isfinite(x); -} - -#define b2Sqrt(x) sqrtf(x) -#define b2Atan2(y, x) atan2f(y, x) - -/// A 2D column vector. -struct B2_API b2Vec2 -{ - /// Default constructor does nothing (for performance). - b2Vec2() = default; - - /// Construct using coordinates. - b2Vec2(float xIn, float yIn) : x(xIn), y(yIn) {} - - /// Set this vector to all zeros. - void SetZero() { x = 0.0f; y = 0.0f; } - - /// Set this vector to some specified coordinates. - void Set(float x_, float y_) { x = x_; y = y_; } - - /// Negate this vector. - b2Vec2 operator -() const { b2Vec2 v; v.Set(-x, -y); return v; } - - /// Read from and indexed element. - float operator () (int32 i) const - { - return (&x)[i]; - } - - /// Write to an indexed element. - float& operator () (int32 i) - { - return (&x)[i]; - } - - /// Add a vector to this vector. - void operator += (const b2Vec2& v) - { - x += v.x; y += v.y; - } - - /// Subtract a vector from this vector. - void operator -= (const b2Vec2& v) - { - x -= v.x; y -= v.y; - } - - /// Multiply this vector by a scalar. - void operator *= (float a) - { - x *= a; y *= a; - } - - /// Get the length of this vector (the norm). - float Length() const - { - return b2Sqrt(x * x + y * y); - } - - /// Get the length squared. For performance, use this instead of - /// b2Vec2::Length (if possible). - float LengthSquared() const - { - return x * x + y * y; - } - - /// Convert this vector into a unit vector. Returns the length. - float Normalize() - { - float length = Length(); - if (length < b2_epsilon) - { - return 0.0f; - } - float invLength = 1.0f / length; - x *= invLength; - y *= invLength; - - return length; - } - - /// Does this vector contain finite coordinates? - bool IsValid() const - { - return b2IsValid(x) && b2IsValid(y); - } - - /// Get the skew vector such that dot(skew_vec, other) == cross(vec, other) - b2Vec2 Skew() const - { - return b2Vec2(-y, x); - } - - float x, y; -}; - -/// A 2D column vector with 3 elements. -struct B2_API b2Vec3 -{ - /// Default constructor does nothing (for performance). - b2Vec3() = default; - - /// Construct using coordinates. - b2Vec3(float xIn, float yIn, float zIn) : x(xIn), y(yIn), z(zIn) {} - - /// Set this vector to all zeros. - void SetZero() { x = 0.0f; y = 0.0f; z = 0.0f; } - - /// Set this vector to some specified coordinates. - void Set(float x_, float y_, float z_) { x = x_; y = y_; z = z_; } - - /// Negate this vector. - b2Vec3 operator -() const { b2Vec3 v; v.Set(-x, -y, -z); return v; } - - /// Add a vector to this vector. - void operator += (const b2Vec3& v) - { - x += v.x; y += v.y; z += v.z; - } - - /// Subtract a vector from this vector. - void operator -= (const b2Vec3& v) - { - x -= v.x; y -= v.y; z -= v.z; - } - - /// Multiply this vector by a scalar. - void operator *= (float s) - { - x *= s; y *= s; z *= s; - } - - float x, y, z; -}; - -/// A 2-by-2 matrix. Stored in column-major order. -struct B2_API b2Mat22 -{ - /// The default constructor does nothing (for performance). - b2Mat22() = default; - - /// Construct this matrix using columns. - b2Mat22(const b2Vec2& c1, const b2Vec2& c2) - { - ex = c1; - ey = c2; - } - - /// Construct this matrix using scalars. - b2Mat22(float a11, float a12, float a21, float a22) - { - ex.x = a11; ex.y = a21; - ey.x = a12; ey.y = a22; - } - - /// Initialize this matrix using columns. - void Set(const b2Vec2& c1, const b2Vec2& c2) - { - ex = c1; - ey = c2; - } - - /// Set this to the identity matrix. - void SetIdentity() - { - ex.x = 1.0f; ey.x = 0.0f; - ex.y = 0.0f; ey.y = 1.0f; - } - - /// Set this matrix to all zeros. - void SetZero() - { - ex.x = 0.0f; ey.x = 0.0f; - ex.y = 0.0f; ey.y = 0.0f; - } - - b2Mat22 GetInverse() const - { - float a = ex.x, b = ey.x, c = ex.y, d = ey.y; - b2Mat22 B; - float det = a * d - b * c; - if (det != 0.0f) - { - det = 1.0f / det; - } - B.ex.x = det * d; B.ey.x = -det * b; - B.ex.y = -det * c; B.ey.y = det * a; - return B; - } - - /// Solve A * x = b, where b is a column vector. This is more efficient - /// than computing the inverse in one-shot cases. - b2Vec2 Solve(const b2Vec2& b) const - { - float a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y; - float det = a11 * a22 - a12 * a21; - if (det != 0.0f) - { - det = 1.0f / det; - } - b2Vec2 x; - x.x = det * (a22 * b.x - a12 * b.y); - x.y = det * (a11 * b.y - a21 * b.x); - return x; - } - - b2Vec2 ex, ey; -}; - -/// A 3-by-3 matrix. Stored in column-major order. -struct B2_API b2Mat33 -{ - /// The default constructor does nothing (for performance). - b2Mat33() = default; - - /// Construct this matrix using columns. - b2Mat33(const b2Vec3& c1, const b2Vec3& c2, const b2Vec3& c3) - { - ex = c1; - ey = c2; - ez = c3; - } - - /// Set this matrix to all zeros. - void SetZero() - { - ex.SetZero(); - ey.SetZero(); - ez.SetZero(); - } - - /// Solve A * x = b, where b is a column vector. This is more efficient - /// than computing the inverse in one-shot cases. - b2Vec3 Solve33(const b2Vec3& b) const; - - /// Solve A * x = b, where b is a column vector. This is more efficient - /// than computing the inverse in one-shot cases. Solve only the upper - /// 2-by-2 matrix equation. - b2Vec2 Solve22(const b2Vec2& b) const; - - /// Get the inverse of this matrix as a 2-by-2. - /// Returns the zero matrix if singular. - void GetInverse22(b2Mat33* M) const; - - /// Get the symmetric inverse of this matrix as a 3-by-3. - /// Returns the zero matrix if singular. - void GetSymInverse33(b2Mat33* M) const; - - b2Vec3 ex, ey, ez; -}; - -/// Rotation -struct B2_API b2Rot -{ - b2Rot() = default; - - /// Initialize from an angle in radians - explicit b2Rot(float angle) - { - /// TODO_ERIN optimize - s = sinf(angle); - c = cosf(angle); - } - - /// Set using an angle in radians. - void Set(float angle) - { - /// TODO_ERIN optimize - s = sinf(angle); - c = cosf(angle); - } - - /// Set to the identity rotation - void SetIdentity() - { - s = 0.0f; - c = 1.0f; - } - - /// Get the angle in radians - float GetAngle() const - { - return b2Atan2(s, c); - } - - /// Get the x-axis - b2Vec2 GetXAxis() const - { - return b2Vec2(c, s); - } - - /// Get the u-axis - b2Vec2 GetYAxis() const - { - return b2Vec2(-s, c); - } - - /// Sine and cosine - float s, c; -}; - -/// A transform contains translation and rotation. It is used to represent -/// the position and orientation of rigid frames. -struct B2_API b2Transform -{ - /// The default constructor does nothing. - b2Transform() = default; - - /// Initialize using a position vector and a rotation. - b2Transform(const b2Vec2& position, const b2Rot& rotation) : p(position), q(rotation) {} - - /// Set this to the identity transform. - void SetIdentity() - { - p.SetZero(); - q.SetIdentity(); - } - - /// Set this based on the position and angle. - void Set(const b2Vec2& position, float angle) - { - p = position; - q.Set(angle); - } - - b2Vec2 p; - b2Rot q; -}; - -/// This describes the motion of a body/shape for TOI computation. -/// Shapes are defined with respect to the body origin, which may -/// no coincide with the center of mass. However, to support dynamics -/// we must interpolate the center of mass position. -struct B2_API b2Sweep -{ - b2Sweep() = default; - - /// Get the interpolated transform at a specific time. - /// @param transform the output transform - /// @param beta is a factor in [0,1], where 0 indicates alpha0. - void GetTransform(b2Transform* transform, float beta) const; - - /// Advance the sweep forward, yielding a new initial state. - /// @param alpha the new initial time. - void Advance(float alpha); - - /// Normalize the angles. - void Normalize(); - - b2Vec2 localCenter; ///< local center of mass position - b2Vec2 c0, c; ///< center world positions - float a0, a; ///< world angles - - /// Fraction of the current time step in the range [0,1] - /// c0 and a0 are the positions at alpha0. - float alpha0; -}; - -/// Useful constant -extern B2_API const b2Vec2 b2Vec2_zero; - -/// Perform the dot product on two vectors. -inline float b2Dot(const b2Vec2& a, const b2Vec2& b) -{ - return a.x * b.x + a.y * b.y; -} - -/// Perform the cross product on two vectors. In 2D this produces a scalar. -inline float b2Cross(const b2Vec2& a, const b2Vec2& b) -{ - return a.x * b.y - a.y * b.x; -} - -/// Perform the cross product on a vector and a scalar. In 2D this produces -/// a vector. -inline b2Vec2 b2Cross(const b2Vec2& a, float s) -{ - return b2Vec2(s * a.y, -s * a.x); -} - -/// Perform the cross product on a scalar and a vector. In 2D this produces -/// a vector. -inline b2Vec2 b2Cross(float s, const b2Vec2& a) -{ - return b2Vec2(-s * a.y, s * a.x); -} - -/// Multiply a matrix times a vector. If a rotation matrix is provided, -/// then this transforms the vector from one frame to another. -inline b2Vec2 b2Mul(const b2Mat22& A, const b2Vec2& v) -{ - return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); -} - -/// Multiply a matrix transpose times a vector. If a rotation matrix is provided, -/// then this transforms the vector from one frame to another (inverse transform). -inline b2Vec2 b2MulT(const b2Mat22& A, const b2Vec2& v) -{ - return b2Vec2(b2Dot(v, A.ex), b2Dot(v, A.ey)); -} - -/// Add two vectors component-wise. -inline b2Vec2 operator + (const b2Vec2& a, const b2Vec2& b) -{ - return b2Vec2(a.x + b.x, a.y + b.y); -} - -/// Subtract two vectors component-wise. -inline b2Vec2 operator - (const b2Vec2& a, const b2Vec2& b) -{ - return b2Vec2(a.x - b.x, a.y - b.y); -} - -inline b2Vec2 operator * (float s, const b2Vec2& a) -{ - return b2Vec2(s * a.x, s * a.y); -} - -inline bool operator == (const b2Vec2& a, const b2Vec2& b) -{ - return a.x == b.x && a.y == b.y; -} - -inline bool operator != (const b2Vec2& a, const b2Vec2& b) -{ - return a.x != b.x || a.y != b.y; -} - -inline float b2Distance(const b2Vec2& a, const b2Vec2& b) -{ - b2Vec2 c = a - b; - return c.Length(); -} - -inline float b2DistanceSquared(const b2Vec2& a, const b2Vec2& b) -{ - b2Vec2 c = a - b; - return b2Dot(c, c); -} - -inline b2Vec3 operator * (float s, const b2Vec3& a) -{ - return b2Vec3(s * a.x, s * a.y, s * a.z); -} - -/// Add two vectors component-wise. -inline b2Vec3 operator + (const b2Vec3& a, const b2Vec3& b) -{ - return b2Vec3(a.x + b.x, a.y + b.y, a.z + b.z); -} - -/// Subtract two vectors component-wise. -inline b2Vec3 operator - (const b2Vec3& a, const b2Vec3& b) -{ - return b2Vec3(a.x - b.x, a.y - b.y, a.z - b.z); -} - -/// Perform the dot product on two vectors. -inline float b2Dot(const b2Vec3& a, const b2Vec3& b) -{ - return a.x * b.x + a.y * b.y + a.z * b.z; -} - -/// Perform the cross product on two vectors. -inline b2Vec3 b2Cross(const b2Vec3& a, const b2Vec3& b) -{ - return b2Vec3(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x); -} - -inline b2Mat22 operator + (const b2Mat22& A, const b2Mat22& B) -{ - return b2Mat22(A.ex + B.ex, A.ey + B.ey); -} - -// A * B -inline b2Mat22 b2Mul(const b2Mat22& A, const b2Mat22& B) -{ - return b2Mat22(b2Mul(A, B.ex), b2Mul(A, B.ey)); -} - -// A^T * B -inline b2Mat22 b2MulT(const b2Mat22& A, const b2Mat22& B) -{ - b2Vec2 c1(b2Dot(A.ex, B.ex), b2Dot(A.ey, B.ex)); - b2Vec2 c2(b2Dot(A.ex, B.ey), b2Dot(A.ey, B.ey)); - return b2Mat22(c1, c2); -} - -/// Multiply a matrix times a vector. -inline b2Vec3 b2Mul(const b2Mat33& A, const b2Vec3& v) -{ - return v.x * A.ex + v.y * A.ey + v.z * A.ez; -} - -/// Multiply a matrix times a vector. -inline b2Vec2 b2Mul22(const b2Mat33& A, const b2Vec2& v) -{ - return b2Vec2(A.ex.x * v.x + A.ey.x * v.y, A.ex.y * v.x + A.ey.y * v.y); -} - -/// Multiply two rotations: q * r -inline b2Rot b2Mul(const b2Rot& q, const b2Rot& r) -{ - // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] - // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] - // s = qs * rc + qc * rs - // c = qc * rc - qs * rs - b2Rot qr; - qr.s = q.s * r.c + q.c * r.s; - qr.c = q.c * r.c - q.s * r.s; - return qr; -} - -/// Transpose multiply two rotations: qT * r -inline b2Rot b2MulT(const b2Rot& q, const b2Rot& r) -{ - // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc] - // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc] - // s = qc * rs - qs * rc - // c = qc * rc + qs * rs - b2Rot qr; - qr.s = q.c * r.s - q.s * r.c; - qr.c = q.c * r.c + q.s * r.s; - return qr; -} - -/// Rotate a vector -inline b2Vec2 b2Mul(const b2Rot& q, const b2Vec2& v) -{ - return b2Vec2(q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y); -} - -/// Inverse rotate a vector -inline b2Vec2 b2MulT(const b2Rot& q, const b2Vec2& v) -{ - return b2Vec2(q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y); -} - -inline b2Vec2 b2Mul(const b2Transform& T, const b2Vec2& v) -{ - float x = (T.q.c * v.x - T.q.s * v.y) + T.p.x; - float y = (T.q.s * v.x + T.q.c * v.y) + T.p.y; - - return b2Vec2(x, y); -} - -inline b2Vec2 b2MulT(const b2Transform& T, const b2Vec2& v) -{ - float px = v.x - T.p.x; - float py = v.y - T.p.y; - float x = (T.q.c * px + T.q.s * py); - float y = (-T.q.s * px + T.q.c * py); - - return b2Vec2(x, y); -} - -// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p -// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p -inline b2Transform b2Mul(const b2Transform& A, const b2Transform& B) -{ - b2Transform C; - C.q = b2Mul(A.q, B.q); - C.p = b2Mul(A.q, B.p) + A.p; - return C; -} - -// v2 = A.q' * (B.q * v1 + B.p - A.p) -// = A.q' * B.q * v1 + A.q' * (B.p - A.p) -inline b2Transform b2MulT(const b2Transform& A, const b2Transform& B) -{ - b2Transform C; - C.q = b2MulT(A.q, B.q); - C.p = b2MulT(A.q, B.p - A.p); - return C; -} - -template -inline T b2Abs(T a) -{ - return a > T(0) ? a : -a; -} - -inline b2Vec2 b2Abs(const b2Vec2& a) -{ - return b2Vec2(b2Abs(a.x), b2Abs(a.y)); -} - -inline b2Mat22 b2Abs(const b2Mat22& A) -{ - return b2Mat22(b2Abs(A.ex), b2Abs(A.ey)); -} - -template -inline T b2Min(T a, T b) -{ - return a < b ? a : b; -} - -inline b2Vec2 b2Min(const b2Vec2& a, const b2Vec2& b) -{ - return b2Vec2(b2Min(a.x, b.x), b2Min(a.y, b.y)); -} - -template -inline T b2Max(T a, T b) -{ - return a > b ? a : b; -} - -inline b2Vec2 b2Max(const b2Vec2& a, const b2Vec2& b) -{ - return b2Vec2(b2Max(a.x, b.x), b2Max(a.y, b.y)); -} - -template -inline T b2Clamp(T a, T low, T high) -{ - return b2Max(low, b2Min(a, high)); -} - -inline b2Vec2 b2Clamp(const b2Vec2& a, const b2Vec2& low, const b2Vec2& high) -{ - return b2Max(low, b2Min(a, high)); -} - -template inline void b2Swap(T& a, T& b) -{ - T tmp = a; - a = b; - b = tmp; -} - -/// "Next Largest Power of 2 -/// Given a binary integer value x, the next largest power of 2 can be computed by a SWAR algorithm -/// that recursively "folds" the upper bits into the lower bits. This process yields a bit vector with -/// the same most significant 1 as x, but all 1's below it. Adding 1 to that value yields the next -/// largest power of 2. For a 32-bit value:" -inline uint32 b2NextPowerOfTwo(uint32 x) -{ - x |= (x >> 1); - x |= (x >> 2); - x |= (x >> 4); - x |= (x >> 8); - x |= (x >> 16); - return x + 1; -} - -inline bool b2IsPowerOfTwo(uint32 x) -{ - bool result = x > 0 && (x & (x - 1)) == 0; - return result; -} - -// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ -inline void b2Sweep::GetTransform(b2Transform* xf, float beta) const -{ - xf->p = (1.0f - beta) * c0 + beta * c; - float angle = (1.0f - beta) * a0 + beta * a; - xf->q.Set(angle); - - // Shift to origin - xf->p -= b2Mul(xf->q, localCenter); -} - -inline void b2Sweep::Advance(float alpha) -{ - b2Assert(alpha0 < 1.0f); - float beta = (alpha - alpha0) / (1.0f - alpha0); - c0 += beta * (c - c0); - a0 += beta * (a - a0); - alpha0 = alpha; -} - -/// Normalize an angle in radians to be between -pi and pi -inline void b2Sweep::Normalize() -{ - float twoPi = 2.0f * b2_pi; - float d = twoPi * floorf(a0 / twoPi); - a0 -= d; - a -= d; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_motor_joint.h b/3rdparty/box2d/include/box2d/b2_motor_joint.h deleted file mode 100644 index c88115f20b48..000000000000 --- a/3rdparty/box2d/include/box2d/b2_motor_joint.h +++ /dev/null @@ -1,138 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_MOTOR_JOINT_H -#define B2_MOTOR_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Motor joint definition. -struct B2_API b2MotorJointDef : public b2JointDef -{ - b2MotorJointDef() - { - type = e_motorJoint; - linearOffset.SetZero(); - angularOffset = 0.0f; - maxForce = 1.0f; - maxTorque = 1.0f; - correctionFactor = 0.3f; - } - - /// Initialize the bodies and offsets using the current transforms. - void Initialize(b2Body* bodyA, b2Body* bodyB); - - /// Position of bodyB minus the position of bodyA, in bodyA's frame, in meters. - b2Vec2 linearOffset; - - /// The bodyB angle minus bodyA angle in radians. - float angularOffset; - - /// The maximum motor force in N. - float maxForce; - - /// The maximum motor torque in N-m. - float maxTorque; - - /// Position correction factor in the range [0,1]. - float correctionFactor; -}; - -/// A motor joint is used to control the relative motion -/// between two bodies. A typical usage is to control the movement -/// of a dynamic body with respect to the ground. -class B2_API b2MotorJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// Set/get the target linear offset, in frame A, in meters. - void SetLinearOffset(const b2Vec2& linearOffset); - const b2Vec2& GetLinearOffset() const; - - /// Set/get the target angular offset, in radians. - void SetAngularOffset(float angularOffset); - float GetAngularOffset() const; - - /// Set the maximum friction force in N. - void SetMaxForce(float force); - - /// Get the maximum friction force in N. - float GetMaxForce() const; - - /// Set the maximum friction torque in N*m. - void SetMaxTorque(float torque); - - /// Get the maximum friction torque in N*m. - float GetMaxTorque() const; - - /// Set the position correction factor in the range [0,1]. - void SetCorrectionFactor(float factor); - - /// Get the position correction factor in the range [0,1]. - float GetCorrectionFactor() const; - - /// Dump to b2Log - void Dump() override; - -protected: - - friend class b2Joint; - - b2MotorJoint(const b2MotorJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - // Solver shared - b2Vec2 m_linearOffset; - float m_angularOffset; - b2Vec2 m_linearImpulse; - float m_angularImpulse; - float m_maxForce; - float m_maxTorque; - float m_correctionFactor; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - b2Vec2 m_linearError; - float m_angularError; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - b2Mat22 m_linearMass; - float m_angularMass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_mouse_joint.h b/3rdparty/box2d/include/box2d/b2_mouse_joint.h deleted file mode 100644 index fcbc56a70ce3..000000000000 --- a/3rdparty/box2d/include/box2d/b2_mouse_joint.h +++ /dev/null @@ -1,134 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_MOUSE_JOINT_H -#define B2_MOUSE_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Mouse joint definition. This requires a world target point, -/// tuning parameters, and the time step. -struct B2_API b2MouseJointDef : public b2JointDef -{ - b2MouseJointDef() - { - type = e_mouseJoint; - target.Set(0.0f, 0.0f); - maxForce = 0.0f; - stiffness = 0.0f; - damping = 0.0f; - } - - /// The initial world target point. This is assumed - /// to coincide with the body anchor initially. - b2Vec2 target; - - /// The maximum constraint force that can be exerted - /// to move the candidate body. Usually you will express - /// as some multiple of the weight (multiplier * mass * gravity). - float maxForce; - - /// The linear stiffness in N/m - float stiffness; - - /// The linear damping in N*s/m - float damping; -}; - -/// A mouse joint is used to make a point on a body track a -/// specified world point. This a soft constraint with a maximum -/// force. This allows the constraint to stretch and without -/// applying huge forces. -/// NOTE: this joint is not documented in the manual because it was -/// developed to be used in the testbed. If you want to learn how to -/// use the mouse joint, look at the testbed. -class B2_API b2MouseJoint : public b2Joint -{ -public: - - /// Implements b2Joint. - b2Vec2 GetAnchorA() const override; - - /// Implements b2Joint. - b2Vec2 GetAnchorB() const override; - - /// Implements b2Joint. - b2Vec2 GetReactionForce(float inv_dt) const override; - - /// Implements b2Joint. - float GetReactionTorque(float inv_dt) const override; - - /// Use this to update the target point. - void SetTarget(const b2Vec2& target); - const b2Vec2& GetTarget() const; - - /// Set/get the maximum force in Newtons. - void SetMaxForce(float force); - float GetMaxForce() const; - - /// Set/get the linear stiffness in N/m - void SetStiffness(float stiffness) { m_stiffness = stiffness; } - float GetStiffness() const { return m_stiffness; } - - /// Set/get linear damping in N*s/m - void SetDamping(float damping) { m_damping = damping; } - float GetDamping() const { return m_damping; } - - /// The mouse joint does not support dumping. - void Dump() override { b2Log("Mouse joint dumping is not supported.\n"); } - - /// Implement b2Joint::ShiftOrigin - void ShiftOrigin(const b2Vec2& newOrigin) override; - -protected: - friend class b2Joint; - - b2MouseJoint(const b2MouseJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Vec2 m_localAnchorB; - b2Vec2 m_targetA; - float m_stiffness; - float m_damping; - float m_beta; - - // Solver shared - b2Vec2 m_impulse; - float m_maxForce; - float m_gamma; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_rB; - b2Vec2 m_localCenterB; - float m_invMassB; - float m_invIB; - b2Mat22 m_mass; - b2Vec2 m_C; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_polygon_shape.h b/3rdparty/box2d/include/box2d/b2_polygon_shape.h deleted file mode 100644 index 8a208b72b66d..000000000000 --- a/3rdparty/box2d/include/box2d/b2_polygon_shape.h +++ /dev/null @@ -1,93 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -#ifndef B2_POLYGON_SHAPE_H -#define B2_POLYGON_SHAPE_H - -#include "b2_api.h" -#include "b2_shape.h" - -struct b2Hull; - -/// A solid convex polygon. It is assumed that the interior of the polygon is to -/// the left of each edge. -/// Polygons have a maximum number of vertices equal to b2_maxPolygonVertices. -/// In most cases you should not need many vertices for a convex polygon. -class B2_API b2PolygonShape : public b2Shape -{ -public: - b2PolygonShape(); - - /// Implement b2Shape. - b2Shape* Clone(b2BlockAllocator* allocator) const override; - - /// @see b2Shape::GetChildCount - int32 GetChildCount() const override; - - /// Create a convex hull from the given array of local points. - /// The count must be in the range [3, b2_maxPolygonVertices]. - /// @warning the points may be re-ordered, even if they form a convex polygon - /// @warning if this fails then the polygon is invalid - /// @returns true if valid - bool Set(const b2Vec2* points, int32 count); - - /// Create a polygon from a given convex hull (see b2ComputeHull). - /// @warning the hull must be valid or this will crash or have unexpected behavior - void Set(const b2Hull& hull); - - /// Build vertices to represent an axis-aligned box centered on the local origin. - /// @param hx the half-width. - /// @param hy the half-height. - void SetAsBox(float hx, float hy); - - /// Build vertices to represent an oriented box. - /// @param hx the half-width. - /// @param hy the half-height. - /// @param center the center of the box in local coordinates. - /// @param angle the rotation of the box in local coordinates. - void SetAsBox(float hx, float hy, const b2Vec2& center, float angle); - - /// @see b2Shape::TestPoint - bool TestPoint(const b2Transform& transform, const b2Vec2& p) const override; - - /// Implement b2Shape. - /// @note because the polygon is solid, rays that start inside do not hit because the normal is - /// not defined. - bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeAABB - void ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const override; - - /// @see b2Shape::ComputeMass - void ComputeMass(b2MassData* massData, float density) const override; - - /// Validate convexity. This is a very time consuming operation. - /// @returns true if valid - bool Validate() const; - - b2Vec2 m_centroid; - b2Vec2 m_vertices[b2_maxPolygonVertices]; - b2Vec2 m_normals[b2_maxPolygonVertices]; - int32 m_count; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_prismatic_joint.h b/3rdparty/box2d/include/box2d/b2_prismatic_joint.h deleted file mode 100644 index 9d12d2126b3d..000000000000 --- a/3rdparty/box2d/include/box2d/b2_prismatic_joint.h +++ /dev/null @@ -1,205 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_PRISMATIC_JOINT_H -#define B2_PRISMATIC_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Prismatic joint definition. This requires defining a line of -/// motion using an axis and an anchor point. The definition uses local -/// anchor points and a local axis so that the initial configuration -/// can violate the constraint slightly. The joint translation is zero -/// when the local anchor points coincide in world space. Using local -/// anchors and a local axis helps when saving and loading a game. -struct B2_API b2PrismaticJointDef : public b2JointDef -{ - b2PrismaticJointDef() - { - type = e_prismaticJoint; - localAnchorA.SetZero(); - localAnchorB.SetZero(); - localAxisA.Set(1.0f, 0.0f); - referenceAngle = 0.0f; - enableLimit = false; - lowerTranslation = 0.0f; - upperTranslation = 0.0f; - enableMotor = false; - maxMotorForce = 0.0f; - motorSpeed = 0.0f; - } - - /// Initialize the bodies, anchors, axis, and reference angle using the world - /// anchor and unit world axis. - void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The local translation unit axis in bodyA. - b2Vec2 localAxisA; - - /// The constrained angle between the bodies: bodyB_angle - bodyA_angle. - float referenceAngle; - - /// Enable/disable the joint limit. - bool enableLimit; - - /// The lower translation limit, usually in meters. - float lowerTranslation; - - /// The upper translation limit, usually in meters. - float upperTranslation; - - /// Enable/disable the joint motor. - bool enableMotor; - - /// The maximum motor torque, usually in N-m. - float maxMotorForce; - - /// The desired motor speed in radians per second. - float motorSpeed; -}; - -/// A prismatic joint. This joint provides one degree of freedom: translation -/// along an axis fixed in bodyA. Relative rotation is prevented. You can -/// use a joint limit to restrict the range of motion and a joint motor to -/// drive the motion or to model joint friction. -class B2_API b2PrismaticJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// The local joint axis relative to bodyA. - const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; } - - /// Get the reference angle. - float GetReferenceAngle() const { return m_referenceAngle; } - - /// Get the current joint translation, usually in meters. - float GetJointTranslation() const; - - /// Get the current joint translation speed, usually in meters per second. - float GetJointSpeed() const; - - /// Is the joint limit enabled? - bool IsLimitEnabled() const; - - /// Enable/disable the joint limit. - void EnableLimit(bool flag); - - /// Get the lower joint limit, usually in meters. - float GetLowerLimit() const; - - /// Get the upper joint limit, usually in meters. - float GetUpperLimit() const; - - /// Set the joint limits, usually in meters. - void SetLimits(float lower, float upper); - - /// Is the joint motor enabled? - bool IsMotorEnabled() const; - - /// Enable/disable the joint motor. - void EnableMotor(bool flag); - - /// Set the motor speed, usually in meters per second. - void SetMotorSpeed(float speed); - - /// Get the motor speed, usually in meters per second. - float GetMotorSpeed() const; - - /// Set the maximum motor force, usually in N. - void SetMaxMotorForce(float force); - float GetMaxMotorForce() const { return m_maxMotorForce; } - - /// Get the current motor force given the inverse time step, usually in N. - float GetMotorForce(float inv_dt) const; - - /// Dump to b2Log - void Dump() override; - - /// - void Draw(b2Draw* draw) const override; - -protected: - friend class b2Joint; - friend class b2GearJoint; - b2PrismaticJoint(const b2PrismaticJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - b2Vec2 m_localXAxisA; - b2Vec2 m_localYAxisA; - float m_referenceAngle; - b2Vec2 m_impulse; - float m_motorImpulse; - float m_lowerImpulse; - float m_upperImpulse; - float m_lowerTranslation; - float m_upperTranslation; - float m_maxMotorForce; - float m_motorSpeed; - bool m_enableLimit; - bool m_enableMotor; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - b2Vec2 m_axis, m_perp; - float m_s1, m_s2; - float m_a1, m_a2; - b2Mat22 m_K; - float m_translation; - float m_axialMass; -}; - -inline float b2PrismaticJoint::GetMotorSpeed() const -{ - return m_motorSpeed; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_pulley_joint.h b/3rdparty/box2d/include/box2d/b2_pulley_joint.h deleted file mode 100644 index 6b1445641045..000000000000 --- a/3rdparty/box2d/include/box2d/b2_pulley_joint.h +++ /dev/null @@ -1,157 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_PULLEY_JOINT_H -#define B2_PULLEY_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -const float b2_minPulleyLength = 2.0f; - -/// Pulley joint definition. This requires two ground anchors, -/// two dynamic body anchor points, and a pulley ratio. -struct B2_API b2PulleyJointDef : public b2JointDef -{ - b2PulleyJointDef() - { - type = e_pulleyJoint; - groundAnchorA.Set(-1.0f, 1.0f); - groundAnchorB.Set(1.0f, 1.0f); - localAnchorA.Set(-1.0f, 0.0f); - localAnchorB.Set(1.0f, 0.0f); - lengthA = 0.0f; - lengthB = 0.0f; - ratio = 1.0f; - collideConnected = true; - } - - /// Initialize the bodies, anchors, lengths, max lengths, and ratio using the world anchors. - void Initialize(b2Body* bodyA, b2Body* bodyB, - const b2Vec2& groundAnchorA, const b2Vec2& groundAnchorB, - const b2Vec2& anchorA, const b2Vec2& anchorB, - float ratio); - - /// The first ground anchor in world coordinates. This point never moves. - b2Vec2 groundAnchorA; - - /// The second ground anchor in world coordinates. This point never moves. - b2Vec2 groundAnchorB; - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The a reference length for the segment attached to bodyA. - float lengthA; - - /// The a reference length for the segment attached to bodyB. - float lengthB; - - /// The pulley ratio, used to simulate a block-and-tackle. - float ratio; -}; - -/// The pulley joint is connected to two bodies and two fixed ground points. -/// The pulley supports a ratio such that: -/// length1 + ratio * length2 <= constant -/// Yes, the force transmitted is scaled by the ratio. -/// Warning: the pulley joint can get a bit squirrelly by itself. They often -/// work better when combined with prismatic joints. You should also cover the -/// the anchor points with static shapes to prevent one side from going to -/// zero length. -class B2_API b2PulleyJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// Get the first ground anchor. - b2Vec2 GetGroundAnchorA() const; - - /// Get the second ground anchor. - b2Vec2 GetGroundAnchorB() const; - - /// Get the current length of the segment attached to bodyA. - float GetLengthA() const; - - /// Get the current length of the segment attached to bodyB. - float GetLengthB() const; - - /// Get the pulley ratio. - float GetRatio() const; - - /// Get the current length of the segment attached to bodyA. - float GetCurrentLengthA() const; - - /// Get the current length of the segment attached to bodyB. - float GetCurrentLengthB() const; - - /// Dump joint to dmLog - void Dump() override; - - /// Implement b2Joint::ShiftOrigin - void ShiftOrigin(const b2Vec2& newOrigin) override; - -protected: - - friend class b2Joint; - b2PulleyJoint(const b2PulleyJointDef* data); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Vec2 m_groundAnchorA; - b2Vec2 m_groundAnchorB; - float m_lengthA; - float m_lengthB; - - // Solver shared - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - float m_constant; - float m_ratio; - float m_impulse; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_uA; - b2Vec2 m_uB; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - float m_mass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_revolute_joint.h b/3rdparty/box2d/include/box2d/b2_revolute_joint.h deleted file mode 100644 index 36ad5314efac..000000000000 --- a/3rdparty/box2d/include/box2d/b2_revolute_joint.h +++ /dev/null @@ -1,211 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_REVOLUTE_JOINT_H -#define B2_REVOLUTE_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Revolute joint definition. This requires defining an anchor point where the -/// bodies are joined. The definition uses local anchor points so that the -/// initial configuration can violate the constraint slightly. You also need to -/// specify the initial relative angle for joint limits. This helps when saving -/// and loading a game. -/// The local anchor points are measured from the body's origin -/// rather than the center of mass because: -/// 1. you might not know where the center of mass will be. -/// 2. if you add/remove shapes from a body and recompute the mass, -/// the joints will be broken. -struct B2_API b2RevoluteJointDef : public b2JointDef -{ - b2RevoluteJointDef() - { - type = e_revoluteJoint; - localAnchorA.Set(0.0f, 0.0f); - localAnchorB.Set(0.0f, 0.0f); - referenceAngle = 0.0f; - lowerAngle = 0.0f; - upperAngle = 0.0f; - maxMotorTorque = 0.0f; - motorSpeed = 0.0f; - enableLimit = false; - enableMotor = false; - } - - /// Initialize the bodies, anchors, and reference angle using a world - /// anchor point. - void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The bodyB angle minus bodyA angle in the reference state (radians). - float referenceAngle; - - /// A flag to enable joint limits. - bool enableLimit; - - /// The lower angle for the joint limit (radians). - float lowerAngle; - - /// The upper angle for the joint limit (radians). - float upperAngle; - - /// A flag to enable the joint motor. - bool enableMotor; - - /// The desired motor speed. Usually in radians per second. - float motorSpeed; - - /// The maximum motor torque used to achieve the desired motor speed. - /// Usually in N-m. - float maxMotorTorque; -}; - -/// A revolute joint constrains two bodies to share a common point while they -/// are free to rotate about the point. The relative rotation about the shared -/// point is the joint angle. You can limit the relative rotation with -/// a joint limit that specifies a lower and upper angle. You can use a motor -/// to drive the relative rotation about the shared point. A maximum motor torque -/// is provided so that infinite forces are not generated. -class B2_API b2RevoluteJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// Get the reference angle. - float GetReferenceAngle() const { return m_referenceAngle; } - - /// Get the current joint angle in radians. - float GetJointAngle() const; - - /// Get the current joint angle speed in radians per second. - float GetJointSpeed() const; - - /// Is the joint limit enabled? - bool IsLimitEnabled() const; - - /// Enable/disable the joint limit. - void EnableLimit(bool flag); - - /// Get the lower joint limit in radians. - float GetLowerLimit() const; - - /// Get the upper joint limit in radians. - float GetUpperLimit() const; - - /// Set the joint limits in radians. - void SetLimits(float lower, float upper); - - /// Is the joint motor enabled? - bool IsMotorEnabled() const; - - /// Enable/disable the joint motor. - void EnableMotor(bool flag); - - /// Set the motor speed in radians per second. - void SetMotorSpeed(float speed); - - /// Get the motor speed in radians per second. - float GetMotorSpeed() const; - - /// Set the maximum motor torque, usually in N-m. - void SetMaxMotorTorque(float torque); - float GetMaxMotorTorque() const { return m_maxMotorTorque; } - - /// Get the reaction force given the inverse time step. - /// Unit is N. - b2Vec2 GetReactionForce(float inv_dt) const override; - - /// Get the reaction torque due to the joint limit given the inverse time step. - /// Unit is N*m. - float GetReactionTorque(float inv_dt) const override; - - /// Get the current motor torque given the inverse time step. - /// Unit is N*m. - float GetMotorTorque(float inv_dt) const; - - /// Dump to b2Log. - void Dump() override; - - /// - void Draw(b2Draw* draw) const override; - -protected: - - friend class b2Joint; - friend class b2GearJoint; - - b2RevoluteJoint(const b2RevoluteJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - // Solver shared - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - b2Vec2 m_impulse; - float m_motorImpulse; - float m_lowerImpulse; - float m_upperImpulse; - bool m_enableMotor; - float m_maxMotorTorque; - float m_motorSpeed; - bool m_enableLimit; - float m_referenceAngle; - float m_lowerAngle; - float m_upperAngle; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - b2Mat22 m_K; - float m_angle; - float m_axialMass; -}; - -inline float b2RevoluteJoint::GetMotorSpeed() const -{ - return m_motorSpeed; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_rope.h b/3rdparty/box2d/include/box2d/b2_rope.h deleted file mode 100644 index 0c4f819595e7..000000000000 --- a/3rdparty/box2d/include/box2d/b2_rope.h +++ /dev/null @@ -1,155 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_ROPE_H -#define B2_ROPE_H - -#include "b2_api.h" -#include "b2_math.h" - -class b2Draw; -struct b2RopeStretch; -struct b2RopeBend; - -enum b2StretchingModel -{ - b2_pbdStretchingModel, - b2_xpbdStretchingModel -}; - -enum b2BendingModel -{ - b2_springAngleBendingModel = 0, - b2_pbdAngleBendingModel, - b2_xpbdAngleBendingModel, - b2_pbdDistanceBendingModel, - b2_pbdHeightBendingModel, - b2_pbdTriangleBendingModel -}; - -/// -struct B2_API b2RopeTuning -{ - b2RopeTuning() - { - stretchingModel = b2_pbdStretchingModel; - bendingModel = b2_pbdAngleBendingModel; - damping = 0.0f; - stretchStiffness = 1.0f; - stretchHertz = 1.0f; - stretchDamping = 0.0f; - bendStiffness = 0.5f; - bendHertz = 1.0f; - bendDamping = 0.0f; - isometric = false; - fixedEffectiveMass = false; - warmStart = false; - } - - b2StretchingModel stretchingModel; - b2BendingModel bendingModel; - float damping; - float stretchStiffness; - float stretchHertz; - float stretchDamping; - float bendStiffness; - float bendHertz; - float bendDamping; - bool isometric; - bool fixedEffectiveMass; - bool warmStart; -}; - -/// -struct B2_API b2RopeDef -{ - b2RopeDef() - { - position.SetZero(); - vertices = nullptr; - count = 0; - masses = nullptr; - gravity.SetZero(); - } - - b2Vec2 position; - b2Vec2* vertices; - int32 count; - float* masses; - b2Vec2 gravity; - b2RopeTuning tuning; -}; - -/// -class B2_API b2Rope -{ -public: - b2Rope(); - ~b2Rope(); - - /// - void Create(const b2RopeDef& def); - - /// - void SetTuning(const b2RopeTuning& tuning); - - /// - void Step(float timeStep, int32 iterations, const b2Vec2& position); - - /// - void Reset(const b2Vec2& position); - - /// - void Draw(b2Draw* draw) const; - -private: - - void SolveStretch_PBD(); - void SolveStretch_XPBD(float dt); - void SolveBend_PBD_Angle(); - void SolveBend_XPBD_Angle(float dt); - void SolveBend_PBD_Distance(); - void SolveBend_PBD_Height(); - void SolveBend_PBD_Triangle(); - void ApplyBendForces(float dt); - - b2Vec2 m_position; - - int32 m_count; - int32 m_stretchCount; - int32 m_bendCount; - - b2RopeStretch* m_stretchConstraints; - b2RopeBend* m_bendConstraints; - - b2Vec2* m_bindPositions; - b2Vec2* m_ps; - b2Vec2* m_p0s; - b2Vec2* m_vs; - - float* m_invMasses; - b2Vec2 m_gravity; - - b2RopeTuning m_tuning; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_settings.h b/3rdparty/box2d/include/box2d/b2_settings.h deleted file mode 100644 index 48cd95dfe2a5..000000000000 --- a/3rdparty/box2d/include/box2d/b2_settings.h +++ /dev/null @@ -1,127 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_SETTINGS_H -#define B2_SETTINGS_H - -#include "b2_types.h" -#include "b2_api.h" - -/// @file -/// Settings that can be overriden for your application -/// - -/// Define this macro in your build if you want to override settings -#ifdef B2_USER_SETTINGS - -/// This is a user file that includes custom definitions of the macros, structs, and functions -/// defined below. -#include "b2_user_settings.h" - -#else - -#include -#include - -// Tunable Constants - -/// You can use this to change the length scale used by your game. -/// For example for inches you could use 39.4. -#define b2_lengthUnitsPerMeter 1.0f - -/// The maximum number of vertices on a convex polygon. You cannot increase -/// this too much because b2BlockAllocator has a maximum object size. -#define b2_maxPolygonVertices 8 - -// User data - -/// You can define this to inject whatever data you want in b2Body -struct B2_API b2BodyUserData -{ - b2BodyUserData() - { - pointer = 0; - } - - /// For legacy compatibility - uintptr_t pointer; -}; - -/// You can define this to inject whatever data you want in b2Fixture -struct B2_API b2FixtureUserData -{ - b2FixtureUserData() - { - pointer = 0; - } - - /// For legacy compatibility - uintptr_t pointer; -}; - -/// You can define this to inject whatever data you want in b2Joint -struct B2_API b2JointUserData -{ - b2JointUserData() - { - pointer = 0; - } - - /// For legacy compatibility - uintptr_t pointer; -}; - -// Memory Allocation - -/// Default allocation functions -B2_API void* b2Alloc_Default(int32 size); -B2_API void b2Free_Default(void* mem); - -/// Implement this function to use your own memory allocator. -inline void* b2Alloc(int32 size) -{ - return b2Alloc_Default(size); -} - -/// If you implement b2Alloc, you should also implement this function. -inline void b2Free(void* mem) -{ - b2Free_Default(mem); -} - -/// Default logging function -B2_API void b2Log_Default(const char* string, va_list args); - -/// Implement this to use your own logging. -inline void b2Log(const char* string, ...) -{ - va_list args; - va_start(args, string); - b2Log_Default(string, args); - va_end(args); -} - -#endif // B2_USER_SETTINGS - -#include "b2_common.h" - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_shape.h b/3rdparty/box2d/include/box2d/b2_shape.h deleted file mode 100644 index cbed2b863358..000000000000 --- a/3rdparty/box2d/include/box2d/b2_shape.h +++ /dev/null @@ -1,110 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_SHAPE_H -#define B2_SHAPE_H - -#include "b2_api.h" -#include "b2_math.h" -#include "b2_collision.h" - -class b2BlockAllocator; - -/// This holds the mass data computed for a shape. -struct B2_API b2MassData -{ - /// The mass of the shape, usually in kilograms. - float mass; - - /// The position of the shape's centroid relative to the shape's origin. - b2Vec2 center; - - /// The rotational inertia of the shape about the local origin. - float I; -}; - -/// A shape is used for collision detection. You can create a shape however you like. -/// Shapes used for simulation in b2World are created automatically when a b2Fixture -/// is created. Shapes may encapsulate a one or more child shapes. -class B2_API b2Shape -{ -public: - - enum Type - { - e_circle = 0, - e_edge = 1, - e_polygon = 2, - e_chain = 3, - e_typeCount = 4 - }; - - virtual ~b2Shape() {} - - /// Clone the concrete shape using the provided allocator. - virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0; - - /// Get the type of this shape. You can use this to down cast to the concrete shape. - /// @return the shape type. - Type GetType() const; - - /// Get the number of child primitives. - virtual int32 GetChildCount() const = 0; - - /// Test a point for containment in this shape. This only works for convex shapes. - /// @param xf the shape world transform. - /// @param p a point in world coordinates. - virtual bool TestPoint(const b2Transform& xf, const b2Vec2& p) const = 0; - - /// Cast a ray against a child shape. - /// @param output the ray-cast results. - /// @param input the ray-cast input parameters. - /// @param transform the transform to be applied to the shape. - /// @param childIndex the child shape index - virtual bool RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const = 0; - - /// Given a transform, compute the associated axis aligned bounding box for a child shape. - /// @param aabb returns the axis aligned box. - /// @param xf the world transform of the shape. - /// @param childIndex the child shape - virtual void ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const = 0; - - /// Compute the mass properties of this shape using its dimensions and density. - /// The inertia tensor is computed about the local origin. - /// @param massData returns the mass data for this shape. - /// @param density the density in kilograms per meter squared. - virtual void ComputeMass(b2MassData* massData, float density) const = 0; - - Type m_type; - - /// Radius of a shape. For polygonal shapes this must be b2_polygonRadius. There is no support for - /// making rounded polygons. - float m_radius; -}; - -inline b2Shape::Type b2Shape::GetType() const -{ - return m_type; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_stack_allocator.h b/3rdparty/box2d/include/box2d/b2_stack_allocator.h deleted file mode 100644 index 1db2af5d95f3..000000000000 --- a/3rdparty/box2d/include/box2d/b2_stack_allocator.h +++ /dev/null @@ -1,65 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_STACK_ALLOCATOR_H -#define B2_STACK_ALLOCATOR_H - -#include "b2_api.h" -#include "b2_settings.h" - -const int32 b2_stackSize = 100 * 1024; // 100k -const int32 b2_maxStackEntries = 32; - -struct B2_API b2StackEntry -{ - char* data; - int32 size; - bool usedMalloc; -}; - -// This is a stack allocator used for fast per step allocations. -// You must nest allocate/free pairs. The code will assert -// if you try to interleave multiple allocate/free pairs. -class B2_API b2StackAllocator -{ -public: - b2StackAllocator(); - ~b2StackAllocator(); - - void* Allocate(int32 size); - void Free(void* p); - - int32 GetMaxAllocation() const; - -private: - - char m_data[b2_stackSize]; - int32 m_index; - - int32 m_allocation; - int32 m_maxAllocation; - - b2StackEntry m_entries[b2_maxStackEntries]; - int32 m_entryCount; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_time_of_impact.h b/3rdparty/box2d/include/box2d/b2_time_of_impact.h deleted file mode 100644 index 04d46262e4ca..000000000000 --- a/3rdparty/box2d/include/box2d/b2_time_of_impact.h +++ /dev/null @@ -1,63 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_TIME_OF_IMPACT_H -#define B2_TIME_OF_IMPACT_H - -#include "b2_api.h" -#include "b2_math.h" -#include "b2_distance.h" - -/// Input parameters for b2TimeOfImpact -struct B2_API b2TOIInput -{ - b2DistanceProxy proxyA; - b2DistanceProxy proxyB; - b2Sweep sweepA; - b2Sweep sweepB; - float tMax; // defines sweep interval [0, tMax] -}; - -/// Output parameters for b2TimeOfImpact. -struct B2_API b2TOIOutput -{ - enum State - { - e_unknown, - e_failed, - e_overlapped, - e_touching, - e_separated - }; - - State state; - float t; -}; - -/// Compute the upper bound on time before two shapes penetrate. Time is represented as -/// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate, -/// non-tunneling collisions. If you change the time interval, you should call this function -/// again. -/// Note: use b2Distance to compute the contact point and normal at the time of impact. -B2_API void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input); - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_time_step.h b/3rdparty/box2d/include/box2d/b2_time_step.h deleted file mode 100644 index 13d6292ec15c..000000000000 --- a/3rdparty/box2d/include/box2d/b2_time_step.h +++ /dev/null @@ -1,74 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -#ifndef B2_TIME_STEP_H -#define B2_TIME_STEP_H - -#include "b2_api.h" -#include "b2_math.h" - -/// Profiling data. Times are in milliseconds. -struct B2_API b2Profile -{ - float step; - float collide; - float solve; - float solveInit; - float solveVelocity; - float solvePosition; - float broadphase; - float solveTOI; -}; - -/// This is an internal structure. -struct B2_API b2TimeStep -{ - float dt; // time step - float inv_dt; // inverse time step (0 if dt == 0). - float dtRatio; // dt * inv_dt0 - int32 velocityIterations; - int32 positionIterations; - bool warmStarting; -}; - -/// This is an internal structure. -struct B2_API b2Position -{ - b2Vec2 c; - float a; -}; - -/// This is an internal structure. -struct B2_API b2Velocity -{ - b2Vec2 v; - float w; -}; - -/// Solver Data -struct B2_API b2SolverData -{ - b2TimeStep step; - b2Position* positions; - b2Velocity* velocities; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_timer.h b/3rdparty/box2d/include/box2d/b2_timer.h deleted file mode 100644 index 7893c32703bc..000000000000 --- a/3rdparty/box2d/include/box2d/b2_timer.h +++ /dev/null @@ -1,55 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_TIMER_H -#define B2_TIMER_H - -#include "b2_api.h" -#include "b2_settings.h" - -/// Timer for profiling. This has platform specific code and may -/// not work on every platform. -class B2_API b2Timer -{ -public: - - /// Constructor - b2Timer(); - - /// Reset the timer. - void Reset(); - - /// Get the time since construction or the last reset. - float GetMilliseconds() const; - -private: - -#if defined(_WIN32) - double m_start; - static double s_invFrequency; -#elif defined(__linux__) || defined (__APPLE__) - unsigned long long m_start_sec; - unsigned long long m_start_usec; -#endif -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_types.h b/3rdparty/box2d/include/box2d/b2_types.h deleted file mode 100644 index e0d4377591d6..000000000000 --- a/3rdparty/box2d/include/box2d/b2_types.h +++ /dev/null @@ -1,33 +0,0 @@ -// MIT License - -// Copyright (c) 2020 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_TYPES_H -#define B2_TYPES_H - -typedef signed char int8; -typedef signed short int16; -typedef signed int int32; -typedef unsigned char uint8; -typedef unsigned short uint16; -typedef unsigned int uint32; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_weld_joint.h b/3rdparty/box2d/include/box2d/b2_weld_joint.h deleted file mode 100644 index 38501f20ab05..000000000000 --- a/3rdparty/box2d/include/box2d/b2_weld_joint.h +++ /dev/null @@ -1,133 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_WELD_JOINT_H -#define B2_WELD_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Weld joint definition. You need to specify local anchor points -/// where they are attached and the relative body angle. The position -/// of the anchor points is important for computing the reaction torque. -struct B2_API b2WeldJointDef : public b2JointDef -{ - b2WeldJointDef() - { - type = e_weldJoint; - localAnchorA.Set(0.0f, 0.0f); - localAnchorB.Set(0.0f, 0.0f); - referenceAngle = 0.0f; - stiffness = 0.0f; - damping = 0.0f; - } - - /// Initialize the bodies, anchors, reference angle, stiffness, and damping. - /// @param bodyA the first body connected by this joint - /// @param bodyB the second body connected by this joint - /// @param anchor the point of connection in world coordinates - void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The bodyB angle minus bodyA angle in the reference state (radians). - float referenceAngle; - - /// The rotational stiffness in N*m - /// Disable softness with a value of 0 - float stiffness; - - /// The rotational damping in N*m*s - float damping; -}; - -/// A weld joint essentially glues two bodies together. A weld joint may -/// distort somewhat because the island constraint solver is approximate. -class B2_API b2WeldJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// Get the reference angle. - float GetReferenceAngle() const { return m_referenceAngle; } - - /// Set/get stiffness in N*m - void SetStiffness(float stiffness) { m_stiffness = stiffness; } - float GetStiffness() const { return m_stiffness; } - - /// Set/get damping in N*m*s - void SetDamping(float damping) { m_damping = damping; } - float GetDamping() const { return m_damping; } - - /// Dump to b2Log - void Dump() override; - -protected: - - friend class b2Joint; - - b2WeldJoint(const b2WeldJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - float m_stiffness; - float m_damping; - float m_bias; - - // Solver shared - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - float m_referenceAngle; - float m_gamma; - b2Vec3 m_impulse; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_rA; - b2Vec2 m_rB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - b2Mat33 m_mass; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_wheel_joint.h b/3rdparty/box2d/include/box2d/b2_wheel_joint.h deleted file mode 100644 index 8576adbd20ec..000000000000 --- a/3rdparty/box2d/include/box2d/b2_wheel_joint.h +++ /dev/null @@ -1,240 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_WHEEL_JOINT_H -#define B2_WHEEL_JOINT_H - -#include "b2_api.h" -#include "b2_joint.h" - -/// Wheel joint definition. This requires defining a line of -/// motion using an axis and an anchor point. The definition uses local -/// anchor points and a local axis so that the initial configuration -/// can violate the constraint slightly. The joint translation is zero -/// when the local anchor points coincide in world space. Using local -/// anchors and a local axis helps when saving and loading a game. -struct B2_API b2WheelJointDef : public b2JointDef -{ - b2WheelJointDef() - { - type = e_wheelJoint; - localAnchorA.SetZero(); - localAnchorB.SetZero(); - localAxisA.Set(1.0f, 0.0f); - enableLimit = false; - lowerTranslation = 0.0f; - upperTranslation = 0.0f; - enableMotor = false; - maxMotorTorque = 0.0f; - motorSpeed = 0.0f; - stiffness = 0.0f; - damping = 0.0f; - } - - /// Initialize the bodies, anchors, axis, and reference angle using the world - /// anchor and world axis. - void Initialize(b2Body* bodyA, b2Body* bodyB, const b2Vec2& anchor, const b2Vec2& axis); - - /// The local anchor point relative to bodyA's origin. - b2Vec2 localAnchorA; - - /// The local anchor point relative to bodyB's origin. - b2Vec2 localAnchorB; - - /// The local translation axis in bodyA. - b2Vec2 localAxisA; - - /// Enable/disable the joint limit. - bool enableLimit; - - /// The lower translation limit, usually in meters. - float lowerTranslation; - - /// The upper translation limit, usually in meters. - float upperTranslation; - - /// Enable/disable the joint motor. - bool enableMotor; - - /// The maximum motor torque, usually in N-m. - float maxMotorTorque; - - /// The desired motor speed in radians per second. - float motorSpeed; - - /// Suspension stiffness. Typically in units N/m. - float stiffness; - - /// Suspension damping. Typically in units of N*s/m. - float damping; -}; - -/// A wheel joint. This joint provides two degrees of freedom: translation -/// along an axis fixed in bodyA and rotation in the plane. In other words, it is a point to -/// line constraint with a rotational motor and a linear spring/damper. The spring/damper is -/// initialized upon creation. This joint is designed for vehicle suspensions. -class B2_API b2WheelJoint : public b2Joint -{ -public: - b2Vec2 GetAnchorA() const override; - b2Vec2 GetAnchorB() const override; - - b2Vec2 GetReactionForce(float inv_dt) const override; - float GetReactionTorque(float inv_dt) const override; - - /// The local anchor point relative to bodyA's origin. - const b2Vec2& GetLocalAnchorA() const { return m_localAnchorA; } - - /// The local anchor point relative to bodyB's origin. - const b2Vec2& GetLocalAnchorB() const { return m_localAnchorB; } - - /// The local joint axis relative to bodyA. - const b2Vec2& GetLocalAxisA() const { return m_localXAxisA; } - - /// Get the current joint translation, usually in meters. - float GetJointTranslation() const; - - /// Get the current joint linear speed, usually in meters per second. - float GetJointLinearSpeed() const; - - /// Get the current joint angle in radians. - float GetJointAngle() const; - - /// Get the current joint angular speed in radians per second. - float GetJointAngularSpeed() const; - - /// Is the joint limit enabled? - bool IsLimitEnabled() const; - - /// Enable/disable the joint translation limit. - void EnableLimit(bool flag); - - /// Get the lower joint translation limit, usually in meters. - float GetLowerLimit() const; - - /// Get the upper joint translation limit, usually in meters. - float GetUpperLimit() const; - - /// Set the joint translation limits, usually in meters. - void SetLimits(float lower, float upper); - - /// Is the joint motor enabled? - bool IsMotorEnabled() const; - - /// Enable/disable the joint motor. - void EnableMotor(bool flag); - - /// Set the motor speed, usually in radians per second. - void SetMotorSpeed(float speed); - - /// Get the motor speed, usually in radians per second. - float GetMotorSpeed() const; - - /// Set/Get the maximum motor force, usually in N-m. - void SetMaxMotorTorque(float torque); - float GetMaxMotorTorque() const; - - /// Get the current motor torque given the inverse time step, usually in N-m. - float GetMotorTorque(float inv_dt) const; - - /// Access spring stiffness - void SetStiffness(float stiffness); - float GetStiffness() const; - - /// Access damping - void SetDamping(float damping); - float GetDamping() const; - - /// Dump to b2Log - void Dump() override; - - /// - void Draw(b2Draw* draw) const override; - -protected: - - friend class b2Joint; - b2WheelJoint(const b2WheelJointDef* def); - - void InitVelocityConstraints(const b2SolverData& data) override; - void SolveVelocityConstraints(const b2SolverData& data) override; - bool SolvePositionConstraints(const b2SolverData& data) override; - - b2Vec2 m_localAnchorA; - b2Vec2 m_localAnchorB; - b2Vec2 m_localXAxisA; - b2Vec2 m_localYAxisA; - - float m_impulse; - float m_motorImpulse; - float m_springImpulse; - - float m_lowerImpulse; - float m_upperImpulse; - float m_translation; - float m_lowerTranslation; - float m_upperTranslation; - - float m_maxMotorTorque; - float m_motorSpeed; - - bool m_enableLimit; - bool m_enableMotor; - - float m_stiffness; - float m_damping; - - // Solver temp - int32 m_indexA; - int32 m_indexB; - b2Vec2 m_localCenterA; - b2Vec2 m_localCenterB; - float m_invMassA; - float m_invMassB; - float m_invIA; - float m_invIB; - - b2Vec2 m_ax, m_ay; - float m_sAx, m_sBx; - float m_sAy, m_sBy; - - float m_mass; - float m_motorMass; - float m_axialMass; - float m_springMass; - - float m_bias; - float m_gamma; - -}; - -inline float b2WheelJoint::GetMotorSpeed() const -{ - return m_motorSpeed; -} - -inline float b2WheelJoint::GetMaxMotorTorque() const -{ - return m_maxMotorTorque; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_world.h b/3rdparty/box2d/include/box2d/b2_world.h deleted file mode 100644 index afd73bd4657a..000000000000 --- a/3rdparty/box2d/include/box2d/b2_world.h +++ /dev/null @@ -1,348 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_WORLD_H -#define B2_WORLD_H - -#include "b2_api.h" -#include "b2_block_allocator.h" -#include "b2_contact_manager.h" -#include "b2_math.h" -#include "b2_stack_allocator.h" -#include "b2_time_step.h" -#include "b2_world_callbacks.h" - -struct b2AABB; -struct b2BodyDef; -struct b2Color; -struct b2JointDef; -class b2Body; -class b2Draw; -class b2Fixture; -class b2Joint; - -/// The world class manages all physics entities, dynamic simulation, -/// and asynchronous queries. The world also contains efficient memory -/// management facilities. -class B2_API b2World -{ -public: - /// Construct a world object. - /// @param gravity the world gravity vector. - b2World(const b2Vec2& gravity); - - /// Destruct the world. All physics entities are destroyed and all heap memory is released. - ~b2World(); - - /// Register a destruction listener. The listener is owned by you and must - /// remain in scope. - void SetDestructionListener(b2DestructionListener* listener); - - /// Register a contact filter to provide specific control over collision. - /// Otherwise the default filter is used (b2_defaultFilter). The listener is - /// owned by you and must remain in scope. - void SetContactFilter(b2ContactFilter* filter); - - /// Register a contact event listener. The listener is owned by you and must - /// remain in scope. - void SetContactListener(b2ContactListener* listener); - - /// Register a routine for debug drawing. The debug draw functions are called - /// inside with b2World::DebugDraw method. The debug draw object is owned - /// by you and must remain in scope. - void SetDebugDraw(b2Draw* debugDraw); - - /// Create a rigid body given a definition. No reference to the definition - /// is retained. - /// @warning This function is locked during callbacks. - b2Body* CreateBody(const b2BodyDef* def); - - /// Destroy a rigid body given a definition. No reference to the definition - /// is retained. This function is locked during callbacks. - /// @warning This automatically deletes all associated shapes and joints. - /// @warning This function is locked during callbacks. - void DestroyBody(b2Body* body); - - /// Create a joint to constrain bodies together. No reference to the definition - /// is retained. This may cause the connected bodies to cease colliding. - /// @warning This function is locked during callbacks. - b2Joint* CreateJoint(const b2JointDef* def); - - /// Destroy a joint. This may cause the connected bodies to begin colliding. - /// @warning This function is locked during callbacks. - void DestroyJoint(b2Joint* joint); - - /// Take a time step. This performs collision detection, integration, - /// and constraint solution. - /// @param timeStep the amount of time to simulate, this should not vary. - /// @param velocityIterations for the velocity constraint solver. - /// @param positionIterations for the position constraint solver. - void Step( float timeStep, - int32 velocityIterations, - int32 positionIterations); - - /// Manually clear the force buffer on all bodies. By default, forces are cleared automatically - /// after each call to Step. The default behavior is modified by calling SetAutoClearForces. - /// The purpose of this function is to support sub-stepping. Sub-stepping is often used to maintain - /// a fixed sized time step under a variable frame-rate. - /// When you perform sub-stepping you will disable auto clearing of forces and instead call - /// ClearForces after all sub-steps are complete in one pass of your game loop. - /// @see SetAutoClearForces - void ClearForces(); - - /// Call this to draw shapes and other debug draw data. This is intentionally non-const. - void DebugDraw(); - - /// Query the world for all fixtures that potentially overlap the - /// provided AABB. - /// @param callback a user implemented callback class. - /// @param aabb the query box. - void QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const; - - /// Ray-cast the world for all fixtures in the path of the ray. Your callback - /// controls whether you get the closest point, any point, or n-points. - /// The ray-cast ignores shapes that contain the starting point. - /// @param callback a user implemented callback class. - /// @param point1 the ray starting point - /// @param point2 the ray ending point - void RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const; - - /// Get the world body list. With the returned body, use b2Body::GetNext to get - /// the next body in the world list. A nullptr body indicates the end of the list. - /// @return the head of the world body list. - b2Body* GetBodyList(); - const b2Body* GetBodyList() const; - - /// Get the world joint list. With the returned joint, use b2Joint::GetNext to get - /// the next joint in the world list. A nullptr joint indicates the end of the list. - /// @return the head of the world joint list. - b2Joint* GetJointList(); - const b2Joint* GetJointList() const; - - /// Get the world contact list. With the returned contact, use b2Contact::GetNext to get - /// the next contact in the world list. A nullptr contact indicates the end of the list. - /// @return the head of the world contact list. - /// @warning contacts are created and destroyed in the middle of a time step. - /// Use b2ContactListener to avoid missing contacts. - b2Contact* GetContactList(); - const b2Contact* GetContactList() const; - - /// Enable/disable sleep. - void SetAllowSleeping(bool flag); - bool GetAllowSleeping() const { return m_allowSleep; } - - /// Enable/disable warm starting. For testing. - void SetWarmStarting(bool flag) { m_warmStarting = flag; } - bool GetWarmStarting() const { return m_warmStarting; } - - /// Enable/disable continuous physics. For testing. - void SetContinuousPhysics(bool flag) { m_continuousPhysics = flag; } - bool GetContinuousPhysics() const { return m_continuousPhysics; } - - /// Enable/disable single stepped continuous physics. For testing. - void SetSubStepping(bool flag) { m_subStepping = flag; } - bool GetSubStepping() const { return m_subStepping; } - - /// Get the number of broad-phase proxies. - int32 GetProxyCount() const; - - /// Get the number of bodies. - int32 GetBodyCount() const; - - /// Get the number of joints. - int32 GetJointCount() const; - - /// Get the number of contacts (each may have 0 or more contact points). - int32 GetContactCount() const; - - /// Get the height of the dynamic tree. - int32 GetTreeHeight() const; - - /// Get the balance of the dynamic tree. - int32 GetTreeBalance() const; - - /// Get the quality metric of the dynamic tree. The smaller the better. - /// The minimum is 1. - float GetTreeQuality() const; - - /// Change the global gravity vector. - void SetGravity(const b2Vec2& gravity); - - /// Get the global gravity vector. - b2Vec2 GetGravity() const; - - /// Is the world locked (in the middle of a time step). - bool IsLocked() const; - - /// Set flag to control automatic clearing of forces after each time step. - void SetAutoClearForces(bool flag); - - /// Get the flag that controls automatic clearing of forces after each time step. - bool GetAutoClearForces() const; - - /// Shift the world origin. Useful for large worlds. - /// The body shift formula is: position -= newOrigin - /// @param newOrigin the new origin with respect to the old origin - void ShiftOrigin(const b2Vec2& newOrigin); - - /// Get the contact manager for testing. - const b2ContactManager& GetContactManager() const; - - /// Get the current profile. - const b2Profile& GetProfile() const; - - /// Dump the world into the log file. - /// @warning this should be called outside of a time step. - void Dump(); - -private: - - friend class b2Body; - friend class b2Fixture; - friend class b2ContactManager; - friend class b2Controller; - - b2World(const b2World&) = delete; - void operator=(const b2World&) = delete; - - void Solve(const b2TimeStep& step); - void SolveTOI(const b2TimeStep& step); - - void DrawShape(b2Fixture* shape, const b2Transform& xf, const b2Color& color); - - b2BlockAllocator m_blockAllocator; - b2StackAllocator m_stackAllocator; - - b2ContactManager m_contactManager; - - b2Body* m_bodyList; - b2Joint* m_jointList; - - int32 m_bodyCount; - int32 m_jointCount; - - b2Vec2 m_gravity; - bool m_allowSleep; - - b2DestructionListener* m_destructionListener; - b2Draw* m_debugDraw; - - // This is used to compute the time step ratio to - // support a variable time step. - float m_inv_dt0; - - bool m_newContacts; - bool m_locked; - bool m_clearForces; - - // These are for debugging the solver. - bool m_warmStarting; - bool m_continuousPhysics; - bool m_subStepping; - - bool m_stepComplete; - - b2Profile m_profile; -}; - -inline b2Body* b2World::GetBodyList() -{ - return m_bodyList; -} - -inline const b2Body* b2World::GetBodyList() const -{ - return m_bodyList; -} - -inline b2Joint* b2World::GetJointList() -{ - return m_jointList; -} - -inline const b2Joint* b2World::GetJointList() const -{ - return m_jointList; -} - -inline b2Contact* b2World::GetContactList() -{ - return m_contactManager.m_contactList; -} - -inline const b2Contact* b2World::GetContactList() const -{ - return m_contactManager.m_contactList; -} - -inline int32 b2World::GetBodyCount() const -{ - return m_bodyCount; -} - -inline int32 b2World::GetJointCount() const -{ - return m_jointCount; -} - -inline int32 b2World::GetContactCount() const -{ - return m_contactManager.m_contactCount; -} - -inline void b2World::SetGravity(const b2Vec2& gravity) -{ - m_gravity = gravity; -} - -inline b2Vec2 b2World::GetGravity() const -{ - return m_gravity; -} - -inline bool b2World::IsLocked() const -{ - return m_locked; -} - -inline void b2World::SetAutoClearForces(bool flag) -{ - m_clearForces = flag; -} - -/// Get the flag that controls automatic clearing of forces after each time step. -inline bool b2World::GetAutoClearForces() const -{ - return m_clearForces; -} - -inline const b2ContactManager& b2World::GetContactManager() const -{ - return m_contactManager; -} - -inline const b2Profile& b2World::GetProfile() const -{ - return m_profile; -} - -#endif diff --git a/3rdparty/box2d/include/box2d/b2_world_callbacks.h b/3rdparty/box2d/include/box2d/b2_world_callbacks.h deleted file mode 100644 index da45640e2f08..000000000000 --- a/3rdparty/box2d/include/box2d/b2_world_callbacks.h +++ /dev/null @@ -1,161 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_WORLD_CALLBACKS_H -#define B2_WORLD_CALLBACKS_H - -#include "b2_api.h" -#include "b2_settings.h" - -struct b2Vec2; -struct b2Transform; -class b2Fixture; -class b2Body; -class b2Joint; -class b2Contact; -struct b2ContactResult; -struct b2Manifold; - -/// Joints and fixtures are destroyed when their associated -/// body is destroyed. Implement this listener so that you -/// may nullify references to these joints and shapes. -class B2_API b2DestructionListener -{ -public: - virtual ~b2DestructionListener() {} - - /// Called when any joint is about to be destroyed due - /// to the destruction of one of its attached bodies. - virtual void SayGoodbye(b2Joint* joint) = 0; - - /// Called when any fixture is about to be destroyed due - /// to the destruction of its parent body. - virtual void SayGoodbye(b2Fixture* fixture) = 0; -}; - -/// Implement this class to provide collision filtering. In other words, you can implement -/// this class if you want finer control over contact creation. -class B2_API b2ContactFilter -{ -public: - virtual ~b2ContactFilter() {} - - /// Return true if contact calculations should be performed between these two shapes. - /// @warning for performance reasons this is only called when the AABBs begin to overlap. - virtual bool ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB); -}; - -/// Contact impulses for reporting. Impulses are used instead of forces because -/// sub-step forces may approach infinity for rigid body collisions. These -/// match up one-to-one with the contact points in b2Manifold. -struct B2_API b2ContactImpulse -{ - float normalImpulses[b2_maxManifoldPoints]; - float tangentImpulses[b2_maxManifoldPoints]; - int32 count; -}; - -/// Implement this class to get contact information. You can use these results for -/// things like sounds and game logic. You can also get contact results by -/// traversing the contact lists after the time step. However, you might miss -/// some contacts because continuous physics leads to sub-stepping. -/// Additionally you may receive multiple callbacks for the same contact in a -/// single time step. -/// You should strive to make your callbacks efficient because there may be -/// many callbacks per time step. -/// @warning You cannot create/destroy Box2D entities inside these callbacks. -class B2_API b2ContactListener -{ -public: - virtual ~b2ContactListener() {} - - /// Called when two fixtures begin to touch. - virtual void BeginContact(b2Contact* contact) { B2_NOT_USED(contact); } - - /// Called when two fixtures cease to touch. - virtual void EndContact(b2Contact* contact) { B2_NOT_USED(contact); } - - /// This is called after a contact is updated. This allows you to inspect a - /// contact before it goes to the solver. If you are careful, you can modify the - /// contact manifold (e.g. disable contact). - /// A copy of the old manifold is provided so that you can detect changes. - /// Note: this is called only for awake bodies. - /// Note: this is called even when the number of contact points is zero. - /// Note: this is not called for sensors. - /// Note: if you set the number of contact points to zero, you will not - /// get an EndContact callback. However, you may get a BeginContact callback - /// the next step. - virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) - { - B2_NOT_USED(contact); - B2_NOT_USED(oldManifold); - } - - /// This lets you inspect a contact after the solver is finished. This is useful - /// for inspecting impulses. - /// Note: the contact manifold does not include time of impact impulses, which can be - /// arbitrarily large if the sub-step is small. Hence the impulse is provided explicitly - /// in a separate data structure. - /// Note: this is only called for contacts that are touching, solid, and awake. - virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) - { - B2_NOT_USED(contact); - B2_NOT_USED(impulse); - } -}; - -/// Callback class for AABB queries. -/// See b2World::Query -class B2_API b2QueryCallback -{ -public: - virtual ~b2QueryCallback() {} - - /// Called for each fixture found in the query AABB. - /// @return false to terminate the query. - virtual bool ReportFixture(b2Fixture* fixture) = 0; -}; - -/// Callback class for ray casts. -/// See b2World::RayCast -class B2_API b2RayCastCallback -{ -public: - virtual ~b2RayCastCallback() {} - - /// Called for each fixture found in the query. You control how the ray cast - /// proceeds by returning a float: - /// return -1: ignore this fixture and continue - /// return 0: terminate the ray cast - /// return fraction: clip the ray to this point - /// return 1: don't clip the ray and continue - /// @param fixture the fixture hit by the ray - /// @param point the point of initial intersection - /// @param normal the normal vector at the point of intersection - /// @param fraction the fraction along the ray at the point of intersection - /// @return -1 to filter, 0 to terminate, fraction to clip the ray for - /// closest hit, 1 to continue - virtual float ReportFixture( b2Fixture* fixture, const b2Vec2& point, - const b2Vec2& normal, float fraction) = 0; -}; - -#endif diff --git a/3rdparty/box2d/include/box2d/base.h b/3rdparty/box2d/include/box2d/base.h new file mode 100644 index 000000000000..2af347a36399 --- /dev/null +++ b/3rdparty/box2d/include/box2d/base.h @@ -0,0 +1,131 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include + +// clang-format off +// +// Shared library macros +#if defined( _MSC_VER ) && defined( box2d_EXPORTS ) + // build the Windows DLL + #define BOX2D_EXPORT __declspec( dllexport ) +#elif defined( _MSC_VER ) && defined( BOX2D_DLL ) + // using the Windows DLL + #define BOX2D_EXPORT __declspec( dllimport ) +#elif defined( box2d_EXPORTS ) + // building or using the shared library + #define BOX2D_EXPORT __attribute__( ( visibility( "default" ) ) ) +#else + // static library + #define BOX2D_EXPORT +#endif + +// C++ macros +#ifdef __cplusplus + #define B2_API extern "C" BOX2D_EXPORT + #define B2_INLINE inline + #define B2_LITERAL(T) T + #define B2_ZERO_INIT {} +#else + #define B2_API BOX2D_EXPORT + #define B2_INLINE static inline + /// Used for C literals like (b2Vec2){1.0f, 2.0f} where C++ requires b2Vec2{1.0f, 2.0f} + #define B2_LITERAL(T) (T) + #define B2_ZERO_INIT {0} +#endif +// clang-format on + +/** + * @defgroup base Base + * Base functionality + * @{ + */ + +/// Prototype for user allocation function +/// @param size the allocation size in bytes +/// @param alignment the required alignment, guaranteed to be a power of 2 +typedef void* b2AllocFcn( unsigned int size, int alignment ); + +/// Prototype for user free function +/// @param mem the memory previously allocated through `b2AllocFcn` +typedef void b2FreeFcn( void* mem ); + +/// Prototype for the user assert callback. Return 0 to skip the debugger break. +typedef int b2AssertFcn( const char* condition, const char* fileName, int lineNumber ); + +/// This allows the user to override the allocation functions. These should be +/// set during application startup. +B2_API void b2SetAllocator( b2AllocFcn* allocFcn, b2FreeFcn* freeFcn ); + +/// @return the total bytes allocated by Box2D +B2_API int b2GetByteCount( void ); + +/// Override the default assert callback +/// @param assertFcn a non-null assert callback +B2_API void b2SetAssertFcn( b2AssertFcn* assertFcn ); + +/// Version numbering scheme. +/// See https://semver.org/ +typedef struct b2Version +{ + /// Significant changes + int major; + + /// Incremental changes + int minor; + + /// Bug fixes + int revision; +} b2Version; + +/// Get the current version of Box2D +B2_API b2Version b2GetVersion( void ); + +/**@}*/ + +//! @cond + +// see https://github.com/scottt/debugbreak +#if defined( _MSC_VER ) +#define B2_BREAKPOINT __debugbreak() +#elif defined( __GNUC__ ) || defined( __clang__ ) +#define B2_BREAKPOINT __builtin_trap() +#else +// Unknown compiler +#include +#define B2_BREAKPOINT assert( 0 ) +#endif + +#if !defined( NDEBUG ) || defined( B2_ENABLE_ASSERT ) +B2_API int b2InternalAssertFcn( const char* condition, const char* fileName, int lineNumber ); +#define B2_ASSERT( condition ) \ + do \ + { \ + if ( !( condition ) && b2InternalAssertFcn( #condition, __FILE__, (int)__LINE__ ) ) \ + B2_BREAKPOINT; \ + } \ + while ( 0 ) +#else +#define B2_ASSERT( ... ) ( (void)0 ) +#endif + +/// Get the absolute number of system ticks. The value is platform specific. +B2_API uint64_t b2GetTicks( void ); + +/// Get the milliseconds passed from an initial tick value. +B2_API float b2GetMilliseconds( uint64_t ticks ); + +/// Get the milliseconds passed from an initial tick value. Resets the passed in +/// value to the current tick value. +B2_API float b2GetMillisecondsAndReset( uint64_t* ticks ); + +/// Yield to be used in a busy loop. +B2_API void b2Yield( void ); + +/// Simple djb2 hash function for determinism testing +#define B2_HASH_INIT 5381 +B2_API uint32_t b2Hash( uint32_t hash, const uint8_t* data, int count ); + +//! @endcond diff --git a/3rdparty/box2d/include/box2d/box2d.h b/3rdparty/box2d/include/box2d/box2d.h index 55c695822c71..61c67238e632 100644 --- a/3rdparty/box2d/include/box2d/box2d.h +++ b/3rdparty/box2d/include/box2d/box2d.h @@ -1,58 +1,1222 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef BOX2D_H -#define BOX2D_H - -// These include files constitute the main Box2D API - -#include "b2_settings.h" -#include "b2_draw.h" -#include "b2_timer.h" - -#include "b2_chain_shape.h" -#include "b2_circle_shape.h" -#include "b2_edge_shape.h" -#include "b2_polygon_shape.h" - -#include "b2_broad_phase.h" -#include "b2_dynamic_tree.h" - -#include "b2_body.h" -#include "b2_contact.h" -#include "b2_fixture.h" -#include "b2_time_step.h" -#include "b2_world.h" -#include "b2_world_callbacks.h" - -#include "b2_distance_joint.h" -#include "b2_friction_joint.h" -#include "b2_gear_joint.h" -#include "b2_motor_joint.h" -#include "b2_mouse_joint.h" -#include "b2_prismatic_joint.h" -#include "b2_pulley_joint.h" -#include "b2_revolute_joint.h" -#include "b2_weld_joint.h" -#include "b2_wheel_joint.h" - -#endif +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "base.h" +#include "collision.h" +#include "id.h" +#include "types.h" + +#include + +/** + * @defgroup world World + * These functions allow you to create a simulation world. + * + * You can add rigid bodies and joint constraints to the world and run the simulation. You can get contact + * information to get contact points and normals as well as events. You can query to world, checking for overlaps and casting rays + * or shapes. There is also debugging information such as debug draw, timing information, and counters. You can find documentation + * here: https://box2d.org/ + * @{ + */ + +/// Create a world for rigid body simulation. A world contains bodies, shapes, and constraints. You make create +/// up to 128 worlds. Each world is completely independent and may be simulated in parallel. +/// @return the world id. +B2_API b2WorldId b2CreateWorld( const b2WorldDef* def ); + +/// Destroy a world +B2_API void b2DestroyWorld( b2WorldId worldId ); + +/// World id validation. Provides validation for up to 64K allocations. +B2_API bool b2World_IsValid( b2WorldId id ); + +/// Simulate a world for one time step. This performs collision detection, integration, and constraint solution. +/// @param worldId The world to simulate +/// @param timeStep The amount of time to simulate, this should be a fixed number. Usually 1/60. +/// @param subStepCount The number of sub-steps, increasing the sub-step count can increase accuracy. Usually 4. +B2_API void b2World_Step( b2WorldId worldId, float timeStep, int subStepCount ); + +/// Call this to draw shapes and other debug draw data +B2_API void b2World_Draw( b2WorldId worldId, b2DebugDraw* draw ); + +/// Get the body events for the current time step. The event data is transient. Do not store a reference to this data. +B2_API b2BodyEvents b2World_GetBodyEvents( b2WorldId worldId ); + +/// Get sensor events for the current time step. The event data is transient. Do not store a reference to this data. +B2_API b2SensorEvents b2World_GetSensorEvents( b2WorldId worldId ); + +/// Get contact events for this current time step. The event data is transient. Do not store a reference to this data. +B2_API b2ContactEvents b2World_GetContactEvents( b2WorldId worldId ); + +/// Overlap test for all shapes that *potentially* overlap the provided AABB +B2_API b2TreeStats b2World_OverlapAABB( b2WorldId worldId, b2AABB aabb, b2QueryFilter filter, b2OverlapResultFcn* fcn, + void* context ); + +/// Overlap test for all shapes that overlap the provided shape proxy. +B2_API b2TreeStats b2World_OverlapShape( b2WorldId worldId, const b2ShapeProxy* proxy, b2QueryFilter filter, + b2OverlapResultFcn* fcn, void* context ); + +/// Cast a ray into the world to collect shapes in the path of the ray. +/// Your callback function controls whether you get the closest point, any point, or n-points. +/// The ray-cast ignores shapes that contain the starting point. +/// @note The callback function may receive shapes in any order +/// @param worldId The world to cast the ray against +/// @param origin The start point of the ray +/// @param translation The translation of the ray from the start point to the end point +/// @param filter Contains bit flags to filter unwanted shapes from the results +/// @param fcn A user implemented callback function +/// @param context A user context that is passed along to the callback function +/// @return traversal performance counters +B2_API b2TreeStats b2World_CastRay( b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter, + b2CastResultFcn* fcn, void* context ); + +/// Cast a ray into the world to collect the closest hit. This is a convenience function. +/// This is less general than b2World_CastRay() and does not allow for custom filtering. +B2_API b2RayResult b2World_CastRayClosest( b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter ); + +/// Cast a shape through the world. Similar to a cast ray except that a shape is cast instead of a point. +/// @see b2World_CastRay +B2_API b2TreeStats b2World_CastShape( b2WorldId worldId, const b2ShapeProxy* proxy, b2Vec2 translation, b2QueryFilter filter, + b2CastResultFcn* fcn, void* context ); + +/// Cast a capsule mover through the world. This is a special shape cast that handles sliding along other shapes while reducing +/// clipping. +B2_API float b2World_CastMover( b2WorldId worldId, const b2Capsule* mover, b2Vec2 translation, b2QueryFilter filter ); + +/// Collide a capsule mover with the world, gathering collision planes that can be fed to b2SolvePlanes. Useful for +/// kinematic character movement. +B2_API void b2World_CollideMover( b2WorldId worldId, const b2Capsule* mover, b2QueryFilter filter, b2PlaneResultFcn* fcn, + void* context ); + +/// Enable/disable sleep. If your application does not need sleeping, you can gain some performance +/// by disabling sleep completely at the world level. +/// @see b2WorldDef +B2_API void b2World_EnableSleeping( b2WorldId worldId, bool flag ); + +/// Is body sleeping enabled? +B2_API bool b2World_IsSleepingEnabled( b2WorldId worldId ); + +/// Enable/disable continuous collision between dynamic and static bodies. Generally you should keep continuous +/// collision enabled to prevent fast moving objects from going through static objects. The performance gain from +/// disabling continuous collision is minor. +/// @see b2WorldDef +B2_API void b2World_EnableContinuous( b2WorldId worldId, bool flag ); + +/// Is continuous collision enabled? +B2_API bool b2World_IsContinuousEnabled( b2WorldId worldId ); + +/// Adjust the restitution threshold. It is recommended not to make this value very small +/// because it will prevent bodies from sleeping. Usually in meters per second. +/// @see b2WorldDef +B2_API void b2World_SetRestitutionThreshold( b2WorldId worldId, float value ); + +/// Get the the restitution speed threshold. Usually in meters per second. +B2_API float b2World_GetRestitutionThreshold( b2WorldId worldId ); + +/// Adjust the hit event threshold. This controls the collision speed needed to generate a b2ContactHitEvent. +/// Usually in meters per second. +/// @see b2WorldDef::hitEventThreshold +B2_API void b2World_SetHitEventThreshold( b2WorldId worldId, float value ); + +/// Get the the hit event speed threshold. Usually in meters per second. +B2_API float b2World_GetHitEventThreshold( b2WorldId worldId ); + +/// Register the custom filter callback. This is optional. +B2_API void b2World_SetCustomFilterCallback( b2WorldId worldId, b2CustomFilterFcn* fcn, void* context ); + +/// Register the pre-solve callback. This is optional. +B2_API void b2World_SetPreSolveCallback( b2WorldId worldId, b2PreSolveFcn* fcn, void* context ); + +/// Set the gravity vector for the entire world. Box2D has no concept of an up direction and this +/// is left as a decision for the application. Usually in m/s^2. +/// @see b2WorldDef +B2_API void b2World_SetGravity( b2WorldId worldId, b2Vec2 gravity ); + +/// Get the gravity vector +B2_API b2Vec2 b2World_GetGravity( b2WorldId worldId ); + +/// Apply a radial explosion +/// @param worldId The world id +/// @param explosionDef The explosion definition +B2_API void b2World_Explode( b2WorldId worldId, const b2ExplosionDef* explosionDef ); + +/// Adjust contact tuning parameters +/// @param worldId The world id +/// @param hertz The contact stiffness (cycles per second) +/// @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) +/// @param pushSpeed The maximum contact constraint push out speed (meters per second) +/// @note Advanced feature +B2_API void b2World_SetContactTuning( b2WorldId worldId, float hertz, float dampingRatio, float pushSpeed ); + +/// Adjust joint tuning parameters +/// @param worldId The world id +/// @param hertz The contact stiffness (cycles per second) +/// @param dampingRatio The contact bounciness with 1 being critical damping (non-dimensional) +/// @note Advanced feature +B2_API void b2World_SetJointTuning( b2WorldId worldId, float hertz, float dampingRatio ); + +/// Set the maximum linear speed. Usually in m/s. +B2_API void b2World_SetMaximumLinearSpeed( b2WorldId worldId, float maximumLinearSpeed ); + +/// Get the maximum linear speed. Usually in m/s. +B2_API float b2World_GetMaximumLinearSpeed( b2WorldId worldId ); + +/// Enable/disable constraint warm starting. Advanced feature for testing. Disabling +/// warm starting greatly reduces stability and provides no performance gain. +B2_API void b2World_EnableWarmStarting( b2WorldId worldId, bool flag ); + +/// Is constraint warm starting enabled? +B2_API bool b2World_IsWarmStartingEnabled( b2WorldId worldId ); + +/// Get the number of awake bodies. +B2_API int b2World_GetAwakeBodyCount( b2WorldId worldId ); + +/// Get the current world performance profile +B2_API b2Profile b2World_GetProfile( b2WorldId worldId ); + +/// Get world counters and sizes +B2_API b2Counters b2World_GetCounters( b2WorldId worldId ); + +/// Set the user data pointer. +B2_API void b2World_SetUserData( b2WorldId worldId, void* userData ); + +/// Get the user data pointer. +B2_API void* b2World_GetUserData( b2WorldId worldId ); + +/// Set the friction callback. Passing NULL resets to default. +B2_API void b2World_SetFrictionCallback( b2WorldId worldId, b2FrictionCallback* callback ); + +/// Set the restitution callback. Passing NULL resets to default. +B2_API void b2World_SetRestitutionCallback( b2WorldId worldId, b2RestitutionCallback* callback ); + +/// Dump memory stats to box2d_memory.txt +B2_API void b2World_DumpMemoryStats( b2WorldId worldId ); + +/// This is for internal testing +B2_API void b2World_RebuildStaticTree( b2WorldId worldId ); + +/// This is for internal testing +B2_API void b2World_EnableSpeculative( b2WorldId worldId, bool flag ); + +/** @} */ + +/** + * @defgroup body Body + * This is the body API. + * @{ + */ + +/// Create a rigid body given a definition. No reference to the definition is retained. So you can create the definition +/// on the stack and pass it as a pointer. +/// @code{.c} +/// b2BodyDef bodyDef = b2DefaultBodyDef(); +/// b2BodyId myBodyId = b2CreateBody(myWorldId, &bodyDef); +/// @endcode +/// @warning This function is locked during callbacks. +B2_API b2BodyId b2CreateBody( b2WorldId worldId, const b2BodyDef* def ); + +/// Destroy a rigid body given an id. This destroys all shapes and joints attached to the body. +/// Do not keep references to the associated shapes and joints. +B2_API void b2DestroyBody( b2BodyId bodyId ); + +/// Body identifier validation. Can be used to detect orphaned ids. Provides validation for up to 64K allocations. +B2_API bool b2Body_IsValid( b2BodyId id ); + +/// Get the body type: static, kinematic, or dynamic +B2_API b2BodyType b2Body_GetType( b2BodyId bodyId ); + +/// Change the body type. This is an expensive operation. This automatically updates the mass +/// properties regardless of the automatic mass setting. +B2_API void b2Body_SetType( b2BodyId bodyId, b2BodyType type ); + +/// Set the body name. Up to 31 characters excluding 0 termination. +B2_API void b2Body_SetName( b2BodyId bodyId, const char* name ); + +/// Get the body name. May be null. +B2_API const char* b2Body_GetName( b2BodyId bodyId ); + +/// Set the user data for a body +B2_API void b2Body_SetUserData( b2BodyId bodyId, void* userData ); + +/// Get the user data stored in a body +B2_API void* b2Body_GetUserData( b2BodyId bodyId ); + +/// Get the world position of a body. This is the location of the body origin. +B2_API b2Vec2 b2Body_GetPosition( b2BodyId bodyId ); + +/// Get the world rotation of a body as a cosine/sine pair (complex number) +B2_API b2Rot b2Body_GetRotation( b2BodyId bodyId ); + +/// Get the world transform of a body. +B2_API b2Transform b2Body_GetTransform( b2BodyId bodyId ); + +/// Set the world transform of a body. This acts as a teleport and is fairly expensive. +/// @note Generally you should create a body with then intended transform. +/// @see b2BodyDef::position and b2BodyDef::angle +B2_API void b2Body_SetTransform( b2BodyId bodyId, b2Vec2 position, b2Rot rotation ); + +/// Get a local point on a body given a world point +B2_API b2Vec2 b2Body_GetLocalPoint( b2BodyId bodyId, b2Vec2 worldPoint ); + +/// Get a world point on a body given a local point +B2_API b2Vec2 b2Body_GetWorldPoint( b2BodyId bodyId, b2Vec2 localPoint ); + +/// Get a local vector on a body given a world vector +B2_API b2Vec2 b2Body_GetLocalVector( b2BodyId bodyId, b2Vec2 worldVector ); + +/// Get a world vector on a body given a local vector +B2_API b2Vec2 b2Body_GetWorldVector( b2BodyId bodyId, b2Vec2 localVector ); + +/// Get the linear velocity of a body's center of mass. Usually in meters per second. +B2_API b2Vec2 b2Body_GetLinearVelocity( b2BodyId bodyId ); + +/// Get the angular velocity of a body in radians per second +B2_API float b2Body_GetAngularVelocity( b2BodyId bodyId ); + +/// Set the linear velocity of a body. Usually in meters per second. +B2_API void b2Body_SetLinearVelocity( b2BodyId bodyId, b2Vec2 linearVelocity ); + +/// Set the angular velocity of a body in radians per second +B2_API void b2Body_SetAngularVelocity( b2BodyId bodyId, float angularVelocity ); + +/// Set the velocity to reach the given transform after a given time step. +/// The result will be close but maybe not exact. This is meant for kinematic bodies. +/// This will automatically wake the body if asleep. +B2_API void b2Body_SetTargetTransform( b2BodyId bodyId, b2Transform target, float timeStep ); + +/// Get the linear velocity of a local point attached to a body. Usually in meters per second. +B2_API b2Vec2 b2Body_GetLocalPointVelocity( b2BodyId bodyId, b2Vec2 localPoint ); + +/// Get the linear velocity of a world point attached to a body. Usually in meters per second. +B2_API b2Vec2 b2Body_GetWorldPointVelocity( b2BodyId bodyId, b2Vec2 worldPoint ); + +/// Apply a force at a world point. If the force is not applied at the center of mass, +/// it will generate a torque and affect the angular velocity. This optionally wakes up the body. +/// The force is ignored if the body is not awake. +/// @param bodyId The body id +/// @param force The world force vector, usually in newtons (N) +/// @param point The world position of the point of application +/// @param wake Option to wake up the body +B2_API void b2Body_ApplyForce( b2BodyId bodyId, b2Vec2 force, b2Vec2 point, bool wake ); + +/// Apply a force to the center of mass. This optionally wakes up the body. +/// The force is ignored if the body is not awake. +/// @param bodyId The body id +/// @param force the world force vector, usually in newtons (N). +/// @param wake also wake up the body +B2_API void b2Body_ApplyForceToCenter( b2BodyId bodyId, b2Vec2 force, bool wake ); + +/// Apply a torque. This affects the angular velocity without affecting the linear velocity. +/// This optionally wakes the body. The torque is ignored if the body is not awake. +/// @param bodyId The body id +/// @param torque about the z-axis (out of the screen), usually in N*m. +/// @param wake also wake up the body +B2_API void b2Body_ApplyTorque( b2BodyId bodyId, float torque, bool wake ); + +/// Apply an impulse at a point. This immediately modifies the velocity. +/// It also modifies the angular velocity if the point of application +/// is not at the center of mass. This optionally wakes the body. +/// The impulse is ignored if the body is not awake. +/// @param bodyId The body id +/// @param impulse the world impulse vector, usually in N*s or kg*m/s. +/// @param point the world position of the point of application. +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady force, +/// use a force instead, which will work better with the sub-stepping solver. +B2_API void b2Body_ApplyLinearImpulse( b2BodyId bodyId, b2Vec2 impulse, b2Vec2 point, bool wake ); + +/// Apply an impulse to the center of mass. This immediately modifies the velocity. +/// The impulse is ignored if the body is not awake. This optionally wakes the body. +/// @param bodyId The body id +/// @param impulse the world impulse vector, usually in N*s or kg*m/s. +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady force, +/// use a force instead, which will work better with the sub-stepping solver. +B2_API void b2Body_ApplyLinearImpulseToCenter( b2BodyId bodyId, b2Vec2 impulse, bool wake ); + +/// Apply an angular impulse. The impulse is ignored if the body is not awake. +/// This optionally wakes the body. +/// @param bodyId The body id +/// @param impulse the angular impulse, usually in units of kg*m*m/s +/// @param wake also wake up the body +/// @warning This should be used for one-shot impulses. If you need a steady force, +/// use a force instead, which will work better with the sub-stepping solver. +B2_API void b2Body_ApplyAngularImpulse( b2BodyId bodyId, float impulse, bool wake ); + +/// Get the mass of the body, usually in kilograms +B2_API float b2Body_GetMass( b2BodyId bodyId ); + +/// Get the rotational inertia of the body, usually in kg*m^2 +B2_API float b2Body_GetRotationalInertia( b2BodyId bodyId ); + +/// Get the center of mass position of the body in local space +B2_API b2Vec2 b2Body_GetLocalCenterOfMass( b2BodyId bodyId ); + +/// Get the center of mass position of the body in world space +B2_API b2Vec2 b2Body_GetWorldCenterOfMass( b2BodyId bodyId ); + +/// Override the body's mass properties. Normally this is computed automatically using the +/// shape geometry and density. This information is lost if a shape is added or removed or if the +/// body type changes. +B2_API void b2Body_SetMassData( b2BodyId bodyId, b2MassData massData ); + +/// Get the mass data for a body +B2_API b2MassData b2Body_GetMassData( b2BodyId bodyId ); + +/// This update the mass properties to the sum of the mass properties of the shapes. +/// This normally does not need to be called unless you called SetMassData to override +/// the mass and you later want to reset the mass. +/// You may also use this when automatic mass computation has been disabled. +/// You should call this regardless of body type. +/// Note that sensor shapes may have mass. +B2_API void b2Body_ApplyMassFromShapes( b2BodyId bodyId ); + +/// Adjust the linear damping. Normally this is set in b2BodyDef before creation. +B2_API void b2Body_SetLinearDamping( b2BodyId bodyId, float linearDamping ); + +/// Get the current linear damping. +B2_API float b2Body_GetLinearDamping( b2BodyId bodyId ); + +/// Adjust the angular damping. Normally this is set in b2BodyDef before creation. +B2_API void b2Body_SetAngularDamping( b2BodyId bodyId, float angularDamping ); + +/// Get the current angular damping. +B2_API float b2Body_GetAngularDamping( b2BodyId bodyId ); + +/// Adjust the gravity scale. Normally this is set in b2BodyDef before creation. +/// @see b2BodyDef::gravityScale +B2_API void b2Body_SetGravityScale( b2BodyId bodyId, float gravityScale ); + +/// Get the current gravity scale +B2_API float b2Body_GetGravityScale( b2BodyId bodyId ); + +/// @return true if this body is awake +B2_API bool b2Body_IsAwake( b2BodyId bodyId ); + +/// Wake a body from sleep. This wakes the entire island the body is touching. +/// @warning Putting a body to sleep will put the entire island of bodies touching this body to sleep, +/// which can be expensive and possibly unintuitive. +B2_API void b2Body_SetAwake( b2BodyId bodyId, bool awake ); + +/// Enable or disable sleeping for this body. If sleeping is disabled the body will wake. +B2_API void b2Body_EnableSleep( b2BodyId bodyId, bool enableSleep ); + +/// Returns true if sleeping is enabled for this body +B2_API bool b2Body_IsSleepEnabled( b2BodyId bodyId ); + +/// Set the sleep threshold, usually in meters per second +B2_API void b2Body_SetSleepThreshold( b2BodyId bodyId, float sleepThreshold ); + +/// Get the sleep threshold, usually in meters per second. +B2_API float b2Body_GetSleepThreshold( b2BodyId bodyId ); + +/// Returns true if this body is enabled +B2_API bool b2Body_IsEnabled( b2BodyId bodyId ); + +/// Disable a body by removing it completely from the simulation. This is expensive. +B2_API void b2Body_Disable( b2BodyId bodyId ); + +/// Enable a body by adding it to the simulation. This is expensive. +B2_API void b2Body_Enable( b2BodyId bodyId ); + +/// Set this body to have fixed rotation. This causes the mass to be reset in all cases. +B2_API void b2Body_SetFixedRotation( b2BodyId bodyId, bool flag ); + +/// Does this body have fixed rotation? +B2_API bool b2Body_IsFixedRotation( b2BodyId bodyId ); + +/// Set this body to be a bullet. A bullet does continuous collision detection +/// against dynamic bodies (but not other bullets). +B2_API void b2Body_SetBullet( b2BodyId bodyId, bool flag ); + +/// Is this body a bullet? +B2_API bool b2Body_IsBullet( b2BodyId bodyId ); + +/// Enable/disable contact events on all shapes. +/// @see b2ShapeDef::enableContactEvents +/// @warning changing this at runtime may cause mismatched begin/end touch events +B2_API void b2Body_EnableContactEvents( b2BodyId bodyId, bool flag ); + +/// Enable/disable hit events on all shapes +/// @see b2ShapeDef::enableHitEvents +B2_API void b2Body_EnableHitEvents( b2BodyId bodyId, bool flag ); + +/// Get the world that owns this body +B2_API b2WorldId b2Body_GetWorld( b2BodyId bodyId ); + +/// Get the number of shapes on this body +B2_API int b2Body_GetShapeCount( b2BodyId bodyId ); + +/// Get the shape ids for all shapes on this body, up to the provided capacity. +/// @returns the number of shape ids stored in the user array +B2_API int b2Body_GetShapes( b2BodyId bodyId, b2ShapeId* shapeArray, int capacity ); + +/// Get the number of joints on this body +B2_API int b2Body_GetJointCount( b2BodyId bodyId ); + +/// Get the joint ids for all joints on this body, up to the provided capacity +/// @returns the number of joint ids stored in the user array +B2_API int b2Body_GetJoints( b2BodyId bodyId, b2JointId* jointArray, int capacity ); + +/// Get the maximum capacity required for retrieving all the touching contacts on a body +B2_API int b2Body_GetContactCapacity( b2BodyId bodyId ); + +/// Get the touching contact data for a body. +/// @note Box2D uses speculative collision so some contact points may be separated. +/// @returns the number of elements filled in the provided array +/// @warning do not ignore the return value, it specifies the valid number of elements +B2_API int b2Body_GetContactData( b2BodyId bodyId, b2ContactData* contactData, int capacity ); + +/// Get the current world AABB that contains all the attached shapes. Note that this may not encompass the body origin. +/// If there are no shapes attached then the returned AABB is empty and centered on the body origin. +B2_API b2AABB b2Body_ComputeAABB( b2BodyId bodyId ); + +/** @} */ + +/** + * @defgroup shape Shape + * Functions to create, destroy, and access. + * Shapes bind raw geometry to bodies and hold material properties including friction and restitution. + * @{ + */ + +/// Create a circle shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +B2_API b2ShapeId b2CreateCircleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Circle* circle ); + +/// Create a line segment shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +B2_API b2ShapeId b2CreateSegmentShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Segment* segment ); + +/// Create a capsule shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +B2_API b2ShapeId b2CreateCapsuleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Capsule* capsule ); + +/// Create a polygon shape and attach it to a body. The shape definition and geometry are fully cloned. +/// Contacts are not created until the next time step. +/// @return the shape id for accessing the shape +B2_API b2ShapeId b2CreatePolygonShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Polygon* polygon ); + +/// Destroy a shape. You may defer the body mass update which can improve performance if several shapes on a +/// body are destroyed at once. +/// @see b2Body_ApplyMassFromShapes +B2_API void b2DestroyShape( b2ShapeId shapeId, bool updateBodyMass ); + +/// Shape identifier validation. Provides validation for up to 64K allocations. +B2_API bool b2Shape_IsValid( b2ShapeId id ); + +/// Get the type of a shape +B2_API b2ShapeType b2Shape_GetType( b2ShapeId shapeId ); + +/// Get the id of the body that a shape is attached to +B2_API b2BodyId b2Shape_GetBody( b2ShapeId shapeId ); + +/// Get the world that owns this shape +B2_API b2WorldId b2Shape_GetWorld( b2ShapeId shapeId ); + +/// Returns true if the shape is a sensor. It is not possible to change a shape +/// from sensor to solid dynamically because this breaks the contract for +/// sensor events. +B2_API bool b2Shape_IsSensor( b2ShapeId shapeId ); + +/// Set the user data for a shape +B2_API void b2Shape_SetUserData( b2ShapeId shapeId, void* userData ); + +/// Get the user data for a shape. This is useful when you get a shape id +/// from an event or query. +B2_API void* b2Shape_GetUserData( b2ShapeId shapeId ); + +/// Set the mass density of a shape, usually in kg/m^2. +/// This will optionally update the mass properties on the parent body. +/// @see b2ShapeDef::density, b2Body_ApplyMassFromShapes +B2_API void b2Shape_SetDensity( b2ShapeId shapeId, float density, bool updateBodyMass ); + +/// Get the density of a shape, usually in kg/m^2 +B2_API float b2Shape_GetDensity( b2ShapeId shapeId ); + +/// Set the friction on a shape +/// @see b2ShapeDef::friction +B2_API void b2Shape_SetFriction( b2ShapeId shapeId, float friction ); + +/// Get the friction of a shape +B2_API float b2Shape_GetFriction( b2ShapeId shapeId ); + +/// Set the shape restitution (bounciness) +/// @see b2ShapeDef::restitution +B2_API void b2Shape_SetRestitution( b2ShapeId shapeId, float restitution ); + +/// Get the shape restitution +B2_API float b2Shape_GetRestitution( b2ShapeId shapeId ); + +/// Set the shape material identifier +/// @see b2ShapeDef::material +B2_API void b2Shape_SetMaterial( b2ShapeId shapeId, int material ); + +/// Get the shape material identifier +B2_API int b2Shape_GetMaterial( b2ShapeId shapeId ); + +/// Get the shape filter +B2_API b2Filter b2Shape_GetFilter( b2ShapeId shapeId ); + +/// Set the current filter. This is almost as expensive as recreating the shape. This may cause +/// contacts to be immediately destroyed. However contacts are not created until the next world step. +/// Sensor overlap state is also not updated until the next world step. +/// @see b2ShapeDef::filter +B2_API void b2Shape_SetFilter( b2ShapeId shapeId, b2Filter filter ); + +/// Enable sensor events for this shape. +/// @see b2ShapeDef::enableSensorEvents +B2_API void b2Shape_EnableSensorEvents( b2ShapeId shapeId, bool flag ); + +/// Returns true if sensor events are enabled. +B2_API bool b2Shape_AreSensorEventsEnabled( b2ShapeId shapeId ); + +/// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. +/// @see b2ShapeDef::enableContactEvents +/// @warning changing this at run-time may lead to lost begin/end events +B2_API void b2Shape_EnableContactEvents( b2ShapeId shapeId, bool flag ); + +/// Returns true if contact events are enabled +B2_API bool b2Shape_AreContactEventsEnabled( b2ShapeId shapeId ); + +/// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive +/// and must be carefully handled due to multithreading. Ignored for sensors. +/// @see b2PreSolveFcn +B2_API void b2Shape_EnablePreSolveEvents( b2ShapeId shapeId, bool flag ); + +/// Returns true if pre-solve events are enabled +B2_API bool b2Shape_ArePreSolveEventsEnabled( b2ShapeId shapeId ); + +/// Enable contact hit events for this shape. Ignored for sensors. +/// @see b2WorldDef.hitEventThreshold +B2_API void b2Shape_EnableHitEvents( b2ShapeId shapeId, bool flag ); + +/// Returns true if hit events are enabled +B2_API bool b2Shape_AreHitEventsEnabled( b2ShapeId shapeId ); + +/// Test a point for overlap with a shape +B2_API bool b2Shape_TestPoint( b2ShapeId shapeId, b2Vec2 point ); + +/// Ray cast a shape directly +B2_API b2CastOutput b2Shape_RayCast( b2ShapeId shapeId, const b2RayCastInput* input ); + +/// Get a copy of the shape's circle. Asserts the type is correct. +B2_API b2Circle b2Shape_GetCircle( b2ShapeId shapeId ); + +/// Get a copy of the shape's line segment. Asserts the type is correct. +B2_API b2Segment b2Shape_GetSegment( b2ShapeId shapeId ); + +/// Get a copy of the shape's chain segment. These come from chain shapes. +/// Asserts the type is correct. +B2_API b2ChainSegment b2Shape_GetChainSegment( b2ShapeId shapeId ); + +/// Get a copy of the shape's capsule. Asserts the type is correct. +B2_API b2Capsule b2Shape_GetCapsule( b2ShapeId shapeId ); + +/// Get a copy of the shape's convex polygon. Asserts the type is correct. +B2_API b2Polygon b2Shape_GetPolygon( b2ShapeId shapeId ); + +/// Allows you to change a shape to be a circle or update the current circle. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +B2_API void b2Shape_SetCircle( b2ShapeId shapeId, const b2Circle* circle ); + +/// Allows you to change a shape to be a capsule or update the current capsule. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +B2_API void b2Shape_SetCapsule( b2ShapeId shapeId, const b2Capsule* capsule ); + +/// Allows you to change a shape to be a segment or update the current segment. +B2_API void b2Shape_SetSegment( b2ShapeId shapeId, const b2Segment* segment ); + +/// Allows you to change a shape to be a polygon or update the current polygon. +/// This does not modify the mass properties. +/// @see b2Body_ApplyMassFromShapes +B2_API void b2Shape_SetPolygon( b2ShapeId shapeId, const b2Polygon* polygon ); + +/// Get the parent chain id if the shape type is a chain segment, otherwise +/// returns b2_nullChainId. +B2_API b2ChainId b2Shape_GetParentChain( b2ShapeId shapeId ); + +/// Get the maximum capacity required for retrieving all the touching contacts on a shape +B2_API int b2Shape_GetContactCapacity( b2ShapeId shapeId ); + +/// Get the touching contact data for a shape. The provided shapeId will be either shapeIdA or shapeIdB on the contact data. +/// @note Box2D uses speculative collision so some contact points may be separated. +/// @returns the number of elements filled in the provided array +/// @warning do not ignore the return value, it specifies the valid number of elements +B2_API int b2Shape_GetContactData( b2ShapeId shapeId, b2ContactData* contactData, int capacity ); + +/// Get the maximum capacity required for retrieving all the overlapped shapes on a sensor shape. +/// This returns 0 if the provided shape is not a sensor. +/// @param shapeId the id of a sensor shape +/// @returns the required capacity to get all the overlaps in b2Shape_GetSensorOverlaps +B2_API int b2Shape_GetSensorCapacity( b2ShapeId shapeId ); + +/// Get the overlapped shapes for a sensor shape. +/// @param shapeId the id of a sensor shape +/// @param overlaps a user allocated array that is filled with the overlapping shapes +/// @param capacity the capacity of overlappedShapes +/// @returns the number of elements filled in the provided array +/// @warning do not ignore the return value, it specifies the valid number of elements +/// @warning overlaps may contain destroyed shapes so use b2Shape_IsValid to confirm each overlap +B2_API int b2Shape_GetSensorOverlaps( b2ShapeId shapeId, b2ShapeId* overlaps, int capacity ); + +/// Get the current world AABB +B2_API b2AABB b2Shape_GetAABB( b2ShapeId shapeId ); + +/// Get the mass data for a shape +B2_API b2MassData b2Shape_GetMassData( b2ShapeId shapeId ); + +/// Get the closest point on a shape to a target point. Target and result are in world space. +/// todo need sample +B2_API b2Vec2 b2Shape_GetClosestPoint( b2ShapeId shapeId, b2Vec2 target ); + +/// Chain Shape + +/// Create a chain shape +/// @see b2ChainDef for details +B2_API b2ChainId b2CreateChain( b2BodyId bodyId, const b2ChainDef* def ); + +/// Destroy a chain shape +B2_API void b2DestroyChain( b2ChainId chainId ); + +/// Get the world that owns this chain shape +B2_API b2WorldId b2Chain_GetWorld( b2ChainId chainId ); + +/// Get the number of segments on this chain +B2_API int b2Chain_GetSegmentCount( b2ChainId chainId ); + +/// Fill a user array with chain segment shape ids up to the specified capacity. Returns +/// the actual number of segments returned. +B2_API int b2Chain_GetSegments( b2ChainId chainId, b2ShapeId* segmentArray, int capacity ); + +/// Set the chain friction +/// @see b2ChainDef::friction +B2_API void b2Chain_SetFriction( b2ChainId chainId, float friction ); + +/// Get the chain friction +B2_API float b2Chain_GetFriction( b2ChainId chainId ); + +/// Set the chain restitution (bounciness) +/// @see b2ChainDef::restitution +B2_API void b2Chain_SetRestitution( b2ChainId chainId, float restitution ); + +/// Get the chain restitution +B2_API float b2Chain_GetRestitution( b2ChainId chainId ); + +/// Set the chain material +/// @see b2ChainDef::material +B2_API void b2Chain_SetMaterial( b2ChainId chainId, int material ); + +/// Get the chain material +B2_API int b2Chain_GetMaterial( b2ChainId chainId ); + +/// Chain identifier validation. Provides validation for up to 64K allocations. +B2_API bool b2Chain_IsValid( b2ChainId id ); + +/** @} */ + +/** + * @defgroup joint Joint + * @brief Joints allow you to connect rigid bodies together while allowing various forms of relative motions. + * @{ + */ + +/// Destroy a joint +B2_API void b2DestroyJoint( b2JointId jointId ); + +/// Joint identifier validation. Provides validation for up to 64K allocations. +B2_API bool b2Joint_IsValid( b2JointId id ); + +/// Get the joint type +B2_API b2JointType b2Joint_GetType( b2JointId jointId ); + +/// Get body A id on a joint +B2_API b2BodyId b2Joint_GetBodyA( b2JointId jointId ); + +/// Get body B id on a joint +B2_API b2BodyId b2Joint_GetBodyB( b2JointId jointId ); + +/// Get the world that owns this joint +B2_API b2WorldId b2Joint_GetWorld( b2JointId jointId ); + +/// Get the local anchor on bodyA +B2_API b2Vec2 b2Joint_GetLocalAnchorA( b2JointId jointId ); + +/// Get the local anchor on bodyB +B2_API b2Vec2 b2Joint_GetLocalAnchorB( b2JointId jointId ); + +/// Toggle collision between connected bodies +B2_API void b2Joint_SetCollideConnected( b2JointId jointId, bool shouldCollide ); + +/// Is collision allowed between connected bodies? +B2_API bool b2Joint_GetCollideConnected( b2JointId jointId ); + +/// Set the user data on a joint +B2_API void b2Joint_SetUserData( b2JointId jointId, void* userData ); + +/// Get the user data on a joint +B2_API void* b2Joint_GetUserData( b2JointId jointId ); + +/// Wake the bodies connect to this joint +B2_API void b2Joint_WakeBodies( b2JointId jointId ); + +/// Get the current constraint force for this joint. Usually in Newtons. +B2_API b2Vec2 b2Joint_GetConstraintForce( b2JointId jointId ); + +/// Get the current constraint torque for this joint. Usually in Newton * meters. +B2_API float b2Joint_GetConstraintTorque( b2JointId jointId ); + +/** + * @defgroup distance_joint Distance Joint + * @brief Functions for the distance joint. + * @{ + */ + +/// Create a distance joint +/// @see b2DistanceJointDef for details +B2_API b2JointId b2CreateDistanceJoint( b2WorldId worldId, const b2DistanceJointDef* def ); + +/// Set the rest length of a distance joint +/// @param jointId The id for a distance joint +/// @param length The new distance joint length +B2_API void b2DistanceJoint_SetLength( b2JointId jointId, float length ); + +/// Get the rest length of a distance joint +B2_API float b2DistanceJoint_GetLength( b2JointId jointId ); + +/// Enable/disable the distance joint spring. When disabled the distance joint is rigid. +B2_API void b2DistanceJoint_EnableSpring( b2JointId jointId, bool enableSpring ); + +/// Is the distance joint spring enabled? +B2_API bool b2DistanceJoint_IsSpringEnabled( b2JointId jointId ); + +/// Set the spring stiffness in Hertz +B2_API void b2DistanceJoint_SetSpringHertz( b2JointId jointId, float hertz ); + +/// Set the spring damping ratio, non-dimensional +B2_API void b2DistanceJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the spring Hertz +B2_API float b2DistanceJoint_GetSpringHertz( b2JointId jointId ); + +/// Get the spring damping ratio +B2_API float b2DistanceJoint_GetSpringDampingRatio( b2JointId jointId ); + +/// Enable joint limit. The limit only works if the joint spring is enabled. Otherwise the joint is rigid +/// and the limit has no effect. +B2_API void b2DistanceJoint_EnableLimit( b2JointId jointId, bool enableLimit ); + +/// Is the distance joint limit enabled? +B2_API bool b2DistanceJoint_IsLimitEnabled( b2JointId jointId ); + +/// Set the minimum and maximum length parameters of a distance joint +B2_API void b2DistanceJoint_SetLengthRange( b2JointId jointId, float minLength, float maxLength ); + +/// Get the distance joint minimum length +B2_API float b2DistanceJoint_GetMinLength( b2JointId jointId ); + +/// Get the distance joint maximum length +B2_API float b2DistanceJoint_GetMaxLength( b2JointId jointId ); + +/// Get the current length of a distance joint +B2_API float b2DistanceJoint_GetCurrentLength( b2JointId jointId ); + +/// Enable/disable the distance joint motor +B2_API void b2DistanceJoint_EnableMotor( b2JointId jointId, bool enableMotor ); + +/// Is the distance joint motor enabled? +B2_API bool b2DistanceJoint_IsMotorEnabled( b2JointId jointId ); + +/// Set the distance joint motor speed, usually in meters per second +B2_API void b2DistanceJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ); + +/// Get the distance joint motor speed, usually in meters per second +B2_API float b2DistanceJoint_GetMotorSpeed( b2JointId jointId ); + +/// Set the distance joint maximum motor force, usually in newtons +B2_API void b2DistanceJoint_SetMaxMotorForce( b2JointId jointId, float force ); + +/// Get the distance joint maximum motor force, usually in newtons +B2_API float b2DistanceJoint_GetMaxMotorForce( b2JointId jointId ); + +/// Get the distance joint current motor force, usually in newtons +B2_API float b2DistanceJoint_GetMotorForce( b2JointId jointId ); + +/** @} */ + +/** + * @defgroup motor_joint Motor Joint + * @brief Functions for the motor joint. + * + * The motor joint is used to drive the relative transform between two bodies. It takes + * a relative position and rotation and applies the forces and torques needed to achieve + * that relative transform over time. + * @{ + */ + +/// Create a motor joint +/// @see b2MotorJointDef for details +B2_API b2JointId b2CreateMotorJoint( b2WorldId worldId, const b2MotorJointDef* def ); + +/// Set the motor joint linear offset target +B2_API void b2MotorJoint_SetLinearOffset( b2JointId jointId, b2Vec2 linearOffset ); + +/// Get the motor joint linear offset target +B2_API b2Vec2 b2MotorJoint_GetLinearOffset( b2JointId jointId ); + +/// Set the motor joint angular offset target in radians +B2_API void b2MotorJoint_SetAngularOffset( b2JointId jointId, float angularOffset ); + +/// Get the motor joint angular offset target in radians +B2_API float b2MotorJoint_GetAngularOffset( b2JointId jointId ); + +/// Set the motor joint maximum force, usually in newtons +B2_API void b2MotorJoint_SetMaxForce( b2JointId jointId, float maxForce ); + +/// Get the motor joint maximum force, usually in newtons +B2_API float b2MotorJoint_GetMaxForce( b2JointId jointId ); + +/// Set the motor joint maximum torque, usually in newton-meters +B2_API void b2MotorJoint_SetMaxTorque( b2JointId jointId, float maxTorque ); + +/// Get the motor joint maximum torque, usually in newton-meters +B2_API float b2MotorJoint_GetMaxTorque( b2JointId jointId ); + +/// Set the motor joint correction factor, usually in [0, 1] +B2_API void b2MotorJoint_SetCorrectionFactor( b2JointId jointId, float correctionFactor ); + +/// Get the motor joint correction factor, usually in [0, 1] +B2_API float b2MotorJoint_GetCorrectionFactor( b2JointId jointId ); + +/**@}*/ + +/** + * @defgroup mouse_joint Mouse Joint + * @brief Functions for the mouse joint. + * + * The mouse joint is designed for use in the samples application, but you may find it useful in applications where + * the user moves a rigid body with a cursor. + * @{ + */ + +/// Create a mouse joint +/// @see b2MouseJointDef for details +B2_API b2JointId b2CreateMouseJoint( b2WorldId worldId, const b2MouseJointDef* def ); + +/// Set the mouse joint target +B2_API void b2MouseJoint_SetTarget( b2JointId jointId, b2Vec2 target ); + +/// Get the mouse joint target +B2_API b2Vec2 b2MouseJoint_GetTarget( b2JointId jointId ); + +/// Set the mouse joint spring stiffness in Hertz +B2_API void b2MouseJoint_SetSpringHertz( b2JointId jointId, float hertz ); + +/// Get the mouse joint spring stiffness in Hertz +B2_API float b2MouseJoint_GetSpringHertz( b2JointId jointId ); + +/// Set the mouse joint spring damping ratio, non-dimensional +B2_API void b2MouseJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the mouse joint damping ratio, non-dimensional +B2_API float b2MouseJoint_GetSpringDampingRatio( b2JointId jointId ); + +/// Set the mouse joint maximum force, usually in newtons +B2_API void b2MouseJoint_SetMaxForce( b2JointId jointId, float maxForce ); + +/// Get the mouse joint maximum force, usually in newtons +B2_API float b2MouseJoint_GetMaxForce( b2JointId jointId ); + +/**@}*/ + +/** + * @defgroup filter_joint Filter Joint + * @brief Functions for the filter joint. + * + * The filter joint is used to disable collision between two bodies. As a side effect of being a joint, it also + * keeps the two bodies in the same simulation island. + * @{ + */ + +/// Create a filter joint. +/// @see b2FilterJointDef for details +B2_API b2JointId b2CreateFilterJoint( b2WorldId worldId, const b2FilterJointDef* def ); + +/**@}*/ + +/** + * @defgroup prismatic_joint Prismatic Joint + * @brief A prismatic joint allows for translation along a single axis with no rotation. + * + * The prismatic joint is useful for things like pistons and moving platforms, where you want a body to translate + * along an axis and have no rotation. Also called a *slider* joint. + * @{ + */ + +/// Create a prismatic (slider) joint. +/// @see b2PrismaticJointDef for details +B2_API b2JointId b2CreatePrismaticJoint( b2WorldId worldId, const b2PrismaticJointDef* def ); + +/// Enable/disable the joint spring. +B2_API void b2PrismaticJoint_EnableSpring( b2JointId jointId, bool enableSpring ); + +/// Is the prismatic joint spring enabled or not? +B2_API bool b2PrismaticJoint_IsSpringEnabled( b2JointId jointId ); + +/// Set the prismatic joint stiffness in Hertz. +/// This should usually be less than a quarter of the simulation rate. For example, if the simulation +/// runs at 60Hz then the joint stiffness should be 15Hz or less. +B2_API void b2PrismaticJoint_SetSpringHertz( b2JointId jointId, float hertz ); + +/// Get the prismatic joint stiffness in Hertz +B2_API float b2PrismaticJoint_GetSpringHertz( b2JointId jointId ); + +/// Set the prismatic joint damping ratio (non-dimensional) +B2_API void b2PrismaticJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the prismatic spring damping ratio (non-dimensional) +B2_API float b2PrismaticJoint_GetSpringDampingRatio( b2JointId jointId ); + +/// Enable/disable a prismatic joint limit +B2_API void b2PrismaticJoint_EnableLimit( b2JointId jointId, bool enableLimit ); + +/// Is the prismatic joint limit enabled? +B2_API bool b2PrismaticJoint_IsLimitEnabled( b2JointId jointId ); + +/// Get the prismatic joint lower limit +B2_API float b2PrismaticJoint_GetLowerLimit( b2JointId jointId ); + +/// Get the prismatic joint upper limit +B2_API float b2PrismaticJoint_GetUpperLimit( b2JointId jointId ); + +/// Set the prismatic joint limits +B2_API void b2PrismaticJoint_SetLimits( b2JointId jointId, float lower, float upper ); + +/// Enable/disable a prismatic joint motor +B2_API void b2PrismaticJoint_EnableMotor( b2JointId jointId, bool enableMotor ); + +/// Is the prismatic joint motor enabled? +B2_API bool b2PrismaticJoint_IsMotorEnabled( b2JointId jointId ); + +/// Set the prismatic joint motor speed, usually in meters per second +B2_API void b2PrismaticJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ); + +/// Get the prismatic joint motor speed, usually in meters per second +B2_API float b2PrismaticJoint_GetMotorSpeed( b2JointId jointId ); + +/// Set the prismatic joint maximum motor force, usually in newtons +B2_API void b2PrismaticJoint_SetMaxMotorForce( b2JointId jointId, float force ); + +/// Get the prismatic joint maximum motor force, usually in newtons +B2_API float b2PrismaticJoint_GetMaxMotorForce( b2JointId jointId ); + +/// Get the prismatic joint current motor force, usually in newtons +B2_API float b2PrismaticJoint_GetMotorForce( b2JointId jointId ); + +/// Get the current joint translation, usually in meters. +B2_API float b2PrismaticJoint_GetTranslation( b2JointId jointId ); + +/// Get the current joint translation speed, usually in meters per second. +B2_API float b2PrismaticJoint_GetSpeed( b2JointId jointId ); + +/** @} */ + +/** + * @defgroup revolute_joint Revolute Joint + * @brief A revolute joint allows for relative rotation in the 2D plane with no relative translation. + * + * The revolute joint is probably the most common joint. It can be used for ragdolls and chains. + * Also called a *hinge* or *pin* joint. + * @{ + */ + +/// Create a revolute joint +/// @see b2RevoluteJointDef for details +B2_API b2JointId b2CreateRevoluteJoint( b2WorldId worldId, const b2RevoluteJointDef* def ); + +/// Enable/disable the revolute joint spring +B2_API void b2RevoluteJoint_EnableSpring( b2JointId jointId, bool enableSpring ); + +/// It the revolute angular spring enabled? +B2_API bool b2RevoluteJoint_IsSpringEnabled( b2JointId jointId ); + +/// Set the revolute joint spring stiffness in Hertz +B2_API void b2RevoluteJoint_SetSpringHertz( b2JointId jointId, float hertz ); + +/// Get the revolute joint spring stiffness in Hertz +B2_API float b2RevoluteJoint_GetSpringHertz( b2JointId jointId ); + +/// Set the revolute joint spring damping ratio, non-dimensional +B2_API void b2RevoluteJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the revolute joint spring damping ratio, non-dimensional +B2_API float b2RevoluteJoint_GetSpringDampingRatio( b2JointId jointId ); + +/// Get the revolute joint current angle in radians relative to the reference angle +/// @see b2RevoluteJointDef::referenceAngle +B2_API float b2RevoluteJoint_GetAngle( b2JointId jointId ); + +/// Enable/disable the revolute joint limit +B2_API void b2RevoluteJoint_EnableLimit( b2JointId jointId, bool enableLimit ); + +/// Is the revolute joint limit enabled? +B2_API bool b2RevoluteJoint_IsLimitEnabled( b2JointId jointId ); + +/// Get the revolute joint lower limit in radians +B2_API float b2RevoluteJoint_GetLowerLimit( b2JointId jointId ); + +/// Get the revolute joint upper limit in radians +B2_API float b2RevoluteJoint_GetUpperLimit( b2JointId jointId ); + +/// Set the revolute joint limits in radians. It is expected that lower <= upper +/// and that -0.95 * B2_PI <= lower && upper <= -0.95 * B2_PI. +B2_API void b2RevoluteJoint_SetLimits( b2JointId jointId, float lower, float upper ); + +/// Enable/disable a revolute joint motor +B2_API void b2RevoluteJoint_EnableMotor( b2JointId jointId, bool enableMotor ); + +/// Is the revolute joint motor enabled? +B2_API bool b2RevoluteJoint_IsMotorEnabled( b2JointId jointId ); + +/// Set the revolute joint motor speed in radians per second +B2_API void b2RevoluteJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ); + +/// Get the revolute joint motor speed in radians per second +B2_API float b2RevoluteJoint_GetMotorSpeed( b2JointId jointId ); + +/// Get the revolute joint current motor torque, usually in newton-meters +B2_API float b2RevoluteJoint_GetMotorTorque( b2JointId jointId ); + +/// Set the revolute joint maximum motor torque, usually in newton-meters +B2_API void b2RevoluteJoint_SetMaxMotorTorque( b2JointId jointId, float torque ); + +/// Get the revolute joint maximum motor torque, usually in newton-meters +B2_API float b2RevoluteJoint_GetMaxMotorTorque( b2JointId jointId ); + +/**@}*/ + +/** + * @defgroup weld_joint Weld Joint + * @brief A weld joint fully constrains the relative transform between two bodies while allowing for springiness + * + * A weld joint constrains the relative rotation and translation between two bodies. Both rotation and translation + * can have damped springs. + * + * @note The accuracy of weld joint is limited by the accuracy of the solver. Long chains of weld joints may flex. + * @{ + */ + +/// Create a weld joint +/// @see b2WeldJointDef for details +B2_API b2JointId b2CreateWeldJoint( b2WorldId worldId, const b2WeldJointDef* def ); + +/// Get the weld joint reference angle in radians +B2_API float b2WeldJoint_GetReferenceAngle( b2JointId jointId ); + +/// Set the weld joint reference angle in radians, must be in [-pi,pi]. +B2_API void b2WeldJoint_SetReferenceAngle( b2JointId jointId, float angleInRadians ); + +/// Set the weld joint linear stiffness in Hertz. 0 is rigid. +B2_API void b2WeldJoint_SetLinearHertz( b2JointId jointId, float hertz ); + +/// Get the weld joint linear stiffness in Hertz +B2_API float b2WeldJoint_GetLinearHertz( b2JointId jointId ); + +/// Set the weld joint linear damping ratio (non-dimensional) +B2_API void b2WeldJoint_SetLinearDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the weld joint linear damping ratio (non-dimensional) +B2_API float b2WeldJoint_GetLinearDampingRatio( b2JointId jointId ); + +/// Set the weld joint angular stiffness in Hertz. 0 is rigid. +B2_API void b2WeldJoint_SetAngularHertz( b2JointId jointId, float hertz ); + +/// Get the weld joint angular stiffness in Hertz +B2_API float b2WeldJoint_GetAngularHertz( b2JointId jointId ); + +/// Set weld joint angular damping ratio, non-dimensional +B2_API void b2WeldJoint_SetAngularDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the weld joint angular damping ratio, non-dimensional +B2_API float b2WeldJoint_GetAngularDampingRatio( b2JointId jointId ); + +/** @} */ + +/** + * @defgroup wheel_joint Wheel Joint + * The wheel joint can be used to simulate wheels on vehicles. + * + * The wheel joint restricts body B to move along a local axis in body A. Body B is free to + * rotate. Supports a linear spring, linear limits, and a rotational motor. + * + * @{ + */ + +/// Create a wheel joint +/// @see b2WheelJointDef for details +B2_API b2JointId b2CreateWheelJoint( b2WorldId worldId, const b2WheelJointDef* def ); + +/// Enable/disable the wheel joint spring +B2_API void b2WheelJoint_EnableSpring( b2JointId jointId, bool enableSpring ); + +/// Is the wheel joint spring enabled? +B2_API bool b2WheelJoint_IsSpringEnabled( b2JointId jointId ); + +/// Set the wheel joint stiffness in Hertz +B2_API void b2WheelJoint_SetSpringHertz( b2JointId jointId, float hertz ); + +/// Get the wheel joint stiffness in Hertz +B2_API float b2WheelJoint_GetSpringHertz( b2JointId jointId ); + +/// Set the wheel joint damping ratio, non-dimensional +B2_API void b2WheelJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ); + +/// Get the wheel joint damping ratio, non-dimensional +B2_API float b2WheelJoint_GetSpringDampingRatio( b2JointId jointId ); + +/// Enable/disable the wheel joint limit +B2_API void b2WheelJoint_EnableLimit( b2JointId jointId, bool enableLimit ); + +/// Is the wheel joint limit enabled? +B2_API bool b2WheelJoint_IsLimitEnabled( b2JointId jointId ); + +/// Get the wheel joint lower limit +B2_API float b2WheelJoint_GetLowerLimit( b2JointId jointId ); + +/// Get the wheel joint upper limit +B2_API float b2WheelJoint_GetUpperLimit( b2JointId jointId ); + +/// Set the wheel joint limits +B2_API void b2WheelJoint_SetLimits( b2JointId jointId, float lower, float upper ); + +/// Enable/disable the wheel joint motor +B2_API void b2WheelJoint_EnableMotor( b2JointId jointId, bool enableMotor ); + +/// Is the wheel joint motor enabled? +B2_API bool b2WheelJoint_IsMotorEnabled( b2JointId jointId ); + +/// Set the wheel joint motor speed in radians per second +B2_API void b2WheelJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ); + +/// Get the wheel joint motor speed in radians per second +B2_API float b2WheelJoint_GetMotorSpeed( b2JointId jointId ); + +/// Set the wheel joint maximum motor torque, usually in newton-meters +B2_API void b2WheelJoint_SetMaxMotorTorque( b2JointId jointId, float torque ); + +/// Get the wheel joint maximum motor torque, usually in newton-meters +B2_API float b2WheelJoint_GetMaxMotorTorque( b2JointId jointId ); + +/// Get the wheel joint current motor torque, usually in newton-meters +B2_API float b2WheelJoint_GetMotorTorque( b2JointId jointId ); + +/**@}*/ + +/**@}*/ diff --git a/3rdparty/box2d/include/box2d/collision.h b/3rdparty/box2d/include/box2d/collision.h new file mode 100644 index 000000000000..5dbf71e08fb4 --- /dev/null +++ b/3rdparty/box2d/include/box2d/collision.h @@ -0,0 +1,830 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "base.h" +#include "math_functions.h" + +#include + +typedef struct b2SimplexCache b2SimplexCache; +typedef struct b2Hull b2Hull; + +/** + * @defgroup geometry Geometry + * @brief Geometry types and algorithms + * + * Definitions of circles, capsules, segments, and polygons. Various algorithms to compute hulls, mass properties, and so on. + * @{ + */ + +/// The maximum number of vertices on a convex polygon. Changing this affects performance even if you +/// don't use more vertices. +#define B2_MAX_POLYGON_VERTICES 8 + +/// Low level ray cast input data +typedef struct b2RayCastInput +{ + /// Start point of the ray cast + b2Vec2 origin; + + /// Translation of the ray cast + b2Vec2 translation; + + /// The maximum fraction of the translation to consider, typically 1 + float maxFraction; +} b2RayCastInput; + +/// A distance proxy is used by the GJK algorithm. It encapsulates any shape. +/// You can provide between 1 and B2_MAX_POLYGON_VERTICES and a radius. +typedef struct b2ShapeProxy +{ + /// The point cloud + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; + + /// The number of points. Must be greater than 0. + int count; + + /// The external radius of the point cloud. May be zero. + float radius; +} b2ShapeProxy; + +/// Low level shape cast input in generic form. This allows casting an arbitrary point +/// cloud wrap with a radius. For example, a circle is a single point with a non-zero radius. +/// A capsule is two points with a non-zero radius. A box is four points with a zero radius. +typedef struct b2ShapeCastInput +{ + /// A generic shape + b2ShapeProxy proxy; + + /// The translation of the shape cast + b2Vec2 translation; + + /// The maximum fraction of the translation to consider, typically 1 + float maxFraction; + + /// Allow shape cast to encroach when initially touching. This only works if the radius is greater than zero. + bool canEncroach; +} b2ShapeCastInput; + +/// Low level ray cast or shape-cast output data +typedef struct b2CastOutput +{ + /// The surface normal at the hit point + b2Vec2 normal; + + /// The surface hit point + b2Vec2 point; + + /// The fraction of the input translation at collision + float fraction; + + /// The number of iterations used + int iterations; + + /// Did the cast hit? + bool hit; +} b2CastOutput; + +/// This holds the mass data computed for a shape. +typedef struct b2MassData +{ + /// The mass of the shape, usually in kilograms. + float mass; + + /// The position of the shape's centroid relative to the shape's origin. + b2Vec2 center; + + /// The rotational inertia of the shape about the local origin. + float rotationalInertia; +} b2MassData; + +/// A solid circle +typedef struct b2Circle +{ + /// The local center + b2Vec2 center; + + /// The radius + float radius; +} b2Circle; + +/// A solid capsule can be viewed as two semicircles connected +/// by a rectangle. +typedef struct b2Capsule +{ + /// Local center of the first semicircle + b2Vec2 center1; + + /// Local center of the second semicircle + b2Vec2 center2; + + /// The radius of the semicircles + float radius; +} b2Capsule; + +/// A solid convex polygon. It is assumed that the interior of the polygon is to +/// the left of each edge. +/// Polygons have a maximum number of vertices equal to B2_MAX_POLYGON_VERTICES. +/// In most cases you should not need many vertices for a convex polygon. +/// @warning DO NOT fill this out manually, instead use a helper function like +/// b2MakePolygon or b2MakeBox. +typedef struct b2Polygon +{ + /// The polygon vertices + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; + + /// The outward normal vectors of the polygon sides + b2Vec2 normals[B2_MAX_POLYGON_VERTICES]; + + /// The centroid of the polygon + b2Vec2 centroid; + + /// The external radius for rounded polygons + float radius; + + /// The number of polygon vertices + int count; +} b2Polygon; + +/// A line segment with two-sided collision. +typedef struct b2Segment +{ + /// The first point + b2Vec2 point1; + + /// The second point + b2Vec2 point2; +} b2Segment; + +/// A line segment with one-sided collision. Only collides on the right side. +/// Several of these are generated for a chain shape. +/// ghost1 -> point1 -> point2 -> ghost2 +typedef struct b2ChainSegment +{ + /// The tail ghost vertex + b2Vec2 ghost1; + + /// The line segment + b2Segment segment; + + /// The head ghost vertex + b2Vec2 ghost2; + + /// The owning chain shape index (internal usage only) + int chainId; +} b2ChainSegment; + +/// Validate ray cast input data (NaN, etc) +B2_API bool b2IsValidRay( const b2RayCastInput* input ); + +/// Make a convex polygon from a convex hull. This will assert if the hull is not valid. +/// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull +B2_API b2Polygon b2MakePolygon( const b2Hull* hull, float radius ); + +/// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid. +/// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull +B2_API b2Polygon b2MakeOffsetPolygon( const b2Hull* hull, b2Vec2 position, b2Rot rotation ); + +/// Make an offset convex polygon from a convex hull. This will assert if the hull is not valid. +/// @warning Do not manually fill in the hull data, it must come directly from b2ComputeHull +B2_API b2Polygon b2MakeOffsetRoundedPolygon( const b2Hull* hull, b2Vec2 position, b2Rot rotation, float radius ); + +/// Make a square polygon, bypassing the need for a convex hull. +/// @param halfWidth the half-width +B2_API b2Polygon b2MakeSquare( float halfWidth ); + +/// Make a box (rectangle) polygon, bypassing the need for a convex hull. +/// @param halfWidth the half-width (x-axis) +/// @param halfHeight the half-height (y-axis) +B2_API b2Polygon b2MakeBox( float halfWidth, float halfHeight ); + +/// Make a rounded box, bypassing the need for a convex hull. +/// @param halfWidth the half-width (x-axis) +/// @param halfHeight the half-height (y-axis) +/// @param radius the radius of the rounded extension +B2_API b2Polygon b2MakeRoundedBox( float halfWidth, float halfHeight, float radius ); + +/// Make an offset box, bypassing the need for a convex hull. +/// @param halfWidth the half-width (x-axis) +/// @param halfHeight the half-height (y-axis) +/// @param center the local center of the box +/// @param rotation the local rotation of the box +B2_API b2Polygon b2MakeOffsetBox( float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation ); + +/// Make an offset rounded box, bypassing the need for a convex hull. +/// @param halfWidth the half-width (x-axis) +/// @param halfHeight the half-height (y-axis) +/// @param center the local center of the box +/// @param rotation the local rotation of the box +/// @param radius the radius of the rounded extension +B2_API b2Polygon b2MakeOffsetRoundedBox( float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation, float radius ); + +/// Transform a polygon. This is useful for transferring a shape from one body to another. +B2_API b2Polygon b2TransformPolygon( b2Transform transform, const b2Polygon* polygon ); + +/// Compute mass properties of a circle +B2_API b2MassData b2ComputeCircleMass( const b2Circle* shape, float density ); + +/// Compute mass properties of a capsule +B2_API b2MassData b2ComputeCapsuleMass( const b2Capsule* shape, float density ); + +/// Compute mass properties of a polygon +B2_API b2MassData b2ComputePolygonMass( const b2Polygon* shape, float density ); + +/// Compute the bounding box of a transformed circle +B2_API b2AABB b2ComputeCircleAABB( const b2Circle* shape, b2Transform transform ); + +/// Compute the bounding box of a transformed capsule +B2_API b2AABB b2ComputeCapsuleAABB( const b2Capsule* shape, b2Transform transform ); + +/// Compute the bounding box of a transformed polygon +B2_API b2AABB b2ComputePolygonAABB( const b2Polygon* shape, b2Transform transform ); + +/// Compute the bounding box of a transformed line segment +B2_API b2AABB b2ComputeSegmentAABB( const b2Segment* shape, b2Transform transform ); + +/// Test a point for overlap with a circle in local space +B2_API bool b2PointInCircle( b2Vec2 point, const b2Circle* shape ); + +/// Test a point for overlap with a capsule in local space +B2_API bool b2PointInCapsule( b2Vec2 point, const b2Capsule* shape ); + +/// Test a point for overlap with a convex polygon in local space +B2_API bool b2PointInPolygon( b2Vec2 point, const b2Polygon* shape ); + +/// Ray cast versus circle shape in local space. Initial overlap is treated as a miss. +B2_API b2CastOutput b2RayCastCircle( const b2RayCastInput* input, const b2Circle* shape ); + +/// Ray cast versus capsule shape in local space. Initial overlap is treated as a miss. +B2_API b2CastOutput b2RayCastCapsule( const b2RayCastInput* input, const b2Capsule* shape ); + +/// Ray cast versus segment shape in local space. Optionally treat the segment as one-sided with hits from +/// the left side being treated as a miss. +B2_API b2CastOutput b2RayCastSegment( const b2RayCastInput* input, const b2Segment* shape, bool oneSided ); + +/// Ray cast versus polygon shape in local space. Initial overlap is treated as a miss. +B2_API b2CastOutput b2RayCastPolygon( const b2RayCastInput* input, const b2Polygon* shape ); + +/// Shape cast versus a circle. Initial overlap is treated as a miss. +B2_API b2CastOutput b2ShapeCastCircle( const b2ShapeCastInput* input, const b2Circle* shape ); + +/// Shape cast versus a capsule. Initial overlap is treated as a miss. +B2_API b2CastOutput b2ShapeCastCapsule( const b2ShapeCastInput* input, const b2Capsule* shape ); + +/// Shape cast versus a line segment. Initial overlap is treated as a miss. +B2_API b2CastOutput b2ShapeCastSegment( const b2ShapeCastInput* input, const b2Segment* shape ); + +/// Shape cast versus a convex polygon. Initial overlap is treated as a miss. +B2_API b2CastOutput b2ShapeCastPolygon( const b2ShapeCastInput* input, const b2Polygon* shape ); + +/// A convex hull. Used to create convex polygons. +/// @warning Do not modify these values directly, instead use b2ComputeHull() +typedef struct b2Hull +{ + /// The final points of the hull + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; + + /// The number of points + int count; +} b2Hull; + +/// Compute the convex hull of a set of points. Returns an empty hull if it fails. +/// Some failure cases: +/// - all points very close together +/// - all points on a line +/// - less than 3 points +/// - more than B2_MAX_POLYGON_VERTICES points +/// This welds close points and removes collinear points. +/// @warning Do not modify a hull once it has been computed +B2_API b2Hull b2ComputeHull( const b2Vec2* points, int count ); + +/// This determines if a hull is valid. Checks for: +/// - convexity +/// - collinear points +/// This is expensive and should not be called at runtime. +B2_API bool b2ValidateHull( const b2Hull* hull ); + +/**@}*/ + +/** + * @defgroup distance Distance + * Functions for computing the distance between shapes. + * + * These are advanced functions you can use to perform distance calculations. There + * are functions for computing the closest points between shapes, doing linear shape casts, + * and doing rotational shape casts. The latter is called time of impact (TOI). + * @{ + */ + +/// Result of computing the distance between two line segments +typedef struct b2SegmentDistanceResult +{ + /// The closest point on the first segment + b2Vec2 closest1; + + /// The closest point on the second segment + b2Vec2 closest2; + + /// The barycentric coordinate on the first segment + float fraction1; + + /// The barycentric coordinate on the second segment + float fraction2; + + /// The squared distance between the closest points + float distanceSquared; +} b2SegmentDistanceResult; + +/// Compute the distance between two line segments, clamping at the end points if needed. +B2_API b2SegmentDistanceResult b2SegmentDistance( b2Vec2 p1, b2Vec2 q1, b2Vec2 p2, b2Vec2 q2 ); + +/// Used to warm start the GJK simplex. If you call this function multiple times with nearby +/// transforms this might improve performance. Otherwise you can zero initialize this. +/// The distance cache must be initialized to zero on the first call. +/// Users should generally just zero initialize this structure for each call. +typedef struct b2SimplexCache +{ + /// The number of stored simplex points + uint16_t count; + + /// The cached simplex indices on shape A + uint8_t indexA[3]; + + /// The cached simplex indices on shape B + uint8_t indexB[3]; +} b2SimplexCache; + +static const b2SimplexCache b2_emptySimplexCache = B2_ZERO_INIT; + +/// Input for b2ShapeDistance +typedef struct b2DistanceInput +{ + /// The proxy for shape A + b2ShapeProxy proxyA; + + /// The proxy for shape B + b2ShapeProxy proxyB; + + /// The world transform for shape A + b2Transform transformA; + + /// The world transform for shape B + b2Transform transformB; + + /// Should the proxy radius be considered? + bool useRadii; +} b2DistanceInput; + +/// Output for b2ShapeDistance +typedef struct b2DistanceOutput +{ + b2Vec2 pointA; ///< Closest point on shapeA + b2Vec2 pointB; ///< Closest point on shapeB + b2Vec2 normal; ///< Normal vector that points from A to B + float distance; ///< The final distance, zero if overlapped + int iterations; ///< Number of GJK iterations used + int simplexCount; ///< The number of simplexes stored in the simplex array +} b2DistanceOutput; + +/// Simplex vertex for debugging the GJK algorithm +typedef struct b2SimplexVertex +{ + b2Vec2 wA; ///< support point in proxyA + b2Vec2 wB; ///< support point in proxyB + b2Vec2 w; ///< wB - wA + float a; ///< barycentric coordinate for closest point + int indexA; ///< wA index + int indexB; ///< wB index +} b2SimplexVertex; + +/// Simplex from the GJK algorithm +typedef struct b2Simplex +{ + b2SimplexVertex v1, v2, v3; ///< vertices + int count; ///< number of valid vertices +} b2Simplex; + +/// Compute the closest points between two shapes represented as point clouds. +/// b2SimplexCache cache is input/output. On the first call set b2SimplexCache.count to zero. +/// The underlying GJK algorithm may be debugged by passing in debug simplexes and capacity. You may pass in NULL and 0 for these. +B2_API b2DistanceOutput b2ShapeDistance( const b2DistanceInput* input, b2SimplexCache* cache, b2Simplex* simplexes, + int simplexCapacity ); + +/// Input parameters for b2ShapeCast +typedef struct b2ShapeCastPairInput +{ + b2ShapeProxy proxyA; ///< The proxy for shape A + b2ShapeProxy proxyB; ///< The proxy for shape B + b2Transform transformA; ///< The world transform for shape A + b2Transform transformB; ///< The world transform for shape B + b2Vec2 translationB; ///< The translation of shape B + float maxFraction; ///< The fraction of the translation to consider, typically 1 + bool canEncroach; ///< Allows shapes with a radius to move slightly closer if already touching +} b2ShapeCastPairInput; + +/// Perform a linear shape cast of shape B moving and shape A fixed. Determines the hit point, normal, and translation fraction. +/// You may optionally supply an array to hold debug data. +B2_API b2CastOutput b2ShapeCast( const b2ShapeCastPairInput* input ); + +/// Make a proxy for use in overlap, shape cast, and related functions. This is a deep copy of the points. +B2_API b2ShapeProxy b2MakeProxy( const b2Vec2* points, int count, float radius ); + +/// Make a proxy with a transform. This is a deep copy of the points. +B2_API b2ShapeProxy b2MakeOffsetProxy( const b2Vec2* points, int count, float radius, b2Vec2 position, b2Rot rotation ); + +/// This describes the motion of a body/shape for TOI computation. Shapes are defined with respect to the body origin, +/// which may not coincide with the center of mass. However, to support dynamics we must interpolate the center of mass +/// position. +typedef struct b2Sweep +{ + b2Vec2 localCenter; ///< Local center of mass position + b2Vec2 c1; ///< Starting center of mass world position + b2Vec2 c2; ///< Ending center of mass world position + b2Rot q1; ///< Starting world rotation + b2Rot q2; ///< Ending world rotation +} b2Sweep; + +/// Evaluate the transform sweep at a specific time. +B2_API b2Transform b2GetSweepTransform( const b2Sweep* sweep, float time ); + +/// Input parameters for b2TimeOfImpact +typedef struct b2TOIInput +{ + b2ShapeProxy proxyA; ///< The proxy for shape A + b2ShapeProxy proxyB; ///< The proxy for shape B + b2Sweep sweepA; ///< The movement of shape A + b2Sweep sweepB; ///< The movement of shape B + float maxFraction; ///< Defines the sweep interval [0, maxFraction] +} b2TOIInput; + +/// Describes the TOI output +typedef enum b2TOIState +{ + b2_toiStateUnknown, + b2_toiStateFailed, + b2_toiStateOverlapped, + b2_toiStateHit, + b2_toiStateSeparated +} b2TOIState; + +/// Output parameters for b2TimeOfImpact. +typedef struct b2TOIOutput +{ + b2TOIState state; ///< The type of result + float fraction; ///< The sweep time of the collision +} b2TOIOutput; + +/// Compute the upper bound on time before two shapes penetrate. Time is represented as +/// a fraction between [0,tMax]. This uses a swept separating axis and may miss some intermediate, +/// non-tunneling collisions. If you change the time interval, you should call this function +/// again. +B2_API b2TOIOutput b2TimeOfImpact( const b2TOIInput* input ); + +/**@}*/ + +/** + * @defgroup collision Collision + * @brief Functions for colliding pairs of shapes + * @{ + */ + +/// A manifold point is a contact point belonging to a contact manifold. +/// It holds details related to the geometry and dynamics of the contact points. +/// Box2D uses speculative collision so some contact points may be separated. +/// You may use the totalNormalImpulse to determine if there was an interaction during +/// the time step. +typedef struct b2ManifoldPoint +{ + /// Location of the contact point in world space. Subject to precision loss at large coordinates. + /// @note Should only be used for debugging. + b2Vec2 point; + + /// Location of the contact point relative to shapeA's origin in world space + /// @note When used internally to the Box2D solver, this is relative to the body center of mass. + b2Vec2 anchorA; + + /// Location of the contact point relative to shapeB's origin in world space + /// @note When used internally to the Box2D solver, this is relative to the body center of mass. + b2Vec2 anchorB; + + /// The separation of the contact point, negative if penetrating + float separation; + + /// The impulse along the manifold normal vector. + float normalImpulse; + + /// The friction impulse + float tangentImpulse; + + /// The total normal impulse applied across sub-stepping and restitution. This is important + /// to identify speculative contact points that had an interaction in the time step. + float totalNormalImpulse; + + /// Relative normal velocity pre-solve. Used for hit events. If the normal impulse is + /// zero then there was no hit. Negative means shapes are approaching. + float normalVelocity; + + /// Uniquely identifies a contact point between two shapes + uint16_t id; + + /// Did this contact point exist the previous step? + bool persisted; +} b2ManifoldPoint; + +/// A contact manifold describes the contact points between colliding shapes. +/// @note Box2D uses speculative collision so some contact points may be separated. +typedef struct b2Manifold +{ + /// The unit normal vector in world space, points from shape A to bodyB + b2Vec2 normal; + + /// Angular impulse applied for rolling resistance. N * m * s = kg * m^2 / s + float rollingImpulse; + + /// The manifold points, up to two are possible in 2D + b2ManifoldPoint points[2]; + + /// The number of contacts points, will be 0, 1, or 2 + int pointCount; + +} b2Manifold; + +/// Compute the contact manifold between two circles +B2_API b2Manifold b2CollideCircles( const b2Circle* circleA, b2Transform xfA, const b2Circle* circleB, b2Transform xfB ); + +/// Compute the contact manifold between a capsule and circle +B2_API b2Manifold b2CollideCapsuleAndCircle( const b2Capsule* capsuleA, b2Transform xfA, const b2Circle* circleB, + b2Transform xfB ); + +/// Compute the contact manifold between an segment and a circle +B2_API b2Manifold b2CollideSegmentAndCircle( const b2Segment* segmentA, b2Transform xfA, const b2Circle* circleB, + b2Transform xfB ); + +/// Compute the contact manifold between a polygon and a circle +B2_API b2Manifold b2CollidePolygonAndCircle( const b2Polygon* polygonA, b2Transform xfA, const b2Circle* circleB, + b2Transform xfB ); + +/// Compute the contact manifold between a capsule and circle +B2_API b2Manifold b2CollideCapsules( const b2Capsule* capsuleA, b2Transform xfA, const b2Capsule* capsuleB, b2Transform xfB ); + +/// Compute the contact manifold between an segment and a capsule +B2_API b2Manifold b2CollideSegmentAndCapsule( const b2Segment* segmentA, b2Transform xfA, const b2Capsule* capsuleB, + b2Transform xfB ); + +/// Compute the contact manifold between a polygon and capsule +B2_API b2Manifold b2CollidePolygonAndCapsule( const b2Polygon* polygonA, b2Transform xfA, const b2Capsule* capsuleB, + b2Transform xfB ); + +/// Compute the contact manifold between two polygons +B2_API b2Manifold b2CollidePolygons( const b2Polygon* polygonA, b2Transform xfA, const b2Polygon* polygonB, b2Transform xfB ); + +/// Compute the contact manifold between an segment and a polygon +B2_API b2Manifold b2CollideSegmentAndPolygon( const b2Segment* segmentA, b2Transform xfA, const b2Polygon* polygonB, + b2Transform xfB ); + +/// Compute the contact manifold between a chain segment and a circle +B2_API b2Manifold b2CollideChainSegmentAndCircle( const b2ChainSegment* segmentA, b2Transform xfA, const b2Circle* circleB, + b2Transform xfB ); + +/// Compute the contact manifold between a chain segment and a capsule +B2_API b2Manifold b2CollideChainSegmentAndCapsule( const b2ChainSegment* segmentA, b2Transform xfA, const b2Capsule* capsuleB, + b2Transform xfB, b2SimplexCache* cache ); + +/// Compute the contact manifold between a chain segment and a rounded polygon +B2_API b2Manifold b2CollideChainSegmentAndPolygon( const b2ChainSegment* segmentA, b2Transform xfA, const b2Polygon* polygonB, + b2Transform xfB, b2SimplexCache* cache ); + +/**@}*/ + +/** + * @defgroup tree Dynamic Tree + * The dynamic tree is a binary AABB tree to organize and query large numbers of geometric objects + * + * Box2D uses the dynamic tree internally to sort collision shapes into a binary bounding volume hierarchy. + * This data structure may have uses in games for organizing other geometry data and may be used independently + * of Box2D rigid body simulation. + * + * A dynamic AABB tree broad-phase, inspired by Nathanael Presson's btDbvt. + * A dynamic tree arranges data in a binary tree to accelerate + * queries such as AABB queries and ray casts. Leaf nodes are proxies + * with an AABB. These are used to hold a user collision object. + * Nodes are pooled and relocatable, so I use node indices rather than pointers. + * The dynamic tree is made available for advanced users that would like to use it to organize + * spatial game data besides rigid bodies. + * @{ + */ + +/// The dynamic tree structure. This should be considered private data. +/// It is placed here for performance reasons. +typedef struct b2DynamicTree +{ + /// The tree nodes + struct b2TreeNode* nodes; + + /// The root index + int root; + + /// The number of nodes + int nodeCount; + + /// The allocated node space + int nodeCapacity; + + /// Node free list + int freeList; + + /// Number of proxies created + int proxyCount; + + /// Leaf indices for rebuild + int* leafIndices; + + /// Leaf bounding boxes for rebuild + b2AABB* leafBoxes; + + /// Leaf bounding box centers for rebuild + b2Vec2* leafCenters; + + /// Bins for sorting during rebuild + int* binIndices; + + /// Allocated space for rebuilding + int rebuildCapacity; +} b2DynamicTree; + +/// These are performance results returned by dynamic tree queries. +typedef struct b2TreeStats +{ + /// Number of internal nodes visited during the query + int nodeVisits; + + /// Number of leaf nodes visited during the query + int leafVisits; +} b2TreeStats; + +/// Constructing the tree initializes the node pool. +B2_API b2DynamicTree b2DynamicTree_Create( void ); + +/// Destroy the tree, freeing the node pool. +B2_API void b2DynamicTree_Destroy( b2DynamicTree* tree ); + +/// Create a proxy. Provide an AABB and a userData value. +B2_API int b2DynamicTree_CreateProxy( b2DynamicTree* tree, b2AABB aabb, uint64_t categoryBits, uint64_t userData ); + +/// Destroy a proxy. This asserts if the id is invalid. +B2_API void b2DynamicTree_DestroyProxy( b2DynamicTree* tree, int proxyId ); + +/// Move a proxy to a new AABB by removing and reinserting into the tree. +B2_API void b2DynamicTree_MoveProxy( b2DynamicTree* tree, int proxyId, b2AABB aabb ); + +/// Enlarge a proxy and enlarge ancestors as necessary. +B2_API void b2DynamicTree_EnlargeProxy( b2DynamicTree* tree, int proxyId, b2AABB aabb ); + +/// Modify the category bits on a proxy. This is an expensive operation. +B2_API void b2DynamicTree_SetCategoryBits( b2DynamicTree* tree, int proxyId, uint64_t categoryBits ); + +/// Get the category bits on a proxy. +B2_API uint64_t b2DynamicTree_GetCategoryBits( b2DynamicTree* tree, int proxyId ); + +/// This function receives proxies found in the AABB query. +/// @return true if the query should continue +typedef bool b2TreeQueryCallbackFcn( int proxyId, uint64_t userData, void* context ); + +/// Query an AABB for overlapping proxies. The callback class is called for each proxy that overlaps the supplied AABB. +/// @return performance data +B2_API b2TreeStats b2DynamicTree_Query( const b2DynamicTree* tree, b2AABB aabb, uint64_t maskBits, + b2TreeQueryCallbackFcn* callback, void* context ); + +/// This function receives clipped ray cast input for a proxy. The function +/// returns the new ray fraction. +/// - return a value of 0 to terminate the ray cast +/// - return a value less than input->maxFraction to clip the ray +/// - return a value of input->maxFraction to continue the ray cast without clipping +typedef float b2TreeRayCastCallbackFcn( const b2RayCastInput* input, int proxyId, uint64_t userData, void* context ); + +/// Ray cast against the proxies in the tree. This relies on the callback +/// to perform a exact ray cast in the case were the proxy contains a shape. +/// The callback also performs the any collision filtering. This has performance +/// roughly equal to k * log(n), where k is the number of collisions and n is the +/// number of proxies in the tree. +/// Bit-wise filtering using mask bits can greatly improve performance in some scenarios. +/// However, this filtering may be approximate, so the user should still apply filtering to results. +/// @param tree the dynamic tree to ray cast +/// @param input the ray cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1) +/// @param maskBits mask bit hint: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param callback a callback class that is called for each proxy that is hit by the ray +/// @param context user context that is passed to the callback +/// @return performance data +B2_API b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInput* input, uint64_t maskBits, + b2TreeRayCastCallbackFcn* callback, void* context ); + +/// This function receives clipped ray cast input for a proxy. The function +/// returns the new ray fraction. +/// - return a value of 0 to terminate the ray cast +/// - return a value less than input->maxFraction to clip the ray +/// - return a value of input->maxFraction to continue the ray cast without clipping +typedef float b2TreeShapeCastCallbackFcn( const b2ShapeCastInput* input, int proxyId, uint64_t userData, void* context ); + +/// Ray cast against the proxies in the tree. This relies on the callback +/// to perform a exact ray cast in the case were the proxy contains a shape. +/// The callback also performs the any collision filtering. This has performance +/// roughly equal to k * log(n), where k is the number of collisions and n is the +/// number of proxies in the tree. +/// @param tree the dynamic tree to ray cast +/// @param input the ray cast input data. The ray extends from p1 to p1 + maxFraction * (p2 - p1). +/// @param maskBits filter bits: `bool accept = (maskBits & node->categoryBits) != 0;` +/// @param callback a callback class that is called for each proxy that is hit by the shape +/// @param context user context that is passed to the callback +/// @return performance data +B2_API b2TreeStats b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCastInput* input, uint64_t maskBits, + b2TreeShapeCastCallbackFcn* callback, void* context ); + +/// Get the height of the binary tree. +B2_API int b2DynamicTree_GetHeight( const b2DynamicTree* tree ); + +/// Get the ratio of the sum of the node areas to the root area. +B2_API float b2DynamicTree_GetAreaRatio( const b2DynamicTree* tree ); + +/// Get the bounding box that contains the entire tree +B2_API b2AABB b2DynamicTree_GetRootBounds( const b2DynamicTree* tree ); + +/// Get the number of proxies created +B2_API int b2DynamicTree_GetProxyCount( const b2DynamicTree* tree ); + +/// Rebuild the tree while retaining subtrees that haven't changed. Returns the number of boxes sorted. +B2_API int b2DynamicTree_Rebuild( b2DynamicTree* tree, bool fullBuild ); + +/// Get the number of bytes used by this tree +B2_API int b2DynamicTree_GetByteCount( const b2DynamicTree* tree ); + +/// Get proxy user data +B2_API uint64_t b2DynamicTree_GetUserData( const b2DynamicTree* tree, int proxyId ); + +/// Get the AABB of a proxy +B2_API b2AABB b2DynamicTree_GetAABB( const b2DynamicTree* tree, int proxyId ); + +/// Validate this tree. For testing. +B2_API void b2DynamicTree_Validate( const b2DynamicTree* tree ); + +/// Validate this tree has no enlarged AABBs. For testing. +B2_API void b2DynamicTree_ValidateNoEnlarged( const b2DynamicTree* tree ); + +/**@}*/ + +/** + * @defgroup character Character mover + * Character movement solver + * @{ + */ + +/// These are the collision planes returned from b2World_CollideMover +typedef struct b2PlaneResult +{ + /// The collision plane between the mover and a convex shape + b2Plane plane; + + /// Did the collision register a hit? If not this plane should be ignored. + bool hit; +} b2PlaneResult; + +/// These are collision planes that can be fed to b2SolvePlanes. Normally +/// this is assembled by the user from plane results in b2PlaneResult +typedef struct b2CollisionPlane +{ + /// The collision plane between the mover and some shape + b2Plane plane; + + /// Setting this to FLT_MAX makes the plane as rigid as possible. Lower values can + /// make the plane collision soft. Usually in meters. + float pushLimit; + + /// The push on the mover determined by b2SolvePlanes. Usually in meters. + float push; + + /// Indicates if b2ClipVector should clip against this plane. Should be false for soft collision. + bool clipVelocity; +} b2CollisionPlane; + +/// Result returned by b2SolvePlanes +typedef struct b2PlaneSolverResult +{ + /// The final position of the mover + b2Vec2 position; + + /// The number of iterations used by the plane solver. For diagnostics. + int iterationCount; +} b2PlaneSolverResult; + +/// Solves the position of a mover that satisfies the given collision planes. +/// @param position this must be the position used to generate the collision planes +/// @param planes the collision planes +/// @param count the number of collision planes +B2_API b2PlaneSolverResult b2SolvePlanes( b2Vec2 position, b2CollisionPlane* planes, int count ); + +/// Clips the velocity against the given collision planes. Planes with zero push or clipVelocity +/// set to false are skipped. +B2_API b2Vec2 b2ClipVector( b2Vec2 vector, const b2CollisionPlane* planes, int count ); + +/**@}*/ diff --git a/3rdparty/box2d/include/box2d/id.h b/3rdparty/box2d/include/box2d/id.h new file mode 100644 index 000000000000..4daaaf2174aa --- /dev/null +++ b/3rdparty/box2d/include/box2d/id.h @@ -0,0 +1,144 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "base.h" + +#include + +/** + * @defgroup id Ids + * These ids serve as handles to internal Box2D objects. + * These should be considered opaque data and passed by value. + * Include this header if you need the id types and not the whole Box2D API. + * All ids are considered null if initialized to zero. + * + * For example in C++: + * + * @code{.cxx} + * b2WorldId worldId = {}; + * @endcode + * + * Or in C: + * + * @code{.c} + * b2WorldId worldId = {0}; + * @endcode + * + * These are both considered null. + * + * @warning Do not use the internals of these ids. They are subject to change. Ids should be treated as opaque objects. + * @warning You should use ids to access objects in Box2D. Do not access files within the src folder. Such usage is unsupported. + * @{ + */ + +/// World id references a world instance. This should be treated as an opaque handle. +typedef struct b2WorldId +{ + uint16_t index1; + uint16_t generation; +} b2WorldId; + +/// Body id references a body instance. This should be treated as an opaque handle. +typedef struct b2BodyId +{ + int32_t index1; + uint16_t world0; + uint16_t generation; +} b2BodyId; + +/// Shape id references a shape instance. This should be treated as an opaque handle. +typedef struct b2ShapeId +{ + int32_t index1; + uint16_t world0; + uint16_t generation; +} b2ShapeId; + +/// Chain id references a chain instances. This should be treated as an opaque handle. +typedef struct b2ChainId +{ + int32_t index1; + uint16_t world0; + uint16_t generation; +} b2ChainId; + +/// Joint id references a joint instance. This should be treated as an opaque handle. +typedef struct b2JointId +{ + int32_t index1; + uint16_t world0; + uint16_t generation; +} b2JointId; + +/// Use these to make your identifiers null. +/// You may also use zero initialization to get null. +static const b2WorldId b2_nullWorldId = B2_ZERO_INIT; +static const b2BodyId b2_nullBodyId = B2_ZERO_INIT; +static const b2ShapeId b2_nullShapeId = B2_ZERO_INIT; +static const b2ChainId b2_nullChainId = B2_ZERO_INIT; +static const b2JointId b2_nullJointId = B2_ZERO_INIT; + +/// Macro to determine if any id is null. +#define B2_IS_NULL( id ) ( id.index1 == 0 ) + +/// Macro to determine if any id is non-null. +#define B2_IS_NON_NULL( id ) ( id.index1 != 0 ) + +/// Compare two ids for equality. Doesn't work for b2WorldId. +#define B2_ID_EQUALS( id1, id2 ) ( id1.index1 == id2.index1 && id1.world0 == id2.world0 && id1.generation == id2.generation ) + +/// Store a body id into a uint64_t. +B2_INLINE uint64_t b2StoreBodyId( b2BodyId id ) +{ + return ( (uint64_t)id.index1 << 32 ) | ( (uint64_t)id.world0 ) << 16 | (uint64_t)id.generation; +} + +/// Load a uint64_t into a body id. +B2_INLINE b2BodyId b2LoadBodyId( uint64_t x ) +{ + b2BodyId id = { (int32_t)( x >> 32 ), (uint16_t)( x >> 16 ), (uint16_t)( x ) }; + return id; +} + +/// Store a shape id into a uint64_t. +B2_INLINE uint64_t b2StoreShapeId( b2ShapeId id ) +{ + return ( (uint64_t)id.index1 << 32 ) | ( (uint64_t)id.world0 ) << 16 | (uint64_t)id.generation; +} + +/// Load a uint64_t into a shape id. +B2_INLINE b2ShapeId b2LoadShapeId( uint64_t x ) +{ + b2ShapeId id = { (int32_t)( x >> 32 ), (uint16_t)( x >> 16 ), (uint16_t)( x ) }; + return id; +} + +/// Store a chain id into a uint64_t. +B2_INLINE uint64_t b2StoreChainId( b2ChainId id ) +{ + return ( (uint64_t)id.index1 << 32 ) | ( (uint64_t)id.world0 ) << 16 | (uint64_t)id.generation; +} + +/// Load a uint64_t into a chain id. +B2_INLINE b2ChainId b2LoadChainId( uint64_t x ) +{ + b2ChainId id = { (int32_t)( x >> 32 ), (uint16_t)( x >> 16 ), (uint16_t)( x ) }; + return id; +} + +/// Store a joint id into a uint64_t. +B2_INLINE uint64_t b2StoreJointId( b2JointId id ) +{ + return ( (uint64_t)id.index1 << 32 ) | ( (uint64_t)id.world0 ) << 16 | (uint64_t)id.generation; +} + +/// Load a uint64_t into a joint id. +B2_INLINE b2JointId b2LoadJointId( uint64_t x ) +{ + b2JointId id = { (int32_t)( x >> 32 ), (uint16_t)( x >> 16 ), (uint16_t)( x ) }; + return id; +} + +/**@}*/ diff --git a/3rdparty/box2d/include/box2d/math_functions.h b/3rdparty/box2d/include/box2d/math_functions.h new file mode 100644 index 000000000000..88597d8c9a28 --- /dev/null +++ b/3rdparty/box2d/include/box2d/math_functions.h @@ -0,0 +1,761 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "base.h" + +#include +#include +#include + +/** + * @defgroup math Math + * @brief Vector math types and functions + * @{ + */ + +/// 2D vector +/// This can be used to represent a point or free vector +typedef struct b2Vec2 +{ + /// coordinates + float x, y; +} b2Vec2; + +/// Cosine and sine pair +/// This uses a custom implementation designed for cross-platform determinism +typedef struct b2CosSin +{ + /// cosine and sine + float cosine; + float sine; +} b2CosSin; + +/// 2D rotation +/// This is similar to using a complex number for rotation +typedef struct b2Rot +{ + /// cosine and sine + float c, s; +} b2Rot; + +/// A 2D rigid transform +typedef struct b2Transform +{ + b2Vec2 p; + b2Rot q; +} b2Transform; + +/// A 2-by-2 Matrix +typedef struct b2Mat22 +{ + /// columns + b2Vec2 cx, cy; +} b2Mat22; + +/// Axis-aligned bounding box +typedef struct b2AABB +{ + b2Vec2 lowerBound; + b2Vec2 upperBound; +} b2AABB; + +/// separation = dot(normal, point) - offset +typedef struct b2Plane +{ + b2Vec2 normal; + float offset; +} b2Plane; + +/**@}*/ + +/** + * @addtogroup math + * @{ + */ + +/// https://en.wikipedia.org/wiki/Pi +#define B2_PI 3.14159265359f + +static const b2Vec2 b2Vec2_zero = { 0.0f, 0.0f }; +static const b2Rot b2Rot_identity = { 1.0f, 0.0f }; +static const b2Transform b2Transform_identity = { { 0.0f, 0.0f }, { 1.0f, 0.0f } }; +static const b2Mat22 b2Mat22_zero = { { 0.0f, 0.0f }, { 0.0f, 0.0f } }; + +/// @return the minimum of two integers +B2_INLINE int b2MinInt( int a, int b ) +{ + return a < b ? a : b; +} + +/// @return the maximum of two integers +B2_INLINE int b2MaxInt( int a, int b ) +{ + return a > b ? a : b; +} + +/// @return the absolute value of an integer +B2_INLINE int b2AbsInt( int a ) +{ + return a < 0 ? -a : a; +} + +/// @return an integer clamped between a lower and upper bound +B2_INLINE int b2ClampInt( int a, int lower, int upper ) +{ + return a < lower ? lower : ( a > upper ? upper : a ); +} + +/// @return the minimum of two floats +B2_INLINE float b2MinFloat( float a, float b ) +{ + return a < b ? a : b; +} + +/// @return the maximum of two floats +B2_INLINE float b2MaxFloat( float a, float b ) +{ + return a > b ? a : b; +} + +/// @return the absolute value of a float +B2_INLINE float b2AbsFloat( float a ) +{ + return a < 0 ? -a : a; +} + +/// @return a float clamped between a lower and upper bound +B2_INLINE float b2ClampFloat( float a, float lower, float upper ) +{ + return a < lower ? lower : ( a > upper ? upper : a ); +} + +/// Compute an approximate arctangent in the range [-pi, pi] +/// This is hand coded for cross-platform determinism. The atan2f +/// function in the standard library is not cross-platform deterministic. +/// Accurate to around 0.0023 degrees +B2_API float b2Atan2( float y, float x ); + +/// Compute the cosine and sine of an angle in radians. Implemented +/// for cross-platform determinism. +B2_API b2CosSin b2ComputeCosSin( float radians ); + +/// Vector dot product +B2_INLINE float b2Dot( b2Vec2 a, b2Vec2 b ) +{ + return a.x * b.x + a.y * b.y; +} + +/// Vector cross product. In 2D this yields a scalar. +B2_INLINE float b2Cross( b2Vec2 a, b2Vec2 b ) +{ + return a.x * b.y - a.y * b.x; +} + +/// Perform the cross product on a vector and a scalar. In 2D this produces a vector. +B2_INLINE b2Vec2 b2CrossVS( b2Vec2 v, float s ) +{ + return B2_LITERAL( b2Vec2 ){ s * v.y, -s * v.x }; +} + +/// Perform the cross product on a scalar and a vector. In 2D this produces a vector. +B2_INLINE b2Vec2 b2CrossSV( float s, b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ -s * v.y, s * v.x }; +} + +/// Get a left pointing perpendicular vector. Equivalent to b2CrossSV(1.0f, v) +B2_INLINE b2Vec2 b2LeftPerp( b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ -v.y, v.x }; +} + +/// Get a right pointing perpendicular vector. Equivalent to b2CrossVS(v, 1.0f) +B2_INLINE b2Vec2 b2RightPerp( b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ v.y, -v.x }; +} + +/// Vector addition +B2_INLINE b2Vec2 b2Add( b2Vec2 a, b2Vec2 b ) +{ + return B2_LITERAL( b2Vec2 ){ a.x + b.x, a.y + b.y }; +} + +/// Vector subtraction +B2_INLINE b2Vec2 b2Sub( b2Vec2 a, b2Vec2 b ) +{ + return B2_LITERAL( b2Vec2 ){ a.x - b.x, a.y - b.y }; +} + +/// Vector negation +B2_INLINE b2Vec2 b2Neg( b2Vec2 a ) +{ + return B2_LITERAL( b2Vec2 ){ -a.x, -a.y }; +} + +/// Vector linear interpolation +/// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ +B2_INLINE b2Vec2 b2Lerp( b2Vec2 a, b2Vec2 b, float t ) +{ + return B2_LITERAL( b2Vec2 ){ ( 1.0f - t ) * a.x + t * b.x, ( 1.0f - t ) * a.y + t * b.y }; +} + +/// Component-wise multiplication +B2_INLINE b2Vec2 b2Mul( b2Vec2 a, b2Vec2 b ) +{ + return B2_LITERAL( b2Vec2 ){ a.x * b.x, a.y * b.y }; +} + +/// Multiply a scalar and vector +B2_INLINE b2Vec2 b2MulSV( float s, b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ s * v.x, s * v.y }; +} + +/// a + s * b +B2_INLINE b2Vec2 b2MulAdd( b2Vec2 a, float s, b2Vec2 b ) +{ + return B2_LITERAL( b2Vec2 ){ a.x + s * b.x, a.y + s * b.y }; +} + +/// a - s * b +B2_INLINE b2Vec2 b2MulSub( b2Vec2 a, float s, b2Vec2 b ) +{ + return B2_LITERAL( b2Vec2 ){ a.x - s * b.x, a.y - s * b.y }; +} + +/// Component-wise absolute vector +B2_INLINE b2Vec2 b2Abs( b2Vec2 a ) +{ + b2Vec2 b; + b.x = b2AbsFloat( a.x ); + b.y = b2AbsFloat( a.y ); + return b; +} + +/// Component-wise minimum vector +B2_INLINE b2Vec2 b2Min( b2Vec2 a, b2Vec2 b ) +{ + b2Vec2 c; + c.x = b2MinFloat( a.x, b.x ); + c.y = b2MinFloat( a.y, b.y ); + return c; +} + +/// Component-wise maximum vector +B2_INLINE b2Vec2 b2Max( b2Vec2 a, b2Vec2 b ) +{ + b2Vec2 c; + c.x = b2MaxFloat( a.x, b.x ); + c.y = b2MaxFloat( a.y, b.y ); + return c; +} + +/// Component-wise clamp vector v into the range [a, b] +B2_INLINE b2Vec2 b2Clamp( b2Vec2 v, b2Vec2 a, b2Vec2 b ) +{ + b2Vec2 c; + c.x = b2ClampFloat( v.x, a.x, b.x ); + c.y = b2ClampFloat( v.y, a.y, b.y ); + return c; +} + +/// Get the length of this vector (the norm) +B2_INLINE float b2Length( b2Vec2 v ) +{ + return sqrtf( v.x * v.x + v.y * v.y ); +} + +/// Get the distance between two points +B2_INLINE float b2Distance( b2Vec2 a, b2Vec2 b ) +{ + float dx = b.x - a.x; + float dy = b.y - a.y; + return sqrtf( dx * dx + dy * dy ); +} + +/// Convert a vector into a unit vector if possible, otherwise returns the zero vector. +/// todo MSVC is not inlining this function in several places per warning 4710 +B2_INLINE b2Vec2 b2Normalize( b2Vec2 v ) +{ + float length = sqrtf( v.x * v.x + v.y * v.y ); + if ( length < FLT_EPSILON ) + { + return B2_LITERAL( b2Vec2 ){ 0.0f, 0.0f }; + } + + float invLength = 1.0f / length; + b2Vec2 n = { invLength * v.x, invLength * v.y }; + return n; +} + +/// Determines if the provided vector is normalized (norm(a) == 1). +B2_INLINE bool b2IsNormalized( b2Vec2 a ) +{ + float aa = b2Dot( a, a ); + return b2AbsFloat( 1.0f - aa ) < 10.0f * FLT_EPSILON; +} + +/// Convert a vector into a unit vector if possible, otherwise returns the zero vector. Also +/// outputs the length. +B2_INLINE b2Vec2 b2GetLengthAndNormalize( float* length, b2Vec2 v ) +{ + *length = sqrtf( v.x * v.x + v.y * v.y ); + if ( *length < FLT_EPSILON ) + { + return B2_LITERAL( b2Vec2 ){ 0.0f, 0.0f }; + } + + float invLength = 1.0f / *length; + b2Vec2 n = { invLength * v.x, invLength * v.y }; + return n; +} + +/// Normalize rotation +B2_INLINE b2Rot b2NormalizeRot( b2Rot q ) +{ + float mag = sqrtf( q.s * q.s + q.c * q.c ); + float invMag = mag > 0.0 ? 1.0f / mag : 0.0f; + b2Rot qn = { q.c * invMag, q.s * invMag }; + return qn; +} + +/// Integrate rotation from angular velocity +/// @param q1 initial rotation +/// @param deltaAngle the angular displacement in radians +B2_INLINE b2Rot b2IntegrateRotation( b2Rot q1, float deltaAngle ) +{ + // dc/dt = -omega * sin(t) + // ds/dt = omega * cos(t) + // c2 = c1 - omega * h * s1 + // s2 = s1 + omega * h * c1 + b2Rot q2 = { q1.c - deltaAngle * q1.s, q1.s + deltaAngle * q1.c }; + float mag = sqrtf( q2.s * q2.s + q2.c * q2.c ); + float invMag = mag > 0.0 ? 1.0f / mag : 0.0f; + b2Rot qn = { q2.c * invMag, q2.s * invMag }; + return qn; +} + +/// Get the length squared of this vector +B2_INLINE float b2LengthSquared( b2Vec2 v ) +{ + return v.x * v.x + v.y * v.y; +} + +/// Get the distance squared between points +B2_INLINE float b2DistanceSquared( b2Vec2 a, b2Vec2 b ) +{ + b2Vec2 c = { b.x - a.x, b.y - a.y }; + return c.x * c.x + c.y * c.y; +} + +/// Make a rotation using an angle in radians +B2_INLINE b2Rot b2MakeRot( float radians ) +{ + b2CosSin cs = b2ComputeCosSin( radians ); + return B2_LITERAL( b2Rot ){ cs.cosine, cs.sine }; +} + +/// Compute the rotation between two unit vectors +B2_API b2Rot b2ComputeRotationBetweenUnitVectors( b2Vec2 v1, b2Vec2 v2 ); + +/// Is this rotation normalized? +B2_INLINE bool b2IsNormalizedRot( b2Rot q ) +{ + // larger tolerance due to failure on mingw 32-bit + float qq = q.s * q.s + q.c * q.c; + return 1.0f - 0.0006f < qq && qq < 1.0f + 0.0006f; +} + +/// Normalized linear interpolation +/// https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ +/// https://web.archive.org/web/20170825184056/http://number-none.com/product/Understanding%20Slerp,%20Then%20Not%20Using%20It/ +B2_INLINE b2Rot b2NLerp( b2Rot q1, b2Rot q2, float t ) +{ + float omt = 1.0f - t; + b2Rot q = { + omt * q1.c + t * q2.c, + omt * q1.s + t * q2.s, + }; + + float mag = sqrtf( q.s * q.s + q.c * q.c ); + float invMag = mag > 0.0 ? 1.0f / mag : 0.0f; + b2Rot qn = { q.c * invMag, q.s * invMag }; + return qn; +} + +/// Compute the angular velocity necessary to rotate between two rotations over a give time +/// @param q1 initial rotation +/// @param q2 final rotation +/// @param inv_h inverse time step +B2_INLINE float b2ComputeAngularVelocity( b2Rot q1, b2Rot q2, float inv_h ) +{ + // ds/dt = omega * cos(t) + // dc/dt = -omega * sin(t) + // s2 = s1 + omega * h * c1 + // c2 = c1 - omega * h * s1 + + // omega * h * s1 = c1 - c2 + // omega * h * c1 = s2 - s1 + // omega * h = (c1 - c2) * s1 + (s2 - s1) * c1; + // omega * h = s1 * c1 - c2 * s1 + s2 * c1 - s1 * c1 + // omega * h = s2 * c1 - c2 * s1 = sin(a2 - a1) ~= a2 - a1 for small delta + float omega = inv_h * ( q2.s * q1.c - q2.c * q1.s ); + return omega; +} + +/// Get the angle in radians in the range [-pi, pi] +B2_INLINE float b2Rot_GetAngle( b2Rot q ) +{ + return b2Atan2( q.s, q.c ); +} + +/// Get the x-axis +B2_INLINE b2Vec2 b2Rot_GetXAxis( b2Rot q ) +{ + b2Vec2 v = { q.c, q.s }; + return v; +} + +/// Get the y-axis +B2_INLINE b2Vec2 b2Rot_GetYAxis( b2Rot q ) +{ + b2Vec2 v = { -q.s, q.c }; + return v; +} + +/// Multiply two rotations: q * r +B2_INLINE b2Rot b2MulRot( b2Rot q, b2Rot r ) +{ + // [qc -qs] * [rc -rs] = [qc*rc-qs*rs -qc*rs-qs*rc] + // [qs qc] [rs rc] [qs*rc+qc*rs -qs*rs+qc*rc] + // s(q + r) = qs * rc + qc * rs + // c(q + r) = qc * rc - qs * rs + b2Rot qr; + qr.s = q.s * r.c + q.c * r.s; + qr.c = q.c * r.c - q.s * r.s; + return qr; +} + +/// Transpose multiply two rotations: qT * r +B2_INLINE b2Rot b2InvMulRot( b2Rot q, b2Rot r ) +{ + // [ qc qs] * [rc -rs] = [qc*rc+qs*rs -qc*rs+qs*rc] + // [-qs qc] [rs rc] [-qs*rc+qc*rs qs*rs+qc*rc] + // s(q - r) = qc * rs - qs * rc + // c(q - r) = qc * rc + qs * rs + b2Rot qr; + qr.s = q.c * r.s - q.s * r.c; + qr.c = q.c * r.c + q.s * r.s; + return qr; +} + +/// relative angle between b and a (rot_b * inv(rot_a)) +B2_INLINE float b2RelativeAngle( b2Rot b, b2Rot a ) +{ + // sin(b - a) = bs * ac - bc * as + // cos(b - a) = bc * ac + bs * as + float s = b.s * a.c - b.c * a.s; + float c = b.c * a.c + b.s * a.s; + return b2Atan2( s, c ); +} + +/// Convert an angle in the range [-2*pi, 2*pi] into the range [-pi, pi] +B2_INLINE float b2UnwindAngle( float radians ) +{ + if ( radians < -B2_PI ) + { + return radians + 2.0f * B2_PI; + } + else if ( radians > B2_PI ) + { + return radians - 2.0f * B2_PI; + } + + return radians; +} + +/// Convert any into the range [-pi, pi] (slow) +B2_INLINE float b2UnwindLargeAngle( float radians ) +{ + while ( radians > B2_PI ) + { + radians -= 2.0f * B2_PI; + } + + while ( radians < -B2_PI ) + { + radians += 2.0f * B2_PI; + } + + return radians; +} + +/// Rotate a vector +B2_INLINE b2Vec2 b2RotateVector( b2Rot q, b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ q.c * v.x - q.s * v.y, q.s * v.x + q.c * v.y }; +} + +/// Inverse rotate a vector +B2_INLINE b2Vec2 b2InvRotateVector( b2Rot q, b2Vec2 v ) +{ + return B2_LITERAL( b2Vec2 ){ q.c * v.x + q.s * v.y, -q.s * v.x + q.c * v.y }; +} + +/// Transform a point (e.g. local space to world space) +B2_INLINE b2Vec2 b2TransformPoint( b2Transform t, const b2Vec2 p ) +{ + float x = ( t.q.c * p.x - t.q.s * p.y ) + t.p.x; + float y = ( t.q.s * p.x + t.q.c * p.y ) + t.p.y; + + return B2_LITERAL( b2Vec2 ){ x, y }; +} + +/// Inverse transform a point (e.g. world space to local space) +B2_INLINE b2Vec2 b2InvTransformPoint( b2Transform t, const b2Vec2 p ) +{ + float vx = p.x - t.p.x; + float vy = p.y - t.p.y; + return B2_LITERAL( b2Vec2 ){ t.q.c * vx + t.q.s * vy, -t.q.s * vx + t.q.c * vy }; +} + +/// Multiply two transforms. If the result is applied to a point p local to frame B, +/// the transform would first convert p to a point local to frame A, then into a point +/// in the world frame. +/// v2 = A.q.Rot(B.q.Rot(v1) + B.p) + A.p +/// = (A.q * B.q).Rot(v1) + A.q.Rot(B.p) + A.p +B2_INLINE b2Transform b2MulTransforms( b2Transform A, b2Transform B ) +{ + b2Transform C; + C.q = b2MulRot( A.q, B.q ); + C.p = b2Add( b2RotateVector( A.q, B.p ), A.p ); + return C; +} + +/// Creates a transform that converts a local point in frame B to a local point in frame A. +/// v2 = A.q' * (B.q * v1 + B.p - A.p) +/// = A.q' * B.q * v1 + A.q' * (B.p - A.p) +B2_INLINE b2Transform b2InvMulTransforms( b2Transform A, b2Transform B ) +{ + b2Transform C; + C.q = b2InvMulRot( A.q, B.q ); + C.p = b2InvRotateVector( A.q, b2Sub( B.p, A.p ) ); + return C; +} + +/// Multiply a 2-by-2 matrix times a 2D vector +B2_INLINE b2Vec2 b2MulMV( b2Mat22 A, b2Vec2 v ) +{ + b2Vec2 u = { + A.cx.x * v.x + A.cy.x * v.y, + A.cx.y * v.x + A.cy.y * v.y, + }; + return u; +} + +/// Get the inverse of a 2-by-2 matrix +B2_INLINE b2Mat22 b2GetInverse22( b2Mat22 A ) +{ + float a = A.cx.x, b = A.cy.x, c = A.cx.y, d = A.cy.y; + float det = a * d - b * c; + if ( det != 0.0f ) + { + det = 1.0f / det; + } + + b2Mat22 B = { + { det * d, -det * c }, + { -det * b, det * a }, + }; + return B; +} + +/// Solve A * x = b, where b is a column vector. This is more efficient +/// than computing the inverse in one-shot cases. +B2_INLINE b2Vec2 b2Solve22( b2Mat22 A, b2Vec2 b ) +{ + float a11 = A.cx.x, a12 = A.cy.x, a21 = A.cx.y, a22 = A.cy.y; + float det = a11 * a22 - a12 * a21; + if ( det != 0.0f ) + { + det = 1.0f / det; + } + b2Vec2 x = { det * ( a22 * b.x - a12 * b.y ), det * ( a11 * b.y - a21 * b.x ) }; + return x; +} + +/// Does a fully contain b +B2_INLINE bool b2AABB_Contains( b2AABB a, b2AABB b ) +{ + bool s = true; + s = s && a.lowerBound.x <= b.lowerBound.x; + s = s && a.lowerBound.y <= b.lowerBound.y; + s = s && b.upperBound.x <= a.upperBound.x; + s = s && b.upperBound.y <= a.upperBound.y; + return s; +} + +/// Get the center of the AABB. +B2_INLINE b2Vec2 b2AABB_Center( b2AABB a ) +{ + b2Vec2 b = { 0.5f * ( a.lowerBound.x + a.upperBound.x ), 0.5f * ( a.lowerBound.y + a.upperBound.y ) }; + return b; +} + +/// Get the extents of the AABB (half-widths). +B2_INLINE b2Vec2 b2AABB_Extents( b2AABB a ) +{ + b2Vec2 b = { 0.5f * ( a.upperBound.x - a.lowerBound.x ), 0.5f * ( a.upperBound.y - a.lowerBound.y ) }; + return b; +} + +/// Union of two AABBs +B2_INLINE b2AABB b2AABB_Union( b2AABB a, b2AABB b ) +{ + b2AABB c; + c.lowerBound.x = b2MinFloat( a.lowerBound.x, b.lowerBound.x ); + c.lowerBound.y = b2MinFloat( a.lowerBound.y, b.lowerBound.y ); + c.upperBound.x = b2MaxFloat( a.upperBound.x, b.upperBound.x ); + c.upperBound.y = b2MaxFloat( a.upperBound.y, b.upperBound.y ); + return c; +} + +/// Compute the bounding box of an array of circles +B2_INLINE b2AABB b2MakeAABB( const b2Vec2* points, int count, float radius ) +{ + B2_ASSERT( count > 0 ); + b2AABB a = { points[0], points[0] }; + for ( int i = 1; i < count; ++i ) + { + a.lowerBound = b2Min( a.lowerBound, points[i] ); + a.upperBound = b2Max( a.upperBound, points[i] ); + } + + b2Vec2 r = { radius, radius }; + a.lowerBound = b2Sub( a.lowerBound, r ); + a.upperBound = b2Add( a.upperBound, r ); + + return a; +} + +/// Signed separation of a point from a plane +B2_INLINE float b2PlaneSeparation( b2Plane plane, b2Vec2 point ) +{ + return b2Dot( plane.normal, point ) - plane.offset; +} + +/// Is this a valid number? Not NaN or infinity. +B2_API bool b2IsValidFloat( float a ); + +/// Is this a valid vector? Not NaN or infinity. +B2_API bool b2IsValidVec2( b2Vec2 v ); + +/// Is this a valid rotation? Not NaN or infinity. Is normalized. +B2_API bool b2IsValidRotation( b2Rot q ); + +/// Is this a valid bounding box? Not Nan or infinity. Upper bound greater than or equal to lower bound. +B2_API bool b2IsValidAABB( b2AABB aabb ); + +/// Is this a valid plane? Normal is a unit vector. Not Nan or infinity. +B2_API bool b2IsValidPlane( b2Plane a ); + +/// Box2D bases all length units on meters, but you may need different units for your game. +/// You can set this value to use different units. This should be done at application startup +/// and only modified once. Default value is 1. +/// For example, if your game uses pixels for units you can use pixels for all length values +/// sent to Box2D. There should be no extra cost. However, Box2D has some internal tolerances +/// and thresholds that have been tuned for meters. By calling this function, Box2D is able +/// to adjust those tolerances and thresholds to improve accuracy. +/// A good rule of thumb is to pass the height of your player character to this function. So +/// if your player character is 32 pixels high, then pass 32 to this function. Then you may +/// confidently use pixels for all the length values sent to Box2D. All length values returned +/// from Box2D will also be pixels because Box2D does not do any scaling internally. +/// However, you are now on the hook for coming up with good values for gravity, density, and +/// forces. +/// @warning This must be modified before any calls to Box2D +B2_API void b2SetLengthUnitsPerMeter( float lengthUnits ); + +/// Get the current length units per meter. +B2_API float b2GetLengthUnitsPerMeter( void ); + +/**@}*/ + +/** + * @defgroup math_cpp C++ Math + * @brief Math operator overloads for C++ + * + * See math_functions.h for details. + * @{ + */ + +#ifdef __cplusplus + +/// Unary add one vector to another +inline void operator+=( b2Vec2& a, b2Vec2 b ) +{ + a.x += b.x; + a.y += b.y; +} + +/// Unary subtract one vector from another +inline void operator-=( b2Vec2& a, b2Vec2 b ) +{ + a.x -= b.x; + a.y -= b.y; +} + +/// Unary multiply a vector by a scalar +inline void operator*=( b2Vec2& a, float b ) +{ + a.x *= b; + a.y *= b; +} + +/// Unary negate a vector +inline b2Vec2 operator-( b2Vec2 a ) +{ + return { -a.x, -a.y }; +} + +/// Binary vector addition +inline b2Vec2 operator+( b2Vec2 a, b2Vec2 b ) +{ + return { a.x + b.x, a.y + b.y }; +} + +/// Binary vector subtraction +inline b2Vec2 operator-( b2Vec2 a, b2Vec2 b ) +{ + return { a.x - b.x, a.y - b.y }; +} + +/// Binary scalar and vector multiplication +inline b2Vec2 operator*( float a, b2Vec2 b ) +{ + return { a * b.x, a * b.y }; +} + +/// Binary scalar and vector multiplication +inline b2Vec2 operator*( b2Vec2 a, float b ) +{ + return { a.x * b, a.y * b }; +} + +/// Binary vector equality +inline bool operator==( b2Vec2 a, b2Vec2 b ) +{ + return a.x == b.x && a.y == b.y; +} + +/// Binary vector inequality +inline bool operator!=( b2Vec2 a, b2Vec2 b ) +{ + return a.x != b.x || a.y != b.y; +} + +#endif + +/**@}*/ diff --git a/3rdparty/box2d/include/box2d/types.h b/3rdparty/box2d/include/box2d/types.h new file mode 100644 index 000000000000..b4a683f848df --- /dev/null +++ b/3rdparty/box2d/include/box2d/types.h @@ -0,0 +1,1457 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "base.h" +#include "collision.h" +#include "id.h" +#include "math_functions.h" + +#include +#include + +#define B2_DEFAULT_CATEGORY_BITS 1 +#define B2_DEFAULT_MASK_BITS UINT64_MAX + +/// Task interface +/// This is prototype for a Box2D task. Your task system is expected to invoke the Box2D task with these arguments. +/// The task spans a range of the parallel-for: [startIndex, endIndex) +/// The worker index must correctly identify each worker in the user thread pool, expected in [0, workerCount). +/// A worker must only exist on only one thread at a time and is analogous to the thread index. +/// The task context is the context pointer sent from Box2D when it is enqueued. +/// The startIndex and endIndex are expected in the range [0, itemCount) where itemCount is the argument to b2EnqueueTaskCallback +/// below. Box2D expects startIndex < endIndex and will execute a loop like this: +/// +/// @code{.c} +/// for (int i = startIndex; i < endIndex; ++i) +/// { +/// DoWork(); +/// } +/// @endcode +/// @ingroup world +typedef void b2TaskCallback( int startIndex, int endIndex, uint32_t workerIndex, void* taskContext ); + +/// These functions can be provided to Box2D to invoke a task system. These are designed to work well with enkiTS. +/// Returns a pointer to the user's task object. May be nullptr. A nullptr indicates to Box2D that the work was executed +/// serially within the callback and there is no need to call b2FinishTaskCallback. +/// The itemCount is the number of Box2D work items that are to be partitioned among workers by the user's task system. +/// This is essentially a parallel-for. The minRange parameter is a suggestion of the minimum number of items to assign +/// per worker to reduce overhead. For example, suppose the task is small and that itemCount is 16. A minRange of 8 suggests +/// that your task system should split the work items among just two workers, even if you have more available. +/// In general the range [startIndex, endIndex) send to b2TaskCallback should obey: +/// endIndex - startIndex >= minRange +/// The exception of course is when itemCount < minRange. +/// @ingroup world +typedef void* b2EnqueueTaskCallback( b2TaskCallback* task, int itemCount, int minRange, void* taskContext, void* userContext ); + +/// Finishes a user task object that wraps a Box2D task. +/// @ingroup world +typedef void b2FinishTaskCallback( void* userTask, void* userContext ); + +/// Optional friction mixing callback. This intentionally provides no context objects because this is called +/// from a worker thread. +/// @warning This function should not attempt to modify Box2D state or user application state. +/// @ingroup world +typedef float b2FrictionCallback( float frictionA, int userMaterialIdA, float frictionB, int userMaterialIdB ); + +/// Optional restitution mixing callback. This intentionally provides no context objects because this is called +/// from a worker thread. +/// @warning This function should not attempt to modify Box2D state or user application state. +/// @ingroup world +typedef float b2RestitutionCallback( float restitutionA, int userMaterialIdA, float restitutionB, int userMaterialIdB ); + +/// Result from b2World_RayCastClosest +/// @ingroup world +typedef struct b2RayResult +{ + b2ShapeId shapeId; + b2Vec2 point; + b2Vec2 normal; + float fraction; + int nodeVisits; + int leafVisits; + bool hit; +} b2RayResult; + +/// World definition used to create a simulation world. +/// Must be initialized using b2DefaultWorldDef(). +/// @ingroup world +typedef struct b2WorldDef +{ + /// Gravity vector. Box2D has no up-vector defined. + b2Vec2 gravity; + + /// Restitution speed threshold, usually in m/s. Collisions above this + /// speed have restitution applied (will bounce). + float restitutionThreshold; + + /// Threshold speed for hit events. Usually meters per second. + float hitEventThreshold; + + /// Contact stiffness. Cycles per second. Increasing this increases the speed of overlap recovery, but can introduce jitter. + float contactHertz; + + /// Contact bounciness. Non-dimensional. You can speed up overlap recovery by decreasing this with + /// the trade-off that overlap resolution becomes more energetic. + float contactDampingRatio; + + /// This parameter controls how fast overlap is resolved and usually has units of meters per second. This only + /// puts a cap on the resolution speed. The resolution speed is increased by increasing the hertz and/or + /// decreasing the damping ratio. + float maxContactPushSpeed; + + /// Joint stiffness. Cycles per second. + float jointHertz; + + /// Joint bounciness. Non-dimensional. + float jointDampingRatio; + + /// Maximum linear speed. Usually meters per second. + float maximumLinearSpeed; + + /// Optional mixing callback for friction. The default uses sqrt(frictionA * frictionB). + b2FrictionCallback* frictionCallback; + + /// Optional mixing callback for restitution. The default uses max(restitutionA, restitutionB). + b2RestitutionCallback* restitutionCallback; + + /// Can bodies go to sleep to improve performance + bool enableSleep; + + /// Enable continuous collision + bool enableContinuous; + + /// Number of workers to use with the provided task system. Box2D performs best when using only + /// performance cores and accessing a single L2 cache. Efficiency cores and hyper-threading provide + /// little benefit and may even harm performance. + /// @note Box2D does not create threads. This is the number of threads your applications has created + /// that you are allocating to b2World_Step. + /// @warning Do not modify the default value unless you are also providing a task system and providing + /// task callbacks (enqueueTask and finishTask). + int workerCount; + + /// Function to spawn tasks + b2EnqueueTaskCallback* enqueueTask; + + /// Function to finish a task + b2FinishTaskCallback* finishTask; + + /// User context that is provided to enqueueTask and finishTask + void* userTaskContext; + + /// User data + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2WorldDef; + +/// Use this to initialize your world definition +/// @ingroup world +B2_API b2WorldDef b2DefaultWorldDef( void ); + +/// The body simulation type. +/// Each body is one of these three types. The type determines how the body behaves in the simulation. +/// @ingroup body +typedef enum b2BodyType +{ + /// zero mass, zero velocity, may be manually moved + b2_staticBody = 0, + + /// zero mass, velocity set by user, moved by solver + b2_kinematicBody = 1, + + /// positive mass, velocity determined by forces, moved by solver + b2_dynamicBody = 2, + + /// number of body types + b2_bodyTypeCount, +} b2BodyType; + +/// A body definition holds all the data needed to construct a rigid body. +/// You can safely re-use body definitions. Shapes are added to a body after construction. +/// Body definitions are temporary objects used to bundle creation parameters. +/// Must be initialized using b2DefaultBodyDef(). +/// @ingroup body +typedef struct b2BodyDef +{ + /// The body type: static, kinematic, or dynamic. + b2BodyType type; + + /// The initial world position of the body. Bodies should be created with the desired position. + /// @note Creating bodies at the origin and then moving them nearly doubles the cost of body creation, especially + /// if the body is moved after shapes have been added. + b2Vec2 position; + + /// The initial world rotation of the body. Use b2MakeRot() if you have an angle. + b2Rot rotation; + + /// The initial linear velocity of the body's origin. Usually in meters per second. + b2Vec2 linearVelocity; + + /// The initial angular velocity of the body. Radians per second. + float angularVelocity; + + /// Linear damping is used to reduce the linear velocity. The damping parameter + /// can be larger than 1 but the damping effect becomes sensitive to the + /// time step when the damping parameter is large. + /// Generally linear damping is undesirable because it makes objects move slowly + /// as if they are floating. + float linearDamping; + + /// Angular damping is used to reduce the angular velocity. The damping parameter + /// can be larger than 1.0f but the damping effect becomes sensitive to the + /// time step when the damping parameter is large. + /// Angular damping can be use slow down rotating bodies. + float angularDamping; + + /// Scale the gravity applied to this body. Non-dimensional. + float gravityScale; + + /// Sleep speed threshold, default is 0.05 meters per second + float sleepThreshold; + + /// Optional body name for debugging. Up to 31 characters (excluding null termination) + const char* name; + + /// Use this to store application specific body data. + void* userData; + + /// Set this flag to false if this body should never fall asleep. + bool enableSleep; + + /// Is this body initially awake or sleeping? + bool isAwake; + + /// Should this body be prevented from rotating? Useful for characters. + bool fixedRotation; + + /// Treat this body as high speed object that performs continuous collision detection + /// against dynamic and kinematic bodies, but not other bullet bodies. + /// @warning Bullets should be used sparingly. They are not a solution for general dynamic-versus-dynamic + /// continuous collision. They may interfere with joint constraints. + bool isBullet; + + /// Used to disable a body. A disabled body does not move or collide. + bool isEnabled; + + /// This allows this body to bypass rotational speed limits. Should only be used + /// for circular objects, like wheels. + bool allowFastRotation; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2BodyDef; + +/// Use this to initialize your body definition +/// @ingroup body +B2_API b2BodyDef b2DefaultBodyDef( void ); + +/// This is used to filter collision on shapes. It affects shape-vs-shape collision +/// and shape-versus-query collision (such as b2World_CastRay). +/// @ingroup shape +typedef struct b2Filter +{ + /// The collision category bits. Normally you would just set one bit. The category bits should + /// represent your application object types. For example: + /// @code{.cpp} + /// enum MyCategories + /// { + /// Static = 0x00000001, + /// Dynamic = 0x00000002, + /// Debris = 0x00000004, + /// Player = 0x00000008, + /// // etc + /// }; + /// @endcode + uint64_t categoryBits; + + /// The collision mask bits. This states the categories that this + /// shape would accept for collision. + /// For example, you may want your player to only collide with static objects + /// and other players. + /// @code{.c} + /// maskBits = Static | Player; + /// @endcode + uint64_t maskBits; + + /// Collision groups allow a certain group of objects to never collide (negative) + /// or always collide (positive). A group index of zero has no effect. Non-zero group filtering + /// always wins against the mask bits. + /// For example, you may want ragdolls to collide with other ragdolls but you don't want + /// ragdoll self-collision. In this case you would give each ragdoll a unique negative group index + /// and apply that group index to all shapes on the ragdoll. + int groupIndex; +} b2Filter; + +/// Use this to initialize your filter +/// @ingroup shape +B2_API b2Filter b2DefaultFilter( void ); + +/// The query filter is used to filter collisions between queries and shapes. For example, +/// you may want a ray-cast representing a projectile to hit players and the static environment +/// but not debris. +/// @ingroup shape +typedef struct b2QueryFilter +{ + /// The collision category bits of this query. Normally you would just set one bit. + uint64_t categoryBits; + + /// The collision mask bits. This states the shape categories that this + /// query would accept for collision. + uint64_t maskBits; +} b2QueryFilter; + +/// Use this to initialize your query filter +/// @ingroup shape +B2_API b2QueryFilter b2DefaultQueryFilter( void ); + +/// Shape type +/// @ingroup shape +typedef enum b2ShapeType +{ + /// A circle with an offset + b2_circleShape, + + /// A capsule is an extruded circle + b2_capsuleShape, + + /// A line segment + b2_segmentShape, + + /// A convex polygon + b2_polygonShape, + + /// A line segment owned by a chain shape + b2_chainSegmentShape, + + /// The number of shape types + b2_shapeTypeCount +} b2ShapeType; + +/// Surface materials allow chain shapes to have per segment surface properties. +/// @ingroup shape +typedef struct b2SurfaceMaterial +{ + /// The Coulomb (dry) friction coefficient, usually in the range [0,1]. + float friction; + + /// The coefficient of restitution (bounce) usually in the range [0,1]. + /// https://en.wikipedia.org/wiki/Coefficient_of_restitution + float restitution; + + /// The rolling resistance usually in the range [0,1]. + float rollingResistance; + + /// The tangent speed for conveyor belts + float tangentSpeed; + + /// User material identifier. This is passed with query results and to friction and restitution + /// combining functions. It is not used internally. + int userMaterialId; + + /// Custom debug draw color. + uint32_t customColor; +} b2SurfaceMaterial; + +/// Use this to initialize your surface material +/// @ingroup shape +B2_API b2SurfaceMaterial b2DefaultSurfaceMaterial( void ); + +/// Used to create a shape. +/// This is a temporary object used to bundle shape creation parameters. You may use +/// the same shape definition to create multiple shapes. +/// Must be initialized using b2DefaultShapeDef(). +/// @ingroup shape +typedef struct b2ShapeDef +{ + /// Use this to store application specific shape data. + void* userData; + + /// The surface material for this shape. + b2SurfaceMaterial material; + + /// The density, usually in kg/m^2. + /// This is not part of the surface material because this is for the interior, which may have + /// other considerations, such as being hollow. For example a wood barrel may be hollow or full of water. + float density; + + /// Collision filtering data. + b2Filter filter; + + /// A sensor shape generates overlap events but never generates a collision response. + /// Sensors do not have continuous collision. Instead, use a ray or shape cast for those scenarios. + /// Sensors still contribute to the body mass if they have non-zero density. + /// @note Sensor events are disabled by default. + /// @see enableSensorEvents + bool isSensor; + + /// Enable sensor events for this shape. This applies to sensors and non-sensors. False by default, even for sensors. + bool enableSensorEvents; + + /// Enable contact events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. False by default. + bool enableContactEvents; + + /// Enable hit events for this shape. Only applies to kinematic and dynamic bodies. Ignored for sensors. False by default. + bool enableHitEvents; + + /// Enable pre-solve contact events for this shape. Only applies to dynamic bodies. These are expensive + /// and must be carefully handled due to threading. Ignored for sensors. + bool enablePreSolveEvents; + + /// When shapes are created they will scan the environment for collision the next time step. This can significantly slow down + /// static body creation when there are many static shapes. + /// This is flag is ignored for dynamic and kinematic shapes which always invoke contact creation. + bool invokeContactCreation; + + /// Should the body update the mass properties when this shape is created. Default is true. + bool updateBodyMass; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2ShapeDef; + +/// Use this to initialize your shape definition +/// @ingroup shape +B2_API b2ShapeDef b2DefaultShapeDef( void ); + +/// Used to create a chain of line segments. This is designed to eliminate ghost collisions with some limitations. +/// - chains are one-sided +/// - chains have no mass and should be used on static bodies +/// - chains have a counter-clockwise winding order (normal points right of segment direction) +/// - chains are either a loop or open +/// - a chain must have at least 4 points +/// - the distance between any two points must be greater than B2_LINEAR_SLOP +/// - a chain shape should not self intersect (this is not validated) +/// - an open chain shape has NO COLLISION on the first and final edge +/// - you may overlap two open chains on their first three and/or last three points to get smooth collision +/// - a chain shape creates multiple line segment shapes on the body +/// https://en.wikipedia.org/wiki/Polygonal_chain +/// Must be initialized using b2DefaultChainDef(). +/// @warning Do not use chain shapes unless you understand the limitations. This is an advanced feature. +/// @ingroup shape +typedef struct b2ChainDef +{ + /// Use this to store application specific shape data. + void* userData; + + /// An array of at least 4 points. These are cloned and may be temporary. + const b2Vec2* points; + + /// The point count, must be 4 or more. + int count; + + /// Surface materials for each segment. These are cloned. + const b2SurfaceMaterial* materials; + + /// The material count. Must be 1 or count. This allows you to provide one + /// material for all segments or a unique material per segment. + int materialCount; + + /// Contact filtering data. + b2Filter filter; + + /// Indicates a closed chain formed by connecting the first and last points + bool isLoop; + + /// Enable sensors to detect this chain. False by default. + bool enableSensorEvents; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2ChainDef; + +/// Use this to initialize your chain definition +/// @ingroup shape +B2_API b2ChainDef b2DefaultChainDef( void ); + +//! @cond +/// Profiling data. Times are in milliseconds. +typedef struct b2Profile +{ + float step; + float pairs; + float collide; + float solve; + float mergeIslands; + float prepareStages; + float solveConstraints; + float prepareConstraints; + float integrateVelocities; + float warmStart; + float solveImpulses; + float integratePositions; + float relaxImpulses; + float applyRestitution; + float storeImpulses; + float splitIslands; + float transforms; + float hitEvents; + float refit; + float bullets; + float sleepIslands; + float sensors; +} b2Profile; + +/// Counters that give details of the simulation size. +typedef struct b2Counters +{ + int bodyCount; + int shapeCount; + int contactCount; + int jointCount; + int islandCount; + int stackUsed; + int staticTreeHeight; + int treeHeight; + int byteCount; + int taskCount; + int colorCounts[12]; +} b2Counters; +//! @endcond + +/// Joint type enumeration +/// +/// This is useful because all joint types use b2JointId and sometimes you +/// want to get the type of a joint. +/// @ingroup joint +typedef enum b2JointType +{ + b2_distanceJoint, + b2_filterJoint, + b2_motorJoint, + b2_mouseJoint, + b2_prismaticJoint, + b2_revoluteJoint, + b2_weldJoint, + b2_wheelJoint, +} b2JointType; + +/// Distance joint definition +/// +/// This requires defining an anchor point on both +/// bodies and the non-zero distance of the distance joint. The definition uses +/// local anchor points so that the initial configuration can violate the +/// constraint slightly. This helps when saving and loading a game. +/// @ingroup distance_joint +typedef struct b2DistanceJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// The local anchor point relative to bodyA's origin + b2Vec2 localAnchorA; + + /// The local anchor point relative to bodyB's origin + b2Vec2 localAnchorB; + + /// The rest length of this joint. Clamped to a stable minimum value. + float length; + + /// Enable the distance constraint to behave like a spring. If false + /// then the distance joint will be rigid, overriding the limit and motor. + bool enableSpring; + + /// The spring linear stiffness Hertz, cycles per second + float hertz; + + /// The spring linear damping ratio, non-dimensional + float dampingRatio; + + /// Enable/disable the joint limit + bool enableLimit; + + /// Minimum length. Clamped to a stable minimum value. + float minLength; + + /// Maximum length. Must be greater than or equal to the minimum length. + float maxLength; + + /// Enable/disable the joint motor + bool enableMotor; + + /// The maximum motor force, usually in newtons + float maxMotorForce; + + /// The desired motor speed, usually in meters per second + float motorSpeed; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2DistanceJointDef; + +/// Use this to initialize your joint definition +/// @ingroup distance_joint +B2_API b2DistanceJointDef b2DefaultDistanceJointDef( void ); + +/// A motor joint is used to control the relative motion between two bodies +/// +/// A typical usage is to control the movement of a dynamic body with respect to the ground. +/// @ingroup motor_joint +typedef struct b2MotorJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// Position of bodyB minus the position of bodyA, in bodyA's frame + b2Vec2 linearOffset; + + /// The bodyB angle minus bodyA angle in radians + float angularOffset; + + /// The maximum motor force in newtons + float maxForce; + + /// The maximum motor torque in newton-meters + float maxTorque; + + /// Position correction factor in the range [0,1] + float correctionFactor; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2MotorJointDef; + +/// Use this to initialize your joint definition +/// @ingroup motor_joint +B2_API b2MotorJointDef b2DefaultMotorJointDef( void ); + +/// A mouse joint is used to make a point on a body track a specified world point. +/// +/// This a soft constraint and allows the constraint to stretch without +/// applying huge forces. This also applies rotation constraint heuristic to improve control. +/// @ingroup mouse_joint +typedef struct b2MouseJointDef +{ + /// The first attached body. This is assumed to be static. + b2BodyId bodyIdA; + + /// The second attached body. + b2BodyId bodyIdB; + + /// The initial target point in world space + b2Vec2 target; + + /// Stiffness in hertz + float hertz; + + /// Damping ratio, non-dimensional + float dampingRatio; + + /// Maximum force, typically in newtons + float maxForce; + + /// Set this flag to true if the attached bodies should collide. + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2MouseJointDef; + +/// Use this to initialize your joint definition +/// @ingroup mouse_joint +B2_API b2MouseJointDef b2DefaultMouseJointDef( void ); + +/// A filter joint is used to disable collision between two specific bodies. +/// +/// @ingroup filter_joint +typedef struct b2FilterJointDef +{ + /// The first attached body. + b2BodyId bodyIdA; + + /// The second attached body. + b2BodyId bodyIdB; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2FilterJointDef; + +/// Use this to initialize your joint definition +/// @ingroup filter_joint +B2_API b2FilterJointDef b2DefaultFilterJointDef( void ); + +/// Prismatic joint definition +/// +/// This requires defining a line of motion using an axis and an anchor point. +/// The definition uses local anchor points and a local axis so that the initial +/// configuration can violate the constraint slightly. The joint translation is zero +/// when the local anchor points coincide in world space. +/// @ingroup prismatic_joint +typedef struct b2PrismaticJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// The local anchor point relative to bodyA's origin + b2Vec2 localAnchorA; + + /// The local anchor point relative to bodyB's origin + b2Vec2 localAnchorB; + + /// The local translation unit axis in bodyA + b2Vec2 localAxisA; + + /// The constrained angle between the bodies: bodyB_angle - bodyA_angle + float referenceAngle; + + /// Enable a linear spring along the prismatic joint axis + bool enableSpring; + + /// The spring stiffness Hertz, cycles per second + float hertz; + + /// The spring damping ratio, non-dimensional + float dampingRatio; + + /// Enable/disable the joint limit + bool enableLimit; + + /// The lower translation limit + float lowerTranslation; + + /// The upper translation limit + float upperTranslation; + + /// Enable/disable the joint motor + bool enableMotor; + + /// The maximum motor force, typically in newtons + float maxMotorForce; + + /// The desired motor speed, typically in meters per second + float motorSpeed; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2PrismaticJointDef; + +/// Use this to initialize your joint definition +/// @ingroupd prismatic_joint +B2_API b2PrismaticJointDef b2DefaultPrismaticJointDef( void ); + +/// Revolute joint definition +/// +/// This requires defining an anchor point where the bodies are joined. +/// The definition uses local anchor points so that the +/// initial configuration can violate the constraint slightly. You also need to +/// specify the initial relative angle for joint limits. This helps when saving +/// and loading a game. +/// The local anchor points are measured from the body's origin +/// rather than the center of mass because: +/// 1. you might not know where the center of mass will be +/// 2. if you add/remove shapes from a body and recompute the mass, the joints will be broken +/// @ingroup revolute_joint +typedef struct b2RevoluteJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// The local anchor point relative to bodyA's origin + b2Vec2 localAnchorA; + + /// The local anchor point relative to bodyB's origin + b2Vec2 localAnchorB; + + /// The bodyB angle minus bodyA angle in the reference state (radians). + /// This defines the zero angle for the joint limit. + float referenceAngle; + + /// Enable a rotational spring on the revolute hinge axis + bool enableSpring; + + /// The spring stiffness Hertz, cycles per second + float hertz; + + /// The spring damping ratio, non-dimensional + float dampingRatio; + + /// A flag to enable joint limits + bool enableLimit; + + /// The lower angle for the joint limit in radians. Minimum of -0.95*pi radians. + float lowerAngle; + + /// The upper angle for the joint limit in radians. Maximum of 0.95*pi radians. + float upperAngle; + + /// A flag to enable the joint motor + bool enableMotor; + + /// The maximum motor torque, typically in newton-meters + float maxMotorTorque; + + /// The desired motor speed in radians per second + float motorSpeed; + + /// Scale the debug draw + float drawSize; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2RevoluteJointDef; + +/// Use this to initialize your joint definition. +/// @ingroup revolute_joint +B2_API b2RevoluteJointDef b2DefaultRevoluteJointDef( void ); + +/// Weld joint definition +/// +/// A weld joint connect to bodies together rigidly. This constraint provides springs to mimic +/// soft-body simulation. +/// @note The approximate solver in Box2D cannot hold many bodies together rigidly +/// @ingroup weld_joint +typedef struct b2WeldJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// The local anchor point relative to bodyA's origin + b2Vec2 localAnchorA; + + /// The local anchor point relative to bodyB's origin + b2Vec2 localAnchorB; + + /// The bodyB angle minus bodyA angle in the reference state (radians) + /// todo maybe make this a b2Rot + float referenceAngle; + + /// Linear stiffness expressed as Hertz (cycles per second). Use zero for maximum stiffness. + float linearHertz; + + /// Angular stiffness as Hertz (cycles per second). Use zero for maximum stiffness. + float angularHertz; + + /// Linear damping ratio, non-dimensional. Use 1 for critical damping. + float linearDampingRatio; + + /// Linear damping ratio, non-dimensional. Use 1 for critical damping. + float angularDampingRatio; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2WeldJointDef; + +/// Use this to initialize your joint definition +/// @ingroup weld_joint +B2_API b2WeldJointDef b2DefaultWeldJointDef( void ); + +/// Wheel joint definition +/// +/// This requires defining a line of motion using an axis and an anchor point. +/// The definition uses local anchor points and a local axis so that the initial +/// configuration can violate the constraint slightly. The joint translation is zero +/// when the local anchor points coincide in world space. +/// @ingroup wheel_joint +typedef struct b2WheelJointDef +{ + /// The first attached body + b2BodyId bodyIdA; + + /// The second attached body + b2BodyId bodyIdB; + + /// The local anchor point relative to bodyA's origin + b2Vec2 localAnchorA; + + /// The local anchor point relative to bodyB's origin + b2Vec2 localAnchorB; + + /// The local translation unit axis in bodyA + b2Vec2 localAxisA; + + /// Enable a linear spring along the local axis + bool enableSpring; + + /// Spring stiffness in Hertz + float hertz; + + /// Spring damping ratio, non-dimensional + float dampingRatio; + + /// Enable/disable the joint linear limit + bool enableLimit; + + /// The lower translation limit + float lowerTranslation; + + /// The upper translation limit + float upperTranslation; + + /// Enable/disable the joint rotational motor + bool enableMotor; + + /// The maximum motor torque, typically in newton-meters + float maxMotorTorque; + + /// The desired motor speed in radians per second + float motorSpeed; + + /// Set this flag to true if the attached bodies should collide + bool collideConnected; + + /// User data pointer + void* userData; + + /// Used internally to detect a valid definition. DO NOT SET. + int internalValue; +} b2WheelJointDef; + +/// Use this to initialize your joint definition +/// @ingroup wheel_joint +B2_API b2WheelJointDef b2DefaultWheelJointDef( void ); + +/// The explosion definition is used to configure options for explosions. Explosions +/// consider shape geometry when computing the impulse. +/// @ingroup world +typedef struct b2ExplosionDef +{ + /// Mask bits to filter shapes + uint64_t maskBits; + + /// The center of the explosion in world space + b2Vec2 position; + + /// The radius of the explosion + float radius; + + /// The falloff distance beyond the radius. Impulse is reduced to zero at this distance. + float falloff; + + /// Impulse per unit length. This applies an impulse according to the shape perimeter that + /// is facing the explosion. Explosions only apply to circles, capsules, and polygons. This + /// may be negative for implosions. + float impulsePerLength; +} b2ExplosionDef; + +/// Use this to initialize your explosion definition +/// @ingroup world +B2_API b2ExplosionDef b2DefaultExplosionDef( void ); + +/** + * @defgroup events Events + * World event types. + * + * Events are used to collect events that occur during the world time step. These events + * are then available to query after the time step is complete. This is preferable to callbacks + * because Box2D uses multithreaded simulation. + * + * Also when events occur in the simulation step it may be problematic to modify the world, which is + * often what applications want to do when events occur. + * + * With event arrays, you can scan the events in a loop and modify the world. However, you need to be careful + * that some event data may become invalid. There are several samples that show how to do this safely. + * + * @{ + */ + +/// A begin touch event is generated when a shape starts to overlap a sensor shape. +typedef struct b2SensorBeginTouchEvent +{ + /// The id of the sensor shape + b2ShapeId sensorShapeId; + + /// The id of the dynamic shape that began touching the sensor shape + b2ShapeId visitorShapeId; +} b2SensorBeginTouchEvent; + +/// An end touch event is generated when a shape stops overlapping a sensor shape. +/// These include things like setting the transform, destroying a body or shape, or changing +/// a filter. You will also get an end event if the sensor or visitor are destroyed. +/// Therefore you should always confirm the shape id is valid using b2Shape_IsValid. +typedef struct b2SensorEndTouchEvent +{ + /// The id of the sensor shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + b2ShapeId sensorShapeId; + + /// The id of the dynamic shape that stopped touching the sensor shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + b2ShapeId visitorShapeId; + +} b2SensorEndTouchEvent; + +/// Sensor events are buffered in the Box2D world and are available +/// as begin/end overlap event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed +typedef struct b2SensorEvents +{ + /// Array of sensor begin touch events + b2SensorBeginTouchEvent* beginEvents; + + /// Array of sensor end touch events + b2SensorEndTouchEvent* endEvents; + + /// The number of begin touch events + int beginCount; + + /// The number of end touch events + int endCount; +} b2SensorEvents; + +/// A begin touch event is generated when two shapes begin touching. +typedef struct b2ContactBeginTouchEvent +{ + /// Id of the first shape + b2ShapeId shapeIdA; + + /// Id of the second shape + b2ShapeId shapeIdB; + + /// The initial contact manifold. This is recorded before the solver is called, + /// so all the impulses will be zero. + b2Manifold manifold; +} b2ContactBeginTouchEvent; + +/// An end touch event is generated when two shapes stop touching. +/// You will get an end event if you do anything that destroys contacts previous to the last +/// world step. These include things like setting the transform, destroying a body +/// or shape, or changing a filter or body type. +typedef struct b2ContactEndTouchEvent +{ + /// Id of the first shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + b2ShapeId shapeIdA; + + /// Id of the second shape + /// @warning this shape may have been destroyed + /// @see b2Shape_IsValid + b2ShapeId shapeIdB; +} b2ContactEndTouchEvent; + +/// A hit touch event is generated when two shapes collide with a speed faster than the hit speed threshold. +typedef struct b2ContactHitEvent +{ + /// Id of the first shape + b2ShapeId shapeIdA; + + /// Id of the second shape + b2ShapeId shapeIdB; + + /// Point where the shapes hit + b2Vec2 point; + + /// Normal vector pointing from shape A to shape B + b2Vec2 normal; + + /// The speed the shapes are approaching. Always positive. Typically in meters per second. + float approachSpeed; +} b2ContactHitEvent; + +/// Contact events are buffered in the Box2D world and are available +/// as event arrays after the time step is complete. +/// Note: these may become invalid if bodies and/or shapes are destroyed +typedef struct b2ContactEvents +{ + /// Array of begin touch events + b2ContactBeginTouchEvent* beginEvents; + + /// Array of end touch events + b2ContactEndTouchEvent* endEvents; + + /// Array of hit events + b2ContactHitEvent* hitEvents; + + /// Number of begin touch events + int beginCount; + + /// Number of end touch events + int endCount; + + /// Number of hit events + int hitCount; +} b2ContactEvents; + +/// Body move events triggered when a body moves. +/// Triggered when a body moves due to simulation. Not reported for bodies moved by the user. +/// This also has a flag to indicate that the body went to sleep so the application can also +/// sleep that actor/entity/object associated with the body. +/// On the other hand if the flag does not indicate the body went to sleep then the application +/// can treat the actor/entity/object associated with the body as awake. +/// This is an efficient way for an application to update game object transforms rather than +/// calling functions such as b2Body_GetTransform() because this data is delivered as a contiguous array +/// and it is only populated with bodies that have moved. +/// @note If sleeping is disabled all dynamic and kinematic bodies will trigger move events. +typedef struct b2BodyMoveEvent +{ + b2Transform transform; + b2BodyId bodyId; + void* userData; + bool fellAsleep; +} b2BodyMoveEvent; + +/// Body events are buffered in the Box2D world and are available +/// as event arrays after the time step is complete. +/// Note: this data becomes invalid if bodies are destroyed +typedef struct b2BodyEvents +{ + /// Array of move events + b2BodyMoveEvent* moveEvents; + + /// Number of move events + int moveCount; +} b2BodyEvents; + +/// The contact data for two shapes. By convention the manifold normal points +/// from shape A to shape B. +/// @see b2Shape_GetContactData() and b2Body_GetContactData() +typedef struct b2ContactData +{ + b2ShapeId shapeIdA; + b2ShapeId shapeIdB; + b2Manifold manifold; +} b2ContactData; + +/**@}*/ + +/// Prototype for a contact filter callback. +/// This is called when a contact pair is considered for collision. This allows you to +/// perform custom logic to prevent collision between shapes. This is only called if +/// one of the two shapes has custom filtering enabled. +/// Notes: +/// - this function must be thread-safe +/// - this is only called if one of the two shapes has enabled custom filtering +/// - this is called only for awake dynamic bodies +/// Return false if you want to disable the collision +/// @see b2ShapeDef +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world +typedef bool b2CustomFilterFcn( b2ShapeId shapeIdA, b2ShapeId shapeIdB, void* context ); + +/// Prototype for a pre-solve callback. +/// This is called after a contact is updated. This allows you to inspect a +/// contact before it goes to the solver. If you are careful, you can modify the +/// contact manifold (e.g. modify the normal). +/// Notes: +/// - this function must be thread-safe +/// - this is only called if the shape has enabled pre-solve events +/// - this is called only for awake dynamic bodies +/// - this is not called for sensors +/// - the supplied manifold has impulse values from the previous step +/// Return false if you want to disable the contact this step +/// @warning Do not attempt to modify the world inside this callback +/// @ingroup world +typedef bool b2PreSolveFcn( b2ShapeId shapeIdA, b2ShapeId shapeIdB, b2Manifold* manifold, void* context ); + +/// Prototype callback for overlap queries. +/// Called for each shape found in the query. +/// @see b2World_OverlapABB +/// @return false to terminate the query. +/// @ingroup world +typedef bool b2OverlapResultFcn( b2ShapeId shapeId, void* context ); + +/// Prototype callback for ray casts. +/// Called for each shape found in the query. You control how the ray cast +/// proceeds by returning a float: +/// return -1: ignore this shape and continue +/// return 0: terminate the ray cast +/// return fraction: clip the ray to this point +/// return 1: don't clip the ray and continue +/// @param shapeId the shape hit by the ray +/// @param point the point of initial intersection +/// @param normal the normal vector at the point of intersection +/// @param fraction the fraction along the ray at the point of intersection +/// @param context the user context +/// @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue +/// @see b2World_CastRay +/// @ingroup world +typedef float b2CastResultFcn( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ); + +// Used to collect collision planes for character movers. +// Return true to continue gathering planes. +typedef bool b2PlaneResultFcn( b2ShapeId shapeId, const b2PlaneResult* plane, void* context ); + +/// These colors are used for debug draw and mostly match the named SVG colors. +/// See https://www.rapidtables.com/web/color/index.html +/// https://johndecember.com/html/spec/colorsvg.html +/// https://upload.wikimedia.org/wikipedia/commons/2/2b/SVG_Recognized_color_keyword_names.svg +typedef enum b2HexColor +{ + b2_colorAliceBlue = 0xF0F8FF, + b2_colorAntiqueWhite = 0xFAEBD7, + b2_colorAqua = 0x00FFFF, + b2_colorAquamarine = 0x7FFFD4, + b2_colorAzure = 0xF0FFFF, + b2_colorBeige = 0xF5F5DC, + b2_colorBisque = 0xFFE4C4, + b2_colorBlack = 0x000000, + b2_colorBlanchedAlmond = 0xFFEBCD, + b2_colorBlue = 0x0000FF, + b2_colorBlueViolet = 0x8A2BE2, + b2_colorBrown = 0xA52A2A, + b2_colorBurlywood = 0xDEB887, + b2_colorCadetBlue = 0x5F9EA0, + b2_colorChartreuse = 0x7FFF00, + b2_colorChocolate = 0xD2691E, + b2_colorCoral = 0xFF7F50, + b2_colorCornflowerBlue = 0x6495ED, + b2_colorCornsilk = 0xFFF8DC, + b2_colorCrimson = 0xDC143C, + b2_colorCyan = 0x00FFFF, + b2_colorDarkBlue = 0x00008B, + b2_colorDarkCyan = 0x008B8B, + b2_colorDarkGoldenRod = 0xB8860B, + b2_colorDarkGray = 0xA9A9A9, + b2_colorDarkGreen = 0x006400, + b2_colorDarkKhaki = 0xBDB76B, + b2_colorDarkMagenta = 0x8B008B, + b2_colorDarkOliveGreen = 0x556B2F, + b2_colorDarkOrange = 0xFF8C00, + b2_colorDarkOrchid = 0x9932CC, + b2_colorDarkRed = 0x8B0000, + b2_colorDarkSalmon = 0xE9967A, + b2_colorDarkSeaGreen = 0x8FBC8F, + b2_colorDarkSlateBlue = 0x483D8B, + b2_colorDarkSlateGray = 0x2F4F4F, + b2_colorDarkTurquoise = 0x00CED1, + b2_colorDarkViolet = 0x9400D3, + b2_colorDeepPink = 0xFF1493, + b2_colorDeepSkyBlue = 0x00BFFF, + b2_colorDimGray = 0x696969, + b2_colorDodgerBlue = 0x1E90FF, + b2_colorFireBrick = 0xB22222, + b2_colorFloralWhite = 0xFFFAF0, + b2_colorForestGreen = 0x228B22, + b2_colorFuchsia = 0xFF00FF, + b2_colorGainsboro = 0xDCDCDC, + b2_colorGhostWhite = 0xF8F8FF, + b2_colorGold = 0xFFD700, + b2_colorGoldenRod = 0xDAA520, + b2_colorGray = 0x808080, + b2_colorGreen = 0x008000, + b2_colorGreenYellow = 0xADFF2F, + b2_colorHoneyDew = 0xF0FFF0, + b2_colorHotPink = 0xFF69B4, + b2_colorIndianRed = 0xCD5C5C, + b2_colorIndigo = 0x4B0082, + b2_colorIvory = 0xFFFFF0, + b2_colorKhaki = 0xF0E68C, + b2_colorLavender = 0xE6E6FA, + b2_colorLavenderBlush = 0xFFF0F5, + b2_colorLawnGreen = 0x7CFC00, + b2_colorLemonChiffon = 0xFFFACD, + b2_colorLightBlue = 0xADD8E6, + b2_colorLightCoral = 0xF08080, + b2_colorLightCyan = 0xE0FFFF, + b2_colorLightGoldenRodYellow = 0xFAFAD2, + b2_colorLightGray = 0xD3D3D3, + b2_colorLightGreen = 0x90EE90, + b2_colorLightPink = 0xFFB6C1, + b2_colorLightSalmon = 0xFFA07A, + b2_colorLightSeaGreen = 0x20B2AA, + b2_colorLightSkyBlue = 0x87CEFA, + b2_colorLightSlateGray = 0x778899, + b2_colorLightSteelBlue = 0xB0C4DE, + b2_colorLightYellow = 0xFFFFE0, + b2_colorLime = 0x00FF00, + b2_colorLimeGreen = 0x32CD32, + b2_colorLinen = 0xFAF0E6, + b2_colorMagenta = 0xFF00FF, + b2_colorMaroon = 0x800000, + b2_colorMediumAquaMarine = 0x66CDAA, + b2_colorMediumBlue = 0x0000CD, + b2_colorMediumOrchid = 0xBA55D3, + b2_colorMediumPurple = 0x9370DB, + b2_colorMediumSeaGreen = 0x3CB371, + b2_colorMediumSlateBlue = 0x7B68EE, + b2_colorMediumSpringGreen = 0x00FA9A, + b2_colorMediumTurquoise = 0x48D1CC, + b2_colorMediumVioletRed = 0xC71585, + b2_colorMidnightBlue = 0x191970, + b2_colorMintCream = 0xF5FFFA, + b2_colorMistyRose = 0xFFE4E1, + b2_colorMoccasin = 0xFFE4B5, + b2_colorNavajoWhite = 0xFFDEAD, + b2_colorNavy = 0x000080, + b2_colorOldLace = 0xFDF5E6, + b2_colorOlive = 0x808000, + b2_colorOliveDrab = 0x6B8E23, + b2_colorOrange = 0xFFA500, + b2_colorOrangeRed = 0xFF4500, + b2_colorOrchid = 0xDA70D6, + b2_colorPaleGoldenRod = 0xEEE8AA, + b2_colorPaleGreen = 0x98FB98, + b2_colorPaleTurquoise = 0xAFEEEE, + b2_colorPaleVioletRed = 0xDB7093, + b2_colorPapayaWhip = 0xFFEFD5, + b2_colorPeachPuff = 0xFFDAB9, + b2_colorPeru = 0xCD853F, + b2_colorPink = 0xFFC0CB, + b2_colorPlum = 0xDDA0DD, + b2_colorPowderBlue = 0xB0E0E6, + b2_colorPurple = 0x800080, + b2_colorRebeccaPurple = 0x663399, + b2_colorRed = 0xFF0000, + b2_colorRosyBrown = 0xBC8F8F, + b2_colorRoyalBlue = 0x4169E1, + b2_colorSaddleBrown = 0x8B4513, + b2_colorSalmon = 0xFA8072, + b2_colorSandyBrown = 0xF4A460, + b2_colorSeaGreen = 0x2E8B57, + b2_colorSeaShell = 0xFFF5EE, + b2_colorSienna = 0xA0522D, + b2_colorSilver = 0xC0C0C0, + b2_colorSkyBlue = 0x87CEEB, + b2_colorSlateBlue = 0x6A5ACD, + b2_colorSlateGray = 0x708090, + b2_colorSnow = 0xFFFAFA, + b2_colorSpringGreen = 0x00FF7F, + b2_colorSteelBlue = 0x4682B4, + b2_colorTan = 0xD2B48C, + b2_colorTeal = 0x008080, + b2_colorThistle = 0xD8BFD8, + b2_colorTomato = 0xFF6347, + b2_colorTurquoise = 0x40E0D0, + b2_colorViolet = 0xEE82EE, + b2_colorWheat = 0xF5DEB3, + b2_colorWhite = 0xFFFFFF, + b2_colorWhiteSmoke = 0xF5F5F5, + b2_colorYellow = 0xFFFF00, + b2_colorYellowGreen = 0x9ACD32, + + b2_colorBox2DRed = 0xDC3132, + b2_colorBox2DBlue = 0x30AEBF, + b2_colorBox2DGreen = 0x8CC924, + b2_colorBox2DYellow = 0xFFEE8C +} b2HexColor; + +/// This struct holds callbacks you can implement to draw a Box2D world. +/// This structure should be zero initialized. +/// @ingroup world +typedef struct b2DebugDraw +{ + /// Draw a closed polygon provided in CCW order. + void ( *DrawPolygonFcn )( const b2Vec2* vertices, int vertexCount, b2HexColor color, void* context ); + + /// Draw a solid closed polygon provided in CCW order. + void ( *DrawSolidPolygonFcn )( b2Transform transform, const b2Vec2* vertices, int vertexCount, float radius, b2HexColor color, + void* context ); + + /// Draw a circle. + void ( *DrawCircleFcn )( b2Vec2 center, float radius, b2HexColor color, void* context ); + + /// Draw a solid circle. + void ( *DrawSolidCircleFcn )( b2Transform transform, float radius, b2HexColor color, void* context ); + + /// Draw a solid capsule. + void ( *DrawSolidCapsuleFcn )( b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context ); + + /// Draw a line segment. + void ( *DrawSegmentFcn )( b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context ); + + /// Draw a transform. Choose your own length scale. + void ( *DrawTransformFcn )( b2Transform transform, void* context ); + + /// Draw a point. + void ( *DrawPointFcn )( b2Vec2 p, float size, b2HexColor color, void* context ); + + /// Draw a string in world space + void ( *DrawStringFcn )( b2Vec2 p, const char* s, b2HexColor color, void* context ); + + /// Bounds to use if restricting drawing to a rectangular region + b2AABB drawingBounds; + + /// Option to restrict drawing to a rectangular region. May suffer from unstable depth sorting. + bool useDrawingBounds; + + /// Option to draw shapes + bool drawShapes; + + /// Option to draw joints + bool drawJoints; + + /// Option to draw additional information for joints + bool drawJointExtras; + + /// Option to draw the bounding boxes for shapes + bool drawBounds; + + /// Option to draw the mass and center of mass of dynamic bodies + bool drawMass; + + /// Option to draw body names + bool drawBodyNames; + + /// Option to draw contact points + bool drawContacts; + + /// Option to visualize the graph coloring used for contacts and joints + bool drawGraphColors; + + /// Option to draw contact normals + bool drawContactNormals; + + /// Option to draw contact normal impulses + bool drawContactImpulses; + + /// Option to draw contact feature ids + bool drawContactFeatures; + + /// Option to draw contact friction impulses + bool drawFrictionImpulses; + + /// Option to draw islands as bounding boxes + bool drawIslands; + + /// User context that is passed as an argument to drawing callback functions + void* context; +} b2DebugDraw; + +/// Use this to initialize your drawing interface. This allows you to implement a sub-set +/// of the drawing functions. +B2_API b2DebugDraw b2DefaultDebugDraw( void ); diff --git a/3rdparty/box2d/src/CMakeLists.txt b/3rdparty/box2d/src/CMakeLists.txt new file mode 100644 index 000000000000..5e08afae0e02 --- /dev/null +++ b/3rdparty/box2d/src/CMakeLists.txt @@ -0,0 +1,223 @@ +include(GNUInstallDirs) + +set(BOX2D_SOURCE_FILES + aabb.c + aabb.h + arena_allocator.c + arena_allocator.h + array.c + array.h + atomic.h + bitset.c + bitset.h + body.c + body.h + broad_phase.c + broad_phase.h + constants.h + constraint_graph.c + constraint_graph.h + contact.c + contact.h + contact_solver.c + contact_solver.h + core.c + core.h + ctz.h + distance.c + distance_joint.c + dynamic_tree.c + geometry.c + hull.c + id_pool.c + id_pool.h + island.c + island.h + joint.c + joint.h + manifold.c + math_functions.c + motor_joint.c + mouse_joint.c + mover.c + prismatic_joint.c + revolute_joint.c + sensor.c + sensor.h + shape.c + shape.h + solver.c + solver.h + solver_set.c + solver_set.h + table.c + table.h + timer.c + types.c + weld_joint.c + wheel_joint.c + world.c + world.h +) + +set(BOX2D_API_FILES + ../include/box2d/base.h + ../include/box2d/box2d.h + ../include/box2d/collision.h + ../include/box2d/id.h + ../include/box2d/math_functions.h + ../include/box2d/types.h +) + +# Hide internal functions +# https://gcc.gnu.org/wiki/Visibility +set(CMAKE_C_VISIBILITY_PRESET hidden) +set(CMAKE_VISIBILITY_INLINES_HIDDEN 1) + +add_library(box2d ${BOX2D_SOURCE_FILES} ${BOX2D_API_FILES}) + +target_include_directories(box2d + PUBLIC + $ + $ + $ + PRIVATE + ${CMAKE_CURRENT_SOURCE_DIR} +) + +set(CMAKE_DEBUG_POSTFIX "d") + +# Box2D uses C17 for _Static_assert and anonymous unions +set_target_properties(box2d PROPERTIES + C_STANDARD 17 + C_STANDARD_REQUIRED YES + C_EXTENSIONS YES + COMPILE_WARNING_AS_ERROR ON + VERSION ${PROJECT_VERSION} + SOVERSION ${PROJECT_VERSION_MAJOR} + DEBUG_POSTFIX ${CMAKE_DEBUG_POSTFIX} +) + +if (BOX2D_PROFILE) + target_compile_definitions(box2d PRIVATE BOX2D_PROFILE) + + FetchContent_Declare( + tracy + GIT_REPOSITORY https://github.com/wolfpld/tracy.git + GIT_TAG v0.11.1 + GIT_SHALLOW TRUE + GIT_PROGRESS TRUE + ) + FetchContent_MakeAvailable(tracy) + + target_link_libraries(box2d PUBLIC TracyClient) +endif() + +if (BOX2D_VALIDATE) + message(STATUS "Box2D validation ON") + target_compile_definitions(box2d PRIVATE BOX2D_VALIDATE) +endif() + +if (BOX2D_DISABLE_SIMD) + message(STATUS "Box2D SIMD disabled") + target_compile_definitions(box2d PRIVATE BOX2D_DISABLE_SIMD) +endif() + +if (MSVC) + message(STATUS "Box2D on MSVC") + if (BUILD_SHARED_LIBS) + # this is needed by DLL users to import Box2D symbols + target_compile_definitions(box2d INTERFACE BOX2D_DLL) + endif() + + # Visual Studio won't load the natvis unless it is in the project + target_sources(box2d PRIVATE box2d.natvis) + + # Enable asserts in release with debug info + target_compile_definitions(box2d PUBLIC "$<$:B2_ENABLE_ASSERT>") + + # Warnings + # 4710 - warn about inline functions that are not inlined + target_compile_options(box2d PRIVATE /Wall /wd4820 /wd5045 /wd4061 /wd4711 /wd4710) + + if (BOX2D_AVX2) + message(STATUS "Box2D using AVX2") + target_compile_definitions(box2d PRIVATE BOX2D_AVX2) + target_compile_options(box2d PRIVATE /arch:AVX2) + endif() + + if (${CMAKE_CXX_COMPILER_ID} STREQUAL "Clang") + target_compile_options(box2d PRIVATE -Wmissing-prototypes) + endif() + +elseif (MINGW) + message(STATUS "Box2D on MinGW") + if (BOX2D_AVX2) + message(STATUS "Box2D using AVX2") + target_compile_definitions(box2d PRIVATE BOX2D_AVX2) + target_compile_options(box2d PRIVATE -mavx2) + else() + endif() +elseif (APPLE) + message(STATUS "Box2D on Apple") + target_compile_options(box2d PRIVATE -Wmissing-prototypes -Wall -Wextra -pedantic -Werror) +elseif (EMSCRIPTEN) + message(STATUS "Box2D on Emscripten") + if (BOX2D_DISABLE_SIMD OFF) + target_compile_options(box2d PRIVATE -msimd128 -msse2) + endif() +elseif (UNIX) + message(STATUS "Box2D using Unix") + target_compile_options(box2d PRIVATE -Wmissing-prototypes -Wall -Wextra -pedantic -Werror -Wno-unused-value) + if ("${CMAKE_HOST_SYSTEM_PROCESSOR}" STREQUAL "aarch64") + # raspberry pi + # -mfpu=neon + # target_compile_options(box2d PRIVATE) + else() + # x64 + if (BOX2D_AVX2) + message(STATUS "Box2D using AVX2") + # FMA -mfma -mavx -march=native + target_compile_definitions(box2d PRIVATE BOX2D_AVX2) + target_compile_options(box2d PRIVATE -mavx2) + else() + endif() + endif() +endif() + +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "src" FILES ${BOX2D_SOURCE_FILES}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/../include" PREFIX "include" FILES ${BOX2D_API_FILES}) + +add_library(box2d::box2d ALIAS box2d) + +install( + TARGETS box2d + EXPORT box2dConfig + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} +) + +install( + EXPORT box2dConfig + NAMESPACE box2d:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d" +) + +install( + FILES ${BOX2D_API_FILES} + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/box2d +) + +include(CMakePackageConfigHelpers) + +write_basic_package_version_file( + "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake" + VERSION ${BOX2D_VERSION} + COMPATIBILITY SameMajorVersion +) + +install( + FILES "${CMAKE_CURRENT_BINARY_DIR}/box2dConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/box2d" +) diff --git a/3rdparty/box2d/src/aabb.c b/3rdparty/box2d/src/aabb.c new file mode 100644 index 000000000000..bfa1e70122ed --- /dev/null +++ b/3rdparty/box2d/src/aabb.c @@ -0,0 +1,132 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "aabb.h" + +#include "box2d/math_functions.h" + +#include + +bool b2IsValidAABB( b2AABB a ) +{ + b2Vec2 d = b2Sub( a.upperBound, a.lowerBound ); + bool valid = d.x >= 0.0f && d.y >= 0.0f; + valid = valid && b2IsValidVec2( a.lowerBound ) && b2IsValidVec2( a.upperBound ); + return valid; +} + +// From Real-time Collision Detection, p179. +b2CastOutput b2AABB_RayCast( b2AABB a, b2Vec2 p1, b2Vec2 p2 ) +{ + // Radius not handled + b2CastOutput output = { 0 }; + + float tmin = -FLT_MAX; + float tmax = FLT_MAX; + + b2Vec2 p = p1; + b2Vec2 d = b2Sub( p2, p1 ); + b2Vec2 absD = b2Abs( d ); + + b2Vec2 normal = b2Vec2_zero; + + // x-coordinate + if ( absD.x < FLT_EPSILON ) + { + // parallel + if ( p.x < a.lowerBound.x || a.upperBound.x < p.x ) + { + return output; + } + } + else + { + float inv_d = 1.0f / d.x; + float t1 = ( a.lowerBound.x - p.x ) * inv_d; + float t2 = ( a.upperBound.x - p.x ) * inv_d; + + // Sign of the normal vector. + float s = -1.0f; + + if ( t1 > t2 ) + { + float tmp = t1; + t1 = t2; + t2 = tmp; + s = 1.0f; + } + + // Push the min up + if ( t1 > tmin ) + { + normal.y = 0.0f; + normal.x = s; + tmin = t1; + } + + // Pull the max down + tmax = b2MinFloat( tmax, t2 ); + + if ( tmin > tmax ) + { + return output; + } + } + + // y-coordinate + if ( absD.y < FLT_EPSILON ) + { + // parallel + if ( p.y < a.lowerBound.y || a.upperBound.y < p.y ) + { + return output; + } + } + else + { + float inv_d = 1.0f / d.y; + float t1 = ( a.lowerBound.y - p.y ) * inv_d; + float t2 = ( a.upperBound.y - p.y ) * inv_d; + + // Sign of the normal vector. + float s = -1.0f; + + if ( t1 > t2 ) + { + float tmp = t1; + t1 = t2; + t2 = tmp; + s = 1.0f; + } + + // Push the min up + if ( t1 > tmin ) + { + normal.x = 0.0f; + normal.y = s; + tmin = t1; + } + + // Pull the max down + tmax = b2MinFloat( tmax, t2 ); + + if ( tmin > tmax ) + { + return output; + } + } + + // Does the ray start inside the box? + // Does the ray intersect beyond the max fraction? + if ( tmin < 0.0f || 1.0f < tmin ) + { + return output; + } + + // Intersection. + output.fraction = tmin; + output.normal = normal; + output.point = b2Lerp( p1, p2, tmin ); + output.hit = true; + return output; +} diff --git a/3rdparty/box2d/src/aabb.h b/3rdparty/box2d/src/aabb.h new file mode 100644 index 000000000000..834c8eaa7b47 --- /dev/null +++ b/3rdparty/box2d/src/aabb.h @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/types.h" + +// Ray cast an AABB +b2CastOutput b2AABB_RayCast( b2AABB a, b2Vec2 p1, b2Vec2 p2 ); + +// Get surface area of an AABB (the perimeter length) +static inline float b2Perimeter( b2AABB a ) +{ + float wx = a.upperBound.x - a.lowerBound.x; + float wy = a.upperBound.y - a.lowerBound.y; + return 2.0f * ( wx + wy ); +} + +/// Enlarge a to contain b +/// @return true if the AABB grew +static inline bool b2EnlargeAABB( b2AABB* a, b2AABB b ) +{ + bool changed = false; + if ( b.lowerBound.x < a->lowerBound.x ) + { + a->lowerBound.x = b.lowerBound.x; + changed = true; + } + + if ( b.lowerBound.y < a->lowerBound.y ) + { + a->lowerBound.y = b.lowerBound.y; + changed = true; + } + + if ( a->upperBound.x < b.upperBound.x ) + { + a->upperBound.x = b.upperBound.x; + changed = true; + } + + if ( a->upperBound.y < b.upperBound.y ) + { + a->upperBound.y = b.upperBound.y; + changed = true; + } + + return changed; +} + +/// Do a and b overlap +static inline bool b2AABB_Overlaps( b2AABB a, b2AABB b ) +{ + return !( b.lowerBound.x > a.upperBound.x || b.lowerBound.y > a.upperBound.y || a.lowerBound.x > b.upperBound.x || + a.lowerBound.y > b.upperBound.y ); +} diff --git a/3rdparty/box2d/src/arena_allocator.c b/3rdparty/box2d/src/arena_allocator.c new file mode 100644 index 000000000000..000f2040377d --- /dev/null +++ b/3rdparty/box2d/src/arena_allocator.c @@ -0,0 +1,112 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "arena_allocator.h" + +#include "array.h" +#include "core.h" + +#include +#include + +B2_ARRAY_SOURCE( b2ArenaEntry, b2ArenaEntry ) + +b2ArenaAllocator b2CreateArenaAllocator( int capacity ) +{ + B2_ASSERT( capacity >= 0 ); + b2ArenaAllocator allocator = { 0 }; + allocator.capacity = capacity; + allocator.data = b2Alloc( capacity ); + allocator.allocation = 0; + allocator.maxAllocation = 0; + allocator.index = 0; + allocator.entries = b2ArenaEntryArray_Create( 32 ); + return allocator; +} + +void b2DestroyArenaAllocator( b2ArenaAllocator* allocator ) +{ + b2ArenaEntryArray_Destroy( &allocator->entries ); + b2Free( allocator->data, allocator->capacity ); +} + +void* b2AllocateArenaItem( b2ArenaAllocator* alloc, int size, const char* name ) +{ + // ensure allocation is 32 byte aligned to support 256-bit SIMD + int size32 = ( ( size - 1 ) | 0x1F ) + 1; + + b2ArenaEntry entry; + entry.size = size32; + entry.name = name; + if ( alloc->index + size32 > alloc->capacity ) + { + // fall back to the heap (undesirable) + entry.data = b2Alloc( size32 ); + entry.usedMalloc = true; + + B2_ASSERT( ( (uintptr_t)entry.data & 0x1F ) == 0 ); + } + else + { + entry.data = alloc->data + alloc->index; + entry.usedMalloc = false; + alloc->index += size32; + + B2_ASSERT( ( (uintptr_t)entry.data & 0x1F ) == 0 ); + } + + alloc->allocation += size32; + if ( alloc->allocation > alloc->maxAllocation ) + { + alloc->maxAllocation = alloc->allocation; + } + + b2ArenaEntryArray_Push( &alloc->entries, entry ); + return entry.data; +} + +void b2FreeArenaItem( b2ArenaAllocator* alloc, void* mem ) +{ + int entryCount = alloc->entries.count; + B2_ASSERT( entryCount > 0 ); + b2ArenaEntry* entry = alloc->entries.data + ( entryCount - 1 ); + B2_ASSERT( mem == entry->data ); + if ( entry->usedMalloc ) + { + b2Free( mem, entry->size ); + } + else + { + alloc->index -= entry->size; + } + alloc->allocation -= entry->size; + b2ArenaEntryArray_Pop( &alloc->entries ); +} + +void b2GrowArena( b2ArenaAllocator* alloc ) +{ + // Stack must not be in use + B2_ASSERT( alloc->allocation == 0 ); + + if ( alloc->maxAllocation > alloc->capacity ) + { + b2Free( alloc->data, alloc->capacity ); + alloc->capacity = alloc->maxAllocation + alloc->maxAllocation / 2; + alloc->data = b2Alloc( alloc->capacity ); + } +} + +int b2GetArenaCapacity( b2ArenaAllocator* alloc ) +{ + return alloc->capacity; +} + +int b2GetArenaAllocation( b2ArenaAllocator* alloc ) +{ + return alloc->allocation; +} + +int b2GetMaxArenaAllocation( b2ArenaAllocator* alloc ) +{ + return alloc->maxAllocation; +} diff --git a/3rdparty/box2d/src/arena_allocator.h b/3rdparty/box2d/src/arena_allocator.h new file mode 100644 index 000000000000..bc67180b1a58 --- /dev/null +++ b/3rdparty/box2d/src/arena_allocator.h @@ -0,0 +1,48 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +B2_ARRAY_DECLARE( b2ArenaEntry, b2ArenaEntry ); + +typedef struct b2ArenaEntry +{ + char* data; + const char* name; + int size; + bool usedMalloc; +} b2ArenaEntry; + +// This is a stack-like arena allocator used for fast per step allocations. +// You must nest allocate/free pairs. The code will B2_ASSERT +// if you try to interleave multiple allocate/free pairs. +// This allocator uses the heap if space is insufficient. +// I could remove the need to free entries individually. +typedef struct b2ArenaAllocator +{ + char* data; + int capacity; + int index; + + int allocation; + int maxAllocation; + + b2ArenaEntryArray entries; +} b2ArenaAllocator; + +b2ArenaAllocator b2CreateArenaAllocator( int capacity ); +void b2DestroyArenaAllocator( b2ArenaAllocator* allocator ); + +void* b2AllocateArenaItem( b2ArenaAllocator* alloc, int size, const char* name ); +void b2FreeArenaItem( b2ArenaAllocator* alloc, void* mem ); + +// Grow the arena based on usage +void b2GrowArena( b2ArenaAllocator* alloc ); + +int b2GetArenaCapacity( b2ArenaAllocator* alloc ); +int b2GetArenaAllocation( b2ArenaAllocator* alloc ); +int b2GetMaxArenaAllocation( b2ArenaAllocator* alloc ); + +B2_ARRAY_INLINE( b2ArenaEntry, b2ArenaEntry ) diff --git a/3rdparty/box2d/src/array.c b/3rdparty/box2d/src/array.c new file mode 100644 index 000000000000..b9c0c1aad526 --- /dev/null +++ b/3rdparty/box2d/src/array.c @@ -0,0 +1,8 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "array.h" + +#include + +B2_ARRAY_SOURCE( int, b2Int ) diff --git a/3rdparty/box2d/src/array.h b/3rdparty/box2d/src/array.h new file mode 100644 index 000000000000..6744fab8021b --- /dev/null +++ b/3rdparty/box2d/src/array.h @@ -0,0 +1,179 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "core.h" + +// Macro generated functions for dynamic arrays +// Pros +// - type safe +// - array data debuggable (visible count and capacity) +// - bounds checking +// - forward declaration +// - simple implementation +// - generates functions (like C++ templates) +// - functions have https://en.wikipedia.org/wiki/Sequence_point +// - avoids stretchy buffer dropped pointer update bugs +// Cons +// - cannot debug +// - breaks code navigation + +// todo_erin consider code-gen: https://github.com/IbrahimHindawi/haikal + +// Array declaration that doesn't need the type T to be defined +#define B2_ARRAY_DECLARE( T, PREFIX ) \ + typedef struct \ + { \ + struct T* data; \ + int count; \ + int capacity; \ + } PREFIX##Array; \ + PREFIX##Array PREFIX##Array_Create( int capacity ); \ + void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ); \ + void PREFIX##Array_Destroy( PREFIX##Array* a ) + +#define B2_DECLARE_ARRAY_NATIVE( T, PREFIX ) \ + typedef struct \ + { \ + T* data; \ + int count; \ + int capacity; \ + } PREFIX##Array; \ + /* Create array with initial capacity. Zero initialization is also supported */ \ + PREFIX##Array PREFIX##Array_Create( int capacity ); \ + void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ); \ + void PREFIX##Array_Destroy( PREFIX##Array* a ) + +// Inline array functions that need the type T to be defined +#define B2_ARRAY_INLINE( T, PREFIX ) \ + /* Resize */ \ + static inline void PREFIX##Array_Resize( PREFIX##Array* a, int count ) \ + { \ + PREFIX##Array_Reserve( a, count ); \ + a->count = count; \ + } \ + /* Get */ \ + static inline T* PREFIX##Array_Get( PREFIX##Array* a, int index ) \ + { \ + B2_ASSERT( 0 <= index && index < a->count ); \ + return a->data + index; \ + } \ + /* Add */ \ + static inline T* PREFIX##Array_Add( PREFIX##Array* a ) \ + { \ + if ( a->count == a->capacity ) \ + { \ + int newCapacity = a->capacity < 2 ? 2 : a->capacity + ( a->capacity >> 1 ); \ + PREFIX##Array_Reserve( a, newCapacity ); \ + } \ + a->count += 1; \ + return a->data + ( a->count - 1 ); \ + } \ + /* Push */ \ + static inline void PREFIX##Array_Push( PREFIX##Array* a, T value ) \ + { \ + if ( a->count == a->capacity ) \ + { \ + int newCapacity = a->capacity < 2 ? 2 : a->capacity + ( a->capacity >> 1 ); \ + PREFIX##Array_Reserve( a, newCapacity ); \ + } \ + a->data[a->count] = value; \ + a->count += 1; \ + } \ + /* Set */ \ + static inline void PREFIX##Array_Set( PREFIX##Array* a, int index, T value ) \ + { \ + B2_ASSERT( 0 <= index && index < a->count ); \ + a->data[index] = value; \ + } \ + /* RemoveSwap */ \ + static inline int PREFIX##Array_RemoveSwap( PREFIX##Array* a, int index ) \ + { \ + B2_ASSERT( 0 <= index && index < a->count ); \ + int movedIndex = B2_NULL_INDEX; \ + if ( index != a->count - 1 ) \ + { \ + movedIndex = a->count - 1; \ + a->data[index] = a->data[movedIndex]; \ + } \ + a->count -= 1; \ + return movedIndex; \ + } \ + /* Pop */ \ + static inline T PREFIX##Array_Pop( PREFIX##Array* a ) \ + { \ + B2_ASSERT( a->count > 0 ); \ + T value = a->data[a->count - 1]; \ + a->count -= 1; \ + return value; \ + } \ + /* Clear */ \ + static inline void PREFIX##Array_Clear( PREFIX##Array* a ) \ + { \ + a->count = 0; \ + } \ + /* ByteCount */ \ + static inline int PREFIX##Array_ByteCount( PREFIX##Array* a ) \ + { \ + return (int)( a->capacity * sizeof( T ) ); \ + } + +// Array implementations to be instantiated in a source file where the type T is known +#define B2_ARRAY_SOURCE( T, PREFIX ) \ + /* Create */ \ + PREFIX##Array PREFIX##Array_Create( int capacity ) \ + { \ + PREFIX##Array a = { 0 }; \ + if ( capacity > 0 ) \ + { \ + a.data = b2Alloc( capacity * sizeof( T ) ); \ + a.capacity = capacity; \ + } \ + return a; \ + } \ + /* Reserve */ \ + void PREFIX##Array_Reserve( PREFIX##Array* a, int newCapacity ) \ + { \ + if ( newCapacity <= a->capacity ) \ + { \ + return; \ + } \ + a->data = b2GrowAlloc( a->data, a->capacity * sizeof( T ), newCapacity * sizeof( T ) ); \ + a->capacity = newCapacity; \ + } \ + /* Destroy */ \ + void PREFIX##Array_Destroy( PREFIX##Array* a ) \ + { \ + b2Free( a->data, a->capacity * sizeof( T ) ); \ + a->data = NULL; \ + a->count = 0; \ + a->capacity = 0; \ + } + +B2_DECLARE_ARRAY_NATIVE( int, b2Int ); +B2_ARRAY_INLINE( int, b2Int ) + +// Declare all the arrays +B2_ARRAY_DECLARE( b2Body, b2Body ); +B2_ARRAY_DECLARE( b2BodyMoveEvent, b2BodyMoveEvent ); +B2_ARRAY_DECLARE( b2BodySim, b2BodySim ); +B2_ARRAY_DECLARE( b2BodyState, b2BodyState ); +B2_ARRAY_DECLARE( b2ChainShape, b2ChainShape ); +B2_ARRAY_DECLARE( b2Contact, b2Contact ); +B2_ARRAY_DECLARE( b2ContactBeginTouchEvent, b2ContactBeginTouchEvent ); +B2_ARRAY_DECLARE( b2ContactEndTouchEvent, b2ContactEndTouchEvent ); +B2_ARRAY_DECLARE( b2ContactHitEvent, b2ContactHitEvent ); +B2_ARRAY_DECLARE( b2ContactSim, b2ContactSim ); +B2_ARRAY_DECLARE( b2Island, b2Island ); +B2_ARRAY_DECLARE( b2IslandSim, b2IslandSim ); +B2_ARRAY_DECLARE( b2Joint, b2Joint ); +B2_ARRAY_DECLARE( b2JointSim, b2JointSim ); +B2_ARRAY_DECLARE( b2Sensor, b2Sensor ); +B2_ARRAY_DECLARE( b2SensorBeginTouchEvent, b2SensorBeginTouchEvent ); +B2_ARRAY_DECLARE( b2SensorEndTouchEvent, b2SensorEndTouchEvent ); +B2_ARRAY_DECLARE( b2SensorTaskContext, b2SensorTaskContext ); +B2_ARRAY_DECLARE( b2Shape, b2Shape ); +B2_ARRAY_DECLARE( b2ShapeRef, b2ShapeRef ); +B2_ARRAY_DECLARE( b2SolverSet, b2SolverSet ); +B2_ARRAY_DECLARE( b2TaskContext, b2TaskContext ); diff --git a/3rdparty/box2d/src/atomic.h b/3rdparty/box2d/src/atomic.h new file mode 100644 index 000000000000..139a91926b26 --- /dev/null +++ b/3rdparty/box2d/src/atomic.h @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "core.h" + +#include + +#if defined( _MSC_VER ) +#include +#endif + +static inline void b2AtomicStoreInt( b2AtomicInt* a, int value ) +{ +#if defined( _MSC_VER ) + (void)_InterlockedExchange( (long*)&a->value, value ); +#elif defined( __GNUC__ ) || defined( __clang__ ) + __atomic_store_n( &a->value, value, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} + +static inline int b2AtomicLoadInt( b2AtomicInt* a ) +{ +#if defined( _MSC_VER ) + return _InterlockedOr( (long*)&a->value, 0 ); +#elif defined( __GNUC__ ) || defined( __clang__ ) + return __atomic_load_n( &a->value, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} + +static inline int b2AtomicFetchAddInt( b2AtomicInt* a, int increment ) +{ +#if defined( _MSC_VER ) + return _InterlockedExchangeAdd( (long*)&a->value, (long)increment ); +#elif defined( __GNUC__ ) || defined( __clang__ ) + return __atomic_fetch_add( &a->value, increment, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} + +static inline bool b2AtomicCompareExchangeInt( b2AtomicInt* a, int expected, int desired ) +{ +#if defined( _MSC_VER ) + return _InterlockedCompareExchange( (long*)&a->value, (long)desired, (long)expected ) == expected; +#elif defined( __GNUC__ ) || defined( __clang__ ) + // The value written to expected is ignored + return __atomic_compare_exchange_n( &a->value, &expected, desired, false, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} + +static inline void b2AtomicStoreU32( b2AtomicU32* a, uint32_t value ) +{ +#if defined( _MSC_VER ) + (void)_InterlockedExchange( (long*)&a->value, value ); +#elif defined( __GNUC__ ) || defined( __clang__ ) + __atomic_store_n( &a->value, value, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} + +static inline uint32_t b2AtomicLoadU32( b2AtomicU32* a ) +{ +#if defined( _MSC_VER ) + return (uint32_t)_InterlockedOr( (long*)&a->value, 0 ); +#elif defined( __GNUC__ ) || defined( __clang__ ) + return __atomic_load_n( &a->value, __ATOMIC_SEQ_CST ); +#else +#error "Unsupported platform" +#endif +} diff --git a/3rdparty/box2d/src/bitset.c b/3rdparty/box2d/src/bitset.c new file mode 100644 index 000000000000..a30464c67037 --- /dev/null +++ b/3rdparty/box2d/src/bitset.c @@ -0,0 +1,67 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "bitset.h" + +#include + +b2BitSet b2CreateBitSet( uint32_t bitCapacity ) +{ + b2BitSet bitSet = { 0 }; + + bitSet.blockCapacity = ( bitCapacity + sizeof( uint64_t ) * 8 - 1 ) / ( sizeof( uint64_t ) * 8 ); + bitSet.blockCount = 0; + bitSet.bits = b2Alloc( bitSet.blockCapacity * sizeof( uint64_t ) ); + memset( bitSet.bits, 0, bitSet.blockCapacity * sizeof( uint64_t ) ); + return bitSet; +} + +void b2DestroyBitSet( b2BitSet* bitSet ) +{ + b2Free( bitSet->bits, bitSet->blockCapacity * sizeof( uint64_t ) ); + bitSet->blockCapacity = 0; + bitSet->blockCount = 0; + bitSet->bits = NULL; +} + +void b2SetBitCountAndClear( b2BitSet* bitSet, uint32_t bitCount ) +{ + uint32_t blockCount = ( bitCount + sizeof( uint64_t ) * 8 - 1 ) / ( sizeof( uint64_t ) * 8 ); + if ( bitSet->blockCapacity < blockCount ) + { + b2DestroyBitSet( bitSet ); + uint32_t newBitCapacity = bitCount + ( bitCount >> 1 ); + *bitSet = b2CreateBitSet( newBitCapacity ); + } + + bitSet->blockCount = blockCount; + memset( bitSet->bits, 0, bitSet->blockCount * sizeof( uint64_t ) ); +} + +void b2GrowBitSet( b2BitSet* bitSet, uint32_t blockCount ) +{ + B2_ASSERT( blockCount > bitSet->blockCount ); + if ( blockCount > bitSet->blockCapacity ) + { + uint32_t oldCapacity = bitSet->blockCapacity; + bitSet->blockCapacity = blockCount + blockCount / 2; + uint64_t* newBits = b2Alloc( bitSet->blockCapacity * sizeof( uint64_t ) ); + memset( newBits, 0, bitSet->blockCapacity * sizeof( uint64_t ) ); + B2_ASSERT( bitSet->bits != NULL ); + memcpy( newBits, bitSet->bits, oldCapacity * sizeof( uint64_t ) ); + b2Free( bitSet->bits, oldCapacity * sizeof( uint64_t ) ); + bitSet->bits = newBits; + } + + bitSet->blockCount = blockCount; +} + +void b2InPlaceUnion( b2BitSet* B2_RESTRICT setA, const b2BitSet* B2_RESTRICT setB ) +{ + B2_ASSERT( setA->blockCount == setB->blockCount ); + uint32_t blockCount = setA->blockCount; + for ( uint32_t i = 0; i < blockCount; ++i ) + { + setA->bits[i] |= setB->bits[i]; + } +} diff --git a/3rdparty/box2d/src/bitset.h b/3rdparty/box2d/src/bitset.h new file mode 100644 index 000000000000..848b486d3807 --- /dev/null +++ b/3rdparty/box2d/src/bitset.h @@ -0,0 +1,65 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "core.h" + +#include +#include + +// Bit set provides fast operations on large arrays of bits. +typedef struct b2BitSet +{ + uint64_t* bits; + uint32_t blockCapacity; + uint32_t blockCount; +} b2BitSet; + +b2BitSet b2CreateBitSet( uint32_t bitCapacity ); +void b2DestroyBitSet( b2BitSet* bitSet ); +void b2SetBitCountAndClear( b2BitSet* bitSet, uint32_t bitCount ); +void b2InPlaceUnion( b2BitSet* setA, const b2BitSet* setB ); +void b2GrowBitSet( b2BitSet* bitSet, uint32_t blockCount ); + +static inline void b2SetBit( b2BitSet* bitSet, uint32_t bitIndex ) +{ + uint32_t blockIndex = bitIndex / 64; + B2_ASSERT( blockIndex < bitSet->blockCount ); + bitSet->bits[blockIndex] |= ( (uint64_t)1 << bitIndex % 64 ); +} + +static inline void b2SetBitGrow( b2BitSet* bitSet, uint32_t bitIndex ) +{ + uint32_t blockIndex = bitIndex / 64; + if ( blockIndex >= bitSet->blockCount ) + { + b2GrowBitSet( bitSet, blockIndex + 1 ); + } + bitSet->bits[blockIndex] |= ( (uint64_t)1 << bitIndex % 64 ); +} + +static inline void b2ClearBit( b2BitSet* bitSet, uint32_t bitIndex ) +{ + uint32_t blockIndex = bitIndex / 64; + if ( blockIndex >= bitSet->blockCount ) + { + return; + } + bitSet->bits[blockIndex] &= ~( (uint64_t)1 << bitIndex % 64 ); +} + +static inline bool b2GetBit( const b2BitSet* bitSet, uint32_t bitIndex ) +{ + uint32_t blockIndex = bitIndex / 64; + if ( blockIndex >= bitSet->blockCount ) + { + return false; + } + return ( bitSet->bits[blockIndex] & ( (uint64_t)1 << bitIndex % 64 ) ) != 0; +} + +static inline int b2GetBitSetBytes( b2BitSet* bitSet ) +{ + return bitSet->blockCapacity * sizeof( uint64_t ); +} diff --git a/3rdparty/box2d/src/body.c b/3rdparty/box2d/src/body.c new file mode 100644 index 000000000000..96ecbfbdb280 --- /dev/null +++ b/3rdparty/box2d/src/body.c @@ -0,0 +1,1884 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" + +#include "aabb.h" +#include "array.h" +#include "contact.h" +#include "core.h" +#include "id_pool.h" +#include "island.h" +#include "joint.h" +#include "shape.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "sensor.h" + +#include "box2d/box2d.h" +#include "box2d/id.h" + +#include + +// Implement functions for b2BodyArray +B2_ARRAY_SOURCE( b2Body, b2Body ) +B2_ARRAY_SOURCE( b2BodySim, b2BodySim ) +B2_ARRAY_SOURCE( b2BodyState, b2BodyState ) + +// Get a validated body from a world using an id. +b2Body* b2GetBodyFullId( b2World* world, b2BodyId bodyId ) +{ + B2_ASSERT( b2Body_IsValid( bodyId ) ); + + // id index starts at one so that zero can represent null + return b2BodyArray_Get( &world->bodies, bodyId.index1 - 1 ); +} + +b2Transform b2GetBodyTransformQuick( b2World* world, b2Body* body ) +{ + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, body->localIndex ); + return bodySim->transform; +} + +b2Transform b2GetBodyTransform( b2World* world, int bodyId ) +{ + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + return b2GetBodyTransformQuick( world, body ); +} + +// Create a b2BodyId from a raw id. +b2BodyId b2MakeBodyId( b2World* world, int bodyId ) +{ + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + return (b2BodyId){ bodyId + 1, world->worldId, body->generation }; +} + +b2BodySim* b2GetBodySim( b2World* world, b2Body* body ) +{ + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, body->localIndex ); + return bodySim; +} + +b2BodyState* b2GetBodyState( b2World* world, b2Body* body ) +{ + if ( body->setIndex == b2_awakeSet ) + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + return b2BodyStateArray_Get( &set->bodyStates, body->localIndex ); + } + + return NULL; +} + +static void b2CreateIslandForBody( b2World* world, int setIndex, b2Body* body ) +{ + B2_ASSERT( body->islandId == B2_NULL_INDEX ); + B2_ASSERT( body->islandPrev == B2_NULL_INDEX ); + B2_ASSERT( body->islandNext == B2_NULL_INDEX ); + B2_ASSERT( setIndex != b2_disabledSet ); + + b2Island* island = b2CreateIsland( world, setIndex ); + + body->islandId = island->islandId; + island->headBody = body->id; + island->tailBody = body->id; + island->bodyCount = 1; +} + +static void b2RemoveBodyFromIsland( b2World* world, b2Body* body ) +{ + if ( body->islandId == B2_NULL_INDEX ) + { + B2_ASSERT( body->islandPrev == B2_NULL_INDEX ); + B2_ASSERT( body->islandNext == B2_NULL_INDEX ); + return; + } + + int islandId = body->islandId; + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + // Fix the island's linked list of sims + if ( body->islandPrev != B2_NULL_INDEX ) + { + b2Body* prevBody = b2BodyArray_Get( &world->bodies, body->islandPrev ); + prevBody->islandNext = body->islandNext; + } + + if ( body->islandNext != B2_NULL_INDEX ) + { + b2Body* nextBody = b2BodyArray_Get( &world->bodies, body->islandNext ); + nextBody->islandPrev = body->islandPrev; + } + + B2_ASSERT( island->bodyCount > 0 ); + island->bodyCount -= 1; + bool islandDestroyed = false; + + if ( island->headBody == body->id ) + { + island->headBody = body->islandNext; + + if ( island->headBody == B2_NULL_INDEX ) + { + // Destroy empty island + B2_ASSERT( island->tailBody == body->id ); + B2_ASSERT( island->bodyCount == 0 ); + B2_ASSERT( island->contactCount == 0 ); + B2_ASSERT( island->jointCount == 0 ); + + // Free the island + b2DestroyIsland( world, island->islandId ); + islandDestroyed = true; + } + } + else if ( island->tailBody == body->id ) + { + island->tailBody = body->islandPrev; + } + + if ( islandDestroyed == false ) + { + b2ValidateIsland( world, islandId ); + } + + body->islandId = B2_NULL_INDEX; + body->islandPrev = B2_NULL_INDEX; + body->islandNext = B2_NULL_INDEX; +} + +static void b2DestroyBodyContacts( b2World* world, b2Body* body, bool wakeBodies ) +{ + // Destroy the attached contacts + int edgeKey = body->headContactKey; + while ( edgeKey != B2_NULL_INDEX ) + { + int contactId = edgeKey >> 1; + int edgeIndex = edgeKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + edgeKey = contact->edges[edgeIndex].nextKey; + b2DestroyContact( world, contact, wakeBodies ); + } + + b2ValidateSolverSets( world ); +} + +b2BodyId b2CreateBody( b2WorldId worldId, const b2BodyDef* def ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( b2IsValidVec2( def->position ) ); + B2_ASSERT( b2IsValidRotation( def->rotation ) ); + B2_ASSERT( b2IsValidVec2( def->linearVelocity ) ); + B2_ASSERT( b2IsValidFloat( def->angularVelocity ) ); + B2_ASSERT( b2IsValidFloat( def->linearDamping ) && def->linearDamping >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->angularDamping ) && def->angularDamping >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->sleepThreshold ) && def->sleepThreshold >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->gravityScale ) ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return b2_nullBodyId; + } + + bool isAwake = ( def->isAwake || def->enableSleep == false ) && def->isEnabled; + + // determine the solver set + int setId; + if ( def->isEnabled == false ) + { + // any body type can be disabled + setId = b2_disabledSet; + } + else if ( def->type == b2_staticBody ) + { + setId = b2_staticSet; + } + else if ( isAwake == true ) + { + setId = b2_awakeSet; + } + else + { + // new set for a sleeping body in its own island + setId = b2AllocId( &world->solverSetIdPool ); + if ( setId == world->solverSets.count ) + { + // Create a zero initialized solver set. All sub-arrays are also zero initialized. + b2SolverSetArray_Push( &world->solverSets, (b2SolverSet){ 0 } ); + } + else + { + B2_ASSERT( world->solverSets.data[setId].setIndex == B2_NULL_INDEX ); + } + + world->solverSets.data[setId].setIndex = setId; + } + + B2_ASSERT( 0 <= setId && setId < world->solverSets.count ); + + int bodyId = b2AllocId( &world->bodyIdPool ); + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setId ); + b2BodySim* bodySim = b2BodySimArray_Add( &set->bodySims ); + *bodySim = (b2BodySim){ 0 }; + bodySim->transform.p = def->position; + bodySim->transform.q = def->rotation; + bodySim->center = def->position; + bodySim->rotation0 = bodySim->transform.q; + bodySim->center0 = bodySim->center; + bodySim->minExtent = B2_HUGE; + bodySim->maxExtent = 0.0f; + bodySim->linearDamping = def->linearDamping; + bodySim->angularDamping = def->angularDamping; + bodySim->gravityScale = def->gravityScale; + bodySim->bodyId = bodyId; + bodySim->isBullet = def->isBullet; + bodySim->allowFastRotation = def->allowFastRotation; + + if ( setId == b2_awakeSet ) + { + b2BodyState* bodyState = b2BodyStateArray_Add( &set->bodyStates ); + B2_ASSERT( ( (uintptr_t)bodyState & 0x1F ) == 0 ); + + *bodyState = (b2BodyState){ 0 }; + bodyState->linearVelocity = def->linearVelocity; + bodyState->angularVelocity = def->angularVelocity; + bodyState->deltaRotation = b2Rot_identity; + } + + if ( bodyId == world->bodies.count ) + { + b2BodyArray_Push( &world->bodies, (b2Body){ 0 } ); + } + else + { + B2_ASSERT( world->bodies.data[bodyId].id == B2_NULL_INDEX ); + } + + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + + if ( def->name ) + { + int i = 0; + while ( i < 31 && def->name[i] != 0 ) + { + body->name[i] = def->name[i]; + i += 1; + } + + while ( i < 32) + { + body->name[i] = 0; + i += 1; + } + } + else + { + memset( body->name, 0, 32 * sizeof( char ) ); + } + + body->userData = def->userData; + body->setIndex = setId; + body->localIndex = set->bodySims.count - 1; + body->generation += 1; + body->headShapeId = B2_NULL_INDEX; + body->shapeCount = 0; + body->headChainId = B2_NULL_INDEX; + body->headContactKey = B2_NULL_INDEX; + body->contactCount = 0; + body->headJointKey = B2_NULL_INDEX; + body->jointCount = 0; + body->islandId = B2_NULL_INDEX; + body->islandPrev = B2_NULL_INDEX; + body->islandNext = B2_NULL_INDEX; + body->bodyMoveIndex = B2_NULL_INDEX; + body->id = bodyId; + body->mass = 0.0f; + body->inertia = 0.0f; + body->sleepThreshold = def->sleepThreshold; + body->sleepTime = 0.0f; + body->type = def->type; + body->enableSleep = def->enableSleep; + body->fixedRotation = def->fixedRotation; + body->isSpeedCapped = false; + body->isMarked = false; + + // dynamic and kinematic bodies that are enabled need a island + if ( setId >= b2_awakeSet ) + { + b2CreateIslandForBody( world, setId, body ); + } + + b2ValidateSolverSets( world ); + + b2BodyId id = { bodyId + 1, world->worldId, body->generation }; + return id; +} + +bool b2WakeBody( b2World* world, b2Body* body ) +{ + if ( body->setIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, body->setIndex ); + return true; + } + + return false; +} + +void b2DestroyBody( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + + // Wake bodies attached to this body, even if this body is static. + bool wakeBodies = true; + + // Destroy the attached joints + int edgeKey = body->headJointKey; + while ( edgeKey != B2_NULL_INDEX ) + { + int jointId = edgeKey >> 1; + int edgeIndex = edgeKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + edgeKey = joint->edges[edgeIndex].nextKey; + + // Careful because this modifies the list being traversed + b2DestroyJointInternal( world, joint, wakeBodies ); + } + + // Destroy all contacts attached to this body. + b2DestroyBodyContacts( world, body, wakeBodies ); + + // Destroy the attached shapes and their broad-phase proxies. + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + if ( shape->sensorIndex != B2_NULL_INDEX ) + { + b2DestroySensor( world, shape ); + } + + b2DestroyShapeProxy( shape, &world->broadPhase ); + + // Return shape to free list. + b2FreeId( &world->shapeIdPool, shapeId ); + shape->id = B2_NULL_INDEX; + + shapeId = shape->nextShapeId; + } + + // Destroy the attached chains. The associated shapes have already been destroyed above. + int chainId = body->headChainId; + while ( chainId != B2_NULL_INDEX ) + { + b2ChainShape* chain = b2ChainShapeArray_Get( &world->chainShapes, chainId ); + + b2FreeChainData( chain ); + + // Return chain to free list. + b2FreeId( &world->chainIdPool, chainId ); + chain->id = B2_NULL_INDEX; + + chainId = chain->nextChainId; + } + + b2RemoveBodyFromIsland( world, body ); + + // Remove body sim from solver set that owns it + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + int movedIndex = b2BodySimArray_RemoveSwap( &set->bodySims, body->localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix moved body index + b2BodySim* movedSim = set->bodySims.data + body->localIndex; + int movedId = movedSim->bodyId; + b2Body* movedBody = b2BodyArray_Get( &world->bodies, movedId ); + B2_ASSERT( movedBody->localIndex == movedIndex ); + movedBody->localIndex = body->localIndex; + } + + // Remove body state from awake set + if ( body->setIndex == b2_awakeSet ) + { + int result = b2BodyStateArray_RemoveSwap( &set->bodyStates, body->localIndex ); + B2_ASSERT( result == movedIndex ); + B2_UNUSED( result ); + } + else if ( set->setIndex >= b2_firstSleepingSet && set->bodySims.count == 0 ) + { + // Remove solver set if it's now an orphan. + b2DestroySolverSet( world, set->setIndex ); + } + + // Free body and id (preserve body generation) + b2FreeId( &world->bodyIdPool, body->id ); + + body->setIndex = B2_NULL_INDEX; + body->localIndex = B2_NULL_INDEX; + body->id = B2_NULL_INDEX; + + b2ValidateSolverSets( world ); +} + +int b2Body_GetContactCapacity( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + + // Conservative and fast + return body->contactCount; +} + +int b2Body_GetContactData( b2BodyId bodyId, b2ContactData* contactData, int capacity ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + + int contactKey = body->headContactKey; + int index = 0; + while ( contactKey != B2_NULL_INDEX && index < capacity ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + + // Is contact touching? + if ( contact->flags & b2_contactTouchingFlag ) + { + b2Shape* shapeA = b2ShapeArray_Get( &world->shapes, contact->shapeIdA ); + b2Shape* shapeB = b2ShapeArray_Get( &world->shapes, contact->shapeIdB ); + + contactData[index].shapeIdA = (b2ShapeId){ shapeA->id + 1, bodyId.world0, shapeA->generation }; + contactData[index].shapeIdB = (b2ShapeId){ shapeB->id + 1, bodyId.world0, shapeB->generation }; + + b2ContactSim* contactSim = b2GetContactSim( world, contact ); + contactData[index].manifold = contactSim->manifold; + + index += 1; + } + + contactKey = contact->edges[edgeIndex].nextKey; + } + + B2_ASSERT( index <= capacity ); + + return index; +} + +b2AABB b2Body_ComputeAABB( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return (b2AABB){ 0 }; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + if ( body->headShapeId == B2_NULL_INDEX ) + { + b2Transform transform = b2GetBodyTransform( world, body->id ); + return (b2AABB){ transform.p, transform.p }; + } + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, body->headShapeId ); + b2AABB aabb = shape->aabb; + while ( shape->nextShapeId != B2_NULL_INDEX ) + { + shape = b2ShapeArray_Get( &world->shapes, shape->nextShapeId ); + aabb = b2AABB_Union( aabb, shape->aabb ); + } + + return aabb; +} + +void b2UpdateBodyMassData( b2World* world, b2Body* body ) +{ + b2BodySim* bodySim = b2GetBodySim( world, body ); + + // Compute mass data from shapes. Each shape has its own density. + body->mass = 0.0f; + body->inertia = 0.0f; + + bodySim->invMass = 0.0f; + bodySim->invInertia = 0.0f; + bodySim->localCenter = b2Vec2_zero; + bodySim->minExtent = B2_HUGE; + bodySim->maxExtent = 0.0f; + + // Static and kinematic sims have zero mass. + if ( body->type != b2_dynamicBody ) + { + bodySim->center = bodySim->transform.p; + + // Need extents for kinematic bodies for sleeping to work correctly. + if ( body->type == b2_kinematicBody ) + { + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + const b2Shape* s = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2ShapeExtent extent = b2ComputeShapeExtent( s, b2Vec2_zero ); + bodySim->minExtent = b2MinFloat( bodySim->minExtent, extent.minExtent ); + bodySim->maxExtent = b2MaxFloat( bodySim->maxExtent, extent.maxExtent ); + + shapeId = s->nextShapeId; + } + } + + return; + } + + // Accumulate mass over all shapes. + b2Vec2 localCenter = b2Vec2_zero; + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + const b2Shape* s = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = s->nextShapeId; + + if ( s->density == 0.0f ) + { + continue; + } + + b2MassData massData = b2ComputeShapeMass( s ); + body->mass += massData.mass; + localCenter = b2MulAdd( localCenter, massData.mass, massData.center ); + body->inertia += massData.rotationalInertia; + } + + // Compute center of mass. + if ( body->mass > 0.0f ) + { + bodySim->invMass = 1.0f / body->mass; + localCenter = b2MulSV( bodySim->invMass, localCenter ); + } + + if ( body->inertia > 0.0f && body->fixedRotation == false ) + { + // Center the inertia about the center of mass. + body->inertia -= body->mass * b2Dot( localCenter, localCenter ); + B2_ASSERT( body->inertia > 0.0f ); + bodySim->invInertia = 1.0f / body->inertia; + } + else + { + body->inertia = 0.0f; + bodySim->invInertia = 0.0f; + } + + // Move center of mass. + b2Vec2 oldCenter = bodySim->center; + bodySim->localCenter = localCenter; + bodySim->center = b2TransformPoint( bodySim->transform, bodySim->localCenter ); + bodySim->center0 = bodySim->center; + + // Update center of mass velocity + b2BodyState* state = b2GetBodyState( world, body ); + if ( state != NULL ) + { + b2Vec2 deltaLinear = b2CrossSV( state->angularVelocity, b2Sub( bodySim->center, oldCenter ) ); + state->linearVelocity = b2Add( state->linearVelocity, deltaLinear ); + } + + // Compute body extents relative to center of mass + shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + const b2Shape* s = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2ShapeExtent extent = b2ComputeShapeExtent( s, localCenter ); + bodySim->minExtent = b2MinFloat( bodySim->minExtent, extent.minExtent ); + bodySim->maxExtent = b2MaxFloat( bodySim->maxExtent, extent.maxExtent ); + + shapeId = s->nextShapeId; + } +} + +b2Vec2 b2Body_GetPosition( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return transform.p; +} + +b2Rot b2Body_GetRotation( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return transform.q; +} + +b2Transform b2Body_GetTransform( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return b2GetBodyTransformQuick( world, body ); +} + +b2Vec2 b2Body_GetLocalPoint( b2BodyId bodyId, b2Vec2 worldPoint ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return b2InvTransformPoint( transform, worldPoint ); +} + +b2Vec2 b2Body_GetWorldPoint( b2BodyId bodyId, b2Vec2 localPoint ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return b2TransformPoint( transform, localPoint ); +} + +b2Vec2 b2Body_GetLocalVector( b2BodyId bodyId, b2Vec2 worldVector ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return b2InvRotateVector( transform.q, worldVector ); +} + +b2Vec2 b2Body_GetWorldVector( b2BodyId bodyId, b2Vec2 localVector ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + return b2RotateVector( transform.q, localVector ); +} + +void b2Body_SetTransform( b2BodyId bodyId, b2Vec2 position, b2Rot rotation ) +{ + B2_ASSERT( b2IsValidVec2( position ) ); + B2_ASSERT( b2IsValidRotation( rotation ) ); + B2_ASSERT( b2Body_IsValid( bodyId ) ); + b2World* world = b2GetWorld( bodyId.world0 ); + B2_ASSERT( world->locked == false ); + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + + bodySim->transform.p = position; + bodySim->transform.q = rotation; + bodySim->center = b2TransformPoint( bodySim->transform, bodySim->localCenter ); + + bodySim->rotation0 = bodySim->transform.q; + bodySim->center0 = bodySim->center; + + b2BroadPhase* broadPhase = &world->broadPhase; + + b2Transform transform = bodySim->transform; + const float margin = B2_AABB_MARGIN; + const float speculativeDistance = B2_SPECULATIVE_DISTANCE; + + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + b2AABB aabb = b2ComputeShapeAABB( shape, transform ); + aabb.lowerBound.x -= speculativeDistance; + aabb.lowerBound.y -= speculativeDistance; + aabb.upperBound.x += speculativeDistance; + aabb.upperBound.y += speculativeDistance; + shape->aabb = aabb; + + if ( b2AABB_Contains( shape->fatAABB, aabb ) == false ) + { + b2AABB fatAABB; + fatAABB.lowerBound.x = aabb.lowerBound.x - margin; + fatAABB.lowerBound.y = aabb.lowerBound.y - margin; + fatAABB.upperBound.x = aabb.upperBound.x + margin; + fatAABB.upperBound.y = aabb.upperBound.y + margin; + shape->fatAABB = fatAABB; + + // They body could be disabled + if ( shape->proxyKey != B2_NULL_INDEX ) + { + b2BroadPhase_MoveProxy( broadPhase, shape->proxyKey, fatAABB ); + } + } + + shapeId = shape->nextShapeId; + } +} + +b2Vec2 b2Body_GetLinearVelocity( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodyState* state = b2GetBodyState( world, body ); + if ( state != NULL ) + { + return state->linearVelocity; + } + return b2Vec2_zero; +} + +float b2Body_GetAngularVelocity( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodyState* state = b2GetBodyState( world, body ); + if ( state != NULL ) + { + return state->angularVelocity; + } + return 0.0; +} + +void b2Body_SetLinearVelocity( b2BodyId bodyId, b2Vec2 linearVelocity ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( body->type == b2_staticBody ) + { + return; + } + + if ( b2LengthSquared( linearVelocity ) > 0.0f ) + { + b2WakeBody( world, body ); + } + + b2BodyState* state = b2GetBodyState( world, body ); + if ( state == NULL ) + { + return; + } + + state->linearVelocity = linearVelocity; +} + +void b2Body_SetAngularVelocity( b2BodyId bodyId, float angularVelocity ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( body->type == b2_staticBody || body->fixedRotation ) + { + return; + } + + if ( angularVelocity != 0.0f ) + { + b2WakeBody( world, body ); + } + + b2BodyState* state = b2GetBodyState( world, body ); + if ( state == NULL ) + { + return; + } + + state->angularVelocity = angularVelocity; +} + +void b2Body_SetTargetTransform( b2BodyId bodyId, b2Transform target, float timeStep ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( body->type == b2_staticBody || timeStep <= 0.0f ) + { + return; + } + + b2BodySim* sim = b2GetBodySim( world, body ); + + // Compute linear velocity + b2Vec2 center1 = sim->center; + b2Vec2 center2 = b2TransformPoint( target, sim->localCenter ); + float invTimeStep = 1.0f / timeStep; + b2Vec2 linearVelocity = b2MulSV( invTimeStep, b2Sub( center2, center1 ) ); + + // Compute angular velocity + float angularVelocity = 0.0f; + if ( body->fixedRotation == false ) + { + b2Rot q1 = sim->transform.q; + b2Rot q2 = target.q; + float deltaAngle = b2RelativeAngle( q2, q1 ); + angularVelocity = invTimeStep * deltaAngle; + } + + // Return if velocity would be zero + if ( b2LengthSquared( linearVelocity ) == 0.0f && b2AbsFloat( angularVelocity ) == 0.0f ) + { + return; + } + + // Must wake for state to exist + b2WakeBody( world, body ); + + b2BodyState* state = b2GetBodyState( world, body ); + if ( state == NULL ) + { + return; + } + + state->linearVelocity = linearVelocity; + state->angularVelocity = angularVelocity; +} + +b2Vec2 b2Body_GetLocalPointVelocity( b2BodyId bodyId, b2Vec2 localPoint ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodyState* state = b2GetBodyState( world, body ); + if ( state == NULL ) + { + return b2Vec2_zero; + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, body->localIndex ); + + b2Vec2 r = b2RotateVector( bodySim->transform.q, b2Sub( localPoint, bodySim->localCenter ) ); + b2Vec2 v = b2Add( state->linearVelocity, b2CrossSV( state->angularVelocity, r ) ); + return v; +} + +b2Vec2 b2Body_GetWorldPointVelocity( b2BodyId bodyId, b2Vec2 worldPoint ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodyState* state = b2GetBodyState( world, body ); + if ( state == NULL ) + { + return b2Vec2_zero; + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, body->localIndex ); + + b2Vec2 r = b2Sub( worldPoint, bodySim->center ); + b2Vec2 v = b2Add( state->linearVelocity, b2CrossSV( state->angularVelocity, r ) ); + return v; +} + +void b2Body_ApplyForce( b2BodyId bodyId, b2Vec2 force, b2Vec2 point, bool wake ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->force = b2Add( bodySim->force, force ); + bodySim->torque += b2Cross( b2Sub( point, bodySim->center ), force ); + } +} + +void b2Body_ApplyForceToCenter( b2BodyId bodyId, b2Vec2 force, bool wake ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->force = b2Add( bodySim->force, force ); + } +} + +void b2Body_ApplyTorque( b2BodyId bodyId, float torque, bool wake ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->torque += torque; + } +} + +void b2Body_ApplyLinearImpulse( b2BodyId bodyId, b2Vec2 impulse, b2Vec2 point, bool wake ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + int localIndex = body->localIndex; + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* state = b2BodyStateArray_Get( &set->bodyStates, localIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, localIndex ); + state->linearVelocity = b2MulAdd( state->linearVelocity, bodySim->invMass, impulse ); + state->angularVelocity += bodySim->invInertia * b2Cross( b2Sub( point, bodySim->center ), impulse ); + } +} + +void b2Body_ApplyLinearImpulseToCenter( b2BodyId bodyId, b2Vec2 impulse, bool wake ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + int localIndex = body->localIndex; + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* state = b2BodyStateArray_Get( &set->bodyStates, localIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, localIndex ); + state->linearVelocity = b2MulAdd( state->linearVelocity, bodySim->invMass, impulse ); + } +} + +void b2Body_ApplyAngularImpulse( b2BodyId bodyId, float impulse, bool wake ) +{ + B2_ASSERT( b2Body_IsValid( bodyId ) ); + b2World* world = b2GetWorld( bodyId.world0 ); + + int id = bodyId.index1 - 1; + b2Body* body = b2BodyArray_Get( &world->bodies, id ); + B2_ASSERT( body->generation == bodyId.generation ); + + if ( wake && body->setIndex >= b2_firstSleepingSet ) + { + // this will not invalidate body pointer + b2WakeBody( world, body ); + } + + if ( body->setIndex == b2_awakeSet ) + { + int localIndex = body->localIndex; + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* state = b2BodyStateArray_Get( &set->bodyStates, localIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, localIndex ); + state->angularVelocity += bodySim->invInertia * impulse; + } +} + +b2BodyType b2Body_GetType( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->type; +} + +// Changing the body type is quite complex mainly due to joints. +// Considerations: +// - body and joints must be moved to the correct set +// - islands must be updated +// - graph coloring must be correct +// - any body connected to a joint may be disabled +// - joints between static bodies must go into the static set +void b2Body_SetType( b2BodyId bodyId, b2BodyType type ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + b2BodyType originalType = body->type; + if ( originalType == type ) + { + return; + } + + if ( body->setIndex == b2_disabledSet ) + { + // Disabled bodies don't change solver sets or islands when they change type. + body->type = type; + + // Body type affects the mass + b2UpdateBodyMassData( world, body ); + return; + } + + // Destroy all contacts but don't wake bodies. + bool wakeBodies = false; + b2DestroyBodyContacts( world, body, wakeBodies ); + + // Wake this body because we assume below that it is awake or static. + b2WakeBody( world, body ); + + // Unlink all joints and wake attached bodies. + { + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + if ( joint->islandId != B2_NULL_INDEX ) + { + b2UnlinkJoint( world, joint ); + } + + // A body going from static to dynamic or kinematic goes to the awake set + // and other attached bodies must be awake as well. For consistency, this is + // done for all cases. + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + b2WakeBody( world, bodyA ); + b2WakeBody( world, bodyB ); + + jointKey = joint->edges[edgeIndex].nextKey; + } + } + + body->type = type; + + if ( originalType == b2_staticBody ) + { + // Body is going from static to dynamic or kinematic. It only makes sense to move it to the awake set. + B2_ASSERT( body->setIndex == b2_staticSet ); + + b2SolverSet* staticSet = b2SolverSetArray_Get( &world->solverSets, b2_staticSet ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + + // Transfer body to awake set + b2TransferBody( world, awakeSet, staticSet, body ); + + // Create island for body + b2CreateIslandForBody( world, b2_awakeSet, body ); + + // Transfer static joints to awake set + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + + // Transfer the joint if it is in the static set + if ( joint->setIndex == b2_staticSet ) + { + b2TransferJoint( world, awakeSet, staticSet, joint ); + } + else if ( joint->setIndex == b2_awakeSet ) + { + // In this case the joint must be re-inserted into the constraint graph to ensure the correct + // graph color. + + // First transfer to the static set. + b2TransferJoint( world, staticSet, awakeSet, joint ); + + // Now transfer it back to the awake set and into the graph coloring. + b2TransferJoint( world, awakeSet, staticSet, joint ); + } + else + { + // Otherwise the joint must be disabled. + B2_ASSERT( joint->setIndex == b2_disabledSet ); + } + + jointKey = joint->edges[edgeIndex].nextKey; + } + + // Recreate shape proxies in movable tree. + b2Transform transform = b2GetBodyTransformQuick( world, body ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = shape->nextShapeId; + b2DestroyShapeProxy( shape, &world->broadPhase ); + bool forcePairCreation = true; + b2BodyType proxyType = type; + b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, forcePairCreation ); + } + } + else if ( type == b2_staticBody ) + { + // The body is going from dynamic/kinematic to static. It should be awake. + B2_ASSERT( body->setIndex == b2_awakeSet ); + + b2SolverSet* staticSet = b2SolverSetArray_Get( &world->solverSets, b2_staticSet ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + + // Transfer body to static set + b2TransferBody( world, staticSet, awakeSet, body ); + + // Remove body from island. + b2RemoveBodyFromIsland( world, body ); + + b2BodySim* bodySim = b2BodySimArray_Get( &staticSet->bodySims, body->localIndex ); + bodySim->isFast = false; + + // Maybe transfer joints to static set. + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + jointKey = joint->edges[edgeIndex].nextKey; + + int otherEdgeIndex = edgeIndex ^ 1; + b2Body* otherBody = b2BodyArray_Get( &world->bodies, joint->edges[otherEdgeIndex].bodyId ); + + // Skip disabled joint + if ( joint->setIndex == b2_disabledSet ) + { + // Joint is disable, should be connected to a disabled body + B2_ASSERT( otherBody->setIndex == b2_disabledSet ); + continue; + } + + // Since the body was not static, the joint must be awake. + B2_ASSERT( joint->setIndex == b2_awakeSet ); + + // Only transfer joint to static set if both bodies are static. + if ( otherBody->setIndex == b2_staticSet ) + { + b2TransferJoint( world, staticSet, awakeSet, joint ); + } + else + { + // The other body must be awake. + B2_ASSERT( otherBody->setIndex == b2_awakeSet ); + + // The joint must live in a graph color. + B2_ASSERT( 0 <= joint->colorIndex && joint->colorIndex < B2_GRAPH_COLOR_COUNT ); + + // In this case the joint must be re-inserted into the constraint graph to ensure the correct + // graph color. + + // First transfer to the static set. + b2TransferJoint( world, staticSet, awakeSet, joint ); + + // Now transfer it back to the awake set and into the graph coloring. + b2TransferJoint( world, awakeSet, staticSet, joint ); + } + } + + // Recreate shape proxies in static tree. + b2Transform transform = b2GetBodyTransformQuick( world, body ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = shape->nextShapeId; + b2DestroyShapeProxy( shape, &world->broadPhase ); + bool forcePairCreation = true; + b2CreateShapeProxy( shape, &world->broadPhase, b2_staticBody, transform, forcePairCreation ); + } + } + else + { + B2_ASSERT( originalType == b2_dynamicBody || originalType == b2_kinematicBody ); + B2_ASSERT( type == b2_dynamicBody || type == b2_kinematicBody ); + + // Recreate shape proxies in static tree. + b2Transform transform = b2GetBodyTransformQuick( world, body ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = shape->nextShapeId; + b2DestroyShapeProxy( shape, &world->broadPhase ); + b2BodyType proxyType = type; + bool forcePairCreation = true; + b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, forcePairCreation ); + } + } + + // Relink all joints + { + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + jointKey = joint->edges[edgeIndex].nextKey; + + int otherEdgeIndex = edgeIndex ^ 1; + int otherBodyId = joint->edges[otherEdgeIndex].bodyId; + b2Body* otherBody = b2BodyArray_Get( &world->bodies, otherBodyId ); + + if ( otherBody->setIndex == b2_disabledSet ) + { + continue; + } + + if ( body->type == b2_staticBody && otherBody->type == b2_staticBody ) + { + continue; + } + + b2LinkJoint( world, joint, false ); + } + + b2MergeAwakeIslands( world ); + } + + // Body type affects the mass + b2UpdateBodyMassData( world, body ); + + b2ValidateSolverSets( world ); +} + +void b2Body_SetName( b2BodyId bodyId, const char* name ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( name != NULL ) + { + for ( int i = 0; i < 31; ++i ) + { + body->name[i] = name[i]; + } + + body->name[31] = 0; + } + else + { + memset( body->name, 0, 32 * sizeof( char ) ); + } +} + +const char* b2Body_GetName( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->name; +} + +void b2Body_SetUserData( b2BodyId bodyId, void* userData ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + body->userData = userData; +} + +void* b2Body_GetUserData( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->userData; +} + +float b2Body_GetMass( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->mass; +} + +float b2Body_GetRotationalInertia( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->inertia; +} + +b2Vec2 b2Body_GetLocalCenterOfMass( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->localCenter; +} + +b2Vec2 b2Body_GetWorldCenterOfMass( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->center; +} + +void b2Body_SetMassData( b2BodyId bodyId, b2MassData massData ) +{ + B2_ASSERT( b2IsValidFloat( massData.mass ) && massData.mass >= 0.0f ); + B2_ASSERT( b2IsValidFloat( massData.rotationalInertia ) && massData.rotationalInertia >= 0.0f ); + B2_ASSERT( b2IsValidVec2( massData.center ) ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + + body->mass = massData.mass; + body->inertia = massData.rotationalInertia; + bodySim->localCenter = massData.center; + + b2Vec2 center = b2TransformPoint( bodySim->transform, massData.center ); + bodySim->center = center; + bodySim->center0 = center; + + bodySim->invMass = body->mass > 0.0f ? 1.0f / body->mass : 0.0f; + bodySim->invInertia = body->inertia > 0.0f ? 1.0f / body->inertia : 0.0f; +} + +b2MassData b2Body_GetMassData( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + b2MassData massData = { body->mass, bodySim->localCenter, body->inertia }; + return massData; +} + +void b2Body_ApplyMassFromShapes( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2UpdateBodyMassData( world, body ); +} + +void b2Body_SetLinearDamping( b2BodyId bodyId, float linearDamping ) +{ + B2_ASSERT( b2IsValidFloat( linearDamping ) && linearDamping >= 0.0f ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->linearDamping = linearDamping; +} + +float b2Body_GetLinearDamping( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->linearDamping; +} + +void b2Body_SetAngularDamping( b2BodyId bodyId, float angularDamping ) +{ + B2_ASSERT( b2IsValidFloat( angularDamping ) && angularDamping >= 0.0f ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->angularDamping = angularDamping; +} + +float b2Body_GetAngularDamping( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->angularDamping; +} + +void b2Body_SetGravityScale( b2BodyId bodyId, float gravityScale ) +{ + B2_ASSERT( b2Body_IsValid( bodyId ) ); + B2_ASSERT( b2IsValidFloat( gravityScale ) ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->gravityScale = gravityScale; +} + +float b2Body_GetGravityScale( b2BodyId bodyId ) +{ + B2_ASSERT( b2Body_IsValid( bodyId ) ); + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->gravityScale; +} + +bool b2Body_IsAwake( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->setIndex == b2_awakeSet; +} + +void b2Body_SetAwake( b2BodyId bodyId, bool awake ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + + if ( awake && body->setIndex >= b2_firstSleepingSet ) + { + b2WakeBody( world, body ); + } + else if ( awake == false && body->setIndex == b2_awakeSet ) + { + b2Island* island = b2IslandArray_Get( &world->islands, body->islandId ); + if ( island->constraintRemoveCount > 0 ) + { + // Must split the island before sleeping. This is expensive. + b2SplitIsland( world, body->islandId ); + } + + b2TrySleepIsland( world, body->islandId ); + } +} + +bool b2Body_IsEnabled( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->setIndex != b2_disabledSet; +} + +bool b2Body_IsSleepEnabled( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->enableSleep; +} + +void b2Body_SetSleepThreshold( b2BodyId bodyId, float sleepThreshold ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + body->sleepThreshold = sleepThreshold; +} + +float b2Body_GetSleepThreshold( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->sleepThreshold; +} + +void b2Body_EnableSleep( b2BodyId bodyId, bool enableSleep ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + body->enableSleep = enableSleep; + + if ( enableSleep == false ) + { + b2WakeBody( world, body ); + } +} + +// Disabling a body requires a lot of detailed bookkeeping, but it is a valuable feature. +// The most challenging aspect that joints may connect to bodies that are not disabled. +void b2Body_Disable( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + if ( body->setIndex == b2_disabledSet ) + { + return; + } + + // Destroy contacts and wake bodies touching this body. This avoid floating bodies. + // This is necessary even for static bodies. + bool wakeBodies = true; + b2DestroyBodyContacts( world, body, wakeBodies ); + + // Disabled bodies are not in an island. + b2RemoveBodyFromIsland( world, body ); + + // Remove shapes from broad-phase + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = shape->nextShapeId; + b2DestroyShapeProxy( shape, &world->broadPhase ); + } + + // Transfer simulation data to disabled set + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, body->setIndex ); + b2SolverSet* disabledSet = b2SolverSetArray_Get( &world->solverSets, b2_disabledSet ); + + // Transfer body sim + b2TransferBody( world, disabledSet, set, body ); + + // Unlink joints and transfer + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + jointKey = joint->edges[edgeIndex].nextKey; + + // joint may already be disabled by other body + if ( joint->setIndex == b2_disabledSet ) + { + continue; + } + + B2_ASSERT( joint->setIndex == set->setIndex || set->setIndex == b2_staticSet ); + + // Remove joint from island + if ( joint->islandId != B2_NULL_INDEX ) + { + b2UnlinkJoint( world, joint ); + } + + // Transfer joint to disabled set + b2SolverSet* jointSet = b2SolverSetArray_Get( &world->solverSets, joint->setIndex ); + b2TransferJoint( world, disabledSet, jointSet, joint ); + } + + b2ValidateConnectivity( world ); + b2ValidateSolverSets( world ); +} + +void b2Body_Enable( b2BodyId bodyId ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + if ( body->setIndex != b2_disabledSet ) + { + return; + } + + b2SolverSet* disabledSet = b2SolverSetArray_Get( &world->solverSets, b2_disabledSet ); + int setId = body->type == b2_staticBody ? b2_staticSet : b2_awakeSet; + b2SolverSet* targetSet = b2SolverSetArray_Get( &world->solverSets, setId ); + + b2TransferBody( world, targetSet, disabledSet, body ); + + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + // Add shapes to broad-phase + b2BodyType proxyType = body->type; + bool forcePairCreation = true; + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = shape->nextShapeId; + + b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, forcePairCreation ); + } + + if ( setId != b2_staticSet ) + { + b2CreateIslandForBody( world, setId, body ); + } + + // Transfer joints. If the other body is disabled, don't transfer. + // If the other body is sleeping, wake it. + bool mergeIslands = false; + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + B2_ASSERT( joint->setIndex == b2_disabledSet ); + B2_ASSERT( joint->islandId == B2_NULL_INDEX ); + + jointKey = joint->edges[edgeIndex].nextKey; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + + if ( bodyA->setIndex == b2_disabledSet || bodyB->setIndex == b2_disabledSet ) + { + // one body is still disabled + continue; + } + + // Transfer joint first + int jointSetId; + if ( bodyA->setIndex == b2_staticSet && bodyB->setIndex == b2_staticSet ) + { + jointSetId = b2_staticSet; + } + else if ( bodyA->setIndex == b2_staticSet ) + { + jointSetId = bodyB->setIndex; + } + else + { + jointSetId = bodyA->setIndex; + } + + b2SolverSet* jointSet = b2SolverSetArray_Get( &world->solverSets, jointSetId ); + b2TransferJoint( world, jointSet, disabledSet, joint ); + + // Now that the joint is in the correct set, I can link the joint in the island. + if ( jointSetId != b2_staticSet ) + { + b2LinkJoint( world, joint, mergeIslands ); + } + } + + // Now merge islands + b2MergeAwakeIslands( world ); + + b2ValidateSolverSets( world ); +} + +void b2Body_SetFixedRotation( b2BodyId bodyId, bool flag ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + if ( body->fixedRotation != flag ) + { + body->fixedRotation = flag; + + b2BodyState* state = b2GetBodyState( world, body ); + if ( state != NULL ) + { + state->angularVelocity = 0.0f; + } + b2UpdateBodyMassData( world, body ); + } +} + +bool b2Body_IsFixedRotation( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->fixedRotation; +} + +void b2Body_SetBullet( b2BodyId bodyId, bool flag ) +{ + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + bodySim->isBullet = flag; +} + +bool b2Body_IsBullet( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + return bodySim->isBullet; +} + +void b2Body_EnableContactEvents( b2BodyId bodyId, bool flag ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shape->enableContactEvents = flag; + shapeId = shape->nextShapeId; + } +} + +void b2Body_EnableHitEvents( b2BodyId bodyId, bool flag ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shape->enableHitEvents = flag; + shapeId = shape->nextShapeId; + } +} + +b2WorldId b2Body_GetWorld( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + return (b2WorldId){ bodyId.world0 + 1, world->generation }; +} + +int b2Body_GetShapeCount( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->shapeCount; +} + +int b2Body_GetShapes( b2BodyId bodyId, b2ShapeId* shapeArray, int capacity ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + int shapeId = body->headShapeId; + int shapeCount = 0; + while ( shapeId != B2_NULL_INDEX && shapeCount < capacity ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + b2ShapeId id = { shape->id + 1, bodyId.world0, shape->generation }; + shapeArray[shapeCount] = id; + shapeCount += 1; + + shapeId = shape->nextShapeId; + } + + return shapeCount; +} + +int b2Body_GetJointCount( b2BodyId bodyId ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + return body->jointCount; +} + +int b2Body_GetJoints( b2BodyId bodyId, b2JointId* jointArray, int capacity ) +{ + b2World* world = b2GetWorld( bodyId.world0 ); + b2Body* body = b2GetBodyFullId( world, bodyId ); + int jointKey = body->headJointKey; + + int jointCount = 0; + while ( jointKey != B2_NULL_INDEX && jointCount < capacity ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + + b2JointId id = { jointId + 1, bodyId.world0, joint->generation }; + jointArray[jointCount] = id; + jointCount += 1; + + jointKey = joint->edges[edgeIndex].nextKey; + } + + return jointCount; +} + +bool b2ShouldBodiesCollide( b2World* world, b2Body* bodyA, b2Body* bodyB ) +{ + if ( bodyA->type != b2_dynamicBody && bodyB->type != b2_dynamicBody ) + { + return false; + } + + int jointKey; + int otherBodyId; + if ( bodyA->jointCount < bodyB->jointCount ) + { + jointKey = bodyA->headJointKey; + otherBodyId = bodyB->id; + } + else + { + jointKey = bodyB->headJointKey; + otherBodyId = bodyA->id; + } + + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + int otherEdgeIndex = edgeIndex ^ 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + if ( joint->collideConnected == false && joint->edges[otherEdgeIndex].bodyId == otherBodyId ) + { + return false; + } + + jointKey = joint->edges[edgeIndex].nextKey; + } + + return true; +} diff --git a/3rdparty/box2d/src/body.h b/3rdparty/box2d/src/body.h new file mode 100644 index 000000000000..7f2786608cef --- /dev/null +++ b/3rdparty/box2d/src/body.h @@ -0,0 +1,194 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +#include "box2d/math_functions.h" +#include "box2d/types.h" + +typedef struct b2World b2World; + +// Body organizational details that are not used in the solver. +typedef struct b2Body +{ + char name[32]; + + void* userData; + + // index of solver set stored in b2World + // may be B2_NULL_INDEX + int setIndex; + + // body sim and state index within set + // may be B2_NULL_INDEX + int localIndex; + + // [31 : contactId | 1 : edgeIndex] + int headContactKey; + int contactCount; + + // todo maybe move this to the body sim + int headShapeId; + int shapeCount; + + int headChainId; + + // [31 : jointId | 1 : edgeIndex] + int headJointKey; + int jointCount; + + // All enabled dynamic and kinematic bodies are in an island. + int islandId; + + // doubly-linked island list + int islandPrev; + int islandNext; + + float mass; + + // Rotational inertia about the center of mass. + float inertia; + + float sleepThreshold; + float sleepTime; + + // this is used to adjust the fellAsleep flag in the body move array + int bodyMoveIndex; + + int id; + + b2BodyType type; + + // This is monotonically advanced when a body is allocated in this slot + // Used to check for invalid b2BodyId + uint16_t generation; + + bool enableSleep; + bool fixedRotation; + bool isSpeedCapped; + bool isMarked; +} b2Body; + +// Body State +// The body state is designed for fast conversion to and from SIMD via scatter-gather. +// Only awake dynamic and kinematic bodies have a body state. +// This is used in the performance critical constraint solver +// +// The solver operates on the body state. The body state array does not hold static bodies. Static bodies are shared +// across worker threads. It would be okay to read their states, but writing to them would cause cache thrashing across +// workers, even if the values don't change. +// This causes some trouble when computing anchors. I rotate joint anchors using the body rotation every sub-step. For static +// bodies the anchor doesn't rotate. Body A or B could be static and this can lead to lots of branching. This branching +// should be minimized. +// +// Solution 1: +// Use delta rotations. This means anchors need to be prepared in world space. The delta rotation for static bodies will be +// identity using a dummy state. Base separation and angles need to be computed. Manifolds will be behind a frame, but that +// is probably best if bodies move fast. +// +// Solution 2: +// Use full rotation. The anchors for static bodies will be in world space while the anchors for dynamic bodies will be in local +// space. Potentially confusing and bug prone. +// +// Note: +// I rotate joint anchors each sub-step but not contact anchors. Joint stability improves a lot by rotating joint anchors +// according to substep progress. Contacts have reduced stability when anchors are rotated during substeps, especially for +// round shapes. + +// 32 bytes +typedef struct b2BodyState +{ + b2Vec2 linearVelocity; // 8 + float angularVelocity; // 4 + int flags; // 4 + + // Using delta position reduces round-off error far from the origin + b2Vec2 deltaPosition; // 8 + + // Using delta rotation because I cannot access the full rotation on static bodies in + // the solver and must use zero delta rotation for static bodies (c,s) = (1,0) + b2Rot deltaRotation; // 8 +} b2BodyState; + +// Identity body state, notice the deltaRotation is {1, 0} +static const b2BodyState b2_identityBodyState = { { 0.0f, 0.0f }, 0.0f, 0, { 0.0f, 0.0f }, { 1.0f, 0.0f } }; + +// Body simulation data used for integration of position and velocity +// Transform data used for collision and solver preparation. +typedef struct b2BodySim +{ + // todo better to have transform in sim or in base body? Try both! + // transform for body origin + b2Transform transform; + + // center of mass position in world space + b2Vec2 center; + + // previous rotation and COM for TOI + b2Rot rotation0; + b2Vec2 center0; + + // location of center of mass relative to the body origin + b2Vec2 localCenter; + + b2Vec2 force; + float torque; + + // inverse inertia + float invMass; + float invInertia; + + float minExtent; + float maxExtent; + float linearDamping; + float angularDamping; + float gravityScale; + + // body data can be moved around, the id is stable (used in b2BodyId) + int bodyId; + + // This flag is used for debug draw + bool isFast; + + bool isBullet; + bool isSpeedCapped; + bool allowFastRotation; + bool enlargeAABB; +} b2BodySim; + +// Get a validated body from a world using an id. +b2Body* b2GetBodyFullId( b2World* world, b2BodyId bodyId ); + +b2Transform b2GetBodyTransformQuick( b2World* world, b2Body* body ); +b2Transform b2GetBodyTransform( b2World* world, int bodyId ); + +// Create a b2BodyId from a raw id. +b2BodyId b2MakeBodyId( b2World* world, int bodyId ); + +bool b2ShouldBodiesCollide( b2World* world, b2Body* bodyA, b2Body* bodyB ); + +b2BodySim* b2GetBodySim( b2World* world, b2Body* body ); +b2BodyState* b2GetBodyState( b2World* world, b2Body* body ); + +// careful calling this because it can invalidate body, state, joint, and contact pointers +bool b2WakeBody( b2World* world, b2Body* body ); + +void b2UpdateBodyMassData( b2World* world, b2Body* body ); + +static inline b2Sweep b2MakeSweep( const b2BodySim* bodySim ) +{ + b2Sweep s; + s.c1 = bodySim->center0; + s.c2 = bodySim->center; + s.q1 = bodySim->rotation0; + s.q2 = bodySim->transform.q; + s.localCenter = bodySim->localCenter; + return s; +} + +// Define inline functions for arrays +B2_ARRAY_INLINE( b2Body, b2Body ) +B2_ARRAY_INLINE( b2BodySim, b2BodySim ) +B2_ARRAY_INLINE( b2BodyState, b2BodyState ) diff --git a/3rdparty/box2d/src/box2d.natvis b/3rdparty/box2d/src/box2d.natvis new file mode 100644 index 000000000000..3cbd9832d31d --- /dev/null +++ b/3rdparty/box2d/src/box2d.natvis @@ -0,0 +1,41 @@ + + + + [{m128_f32[0]}, {m128_f32[1]}, {m128_f32[2]}, {m128_f32[3]}] + + m128_f32[0] + m128_f32[1] + m128_f32[2] + m128_f32[3] + (void*)this + + + + [{m256_f32[0]}, {m256_f32[1]}, {m256_f32[2]}, {m256_f32[3]}, {m256_f32[4]}, {m256_f32[5]}, {m256_f32[6]}, {m256_f32[7]}] + + m256_f32[0] + m256_f32[1] + m256_f32[2] + m256_f32[3] + m256_f32[4] + m256_f32[5] + m256_f32[6] + m256_f32[7] + (void*)this + + + + + index: {index1} + + b2_worlds[ index1 - 1 ] + + + + + + {b2_worlds[world0].bodies.data[index1-1].name,na}, + {b2_worlds[world0].bodies.data[index1-1].type} + + + diff --git a/3rdparty/box2d/src/broad_phase.c b/3rdparty/box2d/src/broad_phase.c new file mode 100644 index 000000000000..c83729bd9ef1 --- /dev/null +++ b/3rdparty/box2d/src/broad_phase.c @@ -0,0 +1,524 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "broad_phase.h" + +#include "aabb.h" +#include "array.h" +#include "atomic.h" +#include "body.h" +#include "contact.h" +#include "core.h" +#include "shape.h" +#include "arena_allocator.h" +#include "world.h" + +#include +#include + +// #include + +// static FILE* s_file = NULL; + +void b2CreateBroadPhase( b2BroadPhase* bp ) +{ + _Static_assert( b2_bodyTypeCount == 3, "must be three body types" ); + + // if (s_file == NULL) + //{ + // s_file = fopen("pairs01.txt", "a"); + // fprintf(s_file, "============\n\n"); + // } + + bp->proxyCount = 0; + bp->moveSet = b2CreateSet( 16 ); + bp->moveArray = b2IntArray_Create( 16 ); + bp->moveResults = NULL; + bp->movePairs = NULL; + bp->movePairCapacity = 0; + b2AtomicStoreInt(&bp->movePairIndex, 0); + bp->pairSet = b2CreateSet( 32 ); + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + bp->trees[i] = b2DynamicTree_Create(); + } +} + +void b2DestroyBroadPhase( b2BroadPhase* bp ) +{ + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2DynamicTree_Destroy( bp->trees + i ); + } + + b2DestroySet( &bp->moveSet ); + b2IntArray_Destroy( &bp->moveArray ); + b2DestroySet( &bp->pairSet ); + + memset( bp, 0, sizeof( b2BroadPhase ) ); + + // if (s_file != NULL) + //{ + // fclose(s_file); + // s_file = NULL; + // } +} + +static inline void b2UnBufferMove( b2BroadPhase* bp, int proxyKey ) +{ + bool found = b2RemoveKey( &bp->moveSet, proxyKey + 1 ); + + if ( found ) + { + // Purge from move buffer. Linear search. + // todo if I can iterate the move set then I don't need the moveArray + int count = bp->moveArray.count; + for ( int i = 0; i < count; ++i ) + { + if ( bp->moveArray.data[i] == proxyKey ) + { + b2IntArray_RemoveSwap( &bp->moveArray, i ); + break; + } + } + } +} + +int b2BroadPhase_CreateProxy( b2BroadPhase* bp, b2BodyType proxyType, b2AABB aabb, uint64_t categoryBits, int shapeIndex, + bool forcePairCreation ) +{ + B2_ASSERT( 0 <= proxyType && proxyType < b2_bodyTypeCount ); + int proxyId = b2DynamicTree_CreateProxy( bp->trees + proxyType, aabb, categoryBits, shapeIndex ); + int proxyKey = B2_PROXY_KEY( proxyId, proxyType ); + if ( proxyType != b2_staticBody || forcePairCreation ) + { + b2BufferMove( bp, proxyKey ); + } + return proxyKey; +} + +void b2BroadPhase_DestroyProxy( b2BroadPhase* bp, int proxyKey ) +{ + B2_ASSERT( bp->moveArray.count == (int)bp->moveSet.count ); + b2UnBufferMove( bp, proxyKey ); + + --bp->proxyCount; + + b2BodyType proxyType = B2_PROXY_TYPE( proxyKey ); + int proxyId = B2_PROXY_ID( proxyKey ); + + B2_ASSERT( 0 <= proxyType && proxyType <= b2_bodyTypeCount ); + b2DynamicTree_DestroyProxy( bp->trees + proxyType, proxyId ); +} + +void b2BroadPhase_MoveProxy( b2BroadPhase* bp, int proxyKey, b2AABB aabb ) +{ + b2BodyType proxyType = B2_PROXY_TYPE( proxyKey ); + int proxyId = B2_PROXY_ID( proxyKey ); + + b2DynamicTree_MoveProxy( bp->trees + proxyType, proxyId, aabb ); + b2BufferMove( bp, proxyKey ); +} + +void b2BroadPhase_EnlargeProxy( b2BroadPhase* bp, int proxyKey, b2AABB aabb ) +{ + B2_ASSERT( proxyKey != B2_NULL_INDEX ); + int typeIndex = B2_PROXY_TYPE( proxyKey ); + int proxyId = B2_PROXY_ID( proxyKey ); + + B2_ASSERT( typeIndex != b2_staticBody ); + + b2DynamicTree_EnlargeProxy( bp->trees + typeIndex, proxyId, aabb ); + b2BufferMove( bp, proxyKey ); +} + +typedef struct b2MovePair +{ + int shapeIndexA; + int shapeIndexB; + b2MovePair* next; + bool heap; +} b2MovePair; + +typedef struct b2MoveResult +{ + b2MovePair* pairList; +} b2MoveResult; + +typedef struct b2QueryPairContext +{ + b2World* world; + b2MoveResult* moveResult; + b2BodyType queryTreeType; + int queryProxyKey; + int queryShapeIndex; +} b2QueryPairContext; + +// This is called from b2DynamicTree::Query when we are gathering pairs. +static bool b2PairQueryCallback( int proxyId, uint64_t userData, void* context ) +{ + int shapeId = (int)userData; + + b2QueryPairContext* queryContext = context; + b2BroadPhase* broadPhase = &queryContext->world->broadPhase; + + int proxyKey = B2_PROXY_KEY( proxyId, queryContext->queryTreeType ); + int queryProxyKey = queryContext->queryProxyKey; + + // A proxy cannot form a pair with itself. + if ( proxyKey == queryContext->queryProxyKey ) + { + return true; + } + + b2BodyType treeType = queryContext->queryTreeType; + b2BodyType queryProxyType = B2_PROXY_TYPE( queryProxyKey ); + + // De-duplication + // It is important to prevent duplicate contacts from being created. Ideally I can prevent duplicates + // early and in the worker. Most of the time the moveSet contains dynamic and kinematic proxies, but + // sometimes it has static proxies. + + // I had an optimization here to skip checking the move set if this is a query into + // the static tree. The assumption is that the static proxies are never in the move set + // so there is no risk of duplication. However, this is not true with + // b2ShapeDef::forceContactCreation, b2ShapeDef::isSensor, or when a static shape is modified. + // There can easily be scenarios where the static proxy is in the moveSet but the dynamic proxy is not. + // I could have some flag to indicate that there are any static bodies in the moveSet. + + // Is this proxy also moving? + if ( queryProxyType == b2_dynamicBody) + { + if ( treeType == b2_dynamicBody && proxyKey < queryProxyKey) + { + bool moved = b2ContainsKey( &broadPhase->moveSet, proxyKey + 1 ); + if ( moved ) + { + // Both proxies are moving. Avoid duplicate pairs. + return true; + } + } + } + else + { + B2_ASSERT( treeType == b2_dynamicBody ); + bool moved = b2ContainsKey( &broadPhase->moveSet, proxyKey + 1 ); + if ( moved ) + { + // Both proxies are moving. Avoid duplicate pairs. + return true; + } + } + + uint64_t pairKey = B2_SHAPE_PAIR_KEY( shapeId, queryContext->queryShapeIndex ); + if ( b2ContainsKey( &broadPhase->pairSet, pairKey ) ) + { + // contact exists + return true; + } + + int shapeIdA, shapeIdB; + if ( proxyKey < queryProxyKey ) + { + shapeIdA = shapeId; + shapeIdB = queryContext->queryShapeIndex; + } + else + { + shapeIdA = queryContext->queryShapeIndex; + shapeIdB = shapeId; + } + + b2World* world = queryContext->world; + + b2Shape* shapeA = b2ShapeArray_Get( &world->shapes, shapeIdA ); + b2Shape* shapeB = b2ShapeArray_Get( &world->shapes, shapeIdB ); + + int bodyIdA = shapeA->bodyId; + int bodyIdB = shapeB->bodyId; + + // Are the shapes on the same body? + if ( bodyIdA == bodyIdB ) + { + return true; + } + + // Sensors are handled elsewhere + if ( shapeA->sensorIndex != B2_NULL_INDEX || shapeB->sensorIndex != B2_NULL_INDEX ) + { + return true; + } + + if ( b2ShouldShapesCollide( shapeA->filter, shapeB->filter ) == false ) + { + return true; + } + + // Does a joint override collision? + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + if ( b2ShouldBodiesCollide( world, bodyA, bodyB ) == false ) + { + return true; + } + + // Custom user filter + b2CustomFilterFcn* customFilterFcn = queryContext->world->customFilterFcn; + if ( customFilterFcn != NULL ) + { + b2ShapeId idA = { shapeIdA + 1, world->worldId, shapeA->generation }; + b2ShapeId idB = { shapeIdB + 1, world->worldId, shapeB->generation }; + bool shouldCollide = customFilterFcn( idA, idB, queryContext->world->customFilterContext ); + if ( shouldCollide == false ) + { + return true; + } + } + + // todo per thread to eliminate atomic? + int pairIndex = b2AtomicFetchAddInt( &broadPhase->movePairIndex, 1 ); + + b2MovePair* pair; + if ( pairIndex < broadPhase->movePairCapacity ) + { + pair = broadPhase->movePairs + pairIndex; + pair->heap = false; + } + else + { + pair = b2Alloc( sizeof( b2MovePair ) ); + pair->heap = true; + } + + pair->shapeIndexA = shapeIdA; + pair->shapeIndexB = shapeIdB; + pair->next = queryContext->moveResult->pairList; + queryContext->moveResult->pairList = pair; + + // continue the query + return true; +} + +// Warning: writing to these globals significantly slows multithreading performance +#if B2_SNOOP_PAIR_COUNTERS +b2TreeStats b2_dynamicStats; +b2TreeStats b2_kinematicStats; +b2TreeStats b2_staticStats; +#endif + +static void b2FindPairsTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + b2TracyCZoneNC( pair_task, "Pair", b2_colorMediumSlateBlue, true ); + + B2_UNUSED( threadIndex ); + + b2World* world = context; + b2BroadPhase* bp = &world->broadPhase; + + b2QueryPairContext queryContext; + queryContext.world = world; + + for ( int i = startIndex; i < endIndex; ++i ) + { + // Initialize move result for this moved proxy + queryContext.moveResult = bp->moveResults + i; + queryContext.moveResult->pairList = NULL; + + int proxyKey = bp->moveArray.data[i]; + if ( proxyKey == B2_NULL_INDEX ) + { + // proxy was destroyed after it moved + continue; + } + + b2BodyType proxyType = B2_PROXY_TYPE( proxyKey ); + + int proxyId = B2_PROXY_ID( proxyKey ); + queryContext.queryProxyKey = proxyKey; + + const b2DynamicTree* baseTree = bp->trees + proxyType; + + // We have to query the tree with the fat AABB so that + // we don't fail to create a contact that may touch later. + b2AABB fatAABB = b2DynamicTree_GetAABB( baseTree, proxyId ); + queryContext.queryShapeIndex = (int)b2DynamicTree_GetUserData( baseTree, proxyId ); + + // Query trees. Only dynamic proxies collide with kinematic and static proxies. + // Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works. + b2TreeStats stats = { 0 }; + if ( proxyType == b2_dynamicBody ) + { + // consider using bits = groupIndex > 0 ? B2_DEFAULT_MASK_BITS : maskBits + queryContext.queryTreeType = b2_kinematicBody; + b2TreeStats statsKinematic = b2DynamicTree_Query( bp->trees + b2_kinematicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); + stats.nodeVisits += statsKinematic.nodeVisits; + stats.leafVisits += statsKinematic.leafVisits; + + queryContext.queryTreeType = b2_staticBody; + b2TreeStats statsStatic = b2DynamicTree_Query( bp->trees + b2_staticBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); + stats.nodeVisits += statsStatic.nodeVisits; + stats.leafVisits += statsStatic.leafVisits; + } + + // All proxies collide with dynamic proxies + // Using B2_DEFAULT_MASK_BITS so that b2Filter::groupIndex works. + queryContext.queryTreeType = b2_dynamicBody; + b2TreeStats statsDynamic = b2DynamicTree_Query( bp->trees + b2_dynamicBody, fatAABB, B2_DEFAULT_MASK_BITS, b2PairQueryCallback, &queryContext ); + stats.nodeVisits += statsDynamic.nodeVisits; + stats.leafVisits += statsDynamic.leafVisits; + } + + b2TracyCZoneEnd( pair_task ); +} + +void b2UpdateBroadPhasePairs( b2World* world ) +{ + b2BroadPhase* bp = &world->broadPhase; + + int moveCount = bp->moveArray.count; + B2_ASSERT( moveCount == (int)bp->moveSet.count ); + + if ( moveCount == 0 ) + { + return; + } + + b2TracyCZoneNC( update_pairs, "Find Pairs", b2_colorMediumSlateBlue, true ); + + b2ArenaAllocator* alloc = &world->arena; + + // todo these could be in the step context + bp->moveResults = b2AllocateArenaItem( alloc, moveCount * sizeof( b2MoveResult ), "move results" ); + bp->movePairCapacity = 16 * moveCount; + bp->movePairs = b2AllocateArenaItem( alloc, bp->movePairCapacity * sizeof( b2MovePair ), "move pairs" ); + b2AtomicStoreInt(&bp->movePairIndex, 0); + +#if B2_SNOOP_TABLE_COUNTERS + extern b2AtomicInt b2_probeCount; + b2AtomicStoreInt(&b2_probeCount, 0); +#endif + + int minRange = 64; + void* userPairTask = world->enqueueTaskFcn( &b2FindPairsTask, moveCount, minRange, world, world->userTaskContext ); + if (userPairTask != NULL) + { + world->finishTaskFcn( userPairTask, world->userTaskContext ); + world->taskCount += 1; + } + + // todo_erin could start tree rebuild here + + b2TracyCZoneNC( create_contacts, "Create Contacts", b2_colorCoral, true ); + + // Single-threaded work + // - Clear move flags + // - Create contacts in deterministic order + for ( int i = 0; i < moveCount; ++i ) + { + b2MoveResult* result = bp->moveResults + i; + b2MovePair* pair = result->pairList; + while ( pair != NULL ) + { + int shapeIdA = pair->shapeIndexA; + int shapeIdB = pair->shapeIndexB; + + // if (s_file != NULL) + //{ + // fprintf(s_file, "%d %d\n", shapeIdA, shapeIdB); + // } + + b2Shape* shapeA = b2ShapeArray_Get( &world->shapes, shapeIdA ); + b2Shape* shapeB = b2ShapeArray_Get( &world->shapes, shapeIdB ); + + b2CreateContact( world, shapeA, shapeB ); + + if ( pair->heap ) + { + b2MovePair* temp = pair; + pair = pair->next; + b2Free( temp, sizeof( b2MovePair ) ); + } + else + { + pair = pair->next; + } + } + + // if (s_file != NULL) + //{ + // fprintf(s_file, "\n"); + // } + } + + // if (s_file != NULL) + //{ + // fprintf(s_file, "count = %d\n\n", pairCount); + // } + + // Reset move buffer + b2IntArray_Clear( &bp->moveArray ); + b2ClearSet( &bp->moveSet ); + + b2FreeArenaItem( alloc, bp->movePairs ); + bp->movePairs = NULL; + b2FreeArenaItem( alloc, bp->moveResults ); + bp->moveResults = NULL; + + b2ValidateSolverSets( world ); + + b2TracyCZoneEnd( create_contacts ); + + b2TracyCZoneEnd( update_pairs ); +} + +bool b2BroadPhase_TestOverlap( const b2BroadPhase* bp, int proxyKeyA, int proxyKeyB ) +{ + int typeIndexA = B2_PROXY_TYPE( proxyKeyA ); + int proxyIdA = B2_PROXY_ID( proxyKeyA ); + int typeIndexB = B2_PROXY_TYPE( proxyKeyB ); + int proxyIdB = B2_PROXY_ID( proxyKeyB ); + + b2AABB aabbA = b2DynamicTree_GetAABB( bp->trees + typeIndexA, proxyIdA ); + b2AABB aabbB = b2DynamicTree_GetAABB( bp->trees + typeIndexB, proxyIdB ); + return b2AABB_Overlaps( aabbA, aabbB ); +} + +void b2BroadPhase_RebuildTrees( b2BroadPhase* bp ) +{ + b2DynamicTree_Rebuild( bp->trees + b2_dynamicBody, false ); + b2DynamicTree_Rebuild( bp->trees + b2_kinematicBody, false ); +} + +int b2BroadPhase_GetShapeIndex( b2BroadPhase* bp, int proxyKey ) +{ + int typeIndex = B2_PROXY_TYPE( proxyKey ); + int proxyId = B2_PROXY_ID( proxyKey ); + + return (int)b2DynamicTree_GetUserData( bp->trees + typeIndex, proxyId ); +} + +void b2ValidateBroadphase( const b2BroadPhase* bp ) +{ + b2DynamicTree_Validate( bp->trees + b2_dynamicBody ); + b2DynamicTree_Validate( bp->trees + b2_kinematicBody ); + + // TODO_ERIN validate every shape AABB is contained in tree AABB +} + +void b2ValidateNoEnlarged( const b2BroadPhase* bp ) +{ +#if B2_VALIDATE == 1 + for ( int j = 0; j < b2_bodyTypeCount; ++j ) + { + const b2DynamicTree* tree = bp->trees + j; + b2DynamicTree_ValidateNoEnlarged( tree ); + } +#else + B2_UNUSED( bp ); +#endif +} diff --git a/3rdparty/box2d/src/broad_phase.h b/3rdparty/box2d/src/broad_phase.h new file mode 100644 index 000000000000..43389ff3caae --- /dev/null +++ b/3rdparty/box2d/src/broad_phase.h @@ -0,0 +1,83 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" +#include "table.h" + +#include "box2d/collision.h" +#include "box2d/types.h" + +typedef struct b2Shape b2Shape; +typedef struct b2MovePair b2MovePair; +typedef struct b2MoveResult b2MoveResult; +typedef struct b2ArenaAllocator b2ArenaAllocator; +typedef struct b2World b2World; + +// Store the proxy type in the lower 2 bits of the proxy key. This leaves 30 bits for the id. +#define B2_PROXY_TYPE( KEY ) ( (b2BodyType)( ( KEY ) & 3 ) ) +#define B2_PROXY_ID( KEY ) ( ( KEY ) >> 2 ) +#define B2_PROXY_KEY( ID, TYPE ) ( ( ( ID ) << 2 ) | ( TYPE ) ) + +/// The broad-phase is used for computing pairs and performing volume queries and ray casts. +/// This broad-phase does not persist pairs. Instead, this reports potentially new pairs. +/// It is up to the client to consume the new pairs and to track subsequent overlap. +typedef struct b2BroadPhase +{ + b2DynamicTree trees[b2_bodyTypeCount]; + int proxyCount; + + // The move set and array are used to track shapes that have moved significantly + // and need a pair query for new contacts. The array has a deterministic order. + // todo perhaps just a move set? + // todo implement a 32bit hash set for faster lookup + // todo moveSet can grow quite large on the first time step and remain large + b2HashSet moveSet; + b2IntArray moveArray; + + // These are the results from the pair query and are used to create new contacts + // in deterministic order. + // todo these could be in the step context + b2MoveResult* moveResults; + b2MovePair* movePairs; + int movePairCapacity; + b2AtomicInt movePairIndex; + + // Tracks shape pairs that have a b2Contact + // todo pairSet can grow quite large on the first time step and remain large + b2HashSet pairSet; + +} b2BroadPhase; + +void b2CreateBroadPhase( b2BroadPhase* bp ); +void b2DestroyBroadPhase( b2BroadPhase* bp ); + +int b2BroadPhase_CreateProxy( b2BroadPhase* bp, b2BodyType proxyType, b2AABB aabb, uint64_t categoryBits, int shapeIndex, + bool forcePairCreation ); +void b2BroadPhase_DestroyProxy( b2BroadPhase* bp, int proxyKey ); + +void b2BroadPhase_MoveProxy( b2BroadPhase* bp, int proxyKey, b2AABB aabb ); +void b2BroadPhase_EnlargeProxy( b2BroadPhase* bp, int proxyKey, b2AABB aabb ); + +void b2BroadPhase_RebuildTrees( b2BroadPhase* bp ); + +int b2BroadPhase_GetShapeIndex( b2BroadPhase* bp, int proxyKey ); + +void b2UpdateBroadPhasePairs( b2World* world ); +bool b2BroadPhase_TestOverlap( const b2BroadPhase* bp, int proxyKeyA, int proxyKeyB ); + +void b2ValidateBroadphase( const b2BroadPhase* bp ); +void b2ValidateNoEnlarged( const b2BroadPhase* bp ); + +// This is what triggers new contact pairs to be created +// Warning: this must be called in deterministic order +static inline void b2BufferMove( b2BroadPhase* bp, int queryProxy ) +{ + // Adding 1 because 0 is the sentinel + bool alreadyAdded = b2AddKey( &bp->moveSet, queryProxy + 1 ); + if ( alreadyAdded == false ) + { + b2IntArray_Push( &bp->moveArray, queryProxy ); + } +} diff --git a/3rdparty/box2d/src/collision/b2_broad_phase.cpp b/3rdparty/box2d/src/collision/b2_broad_phase.cpp deleted file mode 100644 index d063a3aa9bf4..000000000000 --- a/3rdparty/box2d/src/collision/b2_broad_phase.cpp +++ /dev/null @@ -1,131 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_broad_phase.h" -#include - -b2BroadPhase::b2BroadPhase() -{ - m_proxyCount = 0; - - m_pairCapacity = 16; - m_pairCount = 0; - m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair)); - - m_moveCapacity = 16; - m_moveCount = 0; - m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32)); -} - -b2BroadPhase::~b2BroadPhase() -{ - b2Free(m_moveBuffer); - b2Free(m_pairBuffer); -} - -int32 b2BroadPhase::CreateProxy(const b2AABB& aabb, void* userData) -{ - int32 proxyId = m_tree.CreateProxy(aabb, userData); - ++m_proxyCount; - BufferMove(proxyId); - return proxyId; -} - -void b2BroadPhase::DestroyProxy(int32 proxyId) -{ - UnBufferMove(proxyId); - --m_proxyCount; - m_tree.DestroyProxy(proxyId); -} - -void b2BroadPhase::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement) -{ - bool buffer = m_tree.MoveProxy(proxyId, aabb, displacement); - if (buffer) - { - BufferMove(proxyId); - } -} - -void b2BroadPhase::TouchProxy(int32 proxyId) -{ - BufferMove(proxyId); -} - -void b2BroadPhase::BufferMove(int32 proxyId) -{ - if (m_moveCount == m_moveCapacity) - { - int32* oldBuffer = m_moveBuffer; - m_moveCapacity *= 2; - m_moveBuffer = (int32*)b2Alloc(m_moveCapacity * sizeof(int32)); - memcpy(m_moveBuffer, oldBuffer, m_moveCount * sizeof(int32)); - b2Free(oldBuffer); - } - - m_moveBuffer[m_moveCount] = proxyId; - ++m_moveCount; -} - -void b2BroadPhase::UnBufferMove(int32 proxyId) -{ - for (int32 i = 0; i < m_moveCount; ++i) - { - if (m_moveBuffer[i] == proxyId) - { - m_moveBuffer[i] = e_nullProxy; - } - } -} - -// This is called from b2DynamicTree::Query when we are gathering pairs. -bool b2BroadPhase::QueryCallback(int32 proxyId) -{ - // A proxy cannot form a pair with itself. - if (proxyId == m_queryProxyId) - { - return true; - } - - const bool moved = m_tree.WasMoved(proxyId); - if (moved && proxyId > m_queryProxyId) - { - // Both proxies are moving. Avoid duplicate pairs. - return true; - } - - // Grow the pair buffer as needed. - if (m_pairCount == m_pairCapacity) - { - b2Pair* oldBuffer = m_pairBuffer; - m_pairCapacity = m_pairCapacity + (m_pairCapacity >> 1); - m_pairBuffer = (b2Pair*)b2Alloc(m_pairCapacity * sizeof(b2Pair)); - memcpy(m_pairBuffer, oldBuffer, m_pairCount * sizeof(b2Pair)); - b2Free(oldBuffer); - } - - m_pairBuffer[m_pairCount].proxyIdA = b2Min(proxyId, m_queryProxyId); - m_pairBuffer[m_pairCount].proxyIdB = b2Max(proxyId, m_queryProxyId); - ++m_pairCount; - - return true; -} diff --git a/3rdparty/box2d/src/collision/b2_chain_shape.cpp b/3rdparty/box2d/src/collision/b2_chain_shape.cpp deleted file mode 100644 index b964a4303c04..000000000000 --- a/3rdparty/box2d/src/collision/b2_chain_shape.cpp +++ /dev/null @@ -1,185 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_edge_shape.h" - -#include "box2d/b2_block_allocator.h" - -#include -#include - -b2ChainShape::~b2ChainShape() -{ - Clear(); -} - -void b2ChainShape::Clear() -{ - b2Free(m_vertices); - m_vertices = nullptr; - m_count = 0; -} - -void b2ChainShape::CreateLoop(const b2Vec2* vertices, int32 count) -{ - b2Assert(m_vertices == nullptr && m_count == 0); - b2Assert(count >= 3); - if (count < 3) - { - return; - } - - for (int32 i = 1; i < count; ++i) - { - b2Vec2 v1 = vertices[i-1]; - b2Vec2 v2 = vertices[i]; - // If the code crashes here, it means your vertices are too close together. - b2Assert(b2DistanceSquared(v1, v2) > b2_linearSlop * b2_linearSlop); - } - - m_count = count + 1; - m_vertices = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); - memcpy(m_vertices, vertices, count * sizeof(b2Vec2)); - m_vertices[count] = m_vertices[0]; - m_prevVertex = m_vertices[m_count - 2]; - m_nextVertex = m_vertices[1]; -} - -void b2ChainShape::CreateChain(const b2Vec2* vertices, int32 count, const b2Vec2& prevVertex, const b2Vec2& nextVertex) -{ - b2Assert(m_vertices == nullptr && m_count == 0); - b2Assert(count >= 2); - for (int32 i = 1; i < count; ++i) - { - // If the code crashes here, it means your vertices are too close together. - b2Assert(b2DistanceSquared(vertices[i-1], vertices[i]) > b2_linearSlop * b2_linearSlop); - } - - m_count = count; - m_vertices = (b2Vec2*)b2Alloc(count * sizeof(b2Vec2)); - memcpy(m_vertices, vertices, m_count * sizeof(b2Vec2)); - - m_prevVertex = prevVertex; - m_nextVertex = nextVertex; -} - -b2Shape* b2ChainShape::Clone(b2BlockAllocator* allocator) const -{ - void* mem = allocator->Allocate(sizeof(b2ChainShape)); - b2ChainShape* clone = new (mem) b2ChainShape; - clone->CreateChain(m_vertices, m_count, m_prevVertex, m_nextVertex); - return clone; -} - -int32 b2ChainShape::GetChildCount() const -{ - // edge count = vertex count - 1 - return m_count - 1; -} - -void b2ChainShape::GetChildEdge(b2EdgeShape* edge, int32 index) const -{ - b2Assert(0 <= index && index < m_count - 1); - edge->m_type = b2Shape::e_edge; - edge->m_radius = m_radius; - - edge->m_vertex1 = m_vertices[index + 0]; - edge->m_vertex2 = m_vertices[index + 1]; - edge->m_oneSided = true; - - if (index > 0) - { - edge->m_vertex0 = m_vertices[index - 1]; - } - else - { - edge->m_vertex0 = m_prevVertex; - } - - if (index < m_count - 2) - { - edge->m_vertex3 = m_vertices[index + 2]; - } - else - { - edge->m_vertex3 = m_nextVertex; - } -} - -bool b2ChainShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const -{ - B2_NOT_USED(xf); - B2_NOT_USED(p); - return false; -} - -bool b2ChainShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& xf, int32 childIndex) const -{ - b2Assert(childIndex < m_count); - - b2EdgeShape edgeShape; - - int32 i1 = childIndex; - int32 i2 = childIndex + 1; - if (i2 == m_count) - { - i2 = 0; - } - - edgeShape.m_vertex1 = m_vertices[i1]; - edgeShape.m_vertex2 = m_vertices[i2]; - - return edgeShape.RayCast(output, input, xf, 0); -} - -void b2ChainShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const -{ - b2Assert(childIndex < m_count); - - int32 i1 = childIndex; - int32 i2 = childIndex + 1; - if (i2 == m_count) - { - i2 = 0; - } - - b2Vec2 v1 = b2Mul(xf, m_vertices[i1]); - b2Vec2 v2 = b2Mul(xf, m_vertices[i2]); - - b2Vec2 lower = b2Min(v1, v2); - b2Vec2 upper = b2Max(v1, v2); - - b2Vec2 r(m_radius, m_radius); - aabb->lowerBound = lower - r; - aabb->upperBound = upper + r; -} - -void b2ChainShape::ComputeMass(b2MassData* massData, float density) const -{ - B2_NOT_USED(density); - - massData->mass = 0.0f; - massData->center.SetZero(); - massData->I = 0.0f; -} diff --git a/3rdparty/box2d/src/collision/b2_circle_shape.cpp b/3rdparty/box2d/src/collision/b2_circle_shape.cpp deleted file mode 100644 index ecc69293b584..000000000000 --- a/3rdparty/box2d/src/collision/b2_circle_shape.cpp +++ /dev/null @@ -1,105 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_block_allocator.h" - -#include - -b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const -{ - void* mem = allocator->Allocate(sizeof(b2CircleShape)); - b2CircleShape* clone = new (mem) b2CircleShape; - *clone = *this; - return clone; -} - -int32 b2CircleShape::GetChildCount() const -{ - return 1; -} - -bool b2CircleShape::TestPoint(const b2Transform& transform, const b2Vec2& p) const -{ - b2Vec2 center = transform.p + b2Mul(transform.q, m_p); - b2Vec2 d = p - center; - return b2Dot(d, d) <= m_radius * m_radius; -} - -// Collision Detection in Interactive 3D Environments by Gino van den Bergen -// From Section 3.1.2 -// x = s + a * r -// norm(x) = radius -bool b2CircleShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& transform, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - b2Vec2 position = transform.p + b2Mul(transform.q, m_p); - b2Vec2 s = input.p1 - position; - float b = b2Dot(s, s) - m_radius * m_radius; - - // Solve quadratic equation. - b2Vec2 r = input.p2 - input.p1; - float c = b2Dot(s, r); - float rr = b2Dot(r, r); - float sigma = c * c - rr * b; - - // Check for negative discriminant and short segment. - if (sigma < 0.0f || rr < b2_epsilon) - { - return false; - } - - // Find the point of intersection of the line with the circle. - float a = -(c + b2Sqrt(sigma)); - - // Is the intersection point on the segment? - if (0.0f <= a && a <= input.maxFraction * rr) - { - a /= rr; - output->fraction = a; - output->normal = s + a * r; - output->normal.Normalize(); - return true; - } - - return false; -} - -void b2CircleShape::ComputeAABB(b2AABB* aabb, const b2Transform& transform, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - b2Vec2 p = transform.p + b2Mul(transform.q, m_p); - aabb->lowerBound.Set(p.x - m_radius, p.y - m_radius); - aabb->upperBound.Set(p.x + m_radius, p.y + m_radius); -} - -void b2CircleShape::ComputeMass(b2MassData* massData, float density) const -{ - massData->mass = density * b2_pi * m_radius * m_radius; - massData->center = m_p; - - // inertia about the local origin - massData->I = massData->mass * (0.5f * m_radius * m_radius + b2Dot(m_p, m_p)); -} diff --git a/3rdparty/box2d/src/collision/b2_collide_circle.cpp b/3rdparty/box2d/src/collision/b2_collide_circle.cpp deleted file mode 100644 index 469da55907e9..000000000000 --- a/3rdparty/box2d/src/collision/b2_collide_circle.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_collision.h" -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_polygon_shape.h" - -void b2CollideCircles( - b2Manifold* manifold, - const b2CircleShape* circleA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB) -{ - manifold->pointCount = 0; - - b2Vec2 pA = b2Mul(xfA, circleA->m_p); - b2Vec2 pB = b2Mul(xfB, circleB->m_p); - - b2Vec2 d = pB - pA; - float distSqr = b2Dot(d, d); - float rA = circleA->m_radius, rB = circleB->m_radius; - float radius = rA + rB; - if (distSqr > radius * radius) - { - return; - } - - manifold->type = b2Manifold::e_circles; - manifold->localPoint = circleA->m_p; - manifold->localNormal.SetZero(); - manifold->pointCount = 1; - - manifold->points[0].localPoint = circleB->m_p; - manifold->points[0].id.key = 0; -} - -void b2CollidePolygonAndCircle( - b2Manifold* manifold, - const b2PolygonShape* polygonA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB) -{ - manifold->pointCount = 0; - - // Compute circle position in the frame of the polygon. - b2Vec2 c = b2Mul(xfB, circleB->m_p); - b2Vec2 cLocal = b2MulT(xfA, c); - - // Find the min separating edge. - int32 normalIndex = 0; - float separation = -b2_maxFloat; - float radius = polygonA->m_radius + circleB->m_radius; - int32 vertexCount = polygonA->m_count; - const b2Vec2* vertices = polygonA->m_vertices; - const b2Vec2* normals = polygonA->m_normals; - - for (int32 i = 0; i < vertexCount; ++i) - { - float s = b2Dot(normals[i], cLocal - vertices[i]); - - if (s > radius) - { - // Early out. - return; - } - - if (s > separation) - { - separation = s; - normalIndex = i; - } - } - - // Vertices that subtend the incident face. - int32 vertIndex1 = normalIndex; - int32 vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; - b2Vec2 v1 = vertices[vertIndex1]; - b2Vec2 v2 = vertices[vertIndex2]; - - // If the center is inside the polygon ... - if (separation < b2_epsilon) - { - manifold->pointCount = 1; - manifold->type = b2Manifold::e_faceA; - manifold->localNormal = normals[normalIndex]; - manifold->localPoint = 0.5f * (v1 + v2); - manifold->points[0].localPoint = circleB->m_p; - manifold->points[0].id.key = 0; - return; - } - - // Compute barycentric coordinates - float u1 = b2Dot(cLocal - v1, v2 - v1); - float u2 = b2Dot(cLocal - v2, v1 - v2); - if (u1 <= 0.0f) - { - if (b2DistanceSquared(cLocal, v1) > radius * radius) - { - return; - } - - manifold->pointCount = 1; - manifold->type = b2Manifold::e_faceA; - manifold->localNormal = cLocal - v1; - manifold->localNormal.Normalize(); - manifold->localPoint = v1; - manifold->points[0].localPoint = circleB->m_p; - manifold->points[0].id.key = 0; - } - else if (u2 <= 0.0f) - { - if (b2DistanceSquared(cLocal, v2) > radius * radius) - { - return; - } - - manifold->pointCount = 1; - manifold->type = b2Manifold::e_faceA; - manifold->localNormal = cLocal - v2; - manifold->localNormal.Normalize(); - manifold->localPoint = v2; - manifold->points[0].localPoint = circleB->m_p; - manifold->points[0].id.key = 0; - } - else - { - b2Vec2 faceCenter = 0.5f * (v1 + v2); - float s = b2Dot(cLocal - faceCenter, normals[vertIndex1]); - if (s > radius) - { - return; - } - - manifold->pointCount = 1; - manifold->type = b2Manifold::e_faceA; - manifold->localNormal = normals[vertIndex1]; - manifold->localPoint = faceCenter; - manifold->points[0].localPoint = circleB->m_p; - manifold->points[0].id.key = 0; - } -} diff --git a/3rdparty/box2d/src/collision/b2_collide_edge.cpp b/3rdparty/box2d/src/collision/b2_collide_edge.cpp deleted file mode 100644 index e06b90097fad..000000000000 --- a/3rdparty/box2d/src/collision/b2_collide_edge.cpp +++ /dev/null @@ -1,524 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_collision.h" -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_edge_shape.h" -#include "box2d/b2_polygon_shape.h" - - -// Compute contact points for edge versus circle. -// This accounts for edge connectivity. -void b2CollideEdgeAndCircle(b2Manifold* manifold, - const b2EdgeShape* edgeA, const b2Transform& xfA, - const b2CircleShape* circleB, const b2Transform& xfB) -{ - manifold->pointCount = 0; - - // Compute circle in frame of edge - b2Vec2 Q = b2MulT(xfA, b2Mul(xfB, circleB->m_p)); - - b2Vec2 A = edgeA->m_vertex1, B = edgeA->m_vertex2; - b2Vec2 e = B - A; - - // Normal points to the right for a CCW winding - b2Vec2 n(e.y, -e.x); - float offset = b2Dot(n, Q - A); - - bool oneSided = edgeA->m_oneSided; - if (oneSided && offset < 0.0f) - { - return; - } - - // Barycentric coordinates - float u = b2Dot(e, B - Q); - float v = b2Dot(e, Q - A); - - float radius = edgeA->m_radius + circleB->m_radius; - - b2ContactFeature cf; - cf.indexB = 0; - cf.typeB = b2ContactFeature::e_vertex; - - // Region A - if (v <= 0.0f) - { - b2Vec2 P = A; - b2Vec2 d = Q - P; - float dd = b2Dot(d, d); - if (dd > radius * radius) - { - return; - } - - // Is there an edge connected to A? - if (edgeA->m_oneSided) - { - b2Vec2 A1 = edgeA->m_vertex0; - b2Vec2 B1 = A; - b2Vec2 e1 = B1 - A1; - float u1 = b2Dot(e1, B1 - Q); - - // Is the circle in Region AB of the previous edge? - if (u1 > 0.0f) - { - return; - } - } - - cf.indexA = 0; - cf.typeA = b2ContactFeature::e_vertex; - manifold->pointCount = 1; - manifold->type = b2Manifold::e_circles; - manifold->localNormal.SetZero(); - manifold->localPoint = P; - manifold->points[0].id.key = 0; - manifold->points[0].id.cf = cf; - manifold->points[0].localPoint = circleB->m_p; - return; - } - - // Region B - if (u <= 0.0f) - { - b2Vec2 P = B; - b2Vec2 d = Q - P; - float dd = b2Dot(d, d); - if (dd > radius * radius) - { - return; - } - - // Is there an edge connected to B? - if (edgeA->m_oneSided) - { - b2Vec2 B2 = edgeA->m_vertex3; - b2Vec2 A2 = B; - b2Vec2 e2 = B2 - A2; - float v2 = b2Dot(e2, Q - A2); - - // Is the circle in Region AB of the next edge? - if (v2 > 0.0f) - { - return; - } - } - - cf.indexA = 1; - cf.typeA = b2ContactFeature::e_vertex; - manifold->pointCount = 1; - manifold->type = b2Manifold::e_circles; - manifold->localNormal.SetZero(); - manifold->localPoint = P; - manifold->points[0].id.key = 0; - manifold->points[0].id.cf = cf; - manifold->points[0].localPoint = circleB->m_p; - return; - } - - // Region AB - float den = b2Dot(e, e); - b2Assert(den > 0.0f); - b2Vec2 P = (1.0f / den) * (u * A + v * B); - b2Vec2 d = Q - P; - float dd = b2Dot(d, d); - if (dd > radius * radius) - { - return; - } - - if (offset < 0.0f) - { - n.Set(-n.x, -n.y); - } - n.Normalize(); - - cf.indexA = 0; - cf.typeA = b2ContactFeature::e_face; - manifold->pointCount = 1; - manifold->type = b2Manifold::e_faceA; - manifold->localNormal = n; - manifold->localPoint = A; - manifold->points[0].id.key = 0; - manifold->points[0].id.cf = cf; - manifold->points[0].localPoint = circleB->m_p; -} - -// This structure is used to keep track of the best separating axis. -struct b2EPAxis -{ - enum Type - { - e_unknown, - e_edgeA, - e_edgeB - }; - - b2Vec2 normal; - Type type; - int32 index; - float separation; -}; - -// This holds polygon B expressed in frame A. -struct b2TempPolygon -{ - b2Vec2 vertices[b2_maxPolygonVertices]; - b2Vec2 normals[b2_maxPolygonVertices]; - int32 count; -}; - -// Reference face used for clipping -struct b2ReferenceFace -{ - int32 i1, i2; - b2Vec2 v1, v2; - b2Vec2 normal; - - b2Vec2 sideNormal1; - float sideOffset1; - - b2Vec2 sideNormal2; - float sideOffset2; -}; - -static b2EPAxis b2ComputeEdgeSeparation(const b2TempPolygon& polygonB, const b2Vec2& v1, const b2Vec2& normal1) -{ - b2EPAxis axis; - axis.type = b2EPAxis::e_edgeA; - axis.index = -1; - axis.separation = -FLT_MAX; - axis.normal.SetZero(); - - b2Vec2 axes[2] = { normal1, -normal1 }; - - // Find axis with least overlap (min-max problem) - for (int32 j = 0; j < 2; ++j) - { - float sj = FLT_MAX; - - // Find deepest polygon vertex along axis j - for (int32 i = 0; i < polygonB.count; ++i) - { - float si = b2Dot(axes[j], polygonB.vertices[i] - v1); - if (si < sj) - { - sj = si; - } - } - - if (sj > axis.separation) - { - axis.index = j; - axis.separation = sj; - axis.normal = axes[j]; - } - } - - return axis; -} - -static b2EPAxis b2ComputePolygonSeparation(const b2TempPolygon& polygonB, const b2Vec2& v1, const b2Vec2& v2) -{ - b2EPAxis axis; - axis.type = b2EPAxis::e_unknown; - axis.index = -1; - axis.separation = -FLT_MAX; - axis.normal.SetZero(); - - for (int32 i = 0; i < polygonB.count; ++i) - { - b2Vec2 n = -polygonB.normals[i]; - - float s1 = b2Dot(n, polygonB.vertices[i] - v1); - float s2 = b2Dot(n, polygonB.vertices[i] - v2); - float s = b2Min(s1, s2); - - if (s > axis.separation) - { - axis.type = b2EPAxis::e_edgeB; - axis.index = i; - axis.separation = s; - axis.normal = n; - } - } - - return axis; -} - -void b2CollideEdgeAndPolygon(b2Manifold* manifold, - const b2EdgeShape* edgeA, const b2Transform& xfA, - const b2PolygonShape* polygonB, const b2Transform& xfB) -{ - manifold->pointCount = 0; - - b2Transform xf = b2MulT(xfA, xfB); - - b2Vec2 centroidB = b2Mul(xf, polygonB->m_centroid); - - b2Vec2 v1 = edgeA->m_vertex1; - b2Vec2 v2 = edgeA->m_vertex2; - - b2Vec2 edge1 = v2 - v1; - edge1.Normalize(); - - // Normal points to the right for a CCW winding - b2Vec2 normal1(edge1.y, -edge1.x); - float offset1 = b2Dot(normal1, centroidB - v1); - - bool oneSided = edgeA->m_oneSided; - if (oneSided && offset1 < 0.0f) - { - return; - } - - // Get polygonB in frameA - b2TempPolygon tempPolygonB; - tempPolygonB.count = polygonB->m_count; - for (int32 i = 0; i < polygonB->m_count; ++i) - { - tempPolygonB.vertices[i] = b2Mul(xf, polygonB->m_vertices[i]); - tempPolygonB.normals[i] = b2Mul(xf.q, polygonB->m_normals[i]); - } - - float radius = polygonB->m_radius + edgeA->m_radius; - - b2EPAxis edgeAxis = b2ComputeEdgeSeparation(tempPolygonB, v1, normal1); - if (edgeAxis.separation > radius) - { - return; - } - - b2EPAxis polygonAxis = b2ComputePolygonSeparation(tempPolygonB, v1, v2); - if (polygonAxis.separation > radius) - { - return; - } - - // Use hysteresis for jitter reduction. - const float k_relativeTol = 0.98f; - const float k_absoluteTol = 0.001f; - - b2EPAxis primaryAxis; - if (polygonAxis.separation - radius > k_relativeTol * (edgeAxis.separation - radius) + k_absoluteTol) - { - primaryAxis = polygonAxis; - } - else - { - primaryAxis = edgeAxis; - } - - if (oneSided) - { - // Smooth collision - // See https://box2d.org/posts/2020/06/ghost-collisions/ - - b2Vec2 edge0 = v1 - edgeA->m_vertex0; - edge0.Normalize(); - b2Vec2 normal0(edge0.y, -edge0.x); - bool convex1 = b2Cross(edge0, edge1) >= 0.0f; - - b2Vec2 edge2 = edgeA->m_vertex3 - v2; - edge2.Normalize(); - b2Vec2 normal2(edge2.y, -edge2.x); - bool convex2 = b2Cross(edge1, edge2) >= 0.0f; - - const float sinTol = 0.1f; - bool side1 = b2Dot(primaryAxis.normal, edge1) <= 0.0f; - - // Check Gauss Map - if (side1) - { - if (convex1) - { - if (b2Cross(primaryAxis.normal, normal0) > sinTol) - { - // Skip region - return; - } - - // Admit region - } - else - { - // Snap region - primaryAxis = edgeAxis; - } - } - else - { - if (convex2) - { - if (b2Cross(normal2, primaryAxis.normal) > sinTol) - { - // Skip region - return; - } - - // Admit region - } - else - { - // Snap region - primaryAxis = edgeAxis; - } - } - } - - b2ClipVertex clipPoints[2]; - b2ReferenceFace ref; - if (primaryAxis.type == b2EPAxis::e_edgeA) - { - manifold->type = b2Manifold::e_faceA; - - // Search for the polygon normal that is most anti-parallel to the edge normal. - int32 bestIndex = 0; - float bestValue = b2Dot(primaryAxis.normal, tempPolygonB.normals[0]); - for (int32 i = 1; i < tempPolygonB.count; ++i) - { - float value = b2Dot(primaryAxis.normal, tempPolygonB.normals[i]); - if (value < bestValue) - { - bestValue = value; - bestIndex = i; - } - } - - int32 i1 = bestIndex; - int32 i2 = i1 + 1 < tempPolygonB.count ? i1 + 1 : 0; - - clipPoints[0].v = tempPolygonB.vertices[i1]; - clipPoints[0].id.cf.indexA = 0; - clipPoints[0].id.cf.indexB = static_cast(i1); - clipPoints[0].id.cf.typeA = b2ContactFeature::e_face; - clipPoints[0].id.cf.typeB = b2ContactFeature::e_vertex; - - clipPoints[1].v = tempPolygonB.vertices[i2]; - clipPoints[1].id.cf.indexA = 0; - clipPoints[1].id.cf.indexB = static_cast(i2); - clipPoints[1].id.cf.typeA = b2ContactFeature::e_face; - clipPoints[1].id.cf.typeB = b2ContactFeature::e_vertex; - - ref.i1 = 0; - ref.i2 = 1; - ref.v1 = v1; - ref.v2 = v2; - ref.normal = primaryAxis.normal; - ref.sideNormal1 = -edge1; - ref.sideNormal2 = edge1; - } - else - { - manifold->type = b2Manifold::e_faceB; - - clipPoints[0].v = v2; - clipPoints[0].id.cf.indexA = 1; - clipPoints[0].id.cf.indexB = static_cast(primaryAxis.index); - clipPoints[0].id.cf.typeA = b2ContactFeature::e_vertex; - clipPoints[0].id.cf.typeB = b2ContactFeature::e_face; - - clipPoints[1].v = v1; - clipPoints[1].id.cf.indexA = 0; - clipPoints[1].id.cf.indexB = static_cast(primaryAxis.index); - clipPoints[1].id.cf.typeA = b2ContactFeature::e_vertex; - clipPoints[1].id.cf.typeB = b2ContactFeature::e_face; - - ref.i1 = primaryAxis.index; - ref.i2 = ref.i1 + 1 < tempPolygonB.count ? ref.i1 + 1 : 0; - ref.v1 = tempPolygonB.vertices[ref.i1]; - ref.v2 = tempPolygonB.vertices[ref.i2]; - ref.normal = tempPolygonB.normals[ref.i1]; - - // CCW winding - ref.sideNormal1.Set(ref.normal.y, -ref.normal.x); - ref.sideNormal2 = -ref.sideNormal1; - } - - ref.sideOffset1 = b2Dot(ref.sideNormal1, ref.v1); - ref.sideOffset2 = b2Dot(ref.sideNormal2, ref.v2); - - // Clip incident edge against reference face side planes - b2ClipVertex clipPoints1[2]; - b2ClipVertex clipPoints2[2]; - int32 np; - - // Clip to side 1 - np = b2ClipSegmentToLine(clipPoints1, clipPoints, ref.sideNormal1, ref.sideOffset1, ref.i1); - - if (np < b2_maxManifoldPoints) - { - return; - } - - // Clip to side 2 - np = b2ClipSegmentToLine(clipPoints2, clipPoints1, ref.sideNormal2, ref.sideOffset2, ref.i2); - - if (np < b2_maxManifoldPoints) - { - return; - } - - // Now clipPoints2 contains the clipped points. - if (primaryAxis.type == b2EPAxis::e_edgeA) - { - manifold->localNormal = ref.normal; - manifold->localPoint = ref.v1; - } - else - { - manifold->localNormal = polygonB->m_normals[ref.i1]; - manifold->localPoint = polygonB->m_vertices[ref.i1]; - } - - int32 pointCount = 0; - for (int32 i = 0; i < b2_maxManifoldPoints; ++i) - { - float separation; - - separation = b2Dot(ref.normal, clipPoints2[i].v - ref.v1); - - if (separation <= radius) - { - b2ManifoldPoint* cp = manifold->points + pointCount; - - if (primaryAxis.type == b2EPAxis::e_edgeA) - { - cp->localPoint = b2MulT(xf, clipPoints2[i].v); - cp->id = clipPoints2[i].id; - } - else - { - cp->localPoint = clipPoints2[i].v; - cp->id.cf.typeA = clipPoints2[i].id.cf.typeB; - cp->id.cf.typeB = clipPoints2[i].id.cf.typeA; - cp->id.cf.indexA = clipPoints2[i].id.cf.indexB; - cp->id.cf.indexB = clipPoints2[i].id.cf.indexA; - } - - ++pointCount; - } - } - - manifold->pointCount = pointCount; -} diff --git a/3rdparty/box2d/src/collision/b2_collide_polygon.cpp b/3rdparty/box2d/src/collision/b2_collide_polygon.cpp deleted file mode 100644 index f3fa850bcb45..000000000000 --- a/3rdparty/box2d/src/collision/b2_collide_polygon.cpp +++ /dev/null @@ -1,243 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_collision.h" -#include "box2d/b2_polygon_shape.h" - -// Find the max separation between poly1 and poly2 using edge normals from poly1. -static float b2FindMaxSeparation(int32* edgeIndex, - const b2PolygonShape* poly1, const b2Transform& xf1, - const b2PolygonShape* poly2, const b2Transform& xf2) -{ - int32 count1 = poly1->m_count; - int32 count2 = poly2->m_count; - const b2Vec2* n1s = poly1->m_normals; - const b2Vec2* v1s = poly1->m_vertices; - const b2Vec2* v2s = poly2->m_vertices; - b2Transform xf = b2MulT(xf2, xf1); - - int32 bestIndex = 0; - float maxSeparation = -b2_maxFloat; - for (int32 i = 0; i < count1; ++i) - { - // Get poly1 normal in frame2. - b2Vec2 n = b2Mul(xf.q, n1s[i]); - b2Vec2 v1 = b2Mul(xf, v1s[i]); - - // Find deepest point for normal i. - float si = b2_maxFloat; - for (int32 j = 0; j < count2; ++j) - { - float sij = b2Dot(n, v2s[j] - v1); - if (sij < si) - { - si = sij; - } - } - - if (si > maxSeparation) - { - maxSeparation = si; - bestIndex = i; - } - } - - *edgeIndex = bestIndex; - return maxSeparation; -} - -static void b2FindIncidentEdge(b2ClipVertex c[2], - const b2PolygonShape* poly1, const b2Transform& xf1, int32 edge1, - const b2PolygonShape* poly2, const b2Transform& xf2) -{ - const b2Vec2* normals1 = poly1->m_normals; - - int32 count2 = poly2->m_count; - const b2Vec2* vertices2 = poly2->m_vertices; - const b2Vec2* normals2 = poly2->m_normals; - - b2Assert(0 <= edge1 && edge1 < poly1->m_count); - - // Get the normal of the reference edge in poly2's frame. - b2Vec2 normal1 = b2MulT(xf2.q, b2Mul(xf1.q, normals1[edge1])); - - // Find the incident edge on poly2. - int32 index = 0; - float minDot = b2_maxFloat; - for (int32 i = 0; i < count2; ++i) - { - float dot = b2Dot(normal1, normals2[i]); - if (dot < minDot) - { - minDot = dot; - index = i; - } - } - - // Build the clip vertices for the incident edge. - int32 i1 = index; - int32 i2 = i1 + 1 < count2 ? i1 + 1 : 0; - - c[0].v = b2Mul(xf2, vertices2[i1]); - c[0].id.cf.indexA = (uint8)edge1; - c[0].id.cf.indexB = (uint8)i1; - c[0].id.cf.typeA = b2ContactFeature::e_face; - c[0].id.cf.typeB = b2ContactFeature::e_vertex; - - c[1].v = b2Mul(xf2, vertices2[i2]); - c[1].id.cf.indexA = (uint8)edge1; - c[1].id.cf.indexB = (uint8)i2; - c[1].id.cf.typeA = b2ContactFeature::e_face; - c[1].id.cf.typeB = b2ContactFeature::e_vertex; -} - -// Find edge normal of max separation on A - return if separating axis is found -// Find edge normal of max separation on B - return if separation axis is found -// Choose reference edge as min(minA, minB) -// Find incident edge -// Clip - -// The normal points from 1 to 2 -void b2CollidePolygons(b2Manifold* manifold, - const b2PolygonShape* polyA, const b2Transform& xfA, - const b2PolygonShape* polyB, const b2Transform& xfB) -{ - manifold->pointCount = 0; - float totalRadius = polyA->m_radius + polyB->m_radius; - - int32 edgeA = 0; - float separationA = b2FindMaxSeparation(&edgeA, polyA, xfA, polyB, xfB); - if (separationA > totalRadius) - return; - - int32 edgeB = 0; - float separationB = b2FindMaxSeparation(&edgeB, polyB, xfB, polyA, xfA); - if (separationB > totalRadius) - return; - - const b2PolygonShape* poly1; // reference polygon - const b2PolygonShape* poly2; // incident polygon - b2Transform xf1, xf2; - int32 edge1; // reference edge - uint8 flip; - const float k_tol = 0.1f * b2_linearSlop; - - if (separationB > separationA + k_tol) - { - poly1 = polyB; - poly2 = polyA; - xf1 = xfB; - xf2 = xfA; - edge1 = edgeB; - manifold->type = b2Manifold::e_faceB; - flip = 1; - } - else - { - poly1 = polyA; - poly2 = polyB; - xf1 = xfA; - xf2 = xfB; - edge1 = edgeA; - manifold->type = b2Manifold::e_faceA; - flip = 0; - } - - b2ClipVertex incidentEdge[2]; - b2FindIncidentEdge(incidentEdge, poly1, xf1, edge1, poly2, xf2); - - int32 count1 = poly1->m_count; - const b2Vec2* vertices1 = poly1->m_vertices; - - int32 iv1 = edge1; - int32 iv2 = edge1 + 1 < count1 ? edge1 + 1 : 0; - - b2Vec2 v11 = vertices1[iv1]; - b2Vec2 v12 = vertices1[iv2]; - - b2Vec2 localTangent = v12 - v11; - localTangent.Normalize(); - - b2Vec2 localNormal = b2Cross(localTangent, 1.0f); - b2Vec2 planePoint = 0.5f * (v11 + v12); - - b2Vec2 tangent = b2Mul(xf1.q, localTangent); - b2Vec2 normal = b2Cross(tangent, 1.0f); - - v11 = b2Mul(xf1, v11); - v12 = b2Mul(xf1, v12); - - // Face offset. - float frontOffset = b2Dot(normal, v11); - - // Side offsets, extended by polytope skin thickness. - float sideOffset1 = -b2Dot(tangent, v11) + totalRadius; - float sideOffset2 = b2Dot(tangent, v12) + totalRadius; - - // Clip incident edge against extruded edge1 side edges. - b2ClipVertex clipPoints1[2]; - b2ClipVertex clipPoints2[2]; - int np; - - // Clip to box side 1 - np = b2ClipSegmentToLine(clipPoints1, incidentEdge, -tangent, sideOffset1, iv1); - - if (np < 2) - return; - - // Clip to negative box side 1 - np = b2ClipSegmentToLine(clipPoints2, clipPoints1, tangent, sideOffset2, iv2); - - if (np < 2) - { - return; - } - - // Now clipPoints2 contains the clipped points. - manifold->localNormal = localNormal; - manifold->localPoint = planePoint; - - int32 pointCount = 0; - for (int32 i = 0; i < b2_maxManifoldPoints; ++i) - { - float separation = b2Dot(normal, clipPoints2[i].v) - frontOffset; - - if (separation <= totalRadius) - { - b2ManifoldPoint* cp = manifold->points + pointCount; - cp->localPoint = b2MulT(xf2, clipPoints2[i].v); - cp->id = clipPoints2[i].id; - if (flip) - { - // Swap features - b2ContactFeature cf = cp->id.cf; - cp->id.cf.indexA = cf.indexB; - cp->id.cf.indexB = cf.indexA; - cp->id.cf.typeA = cf.typeB; - cp->id.cf.typeB = cf.typeA; - } - ++pointCount; - } - } - - manifold->pointCount = pointCount; -} diff --git a/3rdparty/box2d/src/collision/b2_collision.cpp b/3rdparty/box2d/src/collision/b2_collision.cpp deleted file mode 100644 index 750bff00fe7d..000000000000 --- a/3rdparty/box2d/src/collision/b2_collision.cpp +++ /dev/null @@ -1,580 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_collision.h" -#include "box2d/b2_distance.h" - -void b2WorldManifold::Initialize(const b2Manifold* manifold, - const b2Transform& xfA, float radiusA, - const b2Transform& xfB, float radiusB) -{ - if (manifold->pointCount == 0) - { - return; - } - - switch (manifold->type) - { - case b2Manifold::e_circles: - { - normal.Set(1.0f, 0.0f); - b2Vec2 pointA = b2Mul(xfA, manifold->localPoint); - b2Vec2 pointB = b2Mul(xfB, manifold->points[0].localPoint); - if (b2DistanceSquared(pointA, pointB) > b2_epsilon * b2_epsilon) - { - normal = pointB - pointA; - normal.Normalize(); - } - - b2Vec2 cA = pointA + radiusA * normal; - b2Vec2 cB = pointB - radiusB * normal; - points[0] = 0.5f * (cA + cB); - separations[0] = b2Dot(cB - cA, normal); - } - break; - - case b2Manifold::e_faceA: - { - normal = b2Mul(xfA.q, manifold->localNormal); - b2Vec2 planePoint = b2Mul(xfA, manifold->localPoint); - - for (int32 i = 0; i < manifold->pointCount; ++i) - { - b2Vec2 clipPoint = b2Mul(xfB, manifold->points[i].localPoint); - b2Vec2 cA = clipPoint + (radiusA - b2Dot(clipPoint - planePoint, normal)) * normal; - b2Vec2 cB = clipPoint - radiusB * normal; - points[i] = 0.5f * (cA + cB); - separations[i] = b2Dot(cB - cA, normal); - } - } - break; - - case b2Manifold::e_faceB: - { - normal = b2Mul(xfB.q, manifold->localNormal); - b2Vec2 planePoint = b2Mul(xfB, manifold->localPoint); - - for (int32 i = 0; i < manifold->pointCount; ++i) - { - b2Vec2 clipPoint = b2Mul(xfA, manifold->points[i].localPoint); - b2Vec2 cB = clipPoint + (radiusB - b2Dot(clipPoint - planePoint, normal)) * normal; - b2Vec2 cA = clipPoint - radiusA * normal; - points[i] = 0.5f * (cA + cB); - separations[i] = b2Dot(cA - cB, normal); - } - - // Ensure normal points from A to B. - normal = -normal; - } - break; - } -} - -void b2GetPointStates(b2PointState state1[b2_maxManifoldPoints], b2PointState state2[b2_maxManifoldPoints], - const b2Manifold* manifold1, const b2Manifold* manifold2) -{ - for (int32 i = 0; i < b2_maxManifoldPoints; ++i) - { - state1[i] = b2_nullState; - state2[i] = b2_nullState; - } - - // Detect persists and removes. - for (int32 i = 0; i < manifold1->pointCount; ++i) - { - b2ContactID id = manifold1->points[i].id; - - state1[i] = b2_removeState; - - for (int32 j = 0; j < manifold2->pointCount; ++j) - { - if (manifold2->points[j].id.key == id.key) - { - state1[i] = b2_persistState; - break; - } - } - } - - // Detect persists and adds. - for (int32 i = 0; i < manifold2->pointCount; ++i) - { - b2ContactID id = manifold2->points[i].id; - - state2[i] = b2_addState; - - for (int32 j = 0; j < manifold1->pointCount; ++j) - { - if (manifold1->points[j].id.key == id.key) - { - state2[i] = b2_persistState; - break; - } - } - } -} - -// From Real-time Collision Detection, p179. -bool b2AABB::RayCast(b2RayCastOutput* output, const b2RayCastInput& input) const -{ - float tmin = -b2_maxFloat; - float tmax = b2_maxFloat; - - b2Vec2 p = input.p1; - b2Vec2 d = input.p2 - input.p1; - b2Vec2 absD = b2Abs(d); - - b2Vec2 normal; - - for (int32 i = 0; i < 2; ++i) - { - if (absD(i) < b2_epsilon) - { - // Parallel. - if (p(i) < lowerBound(i) || upperBound(i) < p(i)) - { - return false; - } - } - else - { - float inv_d = 1.0f / d(i); - float t1 = (lowerBound(i) - p(i)) * inv_d; - float t2 = (upperBound(i) - p(i)) * inv_d; - - // Sign of the normal vector. - float s = -1.0f; - - if (t1 > t2) - { - b2Swap(t1, t2); - s = 1.0f; - } - - // Push the min up - if (t1 > tmin) - { - normal.SetZero(); - normal(i) = s; - tmin = t1; - } - - // Pull the max down - tmax = b2Min(tmax, t2); - - if (tmin > tmax) - { - return false; - } - } - } - - // Does the ray start inside the box? - // Does the ray intersect beyond the max fraction? - if (tmin < 0.0f || input.maxFraction < tmin) - { - return false; - } - - // Intersection. - output->fraction = tmin; - output->normal = normal; - return true; -} - -// Sutherland-Hodgman clipping. -int32 b2ClipSegmentToLine(b2ClipVertex vOut[2], const b2ClipVertex vIn[2], - const b2Vec2& normal, float offset, int32 vertexIndexA) -{ - // Start with no output points - int32 count = 0; - - // Calculate the distance of end points to the line - float distance0 = b2Dot(normal, vIn[0].v) - offset; - float distance1 = b2Dot(normal, vIn[1].v) - offset; - - // If the points are behind the plane - if (distance0 <= 0.0f) vOut[count++] = vIn[0]; - if (distance1 <= 0.0f) vOut[count++] = vIn[1]; - - // If the points are on different sides of the plane - if (distance0 * distance1 < 0.0f) - { - // Find intersection point of edge and plane - float interp = distance0 / (distance0 - distance1); - vOut[count].v = vIn[0].v + interp * (vIn[1].v - vIn[0].v); - - // VertexA is hitting edgeB. - vOut[count].id.cf.indexA = static_cast(vertexIndexA); - vOut[count].id.cf.indexB = vIn[0].id.cf.indexB; - vOut[count].id.cf.typeA = b2ContactFeature::e_vertex; - vOut[count].id.cf.typeB = b2ContactFeature::e_face; - ++count; - - b2Assert(count == 2); - } - - return count; -} - -bool b2TestOverlap( const b2Shape* shapeA, int32 indexA, - const b2Shape* shapeB, int32 indexB, - const b2Transform& xfA, const b2Transform& xfB) -{ - b2DistanceInput input; - input.proxyA.Set(shapeA, indexA); - input.proxyB.Set(shapeB, indexB); - input.transformA = xfA; - input.transformB = xfB; - input.useRadii = true; - - b2SimplexCache cache; - cache.count = 0; - - b2DistanceOutput output; - - b2Distance(&output, &cache, &input); - - return output.distance < 10.0f * b2_epsilon; -} - -// quickhull recursion -static b2Hull b2RecurseHull(b2Vec2 p1, b2Vec2 p2, b2Vec2* ps, int32 count) -{ - b2Hull hull; - hull.count = 0; - - if (count == 0) - { - return hull; - } - - // create an edge vector pointing from p1 to p2 - b2Vec2 e = p2 - p1; - e.Normalize(); - - // discard points left of e and find point furthest to the right of e - b2Vec2 rightPoints[b2_maxPolygonVertices]{}; - int32 rightCount = 0; - - int32 bestIndex = 0; - float bestDistance = b2Cross(ps[bestIndex] - p1, e); - if (bestDistance > 0.0f) - { - rightPoints[rightCount++] = ps[bestIndex]; - } - - for (int32 i = 1; i < count; ++i) - { - float distance = b2Cross(ps[i] - p1, e); - if (distance > bestDistance) - { - bestIndex = i; - bestDistance = distance; - } - - if (distance > 0.0f) - { - rightPoints[rightCount++] = ps[i]; - } - } - - if (bestDistance < 2.0f * b2_linearSlop) - { - return hull; - } - - b2Vec2 bestPoint = ps[bestIndex]; - - // compute hull to the right of p1-bestPoint - b2Hull hull1 = b2RecurseHull(p1, bestPoint, rightPoints, rightCount); - - // compute hull to the right of bestPoint-p2 - b2Hull hull2 = b2RecurseHull(bestPoint, p2, rightPoints, rightCount); - - // stich together hulls - for (int32 i = 0; i < hull1.count; ++i) - { - hull.points[hull.count++] = hull1.points[i]; - } - - hull.points[hull.count++] = bestPoint; - - for (int32 i = 0; i < hull2.count; ++i) - { - hull.points[hull.count++] = hull2.points[i]; - } - - b2Assert(hull.count < b2_maxPolygonVertices); - - return hull; -} - -// quickhull algorithm -// - merges vertices based on b2_linearSlop -// - removes collinear points using b2_linearSlop -// - returns an empty hull if it fails -b2Hull b2ComputeHull(const b2Vec2* points, int32 count) -{ - b2Hull hull; - hull.count = 0; - - if (count < 3 || count > b2_maxPolygonVertices) - { - // check your data - return hull; - } - - count = b2Min(count, b2_maxPolygonVertices); - - b2AABB aabb = { {b2_maxFloat, b2_maxFloat}, {-b2_maxFloat, -b2_maxFloat} }; - - // Perform aggressive point welding. First point always remains. - // Also compute the bounding box for later. - b2Vec2 ps[b2_maxPolygonVertices]; - int32 n = 0; - const float tolSqr = 16.0f * b2_linearSlop * b2_linearSlop; - for (int32 i = 0; i < count; ++i) - { - aabb.lowerBound = b2Min(aabb.lowerBound, points[i]); - aabb.upperBound = b2Max(aabb.upperBound, points[i]); - - b2Vec2 vi = points[i]; - - bool unique = true; - for (int32 j = 0; j < i; ++j) - { - b2Vec2 vj = points[j]; - - float distSqr = b2DistanceSquared(vi, vj); - if (distSqr < tolSqr) - { - unique = false; - break; - } - } - - if (unique) - { - ps[n++] = vi; - } - } - - if (n < 3) - { - // all points very close together, check your data and check your scale - return hull; - } - - // Find an extreme point as the first point on the hull - b2Vec2 c = aabb.GetCenter(); - int32 i1 = 0; - float dsq1 = b2DistanceSquared(c, ps[i1]); - for (int32 i = 1; i < n; ++i) - { - float dsq = b2DistanceSquared(c, ps[i]); - if (dsq > dsq1) - { - i1 = i; - dsq1 = dsq; - } - } - - // remove p1 from working set - b2Vec2 p1 = ps[i1]; - ps[i1] = ps[n - 1]; - n = n - 1; - - int32 i2 = 0; - float dsq2 = b2DistanceSquared(p1, ps[i2]); - for (int32 i = 1; i < n; ++i) - { - float dsq = b2DistanceSquared(p1, ps[i]); - if (dsq > dsq2) - { - i2 = i; - dsq2 = dsq; - } - } - - // remove p2 from working set - b2Vec2 p2 = ps[i2]; - ps[i2] = ps[n - 1]; - n = n - 1; - - // split the points into points that are left and right of the line p1-p2. - b2Vec2 rightPoints[b2_maxPolygonVertices - 2]; - int32 rightCount = 0; - - b2Vec2 leftPoints[b2_maxPolygonVertices - 2]; - int32 leftCount = 0; - - b2Vec2 e = p2 - p1; - e.Normalize(); - - for (int32 i = 0; i < n; ++i) - { - float d = b2Cross(ps[i] - p1, e); - - // slop used here to skip points that are very close to the line p1-p2 - if (d >= 2.0f * b2_linearSlop) - { - rightPoints[rightCount++] = ps[i]; - } - else if (d <= -2.0f * b2_linearSlop) - { - leftPoints[leftCount++] = ps[i]; - } - } - - // compute hulls on right and left - b2Hull hull1 = b2RecurseHull(p1, p2, rightPoints, rightCount); - b2Hull hull2 = b2RecurseHull(p2, p1, leftPoints, leftCount); - - if (hull1.count == 0 && hull2.count == 0) - { - // all points collinear - return hull; - } - - // stitch hulls together, preserving CCW winding order - hull.points[hull.count++] = p1; - - for (int32 i = 0; i < hull1.count; ++i) - { - hull.points[hull.count++] = hull1.points[i]; - } - - hull.points[hull.count++] = p2; - - for (int32 i = 0; i < hull2.count; ++i) - { - hull.points[hull.count++] = hull2.points[i]; - } - - b2Assert(hull.count <= b2_maxPolygonVertices); - - // merge collinear - bool searching = true; - while (searching && hull.count > 2) - { - searching = false; - - for (int32 i = 0; i < hull.count; ++i) - { - int32 i1 = i; - int32 i2 = (i + 1) % hull.count; - int32 i3 = (i + 2) % hull.count; - - b2Vec2 p1 = hull.points[i1]; - b2Vec2 p2 = hull.points[i2]; - b2Vec2 p3 = hull.points[i3]; - - b2Vec2 e = p3 - p1; - e.Normalize(); - - b2Vec2 v = p2 - p1; - float distance = b2Cross(p2 - p1, e); - if (distance <= 2.0f * b2_linearSlop) - { - // remove midpoint from hull - for (int32 j = i2; j < hull.count - 1; ++j) - { - hull.points[j] = hull.points[j + 1]; - } - hull.count -= 1; - - // continue searching for collinear points - searching = true; - - break; - } - } - } - - if (hull.count < 3) - { - // all points collinear, shouldn't be reached since this was validated above - hull.count = 0; - } - - return hull; -} - -bool b2ValidateHull(const b2Hull& hull) -{ - if (hull.count < 3 || b2_maxPolygonVertices < hull.count) - { - return false; - } - - // test that every point is behind every edge - for (int32 i = 0; i < hull.count; ++i) - { - // create an edge vector - int32 i1 = i; - int32 i2 = i < hull.count - 1 ? i1 + 1 : 0; - b2Vec2 p = hull.points[i1]; - b2Vec2 e = hull.points[i2] - p; - e.Normalize(); - - for (int32 j = 0; j < hull.count; ++j) - { - // skip points that subtend the current edge - if (j == i1 || j == i2) - { - continue; - } - - float distance = b2Cross(hull.points[j] - p, e); - if (distance >= 0.0f) - { - return false; - } - } - } - - // test for collinear points - for (int32 i = 0; i < hull.count; ++i) - { - int32 i1 = i; - int32 i2 = (i + 1) % hull.count; - int32 i3 = (i + 2) % hull.count; - - b2Vec2 p1 = hull.points[i1]; - b2Vec2 p2 = hull.points[i2]; - b2Vec2 p3 = hull.points[i3]; - - b2Vec2 e = p3 - p1; - e.Normalize(); - - b2Vec2 v = p2 - p1; - float distance = b2Cross(p2 - p1, e); - if (distance <= b2_linearSlop) - { - // p1-p2-p3 are collinear - return false; - } - } - - return true; -} diff --git a/3rdparty/box2d/src/collision/b2_distance.cpp b/3rdparty/box2d/src/collision/b2_distance.cpp deleted file mode 100644 index 16fa3cc3d986..000000000000 --- a/3rdparty/box2d/src/collision/b2_distance.cpp +++ /dev/null @@ -1,744 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_distance.h" -#include "box2d/b2_edge_shape.h" -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_polygon_shape.h" - -// GJK using Voronoi regions (Christer Ericson) and Barycentric coordinates. -B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - -void b2DistanceProxy::Set(const b2Shape* shape, int32 index) -{ - switch (shape->GetType()) - { - case b2Shape::e_circle: - { - const b2CircleShape* circle = static_cast(shape); - m_vertices = &circle->m_p; - m_count = 1; - m_radius = circle->m_radius; - } - break; - - case b2Shape::e_polygon: - { - const b2PolygonShape* polygon = static_cast(shape); - m_vertices = polygon->m_vertices; - m_count = polygon->m_count; - m_radius = polygon->m_radius; - } - break; - - case b2Shape::e_chain: - { - const b2ChainShape* chain = static_cast(shape); - b2Assert(0 <= index && index < chain->m_count); - - m_buffer[0] = chain->m_vertices[index]; - if (index + 1 < chain->m_count) - { - m_buffer[1] = chain->m_vertices[index + 1]; - } - else - { - m_buffer[1] = chain->m_vertices[0]; - } - - m_vertices = m_buffer; - m_count = 2; - m_radius = chain->m_radius; - } - break; - - case b2Shape::e_edge: - { - const b2EdgeShape* edge = static_cast(shape); - m_vertices = &edge->m_vertex1; - m_count = 2; - m_radius = edge->m_radius; - } - break; - - default: - b2Assert(false); - } -} - -void b2DistanceProxy::Set(const b2Vec2* vertices, int32 count, float radius) -{ - m_vertices = vertices; - m_count = count; - m_radius = radius; -} - -struct b2SimplexVertex -{ - b2Vec2 wA; // support point in proxyA - b2Vec2 wB; // support point in proxyB - b2Vec2 w; // wB - wA - float a; // barycentric coordinate for closest point - int32 indexA; // wA index - int32 indexB; // wB index -}; - -struct b2Simplex -{ - void ReadCache( const b2SimplexCache* cache, - const b2DistanceProxy* proxyA, const b2Transform& transformA, - const b2DistanceProxy* proxyB, const b2Transform& transformB) - { - b2Assert(cache->count <= 3); - - // Copy data from cache. - m_count = cache->count; - b2SimplexVertex* vertices = &m_v1; - for (int32 i = 0; i < m_count; ++i) - { - b2SimplexVertex* v = vertices + i; - v->indexA = cache->indexA[i]; - v->indexB = cache->indexB[i]; - b2Vec2 wALocal = proxyA->GetVertex(v->indexA); - b2Vec2 wBLocal = proxyB->GetVertex(v->indexB); - v->wA = b2Mul(transformA, wALocal); - v->wB = b2Mul(transformB, wBLocal); - v->w = v->wB - v->wA; - v->a = 0.0f; - } - - // Compute the new simplex metric, if it is substantially different than - // old metric then flush the simplex. - if (m_count > 1) - { - float metric1 = cache->metric; - float metric2 = GetMetric(); - if (metric2 < 0.5f * metric1 || 2.0f * metric1 < metric2 || metric2 < b2_epsilon) - { - // Reset the simplex. - m_count = 0; - } - } - - // If the cache is empty or invalid ... - if (m_count == 0) - { - b2SimplexVertex* v = vertices + 0; - v->indexA = 0; - v->indexB = 0; - b2Vec2 wALocal = proxyA->GetVertex(0); - b2Vec2 wBLocal = proxyB->GetVertex(0); - v->wA = b2Mul(transformA, wALocal); - v->wB = b2Mul(transformB, wBLocal); - v->w = v->wB - v->wA; - v->a = 1.0f; - m_count = 1; - } - } - - void WriteCache(b2SimplexCache* cache) const - { - cache->metric = GetMetric(); - cache->count = uint16(m_count); - const b2SimplexVertex* vertices = &m_v1; - for (int32 i = 0; i < m_count; ++i) - { - cache->indexA[i] = uint8(vertices[i].indexA); - cache->indexB[i] = uint8(vertices[i].indexB); - } - } - - b2Vec2 GetSearchDirection() const - { - switch (m_count) - { - case 1: - return -m_v1.w; - - case 2: - { - b2Vec2 e12 = m_v2.w - m_v1.w; - float sgn = b2Cross(e12, -m_v1.w); - if (sgn > 0.0f) - { - // Origin is left of e12. - return b2Cross(1.0f, e12); - } - else - { - // Origin is right of e12. - return b2Cross(e12, 1.0f); - } - } - - default: - b2Assert(false); - return b2Vec2_zero; - } - } - - b2Vec2 GetClosestPoint() const - { - switch (m_count) - { - case 0: - b2Assert(false); - return b2Vec2_zero; - - case 1: - return m_v1.w; - - case 2: - return m_v1.a * m_v1.w + m_v2.a * m_v2.w; - - case 3: - return b2Vec2_zero; - - default: - b2Assert(false); - return b2Vec2_zero; - } - } - - void GetWitnessPoints(b2Vec2* pA, b2Vec2* pB) const - { - switch (m_count) - { - case 0: - b2Assert(false); - break; - - case 1: - *pA = m_v1.wA; - *pB = m_v1.wB; - break; - - case 2: - *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA; - *pB = m_v1.a * m_v1.wB + m_v2.a * m_v2.wB; - break; - - case 3: - *pA = m_v1.a * m_v1.wA + m_v2.a * m_v2.wA + m_v3.a * m_v3.wA; - *pB = *pA; - break; - - default: - b2Assert(false); - break; - } - } - - float GetMetric() const - { - switch (m_count) - { - case 0: - b2Assert(false); - return 0.0f; - - case 1: - return 0.0f; - - case 2: - return b2Distance(m_v1.w, m_v2.w); - - case 3: - return b2Cross(m_v2.w - m_v1.w, m_v3.w - m_v1.w); - - default: - b2Assert(false); - return 0.0f; - } - } - - void Solve2(); - void Solve3(); - - b2SimplexVertex m_v1, m_v2, m_v3; - int32 m_count; -}; - - -// Solve a line segment using barycentric coordinates. -// -// p = a1 * w1 + a2 * w2 -// a1 + a2 = 1 -// -// The vector from the origin to the closest point on the line is -// perpendicular to the line. -// e12 = w2 - w1 -// dot(p, e) = 0 -// a1 * dot(w1, e) + a2 * dot(w2, e) = 0 -// -// 2-by-2 linear system -// [1 1 ][a1] = [1] -// [w1.e12 w2.e12][a2] = [0] -// -// Define -// d12_1 = dot(w2, e12) -// d12_2 = -dot(w1, e12) -// d12 = d12_1 + d12_2 -// -// Solution -// a1 = d12_1 / d12 -// a2 = d12_2 / d12 -void b2Simplex::Solve2() -{ - b2Vec2 w1 = m_v1.w; - b2Vec2 w2 = m_v2.w; - b2Vec2 e12 = w2 - w1; - - // w1 region - float d12_2 = -b2Dot(w1, e12); - if (d12_2 <= 0.0f) - { - // a2 <= 0, so we clamp it to 0 - m_v1.a = 1.0f; - m_count = 1; - return; - } - - // w2 region - float d12_1 = b2Dot(w2, e12); - if (d12_1 <= 0.0f) - { - // a1 <= 0, so we clamp it to 0 - m_v2.a = 1.0f; - m_count = 1; - m_v1 = m_v2; - return; - } - - // Must be in e12 region. - float inv_d12 = 1.0f / (d12_1 + d12_2); - m_v1.a = d12_1 * inv_d12; - m_v2.a = d12_2 * inv_d12; - m_count = 2; -} - -// Possible regions: -// - points[2] -// - edge points[0]-points[2] -// - edge points[1]-points[2] -// - inside the triangle -void b2Simplex::Solve3() -{ - b2Vec2 w1 = m_v1.w; - b2Vec2 w2 = m_v2.w; - b2Vec2 w3 = m_v3.w; - - // Edge12 - // [1 1 ][a1] = [1] - // [w1.e12 w2.e12][a2] = [0] - // a3 = 0 - b2Vec2 e12 = w2 - w1; - float w1e12 = b2Dot(w1, e12); - float w2e12 = b2Dot(w2, e12); - float d12_1 = w2e12; - float d12_2 = -w1e12; - - // Edge13 - // [1 1 ][a1] = [1] - // [w1.e13 w3.e13][a3] = [0] - // a2 = 0 - b2Vec2 e13 = w3 - w1; - float w1e13 = b2Dot(w1, e13); - float w3e13 = b2Dot(w3, e13); - float d13_1 = w3e13; - float d13_2 = -w1e13; - - // Edge23 - // [1 1 ][a2] = [1] - // [w2.e23 w3.e23][a3] = [0] - // a1 = 0 - b2Vec2 e23 = w3 - w2; - float w2e23 = b2Dot(w2, e23); - float w3e23 = b2Dot(w3, e23); - float d23_1 = w3e23; - float d23_2 = -w2e23; - - // Triangle123 - float n123 = b2Cross(e12, e13); - - float d123_1 = n123 * b2Cross(w2, w3); - float d123_2 = n123 * b2Cross(w3, w1); - float d123_3 = n123 * b2Cross(w1, w2); - - // w1 region - if (d12_2 <= 0.0f && d13_2 <= 0.0f) - { - m_v1.a = 1.0f; - m_count = 1; - return; - } - - // e12 - if (d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f) - { - float inv_d12 = 1.0f / (d12_1 + d12_2); - m_v1.a = d12_1 * inv_d12; - m_v2.a = d12_2 * inv_d12; - m_count = 2; - return; - } - - // e13 - if (d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f) - { - float inv_d13 = 1.0f / (d13_1 + d13_2); - m_v1.a = d13_1 * inv_d13; - m_v3.a = d13_2 * inv_d13; - m_count = 2; - m_v2 = m_v3; - return; - } - - // w2 region - if (d12_1 <= 0.0f && d23_2 <= 0.0f) - { - m_v2.a = 1.0f; - m_count = 1; - m_v1 = m_v2; - return; - } - - // w3 region - if (d13_1 <= 0.0f && d23_1 <= 0.0f) - { - m_v3.a = 1.0f; - m_count = 1; - m_v1 = m_v3; - return; - } - - // e23 - if (d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f) - { - float inv_d23 = 1.0f / (d23_1 + d23_2); - m_v2.a = d23_1 * inv_d23; - m_v3.a = d23_2 * inv_d23; - m_count = 2; - m_v1 = m_v3; - return; - } - - // Must be in triangle123 - float inv_d123 = 1.0f / (d123_1 + d123_2 + d123_3); - m_v1.a = d123_1 * inv_d123; - m_v2.a = d123_2 * inv_d123; - m_v3.a = d123_3 * inv_d123; - m_count = 3; -} - -void b2Distance(b2DistanceOutput* output, - b2SimplexCache* cache, - const b2DistanceInput* input) -{ - ++b2_gjkCalls; - - const b2DistanceProxy* proxyA = &input->proxyA; - const b2DistanceProxy* proxyB = &input->proxyB; - - b2Transform transformA = input->transformA; - b2Transform transformB = input->transformB; - - // Initialize the simplex. - b2Simplex simplex; - simplex.ReadCache(cache, proxyA, transformA, proxyB, transformB); - - // Get simplex vertices as an array. - b2SimplexVertex* vertices = &simplex.m_v1; - const int32 k_maxIters = 20; - - // These store the vertices of the last simplex so that we - // can check for duplicates and prevent cycling. - int32 saveA[3], saveB[3]; - int32 saveCount = 0; - - // Main iteration loop. - int32 iter = 0; - while (iter < k_maxIters) - { - // Copy simplex so we can identify duplicates. - saveCount = simplex.m_count; - for (int32 i = 0; i < saveCount; ++i) - { - saveA[i] = vertices[i].indexA; - saveB[i] = vertices[i].indexB; - } - - switch (simplex.m_count) - { - case 1: - break; - - case 2: - simplex.Solve2(); - break; - - case 3: - simplex.Solve3(); - break; - - default: - b2Assert(false); - } - - // If we have 3 points, then the origin is in the corresponding triangle. - if (simplex.m_count == 3) - { - break; - } - - // Get search direction. - b2Vec2 d = simplex.GetSearchDirection(); - - // Ensure the search direction is numerically fit. - if (d.LengthSquared() < b2_epsilon * b2_epsilon) - { - // The origin is probably contained by a line segment - // or triangle. Thus the shapes are overlapped. - - // We can't return zero here even though there may be overlap. - // In case the simplex is a point, segment, or triangle it is difficult - // to determine if the origin is contained in the CSO or very close to it. - break; - } - - // Compute a tentative new simplex vertex using support points. - b2SimplexVertex* vertex = vertices + simplex.m_count; - vertex->indexA = proxyA->GetSupport(b2MulT(transformA.q, -d)); - vertex->wA = b2Mul(transformA, proxyA->GetVertex(vertex->indexA)); - vertex->indexB = proxyB->GetSupport(b2MulT(transformB.q, d)); - vertex->wB = b2Mul(transformB, proxyB->GetVertex(vertex->indexB)); - vertex->w = vertex->wB - vertex->wA; - - // Iteration count is equated to the number of support point calls. - ++iter; - ++b2_gjkIters; - - // Check for duplicate support points. This is the main termination criteria. - bool duplicate = false; - for (int32 i = 0; i < saveCount; ++i) - { - if (vertex->indexA == saveA[i] && vertex->indexB == saveB[i]) - { - duplicate = true; - break; - } - } - - // If we found a duplicate support point we must exit to avoid cycling. - if (duplicate) - { - break; - } - - // New vertex is ok and needed. - ++simplex.m_count; - } - - b2_gjkMaxIters = b2Max(b2_gjkMaxIters, iter); - - // Prepare output. - simplex.GetWitnessPoints(&output->pointA, &output->pointB); - output->distance = b2Distance(output->pointA, output->pointB); - output->iterations = iter; - - // Cache the simplex. - simplex.WriteCache(cache); - - // Apply radii if requested - if (input->useRadii) - { - if (output->distance < b2_epsilon) - { - // Shapes are too close to safely compute normal - b2Vec2 p = 0.5f * (output->pointA + output->pointB); - output->pointA = p; - output->pointB = p; - output->distance = 0.0f; - } - else - { - // Keep closest points on perimeter even if overlapped, this way - // the points move smoothly. - float rA = proxyA->m_radius; - float rB = proxyB->m_radius; - b2Vec2 normal = output->pointB - output->pointA; - normal.Normalize(); - output->distance = b2Max(0.0f, output->distance - rA - rB); - output->pointA += rA * normal; - output->pointB -= rB * normal; - } - } -} - -// GJK-raycast -// Algorithm by Gino van den Bergen. -// "Smooth Mesh Contacts with GJK" in Game Physics Pearls. 2010 -bool b2ShapeCast(b2ShapeCastOutput * output, const b2ShapeCastInput * input) -{ - output->iterations = 0; - output->lambda = 1.0f; - output->normal.SetZero(); - output->point.SetZero(); - - const b2DistanceProxy* proxyA = &input->proxyA; - const b2DistanceProxy* proxyB = &input->proxyB; - - float radiusA = b2Max(proxyA->m_radius, b2_polygonRadius); - float radiusB = b2Max(proxyB->m_radius, b2_polygonRadius); - float radius = radiusA + radiusB; - - b2Transform xfA = input->transformA; - b2Transform xfB = input->transformB; - - b2Vec2 r = input->translationB; - b2Vec2 n(0.0f, 0.0f); - float lambda = 0.0f; - - // Initial simplex - b2Simplex simplex; - simplex.m_count = 0; - - // Get simplex vertices as an array. - b2SimplexVertex* vertices = &simplex.m_v1; - - // Get support point in -r direction - int32 indexA = proxyA->GetSupport(b2MulT(xfA.q, -r)); - b2Vec2 wA = b2Mul(xfA, proxyA->GetVertex(indexA)); - int32 indexB = proxyB->GetSupport(b2MulT(xfB.q, r)); - b2Vec2 wB = b2Mul(xfB, proxyB->GetVertex(indexB)); - b2Vec2 v = wA - wB; - - // Sigma is the target distance between polygons - float sigma = b2Max(b2_polygonRadius, radius - b2_polygonRadius); - const float tolerance = 0.5f * b2_linearSlop; - - // Main iteration loop. - const int32 k_maxIters = 20; - int32 iter = 0; - while (iter < k_maxIters && v.Length() - sigma > tolerance) - { - b2Assert(simplex.m_count < 3); - - output->iterations += 1; - - // Support in direction -v (A - B) - indexA = proxyA->GetSupport(b2MulT(xfA.q, -v)); - wA = b2Mul(xfA, proxyA->GetVertex(indexA)); - indexB = proxyB->GetSupport(b2MulT(xfB.q, v)); - wB = b2Mul(xfB, proxyB->GetVertex(indexB)); - b2Vec2 p = wA - wB; - - // -v is a normal at p - v.Normalize(); - - // Intersect ray with plane - float vp = b2Dot(v, p); - float vr = b2Dot(v, r); - if (vp - sigma > lambda * vr) - { - if (vr <= 0.0f) - { - return false; - } - - lambda = (vp - sigma) / vr; - if (lambda > 1.0f) - { - return false; - } - - n = -v; - simplex.m_count = 0; - } - - // Reverse simplex since it works with B - A. - // Shift by lambda * r because we want the closest point to the current clip point. - // Note that the support point p is not shifted because we want the plane equation - // to be formed in unshifted space. - b2SimplexVertex* vertex = vertices + simplex.m_count; - vertex->indexA = indexB; - vertex->wA = wB + lambda * r; - vertex->indexB = indexA; - vertex->wB = wA; - vertex->w = vertex->wB - vertex->wA; - vertex->a = 1.0f; - simplex.m_count += 1; - - switch (simplex.m_count) - { - case 1: - break; - - case 2: - simplex.Solve2(); - break; - - case 3: - simplex.Solve3(); - break; - - default: - b2Assert(false); - } - - // If we have 3 points, then the origin is in the corresponding triangle. - if (simplex.m_count == 3) - { - // Overlap - return false; - } - - // Get search direction. - v = simplex.GetClosestPoint(); - - // Iteration count is equated to the number of support point calls. - ++iter; - } - - if (iter == 0) - { - // Initial overlap - return false; - } - - // Prepare output. - b2Vec2 pointA, pointB; - simplex.GetWitnessPoints(&pointB, &pointA); - - if (v.LengthSquared() > 0.0f) - { - n = -v; - n.Normalize(); - } - - output->point = pointA + radiusA * n; - output->normal = n; - output->lambda = lambda; - output->iterations = iter; - return true; -} diff --git a/3rdparty/box2d/src/collision/b2_dynamic_tree.cpp b/3rdparty/box2d/src/collision/b2_dynamic_tree.cpp deleted file mode 100644 index 55a9d3246ad6..000000000000 --- a/3rdparty/box2d/src/collision/b2_dynamic_tree.cpp +++ /dev/null @@ -1,801 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -#include "box2d/b2_dynamic_tree.h" -#include - -b2DynamicTree::b2DynamicTree() -{ - m_root = b2_nullNode; - - m_nodeCapacity = 16; - m_nodeCount = 0; - m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode)); - memset(m_nodes, 0, m_nodeCapacity * sizeof(b2TreeNode)); - - // Build a linked list for the free list. - for (int32 i = 0; i < m_nodeCapacity - 1; ++i) - { - m_nodes[i].next = i + 1; - m_nodes[i].height = -1; - } - m_nodes[m_nodeCapacity-1].next = b2_nullNode; - m_nodes[m_nodeCapacity-1].height = -1; - m_freeList = 0; - - m_insertionCount = 0; -} - -b2DynamicTree::~b2DynamicTree() -{ - // This frees the entire tree in one shot. - b2Free(m_nodes); -} - -// Allocate a node from the pool. Grow the pool if necessary. -int32 b2DynamicTree::AllocateNode() -{ - // Expand the node pool as needed. - if (m_freeList == b2_nullNode) - { - b2Assert(m_nodeCount == m_nodeCapacity); - - // The free list is empty. Rebuild a bigger pool. - b2TreeNode* oldNodes = m_nodes; - m_nodeCapacity *= 2; - m_nodes = (b2TreeNode*)b2Alloc(m_nodeCapacity * sizeof(b2TreeNode)); - memcpy(m_nodes, oldNodes, m_nodeCount * sizeof(b2TreeNode)); - b2Free(oldNodes); - - // Build a linked list for the free list. The parent - // pointer becomes the "next" pointer. - for (int32 i = m_nodeCount; i < m_nodeCapacity - 1; ++i) - { - m_nodes[i].next = i + 1; - m_nodes[i].height = -1; - } - m_nodes[m_nodeCapacity-1].next = b2_nullNode; - m_nodes[m_nodeCapacity-1].height = -1; - m_freeList = m_nodeCount; - } - - // Peel a node off the free list. - int32 nodeId = m_freeList; - m_freeList = m_nodes[nodeId].next; - m_nodes[nodeId].parent = b2_nullNode; - m_nodes[nodeId].child1 = b2_nullNode; - m_nodes[nodeId].child2 = b2_nullNode; - m_nodes[nodeId].height = 0; - m_nodes[nodeId].userData = nullptr; - m_nodes[nodeId].moved = false; - ++m_nodeCount; - return nodeId; -} - -// Return a node to the pool. -void b2DynamicTree::FreeNode(int32 nodeId) -{ - b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); - b2Assert(0 < m_nodeCount); - m_nodes[nodeId].next = m_freeList; - m_nodes[nodeId].height = -1; - m_freeList = nodeId; - --m_nodeCount; -} - -// Create a proxy in the tree as a leaf node. We return the index -// of the node instead of a pointer so that we can grow -// the node pool. -int32 b2DynamicTree::CreateProxy(const b2AABB& aabb, void* userData) -{ - int32 proxyId = AllocateNode(); - - // Fatten the aabb. - b2Vec2 r(b2_aabbExtension, b2_aabbExtension); - m_nodes[proxyId].aabb.lowerBound = aabb.lowerBound - r; - m_nodes[proxyId].aabb.upperBound = aabb.upperBound + r; - m_nodes[proxyId].userData = userData; - m_nodes[proxyId].height = 0; - m_nodes[proxyId].moved = true; - - InsertLeaf(proxyId); - - return proxyId; -} - -void b2DynamicTree::DestroyProxy(int32 proxyId) -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - b2Assert(m_nodes[proxyId].IsLeaf()); - - RemoveLeaf(proxyId); - FreeNode(proxyId); -} - -bool b2DynamicTree::MoveProxy(int32 proxyId, const b2AABB& aabb, const b2Vec2& displacement) -{ - b2Assert(0 <= proxyId && proxyId < m_nodeCapacity); - - b2Assert(m_nodes[proxyId].IsLeaf()); - - // Extend AABB - b2AABB fatAABB; - b2Vec2 r(b2_aabbExtension, b2_aabbExtension); - fatAABB.lowerBound = aabb.lowerBound - r; - fatAABB.upperBound = aabb.upperBound + r; - - // Predict AABB movement - b2Vec2 d = b2_aabbMultiplier * displacement; - - if (d.x < 0.0f) - { - fatAABB.lowerBound.x += d.x; - } - else - { - fatAABB.upperBound.x += d.x; - } - - if (d.y < 0.0f) - { - fatAABB.lowerBound.y += d.y; - } - else - { - fatAABB.upperBound.y += d.y; - } - - const b2AABB& treeAABB = m_nodes[proxyId].aabb; - if (treeAABB.Contains(aabb)) - { - // The tree AABB still contains the object, but it might be too large. - // Perhaps the object was moving fast but has since gone to sleep. - // The huge AABB is larger than the new fat AABB. - b2AABB hugeAABB; - hugeAABB.lowerBound = fatAABB.lowerBound - 4.0f * r; - hugeAABB.upperBound = fatAABB.upperBound + 4.0f * r; - - if (hugeAABB.Contains(treeAABB)) - { - // The tree AABB contains the object AABB and the tree AABB is - // not too large. No tree update needed. - return false; - } - - // Otherwise the tree AABB is huge and needs to be shrunk - } - - RemoveLeaf(proxyId); - - m_nodes[proxyId].aabb = fatAABB; - - InsertLeaf(proxyId); - - m_nodes[proxyId].moved = true; - - return true; -} - -void b2DynamicTree::InsertLeaf(int32 leaf) -{ - ++m_insertionCount; - - if (m_root == b2_nullNode) - { - m_root = leaf; - m_nodes[m_root].parent = b2_nullNode; - return; - } - - // Find the best sibling for this node - b2AABB leafAABB = m_nodes[leaf].aabb; - int32 index = m_root; - while (m_nodes[index].IsLeaf() == false) - { - int32 child1 = m_nodes[index].child1; - int32 child2 = m_nodes[index].child2; - - float area = m_nodes[index].aabb.GetPerimeter(); - - b2AABB combinedAABB; - combinedAABB.Combine(m_nodes[index].aabb, leafAABB); - float combinedArea = combinedAABB.GetPerimeter(); - - // Cost of creating a new parent for this node and the new leaf - float cost = 2.0f * combinedArea; - - // Minimum cost of pushing the leaf further down the tree - float inheritanceCost = 2.0f * (combinedArea - area); - - // Cost of descending into child1 - float cost1; - if (m_nodes[child1].IsLeaf()) - { - b2AABB aabb; - aabb.Combine(leafAABB, m_nodes[child1].aabb); - cost1 = aabb.GetPerimeter() + inheritanceCost; - } - else - { - b2AABB aabb; - aabb.Combine(leafAABB, m_nodes[child1].aabb); - float oldArea = m_nodes[child1].aabb.GetPerimeter(); - float newArea = aabb.GetPerimeter(); - cost1 = (newArea - oldArea) + inheritanceCost; - } - - // Cost of descending into child2 - float cost2; - if (m_nodes[child2].IsLeaf()) - { - b2AABB aabb; - aabb.Combine(leafAABB, m_nodes[child2].aabb); - cost2 = aabb.GetPerimeter() + inheritanceCost; - } - else - { - b2AABB aabb; - aabb.Combine(leafAABB, m_nodes[child2].aabb); - float oldArea = m_nodes[child2].aabb.GetPerimeter(); - float newArea = aabb.GetPerimeter(); - cost2 = newArea - oldArea + inheritanceCost; - } - - // Descend according to the minimum cost. - if (cost < cost1 && cost < cost2) - { - break; - } - - // Descend - if (cost1 < cost2) - { - index = child1; - } - else - { - index = child2; - } - } - - int32 sibling = index; - - // Create a new parent. - int32 oldParent = m_nodes[sibling].parent; - int32 newParent = AllocateNode(); - m_nodes[newParent].parent = oldParent; - m_nodes[newParent].userData = nullptr; - m_nodes[newParent].aabb.Combine(leafAABB, m_nodes[sibling].aabb); - m_nodes[newParent].height = m_nodes[sibling].height + 1; - - if (oldParent != b2_nullNode) - { - // The sibling was not the root. - if (m_nodes[oldParent].child1 == sibling) - { - m_nodes[oldParent].child1 = newParent; - } - else - { - m_nodes[oldParent].child2 = newParent; - } - - m_nodes[newParent].child1 = sibling; - m_nodes[newParent].child2 = leaf; - m_nodes[sibling].parent = newParent; - m_nodes[leaf].parent = newParent; - } - else - { - // The sibling was the root. - m_nodes[newParent].child1 = sibling; - m_nodes[newParent].child2 = leaf; - m_nodes[sibling].parent = newParent; - m_nodes[leaf].parent = newParent; - m_root = newParent; - } - - // Walk back up the tree fixing heights and AABBs - index = m_nodes[leaf].parent; - while (index != b2_nullNode) - { - index = Balance(index); - - int32 child1 = m_nodes[index].child1; - int32 child2 = m_nodes[index].child2; - - b2Assert(child1 != b2_nullNode); - b2Assert(child2 != b2_nullNode); - - m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height); - m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); - - index = m_nodes[index].parent; - } - - //Validate(); -} - -void b2DynamicTree::RemoveLeaf(int32 leaf) -{ - if (leaf == m_root) - { - m_root = b2_nullNode; - return; - } - - int32 parent = m_nodes[leaf].parent; - int32 grandParent = m_nodes[parent].parent; - int32 sibling; - if (m_nodes[parent].child1 == leaf) - { - sibling = m_nodes[parent].child2; - } - else - { - sibling = m_nodes[parent].child1; - } - - if (grandParent != b2_nullNode) - { - // Destroy parent and connect sibling to grandParent. - if (m_nodes[grandParent].child1 == parent) - { - m_nodes[grandParent].child1 = sibling; - } - else - { - m_nodes[grandParent].child2 = sibling; - } - m_nodes[sibling].parent = grandParent; - FreeNode(parent); - - // Adjust ancestor bounds. - int32 index = grandParent; - while (index != b2_nullNode) - { - index = Balance(index); - - int32 child1 = m_nodes[index].child1; - int32 child2 = m_nodes[index].child2; - - m_nodes[index].aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); - m_nodes[index].height = 1 + b2Max(m_nodes[child1].height, m_nodes[child2].height); - - index = m_nodes[index].parent; - } - } - else - { - m_root = sibling; - m_nodes[sibling].parent = b2_nullNode; - FreeNode(parent); - } - - //Validate(); -} - -// Perform a left or right rotation if node A is imbalanced. -// Returns the new root index. -int32 b2DynamicTree::Balance(int32 iA) -{ - b2Assert(iA != b2_nullNode); - - b2TreeNode* A = m_nodes + iA; - if (A->IsLeaf() || A->height < 2) - { - return iA; - } - - int32 iB = A->child1; - int32 iC = A->child2; - b2Assert(0 <= iB && iB < m_nodeCapacity); - b2Assert(0 <= iC && iC < m_nodeCapacity); - - b2TreeNode* B = m_nodes + iB; - b2TreeNode* C = m_nodes + iC; - - int32 balance = C->height - B->height; - - // Rotate C up - if (balance > 1) - { - int32 iF = C->child1; - int32 iG = C->child2; - b2TreeNode* F = m_nodes + iF; - b2TreeNode* G = m_nodes + iG; - b2Assert(0 <= iF && iF < m_nodeCapacity); - b2Assert(0 <= iG && iG < m_nodeCapacity); - - // Swap A and C - C->child1 = iA; - C->parent = A->parent; - A->parent = iC; - - // A's old parent should point to C - if (C->parent != b2_nullNode) - { - if (m_nodes[C->parent].child1 == iA) - { - m_nodes[C->parent].child1 = iC; - } - else - { - b2Assert(m_nodes[C->parent].child2 == iA); - m_nodes[C->parent].child2 = iC; - } - } - else - { - m_root = iC; - } - - // Rotate - if (F->height > G->height) - { - C->child2 = iF; - A->child2 = iG; - G->parent = iA; - A->aabb.Combine(B->aabb, G->aabb); - C->aabb.Combine(A->aabb, F->aabb); - - A->height = 1 + b2Max(B->height, G->height); - C->height = 1 + b2Max(A->height, F->height); - } - else - { - C->child2 = iG; - A->child2 = iF; - F->parent = iA; - A->aabb.Combine(B->aabb, F->aabb); - C->aabb.Combine(A->aabb, G->aabb); - - A->height = 1 + b2Max(B->height, F->height); - C->height = 1 + b2Max(A->height, G->height); - } - - return iC; - } - - // Rotate B up - if (balance < -1) - { - int32 iD = B->child1; - int32 iE = B->child2; - b2TreeNode* D = m_nodes + iD; - b2TreeNode* E = m_nodes + iE; - b2Assert(0 <= iD && iD < m_nodeCapacity); - b2Assert(0 <= iE && iE < m_nodeCapacity); - - // Swap A and B - B->child1 = iA; - B->parent = A->parent; - A->parent = iB; - - // A's old parent should point to B - if (B->parent != b2_nullNode) - { - if (m_nodes[B->parent].child1 == iA) - { - m_nodes[B->parent].child1 = iB; - } - else - { - b2Assert(m_nodes[B->parent].child2 == iA); - m_nodes[B->parent].child2 = iB; - } - } - else - { - m_root = iB; - } - - // Rotate - if (D->height > E->height) - { - B->child2 = iD; - A->child1 = iE; - E->parent = iA; - A->aabb.Combine(C->aabb, E->aabb); - B->aabb.Combine(A->aabb, D->aabb); - - A->height = 1 + b2Max(C->height, E->height); - B->height = 1 + b2Max(A->height, D->height); - } - else - { - B->child2 = iE; - A->child1 = iD; - D->parent = iA; - A->aabb.Combine(C->aabb, D->aabb); - B->aabb.Combine(A->aabb, E->aabb); - - A->height = 1 + b2Max(C->height, D->height); - B->height = 1 + b2Max(A->height, E->height); - } - - return iB; - } - - return iA; -} - -int32 b2DynamicTree::GetHeight() const -{ - if (m_root == b2_nullNode) - { - return 0; - } - - return m_nodes[m_root].height; -} - -// -float b2DynamicTree::GetAreaRatio() const -{ - if (m_root == b2_nullNode) - { - return 0.0f; - } - - const b2TreeNode* root = m_nodes + m_root; - float rootArea = root->aabb.GetPerimeter(); - - float totalArea = 0.0f; - for (int32 i = 0; i < m_nodeCapacity; ++i) - { - const b2TreeNode* node = m_nodes + i; - if (node->height < 0) - { - // Free node in pool - continue; - } - - totalArea += node->aabb.GetPerimeter(); - } - - return totalArea / rootArea; -} - -// Compute the height of a sub-tree. -int32 b2DynamicTree::ComputeHeight(int32 nodeId) const -{ - b2Assert(0 <= nodeId && nodeId < m_nodeCapacity); - b2TreeNode* node = m_nodes + nodeId; - - if (node->IsLeaf()) - { - return 0; - } - - int32 height1 = ComputeHeight(node->child1); - int32 height2 = ComputeHeight(node->child2); - return 1 + b2Max(height1, height2); -} - -int32 b2DynamicTree::ComputeHeight() const -{ - int32 height = ComputeHeight(m_root); - return height; -} - -void b2DynamicTree::ValidateStructure(int32 index) const -{ - if (index == b2_nullNode) - { - return; - } - - if (index == m_root) - { - b2Assert(m_nodes[index].parent == b2_nullNode); - } - - const b2TreeNode* node = m_nodes + index; - - int32 child1 = node->child1; - int32 child2 = node->child2; - - if (node->IsLeaf()) - { - b2Assert(child1 == b2_nullNode); - b2Assert(child2 == b2_nullNode); - b2Assert(node->height == 0); - return; - } - - b2Assert(0 <= child1 && child1 < m_nodeCapacity); - b2Assert(0 <= child2 && child2 < m_nodeCapacity); - - b2Assert(m_nodes[child1].parent == index); - b2Assert(m_nodes[child2].parent == index); - - ValidateStructure(child1); - ValidateStructure(child2); -} - -void b2DynamicTree::ValidateMetrics(int32 index) const -{ - if (index == b2_nullNode) - { - return; - } - - const b2TreeNode* node = m_nodes + index; - - int32 child1 = node->child1; - int32 child2 = node->child2; - - if (node->IsLeaf()) - { - b2Assert(child1 == b2_nullNode); - b2Assert(child2 == b2_nullNode); - b2Assert(node->height == 0); - return; - } - - b2Assert(0 <= child1 && child1 < m_nodeCapacity); - b2Assert(0 <= child2 && child2 < m_nodeCapacity); - - int32 height1 = m_nodes[child1].height; - int32 height2 = m_nodes[child2].height; - int32 height; - height = 1 + b2Max(height1, height2); - b2Assert(node->height == height); - - b2AABB aabb; - aabb.Combine(m_nodes[child1].aabb, m_nodes[child2].aabb); - - b2Assert(aabb.lowerBound == node->aabb.lowerBound); - b2Assert(aabb.upperBound == node->aabb.upperBound); - - ValidateMetrics(child1); - ValidateMetrics(child2); -} - -void b2DynamicTree::Validate() const -{ -#if defined(b2DEBUG) - ValidateStructure(m_root); - ValidateMetrics(m_root); - - int32 freeCount = 0; - int32 freeIndex = m_freeList; - while (freeIndex != b2_nullNode) - { - b2Assert(0 <= freeIndex && freeIndex < m_nodeCapacity); - freeIndex = m_nodes[freeIndex].next; - ++freeCount; - } - - b2Assert(GetHeight() == ComputeHeight()); - - b2Assert(m_nodeCount + freeCount == m_nodeCapacity); -#endif -} - -int32 b2DynamicTree::GetMaxBalance() const -{ - int32 maxBalance = 0; - for (int32 i = 0; i < m_nodeCapacity; ++i) - { - const b2TreeNode* node = m_nodes + i; - if (node->height <= 1) - { - continue; - } - - b2Assert(node->IsLeaf() == false); - - int32 child1 = node->child1; - int32 child2 = node->child2; - int32 balance = b2Abs(m_nodes[child2].height - m_nodes[child1].height); - maxBalance = b2Max(maxBalance, balance); - } - - return maxBalance; -} - -void b2DynamicTree::RebuildBottomUp() -{ - int32* nodes = (int32*)b2Alloc(m_nodeCount * sizeof(int32)); - int32 count = 0; - - // Build array of leaves. Free the rest. - for (int32 i = 0; i < m_nodeCapacity; ++i) - { - if (m_nodes[i].height < 0) - { - // free node in pool - continue; - } - - if (m_nodes[i].IsLeaf()) - { - m_nodes[i].parent = b2_nullNode; - nodes[count] = i; - ++count; - } - else - { - FreeNode(i); - } - } - - while (count > 1) - { - float minCost = b2_maxFloat; - int32 iMin = -1, jMin = -1; - for (int32 i = 0; i < count; ++i) - { - b2AABB aabbi = m_nodes[nodes[i]].aabb; - - for (int32 j = i + 1; j < count; ++j) - { - b2AABB aabbj = m_nodes[nodes[j]].aabb; - b2AABB b; - b.Combine(aabbi, aabbj); - float cost = b.GetPerimeter(); - if (cost < minCost) - { - iMin = i; - jMin = j; - minCost = cost; - } - } - } - - int32 index1 = nodes[iMin]; - int32 index2 = nodes[jMin]; - b2TreeNode* child1 = m_nodes + index1; - b2TreeNode* child2 = m_nodes + index2; - - int32 parentIndex = AllocateNode(); - b2TreeNode* parent = m_nodes + parentIndex; - parent->child1 = index1; - parent->child2 = index2; - parent->height = 1 + b2Max(child1->height, child2->height); - parent->aabb.Combine(child1->aabb, child2->aabb); - parent->parent = b2_nullNode; - - child1->parent = parentIndex; - child2->parent = parentIndex; - - nodes[jMin] = nodes[count-1]; - nodes[iMin] = parentIndex; - --count; - } - - m_root = nodes[0]; - b2Free(nodes); - - Validate(); -} - -void b2DynamicTree::ShiftOrigin(const b2Vec2& newOrigin) -{ - // Build array of leaves. Free the rest. - for (int32 i = 0; i < m_nodeCapacity; ++i) - { - m_nodes[i].aabb.lowerBound -= newOrigin; - m_nodes[i].aabb.upperBound -= newOrigin; - } -} diff --git a/3rdparty/box2d/src/collision/b2_edge_shape.cpp b/3rdparty/box2d/src/collision/b2_edge_shape.cpp deleted file mode 100644 index 65f0606a6483..000000000000 --- a/3rdparty/box2d/src/collision/b2_edge_shape.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_edge_shape.h" -#include "box2d/b2_block_allocator.h" -#include - -void b2EdgeShape::SetOneSided(const b2Vec2& v0, const b2Vec2& v1, const b2Vec2& v2, const b2Vec2& v3) -{ - m_vertex0 = v0; - m_vertex1 = v1; - m_vertex2 = v2; - m_vertex3 = v3; - m_oneSided = true; -} - -void b2EdgeShape::SetTwoSided(const b2Vec2& v1, const b2Vec2& v2) -{ - m_vertex1 = v1; - m_vertex2 = v2; - m_oneSided = false; -} - -b2Shape* b2EdgeShape::Clone(b2BlockAllocator* allocator) const -{ - void* mem = allocator->Allocate(sizeof(b2EdgeShape)); - b2EdgeShape* clone = new (mem) b2EdgeShape; - *clone = *this; - return clone; -} - -int32 b2EdgeShape::GetChildCount() const -{ - return 1; -} - -bool b2EdgeShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const -{ - B2_NOT_USED(xf); - B2_NOT_USED(p); - return false; -} - -// p = p1 + t * d -// v = v1 + s * e -// p1 + t * d = v1 + s * e -// s * e - t * d = p1 - v1 -bool b2EdgeShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& xf, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - // Put the ray into the edge's frame of reference. - b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p); - b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p); - b2Vec2 d = p2 - p1; - - b2Vec2 v1 = m_vertex1; - b2Vec2 v2 = m_vertex2; - b2Vec2 e = v2 - v1; - - // Normal points to the right, looking from v1 at v2 - b2Vec2 normal(e.y, -e.x); - normal.Normalize(); - - // q = p1 + t * d - // dot(normal, q - v1) = 0 - // dot(normal, p1 - v1) + t * dot(normal, d) = 0 - float numerator = b2Dot(normal, v1 - p1); - if (m_oneSided && numerator > 0.0f) - { - return false; - } - - float denominator = b2Dot(normal, d); - - if (denominator == 0.0f) - { - return false; - } - - float t = numerator / denominator; - if (t < 0.0f || input.maxFraction < t) - { - return false; - } - - b2Vec2 q = p1 + t * d; - - // q = v1 + s * r - // s = dot(q - v1, r) / dot(r, r) - b2Vec2 r = v2 - v1; - float rr = b2Dot(r, r); - if (rr == 0.0f) - { - return false; - } - - float s = b2Dot(q - v1, r) / rr; - if (s < 0.0f || 1.0f < s) - { - return false; - } - - output->fraction = t; - if (numerator > 0.0f) - { - output->normal = -b2Mul(xf.q, normal); - } - else - { - output->normal = b2Mul(xf.q, normal); - } - return true; -} - -void b2EdgeShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - b2Vec2 v1 = b2Mul(xf, m_vertex1); - b2Vec2 v2 = b2Mul(xf, m_vertex2); - - b2Vec2 lower = b2Min(v1, v2); - b2Vec2 upper = b2Max(v1, v2); - - b2Vec2 r(m_radius, m_radius); - aabb->lowerBound = lower - r; - aabb->upperBound = upper + r; -} - -void b2EdgeShape::ComputeMass(b2MassData* massData, float density) const -{ - B2_NOT_USED(density); - - massData->mass = 0.0f; - massData->center = 0.5f * (m_vertex1 + m_vertex2); - massData->I = 0.0f; -} diff --git a/3rdparty/box2d/src/collision/b2_polygon_shape.cpp b/3rdparty/box2d/src/collision/b2_polygon_shape.cpp deleted file mode 100644 index 165919b46fa7..000000000000 --- a/3rdparty/box2d/src/collision/b2_polygon_shape.cpp +++ /dev/null @@ -1,366 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_polygon_shape.h" -#include "box2d/b2_block_allocator.h" - -#include - -b2PolygonShape::b2PolygonShape() -{ - m_type = e_polygon; - m_radius = b2_polygonRadius; - m_count = 0; - m_centroid.SetZero(); -} - -b2Shape* b2PolygonShape::Clone(b2BlockAllocator* allocator) const -{ - void* mem = allocator->Allocate(sizeof(b2PolygonShape)); - b2PolygonShape* clone = new (mem) b2PolygonShape; - *clone = *this; - return clone; -} - -void b2PolygonShape::SetAsBox(float hx, float hy) -{ - m_count = 4; - m_vertices[0].Set(-hx, -hy); - m_vertices[1].Set( hx, -hy); - m_vertices[2].Set( hx, hy); - m_vertices[3].Set(-hx, hy); - m_normals[0].Set(0.0f, -1.0f); - m_normals[1].Set(1.0f, 0.0f); - m_normals[2].Set(0.0f, 1.0f); - m_normals[3].Set(-1.0f, 0.0f); - m_centroid.SetZero(); -} - -void b2PolygonShape::SetAsBox(float hx, float hy, const b2Vec2& center, float angle) -{ - m_count = 4; - m_vertices[0].Set(-hx, -hy); - m_vertices[1].Set( hx, -hy); - m_vertices[2].Set( hx, hy); - m_vertices[3].Set(-hx, hy); - m_normals[0].Set(0.0f, -1.0f); - m_normals[1].Set(1.0f, 0.0f); - m_normals[2].Set(0.0f, 1.0f); - m_normals[3].Set(-1.0f, 0.0f); - m_centroid = center; - - b2Transform xf; - xf.p = center; - xf.q.Set(angle); - - // Transform vertices and normals. - for (int32 i = 0; i < m_count; ++i) - { - m_vertices[i] = b2Mul(xf, m_vertices[i]); - m_normals[i] = b2Mul(xf.q, m_normals[i]); - } -} - -int32 b2PolygonShape::GetChildCount() const -{ - return 1; -} - -static b2Vec2 ComputeCentroid(const b2Vec2* vs, int32 count) -{ - b2Assert(count >= 3); - - b2Vec2 c(0.0f, 0.0f); - float area = 0.0f; - - // Get a reference point for forming triangles. - // Use the first vertex to reduce round-off errors. - b2Vec2 s = vs[0]; - - const float inv3 = 1.0f / 3.0f; - - for (int32 i = 0; i < count; ++i) - { - // Triangle vertices. - b2Vec2 p1 = vs[0] - s; - b2Vec2 p2 = vs[i] - s; - b2Vec2 p3 = i + 1 < count ? vs[i+1] - s : vs[0] - s; - - b2Vec2 e1 = p2 - p1; - b2Vec2 e2 = p3 - p1; - - float D = b2Cross(e1, e2); - - float triangleArea = 0.5f * D; - area += triangleArea; - - // Area weighted centroid - c += triangleArea * inv3 * (p1 + p2 + p3); - } - - // Centroid - b2Assert(area > b2_epsilon); - c = (1.0f / area) * c + s; - return c; -} - -bool b2PolygonShape::Set(const b2Vec2* vertices, int32 count) -{ - b2Hull hull = b2ComputeHull(vertices, count); - - if (hull.count < 3) - { - return false; - } - - Set(hull); - - return true; -} - -void b2PolygonShape::Set(const b2Hull& hull) -{ - b2Assert(hull.count >= 3); - - m_count = hull.count; - - // Copy vertices - for (int32 i = 0; i < hull.count; ++i) - { - m_vertices[i] = hull.points[i]; - } - - // Compute normals. Ensure the edges have non-zero length. - for (int32 i = 0; i < m_count; ++i) - { - int32 i1 = i; - int32 i2 = i + 1 < m_count ? i + 1 : 0; - b2Vec2 edge = m_vertices[i2] - m_vertices[i1]; - b2Assert(edge.LengthSquared() > b2_epsilon * b2_epsilon); - m_normals[i] = b2Cross(edge, 1.0f); - m_normals[i].Normalize(); - } - - // Compute the polygon centroid. - m_centroid = ComputeCentroid(m_vertices, m_count); -} - -bool b2PolygonShape::TestPoint(const b2Transform& xf, const b2Vec2& p) const -{ - b2Vec2 pLocal = b2MulT(xf.q, p - xf.p); - - for (int32 i = 0; i < m_count; ++i) - { - float dot = b2Dot(m_normals[i], pLocal - m_vertices[i]); - if (dot > 0.0f) - { - return false; - } - } - - return true; -} - -bool b2PolygonShape::RayCast(b2RayCastOutput* output, const b2RayCastInput& input, - const b2Transform& xf, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - // Put the ray into the polygon's frame of reference. - b2Vec2 p1 = b2MulT(xf.q, input.p1 - xf.p); - b2Vec2 p2 = b2MulT(xf.q, input.p2 - xf.p); - b2Vec2 d = p2 - p1; - - float lower = 0.0f, upper = input.maxFraction; - - int32 index = -1; - - for (int32 i = 0; i < m_count; ++i) - { - // p = p1 + a * d - // dot(normal, p - v) = 0 - // dot(normal, p1 - v) + a * dot(normal, d) = 0 - float numerator = b2Dot(m_normals[i], m_vertices[i] - p1); - float denominator = b2Dot(m_normals[i], d); - - if (denominator == 0.0f) - { - if (numerator < 0.0f) - { - return false; - } - } - else - { - // Note: we want this predicate without division: - // lower < numerator / denominator, where denominator < 0 - // Since denominator < 0, we have to flip the inequality: - // lower < numerator / denominator <==> denominator * lower > numerator. - if (denominator < 0.0f && numerator < lower * denominator) - { - // Increase lower. - // The segment enters this half-space. - lower = numerator / denominator; - index = i; - } - else if (denominator > 0.0f && numerator < upper * denominator) - { - // Decrease upper. - // The segment exits this half-space. - upper = numerator / denominator; - } - } - - // The use of epsilon here causes the assert on lower to trip - // in some cases. Apparently the use of epsilon was to make edge - // shapes work, but now those are handled separately. - //if (upper < lower - b2_epsilon) - if (upper < lower) - { - return false; - } - } - - b2Assert(0.0f <= lower && lower <= input.maxFraction); - - if (index >= 0) - { - output->fraction = lower; - output->normal = b2Mul(xf.q, m_normals[index]); - return true; - } - - return false; -} - -void b2PolygonShape::ComputeAABB(b2AABB* aabb, const b2Transform& xf, int32 childIndex) const -{ - B2_NOT_USED(childIndex); - - b2Vec2 lower = b2Mul(xf, m_vertices[0]); - b2Vec2 upper = lower; - - for (int32 i = 1; i < m_count; ++i) - { - b2Vec2 v = b2Mul(xf, m_vertices[i]); - lower = b2Min(lower, v); - upper = b2Max(upper, v); - } - - b2Vec2 r(m_radius, m_radius); - aabb->lowerBound = lower - r; - aabb->upperBound = upper + r; -} - -void b2PolygonShape::ComputeMass(b2MassData* massData, float density) const -{ - // Polygon mass, centroid, and inertia. - // Let rho be the polygon density in mass per unit area. - // Then: - // mass = rho * int(dA) - // centroid.x = (1/mass) * rho * int(x * dA) - // centroid.y = (1/mass) * rho * int(y * dA) - // I = rho * int((x*x + y*y) * dA) - // - // We can compute these integrals by summing all the integrals - // for each triangle of the polygon. To evaluate the integral - // for a single triangle, we make a change of variables to - // the (u,v) coordinates of the triangle: - // x = x0 + e1x * u + e2x * v - // y = y0 + e1y * u + e2y * v - // where 0 <= u && 0 <= v && u + v <= 1. - // - // We integrate u from [0,1-v] and then v from [0,1]. - // We also need to use the Jacobian of the transformation: - // D = cross(e1, e2) - // - // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3) - // - // The rest of the derivation is handled by computer algebra. - - b2Assert(m_count >= 3); - - b2Vec2 center(0.0f, 0.0f); - float area = 0.0f; - float I = 0.0f; - - // Get a reference point for forming triangles. - // Use the first vertex to reduce round-off errors. - b2Vec2 s = m_vertices[0]; - - const float k_inv3 = 1.0f / 3.0f; - - for (int32 i = 0; i < m_count; ++i) - { - // Triangle vertices. - b2Vec2 e1 = m_vertices[i] - s; - b2Vec2 e2 = i + 1 < m_count ? m_vertices[i+1] - s : m_vertices[0] - s; - - float D = b2Cross(e1, e2); - - float triangleArea = 0.5f * D; - area += triangleArea; - - // Area weighted centroid - center += triangleArea * k_inv3 * (e1 + e2); - - float ex1 = e1.x, ey1 = e1.y; - float ex2 = e2.x, ey2 = e2.y; - - float intx2 = ex1*ex1 + ex2*ex1 + ex2*ex2; - float inty2 = ey1*ey1 + ey2*ey1 + ey2*ey2; - - I += (0.25f * k_inv3 * D) * (intx2 + inty2); - } - - // Total mass - massData->mass = density * area; - - // Center of mass - b2Assert(area > b2_epsilon); - center *= 1.0f / area; - massData->center = center + s; - - // Inertia tensor relative to the local origin (point s). - massData->I = density * I; - - // Shift to center of mass then to original body origin. - massData->I += massData->mass * (b2Dot(massData->center, massData->center) - b2Dot(center, center)); -} - -bool b2PolygonShape::Validate() const -{ - if (m_count < 3 || b2_maxPolygonVertices < m_count) - { - return false; - } - - b2Hull hull; - for (int32 i = 0; i < m_count; ++i) - { - hull.points[i] = m_vertices[i]; - } - - hull.count = m_count; - - return b2ValidateHull(hull); -} diff --git a/3rdparty/box2d/src/collision/b2_time_of_impact.cpp b/3rdparty/box2d/src/collision/b2_time_of_impact.cpp deleted file mode 100644 index 7a1011b7e7cc..000000000000 --- a/3rdparty/box2d/src/collision/b2_time_of_impact.cpp +++ /dev/null @@ -1,490 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_collision.h" -#include "box2d/b2_distance.h" -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_polygon_shape.h" -#include "box2d/b2_time_of_impact.h" -#include "box2d/b2_timer.h" - -#include - -B2_API float b2_toiTime, b2_toiMaxTime; -B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; -B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - -// -struct b2SeparationFunction -{ - enum Type - { - e_points, - e_faceA, - e_faceB - }; - - // TODO_ERIN might not need to return the separation - - float Initialize(const b2SimplexCache* cache, - const b2DistanceProxy* proxyA, const b2Sweep& sweepA, - const b2DistanceProxy* proxyB, const b2Sweep& sweepB, - float t1) - { - m_proxyA = proxyA; - m_proxyB = proxyB; - int32 count = cache->count; - b2Assert(0 < count && count < 3); - - m_sweepA = sweepA; - m_sweepB = sweepB; - - b2Transform xfA, xfB; - m_sweepA.GetTransform(&xfA, t1); - m_sweepB.GetTransform(&xfB, t1); - - if (count == 1) - { - m_type = e_points; - b2Vec2 localPointA = m_proxyA->GetVertex(cache->indexA[0]); - b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]); - b2Vec2 pointA = b2Mul(xfA, localPointA); - b2Vec2 pointB = b2Mul(xfB, localPointB); - m_axis = pointB - pointA; - float s = m_axis.Normalize(); - return s; - } - else if (cache->indexA[0] == cache->indexA[1]) - { - // Two points on B and one on A. - m_type = e_faceB; - b2Vec2 localPointB1 = proxyB->GetVertex(cache->indexB[0]); - b2Vec2 localPointB2 = proxyB->GetVertex(cache->indexB[1]); - - m_axis = b2Cross(localPointB2 - localPointB1, 1.0f); - m_axis.Normalize(); - b2Vec2 normal = b2Mul(xfB.q, m_axis); - - m_localPoint = 0.5f * (localPointB1 + localPointB2); - b2Vec2 pointB = b2Mul(xfB, m_localPoint); - - b2Vec2 localPointA = proxyA->GetVertex(cache->indexA[0]); - b2Vec2 pointA = b2Mul(xfA, localPointA); - - float s = b2Dot(pointA - pointB, normal); - if (s < 0.0f) - { - m_axis = -m_axis; - s = -s; - } - return s; - } - else - { - // Two points on A and one or two points on B. - m_type = e_faceA; - b2Vec2 localPointA1 = m_proxyA->GetVertex(cache->indexA[0]); - b2Vec2 localPointA2 = m_proxyA->GetVertex(cache->indexA[1]); - - m_axis = b2Cross(localPointA2 - localPointA1, 1.0f); - m_axis.Normalize(); - b2Vec2 normal = b2Mul(xfA.q, m_axis); - - m_localPoint = 0.5f * (localPointA1 + localPointA2); - b2Vec2 pointA = b2Mul(xfA, m_localPoint); - - b2Vec2 localPointB = m_proxyB->GetVertex(cache->indexB[0]); - b2Vec2 pointB = b2Mul(xfB, localPointB); - - float s = b2Dot(pointB - pointA, normal); - if (s < 0.0f) - { - m_axis = -m_axis; - s = -s; - } - return s; - } - } - - // - float FindMinSeparation(int32* indexA, int32* indexB, float t) const - { - b2Transform xfA, xfB; - m_sweepA.GetTransform(&xfA, t); - m_sweepB.GetTransform(&xfB, t); - - switch (m_type) - { - case e_points: - { - b2Vec2 axisA = b2MulT(xfA.q, m_axis); - b2Vec2 axisB = b2MulT(xfB.q, -m_axis); - - *indexA = m_proxyA->GetSupport(axisA); - *indexB = m_proxyB->GetSupport(axisB); - - b2Vec2 localPointA = m_proxyA->GetVertex(*indexA); - b2Vec2 localPointB = m_proxyB->GetVertex(*indexB); - - b2Vec2 pointA = b2Mul(xfA, localPointA); - b2Vec2 pointB = b2Mul(xfB, localPointB); - - float separation = b2Dot(pointB - pointA, m_axis); - return separation; - } - - case e_faceA: - { - b2Vec2 normal = b2Mul(xfA.q, m_axis); - b2Vec2 pointA = b2Mul(xfA, m_localPoint); - - b2Vec2 axisB = b2MulT(xfB.q, -normal); - - *indexA = -1; - *indexB = m_proxyB->GetSupport(axisB); - - b2Vec2 localPointB = m_proxyB->GetVertex(*indexB); - b2Vec2 pointB = b2Mul(xfB, localPointB); - - float separation = b2Dot(pointB - pointA, normal); - return separation; - } - - case e_faceB: - { - b2Vec2 normal = b2Mul(xfB.q, m_axis); - b2Vec2 pointB = b2Mul(xfB, m_localPoint); - - b2Vec2 axisA = b2MulT(xfA.q, -normal); - - *indexB = -1; - *indexA = m_proxyA->GetSupport(axisA); - - b2Vec2 localPointA = m_proxyA->GetVertex(*indexA); - b2Vec2 pointA = b2Mul(xfA, localPointA); - - float separation = b2Dot(pointA - pointB, normal); - return separation; - } - - default: - b2Assert(false); - *indexA = -1; - *indexB = -1; - return 0.0f; - } - } - - // - float Evaluate(int32 indexA, int32 indexB, float t) const - { - b2Transform xfA, xfB; - m_sweepA.GetTransform(&xfA, t); - m_sweepB.GetTransform(&xfB, t); - - switch (m_type) - { - case e_points: - { - b2Vec2 localPointA = m_proxyA->GetVertex(indexA); - b2Vec2 localPointB = m_proxyB->GetVertex(indexB); - - b2Vec2 pointA = b2Mul(xfA, localPointA); - b2Vec2 pointB = b2Mul(xfB, localPointB); - float separation = b2Dot(pointB - pointA, m_axis); - - return separation; - } - - case e_faceA: - { - b2Vec2 normal = b2Mul(xfA.q, m_axis); - b2Vec2 pointA = b2Mul(xfA, m_localPoint); - - b2Vec2 localPointB = m_proxyB->GetVertex(indexB); - b2Vec2 pointB = b2Mul(xfB, localPointB); - - float separation = b2Dot(pointB - pointA, normal); - return separation; - } - - case e_faceB: - { - b2Vec2 normal = b2Mul(xfB.q, m_axis); - b2Vec2 pointB = b2Mul(xfB, m_localPoint); - - b2Vec2 localPointA = m_proxyA->GetVertex(indexA); - b2Vec2 pointA = b2Mul(xfA, localPointA); - - float separation = b2Dot(pointA - pointB, normal); - return separation; - } - - default: - b2Assert(false); - return 0.0f; - } - } - - const b2DistanceProxy* m_proxyA; - const b2DistanceProxy* m_proxyB; - b2Sweep m_sweepA, m_sweepB; - Type m_type; - b2Vec2 m_localPoint; - b2Vec2 m_axis; -}; - -// CCD via the local separating axis method. This seeks progression -// by computing the largest time at which separation is maintained. -void b2TimeOfImpact(b2TOIOutput* output, const b2TOIInput* input) -{ - b2Timer timer; - - ++b2_toiCalls; - - output->state = b2TOIOutput::e_unknown; - output->t = input->tMax; - - const b2DistanceProxy* proxyA = &input->proxyA; - const b2DistanceProxy* proxyB = &input->proxyB; - - b2Sweep sweepA = input->sweepA; - b2Sweep sweepB = input->sweepB; - - // Large rotations can make the root finder fail, so we normalize the - // sweep angles. - sweepA.Normalize(); - sweepB.Normalize(); - - float tMax = input->tMax; - - float totalRadius = proxyA->m_radius + proxyB->m_radius; - float target = b2Max(b2_linearSlop, totalRadius - 3.0f * b2_linearSlop); - float tolerance = 0.25f * b2_linearSlop; - b2Assert(target > tolerance); - - float t1 = 0.0f; - const int32 k_maxIterations = 20; // TODO_ERIN b2Settings - int32 iter = 0; - - // Prepare input for distance query. - b2SimplexCache cache; - cache.count = 0; - b2DistanceInput distanceInput; - distanceInput.proxyA = input->proxyA; - distanceInput.proxyB = input->proxyB; - distanceInput.useRadii = false; - - // The outer loop progressively attempts to compute new separating axes. - // This loop terminates when an axis is repeated (no progress is made). - for(;;) - { - b2Transform xfA, xfB; - sweepA.GetTransform(&xfA, t1); - sweepB.GetTransform(&xfB, t1); - - // Get the distance between shapes. We can also use the results - // to get a separating axis. - distanceInput.transformA = xfA; - distanceInput.transformB = xfB; - b2DistanceOutput distanceOutput; - b2Distance(&distanceOutput, &cache, &distanceInput); - - // If the shapes are overlapped, we give up on continuous collision. - if (distanceOutput.distance <= 0.0f) - { - // Failure! - output->state = b2TOIOutput::e_overlapped; - output->t = 0.0f; - break; - } - - if (distanceOutput.distance < target + tolerance) - { - // Victory! - output->state = b2TOIOutput::e_touching; - output->t = t1; - break; - } - - // Initialize the separating axis. - b2SeparationFunction fcn; - fcn.Initialize(&cache, proxyA, sweepA, proxyB, sweepB, t1); -#if 0 - // Dump the curve seen by the root finder - { - const int32 N = 100; - float dx = 1.0f / N; - float xs[N+1]; - float fs[N+1]; - - float x = 0.0f; - - for (int32 i = 0; i <= N; ++i) - { - sweepA.GetTransform(&xfA, x); - sweepB.GetTransform(&xfB, x); - float f = fcn.Evaluate(xfA, xfB) - target; - - printf("%g %g\n", x, f); - - xs[i] = x; - fs[i] = f; - - x += dx; - } - } -#endif - - // Compute the TOI on the separating axis. We do this by successively - // resolving the deepest point. This loop is bounded by the number of vertices. - bool done = false; - float t2 = tMax; - int32 pushBackIter = 0; - for (;;) - { - // Find the deepest point at t2. Store the witness point indices. - int32 indexA, indexB; - float s2 = fcn.FindMinSeparation(&indexA, &indexB, t2); - - // Is the final configuration separated? - if (s2 > target + tolerance) - { - // Victory! - output->state = b2TOIOutput::e_separated; - output->t = tMax; - done = true; - break; - } - - // Has the separation reached tolerance? - if (s2 > target - tolerance) - { - // Advance the sweeps - t1 = t2; - break; - } - - // Compute the initial separation of the witness points. - float s1 = fcn.Evaluate(indexA, indexB, t1); - - // Check for initial overlap. This might happen if the root finder - // runs out of iterations. - if (s1 < target - tolerance) - { - output->state = b2TOIOutput::e_failed; - output->t = t1; - done = true; - break; - } - - // Check for touching - if (s1 <= target + tolerance) - { - // Victory! t1 should hold the TOI (could be 0.0). - output->state = b2TOIOutput::e_touching; - output->t = t1; - done = true; - break; - } - - // Compute 1D root of: f(x) - target = 0 - int32 rootIterCount = 0; - float a1 = t1, a2 = t2; - for (;;) - { - // Use a mix of the secant rule and bisection. - float t; - if (rootIterCount & 1) - { - // Secant rule to improve convergence. - t = a1 + (target - s1) * (a2 - a1) / (s2 - s1); - } - else - { - // Bisection to guarantee progress. - t = 0.5f * (a1 + a2); - } - - ++rootIterCount; - ++b2_toiRootIters; - - float s = fcn.Evaluate(indexA, indexB, t); - - if (b2Abs(s - target) < tolerance) - { - // t2 holds a tentative value for t1 - t2 = t; - break; - } - - // Ensure we continue to bracket the root. - if (s > target) - { - a1 = t; - s1 = s; - } - else - { - a2 = t; - s2 = s; - } - - if (rootIterCount == 50) - { - break; - } - } - - b2_toiMaxRootIters = b2Max(b2_toiMaxRootIters, rootIterCount); - - ++pushBackIter; - - if (pushBackIter == b2_maxPolygonVertices) - { - break; - } - } - - ++iter; - ++b2_toiIters; - - if (done) - { - break; - } - - if (iter == k_maxIterations) - { - // Root finder got stuck. Semi-victory. - output->state = b2TOIOutput::e_failed; - output->t = t1; - break; - } - } - - b2_toiMaxIters = b2Max(b2_toiMaxIters, iter); - - float time = timer.GetMilliseconds(); - b2_toiMaxTime = b2Max(b2_toiMaxTime, time); - b2_toiTime += time; -} diff --git a/3rdparty/box2d/src/common/b2_block_allocator.cpp b/3rdparty/box2d/src/common/b2_block_allocator.cpp deleted file mode 100644 index 595f2ad393a1..000000000000 --- a/3rdparty/box2d/src/common/b2_block_allocator.cpp +++ /dev/null @@ -1,230 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_block_allocator.h" -#include -#include -#include - -static const int32 b2_chunkSize = 16 * 1024; -static const int32 b2_maxBlockSize = 640; -static const int32 b2_chunkArrayIncrement = 128; - -// These are the supported object sizes. Actual allocations are rounded up the next size. -static const int32 b2_blockSizes[b2_blockSizeCount] = -{ - 16, // 0 - 32, // 1 - 64, // 2 - 96, // 3 - 128, // 4 - 160, // 5 - 192, // 6 - 224, // 7 - 256, // 8 - 320, // 9 - 384, // 10 - 448, // 11 - 512, // 12 - 640, // 13 -}; - -// This maps an arbitrary allocation size to a suitable slot in b2_blockSizes. -struct b2SizeMap -{ - b2SizeMap() - { - int32 j = 0; - values[0] = 0; - for (int32 i = 1; i <= b2_maxBlockSize; ++i) - { - b2Assert(j < b2_blockSizeCount); - if (i <= b2_blockSizes[j]) - { - values[i] = (uint8)j; - } - else - { - ++j; - values[i] = (uint8)j; - } - } - } - - uint8 values[b2_maxBlockSize + 1]; -}; - -static const b2SizeMap b2_sizeMap; - -struct b2Chunk -{ - int32 blockSize; - b2Block* blocks; -}; - -struct b2Block -{ - b2Block* next; -}; - -b2BlockAllocator::b2BlockAllocator() -{ - b2Assert(b2_blockSizeCount < UCHAR_MAX); - - m_chunkSpace = b2_chunkArrayIncrement; - m_chunkCount = 0; - m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk)); - - memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk)); - memset(m_freeLists, 0, sizeof(m_freeLists)); -} - -b2BlockAllocator::~b2BlockAllocator() -{ - for (int32 i = 0; i < m_chunkCount; ++i) - { - b2Free(m_chunks[i].blocks); - } - - b2Free(m_chunks); -} - -void* b2BlockAllocator::Allocate(int32 size) -{ - if (size == 0) - { - return nullptr; - } - - b2Assert(0 < size); - - if (size > b2_maxBlockSize) - { - return b2Alloc(size); - } - - int32 index = b2_sizeMap.values[size]; - b2Assert(0 <= index && index < b2_blockSizeCount); - - if (m_freeLists[index]) - { - b2Block* block = m_freeLists[index]; - m_freeLists[index] = block->next; - return block; - } - else - { - if (m_chunkCount == m_chunkSpace) - { - b2Chunk* oldChunks = m_chunks; - m_chunkSpace += b2_chunkArrayIncrement; - m_chunks = (b2Chunk*)b2Alloc(m_chunkSpace * sizeof(b2Chunk)); - memcpy(m_chunks, oldChunks, m_chunkCount * sizeof(b2Chunk)); - memset(m_chunks + m_chunkCount, 0, b2_chunkArrayIncrement * sizeof(b2Chunk)); - b2Free(oldChunks); - } - - b2Chunk* chunk = m_chunks + m_chunkCount; - chunk->blocks = (b2Block*)b2Alloc(b2_chunkSize); -#if defined(_DEBUG) - memset(chunk->blocks, 0xcd, b2_chunkSize); -#endif - int32 blockSize = b2_blockSizes[index]; - chunk->blockSize = blockSize; - int32 blockCount = b2_chunkSize / blockSize; - b2Assert(blockCount * blockSize <= b2_chunkSize); - for (int32 i = 0; i < blockCount - 1; ++i) - { - b2Block* block = (b2Block*)((int8*)chunk->blocks + blockSize * i); - b2Block* next = (b2Block*)((int8*)chunk->blocks + blockSize * (i + 1)); - block->next = next; - } - b2Block* last = (b2Block*)((int8*)chunk->blocks + blockSize * (blockCount - 1)); - last->next = nullptr; - - m_freeLists[index] = chunk->blocks->next; - ++m_chunkCount; - - return chunk->blocks; - } -} - -void b2BlockAllocator::Free(void* p, int32 size) -{ - if (size == 0) - { - return; - } - - b2Assert(0 < size); - - if (size > b2_maxBlockSize) - { - b2Free(p); - return; - } - - int32 index = b2_sizeMap.values[size]; - b2Assert(0 <= index && index < b2_blockSizeCount); - -#if defined(_DEBUG) - // Verify the memory address and size is valid. - int32 blockSize = b2_blockSizes[index]; - bool found = false; - for (int32 i = 0; i < m_chunkCount; ++i) - { - b2Chunk* chunk = m_chunks + i; - if (chunk->blockSize != blockSize) - { - b2Assert( (int8*)p + blockSize <= (int8*)chunk->blocks || - (int8*)chunk->blocks + b2_chunkSize <= (int8*)p); - } - else - { - if ((int8*)chunk->blocks <= (int8*)p && (int8*)p + blockSize <= (int8*)chunk->blocks + b2_chunkSize) - { - found = true; - } - } - } - - b2Assert(found); - - memset(p, 0xfd, blockSize); -#endif - - b2Block* block = (b2Block*)p; - block->next = m_freeLists[index]; - m_freeLists[index] = block; -} - -void b2BlockAllocator::Clear() -{ - for (int32 i = 0; i < m_chunkCount; ++i) - { - b2Free(m_chunks[i].blocks); - } - - m_chunkCount = 0; - memset(m_chunks, 0, m_chunkSpace * sizeof(b2Chunk)); - memset(m_freeLists, 0, sizeof(m_freeLists)); -} diff --git a/3rdparty/box2d/src/common/b2_draw.cpp b/3rdparty/box2d/src/common/b2_draw.cpp deleted file mode 100644 index 1ec11e54aca3..000000000000 --- a/3rdparty/box2d/src/common/b2_draw.cpp +++ /dev/null @@ -1,47 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. -#include "box2d/b2_draw.h" - -b2Draw::b2Draw() -{ - m_drawFlags = 0; -} - -void b2Draw::SetFlags(uint32 flags) -{ - m_drawFlags = flags; -} - -uint32 b2Draw::GetFlags() const -{ - return m_drawFlags; -} - -void b2Draw::AppendFlags(uint32 flags) -{ - m_drawFlags |= flags; -} - -void b2Draw::ClearFlags(uint32 flags) -{ - m_drawFlags &= ~flags; -} diff --git a/3rdparty/box2d/src/common/b2_math.cpp b/3rdparty/box2d/src/common/b2_math.cpp deleted file mode 100644 index a14460cd501e..000000000000 --- a/3rdparty/box2d/src/common/b2_math.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_math.h" - -const b2Vec2 b2Vec2_zero(0.0f, 0.0f); - -/// Solve A * x = b, where b is a column vector. This is more efficient -/// than computing the inverse in one-shot cases. -b2Vec3 b2Mat33::Solve33(const b2Vec3& b) const -{ - float det = b2Dot(ex, b2Cross(ey, ez)); - if (det != 0.0f) - { - det = 1.0f / det; - } - b2Vec3 x; - x.x = det * b2Dot(b, b2Cross(ey, ez)); - x.y = det * b2Dot(ex, b2Cross(b, ez)); - x.z = det * b2Dot(ex, b2Cross(ey, b)); - return x; -} - -/// Solve A * x = b, where b is a column vector. This is more efficient -/// than computing the inverse in one-shot cases. -b2Vec2 b2Mat33::Solve22(const b2Vec2& b) const -{ - float a11 = ex.x, a12 = ey.x, a21 = ex.y, a22 = ey.y; - float det = a11 * a22 - a12 * a21; - if (det != 0.0f) - { - det = 1.0f / det; - } - b2Vec2 x; - x.x = det * (a22 * b.x - a12 * b.y); - x.y = det * (a11 * b.y - a21 * b.x); - return x; -} - -/// -void b2Mat33::GetInverse22(b2Mat33* M) const -{ - float a = ex.x, b = ey.x, c = ex.y, d = ey.y; - float det = a * d - b * c; - if (det != 0.0f) - { - det = 1.0f / det; - } - - M->ex.x = det * d; M->ey.x = -det * b; M->ex.z = 0.0f; - M->ex.y = -det * c; M->ey.y = det * a; M->ey.z = 0.0f; - M->ez.x = 0.0f; M->ez.y = 0.0f; M->ez.z = 0.0f; -} - -/// Returns the zero matrix if singular. -void b2Mat33::GetSymInverse33(b2Mat33* M) const -{ - float det = b2Dot(ex, b2Cross(ey, ez)); - if (det != 0.0f) - { - det = 1.0f / det; - } - - float a11 = ex.x, a12 = ey.x, a13 = ez.x; - float a22 = ey.y, a23 = ez.y; - float a33 = ez.z; - - M->ex.x = det * (a22 * a33 - a23 * a23); - M->ex.y = det * (a13 * a23 - a12 * a33); - M->ex.z = det * (a12 * a23 - a13 * a22); - - M->ey.x = M->ex.y; - M->ey.y = det * (a11 * a33 - a13 * a13); - M->ey.z = det * (a13 * a12 - a11 * a23); - - M->ez.x = M->ex.z; - M->ez.y = M->ey.z; - M->ez.z = det * (a11 * a22 - a12 * a12); -} diff --git a/3rdparty/box2d/src/common/b2_settings.cpp b/3rdparty/box2d/src/common/b2_settings.cpp deleted file mode 100644 index dde28bb3abd7..000000000000 --- a/3rdparty/box2d/src/common/b2_settings.cpp +++ /dev/null @@ -1,74 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#define _CRT_SECURE_NO_WARNINGS - -#include "box2d/b2_settings.h" -#include -#include -#include - -b2Version b2_version = {2, 4, 1}; - -// Memory allocators. Modify these to use your own allocator. -void* b2Alloc_Default(int32 size) -{ - return malloc(size); -} - -void b2Free_Default(void* mem) -{ - free(mem); -} - -// You can modify this to use your logging facility. -void b2Log_Default(const char* string, va_list args) -{ - vprintf(string, args); -} - -FILE* b2_dumpFile = nullptr; - -void b2OpenDump(const char* fileName) -{ - b2Assert(b2_dumpFile == nullptr); - b2_dumpFile = fopen(fileName, "w"); -} - -void b2Dump(const char* string, ...) -{ - if (b2_dumpFile == nullptr) - { - return; - } - - va_list args; - va_start(args, string); - vfprintf(b2_dumpFile, string, args); - va_end(args); -} - -void b2CloseDump() -{ - fclose(b2_dumpFile); - b2_dumpFile = nullptr; -} diff --git a/3rdparty/box2d/src/common/b2_stack_allocator.cpp b/3rdparty/box2d/src/common/b2_stack_allocator.cpp deleted file mode 100644 index 602db1a00494..000000000000 --- a/3rdparty/box2d/src/common/b2_stack_allocator.cpp +++ /dev/null @@ -1,87 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_stack_allocator.h" -#include "box2d/b2_math.h" - -b2StackAllocator::b2StackAllocator() -{ - m_index = 0; - m_allocation = 0; - m_maxAllocation = 0; - m_entryCount = 0; -} - -b2StackAllocator::~b2StackAllocator() -{ - b2Assert(m_index == 0); - b2Assert(m_entryCount == 0); -} - -void* b2StackAllocator::Allocate(int32 size) -{ - b2Assert(m_entryCount < b2_maxStackEntries); - - b2StackEntry* entry = m_entries + m_entryCount; - entry->size = size; - if (m_index + size > b2_stackSize) - { - entry->data = (char*)b2Alloc(size); - entry->usedMalloc = true; - } - else - { - entry->data = m_data + m_index; - entry->usedMalloc = false; - m_index += size; - } - - m_allocation += size; - m_maxAllocation = b2Max(m_maxAllocation, m_allocation); - ++m_entryCount; - - return entry->data; -} - -void b2StackAllocator::Free(void* p) -{ - b2Assert(m_entryCount > 0); - b2StackEntry* entry = m_entries + m_entryCount - 1; - b2Assert(p == entry->data); - if (entry->usedMalloc) - { - b2Free(p); - } - else - { - m_index -= entry->size; - } - m_allocation -= entry->size; - --m_entryCount; - - p = nullptr; -} - -int32 b2StackAllocator::GetMaxAllocation() const -{ - return m_maxAllocation; -} diff --git a/3rdparty/box2d/src/common/b2_timer.cpp b/3rdparty/box2d/src/common/b2_timer.cpp deleted file mode 100644 index dd7cde7f4709..000000000000 --- a/3rdparty/box2d/src/common/b2_timer.cpp +++ /dev/null @@ -1,125 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_timer.h" - -#if defined(_WIN32) - -double b2Timer::s_invFrequency = 0.0; - -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#include - -b2Timer::b2Timer() -{ - LARGE_INTEGER largeInteger; - - if (s_invFrequency == 0.0) - { - QueryPerformanceFrequency(&largeInteger); - s_invFrequency = double(largeInteger.QuadPart); - if (s_invFrequency > 0.0) - { - s_invFrequency = 1000.0 / s_invFrequency; - } - } - - QueryPerformanceCounter(&largeInteger); - m_start = double(largeInteger.QuadPart); -} - -void b2Timer::Reset() -{ - LARGE_INTEGER largeInteger; - QueryPerformanceCounter(&largeInteger); - m_start = double(largeInteger.QuadPart); -} - -float b2Timer::GetMilliseconds() const -{ - LARGE_INTEGER largeInteger; - QueryPerformanceCounter(&largeInteger); - double count = double(largeInteger.QuadPart); - float ms = float(s_invFrequency * (count - m_start)); - return ms; -} - -#elif defined(__linux__) || defined (__APPLE__) - -#include - -b2Timer::b2Timer() -{ - Reset(); -} - -void b2Timer::Reset() -{ - timeval t; - gettimeofday(&t, 0); - m_start_sec = t.tv_sec; - m_start_usec = t.tv_usec; -} - -float b2Timer::GetMilliseconds() const -{ - timeval t; - gettimeofday(&t, 0); - time_t start_sec = m_start_sec; - suseconds_t start_usec = m_start_usec; - - // http://www.gnu.org/software/libc/manual/html_node/Elapsed-Time.html - if (t.tv_usec < start_usec) - { - int nsec = (start_usec - t.tv_usec) / 1000000 + 1; - start_usec -= 1000000 * nsec; - start_sec += nsec; - } - - if (t.tv_usec - start_usec > 1000000) - { - int nsec = (t.tv_usec - start_usec) / 1000000; - start_usec += 1000000 * nsec; - start_sec -= nsec; - } - return 1000.0f * (t.tv_sec - start_sec) + 0.001f * (t.tv_usec - start_usec); -} - -#else - -b2Timer::b2Timer() -{ -} - -void b2Timer::Reset() -{ -} - -float b2Timer::GetMilliseconds() const -{ - return 0.0f; -} - -#endif diff --git a/3rdparty/box2d/src/constants.h b/3rdparty/box2d/src/constants.h new file mode 100644 index 000000000000..f3dd71cb2236 --- /dev/null +++ b/3rdparty/box2d/src/constants.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +extern float b2_lengthUnitsPerMeter; + +// Used to detect bad values. Positions greater than about 16km will have precision +// problems, so 100km as a limit should be fine in all cases. +#define B2_HUGE ( 100000.0f * b2_lengthUnitsPerMeter ) + +// Maximum parallel workers. Used to size some static arrays. +#define B2_MAX_WORKERS 64 + +// Maximum number of colors in the constraint graph. Constraints that cannot +// find a color are added to the overflow set which are solved single-threaded. +#define B2_GRAPH_COLOR_COUNT 12 + +// A small length used as a collision and constraint tolerance. Usually it is +// chosen to be numerically significant, but visually insignificant. In meters. +// Normally this is 0.5cm. +// @warning modifying this can have a significant impact on stability +#define B2_LINEAR_SLOP ( 0.005f * b2_lengthUnitsPerMeter ) + +// Maximum number of simultaneous worlds that can be allocated +#ifndef B2_MAX_WORLDS +#define B2_MAX_WORLDS 128 +#endif + +// The maximum rotation of a body per time step. This limit is very large and is used +// to prevent numerical problems. You shouldn't need to adjust this. +// @warning increasing this to 0.5f * b2_pi or greater will break continuous collision. +#define B2_MAX_ROTATION ( 0.25f * B2_PI ) + +// Box2D uses limited speculative collision. This reduces jitter. +// Normally this is 2cm. +// @warning modifying this can have a significant impact on performance and stability +#define B2_SPECULATIVE_DISTANCE ( 4.0f * B2_LINEAR_SLOP ) + +// This is used to fatten AABBs in the dynamic tree. This allows proxies +// to move by a small amount without triggering a tree adjustment. This is in meters. +// Normally this is 5cm. +// @warning modifying this can have a significant impact on performance +#define B2_AABB_MARGIN ( 0.05f * b2_lengthUnitsPerMeter ) + +// The time that a body must be still before it will go to sleep. In seconds. +#define B2_TIME_TO_SLEEP 0.5f + +enum b2TreeNodeFlags +{ + b2_allocatedNode = 0x0001, + b2_enlargedNode = 0x0002, + b2_leafNode = 0x0004, +}; diff --git a/3rdparty/box2d/src/constraint_graph.c b/3rdparty/box2d/src/constraint_graph.c new file mode 100644 index 000000000000..1737aea77f9b --- /dev/null +++ b/3rdparty/box2d/src/constraint_graph.c @@ -0,0 +1,322 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constraint_graph.h" + +#include "array.h" +#include "bitset.h" +#include "body.h" +#include "contact.h" +#include "joint.h" +#include "solver_set.h" +#include "world.h" + +#include + +// Solver using graph coloring. Islands are only used for sleep. +// High-Performance Physical Simulations on Next-Generation Architecture with Many Cores +// http://web.eecs.umich.edu/~msmelyan/papers/physsim_onmanycore_itj.pdf + +// Kinematic bodies have to be treated like dynamic bodies in graph coloring. Unlike static bodies, we cannot use a dummy solver +// body for kinematic bodies. We cannot access a kinematic body from multiple threads efficiently because the SIMD solver body +// scatter would write to the same kinematic body from multiple threads. Even if these writes don't modify the body, they will +// cause horrible cache stalls. To make this feasible I would need a way to block these writes. + +// This is used for debugging by making all constraints be assigned to overflow. +#define B2_FORCE_OVERFLOW 0 + +_Static_assert( B2_GRAPH_COLOR_COUNT == 12, "graph color count assumed to be 12" ); + +void b2CreateGraph( b2ConstraintGraph* graph, int bodyCapacity ) +{ + _Static_assert( B2_GRAPH_COLOR_COUNT >= 2, "must have at least two constraint graph colors" ); + _Static_assert( B2_OVERFLOW_INDEX == B2_GRAPH_COLOR_COUNT - 1, "bad over flow index" ); + + *graph = ( b2ConstraintGraph ){ 0 }; + + bodyCapacity = b2MaxInt( bodyCapacity, 8 ); + + // Initialize graph color bit set. + // No bitset for overflow color. + for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + color->bodySet = b2CreateBitSet( bodyCapacity ); + b2SetBitCountAndClear( &color->bodySet, bodyCapacity ); + } +} + +void b2DestroyGraph( b2ConstraintGraph* graph ) +{ + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + b2GraphColor* color = graph->colors + i; + + // The bit set should never be used on the overflow color + B2_ASSERT( i != B2_OVERFLOW_INDEX || color->bodySet.bits == NULL ); + + b2DestroyBitSet( &color->bodySet ); + + b2ContactSimArray_Destroy( &color->contactSims ); + b2JointSimArray_Destroy( &color->jointSims ); + } +} + +// Contacts are always created as non-touching. They get cloned into the constraint +// graph once they are found to be touching. +// todo maybe kinematic bodies should not go into graph +void b2AddContactToGraph( b2World* world, b2ContactSim* contactSim, b2Contact* contact ) +{ + B2_ASSERT( contactSim->manifold.pointCount > 0 ); + B2_ASSERT( contactSim->simFlags & b2_simTouchingFlag ); + B2_ASSERT( contact->flags & b2_contactTouchingFlag ); + + b2ConstraintGraph* graph = &world->constraintGraph; + int colorIndex = B2_OVERFLOW_INDEX; + + int bodyIdA = contact->edges[0].bodyId; + int bodyIdB = contact->edges[1].bodyId; + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + bool staticA = bodyA->setIndex == b2_staticSet; + bool staticB = bodyB->setIndex == b2_staticSet; + B2_ASSERT( staticA == false || staticB == false ); + +#if B2_FORCE_OVERFLOW == 0 + if ( staticA == false && staticB == false ) + { + for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdA ) || b2GetBit( &color->bodySet, bodyIdB ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdA ); + b2SetBitGrow( &color->bodySet, bodyIdB ); + colorIndex = i; + break; + } + } + else if ( staticA == false ) + { + // No static contacts in color 0 + for ( int i = 1; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdA ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdA ); + colorIndex = i; + break; + } + } + else if ( staticB == false ) + { + // No static contacts in color 0 + for ( int i = 1; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdB ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdB ); + colorIndex = i; + break; + } + } +#endif + + b2GraphColor* color = graph->colors + colorIndex; + contact->colorIndex = colorIndex; + contact->localIndex = color->contactSims.count; + + b2ContactSim* newContact = b2ContactSimArray_Add( &color->contactSims ); + memcpy( newContact, contactSim, sizeof( b2ContactSim ) ); + + // todo perhaps skip this if the contact is already awake + + if ( staticA ) + { + newContact->bodySimIndexA = B2_NULL_INDEX; + newContact->invMassA = 0.0f; + newContact->invIA = 0.0f; + } + else + { + B2_ASSERT( bodyA->setIndex == b2_awakeSet ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + + int localIndex = bodyA->localIndex; + newContact->bodySimIndexA = localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &awakeSet->bodySims, localIndex ); + newContact->invMassA = bodySimA->invMass; + newContact->invIA = bodySimA->invInertia; + } + + if ( staticB ) + { + newContact->bodySimIndexB = B2_NULL_INDEX; + newContact->invMassB = 0.0f; + newContact->invIB = 0.0f; + } + else + { + B2_ASSERT( bodyB->setIndex == b2_awakeSet ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + + int localIndex = bodyB->localIndex; + newContact->bodySimIndexB = localIndex; + + b2BodySim* bodySimB = b2BodySimArray_Get( &awakeSet->bodySims, localIndex ); + newContact->invMassB = bodySimB->invMass; + newContact->invIB = bodySimB->invInertia; + } +} + +void b2RemoveContactFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex ) +{ + b2ConstraintGraph* graph = &world->constraintGraph; + + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = graph->colors + colorIndex; + + if ( colorIndex != B2_OVERFLOW_INDEX ) + { + // might clear a bit for a static body, but this has no effect + b2ClearBit( &color->bodySet, bodyIdA ); + b2ClearBit( &color->bodySet, bodyIdB ); + } + + int movedIndex = b2ContactSimArray_RemoveSwap( &color->contactSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix index on swapped contact + b2ContactSim* movedContactSim = color->contactSims.data + localIndex; + + // Fix moved contact + int movedId = movedContactSim->contactId; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedId ); + B2_ASSERT( movedContact->setIndex == b2_awakeSet ); + B2_ASSERT( movedContact->colorIndex == colorIndex ); + B2_ASSERT( movedContact->localIndex == movedIndex ); + movedContact->localIndex = localIndex; + } +} + +static int b2AssignJointColor( b2ConstraintGraph* graph, int bodyIdA, int bodyIdB, bool staticA, bool staticB ) +{ + B2_ASSERT( staticA == false || staticB == false ); + +#if B2_FORCE_OVERFLOW == 0 + if ( staticA == false && staticB == false ) + { + for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdA ) || b2GetBit( &color->bodySet, bodyIdB ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdA ); + b2SetBitGrow( &color->bodySet, bodyIdB ); + return i; + } + } + else if ( staticA == false ) + { + for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdA ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdA ); + return i; + } + } + else if ( staticB == false ) + { + for ( int i = 0; i < B2_OVERFLOW_INDEX; ++i ) + { + b2GraphColor* color = graph->colors + i; + if ( b2GetBit( &color->bodySet, bodyIdB ) ) + { + continue; + } + + b2SetBitGrow( &color->bodySet, bodyIdB ); + return i; + } + } +#else + B2_UNUSED( graph, bodyIdA, bodyIdB, staticA, staticB ); +#endif + + return B2_OVERFLOW_INDEX; +} + +b2JointSim* b2CreateJointInGraph( b2World* world, b2Joint* joint ) +{ + b2ConstraintGraph* graph = &world->constraintGraph; + + int bodyIdA = joint->edges[0].bodyId; + int bodyIdB = joint->edges[1].bodyId; + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + bool staticA = bodyA->setIndex == b2_staticSet; + bool staticB = bodyB->setIndex == b2_staticSet; + + int colorIndex = b2AssignJointColor( graph, bodyIdA, bodyIdB, staticA, staticB ); + + b2JointSim* jointSim = b2JointSimArray_Add( &graph->colors[colorIndex].jointSims ); + memset( jointSim, 0, sizeof( b2JointSim ) ); + + joint->colorIndex = colorIndex; + joint->localIndex = graph->colors[colorIndex].jointSims.count - 1; + return jointSim; +} + +void b2AddJointToGraph( b2World* world, b2JointSim* jointSim, b2Joint* joint ) +{ + b2JointSim* jointDst = b2CreateJointInGraph( world, joint ); + memcpy( jointDst, jointSim, sizeof( b2JointSim ) ); +} + +void b2RemoveJointFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex ) +{ + b2ConstraintGraph* graph = &world->constraintGraph; + + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = graph->colors + colorIndex; + + if ( colorIndex != B2_OVERFLOW_INDEX ) + { + // May clear static bodies, no effect + b2ClearBit( &color->bodySet, bodyIdA ); + b2ClearBit( &color->bodySet, bodyIdB ); + } + + int movedIndex = b2JointSimArray_RemoveSwap( &color->jointSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix moved joint + b2JointSim* movedJointSim = color->jointSims.data + localIndex; + int movedId = movedJointSim->jointId; + b2Joint* movedJoint = b2JointArray_Get( &world->joints, movedId ); + B2_ASSERT( movedJoint->setIndex == b2_awakeSet ); + B2_ASSERT( movedJoint->colorIndex == colorIndex ); + B2_ASSERT( movedJoint->localIndex == movedIndex ); + movedJoint->localIndex = localIndex; + } +} diff --git a/3rdparty/box2d/src/constraint_graph.h b/3rdparty/box2d/src/constraint_graph.h new file mode 100644 index 000000000000..ecee324152b7 --- /dev/null +++ b/3rdparty/box2d/src/constraint_graph.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" +#include "bitset.h" +#include "constants.h" + +typedef struct b2Body b2Body; +typedef struct b2ContactSim b2ContactSim; +typedef struct b2Contact b2Contact; +typedef struct b2ContactConstraint b2ContactConstraint; +typedef struct b2ContactConstraintSIMD b2ContactConstraintSIMD; +typedef struct b2JointSim b2JointSim; +typedef struct b2Joint b2Joint; +typedef struct b2StepContext b2StepContext; +typedef struct b2World b2World; + +// This holds constraints that cannot fit the graph color limit. This happens when a single dynamic body +// is touching many other bodies. +#define B2_OVERFLOW_INDEX (B2_GRAPH_COLOR_COUNT - 1) + +typedef struct b2GraphColor +{ + // This bitset is indexed by bodyId so this is over-sized to encompass static bodies + // however I never traverse these bits or use the bit count for anything + // This bitset is unused on the overflow color. + // todo consider having a uint_16 per body that tracks the graph color membership + b2BitSet bodySet; + + // cache friendly arrays + b2ContactSimArray contactSims; + b2JointSimArray jointSims; + + // transient + union + { + b2ContactConstraintSIMD* simdConstraints; + b2ContactConstraint* overflowConstraints; + }; +} b2GraphColor; + +typedef struct b2ConstraintGraph +{ + // including overflow at the end + b2GraphColor colors[B2_GRAPH_COLOR_COUNT]; +} b2ConstraintGraph; + +void b2CreateGraph( b2ConstraintGraph* graph, int bodyCapacity ); +void b2DestroyGraph( b2ConstraintGraph* graph ); + +void b2AddContactToGraph( b2World* world, b2ContactSim* contactSim, b2Contact* contact ); +void b2RemoveContactFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex ); + +b2JointSim* b2CreateJointInGraph( b2World* world, b2Joint* joint ); +void b2AddJointToGraph( b2World* world, b2JointSim* jointSim, b2Joint* joint ); +void b2RemoveJointFromGraph( b2World* world, int bodyIdA, int bodyIdB, int colorIndex, int localIndex ); diff --git a/3rdparty/box2d/src/contact.c b/3rdparty/box2d/src/contact.c new file mode 100644 index 000000000000..d2edf21522fe --- /dev/null +++ b/3rdparty/box2d/src/contact.c @@ -0,0 +1,650 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "contact.h" + +#include "array.h" +#include "body.h" +#include "core.h" +#include "island.h" +#include "shape.h" +#include "solver_set.h" +#include "table.h" +#include "world.h" + +#include "box2d/collision.h" + +#include +#include +#include + +B2_ARRAY_SOURCE( b2Contact, b2Contact ) +B2_ARRAY_SOURCE( b2ContactSim, b2ContactSim ) + +// Contacts and determinism +// A deterministic simulation requires contacts to exist in the same order in b2Island no matter the thread count. +// The order must reproduce from run to run. This is necessary because the Gauss-Seidel constraint solver is order dependent. +// +// Creation: +// - Contacts are created using results from b2UpdateBroadPhasePairs +// - These results are ordered according to the order of the broad-phase move array +// - The move array is ordered according to the shape creation order using a bitset. +// - The island/shape/body order is determined by creation order +// - Logically contacts are only created for awake bodies, so they are immediately added to the awake contact array (serially) +// +// Island linking: +// - The awake contact array is built from the body-contact graph for all awake bodies in awake islands. +// - Awake contacts are solved in parallel and they generate contact state changes. +// - These state changes may link islands together using union find. +// - The state changes are ordered using a bit array that encompasses all contacts +// - As long as contacts are created in deterministic order, island link order is deterministic. +// - This keeps the order of contacts in islands deterministic + +// Manifold functions should compute important results in local space to improve precision. However, this +// interface function takes two world transforms instead of a relative transform for these reasons: +// +// First: +// The anchors need to be computed relative to the shape origin in world space. This is necessary so the +// solver does not need to access static body transforms. Not even in constraint preparation. This approach +// has world space vectors yet retains precision. +// +// Second: +// b2ManifoldPoint::point is very useful for debugging and it is in world space. +// +// Third: +// The user may call the manifold functions directly and they should be easy to use and have easy to use +// results. +typedef b2Manifold b2ManifoldFcn( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ); + +struct b2ContactRegister +{ + b2ManifoldFcn* fcn; + bool primary; +}; + +static struct b2ContactRegister s_registers[b2_shapeTypeCount][b2_shapeTypeCount]; +static bool s_initialized = false; + +static b2Manifold b2CircleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideCircles( &shapeA->circle, xfA, &shapeB->circle, xfB ); +} + +static b2Manifold b2CapsuleAndCircleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideCapsuleAndCircle( &shapeA->capsule, xfA, &shapeB->circle, xfB ); +} + +static b2Manifold b2CapsuleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideCapsules( &shapeA->capsule, xfA, &shapeB->capsule, xfB ); +} + +static b2Manifold b2PolygonAndCircleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollidePolygonAndCircle( &shapeA->polygon, xfA, &shapeB->circle, xfB ); +} + +static b2Manifold b2PolygonAndCapsuleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollidePolygonAndCapsule( &shapeA->polygon, xfA, &shapeB->capsule, xfB ); +} + +static b2Manifold b2PolygonManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollidePolygons( &shapeA->polygon, xfA, &shapeB->polygon, xfB ); +} + +static b2Manifold b2SegmentAndCircleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideSegmentAndCircle( &shapeA->segment, xfA, &shapeB->circle, xfB ); +} + +static b2Manifold b2SegmentAndCapsuleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideSegmentAndCapsule( &shapeA->segment, xfA, &shapeB->capsule, xfB ); +} + +static b2Manifold b2SegmentAndPolygonManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideSegmentAndPolygon( &shapeA->segment, xfA, &shapeB->polygon, xfB ); +} + +static b2Manifold b2ChainSegmentAndCircleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, b2Transform xfB, + b2SimplexCache* cache ) +{ + B2_UNUSED( cache ); + return b2CollideChainSegmentAndCircle( &shapeA->chainSegment, xfA, &shapeB->circle, xfB ); +} + +static b2Manifold b2ChainSegmentAndCapsuleManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, + b2Transform xfB, b2SimplexCache* cache ) +{ + return b2CollideChainSegmentAndCapsule( &shapeA->chainSegment, xfA, &shapeB->capsule, xfB, cache ); +} + +static b2Manifold b2ChainSegmentAndPolygonManifold( const b2Shape* shapeA, b2Transform xfA, const b2Shape* shapeB, + b2Transform xfB, b2SimplexCache* cache ) +{ + return b2CollideChainSegmentAndPolygon( &shapeA->chainSegment, xfA, &shapeB->polygon, xfB, cache ); +} + +static void b2AddType( b2ManifoldFcn* fcn, b2ShapeType type1, b2ShapeType type2 ) +{ + B2_ASSERT( 0 <= type1 && type1 < b2_shapeTypeCount ); + B2_ASSERT( 0 <= type2 && type2 < b2_shapeTypeCount ); + + s_registers[type1][type2].fcn = fcn; + s_registers[type1][type2].primary = true; + + if ( type1 != type2 ) + { + s_registers[type2][type1].fcn = fcn; + s_registers[type2][type1].primary = false; + } +} + +void b2InitializeContactRegisters( void ) +{ + if ( s_initialized == false ) + { + b2AddType( b2CircleManifold, b2_circleShape, b2_circleShape ); + b2AddType( b2CapsuleAndCircleManifold, b2_capsuleShape, b2_circleShape ); + b2AddType( b2CapsuleManifold, b2_capsuleShape, b2_capsuleShape ); + b2AddType( b2PolygonAndCircleManifold, b2_polygonShape, b2_circleShape ); + b2AddType( b2PolygonAndCapsuleManifold, b2_polygonShape, b2_capsuleShape ); + b2AddType( b2PolygonManifold, b2_polygonShape, b2_polygonShape ); + b2AddType( b2SegmentAndCircleManifold, b2_segmentShape, b2_circleShape ); + b2AddType( b2SegmentAndCapsuleManifold, b2_segmentShape, b2_capsuleShape ); + b2AddType( b2SegmentAndPolygonManifold, b2_segmentShape, b2_polygonShape ); + b2AddType( b2ChainSegmentAndCircleManifold, b2_chainSegmentShape, b2_circleShape ); + b2AddType( b2ChainSegmentAndCapsuleManifold, b2_chainSegmentShape, b2_capsuleShape ); + b2AddType( b2ChainSegmentAndPolygonManifold, b2_chainSegmentShape, b2_polygonShape ); + s_initialized = true; + } +} + +void b2CreateContact( b2World* world, b2Shape* shapeA, b2Shape* shapeB ) +{ + b2ShapeType type1 = shapeA->type; + b2ShapeType type2 = shapeB->type; + + B2_ASSERT( 0 <= type1 && type1 < b2_shapeTypeCount ); + B2_ASSERT( 0 <= type2 && type2 < b2_shapeTypeCount ); + + if ( s_registers[type1][type2].fcn == NULL ) + { + // For example, no segment vs segment collision + return; + } + + if ( s_registers[type1][type2].primary == false ) + { + // flip order + b2CreateContact( world, shapeB, shapeA ); + return; + } + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, shapeA->bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, shapeB->bodyId ); + + B2_ASSERT( bodyA->setIndex != b2_disabledSet && bodyB->setIndex != b2_disabledSet ); + B2_ASSERT( bodyA->setIndex != b2_staticSet || bodyB->setIndex != b2_staticSet ); + + int setIndex; + if ( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ) + { + setIndex = b2_awakeSet; + } + else + { + // sleeping and non-touching contacts live in the disabled set + // later if this set is found to be touching then the sleeping + // islands will be linked and the contact moved to the merged island + setIndex = b2_disabledSet; + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + + // Create contact key and contact + int contactId = b2AllocId( &world->contactIdPool ); + if ( contactId == world->contacts.count ) + { + b2ContactArray_Push( &world->contacts, ( b2Contact ){ 0 } ); + } + + int shapeIdA = shapeA->id; + int shapeIdB = shapeB->id; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contact->contactId = contactId; + contact->setIndex = setIndex; + contact->colorIndex = B2_NULL_INDEX; + contact->localIndex = set->contactSims.count; + contact->islandId = B2_NULL_INDEX; + contact->islandPrev = B2_NULL_INDEX; + contact->islandNext = B2_NULL_INDEX; + contact->shapeIdA = shapeIdA; + contact->shapeIdB = shapeIdB; + contact->isMarked = false; + contact->flags = 0; + + B2_ASSERT( shapeA->sensorIndex == B2_NULL_INDEX && shapeB->sensorIndex == B2_NULL_INDEX ); + + if ( shapeA->enableContactEvents || shapeB->enableContactEvents ) + { + contact->flags |= b2_contactEnableContactEvents; + } + + // Connect to body A + { + contact->edges[0].bodyId = shapeA->bodyId; + contact->edges[0].prevKey = B2_NULL_INDEX; + contact->edges[0].nextKey = bodyA->headContactKey; + + int keyA = ( contactId << 1 ) | 0; + int headContactKey = bodyA->headContactKey; + if ( headContactKey != B2_NULL_INDEX ) + { + b2Contact* headContact = b2ContactArray_Get( &world->contacts, headContactKey >> 1 ); + headContact->edges[headContactKey & 1].prevKey = keyA; + } + bodyA->headContactKey = keyA; + bodyA->contactCount += 1; + } + + // Connect to body B + { + contact->edges[1].bodyId = shapeB->bodyId; + contact->edges[1].prevKey = B2_NULL_INDEX; + contact->edges[1].nextKey = bodyB->headContactKey; + + int keyB = ( contactId << 1 ) | 1; + int headContactKey = bodyB->headContactKey; + if ( bodyB->headContactKey != B2_NULL_INDEX ) + { + b2Contact* headContact = b2ContactArray_Get( &world->contacts, headContactKey >> 1 ); + headContact->edges[headContactKey & 1].prevKey = keyB; + } + bodyB->headContactKey = keyB; + bodyB->contactCount += 1; + } + + // Add to pair set for fast lookup + uint64_t pairKey = B2_SHAPE_PAIR_KEY( shapeIdA, shapeIdB ); + b2AddKey( &world->broadPhase.pairSet, pairKey ); + + // Contacts are created as non-touching. Later if they are found to be touching + // they will link islands and be moved into the constraint graph. + b2ContactSim* contactSim = b2ContactSimArray_Add( &set->contactSims ); + contactSim->contactId = contactId; + +#if B2_VALIDATE + contactSim->bodyIdA = shapeA->bodyId; + contactSim->bodyIdB = shapeB->bodyId; +#endif + + contactSim->bodySimIndexA = B2_NULL_INDEX; + contactSim->bodySimIndexB = B2_NULL_INDEX; + contactSim->invMassA = 0.0f; + contactSim->invIA = 0.0f; + contactSim->invMassB = 0.0f; + contactSim->invIB = 0.0f; + contactSim->shapeIdA = shapeIdA; + contactSim->shapeIdB = shapeIdB; + contactSim->cache = b2_emptySimplexCache; + contactSim->manifold = ( b2Manifold ){ 0 }; + + // These also get updated in the narrow phase + contactSim->friction = world->frictionCallback(shapeA->friction, shapeA->userMaterialId, shapeB->friction, shapeB->userMaterialId); + contactSim->restitution = world->restitutionCallback(shapeA->restitution, shapeA->userMaterialId, shapeB->restitution, shapeB->userMaterialId); + + contactSim->tangentSpeed = 0.0f; + contactSim->simFlags = 0; + + if ( shapeA->enablePreSolveEvents || shapeB->enablePreSolveEvents ) + { + contactSim->simFlags |= b2_simEnablePreSolveEvents; + } +} + +// A contact is destroyed when: +// - broad-phase proxies stop overlapping +// - a body is destroyed +// - a body is disabled +// - a body changes type from dynamic to kinematic or static +// - a shape is destroyed +// - contact filtering is modified +void b2DestroyContact( b2World* world, b2Contact* contact, bool wakeBodies ) +{ + // Remove pair from set + uint64_t pairKey = B2_SHAPE_PAIR_KEY( contact->shapeIdA, contact->shapeIdB ); + b2RemoveKey( &world->broadPhase.pairSet, pairKey ); + + b2ContactEdge* edgeA = contact->edges + 0; + b2ContactEdge* edgeB = contact->edges + 1; + + int bodyIdA = edgeA->bodyId; + int bodyIdB = edgeB->bodyId; + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + + uint32_t flags = contact->flags; + bool touching = ( flags & b2_contactTouchingFlag ) != 0; + + // End touch event + if ( touching && ( flags & b2_contactEnableContactEvents ) != 0 ) + { + uint16_t worldId = world->worldId; + const b2Shape* shapeA = b2ShapeArray_Get( &world->shapes, contact->shapeIdA ); + const b2Shape* shapeB = b2ShapeArray_Get( &world->shapes, contact->shapeIdB ); + b2ShapeId shapeIdA = { shapeA->id + 1, worldId, shapeA->generation }; + b2ShapeId shapeIdB = { shapeB->id + 1, worldId, shapeB->generation }; + + b2ContactEndTouchEvent event = { shapeIdA, shapeIdB }; + b2ContactEndTouchEventArray_Push( world->contactEndEvents + world->endEventArrayIndex, event ); + } + + // Remove from body A + if ( edgeA->prevKey != B2_NULL_INDEX ) + { + b2Contact* prevContact = b2ContactArray_Get( &world->contacts, edgeA->prevKey >> 1 ); + b2ContactEdge* prevEdge = prevContact->edges + ( edgeA->prevKey & 1 ); + prevEdge->nextKey = edgeA->nextKey; + } + + if ( edgeA->nextKey != B2_NULL_INDEX ) + { + b2Contact* nextContact = b2ContactArray_Get( &world->contacts, edgeA->nextKey >> 1 ); + b2ContactEdge* nextEdge = nextContact->edges + ( edgeA->nextKey & 1 ); + nextEdge->prevKey = edgeA->prevKey; + } + + int contactId = contact->contactId; + + int edgeKeyA = ( contactId << 1 ) | 0; + if ( bodyA->headContactKey == edgeKeyA ) + { + bodyA->headContactKey = edgeA->nextKey; + } + + bodyA->contactCount -= 1; + + // Remove from body B + if ( edgeB->prevKey != B2_NULL_INDEX ) + { + b2Contact* prevContact = b2ContactArray_Get( &world->contacts, edgeB->prevKey >> 1 ); + b2ContactEdge* prevEdge = prevContact->edges + ( edgeB->prevKey & 1 ); + prevEdge->nextKey = edgeB->nextKey; + } + + if ( edgeB->nextKey != B2_NULL_INDEX ) + { + b2Contact* nextContact = b2ContactArray_Get( &world->contacts, edgeB->nextKey >> 1 ); + b2ContactEdge* nextEdge = nextContact->edges + ( edgeB->nextKey & 1 ); + nextEdge->prevKey = edgeB->prevKey; + } + + int edgeKeyB = ( contactId << 1 ) | 1; + if ( bodyB->headContactKey == edgeKeyB ) + { + bodyB->headContactKey = edgeB->nextKey; + } + + bodyB->contactCount -= 1; + + // Remove contact from the array that owns it + if ( contact->islandId != B2_NULL_INDEX ) + { + b2UnlinkContact( world, contact ); + } + + if ( contact->colorIndex != B2_NULL_INDEX ) + { + // contact is an active constraint + B2_ASSERT( contact->setIndex == b2_awakeSet ); + b2RemoveContactFromGraph( world, bodyIdA, bodyIdB, contact->colorIndex, contact->localIndex ); + } + else + { + // contact is non-touching or is sleeping or is a sensor + B2_ASSERT( contact->setIndex != b2_awakeSet || ( contact->flags & b2_contactTouchingFlag ) == 0 ); + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, contact->setIndex ); + int movedIndex = b2ContactSimArray_RemoveSwap( &set->contactSims, contact->localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + b2ContactSim* movedContactSim = set->contactSims.data + contact->localIndex; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedContactSim->contactId ); + movedContact->localIndex = contact->localIndex; + } + } + + contact->contactId = B2_NULL_INDEX; + contact->setIndex = B2_NULL_INDEX; + contact->colorIndex = B2_NULL_INDEX; + contact->localIndex = B2_NULL_INDEX; + + b2FreeId( &world->contactIdPool, contactId ); + + if ( wakeBodies && touching ) + { + b2WakeBody( world, bodyA ); + b2WakeBody( world, bodyB ); + } +} + +b2ContactSim* b2GetContactSim( b2World* world, b2Contact* contact ) +{ + if ( contact->setIndex == b2_awakeSet && contact->colorIndex != B2_NULL_INDEX ) + { + // contact lives in constraint graph + B2_ASSERT( 0 <= contact->colorIndex && contact->colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = world->constraintGraph.colors + contact->colorIndex; + return b2ContactSimArray_Get( &color->contactSims, contact->localIndex ); + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, contact->setIndex ); + return b2ContactSimArray_Get( &set->contactSims, contact->localIndex ); +} + +bool b2ShouldShapesCollide( b2Filter filterA, b2Filter filterB ) +{ + if ( filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0 ) + { + return filterA.groupIndex > 0; + } + + bool collide = ( filterA.maskBits & filterB.categoryBits ) != 0 && ( filterA.categoryBits & filterB.maskBits ) != 0; + return collide; +} + +// Update the contact manifold and touching status. Also updates sensor overlap. +// Note: do not assume the shape AABBs are overlapping or are valid. +bool b2UpdateContact( b2World* world, b2ContactSim* contactSim, b2Shape* shapeA, b2Transform transformA, b2Vec2 centerOffsetA, + b2Shape* shapeB, b2Transform transformB, b2Vec2 centerOffsetB ) +{ + // Save old manifold + b2Manifold oldManifold = contactSim->manifold; + + // Compute new manifold + b2ManifoldFcn* fcn = s_registers[shapeA->type][shapeB->type].fcn; + contactSim->manifold = fcn( shapeA, transformA, shapeB, transformB, &contactSim->cache ); + + // Keep these updated in case the values on the shapes are modified + contactSim->friction = world->frictionCallback( shapeA->friction, shapeA->userMaterialId, shapeB->friction, shapeB->userMaterialId ); + contactSim->restitution = world->restitutionCallback( shapeA->restitution, shapeA->userMaterialId, shapeB->restitution, shapeB->userMaterialId ); + + // todo branch improves perf? + if (shapeA->rollingResistance > 0.0f || shapeB->rollingResistance > 0.0f) + { + float radiusA = b2GetShapeRadius( shapeA ); + float radiusB = b2GetShapeRadius( shapeB ); + float maxRadius = b2MaxFloat( radiusA, radiusB ); + contactSim->rollingResistance = b2MaxFloat( shapeA->rollingResistance, shapeB->rollingResistance ) * maxRadius; + } + else + { + contactSim->rollingResistance = 0.0f; + } + + contactSim->tangentSpeed = shapeA->tangentSpeed + shapeB->tangentSpeed; + + int pointCount = contactSim->manifold.pointCount; + bool touching = pointCount > 0; + + if ( touching && world->preSolveFcn && ( contactSim->simFlags & b2_simEnablePreSolveEvents ) != 0 ) + { + b2ShapeId shapeIdA = { shapeA->id + 1, world->worldId, shapeA->generation }; + b2ShapeId shapeIdB = { shapeB->id + 1, world->worldId, shapeB->generation }; + + // this call assumes thread safety + touching = world->preSolveFcn( shapeIdA, shapeIdB, &contactSim->manifold, world->preSolveContext ); + if ( touching == false ) + { + // disable contact + pointCount = 0; + contactSim->manifold.pointCount = 0; + } + } + + // This flag is for testing + if ( world->enableSpeculative == false && pointCount == 2 ) + { + if ( contactSim->manifold.points[0].separation > 1.5f * B2_LINEAR_SLOP ) + { + contactSim->manifold.points[0] = contactSim->manifold.points[1]; + contactSim->manifold.pointCount = 1; + } + else if ( contactSim->manifold.points[0].separation > 1.5f * B2_LINEAR_SLOP ) + { + contactSim->manifold.pointCount = 1; + } + + pointCount = contactSim->manifold.pointCount; + } + + if ( touching && ( shapeA->enableHitEvents || shapeB->enableHitEvents ) ) + { + contactSim->simFlags |= b2_simEnableHitEvent; + } + else + { + contactSim->simFlags &= ~b2_simEnableHitEvent; + } + + if (pointCount > 0) + { + contactSim->manifold.rollingImpulse = oldManifold.rollingImpulse; + } + + // Match old contact ids to new contact ids and copy the + // stored impulses to warm start the solver. + int unmatchedCount = 0; + for ( int i = 0; i < pointCount; ++i ) + { + b2ManifoldPoint* mp2 = contactSim->manifold.points + i; + + // shift anchors to be center of mass relative + mp2->anchorA = b2Sub( mp2->anchorA, centerOffsetA ); + mp2->anchorB = b2Sub( mp2->anchorB, centerOffsetB ); + + mp2->normalImpulse = 0.0f; + mp2->tangentImpulse = 0.0f; + mp2->totalNormalImpulse = 0.0f; + mp2->normalVelocity = 0.0f; + mp2->persisted = false; + + uint16_t id2 = mp2->id; + + for ( int j = 0; j < oldManifold.pointCount; ++j ) + { + b2ManifoldPoint* mp1 = oldManifold.points + j; + + if ( mp1->id == id2 ) + { + mp2->normalImpulse = mp1->normalImpulse; + mp2->tangentImpulse = mp1->tangentImpulse; + mp2->persisted = true; + + // clear old impulse + mp1->normalImpulse = 0.0f; + mp1->tangentImpulse = 0.0f; + break; + } + } + + unmatchedCount += mp2->persisted ? 0 : 1; + } + + B2_UNUSED( unmatchedCount ); + +#if 0 + // todo I haven't found an improvement from this yet + // If there are unmatched new contact points, apply any left over old impulse. + if (unmatchedCount > 0) + { + float unmatchedNormalImpulse = 0.0f; + float unmatchedTangentImpulse = 0.0f; + for (int i = 0; i < oldManifold.pointCount; ++i) + { + b2ManifoldPoint* mp = oldManifold.points + i; + unmatchedNormalImpulse += mp->normalImpulse; + unmatchedTangentImpulse += mp->tangentImpulse; + } + + float inverse = 1.0f / unmatchedCount; + unmatchedNormalImpulse *= inverse; + unmatchedTangentImpulse *= inverse; + + for ( int i = 0; i < pointCount; ++i ) + { + b2ManifoldPoint* mp2 = contactSim->manifold.points + i; + + if (mp2->persisted) + { + continue; + } + + mp2->normalImpulse = unmatchedNormalImpulse; + mp2->tangentImpulse = unmatchedTangentImpulse; + } + } +#endif + + if ( touching ) + { + contactSim->simFlags |= b2_simTouchingFlag; + } + else + { + contactSim->simFlags &= ~b2_simTouchingFlag; + } + + return touching; +} + +b2Manifold b2ComputeManifold( b2Shape* shapeA, b2Transform transformA, b2Shape* shapeB, b2Transform transformB ) +{ + b2ManifoldFcn* fcn = s_registers[shapeA->type][shapeB->type].fcn; + b2SimplexCache cache = { 0 }; + return fcn( shapeA, transformA, shapeB, transformB, &cache ); +} diff --git a/3rdparty/box2d/src/contact.h b/3rdparty/box2d/src/contact.h new file mode 100644 index 000000000000..c23ed56b9f8a --- /dev/null +++ b/3rdparty/box2d/src/contact.h @@ -0,0 +1,148 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" +#include "core.h" + +#include "box2d/collision.h" +#include "box2d/types.h" + +typedef struct b2Shape b2Shape; +typedef struct b2World b2World; + +enum b2ContactFlags +{ + // Set when the solid shapes are touching. + b2_contactTouchingFlag = 0x00000001, + + // Contact has a hit event + b2_contactHitEventFlag = 0x00000002, + + // This contact wants contact events + b2_contactEnableContactEvents = 0x00000004, +}; + +// A contact edge is used to connect bodies and contacts together +// in a contact graph where each body is a node and each contact +// is an edge. A contact edge belongs to a doubly linked list +// maintained in each attached body. Each contact has two contact +// edges, one for each attached body. +typedef struct b2ContactEdge +{ + int bodyId; + int prevKey; + int nextKey; +} b2ContactEdge; + +// Cold contact data. Used as a persistent handle and for persistent island +// connectivity. +typedef struct b2Contact +{ + // index of simulation set stored in b2World + // B2_NULL_INDEX when slot is free + int setIndex; + + // index into the constraint graph color array + // B2_NULL_INDEX for non-touching or sleeping contacts + // B2_NULL_INDEX when slot is free + int colorIndex; + + // contact index within set or graph color + // B2_NULL_INDEX when slot is free + int localIndex; + + b2ContactEdge edges[2]; + int shapeIdA; + int shapeIdB; + + // A contact only belongs to an island if touching, otherwise B2_NULL_INDEX. + int islandPrev; + int islandNext; + int islandId; + + int contactId; + + // b2ContactFlags + uint32_t flags; + + bool isMarked; +} b2Contact; + +// Shifted to be distinct from b2ContactFlags +enum b2ContactSimFlags +{ + // Set when the shapes are touching + b2_simTouchingFlag = 0x00010000, + + // This contact no longer has overlapping AABBs + b2_simDisjoint = 0x00020000, + + // This contact started touching + b2_simStartedTouching = 0x00040000, + + // This contact stopped touching + b2_simStoppedTouching = 0x00080000, + + // This contact has a hit event + b2_simEnableHitEvent = 0x00100000, + + // This contact wants pre-solve events + b2_simEnablePreSolveEvents = 0x00200000, +}; + +/// The class manages contact between two shapes. A contact exists for each overlapping +/// AABB in the broad-phase (except if filtered). Therefore a contact object may exist +/// that has no contact points. +typedef struct b2ContactSim +{ + int contactId; + +#if B2_VALIDATE + int bodyIdA; + int bodyIdB; +#endif + + int bodySimIndexA; + int bodySimIndexB; + + int shapeIdA; + int shapeIdB; + + float invMassA; + float invIA; + + float invMassB; + float invIB; + + b2Manifold manifold; + + // Mixed friction and restitution + float friction; + float restitution; + float rollingResistance; + float tangentSpeed; + + // b2ContactSimFlags + uint32_t simFlags; + + b2SimplexCache cache; +} b2ContactSim; + +void b2InitializeContactRegisters( void ); + +void b2CreateContact( b2World* world, b2Shape* shapeA, b2Shape* shapeB ); +void b2DestroyContact( b2World* world, b2Contact* contact, bool wakeBodies ); + +b2ContactSim* b2GetContactSim( b2World* world, b2Contact* contact ); + +bool b2ShouldShapesCollide( b2Filter filterA, b2Filter filterB ); + +bool b2UpdateContact( b2World* world, b2ContactSim* contactSim, b2Shape* shapeA, b2Transform transformA, b2Vec2 centerOffsetA, + b2Shape* shapeB, b2Transform transformB, b2Vec2 centerOffsetB ); + +b2Manifold b2ComputeManifold( b2Shape* shapeA, b2Transform transformA, b2Shape* shapeB, b2Transform transformB ); + +B2_ARRAY_INLINE( b2Contact, b2Contact ) +B2_ARRAY_INLINE( b2ContactSim, b2ContactSim ) diff --git a/3rdparty/box2d/src/contact_solver.c b/3rdparty/box2d/src/contact_solver.c new file mode 100644 index 000000000000..332e8fbc6731 --- /dev/null +++ b/3rdparty/box2d/src/contact_solver.c @@ -0,0 +1,2120 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "contact_solver.h" + +#include "body.h" +#include "constraint_graph.h" +#include "contact.h" +#include "core.h" +#include "solver_set.h" +#include "world.h" + +#include + +// contact separation for sub-stepping +// s = s0 + dot(cB + rB - cA - rA, normal) +// normal is held constant +// body positions c can translation and anchors r can rotate +// s(t) = s0 + dot(cB(t) + rB(t) - cA(t) - rA(t), normal) +// s(t) = s0 + dot(cB0 + dpB + rot(dqB, rB0) - cA0 - dpA - rot(dqA, rA0), normal) +// s(t) = s0 + dot(cB0 - cA0, normal) + dot(dpB - dpA + rot(dqB, rB0) - rot(dqA, rA0), normal) +// s_base = s0 + dot(cB0 - cA0, normal) + +void b2PrepareOverflowContacts( b2StepContext* context ) +{ + b2TracyCZoneNC( prepare_overflow_contact, "Prepare Overflow Contact", b2_colorYellow, true ); + + b2World* world = context->world; + b2ConstraintGraph* graph = context->graph; + b2GraphColor* color = graph->colors + B2_OVERFLOW_INDEX; + b2ContactConstraint* constraints = color->overflowConstraints; + int contactCount = color->contactSims.count; + b2ContactSim* contacts = color->contactSims.data; + b2BodyState* awakeStates = context->states; + +#if B2_VALIDATE + b2Body* bodies = world->bodies.data; +#endif + + // Stiffer for static contacts to avoid bodies getting pushed through the ground + b2Softness contactSoftness = context->contactSoftness; + b2Softness staticSoftness = context->staticSoftness; + + float warmStartScale = world->enableWarmStarting ? 1.0f : 0.0f; + + for ( int i = 0; i < contactCount; ++i ) + { + b2ContactSim* contactSim = contacts + i; + + const b2Manifold* manifold = &contactSim->manifold; + int pointCount = manifold->pointCount; + + B2_ASSERT( 0 < pointCount && pointCount <= 2 ); + + int indexA = contactSim->bodySimIndexA; + int indexB = contactSim->bodySimIndexB; + +#if B2_VALIDATE + b2Body* bodyA = bodies + contactSim->bodyIdA; + int validIndexA = bodyA->setIndex == b2_awakeSet ? bodyA->localIndex : B2_NULL_INDEX; + B2_ASSERT( indexA == validIndexA ); + + b2Body* bodyB = bodies + contactSim->bodyIdB; + int validIndexB = bodyB->setIndex == b2_awakeSet ? bodyB->localIndex : B2_NULL_INDEX; + B2_ASSERT( indexB == validIndexB ); +#endif + + b2ContactConstraint* constraint = constraints + i; + constraint->indexA = indexA; + constraint->indexB = indexB; + constraint->normal = manifold->normal; + constraint->friction = contactSim->friction; + constraint->restitution = contactSim->restitution; + constraint->rollingResistance = contactSim->rollingResistance; + constraint->rollingImpulse = warmStartScale * manifold->rollingImpulse; + constraint->tangentSpeed = contactSim->tangentSpeed; + constraint->pointCount = pointCount; + + b2Vec2 vA = b2Vec2_zero; + float wA = 0.0f; + float mA = contactSim->invMassA; + float iA = contactSim->invIA; + if ( indexA != B2_NULL_INDEX ) + { + b2BodyState* stateA = awakeStates + indexA; + vA = stateA->linearVelocity; + wA = stateA->angularVelocity; + } + + b2Vec2 vB = b2Vec2_zero; + float wB = 0.0f; + float mB = contactSim->invMassB; + float iB = contactSim->invIB; + if ( indexB != B2_NULL_INDEX ) + { + b2BodyState* stateB = awakeStates + indexB; + vB = stateB->linearVelocity; + wB = stateB->angularVelocity; + } + + if ( indexA == B2_NULL_INDEX || indexB == B2_NULL_INDEX ) + { + constraint->softness = staticSoftness; + } + else + { + constraint->softness = contactSoftness; + } + + // copy mass into constraint to avoid cache misses during sub-stepping + constraint->invMassA = mA; + constraint->invIA = iA; + constraint->invMassB = mB; + constraint->invIB = iB; + + { + float k = iA + iB; + constraint->rollingMass = k > 0.0f ? 1.0f / k : 0.0f; + } + + b2Vec2 normal = constraint->normal; + b2Vec2 tangent = b2RightPerp( constraint->normal ); + + for ( int j = 0; j < pointCount; ++j ) + { + const b2ManifoldPoint* mp = manifold->points + j; + b2ContactConstraintPoint* cp = constraint->points + j; + + cp->normalImpulse = warmStartScale * mp->normalImpulse; + cp->tangentImpulse = warmStartScale * mp->tangentImpulse; + cp->totalNormalImpulse = 0.0f; + + b2Vec2 rA = mp->anchorA; + b2Vec2 rB = mp->anchorB; + + cp->anchorA = rA; + cp->anchorB = rB; + cp->baseSeparation = mp->separation - b2Dot( b2Sub( rB, rA ), normal ); + + float rnA = b2Cross( rA, normal ); + float rnB = b2Cross( rB, normal ); + float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + cp->normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f; + + float rtA = b2Cross( rA, tangent ); + float rtB = b2Cross( rB, tangent ); + float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + cp->tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f; + + // Save relative velocity for restitution + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + cp->relativeVelocity = b2Dot( normal, b2Sub( vrB, vrA ) ); + } + } + + b2TracyCZoneEnd( prepare_overflow_contact ); +} + +void b2WarmStartOverflowContacts( b2StepContext* context ) +{ + b2TracyCZoneNC( warmstart_overflow_contact, "WarmStart Overflow Contact", b2_colorDarkOrange, true ); + + b2ConstraintGraph* graph = context->graph; + b2GraphColor* color = graph->colors + B2_OVERFLOW_INDEX; + b2ContactConstraint* constraints = color->overflowConstraints; + int contactCount = color->contactSims.count; + b2World* world = context->world; + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* states = awakeSet->bodyStates.data; + + // This is a dummy state to represent a static body because static bodies don't have a solver body. + b2BodyState dummyState = b2_identityBodyState; + + for ( int i = 0; i < contactCount; ++i ) + { + const b2ContactConstraint* constraint = constraints + i; + + int indexA = constraint->indexA; + int indexB = constraint->indexB; + + b2BodyState* stateA = indexA == B2_NULL_INDEX ? &dummyState : states + indexA; + b2BodyState* stateB = indexB == B2_NULL_INDEX ? &dummyState : states + indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + float mA = constraint->invMassA; + float iA = constraint->invIA; + float mB = constraint->invMassB; + float iB = constraint->invIB; + + // Stiffer for static contacts to avoid bodies getting pushed through the ground + b2Vec2 normal = constraint->normal; + b2Vec2 tangent = b2RightPerp( constraint->normal ); + int pointCount = constraint->pointCount; + + for ( int j = 0; j < pointCount; ++j ) + { + const b2ContactConstraintPoint* cp = constraint->points + j; + + // fixed anchors + b2Vec2 rA = cp->anchorA; + b2Vec2 rB = cp->anchorB; + + b2Vec2 P = b2Add( b2MulSV( cp->normalImpulse, normal ), b2MulSV( cp->tangentImpulse, tangent ) ); + wA -= iA * b2Cross( rA, P ); + vA = b2MulAdd( vA, -mA, P ); + wB += iB * b2Cross( rB, P ); + vB = b2MulAdd( vB, mB, P ); + } + + wA -= iA * constraint->rollingImpulse; + wB += iB * constraint->rollingImpulse; + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; + } + + b2TracyCZoneEnd( warmstart_overflow_contact ); +} + +void b2SolveOverflowContacts( b2StepContext* context, bool useBias ) +{ + b2TracyCZoneNC( solve_contact, "Solve Contact", b2_colorAliceBlue, true ); + + b2ConstraintGraph* graph = context->graph; + b2GraphColor* color = graph->colors + B2_OVERFLOW_INDEX; + b2ContactConstraint* constraints = color->overflowConstraints; + int contactCount = color->contactSims.count; + b2World* world = context->world; + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* states = awakeSet->bodyStates.data; + + float inv_h = context->inv_h; + const float pushout = context->world->maxContactPushSpeed; + + // This is a dummy body to represent a static body since static bodies don't have a solver body. + b2BodyState dummyState = b2_identityBodyState; + + for ( int i = 0; i < contactCount; ++i ) + { + b2ContactConstraint* constraint = constraints + i; + float mA = constraint->invMassA; + float iA = constraint->invIA; + float mB = constraint->invMassB; + float iB = constraint->invIB; + + b2BodyState* stateA = constraint->indexA == B2_NULL_INDEX ? &dummyState : states + constraint->indexA; + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Rot dqA = stateA->deltaRotation; + + b2BodyState* stateB = constraint->indexB == B2_NULL_INDEX ? &dummyState : states + constraint->indexB; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + b2Rot dqB = stateB->deltaRotation; + + b2Vec2 dp = b2Sub( stateB->deltaPosition, stateA->deltaPosition ); + + b2Vec2 normal = constraint->normal; + b2Vec2 tangent = b2RightPerp( normal ); + float friction = constraint->friction; + b2Softness softness = constraint->softness; + + int pointCount = constraint->pointCount; + float totalNormalImpulse = 0.0f; + + // Non-penetration + for ( int j = 0; j < pointCount; ++j ) + { + b2ContactConstraintPoint* cp = constraint->points + j; + + // fixed anchor points + b2Vec2 rA = cp->anchorA; + b2Vec2 rB = cp->anchorB; + + // compute current separation + // this is subject to round-off error if the anchor is far from the body center of mass + b2Vec2 ds = b2Add( dp, b2Sub( b2RotateVector( dqB, rB ), b2RotateVector( dqA, rA ) ) ); + float s = cp->baseSeparation + b2Dot( ds, normal ); + + float velocityBias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( s > 0.0f ) + { + // speculative bias + velocityBias = s * inv_h; + } + else if ( useBias ) + { + velocityBias = b2MaxFloat( softness.biasRate * s, -pushout ); + massScale = softness.massScale; + impulseScale = softness.impulseScale; + } + + // relative normal velocity at contact + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + float vn = b2Dot( b2Sub( vrB, vrA ), normal ); + + // incremental normal impulse + float impulse = -cp->normalMass * massScale * ( vn + velocityBias ) - impulseScale * cp->normalImpulse; + + // clamp the accumulated impulse + float newImpulse = b2MaxFloat( cp->normalImpulse + impulse, 0.0f ); + impulse = newImpulse - cp->normalImpulse; + cp->normalImpulse = newImpulse; + cp->totalNormalImpulse += newImpulse; + totalNormalImpulse += newImpulse; + + // apply normal impulse + b2Vec2 P = b2MulSV( impulse, normal ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + + // Friction + for ( int j = 0; j < pointCount; ++j ) + { + b2ContactConstraintPoint* cp = constraint->points + j; + + // fixed anchor points + b2Vec2 rA = cp->anchorA; + b2Vec2 rB = cp->anchorB; + + // relative tangent velocity at contact + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + + // vt = dot(vrB - sB * tangent - (vrA + sA * tangent), tangent) + // = dot(vrB - vrA, tangent) - (sA + sB) + + float vt = b2Dot( b2Sub( vrB, vrA ), tangent ) - constraint->tangentSpeed; + + // incremental tangent impulse + float impulse = cp->tangentMass * ( -vt ); + + // clamp the accumulated force + float maxFriction = friction * cp->normalImpulse; + float newImpulse = b2ClampFloat( cp->tangentImpulse + impulse, -maxFriction, maxFriction ); + impulse = newImpulse - cp->tangentImpulse; + cp->tangentImpulse = newImpulse; + + // apply tangent impulse + b2Vec2 P = b2MulSV( impulse, tangent ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + + // Rolling resistance + { + float deltaLambda = -constraint->rollingMass * ( wB - wA ); + float lambda = constraint->rollingImpulse; + float maxLambda = constraint->rollingResistance * totalNormalImpulse; + constraint->rollingImpulse = b2ClampFloat( lambda + deltaLambda, -maxLambda, maxLambda ); + deltaLambda = constraint->rollingImpulse - lambda; + + wA -= iA * deltaLambda; + wB += iB * deltaLambda; + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; + } + + b2TracyCZoneEnd( solve_contact ); +} + +void b2ApplyOverflowRestitution( b2StepContext* context ) +{ + b2TracyCZoneNC( overflow_resitution, "Overflow Restitution", b2_colorViolet, true ); + + b2ConstraintGraph* graph = context->graph; + b2GraphColor* color = graph->colors + B2_OVERFLOW_INDEX; + b2ContactConstraint* constraints = color->overflowConstraints; + int contactCount = color->contactSims.count; + b2World* world = context->world; + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* states = awakeSet->bodyStates.data; + + float threshold = context->world->restitutionThreshold; + + // dummy state to represent a static body + b2BodyState dummyState = b2_identityBodyState; + + for ( int i = 0; i < contactCount; ++i ) + { + b2ContactConstraint* constraint = constraints + i; + + float restitution = constraint->restitution; + if ( restitution == 0.0f ) + { + continue; + } + + float mA = constraint->invMassA; + float iA = constraint->invIA; + float mB = constraint->invMassB; + float iB = constraint->invIB; + + b2BodyState* stateA = constraint->indexA == B2_NULL_INDEX ? &dummyState : states + constraint->indexA; + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + + b2BodyState* stateB = constraint->indexB == B2_NULL_INDEX ? &dummyState : states + constraint->indexB; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + b2Vec2 normal = constraint->normal; + int pointCount = constraint->pointCount; + + // it is possible to get more accurate restitution by iterating + // this only makes a difference if there are two contact points + // for (int iter = 0; iter < 10; ++iter) + { + for ( int j = 0; j < pointCount; ++j ) + { + b2ContactConstraintPoint* cp = constraint->points + j; + + // if the normal impulse is zero then there was no collision + // this skips speculative contact points that didn't generate an impulse + // The max normal impulse is used in case there was a collision that moved away within the sub-step process + if ( cp->relativeVelocity > -threshold || cp->totalNormalImpulse == 0.0f ) + { + continue; + } + + // fixed anchor points + b2Vec2 rA = cp->anchorA; + b2Vec2 rB = cp->anchorB; + + // relative normal velocity at contact + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + float vn = b2Dot( b2Sub( vrB, vrA ), normal ); + + // compute normal impulse + float impulse = -cp->normalMass * ( vn + restitution * cp->relativeVelocity ); + + // clamp the accumulated impulse + // todo should this be stored? + float newImpulse = b2MaxFloat( cp->normalImpulse + impulse, 0.0f ); + impulse = newImpulse - cp->normalImpulse; + cp->normalImpulse = newImpulse; + + // Add the incremental impulse rather than the full impulse because this is not a sub-step + cp->totalNormalImpulse += impulse; + + // apply contact impulse + b2Vec2 P = b2MulSV( impulse, normal ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; + } + + b2TracyCZoneEnd( overflow_resitution ); +} + +void b2StoreOverflowImpulses( b2StepContext* context ) +{ + b2TracyCZoneNC( store_impulses, "Store", b2_colorFireBrick, true ); + + b2ConstraintGraph* graph = context->graph; + b2GraphColor* color = graph->colors + B2_OVERFLOW_INDEX; + b2ContactConstraint* constraints = color->overflowConstraints; + b2ContactSim* contacts = color->contactSims.data; + int contactCount = color->contactSims.count; + + for ( int i = 0; i < contactCount; ++i ) + { + const b2ContactConstraint* constraint = constraints + i; + b2ContactSim* contact = contacts + i; + b2Manifold* manifold = &contact->manifold; + int pointCount = manifold->pointCount; + + for ( int j = 0; j < pointCount; ++j ) + { + manifold->points[j].normalImpulse = constraint->points[j].normalImpulse; + manifold->points[j].tangentImpulse = constraint->points[j].tangentImpulse; + manifold->points[j].totalNormalImpulse = constraint->points[j].totalNormalImpulse; + manifold->points[j].normalVelocity = constraint->points[j].relativeVelocity; + } + + manifold->rollingImpulse = constraint->rollingImpulse; + } + + b2TracyCZoneEnd( store_impulses ); +} + +#if defined( B2_SIMD_AVX2 ) + +#include + +// wide float holds 8 numbers +typedef __m256 b2FloatW; + +#elif defined( B2_SIMD_NEON ) + +#include + +// wide float holds 4 numbers +typedef float32x4_t b2FloatW; + +#elif defined( B2_SIMD_SSE2 ) + +#include + +// wide float holds 4 numbers +typedef __m128 b2FloatW; + +#else + +// scalar math +typedef struct b2FloatW +{ + float x, y, z, w; +} b2FloatW; + +#endif + +// Wide vec2 +typedef struct b2Vec2W +{ + b2FloatW X, Y; +} b2Vec2W; + +// Wide rotation +typedef struct b2RotW +{ + b2FloatW C, S; +} b2RotW; + +#if defined( B2_SIMD_AVX2 ) + +static inline b2FloatW b2ZeroW( void ) +{ + return _mm256_setzero_ps(); +} + +static inline b2FloatW b2SplatW( float scalar ) +{ + return _mm256_set1_ps( scalar ); +} + +static inline b2FloatW b2AddW( b2FloatW a, b2FloatW b ) +{ + return _mm256_add_ps( a, b ); +} + +static inline b2FloatW b2SubW( b2FloatW a, b2FloatW b ) +{ + return _mm256_sub_ps( a, b ); +} + +static inline b2FloatW b2MulW( b2FloatW a, b2FloatW b ) +{ + return _mm256_mul_ps( a, b ); +} + +static inline b2FloatW b2MulAddW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + // FMA can be emulated: https://github.com/lattera/glibc/blob/master/sysdeps/ieee754/dbl-64/s_fmaf.c#L34 + // return _mm256_fmadd_ps( b, c, a ); + return _mm256_add_ps( _mm256_mul_ps( b, c ), a ); +} + +static inline b2FloatW b2MulSubW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + // return _mm256_fnmadd_ps(b, c, a); + return _mm256_sub_ps( a, _mm256_mul_ps( b, c ) ); +} + +static inline b2FloatW b2MinW( b2FloatW a, b2FloatW b ) +{ + return _mm256_min_ps( a, b ); +} + +static inline b2FloatW b2MaxW( b2FloatW a, b2FloatW b ) +{ + return _mm256_max_ps( a, b ); +} + +// a = clamp(a, -b, b) +static inline b2FloatW b2SymClampW( b2FloatW a, b2FloatW b ) +{ + b2FloatW nb = _mm256_sub_ps( _mm256_setzero_ps(), b ); + return _mm256_max_ps( nb, _mm256_min_ps( a, b ) ); +} + +static inline b2FloatW b2OrW( b2FloatW a, b2FloatW b ) +{ + return _mm256_or_ps( a, b ); +} + +static inline b2FloatW b2GreaterThanW( b2FloatW a, b2FloatW b ) +{ + return _mm256_cmp_ps( a, b, _CMP_GT_OQ ); +} + +static inline b2FloatW b2EqualsW( b2FloatW a, b2FloatW b ) +{ + return _mm256_cmp_ps( a, b, _CMP_EQ_OQ ); +} + +static inline bool b2AllZeroW( b2FloatW a ) +{ + // Compare each element with zero + b2FloatW zero = _mm256_setzero_ps(); + b2FloatW cmp = _mm256_cmp_ps( a, zero, _CMP_EQ_OQ ); + + // Create a mask from the comparison results + int mask = _mm256_movemask_ps( cmp ); + + // If all elements are zero, the mask will be 0xFF (11111111 in binary) + return mask == 0xFF; +} + +// component-wise returns mask ? b : a +static inline b2FloatW b2BlendW( b2FloatW a, b2FloatW b, b2FloatW mask ) +{ + return _mm256_blendv_ps( a, b, mask ); +} + +#elif defined( B2_SIMD_NEON ) + +static inline b2FloatW b2ZeroW( void ) +{ + return vdupq_n_f32( 0.0f ); +} + +static inline b2FloatW b2SplatW( float scalar ) +{ + return vdupq_n_f32( scalar ); +} + +static inline b2FloatW b2SetW( float a, float b, float c, float d ) +{ + float32_t array[4] = { a, b, c, d }; + return vld1q_f32( array ); +} + +static inline b2FloatW b2AddW( b2FloatW a, b2FloatW b ) +{ + return vaddq_f32( a, b ); +} + +static inline b2FloatW b2SubW( b2FloatW a, b2FloatW b ) +{ + return vsubq_f32( a, b ); +} + +static inline b2FloatW b2MulW( b2FloatW a, b2FloatW b ) +{ + return vmulq_f32( a, b ); +} + +static inline b2FloatW b2MulAddW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return vmlaq_f32( a, b, c ); +} + +static inline b2FloatW b2MulSubW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return vmlsq_f32( a, b, c ); +} + +static inline b2FloatW b2MinW( b2FloatW a, b2FloatW b ) +{ + return vminq_f32( a, b ); +} + +static inline b2FloatW b2MaxW( b2FloatW a, b2FloatW b ) +{ + return vmaxq_f32( a, b ); +} + +// a = clamp(a, -b, b) +static inline b2FloatW b2SymClampW( b2FloatW a, b2FloatW b ) +{ + b2FloatW nb = vnegq_f32( b ); + return vmaxq_f32( nb, vminq_f32( a, b ) ); +} + +static inline b2FloatW b2OrW( b2FloatW a, b2FloatW b ) +{ + return vreinterpretq_f32_u32( vorrq_u32( vreinterpretq_u32_f32( a ), vreinterpretq_u32_f32( b ) ) ); +} + +static inline b2FloatW b2GreaterThanW( b2FloatW a, b2FloatW b ) +{ + return vreinterpretq_f32_u32( vcgtq_f32( a, b ) ); +} + +static inline b2FloatW b2EqualsW( b2FloatW a, b2FloatW b ) +{ + return vreinterpretq_f32_u32( vceqq_f32( a, b ) ); +} + +static inline bool b2AllZeroW( b2FloatW a ) +{ + // Create a zero vector for comparison + b2FloatW zero = vdupq_n_f32( 0.0f ); + + // Compare the input vector with zero + uint32x4_t cmp_result = vceqq_f32( a, zero ); + +// Check if all comparison results are non-zero using vminvq +#ifdef __ARM_FEATURE_SVE + // ARM v8.2+ has horizontal minimum instruction + return vminvq_u32( cmp_result ) != 0; +#else + // For older ARM architectures, we need to manually check all lanes + return vgetq_lane_u32( cmp_result, 0 ) != 0 && vgetq_lane_u32( cmp_result, 1 ) != 0 && vgetq_lane_u32( cmp_result, 2 ) != 0 && + vgetq_lane_u32( cmp_result, 3 ) != 0; +#endif +} + +// component-wise returns mask ? b : a +static inline b2FloatW b2BlendW( b2FloatW a, b2FloatW b, b2FloatW mask ) +{ + uint32x4_t mask32 = vreinterpretq_u32_f32( mask ); + return vbslq_f32( mask32, b, a ); +} + +static inline b2FloatW b2LoadW( const float32_t* data ) +{ + return vld1q_f32( data ); +} + +static inline void b2StoreW( float32_t* data, b2FloatW a ) +{ + vst1q_f32( data, a ); +} + +static inline b2FloatW b2UnpackLoW( b2FloatW a, b2FloatW b ) +{ +#if defined( __aarch64__ ) + return vzip1q_f32( a, b ); +#else + float32x2_t a1 = vget_low_f32( a ); + float32x2_t b1 = vget_low_f32( b ); + float32x2x2_t result = vzip_f32( a1, b1 ); + return vcombine_f32( result.val[0], result.val[1] ); +#endif +} + +static inline b2FloatW b2UnpackHiW( b2FloatW a, b2FloatW b ) +{ +#if defined( __aarch64__ ) + return vzip2q_f32( a, b ); +#else + float32x2_t a1 = vget_high_f32( a ); + float32x2_t b1 = vget_high_f32( b ); + float32x2x2_t result = vzip_f32( a1, b1 ); + return vcombine_f32( result.val[0], result.val[1] ); +#endif +} + +#elif defined( B2_SIMD_SSE2 ) + +static inline b2FloatW b2ZeroW( void ) +{ + return _mm_setzero_ps(); +} + +static inline b2FloatW b2SplatW( float scalar ) +{ + return _mm_set1_ps( scalar ); +} + +static inline b2FloatW b2SetW( float a, float b, float c, float d ) +{ + return _mm_setr_ps( a, b, c, d ); +} + +static inline b2FloatW b2AddW( b2FloatW a, b2FloatW b ) +{ + return _mm_add_ps( a, b ); +} + +static inline b2FloatW b2SubW( b2FloatW a, b2FloatW b ) +{ + return _mm_sub_ps( a, b ); +} + +static inline b2FloatW b2MulW( b2FloatW a, b2FloatW b ) +{ + return _mm_mul_ps( a, b ); +} + +static inline b2FloatW b2MulAddW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return _mm_add_ps( a, _mm_mul_ps( b, c ) ); +} + +static inline b2FloatW b2MulSubW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return _mm_sub_ps( a, _mm_mul_ps( b, c ) ); +} + +static inline b2FloatW b2MinW( b2FloatW a, b2FloatW b ) +{ + return _mm_min_ps( a, b ); +} + +static inline b2FloatW b2MaxW( b2FloatW a, b2FloatW b ) +{ + return _mm_max_ps( a, b ); +} + +// a = clamp(a, -b, b) +static inline b2FloatW b2SymClampW( b2FloatW a, b2FloatW b ) +{ + // Create a mask with the sign bit set for each element + __m128 mask = _mm_set1_ps( -0.0f ); + + // XOR the input with the mask to negate each element + __m128 nb = _mm_xor_ps( b, mask ); + + return _mm_max_ps( nb, _mm_min_ps( a, b ) ); +} + +static inline b2FloatW b2OrW( b2FloatW a, b2FloatW b ) +{ + return _mm_or_ps( a, b ); +} + +static inline b2FloatW b2GreaterThanW( b2FloatW a, b2FloatW b ) +{ + return _mm_cmpgt_ps( a, b ); +} + +static inline b2FloatW b2EqualsW( b2FloatW a, b2FloatW b ) +{ + return _mm_cmpeq_ps( a, b ); +} + +static inline bool b2AllZeroW( b2FloatW a ) +{ + // Compare each element with zero + b2FloatW zero = _mm_setzero_ps(); + b2FloatW cmp = _mm_cmpeq_ps( a, zero ); + + // Create a mask from the comparison results + int mask = _mm_movemask_ps( cmp ); + + // If all elements are zero, the mask will be 0xF (1111 in binary) + return mask == 0xF; +} + +// component-wise returns mask ? b : a +static inline b2FloatW b2BlendW( b2FloatW a, b2FloatW b, b2FloatW mask ) +{ + return _mm_or_ps( _mm_and_ps( mask, b ), _mm_andnot_ps( mask, a ) ); +} + +static inline b2FloatW b2LoadW( const float* data ) +{ + return _mm_load_ps( data ); +} + +static inline void b2StoreW( float* data, b2FloatW a ) +{ + _mm_store_ps( data, a ); +} + +static inline b2FloatW b2UnpackLoW( b2FloatW a, b2FloatW b ) +{ + return _mm_unpacklo_ps( a, b ); +} + +static inline b2FloatW b2UnpackHiW( b2FloatW a, b2FloatW b ) +{ + return _mm_unpackhi_ps( a, b ); +} + +#else + +static inline b2FloatW b2ZeroW( void ) +{ + return (b2FloatW){ 0.0f, 0.0f, 0.0f, 0.0f }; +} + +static inline b2FloatW b2SplatW( float scalar ) +{ + return (b2FloatW){ scalar, scalar, scalar, scalar }; +} + +static inline b2FloatW b2AddW( b2FloatW a, b2FloatW b ) +{ + return (b2FloatW){ a.x + b.x, a.y + b.y, a.z + b.z, a.w + b.w }; +} + +static inline b2FloatW b2SubW( b2FloatW a, b2FloatW b ) +{ + return (b2FloatW){ a.x - b.x, a.y - b.y, a.z - b.z, a.w - b.w }; +} + +static inline b2FloatW b2MulW( b2FloatW a, b2FloatW b ) +{ + return (b2FloatW){ a.x * b.x, a.y * b.y, a.z * b.z, a.w * b.w }; +} + +static inline b2FloatW b2MulAddW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return (b2FloatW){ a.x + b.x * c.x, a.y + b.y * c.y, a.z + b.z * c.z, a.w + b.w * c.w }; +} + +static inline b2FloatW b2MulSubW( b2FloatW a, b2FloatW b, b2FloatW c ) +{ + return (b2FloatW){ a.x - b.x * c.x, a.y - b.y * c.y, a.z - b.z * c.z, a.w - b.w * c.w }; +} + +static inline b2FloatW b2MinW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = a.x <= b.x ? a.x : b.x; + r.y = a.y <= b.y ? a.y : b.y; + r.z = a.z <= b.z ? a.z : b.z; + r.w = a.w <= b.w ? a.w : b.w; + return r; +} + +static inline b2FloatW b2MaxW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = a.x >= b.x ? a.x : b.x; + r.y = a.y >= b.y ? a.y : b.y; + r.z = a.z >= b.z ? a.z : b.z; + r.w = a.w >= b.w ? a.w : b.w; + return r; +} + +// a = clamp(a, -b, b) +static inline b2FloatW b2SymClampW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = b2ClampFloat( a.x, -b.x, b.x ); + r.y = b2ClampFloat( a.y, -b.y, b.y ); + r.z = b2ClampFloat( a.z, -b.z, b.z ); + r.w = b2ClampFloat( a.w, -b.w, b.w ); + return r; +} + +static inline b2FloatW b2OrW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = a.x != 0.0f || b.x != 0.0f ? 1.0f : 0.0f; + r.y = a.y != 0.0f || b.y != 0.0f ? 1.0f : 0.0f; + r.z = a.z != 0.0f || b.z != 0.0f ? 1.0f : 0.0f; + r.w = a.w != 0.0f || b.w != 0.0f ? 1.0f : 0.0f; + return r; +} + +static inline b2FloatW b2GreaterThanW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = a.x > b.x ? 1.0f : 0.0f; + r.y = a.y > b.y ? 1.0f : 0.0f; + r.z = a.z > b.z ? 1.0f : 0.0f; + r.w = a.w > b.w ? 1.0f : 0.0f; + return r; +} + +static inline b2FloatW b2EqualsW( b2FloatW a, b2FloatW b ) +{ + b2FloatW r; + r.x = a.x == b.x ? 1.0f : 0.0f; + r.y = a.y == b.y ? 1.0f : 0.0f; + r.z = a.z == b.z ? 1.0f : 0.0f; + r.w = a.w == b.w ? 1.0f : 0.0f; + return r; +} + +static inline bool b2AllZeroW( b2FloatW a ) +{ + return a.x == 0.0f && a.y == 0.0f && a.z == 0.0f && a.w == 0.0f; +} + +// component-wise returns mask ? b : a +static inline b2FloatW b2BlendW( b2FloatW a, b2FloatW b, b2FloatW mask ) +{ + b2FloatW r; + r.x = mask.x != 0.0f ? b.x : a.x; + r.y = mask.y != 0.0f ? b.y : a.y; + r.z = mask.z != 0.0f ? b.z : a.z; + r.w = mask.w != 0.0f ? b.w : a.w; + return r; +} + +#endif + +static inline b2FloatW b2DotW( b2Vec2W a, b2Vec2W b ) +{ + return b2AddW( b2MulW( a.X, b.X ), b2MulW( a.Y, b.Y ) ); +} + +static inline b2FloatW b2CrossW( b2Vec2W a, b2Vec2W b ) +{ + return b2SubW( b2MulW( a.X, b.Y ), b2MulW( a.Y, b.X ) ); +} + +static inline b2Vec2W b2RotateVectorW( b2RotW q, b2Vec2W v ) +{ + return (b2Vec2W){ b2SubW( b2MulW( q.C, v.X ), b2MulW( q.S, v.Y ) ), b2AddW( b2MulW( q.S, v.X ), b2MulW( q.C, v.Y ) ) }; +} + +// Soft contact constraints with sub-stepping support +// Uses fixed anchors for Jacobians for better behavior on rolling shapes (circles & capsules) +// http://mmacklin.com/smallsteps.pdf +// https://box2d.org/files/ErinCatto_SoftConstraints_GDC2011.pdf + +typedef struct b2ContactConstraintSIMD +{ + int indexA[B2_SIMD_WIDTH]; + int indexB[B2_SIMD_WIDTH]; + + b2FloatW invMassA, invMassB; + b2FloatW invIA, invIB; + b2Vec2W normal; + b2FloatW friction; + b2FloatW tangentSpeed; + b2FloatW rollingResistance; + b2FloatW rollingMass; + b2FloatW rollingImpulse; + b2FloatW biasRate; + b2FloatW massScale; + b2FloatW impulseScale; + b2Vec2W anchorA1, anchorB1; + b2FloatW normalMass1, tangentMass1; + b2FloatW baseSeparation1; + b2FloatW normalImpulse1; + b2FloatW totalNormalImpulse1; + b2FloatW tangentImpulse1; + b2Vec2W anchorA2, anchorB2; + b2FloatW baseSeparation2; + b2FloatW normalImpulse2; + b2FloatW totalNormalImpulse2; + b2FloatW tangentImpulse2; + b2FloatW normalMass2, tangentMass2; + b2FloatW restitution; + b2FloatW relativeVelocity1, relativeVelocity2; +} b2ContactConstraintSIMD; + +int b2GetContactConstraintSIMDByteCount( void ) +{ + return sizeof( b2ContactConstraintSIMD ); +} + +// wide version of b2BodyState +typedef struct b2BodyStateW +{ + b2Vec2W v; + b2FloatW w; + b2FloatW flags; + b2Vec2W dp; + b2RotW dq; +} b2BodyStateW; + +// Custom gather/scatter for each SIMD type +#if defined( B2_SIMD_AVX2 ) + +// This is a load and 8x8 transpose +static b2BodyStateW b2GatherBodies( const b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + // b2BodyState b2_identityBodyState = {{0.0f, 0.0f}, 0.0f, 0, {0.0f, 0.0f}, {1.0f, 0.0f}}; + b2FloatW identity = _mm256_setr_ps( 0.0f, 0.0f, 0.0f, 0, 0.0f, 0.0f, 1.0f, 0.0f ); + b2FloatW b0 = indices[0] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[0] ) ); + b2FloatW b1 = indices[1] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[1] ) ); + b2FloatW b2 = indices[2] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[2] ) ); + b2FloatW b3 = indices[3] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[3] ) ); + b2FloatW b4 = indices[4] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[4] ) ); + b2FloatW b5 = indices[5] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[5] ) ); + b2FloatW b6 = indices[6] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[6] ) ); + b2FloatW b7 = indices[7] == B2_NULL_INDEX ? identity : _mm256_load_ps( (float*)( states + indices[7] ) ); + + b2FloatW t0 = _mm256_unpacklo_ps( b0, b1 ); + b2FloatW t1 = _mm256_unpackhi_ps( b0, b1 ); + b2FloatW t2 = _mm256_unpacklo_ps( b2, b3 ); + b2FloatW t3 = _mm256_unpackhi_ps( b2, b3 ); + b2FloatW t4 = _mm256_unpacklo_ps( b4, b5 ); + b2FloatW t5 = _mm256_unpackhi_ps( b4, b5 ); + b2FloatW t6 = _mm256_unpacklo_ps( b6, b7 ); + b2FloatW t7 = _mm256_unpackhi_ps( b6, b7 ); + b2FloatW tt0 = _mm256_shuffle_ps( t0, t2, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt1 = _mm256_shuffle_ps( t0, t2, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt2 = _mm256_shuffle_ps( t1, t3, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt3 = _mm256_shuffle_ps( t1, t3, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt4 = _mm256_shuffle_ps( t4, t6, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt5 = _mm256_shuffle_ps( t4, t6, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt6 = _mm256_shuffle_ps( t5, t7, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt7 = _mm256_shuffle_ps( t5, t7, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + + b2BodyStateW simdBody; + simdBody.v.X = _mm256_permute2f128_ps( tt0, tt4, 0x20 ); + simdBody.v.Y = _mm256_permute2f128_ps( tt1, tt5, 0x20 ); + simdBody.w = _mm256_permute2f128_ps( tt2, tt6, 0x20 ); + simdBody.flags = _mm256_permute2f128_ps( tt3, tt7, 0x20 ); + simdBody.dp.X = _mm256_permute2f128_ps( tt0, tt4, 0x31 ); + simdBody.dp.Y = _mm256_permute2f128_ps( tt1, tt5, 0x31 ); + simdBody.dq.C = _mm256_permute2f128_ps( tt2, tt6, 0x31 ); + simdBody.dq.S = _mm256_permute2f128_ps( tt3, tt7, 0x31 ); + return simdBody; +} + +// This writes everything back to the solver bodies but only the velocities change +static void b2ScatterBodies( b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices, const b2BodyStateW* B2_RESTRICT simdBody ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + b2FloatW t0 = _mm256_unpacklo_ps( simdBody->v.X, simdBody->v.Y ); + b2FloatW t1 = _mm256_unpackhi_ps( simdBody->v.X, simdBody->v.Y ); + b2FloatW t2 = _mm256_unpacklo_ps( simdBody->w, simdBody->flags ); + b2FloatW t3 = _mm256_unpackhi_ps( simdBody->w, simdBody->flags ); + b2FloatW t4 = _mm256_unpacklo_ps( simdBody->dp.X, simdBody->dp.Y ); + b2FloatW t5 = _mm256_unpackhi_ps( simdBody->dp.X, simdBody->dp.Y ); + b2FloatW t6 = _mm256_unpacklo_ps( simdBody->dq.C, simdBody->dq.S ); + b2FloatW t7 = _mm256_unpackhi_ps( simdBody->dq.C, simdBody->dq.S ); + b2FloatW tt0 = _mm256_shuffle_ps( t0, t2, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt1 = _mm256_shuffle_ps( t0, t2, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt2 = _mm256_shuffle_ps( t1, t3, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt3 = _mm256_shuffle_ps( t1, t3, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt4 = _mm256_shuffle_ps( t4, t6, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt5 = _mm256_shuffle_ps( t4, t6, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + b2FloatW tt6 = _mm256_shuffle_ps( t5, t7, _MM_SHUFFLE( 1, 0, 1, 0 ) ); + b2FloatW tt7 = _mm256_shuffle_ps( t5, t7, _MM_SHUFFLE( 3, 2, 3, 2 ) ); + + // I don't use any dummy body in the body array because this will lead to multithreaded sharing and the + // associated cache flushing. + if ( indices[0] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[0] ), _mm256_permute2f128_ps( tt0, tt4, 0x20 ) ); + if ( indices[1] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[1] ), _mm256_permute2f128_ps( tt1, tt5, 0x20 ) ); + if ( indices[2] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[2] ), _mm256_permute2f128_ps( tt2, tt6, 0x20 ) ); + if ( indices[3] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[3] ), _mm256_permute2f128_ps( tt3, tt7, 0x20 ) ); + if ( indices[4] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[4] ), _mm256_permute2f128_ps( tt0, tt4, 0x31 ) ); + if ( indices[5] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[5] ), _mm256_permute2f128_ps( tt1, tt5, 0x31 ) ); + if ( indices[6] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[6] ), _mm256_permute2f128_ps( tt2, tt6, 0x31 ) ); + if ( indices[7] != B2_NULL_INDEX ) + _mm256_store_ps( (float*)( states + indices[7] ), _mm256_permute2f128_ps( tt3, tt7, 0x31 ) ); +} + +#elif defined( B2_SIMD_NEON ) + +// This is a load and transpose +static b2BodyStateW b2GatherBodies( const b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + + // [vx vy w flags] + b2FloatW identityA = b2ZeroW(); + + // [dpx dpy dqc dqs] + + b2FloatW identityB = b2SetW( 0.0f, 0.0f, 1.0f, 0.0f ); + + b2FloatW b1a = indices[0] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[0] ) + 0 ); + b2FloatW b1b = indices[0] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[0] ) + 4 ); + b2FloatW b2a = indices[1] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[1] ) + 0 ); + b2FloatW b2b = indices[1] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[1] ) + 4 ); + b2FloatW b3a = indices[2] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[2] ) + 0 ); + b2FloatW b3b = indices[2] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[2] ) + 4 ); + b2FloatW b4a = indices[3] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[3] ) + 0 ); + b2FloatW b4b = indices[3] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[3] ) + 4 ); + + // [vx1 vx3 vy1 vy3] + b2FloatW t1a = b2UnpackLoW( b1a, b3a ); + + // [vx2 vx4 vy2 vy4] + b2FloatW t2a = b2UnpackLoW( b2a, b4a ); + + // [w1 w3 f1 f3] + b2FloatW t3a = b2UnpackHiW( b1a, b3a ); + + // [w2 w4 f2 f4] + b2FloatW t4a = b2UnpackHiW( b2a, b4a ); + + b2BodyStateW simdBody; + simdBody.v.X = b2UnpackLoW( t1a, t2a ); + simdBody.v.Y = b2UnpackHiW( t1a, t2a ); + simdBody.w = b2UnpackLoW( t3a, t4a ); + simdBody.flags = b2UnpackHiW( t3a, t4a ); + + b2FloatW t1b = b2UnpackLoW( b1b, b3b ); + b2FloatW t2b = b2UnpackLoW( b2b, b4b ); + b2FloatW t3b = b2UnpackHiW( b1b, b3b ); + b2FloatW t4b = b2UnpackHiW( b2b, b4b ); + + simdBody.dp.X = b2UnpackLoW( t1b, t2b ); + simdBody.dp.Y = b2UnpackHiW( t1b, t2b ); + simdBody.dq.C = b2UnpackLoW( t3b, t4b ); + simdBody.dq.S = b2UnpackHiW( t3b, t4b ); + + return simdBody; +} + +// This writes only the velocities back to the solver bodies +// https://developer.arm.com/documentation/102107a/0100/Floating-point-4x4-matrix-transposition +static void b2ScatterBodies( b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices, const b2BodyStateW* B2_RESTRICT simdBody ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + + // b2FloatW x = b2SetW(0.0f, 1.0f, 2.0f, 3.0f); + // b2FloatW y = b2SetW(4.0f, 5.0f, 6.0f, 7.0f); + // b2FloatW z = b2SetW(8.0f, 9.0f, 10.0f, 11.0f); + // b2FloatW w = b2SetW(12.0f, 13.0f, 14.0f, 15.0f); + // + // float32x4x2_t rr1 = vtrnq_f32( x, y ); + // float32x4x2_t rr2 = vtrnq_f32( z, w ); + // + // float32x4_t b1 = vcombine_f32(vget_low_f32(rr1.val[0]), vget_low_f32(rr2.val[0])); + // float32x4_t b2 = vcombine_f32(vget_low_f32(rr1.val[1]), vget_low_f32(rr2.val[1])); + // float32x4_t b3 = vcombine_f32(vget_high_f32(rr1.val[0]), vget_high_f32(rr2.val[0])); + // float32x4_t b4 = vcombine_f32(vget_high_f32(rr1.val[1]), vget_high_f32(rr2.val[1])); + + // transpose + float32x4x2_t r1 = vtrnq_f32( simdBody->v.X, simdBody->v.Y ); + float32x4x2_t r2 = vtrnq_f32( simdBody->w, simdBody->flags ); + + // I don't use any dummy body in the body array because this will lead to multithreaded sharing and the + // associated cache flushing. + if ( indices[0] != B2_NULL_INDEX ) + { + float32x4_t body1 = vcombine_f32( vget_low_f32( r1.val[0] ), vget_low_f32( r2.val[0] ) ); + b2StoreW( (float*)( states + indices[0] ), body1 ); + } + + if ( indices[1] != B2_NULL_INDEX ) + { + float32x4_t body2 = vcombine_f32( vget_low_f32( r1.val[1] ), vget_low_f32( r2.val[1] ) ); + b2StoreW( (float*)( states + indices[1] ), body2 ); + } + + if ( indices[2] != B2_NULL_INDEX ) + { + float32x4_t body3 = vcombine_f32( vget_high_f32( r1.val[0] ), vget_high_f32( r2.val[0] ) ); + b2StoreW( (float*)( states + indices[2] ), body3 ); + } + + if ( indices[3] != B2_NULL_INDEX ) + { + float32x4_t body4 = vcombine_f32( vget_high_f32( r1.val[1] ), vget_high_f32( r2.val[1] ) ); + b2StoreW( (float*)( states + indices[3] ), body4 ); + } +} + +#elif defined( B2_SIMD_SSE2 ) + +// This is a load and transpose +static b2BodyStateW b2GatherBodies( const b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + + // [vx vy w flags] + b2FloatW identityA = b2ZeroW(); + + // [dpx dpy dqc dqs] + b2FloatW identityB = b2SetW( 0.0f, 0.0f, 1.0f, 0.0f ); + + b2FloatW b1a = indices[0] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[0] ) + 0 ); + b2FloatW b1b = indices[0] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[0] ) + 4 ); + b2FloatW b2a = indices[1] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[1] ) + 0 ); + b2FloatW b2b = indices[1] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[1] ) + 4 ); + b2FloatW b3a = indices[2] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[2] ) + 0 ); + b2FloatW b3b = indices[2] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[2] ) + 4 ); + b2FloatW b4a = indices[3] == B2_NULL_INDEX ? identityA : b2LoadW( (float*)( states + indices[3] ) + 0 ); + b2FloatW b4b = indices[3] == B2_NULL_INDEX ? identityB : b2LoadW( (float*)( states + indices[3] ) + 4 ); + + // [vx1 vx3 vy1 vy3] + b2FloatW t1a = b2UnpackLoW( b1a, b3a ); + + // [vx2 vx4 vy2 vy4] + b2FloatW t2a = b2UnpackLoW( b2a, b4a ); + + // [w1 w3 f1 f3] + b2FloatW t3a = b2UnpackHiW( b1a, b3a ); + + // [w2 w4 f2 f4] + b2FloatW t4a = b2UnpackHiW( b2a, b4a ); + + b2BodyStateW simdBody; + simdBody.v.X = b2UnpackLoW( t1a, t2a ); + simdBody.v.Y = b2UnpackHiW( t1a, t2a ); + simdBody.w = b2UnpackLoW( t3a, t4a ); + simdBody.flags = b2UnpackHiW( t3a, t4a ); + + b2FloatW t1b = b2UnpackLoW( b1b, b3b ); + b2FloatW t2b = b2UnpackLoW( b2b, b4b ); + b2FloatW t3b = b2UnpackHiW( b1b, b3b ); + b2FloatW t4b = b2UnpackHiW( b2b, b4b ); + + simdBody.dp.X = b2UnpackLoW( t1b, t2b ); + simdBody.dp.Y = b2UnpackHiW( t1b, t2b ); + simdBody.dq.C = b2UnpackLoW( t3b, t4b ); + simdBody.dq.S = b2UnpackHiW( t3b, t4b ); + + return simdBody; +} + +// This writes only the velocities back to the solver bodies +static void b2ScatterBodies( b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices, const b2BodyStateW* B2_RESTRICT simdBody ) +{ + _Static_assert( sizeof( b2BodyState ) == 32, "b2BodyState not 32 bytes" ); + B2_ASSERT( ( (uintptr_t)states & 0x1F ) == 0 ); + + // [vx1 vy1 vx2 vy2] + b2FloatW t1 = b2UnpackLoW( simdBody->v.X, simdBody->v.Y ); + // [vx3 vy3 vx4 vy4] + b2FloatW t2 = b2UnpackHiW( simdBody->v.X, simdBody->v.Y ); + // [w1 f1 w2 f2] + b2FloatW t3 = b2UnpackLoW( simdBody->w, simdBody->flags ); + // [w3 f3 w4 f4] + b2FloatW t4 = b2UnpackHiW( simdBody->w, simdBody->flags ); + + // I don't use any dummy body in the body array because this will lead to multithreaded sharing and the + // associated cache flushing. + if ( indices[0] != B2_NULL_INDEX ) + { + // [t1.x t1.y t3.x t3.y] + b2StoreW( (float*)( states + indices[0] ), _mm_shuffle_ps( t1, t3, _MM_SHUFFLE( 1, 0, 1, 0 ) ) ); + } + + if ( indices[1] != B2_NULL_INDEX ) + { + // [t1.z t1.w t3.z t3.w] + b2StoreW( (float*)( states + indices[1] ), _mm_shuffle_ps( t1, t3, _MM_SHUFFLE( 3, 2, 3, 2 ) ) ); + } + + if ( indices[2] != B2_NULL_INDEX ) + { + // [t2.x t2.y t4.x t4.y] + b2StoreW( (float*)( states + indices[2] ), _mm_shuffle_ps( t2, t4, _MM_SHUFFLE( 1, 0, 1, 0 ) ) ); + } + + if ( indices[3] != B2_NULL_INDEX ) + { + // [t2.z t2.w t4.z t4.w] + b2StoreW( (float*)( states + indices[3] ), _mm_shuffle_ps( t2, t4, _MM_SHUFFLE( 3, 2, 3, 2 ) ) ); + } +} + +#else + +// This is a load and transpose +static b2BodyStateW b2GatherBodies( const b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices ) +{ + b2BodyState identity = b2_identityBodyState; + + b2BodyState s1 = indices[0] == B2_NULL_INDEX ? identity : states[indices[0]]; + b2BodyState s2 = indices[1] == B2_NULL_INDEX ? identity : states[indices[1]]; + b2BodyState s3 = indices[2] == B2_NULL_INDEX ? identity : states[indices[2]]; + b2BodyState s4 = indices[3] == B2_NULL_INDEX ? identity : states[indices[3]]; + + b2BodyStateW simdBody; + simdBody.v.X = (b2FloatW){ s1.linearVelocity.x, s2.linearVelocity.x, s3.linearVelocity.x, s4.linearVelocity.x }; + simdBody.v.Y = (b2FloatW){ s1.linearVelocity.y, s2.linearVelocity.y, s3.linearVelocity.y, s4.linearVelocity.y }; + simdBody.w = (b2FloatW){ s1.angularVelocity, s2.angularVelocity, s3.angularVelocity, s4.angularVelocity }; + simdBody.flags = (b2FloatW){ (float)s1.flags, (float)s2.flags, (float)s3.flags, (float)s4.flags }; + simdBody.dp.X = (b2FloatW){ s1.deltaPosition.x, s2.deltaPosition.x, s3.deltaPosition.x, s4.deltaPosition.x }; + simdBody.dp.Y = (b2FloatW){ s1.deltaPosition.y, s2.deltaPosition.y, s3.deltaPosition.y, s4.deltaPosition.y }; + simdBody.dq.C = (b2FloatW){ s1.deltaRotation.c, s2.deltaRotation.c, s3.deltaRotation.c, s4.deltaRotation.c }; + simdBody.dq.S = (b2FloatW){ s1.deltaRotation.s, s2.deltaRotation.s, s3.deltaRotation.s, s4.deltaRotation.s }; + + return simdBody; +} + +// This writes only the velocities back to the solver bodies +static void b2ScatterBodies( b2BodyState* B2_RESTRICT states, int* B2_RESTRICT indices, const b2BodyStateW* B2_RESTRICT simdBody ) +{ + // todo somehow skip writing to kinematic bodies + + if ( indices[0] != B2_NULL_INDEX ) + { + b2BodyState* state = states + indices[0]; + state->linearVelocity.x = simdBody->v.X.x; + state->linearVelocity.y = simdBody->v.Y.x; + state->angularVelocity = simdBody->w.x; + } + + if ( indices[1] != B2_NULL_INDEX ) + { + b2BodyState* state = states + indices[1]; + state->linearVelocity.x = simdBody->v.X.y; + state->linearVelocity.y = simdBody->v.Y.y; + state->angularVelocity = simdBody->w.y; + } + + if ( indices[2] != B2_NULL_INDEX ) + { + b2BodyState* state = states + indices[2]; + state->linearVelocity.x = simdBody->v.X.z; + state->linearVelocity.y = simdBody->v.Y.z; + state->angularVelocity = simdBody->w.z; + } + + if ( indices[3] != B2_NULL_INDEX ) + { + b2BodyState* state = states + indices[3]; + state->linearVelocity.x = simdBody->v.X.w; + state->linearVelocity.y = simdBody->v.Y.w; + state->angularVelocity = simdBody->w.w; + } +} + +#endif + +void b2PrepareContactsTask( int startIndex, int endIndex, b2StepContext* context ) +{ + b2TracyCZoneNC( prepare_contact, "Prepare Contact", b2_colorYellow, true ); + b2World* world = context->world; + b2ContactSim** contacts = context->contacts; + b2ContactConstraintSIMD* constraints = context->simdContactConstraints; + b2BodyState* awakeStates = context->states; +#if B2_VALIDATE + b2Body* bodies = world->bodies.data; +#endif + + // Stiffer for static contacts to avoid bodies getting pushed through the ground + b2Softness contactSoftness = context->contactSoftness; + b2Softness staticSoftness = context->staticSoftness; + + float warmStartScale = world->enableWarmStarting ? 1.0f : 0.0f; + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2ContactConstraintSIMD* constraint = constraints + i; + + for ( int j = 0; j < B2_SIMD_WIDTH; ++j ) + { + b2ContactSim* contactSim = contacts[B2_SIMD_WIDTH * i + j]; + + if ( contactSim != NULL ) + { + const b2Manifold* manifold = &contactSim->manifold; + + int indexA = contactSim->bodySimIndexA; + int indexB = contactSim->bodySimIndexB; + +#if B2_VALIDATE + b2Body* bodyA = bodies + contactSim->bodyIdA; + int validIndexA = bodyA->setIndex == b2_awakeSet ? bodyA->localIndex : B2_NULL_INDEX; + b2Body* bodyB = bodies + contactSim->bodyIdB; + int validIndexB = bodyB->setIndex == b2_awakeSet ? bodyB->localIndex : B2_NULL_INDEX; + + B2_ASSERT( indexA == validIndexA ); + B2_ASSERT( indexB == validIndexB ); +#endif + constraint->indexA[j] = indexA; + constraint->indexB[j] = indexB; + + b2Vec2 vA = b2Vec2_zero; + float wA = 0.0f; + float mA = contactSim->invMassA; + float iA = contactSim->invIA; + if ( indexA != B2_NULL_INDEX ) + { + b2BodyState* stateA = awakeStates + indexA; + vA = stateA->linearVelocity; + wA = stateA->angularVelocity; + } + + b2Vec2 vB = b2Vec2_zero; + float wB = 0.0f; + float mB = contactSim->invMassB; + float iB = contactSim->invIB; + if ( indexB != B2_NULL_INDEX ) + { + b2BodyState* stateB = awakeStates + indexB; + vB = stateB->linearVelocity; + wB = stateB->angularVelocity; + } + + ( (float*)&constraint->invMassA )[j] = mA; + ( (float*)&constraint->invMassB )[j] = mB; + ( (float*)&constraint->invIA )[j] = iA; + ( (float*)&constraint->invIB )[j] = iB; + + { + float k = iA + iB; + ( (float*)&constraint->rollingMass )[j] = k > 0.0f ? 1.0f / k : 0.0f; + } + + b2Softness soft = ( indexA == B2_NULL_INDEX || indexB == B2_NULL_INDEX ) ? staticSoftness : contactSoftness; + + b2Vec2 normal = manifold->normal; + ( (float*)&constraint->normal.X )[j] = normal.x; + ( (float*)&constraint->normal.Y )[j] = normal.y; + + ( (float*)&constraint->friction )[j] = contactSim->friction; + ( (float*)&constraint->tangentSpeed )[j] = contactSim->tangentSpeed; + ( (float*)&constraint->restitution )[j] = contactSim->restitution; + ( (float*)&constraint->rollingResistance )[j] = contactSim->rollingResistance; + ( (float*)&constraint->rollingImpulse )[j] = warmStartScale * manifold->rollingImpulse; + + ( (float*)&constraint->biasRate )[j] = soft.biasRate; + ( (float*)&constraint->massScale )[j] = soft.massScale; + ( (float*)&constraint->impulseScale )[j] = soft.impulseScale; + + b2Vec2 tangent = b2RightPerp( normal ); + + { + const b2ManifoldPoint* mp = manifold->points + 0; + + b2Vec2 rA = mp->anchorA; + b2Vec2 rB = mp->anchorB; + + ( (float*)&constraint->anchorA1.X )[j] = rA.x; + ( (float*)&constraint->anchorA1.Y )[j] = rA.y; + ( (float*)&constraint->anchorB1.X )[j] = rB.x; + ( (float*)&constraint->anchorB1.Y )[j] = rB.y; + + ( (float*)&constraint->baseSeparation1 )[j] = mp->separation - b2Dot( b2Sub( rB, rA ), normal ); + + ( (float*)&constraint->normalImpulse1 )[j] = warmStartScale * mp->normalImpulse; + ( (float*)&constraint->tangentImpulse1 )[j] = warmStartScale * mp->tangentImpulse; + ( (float*)&constraint->totalNormalImpulse1 )[j] = 0.0f; + + float rnA = b2Cross( rA, normal ); + float rnB = b2Cross( rB, normal ); + float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + ( (float*)&constraint->normalMass1 )[j] = kNormal > 0.0f ? 1.0f / kNormal : 0.0f; + + float rtA = b2Cross( rA, tangent ); + float rtB = b2Cross( rB, tangent ); + float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + ( (float*)&constraint->tangentMass1 )[j] = kTangent > 0.0f ? 1.0f / kTangent : 0.0f; + + // relative velocity for restitution + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + ( (float*)&constraint->relativeVelocity1 )[j] = b2Dot( normal, b2Sub( vrB, vrA ) ); + } + + int pointCount = manifold->pointCount; + B2_ASSERT( 0 < pointCount && pointCount <= 2 ); + + if ( pointCount == 2 ) + { + const b2ManifoldPoint* mp = manifold->points + 1; + + b2Vec2 rA = mp->anchorA; + b2Vec2 rB = mp->anchorB; + + ( (float*)&constraint->anchorA2.X )[j] = rA.x; + ( (float*)&constraint->anchorA2.Y )[j] = rA.y; + ( (float*)&constraint->anchorB2.X )[j] = rB.x; + ( (float*)&constraint->anchorB2.Y )[j] = rB.y; + + ( (float*)&constraint->baseSeparation2 )[j] = mp->separation - b2Dot( b2Sub( rB, rA ), normal ); + + ( (float*)&constraint->normalImpulse2 )[j] = warmStartScale * mp->normalImpulse; + ( (float*)&constraint->tangentImpulse2 )[j] = warmStartScale * mp->tangentImpulse; + ( (float*)&constraint->totalNormalImpulse2 )[j] = 0.0f; + + float rnA = b2Cross( rA, normal ); + float rnB = b2Cross( rB, normal ); + float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; + ( (float*)&constraint->normalMass2 )[j] = kNormal > 0.0f ? 1.0f / kNormal : 0.0f; + + float rtA = b2Cross( rA, tangent ); + float rtB = b2Cross( rB, tangent ); + float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; + ( (float*)&constraint->tangentMass2 )[j] = kTangent > 0.0f ? 1.0f / kTangent : 0.0f; + + // relative velocity for restitution + b2Vec2 vrA = b2Add( vA, b2CrossSV( wA, rA ) ); + b2Vec2 vrB = b2Add( vB, b2CrossSV( wB, rB ) ); + ( (float*)&constraint->relativeVelocity2 )[j] = b2Dot( normal, b2Sub( vrB, vrA ) ); + } + else + { + // dummy data that has no effect + ( (float*)&constraint->baseSeparation2 )[j] = 0.0f; + ( (float*)&constraint->normalImpulse2 )[j] = 0.0f; + ( (float*)&constraint->tangentImpulse2 )[j] = 0.0f; + ( (float*)&constraint->totalNormalImpulse2 )[j] = 0.0f; + ( (float*)&constraint->anchorA2.X )[j] = 0.0f; + ( (float*)&constraint->anchorA2.Y )[j] = 0.0f; + ( (float*)&constraint->anchorB2.X )[j] = 0.0f; + ( (float*)&constraint->anchorB2.Y )[j] = 0.0f; + ( (float*)&constraint->normalMass2 )[j] = 0.0f; + ( (float*)&constraint->tangentMass2 )[j] = 0.0f; + ( (float*)&constraint->relativeVelocity2 )[j] = 0.0f; + } + } + else + { + // SIMD remainder + constraint->indexA[j] = B2_NULL_INDEX; + constraint->indexB[j] = B2_NULL_INDEX; + + ( (float*)&constraint->invMassA )[j] = 0.0f; + ( (float*)&constraint->invMassB )[j] = 0.0f; + ( (float*)&constraint->invIA )[j] = 0.0f; + ( (float*)&constraint->invIB )[j] = 0.0f; + + ( (float*)&constraint->normal.X )[j] = 0.0f; + ( (float*)&constraint->normal.Y )[j] = 0.0f; + ( (float*)&constraint->friction )[j] = 0.0f; + ( (float*)&constraint->tangentSpeed )[j] = 0.0f; + ( (float*)&constraint->rollingResistance )[j] = 0.0f; + ( (float*)&constraint->rollingMass )[j] = 0.0f; + ( (float*)&constraint->rollingImpulse )[j] = 0.0f; + ( (float*)&constraint->biasRate )[j] = 0.0f; + ( (float*)&constraint->massScale )[j] = 0.0f; + ( (float*)&constraint->impulseScale )[j] = 0.0f; + + ( (float*)&constraint->anchorA1.X )[j] = 0.0f; + ( (float*)&constraint->anchorA1.Y )[j] = 0.0f; + ( (float*)&constraint->anchorB1.X )[j] = 0.0f; + ( (float*)&constraint->anchorB1.Y )[j] = 0.0f; + ( (float*)&constraint->baseSeparation1 )[j] = 0.0f; + ( (float*)&constraint->normalImpulse1 )[j] = 0.0f; + ( (float*)&constraint->tangentImpulse1 )[j] = 0.0f; + ( (float*)&constraint->totalNormalImpulse1 )[j] = 0.0f; + ( (float*)&constraint->normalMass1 )[j] = 0.0f; + ( (float*)&constraint->tangentMass1 )[j] = 0.0f; + + ( (float*)&constraint->anchorA2.X )[j] = 0.0f; + ( (float*)&constraint->anchorA2.Y )[j] = 0.0f; + ( (float*)&constraint->anchorB2.X )[j] = 0.0f; + ( (float*)&constraint->anchorB2.Y )[j] = 0.0f; + ( (float*)&constraint->baseSeparation2 )[j] = 0.0f; + ( (float*)&constraint->normalImpulse2 )[j] = 0.0f; + ( (float*)&constraint->tangentImpulse2 )[j] = 0.0f; + ( (float*)&constraint->totalNormalImpulse2 )[j] = 0.0f; + ( (float*)&constraint->normalMass2 )[j] = 0.0f; + ( (float*)&constraint->tangentMass2 )[j] = 0.0f; + + ( (float*)&constraint->restitution )[j] = 0.0f; + ( (float*)&constraint->relativeVelocity1 )[j] = 0.0f; + ( (float*)&constraint->relativeVelocity2 )[j] = 0.0f; + } + } + } + + b2TracyCZoneEnd( prepare_contact ); +} + +void b2WarmStartContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex ) +{ + b2TracyCZoneNC( warm_start_contact, "Warm Start", b2_colorGreen, true ); + + b2BodyState* states = context->states; + b2ContactConstraintSIMD* constraints = context->graph->colors[colorIndex].simdConstraints; + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2ContactConstraintSIMD* c = constraints + i; + b2BodyStateW bA = b2GatherBodies( states, c->indexA ); + b2BodyStateW bB = b2GatherBodies( states, c->indexB ); + + b2FloatW tangentX = c->normal.Y; + b2FloatW tangentY = b2SubW( b2ZeroW(), c->normal.X ); + + { + // fixed anchors + b2Vec2W rA = c->anchorA1; + b2Vec2W rB = c->anchorB1; + + b2Vec2W P; + P.X = b2AddW( b2MulW( c->normalImpulse1, c->normal.X ), b2MulW( c->tangentImpulse1, tangentX ) ); + P.Y = b2AddW( b2MulW( c->normalImpulse1, c->normal.Y ), b2MulW( c->tangentImpulse1, tangentY ) ); + bA.w = b2MulSubW( bA.w, c->invIA, b2CrossW( rA, P ) ); + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, P.X ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, P.Y ); + bB.w = b2MulAddW( bB.w, c->invIB, b2CrossW( rB, P ) ); + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, P.X ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, P.Y ); + } + + { + // fixed anchors + b2Vec2W rA = c->anchorA2; + b2Vec2W rB = c->anchorB2; + + b2Vec2W P; + P.X = b2AddW( b2MulW( c->normalImpulse2, c->normal.X ), b2MulW( c->tangentImpulse2, tangentX ) ); + P.Y = b2AddW( b2MulW( c->normalImpulse2, c->normal.Y ), b2MulW( c->tangentImpulse2, tangentY ) ); + bA.w = b2MulSubW( bA.w, c->invIA, b2CrossW( rA, P ) ); + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, P.X ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, P.Y ); + bB.w = b2MulAddW( bB.w, c->invIB, b2CrossW( rB, P ) ); + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, P.X ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, P.Y ); + } + + bA.w = b2MulSubW( bA.w, c->invIA, c->rollingImpulse ); + bB.w = b2MulAddW( bB.w, c->invIB, c->rollingImpulse ); + + b2ScatterBodies( states, c->indexA, &bA ); + b2ScatterBodies( states, c->indexB, &bB ); + } + + b2TracyCZoneEnd( warm_start_contact ); +} + +void b2SolveContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex, bool useBias ) +{ + b2TracyCZoneNC( solve_contact, "Solve Contact", b2_colorAliceBlue, true ); + + b2BodyState* states = context->states; + b2ContactConstraintSIMD* constraints = context->graph->colors[colorIndex].simdConstraints; + b2FloatW inv_h = b2SplatW( context->inv_h ); + b2FloatW minBiasVel = b2SplatW( -context->world->maxContactPushSpeed ); + b2FloatW oneW = b2SplatW( 1.0f ); + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2ContactConstraintSIMD* c = constraints + i; + + b2BodyStateW bA = b2GatherBodies( states, c->indexA ); + b2BodyStateW bB = b2GatherBodies( states, c->indexB ); + + b2FloatW biasRate, massScale, impulseScale; + if ( useBias ) + { + biasRate = c->biasRate; + massScale = c->massScale; + impulseScale = c->impulseScale; + } + else + { + biasRate = b2ZeroW(); + massScale = oneW; + impulseScale = b2ZeroW(); + } + + b2FloatW totalNormalImpulse = b2ZeroW(); + + b2Vec2W dp = { b2SubW( bB.dp.X, bA.dp.X ), b2SubW( bB.dp.Y, bA.dp.Y ) }; + + // point1 non-penetration constraint + { + // Fixed anchors for impulses + b2Vec2W rA = c->anchorA1; + b2Vec2W rB = c->anchorB1; + + // Moving anchors for current separation + b2Vec2W rsA = b2RotateVectorW( bA.dq, rA ); + b2Vec2W rsB = b2RotateVectorW( bB.dq, rB ); + + // compute current separation + // this is subject to round-off error if the anchor is far from the body center of mass + b2Vec2W ds = { b2AddW( dp.X, b2SubW( rsB.X, rsA.X ) ), b2AddW( dp.Y, b2SubW( rsB.Y, rsA.Y ) ) }; + b2FloatW s = b2AddW( b2DotW( c->normal, ds ), c->baseSeparation1 ); + + // Apply speculative bias if separation is greater than zero, otherwise apply soft constraint bias + // The minBiasVel is meant to limit stiffness, not increase it. + b2FloatW mask = b2GreaterThanW( s, b2ZeroW() ); + b2FloatW specBias = b2MulW( s, inv_h ); + b2FloatW softBias = b2MaxW( b2MulW( biasRate, s ), minBiasVel ); + + // todo try b2MaxW(softBias, specBias); + b2FloatW bias = b2BlendW( softBias, specBias, mask ); + + b2FloatW pointMassScale = b2BlendW( massScale, oneW, mask ); + b2FloatW pointImpulseScale = b2BlendW( impulseScale, b2ZeroW(), mask ); + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vn = b2AddW( b2MulW( dvx, c->normal.X ), b2MulW( dvy, c->normal.Y ) ); + + // Compute normal impulse + b2FloatW negImpulse = b2AddW( b2MulW( c->normalMass1, b2MulW( pointMassScale, b2AddW( vn, bias ) ) ), + b2MulW( pointImpulseScale, c->normalImpulse1 ) ); + + // Clamp the accumulated impulse + b2FloatW newImpulse = b2MaxW( b2SubW( c->normalImpulse1, negImpulse ), b2ZeroW() ); + b2FloatW impulse = b2SubW( newImpulse, c->normalImpulse1 ); + c->normalImpulse1 = newImpulse; + c->totalNormalImpulse1 = b2AddW( c->totalNormalImpulse1, newImpulse ); + + totalNormalImpulse = b2AddW( totalNormalImpulse, newImpulse ); + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, c->normal.X ); + b2FloatW Py = b2MulW( impulse, c->normal.Y ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + // second point non-penetration constraint + { + // moving anchors for current separation + b2Vec2W rsA = b2RotateVectorW( bA.dq, c->anchorA2 ); + b2Vec2W rsB = b2RotateVectorW( bB.dq, c->anchorB2 ); + + // compute current separation + b2Vec2W ds = { b2AddW( dp.X, b2SubW( rsB.X, rsA.X ) ), b2AddW( dp.Y, b2SubW( rsB.Y, rsA.Y ) ) }; + b2FloatW s = b2AddW( b2DotW( c->normal, ds ), c->baseSeparation2 ); + + b2FloatW mask = b2GreaterThanW( s, b2ZeroW() ); + b2FloatW specBias = b2MulW( s, inv_h ); + b2FloatW softBias = b2MaxW( b2MulW( biasRate, s ), minBiasVel ); + b2FloatW bias = b2BlendW( softBias, specBias, mask ); + + b2FloatW pointMassScale = b2BlendW( massScale, oneW, mask ); + b2FloatW pointImpulseScale = b2BlendW( impulseScale, b2ZeroW(), mask ); + + // fixed anchors for Jacobians + b2Vec2W rA = c->anchorA2; + b2Vec2W rB = c->anchorB2; + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vn = b2AddW( b2MulW( dvx, c->normal.X ), b2MulW( dvy, c->normal.Y ) ); + + // Compute normal impulse + b2FloatW negImpulse = b2AddW( b2MulW( c->normalMass2, b2MulW( pointMassScale, b2AddW( vn, bias ) ) ), + b2MulW( pointImpulseScale, c->normalImpulse2 ) ); + + // Clamp the accumulated impulse + b2FloatW newImpulse = b2MaxW( b2SubW( c->normalImpulse2, negImpulse ), b2ZeroW() ); + b2FloatW impulse = b2SubW( newImpulse, c->normalImpulse2 ); + c->normalImpulse2 = newImpulse; + c->totalNormalImpulse2 = b2AddW( c->totalNormalImpulse2, newImpulse ); + + totalNormalImpulse = b2AddW( totalNormalImpulse, newImpulse ); + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, c->normal.X ); + b2FloatW Py = b2MulW( impulse, c->normal.Y ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + b2FloatW tangentX = c->normal.Y; + b2FloatW tangentY = b2SubW( b2ZeroW(), c->normal.X ); + + // point 1 friction constraint + { + // fixed anchors for Jacobians + b2Vec2W rA = c->anchorA1; + b2Vec2W rB = c->anchorB1; + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vt = b2AddW( b2MulW( dvx, tangentX ), b2MulW( dvy, tangentY ) ); + + // Tangent speed (conveyor belt) + vt = b2SubW( vt, c->tangentSpeed ); + + // Compute tangent force + b2FloatW negImpulse = b2MulW( c->tangentMass1, vt ); + + // Clamp the accumulated force + b2FloatW maxFriction = b2MulW( c->friction, c->normalImpulse1 ); + b2FloatW newImpulse = b2SubW( c->tangentImpulse1, negImpulse ); + newImpulse = b2MaxW( b2SubW( b2ZeroW(), maxFriction ), b2MinW( newImpulse, maxFriction ) ); + b2FloatW impulse = b2SubW( newImpulse, c->tangentImpulse1 ); + c->tangentImpulse1 = newImpulse; + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, tangentX ); + b2FloatW Py = b2MulW( impulse, tangentY ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + // second point friction constraint + { + // fixed anchors for Jacobians + b2Vec2W rA = c->anchorA2; + b2Vec2W rB = c->anchorB2; + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vt = b2AddW( b2MulW( dvx, tangentX ), b2MulW( dvy, tangentY ) ); + + // Tangent speed (conveyor belt) + vt = b2SubW( vt, c->tangentSpeed ); + + // Compute tangent force + b2FloatW negImpulse = b2MulW( c->tangentMass2, vt ); + + // Clamp the accumulated force + b2FloatW maxFriction = b2MulW( c->friction, c->normalImpulse2 ); + b2FloatW newImpulse = b2SubW( c->tangentImpulse2, negImpulse ); + newImpulse = b2MaxW( b2SubW( b2ZeroW(), maxFriction ), b2MinW( newImpulse, maxFriction ) ); + b2FloatW impulse = b2SubW( newImpulse, c->tangentImpulse2 ); + c->tangentImpulse2 = newImpulse; + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, tangentX ); + b2FloatW Py = b2MulW( impulse, tangentY ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + // Rolling resistance + { + b2FloatW deltaLambda = b2MulW( c->rollingMass, b2SubW( bA.w, bB.w ) ); + b2FloatW lambda = c->rollingImpulse; + b2FloatW maxLambda = b2MulW( c->rollingResistance, totalNormalImpulse ); + c->rollingImpulse = b2SymClampW( b2AddW( lambda, deltaLambda ), maxLambda ); + deltaLambda = b2SubW( c->rollingImpulse, lambda ); + + bA.w = b2MulSubW( bA.w, c->invIA, deltaLambda ); + bB.w = b2MulAddW( bB.w, c->invIB, deltaLambda ); + } + + b2ScatterBodies( states, c->indexA, &bA ); + b2ScatterBodies( states, c->indexB, &bB ); + } + + b2TracyCZoneEnd( solve_contact ); +} + +void b2ApplyRestitutionTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex ) +{ + b2TracyCZoneNC( restitution, "Restitution", b2_colorDodgerBlue, true ); + + b2BodyState* states = context->states; + b2ContactConstraintSIMD* constraints = context->graph->colors[colorIndex].simdConstraints; + b2FloatW threshold = b2SplatW( context->world->restitutionThreshold ); + b2FloatW zero = b2ZeroW(); + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2ContactConstraintSIMD* c = constraints + i; + + if ( b2AllZeroW( c->restitution ) ) + { + // No lanes have restitution. Common case. + continue; + } + + // Create a mask based on restitution so that lanes with no restitution are not affected + // by the calculations below. + b2FloatW restitutionMask = b2EqualsW( c->restitution, zero ); + + b2BodyStateW bA = b2GatherBodies( states, c->indexA ); + b2BodyStateW bB = b2GatherBodies( states, c->indexB ); + + // first point non-penetration constraint + { + // Set effective mass to zero if restitution should not be applied + b2FloatW mask1 = b2GreaterThanW( b2AddW( c->relativeVelocity1, threshold ), zero ); + b2FloatW mask2 = b2EqualsW( c->totalNormalImpulse1, zero ); + b2FloatW mask = b2OrW( b2OrW( mask1, mask2 ), restitutionMask ); + b2FloatW mass = b2BlendW( c->normalMass1, zero, mask ); + + // fixed anchors for Jacobians + b2Vec2W rA = c->anchorA1; + b2Vec2W rB = c->anchorB1; + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vn = b2AddW( b2MulW( dvx, c->normal.X ), b2MulW( dvy, c->normal.Y ) ); + + // Compute normal impulse + b2FloatW negImpulse = b2MulW( mass, b2AddW( vn, b2MulW( c->restitution, c->relativeVelocity1 ) ) ); + + // Clamp the accumulated impulse + b2FloatW newImpulse = b2MaxW( b2SubW( c->normalImpulse1, negImpulse ), b2ZeroW() ); + b2FloatW impulse = b2SubW( newImpulse, c->normalImpulse1 ); + c->normalImpulse1 = newImpulse; + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, c->normal.X ); + b2FloatW Py = b2MulW( impulse, c->normal.Y ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + // second point non-penetration constraint + { + // Set effective mass to zero if restitution should not be applied + b2FloatW mask1 = b2GreaterThanW( b2AddW( c->relativeVelocity2, threshold ), zero ); + b2FloatW mask2 = b2EqualsW( c->totalNormalImpulse2, zero ); + b2FloatW mask = b2OrW( b2OrW( mask1, mask2 ), restitutionMask ); + b2FloatW mass = b2BlendW( c->normalMass2, zero, mask ); + + // fixed anchors for Jacobians + b2Vec2W rA = c->anchorA2; + b2Vec2W rB = c->anchorB2; + + // Relative velocity at contact + b2FloatW dvx = b2SubW( b2SubW( bB.v.X, b2MulW( bB.w, rB.Y ) ), b2SubW( bA.v.X, b2MulW( bA.w, rA.Y ) ) ); + b2FloatW dvy = b2SubW( b2AddW( bB.v.Y, b2MulW( bB.w, rB.X ) ), b2AddW( bA.v.Y, b2MulW( bA.w, rA.X ) ) ); + b2FloatW vn = b2AddW( b2MulW( dvx, c->normal.X ), b2MulW( dvy, c->normal.Y ) ); + + // Compute normal impulse + b2FloatW negImpulse = b2MulW( mass, b2AddW( vn, b2MulW( c->restitution, c->relativeVelocity2 ) ) ); + + // Clamp the accumulated impulse + b2FloatW newImpulse = b2MaxW( b2SubW( c->normalImpulse2, negImpulse ), b2ZeroW() ); + b2FloatW impulse = b2SubW( newImpulse, c->normalImpulse2 ); + c->normalImpulse2 = newImpulse; + + // Apply contact impulse + b2FloatW Px = b2MulW( impulse, c->normal.X ); + b2FloatW Py = b2MulW( impulse, c->normal.Y ); + + bA.v.X = b2MulSubW( bA.v.X, c->invMassA, Px ); + bA.v.Y = b2MulSubW( bA.v.Y, c->invMassA, Py ); + bA.w = b2MulSubW( bA.w, c->invIA, b2SubW( b2MulW( rA.X, Py ), b2MulW( rA.Y, Px ) ) ); + + bB.v.X = b2MulAddW( bB.v.X, c->invMassB, Px ); + bB.v.Y = b2MulAddW( bB.v.Y, c->invMassB, Py ); + bB.w = b2MulAddW( bB.w, c->invIB, b2SubW( b2MulW( rB.X, Py ), b2MulW( rB.Y, Px ) ) ); + } + + b2ScatterBodies( states, c->indexA, &bA ); + b2ScatterBodies( states, c->indexB, &bB ); + } + + b2TracyCZoneEnd( restitution ); +} + +void b2StoreImpulsesTask( int startIndex, int endIndex, b2StepContext* context ) +{ + b2TracyCZoneNC( store_impulses, "Store", b2_colorFireBrick, true ); + + b2ContactSim** contacts = context->contacts; + const b2ContactConstraintSIMD* constraints = context->simdContactConstraints; + + b2Manifold dummy = { 0 }; + + for ( int constraintIndex = startIndex; constraintIndex < endIndex; ++constraintIndex ) + { + const b2ContactConstraintSIMD* c = constraints + constraintIndex; + const float* rollingImpulse = (float*)&c->rollingImpulse; + const float* normalImpulse1 = (float*)&c->normalImpulse1; + const float* normalImpulse2 = (float*)&c->normalImpulse2; + const float* tangentImpulse1 = (float*)&c->tangentImpulse1; + const float* tangentImpulse2 = (float*)&c->tangentImpulse2; + const float* totalNormalImpulse1 = (float*)&c->totalNormalImpulse1; + const float* totalNormalImpulse2 = (float*)&c->totalNormalImpulse2; + const float* normalVelocity1 = (float*)&c->relativeVelocity1; + const float* normalVelocity2 = (float*)&c->relativeVelocity2; + + int baseIndex = B2_SIMD_WIDTH * constraintIndex; + + for ( int laneIndex = 0; laneIndex < B2_SIMD_WIDTH; ++laneIndex ) + { + b2Manifold* m = contacts[baseIndex + laneIndex] == NULL ? &dummy : &contacts[baseIndex + laneIndex]->manifold; + m->rollingImpulse = rollingImpulse[laneIndex]; + + m->points[0].normalImpulse = normalImpulse1[laneIndex]; + m->points[0].tangentImpulse = tangentImpulse1[laneIndex]; + m->points[0].totalNormalImpulse = totalNormalImpulse1[laneIndex]; + m->points[0].normalVelocity = normalVelocity1[laneIndex]; + + m->points[1].normalImpulse = normalImpulse2[laneIndex]; + m->points[1].tangentImpulse = tangentImpulse2[laneIndex]; + m->points[1].totalNormalImpulse = totalNormalImpulse2[laneIndex]; + m->points[1].normalVelocity = normalVelocity2[laneIndex]; + } + } + + b2TracyCZoneEnd( store_impulses ); +} diff --git a/3rdparty/box2d/src/contact_solver.h b/3rdparty/box2d/src/contact_solver.h new file mode 100644 index 000000000000..61e46c74a3cc --- /dev/null +++ b/3rdparty/box2d/src/contact_solver.h @@ -0,0 +1,54 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "solver.h" + +typedef struct b2ContactSim b2ContactSim; + +typedef struct b2ContactConstraintPoint +{ + b2Vec2 anchorA, anchorB; + float baseSeparation; + float relativeVelocity; + float normalImpulse; + float tangentImpulse; + float totalNormalImpulse; + float normalMass; + float tangentMass; +} b2ContactConstraintPoint; + +typedef struct b2ContactConstraint +{ + int indexA; + int indexB; + b2ContactConstraintPoint points[2]; + b2Vec2 normal; + float invMassA, invMassB; + float invIA, invIB; + float friction; + float restitution; + float tangentSpeed; + float rollingResistance; + float rollingMass; + float rollingImpulse; + b2Softness softness; + int pointCount; +} b2ContactConstraint; + +int b2GetContactConstraintSIMDByteCount( void ); + +// Overflow contacts don't fit into the constraint graph coloring +void b2PrepareOverflowContacts( b2StepContext* context ); +void b2WarmStartOverflowContacts( b2StepContext* context ); +void b2SolveOverflowContacts( b2StepContext* context, bool useBias ); +void b2ApplyOverflowRestitution( b2StepContext* context ); +void b2StoreOverflowImpulses( b2StepContext* context ); + +// Contacts that live within the constraint graph coloring +void b2PrepareContactsTask( int startIndex, int endIndex, b2StepContext* context ); +void b2WarmStartContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex ); +void b2SolveContactsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex, bool useBias ); +void b2ApplyRestitutionTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex ); +void b2StoreImpulsesTask( int startIndex, int endIndex, b2StepContext* context ); diff --git a/3rdparty/box2d/src/core.c b/3rdparty/box2d/src/core.c new file mode 100644 index 000000000000..1ecfbb1703b2 --- /dev/null +++ b/3rdparty/box2d/src/core.c @@ -0,0 +1,178 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "core.h" + +#if defined( B2_COMPILER_MSVC ) +#define _CRTDBG_MAP_ALLOC +#include +#include +#else +#include +#endif + +#include +#include + +#ifdef BOX2D_PROFILE + +#include +#define b2TracyCAlloc( ptr, size ) TracyCAlloc( ptr, size ) +#define b2TracyCFree( ptr ) TracyCFree( ptr ) + +#else + +#define b2TracyCAlloc( ptr, size ) +#define b2TracyCFree( ptr ) + +#endif + +#include "atomic.h" + +// This allows the user to change the length units at runtime +float b2_lengthUnitsPerMeter = 1.0f; + +void b2SetLengthUnitsPerMeter( float lengthUnits ) +{ + B2_ASSERT( b2IsValidFloat( lengthUnits ) && lengthUnits > 0.0f ); + b2_lengthUnitsPerMeter = lengthUnits; +} + +float b2GetLengthUnitsPerMeter( void ) +{ + return b2_lengthUnitsPerMeter; +} + +static int b2DefaultAssertFcn( const char* condition, const char* fileName, int lineNumber ) +{ + printf( "BOX2D ASSERTION: %s, %s, line %d\n", condition, fileName, lineNumber ); + + // return non-zero to break to debugger + return 1; +} + +b2AssertFcn* b2AssertHandler = b2DefaultAssertFcn; + +void b2SetAssertFcn( b2AssertFcn* assertFcn ) +{ + B2_ASSERT( assertFcn != NULL ); + b2AssertHandler = assertFcn; +} + +#if !defined( NDEBUG ) || defined( B2_ENABLE_ASSERT ) +int b2InternalAssertFcn( const char* condition, const char* fileName, int lineNumber ) +{ + return b2AssertHandler( condition, fileName, lineNumber ); +} +#endif + +b2Version b2GetVersion( void ) +{ + return (b2Version){ + .major = 3, + .minor = 1, + .revision = 0, + }; +} + +static b2AllocFcn* b2_allocFcn = NULL; +static b2FreeFcn* b2_freeFcn = NULL; + +b2AtomicInt b2_byteCount; + +void b2SetAllocator( b2AllocFcn* allocFcn, b2FreeFcn* freeFcn ) +{ + b2_allocFcn = allocFcn; + b2_freeFcn = freeFcn; +} + +// Use 32 byte alignment for everything. Works with 256bit SIMD. +#define B2_ALIGNMENT 32 + +void* b2Alloc( int size ) +{ + if ( size == 0 ) + { + return NULL; + } + + // This could cause some sharing issues, however Box2D rarely calls b2Alloc. + b2AtomicFetchAddInt( &b2_byteCount, size ); + + // Allocation must be a multiple of 32 or risk a seg fault + // https://en.cppreference.com/w/c/memory/aligned_alloc + int size32 = ( ( size - 1 ) | 0x1F ) + 1; + + if ( b2_allocFcn != NULL ) + { + void* ptr = b2_allocFcn( size32, B2_ALIGNMENT ); + b2TracyCAlloc( ptr, size ); + + B2_ASSERT( ptr != NULL ); + B2_ASSERT( ( (uintptr_t)ptr & 0x1F ) == 0 ); + + return ptr; + } + +#ifdef B2_PLATFORM_WINDOWS + void* ptr = _aligned_malloc( size32, B2_ALIGNMENT ); +#elif defined( B2_PLATFORM_ANDROID ) + void* ptr = NULL; + if ( posix_memalign( &ptr, B2_ALIGNMENT, size32 ) != 0 ) + { + // allocation failed, exit the application + exit( EXIT_FAILURE ); + } +#else + void* ptr = aligned_alloc( B2_ALIGNMENT, size32 ); +#endif + + b2TracyCAlloc( ptr, size ); + + B2_ASSERT( ptr != NULL ); + B2_ASSERT( ( (uintptr_t)ptr & 0x1F ) == 0 ); + + return ptr; +} + +void b2Free( void* mem, int size ) +{ + if ( mem == NULL ) + { + return; + } + + b2TracyCFree( mem ); + + if ( b2_freeFcn != NULL ) + { + b2_freeFcn( mem ); + } + else + { +#ifdef B2_PLATFORM_WINDOWS + _aligned_free( mem ); +#else + free( mem ); +#endif + } + + b2AtomicFetchAddInt( &b2_byteCount, -size ); +} + +void* b2GrowAlloc( void* oldMem, int oldSize, int newSize ) +{ + B2_ASSERT( newSize > oldSize ); + void* newMem = b2Alloc( newSize ); + if ( oldSize > 0 ) + { + memcpy( newMem, oldMem, oldSize ); + b2Free( oldMem, oldSize ); + } + return newMem; +} + +int b2GetByteCount( void ) +{ + return b2AtomicLoadInt( &b2_byteCount ); +} diff --git a/3rdparty/box2d/src/core.h b/3rdparty/box2d/src/core.h new file mode 100644 index 000000000000..2dfeda4e5a52 --- /dev/null +++ b/3rdparty/box2d/src/core.h @@ -0,0 +1,149 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/math_functions.h" + +// clang-format off + +#define B2_NULL_INDEX ( -1 ) + +// for performance comparisons +#define B2_RESTRICT restrict + +#ifdef NDEBUG + #define B2_DEBUG 0 +#else + #define B2_DEBUG 1 +#endif + +#if defined( BOX2D_VALIDATE ) && !defined( NDEBUG ) + #define B2_VALIDATE 1 +#else + #define B2_VALIDATE 0 +#endif + +// Define platform +#if defined(_WIN32) || defined(_WIN64) + #define B2_PLATFORM_WINDOWS +#elif defined( __ANDROID__ ) + #define B2_PLATFORM_ANDROID +#elif defined( __linux__ ) + #define B2_PLATFORM_LINUX +#elif defined( __APPLE__ ) + #include + #if defined( TARGET_OS_IPHONE ) && !TARGET_OS_IPHONE + #define B2_PLATFORM_MACOS + #else + #define B2_PLATFORM_IOS + #endif +#elif defined( __EMSCRIPTEN__ ) + #define B2_PLATFORM_WASM +#else + #define B2_PLATFORM_UNKNOWN +#endif + +// Define CPU +#if defined( __x86_64__ ) || defined( _M_X64 ) || defined( __i386__ ) || defined( _M_IX86 ) + #define B2_CPU_X86_X64 +#elif defined( __aarch64__ ) || defined( _M_ARM64 ) || defined( __arm__ ) || defined( _M_ARM ) + #define B2_CPU_ARM +#elif defined( __EMSCRIPTEN__ ) + #define B2_CPU_WASM +#else + #define B2_CPU_UNKNOWN +#endif + +// Define SIMD +#if defined( BOX2D_DISABLE_SIMD ) + #define B2_SIMD_NONE + // note: I tried width of 1 and got no performance change + #define B2_SIMD_WIDTH 4 +#else + #if defined( B2_CPU_X86_X64 ) + #if defined( BOX2D_AVX2 ) + #define B2_SIMD_AVX2 + #define B2_SIMD_WIDTH 8 + #else + #define B2_SIMD_SSE2 + #define B2_SIMD_WIDTH 4 + #endif + #elif defined( B2_CPU_ARM ) + #define B2_SIMD_NEON + #define B2_SIMD_WIDTH 4 + #elif defined( B2_CPU_WASM ) + #define B2_CPU_WASM + #define B2_SIMD_SSE2 + #define B2_SIMD_WIDTH 4 + #else + #define B2_SIMD_NONE + #define B2_SIMD_WIDTH 4 + #endif +#endif + +// Define compiler +#if defined( __clang__ ) + #define B2_COMPILER_CLANG +#elif defined( __GNUC__ ) + #define B2_COMPILER_GCC +#elif defined( _MSC_VER ) + #define B2_COMPILER_MSVC +#endif + +/// Tracy profiler instrumentation +/// https://github.com/wolfpld/tracy +#ifdef BOX2D_PROFILE + #include + #define b2TracyCZoneC( ctx, color, active ) TracyCZoneC( ctx, color, active ) + #define b2TracyCZoneNC( ctx, name, color, active ) TracyCZoneNC( ctx, name, color, active ) + #define b2TracyCZoneEnd( ctx ) TracyCZoneEnd( ctx ) +#else + #define b2TracyCZoneC( ctx, color, active ) + #define b2TracyCZoneNC( ctx, name, color, active ) + #define b2TracyCZoneEnd( ctx ) +#endif + +// clang-format on + +// Returns the number of elements of an array +#define B2_ARRAY_COUNT( A ) (int)( sizeof( A ) / sizeof( A[0] ) ) + +// Used to prevent the compiler from warning about unused variables +#define B2_UNUSED( ... ) (void)sizeof( ( __VA_ARGS__, 0 ) ) + +// Use to validate definitions. Do not take my cookie. +#define B2_SECRET_COOKIE 1152023 + +// Snoop counters. These should be disabled in optimized builds because they are expensive. +#if defined( box2d_EXPORTS ) +#define B2_SNOOP_TABLE_COUNTERS B2_DEBUG +#define B2_SNOOP_PAIR_COUNTERS B2_DEBUG +#define B2_SNOOP_TOI_COUNTERS B2_DEBUG +#else +#define B2_SNOOP_TABLE_COUNTERS 0 +#define B2_SNOOP_PAIR_COUNTERS 0 +#define B2_SNOOP_TOI_COUNTERS 0 +#endif + +#define B2_CHECK_DEF( DEF ) B2_ASSERT( DEF->internalValue == B2_SECRET_COOKIE ) + +typedef struct b2AtomicInt +{ + int value; +} b2AtomicInt; + +typedef struct b2AtomicU32 +{ + uint32_t value; +} b2AtomicU32; + +void* b2Alloc( int size ); +#define B2_ALLOC_STRUCT( type ) b2Alloc(sizeof(type)) +#define B2_ALLOC_ARRAY( count, type ) b2Alloc(count * sizeof(type)) + +void b2Free( void* mem, int size ); +#define B2_FREE_STRUCT( mem, type ) b2Free( mem, sizeof(type)); +#define B2_FREE_ARRAY( mem, count, type ) b2Free(mem, count * sizeof(type)) + +void* b2GrowAlloc( void* oldMem, int oldSize, int newSize ); diff --git a/3rdparty/box2d/src/ctz.h b/3rdparty/box2d/src/ctz.h new file mode 100644 index 000000000000..9959527c0871 --- /dev/null +++ b/3rdparty/box2d/src/ctz.h @@ -0,0 +1,112 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#if defined( _MSC_VER ) && !defined( __clang__ ) + #include + +// https://en.wikipedia.org/wiki/Find_first_set + +static inline uint32_t b2CTZ32( uint32_t block ) +{ + unsigned long index; + _BitScanForward( &index, block ); + return index; +} + +// This function doesn't need to be fast, so using the Ivy Bridge fallback. +static inline uint32_t b2CLZ32( uint32_t value ) +{ + #if 1 + + // Use BSR (Bit Scan Reverse) which is available on Ivy Bridge + unsigned long index; + if ( _BitScanReverse( &index, value ) ) + { + // BSR gives the index of the most significant 1-bit + // We need to invert this to get the number of leading zeros + return 31 - index; + } + else + { + // If x is 0, BSR sets the zero flag and doesn't modify index + // LZCNT should return 32 for an input of 0 + return 32; + } + + #else + + return __lzcnt( value ); + + #endif +} + +static inline uint32_t b2CTZ64( uint64_t block ) +{ + unsigned long index; + + #ifdef _WIN64 + _BitScanForward64( &index, block ); + #else + // 32-bit fall back + if ( (uint32_t)block != 0 ) + { + _BitScanForward( &index, (uint32_t)block ); + } + else + { + _BitScanForward( &index, (uint32_t)( block >> 32 ) ); + index += 32; + } + #endif + + return index; +} + +#else + +static inline uint32_t b2CTZ32( uint32_t block ) +{ + return __builtin_ctz( block ); +} + +static inline uint32_t b2CLZ32( uint32_t value ) +{ + return __builtin_clz( value ); +} + +static inline uint32_t b2CTZ64( uint64_t block ) +{ + return __builtin_ctzll( block ); +} + +#endif + +static inline bool b2IsPowerOf2( int x ) +{ + return ( x & ( x - 1 ) ) == 0; +} + +static inline int b2BoundingPowerOf2( int x ) +{ + if ( x <= 1 ) + { + return 1; + } + + return 32 - (int)b2CLZ32( (uint32_t)x - 1 ); +} + +static inline int b2RoundUpPowerOf2( int x ) +{ + if ( x <= 1 ) + { + return 1; + } + + return 1 << ( 32 - (int)b2CLZ32( (uint32_t)x - 1 ) ); +} diff --git a/3rdparty/box2d/src/distance.c b/3rdparty/box2d/src/distance.c new file mode 100644 index 000000000000..415ca80c265e --- /dev/null +++ b/3rdparty/box2d/src/distance.c @@ -0,0 +1,1415 @@ + +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constants.h" +#include "core.h" + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include +#include + +b2Transform b2GetSweepTransform( const b2Sweep* sweep, float time ) +{ + // https://fgiesen.wordpress.com/2012/08/15/linear-interpolation-past-present-and-future/ + b2Transform xf; + xf.p = b2Add( b2MulSV( 1.0f - time, sweep->c1 ), b2MulSV( time, sweep->c2 ) ); + + b2Rot q = { + ( 1.0f - time ) * sweep->q1.c + time * sweep->q2.c, + ( 1.0f - time ) * sweep->q1.s + time * sweep->q2.s, + }; + + xf.q = b2NormalizeRot( q ); + + // Shift to origin + xf.p = b2Sub( xf.p, b2RotateVector( xf.q, sweep->localCenter ) ); + return xf; +} + +/// Follows Ericson 5.1.9 Closest Points of Two Line Segments +b2SegmentDistanceResult b2SegmentDistance( b2Vec2 p1, b2Vec2 q1, b2Vec2 p2, b2Vec2 q2 ) +{ + b2SegmentDistanceResult result = { 0 }; + + b2Vec2 d1 = b2Sub( q1, p1 ); + b2Vec2 d2 = b2Sub( q2, p2 ); + b2Vec2 r = b2Sub( p1, p2 ); + float dd1 = b2Dot( d1, d1 ); + float dd2 = b2Dot( d2, d2 ); + float rd1 = b2Dot( r, d1 ); + float rd2 = b2Dot( r, d2 ); + + const float epsSqr = FLT_EPSILON * FLT_EPSILON; + + if ( dd1 < epsSqr || dd2 < epsSqr ) + { + // Handle all degeneracies + if ( dd1 >= epsSqr ) + { + // Segment 2 is degenerate + result.fraction1 = b2ClampFloat( -rd1 / dd1, 0.0f, 1.0f ); + result.fraction2 = 0.0f; + } + else if ( dd2 >= epsSqr ) + { + // Segment 1 is degenerate + result.fraction1 = 0.0f; + result.fraction2 = b2ClampFloat( rd2 / dd2, 0.0f, 1.0f ); + } + else + { + result.fraction1 = 0.0f; + result.fraction2 = 0.0f; + } + } + else + { + // Non-degenerate segments + float d12 = b2Dot( d1, d2 ); + + float denominator = dd1 * dd2 - d12 * d12; + + // Fraction on segment 1 + float f1 = 0.0f; + if ( denominator != 0.0f ) + { + // not parallel + f1 = b2ClampFloat( ( d12 * rd2 - rd1 * dd2 ) / denominator, 0.0f, 1.0f ); + } + + // Compute point on segment 2 closest to p1 + f1 * d1 + float f2 = ( d12 * f1 + rd2 ) / dd2; + + // Clamping of segment 2 requires a do over on segment 1 + if ( f2 < 0.0f ) + { + f2 = 0.0f; + f1 = b2ClampFloat( -rd1 / dd1, 0.0f, 1.0f ); + } + else if ( f2 > 1.0f ) + { + f2 = 1.0f; + f1 = b2ClampFloat( ( d12 - rd1 ) / dd1, 0.0f, 1.0f ); + } + + result.fraction1 = f1; + result.fraction2 = f2; + } + + result.closest1 = b2MulAdd( p1, result.fraction1, d1 ); + result.closest2 = b2MulAdd( p2, result.fraction2, d2 ); + result.distanceSquared = b2DistanceSquared( result.closest1, result.closest2 ); + return result; +} + +b2ShapeProxy b2MakeProxy( const b2Vec2* points, int count, float radius ) +{ + count = b2MinInt( count, B2_MAX_POLYGON_VERTICES ); + b2ShapeProxy proxy; + for ( int i = 0; i < count; ++i ) + { + proxy.points[i] = points[i]; + } + proxy.count = count; + proxy.radius = radius; + return proxy; +} + +b2ShapeProxy b2MakeOffsetProxy( const b2Vec2* points, int count, float radius, b2Vec2 position, b2Rot rotation ) +{ + count = b2MinInt( count, B2_MAX_POLYGON_VERTICES ); + b2Transform transform = { + .p = position, + .q = rotation, + }; + b2ShapeProxy proxy; + for ( int i = 0; i < count; ++i ) + { + proxy.points[i] = b2TransformPoint( transform, points[i] ); + } + proxy.count = count; + proxy.radius = radius; + return proxy; +} + +static inline b2Vec2 b2Weight2( float a1, b2Vec2 w1, float a2, b2Vec2 w2 ) +{ + return (b2Vec2){ a1 * w1.x + a2 * w2.x, a1 * w1.y + a2 * w2.y }; +} + +static inline b2Vec2 b2Weight3( float a1, b2Vec2 w1, float a2, b2Vec2 w2, float a3, b2Vec2 w3 ) +{ + return (b2Vec2){ a1 * w1.x + a2 * w2.x + a3 * w3.x, a1 * w1.y + a2 * w2.y + a3 * w3.y }; +} + +static inline int b2FindSupport( const b2ShapeProxy* proxy, b2Vec2 direction ) +{ + const b2Vec2* points = proxy->points; + int count = proxy->count; + + int bestIndex = 0; + float bestValue = b2Dot( points[0], direction ); + for ( int i = 1; i < count; ++i ) + { + float value = b2Dot( points[i], direction ); + if ( value > bestValue ) + { + bestIndex = i; + bestValue = value; + } + } + + return bestIndex; +} + +static b2Simplex b2MakeSimplexFromCache( const b2SimplexCache* cache, const b2ShapeProxy* proxyA, const b2ShapeProxy* proxyB ) +{ + B2_ASSERT( cache->count <= 3 ); + b2Simplex s; + + // Copy data from cache. + s.count = cache->count; + + b2SimplexVertex* vertices[] = { &s.v1, &s.v2, &s.v3 }; + for ( int i = 0; i < s.count; ++i ) + { + b2SimplexVertex* v = vertices[i]; + v->indexA = cache->indexA[i]; + v->indexB = cache->indexB[i]; + v->wA = proxyA->points[v->indexA]; + v->wB = proxyB->points[v->indexB]; + v->w = b2Sub( v->wA, v->wB ); + + // invalid + v->a = -1.0f; + } + + // If the cache is empty or invalid ... + if ( s.count == 0 ) + { + b2SimplexVertex* v = vertices[0]; + v->indexA = 0; + v->indexB = 0; + v->wA = proxyA->points[0]; + v->wB = proxyB->points[0]; + v->w = b2Sub( v->wA, v->wB ); + v->a = 1.0f; + s.count = 1; + } + + return s; +} + +static void b2MakeSimplexCache( b2SimplexCache* cache, const b2Simplex* simplex ) +{ + cache->count = (uint16_t)simplex->count; + const b2SimplexVertex* vertices[] = { &simplex->v1, &simplex->v2, &simplex->v3 }; + for ( int i = 0; i < simplex->count; ++i ) + { + cache->indexA[i] = (uint8_t)vertices[i]->indexA; + cache->indexB[i] = (uint8_t)vertices[i]->indexB; + } +} + +static void b2ComputeSimplexWitnessPoints( b2Vec2* a, b2Vec2* b, const b2Simplex* s ) +{ + switch ( s->count ) + { + case 0: + B2_ASSERT( false ); + break; + + case 1: + *a = s->v1.wA; + *b = s->v1.wB; + break; + + case 2: + *a = b2Weight2( s->v1.a, s->v1.wA, s->v2.a, s->v2.wA ); + *b = b2Weight2( s->v1.a, s->v1.wB, s->v2.a, s->v2.wB ); + break; + + case 3: + *a = b2Weight3( s->v1.a, s->v1.wA, s->v2.a, s->v2.wA, s->v3.a, s->v3.wA ); + // todo why are these not equal? + //*b = b2Weight3(s->v1.a, s->v1.wB, s->v2.a, s->v2.wB, s->v3.a, s->v3.wB); + *b = *a; + break; + + default: + B2_ASSERT( false ); + break; + } +} + +// Solve a line segment using barycentric coordinates. +// +// p = a1 * w1 + a2 * w2 +// a1 + a2 = 1 +// +// The vector from the origin to the closest point on the line is +// perpendicular to the line. +// e12 = w2 - w1 +// dot(p, e) = 0 +// a1 * dot(w1, e) + a2 * dot(w2, e) = 0 +// +// 2-by-2 linear system +// [1 1 ][a1] = [1] +// [w1.e12 w2.e12][a2] = [0] +// +// Define +// d12_1 = dot(w2, e12) +// d12_2 = -dot(w1, e12) +// d12 = d12_1 + d12_2 +// +// Solution +// a1 = d12_1 / d12 +// a2 = d12_2 / d12 +// +// returns a vector that points towards the origin +static b2Vec2 b2SolveSimplex2( b2Simplex* s ) +{ + b2Vec2 w1 = s->v1.w; + b2Vec2 w2 = s->v2.w; + b2Vec2 e12 = b2Sub( w2, w1 ); + + // w1 region + float d12_2 = -b2Dot( w1, e12 ); + if ( d12_2 <= 0.0f ) + { + // a2 <= 0, so we clamp it to 0 + s->v1.a = 1.0f; + s->count = 1; + return b2Neg( w1 ); + } + + // w2 region + float d12_1 = b2Dot( w2, e12 ); + if ( d12_1 <= 0.0f ) + { + // a1 <= 0, so we clamp it to 0 + s->v2.a = 1.0f; + s->count = 1; + s->v1 = s->v2; + return b2Neg( w2 ); + } + + // Must be in e12 region. + float inv_d12 = 1.0f / ( d12_1 + d12_2 ); + s->v1.a = d12_1 * inv_d12; + s->v2.a = d12_2 * inv_d12; + s->count = 2; + return b2CrossSV( b2Cross( b2Add( w1, w2 ), e12 ), e12 ); +} + +static b2Vec2 b2SolveSimplex3( b2Simplex* s ) +{ + b2Vec2 w1 = s->v1.w; + b2Vec2 w2 = s->v2.w; + b2Vec2 w3 = s->v3.w; + + // Edge12 + // [1 1 ][a1] = [1] + // [w1.e12 w2.e12][a2] = [0] + // a3 = 0 + b2Vec2 e12 = b2Sub( w2, w1 ); + float w1e12 = b2Dot( w1, e12 ); + float w2e12 = b2Dot( w2, e12 ); + float d12_1 = w2e12; + float d12_2 = -w1e12; + + // Edge13 + // [1 1 ][a1] = [1] + // [w1.e13 w3.e13][a3] = [0] + // a2 = 0 + b2Vec2 e13 = b2Sub( w3, w1 ); + float w1e13 = b2Dot( w1, e13 ); + float w3e13 = b2Dot( w3, e13 ); + float d13_1 = w3e13; + float d13_2 = -w1e13; + + // Edge23 + // [1 1 ][a2] = [1] + // [w2.e23 w3.e23][a3] = [0] + // a1 = 0 + b2Vec2 e23 = b2Sub( w3, w2 ); + float w2e23 = b2Dot( w2, e23 ); + float w3e23 = b2Dot( w3, e23 ); + float d23_1 = w3e23; + float d23_2 = -w2e23; + + // Triangle123 + float n123 = b2Cross( e12, e13 ); + + float d123_1 = n123 * b2Cross( w2, w3 ); + float d123_2 = n123 * b2Cross( w3, w1 ); + float d123_3 = n123 * b2Cross( w1, w2 ); + + // w1 region + if ( d12_2 <= 0.0f && d13_2 <= 0.0f ) + { + s->v1.a = 1.0f; + s->count = 1; + return b2Neg( w1 ); + } + + // e12 + if ( d12_1 > 0.0f && d12_2 > 0.0f && d123_3 <= 0.0f ) + { + float inv_d12 = 1.0f / ( d12_1 + d12_2 ); + s->v1.a = d12_1 * inv_d12; + s->v2.a = d12_2 * inv_d12; + s->count = 2; + return b2CrossSV( b2Cross( b2Add( w1, w2 ), e12 ), e12 ); + } + + // e13 + if ( d13_1 > 0.0f && d13_2 > 0.0f && d123_2 <= 0.0f ) + { + float inv_d13 = 1.0f / ( d13_1 + d13_2 ); + s->v1.a = d13_1 * inv_d13; + s->v3.a = d13_2 * inv_d13; + s->count = 2; + s->v2 = s->v3; + return b2CrossSV( b2Cross( b2Add( w1, w3 ), e13 ), e13 ); + } + + // w2 region + if ( d12_1 <= 0.0f && d23_2 <= 0.0f ) + { + s->v2.a = 1.0f; + s->count = 1; + s->v1 = s->v2; + return b2Neg( w2 ); + } + + // w3 region + if ( d13_1 <= 0.0f && d23_1 <= 0.0f ) + { + s->v3.a = 1.0f; + s->count = 1; + s->v1 = s->v3; + return b2Neg( w3 ); + } + + // e23 + if ( d23_1 > 0.0f && d23_2 > 0.0f && d123_1 <= 0.0f ) + { + float inv_d23 = 1.0f / ( d23_1 + d23_2 ); + s->v2.a = d23_1 * inv_d23; + s->v3.a = d23_2 * inv_d23; + s->count = 2; + s->v1 = s->v3; + return b2CrossSV( b2Cross( b2Add( w2, w3 ), e23 ), e23 ); + } + + // Must be in triangle123 + float inv_d123 = 1.0f / ( d123_1 + d123_2 + d123_3 ); + s->v1.a = d123_1 * inv_d123; + s->v2.a = d123_2 * inv_d123; + s->v3.a = d123_3 * inv_d123; + s->count = 3; + + // No search direction + return b2Vec2_zero; +} + +// Uses GJK for computing the distance between convex shapes. +// https://box2d.org/files/ErinCatto_GJK_GDC2010.pdf +// I spent time optimizing this and could find no further significant gains 3/30/2025 +b2DistanceOutput b2ShapeDistance( const b2DistanceInput* input, b2SimplexCache* cache, b2Simplex* simplexes, int simplexCapacity ) +{ + B2_UNUSED( simplexes, simplexCapacity ); + B2_ASSERT( input->proxyA.count > 0 && input->proxyB.count > 0 ); + B2_ASSERT( input->proxyA.radius >= 0.0f ); + B2_ASSERT( input->proxyB.radius >= 0.0f ); + + b2DistanceOutput output = { 0 }; + + const b2ShapeProxy* proxyA = &input->proxyA; + + // Get proxyB in frame A to avoid further transforms in the main loop. + // This is still a performance gain at 8 points. + b2ShapeProxy localProxyB; + { + b2Transform transform = b2InvMulTransforms( input->transformA, input->transformB ); + localProxyB.count = input->proxyB.count; + localProxyB.radius = input->proxyB.radius; + for ( int i = 0; i < localProxyB.count; ++i ) + { + localProxyB.points[i] = b2TransformPoint( transform, input->proxyB.points[i] ); + } + } + + // Initialize the simplex. + b2Simplex simplex = b2MakeSimplexFromCache( cache, proxyA, &localProxyB ); + + int simplexIndex = 0; + if ( simplexes != NULL && simplexIndex < simplexCapacity ) + { + simplexes[simplexIndex] = simplex; + simplexIndex += 1; + } + + // Get simplex vertices as an array. + b2SimplexVertex* vertices[] = { &simplex.v1, &simplex.v2, &simplex.v3 }; + + b2Vec2 nonUnitNormal = b2Vec2_zero; + + // These store the vertices of the last simplex so that we can check for duplicates and prevent cycling. + int saveA[3], saveB[3]; + + // Main iteration loop. All computations are done in frame A. + const int maxIterations = 20; + int iteration = 0; + while ( iteration < maxIterations ) + { + // Copy simplex so we can identify duplicates. + int saveCount = simplex.count; + for ( int i = 0; i < saveCount; ++i ) + { + saveA[i] = vertices[i]->indexA; + saveB[i] = vertices[i]->indexB; + } + + b2Vec2 d = { 0 }; + switch ( simplex.count ) + { + case 1: + d = b2Neg( simplex.v1.w ); + break; + + case 2: + d = b2SolveSimplex2( &simplex ); + break; + + case 3: + d = b2SolveSimplex3( &simplex ); + break; + + default: + B2_ASSERT( false ); + } + + // If we have 3 points, then the origin is in the corresponding triangle. + if ( simplex.count == 3 ) + { + break; + } + +#ifndef NDEBUG + if ( simplexes != NULL && simplexIndex < simplexCapacity ) + { + simplexes[simplexIndex] = simplex; + simplexIndex += 1; + } +#endif + + // Save the normal + nonUnitNormal = d; + + // Ensure the search direction is numerically fit. + if ( b2Dot( d, d ) < FLT_EPSILON * FLT_EPSILON ) + { + // This is unlikely but could lead to bad cycling. + // The branch predictor seems to make this check have low cost. + + // The origin is probably contained by a line segment + // or triangle. Thus the shapes are overlapped. + + // We can't return zero here even though there may be overlap. + // In case the simplex is a point, segment, or triangle it is difficult + // to determine if the origin is contained in the CSO or very close to it. + break; + } + + // Compute a tentative new simplex vertex using support points. + // support = support(a, d) - support(b, -d) + b2SimplexVertex* vertex = vertices[simplex.count]; + vertex->indexA = b2FindSupport( proxyA, d ); + vertex->wA = proxyA->points[vertex->indexA]; + vertex->indexB = b2FindSupport( &localProxyB, b2Neg( d ) ); + vertex->wB = localProxyB.points[vertex->indexB]; + vertex->w = b2Sub( vertex->wA, vertex->wB ); + + // Iteration count is equated to the number of support point calls. + ++iteration; + + // Check for duplicate support points. This is the main termination criteria. + bool duplicate = false; + for ( int i = 0; i < saveCount; ++i ) + { + if ( vertex->indexA == saveA[i] && vertex->indexB == saveB[i] ) + { + duplicate = true; + break; + } + } + + // If we found a duplicate support point we must exit to avoid cycling. + if ( duplicate ) + { + break; + } + + // New vertex is valid and needed. + simplex.count += 1; + } + +#ifndef NDEBUG + if ( simplexes != NULL && simplexIndex < simplexCapacity ) + { + simplexes[simplexIndex] = simplex; + simplexIndex += 1; + } +#endif + + // Prepare output + b2Vec2 normal = b2Normalize( nonUnitNormal ); + normal = b2RotateVector( input->transformA.q, normal ); + + b2Vec2 localPointA, localPointB; + b2ComputeSimplexWitnessPoints( &localPointA, &localPointB, &simplex ); + output.normal = normal; + output.distance = b2Distance( localPointA, localPointB ); + output.pointA = b2TransformPoint( input->transformA, localPointA ); + output.pointB = b2TransformPoint( input->transformA, localPointB ); + output.iterations = iteration; + output.simplexCount = simplexIndex; + + // Cache the simplex + b2MakeSimplexCache( cache, &simplex ); + + // Apply radii if requested + if ( input->useRadii && output.distance > 0.1f * B2_LINEAR_SLOP ) + { + float radiusA = input->proxyA.radius; + float radiusB = input->proxyB.radius; + output.distance = b2MaxFloat( 0.0f, output.distance - radiusA - radiusB ); + + // Keep closest points on perimeter even if overlapped, this way the points move smoothly. + output.pointA = b2MulAdd( output.pointA, radiusA, normal ); + output.pointB = b2MulSub( output.pointB, radiusB, normal ); + } + + return output; +} + +// Shape cast using conservative advancement +b2CastOutput b2ShapeCast( const b2ShapeCastPairInput* input ) +{ + // Compute tolerance + float linearSlop = B2_LINEAR_SLOP; + float totalRadius = input->proxyA.radius + input->proxyB.radius; + float target = b2MaxFloat( linearSlop, totalRadius - linearSlop ); + float tolerance = 0.25f * linearSlop; + + B2_ASSERT( target > tolerance ); + + // Prepare input for distance query + b2SimplexCache cache = { 0 }; + + float alpha = 0.0f; + + b2DistanceInput distanceInput = { 0 }; + distanceInput.proxyA = input->proxyA; + distanceInput.proxyB = input->proxyB; + distanceInput.transformA = input->transformA; + distanceInput.transformB = input->transformB; + distanceInput.useRadii = false; + + b2Vec2 delta2 = input->translationB; + b2CastOutput output = { 0 }; + + int iteration = 0; + int maxIterations = 20; + for ( ; iteration < maxIterations; ++iteration ) + { + output.iterations += 1; + + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + if ( distanceOutput.distance < target + tolerance ) + { + if ( iteration == 0 ) + { + if ( input->canEncroach && distanceOutput.distance > 2.0f * linearSlop ) + { + target = distanceOutput.distance - linearSlop; + } + else + { + if ( distanceOutput.distance == 0.0f ) + { + // Normal may be invalid + return output; + } + + // Initial overlap but distance is non-zero due to radius + B2_ASSERT( b2IsNormalized( distanceOutput.normal ) ); + output.fraction = alpha; + output.point = b2MulAdd( distanceOutput.pointA, input->proxyA.radius, distanceOutput.normal ); + output.normal = distanceOutput.normal; + output.hit = true; + return output; + } + } + else + { + // Regular hit + B2_ASSERT( distanceOutput.distance > 0.0f && b2IsNormalized( distanceOutput.normal ) ); + output.fraction = alpha; + output.point = b2MulAdd( distanceOutput.pointA, input->proxyA.radius, distanceOutput.normal ); + output.normal = distanceOutput.normal; + output.hit = true; + return output; + } + } + + B2_ASSERT( distanceOutput.distance > 0.0f ); + B2_ASSERT( b2IsNormalized( distanceOutput.normal ) ); + + // Check if shapes are approaching each other + float denominator = b2Dot( delta2, distanceOutput.normal ); + if ( denominator >= 0.0f ) + { + // Miss + output.fraction = 1.0f; + return output; + } + + // Advance sweep + alpha += ( target - distanceOutput.distance ) / denominator; + if ( alpha >= input->maxFraction ) + { + // Miss + output.fraction = 1.0f; + return output; + } + + distanceInput.transformB.p = b2MulAdd( input->transformB.p, alpha, delta2 ); + } + + // Failure! + return output; +} + +#if 0 +static inline b2Vec2 b2ComputeSimplexClosestPoint( const b2Simplex* s ) +{ + if ( s->count == 1 ) + { + return s->v1.w; + } + + if ( s->count == 2 ) + { + return b2Weight2( s->v1.a, s->v1.w, s->v2.a, s->v2.w ); + } + + return b2Vec2_zero; +} + +typedef struct b2ShapeCastData +{ + b2Simplex simplex; + b2Vec2 closestA, closestB; + b2Vec2 normal; + b2Vec2 p0; + float fraction; +} b2ShapeCastData; + +// GJK-raycast +// Algorithm by Gino van den Bergen. +// "Smooth Mesh Contacts with GJK" in Game Physics Pearls. 2010 +// This needs the simplex of A - B because the translation is for B and this +// is how the relative motion works out when both shapes are translating. +// This is similar to ray vs polygon and involves plane clipping. See b2RayCastPolygon. +// In this case the polygon is just points and there are no planes. This uses a modified +// version of GJK to generate planes for clipping. +// The algorithm works by incrementally building clipping planes using GJK. Once a valid +// clip plane is found the simplex origin is moved to the current fraction on the ray. +// This resets the simplex after every clip. Later I should compare performance. +// However, adapting this to work with encroachment is tricky and confusing because encroachment +// needs distance. +// Note: this algorithm is difficult to debug and not worth the effort in my opinion 4/1/2025 +b2CastOutput b2ShapeCastMerged( const b2ShapeCastPairInput* input, b2ShapeCastData* debugData, int debugCapacity ) +{ + B2_UNUSED( debugData, debugCapacity ); + + b2CastOutput output = { 0 }; + output.fraction = input->maxFraction; + + b2ShapeProxy proxyA = input->proxyA; + + b2Transform xf = b2InvMulTransforms( input->transformA, input->transformB ); + + // Put proxyB in proxyA's frame to reduce round-off error + b2ShapeProxy proxyB; + proxyB.count = input->proxyB.count; + proxyB.radius = input->proxyB.radius; + B2_ASSERT( proxyB.count <= B2_MAX_POLYGON_VERTICES ); + + for ( int i = 0; i < proxyB.count; ++i ) + { + proxyB.points[i] = b2TransformPoint( xf, input->proxyB.points[i] ); + } + + float radius = proxyA.radius + proxyB.radius; + + b2Vec2 r = b2RotateVector( xf.q, input->translationB ); + float lambda = 0.0f; + float maxFraction = input->maxFraction; + + // Initial simplex + b2Simplex simplex; + simplex.count = 0; + + // Get simplex vertices as an array. + b2SimplexVertex* vertices[] = { &simplex.v1, &simplex.v2, &simplex.v3 }; + + // Get an initial point in A - B + b2Vec2 wA = proxyA.points[0]; + b2Vec2 wB = proxyB.points[0]; + b2Vec2 v = b2Sub( wA, wB ); + b2Vec2 d = b2Neg( v ); + + // Sigma is the target distance between proxies + const float linearSlop = B2_LINEAR_SLOP; + const float sigma = b2MaxFloat( linearSlop, radius - linearSlop ); + float tolerance = 0.5f * linearSlop; + float stolSquared = ( sigma + tolerance ) * ( sigma + tolerance ); + + // Main iteration loop. + const int maxIterations = 20; + int iteration = 0; + while ( iteration < maxIterations && b2LengthSquared( v ) > stolSquared ) + { + B2_ASSERT( simplex.count < 3 ); + + // Support in direction d (A - B) + int indexA = b2FindSupport( &proxyA, d ); + wA = proxyA.points[indexA]; + int indexB = b2FindSupport( &proxyB, b2Neg( d ) ); + wB = proxyB.points[indexB]; + b2Vec2 p0 = b2Sub( wA, wB ); + + // d is a normal at p, normalize to work with sigma + b2Vec2 normal = b2Normalize( d ); + + // Intersect ray with plane + // p = origin + t * r + // dot(n, p - p0) = sigma + // dot(n, origin - p0) + t * dot(n, r) = sigma + // t = ( dot(n, p0) + sigma) / dot(n, r) + // if t < (dot(n, p0) + sigma) / dot(n, r) then t can be increased + // or (flipping sign because dot(n,r) < 0) + // dot(n, p0) + sigma < t * dot(n, r) && dot(n, r) < 0 + float np0 = b2Dot( normal, p0 ); + float nr = b2Dot( normal, r ); + if ( np0 + sigma < lambda * nr ) + { + if ( nr >= 0.0f ) + { + // miss + return output; + } + + lambda = ( np0 + sigma ) / nr; + if ( lambda > maxFraction ) + { + // too far + return output; + } + + // reset the simplex + simplex.count = 0; + } + + // Shift by lambda * r because we want the closest point to the current clip point. + // Note that the support point p is not shifted because we want the plane equation + // to be formed in un-shifted space. + b2SimplexVertex* vertex = vertices[simplex.count]; + vertex->indexA = indexB; + vertex->wA = wA; + vertex->indexB = indexA; + vertex->wB = (b2Vec2){ wB.x + lambda * r.x, wB.y + lambda * r.y }; + vertex->w = b2Sub( vertex->wA, vertex->wB ); + vertex->a = 1.0f; + simplex.count += 1; + + switch ( simplex.count ) + { + case 1: + d = b2Neg( simplex.v1.w ); + break; + + case 2: + d = b2SolveSimplex2( &simplex ); + break; + + case 3: + d = b2SolveSimplex3( &simplex ); + break; + + default: + B2_ASSERT( false ); + } + +#ifndef NDEBUG + if ( debugData != NULL && output.iterations < debugCapacity ) + { + debugData[output.iterations].simplex = simplex; + debugData[output.iterations].normal = normal; + debugData[output.iterations].p0 = p0; + b2Vec2 cA, cB; + b2ComputeSimplexWitnessPoints( &cA, &cB, &simplex ); + debugData[output.iterations].closestA = cA; + debugData[output.iterations].closestB = cB; + debugData[output.iterations].fraction = lambda; + } +#endif + + output.iterations += 1; + + // If we have 3 points, then the origin is in the corresponding triangle. + if ( simplex.count == 3 ) + { + // Overlap + return output; + } + + // Get distance vector + v = b2ComputeSimplexClosestPoint( &simplex ); + + // Iteration count is equated to the number of support point calls. + ++iteration; + } + + if ( iteration == 0 || lambda == 0.0f ) + { + // Initial overlap + return output; + } + + // Prepare output. + b2Vec2 pointA, pointB; + b2ComputeSimplexWitnessPoints( &pointB, &pointA, &simplex ); + + b2Vec2 n = b2Normalize( b2Neg( v ) ); + b2Vec2 point = { pointA.x + proxyA.radius * n.x, pointA.y + proxyA.radius * n.y }; + + output.point = b2TransformPoint( input->transformA, point ); + output.normal = b2RotateVector( input->transformA.q, n ); + output.fraction = lambda; + output.iterations = iteration; + output.hit = true; + return output; +} +#endif + +// Warning: writing to these globals significantly slows multithreading performance +#if B2_SNOOP_TOI_COUNTERS +float b2_toiTime, b2_toiMaxTime; +int b2_toiCalls, b2_toiDistanceIterations, b2_toiMaxDistanceIterations; +int b2_toiRootIterations, b2_toiMaxRootIterations; +int b2_toiFailedCount; +int b2_toiOverlappedCount; +int b2_toiHitCount; +int b2_toiSeparatedCount; +#endif + +typedef enum b2SeparationType +{ + b2_pointsType, + b2_faceAType, + b2_faceBType +} b2SeparationType; + +typedef struct b2SeparationFunction +{ + const b2ShapeProxy* proxyA; + const b2ShapeProxy* proxyB; + b2Sweep sweepA, sweepB; + b2Vec2 localPoint; + b2Vec2 axis; + b2SeparationType type; +} b2SeparationFunction; + +static b2SeparationFunction b2MakeSeparationFunction( const b2SimplexCache* cache, const b2ShapeProxy* proxyA, + const b2Sweep* sweepA, const b2ShapeProxy* proxyB, const b2Sweep* sweepB, + float t1 ) +{ + b2SeparationFunction f; + + f.proxyA = proxyA; + f.proxyB = proxyB; + int count = cache->count; + B2_ASSERT( 0 < count && count < 3 ); + + f.sweepA = *sweepA; + f.sweepB = *sweepB; + + b2Transform xfA = b2GetSweepTransform( sweepA, t1 ); + b2Transform xfB = b2GetSweepTransform( sweepB, t1 ); + + if ( count == 1 ) + { + f.type = b2_pointsType; + b2Vec2 localPointA = proxyA->points[cache->indexA[0]]; + b2Vec2 localPointB = proxyB->points[cache->indexB[0]]; + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + f.axis = b2Normalize( b2Sub( pointB, pointA ) ); + f.localPoint = b2Vec2_zero; + return f; + } + + if ( cache->indexA[0] == cache->indexA[1] ) + { + // Two points on B and one on A. + f.type = b2_faceBType; + b2Vec2 localPointB1 = proxyB->points[cache->indexB[0]]; + b2Vec2 localPointB2 = proxyB->points[cache->indexB[1]]; + + f.axis = b2CrossVS( b2Sub( localPointB2, localPointB1 ), 1.0f ); + f.axis = b2Normalize( f.axis ); + b2Vec2 normal = b2RotateVector( xfB.q, f.axis ); + + f.localPoint = (b2Vec2){ 0.5f * ( localPointB1.x + localPointB2.x ), 0.5f * ( localPointB1.y + localPointB2.y ) }; + b2Vec2 pointB = b2TransformPoint( xfB, f.localPoint ); + + b2Vec2 localPointA = proxyA->points[cache->indexA[0]]; + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + + float s = b2Dot( b2Sub( pointA, pointB ), normal ); + if ( s < 0.0f ) + { + f.axis = b2Neg( f.axis ); + } + return f; + } + + // Two points on A and one or two points on B. + f.type = b2_faceAType; + b2Vec2 localPointA1 = proxyA->points[cache->indexA[0]]; + b2Vec2 localPointA2 = proxyA->points[cache->indexA[1]]; + + f.axis = b2CrossVS( b2Sub( localPointA2, localPointA1 ), 1.0f ); + f.axis = b2Normalize( f.axis ); + b2Vec2 normal = b2RotateVector( xfA.q, f.axis ); + + f.localPoint = (b2Vec2){ 0.5f * ( localPointA1.x + localPointA2.x ), 0.5f * ( localPointA1.y + localPointA2.y ) }; + b2Vec2 pointA = b2TransformPoint( xfA, f.localPoint ); + + b2Vec2 localPointB = proxyB->points[cache->indexB[0]]; + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + + float s = b2Dot( b2Sub( pointB, pointA ), normal ); + if ( s < 0.0f ) + { + f.axis = b2Neg( f.axis ); + } + return f; +} + +static float b2FindMinSeparation( const b2SeparationFunction* f, int* indexA, int* indexB, float t ) +{ + b2Transform xfA = b2GetSweepTransform( &f->sweepA, t ); + b2Transform xfB = b2GetSweepTransform( &f->sweepB, t ); + + switch ( f->type ) + { + case b2_pointsType: + { + b2Vec2 axisA = b2InvRotateVector( xfA.q, f->axis ); + b2Vec2 axisB = b2InvRotateVector( xfB.q, b2Neg( f->axis ) ); + + *indexA = b2FindSupport( f->proxyA, axisA ); + *indexB = b2FindSupport( f->proxyB, axisB ); + + b2Vec2 localPointA = f->proxyA->points[*indexA]; + b2Vec2 localPointB = f->proxyB->points[*indexB]; + + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + + float separation = b2Dot( b2Sub( pointB, pointA ), f->axis ); + return separation; + } + + case b2_faceAType: + { + b2Vec2 normal = b2RotateVector( xfA.q, f->axis ); + b2Vec2 pointA = b2TransformPoint( xfA, f->localPoint ); + + b2Vec2 axisB = b2InvRotateVector( xfB.q, b2Neg( normal ) ); + + *indexA = -1; + *indexB = b2FindSupport( f->proxyB, axisB ); + + b2Vec2 localPointB = f->proxyB->points[*indexB]; + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + + float separation = b2Dot( b2Sub( pointB, pointA ), normal ); + return separation; + } + + case b2_faceBType: + { + b2Vec2 normal = b2RotateVector( xfB.q, f->axis ); + b2Vec2 pointB = b2TransformPoint( xfB, f->localPoint ); + + b2Vec2 axisA = b2InvRotateVector( xfA.q, b2Neg( normal ) ); + + *indexB = -1; + *indexA = b2FindSupport( f->proxyA, axisA ); + + b2Vec2 localPointA = f->proxyA->points[*indexA]; + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + + float separation = b2Dot( b2Sub( pointA, pointB ), normal ); + return separation; + } + + default: + B2_ASSERT( false ); + *indexA = -1; + *indexB = -1; + return 0.0f; + } +} + +// +static float b2EvaluateSeparation( const b2SeparationFunction* f, int indexA, int indexB, float t ) +{ + b2Transform xfA = b2GetSweepTransform( &f->sweepA, t ); + b2Transform xfB = b2GetSweepTransform( &f->sweepB, t ); + + switch ( f->type ) + { + case b2_pointsType: + { + b2Vec2 localPointA = f->proxyA->points[indexA]; + b2Vec2 localPointB = f->proxyB->points[indexB]; + + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + + float separation = b2Dot( b2Sub( pointB, pointA ), f->axis ); + return separation; + } + + case b2_faceAType: + { + b2Vec2 normal = b2RotateVector( xfA.q, f->axis ); + b2Vec2 pointA = b2TransformPoint( xfA, f->localPoint ); + + b2Vec2 localPointB = f->proxyB->points[indexB]; + b2Vec2 pointB = b2TransformPoint( xfB, localPointB ); + + float separation = b2Dot( b2Sub( pointB, pointA ), normal ); + return separation; + } + + case b2_faceBType: + { + b2Vec2 normal = b2RotateVector( xfB.q, f->axis ); + b2Vec2 pointB = b2TransformPoint( xfB, f->localPoint ); + + b2Vec2 localPointA = f->proxyA->points[indexA]; + b2Vec2 pointA = b2TransformPoint( xfA, localPointA ); + + float separation = b2Dot( b2Sub( pointA, pointB ), normal ); + return separation; + } + + default: + B2_ASSERT( false ); + return 0.0f; + } +} + +// CCD via the local separating axis method. This seeks progression +// by computing the largest time at which separation is maintained. +b2TOIOutput b2TimeOfImpact( const b2TOIInput* input ) +{ +#if B2_SNOOP_TOI_COUNTERS + uint64_t ticks = b2GetTicks(); + ++b2_toiCalls; +#endif + + b2TOIOutput output; + output.state = b2_toiStateUnknown; + output.fraction = input->maxFraction; + + b2Sweep sweepA = input->sweepA; + b2Sweep sweepB = input->sweepB; + B2_ASSERT( b2IsNormalizedRot( sweepA.q1 ) && b2IsNormalizedRot( sweepA.q2 ) ); + B2_ASSERT( b2IsNormalizedRot( sweepB.q1 ) && b2IsNormalizedRot( sweepB.q2 ) ); + + // todo_erin + // c1 can be at the origin yet the points are far away + // b2Vec2 origin = b2Add(sweepA.c1, input->proxyA.points[0]); + + const b2ShapeProxy* proxyA = &input->proxyA; + const b2ShapeProxy* proxyB = &input->proxyB; + + float tMax = input->maxFraction; + + float totalRadius = proxyA->radius + proxyB->radius; + // todo_erin consider different target + // float target = b2MaxFloat( B2_LINEAR_SLOP, totalRadius ); + float target = b2MaxFloat( B2_LINEAR_SLOP, totalRadius - B2_LINEAR_SLOP ); + float tolerance = 0.25f * B2_LINEAR_SLOP; + B2_ASSERT( target > tolerance ); + + float t1 = 0.0f; + const int k_maxIterations = 20; + int distanceIterations = 0; + + // Prepare input for distance query. + b2SimplexCache cache = { 0 }; + b2DistanceInput distanceInput; + distanceInput.proxyA = input->proxyA; + distanceInput.proxyB = input->proxyB; + distanceInput.useRadii = false; + + // The outer loop progressively attempts to compute new separating axes. + // This loop terminates when an axis is repeated (no progress is made). + for ( ;; ) + { + b2Transform xfA = b2GetSweepTransform( &sweepA, t1 ); + b2Transform xfB = b2GetSweepTransform( &sweepB, t1 ); + + // Get the distance between shapes. We can also use the results + // to get a separating axis. + distanceInput.transformA = xfA; + distanceInput.transformB = xfB; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + // Progressive time of impact. This handles slender geometry well but introduces + // significant time loss. + // if (distanceIterations == 0) + //{ + // if ( distanceOutput.distance > totalRadius + B2_SPECULATIVE_DISTANCE ) + // { + // target = totalRadius + B2_SPECULATIVE_DISTANCE - tolerance; + // } + // else + // { + // target = distanceOutput.distance - 1.5f * tolerance; + // target = b2MaxFloat( target, 2.0f * tolerance ); + // } + //} + + distanceIterations += 1; +#if B2_SNOOP_TOI_COUNTERS + b2_toiDistanceIterations += 1; +#endif + + // If the shapes are overlapped, we give up on continuous collision. + if ( distanceOutput.distance <= 0.0f ) + { + // Failure! + output.state = b2_toiStateOverlapped; +#if B2_SNOOP_TOI_COUNTERS + b2_toiOverlappedCount += 1; +#endif + output.fraction = 0.0f; + break; + } + + if ( distanceOutput.distance <= target + tolerance ) + { + // Victory! + output.state = b2_toiStateHit; +#if B2_SNOOP_TOI_COUNTERS + b2_toiHitCount += 1; +#endif + output.fraction = t1; + break; + } + + // Initialize the separating axis. + b2SeparationFunction fcn = b2MakeSeparationFunction( &cache, proxyA, &sweepA, proxyB, &sweepB, t1 ); +#if 0 + // Dump the curve seen by the root finder + { + const int N = 100; + float dx = 1.0f / N; + float xs[N + 1]; + float fs[N + 1]; + + float x = 0.0f; + + for (int i = 0; i <= N; ++i) + { + sweepA.GetTransform(&xfA, x); + sweepB.GetTransform(&xfB, x); + float f = fcn.Evaluate(xfA, xfB) - target; + + printf("%g %g\n", x, f); + + xs[i] = x; + fs[i] = f; + + x += dx; + } + } +#endif + + // Compute the TOI on the separating axis. We do this by successively + // resolving the deepest point. This loop is bounded by the number of vertices. + bool done = false; + float t2 = tMax; + int pushBackIterations = 0; + for ( ;; ) + { + // Find the deepest point at t2. Store the witness point indices. + int indexA, indexB; + float s2 = b2FindMinSeparation( &fcn, &indexA, &indexB, t2 ); + + // Is the final configuration separated? + if ( s2 > target + tolerance ) + { + // Victory! + output.state = b2_toiStateSeparated; +#if B2_SNOOP_TOI_COUNTERS + b2_toiSeparatedCount += 1; +#endif + output.fraction = tMax; + done = true; + break; + } + + // Has the separation reached tolerance? + if ( s2 > target - tolerance ) + { + // Advance the sweeps + t1 = t2; + break; + } + + // Compute the initial separation of the witness points. + float s1 = b2EvaluateSeparation( &fcn, indexA, indexB, t1 ); + + // Check for initial overlap. This might happen if the root finder + // runs out of iterations. + if ( s1 < target - tolerance ) + { + output.state = b2_toiStateFailed; +#if B2_SNOOP_TOI_COUNTERS + b2_toiFailedCount += 1; +#endif + output.fraction = t1; + done = true; + break; + } + + // Check for touching + if ( s1 <= target + tolerance ) + { + // Victory! t1 should hold the TOI (could be 0.0). + output.state = b2_toiStateHit; +#if B2_SNOOP_TOI_COUNTERS + b2_toiHitCount += 1; +#endif + output.fraction = t1; + done = true; + break; + } + + // Compute 1D root of: f(x) - target = 0 + int rootIterationCount = 0; + float a1 = t1, a2 = t2; + for ( ;; ) + { + // Use a mix of the secant rule and bisection. + float t; + if ( rootIterationCount & 1 ) + { + // Secant rule to improve convergence. + t = a1 + ( target - s1 ) * ( a2 - a1 ) / ( s2 - s1 ); + } + else + { + // Bisection to guarantee progress. + t = 0.5f * ( a1 + a2 ); + } + + rootIterationCount += 1; + +#if B2_SNOOP_TOI_COUNTERS + ++b2_toiRootIterations; +#endif + + float s = b2EvaluateSeparation( &fcn, indexA, indexB, t ); + + if ( b2AbsFloat( s - target ) < tolerance ) + { + // t2 holds a tentative value for t1 + t2 = t; + break; + } + + // Ensure we continue to bracket the root. + if ( s > target ) + { + a1 = t; + s1 = s; + } + else + { + a2 = t; + s2 = s; + } + + if ( rootIterationCount == 50 ) + { + break; + } + } + +#if B2_SNOOP_TOI_COUNTERS + b2_toiMaxRootIterations = b2MaxInt( b2_toiMaxRootIterations, rootIterationCount ); +#endif + + pushBackIterations += 1; + + if ( pushBackIterations == B2_MAX_POLYGON_VERTICES ) + { + break; + } + } + + if ( done ) + { + break; + } + + if ( distanceIterations == k_maxIterations ) + { + // Root finder got stuck. Semi-victory. + output.state = b2_toiStateFailed; +#if B2_SNOOP_TOI_COUNTERS + b2_toiFailedCount += 1; +#endif + output.fraction = t1; + break; + } + } + +#if B2_SNOOP_TOI_COUNTERS + b2_toiMaxDistanceIterations = b2MaxInt( b2_toiMaxDistanceIterations, distanceIterations ); + + float time = b2GetMilliseconds( ticks ); + b2_toiMaxTime = b2MaxFloat( b2_toiMaxTime, time ); + b2_toiTime += time; +#endif + + return output; +} diff --git a/3rdparty/box2d/src/distance_joint.c b/3rdparty/box2d/src/distance_joint.c new file mode 100644 index 000000000000..016e8acc67b2 --- /dev/null +++ b/3rdparty/box2d/src/distance_joint.c @@ -0,0 +1,556 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include + +void b2DistanceJoint_SetLength( b2JointId jointId, float length ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + + joint->length = b2ClampFloat( length, B2_LINEAR_SLOP, B2_HUGE ); + joint->impulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; +} + +float b2DistanceJoint_GetLength( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->length; +} + +void b2DistanceJoint_EnableLimit( b2JointId jointId, bool enableLimit ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + joint->enableLimit = enableLimit; +} + +bool b2DistanceJoint_IsLimitEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return joint->distanceJoint.enableLimit; +} + +void b2DistanceJoint_SetLengthRange( b2JointId jointId, float minLength, float maxLength ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + + minLength = b2ClampFloat( minLength, B2_LINEAR_SLOP, B2_HUGE ); + maxLength = b2ClampFloat( maxLength, B2_LINEAR_SLOP, B2_HUGE ); + joint->minLength = b2MinFloat( minLength, maxLength ); + joint->maxLength = b2MaxFloat( minLength, maxLength ); + joint->impulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; +} + +float b2DistanceJoint_GetMinLength( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->minLength; +} + +float b2DistanceJoint_GetMaxLength( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->maxLength; +} + +float b2DistanceJoint_GetCurrentLength( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + + b2World* world = b2GetWorld( jointId.world0 ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return 0.0f; + } + + b2Transform transformA = b2GetBodyTransform( world, base->bodyIdA ); + b2Transform transformB = b2GetBodyTransform( world, base->bodyIdB ); + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + b2Vec2 d = b2Sub( pB, pA ); + float length = b2Length( d ); + return length; +} + +void b2DistanceJoint_EnableSpring( b2JointId jointId, bool enableSpring ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + base->distanceJoint.enableSpring = enableSpring; +} + +bool b2DistanceJoint_IsSpringEnabled( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return base->distanceJoint.enableSpring; +} + +void b2DistanceJoint_SetSpringHertz( b2JointId jointId, float hertz ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + base->distanceJoint.hertz = hertz; +} + +void b2DistanceJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + base->distanceJoint.dampingRatio = dampingRatio; +} + +float b2DistanceJoint_GetSpringHertz( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->hertz; +} + +float b2DistanceJoint_GetSpringDampingRatio( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + b2DistanceJoint* joint = &base->distanceJoint; + return joint->dampingRatio; +} + +void b2DistanceJoint_EnableMotor( b2JointId jointId, bool enableMotor ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + if ( enableMotor != joint->distanceJoint.enableMotor ) + { + joint->distanceJoint.enableMotor = enableMotor; + joint->distanceJoint.motorImpulse = 0.0f; + } +} + +bool b2DistanceJoint_IsMotorEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return joint->distanceJoint.enableMotor; +} + +void b2DistanceJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + joint->distanceJoint.motorSpeed = motorSpeed; +} + +float b2DistanceJoint_GetMotorSpeed( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return joint->distanceJoint.motorSpeed; +} + +float b2DistanceJoint_GetMotorForce( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return world->inv_h * base->distanceJoint.motorImpulse; +} + +void b2DistanceJoint_SetMaxMotorForce( b2JointId jointId, float force ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + joint->distanceJoint.maxMotorForce = force; +} + +float b2DistanceJoint_GetMaxMotorForce( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_distanceJoint ); + return joint->distanceJoint.maxMotorForce; +} + +b2Vec2 b2GetDistanceJointForce( b2World* world, b2JointSim* base ) +{ + b2DistanceJoint* joint = &base->distanceJoint; + + b2Transform transformA = b2GetBodyTransform( world, base->bodyIdA ); + b2Transform transformB = b2GetBodyTransform( world, base->bodyIdB ); + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + b2Vec2 d = b2Sub( pB, pA ); + b2Vec2 axis = b2Normalize( d ); + float force = ( joint->impulse + joint->lowerImpulse - joint->upperImpulse + joint->motorImpulse ) * world->inv_h; + return b2MulSV( force, axis ); +} + +// 1-D constrained system +// m (v2 - v1) = lambda +// v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass. +// x2 = x1 + h * v2 + +// 1-D mass-damper-spring system +// m (v2 - v1) + h * d * v2 + h * k * + +// C = norm(p2 - p1) - L +// u = (p2 - p1) / norm(p2 - p1) +// Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1)) +// J = [-u -cross(r1, u) u cross(r2, u)] +// K = J * invM * JT +// = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2 + +void b2PrepareDistanceJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_distanceJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2DistanceJoint* joint = &base->distanceJoint; + + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + // initial anchors in world space + joint->anchorA = b2RotateVector( bodySimA->transform.q, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center ); + + b2Vec2 rA = joint->anchorA; + b2Vec2 rB = joint->anchorB; + b2Vec2 separation = b2Add( b2Sub( rB, rA ), joint->deltaCenter ); + b2Vec2 axis = b2Normalize( separation ); + + // compute effective mass + float crA = b2Cross( rA, axis ); + float crB = b2Cross( rB, axis ); + float k = mA + mB + iA * crA * crA + iB * crB * crB; + joint->axialMass = k > 0.0f ? 1.0f / k : 0.0f; + + joint->distanceSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h ); + + if ( context->enableWarmStarting == false ) + { + joint->impulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; + joint->motorImpulse = 0.0f; + } +} + +void b2WarmStartDistanceJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_distanceJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2DistanceJoint* joint = &base->distanceJoint; + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 ds = b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), b2Sub( rB, rA ) ); + b2Vec2 separation = b2Add( joint->deltaCenter, ds ); + b2Vec2 axis = b2Normalize( separation ); + + float axialImpulse = joint->impulse + joint->lowerImpulse - joint->upperImpulse + joint->motorImpulse; + b2Vec2 P = b2MulSV( axialImpulse, axis ); + + stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, P ); + stateA->angularVelocity -= iA * b2Cross( rA, P ); + stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, P ); + stateB->angularVelocity += iB * b2Cross( rB, P ); +} + +void b2SolveDistanceJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_ASSERT( base->type == b2_distanceJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2DistanceJoint* joint = &base->distanceJoint; + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + // current anchors + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + // current separation + b2Vec2 ds = b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), b2Sub( rB, rA ) ); + b2Vec2 separation = b2Add( joint->deltaCenter, ds ); + + float length = b2Length( separation ); + b2Vec2 axis = b2Normalize( separation ); + + // joint is soft if + // - spring is enabled + // - and (joint limit is disabled or limits are not equal) + if ( joint->enableSpring && ( joint->minLength < joint->maxLength || joint->enableLimit == false ) ) + { + // spring + if ( joint->hertz > 0.0f ) + { + // Cdot = dot(u, v + cross(w, r)) + b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) ); + float Cdot = b2Dot( axis, vr ); + float C = length - joint->length; + float bias = joint->distanceSoftness.biasRate * C; + + float m = joint->distanceSoftness.massScale * joint->axialMass; + float impulse = -m * ( Cdot + bias ) - joint->distanceSoftness.impulseScale * joint->impulse; + joint->impulse += impulse; + + b2Vec2 P = b2MulSV( impulse, axis ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + + if ( joint->enableLimit ) + { + // lower limit + { + b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) ); + float Cdot = b2Dot( axis, vr ); + + float C = length - joint->minLength; + + float bias = 0.0f; + float massCoeff = 1.0f; + float impulseCoeff = 0.0f; + if ( C > 0.0f ) + { + // speculative + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massCoeff = context->jointSoftness.massScale; + impulseCoeff = context->jointSoftness.impulseScale; + } + + float impulse = -massCoeff * joint->axialMass * ( Cdot + bias ) - impulseCoeff * joint->lowerImpulse; + float newImpulse = b2MaxFloat( 0.0f, joint->lowerImpulse + impulse ); + impulse = newImpulse - joint->lowerImpulse; + joint->lowerImpulse = newImpulse; + + b2Vec2 P = b2MulSV( impulse, axis ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + + // upper + { + b2Vec2 vr = b2Add( b2Sub( vA, vB ), b2Sub( b2CrossSV( wA, rA ), b2CrossSV( wB, rB ) ) ); + float Cdot = b2Dot( axis, vr ); + + float C = joint->maxLength - length; + + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( C > 0.0f ) + { + // speculative + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->upperImpulse; + float newImpulse = b2MaxFloat( 0.0f, joint->upperImpulse + impulse ); + impulse = newImpulse - joint->upperImpulse; + joint->upperImpulse = newImpulse; + + b2Vec2 P = b2MulSV( -impulse, axis ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + } + + if ( joint->enableMotor ) + { + b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) ); + float Cdot = b2Dot( axis, vr ); + float impulse = joint->axialMass * ( joint->motorSpeed - Cdot ); + float oldImpulse = joint->motorImpulse; + float maxImpulse = context->h * joint->maxMotorForce; + joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse ); + impulse = joint->motorImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axis ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + } + else + { + // rigid constraint + b2Vec2 vr = b2Add( b2Sub( vB, vA ), b2Sub( b2CrossSV( wB, rB ), b2CrossSV( wA, rA ) ) ); + float Cdot = b2Dot( axis, vr ); + + float C = length - joint->length; + + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->impulse; + joint->impulse += impulse; + + b2Vec2 P = b2MulSV( impulse, axis ); + vA = b2MulSub( vA, mA, P ); + wA -= iA * b2Cross( rA, P ); + vB = b2MulAdd( vB, mB, P ); + wB += iB * b2Cross( rB, P ); + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +#if 0 +void b2DistanceJoint::Dump() +{ + int32 indexA = m_bodyA->m_islandIndex; + int32 indexB = m_bodyB->m_islandIndex; + + b2Dump(" b2DistanceJointDef jd;\n"); + b2Dump(" jd.bodyA = sims[%d];\n", indexA); + b2Dump(" jd.bodyB = sims[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); + b2Dump(" jd.length = %.9g;\n", m_length); + b2Dump(" jd.minLength = %.9g;\n", m_minLength); + b2Dump(" jd.maxLength = %.9g;\n", m_maxLength); + b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); + b2Dump(" jd.damping = %.9g;\n", m_damping); + b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); +} +#endif + +void b2DrawDistanceJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ) +{ + B2_ASSERT( base->type == b2_distanceJoint ); + + b2DistanceJoint* joint = &base->distanceJoint; + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + + b2Vec2 axis = b2Normalize( b2Sub( pB, pA ) ); + + if ( joint->minLength < joint->maxLength && joint->enableLimit ) + { + b2Vec2 pMin = b2MulAdd( pA, joint->minLength, axis ); + b2Vec2 pMax = b2MulAdd( pA, joint->maxLength, axis ); + b2Vec2 offset = b2MulSV( 0.05f * b2_lengthUnitsPerMeter, b2RightPerp( axis ) ); + + if ( joint->minLength > B2_LINEAR_SLOP ) + { + // draw->DrawPoint(pMin, 4.0f, c2, draw->context); + draw->DrawSegmentFcn( b2Sub( pMin, offset ), b2Add( pMin, offset ), b2_colorLightGreen, draw->context ); + } + + if ( joint->maxLength < B2_HUGE ) + { + // draw->DrawPoint(pMax, 4.0f, c3, draw->context); + draw->DrawSegmentFcn( b2Sub( pMax, offset ), b2Add( pMax, offset ), b2_colorRed, draw->context ); + } + + if ( joint->minLength > B2_LINEAR_SLOP && joint->maxLength < B2_HUGE ) + { + draw->DrawSegmentFcn( pMin, pMax, b2_colorGray, draw->context ); + } + } + + draw->DrawSegmentFcn( pA, pB, b2_colorWhite, draw->context ); + draw->DrawPointFcn( pA, 4.0f, b2_colorWhite, draw->context ); + draw->DrawPointFcn( pB, 4.0f, b2_colorWhite, draw->context ); + + if ( joint->hertz > 0.0f && joint->enableSpring ) + { + b2Vec2 pRest = b2MulAdd( pA, joint->length, axis ); + draw->DrawPointFcn( pRest, 4.0f, b2_colorBlue, draw->context ); + } +} diff --git a/3rdparty/box2d/src/dynamic_tree.c b/3rdparty/box2d/src/dynamic_tree.c new file mode 100644 index 000000000000..03f9325bc1a4 --- /dev/null +++ b/3rdparty/box2d/src/dynamic_tree.c @@ -0,0 +1,1989 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "aabb.h" +#include "constants.h" +#include "core.h" + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include +#include + +#define B2_TREE_STACK_SIZE 1024 + +// todo externalize this to visualize internal nodes and speed up FindPairs + +// A node in the dynamic tree. +typedef struct b2TreeNode +{ + // The node bounding box + b2AABB aabb; // 16 + + // Category bits for collision filtering + uint64_t categoryBits; // 8 + + union + { + // Children (internal node) + struct + { + int32_t child1, child2; + } children; + + /// User data (leaf node) + uint64_t userData; + }; // 8 + + union + { + /// The node parent index (allocated node) + int32_t parent; + + /// The node freelist next index (free node) + int32_t next; + }; // 4 + + uint16_t height; // 2 + uint16_t flags; // 2 +} b2TreeNode; + +static b2TreeNode b2_defaultTreeNode = { + .aabb = { { 0.0f, 0.0f }, { 0.0f, 0.0f } }, + .categoryBits = B2_DEFAULT_CATEGORY_BITS, + .children = + { + .child1 = B2_NULL_INDEX, + .child2 = B2_NULL_INDEX, + }, + .parent = B2_NULL_INDEX, + .height = 0, + .flags = b2_allocatedNode, +}; + +static bool b2IsLeaf( const b2TreeNode* node ) +{ + return node->flags & b2_leafNode; +} + +static bool b2IsAllocated( const b2TreeNode* node ) +{ + return node->flags & b2_allocatedNode; +} + +static uint16_t b2MaxUInt16( uint16_t a, uint16_t b ) +{ + return a > b ? a : b; +} + +b2DynamicTree b2DynamicTree_Create( void ) +{ + b2DynamicTree tree; + tree.root = B2_NULL_INDEX; + + tree.nodeCapacity = 16; + tree.nodeCount = 0; + tree.nodes = (b2TreeNode*)b2Alloc( tree.nodeCapacity * sizeof( b2TreeNode ) ); + memset( tree.nodes, 0, tree.nodeCapacity * sizeof( b2TreeNode ) ); + + // Build a linked list for the free list. + for ( int i = 0; i < tree.nodeCapacity - 1; ++i ) + { + tree.nodes[i].next = i + 1; + } + + tree.nodes[tree.nodeCapacity - 1].next = B2_NULL_INDEX; + tree.freeList = 0; + + tree.proxyCount = 0; + + tree.leafIndices = NULL; + tree.leafBoxes = NULL; + tree.leafCenters = NULL; + tree.binIndices = NULL; + tree.rebuildCapacity = 0; + + return tree; +} + +void b2DynamicTree_Destroy( b2DynamicTree* tree ) +{ + b2Free( tree->nodes, tree->nodeCapacity * sizeof( b2TreeNode ) ); + b2Free( tree->leafIndices, tree->rebuildCapacity * sizeof( int32_t ) ); + b2Free( tree->leafBoxes, tree->rebuildCapacity * sizeof( b2AABB ) ); + b2Free( tree->leafCenters, tree->rebuildCapacity * sizeof( b2Vec2 ) ); + b2Free( tree->binIndices, tree->rebuildCapacity * sizeof( int32_t ) ); + + memset( tree, 0, sizeof( b2DynamicTree ) ); +} + +// Allocate a node from the pool. Grow the pool if necessary. +static int b2AllocateNode( b2DynamicTree* tree ) +{ + // Expand the node pool as needed. + if ( tree->freeList == B2_NULL_INDEX ) + { + B2_ASSERT( tree->nodeCount == tree->nodeCapacity ); + + // The free list is empty. Rebuild a bigger pool. + b2TreeNode* oldNodes = tree->nodes; + int oldCapacity = tree->nodeCapacity; + tree->nodeCapacity += oldCapacity >> 1; + tree->nodes = (b2TreeNode*)b2Alloc( tree->nodeCapacity * sizeof( b2TreeNode ) ); + B2_ASSERT( oldNodes != NULL ); + memcpy( tree->nodes, oldNodes, tree->nodeCount * sizeof( b2TreeNode ) ); + memset( tree->nodes + tree->nodeCount, 0, ( tree->nodeCapacity - tree->nodeCount ) * sizeof( b2TreeNode ) ); + b2Free( oldNodes, oldCapacity * sizeof( b2TreeNode ) ); + + // Build a linked list for the free list. The parent pointer becomes the "next" pointer. + // todo avoid building freelist? + for ( int i = tree->nodeCount; i < tree->nodeCapacity - 1; ++i ) + { + tree->nodes[i].next = i + 1; + } + + tree->nodes[tree->nodeCapacity - 1].next = B2_NULL_INDEX; + tree->freeList = tree->nodeCount; + } + + // Peel a node off the free list. + int nodeIndex = tree->freeList; + b2TreeNode* node = tree->nodes + nodeIndex; + tree->freeList = node->next; + *node = b2_defaultTreeNode; + ++tree->nodeCount; + return nodeIndex; +} + +// Return a node to the pool. +static void b2FreeNode( b2DynamicTree* tree, int nodeId ) +{ + B2_ASSERT( 0 <= nodeId && nodeId < tree->nodeCapacity ); + B2_ASSERT( 0 < tree->nodeCount ); + tree->nodes[nodeId].next = tree->freeList; + tree->nodes[nodeId].flags = 0; + tree->freeList = nodeId; + --tree->nodeCount; +} + +// Greedy algorithm for sibling selection using the SAH +// We have three nodes A-(B,C) and want to add a leaf D, there are three choices. +// 1: make a new parent for A and D : E-(A-(B,C), D) +// 2: associate D with B +// a: B is a leaf : A-(E-(B,D), C) +// b: B is an internal node: A-(B{D},C) +// 3: associate D with C +// a: C is a leaf : A-(B, E-(C,D)) +// b: C is an internal node: A-(B, C{D}) +// All of these have a clear cost except when B or C is an internal node. Hence we need to be greedy. + +// The cost for cases 1, 2a, and 3a can be computed using the sibling cost formula. +// cost of sibling H = area(union(H, D)) + increased area of ancestors + +// Suppose B (or C) is an internal node, then the lowest cost would be one of two cases: +// case1: D becomes a sibling of B +// case2: D becomes a descendant of B along with a new internal node of area(D). +static int b2FindBestSibling( const b2DynamicTree* tree, b2AABB boxD ) +{ + b2Vec2 centerD = b2AABB_Center( boxD ); + float areaD = b2Perimeter( boxD ); + + const b2TreeNode* nodes = tree->nodes; + int rootIndex = tree->root; + + b2AABB rootBox = nodes[rootIndex].aabb; + + // Area of current node + float areaBase = b2Perimeter( rootBox ); + + // Area of inflated node + float directCost = b2Perimeter( b2AABB_Union( rootBox, boxD ) ); + float inheritedCost = 0.0f; + + int bestSibling = rootIndex; + float bestCost = directCost; + + // Descend the tree from root, following a single greedy path. + int index = rootIndex; + while ( nodes[index].height > 0 ) + { + int child1 = nodes[index].children.child1; + int child2 = nodes[index].children.child2; + + // Cost of creating a new parent for this node and the new leaf + float cost = directCost + inheritedCost; + + // Sometimes there are multiple identical costs within tolerance. + // This breaks the ties using the centroid distance. + if ( cost < bestCost ) + { + bestSibling = index; + bestCost = cost; + } + + // Inheritance cost seen by children + inheritedCost += directCost - areaBase; + + bool leaf1 = nodes[child1].height == 0; + bool leaf2 = nodes[child2].height == 0; + + // Cost of descending into child 1 + float lowerCost1 = FLT_MAX; + b2AABB box1 = nodes[child1].aabb; + float directCost1 = b2Perimeter( b2AABB_Union( box1, boxD ) ); + float area1 = 0.0f; + if ( leaf1 ) + { + // Child 1 is a leaf + // Cost of creating new node and increasing area of node P + float cost1 = directCost1 + inheritedCost; + + // Need this here due to while condition above + if ( cost1 < bestCost ) + { + bestSibling = child1; + bestCost = cost1; + } + } + else + { + // Child 1 is an internal node + area1 = b2Perimeter( box1 ); + + // Lower bound cost of inserting under child 1. The minimum accounts for two possibilities: + // 1. Child1 could be the sibling with cost1 = inheritedCost + directCost1 + // 2. A descendent of child1 could be the sibling with the lower bound cost of + // cost1 = inheritedCost + (directCost1 - area1) + areaD + // This minimum here leads to the minimum of these two costs. + lowerCost1 = inheritedCost + directCost1 + b2MinFloat( areaD - area1, 0.0f ); + } + + // Cost of descending into child 2 + float lowerCost2 = FLT_MAX; + b2AABB box2 = nodes[child2].aabb; + float directCost2 = b2Perimeter( b2AABB_Union( box2, boxD ) ); + float area2 = 0.0f; + if ( leaf2 ) + { + float cost2 = directCost2 + inheritedCost; + + if ( cost2 < bestCost ) + { + bestSibling = child2; + bestCost = cost2; + } + } + else + { + area2 = b2Perimeter( box2 ); + lowerCost2 = inheritedCost + directCost2 + b2MinFloat( areaD - area2, 0.0f ); + } + + if ( leaf1 && leaf2 ) + { + break; + } + + // Can the cost possibly be decreased? + if ( bestCost <= lowerCost1 && bestCost <= lowerCost2 ) + { + break; + } + + if ( lowerCost1 == lowerCost2 && leaf1 == false ) + { + B2_ASSERT( lowerCost1 < FLT_MAX ); + B2_ASSERT( lowerCost2 < FLT_MAX ); + + // No clear choice based on lower bound surface area. This can happen when both + // children fully contain D. Fall back to node distance. + b2Vec2 d1 = b2Sub( b2AABB_Center( box1 ), centerD ); + b2Vec2 d2 = b2Sub( b2AABB_Center( box2 ), centerD ); + lowerCost1 = b2LengthSquared( d1 ); + lowerCost2 = b2LengthSquared( d2 ); + } + + // Descend + if ( lowerCost1 < lowerCost2 && leaf1 == false ) + { + index = child1; + areaBase = area1; + directCost = directCost1; + } + else + { + index = child2; + areaBase = area2; + directCost = directCost2; + } + + B2_ASSERT( nodes[index].height > 0 ); + } + + return bestSibling; +} + +enum b2RotateType +{ + b2_rotateNone, + b2_rotateBF, + b2_rotateBG, + b2_rotateCD, + b2_rotateCE +}; + +// Perform a left or right rotation if node A is imbalanced. +// Returns the new root index. +static void b2RotateNodes( b2DynamicTree* tree, int iA ) +{ + B2_ASSERT( iA != B2_NULL_INDEX ); + + b2TreeNode* nodes = tree->nodes; + + b2TreeNode* A = nodes + iA; + if ( A->height < 2 ) + { + return; + } + + int iB = A->children.child1; + int iC = A->children.child2; + B2_ASSERT( 0 <= iB && iB < tree->nodeCapacity ); + B2_ASSERT( 0 <= iC && iC < tree->nodeCapacity ); + + b2TreeNode* B = nodes + iB; + b2TreeNode* C = nodes + iC; + + if ( B->height == 0 ) + { + // B is a leaf and C is internal + B2_ASSERT( C->height > 0 ); + + int iF = C->children.child1; + int iG = C->children.child2; + b2TreeNode* F = nodes + iF; + b2TreeNode* G = nodes + iG; + B2_ASSERT( 0 <= iF && iF < tree->nodeCapacity ); + B2_ASSERT( 0 <= iG && iG < tree->nodeCapacity ); + + // Base cost + float costBase = b2Perimeter( C->aabb ); + + // Cost of swapping B and F + b2AABB aabbBG = b2AABB_Union( B->aabb, G->aabb ); + float costBF = b2Perimeter( aabbBG ); + + // Cost of swapping B and G + b2AABB aabbBF = b2AABB_Union( B->aabb, F->aabb ); + float costBG = b2Perimeter( aabbBF ); + + if ( costBase < costBF && costBase < costBG ) + { + // Rotation does not improve cost + return; + } + + if ( costBF < costBG ) + { + // Swap B and F + A->children.child1 = iF; + C->children.child1 = iB; + + B->parent = iC; + F->parent = iA; + + C->aabb = aabbBG; + + C->height = 1 + b2MaxUInt16( B->height, G->height ); + A->height = 1 + b2MaxUInt16( C->height, F->height ); + C->categoryBits = B->categoryBits | G->categoryBits; + A->categoryBits = C->categoryBits | F->categoryBits; + C->flags |= ( B->flags | G->flags ) & b2_enlargedNode; + A->flags |= ( C->flags | F->flags ) & b2_enlargedNode; + } + else + { + // Swap B and G + A->children.child1 = iG; + C->children.child2 = iB; + + B->parent = iC; + G->parent = iA; + + C->aabb = aabbBF; + + C->height = 1 + b2MaxUInt16( B->height, F->height ); + A->height = 1 + b2MaxUInt16( C->height, G->height ); + C->categoryBits = B->categoryBits | F->categoryBits; + A->categoryBits = C->categoryBits | G->categoryBits; + C->flags |= ( B->flags | F->flags ) & b2_enlargedNode; + A->flags |= ( C->flags | G->flags ) & b2_enlargedNode; + } + } + else if ( C->height == 0 ) + { + // C is a leaf and B is internal + B2_ASSERT( B->height > 0 ); + + int iD = B->children.child1; + int iE = B->children.child2; + b2TreeNode* D = nodes + iD; + b2TreeNode* E = nodes + iE; + B2_ASSERT( 0 <= iD && iD < tree->nodeCapacity ); + B2_ASSERT( 0 <= iE && iE < tree->nodeCapacity ); + + // Base cost + float costBase = b2Perimeter( B->aabb ); + + // Cost of swapping C and D + b2AABB aabbCE = b2AABB_Union( C->aabb, E->aabb ); + float costCD = b2Perimeter( aabbCE ); + + // Cost of swapping C and E + b2AABB aabbCD = b2AABB_Union( C->aabb, D->aabb ); + float costCE = b2Perimeter( aabbCD ); + + if ( costBase < costCD && costBase < costCE ) + { + // Rotation does not improve cost + return; + } + + if ( costCD < costCE ) + { + // Swap C and D + A->children.child2 = iD; + B->children.child1 = iC; + + C->parent = iB; + D->parent = iA; + + B->aabb = aabbCE; + + B->height = 1 + b2MaxUInt16( C->height, E->height ); + A->height = 1 + b2MaxUInt16( B->height, D->height ); + B->categoryBits = C->categoryBits | E->categoryBits; + A->categoryBits = B->categoryBits | D->categoryBits; + B->flags |= ( C->flags | E->flags ) & b2_enlargedNode; + A->flags |= ( B->flags | D->flags ) & b2_enlargedNode; + } + else + { + // Swap C and E + A->children.child2 = iE; + B->children.child2 = iC; + + C->parent = iB; + E->parent = iA; + + B->aabb = aabbCD; + B->height = 1 + b2MaxUInt16( C->height, D->height ); + A->height = 1 + b2MaxUInt16( B->height, E->height ); + B->categoryBits = C->categoryBits | D->categoryBits; + A->categoryBits = B->categoryBits | E->categoryBits; + B->flags |= ( C->flags | D->flags ) & b2_enlargedNode; + A->flags |= ( B->flags | E->flags ) & b2_enlargedNode; + } + } + else + { + int iD = B->children.child1; + int iE = B->children.child2; + int iF = C->children.child1; + int iG = C->children.child2; + + b2TreeNode* D = nodes + iD; + b2TreeNode* E = nodes + iE; + b2TreeNode* F = nodes + iF; + b2TreeNode* G = nodes + iG; + + B2_ASSERT( 0 <= iD && iD < tree->nodeCapacity ); + B2_ASSERT( 0 <= iE && iE < tree->nodeCapacity ); + B2_ASSERT( 0 <= iF && iF < tree->nodeCapacity ); + B2_ASSERT( 0 <= iG && iG < tree->nodeCapacity ); + + // Base cost + float areaB = b2Perimeter( B->aabb ); + float areaC = b2Perimeter( C->aabb ); + float costBase = areaB + areaC; + enum b2RotateType bestRotation = b2_rotateNone; + float bestCost = costBase; + + // Cost of swapping B and F + b2AABB aabbBG = b2AABB_Union( B->aabb, G->aabb ); + float costBF = areaB + b2Perimeter( aabbBG ); + if ( costBF < bestCost ) + { + bestRotation = b2_rotateBF; + bestCost = costBF; + } + + // Cost of swapping B and G + b2AABB aabbBF = b2AABB_Union( B->aabb, F->aabb ); + float costBG = areaB + b2Perimeter( aabbBF ); + if ( costBG < bestCost ) + { + bestRotation = b2_rotateBG; + bestCost = costBG; + } + + // Cost of swapping C and D + b2AABB aabbCE = b2AABB_Union( C->aabb, E->aabb ); + float costCD = areaC + b2Perimeter( aabbCE ); + if ( costCD < bestCost ) + { + bestRotation = b2_rotateCD; + bestCost = costCD; + } + + // Cost of swapping C and E + b2AABB aabbCD = b2AABB_Union( C->aabb, D->aabb ); + float costCE = areaC + b2Perimeter( aabbCD ); + if ( costCE < bestCost ) + { + bestRotation = b2_rotateCE; + // bestCost = costCE; + } + + switch ( bestRotation ) + { + case b2_rotateNone: + break; + + case b2_rotateBF: + A->children.child1 = iF; + C->children.child1 = iB; + + B->parent = iC; + F->parent = iA; + + C->aabb = aabbBG; + C->height = 1 + b2MaxUInt16( B->height, G->height ); + A->height = 1 + b2MaxUInt16( C->height, F->height ); + C->categoryBits = B->categoryBits | G->categoryBits; + A->categoryBits = C->categoryBits | F->categoryBits; + C->flags |= ( B->flags | G->flags ) & b2_enlargedNode; + A->flags |= ( C->flags | F->flags ) & b2_enlargedNode; + break; + + case b2_rotateBG: + A->children.child1 = iG; + C->children.child2 = iB; + + B->parent = iC; + G->parent = iA; + + C->aabb = aabbBF; + C->height = 1 + b2MaxUInt16( B->height, F->height ); + A->height = 1 + b2MaxUInt16( C->height, G->height ); + C->categoryBits = B->categoryBits | F->categoryBits; + A->categoryBits = C->categoryBits | G->categoryBits; + C->flags |= ( B->flags | F->flags ) & b2_enlargedNode; + A->flags |= ( C->flags | G->flags ) & b2_enlargedNode; + break; + + case b2_rotateCD: + A->children.child2 = iD; + B->children.child1 = iC; + + C->parent = iB; + D->parent = iA; + + B->aabb = aabbCE; + B->height = 1 + b2MaxUInt16( C->height, E->height ); + A->height = 1 + b2MaxUInt16( B->height, D->height ); + B->categoryBits = C->categoryBits | E->categoryBits; + A->categoryBits = B->categoryBits | D->categoryBits; + B->flags |= ( C->flags | E->flags ) & b2_enlargedNode; + A->flags |= ( B->flags | D->flags ) & b2_enlargedNode; + break; + + case b2_rotateCE: + A->children.child2 = iE; + B->children.child2 = iC; + + C->parent = iB; + E->parent = iA; + + B->aabb = aabbCD; + B->height = 1 + b2MaxUInt16( C->height, D->height ); + A->height = 1 + b2MaxUInt16( B->height, E->height ); + B->categoryBits = C->categoryBits | D->categoryBits; + A->categoryBits = B->categoryBits | E->categoryBits; + B->flags |= ( C->flags | D->flags ) & b2_enlargedNode; + A->flags |= ( B->flags | E->flags ) & b2_enlargedNode; + break; + + default: + B2_ASSERT( false ); + break; + } + } +} + +static void b2InsertLeaf( b2DynamicTree* tree, int leaf, bool shouldRotate ) +{ + if ( tree->root == B2_NULL_INDEX ) + { + tree->root = leaf; + tree->nodes[tree->root].parent = B2_NULL_INDEX; + return; + } + + // Stage 1: find the best sibling for this node + b2AABB leafAABB = tree->nodes[leaf].aabb; + int sibling = b2FindBestSibling( tree, leafAABB ); + + // Stage 2: create a new parent for the leaf and sibling + int oldParent = tree->nodes[sibling].parent; + int newParent = b2AllocateNode( tree ); + + // warning: node pointer can change after allocation + b2TreeNode* nodes = tree->nodes; + nodes[newParent].parent = oldParent; + nodes[newParent].userData = UINT64_MAX; + nodes[newParent].aabb = b2AABB_Union( leafAABB, nodes[sibling].aabb ); + nodes[newParent].categoryBits = nodes[leaf].categoryBits | nodes[sibling].categoryBits; + nodes[newParent].height = nodes[sibling].height + 1; + + if ( oldParent != B2_NULL_INDEX ) + { + // The sibling was not the root. + if ( nodes[oldParent].children.child1 == sibling ) + { + nodes[oldParent].children.child1 = newParent; + } + else + { + nodes[oldParent].children.child2 = newParent; + } + + nodes[newParent].children.child1 = sibling; + nodes[newParent].children.child2 = leaf; + nodes[sibling].parent = newParent; + nodes[leaf].parent = newParent; + } + else + { + // The sibling was the root. + nodes[newParent].children.child1 = sibling; + nodes[newParent].children.child2 = leaf; + nodes[sibling].parent = newParent; + nodes[leaf].parent = newParent; + tree->root = newParent; + } + + // Stage 3: walk back up the tree fixing heights and AABBs + int index = nodes[leaf].parent; + while ( index != B2_NULL_INDEX ) + { + int child1 = nodes[index].children.child1; + int child2 = nodes[index].children.child2; + + B2_ASSERT( child1 != B2_NULL_INDEX ); + B2_ASSERT( child2 != B2_NULL_INDEX ); + + nodes[index].aabb = b2AABB_Union( nodes[child1].aabb, nodes[child2].aabb ); + nodes[index].categoryBits = nodes[child1].categoryBits | nodes[child2].categoryBits; + nodes[index].height = 1 + b2MaxUInt16( nodes[child1].height, nodes[child2].height ); + nodes[index].flags |= ( nodes[child1].flags | nodes[child2].flags ) & b2_enlargedNode; + + if ( shouldRotate ) + { + b2RotateNodes( tree, index ); + } + + index = nodes[index].parent; + } +} + +static void b2RemoveLeaf( b2DynamicTree* tree, int leaf ) +{ + if ( leaf == tree->root ) + { + tree->root = B2_NULL_INDEX; + return; + } + + b2TreeNode* nodes = tree->nodes; + + int parent = nodes[leaf].parent; + int grandParent = nodes[parent].parent; + int sibling; + if ( nodes[parent].children.child1 == leaf ) + { + sibling = nodes[parent].children.child2; + } + else + { + sibling = nodes[parent].children.child1; + } + + if ( grandParent != B2_NULL_INDEX ) + { + // Destroy parent and connect sibling to grandParent. + if ( nodes[grandParent].children.child1 == parent ) + { + nodes[grandParent].children.child1 = sibling; + } + else + { + nodes[grandParent].children.child2 = sibling; + } + nodes[sibling].parent = grandParent; + b2FreeNode( tree, parent ); + + // Adjust ancestor bounds. + int index = grandParent; + while ( index != B2_NULL_INDEX ) + { + b2TreeNode* node = nodes + index; + b2TreeNode* child1 = nodes + node->children.child1; + b2TreeNode* child2 = nodes + node->children.child2; + + // Fast union using SSE + //__m128 aabb1 = _mm_load_ps(&child1->aabb.lowerBound.x); + //__m128 aabb2 = _mm_load_ps(&child2->aabb.lowerBound.x); + //__m128 lower = _mm_min_ps(aabb1, aabb2); + //__m128 upper = _mm_max_ps(aabb1, aabb2); + //__m128 aabb = _mm_shuffle_ps(lower, upper, _MM_SHUFFLE(3, 2, 1, 0)); + //_mm_store_ps(&node->aabb.lowerBound.x, aabb); + + node->aabb = b2AABB_Union( child1->aabb, child2->aabb ); + node->categoryBits = child1->categoryBits | child2->categoryBits; + node->height = 1 + b2MaxUInt16( child1->height, child2->height ); + + index = node->parent; + } + } + else + { + tree->root = sibling; + tree->nodes[sibling].parent = B2_NULL_INDEX; + b2FreeNode( tree, parent ); + } +} + +// Create a proxy in the tree as a leaf node. We return the index of the node instead of a pointer so that we can grow +// the node pool. +int b2DynamicTree_CreateProxy( b2DynamicTree* tree, b2AABB aabb, uint64_t categoryBits, uint64_t userData ) +{ + B2_ASSERT( -B2_HUGE < aabb.lowerBound.x && aabb.lowerBound.x < B2_HUGE ); + B2_ASSERT( -B2_HUGE < aabb.lowerBound.y && aabb.lowerBound.y < B2_HUGE ); + B2_ASSERT( -B2_HUGE < aabb.upperBound.x && aabb.upperBound.x < B2_HUGE ); + B2_ASSERT( -B2_HUGE < aabb.upperBound.y && aabb.upperBound.y < B2_HUGE ); + + int proxyId = b2AllocateNode( tree ); + b2TreeNode* node = tree->nodes + proxyId; + + node->aabb = aabb; + node->userData = userData; + node->categoryBits = categoryBits; + node->height = 0; + node->flags = b2_allocatedNode | b2_leafNode; + + bool shouldRotate = true; + b2InsertLeaf( tree, proxyId, shouldRotate ); + + tree->proxyCount += 1; + + return proxyId; +} + +void b2DynamicTree_DestroyProxy( b2DynamicTree* tree, int proxyId ) +{ + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + B2_ASSERT( b2IsLeaf( tree->nodes + proxyId ) ); + + b2RemoveLeaf( tree, proxyId ); + b2FreeNode( tree, proxyId ); + + B2_ASSERT( tree->proxyCount > 0 ); + tree->proxyCount -= 1; +} + +int b2DynamicTree_GetProxyCount( const b2DynamicTree* tree ) +{ + return tree->proxyCount; +} + +void b2DynamicTree_MoveProxy( b2DynamicTree* tree, int proxyId, b2AABB aabb ) +{ + B2_ASSERT( b2IsValidAABB( aabb ) ); + B2_ASSERT( aabb.upperBound.x - aabb.lowerBound.x < B2_HUGE ); + B2_ASSERT( aabb.upperBound.y - aabb.lowerBound.y < B2_HUGE ); + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + B2_ASSERT( b2IsLeaf( tree->nodes + proxyId ) ); + + b2RemoveLeaf( tree, proxyId ); + + tree->nodes[proxyId].aabb = aabb; + + bool shouldRotate = false; + b2InsertLeaf( tree, proxyId, shouldRotate ); +} + +void b2DynamicTree_EnlargeProxy( b2DynamicTree* tree, int proxyId, b2AABB aabb ) +{ + b2TreeNode* nodes = tree->nodes; + + B2_ASSERT( b2IsValidAABB( aabb ) ); + B2_ASSERT( aabb.upperBound.x - aabb.lowerBound.x < B2_HUGE ); + B2_ASSERT( aabb.upperBound.y - aabb.lowerBound.y < B2_HUGE ); + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + B2_ASSERT( b2IsLeaf( tree->nodes + proxyId ) ); + + // Caller must ensure this + B2_ASSERT( b2AABB_Contains( nodes[proxyId].aabb, aabb ) == false ); + + nodes[proxyId].aabb = aabb; + + int parentIndex = nodes[proxyId].parent; + while (parentIndex != B2_NULL_INDEX) + { + bool changed = b2EnlargeAABB( &nodes[parentIndex].aabb, aabb ); + nodes[parentIndex].flags |= b2_enlargedNode; + parentIndex = nodes[parentIndex].parent; + + if (changed == false) + { + break; + } + } + + while (parentIndex != B2_NULL_INDEX) + { + if (nodes[parentIndex].flags & b2_enlargedNode) + { + // early out because this ancestor was previously ascended and marked as enlarged + break; + } + + nodes[parentIndex].flags |= b2_enlargedNode; + parentIndex = nodes[parentIndex].parent; + } +} + +void b2DynamicTree_SetCategoryBits( b2DynamicTree* tree, int proxyId, uint64_t categoryBits ) +{ + b2TreeNode* nodes = tree->nodes; + + B2_ASSERT( nodes[proxyId].children.child1 == B2_NULL_INDEX ); + B2_ASSERT( nodes[proxyId].children.child2 == B2_NULL_INDEX ); + B2_ASSERT( (nodes[proxyId].flags & b2_leafNode) == b2_leafNode ); + + nodes[proxyId].categoryBits = categoryBits; + + // Fix up category bits in ancestor internal nodes + int nodeIndex = nodes[proxyId].parent; + while ( nodeIndex != B2_NULL_INDEX ) + { + b2TreeNode* node = nodes + nodeIndex; + int child1 = node->children.child1; + B2_ASSERT( child1 != B2_NULL_INDEX ); + int child2 = node->children.child2; + B2_ASSERT( child2 != B2_NULL_INDEX ); + node->categoryBits = nodes[child1].categoryBits | nodes[child2].categoryBits; + + nodeIndex = node->parent; + } +} + +uint64_t b2DynamicTree_GetCategoryBits( b2DynamicTree* tree, int proxyId ) +{ + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + return tree->nodes[proxyId].categoryBits; +} + +int b2DynamicTree_GetHeight( const b2DynamicTree* tree ) +{ + if ( tree->root == B2_NULL_INDEX ) + { + return 0; + } + + return tree->nodes[tree->root].height; +} + +float b2DynamicTree_GetAreaRatio( const b2DynamicTree* tree ) +{ + if ( tree->root == B2_NULL_INDEX ) + { + return 0.0f; + } + + const b2TreeNode* root = tree->nodes + tree->root; + float rootArea = b2Perimeter( root->aabb ); + + float totalArea = 0.0f; + for ( int i = 0; i < tree->nodeCapacity; ++i ) + { + const b2TreeNode* node = tree->nodes + i; + if ( b2IsAllocated(node) == false || b2IsLeaf( node ) || i == tree->root ) + { + continue; + } + + totalArea += b2Perimeter( node->aabb ); + } + + return totalArea / rootArea; +} + +b2AABB b2DynamicTree_GetRootBounds( const b2DynamicTree* tree ) +{ + if (tree->root != B2_NULL_INDEX) + { + return tree->nodes[tree->root].aabb; + } + + b2AABB empty = { b2Vec2_zero, b2Vec2_zero }; + return empty; +} + +#if B2_VALIDATE +// Compute the height of a sub-tree. +static int b2ComputeHeight( const b2DynamicTree* tree, int nodeId ) +{ + B2_ASSERT( 0 <= nodeId && nodeId < tree->nodeCapacity ); + b2TreeNode* node = tree->nodes + nodeId; + + if ( b2IsLeaf( node ) ) + { + return 0; + } + + int height1 = b2ComputeHeight( tree, node->children.child1 ); + int height2 = b2ComputeHeight( tree, node->children.child2 ); + return 1 + b2MaxInt( height1, height2 ); +} + +static void b2ValidateStructure( const b2DynamicTree* tree, int index ) +{ + if ( index == B2_NULL_INDEX ) + { + return; + } + + if ( index == tree->root ) + { + B2_ASSERT( tree->nodes[index].parent == B2_NULL_INDEX ); + } + + const b2TreeNode* node = tree->nodes + index; + + B2_ASSERT( node->flags == 0 || ( node->flags & b2_allocatedNode ) != 0 ); + + if ( b2IsLeaf( node ) ) + { + B2_ASSERT( node->height == 0 ); + return; + } + + int child1 = node->children.child1; + int child2 = node->children.child2; + + B2_ASSERT( 0 <= child1 && child1 < tree->nodeCapacity ); + B2_ASSERT( 0 <= child2 && child2 < tree->nodeCapacity ); + + B2_ASSERT( tree->nodes[child1].parent == index ); + B2_ASSERT( tree->nodes[child2].parent == index ); + + if ( ( tree->nodes[child1].flags | tree->nodes[child2].flags ) & b2_enlargedNode ) + { + B2_ASSERT( node->flags & b2_enlargedNode ); + } + + b2ValidateStructure( tree, child1 ); + b2ValidateStructure( tree, child2 ); +} + +static void b2ValidateMetrics( const b2DynamicTree* tree, int index ) +{ + if ( index == B2_NULL_INDEX ) + { + return; + } + + const b2TreeNode* node = tree->nodes + index; + + if ( b2IsLeaf( node ) ) + { + B2_ASSERT( node->height == 0 ); + return; + } + + int child1 = node->children.child1; + int child2 = node->children.child2; + + B2_ASSERT( 0 <= child1 && child1 < tree->nodeCapacity ); + B2_ASSERT( 0 <= child2 && child2 < tree->nodeCapacity ); + + int height1 = tree->nodes[child1].height; + int height2 = tree->nodes[child2].height; + int height = 1 + b2MaxInt( height1, height2 ); + B2_ASSERT( node->height == height ); + + // b2AABB aabb = b2AABB_Union(tree->nodes[child1].aabb, tree->nodes[child2].aabb); + + B2_ASSERT( b2AABB_Contains( node->aabb, tree->nodes[child1].aabb ) ); + B2_ASSERT( b2AABB_Contains( node->aabb, tree->nodes[child2].aabb ) ); + + // B2_ASSERT(aabb.lowerBound.x == node->aabb.lowerBound.x); + // B2_ASSERT(aabb.lowerBound.y == node->aabb.lowerBound.y); + // B2_ASSERT(aabb.upperBound.x == node->aabb.upperBound.x); + // B2_ASSERT(aabb.upperBound.y == node->aabb.upperBound.y); + + uint64_t categoryBits = tree->nodes[child1].categoryBits | tree->nodes[child2].categoryBits; + B2_ASSERT( node->categoryBits == categoryBits ); + + b2ValidateMetrics( tree, child1 ); + b2ValidateMetrics( tree, child2 ); +} +#endif + +void b2DynamicTree_Validate( const b2DynamicTree* tree ) +{ +#if B2_VALIDATE + if ( tree->root == B2_NULL_INDEX ) + { + return; + } + + b2ValidateStructure( tree, tree->root ); + b2ValidateMetrics( tree, tree->root ); + + int freeCount = 0; + int freeIndex = tree->freeList; + while ( freeIndex != B2_NULL_INDEX ) + { + B2_ASSERT( 0 <= freeIndex && freeIndex < tree->nodeCapacity ); + freeIndex = tree->nodes[freeIndex].next; + ++freeCount; + } + + int height = b2DynamicTree_GetHeight( tree ); + int computedHeight = b2ComputeHeight( tree, tree->root ); + B2_ASSERT( height == computedHeight ); + + B2_ASSERT( tree->nodeCount + freeCount == tree->nodeCapacity ); +#else + B2_UNUSED( tree ); +#endif +} + +void b2DynamicTree_ValidateNoEnlarged(const b2DynamicTree* tree) +{ +#if B2_VALIDATE == 1 + int capacity = tree->nodeCapacity; + const b2TreeNode* nodes = tree->nodes; + for ( int i = 0; i < capacity; ++i ) + { + const b2TreeNode* node = nodes + i; + if ( node->flags & b2_allocatedNode ) + { + B2_ASSERT( ( node->flags & b2_enlargedNode ) == 0 ); + } + } +#else + B2_UNUSED( tree ); +#endif +} + +int b2DynamicTree_GetByteCount( const b2DynamicTree* tree ) +{ + size_t size = sizeof( b2DynamicTree ) + sizeof( b2TreeNode ) * tree->nodeCapacity + + tree->rebuildCapacity * ( sizeof( int ) + sizeof( b2AABB ) + sizeof( b2Vec2 ) + sizeof( int ) ); + + return (int)size; +} + +uint64_t b2DynamicTree_GetUserData( const b2DynamicTree* tree, int proxyId ) +{ + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + return tree->nodes[proxyId].userData; +} + +b2AABB b2DynamicTree_GetAABB( const b2DynamicTree* tree, int proxyId ) +{ + B2_ASSERT( 0 <= proxyId && proxyId < tree->nodeCapacity ); + return tree->nodes[proxyId].aabb; +} + +b2TreeStats b2DynamicTree_Query( const b2DynamicTree* tree, b2AABB aabb, uint64_t maskBits, b2TreeQueryCallbackFcn* callback, + void* context ) +{ + b2TreeStats result = { 0 }; + + if ( tree->nodeCount == 0 ) + { + return result; + } + + int stack[B2_TREE_STACK_SIZE]; + int stackCount = 0; + stack[stackCount++] = tree->root; + + while ( stackCount > 0 ) + { + int nodeId = stack[--stackCount]; + if ( nodeId == B2_NULL_INDEX ) + { + // todo huh? + B2_ASSERT( false ); + continue; + } + + const b2TreeNode* node = tree->nodes + nodeId; + result.nodeVisits += 1; + + if ( b2AABB_Overlaps( node->aabb, aabb ) && ( node->categoryBits & maskBits ) != 0 ) + { + if ( b2IsLeaf( node ) ) + { + // callback to user code with proxy id + bool proceed = callback( nodeId, node->userData, context ); + result.leafVisits += 1; + + if ( proceed == false ) + { + return result; + } + } + else + { + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) + { + stack[stackCount++] = node->children.child1; + stack[stackCount++] = node->children.child2; + } + else + { + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + } + } + } + } + + return result; +} + +b2TreeStats b2DynamicTree_RayCast( const b2DynamicTree* tree, const b2RayCastInput* input, uint64_t maskBits, + b2TreeRayCastCallbackFcn* callback, void* context ) +{ + b2TreeStats result = { 0 }; + + if ( tree->nodeCount == 0 ) + { + return result; + } + + b2Vec2 p1 = input->origin; + b2Vec2 d = input->translation; + + b2Vec2 r = b2Normalize( d ); + + // v is perpendicular to the segment. + b2Vec2 v = b2CrossSV( 1.0f, r ); + b2Vec2 abs_v = b2Abs( v ); + + // Separating axis for segment (Gino, p80). + // |dot(v, p1 - c)| > dot(|v|, h) + + float maxFraction = input->maxFraction; + + b2Vec2 p2 = b2MulAdd( p1, maxFraction, d ); + + // Build a bounding box for the segment. + b2AABB segmentAABB = { b2Min( p1, p2 ), b2Max( p1, p2 ) }; + + int stack[B2_TREE_STACK_SIZE]; + int stackCount = 0; + stack[stackCount++] = tree->root; + + const b2TreeNode* nodes = tree->nodes; + + b2RayCastInput subInput = *input; + + while ( stackCount > 0 ) + { + int nodeId = stack[--stackCount]; + if ( nodeId == B2_NULL_INDEX ) + { + // todo is this possible? + B2_ASSERT( false ); + continue; + } + + const b2TreeNode* node = nodes + nodeId; + result.nodeVisits += 1; + + b2AABB nodeAABB = node->aabb; + + if ( ( node->categoryBits & maskBits ) == 0 || b2AABB_Overlaps( nodeAABB, segmentAABB ) == false ) + { + continue; + } + + // Separating axis for segment (Gino, p80). + // |dot(v, p1 - c)| > dot(|v|, h) + // radius extension is added to the node in this case + b2Vec2 c = b2AABB_Center( nodeAABB ); + b2Vec2 h = b2AABB_Extents( nodeAABB ); + float term1 = b2AbsFloat( b2Dot( v, b2Sub( p1, c ) ) ); + float term2 = b2Dot( abs_v, h ); + if ( term2 < term1 ) + { + continue; + } + + if ( b2IsLeaf( node ) ) + { + subInput.maxFraction = maxFraction; + + float value = callback( &subInput, nodeId, node->userData, context ); + result.leafVisits += 1; + + // The user may return -1 to indicate this shape should be skipped + + if ( value == 0.0f ) + { + // The client has terminated the ray cast. + return result; + } + + if ( 0.0f < value && value <= maxFraction ) + { + // Update segment bounding box. + maxFraction = value; + p2 = b2MulAdd( p1, maxFraction, d ); + segmentAABB.lowerBound = b2Min( p1, p2 ); + segmentAABB.upperBound = b2Max( p1, p2 ); + } + } + else + { + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) + { + b2Vec2 c1 = b2AABB_Center( nodes[node->children.child1].aabb ); + b2Vec2 c2 = b2AABB_Center( nodes[node->children.child2].aabb ); + if ( b2DistanceSquared( c1, p1 ) < b2DistanceSquared( c2, p1 ) ) + { + stack[stackCount++] = node->children.child2; + stack[stackCount++] = node->children.child1; + } + else + { + stack[stackCount++] = node->children.child1; + stack[stackCount++] = node->children.child2; + } + } + else + { + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + } + } + } + + return result; +} + +b2TreeStats b2DynamicTree_ShapeCast( const b2DynamicTree* tree, const b2ShapeCastInput* input, uint64_t maskBits, + b2TreeShapeCastCallbackFcn* callback, void* context ) +{ + b2TreeStats stats = { 0 }; + + if ( tree->nodeCount == 0 || input->proxy.count == 0 ) + { + return stats; + } + + b2AABB originAABB = { input->proxy.points[0], input->proxy.points[0] }; + for ( int i = 1; i < input->proxy.count; ++i ) + { + originAABB.lowerBound = b2Min( originAABB.lowerBound, input->proxy.points[i] ); + originAABB.upperBound = b2Max( originAABB.upperBound, input->proxy.points[i] ); + } + + b2Vec2 radius = { input->proxy.radius, input->proxy.radius }; + + originAABB.lowerBound = b2Sub( originAABB.lowerBound, radius ); + originAABB.upperBound = b2Add( originAABB.upperBound, radius ); + + b2Vec2 p1 = b2AABB_Center( originAABB ); + b2Vec2 extension = b2AABB_Extents( originAABB ); + + // v is perpendicular to the segment. + b2Vec2 r = input->translation; + b2Vec2 v = b2CrossSV( 1.0f, r ); + b2Vec2 abs_v = b2Abs( v ); + + // Separating axis for segment (Gino, p80). + // |dot(v, p1 - c)| > dot(|v|, h) + + float maxFraction = input->maxFraction; + + // Build total box for the shape cast + b2Vec2 t = b2MulSV( maxFraction, input->translation ); + b2AABB totalAABB = { + b2Min( originAABB.lowerBound, b2Add( originAABB.lowerBound, t ) ), + b2Max( originAABB.upperBound, b2Add( originAABB.upperBound, t ) ), + }; + + b2ShapeCastInput subInput = *input; + const b2TreeNode* nodes = tree->nodes; + + int stack[B2_TREE_STACK_SIZE]; + int stackCount = 0; + stack[stackCount++] = tree->root; + + while ( stackCount > 0 ) + { + int nodeId = stack[--stackCount]; + if ( nodeId == B2_NULL_INDEX ) + { + // todo is this possible? + B2_ASSERT( false ); + continue; + } + + const b2TreeNode* node = nodes + nodeId; + stats.nodeVisits += 1; + + if ( ( node->categoryBits & maskBits ) == 0 || b2AABB_Overlaps( node->aabb, totalAABB ) == false ) + { + continue; + } + + // Separating axis for segment (Gino, p80). + // |dot(v, p1 - c)| > dot(|v|, h) + // radius extension is added to the node in this case + b2Vec2 c = b2AABB_Center( node->aabb ); + b2Vec2 h = b2Add( b2AABB_Extents( node->aabb ), extension ); + float term1 = b2AbsFloat( b2Dot( v, b2Sub( p1, c ) ) ); + float term2 = b2Dot( abs_v, h ); + if ( term2 < term1 ) + { + continue; + } + + if ( b2IsLeaf( node ) ) + { + subInput.maxFraction = maxFraction; + + float value = callback( &subInput, nodeId, node->userData, context ); + stats.leafVisits += 1; + + if ( value == 0.0f ) + { + // The client has terminated the ray cast. + return stats; + } + + if ( 0.0f < value && value < maxFraction ) + { + // Update segment bounding box. + maxFraction = value; + t = b2MulSV( maxFraction, input->translation ); + totalAABB.lowerBound = b2Min( originAABB.lowerBound, b2Add( originAABB.lowerBound, t ) ); + totalAABB.upperBound = b2Max( originAABB.upperBound, b2Add( originAABB.upperBound, t ) ); + } + } + else + { + if ( stackCount < B2_TREE_STACK_SIZE - 1 ) + { + b2Vec2 c1 = b2AABB_Center( nodes[node->children.child1].aabb ); + b2Vec2 c2 = b2AABB_Center( nodes[node->children.child2].aabb ); + if ( b2DistanceSquared( c1, p1 ) < b2DistanceSquared( c2, p1 ) ) + { + stack[stackCount++] = node->children.child2; + stack[stackCount++] = node->children.child1; + } + else + { + stack[stackCount++] = node->children.child1; + stack[stackCount++] = node->children.child2; + } + } + else + { + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE - 1 ); + } + } + } + + return stats; +} + +// Median split == 0, Surface area heuristic == 1 +#define B2_TREE_HEURISTIC 0 + +#if B2_TREE_HEURISTIC == 0 + +// Median split heuristic +static int b2PartitionMid( int* indices, b2Vec2* centers, int count ) +{ + // Handle trivial case + if ( count <= 2 ) + { + return count / 2; + } + + b2Vec2 lowerBound = centers[0]; + b2Vec2 upperBound = centers[0]; + + for ( int i = 1; i < count; ++i ) + { + lowerBound = b2Min( lowerBound, centers[i] ); + upperBound = b2Max( upperBound, centers[i] ); + } + + b2Vec2 d = b2Sub( upperBound, lowerBound ); + b2Vec2 c = { 0.5f * ( lowerBound.x + upperBound.x ), 0.5f * ( lowerBound.y + upperBound.y ) }; + + // Partition longest axis using the Hoare partition scheme + // https://en.wikipedia.org/wiki/Quicksort + // https://nicholasvadivelu.com/2021/01/11/array-partition/ + int i1 = 0, i2 = count; + if ( d.x > d.y ) + { + float pivot = c.x; + + while ( i1 < i2 ) + { + while ( i1 < i2 && centers[i1].x < pivot ) + { + i1 += 1; + }; + + while ( i1 < i2 && centers[i2 - 1].x >= pivot ) + { + i2 -= 1; + }; + + if ( i1 < i2 ) + { + // Swap indices + { + int temp = indices[i1]; + indices[i1] = indices[i2 - 1]; + indices[i2 - 1] = temp; + } + + // Swap centers + { + b2Vec2 temp = centers[i1]; + centers[i1] = centers[i2 - 1]; + centers[i2 - 1] = temp; + } + + i1 += 1; + i2 -= 1; + } + } + } + else + { + float pivot = c.y; + + while ( i1 < i2 ) + { + while ( i1 < i2 && centers[i1].y < pivot ) + { + i1 += 1; + }; + + while ( i1 < i2 && centers[i2 - 1].y >= pivot ) + { + i2 -= 1; + }; + + if ( i1 < i2 ) + { + // Swap indices + { + int temp = indices[i1]; + indices[i1] = indices[i2 - 1]; + indices[i2 - 1] = temp; + } + + // Swap centers + { + b2Vec2 temp = centers[i1]; + centers[i1] = centers[i2 - 1]; + centers[i2 - 1] = temp; + } + + i1 += 1; + i2 -= 1; + } + } + } + B2_ASSERT( i1 == i2 ); + + if ( i1 > 0 && i1 < count ) + { + return i1; + } + + return count / 2; +} + +#else + +#define B2_BIN_COUNT 64 + +typedef struct b2TreeBin +{ + b2AABB aabb; + int count; +} b2TreeBin; + +typedef struct b2TreePlane +{ + b2AABB leftAABB; + b2AABB rightAABB; + int leftCount; + int rightCount; +} b2TreePlane; + +// "On Fast Construction of SAH-based Bounding Volume Hierarchies" by Ingo Wald +// Returns the left child count +static int b2PartitionSAH( int* indices, int* binIndices, b2AABB* boxes, int count ) +{ + B2_ASSERT( count > 0 ); + + b2TreeBin bins[B2_BIN_COUNT]; + b2TreePlane planes[B2_BIN_COUNT - 1]; + + b2Vec2 center = b2AABB_Center( boxes[0] ); + b2AABB centroidAABB; + centroidAABB.lowerBound = center; + centroidAABB.upperBound = center; + + for ( int i = 1; i < count; ++i ) + { + center = b2AABB_Center( boxes[i] ); + centroidAABB.lowerBound = b2Min( centroidAABB.lowerBound, center ); + centroidAABB.upperBound = b2Max( centroidAABB.upperBound, center ); + } + + b2Vec2 d = b2Sub( centroidAABB.upperBound, centroidAABB.lowerBound ); + + // Find longest axis + int axisIndex; + float invD; + if ( d.x > d.y ) + { + axisIndex = 0; + invD = d.x; + } + else + { + axisIndex = 1; + invD = d.y; + } + + invD = invD > 0.0f ? 1.0f / invD : 0.0f; + + // Initialize bin bounds and count + for ( int i = 0; i < B2_BIN_COUNT; ++i ) + { + bins[i].aabb.lowerBound = ( b2Vec2 ){ FLT_MAX, FLT_MAX }; + bins[i].aabb.upperBound = ( b2Vec2 ){ -FLT_MAX, -FLT_MAX }; + bins[i].count = 0; + } + + // Assign boxes to bins and compute bin boxes + // TODO_ERIN optimize + float binCount = B2_BIN_COUNT; + float lowerBoundArray[2] = { centroidAABB.lowerBound.x, centroidAABB.lowerBound.y }; + float minC = lowerBoundArray[axisIndex]; + for ( int i = 0; i < count; ++i ) + { + b2Vec2 c = b2AABB_Center( boxes[i] ); + float cArray[2] = { c.x, c.y }; + int binIndex = (int)( binCount * ( cArray[axisIndex] - minC ) * invD ); + binIndex = b2ClampInt( binIndex, 0, B2_BIN_COUNT - 1 ); + binIndices[i] = binIndex; + bins[binIndex].count += 1; + bins[binIndex].aabb = b2AABB_Union( bins[binIndex].aabb, boxes[i] ); + } + + int planeCount = B2_BIN_COUNT - 1; + + // Prepare all the left planes, candidates for left child + planes[0].leftCount = bins[0].count; + planes[0].leftAABB = bins[0].aabb; + for ( int i = 1; i < planeCount; ++i ) + { + planes[i].leftCount = planes[i - 1].leftCount + bins[i].count; + planes[i].leftAABB = b2AABB_Union( planes[i - 1].leftAABB, bins[i].aabb ); + } + + // Prepare all the right planes, candidates for right child + planes[planeCount - 1].rightCount = bins[planeCount].count; + planes[planeCount - 1].rightAABB = bins[planeCount].aabb; + for ( int i = planeCount - 2; i >= 0; --i ) + { + planes[i].rightCount = planes[i + 1].rightCount + bins[i + 1].count; + planes[i].rightAABB = b2AABB_Union( planes[i + 1].rightAABB, bins[i + 1].aabb ); + } + + // Find best split to minimize SAH + float minCost = FLT_MAX; + int bestPlane = 0; + for ( int i = 0; i < planeCount; ++i ) + { + float leftArea = b2Perimeter( planes[i].leftAABB ); + float rightArea = b2Perimeter( planes[i].rightAABB ); + int leftCount = planes[i].leftCount; + int rightCount = planes[i].rightCount; + + float cost = leftCount * leftArea + rightCount * rightArea; + if ( cost < minCost ) + { + bestPlane = i; + minCost = cost; + } + } + + // Partition node indices and boxes using the Hoare partition scheme + // https://en.wikipedia.org/wiki/Quicksort + // https://nicholasvadivelu.com/2021/01/11/array-partition/ + int i1 = 0, i2 = count; + while ( i1 < i2 ) + { + while ( i1 < i2 && binIndices[i1] < bestPlane ) + { + i1 += 1; + }; + + while ( i1 < i2 && binIndices[i2 - 1] >= bestPlane ) + { + i2 -= 1; + }; + + if ( i1 < i2 ) + { + // Swap indices + { + int temp = indices[i1]; + indices[i1] = indices[i2 - 1]; + indices[i2 - 1] = temp; + } + + // Swap boxes + { + b2AABB temp = boxes[i1]; + boxes[i1] = boxes[i2 - 1]; + boxes[i2 - 1] = temp; + } + + i1 += 1; + i2 -= 1; + } + } + B2_ASSERT( i1 == i2 ); + + if ( i1 > 0 && i1 < count ) + { + return i1; + } + else + { + return count / 2; + } +} + +#endif + +// Temporary data used to track the rebuild of a tree node +struct b2RebuildItem +{ + int nodeIndex; + int childCount; + + // Leaf indices + int startIndex; + int splitIndex; + int endIndex; +}; + +// Returns root node index +static int b2BuildTree( b2DynamicTree* tree, int leafCount ) +{ + b2TreeNode* nodes = tree->nodes; + int* leafIndices = tree->leafIndices; + + if ( leafCount == 1 ) + { + nodes[leafIndices[0]].parent = B2_NULL_INDEX; + return leafIndices[0]; + } + +#if B2_TREE_HEURISTIC == 0 + b2Vec2* leafCenters = tree->leafCenters; +#else + b2AABB* leafBoxes = tree->leafBoxes; + int* binIndices = tree->binIndices; +#endif + + // todo large stack item + struct b2RebuildItem stack[B2_TREE_STACK_SIZE]; + int top = 0; + + stack[0].nodeIndex = b2AllocateNode( tree ); + stack[0].childCount = -1; + stack[0].startIndex = 0; + stack[0].endIndex = leafCount; +#if B2_TREE_HEURISTIC == 0 + stack[0].splitIndex = b2PartitionMid( leafIndices, leafCenters, leafCount ); +#else + stack[0].splitIndex = b2PartitionSAH( leafIndices, binIndices, leafBoxes, leafCount ); +#endif + + while ( true ) + { + struct b2RebuildItem* item = stack + top; + + item->childCount += 1; + + if ( item->childCount == 2 ) + { + // This internal node has both children established + + if ( top == 0 ) + { + // all done + break; + } + + struct b2RebuildItem* parentItem = stack + ( top - 1 ); + b2TreeNode* parentNode = nodes + parentItem->nodeIndex; + + if ( parentItem->childCount == 0 ) + { + B2_ASSERT( parentNode->children.child1 == B2_NULL_INDEX ); + parentNode->children.child1 = item->nodeIndex; + } + else + { + B2_ASSERT( parentItem->childCount == 1 ); + B2_ASSERT( parentNode->children.child2 == B2_NULL_INDEX ); + parentNode->children.child2 = item->nodeIndex; + } + + b2TreeNode* node = nodes + item->nodeIndex; + + B2_ASSERT( node->parent == B2_NULL_INDEX ); + node->parent = parentItem->nodeIndex; + + B2_ASSERT( node->children.child1 != B2_NULL_INDEX ); + B2_ASSERT( node->children.child2 != B2_NULL_INDEX ); + b2TreeNode* child1 = nodes + node->children.child1; + b2TreeNode* child2 = nodes + node->children.child2; + + node->aabb = b2AABB_Union( child1->aabb, child2->aabb ); + node->height = 1 + b2MaxUInt16( child1->height, child2->height ); + node->categoryBits = child1->categoryBits | child2->categoryBits; + + // Pop stack + top -= 1; + } + else + { + int startIndex, endIndex; + if ( item->childCount == 0 ) + { + startIndex = item->startIndex; + endIndex = item->splitIndex; + } + else + { + B2_ASSERT( item->childCount == 1 ); + startIndex = item->splitIndex; + endIndex = item->endIndex; + } + + int count = endIndex - startIndex; + + if ( count == 1 ) + { + int childIndex = leafIndices[startIndex]; + b2TreeNode* node = nodes + item->nodeIndex; + + if ( item->childCount == 0 ) + { + B2_ASSERT( node->children.child1 == B2_NULL_INDEX ); + node->children.child1 = childIndex; + } + else + { + B2_ASSERT( item->childCount == 1 ); + B2_ASSERT( node->children.child2 == B2_NULL_INDEX ); + node->children.child2 = childIndex; + } + + b2TreeNode* childNode = nodes + childIndex; + B2_ASSERT( childNode->parent == B2_NULL_INDEX ); + childNode->parent = item->nodeIndex; + } + else + { + B2_ASSERT( count > 0 ); + B2_ASSERT( top < B2_TREE_STACK_SIZE ); + + top += 1; + struct b2RebuildItem* newItem = stack + top; + newItem->nodeIndex = b2AllocateNode( tree ); + newItem->childCount = -1; + newItem->startIndex = startIndex; + newItem->endIndex = endIndex; +#if B2_TREE_HEURISTIC == 0 + newItem->splitIndex = b2PartitionMid( leafIndices + startIndex, leafCenters + startIndex, count ); +#else + newItem->splitIndex = + b2PartitionSAH( leafIndices + startIndex, binIndices + startIndex, leafBoxes + startIndex, count ); +#endif + newItem->splitIndex += startIndex; + } + } + } + + b2TreeNode* rootNode = nodes + stack[0].nodeIndex; + B2_ASSERT( rootNode->parent == B2_NULL_INDEX ); + B2_ASSERT( rootNode->children.child1 != B2_NULL_INDEX ); + B2_ASSERT( rootNode->children.child2 != B2_NULL_INDEX ); + + b2TreeNode* child1 = nodes + rootNode->children.child1; + b2TreeNode* child2 = nodes + rootNode->children.child2; + + rootNode->aabb = b2AABB_Union( child1->aabb, child2->aabb ); + rootNode->height = 1 + b2MaxUInt16( child1->height, child2->height ); + rootNode->categoryBits = child1->categoryBits | child2->categoryBits; + + return stack[0].nodeIndex; +} + +// Not safe to access tree during this operation because it may grow +int b2DynamicTree_Rebuild( b2DynamicTree* tree, bool fullBuild ) +{ + int proxyCount = tree->proxyCount; + if ( proxyCount == 0 ) + { + return 0; + } + + // Ensure capacity for rebuild space + if ( proxyCount > tree->rebuildCapacity ) + { + int newCapacity = proxyCount + proxyCount / 2; + + b2Free( tree->leafIndices, tree->rebuildCapacity * sizeof( int ) ); + tree->leafIndices = b2Alloc( newCapacity * sizeof( int ) ); + +#if B2_TREE_HEURISTIC == 0 + b2Free( tree->leafCenters, tree->rebuildCapacity * sizeof( b2Vec2 ) ); + tree->leafCenters = b2Alloc( newCapacity * sizeof( b2Vec2 ) ); +#else + b2Free( tree->leafBoxes, tree->rebuildCapacity * sizeof( b2AABB ) ); + tree->leafBoxes = b2Alloc( newCapacity * sizeof( b2AABB ) ); + b2Free( tree->binIndices, tree->rebuildCapacity * sizeof( int ) ); + tree->binIndices = b2Alloc( newCapacity * sizeof( int ) ); +#endif + tree->rebuildCapacity = newCapacity; + } + + int leafCount = 0; + int stack[B2_TREE_STACK_SIZE]; + int stackCount = 0; + + int nodeIndex = tree->root; + b2TreeNode* nodes = tree->nodes; + b2TreeNode* node = nodes + nodeIndex; + + // These are the nodes that get sorted to rebuild the tree. + // I'm using indices because the node pool may grow during the build. + int* leafIndices = tree->leafIndices; + +#if B2_TREE_HEURISTIC == 0 + b2Vec2* leafCenters = tree->leafCenters; +#else + b2AABB* leafBoxes = tree->leafBoxes; +#endif + + // Gather all proxy nodes that have grown and all internal nodes that haven't grown. Both are + // considered leaves in the tree rebuild. + // Free all internal nodes that have grown. + // todo use a node growth metric instead of simply enlarged to reduce rebuild size and frequency + // this should be weighed against B2_AABB_MARGIN + while ( true ) + { + if ( node->height == 0 || ( ( node->flags & b2_enlargedNode ) == 0 && fullBuild == false ) ) + { + leafIndices[leafCount] = nodeIndex; +#if B2_TREE_HEURISTIC == 0 + leafCenters[leafCount] = b2AABB_Center( node->aabb ); +#else + leafBoxes[leafCount] = node->aabb; +#endif + leafCount += 1; + + // Detach + node->parent = B2_NULL_INDEX; + } + else + { + int doomedNodeIndex = nodeIndex; + + // Handle children + nodeIndex = node->children.child1; + + if ( stackCount < B2_TREE_STACK_SIZE ) + { + stack[stackCount++] = node->children.child2; + } + else + { + B2_ASSERT( stackCount < B2_TREE_STACK_SIZE ); + } + + node = nodes + nodeIndex; + + // Remove doomed node + b2FreeNode( tree, doomedNodeIndex ); + + continue; + } + + if ( stackCount == 0 ) + { + break; + } + + nodeIndex = stack[--stackCount]; + node = nodes + nodeIndex; + } + +#if B2_VALIDATE == 1 + int capacity = tree->nodeCapacity; + for ( int i = 0; i < capacity; ++i ) + { + if ( nodes[i].flags & b2_allocatedNode ) + { + B2_ASSERT( ( nodes[i].flags & b2_enlargedNode ) == 0 ); + } + } +#endif + + B2_ASSERT( leafCount <= proxyCount ); + + tree->root = b2BuildTree( tree, leafCount ); + + b2DynamicTree_Validate( tree ); + + return leafCount; +} diff --git a/3rdparty/box2d/src/dynamics/b2_body.cpp b/3rdparty/box2d/src/dynamics/b2_body.cpp deleted file mode 100644 index 00f36856dde1..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_body.cpp +++ /dev/null @@ -1,570 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_joint.h" -#include "box2d/b2_world.h" - -#include - -b2Body::b2Body(const b2BodyDef* bd, b2World* world) -{ - b2Assert(bd->position.IsValid()); - b2Assert(bd->linearVelocity.IsValid()); - b2Assert(b2IsValid(bd->angle)); - b2Assert(b2IsValid(bd->angularVelocity)); - b2Assert(b2IsValid(bd->angularDamping) && bd->angularDamping >= 0.0f); - b2Assert(b2IsValid(bd->linearDamping) && bd->linearDamping >= 0.0f); - - m_flags = 0; - - if (bd->bullet) - { - m_flags |= e_bulletFlag; - } - if (bd->fixedRotation) - { - m_flags |= e_fixedRotationFlag; - } - if (bd->allowSleep) - { - m_flags |= e_autoSleepFlag; - } - if (bd->awake && bd->type != b2_staticBody) - { - m_flags |= e_awakeFlag; - } - if (bd->enabled) - { - m_flags |= e_enabledFlag; - } - - m_world = world; - - m_xf.p = bd->position; - m_xf.q.Set(bd->angle); - - m_sweep.localCenter.SetZero(); - m_sweep.c0 = m_xf.p; - m_sweep.c = m_xf.p; - m_sweep.a0 = bd->angle; - m_sweep.a = bd->angle; - m_sweep.alpha0 = 0.0f; - - m_jointList = nullptr; - m_contactList = nullptr; - m_prev = nullptr; - m_next = nullptr; - - m_linearVelocity = bd->linearVelocity; - m_angularVelocity = bd->angularVelocity; - - m_linearDamping = bd->linearDamping; - m_angularDamping = bd->angularDamping; - m_gravityScale = bd->gravityScale; - - m_force.SetZero(); - m_torque = 0.0f; - - m_sleepTime = 0.0f; - - m_type = bd->type; - - m_mass = 0.0f; - m_invMass = 0.0f; - - m_I = 0.0f; - m_invI = 0.0f; - - m_userData = bd->userData; - - m_fixtureList = nullptr; - m_fixtureCount = 0; -} - -b2Body::~b2Body() -{ - // shapes and joints are destroyed in b2World::Destroy -} - -void b2Body::SetType(b2BodyType type) -{ - b2Assert(m_world->IsLocked() == false); - if (m_world->IsLocked() == true) - { - return; - } - - if (m_type == type) - { - return; - } - - m_type = type; - - ResetMassData(); - - if (m_type == b2_staticBody) - { - m_linearVelocity.SetZero(); - m_angularVelocity = 0.0f; - m_sweep.a0 = m_sweep.a; - m_sweep.c0 = m_sweep.c; - m_flags &= ~e_awakeFlag; - SynchronizeFixtures(); - } - - SetAwake(true); - - m_force.SetZero(); - m_torque = 0.0f; - - // Delete the attached contacts. - b2ContactEdge* ce = m_contactList; - while (ce) - { - b2ContactEdge* ce0 = ce; - ce = ce->next; - m_world->m_contactManager.Destroy(ce0->contact); - } - m_contactList = nullptr; - - // Touch the proxies so that new contacts will be created (when appropriate) - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - int32 proxyCount = f->m_proxyCount; - for (int32 i = 0; i < proxyCount; ++i) - { - broadPhase->TouchProxy(f->m_proxies[i].proxyId); - } - } -} - -b2Fixture* b2Body::CreateFixture(const b2FixtureDef* def) -{ - b2Assert(m_world->IsLocked() == false); - if (m_world->IsLocked() == true) - { - return nullptr; - } - - b2BlockAllocator* allocator = &m_world->m_blockAllocator; - - void* memory = allocator->Allocate(sizeof(b2Fixture)); - b2Fixture* fixture = new (memory) b2Fixture; - fixture->Create(allocator, this, def); - - if (m_flags & e_enabledFlag) - { - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - fixture->CreateProxies(broadPhase, m_xf); - } - - fixture->m_next = m_fixtureList; - m_fixtureList = fixture; - ++m_fixtureCount; - - fixture->m_body = this; - - // Adjust mass properties if needed. - if (fixture->m_density > 0.0f) - { - ResetMassData(); - } - - // Let the world know we have a new fixture. This will cause new contacts - // to be created at the beginning of the next time step. - m_world->m_newContacts = true; - - return fixture; -} - -b2Fixture* b2Body::CreateFixture(const b2Shape* shape, float density) -{ - b2FixtureDef def; - def.shape = shape; - def.density = density; - - return CreateFixture(&def); -} - -void b2Body::DestroyFixture(b2Fixture* fixture) -{ - if (fixture == NULL) - { - return; - } - - b2Assert(m_world->IsLocked() == false); - if (m_world->IsLocked() == true) - { - return; - } - - b2Assert(fixture->m_body == this); - - // Remove the fixture from this body's singly linked list. - b2Assert(m_fixtureCount > 0); - b2Fixture** node = &m_fixtureList; - bool found = false; - while (*node != nullptr) - { - if (*node == fixture) - { - *node = fixture->m_next; - found = true; - break; - } - - node = &(*node)->m_next; - } - - // You tried to remove a shape that is not attached to this body. - b2Assert(found); - - const float density = fixture->m_density; - - // Destroy any contacts associated with the fixture. - b2ContactEdge* edge = m_contactList; - while (edge) - { - b2Contact* c = edge->contact; - edge = edge->next; - - b2Fixture* fixtureA = c->GetFixtureA(); - b2Fixture* fixtureB = c->GetFixtureB(); - - if (fixture == fixtureA || fixture == fixtureB) - { - // This destroys the contact and removes it from - // this body's contact list. - m_world->m_contactManager.Destroy(c); - } - } - - b2BlockAllocator* allocator = &m_world->m_blockAllocator; - - if (m_flags & e_enabledFlag) - { - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - fixture->DestroyProxies(broadPhase); - } - - fixture->m_body = nullptr; - fixture->m_next = nullptr; - fixture->Destroy(allocator); - fixture->~b2Fixture(); - allocator->Free(fixture, sizeof(b2Fixture)); - - --m_fixtureCount; - - // Reset the mass data - if (density > 0.0f) - { - ResetMassData(); - } -} - -void b2Body::ResetMassData() -{ - // Compute mass data from shapes. Each shape has its own density. - m_mass = 0.0f; - m_invMass = 0.0f; - m_I = 0.0f; - m_invI = 0.0f; - m_sweep.localCenter.SetZero(); - - // Static and kinematic bodies have zero mass. - if (m_type == b2_staticBody || m_type == b2_kinematicBody) - { - m_sweep.c0 = m_xf.p; - m_sweep.c = m_xf.p; - m_sweep.a0 = m_sweep.a; - return; - } - - b2Assert(m_type == b2_dynamicBody); - - // Accumulate mass over all fixtures. - b2Vec2 localCenter = b2Vec2_zero; - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - if (f->m_density == 0.0f) - { - continue; - } - - b2MassData massData; - f->GetMassData(&massData); - m_mass += massData.mass; - localCenter += massData.mass * massData.center; - m_I += massData.I; - } - - // Compute center of mass. - if (m_mass > 0.0f) - { - m_invMass = 1.0f / m_mass; - localCenter *= m_invMass; - } - - if (m_I > 0.0f && (m_flags & e_fixedRotationFlag) == 0) - { - // Center the inertia about the center of mass. - m_I -= m_mass * b2Dot(localCenter, localCenter); - b2Assert(m_I > 0.0f); - m_invI = 1.0f / m_I; - - } - else - { - m_I = 0.0f; - m_invI = 0.0f; - } - - // Move center of mass. - b2Vec2 oldCenter = m_sweep.c; - m_sweep.localCenter = localCenter; - m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); - - // Update center of mass velocity. - m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter); -} - -void b2Body::SetMassData(const b2MassData* massData) -{ - b2Assert(m_world->IsLocked() == false); - if (m_world->IsLocked() == true) - { - return; - } - - if (m_type != b2_dynamicBody) - { - return; - } - - m_invMass = 0.0f; - m_I = 0.0f; - m_invI = 0.0f; - - m_mass = massData->mass; - if (m_mass <= 0.0f) - { - m_mass = 1.0f; - } - - m_invMass = 1.0f / m_mass; - - if (massData->I > 0.0f && (m_flags & b2Body::e_fixedRotationFlag) == 0) - { - m_I = massData->I - m_mass * b2Dot(massData->center, massData->center); - b2Assert(m_I > 0.0f); - m_invI = 1.0f / m_I; - } - - // Move center of mass. - b2Vec2 oldCenter = m_sweep.c; - m_sweep.localCenter = massData->center; - m_sweep.c0 = m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); - - // Update center of mass velocity. - m_linearVelocity += b2Cross(m_angularVelocity, m_sweep.c - oldCenter); -} - -bool b2Body::ShouldCollide(const b2Body* other) const -{ - // At least one body should be dynamic. - if (m_type != b2_dynamicBody && other->m_type != b2_dynamicBody) - { - return false; - } - - // Does a joint prevent collision? - for (b2JointEdge* jn = m_jointList; jn; jn = jn->next) - { - if (jn->other == other) - { - if (jn->joint->m_collideConnected == false) - { - return false; - } - } - } - - return true; -} - -void b2Body::SetTransform(const b2Vec2& position, float angle) -{ - b2Assert(m_world->IsLocked() == false); - if (m_world->IsLocked() == true) - { - return; - } - - m_xf.q.Set(angle); - m_xf.p = position; - - m_sweep.c = b2Mul(m_xf, m_sweep.localCenter); - m_sweep.a = angle; - - m_sweep.c0 = m_sweep.c; - m_sweep.a0 = angle; - - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - f->Synchronize(broadPhase, m_xf, m_xf); - } - - // Check for new contacts the next step - m_world->m_newContacts = true; -} - -void b2Body::SynchronizeFixtures() -{ - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - - if (m_flags & b2Body::e_awakeFlag) - { - b2Transform xf1; - xf1.q.Set(m_sweep.a0); - xf1.p = m_sweep.c0 - b2Mul(xf1.q, m_sweep.localCenter); - - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - f->Synchronize(broadPhase, xf1, m_xf); - } - } - else - { - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - f->Synchronize(broadPhase, m_xf, m_xf); - } - } -} - -void b2Body::SetEnabled(bool flag) -{ - b2Assert(m_world->IsLocked() == false); - - if (flag == IsEnabled()) - { - return; - } - - if (flag) - { - m_flags |= e_enabledFlag; - - // Create all proxies. - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - f->CreateProxies(broadPhase, m_xf); - } - - // Contacts are created at the beginning of the next - m_world->m_newContacts = true; - } - else - { - m_flags &= ~e_enabledFlag; - - // Destroy all proxies. - b2BroadPhase* broadPhase = &m_world->m_contactManager.m_broadPhase; - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - f->DestroyProxies(broadPhase); - } - - // Destroy the attached contacts. - b2ContactEdge* ce = m_contactList; - while (ce) - { - b2ContactEdge* ce0 = ce; - ce = ce->next; - m_world->m_contactManager.Destroy(ce0->contact); - } - m_contactList = nullptr; - } -} - -void b2Body::SetFixedRotation(bool flag) -{ - bool status = (m_flags & e_fixedRotationFlag) == e_fixedRotationFlag; - if (status == flag) - { - return; - } - - if (flag) - { - m_flags |= e_fixedRotationFlag; - } - else - { - m_flags &= ~e_fixedRotationFlag; - } - - m_angularVelocity = 0.0f; - - ResetMassData(); -} - -void b2Body::Dump() -{ - int32 bodyIndex = m_islandIndex; - - // %.9g is sufficient to save and load the same value using text - // FLT_DECIMAL_DIG == 9 - - b2Dump("{\n"); - b2Dump(" b2BodyDef bd;\n"); - b2Dump(" bd.type = b2BodyType(%d);\n", m_type); - b2Dump(" bd.position.Set(%.9g, %.9g);\n", m_xf.p.x, m_xf.p.y); - b2Dump(" bd.angle = %.9g;\n", m_sweep.a); - b2Dump(" bd.linearVelocity.Set(%.9g, %.9g);\n", m_linearVelocity.x, m_linearVelocity.y); - b2Dump(" bd.angularVelocity = %.9g;\n", m_angularVelocity); - b2Dump(" bd.linearDamping = %.9g;\n", m_linearDamping); - b2Dump(" bd.angularDamping = %.9g;\n", m_angularDamping); - b2Dump(" bd.allowSleep = bool(%d);\n", m_flags & e_autoSleepFlag); - b2Dump(" bd.awake = bool(%d);\n", m_flags & e_awakeFlag); - b2Dump(" bd.fixedRotation = bool(%d);\n", m_flags & e_fixedRotationFlag); - b2Dump(" bd.bullet = bool(%d);\n", m_flags & e_bulletFlag); - b2Dump(" bd.enabled = bool(%d);\n", m_flags & e_enabledFlag); - b2Dump(" bd.gravityScale = %.9g;\n", m_gravityScale); - b2Dump(" bodies[%d] = m_world->CreateBody(&bd);\n", m_islandIndex); - b2Dump("\n"); - for (b2Fixture* f = m_fixtureList; f; f = f->m_next) - { - b2Dump(" {\n"); - f->Dump(bodyIndex); - b2Dump(" }\n"); - } - b2Dump("}\n"); -} diff --git a/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.cpp b/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.cpp deleted file mode 100644 index 8464fe836312..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_chain_circle_contact.h" -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_edge_shape.h" - -#include - -b2Contact* b2ChainAndCircleContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2ChainAndCircleContact)); - return new (mem) b2ChainAndCircleContact(fixtureA, indexA, fixtureB, indexB); -} - -void b2ChainAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2ChainAndCircleContact*)contact)->~b2ChainAndCircleContact(); - allocator->Free(contact, sizeof(b2ChainAndCircleContact)); -} - -b2ChainAndCircleContact::b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB) -: b2Contact(fixtureA, indexA, fixtureB, indexB) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_chain); - b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); -} - -void b2ChainAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape(); - b2EdgeShape edge; - chain->GetChildEdge(&edge, m_indexA); - b2CollideEdgeAndCircle( manifold, &edge, xfA, - (b2CircleShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.h b/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.h deleted file mode 100644 index 33ced64d80be..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_chain_circle_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CHAIN_AND_CIRCLE_CONTACT_H -#define B2_CHAIN_AND_CIRCLE_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2ChainAndCircleContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2ChainAndCircleContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); - ~b2ChainAndCircleContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.cpp b/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.cpp deleted file mode 100644 index b8257aab9687..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_chain_polygon_contact.h" -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_edge_shape.h" - -#include - -b2Contact* b2ChainAndPolygonContact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2ChainAndPolygonContact)); - return new (mem) b2ChainAndPolygonContact(fixtureA, indexA, fixtureB, indexB); -} - -void b2ChainAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2ChainAndPolygonContact*)contact)->~b2ChainAndPolygonContact(); - allocator->Free(contact, sizeof(b2ChainAndPolygonContact)); -} - -b2ChainAndPolygonContact::b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB) -: b2Contact(fixtureA, indexA, fixtureB, indexB) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_chain); - b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); -} - -void b2ChainAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2ChainShape* chain = (b2ChainShape*)m_fixtureA->GetShape(); - b2EdgeShape edge; - chain->GetChildEdge(&edge, m_indexA); - b2CollideEdgeAndPolygon( manifold, &edge, xfA, - (b2PolygonShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.h b/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.h deleted file mode 100644 index 058154fb1529..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_chain_polygon_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CHAIN_AND_POLYGON_CONTACT_H -#define B2_CHAIN_AND_POLYGON_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2ChainAndPolygonContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2ChainAndPolygonContact(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB); - ~b2ChainAndPolygonContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_circle_contact.cpp b/3rdparty/box2d/src/dynamics/b2_circle_contact.cpp deleted file mode 100644 index 738aa84ca9ca..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_circle_contact.cpp +++ /dev/null @@ -1,56 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_circle_contact.h" -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_body.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_time_of_impact.h" -#include "box2d/b2_world_callbacks.h" - -#include - -b2Contact* b2CircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2CircleContact)); - return new (mem) b2CircleContact(fixtureA, fixtureB); -} - -void b2CircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2CircleContact*)contact)->~b2CircleContact(); - allocator->Free(contact, sizeof(b2CircleContact)); -} - -b2CircleContact::b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) - : b2Contact(fixtureA, 0, fixtureB, 0) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_circle); - b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); -} - -void b2CircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2CollideCircles(manifold, - (b2CircleShape*)m_fixtureA->GetShape(), xfA, - (b2CircleShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_circle_contact.h b/3rdparty/box2d/src/dynamics/b2_circle_contact.h deleted file mode 100644 index 98e09ea5b93a..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_circle_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CIRCLE_CONTACT_H -#define B2_CIRCLE_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2CircleContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2CircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); - ~b2CircleContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_contact.cpp b/3rdparty/box2d/src/dynamics/b2_contact.cpp deleted file mode 100644 index 1c65bc895f54..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_contact.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_chain_circle_contact.h" -#include "b2_chain_polygon_contact.h" -#include "b2_circle_contact.h" -#include "b2_contact_solver.h" -#include "b2_edge_circle_contact.h" -#include "b2_edge_polygon_contact.h" -#include "b2_polygon_circle_contact.h" -#include "b2_polygon_contact.h" - -#include "box2d/b2_contact.h" -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_body.h" -#include "box2d/b2_collision.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_shape.h" -#include "box2d/b2_time_of_impact.h" -#include "box2d/b2_world.h" - -b2ContactRegister b2Contact::s_registers[b2Shape::e_typeCount][b2Shape::e_typeCount]; -bool b2Contact::s_initialized = false; - -void b2Contact::InitializeRegisters() -{ - AddType(b2CircleContact::Create, b2CircleContact::Destroy, b2Shape::e_circle, b2Shape::e_circle); - AddType(b2PolygonAndCircleContact::Create, b2PolygonAndCircleContact::Destroy, b2Shape::e_polygon, b2Shape::e_circle); - AddType(b2PolygonContact::Create, b2PolygonContact::Destroy, b2Shape::e_polygon, b2Shape::e_polygon); - AddType(b2EdgeAndCircleContact::Create, b2EdgeAndCircleContact::Destroy, b2Shape::e_edge, b2Shape::e_circle); - AddType(b2EdgeAndPolygonContact::Create, b2EdgeAndPolygonContact::Destroy, b2Shape::e_edge, b2Shape::e_polygon); - AddType(b2ChainAndCircleContact::Create, b2ChainAndCircleContact::Destroy, b2Shape::e_chain, b2Shape::e_circle); - AddType(b2ChainAndPolygonContact::Create, b2ChainAndPolygonContact::Destroy, b2Shape::e_chain, b2Shape::e_polygon); -} - -void b2Contact::AddType(b2ContactCreateFcn* createFcn, b2ContactDestroyFcn* destoryFcn, - b2Shape::Type type1, b2Shape::Type type2) -{ - b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount); - b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount); - - s_registers[type1][type2].createFcn = createFcn; - s_registers[type1][type2].destroyFcn = destoryFcn; - s_registers[type1][type2].primary = true; - - if (type1 != type2) - { - s_registers[type2][type1].createFcn = createFcn; - s_registers[type2][type1].destroyFcn = destoryFcn; - s_registers[type2][type1].primary = false; - } -} - -b2Contact* b2Contact::Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator) -{ - if (s_initialized == false) - { - InitializeRegisters(); - s_initialized = true; - } - - b2Shape::Type type1 = fixtureA->GetType(); - b2Shape::Type type2 = fixtureB->GetType(); - - b2Assert(0 <= type1 && type1 < b2Shape::e_typeCount); - b2Assert(0 <= type2 && type2 < b2Shape::e_typeCount); - - b2ContactCreateFcn* createFcn = s_registers[type1][type2].createFcn; - if (createFcn) - { - if (s_registers[type1][type2].primary) - { - return createFcn(fixtureA, indexA, fixtureB, indexB, allocator); - } - else - { - return createFcn(fixtureB, indexB, fixtureA, indexA, allocator); - } - } - else - { - return nullptr; - } -} - -void b2Contact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - b2Assert(s_initialized == true); - - b2Fixture* fixtureA = contact->m_fixtureA; - b2Fixture* fixtureB = contact->m_fixtureB; - - if (contact->m_manifold.pointCount > 0 && - fixtureA->IsSensor() == false && - fixtureB->IsSensor() == false) - { - fixtureA->GetBody()->SetAwake(true); - fixtureB->GetBody()->SetAwake(true); - } - - b2Shape::Type typeA = fixtureA->GetType(); - b2Shape::Type typeB = fixtureB->GetType(); - - b2Assert(0 <= typeA && typeA < b2Shape::e_typeCount); - b2Assert(0 <= typeB && typeB < b2Shape::e_typeCount); - - b2ContactDestroyFcn* destroyFcn = s_registers[typeA][typeB].destroyFcn; - destroyFcn(contact, allocator); -} - -b2Contact::b2Contact(b2Fixture* fA, int32 indexA, b2Fixture* fB, int32 indexB) -{ - m_flags = e_enabledFlag; - - m_fixtureA = fA; - m_fixtureB = fB; - - m_indexA = indexA; - m_indexB = indexB; - - m_manifold.pointCount = 0; - - m_prev = nullptr; - m_next = nullptr; - - m_nodeA.contact = nullptr; - m_nodeA.prev = nullptr; - m_nodeA.next = nullptr; - m_nodeA.other = nullptr; - - m_nodeB.contact = nullptr; - m_nodeB.prev = nullptr; - m_nodeB.next = nullptr; - m_nodeB.other = nullptr; - - m_toiCount = 0; - - m_friction = b2MixFriction(m_fixtureA->m_friction, m_fixtureB->m_friction); - m_restitution = b2MixRestitution(m_fixtureA->m_restitution, m_fixtureB->m_restitution); - m_restitutionThreshold = b2MixRestitutionThreshold(m_fixtureA->m_restitutionThreshold, m_fixtureB->m_restitutionThreshold); - - m_tangentSpeed = 0.0f; -} - -// Update the contact manifold and touching status. -// Note: do not assume the fixture AABBs are overlapping or are valid. -void b2Contact::Update(b2ContactListener* listener) -{ - b2Manifold oldManifold = m_manifold; - - // Re-enable this contact. - m_flags |= e_enabledFlag; - - bool touching = false; - bool wasTouching = (m_flags & e_touchingFlag) == e_touchingFlag; - - bool sensorA = m_fixtureA->IsSensor(); - bool sensorB = m_fixtureB->IsSensor(); - bool sensor = sensorA || sensorB; - - b2Body* bodyA = m_fixtureA->GetBody(); - b2Body* bodyB = m_fixtureB->GetBody(); - const b2Transform& xfA = bodyA->GetTransform(); - const b2Transform& xfB = bodyB->GetTransform(); - - // Is this contact a sensor? - if (sensor) - { - const b2Shape* shapeA = m_fixtureA->GetShape(); - const b2Shape* shapeB = m_fixtureB->GetShape(); - touching = b2TestOverlap(shapeA, m_indexA, shapeB, m_indexB, xfA, xfB); - - // Sensors don't generate manifolds. - m_manifold.pointCount = 0; - } - else - { - Evaluate(&m_manifold, xfA, xfB); - touching = m_manifold.pointCount > 0; - - // Match old contact ids to new contact ids and copy the - // stored impulses to warm start the solver. - for (int32 i = 0; i < m_manifold.pointCount; ++i) - { - b2ManifoldPoint* mp2 = m_manifold.points + i; - mp2->normalImpulse = 0.0f; - mp2->tangentImpulse = 0.0f; - b2ContactID id2 = mp2->id; - - for (int32 j = 0; j < oldManifold.pointCount; ++j) - { - b2ManifoldPoint* mp1 = oldManifold.points + j; - - if (mp1->id.key == id2.key) - { - mp2->normalImpulse = mp1->normalImpulse; - mp2->tangentImpulse = mp1->tangentImpulse; - break; - } - } - } - - if (touching != wasTouching) - { - bodyA->SetAwake(true); - bodyB->SetAwake(true); - } - } - - if (touching) - { - m_flags |= e_touchingFlag; - } - else - { - m_flags &= ~e_touchingFlag; - } - - if (wasTouching == false && touching == true && listener) - { - listener->BeginContact(this); - } - - if (wasTouching == true && touching == false && listener) - { - listener->EndContact(this); - } - - if (sensor == false && touching && listener) - { - listener->PreSolve(this, &oldManifold); - } -} diff --git a/3rdparty/box2d/src/dynamics/b2_contact_manager.cpp b/3rdparty/box2d/src/dynamics/b2_contact_manager.cpp deleted file mode 100644 index 56666084cdd8..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_contact_manager.cpp +++ /dev/null @@ -1,293 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_contact_manager.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_world_callbacks.h" - -b2ContactFilter b2_defaultFilter; -b2ContactListener b2_defaultListener; - -b2ContactManager::b2ContactManager() -{ - m_contactList = nullptr; - m_contactCount = 0; - m_contactFilter = &b2_defaultFilter; - m_contactListener = &b2_defaultListener; - m_allocator = nullptr; -} - -void b2ContactManager::Destroy(b2Contact* c) -{ - b2Fixture* fixtureA = c->GetFixtureA(); - b2Fixture* fixtureB = c->GetFixtureB(); - b2Body* bodyA = fixtureA->GetBody(); - b2Body* bodyB = fixtureB->GetBody(); - - if (m_contactListener && c->IsTouching()) - { - m_contactListener->EndContact(c); - } - - // Remove from the world. - if (c->m_prev) - { - c->m_prev->m_next = c->m_next; - } - - if (c->m_next) - { - c->m_next->m_prev = c->m_prev; - } - - if (c == m_contactList) - { - m_contactList = c->m_next; - } - - // Remove from body 1 - if (c->m_nodeA.prev) - { - c->m_nodeA.prev->next = c->m_nodeA.next; - } - - if (c->m_nodeA.next) - { - c->m_nodeA.next->prev = c->m_nodeA.prev; - } - - if (&c->m_nodeA == bodyA->m_contactList) - { - bodyA->m_contactList = c->m_nodeA.next; - } - - // Remove from body 2 - if (c->m_nodeB.prev) - { - c->m_nodeB.prev->next = c->m_nodeB.next; - } - - if (c->m_nodeB.next) - { - c->m_nodeB.next->prev = c->m_nodeB.prev; - } - - if (&c->m_nodeB == bodyB->m_contactList) - { - bodyB->m_contactList = c->m_nodeB.next; - } - - // Call the factory. - b2Contact::Destroy(c, m_allocator); - --m_contactCount; -} - -// This is the top level collision call for the time step. Here -// all the narrow phase collision is processed for the world -// contact list. -void b2ContactManager::Collide() -{ - // Update awake contacts. - b2Contact* c = m_contactList; - while (c) - { - b2Fixture* fixtureA = c->GetFixtureA(); - b2Fixture* fixtureB = c->GetFixtureB(); - int32 indexA = c->GetChildIndexA(); - int32 indexB = c->GetChildIndexB(); - b2Body* bodyA = fixtureA->GetBody(); - b2Body* bodyB = fixtureB->GetBody(); - - // Is this contact flagged for filtering? - if (c->m_flags & b2Contact::e_filterFlag) - { - // Should these bodies collide? - if (bodyB->ShouldCollide(bodyA) == false) - { - b2Contact* cNuke = c; - c = cNuke->GetNext(); - Destroy(cNuke); - continue; - } - - // Check user filtering. - if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) - { - b2Contact* cNuke = c; - c = cNuke->GetNext(); - Destroy(cNuke); - continue; - } - - // Clear the filtering flag. - c->m_flags &= ~b2Contact::e_filterFlag; - } - - bool activeA = bodyA->IsAwake() && bodyA->m_type != b2_staticBody; - bool activeB = bodyB->IsAwake() && bodyB->m_type != b2_staticBody; - - // At least one body must be awake and it must be dynamic or kinematic. - if (activeA == false && activeB == false) - { - c = c->GetNext(); - continue; - } - - int32 proxyIdA = fixtureA->m_proxies[indexA].proxyId; - int32 proxyIdB = fixtureB->m_proxies[indexB].proxyId; - bool overlap = m_broadPhase.TestOverlap(proxyIdA, proxyIdB); - - // Here we destroy contacts that cease to overlap in the broad-phase. - if (overlap == false) - { - b2Contact* cNuke = c; - c = cNuke->GetNext(); - Destroy(cNuke); - continue; - } - - // The contact persists. - c->Update(m_contactListener); - c = c->GetNext(); - } -} - -void b2ContactManager::FindNewContacts() -{ - m_broadPhase.UpdatePairs(this); -} - -void b2ContactManager::AddPair(void* proxyUserDataA, void* proxyUserDataB) -{ - b2FixtureProxy* proxyA = (b2FixtureProxy*)proxyUserDataA; - b2FixtureProxy* proxyB = (b2FixtureProxy*)proxyUserDataB; - - b2Fixture* fixtureA = proxyA->fixture; - b2Fixture* fixtureB = proxyB->fixture; - - int32 indexA = proxyA->childIndex; - int32 indexB = proxyB->childIndex; - - b2Body* bodyA = fixtureA->GetBody(); - b2Body* bodyB = fixtureB->GetBody(); - - // Are the fixtures on the same body? - if (bodyA == bodyB) - { - return; - } - - // TODO_ERIN use a hash table to remove a potential bottleneck when both - // bodies have a lot of contacts. - // Does a contact already exist? - b2ContactEdge* edge = bodyB->GetContactList(); - while (edge) - { - if (edge->other == bodyA) - { - b2Fixture* fA = edge->contact->GetFixtureA(); - b2Fixture* fB = edge->contact->GetFixtureB(); - int32 iA = edge->contact->GetChildIndexA(); - int32 iB = edge->contact->GetChildIndexB(); - - if (fA == fixtureA && fB == fixtureB && iA == indexA && iB == indexB) - { - // A contact already exists. - return; - } - - if (fA == fixtureB && fB == fixtureA && iA == indexB && iB == indexA) - { - // A contact already exists. - return; - } - } - - edge = edge->next; - } - - // Does a joint override collision? Is at least one body dynamic? - if (bodyB->ShouldCollide(bodyA) == false) - { - return; - } - - // Check user filtering. - if (m_contactFilter && m_contactFilter->ShouldCollide(fixtureA, fixtureB) == false) - { - return; - } - - // Call the factory. - b2Contact* c = b2Contact::Create(fixtureA, indexA, fixtureB, indexB, m_allocator); - if (c == nullptr) - { - return; - } - - // Contact creation may swap fixtures. - fixtureA = c->GetFixtureA(); - fixtureB = c->GetFixtureB(); - indexA = c->GetChildIndexA(); - indexB = c->GetChildIndexB(); - bodyA = fixtureA->GetBody(); - bodyB = fixtureB->GetBody(); - - // Insert into the world. - c->m_prev = nullptr; - c->m_next = m_contactList; - if (m_contactList != nullptr) - { - m_contactList->m_prev = c; - } - m_contactList = c; - - // Connect to island graph. - - // Connect to body A - c->m_nodeA.contact = c; - c->m_nodeA.other = bodyB; - - c->m_nodeA.prev = nullptr; - c->m_nodeA.next = bodyA->m_contactList; - if (bodyA->m_contactList != nullptr) - { - bodyA->m_contactList->prev = &c->m_nodeA; - } - bodyA->m_contactList = &c->m_nodeA; - - // Connect to body B - c->m_nodeB.contact = c; - c->m_nodeB.other = bodyA; - - c->m_nodeB.prev = nullptr; - c->m_nodeB.next = bodyB->m_contactList; - if (bodyB->m_contactList != nullptr) - { - bodyB->m_contactList->prev = &c->m_nodeB; - } - bodyB->m_contactList = &c->m_nodeB; - - ++m_contactCount; -} diff --git a/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp b/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp deleted file mode 100644 index d6c08fb17972..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_contact_solver.cpp +++ /dev/null @@ -1,843 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_contact_solver.h" - -#include "box2d/b2_body.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_stack_allocator.h" -#include "box2d/b2_world.h" - -// Solver debugging is normally disabled because the block solver sometimes has to deal with a poorly conditioned effective mass matrix. -#define B2_DEBUG_SOLVER 0 - -B2_API bool g_blockSolve = true; - -struct b2ContactPositionConstraint -{ - b2Vec2 localPoints[b2_maxManifoldPoints]; - b2Vec2 localNormal; - b2Vec2 localPoint; - int32 indexA; - int32 indexB; - float invMassA, invMassB; - b2Vec2 localCenterA, localCenterB; - float invIA, invIB; - b2Manifold::Type type; - float radiusA, radiusB; - int32 pointCount; -}; - -b2ContactSolver::b2ContactSolver(b2ContactSolverDef* def) -{ - m_step = def->step; - m_allocator = def->allocator; - m_count = def->count; - m_positionConstraints = (b2ContactPositionConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactPositionConstraint)); - m_velocityConstraints = (b2ContactVelocityConstraint*)m_allocator->Allocate(m_count * sizeof(b2ContactVelocityConstraint)); - m_positions = def->positions; - m_velocities = def->velocities; - m_contacts = def->contacts; - - // Initialize position independent portions of the constraints. - for (int32 i = 0; i < m_count; ++i) - { - b2Contact* contact = m_contacts[i]; - - b2Fixture* fixtureA = contact->m_fixtureA; - b2Fixture* fixtureB = contact->m_fixtureB; - b2Shape* shapeA = fixtureA->GetShape(); - b2Shape* shapeB = fixtureB->GetShape(); - float radiusA = shapeA->m_radius; - float radiusB = shapeB->m_radius; - b2Body* bodyA = fixtureA->GetBody(); - b2Body* bodyB = fixtureB->GetBody(); - b2Manifold* manifold = contact->GetManifold(); - - int32 pointCount = manifold->pointCount; - b2Assert(pointCount > 0); - - b2ContactVelocityConstraint* vc = m_velocityConstraints + i; - vc->friction = contact->m_friction; - vc->restitution = contact->m_restitution; - vc->threshold = contact->m_restitutionThreshold; - vc->tangentSpeed = contact->m_tangentSpeed; - vc->indexA = bodyA->m_islandIndex; - vc->indexB = bodyB->m_islandIndex; - vc->invMassA = bodyA->m_invMass; - vc->invMassB = bodyB->m_invMass; - vc->invIA = bodyA->m_invI; - vc->invIB = bodyB->m_invI; - vc->contactIndex = i; - vc->pointCount = pointCount; - vc->K.SetZero(); - vc->normalMass.SetZero(); - - b2ContactPositionConstraint* pc = m_positionConstraints + i; - pc->indexA = bodyA->m_islandIndex; - pc->indexB = bodyB->m_islandIndex; - pc->invMassA = bodyA->m_invMass; - pc->invMassB = bodyB->m_invMass; - pc->localCenterA = bodyA->m_sweep.localCenter; - pc->localCenterB = bodyB->m_sweep.localCenter; - pc->invIA = bodyA->m_invI; - pc->invIB = bodyB->m_invI; - pc->localNormal = manifold->localNormal; - pc->localPoint = manifold->localPoint; - pc->pointCount = pointCount; - pc->radiusA = radiusA; - pc->radiusB = radiusB; - pc->type = manifold->type; - - for (int32 j = 0; j < pointCount; ++j) - { - b2ManifoldPoint* cp = manifold->points + j; - b2VelocityConstraintPoint* vcp = vc->points + j; - - if (m_step.warmStarting) - { - vcp->normalImpulse = m_step.dtRatio * cp->normalImpulse; - vcp->tangentImpulse = m_step.dtRatio * cp->tangentImpulse; - } - else - { - vcp->normalImpulse = 0.0f; - vcp->tangentImpulse = 0.0f; - } - - vcp->rA.SetZero(); - vcp->rB.SetZero(); - vcp->normalMass = 0.0f; - vcp->tangentMass = 0.0f; - vcp->velocityBias = 0.0f; - - pc->localPoints[j] = cp->localPoint; - } - } -} - -b2ContactSolver::~b2ContactSolver() -{ - m_allocator->Free(m_velocityConstraints); - m_allocator->Free(m_positionConstraints); -} - -// Initialize position dependent portions of the velocity constraints. -void b2ContactSolver::InitializeVelocityConstraints() -{ - for (int32 i = 0; i < m_count; ++i) - { - b2ContactVelocityConstraint* vc = m_velocityConstraints + i; - b2ContactPositionConstraint* pc = m_positionConstraints + i; - - float radiusA = pc->radiusA; - float radiusB = pc->radiusB; - b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold(); - - int32 indexA = vc->indexA; - int32 indexB = vc->indexB; - - float mA = vc->invMassA; - float mB = vc->invMassB; - float iA = vc->invIA; - float iB = vc->invIB; - b2Vec2 localCenterA = pc->localCenterA; - b2Vec2 localCenterB = pc->localCenterB; - - b2Vec2 cA = m_positions[indexA].c; - float aA = m_positions[indexA].a; - b2Vec2 vA = m_velocities[indexA].v; - float wA = m_velocities[indexA].w; - - b2Vec2 cB = m_positions[indexB].c; - float aB = m_positions[indexB].a; - b2Vec2 vB = m_velocities[indexB].v; - float wB = m_velocities[indexB].w; - - b2Assert(manifold->pointCount > 0); - - b2Transform xfA, xfB; - xfA.q.Set(aA); - xfB.q.Set(aB); - xfA.p = cA - b2Mul(xfA.q, localCenterA); - xfB.p = cB - b2Mul(xfB.q, localCenterB); - - b2WorldManifold worldManifold; - worldManifold.Initialize(manifold, xfA, radiusA, xfB, radiusB); - - vc->normal = worldManifold.normal; - - int32 pointCount = vc->pointCount; - for (int32 j = 0; j < pointCount; ++j) - { - b2VelocityConstraintPoint* vcp = vc->points + j; - - vcp->rA = worldManifold.points[j] - cA; - vcp->rB = worldManifold.points[j] - cB; - - float rnA = b2Cross(vcp->rA, vc->normal); - float rnB = b2Cross(vcp->rB, vc->normal); - - float kNormal = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - - vcp->normalMass = kNormal > 0.0f ? 1.0f / kNormal : 0.0f; - - b2Vec2 tangent = b2Cross(vc->normal, 1.0f); - - float rtA = b2Cross(vcp->rA, tangent); - float rtB = b2Cross(vcp->rB, tangent); - - float kTangent = mA + mB + iA * rtA * rtA + iB * rtB * rtB; - - vcp->tangentMass = kTangent > 0.0f ? 1.0f / kTangent : 0.0f; - - // Setup a velocity bias for restitution. - vcp->velocityBias = 0.0f; - float vRel = b2Dot(vc->normal, vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA)); - if (vRel < -vc->threshold) - { - vcp->velocityBias = -vc->restitution * vRel; - } - } - - // If we have two points, then prepare the block solver. - if (vc->pointCount == 2 && g_blockSolve) - { - b2VelocityConstraintPoint* vcp1 = vc->points + 0; - b2VelocityConstraintPoint* vcp2 = vc->points + 1; - - float rn1A = b2Cross(vcp1->rA, vc->normal); - float rn1B = b2Cross(vcp1->rB, vc->normal); - float rn2A = b2Cross(vcp2->rA, vc->normal); - float rn2B = b2Cross(vcp2->rB, vc->normal); - - float k11 = mA + mB + iA * rn1A * rn1A + iB * rn1B * rn1B; - float k22 = mA + mB + iA * rn2A * rn2A + iB * rn2B * rn2B; - float k12 = mA + mB + iA * rn1A * rn2A + iB * rn1B * rn2B; - - // Ensure a reasonable condition number. - const float k_maxConditionNumber = 1000.0f; - if (k11 * k11 < k_maxConditionNumber * (k11 * k22 - k12 * k12)) - { - // K is safe to invert. - vc->K.ex.Set(k11, k12); - vc->K.ey.Set(k12, k22); - vc->normalMass = vc->K.GetInverse(); - } - else - { - // The constraints are redundant, just use one. - // TODO_ERIN use deepest? - vc->pointCount = 1; - } - } - } -} - -void b2ContactSolver::WarmStart() -{ - // Warm start. - for (int32 i = 0; i < m_count; ++i) - { - b2ContactVelocityConstraint* vc = m_velocityConstraints + i; - - int32 indexA = vc->indexA; - int32 indexB = vc->indexB; - float mA = vc->invMassA; - float iA = vc->invIA; - float mB = vc->invMassB; - float iB = vc->invIB; - int32 pointCount = vc->pointCount; - - b2Vec2 vA = m_velocities[indexA].v; - float wA = m_velocities[indexA].w; - b2Vec2 vB = m_velocities[indexB].v; - float wB = m_velocities[indexB].w; - - b2Vec2 normal = vc->normal; - b2Vec2 tangent = b2Cross(normal, 1.0f); - - for (int32 j = 0; j < pointCount; ++j) - { - b2VelocityConstraintPoint* vcp = vc->points + j; - b2Vec2 P = vcp->normalImpulse * normal + vcp->tangentImpulse * tangent; - wA -= iA * b2Cross(vcp->rA, P); - vA -= mA * P; - wB += iB * b2Cross(vcp->rB, P); - vB += mB * P; - } - - m_velocities[indexA].v = vA; - m_velocities[indexA].w = wA; - m_velocities[indexB].v = vB; - m_velocities[indexB].w = wB; - } -} - -void b2ContactSolver::SolveVelocityConstraints() -{ - for (int32 i = 0; i < m_count; ++i) - { - b2ContactVelocityConstraint* vc = m_velocityConstraints + i; - - int32 indexA = vc->indexA; - int32 indexB = vc->indexB; - float mA = vc->invMassA; - float iA = vc->invIA; - float mB = vc->invMassB; - float iB = vc->invIB; - int32 pointCount = vc->pointCount; - - b2Vec2 vA = m_velocities[indexA].v; - float wA = m_velocities[indexA].w; - b2Vec2 vB = m_velocities[indexB].v; - float wB = m_velocities[indexB].w; - - b2Vec2 normal = vc->normal; - b2Vec2 tangent = b2Cross(normal, 1.0f); - float friction = vc->friction; - - b2Assert(pointCount == 1 || pointCount == 2); - - // Solve tangent constraints first because non-penetration is more important - // than friction. - for (int32 j = 0; j < pointCount; ++j) - { - b2VelocityConstraintPoint* vcp = vc->points + j; - - // Relative velocity at contact - b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA); - - // Compute tangent force - float vt = b2Dot(dv, tangent) - vc->tangentSpeed; - float lambda = vcp->tangentMass * (-vt); - - // b2Clamp the accumulated force - float maxFriction = friction * vcp->normalImpulse; - float newImpulse = b2Clamp(vcp->tangentImpulse + lambda, -maxFriction, maxFriction); - lambda = newImpulse - vcp->tangentImpulse; - vcp->tangentImpulse = newImpulse; - - // Apply contact impulse - b2Vec2 P = lambda * tangent; - - vA -= mA * P; - wA -= iA * b2Cross(vcp->rA, P); - - vB += mB * P; - wB += iB * b2Cross(vcp->rB, P); - } - - // Solve normal constraints - if (pointCount == 1 || g_blockSolve == false) - { - for (int32 j = 0; j < pointCount; ++j) - { - b2VelocityConstraintPoint* vcp = vc->points + j; - - // Relative velocity at contact - b2Vec2 dv = vB + b2Cross(wB, vcp->rB) - vA - b2Cross(wA, vcp->rA); - - // Compute normal impulse - float vn = b2Dot(dv, normal); - float lambda = -vcp->normalMass * (vn - vcp->velocityBias); - - // b2Clamp the accumulated impulse - float newImpulse = b2Max(vcp->normalImpulse + lambda, 0.0f); - lambda = newImpulse - vcp->normalImpulse; - vcp->normalImpulse = newImpulse; - - // Apply contact impulse - b2Vec2 P = lambda * normal; - vA -= mA * P; - wA -= iA * b2Cross(vcp->rA, P); - - vB += mB * P; - wB += iB * b2Cross(vcp->rB, P); - } - } - else - { - // Block solver developed in collaboration with Dirk Gregorius (back in 01/07 on Box2D_Lite). - // Build the mini LCP for this contact patch - // - // vn = A * x + b, vn >= 0, x >= 0 and vn_i * x_i = 0 with i = 1..2 - // - // A = J * W * JT and J = ( -n, -r1 x n, n, r2 x n ) - // b = vn0 - velocityBias - // - // The system is solved using the "Total enumeration method" (s. Murty). The complementary constraint vn_i * x_i - // implies that we must have in any solution either vn_i = 0 or x_i = 0. So for the 2D contact problem the cases - // vn1 = 0 and vn2 = 0, x1 = 0 and x2 = 0, x1 = 0 and vn2 = 0, x2 = 0 and vn1 = 0 need to be tested. The first valid - // solution that satisfies the problem is chosen. - // - // In order to account of the accumulated impulse 'a' (because of the iterative nature of the solver which only requires - // that the accumulated impulse is clamped and not the incremental impulse) we change the impulse variable (x_i). - // - // Substitute: - // - // x = a + d - // - // a := old total impulse - // x := new total impulse - // d := incremental impulse - // - // For the current iteration we extend the formula for the incremental impulse - // to compute the new total impulse: - // - // vn = A * d + b - // = A * (x - a) + b - // = A * x + b - A * a - // = A * x + b' - // b' = b - A * a; - - b2VelocityConstraintPoint* cp1 = vc->points + 0; - b2VelocityConstraintPoint* cp2 = vc->points + 1; - - b2Vec2 a(cp1->normalImpulse, cp2->normalImpulse); - b2Assert(a.x >= 0.0f && a.y >= 0.0f); - - // Relative velocity at contact - b2Vec2 dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); - b2Vec2 dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); - - // Compute normal velocity - float vn1 = b2Dot(dv1, normal); - float vn2 = b2Dot(dv2, normal); - - b2Vec2 b; - b.x = vn1 - cp1->velocityBias; - b.y = vn2 - cp2->velocityBias; - - // Compute b' - b -= b2Mul(vc->K, a); - - const float k_errorTol = 1e-3f; - B2_NOT_USED(k_errorTol); - - for (;;) - { - // - // Case 1: vn = 0 - // - // 0 = A * x + b' - // - // Solve for x: - // - // x = - inv(A) * b' - // - b2Vec2 x = - b2Mul(vc->normalMass, b); - - if (x.x >= 0.0f && x.y >= 0.0f) - { - // Get the incremental impulse - b2Vec2 d = x - a; - - // Apply incremental impulse - b2Vec2 P1 = d.x * normal; - b2Vec2 P2 = d.y * normal; - vA -= mA * (P1 + P2); - wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); - - vB += mB * (P1 + P2); - wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); - - // Accumulate - cp1->normalImpulse = x.x; - cp2->normalImpulse = x.y; - -#if B2_DEBUG_SOLVER == 1 - // Postconditions - dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); - dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); - - // Compute normal velocity - vn1 = b2Dot(dv1, normal); - vn2 = b2Dot(dv2, normal); - - b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol); - b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol); -#endif - break; - } - - // - // Case 2: vn1 = 0 and x2 = 0 - // - // 0 = a11 * x1 + a12 * 0 + b1' - // vn2 = a21 * x1 + a22 * 0 + b2' - // - x.x = - cp1->normalMass * b.x; - x.y = 0.0f; - vn1 = 0.0f; - vn2 = vc->K.ex.y * x.x + b.y; - if (x.x >= 0.0f && vn2 >= 0.0f) - { - // Get the incremental impulse - b2Vec2 d = x - a; - - // Apply incremental impulse - b2Vec2 P1 = d.x * normal; - b2Vec2 P2 = d.y * normal; - vA -= mA * (P1 + P2); - wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); - - vB += mB * (P1 + P2); - wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); - - // Accumulate - cp1->normalImpulse = x.x; - cp2->normalImpulse = x.y; - -#if B2_DEBUG_SOLVER == 1 - // Postconditions - dv1 = vB + b2Cross(wB, cp1->rB) - vA - b2Cross(wA, cp1->rA); - - // Compute normal velocity - vn1 = b2Dot(dv1, normal); - - b2Assert(b2Abs(vn1 - cp1->velocityBias) < k_errorTol); -#endif - break; - } - - - // - // Case 3: vn2 = 0 and x1 = 0 - // - // vn1 = a11 * 0 + a12 * x2 + b1' - // 0 = a21 * 0 + a22 * x2 + b2' - // - x.x = 0.0f; - x.y = - cp2->normalMass * b.y; - vn1 = vc->K.ey.x * x.y + b.x; - vn2 = 0.0f; - - if (x.y >= 0.0f && vn1 >= 0.0f) - { - // Resubstitute for the incremental impulse - b2Vec2 d = x - a; - - // Apply incremental impulse - b2Vec2 P1 = d.x * normal; - b2Vec2 P2 = d.y * normal; - vA -= mA * (P1 + P2); - wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); - - vB += mB * (P1 + P2); - wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); - - // Accumulate - cp1->normalImpulse = x.x; - cp2->normalImpulse = x.y; - -#if B2_DEBUG_SOLVER == 1 - // Postconditions - dv2 = vB + b2Cross(wB, cp2->rB) - vA - b2Cross(wA, cp2->rA); - - // Compute normal velocity - vn2 = b2Dot(dv2, normal); - - b2Assert(b2Abs(vn2 - cp2->velocityBias) < k_errorTol); -#endif - break; - } - - // - // Case 4: x1 = 0 and x2 = 0 - // - // vn1 = b1 - // vn2 = b2; - x.x = 0.0f; - x.y = 0.0f; - vn1 = b.x; - vn2 = b.y; - - if (vn1 >= 0.0f && vn2 >= 0.0f ) - { - // Resubstitute for the incremental impulse - b2Vec2 d = x - a; - - // Apply incremental impulse - b2Vec2 P1 = d.x * normal; - b2Vec2 P2 = d.y * normal; - vA -= mA * (P1 + P2); - wA -= iA * (b2Cross(cp1->rA, P1) + b2Cross(cp2->rA, P2)); - - vB += mB * (P1 + P2); - wB += iB * (b2Cross(cp1->rB, P1) + b2Cross(cp2->rB, P2)); - - // Accumulate - cp1->normalImpulse = x.x; - cp2->normalImpulse = x.y; - - break; - } - - // No solution, give up. This is hit sometimes, but it doesn't seem to matter. - break; - } - } - - m_velocities[indexA].v = vA; - m_velocities[indexA].w = wA; - m_velocities[indexB].v = vB; - m_velocities[indexB].w = wB; - } -} - -void b2ContactSolver::StoreImpulses() -{ - for (int32 i = 0; i < m_count; ++i) - { - b2ContactVelocityConstraint* vc = m_velocityConstraints + i; - b2Manifold* manifold = m_contacts[vc->contactIndex]->GetManifold(); - - for (int32 j = 0; j < vc->pointCount; ++j) - { - manifold->points[j].normalImpulse = vc->points[j].normalImpulse; - manifold->points[j].tangentImpulse = vc->points[j].tangentImpulse; - } - } -} - -struct b2PositionSolverManifold -{ - void Initialize(b2ContactPositionConstraint* pc, const b2Transform& xfA, const b2Transform& xfB, int32 index) - { - b2Assert(pc->pointCount > 0); - - switch (pc->type) - { - case b2Manifold::e_circles: - { - b2Vec2 pointA = b2Mul(xfA, pc->localPoint); - b2Vec2 pointB = b2Mul(xfB, pc->localPoints[0]); - normal = pointB - pointA; - normal.Normalize(); - point = 0.5f * (pointA + pointB); - separation = b2Dot(pointB - pointA, normal) - pc->radiusA - pc->radiusB; - } - break; - - case b2Manifold::e_faceA: - { - normal = b2Mul(xfA.q, pc->localNormal); - b2Vec2 planePoint = b2Mul(xfA, pc->localPoint); - - b2Vec2 clipPoint = b2Mul(xfB, pc->localPoints[index]); - separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB; - point = clipPoint; - } - break; - - case b2Manifold::e_faceB: - { - normal = b2Mul(xfB.q, pc->localNormal); - b2Vec2 planePoint = b2Mul(xfB, pc->localPoint); - - b2Vec2 clipPoint = b2Mul(xfA, pc->localPoints[index]); - separation = b2Dot(clipPoint - planePoint, normal) - pc->radiusA - pc->radiusB; - point = clipPoint; - - // Ensure normal points from A to B - normal = -normal; - } - break; - } - } - - b2Vec2 normal; - b2Vec2 point; - float separation; -}; - -// Sequential solver. -bool b2ContactSolver::SolvePositionConstraints() -{ - float minSeparation = 0.0f; - - for (int32 i = 0; i < m_count; ++i) - { - b2ContactPositionConstraint* pc = m_positionConstraints + i; - - int32 indexA = pc->indexA; - int32 indexB = pc->indexB; - b2Vec2 localCenterA = pc->localCenterA; - float mA = pc->invMassA; - float iA = pc->invIA; - b2Vec2 localCenterB = pc->localCenterB; - float mB = pc->invMassB; - float iB = pc->invIB; - int32 pointCount = pc->pointCount; - - b2Vec2 cA = m_positions[indexA].c; - float aA = m_positions[indexA].a; - - b2Vec2 cB = m_positions[indexB].c; - float aB = m_positions[indexB].a; - - // Solve normal constraints - for (int32 j = 0; j < pointCount; ++j) - { - b2Transform xfA, xfB; - xfA.q.Set(aA); - xfB.q.Set(aB); - xfA.p = cA - b2Mul(xfA.q, localCenterA); - xfB.p = cB - b2Mul(xfB.q, localCenterB); - - b2PositionSolverManifold psm; - psm.Initialize(pc, xfA, xfB, j); - b2Vec2 normal = psm.normal; - - b2Vec2 point = psm.point; - float separation = psm.separation; - - b2Vec2 rA = point - cA; - b2Vec2 rB = point - cB; - - // Track max constraint error. - minSeparation = b2Min(minSeparation, separation); - - // Prevent large corrections and allow slop. - float C = b2Clamp(b2_baumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f); - - // Compute the effective mass. - float rnA = b2Cross(rA, normal); - float rnB = b2Cross(rB, normal); - float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - - // Compute normal impulse - float impulse = K > 0.0f ? - C / K : 0.0f; - - b2Vec2 P = impulse * normal; - - cA -= mA * P; - aA -= iA * b2Cross(rA, P); - - cB += mB * P; - aB += iB * b2Cross(rB, P); - } - - m_positions[indexA].c = cA; - m_positions[indexA].a = aA; - - m_positions[indexB].c = cB; - m_positions[indexB].a = aB; - } - - // We can't expect minSpeparation >= -b2_linearSlop because we don't - // push the separation above -b2_linearSlop. - return minSeparation >= -3.0f * b2_linearSlop; -} - -// Sequential position solver for position constraints. -bool b2ContactSolver::SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB) -{ - float minSeparation = 0.0f; - - for (int32 i = 0; i < m_count; ++i) - { - b2ContactPositionConstraint* pc = m_positionConstraints + i; - - int32 indexA = pc->indexA; - int32 indexB = pc->indexB; - b2Vec2 localCenterA = pc->localCenterA; - b2Vec2 localCenterB = pc->localCenterB; - int32 pointCount = pc->pointCount; - - float mA = 0.0f; - float iA = 0.0f; - if (indexA == toiIndexA || indexA == toiIndexB) - { - mA = pc->invMassA; - iA = pc->invIA; - } - - float mB = 0.0f; - float iB = 0.0f; - if (indexB == toiIndexA || indexB == toiIndexB) - { - mB = pc->invMassB; - iB = pc->invIB; - } - - b2Vec2 cA = m_positions[indexA].c; - float aA = m_positions[indexA].a; - - b2Vec2 cB = m_positions[indexB].c; - float aB = m_positions[indexB].a; - - // Solve normal constraints - for (int32 j = 0; j < pointCount; ++j) - { - b2Transform xfA, xfB; - xfA.q.Set(aA); - xfB.q.Set(aB); - xfA.p = cA - b2Mul(xfA.q, localCenterA); - xfB.p = cB - b2Mul(xfB.q, localCenterB); - - b2PositionSolverManifold psm; - psm.Initialize(pc, xfA, xfB, j); - b2Vec2 normal = psm.normal; - - b2Vec2 point = psm.point; - float separation = psm.separation; - - b2Vec2 rA = point - cA; - b2Vec2 rB = point - cB; - - // Track max constraint error. - minSeparation = b2Min(minSeparation, separation); - - // Prevent large corrections and allow slop. - float C = b2Clamp(b2_toiBaumgarte * (separation + b2_linearSlop), -b2_maxLinearCorrection, 0.0f); - - // Compute the effective mass. - float rnA = b2Cross(rA, normal); - float rnB = b2Cross(rB, normal); - float K = mA + mB + iA * rnA * rnA + iB * rnB * rnB; - - // Compute normal impulse - float impulse = K > 0.0f ? - C / K : 0.0f; - - b2Vec2 P = impulse * normal; - - cA -= mA * P; - aA -= iA * b2Cross(rA, P); - - cB += mB * P; - aB += iB * b2Cross(rB, P); - } - - m_positions[indexA].c = cA; - m_positions[indexA].a = aA; - - m_positions[indexB].c = cB; - m_positions[indexB].a = aB; - } - - // We can't expect minSpeparation >= -b2_linearSlop because we don't - // push the separation above -b2_linearSlop. - return minSeparation >= -1.5f * b2_linearSlop; -} diff --git a/3rdparty/box2d/src/dynamics/b2_contact_solver.h b/3rdparty/box2d/src/dynamics/b2_contact_solver.h deleted file mode 100644 index 1064738ef793..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_contact_solver.h +++ /dev/null @@ -1,100 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_CONTACT_SOLVER_H -#define B2_CONTACT_SOLVER_H - -#include "box2d/b2_collision.h" -#include "box2d/b2_math.h" -#include "box2d/b2_time_step.h" - -class b2Contact; -class b2Body; -class b2StackAllocator; -struct b2ContactPositionConstraint; - -struct b2VelocityConstraintPoint -{ - b2Vec2 rA; - b2Vec2 rB; - float normalImpulse; - float tangentImpulse; - float normalMass; - float tangentMass; - float velocityBias; -}; - -struct b2ContactVelocityConstraint -{ - b2VelocityConstraintPoint points[b2_maxManifoldPoints]; - b2Vec2 normal; - b2Mat22 normalMass; - b2Mat22 K; - int32 indexA; - int32 indexB; - float invMassA, invMassB; - float invIA, invIB; - float friction; - float restitution; - float threshold; - float tangentSpeed; - int32 pointCount; - int32 contactIndex; -}; - -struct b2ContactSolverDef -{ - b2TimeStep step; - b2Contact** contacts; - int32 count; - b2Position* positions; - b2Velocity* velocities; - b2StackAllocator* allocator; -}; - -class b2ContactSolver -{ -public: - b2ContactSolver(b2ContactSolverDef* def); - ~b2ContactSolver(); - - void InitializeVelocityConstraints(); - - void WarmStart(); - void SolveVelocityConstraints(); - void StoreImpulses(); - - bool SolvePositionConstraints(); - bool SolveTOIPositionConstraints(int32 toiIndexA, int32 toiIndexB); - - b2TimeStep m_step; - b2Position* m_positions; - b2Velocity* m_velocities; - b2StackAllocator* m_allocator; - b2ContactPositionConstraint* m_positionConstraints; - b2ContactVelocityConstraint* m_velocityConstraints; - b2Contact** m_contacts; - int m_count; -}; - -#endif - diff --git a/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp b/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp deleted file mode 100644 index 221309ef00ab..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_distance_joint.cpp +++ /dev/null @@ -1,421 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_distance_joint.h" -#include "box2d/b2_time_step.h" - -// 1-D constrained system -// m (v2 - v1) = lambda -// v2 + (beta/h) * x1 + gamma * lambda = 0, gamma has units of inverse mass. -// x2 = x1 + h * v2 - -// 1-D mass-damper-spring system -// m (v2 - v1) + h * d * v2 + h * k * - -// C = norm(p2 - p1) - L -// u = (p2 - p1) / norm(p2 - p1) -// Cdot = dot(u, v2 + cross(w2, r2) - v1 - cross(w1, r1)) -// J = [-u -cross(r1, u) u cross(r2, u)] -// K = J * invM * JT -// = invMass1 + invI1 * cross(r1, u)^2 + invMass2 + invI2 * cross(r2, u)^2 - - -void b2DistanceJointDef::Initialize(b2Body* b1, b2Body* b2, - const b2Vec2& anchor1, const b2Vec2& anchor2) -{ - bodyA = b1; - bodyB = b2; - localAnchorA = bodyA->GetLocalPoint(anchor1); - localAnchorB = bodyB->GetLocalPoint(anchor2); - b2Vec2 d = anchor2 - anchor1; - length = b2Max(d.Length(), b2_linearSlop); - minLength = length; - maxLength = length; -} - -b2DistanceJoint::b2DistanceJoint(const b2DistanceJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - m_length = b2Max(def->length, b2_linearSlop); - m_minLength = b2Max(def->minLength, b2_linearSlop); - m_maxLength = b2Max(def->maxLength, m_minLength); - m_stiffness = def->stiffness; - m_damping = def->damping; - - m_gamma = 0.0f; - m_bias = 0.0f; - m_impulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - m_currentLength = 0.0f; -} - -void b2DistanceJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - m_u = cB + m_rB - cA - m_rA; - - // Handle singularity. - m_currentLength = m_u.Length(); - if (m_currentLength > b2_linearSlop) - { - m_u *= 1.0f / m_currentLength; - } - else - { - m_u.Set(0.0f, 0.0f); - m_mass = 0.0f; - m_impulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - float crAu = b2Cross(m_rA, m_u); - float crBu = b2Cross(m_rB, m_u); - float invMass = m_invMassA + m_invIA * crAu * crAu + m_invMassB + m_invIB * crBu * crBu; - m_mass = invMass != 0.0f ? 1.0f / invMass : 0.0f; - - if (m_stiffness > 0.0f && m_minLength < m_maxLength) - { - // soft - float C = m_currentLength - m_length; - - float d = m_damping; - float k = m_stiffness; - - // magic formulas - float h = data.step.dt; - - // gamma = 1 / (h * (d + h * k)) - // the extra factor of h in the denominator is since the lambda is an impulse, not a force - m_gamma = h * (d + h * k); - m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f; - m_bias = C * h * k * m_gamma; - - invMass += m_gamma; - m_softMass = invMass != 0.0f ? 1.0f / invMass : 0.0f; - } - else - { - // rigid - m_gamma = 0.0f; - m_bias = 0.0f; - m_softMass = m_mass; - } - - if (data.step.warmStarting) - { - // Scale the impulse to support a variable time step. - m_impulse *= data.step.dtRatio; - m_lowerImpulse *= data.step.dtRatio; - m_upperImpulse *= data.step.dtRatio; - - b2Vec2 P = (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u; - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); - } - else - { - m_impulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2DistanceJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - if (m_minLength < m_maxLength) - { - if (m_stiffness > 0.0f) - { - // Cdot = dot(u, v + cross(w, r)) - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - float Cdot = b2Dot(m_u, vpB - vpA); - - float impulse = -m_softMass * (Cdot + m_bias + m_gamma * m_impulse); - m_impulse += impulse; - - b2Vec2 P = impulse * m_u; - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); - } - - // lower - { - float C = m_currentLength - m_minLength; - float bias = b2Max(0.0f, C) * data.step.inv_dt; - - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - float Cdot = b2Dot(m_u, vpB - vpA); - - float impulse = -m_mass * (Cdot + bias); - float oldImpulse = m_lowerImpulse; - m_lowerImpulse = b2Max(0.0f, m_lowerImpulse + impulse); - impulse = m_lowerImpulse - oldImpulse; - b2Vec2 P = impulse * m_u; - - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); - } - - // upper - { - float C = m_maxLength - m_currentLength; - float bias = b2Max(0.0f, C) * data.step.inv_dt; - - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - float Cdot = b2Dot(m_u, vpA - vpB); - - float impulse = -m_mass * (Cdot + bias); - float oldImpulse = m_upperImpulse; - m_upperImpulse = b2Max(0.0f, m_upperImpulse + impulse); - impulse = m_upperImpulse - oldImpulse; - b2Vec2 P = -impulse * m_u; - - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); - } - } - else - { - // Equal limits - - // Cdot = dot(u, v + cross(w, r)) - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - float Cdot = b2Dot(m_u, vpB - vpA); - - float impulse = -m_mass * Cdot; - m_impulse += impulse; - - b2Vec2 P = impulse * m_u; - vA -= m_invMassA * P; - wA -= m_invIA * b2Cross(m_rA, P); - vB += m_invMassB * P; - wB += m_invIB * b2Cross(m_rB, P); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2DistanceJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - b2Rot qA(aA), qB(aB); - - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 u = cB + rB - cA - rA; - - float length = u.Normalize(); - float C; - if (m_minLength == m_maxLength) - { - C = length - m_minLength; - } - else if (length < m_minLength) - { - C = length - m_minLength; - } - else if (m_maxLength < length) - { - C = length - m_maxLength; - } - else - { - return true; - } - - float impulse = -m_mass * C; - b2Vec2 P = impulse * u; - - cA -= m_invMassA * P; - aA -= m_invIA * b2Cross(rA, P); - cB += m_invMassB * P; - aB += m_invIB * b2Cross(rB, P); - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return b2Abs(C) < b2_linearSlop; -} - -b2Vec2 b2DistanceJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2DistanceJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2DistanceJoint::GetReactionForce(float inv_dt) const -{ - b2Vec2 F = inv_dt * (m_impulse + m_lowerImpulse - m_upperImpulse) * m_u; - return F; -} - -float b2DistanceJoint::GetReactionTorque(float inv_dt) const -{ - B2_NOT_USED(inv_dt); - return 0.0f; -} - -float b2DistanceJoint::SetLength(float length) -{ - m_impulse = 0.0f; - m_length = b2Max(b2_linearSlop, length); - return m_length; -} - -float b2DistanceJoint::SetMinLength(float minLength) -{ - m_lowerImpulse = 0.0f; - m_minLength = b2Clamp(minLength, b2_linearSlop, m_maxLength); - return m_minLength; -} - -float b2DistanceJoint::SetMaxLength(float maxLength) -{ - m_upperImpulse = 0.0f; - m_maxLength = b2Max(maxLength, m_minLength); - return m_maxLength; -} - -float b2DistanceJoint::GetCurrentLength() const -{ - b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA); - b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB); - b2Vec2 d = pB - pA; - float length = d.Length(); - return length; -} - -void b2DistanceJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2DistanceJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.length = %.9g;\n", m_length); - b2Dump(" jd.minLength = %.9g;\n", m_minLength); - b2Dump(" jd.maxLength = %.9g;\n", m_maxLength); - b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); - b2Dump(" jd.damping = %.9g;\n", m_damping); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} - -void b2DistanceJoint::Draw(b2Draw* draw) const -{ - const b2Transform& xfA = m_bodyA->GetTransform(); - const b2Transform& xfB = m_bodyB->GetTransform(); - b2Vec2 pA = b2Mul(xfA, m_localAnchorA); - b2Vec2 pB = b2Mul(xfB, m_localAnchorB); - - b2Vec2 axis = pB - pA; - axis.Normalize(); - - b2Color c1(0.7f, 0.7f, 0.7f); - b2Color c2(0.3f, 0.9f, 0.3f); - b2Color c3(0.9f, 0.3f, 0.3f); - b2Color c4(0.4f, 0.4f, 0.4f); - - draw->DrawSegment(pA, pB, c4); - - b2Vec2 pRest = pA + m_length * axis; - draw->DrawPoint(pRest, 8.0f, c1); - - if (m_minLength != m_maxLength) - { - if (m_minLength > b2_linearSlop) - { - b2Vec2 pMin = pA + m_minLength * axis; - draw->DrawPoint(pMin, 4.0f, c2); - } - - if (m_maxLength < FLT_MAX) - { - b2Vec2 pMax = pA + m_maxLength * axis; - draw->DrawPoint(pMax, 4.0f, c3); - } - } -} diff --git a/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.cpp b/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.cpp deleted file mode 100644 index 8a126de6c630..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_edge_circle_contact.h" - -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_fixture.h" - -#include - -b2Contact* b2EdgeAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2EdgeAndCircleContact)); - return new (mem) b2EdgeAndCircleContact(fixtureA, fixtureB); -} - -void b2EdgeAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2EdgeAndCircleContact*)contact)->~b2EdgeAndCircleContact(); - allocator->Free(contact, sizeof(b2EdgeAndCircleContact)); -} - -b2EdgeAndCircleContact::b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) -: b2Contact(fixtureA, 0, fixtureB, 0) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_edge); - b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); -} - -void b2EdgeAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2CollideEdgeAndCircle( manifold, - (b2EdgeShape*)m_fixtureA->GetShape(), xfA, - (b2CircleShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.h b/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.h deleted file mode 100644 index 3efc88e60712..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_edge_circle_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_EDGE_AND_CIRCLE_CONTACT_H -#define B2_EDGE_AND_CIRCLE_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2EdgeAndCircleContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2EdgeAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); - ~b2EdgeAndCircleContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.cpp b/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.cpp deleted file mode 100644 index e617e3516bbc..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_edge_polygon_contact.h" - -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_fixture.h" - -#include - -b2Contact* b2EdgeAndPolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2EdgeAndPolygonContact)); - return new (mem) b2EdgeAndPolygonContact(fixtureA, fixtureB); -} - -void b2EdgeAndPolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2EdgeAndPolygonContact*)contact)->~b2EdgeAndPolygonContact(); - allocator->Free(contact, sizeof(b2EdgeAndPolygonContact)); -} - -b2EdgeAndPolygonContact::b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB) -: b2Contact(fixtureA, 0, fixtureB, 0) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_edge); - b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); -} - -void b2EdgeAndPolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2CollideEdgeAndPolygon( manifold, - (b2EdgeShape*)m_fixtureA->GetShape(), xfA, - (b2PolygonShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.h b/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.h deleted file mode 100644 index e6616b534ebb..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_edge_polygon_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_EDGE_AND_POLYGON_CONTACT_H -#define B2_EDGE_AND_POLYGON_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2EdgeAndPolygonContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2EdgeAndPolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB); - ~b2EdgeAndPolygonContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_fixture.cpp b/3rdparty/box2d/src/dynamics/b2_fixture.cpp deleted file mode 100644 index 9fd700aa9a2a..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_fixture.cpp +++ /dev/null @@ -1,305 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_fixture.h" -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_broad_phase.h" -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_collision.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_edge_shape.h" -#include "box2d/b2_polygon_shape.h" -#include "box2d/b2_world.h" - -b2Fixture::b2Fixture() -{ - m_body = nullptr; - m_next = nullptr; - m_proxies = nullptr; - m_proxyCount = 0; - m_shape = nullptr; - m_density = 0.0f; -} - -void b2Fixture::Create(b2BlockAllocator* allocator, b2Body* body, const b2FixtureDef* def) -{ - m_userData = def->userData; - m_friction = def->friction; - m_restitution = def->restitution; - m_restitutionThreshold = def->restitutionThreshold; - - m_body = body; - m_next = nullptr; - - m_filter = def->filter; - - m_isSensor = def->isSensor; - - m_shape = def->shape->Clone(allocator); - - // Reserve proxy space - int32 childCount = m_shape->GetChildCount(); - m_proxies = (b2FixtureProxy*)allocator->Allocate(childCount * sizeof(b2FixtureProxy)); - for (int32 i = 0; i < childCount; ++i) - { - m_proxies[i].fixture = nullptr; - m_proxies[i].proxyId = b2BroadPhase::e_nullProxy; - } - m_proxyCount = 0; - - m_density = def->density; -} - -void b2Fixture::Destroy(b2BlockAllocator* allocator) -{ - // The proxies must be destroyed before calling this. - b2Assert(m_proxyCount == 0); - - // Free the proxy array. - int32 childCount = m_shape->GetChildCount(); - allocator->Free(m_proxies, childCount * sizeof(b2FixtureProxy)); - m_proxies = nullptr; - - // Free the child shape. - switch (m_shape->m_type) - { - case b2Shape::e_circle: - { - b2CircleShape* s = (b2CircleShape*)m_shape; - s->~b2CircleShape(); - allocator->Free(s, sizeof(b2CircleShape)); - } - break; - - case b2Shape::e_edge: - { - b2EdgeShape* s = (b2EdgeShape*)m_shape; - s->~b2EdgeShape(); - allocator->Free(s, sizeof(b2EdgeShape)); - } - break; - - case b2Shape::e_polygon: - { - b2PolygonShape* s = (b2PolygonShape*)m_shape; - s->~b2PolygonShape(); - allocator->Free(s, sizeof(b2PolygonShape)); - } - break; - - case b2Shape::e_chain: - { - b2ChainShape* s = (b2ChainShape*)m_shape; - s->~b2ChainShape(); - allocator->Free(s, sizeof(b2ChainShape)); - } - break; - - default: - b2Assert(false); - break; - } - - m_shape = nullptr; -} - -void b2Fixture::CreateProxies(b2BroadPhase* broadPhase, const b2Transform& xf) -{ - b2Assert(m_proxyCount == 0); - - // Create proxies in the broad-phase. - m_proxyCount = m_shape->GetChildCount(); - - for (int32 i = 0; i < m_proxyCount; ++i) - { - b2FixtureProxy* proxy = m_proxies + i; - m_shape->ComputeAABB(&proxy->aabb, xf, i); - proxy->proxyId = broadPhase->CreateProxy(proxy->aabb, proxy); - proxy->fixture = this; - proxy->childIndex = i; - } -} - -void b2Fixture::DestroyProxies(b2BroadPhase* broadPhase) -{ - // Destroy proxies in the broad-phase. - for (int32 i = 0; i < m_proxyCount; ++i) - { - b2FixtureProxy* proxy = m_proxies + i; - broadPhase->DestroyProxy(proxy->proxyId); - proxy->proxyId = b2BroadPhase::e_nullProxy; - } - - m_proxyCount = 0; -} - -void b2Fixture::Synchronize(b2BroadPhase* broadPhase, const b2Transform& transform1, const b2Transform& transform2) -{ - if (m_proxyCount == 0) - { - return; - } - - for (int32 i = 0; i < m_proxyCount; ++i) - { - b2FixtureProxy* proxy = m_proxies + i; - - // Compute an AABB that covers the swept shape (may miss some rotation effect). - b2AABB aabb1, aabb2; - m_shape->ComputeAABB(&aabb1, transform1, proxy->childIndex); - m_shape->ComputeAABB(&aabb2, transform2, proxy->childIndex); - - proxy->aabb.Combine(aabb1, aabb2); - - b2Vec2 displacement = aabb2.GetCenter() - aabb1.GetCenter(); - - broadPhase->MoveProxy(proxy->proxyId, proxy->aabb, displacement); - } -} - -void b2Fixture::SetFilterData(const b2Filter& filter) -{ - m_filter = filter; - - Refilter(); -} - -void b2Fixture::Refilter() -{ - if (m_body == nullptr) - { - return; - } - - // Flag associated contacts for filtering. - b2ContactEdge* edge = m_body->GetContactList(); - while (edge) - { - b2Contact* contact = edge->contact; - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - if (fixtureA == this || fixtureB == this) - { - contact->FlagForFiltering(); - } - - edge = edge->next; - } - - b2World* world = m_body->GetWorld(); - - if (world == nullptr) - { - return; - } - - // Touch each proxy so that new pairs may be created - b2BroadPhase* broadPhase = &world->m_contactManager.m_broadPhase; - for (int32 i = 0; i < m_proxyCount; ++i) - { - broadPhase->TouchProxy(m_proxies[i].proxyId); - } -} - -void b2Fixture::SetSensor(bool sensor) -{ - if (sensor != m_isSensor) - { - m_body->SetAwake(true); - m_isSensor = sensor; - } -} - -void b2Fixture::Dump(int32 bodyIndex) -{ - b2Dump(" b2FixtureDef fd;\n"); - b2Dump(" fd.friction = %.9g;\n", m_friction); - b2Dump(" fd.restitution = %.9g;\n", m_restitution); - b2Dump(" fd.restitutionThreshold = %.9g;\n", m_restitutionThreshold); - b2Dump(" fd.density = %.9g;\n", m_density); - b2Dump(" fd.isSensor = bool(%d);\n", m_isSensor); - b2Dump(" fd.filter.categoryBits = uint16(%d);\n", m_filter.categoryBits); - b2Dump(" fd.filter.maskBits = uint16(%d);\n", m_filter.maskBits); - b2Dump(" fd.filter.groupIndex = int16(%d);\n", m_filter.groupIndex); - - switch (m_shape->m_type) - { - case b2Shape::e_circle: - { - b2CircleShape* s = (b2CircleShape*)m_shape; - b2Dump(" b2CircleShape shape;\n"); - b2Dump(" shape.m_radius = %.9g;\n", s->m_radius); - b2Dump(" shape.m_p.Set(%.9g, %.9g);\n", s->m_p.x, s->m_p.y); - } - break; - - case b2Shape::e_edge: - { - b2EdgeShape* s = (b2EdgeShape*)m_shape; - b2Dump(" b2EdgeShape shape;\n"); - b2Dump(" shape.m_radius = %.9g;\n", s->m_radius); - b2Dump(" shape.m_vertex0.Set(%.9g, %.9g);\n", s->m_vertex0.x, s->m_vertex0.y); - b2Dump(" shape.m_vertex1.Set(%.9g, %.9g);\n", s->m_vertex1.x, s->m_vertex1.y); - b2Dump(" shape.m_vertex2.Set(%.9g, %.9g);\n", s->m_vertex2.x, s->m_vertex2.y); - b2Dump(" shape.m_vertex3.Set(%.9g, %.9g);\n", s->m_vertex3.x, s->m_vertex3.y); - b2Dump(" shape.m_oneSided = bool(%d);\n", s->m_oneSided); - } - break; - - case b2Shape::e_polygon: - { - b2PolygonShape* s = (b2PolygonShape*)m_shape; - b2Dump(" b2PolygonShape shape;\n"); - b2Dump(" b2Vec2 vs[%d];\n", b2_maxPolygonVertices); - for (int32 i = 0; i < s->m_count; ++i) - { - b2Dump(" vs[%d].Set(%.9g, %.9g);\n", i, s->m_vertices[i].x, s->m_vertices[i].y); - } - b2Dump(" shape.Set(vs, %d);\n", s->m_count); - } - break; - - case b2Shape::e_chain: - { - b2ChainShape* s = (b2ChainShape*)m_shape; - b2Dump(" b2ChainShape shape;\n"); - b2Dump(" b2Vec2 vs[%d];\n", s->m_count); - for (int32 i = 0; i < s->m_count; ++i) - { - b2Dump(" vs[%d].Set(%.9g, %.9g);\n", i, s->m_vertices[i].x, s->m_vertices[i].y); - } - b2Dump(" shape.CreateChain(vs, %d);\n", s->m_count); - b2Dump(" shape.m_prevVertex.Set(%.9g, %.9g);\n", s->m_prevVertex.x, s->m_prevVertex.y); - b2Dump(" shape.m_nextVertex.Set(%.9g, %.9g);\n", s->m_nextVertex.x, s->m_nextVertex.y); - } - break; - - default: - return; - } - - b2Dump("\n"); - b2Dump(" fd.shape = &shape;\n"); - b2Dump("\n"); - b2Dump(" bodies[%d]->CreateFixture(&fd);\n", bodyIndex); -} diff --git a/3rdparty/box2d/src/dynamics/b2_friction_joint.cpp b/3rdparty/box2d/src/dynamics/b2_friction_joint.cpp deleted file mode 100644 index d9d893ad3e09..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_friction_joint.cpp +++ /dev/null @@ -1,255 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_friction_joint.h" -#include "box2d/b2_body.h" -#include "box2d/b2_time_step.h" - -// Point-to-point constraint -// Cdot = v2 - v1 -// = v2 + cross(w2, r2) - v1 - cross(w1, r1) -// J = [-I -r1_skew I r2_skew ] -// Identity used: -// w k % (rx i + ry j) = w * (-ry i + rx j) - -// Angle constraint -// Cdot = w2 - w1 -// J = [0 0 -1 0 0 1] -// K = invI1 + invI2 - -void b2FrictionJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) -{ - bodyA = bA; - bodyB = bB; - localAnchorA = bodyA->GetLocalPoint(anchor); - localAnchorB = bodyB->GetLocalPoint(anchor); -} - -b2FrictionJoint::b2FrictionJoint(const b2FrictionJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - - m_linearImpulse.SetZero(); - m_angularImpulse = 0.0f; - - m_maxForce = def->maxForce; - m_maxTorque = def->maxTorque; -} - -void b2FrictionJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - // Compute the effective mass matrix. - m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // J = [-I -r1_skew I r2_skew] - // [ 0 -1 0 1] - // r_skew = [-ry; rx] - - // Matlab - // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] - // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] - // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Mat22 K; - K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y; - K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y; - K.ey.x = K.ex.y; - K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x; - - m_linearMass = K.GetInverse(); - - m_angularMass = iA + iB; - if (m_angularMass > 0.0f) - { - m_angularMass = 1.0f / m_angularMass; - } - - if (data.step.warmStarting) - { - // Scale impulses to support a variable time step. - m_linearImpulse *= data.step.dtRatio; - m_angularImpulse *= data.step.dtRatio; - - b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y); - vA -= mA * P; - wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse); - vB += mB * P; - wB += iB * (b2Cross(m_rB, P) + m_angularImpulse); - } - else - { - m_linearImpulse.SetZero(); - m_angularImpulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2FrictionJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - float h = data.step.dt; - - // Solve angular friction - { - float Cdot = wB - wA; - float impulse = -m_angularMass * Cdot; - - float oldImpulse = m_angularImpulse; - float maxImpulse = h * m_maxTorque; - m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse); - impulse = m_angularImpulse - oldImpulse; - - wA -= iA * impulse; - wB += iB * impulse; - } - - // Solve linear friction - { - b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); - - b2Vec2 impulse = -b2Mul(m_linearMass, Cdot); - b2Vec2 oldImpulse = m_linearImpulse; - m_linearImpulse += impulse; - - float maxImpulse = h * m_maxForce; - - if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) - { - m_linearImpulse.Normalize(); - m_linearImpulse *= maxImpulse; - } - - impulse = m_linearImpulse - oldImpulse; - - vA -= mA * impulse; - wA -= iA * b2Cross(m_rA, impulse); - - vB += mB * impulse; - wB += iB * b2Cross(m_rB, impulse); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2FrictionJoint::SolvePositionConstraints(const b2SolverData& data) -{ - B2_NOT_USED(data); - - return true; -} - -b2Vec2 b2FrictionJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2FrictionJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2FrictionJoint::GetReactionForce(float inv_dt) const -{ - return inv_dt * m_linearImpulse; -} - -float b2FrictionJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * m_angularImpulse; -} - -void b2FrictionJoint::SetMaxForce(float force) -{ - b2Assert(b2IsValid(force) && force >= 0.0f); - m_maxForce = force; -} - -float b2FrictionJoint::GetMaxForce() const -{ - return m_maxForce; -} - -void b2FrictionJoint::SetMaxTorque(float torque) -{ - b2Assert(b2IsValid(torque) && torque >= 0.0f); - m_maxTorque = torque; -} - -float b2FrictionJoint::GetMaxTorque() const -{ - return m_maxTorque; -} - -void b2FrictionJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2FrictionJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.maxForce = %.9g;\n", m_maxForce); - b2Dump(" jd.maxTorque = %.9g;\n", m_maxTorque); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} diff --git a/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp b/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp deleted file mode 100644 index 5fb547245e93..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_gear_joint.cpp +++ /dev/null @@ -1,437 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_gear_joint.h" -#include "box2d/b2_revolute_joint.h" -#include "box2d/b2_prismatic_joint.h" -#include "box2d/b2_body.h" -#include "box2d/b2_time_step.h" - -// Gear Joint: -// C0 = (coordinate1 + ratio * coordinate2)_initial -// C = (coordinate1 + ratio * coordinate2) - C0 = 0 -// J = [J1 ratio * J2] -// K = J * invM * JT -// = J1 * invM1 * J1T + ratio * ratio * J2 * invM2 * J2T -// -// Revolute: -// coordinate = rotation -// Cdot = angularVelocity -// J = [0 0 1] -// K = J * invM * JT = invI -// -// Prismatic: -// coordinate = dot(p - pg, ug) -// Cdot = dot(v + cross(w, r), ug) -// J = [ug cross(r, ug)] -// K = J * invM * JT = invMass + invI * cross(r, ug)^2 - -b2GearJoint::b2GearJoint(const b2GearJointDef* def) -: b2Joint(def) -{ - m_joint1 = def->joint1; - m_joint2 = def->joint2; - - m_typeA = m_joint1->GetType(); - m_typeB = m_joint2->GetType(); - - b2Assert(m_typeA == e_revoluteJoint || m_typeA == e_prismaticJoint); - b2Assert(m_typeB == e_revoluteJoint || m_typeB == e_prismaticJoint); - - float coordinateA, coordinateB; - - // TODO_ERIN there might be some problem with the joint edges in b2Joint. - - m_bodyC = m_joint1->GetBodyA(); - m_bodyA = m_joint1->GetBodyB(); - - // Body B on joint1 must be dynamic - b2Assert(m_bodyA->m_type == b2_dynamicBody); - - // Get geometry of joint1 - b2Transform xfA = m_bodyA->m_xf; - float aA = m_bodyA->m_sweep.a; - b2Transform xfC = m_bodyC->m_xf; - float aC = m_bodyC->m_sweep.a; - - if (m_typeA == e_revoluteJoint) - { - b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint1; - m_localAnchorC = revolute->m_localAnchorA; - m_localAnchorA = revolute->m_localAnchorB; - m_referenceAngleA = revolute->m_referenceAngle; - m_localAxisC.SetZero(); - - coordinateA = aA - aC - m_referenceAngleA; - - // position error is measured in radians - m_tolerance = b2_angularSlop; - } - else - { - b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint1; - m_localAnchorC = prismatic->m_localAnchorA; - m_localAnchorA = prismatic->m_localAnchorB; - m_referenceAngleA = prismatic->m_referenceAngle; - m_localAxisC = prismatic->m_localXAxisA; - - b2Vec2 pC = m_localAnchorC; - b2Vec2 pA = b2MulT(xfC.q, b2Mul(xfA.q, m_localAnchorA) + (xfA.p - xfC.p)); - coordinateA = b2Dot(pA - pC, m_localAxisC); - - // position error is measured in meters - m_tolerance = b2_linearSlop; - } - - m_bodyD = m_joint2->GetBodyA(); - m_bodyB = m_joint2->GetBodyB(); - - // Body B on joint2 must be dynamic - b2Assert(m_bodyB->m_type == b2_dynamicBody); - - // Get geometry of joint2 - b2Transform xfB = m_bodyB->m_xf; - float aB = m_bodyB->m_sweep.a; - b2Transform xfD = m_bodyD->m_xf; - float aD = m_bodyD->m_sweep.a; - - if (m_typeB == e_revoluteJoint) - { - b2RevoluteJoint* revolute = (b2RevoluteJoint*)def->joint2; - m_localAnchorD = revolute->m_localAnchorA; - m_localAnchorB = revolute->m_localAnchorB; - m_referenceAngleB = revolute->m_referenceAngle; - m_localAxisD.SetZero(); - - coordinateB = aB - aD - m_referenceAngleB; - } - else - { - b2PrismaticJoint* prismatic = (b2PrismaticJoint*)def->joint2; - m_localAnchorD = prismatic->m_localAnchorA; - m_localAnchorB = prismatic->m_localAnchorB; - m_referenceAngleB = prismatic->m_referenceAngle; - m_localAxisD = prismatic->m_localXAxisA; - - b2Vec2 pD = m_localAnchorD; - b2Vec2 pB = b2MulT(xfD.q, b2Mul(xfB.q, m_localAnchorB) + (xfB.p - xfD.p)); - coordinateB = b2Dot(pB - pD, m_localAxisD); - } - - m_ratio = def->ratio; - - m_constant = coordinateA + m_ratio * coordinateB; - - m_impulse = 0.0f; -} - -void b2GearJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_indexC = m_bodyC->m_islandIndex; - m_indexD = m_bodyD->m_islandIndex; - m_lcA = m_bodyA->m_sweep.localCenter; - m_lcB = m_bodyB->m_sweep.localCenter; - m_lcC = m_bodyC->m_sweep.localCenter; - m_lcD = m_bodyD->m_sweep.localCenter; - m_mA = m_bodyA->m_invMass; - m_mB = m_bodyB->m_invMass; - m_mC = m_bodyC->m_invMass; - m_mD = m_bodyD->m_invMass; - m_iA = m_bodyA->m_invI; - m_iB = m_bodyB->m_invI; - m_iC = m_bodyC->m_invI; - m_iD = m_bodyD->m_invI; - - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float aC = data.positions[m_indexC].a; - b2Vec2 vC = data.velocities[m_indexC].v; - float wC = data.velocities[m_indexC].w; - - float aD = data.positions[m_indexD].a; - b2Vec2 vD = data.velocities[m_indexD].v; - float wD = data.velocities[m_indexD].w; - - b2Rot qA(aA), qB(aB), qC(aC), qD(aD); - - m_mass = 0.0f; - - if (m_typeA == e_revoluteJoint) - { - m_JvAC.SetZero(); - m_JwA = 1.0f; - m_JwC = 1.0f; - m_mass += m_iA + m_iC; - } - else - { - b2Vec2 u = b2Mul(qC, m_localAxisC); - b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC); - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA); - m_JvAC = u; - m_JwC = b2Cross(rC, u); - m_JwA = b2Cross(rA, u); - m_mass += m_mC + m_mA + m_iC * m_JwC * m_JwC + m_iA * m_JwA * m_JwA; - } - - if (m_typeB == e_revoluteJoint) - { - m_JvBD.SetZero(); - m_JwB = m_ratio; - m_JwD = m_ratio; - m_mass += m_ratio * m_ratio * (m_iB + m_iD); - } - else - { - b2Vec2 u = b2Mul(qD, m_localAxisD); - b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB); - m_JvBD = m_ratio * u; - m_JwD = m_ratio * b2Cross(rD, u); - m_JwB = m_ratio * b2Cross(rB, u); - m_mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * m_JwD * m_JwD + m_iB * m_JwB * m_JwB; - } - - // Compute effective mass. - m_mass = m_mass > 0.0f ? 1.0f / m_mass : 0.0f; - - if (data.step.warmStarting) - { - vA += (m_mA * m_impulse) * m_JvAC; - wA += m_iA * m_impulse * m_JwA; - vB += (m_mB * m_impulse) * m_JvBD; - wB += m_iB * m_impulse * m_JwB; - vC -= (m_mC * m_impulse) * m_JvAC; - wC -= m_iC * m_impulse * m_JwC; - vD -= (m_mD * m_impulse) * m_JvBD; - wD -= m_iD * m_impulse * m_JwD; - } - else - { - m_impulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; - data.velocities[m_indexC].v = vC; - data.velocities[m_indexC].w = wC; - data.velocities[m_indexD].v = vD; - data.velocities[m_indexD].w = wD; -} - -void b2GearJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - b2Vec2 vC = data.velocities[m_indexC].v; - float wC = data.velocities[m_indexC].w; - b2Vec2 vD = data.velocities[m_indexD].v; - float wD = data.velocities[m_indexD].w; - - float Cdot = b2Dot(m_JvAC, vA - vC) + b2Dot(m_JvBD, vB - vD); - Cdot += (m_JwA * wA - m_JwC * wC) + (m_JwB * wB - m_JwD * wD); - - float impulse = -m_mass * Cdot; - m_impulse += impulse; - - vA += (m_mA * impulse) * m_JvAC; - wA += m_iA * impulse * m_JwA; - vB += (m_mB * impulse) * m_JvBD; - wB += m_iB * impulse * m_JwB; - vC -= (m_mC * impulse) * m_JvAC; - wC -= m_iC * impulse * m_JwC; - vD -= (m_mD * impulse) * m_JvBD; - wD -= m_iD * impulse * m_JwD; - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; - data.velocities[m_indexC].v = vC; - data.velocities[m_indexC].w = wC; - data.velocities[m_indexD].v = vD; - data.velocities[m_indexD].w = wD; -} - -bool b2GearJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 cC = data.positions[m_indexC].c; - float aC = data.positions[m_indexC].a; - b2Vec2 cD = data.positions[m_indexD].c; - float aD = data.positions[m_indexD].a; - - b2Rot qA(aA), qB(aB), qC(aC), qD(aD); - - float coordinateA, coordinateB; - - b2Vec2 JvAC, JvBD; - float JwA, JwB, JwC, JwD; - float mass = 0.0f; - - if (m_typeA == e_revoluteJoint) - { - JvAC.SetZero(); - JwA = 1.0f; - JwC = 1.0f; - mass += m_iA + m_iC; - - coordinateA = aA - aC - m_referenceAngleA; - } - else - { - b2Vec2 u = b2Mul(qC, m_localAxisC); - b2Vec2 rC = b2Mul(qC, m_localAnchorC - m_lcC); - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_lcA); - JvAC = u; - JwC = b2Cross(rC, u); - JwA = b2Cross(rA, u); - mass += m_mC + m_mA + m_iC * JwC * JwC + m_iA * JwA * JwA; - - b2Vec2 pC = m_localAnchorC - m_lcC; - b2Vec2 pA = b2MulT(qC, rA + (cA - cC)); - coordinateA = b2Dot(pA - pC, m_localAxisC); - } - - if (m_typeB == e_revoluteJoint) - { - JvBD.SetZero(); - JwB = m_ratio; - JwD = m_ratio; - mass += m_ratio * m_ratio * (m_iB + m_iD); - - coordinateB = aB - aD - m_referenceAngleB; - } - else - { - b2Vec2 u = b2Mul(qD, m_localAxisD); - b2Vec2 rD = b2Mul(qD, m_localAnchorD - m_lcD); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_lcB); - JvBD = m_ratio * u; - JwD = m_ratio * b2Cross(rD, u); - JwB = m_ratio * b2Cross(rB, u); - mass += m_ratio * m_ratio * (m_mD + m_mB) + m_iD * JwD * JwD + m_iB * JwB * JwB; - - b2Vec2 pD = m_localAnchorD - m_lcD; - b2Vec2 pB = b2MulT(qD, rB + (cB - cD)); - coordinateB = b2Dot(pB - pD, m_localAxisD); - } - - float C = (coordinateA + m_ratio * coordinateB) - m_constant; - - float impulse = 0.0f; - if (mass > 0.0f) - { - impulse = -C / mass; - } - - cA += m_mA * impulse * JvAC; - aA += m_iA * impulse * JwA; - cB += m_mB * impulse * JvBD; - aB += m_iB * impulse * JwB; - cC -= m_mC * impulse * JvAC; - aC -= m_iC * impulse * JwC; - cD -= m_mD * impulse * JvBD; - aD -= m_iD * impulse * JwD; - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - data.positions[m_indexC].c = cC; - data.positions[m_indexC].a = aC; - data.positions[m_indexD].c = cD; - data.positions[m_indexD].a = aD; - - if (b2Abs(C) < m_tolerance) - { - return true; - } - - return false; -} - -b2Vec2 b2GearJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2GearJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2GearJoint::GetReactionForce(float inv_dt) const -{ - b2Vec2 P = m_impulse * m_JvAC; - return inv_dt * P; -} - -float b2GearJoint::GetReactionTorque(float inv_dt) const -{ - float L = m_impulse * m_JwA; - return inv_dt * L; -} - -void b2GearJoint::SetRatio(float ratio) -{ - b2Assert(b2IsValid(ratio)); - m_ratio = ratio; -} - -float b2GearJoint::GetRatio() const -{ - return m_ratio; -} - -void b2GearJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - int32 index1 = m_joint1->m_index; - int32 index2 = m_joint2->m_index; - - b2Dump(" b2GearJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.joint1 = joints[%d];\n", index1); - b2Dump(" jd.joint2 = joints[%d];\n", index2); - b2Dump(" jd.ratio = %.9g;\n", m_ratio); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} diff --git a/3rdparty/box2d/src/dynamics/b2_island.cpp b/3rdparty/box2d/src/dynamics/b2_island.cpp deleted file mode 100644 index 34413056b1f4..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_island.cpp +++ /dev/null @@ -1,544 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_distance.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_joint.h" -#include "box2d/b2_stack_allocator.h" -#include "box2d/b2_timer.h" -#include "box2d/b2_world.h" - -#include "b2_contact_solver.h" -#include "b2_island.h" - -/* -Position Correction Notes -========================= -I tried the several algorithms for position correction of the 2D revolute joint. -I looked at these systems: -- simple pendulum (1m diameter sphere on massless 5m stick) with initial angular velocity of 100 rad/s. -- suspension bridge with 30 1m long planks of length 1m. -- multi-link chain with 30 1m long links. - -Here are the algorithms: - -Baumgarte - A fraction of the position error is added to the velocity error. There is no -separate position solver. - -Pseudo Velocities - After the velocity solver and position integration, -the position error, Jacobian, and effective mass are recomputed. Then -the velocity constraints are solved with pseudo velocities and a fraction -of the position error is added to the pseudo velocity error. The pseudo -velocities are initialized to zero and there is no warm-starting. After -the position solver, the pseudo velocities are added to the positions. -This is also called the First Order World method or the Position LCP method. - -Modified Nonlinear Gauss-Seidel (NGS) - Like Pseudo Velocities except the -position error is re-computed for each constraint and the positions are updated -after the constraint is solved. The radius vectors (aka Jacobians) are -re-computed too (otherwise the algorithm has horrible instability). The pseudo -velocity states are not needed because they are effectively zero at the beginning -of each iteration. Since we have the current position error, we allow the -iterations to terminate early if the error becomes smaller than b2_linearSlop. - -Full NGS or just NGS - Like Modified NGS except the effective mass are re-computed -each time a constraint is solved. - -Here are the results: -Baumgarte - this is the cheapest algorithm but it has some stability problems, -especially with the bridge. The chain links separate easily close to the root -and they jitter as they struggle to pull together. This is one of the most common -methods in the field. The big drawback is that the position correction artificially -affects the momentum, thus leading to instabilities and false bounce. I used a -bias factor of 0.2. A larger bias factor makes the bridge less stable, a smaller -factor makes joints and contacts more spongy. - -Pseudo Velocities - the is more stable than the Baumgarte method. The bridge is -stable. However, joints still separate with large angular velocities. Drag the -simple pendulum in a circle quickly and the joint will separate. The chain separates -easily and does not recover. I used a bias factor of 0.2. A larger value lead to -the bridge collapsing when a heavy cube drops on it. - -Modified NGS - this algorithm is better in some ways than Baumgarte and Pseudo -Velocities, but in other ways it is worse. The bridge and chain are much more -stable, but the simple pendulum goes unstable at high angular velocities. - -Full NGS - stable in all tests. The joints display good stiffness. The bridge -still sags, but this is better than infinite forces. - -Recommendations -Pseudo Velocities are not really worthwhile because the bridge and chain cannot -recover from joint separation. In other cases the benefit over Baumgarte is small. - -Modified NGS is not a robust method for the revolute joint due to the violent -instability seen in the simple pendulum. Perhaps it is viable with other constraint -types, especially scalar constraints where the effective mass is a scalar. - -This leaves Baumgarte and Full NGS. Baumgarte has small, but manageable instabilities -and is very fast. I don't think we can escape Baumgarte, especially in highly -demanding cases where high constraint fidelity is not needed. - -Full NGS is robust and easy on the eyes. I recommend this as an option for -higher fidelity simulation and certainly for suspension bridges and long chains. -Full NGS might be a good choice for ragdolls, especially motorized ragdolls where -joint separation can be problematic. The number of NGS iterations can be reduced -for better performance without harming robustness much. - -Each joint in a can be handled differently in the position solver. So I recommend -a system where the user can select the algorithm on a per joint basis. I would -probably default to the slower Full NGS and let the user select the faster -Baumgarte method in performance critical scenarios. -*/ - -/* -Cache Performance - -The Box2D solvers are dominated by cache misses. Data structures are designed -to increase the number of cache hits. Much of misses are due to random access -to body data. The constraint structures are iterated over linearly, which leads -to few cache misses. - -The bodies are not accessed during iteration. Instead read only data, such as -the mass values are stored with the constraints. The mutable data are the constraint -impulses and the bodies velocities/positions. The impulses are held inside the -constraint structures. The body velocities/positions are held in compact, temporary -arrays to increase the number of cache hits. Linear and angular velocity are -stored in a single array since multiple arrays lead to multiple misses. -*/ - -/* -2D Rotation - -R = [cos(theta) -sin(theta)] - [sin(theta) cos(theta) ] - -thetaDot = omega - -Let q1 = cos(theta), q2 = sin(theta). -R = [q1 -q2] - [q2 q1] - -q1Dot = -thetaDot * q2 -q2Dot = thetaDot * q1 - -q1_new = q1_old - dt * w * q2 -q2_new = q2_old + dt * w * q1 -then normalize. - -This might be faster than computing sin+cos. -However, we can compute sin+cos of the same angle fast. -*/ - -b2Island::b2Island( - int32 bodyCapacity, - int32 contactCapacity, - int32 jointCapacity, - b2StackAllocator* allocator, - b2ContactListener* listener) -{ - m_bodyCapacity = bodyCapacity; - m_contactCapacity = contactCapacity; - m_jointCapacity = jointCapacity; - m_bodyCount = 0; - m_contactCount = 0; - m_jointCount = 0; - - m_allocator = allocator; - m_listener = listener; - - m_bodies = (b2Body**)m_allocator->Allocate(bodyCapacity * sizeof(b2Body*)); - m_contacts = (b2Contact**)m_allocator->Allocate(contactCapacity * sizeof(b2Contact*)); - m_joints = (b2Joint**)m_allocator->Allocate(jointCapacity * sizeof(b2Joint*)); - - m_velocities = (b2Velocity*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Velocity)); - m_positions = (b2Position*)m_allocator->Allocate(m_bodyCapacity * sizeof(b2Position)); -} - -b2Island::~b2Island() -{ - // Warning: the order should reverse the constructor order. - m_allocator->Free(m_positions); - m_allocator->Free(m_velocities); - m_allocator->Free(m_joints); - m_allocator->Free(m_contacts); - m_allocator->Free(m_bodies); -} - -void b2Island::Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep) -{ - b2Timer timer; - - float h = step.dt; - - // Integrate velocities and apply damping. Initialize the body state. - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Body* b = m_bodies[i]; - - b2Vec2 c = b->m_sweep.c; - float a = b->m_sweep.a; - b2Vec2 v = b->m_linearVelocity; - float w = b->m_angularVelocity; - - // Store positions for continuous collision. - b->m_sweep.c0 = b->m_sweep.c; - b->m_sweep.a0 = b->m_sweep.a; - - if (b->m_type == b2_dynamicBody) - { - // Integrate velocities. - v += h * b->m_invMass * (b->m_gravityScale * b->m_mass * gravity + b->m_force); - w += h * b->m_invI * b->m_torque; - - // Apply damping. - // ODE: dv/dt + c * v = 0 - // Solution: v(t) = v0 * exp(-c * t) - // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v * exp(-c * dt) - // v2 = exp(-c * dt) * v1 - // Pade approximation: - // v2 = v1 * 1 / (1 + c * dt) - v *= 1.0f / (1.0f + h * b->m_linearDamping); - w *= 1.0f / (1.0f + h * b->m_angularDamping); - } - - m_positions[i].c = c; - m_positions[i].a = a; - m_velocities[i].v = v; - m_velocities[i].w = w; - } - - timer.Reset(); - - // Solver data - b2SolverData solverData; - solverData.step = step; - solverData.positions = m_positions; - solverData.velocities = m_velocities; - - // Initialize velocity constraints. - b2ContactSolverDef contactSolverDef; - contactSolverDef.step = step; - contactSolverDef.contacts = m_contacts; - contactSolverDef.count = m_contactCount; - contactSolverDef.positions = m_positions; - contactSolverDef.velocities = m_velocities; - contactSolverDef.allocator = m_allocator; - - b2ContactSolver contactSolver(&contactSolverDef); - contactSolver.InitializeVelocityConstraints(); - - if (step.warmStarting) - { - contactSolver.WarmStart(); - } - - for (int32 i = 0; i < m_jointCount; ++i) - { - m_joints[i]->InitVelocityConstraints(solverData); - } - - profile->solveInit = timer.GetMilliseconds(); - - // Solve velocity constraints - timer.Reset(); - for (int32 i = 0; i < step.velocityIterations; ++i) - { - for (int32 j = 0; j < m_jointCount; ++j) - { - m_joints[j]->SolveVelocityConstraints(solverData); - } - - contactSolver.SolveVelocityConstraints(); - } - - // Store impulses for warm starting - contactSolver.StoreImpulses(); - profile->solveVelocity = timer.GetMilliseconds(); - - // Integrate positions - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Vec2 c = m_positions[i].c; - float a = m_positions[i].a; - b2Vec2 v = m_velocities[i].v; - float w = m_velocities[i].w; - - // Check for large velocities - b2Vec2 translation = h * v; - if (b2Dot(translation, translation) > b2_maxTranslationSquared) - { - float ratio = b2_maxTranslation / translation.Length(); - v *= ratio; - } - - float rotation = h * w; - if (rotation * rotation > b2_maxRotationSquared) - { - float ratio = b2_maxRotation / b2Abs(rotation); - w *= ratio; - } - - // Integrate - c += h * v; - a += h * w; - - m_positions[i].c = c; - m_positions[i].a = a; - m_velocities[i].v = v; - m_velocities[i].w = w; - } - - // Solve position constraints - timer.Reset(); - bool positionSolved = false; - for (int32 i = 0; i < step.positionIterations; ++i) - { - bool contactsOkay = contactSolver.SolvePositionConstraints(); - - bool jointsOkay = true; - for (int32 j = 0; j < m_jointCount; ++j) - { - bool jointOkay = m_joints[j]->SolvePositionConstraints(solverData); - jointsOkay = jointsOkay && jointOkay; - } - - if (contactsOkay && jointsOkay) - { - // Exit early if the position errors are small. - positionSolved = true; - break; - } - } - - // Copy state buffers back to the bodies - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Body* body = m_bodies[i]; - body->m_sweep.c = m_positions[i].c; - body->m_sweep.a = m_positions[i].a; - body->m_linearVelocity = m_velocities[i].v; - body->m_angularVelocity = m_velocities[i].w; - body->SynchronizeTransform(); - } - - profile->solvePosition = timer.GetMilliseconds(); - - Report(contactSolver.m_velocityConstraints); - - if (allowSleep) - { - float minSleepTime = b2_maxFloat; - - const float linTolSqr = b2_linearSleepTolerance * b2_linearSleepTolerance; - const float angTolSqr = b2_angularSleepTolerance * b2_angularSleepTolerance; - - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Body* b = m_bodies[i]; - if (b->GetType() == b2_staticBody) - { - continue; - } - - if ((b->m_flags & b2Body::e_autoSleepFlag) == 0 || - b->m_angularVelocity * b->m_angularVelocity > angTolSqr || - b2Dot(b->m_linearVelocity, b->m_linearVelocity) > linTolSqr) - { - b->m_sleepTime = 0.0f; - minSleepTime = 0.0f; - } - else - { - b->m_sleepTime += h; - minSleepTime = b2Min(minSleepTime, b->m_sleepTime); - } - } - - if (minSleepTime >= b2_timeToSleep && positionSolved) - { - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Body* b = m_bodies[i]; - b->SetAwake(false); - } - } - } -} - -void b2Island::SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB) -{ - b2Assert(toiIndexA < m_bodyCount); - b2Assert(toiIndexB < m_bodyCount); - - // Initialize the body state. - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Body* b = m_bodies[i]; - m_positions[i].c = b->m_sweep.c; - m_positions[i].a = b->m_sweep.a; - m_velocities[i].v = b->m_linearVelocity; - m_velocities[i].w = b->m_angularVelocity; - } - - b2ContactSolverDef contactSolverDef; - contactSolverDef.contacts = m_contacts; - contactSolverDef.count = m_contactCount; - contactSolverDef.allocator = m_allocator; - contactSolverDef.step = subStep; - contactSolverDef.positions = m_positions; - contactSolverDef.velocities = m_velocities; - b2ContactSolver contactSolver(&contactSolverDef); - - // Solve position constraints. - for (int32 i = 0; i < subStep.positionIterations; ++i) - { - bool contactsOkay = contactSolver.SolveTOIPositionConstraints(toiIndexA, toiIndexB); - if (contactsOkay) - { - break; - } - } - -#if 0 - // Is the new position really safe? - for (int32 i = 0; i < m_contactCount; ++i) - { - b2Contact* c = m_contacts[i]; - b2Fixture* fA = c->GetFixtureA(); - b2Fixture* fB = c->GetFixtureB(); - - b2Body* bA = fA->GetBody(); - b2Body* bB = fB->GetBody(); - - int32 indexA = c->GetChildIndexA(); - int32 indexB = c->GetChildIndexB(); - - b2DistanceInput input; - input.proxyA.Set(fA->GetShape(), indexA); - input.proxyB.Set(fB->GetShape(), indexB); - input.transformA = bA->GetTransform(); - input.transformB = bB->GetTransform(); - input.useRadii = false; - - b2DistanceOutput output; - b2SimplexCache cache; - cache.count = 0; - b2Distance(&output, &cache, &input); - - if (output.distance == 0 || cache.count == 3) - { - cache.count += 0; - } - } -#endif - - // Leap of faith to new safe state. - m_bodies[toiIndexA]->m_sweep.c0 = m_positions[toiIndexA].c; - m_bodies[toiIndexA]->m_sweep.a0 = m_positions[toiIndexA].a; - m_bodies[toiIndexB]->m_sweep.c0 = m_positions[toiIndexB].c; - m_bodies[toiIndexB]->m_sweep.a0 = m_positions[toiIndexB].a; - - // No warm starting is needed for TOI events because warm - // starting impulses were applied in the discrete solver. - contactSolver.InitializeVelocityConstraints(); - - // Solve velocity constraints. - for (int32 i = 0; i < subStep.velocityIterations; ++i) - { - contactSolver.SolveVelocityConstraints(); - } - - // Don't store the TOI contact forces for warm starting - // because they can be quite large. - - float h = subStep.dt; - - // Integrate positions - for (int32 i = 0; i < m_bodyCount; ++i) - { - b2Vec2 c = m_positions[i].c; - float a = m_positions[i].a; - b2Vec2 v = m_velocities[i].v; - float w = m_velocities[i].w; - - // Check for large velocities - b2Vec2 translation = h * v; - if (b2Dot(translation, translation) > b2_maxTranslationSquared) - { - float ratio = b2_maxTranslation / translation.Length(); - v *= ratio; - } - - float rotation = h * w; - if (rotation * rotation > b2_maxRotationSquared) - { - float ratio = b2_maxRotation / b2Abs(rotation); - w *= ratio; - } - - // Integrate - c += h * v; - a += h * w; - - m_positions[i].c = c; - m_positions[i].a = a; - m_velocities[i].v = v; - m_velocities[i].w = w; - - // Sync bodies - b2Body* body = m_bodies[i]; - body->m_sweep.c = c; - body->m_sweep.a = a; - body->m_linearVelocity = v; - body->m_angularVelocity = w; - body->SynchronizeTransform(); - } - - Report(contactSolver.m_velocityConstraints); -} - -void b2Island::Report(const b2ContactVelocityConstraint* constraints) -{ - if (m_listener == nullptr) - { - return; - } - - for (int32 i = 0; i < m_contactCount; ++i) - { - b2Contact* c = m_contacts[i]; - - const b2ContactVelocityConstraint* vc = constraints + i; - - b2ContactImpulse impulse; - impulse.count = vc->pointCount; - for (int32 j = 0; j < vc->pointCount; ++j) - { - impulse.normalImpulses[j] = vc->points[j].normalImpulse; - impulse.tangentImpulses[j] = vc->points[j].tangentImpulse; - } - - m_listener->PostSolve(c, &impulse); - } -} diff --git a/3rdparty/box2d/src/dynamics/b2_island.h b/3rdparty/box2d/src/dynamics/b2_island.h deleted file mode 100644 index 2e28a357b047..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_island.h +++ /dev/null @@ -1,97 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_ISLAND_H -#define B2_ISLAND_H - -#include "box2d/b2_body.h" -#include "box2d/b2_math.h" -#include "box2d/b2_time_step.h" - -class b2Contact; -class b2Joint; -class b2StackAllocator; -class b2ContactListener; -struct b2ContactVelocityConstraint; -struct b2Profile; - -/// This is an internal class. -class b2Island -{ -public: - b2Island(int32 bodyCapacity, int32 contactCapacity, int32 jointCapacity, - b2StackAllocator* allocator, b2ContactListener* listener); - ~b2Island(); - - void Clear() - { - m_bodyCount = 0; - m_contactCount = 0; - m_jointCount = 0; - } - - void Solve(b2Profile* profile, const b2TimeStep& step, const b2Vec2& gravity, bool allowSleep); - - void SolveTOI(const b2TimeStep& subStep, int32 toiIndexA, int32 toiIndexB); - - void Add(b2Body* body) - { - b2Assert(m_bodyCount < m_bodyCapacity); - body->m_islandIndex = m_bodyCount; - m_bodies[m_bodyCount] = body; - ++m_bodyCount; - } - - void Add(b2Contact* contact) - { - b2Assert(m_contactCount < m_contactCapacity); - m_contacts[m_contactCount++] = contact; - } - - void Add(b2Joint* joint) - { - b2Assert(m_jointCount < m_jointCapacity); - m_joints[m_jointCount++] = joint; - } - - void Report(const b2ContactVelocityConstraint* constraints); - - b2StackAllocator* m_allocator; - b2ContactListener* m_listener; - - b2Body** m_bodies; - b2Contact** m_contacts; - b2Joint** m_joints; - - b2Position* m_positions; - b2Velocity* m_velocities; - - int32 m_bodyCount; - int32 m_jointCount; - int32 m_contactCount; - - int32 m_bodyCapacity; - int32 m_contactCapacity; - int32 m_jointCapacity; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_joint.cpp b/3rdparty/box2d/src/dynamics/b2_joint.cpp deleted file mode 100644 index 41addbbb2dda..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_joint.cpp +++ /dev/null @@ -1,301 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_body.h" -#include "box2d/b2_distance_joint.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_friction_joint.h" -#include "box2d/b2_gear_joint.h" -#include "box2d/b2_motor_joint.h" -#include "box2d/b2_mouse_joint.h" -#include "box2d/b2_prismatic_joint.h" -#include "box2d/b2_pulley_joint.h" -#include "box2d/b2_revolute_joint.h" -#include "box2d/b2_weld_joint.h" -#include "box2d/b2_wheel_joint.h" -#include "box2d/b2_world.h" - -#include - -void b2LinearStiffness(float& stiffness, float& damping, - float frequencyHertz, float dampingRatio, - const b2Body* bodyA, const b2Body* bodyB) -{ - float massA = bodyA->GetMass(); - float massB = bodyB->GetMass(); - float mass; - if (massA > 0.0f && massB > 0.0f) - { - mass = massA * massB / (massA + massB); - } - else if (massA > 0.0f) - { - mass = massA; - } - else - { - mass = massB; - } - - float omega = 2.0f * b2_pi * frequencyHertz; - stiffness = mass * omega * omega; - damping = 2.0f * mass * dampingRatio * omega; -} - -void b2AngularStiffness(float& stiffness, float& damping, - float frequencyHertz, float dampingRatio, - const b2Body* bodyA, const b2Body* bodyB) -{ - float IA = bodyA->GetInertia(); - float IB = bodyB->GetInertia(); - float I; - if (IA > 0.0f && IB > 0.0f) - { - I = IA * IB / (IA + IB); - } - else if (IA > 0.0f) - { - I = IA; - } - else - { - I = IB; - } - - float omega = 2.0f * b2_pi * frequencyHertz; - stiffness = I * omega * omega; - damping = 2.0f * I * dampingRatio * omega; -} - -b2Joint* b2Joint::Create(const b2JointDef* def, b2BlockAllocator* allocator) -{ - b2Joint* joint = nullptr; - - switch (def->type) - { - case e_distanceJoint: - { - void* mem = allocator->Allocate(sizeof(b2DistanceJoint)); - joint = new (mem) b2DistanceJoint(static_cast(def)); - } - break; - - case e_mouseJoint: - { - void* mem = allocator->Allocate(sizeof(b2MouseJoint)); - joint = new (mem) b2MouseJoint(static_cast(def)); - } - break; - - case e_prismaticJoint: - { - void* mem = allocator->Allocate(sizeof(b2PrismaticJoint)); - joint = new (mem) b2PrismaticJoint(static_cast(def)); - } - break; - - case e_revoluteJoint: - { - void* mem = allocator->Allocate(sizeof(b2RevoluteJoint)); - joint = new (mem) b2RevoluteJoint(static_cast(def)); - } - break; - - case e_pulleyJoint: - { - void* mem = allocator->Allocate(sizeof(b2PulleyJoint)); - joint = new (mem) b2PulleyJoint(static_cast(def)); - } - break; - - case e_gearJoint: - { - void* mem = allocator->Allocate(sizeof(b2GearJoint)); - joint = new (mem) b2GearJoint(static_cast(def)); - } - break; - - case e_wheelJoint: - { - void* mem = allocator->Allocate(sizeof(b2WheelJoint)); - joint = new (mem) b2WheelJoint(static_cast(def)); - } - break; - - case e_weldJoint: - { - void* mem = allocator->Allocate(sizeof(b2WeldJoint)); - joint = new (mem) b2WeldJoint(static_cast(def)); - } - break; - - case e_frictionJoint: - { - void* mem = allocator->Allocate(sizeof(b2FrictionJoint)); - joint = new (mem) b2FrictionJoint(static_cast(def)); - } - break; - - case e_motorJoint: - { - void* mem = allocator->Allocate(sizeof(b2MotorJoint)); - joint = new (mem) b2MotorJoint(static_cast(def)); - } - break; - - default: - b2Assert(false); - break; - } - - return joint; -} - -void b2Joint::Destroy(b2Joint* joint, b2BlockAllocator* allocator) -{ - joint->~b2Joint(); - switch (joint->m_type) - { - case e_distanceJoint: - allocator->Free(joint, sizeof(b2DistanceJoint)); - break; - - case e_mouseJoint: - allocator->Free(joint, sizeof(b2MouseJoint)); - break; - - case e_prismaticJoint: - allocator->Free(joint, sizeof(b2PrismaticJoint)); - break; - - case e_revoluteJoint: - allocator->Free(joint, sizeof(b2RevoluteJoint)); - break; - - case e_pulleyJoint: - allocator->Free(joint, sizeof(b2PulleyJoint)); - break; - - case e_gearJoint: - allocator->Free(joint, sizeof(b2GearJoint)); - break; - - case e_wheelJoint: - allocator->Free(joint, sizeof(b2WheelJoint)); - break; - - case e_weldJoint: - allocator->Free(joint, sizeof(b2WeldJoint)); - break; - - case e_frictionJoint: - allocator->Free(joint, sizeof(b2FrictionJoint)); - break; - - case e_motorJoint: - allocator->Free(joint, sizeof(b2MotorJoint)); - break; - - default: - b2Assert(false); - break; - } -} - -b2Joint::b2Joint(const b2JointDef* def) -{ - b2Assert(def->bodyA != def->bodyB); - - m_type = def->type; - m_prev = nullptr; - m_next = nullptr; - m_bodyA = def->bodyA; - m_bodyB = def->bodyB; - m_index = 0; - m_collideConnected = def->collideConnected; - m_islandFlag = false; - m_userData = def->userData; - - m_edgeA.joint = nullptr; - m_edgeA.other = nullptr; - m_edgeA.prev = nullptr; - m_edgeA.next = nullptr; - - m_edgeB.joint = nullptr; - m_edgeB.other = nullptr; - m_edgeB.prev = nullptr; - m_edgeB.next = nullptr; -} - -bool b2Joint::IsEnabled() const -{ - return m_bodyA->IsEnabled() && m_bodyB->IsEnabled(); -} - -void b2Joint::Draw(b2Draw* draw) const -{ - const b2Transform& xf1 = m_bodyA->GetTransform(); - const b2Transform& xf2 = m_bodyB->GetTransform(); - b2Vec2 x1 = xf1.p; - b2Vec2 x2 = xf2.p; - b2Vec2 p1 = GetAnchorA(); - b2Vec2 p2 = GetAnchorB(); - - b2Color color(0.5f, 0.8f, 0.8f); - - switch (m_type) - { - case e_distanceJoint: - draw->DrawSegment(p1, p2, color); - break; - - case e_pulleyJoint: - { - b2PulleyJoint* pulley = (b2PulleyJoint*)this; - b2Vec2 s1 = pulley->GetGroundAnchorA(); - b2Vec2 s2 = pulley->GetGroundAnchorB(); - draw->DrawSegment(s1, p1, color); - draw->DrawSegment(s2, p2, color); - draw->DrawSegment(s1, s2, color); - } - break; - - case e_mouseJoint: - { - b2Color c; - c.Set(0.0f, 1.0f, 0.0f); - draw->DrawPoint(p1, 4.0f, c); - draw->DrawPoint(p2, 4.0f, c); - - c.Set(0.8f, 0.8f, 0.8f); - draw->DrawSegment(p1, p2, c); - - } - break; - - default: - draw->DrawSegment(x1, p1, color); - draw->DrawSegment(p1, p2, color); - draw->DrawSegment(x2, p2, color); - } -} diff --git a/3rdparty/box2d/src/dynamics/b2_motor_joint.cpp b/3rdparty/box2d/src/dynamics/b2_motor_joint.cpp deleted file mode 100644 index 6e0b07538099..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_motor_joint.cpp +++ /dev/null @@ -1,311 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_motor_joint.h" -#include "box2d/b2_time_step.h" - -// Point-to-point constraint -// Cdot = v2 - v1 -// = v2 + cross(w2, r2) - v1 - cross(w1, r1) -// J = [-I -r1_skew I r2_skew ] -// Identity used: -// w k % (rx i + ry j) = w * (-ry i + rx j) -// -// r1 = offset - c1 -// r2 = -c2 - -// Angle constraint -// Cdot = w2 - w1 -// J = [0 0 -1 0 0 1] -// K = invI1 + invI2 - -void b2MotorJointDef::Initialize(b2Body* bA, b2Body* bB) -{ - bodyA = bA; - bodyB = bB; - b2Vec2 xB = bodyB->GetPosition(); - linearOffset = bodyA->GetLocalPoint(xB); - - float angleA = bodyA->GetAngle(); - float angleB = bodyB->GetAngle(); - angularOffset = angleB - angleA; -} - -b2MotorJoint::b2MotorJoint(const b2MotorJointDef* def) -: b2Joint(def) -{ - m_linearOffset = def->linearOffset; - m_angularOffset = def->angularOffset; - - m_linearImpulse.SetZero(); - m_angularImpulse = 0.0f; - - m_maxForce = def->maxForce; - m_maxTorque = def->maxTorque; - m_correctionFactor = def->correctionFactor; -} - -void b2MotorJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - // Compute the effective mass matrix. - m_rA = b2Mul(qA, m_linearOffset - m_localCenterA); - m_rB = b2Mul(qB, -m_localCenterB); - - // J = [-I -r1_skew I r2_skew] - // r_skew = [-ry; rx] - - // Matlab - // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] - // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] - // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - // Upper 2 by 2 of K for point to point - b2Mat22 K; - K.ex.x = mA + mB + iA * m_rA.y * m_rA.y + iB * m_rB.y * m_rB.y; - K.ex.y = -iA * m_rA.x * m_rA.y - iB * m_rB.x * m_rB.y; - K.ey.x = K.ex.y; - K.ey.y = mA + mB + iA * m_rA.x * m_rA.x + iB * m_rB.x * m_rB.x; - - m_linearMass = K.GetInverse(); - - m_angularMass = iA + iB; - if (m_angularMass > 0.0f) - { - m_angularMass = 1.0f / m_angularMass; - } - - m_linearError = cB + m_rB - cA - m_rA; - m_angularError = aB - aA - m_angularOffset; - - if (data.step.warmStarting) - { - // Scale impulses to support a variable time step. - m_linearImpulse *= data.step.dtRatio; - m_angularImpulse *= data.step.dtRatio; - - b2Vec2 P(m_linearImpulse.x, m_linearImpulse.y); - vA -= mA * P; - wA -= iA * (b2Cross(m_rA, P) + m_angularImpulse); - vB += mB * P; - wB += iB * (b2Cross(m_rB, P) + m_angularImpulse); - } - else - { - m_linearImpulse.SetZero(); - m_angularImpulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2MotorJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - float h = data.step.dt; - float inv_h = data.step.inv_dt; - - // Solve angular friction - { - float Cdot = wB - wA + inv_h * m_correctionFactor * m_angularError; - float impulse = -m_angularMass * Cdot; - - float oldImpulse = m_angularImpulse; - float maxImpulse = h * m_maxTorque; - m_angularImpulse = b2Clamp(m_angularImpulse + impulse, -maxImpulse, maxImpulse); - impulse = m_angularImpulse - oldImpulse; - - wA -= iA * impulse; - wB += iB * impulse; - } - - // Solve linear friction - { - b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA) + inv_h * m_correctionFactor * m_linearError; - - b2Vec2 impulse = -b2Mul(m_linearMass, Cdot); - b2Vec2 oldImpulse = m_linearImpulse; - m_linearImpulse += impulse; - - float maxImpulse = h * m_maxForce; - - if (m_linearImpulse.LengthSquared() > maxImpulse * maxImpulse) - { - m_linearImpulse.Normalize(); - m_linearImpulse *= maxImpulse; - } - - impulse = m_linearImpulse - oldImpulse; - - vA -= mA * impulse; - wA -= iA * b2Cross(m_rA, impulse); - - vB += mB * impulse; - wB += iB * b2Cross(m_rB, impulse); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2MotorJoint::SolvePositionConstraints(const b2SolverData& data) -{ - B2_NOT_USED(data); - - return true; -} - -b2Vec2 b2MotorJoint::GetAnchorA() const -{ - return m_bodyA->GetPosition(); -} - -b2Vec2 b2MotorJoint::GetAnchorB() const -{ - return m_bodyB->GetPosition(); -} - -b2Vec2 b2MotorJoint::GetReactionForce(float inv_dt) const -{ - return inv_dt * m_linearImpulse; -} - -float b2MotorJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * m_angularImpulse; -} - -void b2MotorJoint::SetMaxForce(float force) -{ - b2Assert(b2IsValid(force) && force >= 0.0f); - m_maxForce = force; -} - -float b2MotorJoint::GetMaxForce() const -{ - return m_maxForce; -} - -void b2MotorJoint::SetMaxTorque(float torque) -{ - b2Assert(b2IsValid(torque) && torque >= 0.0f); - m_maxTorque = torque; -} - -float b2MotorJoint::GetMaxTorque() const -{ - return m_maxTorque; -} - -void b2MotorJoint::SetCorrectionFactor(float factor) -{ - b2Assert(b2IsValid(factor) && 0.0f <= factor && factor <= 1.0f); - m_correctionFactor = factor; -} - -float b2MotorJoint::GetCorrectionFactor() const -{ - return m_correctionFactor; -} - -void b2MotorJoint::SetLinearOffset(const b2Vec2& linearOffset) -{ - if (linearOffset.x != m_linearOffset.x || linearOffset.y != m_linearOffset.y) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_linearOffset = linearOffset; - } -} - -const b2Vec2& b2MotorJoint::GetLinearOffset() const -{ - return m_linearOffset; -} - -void b2MotorJoint::SetAngularOffset(float angularOffset) -{ - if (angularOffset != m_angularOffset) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_angularOffset = angularOffset; - } -} - -float b2MotorJoint::GetAngularOffset() const -{ - return m_angularOffset; -} - -void b2MotorJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2MotorJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.linearOffset.Set(%.9g, %.9g);\n", m_linearOffset.x, m_linearOffset.y); - b2Dump(" jd.angularOffset = %.9g;\n", m_angularOffset); - b2Dump(" jd.maxForce = %.9g;\n", m_maxForce); - b2Dump(" jd.maxTorque = %.9g;\n", m_maxTorque); - b2Dump(" jd.correctionFactor = %.9g;\n", m_correctionFactor); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} diff --git a/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp b/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp deleted file mode 100644 index dbc214fae749..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_mouse_joint.cpp +++ /dev/null @@ -1,190 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_mouse_joint.h" -#include "box2d/b2_time_step.h" - -// p = attached point, m = mouse point -// C = p - m -// Cdot = v -// = v + cross(w, r) -// J = [I r_skew] -// Identity used: -// w k % (rx i + ry j) = w * (-ry i + rx j) - -b2MouseJoint::b2MouseJoint(const b2MouseJointDef* def) -: b2Joint(def) -{ - m_targetA = def->target; - m_localAnchorB = b2MulT(m_bodyB->GetTransform(), m_targetA); - m_maxForce = def->maxForce; - m_stiffness = def->stiffness; - m_damping = def->damping; - - m_impulse.SetZero(); - m_beta = 0.0f; - m_gamma = 0.0f; -} - -void b2MouseJoint::SetTarget(const b2Vec2& target) -{ - if (target != m_targetA) - { - m_bodyB->SetAwake(true); - m_targetA = target; - } -} - -const b2Vec2& b2MouseJoint::GetTarget() const -{ - return m_targetA; -} - -void b2MouseJoint::SetMaxForce(float force) -{ - m_maxForce = force; -} - -float b2MouseJoint::GetMaxForce() const -{ - return m_maxForce; -} - -void b2MouseJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexB = m_bodyB->m_islandIndex; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassB = m_bodyB->m_invMass; - m_invIB = m_bodyB->m_invI; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qB(aB); - - float d = m_damping; - float k = m_stiffness; - - // magic formulas - // gamma has units of inverse mass. - // beta has units of inverse time. - float h = data.step.dt; - m_gamma = h * (d + h * k); - if (m_gamma != 0.0f) - { - m_gamma = 1.0f / m_gamma; - } - m_beta = h * k * m_gamma; - - // Compute the effective mass matrix. - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)] - // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y] - // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x] - b2Mat22 K; - K.ex.x = m_invMassB + m_invIB * m_rB.y * m_rB.y + m_gamma; - K.ex.y = -m_invIB * m_rB.x * m_rB.y; - K.ey.x = K.ex.y; - K.ey.y = m_invMassB + m_invIB * m_rB.x * m_rB.x + m_gamma; - - m_mass = K.GetInverse(); - - m_C = cB + m_rB - m_targetA; - m_C *= m_beta; - - // Cheat with some damping - wB *= b2Max(0.0f, 1.0f - 0.02f * (60.0f * data.step.dt)); - - if (data.step.warmStarting) - { - m_impulse *= data.step.dtRatio; - vB += m_invMassB * m_impulse; - wB += m_invIB * b2Cross(m_rB, m_impulse); - } - else - { - m_impulse.SetZero(); - } - - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2MouseJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - // Cdot = v + cross(w, r) - b2Vec2 Cdot = vB + b2Cross(wB, m_rB); - b2Vec2 impulse = b2Mul(m_mass, -(Cdot + m_C + m_gamma * m_impulse)); - - b2Vec2 oldImpulse = m_impulse; - m_impulse += impulse; - float maxImpulse = data.step.dt * m_maxForce; - if (m_impulse.LengthSquared() > maxImpulse * maxImpulse) - { - m_impulse *= maxImpulse / m_impulse.Length(); - } - impulse = m_impulse - oldImpulse; - - vB += m_invMassB * impulse; - wB += m_invIB * b2Cross(m_rB, impulse); - - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2MouseJoint::SolvePositionConstraints(const b2SolverData& data) -{ - B2_NOT_USED(data); - return true; -} - -b2Vec2 b2MouseJoint::GetAnchorA() const -{ - return m_targetA; -} - -b2Vec2 b2MouseJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2MouseJoint::GetReactionForce(float inv_dt) const -{ - return inv_dt * m_impulse; -} - -float b2MouseJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * 0.0f; -} - -void b2MouseJoint::ShiftOrigin(const b2Vec2& newOrigin) -{ - m_targetA -= newOrigin; -} diff --git a/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.cpp b/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.cpp deleted file mode 100644 index e4f34f582f74..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.cpp +++ /dev/null @@ -1,54 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_polygon_circle_contact.h" - -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_fixture.h" - -#include - -b2Contact* b2PolygonAndCircleContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2PolygonAndCircleContact)); - return new (mem) b2PolygonAndCircleContact(fixtureA, fixtureB); -} - -void b2PolygonAndCircleContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2PolygonAndCircleContact*)contact)->~b2PolygonAndCircleContact(); - allocator->Free(contact, sizeof(b2PolygonAndCircleContact)); -} - -b2PolygonAndCircleContact::b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB) -: b2Contact(fixtureA, 0, fixtureB, 0) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon); - b2Assert(m_fixtureB->GetType() == b2Shape::e_circle); -} - -void b2PolygonAndCircleContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2CollidePolygonAndCircle( manifold, - (b2PolygonShape*)m_fixtureA->GetShape(), xfA, - (b2CircleShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.h b/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.h deleted file mode 100644 index 6ae542510cb4..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_polygon_circle_contact.h +++ /dev/null @@ -1,42 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_POLYGON_AND_CIRCLE_CONTACT_H -#define B2_POLYGON_AND_CIRCLE_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2PolygonAndCircleContact : public b2Contact -{ -public: - static b2Contact* Create(b2Fixture* fixtureA, int32 indexA, b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2PolygonAndCircleContact(b2Fixture* fixtureA, b2Fixture* fixtureB); - ~b2PolygonAndCircleContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_polygon_contact.cpp b/3rdparty/box2d/src/dynamics/b2_polygon_contact.cpp deleted file mode 100644 index e92a9e806318..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_polygon_contact.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_polygon_contact.h" - -#include "box2d/b2_block_allocator.h" -#include "box2d/b2_body.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_time_of_impact.h" -#include "box2d/b2_world_callbacks.h" - -#include - -b2Contact* b2PolygonContact::Create(b2Fixture* fixtureA, int32, b2Fixture* fixtureB, int32, b2BlockAllocator* allocator) -{ - void* mem = allocator->Allocate(sizeof(b2PolygonContact)); - return new (mem) b2PolygonContact(fixtureA, fixtureB); -} - -void b2PolygonContact::Destroy(b2Contact* contact, b2BlockAllocator* allocator) -{ - ((b2PolygonContact*)contact)->~b2PolygonContact(); - allocator->Free(contact, sizeof(b2PolygonContact)); -} - -b2PolygonContact::b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB) - : b2Contact(fixtureA, 0, fixtureB, 0) -{ - b2Assert(m_fixtureA->GetType() == b2Shape::e_polygon); - b2Assert(m_fixtureB->GetType() == b2Shape::e_polygon); -} - -void b2PolygonContact::Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) -{ - b2CollidePolygons( manifold, - (b2PolygonShape*)m_fixtureA->GetShape(), xfA, - (b2PolygonShape*)m_fixtureB->GetShape(), xfB); -} diff --git a/3rdparty/box2d/src/dynamics/b2_polygon_contact.h b/3rdparty/box2d/src/dynamics/b2_polygon_contact.h deleted file mode 100644 index 0516cb0ec623..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_polygon_contact.h +++ /dev/null @@ -1,43 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef B2_POLYGON_CONTACT_H -#define B2_POLYGON_CONTACT_H - -#include "box2d/b2_contact.h" - -class b2BlockAllocator; - -class b2PolygonContact : public b2Contact -{ -public: - static b2Contact* Create( b2Fixture* fixtureA, int32 indexA, - b2Fixture* fixtureB, int32 indexB, b2BlockAllocator* allocator); - static void Destroy(b2Contact* contact, b2BlockAllocator* allocator); - - b2PolygonContact(b2Fixture* fixtureA, b2Fixture* fixtureB); - ~b2PolygonContact() {} - - void Evaluate(b2Manifold* manifold, const b2Transform& xfA, const b2Transform& xfB) override; -}; - -#endif diff --git a/3rdparty/box2d/src/dynamics/b2_prismatic_joint.cpp b/3rdparty/box2d/src/dynamics/b2_prismatic_joint.cpp deleted file mode 100644 index 00e77690eb6b..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_prismatic_joint.cpp +++ /dev/null @@ -1,643 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_prismatic_joint.h" -#include "box2d/b2_time_step.h" - -// Linear constraint (point-to-line) -// d = p2 - p1 = x2 + r2 - x1 - r1 -// C = dot(perp, d) -// Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1)) -// = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2) -// J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)] -// -// Angular constraint -// C = a2 - a1 + a_initial -// Cdot = w2 - w1 -// J = [0 0 -1 0 0 1] -// -// K = J * invM * JT -// -// J = [-a -s1 a s2] -// [0 -1 0 1] -// a = perp -// s1 = cross(d + r1, a) = cross(p2 - x1, a) -// s2 = cross(r2, a) = cross(p2 - x2, a) - -// Motor/Limit linear constraint -// C = dot(ax1, d) -// Cdot = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2) -// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)] - -// Predictive limit is applied even when the limit is not active. -// Prevents a constraint speed that can lead to a constraint error in one time step. -// Want C2 = C1 + h * Cdot >= 0 -// Or: -// Cdot + C1/h >= 0 -// I do not apply a negative constraint error because that is handled in position correction. -// So: -// Cdot + max(C1, 0)/h >= 0 - -// Block Solver -// We develop a block solver that includes the angular and linear constraints. This makes the limit stiffer. -// -// The Jacobian has 2 rows: -// J = [-uT -s1 uT s2] // linear -// [0 -1 0 1] // angular -// -// u = perp -// s1 = cross(d + r1, u), s2 = cross(r2, u) -// a1 = cross(d + r1, v), a2 = cross(r2, v) - -void b2PrismaticJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis) -{ - bodyA = bA; - bodyB = bB; - localAnchorA = bodyA->GetLocalPoint(anchor); - localAnchorB = bodyB->GetLocalPoint(anchor); - localAxisA = bodyA->GetLocalVector(axis); - referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); -} - -b2PrismaticJoint::b2PrismaticJoint(const b2PrismaticJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - m_localXAxisA = def->localAxisA; - m_localXAxisA.Normalize(); - m_localYAxisA = b2Cross(1.0f, m_localXAxisA); - m_referenceAngle = def->referenceAngle; - - m_impulse.SetZero(); - m_axialMass = 0.0f; - m_motorImpulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - - m_lowerTranslation = def->lowerTranslation; - m_upperTranslation = def->upperTranslation; - - b2Assert(m_lowerTranslation <= m_upperTranslation); - - m_maxMotorForce = def->maxMotorForce; - m_motorSpeed = def->motorSpeed; - m_enableLimit = def->enableLimit; - m_enableMotor = def->enableMotor; - - m_translation = 0.0f; - m_axis.SetZero(); - m_perp.SetZero(); -} - -void b2PrismaticJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - // Compute the effective masses. - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 d = (cB - cA) + rB - rA; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - // Compute motor Jacobian and effective mass. - { - m_axis = b2Mul(qA, m_localXAxisA); - m_a1 = b2Cross(d + rA, m_axis); - m_a2 = b2Cross(rB, m_axis); - - m_axialMass = mA + mB + iA * m_a1 * m_a1 + iB * m_a2 * m_a2; - if (m_axialMass > 0.0f) - { - m_axialMass = 1.0f / m_axialMass; - } - } - - // Prismatic constraint. - { - m_perp = b2Mul(qA, m_localYAxisA); - - m_s1 = b2Cross(d + rA, m_perp); - m_s2 = b2Cross(rB, m_perp); - - float k11 = mA + mB + iA * m_s1 * m_s1 + iB * m_s2 * m_s2; - float k12 = iA * m_s1 + iB * m_s2; - float k22 = iA + iB; - if (k22 == 0.0f) - { - // For bodies with fixed rotation. - k22 = 1.0f; - } - - m_K.ex.Set(k11, k12); - m_K.ey.Set(k12, k22); - } - - if (m_enableLimit) - { - m_translation = b2Dot(m_axis, d); - } - else - { - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - if (m_enableMotor == false) - { - m_motorImpulse = 0.0f; - } - - if (data.step.warmStarting) - { - // Account for variable time step. - m_impulse *= data.step.dtRatio; - m_motorImpulse *= data.step.dtRatio; - m_lowerImpulse *= data.step.dtRatio; - m_upperImpulse *= data.step.dtRatio; - - float axialImpulse = m_motorImpulse + m_lowerImpulse - m_upperImpulse; - b2Vec2 P = m_impulse.x * m_perp + axialImpulse * m_axis; - float LA = m_impulse.x * m_s1 + m_impulse.y + axialImpulse * m_a1; - float LB = m_impulse.x * m_s2 + m_impulse.y + axialImpulse * m_a2; - - vA -= mA * P; - wA -= iA * LA; - - vB += mB * P; - wB += iB * LB; - } - else - { - m_impulse.SetZero(); - m_motorImpulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2PrismaticJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - // Solve linear motor constraint - if (m_enableMotor) - { - float Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; - float impulse = m_axialMass * (m_motorSpeed - Cdot); - float oldImpulse = m_motorImpulse; - float maxImpulse = data.step.dt * m_maxMotorForce; - m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = m_motorImpulse - oldImpulse; - - b2Vec2 P = impulse * m_axis; - float LA = impulse * m_a1; - float LB = impulse * m_a2; - - vA -= mA * P; - wA -= iA * LA; - vB += mB * P; - wB += iB * LB; - } - - if (m_enableLimit) - { - // Lower limit - { - float C = m_translation - m_lowerTranslation; - float Cdot = b2Dot(m_axis, vB - vA) + m_a2 * wB - m_a1 * wA; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_lowerImpulse; - m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f); - impulse = m_lowerImpulse - oldImpulse; - - b2Vec2 P = impulse * m_axis; - float LA = impulse * m_a1; - float LB = impulse * m_a2; - - vA -= mA * P; - wA -= iA * LA; - vB += mB * P; - wB += iB * LB; - } - - // Upper limit - // Note: signs are flipped to keep C positive when the constraint is satisfied. - // This also keeps the impulse positive when the limit is active. - { - float C = m_upperTranslation - m_translation; - float Cdot = b2Dot(m_axis, vA - vB) + m_a1 * wA - m_a2 * wB; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_upperImpulse; - m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f); - impulse = m_upperImpulse - oldImpulse; - - b2Vec2 P = impulse * m_axis; - float LA = impulse * m_a1; - float LB = impulse * m_a2; - - vA += mA * P; - wA += iA * LA; - vB -= mB * P; - wB -= iB * LB; - } - } - - // Solve the prismatic constraint in block form. - { - b2Vec2 Cdot; - Cdot.x = b2Dot(m_perp, vB - vA) + m_s2 * wB - m_s1 * wA; - Cdot.y = wB - wA; - - b2Vec2 df = m_K.Solve(-Cdot); - m_impulse += df; - - b2Vec2 P = df.x * m_perp; - float LA = df.x * m_s1 + df.y; - float LB = df.x * m_s2 + df.y; - - vA -= mA * P; - wA -= iA * LA; - - vB += mB * P; - wB += iB * LB; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -// A velocity based solver computes reaction forces(impulses) using the velocity constraint solver.Under this context, -// the position solver is not there to resolve forces.It is only there to cope with integration error. -// -// Therefore, the pseudo impulses in the position solver do not have any physical meaning.Thus it is okay if they suck. -// -// We could take the active state from the velocity solver.However, the joint might push past the limit when the velocity -// solver indicates the limit is inactive. -bool b2PrismaticJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - b2Rot qA(aA), qB(aB); - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - // Compute fresh Jacobians - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 d = cB + rB - cA - rA; - - b2Vec2 axis = b2Mul(qA, m_localXAxisA); - float a1 = b2Cross(d + rA, axis); - float a2 = b2Cross(rB, axis); - b2Vec2 perp = b2Mul(qA, m_localYAxisA); - - float s1 = b2Cross(d + rA, perp); - float s2 = b2Cross(rB, perp); - - b2Vec3 impulse; - b2Vec2 C1; - C1.x = b2Dot(perp, d); - C1.y = aB - aA - m_referenceAngle; - - float linearError = b2Abs(C1.x); - float angularError = b2Abs(C1.y); - - bool active = false; - float C2 = 0.0f; - if (m_enableLimit) - { - float translation = b2Dot(axis, d); - if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) - { - C2 = translation; - linearError = b2Max(linearError, b2Abs(translation)); - active = true; - } - else if (translation <= m_lowerTranslation) - { - C2 = b2Min(translation - m_lowerTranslation, 0.0f); - linearError = b2Max(linearError, m_lowerTranslation - translation); - active = true; - } - else if (translation >= m_upperTranslation) - { - C2 = b2Max(translation - m_upperTranslation, 0.0f); - linearError = b2Max(linearError, translation - m_upperTranslation); - active = true; - } - } - - if (active) - { - float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; - float k12 = iA * s1 + iB * s2; - float k13 = iA * s1 * a1 + iB * s2 * a2; - float k22 = iA + iB; - if (k22 == 0.0f) - { - // For fixed rotation - k22 = 1.0f; - } - float k23 = iA * a1 + iB * a2; - float k33 = mA + mB + iA * a1 * a1 + iB * a2 * a2; - - b2Mat33 K; - K.ex.Set(k11, k12, k13); - K.ey.Set(k12, k22, k23); - K.ez.Set(k13, k23, k33); - - b2Vec3 C; - C.x = C1.x; - C.y = C1.y; - C.z = C2; - - impulse = K.Solve33(-C); - } - else - { - float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; - float k12 = iA * s1 + iB * s2; - float k22 = iA + iB; - if (k22 == 0.0f) - { - k22 = 1.0f; - } - - b2Mat22 K; - K.ex.Set(k11, k12); - K.ey.Set(k12, k22); - - b2Vec2 impulse1 = K.Solve(-C1); - impulse.x = impulse1.x; - impulse.y = impulse1.y; - impulse.z = 0.0f; - } - - b2Vec2 P = impulse.x * perp + impulse.z * axis; - float LA = impulse.x * s1 + impulse.y + impulse.z * a1; - float LB = impulse.x * s2 + impulse.y + impulse.z * a2; - - cA -= mA * P; - aA -= iA * LA; - cB += mB * P; - aB += iB * LB; - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return linearError <= b2_linearSlop && angularError <= b2_angularSlop; -} - -b2Vec2 b2PrismaticJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2PrismaticJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2PrismaticJoint::GetReactionForce(float inv_dt) const -{ - return inv_dt * (m_impulse.x * m_perp + (m_motorImpulse + m_lowerImpulse - m_upperImpulse) * m_axis); -} - -float b2PrismaticJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * m_impulse.y; -} - -float b2PrismaticJoint::GetJointTranslation() const -{ - b2Vec2 pA = m_bodyA->GetWorldPoint(m_localAnchorA); - b2Vec2 pB = m_bodyB->GetWorldPoint(m_localAnchorB); - b2Vec2 d = pB - pA; - b2Vec2 axis = m_bodyA->GetWorldVector(m_localXAxisA); - - float translation = b2Dot(d, axis); - return translation; -} - -float b2PrismaticJoint::GetJointSpeed() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - - b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter); - b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter); - b2Vec2 p1 = bA->m_sweep.c + rA; - b2Vec2 p2 = bB->m_sweep.c + rB; - b2Vec2 d = p2 - p1; - b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA); - - b2Vec2 vA = bA->m_linearVelocity; - b2Vec2 vB = bB->m_linearVelocity; - float wA = bA->m_angularVelocity; - float wB = bB->m_angularVelocity; - - float speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA)); - return speed; -} - -bool b2PrismaticJoint::IsLimitEnabled() const -{ - return m_enableLimit; -} - -void b2PrismaticJoint::EnableLimit(bool flag) -{ - if (flag != m_enableLimit) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableLimit = flag; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } -} - -float b2PrismaticJoint::GetLowerLimit() const -{ - return m_lowerTranslation; -} - -float b2PrismaticJoint::GetUpperLimit() const -{ - return m_upperTranslation; -} - -void b2PrismaticJoint::SetLimits(float lower, float upper) -{ - b2Assert(lower <= upper); - if (lower != m_lowerTranslation || upper != m_upperTranslation) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_lowerTranslation = lower; - m_upperTranslation = upper; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } -} - -bool b2PrismaticJoint::IsMotorEnabled() const -{ - return m_enableMotor; -} - -void b2PrismaticJoint::EnableMotor(bool flag) -{ - if (flag != m_enableMotor) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableMotor = flag; - } -} - -void b2PrismaticJoint::SetMotorSpeed(float speed) -{ - if (speed != m_motorSpeed) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_motorSpeed = speed; - } -} - -void b2PrismaticJoint::SetMaxMotorForce(float force) -{ - if (force != m_maxMotorForce) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_maxMotorForce = force; - } -} - -float b2PrismaticJoint::GetMotorForce(float inv_dt) const -{ - return inv_dt * m_motorImpulse; -} - -void b2PrismaticJoint::Dump() -{ - // FLT_DECIMAL_DIG == 9 - - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2PrismaticJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.localAxisA.Set(%.9g, %.9g);\n", m_localXAxisA.x, m_localXAxisA.y); - b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle); - b2Dump(" jd.enableLimit = bool(%d);\n", m_enableLimit); - b2Dump(" jd.lowerTranslation = %.9g;\n", m_lowerTranslation); - b2Dump(" jd.upperTranslation = %.9g;\n", m_upperTranslation); - b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor); - b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed); - b2Dump(" jd.maxMotorForce = %.9g;\n", m_maxMotorForce); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} - -void b2PrismaticJoint::Draw(b2Draw* draw) const -{ - const b2Transform& xfA = m_bodyA->GetTransform(); - const b2Transform& xfB = m_bodyB->GetTransform(); - b2Vec2 pA = b2Mul(xfA, m_localAnchorA); - b2Vec2 pB = b2Mul(xfB, m_localAnchorB); - - b2Vec2 axis = b2Mul(xfA.q, m_localXAxisA); - - b2Color c1(0.7f, 0.7f, 0.7f); - b2Color c2(0.3f, 0.9f, 0.3f); - b2Color c3(0.9f, 0.3f, 0.3f); - b2Color c4(0.3f, 0.3f, 0.9f); - b2Color c5(0.4f, 0.4f, 0.4f); - - draw->DrawSegment(pA, pB, c5); - - if (m_enableLimit) - { - b2Vec2 lower = pA + m_lowerTranslation * axis; - b2Vec2 upper = pA + m_upperTranslation * axis; - b2Vec2 perp = b2Mul(xfA.q, m_localYAxisA); - draw->DrawSegment(lower, upper, c1); - draw->DrawSegment(lower - 0.5f * perp, lower + 0.5f * perp, c2); - draw->DrawSegment(upper - 0.5f * perp, upper + 0.5f * perp, c3); - } - else - { - draw->DrawSegment(pA - 1.0f * axis, pA + 1.0f * axis, c1); - } - - draw->DrawPoint(pA, 5.0f, c1); - draw->DrawPoint(pB, 5.0f, c4); -} diff --git a/3rdparty/box2d/src/dynamics/b2_pulley_joint.cpp b/3rdparty/box2d/src/dynamics/b2_pulley_joint.cpp deleted file mode 100644 index 099e57e49d91..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_pulley_joint.cpp +++ /dev/null @@ -1,352 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_pulley_joint.h" -#include "box2d/b2_time_step.h" - -// Pulley: -// length1 = norm(p1 - s1) -// length2 = norm(p2 - s2) -// C0 = (length1 + ratio * length2)_initial -// C = C0 - (length1 + ratio * length2) -// u1 = (p1 - s1) / norm(p1 - s1) -// u2 = (p2 - s2) / norm(p2 - s2) -// Cdot = -dot(u1, v1 + cross(w1, r1)) - ratio * dot(u2, v2 + cross(w2, r2)) -// J = -[u1 cross(r1, u1) ratio * u2 ratio * cross(r2, u2)] -// K = J * invM * JT -// = invMass1 + invI1 * cross(r1, u1)^2 + ratio^2 * (invMass2 + invI2 * cross(r2, u2)^2) - -void b2PulleyJointDef::Initialize(b2Body* bA, b2Body* bB, - const b2Vec2& groundA, const b2Vec2& groundB, - const b2Vec2& anchorA, const b2Vec2& anchorB, - float r) -{ - bodyA = bA; - bodyB = bB; - groundAnchorA = groundA; - groundAnchorB = groundB; - localAnchorA = bodyA->GetLocalPoint(anchorA); - localAnchorB = bodyB->GetLocalPoint(anchorB); - b2Vec2 dA = anchorA - groundA; - lengthA = dA.Length(); - b2Vec2 dB = anchorB - groundB; - lengthB = dB.Length(); - ratio = r; - b2Assert(ratio > b2_epsilon); -} - -b2PulleyJoint::b2PulleyJoint(const b2PulleyJointDef* def) -: b2Joint(def) -{ - m_groundAnchorA = def->groundAnchorA; - m_groundAnchorB = def->groundAnchorB; - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - - m_lengthA = def->lengthA; - m_lengthB = def->lengthB; - - b2Assert(def->ratio != 0.0f); - m_ratio = def->ratio; - - m_constant = def->lengthA + m_ratio * def->lengthB; - - m_impulse = 0.0f; -} - -void b2PulleyJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // Get the pulley axes. - m_uA = cA + m_rA - m_groundAnchorA; - m_uB = cB + m_rB - m_groundAnchorB; - - float lengthA = m_uA.Length(); - float lengthB = m_uB.Length(); - - if (lengthA > 10.0f * b2_linearSlop) - { - m_uA *= 1.0f / lengthA; - } - else - { - m_uA.SetZero(); - } - - if (lengthB > 10.0f * b2_linearSlop) - { - m_uB *= 1.0f / lengthB; - } - else - { - m_uB.SetZero(); - } - - // Compute effective mass. - float ruA = b2Cross(m_rA, m_uA); - float ruB = b2Cross(m_rB, m_uB); - - float mA = m_invMassA + m_invIA * ruA * ruA; - float mB = m_invMassB + m_invIB * ruB * ruB; - - m_mass = mA + m_ratio * m_ratio * mB; - - if (m_mass > 0.0f) - { - m_mass = 1.0f / m_mass; - } - - if (data.step.warmStarting) - { - // Scale impulses to support variable time steps. - m_impulse *= data.step.dtRatio; - - // Warm starting. - b2Vec2 PA = -(m_impulse) * m_uA; - b2Vec2 PB = (-m_ratio * m_impulse) * m_uB; - - vA += m_invMassA * PA; - wA += m_invIA * b2Cross(m_rA, PA); - vB += m_invMassB * PB; - wB += m_invIB * b2Cross(m_rB, PB); - } - else - { - m_impulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2PulleyJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Vec2 vpA = vA + b2Cross(wA, m_rA); - b2Vec2 vpB = vB + b2Cross(wB, m_rB); - - float Cdot = -b2Dot(m_uA, vpA) - m_ratio * b2Dot(m_uB, vpB); - float impulse = -m_mass * Cdot; - m_impulse += impulse; - - b2Vec2 PA = -impulse * m_uA; - b2Vec2 PB = -m_ratio * impulse * m_uB; - vA += m_invMassA * PA; - wA += m_invIA * b2Cross(m_rA, PA); - vB += m_invMassB * PB; - wB += m_invIB * b2Cross(m_rB, PB); - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2PulleyJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - b2Rot qA(aA), qB(aB); - - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // Get the pulley axes. - b2Vec2 uA = cA + rA - m_groundAnchorA; - b2Vec2 uB = cB + rB - m_groundAnchorB; - - float lengthA = uA.Length(); - float lengthB = uB.Length(); - - if (lengthA > 10.0f * b2_linearSlop) - { - uA *= 1.0f / lengthA; - } - else - { - uA.SetZero(); - } - - if (lengthB > 10.0f * b2_linearSlop) - { - uB *= 1.0f / lengthB; - } - else - { - uB.SetZero(); - } - - // Compute effective mass. - float ruA = b2Cross(rA, uA); - float ruB = b2Cross(rB, uB); - - float mA = m_invMassA + m_invIA * ruA * ruA; - float mB = m_invMassB + m_invIB * ruB * ruB; - - float mass = mA + m_ratio * m_ratio * mB; - - if (mass > 0.0f) - { - mass = 1.0f / mass; - } - - float C = m_constant - lengthA - m_ratio * lengthB; - float linearError = b2Abs(C); - - float impulse = -mass * C; - - b2Vec2 PA = -impulse * uA; - b2Vec2 PB = -m_ratio * impulse * uB; - - cA += m_invMassA * PA; - aA += m_invIA * b2Cross(rA, PA); - cB += m_invMassB * PB; - aB += m_invIB * b2Cross(rB, PB); - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return linearError < b2_linearSlop; -} - -b2Vec2 b2PulleyJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2PulleyJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2PulleyJoint::GetReactionForce(float inv_dt) const -{ - b2Vec2 P = m_impulse * m_uB; - return inv_dt * P; -} - -float b2PulleyJoint::GetReactionTorque(float inv_dt) const -{ - B2_NOT_USED(inv_dt); - return 0.0f; -} - -b2Vec2 b2PulleyJoint::GetGroundAnchorA() const -{ - return m_groundAnchorA; -} - -b2Vec2 b2PulleyJoint::GetGroundAnchorB() const -{ - return m_groundAnchorB; -} - -float b2PulleyJoint::GetLengthA() const -{ - return m_lengthA; -} - -float b2PulleyJoint::GetLengthB() const -{ - return m_lengthB; -} - -float b2PulleyJoint::GetRatio() const -{ - return m_ratio; -} - -float b2PulleyJoint::GetCurrentLengthA() const -{ - b2Vec2 p = m_bodyA->GetWorldPoint(m_localAnchorA); - b2Vec2 s = m_groundAnchorA; - b2Vec2 d = p - s; - return d.Length(); -} - -float b2PulleyJoint::GetCurrentLengthB() const -{ - b2Vec2 p = m_bodyB->GetWorldPoint(m_localAnchorB); - b2Vec2 s = m_groundAnchorB; - b2Vec2 d = p - s; - return d.Length(); -} - -void b2PulleyJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2PulleyJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.groundAnchorA.Set(%.9g, %.9g);\n", m_groundAnchorA.x, m_groundAnchorA.y); - b2Dump(" jd.groundAnchorB.Set(%.9g, %.9g);\n", m_groundAnchorB.x, m_groundAnchorB.y); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.lengthA = %.9g;\n", m_lengthA); - b2Dump(" jd.lengthB = %.9g;\n", m_lengthB); - b2Dump(" jd.ratio = %.9g;\n", m_ratio); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} - -void b2PulleyJoint::ShiftOrigin(const b2Vec2& newOrigin) -{ - m_groundAnchorA -= newOrigin; - m_groundAnchorB -= newOrigin; -} diff --git a/3rdparty/box2d/src/dynamics/b2_revolute_joint.cpp b/3rdparty/box2d/src/dynamics/b2_revolute_joint.cpp deleted file mode 100644 index f7cc4cc29afe..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_revolute_joint.cpp +++ /dev/null @@ -1,501 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_revolute_joint.h" -#include "box2d/b2_time_step.h" - -// Point-to-point constraint -// C = p2 - p1 -// Cdot = v2 - v1 -// = v2 + cross(w2, r2) - v1 - cross(w1, r1) -// J = [-I -r1_skew I r2_skew ] -// Identity used: -// w k % (rx i + ry j) = w * (-ry i + rx j) - -// Motor constraint -// Cdot = w2 - w1 -// J = [0 0 -1 0 0 1] -// K = invI1 + invI2 - -void b2RevoluteJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) -{ - bodyA = bA; - bodyB = bB; - localAnchorA = bodyA->GetLocalPoint(anchor); - localAnchorB = bodyB->GetLocalPoint(anchor); - referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); -} - -b2RevoluteJoint::b2RevoluteJoint(const b2RevoluteJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - m_referenceAngle = def->referenceAngle; - - m_impulse.SetZero(); - m_axialMass = 0.0f; - m_motorImpulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - - m_lowerAngle = def->lowerAngle; - m_upperAngle = def->upperAngle; - m_maxMotorTorque = def->maxMotorTorque; - m_motorSpeed = def->motorSpeed; - m_enableLimit = def->enableLimit; - m_enableMotor = def->enableMotor; - - m_angle = 0.0f; -} - -void b2RevoluteJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // J = [-I -r1_skew I r2_skew] - // r_skew = [-ry; rx] - - // Matlab - // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x] - // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB] - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - m_K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB; - m_K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB; - m_K.ex.y = m_K.ey.x; - m_K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB; - - m_axialMass = iA + iB; - bool fixedRotation; - if (m_axialMass > 0.0f) - { - m_axialMass = 1.0f / m_axialMass; - fixedRotation = false; - } - else - { - fixedRotation = true; - } - - m_angle = aB - aA - m_referenceAngle; - if (m_enableLimit == false || fixedRotation) - { - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - if (m_enableMotor == false || fixedRotation) - { - m_motorImpulse = 0.0f; - } - - if (data.step.warmStarting) - { - // Scale impulses to support a variable time step. - m_impulse *= data.step.dtRatio; - m_motorImpulse *= data.step.dtRatio; - m_lowerImpulse *= data.step.dtRatio; - m_upperImpulse *= data.step.dtRatio; - - float axialImpulse = m_motorImpulse + m_lowerImpulse - m_upperImpulse; - b2Vec2 P(m_impulse.x, m_impulse.y); - - vA -= mA * P; - wA -= iA * (b2Cross(m_rA, P) + axialImpulse); - - vB += mB * P; - wB += iB * (b2Cross(m_rB, P) + axialImpulse); - } - else - { - m_impulse.SetZero(); - m_motorImpulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2RevoluteJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - bool fixedRotation = (iA + iB == 0.0f); - - // Solve motor constraint. - if (m_enableMotor && fixedRotation == false) - { - float Cdot = wB - wA - m_motorSpeed; - float impulse = -m_axialMass * Cdot; - float oldImpulse = m_motorImpulse; - float maxImpulse = data.step.dt * m_maxMotorTorque; - m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = m_motorImpulse - oldImpulse; - - wA -= iA * impulse; - wB += iB * impulse; - } - - if (m_enableLimit && fixedRotation == false) - { - // Lower limit - { - float C = m_angle - m_lowerAngle; - float Cdot = wB - wA; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_lowerImpulse; - m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f); - impulse = m_lowerImpulse - oldImpulse; - - wA -= iA * impulse; - wB += iB * impulse; - } - - // Upper limit - // Note: signs are flipped to keep C positive when the constraint is satisfied. - // This also keeps the impulse positive when the limit is active. - { - float C = m_upperAngle - m_angle; - float Cdot = wA - wB; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_upperImpulse; - m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f); - impulse = m_upperImpulse - oldImpulse; - - wA += iA * impulse; - wB -= iB * impulse; - } - } - - // Solve point-to-point constraint - { - b2Vec2 Cdot = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); - b2Vec2 impulse = m_K.Solve(-Cdot); - - m_impulse.x += impulse.x; - m_impulse.y += impulse.y; - - vA -= mA * impulse; - wA -= iA * b2Cross(m_rA, impulse); - - vB += mB * impulse; - wB += iB * b2Cross(m_rB, impulse); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2RevoluteJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - b2Rot qA(aA), qB(aB); - - float angularError = 0.0f; - float positionError = 0.0f; - - bool fixedRotation = (m_invIA + m_invIB == 0.0f); - - // Solve angular limit constraint - if (m_enableLimit && fixedRotation == false) - { - float angle = aB - aA - m_referenceAngle; - float C = 0.0f; - - if (b2Abs(m_upperAngle - m_lowerAngle) < 2.0f * b2_angularSlop) - { - // Prevent large angular corrections - C = b2Clamp(angle - m_lowerAngle, -b2_maxAngularCorrection, b2_maxAngularCorrection); - } - else if (angle <= m_lowerAngle) - { - // Prevent large angular corrections and allow some slop. - C = b2Clamp(angle - m_lowerAngle + b2_angularSlop, -b2_maxAngularCorrection, 0.0f); - } - else if (angle >= m_upperAngle) - { - // Prevent large angular corrections and allow some slop. - C = b2Clamp(angle - m_upperAngle - b2_angularSlop, 0.0f, b2_maxAngularCorrection); - } - - float limitImpulse = -m_axialMass * C; - aA -= m_invIA * limitImpulse; - aB += m_invIB * limitImpulse; - angularError = b2Abs(C); - } - - // Solve point-to-point constraint. - { - qA.Set(aA); - qB.Set(aB); - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - b2Vec2 C = cB + rB - cA - rA; - positionError = C.Length(); - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Mat22 K; - K.ex.x = mA + mB + iA * rA.y * rA.y + iB * rB.y * rB.y; - K.ex.y = -iA * rA.x * rA.y - iB * rB.x * rB.y; - K.ey.x = K.ex.y; - K.ey.y = mA + mB + iA * rA.x * rA.x + iB * rB.x * rB.x; - - b2Vec2 impulse = -K.Solve(C); - - cA -= mA * impulse; - aA -= iA * b2Cross(rA, impulse); - - cB += mB * impulse; - aB += iB * b2Cross(rB, impulse); - } - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return positionError <= b2_linearSlop && angularError <= b2_angularSlop; -} - -b2Vec2 b2RevoluteJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2RevoluteJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2RevoluteJoint::GetReactionForce(float inv_dt) const -{ - b2Vec2 P(m_impulse.x, m_impulse.y); - return inv_dt * P; -} - -float b2RevoluteJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * (m_motorImpulse + m_lowerImpulse - m_upperImpulse); -} - -float b2RevoluteJoint::GetJointAngle() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - return bB->m_sweep.a - bA->m_sweep.a - m_referenceAngle; -} - -float b2RevoluteJoint::GetJointSpeed() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - return bB->m_angularVelocity - bA->m_angularVelocity; -} - -bool b2RevoluteJoint::IsMotorEnabled() const -{ - return m_enableMotor; -} - -void b2RevoluteJoint::EnableMotor(bool flag) -{ - if (flag != m_enableMotor) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableMotor = flag; - } -} - -float b2RevoluteJoint::GetMotorTorque(float inv_dt) const -{ - return inv_dt * m_motorImpulse; -} - -void b2RevoluteJoint::SetMotorSpeed(float speed) -{ - if (speed != m_motorSpeed) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_motorSpeed = speed; - } -} - -void b2RevoluteJoint::SetMaxMotorTorque(float torque) -{ - if (torque != m_maxMotorTorque) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_maxMotorTorque = torque; - } -} - -bool b2RevoluteJoint::IsLimitEnabled() const -{ - return m_enableLimit; -} - -void b2RevoluteJoint::EnableLimit(bool flag) -{ - if (flag != m_enableLimit) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableLimit = flag; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } -} - -float b2RevoluteJoint::GetLowerLimit() const -{ - return m_lowerAngle; -} - -float b2RevoluteJoint::GetUpperLimit() const -{ - return m_upperAngle; -} - -void b2RevoluteJoint::SetLimits(float lower, float upper) -{ - b2Assert(lower <= upper); - - if (lower != m_lowerAngle || upper != m_upperAngle) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - m_lowerAngle = lower; - m_upperAngle = upper; - } -} - -void b2RevoluteJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2RevoluteJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle); - b2Dump(" jd.enableLimit = bool(%d);\n", m_enableLimit); - b2Dump(" jd.lowerAngle = %.9g;\n", m_lowerAngle); - b2Dump(" jd.upperAngle = %.9g;\n", m_upperAngle); - b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor); - b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed); - b2Dump(" jd.maxMotorTorque = %.9g;\n", m_maxMotorTorque); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} - -/// -void b2RevoluteJoint::Draw(b2Draw* draw) const -{ - const b2Transform& xfA = m_bodyA->GetTransform(); - const b2Transform& xfB = m_bodyB->GetTransform(); - b2Vec2 pA = b2Mul(xfA, m_localAnchorA); - b2Vec2 pB = b2Mul(xfB, m_localAnchorB); - - b2Color c1(0.7f, 0.7f, 0.7f); - b2Color c2(0.3f, 0.9f, 0.3f); - b2Color c3(0.9f, 0.3f, 0.3f); - b2Color c4(0.3f, 0.3f, 0.9f); - b2Color c5(0.4f, 0.4f, 0.4f); - - draw->DrawPoint(pA, 5.0f, c4); - draw->DrawPoint(pB, 5.0f, c5); - - float aA = m_bodyA->GetAngle(); - float aB = m_bodyB->GetAngle(); - float angle = aB - aA - m_referenceAngle; - - const float L = 0.5f; - - b2Vec2 r = L * b2Vec2(cosf(angle), sinf(angle)); - draw->DrawSegment(pB, pB + r, c1); - draw->DrawCircle(pB, L, c1); - - if (m_enableLimit) - { - b2Vec2 rlo = L * b2Vec2(cosf(m_lowerAngle), sinf(m_lowerAngle)); - b2Vec2 rhi = L * b2Vec2(cosf(m_upperAngle), sinf(m_upperAngle)); - - draw->DrawSegment(pB, pB + rlo, c2); - draw->DrawSegment(pB, pB + rhi, c3); - } - - b2Color color(0.5f, 0.8f, 0.8f); - draw->DrawSegment(xfA.p, pA, color); - draw->DrawSegment(pA, pB, color); - draw->DrawSegment(xfB.p, pB, color); -} diff --git a/3rdparty/box2d/src/dynamics/b2_weld_joint.cpp b/3rdparty/box2d/src/dynamics/b2_weld_joint.cpp deleted file mode 100644 index df3ee0a3eaf1..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_weld_joint.cpp +++ /dev/null @@ -1,344 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_time_step.h" -#include "box2d/b2_weld_joint.h" - -// Point-to-point constraint -// C = p2 - p1 -// Cdot = v2 - v1 -// = v2 + cross(w2, r2) - v1 - cross(w1, r1) -// J = [-I -r1_skew I r2_skew ] -// Identity used: -// w k % (rx i + ry j) = w * (-ry i + rx j) - -// Angle constraint -// C = angle2 - angle1 - referenceAngle -// Cdot = w2 - w1 -// J = [0 0 -1 0 0 1] -// K = invI1 + invI2 - -void b2WeldJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor) -{ - bodyA = bA; - bodyB = bB; - localAnchorA = bodyA->GetLocalPoint(anchor); - localAnchorB = bodyB->GetLocalPoint(anchor); - referenceAngle = bodyB->GetAngle() - bodyA->GetAngle(); -} - -b2WeldJoint::b2WeldJoint(const b2WeldJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - m_referenceAngle = def->referenceAngle; - m_stiffness = def->stiffness; - m_damping = def->damping; - - m_impulse.SetZero(); -} - -void b2WeldJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - m_rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - m_rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - // J = [-I -r1_skew I r2_skew] - // [ 0 -1 0 1] - // r_skew = [-ry; rx] - - // Matlab - // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x, -r1y*iA-r2y*iB] - // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB, r1x*iA+r2x*iB] - // [ -r1y*iA-r2y*iB, r1x*iA+r2x*iB, iA+iB] - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Mat33 K; - K.ex.x = mA + mB + m_rA.y * m_rA.y * iA + m_rB.y * m_rB.y * iB; - K.ey.x = -m_rA.y * m_rA.x * iA - m_rB.y * m_rB.x * iB; - K.ez.x = -m_rA.y * iA - m_rB.y * iB; - K.ex.y = K.ey.x; - K.ey.y = mA + mB + m_rA.x * m_rA.x * iA + m_rB.x * m_rB.x * iB; - K.ez.y = m_rA.x * iA + m_rB.x * iB; - K.ex.z = K.ez.x; - K.ey.z = K.ez.y; - K.ez.z = iA + iB; - - if (m_stiffness > 0.0f) - { - K.GetInverse22(&m_mass); - - float invM = iA + iB; - - float C = aB - aA - m_referenceAngle; - - // Damping coefficient - float d = m_damping; - - // Spring stiffness - float k = m_stiffness; - - // magic formulas - float h = data.step.dt; - m_gamma = h * (d + h * k); - m_gamma = m_gamma != 0.0f ? 1.0f / m_gamma : 0.0f; - m_bias = C * h * k * m_gamma; - - invM += m_gamma; - m_mass.ez.z = invM != 0.0f ? 1.0f / invM : 0.0f; - } - else if (K.ez.z == 0.0f) - { - K.GetInverse22(&m_mass); - m_gamma = 0.0f; - m_bias = 0.0f; - } - else - { - K.GetSymInverse33(&m_mass); - m_gamma = 0.0f; - m_bias = 0.0f; - } - - if (data.step.warmStarting) - { - // Scale impulses to support a variable time step. - m_impulse *= data.step.dtRatio; - - b2Vec2 P(m_impulse.x, m_impulse.y); - - vA -= mA * P; - wA -= iA * (b2Cross(m_rA, P) + m_impulse.z); - - vB += mB * P; - wB += iB * (b2Cross(m_rB, P) + m_impulse.z); - } - else - { - m_impulse.SetZero(); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2WeldJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - if (m_stiffness > 0.0f) - { - float Cdot2 = wB - wA; - - float impulse2 = -m_mass.ez.z * (Cdot2 + m_bias + m_gamma * m_impulse.z); - m_impulse.z += impulse2; - - wA -= iA * impulse2; - wB += iB * impulse2; - - b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); - - b2Vec2 impulse1 = -b2Mul22(m_mass, Cdot1); - m_impulse.x += impulse1.x; - m_impulse.y += impulse1.y; - - b2Vec2 P = impulse1; - - vA -= mA * P; - wA -= iA * b2Cross(m_rA, P); - - vB += mB * P; - wB += iB * b2Cross(m_rB, P); - } - else - { - b2Vec2 Cdot1 = vB + b2Cross(wB, m_rB) - vA - b2Cross(wA, m_rA); - float Cdot2 = wB - wA; - b2Vec3 Cdot(Cdot1.x, Cdot1.y, Cdot2); - - b2Vec3 impulse = -b2Mul(m_mass, Cdot); - m_impulse += impulse; - - b2Vec2 P(impulse.x, impulse.y); - - vA -= mA * P; - wA -= iA * (b2Cross(m_rA, P) + impulse.z); - - vB += mB * P; - wB += iB * (b2Cross(m_rB, P) + impulse.z); - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2WeldJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - b2Rot qA(aA), qB(aB); - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - - float positionError, angularError; - - b2Mat33 K; - K.ex.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; - K.ey.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; - K.ez.x = -rA.y * iA - rB.y * iB; - K.ex.y = K.ey.x; - K.ey.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; - K.ez.y = rA.x * iA + rB.x * iB; - K.ex.z = K.ez.x; - K.ey.z = K.ez.y; - K.ez.z = iA + iB; - - if (m_stiffness > 0.0f) - { - b2Vec2 C1 = cB + rB - cA - rA; - - positionError = C1.Length(); - angularError = 0.0f; - - b2Vec2 P = -K.Solve22(C1); - - cA -= mA * P; - aA -= iA * b2Cross(rA, P); - - cB += mB * P; - aB += iB * b2Cross(rB, P); - } - else - { - b2Vec2 C1 = cB + rB - cA - rA; - float C2 = aB - aA - m_referenceAngle; - - positionError = C1.Length(); - angularError = b2Abs(C2); - - b2Vec3 C(C1.x, C1.y, C2); - - b2Vec3 impulse; - if (K.ez.z > 0.0f) - { - impulse = -K.Solve33(C); - } - else - { - b2Vec2 impulse2 = -K.Solve22(C1); - impulse.Set(impulse2.x, impulse2.y, 0.0f); - } - - b2Vec2 P(impulse.x, impulse.y); - - cA -= mA * P; - aA -= iA * (b2Cross(rA, P) + impulse.z); - - cB += mB * P; - aB += iB * (b2Cross(rB, P) + impulse.z); - } - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return positionError <= b2_linearSlop && angularError <= b2_angularSlop; -} - -b2Vec2 b2WeldJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2WeldJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2WeldJoint::GetReactionForce(float inv_dt) const -{ - b2Vec2 P(m_impulse.x, m_impulse.y); - return inv_dt * P; -} - -float b2WeldJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * m_impulse.z; -} - -void b2WeldJoint::Dump() -{ - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2WeldJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle); - b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); - b2Dump(" jd.damping = %.9g;\n", m_damping); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} diff --git a/3rdparty/box2d/src/dynamics/b2_wheel_joint.cpp b/3rdparty/box2d/src/dynamics/b2_wheel_joint.cpp deleted file mode 100644 index c23b98460973..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_wheel_joint.cpp +++ /dev/null @@ -1,672 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_body.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_wheel_joint.h" -#include "box2d/b2_time_step.h" - -// Linear constraint (point-to-line) -// d = pB - pA = xB + rB - xA - rA -// C = dot(ay, d) -// Cdot = dot(d, cross(wA, ay)) + dot(ay, vB + cross(wB, rB) - vA - cross(wA, rA)) -// = -dot(ay, vA) - dot(cross(d + rA, ay), wA) + dot(ay, vB) + dot(cross(rB, ay), vB) -// J = [-ay, -cross(d + rA, ay), ay, cross(rB, ay)] - -// Spring linear constraint -// C = dot(ax, d) -// Cdot = = -dot(ax, vA) - dot(cross(d + rA, ax), wA) + dot(ax, vB) + dot(cross(rB, ax), vB) -// J = [-ax -cross(d+rA, ax) ax cross(rB, ax)] - -// Motor rotational constraint -// Cdot = wB - wA -// J = [0 0 -1 0 0 1] - -void b2WheelJointDef::Initialize(b2Body* bA, b2Body* bB, const b2Vec2& anchor, const b2Vec2& axis) -{ - bodyA = bA; - bodyB = bB; - localAnchorA = bodyA->GetLocalPoint(anchor); - localAnchorB = bodyB->GetLocalPoint(anchor); - localAxisA = bodyA->GetLocalVector(axis); -} - -b2WheelJoint::b2WheelJoint(const b2WheelJointDef* def) -: b2Joint(def) -{ - m_localAnchorA = def->localAnchorA; - m_localAnchorB = def->localAnchorB; - m_localXAxisA = def->localAxisA; - m_localYAxisA = b2Cross(1.0f, m_localXAxisA); - - m_mass = 0.0f; - m_impulse = 0.0f; - m_motorMass = 0.0f; - m_motorImpulse = 0.0f; - m_springMass = 0.0f; - m_springImpulse = 0.0f; - - m_axialMass = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - m_lowerTranslation = def->lowerTranslation; - m_upperTranslation = def->upperTranslation; - m_enableLimit = def->enableLimit; - - m_maxMotorTorque = def->maxMotorTorque; - m_motorSpeed = def->motorSpeed; - m_enableMotor = def->enableMotor; - - m_bias = 0.0f; - m_gamma = 0.0f; - - m_ax.SetZero(); - m_ay.SetZero(); - - m_stiffness = def->stiffness; - m_damping = def->damping; -} - -void b2WheelJoint::InitVelocityConstraints(const b2SolverData& data) -{ - m_indexA = m_bodyA->m_islandIndex; - m_indexB = m_bodyB->m_islandIndex; - m_localCenterA = m_bodyA->m_sweep.localCenter; - m_localCenterB = m_bodyB->m_sweep.localCenter; - m_invMassA = m_bodyA->m_invMass; - m_invMassB = m_bodyB->m_invMass; - m_invIA = m_bodyA->m_invI; - m_invIB = m_bodyB->m_invI; - - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - b2Rot qA(aA), qB(aB); - - // Compute the effective masses. - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 d = cB + rB - cA - rA; - - // Point to line constraint - { - m_ay = b2Mul(qA, m_localYAxisA); - m_sAy = b2Cross(d + rA, m_ay); - m_sBy = b2Cross(rB, m_ay); - - m_mass = mA + mB + iA * m_sAy * m_sAy + iB * m_sBy * m_sBy; - - if (m_mass > 0.0f) - { - m_mass = 1.0f / m_mass; - } - } - - // Spring constraint - m_ax = b2Mul(qA, m_localXAxisA); - m_sAx = b2Cross(d + rA, m_ax); - m_sBx = b2Cross(rB, m_ax); - - const float invMass = mA + mB + iA * m_sAx * m_sAx + iB * m_sBx * m_sBx; - if (invMass > 0.0f) - { - m_axialMass = 1.0f / invMass; - } - else - { - m_axialMass = 0.0f; - } - - m_springMass = 0.0f; - m_bias = 0.0f; - m_gamma = 0.0f; - - if (m_stiffness > 0.0f && invMass > 0.0f) - { - m_springMass = 1.0f / invMass; - - float C = b2Dot(d, m_ax); - - // magic formulas - float h = data.step.dt; - m_gamma = h * (m_damping + h * m_stiffness); - if (m_gamma > 0.0f) - { - m_gamma = 1.0f / m_gamma; - } - - m_bias = C * h * m_stiffness * m_gamma; - - m_springMass = invMass + m_gamma; - if (m_springMass > 0.0f) - { - m_springMass = 1.0f / m_springMass; - } - } - else - { - m_springImpulse = 0.0f; - } - - if (m_enableLimit) - { - m_translation = b2Dot(m_ax, d); - } - else - { - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - if (m_enableMotor) - { - m_motorMass = iA + iB; - if (m_motorMass > 0.0f) - { - m_motorMass = 1.0f / m_motorMass; - } - } - else - { - m_motorMass = 0.0f; - m_motorImpulse = 0.0f; - } - - if (data.step.warmStarting) - { - // Account for variable time step. - m_impulse *= data.step.dtRatio; - m_springImpulse *= data.step.dtRatio; - m_motorImpulse *= data.step.dtRatio; - - float axialImpulse = m_springImpulse + m_lowerImpulse - m_upperImpulse; - b2Vec2 P = m_impulse * m_ay + axialImpulse * m_ax; - float LA = m_impulse * m_sAy + axialImpulse * m_sAx + m_motorImpulse; - float LB = m_impulse * m_sBy + axialImpulse * m_sBx + m_motorImpulse; - - vA -= m_invMassA * P; - wA -= m_invIA * LA; - - vB += m_invMassB * P; - wB += m_invIB * LB; - } - else - { - m_impulse = 0.0f; - m_springImpulse = 0.0f; - m_motorImpulse = 0.0f; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -void b2WheelJoint::SolveVelocityConstraints(const b2SolverData& data) -{ - float mA = m_invMassA, mB = m_invMassB; - float iA = m_invIA, iB = m_invIB; - - b2Vec2 vA = data.velocities[m_indexA].v; - float wA = data.velocities[m_indexA].w; - b2Vec2 vB = data.velocities[m_indexB].v; - float wB = data.velocities[m_indexB].w; - - // Solve spring constraint - { - float Cdot = b2Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA; - float impulse = -m_springMass * (Cdot + m_bias + m_gamma * m_springImpulse); - m_springImpulse += impulse; - - b2Vec2 P = impulse * m_ax; - float LA = impulse * m_sAx; - float LB = impulse * m_sBx; - - vA -= mA * P; - wA -= iA * LA; - - vB += mB * P; - wB += iB * LB; - } - - // Solve rotational motor constraint - { - float Cdot = wB - wA - m_motorSpeed; - float impulse = -m_motorMass * Cdot; - - float oldImpulse = m_motorImpulse; - float maxImpulse = data.step.dt * m_maxMotorTorque; - m_motorImpulse = b2Clamp(m_motorImpulse + impulse, -maxImpulse, maxImpulse); - impulse = m_motorImpulse - oldImpulse; - - wA -= iA * impulse; - wB += iB * impulse; - } - - if (m_enableLimit) - { - // Lower limit - { - float C = m_translation - m_lowerTranslation; - float Cdot = b2Dot(m_ax, vB - vA) + m_sBx * wB - m_sAx * wA; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_lowerImpulse; - m_lowerImpulse = b2Max(m_lowerImpulse + impulse, 0.0f); - impulse = m_lowerImpulse - oldImpulse; - - b2Vec2 P = impulse * m_ax; - float LA = impulse * m_sAx; - float LB = impulse * m_sBx; - - vA -= mA * P; - wA -= iA * LA; - vB += mB * P; - wB += iB * LB; - } - - // Upper limit - // Note: signs are flipped to keep C positive when the constraint is satisfied. - // This also keeps the impulse positive when the limit is active. - { - float C = m_upperTranslation - m_translation; - float Cdot = b2Dot(m_ax, vA - vB) + m_sAx * wA - m_sBx * wB; - float impulse = -m_axialMass * (Cdot + b2Max(C, 0.0f) * data.step.inv_dt); - float oldImpulse = m_upperImpulse; - m_upperImpulse = b2Max(m_upperImpulse + impulse, 0.0f); - impulse = m_upperImpulse - oldImpulse; - - b2Vec2 P = impulse * m_ax; - float LA = impulse * m_sAx; - float LB = impulse * m_sBx; - - vA += mA * P; - wA += iA * LA; - vB -= mB * P; - wB -= iB * LB; - } - } - - // Solve point to line constraint - { - float Cdot = b2Dot(m_ay, vB - vA) + m_sBy * wB - m_sAy * wA; - float impulse = -m_mass * Cdot; - m_impulse += impulse; - - b2Vec2 P = impulse * m_ay; - float LA = impulse * m_sAy; - float LB = impulse * m_sBy; - - vA -= mA * P; - wA -= iA * LA; - - vB += mB * P; - wB += iB * LB; - } - - data.velocities[m_indexA].v = vA; - data.velocities[m_indexA].w = wA; - data.velocities[m_indexB].v = vB; - data.velocities[m_indexB].w = wB; -} - -bool b2WheelJoint::SolvePositionConstraints(const b2SolverData& data) -{ - b2Vec2 cA = data.positions[m_indexA].c; - float aA = data.positions[m_indexA].a; - b2Vec2 cB = data.positions[m_indexB].c; - float aB = data.positions[m_indexB].a; - - float linearError = 0.0f; - - if (m_enableLimit) - { - b2Rot qA(aA), qB(aB); - - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 d = (cB - cA) + rB - rA; - - b2Vec2 ax = b2Mul(qA, m_localXAxisA); - float sAx = b2Cross(d + rA, m_ax); - float sBx = b2Cross(rB, m_ax); - - float C = 0.0f; - float translation = b2Dot(ax, d); - if (b2Abs(m_upperTranslation - m_lowerTranslation) < 2.0f * b2_linearSlop) - { - C = translation; - } - else if (translation <= m_lowerTranslation) - { - C = b2Min(translation - m_lowerTranslation, 0.0f); - } - else if (translation >= m_upperTranslation) - { - C = b2Max(translation - m_upperTranslation, 0.0f); - } - - if (C != 0.0f) - { - - float invMass = m_invMassA + m_invMassB + m_invIA * sAx * sAx + m_invIB * sBx * sBx; - float impulse = 0.0f; - if (invMass != 0.0f) - { - impulse = -C / invMass; - } - - b2Vec2 P = impulse * ax; - float LA = impulse * sAx; - float LB = impulse * sBx; - - cA -= m_invMassA * P; - aA -= m_invIA * LA; - cB += m_invMassB * P; - aB += m_invIB * LB; - - linearError = b2Abs(C); - } - } - - // Solve perpendicular constraint - { - b2Rot qA(aA), qB(aB); - - b2Vec2 rA = b2Mul(qA, m_localAnchorA - m_localCenterA); - b2Vec2 rB = b2Mul(qB, m_localAnchorB - m_localCenterB); - b2Vec2 d = (cB - cA) + rB - rA; - - b2Vec2 ay = b2Mul(qA, m_localYAxisA); - - float sAy = b2Cross(d + rA, ay); - float sBy = b2Cross(rB, ay); - - float C = b2Dot(d, ay); - - float invMass = m_invMassA + m_invMassB + m_invIA * m_sAy * m_sAy + m_invIB * m_sBy * m_sBy; - - float impulse = 0.0f; - if (invMass != 0.0f) - { - impulse = - C / invMass; - } - - b2Vec2 P = impulse * ay; - float LA = impulse * sAy; - float LB = impulse * sBy; - - cA -= m_invMassA * P; - aA -= m_invIA * LA; - cB += m_invMassB * P; - aB += m_invIB * LB; - - linearError = b2Max(linearError, b2Abs(C)); - } - - data.positions[m_indexA].c = cA; - data.positions[m_indexA].a = aA; - data.positions[m_indexB].c = cB; - data.positions[m_indexB].a = aB; - - return linearError <= b2_linearSlop; -} - -b2Vec2 b2WheelJoint::GetAnchorA() const -{ - return m_bodyA->GetWorldPoint(m_localAnchorA); -} - -b2Vec2 b2WheelJoint::GetAnchorB() const -{ - return m_bodyB->GetWorldPoint(m_localAnchorB); -} - -b2Vec2 b2WheelJoint::GetReactionForce(float inv_dt) const -{ - return inv_dt * (m_impulse * m_ay + (m_springImpulse + m_lowerImpulse - m_upperImpulse) * m_ax); -} - -float b2WheelJoint::GetReactionTorque(float inv_dt) const -{ - return inv_dt * m_motorImpulse; -} - -float b2WheelJoint::GetJointTranslation() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - - b2Vec2 pA = bA->GetWorldPoint(m_localAnchorA); - b2Vec2 pB = bB->GetWorldPoint(m_localAnchorB); - b2Vec2 d = pB - pA; - b2Vec2 axis = bA->GetWorldVector(m_localXAxisA); - - float translation = b2Dot(d, axis); - return translation; -} - -float b2WheelJoint::GetJointLinearSpeed() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - - b2Vec2 rA = b2Mul(bA->m_xf.q, m_localAnchorA - bA->m_sweep.localCenter); - b2Vec2 rB = b2Mul(bB->m_xf.q, m_localAnchorB - bB->m_sweep.localCenter); - b2Vec2 p1 = bA->m_sweep.c + rA; - b2Vec2 p2 = bB->m_sweep.c + rB; - b2Vec2 d = p2 - p1; - b2Vec2 axis = b2Mul(bA->m_xf.q, m_localXAxisA); - - b2Vec2 vA = bA->m_linearVelocity; - b2Vec2 vB = bB->m_linearVelocity; - float wA = bA->m_angularVelocity; - float wB = bB->m_angularVelocity; - - float speed = b2Dot(d, b2Cross(wA, axis)) + b2Dot(axis, vB + b2Cross(wB, rB) - vA - b2Cross(wA, rA)); - return speed; -} - -float b2WheelJoint::GetJointAngle() const -{ - b2Body* bA = m_bodyA; - b2Body* bB = m_bodyB; - return bB->m_sweep.a - bA->m_sweep.a; -} - -float b2WheelJoint::GetJointAngularSpeed() const -{ - float wA = m_bodyA->m_angularVelocity; - float wB = m_bodyB->m_angularVelocity; - return wB - wA; -} - -bool b2WheelJoint::IsLimitEnabled() const -{ - return m_enableLimit; -} - -void b2WheelJoint::EnableLimit(bool flag) -{ - if (flag != m_enableLimit) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableLimit = flag; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } -} - -float b2WheelJoint::GetLowerLimit() const -{ - return m_lowerTranslation; -} - -float b2WheelJoint::GetUpperLimit() const -{ - return m_upperTranslation; -} - -void b2WheelJoint::SetLimits(float lower, float upper) -{ - b2Assert(lower <= upper); - if (lower != m_lowerTranslation || upper != m_upperTranslation) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_lowerTranslation = lower; - m_upperTranslation = upper; - m_lowerImpulse = 0.0f; - m_upperImpulse = 0.0f; - } -} - -bool b2WheelJoint::IsMotorEnabled() const -{ - return m_enableMotor; -} - -void b2WheelJoint::EnableMotor(bool flag) -{ - if (flag != m_enableMotor) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_enableMotor = flag; - } -} - -void b2WheelJoint::SetMotorSpeed(float speed) -{ - if (speed != m_motorSpeed) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_motorSpeed = speed; - } -} - -void b2WheelJoint::SetMaxMotorTorque(float torque) -{ - if (torque != m_maxMotorTorque) - { - m_bodyA->SetAwake(true); - m_bodyB->SetAwake(true); - m_maxMotorTorque = torque; - } -} - -float b2WheelJoint::GetMotorTorque(float inv_dt) const -{ - return inv_dt * m_motorImpulse; -} - -void b2WheelJoint::SetStiffness(float stiffness) -{ - m_stiffness = stiffness; -} - -float b2WheelJoint::GetStiffness() const -{ - return m_stiffness; -} - -void b2WheelJoint::SetDamping(float damping) -{ - m_damping = damping; -} - -float b2WheelJoint::GetDamping() const -{ - return m_damping; -} - -void b2WheelJoint::Dump() -{ - // FLT_DECIMAL_DIG == 9 - - int32 indexA = m_bodyA->m_islandIndex; - int32 indexB = m_bodyB->m_islandIndex; - - b2Dump(" b2WheelJointDef jd;\n"); - b2Dump(" jd.bodyA = bodies[%d];\n", indexA); - b2Dump(" jd.bodyB = bodies[%d];\n", indexB); - b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); - b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); - b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); - b2Dump(" jd.localAxisA.Set(%.9g, %.9g);\n", m_localXAxisA.x, m_localXAxisA.y); - b2Dump(" jd.enableMotor = bool(%d);\n", m_enableMotor); - b2Dump(" jd.motorSpeed = %.9g;\n", m_motorSpeed); - b2Dump(" jd.maxMotorTorque = %.9g;\n", m_maxMotorTorque); - b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); - b2Dump(" jd.damping = %.9g;\n", m_damping); - b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); -} - -/// -void b2WheelJoint::Draw(b2Draw* draw) const -{ - const b2Transform& xfA = m_bodyA->GetTransform(); - const b2Transform& xfB = m_bodyB->GetTransform(); - b2Vec2 pA = b2Mul(xfA, m_localAnchorA); - b2Vec2 pB = b2Mul(xfB, m_localAnchorB); - - b2Vec2 axis = b2Mul(xfA.q, m_localXAxisA); - - b2Color c1(0.7f, 0.7f, 0.7f); - b2Color c2(0.3f, 0.9f, 0.3f); - b2Color c3(0.9f, 0.3f, 0.3f); - b2Color c4(0.3f, 0.3f, 0.9f); - b2Color c5(0.4f, 0.4f, 0.4f); - - draw->DrawSegment(pA, pB, c5); - - if (m_enableLimit) - { - b2Vec2 lower = pA + m_lowerTranslation * axis; - b2Vec2 upper = pA + m_upperTranslation * axis; - b2Vec2 perp = b2Mul(xfA.q, m_localYAxisA); - draw->DrawSegment(lower, upper, c1); - draw->DrawSegment(lower - 0.5f * perp, lower + 0.5f * perp, c2); - draw->DrawSegment(upper - 0.5f * perp, upper + 0.5f * perp, c3); - } - else - { - draw->DrawSegment(pA - 1.0f * axis, pA + 1.0f * axis, c1); - } - - draw->DrawPoint(pA, 5.0f, c1); - draw->DrawPoint(pB, 5.0f, c4); -} diff --git a/3rdparty/box2d/src/dynamics/b2_world.cpp b/3rdparty/box2d/src/dynamics/b2_world.cpp deleted file mode 100644 index 78ec084c800b..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_world.cpp +++ /dev/null @@ -1,1322 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "b2_contact_solver.h" -#include "b2_island.h" - -#include "box2d/b2_body.h" -#include "box2d/b2_broad_phase.h" -#include "box2d/b2_chain_shape.h" -#include "box2d/b2_circle_shape.h" -#include "box2d/b2_collision.h" -#include "box2d/b2_contact.h" -#include "box2d/b2_draw.h" -#include "box2d/b2_edge_shape.h" -#include "box2d/b2_fixture.h" -#include "box2d/b2_polygon_shape.h" -#include "box2d/b2_pulley_joint.h" -#include "box2d/b2_time_of_impact.h" -#include "box2d/b2_timer.h" -#include "box2d/b2_world.h" - -#include - -b2World::b2World(const b2Vec2& gravity) -{ - m_destructionListener = nullptr; - m_debugDraw = nullptr; - - m_bodyList = nullptr; - m_jointList = nullptr; - - m_bodyCount = 0; - m_jointCount = 0; - - m_warmStarting = true; - m_continuousPhysics = true; - m_subStepping = false; - - m_stepComplete = true; - - m_allowSleep = true; - m_gravity = gravity; - - m_newContacts = false; - m_locked = false; - m_clearForces = true; - - m_inv_dt0 = 0.0f; - - m_contactManager.m_allocator = &m_blockAllocator; - - memset(&m_profile, 0, sizeof(b2Profile)); -} - -b2World::~b2World() -{ - // Some shapes allocate using b2Alloc. - b2Body* b = m_bodyList; - while (b) - { - b2Body* bNext = b->m_next; - - b2Fixture* f = b->m_fixtureList; - while (f) - { - b2Fixture* fNext = f->m_next; - f->m_proxyCount = 0; - f->Destroy(&m_blockAllocator); - f = fNext; - } - - b = bNext; - } -} - -void b2World::SetDestructionListener(b2DestructionListener* listener) -{ - m_destructionListener = listener; -} - -void b2World::SetContactFilter(b2ContactFilter* filter) -{ - m_contactManager.m_contactFilter = filter; -} - -void b2World::SetContactListener(b2ContactListener* listener) -{ - m_contactManager.m_contactListener = listener; -} - -void b2World::SetDebugDraw(b2Draw* debugDraw) -{ - m_debugDraw = debugDraw; -} - -b2Body* b2World::CreateBody(const b2BodyDef* def) -{ - b2Assert(IsLocked() == false); - if (IsLocked()) - { - return nullptr; - } - - void* mem = m_blockAllocator.Allocate(sizeof(b2Body)); - b2Body* b = new (mem) b2Body(def, this); - - // Add to world doubly linked list. - b->m_prev = nullptr; - b->m_next = m_bodyList; - if (m_bodyList) - { - m_bodyList->m_prev = b; - } - m_bodyList = b; - ++m_bodyCount; - - return b; -} - -void b2World::DestroyBody(b2Body* b) -{ - b2Assert(m_bodyCount > 0); - b2Assert(IsLocked() == false); - if (IsLocked()) - { - return; - } - - // Delete the attached joints. - b2JointEdge* je = b->m_jointList; - while (je) - { - b2JointEdge* je0 = je; - je = je->next; - - if (m_destructionListener) - { - m_destructionListener->SayGoodbye(je0->joint); - } - - DestroyJoint(je0->joint); - - b->m_jointList = je; - } - b->m_jointList = nullptr; - - // Delete the attached contacts. - b2ContactEdge* ce = b->m_contactList; - while (ce) - { - b2ContactEdge* ce0 = ce; - ce = ce->next; - m_contactManager.Destroy(ce0->contact); - } - b->m_contactList = nullptr; - - // Delete the attached fixtures. This destroys broad-phase proxies. - b2Fixture* f = b->m_fixtureList; - while (f) - { - b2Fixture* f0 = f; - f = f->m_next; - - if (m_destructionListener) - { - m_destructionListener->SayGoodbye(f0); - } - - f0->DestroyProxies(&m_contactManager.m_broadPhase); - f0->Destroy(&m_blockAllocator); - f0->~b2Fixture(); - m_blockAllocator.Free(f0, sizeof(b2Fixture)); - - b->m_fixtureList = f; - b->m_fixtureCount -= 1; - } - b->m_fixtureList = nullptr; - b->m_fixtureCount = 0; - - // Remove world body list. - if (b->m_prev) - { - b->m_prev->m_next = b->m_next; - } - - if (b->m_next) - { - b->m_next->m_prev = b->m_prev; - } - - if (b == m_bodyList) - { - m_bodyList = b->m_next; - } - - --m_bodyCount; - b->~b2Body(); - m_blockAllocator.Free(b, sizeof(b2Body)); -} - -b2Joint* b2World::CreateJoint(const b2JointDef* def) -{ - b2Assert(IsLocked() == false); - if (IsLocked()) - { - return nullptr; - } - - b2Joint* j = b2Joint::Create(def, &m_blockAllocator); - - // Connect to the world list. - j->m_prev = nullptr; - j->m_next = m_jointList; - if (m_jointList) - { - m_jointList->m_prev = j; - } - m_jointList = j; - ++m_jointCount; - - // Connect to the bodies' doubly linked lists. - j->m_edgeA.joint = j; - j->m_edgeA.other = j->m_bodyB; - j->m_edgeA.prev = nullptr; - j->m_edgeA.next = j->m_bodyA->m_jointList; - if (j->m_bodyA->m_jointList) j->m_bodyA->m_jointList->prev = &j->m_edgeA; - j->m_bodyA->m_jointList = &j->m_edgeA; - - j->m_edgeB.joint = j; - j->m_edgeB.other = j->m_bodyA; - j->m_edgeB.prev = nullptr; - j->m_edgeB.next = j->m_bodyB->m_jointList; - if (j->m_bodyB->m_jointList) j->m_bodyB->m_jointList->prev = &j->m_edgeB; - j->m_bodyB->m_jointList = &j->m_edgeB; - - b2Body* bodyA = def->bodyA; - b2Body* bodyB = def->bodyB; - - // If the joint prevents collisions, then flag any contacts for filtering. - if (def->collideConnected == false) - { - b2ContactEdge* edge = bodyB->GetContactList(); - while (edge) - { - if (edge->other == bodyA) - { - // Flag the contact for filtering at the next time step (where either - // body is awake). - edge->contact->FlagForFiltering(); - } - - edge = edge->next; - } - } - - // Note: creating a joint doesn't wake the bodies. - - return j; -} - -void b2World::DestroyJoint(b2Joint* j) -{ - b2Assert(IsLocked() == false); - if (IsLocked()) - { - return; - } - - bool collideConnected = j->m_collideConnected; - - // Remove from the doubly linked list. - if (j->m_prev) - { - j->m_prev->m_next = j->m_next; - } - - if (j->m_next) - { - j->m_next->m_prev = j->m_prev; - } - - if (j == m_jointList) - { - m_jointList = j->m_next; - } - - // Disconnect from island graph. - b2Body* bodyA = j->m_bodyA; - b2Body* bodyB = j->m_bodyB; - - // Wake up connected bodies. - bodyA->SetAwake(true); - bodyB->SetAwake(true); - - // Remove from body 1. - if (j->m_edgeA.prev) - { - j->m_edgeA.prev->next = j->m_edgeA.next; - } - - if (j->m_edgeA.next) - { - j->m_edgeA.next->prev = j->m_edgeA.prev; - } - - if (&j->m_edgeA == bodyA->m_jointList) - { - bodyA->m_jointList = j->m_edgeA.next; - } - - j->m_edgeA.prev = nullptr; - j->m_edgeA.next = nullptr; - - // Remove from body 2 - if (j->m_edgeB.prev) - { - j->m_edgeB.prev->next = j->m_edgeB.next; - } - - if (j->m_edgeB.next) - { - j->m_edgeB.next->prev = j->m_edgeB.prev; - } - - if (&j->m_edgeB == bodyB->m_jointList) - { - bodyB->m_jointList = j->m_edgeB.next; - } - - j->m_edgeB.prev = nullptr; - j->m_edgeB.next = nullptr; - - b2Joint::Destroy(j, &m_blockAllocator); - - b2Assert(m_jointCount > 0); - --m_jointCount; - - // If the joint prevents collisions, then flag any contacts for filtering. - if (collideConnected == false) - { - b2ContactEdge* edge = bodyB->GetContactList(); - while (edge) - { - if (edge->other == bodyA) - { - // Flag the contact for filtering at the next time step (where either - // body is awake). - edge->contact->FlagForFiltering(); - } - - edge = edge->next; - } - } -} - -// -void b2World::SetAllowSleeping(bool flag) -{ - if (flag == m_allowSleep) - { - return; - } - - m_allowSleep = flag; - if (m_allowSleep == false) - { - for (b2Body* b = m_bodyList; b; b = b->m_next) - { - b->SetAwake(true); - } - } -} - -// Find islands, integrate and solve constraints, solve position constraints -void b2World::Solve(const b2TimeStep& step) -{ - m_profile.solveInit = 0.0f; - m_profile.solveVelocity = 0.0f; - m_profile.solvePosition = 0.0f; - - // Size the island for the worst case. - b2Island island(m_bodyCount, - m_contactManager.m_contactCount, - m_jointCount, - &m_stackAllocator, - m_contactManager.m_contactListener); - - // Clear all the island flags. - for (b2Body* b = m_bodyList; b; b = b->m_next) - { - b->m_flags &= ~b2Body::e_islandFlag; - } - for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) - { - c->m_flags &= ~b2Contact::e_islandFlag; - } - for (b2Joint* j = m_jointList; j; j = j->m_next) - { - j->m_islandFlag = false; - } - - // Build and simulate all awake islands. - int32 stackSize = m_bodyCount; - b2Body** stack = (b2Body**)m_stackAllocator.Allocate(stackSize * sizeof(b2Body*)); - for (b2Body* seed = m_bodyList; seed; seed = seed->m_next) - { - if (seed->m_flags & b2Body::e_islandFlag) - { - continue; - } - - if (seed->IsAwake() == false || seed->IsEnabled() == false) - { - continue; - } - - // The seed can be dynamic or kinematic. - if (seed->GetType() == b2_staticBody) - { - continue; - } - - // Reset island and stack. - island.Clear(); - int32 stackCount = 0; - stack[stackCount++] = seed; - seed->m_flags |= b2Body::e_islandFlag; - - // Perform a depth first search (DFS) on the constraint graph. - while (stackCount > 0) - { - // Grab the next body off the stack and add it to the island. - b2Body* b = stack[--stackCount]; - b2Assert(b->IsEnabled() == true); - island.Add(b); - - // To keep islands as small as possible, we don't - // propagate islands across static bodies. - if (b->GetType() == b2_staticBody) - { - continue; - } - - // Make sure the body is awake (without resetting sleep timer). - b->m_flags |= b2Body::e_awakeFlag; - - // Search all contacts connected to this body. - for (b2ContactEdge* ce = b->m_contactList; ce; ce = ce->next) - { - b2Contact* contact = ce->contact; - - // Has this contact already been added to an island? - if (contact->m_flags & b2Contact::e_islandFlag) - { - continue; - } - - // Is this contact solid and touching? - if (contact->IsEnabled() == false || - contact->IsTouching() == false) - { - continue; - } - - // Skip sensors. - bool sensorA = contact->m_fixtureA->m_isSensor; - bool sensorB = contact->m_fixtureB->m_isSensor; - if (sensorA || sensorB) - { - continue; - } - - island.Add(contact); - contact->m_flags |= b2Contact::e_islandFlag; - - b2Body* other = ce->other; - - // Was the other body already added to this island? - if (other->m_flags & b2Body::e_islandFlag) - { - continue; - } - - b2Assert(stackCount < stackSize); - stack[stackCount++] = other; - other->m_flags |= b2Body::e_islandFlag; - } - - // Search all joints connect to this body. - for (b2JointEdge* je = b->m_jointList; je; je = je->next) - { - if (je->joint->m_islandFlag == true) - { - continue; - } - - b2Body* other = je->other; - - // Don't simulate joints connected to disabled bodies. - if (other->IsEnabled() == false) - { - continue; - } - - island.Add(je->joint); - je->joint->m_islandFlag = true; - - if (other->m_flags & b2Body::e_islandFlag) - { - continue; - } - - b2Assert(stackCount < stackSize); - stack[stackCount++] = other; - other->m_flags |= b2Body::e_islandFlag; - } - } - - b2Profile profile; - island.Solve(&profile, step, m_gravity, m_allowSleep); - m_profile.solveInit += profile.solveInit; - m_profile.solveVelocity += profile.solveVelocity; - m_profile.solvePosition += profile.solvePosition; - - // Post solve cleanup. - for (int32 i = 0; i < island.m_bodyCount; ++i) - { - // Allow static bodies to participate in other islands. - b2Body* b = island.m_bodies[i]; - if (b->GetType() == b2_staticBody) - { - b->m_flags &= ~b2Body::e_islandFlag; - } - } - } - - m_stackAllocator.Free(stack); - - { - b2Timer timer; - // Synchronize fixtures, check for out of range bodies. - for (b2Body* b = m_bodyList; b; b = b->GetNext()) - { - // If a body was not in an island then it did not move. - if ((b->m_flags & b2Body::e_islandFlag) == 0) - { - continue; - } - - if (b->GetType() == b2_staticBody) - { - continue; - } - - // Update fixtures (for broad-phase). - b->SynchronizeFixtures(); - } - - // Look for new contacts. - m_contactManager.FindNewContacts(); - m_profile.broadphase = timer.GetMilliseconds(); - } -} - -// Find TOI contacts and solve them. -void b2World::SolveTOI(const b2TimeStep& step) -{ - b2Island island(2 * b2_maxTOIContacts, b2_maxTOIContacts, 0, &m_stackAllocator, m_contactManager.m_contactListener); - - if (m_stepComplete) - { - for (b2Body* b = m_bodyList; b; b = b->m_next) - { - b->m_flags &= ~b2Body::e_islandFlag; - b->m_sweep.alpha0 = 0.0f; - } - - for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) - { - // Invalidate TOI - c->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); - c->m_toiCount = 0; - c->m_toi = 1.0f; - } - } - - // Find TOI events and solve them. - for (;;) - { - // Find the first TOI. - b2Contact* minContact = nullptr; - float minAlpha = 1.0f; - - for (b2Contact* c = m_contactManager.m_contactList; c; c = c->m_next) - { - // Is this contact disabled? - if (c->IsEnabled() == false) - { - continue; - } - - // Prevent excessive sub-stepping. - if (c->m_toiCount > b2_maxSubSteps) - { - continue; - } - - float alpha = 1.0f; - if (c->m_flags & b2Contact::e_toiFlag) - { - // This contact has a valid cached TOI. - alpha = c->m_toi; - } - else - { - b2Fixture* fA = c->GetFixtureA(); - b2Fixture* fB = c->GetFixtureB(); - - // Is there a sensor? - if (fA->IsSensor() || fB->IsSensor()) - { - continue; - } - - b2Body* bA = fA->GetBody(); - b2Body* bB = fB->GetBody(); - - b2BodyType typeA = bA->m_type; - b2BodyType typeB = bB->m_type; - b2Assert(typeA == b2_dynamicBody || typeB == b2_dynamicBody); - - bool activeA = bA->IsAwake() && typeA != b2_staticBody; - bool activeB = bB->IsAwake() && typeB != b2_staticBody; - - // Is at least one body active (awake and dynamic or kinematic)? - if (activeA == false && activeB == false) - { - continue; - } - - bool collideA = bA->IsBullet() || typeA != b2_dynamicBody; - bool collideB = bB->IsBullet() || typeB != b2_dynamicBody; - - // Are these two non-bullet dynamic bodies? - if (collideA == false && collideB == false) - { - continue; - } - - // Compute the TOI for this contact. - // Put the sweeps onto the same time interval. - float alpha0 = bA->m_sweep.alpha0; - - if (bA->m_sweep.alpha0 < bB->m_sweep.alpha0) - { - alpha0 = bB->m_sweep.alpha0; - bA->m_sweep.Advance(alpha0); - } - else if (bB->m_sweep.alpha0 < bA->m_sweep.alpha0) - { - alpha0 = bA->m_sweep.alpha0; - bB->m_sweep.Advance(alpha0); - } - - b2Assert(alpha0 < 1.0f); - - int32 indexA = c->GetChildIndexA(); - int32 indexB = c->GetChildIndexB(); - - // Compute the time of impact in interval [0, minTOI] - b2TOIInput input; - input.proxyA.Set(fA->GetShape(), indexA); - input.proxyB.Set(fB->GetShape(), indexB); - input.sweepA = bA->m_sweep; - input.sweepB = bB->m_sweep; - input.tMax = 1.0f; - - b2TOIOutput output; - b2TimeOfImpact(&output, &input); - - // Beta is the fraction of the remaining portion of the . - float beta = output.t; - if (output.state == b2TOIOutput::e_touching) - { - alpha = b2Min(alpha0 + (1.0f - alpha0) * beta, 1.0f); - } - else - { - alpha = 1.0f; - } - - c->m_toi = alpha; - c->m_flags |= b2Contact::e_toiFlag; - } - - if (alpha < minAlpha) - { - // This is the minimum TOI found so far. - minContact = c; - minAlpha = alpha; - } - } - - if (minContact == nullptr || 1.0f - 10.0f * b2_epsilon < minAlpha) - { - // No more TOI events. Done! - m_stepComplete = true; - break; - } - - // Advance the bodies to the TOI. - b2Fixture* fA = minContact->GetFixtureA(); - b2Fixture* fB = minContact->GetFixtureB(); - b2Body* bA = fA->GetBody(); - b2Body* bB = fB->GetBody(); - - b2Sweep backup1 = bA->m_sweep; - b2Sweep backup2 = bB->m_sweep; - - bA->Advance(minAlpha); - bB->Advance(minAlpha); - - // The TOI contact likely has some new contact points. - minContact->Update(m_contactManager.m_contactListener); - minContact->m_flags &= ~b2Contact::e_toiFlag; - ++minContact->m_toiCount; - - // Is the contact solid? - if (minContact->IsEnabled() == false || minContact->IsTouching() == false) - { - // Restore the sweeps. - minContact->SetEnabled(false); - bA->m_sweep = backup1; - bB->m_sweep = backup2; - bA->SynchronizeTransform(); - bB->SynchronizeTransform(); - continue; - } - - bA->SetAwake(true); - bB->SetAwake(true); - - // Build the island - island.Clear(); - island.Add(bA); - island.Add(bB); - island.Add(minContact); - - bA->m_flags |= b2Body::e_islandFlag; - bB->m_flags |= b2Body::e_islandFlag; - minContact->m_flags |= b2Contact::e_islandFlag; - - // Get contacts on bodyA and bodyB. - b2Body* bodies[2] = {bA, bB}; - for (int32 i = 0; i < 2; ++i) - { - b2Body* body = bodies[i]; - if (body->m_type == b2_dynamicBody) - { - for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next) - { - if (island.m_bodyCount == island.m_bodyCapacity) - { - break; - } - - if (island.m_contactCount == island.m_contactCapacity) - { - break; - } - - b2Contact* contact = ce->contact; - - // Has this contact already been added to the island? - if (contact->m_flags & b2Contact::e_islandFlag) - { - continue; - } - - // Only add static, kinematic, or bullet bodies. - b2Body* other = ce->other; - if (other->m_type == b2_dynamicBody && - body->IsBullet() == false && other->IsBullet() == false) - { - continue; - } - - // Skip sensors. - bool sensorA = contact->m_fixtureA->m_isSensor; - bool sensorB = contact->m_fixtureB->m_isSensor; - if (sensorA || sensorB) - { - continue; - } - - // Tentatively advance the body to the TOI. - b2Sweep backup = other->m_sweep; - if ((other->m_flags & b2Body::e_islandFlag) == 0) - { - other->Advance(minAlpha); - } - - // Update the contact points - contact->Update(m_contactManager.m_contactListener); - - // Was the contact disabled by the user? - if (contact->IsEnabled() == false) - { - other->m_sweep = backup; - other->SynchronizeTransform(); - continue; - } - - // Are there contact points? - if (contact->IsTouching() == false) - { - other->m_sweep = backup; - other->SynchronizeTransform(); - continue; - } - - // Add the contact to the island - contact->m_flags |= b2Contact::e_islandFlag; - island.Add(contact); - - // Has the other body already been added to the island? - if (other->m_flags & b2Body::e_islandFlag) - { - continue; - } - - // Add the other body to the island. - other->m_flags |= b2Body::e_islandFlag; - - if (other->m_type != b2_staticBody) - { - other->SetAwake(true); - } - - island.Add(other); - } - } - } - - b2TimeStep subStep; - subStep.dt = (1.0f - minAlpha) * step.dt; - subStep.inv_dt = 1.0f / subStep.dt; - subStep.dtRatio = 1.0f; - subStep.positionIterations = 20; - subStep.velocityIterations = step.velocityIterations; - subStep.warmStarting = false; - island.SolveTOI(subStep, bA->m_islandIndex, bB->m_islandIndex); - - // Reset island flags and synchronize broad-phase proxies. - for (int32 i = 0; i < island.m_bodyCount; ++i) - { - b2Body* body = island.m_bodies[i]; - body->m_flags &= ~b2Body::e_islandFlag; - - if (body->m_type != b2_dynamicBody) - { - continue; - } - - body->SynchronizeFixtures(); - - // Invalidate all contact TOIs on this displaced body. - for (b2ContactEdge* ce = body->m_contactList; ce; ce = ce->next) - { - ce->contact->m_flags &= ~(b2Contact::e_toiFlag | b2Contact::e_islandFlag); - } - } - - // Commit fixture proxy movements to the broad-phase so that new contacts are created. - // Also, some contacts can be destroyed. - m_contactManager.FindNewContacts(); - - if (m_subStepping) - { - m_stepComplete = false; - break; - } - } -} - -void b2World::Step(float dt, int32 velocityIterations, int32 positionIterations) -{ - b2Timer stepTimer; - - // If new fixtures were added, we need to find the new contacts. - if (m_newContacts) - { - m_contactManager.FindNewContacts(); - m_newContacts = false; - } - - m_locked = true; - - b2TimeStep step; - step.dt = dt; - step.velocityIterations = velocityIterations; - step.positionIterations = positionIterations; - if (dt > 0.0f) - { - step.inv_dt = 1.0f / dt; - } - else - { - step.inv_dt = 0.0f; - } - - step.dtRatio = m_inv_dt0 * dt; - - step.warmStarting = m_warmStarting; - - // Update contacts. This is where some contacts are destroyed. - { - b2Timer timer; - m_contactManager.Collide(); - m_profile.collide = timer.GetMilliseconds(); - } - - // Integrate velocities, solve velocity constraints, and integrate positions. - if (m_stepComplete && step.dt > 0.0f) - { - b2Timer timer; - Solve(step); - m_profile.solve = timer.GetMilliseconds(); - } - - // Handle TOI events. - if (m_continuousPhysics && step.dt > 0.0f) - { - b2Timer timer; - SolveTOI(step); - m_profile.solveTOI = timer.GetMilliseconds(); - } - - if (step.dt > 0.0f) - { - m_inv_dt0 = step.inv_dt; - } - - if (m_clearForces) - { - ClearForces(); - } - - m_locked = false; - - m_profile.step = stepTimer.GetMilliseconds(); -} - -void b2World::ClearForces() -{ - for (b2Body* body = m_bodyList; body; body = body->GetNext()) - { - body->m_force.SetZero(); - body->m_torque = 0.0f; - } -} - -struct b2WorldQueryWrapper -{ - bool QueryCallback(int32 proxyId) - { - b2FixtureProxy* proxy = (b2FixtureProxy*)broadPhase->GetUserData(proxyId); - return callback->ReportFixture(proxy->fixture); - } - - const b2BroadPhase* broadPhase; - b2QueryCallback* callback; -}; - -void b2World::QueryAABB(b2QueryCallback* callback, const b2AABB& aabb) const -{ - b2WorldQueryWrapper wrapper; - wrapper.broadPhase = &m_contactManager.m_broadPhase; - wrapper.callback = callback; - m_contactManager.m_broadPhase.Query(&wrapper, aabb); -} - -struct b2WorldRayCastWrapper -{ - float RayCastCallback(const b2RayCastInput& input, int32 proxyId) - { - void* userData = broadPhase->GetUserData(proxyId); - b2FixtureProxy* proxy = (b2FixtureProxy*)userData; - b2Fixture* fixture = proxy->fixture; - int32 index = proxy->childIndex; - b2RayCastOutput output; - bool hit = fixture->RayCast(&output, input, index); - - if (hit) - { - float fraction = output.fraction; - b2Vec2 point = (1.0f - fraction) * input.p1 + fraction * input.p2; - return callback->ReportFixture(fixture, point, output.normal, fraction); - } - - return input.maxFraction; - } - - const b2BroadPhase* broadPhase; - b2RayCastCallback* callback; -}; - -void b2World::RayCast(b2RayCastCallback* callback, const b2Vec2& point1, const b2Vec2& point2) const -{ - b2WorldRayCastWrapper wrapper; - wrapper.broadPhase = &m_contactManager.m_broadPhase; - wrapper.callback = callback; - b2RayCastInput input; - input.maxFraction = 1.0f; - input.p1 = point1; - input.p2 = point2; - m_contactManager.m_broadPhase.RayCast(&wrapper, input); -} - -void b2World::DrawShape(b2Fixture* fixture, const b2Transform& xf, const b2Color& color) -{ - switch (fixture->GetType()) - { - case b2Shape::e_circle: - { - b2CircleShape* circle = (b2CircleShape*)fixture->GetShape(); - - b2Vec2 center = b2Mul(xf, circle->m_p); - float radius = circle->m_radius; - b2Vec2 axis = b2Mul(xf.q, b2Vec2(1.0f, 0.0f)); - - m_debugDraw->DrawSolidCircle(center, radius, axis, color); - } - break; - - case b2Shape::e_edge: - { - b2EdgeShape* edge = (b2EdgeShape*)fixture->GetShape(); - b2Vec2 v1 = b2Mul(xf, edge->m_vertex1); - b2Vec2 v2 = b2Mul(xf, edge->m_vertex2); - m_debugDraw->DrawSegment(v1, v2, color); - - if (edge->m_oneSided == false) - { - m_debugDraw->DrawPoint(v1, 4.0f, color); - m_debugDraw->DrawPoint(v2, 4.0f, color); - } - } - break; - - case b2Shape::e_chain: - { - b2ChainShape* chain = (b2ChainShape*)fixture->GetShape(); - int32 count = chain->m_count; - const b2Vec2* vertices = chain->m_vertices; - - b2Vec2 v1 = b2Mul(xf, vertices[0]); - for (int32 i = 1; i < count; ++i) - { - b2Vec2 v2 = b2Mul(xf, vertices[i]); - m_debugDraw->DrawSegment(v1, v2, color); - v1 = v2; - } - } - break; - - case b2Shape::e_polygon: - { - b2PolygonShape* poly = (b2PolygonShape*)fixture->GetShape(); - int32 vertexCount = poly->m_count; - b2Assert(vertexCount <= b2_maxPolygonVertices); - b2Vec2 vertices[b2_maxPolygonVertices]; - - for (int32 i = 0; i < vertexCount; ++i) - { - vertices[i] = b2Mul(xf, poly->m_vertices[i]); - } - - m_debugDraw->DrawSolidPolygon(vertices, vertexCount, color); - } - break; - - default: - break; - } -} - -void b2World::DebugDraw() -{ - if (m_debugDraw == nullptr) - { - return; - } - - uint32 flags = m_debugDraw->GetFlags(); - - if (flags & b2Draw::e_shapeBit) - { - for (b2Body* b = m_bodyList; b; b = b->GetNext()) - { - const b2Transform& xf = b->GetTransform(); - for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) - { - if (b->GetType() == b2_dynamicBody && b->m_mass == 0.0f) - { - // Bad body - DrawShape(f, xf, b2Color(1.0f, 0.0f, 0.0f)); - } - else if (b->IsEnabled() == false) - { - DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.3f)); - } - else if (b->GetType() == b2_staticBody) - { - DrawShape(f, xf, b2Color(0.5f, 0.9f, 0.5f)); - } - else if (b->GetType() == b2_kinematicBody) - { - DrawShape(f, xf, b2Color(0.5f, 0.5f, 0.9f)); - } - else if (b->IsAwake() == false) - { - DrawShape(f, xf, b2Color(0.6f, 0.6f, 0.6f)); - } - else - { - DrawShape(f, xf, b2Color(0.9f, 0.7f, 0.7f)); - } - } - } - } - - if (flags & b2Draw::e_jointBit) - { - for (b2Joint* j = m_jointList; j; j = j->GetNext()) - { - j->Draw(m_debugDraw); - } - } - - if (flags & b2Draw::e_pairBit) - { - b2Color color(0.3f, 0.9f, 0.9f); - for (b2Contact* c = m_contactManager.m_contactList; c; c = c->GetNext()) - { - b2Fixture* fixtureA = c->GetFixtureA(); - b2Fixture* fixtureB = c->GetFixtureB(); - int32 indexA = c->GetChildIndexA(); - int32 indexB = c->GetChildIndexB(); - b2Vec2 cA = fixtureA->GetAABB(indexA).GetCenter(); - b2Vec2 cB = fixtureB->GetAABB(indexB).GetCenter(); - - m_debugDraw->DrawSegment(cA, cB, color); - } - } - - if (flags & b2Draw::e_aabbBit) - { - b2Color color(0.9f, 0.3f, 0.9f); - b2BroadPhase* bp = &m_contactManager.m_broadPhase; - - for (b2Body* b = m_bodyList; b; b = b->GetNext()) - { - if (b->IsEnabled() == false) - { - continue; - } - - for (b2Fixture* f = b->GetFixtureList(); f; f = f->GetNext()) - { - for (int32 i = 0; i < f->m_proxyCount; ++i) - { - b2FixtureProxy* proxy = f->m_proxies + i; - b2AABB aabb = bp->GetFatAABB(proxy->proxyId); - b2Vec2 vs[4]; - vs[0].Set(aabb.lowerBound.x, aabb.lowerBound.y); - vs[1].Set(aabb.upperBound.x, aabb.lowerBound.y); - vs[2].Set(aabb.upperBound.x, aabb.upperBound.y); - vs[3].Set(aabb.lowerBound.x, aabb.upperBound.y); - - m_debugDraw->DrawPolygon(vs, 4, color); - } - } - } - } - - if (flags & b2Draw::e_centerOfMassBit) - { - for (b2Body* b = m_bodyList; b; b = b->GetNext()) - { - b2Transform xf = b->GetTransform(); - xf.p = b->GetWorldCenter(); - m_debugDraw->DrawTransform(xf); - } - } -} - -int32 b2World::GetProxyCount() const -{ - return m_contactManager.m_broadPhase.GetProxyCount(); -} - -int32 b2World::GetTreeHeight() const -{ - return m_contactManager.m_broadPhase.GetTreeHeight(); -} - -int32 b2World::GetTreeBalance() const -{ - return m_contactManager.m_broadPhase.GetTreeBalance(); -} - -float b2World::GetTreeQuality() const -{ - return m_contactManager.m_broadPhase.GetTreeQuality(); -} - -void b2World::ShiftOrigin(const b2Vec2& newOrigin) -{ - b2Assert(m_locked == false); - if (m_locked) - { - return; - } - - for (b2Body* b = m_bodyList; b; b = b->m_next) - { - b->m_xf.p -= newOrigin; - b->m_sweep.c0 -= newOrigin; - b->m_sweep.c -= newOrigin; - } - - for (b2Joint* j = m_jointList; j; j = j->m_next) - { - j->ShiftOrigin(newOrigin); - } - - m_contactManager.m_broadPhase.ShiftOrigin(newOrigin); -} - -void b2World::Dump() -{ - if (m_locked) - { - return; - } - - b2OpenDump("box2d_dump.inl"); - - b2Dump("b2Vec2 g(%.9g, %.9g);\n", m_gravity.x, m_gravity.y); - b2Dump("m_world->SetGravity(g);\n"); - - b2Dump("b2Body** bodies = (b2Body**)b2Alloc(%d * sizeof(b2Body*));\n", m_bodyCount); - b2Dump("b2Joint** joints = (b2Joint**)b2Alloc(%d * sizeof(b2Joint*));\n", m_jointCount); - - int32 i = 0; - for (b2Body* b = m_bodyList; b; b = b->m_next) - { - b->m_islandIndex = i; - b->Dump(); - ++i; - } - - i = 0; - for (b2Joint* j = m_jointList; j; j = j->m_next) - { - j->m_index = i; - ++i; - } - - // First pass on joints, skip gear joints. - for (b2Joint* j = m_jointList; j; j = j->m_next) - { - if (j->m_type == e_gearJoint) - { - continue; - } - - b2Dump("{\n"); - j->Dump(); - b2Dump("}\n"); - } - - // Second pass on joints, only gear joints. - for (b2Joint* j = m_jointList; j; j = j->m_next) - { - if (j->m_type != e_gearJoint) - { - continue; - } - - b2Dump("{\n"); - j->Dump(); - b2Dump("}\n"); - } - - b2Dump("b2Free(joints);\n"); - b2Dump("b2Free(bodies);\n"); - b2Dump("joints = nullptr;\n"); - b2Dump("bodies = nullptr;\n"); - - b2CloseDump(); -} diff --git a/3rdparty/box2d/src/dynamics/b2_world_callbacks.cpp b/3rdparty/box2d/src/dynamics/b2_world_callbacks.cpp deleted file mode 100644 index e1583e221b3b..000000000000 --- a/3rdparty/box2d/src/dynamics/b2_world_callbacks.cpp +++ /dev/null @@ -1,40 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_fixture.h" -#include "box2d/b2_world_callbacks.h" - -// Return true if contact calculations should be performed between these two shapes. -// If you implement your own collision filter you may want to build from this implementation. -bool b2ContactFilter::ShouldCollide(b2Fixture* fixtureA, b2Fixture* fixtureB) -{ - const b2Filter& filterA = fixtureA->GetFilterData(); - const b2Filter& filterB = fixtureB->GetFilterData(); - - if (filterA.groupIndex == filterB.groupIndex && filterA.groupIndex != 0) - { - return filterA.groupIndex > 0; - } - - bool collide = (filterA.maskBits & filterB.categoryBits) != 0 && (filterA.categoryBits & filterB.maskBits) != 0; - return collide; -} diff --git a/3rdparty/box2d/src/geometry.c b/3rdparty/box2d/src/geometry.c new file mode 100644 index 000000000000..a6a591909f7c --- /dev/null +++ b/3rdparty/box2d/src/geometry.c @@ -0,0 +1,1028 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constants.h" +#include "shape.h" + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include +#include + +_Static_assert( B2_MAX_POLYGON_VERTICES > 2, "must be 3 or more" ); + +bool b2IsValidRay( const b2RayCastInput* input ) +{ + bool isValid = b2IsValidVec2( input->origin ) && b2IsValidVec2( input->translation ) && + b2IsValidFloat( input->maxFraction ) && 0.0f <= input->maxFraction && input->maxFraction < B2_HUGE; + return isValid; +} + +static b2Vec2 b2ComputePolygonCentroid( const b2Vec2* vertices, int count ) +{ + b2Vec2 center = { 0.0f, 0.0f }; + float area = 0.0f; + + // Get a reference point for forming triangles. + // Use the first vertex to reduce round-off errors. + b2Vec2 origin = vertices[0]; + + const float inv3 = 1.0f / 3.0f; + + for ( int i = 1; i < count - 1; ++i ) + { + // Triangle edges + b2Vec2 e1 = b2Sub( vertices[i], origin ); + b2Vec2 e2 = b2Sub( vertices[i + 1], origin ); + float a = 0.5f * b2Cross( e1, e2 ); + + // Area weighted centroid + center = b2MulAdd( center, a * inv3, b2Add( e1, e2 ) ); + area += a; + } + + B2_ASSERT( area > FLT_EPSILON ); + float invArea = 1.0f / area; + center.x *= invArea; + center.y *= invArea; + + // Restore offset + center = b2Add( origin, center ); + + return center; +} + +b2Polygon b2MakePolygon( const b2Hull* hull, float radius ) +{ + B2_ASSERT( b2ValidateHull( hull ) ); + + if ( hull->count < 3 ) + { + // Handle a bad hull when assertions are disabled + return b2MakeSquare( 0.5f ); + } + + b2Polygon shape = { 0 }; + shape.count = hull->count; + shape.radius = radius; + + // Copy vertices + for ( int i = 0; i < shape.count; ++i ) + { + shape.vertices[i] = hull->points[i]; + } + + // Compute normals. Ensure the edges have non-zero length. + for ( int i = 0; i < shape.count; ++i ) + { + int i1 = i; + int i2 = i + 1 < shape.count ? i + 1 : 0; + b2Vec2 edge = b2Sub( shape.vertices[i2], shape.vertices[i1] ); + B2_ASSERT( b2Dot( edge, edge ) > FLT_EPSILON * FLT_EPSILON ); + shape.normals[i] = b2Normalize( b2CrossVS( edge, 1.0f ) ); + } + + shape.centroid = b2ComputePolygonCentroid( shape.vertices, shape.count ); + + return shape; +} + +b2Polygon b2MakeOffsetPolygon( const b2Hull* hull, b2Vec2 position, b2Rot rotation ) +{ + return b2MakeOffsetRoundedPolygon( hull, position, rotation, 0.0f ); +} + +b2Polygon b2MakeOffsetRoundedPolygon( const b2Hull* hull, b2Vec2 position, b2Rot rotation, float radius ) +{ + B2_ASSERT( b2ValidateHull( hull ) ); + + if ( hull->count < 3 ) + { + // Handle a bad hull when assertions are disabled + return b2MakeSquare( 0.5f ); + } + + b2Transform transform = { position, rotation }; + + b2Polygon shape = { 0 }; + shape.count = hull->count; + shape.radius = radius; + + // Copy vertices + for ( int i = 0; i < shape.count; ++i ) + { + shape.vertices[i] = b2TransformPoint( transform, hull->points[i] ); + } + + // Compute normals. Ensure the edges have non-zero length. + for ( int i = 0; i < shape.count; ++i ) + { + int i1 = i; + int i2 = i + 1 < shape.count ? i + 1 : 0; + b2Vec2 edge = b2Sub( shape.vertices[i2], shape.vertices[i1] ); + B2_ASSERT( b2Dot( edge, edge ) > FLT_EPSILON * FLT_EPSILON ); + shape.normals[i] = b2Normalize( b2CrossVS( edge, 1.0f ) ); + } + + shape.centroid = b2ComputePolygonCentroid( shape.vertices, shape.count ); + + return shape; +} + +b2Polygon b2MakeSquare( float halfWidth ) +{ + return b2MakeBox( halfWidth, halfWidth ); +} + +b2Polygon b2MakeBox( float halfWidth, float halfHeight ) +{ + B2_ASSERT( b2IsValidFloat( halfWidth ) && halfWidth > 0.0f ); + B2_ASSERT( b2IsValidFloat( halfHeight ) && halfHeight > 0.0f ); + + b2Polygon shape = { 0 }; + shape.count = 4; + shape.vertices[0] = (b2Vec2){ -halfWidth, -halfHeight }; + shape.vertices[1] = (b2Vec2){ halfWidth, -halfHeight }; + shape.vertices[2] = (b2Vec2){ halfWidth, halfHeight }; + shape.vertices[3] = (b2Vec2){ -halfWidth, halfHeight }; + shape.normals[0] = (b2Vec2){ 0.0f, -1.0f }; + shape.normals[1] = (b2Vec2){ 1.0f, 0.0f }; + shape.normals[2] = (b2Vec2){ 0.0f, 1.0f }; + shape.normals[3] = (b2Vec2){ -1.0f, 0.0f }; + shape.radius = 0.0f; + shape.centroid = b2Vec2_zero; + return shape; +} + +b2Polygon b2MakeRoundedBox( float halfWidth, float halfHeight, float radius ) +{ + B2_ASSERT( b2IsValidFloat( radius ) && radius >= 0.0f ); + b2Polygon shape = b2MakeBox( halfWidth, halfHeight ); + shape.radius = radius; + return shape; +} + +b2Polygon b2MakeOffsetBox( float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation ) +{ + b2Transform xf = { center, rotation }; + + b2Polygon shape = { 0 }; + shape.count = 4; + shape.vertices[0] = b2TransformPoint( xf, (b2Vec2){ -halfWidth, -halfHeight } ); + shape.vertices[1] = b2TransformPoint( xf, (b2Vec2){ halfWidth, -halfHeight } ); + shape.vertices[2] = b2TransformPoint( xf, (b2Vec2){ halfWidth, halfHeight } ); + shape.vertices[3] = b2TransformPoint( xf, (b2Vec2){ -halfWidth, halfHeight } ); + shape.normals[0] = b2RotateVector( xf.q, (b2Vec2){ 0.0f, -1.0f } ); + shape.normals[1] = b2RotateVector( xf.q, (b2Vec2){ 1.0f, 0.0f } ); + shape.normals[2] = b2RotateVector( xf.q, (b2Vec2){ 0.0f, 1.0f } ); + shape.normals[3] = b2RotateVector( xf.q, (b2Vec2){ -1.0f, 0.0f } ); + shape.radius = 0.0f; + shape.centroid = xf.p; + return shape; +} + +b2Polygon b2MakeOffsetRoundedBox( float halfWidth, float halfHeight, b2Vec2 center, b2Rot rotation, float radius ) +{ + B2_ASSERT( b2IsValidFloat( radius ) && radius >= 0.0f ); + b2Transform xf = { center, rotation }; + + b2Polygon shape = { 0 }; + shape.count = 4; + shape.vertices[0] = b2TransformPoint( xf, (b2Vec2){ -halfWidth, -halfHeight } ); + shape.vertices[1] = b2TransformPoint( xf, (b2Vec2){ halfWidth, -halfHeight } ); + shape.vertices[2] = b2TransformPoint( xf, (b2Vec2){ halfWidth, halfHeight } ); + shape.vertices[3] = b2TransformPoint( xf, (b2Vec2){ -halfWidth, halfHeight } ); + shape.normals[0] = b2RotateVector( xf.q, (b2Vec2){ 0.0f, -1.0f } ); + shape.normals[1] = b2RotateVector( xf.q, (b2Vec2){ 1.0f, 0.0f } ); + shape.normals[2] = b2RotateVector( xf.q, (b2Vec2){ 0.0f, 1.0f } ); + shape.normals[3] = b2RotateVector( xf.q, (b2Vec2){ -1.0f, 0.0f } ); + shape.radius = radius; + shape.centroid = xf.p; + return shape; +} + +b2Polygon b2TransformPolygon( b2Transform transform, const b2Polygon* polygon ) +{ + b2Polygon p = *polygon; + + for ( int i = 0; i < p.count; ++i ) + { + p.vertices[i] = b2TransformPoint( transform, p.vertices[i] ); + p.normals[i] = b2RotateVector( transform.q, p.normals[i] ); + } + + p.centroid = b2TransformPoint( transform, p.centroid ); + + return p; +} + +b2MassData b2ComputeCircleMass( const b2Circle* shape, float density ) +{ + float rr = shape->radius * shape->radius; + + b2MassData massData; + massData.mass = density * B2_PI * rr; + massData.center = shape->center; + + // inertia about the local origin + massData.rotationalInertia = massData.mass * ( 0.5f * rr + b2Dot( shape->center, shape->center ) ); + + return massData; +} + +b2MassData b2ComputeCapsuleMass( const b2Capsule* shape, float density ) +{ + float radius = shape->radius; + float rr = radius * radius; + b2Vec2 p1 = shape->center1; + b2Vec2 p2 = shape->center2; + float length = b2Length( b2Sub( p2, p1 ) ); + float ll = length * length; + + float circleMass = density * ( B2_PI * radius * radius ); + float boxMass = density * ( 2.0f * radius * length ); + + b2MassData massData; + massData.mass = circleMass + boxMass; + massData.center.x = 0.5f * ( p1.x + p2.x ); + massData.center.y = 0.5f * ( p1.y + p2.y ); + + // two offset half circles, both halves add up to full circle and each half is offset by half length + // semi-circle centroid = 4 r / 3 pi + // Need to apply parallel-axis theorem twice: + // 1. shift semi-circle centroid to origin + // 2. shift semi-circle to box end + // m * ((h + lc)^2 - lc^2) = m * (h^2 + 2 * h * lc) + // See: https://en.wikipedia.org/wiki/Parallel_axis_theorem + // I verified this formula by computing the convex hull of a 128 vertex capsule + + // half circle centroid + float lc = 4.0f * radius / ( 3.0f * B2_PI ); + + // half length of rectangular portion of capsule + float h = 0.5f * length; + + float circleInertia = circleMass * ( 0.5f * rr + h * h + 2.0f * h * lc ); + float boxInertia = boxMass * ( 4.0f * rr + ll ) / 12.0f; + massData.rotationalInertia = circleInertia + boxInertia; + + // inertia about the local origin + massData.rotationalInertia += massData.mass * b2Dot( massData.center, massData.center ); + + return massData; +} + +b2MassData b2ComputePolygonMass( const b2Polygon* shape, float density ) +{ + // Polygon mass, centroid, and inertia. + // Let rho be the polygon density in mass per unit area. + // Then: + // mass = rho * int(dA) + // centroid.x = (1/mass) * rho * int(x * dA) + // centroid.y = (1/mass) * rho * int(y * dA) + // I = rho * int((x*x + y*y) * dA) + // + // We can compute these integrals by summing all the integrals + // for each triangle of the polygon. To evaluate the integral + // for a single triangle, we make a change of variables to + // the (u,v) coordinates of the triangle: + // x = x0 + e1x * u + e2x * v + // y = y0 + e1y * u + e2y * v + // where 0 <= u && 0 <= v && u + v <= 1. + // + // We integrate u from [0,1-v] and then v from [0,1]. + // We also need to use the Jacobian of the transformation: + // D = cross(e1, e2) + // + // Simplification: triangle centroid = (1/3) * (p1 + p2 + p3) + // + // The rest of the derivation is handled by computer algebra. + + B2_ASSERT( shape->count > 0 ); + + if ( shape->count == 1 ) + { + b2Circle circle; + circle.center = shape->vertices[0]; + circle.radius = shape->radius; + return b2ComputeCircleMass( &circle, density ); + } + + if ( shape->count == 2 ) + { + b2Capsule capsule; + capsule.center1 = shape->vertices[0]; + capsule.center2 = shape->vertices[1]; + capsule.radius = shape->radius; + return b2ComputeCapsuleMass( &capsule, density ); + } + + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES] = { 0 }; + int count = shape->count; + float radius = shape->radius; + + if ( radius > 0.0f ) + { + // Approximate mass of rounded polygons by pushing out the vertices. + float sqrt2 = 1.412f; + for ( int i = 0; i < count; ++i ) + { + int j = i == 0 ? count - 1 : i - 1; + b2Vec2 n1 = shape->normals[j]; + b2Vec2 n2 = shape->normals[i]; + + b2Vec2 mid = b2Normalize( b2Add( n1, n2 ) ); + vertices[i] = b2MulAdd( shape->vertices[i], sqrt2 * radius, mid ); + } + } + else + { + for ( int i = 0; i < count; ++i ) + { + vertices[i] = shape->vertices[i]; + } + } + + b2Vec2 center = { 0.0f, 0.0f }; + float area = 0.0f; + float rotationalInertia = 0.0f; + + // Get a reference point for forming triangles. + // Use the first vertex to reduce round-off errors. + b2Vec2 r = vertices[0]; + + const float inv3 = 1.0f / 3.0f; + + for ( int i = 1; i < count - 1; ++i ) + { + // Triangle edges + b2Vec2 e1 = b2Sub( vertices[i], r ); + b2Vec2 e2 = b2Sub( vertices[i + 1], r ); + + float D = b2Cross( e1, e2 ); + + float triangleArea = 0.5f * D; + area += triangleArea; + + // Area weighted centroid, r at origin + center = b2MulAdd( center, triangleArea * inv3, b2Add( e1, e2 ) ); + + float ex1 = e1.x, ey1 = e1.y; + float ex2 = e2.x, ey2 = e2.y; + + float intx2 = ex1 * ex1 + ex2 * ex1 + ex2 * ex2; + float inty2 = ey1 * ey1 + ey2 * ey1 + ey2 * ey2; + + rotationalInertia += ( 0.25f * inv3 * D ) * ( intx2 + inty2 ); + } + + b2MassData massData; + + // Total mass + massData.mass = density * area; + + // Center of mass, shift back from origin at r + B2_ASSERT( area > FLT_EPSILON ); + float invArea = 1.0f / area; + center.x *= invArea; + center.y *= invArea; + massData.center = b2Add( r, center ); + + // Inertia tensor relative to the local origin (point s). + massData.rotationalInertia = density * rotationalInertia; + + // Shift to center of mass then to original body origin. + massData.rotationalInertia += massData.mass * ( b2Dot( massData.center, massData.center ) - b2Dot( center, center ) ); + + return massData; +} + +b2AABB b2ComputeCircleAABB( const b2Circle* shape, b2Transform xf ) +{ + b2Vec2 p = b2TransformPoint( xf, shape->center ); + float r = shape->radius; + + b2AABB aabb = { { p.x - r, p.y - r }, { p.x + r, p.y + r } }; + return aabb; +} + +b2AABB b2ComputeCapsuleAABB( const b2Capsule* shape, b2Transform xf ) +{ + b2Vec2 v1 = b2TransformPoint( xf, shape->center1 ); + b2Vec2 v2 = b2TransformPoint( xf, shape->center2 ); + + b2Vec2 r = { shape->radius, shape->radius }; + b2Vec2 lower = b2Sub( b2Min( v1, v2 ), r ); + b2Vec2 upper = b2Add( b2Max( v1, v2 ), r ); + + b2AABB aabb = { lower, upper }; + return aabb; +} + +b2AABB b2ComputePolygonAABB( const b2Polygon* shape, b2Transform xf ) +{ + B2_ASSERT( shape->count > 0 ); + b2Vec2 lower = b2TransformPoint( xf, shape->vertices[0] ); + b2Vec2 upper = lower; + + for ( int i = 1; i < shape->count; ++i ) + { + b2Vec2 v = b2TransformPoint( xf, shape->vertices[i] ); + lower = b2Min( lower, v ); + upper = b2Max( upper, v ); + } + + b2Vec2 r = { shape->radius, shape->radius }; + lower = b2Sub( lower, r ); + upper = b2Add( upper, r ); + + b2AABB aabb = { lower, upper }; + return aabb; +} + +b2AABB b2ComputeSegmentAABB( const b2Segment* shape, b2Transform xf ) +{ + b2Vec2 v1 = b2TransformPoint( xf, shape->point1 ); + b2Vec2 v2 = b2TransformPoint( xf, shape->point2 ); + + b2Vec2 lower = b2Min( v1, v2 ); + b2Vec2 upper = b2Max( v1, v2 ); + + b2AABB aabb = { lower, upper }; + return aabb; +} + +bool b2PointInCircle( b2Vec2 point, const b2Circle* shape ) +{ + b2Vec2 center = shape->center; + return b2DistanceSquared( point, center ) <= shape->radius * shape->radius; +} + +bool b2PointInCapsule( b2Vec2 point, const b2Capsule* shape ) +{ + float rr = shape->radius * shape->radius; + b2Vec2 p1 = shape->center1; + b2Vec2 p2 = shape->center2; + + b2Vec2 d = b2Sub( p2, p1 ); + float dd = b2Dot( d, d ); + if ( dd == 0.0f ) + { + // Capsule is really a circle + return b2DistanceSquared( point, p1 ) <= rr; + } + + // Get closest point on capsule segment + // c = p1 + t * d + // dot(point - c, d) = 0 + // dot(point - p1 - t * d, d) = 0 + // t = dot(point - p1, d) / dot(d, d) + float t = b2Dot( b2Sub( point, p1 ), d ) / dd; + t = b2ClampFloat( t, 0.0f, 1.0f ); + b2Vec2 c = b2MulAdd( p1, t, d ); + + // Is query point within radius around closest point? + return b2DistanceSquared( point, c ) <= rr; +} + +bool b2PointInPolygon( b2Vec2 point, const b2Polygon* shape ) +{ + b2DistanceInput input = { 0 }; + input.proxyA = b2MakeProxy( shape->vertices, shape->count, 0.0f ); + input.proxyB = b2MakeProxy( &point, 1, 0.0f ); + input.transformA = b2Transform_identity; + input.transformB = b2Transform_identity; + input.useRadii = false; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput output = b2ShapeDistance( &input, &cache, NULL, 0 ); + + return output.distance <= shape->radius; +} + +// Precision Improvements for Ray / Sphere Intersection - Ray Tracing Gems 2019 +// http://www.codercorner.com/blog/?p=321 +b2CastOutput b2RayCastCircle( const b2RayCastInput* input, const b2Circle* shape ) +{ + B2_ASSERT( b2IsValidRay( input ) ); + + b2Vec2 p = shape->center; + + b2CastOutput output = { 0 }; + + // Shift ray so circle center is the origin + b2Vec2 s = b2Sub( input->origin, p ); + float length; + b2Vec2 d = b2GetLengthAndNormalize( &length, input->translation ); + if ( length == 0.0f ) + { + // zero length ray + return output; + } + + // Find closest point on ray to origin + + // solve: dot(s + t * d, d) = 0 + float t = -b2Dot( s, d ); + + // c is the closest point on the line to the origin + b2Vec2 c = b2MulAdd( s, t, d ); + + float cc = b2Dot( c, c ); + float r = shape->radius; + float rr = r * r; + + if ( cc > rr ) + { + // closest point is outside the circle + return output; + } + + // Pythagoras + float h = sqrtf( rr - cc ); + + float fraction = t - h; + + if ( fraction < 0.0f || input->maxFraction * length < fraction ) + { + // outside the range of the ray segment + return output; + } + + // hit point relative to center + b2Vec2 hitPoint = b2MulAdd( s, fraction, d ); + + output.fraction = fraction / length; + output.normal = b2Normalize( hitPoint ); + output.point = b2MulAdd( p, shape->radius, output.normal ); + output.hit = true; + + return output; +} + +b2CastOutput b2RayCastCapsule( const b2RayCastInput* input, const b2Capsule* shape ) +{ + B2_ASSERT( b2IsValidRay( input ) ); + + b2CastOutput output = { 0 }; + + b2Vec2 v1 = shape->center1; + b2Vec2 v2 = shape->center2; + + b2Vec2 e = b2Sub( v2, v1 ); + + float capsuleLength; + b2Vec2 a = b2GetLengthAndNormalize( &capsuleLength, e ); + + if ( capsuleLength < FLT_EPSILON ) + { + // Capsule is really a circle + b2Circle circle = { v1, shape->radius }; + return b2RayCastCircle( input, &circle ); + } + + b2Vec2 p1 = input->origin; + b2Vec2 d = input->translation; + + // Ray from capsule start to ray start + b2Vec2 q = b2Sub( p1, v1 ); + float qa = b2Dot( q, a ); + + // Vector to ray start that is perpendicular to capsule axis + b2Vec2 qp = b2MulAdd( q, -qa, a ); + + float radius = shape->radius; + + // Does the ray start within the infinite length capsule? + if ( b2Dot( qp, qp ) < radius * radius ) + { + if ( qa < 0.0f ) + { + // start point behind capsule segment + b2Circle circle = { v1, shape->radius }; + return b2RayCastCircle( input, &circle ); + } + + if ( qa > 1.0f ) + { + // start point ahead of capsule segment + b2Circle circle = { v2, shape->radius }; + return b2RayCastCircle( input, &circle ); + } + + // ray starts inside capsule -> no hit + return output; + } + + // Perpendicular to capsule axis, pointing right + b2Vec2 n = { a.y, -a.x }; + + float rayLength; + b2Vec2 u = b2GetLengthAndNormalize( &rayLength, d ); + + // Intersect ray with infinite length capsule + // v1 + radius * n + s1 * a = p1 + s2 * u + // v1 - radius * n + s1 * a = p1 + s2 * u + + // s1 * a - s2 * u = b + // b = q - radius * ap + // or + // b = q + radius * ap + + // Cramer's rule [a -u] + float den = -a.x * u.y + u.x * a.y; + if ( -FLT_EPSILON < den && den < FLT_EPSILON ) + { + // Ray is parallel to capsule and outside infinite length capsule + return output; + } + + b2Vec2 b1 = b2MulSub( q, radius, n ); + b2Vec2 b2 = b2MulAdd( q, radius, n ); + + float invDen = 1.0f / den; + + // Cramer's rule [a b1] + float s21 = ( a.x * b1.y - b1.x * a.y ) * invDen; + + // Cramer's rule [a b2] + float s22 = ( a.x * b2.y - b2.x * a.y ) * invDen; + + float s2; + b2Vec2 b; + if ( s21 < s22 ) + { + s2 = s21; + b = b1; + } + else + { + s2 = s22; + b = b2; + n = b2Neg( n ); + } + + if ( s2 < 0.0f || input->maxFraction * rayLength < s2 ) + { + return output; + } + + // Cramer's rule [b -u] + float s1 = ( -b.x * u.y + u.x * b.y ) * invDen; + + if ( s1 < 0.0f ) + { + // ray passes behind capsule segment + b2Circle circle = { v1, shape->radius }; + return b2RayCastCircle( input, &circle ); + } + else if ( capsuleLength < s1 ) + { + // ray passes ahead of capsule segment + b2Circle circle = { v2, shape->radius }; + return b2RayCastCircle( input, &circle ); + } + else + { + // ray hits capsule side + output.fraction = s2 / rayLength; + output.point = b2Add( b2Lerp( v1, v2, s1 / capsuleLength ), b2MulSV( shape->radius, n ) ); + output.normal = n; + output.hit = true; + return output; + } +} + +// Ray vs line segment +b2CastOutput b2RayCastSegment( const b2RayCastInput* input, const b2Segment* shape, bool oneSided ) +{ + if ( oneSided ) + { + // Skip left-side collision + float offset = b2Cross( b2Sub( input->origin, shape->point1 ), b2Sub( shape->point2, shape->point1 ) ); + if ( offset < 0.0f ) + { + b2CastOutput output = { 0 }; + return output; + } + } + + // Put the ray into the edge's frame of reference. + b2Vec2 p1 = input->origin; + b2Vec2 d = input->translation; + + b2Vec2 v1 = shape->point1; + b2Vec2 v2 = shape->point2; + b2Vec2 e = b2Sub( v2, v1 ); + + b2CastOutput output = { 0 }; + + float length; + b2Vec2 eUnit = b2GetLengthAndNormalize( &length, e ); + if ( length == 0.0f ) + { + return output; + } + + // Normal points to the right, looking from v1 towards v2 + b2Vec2 normal = b2RightPerp( eUnit ); + + // Intersect ray with infinite segment using normal + // Similar to intersecting a ray with an infinite plane + // p = p1 + t * d + // dot(normal, p - v1) = 0 + // dot(normal, p1 - v1) + t * dot(normal, d) = 0 + float numerator = b2Dot( normal, b2Sub( v1, p1 ) ); + float denominator = b2Dot( normal, d ); + + if ( denominator == 0.0f ) + { + // parallel + return output; + } + + float t = numerator / denominator; + if ( t < 0.0f || input->maxFraction < t ) + { + // out of ray range + return output; + } + + // Intersection point on infinite segment + b2Vec2 p = b2MulAdd( p1, t, d ); + + // Compute position of p along segment + // p = v1 + s * e + // s = dot(p - v1, e) / dot(e, e) + + float s = b2Dot( b2Sub( p, v1 ), eUnit ); + if ( s < 0.0f || length < s ) + { + // out of segment range + return output; + } + + if ( numerator > 0.0f ) + { + normal = b2Neg( normal ); + } + + output.fraction = t; + output.point = p; + output.normal = normal; + output.hit = true; + + return output; +} + +b2CastOutput b2RayCastPolygon( const b2RayCastInput* input, const b2Polygon* shape ) +{ + B2_ASSERT( b2IsValidRay( input ) ); + + if ( shape->radius == 0.0f ) + { + // Put the ray into the polygon's frame of reference. + b2Vec2 p1 = input->origin; + b2Vec2 d = input->translation; + + float lower = 0.0f, upper = input->maxFraction; + + int index = -1; + + b2CastOutput output = { 0 }; + + for ( int i = 0; i < shape->count; ++i ) + { + // p = p1 + a * d + // dot(normal, p - v) = 0 + // dot(normal, p1 - v) + a * dot(normal, d) = 0 + float numerator = b2Dot( shape->normals[i], b2Sub( shape->vertices[i], p1 ) ); + float denominator = b2Dot( shape->normals[i], d ); + + if ( denominator == 0.0f ) + { + if ( numerator < 0.0f ) + { + return output; + } + } + else + { + // Note: we want this predicate without division: + // lower < numerator / denominator, where denominator < 0 + // Since denominator < 0, we have to flip the inequality: + // lower < numerator / denominator <==> denominator * lower > numerator. + if ( denominator < 0.0f && numerator < lower * denominator ) + { + // Increase lower. + // The segment enters this half-space. + lower = numerator / denominator; + index = i; + } + else if ( denominator > 0.0f && numerator < upper * denominator ) + { + // Decrease upper. + // The segment exits this half-space. + upper = numerator / denominator; + } + } + + // The use of epsilon here causes the B2_ASSERT on lower to trip + // in some cases. Apparently the use of epsilon was to make edge + // shapes work, but now those are handled separately. + // if (upper < lower - b2_epsilon) + if ( upper < lower ) + { + return output; + } + } + + B2_ASSERT( 0.0f <= lower && lower <= input->maxFraction ); + + if ( index >= 0 ) + { + output.fraction = lower; + output.normal = shape->normals[index]; + output.point = b2MulAdd( p1, lower, d ); + output.hit = true; + } + + return output; + } + + // TODO_ERIN this is not working for ray vs box (zero radii) + b2ShapeCastPairInput castInput; + castInput.proxyA = b2MakeProxy( shape->vertices, shape->count, shape->radius ); + castInput.proxyB = b2MakeProxy( &input->origin, 1, 0.0f ); + castInput.transformA = b2Transform_identity; + castInput.transformB = b2Transform_identity; + castInput.translationB = input->translation; + castInput.maxFraction = input->maxFraction; + castInput.canEncroach = false; + return b2ShapeCast( &castInput ); +} + +b2CastOutput b2ShapeCastCircle( const b2ShapeCastInput* input, const b2Circle* shape ) +{ + b2ShapeCastPairInput pairInput; + pairInput.proxyA = b2MakeProxy( &shape->center, 1, shape->radius ); + pairInput.proxyB = input->proxy; + pairInput.transformA = b2Transform_identity; + pairInput.transformB = b2Transform_identity; + pairInput.translationB = input->translation; + pairInput.maxFraction = input->maxFraction; + pairInput.canEncroach = input->canEncroach; + + b2CastOutput output = b2ShapeCast( &pairInput ); + return output; +} + +b2CastOutput b2ShapeCastCapsule( const b2ShapeCastInput* input, const b2Capsule* shape ) +{ + b2ShapeCastPairInput pairInput; + pairInput.proxyA = b2MakeProxy( &shape->center1, 2, shape->radius ); + pairInput.proxyB = input->proxy; + pairInput.transformA = b2Transform_identity; + pairInput.transformB = b2Transform_identity; + pairInput.translationB = input->translation; + pairInput.maxFraction = input->maxFraction; + pairInput.canEncroach = input->canEncroach; + + b2CastOutput output = b2ShapeCast( &pairInput ); + return output; +} + +b2CastOutput b2ShapeCastSegment( const b2ShapeCastInput* input, const b2Segment* shape ) +{ + b2ShapeCastPairInput pairInput; + pairInput.proxyA = b2MakeProxy( &shape->point1, 2, 0.0f ); + pairInput.proxyB = input->proxy; + pairInput.transformA = b2Transform_identity; + pairInput.transformB = b2Transform_identity; + pairInput.translationB = input->translation; + pairInput.maxFraction = input->maxFraction; + pairInput.canEncroach = input->canEncroach; + + b2CastOutput output = b2ShapeCast( &pairInput ); + return output; +} + +b2CastOutput b2ShapeCastPolygon( const b2ShapeCastInput* input, const b2Polygon* shape ) +{ + b2ShapeCastPairInput pairInput; + pairInput.proxyA = b2MakeProxy( shape->vertices, shape->count, shape->radius ); + pairInput.proxyB = input->proxy; + pairInput.transformA = b2Transform_identity; + pairInput.transformB = b2Transform_identity; + pairInput.translationB = input->translation; + pairInput.maxFraction = input->maxFraction; + pairInput.canEncroach = input->canEncroach; + + b2CastOutput output = b2ShapeCast( &pairInput ); + return output; +} + +b2PlaneResult b2CollideMoverAndCircle( const b2Circle* shape, const b2Capsule* mover ) +{ + b2DistanceInput distanceInput; + distanceInput.proxyA = b2MakeProxy( &shape->center, 1, 0.0f ); + distanceInput.proxyB = b2MakeProxy( &mover->center1, 2, mover->radius ); + distanceInput.transformA = b2Transform_identity; + distanceInput.transformB = b2Transform_identity; + distanceInput.useRadii = false; + + float totalRadius = mover->radius + shape->radius; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + if ( distanceOutput.distance <= totalRadius ) + { + b2Plane plane = { distanceOutput.normal, totalRadius - distanceOutput.distance }; + return (b2PlaneResult){ + .plane = plane, + .hit = true, + }; + } + + return (b2PlaneResult){ 0 }; +} + +b2PlaneResult b2CollideMoverAndCapsule( const b2Capsule* shape, const b2Capsule* mover ) +{ + b2DistanceInput distanceInput; + distanceInput.proxyA = b2MakeProxy( &shape->center1, 2, 0.0f ); + distanceInput.proxyB = b2MakeProxy( &mover->center1, 2, mover->radius ); + distanceInput.transformA = b2Transform_identity; + distanceInput.transformB = b2Transform_identity; + distanceInput.useRadii = false; + + float totalRadius = mover->radius + shape->radius; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + if ( distanceOutput.distance <= totalRadius ) + { + b2Plane plane = { distanceOutput.normal, totalRadius - distanceOutput.distance }; + return (b2PlaneResult){ + .plane = plane, + .hit = true, + }; + } + + return (b2PlaneResult){ 0 }; +} + +b2PlaneResult b2CollideMoverAndPolygon( const b2Polygon* shape, const b2Capsule* mover ) +{ + b2DistanceInput distanceInput; + distanceInput.proxyA = b2MakeProxy( shape->vertices, shape->count, shape->radius ); + distanceInput.proxyB = b2MakeProxy( &mover->center1, 2, mover->radius ); + distanceInput.transformA = b2Transform_identity; + distanceInput.transformB = b2Transform_identity; + distanceInput.useRadii = false; + + float totalRadius = mover->radius + shape->radius; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + if ( distanceOutput.distance <= totalRadius ) + { + b2Plane plane = { distanceOutput.normal, totalRadius - distanceOutput.distance }; + return (b2PlaneResult){ + .plane = plane, + .hit = true, + }; + } + + return (b2PlaneResult){ 0 }; +} + +b2PlaneResult b2CollideMoverAndSegment( const b2Segment* shape, const b2Capsule* mover ) +{ + b2DistanceInput distanceInput; + distanceInput.proxyA = b2MakeProxy( &shape->point1, 2, 0.0f ); + distanceInput.proxyB = b2MakeProxy( &mover->center1, 2, mover->radius ); + distanceInput.transformA = b2Transform_identity; + distanceInput.transformB = b2Transform_identity; + distanceInput.useRadii = false; + + float totalRadius = mover->radius; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, NULL, 0 ); + + if ( distanceOutput.distance <= totalRadius ) + { + b2Plane plane = { distanceOutput.normal, totalRadius - distanceOutput.distance }; + return (b2PlaneResult){ + .plane = plane, + .hit = true, + }; + } + + return (b2PlaneResult){ 0 }; +} diff --git a/3rdparty/box2d/src/hull.c b/3rdparty/box2d/src/hull.c new file mode 100644 index 000000000000..27cc3953ae67 --- /dev/null +++ b/3rdparty/box2d/src/hull.c @@ -0,0 +1,328 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constants.h" +#include "core.h" + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include + +// quickhull recursion +static b2Hull b2RecurseHull( b2Vec2 p1, b2Vec2 p2, b2Vec2* ps, int count ) +{ + b2Hull hull; + hull.count = 0; + + if ( count == 0 ) + { + return hull; + } + + // create an edge vector pointing from p1 to p2 + b2Vec2 e = b2Normalize( b2Sub( p2, p1 ) ); + + // discard points left of e and find point furthest to the right of e + b2Vec2 rightPoints[B2_MAX_POLYGON_VERTICES]; + int rightCount = 0; + + int bestIndex = 0; + float bestDistance = b2Cross( b2Sub( ps[bestIndex], p1 ), e ); + if ( bestDistance > 0.0f ) + { + rightPoints[rightCount++] = ps[bestIndex]; + } + + for ( int i = 1; i < count; ++i ) + { + float distance = b2Cross( b2Sub( ps[i], p1 ), e ); + if ( distance > bestDistance ) + { + bestIndex = i; + bestDistance = distance; + } + + if ( distance > 0.0f ) + { + rightPoints[rightCount++] = ps[i]; + } + } + + if ( bestDistance < 2.0f * B2_LINEAR_SLOP ) + { + return hull; + } + + b2Vec2 bestPoint = ps[bestIndex]; + + // compute hull to the right of p1-bestPoint + b2Hull hull1 = b2RecurseHull( p1, bestPoint, rightPoints, rightCount ); + + // compute hull to the right of bestPoint-p2 + b2Hull hull2 = b2RecurseHull( bestPoint, p2, rightPoints, rightCount ); + + // stitch together hulls + for ( int i = 0; i < hull1.count; ++i ) + { + hull.points[hull.count++] = hull1.points[i]; + } + + hull.points[hull.count++] = bestPoint; + + for ( int i = 0; i < hull2.count; ++i ) + { + hull.points[hull.count++] = hull2.points[i]; + } + + B2_ASSERT( hull.count < B2_MAX_POLYGON_VERTICES ); + + return hull; +} + +// quickhull algorithm +// - merges vertices based on B2_LINEAR_SLOP +// - removes collinear points using B2_LINEAR_SLOP +// - returns an empty hull if it fails +b2Hull b2ComputeHull( const b2Vec2* points, int count ) +{ + b2Hull hull; + hull.count = 0; + + if ( count < 3 || count > B2_MAX_POLYGON_VERTICES ) + { + // check your data + return hull; + } + + count = b2MinInt( count, B2_MAX_POLYGON_VERTICES ); + + b2AABB aabb = { { FLT_MAX, FLT_MAX }, { -FLT_MAX, -FLT_MAX } }; + + // Perform aggressive point welding. First point always remains. + // Also compute the bounding box for later. + b2Vec2 ps[B2_MAX_POLYGON_VERTICES]; + int n = 0; + const float linearSlop = B2_LINEAR_SLOP; + const float tolSqr = 16.0f * linearSlop * linearSlop; + for ( int i = 0; i < count; ++i ) + { + aabb.lowerBound = b2Min( aabb.lowerBound, points[i] ); + aabb.upperBound = b2Max( aabb.upperBound, points[i] ); + + b2Vec2 vi = points[i]; + + bool unique = true; + for ( int j = 0; j < i; ++j ) + { + b2Vec2 vj = points[j]; + + float distSqr = b2DistanceSquared( vi, vj ); + if ( distSqr < tolSqr ) + { + unique = false; + break; + } + } + + if ( unique ) + { + ps[n++] = vi; + } + } + + if ( n < 3 ) + { + // all points very close together, check your data and check your scale + return hull; + } + + // Find an extreme point as the first point on the hull + b2Vec2 c = b2AABB_Center( aabb ); + int f1 = 0; + float dsq1 = b2DistanceSquared( c, ps[f1] ); + for ( int i = 1; i < n; ++i ) + { + float dsq = b2DistanceSquared( c, ps[i] ); + if ( dsq > dsq1 ) + { + f1 = i; + dsq1 = dsq; + } + } + + // remove p1 from working set + b2Vec2 p1 = ps[f1]; + ps[f1] = ps[n - 1]; + n = n - 1; + + int f2 = 0; + float dsq2 = b2DistanceSquared( p1, ps[f2] ); + for ( int i = 1; i < n; ++i ) + { + float dsq = b2DistanceSquared( p1, ps[i] ); + if ( dsq > dsq2 ) + { + f2 = i; + dsq2 = dsq; + } + } + + // remove p2 from working set + b2Vec2 p2 = ps[f2]; + ps[f2] = ps[n - 1]; + n = n - 1; + + // split the points into points that are left and right of the line p1-p2. + b2Vec2 rightPoints[B2_MAX_POLYGON_VERTICES - 2]; + int rightCount = 0; + + b2Vec2 leftPoints[B2_MAX_POLYGON_VERTICES - 2]; + int leftCount = 0; + + b2Vec2 e = b2Normalize( b2Sub( p2, p1 ) ); + + for ( int i = 0; i < n; ++i ) + { + float d = b2Cross( b2Sub( ps[i], p1 ), e ); + + // slop used here to skip points that are very close to the line p1-p2 + if ( d >= 2.0f * linearSlop ) + { + rightPoints[rightCount++] = ps[i]; + } + else if ( d <= -2.0f * linearSlop ) + { + leftPoints[leftCount++] = ps[i]; + } + } + + // compute hulls on right and left + b2Hull hull1 = b2RecurseHull( p1, p2, rightPoints, rightCount ); + b2Hull hull2 = b2RecurseHull( p2, p1, leftPoints, leftCount ); + + if ( hull1.count == 0 && hull2.count == 0 ) + { + // all points collinear + return hull; + } + + // stitch hulls together, preserving CCW winding order + hull.points[hull.count++] = p1; + + for ( int i = 0; i < hull1.count; ++i ) + { + hull.points[hull.count++] = hull1.points[i]; + } + + hull.points[hull.count++] = p2; + + for ( int i = 0; i < hull2.count; ++i ) + { + hull.points[hull.count++] = hull2.points[i]; + } + + B2_ASSERT( hull.count <= B2_MAX_POLYGON_VERTICES ); + + // merge collinear + bool searching = true; + while ( searching && hull.count > 2 ) + { + searching = false; + + for ( int i = 0; i < hull.count; ++i ) + { + int i1 = i; + int i2 = ( i + 1 ) % hull.count; + int i3 = ( i + 2 ) % hull.count; + + b2Vec2 s1 = hull.points[i1]; + b2Vec2 s2 = hull.points[i2]; + b2Vec2 s3 = hull.points[i3]; + + // unit edge vector for s1-s3 + b2Vec2 r = b2Normalize( b2Sub( s3, s1 ) ); + + float distance = b2Cross( b2Sub( s2, s1 ), r ); + if ( distance <= 2.0f * linearSlop ) + { + // remove midpoint from hull + for ( int j = i2; j < hull.count - 1; ++j ) + { + hull.points[j] = hull.points[j + 1]; + } + hull.count -= 1; + + // continue searching for collinear points + searching = true; + + break; + } + } + } + + if ( hull.count < 3 ) + { + // all points collinear, shouldn't be reached since this was validated above + hull.count = 0; + } + + return hull; +} + +bool b2ValidateHull( const b2Hull* hull ) +{ + if ( hull->count < 3 || B2_MAX_POLYGON_VERTICES < hull->count ) + { + return false; + } + + // test that every point is behind every edge + for ( int i = 0; i < hull->count; ++i ) + { + // create an edge vector + int i1 = i; + int i2 = i < hull->count - 1 ? i1 + 1 : 0; + b2Vec2 p = hull->points[i1]; + b2Vec2 e = b2Normalize( b2Sub( hull->points[i2], p ) ); + + for ( int j = 0; j < hull->count; ++j ) + { + // skip points that subtend the current edge + if ( j == i1 || j == i2 ) + { + continue; + } + + float distance = b2Cross( b2Sub( hull->points[j], p ), e ); + if ( distance >= 0.0f ) + { + return false; + } + } + } + + // test for collinear points + const float linearSlop = B2_LINEAR_SLOP; + for ( int i = 0; i < hull->count; ++i ) + { + int i1 = i; + int i2 = ( i + 1 ) % hull->count; + int i3 = ( i + 2 ) % hull->count; + + b2Vec2 p1 = hull->points[i1]; + b2Vec2 p2 = hull->points[i2]; + b2Vec2 p3 = hull->points[i3]; + + b2Vec2 e = b2Normalize( b2Sub( p3, p1 ) ); + + float distance = b2Cross( b2Sub( p2, p1 ), e ); + if ( distance <= linearSlop ) + { + // p1-p2-p3 are collinear + return false; + } + } + + return true; +} diff --git a/3rdparty/box2d/src/id_pool.c b/3rdparty/box2d/src/id_pool.c new file mode 100644 index 000000000000..03ef2002730f --- /dev/null +++ b/3rdparty/box2d/src/id_pool.c @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "id_pool.h" + +b2IdPool b2CreateIdPool( void ) +{ + b2IdPool pool = { 0 }; + pool.freeArray = b2IntArray_Create( 32 ); + return pool; +} + +void b2DestroyIdPool( b2IdPool* pool ) +{ + b2IntArray_Destroy( &pool->freeArray ); + *pool = ( b2IdPool ){ 0 }; +} + +int b2AllocId( b2IdPool* pool ) +{ + int count = pool->freeArray.count; + if ( count > 0 ) + { + int id = b2IntArray_Pop( &pool->freeArray ); + return id; + } + + int id = pool->nextIndex; + pool->nextIndex += 1; + return id; +} + +void b2FreeId( b2IdPool* pool, int id ) +{ + B2_ASSERT( pool->nextIndex > 0 ); + B2_ASSERT( 0 <= id && id < pool->nextIndex ); + b2IntArray_Push( &pool->freeArray, id ); +} + +#if B2_VALIDATE + +void b2ValidateFreeId( b2IdPool* pool, int id ) +{ + int freeCount = pool->freeArray.count; + for ( int i = 0; i < freeCount; ++i ) + { + if ( pool->freeArray.data[i] == id ) + { + return; + } + } + + B2_ASSERT( 0 ); +} + +void b2ValidateUsedId( b2IdPool* pool, int id ) +{ + int freeCount = pool->freeArray.count; + for ( int i = 0; i < freeCount; ++i ) + { + if ( pool->freeArray.data[i] == id ) + { + B2_ASSERT( 0 ); + } + } +} + +#else + +void b2ValidateFreeId( b2IdPool* pool, int id ) +{ + B2_UNUSED( pool, id ); +} + +void b2ValidateUsedId( b2IdPool* pool, int id ) +{ + B2_UNUSED( pool, id ); +} +#endif diff --git a/3rdparty/box2d/src/id_pool.h b/3rdparty/box2d/src/id_pool.h new file mode 100644 index 000000000000..16a318886238 --- /dev/null +++ b/3rdparty/box2d/src/id_pool.h @@ -0,0 +1,35 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +typedef struct b2IdPool +{ + b2IntArray freeArray; + int nextIndex; +} b2IdPool; + +b2IdPool b2CreateIdPool( void ); +void b2DestroyIdPool( b2IdPool* pool ); + +int b2AllocId( b2IdPool* pool ); +void b2FreeId( b2IdPool* pool, int id ); +void b2ValidateFreeId( b2IdPool* pool, int id ); +void b2ValidateUsedId( b2IdPool* pool, int id ); + +static inline int b2GetIdCount( b2IdPool* pool ) +{ + return pool->nextIndex - pool->freeArray.count; +} + +static inline int b2GetIdCapacity( b2IdPool* pool ) +{ + return pool->nextIndex; +} + +static inline int b2GetIdBytes( b2IdPool* pool ) +{ + return b2IntArray_ByteCount(&pool->freeArray); +} diff --git a/3rdparty/box2d/src/island.c b/3rdparty/box2d/src/island.c new file mode 100644 index 000000000000..95c5a2f433f2 --- /dev/null +++ b/3rdparty/box2d/src/island.c @@ -0,0 +1,977 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "island.h" + +#include "body.h" +#include "contact.h" +#include "core.h" +#include "joint.h" +#include "solver_set.h" +#include "world.h" + +#include + +B2_ARRAY_SOURCE( b2Island, b2Island ) +B2_ARRAY_SOURCE( b2IslandSim, b2IslandSim ) + +b2Island* b2CreateIsland( b2World* world, int setIndex ) +{ + B2_ASSERT( setIndex == b2_awakeSet || setIndex >= b2_firstSleepingSet ); + + int islandId = b2AllocId( &world->islandIdPool ); + + if ( islandId == world->islands.count ) + { + b2Island emptyIsland = { 0 }; + b2IslandArray_Push( &world->islands, emptyIsland ); + } + else + { + B2_ASSERT( world->islands.data[islandId].setIndex == B2_NULL_INDEX ); + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + island->setIndex = setIndex; + island->localIndex = set->islandSims.count; + island->islandId = islandId; + island->headBody = B2_NULL_INDEX; + island->tailBody = B2_NULL_INDEX; + island->bodyCount = 0; + island->headContact = B2_NULL_INDEX; + island->tailContact = B2_NULL_INDEX; + island->contactCount = 0; + island->headJoint = B2_NULL_INDEX; + island->tailJoint = B2_NULL_INDEX; + island->jointCount = 0; + island->parentIsland = B2_NULL_INDEX; + island->constraintRemoveCount = 0; + + b2IslandSim* islandSim = b2IslandSimArray_Add( &set->islandSims ); + islandSim->islandId = islandId; + + return island; +} + +void b2DestroyIsland( b2World* world, int islandId ) +{ + if (world->splitIslandId == islandId) + { + world->splitIslandId = B2_NULL_INDEX; + } + + // assume island is empty + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, island->setIndex ); + int movedIndex = b2IslandSimArray_RemoveSwap( &set->islandSims, island->localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix index on moved element + b2IslandSim* movedElement = set->islandSims.data + island->localIndex; + int movedId = movedElement->islandId; + b2Island* movedIsland = b2IslandArray_Get( &world->islands, movedId ); + B2_ASSERT( movedIsland->localIndex == movedIndex ); + movedIsland->localIndex = island->localIndex; + } + + // Free island and id (preserve island revision) + island->islandId = B2_NULL_INDEX; + island->setIndex = B2_NULL_INDEX; + island->localIndex = B2_NULL_INDEX; + b2FreeId( &world->islandIdPool, islandId ); +} + +static void b2AddContactToIsland( b2World* world, int islandId, b2Contact* contact ) +{ + B2_ASSERT( contact->islandId == B2_NULL_INDEX ); + B2_ASSERT( contact->islandPrev == B2_NULL_INDEX ); + B2_ASSERT( contact->islandNext == B2_NULL_INDEX ); + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + if ( island->headContact != B2_NULL_INDEX ) + { + contact->islandNext = island->headContact; + b2Contact* headContact = b2ContactArray_Get( &world->contacts, island->headContact); + headContact->islandPrev = contact->contactId; + } + + island->headContact = contact->contactId; + if ( island->tailContact == B2_NULL_INDEX ) + { + island->tailContact = island->headContact; + } + + island->contactCount += 1; + contact->islandId = islandId; + + b2ValidateIsland( world, islandId ); +} + +// Link a contact into an island. +// This performs union-find and path compression to join islands. +// https://en.wikipedia.org/wiki/Disjoint-set_data_structure +void b2LinkContact( b2World* world, b2Contact* contact ) +{ + B2_ASSERT( ( contact->flags & b2_contactTouchingFlag ) != 0 ); + + int bodyIdA = contact->edges[0].bodyId; + int bodyIdB = contact->edges[1].bodyId; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + + B2_ASSERT( bodyA->setIndex != b2_disabledSet && bodyB->setIndex != b2_disabledSet ); + B2_ASSERT( bodyA->setIndex != b2_staticSet || bodyB->setIndex != b2_staticSet ); + + // Wake bodyB if bodyA is awake and bodyB is sleeping + if ( bodyA->setIndex == b2_awakeSet && bodyB->setIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, bodyB->setIndex ); + } + + // Wake bodyA if bodyB is awake and bodyA is sleeping + if ( bodyB->setIndex == b2_awakeSet && bodyA->setIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, bodyA->setIndex ); + } + + int islandIdA = bodyA->islandId; + int islandIdB = bodyB->islandId; + + // Static bodies have null island indices. + B2_ASSERT( bodyA->setIndex != b2_staticSet || islandIdA == B2_NULL_INDEX ); + B2_ASSERT( bodyB->setIndex != b2_staticSet || islandIdB == B2_NULL_INDEX ); + B2_ASSERT( islandIdA != B2_NULL_INDEX || islandIdB != B2_NULL_INDEX ); + + if ( islandIdA == islandIdB ) + { + // Contact in same island + b2AddContactToIsland( world, islandIdA, contact ); + return; + } + + // Union-find root of islandA + b2Island* islandA = NULL; + if ( islandIdA != B2_NULL_INDEX ) + { + islandA = b2IslandArray_Get( &world->islands, islandIdA ); + int parentId = islandA->parentIsland; + while ( parentId != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, parentId ); + if ( parent->parentIsland != B2_NULL_INDEX ) + { + // path compression + islandA->parentIsland = parent->parentIsland; + } + + islandA = parent; + islandIdA = parentId; + parentId = islandA->parentIsland; + } + } + + // Union-find root of islandB + b2Island* islandB = NULL; + if ( islandIdB != B2_NULL_INDEX ) + { + islandB = b2IslandArray_Get( &world->islands, islandIdB ); + int parentId = islandB->parentIsland; + while ( islandB->parentIsland != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, parentId ); + if ( parent->parentIsland != B2_NULL_INDEX ) + { + // path compression + islandB->parentIsland = parent->parentIsland; + } + + islandB = parent; + islandIdB = parentId; + parentId = islandB->parentIsland; + } + } + + B2_ASSERT( islandA != NULL || islandB != NULL ); + + // Union-Find link island roots + if ( islandA != islandB && islandA != NULL && islandB != NULL ) + { + B2_ASSERT( islandA != islandB ); + B2_ASSERT( islandB->parentIsland == B2_NULL_INDEX ); + islandB->parentIsland = islandIdA; + } + + if ( islandA != NULL ) + { + b2AddContactToIsland( world, islandIdA, contact ); + } + else + { + b2AddContactToIsland( world, islandIdB, contact ); + } + + // todo why not merge the islands right here? +} + +// This is called when a contact no longer has contact points or when a contact is destroyed. +void b2UnlinkContact( b2World* world, b2Contact* contact ) +{ + B2_ASSERT( contact->islandId != B2_NULL_INDEX ); + + // remove from island + int islandId = contact->islandId; + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + if ( contact->islandPrev != B2_NULL_INDEX ) + { + b2Contact* prevContact = b2ContactArray_Get( &world->contacts, contact->islandPrev); + B2_ASSERT( prevContact->islandNext == contact->contactId ); + prevContact->islandNext = contact->islandNext; + } + + if ( contact->islandNext != B2_NULL_INDEX ) + { + b2Contact* nextContact = b2ContactArray_Get( &world->contacts, contact->islandNext ); + B2_ASSERT( nextContact->islandPrev == contact->contactId ); + nextContact->islandPrev = contact->islandPrev; + } + + if ( island->headContact == contact->contactId ) + { + island->headContact = contact->islandNext; + } + + if ( island->tailContact == contact->contactId ) + { + island->tailContact = contact->islandPrev; + } + + B2_ASSERT( island->contactCount > 0 ); + island->contactCount -= 1; + island->constraintRemoveCount += 1; + + contact->islandId = B2_NULL_INDEX; + contact->islandPrev = B2_NULL_INDEX; + contact->islandNext = B2_NULL_INDEX; + + b2ValidateIsland( world, islandId ); +} + +static void b2AddJointToIsland( b2World* world, int islandId, b2Joint* joint ) +{ + B2_ASSERT( joint->islandId == B2_NULL_INDEX ); + B2_ASSERT( joint->islandPrev == B2_NULL_INDEX ); + B2_ASSERT( joint->islandNext == B2_NULL_INDEX ); + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + if ( island->headJoint != B2_NULL_INDEX ) + { + joint->islandNext = island->headJoint; + b2Joint* headJoint = b2JointArray_Get( &world->joints, island->headJoint ); + headJoint->islandPrev = joint->jointId; + } + + island->headJoint = joint->jointId; + if ( island->tailJoint == B2_NULL_INDEX ) + { + island->tailJoint = island->headJoint; + } + + island->jointCount += 1; + joint->islandId = islandId; + + b2ValidateIsland( world, islandId ); +} + +void b2LinkJoint( b2World* world, b2Joint* joint, bool mergeIslands ) +{ + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + + if ( bodyA->setIndex == b2_awakeSet && bodyB->setIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, bodyB->setIndex ); + } + else if ( bodyB->setIndex == b2_awakeSet && bodyA->setIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, bodyA->setIndex ); + } + + int islandIdA = bodyA->islandId; + int islandIdB = bodyB->islandId; + + B2_ASSERT( islandIdA != B2_NULL_INDEX || islandIdB != B2_NULL_INDEX ); + + if ( islandIdA == islandIdB ) + { + // Joint in same island + b2AddJointToIsland( world, islandIdA, joint ); + return; + } + + // Union-find root of islandA + b2Island* islandA = NULL; + if ( islandIdA != B2_NULL_INDEX ) + { + islandA = b2IslandArray_Get( &world->islands, islandIdA ); + while ( islandA->parentIsland != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, islandA->parentIsland ); + if ( parent->parentIsland != B2_NULL_INDEX ) + { + // path compression + islandA->parentIsland = parent->parentIsland; + } + + islandIdA = islandA->parentIsland; + islandA = parent; + } + } + + // Union-find root of islandB + b2Island* islandB = NULL; + if ( islandIdB != B2_NULL_INDEX ) + { + islandB = b2IslandArray_Get( &world->islands, islandIdB ); + while ( islandB->parentIsland != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, islandB->parentIsland ); + if ( parent->parentIsland != B2_NULL_INDEX ) + { + // path compression + islandB->parentIsland = parent->parentIsland; + } + + islandIdB = islandB->parentIsland; + islandB = parent; + } + } + + B2_ASSERT( islandA != NULL || islandB != NULL ); + + // Union-Find link island roots + if ( islandA != islandB && islandA != NULL && islandB != NULL ) + { + B2_ASSERT( islandA != islandB ); + B2_ASSERT( islandB->parentIsland == B2_NULL_INDEX ); + islandB->parentIsland = islandIdA; + } + + if ( islandA != NULL ) + { + b2AddJointToIsland( world, islandIdA, joint ); + } + else + { + b2AddJointToIsland( world, islandIdB, joint ); + } + + // Joints need to have islands merged immediately when they are created + // to keep the island graph valid. + // However, when a body type is being changed the merge can be deferred until + // all joints are linked. + if (mergeIslands) + { + b2MergeAwakeIslands( world ); + } +} + +void b2UnlinkJoint( b2World* world, b2Joint* joint ) +{ + B2_ASSERT( joint->islandId != B2_NULL_INDEX ); + + // remove from island + int islandId = joint->islandId; + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + if ( joint->islandPrev != B2_NULL_INDEX ) + { + b2Joint* prevJoint = b2JointArray_Get( &world->joints, joint->islandPrev ); + B2_ASSERT( prevJoint->islandNext == joint->jointId ); + prevJoint->islandNext = joint->islandNext; + } + + if ( joint->islandNext != B2_NULL_INDEX ) + { + b2Joint* nextJoint = b2JointArray_Get( &world->joints, joint->islandNext ); + B2_ASSERT( nextJoint->islandPrev == joint->jointId ); + nextJoint->islandPrev = joint->islandPrev; + } + + if ( island->headJoint == joint->jointId ) + { + island->headJoint = joint->islandNext; + } + + if ( island->tailJoint == joint->jointId ) + { + island->tailJoint = joint->islandPrev; + } + + B2_ASSERT( island->jointCount > 0 ); + island->jointCount -= 1; + island->constraintRemoveCount += 1; + + joint->islandId = B2_NULL_INDEX; + joint->islandPrev = B2_NULL_INDEX; + joint->islandNext = B2_NULL_INDEX; + + b2ValidateIsland( world, islandId ); +} + +// Merge an island into its root island. +// todo we can assume all islands are awake here +static void b2MergeIsland( b2World* world, b2Island* island ) +{ + B2_ASSERT( island->parentIsland != B2_NULL_INDEX ); + + int rootId = island->parentIsland; + b2Island* rootIsland = b2IslandArray_Get( &world->islands, rootId ); + B2_ASSERT( rootIsland->parentIsland == B2_NULL_INDEX ); + + // remap island indices + int bodyId = island->headBody; + while ( bodyId != B2_NULL_INDEX ) + { + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + body->islandId = rootId; + bodyId = body->islandNext; + } + + int contactId = island->headContact; + while ( contactId != B2_NULL_INDEX ) + { + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contact->islandId = rootId; + contactId = contact->islandNext; + } + + int jointId = island->headJoint; + while ( jointId != B2_NULL_INDEX ) + { + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + joint->islandId = rootId; + jointId = joint->islandNext; + } + + // connect body lists + B2_ASSERT( rootIsland->tailBody != B2_NULL_INDEX ); + b2Body* tailBody = b2BodyArray_Get( &world->bodies, rootIsland->tailBody ); + B2_ASSERT( tailBody->islandNext == B2_NULL_INDEX ); + tailBody->islandNext = island->headBody; + + B2_ASSERT( island->headBody != B2_NULL_INDEX ); + b2Body* headBody = b2BodyArray_Get( &world->bodies, island->headBody ); + B2_ASSERT( headBody->islandPrev == B2_NULL_INDEX ); + headBody->islandPrev = rootIsland->tailBody; + + rootIsland->tailBody = island->tailBody; + rootIsland->bodyCount += island->bodyCount; + + // connect contact lists + if ( rootIsland->headContact == B2_NULL_INDEX ) + { + // Root island has no contacts + B2_ASSERT( rootIsland->tailContact == B2_NULL_INDEX && rootIsland->contactCount == 0 ); + rootIsland->headContact = island->headContact; + rootIsland->tailContact = island->tailContact; + rootIsland->contactCount = island->contactCount; + } + else if ( island->headContact != B2_NULL_INDEX ) + { + // Both islands have contacts + B2_ASSERT( island->tailContact != B2_NULL_INDEX && island->contactCount > 0 ); + B2_ASSERT( rootIsland->tailContact != B2_NULL_INDEX && rootIsland->contactCount > 0 ); + + b2Contact* tailContact = b2ContactArray_Get( &world->contacts, rootIsland->tailContact ); + B2_ASSERT( tailContact->islandNext == B2_NULL_INDEX ); + tailContact->islandNext = island->headContact; + + b2Contact* headContact = b2ContactArray_Get( &world->contacts, island->headContact ); + B2_ASSERT( headContact->islandPrev == B2_NULL_INDEX ); + headContact->islandPrev = rootIsland->tailContact; + + rootIsland->tailContact = island->tailContact; + rootIsland->contactCount += island->contactCount; + } + + if ( rootIsland->headJoint == B2_NULL_INDEX ) + { + // Root island has no joints + B2_ASSERT( rootIsland->tailJoint == B2_NULL_INDEX && rootIsland->jointCount == 0 ); + rootIsland->headJoint = island->headJoint; + rootIsland->tailJoint = island->tailJoint; + rootIsland->jointCount = island->jointCount; + } + else if ( island->headJoint != B2_NULL_INDEX ) + { + // Both islands have joints + B2_ASSERT( island->tailJoint != B2_NULL_INDEX && island->jointCount > 0 ); + B2_ASSERT( rootIsland->tailJoint != B2_NULL_INDEX && rootIsland->jointCount > 0 ); + + b2Joint* tailJoint = b2JointArray_Get( &world->joints, rootIsland->tailJoint ); + B2_ASSERT( tailJoint->islandNext == B2_NULL_INDEX ); + tailJoint->islandNext = island->headJoint; + + b2Joint* headJoint = b2JointArray_Get( &world->joints, island->headJoint ); + B2_ASSERT( headJoint->islandPrev == B2_NULL_INDEX ); + headJoint->islandPrev = rootIsland->tailJoint; + + rootIsland->tailJoint = island->tailJoint; + rootIsland->jointCount += island->jointCount; + } + + // Track removed constraints + rootIsland->constraintRemoveCount += island->constraintRemoveCount; + + b2ValidateIsland( world, rootId ); +} + +// Iterate over all awake islands and merge any that need merging +// Islands that get merged into a root island will be removed from the awake island array +// and returned to the pool. +// todo this might be faster if b2IslandSim held the connectivity data +void b2MergeAwakeIslands( b2World* world ) +{ + b2TracyCZoneNC( merge_islands, "Merge Islands", b2_colorMediumTurquoise, true ); + + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2IslandSim* islandSims = awakeSet->islandSims.data; + int awakeIslandCount = awakeSet->islandSims.count; + + // Step 1: Ensure every child island points to its root island. This avoids merging a child island with + // a parent island that has already been merged with a grand-parent island. + for ( int i = 0; i < awakeIslandCount; ++i ) + { + int islandId = islandSims[i].islandId; + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + // find the root island + int rootId = islandId; + b2Island* rootIsland = island; + while ( rootIsland->parentIsland != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, rootIsland->parentIsland ); + if ( parent->parentIsland != B2_NULL_INDEX ) + { + // path compression + rootIsland->parentIsland = parent->parentIsland; + } + + rootId = rootIsland->parentIsland; + rootIsland = parent; + } + + if ( rootIsland != island ) + { + island->parentIsland = rootId; + } + } + + // Step 2: merge every awake island into its parent (which must be a root island) + // Reverse to support removal from awake array. + for ( int i = awakeIslandCount - 1; i >= 0; --i ) + { + int islandId = islandSims[i].islandId; + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + if ( island->parentIsland == B2_NULL_INDEX ) + { + continue; + } + + b2MergeIsland( world, island ); + + // this call does a remove swap from the end of the island sim array + b2DestroyIsland( world, islandId ); + } + + b2ValidateConnectivity( world ); + + b2TracyCZoneEnd( merge_islands ); +} + +#define B2_CONTACT_REMOVE_THRESHOLD 1 + +void b2SplitIsland( b2World* world, int baseId ) +{ + b2Island* baseIsland = b2IslandArray_Get( &world->islands, baseId ); + int setIndex = baseIsland->setIndex; + + if ( setIndex != b2_awakeSet ) + { + // can only split awake island + return; + } + + if ( baseIsland->constraintRemoveCount == 0 ) + { + // this island doesn't need to be split + return; + } + + b2ValidateIsland( world, baseId ); + + int bodyCount = baseIsland->bodyCount; + + b2Body* bodies = world->bodies.data; + b2ArenaAllocator* alloc = &world->arena; + + // No lock is needed because I ensure the allocator is not used while this task is active. + int* stack = b2AllocateArenaItem( alloc, bodyCount * sizeof( int ), "island stack" ); + int* bodyIds = b2AllocateArenaItem( alloc, bodyCount * sizeof( int ), "body ids" ); + + // Build array containing all body indices from base island. These + // serve as seed bodies for the depth first search (DFS). + int index = 0; + int nextBody = baseIsland->headBody; + while ( nextBody != B2_NULL_INDEX ) + { + bodyIds[index++] = nextBody; + b2Body* body = bodies + nextBody; + + // Clear visitation mark + body->isMarked = false; + + nextBody = body->islandNext; + } + B2_ASSERT( index == bodyCount ); + + // Clear contact island flags. Only need to consider contacts + // already in the base island. + int nextContactId = baseIsland->headContact; + while ( nextContactId != B2_NULL_INDEX ) + { + b2Contact* contact = b2ContactArray_Get( &world->contacts, nextContactId ); + contact->isMarked = false; + nextContactId = contact->islandNext; + } + + // Clear joint island flags. + int nextJoint = baseIsland->headJoint; + while ( nextJoint != B2_NULL_INDEX ) + { + b2Joint* joint = b2JointArray_Get( &world->joints, nextJoint ); + joint->isMarked = false; + nextJoint = joint->islandNext; + } + + // Done with the base split island. + b2DestroyIsland( world, baseId ); + + // Each island is found as a depth first search starting from a seed body + for ( int i = 0; i < bodyCount; ++i ) + { + int seedIndex = bodyIds[i]; + b2Body* seed = bodies + seedIndex; + B2_ASSERT( seed->setIndex == setIndex ); + + if ( seed->isMarked == true ) + { + // The body has already been visited + continue; + } + + int stackCount = 0; + stack[stackCount++] = seedIndex; + seed->isMarked = true; + + // Create new island + // No lock needed because only a single island can split per time step. No islands are being used during the constraint + // solve. However, islands are touched during body finalization. + b2Island* island = b2CreateIsland( world, setIndex ); + + int islandId = island->islandId; + + // Perform a depth first search (DFS) on the constraint graph. + while ( stackCount > 0 ) + { + // Grab the next body off the stack and add it to the island. + int bodyId = stack[--stackCount]; + b2Body* body = bodies + bodyId; + B2_ASSERT( body->setIndex == b2_awakeSet ); + B2_ASSERT( body->isMarked == true ); + + // Add body to island + body->islandId = islandId; + if ( island->tailBody != B2_NULL_INDEX ) + { + bodies[island->tailBody].islandNext = bodyId; + } + body->islandPrev = island->tailBody; + body->islandNext = B2_NULL_INDEX; + island->tailBody = bodyId; + + if ( island->headBody == B2_NULL_INDEX ) + { + island->headBody = bodyId; + } + + island->bodyCount += 1; + + // Search all contacts connected to this body. + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + B2_ASSERT( contact->contactId == contactId ); + + // Next key + contactKey = contact->edges[edgeIndex].nextKey; + + // Has this contact already been added to this island? + if ( contact->isMarked ) + { + continue; + } + + // Is this contact enabled and touching? + if ( ( contact->flags & b2_contactTouchingFlag ) == 0 ) + { + continue; + } + + contact->isMarked = true; + + int otherEdgeIndex = edgeIndex ^ 1; + int otherBodyId = contact->edges[otherEdgeIndex].bodyId; + b2Body* otherBody = bodies + otherBodyId; + + // Maybe add other body to stack + if ( otherBody->isMarked == false && otherBody->setIndex != b2_staticSet ) + { + B2_ASSERT( stackCount < bodyCount ); + stack[stackCount++] = otherBodyId; + otherBody->isMarked = true; + } + + // Add contact to island + contact->islandId = islandId; + if ( island->tailContact != B2_NULL_INDEX ) + { + b2Contact* tailContact = b2ContactArray_Get( &world->contacts, island->tailContact ); + tailContact->islandNext = contactId; + } + contact->islandPrev = island->tailContact; + contact->islandNext = B2_NULL_INDEX; + island->tailContact = contactId; + + if ( island->headContact == B2_NULL_INDEX ) + { + island->headContact = contactId; + } + + island->contactCount += 1; + } + + // Search all joints connect to this body. + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + B2_ASSERT( joint->jointId == jointId ); + + // Next key + jointKey = joint->edges[edgeIndex].nextKey; + + // Has this joint already been added to this island? + if ( joint->isMarked ) + { + continue; + } + + joint->isMarked = true; + + int otherEdgeIndex = edgeIndex ^ 1; + int otherBodyId = joint->edges[otherEdgeIndex].bodyId; + b2Body* otherBody = bodies + otherBodyId; + + // Don't simulate joints connected to disabled bodies. + if ( otherBody->setIndex == b2_disabledSet ) + { + continue; + } + + // Maybe add other body to stack + if ( otherBody->isMarked == false && otherBody->setIndex == b2_awakeSet ) + { + B2_ASSERT( stackCount < bodyCount ); + stack[stackCount++] = otherBodyId; + otherBody->isMarked = true; + } + + // Add joint to island + joint->islandId = islandId; + if ( island->tailJoint != B2_NULL_INDEX ) + { + b2Joint* tailJoint = b2JointArray_Get( &world->joints, island->tailJoint ); + tailJoint->islandNext = jointId; + } + joint->islandPrev = island->tailJoint; + joint->islandNext = B2_NULL_INDEX; + island->tailJoint = jointId; + + if ( island->headJoint == B2_NULL_INDEX ) + { + island->headJoint = jointId; + } + + island->jointCount += 1; + } + } + + b2ValidateIsland( world, islandId ); + } + + b2FreeArenaItem( alloc, bodyIds ); + b2FreeArenaItem( alloc, stack ); +} + +// Split an island because some contacts and/or joints have been removed. +// This is called during the constraint solve while islands are not being touched. This uses DFS and touches a lot of memory, +// so it can be quite slow. +// Note: contacts/joints connected to static bodies must belong to an island but don't affect island connectivity +// Note: static bodies are never in an island +// Note: this task interacts with some allocators without locks under the assumption that no other tasks +// are interacting with these data structures. +void b2SplitIslandTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + b2TracyCZoneNC( split, "Split Island", b2_colorOlive, true ); + + B2_UNUSED( startIndex, endIndex, threadIndex ); + + uint64_t ticks = b2GetTicks(); + b2World* world = context; + + B2_ASSERT( world->splitIslandId != B2_NULL_INDEX ); + + b2SplitIsland( world, world->splitIslandId ); + + world->profile.splitIslands += b2GetMilliseconds( ticks ); + b2TracyCZoneEnd( split ); +} + +#if B2_VALIDATE +void b2ValidateIsland( b2World* world, int islandId ) +{ + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + B2_ASSERT( island->islandId == islandId ); + B2_ASSERT( island->setIndex != B2_NULL_INDEX ); + B2_ASSERT( island->headBody != B2_NULL_INDEX ); + + { + B2_ASSERT( island->tailBody != B2_NULL_INDEX ); + B2_ASSERT( island->bodyCount > 0 ); + if ( island->bodyCount > 1 ) + { + B2_ASSERT( island->tailBody != island->headBody ); + } + B2_ASSERT( island->bodyCount <= b2GetIdCount( &world->bodyIdPool ) ); + + int count = 0; + int bodyId = island->headBody; + while ( bodyId != B2_NULL_INDEX ) + { + b2Body* body = b2BodyArray_Get(&world->bodies, bodyId); + B2_ASSERT( body->islandId == islandId ); + B2_ASSERT( body->setIndex == island->setIndex ); + count += 1; + + if ( count == island->bodyCount ) + { + B2_ASSERT( bodyId == island->tailBody ); + } + + bodyId = body->islandNext; + } + B2_ASSERT( count == island->bodyCount ); + } + + if ( island->headContact != B2_NULL_INDEX ) + { + B2_ASSERT( island->tailContact != B2_NULL_INDEX ); + B2_ASSERT( island->contactCount > 0 ); + if ( island->contactCount > 1 ) + { + B2_ASSERT( island->tailContact != island->headContact ); + } + B2_ASSERT( island->contactCount <= b2GetIdCount( &world->contactIdPool ) ); + + int count = 0; + int contactId = island->headContact; + while ( contactId != B2_NULL_INDEX ) + { + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + B2_ASSERT( contact->setIndex == island->setIndex ); + B2_ASSERT( contact->islandId == islandId ); + count += 1; + + if ( count == island->contactCount ) + { + B2_ASSERT( contactId == island->tailContact ); + } + + contactId = contact->islandNext; + } + B2_ASSERT( count == island->contactCount ); + } + else + { + B2_ASSERT( island->tailContact == B2_NULL_INDEX ); + B2_ASSERT( island->contactCount == 0 ); + } + + if ( island->headJoint != B2_NULL_INDEX ) + { + B2_ASSERT( island->tailJoint != B2_NULL_INDEX ); + B2_ASSERT( island->jointCount > 0 ); + if ( island->jointCount > 1 ) + { + B2_ASSERT( island->tailJoint != island->headJoint ); + } + B2_ASSERT( island->jointCount <= b2GetIdCount( &world->jointIdPool ) ); + + int count = 0; + int jointId = island->headJoint; + while ( jointId != B2_NULL_INDEX ) + { + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + B2_ASSERT( joint->setIndex == island->setIndex ); + count += 1; + + if ( count == island->jointCount ) + { + B2_ASSERT( jointId == island->tailJoint ); + } + + jointId = joint->islandNext; + } + B2_ASSERT( count == island->jointCount ); + } + else + { + B2_ASSERT( island->tailJoint == B2_NULL_INDEX ); + B2_ASSERT( island->jointCount == 0 ); + } +} + +#else + +void b2ValidateIsland( b2World* world, int islandId ) +{ + B2_UNUSED( world ); + B2_UNUSED( islandId ); +} +#endif diff --git a/3rdparty/box2d/src/island.h b/3rdparty/box2d/src/island.h new file mode 100644 index 000000000000..0243c0188428 --- /dev/null +++ b/3rdparty/box2d/src/island.h @@ -0,0 +1,89 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +#include +#include + +typedef struct b2Contact b2Contact; +typedef struct b2Joint b2Joint; +typedef struct b2World b2World; + +// Deterministic solver +// +// Collide all awake contacts +// Use bit array to emit start/stop touching events in defined order, per thread. Try using contact index, assuming contacts are +// created in a deterministic order. bit-wise OR together bit arrays and issue changes: +// - start touching: merge islands - temporary linked list - mark root island dirty - wake all - largest island is root +// - stop touching: increment constraintRemoveCount + +// Persistent island for awake bodies, joints, and contacts +// https://en.wikipedia.org/wiki/Component_(graph_theory) +// https://en.wikipedia.org/wiki/Dynamic_connectivity +// map from int to solver set and index +typedef struct b2Island +{ + // index of solver set stored in b2World + // may be B2_NULL_INDEX + int setIndex; + + // island index within set + // may be B2_NULL_INDEX + int localIndex; + + int islandId; + + int headBody; + int tailBody; + int bodyCount; + + int headContact; + int tailContact; + int contactCount; + + int headJoint; + int tailJoint; + int jointCount; + + // Union find + // todo this could go away if islands are merged immediately with b2LinkJoint and b2LinkContact + int parentIsland; + + // Keeps track of how many contacts have been removed from this island. + // This is used to determine if an island is a candidate for splitting. + int constraintRemoveCount; +} b2Island; + +// This is used to move islands across solver sets +typedef struct b2IslandSim +{ + int islandId; +} b2IslandSim; + +b2Island* b2CreateIsland( b2World* world, int setIndex ); +void b2DestroyIsland( b2World* world, int islandId ); + +// Link contacts into the island graph when it starts having contact points +void b2LinkContact( b2World* world, b2Contact* contact ); + +// Unlink contact from the island graph when it stops having contact points +void b2UnlinkContact( b2World* world, b2Contact* contact ); + +// Link a joint into the island graph when it is created +void b2LinkJoint( b2World* world, b2Joint* joint, bool mergeIslands ); + +// Unlink a joint from the island graph when it is destroyed +void b2UnlinkJoint( b2World* world, b2Joint* joint ); + +void b2MergeAwakeIslands( b2World* world ); + +void b2SplitIsland( b2World* world, int baseId ); +void b2SplitIslandTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ); + +void b2ValidateIsland( b2World* world, int islandId ); + +B2_ARRAY_INLINE( b2Island, b2Island ) +B2_ARRAY_INLINE( b2IslandSim, b2IslandSim ) diff --git a/3rdparty/box2d/src/joint.c b/3rdparty/box2d/src/joint.c new file mode 100644 index 000000000000..de8ab1cf6c0a --- /dev/null +++ b/3rdparty/box2d/src/joint.c @@ -0,0 +1,1272 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "joint.h" + +#include "body.h" +#include "contact.h" +#include "core.h" +#include "island.h" +#include "shape.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include +#include + +B2_ARRAY_SOURCE( b2Joint, b2Joint ) +B2_ARRAY_SOURCE( b2JointSim, b2JointSim ) + +b2DistanceJointDef b2DefaultDistanceJointDef( void ) +{ + b2DistanceJointDef def = { 0 }; + def.length = 1.0f; + def.maxLength = B2_HUGE; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2MotorJointDef b2DefaultMotorJointDef( void ) +{ + b2MotorJointDef def = { 0 }; + def.maxForce = 1.0f; + def.maxTorque = 1.0f; + def.correctionFactor = 0.3f; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2MouseJointDef b2DefaultMouseJointDef( void ) +{ + b2MouseJointDef def = { 0 }; + def.hertz = 4.0f; + def.dampingRatio = 1.0f; + def.maxForce = 1.0f; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2FilterJointDef b2DefaultFilterJointDef( void ) +{ + b2FilterJointDef def = { 0 }; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2PrismaticJointDef b2DefaultPrismaticJointDef( void ) +{ + b2PrismaticJointDef def = { 0 }; + def.localAxisA = (b2Vec2){ 1.0f, 0.0f }; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2RevoluteJointDef b2DefaultRevoluteJointDef( void ) +{ + b2RevoluteJointDef def = { 0 }; + def.drawSize = 0.25f; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2WeldJointDef b2DefaultWeldJointDef( void ) +{ + b2WeldJointDef def = { 0 }; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2WheelJointDef b2DefaultWheelJointDef( void ) +{ + b2WheelJointDef def = { 0 }; + def.localAxisA.y = 1.0f; + def.enableSpring = true; + def.hertz = 1.0f; + def.dampingRatio = 0.7f; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2ExplosionDef b2DefaultExplosionDef( void ) +{ + b2ExplosionDef def = { 0 }; + def.maskBits = B2_DEFAULT_MASK_BITS; + return def; +} + +b2Joint* b2GetJointFullId( b2World* world, b2JointId jointId ) +{ + int id = jointId.index1 - 1; + b2Joint* joint = b2JointArray_Get( &world->joints, id ); + B2_ASSERT( joint->jointId == id && joint->generation == jointId.generation ); + return joint; +} + +b2JointSim* b2GetJointSim( b2World* world, b2Joint* joint ) +{ + if ( joint->setIndex == b2_awakeSet ) + { + B2_ASSERT( 0 <= joint->colorIndex && joint->colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = world->constraintGraph.colors + joint->colorIndex; + return b2JointSimArray_Get( &color->jointSims, joint->localIndex ); + } + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, joint->setIndex ); + return b2JointSimArray_Get( &set->jointSims, joint->localIndex ); +} + +b2JointSim* b2GetJointSimCheckType( b2JointId jointId, b2JointType type ) +{ + B2_UNUSED( type ); + + b2World* world = b2GetWorld( jointId.world0 ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return NULL; + } + + b2Joint* joint = b2GetJointFullId( world, jointId ); + B2_ASSERT( joint->type == type ); + b2JointSim* jointSim = b2GetJointSim( world, joint ); + B2_ASSERT( jointSim->type == type ); + return jointSim; +} + +typedef struct b2JointPair +{ + b2Joint* joint; + b2JointSim* jointSim; +} b2JointPair; + +static b2JointPair b2CreateJoint( b2World* world, b2Body* bodyA, b2Body* bodyB, void* userData, float drawSize, b2JointType type, + bool collideConnected ) +{ + int bodyIdA = bodyA->id; + int bodyIdB = bodyB->id; + int maxSetIndex = b2MaxInt( bodyA->setIndex, bodyB->setIndex ); + + // Create joint id and joint + int jointId = b2AllocId( &world->jointIdPool ); + if ( jointId == world->joints.count ) + { + b2JointArray_Push( &world->joints, (b2Joint){ 0 } ); + } + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + joint->jointId = jointId; + joint->userData = userData; + joint->generation += 1; + joint->setIndex = B2_NULL_INDEX; + joint->colorIndex = B2_NULL_INDEX; + joint->localIndex = B2_NULL_INDEX; + joint->islandId = B2_NULL_INDEX; + joint->islandPrev = B2_NULL_INDEX; + joint->islandNext = B2_NULL_INDEX; + joint->drawSize = drawSize; + joint->type = type; + joint->collideConnected = collideConnected; + joint->isMarked = false; + + // Doubly linked list on bodyA + joint->edges[0].bodyId = bodyIdA; + joint->edges[0].prevKey = B2_NULL_INDEX; + joint->edges[0].nextKey = bodyA->headJointKey; + + int keyA = ( jointId << 1 ) | 0; + if ( bodyA->headJointKey != B2_NULL_INDEX ) + { + b2Joint* jointA = b2JointArray_Get( &world->joints, bodyA->headJointKey >> 1 ); + b2JointEdge* edgeA = jointA->edges + ( bodyA->headJointKey & 1 ); + edgeA->prevKey = keyA; + } + bodyA->headJointKey = keyA; + bodyA->jointCount += 1; + + // Doubly linked list on bodyB + joint->edges[1].bodyId = bodyIdB; + joint->edges[1].prevKey = B2_NULL_INDEX; + joint->edges[1].nextKey = bodyB->headJointKey; + + int keyB = ( jointId << 1 ) | 1; + if ( bodyB->headJointKey != B2_NULL_INDEX ) + { + b2Joint* jointB = b2JointArray_Get( &world->joints, bodyB->headJointKey >> 1 ); + b2JointEdge* edgeB = jointB->edges + ( bodyB->headJointKey & 1 ); + edgeB->prevKey = keyB; + } + bodyB->headJointKey = keyB; + bodyB->jointCount += 1; + + b2JointSim* jointSim; + + if ( bodyA->setIndex == b2_disabledSet || bodyB->setIndex == b2_disabledSet ) + { + // if either body is disabled, create in disabled set + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_disabledSet ); + joint->setIndex = b2_disabledSet; + joint->localIndex = set->jointSims.count; + + jointSim = b2JointSimArray_Add( &set->jointSims ); + memset( jointSim, 0, sizeof( b2JointSim ) ); + + jointSim->jointId = jointId; + jointSim->bodyIdA = bodyIdA; + jointSim->bodyIdB = bodyIdB; + } + else if ( bodyA->setIndex == b2_staticSet && bodyB->setIndex == b2_staticSet ) + { + // joint is connecting static bodies + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_staticSet ); + joint->setIndex = b2_staticSet; + joint->localIndex = set->jointSims.count; + + jointSim = b2JointSimArray_Add( &set->jointSims ); + memset( jointSim, 0, sizeof( b2JointSim ) ); + + jointSim->jointId = jointId; + jointSim->bodyIdA = bodyIdA; + jointSim->bodyIdB = bodyIdB; + } + else if ( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ) + { + // if either body is sleeping, wake it + if ( maxSetIndex >= b2_firstSleepingSet ) + { + b2WakeSolverSet( world, maxSetIndex ); + } + + joint->setIndex = b2_awakeSet; + + jointSim = b2CreateJointInGraph( world, joint ); + jointSim->jointId = jointId; + jointSim->bodyIdA = bodyIdA; + jointSim->bodyIdB = bodyIdB; + } + else + { + // joint connected between sleeping and/or static bodies + B2_ASSERT( bodyA->setIndex >= b2_firstSleepingSet || bodyB->setIndex >= b2_firstSleepingSet ); + B2_ASSERT( bodyA->setIndex != b2_staticSet || bodyB->setIndex != b2_staticSet ); + + // joint should go into the sleeping set (not static set) + int setIndex = maxSetIndex; + + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + joint->setIndex = setIndex; + joint->localIndex = set->jointSims.count; + + jointSim = b2JointSimArray_Add( &set->jointSims ); + memset( jointSim, 0, sizeof( b2JointSim ) ); + + jointSim->jointId = jointId; + jointSim->bodyIdA = bodyIdA; + jointSim->bodyIdB = bodyIdB; + + if ( bodyA->setIndex != bodyB->setIndex && bodyA->setIndex >= b2_firstSleepingSet && + bodyB->setIndex >= b2_firstSleepingSet ) + { + // merge sleeping sets + b2MergeSolverSets( world, bodyA->setIndex, bodyB->setIndex ); + B2_ASSERT( bodyA->setIndex == bodyB->setIndex ); + + // fix potentially invalid set index + setIndex = bodyA->setIndex; + + b2SolverSet* mergedSet = b2SolverSetArray_Get( &world->solverSets, setIndex ); + + // Careful! The joint sim pointer was orphaned by the set merge. + jointSim = b2JointSimArray_Get( &mergedSet->jointSims, joint->localIndex ); + } + + B2_ASSERT( joint->setIndex == setIndex ); + } + + B2_ASSERT( jointSim->jointId == jointId ); + B2_ASSERT( jointSim->bodyIdA == bodyIdA ); + B2_ASSERT( jointSim->bodyIdB == bodyIdB ); + + if ( joint->setIndex > b2_disabledSet ) + { + // Add edge to island graph + bool mergeIslands = true; + b2LinkJoint( world, joint, mergeIslands ); + } + + b2ValidateSolverSets( world ); + + return (b2JointPair){ joint, jointSim }; +} + +static void b2DestroyContactsBetweenBodies( b2World* world, b2Body* bodyA, b2Body* bodyB ) +{ + int contactKey; + int otherBodyId; + + // use the smaller of the two contact lists + if ( bodyA->contactCount < bodyB->contactCount ) + { + contactKey = bodyA->headContactKey; + otherBodyId = bodyB->id; + } + else + { + contactKey = bodyB->headContactKey; + otherBodyId = bodyA->id; + } + + // no need to wake bodies when a joint removes collision between them + bool wakeBodies = false; + + // destroy the contacts + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contactKey = contact->edges[edgeIndex].nextKey; + + int otherEdgeIndex = edgeIndex ^ 1; + if ( contact->edges[otherEdgeIndex].bodyId == otherBodyId ) + { + // Careful, this removes the contact from the current doubly linked list + b2DestroyContact( world, contact, wakeBodies ); + } + } + + b2ValidateSolverSets( world ); +} + +b2JointId b2CreateDistanceJoint( b2WorldId worldId, const b2DistanceJointDef* def ) +{ + B2_CHECK_DEF( def ); + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + B2_ASSERT( b2Body_IsValid( def->bodyIdA ) ); + B2_ASSERT( b2Body_IsValid( def->bodyIdB ) ); + B2_ASSERT( b2IsValidFloat( def->length ) && def->length > 0.0f ); + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_distanceJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_distanceJoint; + joint->localOriginAnchorA = def->localAnchorA; + joint->localOriginAnchorB = def->localAnchorB; + + b2DistanceJoint empty = { 0 }; + joint->distanceJoint = empty; + joint->distanceJoint.length = b2MaxFloat( def->length, B2_LINEAR_SLOP ); + joint->distanceJoint.hertz = def->hertz; + joint->distanceJoint.dampingRatio = def->dampingRatio; + joint->distanceJoint.minLength = b2MaxFloat( def->minLength, B2_LINEAR_SLOP ); + joint->distanceJoint.maxLength = b2MaxFloat( def->minLength, def->maxLength ); + joint->distanceJoint.maxMotorForce = def->maxMotorForce; + joint->distanceJoint.motorSpeed = def->motorSpeed; + joint->distanceJoint.enableSpring = def->enableSpring; + joint->distanceJoint.enableLimit = def->enableLimit; + joint->distanceJoint.enableMotor = def->enableMotor; + joint->distanceJoint.impulse = 0.0f; + joint->distanceJoint.lowerImpulse = 0.0f; + joint->distanceJoint.upperImpulse = 0.0f; + joint->distanceJoint.motorImpulse = 0.0f; + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateMotorJoint( b2WorldId worldId, const b2MotorJointDef* def ) +{ + B2_CHECK_DEF( def ); + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_motorJoint, def->collideConnected ); + b2JointSim* joint = pair.jointSim; + + joint->type = b2_motorJoint; + joint->localOriginAnchorA = (b2Vec2){ 0.0f, 0.0f }; + joint->localOriginAnchorB = (b2Vec2){ 0.0f, 0.0f }; + joint->motorJoint = (b2MotorJoint){ 0 }; + joint->motorJoint.linearOffset = def->linearOffset; + joint->motorJoint.angularOffset = def->angularOffset; + joint->motorJoint.maxForce = def->maxForce; + joint->motorJoint.maxTorque = def->maxTorque; + joint->motorJoint.correctionFactor = b2ClampFloat( def->correctionFactor, 0.0f, 1.0f ); + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateMouseJoint( b2WorldId worldId, const b2MouseJointDef* def ) +{ + B2_CHECK_DEF( def ); + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2Transform transformA = b2GetBodyTransformQuick( world, bodyA ); + b2Transform transformB = b2GetBodyTransformQuick( world, bodyB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_mouseJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_mouseJoint; + joint->localOriginAnchorA = b2InvTransformPoint( transformA, def->target ); + joint->localOriginAnchorB = b2InvTransformPoint( transformB, def->target ); + + b2MouseJoint empty = { 0 }; + joint->mouseJoint = empty; + joint->mouseJoint.targetA = def->target; + joint->mouseJoint.hertz = def->hertz; + joint->mouseJoint.dampingRatio = def->dampingRatio; + joint->mouseJoint.maxForce = def->maxForce; + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateFilterJoint( b2WorldId worldId, const b2FilterJointDef* def ) +{ + B2_CHECK_DEF( def ); + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + bool collideConnected = false; + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_filterJoint, collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_filterJoint; + joint->localOriginAnchorA = b2Vec2_zero; + joint->localOriginAnchorB = b2Vec2_zero; + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateRevoluteJoint( b2WorldId worldId, const b2RevoluteJointDef* def ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( def->lowerAngle <= def->upperAngle ); + B2_ASSERT( def->lowerAngle >= -0.95f * B2_PI ); + B2_ASSERT( def->upperAngle <= 0.95f * B2_PI ); + + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = + b2CreateJoint( world, bodyA, bodyB, def->userData, def->drawSize, b2_revoluteJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_revoluteJoint; + joint->localOriginAnchorA = def->localAnchorA; + joint->localOriginAnchorB = def->localAnchorB; + + b2RevoluteJoint empty = { 0 }; + joint->revoluteJoint = empty; + + joint->revoluteJoint.referenceAngle = b2ClampFloat( def->referenceAngle, -B2_PI, B2_PI ); + joint->revoluteJoint.linearImpulse = b2Vec2_zero; + joint->revoluteJoint.axialMass = 0.0f; + joint->revoluteJoint.springImpulse = 0.0f; + joint->revoluteJoint.motorImpulse = 0.0f; + joint->revoluteJoint.lowerImpulse = 0.0f; + joint->revoluteJoint.upperImpulse = 0.0f; + joint->revoluteJoint.hertz = def->hertz; + joint->revoluteJoint.dampingRatio = def->dampingRatio; + joint->revoluteJoint.lowerAngle = def->lowerAngle; + joint->revoluteJoint.upperAngle = def->upperAngle; + joint->revoluteJoint.maxMotorTorque = def->maxMotorTorque; + joint->revoluteJoint.motorSpeed = def->motorSpeed; + joint->revoluteJoint.enableSpring = def->enableSpring; + joint->revoluteJoint.enableLimit = def->enableLimit; + joint->revoluteJoint.enableMotor = def->enableMotor; + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreatePrismaticJoint( b2WorldId worldId, const b2PrismaticJointDef* def ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( def->lowerTranslation <= def->upperTranslation ); + + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_prismaticJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_prismaticJoint; + joint->localOriginAnchorA = def->localAnchorA; + joint->localOriginAnchorB = def->localAnchorB; + + b2PrismaticJoint empty = { 0 }; + joint->prismaticJoint = empty; + + joint->prismaticJoint.localAxisA = b2Normalize( def->localAxisA ); + joint->prismaticJoint.referenceAngle = def->referenceAngle; + joint->prismaticJoint.impulse = b2Vec2_zero; + joint->prismaticJoint.axialMass = 0.0f; + joint->prismaticJoint.springImpulse = 0.0f; + joint->prismaticJoint.motorImpulse = 0.0f; + joint->prismaticJoint.lowerImpulse = 0.0f; + joint->prismaticJoint.upperImpulse = 0.0f; + joint->prismaticJoint.hertz = def->hertz; + joint->prismaticJoint.dampingRatio = def->dampingRatio; + joint->prismaticJoint.lowerTranslation = def->lowerTranslation; + joint->prismaticJoint.upperTranslation = def->upperTranslation; + joint->prismaticJoint.maxMotorForce = def->maxMotorForce; + joint->prismaticJoint.motorSpeed = def->motorSpeed; + joint->prismaticJoint.enableSpring = def->enableSpring; + joint->prismaticJoint.enableLimit = def->enableLimit; + joint->prismaticJoint.enableMotor = def->enableMotor; + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateWeldJoint( b2WorldId worldId, const b2WeldJointDef* def ) +{ + B2_CHECK_DEF( def ); + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_weldJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_weldJoint; + joint->localOriginAnchorA = def->localAnchorA; + joint->localOriginAnchorB = def->localAnchorB; + + b2WeldJoint empty = { 0 }; + joint->weldJoint = empty; + joint->weldJoint.referenceAngle = def->referenceAngle; + joint->weldJoint.linearHertz = def->linearHertz; + joint->weldJoint.linearDampingRatio = def->linearDampingRatio; + joint->weldJoint.angularHertz = def->angularHertz; + joint->weldJoint.angularDampingRatio = def->angularDampingRatio; + joint->weldJoint.linearImpulse = b2Vec2_zero; + joint->weldJoint.angularImpulse = 0.0f; + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +b2JointId b2CreateWheelJoint( b2WorldId worldId, const b2WheelJointDef* def ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( def->lowerTranslation <= def->upperTranslation ); + + b2World* world = b2GetWorldFromId( worldId ); + + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return (b2JointId){ 0 }; + } + + b2Body* bodyA = b2GetBodyFullId( world, def->bodyIdA ); + b2Body* bodyB = b2GetBodyFullId( world, def->bodyIdB ); + + b2JointPair pair = b2CreateJoint( world, bodyA, bodyB, def->userData, 1.0f, b2_wheelJoint, def->collideConnected ); + + b2JointSim* joint = pair.jointSim; + joint->type = b2_wheelJoint; + joint->localOriginAnchorA = def->localAnchorA; + joint->localOriginAnchorB = def->localAnchorB; + + joint->wheelJoint = (b2WheelJoint){ 0 }; + joint->wheelJoint.localAxisA = b2Normalize( def->localAxisA ); + joint->wheelJoint.perpMass = 0.0f; + joint->wheelJoint.axialMass = 0.0f; + joint->wheelJoint.motorImpulse = 0.0f; + joint->wheelJoint.lowerImpulse = 0.0f; + joint->wheelJoint.upperImpulse = 0.0f; + joint->wheelJoint.lowerTranslation = def->lowerTranslation; + joint->wheelJoint.upperTranslation = def->upperTranslation; + joint->wheelJoint.maxMotorTorque = def->maxMotorTorque; + joint->wheelJoint.motorSpeed = def->motorSpeed; + joint->wheelJoint.hertz = def->hertz; + joint->wheelJoint.dampingRatio = def->dampingRatio; + joint->wheelJoint.enableSpring = def->enableSpring; + joint->wheelJoint.enableLimit = def->enableLimit; + joint->wheelJoint.enableMotor = def->enableMotor; + + // If the joint prevents collisions, then destroy all contacts between attached bodies + if ( def->collideConnected == false ) + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } + + b2JointId jointId = { joint->jointId + 1, world->worldId, pair.joint->generation }; + return jointId; +} + +void b2DestroyJointInternal( b2World* world, b2Joint* joint, bool wakeBodies ) +{ + int jointId = joint->jointId; + + b2JointEdge* edgeA = joint->edges + 0; + b2JointEdge* edgeB = joint->edges + 1; + + int idA = edgeA->bodyId; + int idB = edgeB->bodyId; + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + // Remove from body A + if ( edgeA->prevKey != B2_NULL_INDEX ) + { + b2Joint* prevJoint = b2JointArray_Get( &world->joints, edgeA->prevKey >> 1 ); + b2JointEdge* prevEdge = prevJoint->edges + ( edgeA->prevKey & 1 ); + prevEdge->nextKey = edgeA->nextKey; + } + + if ( edgeA->nextKey != B2_NULL_INDEX ) + { + b2Joint* nextJoint = b2JointArray_Get( &world->joints, edgeA->nextKey >> 1 ); + b2JointEdge* nextEdge = nextJoint->edges + ( edgeA->nextKey & 1 ); + nextEdge->prevKey = edgeA->prevKey; + } + + int edgeKeyA = ( jointId << 1 ) | 0; + if ( bodyA->headJointKey == edgeKeyA ) + { + bodyA->headJointKey = edgeA->nextKey; + } + + bodyA->jointCount -= 1; + + // Remove from body B + if ( edgeB->prevKey != B2_NULL_INDEX ) + { + b2Joint* prevJoint = b2JointArray_Get( &world->joints, edgeB->prevKey >> 1 ); + b2JointEdge* prevEdge = prevJoint->edges + ( edgeB->prevKey & 1 ); + prevEdge->nextKey = edgeB->nextKey; + } + + if ( edgeB->nextKey != B2_NULL_INDEX ) + { + b2Joint* nextJoint = b2JointArray_Get( &world->joints, edgeB->nextKey >> 1 ); + b2JointEdge* nextEdge = nextJoint->edges + ( edgeB->nextKey & 1 ); + nextEdge->prevKey = edgeB->prevKey; + } + + int edgeKeyB = ( jointId << 1 ) | 1; + if ( bodyB->headJointKey == edgeKeyB ) + { + bodyB->headJointKey = edgeB->nextKey; + } + + bodyB->jointCount -= 1; + + if ( joint->islandId != B2_NULL_INDEX ) + { + B2_ASSERT( joint->setIndex > b2_disabledSet ); + b2UnlinkJoint( world, joint ); + } + else + { + B2_ASSERT( joint->setIndex <= b2_disabledSet ); + } + + // Remove joint from solver set that owns it + int setIndex = joint->setIndex; + int localIndex = joint->localIndex; + + if ( setIndex == b2_awakeSet ) + { + b2RemoveJointFromGraph( world, joint->edges[0].bodyId, joint->edges[1].bodyId, joint->colorIndex, localIndex ); + } + else + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + int movedIndex = b2JointSimArray_RemoveSwap( &set->jointSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix moved joint + b2JointSim* movedJointSim = set->jointSims.data + localIndex; + int movedId = movedJointSim->jointId; + b2Joint* movedJoint = b2JointArray_Get( &world->joints, movedId ); + B2_ASSERT( movedJoint->localIndex == movedIndex ); + movedJoint->localIndex = localIndex; + } + } + + // Free joint and id (preserve joint generation) + joint->setIndex = B2_NULL_INDEX; + joint->localIndex = B2_NULL_INDEX; + joint->colorIndex = B2_NULL_INDEX; + joint->jointId = B2_NULL_INDEX; + b2FreeId( &world->jointIdPool, jointId ); + + if ( wakeBodies ) + { + b2WakeBody( world, bodyA ); + b2WakeBody( world, bodyB ); + } + + b2ValidateSolverSets( world ); +} + +void b2DestroyJoint( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + B2_ASSERT( world->locked == false ); + + if ( world->locked ) + { + return; + } + + b2Joint* joint = b2GetJointFullId( world, jointId ); + + b2DestroyJointInternal( world, joint, true ); +} + +b2JointType b2Joint_GetType( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + return joint->type; +} + +b2BodyId b2Joint_GetBodyA( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + return b2MakeBodyId( world, joint->edges[0].bodyId ); +} + +b2BodyId b2Joint_GetBodyB( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + return b2MakeBodyId( world, joint->edges[1].bodyId ); +} + +b2WorldId b2Joint_GetWorld( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + return (b2WorldId){ jointId.world0 + 1, world->generation }; +} + +b2Vec2 b2Joint_GetLocalAnchorA( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + b2JointSim* jointSim = b2GetJointSim( world, joint ); + return jointSim->localOriginAnchorA; +} + +b2Vec2 b2Joint_GetLocalAnchorB( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + b2JointSim* jointSim = b2GetJointSim( world, joint ); + return jointSim->localOriginAnchorB; +} + +void b2Joint_SetCollideConnected( b2JointId jointId, bool shouldCollide ) +{ + b2World* world = b2GetWorldLocked( jointId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Joint* joint = b2GetJointFullId( world, jointId ); + if ( joint->collideConnected == shouldCollide ) + { + return; + } + + joint->collideConnected = shouldCollide; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + + if ( shouldCollide ) + { + // need to tell the broad-phase to look for new pairs for one of the + // two bodies. Pick the one with the fewest shapes. + int shapeCountA = bodyA->shapeCount; + int shapeCountB = bodyB->shapeCount; + + int shapeId = shapeCountA < shapeCountB ? bodyA->headShapeId : bodyB->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + if ( shape->proxyKey != B2_NULL_INDEX ) + { + b2BufferMove( &world->broadPhase, shape->proxyKey ); + } + + shapeId = shape->nextShapeId; + } + } + else + { + b2DestroyContactsBetweenBodies( world, bodyA, bodyB ); + } +} + +bool b2Joint_GetCollideConnected( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + return joint->collideConnected; +} + +void b2Joint_SetUserData( b2JointId jointId, void* userData ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + joint->userData = userData; +} + +void* b2Joint_GetUserData( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + return joint->userData; +} + +void b2Joint_WakeBodies( b2JointId jointId ) +{ + b2World* world = b2GetWorldLocked( jointId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Joint* joint = b2GetJointFullId( world, jointId ); + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + + b2WakeBody( world, bodyA ); + b2WakeBody( world, bodyB ); +} + +b2Vec2 b2Joint_GetConstraintForce( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + b2JointSim* base = b2GetJointSim( world, joint ); + + switch ( joint->type ) + { + case b2_distanceJoint: + return b2GetDistanceJointForce( world, base ); + + case b2_motorJoint: + return b2GetMotorJointForce( world, base ); + + case b2_mouseJoint: + return b2GetMouseJointForce( world, base ); + + case b2_filterJoint: + return b2Vec2_zero; + + case b2_prismaticJoint: + return b2GetPrismaticJointForce( world, base ); + + case b2_revoluteJoint: + return b2GetRevoluteJointForce( world, base ); + + case b2_weldJoint: + return b2GetWeldJointForce( world, base ); + + case b2_wheelJoint: + return b2GetWheelJointForce( world, base ); + + default: + B2_ASSERT( false ); + return b2Vec2_zero; + } +} + +float b2Joint_GetConstraintTorque( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + b2JointSim* base = b2GetJointSim( world, joint ); + + switch ( joint->type ) + { + case b2_distanceJoint: + return 0.0f; + + case b2_motorJoint: + return b2GetMotorJointTorque( world, base ); + + case b2_mouseJoint: + return b2GetMouseJointTorque( world, base ); + + case b2_filterJoint: + return 0.0f; + + case b2_prismaticJoint: + return b2GetPrismaticJointTorque( world, base ); + + case b2_revoluteJoint: + return b2GetRevoluteJointTorque( world, base ); + + case b2_weldJoint: + return b2GetWeldJointTorque( world, base ); + + case b2_wheelJoint: + return b2GetWheelJointTorque( world, base ); + + default: + B2_ASSERT( false ); + return 0.0f; + } +} + +void b2PrepareJoint( b2JointSim* joint, b2StepContext* context ) +{ + switch ( joint->type ) + { + case b2_distanceJoint: + b2PrepareDistanceJoint( joint, context ); + break; + + case b2_motorJoint: + b2PrepareMotorJoint( joint, context ); + break; + + case b2_mouseJoint: + b2PrepareMouseJoint( joint, context ); + break; + + case b2_filterJoint: + break; + + case b2_prismaticJoint: + b2PreparePrismaticJoint( joint, context ); + break; + + case b2_revoluteJoint: + b2PrepareRevoluteJoint( joint, context ); + break; + + case b2_weldJoint: + b2PrepareWeldJoint( joint, context ); + break; + + case b2_wheelJoint: + b2PrepareWheelJoint( joint, context ); + break; + + default: + B2_ASSERT( false ); + } +} + +void b2WarmStartJoint( b2JointSim* joint, b2StepContext* context ) +{ + switch ( joint->type ) + { + case b2_distanceJoint: + b2WarmStartDistanceJoint( joint, context ); + break; + + case b2_motorJoint: + b2WarmStartMotorJoint( joint, context ); + break; + + case b2_mouseJoint: + b2WarmStartMouseJoint( joint, context ); + break; + + case b2_filterJoint: + break; + + case b2_prismaticJoint: + b2WarmStartPrismaticJoint( joint, context ); + break; + + case b2_revoluteJoint: + b2WarmStartRevoluteJoint( joint, context ); + break; + + case b2_weldJoint: + b2WarmStartWeldJoint( joint, context ); + break; + + case b2_wheelJoint: + b2WarmStartWheelJoint( joint, context ); + break; + + default: + B2_ASSERT( false ); + } +} + +void b2SolveJoint( b2JointSim* joint, b2StepContext* context, bool useBias ) +{ + switch ( joint->type ) + { + case b2_distanceJoint: + b2SolveDistanceJoint( joint, context, useBias ); + break; + + case b2_motorJoint: + b2SolveMotorJoint( joint, context, useBias ); + break; + + case b2_mouseJoint: + b2SolveMouseJoint( joint, context ); + break; + + case b2_filterJoint: + break; + + case b2_prismaticJoint: + b2SolvePrismaticJoint( joint, context, useBias ); + break; + + case b2_revoluteJoint: + b2SolveRevoluteJoint( joint, context, useBias ); + break; + + case b2_weldJoint: + b2SolveWeldJoint( joint, context, useBias ); + break; + + case b2_wheelJoint: + b2SolveWheelJoint( joint, context, useBias ); + break; + + default: + B2_ASSERT( false ); + } +} + +void b2PrepareOverflowJoints( b2StepContext* context ) +{ + b2TracyCZoneNC( prepare_joints, "PrepJoints", b2_colorOldLace, true ); + + b2ConstraintGraph* graph = context->graph; + b2JointSim* joints = graph->colors[B2_OVERFLOW_INDEX].jointSims.data; + int jointCount = graph->colors[B2_OVERFLOW_INDEX].jointSims.count; + + for ( int i = 0; i < jointCount; ++i ) + { + b2JointSim* joint = joints + i; + b2PrepareJoint( joint, context ); + } + + b2TracyCZoneEnd( prepare_joints ); +} + +void b2WarmStartOverflowJoints( b2StepContext* context ) +{ + b2TracyCZoneNC( prepare_joints, "PrepJoints", b2_colorOldLace, true ); + + b2ConstraintGraph* graph = context->graph; + b2JointSim* joints = graph->colors[B2_OVERFLOW_INDEX].jointSims.data; + int jointCount = graph->colors[B2_OVERFLOW_INDEX].jointSims.count; + + for ( int i = 0; i < jointCount; ++i ) + { + b2JointSim* joint = joints + i; + b2WarmStartJoint( joint, context ); + } + + b2TracyCZoneEnd( prepare_joints ); +} + +void b2SolveOverflowJoints( b2StepContext* context, bool useBias ) +{ + b2TracyCZoneNC( solve_joints, "SolveJoints", b2_colorLemonChiffon, true ); + + b2ConstraintGraph* graph = context->graph; + b2JointSim* joints = graph->colors[B2_OVERFLOW_INDEX].jointSims.data; + int jointCount = graph->colors[B2_OVERFLOW_INDEX].jointSims.count; + + for ( int i = 0; i < jointCount; ++i ) + { + b2JointSim* joint = joints + i; + b2SolveJoint( joint, context, useBias ); + } + + b2TracyCZoneEnd( solve_joints ); +} + +void b2DrawJoint( b2DebugDraw* draw, b2World* world, b2Joint* joint ) +{ + b2Body* bodyA = b2BodyArray_Get( &world->bodies, joint->edges[0].bodyId ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, joint->edges[1].bodyId ); + if ( bodyA->setIndex == b2_disabledSet || bodyB->setIndex == b2_disabledSet ) + { + return; + } + + b2JointSim* jointSim = b2GetJointSim( world, joint ); + + b2Transform transformA = b2GetBodyTransformQuick( world, bodyA ); + b2Transform transformB = b2GetBodyTransformQuick( world, bodyB ); + b2Vec2 pA = b2TransformPoint( transformA, jointSim->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, jointSim->localOriginAnchorB ); + + b2HexColor color = b2_colorDarkSeaGreen; + + switch ( joint->type ) + { + case b2_distanceJoint: + b2DrawDistanceJoint( draw, jointSim, transformA, transformB ); + break; + + case b2_mouseJoint: + { + b2Vec2 target = jointSim->mouseJoint.targetA; + + b2HexColor c1 = b2_colorGreen; + draw->DrawPointFcn( target, 4.0f, c1, draw->context ); + draw->DrawPointFcn( pB, 4.0f, c1, draw->context ); + + b2HexColor c2 = b2_colorLightGray; + draw->DrawSegmentFcn( target, pB, c2, draw->context ); + } + break; + + case b2_filterJoint: + { + draw->DrawSegmentFcn( pA, pB, b2_colorGold, draw->context ); + } + break; + + case b2_prismaticJoint: + b2DrawPrismaticJoint( draw, jointSim, transformA, transformB ); + break; + + case b2_revoluteJoint: + b2DrawRevoluteJoint( draw, jointSim, transformA, transformB, joint->drawSize ); + break; + + case b2_wheelJoint: + b2DrawWheelJoint( draw, jointSim, transformA, transformB ); + break; + + default: + draw->DrawSegmentFcn( transformA.p, pA, color, draw->context ); + draw->DrawSegmentFcn( pA, pB, color, draw->context ); + draw->DrawSegmentFcn( transformB.p, pB, color, draw->context ); + } + + if ( draw->drawGraphColors ) + { + b2HexColor colors[B2_GRAPH_COLOR_COUNT] = { b2_colorRed, b2_colorOrange, b2_colorYellow, b2_colorGreen, + b2_colorCyan, b2_colorBlue, b2_colorViolet, b2_colorPink, + b2_colorChocolate, b2_colorGoldenRod, b2_colorCoral, b2_colorBlack }; + + int colorIndex = joint->colorIndex; + if ( colorIndex != B2_NULL_INDEX ) + { + b2Vec2 p = b2Lerp( pA, pB, 0.5f ); + draw->DrawPointFcn( p, 5.0f, colors[colorIndex], draw->context ); + } + } +} diff --git a/3rdparty/box2d/src/joint.h b/3rdparty/box2d/src/joint.h new file mode 100644 index 000000000000..e123661602f3 --- /dev/null +++ b/3rdparty/box2d/src/joint.h @@ -0,0 +1,335 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT +#pragma once + +#include "array.h" +#include "solver.h" + +#include "box2d/types.h" + +typedef struct b2DebugDraw b2DebugDraw; +typedef struct b2StepContext b2StepContext; +typedef struct b2World b2World; + +/// A joint edge is used to connect bodies and joints together +/// in a joint graph where each body is a node and each joint +/// is an edge. A joint edge belongs to a doubly linked list +/// maintained in each attached body. Each joint has two joint +/// nodes, one for each attached body. +typedef struct b2JointEdge +{ + int bodyId; + int prevKey; + int nextKey; +} b2JointEdge; + +// Map from b2JointId to b2Joint in the solver sets +typedef struct b2Joint +{ + void* userData; + + // index of simulation set stored in b2World + // B2_NULL_INDEX when slot is free + int setIndex; + + // index into the constraint graph color array, may be B2_NULL_INDEX for sleeping/disabled joints + // B2_NULL_INDEX when slot is free + int colorIndex; + + // joint index within set or graph color + // B2_NULL_INDEX when slot is free + int localIndex; + + b2JointEdge edges[2]; + + int jointId; + int islandId; + int islandPrev; + int islandNext; + + float drawSize; + + b2JointType type; + + // This is monotonically advanced when a body is allocated in this slot + // Used to check for invalid b2JointId + uint16_t generation; + + bool isMarked; + bool collideConnected; + +} b2Joint; + +typedef struct b2DistanceJoint +{ + float length; + float hertz; + float dampingRatio; + float minLength; + float maxLength; + + float maxMotorForce; + float motorSpeed; + + float impulse; + float lowerImpulse; + float upperImpulse; + float motorImpulse; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 deltaCenter; + b2Softness distanceSoftness; + float axialMass; + + bool enableSpring; + bool enableLimit; + bool enableMotor; +} b2DistanceJoint; + +typedef struct b2MotorJoint +{ + b2Vec2 linearOffset; + float angularOffset; + b2Vec2 linearImpulse; + float angularImpulse; + float maxForce; + float maxTorque; + float correctionFactor; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 deltaCenter; + float deltaAngle; + b2Mat22 linearMass; + float angularMass; +} b2MotorJoint; + +typedef struct b2MouseJoint +{ + b2Vec2 targetA; + float hertz; + float dampingRatio; + float maxForce; + + b2Vec2 linearImpulse; + float angularImpulse; + + b2Softness linearSoftness; + b2Softness angularSoftness; + int indexB; + b2Vec2 anchorB; + b2Vec2 deltaCenter; + b2Mat22 linearMass; +} b2MouseJoint; + +typedef struct b2PrismaticJoint +{ + b2Vec2 localAxisA; + b2Vec2 impulse; + float springImpulse; + float motorImpulse; + float lowerImpulse; + float upperImpulse; + float hertz; + float dampingRatio; + float maxMotorForce; + float motorSpeed; + float referenceAngle; + float lowerTranslation; + float upperTranslation; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 axisA; + b2Vec2 deltaCenter; + float deltaAngle; + float axialMass; + b2Softness springSoftness; + + bool enableSpring; + bool enableLimit; + bool enableMotor; +} b2PrismaticJoint; + +typedef struct b2RevoluteJoint +{ + b2Vec2 linearImpulse; + float springImpulse; + float motorImpulse; + float lowerImpulse; + float upperImpulse; + float hertz; + float dampingRatio; + float maxMotorTorque; + float motorSpeed; + float referenceAngle; + float lowerAngle; + float upperAngle; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 deltaCenter; + float deltaAngle; + float axialMass; + b2Softness springSoftness; + + bool enableSpring; + bool enableMotor; + bool enableLimit; +} b2RevoluteJoint; + +typedef struct b2WeldJoint +{ + float referenceAngle; + float linearHertz; + float linearDampingRatio; + float angularHertz; + float angularDampingRatio; + + b2Softness linearSoftness; + b2Softness angularSoftness; + b2Vec2 linearImpulse; + float angularImpulse; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 deltaCenter; + float deltaAngle; + float axialMass; +} b2WeldJoint; + +typedef struct b2WheelJoint +{ + b2Vec2 localAxisA; + float perpImpulse; + float motorImpulse; + float springImpulse; + float lowerImpulse; + float upperImpulse; + float maxMotorTorque; + float motorSpeed; + float lowerTranslation; + float upperTranslation; + float hertz; + float dampingRatio; + + int indexA; + int indexB; + b2Vec2 anchorA; + b2Vec2 anchorB; + b2Vec2 axisA; + b2Vec2 deltaCenter; + float perpMass; + float motorMass; + float axialMass; + b2Softness springSoftness; + + bool enableSpring; + bool enableMotor; + bool enableLimit; +} b2WheelJoint; + +/// The base joint class. Joints are used to constraint two bodies together in +/// various fashions. Some joints also feature limits and motors. +typedef struct b2JointSim +{ + int jointId; + + int bodyIdA; + int bodyIdB; + + b2JointType type; + + // Anchors relative to body origin + b2Vec2 localOriginAnchorA; + b2Vec2 localOriginAnchorB; + + float invMassA, invMassB; + float invIA, invIB; + + union + { + b2DistanceJoint distanceJoint; + b2MotorJoint motorJoint; + b2MouseJoint mouseJoint; + b2RevoluteJoint revoluteJoint; + b2PrismaticJoint prismaticJoint; + b2WeldJoint weldJoint; + b2WheelJoint wheelJoint; + }; +} b2JointSim; + +void b2DestroyJointInternal( b2World* world, b2Joint* joint, bool wakeBodies ); + +b2Joint* b2GetJointFullId( b2World* world, b2JointId jointId ); +b2JointSim* b2GetJointSim( b2World* world, b2Joint* joint ); +b2JointSim* b2GetJointSimCheckType( b2JointId jointId, b2JointType type ); + +void b2PrepareJoint( b2JointSim* joint, b2StepContext* context ); +void b2WarmStartJoint( b2JointSim* joint, b2StepContext* context ); +void b2SolveJoint( b2JointSim* joint, b2StepContext* context, bool useBias ); + +void b2PrepareOverflowJoints( b2StepContext* context ); +void b2WarmStartOverflowJoints( b2StepContext* context ); +void b2SolveOverflowJoints( b2StepContext* context, bool useBias ); + +void b2DrawJoint( b2DebugDraw* draw, b2World* world, b2Joint* joint ); + +b2Vec2 b2GetDistanceJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetMotorJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetMouseJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetPrismaticJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetRevoluteJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetWeldJointForce( b2World* world, b2JointSim* base ); +b2Vec2 b2GetWheelJointForce( b2World* world, b2JointSim* base ); + +float b2GetMotorJointTorque( b2World* world, b2JointSim* base ); +float b2GetMouseJointTorque( b2World* world, b2JointSim* base ); +float b2GetPrismaticJointTorque( b2World* world, b2JointSim* base ); +float b2GetRevoluteJointTorque( b2World* world, b2JointSim* base ); +float b2GetWeldJointTorque( b2World* world, b2JointSim* base ); +float b2GetWheelJointTorque( b2World* world, b2JointSim* base ); + +void b2PrepareDistanceJoint( b2JointSim* base, b2StepContext* context ); +void b2PrepareMotorJoint( b2JointSim* base, b2StepContext* context ); +void b2PrepareMouseJoint( b2JointSim* base, b2StepContext* context ); +void b2PreparePrismaticJoint( b2JointSim* base, b2StepContext* context ); +void b2PrepareRevoluteJoint( b2JointSim* base, b2StepContext* context ); +void b2PrepareWeldJoint( b2JointSim* base, b2StepContext* context ); +void b2PrepareWheelJoint( b2JointSim* base, b2StepContext* context ); + +void b2WarmStartDistanceJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartMotorJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartMouseJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartPrismaticJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartRevoluteJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartWeldJoint( b2JointSim* base, b2StepContext* context ); +void b2WarmStartWheelJoint( b2JointSim* base, b2StepContext* context ); + +void b2SolveDistanceJoint( b2JointSim* base, b2StepContext* context, bool useBias ); +void b2SolveMotorJoint( b2JointSim* base, b2StepContext* context, bool useBias ); +void b2SolveMouseJoint( b2JointSim* base, b2StepContext* context ); +void b2SolvePrismaticJoint( b2JointSim* base, b2StepContext* context, bool useBias ); +void b2SolveRevoluteJoint( b2JointSim* base, b2StepContext* context, bool useBias ); +void b2SolveWeldJoint( b2JointSim* base, b2StepContext* context, bool useBias ); +void b2SolveWheelJoint( b2JointSim* base, b2StepContext* context, bool useBias ); + +void b2DrawDistanceJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ); +void b2DrawPrismaticJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ); +void b2DrawRevoluteJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB, float drawSize ); +void b2DrawWheelJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ); + +// Define inline functions for arrays +B2_ARRAY_INLINE( b2Joint, b2Joint ) +B2_ARRAY_INLINE( b2JointSim, b2JointSim ) diff --git a/3rdparty/box2d/src/manifold.c b/3rdparty/box2d/src/manifold.c new file mode 100644 index 000000000000..6bfec835687b --- /dev/null +++ b/3rdparty/box2d/src/manifold.c @@ -0,0 +1,1726 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constants.h" +#include "core.h" + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +#define B2_MAKE_ID( A, B ) ( (uint8_t)( A ) << 8 | (uint8_t)( B ) ) + +static b2Polygon b2MakeCapsule( b2Vec2 p1, b2Vec2 p2, float radius ) +{ + b2Polygon shape = { 0 }; + shape.vertices[0] = p1; + shape.vertices[1] = p2; + shape.centroid = b2Lerp( p1, p2, 0.5f ); + + b2Vec2 d = b2Sub( p2, p1 ); + B2_ASSERT( b2LengthSquared( d ) > FLT_EPSILON ); + b2Vec2 axis = b2Normalize( d ); + b2Vec2 normal = b2RightPerp( axis ); + + shape.normals[0] = normal; + shape.normals[1] = b2Neg( normal ); + shape.count = 2; + shape.radius = radius; + + return shape; +} + +// point = qA * localAnchorA + pA +// localAnchorB = qBc * (point - pB) +// anchorB = point - pB = qA * localAnchorA + pA - pB +// = anchorA + (pA - pB) +b2Manifold b2CollideCircles( const b2Circle* circleA, b2Transform xfA, const b2Circle* circleB, b2Transform xfB ) +{ + b2Manifold manifold = { 0 }; + + b2Transform xf = b2InvMulTransforms( xfA, xfB ); + + b2Vec2 pointA = circleA->center; + b2Vec2 pointB = b2TransformPoint( xf, circleB->center ); + + float distance; + b2Vec2 normal = b2GetLengthAndNormalize( &distance, b2Sub( pointB, pointA ) ); + + float radiusA = circleA->radius; + float radiusB = circleB->radius; + + float separation = distance - radiusA - radiusB; + if ( separation > B2_SPECULATIVE_DISTANCE ) + { + return manifold; + } + + b2Vec2 cA = b2MulAdd( pointA, radiusA, normal ); + b2Vec2 cB = b2MulAdd( pointB, -radiusB, normal ); + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + manifold.normal = b2RotateVector( xfA.q, normal ); + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( mp->anchorA, xfA.p ); + mp->separation = separation; + mp->id = 0; + manifold.pointCount = 1; + return manifold; +} + +/// Compute the collision manifold between a capsule and circle +b2Manifold b2CollideCapsuleAndCircle( const b2Capsule* capsuleA, b2Transform xfA, const b2Circle* circleB, b2Transform xfB ) +{ + b2Manifold manifold = { 0 }; + + b2Transform xf = b2InvMulTransforms( xfA, xfB ); + + // Compute circle position in the frame of the capsule. + b2Vec2 pB = b2TransformPoint( xf, circleB->center ); + + // Compute closest point + b2Vec2 p1 = capsuleA->center1; + b2Vec2 p2 = capsuleA->center2; + + b2Vec2 e = b2Sub( p2, p1 ); + + // dot(p - pA, e) = 0 + // dot(p - (p1 + s1 * e), e) = 0 + // s1 = dot(p - p1, e) + b2Vec2 pA; + float s1 = b2Dot( b2Sub( pB, p1 ), e ); + float s2 = b2Dot( b2Sub( p2, pB ), e ); + if ( s1 < 0.0f ) + { + // p1 region + pA = p1; + } + else if ( s2 < 0.0f ) + { + // p2 region + pA = p2; + } + else + { + // circle colliding with segment interior + float s = s1 / b2Dot( e, e ); + pA = b2MulAdd( p1, s, e ); + } + + float distance; + b2Vec2 normal = b2GetLengthAndNormalize( &distance, b2Sub( pB, pA ) ); + + float radiusA = capsuleA->radius; + float radiusB = circleB->radius; + float separation = distance - radiusA - radiusB; + if ( separation > B2_SPECULATIVE_DISTANCE ) + { + return manifold; + } + + b2Vec2 cA = b2MulAdd( pA, radiusA, normal ); + b2Vec2 cB = b2MulAdd( pB, -radiusB, normal ); + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + manifold.normal = b2RotateVector( xfA.q, normal ); + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + mp->separation = separation; + mp->id = 0; + manifold.pointCount = 1; + return manifold; +} + +b2Manifold b2CollidePolygonAndCircle( const b2Polygon* polygonA, b2Transform xfA, const b2Circle* circleB, b2Transform xfB ) +{ + b2Manifold manifold = { 0 }; + const float speculativeDistance = B2_SPECULATIVE_DISTANCE; + + b2Transform xf = b2InvMulTransforms( xfA, xfB ); + + // Compute circle position in the frame of the polygon. + b2Vec2 center = b2TransformPoint( xf, circleB->center ); + float radiusA = polygonA->radius; + float radiusB = circleB->radius; + float radius = radiusA + radiusB; + + // Find the min separating edge. + int normalIndex = 0; + float separation = -FLT_MAX; + int vertexCount = polygonA->count; + const b2Vec2* vertices = polygonA->vertices; + const b2Vec2* normals = polygonA->normals; + + for ( int i = 0; i < vertexCount; ++i ) + { + float s = b2Dot( normals[i], b2Sub( center, vertices[i] ) ); + if ( s > separation ) + { + separation = s; + normalIndex = i; + } + } + + if ( separation > radius + speculativeDistance ) + { + return manifold; + } + + // Vertices of the reference edge. + int vertIndex1 = normalIndex; + int vertIndex2 = vertIndex1 + 1 < vertexCount ? vertIndex1 + 1 : 0; + b2Vec2 v1 = vertices[vertIndex1]; + b2Vec2 v2 = vertices[vertIndex2]; + + // Compute barycentric coordinates + float u1 = b2Dot( b2Sub( center, v1 ), b2Sub( v2, v1 ) ); + float u2 = b2Dot( b2Sub( center, v2 ), b2Sub( v1, v2 ) ); + + if ( u1 < 0.0f && separation > FLT_EPSILON ) + { + // Circle center is closest to v1 and safely outside the polygon + b2Vec2 normal = b2Normalize( b2Sub( center, v1 ) ); + separation = b2Dot( b2Sub( center, v1 ), normal ); + if ( separation > radius + speculativeDistance ) + { + return manifold; + } + + b2Vec2 cA = b2MulAdd( v1, radiusA, normal ); + b2Vec2 cB = b2MulSub( center, radiusB, normal ); + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + manifold.normal = b2RotateVector( xfA.q, normal ); + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + mp->separation = b2Dot( b2Sub( cB, cA ), normal ); + mp->id = 0; + manifold.pointCount = 1; + } + else if ( u2 < 0.0f && separation > FLT_EPSILON ) + { + // Circle center is closest to v2 and safely outside the polygon + b2Vec2 normal = b2Normalize( b2Sub( center, v2 ) ); + separation = b2Dot( b2Sub( center, v2 ), normal ); + if ( separation > radius + speculativeDistance ) + { + return manifold; + } + + b2Vec2 cA = b2MulAdd( v2, radiusA, normal ); + b2Vec2 cB = b2MulSub( center, radiusB, normal ); + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + manifold.normal = b2RotateVector( xfA.q, normal ); + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + mp->separation = b2Dot( b2Sub( cB, cA ), normal ); + mp->id = 0; + manifold.pointCount = 1; + } + else + { + // Circle center is between v1 and v2. Center may be inside polygon + b2Vec2 normal = normals[normalIndex]; + manifold.normal = b2RotateVector( xfA.q, normal ); + + // cA is the projection of the circle center onto to the reference edge + b2Vec2 cA = b2MulAdd( center, radiusA - b2Dot( b2Sub( center, v1 ), normal ), normal ); + + // cB is the deepest point on the circle with respect to the reference edge + b2Vec2 cB = b2MulSub( center, radiusB, normal ); + + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + // The contact point is the midpoint in world space + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + mp->separation = separation - radius; + mp->id = 0; + manifold.pointCount = 1; + } + + return manifold; +} + +// Follows Ericson 5.1.9 Closest Points of Two Line Segments +// Adds some logic to support clipping to get two contact points +b2Manifold b2CollideCapsules( const b2Capsule* capsuleA, b2Transform xfA, const b2Capsule* capsuleB, b2Transform xfB ) +{ + b2Vec2 origin = capsuleA->center1; + + // Shift polyA to origin + // pw = q * pb + p + // pw = q * (pbs + origin) + p + // pw = q * pbs + (p + q * origin) + b2Transform sfA = { b2Add( xfA.p, b2RotateVector( xfA.q, origin ) ), xfA.q }; + b2Transform xf = b2InvMulTransforms( sfA, xfB ); + + b2Vec2 p1 = b2Vec2_zero; + b2Vec2 q1 = b2Sub( capsuleA->center2, origin ); + + b2Vec2 p2 = b2TransformPoint( xf, capsuleB->center1 ); + b2Vec2 q2 = b2TransformPoint( xf, capsuleB->center2 ); + + b2Vec2 d1 = b2Sub( q1, p1 ); + b2Vec2 d2 = b2Sub( q2, p2 ); + + float dd1 = b2Dot( d1, d1 ); + float dd2 = b2Dot( d2, d2 ); + + const float epsSqr = FLT_EPSILON * FLT_EPSILON; + B2_ASSERT( dd1 > epsSqr && dd2 > epsSqr ); + + b2Vec2 r = b2Sub( p1, p2 ); + float rd1 = b2Dot( r, d1 ); + float rd2 = b2Dot( r, d2 ); + + float d12 = b2Dot( d1, d2 ); + + float denom = dd1 * dd2 - d12 * d12; + + // Fraction on segment 1 + float f1 = 0.0f; + if ( denom != 0.0f ) + { + // not parallel + f1 = b2ClampFloat( ( d12 * rd2 - rd1 * dd2 ) / denom, 0.0f, 1.0f ); + } + + // Compute point on segment 2 closest to p1 + f1 * d1 + float f2 = ( d12 * f1 + rd2 ) / dd2; + + // Clamping of segment 2 requires a do over on segment 1 + if ( f2 < 0.0f ) + { + f2 = 0.0f; + f1 = b2ClampFloat( -rd1 / dd1, 0.0f, 1.0f ); + } + else if ( f2 > 1.0f ) + { + f2 = 1.0f; + f1 = b2ClampFloat( ( d12 - rd1 ) / dd1, 0.0f, 1.0f ); + } + + b2Vec2 closest1 = b2MulAdd( p1, f1, d1 ); + b2Vec2 closest2 = b2MulAdd( p2, f2, d2 ); + float distanceSquared = b2DistanceSquared( closest1, closest2 ); + + b2Manifold manifold = { 0 }; + float radiusA = capsuleA->radius; + float radiusB = capsuleB->radius; + float radius = radiusA + radiusB; + float maxDistance = radius + B2_SPECULATIVE_DISTANCE; + + if ( distanceSquared > maxDistance * maxDistance ) + { + return manifold; + } + + float distance = sqrtf( distanceSquared ); + + float length1, length2; + b2Vec2 u1 = b2GetLengthAndNormalize( &length1, d1 ); + b2Vec2 u2 = b2GetLengthAndNormalize( &length2, d2 ); + + // Does segment B project outside segment A? + float fp2 = b2Dot( b2Sub( p2, p1 ), u1 ); + float fq2 = b2Dot( b2Sub( q2, p1 ), u1 ); + bool outsideA = ( fp2 <= 0.0f && fq2 <= 0.0f ) || ( fp2 >= length1 && fq2 >= length1 ); + + // Does segment A project outside segment B? + float fp1 = b2Dot( b2Sub( p1, p2 ), u2 ); + float fq1 = b2Dot( b2Sub( q1, p2 ), u2 ); + bool outsideB = ( fp1 <= 0.0f && fq1 <= 0.0f ) || ( fp1 >= length2 && fq1 >= length2 ); + + if ( outsideA == false && outsideB == false ) + { + // attempt to clip + // this may yield contact points with excessive separation + // in that case the algorithm falls back to single point collision + + // find reference edge using SAT + b2Vec2 normalA; + float separationA; + + { + normalA = b2LeftPerp( u1 ); + float ss1 = b2Dot( b2Sub( p2, p1 ), normalA ); + float ss2 = b2Dot( b2Sub( q2, p1 ), normalA ); + float s1p = ss1 < ss2 ? ss1 : ss2; + float s1n = -ss1 < -ss2 ? -ss1 : -ss2; + + if ( s1p > s1n ) + { + separationA = s1p; + } + else + { + separationA = s1n; + normalA = b2Neg( normalA ); + } + } + + b2Vec2 normalB; + float separationB; + { + normalB = b2LeftPerp( u2 ); + float ss1 = b2Dot( b2Sub( p1, p2 ), normalB ); + float ss2 = b2Dot( b2Sub( q1, p2 ), normalB ); + float s1p = ss1 < ss2 ? ss1 : ss2; + float s1n = -ss1 < -ss2 ? -ss1 : -ss2; + + if ( s1p > s1n ) + { + separationB = s1p; + } + else + { + separationB = s1n; + normalB = b2Neg( normalB ); + } + } + + // biased to avoid feature flip-flop + // todo more testing? + if ( separationA + 0.1f * B2_LINEAR_SLOP >= separationB ) + { + manifold.normal = normalA; + + b2Vec2 cp = p2; + b2Vec2 cq = q2; + + // clip to p1 + if ( fp2 < 0.0f && fq2 > 0.0f ) + { + cp = b2Lerp( p2, q2, ( 0.0f - fp2 ) / ( fq2 - fp2 ) ); + } + else if ( fq2 < 0.0f && fp2 > 0.0f ) + { + cq = b2Lerp( q2, p2, ( 0.0f - fq2 ) / ( fp2 - fq2 ) ); + } + + // clip to q1 + if ( fp2 > length1 && fq2 < length1 ) + { + cp = b2Lerp( p2, q2, ( fp2 - length1 ) / ( fp2 - fq2 ) ); + } + else if ( fq2 > length1 && fp2 < length1 ) + { + cq = b2Lerp( q2, p2, ( fq2 - length1 ) / ( fq2 - fp2 ) ); + } + + float sp = b2Dot( b2Sub( cp, p1 ), normalA ); + float sq = b2Dot( b2Sub( cq, p1 ), normalA ); + + if ( sp <= distance + B2_LINEAR_SLOP || sq <= distance + B2_LINEAR_SLOP ) + { + b2ManifoldPoint* mp; + mp = manifold.points + 0; + mp->anchorA = b2MulAdd( cp, 0.5f * ( radiusA - radiusB - sp ), normalA ); + mp->separation = sp - radius; + mp->id = B2_MAKE_ID( 0, 0 ); + + mp = manifold.points + 1; + mp->anchorA = b2MulAdd( cq, 0.5f * ( radiusA - radiusB - sq ), normalA ); + mp->separation = sq - radius; + mp->id = B2_MAKE_ID( 0, 1 ); + manifold.pointCount = 2; + } + } + else + { + // normal always points from A to B + manifold.normal = b2Neg( normalB ); + + b2Vec2 cp = p1; + b2Vec2 cq = q1; + + // clip to p2 + if ( fp1 < 0.0f && fq1 > 0.0f ) + { + cp = b2Lerp( p1, q1, ( 0.0f - fp1 ) / ( fq1 - fp1 ) ); + } + else if ( fq1 < 0.0f && fp1 > 0.0f ) + { + cq = b2Lerp( q1, p1, ( 0.0f - fq1 ) / ( fp1 - fq1 ) ); + } + + // clip to q2 + if ( fp1 > length2 && fq1 < length2 ) + { + cp = b2Lerp( p1, q1, ( fp1 - length2 ) / ( fp1 - fq1 ) ); + } + else if ( fq1 > length2 && fp1 < length2 ) + { + cq = b2Lerp( q1, p1, ( fq1 - length2 ) / ( fq1 - fp1 ) ); + } + + float sp = b2Dot( b2Sub( cp, p2 ), normalB ); + float sq = b2Dot( b2Sub( cq, p2 ), normalB ); + + if ( sp <= distance + B2_LINEAR_SLOP || sq <= distance + B2_LINEAR_SLOP ) + { + b2ManifoldPoint* mp; + mp = manifold.points + 0; + mp->anchorA = b2MulAdd( cp, 0.5f * ( radiusB - radiusA - sp ), normalB ); + mp->separation = sp - radius; + mp->id = B2_MAKE_ID( 0, 0 ); + mp = manifold.points + 1; + mp->anchorA = b2MulAdd( cq, 0.5f * ( radiusB - radiusA - sq ), normalB ); + mp->separation = sq - radius; + mp->id = B2_MAKE_ID( 1, 0 ); + manifold.pointCount = 2; + } + } + } + + if ( manifold.pointCount == 0 ) + { + // single point collision + b2Vec2 normal = b2Sub( closest2, closest1 ); + if ( b2Dot( normal, normal ) > epsSqr ) + { + normal = b2Normalize( normal ); + } + else + { + normal = b2LeftPerp( u1 ); + } + + b2Vec2 c1 = b2MulAdd( closest1, radiusA, normal ); + b2Vec2 c2 = b2MulAdd( closest2, -radiusB, normal ); + + int i1 = f1 == 0.0f ? 0 : 1; + int i2 = f2 == 0.0f ? 0 : 1; + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = sqrtf( distanceSquared ) - radius; + manifold.points[0].id = B2_MAKE_ID( i1, i2 ); + manifold.pointCount = 1; + } + + // Convert manifold to world space + manifold.normal = b2RotateVector( xfA.q, manifold.normal ); + for ( int i = 0; i < manifold.pointCount; ++i ) + { + b2ManifoldPoint* mp = manifold.points + i; + + // anchor points relative to shape origin in world space + mp->anchorA = b2RotateVector( xfA.q, b2Add( mp->anchorA, origin ) ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + } + + return manifold; +} + +b2Manifold b2CollideSegmentAndCapsule( const b2Segment* segmentA, b2Transform xfA, const b2Capsule* capsuleB, b2Transform xfB ) +{ + b2Capsule capsuleA = { segmentA->point1, segmentA->point2, 0.0f }; + return b2CollideCapsules( &capsuleA, xfA, capsuleB, xfB ); +} + +b2Manifold b2CollidePolygonAndCapsule( const b2Polygon* polygonA, b2Transform xfA, const b2Capsule* capsuleB, b2Transform xfB ) +{ + b2Polygon polyB = b2MakeCapsule( capsuleB->center1, capsuleB->center2, capsuleB->radius ); + return b2CollidePolygons( polygonA, xfA, &polyB, xfB ); +} + +// Polygon clipper used to compute contact points when there are potentially two contact points. +static b2Manifold b2ClipPolygons( const b2Polygon* polyA, const b2Polygon* polyB, int edgeA, int edgeB, bool flip ) +{ + b2Manifold manifold = { 0 }; + + // reference polygon + const b2Polygon* poly1; + int i11, i12; + + // incident polygon + const b2Polygon* poly2; + int i21, i22; + + if ( flip ) + { + poly1 = polyB; + poly2 = polyA; + i11 = edgeB; + i12 = edgeB + 1 < polyB->count ? edgeB + 1 : 0; + i21 = edgeA; + i22 = edgeA + 1 < polyA->count ? edgeA + 1 : 0; + } + else + { + poly1 = polyA; + poly2 = polyB; + i11 = edgeA; + i12 = edgeA + 1 < polyA->count ? edgeA + 1 : 0; + i21 = edgeB; + i22 = edgeB + 1 < polyB->count ? edgeB + 1 : 0; + } + + b2Vec2 normal = poly1->normals[i11]; + + // Reference edge vertices + b2Vec2 v11 = poly1->vertices[i11]; + b2Vec2 v12 = poly1->vertices[i12]; + + // Incident edge vertices + b2Vec2 v21 = poly2->vertices[i21]; + b2Vec2 v22 = poly2->vertices[i22]; + + b2Vec2 tangent = b2CrossSV( 1.0f, normal ); + + float lower1 = 0.0f; + float upper1 = b2Dot( b2Sub( v12, v11 ), tangent ); + + // Incident edge points opposite of tangent due to CCW winding + float upper2 = b2Dot( b2Sub( v21, v11 ), tangent ); + float lower2 = b2Dot( b2Sub( v22, v11 ), tangent ); + + // Are the segments disjoint? + if ( upper2 < lower1 || upper1 < lower2 ) + { + return manifold; + } + + b2Vec2 vLower; + if ( lower2 < lower1 && upper2 - lower2 > FLT_EPSILON ) + { + vLower = b2Lerp( v22, v21, ( lower1 - lower2 ) / ( upper2 - lower2 ) ); + } + else + { + vLower = v22; + } + + b2Vec2 vUpper; + if ( upper2 > upper1 && upper2 - lower2 > FLT_EPSILON ) + { + vUpper = b2Lerp( v22, v21, ( upper1 - lower2 ) / ( upper2 - lower2 ) ); + } + else + { + vUpper = v21; + } + + // todo vLower can be very close to vUpper, reduce to one point? + + float separationLower = b2Dot( b2Sub( vLower, v11 ), normal ); + float separationUpper = b2Dot( b2Sub( vUpper, v11 ), normal ); + + float r1 = poly1->radius; + float r2 = poly2->radius; + + // Put contact points at midpoint, accounting for radii + vLower = b2MulAdd( vLower, 0.5f * ( r1 - r2 - separationLower ), normal ); + vUpper = b2MulAdd( vUpper, 0.5f * ( r1 - r2 - separationUpper ), normal ); + + float radius = r1 + r2; + + if ( flip == false ) + { + manifold.normal = normal; + b2ManifoldPoint* cp = manifold.points + 0; + + { + cp->anchorA = vLower; + cp->separation = separationLower - radius; + cp->id = B2_MAKE_ID( i11, i22 ); + manifold.pointCount += 1; + cp += 1; + } + + { + cp->anchorA = vUpper; + cp->separation = separationUpper - radius; + cp->id = B2_MAKE_ID( i12, i21 ); + manifold.pointCount += 1; + } + } + else + { + manifold.normal = b2Neg( normal ); + b2ManifoldPoint* cp = manifold.points + 0; + + { + cp->anchorA = vUpper; + cp->separation = separationUpper - radius; + cp->id = B2_MAKE_ID( i21, i12 ); + manifold.pointCount += 1; + cp += 1; + } + + { + cp->anchorA = vLower; + cp->separation = separationLower - radius; + cp->id = B2_MAKE_ID( i22, i11 ); + manifold.pointCount += 1; + } + } + + return manifold; +} + +// Find the max separation between poly1 and poly2 using edge normals from poly1. +static float b2FindMaxSeparation( int* edgeIndex, const b2Polygon* poly1, const b2Polygon* poly2 ) +{ + int count1 = poly1->count; + int count2 = poly2->count; + const b2Vec2* n1s = poly1->normals; + const b2Vec2* v1s = poly1->vertices; + const b2Vec2* v2s = poly2->vertices; + + int bestIndex = 0; + float maxSeparation = -FLT_MAX; + for ( int i = 0; i < count1; ++i ) + { + // Get poly1 normal in frame2. + b2Vec2 n = n1s[i]; + b2Vec2 v1 = v1s[i]; + + // Find the deepest point for normal i. + float si = FLT_MAX; + for ( int j = 0; j < count2; ++j ) + { + float sij = b2Dot( n, b2Sub( v2s[j], v1 ) ); + if ( sij < si ) + { + si = sij; + } + } + + if ( si > maxSeparation ) + { + maxSeparation = si; + bestIndex = i; + } + } + + *edgeIndex = bestIndex; + return maxSeparation; +} + +// Due to speculation, every polygon is rounded +// Algorithm: +// +// compute edge separation using the separating axis test (SAT) +// if (separation > speculation_distance) +// return +// find reference and incident edge +// if separation >= 0.1f * B2_LINEAR_SLOP +// compute closest points between reference and incident edge +// if vertices are closest +// single vertex-vertex contact +// else +// clip edges +// end +// else +// clip edges +// end + +b2Manifold b2CollidePolygons( const b2Polygon* polygonA, b2Transform xfA, const b2Polygon* polygonB, b2Transform xfB ) +{ + b2Vec2 origin = polygonA->vertices[0]; + float linearSlop = B2_LINEAR_SLOP; + float speculativeDistance = B2_SPECULATIVE_DISTANCE; + + // Shift polyA to origin + // pw = q * pb + p + // pw = q * (pbs + origin) + p + // pw = q * pbs + (p + q * origin) + b2Transform sfA = { b2Add( xfA.p, b2RotateVector( xfA.q, origin ) ), xfA.q }; + b2Transform xf = b2InvMulTransforms( sfA, xfB ); + + b2Polygon localPolyA; + localPolyA.count = polygonA->count; + localPolyA.radius = polygonA->radius; + localPolyA.vertices[0] = b2Vec2_zero; + localPolyA.normals[0] = polygonA->normals[0]; + for ( int i = 1; i < localPolyA.count; ++i ) + { + localPolyA.vertices[i] = b2Sub( polygonA->vertices[i], origin ); + localPolyA.normals[i] = polygonA->normals[i]; + } + + // Put polyB in polyA's frame to reduce round-off error + b2Polygon localPolyB; + localPolyB.count = polygonB->count; + localPolyB.radius = polygonB->radius; + for ( int i = 0; i < localPolyB.count; ++i ) + { + localPolyB.vertices[i] = b2TransformPoint( xf, polygonB->vertices[i] ); + localPolyB.normals[i] = b2RotateVector( xf.q, polygonB->normals[i] ); + } + + int edgeA = 0; + float separationA = b2FindMaxSeparation( &edgeA, &localPolyA, &localPolyB ); + + int edgeB = 0; + float separationB = b2FindMaxSeparation( &edgeB, &localPolyB, &localPolyA ); + + float radius = localPolyA.radius + localPolyB.radius; + + if ( separationA > speculativeDistance + radius || separationB > speculativeDistance + radius ) + { + return (b2Manifold){ 0 }; + } + + // Find incident edge + bool flip; + if ( separationA >= separationB ) + { + flip = false; + + b2Vec2 searchDirection = localPolyA.normals[edgeA]; + + // Find the incident edge on polyB + int count = localPolyB.count; + const b2Vec2* normals = localPolyB.normals; + edgeB = 0; + float minDot = FLT_MAX; + for ( int i = 0; i < count; ++i ) + { + float dot = b2Dot( searchDirection, normals[i] ); + if ( dot < minDot ) + { + minDot = dot; + edgeB = i; + } + } + } + else + { + flip = true; + + b2Vec2 searchDirection = localPolyB.normals[edgeB]; + + // Find the incident edge on polyA + int count = localPolyA.count; + const b2Vec2* normals = localPolyA.normals; + edgeA = 0; + float minDot = FLT_MAX; + for ( int i = 0; i < count; ++i ) + { + float dot = b2Dot( searchDirection, normals[i] ); + if ( dot < minDot ) + { + minDot = dot; + edgeA = i; + } + } + } + + b2Manifold manifold = { 0 }; + + // Using slop here to ensure vertex-vertex normal vectors can be safely normalized + // todo this means edge clipping needs to handle slightly non-overlapping edges. + if ( separationA > 0.1f * linearSlop || separationB > 0.1f * linearSlop ) + { +#if 1 + // Edges are disjoint. Find closest points between reference edge and incident edge + // Reference edge on polygon A + int i11 = edgeA; + int i12 = edgeA + 1 < localPolyA.count ? edgeA + 1 : 0; + int i21 = edgeB; + int i22 = edgeB + 1 < localPolyB.count ? edgeB + 1 : 0; + + b2Vec2 v11 = localPolyA.vertices[i11]; + b2Vec2 v12 = localPolyA.vertices[i12]; + b2Vec2 v21 = localPolyB.vertices[i21]; + b2Vec2 v22 = localPolyB.vertices[i22]; + + b2SegmentDistanceResult result = b2SegmentDistance( v11, v12, v21, v22 ); + B2_ASSERT( result.distanceSquared > 0.0f ); + float distance = sqrtf( result.distanceSquared ); + float separation = distance - radius; + + if ( distance - radius > speculativeDistance ) + { + // This can happen in the vertex-vertex case + return manifold; + } + + // Attempt to clip edges + manifold = b2ClipPolygons( &localPolyA, &localPolyB, edgeA, edgeB, flip ); + + float minSeparation = FLT_MAX; + for ( int i = 0; i < manifold.pointCount; ++i ) + { + minSeparation = b2MinFloat( minSeparation, manifold.points[i].separation ); + } + + // Does vertex-vertex have substantially larger separation? + if ( separation + 0.1f * linearSlop < minSeparation ) + { + if ( result.fraction1 == 0.0f && result.fraction2 == 0.0f ) + { + // v11 - v21 + b2Vec2 normal = b2Sub( v21, v11 ); + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v11, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v21, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i11, i21 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 0.0f && result.fraction2 == 1.0f ) + { + // v11 - v22 + b2Vec2 normal = b2Sub( v22, v11 ); + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v11, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v22, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i11, i22 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 1.0f && result.fraction2 == 0.0f ) + { + // v12 - v21 + b2Vec2 normal = b2Sub( v21, v12 ); + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v12, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v21, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i12, i21 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 1.0f && result.fraction2 == 1.0f ) + { + // v12 - v22 + b2Vec2 normal = b2Sub( v22, v12 ); + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v12, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v22, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i12, i22 ); + manifold.pointCount = 1; + } + } +#else + // Polygons are disjoint. Find closest points between reference edge and incident edge + // Reference edge on polygon A + int i11 = edgeA; + int i12 = edgeA + 1 < localPolyA.count ? edgeA + 1 : 0; + int i21 = edgeB; + int i22 = edgeB + 1 < localPolyB.count ? edgeB + 1 : 0; + + b2Vec2 v11 = localPolyA.vertices[i11]; + b2Vec2 v12 = localPolyA.vertices[i12]; + b2Vec2 v21 = localPolyB.vertices[i21]; + b2Vec2 v22 = localPolyB.vertices[i22]; + + b2SegmentDistanceResult result = b2SegmentDistance( v11, v12, v21, v22 ); + + if ( result.fraction1 == 0.0f && result.fraction2 == 0.0f ) + { + // v11 - v21 + b2Vec2 normal = b2Sub( v21, v11 ); + B2_ASSERT( result.distanceSquared > 0.0f ); + float distance = sqrtf( result.distanceSquared ); + if ( distance > B2_SPECULATIVE_DISTANCE + radius ) + { + return manifold; + } + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v11, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v21, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i11, i21 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 0.0f && result.fraction2 == 1.0f ) + { + // v11 - v22 + b2Vec2 normal = b2Sub( v22, v11 ); + B2_ASSERT( result.distanceSquared > 0.0f ); + float distance = sqrtf( result.distanceSquared ); + if ( distance > B2_SPECULATIVE_DISTANCE + radius ) + { + return manifold; + } + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v11, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v22, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i11, i22 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 1.0f && result.fraction2 == 0.0f ) + { + // v12 - v21 + b2Vec2 normal = b2Sub( v21, v12 ); + B2_ASSERT( result.distanceSquared > 0.0f ); + float distance = sqrtf( result.distanceSquared ); + if ( distance > B2_SPECULATIVE_DISTANCE + radius ) + { + return manifold; + } + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v12, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v21, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i12, i21 ); + manifold.pointCount = 1; + } + else if ( result.fraction1 == 1.0f && result.fraction2 == 1.0f ) + { + // v12 - v22 + b2Vec2 normal = b2Sub( v22, v12 ); + B2_ASSERT( result.distanceSquared > 0.0f ); + float distance = sqrtf( result.distanceSquared ); + if ( distance > B2_SPECULATIVE_DISTANCE + radius ) + { + return manifold; + } + float invDistance = 1.0f / distance; + normal.x *= invDistance; + normal.y *= invDistance; + + b2Vec2 c1 = b2MulAdd( v12, localPolyA.radius, normal ); + b2Vec2 c2 = b2MulAdd( v22, -localPolyB.radius, normal ); + + manifold.normal = normal; + manifold.points[0].anchorA = b2Lerp( c1, c2, 0.5f ); + manifold.points[0].separation = distance - radius; + manifold.points[0].id = B2_MAKE_ID( i12, i22 ); + manifold.pointCount = 1; + } + else + { + // Edge region + manifold = b2ClipPolygons( &localPolyA, &localPolyB, edgeA, edgeB, flip ); + } +#endif + } + else + { + // Polygons overlap + manifold = b2ClipPolygons( &localPolyA, &localPolyB, edgeA, edgeB, flip ); + } + + // Convert manifold to world space + if ( manifold.pointCount > 0 ) + { + manifold.normal = b2RotateVector( xfA.q, manifold.normal ); + for ( int i = 0; i < manifold.pointCount; ++i ) + { + b2ManifoldPoint* mp = manifold.points + i; + + // anchor points relative to shape origin in world space + mp->anchorA = b2RotateVector( xfA.q, b2Add( mp->anchorA, origin ) ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + } + } + + return manifold; +} + +b2Manifold b2CollideSegmentAndCircle( const b2Segment* segmentA, b2Transform xfA, const b2Circle* circleB, b2Transform xfB ) +{ + b2Capsule capsuleA = { segmentA->point1, segmentA->point2, 0.0f }; + return b2CollideCapsuleAndCircle( &capsuleA, xfA, circleB, xfB ); +} + +b2Manifold b2CollideSegmentAndPolygon( const b2Segment* segmentA, b2Transform xfA, const b2Polygon* polygonB, b2Transform xfB ) +{ + b2Polygon polygonA = b2MakeCapsule( segmentA->point1, segmentA->point2, 0.0f ); + return b2CollidePolygons( &polygonA, xfA, polygonB, xfB ); +} + +b2Manifold b2CollideChainSegmentAndCircle( const b2ChainSegment* segmentA, b2Transform xfA, const b2Circle* circleB, + b2Transform xfB ) +{ + b2Manifold manifold = { 0 }; + + b2Transform xf = b2InvMulTransforms( xfA, xfB ); + + // Compute circle in frame of segment + b2Vec2 pB = b2TransformPoint( xf, circleB->center ); + + b2Vec2 p1 = segmentA->segment.point1; + b2Vec2 p2 = segmentA->segment.point2; + b2Vec2 e = b2Sub( p2, p1 ); + + // Normal points to the right + float offset = b2Dot( b2RightPerp( e ), b2Sub( pB, p1 ) ); + if ( offset < 0.0f ) + { + // collision is one-sided + return manifold; + } + + // Barycentric coordinates + float u = b2Dot( e, b2Sub( p2, pB ) ); + float v = b2Dot( e, b2Sub( pB, p1 ) ); + + b2Vec2 pA; + + if ( v <= 0.0f ) + { + // Behind point1? + // Is pB in the Voronoi region of the previous edge? + b2Vec2 prevEdge = b2Sub( p1, segmentA->ghost1 ); + float uPrev = b2Dot( prevEdge, b2Sub( pB, p1 ) ); + if ( uPrev <= 0.0f ) + { + return manifold; + } + + pA = p1; + } + else if ( u <= 0.0f ) + { + // Ahead of point2? + b2Vec2 nextEdge = b2Sub( segmentA->ghost2, p2 ); + float vNext = b2Dot( nextEdge, b2Sub( pB, p2 ) ); + + // Is pB in the Voronoi region of the next edge? + if ( vNext > 0.0f ) + { + return manifold; + } + + pA = p2; + } + else + { + float ee = b2Dot( e, e ); + pA = (b2Vec2){ u * p1.x + v * p2.x, u * p1.y + v * p2.y }; + pA = ee > 0.0f ? b2MulSV( 1.0f / ee, pA ) : p1; + } + + float distance; + b2Vec2 normal = b2GetLengthAndNormalize( &distance, b2Sub( pB, pA ) ); + + float radius = circleB->radius; + float separation = distance - radius; + if ( separation > B2_SPECULATIVE_DISTANCE ) + { + return manifold; + } + + b2Vec2 cA = pA; + b2Vec2 cB = b2MulAdd( pB, -radius, normal ); + b2Vec2 contactPointA = b2Lerp( cA, cB, 0.5f ); + + manifold.normal = b2RotateVector( xfA.q, normal ); + + b2ManifoldPoint* mp = manifold.points + 0; + mp->anchorA = b2RotateVector( xfA.q, contactPointA ); + mp->anchorB = b2Add( mp->anchorA, b2Sub( xfA.p, xfB.p ) ); + mp->point = b2Add( xfA.p, mp->anchorA ); + mp->separation = separation; + mp->id = 0; + manifold.pointCount = 1; + return manifold; +} + +b2Manifold b2CollideChainSegmentAndCapsule( const b2ChainSegment* segmentA, b2Transform xfA, const b2Capsule* capsuleB, + b2Transform xfB, b2SimplexCache* cache ) +{ + b2Polygon polyB = b2MakeCapsule( capsuleB->center1, capsuleB->center2, capsuleB->radius ); + return b2CollideChainSegmentAndPolygon( segmentA, xfA, &polyB, xfB, cache ); +} + +static b2Manifold b2ClipSegments( b2Vec2 a1, b2Vec2 a2, b2Vec2 b1, b2Vec2 b2, b2Vec2 normal, float ra, float rb, uint16_t id1, + uint16_t id2 ) +{ + b2Manifold manifold = { 0 }; + + b2Vec2 tangent = b2LeftPerp( normal ); + + // Barycentric coordinates of each point relative to a1 along tangent + float lower1 = 0.0f; + float upper1 = b2Dot( b2Sub( a2, a1 ), tangent ); + + // Incident edge points opposite of tangent due to CCW winding + float upper2 = b2Dot( b2Sub( b1, a1 ), tangent ); + float lower2 = b2Dot( b2Sub( b2, a1 ), tangent ); + + // Do segments overlap? + if ( upper2 < lower1 || upper1 < lower2 ) + { + return manifold; + } + + b2Vec2 vLower; + if ( lower2 < lower1 && upper2 - lower2 > FLT_EPSILON ) + { + vLower = b2Lerp( b2, b1, ( lower1 - lower2 ) / ( upper2 - lower2 ) ); + } + else + { + vLower = b2; + } + + b2Vec2 vUpper; + if ( upper2 > upper1 && upper2 - lower2 > FLT_EPSILON ) + { + vUpper = b2Lerp( b2, b1, ( upper1 - lower2 ) / ( upper2 - lower2 ) ); + } + else + { + vUpper = b1; + } + + // todo vLower can be very close to vUpper, reduce to one point? + + float separationLower = b2Dot( b2Sub( vLower, a1 ), normal ); + float separationUpper = b2Dot( b2Sub( vUpper, a1 ), normal ); + + // Put contact points at midpoint, accounting for radii + vLower = b2MulAdd( vLower, 0.5f * ( ra - rb - separationLower ), normal ); + vUpper = b2MulAdd( vUpper, 0.5f * ( ra - rb - separationUpper ), normal ); + + float radius = ra + rb; + + manifold.normal = normal; + { + b2ManifoldPoint* cp = manifold.points + 0; + cp->anchorA = vLower; + cp->separation = separationLower - radius; + cp->id = id1; + } + + { + b2ManifoldPoint* cp = manifold.points + 1; + cp->anchorA = vUpper; + cp->separation = separationUpper - radius; + cp->id = id2; + } + + manifold.pointCount = 2; + + return manifold; +} + +enum b2NormalType +{ + // This means the normal points in a direction that is non-smooth relative to a convex vertex and should be skipped + b2_normalSkip, + + // This means the normal points in a direction that is smooth relative to a convex vertex and should be used for collision + b2_normalAdmit, + + // This means the normal is in a region of a concave vertex and should be snapped to the segment normal + b2_normalSnap +}; + +struct b2ChainSegmentParams +{ + b2Vec2 edge1; + b2Vec2 normal0; + b2Vec2 normal2; + bool convex1; + bool convex2; +}; + +// Evaluate Gauss map +// See https://box2d.org/posts/2020/06/ghost-collisions/ +static enum b2NormalType b2ClassifyNormal( struct b2ChainSegmentParams params, b2Vec2 normal ) +{ + const float sinTol = 0.01f; + + if ( b2Dot( normal, params.edge1 ) <= 0.0f ) + { + // Normal points towards the segment tail + if ( params.convex1 ) + { + if ( b2Cross( normal, params.normal0 ) > sinTol ) + { + return b2_normalSkip; + } + + return b2_normalAdmit; + } + else + { + return b2_normalSnap; + } + } + else + { + // Normal points towards segment head + if ( params.convex2 ) + { + if ( b2Cross( params.normal2, normal ) > sinTol ) + { + return b2_normalSkip; + } + + return b2_normalAdmit; + } + else + { + return b2_normalSnap; + } + } +} + +b2Manifold b2CollideChainSegmentAndPolygon( const b2ChainSegment* segmentA, b2Transform xfA, const b2Polygon* polygonB, + b2Transform xfB, b2SimplexCache* cache ) +{ + b2Manifold manifold = { 0 }; + + b2Transform xf = b2InvMulTransforms( xfA, xfB ); + + b2Vec2 centroidB = b2TransformPoint( xf, polygonB->centroid ); + float radiusB = polygonB->radius; + + b2Vec2 p1 = segmentA->segment.point1; + b2Vec2 p2 = segmentA->segment.point2; + + b2Vec2 edge1 = b2Normalize( b2Sub( p2, p1 ) ); + + struct b2ChainSegmentParams smoothParams = { 0 }; + smoothParams.edge1 = edge1; + + const float convexTol = 0.01f; + b2Vec2 edge0 = b2Normalize( b2Sub( p1, segmentA->ghost1 ) ); + smoothParams.normal0 = b2RightPerp( edge0 ); + smoothParams.convex1 = b2Cross( edge0, edge1 ) >= convexTol; + + b2Vec2 edge2 = b2Normalize( b2Sub( segmentA->ghost2, p2 ) ); + smoothParams.normal2 = b2RightPerp( edge2 ); + smoothParams.convex2 = b2Cross( edge1, edge2 ) >= convexTol; + + // Normal points to the right + b2Vec2 normal1 = b2RightPerp( edge1 ); + bool behind1 = b2Dot( normal1, b2Sub( centroidB, p1 ) ) < 0.0f; + bool behind0 = true; + bool behind2 = true; + if ( smoothParams.convex1 ) + { + behind0 = b2Dot( smoothParams.normal0, b2Sub( centroidB, p1 ) ) < 0.0f; + } + + if ( smoothParams.convex2 ) + { + behind2 = b2Dot( smoothParams.normal2, b2Sub( centroidB, p2 ) ) < 0.0f; + } + + if ( behind1 && behind0 && behind2 ) + { + // one-sided collision + return manifold; + } + + // Get polygonB in frameA + int count = polygonB->count; + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; + b2Vec2 normals[B2_MAX_POLYGON_VERTICES]; + for ( int i = 0; i < count; ++i ) + { + vertices[i] = b2TransformPoint( xf, polygonB->vertices[i] ); + normals[i] = b2RotateVector( xf.q, polygonB->normals[i] ); + } + + // Distance doesn't work correctly with partial polygons + b2DistanceInput input; + input.proxyA = b2MakeProxy( &segmentA->segment.point1, 2, 0.0f ); + input.proxyB = b2MakeProxy( vertices, count, 0.0f ); + input.transformA = b2Transform_identity; + input.transformB = b2Transform_identity; + input.useRadii = false; + + b2DistanceOutput output = b2ShapeDistance( &input, cache, NULL, 0 ); + + if ( output.distance > radiusB + B2_SPECULATIVE_DISTANCE ) + { + return manifold; + } + + // Snap concave normals for partial polygon + b2Vec2 n0 = smoothParams.convex1 ? smoothParams.normal0 : normal1; + b2Vec2 n2 = smoothParams.convex2 ? smoothParams.normal2 : normal1; + + // Index of incident vertex on polygon + int incidentIndex = -1; + int incidentNormal = -1; + + if ( behind1 == false && output.distance > 0.1f * B2_LINEAR_SLOP ) + { + // The closest features may be two vertices or an edge and a vertex even when there should + // be face contact + + if ( cache->count == 1 ) + { + // vertex-vertex collision + b2Vec2 pA = output.pointA; + b2Vec2 pB = output.pointB; + + b2Vec2 normal = b2Normalize( b2Sub( pB, pA ) ); + + enum b2NormalType type = b2ClassifyNormal( smoothParams, normal ); + if ( type == b2_normalSkip ) + { + return manifold; + } + + if ( type == b2_normalAdmit ) + { + manifold.normal = b2RotateVector( xfA.q, normal ); + b2ManifoldPoint* cp = manifold.points + 0; + cp->anchorA = b2RotateVector( xfA.q, pA ); + cp->anchorB = b2Add( cp->anchorA, b2Sub( xfA.p, xfB.p ) ); + cp->point = b2Add( xfA.p, cp->anchorA ); + cp->separation = output.distance - radiusB; + cp->id = B2_MAKE_ID( cache->indexA[0], cache->indexB[0] ); + manifold.pointCount = 1; + return manifold; + } + + // fall through b2_normalSnap + incidentIndex = cache->indexB[0]; + } + else + { + // vertex-edge collision + B2_ASSERT( cache->count == 2 ); + + int ia1 = cache->indexA[0]; + int ia2 = cache->indexA[1]; + int ib1 = cache->indexB[0]; + int ib2 = cache->indexB[1]; + + if ( ia1 == ia2 ) + { + // 1 point on A, expect 2 points on B + B2_ASSERT( ib1 != ib2 ); + + // Find polygon normal most aligned with vector between closest points. + // This effectively sorts ib1 and ib2 + b2Vec2 normalB = b2Sub( output.pointA, output.pointB ); + float dot1 = b2Dot( normalB, normals[ib1] ); + float dot2 = b2Dot( normalB, normals[ib2] ); + int ib = dot1 > dot2 ? ib1 : ib2; + + // Use accurate normal + normalB = normals[ib]; + + enum b2NormalType type = b2ClassifyNormal( smoothParams, b2Neg( normalB ) ); + if ( type == b2_normalSkip ) + { + return manifold; + } + + if ( type == b2_normalAdmit ) + { + // Get polygon edge associated with normal + ib1 = ib; + ib2 = ib < count - 1 ? ib + 1 : 0; + + b2Vec2 b1 = vertices[ib1]; + b2Vec2 b2 = vertices[ib2]; + + // Find incident segment vertex + dot1 = b2Dot( normalB, b2Sub( p1, b1 ) ); + dot2 = b2Dot( normalB, b2Sub( p2, b1 ) ); + + if ( dot1 < dot2 ) + { + if ( b2Dot( n0, normalB ) < b2Dot( normal1, normalB ) ) + { + // Neighbor is incident + return manifold; + } + } + else + { + if ( b2Dot( n2, normalB ) < b2Dot( normal1, normalB ) ) + { + // Neighbor is incident + return manifold; + } + } + + manifold = + b2ClipSegments( b1, b2, p1, p2, normalB, radiusB, 0.0f, B2_MAKE_ID( ib1, 1 ), B2_MAKE_ID( ib2, 0 ) ); + + B2_ASSERT( manifold.pointCount == 0 || manifold.pointCount == 2 ); + if ( manifold.pointCount == 2 ) + { + manifold.normal = b2RotateVector( xfA.q, b2Neg( normalB ) ); + manifold.points[0].anchorA = b2RotateVector( xfA.q, manifold.points[0].anchorA ); + manifold.points[1].anchorA = b2RotateVector( xfA.q, manifold.points[1].anchorA ); + b2Vec2 pAB = b2Sub( xfA.p, xfB.p ); + manifold.points[0].anchorB = b2Add( manifold.points[0].anchorA, pAB ); + manifold.points[1].anchorB = b2Add( manifold.points[1].anchorA, pAB ); + manifold.points[0].point = b2Add( xfA.p, manifold.points[0].anchorA ); + manifold.points[1].point = b2Add( xfA.p, manifold.points[1].anchorA ); + } + return manifold; + } + + // fall through b2_normalSnap + incidentNormal = ib; + } + else + { + // Get index of incident polygonB vertex + float dot1 = b2Dot( normal1, b2Sub( vertices[ib1], p1 ) ); + float dot2 = b2Dot( normal1, b2Sub( vertices[ib2], p2 ) ); + incidentIndex = dot1 < dot2 ? ib1 : ib2; + } + } + } + else + { + // SAT edge normal + float edgeSeparation = FLT_MAX; + + for ( int i = 0; i < count; ++i ) + { + float s = b2Dot( normal1, b2Sub( vertices[i], p1 ) ); + if ( s < edgeSeparation ) + { + edgeSeparation = s; + incidentIndex = i; + } + } + + // Check convex neighbor for edge separation + if ( smoothParams.convex1 ) + { + float s0 = FLT_MAX; + + for ( int i = 0; i < count; ++i ) + { + float s = b2Dot( smoothParams.normal0, b2Sub( vertices[i], p1 ) ); + if ( s < s0 ) + { + s0 = s; + } + } + + if ( s0 > edgeSeparation ) + { + edgeSeparation = s0; + + // Indicate neighbor owns edge separation + incidentIndex = -1; + } + } + + // Check convex neighbor for edge separation + if ( smoothParams.convex2 ) + { + float s2 = FLT_MAX; + + for ( int i = 0; i < count; ++i ) + { + float s = b2Dot( smoothParams.normal2, b2Sub( vertices[i], p2 ) ); + if ( s < s2 ) + { + s2 = s; + } + } + + if ( s2 > edgeSeparation ) + { + edgeSeparation = s2; + + // Indicate neighbor owns edge separation + incidentIndex = -1; + } + } + + // SAT polygon normals + float polygonSeparation = -FLT_MAX; + int referenceIndex = -1; + + for ( int i = 0; i < count; ++i ) + { + b2Vec2 n = normals[i]; + + enum b2NormalType type = b2ClassifyNormal( smoothParams, b2Neg( n ) ); + if ( type != b2_normalAdmit ) + { + continue; + } + + // Check the infinite sides of the partial polygon + // if ((smoothParams.convex1 && b2Cross(n0, n) > 0.0f) || (smoothParams.convex2 && b2Cross(n, n2) > 0.0f)) + //{ + // continue; + //} + + b2Vec2 p = vertices[i]; + float s = b2MinFloat( b2Dot( n, b2Sub( p2, p ) ), b2Dot( n, b2Sub( p1, p ) ) ); + + if ( s > polygonSeparation ) + { + polygonSeparation = s; + referenceIndex = i; + } + } + + if ( polygonSeparation > edgeSeparation ) + { + int ia1 = referenceIndex; + int ia2 = ia1 < count - 1 ? ia1 + 1 : 0; + b2Vec2 a1 = vertices[ia1]; + b2Vec2 a2 = vertices[ia2]; + + b2Vec2 n = normals[ia1]; + + float dot1 = b2Dot( n, b2Sub( p1, a1 ) ); + float dot2 = b2Dot( n, b2Sub( p2, a1 ) ); + + if ( dot1 < dot2 ) + { + if ( b2Dot( n0, n ) < b2Dot( normal1, n ) ) + { + // Neighbor is incident + return manifold; + } + } + else + { + if ( b2Dot( n2, n ) < b2Dot( normal1, n ) ) + { + // Neighbor is incident + return manifold; + } + } + + manifold = b2ClipSegments( a1, a2, p1, p2, normals[ia1], radiusB, 0.0f, B2_MAKE_ID( ia1, 1 ), B2_MAKE_ID( ia2, 0 ) ); + + B2_ASSERT( manifold.pointCount == 0 || manifold.pointCount == 2 ); + if ( manifold.pointCount == 2 ) + { + + manifold.normal = b2RotateVector( xfA.q, b2Neg( normals[ia1] ) ); + manifold.points[0].anchorA = b2RotateVector( xfA.q, manifold.points[0].anchorA ); + manifold.points[1].anchorA = b2RotateVector( xfA.q, manifold.points[1].anchorA ); + b2Vec2 pAB = b2Sub( xfA.p, xfB.p ); + manifold.points[0].anchorB = b2Add( manifold.points[0].anchorA, pAB ); + manifold.points[1].anchorB = b2Add( manifold.points[1].anchorA, pAB ); + manifold.points[0].point = b2Add( xfA.p, manifold.points[0].anchorA ); + manifold.points[1].point = b2Add( xfA.p, manifold.points[1].anchorA ); + } + + return manifold; + } + + if ( incidentIndex == -1 ) + { + // neighboring segment is the separating axis + return manifold; + } + + // fall through segment normal axis + } + + B2_ASSERT( incidentNormal != -1 || incidentIndex != -1 ); + + // Segment normal + + // Find incident polygon normal: normal adjacent to deepest vertex that is most anti-parallel to segment normal + b2Vec2 b1, b2; + int ib1, ib2; + + if ( incidentNormal != -1 ) + { + ib1 = incidentNormal; + ib2 = ib1 < count - 1 ? ib1 + 1 : 0; + b1 = vertices[ib1]; + b2 = vertices[ib2]; + } + else + { + int i2 = incidentIndex; + int i1 = i2 > 0 ? i2 - 1 : count - 1; + float d1 = b2Dot( normal1, normals[i1] ); + float d2 = b2Dot( normal1, normals[i2] ); + if ( d1 < d2 ) + { + ib1 = i1, ib2 = i2; + b1 = vertices[ib1]; + b2 = vertices[ib2]; + } + else + { + ib1 = i2, ib2 = i2 < count - 1 ? i2 + 1 : 0; + b1 = vertices[ib1]; + b2 = vertices[ib2]; + } + } + + manifold = b2ClipSegments( p1, p2, b1, b2, normal1, 0.0f, radiusB, B2_MAKE_ID( 0, ib2 ), B2_MAKE_ID( 1, ib1 ) ); + + B2_ASSERT( manifold.pointCount == 0 || manifold.pointCount == 2 ); + if ( manifold.pointCount == 2 ) + { + // There may be no points c + manifold.normal = b2RotateVector( xfA.q, manifold.normal ); + manifold.points[0].anchorA = b2RotateVector( xfA.q, manifold.points[0].anchorA ); + manifold.points[1].anchorA = b2RotateVector( xfA.q, manifold.points[1].anchorA ); + b2Vec2 pAB = b2Sub( xfA.p, xfB.p ); + manifold.points[0].anchorB = b2Add( manifold.points[0].anchorA, pAB ); + manifold.points[1].anchorB = b2Add( manifold.points[1].anchorA, pAB ); + manifold.points[0].point = b2Add( xfA.p, manifold.points[0].anchorA ); + manifold.points[1].point = b2Add( xfA.p, manifold.points[1].anchorA ); + } + + return manifold; +} diff --git a/3rdparty/box2d/src/math_functions.c b/3rdparty/box2d/src/math_functions.c new file mode 100644 index 000000000000..5b1e94972a66 --- /dev/null +++ b/3rdparty/box2d/src/math_functions.c @@ -0,0 +1,159 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "box2d/math_functions.h" + +#include + +_Static_assert( sizeof( int32_t ) == sizeof( int ), "Box2D expects int32_t and int to be the same" ); + +bool b2IsValidFloat( float a ) +{ + if ( isnan( a ) ) + { + return false; + } + + if ( isinf( a ) ) + { + return false; + } + + return true; +} + +bool b2IsValidVec2( b2Vec2 v ) +{ + if ( isnan( v.x ) || isnan( v.y ) ) + { + return false; + } + + if ( isinf( v.x ) || isinf( v.y ) ) + { + return false; + } + + return true; +} + +bool b2IsValidRotation( b2Rot q ) +{ + if ( isnan( q.s ) || isnan( q.c ) ) + { + return false; + } + + if ( isinf( q.s ) || isinf( q.c ) ) + { + return false; + } + + return b2IsNormalizedRot( q ); +} + +bool b2IsValidPlane( b2Plane a ) +{ + return b2IsValidVec2( a.normal ) && b2IsNormalized( a.normal ) && b2IsValidFloat( a.offset ); +} + +// https://stackoverflow.com/questions/46210708/atan2-approximation-with-11bits-in-mantissa-on-x86with-sse2-and-armwith-vfpv4 +float b2Atan2( float y, float x ) +{ + // Added check for (0,0) to match atan2f and avoid NaN + if (x == 0.0f && y == 0.0f) + { + return 0.0f; + } + + float ax = b2AbsFloat( x ); + float ay = b2AbsFloat( y ); + float mx = b2MaxFloat( ay, ax ); + float mn = b2MinFloat( ay, ax ); + float a = mn / mx; + + // Minimax polynomial approximation to atan(a) on [0,1] + float s = a * a; + float c = s * a; + float q = s * s; + float r = 0.024840285f * q + 0.18681418f; + float t = -0.094097948f * q - 0.33213072f; + r = r * s + t; + r = r * c + a; + + // Map to full circle + if ( ay > ax ) + { + r = 1.57079637f - r; + } + + if ( x < 0 ) + { + r = 3.14159274f - r; + } + + if ( y < 0 ) + { + r = -r; + } + + return r; +} + +// Approximate cosine and sine for determinism. In my testing cosf and sinf produced +// the same results on x64 and ARM using MSVC, GCC, and Clang. However, I don't trust +// this result. +// https://en.wikipedia.org/wiki/Bh%C4%81skara_I%27s_sine_approximation_formula +b2CosSin b2ComputeCosSin( float radians ) +{ + float x = b2UnwindLargeAngle( radians ); + float pi2 = B2_PI * B2_PI; + + // cosine needs angle in [-pi/2, pi/2] + float c; + if ( x < -0.5f * B2_PI ) + { + float y = x + B2_PI; + float y2 = y * y; + c = -( pi2 - 4.0f * y2 ) / ( pi2 + y2 ); + } + else if ( x > 0.5f * B2_PI ) + { + float y = x - B2_PI; + float y2 = y * y; + c = -( pi2 - 4.0f * y2 ) / ( pi2 + y2 ); + } + else + { + float y2 = x * x; + c = ( pi2 - 4.0f * y2 ) / ( pi2 + y2 ); + } + + // sine needs angle in [0, pi] + float s; + if ( x < 0.0f ) + { + float y = x + B2_PI; + s = -16.0f * y * ( B2_PI - y ) / ( 5.0f * pi2 - 4.0f * y * ( B2_PI - y ) ); + } + else + { + s = 16.0f * x * ( B2_PI - x ) / ( 5.0f * pi2 - 4.0f * x * ( B2_PI - x ) ); + } + + float mag = sqrtf( s * s + c * c ); + float invMag = mag > 0.0 ? 1.0f / mag : 0.0f; + b2CosSin cs = { c * invMag, s * invMag }; + return cs; +} + +b2Rot b2ComputeRotationBetweenUnitVectors(b2Vec2 v1, b2Vec2 v2) +{ + B2_ASSERT( b2AbsFloat( 1.0f - b2Length( v1 ) ) < 100.0f * FLT_EPSILON ); + B2_ASSERT( b2AbsFloat( 1.0f - b2Length( v2 ) ) < 100.0f * FLT_EPSILON ); + + b2Rot rot; + rot.c = b2Dot( v1, v2 ); + rot.s = b2Cross( v1, v2 ); + return b2NormalizeRot( rot ); +} diff --git a/3rdparty/box2d/src/motor_joint.c b/3rdparty/box2d/src/motor_joint.c new file mode 100644 index 000000000000..d6610d62eb41 --- /dev/null +++ b/3rdparty/box2d/src/motor_joint.c @@ -0,0 +1,283 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +void b2MotorJoint_SetLinearOffset( b2JointId jointId, b2Vec2 linearOffset ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + joint->motorJoint.linearOffset = linearOffset; +} + +b2Vec2 b2MotorJoint_GetLinearOffset( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + return joint->motorJoint.linearOffset; +} + +void b2MotorJoint_SetAngularOffset( b2JointId jointId, float angularOffset ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + joint->motorJoint.angularOffset = b2ClampFloat( angularOffset, -B2_PI, B2_PI ); +} + +float b2MotorJoint_GetAngularOffset( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + return joint->motorJoint.angularOffset; +} + +void b2MotorJoint_SetMaxForce( b2JointId jointId, float maxForce ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + joint->motorJoint.maxForce = b2MaxFloat( 0.0f, maxForce ); +} + +float b2MotorJoint_GetMaxForce( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + return joint->motorJoint.maxForce; +} + +void b2MotorJoint_SetMaxTorque( b2JointId jointId, float maxTorque ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + joint->motorJoint.maxTorque = b2MaxFloat( 0.0f, maxTorque ); +} + +float b2MotorJoint_GetMaxTorque( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + return joint->motorJoint.maxTorque; +} + +void b2MotorJoint_SetCorrectionFactor( b2JointId jointId, float correctionFactor ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + joint->motorJoint.correctionFactor = b2ClampFloat( correctionFactor, 0.0f, 1.0f ); +} + +float b2MotorJoint_GetCorrectionFactor( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_motorJoint ); + return joint->motorJoint.correctionFactor; +} + +b2Vec2 b2GetMotorJointForce( b2World* world, b2JointSim* base ) +{ + b2Vec2 force = b2MulSV( world->inv_h, base->motorJoint.linearImpulse ); + return force; +} + +float b2GetMotorJointTorque( b2World* world, b2JointSim* base ) +{ + return world->inv_h * base->motorJoint.angularImpulse; +} + +// Point-to-point constraint +// C = p2 - p1 +// Cdot = v2 - v1 +// = v2 + cross(w2, r2) - v1 - cross(w1, r1) +// J = [-I -r1_skew I r2_skew ] +// Identity used: +// w k % (rx i + ry j) = w * (-ry i + rx j) + +// Angle constraint +// C = angle2 - angle1 - referenceAngle +// Cdot = w2 - w1 +// J = [0 0 -1 0 0 1] +// K = invI1 + invI2 + +void b2PrepareMotorJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_motorJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2MotorJoint* joint = &base->motorJoint; + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + joint->anchorA = b2RotateVector( bodySimA->transform.q, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->deltaCenter = b2Sub( b2Sub( bodySimB->center, bodySimA->center ), joint->linearOffset ); + joint->deltaAngle = b2RelativeAngle( bodySimB->transform.q, bodySimA->transform.q ) - joint->angularOffset; + joint->deltaAngle = b2UnwindAngle( joint->deltaAngle ); + + b2Vec2 rA = joint->anchorA; + b2Vec2 rB = joint->anchorB; + + b2Mat22 K; + K.cx.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; + K.cx.y = -rA.y * rA.x * iA - rB.y * rB.x * iB; + K.cy.x = K.cx.y; + K.cy.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; + joint->linearMass = b2GetInverse22( K ); + + float ka = iA + iB; + joint->angularMass = ka > 0.0f ? 1.0f / ka : 0.0f; + + if ( context->enableWarmStarting == false ) + { + joint->linearImpulse = b2Vec2_zero; + joint->angularImpulse = 0.0f; + } +} + +void b2WarmStartMotorJoint( b2JointSim* base, b2StepContext* context ) +{ + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + b2MotorJoint* joint = &base->motorJoint; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2BodyState* bodyA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* bodyB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( bodyA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( bodyB->deltaRotation, joint->anchorB ); + + bodyA->linearVelocity = b2MulSub( bodyA->linearVelocity, mA, joint->linearImpulse ); + bodyA->angularVelocity -= iA * ( b2Cross( rA, joint->linearImpulse ) + joint->angularImpulse ); + bodyB->linearVelocity = b2MulAdd( bodyB->linearVelocity, mB, joint->linearImpulse ); + bodyB->angularVelocity += iB * ( b2Cross( rB, joint->linearImpulse ) + joint->angularImpulse ); +} + +void b2SolveMotorJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_UNUSED( useBias ); + B2_ASSERT( base->type == b2_motorJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2MotorJoint* joint = &base->motorJoint; + b2BodyState* bodyA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* bodyB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = bodyA->linearVelocity; + float wA = bodyA->angularVelocity; + b2Vec2 vB = bodyB->linearVelocity; + float wB = bodyB->angularVelocity; + + // angular constraint + { + float angularSeperation = b2RelativeAngle( bodyB->deltaRotation, bodyA->deltaRotation ) + joint->deltaAngle; + angularSeperation = b2UnwindAngle( angularSeperation ); + + float angularBias = context->inv_h * joint->correctionFactor * angularSeperation; + + float Cdot = wB - wA; + float impulse = -joint->angularMass * ( Cdot + angularBias ); + + float oldImpulse = joint->angularImpulse; + float maxImpulse = context->h * joint->maxTorque; + joint->angularImpulse = b2ClampFloat( joint->angularImpulse + impulse, -maxImpulse, maxImpulse ); + impulse = joint->angularImpulse - oldImpulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + // linear constraint + { + b2Vec2 rA = b2RotateVector( bodyA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( bodyB->deltaRotation, joint->anchorB ); + + b2Vec2 ds = b2Add( b2Sub( bodyB->deltaPosition, bodyA->deltaPosition ), b2Sub( rB, rA ) ); + b2Vec2 linearSeparation = b2Add( joint->deltaCenter, ds ); + b2Vec2 linearBias = b2MulSV( context->inv_h * joint->correctionFactor, linearSeparation ); + + b2Vec2 Cdot = b2Sub( b2Add( vB, b2CrossSV( wB, rB ) ), b2Add( vA, b2CrossSV( wA, rA ) ) ); + b2Vec2 b = b2MulMV( joint->linearMass, b2Add( Cdot, linearBias ) ); + b2Vec2 impulse = { -b.x, -b.y }; + + b2Vec2 oldImpulse = joint->linearImpulse; + float maxImpulse = context->h * joint->maxForce; + joint->linearImpulse = b2Add( joint->linearImpulse, impulse ); + + if ( b2LengthSquared( joint->linearImpulse ) > maxImpulse * maxImpulse ) + { + joint->linearImpulse = b2Normalize( joint->linearImpulse ); + joint->linearImpulse.x *= maxImpulse; + joint->linearImpulse.y *= maxImpulse; + } + + impulse = b2Sub( joint->linearImpulse, oldImpulse ); + + vA = b2MulSub( vA, mA, impulse ); + wA -= iA * b2Cross( rA, impulse ); + vB = b2MulAdd( vB, mB, impulse ); + wB += iB * b2Cross( rB, impulse ); + } + + bodyA->linearVelocity = vA; + bodyA->angularVelocity = wA; + bodyB->linearVelocity = vB; + bodyB->angularVelocity = wB; +} + +#if 0 +void b2DumpMotorJoint() +{ + int32 indexA = m_bodyA->m_islandIndex; + int32 indexB = m_bodyB->m_islandIndex; + + b2Dump(" b2MotorJointDef jd;\n"); + b2Dump(" jd.bodyA = sims[%d];\n", indexA); + b2Dump(" jd.bodyB = sims[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); + b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle); + b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); + b2Dump(" jd.damping = %.9g;\n", m_damping); + b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); +} +#endif diff --git a/3rdparty/box2d/src/mouse_joint.c b/3rdparty/box2d/src/mouse_joint.c new file mode 100644 index 000000000000..6042fd35d135 --- /dev/null +++ b/3rdparty/box2d/src/mouse_joint.c @@ -0,0 +1,214 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +void b2MouseJoint_SetTarget( b2JointId jointId, b2Vec2 target ) +{ + B2_ASSERT( b2IsValidVec2( target ) ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + base->mouseJoint.targetA = target; +} + +b2Vec2 b2MouseJoint_GetTarget( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + return base->mouseJoint.targetA; +} + +void b2MouseJoint_SetSpringHertz( b2JointId jointId, float hertz ) +{ + B2_ASSERT( b2IsValidFloat( hertz ) && hertz >= 0.0f ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + base->mouseJoint.hertz = hertz; +} + +float b2MouseJoint_GetSpringHertz( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + return base->mouseJoint.hertz; +} + +void b2MouseJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ) +{ + B2_ASSERT( b2IsValidFloat( dampingRatio ) && dampingRatio >= 0.0f ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + base->mouseJoint.dampingRatio = dampingRatio; +} + +float b2MouseJoint_GetSpringDampingRatio( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + return base->mouseJoint.dampingRatio; +} + +void b2MouseJoint_SetMaxForce( b2JointId jointId, float maxForce ) +{ + B2_ASSERT( b2IsValidFloat( maxForce ) && maxForce >= 0.0f ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + base->mouseJoint.maxForce = maxForce; +} + +float b2MouseJoint_GetMaxForce( b2JointId jointId ) +{ + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_mouseJoint ); + return base->mouseJoint.maxForce; +} + +b2Vec2 b2GetMouseJointForce( b2World* world, b2JointSim* base ) +{ + b2Vec2 force = b2MulSV( world->inv_h, base->mouseJoint.linearImpulse ); + return force; +} + +float b2GetMouseJointTorque( b2World* world, b2JointSim* base ) +{ + return world->inv_h * base->mouseJoint.angularImpulse; +} + +void b2PrepareMouseJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_mouseJoint ); + + // chase body id to the solver set where the body lives + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyB->setIndex == b2_awakeSet ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexB = bodyB->localIndex; + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + base->invMassB = bodySimB->invMass; + base->invIB = bodySimB->invInertia; + + b2MouseJoint* joint = &base->mouseJoint; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + + joint->linearSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h ); + + float angularHertz = 0.5f; + float angularDampingRatio = 0.1f; + joint->angularSoftness = b2MakeSoft( angularHertz, angularDampingRatio, context->h ); + + b2Vec2 rB = joint->anchorB; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + // K = [(1/m1 + 1/m2) * eye(2) - skew(r1) * invI1 * skew(r1) - skew(r2) * invI2 * skew(r2)] + // = [1/m1+1/m2 0 ] + invI1 * [r1.y*r1.y -r1.x*r1.y] + invI2 * [r1.y*r1.y -r1.x*r1.y] + // [ 0 1/m1+1/m2] [-r1.x*r1.y r1.x*r1.x] [-r1.x*r1.y r1.x*r1.x] + b2Mat22 K; + K.cx.x = mB + iB * rB.y * rB.y; + K.cx.y = -iB * rB.x * rB.y; + K.cy.x = K.cx.y; + K.cy.y = mB + iB * rB.x * rB.x; + + joint->linearMass = b2GetInverse22( K ); + joint->deltaCenter = b2Sub( bodySimB->center, joint->targetA ); + + if ( context->enableWarmStarting == false ) + { + joint->linearImpulse = b2Vec2_zero; + joint->angularImpulse = 0.0f; + } +} + +void b2WarmStartMouseJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_mouseJoint ); + + float mB = base->invMassB; + float iB = base->invIB; + + b2MouseJoint* joint = &base->mouseJoint; + + b2BodyState* stateB = context->states + joint->indexB; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + b2Rot dqB = stateB->deltaRotation; + b2Vec2 rB = b2RotateVector( dqB, joint->anchorB ); + + vB = b2MulAdd( vB, mB, joint->linearImpulse ); + wB += iB * ( b2Cross( rB, joint->linearImpulse ) + joint->angularImpulse ); + + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +void b2SolveMouseJoint( b2JointSim* base, b2StepContext* context ) +{ + float mB = base->invMassB; + float iB = base->invIB; + + b2MouseJoint* joint = &base->mouseJoint; + b2BodyState* stateB = context->states + joint->indexB; + + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + // Softness with no bias to reduce rotation speed + { + float massScale = joint->angularSoftness.massScale; + float impulseScale = joint->angularSoftness.impulseScale; + + float impulse = iB > 0.0f ? -wB / iB : 0.0f; + impulse = massScale * impulse - impulseScale * joint->angularImpulse; + joint->angularImpulse += impulse; + + wB += iB * impulse; + } + + float maxImpulse = joint->maxForce * context->h; + + { + b2Rot dqB = stateB->deltaRotation; + b2Vec2 rB = b2RotateVector( dqB, joint->anchorB ); + b2Vec2 Cdot = b2Add( vB, b2CrossSV( wB, rB ) ); + + b2Vec2 separation = b2Add( b2Add( stateB->deltaPosition, rB ), joint->deltaCenter ); + b2Vec2 bias = b2MulSV( joint->linearSoftness.biasRate, separation ); + + float massScale = joint->linearSoftness.massScale; + float impulseScale = joint->linearSoftness.impulseScale; + + b2Vec2 b = b2MulMV( joint->linearMass, b2Add( Cdot, bias ) ); + + b2Vec2 impulse; + impulse.x = -massScale * b.x - impulseScale * joint->linearImpulse.x; + impulse.y = -massScale * b.y - impulseScale * joint->linearImpulse.y; + + b2Vec2 oldImpulse = joint->linearImpulse; + joint->linearImpulse.x += impulse.x; + joint->linearImpulse.y += impulse.y; + + float mag = b2Length( joint->linearImpulse ); + if ( mag > maxImpulse ) + { + joint->linearImpulse = b2MulSV( maxImpulse, b2Normalize( joint->linearImpulse ) ); + } + + impulse.x = joint->linearImpulse.x - oldImpulse.x; + impulse.y = joint->linearImpulse.y - oldImpulse.y; + + vB = b2MulAdd( vB, mB, impulse ); + wB += iB * b2Cross( rB, impulse ); + } + + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} diff --git a/3rdparty/box2d/src/mover.c b/3rdparty/box2d/src/mover.c new file mode 100644 index 000000000000..10644b0b95a3 --- /dev/null +++ b/3rdparty/box2d/src/mover.c @@ -0,0 +1,73 @@ +// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-License-Identifier: MIT + +#include "constants.h" + +#include "box2d/collision.h" + +b2PlaneSolverResult b2SolvePlanes( b2Vec2 position, b2CollisionPlane* planes, int count ) +{ + for ( int i = 0; i < count; ++i ) + { + planes[i].push = 0.0f; + } + + b2Vec2 delta = b2Vec2_zero; + float tolerance = B2_LINEAR_SLOP; + + int iteration; + for ( iteration = 0; iteration < 20; ++iteration ) + { + float totalPush = 0.0f; + for ( int planeIndex = 0; planeIndex < count; ++planeIndex ) + { + b2CollisionPlane* plane = planes + planeIndex; + + // Add slop to prevent jitter + float separation = b2PlaneSeparation( plane->plane, delta ) + B2_LINEAR_SLOP; + // if (separation > 0.0f) + //{ + // continue; + // } + + float push = -separation; + + // Clamp accumulated push + float accumulatedPush = plane->push; + plane->push = b2ClampFloat( plane->push + push, 0.0f, plane->pushLimit ); + push = plane->push - accumulatedPush; + delta = b2MulAdd( delta, push, plane->plane.normal ); + + // Track maximum push for convergence + totalPush += b2AbsFloat( push ); + } + + if ( totalPush < tolerance ) + { + break; + } + } + + return (b2PlaneSolverResult){ + .position = b2Add( delta, position ), + .iterationCount = iteration, + }; +} + +b2Vec2 b2ClipVector( b2Vec2 vector, const b2CollisionPlane* planes, int count ) +{ + b2Vec2 v = vector; + + for ( int planeIndex = 0; planeIndex < count; ++planeIndex ) + { + const b2CollisionPlane* plane = planes + planeIndex; + if ( plane->push == 0.0f || plane->clipVelocity == false ) + { + continue; + } + + v = b2MulSub( v, b2MinFloat( 0.0f, b2Dot( v, plane->plane.normal ) ), plane->plane.normal ); + } + + return v; +} diff --git a/3rdparty/box2d/src/prismatic_joint.c b/3rdparty/box2d/src/prismatic_joint.c new file mode 100644 index 000000000000..0d5209c4ffec --- /dev/null +++ b/3rdparty/box2d/src/prismatic_joint.c @@ -0,0 +1,656 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include + +void b2PrismaticJoint_EnableSpring( b2JointId jointId, bool enableSpring ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + if ( enableSpring != joint->prismaticJoint.enableSpring ) + { + joint->prismaticJoint.enableSpring = enableSpring; + joint->prismaticJoint.springImpulse = 0.0f; + } +} + +bool b2PrismaticJoint_IsSpringEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.enableSpring; +} + +void b2PrismaticJoint_SetSpringHertz( b2JointId jointId, float hertz ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + joint->prismaticJoint.hertz = hertz; +} + +float b2PrismaticJoint_GetSpringHertz( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.hertz; +} + +void b2PrismaticJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + joint->prismaticJoint.dampingRatio = dampingRatio; +} + +float b2PrismaticJoint_GetSpringDampingRatio( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.dampingRatio; +} + +void b2PrismaticJoint_EnableLimit( b2JointId jointId, bool enableLimit ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + if ( enableLimit != joint->prismaticJoint.enableLimit ) + { + joint->prismaticJoint.enableLimit = enableLimit; + joint->prismaticJoint.lowerImpulse = 0.0f; + joint->prismaticJoint.upperImpulse = 0.0f; + } +} + +bool b2PrismaticJoint_IsLimitEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.enableLimit; +} + +float b2PrismaticJoint_GetLowerLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.lowerTranslation; +} + +float b2PrismaticJoint_GetUpperLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.upperTranslation; +} + +void b2PrismaticJoint_SetLimits( b2JointId jointId, float lower, float upper ) +{ + B2_ASSERT( lower <= upper ); + + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + if ( lower != joint->prismaticJoint.lowerTranslation || upper != joint->prismaticJoint.upperTranslation ) + { + joint->prismaticJoint.lowerTranslation = b2MinFloat( lower, upper ); + joint->prismaticJoint.upperTranslation = b2MaxFloat( lower, upper ); + joint->prismaticJoint.lowerImpulse = 0.0f; + joint->prismaticJoint.upperImpulse = 0.0f; + } +} + +void b2PrismaticJoint_EnableMotor( b2JointId jointId, bool enableMotor ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + if ( enableMotor != joint->prismaticJoint.enableMotor ) + { + joint->prismaticJoint.enableMotor = enableMotor; + joint->prismaticJoint.motorImpulse = 0.0f; + } +} + +bool b2PrismaticJoint_IsMotorEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.enableMotor; +} + +void b2PrismaticJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + joint->prismaticJoint.motorSpeed = motorSpeed; +} + +float b2PrismaticJoint_GetMotorSpeed( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.motorSpeed; +} + +float b2PrismaticJoint_GetMotorForce( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* base = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return world->inv_h * base->prismaticJoint.motorImpulse; +} + +void b2PrismaticJoint_SetMaxMotorForce( b2JointId jointId, float force ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + joint->prismaticJoint.maxMotorForce = force; +} + +float b2PrismaticJoint_GetMaxMotorForce( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + return joint->prismaticJoint.maxMotorForce; +} + +float b2PrismaticJoint_GetTranslation(b2JointId jointId) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* jointSim = b2GetJointSimCheckType( jointId, b2_prismaticJoint ); + b2Transform transformA = b2GetBodyTransform( world, jointSim->bodyIdA ); + b2Transform transformB = b2GetBodyTransform( world, jointSim->bodyIdB ); + + b2PrismaticJoint* joint = &jointSim->prismaticJoint; + b2Vec2 axisA = b2RotateVector( transformA.q, joint->localAxisA ); + b2Vec2 pA = b2TransformPoint( transformA, jointSim->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, jointSim->localOriginAnchorB ); + b2Vec2 d = b2Sub( pB, pA ); + float translation = b2Dot( d, axisA ); + return translation; +} + +float b2PrismaticJoint_GetSpeed(b2JointId jointId) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2Joint* joint = b2GetJointFullId( world, jointId ); + B2_ASSERT( joint->type == b2_prismaticJoint ); + b2JointSim* jointSim = b2GetJointSim( world, joint ); + B2_ASSERT( jointSim->type == b2_prismaticJoint ); + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, jointSim->bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, jointSim->bodyIdB ); + b2BodySim* bodySimA = b2GetBodySim( world, bodyA ); + b2BodySim* bodySimB = b2GetBodySim( world, bodyB ); + b2BodyState* bodyStateA = b2GetBodyState( world, bodyA ); + b2BodyState* bodyStateB = b2GetBodyState( world, bodyB ); + + b2Transform transformA = bodySimA->transform; + b2Transform transformB = bodySimB->transform; + + b2PrismaticJoint* prismatic = &jointSim->prismaticJoint; + b2Vec2 axisA = b2RotateVector( transformA.q, prismatic->localAxisA ); + b2Vec2 cA = bodySimA->center; + b2Vec2 cB = bodySimB->center; + b2Vec2 rA = b2RotateVector( transformA.q, b2Sub( jointSim->localOriginAnchorA, bodySimA->localCenter ) ); + b2Vec2 rB = b2RotateVector( transformB.q, b2Sub( jointSim->localOriginAnchorB, bodySimB->localCenter ) ); + + b2Vec2 d = b2Add(b2Sub(cB, cA), b2Sub( rB, rA )); + + b2Vec2 vA = bodyStateA ? bodyStateA->linearVelocity : b2Vec2_zero; + b2Vec2 vB = bodyStateB ? bodyStateB->linearVelocity : b2Vec2_zero; + float wA = bodyStateA ? bodyStateA->angularVelocity : 0.0f; + float wB = bodyStateB ? bodyStateB->angularVelocity : 0.0f; + + b2Vec2 vRel = b2Sub( b2Add( vB, b2CrossSV( wB, rB ) ), b2Add( vA, b2CrossSV( wA, rA ) ) ); + float speed = b2Dot( d, b2CrossSV( wA, axisA ) ) + b2Dot( axisA, vRel ); + return speed; +} + +b2Vec2 b2GetPrismaticJointForce( b2World* world, b2JointSim* base ) +{ + int idA = base->bodyIdA; + b2Transform transformA = b2GetBodyTransform( world, idA ); + + b2PrismaticJoint* joint = &base->prismaticJoint; + + b2Vec2 axisA = b2RotateVector( transformA.q, joint->localAxisA ); + b2Vec2 perpA = b2LeftPerp( axisA ); + + float inv_h = world->inv_h; + float perpForce = inv_h * joint->impulse.x; + float axialForce = inv_h * ( joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse ); + + b2Vec2 force = b2Add( b2MulSV( perpForce, perpA ), b2MulSV( axialForce, axisA ) ); + return force; +} + +float b2GetPrismaticJointTorque( b2World* world, b2JointSim* base ) +{ + return world->inv_h * base->prismaticJoint.impulse.y; +} + +// Linear constraint (point-to-line) +// d = p2 - p1 = x2 + r2 - x1 - r1 +// C = dot(perp, d) +// Cdot = dot(d, cross(w1, perp)) + dot(perp, v2 + cross(w2, r2) - v1 - cross(w1, r1)) +// = -dot(perp, v1) - dot(cross(d + r1, perp), w1) + dot(perp, v2) + dot(cross(r2, perp), v2) +// J = [-perp, -cross(d + r1, perp), perp, cross(r2,perp)] +// +// Angular constraint +// C = a2 - a1 + a_initial +// Cdot = w2 - w1 +// J = [0 0 -1 0 0 1] +// +// K = J * invM * JT +// +// J = [-a -s1 a s2] +// [0 -1 0 1] +// a = perp +// s1 = cross(d + r1, a) = cross(p2 - x1, a) +// s2 = cross(r2, a) = cross(p2 - x2, a) + +// Motor/Limit linear constraint +// C = dot(ax1, d) +// Cdot = -dot(ax1, v1) - dot(cross(d + r1, ax1), w1) + dot(ax1, v2) + dot(cross(r2, ax1), v2) +// J = [-ax1 -cross(d+r1,ax1) ax1 cross(r2,ax1)] + +// Predictive limit is applied even when the limit is not active. +// Prevents a constraint speed that can lead to a constraint error in one time step. +// Want C2 = C1 + h * Cdot >= 0 +// Or: +// Cdot + C1/h >= 0 +// I do not apply a negative constraint error because that is handled in position correction. +// So: +// Cdot + max(C1, 0)/h >= 0 + +// Block Solver +// We develop a block solver that includes the angular and linear constraints. This makes the limit stiffer. +// +// The Jacobian has 2 rows: +// J = [-uT -s1 uT s2] // linear +// [0 -1 0 1] // angular +// +// u = perp +// s1 = cross(d + r1, u), s2 = cross(r2, u) +// a1 = cross(d + r1, v), a2 = cross(r2, v) + +void b2PreparePrismaticJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_prismaticJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2PrismaticJoint* joint = &base->prismaticJoint; + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + b2Rot qA = bodySimA->transform.q; + b2Rot qB = bodySimB->transform.q; + + joint->anchorA = b2RotateVector( qA, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( qB, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->axisA = b2RotateVector( qA, joint->localAxisA ); + joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center ); + joint->deltaAngle = b2RelativeAngle( qB, qA ) - joint->referenceAngle; + joint->deltaAngle = b2UnwindAngle( joint->deltaAngle ); + + b2Vec2 rA = joint->anchorA; + b2Vec2 rB = joint->anchorB; + + b2Vec2 d = b2Add( joint->deltaCenter, b2Sub( rB, rA ) ); + float a1 = b2Cross( b2Add( d, rA ), joint->axisA ); + float a2 = b2Cross( rB, joint->axisA ); + + // effective masses + float k = mA + mB + iA * a1 * a1 + iB * a2 * a2; + joint->axialMass = k > 0.0f ? 1.0f / k : 0.0f; + + joint->springSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h ); + + if ( context->enableWarmStarting == false ) + { + joint->impulse = b2Vec2_zero; + joint->springImpulse = 0.0f; + joint->motorImpulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; + } +} + +void b2WarmStartPrismaticJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_prismaticJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2PrismaticJoint* joint = &base->prismaticJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 d = b2Add( b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), joint->deltaCenter ), b2Sub( rB, rA ) ); + b2Vec2 axisA = b2RotateVector( stateA->deltaRotation, joint->axisA ); + + // impulse is applied at anchor point on body B + float a1 = b2Cross( b2Add( d, rA ), axisA ); + float a2 = b2Cross( rB, axisA ); + float axialImpulse = joint->springImpulse + joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse; + + // perpendicular constraint + b2Vec2 perpA = b2LeftPerp( axisA ); + float s1 = b2Cross( b2Add( d, rA ), perpA ); + float s2 = b2Cross( rB, perpA ); + float perpImpulse = joint->impulse.x; + float angleImpulse = joint->impulse.y; + + b2Vec2 P = b2Add( b2MulSV( axialImpulse, axisA ), b2MulSV( perpImpulse, perpA ) ); + float LA = axialImpulse * a1 + perpImpulse * s1 + angleImpulse; + float LB = axialImpulse * a2 + perpImpulse * s2 + angleImpulse; + + stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, P ); + stateA->angularVelocity -= iA * LA; + stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, P ); + stateB->angularVelocity += iB * LB; +} + +void b2SolvePrismaticJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_ASSERT( base->type == b2_prismaticJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2PrismaticJoint* joint = &base->prismaticJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + // current anchors + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 d = b2Add( b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), joint->deltaCenter ), b2Sub( rB, rA ) ); + b2Vec2 axisA = b2RotateVector( stateA->deltaRotation, joint->axisA ); + float translation = b2Dot( axisA, d ); + + // These scalars are for torques generated by axial forces + float a1 = b2Cross( b2Add( d, rA ), axisA ); + float a2 = b2Cross( rB, axisA ); + + // spring constraint + if ( joint->enableSpring ) + { + // This is a real spring and should be applied even during relax + float C = translation; + float bias = joint->springSoftness.biasRate * C; + float massScale = joint->springSoftness.massScale; + float impulseScale = joint->springSoftness.impulseScale; + + float Cdot = b2Dot( axisA, b2Sub( vB, vA ) ) + a2 * wB - a1 * wA; + float deltaImpulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->springImpulse; + joint->springImpulse += deltaImpulse; + + b2Vec2 P = b2MulSV( deltaImpulse, axisA ); + float LA = deltaImpulse * a1; + float LB = deltaImpulse * a2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + // Solve motor constraint + if ( joint->enableMotor ) + { + float Cdot = b2Dot( axisA, b2Sub( vB, vA ) ) + a2 * wB - a1 * wA; + float impulse = joint->axialMass * ( joint->motorSpeed - Cdot ); + float oldImpulse = joint->motorImpulse; + float maxImpulse = context->h * joint->maxMotorForce; + joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse ); + impulse = joint->motorImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + if ( joint->enableLimit ) + { + // Lower limit + { + float C = translation - joint->lowerTranslation; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float oldImpulse = joint->lowerImpulse; + float Cdot = b2Dot( axisA, b2Sub( vB, vA ) ) + a2 * wB - a1 * wA; + float impulse = -joint->axialMass * massScale * ( Cdot + bias ) - impulseScale * oldImpulse; + joint->lowerImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->lowerImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + // Upper limit + // Note: signs are flipped to keep C positive when the constraint is satisfied. + // This also keeps the impulse positive when the limit is active. + { + // sign flipped + float C = joint->upperTranslation - translation; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float oldImpulse = joint->upperImpulse; + // sign flipped + float Cdot = b2Dot( axisA, b2Sub( vA, vB ) ) + a1 * wA - a2 * wB; + float impulse = -joint->axialMass * massScale * ( Cdot + bias ) - impulseScale * oldImpulse; + joint->upperImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->upperImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + // sign flipped + vA = b2MulAdd( vA, mA, P ); + wA += iA * LA; + vB = b2MulSub( vB, mB, P ); + wB -= iB * LB; + } + } + + // Solve the prismatic constraint in block form + { + b2Vec2 perpA = b2LeftPerp( axisA ); + + // These scalars are for torques generated by the perpendicular constraint force + float s1 = b2Cross( b2Add( d, rA ), perpA ); + float s2 = b2Cross( rB, perpA ); + + b2Vec2 Cdot; + Cdot.x = b2Dot( perpA, b2Sub( vB, vA ) ) + s2 * wB - s1 * wA; + Cdot.y = wB - wA; + + b2Vec2 bias = b2Vec2_zero; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias ) + { + b2Vec2 C; + C.x = b2Dot( perpA, d ); + C.y = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle; + + bias = b2MulSV( context->jointSoftness.biasRate, C ); + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float k11 = mA + mB + iA * s1 * s1 + iB * s2 * s2; + float k12 = iA * s1 + iB * s2; + float k22 = iA + iB; + if ( k22 == 0.0f ) + { + // For bodies with fixed rotation. + k22 = 1.0f; + } + + b2Mat22 K = { { k11, k12 }, { k12, k22 } }; + + b2Vec2 b = b2Solve22( K, b2Add( Cdot, bias ) ); + b2Vec2 impulse; + impulse.x = -massScale * b.x - impulseScale * joint->impulse.x; + impulse.y = -massScale * b.y - impulseScale * joint->impulse.y; + + joint->impulse.x += impulse.x; + joint->impulse.y += impulse.y; + + b2Vec2 P = b2MulSV( impulse.x, perpA ); + float LA = impulse.x * s1 + impulse.y; + float LB = impulse.x * s2 + impulse.y; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +#if 0 +void b2PrismaticJoint::Dump() +{ + int32 indexA = joint->bodyA->joint->islandIndex; + int32 indexB = joint->bodyB->joint->islandIndex; + + b2Dump(" b2PrismaticJointDef jd;\n"); + b2Dump(" jd.bodyA = sims[%d];\n", indexA); + b2Dump(" jd.bodyB = sims[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", joint->collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", joint->localAnchorA.x, joint->localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", joint->localAnchorB.x, joint->localAnchorB.y); + b2Dump(" jd.referenceAngle = %.9g;\n", joint->referenceAngle); + b2Dump(" jd.enableLimit = bool(%d);\n", joint->enableLimit); + b2Dump(" jd.lowerAngle = %.9g;\n", joint->lowerAngle); + b2Dump(" jd.upperAngle = %.9g;\n", joint->upperAngle); + b2Dump(" jd.enableMotor = bool(%d);\n", joint->enableMotor); + b2Dump(" jd.motorSpeed = %.9g;\n", joint->motorSpeed); + b2Dump(" jd.maxMotorTorque = %.9g;\n", joint->maxMotorTorque); + b2Dump(" joints[%d] = joint->world->CreateJoint(&jd);\n", joint->index); +} +#endif + +void b2DrawPrismaticJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ) +{ + B2_ASSERT( base->type == b2_prismaticJoint ); + + b2PrismaticJoint* joint = &base->prismaticJoint; + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + + b2Vec2 axis = b2RotateVector( transformA.q, joint->localAxisA ); + + b2HexColor c1 = b2_colorGray; + b2HexColor c2 = b2_colorGreen; + b2HexColor c3 = b2_colorRed; + b2HexColor c4 = b2_colorBlue; + b2HexColor c5 = b2_colorDimGray; + + draw->DrawSegmentFcn( pA, pB, c5, draw->context ); + + if ( joint->enableLimit ) + { + b2Vec2 lower = b2MulAdd( pA, joint->lowerTranslation, axis ); + b2Vec2 upper = b2MulAdd( pA, joint->upperTranslation, axis ); + b2Vec2 perp = b2LeftPerp( axis ); + draw->DrawSegmentFcn( lower, upper, c1, draw->context ); + draw->DrawSegmentFcn( b2MulSub( lower, 0.1f, perp ), b2MulAdd( lower, 0.1f, perp ), c2, draw->context ); + draw->DrawSegmentFcn( b2MulSub( upper, 0.1f, perp ), b2MulAdd( upper, 0.1f, perp ), c3, draw->context ); + } + else + { + draw->DrawSegmentFcn( b2MulSub( pA, 1.0f, axis ), b2MulAdd( pA, 1.0f, axis ), c1, draw->context ); + } + + draw->DrawPointFcn( pA, 5.0f, c1, draw->context ); + draw->DrawPointFcn( pB, 5.0f, c4, draw->context ); +} diff --git a/3rdparty/box2d/src/revolute_joint.c b/3rdparty/box2d/src/revolute_joint.c new file mode 100644 index 000000000000..ace148e6638a --- /dev/null +++ b/3rdparty/box2d/src/revolute_joint.c @@ -0,0 +1,534 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include + +void b2RevoluteJoint_EnableSpring( b2JointId jointId, bool enableSpring ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + if ( enableSpring != joint->revoluteJoint.enableSpring ) + { + joint->revoluteJoint.enableSpring = enableSpring; + joint->revoluteJoint.springImpulse = 0.0f; + } +} + +bool b2RevoluteJoint_IsSpringEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.enableSpring; +} + +void b2RevoluteJoint_SetSpringHertz( b2JointId jointId, float hertz ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + joint->revoluteJoint.hertz = hertz; +} + +float b2RevoluteJoint_GetSpringHertz( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.hertz; +} + +void b2RevoluteJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + joint->revoluteJoint.dampingRatio = dampingRatio; +} + +float b2RevoluteJoint_GetSpringDampingRatio( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.dampingRatio; +} + +float b2RevoluteJoint_GetAngle( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* jointSim = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + b2Transform transformA = b2GetBodyTransform( world, jointSim->bodyIdA ); + b2Transform transformB = b2GetBodyTransform( world, jointSim->bodyIdB ); + + float angle = b2RelativeAngle( transformB.q, transformA.q ) - jointSim->revoluteJoint.referenceAngle; + angle = b2UnwindAngle( angle ); + return angle; +} + +void b2RevoluteJoint_EnableLimit( b2JointId jointId, bool enableLimit ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + if ( enableLimit != joint->revoluteJoint.enableLimit ) + { + joint->revoluteJoint.enableLimit = enableLimit; + joint->revoluteJoint.lowerImpulse = 0.0f; + joint->revoluteJoint.upperImpulse = 0.0f; + } +} + +bool b2RevoluteJoint_IsLimitEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.enableLimit; +} + +float b2RevoluteJoint_GetLowerLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.lowerAngle; +} + +float b2RevoluteJoint_GetUpperLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.upperAngle; +} + +void b2RevoluteJoint_SetLimits( b2JointId jointId, float lower, float upper ) +{ + B2_ASSERT( lower <= upper ); + B2_ASSERT( lower >= -0.95f * B2_PI ); + B2_ASSERT( upper <= 0.95f * B2_PI ); + + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + if ( lower != joint->revoluteJoint.lowerAngle || upper != joint->revoluteJoint.upperAngle ) + { + joint->revoluteJoint.lowerAngle = b2MinFloat( lower, upper ); + joint->revoluteJoint.upperAngle = b2MaxFloat( lower, upper ); + joint->revoluteJoint.lowerImpulse = 0.0f; + joint->revoluteJoint.upperImpulse = 0.0f; + } +} + +void b2RevoluteJoint_EnableMotor( b2JointId jointId, bool enableMotor ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + if ( enableMotor != joint->revoluteJoint.enableMotor ) + { + joint->revoluteJoint.enableMotor = enableMotor; + joint->revoluteJoint.motorImpulse = 0.0f; + } +} + +bool b2RevoluteJoint_IsMotorEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.enableMotor; +} + +void b2RevoluteJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + joint->revoluteJoint.motorSpeed = motorSpeed; +} + +float b2RevoluteJoint_GetMotorSpeed( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.motorSpeed; +} + +float b2RevoluteJoint_GetMotorTorque( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return world->inv_h * joint->revoluteJoint.motorImpulse; +} + +void b2RevoluteJoint_SetMaxMotorTorque( b2JointId jointId, float torque ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + joint->revoluteJoint.maxMotorTorque = torque; +} + +float b2RevoluteJoint_GetMaxMotorTorque( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_revoluteJoint ); + return joint->revoluteJoint.maxMotorTorque; +} + +b2Vec2 b2GetRevoluteJointForce( b2World* world, b2JointSim* base ) +{ + b2Vec2 force = b2MulSV( world->inv_h, base->revoluteJoint.linearImpulse ); + return force; +} + +float b2GetRevoluteJointTorque( b2World* world, b2JointSim* base ) +{ + const b2RevoluteJoint* revolute = &base->revoluteJoint; + float torque = world->inv_h * ( revolute->motorImpulse + revolute->lowerImpulse - revolute->upperImpulse ); + return torque; +} + +// Point-to-point constraint +// C = p2 - p1 +// Cdot = v2 - v1 +// = v2 + cross(w2, r2) - v1 - cross(w1, r1) +// J = [-I -r1_skew I r2_skew ] +// Identity used: +// w k % (rx i + ry j) = w * (-ry i + rx j) + +// Motor constraint +// Cdot = w2 - w1 +// J = [0 0 -1 0 0 1] +// K = invI1 + invI2 + +void b2PrepareRevoluteJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_revoluteJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2RevoluteJoint* joint = &base->revoluteJoint; + + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + // initial anchors in world space + joint->anchorA = b2RotateVector( bodySimA->transform.q, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( bodySimB->transform.q, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center ); + joint->deltaAngle = b2RelativeAngle( bodySimB->transform.q, bodySimA->transform.q ) - joint->referenceAngle; + joint->deltaAngle = b2UnwindAngle( joint->deltaAngle ); + + float k = iA + iB; + joint->axialMass = k > 0.0f ? 1.0f / k : 0.0f; + + joint->springSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h ); + + if ( context->enableWarmStarting == false ) + { + joint->linearImpulse = b2Vec2_zero; + joint->springImpulse = 0.0f; + joint->motorImpulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; + } +} + +void b2WarmStartRevoluteJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_revoluteJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2RevoluteJoint* joint = &base->revoluteJoint; + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + float axialImpulse = joint->springImpulse + joint->motorImpulse + joint->lowerImpulse - joint->upperImpulse; + + stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, joint->linearImpulse ); + stateA->angularVelocity -= iA * ( b2Cross( rA, joint->linearImpulse ) + axialImpulse ); + + stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, joint->linearImpulse ); + stateB->angularVelocity += iB * ( b2Cross( rB, joint->linearImpulse ) + axialImpulse ); +} + +void b2SolveRevoluteJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_ASSERT( base->type == b2_revoluteJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2RevoluteJoint* joint = &base->revoluteJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + bool fixedRotation = ( iA + iB == 0.0f ); + // const float maxBias = context->maxBiasVelocity; + + // Solve spring. + if ( joint->enableSpring && fixedRotation == false ) + { + float C = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle; + float bias = joint->springSoftness.biasRate * C; + float massScale = joint->springSoftness.massScale; + float impulseScale = joint->springSoftness.impulseScale; + + float Cdot = wB - wA; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->springImpulse; + joint->springImpulse += impulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + // Solve motor constraint. + if ( joint->enableMotor && fixedRotation == false ) + { + float Cdot = wB - wA - joint->motorSpeed; + float impulse = -joint->axialMass * Cdot; + float oldImpulse = joint->motorImpulse; + float maxImpulse = context->h * joint->maxMotorTorque; + joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse ); + impulse = joint->motorImpulse - oldImpulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + if ( joint->enableLimit && fixedRotation == false ) + { + float jointAngle = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle; + jointAngle = b2UnwindAngle( jointAngle ); + + // Lower limit + { + float C = jointAngle - joint->lowerAngle; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float Cdot = wB - wA; + float oldImpulse = joint->lowerImpulse; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * oldImpulse; + joint->lowerImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->lowerImpulse - oldImpulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + // Upper limit + // Note: signs are flipped to keep C positive when the constraint is satisfied. + // This also keeps the impulse positive when the limit is active. + { + float C = joint->upperAngle - jointAngle; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + // sign flipped on Cdot + float Cdot = wA - wB; + float oldImpulse = joint->upperImpulse; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * oldImpulse; + joint->upperImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->upperImpulse - oldImpulse; + + // sign flipped on applied impulse + wA += iA * impulse; + wB -= iB * impulse; + } + } + + // Solve point-to-point constraint + { + // J = [-I -r1_skew I r2_skew] + // r_skew = [-ry; rx] + // K = [ mA+r1y^2*iA+mB+r2y^2*iB, -r1y*iA*r1x-r2y*iB*r2x] + // [ -r1y*iA*r1x-r2y*iB*r2x, mA+r1x^2*iA+mB+r2x^2*iB] + + // current anchors + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 Cdot = b2Sub( b2Add( vB, b2CrossSV( wB, rB ) ), b2Add( vA, b2CrossSV( wA, rA ) ) ); + + b2Vec2 bias = b2Vec2_zero; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias ) + { + b2Vec2 dcA = stateA->deltaPosition; + b2Vec2 dcB = stateB->deltaPosition; + + b2Vec2 separation = b2Add( b2Add( b2Sub( dcB, dcA ), b2Sub( rB, rA ) ), joint->deltaCenter ); + bias = b2MulSV( context->jointSoftness.biasRate, separation ); + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + b2Mat22 K; + K.cx.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; + K.cy.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; + K.cx.y = K.cy.x; + K.cy.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; + b2Vec2 b = b2Solve22( K, b2Add( Cdot, bias ) ); + + b2Vec2 impulse; + impulse.x = -massScale * b.x - impulseScale * joint->linearImpulse.x; + impulse.y = -massScale * b.y - impulseScale * joint->linearImpulse.y; + joint->linearImpulse.x += impulse.x; + joint->linearImpulse.y += impulse.y; + + vA = b2MulSub( vA, mA, impulse ); + wA -= iA * b2Cross( rA, impulse ); + vB = b2MulAdd( vB, mB, impulse ); + wB += iB * b2Cross( rB, impulse ); + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +#if 0 +void b2RevoluteJoint::Dump() +{ + int32 indexA = joint->bodyA->joint->islandIndex; + int32 indexB = joint->bodyB->joint->islandIndex; + + b2Dump(" b2RevoluteJointDef jd;\n"); + b2Dump(" jd.bodyA = bodies[%d];\n", indexA); + b2Dump(" jd.bodyB = bodies[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", joint->collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", joint->localAnchorA.x, joint->localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", joint->localAnchorB.x, joint->localAnchorB.y); + b2Dump(" jd.referenceAngle = %.9g;\n", joint->referenceAngle); + b2Dump(" jd.enableLimit = bool(%d);\n", joint->enableLimit); + b2Dump(" jd.lowerAngle = %.9g;\n", joint->lowerAngle); + b2Dump(" jd.upperAngle = %.9g;\n", joint->upperAngle); + b2Dump(" jd.enableMotor = bool(%d);\n", joint->enableMotor); + b2Dump(" jd.motorSpeed = %.9g;\n", joint->motorSpeed); + b2Dump(" jd.maxMotorTorque = %.9g;\n", joint->maxMotorTorque); + b2Dump(" joints[%d] = joint->world->CreateJoint(&jd);\n", joint->index); +} +#endif + +void b2DrawRevoluteJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB, float drawSize ) +{ + B2_ASSERT( base->type == b2_revoluteJoint ); + + b2RevoluteJoint* joint = &base->revoluteJoint; + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + + b2HexColor c1 = b2_colorGray; + b2HexColor c2 = b2_colorGreen; + b2HexColor c3 = b2_colorRed; + + const float L = drawSize; + // draw->drawPoint(pA, 3.0f, b2_colorGray40, draw->context); + // draw->drawPoint(pB, 3.0f, b2_colorLightBlue, draw->context); + draw->DrawCircleFcn( pB, L, c1, draw->context ); + + float angle = b2RelativeAngle( transformB.q, transformA.q ); + + b2Rot rot = b2MakeRot( angle ); + b2Vec2 r = { L * rot.c, L * rot.s }; + b2Vec2 pC = b2Add( pB, r ); + draw->DrawSegmentFcn( pB, pC, c1, draw->context ); + + if ( draw->drawJointExtras ) + { + float jointAngle = b2UnwindAngle( angle - joint->referenceAngle ); + char buffer[32]; + snprintf( buffer, 32, " %.1f deg", 180.0f * jointAngle / B2_PI ); + draw->DrawStringFcn( pC, buffer, b2_colorWhite, draw->context ); + } + + float lowerAngle = joint->lowerAngle + joint->referenceAngle; + float upperAngle = joint->upperAngle + joint->referenceAngle; + + if ( joint->enableLimit ) + { + b2Rot rotLo = b2MakeRot( lowerAngle ); + b2Vec2 rlo = { L * rotLo.c, L * rotLo.s }; + + b2Rot rotHi = b2MakeRot( upperAngle ); + b2Vec2 rhi = { L * rotHi.c, L * rotHi.s }; + + draw->DrawSegmentFcn( pB, b2Add( pB, rlo ), c2, draw->context ); + draw->DrawSegmentFcn( pB, b2Add( pB, rhi ), c3, draw->context ); + + b2Rot rotRef = b2MakeRot( joint->referenceAngle ); + b2Vec2 ref = (b2Vec2){ L * rotRef.c, L * rotRef.s }; + draw->DrawSegmentFcn( pB, b2Add( pB, ref ), b2_colorBlue, draw->context ); + } + + b2HexColor color = b2_colorGold; + draw->DrawSegmentFcn( transformA.p, pA, color, draw->context ); + draw->DrawSegmentFcn( pA, pB, color, draw->context ); + draw->DrawSegmentFcn( transformB.p, pB, color, draw->context ); + + // char buffer[32]; + // sprintf(buffer, "%.1f", b2Length(joint->impulse)); + // draw->DrawString(pA, buffer, draw->context); +} diff --git a/3rdparty/box2d/src/rope/b2_rope.cpp b/3rdparty/box2d/src/rope/b2_rope.cpp deleted file mode 100644 index 71fbe79ee9f7..000000000000 --- a/3rdparty/box2d/src/rope/b2_rope.cpp +++ /dev/null @@ -1,809 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "box2d/b2_draw.h" -#include "box2d/b2_rope.h" - -#include - -struct b2RopeStretch -{ - int32 i1, i2; - float invMass1, invMass2; - float L; - float lambda; - float spring; - float damper; -}; - -struct b2RopeBend -{ - int32 i1, i2, i3; - float invMass1, invMass2, invMass3; - float invEffectiveMass; - float lambda; - float L1, L2; - float alpha1, alpha2; - float spring; - float damper; -}; - -b2Rope::b2Rope() -{ - m_position.SetZero(); - m_count = 0; - m_stretchCount = 0; - m_bendCount = 0; - m_stretchConstraints = nullptr; - m_bendConstraints = nullptr; - m_bindPositions = nullptr; - m_ps = nullptr; - m_p0s = nullptr; - m_vs = nullptr; - m_invMasses = nullptr; - m_gravity.SetZero(); -} - -b2Rope::~b2Rope() -{ - b2Free(m_stretchConstraints); - b2Free(m_bendConstraints); - b2Free(m_bindPositions); - b2Free(m_ps); - b2Free(m_p0s); - b2Free(m_vs); - b2Free(m_invMasses); -} - -void b2Rope::Create(const b2RopeDef& def) -{ - b2Assert(def.count >= 3); - m_position = def.position; - m_count = def.count; - m_bindPositions = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); - m_ps = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); - m_p0s = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); - m_vs = (b2Vec2*)b2Alloc(m_count * sizeof(b2Vec2)); - m_invMasses = (float*)b2Alloc(m_count * sizeof(float)); - - for (int32 i = 0; i < m_count; ++i) - { - m_bindPositions[i] = def.vertices[i]; - m_ps[i] = def.vertices[i] + m_position; - m_p0s[i] = def.vertices[i] + m_position; - m_vs[i].SetZero(); - - float m = def.masses[i]; - if (m > 0.0f) - { - m_invMasses[i] = 1.0f / m; - } - else - { - m_invMasses[i] = 0.0f; - } - } - - m_stretchCount = m_count - 1; - m_bendCount = m_count - 2; - - m_stretchConstraints = (b2RopeStretch*)b2Alloc(m_stretchCount * sizeof(b2RopeStretch)); - m_bendConstraints = (b2RopeBend*)b2Alloc(m_bendCount * sizeof(b2RopeBend)); - - for (int32 i = 0; i < m_stretchCount; ++i) - { - b2RopeStretch& c = m_stretchConstraints[i]; - - b2Vec2 p1 = m_ps[i]; - b2Vec2 p2 = m_ps[i+1]; - - c.i1 = i; - c.i2 = i + 1; - c.L = b2Distance(p1, p2); - c.invMass1 = m_invMasses[i]; - c.invMass2 = m_invMasses[i + 1]; - c.lambda = 0.0f; - c.damper = 0.0f; - c.spring = 0.0f; - } - - for (int32 i = 0; i < m_bendCount; ++i) - { - b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 p1 = m_ps[i]; - b2Vec2 p2 = m_ps[i + 1]; - b2Vec2 p3 = m_ps[i + 2]; - - c.i1 = i; - c.i2 = i + 1; - c.i3 = i + 2; - c.invMass1 = m_invMasses[i]; - c.invMass2 = m_invMasses[i + 1]; - c.invMass3 = m_invMasses[i + 2]; - c.invEffectiveMass = 0.0f; - c.L1 = b2Distance(p1, p2); - c.L2 = b2Distance(p2, p3); - c.lambda = 0.0f; - - // Pre-compute effective mass (TODO use flattened config) - b2Vec2 e1 = p2 - p1; - b2Vec2 e2 = p3 - p2; - float L1sqr = e1.LengthSquared(); - float L2sqr = e2.LengthSquared(); - - if (L1sqr * L2sqr == 0.0f) - { - continue; - } - - b2Vec2 Jd1 = (-1.0f / L1sqr) * e1.Skew(); - b2Vec2 Jd2 = (1.0f / L2sqr) * e2.Skew(); - - b2Vec2 J1 = -Jd1; - b2Vec2 J2 = Jd1 - Jd2; - b2Vec2 J3 = Jd2; - - c.invEffectiveMass = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3); - - b2Vec2 r = p3 - p1; - - float rr = r.LengthSquared(); - if (rr == 0.0f) - { - continue; - } - - // a1 = h2 / (h1 + h2) - // a2 = h1 / (h1 + h2) - c.alpha1 = b2Dot(e2, r) / rr; - c.alpha2 = b2Dot(e1, r) / rr; - } - - m_gravity = def.gravity; - - SetTuning(def.tuning); -} - -void b2Rope::SetTuning(const b2RopeTuning& tuning) -{ - m_tuning = tuning; - - // Pre-compute spring and damper values based on tuning - - const float bendOmega = 2.0f * b2_pi * m_tuning.bendHertz; - - for (int32 i = 0; i < m_bendCount; ++i) - { - b2RopeBend& c = m_bendConstraints[i]; - - float L1sqr = c.L1 * c.L1; - float L2sqr = c.L2 * c.L2; - - if (L1sqr * L2sqr == 0.0f) - { - c.spring = 0.0f; - c.damper = 0.0f; - continue; - } - - // Flatten the triangle formed by the two edges - float J2 = 1.0f / c.L1 + 1.0f / c.L2; - float sum = c.invMass1 / L1sqr + c.invMass2 * J2 * J2 + c.invMass3 / L2sqr; - if (sum == 0.0f) - { - c.spring = 0.0f; - c.damper = 0.0f; - continue; - } - - float mass = 1.0f / sum; - - c.spring = mass * bendOmega * bendOmega; - c.damper = 2.0f * mass * m_tuning.bendDamping * bendOmega; - } - - const float stretchOmega = 2.0f * b2_pi * m_tuning.stretchHertz; - - for (int32 i = 0; i < m_stretchCount; ++i) - { - b2RopeStretch& c = m_stretchConstraints[i]; - - float sum = c.invMass1 + c.invMass2; - if (sum == 0.0f) - { - continue; - } - - float mass = 1.0f / sum; - - c.spring = mass * stretchOmega * stretchOmega; - c.damper = 2.0f * mass * m_tuning.stretchDamping * stretchOmega; - } -} - -void b2Rope::Step(float dt, int32 iterations, const b2Vec2& position) -{ - if (dt == 0.0f) - { - return; - } - - const float inv_dt = 1.0f / dt; - float d = expf(- dt * m_tuning.damping); - - // Apply gravity and damping - for (int32 i = 0; i < m_count; ++i) - { - if (m_invMasses[i] > 0.0f) - { - m_vs[i] *= d; - m_vs[i] += dt * m_gravity; - } - else - { - m_vs[i] = inv_dt * (m_bindPositions[i] + position - m_p0s[i]); - } - } - - // Apply bending spring - if (m_tuning.bendingModel == b2_springAngleBendingModel) - { - ApplyBendForces(dt); - } - - for (int32 i = 0; i < m_bendCount; ++i) - { - m_bendConstraints[i].lambda = 0.0f; - } - - for (int32 i = 0; i < m_stretchCount; ++i) - { - m_stretchConstraints[i].lambda = 0.0f; - } - - // Update position - for (int32 i = 0; i < m_count; ++i) - { - m_ps[i] += dt * m_vs[i]; - } - - // Solve constraints - for (int32 i = 0; i < iterations; ++i) - { - if (m_tuning.bendingModel == b2_pbdAngleBendingModel) - { - SolveBend_PBD_Angle(); - } - else if (m_tuning.bendingModel == b2_xpbdAngleBendingModel) - { - SolveBend_XPBD_Angle(dt); - } - else if (m_tuning.bendingModel == b2_pbdDistanceBendingModel) - { - SolveBend_PBD_Distance(); - } - else if (m_tuning.bendingModel == b2_pbdHeightBendingModel) - { - SolveBend_PBD_Height(); - } - else if (m_tuning.bendingModel == b2_pbdTriangleBendingModel) - { - SolveBend_PBD_Triangle(); - } - - if (m_tuning.stretchingModel == b2_pbdStretchingModel) - { - SolveStretch_PBD(); - } - else if (m_tuning.stretchingModel == b2_xpbdStretchingModel) - { - SolveStretch_XPBD(dt); - } - } - - // Constrain velocity - for (int32 i = 0; i < m_count; ++i) - { - m_vs[i] = inv_dt * (m_ps[i] - m_p0s[i]); - m_p0s[i] = m_ps[i]; - } -} - -void b2Rope::Reset(const b2Vec2& position) -{ - m_position = position; - - for (int32 i = 0; i < m_count; ++i) - { - m_ps[i] = m_bindPositions[i] + m_position; - m_p0s[i] = m_bindPositions[i] + m_position; - m_vs[i].SetZero(); - } - - for (int32 i = 0; i < m_bendCount; ++i) - { - m_bendConstraints[i].lambda = 0.0f; - } - - for (int32 i = 0; i < m_stretchCount; ++i) - { - m_stretchConstraints[i].lambda = 0.0f; - } -} - -void b2Rope::SolveStretch_PBD() -{ - const float stiffness = m_tuning.stretchStiffness; - - for (int32 i = 0; i < m_stretchCount; ++i) - { - const b2RopeStretch& c = m_stretchConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - - b2Vec2 d = p2 - p1; - float L = d.Normalize(); - - float sum = c.invMass1 + c.invMass2; - if (sum == 0.0f) - { - continue; - } - - float s1 = c.invMass1 / sum; - float s2 = c.invMass2 / sum; - - p1 -= stiffness * s1 * (c.L - L) * d; - p2 += stiffness * s2 * (c.L - L) * d; - - m_ps[c.i1] = p1; - m_ps[c.i2] = p2; - } -} - -void b2Rope::SolveStretch_XPBD(float dt) -{ - b2Assert(dt > 0.0f); - - for (int32 i = 0; i < m_stretchCount; ++i) - { - b2RopeStretch& c = m_stretchConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - - b2Vec2 dp1 = p1 - m_p0s[c.i1]; - b2Vec2 dp2 = p2 - m_p0s[c.i2]; - - b2Vec2 u = p2 - p1; - float L = u.Normalize(); - - b2Vec2 J1 = -u; - b2Vec2 J2 = u; - - float sum = c.invMass1 + c.invMass2; - if (sum == 0.0f) - { - continue; - } - - const float alpha = 1.0f / (c.spring * dt * dt); // 1 / kg - const float beta = dt * dt * c.damper; // kg * s - const float sigma = alpha * beta / dt; // non-dimensional - float C = L - c.L; - - // This is using the initial velocities - float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2); - - float B = C + alpha * c.lambda + sigma * Cdot; - float sum2 = (1.0f + sigma) * sum + alpha; - - float impulse = -B / sum2; - - p1 += (c.invMass1 * impulse) * J1; - p2 += (c.invMass2 * impulse) * J2; - - m_ps[c.i1] = p1; - m_ps[c.i2] = p2; - c.lambda += impulse; - } -} - -void b2Rope::SolveBend_PBD_Angle() -{ - const float stiffness = m_tuning.bendStiffness; - - for (int32 i = 0; i < m_bendCount; ++i) - { - const b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - b2Vec2 p3 = m_ps[c.i3]; - - b2Vec2 d1 = p2 - p1; - b2Vec2 d2 = p3 - p2; - float a = b2Cross(d1, d2); - float b = b2Dot(d1, d2); - - float angle = b2Atan2(a, b); - - float L1sqr, L2sqr; - - if (m_tuning.isometric) - { - L1sqr = c.L1 * c.L1; - L2sqr = c.L2 * c.L2; - } - else - { - L1sqr = d1.LengthSquared(); - L2sqr = d2.LengthSquared(); - } - - if (L1sqr * L2sqr == 0.0f) - { - continue; - } - - b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew(); - b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew(); - - b2Vec2 J1 = -Jd1; - b2Vec2 J2 = Jd1 - Jd2; - b2Vec2 J3 = Jd2; - - float sum; - if (m_tuning.fixedEffectiveMass) - { - sum = c.invEffectiveMass; - } - else - { - sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3); - } - - if (sum == 0.0f) - { - sum = c.invEffectiveMass; - } - - float impulse = -stiffness * angle / sum; - - p1 += (c.invMass1 * impulse) * J1; - p2 += (c.invMass2 * impulse) * J2; - p3 += (c.invMass3 * impulse) * J3; - - m_ps[c.i1] = p1; - m_ps[c.i2] = p2; - m_ps[c.i3] = p3; - } -} - -void b2Rope::SolveBend_XPBD_Angle(float dt) -{ - b2Assert(dt > 0.0f); - - for (int32 i = 0; i < m_bendCount; ++i) - { - b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - b2Vec2 p3 = m_ps[c.i3]; - - b2Vec2 dp1 = p1 - m_p0s[c.i1]; - b2Vec2 dp2 = p2 - m_p0s[c.i2]; - b2Vec2 dp3 = p3 - m_p0s[c.i3]; - - b2Vec2 d1 = p2 - p1; - b2Vec2 d2 = p3 - p2; - - float L1sqr, L2sqr; - - if (m_tuning.isometric) - { - L1sqr = c.L1 * c.L1; - L2sqr = c.L2 * c.L2; - } - else - { - L1sqr = d1.LengthSquared(); - L2sqr = d2.LengthSquared(); - } - - if (L1sqr * L2sqr == 0.0f) - { - continue; - } - - float a = b2Cross(d1, d2); - float b = b2Dot(d1, d2); - - float angle = b2Atan2(a, b); - - b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew(); - b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew(); - - b2Vec2 J1 = -Jd1; - b2Vec2 J2 = Jd1 - Jd2; - b2Vec2 J3 = Jd2; - - float sum; - if (m_tuning.fixedEffectiveMass) - { - sum = c.invEffectiveMass; - } - else - { - sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3); - } - - if (sum == 0.0f) - { - continue; - } - - const float alpha = 1.0f / (c.spring * dt * dt); - const float beta = dt * dt * c.damper; - const float sigma = alpha * beta / dt; - float C = angle; - - // This is using the initial velocities - float Cdot = b2Dot(J1, dp1) + b2Dot(J2, dp2) + b2Dot(J3, dp3); - - float B = C + alpha * c.lambda + sigma * Cdot; - float sum2 = (1.0f + sigma) * sum + alpha; - - float impulse = -B / sum2; - - p1 += (c.invMass1 * impulse) * J1; - p2 += (c.invMass2 * impulse) * J2; - p3 += (c.invMass3 * impulse) * J3; - - m_ps[c.i1] = p1; - m_ps[c.i2] = p2; - m_ps[c.i3] = p3; - c.lambda += impulse; - } -} - -void b2Rope::ApplyBendForces(float dt) -{ - // omega = 2 * pi * hz - const float omega = 2.0f * b2_pi * m_tuning.bendHertz; - - for (int32 i = 0; i < m_bendCount; ++i) - { - const b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - b2Vec2 p3 = m_ps[c.i3]; - - b2Vec2 v1 = m_vs[c.i1]; - b2Vec2 v2 = m_vs[c.i2]; - b2Vec2 v3 = m_vs[c.i3]; - - b2Vec2 d1 = p2 - p1; - b2Vec2 d2 = p3 - p2; - - float L1sqr, L2sqr; - - if (m_tuning.isometric) - { - L1sqr = c.L1 * c.L1; - L2sqr = c.L2 * c.L2; - } - else - { - L1sqr = d1.LengthSquared(); - L2sqr = d2.LengthSquared(); - } - - if (L1sqr * L2sqr == 0.0f) - { - continue; - } - - float a = b2Cross(d1, d2); - float b = b2Dot(d1, d2); - - float angle = b2Atan2(a, b); - - b2Vec2 Jd1 = (-1.0f / L1sqr) * d1.Skew(); - b2Vec2 Jd2 = (1.0f / L2sqr) * d2.Skew(); - - b2Vec2 J1 = -Jd1; - b2Vec2 J2 = Jd1 - Jd2; - b2Vec2 J3 = Jd2; - - float sum; - if (m_tuning.fixedEffectiveMass) - { - sum = c.invEffectiveMass; - } - else - { - sum = c.invMass1 * b2Dot(J1, J1) + c.invMass2 * b2Dot(J2, J2) + c.invMass3 * b2Dot(J3, J3); - } - - if (sum == 0.0f) - { - continue; - } - - float mass = 1.0f / sum; - - const float spring = mass * omega * omega; - const float damper = 2.0f * mass * m_tuning.bendDamping * omega; - - float C = angle; - float Cdot = b2Dot(J1, v1) + b2Dot(J2, v2) + b2Dot(J3, v3); - - float impulse = -dt * (spring * C + damper * Cdot); - - m_vs[c.i1] += (c.invMass1 * impulse) * J1; - m_vs[c.i2] += (c.invMass2 * impulse) * J2; - m_vs[c.i3] += (c.invMass3 * impulse) * J3; - } -} - -void b2Rope::SolveBend_PBD_Distance() -{ - const float stiffness = m_tuning.bendStiffness; - - for (int32 i = 0; i < m_bendCount; ++i) - { - const b2RopeBend& c = m_bendConstraints[i]; - - int32 i1 = c.i1; - int32 i2 = c.i3; - - b2Vec2 p1 = m_ps[i1]; - b2Vec2 p2 = m_ps[i2]; - - b2Vec2 d = p2 - p1; - float L = d.Normalize(); - - float sum = c.invMass1 + c.invMass3; - if (sum == 0.0f) - { - continue; - } - - float s1 = c.invMass1 / sum; - float s2 = c.invMass3 / sum; - - p1 -= stiffness * s1 * (c.L1 + c.L2 - L) * d; - p2 += stiffness * s2 * (c.L1 + c.L2 - L) * d; - - m_ps[i1] = p1; - m_ps[i2] = p2; - } -} - -// Constraint based implementation of: -// P. Volino: Simple Linear Bending Stiffness in Particle Systems -void b2Rope::SolveBend_PBD_Height() -{ - const float stiffness = m_tuning.bendStiffness; - - for (int32 i = 0; i < m_bendCount; ++i) - { - const b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 p1 = m_ps[c.i1]; - b2Vec2 p2 = m_ps[c.i2]; - b2Vec2 p3 = m_ps[c.i3]; - - // Barycentric coordinates are held constant - b2Vec2 d = c.alpha1 * p1 + c.alpha2 * p3 - p2; - float dLen = d.Length(); - - if (dLen == 0.0f) - { - continue; - } - - b2Vec2 dHat = (1.0f / dLen) * d; - - b2Vec2 J1 = c.alpha1 * dHat; - b2Vec2 J2 = -dHat; - b2Vec2 J3 = c.alpha2 * dHat; - - float sum = c.invMass1 * c.alpha1 * c.alpha1 + c.invMass2 + c.invMass3 * c.alpha2 * c.alpha2; - - if (sum == 0.0f) - { - continue; - } - - float C = dLen; - float mass = 1.0f / sum; - float impulse = -stiffness * mass * C; - - p1 += (c.invMass1 * impulse) * J1; - p2 += (c.invMass2 * impulse) * J2; - p3 += (c.invMass3 * impulse) * J3; - - m_ps[c.i1] = p1; - m_ps[c.i2] = p2; - m_ps[c.i3] = p3; - } -} - -// M. Kelager: A Triangle Bending Constraint Model for PBD -void b2Rope::SolveBend_PBD_Triangle() -{ - const float stiffness = m_tuning.bendStiffness; - - for (int32 i = 0; i < m_bendCount; ++i) - { - const b2RopeBend& c = m_bendConstraints[i]; - - b2Vec2 b0 = m_ps[c.i1]; - b2Vec2 v = m_ps[c.i2]; - b2Vec2 b1 = m_ps[c.i3]; - - float wb0 = c.invMass1; - float wv = c.invMass2; - float wb1 = c.invMass3; - - float W = wb0 + wb1 + 2.0f * wv; - float invW = stiffness / W; - - b2Vec2 d = v - (1.0f / 3.0f) * (b0 + v + b1); - - b2Vec2 db0 = 2.0f * wb0 * invW * d; - b2Vec2 dv = -4.0f * wv * invW * d; - b2Vec2 db1 = 2.0f * wb1 * invW * d; - - b0 += db0; - v += dv; - b1 += db1; - - m_ps[c.i1] = b0; - m_ps[c.i2] = v; - m_ps[c.i3] = b1; - } -} - -void b2Rope::Draw(b2Draw* draw) const -{ - b2Color c(0.4f, 0.5f, 0.7f); - b2Color pg(0.1f, 0.8f, 0.1f); - b2Color pd(0.7f, 0.2f, 0.4f); - - for (int32 i = 0; i < m_count - 1; ++i) - { - draw->DrawSegment(m_ps[i], m_ps[i+1], c); - - const b2Color& pc = m_invMasses[i] > 0.0f ? pd : pg; - draw->DrawPoint(m_ps[i], 5.0f, pc); - } - - const b2Color& pc = m_invMasses[m_count - 1] > 0.0f ? pd : pg; - draw->DrawPoint(m_ps[m_count - 1], 5.0f, pc); -} diff --git a/3rdparty/box2d/src/sensor.c b/3rdparty/box2d/src/sensor.c new file mode 100644 index 000000000000..3d203ed5ba2f --- /dev/null +++ b/3rdparty/box2d/src/sensor.c @@ -0,0 +1,389 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "sensor.h" + +#include "array.h" +#include "body.h" +#include "contact.h" +#include "ctz.h" +#include "shape.h" +#include "world.h" + +#include "box2d/collision.h" + +#include +#include + +B2_ARRAY_SOURCE( b2ShapeRef, b2ShapeRef ) +B2_ARRAY_SOURCE( b2Sensor, b2Sensor ) +B2_ARRAY_SOURCE( b2SensorTaskContext, b2SensorTaskContext ) + +struct b2SensorQueryContext +{ + b2World* world; + b2SensorTaskContext* taskContext; + b2Sensor* sensor; + b2Shape* sensorShape; + b2Transform transform; +}; + +// Sensor shapes need to +// - detect begin and end overlap events +// - events must be reported in deterministic order +// - maintain an active list of overlaps for query + +// Assumption +// - sensors don't detect shapes on the same body + +// Algorithm +// Query all sensors for overlaps +// Check against previous overlaps + +// Data structures +// Each sensor has an double buffered array of overlaps +// These overlaps use a shape reference with index and generation + +static bool b2SensorQueryCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + struct b2SensorQueryContext* queryContext = context; + b2Shape* sensorShape = queryContext->sensorShape; + int sensorShapeId = sensorShape->id; + + if ( shapeId == sensorShapeId ) + { + return true; + } + + b2World* world = queryContext->world; + b2Shape* otherShape = b2ShapeArray_Get( &world->shapes, shapeId ); + + // Are sensor events enabled on the other shape? + if ( otherShape->enableSensorEvents == false ) + { + return true; + } + + // Skip shapes on the same body + if ( otherShape->bodyId == sensorShape->bodyId ) + { + return true; + } + + // Check filter + if ( b2ShouldShapesCollide( sensorShape->filter, otherShape->filter ) == false ) + { + return true; + } + + b2Transform otherTransform = b2GetBodyTransform( world, otherShape->bodyId ); + + b2DistanceInput input; + input.proxyA = b2MakeShapeDistanceProxy( sensorShape ); + input.proxyB = b2MakeShapeDistanceProxy( otherShape ); + input.transformA = queryContext->transform; + input.transformB = otherTransform; + input.useRadii = true; + b2SimplexCache cache = { 0 }; + b2DistanceOutput output = b2ShapeDistance(&input, &cache, NULL, 0 ); + + bool overlaps = output.distance < 10.0f * FLT_EPSILON; + if ( overlaps == false ) + { + return true; + } + + // Record the overlap + b2Sensor* sensor = queryContext->sensor; + b2ShapeRef* shapeRef = b2ShapeRefArray_Add( &sensor->overlaps2 ); + shapeRef->shapeId = shapeId; + shapeRef->generation = otherShape->generation; + + return true; +} + +static int b2CompareShapeRefs( const void* a, const void* b ) +{ + const b2ShapeRef* sa = a; + const b2ShapeRef* sb = b; + + if ( sa->shapeId < sb->shapeId ) + { + return -1; + } + + if ( sa->shapeId == sb->shapeId ) + { + if ( sa->generation < sb->generation ) + { + return -1; + } + + if ( sa->generation == sb->generation ) + { + return 0; + } + } + + return 1; +} + +static void b2SensorTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + b2TracyCZoneNC( sensor_task, "Overlap", b2_colorBrown, true ); + + b2World* world = context; + B2_ASSERT( (int)threadIndex < world->workerCount ); + b2SensorTaskContext* taskContext = world->sensorTaskContexts.data + threadIndex; + + B2_ASSERT( startIndex < endIndex ); + + b2DynamicTree* trees = world->broadPhase.trees; + for ( int sensorIndex = startIndex; sensorIndex < endIndex; ++sensorIndex ) + { + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorIndex ); + b2Shape* sensorShape = b2ShapeArray_Get( &world->shapes, sensor->shapeId ); + + // swap overlap arrays + b2ShapeRefArray temp = sensor->overlaps1; + sensor->overlaps1 = sensor->overlaps2; + sensor->overlaps2 = temp; + b2ShapeRefArray_Clear( &sensor->overlaps2 ); + + b2Body* body = b2BodyArray_Get( &world->bodies, sensorShape->bodyId ); + if ( body->setIndex == b2_disabledSet || sensorShape->enableSensorEvents == false ) + { + if ( sensor->overlaps1.count != 0 ) + { + b2SetBit( &taskContext->eventBits, sensorIndex ); + } + continue; + } + + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + struct b2SensorQueryContext queryContext = { + .world = world, + .taskContext = taskContext, + .sensorShape = sensorShape, + .sensor = sensor, + .transform = transform, + }; + + B2_ASSERT( sensorShape->sensorIndex == sensorIndex ); + b2AABB queryBounds = sensorShape->aabb; + + // Query all trees + b2DynamicTree_Query( trees + 0, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext ); + b2DynamicTree_Query( trees + 1, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext ); + b2DynamicTree_Query( trees + 2, queryBounds, sensorShape->filter.maskBits, b2SensorQueryCallback, &queryContext ); + + // Sort the overlaps to enable finding begin and end events. + qsort( sensor->overlaps2.data, sensor->overlaps2.count, sizeof( b2ShapeRef ), b2CompareShapeRefs ); + + int count1 = sensor->overlaps1.count; + int count2 = sensor->overlaps2.count; + if ( count1 != count2 ) + { + // something changed + b2SetBit( &taskContext->eventBits, sensorIndex ); + } + else + { + for ( int i = 0; i < count1; ++i ) + { + b2ShapeRef* s1 = sensor->overlaps1.data + i; + b2ShapeRef* s2 = sensor->overlaps2.data + i; + + if ( s1->shapeId != s2->shapeId || s1->generation != s2->generation ) + { + // something changed + b2SetBit( &taskContext->eventBits, sensorIndex ); + break; + } + } + } + } + + b2TracyCZoneEnd( sensor_task ); +} + +void b2OverlapSensors( b2World* world ) +{ + int sensorCount = world->sensors.count; + if ( sensorCount == 0 ) + { + return; + } + + B2_ASSERT( world->workerCount > 0 ); + + b2TracyCZoneNC( overlap_sensors, "Sensors", b2_colorMediumPurple, true ); + + for ( int i = 0; i < world->workerCount; ++i ) + { + b2SetBitCountAndClear( &world->sensorTaskContexts.data[i].eventBits, sensorCount ); + } + + // Parallel-for sensors overlaps + int minRange = 16; + void* userSensorTask = world->enqueueTaskFcn( &b2SensorTask, sensorCount, minRange, world, world->userTaskContext ); + world->taskCount += 1; + if ( userSensorTask != NULL ) + { + world->finishTaskFcn( userSensorTask, world->userTaskContext ); + } + + b2TracyCZoneNC( sensor_state, "Events", b2_colorLightSlateGray, true ); + + b2BitSet* bitSet = &world->sensorTaskContexts.data[0].eventBits; + for ( int i = 1; i < world->workerCount; ++i ) + { + b2InPlaceUnion( bitSet, &world->sensorTaskContexts.data[i].eventBits ); + } + + // Iterate sensors bits and publish events + // Process contact state changes. Iterate over set bits + uint64_t* bits = bitSet->bits; + uint32_t blockCount = bitSet->blockCount; + + for ( uint32_t k = 0; k < blockCount; ++k ) + { + uint64_t word = bits[k]; + while ( word != 0 ) + { + uint32_t ctz = b2CTZ64( word ); + int sensorIndex = (int)( 64 * k + ctz ); + + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorIndex ); + b2Shape* sensorShape = b2ShapeArray_Get( &world->shapes, sensor->shapeId ); + b2ShapeId sensorId = { sensor->shapeId + 1, world->worldId, sensorShape->generation }; + + int count1 = sensor->overlaps1.count; + int count2 = sensor->overlaps2.count; + const b2ShapeRef* refs1 = sensor->overlaps1.data; + const b2ShapeRef* refs2 = sensor->overlaps2.data; + + // overlaps1 can have overlaps that end + // overlaps2 can have overlaps that begin + int index1 = 0, index2 = 0; + while ( index1 < count1 && index2 < count2 ) + { + const b2ShapeRef* r1 = refs1 + index1; + const b2ShapeRef* r2 = refs2 + index2; + if ( r1->shapeId == r2->shapeId ) + { + if ( r1->generation < r2->generation ) + { + // end + b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation }; + b2SensorEndTouchEvent event = { + .sensorShapeId = sensorId, + .visitorShapeId = visitorId, + }; + b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event ); + index1 += 1; + } + else if ( r1->generation > r2->generation ) + { + // begin + b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation }; + b2SensorBeginTouchEvent event = { sensorId, visitorId }; + b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event ); + index2 += 1; + } + else + { + // persisted + index1 += 1; + index2 += 1; + } + } + else if ( r1->shapeId < r2->shapeId ) + { + // end + b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation }; + b2SensorEndTouchEvent event = { sensorId, visitorId }; + b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event ); + index1 += 1; + } + else + { + // begin + b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation }; + b2SensorBeginTouchEvent event = { sensorId, visitorId }; + b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event ); + index2 += 1; + } + } + + while ( index1 < count1 ) + { + // end + const b2ShapeRef* r1 = refs1 + index1; + b2ShapeId visitorId = { r1->shapeId + 1, world->worldId, r1->generation }; + b2SensorEndTouchEvent event = { sensorId, visitorId }; + b2SensorEndTouchEventArray_Push( &world->sensorEndEvents[world->endEventArrayIndex], event ); + index1 += 1; + } + + while ( index2 < count2 ) + { + // begin + const b2ShapeRef* r2 = refs2 + index2; + b2ShapeId visitorId = { r2->shapeId + 1, world->worldId, r2->generation }; + b2SensorBeginTouchEvent event = { sensorId, visitorId }; + b2SensorBeginTouchEventArray_Push( &world->sensorBeginEvents, event ); + index2 += 1; + } + + // Clear the smallest set bit + word = word & ( word - 1 ); + } + } + + b2TracyCZoneEnd( sensor_state ); + b2TracyCZoneEnd( overlap_sensors ); +} + +void b2DestroySensor( b2World* world, b2Shape* sensorShape ) +{ + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, sensorShape->sensorIndex ); + for ( int i = 0; i < sensor->overlaps2.count; ++i ) + { + b2ShapeRef* ref = sensor->overlaps2.data + i; + b2SensorEndTouchEvent event = { + .sensorShapeId = + { + .index1 = sensorShape->id + 1, + .generation = sensorShape->generation, + .world0 = world->worldId, + }, + .visitorShapeId = + { + .index1 = ref->shapeId + 1, + .generation = ref->generation, + .world0 = world->worldId, + }, + }; + + b2SensorEndTouchEventArray_Push( world->sensorEndEvents + world->endEventArrayIndex, event ); + } + + // Destroy sensor + b2ShapeRefArray_Destroy( &sensor->overlaps1 ); + b2ShapeRefArray_Destroy( &sensor->overlaps2 ); + + int movedIndex = b2SensorArray_RemoveSwap( &world->sensors, sensorShape->sensorIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fixup moved sensor + b2Sensor* movedSensor = b2SensorArray_Get( &world->sensors, sensorShape->sensorIndex ); + b2Shape* otherSensorShape = b2ShapeArray_Get( &world->shapes, movedSensor->shapeId ); + otherSensorShape->sensorIndex = sensorShape->sensorIndex; + } +} diff --git a/3rdparty/box2d/src/sensor.h b/3rdparty/box2d/src/sensor.h new file mode 100644 index 000000000000..6136d9ec44dd --- /dev/null +++ b/3rdparty/box2d/src/sensor.h @@ -0,0 +1,36 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" +#include "bitset.h" + +typedef struct b2Shape b2Shape; +typedef struct b2World b2World; + +typedef struct b2ShapeRef +{ + int shapeId; + uint16_t generation; +} b2ShapeRef; + +typedef struct b2Sensor +{ + b2ShapeRefArray overlaps1; + b2ShapeRefArray overlaps2; + int shapeId; +} b2Sensor; + +typedef struct b2SensorTaskContext +{ + b2BitSet eventBits; +} b2SensorTaskContext; + +void b2OverlapSensors( b2World* world ); + +void b2DestroySensor( b2World* world, b2Shape* sensorShape ); + +B2_ARRAY_INLINE( b2ShapeRef, b2ShapeRef ) +B2_ARRAY_INLINE( b2Sensor, b2Sensor ) +B2_ARRAY_INLINE( b2SensorTaskContext, b2SensorTaskContext ) diff --git a/3rdparty/box2d/src/shape.c b/3rdparty/box2d/src/shape.c new file mode 100644 index 000000000000..a6cc913fe7e0 --- /dev/null +++ b/3rdparty/box2d/src/shape.c @@ -0,0 +1,1714 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "shape.h" + +#include "body.h" +#include "broad_phase.h" +#include "contact.h" +#include "sensor.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include + +B2_ARRAY_SOURCE( b2ChainShape, b2ChainShape ) +B2_ARRAY_SOURCE( b2Shape, b2Shape ) + +static b2Shape* b2GetShape( b2World* world, b2ShapeId shapeId ) +{ + int id = shapeId.index1 - 1; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, id ); + B2_ASSERT( shape->id == id && shape->generation == shapeId.generation ); + return shape; +} + +static b2ChainShape* b2GetChainShape( b2World* world, b2ChainId chainId ) +{ + int id = chainId.index1 - 1; + b2ChainShape* chain = b2ChainShapeArray_Get( &world->chainShapes, id ); + B2_ASSERT( chain->id == id && chain->generation == chainId.generation ); + return chain; +} + +static void b2UpdateShapeAABBs( b2Shape* shape, b2Transform transform, b2BodyType proxyType ) +{ + // Compute a bounding box with a speculative margin + const float speculativeDistance = B2_SPECULATIVE_DISTANCE; + const float aabbMargin = B2_AABB_MARGIN; + + b2AABB aabb = b2ComputeShapeAABB( shape, transform ); + aabb.lowerBound.x -= speculativeDistance; + aabb.lowerBound.y -= speculativeDistance; + aabb.upperBound.x += speculativeDistance; + aabb.upperBound.y += speculativeDistance; + shape->aabb = aabb; + + // Smaller margin for static bodies. Cannot be zero due to TOI tolerance. + float margin = proxyType == b2_staticBody ? speculativeDistance : aabbMargin; + b2AABB fatAABB; + fatAABB.lowerBound.x = aabb.lowerBound.x - margin; + fatAABB.lowerBound.y = aabb.lowerBound.y - margin; + fatAABB.upperBound.x = aabb.upperBound.x + margin; + fatAABB.upperBound.y = aabb.upperBound.y + margin; + shape->fatAABB = fatAABB; +} + +static b2Shape* b2CreateShapeInternal( b2World* world, b2Body* body, b2Transform transform, const b2ShapeDef* def, + const void* geometry, b2ShapeType shapeType ) +{ + int shapeId = b2AllocId( &world->shapeIdPool ); + + if ( shapeId == world->shapes.count ) + { + b2ShapeArray_Push( &world->shapes, ( b2Shape ){ 0 } ); + } + else + { + B2_ASSERT( world->shapes.data[shapeId].id == B2_NULL_INDEX ); + } + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + switch ( shapeType ) + { + case b2_capsuleShape: + shape->capsule = *(const b2Capsule*)geometry; + break; + + case b2_circleShape: + shape->circle = *(const b2Circle*)geometry; + break; + + case b2_polygonShape: + shape->polygon = *(const b2Polygon*)geometry; + break; + + case b2_segmentShape: + shape->segment = *(const b2Segment*)geometry; + break; + + case b2_chainSegmentShape: + shape->chainSegment = *(const b2ChainSegment*)geometry; + break; + + default: + B2_ASSERT( false ); + break; + } + + shape->id = shapeId; + shape->bodyId = body->id; + shape->type = shapeType; + shape->density = def->density; + shape->friction = def->material.friction; + shape->restitution = def->material.restitution; + shape->rollingResistance = def->material.rollingResistance; + shape->tangentSpeed = def->material.tangentSpeed; + shape->userMaterialId = def->material.userMaterialId; + shape->filter = def->filter; + shape->userData = def->userData; + shape->customColor = def->material.customColor; + shape->enlargedAABB = false; + shape->enableSensorEvents = def->enableSensorEvents; + shape->enableContactEvents = def->enableContactEvents; + shape->enableHitEvents = def->enableHitEvents; + shape->enablePreSolveEvents = def->enablePreSolveEvents; + shape->proxyKey = B2_NULL_INDEX; + shape->localCentroid = b2GetShapeCentroid( shape ); + shape->aabb = ( b2AABB ){ b2Vec2_zero, b2Vec2_zero }; + shape->fatAABB = ( b2AABB ){ b2Vec2_zero, b2Vec2_zero }; + shape->generation += 1; + + if ( body->setIndex != b2_disabledSet ) + { + b2BodyType proxyType = body->type; + b2CreateShapeProxy( shape, &world->broadPhase, proxyType, transform, def->invokeContactCreation || def->isSensor ); + } + + // Add to shape doubly linked list + if ( body->headShapeId != B2_NULL_INDEX ) + { + b2Shape* headShape = b2ShapeArray_Get( &world->shapes, body->headShapeId ); + headShape->prevShapeId = shapeId; + } + + shape->prevShapeId = B2_NULL_INDEX; + shape->nextShapeId = body->headShapeId; + body->headShapeId = shapeId; + body->shapeCount += 1; + + if ( def->isSensor ) + { + shape->sensorIndex = world->sensors.count; + b2Sensor sensor = { + .overlaps1 = b2ShapeRefArray_Create( 16 ), + .overlaps2 = b2ShapeRefArray_Create( 16 ), + .shapeId = shapeId, + }; + b2SensorArray_Push( &world->sensors, sensor ); + } + else + { + shape->sensorIndex = B2_NULL_INDEX; + } + + b2ValidateSolverSets( world ); + + return shape; +} + +static b2ShapeId b2CreateShape( b2BodyId bodyId, const b2ShapeDef* def, const void* geometry, b2ShapeType shapeType ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( b2IsValidFloat( def->density ) && def->density >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->material.friction ) && def->material.friction >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->material.restitution ) && def->material.restitution >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->material.rollingResistance ) && def->material.rollingResistance >= 0.0f ); + B2_ASSERT( b2IsValidFloat( def->material.tangentSpeed ) ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return ( b2ShapeId ){ 0 }; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2Shape* shape = b2CreateShapeInternal( world, body, transform, def, geometry, shapeType ); + + if ( def->updateBodyMass == true ) + { + b2UpdateBodyMassData( world, body ); + } + + b2ValidateSolverSets( world ); + + b2ShapeId id = { shape->id + 1, bodyId.world0, shape->generation }; + return id; +} + +b2ShapeId b2CreateCircleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Circle* circle ) +{ + return b2CreateShape( bodyId, def, circle, b2_circleShape ); +} + +b2ShapeId b2CreateCapsuleShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Capsule* capsule ) +{ + float lengthSqr = b2DistanceSquared( capsule->center1, capsule->center2 ); + if ( lengthSqr <= B2_LINEAR_SLOP * B2_LINEAR_SLOP ) + { + b2Circle circle = { b2Lerp( capsule->center1, capsule->center2, 0.5f ), capsule->radius }; + return b2CreateShape( bodyId, def, &circle, b2_circleShape ); + } + + return b2CreateShape( bodyId, def, capsule, b2_capsuleShape ); +} + +b2ShapeId b2CreatePolygonShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Polygon* polygon ) +{ + B2_ASSERT( b2IsValidFloat( polygon->radius ) && polygon->radius >= 0.0f ); + return b2CreateShape( bodyId, def, polygon, b2_polygonShape ); +} + +b2ShapeId b2CreateSegmentShape( b2BodyId bodyId, const b2ShapeDef* def, const b2Segment* segment ) +{ + float lengthSqr = b2DistanceSquared( segment->point1, segment->point2 ); + if ( lengthSqr <= B2_LINEAR_SLOP * B2_LINEAR_SLOP ) + { + B2_ASSERT( false ); + return b2_nullShapeId; + } + + return b2CreateShape( bodyId, def, segment, b2_segmentShape ); +} + +// Destroy a shape on a body. This doesn't need to be called when destroying a body. +static void b2DestroyShapeInternal( b2World* world, b2Shape* shape, b2Body* body, bool wakeBodies ) +{ + int shapeId = shape->id; + + // Remove the shape from the body's doubly linked list. + if ( shape->prevShapeId != B2_NULL_INDEX ) + { + b2Shape* prevShape = b2ShapeArray_Get( &world->shapes, shape->prevShapeId ); + prevShape->nextShapeId = shape->nextShapeId; + } + + if ( shape->nextShapeId != B2_NULL_INDEX ) + { + b2Shape* nextShape = b2ShapeArray_Get( &world->shapes, shape->nextShapeId ); + nextShape->prevShapeId = shape->prevShapeId; + } + + if ( shapeId == body->headShapeId ) + { + body->headShapeId = shape->nextShapeId; + } + + body->shapeCount -= 1; + + // Remove from broad-phase. + b2DestroyShapeProxy( shape, &world->broadPhase ); + + // Destroy any contacts associated with the shape. + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contactKey = contact->edges[edgeIndex].nextKey; + + if ( contact->shapeIdA == shapeId || contact->shapeIdB == shapeId ) + { + b2DestroyContact( world, contact, wakeBodies ); + } + } + + if ( shape->sensorIndex != B2_NULL_INDEX ) + { + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, shape->sensorIndex ); + for ( int i = 0; i < sensor->overlaps2.count; ++i ) + { + b2ShapeRef* ref = sensor->overlaps2.data + i; + b2SensorEndTouchEvent event = { + .sensorShapeId = + { + .index1 = shapeId + 1, + .generation = shape->generation, + .world0 = world->worldId, + }, + .visitorShapeId = + { + .index1 = ref->shapeId + 1, + .generation = ref->generation, + .world0 = world->worldId, + }, + }; + + b2SensorEndTouchEventArray_Push( world->sensorEndEvents + world->endEventArrayIndex, event ); + } + + // Destroy sensor + b2ShapeRefArray_Destroy( &sensor->overlaps1 ); + b2ShapeRefArray_Destroy( &sensor->overlaps2 ); + + int movedIndex = b2SensorArray_RemoveSwap( &world->sensors, shape->sensorIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fixup moved sensor + b2Sensor* movedSensor = b2SensorArray_Get( &world->sensors, shape->sensorIndex ); + b2Shape* otherSensorShape = b2ShapeArray_Get( &world->shapes, movedSensor->shapeId ); + otherSensorShape->sensorIndex = shape->sensorIndex; + } + } + + // Return shape to free list. + b2FreeId( &world->shapeIdPool, shapeId ); + shape->id = B2_NULL_INDEX; + + b2ValidateSolverSets( world ); +} + +void b2DestroyShape( b2ShapeId shapeId, bool updateBodyMass ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + + // need to wake bodies because this might be a static body + bool wakeBodies = true; + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2DestroyShapeInternal( world, shape, body, wakeBodies ); + + if ( updateBodyMass == true ) + { + b2UpdateBodyMassData( world, body ); + } +} + +b2ChainId b2CreateChain( b2BodyId bodyId, const b2ChainDef* def ) +{ + B2_CHECK_DEF( def ); + B2_ASSERT( def->count >= 4 ); + B2_ASSERT( def->materialCount == 1 || def->materialCount == def->count ); + + b2World* world = b2GetWorldLocked( bodyId.world0 ); + if ( world == NULL ) + { + return ( b2ChainId ){ 0 }; + } + + b2Body* body = b2GetBodyFullId( world, bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + int chainId = b2AllocId( &world->chainIdPool ); + + if ( chainId == world->chainShapes.count ) + { + b2ChainShapeArray_Push( &world->chainShapes, ( b2ChainShape ){ 0 } ); + } + else + { + B2_ASSERT( world->chainShapes.data[chainId].id == B2_NULL_INDEX ); + } + + b2ChainShape* chainShape = b2ChainShapeArray_Get( &world->chainShapes, chainId ); + + chainShape->id = chainId; + chainShape->bodyId = body->id; + chainShape->nextChainId = body->headChainId; + chainShape->generation += 1; + + int materialCount = def->materialCount; + chainShape->materialCount = materialCount; + chainShape->materials = b2Alloc( materialCount * sizeof( b2SurfaceMaterial ) ); + + for ( int i = 0; i < materialCount; ++i ) + { + const b2SurfaceMaterial* material = def->materials + i; + B2_ASSERT( b2IsValidFloat( material->friction ) && material->friction >= 0.0f ); + B2_ASSERT( b2IsValidFloat( material->restitution ) && material->restitution >= 0.0f ); + B2_ASSERT( b2IsValidFloat( material->rollingResistance ) && material->rollingResistance >= 0.0f ); + B2_ASSERT( b2IsValidFloat( material->tangentSpeed ) ); + + chainShape->materials[i] = *material; + } + + body->headChainId = chainId; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.userData = def->userData; + shapeDef.filter = def->filter; + shapeDef.enableSensorEvents = def->enableSensorEvents; + shapeDef.enableContactEvents = false; + shapeDef.enableHitEvents = false; + + const b2Vec2* points = def->points; + int n = def->count; + + if ( def->isLoop ) + { + chainShape->count = n; + chainShape->shapeIndices = b2Alloc( chainShape->count * sizeof( int ) ); + + b2ChainSegment chainSegment; + + int prevIndex = n - 1; + for ( int i = 0; i < n - 2; ++i ) + { + chainSegment.ghost1 = points[prevIndex]; + chainSegment.segment.point1 = points[i]; + chainSegment.segment.point2 = points[i + 1]; + chainSegment.ghost2 = points[i + 2]; + chainSegment.chainId = chainId; + prevIndex = i; + + int materialIndex = materialCount == 1 ? 0 : i; + shapeDef.material = def->materials[materialIndex]; + + b2Shape* shape = b2CreateShapeInternal( world, body, transform, &shapeDef, &chainSegment, b2_chainSegmentShape ); + chainShape->shapeIndices[i] = shape->id; + } + + { + chainSegment.ghost1 = points[n - 3]; + chainSegment.segment.point1 = points[n - 2]; + chainSegment.segment.point2 = points[n - 1]; + chainSegment.ghost2 = points[0]; + chainSegment.chainId = chainId; + + int materialIndex = materialCount == 1 ? 0 : n - 2; + shapeDef.material = def->materials[materialIndex]; + + b2Shape* shape = b2CreateShapeInternal( world, body, transform, &shapeDef, &chainSegment, b2_chainSegmentShape ); + chainShape->shapeIndices[n - 2] = shape->id; + } + + { + chainSegment.ghost1 = points[n - 2]; + chainSegment.segment.point1 = points[n - 1]; + chainSegment.segment.point2 = points[0]; + chainSegment.ghost2 = points[1]; + chainSegment.chainId = chainId; + + int materialIndex = materialCount == 1 ? 0 : n - 1; + shapeDef.material = def->materials[materialIndex]; + + b2Shape* shape = b2CreateShapeInternal( world, body, transform, &shapeDef, &chainSegment, b2_chainSegmentShape ); + chainShape->shapeIndices[n - 1] = shape->id; + } + } + else + { + chainShape->count = n - 3; + chainShape->shapeIndices = b2Alloc( chainShape->count * sizeof( int ) ); + + b2ChainSegment chainSegment; + + for ( int i = 0; i < n - 3; ++i ) + { + chainSegment.ghost1 = points[i]; + chainSegment.segment.point1 = points[i + 1]; + chainSegment.segment.point2 = points[i + 2]; + chainSegment.ghost2 = points[i + 3]; + chainSegment.chainId = chainId; + + // Material is associated with leading point of solid segment + int materialIndex = materialCount == 1 ? 0 : i + 1; + shapeDef.material = def->materials[materialIndex]; + + b2Shape* shape = b2CreateShapeInternal( world, body, transform, &shapeDef, &chainSegment, b2_chainSegmentShape ); + chainShape->shapeIndices[i] = shape->id; + } + } + + b2ChainId id = { chainId + 1, world->worldId, chainShape->generation }; + return id; +} + +void b2FreeChainData(b2ChainShape* chain) +{ + b2Free( chain->shapeIndices, chain->count * sizeof( int ) ); + chain->shapeIndices = NULL; + + b2Free( chain->materials, chain->materialCount * sizeof( b2SurfaceMaterial ) ); + chain->materials = NULL; +} + +void b2DestroyChain( b2ChainId chainId ) +{ + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return; + } + + b2ChainShape* chain = b2GetChainShape( world, chainId ); + + b2Body* body = b2BodyArray_Get( &world->bodies, chain->bodyId ); + + // Remove the chain from the body's singly linked list. + int* chainIdPtr = &body->headChainId; + bool found = false; + while ( *chainIdPtr != B2_NULL_INDEX ) + { + if ( *chainIdPtr == chain->id ) + { + *chainIdPtr = chain->nextChainId; + found = true; + break; + } + + chainIdPtr = &( world->chainShapes.data[*chainIdPtr].nextChainId ); + } + + B2_ASSERT( found == true ); + if ( found == false ) + { + return; + } + + int count = chain->count; + for ( int i = 0; i < count; ++i ) + { + int shapeId = chain->shapeIndices[i]; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + bool wakeBodies = true; + b2DestroyShapeInternal( world, shape, body, wakeBodies ); + } + + b2FreeChainData( chain ); + + // Return chain to free list. + b2FreeId( &world->chainIdPool, chain->id ); + chain->id = B2_NULL_INDEX; + + b2ValidateSolverSets( world ); +} + +b2WorldId b2Chain_GetWorld( b2ChainId chainId ) +{ + b2World* world = b2GetWorld( chainId.world0 ); + return ( b2WorldId ){ chainId.world0 + 1, world->generation }; +} + +int b2Chain_GetSegmentCount( b2ChainId chainId ) +{ + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2ChainShape* chain = b2GetChainShape( world, chainId ); + return chain->count; +} + +int b2Chain_GetSegments( b2ChainId chainId, b2ShapeId* segmentArray, int capacity ) +{ + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2ChainShape* chain = b2GetChainShape( world, chainId ); + + int count = b2MinInt( chain->count, capacity ); + for ( int i = 0; i < count; ++i ) + { + int shapeId = chain->shapeIndices[i]; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + segmentArray[i] = ( b2ShapeId ){ shapeId + 1, chainId.world0, shape->generation }; + } + + return count; +} + +b2AABB b2ComputeShapeAABB( const b2Shape* shape, b2Transform xf ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return b2ComputeCapsuleAABB( &shape->capsule, xf ); + case b2_circleShape: + return b2ComputeCircleAABB( &shape->circle, xf ); + case b2_polygonShape: + return b2ComputePolygonAABB( &shape->polygon, xf ); + case b2_segmentShape: + return b2ComputeSegmentAABB( &shape->segment, xf ); + case b2_chainSegmentShape: + return b2ComputeSegmentAABB( &shape->chainSegment.segment, xf ); + default: + { + B2_ASSERT( false ); + b2AABB empty = { xf.p, xf.p }; + return empty; + } + } +} + +b2Vec2 b2GetShapeCentroid( const b2Shape* shape ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return b2Lerp( shape->capsule.center1, shape->capsule.center2, 0.5f ); + case b2_circleShape: + return shape->circle.center; + case b2_polygonShape: + return shape->polygon.centroid; + case b2_segmentShape: + return b2Lerp( shape->segment.point1, shape->segment.point2, 0.5f ); + case b2_chainSegmentShape: + return b2Lerp( shape->chainSegment.segment.point1, shape->chainSegment.segment.point2, 0.5f ); + default: + return b2Vec2_zero; + } +} + +// todo_erin maybe compute this on shape creation +float b2GetShapePerimeter( const b2Shape* shape ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return 2.0f * b2Length( b2Sub( shape->capsule.center1, shape->capsule.center2 ) ) + + 2.0f * B2_PI * shape->capsule.radius; + case b2_circleShape: + return 2.0f * B2_PI * shape->circle.radius; + case b2_polygonShape: + { + const b2Vec2* points = shape->polygon.vertices; + int count = shape->polygon.count; + float perimeter = 2.0f * B2_PI * shape->polygon.radius; + B2_ASSERT( count > 0 ); + b2Vec2 prev = points[count - 1]; + for ( int i = 0; i < count; ++i ) + { + b2Vec2 next = points[i]; + perimeter += b2Length( b2Sub( next, prev ) ); + prev = next; + } + + return perimeter; + } + case b2_segmentShape: + return 2.0f * b2Length( b2Sub( shape->segment.point1, shape->segment.point2 ) ); + case b2_chainSegmentShape: + return 2.0f * b2Length( b2Sub( shape->chainSegment.segment.point1, shape->chainSegment.segment.point2 ) ); + default: + return 0.0f; + } +} + +// This projects the shape perimeter onto an infinite line +float b2GetShapeProjectedPerimeter( const b2Shape* shape, b2Vec2 line ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + { + b2Vec2 axis = b2Sub( shape->capsule.center2, shape->capsule.center1 ); + float projectedLength = b2AbsFloat( b2Dot( axis, line ) ); + return projectedLength + 2.0f * shape->capsule.radius; + } + + case b2_circleShape: + return 2.0f * shape->circle.radius; + + case b2_polygonShape: + { + const b2Vec2* points = shape->polygon.vertices; + int count = shape->polygon.count; + B2_ASSERT( count > 0 ); + float value = b2Dot( points[0], line ); + float lower = value; + float upper = value; + for ( int i = 1; i < count; ++i ) + { + value = b2Dot( points[i], line ); + lower = b2MinFloat( lower, value ); + upper = b2MaxFloat( upper, value ); + } + + return ( upper - lower ) + 2.0f * shape->polygon.radius; + } + + case b2_segmentShape: + { + float value1 = b2Dot( shape->segment.point1, line ); + float value2 = b2Dot( shape->segment.point2, line ); + return b2AbsFloat( value2 - value1 ); + } + + case b2_chainSegmentShape: + { + float value1 = b2Dot( shape->chainSegment.segment.point1, line ); + float value2 = b2Dot( shape->chainSegment.segment.point2, line ); + return b2AbsFloat( value2 - value1 ); + } + + default: + return 0.0f; + } +} + +b2MassData b2ComputeShapeMass( const b2Shape* shape ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return b2ComputeCapsuleMass( &shape->capsule, shape->density ); + case b2_circleShape: + return b2ComputeCircleMass( &shape->circle, shape->density ); + case b2_polygonShape: + return b2ComputePolygonMass( &shape->polygon, shape->density ); + default: + return ( b2MassData ){ 0 }; + } +} + +b2ShapeExtent b2ComputeShapeExtent( const b2Shape* shape, b2Vec2 localCenter ) +{ + b2ShapeExtent extent = { 0 }; + + switch ( shape->type ) + { + case b2_capsuleShape: + { + float radius = shape->capsule.radius; + extent.minExtent = radius; + b2Vec2 c1 = b2Sub( shape->capsule.center1, localCenter ); + b2Vec2 c2 = b2Sub( shape->capsule.center2, localCenter ); + extent.maxExtent = sqrtf( b2MaxFloat( b2LengthSquared( c1 ), b2LengthSquared( c2 ) ) ) + radius; + } + break; + + case b2_circleShape: + { + float radius = shape->circle.radius; + extent.minExtent = radius; + extent.maxExtent = b2Length( b2Sub( shape->circle.center, localCenter ) ) + radius; + } + break; + + case b2_polygonShape: + { + const b2Polygon* poly = &shape->polygon; + float minExtent = B2_HUGE; + float maxExtentSqr = 0.0f; + int count = poly->count; + for ( int i = 0; i < count; ++i ) + { + b2Vec2 v = poly->vertices[i]; + float planeOffset = b2Dot( poly->normals[i], b2Sub( v, poly->centroid ) ); + minExtent = b2MinFloat( minExtent, planeOffset ); + + float distanceSqr = b2LengthSquared( b2Sub( v, localCenter ) ); + maxExtentSqr = b2MaxFloat( maxExtentSqr, distanceSqr ); + } + + extent.minExtent = minExtent + poly->radius; + extent.maxExtent = sqrtf( maxExtentSqr ) + poly->radius; + } + break; + + case b2_segmentShape: + { + extent.minExtent = 0.0f; + b2Vec2 c1 = b2Sub( shape->segment.point1, localCenter ); + b2Vec2 c2 = b2Sub( shape->segment.point2, localCenter ); + extent.maxExtent = sqrtf( b2MaxFloat( b2LengthSquared( c1 ), b2LengthSquared( c2 ) ) ); + } + break; + + case b2_chainSegmentShape: + { + extent.minExtent = 0.0f; + b2Vec2 c1 = b2Sub( shape->chainSegment.segment.point1, localCenter ); + b2Vec2 c2 = b2Sub( shape->chainSegment.segment.point2, localCenter ); + extent.maxExtent = sqrtf( b2MaxFloat( b2LengthSquared( c1 ), b2LengthSquared( c2 ) ) ); + } + break; + + default: + break; + } + + return extent; +} + +b2CastOutput b2RayCastShape( const b2RayCastInput* input, const b2Shape* shape, b2Transform transform ) +{ + b2RayCastInput localInput = *input; + localInput.origin = b2InvTransformPoint( transform, input->origin ); + localInput.translation = b2InvRotateVector( transform.q, input->translation ); + + b2CastOutput output = { 0 }; + switch ( shape->type ) + { + case b2_capsuleShape: + output = b2RayCastCapsule( &localInput, &shape->capsule ); + break; + case b2_circleShape: + output = b2RayCastCircle( &localInput, &shape->circle ); + break; + case b2_polygonShape: + output = b2RayCastPolygon( &localInput, &shape->polygon ); + break; + case b2_segmentShape: + output = b2RayCastSegment( &localInput, &shape->segment, false ); + break; + case b2_chainSegmentShape: + output = b2RayCastSegment( &localInput, &shape->chainSegment.segment, true ); + break; + default: + return output; + } + + output.point = b2TransformPoint( transform, output.point ); + output.normal = b2RotateVector( transform.q, output.normal ); + return output; +} + +b2CastOutput b2ShapeCastShape( const b2ShapeCastInput* input, const b2Shape* shape, b2Transform transform ) +{ + b2ShapeCastInput localInput = *input; + + for ( int i = 0; i < localInput.proxy.count; ++i ) + { + localInput.proxy.points[i] = b2InvTransformPoint( transform, input->proxy.points[i] ); + } + + localInput.translation = b2InvRotateVector( transform.q, input->translation ); + + b2CastOutput output = { 0 }; + switch ( shape->type ) + { + case b2_capsuleShape: + output = b2ShapeCastCapsule( &localInput, &shape->capsule ); + break; + case b2_circleShape: + output = b2ShapeCastCircle( &localInput, &shape->circle ); + break; + case b2_polygonShape: + output = b2ShapeCastPolygon( &localInput, &shape->polygon ); + break; + case b2_segmentShape: + output = b2ShapeCastSegment( &localInput, &shape->segment ); + break; + case b2_chainSegmentShape: + output = b2ShapeCastSegment( &localInput, &shape->chainSegment.segment ); + break; + default: + return output; + } + + output.point = b2TransformPoint( transform, output.point ); + output.normal = b2RotateVector( transform.q, output.normal ); + return output; +} + +b2PlaneResult b2CollideMover( const b2Shape* shape, b2Transform transform, const b2Capsule* mover ) +{ + b2Capsule localMover; + localMover.center1 = b2InvTransformPoint( transform, mover->center1 ); + localMover.center2 = b2InvTransformPoint( transform, mover->center2 ); + localMover.radius = mover->radius; + + b2PlaneResult result = { 0 }; + switch ( shape->type ) + { + case b2_capsuleShape: + result = b2CollideMoverAndCapsule( &shape->capsule, &localMover ); + break; + case b2_circleShape: + result = b2CollideMoverAndCircle( &shape->circle, &localMover ); + break; + case b2_polygonShape: + result = b2CollideMoverAndPolygon( &shape->polygon, &localMover ); + break; + case b2_segmentShape: + result = b2CollideMoverAndSegment( &shape->segment, &localMover ); + break; + case b2_chainSegmentShape: + result = b2CollideMoverAndSegment( &shape->chainSegment.segment, &localMover ); + break; + default: + return result; + } + + if (result.hit == false) + { + return result; + } + + result.plane.normal = b2RotateVector( transform.q, result.plane.normal ); + return result; +} + +void b2CreateShapeProxy( b2Shape* shape, b2BroadPhase* bp, b2BodyType type, b2Transform transform, bool forcePairCreation ) +{ + B2_ASSERT( shape->proxyKey == B2_NULL_INDEX ); + + b2UpdateShapeAABBs( shape, transform, type ); + + // Create proxies in the broad-phase. + shape->proxyKey = + b2BroadPhase_CreateProxy( bp, type, shape->fatAABB, shape->filter.categoryBits, shape->id, forcePairCreation ); + B2_ASSERT( B2_PROXY_TYPE( shape->proxyKey ) < b2_bodyTypeCount ); +} + +void b2DestroyShapeProxy( b2Shape* shape, b2BroadPhase* bp ) +{ + if ( shape->proxyKey != B2_NULL_INDEX ) + { + b2BroadPhase_DestroyProxy( bp, shape->proxyKey ); + shape->proxyKey = B2_NULL_INDEX; + } +} + +b2ShapeProxy b2MakeShapeDistanceProxy( const b2Shape* shape ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return b2MakeProxy( &shape->capsule.center1, 2, shape->capsule.radius ); + case b2_circleShape: + return b2MakeProxy( &shape->circle.center, 1, shape->circle.radius ); + case b2_polygonShape: + return b2MakeProxy( shape->polygon.vertices, shape->polygon.count, shape->polygon.radius ); + case b2_segmentShape: + return b2MakeProxy( &shape->segment.point1, 2, 0.0f ); + case b2_chainSegmentShape: + return b2MakeProxy( &shape->chainSegment.segment.point1, 2, 0.0f ); + default: + { + B2_ASSERT( false ); + b2ShapeProxy empty = { 0 }; + return empty; + } + } +} + +b2BodyId b2Shape_GetBody( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return b2MakeBodyId( world, shape->bodyId ); +} + +b2WorldId b2Shape_GetWorld( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + return ( b2WorldId ){ shapeId.world0 + 1, world->generation }; +} + +void b2Shape_SetUserData( b2ShapeId shapeId, void* userData ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + shape->userData = userData; +} + +void* b2Shape_GetUserData( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->userData; +} + +bool b2Shape_IsSensor( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->sensorIndex != B2_NULL_INDEX; +} + +bool b2Shape_TestPoint( b2ShapeId shapeId, b2Vec2 point ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + + b2Transform transform = b2GetBodyTransform( world, shape->bodyId ); + b2Vec2 localPoint = b2InvTransformPoint( transform, point ); + + switch ( shape->type ) + { + case b2_capsuleShape: + return b2PointInCapsule( localPoint, &shape->capsule ); + + case b2_circleShape: + return b2PointInCircle( localPoint, &shape->circle ); + + case b2_polygonShape: + return b2PointInPolygon( localPoint, &shape->polygon ); + + default: + return false; + } +} + +// todo_erin untested +b2CastOutput b2Shape_RayCast( b2ShapeId shapeId, const b2RayCastInput* input ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + + b2Transform transform = b2GetBodyTransform( world, shape->bodyId ); + + // input in local coordinates + b2RayCastInput localInput; + localInput.origin = b2InvTransformPoint( transform, input->origin ); + localInput.translation = b2InvRotateVector( transform.q, input->translation ); + localInput.maxFraction = input->maxFraction; + + b2CastOutput output = { 0 }; + switch ( shape->type ) + { + case b2_capsuleShape: + output = b2RayCastCapsule( &localInput, &shape->capsule ); + break; + + case b2_circleShape: + output = b2RayCastCircle( &localInput, &shape->circle ); + break; + + case b2_segmentShape: + output = b2RayCastSegment( &localInput, &shape->segment, false ); + break; + + case b2_polygonShape: + output = b2RayCastPolygon( &localInput, &shape->polygon ); + break; + + case b2_chainSegmentShape: + output = b2RayCastSegment( &localInput, &shape->chainSegment.segment, true ); + break; + + default: + B2_ASSERT( false ); + return output; + } + + if ( output.hit ) + { + // convert to world coordinates + output.normal = b2RotateVector( transform.q, output.normal ); + output.point = b2TransformPoint( transform, output.point ); + } + + return output; +} + +void b2Shape_SetDensity( b2ShapeId shapeId, float density, bool updateBodyMass ) +{ + B2_ASSERT( b2IsValidFloat( density ) && density >= 0.0f ); + + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( density == shape->density ) + { + // early return to avoid expensive function + return; + } + + shape->density = density; + + if ( updateBodyMass == true ) + { + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2UpdateBodyMassData( world, body ); + } +} + +float b2Shape_GetDensity( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->density; +} + +void b2Shape_SetFriction( b2ShapeId shapeId, float friction ) +{ + B2_ASSERT( b2IsValidFloat( friction ) && friction >= 0.0f ); + + b2World* world = b2GetWorld( shapeId.world0 ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->friction = friction; +} + +float b2Shape_GetFriction( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->friction; +} + +void b2Shape_SetRestitution( b2ShapeId shapeId, float restitution ) +{ + B2_ASSERT( b2IsValidFloat( restitution ) && restitution >= 0.0f ); + + b2World* world = b2GetWorld( shapeId.world0 ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->restitution = restitution; +} + +float b2Shape_GetRestitution( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->restitution; +} + +void b2Shape_SetMaterial( b2ShapeId shapeId, int material ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->userMaterialId = material; +} + +int b2Shape_GetMaterial( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->userMaterialId; +} + +b2Filter b2Shape_GetFilter( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->filter; +} + +static void b2ResetProxy( b2World* world, b2Shape* shape, bool wakeBodies, bool destroyProxy ) +{ + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + + int shapeId = shape->id; + + // destroy all contacts associated with this shape + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contactKey = contact->edges[edgeIndex].nextKey; + + if ( contact->shapeIdA == shapeId || contact->shapeIdB == shapeId ) + { + b2DestroyContact( world, contact, wakeBodies ); + } + } + + b2Transform transform = b2GetBodyTransformQuick( world, body ); + if ( shape->proxyKey != B2_NULL_INDEX ) + { + b2BodyType proxyType = B2_PROXY_TYPE( shape->proxyKey ); + b2UpdateShapeAABBs( shape, transform, proxyType ); + + if ( destroyProxy ) + { + b2BroadPhase_DestroyProxy( &world->broadPhase, shape->proxyKey ); + + bool forcePairCreation = true; + shape->proxyKey = b2BroadPhase_CreateProxy( &world->broadPhase, proxyType, shape->fatAABB, shape->filter.categoryBits, + shapeId, forcePairCreation ); + } + else + { + b2BroadPhase_MoveProxy( &world->broadPhase, shape->proxyKey, shape->fatAABB ); + } + } + else + { + b2BodyType proxyType = body->type; + b2UpdateShapeAABBs( shape, transform, proxyType ); + } + + b2ValidateSolverSets( world ); +} + +void b2Shape_SetFilter( b2ShapeId shapeId, b2Filter filter ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( filter.maskBits == shape->filter.maskBits && filter.categoryBits == shape->filter.categoryBits && + filter.groupIndex == shape->filter.groupIndex ) + { + return; + } + + // If the category bits change, I need to destroy the proxy because it affects the tree sorting. + bool destroyProxy = filter.categoryBits != shape->filter.categoryBits; + + shape->filter = filter; + + // need to wake bodies because a filter change may destroy contacts + bool wakeBodies = true; + b2ResetProxy( world, shape, wakeBodies, destroyProxy ); + + // note: this does not immediately update sensor overlaps. Instead sensor + // overlaps are updated the next time step +} + +void b2Shape_EnableSensorEvents( b2ShapeId shapeId, bool flag ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->enableSensorEvents = flag; +} + +bool b2Shape_AreSensorEventsEnabled( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->enableSensorEvents; +} + +void b2Shape_EnableContactEvents( b2ShapeId shapeId, bool flag ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->enableContactEvents = flag; +} + +bool b2Shape_AreContactEventsEnabled( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->enableContactEvents; +} + +void b2Shape_EnablePreSolveEvents( b2ShapeId shapeId, bool flag ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->enablePreSolveEvents = flag; +} + +bool b2Shape_ArePreSolveEventsEnabled( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->enablePreSolveEvents; +} + +void b2Shape_EnableHitEvents( b2ShapeId shapeId, bool flag ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->enableHitEvents = flag; +} + +bool b2Shape_AreHitEventsEnabled( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->enableHitEvents; +} + +b2ShapeType b2Shape_GetType( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->type; +} + +b2Circle b2Shape_GetCircle( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + B2_ASSERT( shape->type == b2_circleShape ); + return shape->circle; +} + +b2Segment b2Shape_GetSegment( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + B2_ASSERT( shape->type == b2_segmentShape ); + return shape->segment; +} + +b2ChainSegment b2Shape_GetChainSegment( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + B2_ASSERT( shape->type == b2_chainSegmentShape ); + return shape->chainSegment; +} + +b2Capsule b2Shape_GetCapsule( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + B2_ASSERT( shape->type == b2_capsuleShape ); + return shape->capsule; +} + +b2Polygon b2Shape_GetPolygon( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + B2_ASSERT( shape->type == b2_polygonShape ); + return shape->polygon; +} + +void b2Shape_SetCircle( b2ShapeId shapeId, const b2Circle* circle ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->circle = *circle; + shape->type = b2_circleShape; + + // need to wake bodies so they can react to the shape change + bool wakeBodies = true; + bool destroyProxy = true; + b2ResetProxy( world, shape, wakeBodies, destroyProxy ); +} + +void b2Shape_SetCapsule( b2ShapeId shapeId, const b2Capsule* capsule ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->capsule = *capsule; + shape->type = b2_capsuleShape; + + // need to wake bodies so they can react to the shape change + bool wakeBodies = true; + bool destroyProxy = true; + b2ResetProxy( world, shape, wakeBodies, destroyProxy ); +} + +void b2Shape_SetSegment( b2ShapeId shapeId, const b2Segment* segment ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->segment = *segment; + shape->type = b2_segmentShape; + + // need to wake bodies so they can react to the shape change + bool wakeBodies = true; + bool destroyProxy = true; + b2ResetProxy( world, shape, wakeBodies, destroyProxy ); +} + +void b2Shape_SetPolygon( b2ShapeId shapeId, const b2Polygon* polygon ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + shape->polygon = *polygon; + shape->type = b2_polygonShape; + + // need to wake bodies so they can react to the shape change + bool wakeBodies = true; + bool destroyProxy = true; + b2ResetProxy( world, shape, wakeBodies, destroyProxy ); +} + +b2ChainId b2Shape_GetParentChain( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + b2Shape* shape = b2GetShape( world, shapeId ); + if ( shape->type == b2_chainSegmentShape ) + { + int chainId = shape->chainSegment.chainId; + if ( chainId != B2_NULL_INDEX ) + { + b2ChainShape* chain = b2ChainShapeArray_Get( &world->chainShapes, chainId ); + b2ChainId id = { chainId + 1, shapeId.world0, chain->generation }; + return id; + } + } + + return ( b2ChainId ){ 0 }; +} + +void b2Chain_SetFriction( b2ChainId chainId, float friction ) +{ + B2_ASSERT( b2IsValidFloat( friction ) && friction >= 0.0f ); + + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return; + } + + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + + int materialCount = chainShape->materialCount; + for ( int i = 0; i < materialCount; ++i ) + { + chainShape->materials[i].friction = friction; + } + + int count = chainShape->count; + + for ( int i = 0; i < count; ++i ) + { + int shapeId = chainShape->shapeIndices[i]; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shape->friction = friction; + } +} + +float b2Chain_GetFriction( b2ChainId chainId ) +{ + b2World* world = b2GetWorld( chainId.world0 ); + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + return chainShape->materials[0].friction; +} + +void b2Chain_SetRestitution( b2ChainId chainId, float restitution ) +{ + B2_ASSERT( b2IsValidFloat( restitution ) ); + + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return; + } + + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + + int materialCount = chainShape->materialCount; + for ( int i = 0; i < materialCount; ++i ) + { + chainShape->materials[i].restitution = restitution; + } + + int count = chainShape->count; + + for ( int i = 0; i < count; ++i ) + { + int shapeId = chainShape->shapeIndices[i]; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shape->restitution = restitution; + } +} + +float b2Chain_GetRestitution( b2ChainId chainId ) +{ + b2World* world = b2GetWorld( chainId.world0 ); + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + return chainShape->materials[0].restitution; +} + +void b2Chain_SetMaterial( b2ChainId chainId, int material ) +{ + b2World* world = b2GetWorldLocked( chainId.world0 ); + if ( world == NULL ) + { + return; + } + + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + int materialCount = chainShape->materialCount; + for ( int i = 0; i < materialCount; ++i ) + { + chainShape->materials[i].userMaterialId = material; + } + + int count = chainShape->count; + + for ( int i = 0; i < count; ++i ) + { + int shapeId = chainShape->shapeIndices[i]; + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + shape->userMaterialId = material; + } +} + +int b2Chain_GetMaterial( b2ChainId chainId ) +{ + b2World* world = b2GetWorld( chainId.world0 ); + b2ChainShape* chainShape = b2GetChainShape( world, chainId ); + return chainShape->materials[0].userMaterialId; +} + +int b2Shape_GetContactCapacity( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( shape->sensorIndex != B2_NULL_INDEX ) + { + return 0; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + + // Conservative and fast + return body->contactCount; +} + +int b2Shape_GetContactData( b2ShapeId shapeId, b2ContactData* contactData, int capacity ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( shape->sensorIndex != B2_NULL_INDEX ) + { + return 0; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + int contactKey = body->headContactKey; + int index = 0; + while ( contactKey != B2_NULL_INDEX && index < capacity ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + + // Does contact involve this shape and is it touching? + if ( ( contact->shapeIdA == shapeId.index1 - 1 || contact->shapeIdB == shapeId.index1 - 1 ) && + ( contact->flags & b2_contactTouchingFlag ) != 0 ) + { + b2Shape* shapeA = world->shapes.data + contact->shapeIdA; + b2Shape* shapeB = world->shapes.data + contact->shapeIdB; + + contactData[index].shapeIdA = ( b2ShapeId ){ shapeA->id + 1, shapeId.world0, shapeA->generation }; + contactData[index].shapeIdB = ( b2ShapeId ){ shapeB->id + 1, shapeId.world0, shapeB->generation }; + + b2ContactSim* contactSim = b2GetContactSim( world, contact ); + contactData[index].manifold = contactSim->manifold; + index += 1; + } + + contactKey = contact->edges[edgeIndex].nextKey; + } + + B2_ASSERT( index <= capacity ); + + return index; +} + +int b2Shape_GetSensorCapacity( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( shape->sensorIndex == B2_NULL_INDEX ) + { + return 0; + } + + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, shape->sensorIndex ); + return sensor->overlaps2.count; +} + +int b2Shape_GetSensorOverlaps( b2ShapeId shapeId, b2ShapeId* overlaps, int capacity ) +{ + b2World* world = b2GetWorldLocked( shapeId.world0 ); + if ( world == NULL ) + { + return 0; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + if ( shape->sensorIndex == B2_NULL_INDEX ) + { + return 0; + } + + b2Sensor* sensor = b2SensorArray_Get( &world->sensors, shape->sensorIndex ); + + int count = b2MinInt( sensor->overlaps2.count, capacity ); + b2ShapeRef* refs = sensor->overlaps2.data; + for ( int i = 0; i < count; ++i ) + { + overlaps[i] = ( b2ShapeId ){ + .index1 = refs[i].shapeId + 1, + .generation = refs[i].generation, + .world0 = shapeId.world0, + }; + } + + return count; +} + +b2AABB b2Shape_GetAABB( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + if ( world == NULL ) + { + return ( b2AABB ){ 0 }; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + return shape->aabb; +} + +b2MassData b2Shape_GetMassData( b2ShapeId shapeId ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + if ( world == NULL ) + { + return ( b2MassData ){ 0 }; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + return b2ComputeShapeMass( shape ); +} + +b2Vec2 b2Shape_GetClosestPoint( b2ShapeId shapeId, b2Vec2 target ) +{ + b2World* world = b2GetWorld( shapeId.world0 ); + if ( world == NULL ) + { + return ( b2Vec2 ){ 0 }; + } + + b2Shape* shape = b2GetShape( world, shapeId ); + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2DistanceInput input; + input.proxyA = b2MakeShapeDistanceProxy( shape ); + input.proxyB = b2MakeProxy( &target, 1, 0.0f ); + input.transformA = transform; + input.transformB = b2Transform_identity; + input.useRadii = true; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput output = b2ShapeDistance(&input, &cache, NULL, 0 ); + + return output.pointA; +} diff --git a/3rdparty/box2d/src/shape.h b/3rdparty/box2d/src/shape.h new file mode 100644 index 000000000000..9dbb0be33809 --- /dev/null +++ b/3rdparty/box2d/src/shape.h @@ -0,0 +1,123 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +#include "box2d/types.h" + +typedef struct b2BroadPhase b2BroadPhase; +typedef struct b2World b2World; + +typedef struct b2Shape +{ + int id; + int bodyId; + int prevShapeId; + int nextShapeId; + int sensorIndex; + b2ShapeType type; + float density; + float friction; + float restitution; + float rollingResistance; + float tangentSpeed; + int userMaterialId; + + b2AABB aabb; + b2AABB fatAABB; + b2Vec2 localCentroid; + int proxyKey; + + b2Filter filter; + void* userData; + uint32_t customColor; + + union + { + b2Capsule capsule; + b2Circle circle; + b2Polygon polygon; + b2Segment segment; + b2ChainSegment chainSegment; + }; + + uint16_t generation; + bool enableSensorEvents; + bool enableContactEvents; + bool enableHitEvents; + bool enablePreSolveEvents; + bool enlargedAABB; +} b2Shape; + +typedef struct b2ChainShape +{ + int id; + int bodyId; + int nextChainId; + int count; + int materialCount; + int* shapeIndices; + b2SurfaceMaterial* materials; + uint16_t generation; +} b2ChainShape; + +typedef struct b2ShapeExtent +{ + float minExtent; + float maxExtent; +} b2ShapeExtent; + +// Sensors are shapes that live in the broad-phase but never have contacts. +// At the end of the time step all sensors are queried for overlap with any other shapes. +// Sensors ignore body type and sleeping. +// Sensors generate events when there is a new overlap or and overlap disappears. +// The sensor overlaps don't get cleared until the next time step regardless of the overlapped +// shapes being destroyed. +// When a sensor is destroyed. +typedef struct +{ + b2IntArray overlaps; +} b2SensorOverlaps; + +void b2CreateShapeProxy( b2Shape* shape, b2BroadPhase* bp, b2BodyType type, b2Transform transform, bool forcePairCreation ); +void b2DestroyShapeProxy( b2Shape* shape, b2BroadPhase* bp ); + +void b2FreeChainData( b2ChainShape* chain ); + +b2MassData b2ComputeShapeMass( const b2Shape* shape ); +b2ShapeExtent b2ComputeShapeExtent( const b2Shape* shape, b2Vec2 localCenter ); +b2AABB b2ComputeShapeAABB( const b2Shape* shape, b2Transform transform ); +b2Vec2 b2GetShapeCentroid( const b2Shape* shape ); +float b2GetShapePerimeter( const b2Shape* shape ); +float b2GetShapeProjectedPerimeter( const b2Shape* shape, b2Vec2 line ); + +b2ShapeProxy b2MakeShapeDistanceProxy( const b2Shape* shape ); + +b2CastOutput b2RayCastShape( const b2RayCastInput* input, const b2Shape* shape, b2Transform transform ); +b2CastOutput b2ShapeCastShape( const b2ShapeCastInput* input, const b2Shape* shape, b2Transform transform ); + +b2PlaneResult b2CollideMoverAndCircle( const b2Circle* shape, const b2Capsule* mover ); +b2PlaneResult b2CollideMoverAndCapsule( const b2Capsule* shape, const b2Capsule* mover ); +b2PlaneResult b2CollideMoverAndPolygon( const b2Polygon* shape, const b2Capsule* mover ); +b2PlaneResult b2CollideMoverAndSegment( const b2Segment* shape, const b2Capsule* mover ); +b2PlaneResult b2CollideMover( const b2Shape* shape, b2Transform transform, const b2Capsule* mover ); + +static inline float b2GetShapeRadius( const b2Shape* shape ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + return shape->capsule.radius; + case b2_circleShape: + return shape->circle.radius; + case b2_polygonShape: + return shape->polygon.radius; + default: + return 0.0f; + } +} + +B2_ARRAY_INLINE( b2ChainShape, b2ChainShape ) +B2_ARRAY_INLINE( b2Shape, b2Shape ) diff --git a/3rdparty/box2d/src/solver.c b/3rdparty/box2d/src/solver.c new file mode 100644 index 000000000000..4f009a84cf60 --- /dev/null +++ b/3rdparty/box2d/src/solver.c @@ -0,0 +1,2038 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "solver.h" + +#include "array.h" +#include "atomic.h" +#include "bitset.h" +#include "body.h" +#include "contact.h" +#include "contact_solver.h" +#include "core.h" +#include "ctz.h" +#include "island.h" +#include "joint.h" +#include "shape.h" +#include "solver_set.h" +#include "arena_allocator.h" +#include "world.h" + +#include +#include +#include + +// Compare to SDL_CPUPauseInstruction +#if ( defined( __GNUC__ ) || defined( __clang__ ) ) && ( defined( __i386__ ) || defined( __x86_64__ ) ) +static inline void b2Pause( void ) +{ + __asm__ __volatile__( "pause\n" ); +} +#elif ( defined( __arm__ ) && defined( __ARM_ARCH ) && __ARM_ARCH >= 7 ) || defined( __aarch64__ ) +static inline void b2Pause( void ) +{ + __asm__ __volatile__( "yield" ::: "memory" ); +} +#elif defined( _MSC_VER ) && ( defined( _M_IX86 ) || defined( _M_X64 ) ) +//#include +static inline void b2Pause( void ) +{ + _mm_pause(); +} +#elif defined( _MSC_VER ) && ( defined( _M_ARM ) || defined( _M_ARM64 ) ) +static inline void b2Pause( void ) +{ + __yield(); +} +#else +static inline void b2Pause( void ) +{ +} +#endif + +typedef struct b2WorkerContext +{ + b2StepContext* context; + int workerIndex; + void* userTask; +} b2WorkerContext; + +// Integrate velocities and apply damping +static void b2IntegrateVelocitiesTask( int startIndex, int endIndex, b2StepContext* context ) +{ + b2TracyCZoneNC( integrate_velocity, "IntVel", b2_colorDeepPink, true ); + + b2BodyState* states = context->states; + b2BodySim* sims = context->sims; + + b2Vec2 gravity = context->world->gravity; + float h = context->h; + float maxLinearSpeed = context->maxLinearVelocity; + float maxAngularSpeed = B2_MAX_ROTATION * context->inv_dt; + float maxLinearSpeedSquared = maxLinearSpeed * maxLinearSpeed; + float maxAngularSpeedSquared = maxAngularSpeed * maxAngularSpeed; + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2BodySim* sim = sims + i; + b2BodyState* state = states + i; + + b2Vec2 v = state->linearVelocity; + float w = state->angularVelocity; + + // Apply forces, torque, gravity, and damping + // Apply damping. + // Differential equation: dv/dt + c * v = 0 + // Solution: v(t) = v0 * exp(-c * t) + // Time step: v(t + dt) = v0 * exp(-c * (t + dt)) = v0 * exp(-c * t) * exp(-c * dt) = v(t) * exp(-c * dt) + // v2 = exp(-c * dt) * v1 + // Pade approximation: + // v2 = v1 * 1 / (1 + c * dt) + float linearDamping = 1.0f / ( 1.0f + h * sim->linearDamping ); + float angularDamping = 1.0f / ( 1.0f + h * sim->angularDamping ); + + // Gravity scale will be zero for kinematic bodies + float gravityScale = sim->invMass > 0.0f ? sim->gravityScale : 0.0f; + + // lvd = h * im * f + h * g + b2Vec2 linearVelocityDelta = b2Add( b2MulSV( h * sim->invMass, sim->force ), b2MulSV( h * gravityScale, gravity ) ); + float angularVelocityDelta = h * sim->invInertia * sim->torque; + + v = b2MulAdd( linearVelocityDelta, linearDamping, v ); + w = angularVelocityDelta + angularDamping * w; + + // Clamp to max linear speed + if ( b2Dot( v, v ) > maxLinearSpeedSquared ) + { + float ratio = maxLinearSpeed / b2Length( v ); + v = b2MulSV( ratio, v ); + sim->isSpeedCapped = true; + } + + // Clamp to max angular speed + if ( w * w > maxAngularSpeedSquared && sim->allowFastRotation == false ) + { + float ratio = maxAngularSpeed / b2AbsFloat( w ); + w *= ratio; + sim->isSpeedCapped = true; + } + + state->linearVelocity = v; + state->angularVelocity = w; + } + + b2TracyCZoneEnd( integrate_velocity ); +} + +static void b2PrepareJointsTask( int startIndex, int endIndex, b2StepContext* context ) +{ + b2TracyCZoneNC( prepare_joints, "PrepJoints", b2_colorOldLace, true ); + + b2JointSim** joints = context->joints; + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2JointSim* joint = joints[i]; + b2PrepareJoint( joint, context ); + } + + b2TracyCZoneEnd( prepare_joints ); +} + +static void b2WarmStartJointsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex ) +{ + b2TracyCZoneNC( warm_joints, "WarmJoints", b2_colorGold, true ); + + b2GraphColor* color = context->graph->colors + colorIndex; + b2JointSim* joints = color->jointSims.data; + B2_ASSERT( 0 <= startIndex && startIndex < color->jointSims.count ); + B2_ASSERT( startIndex <= endIndex && endIndex <= color->jointSims.count ); + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2JointSim* joint = joints + i; + b2WarmStartJoint( joint, context ); + } + + b2TracyCZoneEnd( warm_joints ); +} + +static void b2SolveJointsTask( int startIndex, int endIndex, b2StepContext* context, int colorIndex, bool useBias ) +{ + b2TracyCZoneNC( solve_joints, "SolveJoints", b2_colorLemonChiffon, true ); + + b2GraphColor* color = context->graph->colors + colorIndex; + b2JointSim* joints = color->jointSims.data; + B2_ASSERT( 0 <= startIndex && startIndex < color->jointSims.count ); + B2_ASSERT( startIndex <= endIndex && endIndex <= color->jointSims.count ); + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2JointSim* joint = joints + i; + b2SolveJoint( joint, context, useBias ); + } + + b2TracyCZoneEnd( solve_joints ); +} + +static void b2IntegratePositionsTask( int startIndex, int endIndex, b2StepContext* context ) +{ + b2TracyCZoneNC( integrate_positions, "IntPos", b2_colorDarkSeaGreen, true ); + + b2BodyState* states = context->states; + float h = context->h; + + B2_ASSERT( startIndex <= endIndex ); + + for ( int i = startIndex; i < endIndex; ++i ) + { + b2BodyState* state = states + i; + state->deltaRotation = b2IntegrateRotation( state->deltaRotation, h * state->angularVelocity ); + state->deltaPosition = b2MulAdd( state->deltaPosition, h, state->linearVelocity ); + } + + b2TracyCZoneEnd( integrate_positions ); +} + +struct b2ContinuousContext +{ + b2World* world; + b2BodySim* fastBodySim; + b2Shape* fastShape; + b2Vec2 centroid1, centroid2; + b2Sweep sweep; + float fraction; +}; + +// This is called from b2DynamicTree_Query for continuous collision +static bool b2ContinuousQueryCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + struct b2ContinuousContext* continuousContext = context; + b2Shape* fastShape = continuousContext->fastShape; + b2BodySim* fastBodySim = continuousContext->fastBodySim; + + // Skip same shape + if ( shapeId == fastShape->id ) + { + return true; + } + + b2World* world = continuousContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + // Skip same body + if ( shape->bodyId == fastShape->bodyId ) + { + return true; + } + + // Skip sensors + if ( shape->sensorIndex != B2_NULL_INDEX ) + { + return true; + } + + // Skip filtered shapes + bool canCollide = b2ShouldShapesCollide( fastShape->filter, shape->filter ); + if ( canCollide == false ) + { + return true; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + + b2BodySim* bodySim = b2GetBodySim( world, body ); + B2_ASSERT( body->type == b2_staticBody || fastBodySim->isBullet ); + + // Skip bullets + if ( bodySim->isBullet ) + { + return true; + } + + // Skip filtered bodies + b2Body* fastBody = b2BodyArray_Get( &world->bodies, fastBodySim->bodyId ); + canCollide = b2ShouldBodiesCollide( world, fastBody, body ); + if ( canCollide == false ) + { + return true; + } + + // Custom user filtering + b2CustomFilterFcn* customFilterFcn = world->customFilterFcn; + if ( customFilterFcn != NULL ) + { + b2ShapeId idA = { shape->id + 1, world->worldId, shape->generation }; + b2ShapeId idB = { fastShape->id + 1, world->worldId, fastShape->generation }; + canCollide = customFilterFcn( idA, idB, world->customFilterContext ); + if ( canCollide == false ) + { + return true; + } + } + + // Prevent pausing on chain segment junctions + if ( shape->type == b2_chainSegmentShape ) + { + b2Transform transform = bodySim->transform; + b2Vec2 p1 = b2TransformPoint( transform, shape->chainSegment.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform, shape->chainSegment.segment.point2 ); + b2Vec2 e = b2Sub( p2, p1 ); + float length; + e = b2GetLengthAndNormalize( &length, e ); + if (length > B2_LINEAR_SLOP) + { + b2Vec2 c1 = continuousContext->centroid1; + float offset1 = b2Cross( b2Sub( c1, p1 ), e ); + b2Vec2 c2 = continuousContext->centroid2; + float offset2 = b2Cross( b2Sub( c2, p1 ), e ); + + // todo this should use the min extent of the fast shape, not the body + const float allowedFraction = 0.25f; + if ( offset1 < 0.0f || offset1 - offset2 < allowedFraction * fastBodySim->minExtent ) + { + // Minimal clipping + return true; + } + } + } + + // todo_erin testing early out for segments +#if 0 + if ( shape->type == b2_segmentShape ) + { + b2Transform transform = bodySim->transform; + b2Vec2 p1 = b2TransformPoint( transform, shape->segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform, shape->segment.point2 ); + b2Vec2 e = b2Sub( p2, p1 ); + b2Vec2 c1 = continuousContext->centroid1; + b2Vec2 c2 = continuousContext->centroid2; + float offset1 = b2Cross( b2Sub( c1, p1 ), e ); + float offset2 = b2Cross( b2Sub( c2, p1 ), e ); + + if ( offset1 > 0.0f && offset2 > 0.0f ) + { + // Started behind or finished in front + return true; + } + + if ( offset1 < 0.0f && offset2 < 0.0f ) + { + // Started behind or finished in front + return true; + } + } +#endif + + b2TOIInput input; + input.proxyA = b2MakeShapeDistanceProxy( shape ); + input.proxyB = b2MakeShapeDistanceProxy( fastShape ); + input.sweepA = b2MakeSweep( bodySim ); + input.sweepB = continuousContext->sweep; + input.maxFraction = continuousContext->fraction; + + float hitFraction = continuousContext->fraction; + + bool didHit = false; + b2TOIOutput output = b2TimeOfImpact( &input ); + if ( 0.0f < output.fraction && output.fraction < continuousContext->fraction ) + { + hitFraction = output.fraction; + didHit = true; + } + else if ( 0.0f == output.fraction ) + { + // fallback to TOI of a small circle around the fast shape centroid + b2Vec2 centroid = b2GetShapeCentroid( fastShape ); + b2ShapeExtent extent = b2ComputeShapeExtent( fastShape, centroid ); + float radius = 0.25f * extent.minExtent; + input.proxyB = b2MakeProxy( ¢roid, 1, radius ); + output = b2TimeOfImpact( &input ); + if ( 0.0f < output.fraction && output.fraction < continuousContext->fraction ) + { + hitFraction = output.fraction; + didHit = true; + } + } + + if ( didHit && ( shape->enablePreSolveEvents || fastShape->enablePreSolveEvents ) ) + { + // Pre-solve is expensive because I need to compute a temporary manifold + b2Transform transformA = b2GetSweepTransform( &input.sweepA, hitFraction ); + b2Transform transformB = b2GetSweepTransform( &input.sweepB, hitFraction ); + b2Manifold manifold = b2ComputeManifold( shape, transformA, fastShape, transformB ); + b2ShapeId shapeIdA = { shape->id + 1, world->worldId, shape->generation }; + b2ShapeId shapeIdB = { fastShape->id + 1, world->worldId, fastShape->generation }; + + // The user may modify the temporary manifold here but it doesn't matter. They will be able to + // modify the real manifold in the discrete solver. + didHit = world->preSolveFcn( shapeIdA, shapeIdB, &manifold, world->preSolveContext ); + } + + if ( didHit ) + { + continuousContext->fraction = hitFraction; + } + + return true; +} + +// Continuous collision of dynamic versus static +static void b2SolveContinuous( b2World* world, int bodySimIndex ) +{ + b2TracyCZoneNC( ccd, "CCD", b2_colorDarkGoldenRod, true ); + + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodySim* fastBodySim = b2BodySimArray_Get( &awakeSet->bodySims, bodySimIndex ); + B2_ASSERT( fastBodySim->isFast ); + + b2Sweep sweep = b2MakeSweep( fastBodySim ); + + b2Transform xf1; + xf1.q = sweep.q1; + xf1.p = b2Sub( sweep.c1, b2RotateVector( sweep.q1, sweep.localCenter ) ); + + b2Transform xf2; + xf2.q = sweep.q2; + xf2.p = b2Sub( sweep.c2, b2RotateVector( sweep.q2, sweep.localCenter ) ); + + b2DynamicTree* staticTree = world->broadPhase.trees + b2_staticBody; + b2DynamicTree* kinematicTree = world->broadPhase.trees + b2_kinematicBody; + b2DynamicTree* dynamicTree = world->broadPhase.trees + b2_dynamicBody; + b2Body* fastBody = b2BodyArray_Get( &world->bodies, fastBodySim->bodyId ); + + struct b2ContinuousContext context; + context.world = world; + context.sweep = sweep; + context.fastBodySim = fastBodySim; + context.fraction = 1.0f; + + bool isBullet = fastBodySim->isBullet; + + int shapeId = fastBody->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* fastShape = b2ShapeArray_Get( &world->shapes, shapeId ); + shapeId = fastShape->nextShapeId; + + context.fastShape = fastShape; + context.centroid1 = b2TransformPoint( xf1, fastShape->localCentroid ); + context.centroid2 = b2TransformPoint( xf2, fastShape->localCentroid ); + + b2AABB box1 = fastShape->aabb; + b2AABB box2 = b2ComputeShapeAABB( fastShape, xf2 ); + b2AABB box = b2AABB_Union( box1, box2 ); + + // Store this to avoid double computation in the case there is no impact event + fastShape->aabb = box2; + + // No continuous collision for sensors (but still need the updated bounds) + if ( fastShape->sensorIndex != B2_NULL_INDEX ) + { + continue; + } + + b2DynamicTree_Query( staticTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); + + if ( isBullet ) + { + b2DynamicTree_Query( kinematicTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); + b2DynamicTree_Query( dynamicTree, box, B2_DEFAULT_MASK_BITS, b2ContinuousQueryCallback, &context ); + } + } + + const float speculativeDistance = B2_SPECULATIVE_DISTANCE; + const float aabbMargin = B2_AABB_MARGIN; + + if ( context.fraction < 1.0f ) + { + // Handle time of impact event + b2Rot q = b2NLerp( sweep.q1, sweep.q2, context.fraction ); + b2Vec2 c = b2Lerp( sweep.c1, sweep.c2, context.fraction ); + b2Vec2 origin = b2Sub( c, b2RotateVector( q, sweep.localCenter ) ); + + // Advance body + b2Transform transform = { origin, q }; + fastBodySim->transform = transform; + fastBodySim->center = c; + fastBodySim->rotation0 = q; + fastBodySim->center0 = c; + + // Update body move event + b2BodyMoveEvent* event = b2BodyMoveEventArray_Get( &world->bodyMoveEvents, bodySimIndex ); + event->transform = transform; + + // Prepare AABBs for broad-phase. + // Even though a body is fast, it may not move much. So the + // AABB may not need enlargement. + + shapeId = fastBody->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + // Must recompute aabb at the interpolated transform + b2AABB aabb = b2ComputeShapeAABB( shape, transform ); + aabb.lowerBound.x -= speculativeDistance; + aabb.lowerBound.y -= speculativeDistance; + aabb.upperBound.x += speculativeDistance; + aabb.upperBound.y += speculativeDistance; + shape->aabb = aabb; + + if ( b2AABB_Contains( shape->fatAABB, aabb ) == false ) + { + b2AABB fatAABB; + fatAABB.lowerBound.x = aabb.lowerBound.x - aabbMargin; + fatAABB.lowerBound.y = aabb.lowerBound.y - aabbMargin; + fatAABB.upperBound.x = aabb.upperBound.x + aabbMargin; + fatAABB.upperBound.y = aabb.upperBound.y + aabbMargin; + shape->fatAABB = fatAABB; + + shape->enlargedAABB = true; + fastBodySim->enlargeAABB = true; + } + + shapeId = shape->nextShapeId; + } + } + else + { + // No time of impact event + + // Advance body + fastBodySim->rotation0 = fastBodySim->transform.q; + fastBodySim->center0 = fastBodySim->center; + + // Prepare AABBs for broad-phase + shapeId = fastBody->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + // shape->aabb is still valid from above + + if ( b2AABB_Contains( shape->fatAABB, shape->aabb ) == false ) + { + b2AABB fatAABB; + fatAABB.lowerBound.x = shape->aabb.lowerBound.x - aabbMargin; + fatAABB.lowerBound.y = shape->aabb.lowerBound.y - aabbMargin; + fatAABB.upperBound.x = shape->aabb.upperBound.x + aabbMargin; + fatAABB.upperBound.y = shape->aabb.upperBound.y + aabbMargin; + shape->fatAABB = fatAABB; + + shape->enlargedAABB = true; + fastBodySim->enlargeAABB = true; + } + + shapeId = shape->nextShapeId; + } + } + + b2TracyCZoneEnd( ccd ); +} + +static void b2FinalizeBodiesTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + b2TracyCZoneNC( finalize_transfprms, "Transforms", b2_colorMediumSeaGreen, true ); + + b2StepContext* stepContext = context; + b2World* world = stepContext->world; + bool enableSleep = world->enableSleep; + b2BodyState* states = stepContext->states; + b2BodySim* sims = stepContext->sims; + b2Body* bodies = world->bodies.data; + float timeStep = stepContext->dt; + float invTimeStep = stepContext->inv_dt; + + uint16_t worldId = world->worldId; + + // The body move event array should already have the correct size + B2_ASSERT( endIndex <= world->bodyMoveEvents.count ); + b2BodyMoveEvent* moveEvents = world->bodyMoveEvents.data; + + b2BitSet* enlargedSimBitSet = &world->taskContexts.data[threadIndex].enlargedSimBitSet; + b2BitSet* awakeIslandBitSet = &world->taskContexts.data[threadIndex].awakeIslandBitSet; + b2TaskContext* taskContext = world->taskContexts.data + threadIndex; + + bool enableContinuous = world->enableContinuous; + + const float speculativeDistance = B2_SPECULATIVE_DISTANCE; + const float aabbMargin = B2_AABB_MARGIN; + + B2_ASSERT( startIndex <= endIndex ); + + for ( int simIndex = startIndex; simIndex < endIndex; ++simIndex ) + { + b2BodyState* state = states + simIndex; + b2BodySim* sim = sims + simIndex; + + b2Vec2 v = state->linearVelocity; + float w = state->angularVelocity; + + B2_ASSERT( b2IsValidVec2( v ) ); + B2_ASSERT( b2IsValidFloat( w ) ); + + sim->center = b2Add( sim->center, state->deltaPosition ); + sim->transform.q = b2NormalizeRot( b2MulRot( state->deltaRotation, sim->transform.q ) ); + + // Use the velocity of the farthest point on the body to account for rotation. + float maxVelocity = b2Length( v ) + b2AbsFloat( w ) * sim->maxExtent; + + // Sleep needs to observe position correction as well as true velocity. + float maxDeltaPosition = b2Length( state->deltaPosition ) + b2AbsFloat( state->deltaRotation.s ) * sim->maxExtent; + + // Position correction is not as important for sleep as true velocity. + float positionSleepFactor = 0.5f; + + float sleepVelocity = b2MaxFloat( maxVelocity, positionSleepFactor * invTimeStep * maxDeltaPosition ); + + // reset state deltas + state->deltaPosition = b2Vec2_zero; + state->deltaRotation = b2Rot_identity; + + sim->transform.p = b2Sub( sim->center, b2RotateVector( sim->transform.q, sim->localCenter ) ); + + // cache miss here, however I need the shape list below + b2Body* body = bodies + sim->bodyId; + body->bodyMoveIndex = simIndex; + moveEvents[simIndex].transform = sim->transform; + moveEvents[simIndex].bodyId = ( b2BodyId ){ sim->bodyId + 1, worldId, body->generation }; + moveEvents[simIndex].userData = body->userData; + moveEvents[simIndex].fellAsleep = false; + + // reset applied force and torque + sim->force = b2Vec2_zero; + sim->torque = 0.0f; + + body->isSpeedCapped = sim->isSpeedCapped; + sim->isSpeedCapped = false; + + sim->isFast = false; + + if ( enableSleep == false || body->enableSleep == false || sleepVelocity > body->sleepThreshold ) + { + // Body is not sleepy + body->sleepTime = 0.0f; + + if ( body->type == b2_dynamicBody && enableContinuous && maxVelocity * timeStep > 0.5f * sim->minExtent ) + { + // This flag is only retained for debug draw + sim->isFast = true; + + // Store in fast array for the continuous collision stage + // This is deterministic because the order of TOI sweeps doesn't matter + if ( sim->isBullet ) + { + int bulletIndex = b2AtomicFetchAddInt( &stepContext->bulletBodyCount, 1 ); + stepContext->bulletBodies[bulletIndex] = simIndex; + } + else + { + b2SolveContinuous( world, simIndex ); + } + } + else + { + // Body is safe to advance + sim->center0 = sim->center; + sim->rotation0 = sim->transform.q; + } + } + else + { + // Body is safe to advance and is falling asleep + sim->center0 = sim->center; + sim->rotation0 = sim->transform.q; + body->sleepTime += timeStep; + } + + // Any single body in an island can keep it awake + b2Island* island = b2IslandArray_Get( &world->islands, body->islandId ); + if ( body->sleepTime < B2_TIME_TO_SLEEP ) + { + // keep island awake + int islandIndex = island->localIndex; + b2SetBit( awakeIslandBitSet, islandIndex ); + } + else if ( island->constraintRemoveCount > 0 ) + { + // body wants to sleep but its island needs splitting first + if ( body->sleepTime > taskContext->splitSleepTime ) + { + // pick the sleepiest candidate + taskContext->splitIslandId = body->islandId; + taskContext->splitSleepTime = body->sleepTime; + } + } + + // Update shapes AABBs + b2Transform transform = sim->transform; + bool isFast = sim->isFast; + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + if ( isFast ) + { + // For fast non-bullet bodies the AABB has already been updated in b2SolveContinuous + // For fast bullet bodies the AABB will be updated at a later stage + + // Add to enlarged shapes regardless of AABB changes. + // Bit-set to keep the move array sorted + b2SetBit( enlargedSimBitSet, simIndex ); + } + else + { + b2AABB aabb = b2ComputeShapeAABB( shape, transform ); + aabb.lowerBound.x -= speculativeDistance; + aabb.lowerBound.y -= speculativeDistance; + aabb.upperBound.x += speculativeDistance; + aabb.upperBound.y += speculativeDistance; + shape->aabb = aabb; + + B2_ASSERT( shape->enlargedAABB == false ); + + if ( b2AABB_Contains( shape->fatAABB, aabb ) == false ) + { + b2AABB fatAABB; + fatAABB.lowerBound.x = aabb.lowerBound.x - aabbMargin; + fatAABB.lowerBound.y = aabb.lowerBound.y - aabbMargin; + fatAABB.upperBound.x = aabb.upperBound.x + aabbMargin; + fatAABB.upperBound.y = aabb.upperBound.y + aabbMargin; + shape->fatAABB = fatAABB; + + shape->enlargedAABB = true; + + // Bit-set to keep the move array sorted + b2SetBit( enlargedSimBitSet, simIndex ); + } + } + + shapeId = shape->nextShapeId; + } + } + + b2TracyCZoneEnd( finalize_transfprms ); +} + +/* + typedef enum b2SolverStageType +{ + b2_stagePrepareJoints, + b2_stagePrepareContacts, + b2_stageIntegrateVelocities, + b2_stageWarmStart, + b2_stageSolve, + b2_stageIntegratePositions, + b2_stageRelax, + b2_stageRestitution, + b2_stageStoreImpulses +} b2SolverStageType; + +typedef enum b2SolverBlockType +{ + b2_bodyBlock, + b2_jointBlock, + b2_contactBlock, + b2_graphJointBlock, + b2_graphContactBlock +} b2SolverBlockType; +*/ + +static void b2ExecuteBlock( b2SolverStage* stage, b2StepContext* context, b2SolverBlock* block ) +{ + b2SolverStageType stageType = stage->type; + b2SolverBlockType blockType = block->blockType; + int startIndex = block->startIndex; + int endIndex = startIndex + block->count; + + switch ( stageType ) + { + case b2_stagePrepareJoints: + b2PrepareJointsTask( startIndex, endIndex, context ); + break; + + case b2_stagePrepareContacts: + b2PrepareContactsTask( startIndex, endIndex, context ); + break; + + case b2_stageIntegrateVelocities: + b2IntegrateVelocitiesTask( startIndex, endIndex, context ); + break; + + case b2_stageWarmStart: + if ( context->world->enableWarmStarting ) + { + if ( blockType == b2_graphContactBlock ) + { + b2WarmStartContactsTask( startIndex, endIndex, context, stage->colorIndex ); + } + else if ( blockType == b2_graphJointBlock ) + { + b2WarmStartJointsTask( startIndex, endIndex, context, stage->colorIndex ); + } + } + break; + + case b2_stageSolve: + if ( blockType == b2_graphContactBlock ) + { + b2SolveContactsTask( startIndex, endIndex, context, stage->colorIndex, true ); + } + else if ( blockType == b2_graphJointBlock ) + { + b2SolveJointsTask( startIndex, endIndex, context, stage->colorIndex, true ); + } + break; + + case b2_stageIntegratePositions: + b2IntegratePositionsTask( startIndex, endIndex, context ); + break; + + case b2_stageRelax: + if ( blockType == b2_graphContactBlock ) + { + b2SolveContactsTask( startIndex, endIndex, context, stage->colorIndex, false ); + } + else if ( blockType == b2_graphJointBlock ) + { + b2SolveJointsTask( startIndex, endIndex, context, stage->colorIndex, false ); + } + break; + + case b2_stageRestitution: + if ( blockType == b2_graphContactBlock ) + { + b2ApplyRestitutionTask( startIndex, endIndex, context, stage->colorIndex ); + } + break; + + case b2_stageStoreImpulses: + b2StoreImpulsesTask( startIndex, endIndex, context ); + break; + } +} + +static inline int GetWorkerStartIndex( int workerIndex, int blockCount, int workerCount ) +{ + if ( blockCount <= workerCount ) + { + return workerIndex < blockCount ? workerIndex : B2_NULL_INDEX; + } + + int blocksPerWorker = blockCount / workerCount; + int remainder = blockCount - blocksPerWorker * workerCount; + return blocksPerWorker * workerIndex + b2MinInt( remainder, workerIndex ); +} + +static void b2ExecuteStage( b2SolverStage* stage, b2StepContext* context, int previousSyncIndex, int syncIndex, int workerIndex ) +{ + int completedCount = 0; + b2SolverBlock* blocks = stage->blocks; + int blockCount = stage->blockCount; + + int expectedSyncIndex = previousSyncIndex; + + int startIndex = GetWorkerStartIndex( workerIndex, blockCount, context->workerCount ); + if ( startIndex == B2_NULL_INDEX ) + { + return; + } + + B2_ASSERT( 0 <= startIndex && startIndex < blockCount ); + + int blockIndex = startIndex; + + while ( b2AtomicCompareExchangeInt( &blocks[blockIndex].syncIndex, expectedSyncIndex, syncIndex ) == true ) + { + B2_ASSERT( stage->type != b2_stagePrepareContacts || syncIndex < 2 ); + + B2_ASSERT( completedCount < blockCount ); + + b2ExecuteBlock( stage, context, blocks + blockIndex ); + + completedCount += 1; + blockIndex += 1; + if ( blockIndex >= blockCount ) + { + // Keep looking for work + blockIndex = 0; + } + + expectedSyncIndex = previousSyncIndex; + } + + // Search backwards for blocks + blockIndex = startIndex - 1; + while ( true ) + { + if ( blockIndex < 0 ) + { + blockIndex = blockCount - 1; + } + + expectedSyncIndex = previousSyncIndex; + + if ( b2AtomicCompareExchangeInt( &blocks[blockIndex].syncIndex, expectedSyncIndex, syncIndex ) == false ) + { + break; + } + + b2ExecuteBlock( stage, context, blocks + blockIndex ); + completedCount += 1; + blockIndex -= 1; + } + + (void)b2AtomicFetchAddInt( &stage->completionCount, completedCount ); +} + +static void b2ExecuteMainStage( b2SolverStage* stage, b2StepContext* context, uint32_t syncBits ) +{ + int blockCount = stage->blockCount; + if ( blockCount == 0 ) + { + return; + } + + if ( blockCount == 1 ) + { + b2ExecuteBlock( stage, context, stage->blocks ); + } + else + { + b2AtomicStoreU32( &context->atomicSyncBits, syncBits ); + + int syncIndex = ( syncBits >> 16 ) & 0xFFFF; + B2_ASSERT( syncIndex > 0 ); + int previousSyncIndex = syncIndex - 1; + + b2ExecuteStage( stage, context, previousSyncIndex, syncIndex, 0 ); + + // todo consider using the cycle counter as well + while ( b2AtomicLoadInt( &stage->completionCount ) != blockCount ) + { + b2Pause(); + } + + b2AtomicStoreInt( &stage->completionCount, 0 ); + } +} + +// This should not use the thread index because thread 0 can be called twice by enkiTS. +static void b2SolverTask( int startIndex, int endIndex, uint32_t threadIndexIgnore, void* taskContext ) +{ + B2_UNUSED( startIndex, endIndex, threadIndexIgnore ); + + b2WorkerContext* workerContext = taskContext; + int workerIndex = workerContext->workerIndex; + b2StepContext* context = workerContext->context; + int activeColorCount = context->activeColorCount; + b2SolverStage* stages = context->stages; + b2Profile* profile = &context->world->profile; + + if ( workerIndex == 0 ) + { + // Main thread synchronizes the workers and does work itself. + // + // Stages are re-used by loops so that I don't need more stages for large iteration counts. + // The sync indices grow monotonically for the body/graph/constraint groupings because they share solver blocks. + // The stage index and sync indices are combined in to sync bits for atomic synchronization. + // The workers need to compute the previous sync index for a given stage so that CAS works correctly. This + // setup makes this easy to do. + + /* + b2_stagePrepareJoints, + b2_stagePrepareContacts, + b2_stageIntegrateVelocities, + b2_stageWarmStart, + b2_stageSolve, + b2_stageIntegratePositions, + b2_stageRelax, + b2_stageRestitution, + b2_stageStoreImpulses + */ + + uint64_t ticks = b2GetTicks(); + + int bodySyncIndex = 1; + int stageIndex = 0; + + // This stage loops over all awake joints + uint32_t jointSyncIndex = 1; + uint32_t syncBits = ( jointSyncIndex << 16 ) | stageIndex; + B2_ASSERT( stages[stageIndex].type == b2_stagePrepareJoints ); + b2ExecuteMainStage( stages + stageIndex, context, syncBits ); + stageIndex += 1; + jointSyncIndex += 1; + + // This stage loops over all contact constraints + uint32_t contactSyncIndex = 1; + syncBits = ( contactSyncIndex << 16 ) | stageIndex; + B2_ASSERT( stages[stageIndex].type == b2_stagePrepareContacts ); + b2ExecuteMainStage( stages + stageIndex, context, syncBits ); + stageIndex += 1; + contactSyncIndex += 1; + + int graphSyncIndex = 1; + + // Single-threaded overflow work. These constraints don't fit in the graph coloring. + b2PrepareOverflowJoints( context ); + b2PrepareOverflowContacts( context ); + + profile->prepareConstraints += b2GetMillisecondsAndReset( &ticks ); + + int subStepCount = context->subStepCount; + for ( int i = 0; i < subStepCount; ++i ) + { + // stage index restarted each iteration + // syncBits still increases monotonically because the upper bits increase each iteration + int iterStageIndex = stageIndex; + + // integrate velocities + syncBits = ( bodySyncIndex << 16 ) | iterStageIndex; + B2_ASSERT( stages[iterStageIndex].type == b2_stageIntegrateVelocities ); + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + bodySyncIndex += 1; + + profile->integrateVelocities += b2GetMillisecondsAndReset( &ticks ); + + // warm start constraints + b2WarmStartOverflowJoints( context ); + b2WarmStartOverflowContacts( context ); + + for ( int colorIndex = 0; colorIndex < activeColorCount; ++colorIndex ) + { + syncBits = ( graphSyncIndex << 16 ) | iterStageIndex; + B2_ASSERT( stages[iterStageIndex].type == b2_stageWarmStart ); + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + } + graphSyncIndex += 1; + + profile->warmStart += b2GetMillisecondsAndReset( &ticks ); + + // solve constraints + bool useBias = true; + b2SolveOverflowJoints( context, useBias ); + b2SolveOverflowContacts( context, useBias ); + + for ( int colorIndex = 0; colorIndex < activeColorCount; ++colorIndex ) + { + syncBits = ( graphSyncIndex << 16 ) | iterStageIndex; + B2_ASSERT( stages[iterStageIndex].type == b2_stageSolve ); + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + } + graphSyncIndex += 1; + + profile->solveImpulses += b2GetMillisecondsAndReset( &ticks ); + + // integrate positions + B2_ASSERT( stages[iterStageIndex].type == b2_stageIntegratePositions ); + syncBits = ( bodySyncIndex << 16 ) | iterStageIndex; + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + bodySyncIndex += 1; + + profile->integratePositions += b2GetMillisecondsAndReset( &ticks ); + + // relax constraints + useBias = false; + b2SolveOverflowJoints( context, useBias ); + b2SolveOverflowContacts( context, useBias ); + + for ( int colorIndex = 0; colorIndex < activeColorCount; ++colorIndex ) + { + syncBits = ( graphSyncIndex << 16 ) | iterStageIndex; + B2_ASSERT( stages[iterStageIndex].type == b2_stageRelax ); + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + } + graphSyncIndex += 1; + + profile->relaxImpulses += b2GetMillisecondsAndReset( &ticks ); + } + + // advance the stage according to the sub-stepping tasks just completed + // integrate velocities / warm start / solve / integrate positions / relax + stageIndex += 1 + activeColorCount + activeColorCount + 1 + activeColorCount; + + // Restitution + { + b2ApplyOverflowRestitution( context ); + + int iterStageIndex = stageIndex; + for ( int colorIndex = 0; colorIndex < activeColorCount; ++colorIndex ) + { + syncBits = ( graphSyncIndex << 16 ) | iterStageIndex; + B2_ASSERT( stages[iterStageIndex].type == b2_stageRestitution ); + b2ExecuteMainStage( stages + iterStageIndex, context, syncBits ); + iterStageIndex += 1; + } + // graphSyncIndex += 1; + stageIndex += activeColorCount; + } + + profile->applyRestitution += b2GetMillisecondsAndReset( &ticks ); + + b2StoreOverflowImpulses( context ); + + syncBits = ( contactSyncIndex << 16 ) | stageIndex; + B2_ASSERT( stages[stageIndex].type == b2_stageStoreImpulses ); + b2ExecuteMainStage( stages + stageIndex, context, syncBits ); + + profile->storeImpulses += b2GetMillisecondsAndReset( &ticks ); + + // Signal workers to finish + b2AtomicStoreU32( &context->atomicSyncBits, UINT_MAX ); + + B2_ASSERT( stageIndex + 1 == context->stageCount ); + return; + } + + // Worker spins and waits for work + uint32_t lastSyncBits = 0; + // uint64_t maxSpinTime = 10; + while ( true ) + { + // Spin until main thread bumps changes the sync bits. This can waste significant time overall, but it is necessary for + // parallel simulation with graph coloring. + uint32_t syncBits; + int spinCount = 0; + while ( ( syncBits = b2AtomicLoadU32( &context->atomicSyncBits ) ) == lastSyncBits ) + { + if ( spinCount > 5 ) + { + b2Yield(); + spinCount = 0; + } + else + { + // Using the cycle counter helps to account for variation in mm_pause timing across different + // CPUs. However, this is X64 only. + // uint64_t prev = __rdtsc(); + // do + //{ + // b2Pause(); + //} + // while ((__rdtsc() - prev) < maxSpinTime); + // maxSpinTime += 10; + b2Pause(); + b2Pause(); + spinCount += 1; + } + } + + if ( syncBits == UINT_MAX ) + { + // sentinel hit + break; + } + + int stageIndex = syncBits & 0xFFFF; + B2_ASSERT( stageIndex < context->stageCount ); + + int syncIndex = ( syncBits >> 16 ) & 0xFFFF; + B2_ASSERT( syncIndex > 0 ); + + int previousSyncIndex = syncIndex - 1; + + b2SolverStage* stage = stages + stageIndex; + b2ExecuteStage( stage, context, previousSyncIndex, syncIndex, workerIndex ); + + lastSyncBits = syncBits; + } +} + +static void b2BulletBodyTask( int startIndex, int endIndex, uint32_t threadIndex, void* taskContext ) +{ + B2_UNUSED( threadIndex ); + + b2TracyCZoneNC( bullet_body_task, "Bullet", b2_colorLightSkyBlue, true ); + + b2StepContext* stepContext = taskContext; + + B2_ASSERT( startIndex <= endIndex ); + + for ( int i = startIndex; i < endIndex; ++i ) + { + int simIndex = stepContext->bulletBodies[i]; + b2SolveContinuous( stepContext->world, simIndex ); + } + + b2TracyCZoneEnd( bullet_body_task ); +} + +#if B2_SIMD_WIDTH == 8 +#define B2_SIMD_SHIFT 3 +#elif B2_SIMD_WIDTH == 4 +#define B2_SIMD_SHIFT 2 +#else +#define B2_SIMD_SHIFT 0 +#endif + +// Solve with graph coloring +void b2Solve( b2World* world, b2StepContext* stepContext ) +{ + world->stepIndex += 1; + + // Merge islands + { + b2TracyCZoneNC( merge, "Merge", b2_colorLightGoldenRodYellow, true ); + uint64_t mergeTicks = b2GetTicks(); + + b2MergeAwakeIslands( world ); + + world->profile.mergeIslands = b2GetMilliseconds( mergeTicks ); + b2TracyCZoneEnd( merge ); + } + + // Are there any awake bodies? This scenario should not be important for profiling. + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + int awakeBodyCount = awakeSet->bodySims.count; + if ( awakeBodyCount == 0 ) + { + // Nothing to simulate, however the tree rebuild must be finished. + if ( world->userTreeTask != NULL ) + { + world->finishTaskFcn( world->userTreeTask, world->userTaskContext ); + world->userTreeTask = NULL; + world->activeTaskCount -= 1; + } + + b2ValidateNoEnlarged( &world->broadPhase ); + return; + } + + // Solve constraints using graph coloring + { + // Prepare buffers for bullets + b2AtomicStoreInt(&stepContext->bulletBodyCount, 0); + stepContext->bulletBodies = b2AllocateArenaItem( &world->arena, awakeBodyCount * sizeof( int ), "bullet bodies" ); + + b2TracyCZoneNC( prepare_stages, "Prepare Stages", b2_colorDarkOrange, true ); + uint64_t prepareTicks = b2GetTicks(); + + b2ConstraintGraph* graph = &world->constraintGraph; + b2GraphColor* colors = graph->colors; + + stepContext->sims = awakeSet->bodySims.data; + stepContext->states = awakeSet->bodyStates.data; + + // count contacts, joints, and colors + int awakeJointCount = 0; + int activeColorCount = 0; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT - 1; ++i ) + { + int perColorContactCount = colors[i].contactSims.count; + int perColorJointCount = colors[i].jointSims.count; + int occupancyCount = perColorContactCount + perColorJointCount; + activeColorCount += occupancyCount > 0 ? 1 : 0; + awakeJointCount += perColorJointCount; + } + + // prepare for move events + b2BodyMoveEventArray_Resize( &world->bodyMoveEvents, awakeBodyCount ); + + // Each worker receives at most M blocks of work. The workers may receive less blocks if there is not sufficient work. + // Each block of work has a minimum number of elements (block size). This in turn may limit the number of blocks. + // If there are many elements then the block size is increased so there are still at most M blocks of work per worker. + // M is a tunable number that has two goals: + // 1. keep M small to reduce overhead + // 2. keep M large enough for other workers to be able to steal work + // The block size is a power of two to make math efficient. + + int workerCount = world->workerCount; + const int blocksPerWorker = 4; + const int maxBlockCount = blocksPerWorker * workerCount; + + // Configure blocks for tasks that parallel-for bodies + int bodyBlockSize = 1 << 5; + int bodyBlockCount; + if ( awakeBodyCount > bodyBlockSize * maxBlockCount ) + { + // Too many blocks, increase block size + bodyBlockSize = awakeBodyCount / maxBlockCount; + bodyBlockCount = maxBlockCount; + } + else + { + bodyBlockCount = ( ( awakeBodyCount - 1 ) >> 5 ) + 1; + } + + // Configure blocks for tasks parallel-for each active graph color + // The blocks are a mix of SIMD contact blocks and joint blocks + int activeColorIndices[B2_GRAPH_COLOR_COUNT]; + + int colorContactCounts[B2_GRAPH_COLOR_COUNT]; + int colorContactBlockSizes[B2_GRAPH_COLOR_COUNT]; + int colorContactBlockCounts[B2_GRAPH_COLOR_COUNT]; + + int colorJointCounts[B2_GRAPH_COLOR_COUNT]; + int colorJointBlockSizes[B2_GRAPH_COLOR_COUNT]; + int colorJointBlockCounts[B2_GRAPH_COLOR_COUNT]; + + int graphBlockCount = 0; + + // c is the active color index + int simdContactCount = 0; + int c = 0; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT - 1; ++i ) + { + int colorContactCount = colors[i].contactSims.count; + int colorJointCount = colors[i].jointSims.count; + + if ( colorContactCount + colorJointCount > 0 ) + { + activeColorIndices[c] = i; + + // 4/8-way SIMD + int colorContactCountSIMD = colorContactCount > 0 ? ( ( colorContactCount - 1 ) >> B2_SIMD_SHIFT ) + 1 : 0; + + colorContactCounts[c] = colorContactCountSIMD; + + // determine the number of contact work blocks for this color + if ( colorContactCountSIMD > blocksPerWorker * maxBlockCount ) + { + // too many contact blocks + colorContactBlockSizes[c] = colorContactCountSIMD / maxBlockCount; + colorContactBlockCounts[c] = maxBlockCount; + } + else if ( colorContactCountSIMD > 0 ) + { + // dividing by blocksPerWorker (4) + colorContactBlockSizes[c] = blocksPerWorker; + colorContactBlockCounts[c] = ( ( colorContactCountSIMD - 1 ) >> 2 ) + 1; + } + else + { + // no contacts in this color + colorContactBlockSizes[c] = 0; + colorContactBlockCounts[c] = 0; + } + + colorJointCounts[c] = colorJointCount; + + // determine number of joint work blocks for this color + if ( colorJointCount > blocksPerWorker * maxBlockCount ) + { + // too many joint blocks + colorJointBlockSizes[c] = colorJointCount / maxBlockCount; + colorJointBlockCounts[c] = maxBlockCount; + } + else if ( colorJointCount > 0 ) + { + // dividing by blocksPerWorker (4) + colorJointBlockSizes[c] = blocksPerWorker; + colorJointBlockCounts[c] = ( ( colorJointCount - 1 ) >> 2 ) + 1; + } + else + { + colorJointBlockSizes[c] = 0; + colorJointBlockCounts[c] = 0; + } + + graphBlockCount += colorContactBlockCounts[c] + colorJointBlockCounts[c]; + simdContactCount += colorContactCountSIMD; + c += 1; + } + } + activeColorCount = c; + + // Gather contact pointers for easy parallel-for traversal. Some may be NULL due to SIMD remainders. + b2ContactSim** contacts = b2AllocateArenaItem( + &world->arena, B2_SIMD_WIDTH * simdContactCount * sizeof( b2ContactSim* ), "contact pointers" ); + + // Gather joint pointers for easy parallel-for traversal. + b2JointSim** joints = + b2AllocateArenaItem( &world->arena, awakeJointCount * sizeof( b2JointSim* ), "joint pointers" ); + + int simdConstraintSize = b2GetContactConstraintSIMDByteCount(); + b2ContactConstraintSIMD* simdContactConstraints = + b2AllocateArenaItem( &world->arena, simdContactCount * simdConstraintSize, "contact constraint" ); + + int overflowContactCount = colors[B2_OVERFLOW_INDEX].contactSims.count; + b2ContactConstraint* overflowContactConstraints = b2AllocateArenaItem( + &world->arena, overflowContactCount * sizeof( b2ContactConstraint ), "overflow contact constraint" ); + + graph->colors[B2_OVERFLOW_INDEX].overflowConstraints = overflowContactConstraints; + + // Distribute transient constraints to each graph color and build flat arrays of contact and joint pointers + { + int contactBase = 0; + int jointBase = 0; + for ( int i = 0; i < activeColorCount; ++i ) + { + int j = activeColorIndices[i]; + b2GraphColor* color = colors + j; + + int colorContactCount = color->contactSims.count; + + if ( colorContactCount == 0 ) + { + color->simdConstraints = NULL; + } + else + { + color->simdConstraints = + (b2ContactConstraintSIMD*)( (uint8_t*)simdContactConstraints + contactBase * simdConstraintSize ); + + for ( int k = 0; k < colorContactCount; ++k ) + { + contacts[B2_SIMD_WIDTH * contactBase + k] = color->contactSims.data + k; + } + + // remainder + int colorContactCountSIMD = ( ( colorContactCount - 1 ) >> B2_SIMD_SHIFT ) + 1; + for ( int k = colorContactCount; k < B2_SIMD_WIDTH * colorContactCountSIMD; ++k ) + { + contacts[B2_SIMD_WIDTH * contactBase + k] = NULL; + } + + contactBase += colorContactCountSIMD; + } + + int colorJointCount = color->jointSims.count; + for ( int k = 0; k < colorJointCount; ++k ) + { + joints[jointBase + k] = color->jointSims.data + k; + } + jointBase += colorJointCount; + } + + B2_ASSERT( contactBase == simdContactCount ); + B2_ASSERT( jointBase == awakeJointCount ); + } + + // Define work blocks for preparing contacts and storing contact impulses + int contactBlockSize = blocksPerWorker; + int contactBlockCount = simdContactCount > 0 ? ( ( simdContactCount - 1 ) >> 2 ) + 1 : 0; + if ( simdContactCount > contactBlockSize * maxBlockCount ) + { + // Too many blocks, increase block size + contactBlockSize = simdContactCount / maxBlockCount; + contactBlockCount = maxBlockCount; + } + + // Define work blocks for preparing joints + int jointBlockSize = blocksPerWorker; + int jointBlockCount = awakeJointCount > 0 ? ( ( awakeJointCount - 1 ) >> 2 ) + 1 : 0; + if ( awakeJointCount > jointBlockSize * maxBlockCount ) + { + // Too many blocks, increase block size + jointBlockSize = awakeJointCount / maxBlockCount; + jointBlockCount = maxBlockCount; + } + + int stageCount = 0; + + // b2_stagePrepareJoints + stageCount += 1; + // b2_stagePrepareContacts + stageCount += 1; + // b2_stageIntegrateVelocities + stageCount += 1; + // b2_stageWarmStart + stageCount += activeColorCount; + // b2_stageSolve + stageCount += activeColorCount; + // b2_stageIntegratePositions + stageCount += 1; + // b2_stageRelax + stageCount += activeColorCount; + // b2_stageRestitution + stageCount += activeColorCount; + // b2_stageStoreImpulses + stageCount += 1; + + b2SolverStage* stages = b2AllocateArenaItem( &world->arena, stageCount * sizeof( b2SolverStage ), "stages" ); + b2SolverBlock* bodyBlocks = + b2AllocateArenaItem( &world->arena, bodyBlockCount * sizeof( b2SolverBlock ), "body blocks" ); + b2SolverBlock* contactBlocks = + b2AllocateArenaItem( &world->arena, contactBlockCount * sizeof( b2SolverBlock ), "contact blocks" ); + b2SolverBlock* jointBlocks = + b2AllocateArenaItem( &world->arena, jointBlockCount * sizeof( b2SolverBlock ), "joint blocks" ); + b2SolverBlock* graphBlocks = + b2AllocateArenaItem( &world->arena, graphBlockCount * sizeof( b2SolverBlock ), "graph blocks" ); + + // Split an awake island. This modifies: + // - stack allocator + // - world island array and solver set + // - island indices on bodies, contacts, and joints + // I'm squeezing this task in here because it may be expensive and this is a safe place to put it. + // Note: cannot split islands in parallel with FinalizeBodies + void* splitIslandTask = NULL; + if ( world->splitIslandId != B2_NULL_INDEX ) + { + splitIslandTask = world->enqueueTaskFcn( &b2SplitIslandTask, 1, 1, world, world->userTaskContext ); + world->taskCount += 1; + world->activeTaskCount += splitIslandTask == NULL ? 0 : 1; + } + + // Prepare body work blocks + for ( int i = 0; i < bodyBlockCount; ++i ) + { + b2SolverBlock* block = bodyBlocks + i; + block->startIndex = i * bodyBlockSize; + block->count = (int16_t)bodyBlockSize; + block->blockType = b2_bodyBlock; + b2AtomicStoreInt(&block->syncIndex, 0); + } + bodyBlocks[bodyBlockCount - 1].count = (int16_t)( awakeBodyCount - ( bodyBlockCount - 1 ) * bodyBlockSize ); + + // Prepare joint work blocks + for ( int i = 0; i < jointBlockCount; ++i ) + { + b2SolverBlock* block = jointBlocks + i; + block->startIndex = i * jointBlockSize; + block->count = (int16_t)jointBlockSize; + block->blockType = b2_jointBlock; + b2AtomicStoreInt( &block->syncIndex, 0 ); + } + + if ( jointBlockCount > 0 ) + { + jointBlocks[jointBlockCount - 1].count = (int16_t)( awakeJointCount - ( jointBlockCount - 1 ) * jointBlockSize ); + } + + // Prepare contact work blocks + for ( int i = 0; i < contactBlockCount; ++i ) + { + b2SolverBlock* block = contactBlocks + i; + block->startIndex = i * contactBlockSize; + block->count = (int16_t)contactBlockSize; + block->blockType = b2_contactBlock; + b2AtomicStoreInt( &block->syncIndex, 0 ); + } + + if ( contactBlockCount > 0 ) + { + contactBlocks[contactBlockCount - 1].count = + (int16_t)( simdContactCount - ( contactBlockCount - 1 ) * contactBlockSize ); + } + + // Prepare graph work blocks + b2SolverBlock* graphColorBlocks[B2_GRAPH_COLOR_COUNT]; + b2SolverBlock* baseGraphBlock = graphBlocks; + + for ( int i = 0; i < activeColorCount; ++i ) + { + graphColorBlocks[i] = baseGraphBlock; + + int colorJointBlockCount = colorJointBlockCounts[i]; + int colorJointBlockSize = colorJointBlockSizes[i]; + for ( int j = 0; j < colorJointBlockCount; ++j ) + { + b2SolverBlock* block = baseGraphBlock + j; + block->startIndex = j * colorJointBlockSize; + block->count = (int16_t)colorJointBlockSize; + block->blockType = b2_graphJointBlock; + b2AtomicStoreInt( &block->syncIndex, 0 ); + } + + if ( colorJointBlockCount > 0 ) + { + baseGraphBlock[colorJointBlockCount - 1].count = + (int16_t)( colorJointCounts[i] - ( colorJointBlockCount - 1 ) * colorJointBlockSize ); + baseGraphBlock += colorJointBlockCount; + } + + int colorContactBlockCount = colorContactBlockCounts[i]; + int colorContactBlockSize = colorContactBlockSizes[i]; + for ( int j = 0; j < colorContactBlockCount; ++j ) + { + b2SolverBlock* block = baseGraphBlock + j; + block->startIndex = j * colorContactBlockSize; + block->count = (int16_t)colorContactBlockSize; + block->blockType = b2_graphContactBlock; + b2AtomicStoreInt( &block->syncIndex, 0 ); + } + + if ( colorContactBlockCount > 0 ) + { + baseGraphBlock[colorContactBlockCount - 1].count = + (int16_t)( colorContactCounts[i] - ( colorContactBlockCount - 1 ) * colorContactBlockSize ); + baseGraphBlock += colorContactBlockCount; + } + } + + B2_ASSERT( (ptrdiff_t)(baseGraphBlock - graphBlocks) == graphBlockCount ); + + b2SolverStage* stage = stages; + + // Prepare joints + stage->type = b2_stagePrepareJoints; + stage->blocks = jointBlocks; + stage->blockCount = jointBlockCount; + stage->colorIndex = -1; + b2AtomicStoreInt(&stage->completionCount, 0); + stage += 1; + + // Prepare contacts + stage->type = b2_stagePrepareContacts; + stage->blocks = contactBlocks; + stage->blockCount = contactBlockCount; + stage->colorIndex = -1; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + + // Integrate velocities + stage->type = b2_stageIntegrateVelocities; + stage->blocks = bodyBlocks; + stage->blockCount = bodyBlockCount; + stage->colorIndex = -1; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + + // Warm start + for ( int i = 0; i < activeColorCount; ++i ) + { + stage->type = b2_stageWarmStart; + stage->blocks = graphColorBlocks[i]; + stage->blockCount = colorJointBlockCounts[i] + colorContactBlockCounts[i]; + stage->colorIndex = activeColorIndices[i]; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + } + + // Solve graph + for ( int i = 0; i < activeColorCount; ++i ) + { + stage->type = b2_stageSolve; + stage->blocks = graphColorBlocks[i]; + stage->blockCount = colorJointBlockCounts[i] + colorContactBlockCounts[i]; + stage->colorIndex = activeColorIndices[i]; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + } + + // Integrate positions + stage->type = b2_stageIntegratePositions; + stage->blocks = bodyBlocks; + stage->blockCount = bodyBlockCount; + stage->colorIndex = -1; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + + // Relax constraints + for ( int i = 0; i < activeColorCount; ++i ) + { + stage->type = b2_stageRelax; + stage->blocks = graphColorBlocks[i]; + stage->blockCount = colorJointBlockCounts[i] + colorContactBlockCounts[i]; + stage->colorIndex = activeColorIndices[i]; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + } + + // Restitution + // Note: joint blocks mixed in, could have joint limit restitution + for ( int i = 0; i < activeColorCount; ++i ) + { + stage->type = b2_stageRestitution; + stage->blocks = graphColorBlocks[i]; + stage->blockCount = colorJointBlockCounts[i] + colorContactBlockCounts[i]; + stage->colorIndex = activeColorIndices[i]; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + } + + // Store impulses + stage->type = b2_stageStoreImpulses; + stage->blocks = contactBlocks; + stage->blockCount = contactBlockCount; + stage->colorIndex = -1; + b2AtomicStoreInt( &stage->completionCount, 0 ); + stage += 1; + + B2_ASSERT( (int)( stage - stages ) == stageCount ); + + B2_ASSERT( workerCount <= B2_MAX_WORKERS ); + b2WorkerContext workerContext[B2_MAX_WORKERS]; + + stepContext->graph = graph; + stepContext->joints = joints; + stepContext->contacts = contacts; + stepContext->simdContactConstraints = simdContactConstraints; + stepContext->activeColorCount = activeColorCount; + stepContext->workerCount = workerCount; + stepContext->stageCount = stageCount; + stepContext->stages = stages; + b2AtomicStoreU32(&stepContext->atomicSyncBits, 0); + + world->profile.prepareStages = b2GetMillisecondsAndReset( &prepareTicks ); + b2TracyCZoneEnd( prepare_stages ); + + b2TracyCZoneNC( solve_constraints, "Solve Constraints", b2_colorIndigo, true ); + uint64_t constraintTicks = b2GetTicks(); + + // Must use worker index because thread 0 can be assigned multiple tasks by enkiTS + for ( int i = 0; i < workerCount; ++i ) + { + workerContext[i].context = stepContext; + workerContext[i].workerIndex = i; + workerContext[i].userTask = world->enqueueTaskFcn( b2SolverTask, 1, 1, workerContext + i, world->userTaskContext ); + world->taskCount += 1; + world->activeTaskCount += workerContext[i].userTask == NULL ? 0 : 1; + } + + // Finish island split + if ( splitIslandTask != NULL ) + { + world->finishTaskFcn( splitIslandTask, world->userTaskContext ); + world->activeTaskCount -= 1; + } + world->splitIslandId = B2_NULL_INDEX; + + // Finish constraint solve + for ( int i = 0; i < workerCount; ++i ) + { + if ( workerContext[i].userTask != NULL ) + { + world->finishTaskFcn( workerContext[i].userTask, world->userTaskContext ); + world->activeTaskCount -= 1; + } + } + + world->profile.solveConstraints = b2GetMillisecondsAndReset( &constraintTicks ); + b2TracyCZoneEnd( solve_constraints ); + + b2TracyCZoneNC( update_transforms, "Update Transforms", b2_colorMediumSeaGreen, true ); + uint64_t transformTicks = b2GetTicks(); + + // Prepare contact, enlarged body, and island bit sets used in body finalization. + int awakeIslandCount = awakeSet->islandSims.count; + for ( int i = 0; i < world->workerCount; ++i ) + { + b2TaskContext* taskContext = world->taskContexts.data + i; + b2SetBitCountAndClear( &taskContext->enlargedSimBitSet, awakeBodyCount ); + b2SetBitCountAndClear( &taskContext->awakeIslandBitSet, awakeIslandCount ); + taskContext->splitIslandId = B2_NULL_INDEX; + taskContext->splitSleepTime = 0.0f; + } + + // Finalize bodies. Must happen after the constraint solver and after island splitting. + void* finalizeBodiesTask = + world->enqueueTaskFcn( b2FinalizeBodiesTask, awakeBodyCount, 64, stepContext, world->userTaskContext ); + world->taskCount += 1; + if ( finalizeBodiesTask != NULL ) + { + world->finishTaskFcn( finalizeBodiesTask, world->userTaskContext ); + } + + b2FreeArenaItem( &world->arena, graphBlocks ); + b2FreeArenaItem( &world->arena, jointBlocks ); + b2FreeArenaItem( &world->arena, contactBlocks ); + b2FreeArenaItem( &world->arena, bodyBlocks ); + b2FreeArenaItem( &world->arena, stages ); + b2FreeArenaItem( &world->arena, overflowContactConstraints ); + b2FreeArenaItem( &world->arena, simdContactConstraints ); + b2FreeArenaItem( &world->arena, joints ); + b2FreeArenaItem( &world->arena, contacts ); + + world->profile.transforms = b2GetMilliseconds( transformTicks ); + b2TracyCZoneEnd( update_transforms ); + } + + // Report hit events + // todo_erin perhaps optimize this with a bitset + // todo_erin perhaps do this in parallel with other work below + { + b2TracyCZoneNC( hit_events, "Hit Events", b2_colorRosyBrown, true ); + uint64_t hitTicks = b2GetTicks(); + + B2_ASSERT( world->contactHitEvents.count == 0 ); + + float threshold = world->hitEventThreshold; + b2GraphColor* colors = world->constraintGraph.colors; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + b2GraphColor* color = colors + i; + int contactCount = color->contactSims.count; + b2ContactSim* contactSims = color->contactSims.data; + for ( int j = 0; j < contactCount; ++j ) + { + b2ContactSim* contactSim = contactSims + j; + if ( ( contactSim->simFlags & b2_simEnableHitEvent ) == 0 ) + { + continue; + } + + b2ContactHitEvent event = { 0 }; + event.approachSpeed = threshold; + + bool hit = false; + int pointCount = contactSim->manifold.pointCount; + for ( int k = 0; k < pointCount; ++k ) + { + b2ManifoldPoint* mp = contactSim->manifold.points + k; + float approachSpeed = -mp->normalVelocity; + + // Need to check total impulse because the point may be speculative and not colliding + if ( approachSpeed > event.approachSpeed && mp->totalNormalImpulse > 0.0f ) + { + event.approachSpeed = approachSpeed; + event.point = mp->point; + hit = true; + } + } + + if ( hit == true ) + { + event.normal = contactSim->manifold.normal; + + b2Shape* shapeA = b2ShapeArray_Get( &world->shapes, contactSim->shapeIdA ); + b2Shape* shapeB = b2ShapeArray_Get( &world->shapes, contactSim->shapeIdB ); + + event.shapeIdA = ( b2ShapeId ){ shapeA->id + 1, world->worldId, shapeA->generation }; + event.shapeIdB = ( b2ShapeId ){ shapeB->id + 1, world->worldId, shapeB->generation }; + + b2ContactHitEventArray_Push( &world->contactHitEvents, event ); + } + } + } + + world->profile.hitEvents = b2GetMilliseconds( hitTicks ); + b2TracyCZoneEnd( hit_events ); + } + + { + b2TracyCZoneNC( refit_bvh, "Refit BVH", b2_colorFireBrick, true ); + uint64_t refitTicks = b2GetTicks(); + + // Finish the user tree task that was queued earlier in the time step. This must be complete before touching the + // broad-phase. + if ( world->userTreeTask != NULL ) + { + world->finishTaskFcn( world->userTreeTask, world->userTaskContext ); + world->userTreeTask = NULL; + world->activeTaskCount -= 1; + } + + b2ValidateNoEnlarged( &world->broadPhase ); + + // Gather bits for all sim bodies that have enlarged AABBs + b2BitSet* enlargedBodyBitSet = &world->taskContexts.data[0].enlargedSimBitSet; + for ( int i = 1; i < world->workerCount; ++i ) + { + b2InPlaceUnion( enlargedBodyBitSet, &world->taskContexts.data[i].enlargedSimBitSet ); + } + + // Enlarge broad-phase proxies and build move array + // Apply shape AABB changes to broad-phase. This also create the move array which must be + // in deterministic order. I'm tracking sim bodies because the number of shape ids can be huge. + // This has to happen before bullets are processed. + { + b2BroadPhase* broadPhase = &world->broadPhase; + uint32_t wordCount = enlargedBodyBitSet->blockCount; + uint64_t* bits = enlargedBodyBitSet->bits; + + // Fast array access is important here + b2Body* bodyArray = world->bodies.data; + b2BodySim* bodySimArray = awakeSet->bodySims.data; + b2Shape* shapeArray = world->shapes.data; + + for ( uint32_t k = 0; k < wordCount; ++k ) + { + uint64_t word = bits[k]; + while ( word != 0 ) + { + uint32_t ctz = b2CTZ64( word ); + uint32_t bodySimIndex = 64 * k + ctz; + + b2BodySim* bodySim = bodySimArray + bodySimIndex; + + b2Body* body = bodyArray + bodySim->bodyId; + + int shapeId = body->headShapeId; + if ( bodySim->isBullet && bodySim->isFast ) + { + // Fast bullet bodies don't have their final AABB yet + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = shapeArray + shapeId; + + // Shape is fast. It's aabb will be enlarged in continuous collision. + // Update the move array here for determinism because bullets are processed + // below in non-deterministic order. + b2BufferMove( broadPhase, shape->proxyKey ); + + shapeId = shape->nextShapeId; + } + } + else + { + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = shapeArray + shapeId; + + // The AABB may not have been enlarged, despite the body being flagged as enlarged. + // For example, a body with multiple shapes may have not have all shapes enlarged. + // A fast body may have been flagged as enlarged despite having no shapes enlarged. + if ( shape->enlargedAABB ) + { + b2BroadPhase_EnlargeProxy( broadPhase, shape->proxyKey, shape->fatAABB ); + shape->enlargedAABB = false; + } + + shapeId = shape->nextShapeId; + } + } + + // Clear the smallest set bit + word = word & ( word - 1 ); + } + } + } + + b2ValidateBroadphase( &world->broadPhase ); + + world->profile.refit = b2GetMilliseconds( refitTicks ); + b2TracyCZoneEnd( refit_bvh ); + } + + int bulletBodyCount = b2AtomicLoadInt( &stepContext->bulletBodyCount ); + if ( bulletBodyCount > 0 ) + { + b2TracyCZoneNC( bullets, "Bullets", b2_colorLightYellow, true ); + uint64_t bulletTicks = b2GetTicks(); + + // Fast bullet bodies + // Note: a bullet body may be moving slow + int minRange = 8; + void* userBulletBodyTask = world->enqueueTaskFcn( &b2BulletBodyTask, bulletBodyCount, minRange, stepContext, + world->userTaskContext ); + world->taskCount += 1; + if ( userBulletBodyTask != NULL ) + { + world->finishTaskFcn( userBulletBodyTask, world->userTaskContext ); + } + + // Serially enlarge broad-phase proxies for bullet shapes + b2BroadPhase* broadPhase = &world->broadPhase; + b2DynamicTree* dynamicTree = broadPhase->trees + b2_dynamicBody; + + // Fast array access is important here + b2Body* bodyArray = world->bodies.data; + b2BodySim* bodySimArray = awakeSet->bodySims.data; + b2Shape* shapeArray = world->shapes.data; + + // Serially enlarge broad-phase proxies for bullet shapes + int* bulletBodySimIndices = stepContext->bulletBodies; + + // This loop has non-deterministic order but it shouldn't affect the result + for ( int i = 0; i < bulletBodyCount; ++i ) + { + b2BodySim* bulletBodySim = bodySimArray + bulletBodySimIndices[i]; + if ( bulletBodySim->enlargeAABB == false ) + { + continue; + } + + // clear flag + bulletBodySim->enlargeAABB = false; + + int bodyId = bulletBodySim->bodyId; + B2_ASSERT( 0 <= bodyId && bodyId < world->bodies.count ); + b2Body* bulletBody = bodyArray + bodyId; + + int shapeId = bulletBody->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = shapeArray + shapeId; + if ( shape->enlargedAABB == false ) + { + shapeId = shape->nextShapeId; + continue; + } + + // clear flag + shape->enlargedAABB = false; + + int proxyKey = shape->proxyKey; + int proxyId = B2_PROXY_ID( proxyKey ); + B2_ASSERT( B2_PROXY_TYPE( proxyKey ) == b2_dynamicBody ); + + // all fast bullet shapes should already be in the move buffer + B2_ASSERT( b2ContainsKey( &broadPhase->moveSet, proxyKey + 1 ) ); + + b2DynamicTree_EnlargeProxy( dynamicTree, proxyId, shape->fatAABB ); + + shapeId = shape->nextShapeId; + } + } + + world->profile.bullets = b2GetMilliseconds( bulletTicks ); + b2TracyCZoneEnd( bullets ); + } + + // Need to free this even if no bullets got processed. + b2FreeArenaItem( &world->arena, stepContext->bulletBodies ); + stepContext->bulletBodies = NULL; + b2AtomicStoreInt(&stepContext->bulletBodyCount, 0); + + // Island sleeping + // This must be done last because putting islands to sleep invalidates the enlarged body bits. + // todo_erin figure out how to do this in parallel with tree refit + if ( world->enableSleep == true ) + { + b2TracyCZoneNC( sleep_islands, "Island Sleep", b2_colorLightSlateGray, true ); + uint64_t sleepTicks = b2GetTicks(); + + // Collect split island candidate for the next time step. No need to split if sleeping is disabled. + B2_ASSERT( world->splitIslandId == B2_NULL_INDEX ); + float splitSleepTimer = 0.0f; + for ( int i = 0; i < world->workerCount; ++i ) + { + b2TaskContext* taskContext = world->taskContexts.data + i; + if ( taskContext->splitIslandId != B2_NULL_INDEX && taskContext->splitSleepTime >= splitSleepTimer ) + { + B2_ASSERT( taskContext->splitSleepTime > 0.0f ); + + // Tie breaking for determinism. Largest island id wins. Needed due to work stealing. + if ( taskContext->splitSleepTime == splitSleepTimer && taskContext->splitIslandId < world->splitIslandId ) + { + continue; + } + + world->splitIslandId = taskContext->splitIslandId; + splitSleepTimer = taskContext->splitSleepTime; + } + } + + b2BitSet* awakeIslandBitSet = &world->taskContexts.data[0].awakeIslandBitSet; + for ( int i = 1; i < world->workerCount; ++i ) + { + b2InPlaceUnion( awakeIslandBitSet, &world->taskContexts.data[i].awakeIslandBitSet ); + } + + // Need to process in reverse because this moves islands to sleeping solver sets. + b2IslandSim* islands = awakeSet->islandSims.data; + int count = awakeSet->islandSims.count; + for ( int islandIndex = count - 1; islandIndex >= 0; islandIndex -= 1 ) + { + if ( b2GetBit( awakeIslandBitSet, islandIndex ) == true ) + { + // this island is still awake + continue; + } + + b2IslandSim* island = islands + islandIndex; + int islandId = island->islandId; + + b2TrySleepIsland( world, islandId ); + } + + b2ValidateSolverSets( world ); + + world->profile.sleepIslands = b2GetMilliseconds( sleepTicks ); + b2TracyCZoneEnd( sleep_islands ); + } +} diff --git a/3rdparty/box2d/src/solver.h b/3rdparty/box2d/src/solver.h new file mode 100644 index 000000000000..2a2d4a13e38d --- /dev/null +++ b/3rdparty/box2d/src/solver.h @@ -0,0 +1,155 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/math_functions.h" + +#include "core.h" + +#include +#include + +typedef struct b2BodySim b2BodySim; +typedef struct b2BodyState b2BodyState; +typedef struct b2ContactSim b2ContactSim; +typedef struct b2JointSim b2JointSim; +typedef struct b2World b2World; + +typedef struct b2Softness +{ + float biasRate; + float massScale; + float impulseScale; +} b2Softness; + +typedef enum b2SolverStageType +{ + b2_stagePrepareJoints, + b2_stagePrepareContacts, + b2_stageIntegrateVelocities, + b2_stageWarmStart, + b2_stageSolve, + b2_stageIntegratePositions, + b2_stageRelax, + b2_stageRestitution, + b2_stageStoreImpulses +} b2SolverStageType; + +typedef enum b2SolverBlockType +{ + b2_bodyBlock, + b2_jointBlock, + b2_contactBlock, + b2_graphJointBlock, + b2_graphContactBlock +} b2SolverBlockType; + +// Each block of work has a sync index that gets incremented when a worker claims the block. This ensures only a single worker +// claims a block, yet lets work be distributed dynamically across multiple workers (work stealing). This also reduces contention +// on a single block index atomic. For non-iterative stages the sync index is simply set to one. For iterative stages (solver +// iteration) the same block of work is executed once per iteration and the atomic sync index is shared across iterations, so it +// increases monotonically. +typedef struct b2SolverBlock +{ + int startIndex; + int16_t count; + int16_t blockType; // b2SolverBlockType + // todo consider false sharing of this atomic + b2AtomicInt syncIndex; +} b2SolverBlock; + +// Each stage must be completed before going to the next stage. +// Non-iterative stages use a stage instance once while iterative stages re-use the same instance each iteration. +typedef struct b2SolverStage +{ + b2SolverStageType type; + b2SolverBlock* blocks; + int blockCount; + int colorIndex; + // todo consider false sharing of this atomic + b2AtomicInt completionCount; +} b2SolverStage; + +// Context for a time step. Recreated each time step. +typedef struct b2StepContext +{ + // time step + float dt; + + // inverse time step (0 if dt == 0). + float inv_dt; + + // sub-step + float h; + float inv_h; + + int subStepCount; + + b2Softness jointSoftness; + b2Softness contactSoftness; + b2Softness staticSoftness; + + float restitutionThreshold; + float maxLinearVelocity; + + struct b2World* world; + struct b2ConstraintGraph* graph; + + // shortcut to body states from awake set + b2BodyState* states; + + // shortcut to body sims from awake set + b2BodySim* sims; + + // array of all shape ids for shapes that have enlarged AABBs + int* enlargedShapes; + int enlargedShapeCount; + + // Array of bullet bodies that need continuous collision handling + int* bulletBodies; + b2AtomicInt bulletBodyCount; + + // joint pointers for simplified parallel-for access. + b2JointSim** joints; + + // contact pointers for simplified parallel-for access. + // - parallel-for collide with no gaps + // - parallel-for prepare and store contacts with NULL gaps for SIMD remainders + // despite being an array of pointers, these are contiguous sub-arrays corresponding + // to constraint graph colors + b2ContactSim** contacts; + + struct b2ContactConstraintSIMD* simdContactConstraints; + int activeColorCount; + int workerCount; + + b2SolverStage* stages; + int stageCount; + bool enableWarmStarting; + + // todo padding to prevent false sharing + char dummy1[64]; + + // sync index (16-bits) | stage type (16-bits) + b2AtomicU32 atomicSyncBits; + + char dummy2[64]; + +} b2StepContext; + +static inline b2Softness b2MakeSoft( float hertz, float zeta, float h ) +{ + if ( hertz == 0.0f ) + { + return ( b2Softness ){ 0.0f, 1.0f, 0.0f }; + } + + float omega = 2.0f * B2_PI * hertz; + float a1 = 2.0f * zeta + h * omega; + float a2 = h * omega * a1; + float a3 = 1.0f / ( 1.0f + a2 ); + return ( b2Softness ){ omega / a1, a2 * a3, a3 }; +} + +void b2Solve( b2World* world, b2StepContext* stepContext ); diff --git a/3rdparty/box2d/src/solver_set.c b/3rdparty/box2d/src/solver_set.c new file mode 100644 index 000000000000..cbc7553cb4f4 --- /dev/null +++ b/3rdparty/box2d/src/solver_set.c @@ -0,0 +1,613 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "solver_set.h" + +#include "body.h" +#include "constraint_graph.h" +#include "contact.h" +#include "core.h" +#include "island.h" +#include "joint.h" +#include "world.h" + +#include + +B2_ARRAY_SOURCE( b2SolverSet, b2SolverSet ) + +void b2DestroySolverSet( b2World* world, int setIndex ) +{ + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + b2BodySimArray_Destroy( &set->bodySims ); + b2BodyStateArray_Destroy( &set->bodyStates ); + b2ContactSimArray_Destroy( &set->contactSims ); + b2JointSimArray_Destroy( &set->jointSims ); + b2IslandSimArray_Destroy( &set->islandSims ); + b2FreeId( &world->solverSetIdPool, setIndex ); + *set = ( b2SolverSet ){ 0 }; + set->setIndex = B2_NULL_INDEX; +} + +// Wake a solver set. Does not merge islands. +// Contacts can be in several places: +// 1. non-touching contacts in the disabled set +// 2. non-touching contacts already in the awake set +// 3. touching contacts in the sleeping set +// This handles contact types 1 and 3. Type 2 doesn't need any action. +void b2WakeSolverSet( b2World* world, int setIndex ) +{ + B2_ASSERT( setIndex >= b2_firstSleepingSet ); + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2SolverSet* disabledSet = b2SolverSetArray_Get( &world->solverSets, b2_disabledSet ); + + b2Body* bodies = world->bodies.data; + + int bodyCount = set->bodySims.count; + for ( int i = 0; i < bodyCount; ++i ) + { + b2BodySim* simSrc = set->bodySims.data + i; + + b2Body* body = bodies + simSrc->bodyId; + B2_ASSERT( body->setIndex == setIndex ); + body->setIndex = b2_awakeSet; + body->localIndex = awakeSet->bodySims.count; + + // Reset sleep timer + body->sleepTime = 0.0f; + + b2BodySim* simDst = b2BodySimArray_Add( &awakeSet->bodySims ); + memcpy( simDst, simSrc, sizeof( b2BodySim ) ); + + b2BodyState* state = b2BodyStateArray_Add( &awakeSet->bodyStates ); + *state = b2_identityBodyState; + + // move non-touching contacts from disabled set to awake set + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int edgeIndex = contactKey & 1; + int contactId = contactKey >> 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + + contactKey = contact->edges[edgeIndex].nextKey; + + if ( contact->setIndex != b2_disabledSet ) + { + B2_ASSERT( contact->setIndex == b2_awakeSet || contact->setIndex == setIndex ); + continue; + } + + int localIndex = contact->localIndex; + b2ContactSim* contactSim = b2ContactSimArray_Get( &disabledSet->contactSims, localIndex ); + + B2_ASSERT( ( contact->flags & b2_contactTouchingFlag ) == 0 && contactSim->manifold.pointCount == 0 ); + + contact->setIndex = b2_awakeSet; + contact->localIndex = awakeSet->contactSims.count; + b2ContactSim* awakeContactSim = b2ContactSimArray_Add( &awakeSet->contactSims ); + memcpy( awakeContactSim, contactSim, sizeof( b2ContactSim ) ); + + int movedLocalIndex = b2ContactSimArray_RemoveSwap( &disabledSet->contactSims, localIndex ); + if ( movedLocalIndex != B2_NULL_INDEX ) + { + // fix moved element + b2ContactSim* movedContactSim = disabledSet->contactSims.data + localIndex; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedContactSim->contactId ); + B2_ASSERT( movedContact->localIndex == movedLocalIndex ); + movedContact->localIndex = localIndex; + } + } + } + + // transfer touching contacts from sleeping set to contact graph + { + int contactCount = set->contactSims.count; + for ( int i = 0; i < contactCount; ++i ) + { + b2ContactSim* contactSim = set->contactSims.data + i; + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactSim->contactId ); + B2_ASSERT( contact->flags & b2_contactTouchingFlag ); + B2_ASSERT( contactSim->simFlags & b2_simTouchingFlag ); + B2_ASSERT( contactSim->manifold.pointCount > 0 ); + B2_ASSERT( contact->setIndex == setIndex ); + b2AddContactToGraph( world, contactSim, contact ); + contact->setIndex = b2_awakeSet; + } + } + + // transfer joints from sleeping set to awake set + { + int jointCount = set->jointSims.count; + for ( int i = 0; i < jointCount; ++i ) + { + b2JointSim* jointSim = set->jointSims.data + i; + b2Joint* joint = b2JointArray_Get( &world->joints, jointSim->jointId ); + B2_ASSERT( joint->setIndex == setIndex ); + b2AddJointToGraph( world, jointSim, joint ); + joint->setIndex = b2_awakeSet; + } + } + + // transfer island from sleeping set to awake set + // Usually a sleeping set has only one island, but it is possible + // that joints are created between sleeping islands and they + // are moved to the same sleeping set. + { + int islandCount = set->islandSims.count; + for ( int i = 0; i < islandCount; ++i ) + { + b2IslandSim* islandSrc = set->islandSims.data + i; + b2Island* island = b2IslandArray_Get( &world->islands, islandSrc->islandId ); + island->setIndex = b2_awakeSet; + island->localIndex = awakeSet->islandSims.count; + b2IslandSim* islandDst = b2IslandSimArray_Add( &awakeSet->islandSims ); + memcpy( islandDst, islandSrc, sizeof( b2IslandSim ) ); + } + } + + // destroy the sleeping set + b2DestroySolverSet( world, setIndex ); + + b2ValidateSolverSets( world ); +} + +void b2TrySleepIsland( b2World* world, int islandId ) +{ + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + B2_ASSERT( island->setIndex == b2_awakeSet ); + + // cannot put an island to sleep while it has a pending split + if ( island->constraintRemoveCount > 0 ) + { + return; + } + + // island is sleeping + // - create new sleeping solver set + // - move island to sleeping solver set + // - identify non-touching contacts that should move to sleeping solver set or disabled set + // - remove old island + // - fix island + int sleepSetId = b2AllocId( &world->solverSetIdPool ); + if ( sleepSetId == world->solverSets.count ) + { + b2SolverSet set = { 0 }; + set.setIndex = B2_NULL_INDEX; + b2SolverSetArray_Push( &world->solverSets, set ); + } + + b2SolverSet* sleepSet = b2SolverSetArray_Get( &world->solverSets, sleepSetId ); + *sleepSet = ( b2SolverSet ){ 0 }; + + // grab awake set after creating the sleep set because the solver set array may have been resized + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + B2_ASSERT( 0 <= island->localIndex && island->localIndex < awakeSet->islandSims.count ); + + sleepSet->setIndex = sleepSetId; + sleepSet->bodySims = b2BodySimArray_Create( island->bodyCount ); + sleepSet->contactSims = b2ContactSimArray_Create( island->contactCount ); + sleepSet->jointSims = b2JointSimArray_Create( island->jointCount ); + + // move awake bodies to sleeping set + // this shuffles around bodies in the awake set + { + b2SolverSet* disabledSet = b2SolverSetArray_Get( &world->solverSets, b2_disabledSet ); + int bodyId = island->headBody; + while ( bodyId != B2_NULL_INDEX ) + { + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + B2_ASSERT( body->setIndex == b2_awakeSet ); + B2_ASSERT( body->islandId == islandId ); + + // Update the body move event to indicate this body fell asleep + // It could happen the body is forced asleep before it ever moves. + if ( body->bodyMoveIndex != B2_NULL_INDEX ) + { + b2BodyMoveEvent* moveEvent = b2BodyMoveEventArray_Get( &world->bodyMoveEvents, body->bodyMoveIndex ); + B2_ASSERT( moveEvent->bodyId.index1 - 1 == bodyId ); + B2_ASSERT( moveEvent->bodyId.generation == body->generation ); + moveEvent->fellAsleep = true; + body->bodyMoveIndex = B2_NULL_INDEX; + } + + int awakeBodyIndex = body->localIndex; + b2BodySim* awakeSim = b2BodySimArray_Get( &awakeSet->bodySims, awakeBodyIndex ); + + // move body sim to sleep set + int sleepBodyIndex = sleepSet->bodySims.count; + b2BodySim* sleepBodySim = b2BodySimArray_Add( &sleepSet->bodySims ); + memcpy( sleepBodySim, awakeSim, sizeof( b2BodySim ) ); + + int movedIndex = b2BodySimArray_RemoveSwap( &awakeSet->bodySims, awakeBodyIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // fix local index on moved element + b2BodySim* movedSim = awakeSet->bodySims.data + awakeBodyIndex; + int movedId = movedSim->bodyId; + b2Body* movedBody = b2BodyArray_Get( &world->bodies, movedId ); + B2_ASSERT( movedBody->localIndex == movedIndex ); + movedBody->localIndex = awakeBodyIndex; + } + + // destroy state, no need to clone + b2BodyStateArray_RemoveSwap( &awakeSet->bodyStates, awakeBodyIndex ); + + body->setIndex = sleepSetId; + body->localIndex = sleepBodyIndex; + + // Move non-touching contacts to the disabled set. + // Non-touching contacts may exist between sleeping islands and there is no clear ownership. + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + + B2_ASSERT( contact->setIndex == b2_awakeSet || contact->setIndex == b2_disabledSet ); + contactKey = contact->edges[edgeIndex].nextKey; + + if ( contact->setIndex == b2_disabledSet ) + { + // already moved to disabled set by another body in the island + continue; + } + + if ( contact->colorIndex != B2_NULL_INDEX ) + { + // contact is touching and will be moved separately + B2_ASSERT( ( contact->flags & b2_contactTouchingFlag ) != 0 ); + continue; + } + + // the other body may still be awake, it still may go to sleep and then it will be responsible + // for moving this contact to the disabled set. + int otherEdgeIndex = edgeIndex ^ 1; + int otherBodyId = contact->edges[otherEdgeIndex].bodyId; + b2Body* otherBody = b2BodyArray_Get( &world->bodies, otherBodyId ); + if ( otherBody->setIndex == b2_awakeSet ) + { + continue; + } + + int localIndex = contact->localIndex; + b2ContactSim* contactSim = b2ContactSimArray_Get( &awakeSet->contactSims, localIndex ); + + B2_ASSERT( contactSim->manifold.pointCount == 0 ); + B2_ASSERT( ( contact->flags & b2_contactTouchingFlag ) == 0 ); + + // move the non-touching contact to the disabled set + contact->setIndex = b2_disabledSet; + contact->localIndex = disabledSet->contactSims.count; + b2ContactSim* disabledContactSim = b2ContactSimArray_Add( &disabledSet->contactSims ); + memcpy( disabledContactSim, contactSim, sizeof( b2ContactSim ) ); + + int movedLocalIndex = b2ContactSimArray_RemoveSwap( &awakeSet->contactSims, localIndex ); + if ( movedLocalIndex != B2_NULL_INDEX ) + { + // fix moved element + b2ContactSim* movedContactSim = awakeSet->contactSims.data + localIndex; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedContactSim->contactId ); + B2_ASSERT( movedContact->localIndex == movedLocalIndex ); + movedContact->localIndex = localIndex; + } + } + + bodyId = body->islandNext; + } + } + + // move touching contacts + // this shuffles contacts in the awake set + { + int contactId = island->headContact; + while ( contactId != B2_NULL_INDEX ) + { + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + B2_ASSERT( contact->setIndex == b2_awakeSet ); + B2_ASSERT( contact->islandId == islandId ); + int colorIndex = contact->colorIndex; + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + + b2GraphColor* color = world->constraintGraph.colors + colorIndex; + + // Remove bodies from graph coloring associated with this constraint + if ( colorIndex != B2_OVERFLOW_INDEX ) + { + // might clear a bit for a static body, but this has no effect + b2ClearBit( &color->bodySet, contact->edges[0].bodyId ); + b2ClearBit( &color->bodySet, contact->edges[1].bodyId ); + } + + int localIndex = contact->localIndex; + b2ContactSim* awakeContactSim = b2ContactSimArray_Get( &color->contactSims, localIndex ); + + int sleepContactIndex = sleepSet->contactSims.count; + b2ContactSim* sleepContactSim = b2ContactSimArray_Add( &sleepSet->contactSims ); + memcpy( sleepContactSim, awakeContactSim, sizeof( b2ContactSim ) ); + + int movedLocalIndex = b2ContactSimArray_RemoveSwap( &color->contactSims, localIndex ); + if ( movedLocalIndex != B2_NULL_INDEX ) + { + // fix moved element + b2ContactSim* movedContactSim = color->contactSims.data + localIndex; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedContactSim->contactId ); + B2_ASSERT( movedContact->localIndex == movedLocalIndex ); + movedContact->localIndex = localIndex; + } + + contact->setIndex = sleepSetId; + contact->colorIndex = B2_NULL_INDEX; + contact->localIndex = sleepContactIndex; + + contactId = contact->islandNext; + } + } + + // move joints + // this shuffles joints in the awake set + { + int jointId = island->headJoint; + while ( jointId != B2_NULL_INDEX ) + { + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + B2_ASSERT( joint->setIndex == b2_awakeSet ); + B2_ASSERT( joint->islandId == islandId ); + int colorIndex = joint->colorIndex; + int localIndex = joint->localIndex; + + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + + b2GraphColor* color = world->constraintGraph.colors + colorIndex; + + b2JointSim* awakeJointSim = b2JointSimArray_Get( &color->jointSims, localIndex ); + + if ( colorIndex != B2_OVERFLOW_INDEX ) + { + // might clear a bit for a static body, but this has no effect + b2ClearBit( &color->bodySet, joint->edges[0].bodyId ); + b2ClearBit( &color->bodySet, joint->edges[1].bodyId ); + } + + int sleepJointIndex = sleepSet->jointSims.count; + b2JointSim* sleepJointSim = b2JointSimArray_Add( &sleepSet->jointSims ); + memcpy( sleepJointSim, awakeJointSim, sizeof( b2JointSim ) ); + + int movedIndex = b2JointSimArray_RemoveSwap( &color->jointSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // fix moved element + b2JointSim* movedJointSim = color->jointSims.data + localIndex; + int movedId = movedJointSim->jointId; + b2Joint* movedJoint = b2JointArray_Get( &world->joints, movedId ); + B2_ASSERT( movedJoint->localIndex == movedIndex ); + movedJoint->localIndex = localIndex; + } + + joint->setIndex = sleepSetId; + joint->colorIndex = B2_NULL_INDEX; + joint->localIndex = sleepJointIndex; + + jointId = joint->islandNext; + } + } + + // move island struct + { + B2_ASSERT( island->setIndex == b2_awakeSet ); + + int islandIndex = island->localIndex; + b2IslandSim* sleepIsland = b2IslandSimArray_Add( &sleepSet->islandSims ); + sleepIsland->islandId = islandId; + + int movedIslandIndex = b2IslandSimArray_RemoveSwap( &awakeSet->islandSims, islandIndex ); + if ( movedIslandIndex != B2_NULL_INDEX ) + { + // fix index on moved element + b2IslandSim* movedIslandSim = awakeSet->islandSims.data + islandIndex; + int movedIslandId = movedIslandSim->islandId; + b2Island* movedIsland = b2IslandArray_Get( &world->islands, movedIslandId ); + B2_ASSERT( movedIsland->localIndex == movedIslandIndex ); + movedIsland->localIndex = islandIndex; + } + + island->setIndex = sleepSetId; + island->localIndex = 0; + } + + b2ValidateSolverSets( world ); +} + +// This is called when joints are created between sets. I want to allow the sets +// to continue sleeping if both are asleep. Otherwise one set is waked. +// Islands will get merge when the set is waked. +void b2MergeSolverSets( b2World* world, int setId1, int setId2 ) +{ + B2_ASSERT( setId1 >= b2_firstSleepingSet ); + B2_ASSERT( setId2 >= b2_firstSleepingSet ); + b2SolverSet* set1 = b2SolverSetArray_Get( &world->solverSets, setId1 ); + b2SolverSet* set2 = b2SolverSetArray_Get( &world->solverSets, setId2 ); + + // Move the fewest number of bodies + if ( set1->bodySims.count < set2->bodySims.count ) + { + b2SolverSet* tempSet = set1; + set1 = set2; + set2 = tempSet; + + int tempId = setId1; + setId1 = setId2; + setId2 = tempId; + } + + // transfer bodies + { + b2Body* bodies = world->bodies.data; + int bodyCount = set2->bodySims.count; + for ( int i = 0; i < bodyCount; ++i ) + { + b2BodySim* simSrc = set2->bodySims.data + i; + + b2Body* body = bodies + simSrc->bodyId; + B2_ASSERT( body->setIndex == setId2 ); + body->setIndex = setId1; + body->localIndex = set1->bodySims.count; + + b2BodySim* simDst = b2BodySimArray_Add( &set1->bodySims ); + memcpy( simDst, simSrc, sizeof( b2BodySim ) ); + } + } + + // transfer contacts + { + int contactCount = set2->contactSims.count; + for ( int i = 0; i < contactCount; ++i ) + { + b2ContactSim* contactSrc = set2->contactSims.data + i; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactSrc->contactId ); + B2_ASSERT( contact->setIndex == setId2 ); + contact->setIndex = setId1; + contact->localIndex = set1->contactSims.count; + + b2ContactSim* contactDst = b2ContactSimArray_Add( &set1->contactSims ); + memcpy( contactDst, contactSrc, sizeof( b2ContactSim ) ); + } + } + + // transfer joints + { + int jointCount = set2->jointSims.count; + for ( int i = 0; i < jointCount; ++i ) + { + b2JointSim* jointSrc = set2->jointSims.data + i; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointSrc->jointId ); + B2_ASSERT( joint->setIndex == setId2 ); + joint->setIndex = setId1; + joint->localIndex = set1->jointSims.count; + + b2JointSim* jointDst = b2JointSimArray_Add( &set1->jointSims ); + memcpy( jointDst, jointSrc, sizeof( b2JointSim ) ); + } + } + + // transfer islands + { + int islandCount = set2->islandSims.count; + for ( int i = 0; i < islandCount; ++i ) + { + b2IslandSim* islandSrc = set2->islandSims.data + i; + int islandId = islandSrc->islandId; + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + island->setIndex = setId1; + island->localIndex = set1->islandSims.count; + + b2IslandSim* islandDst = b2IslandSimArray_Add( &set1->islandSims ); + memcpy( islandDst, islandSrc, sizeof( b2IslandSim ) ); + } + } + + // destroy the merged set + b2DestroySolverSet( world, setId2 ); + + b2ValidateSolverSets( world ); +} + +void b2TransferBody( b2World* world, b2SolverSet* targetSet, b2SolverSet* sourceSet, b2Body* body ) +{ + B2_ASSERT( targetSet != sourceSet ); + + int sourceIndex = body->localIndex; + b2BodySim* sourceSim = b2BodySimArray_Get( &sourceSet->bodySims, sourceIndex ); + + int targetIndex = targetSet->bodySims.count; + b2BodySim* targetSim = b2BodySimArray_Add( &targetSet->bodySims ); + memcpy( targetSim, sourceSim, sizeof( b2BodySim ) ); + + // Remove body sim from solver set that owns it + int movedIndex = b2BodySimArray_RemoveSwap( &sourceSet->bodySims, sourceIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // Fix moved body index + b2BodySim* movedSim = sourceSet->bodySims.data + sourceIndex; + int movedId = movedSim->bodyId; + b2Body* movedBody = b2BodyArray_Get( &world->bodies, movedId ); + B2_ASSERT( movedBody->localIndex == movedIndex ); + movedBody->localIndex = sourceIndex; + } + + if ( sourceSet->setIndex == b2_awakeSet ) + { + b2BodyStateArray_RemoveSwap( &sourceSet->bodyStates, sourceIndex ); + } + else if ( targetSet->setIndex == b2_awakeSet ) + { + b2BodyState* state = b2BodyStateArray_Add( &targetSet->bodyStates ); + *state = b2_identityBodyState; + } + + body->setIndex = targetSet->setIndex; + body->localIndex = targetIndex; +} + +void b2TransferJoint( b2World* world, b2SolverSet* targetSet, b2SolverSet* sourceSet, b2Joint* joint ) +{ + B2_ASSERT( targetSet != sourceSet ); + + int localIndex = joint->localIndex; + int colorIndex = joint->colorIndex; + + // Retrieve source. + b2JointSim* sourceSim; + if ( sourceSet->setIndex == b2_awakeSet ) + { + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = world->constraintGraph.colors + colorIndex; + + sourceSim = b2JointSimArray_Get( &color->jointSims, localIndex ); + } + else + { + B2_ASSERT( colorIndex == B2_NULL_INDEX ); + sourceSim = b2JointSimArray_Get( &sourceSet->jointSims, localIndex ); + } + + // Create target and copy. Fix joint. + if ( targetSet->setIndex == b2_awakeSet ) + { + b2AddJointToGraph( world, sourceSim, joint ); + joint->setIndex = b2_awakeSet; + } + else + { + joint->setIndex = targetSet->setIndex; + joint->localIndex = targetSet->jointSims.count; + joint->colorIndex = B2_NULL_INDEX; + + b2JointSim* targetSim = b2JointSimArray_Add( &targetSet->jointSims ); + memcpy( targetSim, sourceSim, sizeof( b2JointSim ) ); + } + + // Destroy source. + if ( sourceSet->setIndex == b2_awakeSet ) + { + b2RemoveJointFromGraph( world, joint->edges[0].bodyId, joint->edges[1].bodyId, colorIndex, localIndex ); + } + else + { + int movedIndex = b2JointSimArray_RemoveSwap( &sourceSet->jointSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + // fix swapped element + b2JointSim* movedJointSim = sourceSet->jointSims.data + localIndex; + int movedId = movedJointSim->jointId; + b2Joint* movedJoint = b2JointArray_Get( &world->joints, movedId ); + movedJoint->localIndex = localIndex; + } + } +} diff --git a/3rdparty/box2d/src/solver_set.h b/3rdparty/box2d/src/solver_set.h new file mode 100644 index 000000000000..540673a43373 --- /dev/null +++ b/3rdparty/box2d/src/solver_set.h @@ -0,0 +1,57 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" + +typedef struct b2Body b2Body; +typedef struct b2Joint b2Joint; +typedef struct b2World b2World; + +// This holds solver set data. The following sets are used: +// - static set for all static bodies (no contacts or joints) +// - active set for all active bodies with body states (no contacts or joints) +// - disabled set for disabled bodies and their joints +// - all further sets are sleeping island sets along with their contacts and joints +// The purpose of solver sets is to achieve high memory locality. +// https://www.youtube.com/watch?v=nZNd5FjSquk +typedef struct b2SolverSet +{ + // Body array. Empty for unused set. + b2BodySimArray bodySims; + + // Body state only exists for active set + b2BodyStateArray bodyStates; + + // This holds sleeping/disabled joints. Empty for static/active set. + b2JointSimArray jointSims; + + // This holds all contacts for sleeping sets. + // This holds non-touching contacts for the awake set. + b2ContactSimArray contactSims; + + // The awake set has an array of islands. Sleeping sets normally have a single islands. However, joints + // created between sleeping sets causes the sets to merge, leaving them with multiple islands. These sleeping + // islands will be naturally merged with the set is woken. + // The static and disabled sets have no islands. + // Islands live in the solver sets to limit the number of islands that need to be considered for sleeping. + b2IslandSimArray islandSims; + + // Aligns with b2World::solverSetIdPool. Used to create a stable id for body/contact/joint/islands. + int setIndex; +} b2SolverSet; + +void b2DestroySolverSet( b2World* world, int setIndex ); + +void b2WakeSolverSet( b2World* world, int setIndex ); +void b2TrySleepIsland( b2World* world, int islandId ); + +// Merge set 2 into set 1 then destroy set 2. +// Warning: any pointers into these sets will be orphaned. +void b2MergeSolverSets( b2World* world, int setIndex1, int setIndex2 ); + +void b2TransferBody( b2World* world, b2SolverSet* targetSet, b2SolverSet* sourceSet, b2Body* body ); +void b2TransferJoint( b2World* world, b2SolverSet* targetSet, b2SolverSet* sourceSet, b2Joint* joint ); + +B2_ARRAY_INLINE( b2SolverSet, b2SolverSet ) diff --git a/3rdparty/box2d/src/table.c b/3rdparty/box2d/src/table.c new file mode 100644 index 000000000000..9e1fdc8d338d --- /dev/null +++ b/3rdparty/box2d/src/table.c @@ -0,0 +1,238 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "table.h" + +#include "atomic.h" +#include "core.h" +#include "ctz.h" + +#include +#include + +#if B2_SNOOP_TABLE_COUNTERS +b2AtomicInt b2_findCount; +b2AtomicInt b2_probeCount; +#endif + +// todo compare with https://github.com/skeeto/scratch/blob/master/set32/set32.h + +b2HashSet b2CreateSet( int capacity ) +{ + b2HashSet set = { 0 }; + + // Capacity must be a power of 2 + if ( capacity > 16 ) + { + set.capacity = b2RoundUpPowerOf2( capacity ); + } + else + { + set.capacity = 16; + } + + set.count = 0; + set.items = b2Alloc( capacity * sizeof( b2SetItem ) ); + memset( set.items, 0, capacity * sizeof( b2SetItem ) ); + + return set; +} + +void b2DestroySet( b2HashSet* set ) +{ + b2Free( set->items, set->capacity * sizeof( b2SetItem ) ); + set->items = NULL; + set->count = 0; + set->capacity = 0; +} + +void b2ClearSet( b2HashSet* set ) +{ + set->count = 0; + memset( set->items, 0, set->capacity * sizeof( b2SetItem ) ); +} + +// I need a good hash because the keys are built from pairs of increasing integers. +// A simple hash like hash = (integer1 XOR integer2) has many collisions. +// https://lemire.me/blog/2018/08/15/fast-strongly-universal-64-bit-hashing-everywhere/ +// https://preshing.com/20130107/this-hash-set-is-faster-than-a-judy-array/ +// todo try: https://www.jandrewrogers.com/2019/02/12/fast-perfect-hashing/ +// todo try: https://probablydance.com/2018/06/16/fibonacci-hashing-the-optimization-that-the-world-forgot-or-a-better-alternative-to-integer-modulo/ +static uint32_t b2KeyHash( uint64_t key ) +{ + // Murmur hash + uint64_t h = key; + h ^= h >> 33; + h *= 0xff51afd7ed558ccduLL; + h ^= h >> 33; + h *= 0xc4ceb9fe1a85ec53uLL; + h ^= h >> 33; + + return (uint32_t)h; +} + +static int b2FindSlot( const b2HashSet* set, uint64_t key, uint32_t hash ) +{ +#if B2_SNOOP_TABLE_COUNTERS + b2AtomicFetchAddInt( &b2_findCount, 1 ); +#endif + + uint32_t capacity = set->capacity; + int index = hash & ( capacity - 1 ); + const b2SetItem* items = set->items; + while ( items[index].hash != 0 && items[index].key != key ) + { +#if B2_SNOOP_TABLE_COUNTERS + b2AtomicFetchAddInt( &b2_probeCount, 1 ); +#endif + index = ( index + 1 ) & ( capacity - 1 ); + } + + return index; +} + +static void b2AddKeyHaveCapacity( b2HashSet* set, uint64_t key, uint32_t hash ) +{ + int index = b2FindSlot( set, key, hash ); + b2SetItem* items = set->items; + B2_ASSERT( items[index].hash == 0 ); + + items[index].key = key; + items[index].hash = hash; + set->count += 1; +} + +static void b2GrowTable( b2HashSet* set ) +{ + uint32_t oldCount = set->count; + B2_UNUSED( oldCount ); + + uint32_t oldCapacity = set->capacity; + b2SetItem* oldItems = set->items; + + set->count = 0; + // Capacity must be a power of 2 + set->capacity = 2 * oldCapacity; + set->items = b2Alloc( set->capacity * sizeof( b2SetItem ) ); + memset( set->items, 0, set->capacity * sizeof( b2SetItem ) ); + + // Transfer items into new array + for ( uint32_t i = 0; i < oldCapacity; ++i ) + { + b2SetItem* item = oldItems + i; + if ( item->hash == 0 ) + { + // this item was empty + continue; + } + + b2AddKeyHaveCapacity( set, item->key, item->hash ); + } + + B2_ASSERT( set->count == oldCount ); + + b2Free( oldItems, oldCapacity * sizeof( b2SetItem ) ); +} + +bool b2ContainsKey( const b2HashSet* set, uint64_t key ) +{ + // key of zero is a sentinel + B2_ASSERT( key != 0 ); + uint32_t hash = b2KeyHash( key ); + int index = b2FindSlot( set, key, hash ); + return set->items[index].key == key; +} + +int b2GetHashSetBytes( b2HashSet* set ) +{ + return set->capacity * (int)sizeof( b2SetItem ); +} + +bool b2AddKey( b2HashSet* set, uint64_t key ) +{ + // key of zero is a sentinel + B2_ASSERT( key != 0 ); + + uint32_t hash = b2KeyHash( key ); + B2_ASSERT( hash != 0 ); + + int index = b2FindSlot( set, key, hash ); + if ( set->items[index].hash != 0 ) + { + // Already in set + B2_ASSERT( set->items[index].hash == hash && set->items[index].key == key ); + return true; + } + + if ( 2 * set->count >= set->capacity ) + { + b2GrowTable( set ); + } + + b2AddKeyHaveCapacity( set, key, hash ); + return false; +} + +// See https://en.wikipedia.org/wiki/Open_addressing +bool b2RemoveKey( b2HashSet* set, uint64_t key ) +{ + uint32_t hash = b2KeyHash( key ); + int i = b2FindSlot( set, key, hash ); + b2SetItem* items = set->items; + if ( items[i].hash == 0 ) + { + // Not in set + return false; + } + + // Mark item i as unoccupied + items[i].key = 0; + items[i].hash = 0; + + B2_ASSERT( set->count > 0 ); + set->count -= 1; + + // Attempt to fill item i + int j = i; + uint32_t capacity = set->capacity; + for ( ;; ) + { + j = ( j + 1 ) & ( capacity - 1 ); + if ( items[j].hash == 0 ) + { + break; + } + + // k is the first item for the hash of j + int k = items[j].hash & ( capacity - 1 ); + + // determine if k lies cyclically in (i,j] + // i <= j: | i..k..j | + // i > j: |.k..j i....| or |....j i..k.| + if ( i <= j ) + { + if ( i < k && k <= j ) + { + continue; + } + } + else + { + if ( i < k || k <= j ) + { + continue; + } + } + + // Move j into i + items[i] = items[j]; + + // Mark item j as unoccupied + items[j].key = 0; + items[j].hash = 0; + + i = j; + } + + return true; +} diff --git a/3rdparty/box2d/src/table.h b/3rdparty/box2d/src/table.h new file mode 100644 index 000000000000..3c2d27596867 --- /dev/null +++ b/3rdparty/box2d/src/table.h @@ -0,0 +1,37 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include +#include + +#define B2_SHAPE_PAIR_KEY( K1, K2 ) K1 < K2 ? (uint64_t)K1 << 32 | (uint64_t)K2 : (uint64_t)K2 << 32 | (uint64_t)K1 + +typedef struct b2SetItem +{ + uint64_t key; + uint32_t hash; +} b2SetItem; + +typedef struct b2HashSet +{ + b2SetItem* items; + uint32_t capacity; + uint32_t count; +} b2HashSet; + +b2HashSet b2CreateSet( int capacity ); +void b2DestroySet( b2HashSet* set ); + +void b2ClearSet( b2HashSet* set ); + +// Returns true if key was already in set +bool b2AddKey( b2HashSet* set, uint64_t key ); + +// Returns true if the key was found +bool b2RemoveKey( b2HashSet* set, uint64_t key ); + +bool b2ContainsKey( const b2HashSet* set, uint64_t key ); + +int b2GetHashSetBytes( b2HashSet* set ); diff --git a/3rdparty/box2d/src/timer.c b/3rdparty/box2d/src/timer.c new file mode 100644 index 000000000000..e8e4935f3dab --- /dev/null +++ b/3rdparty/box2d/src/timer.c @@ -0,0 +1,185 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "box2d/base.h" + +#include + +#if defined( _MSC_VER ) + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN 1 +#endif + +#include + +static double s_invFrequency = 0.0; + +uint64_t b2GetTicks( void ) +{ + LARGE_INTEGER counter; + QueryPerformanceCounter( &counter ); + return (uint64_t)counter.QuadPart; +} + +float b2GetMilliseconds( uint64_t ticks ) +{ + if ( s_invFrequency == 0.0 ) + { + LARGE_INTEGER frequency; + QueryPerformanceFrequency( &frequency ); + + s_invFrequency = (double)frequency.QuadPart; + if ( s_invFrequency > 0.0 ) + { + s_invFrequency = 1000.0 / s_invFrequency; + } + } + + uint64_t ticksNow = b2GetTicks(); + return (float)( s_invFrequency * ( ticksNow - ticks ) ); +} + +float b2GetMillisecondsAndReset( uint64_t* ticks ) +{ + if ( s_invFrequency == 0.0 ) + { + LARGE_INTEGER frequency; + QueryPerformanceFrequency( &frequency ); + + s_invFrequency = (double)frequency.QuadPart; + if ( s_invFrequency > 0.0 ) + { + s_invFrequency = 1000.0 / s_invFrequency; + } + } + + uint64_t ticksNow = b2GetTicks(); + float ms = (float)( s_invFrequency * ( ticksNow - *ticks ) ); + *ticks = ticksNow; + return ms; +} + +void b2Yield( void ) +{ + SwitchToThread(); +} + +#elif defined( __linux__ ) || defined( __EMSCRIPTEN__ ) + +#include +#include + +uint64_t b2GetTicks( void ) +{ + struct timespec ts; + clock_gettime( CLOCK_MONOTONIC, &ts ); + return ts.tv_sec * 1000000000LL + ts.tv_nsec; +} + +float b2GetMilliseconds( uint64_t ticks ) +{ + uint64_t ticksNow = b2GetTicks(); + return (float)( (ticksNow - ticks) / 1000000.0 ); +} + +float b2GetMillisecondsAndReset( uint64_t* ticks ) +{ + uint64_t ticksNow = b2GetTicks(); + float ms = (float)( (ticksNow - *ticks) / 1000000.0 ); + *ticks = ticksNow; + return ms; +} + +void b2Yield( void ) +{ + sched_yield(); +} + +#elif defined( __APPLE__ ) + +#include +#include +#include + +static double s_invFrequency = 0.0; + +uint64_t b2GetTicks( void ) +{ + return mach_absolute_time(); +} + +float b2GetMilliseconds( uint64_t ticks ) +{ + if ( s_invFrequency == 0 ) + { + mach_timebase_info_data_t timebase; + mach_timebase_info( &timebase ); + + // convert to ns then to ms + s_invFrequency = 1e-6 * (double)timebase.numer / (double)timebase.denom; + } + + uint64_t ticksNow = b2GetTicks(); + return (float)( s_invFrequency * (ticksNow - ticks) ); +} + +float b2GetMillisecondsAndReset( uint64_t* ticks ) +{ + if ( s_invFrequency == 0 ) + { + mach_timebase_info_data_t timebase; + mach_timebase_info( &timebase ); + + // convert to ns then to ms + s_invFrequency = 1e-6 * (double)timebase.numer / (double)timebase.denom; + } + + uint64_t ticksNow = b2GetTicks(); + float ms = (float)( s_invFrequency * ( ticksNow - *ticks ) ); + *ticks = ticksNow; + return ms; +} + +void b2Yield( void ) +{ + sched_yield(); +} + +#else + +uint64_t b2GetTicks( void ) +{ + return 0; +} + +float b2GetMilliseconds( uint64_t ticks ) +{ + ( (void)( ticks ) ); + return 0.0f; +} + +float b2GetMillisecondsAndReset( uint64_t* ticks ) +{ + ( (void)( ticks ) ); + return 0.0f; +} + +void b2Yield( void ) +{ +} + +#endif + +// djb2 hash +// https://en.wikipedia.org/wiki/List_of_hash_functions +uint32_t b2Hash( uint32_t hash, const uint8_t* data, int count ) +{ + uint32_t result = hash; + for ( int i = 0; i < count; i++ ) + { + result = ( result << 5 ) + result + data[i]; + } + + return result; +} diff --git a/3rdparty/box2d/src/types.c b/3rdparty/box2d/src/types.c new file mode 100644 index 000000000000..0c0a1437e4dc --- /dev/null +++ b/3rdparty/box2d/src/types.c @@ -0,0 +1,151 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "box2d/types.h" + +#include "constants.h" +#include "core.h" + +b2WorldDef b2DefaultWorldDef( void ) +{ + b2WorldDef def = { 0 }; + def.gravity.x = 0.0f; + def.gravity.y = -10.0f; + def.hitEventThreshold = 1.0f * b2_lengthUnitsPerMeter; + def.restitutionThreshold = 1.0f * b2_lengthUnitsPerMeter; + def.maxContactPushSpeed = 3.0f * b2_lengthUnitsPerMeter; + def.contactHertz = 30.0; + def.contactDampingRatio = 10.0f; + def.jointHertz = 60.0; + def.jointDampingRatio = 2.0f; + // 400 meters per second, faster than the speed of sound + def.maximumLinearSpeed = 400.0f * b2_lengthUnitsPerMeter; + def.enableSleep = true; + def.enableContinuous = true; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2BodyDef b2DefaultBodyDef( void ) +{ + b2BodyDef def = { 0 }; + def.type = b2_staticBody; + def.rotation = b2Rot_identity; + def.sleepThreshold = 0.05f * b2_lengthUnitsPerMeter; + def.gravityScale = 1.0f; + def.enableSleep = true; + def.isAwake = true; + def.isEnabled = true; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2Filter b2DefaultFilter( void ) +{ + b2Filter filter = { B2_DEFAULT_CATEGORY_BITS, B2_DEFAULT_MASK_BITS, 0 }; + return filter; +} + +b2QueryFilter b2DefaultQueryFilter( void ) +{ + b2QueryFilter filter = { B2_DEFAULT_CATEGORY_BITS, B2_DEFAULT_MASK_BITS }; + return filter; +} + +b2ShapeDef b2DefaultShapeDef( void ) +{ + b2ShapeDef def = { 0 }; + def.material.friction = 0.6f; + def.density = 1.0f; + def.filter = b2DefaultFilter(); + def.updateBodyMass = true; + def.invokeContactCreation = true; + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +b2SurfaceMaterial b2DefaultSurfaceMaterial( void ) +{ + b2SurfaceMaterial material = { + .friction = 0.6f, + }; + + return material; +} + +b2ChainDef b2DefaultChainDef( void ) +{ + static b2SurfaceMaterial defaultMaterial = { + .friction = 0.6f, + }; + + b2ChainDef def = { 0 }; + def.materials = &defaultMaterial; + def.materialCount = 1; + def.filter = b2DefaultFilter(); + def.internalValue = B2_SECRET_COOKIE; + return def; +} + +static void b2EmptyDrawPolygon( const b2Vec2* vertices, int vertexCount, b2HexColor color, void* context ) +{ + B2_UNUSED( vertices, vertexCount, color, context ); +} + +static void b2EmptyDrawSolidPolygon( b2Transform transform, const b2Vec2* vertices, int vertexCount, float radius, + b2HexColor color, void* context ) +{ + B2_UNUSED( transform, vertices, vertexCount, radius, color, context ); +} + +static void b2EmptyDrawCircle( b2Vec2 center, float radius, b2HexColor color, void* context ) +{ + B2_UNUSED( center, radius, color, context ); +} + +static void b2EmptyDrawSolidCircle( b2Transform transform, float radius, b2HexColor color, void* context ) +{ + B2_UNUSED( transform, radius, color, context ); +} + +static void b2EmptyDrawSolidCapsule( b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context ) +{ + B2_UNUSED( p1, p2, radius, color, context ); +} + +static void b2EmptyDrawSegment( b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context ) +{ + B2_UNUSED( p1, p2, color, context ); +} + +static void b2EmptyDrawTransform( b2Transform transform, void* context ) +{ + B2_UNUSED( transform, context ); +} + +static void b2EmptyDrawPoint( b2Vec2 p, float size, b2HexColor color, void* context ) +{ + B2_UNUSED( p, size, color, context ); +} + +static void b2EmptyDrawString( b2Vec2 p, const char* s, b2HexColor color, void* context ) +{ + B2_UNUSED( p, s, color, context ); +} + +b2DebugDraw b2DefaultDebugDraw( void ) +{ + b2DebugDraw draw = { 0 }; + + // These allow the user to skip some implementations and not hit null exceptions. + draw.DrawPolygonFcn = b2EmptyDrawPolygon; + draw.DrawSolidPolygonFcn = b2EmptyDrawSolidPolygon; + draw.DrawCircleFcn = b2EmptyDrawCircle; + draw.DrawSolidCircleFcn = b2EmptyDrawSolidCircle; + draw.DrawSolidCapsuleFcn = b2EmptyDrawSolidCapsule; + draw.DrawSegmentFcn = b2EmptyDrawSegment; + draw.DrawTransformFcn = b2EmptyDrawTransform; + draw.DrawPointFcn = b2EmptyDrawPoint; + draw.DrawStringFcn = b2EmptyDrawString; + return draw; +} diff --git a/3rdparty/box2d/src/weld_joint.c b/3rdparty/box2d/src/weld_joint.c new file mode 100644 index 000000000000..a305d0add428 --- /dev/null +++ b/3rdparty/box2d/src/weld_joint.c @@ -0,0 +1,310 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +float b2WeldJoint_GetReferenceAngle( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + return joint->weldJoint.referenceAngle; +} + +void b2WeldJoint_SetReferenceAngle( b2JointId jointId, float angleInRadians ) +{ + B2_ASSERT( b2IsValidFloat( angleInRadians ) ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + joint->weldJoint.referenceAngle = b2ClampFloat(angleInRadians, -B2_PI, B2_PI); +} + +void b2WeldJoint_SetLinearHertz( b2JointId jointId, float hertz ) +{ + B2_ASSERT( b2IsValidFloat( hertz ) && hertz >= 0.0f ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + joint->weldJoint.linearHertz = hertz; +} + +float b2WeldJoint_GetLinearHertz( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + return joint->weldJoint.linearHertz; +} + +void b2WeldJoint_SetLinearDampingRatio( b2JointId jointId, float dampingRatio ) +{ + B2_ASSERT( b2IsValidFloat( dampingRatio ) && dampingRatio >= 0.0f ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + joint->weldJoint.linearDampingRatio = dampingRatio; +} + +float b2WeldJoint_GetLinearDampingRatio( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + return joint->weldJoint.linearDampingRatio; +} + +void b2WeldJoint_SetAngularHertz( b2JointId jointId, float hertz ) +{ + B2_ASSERT( b2IsValidFloat( hertz ) && hertz >= 0.0f ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + joint->weldJoint.angularHertz = hertz; +} + +float b2WeldJoint_GetAngularHertz( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + return joint->weldJoint.angularHertz; +} + +void b2WeldJoint_SetAngularDampingRatio( b2JointId jointId, float dampingRatio ) +{ + B2_ASSERT( b2IsValidFloat( dampingRatio ) && dampingRatio >= 0.0f ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + joint->weldJoint.angularDampingRatio = dampingRatio; +} + +float b2WeldJoint_GetAngularDampingRatio( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_weldJoint ); + return joint->weldJoint.angularDampingRatio; +} + +b2Vec2 b2GetWeldJointForce( b2World* world, b2JointSim* base ) +{ + b2Vec2 force = b2MulSV( world->inv_h, base->weldJoint.linearImpulse ); + return force; +} + +float b2GetWeldJointTorque( b2World* world, b2JointSim* base ) +{ + return world->inv_h * base->weldJoint.angularImpulse; +} + +// Point-to-point constraint +// C = p2 - p1 +// Cdot = v2 - v1 +// = v2 + cross(w2, r2) - v1 - cross(w1, r1) +// J = [-I -r1_skew I r2_skew ] +// Identity used: +// w k % (rx i + ry j) = w * (-ry i + rx j) + +// Angle constraint +// C = angle2 - angle1 - referenceAngle +// Cdot = w2 - w1 +// J = [0 0 -1 0 0 1] +// K = invI1 + invI2 + +void b2PrepareWeldJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_weldJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2WeldJoint* joint = &base->weldJoint; + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + b2Rot qA = bodySimA->transform.q; + b2Rot qB = bodySimB->transform.q; + + joint->anchorA = b2RotateVector( qA, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( qB, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center ); + joint->deltaAngle = b2RelativeAngle( qB, qA ) - joint->referenceAngle; + joint->deltaAngle = b2UnwindAngle( joint->deltaAngle ); + + float ka = iA + iB; + joint->axialMass = ka > 0.0f ? 1.0f / ka : 0.0f; + + if ( joint->linearHertz == 0.0f ) + { + joint->linearSoftness = context->jointSoftness; + } + else + { + joint->linearSoftness = b2MakeSoft( joint->linearHertz, joint->linearDampingRatio, context->h ); + } + + if ( joint->angularHertz == 0.0f ) + { + joint->angularSoftness = context->jointSoftness; + } + else + { + joint->angularSoftness = b2MakeSoft( joint->angularHertz, joint->angularDampingRatio, context->h ); + } + + if ( context->enableWarmStarting == false ) + { + joint->linearImpulse = b2Vec2_zero; + joint->angularImpulse = 0.0f; + } +} + +void b2WarmStartWeldJoint( b2JointSim* base, b2StepContext* context ) +{ + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2WeldJoint* joint = &base->weldJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, joint->linearImpulse ); + stateA->angularVelocity -= iA * ( b2Cross( rA, joint->linearImpulse ) + joint->angularImpulse ); + + stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, joint->linearImpulse ); + stateB->angularVelocity += iB * ( b2Cross( rB, joint->linearImpulse ) + joint->angularImpulse ); +} + +void b2SolveWeldJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_ASSERT( base->type == b2_weldJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2WeldJoint* joint = &base->weldJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + // angular constraint + { + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias || joint->angularHertz > 0.0f ) + { + float C = b2RelativeAngle( stateB->deltaRotation, stateA->deltaRotation ) + joint->deltaAngle; + bias = joint->angularSoftness.biasRate * C; + massScale = joint->angularSoftness.massScale; + impulseScale = joint->angularSoftness.impulseScale; + } + + float Cdot = wB - wA; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->angularImpulse; + joint->angularImpulse += impulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + // linear constraint + { + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 bias = b2Vec2_zero; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias || joint->linearHertz > 0.0f ) + { + b2Vec2 dcA = stateA->deltaPosition; + b2Vec2 dcB = stateB->deltaPosition; + b2Vec2 C = b2Add( b2Add( b2Sub( dcB, dcA ), b2Sub( rB, rA ) ), joint->deltaCenter ); + + bias = b2MulSV( joint->linearSoftness.biasRate, C ); + massScale = joint->linearSoftness.massScale; + impulseScale = joint->linearSoftness.impulseScale; + } + + b2Vec2 Cdot = b2Sub( b2Add( vB, b2CrossSV( wB, rB ) ), b2Add( vA, b2CrossSV( wA, rA ) ) ); + + b2Mat22 K; + K.cx.x = mA + mB + rA.y * rA.y * iA + rB.y * rB.y * iB; + K.cy.x = -rA.y * rA.x * iA - rB.y * rB.x * iB; + K.cx.y = K.cy.x; + K.cy.y = mA + mB + rA.x * rA.x * iA + rB.x * rB.x * iB; + b2Vec2 b = b2Solve22( K, b2Add( Cdot, bias ) ); + + b2Vec2 impulse = { + -massScale * b.x - impulseScale * joint->linearImpulse.x, + -massScale * b.y - impulseScale * joint->linearImpulse.y, + }; + + joint->linearImpulse = b2Add( joint->linearImpulse, impulse ); + + vA = b2MulSub( vA, mA, impulse ); + wA -= iA * b2Cross( rA, impulse ); + vB = b2MulAdd( vB, mB, impulse ); + wB += iB * b2Cross( rB, impulse ); + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +#if 0 +void b2DumpWeldJoint() +{ + int32 indexA = m_bodyA->m_islandIndex; + int32 indexB = m_bodyB->m_islandIndex; + + b2Dump(" b2WeldJointDef jd;\n"); + b2Dump(" jd.bodyA = sims[%d];\n", indexA); + b2Dump(" jd.bodyB = sims[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", m_collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", m_localAnchorA.x, m_localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", m_localAnchorB.x, m_localAnchorB.y); + b2Dump(" jd.referenceAngle = %.9g;\n", m_referenceAngle); + b2Dump(" jd.stiffness = %.9g;\n", m_stiffness); + b2Dump(" jd.damping = %.9g;\n", m_damping); + b2Dump(" joints[%d] = m_world->CreateJoint(&jd);\n", m_index); +} +#endif diff --git a/3rdparty/box2d/src/wheel_joint.c b/3rdparty/box2d/src/wheel_joint.c new file mode 100644 index 000000000000..65f828b89d73 --- /dev/null +++ b/3rdparty/box2d/src/wheel_joint.c @@ -0,0 +1,551 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "body.h" +#include "core.h" +#include "joint.h" +#include "solver.h" +#include "solver_set.h" +#include "world.h" + +// needed for dll export +#include "box2d/box2d.h" + +#include + +void b2WheelJoint_EnableSpring( b2JointId jointId, bool enableSpring ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + + if ( enableSpring != joint->wheelJoint.enableSpring ) + { + joint->wheelJoint.enableSpring = enableSpring; + joint->wheelJoint.springImpulse = 0.0f; + } +} + +bool b2WheelJoint_IsSpringEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.enableSpring; +} + +void b2WheelJoint_SetSpringHertz( b2JointId jointId, float hertz ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + joint->wheelJoint.hertz = hertz; +} + +float b2WheelJoint_GetSpringHertz( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.hertz; +} + +void b2WheelJoint_SetSpringDampingRatio( b2JointId jointId, float dampingRatio ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + joint->wheelJoint.dampingRatio = dampingRatio; +} + +float b2WheelJoint_GetSpringDampingRatio( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.dampingRatio; +} + +void b2WheelJoint_EnableLimit( b2JointId jointId, bool enableLimit ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + if ( joint->wheelJoint.enableLimit != enableLimit ) + { + joint->wheelJoint.lowerImpulse = 0.0f; + joint->wheelJoint.upperImpulse = 0.0f; + joint->wheelJoint.enableLimit = enableLimit; + } +} + +bool b2WheelJoint_IsLimitEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.enableLimit; +} + +float b2WheelJoint_GetLowerLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.lowerTranslation; +} + +float b2WheelJoint_GetUpperLimit( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.upperTranslation; +} + +void b2WheelJoint_SetLimits( b2JointId jointId, float lower, float upper ) +{ + B2_ASSERT( lower <= upper ); + + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + if ( lower != joint->wheelJoint.lowerTranslation || upper != joint->wheelJoint.upperTranslation ) + { + joint->wheelJoint.lowerTranslation = b2MinFloat( lower, upper ); + joint->wheelJoint.upperTranslation = b2MaxFloat( lower, upper ); + joint->wheelJoint.lowerImpulse = 0.0f; + joint->wheelJoint.upperImpulse = 0.0f; + } +} + +void b2WheelJoint_EnableMotor( b2JointId jointId, bool enableMotor ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + if ( joint->wheelJoint.enableMotor != enableMotor ) + { + joint->wheelJoint.motorImpulse = 0.0f; + joint->wheelJoint.enableMotor = enableMotor; + } +} + +bool b2WheelJoint_IsMotorEnabled( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.enableMotor; +} + +void b2WheelJoint_SetMotorSpeed( b2JointId jointId, float motorSpeed ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + joint->wheelJoint.motorSpeed = motorSpeed; +} + +float b2WheelJoint_GetMotorSpeed( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.motorSpeed; +} + +float b2WheelJoint_GetMotorTorque( b2JointId jointId ) +{ + b2World* world = b2GetWorld( jointId.world0 ); + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return world->inv_h * joint->wheelJoint.motorImpulse; +} + +void b2WheelJoint_SetMaxMotorTorque( b2JointId jointId, float torque ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + joint->wheelJoint.maxMotorTorque = torque; +} + +float b2WheelJoint_GetMaxMotorTorque( b2JointId jointId ) +{ + b2JointSim* joint = b2GetJointSimCheckType( jointId, b2_wheelJoint ); + return joint->wheelJoint.maxMotorTorque; +} + +b2Vec2 b2GetWheelJointForce( b2World* world, b2JointSim* base ) +{ + b2WheelJoint* joint = &base->wheelJoint; + + // This is a frame behind + b2Vec2 axisA = joint->axisA; + b2Vec2 perpA = b2LeftPerp( axisA ); + + float perpForce = world->inv_h * joint->perpImpulse; + float axialForce = world->inv_h * ( joint->springImpulse + joint->lowerImpulse - joint->upperImpulse ); + + b2Vec2 force = b2Add( b2MulSV( perpForce, perpA ), b2MulSV( axialForce, axisA ) ); + return force; +} + +float b2GetWheelJointTorque( b2World* world, b2JointSim* base ) +{ + return world->inv_h * base->wheelJoint.motorImpulse; +} + +// Linear constraint (point-to-line) +// d = pB - pA = xB + rB - xA - rA +// C = dot(ay, d) +// Cdot = dot(d, cross(wA, ay)) + dot(ay, vB + cross(wB, rB) - vA - cross(wA, rA)) +// = -dot(ay, vA) - dot(cross(d + rA, ay), wA) + dot(ay, vB) + dot(cross(rB, ay), vB) +// J = [-ay, -cross(d + rA, ay), ay, cross(rB, ay)] + +// Spring linear constraint +// C = dot(ax, d) +// Cdot = = -dot(ax, vA) - dot(cross(d + rA, ax), wA) + dot(ax, vB) + dot(cross(rB, ax), vB) +// J = [-ax -cross(d+rA, ax) ax cross(rB, ax)] + +// Motor rotational constraint +// Cdot = wB - wA +// J = [0 0 -1 0 0 1] + +void b2PrepareWheelJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_wheelJoint ); + + // chase body id to the solver set where the body lives + int idA = base->bodyIdA; + int idB = base->bodyIdB; + + b2World* world = context->world; + + b2Body* bodyA = b2BodyArray_Get( &world->bodies, idA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, idB ); + + B2_ASSERT( bodyA->setIndex == b2_awakeSet || bodyB->setIndex == b2_awakeSet ); + b2SolverSet* setA = b2SolverSetArray_Get( &world->solverSets, bodyA->setIndex ); + b2SolverSet* setB = b2SolverSetArray_Get( &world->solverSets, bodyB->setIndex ); + + int localIndexA = bodyA->localIndex; + int localIndexB = bodyB->localIndex; + + b2BodySim* bodySimA = b2BodySimArray_Get( &setA->bodySims, localIndexA ); + b2BodySim* bodySimB = b2BodySimArray_Get( &setB->bodySims, localIndexB ); + + float mA = bodySimA->invMass; + float iA = bodySimA->invInertia; + float mB = bodySimB->invMass; + float iB = bodySimB->invInertia; + + base->invMassA = mA; + base->invMassB = mB; + base->invIA = iA; + base->invIB = iB; + + b2WheelJoint* joint = &base->wheelJoint; + + joint->indexA = bodyA->setIndex == b2_awakeSet ? localIndexA : B2_NULL_INDEX; + joint->indexB = bodyB->setIndex == b2_awakeSet ? localIndexB : B2_NULL_INDEX; + + b2Rot qA = bodySimA->transform.q; + b2Rot qB = bodySimB->transform.q; + + joint->anchorA = b2RotateVector( qA, b2Sub( base->localOriginAnchorA, bodySimA->localCenter ) ); + joint->anchorB = b2RotateVector( qB, b2Sub( base->localOriginAnchorB, bodySimB->localCenter ) ); + joint->axisA = b2RotateVector( qA, joint->localAxisA ); + joint->deltaCenter = b2Sub( bodySimB->center, bodySimA->center ); + + b2Vec2 rA = joint->anchorA; + b2Vec2 rB = joint->anchorB; + + b2Vec2 d = b2Add( joint->deltaCenter, b2Sub( rB, rA ) ); + b2Vec2 axisA = joint->axisA; + b2Vec2 perpA = b2LeftPerp( axisA ); + + // perpendicular constraint (keep wheel on line) + float s1 = b2Cross( b2Add( d, rA ), perpA ); + float s2 = b2Cross( rB, perpA ); + + float kp = mA + mB + iA * s1 * s1 + iB * s2 * s2; + joint->perpMass = kp > 0.0f ? 1.0f / kp : 0.0f; + + // spring constraint + float a1 = b2Cross( b2Add( d, rA ), axisA ); + float a2 = b2Cross( rB, axisA ); + + float ka = mA + mB + iA * a1 * a1 + iB * a2 * a2; + joint->axialMass = ka > 0.0f ? 1.0f / ka : 0.0f; + + joint->springSoftness = b2MakeSoft( joint->hertz, joint->dampingRatio, context->h ); + + float km = iA + iB; + joint->motorMass = km > 0.0f ? 1.0f / km : 0.0f; + + if ( context->enableWarmStarting == false ) + { + joint->perpImpulse = 0.0f; + joint->springImpulse = 0.0f; + joint->motorImpulse = 0.0f; + joint->lowerImpulse = 0.0f; + joint->upperImpulse = 0.0f; + } +} + +void b2WarmStartWheelJoint( b2JointSim* base, b2StepContext* context ) +{ + B2_ASSERT( base->type == b2_wheelJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2WheelJoint* joint = &base->wheelJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 d = b2Add( b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), joint->deltaCenter ), b2Sub( rB, rA ) ); + b2Vec2 axisA = b2RotateVector( stateA->deltaRotation, joint->axisA ); + b2Vec2 perpA = b2LeftPerp( axisA ); + + float a1 = b2Cross( b2Add( d, rA ), axisA ); + float a2 = b2Cross( rB, axisA ); + float s1 = b2Cross( b2Add( d, rA ), perpA ); + float s2 = b2Cross( rB, perpA ); + + float axialImpulse = joint->springImpulse + joint->lowerImpulse - joint->upperImpulse; + + b2Vec2 P = b2Add( b2MulSV( axialImpulse, axisA ), b2MulSV( joint->perpImpulse, perpA ) ); + float LA = axialImpulse * a1 + joint->perpImpulse * s1 + joint->motorImpulse; + float LB = axialImpulse * a2 + joint->perpImpulse * s2 + joint->motorImpulse; + + stateA->linearVelocity = b2MulSub( stateA->linearVelocity, mA, P ); + stateA->angularVelocity -= iA * LA; + stateB->linearVelocity = b2MulAdd( stateB->linearVelocity, mB, P ); + stateB->angularVelocity += iB * LB; +} + +void b2SolveWheelJoint( b2JointSim* base, b2StepContext* context, bool useBias ) +{ + B2_ASSERT( base->type == b2_wheelJoint ); + + float mA = base->invMassA; + float mB = base->invMassB; + float iA = base->invIA; + float iB = base->invIB; + + // dummy state for static bodies + b2BodyState dummyState = b2_identityBodyState; + + b2WheelJoint* joint = &base->wheelJoint; + + b2BodyState* stateA = joint->indexA == B2_NULL_INDEX ? &dummyState : context->states + joint->indexA; + b2BodyState* stateB = joint->indexB == B2_NULL_INDEX ? &dummyState : context->states + joint->indexB; + + b2Vec2 vA = stateA->linearVelocity; + float wA = stateA->angularVelocity; + b2Vec2 vB = stateB->linearVelocity; + float wB = stateB->angularVelocity; + + bool fixedRotation = ( iA + iB == 0.0f ); + + // current anchors + b2Vec2 rA = b2RotateVector( stateA->deltaRotation, joint->anchorA ); + b2Vec2 rB = b2RotateVector( stateB->deltaRotation, joint->anchorB ); + + b2Vec2 d = b2Add( b2Add( b2Sub( stateB->deltaPosition, stateA->deltaPosition ), joint->deltaCenter ), b2Sub( rB, rA ) ); + b2Vec2 axisA = b2RotateVector( stateA->deltaRotation, joint->axisA ); + float translation = b2Dot( axisA, d ); + + float a1 = b2Cross( b2Add( d, rA ), axisA ); + float a2 = b2Cross( rB, axisA ); + + // motor constraint + if ( joint->enableMotor && fixedRotation == false ) + { + float Cdot = wB - wA - joint->motorSpeed; + float impulse = -joint->motorMass * Cdot; + float oldImpulse = joint->motorImpulse; + float maxImpulse = context->h * joint->maxMotorTorque; + joint->motorImpulse = b2ClampFloat( joint->motorImpulse + impulse, -maxImpulse, maxImpulse ); + impulse = joint->motorImpulse - oldImpulse; + + wA -= iA * impulse; + wB += iB * impulse; + } + + // spring constraint + if ( joint->enableSpring ) + { + // This is a real spring and should be applied even during relax + float C = translation; + float bias = joint->springSoftness.biasRate * C; + float massScale = joint->springSoftness.massScale; + float impulseScale = joint->springSoftness.impulseScale; + + float Cdot = b2Dot( axisA, b2Sub( vB, vA ) ) + a2 * wB - a1 * wA; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->springImpulse; + joint->springImpulse += impulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + if ( joint->enableLimit ) + { + // Lower limit + { + float C = translation - joint->lowerTranslation; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float Cdot = b2Dot( axisA, b2Sub( vB, vA ) ) + a2 * wB - a1 * wA; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->lowerImpulse; + float oldImpulse = joint->lowerImpulse; + joint->lowerImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->lowerImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + // Upper limit + // Note: signs are flipped to keep C positive when the constraint is satisfied. + // This also keeps the impulse positive when the limit is active. + { + // sign flipped + float C = joint->upperTranslation - translation; + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + + if ( C > 0.0f ) + { + // speculation + bias = C * context->inv_h; + } + else if ( useBias ) + { + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + // sign flipped on Cdot + float Cdot = b2Dot( axisA, b2Sub( vA, vB ) ) + a1 * wA - a2 * wB; + float impulse = -massScale * joint->axialMass * ( Cdot + bias ) - impulseScale * joint->upperImpulse; + float oldImpulse = joint->upperImpulse; + joint->upperImpulse = b2MaxFloat( oldImpulse + impulse, 0.0f ); + impulse = joint->upperImpulse - oldImpulse; + + b2Vec2 P = b2MulSV( impulse, axisA ); + float LA = impulse * a1; + float LB = impulse * a2; + + // sign flipped on applied impulse + vA = b2MulAdd( vA, mA, P ); + wA += iA * LA; + vB = b2MulSub( vB, mB, P ); + wB -= iB * LB; + } + } + + // point to line constraint + { + b2Vec2 perpA = b2LeftPerp( axisA ); + + float bias = 0.0f; + float massScale = 1.0f; + float impulseScale = 0.0f; + if ( useBias ) + { + float C = b2Dot( perpA, d ); + bias = context->jointSoftness.biasRate * C; + massScale = context->jointSoftness.massScale; + impulseScale = context->jointSoftness.impulseScale; + } + + float s1 = b2Cross( b2Add( d, rA ), perpA ); + float s2 = b2Cross( rB, perpA ); + float Cdot = b2Dot( perpA, b2Sub( vB, vA ) ) + s2 * wB - s1 * wA; + + float impulse = -massScale * joint->perpMass * ( Cdot + bias ) - impulseScale * joint->perpImpulse; + joint->perpImpulse += impulse; + + b2Vec2 P = b2MulSV( impulse, perpA ); + float LA = impulse * s1; + float LB = impulse * s2; + + vA = b2MulSub( vA, mA, P ); + wA -= iA * LA; + vB = b2MulAdd( vB, mB, P ); + wB += iB * LB; + } + + stateA->linearVelocity = vA; + stateA->angularVelocity = wA; + stateB->linearVelocity = vB; + stateB->angularVelocity = wB; +} + +#if 0 +void b2WheelJoint_Dump() +{ + int32 indexA = joint->bodyA->joint->islandIndex; + int32 indexB = joint->bodyB->joint->islandIndex; + + b2Dump(" b2WheelJointDef jd;\n"); + b2Dump(" jd.bodyA = sims[%d];\n", indexA); + b2Dump(" jd.bodyB = sims[%d];\n", indexB); + b2Dump(" jd.collideConnected = bool(%d);\n", joint->collideConnected); + b2Dump(" jd.localAnchorA.Set(%.9g, %.9g);\n", joint->localAnchorA.x, joint->localAnchorA.y); + b2Dump(" jd.localAnchorB.Set(%.9g, %.9g);\n", joint->localAnchorB.x, joint->localAnchorB.y); + b2Dump(" jd.referenceAngle = %.9g;\n", joint->referenceAngle); + b2Dump(" jd.enableLimit = bool(%d);\n", joint->enableLimit); + b2Dump(" jd.lowerAngle = %.9g;\n", joint->lowerAngle); + b2Dump(" jd.upperAngle = %.9g;\n", joint->upperAngle); + b2Dump(" jd.enableMotor = bool(%d);\n", joint->enableMotor); + b2Dump(" jd.motorSpeed = %.9g;\n", joint->motorSpeed); + b2Dump(" jd.maxMotorTorque = %.9g;\n", joint->maxMotorTorque); + b2Dump(" joints[%d] = joint->world->CreateJoint(&jd);\n", joint->index); +} +#endif + +void b2DrawWheelJoint( b2DebugDraw* draw, b2JointSim* base, b2Transform transformA, b2Transform transformB ) +{ + B2_ASSERT( base->type == b2_wheelJoint ); + + b2WheelJoint* joint = &base->wheelJoint; + + b2Vec2 pA = b2TransformPoint( transformA, base->localOriginAnchorA ); + b2Vec2 pB = b2TransformPoint( transformB, base->localOriginAnchorB ); + b2Vec2 axis = b2RotateVector( transformA.q, joint->localAxisA ); + + b2HexColor c1 = b2_colorGray; + b2HexColor c2 = b2_colorGreen; + b2HexColor c3 = b2_colorRed; + b2HexColor c4 = b2_colorDimGray; + b2HexColor c5 = b2_colorBlue; + + draw->DrawSegmentFcn( pA, pB, c5, draw->context ); + + if ( joint->enableLimit ) + { + b2Vec2 lower = b2MulAdd( pA, joint->lowerTranslation, axis ); + b2Vec2 upper = b2MulAdd( pA, joint->upperTranslation, axis ); + b2Vec2 perp = b2LeftPerp( axis ); + draw->DrawSegmentFcn( lower, upper, c1, draw->context ); + draw->DrawSegmentFcn( b2MulSub( lower, 0.1f, perp ), b2MulAdd( lower, 0.1f, perp ), c2, draw->context ); + draw->DrawSegmentFcn( b2MulSub( upper, 0.1f, perp ), b2MulAdd( upper, 0.1f, perp ), c3, draw->context ); + } + else + { + draw->DrawSegmentFcn( b2MulSub( pA, 1.0f, axis ), b2MulAdd( pA, 1.0f, axis ), c1, draw->context ); + } + + draw->DrawPointFcn( pA, 5.0f, c1, draw->context ); + draw->DrawPointFcn( pB, 5.0f, c4, draw->context ); +} diff --git a/3rdparty/box2d/src/world.c b/3rdparty/box2d/src/world.c new file mode 100644 index 000000000000..538eff84d188 --- /dev/null +++ b/3rdparty/box2d/src/world.c @@ -0,0 +1,3301 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "world.h" + +#include "aabb.h" +#include "arena_allocator.h" +#include "array.h" +#include "bitset.h" +#include "body.h" +#include "broad_phase.h" +#include "constants.h" +#include "constraint_graph.h" +#include "contact.h" +#include "core.h" +#include "ctz.h" +#include "island.h" +#include "joint.h" +#include "sensor.h" +#include "shape.h" +#include "solver.h" +#include "solver_set.h" + +#include "box2d/box2d.h" + +#include +#include +#include + +_Static_assert( B2_MAX_WORLDS > 0, "must be 1 or more" ); +_Static_assert( B2_MAX_WORLDS < UINT16_MAX, "B2_MAX_WORLDS limit exceeded" ); +b2World b2_worlds[B2_MAX_WORLDS]; + +B2_ARRAY_SOURCE( b2BodyMoveEvent, b2BodyMoveEvent ) +B2_ARRAY_SOURCE( b2ContactBeginTouchEvent, b2ContactBeginTouchEvent ) +B2_ARRAY_SOURCE( b2ContactEndTouchEvent, b2ContactEndTouchEvent ) +B2_ARRAY_SOURCE( b2ContactHitEvent, b2ContactHitEvent ) +B2_ARRAY_SOURCE( b2SensorBeginTouchEvent, b2SensorBeginTouchEvent ) +B2_ARRAY_SOURCE( b2SensorEndTouchEvent, b2SensorEndTouchEvent ) +B2_ARRAY_SOURCE( b2TaskContext, b2TaskContext ) + +b2World* b2GetWorldFromId( b2WorldId id ) +{ + B2_ASSERT( 1 <= id.index1 && id.index1 <= B2_MAX_WORLDS ); + b2World* world = b2_worlds + ( id.index1 - 1 ); + B2_ASSERT( id.index1 == world->worldId + 1 ); + B2_ASSERT( id.generation == world->generation ); + return world; +} + +b2World* b2GetWorld( int index ) +{ + B2_ASSERT( 0 <= index && index < B2_MAX_WORLDS ); + b2World* world = b2_worlds + index; + B2_ASSERT( world->worldId == index ); + return world; +} + +b2World* b2GetWorldLocked( int index ) +{ + B2_ASSERT( 0 <= index && index < B2_MAX_WORLDS ); + b2World* world = b2_worlds + index; + B2_ASSERT( world->worldId == index ); + if ( world->locked ) + { + B2_ASSERT( false ); + return NULL; + } + + return world; +} + +static void* b2DefaultAddTaskFcn( b2TaskCallback* task, int count, int minRange, void* taskContext, void* userContext ) +{ + B2_UNUSED( minRange, userContext ); + task( 0, count, 0, taskContext ); + return NULL; +} + +static void b2DefaultFinishTaskFcn( void* userTask, void* userContext ) +{ + B2_UNUSED( userTask, userContext ); +} + +static float b2DefaultFrictionCallback( float frictionA, int materialA, float frictionB, int materialB ) +{ + B2_UNUSED( materialA, materialB ); + return sqrtf( frictionA * frictionB ); +} + +static float b2DefaultRestitutionCallback( float restitutionA, int materialA, float restitutionB, int materialB ) +{ + B2_UNUSED( materialA, materialB ); + return b2MaxFloat( restitutionA, restitutionB ); +} + +b2WorldId b2CreateWorld( const b2WorldDef* def ) +{ + _Static_assert( B2_MAX_WORLDS < UINT16_MAX, "B2_MAX_WORLDS limit exceeded" ); + B2_CHECK_DEF( def ); + + int worldId = B2_NULL_INDEX; + for ( int i = 0; i < B2_MAX_WORLDS; ++i ) + { + if ( b2_worlds[i].inUse == false ) + { + worldId = i; + break; + } + } + + if ( worldId == B2_NULL_INDEX ) + { + return (b2WorldId){ 0 }; + } + + b2InitializeContactRegisters(); + + b2World* world = b2_worlds + worldId; + uint16_t generation = world->generation; + + *world = (b2World){ 0 }; + + world->worldId = (uint16_t)worldId; + world->generation = generation; + world->inUse = true; + + world->arena = b2CreateArenaAllocator( 2048 ); + b2CreateBroadPhase( &world->broadPhase ); + b2CreateGraph( &world->constraintGraph, 16 ); + + // pools + world->bodyIdPool = b2CreateIdPool(); + world->bodies = b2BodyArray_Create( 16 ); + world->solverSets = b2SolverSetArray_Create( 8 ); + + // add empty static, active, and disabled body sets + world->solverSetIdPool = b2CreateIdPool(); + b2SolverSet set = { 0 }; + + // static set + set.setIndex = b2AllocId( &world->solverSetIdPool ); + b2SolverSetArray_Push( &world->solverSets, set ); + B2_ASSERT( world->solverSets.data[b2_staticSet].setIndex == b2_staticSet ); + + // disabled set + set.setIndex = b2AllocId( &world->solverSetIdPool ); + b2SolverSetArray_Push( &world->solverSets, set ); + B2_ASSERT( world->solverSets.data[b2_disabledSet].setIndex == b2_disabledSet ); + + // awake set + set.setIndex = b2AllocId( &world->solverSetIdPool ); + b2SolverSetArray_Push( &world->solverSets, set ); + B2_ASSERT( world->solverSets.data[b2_awakeSet].setIndex == b2_awakeSet ); + + world->shapeIdPool = b2CreateIdPool(); + world->shapes = b2ShapeArray_Create( 16 ); + + world->chainIdPool = b2CreateIdPool(); + world->chainShapes = b2ChainShapeArray_Create( 4 ); + + world->contactIdPool = b2CreateIdPool(); + world->contacts = b2ContactArray_Create( 16 ); + + world->jointIdPool = b2CreateIdPool(); + world->joints = b2JointArray_Create( 16 ); + + world->islandIdPool = b2CreateIdPool(); + world->islands = b2IslandArray_Create( 8 ); + + world->sensors = b2SensorArray_Create( 4 ); + + world->bodyMoveEvents = b2BodyMoveEventArray_Create( 4 ); + world->sensorBeginEvents = b2SensorBeginTouchEventArray_Create( 4 ); + world->sensorEndEvents[0] = b2SensorEndTouchEventArray_Create( 4 ); + world->sensorEndEvents[1] = b2SensorEndTouchEventArray_Create( 4 ); + world->contactBeginEvents = b2ContactBeginTouchEventArray_Create( 4 ); + world->contactEndEvents[0] = b2ContactEndTouchEventArray_Create( 4 ); + world->contactEndEvents[1] = b2ContactEndTouchEventArray_Create( 4 ); + world->contactHitEvents = b2ContactHitEventArray_Create( 4 ); + world->endEventArrayIndex = 0; + + world->stepIndex = 0; + world->splitIslandId = B2_NULL_INDEX; + world->activeTaskCount = 0; + world->taskCount = 0; + world->gravity = def->gravity; + world->hitEventThreshold = def->hitEventThreshold; + world->restitutionThreshold = def->restitutionThreshold; + world->maxLinearSpeed = def->maximumLinearSpeed; + world->maxContactPushSpeed = def->maxContactPushSpeed; + world->contactHertz = def->contactHertz; + world->contactDampingRatio = def->contactDampingRatio; + world->jointHertz = def->jointHertz; + world->jointDampingRatio = def->jointDampingRatio; + + if ( def->frictionCallback == NULL ) + { + world->frictionCallback = b2DefaultFrictionCallback; + } + else + { + world->frictionCallback = def->frictionCallback; + } + + if ( def->restitutionCallback == NULL ) + { + world->restitutionCallback = b2DefaultRestitutionCallback; + } + else + { + world->restitutionCallback = def->restitutionCallback; + } + + world->enableSleep = def->enableSleep; + world->locked = false; + world->enableWarmStarting = true; + world->enableContinuous = def->enableContinuous; + world->enableSpeculative = true; + world->userTreeTask = NULL; + world->userData = def->userData; + + if ( def->workerCount > 0 && def->enqueueTask != NULL && def->finishTask != NULL ) + { + world->workerCount = b2MinInt( def->workerCount, B2_MAX_WORKERS ); + world->enqueueTaskFcn = def->enqueueTask; + world->finishTaskFcn = def->finishTask; + world->userTaskContext = def->userTaskContext; + } + else + { + world->workerCount = 1; + world->enqueueTaskFcn = b2DefaultAddTaskFcn; + world->finishTaskFcn = b2DefaultFinishTaskFcn; + world->userTaskContext = NULL; + } + + world->taskContexts = b2TaskContextArray_Create( world->workerCount ); + b2TaskContextArray_Resize( &world->taskContexts, world->workerCount ); + + world->sensorTaskContexts = b2SensorTaskContextArray_Create( world->workerCount ); + b2SensorTaskContextArray_Resize( &world->sensorTaskContexts, world->workerCount ); + + for ( int i = 0; i < world->workerCount; ++i ) + { + world->taskContexts.data[i].contactStateBitSet = b2CreateBitSet( 1024 ); + world->taskContexts.data[i].enlargedSimBitSet = b2CreateBitSet( 256 ); + world->taskContexts.data[i].awakeIslandBitSet = b2CreateBitSet( 256 ); + + world->sensorTaskContexts.data[i].eventBits = b2CreateBitSet( 128 ); + } + + world->debugBodySet = b2CreateBitSet( 256 ); + world->debugJointSet = b2CreateBitSet( 256 ); + world->debugContactSet = b2CreateBitSet( 256 ); + world->debugIslandSet = b2CreateBitSet( 256 ); + + // add one to worldId so that 0 represents a null b2WorldId + return (b2WorldId){ (uint16_t)( worldId + 1 ), world->generation }; +} + +void b2DestroyWorld( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + + b2DestroyBitSet( &world->debugBodySet ); + b2DestroyBitSet( &world->debugJointSet ); + b2DestroyBitSet( &world->debugContactSet ); + b2DestroyBitSet( &world->debugIslandSet ); + + for ( int i = 0; i < world->workerCount; ++i ) + { + b2DestroyBitSet( &world->taskContexts.data[i].contactStateBitSet ); + b2DestroyBitSet( &world->taskContexts.data[i].enlargedSimBitSet ); + b2DestroyBitSet( &world->taskContexts.data[i].awakeIslandBitSet ); + + b2DestroyBitSet( &world->sensorTaskContexts.data[i].eventBits ); + } + + b2TaskContextArray_Destroy( &world->taskContexts ); + b2SensorTaskContextArray_Destroy( &world->sensorTaskContexts ); + + b2BodyMoveEventArray_Destroy( &world->bodyMoveEvents ); + b2SensorBeginTouchEventArray_Destroy( &world->sensorBeginEvents ); + b2SensorEndTouchEventArray_Destroy( world->sensorEndEvents + 0 ); + b2SensorEndTouchEventArray_Destroy( world->sensorEndEvents + 1 ); + b2ContactBeginTouchEventArray_Destroy( &world->contactBeginEvents ); + b2ContactEndTouchEventArray_Destroy( world->contactEndEvents + 0 ); + b2ContactEndTouchEventArray_Destroy( world->contactEndEvents + 1 ); + b2ContactHitEventArray_Destroy( &world->contactHitEvents ); + + int chainCapacity = world->chainShapes.count; + for ( int i = 0; i < chainCapacity; ++i ) + { + b2ChainShape* chain = world->chainShapes.data + i; + if ( chain->id != B2_NULL_INDEX ) + { + b2FreeChainData( chain ); + } + else + { + B2_ASSERT( chain->shapeIndices == NULL ); + B2_ASSERT( chain->materials == NULL ); + } + } + + int sensorCount = world->sensors.count; + for ( int i = 0; i < sensorCount; ++i ) + { + b2ShapeRefArray_Destroy( &world->sensors.data[i].overlaps1 ); + b2ShapeRefArray_Destroy( &world->sensors.data[i].overlaps2 ); + } + + b2SensorArray_Destroy( &world->sensors ); + + b2BodyArray_Destroy( &world->bodies ); + b2ShapeArray_Destroy( &world->shapes ); + b2ChainShapeArray_Destroy( &world->chainShapes ); + b2ContactArray_Destroy( &world->contacts ); + b2JointArray_Destroy( &world->joints ); + b2IslandArray_Destroy( &world->islands ); + + // Destroy solver sets + int setCapacity = world->solverSets.count; + for ( int i = 0; i < setCapacity; ++i ) + { + b2SolverSet* set = world->solverSets.data + i; + if ( set->setIndex != B2_NULL_INDEX ) + { + b2DestroySolverSet( world, i ); + } + } + + b2SolverSetArray_Destroy( &world->solverSets ); + + b2DestroyGraph( &world->constraintGraph ); + b2DestroyBroadPhase( &world->broadPhase ); + + b2DestroyIdPool( &world->bodyIdPool ); + b2DestroyIdPool( &world->shapeIdPool ); + b2DestroyIdPool( &world->chainIdPool ); + b2DestroyIdPool( &world->contactIdPool ); + b2DestroyIdPool( &world->jointIdPool ); + b2DestroyIdPool( &world->islandIdPool ); + b2DestroyIdPool( &world->solverSetIdPool ); + + b2DestroyArenaAllocator( &world->arena ); + + // Wipe world but preserve generation + uint16_t generation = world->generation; + *world = (b2World){ 0 }; + world->worldId = 0; + world->generation = generation + 1; +} + +static void b2CollideTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + b2TracyCZoneNC( collide_task, "Collide", b2_colorDodgerBlue, true ); + + b2StepContext* stepContext = context; + b2World* world = stepContext->world; + B2_ASSERT( (int)threadIndex < world->workerCount ); + b2TaskContext* taskContext = world->taskContexts.data + threadIndex; + b2ContactSim** contactSims = stepContext->contacts; + b2Shape* shapes = world->shapes.data; + b2Body* bodies = world->bodies.data; + + B2_ASSERT( startIndex < endIndex ); + + for ( int contactIndex = startIndex; contactIndex < endIndex; ++contactIndex ) + { + b2ContactSim* contactSim = contactSims[contactIndex]; + + int contactId = contactSim->contactId; + + b2Shape* shapeA = shapes + contactSim->shapeIdA; + b2Shape* shapeB = shapes + contactSim->shapeIdB; + + // Do proxies still overlap? + bool overlap = b2AABB_Overlaps( shapeA->fatAABB, shapeB->fatAABB ); + if ( overlap == false ) + { + contactSim->simFlags |= b2_simDisjoint; + contactSim->simFlags &= ~b2_simTouchingFlag; + b2SetBit( &taskContext->contactStateBitSet, contactId ); + } + else + { + bool wasTouching = ( contactSim->simFlags & b2_simTouchingFlag ); + + // Update contact respecting shape/body order (A,B) + b2Body* bodyA = bodies + shapeA->bodyId; + b2Body* bodyB = bodies + shapeB->bodyId; + b2BodySim* bodySimA = b2GetBodySim( world, bodyA ); + b2BodySim* bodySimB = b2GetBodySim( world, bodyB ); + + // avoid cache misses in b2PrepareContactsTask + contactSim->bodySimIndexA = bodyA->setIndex == b2_awakeSet ? bodyA->localIndex : B2_NULL_INDEX; + contactSim->invMassA = bodySimA->invMass; + contactSim->invIA = bodySimA->invInertia; + + contactSim->bodySimIndexB = bodyB->setIndex == b2_awakeSet ? bodyB->localIndex : B2_NULL_INDEX; + contactSim->invMassB = bodySimB->invMass; + contactSim->invIB = bodySimB->invInertia; + + b2Transform transformA = bodySimA->transform; + b2Transform transformB = bodySimB->transform; + + b2Vec2 centerOffsetA = b2RotateVector( transformA.q, bodySimA->localCenter ); + b2Vec2 centerOffsetB = b2RotateVector( transformB.q, bodySimB->localCenter ); + + // This updates solid contacts and sensors + bool touching = + b2UpdateContact( world, contactSim, shapeA, transformA, centerOffsetA, shapeB, transformB, centerOffsetB ); + + // State changes that affect island connectivity. Also affects contact and sensor events. + if ( touching == true && wasTouching == false ) + { + contactSim->simFlags |= b2_simStartedTouching; + b2SetBit( &taskContext->contactStateBitSet, contactId ); + } + else if ( touching == false && wasTouching == true ) + { + contactSim->simFlags |= b2_simStoppedTouching; + b2SetBit( &taskContext->contactStateBitSet, contactId ); + } + + // To make this work, the time of impact code needs to adjust the target + // distance based on the number of TOI events for a body. + // if (touching && bodySimB->isFast) + //{ + // b2Manifold* manifold = &contactSim->manifold; + // int pointCount = manifold->pointCount; + // for (int i = 0; i < pointCount; ++i) + // { + // // trick the solver into pushing the fast shapes apart + // manifold->points[i].separation -= 0.25f * B2_SPECULATIVE_DISTANCE; + // } + //} + } + } + + b2TracyCZoneEnd( collide_task ); +} + +static void b2UpdateTreesTask( int startIndex, int endIndex, uint32_t threadIndex, void* context ) +{ + B2_UNUSED( startIndex ); + B2_UNUSED( endIndex ); + B2_UNUSED( threadIndex ); + + b2TracyCZoneNC( tree_task, "Rebuild BVH", b2_colorFireBrick, true ); + + b2World* world = context; + b2BroadPhase_RebuildTrees( &world->broadPhase ); + + b2TracyCZoneEnd( tree_task ); +} + +static void b2AddNonTouchingContact( b2World* world, b2Contact* contact, b2ContactSim* contactSim ) +{ + B2_ASSERT( contact->setIndex == b2_awakeSet ); + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + contact->colorIndex = B2_NULL_INDEX; + contact->localIndex = set->contactSims.count; + + b2ContactSim* newContactSim = b2ContactSimArray_Add( &set->contactSims ); + memcpy( newContactSim, contactSim, sizeof( b2ContactSim ) ); +} + +static void b2RemoveNonTouchingContact( b2World* world, int setIndex, int localIndex ) +{ + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + int movedIndex = b2ContactSimArray_RemoveSwap( &set->contactSims, localIndex ); + if ( movedIndex != B2_NULL_INDEX ) + { + b2ContactSim* movedContactSim = set->contactSims.data + localIndex; + b2Contact* movedContact = b2ContactArray_Get( &world->contacts, movedContactSim->contactId ); + B2_ASSERT( movedContact->setIndex == setIndex ); + B2_ASSERT( movedContact->localIndex == movedIndex ); + B2_ASSERT( movedContact->colorIndex == B2_NULL_INDEX ); + movedContact->localIndex = localIndex; + } +} + +// Narrow-phase collision +static void b2Collide( b2StepContext* context ) +{ + b2World* world = context->world; + + B2_ASSERT( world->workerCount > 0 ); + + b2TracyCZoneNC( collide, "Narrow Phase", b2_colorDodgerBlue, true ); + + // Task that can be done in parallel with the narrow-phase + // - rebuild the collision tree for dynamic and kinematic bodies to keep their query performance good + // todo_erin move this to start when contacts are being created + world->userTreeTask = world->enqueueTaskFcn( &b2UpdateTreesTask, 1, 1, world, world->userTaskContext ); + world->taskCount += 1; + world->activeTaskCount += world->userTreeTask == NULL ? 0 : 1; + + // gather contacts into a single array for easier parallel-for + int contactCount = 0; + b2GraphColor* graphColors = world->constraintGraph.colors; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + contactCount += graphColors[i].contactSims.count; + } + + int nonTouchingCount = world->solverSets.data[b2_awakeSet].contactSims.count; + contactCount += nonTouchingCount; + + if ( contactCount == 0 ) + { + b2TracyCZoneEnd( collide ); + return; + } + + b2ContactSim** contactSims = b2AllocateArenaItem( &world->arena, contactCount * sizeof( b2ContactSim* ), "contacts" ); + + int contactIndex = 0; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + b2GraphColor* color = graphColors + i; + int count = color->contactSims.count; + b2ContactSim* base = color->contactSims.data; + for ( int j = 0; j < count; ++j ) + { + contactSims[contactIndex] = base + j; + contactIndex += 1; + } + } + + { + b2ContactSim* base = world->solverSets.data[b2_awakeSet].contactSims.data; + for ( int i = 0; i < nonTouchingCount; ++i ) + { + contactSims[contactIndex] = base + i; + contactIndex += 1; + } + } + + B2_ASSERT( contactIndex == contactCount ); + + context->contacts = contactSims; + + // Contact bit set on ids because contact pointers are unstable as they move between touching and not touching. + int contactIdCapacity = b2GetIdCapacity( &world->contactIdPool ); + for ( int i = 0; i < world->workerCount; ++i ) + { + b2SetBitCountAndClear( &world->taskContexts.data[i].contactStateBitSet, contactIdCapacity ); + } + + // Task should take at least 40us on a 4GHz CPU (10K cycles) + int minRange = 64; + void* userCollideTask = world->enqueueTaskFcn( &b2CollideTask, contactCount, minRange, context, world->userTaskContext ); + world->taskCount += 1; + if ( userCollideTask != NULL ) + { + world->finishTaskFcn( userCollideTask, world->userTaskContext ); + } + + b2FreeArenaItem( &world->arena, contactSims ); + context->contacts = NULL; + contactSims = NULL; + + // Serially update contact state + // todo_erin bring this zone together with island merge + b2TracyCZoneNC( contact_state, "Contact State", b2_colorLightSlateGray, true ); + + // Bitwise OR all contact bits + b2BitSet* bitSet = &world->taskContexts.data[0].contactStateBitSet; + for ( int i = 1; i < world->workerCount; ++i ) + { + b2InPlaceUnion( bitSet, &world->taskContexts.data[i].contactStateBitSet ); + } + + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + + int endEventArrayIndex = world->endEventArrayIndex; + + const b2Shape* shapes = world->shapes.data; + uint16_t worldId = world->worldId; + + // Process contact state changes. Iterate over set bits + for ( uint32_t k = 0; k < bitSet->blockCount; ++k ) + { + uint64_t bits = bitSet->bits[k]; + while ( bits != 0 ) + { + uint32_t ctz = b2CTZ64( bits ); + int contactId = (int)( 64 * k + ctz ); + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + B2_ASSERT( contact->setIndex == b2_awakeSet ); + + int colorIndex = contact->colorIndex; + int localIndex = contact->localIndex; + + b2ContactSim* contactSim = NULL; + if ( colorIndex != B2_NULL_INDEX ) + { + // contact lives in constraint graph + B2_ASSERT( 0 <= colorIndex && colorIndex < B2_GRAPH_COLOR_COUNT ); + b2GraphColor* color = graphColors + colorIndex; + contactSim = b2ContactSimArray_Get( &color->contactSims, localIndex ); + } + else + { + contactSim = b2ContactSimArray_Get( &awakeSet->contactSims, localIndex ); + } + + const b2Shape* shapeA = shapes + contact->shapeIdA; + const b2Shape* shapeB = shapes + contact->shapeIdB; + b2ShapeId shapeIdA = { shapeA->id + 1, worldId, shapeA->generation }; + b2ShapeId shapeIdB = { shapeB->id + 1, worldId, shapeB->generation }; + uint32_t flags = contact->flags; + uint32_t simFlags = contactSim->simFlags; + + if ( simFlags & b2_simDisjoint ) + { + // Bounding boxes no longer overlap + b2DestroyContact( world, contact, false ); + contact = NULL; + contactSim = NULL; + } + else if ( simFlags & b2_simStartedTouching ) + { + B2_ASSERT( contact->islandId == B2_NULL_INDEX ); + // Contact is solid + if ( flags & b2_contactEnableContactEvents ) + { + b2ContactBeginTouchEvent event = { shapeIdA, shapeIdB, contactSim->manifold }; + b2ContactBeginTouchEventArray_Push( &world->contactBeginEvents, event ); + } + + B2_ASSERT( contactSim->manifold.pointCount > 0 ); + B2_ASSERT( contact->setIndex == b2_awakeSet ); + + // Link first because this wakes colliding bodies and ensures the body sims + // are in the correct place. + contact->flags |= b2_contactTouchingFlag; + b2LinkContact( world, contact ); + + // Make sure these didn't change + B2_ASSERT( contact->colorIndex == B2_NULL_INDEX ); + B2_ASSERT( contact->localIndex == localIndex ); + + // Contact sim pointer may have become orphaned due to awake set growth, + // so I just need to refresh it. + contactSim = b2ContactSimArray_Get( &awakeSet->contactSims, localIndex ); + + contactSim->simFlags &= ~b2_simStartedTouching; + + b2AddContactToGraph( world, contactSim, contact ); + b2RemoveNonTouchingContact( world, b2_awakeSet, localIndex ); + contactSim = NULL; + } + else if ( simFlags & b2_simStoppedTouching ) + { + contactSim->simFlags &= ~b2_simStoppedTouching; + + // Contact is solid + contact->flags &= ~b2_contactTouchingFlag; + + if ( contact->flags & b2_contactEnableContactEvents ) + { + b2ContactEndTouchEvent event = { shapeIdA, shapeIdB }; + b2ContactEndTouchEventArray_Push( world->contactEndEvents + endEventArrayIndex, event ); + } + + B2_ASSERT( contactSim->manifold.pointCount == 0 ); + + b2UnlinkContact( world, contact ); + int bodyIdA = contact->edges[0].bodyId; + int bodyIdB = contact->edges[1].bodyId; + + b2AddNonTouchingContact( world, contact, contactSim ); + b2RemoveContactFromGraph( world, bodyIdA, bodyIdB, colorIndex, localIndex ); + contact = NULL; + contactSim = NULL; + } + + // Clear the smallest set bit + bits = bits & ( bits - 1 ); + } + } + + b2ValidateSolverSets( world ); + b2ValidateContacts( world ); + + b2TracyCZoneEnd( contact_state ); + b2TracyCZoneEnd( collide ); +} + +void b2World_Step( b2WorldId worldId, float timeStep, int subStepCount ) +{ + B2_ASSERT( b2IsValidFloat( timeStep ) ); + B2_ASSERT( 0 < subStepCount ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + // Prepare to capture events + // Ensure user does not access stale data if there is an early return + b2BodyMoveEventArray_Clear( &world->bodyMoveEvents ); + b2SensorBeginTouchEventArray_Clear( &world->sensorBeginEvents ); + b2ContactBeginTouchEventArray_Clear( &world->contactBeginEvents ); + b2ContactHitEventArray_Clear( &world->contactHitEvents ); + + world->profile = (b2Profile){ 0 }; + + if ( timeStep == 0.0f ) + { + // Swap end event array buffers + world->endEventArrayIndex = 1 - world->endEventArrayIndex; + b2SensorEndTouchEventArray_Clear( world->sensorEndEvents + world->endEventArrayIndex ); + b2ContactEndTouchEventArray_Clear( world->contactEndEvents + world->endEventArrayIndex ); + + // todo_erin would be useful to still process collision while paused + return; + } + + b2TracyCZoneNC( world_step, "Step", b2_colorBox2DGreen, true ); + + world->locked = true; + world->activeTaskCount = 0; + world->taskCount = 0; + + uint64_t stepTicks = b2GetTicks(); + + // Update collision pairs and create contacts + { + uint64_t pairTicks = b2GetTicks(); + b2UpdateBroadPhasePairs( world ); + world->profile.pairs = b2GetMilliseconds( pairTicks ); + } + + b2StepContext context = { 0 }; + context.world = world; + context.dt = timeStep; + context.subStepCount = b2MaxInt( 1, subStepCount ); + + if ( timeStep > 0.0f ) + { + context.inv_dt = 1.0f / timeStep; + context.h = timeStep / context.subStepCount; + context.inv_h = context.subStepCount * context.inv_dt; + } + else + { + context.inv_dt = 0.0f; + context.h = 0.0f; + context.inv_h = 0.0f; + } + + world->inv_h = context.inv_h; + + // Hertz values get reduced for large time steps + float contactHertz = b2MinFloat( world->contactHertz, 0.25f * context.inv_h ); + float jointHertz = b2MinFloat( world->jointHertz, 0.125f * context.inv_h ); + + context.contactSoftness = b2MakeSoft( contactHertz, world->contactDampingRatio, context.h ); + context.staticSoftness = b2MakeSoft( 2.0f * contactHertz, world->contactDampingRatio, context.h ); + context.jointSoftness = b2MakeSoft( jointHertz, world->jointDampingRatio, context.h ); + + context.restitutionThreshold = world->restitutionThreshold; + context.maxLinearVelocity = world->maxLinearSpeed; + context.enableWarmStarting = world->enableWarmStarting; + + // Update contacts + { + uint64_t collideTicks = b2GetTicks(); + b2Collide( &context ); + world->profile.collide = b2GetMilliseconds( collideTicks ); + } + + // Integrate velocities, solve velocity constraints, and integrate positions. + if ( context.dt > 0.0f ) + { + uint64_t solveTicks = b2GetTicks(); + b2Solve( world, &context ); + world->profile.solve = b2GetMilliseconds( solveTicks ); + } + + // Update sensors + { + uint64_t sensorTicks = b2GetTicks(); + b2OverlapSensors( world ); + world->profile.sensors = b2GetMilliseconds( sensorTicks ); + } + + world->profile.step = b2GetMilliseconds( stepTicks ); + + B2_ASSERT( b2GetArenaAllocation( &world->arena ) == 0 ); + + // Ensure stack is large enough + b2GrowArena( &world->arena ); + + // Make sure all tasks that were started were also finished + B2_ASSERT( world->activeTaskCount == 0 ); + + b2TracyCZoneEnd( world_step ); + + // Swap end event array buffers + world->endEventArrayIndex = 1 - world->endEventArrayIndex; + b2SensorEndTouchEventArray_Clear( world->sensorEndEvents + world->endEventArrayIndex ); + b2ContactEndTouchEventArray_Clear( world->contactEndEvents + world->endEventArrayIndex ); + world->locked = false; +} + +static void b2DrawShape( b2DebugDraw* draw, b2Shape* shape, b2Transform xf, b2HexColor color ) +{ + switch ( shape->type ) + { + case b2_capsuleShape: + { + b2Capsule* capsule = &shape->capsule; + b2Vec2 p1 = b2TransformPoint( xf, capsule->center1 ); + b2Vec2 p2 = b2TransformPoint( xf, capsule->center2 ); + draw->DrawSolidCapsuleFcn( p1, p2, capsule->radius, color, draw->context ); + } + break; + + case b2_circleShape: + { + b2Circle* circle = &shape->circle; + xf.p = b2TransformPoint( xf, circle->center ); + draw->DrawSolidCircleFcn( xf, circle->radius, color, draw->context ); + } + break; + + case b2_polygonShape: + { + b2Polygon* poly = &shape->polygon; + draw->DrawSolidPolygonFcn( xf, poly->vertices, poly->count, poly->radius, color, draw->context ); + } + break; + + case b2_segmentShape: + { + b2Segment* segment = &shape->segment; + b2Vec2 p1 = b2TransformPoint( xf, segment->point1 ); + b2Vec2 p2 = b2TransformPoint( xf, segment->point2 ); + draw->DrawSegmentFcn( p1, p2, color, draw->context ); + } + break; + + case b2_chainSegmentShape: + { + b2Segment* segment = &shape->chainSegment.segment; + b2Vec2 p1 = b2TransformPoint( xf, segment->point1 ); + b2Vec2 p2 = b2TransformPoint( xf, segment->point2 ); + draw->DrawSegmentFcn( p1, p2, color, draw->context ); + draw->DrawPointFcn( p2, 4.0f, color, draw->context ); + draw->DrawSegmentFcn( p1, b2Lerp( p1, p2, 0.1f ), b2_colorPaleGreen, draw->context ); + } + break; + + default: + break; + } +} + +struct DrawContext +{ + b2World* world; + b2DebugDraw* draw; +}; + +static bool DrawQueryCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + struct DrawContext* drawContext = context; + b2World* world = drawContext->world; + b2DebugDraw* draw = drawContext->draw; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + B2_ASSERT( shape->id == shapeId ); + + b2SetBit( &world->debugBodySet, shape->bodyId ); + + if ( draw->drawShapes ) + { + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2BodySim* bodySim = b2GetBodySim( world, body ); + + b2HexColor color; + + if ( shape->customColor != 0 ) + { + color = shape->customColor; + } + else if ( body->type == b2_dynamicBody && body->mass == 0.0f ) + { + // Bad body + color = b2_colorRed; + } + else if ( body->setIndex == b2_disabledSet ) + { + color = b2_colorSlateGray; + } + else if ( shape->sensorIndex != B2_NULL_INDEX ) + { + color = b2_colorWheat; + } + else if ( bodySim->isBullet && body->setIndex == b2_awakeSet ) + { + color = b2_colorTurquoise; + } + else if ( body->isSpeedCapped ) + { + color = b2_colorYellow; + } + else if ( bodySim->isFast ) + { + color = b2_colorSalmon; + } + else if ( body->type == b2_staticBody ) + { + color = b2_colorPaleGreen; + } + else if ( body->type == b2_kinematicBody ) + { + color = b2_colorRoyalBlue; + } + else if ( body->setIndex == b2_awakeSet ) + { + color = b2_colorPink; + } + else + { + color = b2_colorGray; + } + + b2DrawShape( draw, shape, bodySim->transform, color ); + } + + if ( draw->drawBounds ) + { + b2AABB aabb = shape->fatAABB; + + b2Vec2 vs[4] = { { aabb.lowerBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.upperBound.y }, + { aabb.lowerBound.x, aabb.upperBound.y } }; + + draw->DrawPolygonFcn( vs, 4, b2_colorGold, draw->context ); + } + + return true; +} + +// todo this has varying order for moving shapes, causing flicker when overlapping shapes are moving +// solution: display order by shape id modulus 3, keep 3 buckets in GLSolid* and flush in 3 passes. +static void b2DrawWithBounds( b2World* world, b2DebugDraw* draw ) +{ + B2_ASSERT( b2IsValidAABB( draw->drawingBounds ) ); + + const float k_impulseScale = 1.0f; + const float k_axisScale = 0.3f; + b2HexColor speculativeColor = b2_colorGainsboro; + b2HexColor addColor = b2_colorGreen; + b2HexColor persistColor = b2_colorBlue; + b2HexColor normalColor = b2_colorDimGray; + b2HexColor impulseColor = b2_colorMagenta; + b2HexColor frictionColor = b2_colorYellow; + + b2HexColor graphColors[B2_GRAPH_COLOR_COUNT] = { b2_colorRed, b2_colorOrange, b2_colorYellow, b2_colorGreen, + b2_colorCyan, b2_colorBlue, b2_colorViolet, b2_colorPink, + b2_colorChocolate, b2_colorGoldenRod, b2_colorCoral, b2_colorBlack }; + + int bodyCapacity = b2GetIdCapacity( &world->bodyIdPool ); + b2SetBitCountAndClear( &world->debugBodySet, bodyCapacity ); + + int jointCapacity = b2GetIdCapacity( &world->jointIdPool ); + b2SetBitCountAndClear( &world->debugJointSet, jointCapacity ); + + int contactCapacity = b2GetIdCapacity( &world->contactIdPool ); + b2SetBitCountAndClear( &world->debugContactSet, contactCapacity ); + + struct DrawContext drawContext = { world, draw }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2DynamicTree_Query( world->broadPhase.trees + i, draw->drawingBounds, B2_DEFAULT_MASK_BITS, DrawQueryCallback, + &drawContext ); + } + + uint32_t wordCount = world->debugBodySet.blockCount; + uint64_t* bits = world->debugBodySet.bits; + for ( uint32_t k = 0; k < wordCount; ++k ) + { + uint64_t word = bits[k]; + while ( word != 0 ) + { + uint32_t ctz = b2CTZ64( word ); + uint32_t bodyId = 64 * k + ctz; + + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + + if ( draw->drawBodyNames && body->name[0] != 0 ) + { + b2Vec2 offset = { 0.1f, 0.1f }; + b2BodySim* bodySim = b2GetBodySim( world, body ); + + b2Transform transform = { bodySim->center, bodySim->transform.q }; + b2Vec2 p = b2TransformPoint( transform, offset ); + draw->DrawStringFcn( p, body->name, b2_colorBlueViolet, draw->context ); + } + + if ( draw->drawMass && body->type == b2_dynamicBody ) + { + b2Vec2 offset = { 0.1f, 0.1f }; + b2BodySim* bodySim = b2GetBodySim( world, body ); + + b2Transform transform = { bodySim->center, bodySim->transform.q }; + draw->DrawTransformFcn( transform, draw->context ); + + b2Vec2 p = b2TransformPoint( transform, offset ); + + char buffer[32]; + snprintf( buffer, 32, " %.2f", body->mass ); + draw->DrawStringFcn( p, buffer, b2_colorWhite, draw->context ); + } + + if ( draw->drawJoints ) + { + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + + // avoid double draw + if ( b2GetBit( &world->debugJointSet, jointId ) == false ) + { + b2DrawJoint( draw, world, joint ); + b2SetBit( &world->debugJointSet, jointId ); + } + else + { + // todo testing + edgeIndex += 0; + } + + jointKey = joint->edges[edgeIndex].nextKey; + } + } + + const float linearSlop = B2_LINEAR_SLOP; + if ( draw->drawContacts && body->type == b2_dynamicBody && body->setIndex == b2_awakeSet ) + { + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + contactKey = contact->edges[edgeIndex].nextKey; + + if ( contact->setIndex != b2_awakeSet || contact->colorIndex == B2_NULL_INDEX ) + { + continue; + } + + // avoid double draw + if ( b2GetBit( &world->debugContactSet, contactId ) == false ) + { + B2_ASSERT( 0 <= contact->colorIndex && contact->colorIndex < B2_GRAPH_COLOR_COUNT ); + + b2GraphColor* gc = world->constraintGraph.colors + contact->colorIndex; + b2ContactSim* contactSim = b2ContactSimArray_Get( &gc->contactSims, contact->localIndex ); + int pointCount = contactSim->manifold.pointCount; + b2Vec2 normal = contactSim->manifold.normal; + char buffer[32]; + + for ( int j = 0; j < pointCount; ++j ) + { + b2ManifoldPoint* point = contactSim->manifold.points + j; + + if ( draw->drawGraphColors ) + { + // graph color + float pointSize = contact->colorIndex == B2_OVERFLOW_INDEX ? 7.5f : 5.0f; + draw->DrawPointFcn( point->point, pointSize, graphColors[contact->colorIndex], draw->context ); + // g_draw.DrawString(point->position, "%d", point->color); + } + else if ( point->separation > linearSlop ) + { + // Speculative + draw->DrawPointFcn( point->point, 5.0f, speculativeColor, draw->context ); + } + else if ( point->persisted == false ) + { + // Add + draw->DrawPointFcn( point->point, 10.0f, addColor, draw->context ); + } + else if ( point->persisted == true ) + { + // Persist + draw->DrawPointFcn( point->point, 5.0f, persistColor, draw->context ); + } + + if ( draw->drawContactNormals ) + { + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_axisScale, normal ); + draw->DrawSegmentFcn( p1, p2, normalColor, draw->context ); + } + else if ( draw->drawContactImpulses ) + { + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_impulseScale * point->normalImpulse, normal ); + draw->DrawSegmentFcn( p1, p2, impulseColor, draw->context ); + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%.1f", 1000.0f * point->normalImpulse ); + draw->DrawStringFcn( p1, buffer, b2_colorWhite, draw->context ); + } + + if ( draw->drawContactFeatures ) + { + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%d", point->id ); + draw->DrawStringFcn( point->point, buffer, b2_colorOrange, draw->context ); + } + + if ( draw->drawFrictionImpulses ) + { + b2Vec2 tangent = b2RightPerp( normal ); + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_impulseScale * point->tangentImpulse, tangent ); + draw->DrawSegmentFcn( p1, p2, frictionColor, draw->context ); + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%.1f", 1000.0f * point->tangentImpulse ); + draw->DrawStringFcn( p1, buffer, b2_colorWhite, draw->context ); + } + } + + b2SetBit( &world->debugContactSet, contactId ); + } + else + { + // todo testing + edgeIndex += 0; + } + + contactKey = contact->edges[edgeIndex].nextKey; + } + } + + // Clear the smallest set bit + word = word & ( word - 1 ); + } + } +} + +void b2World_Draw( b2WorldId worldId, b2DebugDraw* draw ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + // todo it seems bounds drawing is fast enough for regular usage + if ( draw->useDrawingBounds ) + { + b2DrawWithBounds( world, draw ); + return; + } + + if ( draw->drawShapes ) + { + int setCount = world->solverSets.count; + for ( int setIndex = 0; setIndex < setCount; ++setIndex ) + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + int bodyCount = set->bodySims.count; + for ( int bodyIndex = 0; bodyIndex < bodyCount; ++bodyIndex ) + { + b2BodySim* bodySim = set->bodySims.data + bodyIndex; + b2Body* body = b2BodyArray_Get( &world->bodies, bodySim->bodyId ); + B2_ASSERT( body->setIndex == setIndex ); + + b2Transform xf = bodySim->transform; + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = world->shapes.data + shapeId; + b2HexColor color; + + if ( shape->customColor != 0 ) + { + color = shape->customColor; + } + else if ( body->type == b2_dynamicBody && body->mass == 0.0f ) + { + // Bad body + color = b2_colorRed; + } + else if ( body->setIndex == b2_disabledSet ) + { + color = b2_colorSlateGray; + } + else if ( shape->sensorIndex != B2_NULL_INDEX ) + { + color = b2_colorWheat; + } + else if ( bodySim->isBullet && body->setIndex == b2_awakeSet ) + { + color = b2_colorTurquoise; + } + else if ( body->isSpeedCapped ) + { + color = b2_colorYellow; + } + else if ( bodySim->isFast ) + { + color = b2_colorSalmon; + } + else if ( body->type == b2_staticBody ) + { + color = b2_colorPaleGreen; + } + else if ( body->type == b2_kinematicBody ) + { + color = b2_colorRoyalBlue; + } + else if ( body->setIndex == b2_awakeSet ) + { + color = b2_colorPink; + } + else + { + color = b2_colorGray; + } + + b2DrawShape( draw, shape, xf, color ); + shapeId = shape->nextShapeId; + } + } + } + } + + if ( draw->drawJoints ) + { + int count = world->joints.count; + for ( int i = 0; i < count; ++i ) + { + b2Joint* joint = world->joints.data + i; + if ( joint->setIndex == B2_NULL_INDEX ) + { + continue; + } + + b2DrawJoint( draw, world, joint ); + } + } + + if ( draw->drawBounds ) + { + b2HexColor color = b2_colorGold; + + int setCount = world->solverSets.count; + for ( int setIndex = 0; setIndex < setCount; ++setIndex ) + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + int bodyCount = set->bodySims.count; + for ( int bodyIndex = 0; bodyIndex < bodyCount; ++bodyIndex ) + { + b2BodySim* bodySim = set->bodySims.data + bodyIndex; + + char buffer[32]; + snprintf( buffer, 32, "%d", bodySim->bodyId ); + draw->DrawStringFcn( bodySim->center, buffer, b2_colorWhite, draw->context ); + + b2Body* body = b2BodyArray_Get( &world->bodies, bodySim->bodyId ); + B2_ASSERT( body->setIndex == setIndex ); + + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = world->shapes.data + shapeId; + b2AABB aabb = shape->fatAABB; + + b2Vec2 vs[4] = { { aabb.lowerBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.upperBound.y }, + { aabb.lowerBound.x, aabb.upperBound.y } }; + + draw->DrawPolygonFcn( vs, 4, color, draw->context ); + + shapeId = shape->nextShapeId; + } + } + } + } + + if ( draw->drawBodyNames ) + { + b2Vec2 offset = { 0.05f, 0.05f }; + int count = world->bodies.count; + for ( int i = 0; i < count; ++i ) + { + b2Body* body = world->bodies.data + i; + if ( body->setIndex == B2_NULL_INDEX ) + { + continue; + } + + if ( body->name[0] == 0 ) + { + continue; + } + + b2BodySim* bodySim = b2GetBodySim( world, body ); + + b2Transform transform = { bodySim->center, bodySim->transform.q }; + b2Vec2 p = b2TransformPoint( transform, offset ); + draw->DrawStringFcn( p, body->name, b2_colorBlueViolet, draw->context ); + } + } + + if ( draw->drawMass ) + { + b2Vec2 offset = { 0.1f, 0.1f }; + int setCount = world->solverSets.count; + for ( int setIndex = 0; setIndex < setCount; ++setIndex ) + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, setIndex ); + int bodyCount = set->bodySims.count; + for ( int bodyIndex = 0; bodyIndex < bodyCount; ++bodyIndex ) + { + b2BodySim* bodySim = set->bodySims.data + bodyIndex; + + b2Transform transform = { bodySim->center, bodySim->transform.q }; + draw->DrawTransformFcn( transform, draw->context ); + + b2Vec2 p = b2TransformPoint( transform, offset ); + + char buffer[32]; + float mass = bodySim->invMass > 0.0f ? 1.0f / bodySim->invMass : 0.0f; + snprintf( buffer, 32, " %.2f", mass ); + draw->DrawStringFcn( p, buffer, b2_colorWhite, draw->context ); + } + } + } + + if ( draw->drawContacts ) + { + const float k_impulseScale = 1.0f; + const float k_axisScale = 0.3f; + const float linearSlop = B2_LINEAR_SLOP; + + b2HexColor speculativeColor = b2_colorLightGray; + b2HexColor addColor = b2_colorGreen; + b2HexColor persistColor = b2_colorBlue; + b2HexColor normalColor = b2_colorDimGray; + b2HexColor impulseColor = b2_colorMagenta; + b2HexColor frictionColor = b2_colorYellow; + + b2HexColor colors[B2_GRAPH_COLOR_COUNT] = { b2_colorRed, b2_colorOrange, b2_colorYellow, b2_colorGreen, + b2_colorCyan, b2_colorBlue, b2_colorViolet, b2_colorPink, + b2_colorChocolate, b2_colorGoldenRod, b2_colorCoral, b2_colorBlack }; + + for ( int colorIndex = 0; colorIndex < B2_GRAPH_COLOR_COUNT; ++colorIndex ) + { + b2GraphColor* graphColor = world->constraintGraph.colors + colorIndex; + + int contactCount = graphColor->contactSims.count; + for ( int contactIndex = 0; contactIndex < contactCount; ++contactIndex ) + { + b2ContactSim* contact = graphColor->contactSims.data + contactIndex; + int pointCount = contact->manifold.pointCount; + b2Vec2 normal = contact->manifold.normal; + char buffer[32]; + + for ( int j = 0; j < pointCount; ++j ) + { + b2ManifoldPoint* point = contact->manifold.points + j; + + if ( draw->drawGraphColors && 0 <= colorIndex && colorIndex <= B2_GRAPH_COLOR_COUNT ) + { + // graph color + float pointSize = colorIndex == B2_OVERFLOW_INDEX ? 7.5f : 5.0f; + draw->DrawPointFcn( point->point, pointSize, colors[colorIndex], draw->context ); + // g_draw.DrawString(point->position, "%d", point->color); + } + else if ( point->separation > linearSlop ) + { + // Speculative + draw->DrawPointFcn( point->point, 5.0f, speculativeColor, draw->context ); + } + else if ( point->persisted == false ) + { + // Add + draw->DrawPointFcn( point->point, 10.0f, addColor, draw->context ); + } + else if ( point->persisted == true ) + { + // Persist + draw->DrawPointFcn( point->point, 5.0f, persistColor, draw->context ); + } + + if ( draw->drawContactNormals ) + { + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_axisScale, normal ); + draw->DrawSegmentFcn( p1, p2, normalColor, draw->context ); + } + else if ( draw->drawContactImpulses ) + { + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_impulseScale * point->normalImpulse, normal ); + draw->DrawSegmentFcn( p1, p2, impulseColor, draw->context ); + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%.2f", 1000.0f * point->normalImpulse ); + draw->DrawStringFcn( p1, buffer, b2_colorWhite, draw->context ); + } + + if ( draw->drawContactFeatures ) + { + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%d", point->id ); + draw->DrawStringFcn( point->point, buffer, b2_colorOrange, draw->context ); + } + + if ( draw->drawFrictionImpulses ) + { + b2Vec2 tangent = b2RightPerp( normal ); + b2Vec2 p1 = point->point; + b2Vec2 p2 = b2MulAdd( p1, k_impulseScale * point->tangentImpulse, tangent ); + draw->DrawSegmentFcn( p1, p2, frictionColor, draw->context ); + snprintf( buffer, B2_ARRAY_COUNT( buffer ), "%.2f", point->tangentImpulse ); + draw->DrawStringFcn( p1, buffer, b2_colorWhite, draw->context ); + } + } + } + } + } + + if ( draw->drawIslands ) + { + int count = world->islands.count; + for ( int i = 0; i < count; ++i ) + { + b2Island* island = world->islands.data + i; + if ( island->setIndex == B2_NULL_INDEX ) + { + continue; + } + + int shapeCount = 0; + b2AABB aabb = { + .lowerBound = { FLT_MAX, FLT_MAX }, + .upperBound = { -FLT_MAX, -FLT_MAX }, + }; + + int bodyId = island->headBody; + while ( bodyId != B2_NULL_INDEX ) + { + b2Body* body = b2BodyArray_Get( &world->bodies, bodyId ); + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + aabb = b2AABB_Union( aabb, shape->fatAABB ); + shapeCount += 1; + shapeId = shape->nextShapeId; + } + + bodyId = body->islandNext; + } + + if ( shapeCount > 0 ) + { + b2Vec2 vs[4] = { { aabb.lowerBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.lowerBound.y }, + { aabb.upperBound.x, aabb.upperBound.y }, + { aabb.lowerBound.x, aabb.upperBound.y } }; + + draw->DrawPolygonFcn( vs, 4, b2_colorOrangeRed, draw->context ); + } + } + } +} + +b2BodyEvents b2World_GetBodyEvents( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return (b2BodyEvents){ 0 }; + } + + int count = world->bodyMoveEvents.count; + b2BodyEvents events = { world->bodyMoveEvents.data, count }; + return events; +} + +b2SensorEvents b2World_GetSensorEvents( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return (b2SensorEvents){ 0 }; + } + + // Careful to use previous buffer + int endEventArrayIndex = 1 - world->endEventArrayIndex; + + int beginCount = world->sensorBeginEvents.count; + int endCount = world->sensorEndEvents[endEventArrayIndex].count; + + b2SensorEvents events = { + .beginEvents = world->sensorBeginEvents.data, + .endEvents = world->sensorEndEvents[endEventArrayIndex].data, + .beginCount = beginCount, + .endCount = endCount, + }; + return events; +} + +b2ContactEvents b2World_GetContactEvents( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return (b2ContactEvents){ 0 }; + } + + // Careful to use previous buffer + int endEventArrayIndex = 1 - world->endEventArrayIndex; + + int beginCount = world->contactBeginEvents.count; + int endCount = world->contactEndEvents[endEventArrayIndex].count; + int hitCount = world->contactHitEvents.count; + + b2ContactEvents events = { + .beginEvents = world->contactBeginEvents.data, + .endEvents = world->contactEndEvents[endEventArrayIndex].data, + .hitEvents = world->contactHitEvents.data, + .beginCount = beginCount, + .endCount = endCount, + .hitCount = hitCount, + }; + + return events; +} + +bool b2World_IsValid( b2WorldId id ) +{ + if ( id.index1 < 1 || B2_MAX_WORLDS < id.index1 ) + { + return false; + } + + b2World* world = b2_worlds + ( id.index1 - 1 ); + + if ( world->worldId != id.index1 - 1 ) + { + // world is not allocated + return false; + } + + return id.generation == world->generation; +} + +bool b2Body_IsValid( b2BodyId id ) +{ + if ( B2_MAX_WORLDS <= id.world0 ) + { + // invalid world + return false; + } + + b2World* world = b2_worlds + id.world0; + if ( world->worldId != id.world0 ) + { + // world is free + return false; + } + + if ( id.index1 < 1 || world->bodies.count < id.index1 ) + { + // invalid index + return false; + } + + b2Body* body = world->bodies.data + ( id.index1 - 1 ); + if ( body->setIndex == B2_NULL_INDEX ) + { + // this was freed + return false; + } + + B2_ASSERT( body->localIndex != B2_NULL_INDEX ); + + if ( body->generation != id.generation ) + { + // this id is orphaned + return false; + } + + return true; +} + +bool b2Shape_IsValid( b2ShapeId id ) +{ + if ( B2_MAX_WORLDS <= id.world0 ) + { + return false; + } + + b2World* world = b2_worlds + id.world0; + if ( world->worldId != id.world0 ) + { + // world is free + return false; + } + + int shapeId = id.index1 - 1; + if ( shapeId < 0 || world->shapes.count <= shapeId ) + { + return false; + } + + b2Shape* shape = world->shapes.data + shapeId; + if ( shape->id == B2_NULL_INDEX ) + { + // shape is free + return false; + } + + B2_ASSERT( shape->id == shapeId ); + + return id.generation == shape->generation; +} + +bool b2Chain_IsValid( b2ChainId id ) +{ + if ( B2_MAX_WORLDS <= id.world0 ) + { + return false; + } + + b2World* world = b2_worlds + id.world0; + if ( world->worldId != id.world0 ) + { + // world is free + return false; + } + + int chainId = id.index1 - 1; + if ( chainId < 0 || world->chainShapes.count <= chainId ) + { + return false; + } + + b2ChainShape* chain = world->chainShapes.data + chainId; + if ( chain->id == B2_NULL_INDEX ) + { + // chain is free + return false; + } + + B2_ASSERT( chain->id == chainId ); + + return id.generation == chain->generation; +} + +bool b2Joint_IsValid( b2JointId id ) +{ + if ( B2_MAX_WORLDS <= id.world0 ) + { + return false; + } + + b2World* world = b2_worlds + id.world0; + if ( world->worldId != id.world0 ) + { + // world is free + return false; + } + + int jointId = id.index1 - 1; + if ( jointId < 0 || world->joints.count <= jointId ) + { + return false; + } + + b2Joint* joint = world->joints.data + jointId; + if ( joint->jointId == B2_NULL_INDEX ) + { + // joint is free + return false; + } + + B2_ASSERT( joint->jointId == jointId ); + + return id.generation == joint->generation; +} + +void b2World_EnableSleeping( b2WorldId worldId, bool flag ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + if ( flag == world->enableSleep ) + { + return; + } + + world->enableSleep = flag; + + if ( flag == false ) + { + int setCount = world->solverSets.count; + for ( int i = b2_firstSleepingSet; i < setCount; ++i ) + { + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, i ); + if ( set->bodySims.count > 0 ) + { + b2WakeSolverSet( world, i ); + } + } + } +} + +bool b2World_IsSleepingEnabled( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->enableSleep; +} + +void b2World_EnableWarmStarting( b2WorldId worldId, bool flag ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->enableWarmStarting = flag; +} + +bool b2World_IsWarmStartingEnabled( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->enableWarmStarting; +} + +int b2World_GetAwakeBodyCount( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + b2SolverSet* awakeSet = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + return awakeSet->bodySims.count; +} + +void b2World_EnableContinuous( b2WorldId worldId, bool flag ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->enableContinuous = flag; +} + +bool b2World_IsContinuousEnabled( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->enableContinuous; +} + +void b2World_SetRestitutionThreshold( b2WorldId worldId, float value ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->restitutionThreshold = b2ClampFloat( value, 0.0f, FLT_MAX ); +} + +float b2World_GetRestitutionThreshold( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->restitutionThreshold; +} + +void b2World_SetHitEventThreshold( b2WorldId worldId, float value ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->hitEventThreshold = b2ClampFloat( value, 0.0f, FLT_MAX ); +} + +float b2World_GetHitEventThreshold( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->hitEventThreshold; +} + +void b2World_SetContactTuning( b2WorldId worldId, float hertz, float dampingRatio, float pushSpeed ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->contactHertz = b2ClampFloat( hertz, 0.0f, FLT_MAX ); + world->contactDampingRatio = b2ClampFloat( dampingRatio, 0.0f, FLT_MAX ); + world->maxContactPushSpeed = b2ClampFloat( pushSpeed, 0.0f, FLT_MAX ); +} + +void b2World_SetJointTuning( b2WorldId worldId, float hertz, float dampingRatio ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->jointHertz = b2ClampFloat( hertz, 0.0f, FLT_MAX ); + world->jointDampingRatio = b2ClampFloat( dampingRatio, 0.0f, FLT_MAX ); +} + +void b2World_SetMaximumLinearSpeed( b2WorldId worldId, float maximumLinearSpeed ) +{ + B2_ASSERT( b2IsValidFloat( maximumLinearSpeed ) && maximumLinearSpeed > 0.0f ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + world->maxLinearSpeed = maximumLinearSpeed; +} + +float b2World_GetMaximumLinearSpeed( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->maxLinearSpeed; +} + +b2Profile b2World_GetProfile( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->profile; +} + +b2Counters b2World_GetCounters( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + b2Counters s = { 0 }; + s.bodyCount = b2GetIdCount( &world->bodyIdPool ); + s.shapeCount = b2GetIdCount( &world->shapeIdPool ); + s.contactCount = b2GetIdCount( &world->contactIdPool ); + s.jointCount = b2GetIdCount( &world->jointIdPool ); + s.islandCount = b2GetIdCount( &world->islandIdPool ); + + b2DynamicTree* staticTree = world->broadPhase.trees + b2_staticBody; + s.staticTreeHeight = b2DynamicTree_GetHeight( staticTree ); + + b2DynamicTree* dynamicTree = world->broadPhase.trees + b2_dynamicBody; + b2DynamicTree* kinematicTree = world->broadPhase.trees + b2_kinematicBody; + s.treeHeight = b2MaxInt( b2DynamicTree_GetHeight( dynamicTree ), b2DynamicTree_GetHeight( kinematicTree ) ); + + s.stackUsed = b2GetMaxArenaAllocation( &world->arena ); + s.byteCount = b2GetByteCount(); + s.taskCount = world->taskCount; + + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + s.colorCounts[i] = world->constraintGraph.colors[i].contactSims.count + world->constraintGraph.colors[i].jointSims.count; + } + return s; +} + +void b2World_SetUserData( b2WorldId worldId, void* userData ) +{ + b2World* world = b2GetWorldFromId( worldId ); + world->userData = userData; +} + +void* b2World_GetUserData( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->userData; +} + +void b2World_SetFrictionCallback( b2WorldId worldId, b2FrictionCallback* callback ) +{ + b2World* world = b2GetWorldFromId( worldId ); + if ( world->locked ) + { + return; + } + + if ( callback != NULL ) + { + world->frictionCallback = callback; + } + else + { + world->frictionCallback = b2DefaultFrictionCallback; + } +} + +void b2World_SetRestitutionCallback( b2WorldId worldId, b2RestitutionCallback* callback ) +{ + b2World* world = b2GetWorldFromId( worldId ); + if ( world->locked ) + { + return; + } + + if ( callback != NULL ) + { + world->restitutionCallback = callback; + } + else + { + world->restitutionCallback = b2DefaultRestitutionCallback; + } +} + +void b2World_DumpMemoryStats( b2WorldId worldId ) +{ + FILE* file = fopen( "box2d_memory.txt", "w" ); + if ( file == NULL ) + { + return; + } + + b2World* world = b2GetWorldFromId( worldId ); + + // id pools + fprintf( file, "id pools\n" ); + fprintf( file, "body ids: %d\n", b2GetIdBytes( &world->bodyIdPool ) ); + fprintf( file, "solver set ids: %d\n", b2GetIdBytes( &world->solverSetIdPool ) ); + fprintf( file, "joint ids: %d\n", b2GetIdBytes( &world->jointIdPool ) ); + fprintf( file, "contact ids: %d\n", b2GetIdBytes( &world->contactIdPool ) ); + fprintf( file, "island ids: %d\n", b2GetIdBytes( &world->islandIdPool ) ); + fprintf( file, "shape ids: %d\n", b2GetIdBytes( &world->shapeIdPool ) ); + fprintf( file, "chain ids: %d\n", b2GetIdBytes( &world->chainIdPool ) ); + fprintf( file, "\n" ); + + // world arrays + fprintf( file, "world arrays\n" ); + fprintf( file, "bodies: %d\n", b2BodyArray_ByteCount( &world->bodies ) ); + fprintf( file, "solver sets: %d\n", b2SolverSetArray_ByteCount( &world->solverSets ) ); + fprintf( file, "joints: %d\n", b2JointArray_ByteCount( &world->joints ) ); + fprintf( file, "contacts: %d\n", b2ContactArray_ByteCount( &world->contacts ) ); + fprintf( file, "islands: %d\n", b2IslandArray_ByteCount( &world->islands ) ); + fprintf( file, "shapes: %d\n", b2ShapeArray_ByteCount( &world->shapes ) ); + fprintf( file, "chains: %d\n", b2ChainShapeArray_ByteCount( &world->chainShapes ) ); + fprintf( file, "\n" ); + + // broad-phase + fprintf( file, "broad-phase\n" ); + fprintf( file, "static tree: %d\n", b2DynamicTree_GetByteCount( world->broadPhase.trees + b2_staticBody ) ); + fprintf( file, "kinematic tree: %d\n", b2DynamicTree_GetByteCount( world->broadPhase.trees + b2_kinematicBody ) ); + fprintf( file, "dynamic tree: %d\n", b2DynamicTree_GetByteCount( world->broadPhase.trees + b2_dynamicBody ) ); + b2HashSet* moveSet = &world->broadPhase.moveSet; + fprintf( file, "moveSet: %d (%d, %d)\n", b2GetHashSetBytes( moveSet ), moveSet->count, moveSet->capacity ); + fprintf( file, "moveArray: %d\n", b2IntArray_ByteCount( &world->broadPhase.moveArray ) ); + b2HashSet* pairSet = &world->broadPhase.pairSet; + fprintf( file, "pairSet: %d (%d, %d)\n", b2GetHashSetBytes( pairSet ), pairSet->count, pairSet->capacity ); + fprintf( file, "\n" ); + + // solver sets + int bodySimCapacity = 0; + int bodyStateCapacity = 0; + int jointSimCapacity = 0; + int contactSimCapacity = 0; + int islandSimCapacity = 0; + int solverSetCapacity = world->solverSets.count; + for ( int i = 0; i < solverSetCapacity; ++i ) + { + b2SolverSet* set = world->solverSets.data + i; + if ( set->setIndex == B2_NULL_INDEX ) + { + continue; + } + + bodySimCapacity += set->bodySims.capacity; + bodyStateCapacity += set->bodyStates.capacity; + jointSimCapacity += set->jointSims.capacity; + contactSimCapacity += set->contactSims.capacity; + islandSimCapacity += set->islandSims.capacity; + } + + fprintf( file, "solver sets\n" ); + fprintf( file, "body sim: %d\n", bodySimCapacity * (int)sizeof( b2BodySim ) ); + fprintf( file, "body state: %d\n", bodyStateCapacity * (int)sizeof( b2BodyState ) ); + fprintf( file, "joint sim: %d\n", jointSimCapacity * (int)sizeof( b2JointSim ) ); + fprintf( file, "contact sim: %d\n", contactSimCapacity * (int)sizeof( b2ContactSim ) ); + fprintf( file, "island sim: %d\n", islandSimCapacity * (int)sizeof( islandSimCapacity ) ); + fprintf( file, "\n" ); + + // constraint graph + int bodyBitSetBytes = 0; + contactSimCapacity = 0; + jointSimCapacity = 0; + for ( int i = 0; i < B2_GRAPH_COLOR_COUNT; ++i ) + { + b2GraphColor* c = world->constraintGraph.colors + i; + bodyBitSetBytes += b2GetBitSetBytes( &c->bodySet ); + contactSimCapacity += c->contactSims.capacity; + jointSimCapacity += c->jointSims.capacity; + } + + fprintf( file, "constraint graph\n" ); + fprintf( file, "body bit sets: %d\n", bodyBitSetBytes ); + fprintf( file, "joint sim: %d\n", jointSimCapacity * (int)sizeof( b2JointSim ) ); + fprintf( file, "contact sim: %d\n", contactSimCapacity * (int)sizeof( b2ContactSim ) ); + fprintf( file, "\n" ); + + // stack allocator + fprintf( file, "stack allocator: %d\n\n", world->arena.capacity ); + + // chain shapes + // todo + + fclose( file ); +} + +typedef struct WorldQueryContext +{ + b2World* world; + b2OverlapResultFcn* fcn; + b2QueryFilter filter; + void* userContext; +} WorldQueryContext; + +static bool TreeQueryCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + WorldQueryContext* worldContext = context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return true; + } + + b2ShapeId id = { shapeId + 1, world->worldId, shape->generation }; + bool result = worldContext->fcn( id, worldContext->userContext ); + return result; +} + +b2TreeStats b2World_OverlapAABB( b2WorldId worldId, b2AABB aabb, b2QueryFilter filter, b2OverlapResultFcn* fcn, void* context ) +{ + b2TreeStats treeStats = { 0 }; + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return treeStats; + } + + B2_ASSERT( b2IsValidAABB( aabb ) ); + + WorldQueryContext worldContext = { world, fcn, filter, context }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2TreeStats treeResult = + b2DynamicTree_Query( world->broadPhase.trees + i, aabb, filter.maskBits, TreeQueryCallback, &worldContext ); + + treeStats.nodeVisits += treeResult.nodeVisits; + treeStats.leafVisits += treeResult.leafVisits; + } + + return treeStats; +} + +typedef struct WorldOverlapContext +{ + b2World* world; + b2OverlapResultFcn* fcn; + b2QueryFilter filter; + const b2ShapeProxy* proxy; + void* userContext; +} WorldOverlapContext; + +static bool TreeOverlapCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + WorldOverlapContext* worldContext = context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return true; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2DistanceInput input; + input.proxyA = *worldContext->proxy; + input.proxyB = b2MakeShapeDistanceProxy( shape ); + input.transformA = b2Transform_identity; + input.transformB = transform; + input.useRadii = true; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput output = b2ShapeDistance( &input, &cache, NULL, 0 ); + + float tolerance = 0.1f * B2_LINEAR_SLOP; + if ( output.distance > tolerance ) + { + return true; + } + + b2ShapeId id = { shape->id + 1, world->worldId, shape->generation }; + bool result = worldContext->fcn( id, worldContext->userContext ); + return result; +} + +b2TreeStats b2World_OverlapShape( b2WorldId worldId, const b2ShapeProxy* proxy, b2QueryFilter filter, b2OverlapResultFcn* fcn, + void* context ) +{ + b2TreeStats treeStats = { 0 }; + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return treeStats; + } + + b2AABB aabb = b2MakeAABB( proxy->points, proxy->count, proxy->radius ); + WorldOverlapContext worldContext = { + world, fcn, filter, proxy, context, + }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2TreeStats treeResult = + b2DynamicTree_Query( world->broadPhase.trees + i, aabb, filter.maskBits, TreeOverlapCallback, &worldContext ); + + treeStats.nodeVisits += treeResult.nodeVisits; + treeStats.leafVisits += treeResult.leafVisits; + } + + return treeStats; +} + +typedef struct WorldRayCastContext +{ + b2World* world; + b2CastResultFcn* fcn; + b2QueryFilter filter; + float fraction; + void* userContext; +} WorldRayCastContext; + +static float RayCastCallback( const b2RayCastInput* input, int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + WorldRayCastContext* worldContext = context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return input->maxFraction; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + b2CastOutput output = b2RayCastShape( input, shape, transform ); + + if ( output.hit ) + { + b2ShapeId id = { shapeId + 1, world->worldId, shape->generation }; + float fraction = worldContext->fcn( id, output.point, output.normal, output.fraction, worldContext->userContext ); + + // The user may return -1 to skip this shape + if ( 0.0f <= fraction && fraction <= 1.0f ) + { + worldContext->fraction = fraction; + } + + return fraction; + } + + return input->maxFraction; +} + +b2TreeStats b2World_CastRay( b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter, b2CastResultFcn* fcn, + void* context ) +{ + b2TreeStats treeStats = { 0 }; + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return treeStats; + } + + B2_ASSERT( b2IsValidVec2( origin ) ); + B2_ASSERT( b2IsValidVec2( translation ) ); + + b2RayCastInput input = { origin, translation, 1.0f }; + + WorldRayCastContext worldContext = { world, fcn, filter, 1.0f, context }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2TreeStats treeResult = + b2DynamicTree_RayCast( world->broadPhase.trees + i, &input, filter.maskBits, RayCastCallback, &worldContext ); + treeStats.nodeVisits += treeResult.nodeVisits; + treeStats.leafVisits += treeResult.leafVisits; + + if ( worldContext.fraction == 0.0f ) + { + return treeStats; + } + + input.maxFraction = worldContext.fraction; + } + + return treeStats; +} + +// This callback finds the closest hit. This is the most common callback used in games. +static float b2RayCastClosestFcn( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + b2RayResult* rayResult = (b2RayResult*)context; + rayResult->shapeId = shapeId; + rayResult->point = point; + rayResult->normal = normal; + rayResult->fraction = fraction; + rayResult->hit = true; + return fraction; +} + +b2RayResult b2World_CastRayClosest( b2WorldId worldId, b2Vec2 origin, b2Vec2 translation, b2QueryFilter filter ) +{ + b2RayResult result = { 0 }; + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return result; + } + + B2_ASSERT( b2IsValidVec2( origin ) ); + B2_ASSERT( b2IsValidVec2( translation ) ); + + b2RayCastInput input = { origin, translation, 1.0f }; + WorldRayCastContext worldContext = { world, b2RayCastClosestFcn, filter, 1.0f, &result }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2TreeStats treeResult = + b2DynamicTree_RayCast( world->broadPhase.trees + i, &input, filter.maskBits, RayCastCallback, &worldContext ); + result.nodeVisits += treeResult.nodeVisits; + result.leafVisits += treeResult.leafVisits; + + if ( worldContext.fraction == 0.0f ) + { + return result; + } + + input.maxFraction = worldContext.fraction; + } + + return result; +} + +static float ShapeCastCallback( const b2ShapeCastInput* input, int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + WorldRayCastContext* worldContext = context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return input->maxFraction; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2CastOutput output = b2ShapeCastShape( input, shape, transform ); + + if ( output.hit ) + { + b2ShapeId id = { shapeId + 1, world->worldId, shape->generation }; + float fraction = worldContext->fcn( id, output.point, output.normal, output.fraction, worldContext->userContext ); + + // The user may return -1 to skip this shape + if ( 0.0f <= fraction && fraction <= 1.0f ) + { + worldContext->fraction = fraction; + } + + return fraction; + } + + return input->maxFraction; +} + +b2TreeStats b2World_CastShape( b2WorldId worldId, const b2ShapeProxy* proxy, b2Vec2 translation, b2QueryFilter filter, + b2CastResultFcn* fcn, void* context ) +{ + b2TreeStats treeStats = { 0 }; + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return treeStats; + } + + B2_ASSERT( b2IsValidVec2( translation ) ); + + b2ShapeCastInput input = { 0 }; + input.proxy = *proxy; + input.translation = translation; + input.maxFraction = 1.0f; + + WorldRayCastContext worldContext = { world, fcn, filter, 1.0f, context }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2TreeStats treeResult = + b2DynamicTree_ShapeCast( world->broadPhase.trees + i, &input, filter.maskBits, ShapeCastCallback, &worldContext ); + treeStats.nodeVisits += treeResult.nodeVisits; + treeStats.leafVisits += treeResult.leafVisits; + + if ( worldContext.fraction == 0.0f ) + { + return treeStats; + } + + input.maxFraction = worldContext.fraction; + } + + return treeStats; +} + +typedef struct b2MoverContext +{ + b2World* world; + b2QueryFilter filter; + b2ShapeProxy proxy; + b2Transform transform; + void* userContext; +} b2CharacterCallbackContext; + +typedef struct WorldMoverCastContext +{ + b2World* world; + b2QueryFilter filter; + float fraction; +} WorldMoverCastContext; + +static float MoverCastCallback( const b2ShapeCastInput* input, int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + WorldMoverCastContext* worldContext = context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return worldContext->fraction; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2CastOutput output = b2ShapeCastShape( input, shape, transform ); + if ( output.fraction == 0.0f ) + { + // Ignore overlapping shapes + return worldContext->fraction; + } + + worldContext->fraction = output.fraction; + return output.fraction; +} + +float b2World_CastMover( b2WorldId worldId, const b2Capsule* mover, b2Vec2 translation, b2QueryFilter filter ) +{ + B2_ASSERT( b2IsValidVec2( translation ) ); + B2_ASSERT( mover->radius > 2.0f * B2_LINEAR_SLOP ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return 1.0f; + } + + b2ShapeCastInput input = { 0 }; + input.proxy.points[0] = mover->center1; + input.proxy.points[1] = mover->center2; + input.proxy.count = 2; + input.proxy.radius = mover->radius; + input.translation = translation; + input.maxFraction = 1.0f; + input.canEncroach = true; + + WorldMoverCastContext worldContext = { world, filter, 1.0f }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2DynamicTree_ShapeCast( world->broadPhase.trees + i, &input, filter.maskBits, MoverCastCallback, &worldContext ); + + if ( worldContext.fraction == 0.0f ) + { + return 0.0f; + } + + input.maxFraction = worldContext.fraction; + } + + return worldContext.fraction; +} + +typedef struct WorldMoverContext +{ + b2World* world; + b2PlaneResultFcn* fcn; + b2QueryFilter filter; + b2Capsule mover; + void* userContext; +} WorldMoverContext; + +static bool TreeCollideCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + WorldMoverContext* worldContext = (WorldMoverContext*)context; + b2World* world = worldContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2Filter shapeFilter = shape->filter; + b2QueryFilter queryFilter = worldContext->filter; + + if ( ( shapeFilter.categoryBits & queryFilter.maskBits ) == 0 || ( shapeFilter.maskBits & queryFilter.categoryBits ) == 0 ) + { + return true; + } + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2PlaneResult result = b2CollideMover( shape, transform, &worldContext->mover ); + + if ( result.hit ) + { + b2ShapeId id = { shape->id + 1, world->worldId, shape->generation }; + return worldContext->fcn( id, &result, worldContext->userContext ); + } + + return true; +} + +// It is tempting to use a shape proxy for the mover, but this makes handling deep overlap difficult and the generality may +// not be worth it. +void b2World_CollideMover( b2WorldId worldId, const b2Capsule* mover, b2QueryFilter filter, b2PlaneResultFcn* fcn, void* context ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + b2Vec2 r = { mover->radius, mover->radius }; + + b2AABB aabb; + aabb.lowerBound = b2Sub( b2Min( mover->center1, mover->center2 ), r ); + aabb.upperBound = b2Add( b2Max( mover->center1, mover->center2 ), r ); + + WorldMoverContext worldContext = { + world, fcn, filter, *mover, context, + }; + + for ( int i = 0; i < b2_bodyTypeCount; ++i ) + { + b2DynamicTree_Query( world->broadPhase.trees + i, aabb, filter.maskBits, TreeCollideCallback, &worldContext ); + } +} + +#if 0 + +void b2World_Dump() +{ + if (m_locked) + { + return; + } + + b2OpenDump("box2d_dump.inl"); + + b2Dump("b2Vec2 g(%.9g, %.9g);\n", m_gravity.x, m_gravity.y); + b2Dump("m_world->SetGravity(g);\n"); + + b2Dump("b2Body** sims = (b2Body**)b2Alloc(%d * sizeof(b2Body*));\n", m_bodyCount); + b2Dump("b2Joint** joints = (b2Joint**)b2Alloc(%d * sizeof(b2Joint*));\n", m_jointCount); + + int32 i = 0; + for (b2Body* b = m_bodyList; b; b = b->m_next) + { + b->m_islandIndex = i; + b->Dump(); + ++i; + } + + i = 0; + for (b2Joint* j = m_jointList; j; j = j->m_next) + { + j->m_index = i; + ++i; + } + + // First pass on joints, skip gear joints. + for (b2Joint* j = m_jointList; j; j = j->m_next) + { + if (j->m_type == e_gearJoint) + { + continue; + } + + b2Dump("{\n"); + j->Dump(); + b2Dump("}\n"); + } + + // Second pass on joints, only gear joints. + for (b2Joint* j = m_jointList; j; j = j->m_next) + { + if (j->m_type != e_gearJoint) + { + continue; + } + + b2Dump("{\n"); + j->Dump(); + b2Dump("}\n"); + } + + b2Dump("b2Free(joints);\n"); + b2Dump("b2Free(sims);\n"); + b2Dump("joints = nullptr;\n"); + b2Dump("sims = nullptr;\n"); + + b2CloseDump(); +} +#endif + +void b2World_SetCustomFilterCallback( b2WorldId worldId, b2CustomFilterFcn* fcn, void* context ) +{ + b2World* world = b2GetWorldFromId( worldId ); + world->customFilterFcn = fcn; + world->customFilterContext = context; +} + +void b2World_SetPreSolveCallback( b2WorldId worldId, b2PreSolveFcn* fcn, void* context ) +{ + b2World* world = b2GetWorldFromId( worldId ); + world->preSolveFcn = fcn; + world->preSolveContext = context; +} + +void b2World_SetGravity( b2WorldId worldId, b2Vec2 gravity ) +{ + b2World* world = b2GetWorldFromId( worldId ); + world->gravity = gravity; +} + +b2Vec2 b2World_GetGravity( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + return world->gravity; +} + +struct ExplosionContext +{ + b2World* world; + b2Vec2 position; + float radius; + float falloff; + float impulsePerLength; +}; + +static bool ExplosionCallback( int proxyId, uint64_t userData, void* context ) +{ + B2_UNUSED( proxyId ); + + int shapeId = (int)userData; + + struct ExplosionContext* explosionContext = context; + b2World* world = explosionContext->world; + + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + + b2Body* body = b2BodyArray_Get( &world->bodies, shape->bodyId ); + B2_ASSERT( body->type == b2_dynamicBody ); + + b2Transform transform = b2GetBodyTransformQuick( world, body ); + + b2DistanceInput input; + input.proxyA = b2MakeShapeDistanceProxy( shape ); + input.proxyB = b2MakeProxy( &explosionContext->position, 1, 0.0f ); + input.transformA = transform; + input.transformB = b2Transform_identity; + input.useRadii = true; + + b2SimplexCache cache = { 0 }; + b2DistanceOutput output = b2ShapeDistance( &input, &cache, NULL, 0 ); + + float radius = explosionContext->radius; + float falloff = explosionContext->falloff; + if ( output.distance > radius + falloff ) + { + return true; + } + + b2WakeBody( world, body ); + + if ( body->setIndex != b2_awakeSet ) + { + return true; + } + + b2Vec2 closestPoint = output.pointA; + if ( output.distance == 0.0f ) + { + b2Vec2 localCentroid = b2GetShapeCentroid( shape ); + closestPoint = b2TransformPoint( transform, localCentroid ); + } + + b2Vec2 direction = b2Sub( closestPoint, explosionContext->position ); + if ( b2LengthSquared( direction ) > 100.0f * FLT_EPSILON * FLT_EPSILON ) + { + direction = b2Normalize( direction ); + } + else + { + direction = (b2Vec2){ 1.0f, 0.0f }; + } + + b2Vec2 localLine = b2InvRotateVector( transform.q, b2LeftPerp( direction ) ); + float perimeter = b2GetShapeProjectedPerimeter( shape, localLine ); + float scale = 1.0f; + if ( output.distance > radius && falloff > 0.0f ) + { + scale = b2ClampFloat( ( radius + falloff - output.distance ) / falloff, 0.0f, 1.0f ); + } + + float magnitude = explosionContext->impulsePerLength * perimeter * scale; + b2Vec2 impulse = b2MulSV( magnitude, direction ); + + int localIndex = body->localIndex; + b2SolverSet* set = b2SolverSetArray_Get( &world->solverSets, b2_awakeSet ); + b2BodyState* state = b2BodyStateArray_Get( &set->bodyStates, localIndex ); + b2BodySim* bodySim = b2BodySimArray_Get( &set->bodySims, localIndex ); + state->linearVelocity = b2MulAdd( state->linearVelocity, bodySim->invMass, impulse ); + state->angularVelocity += bodySim->invInertia * b2Cross( b2Sub( closestPoint, bodySim->center ), impulse ); + + return true; +} + +void b2World_Explode( b2WorldId worldId, const b2ExplosionDef* explosionDef ) +{ + uint64_t maskBits = explosionDef->maskBits; + b2Vec2 position = explosionDef->position; + float radius = explosionDef->radius; + float falloff = explosionDef->falloff; + float impulsePerLength = explosionDef->impulsePerLength; + + B2_ASSERT( b2IsValidVec2( position ) ); + B2_ASSERT( b2IsValidFloat( radius ) && radius >= 0.0f ); + B2_ASSERT( b2IsValidFloat( falloff ) && falloff >= 0.0f ); + B2_ASSERT( b2IsValidFloat( impulsePerLength ) ); + + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + struct ExplosionContext explosionContext = { world, position, radius, falloff, impulsePerLength }; + + b2AABB aabb; + aabb.lowerBound.x = position.x - ( radius + falloff ); + aabb.lowerBound.y = position.y - ( radius + falloff ); + aabb.upperBound.x = position.x + ( radius + falloff ); + aabb.upperBound.y = position.y + ( radius + falloff ); + + b2DynamicTree_Query( world->broadPhase.trees + b2_dynamicBody, aabb, maskBits, ExplosionCallback, &explosionContext ); +} + +void b2World_RebuildStaticTree( b2WorldId worldId ) +{ + b2World* world = b2GetWorldFromId( worldId ); + B2_ASSERT( world->locked == false ); + if ( world->locked ) + { + return; + } + + b2DynamicTree* staticTree = world->broadPhase.trees + b2_staticBody; + b2DynamicTree_Rebuild( staticTree, true ); +} + +void b2World_EnableSpeculative( b2WorldId worldId, bool flag ) +{ + b2World* world = b2GetWorldFromId( worldId ); + world->enableSpeculative = flag; +} + +#if B2_VALIDATE +// When validating islands ids I have to compare the root island +// ids because islands are not merged until the next time step. +static int b2GetRootIslandId( b2World* world, int islandId ) +{ + if ( islandId == B2_NULL_INDEX ) + { + return B2_NULL_INDEX; + } + + b2Island* island = b2IslandArray_Get( &world->islands, islandId ); + + int rootId = islandId; + b2Island* rootIsland = island; + while ( rootIsland->parentIsland != B2_NULL_INDEX ) + { + b2Island* parent = b2IslandArray_Get( &world->islands, rootIsland->parentIsland ); + rootId = rootIsland->parentIsland; + rootIsland = parent; + } + + return rootId; +} + +// This validates island graph connectivity for each body +void b2ValidateConnectivity( b2World* world ) +{ + b2Body* bodies = world->bodies.data; + int bodyCapacity = world->bodies.count; + + for ( int bodyIndex = 0; bodyIndex < bodyCapacity; ++bodyIndex ) + { + b2Body* body = bodies + bodyIndex; + if ( body->id == B2_NULL_INDEX ) + { + b2ValidateFreeId( &world->bodyIdPool, bodyIndex ); + continue; + } + + b2ValidateUsedId( &world->bodyIdPool, bodyIndex ); + + B2_ASSERT( bodyIndex == body->id ); + + // Need to get the root island because islands are not merged until the next time step + int bodyIslandId = b2GetRootIslandId( world, body->islandId ); + int bodySetIndex = body->setIndex; + + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + + bool touching = ( contact->flags & b2_contactTouchingFlag ) != 0; + if ( touching ) + { + if ( bodySetIndex != b2_staticSet ) + { + int contactIslandId = b2GetRootIslandId( world, contact->islandId ); + B2_ASSERT( contactIslandId == bodyIslandId ); + } + } + else + { + B2_ASSERT( contact->islandId == B2_NULL_INDEX ); + } + + contactKey = contact->edges[edgeIndex].nextKey; + } + + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + + int otherEdgeIndex = edgeIndex ^ 1; + + b2Body* otherBody = b2BodyArray_Get( &world->bodies, joint->edges[otherEdgeIndex].bodyId ); + + if ( bodySetIndex == b2_disabledSet || otherBody->setIndex == b2_disabledSet ) + { + B2_ASSERT( joint->islandId == B2_NULL_INDEX ); + } + else if ( bodySetIndex == b2_staticSet ) + { + if ( otherBody->setIndex == b2_staticSet ) + { + B2_ASSERT( joint->islandId == B2_NULL_INDEX ); + } + } + else + { + int jointIslandId = b2GetRootIslandId( world, joint->islandId ); + B2_ASSERT( jointIslandId == bodyIslandId ); + } + + jointKey = joint->edges[edgeIndex].nextKey; + } + } +} + +// Validates solver sets, but not island connectivity +void b2ValidateSolverSets( b2World* world ) +{ + B2_ASSERT( b2GetIdCapacity( &world->bodyIdPool ) == world->bodies.count ); + B2_ASSERT( b2GetIdCapacity( &world->contactIdPool ) == world->contacts.count ); + B2_ASSERT( b2GetIdCapacity( &world->jointIdPool ) == world->joints.count ); + B2_ASSERT( b2GetIdCapacity( &world->islandIdPool ) == world->islands.count ); + B2_ASSERT( b2GetIdCapacity( &world->solverSetIdPool ) == world->solverSets.count ); + + int activeSetCount = 0; + int totalBodyCount = 0; + int totalJointCount = 0; + int totalContactCount = 0; + int totalIslandCount = 0; + + // Validate all solver sets + int setCount = world->solverSets.count; + for ( int setIndex = 0; setIndex < setCount; ++setIndex ) + { + b2SolverSet* set = world->solverSets.data + setIndex; + if ( set->setIndex != B2_NULL_INDEX ) + { + activeSetCount += 1; + + if ( setIndex == b2_staticSet ) + { + B2_ASSERT( set->contactSims.count == 0 ); + B2_ASSERT( set->islandSims.count == 0 ); + B2_ASSERT( set->bodyStates.count == 0 ); + } + else if ( setIndex == b2_awakeSet ) + { + B2_ASSERT( set->bodySims.count == set->bodyStates.count ); + B2_ASSERT( set->jointSims.count == 0 ); + } + else if ( setIndex == b2_disabledSet ) + { + B2_ASSERT( set->islandSims.count == 0 ); + B2_ASSERT( set->bodyStates.count == 0 ); + } + else + { + B2_ASSERT( set->bodyStates.count == 0 ); + } + + // Validate bodies + { + b2Body* bodies = world->bodies.data; + B2_ASSERT( set->bodySims.count >= 0 ); + totalBodyCount += set->bodySims.count; + for ( int i = 0; i < set->bodySims.count; ++i ) + { + b2BodySim* bodySim = set->bodySims.data + i; + + int bodyId = bodySim->bodyId; + B2_ASSERT( 0 <= bodyId && bodyId < world->bodies.count ); + b2Body* body = bodies + bodyId; + B2_ASSERT( body->setIndex == setIndex ); + B2_ASSERT( body->localIndex == i ); + B2_ASSERT( body->generation == body->generation ); + + if ( setIndex == b2_disabledSet ) + { + B2_ASSERT( body->headContactKey == B2_NULL_INDEX ); + } + + // Validate body shapes + int prevShapeId = B2_NULL_INDEX; + int shapeId = body->headShapeId; + while ( shapeId != B2_NULL_INDEX ) + { + b2Shape* shape = b2ShapeArray_Get( &world->shapes, shapeId ); + B2_ASSERT( shape->id == shapeId ); + B2_ASSERT( shape->prevShapeId == prevShapeId ); + + if ( setIndex == b2_disabledSet ) + { + B2_ASSERT( shape->proxyKey == B2_NULL_INDEX ); + } + else if ( setIndex == b2_staticSet ) + { + B2_ASSERT( B2_PROXY_TYPE( shape->proxyKey ) == b2_staticBody ); + } + else + { + b2BodyType proxyType = B2_PROXY_TYPE( shape->proxyKey ); + B2_ASSERT( proxyType == b2_kinematicBody || proxyType == b2_dynamicBody ); + } + + prevShapeId = shapeId; + shapeId = shape->nextShapeId; + } + + // Validate body contacts + int contactKey = body->headContactKey; + while ( contactKey != B2_NULL_INDEX ) + { + int contactId = contactKey >> 1; + int edgeIndex = contactKey & 1; + + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactId ); + B2_ASSERT( contact->setIndex != b2_staticSet ); + B2_ASSERT( contact->edges[0].bodyId == bodyId || contact->edges[1].bodyId == bodyId ); + contactKey = contact->edges[edgeIndex].nextKey; + } + + // Validate body joints + int jointKey = body->headJointKey; + while ( jointKey != B2_NULL_INDEX ) + { + int jointId = jointKey >> 1; + int edgeIndex = jointKey & 1; + + b2Joint* joint = b2JointArray_Get( &world->joints, jointId ); + + int otherEdgeIndex = edgeIndex ^ 1; + + b2Body* otherBody = b2BodyArray_Get( &world->bodies, joint->edges[otherEdgeIndex].bodyId ); + + if ( setIndex == b2_disabledSet || otherBody->setIndex == b2_disabledSet ) + { + B2_ASSERT( joint->setIndex == b2_disabledSet ); + } + else if ( setIndex == b2_staticSet && otherBody->setIndex == b2_staticSet ) + { + B2_ASSERT( joint->setIndex == b2_staticSet ); + } + else if ( setIndex == b2_awakeSet ) + { + B2_ASSERT( joint->setIndex == b2_awakeSet ); + } + else if ( setIndex >= b2_firstSleepingSet ) + { + B2_ASSERT( joint->setIndex == setIndex ); + } + + b2JointSim* jointSim = b2GetJointSim( world, joint ); + B2_ASSERT( jointSim->jointId == jointId ); + B2_ASSERT( jointSim->bodyIdA == joint->edges[0].bodyId ); + B2_ASSERT( jointSim->bodyIdB == joint->edges[1].bodyId ); + + jointKey = joint->edges[edgeIndex].nextKey; + } + } + } + + // Validate contacts + { + B2_ASSERT( set->contactSims.count >= 0 ); + totalContactCount += set->contactSims.count; + for ( int i = 0; i < set->contactSims.count; ++i ) + { + b2ContactSim* contactSim = set->contactSims.data + i; + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactSim->contactId ); + if ( setIndex == b2_awakeSet ) + { + // contact should be non-touching if awake + // or it could be this contact hasn't been transferred yet + B2_ASSERT( contactSim->manifold.pointCount == 0 || + ( contactSim->simFlags & b2_simStartedTouching ) != 0 ); + } + B2_ASSERT( contact->setIndex == setIndex ); + B2_ASSERT( contact->colorIndex == B2_NULL_INDEX ); + B2_ASSERT( contact->localIndex == i ); + } + } + + // Validate joints + { + B2_ASSERT( set->jointSims.count >= 0 ); + totalJointCount += set->jointSims.count; + for ( int i = 0; i < set->jointSims.count; ++i ) + { + b2JointSim* jointSim = set->jointSims.data + i; + b2Joint* joint = b2JointArray_Get( &world->joints, jointSim->jointId ); + B2_ASSERT( joint->setIndex == setIndex ); + B2_ASSERT( joint->colorIndex == B2_NULL_INDEX ); + B2_ASSERT( joint->localIndex == i ); + } + } + + // Validate islands + { + B2_ASSERT( set->islandSims.count >= 0 ); + totalIslandCount += set->islandSims.count; + for ( int i = 0; i < set->islandSims.count; ++i ) + { + b2IslandSim* islandSim = set->islandSims.data + i; + b2Island* island = b2IslandArray_Get( &world->islands, islandSim->islandId ); + B2_ASSERT( island->setIndex == setIndex ); + B2_ASSERT( island->localIndex == i ); + } + } + } + else + { + B2_ASSERT( set->bodySims.count == 0 ); + B2_ASSERT( set->contactSims.count == 0 ); + B2_ASSERT( set->jointSims.count == 0 ); + B2_ASSERT( set->islandSims.count == 0 ); + B2_ASSERT( set->bodyStates.count == 0 ); + } + } + + int setIdCount = b2GetIdCount( &world->solverSetIdPool ); + B2_ASSERT( activeSetCount == setIdCount ); + + int bodyIdCount = b2GetIdCount( &world->bodyIdPool ); + B2_ASSERT( totalBodyCount == bodyIdCount ); + + int islandIdCount = b2GetIdCount( &world->islandIdPool ); + B2_ASSERT( totalIslandCount == islandIdCount ); + + // Validate constraint graph + for ( int colorIndex = 0; colorIndex < B2_GRAPH_COLOR_COUNT; ++colorIndex ) + { + b2GraphColor* color = world->constraintGraph.colors + colorIndex; + { + B2_ASSERT( color->contactSims.count >= 0 ); + totalContactCount += color->contactSims.count; + for ( int i = 0; i < color->contactSims.count; ++i ) + { + b2ContactSim* contactSim = color->contactSims.data + i; + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactSim->contactId ); + // contact should be touching in the constraint graph or awaiting transfer to non-touching + B2_ASSERT( contactSim->manifold.pointCount > 0 || + ( contactSim->simFlags & ( b2_simStoppedTouching | b2_simDisjoint ) ) != 0 ); + B2_ASSERT( contact->setIndex == b2_awakeSet ); + B2_ASSERT( contact->colorIndex == colorIndex ); + B2_ASSERT( contact->localIndex == i ); + + int bodyIdA = contact->edges[0].bodyId; + int bodyIdB = contact->edges[1].bodyId; + + if ( colorIndex < B2_OVERFLOW_INDEX ) + { + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + B2_ASSERT( b2GetBit( &color->bodySet, bodyIdA ) == ( bodyA->type != b2_staticBody ) ); + B2_ASSERT( b2GetBit( &color->bodySet, bodyIdB ) == ( bodyB->type != b2_staticBody ) ); + } + } + } + + { + B2_ASSERT( color->jointSims.count >= 0 ); + totalJointCount += color->jointSims.count; + for ( int i = 0; i < color->jointSims.count; ++i ) + { + b2JointSim* jointSim = color->jointSims.data + i; + b2Joint* joint = b2JointArray_Get( &world->joints, jointSim->jointId ); + B2_ASSERT( joint->setIndex == b2_awakeSet ); + B2_ASSERT( joint->colorIndex == colorIndex ); + B2_ASSERT( joint->localIndex == i ); + + int bodyIdA = joint->edges[0].bodyId; + int bodyIdB = joint->edges[1].bodyId; + + if ( colorIndex < B2_OVERFLOW_INDEX ) + { + b2Body* bodyA = b2BodyArray_Get( &world->bodies, bodyIdA ); + b2Body* bodyB = b2BodyArray_Get( &world->bodies, bodyIdB ); + B2_ASSERT( b2GetBit( &color->bodySet, bodyIdA ) == ( bodyA->type != b2_staticBody ) ); + B2_ASSERT( b2GetBit( &color->bodySet, bodyIdB ) == ( bodyB->type != b2_staticBody ) ); + } + } + } + } + + int contactIdCount = b2GetIdCount( &world->contactIdPool ); + B2_ASSERT( totalContactCount == contactIdCount ); + B2_ASSERT( totalContactCount == (int)world->broadPhase.pairSet.count ); + + int jointIdCount = b2GetIdCount( &world->jointIdPool ); + B2_ASSERT( totalJointCount == jointIdCount ); + +// Validate shapes +// This is very slow on compounds +#if 0 + int shapeCapacity = b2Array(world->shapeArray).count; + for (int shapeIndex = 0; shapeIndex < shapeCapacity; shapeIndex += 1) + { + b2Shape* shape = world->shapeArray + shapeIndex; + if (shape->id != shapeIndex) + { + continue; + } + + B2_ASSERT(0 <= shape->bodyId && shape->bodyId < b2Array(world->bodyArray).count); + + b2Body* body = world->bodyArray + shape->bodyId; + B2_ASSERT(0 <= body->setIndex && body->setIndex < b2Array(world->solverSetArray).count); + + b2SolverSet* set = world->solverSetArray + body->setIndex; + B2_ASSERT(0 <= body->localIndex && body->localIndex < set->sims.count); + + b2BodySim* bodySim = set->sims.data + body->localIndex; + B2_ASSERT(bodySim->bodyId == shape->bodyId); + + bool found = false; + int shapeCount = 0; + int index = body->headShapeId; + while (index != B2_NULL_INDEX) + { + b2CheckId(world->shapeArray, index); + b2Shape* s = world->shapeArray + index; + if (index == shapeIndex) + { + found = true; + } + + index = s->nextShapeId; + shapeCount += 1; + } + + B2_ASSERT(found); + B2_ASSERT(shapeCount == body->shapeCount); + } +#endif +} + +// Validate contact touching status. +void b2ValidateContacts( b2World* world ) +{ + int contactCount = world->contacts.count; + B2_ASSERT( contactCount == b2GetIdCapacity( &world->contactIdPool ) ); + int allocatedContactCount = 0; + + for ( int contactIndex = 0; contactIndex < contactCount; ++contactIndex ) + { + b2Contact* contact = b2ContactArray_Get( &world->contacts, contactIndex ); + if ( contact->contactId == B2_NULL_INDEX ) + { + continue; + } + + B2_ASSERT( contact->contactId == contactIndex ); + + allocatedContactCount += 1; + + bool touching = ( contact->flags & b2_contactTouchingFlag ) != 0; + + int setId = contact->setIndex; + + if ( setId == b2_awakeSet ) + { + // If touching and not a sensor + if ( touching ) + { + B2_ASSERT( 0 <= contact->colorIndex && contact->colorIndex < B2_GRAPH_COLOR_COUNT ); + } + else + { + B2_ASSERT( contact->colorIndex == B2_NULL_INDEX ); + } + } + else if ( setId >= b2_firstSleepingSet ) + { + // Only touching contacts allowed in a sleeping set + B2_ASSERT( touching == true ); + } + else + { + // Sleeping and non-touching contacts or sensor contacts belong in the disabled set + B2_ASSERT( touching == false && setId == b2_disabledSet ); + } + + b2ContactSim* contactSim = b2GetContactSim( world, contact ); + B2_ASSERT( contactSim->contactId == contactIndex ); + B2_ASSERT( contactSim->bodyIdA == contact->edges[0].bodyId ); + B2_ASSERT( contactSim->bodyIdB == contact->edges[1].bodyId ); + + // Sim touching is true for solid and sensor contacts + bool simTouching = ( contactSim->simFlags & b2_simTouchingFlag ) != 0; + B2_ASSERT( touching == simTouching ); + + B2_ASSERT( 0 <= contactSim->manifold.pointCount && contactSim->manifold.pointCount <= 2 ); + } + + int contactIdCount = b2GetIdCount( &world->contactIdPool ); + B2_ASSERT( allocatedContactCount == contactIdCount ); +} + +#else + +void b2ValidateConnectivity( b2World* world ) +{ + B2_UNUSED( world ); +} + +void b2ValidateSolverSets( b2World* world ) +{ + B2_UNUSED( world ); +} + +void b2ValidateContacts( b2World* world ) +{ + B2_UNUSED( world ); +} + +#endif diff --git a/3rdparty/box2d/src/world.h b/3rdparty/box2d/src/world.h new file mode 100644 index 000000000000..fcc80c5a5e73 --- /dev/null +++ b/3rdparty/box2d/src/world.h @@ -0,0 +1,192 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "array.h" +#include "bitset.h" +#include "broad_phase.h" +#include "constraint_graph.h" +#include "id_pool.h" +#include "arena_allocator.h" + +#include "box2d/types.h" + +enum b2SetType +{ + b2_staticSet = 0, + b2_disabledSet = 1, + b2_awakeSet = 2, + b2_firstSleepingSet = 3, +}; + +// Per thread task storage +typedef struct b2TaskContext +{ + // These bits align with the b2ConstraintGraph::contactBlocks and signal a change in contact status + b2BitSet contactStateBitSet; + + // Used to track bodies with shapes that have enlarged AABBs. This avoids having a bit array + // that is very large when there are many static shapes. + b2BitSet enlargedSimBitSet; + + // Used to put islands to sleep + b2BitSet awakeIslandBitSet; + + // Per worker split island candidate + float splitSleepTime; + int splitIslandId; + +} b2TaskContext; + +// The world struct manages all physics entities, dynamic simulation, and asynchronous queries. +// The world also contains efficient memory management facilities. +typedef struct b2World +{ + b2ArenaAllocator arena; + b2BroadPhase broadPhase; + b2ConstraintGraph constraintGraph; + + // The body id pool is used to allocate and recycle body ids. Body ids + // provide a stable identifier for users, but incur caches misses when used + // to access body data. Aligns with b2Body. + b2IdPool bodyIdPool; + + // This is a sparse array that maps body ids to the body data + // stored in solver sets. As sims move within a set or across set. + // Indices come from id pool. + b2BodyArray bodies; + + // Provides free list for solver sets. + b2IdPool solverSetIdPool; + + // Solvers sets allow sims to be stored in contiguous arrays. The first + // set is all static sims. The second set is active sims. The third set is disabled + // sims. The remaining sets are sleeping islands. + b2SolverSetArray solverSets; + + // Used to create stable ids for joints + b2IdPool jointIdPool; + + // This is a sparse array that maps joint ids to the joint data stored in the constraint graph + // or in the solver sets. + b2JointArray joints; + + // Used to create stable ids for contacts + b2IdPool contactIdPool; + + // This is a sparse array that maps contact ids to the contact data stored in the constraint graph + // or in the solver sets. + b2ContactArray contacts; + + // Used to create stable ids for islands + b2IdPool islandIdPool; + + // This is a sparse array that maps island ids to the island data stored in the solver sets. + b2IslandArray islands; + + b2IdPool shapeIdPool; + b2IdPool chainIdPool; + + // These are sparse arrays that point into the pools above + b2ShapeArray shapes; + b2ChainShapeArray chainShapes; + + // This is a dense array of sensor data. + b2SensorArray sensors; + + // Per thread storage + b2TaskContextArray taskContexts; + b2SensorTaskContextArray sensorTaskContexts; + + b2BodyMoveEventArray bodyMoveEvents; + b2SensorBeginTouchEventArray sensorBeginEvents; + b2ContactBeginTouchEventArray contactBeginEvents; + + // End events are double buffered so that the user doesn't need to flush events + b2SensorEndTouchEventArray sensorEndEvents[2]; + b2ContactEndTouchEventArray contactEndEvents[2]; + int endEventArrayIndex; + + b2ContactHitEventArray contactHitEvents; + + // Used to track debug draw + b2BitSet debugBodySet; + b2BitSet debugJointSet; + b2BitSet debugContactSet; + b2BitSet debugIslandSet; + + // Id that is incremented every time step + uint64_t stepIndex; + + // Identify islands for splitting as follows: + // - I want to split islands so smaller islands can sleep + // - when a body comes to rest and its sleep timer trips, I can look at the island and flag it for splitting + // if it has removed constraints + // - islands that have removed constraints must be put split first because I don't want to wake bodies incorrectly + // - otherwise I can use the awake islands that have bodies wanting to sleep as the splitting candidates + // - if no bodies want to sleep then there is no reason to perform island splitting + int splitIslandId; + + b2Vec2 gravity; + float hitEventThreshold; + float restitutionThreshold; + float maxLinearSpeed; + float maxContactPushSpeed; + float contactHertz; + float contactDampingRatio; + float jointHertz; + float jointDampingRatio; + + b2FrictionCallback* frictionCallback; + b2RestitutionCallback* restitutionCallback; + + uint16_t generation; + + b2Profile profile; + + b2PreSolveFcn* preSolveFcn; + void* preSolveContext; + + b2CustomFilterFcn* customFilterFcn; + void* customFilterContext; + + int workerCount; + b2EnqueueTaskCallback* enqueueTaskFcn; + b2FinishTaskCallback* finishTaskFcn; + void* userTaskContext; + void* userTreeTask; + + void* userData; + + // Remember type step used for reporting forces and torques + float inv_h; + + int activeTaskCount; + int taskCount; + + uint16_t worldId; + + bool enableSleep; + bool locked; + bool enableWarmStarting; + bool enableContinuous; + bool enableSpeculative; + bool inUse; +} b2World; + +b2World* b2GetWorldFromId( b2WorldId id ); +b2World* b2GetWorld( int index ); +b2World* b2GetWorldLocked( int index ); + +void b2ValidateConnectivity( b2World* world ); +void b2ValidateSolverSets( b2World* world ); +void b2ValidateContacts( b2World* world ); + +B2_ARRAY_INLINE( b2BodyMoveEvent, b2BodyMoveEvent ) +B2_ARRAY_INLINE( b2ContactBeginTouchEvent, b2ContactBeginTouchEvent ) +B2_ARRAY_INLINE( b2ContactEndTouchEvent, b2ContactEndTouchEvent ) +B2_ARRAY_INLINE( b2ContactHitEvent, b2ContactHitEvent ) +B2_ARRAY_INLINE( b2SensorBeginTouchEvent, b2SensorBeginTouchEvent ) +B2_ARRAY_INLINE( b2SensorEndTouchEvent, b2SensorEndTouchEvent ) +B2_ARRAY_INLINE( b2TaskContext, b2TaskContext ) diff --git a/3rdparty/chipmunk/CMakeLists.txt b/3rdparty/chipmunk/CMakeLists.txt deleted file mode 100644 index 310c5ab07c66..000000000000 --- a/3rdparty/chipmunk/CMakeLists.txt +++ /dev/null @@ -1,75 +0,0 @@ -cmake_minimum_required(VERSION 3.10...4.0) - -project(chipmunk) - -# to change the prefix, run cmake with the parameter: -# -D CMAKE_INSTALL_PREFIX=/my/prefix - -# to change the build type, run cmake with the parameter: -# -D CMAKE_BUILD_TYPE= -# run "cmake --help-variable CMAKE_BUILD_TYPE" for details -if(NOT CMAKE_BUILD_TYPE) - SET(CMAKE_BUILD_TYPE Release CACHE STRING - "Choose the type of build, options are: None Debug Release RelWithDebInfo MinSizeRel." - FORCE) -endif() - -# to manually select install locations of libraries and executables -# -D LIB_INSTALL_DIR mylib -# -D BIN_INSTALL_DIR newbin -set(LIB_INSTALL_DIR lib CACHE STRING "Install location of libraries") -set(BIN_INSTALL_DIR bin CACHE STRING "Install location of executables") - -# other options for the build, you can i.e. activate the shared library by passing -# -D CP_BUILD_SHARED=ON -# to cmake. Other options analog -if(ANDROID) - option(CP_BUILD_DEMOS "Build the demo applications" OFF) - option(CP_INSTALL_DEMOS "Install the demo applications" OFF) - option(CP_BUILD_SHARED "Build and install the shared library" ON) - option(CP_BUILD_STATIC "Build as static library" ON) - option(CP_INSTALL_STATIC "Install the static library" OFF) -else() - option(CP_BUILD_DEMOS "Build the demo applications" ON) - option(CP_INSTALL_DEMOS "Install the demo applications" OFF) - option(CP_BUILD_SHARED "Build and install the shared library" ON) - option(CP_BUILD_STATIC "Build as static library" ON) - option(CP_INSTALL_STATIC "Install the static library" ON) -endif() - -option(CP_USE_DOUBLES ON) - -if(NOT CP_USE_DOUBLES) - add_definitions(-DCP_USE_DOUBLES=0) -endif() - -if(CMAKE_C_COMPILER_ID STREQUAL "Clang") - option(FORCE_CLANG_BLOCKS "Force enable Clang blocks" YES) -endif() - -# sanity checks... -if(CP_INSTALL_DEMOS) - set(CP_BUILD_DEMOS ON FORCE) -endif() - -# these need the static lib too -if(CP_BUILD_DEMOS OR CP_INSTALL_STATIC) - set(CP_BUILD_STATIC ON FORCE) -endif() - -if(NOT MSVC) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu99") # always use gnu99 - - if(FORCE_CLANG_BLOCKS) - set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fblocks") - endif() - - set(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} -ffast-math") # extend release-profile with fast-math - set(CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG} -Wall") # extend debug-profile with -Wall -endif() - -add_subdirectory(src) - -if(CP_BUILD_DEMOS) - add_subdirectory(demo) -endif() diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk.h b/3rdparty/chipmunk/include/chipmunk/chipmunk.h deleted file mode 100644 index 68359d3fa4ca..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk.h +++ /dev/null @@ -1,235 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_H -#define CHIPMUNK_H - -#include -#include - -#ifndef alloca - #ifdef _WIN32 - #include - #elif defined(__FreeBSD__) - /* already included in */ - #else - #include - #endif -#endif - -#ifdef _WIN32 - #define CP_EXPORT __declspec(dllexport) -#else - #define CP_EXPORT -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -CP_EXPORT void cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...); -#ifdef NDEBUG - #define cpAssertWarn(__condition__, ...) - #define cpAssertSoft(__condition__, ...) -#else - #define cpAssertSoft(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 0, __VA_ARGS__); abort();} - #define cpAssertWarn(__condition__, ...) if(!(__condition__)) cpMessage(#__condition__, __FILE__, __LINE__, 0, 0, __VA_ARGS__) -#endif - -// Hard assertions are used in situations where the program definitely will crash anyway, and the reason is inexpensive to detect. -#define cpAssertHard(__condition__, ...) if(!(__condition__)){cpMessage(#__condition__, __FILE__, __LINE__, 1, 1, __VA_ARGS__); abort();} - -#include "chipmunk_types.h" - -/// @defgroup misc Misc -/// @{ - -/// Allocated size for various Chipmunk buffers -#ifndef CP_BUFFER_BYTES - #define CP_BUFFER_BYTES (32*1024) -#endif - -#ifndef cpcalloc - /// Chipmunk calloc() alias. - #define cpcalloc calloc -#endif - -#ifndef cprealloc - /// Chipmunk realloc() alias. - #define cprealloc realloc -#endif - -#ifndef cpfree - /// Chipmunk free() alias. - #define cpfree free -#endif - -typedef struct cpArray cpArray; -typedef struct cpHashSet cpHashSet; - -typedef struct cpBody cpBody; - -typedef struct cpShape cpShape; -typedef struct cpCircleShape cpCircleShape; -typedef struct cpSegmentShape cpSegmentShape; -typedef struct cpPolyShape cpPolyShape; - -typedef struct cpConstraint cpConstraint; -typedef struct cpPinJoint cpPinJoint; -typedef struct cpSlideJoint cpSlideJoint; -typedef struct cpPivotJoint cpPivotJoint; -typedef struct cpGrooveJoint cpGrooveJoint; -typedef struct cpDampedSpring cpDampedSpring; -typedef struct cpDampedRotarySpring cpDampedRotarySpring; -typedef struct cpRotaryLimitJoint cpRotaryLimitJoint; -typedef struct cpRatchetJoint cpRatchetJoint; -typedef struct cpGearJoint cpGearJoint; -typedef struct cpSimpleMotorJoint cpSimpleMotorJoint; - -typedef struct cpCollisionHandler cpCollisionHandler; -typedef struct cpContactPointSet cpContactPointSet; -typedef struct cpArbiter cpArbiter; - -typedef struct cpSpace cpSpace; - -#include "cpVect.h" -#include "cpBB.h" -#include "cpTransform.h" -#include "cpSpatialIndex.h" - -#include "cpArbiter.h" - -#include "cpBody.h" -#include "cpShape.h" -#include "cpPolyShape.h" - -#include "cpConstraint.h" - -#include "cpSpace.h" - -// patch me: axis link android required -#include "cpHastySpace.h" - -// Chipmunk 7.0.3 -#define CP_VERSION_MAJOR 7 -#define CP_VERSION_MINOR 0 -#define CP_VERSION_RELEASE 3 - -/// Version string. -CP_EXPORT extern const char *cpVersionString; - -/// Calculate the moment of inertia for a circle. -/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0. -CP_EXPORT cpFloat cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset); - -/// Calculate area of a hollow circle. -/// @c r1 and @c r2 are the inner and outer diameters. A solid circle has an inner diameter of 0. -CP_EXPORT cpFloat cpAreaForCircle(cpFloat r1, cpFloat r2); - -/// Calculate the moment of inertia for a line segment. -/// Beveling radius is not supported. -CP_EXPORT cpFloat cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat radius); - -/// Calculate the area of a fattened (capsule shaped) line segment. -CP_EXPORT cpFloat cpAreaForSegment(cpVect a, cpVect b, cpFloat radius); - -/// Calculate the moment of inertia for a solid polygon shape assuming it's center of gravity is at it's centroid. The offset is added to each vertex. -CP_EXPORT cpFloat cpMomentForPoly(cpFloat m, int count, const cpVect *verts, cpVect offset, cpFloat radius); - -/// Calculate the signed area of a polygon. A Clockwise winding gives positive area. -/// This is probably backwards from what you expect, but matches Chipmunk's the winding for poly shapes. -CP_EXPORT cpFloat cpAreaForPoly(const int count, const cpVect *verts, cpFloat radius); - -/// Calculate the natural centroid of a polygon. -CP_EXPORT cpVect cpCentroidForPoly(const int count, const cpVect *verts); - -/// Calculate the moment of inertia for a solid box. -CP_EXPORT cpFloat cpMomentForBox(cpFloat m, cpFloat width, cpFloat height); - -/// Calculate the moment of inertia for a solid box. -CP_EXPORT cpFloat cpMomentForBox2(cpFloat m, cpBB box); - -/// Calculate the convex hull of a given set of points. Returns the count of points in the hull. -/// @c result must be a pointer to a @c cpVect array with at least @c count elements. If @c verts == @c result, then @c verts will be reduced inplace. -/// @c first is an optional pointer to an integer to store where the first vertex in the hull came from (i.e. verts[first] == result[0]) -/// @c tol is the allowed amount to shrink the hull when simplifying it. A tolerance of 0.0 creates an exact hull. -CP_EXPORT int cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol); - -/// Convenience macro to work with cpConvexHull. -/// @c count and @c verts is the input array passed to cpConvexHull(). -/// @c count_var and @c verts_var are the names of the variables the macro creates to store the result. -/// The output vertex array is allocated on the stack using alloca() so it will be freed automatically, but cannot be returned from the current scope. -#define CP_CONVEX_HULL(__count__, __verts__, __count_var__, __verts_var__) \ -cpVect *__verts_var__ = (cpVect *)alloca(__count__*sizeof(cpVect)); \ -int __count_var__ = cpConvexHull(__count__, __verts__, __verts_var__, NULL, 0.0); \ - -/// Returns the closest point on the line segment ab, to the point p. -static inline cpVect -cpClosetPointOnSegment(const cpVect p, const cpVect a, const cpVect b) -{ - cpVect delta = cpvsub(a, b); - cpFloat t = cpfclamp01(cpvdot(delta, cpvsub(p, b))/cpvlengthsq(delta)); - return cpvadd(b, cpvmult(delta, t)); -} - -#if defined(__has_extension) -#if __has_extension(blocks) -// Define alternate block based alternatives for a few of the callback heavy functions. -// Collision handlers are post-step callbacks are not included to avoid memory management issues. -// If you want to use blocks for those and are aware of how to correctly manage the memory, the implementation is trivial. - -void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body)); -void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape)); -void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint)); - -void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape)); -void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint)); -void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter)); - -typedef void (^cpSpacePointQueryBlock)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient); -void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block); - -typedef void (^cpSpaceSegmentQueryBlock)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha); -void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block); - -typedef void (^cpSpaceBBQueryBlock)(cpShape *shape); -void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block); - -typedef void (^cpSpaceShapeQueryBlock)(cpShape *shape, cpContactPointSet *points); -cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block); - -#endif -#endif - - -//@} - -#ifdef __cplusplus -} - -static inline cpVect operator *(const cpVect v, const cpFloat s){return cpvmult(v, s);} -static inline cpVect operator +(const cpVect v1, const cpVect v2){return cpvadd(v1, v2);} -static inline cpVect operator -(const cpVect v1, const cpVect v2){return cpvsub(v1, v2);} -static inline cpBool operator ==(const cpVect v1, const cpVect v2){return cpveql(v1, v2);} -static inline cpVect operator -(const cpVect v){return cpvneg(v);} - -#endif -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk_ffi.h b/3rdparty/chipmunk/include/chipmunk/chipmunk_ffi.h deleted file mode 100644 index 86e3d9fcd6fd..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk_ffi.h +++ /dev/null @@ -1,105 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifdef CHIPMUNK_FFI - -// Create non static inlined copies of Chipmunk functions, useful for working with dynamic FFIs -// For many languages, it may be faster to reimplement these functions natively instead. -// Note: This file should only be included by chipmunk.c. - -#ifdef _MSC_VER - #if _MSC_VER >= 1600 - #define MAKE_REF(name) CP_EXPORT decltype(name) *_##name = name - #else - #define MAKE_REF(name) - #endif -#else - #define MAKE_REF(name) __typeof__(name) *_##name = name -#endif - -#ifdef __cplusplus -extern "C" { -#endif - -MAKE_REF(cpv); // makes a variable named _cpv that contains the function pointer for cpv() -MAKE_REF(cpveql); -MAKE_REF(cpvadd); -MAKE_REF(cpvneg); -MAKE_REF(cpvsub); -MAKE_REF(cpvmult); -MAKE_REF(cpvdot); -MAKE_REF(cpvcross); -MAKE_REF(cpvperp); -MAKE_REF(cpvrperp); -MAKE_REF(cpvproject); -MAKE_REF(cpvforangle); -MAKE_REF(cpvtoangle); -MAKE_REF(cpvrotate); -MAKE_REF(cpvunrotate); -MAKE_REF(cpvlengthsq); -MAKE_REF(cpvlength); -MAKE_REF(cpvlerp); -MAKE_REF(cpvnormalize); -MAKE_REF(cpvclamp); -MAKE_REF(cpvlerpconst); -MAKE_REF(cpvdist); -MAKE_REF(cpvdistsq); -MAKE_REF(cpvnear); - -MAKE_REF(cpfmax); -MAKE_REF(cpfmin); -MAKE_REF(cpfabs); -MAKE_REF(cpfclamp); -MAKE_REF(cpflerp); -MAKE_REF(cpflerpconst); - -MAKE_REF(cpBBNew); -MAKE_REF(cpBBNewForExtents); -MAKE_REF(cpBBNewForCircle); -MAKE_REF(cpBBIntersects); -MAKE_REF(cpBBContainsBB); -MAKE_REF(cpBBContainsVect); -MAKE_REF(cpBBMerge); -MAKE_REF(cpBBExpand); -MAKE_REF(cpBBCenter); -MAKE_REF(cpBBArea); -MAKE_REF(cpBBMergedArea); -MAKE_REF(cpBBSegmentQuery); -MAKE_REF(cpBBIntersectsSegment); -MAKE_REF(cpBBClampVect); - -MAKE_REF(cpSpatialIndexDestroy); -MAKE_REF(cpSpatialIndexCount); -MAKE_REF(cpSpatialIndexEach); -MAKE_REF(cpSpatialIndexContains); -MAKE_REF(cpSpatialIndexInsert); -MAKE_REF(cpSpatialIndexRemove); -MAKE_REF(cpSpatialIndexReindex); -MAKE_REF(cpSpatialIndexReindexObject); -MAKE_REF(cpSpatialIndexSegmentQuery); -MAKE_REF(cpSpatialIndexQuery); -MAKE_REF(cpSpatialIndexReindexQuery); - -#ifdef __cplusplus -} -#endif - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk_private.h b/3rdparty/chipmunk/include/chipmunk/chipmunk_private.h deleted file mode 100644 index e606ba16c0e6..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk_private.h +++ /dev/null @@ -1,344 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_PRIVATE_H -#define CHIPMUNK_PRIVATE_H - -#include "chipmunk/chipmunk.h" -#include "chipmunk/chipmunk_structs.h" - -#define CP_HASH_COEF (3344921057ul) -#define CP_HASH_PAIR(A, B) ((cpHashValue)(A)*CP_HASH_COEF ^ (cpHashValue)(B)*CP_HASH_COEF) - -// TODO: Eww. Magic numbers. -#define MAGIC_EPSILON 1e-5 - - -//MARK: cpArray - -cpArray *cpArrayNew(int size); - -void cpArrayFree(cpArray *arr); - -void cpArrayPush(cpArray *arr, void *object); -void *cpArrayPop(cpArray *arr); -void cpArrayDeleteObj(cpArray *arr, void *obj); -cpBool cpArrayContains(cpArray *arr, void *ptr); - -void cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*)); - - -//MARK: cpHashSet - -typedef cpBool (*cpHashSetEqlFunc)(const void *ptr, const void *elt); -typedef void *(*cpHashSetTransFunc)(const void *ptr, void *data); - -cpHashSet *cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc); -void cpHashSetSetDefaultValue(cpHashSet *set, void *default_value); - -void cpHashSetFree(cpHashSet *set); - -int cpHashSetCount(cpHashSet *set); -const void *cpHashSetInsert(cpHashSet *set, cpHashValue hash, const void *ptr, cpHashSetTransFunc trans, void *data); -const void *cpHashSetRemove(cpHashSet *set, cpHashValue hash, const void *ptr); -const void *cpHashSetFind(cpHashSet *set, cpHashValue hash, const void *ptr); - -typedef void (*cpHashSetIteratorFunc)(void *elt, void *data); -void cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data); - -typedef cpBool (*cpHashSetFilterFunc)(void *elt, void *data); -void cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data); - - -//MARK: Bodies - -void cpBodyAddShape(cpBody *body, cpShape *shape); -void cpBodyRemoveShape(cpBody *body, cpShape *shape); - -//void cpBodyAccumulateMassForShape(cpBody *body, cpShape *shape); -void cpBodyAccumulateMassFromShapes(cpBody *body); - -void cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint); - - -//MARK: Spatial Index Functions - -cpSpatialIndex *cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); - - -//MARK: Arbiters - -cpArbiter* cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b); - -static inline struct cpArbiterThread * -cpArbiterThreadForBody(cpArbiter *arb, cpBody *body) -{ - return (arb->body_a == body ? &arb->thread_a : &arb->thread_b); -} - -void cpArbiterUnthread(cpArbiter *arb); - -void cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space); -void cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat bias, cpFloat slop); -void cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef); -void cpArbiterApplyImpulse(cpArbiter *arb); - - -//MARK: Shapes/Collisions - -cpShape *cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo); - -static inline cpBool -cpShapeActive(cpShape *shape) -{ - // checks if the shape is added to a shape list. - // TODO could this just check the space now? - return (shape->prev || (shape->body && shape->body->shapeList == shape)); -} - -// Note: This function returns contact points with r1/r2 in absolute coordinates, not body relative. -struct cpCollisionInfo cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts); - -static inline void -CircleSegmentQuery(cpShape *shape, cpVect center, cpFloat r1, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info) -{ - cpVect da = cpvsub(a, center); - cpVect db = cpvsub(b, center); - cpFloat rsum = r1 + r2; - - cpFloat qa = cpvdot(da, da) - 2.0f*cpvdot(da, db) + cpvdot(db, db); - cpFloat qb = cpvdot(da, db) - cpvdot(da, da); - cpFloat det = qb*qb - qa*(cpvdot(da, da) - rsum*rsum); - - if(det >= 0.0f){ - cpFloat t = (-qb - cpfsqrt(det))/(qa); - if(0.0f<= t && t <= 1.0f){ - cpVect n = cpvnormalize(cpvlerp(da, db, t)); - - info->shape = shape; - info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2)); - info->normal = n; - info->alpha = t; - } - } -} - -static inline cpBool -cpShapeFilterReject(cpShapeFilter a, cpShapeFilter b) -{ - // Reject the collision if: - return ( - // They are in the same non-zero group. - (a.group != 0 && a.group == b.group) || - // One of the category/mask combinations fails. - (a.categories & b.mask) == 0 || - (b.categories & a.mask) == 0 - ); -} - -void cpLoopIndexes(const cpVect *verts, int count, int *start, int *end); - - -//MARK: Constraints -// TODO naming conventions here - -void cpConstraintInit(cpConstraint *constraint, const struct cpConstraintClass *klass, cpBody *a, cpBody *b); - -static inline void -cpConstraintActivateBodies(cpConstraint *constraint) -{ - cpBody *a = constraint->a; cpBodyActivate(a); - cpBody *b = constraint->b; cpBodyActivate(b); -} - -static inline cpVect -relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2){ - cpVect v1_sum = cpvadd(a->v, cpvmult(cpvperp(r1), a->w)); - cpVect v2_sum = cpvadd(b->v, cpvmult(cpvperp(r2), b->w)); - - return cpvsub(v2_sum, v1_sum); -} - -static inline cpFloat -normal_relative_velocity(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n){ - return cpvdot(relative_velocity(a, b, r1, r2), n); -} - -static inline void -apply_impulse(cpBody *body, cpVect j, cpVect r){ - body->v = cpvadd(body->v, cpvmult(j, body->m_inv)); - body->w += body->i_inv*cpvcross(r, j); -} - -static inline void -apply_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) -{ - apply_impulse(a, cpvneg(j), r1); - apply_impulse(b, j, r2); -} - -static inline void -apply_bias_impulse(cpBody *body, cpVect j, cpVect r) -{ - body->v_bias = cpvadd(body->v_bias, cpvmult(j, body->m_inv)); - body->w_bias += body->i_inv*cpvcross(r, j); -} - -static inline void -apply_bias_impulses(cpBody *a , cpBody *b, cpVect r1, cpVect r2, cpVect j) -{ - apply_bias_impulse(a, cpvneg(j), r1); - apply_bias_impulse(b, j, r2); -} - -static inline cpFloat -k_scalar_body(cpBody *body, cpVect r, cpVect n) -{ - cpFloat rcn = cpvcross(r, n); - return body->m_inv + body->i_inv*rcn*rcn; -} - -static inline cpFloat -k_scalar(cpBody *a, cpBody *b, cpVect r1, cpVect r2, cpVect n) -{ - cpFloat value = k_scalar_body(a, r1, n) + k_scalar_body(b, r2, n); - cpAssertSoft(value != 0.0, "Unsolvable collision or constraint."); - - return value; -} - -static inline cpMat2x2 -k_tensor(cpBody *a, cpBody *b, cpVect r1, cpVect r2) -{ - cpFloat m_sum = a->m_inv + b->m_inv; - - // start with Identity*m_sum - cpFloat k11 = m_sum, k12 = 0.0f; - cpFloat k21 = 0.0f, k22 = m_sum; - - // add the influence from r1 - cpFloat a_i_inv = a->i_inv; - cpFloat r1xsq = r1.x * r1.x * a_i_inv; - cpFloat r1ysq = r1.y * r1.y * a_i_inv; - cpFloat r1nxy = -r1.x * r1.y * a_i_inv; - k11 += r1ysq; k12 += r1nxy; - k21 += r1nxy; k22 += r1xsq; - - // add the influnce from r2 - cpFloat b_i_inv = b->i_inv; - cpFloat r2xsq = r2.x * r2.x * b_i_inv; - cpFloat r2ysq = r2.y * r2.y * b_i_inv; - cpFloat r2nxy = -r2.x * r2.y * b_i_inv; - k11 += r2ysq; k12 += r2nxy; - k21 += r2nxy; k22 += r2xsq; - - // invert - cpFloat det = k11*k22 - k12*k21; - cpAssertSoft(det != 0.0, "Unsolvable constraint."); - - cpFloat det_inv = 1.0f/det; - return cpMat2x2New( - k22*det_inv, -k12*det_inv, - -k21*det_inv, k11*det_inv - ); -} - -static inline cpFloat -bias_coef(cpFloat errorBias, cpFloat dt) -{ - return 1.0f - cpfpow(errorBias, dt); -} - - -//MARK: Spaces - -#define cpAssertSpaceUnlocked(space) \ - cpAssertHard(!space->locked, \ - "This operation cannot be done safely during a call to cpSpaceStep() or during a query. " \ - "Put these calls into a post-step callback." \ - ); - -void cpSpaceSetStaticBody(cpSpace *space, cpBody *body); - -extern cpCollisionHandler cpCollisionHandlerDoNothing; - -void cpSpaceProcessComponents(cpSpace *space, cpFloat dt); - -void cpSpacePushFreshContactBuffer(cpSpace *space); -struct cpContact *cpContactBufferGetArray(cpSpace *space); -void cpSpacePushContacts(cpSpace *space, int count); - -cpPostStepCallback *cpSpaceGetPostStepCallback(cpSpace *space, void *key); - -cpBool cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space); -void cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter); - -void cpSpaceActivateBody(cpSpace *space, cpBody *body); -void cpSpaceLock(cpSpace *space); -void cpSpaceUnlock(cpSpace *space, cpBool runPostStep); - -static inline void -cpSpaceUncacheArbiter(cpSpace *space, cpArbiter *arb) -{ - const cpShape *a = arb->a, *b = arb->b; - const cpShape *shape_pair[] = {a, b}; - cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b); - cpHashSetRemove(space->cachedArbiters, arbHashID, shape_pair); - cpArrayDeleteObj(space->arbiters, arb); -} - -static inline cpArray * -cpSpaceArrayForBodyType(cpSpace *space, cpBodyType type) -{ - return (type == CP_BODY_TYPE_STATIC ? space->staticBodies : space->dynamicBodies); -} - -void cpShapeUpdateFunc(cpShape *shape, void *unused); -cpCollisionID cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space); - - -//MARK: Foreach loops - -static inline cpConstraint * -cpConstraintNext(cpConstraint *node, cpBody *body) -{ - return (node->a == body ? node->next_a : node->next_b); -} - -#define CP_BODY_FOREACH_CONSTRAINT(bdy, var)\ - for(cpConstraint *var = bdy->constraintList; var; var = cpConstraintNext(var, bdy)) - -static inline cpArbiter * -cpArbiterNext(cpArbiter *node, cpBody *body) -{ - return (node->body_a == body ? node->thread_a.next : node->thread_b.next); -} - -#define CP_BODY_FOREACH_ARBITER(bdy, var)\ - for(cpArbiter *var = bdy->arbiterList; var; var = cpArbiterNext(var, bdy)) - -#define CP_BODY_FOREACH_SHAPE(body, var)\ - for(cpShape *var = body->shapeList; var; var = var->next) - -#define CP_BODY_FOREACH_COMPONENT(root, var)\ - for(cpBody *var = root; var; var = var->sleeping.next) - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk_structs.h b/3rdparty/chipmunk/include/chipmunk/chipmunk_structs.h deleted file mode 100644 index 1485795d4e97..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk_structs.h +++ /dev/null @@ -1,450 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -// All of the struct definitions for Chipmunk should be considered part of the private API. -// However, it is very valuable to know the struct sizes for preallocating memory. - -#ifndef CHIPMUNK_STRUCTS_H -#define CHIPMUNK_STRUCTS_H - -#include "chipmunk/chipmunk.h" - -struct cpArray { - int num, max; - void **arr; -}; - -struct cpBody { - // Integration functions - cpBodyVelocityFunc velocity_func; - cpBodyPositionFunc position_func; - - // mass and it's inverse - cpFloat m; - cpFloat m_inv; - - // moment of inertia and it's inverse - cpFloat i; - cpFloat i_inv; - - // center of gravity - cpVect cog; - - // position, velocity, force - cpVect p; - cpVect v; - cpVect f; - - // Angle, angular velocity, torque (radians) - cpFloat a; - cpFloat w; - cpFloat t; - - cpTransform transform; - - cpDataPointer userData; - - // "pseudo-velocities" used for eliminating overlap. - // Erin Catto has some papers that talk about what these are. - cpVect v_bias; - cpFloat w_bias; - - cpSpace *space; - - cpShape *shapeList; - cpArbiter *arbiterList; - cpConstraint *constraintList; - - struct { - cpBody *root; - cpBody *next; - cpFloat idleTime; - } sleeping; -}; - -enum cpArbiterState { - // Arbiter is active and its the first collision. - CP_ARBITER_STATE_FIRST_COLLISION, - // Arbiter is active and its not the first collision. - CP_ARBITER_STATE_NORMAL, - // Collision has been explicitly ignored. - // Either by returning false from a begin collision handler or calling cpArbiterIgnore(). - CP_ARBITER_STATE_IGNORE, - // Collison is no longer active. A space will cache an arbiter for up to cpSpace.collisionPersistence more steps. - CP_ARBITER_STATE_CACHED, - // Collison arbiter is invalid because one of the shapes was removed. - CP_ARBITER_STATE_INVALIDATED, -}; - -struct cpArbiterThread { - struct cpArbiter *next, *prev; -}; - -struct cpContact { - cpVect r1, r2; - - cpFloat nMass, tMass; - cpFloat bounce; // TODO: look for an alternate bounce solution. - - cpFloat jnAcc, jtAcc, jBias; - cpFloat bias; - - cpHashValue hash; -}; - -struct cpCollisionInfo { - const cpShape *a, *b; - cpCollisionID id; - - cpVect n; - - int count; - // TODO Should this be a unique struct type? - struct cpContact *arr; -}; - -struct cpArbiter { - cpFloat e; - cpFloat u; - cpVect surface_vr; - - cpDataPointer data; - - const cpShape *a, *b; - cpBody *body_a, *body_b; - struct cpArbiterThread thread_a, thread_b; - - int count; - struct cpContact *contacts; - cpVect n; - - // Regular, wildcard A and wildcard B collision handlers. - cpCollisionHandler *handler, *handlerA, *handlerB; - cpBool swapped; - - cpTimestamp stamp; - enum cpArbiterState state; -}; - -struct cpShapeMassInfo { - cpFloat m; - cpFloat i; - cpVect cog; - cpFloat area; -}; - -typedef enum cpShapeType{ - CP_CIRCLE_SHAPE, - CP_SEGMENT_SHAPE, - CP_POLY_SHAPE, - CP_NUM_SHAPES -} cpShapeType; - -typedef cpBB (*cpShapeCacheDataImpl)(cpShape *shape, cpTransform transform); -typedef void (*cpShapeDestroyImpl)(cpShape *shape); -typedef void (*cpShapePointQueryImpl)(const cpShape *shape, cpVect p, cpPointQueryInfo *info); -typedef void (*cpShapeSegmentQueryImpl)(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info); - -typedef struct cpShapeClass cpShapeClass; - -struct cpShapeClass { - cpShapeType type; - - cpShapeCacheDataImpl cacheData; - cpShapeDestroyImpl destroy; - cpShapePointQueryImpl pointQuery; - cpShapeSegmentQueryImpl segmentQuery; -}; - -struct cpShape { - const cpShapeClass *klass; - - cpSpace *space; - cpBody *body; - struct cpShapeMassInfo massInfo; - cpBB bb; - - cpBool sensor; - - cpFloat e; - cpFloat u; - cpVect surfaceV; - - cpDataPointer userData; - - cpCollisionType type; - cpShapeFilter filter; - - cpShape *next; - cpShape *prev; - - cpHashValue hashid; -}; - -struct cpCircleShape { - cpShape shape; - - cpVect c, tc; - cpFloat r; -}; - -struct cpSegmentShape { - cpShape shape; - - cpVect a, b, n; - cpVect ta, tb, tn; - cpFloat r; - - cpVect a_tangent, b_tangent; -}; - -struct cpSplittingPlane { - cpVect v0, n; -}; - -#define CP_POLY_SHAPE_INLINE_ALLOC 6 - -struct cpPolyShape { - cpShape shape; - - cpFloat r; - - int count; - // The untransformed planes are appended at the end of the transformed planes. - struct cpSplittingPlane *planes; - - // Allocate a small number of splitting planes internally for simple poly. - struct cpSplittingPlane _planes[2*CP_POLY_SHAPE_INLINE_ALLOC]; -}; - -typedef void (*cpConstraintPreStepImpl)(cpConstraint *constraint, cpFloat dt); -typedef void (*cpConstraintApplyCachedImpulseImpl)(cpConstraint *constraint, cpFloat dt_coef); -typedef void (*cpConstraintApplyImpulseImpl)(cpConstraint *constraint, cpFloat dt); -typedef cpFloat (*cpConstraintGetImpulseImpl)(cpConstraint *constraint); - -typedef struct cpConstraintClass { - cpConstraintPreStepImpl preStep; - cpConstraintApplyCachedImpulseImpl applyCachedImpulse; - cpConstraintApplyImpulseImpl applyImpulse; - cpConstraintGetImpulseImpl getImpulse; -} cpConstraintClass; - -struct cpConstraint { - const cpConstraintClass *klass; - - cpSpace *space; - - cpBody *a, *b; - cpConstraint *next_a, *next_b; - - cpFloat maxForce; - cpFloat errorBias; - cpFloat maxBias; - - cpBool collideBodies; - - cpConstraintPreSolveFunc preSolve; - cpConstraintPostSolveFunc postSolve; - - cpDataPointer userData; -}; - -struct cpPinJoint { - cpConstraint constraint; - cpVect anchorA, anchorB; - cpFloat dist; - - cpVect r1, r2; - cpVect n; - cpFloat nMass; - - cpFloat jnAcc; - cpFloat bias; -}; - -struct cpSlideJoint { - cpConstraint constraint; - cpVect anchorA, anchorB; - cpFloat min, max; - - cpVect r1, r2; - cpVect n; - cpFloat nMass; - - cpFloat jnAcc; - cpFloat bias; -}; - -struct cpPivotJoint { - cpConstraint constraint; - cpVect anchorA, anchorB; - - cpVect r1, r2; - cpMat2x2 k; - - cpVect jAcc; - cpVect bias; -}; - -struct cpGrooveJoint { - cpConstraint constraint; - cpVect grv_n, grv_a, grv_b; - cpVect anchorB; - - cpVect grv_tn; - cpFloat clamp; - cpVect r1, r2; - cpMat2x2 k; - - cpVect jAcc; - cpVect bias; -}; - -struct cpDampedSpring { - cpConstraint constraint; - cpVect anchorA, anchorB; - cpFloat restLength; - cpFloat stiffness; - cpFloat damping; - cpDampedSpringForceFunc springForceFunc; - - cpFloat target_vrn; - cpFloat v_coef; - - cpVect r1, r2; - cpFloat nMass; - cpVect n; - - cpFloat jAcc; -}; - -struct cpDampedRotarySpring { - cpConstraint constraint; - cpFloat restAngle; - cpFloat stiffness; - cpFloat damping; - cpDampedRotarySpringTorqueFunc springTorqueFunc; - - cpFloat target_wrn; - cpFloat w_coef; - - cpFloat iSum; - cpFloat jAcc; -}; - -struct cpRotaryLimitJoint { - cpConstraint constraint; - cpFloat min, max; - - cpFloat iSum; - - cpFloat bias; - cpFloat jAcc; -}; - -struct cpRatchetJoint { - cpConstraint constraint; - cpFloat angle, phase, ratchet; - - cpFloat iSum; - - cpFloat bias; - cpFloat jAcc; -}; - -struct cpGearJoint { - cpConstraint constraint; - cpFloat phase, ratio; - cpFloat ratio_inv; - - cpFloat iSum; - - cpFloat bias; - cpFloat jAcc; -}; - -struct cpSimpleMotor { - cpConstraint constraint; - cpFloat rate; - - cpFloat iSum; - - cpFloat jAcc; -}; - -typedef struct cpContactBufferHeader cpContactBufferHeader; -typedef void (*cpSpaceArbiterApplyImpulseFunc)(cpArbiter *arb); - -struct cpSpace { - int iterations; - - cpVect gravity; - cpFloat damping; - - cpFloat idleSpeedThreshold; - cpFloat sleepTimeThreshold; - - cpFloat collisionSlop; - cpFloat collisionBias; - cpTimestamp collisionPersistence; - - cpDataPointer userData; - - cpTimestamp stamp; - cpFloat curr_dt; - - cpArray *dynamicBodies; - cpArray *staticBodies; - cpArray *rousedBodies; - cpArray *sleepingComponents; - - cpHashValue shapeIDCounter; - cpSpatialIndex *staticShapes; - cpSpatialIndex *dynamicShapes; - - cpArray *constraints; - - cpArray *arbiters; - cpContactBufferHeader *contactBuffersHead; - cpHashSet *cachedArbiters; - cpArray *pooledArbiters; - - cpArray *allocatedBuffers; - int locked; - - cpBool usesWildcards; - cpHashSet *collisionHandlers; - cpCollisionHandler defaultHandler; - - cpBool skipPostStep; - cpArray *postStepCallbacks; - - cpBody *staticBody; - cpBody _staticBody; -}; - -typedef struct cpPostStepCallback { - cpPostStepFunc func; - void *key; - void *data; -} cpPostStepCallback; - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk_types.h b/3rdparty/chipmunk/include/chipmunk/chipmunk_types.h deleted file mode 100644 index 285e2c41b1e6..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk_types.h +++ /dev/null @@ -1,272 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_TYPES_H -#define CHIPMUNK_TYPES_H - -// EGNX use float precision, so disable chipmunk double use. -#define CP_USE_CGTYPES 0 -#define CP_USE_DOUBLES 0 - -#include -#include -#include - -#ifdef __APPLE__ - #include "TargetConditionals.h" -#endif - -// Use CGTypes by default on iOS and Mac. -// Also enables usage of doubles on 64 bit. -// Performance is usually very comparable when the CPU cache is well utilised. -#if (TARGET_OS_IPHONE || TARGET_OS_MAC) && (!defined CP_USE_CGTYPES) - #define CP_USE_CGTYPES 1 -#endif - -#if CP_USE_CGTYPES - #if TARGET_OS_IPHONE - #include - #include - #elif TARGET_OS_MAC - #include - #endif - - #if defined(__LP64__) && __LP64__ - #define CP_USE_DOUBLES 1 - #else - #define CP_USE_DOUBLES 0 - #endif -#endif - -#ifndef CP_USE_DOUBLES - // Use doubles by default for higher precision. - #define CP_USE_DOUBLES 1 -#endif - -/// @defgroup basicTypes Basic Types -/// Most of these types can be configured at compile time. -/// @{ - -#if CP_USE_DOUBLES -/// Chipmunk's floating point type. -/// Can be reconfigured at compile time. - typedef double cpFloat; - #define cpfsqrt sqrt - #define cpfsin sin - #define cpfcos cos - #define cpfacos acos - #define cpfatan2 atan2 - #define cpfmod fmod - #define cpfexp exp - #define cpfpow pow - #define cpffloor floor - #define cpfceil ceil - #define CPFLOAT_MIN DBL_MIN -#else - typedef float cpFloat; - #define cpfsqrt sqrtf - #define cpfsin sinf - #define cpfcos cosf - #define cpfacos acosf - #define cpfatan2 atan2f - #define cpfmod fmodf - #define cpfexp expf - #define cpfpow powf - #define cpffloor floorf - #define cpfceil ceilf - #define CPFLOAT_MIN FLT_MIN -#endif - -#ifndef INFINITY - #ifdef _MSC_VER - union MSVC_EVIL_FLOAT_HACK - { - unsigned __int8 Bytes[4]; - float Value; - }; - static union MSVC_EVIL_FLOAT_HACK INFINITY_HACK = {{0x00, 0x00, 0x80, 0x7F}}; - #define INFINITY (INFINITY_HACK.Value) - #endif - - #ifdef __GNUC__ - #define INFINITY (__builtin_inf()) - #endif - - #ifndef INFINITY - #define INFINITY (1e1000) - #endif -#endif - - -#define CP_PI ((cpFloat)3.14159265358979323846264338327950288) - - -/// Return the max of two cpFloats. -static inline cpFloat cpfmax(cpFloat a, cpFloat b) -{ - return (a > b) ? a : b; -} - -/// Return the min of two cpFloats. -static inline cpFloat cpfmin(cpFloat a, cpFloat b) -{ - return (a < b) ? a : b; -} - -/// Return the absolute value of a cpFloat. -static inline cpFloat cpfabs(cpFloat f) -{ - return (f < 0) ? -f : f; -} - -/// Clamp @c f to be between @c min and @c max. -static inline cpFloat cpfclamp(cpFloat f, cpFloat min, cpFloat max) -{ - return cpfmin(cpfmax(f, min), max); -} - -/// Clamp @c f to be between 0 and 1. -static inline cpFloat cpfclamp01(cpFloat f) -{ - return cpfmax(0.0f, cpfmin(f, 1.0f)); -} - - - -/// Linearly interpolate (or extrapolate) between @c f1 and @c f2 by @c t percent. -static inline cpFloat cpflerp(cpFloat f1, cpFloat f2, cpFloat t) -{ - return f1*(1.0f - t) + f2*t; -} - -/// Linearly interpolate from @c f1 to @c f2 by no more than @c d. -static inline cpFloat cpflerpconst(cpFloat f1, cpFloat f2, cpFloat d) -{ - return f1 + cpfclamp(f2 - f1, -d, d); -} - -/// Hash value type. -#ifdef CP_HASH_VALUE_TYPE - typedef CP_HASH_VALUE_TYPE cpHashValue; -#else - typedef uintptr_t cpHashValue; -#endif - -/// Type used internally to cache colliding object info for cpCollideShapes(). -/// Should be at least 32 bits. -typedef uint32_t cpCollisionID; - -// Oh C, how we love to define our own boolean types to get compiler compatibility -/// Chipmunk's boolean type. -#ifdef CP_BOOL_TYPE - typedef CP_BOOL_TYPE cpBool; -#else - typedef unsigned char cpBool; -#endif - -#ifndef cpTrue -/// true value. - #define cpTrue 1 -#endif - -#ifndef cpFalse -/// false value. - #define cpFalse 0 -#endif - -#ifdef CP_DATA_POINTER_TYPE - typedef CP_DATA_POINTER_TYPE cpDataPointer; -#else -/// Type used for user data pointers. - typedef void * cpDataPointer; -#endif - -#ifdef CP_COLLISION_TYPE_TYPE - typedef CP_COLLISION_TYPE_TYPE cpCollisionType; -#else -/// Type used for cpSpace.collision_type. - typedef uintptr_t cpCollisionType; -#endif - -#ifdef CP_GROUP_TYPE - typedef CP_GROUP_TYPE cpGroup; -#else -/// Type used for cpShape.group. - typedef uintptr_t cpGroup; -#endif - -#ifdef CP_BITMASK_TYPE - typedef CP_BITMASK_TYPE cpBitmask; -#else -/// Type used for cpShapeFilter category and mask. - typedef unsigned int cpBitmask; -#endif - -#ifdef CP_TIMESTAMP_TYPE - typedef CP_TIMESTAMP_TYPE cpTimestamp; -#else -/// Type used for various timestamps in Chipmunk. - typedef unsigned int cpTimestamp; -#endif - -#ifndef CP_NO_GROUP -/// Value for cpShape.group signifying that a shape is in no group. - #define CP_NO_GROUP ((cpGroup)0) -#endif - -#ifndef CP_ALL_CATEGORIES -/// Value for cpShape.layers signifying that a shape is in every layer. - #define CP_ALL_CATEGORIES (~(cpBitmask)0) -#endif - -#ifndef CP_WILDCARD_COLLISION_TYPE -/// cpCollisionType value internally reserved for hashing wildcard handlers. - #define CP_WILDCARD_COLLISION_TYPE (~(cpCollisionType)0) -#endif - -/// @} - -// CGPoints are structurally the same, and allow -// easy interoperability with other Cocoa libraries -#if CP_USE_CGTYPES - typedef CGPoint cpVect; -#else -/// Chipmunk's 2D vector type. -/// @addtogroup cpVect - typedef struct cpVect{cpFloat x,y;} cpVect; -#endif - -#if CP_USE_CGTYPES - typedef CGAffineTransform cpTransform; -#else - /// Column major affine transform. - typedef struct cpTransform { - cpFloat a, b, c, d, tx, ty; - } cpTransform; -#endif - -// NUKE -typedef struct cpMat2x2 { - // Row major [[a, b][c d]] - cpFloat a, b, c, d; -} cpMat2x2; - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/chipmunk_unsafe.h b/3rdparty/chipmunk/include/chipmunk/chipmunk_unsafe.h deleted file mode 100644 index 990bd012af45..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/chipmunk_unsafe.h +++ /dev/null @@ -1,66 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* This header defines a number of "unsafe" operations on Chipmunk objects. - * In this case "unsafe" is referring to operations which may reduce the - * physical accuracy or numerical stability of the simulation, but will not - * cause crashes. - * - * The prime example is mutating collision shapes. Chipmunk does not support - * this directly. Mutating shapes using this API will caused objects in contact - * to be pushed apart using Chipmunk's overlap solver, but not using real - * persistent velocities. Probably not what you meant, but perhaps close enough. - */ - -/// @defgroup unsafe Chipmunk Unsafe Shape Operations -/// These functions are used for mutating collision shapes. -/// Chipmunk does not have any way to get velocity information on changing shapes, -/// so the results will be unrealistic. You must explicity include the chipmunk_unsafe.h header to use them. -/// @{ - -#ifndef CHIPMUNK_UNSAFE_H -#define CHIPMUNK_UNSAFE_H - -#ifdef __cplusplus -extern "C" { -#endif - -/// Set the radius of a circle shape. -CP_EXPORT void cpCircleShapeSetRadius(cpShape *shape, cpFloat radius); -/// Set the offset of a circle shape. -CP_EXPORT void cpCircleShapeSetOffset(cpShape *shape, cpVect offset); - -/// Set the endpoints of a segment shape. -CP_EXPORT void cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b); -/// Set the radius of a segment shape. -CP_EXPORT void cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius); - -/// Set the vertexes of a poly shape. -CP_EXPORT void cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform); -CP_EXPORT void cpPolyShapeSetVertsRaw(cpShape *shape, int count, cpVect *verts); -/// Set the radius of a poly shape. -CP_EXPORT void cpPolyShapeSetRadius(cpShape *shape, cpFloat radius); - -#ifdef __cplusplus -} -#endif -#endif -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpArbiter.h b/3rdparty/chipmunk/include/chipmunk/cpArbiter.h deleted file mode 100644 index 1dc130afb040..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpArbiter.h +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpArbiter cpArbiter -/// The cpArbiter struct tracks pairs of colliding shapes. -/// They are also used in conjuction with collision handler callbacks -/// allowing you to retrieve information on the collision or change it. -/// A unique arbiter value is used for each pair of colliding objects. It persists until the shapes separate. -/// @{ - -#define CP_MAX_CONTACTS_PER_ARBITER 2 - -/// Get the restitution (elasticity) that will be applied to the pair of colliding objects. -CP_EXPORT cpFloat cpArbiterGetRestitution(const cpArbiter *arb); -/// Override the restitution (elasticity) that will be applied to the pair of colliding objects. -CP_EXPORT void cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution); -/// Get the friction coefficient that will be applied to the pair of colliding objects. -CP_EXPORT cpFloat cpArbiterGetFriction(const cpArbiter *arb); -/// Override the friction coefficient that will be applied to the pair of colliding objects. -CP_EXPORT void cpArbiterSetFriction(cpArbiter *arb, cpFloat friction); - -// Get the relative surface velocity of the two shapes in contact. -CP_EXPORT cpVect cpArbiterGetSurfaceVelocity(cpArbiter *arb); - -// Override the relative surface velocity of the two shapes in contact. -// By default this is calculated to be the difference of the two surface velocities clamped to the tangent plane. -CP_EXPORT void cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr); - -/// Get the user data pointer associated with this pair of colliding objects. -CP_EXPORT cpDataPointer cpArbiterGetUserData(const cpArbiter *arb); -/// Set a user data point associated with this pair of colliding objects. -/// If you need to perform any cleanup for this pointer, you must do it yourself, in the separate callback for instance. -CP_EXPORT void cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData); - -/// Calculate the total impulse including the friction that was applied by this arbiter. -/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. -CP_EXPORT cpVect cpArbiterTotalImpulse(const cpArbiter *arb); -/// Calculate the amount of energy lost in a collision including static, but not dynamic friction. -/// This function should only be called from a post-solve, post-step or cpBodyEachArbiter callback. -CP_EXPORT cpFloat cpArbiterTotalKE(const cpArbiter *arb); - -/// Mark a collision pair to be ignored until the two objects separate. -/// Pre-solve and post-solve callbacks will not be called, but the separate callback will be called. -CP_EXPORT cpBool cpArbiterIgnore(cpArbiter *arb); - -/// Return the colliding shapes involved for this arbiter. -/// The order of their cpSpace.collision_type values will match -/// the order set when the collision handler was registered. -CP_EXPORT void cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b); - -/// A macro shortcut for defining and retrieving the shapes from an arbiter. -#define CP_ARBITER_GET_SHAPES(__arb__, __a__, __b__) cpShape *__a__, *__b__; cpArbiterGetShapes(__arb__, &__a__, &__b__); - -/// Return the colliding bodies involved for this arbiter. -/// The order of the cpSpace.collision_type the bodies are associated with values will match -/// the order set when the collision handler was registered. -CP_EXPORT void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b); - -/// A macro shortcut for defining and retrieving the bodies from an arbiter. -#define CP_ARBITER_GET_BODIES(__arb__, __a__, __b__) cpBody *__a__, *__b__; cpArbiterGetBodies(__arb__, &__a__, &__b__); - -/// A struct that wraps up the important collision data for an arbiter. -struct cpContactPointSet { - /// The number of contact points in the set. - int count; - - /// The normal of the collision. - cpVect normal; - - /// The array of contact points. - struct { - /// The position of the contact on the surface of each shape. - cpVect pointA, pointB; - /// Penetration distance of the two shapes. Overlapping means it will be negative. - /// This value is calculated as cpvdot(cpvsub(point2, point1), normal) and is ignored by cpArbiterSetContactPointSet(). - cpFloat distance; - } points[CP_MAX_CONTACTS_PER_ARBITER]; -}; - -/// Return a contact set from an arbiter. -CP_EXPORT cpContactPointSet cpArbiterGetContactPointSet(const cpArbiter *arb); - -/// Replace the contact point set for an arbiter. -/// This can be a very powerful feature, but use it with caution! -CP_EXPORT void cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set); - -/// Returns true if this is the first step a pair of objects started colliding. -CP_EXPORT cpBool cpArbiterIsFirstContact(const cpArbiter *arb); -/// Returns true if the separate callback is due to a shape being removed from the space. -CP_EXPORT cpBool cpArbiterIsRemoval(const cpArbiter *arb); - -/// Get the number of contact points for this arbiter. -CP_EXPORT int cpArbiterGetCount(const cpArbiter *arb); -/// Get the normal of the collision. -CP_EXPORT cpVect cpArbiterGetNormal(const cpArbiter *arb); -/// Get the position of the @c ith contact point on the surface of the first shape. -CP_EXPORT cpVect cpArbiterGetPointA(const cpArbiter *arb, int i); -/// Get the position of the @c ith contact point on the surface of the second shape. -CP_EXPORT cpVect cpArbiterGetPointB(const cpArbiter *arb, int i); -/// Get the depth of the @c ith contact point. -CP_EXPORT cpFloat cpArbiterGetDepth(const cpArbiter *arb, int i); - -/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly. -/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own. -CP_EXPORT cpBool cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space); -/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly. -/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own. -CP_EXPORT cpBool cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space); - -/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly. -/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own. -CP_EXPORT cpBool cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space); -/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly. -/// You must decide how to handle the wildcard's return value since it may disagree with the other wildcard handler's return value or your own. -CP_EXPORT cpBool cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space); - -/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly. -CP_EXPORT void cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space); -/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly. -CP_EXPORT void cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space); - -/// If you want a custom callback to invoke the wildcard callback for the first collision type, you must call this function explicitly. -CP_EXPORT void cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space); -/// If you want a custom callback to invoke the wildcard callback for the second collision type, you must call this function explicitly. -CP_EXPORT void cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpBB.h b/3rdparty/chipmunk/include/chipmunk/cpBB.h deleted file mode 100644 index 8fc87049cc40..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpBB.h +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_BB_H -#define CHIPMUNK_BB_H - -#include "chipmunk_types.h" -#include "cpVect.h" - -/// @defgroup cpBBB cpBB -/// Chipmunk's axis-aligned 2D bounding box type along with a few handy routines. -/// @{ - -/// Chipmunk's axis-aligned 2D bounding box type. (left, bottom, right, top) -typedef struct cpBB{ - cpFloat l, b, r ,t; -} cpBB; - -/// Convenience constructor for cpBB structs. -static inline cpBB cpBBNew(const cpFloat l, const cpFloat b, const cpFloat r, const cpFloat t) -{ - cpBB bb = {l, b, r, t}; - return bb; -} - -/// Constructs a cpBB centered on a point with the given extents (half sizes). -static inline cpBB -cpBBNewForExtents(const cpVect c, const cpFloat hw, const cpFloat hh) -{ - return cpBBNew(c.x - hw, c.y - hh, c.x + hw, c.y + hh); -} - -/// Constructs a cpBB for a circle with the given position and radius. -static inline cpBB cpBBNewForCircle(const cpVect p, const cpFloat r) -{ - return cpBBNewForExtents(p, r, r); -} - -/// Returns true if @c a and @c b intersect. -static inline cpBool cpBBIntersects(const cpBB a, const cpBB b) -{ - return (a.l <= b.r && b.l <= a.r && a.b <= b.t && b.b <= a.t); -} - -/// Returns true if @c other lies completely within @c bb. -static inline cpBool cpBBContainsBB(const cpBB bb, const cpBB other) -{ - return (bb.l <= other.l && bb.r >= other.r && bb.b <= other.b && bb.t >= other.t); -} - -/// Returns true if @c bb contains @c v. -static inline cpBool cpBBContainsVect(const cpBB bb, const cpVect v) -{ - return (bb.l <= v.x && bb.r >= v.x && bb.b <= v.y && bb.t >= v.y); -} - -/// Returns a bounding box that holds both bounding boxes. -static inline cpBB cpBBMerge(const cpBB a, const cpBB b){ - return cpBBNew( - cpfmin(a.l, b.l), - cpfmin(a.b, b.b), - cpfmax(a.r, b.r), - cpfmax(a.t, b.t) - ); -} - -/// Returns a bounding box that holds both @c bb and @c v. -static inline cpBB cpBBExpand(const cpBB bb, const cpVect v){ - return cpBBNew( - cpfmin(bb.l, v.x), - cpfmin(bb.b, v.y), - cpfmax(bb.r, v.x), - cpfmax(bb.t, v.y) - ); -} - -/// Returns the center of a bounding box. -static inline cpVect -cpBBCenter(cpBB bb) -{ - return cpvlerp(cpv(bb.l, bb.b), cpv(bb.r, bb.t), 0.5f); -} - -/// Returns the area of the bounding box. -static inline cpFloat cpBBArea(cpBB bb) -{ - return (bb.r - bb.l)*(bb.t - bb.b); -} - -/// Merges @c a and @c b and returns the area of the merged bounding box. -static inline cpFloat cpBBMergedArea(cpBB a, cpBB b) -{ - return (cpfmax(a.r, b.r) - cpfmin(a.l, b.l))*(cpfmax(a.t, b.t) - cpfmin(a.b, b.b)); -} - -/// Returns the fraction along the segment query the cpBB is hit. Returns INFINITY if it doesn't hit. -static inline cpFloat cpBBSegmentQuery(cpBB bb, cpVect a, cpVect b) -{ - cpVect delta = cpvsub(b, a); - cpFloat tmin = -INFINITY, tmax = INFINITY; - - if(delta.x == 0.0f){ - if(a.x < bb.l || bb.r < a.x) return INFINITY; - } else { - cpFloat t1 = (bb.l - a.x)/delta.x; - cpFloat t2 = (bb.r - a.x)/delta.x; - tmin = cpfmax(tmin, cpfmin(t1, t2)); - tmax = cpfmin(tmax, cpfmax(t1, t2)); - } - - if(delta.y == 0.0f){ - if(a.y < bb.b || bb.t < a.y) return INFINITY; - } else { - cpFloat t1 = (bb.b - a.y)/delta.y; - cpFloat t2 = (bb.t - a.y)/delta.y; - tmin = cpfmax(tmin, cpfmin(t1, t2)); - tmax = cpfmin(tmax, cpfmax(t1, t2)); - } - - if(tmin <= tmax && 0.0f <= tmax && tmin <= 1.0f){ - return cpfmax(tmin, 0.0f); - } else { - return INFINITY; - } -} - -/// Return true if the bounding box intersects the line segment with ends @c a and @c b. -static inline cpBool cpBBIntersectsSegment(cpBB bb, cpVect a, cpVect b) -{ - return (cpBBSegmentQuery(bb, a, b) != INFINITY); -} - -/// Clamp a vector to a bounding box. -static inline cpVect -cpBBClampVect(const cpBB bb, const cpVect v) -{ - return cpv(cpfclamp(v.x, bb.l, bb.r), cpfclamp(v.y, bb.b, bb.t)); -} - -/// Wrap a vector to a bounding box. -static inline cpVect -cpBBWrapVect(const cpBB bb, const cpVect v) -{ - cpFloat dx = cpfabs(bb.r - bb.l); - cpFloat modx = cpfmod(v.x - bb.l, dx); - cpFloat x = (modx > 0.0f) ? modx : modx + dx; - - cpFloat dy = cpfabs(bb.t - bb.b); - cpFloat mody = cpfmod(v.y - bb.b, dy); - cpFloat y = (mody > 0.0f) ? mody : mody + dy; - - return cpv(x + bb.l, y + bb.b); -} - -/// Returns a bounding box offseted by @c v. -static inline cpBB -cpBBOffset(const cpBB bb, const cpVect v) -{ - return cpBBNew( - bb.l + v.x, - bb.b + v.y, - bb.r + v.x, - bb.t + v.y - ); -} - -///@} - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/cpBody.h b/3rdparty/chipmunk/include/chipmunk/cpBody.h deleted file mode 100644 index 7e6943d15794..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpBody.h +++ /dev/null @@ -1,189 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpBody cpBody -/// Chipmunk's rigid body type. Rigid bodies hold the physical properties of an object like -/// it's mass, and position and velocity of it's center of gravity. They don't have an shape on their own. -/// They are given a shape by creating collision shapes (cpShape) that point to the body. -/// @{ - -typedef enum cpBodyType { - /// A dynamic body is one that is affected by gravity, forces, and collisions. - /// This is the default body type. - CP_BODY_TYPE_DYNAMIC, - /// A kinematic body is an infinite mass, user controlled body that is not affected by gravity, forces or collisions. - /// Instead the body only moves based on it's velocity. - /// Dynamic bodies collide normally with kinematic bodies, though the kinematic body will be unaffected. - /// Collisions between two kinematic bodies, or a kinematic body and a static body produce collision callbacks, but no collision response. - CP_BODY_TYPE_KINEMATIC, - /// A static body is a body that never (or rarely) moves. If you move a static body, you must call one of the cpSpaceReindex*() functions. - /// Chipmunk uses this information to optimize the collision detection. - /// Static bodies do not produce collision callbacks when colliding with other static bodies. - CP_BODY_TYPE_STATIC, -} cpBodyType; - -/// Rigid body velocity update function type. -typedef void (*cpBodyVelocityFunc)(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt); -/// Rigid body position update function type. -typedef void (*cpBodyPositionFunc)(cpBody *body, cpFloat dt); - -/// Allocate a cpBody. -CP_EXPORT cpBody* cpBodyAlloc(void); -/// Initialize a cpBody. -CP_EXPORT cpBody* cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment); -/// Allocate and initialize a cpBody. -CP_EXPORT cpBody* cpBodyNew(cpFloat mass, cpFloat moment); - -/// Allocate and initialize a cpBody, and set it as a kinematic body. -CP_EXPORT cpBody* cpBodyNewKinematic(void); -/// Allocate and initialize a cpBody, and set it as a static body. -CP_EXPORT cpBody* cpBodyNewStatic(void); - -/// Destroy a cpBody. -CP_EXPORT void cpBodyDestroy(cpBody *body); -/// Destroy and free a cpBody. -CP_EXPORT void cpBodyFree(cpBody *body); - -// Defined in cpSpace.c -/// Wake up a sleeping or idle body. -CP_EXPORT void cpBodyActivate(cpBody *body); -/// Wake up any sleeping or idle bodies touching a static body. -CP_EXPORT void cpBodyActivateStatic(cpBody *body, cpShape *filter); - -/// Force a body to fall asleep immediately. -CP_EXPORT void cpBodySleep(cpBody *body); -/// Force a body to fall asleep immediately along with other bodies in a group. -CP_EXPORT void cpBodySleepWithGroup(cpBody *body, cpBody *group); - -/// Returns true if the body is sleeping. -CP_EXPORT cpBool cpBodyIsSleeping(const cpBody *body); - -/// Get the type of the body. -CP_EXPORT cpBodyType cpBodyGetType(cpBody *body); -/// Set the type of the body. -CP_EXPORT void cpBodySetType(cpBody *body, cpBodyType type); - -/// Get the space this body is added to. -CP_EXPORT cpSpace* cpBodyGetSpace(const cpBody *body); - -/// Get the mass of the body. -CP_EXPORT cpFloat cpBodyGetMass(const cpBody *body); -/// Set the mass of the body. -CP_EXPORT void cpBodySetMass(cpBody *body, cpFloat m); - -/// Get the moment of inertia of the body. -CP_EXPORT cpFloat cpBodyGetMoment(const cpBody *body); -/// Set the moment of inertia of the body. -CP_EXPORT void cpBodySetMoment(cpBody *body, cpFloat i); - -/// Set the position of a body. -CP_EXPORT cpVect cpBodyGetPosition(const cpBody *body); -/// Set the position of the body. -CP_EXPORT void cpBodySetPosition(cpBody *body, cpVect pos); - -/// Get the offset of the center of gravity in body local coordinates. -CP_EXPORT cpVect cpBodyGetCenterOfGravity(const cpBody *body); -/// Set the offset of the center of gravity in body local coordinates. -CP_EXPORT void cpBodySetCenterOfGravity(cpBody *body, cpVect cog); - -/// Get the velocity of the body. -CP_EXPORT cpVect cpBodyGetVelocity(const cpBody *body); -/// Set the velocity of the body. -CP_EXPORT void cpBodySetVelocity(cpBody *body, cpVect velocity); - -/// Get the force applied to the body for the next time step. -CP_EXPORT cpVect cpBodyGetForce(const cpBody *body); -/// Set the force applied to the body for the next time step. -CP_EXPORT void cpBodySetForce(cpBody *body, cpVect force); - -/// Get the angle of the body. -CP_EXPORT cpFloat cpBodyGetAngle(const cpBody *body); -/// Set the angle of a body. -CP_EXPORT void cpBodySetAngle(cpBody *body, cpFloat a); - -/// Get the angular velocity of the body. -CP_EXPORT cpFloat cpBodyGetAngularVelocity(const cpBody *body); -/// Set the angular velocity of the body. -CP_EXPORT void cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity); - -/// Get the torque applied to the body for the next time step. -CP_EXPORT cpFloat cpBodyGetTorque(const cpBody *body); -/// Set the torque applied to the body for the next time step. -CP_EXPORT void cpBodySetTorque(cpBody *body, cpFloat torque); - -/// Get the rotation vector of the body. (The x basis vector of it's transform.) -CP_EXPORT cpVect cpBodyGetRotation(const cpBody *body); - -/// Get the user data pointer assigned to the body. -CP_EXPORT cpDataPointer cpBodyGetUserData(const cpBody *body); -/// Set the user data pointer assigned to the body. -CP_EXPORT void cpBodySetUserData(cpBody *body, cpDataPointer userData); - -/// Set the callback used to update a body's velocity. -CP_EXPORT void cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc); -/// Set the callback used to update a body's position. -/// NOTE: It's not generally recommended to override this unless you call the default position update function. -CP_EXPORT void cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc); - -/// Default velocity integration function.. -CP_EXPORT void cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt); -/// Default position integration function. -CP_EXPORT void cpBodyUpdatePosition(cpBody *body, cpFloat dt); - -/// Convert body relative/local coordinates to absolute/world coordinates. -CP_EXPORT cpVect cpBodyLocalToWorld(const cpBody *body, const cpVect point); -/// Convert body absolute/world coordinates to relative/local coordinates. -CP_EXPORT cpVect cpBodyWorldToLocal(const cpBody *body, const cpVect point); - -/// Apply a force to a body. Both the force and point are expressed in world coordinates. -CP_EXPORT void cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point); -/// Apply a force to a body. Both the force and point are expressed in body local coordinates. -CP_EXPORT void cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point); - -/// Apply an impulse to a body. Both the impulse and point are expressed in world coordinates. -CP_EXPORT void cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point); -/// Apply an impulse to a body. Both the impulse and point are expressed in body local coordinates. -CP_EXPORT void cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point); - -/// Get the velocity on a body (in world units) at a point on the body in world coordinates. -CP_EXPORT cpVect cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point); -/// Get the velocity on a body (in world units) at a point on the body in local coordinates. -CP_EXPORT cpVect cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point); - -/// Get the amount of kinetic energy contained by the body. -CP_EXPORT cpFloat cpBodyKineticEnergy(const cpBody *body); - -/// Body/shape iterator callback function type. -typedef void (*cpBodyShapeIteratorFunc)(cpBody *body, cpShape *shape, void *data); -/// Call @c func once for each shape attached to @c body and added to the space. -CP_EXPORT void cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data); - -/// Body/constraint iterator callback function type. -typedef void (*cpBodyConstraintIteratorFunc)(cpBody *body, cpConstraint *constraint, void *data); -/// Call @c func once for each constraint attached to @c body and added to the space. -CP_EXPORT void cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data); - -/// Body/arbiter iterator callback function type. -typedef void (*cpBodyArbiterIteratorFunc)(cpBody *body, cpArbiter *arbiter, void *data); -/// Call @c func once for each arbiter that is currently active on the body. -CP_EXPORT void cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data); - -///@} diff --git a/3rdparty/chipmunk/include/chipmunk/cpConstraint.h b/3rdparty/chipmunk/include/chipmunk/cpConstraint.h deleted file mode 100644 index b1a439f7be24..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpConstraint.h +++ /dev/null @@ -1,95 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpConstraint cpConstraint -/// @{ - -/// Callback function type that gets called before solving a joint. -typedef void (*cpConstraintPreSolveFunc)(cpConstraint *constraint, cpSpace *space); -/// Callback function type that gets called after solving a joint. -typedef void (*cpConstraintPostSolveFunc)(cpConstraint *constraint, cpSpace *space); - -/// Destroy a constraint. -CP_EXPORT void cpConstraintDestroy(cpConstraint *constraint); -/// Destroy and free a constraint. -CP_EXPORT void cpConstraintFree(cpConstraint *constraint); - -/// Get the cpSpace this constraint is added to. -CP_EXPORT cpSpace* cpConstraintGetSpace(const cpConstraint *constraint); - -/// Get the first body the constraint is attached to. -CP_EXPORT cpBody* cpConstraintGetBodyA(const cpConstraint *constraint); - -/// Get the second body the constraint is attached to. -CP_EXPORT cpBody* cpConstraintGetBodyB(const cpConstraint *constraint); - -/// Get the maximum force that this constraint is allowed to use. -CP_EXPORT cpFloat cpConstraintGetMaxForce(const cpConstraint *constraint); -/// Set the maximum force that this constraint is allowed to use. (defaults to INFINITY) -CP_EXPORT void cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce); - -/// Get rate at which joint error is corrected. -CP_EXPORT cpFloat cpConstraintGetErrorBias(const cpConstraint *constraint); -/// Set rate at which joint error is corrected. -/// Defaults to pow(1.0 - 0.1, 60.0) meaning that it will -/// correct 10% of the error every 1/60th of a second. -CP_EXPORT void cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias); - -/// Get the maximum rate at which joint error is corrected. -CP_EXPORT cpFloat cpConstraintGetMaxBias(const cpConstraint *constraint); -/// Set the maximum rate at which joint error is corrected. (defaults to INFINITY) -CP_EXPORT void cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias); - -/// Get if the two bodies connected by the constraint are allowed to collide or not. -CP_EXPORT cpBool cpConstraintGetCollideBodies(const cpConstraint *constraint); -/// Set if the two bodies connected by the constraint are allowed to collide or not. (defaults to cpFalse) -CP_EXPORT void cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies); - -/// Get the pre-solve function that is called before the solver runs. -CP_EXPORT cpConstraintPreSolveFunc cpConstraintGetPreSolveFunc(const cpConstraint *constraint); -/// Set the pre-solve function that is called before the solver runs. -CP_EXPORT void cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc); - -/// Get the post-solve function that is called before the solver runs. -CP_EXPORT cpConstraintPostSolveFunc cpConstraintGetPostSolveFunc(const cpConstraint *constraint); -/// Set the post-solve function that is called before the solver runs. -CP_EXPORT void cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc); - -/// Get the user definable data pointer for this constraint -CP_EXPORT cpDataPointer cpConstraintGetUserData(const cpConstraint *constraint); -/// Set the user definable data pointer for this constraint -CP_EXPORT void cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData); - -/// Get the last impulse applied by this constraint. -CP_EXPORT cpFloat cpConstraintGetImpulse(cpConstraint *constraint); - -#include "cpPinJoint.h" -#include "cpSlideJoint.h" -#include "cpPivotJoint.h" -#include "cpGrooveJoint.h" -#include "cpDampedSpring.h" -#include "cpDampedRotarySpring.h" -#include "cpRotaryLimitJoint.h" -#include "cpRatchetJoint.h" -#include "cpGearJoint.h" -#include "cpSimpleMotor.h" - -///@} diff --git a/3rdparty/chipmunk/include/chipmunk/cpDampedRotarySpring.h b/3rdparty/chipmunk/include/chipmunk/cpDampedRotarySpring.h deleted file mode 100644 index 6f60e86e301a..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpDampedRotarySpring.h +++ /dev/null @@ -1,58 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpDampedRotarySpring cpDampedRotarySpring -/// @{ - -/// Check if a constraint is a damped rotary springs. -CP_EXPORT cpBool cpConstraintIsDampedRotarySpring(const cpConstraint *constraint); - -/// Function type used for damped rotary spring force callbacks. -typedef cpFloat (*cpDampedRotarySpringTorqueFunc)(struct cpConstraint *spring, cpFloat relativeAngle); - -/// Allocate a damped rotary spring. -CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringAlloc(void); -/// Initialize a damped rotary spring. -CP_EXPORT cpDampedRotarySpring* cpDampedRotarySpringInit(cpDampedRotarySpring *joint, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); -/// Allocate and initialize a damped rotary spring. -CP_EXPORT cpConstraint* cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping); - -/// Get the rest length of the spring. -CP_EXPORT cpFloat cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint); -/// Set the rest length of the spring. -CP_EXPORT void cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle); - -/// Get the stiffness of the spring in force/distance. -CP_EXPORT cpFloat cpDampedRotarySpringGetStiffness(const cpConstraint *constraint); -/// Set the stiffness of the spring in force/distance. -CP_EXPORT void cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness); - -/// Get the damping of the spring. -CP_EXPORT cpFloat cpDampedRotarySpringGetDamping(const cpConstraint *constraint); -/// Set the damping of the spring. -CP_EXPORT void cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping); - -/// Get the damping of the spring. -CP_EXPORT cpDampedRotarySpringTorqueFunc cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint); -/// Set the damping of the spring. -CP_EXPORT void cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpDampedSpring.h b/3rdparty/chipmunk/include/chipmunk/cpDampedSpring.h deleted file mode 100644 index b332fc7f02dc..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpDampedSpring.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpDampedSpring cpDampedSpring -/// @{ - -/// Check if a constraint is a slide joint. -CP_EXPORT cpBool cpConstraintIsDampedSpring(const cpConstraint *constraint); - -/// Function type used for damped spring force callbacks. -typedef cpFloat (*cpDampedSpringForceFunc)(cpConstraint *spring, cpFloat dist); - -/// Allocate a damped spring. -CP_EXPORT cpDampedSpring* cpDampedSpringAlloc(void); -/// Initialize a damped spring. -CP_EXPORT cpDampedSpring* cpDampedSpringInit(cpDampedSpring *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping); -/// Allocate and initialize a damped spring. -CP_EXPORT cpConstraint* cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping); - -/// Get the location of the first anchor relative to the first body. -CP_EXPORT cpVect cpDampedSpringGetAnchorA(const cpConstraint *constraint); -/// Set the location of the first anchor relative to the first body. -CP_EXPORT void cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA); - -/// Get the location of the second anchor relative to the second body. -CP_EXPORT cpVect cpDampedSpringGetAnchorB(const cpConstraint *constraint); -/// Set the location of the second anchor relative to the second body. -CP_EXPORT void cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB); - -/// Get the rest length of the spring. -CP_EXPORT cpFloat cpDampedSpringGetRestLength(const cpConstraint *constraint); -/// Set the rest length of the spring. -CP_EXPORT void cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength); - -/// Get the stiffness of the spring in force/distance. -CP_EXPORT cpFloat cpDampedSpringGetStiffness(const cpConstraint *constraint); -/// Set the stiffness of the spring in force/distance. -CP_EXPORT void cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness); - -/// Get the damping of the spring. -CP_EXPORT cpFloat cpDampedSpringGetDamping(const cpConstraint *constraint); -/// Set the damping of the spring. -CP_EXPORT void cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping); - -/// Get the damping of the spring. -CP_EXPORT cpDampedSpringForceFunc cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint); -/// Set the damping of the spring. -CP_EXPORT void cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpGearJoint.h b/3rdparty/chipmunk/include/chipmunk/cpGearJoint.h deleted file mode 100644 index 8cd80e0b906c..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpGearJoint.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpGearJoint cpGearJoint -/// @{ - -/// Check if a constraint is a damped rotary springs. -CP_EXPORT cpBool cpConstraintIsGearJoint(const cpConstraint *constraint); - -/// Allocate a gear joint. -CP_EXPORT cpGearJoint* cpGearJointAlloc(void); -/// Initialize a gear joint. -CP_EXPORT cpGearJoint* cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); -/// Allocate and initialize a gear joint. -CP_EXPORT cpConstraint* cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio); - -/// Get the phase offset of the gears. -CP_EXPORT cpFloat cpGearJointGetPhase(const cpConstraint *constraint); -/// Set the phase offset of the gears. -CP_EXPORT void cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase); - -/// Get the angular distance of each ratchet. -CP_EXPORT cpFloat cpGearJointGetRatio(const cpConstraint *constraint); -/// Set the ratio of a gear joint. -CP_EXPORT void cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpGrooveJoint.h b/3rdparty/chipmunk/include/chipmunk/cpGrooveJoint.h deleted file mode 100644 index 8bdafc14aa2f..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpGrooveJoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpGrooveJoint cpGrooveJoint -/// @{ - -/// Check if a constraint is a slide joint. -CP_EXPORT cpBool cpConstraintIsGrooveJoint(const cpConstraint *constraint); - -/// Allocate a groove joint. -CP_EXPORT cpGrooveJoint* cpGrooveJointAlloc(void); -/// Initialize a groove joint. -CP_EXPORT cpGrooveJoint* cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB); -/// Allocate and initialize a groove joint. -CP_EXPORT cpConstraint* cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB); - -/// Get the first endpoint of the groove relative to the first body. -CP_EXPORT cpVect cpGrooveJointGetGrooveA(const cpConstraint *constraint); -/// Set the first endpoint of the groove relative to the first body. -CP_EXPORT void cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect grooveA); - -/// Get the first endpoint of the groove relative to the first body. -CP_EXPORT cpVect cpGrooveJointGetGrooveB(const cpConstraint *constraint); -/// Set the first endpoint of the groove relative to the first body. -CP_EXPORT void cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect grooveB); - -/// Get the location of the second anchor relative to the second body. -CP_EXPORT cpVect cpGrooveJointGetAnchorB(const cpConstraint *constraint); -/// Set the location of the second anchor relative to the second body. -CP_EXPORT void cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpHastySpace.h b/3rdparty/chipmunk/include/chipmunk/cpHastySpace.h deleted file mode 100644 index 6de2283b9fb7..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpHastySpace.h +++ /dev/null @@ -1,27 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -/// cpHastySpace is exclusive to Chipmunk Pro -/// Currently it enables ARM NEON optimizations in the solver, but in the future will include other optimizations such as -/// a multi-threaded solver and multi-threaded collision broadphases. - -struct cpHastySpace; -typedef struct cpHastySpace cpHastySpace; - -/// Create a new hasty space. -/// On ARM platforms that support NEON, this will enable the vectorized solver. -/// cpHastySpace also supports multiple threads, but runs single threaded by default for determinism. -CP_EXPORT cpSpace *cpHastySpaceNew(void); -CP_EXPORT void cpHastySpaceFree(cpSpace *space); - -/// Set the number of threads to use for the solver. -/// Currently Chipmunk is limited to 2 threads as using more generally provides very minimal performance gains. -/// Passing 0 as the thread count on iOS or OS X will cause Chipmunk to automatically detect the number of threads it should use. -/// On other platforms passing 0 for the thread count will set 1 thread. -CP_EXPORT void cpHastySpaceSetThreads(cpSpace *space, unsigned long threads); - -/// Returns the number of threads the solver is using to run. -CP_EXPORT unsigned long cpHastySpaceGetThreads(cpSpace *space); - -/// When stepping a hasty space, you must use this function. -CP_EXPORT void cpHastySpaceStep(cpSpace *space, cpFloat dt); diff --git a/3rdparty/chipmunk/include/chipmunk/cpMarch.h b/3rdparty/chipmunk/include/chipmunk/cpMarch.h deleted file mode 100644 index cc1f5c061d1f..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpMarch.h +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -/// Function type used as a callback from the marching squares algorithm to sample an image function. -/// It passes you the point to sample and your context pointer, and you return the density. -typedef cpFloat (*cpMarchSampleFunc)(cpVect point, void *data); - -/// Function type used as a callback from the marching squares algorithm to output a line segment. -/// It passes you the two endpoints and your context pointer. -typedef void (*cpMarchSegmentFunc)(cpVect v0, cpVect v1, void *data); - -/// Trace an anti-aliased contour of an image along a particular threshold. -/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context. -/// The segment function will be called for each segment detected that lies along the density contour for @c threshold. -CP_EXPORT void cpMarchSoft( - cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold, - cpMarchSegmentFunc segment, void *segment_data, - cpMarchSampleFunc sample, void *sample_data -); - -/// Trace an aliased curve of an image along a particular threshold. -/// The given number of samples will be taken and spread across the bounding box area using the sampling function and context. -/// The segment function will be called for each segment detected that lies along the density contour for @c threshold. -CP_EXPORT void cpMarchHard( - cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat threshold, - cpMarchSegmentFunc segment, void *segment_data, - cpMarchSampleFunc sample, void *sample_data -); diff --git a/3rdparty/chipmunk/include/chipmunk/cpPinJoint.h b/3rdparty/chipmunk/include/chipmunk/cpPinJoint.h deleted file mode 100644 index 45aaa3e333da..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpPinJoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpPinJoint cpPinJoint -/// @{ - -/// Check if a constraint is a pin joint. -CP_EXPORT cpBool cpConstraintIsPinJoint(const cpConstraint *constraint); - -/// Allocate a pin joint. -CP_EXPORT cpPinJoint* cpPinJointAlloc(void); -/// Initialize a pin joint. -CP_EXPORT cpPinJoint* cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB); -/// Allocate and initialize a pin joint. -CP_EXPORT cpConstraint* cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB); - -/// Get the location of the first anchor relative to the first body. -CP_EXPORT cpVect cpPinJointGetAnchorA(const cpConstraint *constraint); -/// Set the location of the first anchor relative to the first body. -CP_EXPORT void cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA); - -/// Get the location of the second anchor relative to the second body. -CP_EXPORT cpVect cpPinJointGetAnchorB(const cpConstraint *constraint); -/// Set the location of the second anchor relative to the second body. -CP_EXPORT void cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB); - -/// Get the distance the joint will maintain between the two anchors. -CP_EXPORT cpFloat cpPinJointGetDist(const cpConstraint *constraint); -/// Set the distance the joint will maintain between the two anchors. -CP_EXPORT void cpPinJointSetDist(cpConstraint *constraint, cpFloat dist); - -///@} diff --git a/3rdparty/chipmunk/include/chipmunk/cpPivotJoint.h b/3rdparty/chipmunk/include/chipmunk/cpPivotJoint.h deleted file mode 100644 index 4a620ef2553d..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpPivotJoint.h +++ /dev/null @@ -1,47 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpPivotJoint cpPivotJoint -/// @{ - -/// Check if a constraint is a slide joint. -CP_EXPORT cpBool cpConstraintIsPivotJoint(const cpConstraint *constraint); - -/// Allocate a pivot joint -CP_EXPORT cpPivotJoint* cpPivotJointAlloc(void); -/// Initialize a pivot joint. -CP_EXPORT cpPivotJoint* cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB); -/// Allocate and initialize a pivot joint. -CP_EXPORT cpConstraint* cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot); -/// Allocate and initialize a pivot joint with specific anchors. -CP_EXPORT cpConstraint* cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB); - -/// Get the location of the first anchor relative to the first body. -CP_EXPORT cpVect cpPivotJointGetAnchorA(const cpConstraint *constraint); -/// Set the location of the first anchor relative to the first body. -CP_EXPORT void cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA); - -/// Get the location of the second anchor relative to the second body. -CP_EXPORT cpVect cpPivotJointGetAnchorB(const cpConstraint *constraint); -/// Set the location of the second anchor relative to the second body. -CP_EXPORT void cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpPolyShape.h b/3rdparty/chipmunk/include/chipmunk/cpPolyShape.h deleted file mode 100644 index 25f688b896ae..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpPolyShape.h +++ /dev/null @@ -1,56 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpPolyShape cpPolyShape -/// @{ - -/// Allocate a polygon shape. -CP_EXPORT cpPolyShape* cpPolyShapeAlloc(void); -/// Initialize a polygon shape with rounded corners. -/// A convex hull will be created from the vertexes. -CP_EXPORT cpPolyShape* cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius); -/// Initialize a polygon shape with rounded corners. -/// The vertexes must be convex with a counter-clockwise winding. -CP_EXPORT cpPolyShape* cpPolyShapeInitRaw(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpFloat radius); -/// Allocate and initialize a polygon shape with rounded corners. -/// A convex hull will be created from the vertexes. -CP_EXPORT cpShape* cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius); -/// Allocate and initialize a polygon shape with rounded corners. -/// The vertexes must be convex with a counter-clockwise winding. -CP_EXPORT cpShape* cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius); - -/// Initialize a box shaped polygon shape with rounded corners. -CP_EXPORT cpPolyShape* cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius); -/// Initialize an offset box shaped polygon shape with rounded corners. -CP_EXPORT cpPolyShape* cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius); -/// Allocate and initialize a box shaped polygon shape. -CP_EXPORT cpShape* cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius); -/// Allocate and initialize an offset box shaped polygon shape. -CP_EXPORT cpShape* cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius); - -/// Get the number of verts in a polygon shape. -CP_EXPORT int cpPolyShapeGetCount(const cpShape *shape); -/// Get the @c ith vertex of a polygon shape. -CP_EXPORT cpVect cpPolyShapeGetVert(const cpShape *shape, int index); -/// Get the radius of a polygon shape. -CP_EXPORT cpFloat cpPolyShapeGetRadius(const cpShape *shape); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpPolyline.h b/3rdparty/chipmunk/include/chipmunk/cpPolyline.h deleted file mode 100644 index 9a6ebed3caa1..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpPolyline.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -// Polylines are just arrays of vertexes. -// They are looped if the first vertex is equal to the last. -// cpPolyline structs are intended to be passed by value and destroyed when you are done with them. -typedef struct cpPolyline { - int count, capacity; - cpVect verts[]; -} cpPolyline; - -/// Destroy and free a polyline instance. -CP_EXPORT void cpPolylineFree(cpPolyline *line); - -/// Returns true if the first vertex is equal to the last. -CP_EXPORT cpBool cpPolylineIsClosed(cpPolyline *line); - -/** - Returns a copy of a polyline simplified by using the Douglas-Peucker algorithm. - This works very well on smooth or gently curved shapes, but not well on straight edged or angular shapes. -*/ -CP_EXPORT cpPolyline *cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol); - -/** - Returns a copy of a polyline simplified by discarding "flat" vertexes. - This works well on straight edged or angular shapes, not as well on smooth shapes. -*/ -CP_EXPORT cpPolyline *cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol); - -/// Get the convex hull of a polyline as a looped polyline. -CP_EXPORT cpPolyline *cpPolylineToConvexHull(cpPolyline *line, cpFloat tol); - - -/// Polyline sets are collections of polylines, generally built by cpMarchSoft() or cpMarchHard(). -typedef struct cpPolylineSet { - int count, capacity; - cpPolyline **lines; -} cpPolylineSet; - -/// Allocate a new polyline set. -CP_EXPORT cpPolylineSet *cpPolylineSetAlloc(void); - -/// Initialize a new polyline set. -CP_EXPORT cpPolylineSet *cpPolylineSetInit(cpPolylineSet *set); - -/// Allocate and initialize a polyline set. -CP_EXPORT cpPolylineSet *cpPolylineSetNew(void); - -/// Destroy a polyline set. -CP_EXPORT void cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines); - -/// Destroy and free a polyline set. -CP_EXPORT void cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines); - -/** - Add a line segment to a polyline set. - A segment will either start a new polyline, join two others, or add to or loop an existing polyline. - This is mostly intended to be used as a callback directly from cpMarchSoft() or cpMarchHard(). -*/ -CP_EXPORT void cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines); - -/** - Get an approximate convex decomposition from a polyline. - Returns a cpPolylineSet of convex hulls that match the original shape to within 'tol'. - NOTE: If the input is a self intersecting polygon, the output might end up overly simplified. -*/ - -CP_EXPORT cpPolylineSet *cpPolylineConvexDecomposition(cpPolyline *line, cpFloat tol); - -#define cpPolylineConvexDecomposition_BETA cpPolylineConvexDecomposition diff --git a/3rdparty/chipmunk/include/chipmunk/cpRatchetJoint.h b/3rdparty/chipmunk/include/chipmunk/cpRatchetJoint.h deleted file mode 100644 index 3ed4c915ee75..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpRatchetJoint.h +++ /dev/null @@ -1,50 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpRatchetJoint cpRatchetJoint -/// @{ - -/// Check if a constraint is a damped rotary springs. -CP_EXPORT cpBool cpConstraintIsRatchetJoint(const cpConstraint *constraint); - -/// Allocate a ratchet joint. -CP_EXPORT cpRatchetJoint* cpRatchetJointAlloc(void); -/// Initialize a ratched joint. -CP_EXPORT cpRatchetJoint* cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); -/// Allocate and initialize a ratchet joint. -CP_EXPORT cpConstraint* cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet); - -/// Get the angle of the current ratchet tooth. -CP_EXPORT cpFloat cpRatchetJointGetAngle(const cpConstraint *constraint); -/// Set the angle of the current ratchet tooth. -CP_EXPORT void cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle); - -/// Get the phase offset of the ratchet. -CP_EXPORT cpFloat cpRatchetJointGetPhase(const cpConstraint *constraint); -/// Get the phase offset of the ratchet. -CP_EXPORT void cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase); - -/// Get the angular distance of each ratchet. -CP_EXPORT cpFloat cpRatchetJointGetRatchet(const cpConstraint *constraint); -/// Set the angular distance of each ratchet. -CP_EXPORT void cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpRobust.h b/3rdparty/chipmunk/include/chipmunk/cpRobust.h deleted file mode 100644 index e4b2c42082e3..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpRobust.h +++ /dev/null @@ -1,11 +0,0 @@ -#include "chipmunk/cpVect.h" - -// This is a private header for functions (currently just one) that need strict floating point results. -// It was easier to put this in it's own file than to fiddle with 4 different compiler specific pragmas or attributes. -// "Fast math" should be disabled here. - -// Check if c is to the left of segment (a, b). -cpBool cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c); - -// Check if p is behind one of v0 or v1 on axis n. -cpBool cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n); diff --git a/3rdparty/chipmunk/include/chipmunk/cpRotaryLimitJoint.h b/3rdparty/chipmunk/include/chipmunk/cpRotaryLimitJoint.h deleted file mode 100644 index fac7ad859166..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpRotaryLimitJoint.h +++ /dev/null @@ -1,45 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpRotaryLimitJoint cpRotaryLimitJoint -/// @{ - -/// Check if a constraint is a damped rotary springs. -CP_EXPORT cpBool cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint); - -/// Allocate a damped rotary limit joint. -CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointAlloc(void); -/// Initialize a damped rotary limit joint. -CP_EXPORT cpRotaryLimitJoint* cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max); -/// Allocate and initialize a damped rotary limit joint. -CP_EXPORT cpConstraint* cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max); - -/// Get the minimum distance the joint will maintain between the two anchors. -CP_EXPORT cpFloat cpRotaryLimitJointGetMin(const cpConstraint *constraint); -/// Set the minimum distance the joint will maintain between the two anchors. -CP_EXPORT void cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min); - -/// Get the maximum distance the joint will maintain between the two anchors. -CP_EXPORT cpFloat cpRotaryLimitJointGetMax(const cpConstraint *constraint); -/// Set the maximum distance the joint will maintain between the two anchors. -CP_EXPORT void cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpShape.h b/3rdparty/chipmunk/include/chipmunk/cpShape.h deleted file mode 100644 index c78ed05d092b..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpShape.h +++ /dev/null @@ -1,199 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpShape cpShape -/// The cpShape struct defines the shape of a rigid body. -/// @{ - -/// Point query info struct. -typedef struct cpPointQueryInfo { - /// The nearest shape, NULL if no shape was within range. - const cpShape *shape; - /// The closest point on the shape's surface. (in world space coordinates) - cpVect point; - /// The distance to the point. The distance is negative if the point is inside the shape. - cpFloat distance; - /// The gradient of the signed distance function. - /// The value should be similar to info.p/info.d, but accurate even for very small values of info.d. - cpVect gradient; -} cpPointQueryInfo; - -/// Segment query info struct. -typedef struct cpSegmentQueryInfo { - /// The shape that was hit, or NULL if no collision occured. - const cpShape *shape; - /// The point of impact. - cpVect point; - /// The normal of the surface hit. - cpVect normal; - /// The normalized distance along the query segment in the range [0, 1]. - cpFloat alpha; -} cpSegmentQueryInfo; - -/// Fast collision filtering type that is used to determine if two objects collide before calling collision or query callbacks. -typedef struct cpShapeFilter { - /// Two objects with the same non-zero group value do not collide. - /// This is generally used to group objects in a composite object together to disable self collisions. - cpGroup group; - /// A bitmask of user definable categories that this object belongs to. - /// The category/mask combinations of both objects in a collision must agree for a collision to occur. - cpBitmask categories; - /// A bitmask of user definable category types that this object object collides with. - /// The category/mask combinations of both objects in a collision must agree for a collision to occur. - cpBitmask mask; -} cpShapeFilter; - -/// Collision filter value for a shape that will collide with anything except CP_SHAPE_FILTER_NONE. -static const cpShapeFilter CP_SHAPE_FILTER_ALL = {CP_NO_GROUP, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES}; -/// Collision filter value for a shape that does not collide with anything. -static const cpShapeFilter CP_SHAPE_FILTER_NONE = {CP_NO_GROUP, ~CP_ALL_CATEGORIES, ~CP_ALL_CATEGORIES}; - -/// Create a new collision filter. -static inline cpShapeFilter -cpShapeFilterNew(cpGroup group, cpBitmask categories, cpBitmask mask) -{ - cpShapeFilter filter = {group, categories, mask}; - return filter; -} - -/// Destroy a shape. -CP_EXPORT void cpShapeDestroy(cpShape *shape); -/// Destroy and Free a shape. -CP_EXPORT void cpShapeFree(cpShape *shape); - -/// Update, cache and return the bounding box of a shape based on the body it's attached to. -CP_EXPORT cpBB cpShapeCacheBB(cpShape *shape); -/// Update, cache and return the bounding box of a shape with an explicit transformation. -CP_EXPORT cpBB cpShapeUpdate(cpShape *shape, cpTransform transform); - -/// Perform a nearest point query. It finds the closest point on the surface of shape to a specific point. -/// The value returned is the distance between the points. A negative distance means the point is inside the shape. -CP_EXPORT cpFloat cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *out); - -/// Perform a segment query against a shape. @c info must be a pointer to a valid cpSegmentQueryInfo structure. -CP_EXPORT cpBool cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info); - -/// Return contact information about two shapes. -CP_EXPORT cpContactPointSet cpShapesCollide(const cpShape *a, const cpShape *b); - -/// The cpSpace this body is added to. -CP_EXPORT cpSpace* cpShapeGetSpace(const cpShape *shape); - -/// The cpBody this shape is connected to. -CP_EXPORT cpBody* cpShapeGetBody(const cpShape *shape); -/// Set the cpBody this shape is connected to. -/// Can only be used if the shape is not currently added to a space. -CP_EXPORT void cpShapeSetBody(cpShape *shape, cpBody *body); - -/// Get the mass of the shape if you are having Chipmunk calculate mass properties for you. -CP_EXPORT cpFloat cpShapeGetMass(cpShape *shape); -/// Set the mass of this shape to have Chipmunk calculate mass properties for you. -CP_EXPORT void cpShapeSetMass(cpShape *shape, cpFloat mass); - -/// Get the density of the shape if you are having Chipmunk calculate mass properties for you. -CP_EXPORT cpFloat cpShapeGetDensity(cpShape *shape); -/// Set the density of this shape to have Chipmunk calculate mass properties for you. -CP_EXPORT void cpShapeSetDensity(cpShape *shape, cpFloat density); - -/// Get the calculated moment of inertia for this shape. -CP_EXPORT cpFloat cpShapeGetMoment(cpShape *shape); -/// Get the calculated area of this shape. -CP_EXPORT cpFloat cpShapeGetArea(cpShape *shape); -/// Get the centroid of this shape. -CP_EXPORT cpVect cpShapeGetCenterOfGravity(cpShape *shape); - -/// Get the bounding box that contains the shape given it's current position and angle. -CP_EXPORT cpBB cpShapeGetBB(const cpShape *shape); - -/// Get if the shape is set to be a sensor or not. -CP_EXPORT cpBool cpShapeGetSensor(const cpShape *shape); -/// Set if the shape is a sensor or not. -CP_EXPORT void cpShapeSetSensor(cpShape *shape, cpBool sensor); - -/// Get the elasticity of this shape. -CP_EXPORT cpFloat cpShapeGetElasticity(const cpShape *shape); -/// Set the elasticity of this shape. -CP_EXPORT void cpShapeSetElasticity(cpShape *shape, cpFloat elasticity); - -/// Get the friction of this shape. -CP_EXPORT cpFloat cpShapeGetFriction(const cpShape *shape); -/// Set the friction of this shape. -CP_EXPORT void cpShapeSetFriction(cpShape *shape, cpFloat friction); - -/// Get the surface velocity of this shape. -CP_EXPORT cpVect cpShapeGetSurfaceVelocity(const cpShape *shape); -/// Set the surface velocity of this shape. -CP_EXPORT void cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity); - -/// Get the user definable data pointer of this shape. -CP_EXPORT cpDataPointer cpShapeGetUserData(const cpShape *shape); -/// Set the user definable data pointer of this shape. -CP_EXPORT void cpShapeSetUserData(cpShape *shape, cpDataPointer userData); - -/// Set the collision type of this shape. -CP_EXPORT cpCollisionType cpShapeGetCollisionType(const cpShape *shape); -/// Get the collision type of this shape. -CP_EXPORT void cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType); - -/// Get the collision filtering parameters of this shape. -CP_EXPORT cpShapeFilter cpShapeGetFilter(const cpShape *shape); -/// Set the collision filtering parameters of this shape. -CP_EXPORT void cpShapeSetFilter(cpShape *shape, cpShapeFilter filter); - - -/// @} -/// @defgroup cpCircleShape cpCircleShape - -/// Allocate a circle shape. -CP_EXPORT cpCircleShape* cpCircleShapeAlloc(void); -/// Initialize a circle shape. -CP_EXPORT cpCircleShape* cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset); -/// Allocate and initialize a circle shape. -CP_EXPORT cpShape* cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset); - -/// Get the offset of a circle shape. -CP_EXPORT cpVect cpCircleShapeGetOffset(const cpShape *shape); -/// Get the radius of a circle shape. -CP_EXPORT cpFloat cpCircleShapeGetRadius(const cpShape *shape); - -/// @} -/// @defgroup cpSegmentShape cpSegmentShape - -/// Allocate a segment shape. -CP_EXPORT cpSegmentShape* cpSegmentShapeAlloc(void); -/// Initialize a segment shape. -CP_EXPORT cpSegmentShape* cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat radius); -/// Allocate and initialize a segment shape. -CP_EXPORT cpShape* cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat radius); - -/// Let Chipmunk know about the geometry of adjacent segments to avoid colliding with endcaps. -CP_EXPORT void cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next); - -/// Get the first endpoint of a segment shape. -CP_EXPORT cpVect cpSegmentShapeGetA(const cpShape *shape); -/// Get the second endpoint of a segment shape. -CP_EXPORT cpVect cpSegmentShapeGetB(const cpShape *shape); -/// Get the normal of a segment shape. -CP_EXPORT cpVect cpSegmentShapeGetNormal(const cpShape *shape); -/// Get the first endpoint of a segment shape. -CP_EXPORT cpFloat cpSegmentShapeGetRadius(const cpShape *shape); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpSimpleMotor.h b/3rdparty/chipmunk/include/chipmunk/cpSimpleMotor.h deleted file mode 100644 index 811b01143e25..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpSimpleMotor.h +++ /dev/null @@ -1,43 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpSimpleMotor cpSimpleMotor -/// @{ - -/// Opaque struct type for damped rotary springs. -typedef struct cpSimpleMotor cpSimpleMotor; - -/// Check if a constraint is a damped rotary springs. -CP_EXPORT cpBool cpConstraintIsSimpleMotor(const cpConstraint *constraint); - -/// Allocate a simple motor. -CP_EXPORT cpSimpleMotor* cpSimpleMotorAlloc(void); -/// initialize a simple motor. -CP_EXPORT cpSimpleMotor* cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate); -/// Allocate and initialize a simple motor. -CP_EXPORT cpConstraint* cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate); - -/// Get the rate of the motor. -CP_EXPORT cpFloat cpSimpleMotorGetRate(const cpConstraint *constraint); -/// Set the rate of the motor. -CP_EXPORT void cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpSlideJoint.h b/3rdparty/chipmunk/include/chipmunk/cpSlideJoint.h deleted file mode 100644 index c41f9a42eead..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpSlideJoint.h +++ /dev/null @@ -1,55 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpSlideJoint cpSlideJoint -/// @{ - -/// Check if a constraint is a slide joint. -CP_EXPORT cpBool cpConstraintIsSlideJoint(const cpConstraint *constraint); - -/// Allocate a slide joint. -CP_EXPORT cpSlideJoint* cpSlideJointAlloc(void); -/// Initialize a slide joint. -CP_EXPORT cpSlideJoint* cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max); -/// Allocate and initialize a slide joint. -CP_EXPORT cpConstraint* cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max); - -/// Get the location of the first anchor relative to the first body. -CP_EXPORT cpVect cpSlideJointGetAnchorA(const cpConstraint *constraint); -/// Set the location of the first anchor relative to the first body. -CP_EXPORT void cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA); - -/// Get the location of the second anchor relative to the second body. -CP_EXPORT cpVect cpSlideJointGetAnchorB(const cpConstraint *constraint); -/// Set the location of the second anchor relative to the second body. -CP_EXPORT void cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB); - -/// Get the minimum distance the joint will maintain between the two anchors. -CP_EXPORT cpFloat cpSlideJointGetMin(const cpConstraint *constraint); -/// Set the minimum distance the joint will maintain between the two anchors. -CP_EXPORT void cpSlideJointSetMin(cpConstraint *constraint, cpFloat min); - -/// Get the maximum distance the joint will maintain between the two anchors. -CP_EXPORT cpFloat cpSlideJointGetMax(const cpConstraint *constraint); -/// Set the maximum distance the joint will maintain between the two anchors. -CP_EXPORT void cpSlideJointSetMax(cpConstraint *constraint, cpFloat max); - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpSpace.h b/3rdparty/chipmunk/include/chipmunk/cpSpace.h deleted file mode 100644 index 7bbabb857d52..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpSpace.h +++ /dev/null @@ -1,319 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/// @defgroup cpSpace cpSpace -/// @{ - -//MARK: Definitions - -/// Collision begin event function callback type. -/// Returning false from a begin callback causes the collision to be ignored until -/// the the separate callback is called when the objects stop colliding. -typedef cpBool (*cpCollisionBeginFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData); -/// Collision pre-solve event function callback type. -/// Returning false from a pre-step callback causes the collision to be ignored until the next step. -typedef cpBool (*cpCollisionPreSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData); -/// Collision post-solve event function callback type. -typedef void (*cpCollisionPostSolveFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData); -/// Collision separate event function callback type. -typedef void (*cpCollisionSeparateFunc)(cpArbiter *arb, cpSpace *space, cpDataPointer userData); - -/// Struct that holds function callback pointers to configure custom collision handling. -/// Collision handlers have a pair of types; when a collision occurs between two shapes that have these types, the collision handler functions are triggered. -struct cpCollisionHandler { - /// Collision type identifier of the first shape that this handler recognizes. - /// In the collision handler callback, the shape with this type will be the first argument. Read only. - const cpCollisionType typeA; - /// Collision type identifier of the second shape that this handler recognizes. - /// In the collision handler callback, the shape with this type will be the second argument. Read only. - const cpCollisionType typeB; - /// This function is called when two shapes with types that match this collision handler begin colliding. - cpCollisionBeginFunc beginFunc; - /// This function is called each step when two shapes with types that match this collision handler are colliding. - /// It's called before the collision solver runs so that you can affect a collision's outcome. - cpCollisionPreSolveFunc preSolveFunc; - /// This function is called each step when two shapes with types that match this collision handler are colliding. - /// It's called after the collision solver runs so that you can read back information about the collision to trigger events in your game. - cpCollisionPostSolveFunc postSolveFunc; - /// This function is called when two shapes with types that match this collision handler stop colliding. - cpCollisionSeparateFunc separateFunc; - /// This is a user definable context pointer that is passed to all of the collision handler functions. - cpDataPointer userData; -}; - -// TODO: Make timestep a parameter? - - -//MARK: Memory and Initialization - -/// Allocate a cpSpace. -CP_EXPORT cpSpace* cpSpaceAlloc(void); -/// Initialize a cpSpace. -CP_EXPORT cpSpace* cpSpaceInit(cpSpace *space); -/// Allocate and initialize a cpSpace. -CP_EXPORT cpSpace* cpSpaceNew(void); - -/// Destroy a cpSpace. -CP_EXPORT void cpSpaceDestroy(cpSpace *space); -/// Destroy and free a cpSpace. -CP_EXPORT void cpSpaceFree(cpSpace *space); - - -//MARK: Properties - -/// Number of iterations to use in the impulse solver to solve contacts and other constraints. -CP_EXPORT int cpSpaceGetIterations(const cpSpace *space); -CP_EXPORT void cpSpaceSetIterations(cpSpace *space, int iterations); - -/// Gravity to pass to rigid bodies when integrating velocity. -CP_EXPORT cpVect cpSpaceGetGravity(const cpSpace *space); -CP_EXPORT void cpSpaceSetGravity(cpSpace *space, cpVect gravity); - -/// Damping rate expressed as the fraction of velocity bodies retain each second. -/// A value of 0.9 would mean that each body's velocity will drop 10% per second. -/// The default value is 1.0, meaning no damping is applied. -/// @note This damping value is different than those of cpDampedSpring and cpDampedRotarySpring. -CP_EXPORT cpFloat cpSpaceGetDamping(const cpSpace *space); -CP_EXPORT void cpSpaceSetDamping(cpSpace *space, cpFloat damping); - -/// Speed threshold for a body to be considered idle. -/// The default value of 0 means to let the space guess a good threshold based on gravity. -CP_EXPORT cpFloat cpSpaceGetIdleSpeedThreshold(const cpSpace *space); -CP_EXPORT void cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold); - -/// Time a group of bodies must remain idle in order to fall asleep. -/// Enabling sleeping also implicitly enables the the contact graph. -/// The default value of INFINITY disables the sleeping algorithm. -CP_EXPORT cpFloat cpSpaceGetSleepTimeThreshold(const cpSpace *space); -CP_EXPORT void cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold); - -/// Amount of encouraged penetration between colliding shapes. -/// Used to reduce oscillating contacts and keep the collision cache warm. -/// Defaults to 0.1. If you have poor simulation quality, -/// increase this number as much as possible without allowing visible amounts of overlap. -CP_EXPORT cpFloat cpSpaceGetCollisionSlop(const cpSpace *space); -CP_EXPORT void cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop); - -/// Determines how fast overlapping shapes are pushed apart. -/// Expressed as a fraction of the error remaining after each second. -/// Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz. -CP_EXPORT cpFloat cpSpaceGetCollisionBias(const cpSpace *space); -CP_EXPORT void cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias); - -/// Number of frames that contact information should persist. -/// Defaults to 3. There is probably never a reason to change this value. -CP_EXPORT cpTimestamp cpSpaceGetCollisionPersistence(const cpSpace *space); -CP_EXPORT void cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence); - -/// User definable data pointer. -/// Generally this points to your game's controller or game state -/// class so you can access it when given a cpSpace reference in a callback. -CP_EXPORT cpDataPointer cpSpaceGetUserData(const cpSpace *space); -CP_EXPORT void cpSpaceSetUserData(cpSpace *space, cpDataPointer userData); - -/// The Space provided static body for a given cpSpace. -/// This is merely provided for convenience and you are not required to use it. -CP_EXPORT cpBody* cpSpaceGetStaticBody(const cpSpace *space); - -/// Returns the current (or most recent) time step used with the given space. -/// Useful from callbacks if your time step is not a compile-time global. -CP_EXPORT cpFloat cpSpaceGetCurrentTimeStep(const cpSpace *space); - -/// returns true from inside a callback when objects cannot be added/removed. -CP_EXPORT cpBool cpSpaceIsLocked(cpSpace *space); - - -//MARK: Collision Handlers - -/// Create or return the existing collision handler that is called for all collisions that are not handled by a more specific collision handler. -CP_EXPORT cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space); -/// Create or return the existing collision handler for the specified pair of collision types. -/// If wildcard handlers are used with either of the collision types, it's the responibility of the custom handler to invoke the wildcard handlers. -CP_EXPORT cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b); -/// Create or return the existing wildcard collision handler for the specified type. -CP_EXPORT cpCollisionHandler *cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type); - - -//MARK: Add/Remove objects - -/// Add a collision shape to the simulation. -/// If the shape is attached to a static body, it will be added as a static shape. -CP_EXPORT cpShape* cpSpaceAddShape(cpSpace *space, cpShape *shape); -/// Add a rigid body to the simulation. -CP_EXPORT cpBody* cpSpaceAddBody(cpSpace *space, cpBody *body); -/// Add a constraint to the simulation. -CP_EXPORT cpConstraint* cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint); - -/// Remove a collision shape from the simulation. -CP_EXPORT void cpSpaceRemoveShape(cpSpace *space, cpShape *shape); -/// Remove a rigid body from the simulation. -CP_EXPORT void cpSpaceRemoveBody(cpSpace *space, cpBody *body); -/// Remove a constraint from the simulation. -CP_EXPORT void cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint); - -/// Test if a collision shape has been added to the space. -CP_EXPORT cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape); -/// Test if a rigid body has been added to the space. -CP_EXPORT cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body); -/// Test if a constraint has been added to the space. -CP_EXPORT cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint); - -//MARK: Post-Step Callbacks - -/// Post Step callback function type. -typedef void (*cpPostStepFunc)(cpSpace *space, void *key, void *data); -/// Schedule a post-step callback to be called when cpSpaceStep() finishes. -/// You can only register one callback per unique value for @c key. -/// Returns true only if @c key has never been scheduled before. -/// It's possible to pass @c NULL for @c func if you only want to mark @c key as being used. -CP_EXPORT cpBool cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data); - - -//MARK: Queries - -// TODO: Queries and iterators should take a cpSpace parametery. -// TODO: They should also be abortable. - -/// Nearest point query callback function type. -typedef void (*cpSpacePointQueryFunc)(cpShape *shape, cpVect point, cpFloat distance, cpVect gradient, void *data); -/// Query the space at a point and call @c func for each shape found. -CP_EXPORT void cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data); -/// Query the space at a point and return the nearest shape found. Returns NULL if no shapes were found. -CP_EXPORT cpShape *cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out); - -/// Segment query callback function type. -typedef void (*cpSpaceSegmentQueryFunc)(cpShape *shape, cpVect point, cpVect normal, cpFloat alpha, void *data); -/// Perform a directed line segment query (like a raycast) against the space calling @c func for each shape intersected. -CP_EXPORT void cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data); -/// Perform a directed line segment query (like a raycast) against the space and return the first shape hit. Returns NULL if no shapes were hit. -CP_EXPORT cpShape *cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out); - -/// Rectangle Query callback function type. -typedef void (*cpSpaceBBQueryFunc)(cpShape *shape, void *data); -/// Perform a fast rectangle query on the space calling @c func for each shape found. -/// Only the shape's bounding boxes are checked for overlap, not their full shape. -CP_EXPORT void cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data); - -/// Shape query callback function type. -typedef void (*cpSpaceShapeQueryFunc)(cpShape *shape, cpContactPointSet *points, void *data); -/// Query a space for any shapes overlapping the given shape and call @c func for each shape found. -CP_EXPORT cpBool cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data); - - -//MARK: Iteration - -/// Space/body iterator callback function type. -typedef void (*cpSpaceBodyIteratorFunc)(cpBody *body, void *data); -/// Call @c func for each body in the space. -CP_EXPORT void cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data); - -/// Space/body iterator callback function type. -typedef void (*cpSpaceShapeIteratorFunc)(cpShape *shape, void *data); -/// Call @c func for each shape in the space. -CP_EXPORT void cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data); - -/// Space/constraint iterator callback function type. -typedef void (*cpSpaceConstraintIteratorFunc)(cpConstraint *constraint, void *data); -/// Call @c func for each shape in the space. -CP_EXPORT void cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data); - - -//MARK: Indexing - -/// Update the collision detection info for the static shapes in the space. -CP_EXPORT void cpSpaceReindexStatic(cpSpace *space); -/// Update the collision detection data for a specific shape in the space. -CP_EXPORT void cpSpaceReindexShape(cpSpace *space, cpShape *shape); -/// Update the collision detection data for all shapes attached to a body. -CP_EXPORT void cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body); - -/// Switch the space to use a spatial has as it's spatial index. -CP_EXPORT void cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count); - - -//MARK: Time Stepping - -/// Step the space forward in time by @c dt. -CP_EXPORT void cpSpaceStep(cpSpace *space, cpFloat dt); - - -//MARK: Debug API - -#ifndef CP_SPACE_DISABLE_DEBUG_API - -/// Color type to use with the space debug drawing API. -typedef struct cpSpaceDebugColor { - float r, g, b, a; -} cpSpaceDebugColor; - -/// Callback type for a function that draws a filled, stroked circle. -typedef void (*cpSpaceDebugDrawCircleImpl)(cpVect pos, cpFloat angle, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data); -/// Callback type for a function that draws a line segment. -typedef void (*cpSpaceDebugDrawSegmentImpl)(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer data); -/// Callback type for a function that draws a thick line segment. -typedef void (*cpSpaceDebugDrawFatSegmentImpl)(cpVect a, cpVect b, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data); -/// Callback type for a function that draws a convex polygon. -typedef void (*cpSpaceDebugDrawPolygonImpl)(int count, const cpVect *verts, cpFloat radius, cpSpaceDebugColor outlineColor, cpSpaceDebugColor fillColor, cpDataPointer data); -/// Callback type for a function that draws a dot. -typedef void (*cpSpaceDebugDrawDotImpl)(cpFloat size, cpVect pos, cpSpaceDebugColor color, cpDataPointer data); -/// Callback type for a function that returns a color for a given shape. This gives you an opportunity to color shapes based on how they are used in your engine. -typedef cpSpaceDebugColor (*cpSpaceDebugDrawColorForShapeImpl)(cpShape *shape, cpDataPointer data); - -typedef enum cpSpaceDebugDrawFlags { - CP_SPACE_DEBUG_DRAW_SHAPES = 1<<0, - CP_SPACE_DEBUG_DRAW_CONSTRAINTS = 1<<1, - CP_SPACE_DEBUG_DRAW_COLLISION_POINTS = 1<<2, -} cpSpaceDebugDrawFlags; - -/// Struct used with cpSpaceDebugDraw() containing drawing callbacks and other drawing settings. -typedef struct cpSpaceDebugDrawOptions { - /// Function that will be invoked to draw circles. - cpSpaceDebugDrawCircleImpl drawCircle; - /// Function that will be invoked to draw line segments. - cpSpaceDebugDrawSegmentImpl drawSegment; - /// Function that will be invoked to draw thick line segments. - cpSpaceDebugDrawFatSegmentImpl drawFatSegment; - /// Function that will be invoked to draw convex polygons. - cpSpaceDebugDrawPolygonImpl drawPolygon; - /// Function that will be invoked to draw dots. - cpSpaceDebugDrawDotImpl drawDot; - - /// Flags that request which things to draw (collision shapes, constraints, contact points). - cpSpaceDebugDrawFlags flags; - /// Outline color passed to the drawing function. - cpSpaceDebugColor shapeOutlineColor; - /// Function that decides what fill color to draw shapes using. - cpSpaceDebugDrawColorForShapeImpl colorForShape; - /// Color passed to drawing functions for constraints. - cpSpaceDebugColor constraintColor; - /// Color passed to drawing functions for collision points. - cpSpaceDebugColor collisionPointColor; - - /// User defined context pointer passed to all of the callback functions as the 'data' argument. - cpDataPointer data; -} cpSpaceDebugDrawOptions; - -/// Debug draw the current state of the space using the supplied drawing options. -CP_EXPORT void cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options); - -#endif - -/// @} diff --git a/3rdparty/chipmunk/include/chipmunk/cpSpatialIndex.h b/3rdparty/chipmunk/include/chipmunk/cpSpatialIndex.h deleted file mode 100644 index 1f7c68ca959d..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpSpatialIndex.h +++ /dev/null @@ -1,227 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/** - @defgroup cpSpatialIndex cpSpatialIndex - - Spatial indexes are data structures that are used to accelerate collision detection - and spatial queries. Chipmunk provides a number of spatial index algorithms to pick from - and they are programmed in a generic way so that you can use them for holding more than - just cpShape structs. - - It works by using @c void pointers to the objects you add and using a callback to ask your code - for bounding boxes when it needs them. Several types of queries can be performed an index as well - as reindexing and full collision information. All communication to the spatial indexes is performed - through callback functions. - - Spatial indexes should be treated as opaque structs. - This meanns you shouldn't be reading any of the struct fields. - @{ -*/ - -//MARK: Spatial Index - -/// Spatial index bounding box callback function type. -/// The spatial index calls this function and passes you a pointer to an object you added -/// when it needs to get the bounding box associated with that object. -typedef cpBB (*cpSpatialIndexBBFunc)(void *obj); -/// Spatial index/object iterator callback function type. -typedef void (*cpSpatialIndexIteratorFunc)(void *obj, void *data); -/// Spatial query callback function type. -typedef cpCollisionID (*cpSpatialIndexQueryFunc)(void *obj1, void *obj2, cpCollisionID id, void *data); -/// Spatial segment query callback function type. -typedef cpFloat (*cpSpatialIndexSegmentQueryFunc)(void *obj1, void *obj2, void *data); - - -typedef struct cpSpatialIndexClass cpSpatialIndexClass; -typedef struct cpSpatialIndex cpSpatialIndex; - -/// @private -struct cpSpatialIndex { - cpSpatialIndexClass *klass; - - cpSpatialIndexBBFunc bbfunc; - - cpSpatialIndex *staticIndex, *dynamicIndex; -}; - - -//MARK: Spatial Hash - -typedef struct cpSpaceHash cpSpaceHash; - -/// Allocate a spatial hash. -CP_EXPORT cpSpaceHash* cpSpaceHashAlloc(void); -/// Initialize a spatial hash. -CP_EXPORT cpSpatialIndex* cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); -/// Allocate and initialize a spatial hash. -CP_EXPORT cpSpatialIndex* cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); - -/// Change the cell dimensions and table size of the spatial hash to tune it. -/// The cell dimensions should roughly match the average size of your objects -/// and the table size should be ~10 larger than the number of objects inserted. -/// Some trial and error is required to find the optimum numbers for efficiency. -CP_EXPORT void cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells); - -//MARK: AABB Tree - -typedef struct cpBBTree cpBBTree; - -/// Allocate a bounding box tree. -CP_EXPORT cpBBTree* cpBBTreeAlloc(void); -/// Initialize a bounding box tree. -CP_EXPORT cpSpatialIndex* cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); -/// Allocate and initialize a bounding box tree. -CP_EXPORT cpSpatialIndex* cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); - -/// Perform a static top down optimization of the tree. -CP_EXPORT void cpBBTreeOptimize(cpSpatialIndex *index); - -/// Bounding box tree velocity callback function. -/// This function should return an estimate for the object's velocity. -typedef cpVect (*cpBBTreeVelocityFunc)(void *obj); -/// Set the velocity function for the bounding box tree to enable temporal coherence. -CP_EXPORT void cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func); - -//MARK: Single Axis Sweep - -typedef struct cpSweep1D cpSweep1D; - -/// Allocate a 1D sort and sweep broadphase. -CP_EXPORT cpSweep1D* cpSweep1DAlloc(void); -/// Initialize a 1D sort and sweep broadphase. -CP_EXPORT cpSpatialIndex* cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); -/// Allocate and initialize a 1D sort and sweep broadphase. -CP_EXPORT cpSpatialIndex* cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex); - -//MARK: Spatial Index Implementation - -typedef void (*cpSpatialIndexDestroyImpl)(cpSpatialIndex *index); - -typedef int (*cpSpatialIndexCountImpl)(cpSpatialIndex *index); -typedef void (*cpSpatialIndexEachImpl)(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data); - -typedef cpBool (*cpSpatialIndexContainsImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid); -typedef void (*cpSpatialIndexInsertImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid); -typedef void (*cpSpatialIndexRemoveImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid); - -typedef void (*cpSpatialIndexReindexImpl)(cpSpatialIndex *index); -typedef void (*cpSpatialIndexReindexObjectImpl)(cpSpatialIndex *index, void *obj, cpHashValue hashid); -typedef void (*cpSpatialIndexReindexQueryImpl)(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data); - -typedef void (*cpSpatialIndexQueryImpl)(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data); -typedef void (*cpSpatialIndexSegmentQueryImpl)(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data); - -struct cpSpatialIndexClass { - cpSpatialIndexDestroyImpl destroy; - - cpSpatialIndexCountImpl count; - cpSpatialIndexEachImpl each; - - cpSpatialIndexContainsImpl contains; - cpSpatialIndexInsertImpl insert; - cpSpatialIndexRemoveImpl remove; - - cpSpatialIndexReindexImpl reindex; - cpSpatialIndexReindexObjectImpl reindexObject; - cpSpatialIndexReindexQueryImpl reindexQuery; - - cpSpatialIndexQueryImpl query; - cpSpatialIndexSegmentQueryImpl segmentQuery; -}; - -/// Destroy and free a spatial index. -CP_EXPORT void cpSpatialIndexFree(cpSpatialIndex *index); -/// Collide the objects in @c dynamicIndex against the objects in @c staticIndex using the query callback function. -CP_EXPORT void cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data); - -/// Destroy a spatial index. -static inline void cpSpatialIndexDestroy(cpSpatialIndex *index) -{ - if(index->klass) index->klass->destroy(index); -} - -/// Get the number of objects in the spatial index. -static inline int cpSpatialIndexCount(cpSpatialIndex *index) -{ - return index->klass->count(index); -} - -/// Iterate the objects in the spatial index. @c func will be called once for each object. -static inline void cpSpatialIndexEach(cpSpatialIndex *index, cpSpatialIndexIteratorFunc func, void *data) -{ - index->klass->each(index, func, data); -} - -/// Returns true if the spatial index contains the given object. -/// Most spatial indexes use hashed storage, so you must provide a hash value too. -static inline cpBool cpSpatialIndexContains(cpSpatialIndex *index, void *obj, cpHashValue hashid) -{ - return index->klass->contains(index, obj, hashid); -} - -/// Add an object to a spatial index. -/// Most spatial indexes use hashed storage, so you must provide a hash value too. -static inline void cpSpatialIndexInsert(cpSpatialIndex *index, void *obj, cpHashValue hashid) -{ - index->klass->insert(index, obj, hashid); -} - -/// Remove an object from a spatial index. -/// Most spatial indexes use hashed storage, so you must provide a hash value too. -static inline void cpSpatialIndexRemove(cpSpatialIndex *index, void *obj, cpHashValue hashid) -{ - index->klass->remove(index, obj, hashid); -} - -/// Perform a full reindex of a spatial index. -static inline void cpSpatialIndexReindex(cpSpatialIndex *index) -{ - index->klass->reindex(index); -} - -/// Reindex a single object in the spatial index. -static inline void cpSpatialIndexReindexObject(cpSpatialIndex *index, void *obj, cpHashValue hashid) -{ - index->klass->reindexObject(index, obj, hashid); -} - -/// Perform a rectangle query against the spatial index, calling @c func for each potential match. -static inline void cpSpatialIndexQuery(cpSpatialIndex *index, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) -{ - index->klass->query(index, obj, bb, func, data); -} - -/// Perform a segment query against the spatial index, calling @c func for each potential match. -static inline void cpSpatialIndexSegmentQuery(cpSpatialIndex *index, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data) -{ - index->klass->segmentQuery(index, obj, a, b, t_exit, func, data); -} - -/// Simultaneously reindex and find all colliding objects. -/// @c func will be called once for each potentially overlapping pair of objects found. -/// If the spatial index was initialized with a static index, it will collide it's objects against that as well. -static inline void cpSpatialIndexReindexQuery(cpSpatialIndex *index, cpSpatialIndexQueryFunc func, void *data) -{ - index->klass->reindexQuery(index, func, data); -} - -///@} diff --git a/3rdparty/chipmunk/include/chipmunk/cpTransform.h b/3rdparty/chipmunk/include/chipmunk/cpTransform.h deleted file mode 100644 index 4a6256b91564..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpTransform.h +++ /dev/null @@ -1,198 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_TRANSFORM_H -#define CHIPMUNK_TRANSFORM_H - -#include "chipmunk_types.h" -#include "cpVect.h" -#include "cpBB.h" - -/// Identity transform matrix. -static const cpTransform cpTransformIdentity = {1.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f}; - -/// Construct a new transform matrix. -/// (a, b) is the x basis vector. -/// (c, d) is the y basis vector. -/// (tx, ty) is the translation. -static inline cpTransform -cpTransformNew(cpFloat a, cpFloat b, cpFloat c, cpFloat d, cpFloat tx, cpFloat ty) -{ - cpTransform t = {a, b, c, d, tx, ty}; - return t; -} - -/// Construct a new transform matrix in transposed order. -static inline cpTransform -cpTransformNewTranspose(cpFloat a, cpFloat c, cpFloat tx, cpFloat b, cpFloat d, cpFloat ty) -{ - cpTransform t = {a, b, c, d, tx, ty}; - return t; -} - -/// Get the inverse of a transform matrix. -static inline cpTransform -cpTransformInverse(cpTransform t) -{ - cpFloat inv_det = 1.0/(t.a*t.d - t.c*t.b); - return cpTransformNewTranspose( - t.d*inv_det, -t.c*inv_det, (t.c*t.ty - t.tx*t.d)*inv_det, - -t.b*inv_det, t.a*inv_det, (t.tx*t.b - t.a*t.ty)*inv_det - ); -} - -/// Multiply two transformation matrices. -static inline cpTransform -cpTransformMult(cpTransform t1, cpTransform t2) -{ - return cpTransformNewTranspose( - t1.a*t2.a + t1.c*t2.b, t1.a*t2.c + t1.c*t2.d, t1.a*t2.tx + t1.c*t2.ty + t1.tx, - t1.b*t2.a + t1.d*t2.b, t1.b*t2.c + t1.d*t2.d, t1.b*t2.tx + t1.d*t2.ty + t1.ty - ); -} - -/// Transform an absolute point. (i.e. a vertex) -static inline cpVect -cpTransformPoint(cpTransform t, cpVect p) -{ - return cpv(t.a*p.x + t.c*p.y + t.tx, t.b*p.x + t.d*p.y + t.ty); -} - -/// Transform a vector (i.e. a normal) -static inline cpVect -cpTransformVect(cpTransform t, cpVect v) -{ - return cpv(t.a*v.x + t.c*v.y, t.b*v.x + t.d*v.y); -} - -/// Transform a cpBB. -static inline cpBB -cpTransformbBB(cpTransform t, cpBB bb) -{ - cpVect center = cpBBCenter(bb); - cpFloat hw = (bb.r - bb.l)*0.5; - cpFloat hh = (bb.t - bb.b)*0.5; - - cpFloat a = t.a*hw, b = t.c*hh, d = t.b*hw, e = t.d*hh; - cpFloat hw_max = cpfmax(cpfabs(a + b), cpfabs(a - b)); - cpFloat hh_max = cpfmax(cpfabs(d + e), cpfabs(d - e)); - return cpBBNewForExtents(cpTransformPoint(t, center), hw_max, hh_max); -} - -/// Create a transation matrix. -static inline cpTransform -cpTransformTranslate(cpVect translate) -{ - return cpTransformNewTranspose( - 1.0, 0.0, translate.x, - 0.0, 1.0, translate.y - ); -} - -/// Create a scale matrix. -static inline cpTransform -cpTransformScale(cpFloat scaleX, cpFloat scaleY) -{ - return cpTransformNewTranspose( - scaleX, 0.0, 0.0, - 0.0, scaleY, 0.0 - ); -} - -/// Create a rotation matrix. -static inline cpTransform -cpTransformRotate(cpFloat radians) -{ - cpVect rot = cpvforangle(radians); - return cpTransformNewTranspose( - rot.x, -rot.y, 0.0, - rot.y, rot.x, 0.0 - ); -} - -/// Create a rigid transformation matrix. (transation + rotation) -static inline cpTransform -cpTransformRigid(cpVect translate, cpFloat radians) -{ - cpVect rot = cpvforangle(radians); - return cpTransformNewTranspose( - rot.x, -rot.y, translate.x, - rot.y, rot.x, translate.y - ); -} - -/// Fast inverse of a rigid transformation matrix. -static inline cpTransform -cpTransformRigidInverse(cpTransform t) -{ - return cpTransformNewTranspose( - t.d, -t.c, (t.c*t.ty - t.tx*t.d), - -t.b, t.a, (t.tx*t.b - t.a*t.ty) - ); -} - -//MARK: Miscellaneous (but useful) transformation matrices. -// See source for documentation... - -static inline cpTransform -cpTransformWrap(cpTransform outer, cpTransform inner) -{ - return cpTransformMult(cpTransformInverse(outer), cpTransformMult(inner, outer)); -} - -static inline cpTransform -cpTransformWrapInverse(cpTransform outer, cpTransform inner) -{ - return cpTransformMult(outer, cpTransformMult(inner, cpTransformInverse(outer))); -} - -static inline cpTransform -cpTransformOrtho(cpBB bb) -{ - return cpTransformNewTranspose( - 2.0/(bb.r - bb.l), 0.0, -(bb.r + bb.l)/(bb.r - bb.l), - 0.0, 2.0/(bb.t - bb.b), -(bb.t + bb.b)/(bb.t - bb.b) - ); -} - -static inline cpTransform -cpTransformBoneScale(cpVect v0, cpVect v1) -{ - cpVect d = cpvsub(v1, v0); - return cpTransformNewTranspose( - d.x, -d.y, v0.x, - d.y, d.x, v0.y - ); -} - -static inline cpTransform -cpTransformAxialScale(cpVect axis, cpVect pivot, cpFloat scale) -{ - cpFloat A = axis.x*axis.y*(scale - 1.0); - cpFloat B = cpvdot(axis, pivot)*(1.0 - scale); - - return cpTransformNewTranspose( - scale*axis.x*axis.x + axis.y*axis.y, A, axis.x*B, - A, axis.x*axis.x + scale*axis.y*axis.y, axis.y*B - ); -} - -#endif diff --git a/3rdparty/chipmunk/include/chipmunk/cpVect.h b/3rdparty/chipmunk/include/chipmunk/cpVect.h deleted file mode 100644 index 8ec02bdce35c..000000000000 --- a/3rdparty/chipmunk/include/chipmunk/cpVect.h +++ /dev/null @@ -1,230 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#ifndef CHIPMUNK_VECT_H -#define CHIPMUNK_VECT_H - -#include "chipmunk_types.h" - -/// @defgroup cpVect cpVect -/// Chipmunk's 2D vector type along with a handy 2D vector math lib. -/// @{ - -/// Constant for the zero vector. -static const cpVect cpvzero = {0.0f,0.0f}; - -/// Convenience constructor for cpVect structs. -static inline cpVect cpv(const cpFloat x, const cpFloat y) -{ - cpVect v = {x, y}; - return v; -} - -/// Check if two vectors are equal. (Be careful when comparing floating point numbers!) -static inline cpBool cpveql(const cpVect v1, const cpVect v2) -{ - return (v1.x == v2.x && v1.y == v2.y); -} - -/// Add two vectors -static inline cpVect cpvadd(const cpVect v1, const cpVect v2) -{ - return cpv(v1.x + v2.x, v1.y + v2.y); -} - -/// Subtract two vectors. -static inline cpVect cpvsub(const cpVect v1, const cpVect v2) -{ - return cpv(v1.x - v2.x, v1.y - v2.y); -} - -/// Negate a vector. -static inline cpVect cpvneg(const cpVect v) -{ - return cpv(-v.x, -v.y); -} - -/// Scalar multiplication. -static inline cpVect cpvmult(const cpVect v, const cpFloat s) -{ - return cpv(v.x*s, v.y*s); -} - -/// Vector dot product. -static inline cpFloat cpvdot(const cpVect v1, const cpVect v2) -{ - return v1.x*v2.x + v1.y*v2.y; -} - -/// 2D vector cross product analog. -/// The cross product of 2D vectors results in a 3D vector with only a z component. -/// This function returns the magnitude of the z value. -static inline cpFloat cpvcross(const cpVect v1, const cpVect v2) -{ - return v1.x*v2.y - v1.y*v2.x; -} - -/// Returns a perpendicular vector. (90 degree rotation) -static inline cpVect cpvperp(const cpVect v) -{ - return cpv(-v.y, v.x); -} - -/// Returns a perpendicular vector. (-90 degree rotation) -static inline cpVect cpvrperp(const cpVect v) -{ - return cpv(v.y, -v.x); -} - -/// Returns the vector projection of v1 onto v2. -static inline cpVect cpvproject(const cpVect v1, const cpVect v2) -{ - return cpvmult(v2, cpvdot(v1, v2)/cpvdot(v2, v2)); -} - -/// Returns the unit length vector for the given angle (in radians). -static inline cpVect cpvforangle(const cpFloat a) -{ - return cpv(cpfcos(a), cpfsin(a)); -} - -/// Returns the angular direction v is pointing in (in radians). -static inline cpFloat cpvtoangle(const cpVect v) -{ - return cpfatan2(v.y, v.x); -} - -/// Uses complex number multiplication to rotate v1 by v2. Scaling will occur if v1 is not a unit vector. -static inline cpVect cpvrotate(const cpVect v1, const cpVect v2) -{ - return cpv(v1.x*v2.x - v1.y*v2.y, v1.x*v2.y + v1.y*v2.x); -} - -/// Inverse of cpvrotate(). -static inline cpVect cpvunrotate(const cpVect v1, const cpVect v2) -{ - return cpv(v1.x*v2.x + v1.y*v2.y, v1.y*v2.x - v1.x*v2.y); -} - -/// Returns the squared length of v. Faster than cpvlength() when you only need to compare lengths. -static inline cpFloat cpvlengthsq(const cpVect v) -{ - return cpvdot(v, v); -} - -/// Returns the length of v. -static inline cpFloat cpvlength(const cpVect v) -{ - return cpfsqrt(cpvdot(v, v)); -} - -/// Linearly interpolate between v1 and v2. -static inline cpVect cpvlerp(const cpVect v1, const cpVect v2, const cpFloat t) -{ - return cpvadd(cpvmult(v1, 1.0f - t), cpvmult(v2, t)); -} - -/// Returns a normalized copy of v. -static inline cpVect cpvnormalize(const cpVect v) -{ - // Neat trick I saw somewhere to avoid div/0. - return cpvmult(v, 1.0f/(cpvlength(v) + CPFLOAT_MIN)); -} - -/// Spherical linearly interpolate between v1 and v2. -static inline cpVect -cpvslerp(const cpVect v1, const cpVect v2, const cpFloat t) -{ - cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); - cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); - - if(omega < 1e-3){ - // If the angle between two vectors is very small, lerp instead to avoid precision issues. - return cpvlerp(v1, v2, t); - } else { - cpFloat denom = 1.0f/cpfsin(omega); - return cpvadd(cpvmult(v1, cpfsin((1.0f - t)*omega)*denom), cpvmult(v2, cpfsin(t*omega)*denom)); - } -} - -/// Spherical linearly interpolate between v1 towards v2 by no more than angle a radians -static inline cpVect -cpvslerpconst(const cpVect v1, const cpVect v2, const cpFloat a) -{ - cpFloat dot = cpvdot(cpvnormalize(v1), cpvnormalize(v2)); - cpFloat omega = cpfacos(cpfclamp(dot, -1.0f, 1.0f)); - - return cpvslerp(v1, v2, cpfmin(a, omega)/omega); -} - -/// Clamp v to length len. -static inline cpVect cpvclamp(const cpVect v, const cpFloat len) -{ - return (cpvdot(v,v) > len*len) ? cpvmult(cpvnormalize(v), len) : v; -} - -/// Linearly interpolate between v1 towards v2 by distance d. -static inline cpVect cpvlerpconst(cpVect v1, cpVect v2, cpFloat d) -{ - return cpvadd(v1, cpvclamp(cpvsub(v2, v1), d)); -} - -/// Returns the distance between v1 and v2. -static inline cpFloat cpvdist(const cpVect v1, const cpVect v2) -{ - return cpvlength(cpvsub(v1, v2)); -} - -/// Returns the squared distance between v1 and v2. Faster than cpvdist() when you only need to compare distances. -static inline cpFloat cpvdistsq(const cpVect v1, const cpVect v2) -{ - return cpvlengthsq(cpvsub(v1, v2)); -} - -/// Returns true if the distance between v1 and v2 is less than dist. -static inline cpBool cpvnear(const cpVect v1, const cpVect v2, const cpFloat dist) -{ - return cpvdistsq(v1, v2) < dist*dist; -} - -/// @} - -/// @defgroup cpMat2x2 cpMat2x2 -/// 2x2 matrix type used for tensors and such. -/// @{ - -// NUKE -static inline cpMat2x2 -cpMat2x2New(cpFloat a, cpFloat b, cpFloat c, cpFloat d) -{ - cpMat2x2 m = {a, b, c, d}; - return m; -} - -static inline cpVect -cpMat2x2Transform(cpMat2x2 m, cpVect v) -{ - return cpv(v.x*m.a + v.y*m.b, v.x*m.c + v.y*m.d); -} - -///@} - -#endif diff --git a/3rdparty/chipmunk/src/CMakeLists.txt b/3rdparty/chipmunk/src/CMakeLists.txt deleted file mode 100644 index 2dcf316b9010..000000000000 --- a/3rdparty/chipmunk/src/CMakeLists.txt +++ /dev/null @@ -1,59 +0,0 @@ -file(GLOB chipmunk_source_files "*.c") -file(GLOB chipmunk_public_header "${chipmunk_SOURCE_DIR}/include/chipmunk/*.h") - -include_directories(${chipmunk_SOURCE_DIR}/include) - -# Chipmunk2D 7.0.3 -set(CHIPMUNK_VERSION_MAJOR 7) -set(CHIPMUNK_VERSION_MINOR 0) -set(CHIPMUNK_VERSION_PATCH 3) -set(CHIPMUNK_VERSION "${CHIPMUNK_VERSION_MAJOR}.${CHIPMUNK_VERSION_MINOR}.${CHIPMUNK_VERSION_PATCH}") -message(STATUS "Configuring Chipmunk2D version ${CHIPMUNK_VERSION}") - - -if(CP_BUILD_SHARED) - add_library(chipmunk SHARED - ${chipmunk_source_files} - ) - # Tell MSVC to compile the code as C++. - if(MSVC) - set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX) - set_target_properties(chipmunk PROPERTIES LINKER_LANGUAGE CXX) - endif(MSVC) - # set the lib's version number - # But avoid on Android because symlinks to version numbered .so's don't work with Android's Java-side loadLibrary. - if(NOT ANDROID) - set_target_properties(chipmunk PROPERTIES - SOVERSION ${CHIPMUNK_VERSION_MAJOR} - VERSION ${CHIPMUNK_VERSION}) - endif(NOT ANDROID) - if(ANDROID OR UNIX) - # need to explicitly link to the math library because the CMake/Android toolchains may not do it automatically - target_link_libraries(chipmunk m) - endif(ANDROID OR UNIX) - install(TARGETS chipmunk RUNTIME DESTINATION ${BIN_INSTALL_DIR} - LIBRARY DESTINATION ${LIB_INSTALL_DIR} - ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) -endif(CP_BUILD_SHARED) - -if(CP_BUILD_STATIC) - add_library(chipmunk STATIC - ${chipmunk_source_files} - ) - # Tell MSVC to compile the code as C++. - if(MSVC) - set_source_files_properties(${chipmunk_source_files} PROPERTIES LANGUAGE CXX) - set_target_properties(chipmunk PROPERTIES LINKER_LANGUAGE CXX) - endif(MSVC) - # Sets chipmunk to output "libchipmunk.a" not "libchipmunk.a" - set_target_properties(chipmunk PROPERTIES OUTPUT_NAME chipmunk) - if(CP_INSTALL_STATIC) - install(TARGETS chipmunk ARCHIVE DESTINATION ${LIB_INSTALL_DIR}) - endif(CP_INSTALL_STATIC) -endif(CP_BUILD_STATIC) - -if(CP_BUILD_SHARED OR CP_INSTALL_STATIC) - # FIXME: change to PUBLIC_HEADER to allow building frameworks - install(FILES ${chipmunk_public_header} DESTINATION include/chipmunk) - install(FILES ${chipmunk_constraint_header} DESTINATION include/chipmunk/constraints) -endif(CP_BUILD_SHARED OR CP_INSTALL_STATIC) diff --git a/3rdparty/chipmunk/src/chipmunk.c b/3rdparty/chipmunk/src/chipmunk.c deleted file mode 100644 index a6cc9d6d4d16..000000000000 --- a/3rdparty/chipmunk/src/chipmunk.c +++ /dev/null @@ -1,331 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include -#include -#if defined(ANDROID) -# include -#endif - -#include "chipmunk/chipmunk_private.h" - -void -cpMessage(const char *condition, const char *file, int line, int isError, int isHardError, const char *message, ...) -{ - fprintf(stderr, (isError ? "Aborting due to Chipmunk error: " : "Chipmunk warning: ")); - - va_list vargs; - va_start(vargs, message); { -#if defined(ANDROID) - __android_log_print( ANDROID_LOG_INFO, "Chipmunk", "%s(%d)", file, line ); - __android_log_print( ANDROID_LOG_INFO, "Chipmunk", message, vargs ); -#else - vfprintf(stderr, message, vargs); - fprintf(stderr, "\n"); -#endif - } va_end(vargs); - -#if defined(ANDROID) - __android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tFailed condition: %s\n", condition); - __android_log_print(ANDROID_LOG_INFO, "Chipmunk", "\tSource:%s:%d\n", file, line); -#else - fprintf(stderr, "\tFailed condition: %s\n", condition); - fprintf(stderr, "\tSource:%s:%d\n", file, line); -#endif -} - -#define STR(s) #s -#define XSTR(s) STR(s) - -const char *cpVersionString = XSTR(CP_VERSION_MAJOR) "." XSTR(CP_VERSION_MINOR) "." XSTR(CP_VERSION_RELEASE); - -//MARK: Misc Functions - -cpFloat -cpMomentForCircle(cpFloat m, cpFloat r1, cpFloat r2, cpVect offset) -{ - return m*(0.5f*(r1*r1 + r2*r2) + cpvlengthsq(offset)); -} - -cpFloat -cpAreaForCircle(cpFloat r1, cpFloat r2) -{ - return (cpFloat)CP_PI*cpfabs(r1*r1 - r2*r2); -} - -cpFloat -cpMomentForSegment(cpFloat m, cpVect a, cpVect b, cpFloat r) -{ - cpVect offset = cpvlerp(a, b, 0.5f); - - // This approximates the shape as a box for rounded segments, but it's quite close. - cpFloat length = cpvdist(b, a) + 2.0f*r; - return m*((length*length + 4.0f*r*r)/12.0f + cpvlengthsq(offset)); -} - -cpFloat -cpAreaForSegment(cpVect a, cpVect b, cpFloat r) -{ - return r*((cpFloat)CP_PI*r + 2.0f*cpvdist(a, b)); -} - -cpFloat -cpMomentForPoly(cpFloat m, int count, const cpVect *verts, cpVect offset, cpFloat r) -{ - // TODO account for radius. - if(count == 2) return cpMomentForSegment(m, verts[0], verts[1], 0.0f); - - cpFloat sum1 = 0.0f; - cpFloat sum2 = 0.0f; - for(int i=0; i max.x || (v.x == max.x && v.y > max.y)){ - max = v; - (*end) = i; - } - } -} - -#define SWAP(__A__, __B__) {cpVect __TMP__ = __A__; __A__ = __B__; __B__ = __TMP__;} - -static int -QHullPartition(cpVect *verts, int count, cpVect a, cpVect b, cpFloat tol) -{ - if(count == 0) return 0; - - cpFloat max = 0; - int pivot = 0; - - cpVect delta = cpvsub(b, a); - cpFloat valueTol = tol*cpvlength(delta); - - int head = 0; - for(int tail = count-1; head <= tail;){ - cpFloat value = cpvcross(cpvsub(verts[head], a), delta); - if(value > valueTol){ - if(value > max){ - max = value; - pivot = head; - } - - head++; - } else { - SWAP(verts[head], verts[tail]); - tail--; - } - } - - // move the new pivot to the front if it's not already there. - if(pivot != 0) SWAP(verts[0], verts[pivot]); - return head; -} - -static int -QHullReduce(cpFloat tol, cpVect *verts, int count, cpVect a, cpVect pivot, cpVect b, cpVect *result) -{ - if(count < 0){ - return 0; - } else if(count == 0) { - result[0] = pivot; - return 1; - } else { - int left_count = QHullPartition(verts, count, a, pivot, tol); - int index = QHullReduce(tol, verts + 1, left_count - 1, a, verts[0], pivot, result); - - result[index++] = pivot; - - int right_count = QHullPartition(verts + left_count, count - left_count, pivot, b, tol); - return index + QHullReduce(tol, verts + left_count + 1, right_count - 1, pivot, verts[left_count], b, result + index); - } -} - -// QuickHull seemed like a neat algorithm, and efficient-ish for large input sets. -// My implementation performs an in place reduction using the result array as scratch space. -int -cpConvexHull(int count, const cpVect *verts, cpVect *result, int *first, cpFloat tol) -{ - if(verts != result){ - // Copy the line vertexes into the empty part of the result polyline to use as a scratch buffer. - memcpy(result, verts, count*sizeof(cpVect)); - } - - // Degenerate case, all points are the same. - int start, end; - cpLoopIndexes(verts, count, &start, &end); - if(start == end){ - if(first) (*first) = 0; - return 1; - } - - SWAP(result[0], result[start]); - SWAP(result[1], result[end == 0 ? start : end]); - - cpVect a = result[0]; - cpVect b = result[1]; - - if(first) (*first) = start; - return QHullReduce(tol, result + 2, count - 2, a, b, a, result + 1) + 1; -} - -//MARK: Alternate Block Iterators - -#if defined(__has_extension) -#if __has_extension(blocks) - -static void IteratorFunc(void *ptr, void (^block)(void *ptr)){block(ptr);} - -void cpSpaceEachBody_b(cpSpace *space, void (^block)(cpBody *body)){ - cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)IteratorFunc, block); -} - -void cpSpaceEachShape_b(cpSpace *space, void (^block)(cpShape *shape)){ - cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)IteratorFunc, block); -} - -void cpSpaceEachConstraint_b(cpSpace *space, void (^block)(cpConstraint *constraint)){ - cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)IteratorFunc, block); -} - -static void BodyIteratorFunc(cpBody *body, void *ptr, void (^block)(void *ptr)){block(ptr);} - -void cpBodyEachShape_b(cpBody *body, void (^block)(cpShape *shape)){ - cpBodyEachShape(body, (cpBodyShapeIteratorFunc)BodyIteratorFunc, block); -} - -void cpBodyEachConstraint_b(cpBody *body, void (^block)(cpConstraint *constraint)){ - cpBodyEachConstraint(body, (cpBodyConstraintIteratorFunc)BodyIteratorFunc, block); -} - -void cpBodyEachArbiter_b(cpBody *body, void (^block)(cpArbiter *arbiter)){ - cpBodyEachArbiter(body, (cpBodyArbiterIteratorFunc)BodyIteratorFunc, block); -} - -static void PointQueryIteratorFunc(cpShape *shape, cpVect p, cpFloat d, cpVect g, cpSpacePointQueryBlock block){block(shape, p, d, g);} -void cpSpacePointQuery_b(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryBlock block){ - cpSpacePointQuery(space, point, maxDistance, filter, (cpSpacePointQueryFunc)PointQueryIteratorFunc, block); -} - -static void SegmentQueryIteratorFunc(cpShape *shape, cpVect p, cpVect n, cpFloat t, cpSpaceSegmentQueryBlock block){block(shape, p, n, t);} -void cpSpaceSegmentQuery_b(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryBlock block){ - cpSpaceSegmentQuery(space, start, end, radius, filter, (cpSpaceSegmentQueryFunc)SegmentQueryIteratorFunc, block); -} - -void cpSpaceBBQuery_b(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryBlock block){ - cpSpaceBBQuery(space, bb, filter, (cpSpaceBBQueryFunc)IteratorFunc, block); -} - -static void ShapeQueryIteratorFunc(cpShape *shape, cpContactPointSet *points, cpSpaceShapeQueryBlock block){block(shape, points);} -cpBool cpSpaceShapeQuery_b(cpSpace *space, cpShape *shape, cpSpaceShapeQueryBlock block){ - return cpSpaceShapeQuery(space, shape, (cpSpaceShapeQueryFunc)ShapeQueryIteratorFunc, block); -} - -#endif -#endif - -#include "chipmunk/chipmunk_ffi.h" diff --git a/3rdparty/chipmunk/src/cpArbiter.c b/3rdparty/chipmunk/src/cpArbiter.c deleted file mode 100644 index 5248e6aaec08..000000000000 --- a/3rdparty/chipmunk/src/cpArbiter.c +++ /dev/null @@ -1,498 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -// TODO: make this generic so I can reuse it for constraints also. -static inline void -unthreadHelper(cpArbiter *arb, cpBody *body) -{ - struct cpArbiterThread *thread = cpArbiterThreadForBody(arb, body); - cpArbiter *prev = thread->prev; - cpArbiter *next = thread->next; - - if(prev){ - cpArbiterThreadForBody(prev, body)->next = next; - } else if(body->arbiterList == arb) { - // IFF prev is NULL and body->arbiterList == arb, is arb at the head of the list. - // This function may be called for an arbiter that was never in a list. - // In that case, we need to protect it from wiping out the body->arbiterList pointer. - body->arbiterList = next; - } - - if(next) cpArbiterThreadForBody(next, body)->prev = prev; - - thread->prev = NULL; - thread->next = NULL; -} - -void -cpArbiterUnthread(cpArbiter *arb) -{ - unthreadHelper(arb, arb->body_a); - unthreadHelper(arb, arb->body_b); -} - -cpBool cpArbiterIsFirstContact(const cpArbiter *arb) -{ - return arb->state == CP_ARBITER_STATE_FIRST_COLLISION; -} - -cpBool cpArbiterIsRemoval(const cpArbiter *arb) -{ - return arb->state == CP_ARBITER_STATE_INVALIDATED; -} - -int cpArbiterGetCount(const cpArbiter *arb) -{ - // Return 0 contacts if we are in a separate callback. - return (arb->state < CP_ARBITER_STATE_CACHED ? arb->count : 0); -} - -cpVect -cpArbiterGetNormal(const cpArbiter *arb) -{ - return cpvmult(arb->n, arb->swapped ? -1.0f : 1.0); -} - -cpVect -cpArbiterGetPointA(const cpArbiter *arb, int i) -{ - cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter"); - return cpvadd(arb->body_a->p, arb->contacts[i].r1); -} - -cpVect -cpArbiterGetPointB(const cpArbiter *arb, int i) -{ - cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter"); - return cpvadd(arb->body_b->p, arb->contacts[i].r2); -} - -cpFloat -cpArbiterGetDepth(const cpArbiter *arb, int i) -{ - cpAssertHard(0 <= i && i < cpArbiterGetCount(arb), "Index error: The specified contact index is invalid for this arbiter"); - - struct cpContact *con = &arb->contacts[i]; - return cpvdot(cpvadd(cpvsub(con->r2, con->r1), cpvsub(arb->body_b->p, arb->body_a->p)), arb->n); -} - -cpContactPointSet -cpArbiterGetContactPointSet(const cpArbiter *arb) -{ - cpContactPointSet set; - set.count = cpArbiterGetCount(arb); - - cpBool swapped = arb->swapped; - cpVect n = arb->n; - set.normal = (swapped ? cpvneg(n) : n); - - for(int i=0; ibody_a->p, arb->contacts[i].r1); - cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[i].r2); - - set.points[i].pointA = (swapped ? p2 : p1); - set.points[i].pointB = (swapped ? p1 : p2); - set.points[i].distance = cpvdot(cpvsub(p2, p1), n); - } - - return set; -} - -void -cpArbiterSetContactPointSet(cpArbiter *arb, cpContactPointSet *set) -{ - int count = set->count; - cpAssertHard(count == arb->count, "The number of contact points cannot be changed."); - - cpBool swapped = arb->swapped; - arb->n = (swapped ? cpvneg(set->normal) : set->normal); - - for(int i=0; ipoints[i].pointA; - cpVect p2 = set->points[i].pointB; - - arb->contacts[i].r1 = cpvsub(swapped ? p2 : p1, arb->body_a->p); - arb->contacts[i].r2 = cpvsub(swapped ? p1 : p2, arb->body_b->p); - } -} - -cpVect -cpArbiterTotalImpulse(const cpArbiter *arb) -{ - struct cpContact *contacts = arb->contacts; - cpVect n = arb->n; - cpVect sum = cpvzero; - - for(int i=0, count=cpArbiterGetCount(arb); ijnAcc, con->jtAcc))); - } - - return (arb->swapped ? sum : cpvneg(sum)); - return cpvzero; -} - -cpFloat -cpArbiterTotalKE(const cpArbiter *arb) -{ - cpFloat eCoef = (1 - arb->e)/(1 + arb->e); - cpFloat sum = 0.0; - - struct cpContact *contacts = arb->contacts; - for(int i=0, count=cpArbiterGetCount(arb); ijnAcc; - cpFloat jtAcc = con->jtAcc; - - sum += eCoef*jnAcc*jnAcc/con->nMass + jtAcc*jtAcc/con->tMass; - } - - return sum; -} - -cpBool -cpArbiterIgnore(cpArbiter *arb) -{ - arb->state = CP_ARBITER_STATE_IGNORE; - return cpFalse; -} - -cpFloat -cpArbiterGetRestitution(const cpArbiter *arb) -{ - return arb->e; -} - -void -cpArbiterSetRestitution(cpArbiter *arb, cpFloat restitution) -{ - arb->e = restitution; -} - -cpFloat -cpArbiterGetFriction(const cpArbiter *arb) -{ - return arb->u; -} - -void -cpArbiterSetFriction(cpArbiter *arb, cpFloat friction) -{ - arb->u = friction; -} - -cpVect -cpArbiterGetSurfaceVelocity(cpArbiter *arb) -{ - return cpvmult(arb->surface_vr, arb->swapped ? -1.0f : 1.0); -} - -void -cpArbiterSetSurfaceVelocity(cpArbiter *arb, cpVect vr) -{ - arb->surface_vr = cpvmult(vr, arb->swapped ? -1.0f : 1.0); -} - -cpDataPointer -cpArbiterGetUserData(const cpArbiter *arb) -{ - return arb->data; -} - -void -cpArbiterSetUserData(cpArbiter *arb, cpDataPointer userData) -{ - arb->data = userData; -} - -void -cpArbiterGetShapes(const cpArbiter *arb, cpShape **a, cpShape **b) -{ - if(arb->swapped){ - (*a) = (cpShape *)arb->b; - (*b) = (cpShape *)arb->a; - } else { - (*a) = (cpShape *)arb->a; - (*b) = (cpShape *)arb->b; - } -} - -void cpArbiterGetBodies(const cpArbiter *arb, cpBody **a, cpBody **b) -{ - CP_ARBITER_GET_SHAPES(arb, shape_a, shape_b); - (*a) = shape_a->body; - (*b) = shape_b->body; -} - -cpBool -cpArbiterCallWildcardBeginA(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerA; - return handler->beginFunc(arb, space, handler->userData); -} - -cpBool -cpArbiterCallWildcardBeginB(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerB; - arb->swapped = !arb->swapped; - cpBool retval = handler->beginFunc(arb, space, handler->userData); - arb->swapped = !arb->swapped; - return retval; -} - -cpBool -cpArbiterCallWildcardPreSolveA(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerA; - return handler->preSolveFunc(arb, space, handler->userData); -} - -cpBool -cpArbiterCallWildcardPreSolveB(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerB; - arb->swapped = !arb->swapped; - cpBool retval = handler->preSolveFunc(arb, space, handler->userData); - arb->swapped = !arb->swapped; - return retval; -} - -void -cpArbiterCallWildcardPostSolveA(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerA; - handler->postSolveFunc(arb, space, handler->userData); -} - -void -cpArbiterCallWildcardPostSolveB(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerB; - arb->swapped = !arb->swapped; - handler->postSolveFunc(arb, space, handler->userData); - arb->swapped = !arb->swapped; -} - -void -cpArbiterCallWildcardSeparateA(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerA; - handler->separateFunc(arb, space, handler->userData); -} - -void -cpArbiterCallWildcardSeparateB(cpArbiter *arb, cpSpace *space) -{ - cpCollisionHandler *handler = arb->handlerB; - arb->swapped = !arb->swapped; - handler->separateFunc(arb, space, handler->userData); - arb->swapped = !arb->swapped; -} - -cpArbiter* -cpArbiterInit(cpArbiter *arb, cpShape *a, cpShape *b) -{ - arb->handler = NULL; - arb->swapped = cpFalse; - - arb->handler = NULL; - arb->handlerA = NULL; - arb->handlerB = NULL; - - arb->e = 0.0f; - arb->u = 0.0f; - arb->surface_vr = cpvzero; - - arb->count = 0; - arb->contacts = NULL; - - arb->a = a; arb->body_a = a->body; - arb->b = b; arb->body_b = b->body; - - arb->thread_a.next = NULL; - arb->thread_b.next = NULL; - arb->thread_a.prev = NULL; - arb->thread_b.prev = NULL; - - arb->stamp = 0; - arb->state = CP_ARBITER_STATE_FIRST_COLLISION; - - arb->data = NULL; - - return arb; -} - -static inline cpCollisionHandler * -cpSpaceLookupHandler(cpSpace *space, cpCollisionType a, cpCollisionType b, cpCollisionHandler *defaultValue) -{ - cpCollisionType types[] = {a, b}; - cpCollisionHandler *handler = (cpCollisionHandler *)cpHashSetFind(space->collisionHandlers, CP_HASH_PAIR(a, b), types); - return (handler ? handler : defaultValue); -} - -void -cpArbiterUpdate(cpArbiter *arb, struct cpCollisionInfo *info, cpSpace *space) -{ - const cpShape *a = info->a, *b = info->b; - - // For collisions between two similar primitive types, the order could have been swapped since the last frame. - arb->a = a; arb->body_a = a->body; - arb->b = b; arb->body_b = b->body; - - // Iterate over the possible pairs to look for hash value matches. - for(int i=0; icount; i++){ - struct cpContact *con = &info->arr[i]; - - // r1 and r2 store absolute offsets at init time. - // Need to convert them to relative offsets. - con->r1 = cpvsub(con->r1, a->body->p); - con->r2 = cpvsub(con->r2, b->body->p); - - // Cached impulses are not zeroed at init time. - con->jnAcc = con->jtAcc = 0.0f; - - for(int j=0; jcount; j++){ - struct cpContact *old = &arb->contacts[j]; - - // This could trigger false positives, but is fairly unlikely nor serious if it does. - if(con->hash == old->hash){ - // Copy the persistant contact information. - con->jnAcc = old->jnAcc; - con->jtAcc = old->jtAcc; - } - } - } - - arb->contacts = info->arr; - arb->count = info->count; - arb->n = info->n; - - arb->e = a->e * b->e; - arb->u = a->u * b->u; - - cpVect surface_vr = cpvsub(b->surfaceV, a->surfaceV); - arb->surface_vr = cpvsub(surface_vr, cpvmult(info->n, cpvdot(surface_vr, info->n))); - - cpCollisionType typeA = info->a->type, typeB = info->b->type; - cpCollisionHandler *defaultHandler = &space->defaultHandler; - cpCollisionHandler *handler = arb->handler = cpSpaceLookupHandler(space, typeA, typeB, defaultHandler); - - // Check if the types match, but don't swap for a default handler which use the wildcard for type A. - cpBool swapped = arb->swapped = (typeA != handler->typeA && handler->typeA != CP_WILDCARD_COLLISION_TYPE); - - if(handler != defaultHandler || space->usesWildcards){ - // The order of the main handler swaps the wildcard handlers too. Uffda. - arb->handlerA = cpSpaceLookupHandler(space, (swapped ? typeB : typeA), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing); - arb->handlerB = cpSpaceLookupHandler(space, (swapped ? typeA : typeB), CP_WILDCARD_COLLISION_TYPE, &cpCollisionHandlerDoNothing); - } - - // mark it as new if it's been cached - if(arb->state == CP_ARBITER_STATE_CACHED) arb->state = CP_ARBITER_STATE_FIRST_COLLISION; -} - -void -cpArbiterPreStep(cpArbiter *arb, cpFloat dt, cpFloat slop, cpFloat bias) -{ - cpBody *a = arb->body_a; - cpBody *b = arb->body_b; - cpVect n = arb->n; - cpVect body_delta = cpvsub(b->p, a->p); - - for(int i=0; icount; i++){ - struct cpContact *con = &arb->contacts[i]; - - // Calculate the mass normal and mass tangent. - con->nMass = 1.0f/k_scalar(a, b, con->r1, con->r2, n); - con->tMass = 1.0f/k_scalar(a, b, con->r1, con->r2, cpvperp(n)); - - // Calculate the target bias velocity. - cpFloat dist = cpvdot(cpvadd(cpvsub(con->r2, con->r1), body_delta), n); - con->bias = -bias*cpfmin(0.0f, dist + slop)/dt; - con->jBias = 0.0f; - - // Calculate the target bounce velocity. - con->bounce = normal_relative_velocity(a, b, con->r1, con->r2, n)*arb->e; - } -} - -void -cpArbiterApplyCachedImpulse(cpArbiter *arb, cpFloat dt_coef) -{ - if(cpArbiterIsFirstContact(arb)) return; - - cpBody *a = arb->body_a; - cpBody *b = arb->body_b; - cpVect n = arb->n; - - for(int i=0; icount; i++){ - struct cpContact *con = &arb->contacts[i]; - cpVect j = cpvrotate(n, cpv(con->jnAcc, con->jtAcc)); - apply_impulses(a, b, con->r1, con->r2, cpvmult(j, dt_coef)); - } -} - -// TODO: is it worth splitting velocity/position correction? - -void -cpArbiterApplyImpulse(cpArbiter *arb) -{ - cpBody *a = arb->body_a; - cpBody *b = arb->body_b; - cpVect n = arb->n; - cpVect surface_vr = arb->surface_vr; - cpFloat friction = arb->u; - - for(int i=0; icount; i++){ - struct cpContact *con = &arb->contacts[i]; - cpFloat nMass = con->nMass; - cpVect r1 = con->r1; - cpVect r2 = con->r2; - - cpVect vb1 = cpvadd(a->v_bias, cpvmult(cpvperp(r1), a->w_bias)); - cpVect vb2 = cpvadd(b->v_bias, cpvmult(cpvperp(r2), b->w_bias)); - cpVect vr = cpvadd(relative_velocity(a, b, r1, r2), surface_vr); - - cpFloat vbn = cpvdot(cpvsub(vb2, vb1), n); - cpFloat vrn = cpvdot(vr, n); - cpFloat vrt = cpvdot(vr, cpvperp(n)); - - cpFloat jbn = (con->bias - vbn)*nMass; - cpFloat jbnOld = con->jBias; - con->jBias = cpfmax(jbnOld + jbn, 0.0f); - - cpFloat jn = -(con->bounce + vrn)*nMass; - cpFloat jnOld = con->jnAcc; - con->jnAcc = cpfmax(jnOld + jn, 0.0f); - - cpFloat jtMax = friction*con->jnAcc; - cpFloat jt = -vrt*con->tMass; - cpFloat jtOld = con->jtAcc; - con->jtAcc = cpfclamp(jtOld + jt, -jtMax, jtMax); - - apply_bias_impulses(a, b, r1, r2, cpvmult(n, con->jBias - jbnOld)); - apply_impulses(a, b, r1, r2, cpvrotate(n, cpv(con->jnAcc - jnOld, con->jtAcc - jtOld))); - } -} diff --git a/3rdparty/chipmunk/src/cpArray.c b/3rdparty/chipmunk/src/cpArray.c deleted file mode 100644 index a1f8df526fc4..000000000000 --- a/3rdparty/chipmunk/src/cpArray.c +++ /dev/null @@ -1,101 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "chipmunk/chipmunk_private.h" - - -cpArray * -cpArrayNew(int size) -{ - cpArray *arr = (cpArray *)cpcalloc(1, sizeof(cpArray)); - - arr->num = 0; - arr->max = (size ? size : 4); - arr->arr = (void **)cpcalloc(arr->max, sizeof(void*)); - - return arr; -} - -void -cpArrayFree(cpArray *arr) -{ - if(arr){ - cpfree(arr->arr); - arr->arr = NULL; - - cpfree(arr); - } -} - -void -cpArrayPush(cpArray *arr, void *object) -{ - if(arr->num == arr->max){ - arr->max = 3*(arr->max + 1)/2; - arr->arr = (void **)cprealloc(arr->arr, arr->max*sizeof(void*)); - } - - arr->arr[arr->num] = object; - arr->num++; -} - -void * -cpArrayPop(cpArray *arr) -{ - arr->num--; - - void *value = arr->arr[arr->num]; - arr->arr[arr->num] = NULL; - - return value; -} - -void -cpArrayDeleteObj(cpArray *arr, void *obj) -{ - for(int i=0; inum; i++){ - if(arr->arr[i] == obj){ - arr->num--; - - arr->arr[i] = arr->arr[arr->num]; - arr->arr[arr->num] = NULL; - - return; - } - } -} - -void -cpArrayFreeEach(cpArray *arr, void (freeFunc)(void*)) -{ - for(int i=0; inum; i++) freeFunc(arr->arr[i]); -} - -cpBool -cpArrayContains(cpArray *arr, void *ptr) -{ - for(int i=0; inum; i++) - if(arr->arr[i] == ptr) return cpTrue; - - return cpFalse; -} diff --git a/3rdparty/chipmunk/src/cpBBTree.c b/3rdparty/chipmunk/src/cpBBTree.c deleted file mode 100644 index 2cef7bc755c8..000000000000 --- a/3rdparty/chipmunk/src/cpBBTree.c +++ /dev/null @@ -1,896 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "stdlib.h" -#include "stdio.h" - -#include "chipmunk/chipmunk_private.h" - -static inline cpSpatialIndexClass *Klass(void); - -typedef struct Node Node; -typedef struct Pair Pair; - -struct cpBBTree { - cpSpatialIndex spatialIndex; - cpBBTreeVelocityFunc velocityFunc; - - cpHashSet *leaves; - Node *root; - - Node *pooledNodes; - Pair *pooledPairs; - cpArray *allocatedBuffers; - - cpTimestamp stamp; -}; - -struct Node { - void *obj; - cpBB bb; - Node *parent; - - union { - // Internal nodes - struct { Node *a, *b; } children; - - // Leaves - struct { - cpTimestamp stamp; - Pair *pairs; - } leaf; - } node; -}; - -// Can't use anonymous unions and still get good x-compiler compatability -#define A node.children.a -#define B node.children.b -#define STAMP node.leaf.stamp -#define PAIRS node.leaf.pairs - -typedef struct Thread { - Pair *prev; - Node *leaf; - Pair *next; -} Thread; - -struct Pair { - Thread a, b; - cpCollisionID id; -}; - -//MARK: Misc Functions - -static inline cpBB -GetBB(cpBBTree *tree, void *obj) -{ - cpBB bb = tree->spatialIndex.bbfunc(obj); - - cpBBTreeVelocityFunc velocityFunc = tree->velocityFunc; - if(velocityFunc){ - cpFloat coef = 0.1f; - cpFloat x = (bb.r - bb.l)*coef; - cpFloat y = (bb.t - bb.b)*coef; - - cpVect v = cpvmult(velocityFunc(obj), 0.1f); - return cpBBNew(bb.l + cpfmin(-x, v.x), bb.b + cpfmin(-y, v.y), bb.r + cpfmax(x, v.x), bb.t + cpfmax(y, v.y)); - } else { - return bb; - } -} - -static inline cpBBTree * -GetTree(cpSpatialIndex *index) -{ - return (index && index->klass == Klass() ? (cpBBTree *)index : NULL); -} - -static inline Node * -GetRootIfTree(cpSpatialIndex *index){ - return (index && index->klass == Klass() ? ((cpBBTree *)index)->root : NULL); -} - -static inline cpBBTree * -GetMasterTree(cpBBTree *tree) -{ - cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex); - return (dynamicTree ? dynamicTree : tree); -} - -static inline void -IncrementStamp(cpBBTree *tree) -{ - cpBBTree *dynamicTree = GetTree(tree->spatialIndex.dynamicIndex); - if(dynamicTree){ - dynamicTree->stamp++; - } else { - tree->stamp++; - } -} - -//MARK: Pair/Thread Functions - -static void -PairRecycle(cpBBTree *tree, Pair *pair) -{ - // Share the pool of the master tree. - // TODO: would be lovely to move the pairs stuff into an external data structure. - tree = GetMasterTree(tree); - - pair->a.next = tree->pooledPairs; - tree->pooledPairs = pair; -} - -static Pair * -PairFromPool(cpBBTree *tree) -{ - // Share the pool of the master tree. - // TODO: would be lovely to move the pairs stuff into an external data structure. - tree = GetMasterTree(tree); - - Pair *pair = tree->pooledPairs; - - if(pair){ - tree->pooledPairs = pair->a.next; - return pair; - } else { - // Pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(Pair); - cpAssertHard(count, "Internal Error: Buffer size is too small."); - - Pair *buffer = (Pair *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(tree->allocatedBuffers, buffer); - - // push all but the first one, return the first instead - for(int i=1; ia.leaf == thread.leaf) next->a.prev = prev; else next->b.prev = prev; - } - - if(prev){ - if(prev->a.leaf == thread.leaf) prev->a.next = next; else prev->b.next = next; - } else { - thread.leaf->PAIRS = next; - } -} - -static void -PairsClear(Node *leaf, cpBBTree *tree) -{ - Pair *pair = leaf->PAIRS; - leaf->PAIRS = NULL; - - while(pair){ - if(pair->a.leaf == leaf){ - Pair *next = pair->a.next; - ThreadUnlink(pair->b); - PairRecycle(tree, pair); - pair = next; - } else { - Pair *next = pair->b.next; - ThreadUnlink(pair->a); - PairRecycle(tree, pair); - pair = next; - } - } -} - -static void -PairInsert(Node *a, Node *b, cpBBTree *tree) -{ - Pair *nextA = a->PAIRS, *nextB = b->PAIRS; - Pair *pair = PairFromPool(tree); - Pair temp = {{NULL, a, nextA},{NULL, b, nextB}, 0}; - - a->PAIRS = b->PAIRS = pair; - *pair = temp; - - if(nextA){ - if(nextA->a.leaf == a) nextA->a.prev = pair; else nextA->b.prev = pair; - } - - if(nextB){ - if(nextB->a.leaf == b) nextB->a.prev = pair; else nextB->b.prev = pair; - } -} - - -//MARK: Node Functions - -static void -NodeRecycle(cpBBTree *tree, Node *node) -{ - node->parent = tree->pooledNodes; - tree->pooledNodes = node; -} - -static Node * -NodeFromPool(cpBBTree *tree) -{ - Node *node = tree->pooledNodes; - - if(node){ - tree->pooledNodes = node->parent; - return node; - } else { - // Pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(Node); - cpAssertHard(count, "Internal Error: Buffer size is too small."); - - Node *buffer = (Node *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(tree->allocatedBuffers, buffer); - - // push all but the first one, return the first instead - for(int i=1; iA = value; - value->parent = node; -} - -static inline void -NodeSetB(Node *node, Node *value) -{ - node->B = value; - value->parent = node; -} - -static Node * -NodeNew(cpBBTree *tree, Node *a, Node *b) -{ - Node *node = NodeFromPool(tree); - - node->obj = NULL; - node->bb = cpBBMerge(a->bb, b->bb); - node->parent = NULL; - - NodeSetA(node, a); - NodeSetB(node, b); - - return node; -} - -static inline cpBool -NodeIsLeaf(Node *node) -{ - return (node->obj != NULL); -} - -static inline Node * -NodeOther(Node *node, Node *child) -{ - return (node->A == child ? node->B : node->A); -} - -static inline void -NodeReplaceChild(Node *parent, Node *child, Node *value, cpBBTree *tree) -{ - cpAssertSoft(!NodeIsLeaf(parent), "Internal Error: Cannot replace child of a leaf."); - cpAssertSoft(child == parent->A || child == parent->B, "Internal Error: Node is not a child of parent."); - - if(parent->A == child){ - NodeRecycle(tree, parent->A); - NodeSetA(parent, value); - } else { - NodeRecycle(tree, parent->B); - NodeSetB(parent, value); - } - - for(Node *node=parent; node; node = node->parent){ - node->bb = cpBBMerge(node->A->bb, node->B->bb); - } -} - -//MARK: Subtree Functions - -static inline cpFloat -cpBBProximity(cpBB a, cpBB b) -{ - return cpfabs(a.l + a.r - b.l - b.r) + cpfabs(a.b + a.t - b.b - b.t); -} - -static Node * -SubtreeInsert(Node *subtree, Node *leaf, cpBBTree *tree) -{ - if(subtree == NULL){ - return leaf; - } else if(NodeIsLeaf(subtree)){ - return NodeNew(tree, leaf, subtree); - } else { - cpFloat cost_a = cpBBArea(subtree->B->bb) + cpBBMergedArea(subtree->A->bb, leaf->bb); - cpFloat cost_b = cpBBArea(subtree->A->bb) + cpBBMergedArea(subtree->B->bb, leaf->bb); - - if(cost_a == cost_b){ - cost_a = cpBBProximity(subtree->A->bb, leaf->bb); - cost_b = cpBBProximity(subtree->B->bb, leaf->bb); - } - - if(cost_b < cost_a){ - NodeSetB(subtree, SubtreeInsert(subtree->B, leaf, tree)); - } else { - NodeSetA(subtree, SubtreeInsert(subtree->A, leaf, tree)); - } - - subtree->bb = cpBBMerge(subtree->bb, leaf->bb); - return subtree; - } -} - -static void -SubtreeQuery(Node *subtree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) -{ - if(cpBBIntersects(subtree->bb, bb)){ - if(NodeIsLeaf(subtree)){ - func(obj, subtree->obj, 0, data); - } else { - SubtreeQuery(subtree->A, obj, bb, func, data); - SubtreeQuery(subtree->B, obj, bb, func, data); - } - } -} - - -static cpFloat -SubtreeSegmentQuery(Node *subtree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data) -{ - if(NodeIsLeaf(subtree)){ - return func(obj, subtree->obj, data); - } else { - cpFloat t_a = cpBBSegmentQuery(subtree->A->bb, a, b); - cpFloat t_b = cpBBSegmentQuery(subtree->B->bb, a, b); - - if(t_a < t_b){ - if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data)); - if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data)); - } else { - if(t_b < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->B, obj, a, b, t_exit, func, data)); - if(t_a < t_exit) t_exit = cpfmin(t_exit, SubtreeSegmentQuery(subtree->A, obj, a, b, t_exit, func, data)); - } - - return t_exit; - } -} - -static void -SubtreeRecycle(cpBBTree *tree, Node *node) -{ - if(!NodeIsLeaf(node)){ - SubtreeRecycle(tree, node->A); - SubtreeRecycle(tree, node->B); - NodeRecycle(tree, node); - } -} - -static inline Node * -SubtreeRemove(Node *subtree, Node *leaf, cpBBTree *tree) -{ - if(leaf == subtree){ - return NULL; - } else { - Node *parent = leaf->parent; - if(parent == subtree){ - Node *other = NodeOther(subtree, leaf); - other->parent = subtree->parent; - NodeRecycle(tree, subtree); - return other; - } else { - NodeReplaceChild(parent->parent, parent, NodeOther(parent, leaf), tree); - return subtree; - } - } -} - -//MARK: Marking Functions - -typedef struct MarkContext { - cpBBTree *tree; - Node *staticRoot; - cpSpatialIndexQueryFunc func; - void *data; -} MarkContext; - -static void -MarkLeafQuery(Node *subtree, Node *leaf, cpBool left, MarkContext *context) -{ - if(cpBBIntersects(leaf->bb, subtree->bb)){ - if(NodeIsLeaf(subtree)){ - if(left){ - PairInsert(leaf, subtree, context->tree); - } else { - if(subtree->STAMP < leaf->STAMP) PairInsert(subtree, leaf, context->tree); - context->func(leaf->obj, subtree->obj, 0, context->data); - } - } else { - MarkLeafQuery(subtree->A, leaf, left, context); - MarkLeafQuery(subtree->B, leaf, left, context); - } - } -} - -static void -MarkLeaf(Node *leaf, MarkContext *context) -{ - cpBBTree *tree = context->tree; - if(leaf->STAMP == GetMasterTree(tree)->stamp){ - Node *staticRoot = context->staticRoot; - if(staticRoot) MarkLeafQuery(staticRoot, leaf, cpFalse, context); - - for(Node *node = leaf; node->parent; node = node->parent){ - if(node == node->parent->A){ - MarkLeafQuery(node->parent->B, leaf, cpTrue, context); - } else { - MarkLeafQuery(node->parent->A, leaf, cpFalse, context); - } - } - } else { - Pair *pair = leaf->PAIRS; - while(pair){ - if(leaf == pair->b.leaf){ - pair->id = context->func(pair->a.leaf->obj, leaf->obj, pair->id, context->data); - pair = pair->b.next; - } else { - pair = pair->a.next; - } - } - } -} - -static void -MarkSubtree(Node *subtree, MarkContext *context) -{ - if(NodeIsLeaf(subtree)){ - MarkLeaf(subtree, context); - } else { - MarkSubtree(subtree->A, context); - MarkSubtree(subtree->B, context); // TODO: Force TCO here? - } -} - -//MARK: Leaf Functions - -static Node * -LeafNew(cpBBTree *tree, void *obj, cpBB bb) -{ - Node *node = NodeFromPool(tree); - node->obj = obj; - node->bb = GetBB(tree, obj); - - node->parent = NULL; - node->STAMP = 0; - node->PAIRS = NULL; - - return node; -} - -static cpBool -LeafUpdate(Node *leaf, cpBBTree *tree) -{ - Node *root = tree->root; - cpBB bb = tree->spatialIndex.bbfunc(leaf->obj); - - if(!cpBBContainsBB(leaf->bb, bb)){ - leaf->bb = GetBB(tree, leaf->obj); - - root = SubtreeRemove(root, leaf, tree); - tree->root = SubtreeInsert(root, leaf, tree); - - PairsClear(leaf, tree); - leaf->STAMP = GetMasterTree(tree)->stamp; - - return cpTrue; - } else { - return cpFalse; - } -} - -static cpCollisionID VoidQueryFunc(void *obj1, void *obj2, cpCollisionID id, void *data){return id;} - -static void -LeafAddPairs(Node *leaf, cpBBTree *tree) -{ - cpSpatialIndex *dynamicIndex = tree->spatialIndex.dynamicIndex; - if(dynamicIndex){ - Node *dynamicRoot = GetRootIfTree(dynamicIndex); - if(dynamicRoot){ - cpBBTree *dynamicTree = GetTree(dynamicIndex); - MarkContext context = {dynamicTree, NULL, NULL, NULL}; - MarkLeafQuery(dynamicRoot, leaf, cpTrue, &context); - } - } else { - Node *staticRoot = GetRootIfTree(tree->spatialIndex.staticIndex); - MarkContext context = {tree, staticRoot, VoidQueryFunc, NULL}; - MarkLeaf(leaf, &context); - } -} - -//MARK: Memory Management Functions - -cpBBTree * -cpBBTreeAlloc(void) -{ - return (cpBBTree *)cpcalloc(1, sizeof(cpBBTree)); -} - -static int -leafSetEql(void *obj, Node *node) -{ - return (obj == node->obj); -} - -static void * -leafSetTrans(void *obj, cpBBTree *tree) -{ - return LeafNew(tree, obj, tree->spatialIndex.bbfunc(obj)); -} - -cpSpatialIndex * -cpBBTreeInit(cpBBTree *tree, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - cpSpatialIndexInit((cpSpatialIndex *)tree, Klass(), bbfunc, staticIndex); - - tree->velocityFunc = NULL; - - tree->leaves = cpHashSetNew(0, (cpHashSetEqlFunc)leafSetEql); - tree->root = NULL; - - tree->pooledNodes = NULL; - tree->allocatedBuffers = cpArrayNew(0); - - tree->stamp = 0; - - return (cpSpatialIndex *)tree; -} - -void -cpBBTreeSetVelocityFunc(cpSpatialIndex *index, cpBBTreeVelocityFunc func) -{ - if(index->klass != Klass()){ - cpAssertWarn(cpFalse, "Ignoring cpBBTreeSetVelocityFunc() call to non-tree spatial index."); - return; - } - - ((cpBBTree *)index)->velocityFunc = func; -} - -cpSpatialIndex * -cpBBTreeNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - return cpBBTreeInit(cpBBTreeAlloc(), bbfunc, staticIndex); -} - -static void -cpBBTreeDestroy(cpBBTree *tree) -{ - cpHashSetFree(tree->leaves); - - if(tree->allocatedBuffers) cpArrayFreeEach(tree->allocatedBuffers, cpfree); - cpArrayFree(tree->allocatedBuffers); -} - -//MARK: Insert/Remove - -static void -cpBBTreeInsert(cpBBTree *tree, void *obj, cpHashValue hashid) -{ - Node *leaf = (Node *)cpHashSetInsert(tree->leaves, hashid, obj, (cpHashSetTransFunc)leafSetTrans, tree); - - Node *root = tree->root; - tree->root = SubtreeInsert(root, leaf, tree); - - leaf->STAMP = GetMasterTree(tree)->stamp; - LeafAddPairs(leaf, tree); - IncrementStamp(tree); -} - -static void -cpBBTreeRemove(cpBBTree *tree, void *obj, cpHashValue hashid) -{ - Node *leaf = (Node *)cpHashSetRemove(tree->leaves, hashid, obj); - - tree->root = SubtreeRemove(tree->root, leaf, tree); - PairsClear(leaf, tree); - NodeRecycle(tree, leaf); -} - -static cpBool -cpBBTreeContains(cpBBTree *tree, void *obj, cpHashValue hashid) -{ - return (cpHashSetFind(tree->leaves, hashid, obj) != NULL); -} - -//MARK: Reindex - -static void LeafUpdateWrap(Node *leaf, cpBBTree *tree) {LeafUpdate(leaf, tree);} - -static void -cpBBTreeReindexQuery(cpBBTree *tree, cpSpatialIndexQueryFunc func, void *data) -{ - if(!tree->root) return; - - // LeafUpdate() may modify tree->root. Don't cache it. - cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)LeafUpdateWrap, tree); - - cpSpatialIndex *staticIndex = tree->spatialIndex.staticIndex; - Node *staticRoot = (staticIndex && staticIndex->klass == Klass() ? ((cpBBTree *)staticIndex)->root : NULL); - - MarkContext context = {tree, staticRoot, func, data}; - MarkSubtree(tree->root, &context); - if(staticIndex && !staticRoot) cpSpatialIndexCollideStatic((cpSpatialIndex *)tree, staticIndex, func, data); - - IncrementStamp(tree); -} - -static void -cpBBTreeReindex(cpBBTree *tree) -{ - cpBBTreeReindexQuery(tree, VoidQueryFunc, NULL); -} - -static void -cpBBTreeReindexObject(cpBBTree *tree, void *obj, cpHashValue hashid) -{ - Node *leaf = (Node *)cpHashSetFind(tree->leaves, hashid, obj); - if(leaf){ - if(LeafUpdate(leaf, tree)) LeafAddPairs(leaf, tree); - IncrementStamp(tree); - } -} - -//MARK: Query - -static void -cpBBTreeSegmentQuery(cpBBTree *tree, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data) -{ - Node *root = tree->root; - if(root) SubtreeSegmentQuery(root, obj, a, b, t_exit, func, data); -} - -static void -cpBBTreeQuery(cpBBTree *tree, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) -{ - if(tree->root) SubtreeQuery(tree->root, obj, bb, func, data); -} - -//MARK: Misc - -static int -cpBBTreeCount(cpBBTree *tree) -{ - return cpHashSetCount(tree->leaves); -} - -typedef struct eachContext { - cpSpatialIndexIteratorFunc func; - void *data; -} eachContext; - -static void each_helper(Node *node, eachContext *context){context->func(node->obj, context->data);} - -static void -cpBBTreeEach(cpBBTree *tree, cpSpatialIndexIteratorFunc func, void *data) -{ - eachContext context = {func, data}; - cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)each_helper, &context); -} - -static cpSpatialIndexClass klass = { - (cpSpatialIndexDestroyImpl)cpBBTreeDestroy, - - (cpSpatialIndexCountImpl)cpBBTreeCount, - (cpSpatialIndexEachImpl)cpBBTreeEach, - - (cpSpatialIndexContainsImpl)cpBBTreeContains, - (cpSpatialIndexInsertImpl)cpBBTreeInsert, - (cpSpatialIndexRemoveImpl)cpBBTreeRemove, - - (cpSpatialIndexReindexImpl)cpBBTreeReindex, - (cpSpatialIndexReindexObjectImpl)cpBBTreeReindexObject, - (cpSpatialIndexReindexQueryImpl)cpBBTreeReindexQuery, - - (cpSpatialIndexQueryImpl)cpBBTreeQuery, - (cpSpatialIndexSegmentQueryImpl)cpBBTreeSegmentQuery, -}; - -static inline cpSpatialIndexClass *Klass(){return &klass;} - - -//MARK: Tree Optimization - -static int -cpfcompare(const cpFloat *a, const cpFloat *b){ - return (*a < *b ? -1 : (*b < *a ? 1 : 0)); -} - -static void -fillNodeArray(Node *node, Node ***cursor){ - (**cursor) = node; - (*cursor)++; -} - -static Node * -partitionNodes(cpBBTree *tree, Node **nodes, int count) -{ - if(count == 1){ - return nodes[0]; - } else if(count == 2) { - return NodeNew(tree, nodes[0], nodes[1]); - } - - // Find the AABB for these nodes - cpBB bb = nodes[0]->bb; - for(int i=1; ibb); - - // Split it on it's longest axis - cpBool splitWidth = (bb.r - bb.l > bb.t - bb.b); - - // Sort the bounds and use the median as the splitting point - cpFloat *bounds = (cpFloat *)cpcalloc(count*2, sizeof(cpFloat)); - if(splitWidth){ - for(int i=0; ibb.l; - bounds[2*i + 1] = nodes[i]->bb.r; - } - } else { - for(int i=0; ibb.b; - bounds[2*i + 1] = nodes[i]->bb.t; - } - } - - qsort(bounds, count*2, sizeof(cpFloat), (int (*)(const void *, const void *))cpfcompare); - cpFloat split = (bounds[count - 1] + bounds[count])*0.5f; // use the medain as the split - cpfree(bounds); - - // Generate the child BBs - cpBB a = bb, b = bb; - if(splitWidth) a.r = b.l = split; else a.t = b.b = split; - - // Partition the nodes - int right = count; - for(int left=0; left < right;){ - Node *node = nodes[left]; - if(cpBBMergedArea(node->bb, b) < cpBBMergedArea(node->bb, a)){ -// if(cpBBProximity(node->bb, b) < cpBBProximity(node->bb, a)){ - right--; - nodes[left] = nodes[right]; - nodes[right] = node; - } else { - left++; - } - } - - if(right == count){ - Node *node = NULL; - for(int i=0; iroot; -// Node *node = root; -// int bit = 0; -// unsigned int path = tree->opath; -// -// while(!NodeIsLeaf(node)){ -// node = (path&(1<a : node->b); -// bit = (bit + 1)&(sizeof(unsigned int)*8 - 1); -// } -// -// root = subtreeRemove(root, node, tree); -// tree->root = subtreeInsert(root, node, tree); -// } -//} - -void -cpBBTreeOptimize(cpSpatialIndex *index) -{ - if(index->klass != &klass){ - cpAssertWarn(cpFalse, "Ignoring cpBBTreeOptimize() call to non-tree spatial index."); - return; - } - - cpBBTree *tree = (cpBBTree *)index; - Node *root = tree->root; - if(!root) return; - - int count = cpBBTreeCount(tree); - Node **nodes = (Node **)cpcalloc(count, sizeof(Node *)); - Node **cursor = nodes; - - cpHashSetEach(tree->leaves, (cpHashSetIteratorFunc)fillNodeArray, &cursor); - - SubtreeRecycle(tree, root); - tree->root = partitionNodes(tree, nodes, count); - cpfree(nodes); -} - -//MARK: Debug Draw - -//#define CP_BBTREE_DEBUG_DRAW -#ifdef CP_BBTREE_DEBUG_DRAW -#include "OpenGL/gl.h" -#include "OpenGL/glu.h" -#include - -static void -NodeRender(Node *node, int depth) -{ - if(!NodeIsLeaf(node) && depth <= 10){ - NodeRender(node->a, depth + 1); - NodeRender(node->b, depth + 1); - } - - cpBB bb = node->bb; - -// GLfloat v = depth/2.0f; -// glColor3f(1.0f - v, v, 0.0f); - glLineWidth(cpfmax(5.0f - depth, 1.0f)); - glBegin(GL_LINES); { - glVertex2f(bb.l, bb.b); - glVertex2f(bb.l, bb.t); - - glVertex2f(bb.l, bb.t); - glVertex2f(bb.r, bb.t); - - glVertex2f(bb.r, bb.t); - glVertex2f(bb.r, bb.b); - - glVertex2f(bb.r, bb.b); - glVertex2f(bb.l, bb.b); - }; glEnd(); -} - -void -cpBBTreeRenderDebug(cpSpatialIndex *index){ - if(index->klass != &klass){ - cpAssertWarn(cpFalse, "Ignoring cpBBTreeRenderDebug() call to non-tree spatial index."); - return; - } - - cpBBTree *tree = (cpBBTree *)index; - if(tree->root) NodeRender(tree->root, 0); -} -#endif diff --git a/3rdparty/chipmunk/src/cpBody.c b/3rdparty/chipmunk/src/cpBody.c deleted file mode 100644 index 4ba4b494ec52..000000000000 --- a/3rdparty/chipmunk/src/cpBody.c +++ /dev/null @@ -1,626 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "chipmunk/chipmunk_private.h" - -cpBody* -cpBodyAlloc(void) -{ - return (cpBody *)cpcalloc(1, sizeof(cpBody)); -} - -cpBody * -cpBodyInit(cpBody *body, cpFloat mass, cpFloat moment) -{ - body->space = NULL; - body->shapeList = NULL; - body->arbiterList = NULL; - body->constraintList = NULL; - - body->velocity_func = cpBodyUpdateVelocity; - body->position_func = cpBodyUpdatePosition; - - body->sleeping.root = NULL; - body->sleeping.next = NULL; - body->sleeping.idleTime = 0.0f; - - body->p = cpvzero; - body->v = cpvzero; - body->f = cpvzero; - - body->w = 0.0f; - body->t = 0.0f; - - body->v_bias = cpvzero; - body->w_bias = 0.0f; - - body->userData = NULL; - - // Setters must be called after full initialization so the sanity checks don't assert on garbage data. - cpBodySetMass(body, mass); - cpBodySetMoment(body, moment); - cpBodySetAngle(body, 0.0f); - - return body; -} - -cpBody* -cpBodyNew(cpFloat mass, cpFloat moment) -{ - return cpBodyInit(cpBodyAlloc(), mass, moment); -} - -cpBody* -cpBodyNewKinematic() -{ - cpBody *body = cpBodyNew(0.0f, 0.0f); - cpBodySetType(body, CP_BODY_TYPE_KINEMATIC); - - return body; -} - -cpBody* -cpBodyNewStatic() -{ - cpBody *body = cpBodyNew(0.0f, 0.0f); - cpBodySetType(body, CP_BODY_TYPE_STATIC); - - return body; -} - -void cpBodyDestroy(cpBody *body){} - -void -cpBodyFree(cpBody *body) -{ - if(body){ - cpBodyDestroy(body); - cpfree(body); - } -} - -#ifdef NDEBUG - #define cpAssertSaneBody(body) -#else - static void cpv_assert_nan(cpVect v, const char *message){cpAssertHard(v.x == v.x && v.y == v.y, message);} - static void cpv_assert_infinite(cpVect v, const char *message){cpAssertHard(cpfabs(v.x) != INFINITY && cpfabs(v.y) != INFINITY, message);} - static void cpv_assert_sane(cpVect v, const char *message){cpv_assert_nan(v, message); cpv_assert_infinite(v, message);} - - static void - cpBodySanityCheck(const cpBody *body) - { - cpAssertHard(body->m == body->m && body->m_inv == body->m_inv, "Body's mass is NaN."); - cpAssertHard(body->i == body->i && body->i_inv == body->i_inv, "Body's moment is NaN."); - cpAssertHard(body->m >= 0.0f, "Body's mass is negative."); - cpAssertHard(body->i >= 0.0f, "Body's moment is negative."); - - cpv_assert_sane(body->p, "Body's position is invalid."); - cpv_assert_sane(body->v, "Body's velocity is invalid."); - cpv_assert_sane(body->f, "Body's force is invalid."); - - cpAssertHard(body->a == body->a && cpfabs(body->a) != INFINITY, "Body's angle is invalid."); - cpAssertHard(body->w == body->w && cpfabs(body->w) != INFINITY, "Body's angular velocity is invalid."); - cpAssertHard(body->t == body->t && cpfabs(body->t) != INFINITY, "Body's torque is invalid."); - } - - #define cpAssertSaneBody(body) cpBodySanityCheck(body) -#endif - -cpBool -cpBodyIsSleeping(const cpBody *body) -{ - return (body->sleeping.root != ((cpBody*)0)); -} - -cpBodyType -cpBodyGetType(cpBody *body) -{ - if(body->sleeping.idleTime == INFINITY){ - return CP_BODY_TYPE_STATIC; - } else if(body->m == INFINITY){ - return CP_BODY_TYPE_KINEMATIC; - } else { - return CP_BODY_TYPE_DYNAMIC; - } -} - -void -cpBodySetType(cpBody *body, cpBodyType type) -{ - cpBodyType oldType = cpBodyGetType(body); - if(oldType == type) return; - - // Static bodies have their idle timers set to infinity. - // Non-static bodies should have their idle timer reset. - body->sleeping.idleTime = (type == CP_BODY_TYPE_STATIC ? INFINITY : 0.0f); - - if(type == CP_BODY_TYPE_DYNAMIC){ - body->m = body->i = 0.0f; - body->m_inv = body->i_inv = INFINITY; - - cpBodyAccumulateMassFromShapes(body); - } else { - body->m = body->i = INFINITY; - body->m_inv = body->i_inv = 0.0f; - - body->v = cpvzero; - body->w = 0.0f; - } - - // If the body is added to a space already, we'll need to update some space data structures. - cpSpace *space = cpBodyGetSpace(body); - if(space != NULL){ - cpAssertSpaceUnlocked(space); - - if(oldType == CP_BODY_TYPE_STATIC){ - // TODO This is probably not necessary -// cpBodyActivateStatic(body, NULL); - } else { - cpBodyActivate(body); - } - - // Move the bodies to the correct array. - cpArray *fromArray = cpSpaceArrayForBodyType(space, oldType); - cpArray *toArray = cpSpaceArrayForBodyType(space, type); - if(fromArray != toArray){ - cpArrayDeleteObj(fromArray, body); - cpArrayPush(toArray, body); - } - - // Move the body's shapes to the correct spatial index. - cpSpatialIndex *fromIndex = (oldType == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes); - cpSpatialIndex *toIndex = (type == CP_BODY_TYPE_STATIC ? space->staticShapes : space->dynamicShapes); - if(fromIndex != toIndex){ - CP_BODY_FOREACH_SHAPE(body, shape){ - cpSpatialIndexRemove(fromIndex, shape, shape->hashid); - cpSpatialIndexInsert(toIndex, shape, shape->hashid); - } - } - } -} - - - -// Should *only* be called when shapes with mass info are modified, added or removed. -void -cpBodyAccumulateMassFromShapes(cpBody *body) -{ - if(body == NULL || cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) return; - - // Reset the body's mass data. - body->m = body->i = 0.0f; - body->cog = cpvzero; - - // Cache the position to realign it at the end. - cpVect pos = cpBodyGetPosition(body); - - // Accumulate mass from shapes. - CP_BODY_FOREACH_SHAPE(body, shape){ - struct cpShapeMassInfo *info = &shape->massInfo; - cpFloat m = info->m; - - if(m > 0.0f){ - cpFloat msum = body->m + m; - - body->i += m*info->i + cpvdistsq(body->cog, info->cog)*(m*body->m)/msum; - body->cog = cpvlerp(body->cog, info->cog, m/msum); - body->m = msum; - } - } - - // Recalculate the inverses. - body->m_inv = 1.0f/body->m; - body->i_inv = 1.0f/body->i; - - // Realign the body since the CoG has probably moved. - cpBodySetPosition(body, pos); - cpAssertSaneBody(body); -} - -cpSpace * -cpBodyGetSpace(const cpBody *body) -{ - return body->space; -} - -cpFloat -cpBodyGetMass(const cpBody *body) -{ - return body->m; -} - -void -cpBodySetMass(cpBody *body, cpFloat mass) -{ - cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "You cannot set the mass of kinematic or static bodies."); - cpAssertHard(0.0f <= mass && mass < INFINITY, "Mass must be positive and finite."); - - cpBodyActivate(body); - body->m = mass; - body->m_inv = mass == 0.0f ? INFINITY : 1.0f/mass; - cpAssertSaneBody(body); -} - -cpFloat -cpBodyGetMoment(const cpBody *body) -{ - return body->i; -} - -void -cpBodySetMoment(cpBody *body, cpFloat moment) -{ - cpAssertHard(moment >= 0.0f, "Moment of Inertia must be positive."); - - cpBodyActivate(body); - body->i = moment; - body->i_inv = moment == 0.0f ? INFINITY : 1.0f/moment; - cpAssertSaneBody(body); -} - -cpVect -cpBodyGetRotation(const cpBody *body) -{ - return cpv(body->transform.a, body->transform.b); -} - -void -cpBodyAddShape(cpBody *body, cpShape *shape) -{ - cpShape *next = body->shapeList; - if(next) next->prev = shape; - - shape->next = next; - body->shapeList = shape; - - if(shape->massInfo.m > 0.0f){ - cpBodyAccumulateMassFromShapes(body); - } -} - -void -cpBodyRemoveShape(cpBody *body, cpShape *shape) -{ - cpShape *prev = shape->prev; - cpShape *next = shape->next; - - if(prev){ - prev->next = next; - } else { - body->shapeList = next; - } - - if(next){ - next->prev = prev; - } - - shape->prev = NULL; - shape->next = NULL; - - if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC && shape->massInfo.m > 0.0f){ - cpBodyAccumulateMassFromShapes(body); - } -} - -static cpConstraint * -filterConstraints(cpConstraint *node, cpBody *body, cpConstraint *filter) -{ - if(node == filter){ - return cpConstraintNext(node, body); - } else if(node->a == body){ - node->next_a = filterConstraints(node->next_a, body, filter); - } else { - node->next_b = filterConstraints(node->next_b, body, filter); - } - - return node; -} - -void -cpBodyRemoveConstraint(cpBody *body, cpConstraint *constraint) -{ - body->constraintList = filterConstraints(body->constraintList, body, constraint); -} - -// 'p' is the position of the CoG -static void -SetTransform(cpBody *body, cpVect p, cpFloat a) -{ - cpVect rot = cpvforangle(a); - cpVect c = body->cog; - - body->transform = cpTransformNewTranspose( - rot.x, -rot.y, p.x - (c.x*rot.x - c.y*rot.y), - rot.y, rot.x, p.y - (c.x*rot.y + c.y*rot.x) - ); -} - -static inline cpFloat -SetAngle(cpBody *body, cpFloat a) -{ - body->a = a; - cpAssertSaneBody(body); - - return a; -} - -cpVect -cpBodyGetPosition(const cpBody *body) -{ - return cpTransformPoint(body->transform, cpvzero); -} - -void -cpBodySetPosition(cpBody *body, cpVect position) -{ - cpBodyActivate(body); - cpVect p = body->p = cpvadd(cpTransformVect(body->transform, body->cog), position); - cpAssertSaneBody(body); - - SetTransform(body, p, body->a); -} - -cpVect -cpBodyGetCenterOfGravity(const cpBody *body) -{ - return body->cog; -} - -void -cpBodySetCenterOfGravity(cpBody *body, cpVect cog) -{ - cpBodyActivate(body); - body->cog = cog; - cpAssertSaneBody(body); -} - -cpVect -cpBodyGetVelocity(const cpBody *body) -{ - return body->v; -} - -void -cpBodySetVelocity(cpBody *body, cpVect velocity) -{ - cpBodyActivate(body); - body->v = velocity; - cpAssertSaneBody(body); -} - -cpVect -cpBodyGetForce(const cpBody *body) -{ - return body->f; -} - -void -cpBodySetForce(cpBody *body, cpVect force) -{ - cpBodyActivate(body); - body->f = force; - cpAssertSaneBody(body); -} - -cpFloat -cpBodyGetAngle(const cpBody *body) -{ - return body->a; -} - -void -cpBodySetAngle(cpBody *body, cpFloat angle) -{ - cpBodyActivate(body); - SetAngle(body, angle); - - SetTransform(body, body->p, angle); -} - -cpFloat -cpBodyGetAngularVelocity(const cpBody *body) -{ - return body->w; -} - -void -cpBodySetAngularVelocity(cpBody *body, cpFloat angularVelocity) -{ - cpBodyActivate(body); - body->w = angularVelocity; - cpAssertSaneBody(body); -} - -cpFloat -cpBodyGetTorque(const cpBody *body) -{ - return body->t; -} - -void -cpBodySetTorque(cpBody *body, cpFloat torque) -{ - cpBodyActivate(body); - body->t = torque; - cpAssertSaneBody(body); -} - -cpDataPointer -cpBodyGetUserData(const cpBody *body) -{ - return body->userData; -} - -void -cpBodySetUserData(cpBody *body, cpDataPointer userData) -{ - body->userData = userData; -} - -void -cpBodySetVelocityUpdateFunc(cpBody *body, cpBodyVelocityFunc velocityFunc) -{ - body->velocity_func = velocityFunc; -} - -void -cpBodySetPositionUpdateFunc(cpBody *body, cpBodyPositionFunc positionFunc) -{ - body->position_func = positionFunc; -} - -void -cpBodyUpdateVelocity(cpBody *body, cpVect gravity, cpFloat damping, cpFloat dt) -{ - // Skip kinematic bodies. - if(cpBodyGetType(body) == CP_BODY_TYPE_KINEMATIC) return; - - cpAssertSoft(body->m > 0.0f && body->i > 0.0f, "Body's mass and moment must be positive to simulate. (Mass: %f Moment: %f)", body->m, body->i); - - body->v = cpvadd(cpvmult(body->v, damping), cpvmult(cpvadd(gravity, cpvmult(body->f, body->m_inv)), dt)); - body->w = body->w*damping + body->t*body->i_inv*dt; - - // Reset forces. - body->f = cpvzero; - body->t = 0.0f; - - cpAssertSaneBody(body); -} - -void -cpBodyUpdatePosition(cpBody *body, cpFloat dt) -{ - cpVect p = body->p = cpvadd(body->p, cpvmult(cpvadd(body->v, body->v_bias), dt)); - cpFloat a = SetAngle(body, body->a + (body->w + body->w_bias)*dt); - SetTransform(body, p, a); - - body->v_bias = cpvzero; - body->w_bias = 0.0f; - - cpAssertSaneBody(body); -} - -cpVect -cpBodyLocalToWorld(const cpBody *body, const cpVect point) -{ - return cpTransformPoint(body->transform, point); -} - -cpVect -cpBodyWorldToLocal(const cpBody *body, const cpVect point) -{ - return cpTransformPoint(cpTransformRigidInverse(body->transform), point); -} - -void -cpBodyApplyForceAtWorldPoint(cpBody *body, cpVect force, cpVect point) -{ - cpBodyActivate(body); - body->f = cpvadd(body->f, force); - - cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog)); - body->t += cpvcross(r, force); -} - -void -cpBodyApplyForceAtLocalPoint(cpBody *body, cpVect force, cpVect point) -{ - cpBodyApplyForceAtWorldPoint(body, cpTransformVect(body->transform, force), cpTransformPoint(body->transform, point)); -} - -void -cpBodyApplyImpulseAtWorldPoint(cpBody *body, cpVect impulse, cpVect point) -{ - cpBodyActivate(body); - - cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog)); - apply_impulse(body, impulse, r); -} - -void -cpBodyApplyImpulseAtLocalPoint(cpBody *body, cpVect impulse, cpVect point) -{ - cpBodyApplyImpulseAtWorldPoint(body, cpTransformVect(body->transform, impulse), cpTransformPoint(body->transform, point)); -} - -cpVect -cpBodyGetVelocityAtLocalPoint(const cpBody *body, cpVect point) -{ - cpVect r = cpTransformVect(body->transform, cpvsub(point, body->cog)); - return cpvadd(body->v, cpvmult(cpvperp(r), body->w)); -} - -cpVect -cpBodyGetVelocityAtWorldPoint(const cpBody *body, cpVect point) -{ - cpVect r = cpvsub(point, cpTransformPoint(body->transform, body->cog)); - return cpvadd(body->v, cpvmult(cpvperp(r), body->w)); -} - -cpFloat -cpBodyKineticEnergy(const cpBody *body) -{ - // Need to do some fudging to avoid NaNs - cpFloat vsq = cpvdot(body->v, body->v); - cpFloat wsq = body->w*body->w; - return (vsq ? vsq*body->m : 0.0f) + (wsq ? wsq*body->i : 0.0f); -} - -void -cpBodyEachShape(cpBody *body, cpBodyShapeIteratorFunc func, void *data) -{ - cpShape *shape = body->shapeList; - while(shape){ - cpShape *next = shape->next; - func(body, shape, data); - shape = next; - } -} - -void -cpBodyEachConstraint(cpBody *body, cpBodyConstraintIteratorFunc func, void *data) -{ - cpConstraint *constraint = body->constraintList; - while(constraint){ - cpConstraint *next = cpConstraintNext(constraint, body); - func(body, constraint, data); - constraint = next; - } -} - -void -cpBodyEachArbiter(cpBody *body, cpBodyArbiterIteratorFunc func, void *data) -{ - cpArbiter *arb = body->arbiterList; - while(arb){ - cpArbiter *next = cpArbiterNext(arb, body); - - cpBool swapped = arb->swapped; { - arb->swapped = (body == arb->body_b); - func(body, arb, data); - } arb->swapped = swapped; - - arb = next; - } -} diff --git a/3rdparty/chipmunk/src/cpCollision.c b/3rdparty/chipmunk/src/cpCollision.c deleted file mode 100644 index 33b3f59917db..000000000000 --- a/3rdparty/chipmunk/src/cpCollision.c +++ /dev/null @@ -1,726 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/cpRobust.h" - -#if DEBUG && 0 -#include "ChipmunkDemo.h" -#define DRAW_ALL 0 -#define DRAW_GJK (0 || DRAW_ALL) -#define DRAW_EPA (0 || DRAW_ALL) -#define DRAW_CLOSEST (0 || DRAW_ALL) -#define DRAW_CLIP (0 || DRAW_ALL) - -#define PRINT_LOG 0 -#endif - -#define MAX_GJK_ITERATIONS 30 -#define MAX_EPA_ITERATIONS 30 -#define WARN_GJK_ITERATIONS 20 -#define WARN_EPA_ITERATIONS 20 - -static inline void -cpCollisionInfoPushContact(struct cpCollisionInfo *info, cpVect p1, cpVect p2, cpHashValue hash) -{ - cpAssertSoft(info->count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal error: Tried to push too many contacts."); - - struct cpContact *con = &info->arr[info->count]; - con->r1 = p1; - con->r2 = p2; - con->hash = hash; - - info->count++; -} - -//MARK: Support Points and Edges: - -// Support points are the maximal points on a shape's perimeter along a certain axis. -// The GJK and EPA algorithms use support points to iteratively sample the surface of the two shapes' minkowski difference. - -static inline int -PolySupportPointIndex(const int count, const struct cpSplittingPlane *planes, const cpVect n) -{ - cpFloat max = -INFINITY; - int index = 0; - - for(int i=0; i max){ - max = d; - index = i; - } - } - - return index; -} - -struct SupportPoint { - cpVect p; - // Save an index of the point so it can be cheaply looked up as a starting point for the next frame. - cpCollisionID index; -}; - -static inline struct SupportPoint -SupportPointNew(cpVect p, cpCollisionID index) -{ - struct SupportPoint point = {p, index}; - return point; -} - -typedef struct SupportPoint (*SupportPointFunc)(const cpShape *shape, const cpVect n); - -static inline struct SupportPoint -CircleSupportPoint(const cpCircleShape *circle, const cpVect n) -{ - return SupportPointNew(circle->tc, 0); -} - -static inline struct SupportPoint -SegmentSupportPoint(const cpSegmentShape *seg, const cpVect n) -{ - if(cpvdot(seg->ta, n) > cpvdot(seg->tb, n)){ - return SupportPointNew(seg->ta, 0); - } else { - return SupportPointNew(seg->tb, 1); - } -} - -static inline struct SupportPoint -PolySupportPoint(const cpPolyShape *poly, const cpVect n) -{ - const struct cpSplittingPlane *planes = poly->planes; - int i = PolySupportPointIndex(poly->count, planes, n); - return SupportPointNew(planes[i].v0, i); -} - -// A point on the surface of two shape's minkowski difference. -struct MinkowskiPoint { - // Cache the two original support points. - cpVect a, b; - // b - a - cpVect ab; - // Concatenate the two support point indexes. - cpCollisionID id; -}; - -static inline struct MinkowskiPoint -MinkowskiPointNew(const struct SupportPoint a, const struct SupportPoint b) -{ - struct MinkowskiPoint point = {a.p, b.p, cpvsub(b.p, a.p), (a.index & 0xFF)<<8 | (b.index & 0xFF)}; - return point; -} - -struct SupportContext { - const cpShape *shape1, *shape2; - SupportPointFunc func1, func2; -}; - -// Calculate the maximal point on the minkowski difference of two shapes along a particular axis. -static inline struct MinkowskiPoint -Support(const struct SupportContext *ctx, const cpVect n) -{ - struct SupportPoint a = ctx->func1(ctx->shape1, cpvneg(n)); - struct SupportPoint b = ctx->func2(ctx->shape2, n); - return MinkowskiPointNew(a, b); -} - -struct EdgePoint { - cpVect p; - // Keep a hash value for Chipmunk's collision hashing mechanism. - cpHashValue hash; -}; - -// Support edges are the edges of a polygon or segment shape that are in contact. -struct Edge { - struct EdgePoint a, b; - cpFloat r; - cpVect n; -}; - -static struct Edge -SupportEdgeForPoly(const cpPolyShape *poly, const cpVect n) -{ - int count = poly->count; - int i1 = PolySupportPointIndex(poly->count, poly->planes, n); - - // TODO: get rid of mod eventually, very expensive on ARM - int i0 = (i1 - 1 + count)%count; - int i2 = (i1 + 1)%count; - - const struct cpSplittingPlane *planes = poly->planes; - cpHashValue hashid = poly->shape.hashid; - if(cpvdot(n, planes[i1].n) > cpvdot(n, planes[i2].n)){ - struct Edge edge = {{planes[i0].v0, CP_HASH_PAIR(hashid, i0)}, {planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, poly->r, planes[i1].n}; - return edge; - } else { - struct Edge edge = {{planes[i1].v0, CP_HASH_PAIR(hashid, i1)}, {planes[i2].v0, CP_HASH_PAIR(hashid, i2)}, poly->r, planes[i2].n}; - return edge; - } -} - -static struct Edge -SupportEdgeForSegment(const cpSegmentShape *seg, const cpVect n) -{ - cpHashValue hashid = seg->shape.hashid; - if(cpvdot(seg->tn, n) > 0.0){ - struct Edge edge = {{seg->ta, CP_HASH_PAIR(hashid, 0)}, {seg->tb, CP_HASH_PAIR(hashid, 1)}, seg->r, seg->tn}; - return edge; - } else { - struct Edge edge = {{seg->tb, CP_HASH_PAIR(hashid, 1)}, {seg->ta, CP_HASH_PAIR(hashid, 0)}, seg->r, cpvneg(seg->tn)}; - return edge; - } -} - -// Find the closest p(t) to (0, 0) where p(t) = a*(1-t)/2 + b*(1+t)/2 -// The range for t is [-1, 1] to avoid floating point issues if the parameters are swapped. -static inline cpFloat -ClosestT(const cpVect a, const cpVect b) -{ - cpVect delta = cpvsub(b, a); - return -cpfclamp(cpvdot(delta, cpvadd(a, b))/(cpvlengthsq(delta) + CPFLOAT_MIN), -1.0f, 1.0f); -} - -// Basically the same as cpvlerp(), except t = [-1, 1] -static inline cpVect -LerpT(const cpVect a, const cpVect b, const cpFloat t) -{ - cpFloat ht = 0.5f*t; - return cpvadd(cpvmult(a, 0.5f - ht), cpvmult(b, 0.5f + ht)); -} - -// Closest points on the surface of two shapes. -struct ClosestPoints { - // Surface points in absolute coordinates. - cpVect a, b; - // Minimum separating axis of the two shapes. - cpVect n; - // Signed distance between the points. - cpFloat d; - // Concatenation of the id's of the minkoski points. - cpCollisionID id; -}; - -// Calculate the closest points on two shapes given the closest edge on their minkowski difference to (0, 0) -static inline struct ClosestPoints -ClosestPointsNew(const struct MinkowskiPoint v0, const struct MinkowskiPoint v1) -{ - // Find the closest p(t) on the minkowski difference to (0, 0) - cpFloat t = ClosestT(v0.ab, v1.ab); - cpVect p = LerpT(v0.ab, v1.ab, t); - - // Interpolate the original support points using the same 't' value as above. - // This gives you the closest surface points in absolute coordinates. NEAT! - cpVect pa = LerpT(v0.a, v1.a, t); - cpVect pb = LerpT(v0.b, v1.b, t); - cpCollisionID id = (v0.id & 0xFFFF)<<16 | (v1.id & 0xFFFF); - - // First try calculating the MSA from the minkowski difference edge. - // This gives us a nice, accurate MSA when the surfaces are close together. - cpVect delta = cpvsub(v1.ab, v0.ab); - cpVect n = cpvnormalize(cpvrperp(delta)); - cpFloat d = cpvdot(n, p); - - if(d <= 0.0f || (-1.0f < t && t < 1.0f)){ - // If the shapes are overlapping, or we have a regular vertex/edge collision, we are done. - struct ClosestPoints points = {pa, pb, n, d, id}; - return points; - } else { - // Vertex/vertex collisions need special treatment since the MSA won't be shared with an axis of the minkowski difference. - cpFloat d2 = cpvlength(p); - cpVect n2 = cpvmult(p, 1.0f/(d2 + CPFLOAT_MIN)); - - struct ClosestPoints points = {pa, pb, n2, d2, id}; - return points; - } -} - -//MARK: EPA Functions - -static inline cpFloat -ClosestDist(const cpVect v0,const cpVect v1) -{ - return cpvlengthsq(LerpT(v0, v1, ClosestT(v0, v1))); -} - -// Recursive implementation of the EPA loop. -// Each recursion adds a point to the convex hull until it's known that we have the closest point on the surface. -static struct ClosestPoints -EPARecurse(const struct SupportContext *ctx, const int count, const struct MinkowskiPoint *hull, const int iteration) -{ - int mini = 0; - cpFloat minDist = INFINITY; - - // TODO: precalculate this when building the hull and save a step. - // Find the closest segment hull[i] and hull[i + 1] to (0, 0) - for(int j=0, i=count-1; j MAX_GJK_ITERATIONS){ - cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration); - return ClosestPointsNew(v0, v1); - } - - if(cpCheckPointGreater(v1.ab, v0.ab, cpvzero)){ - // Origin is behind axis. Flip and try again. - return GJKRecurse(ctx, v1, v0, iteration); - } else { - cpFloat t = ClosestT(v0.ab, v1.ab); - cpVect n = (-1.0f < t && t < 1.0f ? cpvperp(cpvsub(v1.ab, v0.ab)) : cpvneg(LerpT(v0.ab, v1.ab, t))); - struct MinkowskiPoint p = Support(ctx, n); - -#if DRAW_GJK - ChipmunkDebugDrawSegment(v0.ab, v1.ab, RGBAColor(1, 1, 1, 1)); - cpVect c = cpvlerp(v0.ab, v1.ab, 0.5); - ChipmunkDebugDrawSegment(c, cpvadd(c, cpvmult(cpvnormalize(n), 5.0)), RGBAColor(1, 0, 0, 1)); - - ChipmunkDebugDrawDot(5.0, p.ab, LAColor(1, 1)); -#endif - - if(cpCheckPointGreater(p.ab, v0.ab, cpvzero) && cpCheckPointGreater(v1.ab, p.ab, cpvzero)){ - // The triangle v0, p, v1 contains the origin. Use EPA to find the MSA. - cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK->EPA iterations: %d", iteration); - return EPA(ctx, v0, p, v1); - } else { - if(cpCheckAxis(v0.ab, v1.ab, p.ab, n)){ - // The edge v0, v1 that we already have is the closest to (0, 0) since p was not closer. - cpAssertWarn(iteration < WARN_GJK_ITERATIONS, "High GJK iterations: %d", iteration); - return ClosestPointsNew(v0, v1); - } else { - // p was closer to the origin than our existing edge. - // Need to figure out which existing point to drop. - if(ClosestDist(v0.ab, p.ab) < ClosestDist(p.ab, v1.ab)){ - return GJKRecurse(ctx, v0, p, iteration + 1); - } else { - return GJKRecurse(ctx, p, v1, iteration + 1); - } - } - } - } -} - -// Get a SupportPoint from a cached shape and index. -static struct SupportPoint -ShapePoint(const cpShape *shape, const int i) -{ - switch(shape->klass->type){ - case CP_CIRCLE_SHAPE: { - return SupportPointNew(((cpCircleShape *)shape)->tc, 0); - } case CP_SEGMENT_SHAPE: { - cpSegmentShape *seg = (cpSegmentShape *)shape; - return SupportPointNew(i == 0 ? seg->ta : seg->tb, i); - } case CP_POLY_SHAPE: { - cpPolyShape *poly = (cpPolyShape *)shape; - // Poly shapes may change vertex count. - int index = (i < poly->count ? i : 0); - return SupportPointNew(poly->planes[index].v0, index); - } default: { - return SupportPointNew(cpvzero, 0); - } - } -} - -// Find the closest points between two shapes using the GJK algorithm. -static struct ClosestPoints -GJK(const struct SupportContext *ctx, cpCollisionID *id) -{ -#if DRAW_GJK || DRAW_EPA - int count1 = 1; - int count2 = 1; - - switch(ctx->shape1->klass->type){ - case CP_SEGMENT_SHAPE: count1 = 2; break; - case CP_POLY_SHAPE: count1 = ((cpPolyShape *)ctx->shape1)->count; break; - default: break; - } - - switch(ctx->shape2->klass->type){ - case CP_SEGMENT_SHAPE: count1 = 2; break; - case CP_POLY_SHAPE: count2 = ((cpPolyShape *)ctx->shape2)->count; break; - default: break; - } - - - // draw the minkowski difference origin - cpVect origin = cpvzero; - ChipmunkDebugDrawDot(5.0, origin, RGBAColor(1,0,0,1)); - - int mdiffCount = count1*count2; - cpVect *mdiffVerts = alloca(mdiffCount*sizeof(cpVect)); - - for(int i=0; ishape2, j).p, ShapePoint(ctx->shape1, i).p); - mdiffVerts[i*count2 + j] = v; - ChipmunkDebugDrawDot(2.0, v, RGBAColor(1, 0, 0, 1)); - } - } - - cpVect *hullVerts = alloca(mdiffCount*sizeof(cpVect)); - int hullCount = cpConvexHull(mdiffCount, mdiffVerts, hullVerts, NULL, 0.0); - - ChipmunkDebugDrawPolygon(hullCount, hullVerts, 0.0, RGBAColor(1, 0, 0, 1), RGBAColor(1, 0, 0, 0.25)); -#endif - - struct MinkowskiPoint v0, v1; - if(*id){ - // Use the minkowski points from the last frame as a starting point using the cached indexes. - v0 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>>24)&0xFF), ShapePoint(ctx->shape2, (*id>>16)&0xFF)); - v1 = MinkowskiPointNew(ShapePoint(ctx->shape1, (*id>> 8)&0xFF), ShapePoint(ctx->shape2, (*id )&0xFF)); - } else { - // No cached indexes, use the shapes' bounding box centers as a guess for a starting axis. - cpVect axis = cpvperp(cpvsub(cpBBCenter(ctx->shape1->bb), cpBBCenter(ctx->shape2->bb))); - v0 = Support(ctx, axis); - v1 = Support(ctx, cpvneg(axis)); - } - - struct ClosestPoints points = GJKRecurse(ctx, v0, v1, 1); - *id = points.id; - return points; -} - -//MARK: Contact Clipping - -// Given two support edges, find contact point pairs on their surfaces. -static inline void -ContactPoints(const struct Edge e1, const struct Edge e2, const struct ClosestPoints points, struct cpCollisionInfo *info) -{ - cpFloat mindist = e1.r + e2.r; - if(points.d <= mindist){ -#ifdef DRAW_CLIP - ChipmunkDebugDrawFatSegment(e1.a.p, e1.b.p, e1.r, RGBAColor(0, 1, 0, 1), LAColor(0, 0)); - ChipmunkDebugDrawFatSegment(e2.a.p, e2.b.p, e2.r, RGBAColor(1, 0, 0, 1), LAColor(0, 0)); -#endif - cpVect n = info->n = points.n; - - // Distances along the axis parallel to n - cpFloat d_e1_a = cpvcross(e1.a.p, n); - cpFloat d_e1_b = cpvcross(e1.b.p, n); - cpFloat d_e2_a = cpvcross(e2.a.p, n); - cpFloat d_e2_b = cpvcross(e2.b.p, n); - - // TODO + min isn't a complete fix. - cpFloat e1_denom = 1.0f/(d_e1_b - d_e1_a + CPFLOAT_MIN); - cpFloat e2_denom = 1.0f/(d_e2_b - d_e2_a + CPFLOAT_MIN); - - // Project the endpoints of the two edges onto the opposing edge, clamping them as necessary. - // Compare the projected points to the collision normal to see if the shapes overlap there. - { - cpVect p1 = cpvadd(cpvmult(n, e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_b - d_e1_a)*e1_denom))); - cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_a - d_e2_a)*e2_denom))); - cpFloat dist = cpvdot(cpvsub(p2, p1), n); - if(dist <= 0.0f){ - cpHashValue hash_1a2b = CP_HASH_PAIR(e1.a.hash, e2.b.hash); - cpCollisionInfoPushContact(info, p1, p2, hash_1a2b); - } - }{ - cpVect p1 = cpvadd(cpvmult(n, e1.r), cpvlerp(e1.a.p, e1.b.p, cpfclamp01((d_e2_a - d_e1_a)*e1_denom))); - cpVect p2 = cpvadd(cpvmult(n, -e2.r), cpvlerp(e2.a.p, e2.b.p, cpfclamp01((d_e1_b - d_e2_a)*e2_denom))); - cpFloat dist = cpvdot(cpvsub(p2, p1), n); - if(dist <= 0.0f){ - cpHashValue hash_1b2a = CP_HASH_PAIR(e1.b.hash, e2.a.hash); - cpCollisionInfoPushContact(info, p1, p2, hash_1b2a); - } - } - } -} - -//MARK: Collision Functions - -typedef void (*CollisionFunc)(const cpShape *a, const cpShape *b, struct cpCollisionInfo *info); - -// Collide circle shapes. -static void -CircleToCircle(const cpCircleShape *c1, const cpCircleShape *c2, struct cpCollisionInfo *info) -{ - cpFloat mindist = c1->r + c2->r; - cpVect delta = cpvsub(c2->tc, c1->tc); - cpFloat distsq = cpvlengthsq(delta); - - if(distsq < mindist*mindist){ - cpFloat dist = cpfsqrt(distsq); - cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : cpv(1.0f, 0.0f)); - cpCollisionInfoPushContact(info, cpvadd(c1->tc, cpvmult(n, c1->r)), cpvadd(c2->tc, cpvmult(n, -c2->r)), 0); - } -} - -static void -CircleToSegment(const cpCircleShape *circle, const cpSegmentShape *segment, struct cpCollisionInfo *info) -{ - cpVect seg_a = segment->ta; - cpVect seg_b = segment->tb; - cpVect center = circle->tc; - - // Find the closest point on the segment to the circle. - cpVect seg_delta = cpvsub(seg_b, seg_a); - cpFloat closest_t = cpfclamp01(cpvdot(seg_delta, cpvsub(center, seg_a))/cpvlengthsq(seg_delta)); - cpVect closest = cpvadd(seg_a, cpvmult(seg_delta, closest_t)); - - // Compare the radii of the two shapes to see if they are colliding. - cpFloat mindist = circle->r + segment->r; - cpVect delta = cpvsub(closest, center); - cpFloat distsq = cpvlengthsq(delta); - if(distsq < mindist*mindist){ - cpFloat dist = cpfsqrt(distsq); - // Handle coincident shapes as gracefully as possible. - cpVect n = info->n = (dist ? cpvmult(delta, 1.0f/dist) : segment->tn); - - // Reject endcap collisions if tangents are provided. - cpVect rot = cpBodyGetRotation(segment->shape.body); - if( - (closest_t != 0.0f || cpvdot(n, cpvrotate(segment->a_tangent, rot)) >= 0.0) && - (closest_t != 1.0f || cpvdot(n, cpvrotate(segment->b_tangent, rot)) >= 0.0) - ){ - cpCollisionInfoPushContact(info, cpvadd(center, cpvmult(n, circle->r)), cpvadd(closest, cpvmult(n, -segment->r)), 0); - } - } -} - -static void -SegmentToSegment(const cpSegmentShape *seg1, const cpSegmentShape *seg2, struct cpCollisionInfo *info) -{ - struct SupportContext context = {(cpShape *)seg1, (cpShape *)seg2, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)SegmentSupportPoint}; - struct ClosestPoints points = GJK(&context, &info->id); - -#if DRAW_CLOSEST -#if PRINT_LOG -// ChipmunkDemoPrintString("Distance: %.2f\n", points.d); -#endif - - ChipmunkDebugDrawDot(6.0, points.a, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawDot(6.0, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1)); -#endif - - cpVect n = points.n; - cpVect rot1 = cpBodyGetRotation(seg1->shape.body); - cpVect rot2 = cpBodyGetRotation(seg2->shape.body); - - // If the closest points are nearer than the sum of the radii... - if( - points.d <= (seg1->r + seg2->r) && ( - // Reject endcap collisions if tangents are provided. - (!cpveql(points.a, seg1->ta) || cpvdot(n, cpvrotate(seg1->a_tangent, rot1)) <= 0.0) && - (!cpveql(points.a, seg1->tb) || cpvdot(n, cpvrotate(seg1->b_tangent, rot1)) <= 0.0) && - (!cpveql(points.b, seg2->ta) || cpvdot(n, cpvrotate(seg2->a_tangent, rot2)) >= 0.0) && - (!cpveql(points.b, seg2->tb) || cpvdot(n, cpvrotate(seg2->b_tangent, rot2)) >= 0.0) - ) - ){ - ContactPoints(SupportEdgeForSegment(seg1, n), SupportEdgeForSegment(seg2, cpvneg(n)), points, info); - } -} - -static void -PolyToPoly(const cpPolyShape *poly1, const cpPolyShape *poly2, struct cpCollisionInfo *info) -{ - struct SupportContext context = {(cpShape *)poly1, (cpShape *)poly2, (SupportPointFunc)PolySupportPoint, (SupportPointFunc)PolySupportPoint}; - struct ClosestPoints points = GJK(&context, &info->id); - -#if DRAW_CLOSEST -#if PRINT_LOG -// ChipmunkDemoPrintString("Distance: %.2f\n", points.d); -#endif - - ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1)); -#endif - - // If the closest points are nearer than the sum of the radii... - if(points.d - poly1->r - poly2->r <= 0.0){ - ContactPoints(SupportEdgeForPoly(poly1, points.n), SupportEdgeForPoly(poly2, cpvneg(points.n)), points, info); - } -} - -static void -SegmentToPoly(const cpSegmentShape *seg, const cpPolyShape *poly, struct cpCollisionInfo *info) -{ - struct SupportContext context = {(cpShape *)seg, (cpShape *)poly, (SupportPointFunc)SegmentSupportPoint, (SupportPointFunc)PolySupportPoint}; - struct ClosestPoints points = GJK(&context, &info->id); - -#if DRAW_CLOSEST -#if PRINT_LOG -// ChipmunkDemoPrintString("Distance: %.2f\n", points.d); -#endif - - ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1)); -#endif - - cpVect n = points.n; - cpVect rot = cpBodyGetRotation(seg->shape.body); - - if( - // If the closest points are nearer than the sum of the radii... - points.d - seg->r - poly->r <= 0.0 && ( - // Reject endcap collisions if tangents are provided. - (!cpveql(points.a, seg->ta) || cpvdot(n, cpvrotate(seg->a_tangent, rot)) <= 0.0) && - (!cpveql(points.a, seg->tb) || cpvdot(n, cpvrotate(seg->b_tangent, rot)) <= 0.0) - ) - ){ - ContactPoints(SupportEdgeForSegment(seg, n), SupportEdgeForPoly(poly, cpvneg(n)), points, info); - } -} - -static void -CircleToPoly(const cpCircleShape *circle, const cpPolyShape *poly, struct cpCollisionInfo *info) -{ - struct SupportContext context = {(cpShape *)circle, (cpShape *)poly, (SupportPointFunc)CircleSupportPoint, (SupportPointFunc)PolySupportPoint}; - struct ClosestPoints points = GJK(&context, &info->id); - -#if DRAW_CLOSEST - ChipmunkDebugDrawDot(3.0, points.a, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawDot(3.0, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, points.b, RGBAColor(1, 1, 1, 1)); - ChipmunkDebugDrawSegment(points.a, cpvadd(points.a, cpvmult(points.n, 10.0)), RGBAColor(1, 0, 0, 1)); -#endif - - // If the closest points are nearer than the sum of the radii... - if(points.d <= circle->r + poly->r){ - cpVect n = info->n = points.n; - cpCollisionInfoPushContact(info, cpvadd(points.a, cpvmult(n, circle->r)), cpvadd(points.b, cpvmult(n, -poly->r)), 0); - } -} - -static void -CollisionError(const cpShape *circle, const cpShape *poly, struct cpCollisionInfo *info) -{ - cpAssertHard(cpFalse, "Internal Error: Shape types are not sorted."); -} - - -static const CollisionFunc BuiltinCollisionFuncs[9] = { - (CollisionFunc)CircleToCircle, - CollisionError, - CollisionError, - (CollisionFunc)CircleToSegment, - (CollisionFunc)SegmentToSegment, - CollisionError, - (CollisionFunc)CircleToPoly, - (CollisionFunc)SegmentToPoly, - (CollisionFunc)PolyToPoly, -}; -static const CollisionFunc *CollisionFuncs = BuiltinCollisionFuncs; - -struct cpCollisionInfo -cpCollide(const cpShape *a, const cpShape *b, cpCollisionID id, struct cpContact *contacts) -{ - struct cpCollisionInfo info = {a, b, id, cpvzero, 0, contacts}; - - // Make sure the shape types are in order. - if(a->klass->type > b->klass->type){ - info.a = b; - info.b = a; - } - - CollisionFuncs[info.a->klass->type + info.b->klass->type*CP_NUM_SHAPES](info.a, info.b, &info); - -// if(0){ -// for(int i=0; iklass = klass; - - constraint->a = a; - constraint->b = b; - constraint->space = NULL; - - constraint->next_a = NULL; - constraint->next_b = NULL; - - constraint->maxForce = (cpFloat)INFINITY; - constraint->errorBias = cpfpow(1.0f - 0.1f, 60.0f); - constraint->maxBias = (cpFloat)INFINITY; - - constraint->collideBodies = cpTrue; - - constraint->preSolve = NULL; - constraint->postSolve = NULL; -} - -cpSpace * -cpConstraintGetSpace(const cpConstraint *constraint) -{ - return constraint->space; -} - -cpBody * -cpConstraintGetBodyA(const cpConstraint *constraint) -{ - return constraint->a; -} - -cpBody * -cpConstraintGetBodyB(const cpConstraint *constraint) -{ - return constraint->b; -} - -cpFloat -cpConstraintGetMaxForce(const cpConstraint *constraint) -{ - return constraint->maxForce; -} - -void -cpConstraintSetMaxForce(cpConstraint *constraint, cpFloat maxForce) -{ - cpAssertHard(maxForce >= 0.0f, "maxForce must be positive."); - cpConstraintActivateBodies(constraint); - constraint->maxForce = maxForce; -} - -cpFloat -cpConstraintGetErrorBias(const cpConstraint *constraint) -{ - return constraint->errorBias; -} - -void -cpConstraintSetErrorBias(cpConstraint *constraint, cpFloat errorBias) -{ - cpAssertHard(errorBias >= 0.0f, "errorBias must be positive."); - cpConstraintActivateBodies(constraint); - constraint->errorBias = errorBias; -} - -cpFloat -cpConstraintGetMaxBias(const cpConstraint *constraint) -{ - return constraint->maxBias; -} - -void -cpConstraintSetMaxBias(cpConstraint *constraint, cpFloat maxBias) -{ - cpAssertHard(maxBias >= 0.0f, "maxBias must be positive."); - cpConstraintActivateBodies(constraint); - constraint->maxBias = maxBias; -} - -cpBool -cpConstraintGetCollideBodies(const cpConstraint *constraint) -{ - return constraint->collideBodies; -} - -void -cpConstraintSetCollideBodies(cpConstraint *constraint, cpBool collideBodies) -{ - cpConstraintActivateBodies(constraint); - constraint->collideBodies = collideBodies; -} - -cpConstraintPreSolveFunc -cpConstraintGetPreSolveFunc(const cpConstraint *constraint) -{ - return constraint->preSolve; -} - -void -cpConstraintSetPreSolveFunc(cpConstraint *constraint, cpConstraintPreSolveFunc preSolveFunc) -{ - constraint->preSolve = preSolveFunc; -} - -cpConstraintPostSolveFunc -cpConstraintGetPostSolveFunc(const cpConstraint *constraint) -{ - return constraint->postSolve; -} - -void -cpConstraintSetPostSolveFunc(cpConstraint *constraint, cpConstraintPostSolveFunc postSolveFunc) -{ - constraint->postSolve = postSolveFunc; -} - -cpDataPointer -cpConstraintGetUserData(const cpConstraint *constraint) -{ - return constraint->userData; -} - -void -cpConstraintSetUserData(cpConstraint *constraint, cpDataPointer userData) -{ - constraint->userData = userData; -} - - -cpFloat -cpConstraintGetImpulse(cpConstraint *constraint) -{ - return constraint->klass->getImpulse(constraint); -} diff --git a/3rdparty/chipmunk/src/cpDampedRotarySpring.c b/3rdparty/chipmunk/src/cpDampedRotarySpring.c deleted file mode 100644 index 8d38a545e0f9..000000000000 --- a/3rdparty/chipmunk/src/cpDampedRotarySpring.c +++ /dev/null @@ -1,178 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static cpFloat -defaultSpringTorque(cpDampedRotarySpring *spring, cpFloat relativeAngle){ - return (relativeAngle - spring->restAngle)*spring->stiffness; -} - -static void -preStep(cpDampedRotarySpring *spring, cpFloat dt) -{ - cpBody *a = spring->constraint.a; - cpBody *b = spring->constraint.b; - - cpFloat moment = a->i_inv + b->i_inv; - cpAssertSoft(moment != 0.0, "Unsolvable spring."); - spring->iSum = 1.0f/moment; - - spring->w_coef = 1.0f - cpfexp(-spring->damping*dt*moment); - spring->target_wrn = 0.0f; - - // apply spring torque - cpFloat j_spring = spring->springTorqueFunc((cpConstraint *)spring, a->a - b->a)*dt; - spring->jAcc = j_spring; - - a->w -= j_spring*a->i_inv; - b->w += j_spring*b->i_inv; -} - -static void applyCachedImpulse(cpDampedRotarySpring *spring, cpFloat dt_coef){} - -static void -applyImpulse(cpDampedRotarySpring *spring, cpFloat dt) -{ - cpBody *a = spring->constraint.a; - cpBody *b = spring->constraint.b; - - // compute relative velocity - cpFloat wrn = a->w - b->w;//normal_relative_velocity(a, b, r1, r2, n) - spring->target_vrn; - - // compute velocity loss from drag - // not 100% certain this is derived correctly, though it makes sense - cpFloat w_damp = (spring->target_wrn - wrn)*spring->w_coef; - spring->target_wrn = wrn + w_damp; - - //apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, v_damp*spring->nMass)); - cpFloat j_damp = w_damp*spring->iSum; - spring->jAcc += j_damp; - - a->w += j_damp*a->i_inv; - b->w -= j_damp*b->i_inv; -} - -static cpFloat -getImpulse(cpDampedRotarySpring *spring) -{ - return spring->jAcc; -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpDampedRotarySpring * -cpDampedRotarySpringAlloc(void) -{ - return (cpDampedRotarySpring *)cpcalloc(1, sizeof(cpDampedRotarySpring)); -} - -cpDampedRotarySpring * -cpDampedRotarySpringInit(cpDampedRotarySpring *spring, cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping) -{ - cpConstraintInit((cpConstraint *)spring, &klass, a, b); - - spring->restAngle = restAngle; - spring->stiffness = stiffness; - spring->damping = damping; - spring->springTorqueFunc = (cpDampedRotarySpringTorqueFunc)defaultSpringTorque; - - spring->jAcc = 0.0f; - - return spring; -} - -cpConstraint * -cpDampedRotarySpringNew(cpBody *a, cpBody *b, cpFloat restAngle, cpFloat stiffness, cpFloat damping) -{ - return (cpConstraint *)cpDampedRotarySpringInit(cpDampedRotarySpringAlloc(), a, b, restAngle, stiffness, damping); -} - -cpBool -cpConstraintIsDampedRotarySpring(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpFloat -cpDampedRotarySpringGetRestAngle(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - return ((cpDampedRotarySpring *)constraint)->restAngle; -} - -void -cpDampedRotarySpringSetRestAngle(cpConstraint *constraint, cpFloat restAngle) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedRotarySpring *)constraint)->restAngle = restAngle; -} - -cpFloat -cpDampedRotarySpringGetStiffness(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - return ((cpDampedRotarySpring *)constraint)->stiffness; -} - -void -cpDampedRotarySpringSetStiffness(cpConstraint *constraint, cpFloat stiffness) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedRotarySpring *)constraint)->stiffness = stiffness; -} - -cpFloat -cpDampedRotarySpringGetDamping(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - return ((cpDampedRotarySpring *)constraint)->damping; -} - -void -cpDampedRotarySpringSetDamping(cpConstraint *constraint, cpFloat damping) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedRotarySpring *)constraint)->damping = damping; -} - -cpDampedRotarySpringTorqueFunc -cpDampedRotarySpringGetSpringTorqueFunc(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - return ((cpDampedRotarySpring *)constraint)->springTorqueFunc; -} - -void -cpDampedRotarySpringSetSpringTorqueFunc(cpConstraint *constraint, cpDampedRotarySpringTorqueFunc springTorqueFunc) -{ - cpAssertHard(cpConstraintIsDampedRotarySpring(constraint), "Constraint is not a damped rotary spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedRotarySpring *)constraint)->springTorqueFunc = springTorqueFunc; -} diff --git a/3rdparty/chipmunk/src/cpDampedSpring.c b/3rdparty/chipmunk/src/cpDampedSpring.c deleted file mode 100644 index e4d019e9a02f..000000000000 --- a/3rdparty/chipmunk/src/cpDampedSpring.c +++ /dev/null @@ -1,216 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static cpFloat -defaultSpringForce(cpDampedSpring *spring, cpFloat dist){ - return (spring->restLength - dist)*spring->stiffness; -} - -static void -preStep(cpDampedSpring *spring, cpFloat dt) -{ - cpBody *a = spring->constraint.a; - cpBody *b = spring->constraint.b; - - spring->r1 = cpTransformVect(a->transform, cpvsub(spring->anchorA, a->cog)); - spring->r2 = cpTransformVect(b->transform, cpvsub(spring->anchorB, b->cog)); - - cpVect delta = cpvsub(cpvadd(b->p, spring->r2), cpvadd(a->p, spring->r1)); - cpFloat dist = cpvlength(delta); - spring->n = cpvmult(delta, 1.0f/(dist ? dist : INFINITY)); - - cpFloat k = k_scalar(a, b, spring->r1, spring->r2, spring->n); - cpAssertSoft(k != 0.0, "Unsolvable spring."); - spring->nMass = 1.0f/k; - - spring->target_vrn = 0.0f; - spring->v_coef = 1.0f - cpfexp(-spring->damping*dt*k); - - // apply spring force - cpFloat f_spring = spring->springForceFunc((cpConstraint *)spring, dist); - cpFloat j_spring = spring->jAcc = f_spring*dt; - apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_spring)); -} - -static void applyCachedImpulse(cpDampedSpring *spring, cpFloat dt_coef){} - -static void -applyImpulse(cpDampedSpring *spring, cpFloat dt) -{ - cpBody *a = spring->constraint.a; - cpBody *b = spring->constraint.b; - - cpVect n = spring->n; - cpVect r1 = spring->r1; - cpVect r2 = spring->r2; - - // compute relative velocity - cpFloat vrn = normal_relative_velocity(a, b, r1, r2, n); - - // compute velocity loss from drag - cpFloat v_damp = (spring->target_vrn - vrn)*spring->v_coef; - spring->target_vrn = vrn + v_damp; - - cpFloat j_damp = v_damp*spring->nMass; - spring->jAcc += j_damp; - apply_impulses(a, b, spring->r1, spring->r2, cpvmult(spring->n, j_damp)); -} - -static cpFloat -getImpulse(cpDampedSpring *spring) -{ - return spring->jAcc; -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpDampedSpring * -cpDampedSpringAlloc(void) -{ - return (cpDampedSpring *)cpcalloc(1, sizeof(cpDampedSpring)); -} - -cpDampedSpring * -cpDampedSpringInit(cpDampedSpring *spring, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping) -{ - cpConstraintInit((cpConstraint *)spring, &klass, a, b); - - spring->anchorA = anchorA; - spring->anchorB = anchorB; - - spring->restLength = restLength; - spring->stiffness = stiffness; - spring->damping = damping; - spring->springForceFunc = (cpDampedSpringForceFunc)defaultSpringForce; - - spring->jAcc = 0.0f; - - return spring; -} - -cpConstraint * -cpDampedSpringNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiffness, cpFloat damping) -{ - return (cpConstraint *)cpDampedSpringInit(cpDampedSpringAlloc(), a, b, anchorA, anchorB, restLength, stiffness, damping); -} - -cpBool -cpConstraintIsDampedSpring(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpVect -cpDampedSpringGetAnchorA(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->anchorA; -} - -void -cpDampedSpringSetAnchorA(cpConstraint *constraint, cpVect anchorA) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->anchorA = anchorA; -} - -cpVect -cpDampedSpringGetAnchorB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->anchorB; -} - -void -cpDampedSpringSetAnchorB(cpConstraint *constraint, cpVect anchorB) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->anchorB = anchorB; -} - -cpFloat -cpDampedSpringGetRestLength(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->restLength; -} - -void -cpDampedSpringSetRestLength(cpConstraint *constraint, cpFloat restLength) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->restLength = restLength; -} - -cpFloat -cpDampedSpringGetStiffness(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->stiffness; -} - -void -cpDampedSpringSetStiffness(cpConstraint *constraint, cpFloat stiffness) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->stiffness = stiffness; -} - -cpFloat -cpDampedSpringGetDamping(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->damping; -} - -void -cpDampedSpringSetDamping(cpConstraint *constraint, cpFloat damping) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->damping = damping; -} - -cpDampedSpringForceFunc -cpDampedSpringGetSpringForceFunc(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - return ((cpDampedSpring *)constraint)->springForceFunc; -} - -void -cpDampedSpringSetSpringForceFunc(cpConstraint *constraint, cpDampedSpringForceFunc springForceFunc) -{ - cpAssertHard(cpConstraintIsDampedSpring(constraint), "Constraint is not a damped spring."); - cpConstraintActivateBodies(constraint); - ((cpDampedSpring *)constraint)->springForceFunc = springForceFunc; -} diff --git a/3rdparty/chipmunk/src/cpGearJoint.c b/3rdparty/chipmunk/src/cpGearJoint.c deleted file mode 100644 index 3670173b3c59..000000000000 --- a/3rdparty/chipmunk/src/cpGearJoint.c +++ /dev/null @@ -1,145 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpGearJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // calculate moment of inertia coefficient. - joint->iSum = 1.0f/(a->i_inv*joint->ratio_inv + joint->ratio*b->i_inv); - - // calculate bias velocity - cpFloat maxBias = joint->constraint.maxBias; - joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(b->a*joint->ratio - a->a - joint->phase)/dt, -maxBias, maxBias); -} - -static void -applyCachedImpulse(cpGearJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat j = joint->jAcc*dt_coef; - a->w -= j*a->i_inv*joint->ratio_inv; - b->w += j*b->i_inv; -} - -static void -applyImpulse(cpGearJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // compute relative rotational velocity - cpFloat wr = b->w*joint->ratio - a->w; - - cpFloat jMax = joint->constraint.maxForce*dt; - - // compute normal impulse - cpFloat j = (joint->bias - wr)*joint->iSum; - cpFloat jOld = joint->jAcc; - joint->jAcc = cpfclamp(jOld + j, -jMax, jMax); - j = joint->jAcc - jOld; - - // apply impulse - a->w -= j*a->i_inv*joint->ratio_inv; - b->w += j*b->i_inv; -} - -static cpFloat -getImpulse(cpGearJoint *joint) -{ - return cpfabs(joint->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpGearJoint * -cpGearJointAlloc(void) -{ - return (cpGearJoint *)cpcalloc(1, sizeof(cpGearJoint)); -} - -cpGearJoint * -cpGearJointInit(cpGearJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->phase = phase; - joint->ratio = ratio; - joint->ratio_inv = 1.0f/ratio; - - joint->jAcc = 0.0f; - - return joint; -} - -cpConstraint * -cpGearJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratio) -{ - return (cpConstraint *)cpGearJointInit(cpGearJointAlloc(), a, b, phase, ratio); -} - -cpBool -cpConstraintIsGearJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpFloat -cpGearJointGetPhase(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint."); - return ((cpGearJoint *)constraint)->phase; -} - -void -cpGearJointSetPhase(cpConstraint *constraint, cpFloat phase) -{ - cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint."); - cpConstraintActivateBodies(constraint); - ((cpGearJoint *)constraint)->phase = phase; -} - -cpFloat -cpGearJointGetRatio(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint."); - return ((cpGearJoint *)constraint)->ratio; -} - -void -cpGearJointSetRatio(cpConstraint *constraint, cpFloat ratio) -{ - cpAssertHard(cpConstraintIsGearJoint(constraint), "Constraint is not a ratchet joint."); - cpConstraintActivateBodies(constraint); - ((cpGearJoint *)constraint)->ratio = ratio; - ((cpGearJoint *)constraint)->ratio_inv = 1.0f/ratio; -} diff --git a/3rdparty/chipmunk/src/cpGrooveJoint.c b/3rdparty/chipmunk/src/cpGrooveJoint.c deleted file mode 100644 index 50d1857d440b..000000000000 --- a/3rdparty/chipmunk/src/cpGrooveJoint.c +++ /dev/null @@ -1,197 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpGrooveJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // calculate endpoints in worldspace - cpVect ta = cpTransformPoint(a->transform, joint->grv_a); - cpVect tb = cpTransformPoint(a->transform, joint->grv_b); - - // calculate axis - cpVect n = cpTransformVect(a->transform, joint->grv_n); - cpFloat d = cpvdot(ta, n); - - joint->grv_tn = n; - joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog)); - - // calculate tangential distance along the axis of r2 - cpFloat td = cpvcross(cpvadd(b->p, joint->r2), n); - // calculate clamping factor and r2 - if(td <= cpvcross(ta, n)){ - joint->clamp = 1.0f; - joint->r1 = cpvsub(ta, a->p); - } else if(td >= cpvcross(tb, n)){ - joint->clamp = -1.0f; - joint->r1 = cpvsub(tb, a->p); - } else { - joint->clamp = 0.0f; - joint->r1 = cpvsub(cpvadd(cpvmult(cpvperp(n), -td), cpvmult(n, d)), a->p); - } - - // Calculate mass tensor - joint->k = k_tensor(a, b, joint->r1, joint->r2); - - // calculate bias velocity - cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); - joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias); -} - -static void -applyCachedImpulse(cpGrooveJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef)); -} - -static inline cpVect -grooveConstrain(cpGrooveJoint *joint, cpVect j, cpFloat dt){ - cpVect n = joint->grv_tn; - cpVect jClamp = (joint->clamp*cpvcross(j, n) > 0.0f) ? j : cpvproject(j, n); - return cpvclamp(jClamp, joint->constraint.maxForce*dt); -} - -static void -applyImpulse(cpGrooveJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpVect r1 = joint->r1; - cpVect r2 = joint->r2; - - // compute impulse - cpVect vr = relative_velocity(a, b, r1, r2); - - cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr)); - cpVect jOld = joint->jAcc; - joint->jAcc = grooveConstrain(joint, cpvadd(jOld, j), dt); - j = cpvsub(joint->jAcc, jOld); - - // apply impulse - apply_impulses(a, b, joint->r1, joint->r2, j); -} - -static cpFloat -getImpulse(cpGrooveJoint *joint) -{ - return cpvlength(joint->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpGrooveJoint * -cpGrooveJointAlloc(void) -{ - return (cpGrooveJoint *)cpcalloc(1, sizeof(cpGrooveJoint)); -} - -cpGrooveJoint * -cpGrooveJointInit(cpGrooveJoint *joint, cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->grv_a = groove_a; - joint->grv_b = groove_b; - joint->grv_n = cpvperp(cpvnormalize(cpvsub(groove_b, groove_a))); - joint->anchorB = anchorB; - - joint->jAcc = cpvzero; - - return joint; -} - -cpConstraint * -cpGrooveJointNew(cpBody *a, cpBody *b, cpVect groove_a, cpVect groove_b, cpVect anchorB) -{ - return (cpConstraint *)cpGrooveJointInit(cpGrooveJointAlloc(), a, b, groove_a, groove_b, anchorB); -} - -cpBool -cpConstraintIsGrooveJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpVect -cpGrooveJointGetGrooveA(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - return ((cpGrooveJoint *)constraint)->grv_a; -} - -void -cpGrooveJointSetGrooveA(cpConstraint *constraint, cpVect value) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - cpGrooveJoint *g = (cpGrooveJoint *)constraint; - - g->grv_a = value; - g->grv_n = cpvperp(cpvnormalize(cpvsub(g->grv_b, value))); - - cpConstraintActivateBodies(constraint); -} - -cpVect -cpGrooveJointGetGrooveB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - return ((cpGrooveJoint *)constraint)->grv_b; -} - -void -cpGrooveJointSetGrooveB(cpConstraint *constraint, cpVect value) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - cpGrooveJoint *g = (cpGrooveJoint *)constraint; - - g->grv_b = value; - g->grv_n = cpvperp(cpvnormalize(cpvsub(value, g->grv_a))); - - cpConstraintActivateBodies(constraint); -} - -cpVect -cpGrooveJointGetAnchorB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - return ((cpGrooveJoint *)constraint)->anchorB; -} - -void -cpGrooveJointSetAnchorB(cpConstraint *constraint, cpVect anchorB) -{ - cpAssertHard(cpConstraintIsGrooveJoint(constraint), "Constraint is not a groove joint."); - cpConstraintActivateBodies(constraint); - ((cpGrooveJoint *)constraint)->anchorB = anchorB; -} diff --git a/3rdparty/chipmunk/src/cpHashSet.c b/3rdparty/chipmunk/src/cpHashSet.c deleted file mode 100644 index b2918defb531..000000000000 --- a/3rdparty/chipmunk/src/cpHashSet.c +++ /dev/null @@ -1,253 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" -#include "prime.h" - -typedef struct cpHashSetBin { - void *elt; - cpHashValue hash; - struct cpHashSetBin *next; -} cpHashSetBin; - -struct cpHashSet { - unsigned int entries, size; - - cpHashSetEqlFunc eql; - void *default_value; - - cpHashSetBin **table; - cpHashSetBin *pooledBins; - - cpArray *allocatedBuffers; -}; - -void -cpHashSetFree(cpHashSet *set) -{ - if(set){ - cpfree(set->table); - - cpArrayFreeEach(set->allocatedBuffers, cpfree); - cpArrayFree(set->allocatedBuffers); - - cpfree(set); - } -} - -cpHashSet * -cpHashSetNew(int size, cpHashSetEqlFunc eqlFunc) -{ - cpHashSet *set = (cpHashSet *)cpcalloc(1, sizeof(cpHashSet)); - - set->size = next_prime(size); - set->entries = 0; - - set->eql = eqlFunc; - set->default_value = NULL; - - set->table = (cpHashSetBin **)cpcalloc(set->size, sizeof(cpHashSetBin *)); - set->pooledBins = NULL; - - set->allocatedBuffers = cpArrayNew(0); - - return set; -} - -void -cpHashSetSetDefaultValue(cpHashSet *set, void *default_value) -{ - set->default_value = default_value; -} - -static int -setIsFull(cpHashSet *set) -{ - return (set->entries >= set->size); -} - -static void -cpHashSetResize(cpHashSet *set) -{ - // Get the next approximate doubled prime. - unsigned int newSize = next_prime(set->size + 1); - // Allocate a new table. - cpHashSetBin **newTable = (cpHashSetBin **)cpcalloc(newSize, sizeof(cpHashSetBin *)); - - // Iterate over the chains. - for(unsigned int i=0; isize; i++){ - // Rehash the bins into the new table. - cpHashSetBin *bin = set->table[i]; - while(bin){ - cpHashSetBin *next = bin->next; - - cpHashValue idx = bin->hash%newSize; - bin->next = newTable[idx]; - newTable[idx] = bin; - - bin = next; - } - } - - cpfree(set->table); - - set->table = newTable; - set->size = newSize; -} - -static inline void -recycleBin(cpHashSet *set, cpHashSetBin *bin) -{ - bin->next = set->pooledBins; - set->pooledBins = bin; - bin->elt = NULL; -} - -static cpHashSetBin * -getUnusedBin(cpHashSet *set) -{ - cpHashSetBin *bin = set->pooledBins; - - if(bin){ - set->pooledBins = bin->next; - return bin; - } else { - // Pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(cpHashSetBin); - cpAssertHard(count, "Internal Error: Buffer size is too small."); - - cpHashSetBin *buffer = (cpHashSetBin *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(set->allocatedBuffers, buffer); - - // push all but the first one, return it instead - for(int i=1; ientries; -} - -const void * -cpHashSetInsert(cpHashSet *set, cpHashValue hash, const void *ptr, cpHashSetTransFunc trans, void *data) -{ - cpHashValue idx = hash%set->size; - - // Find the bin with the matching element. - cpHashSetBin *bin = set->table[idx]; - while(bin && !set->eql(ptr, bin->elt)) - bin = bin->next; - - // Create it if necessary. - if(!bin){ - bin = getUnusedBin(set); - bin->hash = hash; - bin->elt = (trans ? trans(ptr, data) : data); - - bin->next = set->table[idx]; - set->table[idx] = bin; - - set->entries++; - if(setIsFull(set)) cpHashSetResize(set); - } - - return bin->elt; -} - -const void * -cpHashSetRemove(cpHashSet *set, cpHashValue hash, const void *ptr) -{ - cpHashValue idx = hash%set->size; - - cpHashSetBin **prev_ptr = &set->table[idx]; - cpHashSetBin *bin = set->table[idx]; - - // Find the bin - while(bin && !set->eql(ptr, bin->elt)){ - prev_ptr = &bin->next; - bin = bin->next; - } - - // Remove it if it exists. - if(bin){ - // Update the previous linked list pointer - (*prev_ptr) = bin->next; - set->entries--; - - const void *elt = bin->elt; - recycleBin(set, bin); - - return elt; - } - - return NULL; -} - -const void * -cpHashSetFind(cpHashSet *set, cpHashValue hash, const void *ptr) -{ - cpHashValue idx = hash%set->size; - cpHashSetBin *bin = set->table[idx]; - while(bin && !set->eql(ptr, bin->elt)) - bin = bin->next; - - return (bin ? bin->elt : set->default_value); -} - -void -cpHashSetEach(cpHashSet *set, cpHashSetIteratorFunc func, void *data) -{ - for(unsigned int i=0; isize; i++){ - cpHashSetBin *bin = set->table[i]; - while(bin){ - cpHashSetBin *next = bin->next; - func(bin->elt, data); - bin = next; - } - } -} - -void -cpHashSetFilter(cpHashSet *set, cpHashSetFilterFunc func, void *data) -{ - for(unsigned int i=0; isize; i++){ - // The rest works similarly to cpHashSetRemove() above. - cpHashSetBin **prev_ptr = &set->table[i]; - cpHashSetBin *bin = set->table[i]; - while(bin){ - cpHashSetBin *next = bin->next; - - if(func(bin->elt, data)){ - prev_ptr = &bin->next; - } else { - (*prev_ptr) = next; - - set->entries--; - recycleBin(set, bin); - } - - bin = next; - } - } -} diff --git a/3rdparty/chipmunk/src/cpHastySpace.c b/3rdparty/chipmunk/src/cpHastySpace.c deleted file mode 100644 index 8422c3ebe64a..000000000000 --- a/3rdparty/chipmunk/src/cpHastySpace.c +++ /dev/null @@ -1,700 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -#include -#include - -//TODO: Move all the thread stuff to another file - -//#include - -#ifdef __APPLE__ -#include -#endif - -#ifndef _WIN32 -#include -#elif defined(__MINGW32__) -#include -#else -#ifndef WIN32_LEAN_AND_MEAN -#define WIN32_LEAN_AND_MEAN -#endif - -#ifndef NOMINMAX -#define NOMINMAX -#endif - -#include // _beginthreadex -#include - -#ifndef ETIMEDOUT -#define ETIMEDOUT 1 -#endif - -// Simple pthread implementation for Windows -// Made from scratch to avoid the LGPL licence from pthread-win32 -enum { - SIGNAL = 0, - BROADCAST = 1, - MAX_EVENTS = 2 -}; - -typedef HANDLE pthread_t; -typedef struct -{ - // Based on http://www.cs.wustl.edu/~schmidt/win32-cv-1.html since Windows has no condition variable until NT6 - UINT waiters_count; - // Count of the number of waiters. - - CRITICAL_SECTION waiters_count_lock; - // Serialize access to . - - HANDLE events[MAX_EVENTS]; -} pthread_cond_t; -typedef CRITICAL_SECTION pthread_mutex_t; - -typedef struct {} pthread_condattr_t; // Dummy; - -int pthread_cond_destroy(pthread_cond_t* cv) -{ - CloseHandle(cv->events[BROADCAST]); - CloseHandle(cv->events[SIGNAL]); - - DeleteCriticalSection(&cv->waiters_count_lock); - - return 0; -} - -int pthread_cond_init(pthread_cond_t* cv, const pthread_condattr_t* attr) -{ - // Initialize the count to 0. - cv->waiters_count = 0; - - // Create an auto-reset event. - cv->events[SIGNAL] = CreateEvent(NULL, // no security - FALSE, // auto-reset event - FALSE, // non-signaled initially - NULL); // unnamed - - // Create a manual-reset event. - cv->events[BROADCAST] = CreateEvent(NULL, // no security - TRUE, // manual-reset - FALSE, // non-signaled initially - NULL); // unnamed - - InitializeCriticalSection(&cv->waiters_count_lock); - - return 0; -} - -int pthread_cond_broadcast(pthread_cond_t *cv) -{ - // Avoid race conditions. - EnterCriticalSection(&cv->waiters_count_lock); - int have_waiters = cv->waiters_count > 0; - LeaveCriticalSection(&cv->waiters_count_lock); - - if (have_waiters) - SetEvent(cv->events[BROADCAST]); - - return 0; -} - -int pthread_cond_signal(pthread_cond_t* cv) -{ - // Avoid race conditions. - EnterCriticalSection(&cv->waiters_count_lock); - int have_waiters = cv->waiters_count > 0; - LeaveCriticalSection(&cv->waiters_count_lock); - - if (have_waiters) - SetEvent(cv->events[SIGNAL]); - - return 0; -} - -int pthread_cond_wait(pthread_cond_t* cv, pthread_mutex_t* external_mutex) -{ - // Avoid race conditions. - EnterCriticalSection(&cv->waiters_count_lock); - cv->waiters_count++; - LeaveCriticalSection(&cv->waiters_count_lock); - - // It's ok to release the here since Win32 - // manual-reset events maintain state when used with - // . This avoids the "lost wakeup" bug... - LeaveCriticalSection(external_mutex); - - // Wait for either event to become signaled due to - // being called or being called. - int result = WaitForMultipleObjects(2, cv->events, FALSE, INFINITE); - - EnterCriticalSection(&cv->waiters_count_lock); - cv->waiters_count--; - int last_waiter = - result == WAIT_OBJECT_0 + BROADCAST - && cv->waiters_count == 0; - LeaveCriticalSection(&cv->waiters_count_lock); - - // Some thread called . - if (last_waiter) - // We're the last waiter to be notified or to stop waiting, so - // reset the manual event. - ResetEvent(cv->events[BROADCAST]); - - // Reacquire the . - EnterCriticalSection(external_mutex); - - return result == WAIT_TIMEOUT ? ETIMEDOUT : 0; -} - -typedef struct {} pthread_mutexattr_t; //< Dummy - -int pthread_mutex_init(pthread_mutex_t* mutex, const pthread_mutexattr_t* attr) -{ - InitializeCriticalSection(mutex); - return 0; -} - -int pthread_mutex_destroy(pthread_mutex_t* mutex) -{ - DeleteCriticalSection(mutex); - return 0; -} - -int pthread_mutex_lock(pthread_mutex_t* mutex) -{ - EnterCriticalSection(mutex); - return 0; -} - -int pthread_mutex_unlock(pthread_mutex_t* mutex) -{ - LeaveCriticalSection(mutex); - return 0; -} - -typedef struct {} pthread_attr_t; - -typedef struct -{ - void *(*start_routine) (void *); - void* arg; -} pthread_internal_thread; - -unsigned int __stdcall ThreadProc(void* userdata) -{ - pthread_internal_thread* ud = (pthread_internal_thread*) userdata; - ud->start_routine(ud->arg); - - free(ud); - - return 0; -} - -int pthread_create(pthread_t* thread, const pthread_attr_t* attr, void *(*start_routine) (void *), void *arg) -{ - pthread_internal_thread* ud = (pthread_internal_thread*) malloc(sizeof(pthread_internal_thread)); - ud->start_routine = start_routine; - ud->arg = arg; - - *thread = (HANDLE) (_beginthreadex(NULL, 0, &ThreadProc, ud, 0, NULL)); - if (!*thread) - return 1; - - return 0; -} - -int pthread_join(pthread_t thread, void **value_ptr) -{ - WaitForSingleObject(thread, INFINITE); - CloseHandle(thread); - - return 0; -} - -#endif - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/cpHastySpace.h" - - -//MARK: ARM NEON Solver - -#if __ARM_NEON__ -#include - -// Tested and known to work fine with Clang 3.0 and GCC 4.2 -// Doesn't work with Clang 1.6, and I have no idea why. -#if defined(__clang_major__) && __clang_major__ < 3 - #error Compiler not supported. -#endif - -#if CP_USE_DOUBLES - #if !__arm64 - #error Cannot use CP_USE_DOUBLES on 32 bit ARM. - #endif - - typedef float64_t cpFloat_t; - typedef float64x2_t cpFloatx2_t; - #define vld vld1q_f64 - #define vdup_n vdupq_n_f64 - #define vst vst1q_f64 - #define vst_lane vst1q_lane_f64 - #define vadd vaddq_f64 - #define vsub vsubq_f64 - #define vpadd vpaddq_f64 - #define vmul vmulq_f64 - #define vmul_n vmulq_n_f64 - #define vneg vnegq_f64 - #define vget_lane vgetq_lane_f64 - #define vset_lane vsetq_lane_f64 - #define vmin vminq_f64 - #define vmax vmaxq_f64 - #define vrev(__a) __builtin_shufflevector(__a, __a, 1, 0) -#else - typedef float32_t cpFloat_t; - typedef float32x2_t cpFloatx2_t; - #define vld vld1_f32 - #define vdup_n vdup_n_f32 - #define vst vst1_f32 - #define vst_lane vst1_lane_f32 - #define vadd vadd_f32 - #define vsub vsub_f32 - #define vpadd vpadd_f32 - #define vmul vmul_f32 - #define vmul_n vmul_n_f32 - #define vneg vneg_f32 - #define vget_lane vget_lane_f32 - #define vset_lane vset_lane_f32 - #define vmin vmin_f32 - #define vmax vmax_f32 - #define vrev vrev64_f32 -#endif - -// TODO could probably do better here, maybe using vcreate? -// especially for the constants -// Maybe use the {} notation for GCC/Clang? -static inline cpFloatx2_t -vmake(cpFloat_t x, cpFloat_t y) -{ -// cpFloatx2_t v = {}; -// v = vset_lane(x, v, 0); -// v = vset_lane(y, v, 1); -// -// return v; - - // This might not be super compatible, but all the NEON headers use it... - return (cpFloatx2_t){x, y}; -} - -static void -cpArbiterApplyImpulse_NEON(cpArbiter *arb) -{ - cpBody *a = arb->body_a; - cpBody *b = arb->body_b; - cpFloatx2_t surface_vr = vld((cpFloat_t *)&arb->surface_vr); - cpFloatx2_t n = vld((cpFloat_t *)&arb->n); - cpFloat_t friction = arb->u; - - int numContacts = arb->count; - struct cpContact *contacts = arb->contacts; - for(int i=0; ir1); - cpFloatx2_t r2 = vld((cpFloat_t *)&con->r2); - - cpFloatx2_t perp = vmake(-1.0, 1.0); - cpFloatx2_t r1p = vmul(vrev(r1), perp); - cpFloatx2_t r2p = vmul(vrev(r2), perp); - - cpFloatx2_t vBias_a = vld((cpFloat_t *)&a->v_bias); - cpFloatx2_t vBias_b = vld((cpFloat_t *)&b->v_bias); - cpFloatx2_t wBias = vmake(a->w_bias, b->w_bias); - - cpFloatx2_t vb1 = vadd(vBias_a, vmul_n(r1p, vget_lane(wBias, 0))); - cpFloatx2_t vb2 = vadd(vBias_b, vmul_n(r2p, vget_lane(wBias, 1))); - cpFloatx2_t vbr = vsub(vb2, vb1); - - cpFloatx2_t v_a = vld((cpFloat_t *)&a->v); - cpFloatx2_t v_b = vld((cpFloat_t *)&b->v); - cpFloatx2_t w = vmake(a->w, b->w); - cpFloatx2_t v1 = vadd(v_a, vmul_n(r1p, vget_lane(w, 0))); - cpFloatx2_t v2 = vadd(v_b, vmul_n(r2p, vget_lane(w, 1))); - cpFloatx2_t vr = vsub(v2, v1); - - cpFloatx2_t vbn_vrn = vpadd(vmul(vbr, n), vmul(vr, n)); - - cpFloatx2_t v_offset = vmake(con->bias, -con->bounce); - cpFloatx2_t jOld = vmake(con->jBias, con->jnAcc); - cpFloatx2_t jbn_jn = vmul_n(vsub(v_offset, vbn_vrn), con->nMass); - jbn_jn = vmax(vadd(jOld, jbn_jn), vdup_n(0.0)); - cpFloatx2_t jApply = vsub(jbn_jn, jOld); - - cpFloatx2_t t = vmul(vrev(n), perp); - cpFloatx2_t vrt_tmp = vmul(vadd(vr, surface_vr), t); - cpFloatx2_t vrt = vpadd(vrt_tmp, vrt_tmp); - - cpFloatx2_t jtOld = {}; jtOld = vset_lane(con->jtAcc, jtOld, 0); - cpFloatx2_t jtMax = vrev(vmul_n(jbn_jn, friction)); - cpFloatx2_t jt = vmul_n(vrt, -con->tMass); - jt = vmax(vneg(jtMax), vmin(vadd(jtOld, jt), jtMax)); - cpFloatx2_t jtApply = vsub(jt, jtOld); - - cpFloatx2_t i_inv = vmake(-a->i_inv, b->i_inv); - cpFloatx2_t nperp = vmake(1.0, -1.0); - - cpFloatx2_t jBias = vmul_n(n, vget_lane(jApply, 0)); - cpFloatx2_t jBiasCross = vmul(vrev(jBias), nperp); - cpFloatx2_t biasCrosses = vpadd(vmul(r1, jBiasCross), vmul(r2, jBiasCross)); - wBias = vadd(wBias, vmul(i_inv, biasCrosses)); - - vBias_a = vsub(vBias_a, vmul_n(jBias, a->m_inv)); - vBias_b = vadd(vBias_b, vmul_n(jBias, b->m_inv)); - - cpFloatx2_t j = vadd(vmul_n(n, vget_lane(jApply, 1)), vmul_n(t, vget_lane(jtApply, 0))); - cpFloatx2_t jCross = vmul(vrev(j), nperp); - cpFloatx2_t crosses = vpadd(vmul(r1, jCross), vmul(r2, jCross)); - w = vadd(w, vmul(i_inv, crosses)); - - v_a = vsub(v_a, vmul_n(j, a->m_inv)); - v_b = vadd(v_b, vmul_n(j, b->m_inv)); - - // TODO would moving these earlier help pipeline them better? - vst((cpFloat_t *)&a->v_bias, vBias_a); - vst((cpFloat_t *)&b->v_bias, vBias_b); - vst_lane((cpFloat_t *)&a->w_bias, wBias, 0); - vst_lane((cpFloat_t *)&b->w_bias, wBias, 1); - - vst((cpFloat_t *)&a->v, v_a); - vst((cpFloat_t *)&b->v, v_b); - vst_lane((cpFloat_t *)&a->w, w, 0); - vst_lane((cpFloat_t *)&b->w, w, 1); - - vst_lane((cpFloat_t *)&con->jBias, jbn_jn, 0); - vst_lane((cpFloat_t *)&con->jnAcc, jbn_jn, 1); - vst_lane((cpFloat_t *)&con->jtAcc, jt, 0); - } -} - -#endif - -//MARK: PThreads - -// Right now using more than 2 threads probably wont help your performance any. -// If you are using a ridiculous number of iterations it could help though. -#define MAX_THREADS 2 - -struct ThreadContext { - pthread_t thread; - cpHastySpace *space; - unsigned long thread_num; -}; - -typedef void (*cpHastySpaceWorkFunction)(cpSpace *space, unsigned long worker, unsigned long worker_count); - -struct cpHastySpace { - cpSpace space; - - // Number of worker threads (including the main thread) - unsigned long num_threads; - - // Number of worker threads currently executing. (also including the main thread) - unsigned long num_working; - - // Number of constraints (plus contacts) that must exist per step to start the worker threads. - unsigned long constraint_count_threshold; - - pthread_mutex_t mutex; - pthread_cond_t cond_work, cond_resume; - - // Work function to invoke. - cpHastySpaceWorkFunction work; - - struct ThreadContext workers[MAX_THREADS - 1]; -}; - -static void * -WorkerThreadLoop(struct ThreadContext *context) -{ - cpHastySpace *hasty = context->space; - - unsigned long thread = context->thread_num; - unsigned long num_threads = hasty->num_threads; - - for(;;){ - pthread_mutex_lock(&hasty->mutex); { - if(--hasty->num_working == 0){ - pthread_cond_signal(&hasty->cond_resume); - } - - pthread_cond_wait(&hasty->cond_work, &hasty->mutex); - } pthread_mutex_unlock(&hasty->mutex); - - cpHastySpaceWorkFunction func = hasty->work; - if(func){ - hasty->work(&hasty->space, thread, num_threads); - } else { - break; - } - } - - return NULL; -} - -static void -RunWorkers(cpHastySpace *hasty, cpHastySpaceWorkFunction func) -{ - hasty->num_working = hasty->num_threads - 1; - hasty->work = func; - - if(hasty->num_working > 0){ - pthread_mutex_lock(&hasty->mutex); { - pthread_cond_broadcast(&hasty->cond_work); - } pthread_mutex_unlock(&hasty->mutex); - - func((cpSpace *)hasty, 0, hasty->num_threads); - - pthread_mutex_lock(&hasty->mutex); { - if(hasty->num_working > 0){ - pthread_cond_wait(&hasty->cond_resume, &hasty->mutex); - } - } pthread_mutex_unlock(&hasty->mutex); - } else { - func((cpSpace *)hasty, 0, hasty->num_threads); - } - - hasty->work = NULL; -} - -static void -Solver(cpSpace *space, unsigned long worker, unsigned long worker_count) -{ - cpArray *constraints = space->constraints; - cpArray *arbiters = space->arbiters; - - cpFloat dt = space->curr_dt; - unsigned long iterations = (space->iterations + worker_count - 1)/worker_count; - - for(unsigned long i=0; inum; j++){ - cpArbiter *arb = (cpArbiter *)arbiters->arr[j]; - #ifdef __ARM_NEON__ - cpArbiterApplyImpulse_NEON(arb); - #else - cpArbiterApplyImpulse(arb); - #endif - } - - for(int j=0; jnum; j++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[j]; - constraint->klass->applyImpulse(constraint, dt); - } - } -} - -//MARK: Thread Management Functions - -static void -HaltThreads(cpHastySpace *hasty) -{ - pthread_mutex_t *mutex = &hasty->mutex; - pthread_mutex_lock(mutex); { - hasty->work = NULL; // NULL work function means break and exit - pthread_cond_broadcast(&hasty->cond_work); - } pthread_mutex_unlock(mutex); - - for(unsigned long i=0; i<(hasty->num_threads-1); i++){ - pthread_join(hasty->workers[i].thread, NULL); - } -} - -void -cpHastySpaceSetThreads(cpSpace *space, unsigned long threads) -{ -#if TARGET_IPHONE_SIMULATOR == 1 - // Individual values appear to be written non-atomically when compiled as debug for the simulator. - // No idea why, so threads are disabled. - threads = 1; -#endif - - cpHastySpace *hasty = (cpHastySpace *)space; - HaltThreads(hasty); - -#ifdef __APPLE__ - if(threads == 0){ - size_t size = sizeof(threads); - sysctlbyname("hw.ncpu", &threads, &size, NULL, 0); - } -#else - if(threads == 0) threads = 1; -#endif - - hasty->num_threads = (threads < MAX_THREADS ? threads : MAX_THREADS); - hasty->num_working = hasty->num_threads - 1; - - // Create the worker threads and wait for them to signal ready. - if(hasty->num_working > 0){ - pthread_mutex_lock(&hasty->mutex); - for(unsigned long i=0; i<(hasty->num_threads-1); i++){ - hasty->workers[i].space = hasty; - hasty->workers[i].thread_num = i + 1; - - pthread_create(&hasty->workers[i].thread, NULL, (void*(*)(void*))WorkerThreadLoop, &hasty->workers[i]); - } - - pthread_cond_wait(&hasty->cond_resume, &hasty->mutex); - pthread_mutex_unlock(&hasty->mutex); - } -} - -unsigned long -cpHastySpaceGetThreads(cpSpace *space) -{ - return ((cpHastySpace *)space)->num_threads; -} - -//MARK: Overriden cpSpace Functions. - -cpSpace * -cpHastySpaceNew(void) -{ - cpHastySpace *hasty = (cpHastySpace *)cpcalloc(1, sizeof(cpHastySpace)); - cpSpaceInit((cpSpace *)hasty); - - pthread_mutex_init(&hasty->mutex, NULL); - pthread_cond_init(&hasty->cond_work, NULL); - pthread_cond_init(&hasty->cond_resume, NULL); - - // TODO magic number, should test this more thoroughly. - hasty->constraint_count_threshold = 50; - - // Default to 1 thread for determinism. - hasty->num_threads = 1; - cpHastySpaceSetThreads((cpSpace *)hasty, 1); - - return (cpSpace *)hasty; -} - -void -cpHastySpaceFree(cpSpace *space) -{ - cpHastySpace *hasty = (cpHastySpace *)space; - - HaltThreads(hasty); - - pthread_mutex_destroy(&hasty->mutex); - pthread_cond_destroy(&hasty->cond_work); - pthread_cond_destroy(&hasty->cond_resume); - - cpSpaceFree(space); -} - -void -cpHastySpaceStep(cpSpace *space, cpFloat dt) -{ - // don't step if the timestep is 0! - if(dt == 0.0f) return; - - space->stamp++; - - cpFloat prev_dt = space->curr_dt; - space->curr_dt = dt; - - cpArray *bodies = space->dynamicBodies; - cpArray *constraints = space->constraints; - cpArray *arbiters = space->arbiters; - - // Reset and empty the arbiter list. - for(int i=0; inum; i++){ - cpArbiter *arb = (cpArbiter *)arbiters->arr[i]; - arb->state = CP_ARBITER_STATE_NORMAL; - - // If both bodies are awake, unthread the arbiter from the contact graph. - if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){ - cpArbiterUnthread(arb); - } - } - arbiters->num = 0; - - cpSpaceLock(space); { - // Integrate positions - for(int i=0; inum; i++){ - cpBody *body = (cpBody *)bodies->arr[i]; - body->position_func(body, dt); - } - - // Find colliding pairs. - cpSpacePushFreshContactBuffer(space); - cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL); - cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space); - } cpSpaceUnlock(space, cpFalse); - - // Rebuild the contact graph (and detect sleeping components if sleeping is enabled) - cpSpaceProcessComponents(space, dt); - - cpSpaceLock(space); { - // Clear out old cached arbiters and call separate callbacks - cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space); - - // Prestep the arbiters and constraints. - cpFloat slop = space->collisionSlop; - cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt); - for(int i=0; inum; i++){ - cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef); - } - - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - - cpConstraintPreSolveFunc preSolve = constraint->preSolve; - if(preSolve) preSolve(constraint, space); - - constraint->klass->preStep(constraint, dt); - } - - // Integrate velocities. - cpFloat damping = cpfpow(space->damping, dt); - cpVect gravity = space->gravity; - for(int i=0; inum; i++){ - cpBody *body = (cpBody *)bodies->arr[i]; - body->velocity_func(body, gravity, damping, dt); - } - - // Apply cached impulses - cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt); - for(int i=0; inum; i++){ - cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef); - } - - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - constraint->klass->applyCachedImpulse(constraint, dt_coef); - } - - // Run the impulse solver. - cpHastySpace *hasty = (cpHastySpace *)space; - if((unsigned long)(arbiters->num + constraints->num) > hasty->constraint_count_threshold){ - RunWorkers(hasty, Solver); - } else { - Solver(space, 0, 1); - } - - // Run the constraint post-solve callbacks - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - - cpConstraintPostSolveFunc postSolve = constraint->postSolve; - if(postSolve) postSolve(constraint, space); - } - - // run the post-solve callbacks - for(int i=0; inum; i++){ - cpArbiter *arb = (cpArbiter *) arbiters->arr[i]; - - cpCollisionHandler *handler = arb->handler; - handler->postSolveFunc(arb, space, handler->userData); - } - } cpSpaceUnlock(space, cpTrue); -} diff --git a/3rdparty/chipmunk/src/cpMarch.c b/3rdparty/chipmunk/src/cpMarch.c deleted file mode 100644 index 1ba0dabb4601..000000000000 --- a/3rdparty/chipmunk/src/cpMarch.c +++ /dev/null @@ -1,157 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -#include -#include -#include - -#include "chipmunk/chipmunk.h" -#include "chipmunk/cpMarch.h" - - -typedef void (*cpMarchCellFunc)( - cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d, - cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1, - cpMarchSegmentFunc segment, void *segment_data -); - -// The looping and sample caching code is shared between cpMarchHard() and cpMarchSoft(). -static void -cpMarchCells( - cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t, - cpMarchSegmentFunc segment, void *segment_data, - cpMarchSampleFunc sample, void *sample_data, - cpMarchCellFunc cell -){ - cpFloat x_denom = 1.0/(cpFloat)(x_samples - 1); - cpFloat y_denom = 1.0/(cpFloat)(y_samples - 1); - - // TODO range assertions and short circuit for 0 sized windows. - - // Keep a copy of the previous row to avoid double lookups. - cpFloat *buffer = (cpFloat *)cpcalloc(x_samples, sizeof(cpFloat)); - for(unsigned long i=0; it)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){ - case 0x1: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break; - case 0x2: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break; - case 0x3: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break; - case 0x4: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break; - case 0x5: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break; - case 0x6: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); - seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break; - case 0x7: seg(cpv(midlerp(x0,x1,c,d,t), y1), cpv(x1, midlerp(y0,y1,b,d,t)), segment, segment_data); break; - case 0x8: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break; - case 0x9: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); - seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break; - case 0xA: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break; - case 0xB: seg(cpv(x0, midlerp(y0,y1,a,c,t)), cpv(midlerp(x0,x1,c,d,t), y1), segment, segment_data); break; - case 0xC: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break; - case 0xD: seg(cpv(x1, midlerp(y0,y1,b,d,t)), cpv(midlerp(x0,x1,a,b,t), y0), segment, segment_data); break; - case 0xE: seg(cpv(midlerp(x0,x1,a,b,t), y0), cpv(x0, midlerp(y0,y1,a,c,t)), segment, segment_data); break; - default: break; // 0x0 and 0xF - } -} - -void -cpMarchSoft( - cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t, - cpMarchSegmentFunc segment, void *segment_data, - cpMarchSampleFunc sample, void *sample_data -){ - cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellSoft); -} - - -// TODO should flip this around eventually. -static inline void -segs(cpVect a, cpVect b, cpVect c, cpMarchSegmentFunc f, void *data) -{ - seg(b, c, f, data); - seg(a, b, f, data); -} - -static void -cpMarchCellHard( - cpFloat t, cpFloat a, cpFloat b, cpFloat c, cpFloat d, - cpFloat x0, cpFloat x1, cpFloat y0, cpFloat y1, - cpMarchSegmentFunc segment, void *segment_data -){ - // midpoints - cpFloat xm = cpflerp(x0, x1, 0.5f); - cpFloat ym = cpflerp(y0, y1, 0.5f); - - switch((a>t)<<0 | (b>t)<<1 | (c>t)<<2 | (d>t)<<3){ - case 0x1: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break; - case 0x2: segs(cpv(xm, y0), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break; - case 0x3: seg(cpv(x0, ym), cpv(x1, ym), segment, segment_data); break; - case 0x4: segs(cpv(xm, y1), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break; - case 0x5: seg(cpv(xm, y1), cpv(xm, y0), segment, segment_data); break; - case 0x6: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data); - segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break; - case 0x7: segs(cpv(xm, y1), cpv(xm, ym), cpv(x1, ym), segment, segment_data); break; - case 0x8: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break; - case 0x9: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); - segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break; - case 0xA: seg(cpv(xm, y0), cpv(xm, y1), segment, segment_data); break; - case 0xB: segs(cpv(x0, ym), cpv(xm, ym), cpv(xm, y1), segment, segment_data); break; - case 0xC: seg(cpv(x1, ym), cpv(x0, ym), segment, segment_data); break; - case 0xD: segs(cpv(x1, ym), cpv(xm, ym), cpv(xm, y0), segment, segment_data); break; - case 0xE: segs(cpv(xm, y0), cpv(xm, ym), cpv(x0, ym), segment, segment_data); break; - default: break; // 0x0 and 0xF - } -} - -void -cpMarchHard( - cpBB bb, unsigned long x_samples, unsigned long y_samples, cpFloat t, - cpMarchSegmentFunc segment, void *segment_data, - cpMarchSampleFunc sample, void *sample_data -){ - cpMarchCells(bb, x_samples, y_samples, t, segment, segment_data, sample, sample_data, cpMarchCellHard); -} diff --git a/3rdparty/chipmunk/src/cpPinJoint.c b/3rdparty/chipmunk/src/cpPinJoint.c deleted file mode 100644 index 545e78bf8b50..000000000000 --- a/3rdparty/chipmunk/src/cpPinJoint.c +++ /dev/null @@ -1,172 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpPinJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog)); - joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog)); - - cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); - cpFloat dist = cpvlength(delta); - joint->n = cpvmult(delta, 1.0f/(dist ? dist : (cpFloat)INFINITY)); - - // calculate mass normal - joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n); - - // calculate bias velocity - cpFloat maxBias = joint->constraint.maxBias; - joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*(dist - joint->dist)/dt, -maxBias, maxBias); -} - -static void -applyCachedImpulse(cpPinJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef); - apply_impulses(a, b, joint->r1, joint->r2, j); -} - -static void -applyImpulse(cpPinJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - cpVect n = joint->n; - - // compute relative velocity - cpFloat vrn = normal_relative_velocity(a, b, joint->r1, joint->r2, n); - - cpFloat jnMax = joint->constraint.maxForce*dt; - - // compute normal impulse - cpFloat jn = (joint->bias - vrn)*joint->nMass; - cpFloat jnOld = joint->jnAcc; - joint->jnAcc = cpfclamp(jnOld + jn, -jnMax, jnMax); - jn = joint->jnAcc - jnOld; - - // apply impulse - apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn)); -} - -static cpFloat -getImpulse(cpPinJoint *joint) -{ - return cpfabs(joint->jnAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - - -cpPinJoint * -cpPinJointAlloc(void) -{ - return (cpPinJoint *)cpcalloc(1, sizeof(cpPinJoint)); -} - -cpPinJoint * -cpPinJointInit(cpPinJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->anchorA = anchorA; - joint->anchorB = anchorB; - - // STATIC_BODY_CHECK - cpVect p1 = (a ? cpTransformPoint(a->transform, anchorA) : anchorA); - cpVect p2 = (b ? cpTransformPoint(b->transform, anchorB) : anchorB); - joint->dist = cpvlength(cpvsub(p2, p1)); - - cpAssertWarn(joint->dist > 0.0, "You created a 0 length pin joint. A pivot joint will be much more stable."); - - joint->jnAcc = 0.0f; - - return joint; -} - -cpConstraint * -cpPinJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB) -{ - return (cpConstraint *)cpPinJointInit(cpPinJointAlloc(), a, b, anchorA, anchorB); -} - -cpBool -cpConstraintIsPinJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpVect -cpPinJointGetAnchorA(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - return ((cpPinJoint *)constraint)->anchorA; -} - -void -cpPinJointSetAnchorA(cpConstraint *constraint, cpVect anchorA) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - cpConstraintActivateBodies(constraint); - ((cpPinJoint *)constraint)->anchorA = anchorA; -} - -cpVect -cpPinJointGetAnchorB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - return ((cpPinJoint *)constraint)->anchorB; -} - -void -cpPinJointSetAnchorB(cpConstraint *constraint, cpVect anchorB) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - cpConstraintActivateBodies(constraint); - ((cpPinJoint *)constraint)->anchorB = anchorB; -} - -cpFloat -cpPinJointGetDist(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - return ((cpPinJoint *)constraint)->dist; -} - -void -cpPinJointSetDist(cpConstraint *constraint, cpFloat dist) -{ - cpAssertHard(cpConstraintIsPinJoint(constraint), "Constraint is not a pin joint."); - cpConstraintActivateBodies(constraint); - ((cpPinJoint *)constraint)->dist = dist; -} diff --git a/3rdparty/chipmunk/src/cpPivotJoint.c b/3rdparty/chipmunk/src/cpPivotJoint.c deleted file mode 100644 index e45ba072bce5..000000000000 --- a/3rdparty/chipmunk/src/cpPivotJoint.c +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpPivotJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog)); - joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog)); - - // Calculate mass tensor - joint-> k = k_tensor(a, b, joint->r1, joint->r2); - - // calculate bias velocity - cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); - joint->bias = cpvclamp(cpvmult(delta, -bias_coef(joint->constraint.errorBias, dt)/dt), joint->constraint.maxBias); -} - -static void -applyCachedImpulse(cpPivotJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - apply_impulses(a, b, joint->r1, joint->r2, cpvmult(joint->jAcc, dt_coef)); -} - -static void -applyImpulse(cpPivotJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpVect r1 = joint->r1; - cpVect r2 = joint->r2; - - // compute relative velocity - cpVect vr = relative_velocity(a, b, r1, r2); - - // compute normal impulse - cpVect j = cpMat2x2Transform(joint->k, cpvsub(joint->bias, vr)); - cpVect jOld = joint->jAcc; - joint->jAcc = cpvclamp(cpvadd(joint->jAcc, j), joint->constraint.maxForce*dt); - j = cpvsub(joint->jAcc, jOld); - - // apply impulse - apply_impulses(a, b, joint->r1, joint->r2, j); -} - -static cpFloat -getImpulse(cpConstraint *joint) -{ - return cpvlength(((cpPivotJoint *)joint)->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpPivotJoint * -cpPivotJointAlloc(void) -{ - return (cpPivotJoint *)cpcalloc(1, sizeof(cpPivotJoint)); -} - -cpPivotJoint * -cpPivotJointInit(cpPivotJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->anchorA = anchorA; - joint->anchorB = anchorB; - - joint->jAcc = cpvzero; - - return joint; -} - -cpConstraint * -cpPivotJointNew2(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB) -{ - return (cpConstraint *)cpPivotJointInit(cpPivotJointAlloc(), a, b, anchorA, anchorB); -} - -cpConstraint * -cpPivotJointNew(cpBody *a, cpBody *b, cpVect pivot) -{ - cpVect anchorA = (a ? cpBodyWorldToLocal(a, pivot) : pivot); - cpVect anchorB = (b ? cpBodyWorldToLocal(b, pivot) : pivot); - return cpPivotJointNew2(a, b, anchorA, anchorB); -} - -cpBool -cpConstraintIsPivotJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpVect -cpPivotJointGetAnchorA(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint."); - return ((cpPivotJoint *)constraint)->anchorA; -} - -void -cpPivotJointSetAnchorA(cpConstraint *constraint, cpVect anchorA) -{ - cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint."); - cpConstraintActivateBodies(constraint); - ((cpPivotJoint *)constraint)->anchorA = anchorA; -} - -cpVect -cpPivotJointGetAnchorB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint."); - return ((cpPivotJoint *)constraint)->anchorB; -} - -void -cpPivotJointSetAnchorB(cpConstraint *constraint, cpVect anchorB) -{ - cpAssertHard(cpConstraintIsPivotJoint(constraint), "Constraint is not a pivot joint."); - cpConstraintActivateBodies(constraint); - ((cpPivotJoint *)constraint)->anchorB = anchorB; -} diff --git a/3rdparty/chipmunk/src/cpPolyShape.c b/3rdparty/chipmunk/src/cpPolyShape.c deleted file mode 100644 index 554a7f8f313c..000000000000 --- a/3rdparty/chipmunk/src/cpPolyShape.c +++ /dev/null @@ -1,324 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/chipmunk_unsafe.h" - -cpPolyShape * -cpPolyShapeAlloc(void) -{ - return (cpPolyShape *)cpcalloc(1, sizeof(cpPolyShape)); -} - -static void -cpPolyShapeDestroy(cpPolyShape *poly) -{ - if(poly->count > CP_POLY_SHAPE_INLINE_ALLOC){ - cpfree(poly->planes); - } -} - -static cpBB -cpPolyShapeCacheData(cpPolyShape *poly, cpTransform transform) -{ - int count = poly->count; - struct cpSplittingPlane *dst = poly->planes; - struct cpSplittingPlane *src = dst + count; - - cpFloat l = (cpFloat)INFINITY, r = -(cpFloat)INFINITY; - cpFloat b = (cpFloat)INFINITY, t = -(cpFloat)INFINITY; - - for(int i=0; ir; - return (poly->shape.bb = cpBBNew(l - radius, b - radius, r + radius, t + radius)); -} - -static void -cpPolyShapePointQuery(cpPolyShape *poly, cpVect p, cpPointQueryInfo *info){ - int count = poly->count; - struct cpSplittingPlane *planes = poly->planes; - cpFloat r = poly->r; - - cpVect v0 = planes[count - 1].v0; - cpFloat minDist = INFINITY; - cpVect closestPoint = cpvzero; - cpVect closestNormal = cpvzero; - cpBool outside = cpFalse; - - for(int i=0; i 0.0f); - - cpVect closest = cpClosetPointOnSegment(p, v0, v1); - - cpFloat dist = cpvdist(p, closest); - if(dist < minDist){ - minDist = dist; - closestPoint = closest; - closestNormal = planes[i].n; - } - - v0 = v1; - } - - cpFloat dist = (outside ? minDist : -minDist); - cpVect g = cpvmult(cpvsub(p, closestPoint), 1.0f/dist); - - info->shape = (cpShape *)poly; - info->point = cpvadd(closestPoint, cpvmult(g, r)); - info->distance = dist - r; - - // Use the normal of the closest segment if the distance is small. - info->gradient = (minDist > MAGIC_EPSILON ? g : closestNormal); -} - -static void -cpPolyShapeSegmentQuery(cpPolyShape *poly, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info) -{ - struct cpSplittingPlane *planes = poly->planes; - int count = poly->count; - cpFloat r = poly->r; - cpFloat rsum = r + r2; - - for(int i=0; ishape = (cpShape *)poly; - info->point = cpvsub(cpvlerp(a, b, t), cpvmult(n, r2)); - info->normal = n; - info->alpha = t; - } - } - - // Also check against the beveled vertexes. - if(rsum > 0.0f){ - for(int i=0; ishape, planes[i].v0, r, a, b, r2, &circle_info); - if(circle_info.alpha < info->alpha) (*info) = circle_info; - } - } -} - -static void -SetVerts(cpPolyShape *poly, int count, const cpVect *verts) -{ - poly->count = count; - if(count <= CP_POLY_SHAPE_INLINE_ALLOC){ - poly->planes = poly->_planes; - } else { - poly->planes = (struct cpSplittingPlane *)cpcalloc(2*count, sizeof(struct cpSplittingPlane)); - } - - for(int i=0; iplanes[i + count].v0 = b; - poly->planes[i + count].n = n; - } -} - -static struct cpShapeMassInfo -cpPolyShapeMassInfo(cpFloat mass, int count, const cpVect *verts, cpFloat radius) -{ - // TODO moment is approximate due to radius. - - cpVect centroid = cpCentroidForPoly(count, verts); - struct cpShapeMassInfo info = { - mass, cpMomentForPoly(1.0f, count, verts, cpvneg(centroid), radius), - centroid, - cpAreaForPoly(count, verts, radius), - }; - - return info; -} - -static const cpShapeClass polyClass = { - CP_POLY_SHAPE, - (cpShapeCacheDataImpl)cpPolyShapeCacheData, - (cpShapeDestroyImpl)cpPolyShapeDestroy, - (cpShapePointQueryImpl)cpPolyShapePointQuery, - (cpShapeSegmentQueryImpl)cpPolyShapeSegmentQuery, -}; - -cpPolyShape * -cpPolyShapeInit(cpPolyShape *poly, cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius) -{ - cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect)); - - // Transform the verts before building the hull in case of a negative scale. - for(int i=0; ir = radius; - - return poly; -} - -cpShape * -cpPolyShapeNew(cpBody *body, int count, const cpVect *verts, cpTransform transform, cpFloat radius) -{ - return (cpShape *)cpPolyShapeInit(cpPolyShapeAlloc(), body, count, verts, transform, radius); -} - -cpShape * -cpPolyShapeNewRaw(cpBody *body, int count, const cpVect *verts, cpFloat radius) -{ - return (cpShape *)cpPolyShapeInitRaw(cpPolyShapeAlloc(), body, count, verts, radius); -} - -cpPolyShape * -cpBoxShapeInit(cpPolyShape *poly, cpBody *body, cpFloat width, cpFloat height, cpFloat radius) -{ - cpFloat hw = width/2.0f; - cpFloat hh = height/2.0f; - - return cpBoxShapeInit2(poly, body, cpBBNew(-hw, -hh, hw, hh), radius); -} - -cpPolyShape * -cpBoxShapeInit2(cpPolyShape *poly, cpBody *body, cpBB box, cpFloat radius) -{ - cpVect verts[4] = { - cpv(box.r, box.b), - cpv(box.r, box.t), - cpv(box.l, box.t), - cpv(box.l, box.b), - }; - - return cpPolyShapeInitRaw(poly, body, 4, verts, radius); -} - -cpShape * -cpBoxShapeNew(cpBody *body, cpFloat width, cpFloat height, cpFloat radius) -{ - return (cpShape *)cpBoxShapeInit(cpPolyShapeAlloc(), body, width, height, radius); -} - -cpShape * -cpBoxShapeNew2(cpBody *body, cpBB box, cpFloat radius) -{ - return (cpShape *)cpBoxShapeInit2(cpPolyShapeAlloc(), body, box, radius); -} - -int -cpPolyShapeGetCount(const cpShape *shape) -{ - cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape."); - return ((cpPolyShape *)shape)->count; -} - -cpVect -cpPolyShapeGetVert(const cpShape *shape, int i) -{ - cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape."); - - int count = cpPolyShapeGetCount(shape); - cpAssertHard(0 <= i && i < count, "Index out of range."); - - return ((cpPolyShape *)shape)->planes[i + count].v0; -} - -cpFloat -cpPolyShapeGetRadius(const cpShape *shape) -{ - cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape."); - return ((cpPolyShape *)shape)->r; -} - -// Unsafe API (chipmunk_unsafe.h) - -void -cpPolyShapeSetVerts(cpShape *shape, int count, cpVect *verts, cpTransform transform) -{ - cpVect *hullVerts = (cpVect *)alloca(count*sizeof(cpVect)); - - // Transform the verts before building the hull in case of a negative scale. - for(int i=0; iklass == &polyClass, "Shape is not a poly shape."); - cpPolyShape *poly = (cpPolyShape *)shape; - cpPolyShapeDestroy(poly); - - SetVerts(poly, count, verts); - - cpFloat mass = shape->massInfo.m; - shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, count, verts, poly->r); - if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} - -void -cpPolyShapeSetRadius(cpShape *shape, cpFloat radius) -{ - cpAssertHard(shape->klass == &polyClass, "Shape is not a poly shape."); - cpPolyShape *poly = (cpPolyShape *)shape; - poly->r = radius; - - - // TODO radius is not handled by moment/area -// cpFloat mass = shape->massInfo.m; -// shape->massInfo = cpPolyShapeMassInfo(shape->massInfo.m, poly->count, poly->verts, poly->r); -// if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} diff --git a/3rdparty/chipmunk/src/cpPolyline.c b/3rdparty/chipmunk/src/cpPolyline.c deleted file mode 100644 index 5b375348d4ea..000000000000 --- a/3rdparty/chipmunk/src/cpPolyline.c +++ /dev/null @@ -1,652 +0,0 @@ -// Copyright 2013 Howling Moon Software. All rights reserved. -// See http://chipmunk2d.net/legal.php for more information. - -#include -#include -#include -#include - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/cpPolyline.h" - - -static inline int Next(int i, int count){return (i+1)%count;} - -//MARK: Polylines - -#define DEFAULT_POLYLINE_CAPACITY 16 - -static int -cpPolylineSizeForCapacity(int capacity) -{ - return sizeof(cpPolyline) + capacity*sizeof(cpVect); -} - -static cpPolyline * -cpPolylineMake(int capacity) -{ - capacity = (capacity > DEFAULT_POLYLINE_CAPACITY ? capacity : DEFAULT_POLYLINE_CAPACITY); - - cpPolyline *line = (cpPolyline *)cpcalloc(1, cpPolylineSizeForCapacity(capacity)); - line->count = 0; - line->capacity = capacity; - - return line; -} - -static cpPolyline * -cpPolylineMake2(int capacity, cpVect a, cpVect b) -{ - cpPolyline *line = cpPolylineMake(capacity); - line->count = 2; - line->verts[0] = a; - line->verts[1] = b; - - return line; -} - -static cpPolyline * -cpPolylineShrink(cpPolyline *line) -{ - line->capacity = line->count; - return (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(line->count)); -} - -void -cpPolylineFree(cpPolyline *line) -{ - cpfree(line); -} - -// Grow the allocated memory for a polyline. -static cpPolyline * -cpPolylineGrow(cpPolyline *line, int count) -{ - line->count += count; - - int capacity = line->capacity; - while(line->count > capacity) capacity *= 2; - - if(line->capacity < capacity){ - line->capacity = capacity; - line = (cpPolyline*) cprealloc(line, cpPolylineSizeForCapacity(capacity)); - } - - return line; -} - -// Push v onto the end of line. -static cpPolyline * -cpPolylinePush(cpPolyline *line, cpVect v) -{ - int count = line->count; - line = cpPolylineGrow(line, 1); - line->verts[count] = v; - - return line; -} - -// Push v onto the beginning of line. -static cpPolyline * -cpPolylineEnqueue(cpPolyline *line, cpVect v) -{ - // TODO could optimize this to grow in both directions. - // Probably doesn't matter though. - int count = line->count; - line = cpPolylineGrow(line, 1); - memmove(line->verts + 1, line->verts, count*sizeof(cpVect)); - line->verts[0] = v; - - return line; -} - -// Returns true if the polyline starts and ends with the same vertex. -cpBool -cpPolylineIsClosed(cpPolyline *line) -{ - return (line->count > 1 && cpveql(line->verts[0], line->verts[line->count-1])); -} - -// Check if a cpPolyline is longer than a certain length -// Takes a range which can wrap around if the polyline is looped. -static cpBool -cpPolylineIsShort(cpVect *points, int count, int start, int end, cpFloat min) -{ - cpFloat length = 0.0f; - for(int i=start; i!=end; i=Next(i, count)){ - length += cpvdist(points[i], points[Next(i, count)]); - if(length > min) return cpFalse; - } - - return cpTrue; -} - -//MARK: Polyline Simplification - -static inline cpFloat -Sharpness(cpVect a, cpVect b, cpVect c) -{ - // TODO could speed this up by caching the normals instead of calculating each twice. - return cpvdot(cpvnormalize(cpvsub(a, b)), cpvnormalize(cpvsub(c, b))); -} - -// Join similar adjacent line segments together. Works well for hard edged shapes. -// 'tol' is the minimum anglular difference in radians of a vertex. -cpPolyline * -cpPolylineSimplifyVertexes(cpPolyline *line, cpFloat tol) -{ - cpPolyline *reduced = cpPolylineMake2(0, line->verts[0], line->verts[1]); - - cpFloat minSharp = -cpfcos(tol); - - for(int i=2; icount; i++){ - cpVect vert = line->verts[i]; - cpFloat sharp = Sharpness(reduced->verts[reduced->count - 2], reduced->verts[reduced->count - 1], vert); - - if(sharp <= minSharp){ - reduced->verts[reduced->count - 1] = vert; - } else { - reduced = cpPolylinePush(reduced, vert); - } - } - - if( - cpPolylineIsClosed(line) && - Sharpness(reduced->verts[reduced->count - 2], reduced->verts[0], reduced->verts[1]) < minSharp - ){ - reduced->verts[0] = reduced->verts[reduced->count - 2]; - reduced->count--; - } - - // TODO shrink - return reduced; -} - -// Recursive function used by cpPolylineSimplifyCurves(). -static cpPolyline * -DouglasPeucker( - cpVect *verts, cpPolyline *reduced, - int length, int start, int end, - cpFloat min, cpFloat tol -){ - // Early exit if the points are adjacent - if((end - start + length)%length < 2) return reduced; - - cpVect a = verts[start]; - cpVect b = verts[end]; - - // Check if the length is below the threshold - if(cpvnear(a, b, min) && cpPolylineIsShort(verts, length, start, end, min)) return reduced; - - // Find the maximal vertex to split and recurse on - cpFloat max = 0.0; - int maxi = start; - - cpVect n = cpvnormalize(cpvperp(cpvsub(b, a))); - cpFloat d = cpvdot(n, a); - - for(int i=Next(start, length); i!=end; i=Next(i, length)){ - cpFloat dist = fabs(cpvdot(n, verts[i]) - d); - - if(dist > max){ - max = dist; - maxi = i; - } - } - - if(max > tol){ - reduced = DouglasPeucker(verts, reduced, length, start, maxi, min, tol); - reduced = cpPolylinePush(reduced, verts[maxi]); - reduced = DouglasPeucker(verts, reduced, length, maxi, end, min, tol); - } - - return reduced; -} - -// Recursively reduce the vertex count on a polyline. Works best for smooth shapes. -// 'tol' is the maximum error for the reduction. -// The reduced polyline will never be farther than this distance from the original polyline. -cpPolyline * -cpPolylineSimplifyCurves(cpPolyline *line, cpFloat tol) -{ - cpPolyline *reduced = cpPolylineMake(line->count); - - cpFloat min = tol/2.0f; - - if(cpPolylineIsClosed(line)){ - int start, end; - cpLoopIndexes(line->verts, line->count - 1, &start, &end); - - reduced = cpPolylinePush(reduced, line->verts[start]); - reduced = DouglasPeucker(line->verts, reduced, line->count - 1, start, end, min, tol); - reduced = cpPolylinePush(reduced, line->verts[end]); - reduced = DouglasPeucker(line->verts, reduced, line->count - 1, end, start, min, tol); - reduced = cpPolylinePush(reduced, line->verts[start]); - } else { - reduced = cpPolylinePush(reduced, line->verts[0]); - reduced = DouglasPeucker(line->verts, reduced, line->count, 0, line->count - 1, min, tol); - reduced = cpPolylinePush(reduced, line->verts[line->count - 1]); - } - - return cpPolylineShrink(reduced); -} - -//MARK: Polyline Sets - -cpPolylineSet * -cpPolylineSetAlloc(void) -{ - return (cpPolylineSet *)cpcalloc(1, sizeof(cpPolylineSet)); -} - -cpPolylineSet * -cpPolylineSetInit(cpPolylineSet *set) -{ - set->count = 0; - set->capacity = 8; - set->lines = (cpPolyline**) cpcalloc(set->capacity, sizeof(cpPolyline)); - - return set; -} - - -cpPolylineSet * -cpPolylineSetNew(void) -{ - return cpPolylineSetInit(cpPolylineSetAlloc()); -} - -void -cpPolylineSetDestroy(cpPolylineSet *set, cpBool freePolylines) -{ - if(freePolylines){ - for(int i=0; icount; i++){ - cpPolylineFree(set->lines[i]); - } - } - - cpfree(set->lines); -} - - -void -cpPolylineSetFree(cpPolylineSet *set, cpBool freePolylines) -{ - if(set){ - cpPolylineSetDestroy(set, freePolylines); - cpfree(set); - } -} - -// Find the polyline that ends with v. -static int -cpPolylineSetFindEnds(cpPolylineSet *set, cpVect v){ - int count = set->count; - cpPolyline **lines = set->lines; - - for(int i=0; iverts[line->count - 1], v)) return i; - } - - return -1; -} - -// Find the polyline that starts with v. -static int -cpPolylineSetFindStarts(cpPolylineSet *set, cpVect v){ - int count = set->count; - cpPolyline **lines = set->lines; - - for(int i=0; iverts[0], v)) return i; - } - - return -1; -} - -// Add a new polyline to a polyline set. -static void -cpPolylineSetPush(cpPolylineSet *set, cpPolyline *line) -{ - // grow set - set->count++; - if(set->count > set->capacity){ - set->capacity *= 2; - set->lines = (cpPolyline**) cprealloc(set->lines, set->capacity*sizeof(cpPolyline)); - } - - set->lines[set->count - 1] = line; -} - -// Add a new polyline to a polyline set. -static void -cpPolylineSetAdd(cpPolylineSet *set, cpVect v0, cpVect v1) -{ - cpPolylineSetPush(set, cpPolylineMake2(DEFAULT_POLYLINE_CAPACITY, v0, v1)); -} - -// Join two cpPolylines in a polyline set together. -static void -cpPolylineSetJoin(cpPolylineSet *set, int before, int after) -{ - cpPolyline *lbefore = set->lines[before]; - cpPolyline *lafter = set->lines[after]; - - // append - int count = lbefore->count; - lbefore = cpPolylineGrow(lbefore, lafter->count); - memmove(lbefore->verts + count, lafter->verts, lafter->count*sizeof(cpVect)); - set->lines[before] = lbefore; - - // delete lafter - set->count--; - cpPolylineFree(set->lines[after]); - set->lines[after] = set->lines[set->count]; -} - -// Add a segment to a polyline set. -// A segment will either start a new polyline, join two others, or add to or loop an existing polyline. -void -cpPolylineSetCollectSegment(cpVect v0, cpVect v1, cpPolylineSet *lines) -{ - int before = cpPolylineSetFindEnds(lines, v0); - int after = cpPolylineSetFindStarts(lines, v1); - - if(before >= 0 && after >= 0){ - if(before == after){ - // loop by pushing v1 onto before - lines->lines[before] = cpPolylinePush(lines->lines[before], v1); - } else { - // join before and after - cpPolylineSetJoin(lines, before, after); - } - } else if(before >= 0){ - // push v1 onto before - lines->lines[before] = cpPolylinePush(lines->lines[before], v1); - } else if(after >= 0){ - // enqueue v0 onto after - lines->lines[after] = cpPolylineEnqueue(lines->lines[after], v0); - } else { - // create new line from v0 and v1 - cpPolylineSetAdd(lines, v0, v1); - } -} - -//MARK: Convex Hull Functions - -cpPolyline * -cpPolylineToConvexHull(cpPolyline *line, cpFloat tol) -{ - cpPolyline *hull = cpPolylineMake(line->count + 1); - hull->count = cpConvexHull(line->count, line->verts, hull->verts, NULL, tol); - hull = cpPolylinePush(hull, hull->verts[0]); - - return cpPolylineShrink(hull); -} - -//MARK: Approximate Concave Decompostition - -struct Notch { - int i; - cpFloat d; - cpVect v; - cpVect n; -}; - -static cpFloat -FindSteiner(int count, cpVect *verts, struct Notch notch) -{ - cpFloat min = INFINITY; - cpFloat feature = -1.0; - - for(int i=1; i= 0.0 && dist <= min){ - min = dist; - feature = index + t; - } - } - } - - return feature; -} - -//static cpFloat -//FindSteiner2(cpVect *verts, int count, struct Notch notch) -//{ -// cpVect a = verts[(notch.i + count - 1)%count]; -// cpVect b = verts[(notch.i + 1)%count]; -// cpVect n = cpvnormalize(cpvadd(cpvnormalize(cpvsub(notch.v, a)), cpvnormalize(cpvsub(notch.v, b)))); -// -// cpFloat min = INFINITY; -// cpFloat feature = -1.0; -// -// for(int i=1; i= 0.0 && dist <= min){ -// min = dist; -// feature = index + t; -// } -// } -// } -// -// cpAssertSoft(feature >= 0.0, "No closest features detected. This is likely due to a self intersecting polygon."); -// return feature; -//} - -//struct Range {cpFloat min, max;}; -//static inline struct Range -//clip_range(cpVect delta_a, cpVect delta_b, cpVect clip) -//{ -// cpFloat da = cpvcross(delta_a, clip); -// cpFloat db = cpvcross(delta_b, clip); -// cpFloat clamp = da/(da - db); -// if(da > db){ -// return (struct Range){-INFINITY, clamp}; -// } else if(da < db){ -// return (struct Range){clamp, INFINITY}; -// } else { -// return (struct Range){-INFINITY, INFINITY}; -// } -//} -// -//static cpFloat -//FindSteiner3(cpVect *verts, int count, struct Notch notch) -//{ -// cpFloat min = INFINITY; -// cpFloat feature = -1.0; -// -// cpVect support_a = verts[(notch.i - 1 + count)%count]; -// cpVect support_b = verts[(notch.i + 1)%count]; -// -// cpVect clip_a = cpvlerp(support_a, support_b, 0.1); -// cpVect clip_b = cpvlerp(support_b, support_b, 0.9); -// -// for(int i=1; i 0.0){ -// struct Range range1 = clip_range(delta_a, delta_b, cpvsub(notch.v, clip_a)); -// struct Range range2 = clip_range(delta_a, delta_b, cpvsub(clip_b, notch.v)); -// -// cpFloat min_t = cpfmax(0.0, cpfmax(range1.min, range2.min)); -// cpFloat max_t = cpfmin(1.0, cpfmin(range1.max, range2.max)); -// -// // Ignore if the segment has been completely clipped away. -// if(min_t < max_t){ -// cpVect seg_delta = cpvsub(seg_b, seg_a); -// cpFloat closest_t = cpfclamp(cpvdot(seg_delta, cpvsub(notch.v, seg_a))/cpvlengthsq(seg_delta), min_t, max_t); -// cpVect closest = cpvlerp(seg_a, seg_b, closest_t); -// -// cpFloat dist = cpvdistsq(notch.v, closest); -// if(dist < min){ -// min = dist; -// feature = index + closest_t; -// } -// } -// } -// } -// -// cpAssertWarn(feature >= 0.0, "Internal Error: No closest features detected."); -// return feature; -//} - -//static cpBool -//VertexUnobscured(int count, cpVect *verts, int index, int notch_i) -//{ -// cpVect v = verts[notch_i]; -// cpVect n = cpvnormalize(cpvsub(verts[index], v)); -// -// for(int i=0; i= 0.0, "No closest features detected. This is likely due to a self intersecting polygon."); -// return feature; -//} - -static struct Notch -DeepestNotch(int count, cpVect *verts, int hullCount, cpVect *hullVerts, int first, cpFloat tol) -{ - struct Notch notch = {}; - int j = Next(first, count); - - for(int i=0; i notch.d){ - notch.d = depth; - notch.i = j; - notch.v = v; - notch.n = n; - } - - j = Next(j, count); - v = verts[j]; - } - - j = Next(j, count); - } - - return notch; -} - -static inline int IMAX(int a, int b){return (a > b ? a : b);} - -static void -ApproximateConcaveDecomposition(cpVect *verts, int count, cpFloat tol, cpPolylineSet *set) -{ - int first; - cpVect *hullVerts = (cpVect*) alloca(count*sizeof(cpVect)); - int hullCount = cpConvexHull(count, verts, hullVerts, &first, 0.0); - - if(hullCount != count){ - struct Notch notch = DeepestNotch(count, verts, hullCount, hullVerts, first, tol); - - if(notch.d > tol){ - cpFloat steiner_it = FindSteiner(count, verts, notch); - - if(steiner_it >= 0.0){ - int steiner_i = (int)steiner_it; - cpVect steiner = cpvlerp(verts[steiner_i], verts[Next(steiner_i, count)], steiner_it - steiner_i); - - // Vertex counts NOT including the steiner point. - int sub1_count = (steiner_i - notch.i + count)%count + 1; - int sub2_count = count - (steiner_i - notch.i + count)%count; - cpVect *scratch = (cpVect*) alloca((IMAX(sub1_count, sub2_count) + 1)*sizeof(cpVect)); - - for(int i=0; iverts, hullVerts, hullCount*sizeof(cpVect)); - hull->verts[hullCount] = hullVerts[0]; - hull->count = hullCount + 1; - - cpPolylineSetPush(set, hull); -} - -cpPolylineSet * -cpPolylineConvexDecomposition_BETA(cpPolyline *line, cpFloat tol) -{ - cpAssertSoft(cpPolylineIsClosed(line), "Cannot decompose an open polygon."); - cpAssertSoft(cpAreaForPoly(line->count, line->verts, 0.0) >= 0.0, "Winding is backwards. (Are you passing a hole?)"); - - cpPolylineSet *set = cpPolylineSetNew(); - ApproximateConcaveDecomposition(line->verts, line->count - 1, tol, set); - - return set; -} diff --git a/3rdparty/chipmunk/src/cpRatchetJoint.c b/3rdparty/chipmunk/src/cpRatchetJoint.c deleted file mode 100644 index b3c9687e3562..000000000000 --- a/3rdparty/chipmunk/src/cpRatchetJoint.c +++ /dev/null @@ -1,179 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpRatchetJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat angle = joint->angle; - cpFloat phase = joint->phase; - cpFloat ratchet = joint->ratchet; - - cpFloat delta = b->a - a->a; - cpFloat diff = angle - delta; - cpFloat pdist = 0.0f; - - if(diff*ratchet > 0.0f){ - pdist = diff; - } else { - joint->angle = cpffloor((delta - phase)/ratchet)*ratchet + phase; - } - - // calculate moment of inertia coefficient. - joint->iSum = 1.0f/(a->i_inv + b->i_inv); - - // calculate bias velocity - cpFloat maxBias = joint->constraint.maxBias; - joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); - - // If the bias is 0, the joint is not at a limit. Reset the impulse. - if(!joint->bias) joint->jAcc = 0.0f; -} - -static void -applyCachedImpulse(cpRatchetJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat j = joint->jAcc*dt_coef; - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static void -applyImpulse(cpRatchetJoint *joint, cpFloat dt) -{ - if(!joint->bias) return; // early exit - - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // compute relative rotational velocity - cpFloat wr = b->w - a->w; - cpFloat ratchet = joint->ratchet; - - cpFloat jMax = joint->constraint.maxForce*dt; - - // compute normal impulse - cpFloat j = -(joint->bias + wr)*joint->iSum; - cpFloat jOld = joint->jAcc; - joint->jAcc = cpfclamp((jOld + j)*ratchet, 0.0f, jMax*cpfabs(ratchet))/ratchet; - j = joint->jAcc - jOld; - - // apply impulse - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static cpFloat -getImpulse(cpRatchetJoint *joint) -{ - return cpfabs(joint->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpRatchetJoint * -cpRatchetJointAlloc(void) -{ - return (cpRatchetJoint *)cpcalloc(1, sizeof(cpRatchetJoint)); -} - -cpRatchetJoint * -cpRatchetJointInit(cpRatchetJoint *joint, cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->angle = 0.0f; - joint->phase = phase; - joint->ratchet = ratchet; - - // STATIC_BODY_CHECK - joint->angle = (b ? b->a : 0.0f) - (a ? a->a : 0.0f); - - return joint; -} - -cpConstraint * -cpRatchetJointNew(cpBody *a, cpBody *b, cpFloat phase, cpFloat ratchet) -{ - return (cpConstraint *)cpRatchetJointInit(cpRatchetJointAlloc(), a, b, phase, ratchet); -} - -cpBool -cpConstraintIsRatchetJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpFloat -cpRatchetJointGetAngle(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - return ((cpRatchetJoint *)constraint)->angle; -} - -void -cpRatchetJointSetAngle(cpConstraint *constraint, cpFloat angle) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - cpConstraintActivateBodies(constraint); - ((cpRatchetJoint *)constraint)->angle = angle; -} - -cpFloat -cpRatchetJointGetPhase(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - return ((cpRatchetJoint *)constraint)->phase; -} - -void -cpRatchetJointSetPhase(cpConstraint *constraint, cpFloat phase) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - cpConstraintActivateBodies(constraint); - ((cpRatchetJoint *)constraint)->phase = phase; -} -cpFloat -cpRatchetJointGetRatchet(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - return ((cpRatchetJoint *)constraint)->ratchet; -} - -void -cpRatchetJointSetRatchet(cpConstraint *constraint, cpFloat ratchet) -{ - cpAssertHard(cpConstraintIsRatchetJoint(constraint), "Constraint is not a ratchet joint."); - cpConstraintActivateBodies(constraint); - ((cpRatchetJoint *)constraint)->ratchet = ratchet; -} diff --git a/3rdparty/chipmunk/src/cpRobust.c b/3rdparty/chipmunk/src/cpRobust.c deleted file mode 100644 index 57507d14e6b4..000000000000 --- a/3rdparty/chipmunk/src/cpRobust.c +++ /dev/null @@ -1,13 +0,0 @@ -#include "chipmunk/cpRobust.h" - - -cpBool -cpCheckPointGreater(const cpVect a, const cpVect b, const cpVect c) -{ - return (b.y - a.y)*(a.x + b.x - 2*c.x) > (b.x - a.x)*(a.y + b.y - 2*c.y); -} - -cpBool -cpCheckAxis(cpVect v0, cpVect v1, cpVect p, cpVect n){ - return cpvdot(p, n) <= cpfmax(cpvdot(v0, n), cpvdot(v1, n)); -} diff --git a/3rdparty/chipmunk/src/cpRotaryLimitJoint.c b/3rdparty/chipmunk/src/cpRotaryLimitJoint.c deleted file mode 100644 index 548adbebf053..000000000000 --- a/3rdparty/chipmunk/src/cpRotaryLimitJoint.c +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpRotaryLimitJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat dist = b->a - a->a; - cpFloat pdist = 0.0f; - if(dist > joint->max) { - pdist = joint->max - dist; - } else if(dist < joint->min) { - pdist = joint->min - dist; - } - - // calculate moment of inertia coefficient. - joint->iSum = 1.0f/(a->i_inv + b->i_inv); - - // calculate bias velocity - cpFloat maxBias = joint->constraint.maxBias; - joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); - - // If the bias is 0, the joint is not at a limit. Reset the impulse. - if(!joint->bias) joint->jAcc = 0.0f; -} - -static void -applyCachedImpulse(cpRotaryLimitJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat j = joint->jAcc*dt_coef; - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static void -applyImpulse(cpRotaryLimitJoint *joint, cpFloat dt) -{ - if(!joint->bias) return; // early exit - - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // compute relative rotational velocity - cpFloat wr = b->w - a->w; - - cpFloat jMax = joint->constraint.maxForce*dt; - - // compute normal impulse - cpFloat j = -(joint->bias + wr)*joint->iSum; - cpFloat jOld = joint->jAcc; - if(joint->bias < 0.0f){ - joint->jAcc = cpfclamp(jOld + j, 0.0f, jMax); - } else { - joint->jAcc = cpfclamp(jOld + j, -jMax, 0.0f); - } - j = joint->jAcc - jOld; - - // apply impulse - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static cpFloat -getImpulse(cpRotaryLimitJoint *joint) -{ - return cpfabs(joint->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpRotaryLimitJoint * -cpRotaryLimitJointAlloc(void) -{ - return (cpRotaryLimitJoint *)cpcalloc(1, sizeof(cpRotaryLimitJoint)); -} - -cpRotaryLimitJoint * -cpRotaryLimitJointInit(cpRotaryLimitJoint *joint, cpBody *a, cpBody *b, cpFloat min, cpFloat max) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->min = min; - joint->max = max; - - joint->jAcc = 0.0f; - - return joint; -} - -cpConstraint * -cpRotaryLimitJointNew(cpBody *a, cpBody *b, cpFloat min, cpFloat max) -{ - return (cpConstraint *)cpRotaryLimitJointInit(cpRotaryLimitJointAlloc(), a, b, min, max); -} - -cpBool -cpConstraintIsRotaryLimitJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpFloat -cpRotaryLimitJointGetMin(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint."); - return ((cpRotaryLimitJoint *)constraint)->min; -} - -void -cpRotaryLimitJointSetMin(cpConstraint *constraint, cpFloat min) -{ - cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint."); - cpConstraintActivateBodies(constraint); - ((cpRotaryLimitJoint *)constraint)->min = min; -} - -cpFloat -cpRotaryLimitJointGetMax(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint."); - return ((cpRotaryLimitJoint *)constraint)->max; -} - -void -cpRotaryLimitJointSetMax(cpConstraint *constraint, cpFloat max) -{ - cpAssertHard(cpConstraintIsRotaryLimitJoint(constraint), "Constraint is not a rotary limit joint."); - cpConstraintActivateBodies(constraint); - ((cpRotaryLimitJoint *)constraint)->max = max; -} diff --git a/3rdparty/chipmunk/src/cpShape.c b/3rdparty/chipmunk/src/cpShape.c deleted file mode 100644 index 513b5353ed48..000000000000 --- a/3rdparty/chipmunk/src/cpShape.c +++ /dev/null @@ -1,604 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/chipmunk_unsafe.h" - -#define CP_DefineShapeGetter(struct, type, member, name) \ -CP_DeclareShapeGetter(struct, type, name){ \ - cpAssertHard(shape->klass == &struct##Class, "shape is not a "#struct); \ - return ((struct *)shape)->member; \ -} - -cpShape * -cpShapeInit(cpShape *shape, const cpShapeClass *klass, cpBody *body, struct cpShapeMassInfo massInfo) -{ - shape->klass = klass; - - shape->body = body; - shape->massInfo = massInfo; - - shape->sensor = 0; - - shape->e = 0.0f; - shape->u = 0.0f; - shape->surfaceV = cpvzero; - - shape->type = 0; - shape->filter.group = CP_NO_GROUP; - shape->filter.categories = CP_ALL_CATEGORIES; - shape->filter.mask = CP_ALL_CATEGORIES; - - shape->userData = NULL; - - shape->space = NULL; - - shape->next = NULL; - shape->prev = NULL; - - return shape; -} - -void -cpShapeDestroy(cpShape *shape) -{ - if(shape->klass && shape->klass->destroy) shape->klass->destroy(shape); -} - -void -cpShapeFree(cpShape *shape) -{ - if(shape){ - cpShapeDestroy(shape); - cpfree(shape); - } -} - -cpSpace * -cpShapeGetSpace(const cpShape *shape) -{ - return shape->space; -} - -cpBody * -cpShapeGetBody(const cpShape *shape) -{ - return shape->body; -} - -void -cpShapeSetBody(cpShape *shape, cpBody *body) -{ - cpAssertHard(!cpShapeActive(shape), "You cannot change the body on an active shape. You must remove the shape from the space before changing the body."); - shape->body = body; -} - -cpFloat cpShapeGetMass(cpShape *shape){ return shape->massInfo.m; } - -void -cpShapeSetMass(cpShape *shape, cpFloat mass){ - cpBody *body = shape->body; - cpBodyActivate(body); - - shape->massInfo.m = mass; - cpBodyAccumulateMassFromShapes(body); -} - -cpFloat cpShapeGetDensity(cpShape *shape){ return shape->massInfo.m/shape->massInfo.area; } -void cpShapeSetDensity(cpShape *shape, cpFloat density){ cpShapeSetMass(shape, density*shape->massInfo.area); } - -cpFloat cpShapeGetMoment(cpShape *shape){ return shape->massInfo.m*shape->massInfo.i; } -cpFloat cpShapeGetArea(cpShape *shape){ return shape->massInfo.area; } -cpVect cpShapeGetCenterOfGravity(cpShape *shape) { return shape->massInfo.cog; } - -cpBB -cpShapeGetBB(const cpShape *shape) -{ - return shape->bb; -} - -cpBool -cpShapeGetSensor(const cpShape *shape) -{ - return shape->sensor; -} - -void -cpShapeSetSensor(cpShape *shape, cpBool sensor) -{ - cpBodyActivate(shape->body); - shape->sensor = sensor; -} - -cpFloat -cpShapeGetElasticity(const cpShape *shape) -{ - return shape->e; -} - -void -cpShapeSetElasticity(cpShape *shape, cpFloat elasticity) -{ - cpAssertHard(elasticity >= 0.0f, "Elasticity must be positive."); - cpBodyActivate(shape->body); - shape->e = elasticity; -} - -cpFloat -cpShapeGetFriction(const cpShape *shape) -{ - return shape->u; -} - -void -cpShapeSetFriction(cpShape *shape, cpFloat friction) -{ - cpAssertHard(friction >= 0.0f, "Friction must be postive."); - cpBodyActivate(shape->body); - shape->u = friction; -} - -cpVect -cpShapeGetSurfaceVelocity(const cpShape *shape) -{ - return shape->surfaceV; -} - -void -cpShapeSetSurfaceVelocity(cpShape *shape, cpVect surfaceVelocity) -{ - cpBodyActivate(shape->body); - shape->surfaceV = surfaceVelocity; -} - -cpDataPointer -cpShapeGetUserData(const cpShape *shape) -{ - return shape->userData; -} - -void -cpShapeSetUserData(cpShape *shape, cpDataPointer userData) -{ - shape->userData = userData; -} - -cpCollisionType -cpShapeGetCollisionType(const cpShape *shape) -{ - return shape->type; -} - -void -cpShapeSetCollisionType(cpShape *shape, cpCollisionType collisionType) -{ - cpBodyActivate(shape->body); - shape->type = collisionType; -} - -cpShapeFilter -cpShapeGetFilter(const cpShape *shape) -{ - return shape->filter; -} - -void -cpShapeSetFilter(cpShape *shape, cpShapeFilter filter) -{ - cpBodyActivate(shape->body); - shape->filter = filter; -} - -cpBB -cpShapeCacheBB(cpShape *shape) -{ - return cpShapeUpdate(shape, shape->body->transform); -} - -cpBB -cpShapeUpdate(cpShape *shape, cpTransform transform) -{ - return (shape->bb = shape->klass->cacheData(shape, transform)); -} - -cpFloat -cpShapePointQuery(const cpShape *shape, cpVect p, cpPointQueryInfo *info) -{ - cpPointQueryInfo blank = {NULL, cpvzero, INFINITY, cpvzero}; - if(info){ - (*info) = blank; - } else { - info = ␣ - } - - shape->klass->pointQuery(shape, p, info); - return info->distance; -} - - -cpBool -cpShapeSegmentQuery(const cpShape *shape, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info){ - cpSegmentQueryInfo blank = {NULL, b, cpvzero, 1.0f}; - if(info){ - (*info) = blank; - } else { - info = ␣ - } - - cpPointQueryInfo nearest; - shape->klass->pointQuery(shape, a, &nearest); - if(nearest.distance <= radius){ - info->shape = shape; - info->alpha = 0.0; - info->normal = cpvnormalize(cpvsub(a, nearest.point)); - } else { - shape->klass->segmentQuery(shape, a, b, radius, info); - } - - return (info->shape != NULL); -} - -cpContactPointSet -cpShapesCollide(const cpShape *a, const cpShape *b) -{ - struct cpContact contacts[CP_MAX_CONTACTS_PER_ARBITER]; - struct cpCollisionInfo info = cpCollide(a, b, 0, contacts); - - cpContactPointSet set; - set.count = info.count; - - // cpCollideShapes() may have swapped the contact order. Flip the normal. - cpBool swapped = (a != info.a); - set.normal = (swapped ? cpvneg(info.n) : info.n); - - for(int i=0; itc = cpTransformPoint(transform, circle->c); - return cpBBNewForCircle(c, circle->r); -} - -static void -cpCircleShapePointQuery(cpCircleShape *circle, cpVect p, cpPointQueryInfo *info) -{ - cpVect delta = cpvsub(p, circle->tc); - cpFloat d = cpvlength(delta); - cpFloat r = circle->r; - - info->shape = (cpShape *)circle; - cpFloat r_over_d = d > 0.0f ? r/d : r; - info->point = cpvadd(circle->tc, cpvmult(delta, r_over_d)); // TODO: div/0 - info->distance = d - r; - - // Use up for the gradient if the distance is very small. - info->gradient = (d > MAGIC_EPSILON ? cpvmult(delta, 1.0f/d) : cpv(0.0f, 1.0f)); -} - -static void -cpCircleShapeSegmentQuery(cpCircleShape *circle, cpVect a, cpVect b, cpFloat radius, cpSegmentQueryInfo *info) -{ - CircleSegmentQuery((cpShape *)circle, circle->tc, circle->r, a, b, radius, info); -} - -static struct cpShapeMassInfo -cpCircleShapeMassInfo(cpFloat mass, cpFloat radius, cpVect center) -{ - struct cpShapeMassInfo info = { - mass, cpMomentForCircle(1.0f, 0.0f, radius, cpvzero), - center, - cpAreaForCircle(0.0f, radius), - }; - - return info; -} - -static const cpShapeClass cpCircleShapeClass = { - CP_CIRCLE_SHAPE, - (cpShapeCacheDataImpl)cpCircleShapeCacheData, - NULL, - (cpShapePointQueryImpl)cpCircleShapePointQuery, - (cpShapeSegmentQueryImpl)cpCircleShapeSegmentQuery, -}; - -cpCircleShape * -cpCircleShapeInit(cpCircleShape *circle, cpBody *body, cpFloat radius, cpVect offset) -{ - circle->c = offset; - circle->r = radius; - - cpShapeInit((cpShape *)circle, &cpCircleShapeClass, body, cpCircleShapeMassInfo(0.0f, radius, offset)); - - return circle; -} - -cpShape * -cpCircleShapeNew(cpBody *body, cpFloat radius, cpVect offset) -{ - return (cpShape *)cpCircleShapeInit(cpCircleShapeAlloc(), body, radius, offset); -} - -cpVect -cpCircleShapeGetOffset(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape."); - return ((cpCircleShape *)shape)->c; -} - -cpFloat -cpCircleShapeGetRadius(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape."); - return ((cpCircleShape *)shape)->r; -} - - -cpSegmentShape * -cpSegmentShapeAlloc(void) -{ - return (cpSegmentShape *)cpcalloc(1, sizeof(cpSegmentShape)); -} - -static cpBB -cpSegmentShapeCacheData(cpSegmentShape *seg, cpTransform transform) -{ - seg->ta = cpTransformPoint(transform, seg->a); - seg->tb = cpTransformPoint(transform, seg->b); - seg->tn = cpTransformVect(transform, seg->n); - - cpFloat l,r,b,t; - - if(seg->ta.x < seg->tb.x){ - l = seg->ta.x; - r = seg->tb.x; - } else { - l = seg->tb.x; - r = seg->ta.x; - } - - if(seg->ta.y < seg->tb.y){ - b = seg->ta.y; - t = seg->tb.y; - } else { - b = seg->tb.y; - t = seg->ta.y; - } - - cpFloat rad = seg->r; - return cpBBNew(l - rad, b - rad, r + rad, t + rad); -} - -static void -cpSegmentShapePointQuery(cpSegmentShape *seg, cpVect p, cpPointQueryInfo *info) -{ - cpVect closest = cpClosetPointOnSegment(p, seg->ta, seg->tb); - - cpVect delta = cpvsub(p, closest); - cpFloat d = cpvlength(delta); - cpFloat r = seg->r; - cpVect g = cpvmult(delta, 1.0f/d); - - info->shape = (cpShape *)seg; - info->point = (d ? cpvadd(closest, cpvmult(g, r)) : closest); - info->distance = d - r; - - // Use the segment's normal if the distance is very small. - info->gradient = (d > MAGIC_EPSILON ? g : seg->n); -} - -static void -cpSegmentShapeSegmentQuery(cpSegmentShape *seg, cpVect a, cpVect b, cpFloat r2, cpSegmentQueryInfo *info) -{ - cpVect n = seg->tn; - cpFloat d = cpvdot(cpvsub(seg->ta, a), n); - cpFloat r = seg->r + r2; - - cpVect flipped_n = (d > 0.0f ? cpvneg(n) : n); - cpVect seg_offset = cpvsub(cpvmult(flipped_n, r), a); - - // Make the endpoints relative to 'a' and move them by the thickness of the segment. - cpVect seg_a = cpvadd(seg->ta, seg_offset); - cpVect seg_b = cpvadd(seg->tb, seg_offset); - cpVect delta = cpvsub(b, a); - - if(cpvcross(delta, seg_a)*cpvcross(delta, seg_b) <= 0.0f){ - cpFloat d_offset = d + (d > 0.0f ? -r : r); - cpFloat ad = -d_offset; - cpFloat bd = cpvdot(delta, n) - d_offset; - - if(ad*bd < 0.0f){ - cpFloat t = ad/(ad - bd); - - info->shape = (cpShape *)seg; - info->point = cpvsub(cpvlerp(a, b, t), cpvmult(flipped_n, r2)); - info->normal = flipped_n; - info->alpha = t; - } - } else if(r != 0.0f){ - cpSegmentQueryInfo info1 = {NULL, b, cpvzero, 1.0f}; - cpSegmentQueryInfo info2 = {NULL, b, cpvzero, 1.0f}; - CircleSegmentQuery((cpShape *)seg, seg->ta, seg->r, a, b, r2, &info1); - CircleSegmentQuery((cpShape *)seg, seg->tb, seg->r, a, b, r2, &info2); - - if(info1.alpha < info2.alpha){ - (*info) = info1; - } else { - (*info) = info2; - } - } -} - -static struct cpShapeMassInfo -cpSegmentShapeMassInfo(cpFloat mass, cpVect a, cpVect b, cpFloat r) -{ - struct cpShapeMassInfo info = { - mass, cpMomentForBox(1.0f, cpvdist(a, b) + 2.0f*r, 2.0f*r), // TODO is an approximation. - cpvlerp(a, b, 0.5f), - cpAreaForSegment(a, b, r), - }; - - return info; -} - -static const cpShapeClass cpSegmentShapeClass = { - CP_SEGMENT_SHAPE, - (cpShapeCacheDataImpl)cpSegmentShapeCacheData, - NULL, - (cpShapePointQueryImpl)cpSegmentShapePointQuery, - (cpShapeSegmentQueryImpl)cpSegmentShapeSegmentQuery, -}; - -cpSegmentShape * -cpSegmentShapeInit(cpSegmentShape *seg, cpBody *body, cpVect a, cpVect b, cpFloat r) -{ - seg->a = a; - seg->b = b; - seg->n = cpvrperp(cpvnormalize(cpvsub(b, a))); - - seg->r = r; - - seg->a_tangent = cpvzero; - seg->b_tangent = cpvzero; - - cpShapeInit((cpShape *)seg, &cpSegmentShapeClass, body, cpSegmentShapeMassInfo(0.0f, a, b, r)); - - return seg; -} - -cpShape* -cpSegmentShapeNew(cpBody *body, cpVect a, cpVect b, cpFloat r) -{ - return (cpShape *)cpSegmentShapeInit(cpSegmentShapeAlloc(), body, a, b, r); -} - -cpVect -cpSegmentShapeGetA(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - return ((cpSegmentShape *)shape)->a; -} - -cpVect -cpSegmentShapeGetB(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - return ((cpSegmentShape *)shape)->b; -} - -cpVect -cpSegmentShapeGetNormal(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - return ((cpSegmentShape *)shape)->n; -} - -cpFloat -cpSegmentShapeGetRadius(const cpShape *shape) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - return ((cpSegmentShape *)shape)->r; -} - -void -cpSegmentShapeSetNeighbors(cpShape *shape, cpVect prev, cpVect next) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - cpSegmentShape *seg = (cpSegmentShape *)shape; - - seg->a_tangent = cpvsub(prev, seg->a); - seg->b_tangent = cpvsub(next, seg->b); -} - -// Unsafe API (chipmunk_unsafe.h) - -// TODO setters should wake the shape up? - -void -cpCircleShapeSetRadius(cpShape *shape, cpFloat radius) -{ - cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape."); - cpCircleShape *circle = (cpCircleShape *)shape; - - circle->r = radius; - - cpFloat mass = shape->massInfo.m; - shape->massInfo = cpCircleShapeMassInfo(mass, circle->r, circle->c); - if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} - -void -cpCircleShapeSetOffset(cpShape *shape, cpVect offset) -{ - cpAssertHard(shape->klass == &cpCircleShapeClass, "Shape is not a circle shape."); - cpCircleShape *circle = (cpCircleShape *)shape; - - circle->c = offset; - - cpFloat mass = shape->massInfo.m; - shape->massInfo = cpCircleShapeMassInfo(shape->massInfo.m, circle->r, circle->c); - if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} - -void -cpSegmentShapeSetEndpoints(cpShape *shape, cpVect a, cpVect b) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - cpSegmentShape *seg = (cpSegmentShape *)shape; - - seg->a = a; - seg->b = b; - seg->n = cpvperp(cpvnormalize(cpvsub(b, a))); - - cpFloat mass = shape->massInfo.m; - shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r); - if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} - -void -cpSegmentShapeSetRadius(cpShape *shape, cpFloat radius) -{ - cpAssertHard(shape->klass == &cpSegmentShapeClass, "Shape is not a segment shape."); - cpSegmentShape *seg = (cpSegmentShape *)shape; - - seg->r = radius; - - cpFloat mass = shape->massInfo.m; - shape->massInfo = cpSegmentShapeMassInfo(shape->massInfo.m, seg->a, seg->b, seg->r); - if(mass > 0.0f) cpBodyAccumulateMassFromShapes(shape->body); -} diff --git a/3rdparty/chipmunk/src/cpSimpleMotor.c b/3rdparty/chipmunk/src/cpSimpleMotor.c deleted file mode 100644 index 2bea74a525da..000000000000 --- a/3rdparty/chipmunk/src/cpSimpleMotor.c +++ /dev/null @@ -1,123 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpSimpleMotor *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // calculate moment of inertia coefficient. - joint->iSum = 1.0f/(a->i_inv + b->i_inv); -} - -static void -applyCachedImpulse(cpSimpleMotor *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpFloat j = joint->jAcc*dt_coef; - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static void -applyImpulse(cpSimpleMotor *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - // compute relative rotational velocity - cpFloat wr = b->w - a->w + joint->rate; - - cpFloat jMax = joint->constraint.maxForce*dt; - - // compute normal impulse - cpFloat j = -wr*joint->iSum; - cpFloat jOld = joint->jAcc; - joint->jAcc = cpfclamp(jOld + j, -jMax, jMax); - j = joint->jAcc - jOld; - - // apply impulse - a->w -= j*a->i_inv; - b->w += j*b->i_inv; -} - -static cpFloat -getImpulse(cpSimpleMotor *joint) -{ - return cpfabs(joint->jAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpSimpleMotor * -cpSimpleMotorAlloc(void) -{ - return (cpSimpleMotor *)cpcalloc(1, sizeof(cpSimpleMotor)); -} - -cpSimpleMotor * -cpSimpleMotorInit(cpSimpleMotor *joint, cpBody *a, cpBody *b, cpFloat rate) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->rate = rate; - - joint->jAcc = 0.0f; - - return joint; -} - -cpConstraint * -cpSimpleMotorNew(cpBody *a, cpBody *b, cpFloat rate) -{ - return (cpConstraint *)cpSimpleMotorInit(cpSimpleMotorAlloc(), a, b, rate); -} - -cpBool -cpConstraintIsSimpleMotor(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpFloat -cpSimpleMotorGetRate(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a SimpleMotor."); - return ((cpSimpleMotor *)constraint)->rate; -} - -void -cpSimpleMotorSetRate(cpConstraint *constraint, cpFloat rate) -{ - cpAssertHard(cpConstraintIsSimpleMotor(constraint), "Constraint is not a SimpleMotor."); - cpConstraintActivateBodies(constraint); - ((cpSimpleMotor *)constraint)->rate = rate; -} diff --git a/3rdparty/chipmunk/src/cpSlideJoint.c b/3rdparty/chipmunk/src/cpSlideJoint.c deleted file mode 100644 index 61afe33e4b1a..000000000000 --- a/3rdparty/chipmunk/src/cpSlideJoint.c +++ /dev/null @@ -1,195 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static void -preStep(cpSlideJoint *joint, cpFloat dt) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - joint->r1 = cpTransformVect(a->transform, cpvsub(joint->anchorA, a->cog)); - joint->r2 = cpTransformVect(b->transform, cpvsub(joint->anchorB, b->cog)); - - cpVect delta = cpvsub(cpvadd(b->p, joint->r2), cpvadd(a->p, joint->r1)); - cpFloat dist = cpvlength(delta); - cpFloat pdist = 0.0f; - if(dist > joint->max) { - pdist = dist - joint->max; - joint->n = cpvnormalize(delta); - } else if(dist < joint->min) { - pdist = joint->min - dist; - joint->n = cpvneg(cpvnormalize(delta)); - } else { - joint->n = cpvzero; - joint->jnAcc = 0.0f; - } - - // calculate mass normal - joint->nMass = 1.0f/k_scalar(a, b, joint->r1, joint->r2, joint->n); - - // calculate bias velocity - cpFloat maxBias = joint->constraint.maxBias; - joint->bias = cpfclamp(-bias_coef(joint->constraint.errorBias, dt)*pdist/dt, -maxBias, maxBias); -} - -static void -applyCachedImpulse(cpSlideJoint *joint, cpFloat dt_coef) -{ - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpVect j = cpvmult(joint->n, joint->jnAcc*dt_coef); - apply_impulses(a, b, joint->r1, joint->r2, j); -} - -static void -applyImpulse(cpSlideJoint *joint, cpFloat dt) -{ - if(cpveql(joint->n, cpvzero)) return; // early exit - - cpBody *a = joint->constraint.a; - cpBody *b = joint->constraint.b; - - cpVect n = joint->n; - cpVect r1 = joint->r1; - cpVect r2 = joint->r2; - - // compute relative velocity - cpVect vr = relative_velocity(a, b, r1, r2); - cpFloat vrn = cpvdot(vr, n); - - // compute normal impulse - cpFloat jn = (joint->bias - vrn)*joint->nMass; - cpFloat jnOld = joint->jnAcc; - joint->jnAcc = cpfclamp(jnOld + jn, -joint->constraint.maxForce*dt, 0.0f); - jn = joint->jnAcc - jnOld; - - // apply impulse - apply_impulses(a, b, joint->r1, joint->r2, cpvmult(n, jn)); -} - -static cpFloat -getImpulse(cpConstraint *joint) -{ - return cpfabs(((cpSlideJoint *)joint)->jnAcc); -} - -static const cpConstraintClass klass = { - (cpConstraintPreStepImpl)preStep, - (cpConstraintApplyCachedImpulseImpl)applyCachedImpulse, - (cpConstraintApplyImpulseImpl)applyImpulse, - (cpConstraintGetImpulseImpl)getImpulse, -}; - -cpSlideJoint * -cpSlideJointAlloc(void) -{ - return (cpSlideJoint *)cpcalloc(1, sizeof(cpSlideJoint)); -} - -cpSlideJoint * -cpSlideJointInit(cpSlideJoint *joint, cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max) -{ - cpConstraintInit((cpConstraint *)joint, &klass, a, b); - - joint->anchorA = anchorA; - joint->anchorB = anchorB; - joint->min = min; - joint->max = max; - - joint->jnAcc = 0.0f; - - return joint; -} - -cpConstraint * -cpSlideJointNew(cpBody *a, cpBody *b, cpVect anchorA, cpVect anchorB, cpFloat min, cpFloat max) -{ - return (cpConstraint *)cpSlideJointInit(cpSlideJointAlloc(), a, b, anchorA, anchorB, min, max); -} - -cpBool -cpConstraintIsSlideJoint(const cpConstraint *constraint) -{ - return (constraint->klass == &klass); -} - -cpVect -cpSlideJointGetAnchorA(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - return ((cpSlideJoint *)constraint)->anchorA; -} - -void -cpSlideJointSetAnchorA(cpConstraint *constraint, cpVect anchorA) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - cpConstraintActivateBodies(constraint); - ((cpSlideJoint *)constraint)->anchorA = anchorA; -} - -cpVect -cpSlideJointGetAnchorB(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - return ((cpSlideJoint *)constraint)->anchorB; -} - -void -cpSlideJointSetAnchorB(cpConstraint *constraint, cpVect anchorB) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - cpConstraintActivateBodies(constraint); - ((cpSlideJoint *)constraint)->anchorB = anchorB; -} - -cpFloat -cpSlideJointGetMin(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - return ((cpSlideJoint *)constraint)->min; -} - -void -cpSlideJointSetMin(cpConstraint *constraint, cpFloat min) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - cpConstraintActivateBodies(constraint); - ((cpSlideJoint *)constraint)->min = min; -} - -cpFloat -cpSlideJointGetMax(const cpConstraint *constraint) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - return ((cpSlideJoint *)constraint)->max; -} - -void -cpSlideJointSetMax(cpConstraint *constraint, cpFloat max) -{ - cpAssertHard(cpConstraintIsSlideJoint(constraint), "Constraint is not a slide joint."); - cpConstraintActivateBodies(constraint); - ((cpSlideJoint *)constraint)->max = max; -} diff --git a/3rdparty/chipmunk/src/cpSpace.c b/3rdparty/chipmunk/src/cpSpace.c deleted file mode 100644 index b319d3a4e831..000000000000 --- a/3rdparty/chipmunk/src/cpSpace.c +++ /dev/null @@ -1,701 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include -#include - -#include "chipmunk/chipmunk_private.h" - -//MARK: Contact Set Helpers - -// Equal function for arbiterSet. -static cpBool -arbiterSetEql(cpShape **shapes, cpArbiter *arb) -{ - cpShape *a = shapes[0]; - cpShape *b = shapes[1]; - - return ((a == arb->a && b == arb->b) || (b == arb->a && a == arb->b)); -} - -//MARK: Collision Handler Set HelperFunctions - -// Equals function for collisionHandlers. -static cpBool -handlerSetEql(cpCollisionHandler *check, cpCollisionHandler *pair) -{ - return ( - (check->typeA == pair->typeA && check->typeB == pair->typeB) || - (check->typeB == pair->typeA && check->typeA == pair->typeB) - ); -} - -// Transformation function for collisionHandlers. -static void * -handlerSetTrans(cpCollisionHandler *handler, void *unused) -{ - cpCollisionHandler *copy = (cpCollisionHandler *)cpcalloc(1, sizeof(cpCollisionHandler)); - memcpy(copy, handler, sizeof(cpCollisionHandler)); - - return copy; -} - -//MARK: Misc Helper Funcs - -// Default collision functions. - -static cpBool -DefaultBegin(cpArbiter *arb, cpSpace *space, cpDataPointer data){ - cpBool retA = cpArbiterCallWildcardBeginA(arb, space); - cpBool retB = cpArbiterCallWildcardBeginB(arb, space); - return retA && retB; -} - -static cpBool -DefaultPreSolve(cpArbiter *arb, cpSpace *space, cpDataPointer data){ - cpBool retA = cpArbiterCallWildcardPreSolveA(arb, space); - cpBool retB = cpArbiterCallWildcardPreSolveB(arb, space); - return retA && retB; -} - -static void -DefaultPostSolve(cpArbiter *arb, cpSpace *space, cpDataPointer data){ - cpArbiterCallWildcardPostSolveA(arb, space); - cpArbiterCallWildcardPostSolveB(arb, space); -} - -static void -DefaultSeparate(cpArbiter *arb, cpSpace *space, cpDataPointer data){ - cpArbiterCallWildcardSeparateA(arb, space); - cpArbiterCallWildcardSeparateB(arb, space); -} - -// Use the wildcard identifier since the default handler should never match any type pair. -static cpCollisionHandler cpCollisionHandlerDefault = { - CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE, - DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL -}; - -static cpBool AlwaysCollide(cpArbiter *arb, cpSpace *space, cpDataPointer data){return cpTrue;} -static void DoNothing(cpArbiter *arb, cpSpace *space, cpDataPointer data){} - -cpCollisionHandler cpCollisionHandlerDoNothing = { - CP_WILDCARD_COLLISION_TYPE, CP_WILDCARD_COLLISION_TYPE, - AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL -}; - -// function to get the estimated velocity of a shape for the cpBBTree. -static cpVect ShapeVelocityFunc(cpShape *shape){return shape->body->v;} - -// Used for disposing of collision handlers. -static void FreeWrap(void *ptr, void *unused){cpfree(ptr);} - -//MARK: Memory Management Functions - -cpSpace * -cpSpaceAlloc(void) -{ - return (cpSpace *)cpcalloc(1, sizeof(cpSpace)); -} - -cpSpace* -cpSpaceInit(cpSpace *space) -{ -#ifndef NDEBUG - static cpBool done = cpFalse; - if(!done){ - printf("Initializing cpSpace - Chipmunk v%s (Debug Enabled)\n", cpVersionString); - printf("Compile with -DNDEBUG defined to disable debug mode and runtime assertion checks\n"); - done = cpTrue; - } -#endif - - space->iterations = 10; - - space->gravity = cpvzero; - space->damping = 1.0f; - - space->collisionSlop = 0.1f; - space->collisionBias = cpfpow(1.0f - 0.1f, 60.0f); - space->collisionPersistence = 3; - - space->locked = 0; - space->stamp = 0; - - space->shapeIDCounter = 0; - space->staticShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, NULL); - space->dynamicShapes = cpBBTreeNew((cpSpatialIndexBBFunc)cpShapeGetBB, space->staticShapes); - cpBBTreeSetVelocityFunc(space->dynamicShapes, (cpBBTreeVelocityFunc)ShapeVelocityFunc); - - space->allocatedBuffers = cpArrayNew(0); - - space->dynamicBodies = cpArrayNew(0); - space->staticBodies = cpArrayNew(0); - space->sleepingComponents = cpArrayNew(0); - space->rousedBodies = cpArrayNew(0); - - space->sleepTimeThreshold = INFINITY; - space->idleSpeedThreshold = 0.0f; - - space->arbiters = cpArrayNew(0); - space->pooledArbiters = cpArrayNew(0); - - space->contactBuffersHead = NULL; - space->cachedArbiters = cpHashSetNew(0, (cpHashSetEqlFunc)arbiterSetEql); - - space->constraints = cpArrayNew(0); - - space->usesWildcards = cpFalse; - memcpy(&space->defaultHandler, &cpCollisionHandlerDoNothing, sizeof(cpCollisionHandler)); - space->collisionHandlers = cpHashSetNew(0, (cpHashSetEqlFunc)handlerSetEql); - - space->postStepCallbacks = cpArrayNew(0); - space->skipPostStep = cpFalse; - - cpBody *staticBody = cpBodyInit(&space->_staticBody, 0.0f, 0.0f); - cpBodySetType(staticBody, CP_BODY_TYPE_STATIC); - cpSpaceSetStaticBody(space, staticBody); - - return space; -} - -cpSpace* -cpSpaceNew(void) -{ - return cpSpaceInit(cpSpaceAlloc()); -} - -static void cpBodyActivateWrap(cpBody *body, void *unused){cpBodyActivate(body);} - -void -cpSpaceDestroy(cpSpace *space) -{ - cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)cpBodyActivateWrap, NULL); - - cpSpatialIndexFree(space->staticShapes); - cpSpatialIndexFree(space->dynamicShapes); - - cpArrayFree(space->dynamicBodies); - cpArrayFree(space->staticBodies); - cpArrayFree(space->sleepingComponents); - cpArrayFree(space->rousedBodies); - - cpArrayFree(space->constraints); - - cpHashSetFree(space->cachedArbiters); - - cpArrayFree(space->arbiters); - cpArrayFree(space->pooledArbiters); - - if(space->allocatedBuffers){ - cpArrayFreeEach(space->allocatedBuffers, cpfree); - cpArrayFree(space->allocatedBuffers); - } - - if(space->postStepCallbacks){ - cpArrayFreeEach(space->postStepCallbacks, cpfree); - cpArrayFree(space->postStepCallbacks); - } - - if(space->collisionHandlers) cpHashSetEach(space->collisionHandlers, FreeWrap, NULL); - cpHashSetFree(space->collisionHandlers); -} - -void -cpSpaceFree(cpSpace *space) -{ - if(space){ - cpSpaceDestroy(space); - cpfree(space); - } -} - - -//MARK: Basic properties: - -int -cpSpaceGetIterations(const cpSpace *space) -{ - return space->iterations; -} - -void -cpSpaceSetIterations(cpSpace *space, int iterations) -{ - cpAssertHard(iterations > 0, "Iterations must be positive and non-zero."); - space->iterations = iterations; -} - -cpVect -cpSpaceGetGravity(const cpSpace *space) -{ - return space->gravity; -} - -void -cpSpaceSetGravity(cpSpace *space, cpVect gravity) -{ - space->gravity = gravity; - - // Wake up all of the bodies since the gravity changed. - cpArray *components = space->sleepingComponents; - for(int i=0; inum; i++){ - cpBodyActivate((cpBody *)components->arr[i]); - } -} - -cpFloat -cpSpaceGetDamping(const cpSpace *space) -{ - return space->damping; -} - -void -cpSpaceSetDamping(cpSpace *space, cpFloat damping) -{ - cpAssertHard(damping >= 0.0, "Damping must be positive."); - space->damping = damping; -} - -cpFloat -cpSpaceGetIdleSpeedThreshold(const cpSpace *space) -{ - return space->idleSpeedThreshold; -} - -void -cpSpaceSetIdleSpeedThreshold(cpSpace *space, cpFloat idleSpeedThreshold) -{ - space->idleSpeedThreshold = idleSpeedThreshold; -} - -cpFloat -cpSpaceGetSleepTimeThreshold(const cpSpace *space) -{ - return space->sleepTimeThreshold; -} - -void -cpSpaceSetSleepTimeThreshold(cpSpace *space, cpFloat sleepTimeThreshold) -{ - space->sleepTimeThreshold = sleepTimeThreshold; -} - -cpFloat -cpSpaceGetCollisionSlop(const cpSpace *space) -{ - return space->collisionSlop; -} - -void -cpSpaceSetCollisionSlop(cpSpace *space, cpFloat collisionSlop) -{ - space->collisionSlop = collisionSlop; -} - -cpFloat -cpSpaceGetCollisionBias(const cpSpace *space) -{ - return space->collisionBias; -} - -void -cpSpaceSetCollisionBias(cpSpace *space, cpFloat collisionBias) -{ - space->collisionBias = collisionBias; -} - -cpTimestamp -cpSpaceGetCollisionPersistence(const cpSpace *space) -{ - return space->collisionPersistence; -} - -void -cpSpaceSetCollisionPersistence(cpSpace *space, cpTimestamp collisionPersistence) -{ - space->collisionPersistence = collisionPersistence; -} - -cpDataPointer -cpSpaceGetUserData(const cpSpace *space) -{ - return space->userData; -} - -void -cpSpaceSetUserData(cpSpace *space, cpDataPointer userData) -{ - space->userData = userData; -} - -cpBody * -cpSpaceGetStaticBody(const cpSpace *space) -{ - return space->staticBody; -} - -cpFloat -cpSpaceGetCurrentTimeStep(const cpSpace *space) -{ - return space->curr_dt; -} - -void -cpSpaceSetStaticBody(cpSpace *space, cpBody *body) -{ - if(space->staticBody != NULL){ - cpAssertHard(space->staticBody->shapeList == NULL, "Internal Error: Changing the designated static body while the old one still had shapes attached."); - space->staticBody->space = NULL; - } - - space->staticBody = body; - body->space = space; -} - -cpBool -cpSpaceIsLocked(cpSpace *space) -{ - return (space->locked > 0); -} - -//MARK: Collision Handler Function Management - -static void -cpSpaceUseWildcardDefaultHandler(cpSpace *space) -{ - // Spaces default to using the slightly faster "do nothing" default handler until wildcards are potentially needed. - if(!space->usesWildcards){ - space->usesWildcards = cpTrue; - memcpy(&space->defaultHandler, &cpCollisionHandlerDefault, sizeof(cpCollisionHandler)); - } -} - -cpCollisionHandler *cpSpaceAddDefaultCollisionHandler(cpSpace *space) -{ - cpSpaceUseWildcardDefaultHandler(space); - return &space->defaultHandler; -} - -cpCollisionHandler *cpSpaceAddCollisionHandler(cpSpace *space, cpCollisionType a, cpCollisionType b) -{ - cpHashValue hash = CP_HASH_PAIR(a, b); - cpCollisionHandler handler = {a, b, DefaultBegin, DefaultPreSolve, DefaultPostSolve, DefaultSeparate, NULL}; - return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL); -} - -cpCollisionHandler * -cpSpaceAddWildcardHandler(cpSpace *space, cpCollisionType type) -{ - cpSpaceUseWildcardDefaultHandler(space); - - cpHashValue hash = CP_HASH_PAIR(type, CP_WILDCARD_COLLISION_TYPE); - cpCollisionHandler handler = {type, CP_WILDCARD_COLLISION_TYPE, AlwaysCollide, AlwaysCollide, DoNothing, DoNothing, NULL}; - return (cpCollisionHandler*)cpHashSetInsert(space->collisionHandlers, hash, &handler, (cpHashSetTransFunc)handlerSetTrans, NULL); -} - - -//MARK: Body, Shape, and Joint Management -cpShape * -cpSpaceAddShape(cpSpace *space, cpShape *shape) -{ - cpAssertHard(shape->space != space, "You have already added this shape to this space. You must not add it a second time."); - cpAssertHard(!shape->space, "You have already added this shape to another space. You cannot add it to a second."); - cpAssertHard(shape->body, "The shape's body is not defined."); - cpAssertHard(shape->body->space == space, "The shape's body must be added to the space before the shape."); - cpAssertSpaceUnlocked(space); - - cpBody *body = shape->body; - - cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC); - if(!isStatic) cpBodyActivate(body); - cpBodyAddShape(body, shape); - - shape->hashid = space->shapeIDCounter++; - cpShapeUpdate(shape, body->transform); - cpSpatialIndexInsert(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid); - shape->space = space; - - return shape; -} - -cpBody * -cpSpaceAddBody(cpSpace *space, cpBody *body) -{ - cpAssertHard(body->space != space, "You have already added this body to this space. You must not add it a second time."); - cpAssertHard(!body->space, "You have already added this body to another space. You cannot add it to a second."); - cpAssertSpaceUnlocked(space); - - cpArrayPush(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body); - body->space = space; - - return body; -} - -cpConstraint * -cpSpaceAddConstraint(cpSpace *space, cpConstraint *constraint) -{ - cpAssertHard(constraint->space != space, "You have already added this constraint to this space. You must not add it a second time."); - cpAssertHard(!constraint->space, "You have already added this constraint to another space. You cannot add it to a second."); - cpAssertSpaceUnlocked(space); - - cpBody *a = constraint->a, *b = constraint->b; - cpAssertHard(a != NULL && b != NULL, "Constraint is attached to a NULL body."); -// cpAssertHard(a->space == space && b->space == space, "The constraint's bodies must be added to the space before the constraint."); - - cpBodyActivate(a); - cpBodyActivate(b); - cpArrayPush(space->constraints, constraint); - - // Push onto the heads of the bodies' constraint lists - constraint->next_a = a->constraintList; a->constraintList = constraint; - constraint->next_b = b->constraintList; b->constraintList = constraint; - constraint->space = space; - - return constraint; -} - -struct arbiterFilterContext { - cpSpace *space; - cpBody *body; - cpShape *shape; -}; - -static cpBool -cachedArbitersFilter(cpArbiter *arb, struct arbiterFilterContext *context) -{ - cpShape *shape = context->shape; - cpBody *body = context->body; - - - // Match on the filter shape, or if it's NULL the filter body - if( - (body == arb->body_a && (shape == arb->a || shape == NULL)) || - (body == arb->body_b && (shape == arb->b || shape == NULL)) - ){ - // Call separate when removing shapes. - if(shape && arb->state != CP_ARBITER_STATE_CACHED){ - // Invalidate the arbiter since one of the shapes was removed. - arb->state = CP_ARBITER_STATE_INVALIDATED; - - cpCollisionHandler *handler = arb->handler; - handler->separateFunc(arb, context->space, handler->userData); - } - - cpArbiterUnthread(arb); - cpArrayDeleteObj(context->space->arbiters, arb); - cpArrayPush(context->space->pooledArbiters, arb); - - return cpFalse; - } - - return cpTrue; -} - -void -cpSpaceFilterArbiters(cpSpace *space, cpBody *body, cpShape *filter) -{ - cpSpaceLock(space); { - struct arbiterFilterContext context = {space, body, filter}; - cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cachedArbitersFilter, &context); - } cpSpaceUnlock(space, cpTrue); -} - -void -cpSpaceRemoveShape(cpSpace *space, cpShape *shape) -{ - cpBody *body = shape->body; - cpAssertHard(cpSpaceContainsShape(space, shape), "Cannot remove a shape that was not added to the space. (Removed twice maybe?)"); - cpAssertSpaceUnlocked(space); - - cpBool isStatic = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC); - if(isStatic){ - cpBodyActivateStatic(body, shape); - } else { - cpBodyActivate(body); - } - - cpBodyRemoveShape(body, shape); - cpSpaceFilterArbiters(space, body, shape); - cpSpatialIndexRemove(isStatic ? space->staticShapes : space->dynamicShapes, shape, shape->hashid); - shape->space = NULL; - shape->hashid = 0; -} - -void -cpSpaceRemoveBody(cpSpace *space, cpBody *body) -{ - cpAssertHard(body != cpSpaceGetStaticBody(space), "Cannot remove the designated static body for the space."); - cpAssertHard(cpSpaceContainsBody(space, body), "Cannot remove a body that was not added to the space. (Removed twice maybe?)"); -// cpAssertHard(body->shapeList == NULL, "Cannot remove a body from the space before removing the bodies attached to it."); -// cpAssertHard(body->constraintList == NULL, "Cannot remove a body from the space before removing the constraints attached to it."); - cpAssertSpaceUnlocked(space); - - cpBodyActivate(body); -// cpSpaceFilterArbiters(space, body, NULL); - cpArrayDeleteObj(cpSpaceArrayForBodyType(space, cpBodyGetType(body)), body); - body->space = NULL; -} - -void -cpSpaceRemoveConstraint(cpSpace *space, cpConstraint *constraint) -{ - cpAssertHard(cpSpaceContainsConstraint(space, constraint), "Cannot remove a constraint that was not added to the space. (Removed twice maybe?)"); - cpAssertSpaceUnlocked(space); - - cpBodyActivate(constraint->a); - cpBodyActivate(constraint->b); - cpArrayDeleteObj(space->constraints, constraint); - - cpBodyRemoveConstraint(constraint->a, constraint); - cpBodyRemoveConstraint(constraint->b, constraint); - constraint->space = NULL; -} - -cpBool cpSpaceContainsShape(cpSpace *space, cpShape *shape) -{ - return (shape->space == space); -} - -cpBool cpSpaceContainsBody(cpSpace *space, cpBody *body) -{ - return (body->space == space); -} - -cpBool cpSpaceContainsConstraint(cpSpace *space, cpConstraint *constraint) -{ - return (constraint->space == space); -} - -//MARK: Iteration - -void -cpSpaceEachBody(cpSpace *space, cpSpaceBodyIteratorFunc func, void *data) -{ - cpSpaceLock(space); { - cpArray *bodies = space->dynamicBodies; - for(int i=0; inum; i++){ - func((cpBody *)bodies->arr[i], data); - } - - cpArray *otherBodies = space->staticBodies; - for(int i=0; inum; i++){ - func((cpBody *)otherBodies->arr[i], data); - } - - cpArray *components = space->sleepingComponents; - for(int i=0; inum; i++){ - cpBody *root = (cpBody *)components->arr[i]; - - cpBody *body = root; - while(body){ - cpBody *next = body->sleeping.next; - func(body, data); - body = next; - } - } - } cpSpaceUnlock(space, cpTrue); -} - -typedef struct spaceShapeContext { - cpSpaceShapeIteratorFunc func; - void *data; -} spaceShapeContext; - -static void -spaceEachShapeIterator(cpShape *shape, spaceShapeContext *context) -{ - context->func(shape, context->data); -} - -void -cpSpaceEachShape(cpSpace *space, cpSpaceShapeIteratorFunc func, void *data) -{ - cpSpaceLock(space); { - spaceShapeContext context = {func, data}; - cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context); - cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)spaceEachShapeIterator, &context); - } cpSpaceUnlock(space, cpTrue); -} - -void -cpSpaceEachConstraint(cpSpace *space, cpSpaceConstraintIteratorFunc func, void *data) -{ - cpSpaceLock(space); { - cpArray *constraints = space->constraints; - - for(int i=0; inum; i++){ - func((cpConstraint *)constraints->arr[i], data); - } - } cpSpaceUnlock(space, cpTrue); -} - -//MARK: Spatial Index Management - -void -cpSpaceReindexStatic(cpSpace *space) -{ - cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete."); - - cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)&cpShapeUpdateFunc, NULL); - cpSpatialIndexReindex(space->staticShapes); -} - -void -cpSpaceReindexShape(cpSpace *space, cpShape *shape) -{ - cpAssertHard(!space->locked, "You cannot manually reindex objects while the space is locked. Wait until the current query or step is complete."); - - cpShapeCacheBB(shape); - - // attempt to rehash the shape in both hashes - cpSpatialIndexReindexObject(space->dynamicShapes, shape, shape->hashid); - cpSpatialIndexReindexObject(space->staticShapes, shape, shape->hashid); -} - -void -cpSpaceReindexShapesForBody(cpSpace *space, cpBody *body) -{ - CP_BODY_FOREACH_SHAPE(body, shape) cpSpaceReindexShape(space, shape); -} - - -static void -copyShapes(cpShape *shape, cpSpatialIndex *index) -{ - cpSpatialIndexInsert(index, shape, shape->hashid); -} - -void -cpSpaceUseSpatialHash(cpSpace *space, cpFloat dim, int count) -{ - cpSpatialIndex *staticShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, NULL); - cpSpatialIndex *dynamicShapes = cpSpaceHashNew(dim, count, (cpSpatialIndexBBFunc)cpShapeGetBB, staticShapes); - - cpSpatialIndexEach(space->staticShapes, (cpSpatialIndexIteratorFunc)copyShapes, staticShapes); - cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)copyShapes, dynamicShapes); - - cpSpatialIndexFree(space->staticShapes); - cpSpatialIndexFree(space->dynamicShapes); - - space->staticShapes = staticShapes; - space->dynamicShapes = dynamicShapes; -} diff --git a/3rdparty/chipmunk/src/cpSpaceComponent.c b/3rdparty/chipmunk/src/cpSpaceComponent.c deleted file mode 100644 index 7b2d60699111..000000000000 --- a/3rdparty/chipmunk/src/cpSpaceComponent.c +++ /dev/null @@ -1,349 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "chipmunk/chipmunk_private.h" - -//MARK: Sleeping Functions - -void -cpSpaceActivateBody(cpSpace *space, cpBody *body) -{ - cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to activate a non-dynamic body."); - - if(space->locked){ - // cpSpaceActivateBody() is called again once the space is unlocked - if(!cpArrayContains(space->rousedBodies, body)) cpArrayPush(space->rousedBodies, body); - } else { - cpAssertSoft(body->sleeping.root == NULL && body->sleeping.next == NULL, "Internal error: Activating body non-NULL node pointers."); - cpArrayPush(space->dynamicBodies, body); - - CP_BODY_FOREACH_SHAPE(body, shape){ - cpSpatialIndexRemove(space->staticShapes, shape, shape->hashid); - cpSpatialIndexInsert(space->dynamicShapes, shape, shape->hashid); - } - - CP_BODY_FOREACH_ARBITER(body, arb){ - cpBody *bodyA = arb->body_a; - - // Arbiters are shared between two bodies that are always woken up together. - // You only want to restore the arbiter once, so bodyA is arbitrarily chosen to own the arbiter. - // The edge case is when static bodies are involved as the static bodies never actually sleep. - // If the static body is bodyB then all is good. If the static body is bodyA, that can easily be checked. - if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){ - int numContacts = arb->count; - struct cpContact *contacts = arb->contacts; - - // Restore contact values back to the space's contact buffer memory - arb->contacts = cpContactBufferGetArray(space); - memcpy(arb->contacts, contacts, numContacts*sizeof(struct cpContact)); - cpSpacePushContacts(space, numContacts); - - // Reinsert the arbiter into the arbiter cache - const cpShape *a = arb->a, *b = arb->b; - const cpShape *shape_pair[] = {a, b}; - cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)a, (cpHashValue)b); - cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, NULL, arb); - - // Update the arbiter's state - arb->stamp = space->stamp; - cpArrayPush(space->arbiters, arb); - - cpfree(contacts); - } - } - - CP_BODY_FOREACH_CONSTRAINT(body, constraint){ - cpBody *bodyA = constraint->a; - if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayPush(space->constraints, constraint); - } - } -} - -static void -cpSpaceDeactivateBody(cpSpace *space, cpBody *body) -{ - cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Internal error: Attempting to deactivate a non-dynamic body."); - - cpArrayDeleteObj(space->dynamicBodies, body); - - CP_BODY_FOREACH_SHAPE(body, shape){ - cpSpatialIndexRemove(space->dynamicShapes, shape, shape->hashid); - cpSpatialIndexInsert(space->staticShapes, shape, shape->hashid); - } - - CP_BODY_FOREACH_ARBITER(body, arb){ - cpBody *bodyA = arb->body_a; - if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC){ - cpSpaceUncacheArbiter(space, arb); - - // Save contact values to a new block of memory so they won't time out - size_t bytes = arb->count*sizeof(struct cpContact); - struct cpContact *contacts = (struct cpContact *)cpcalloc(1, bytes); - memcpy(contacts, arb->contacts, bytes); - arb->contacts = contacts; - } - } - - CP_BODY_FOREACH_CONSTRAINT(body, constraint){ - cpBody *bodyA = constraint->a; - if(body == bodyA || cpBodyGetType(bodyA) == CP_BODY_TYPE_STATIC) cpArrayDeleteObj(space->constraints, constraint); - } -} - -static inline cpBody * -ComponentRoot(cpBody *body) -{ - return (body ? body->sleeping.root : NULL); -} - -void -cpBodyActivate(cpBody *body) -{ - if(body != NULL && cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){ - body->sleeping.idleTime = 0.0f; - - cpBody *root = ComponentRoot(body); - if(root && cpBodyIsSleeping(root)){ - // TODO should cpBodyIsSleeping(root) be an assertion? - cpAssertSoft(cpBodyGetType(root) == CP_BODY_TYPE_DYNAMIC, "Internal Error: Non-dynamic body component root detected."); - - cpSpace *space = root->space; - cpBody *body = root; - while(body){ - cpBody *next = body->sleeping.next; - - body->sleeping.idleTime = 0.0f; - body->sleeping.root = NULL; - body->sleeping.next = NULL; - cpSpaceActivateBody(space, body); - - body = next; - } - - cpArrayDeleteObj(space->sleepingComponents, root); - } - - CP_BODY_FOREACH_ARBITER(body, arb){ - // Reset the idle timer of things the body is touching as well. - // That way things don't get left hanging in the air. - cpBody *other = (arb->body_a == body ? arb->body_b : arb->body_a); - if(cpBodyGetType(other) != CP_BODY_TYPE_STATIC) other->sleeping.idleTime = 0.0f; - } - } -} - -void -cpBodyActivateStatic(cpBody *body, cpShape *filter) -{ - cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_STATIC, "cpBodyActivateStatic() called on a non-static body."); - - CP_BODY_FOREACH_ARBITER(body, arb){ - if(!filter || filter == arb->a || filter == arb->b){ - cpBodyActivate(arb->body_a == body ? arb->body_b : arb->body_a); - } - } - - // TODO: should also activate joints? -} - -static inline void -cpBodyPushArbiter(cpBody *body, cpArbiter *arb) -{ - cpAssertSoft(cpArbiterThreadForBody(arb, body)->next == NULL, "Internal Error: Dangling contact graph pointers detected. (A)"); - cpAssertSoft(cpArbiterThreadForBody(arb, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (B)"); - - cpArbiter *next = body->arbiterList; - cpAssertSoft(next == NULL || cpArbiterThreadForBody(next, body)->prev == NULL, "Internal Error: Dangling contact graph pointers detected. (C)"); - cpArbiterThreadForBody(arb, body)->next = next; - - if(next) cpArbiterThreadForBody(next, body)->prev = arb; - body->arbiterList = arb; -} - -static inline void -ComponentAdd(cpBody *root, cpBody *body){ - body->sleeping.root = root; - - if(body != root){ - body->sleeping.next = root->sleeping.next; - root->sleeping.next = body; - } -} - -static inline void -FloodFillComponent(cpBody *root, cpBody *body) -{ - // Kinematic bodies cannot be put to sleep and prevent bodies they are touching from sleeping. - // Static bodies are effectively sleeping all the time. - if(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC){ - cpBody *other_root = ComponentRoot(body); - if(other_root == NULL){ - ComponentAdd(root, body); - CP_BODY_FOREACH_ARBITER(body, arb) FloodFillComponent(root, (body == arb->body_a ? arb->body_b : arb->body_a)); - CP_BODY_FOREACH_CONSTRAINT(body, constraint) FloodFillComponent(root, (body == constraint->a ? constraint->b : constraint->a)); - } else { - cpAssertSoft(other_root == root, "Internal Error: Inconsistency dectected in the contact graph."); - } - } -} - -static inline cpBool -ComponentActive(cpBody *root, cpFloat threshold) -{ - CP_BODY_FOREACH_COMPONENT(root, body){ - if(body->sleeping.idleTime < threshold) return cpTrue; - } - - return cpFalse; -} - -void -cpSpaceProcessComponents(cpSpace *space, cpFloat dt) -{ - cpBool sleep = (space->sleepTimeThreshold != INFINITY); - cpArray *bodies = space->dynamicBodies; - -#ifndef NDEBUG - for(int i=0; inum; i++){ - cpBody *body = (cpBody*)bodies->arr[i]; - - cpAssertSoft(body->sleeping.next == NULL, "Internal Error: Dangling next pointer detected in contact graph."); - cpAssertSoft(body->sleeping.root == NULL, "Internal Error: Dangling root pointer detected in contact graph."); - } -#endif - - // Calculate the kinetic energy of all the bodies. - if(sleep){ - cpFloat dv = space->idleSpeedThreshold; - cpFloat dvsq = (dv ? dv*dv : cpvlengthsq(space->gravity)*dt*dt); - - // update idling and reset component nodes - for(int i=0; inum; i++){ - cpBody *body = (cpBody*)bodies->arr[i]; - - // TODO should make a separate array for kinematic bodies. - if(cpBodyGetType(body) != CP_BODY_TYPE_DYNAMIC) continue; - - // Need to deal with infinite mass objects - cpFloat keThreshold = (dvsq ? body->m*dvsq : 0.0f); - body->sleeping.idleTime = (cpBodyKineticEnergy(body) > keThreshold ? 0.0f : body->sleeping.idleTime + dt); - } - } - - // Awaken any sleeping bodies found and then push arbiters to the bodies' lists. - cpArray *arbiters = space->arbiters; - for(int i=0, count=arbiters->num; iarr[i]; - cpBody *a = arb->body_a, *b = arb->body_b; - - if(sleep){ - // TODO checking cpBodyIsSleepin() redundant? - if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(a)) cpBodyActivate(a); - if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC || cpBodyIsSleeping(b)) cpBodyActivate(b); - } - - cpBodyPushArbiter(a, arb); - cpBodyPushArbiter(b, arb); - } - - if(sleep){ - // Bodies should be held active if connected by a joint to a kinematic. - cpArray *constraints = space->constraints; - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - cpBody *a = constraint->a, *b = constraint->b; - - if(cpBodyGetType(b) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(a); - if(cpBodyGetType(a) == CP_BODY_TYPE_KINEMATIC) cpBodyActivate(b); - } - - // Generate components and deactivate sleeping ones - for(int i=0; inum;){ - cpBody *body = (cpBody*)bodies->arr[i]; - - if(ComponentRoot(body) == NULL){ - // Body not in a component yet. Perform a DFS to flood fill mark - // the component in the contact graph using this body as the root. - FloodFillComponent(body, body); - - // Check if the component should be put to sleep. - if(!ComponentActive(body, space->sleepTimeThreshold)){ - cpArrayPush(space->sleepingComponents, body); - CP_BODY_FOREACH_COMPONENT(body, other) cpSpaceDeactivateBody(space, other); - - // cpSpaceDeactivateBody() removed the current body from the list. - // Skip incrementing the index counter. - continue; - } - } - - i++; - - // Only sleeping bodies retain their component node pointers. - body->sleeping.root = NULL; - body->sleeping.next = NULL; - } - } -} - -void -cpBodySleep(cpBody *body) -{ - cpBodySleepWithGroup(body, NULL); -} - -void -cpBodySleepWithGroup(cpBody *body, cpBody *group){ - cpAssertHard(cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC, "Non-dynamic bodies cannot be put to sleep."); - - cpSpace *space = body->space; - cpAssertHard(!cpSpaceIsLocked(space), "Bodies cannot be put to sleep during a query or a call to cpSpaceStep(). Put these calls into a post-step callback."); - cpAssertHard(cpSpaceGetSleepTimeThreshold(space) < INFINITY, "Sleeping is not enabled on the space. You cannot sleep a body without setting a sleep time threshold on the space."); - cpAssertHard(group == NULL || cpBodyIsSleeping(group), "Cannot use a non-sleeping body as a group identifier."); - - if(cpBodyIsSleeping(body)){ - cpAssertHard(ComponentRoot(body) == ComponentRoot(group), "The body is already sleeping and it's group cannot be reassigned."); - return; - } - - CP_BODY_FOREACH_SHAPE(body, shape) cpShapeCacheBB(shape); - cpSpaceDeactivateBody(space, body); - - if(group){ - cpBody *root = ComponentRoot(group); - - body->sleeping.root = root; - body->sleeping.next = root->sleeping.next; - body->sleeping.idleTime = 0.0f; - - root->sleeping.next = body; - } else { - body->sleeping.root = body; - body->sleeping.next = NULL; - body->sleeping.idleTime = 0.0f; - - cpArrayPush(space->sleepingComponents, body); - } - - cpArrayDeleteObj(space->dynamicBodies, body); -} diff --git a/3rdparty/chipmunk/src/cpSpaceDebug.c b/3rdparty/chipmunk/src/cpSpaceDebug.c deleted file mode 100644 index 6b80894b0f18..000000000000 --- a/3rdparty/chipmunk/src/cpSpaceDebug.c +++ /dev/null @@ -1,187 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -#ifndef CP_SPACE_DISABLE_DEBUG_API - -static void -cpSpaceDebugDrawShape(cpShape *shape, cpSpaceDebugDrawOptions *options) -{ - cpBody *body = shape->body; - cpDataPointer data = options->data; - - cpSpaceDebugColor outline_color = options->shapeOutlineColor; - cpSpaceDebugColor fill_color = options->colorForShape(shape, data); - - switch(shape->klass->type){ - case CP_CIRCLE_SHAPE: { - cpCircleShape *circle = (cpCircleShape *)shape; - options->drawCircle(circle->tc, body->a, circle->r, outline_color, fill_color, data); - break; - } - case CP_SEGMENT_SHAPE: { - cpSegmentShape *seg = (cpSegmentShape *)shape; - options->drawFatSegment(seg->ta, seg->tb, seg->r, outline_color, fill_color, data); - break; - } - case CP_POLY_SHAPE: { - cpPolyShape *poly = (cpPolyShape *)shape; - - int count = poly->count; - struct cpSplittingPlane *planes = poly->planes; - cpVect *verts = (cpVect *)alloca(count*sizeof(cpVect)); - - for(int i=0; idrawPolygon(count, verts, poly->r, outline_color, fill_color, data); - break; - } - default: break; - } -} - -static const cpVect spring_verts[] = { - {0.00f, 0.0f}, - {0.20f, 0.0f}, - {0.25f, 3.0f}, - {0.30f,-6.0f}, - {0.35f, 6.0f}, - {0.40f,-6.0f}, - {0.45f, 6.0f}, - {0.50f,-6.0f}, - {0.55f, 6.0f}, - {0.60f,-6.0f}, - {0.65f, 6.0f}, - {0.70f,-3.0f}, - {0.75f, 6.0f}, - {0.80f, 0.0f}, - {1.00f, 0.0f}, -}; -static const int spring_count = sizeof(spring_verts)/sizeof(cpVect); - -static void -cpSpaceDebugDrawConstraint(cpConstraint *constraint, cpSpaceDebugDrawOptions *options) -{ - cpDataPointer data = options->data; - cpSpaceDebugColor color = options->constraintColor; - - cpBody *body_a = constraint->a; - cpBody *body_b = constraint->b; - - if(cpConstraintIsPinJoint(constraint)){ - cpPinJoint *joint = (cpPinJoint *)constraint; - - cpVect a = cpTransformPoint(body_a->transform, joint->anchorA); - cpVect b = cpTransformPoint(body_b->transform, joint->anchorB); - - options->drawDot(5, a, color, data); - options->drawDot(5, b, color, data); - options->drawSegment(a, b, color, data); - } else if(cpConstraintIsSlideJoint(constraint)){ - cpSlideJoint *joint = (cpSlideJoint *)constraint; - - cpVect a = cpTransformPoint(body_a->transform, joint->anchorA); - cpVect b = cpTransformPoint(body_b->transform, joint->anchorB); - - options->drawDot(5, a, color, data); - options->drawDot(5, b, color, data); - options->drawSegment(a, b, color, data); - } else if(cpConstraintIsPivotJoint(constraint)){ - cpPivotJoint *joint = (cpPivotJoint *)constraint; - - cpVect a = cpTransformPoint(body_a->transform, joint->anchorA); - cpVect b = cpTransformPoint(body_b->transform, joint->anchorB); - - options->drawDot(5, a, color, data); - options->drawDot(5, b, color, data); - } else if(cpConstraintIsGrooveJoint(constraint)){ - cpGrooveJoint *joint = (cpGrooveJoint *)constraint; - - cpVect a = cpTransformPoint(body_a->transform, joint->grv_a); - cpVect b = cpTransformPoint(body_a->transform, joint->grv_b); - cpVect c = cpTransformPoint(body_b->transform, joint->anchorB); - - options->drawDot(5, c, color, data); - options->drawSegment(a, b, color, data); - } else if(cpConstraintIsDampedSpring(constraint)){ - cpDampedSpring *spring = (cpDampedSpring *)constraint; - - cpVect a = cpTransformPoint(body_a->transform, spring->anchorA); - cpVect b = cpTransformPoint(body_b->transform, spring->anchorB); - - options->drawDot(5, a, color, data); - options->drawDot(5, b, color, data); - - cpVect delta = cpvsub(b, a); - cpFloat cos = delta.x; - cpFloat sin = delta.y; - cpFloat s = 1.0f/cpvlength(delta); - - cpVect r1 = cpv(cos, -sin*s); - cpVect r2 = cpv(sin, cos*s); - - cpVect *verts = (cpVect *)alloca(spring_count*sizeof(cpVect)); - for(int i=0; idrawSegment(verts[i], verts[i + 1], color, data); - } - } -} - -void -cpSpaceDebugDraw(cpSpace *space, cpSpaceDebugDrawOptions *options) -{ - if(options->flags & CP_SPACE_DEBUG_DRAW_SHAPES){ - cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)cpSpaceDebugDrawShape, options); - } - - if(options->flags & CP_SPACE_DEBUG_DRAW_CONSTRAINTS){ - cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)cpSpaceDebugDrawConstraint, options); - } - - if(options->flags & CP_SPACE_DEBUG_DRAW_COLLISION_POINTS){ - cpArray *arbiters = space->arbiters; - cpSpaceDebugColor color = options->collisionPointColor; - cpSpaceDebugDrawSegmentImpl draw_seg = options->drawSegment; - cpDataPointer data = options->data; - - for(int i=0; inum; i++){ - cpArbiter *arb = (cpArbiter*)arbiters->arr[i]; - cpVect n = arb->n; - - for(int j=0; jcount; j++){ - cpVect p1 = cpvadd(arb->body_a->p, arb->contacts[j].r1); - cpVect p2 = cpvadd(arb->body_b->p, arb->contacts[j].r2); - - cpFloat d = 2.0f; - cpVect a = cpvadd(p1, cpvmult(n, -d)); - cpVect b = cpvadd(p2, cpvmult(n, d)); - draw_seg(a, b, color, data); - } - } - } -} - -#endif diff --git a/3rdparty/chipmunk/src/cpSpaceHash.c b/3rdparty/chipmunk/src/cpSpaceHash.c deleted file mode 100644 index 556c8d38dc2c..000000000000 --- a/3rdparty/chipmunk/src/cpSpaceHash.c +++ /dev/null @@ -1,634 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" -#include "prime.h" - -typedef struct cpSpaceHashBin cpSpaceHashBin; -typedef struct cpHandle cpHandle; - -struct cpSpaceHash { - cpSpatialIndex spatialIndex; - - int numcells; - cpFloat celldim; - - cpSpaceHashBin **table; - cpHashSet *handleSet; - - cpSpaceHashBin *pooledBins; - cpArray *pooledHandles; - cpArray *allocatedBuffers; - - cpTimestamp stamp; -}; - - -//MARK: Handle Functions - -struct cpHandle { - void *obj; - int retain; - cpTimestamp stamp; -}; - -static cpHandle* -cpHandleInit(cpHandle *hand, void *obj) -{ - hand->obj = obj; - hand->retain = 0; - hand->stamp = 0; - - return hand; -} - -static inline void cpHandleRetain(cpHandle *hand){hand->retain++;} - -static inline void -cpHandleRelease(cpHandle *hand, cpArray *pooledHandles) -{ - hand->retain--; - if(hand->retain == 0) cpArrayPush(pooledHandles, hand); -} - -static int handleSetEql(void *obj, cpHandle *hand){return (obj == hand->obj);} - -static void * -handleSetTrans(void *obj, cpSpaceHash *hash) -{ - if(hash->pooledHandles->num == 0){ - // handle pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(cpHandle); - cpAssertHard(count, "Internal Error: Buffer size is too small."); - - cpHandle *buffer = (cpHandle *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(hash->allocatedBuffers, buffer); - - for(int i=0; ipooledHandles, buffer + i); - } - - cpHandle *hand = cpHandleInit((cpHandle *)cpArrayPop(hash->pooledHandles), obj); - cpHandleRetain(hand); - - return hand; -} - -//MARK: Bin Functions - -struct cpSpaceHashBin { - cpHandle *handle; - cpSpaceHashBin *next; -}; - -static inline void -recycleBin(cpSpaceHash *hash, cpSpaceHashBin *bin) -{ - bin->next = hash->pooledBins; - hash->pooledBins = bin; -} - -static inline void -clearTableCell(cpSpaceHash *hash, int idx) -{ - cpSpaceHashBin *bin = hash->table[idx]; - while(bin){ - cpSpaceHashBin *next = bin->next; - - cpHandleRelease(bin->handle, hash->pooledHandles); - recycleBin(hash, bin); - - bin = next; - } - - hash->table[idx] = NULL; -} - -static void -clearTable(cpSpaceHash *hash) -{ - for(int i=0; inumcells; i++) clearTableCell(hash, i); -} - -// Get a recycled or new bin. -static inline cpSpaceHashBin * -getEmptyBin(cpSpaceHash *hash) -{ - cpSpaceHashBin *bin = hash->pooledBins; - - if(bin){ - hash->pooledBins = bin->next; - return bin; - } else { - // Pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(cpSpaceHashBin); - cpAssertHard(count, "Internal Error: Buffer size is too small."); - - cpSpaceHashBin *buffer = (cpSpaceHashBin *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(hash->allocatedBuffers, buffer); - - // push all but the first one, return the first instead - for(int i=1; itable); - - hash->numcells = numcells; - hash->table = (cpSpaceHashBin **)cpcalloc(numcells, sizeof(cpSpaceHashBin *)); -} - -static inline cpSpatialIndexClass *Klass(void); - -cpSpatialIndex * -cpSpaceHashInit(cpSpaceHash *hash, cpFloat celldim, int numcells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - cpSpatialIndexInit((cpSpatialIndex *)hash, Klass(), bbfunc, staticIndex); - - cpSpaceHashAllocTable(hash, next_prime(numcells)); - hash->celldim = celldim; - - hash->handleSet = cpHashSetNew(0, (cpHashSetEqlFunc)handleSetEql); - - hash->pooledHandles = cpArrayNew(0); - - hash->pooledBins = NULL; - hash->allocatedBuffers = cpArrayNew(0); - - hash->stamp = 1; - - return (cpSpatialIndex *)hash; -} - -cpSpatialIndex * -cpSpaceHashNew(cpFloat celldim, int cells, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - return cpSpaceHashInit(cpSpaceHashAlloc(), celldim, cells, bbfunc, staticIndex); -} - -static void -cpSpaceHashDestroy(cpSpaceHash *hash) -{ - if(hash->table) clearTable(hash); - cpfree(hash->table); - - cpHashSetFree(hash->handleSet); - - cpArrayFreeEach(hash->allocatedBuffers, cpfree); - cpArrayFree(hash->allocatedBuffers); - cpArrayFree(hash->pooledHandles); -} - -//MARK: Helper Functions - -static inline cpBool -containsHandle(cpSpaceHashBin *bin, cpHandle *hand) -{ - while(bin){ - if(bin->handle == hand) return cpTrue; - bin = bin->next; - } - - return cpFalse; -} - -// The hash function itself. -static inline cpHashValue -hash_func(cpHashValue x, cpHashValue y, cpHashValue n) -{ - return (x*1640531513ul ^ y*2654435789ul) % n; -} - -// Much faster than (int)floor(f) -// Profiling showed floor() to be a sizable performance hog -static inline int -floor_int(cpFloat f) -{ - int i = (int)f; - return (f < 0.0f && f != i ? i - 1 : i); -} - -static inline void -hashHandle(cpSpaceHash *hash, cpHandle *hand, cpBB bb) -{ - // Find the dimensions in cell coordinates. - cpFloat dim = hash->celldim; - int l = floor_int(bb.l/dim); // Fix by ShiftZ - int r = floor_int(bb.r/dim); - int b = floor_int(bb.b/dim); - int t = floor_int(bb.t/dim); - - int n = hash->numcells; - for(int i=l; i<=r; i++){ - for(int j=b; j<=t; j++){ - cpHashValue idx = hash_func(i,j,n); - cpSpaceHashBin *bin = hash->table[idx]; - - // Don't add an object twice to the same cell. - if(containsHandle(bin, hand)) continue; - - cpHandleRetain(hand); - // Insert a new bin for the handle in this cell. - cpSpaceHashBin *newBin = getEmptyBin(hash); - newBin->handle = hand; - newBin->next = bin; - hash->table[idx] = newBin; - } - } -} - -//MARK: Basic Operations - -static void -cpSpaceHashInsert(cpSpaceHash *hash, void *obj, cpHashValue hashid) -{ - cpHandle *hand = (cpHandle *)cpHashSetInsert(hash->handleSet, hashid, obj, (cpHashSetTransFunc)handleSetTrans, hash); - hashHandle(hash, hand, hash->spatialIndex.bbfunc(obj)); -} - -static void -cpSpaceHashRehashObject(cpSpaceHash *hash, void *obj, cpHashValue hashid) -{ - cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj); - - if(hand){ - hand->obj = NULL; - cpHandleRelease(hand, hash->pooledHandles); - - cpSpaceHashInsert(hash, obj, hashid); - } -} - -static void -rehash_helper(cpHandle *hand, cpSpaceHash *hash) -{ - hashHandle(hash, hand, hash->spatialIndex.bbfunc(hand->obj)); -} - -static void -cpSpaceHashRehash(cpSpaceHash *hash) -{ - clearTable(hash); - cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)rehash_helper, hash); -} - -static void -cpSpaceHashRemove(cpSpaceHash *hash, void *obj, cpHashValue hashid) -{ - cpHandle *hand = (cpHandle *)cpHashSetRemove(hash->handleSet, hashid, obj); - - if(hand){ - hand->obj = NULL; - cpHandleRelease(hand, hash->pooledHandles); - } -} - -typedef struct eachContext { - cpSpatialIndexIteratorFunc func; - void *data; -} eachContext; - -static void eachHelper(cpHandle *hand, eachContext *context){context->func(hand->obj, context->data);} - -static void -cpSpaceHashEach(cpSpaceHash *hash, cpSpatialIndexIteratorFunc func, void *data) -{ - eachContext context = {func, data}; - cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)eachHelper, &context); -} - -static void -remove_orphaned_handles(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr) -{ - cpSpaceHashBin *bin = *bin_ptr; - while(bin){ - cpHandle *hand = bin->handle; - cpSpaceHashBin *next = bin->next; - - if(!hand->obj){ - // orphaned handle, unlink and recycle the bin - (*bin_ptr) = bin->next; - recycleBin(hash, bin); - - cpHandleRelease(hand, hash->pooledHandles); - } else { - bin_ptr = &bin->next; - } - - bin = next; - } -} - -//MARK: Query Functions - -static inline void -query_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexQueryFunc func, void *data) -{ - restart: - for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){ - cpHandle *hand = bin->handle; - void *other = hand->obj; - - if(hand->stamp == hash->stamp || obj == other){ - continue; - } else if(other){ - func(obj, other, 0, data); - hand->stamp = hash->stamp; - } else { - // The object for this handle has been removed - // cleanup this cell and restart the query - remove_orphaned_handles(hash, bin_ptr); - goto restart; // GCC not smart enough/able to tail call an inlined function. - } - } -} - -static void -cpSpaceHashQuery(cpSpaceHash *hash, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) -{ - // Get the dimensions in cell coordinates. - cpFloat dim = hash->celldim; - int l = floor_int(bb.l/dim); // Fix by ShiftZ - int r = floor_int(bb.r/dim); - int b = floor_int(bb.b/dim); - int t = floor_int(bb.t/dim); - - int n = hash->numcells; - cpSpaceHashBin **table = hash->table; - - // Iterate over the cells and query them. - for(int i=l; i<=r; i++){ - for(int j=b; j<=t; j++){ - query_helper(hash, &table[hash_func(i,j,n)], obj, func, data); - } - } - - hash->stamp++; -} - -// Similar to struct eachPair above. -typedef struct queryRehashContext { - cpSpaceHash *hash; - cpSpatialIndexQueryFunc func; - void *data; -} queryRehashContext; - -// Hashset iterator func used with cpSpaceHashQueryRehash(). -static void -queryRehash_helper(cpHandle *hand, queryRehashContext *context) -{ - cpSpaceHash *hash = context->hash; - cpSpatialIndexQueryFunc func = context->func; - void *data = context->data; - - cpFloat dim = hash->celldim; - int n = hash->numcells; - - void *obj = hand->obj; - cpBB bb = hash->spatialIndex.bbfunc(obj); - - int l = floor_int(bb.l/dim); - int r = floor_int(bb.r/dim); - int b = floor_int(bb.b/dim); - int t = floor_int(bb.t/dim); - - cpSpaceHashBin **table = hash->table; - - for(int i=l; i<=r; i++){ - for(int j=b; j<=t; j++){ - cpHashValue idx = hash_func(i,j,n); - cpSpaceHashBin *bin = table[idx]; - - if(containsHandle(bin, hand)) continue; - - cpHandleRetain(hand); // this MUST be done first in case the object is removed in func() - query_helper(hash, &bin, obj, func, data); - - cpSpaceHashBin *newBin = getEmptyBin(hash); - newBin->handle = hand; - newBin->next = bin; - table[idx] = newBin; - } - } - - // Increment the stamp for each object hashed. - hash->stamp++; -} - -static void -cpSpaceHashReindexQuery(cpSpaceHash *hash, cpSpatialIndexQueryFunc func, void *data) -{ - clearTable(hash); - - queryRehashContext context = {hash, func, data}; - cpHashSetEach(hash->handleSet, (cpHashSetIteratorFunc)queryRehash_helper, &context); - - cpSpatialIndexCollideStatic((cpSpatialIndex *)hash, hash->spatialIndex.staticIndex, func, data); -} - -static inline cpFloat -segmentQuery_helper(cpSpaceHash *hash, cpSpaceHashBin **bin_ptr, void *obj, cpSpatialIndexSegmentQueryFunc func, void *data) -{ - cpFloat t = 1.0f; - - restart: - for(cpSpaceHashBin *bin = *bin_ptr; bin; bin = bin->next){ - cpHandle *hand = bin->handle; - void *other = hand->obj; - - // Skip over certain conditions - if(hand->stamp == hash->stamp){ - continue; - } else if(other){ - t = cpfmin(t, func(obj, other, data)); - hand->stamp = hash->stamp; - } else { - // The object for this handle has been removed - // cleanup this cell and restart the query - remove_orphaned_handles(hash, bin_ptr); - goto restart; // GCC not smart enough/able to tail call an inlined function. - } - } - - return t; -} - -// modified from http://playtechs.blogspot.com/2007/03/raytracing-on-grid.html -static void -cpSpaceHashSegmentQuery(cpSpaceHash *hash, void *obj, cpVect a, cpVect b, cpFloat t_exit, cpSpatialIndexSegmentQueryFunc func, void *data) -{ - a = cpvmult(a, 1.0f/hash->celldim); - b = cpvmult(b, 1.0f/hash->celldim); - - int cell_x = floor_int(a.x), cell_y = floor_int(a.y); - - cpFloat t = 0; - - int x_inc, y_inc; - cpFloat temp_v, temp_h; - - if (b.x > a.x){ - x_inc = 1; - temp_h = (cpffloor(a.x + 1.0f) - a.x); - } else { - x_inc = -1; - temp_h = (a.x - cpffloor(a.x)); - } - - if (b.y > a.y){ - y_inc = 1; - temp_v = (cpffloor(a.y + 1.0f) - a.y); - } else { - y_inc = -1; - temp_v = (a.y - cpffloor(a.y)); - } - - // Division by zero is *very* slow on ARM - cpFloat dx = cpfabs(b.x - a.x), dy = cpfabs(b.y - a.y); - cpFloat dt_dx = (dx ? 1.0f/dx : INFINITY), dt_dy = (dy ? 1.0f/dy : INFINITY); - - // fix NANs in horizontal directions - cpFloat next_h = (temp_h ? temp_h*dt_dx : dt_dx); - cpFloat next_v = (temp_v ? temp_v*dt_dy : dt_dy); - - int n = hash->numcells; - cpSpaceHashBin **table = hash->table; - - while(t < t_exit){ - cpHashValue idx = hash_func(cell_x, cell_y, n); - t_exit = cpfmin(t_exit, segmentQuery_helper(hash, &table[idx], obj, func, data)); - - if (next_v < next_h){ - cell_y += y_inc; - t = next_v; - next_v += dt_dy; - } else { - cell_x += x_inc; - t = next_h; - next_h += dt_dx; - } - } - - hash->stamp++; -} - -//MARK: Misc - -void -cpSpaceHashResize(cpSpaceHash *hash, cpFloat celldim, int numcells) -{ - if(hash->spatialIndex.klass != Klass()){ - cpAssertWarn(cpFalse, "Ignoring cpSpaceHashResize() call to non-cpSpaceHash spatial index."); - return; - } - - clearTable(hash); - - hash->celldim = celldim; - cpSpaceHashAllocTable(hash, next_prime(numcells)); -} - -static int -cpSpaceHashCount(cpSpaceHash *hash) -{ - return cpHashSetCount(hash->handleSet); -} - -static int -cpSpaceHashContains(cpSpaceHash *hash, void *obj, cpHashValue hashid) -{ - return cpHashSetFind(hash->handleSet, hashid, obj) != NULL; -} - -static cpSpatialIndexClass klass = { - (cpSpatialIndexDestroyImpl)cpSpaceHashDestroy, - - (cpSpatialIndexCountImpl)cpSpaceHashCount, - (cpSpatialIndexEachImpl)cpSpaceHashEach, - (cpSpatialIndexContainsImpl)cpSpaceHashContains, - - (cpSpatialIndexInsertImpl)cpSpaceHashInsert, - (cpSpatialIndexRemoveImpl)cpSpaceHashRemove, - - (cpSpatialIndexReindexImpl)cpSpaceHashRehash, - (cpSpatialIndexReindexObjectImpl)cpSpaceHashRehashObject, - (cpSpatialIndexReindexQueryImpl)cpSpaceHashReindexQuery, - - (cpSpatialIndexQueryImpl)cpSpaceHashQuery, - (cpSpatialIndexSegmentQueryImpl)cpSpaceHashSegmentQuery, -}; - -static inline cpSpatialIndexClass *Klass(){return &klass;} - -//MARK: Debug Drawing - -//#define CP_BBTREE_DEBUG_DRAW -#ifdef CP_BBTREE_DEBUG_DRAW -#include "OpenGL/gl.h" -#include "OpenGL/glu.h" -#include - -void -cpSpaceHashRenderDebug(cpSpatialIndex *index) -{ - if(index->klass != &klass){ - cpAssertWarn(cpFalse, "Ignoring cpSpaceHashRenderDebug() call to non-spatial hash spatial index."); - return; - } - - cpSpaceHash *hash = (cpSpaceHash *)index; - cpBB bb = cpBBNew(-320, -240, 320, 240); - - cpFloat dim = hash->celldim; - int n = hash->numcells; - - int l = (int)floor(bb.l/dim); - int r = (int)floor(bb.r/dim); - int b = (int)floor(bb.b/dim); - int t = (int)floor(bb.t/dim); - - for(int i=l; i<=r; i++){ - for(int j=b; j<=t; j++){ - int cell_count = 0; - - int index = hash_func(i,j,n); - for(cpSpaceHashBin *bin = hash->table[index]; bin; bin = bin->next) - cell_count++; - - GLfloat v = 1.0f - (GLfloat)cell_count/10.0f; - glColor3f(v,v,v); - glRectf(i*dim, j*dim, (i + 1)*dim, (j + 1)*dim); - } - } -} -#endif diff --git a/3rdparty/chipmunk/src/cpSpaceQuery.c b/3rdparty/chipmunk/src/cpSpaceQuery.c deleted file mode 100644 index 1ce4a10c15a3..000000000000 --- a/3rdparty/chipmunk/src/cpSpaceQuery.c +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -//MARK: Nearest Point Query Functions - -struct PointQueryContext { - cpVect point; - cpFloat maxDistance; - cpShapeFilter filter; - cpSpacePointQueryFunc func; -}; - -static cpCollisionID -NearestPointQuery(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, void *data) -{ - if( - !cpShapeFilterReject(shape->filter, context->filter) - ){ - cpPointQueryInfo info; - cpShapePointQuery(shape, context->point, &info); - - if(info.shape && info.distance < context->maxDistance) context->func(shape, info.point, info.distance, info.gradient, data); - } - - return id; -} - -void -cpSpacePointQuery(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpSpacePointQueryFunc func, void *data) -{ - struct PointQueryContext context = {point, maxDistance, filter, func}; - cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f)); - - cpSpaceLock(space); { - cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data); - cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQuery, data); - } cpSpaceUnlock(space, cpTrue); -} - -static cpCollisionID -NearestPointQueryNearest(struct PointQueryContext *context, cpShape *shape, cpCollisionID id, cpPointQueryInfo *out) -{ - if( - !cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor - ){ - cpPointQueryInfo info; - cpShapePointQuery(shape, context->point, &info); - - if(info.distance < out->distance) (*out) = info; - } - - return id; -} - -cpShape * -cpSpacePointQueryNearest(cpSpace *space, cpVect point, cpFloat maxDistance, cpShapeFilter filter, cpPointQueryInfo *out) -{ - cpPointQueryInfo info = {NULL, cpvzero, maxDistance, cpvzero}; - if(out){ - (*out) = info; - } else { - out = &info; - } - - struct PointQueryContext context = { - point, maxDistance, - filter, - NULL - }; - - cpBB bb = cpBBNewForCircle(point, cpfmax(maxDistance, 0.0f)); - cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out); - cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)NearestPointQueryNearest, out); - - return (cpShape *)out->shape; -} - - -//MARK: Segment Query Functions - -struct SegmentQueryContext { - cpVect start, end; - cpFloat radius; - cpShapeFilter filter; - cpSpaceSegmentQueryFunc func; -}; - -static cpFloat -SegmentQuery(struct SegmentQueryContext *context, cpShape *shape, void *data) -{ - cpSegmentQueryInfo info; - - if( - !cpShapeFilterReject(shape->filter, context->filter) && - cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info) - ){ - context->func(shape, info.point, info.normal, info.alpha, data); - } - - return 1.0f; -} - -void -cpSpaceSegmentQuery(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSpaceSegmentQueryFunc func, void *data) -{ - struct SegmentQueryContext context = { - start, end, - radius, - filter, - func, - }; - - cpSpaceLock(space); { - cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data); - cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQuery, data); - } cpSpaceUnlock(space, cpTrue); -} - -static cpFloat -SegmentQueryFirst(struct SegmentQueryContext *context, cpShape *shape, cpSegmentQueryInfo *out) -{ - cpSegmentQueryInfo info; - - if( - !cpShapeFilterReject(shape->filter, context->filter) && !shape->sensor && - cpShapeSegmentQuery(shape, context->start, context->end, context->radius, &info) && - info.alpha < out->alpha - ){ - (*out) = info; - } - - return out->alpha; -} - -cpShape * -cpSpaceSegmentQueryFirst(cpSpace *space, cpVect start, cpVect end, cpFloat radius, cpShapeFilter filter, cpSegmentQueryInfo *out) -{ - cpSegmentQueryInfo info = {NULL, end, cpvzero, 1.0f}; - if(out){ - (*out) = info; - } else { - out = &info; - } - - struct SegmentQueryContext context = { - start, end, - radius, - filter, - NULL - }; - - cpSpatialIndexSegmentQuery(space->staticShapes, &context, start, end, 1.0f, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out); - cpSpatialIndexSegmentQuery(space->dynamicShapes, &context, start, end, out->alpha, (cpSpatialIndexSegmentQueryFunc)SegmentQueryFirst, out); - - return (cpShape *)out->shape; -} - -//MARK: BB Query Functions - -struct BBQueryContext { - cpBB bb; - cpShapeFilter filter; - cpSpaceBBQueryFunc func; -}; - -static cpCollisionID -BBQuery(struct BBQueryContext *context, cpShape *shape, cpCollisionID id, void *data) -{ - if( - !cpShapeFilterReject(shape->filter, context->filter) && - cpBBIntersects(context->bb, shape->bb) - ){ - context->func(shape, data); - } - - return id; -} - -void -cpSpaceBBQuery(cpSpace *space, cpBB bb, cpShapeFilter filter, cpSpaceBBQueryFunc func, void *data) -{ - struct BBQueryContext context = {bb, filter, func}; - - cpSpaceLock(space); { - cpSpatialIndexQuery(space->dynamicShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data); - cpSpatialIndexQuery(space->staticShapes, &context, bb, (cpSpatialIndexQueryFunc)BBQuery, data); - } cpSpaceUnlock(space, cpTrue); -} - -//MARK: Shape Query Functions - -struct ShapeQueryContext { - cpSpaceShapeQueryFunc func; - void *data; - cpBool anyCollision; -}; - -// Callback from the spatial hash. -static cpCollisionID -ShapeQuery(cpShape *a, cpShape *b, cpCollisionID id, struct ShapeQueryContext *context) -{ - if(cpShapeFilterReject(a->filter, b->filter) || a == b) return id; - - cpContactPointSet set = cpShapesCollide(a, b); - if(set.count){ - if(context->func) context->func(b, &set, context->data); - context->anyCollision = !(a->sensor || b->sensor); - } - - return id; -} - -cpBool -cpSpaceShapeQuery(cpSpace *space, cpShape *shape, cpSpaceShapeQueryFunc func, void *data) -{ - cpBody *body = shape->body; - cpBB bb = (body ? cpShapeUpdate(shape, body->transform) : shape->bb); - struct ShapeQueryContext context = {func, data, cpFalse}; - - cpSpaceLock(space); { - cpSpatialIndexQuery(space->dynamicShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context); - cpSpatialIndexQuery(space->staticShapes, shape, bb, (cpSpatialIndexQueryFunc)ShapeQuery, &context); - } cpSpaceUnlock(space, cpTrue); - - return context.anyCollision; -} diff --git a/3rdparty/chipmunk/src/cpSpaceStep.c b/3rdparty/chipmunk/src/cpSpaceStep.c deleted file mode 100644 index 85cbb3d0c865..000000000000 --- a/3rdparty/chipmunk/src/cpSpaceStep.c +++ /dev/null @@ -1,445 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -//MARK: Post Step Callback Functions - -cpPostStepCallback * -cpSpaceGetPostStepCallback(cpSpace *space, void *key) -{ - cpArray *arr = space->postStepCallbacks; - for(int i=0; inum; i++){ - cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i]; - if(callback && callback->key == key) return callback; - } - - return NULL; -} - -static void PostStepDoNothing(cpSpace *space, void *obj, void *data){} - -cpBool -cpSpaceAddPostStepCallback(cpSpace *space, cpPostStepFunc func, void *key, void *data) -{ - cpAssertWarn(space->locked, - "Adding a post-step callback when the space is not locked is unnecessary. " - "Post-step callbacks will not called until the end of the next call to cpSpaceStep() or the next query."); - - if(!cpSpaceGetPostStepCallback(space, key)){ - cpPostStepCallback *callback = (cpPostStepCallback *)cpcalloc(1, sizeof(cpPostStepCallback)); - callback->func = (func ? func : PostStepDoNothing); - callback->key = key; - callback->data = data; - - cpArrayPush(space->postStepCallbacks, callback); - return cpTrue; - } else { - return cpFalse; - } -} - -//MARK: Locking Functions - -void -cpSpaceLock(cpSpace *space) -{ - space->locked++; -} - -void -cpSpaceUnlock(cpSpace *space, cpBool runPostStep) -{ - space->locked--; - cpAssertHard(space->locked >= 0, "Internal Error: Space lock underflow."); - - if(space->locked == 0){ - cpArray *waking = space->rousedBodies; - - for(int i=0, count=waking->num; iarr[i]); - waking->arr[i] = NULL; - } - - waking->num = 0; - - if(space->locked == 0 && runPostStep && !space->skipPostStep){ - space->skipPostStep = cpTrue; - - cpArray *arr = space->postStepCallbacks; - for(int i=0; inum; i++){ - cpPostStepCallback *callback = (cpPostStepCallback *)arr->arr[i]; - cpPostStepFunc func = callback->func; - - // Mark the func as NULL in case calling it calls cpSpaceRunPostStepCallbacks() again. - // TODO: need more tests around this case I think. - callback->func = NULL; - if(func) func(space, callback->key, callback->data); - - arr->arr[i] = NULL; - cpfree(callback); - } - - arr->num = 0; - space->skipPostStep = cpFalse; - } - } -} - -//MARK: Contact Buffer Functions - -struct cpContactBufferHeader { - cpTimestamp stamp; - cpContactBufferHeader *next; - unsigned int numContacts; -}; - -#define CP_CONTACTS_BUFFER_SIZE ((CP_BUFFER_BYTES - sizeof(cpContactBufferHeader))/sizeof(struct cpContact)) -typedef struct cpContactBuffer { - cpContactBufferHeader header; - struct cpContact contacts[CP_CONTACTS_BUFFER_SIZE]; -} cpContactBuffer; - -static cpContactBufferHeader * -cpSpaceAllocContactBuffer(cpSpace *space) -{ - cpContactBuffer *buffer = (cpContactBuffer *)cpcalloc(1, sizeof(cpContactBuffer)); - cpArrayPush(space->allocatedBuffers, buffer); - return (cpContactBufferHeader *)buffer; -} - -static cpContactBufferHeader * -cpContactBufferHeaderInit(cpContactBufferHeader *header, cpTimestamp stamp, cpContactBufferHeader *splice) -{ - header->stamp = stamp; - header->next = (splice ? splice->next : header); - header->numContacts = 0; - - return header; -} - -void -cpSpacePushFreshContactBuffer(cpSpace *space) -{ - cpTimestamp stamp = space->stamp; - - cpContactBufferHeader *head = space->contactBuffersHead; - - if(!head){ - // No buffers have been allocated, make one - space->contactBuffersHead = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, NULL); - } else if(stamp - head->next->stamp > space->collisionPersistence){ - // The tail buffer is available, rotate the ring - cpContactBufferHeader *tail = head->next; - space->contactBuffersHead = cpContactBufferHeaderInit(tail, stamp, tail); - } else { - // Allocate a new buffer and push it into the ring - cpContactBufferHeader *buffer = cpContactBufferHeaderInit(cpSpaceAllocContactBuffer(space), stamp, head); - space->contactBuffersHead = head->next = buffer; - } -} - - -struct cpContact * -cpContactBufferGetArray(cpSpace *space) -{ - if(space->contactBuffersHead->numContacts + CP_MAX_CONTACTS_PER_ARBITER > CP_CONTACTS_BUFFER_SIZE){ - // contact buffer could overflow on the next collision, push a fresh one. - cpSpacePushFreshContactBuffer(space); - } - - cpContactBufferHeader *head = space->contactBuffersHead; - return ((cpContactBuffer *)head)->contacts + head->numContacts; -} - -void -cpSpacePushContacts(cpSpace *space, int count) -{ - cpAssertHard(count <= CP_MAX_CONTACTS_PER_ARBITER, "Internal Error: Contact buffer overflow!"); - space->contactBuffersHead->numContacts += count; -} - -static void -cpSpacePopContacts(cpSpace *space, int count){ - space->contactBuffersHead->numContacts -= count; -} - -//MARK: Collision Detection Functions - -static void * -cpSpaceArbiterSetTrans(cpShape **shapes, cpSpace *space) -{ - if(space->pooledArbiters->num == 0){ - // arbiter pool is exhausted, make more - int count = CP_BUFFER_BYTES/sizeof(cpArbiter); - cpAssertHard(count, "Internal Error: Buffer size too small."); - - cpArbiter *buffer = (cpArbiter *)cpcalloc(1, CP_BUFFER_BYTES); - cpArrayPush(space->allocatedBuffers, buffer); - - for(int i=0; ipooledArbiters, buffer + i); - } - - return cpArbiterInit((cpArbiter *)cpArrayPop(space->pooledArbiters), shapes[0], shapes[1]); -} - -static inline cpBool -QueryRejectConstraint(cpBody *a, cpBody *b) -{ - CP_BODY_FOREACH_CONSTRAINT(a, constraint){ - if( - !constraint->collideBodies && ( - (constraint->a == a && constraint->b == b) || - (constraint->a == b && constraint->b == a) - ) - ) return cpTrue; - } - - return cpFalse; -} - -static inline cpBool -QueryReject(cpShape *a, cpShape *b) -{ - return ( - // BBoxes must overlap - !cpBBIntersects(a->bb, b->bb) - // Don't collide shapes attached to the same body. - || a->body == b->body - // Don't collide shapes that are filtered. - || cpShapeFilterReject(a->filter, b->filter) - // Don't collide bodies if they have a constraint with collideBodies == cpFalse. - || QueryRejectConstraint(a->body, b->body) - ); -} - -// Callback from the spatial hash. -cpCollisionID -cpSpaceCollideShapes(cpShape *a, cpShape *b, cpCollisionID id, cpSpace *space) -{ - // Reject any of the simple cases - if(QueryReject(a,b)) return id; - - // Narrow-phase collision detection. - struct cpCollisionInfo info = cpCollide(a, b, id, cpContactBufferGetArray(space)); - - if(info.count == 0) return info.id; // Shapes are not colliding. - cpSpacePushContacts(space, info.count); - - // Get an arbiter from space->arbiterSet for the two shapes. - // This is where the persistant contact magic comes from. - const cpShape *shape_pair[] = {info.a, info.b}; - cpHashValue arbHashID = CP_HASH_PAIR((cpHashValue)info.a, (cpHashValue)info.b); - cpArbiter *arb = (cpArbiter *)cpHashSetInsert(space->cachedArbiters, arbHashID, shape_pair, (cpHashSetTransFunc)cpSpaceArbiterSetTrans, space); - cpArbiterUpdate(arb, &info, space); - - cpCollisionHandler *handler = arb->handler; - - // Call the begin function first if it's the first step - if(arb->state == CP_ARBITER_STATE_FIRST_COLLISION && !handler->beginFunc(arb, space, handler->userData)){ - cpArbiterIgnore(arb); // permanently ignore the collision until separation - } - - if( - // Ignore the arbiter if it has been flagged - (arb->state != CP_ARBITER_STATE_IGNORE) && - // Call preSolve - handler->preSolveFunc(arb, space, handler->userData) && - // Check (again) in case the pre-solve() callback called cpArbiterIgnored(). - arb->state != CP_ARBITER_STATE_IGNORE && - // Process, but don't add collisions for sensors. - !(a->sensor || b->sensor) && - // Don't process collisions between two infinite mass bodies. - // This includes collisions between two kinematic bodies, or a kinematic body and a static body. - !(a->body->m == INFINITY && b->body->m == INFINITY) - ){ - cpArrayPush(space->arbiters, arb); - } else { - cpSpacePopContacts(space, info.count); - - arb->contacts = NULL; - arb->count = 0; - - // Normally arbiters are set as used after calling the post-solve callback. - // However, post-solve() callbacks are not called for sensors or arbiters rejected from pre-solve. - if(arb->state != CP_ARBITER_STATE_IGNORE) arb->state = CP_ARBITER_STATE_NORMAL; - } - - // Time stamp the arbiter so we know it was used recently. - arb->stamp = space->stamp; - return info.id; -} - -// Hashset filter func to throw away old arbiters. -cpBool -cpSpaceArbiterSetFilter(cpArbiter *arb, cpSpace *space) -{ - cpTimestamp ticks = space->stamp - arb->stamp; - - cpBody *a = arb->body_a, *b = arb->body_b; - - // TODO: should make an arbiter state for this so it doesn't require filtering arbiters for dangling body pointers on body removal. - // Preserve arbiters on sensors and rejected arbiters for sleeping objects. - // This prevents errant separate callbacks from happenening. - if( - (cpBodyGetType(a) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(a)) && - (cpBodyGetType(b) == CP_BODY_TYPE_STATIC || cpBodyIsSleeping(b)) - ){ - return cpTrue; - } - - // Arbiter was used last frame, but not this one - if(ticks >= 1 && arb->state != CP_ARBITER_STATE_CACHED){ - arb->state = CP_ARBITER_STATE_CACHED; - cpCollisionHandler *handler = arb->handler; - handler->separateFunc(arb, space, handler->userData); - } - - if(ticks >= space->collisionPersistence){ - arb->contacts = NULL; - arb->count = 0; - - cpArrayPush(space->pooledArbiters, arb); - return cpFalse; - } - - return cpTrue; -} - -//MARK: All Important cpSpaceStep() Function - - void -cpShapeUpdateFunc(cpShape *shape, void *unused) -{ - cpShapeCacheBB(shape); -} - -void -cpSpaceStep(cpSpace *space, cpFloat dt) -{ - // don't step if the timestep is 0! - if(dt == 0.0f) return; - - space->stamp++; - - cpFloat prev_dt = space->curr_dt; - space->curr_dt = dt; - - cpArray *bodies = space->dynamicBodies; - cpArray *constraints = space->constraints; - cpArray *arbiters = space->arbiters; - - // Reset and empty the arbiter lists. - for(int i=0; inum; i++){ - cpArbiter *arb = (cpArbiter *)arbiters->arr[i]; - arb->state = CP_ARBITER_STATE_NORMAL; - - // If both bodies are awake, unthread the arbiter from the contact graph. - if(!cpBodyIsSleeping(arb->body_a) && !cpBodyIsSleeping(arb->body_b)){ - cpArbiterUnthread(arb); - } - } - arbiters->num = 0; - - cpSpaceLock(space); { - // Integrate positions - for(int i=0; inum; i++){ - cpBody *body = (cpBody *)bodies->arr[i]; - body->position_func(body, dt); - } - - // Find colliding pairs. - cpSpacePushFreshContactBuffer(space); - cpSpatialIndexEach(space->dynamicShapes, (cpSpatialIndexIteratorFunc)cpShapeUpdateFunc, NULL); - cpSpatialIndexReindexQuery(space->dynamicShapes, (cpSpatialIndexQueryFunc)cpSpaceCollideShapes, space); - } cpSpaceUnlock(space, cpFalse); - - // Rebuild the contact graph (and detect sleeping components if sleeping is enabled) - cpSpaceProcessComponents(space, dt); - - cpSpaceLock(space); { - // Clear out old cached arbiters and call separate callbacks - cpHashSetFilter(space->cachedArbiters, (cpHashSetFilterFunc)cpSpaceArbiterSetFilter, space); - - // Prestep the arbiters and constraints. - cpFloat slop = space->collisionSlop; - cpFloat biasCoef = 1.0f - cpfpow(space->collisionBias, dt); - for(int i=0; inum; i++){ - cpArbiterPreStep((cpArbiter *)arbiters->arr[i], dt, slop, biasCoef); - } - - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - - cpConstraintPreSolveFunc preSolve = constraint->preSolve; - if(preSolve) preSolve(constraint, space); - - constraint->klass->preStep(constraint, dt); - } - - // Integrate velocities. - cpFloat damping = cpfpow(space->damping, dt); - cpVect gravity = space->gravity; - for(int i=0; inum; i++){ - cpBody *body = (cpBody *)bodies->arr[i]; - body->velocity_func(body, gravity, damping, dt); - } - - // Apply cached impulses - cpFloat dt_coef = (prev_dt == 0.0f ? 0.0f : dt/prev_dt); - for(int i=0; inum; i++){ - cpArbiterApplyCachedImpulse((cpArbiter *)arbiters->arr[i], dt_coef); - } - - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - constraint->klass->applyCachedImpulse(constraint, dt_coef); - } - - // Run the impulse solver. - for(int i=0; iiterations; i++){ - for(int j=0; jnum; j++){ - cpArbiterApplyImpulse((cpArbiter *)arbiters->arr[j]); - } - - for(int j=0; jnum; j++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[j]; - constraint->klass->applyImpulse(constraint, dt); - } - } - - // Run the constraint post-solve callbacks - for(int i=0; inum; i++){ - cpConstraint *constraint = (cpConstraint *)constraints->arr[i]; - - cpConstraintPostSolveFunc postSolve = constraint->postSolve; - if(postSolve) postSolve(constraint, space); - } - - // run the post-solve callbacks - for(int i=0; inum; i++){ - cpArbiter *arb = (cpArbiter *) arbiters->arr[i]; - - cpCollisionHandler *handler = arb->handler; - handler->postSolveFunc(arb, space, handler->userData); - } - } cpSpaceUnlock(space, cpTrue); -} diff --git a/3rdparty/chipmunk/src/cpSpatialIndex.c b/3rdparty/chipmunk/src/cpSpatialIndex.c deleted file mode 100644 index 3fb7cb5d9113..000000000000 --- a/3rdparty/chipmunk/src/cpSpatialIndex.c +++ /dev/null @@ -1,69 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -void -cpSpatialIndexFree(cpSpatialIndex *index) -{ - if(index){ - cpSpatialIndexDestroy(index); - cpfree(index); - } -} - -cpSpatialIndex * -cpSpatialIndexInit(cpSpatialIndex *index, cpSpatialIndexClass *klass, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - index->klass = klass; - index->bbfunc = bbfunc; - index->staticIndex = staticIndex; - - if(staticIndex){ - cpAssertHard(!staticIndex->dynamicIndex, "This static index is already associated with a dynamic index."); - staticIndex->dynamicIndex = index; - } - - return index; -} - -typedef struct dynamicToStaticContext { - cpSpatialIndexBBFunc bbfunc; - cpSpatialIndex *staticIndex; - cpSpatialIndexQueryFunc queryFunc; - void *data; -} dynamicToStaticContext; - -static void -dynamicToStaticIter(void *obj, dynamicToStaticContext *context) -{ - cpSpatialIndexQuery(context->staticIndex, obj, context->bbfunc(obj), context->queryFunc, context->data); -} - -void -cpSpatialIndexCollideStatic(cpSpatialIndex *dynamicIndex, cpSpatialIndex *staticIndex, cpSpatialIndexQueryFunc func, void *data) -{ - if(staticIndex && cpSpatialIndexCount(staticIndex) > 0){ - dynamicToStaticContext context = {dynamicIndex->bbfunc, staticIndex, func, data}; - cpSpatialIndexEach(dynamicIndex, (cpSpatialIndexIteratorFunc)dynamicToStaticIter, &context); - } -} - diff --git a/3rdparty/chipmunk/src/cpSweep1D.c b/3rdparty/chipmunk/src/cpSweep1D.c deleted file mode 100644 index 94c4e2255c6f..000000000000 --- a/3rdparty/chipmunk/src/cpSweep1D.c +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" - -static inline cpSpatialIndexClass *Klass(void); - -//MARK: Basic Structures - -typedef struct Bounds { - cpFloat min, max; -} Bounds; - -typedef struct TableCell { - void *obj; - Bounds bounds; -} TableCell; - -struct cpSweep1D -{ - cpSpatialIndex spatialIndex; - - int num; - int max; - TableCell *table; -}; - -static inline cpBool -BoundsOverlap(Bounds a, Bounds b) -{ - return (a.min <= b.max && b.min <= a.max); -} - -static inline Bounds -BBToBounds(cpSweep1D *sweep, cpBB bb) -{ - Bounds bounds = {bb.l, bb.r}; - return bounds; -} - -static inline TableCell -MakeTableCell(cpSweep1D *sweep, void *obj) -{ - TableCell cell = {obj, BBToBounds(sweep, sweep->spatialIndex.bbfunc(obj))}; - return cell; -} - -//MARK: Memory Management Functions - -cpSweep1D * -cpSweep1DAlloc(void) -{ - return (cpSweep1D *)cpcalloc(1, sizeof(cpSweep1D)); -} - -static void -ResizeTable(cpSweep1D *sweep, int size) -{ - sweep->max = size; - sweep->table = (TableCell *)cprealloc(sweep->table, size*sizeof(TableCell)); -} - -cpSpatialIndex * -cpSweep1DInit(cpSweep1D *sweep, cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - cpSpatialIndexInit((cpSpatialIndex *)sweep, Klass(), bbfunc, staticIndex); - - sweep->num = 0; - ResizeTable(sweep, 32); - - return (cpSpatialIndex *)sweep; -} - -cpSpatialIndex * -cpSweep1DNew(cpSpatialIndexBBFunc bbfunc, cpSpatialIndex *staticIndex) -{ - return cpSweep1DInit(cpSweep1DAlloc(), bbfunc, staticIndex); -} - -static void -cpSweep1DDestroy(cpSweep1D *sweep) -{ - cpfree(sweep->table); - sweep->table = NULL; -} - -//MARK: Misc - -static int -cpSweep1DCount(cpSweep1D *sweep) -{ - return sweep->num; -} - -static void -cpSweep1DEach(cpSweep1D *sweep, cpSpatialIndexIteratorFunc func, void *data) -{ - TableCell *table = sweep->table; - for(int i=0, count=sweep->num; itable; - for(int i=0, count=sweep->num; inum == sweep->max) ResizeTable(sweep, sweep->max*2); - - sweep->table[sweep->num] = MakeTableCell(sweep, obj); - sweep->num++; -} - -static void -cpSweep1DRemove(cpSweep1D *sweep, void *obj, cpHashValue hashid) -{ - TableCell *table = sweep->table; - for(int i=0, count=sweep->num; inum; - - table[i] = table[num]; - table[num].obj = NULL; - - return; - } - } -} - -//MARK: Reindexing Functions - -static void -cpSweep1DReindexObject(cpSweep1D *sweep, void *obj, cpHashValue hashid) -{ - // Nothing to do here -} - -static void -cpSweep1DReindex(cpSweep1D *sweep) -{ - // Nothing to do here - // Could perform a sort, but queries are not accelerated anyway. -} - -//MARK: Query Functions - -static void -cpSweep1DQuery(cpSweep1D *sweep, void *obj, cpBB bb, cpSpatialIndexQueryFunc func, void *data) -{ - // Implementing binary search here would allow you to find an upper limit - // but not a lower limit. Probably not worth the hassle. - - Bounds bounds = BBToBounds(sweep, bb); - - TableCell *table = sweep->table; - for(int i=0, count=sweep->num; itable; - for(int i=0, count=sweep->num; ibounds.min < b->bounds.min ? -1 : (a->bounds.min > b->bounds.min ? 1 : 0)); -} - -static void -cpSweep1DReindexQuery(cpSweep1D *sweep, cpSpatialIndexQueryFunc func, void *data) -{ - TableCell *table = sweep->table; - int count = sweep->num; - - // Update bounds and sort - for(int i=0; ispatialIndex.staticIndex, func, data); -} - -static cpSpatialIndexClass klass = { - (cpSpatialIndexDestroyImpl)cpSweep1DDestroy, - - (cpSpatialIndexCountImpl)cpSweep1DCount, - (cpSpatialIndexEachImpl)cpSweep1DEach, - (cpSpatialIndexContainsImpl)cpSweep1DContains, - - (cpSpatialIndexInsertImpl)cpSweep1DInsert, - (cpSpatialIndexRemoveImpl)cpSweep1DRemove, - - (cpSpatialIndexReindexImpl)cpSweep1DReindex, - (cpSpatialIndexReindexObjectImpl)cpSweep1DReindexObject, - (cpSpatialIndexReindexQueryImpl)cpSweep1DReindexQuery, - - (cpSpatialIndexQueryImpl)cpSweep1DQuery, - (cpSpatialIndexSegmentQueryImpl)cpSweep1DSegmentQuery, -}; - -static inline cpSpatialIndexClass *Klass(){return &klass;} - diff --git a/3rdparty/chipmunk/src/prime.h b/3rdparty/chipmunk/src/prime.h deleted file mode 100644 index d470c2cdd76d..000000000000 --- a/3rdparty/chipmunk/src/prime.h +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -// Used for resizing hash tables. -// Values approximately double. -// http://planetmath.org/encyclopedia/GoodHashTablePrimes.html -static int primes[] = { - 5, - 13, - 23, - 47, - 97, - 193, - 389, - 769, - 1543, - 3079, - 6151, - 12289, - 24593, - 49157, - 98317, - 196613, - 393241, - 786433, - 1572869, - 3145739, - 6291469, - 12582917, - 25165843, - 50331653, - 100663319, - 201326611, - 402653189, - 805306457, - 1610612741, - 0, -}; - -static inline int -next_prime(int n) -{ - int i = 0; - while(n > primes[i]){ - i++; - cpAssertHard(primes[i], "Tried to resize a hash table to a size greater than 1610612741 O_o"); // realistically this should never happen - } - - return primes[i]; -} diff --git a/3rdparty/fast_float/ascii_number.h b/3rdparty/fast_float/ascii_number.h new file mode 100644 index 000000000000..97f0681077eb --- /dev/null +++ b/3rdparty/fast_float/ascii_number.h @@ -0,0 +1,588 @@ +#ifndef FASTFLOAT_ASCII_NUMBER_H +#define FASTFLOAT_ASCII_NUMBER_H + +#include +#include +#include +#include +#include +#include + +#include "float_common.h" + +#ifdef FASTFLOAT_SSE2 +#include +#endif + +#ifdef FASTFLOAT_NEON +#include +#endif + +namespace fast_float { + +template fastfloat_really_inline constexpr bool has_simd_opt() { +#ifdef FASTFLOAT_HAS_SIMD + return std::is_same::value; +#else + return false; +#endif +} + +// Next function can be micro-optimized, but compilers are entirely +// able to optimize it well. +template +fastfloat_really_inline constexpr bool is_integer(UC c) noexcept { + return !(c > UC('9') || c < UC('0')); +} + +fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) { + return (val & 0xFF00000000000000) >> 56 | (val & 0x00FF000000000000) >> 40 | + (val & 0x0000FF0000000000) >> 24 | (val & 0x000000FF00000000) >> 8 | + (val & 0x00000000FF000000) << 8 | (val & 0x0000000000FF0000) << 24 | + (val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56; +} + +// Read 8 UC into a u64. Truncates UC if not char. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +read8_to_u64(UC const *chars) { + if (cpp20_and_in_constexpr() || !std::is_same::value) { + uint64_t val = 0; + for (int i = 0; i < 8; ++i) { + val |= uint64_t(uint8_t(*chars)) << (i * 8); + ++chars; + } + return val; + } + uint64_t val; + ::memcpy(&val, chars, sizeof(uint64_t)); +#if FASTFLOAT_IS_BIG_ENDIAN == 1 + // Need to read as-if the number was in little-endian order. + val = byteswap(val); +#endif + return val; +} + +#ifdef FASTFLOAT_SSE2 + +fastfloat_really_inline uint64_t simd_read8_to_u64(__m128i const data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + __m128i const packed = _mm_packus_epi16(data, data); +#ifdef FASTFLOAT_64BIT + return uint64_t(_mm_cvtsi128_si64(packed)); +#else + uint64_t value; + // Visual Studio + older versions of GCC don't support _mm_storeu_si64 + _mm_storel_epi64(reinterpret_cast<__m128i *>(&value), packed); + return value; +#endif + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + _mm_loadu_si128(reinterpret_cast<__m128i const *>(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#elif defined(FASTFLOAT_NEON) + +fastfloat_really_inline uint64_t simd_read8_to_u64(uint16x8_t const data) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + uint8x8_t utf8_packed = vmovn_u16(data); + return vget_lane_u64(vreinterpret_u64_u8(utf8_packed), 0); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +fastfloat_really_inline uint64_t simd_read8_to_u64(char16_t const *chars) { + FASTFLOAT_SIMD_DISABLE_WARNINGS + return simd_read8_to_u64( + vld1q_u16(reinterpret_cast(chars))); + FASTFLOAT_SIMD_RESTORE_WARNINGS +} + +#endif // FASTFLOAT_SSE2 + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +uint64_t simd_read8_to_u64(UC const *) { + return 0; +} + +// credit @aqrit +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint32_t +parse_eight_digits_unrolled(uint64_t val) { + uint64_t const mask = 0x000000FF000000FF; + uint64_t const mul1 = 0x000F424000000064; // 100 + (1000000ULL << 32) + uint64_t const mul2 = 0x0000271000000001; // 1 + (10000ULL << 32) + val -= 0x3030303030303030; + val = (val * 10) + (val >> 8); // val = (val * 2561) >> 8; + val = (((val & mask) * mul1) + (((val >> 16) & mask) * mul2)) >> 32; + return uint32_t(val); +} + +// Call this if chars are definitely 8 digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint32_t +parse_eight_digits_unrolled(UC const *chars) noexcept { + if (cpp20_and_in_constexpr() || !has_simd_opt()) { + return parse_eight_digits_unrolled(read8_to_u64(chars)); // truncation okay + } + return parse_eight_digits_unrolled(simd_read8_to_u64(chars)); +} + +// credit @aqrit +fastfloat_really_inline constexpr bool +is_made_of_eight_digits_fast(uint64_t val) noexcept { + return !((((val + 0x4646464646464646) | (val - 0x3030303030303030)) & + 0x8080808080808080)); +} + +#ifdef FASTFLOAT_HAS_SIMD + +// Call this if chars might not be 8 digits. +// Using this style (instead of is_made_of_eight_digits_fast() then +// parse_eight_digits_unrolled()) ensures we don't load SIMD registers twice. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +simd_parse_if_eight_digits_unrolled(char16_t const *chars, + uint64_t &i) noexcept { + if (cpp20_and_in_constexpr()) { + return false; + } +#ifdef FASTFLOAT_SSE2 + FASTFLOAT_SIMD_DISABLE_WARNINGS + __m128i const data = + _mm_loadu_si128(reinterpret_cast<__m128i const *>(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + __m128i const t0 = _mm_add_epi16(data, _mm_set1_epi16(32720)); + __m128i const t1 = _mm_cmpgt_epi16(t0, _mm_set1_epi16(-32759)); + + if (_mm_movemask_epi8(t1) == 0) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#elif defined(FASTFLOAT_NEON) + FASTFLOAT_SIMD_DISABLE_WARNINGS + uint16x8_t const data = vld1q_u16(reinterpret_cast(chars)); + + // (x - '0') <= 9 + // http://0x80.pl/articles/simd-parsing-int-sequences.html + uint16x8_t const t0 = vsubq_u16(data, vmovq_n_u16('0')); + uint16x8_t const mask = vcltq_u16(t0, vmovq_n_u16('9' - '0' + 1)); + + if (vminvq_u16(mask) == 0xFFFF) { + i = i * 100000000 + parse_eight_digits_unrolled(simd_read8_to_u64(data)); + return true; + } else + return false; + FASTFLOAT_SIMD_RESTORE_WARNINGS +#else + (void)chars; + (void)i; + return false; +#endif // FASTFLOAT_SSE2 +} + +#endif // FASTFLOAT_HAS_SIMD + +// MSVC SFINAE is broken pre-VS2017 +#if defined(_MSC_VER) && _MSC_VER <= 1900 +template +#else +template ()) = 0> +#endif +// dummy for compile +bool simd_parse_if_eight_digits_unrolled(UC const *, uint64_t &) { + return 0; +} + +template ::value) = 0> +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(UC const *&p, UC const *const pend, uint64_t &i) { + if (!has_simd_opt()) { + return; + } + while ((std::distance(p, pend) >= 8) && + simd_parse_if_eight_digits_unrolled( + p, i)) { // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +loop_parse_if_eight_digits(char const *&p, char const *const pend, + uint64_t &i) { + // optimizes better than parse_if_eight_digits_unrolled() for UC = char. + while ((std::distance(p, pend) >= 8) && + is_made_of_eight_digits_fast(read8_to_u64(p))) { + i = i * 100000000 + + parse_eight_digits_unrolled(read8_to_u64( + p)); // in rare cases, this will overflow, but that's ok + p += 8; + } +} + +enum class parse_error { + no_error, + // [JSON-only] The minus sign must be followed by an integer. + missing_integer_after_sign, + // A sign must be followed by an integer or dot. + missing_integer_or_dot_after_sign, + // [JSON-only] The integer part must not have leading zeros. + leading_zeros_in_integer_part, + // [JSON-only] The integer part must have at least one digit. + no_digits_in_integer_part, + // [JSON-only] If there is a decimal point, there must be digits in the + // fractional part. + no_digits_in_fractional_part, + // The mantissa must have at least one digit. + no_digits_in_mantissa, + // Scientific notation requires an exponential part. + missing_exponential_part, +}; + +template struct parsed_number_string_t { + int64_t exponent{0}; + uint64_t mantissa{0}; + UC const *lastmatch{nullptr}; + bool negative{false}; + bool valid{false}; + bool too_many_digits{false}; + // contains the range of the significant digits + span integer{}; // non-nullable + span fraction{}; // nullable + parse_error error{parse_error::no_error}; +}; + +using byte_span = span; +using parsed_number_string = parsed_number_string_t; + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +report_parse_error(UC const *p, parse_error error) { + parsed_number_string_t answer; + answer.valid = false; + answer.lastmatch = p; + answer.error = error; + return answer; +} + +// Assuming that you use no more than 19 digits, this will +// parse an ASCII string. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 parsed_number_string_t +parse_number_string(UC const *p, UC const *pend, + parse_options_t options) noexcept { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + UC const decimal_point = options.decimal_point; + + parsed_number_string_t answer; + answer.valid = false; + answer.too_many_digits = false; + // assume p < pend, so dereference without checks; + answer.negative = (*p == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*p == UC('-')) || (uint64_t(fmt & chars_format::allow_leading_plus) && + !basic_json_fmt && *p == UC('+'))) { + ++p; + if (p == pend) { + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { + if (!is_integer(*p)) { // a sign must be followed by an integer + return report_parse_error(p, + parse_error::missing_integer_after_sign); + } + } + else { + if (!is_integer(*p) && + (*p != + decimal_point)) { // a sign must be followed by an integer or the dot + return report_parse_error( + p, parse_error::missing_integer_or_dot_after_sign); + } + } + } + UC const *const start_digits = p; + + uint64_t i = 0; // an unsigned int avoids signed overflows (which are bad) + + while ((p != pend) && is_integer(*p)) { + // a multiplication by 10 is cheaper than an arbitrary integer + // multiplication + i = 10 * i + + uint64_t(*p - + UC('0')); // might overflow, we will handle the overflow later + ++p; + } + UC const *const end_of_integer_part = p; + int64_t digit_count = int64_t(end_of_integer_part - start_digits); + answer.integer = span(start_digits, size_t(digit_count)); + FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { + // at least 1 digit in integer part, without leading zeros + if (digit_count == 0) { + return report_parse_error(p, parse_error::no_digits_in_integer_part); + } + if ((start_digits[0] == UC('0') && digit_count > 1)) { + return report_parse_error(start_digits, + parse_error::leading_zeros_in_integer_part); + } + } + + int64_t exponent = 0; + bool const has_decimal_point = (p != pend) && (*p == decimal_point); + if (has_decimal_point) { + ++p; + UC const *before = p; + // can occur at most twice without overflowing, but let it occur more, since + // for integers with many digits, digit parsing is the primary bottleneck. + loop_parse_if_eight_digits(p, pend, i); + + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + ++p; + i = i * 10 + digit; // in rare cases, this will overflow, but that's ok + } + exponent = before - p; + answer.fraction = span(before, size_t(p - before)); + digit_count -= exponent; + } + FASTFLOAT_IF_CONSTEXPR17(basic_json_fmt) { + // at least 1 digit in fractional part + if (has_decimal_point && exponent == 0) { + return report_parse_error(p, + parse_error::no_digits_in_fractional_part); + } + } + else if (digit_count == 0) { // we must have encountered at least one integer! + return report_parse_error(p, parse_error::no_digits_in_mantissa); + } + int64_t exp_number = 0; // explicit exponential part + if ((uint64_t(fmt & chars_format::scientific) && (p != pend) && + ((UC('e') == *p) || (UC('E') == *p))) || + (uint64_t(fmt & detail::basic_fortran_fmt) && (p != pend) && + ((UC('+') == *p) || (UC('-') == *p) || (UC('d') == *p) || + (UC('D') == *p)))) { + UC const *location_of_e = p; + if ((UC('e') == *p) || (UC('E') == *p) || (UC('d') == *p) || + (UC('D') == *p)) { + ++p; + } + bool neg_exp = false; + if ((p != pend) && (UC('-') == *p)) { + neg_exp = true; + ++p; + } else if ((p != pend) && + (UC('+') == + *p)) { // '+' on exponent is allowed by C++17 20.19.3.(7.1) + ++p; + } + if ((p == pend) || !is_integer(*p)) { + if (!uint64_t(fmt & chars_format::fixed)) { + // The exponential part is invalid for scientific notation, so it must + // be a trailing token for fixed notation. However, fixed notation is + // disabled, so report a scientific notation error. + return report_parse_error(p, parse_error::missing_exponential_part); + } + // Otherwise, we will be ignoring the 'e'. + p = location_of_e; + } else { + while ((p != pend) && is_integer(*p)) { + uint8_t digit = uint8_t(*p - UC('0')); + if (exp_number < 0x10000000) { + exp_number = 10 * exp_number + digit; + } + ++p; + } + if (neg_exp) { + exp_number = -exp_number; + } + exponent += exp_number; + } + } else { + // If it scientific and not fixed, we have to bail out. + if (uint64_t(fmt & chars_format::scientific) && + !uint64_t(fmt & chars_format::fixed)) { + return report_parse_error(p, parse_error::missing_exponential_part); + } + } + answer.lastmatch = p; + answer.valid = true; + + // If we frequently had to deal with long strings of digits, + // we could extend our code by using a 128-bit integer instead + // of a 64-bit integer. However, this is uncommon. + // + // We can deal with up to 19 digits. + if (digit_count > 19) { // this is uncommon + // It is possible that the integer had an overflow. + // We have to handle the case where we have 0.0000somenumber. + // We need to be mindful of the case where we only have zeroes... + // E.g., 0.000000000...000. + UC const *start = start_digits; + while ((start != pend) && (*start == UC('0') || *start == decimal_point)) { + if (*start == UC('0')) { + digit_count--; + } + start++; + } + + if (digit_count > 19) { + answer.too_many_digits = true; + // Let us start again, this time, avoiding overflows. + // We don't need to check if is_integer, since we use the + // pre-tokenized spans from above. + i = 0; + p = answer.integer.ptr; + UC const *int_end = p + answer.integer.len(); + uint64_t const minimal_nineteen_digit_integer{1000000000000000000}; + while ((i < minimal_nineteen_digit_integer) && (p != int_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + if (i >= minimal_nineteen_digit_integer) { // We have a big integers + exponent = end_of_integer_part - p + exp_number; + } else { // We have a value with a fractional component. + p = answer.fraction.ptr; + UC const *frac_end = p + answer.fraction.len(); + while ((i < minimal_nineteen_digit_integer) && (p != frac_end)) { + i = i * 10 + uint64_t(*p - UC('0')); + ++p; + } + exponent = answer.fraction.ptr - p + exp_number; + } + // We have now corrected both exponent and i, to a truncated value + } + } + answer.exponent = exponent; + answer.mantissa = i; + return answer; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 from_chars_result_t +parse_int_string(UC const *p, UC const *pend, T &value, + parse_options_t options) { + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + + UC const *const first = p; + + bool const negative = (*p == UC('-')); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable : 4127) +#endif + if (!std::is_signed::value && negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + if ((*p == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && (*p == UC('+')))) { + ++p; + } + + UC const *const start_num = p; + + while (p != pend && *p == UC('0')) { + ++p; + } + + bool const has_leading_zeros = p > start_num; + + UC const *const start_digits = p; + + uint64_t i = 0; + if (base == 10) { + loop_parse_if_eight_digits(p, pend, i); // use SIMD if possible + } + while (p != pend) { + uint8_t digit = ch_to_digit(*p); + if (digit >= base) { + break; + } + i = uint64_t(base) * i + digit; // might overflow, check this later + p++; + } + + size_t digit_count = size_t(p - start_digits); + + if (digit_count == 0) { + if (has_leading_zeros) { + value = 0; + answer.ec = std::errc(); + answer.ptr = p; + } else { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + } + return answer; + } + + answer.ptr = p; + + // check u64 overflow + size_t max_digits = max_digits_u64(base); + if (digit_count > max_digits) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + // this check can be eliminated for all other types, but they will all require + // a max_digits(base) equivalent + if (digit_count == max_digits && i < min_safe_u64(base)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + + // check other types overflow + if (!std::is_same::value) { + if (i > uint64_t(std::numeric_limits::max()) + uint64_t(negative)) { + answer.ec = std::errc::result_out_of_range; + return answer; + } + } + + if (negative) { +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +#pragma warning(disable : 4146) +#endif + // this weird workaround is required because: + // - converting unsigned to signed when its value is greater than signed max + // is UB pre-C++23. + // - reinterpret_casting (~i + 1) would work, but it is not constexpr + // this is always optimized into a neg instruction (note: T is an integer + // type) + value = T(-std::numeric_limits::max() - + T(i - uint64_t(std::numeric_limits::max()))); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#endif + } else { + value = T(i); + } + + answer.ec = std::errc(); + return answer; +} + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/bigint.h b/3rdparty/fast_float/bigint.h new file mode 100644 index 000000000000..74901e3956f2 --- /dev/null +++ b/3rdparty/fast_float/bigint.h @@ -0,0 +1,638 @@ +#ifndef FASTFLOAT_BIGINT_H +#define FASTFLOAT_BIGINT_H + +#include +#include +#include +#include + +#include "float_common.h" + +namespace fast_float { + +// the limb width: we want efficient multiplication of double the bits in +// limb, or for 64-bit limbs, at least 64-bit multiplication where we can +// extract the high and low parts efficiently. this is every 64-bit +// architecture except for sparc, which emulates 128-bit multiplication. +// we might have platforms where `CHAR_BIT` is not 8, so let's avoid +// doing `8 * sizeof(limb)`. +#if defined(FASTFLOAT_64BIT) && !defined(__sparc) +#define FASTFLOAT_64BIT_LIMB 1 +typedef uint64_t limb; +constexpr size_t limb_bits = 64; +#else +#define FASTFLOAT_32BIT_LIMB +typedef uint32_t limb; +constexpr size_t limb_bits = 32; +#endif + +typedef span limb_span; + +// number of bits in a bigint. this needs to be at least the number +// of bits required to store the largest bigint, which is +// `log2(10**(digits + max_exp))`, or `log2(10**(767 + 342))`, or +// ~3600 bits, so we round to 4000. +constexpr size_t bigint_bits = 4000; +constexpr size_t bigint_limbs = bigint_bits / limb_bits; + +// vector-like type that is allocated on the stack. the entire +// buffer is pre-allocated, and only the length changes. +template struct stackvec { + limb data[size]; + // we never need more than 150 limbs + uint16_t length{0}; + + stackvec() = default; + stackvec(stackvec const &) = delete; + stackvec &operator=(stackvec const &) = delete; + stackvec(stackvec &&) = delete; + stackvec &operator=(stackvec &&other) = delete; + + // create stack vector from existing limb span. + FASTFLOAT_CONSTEXPR20 stackvec(limb_span s) { + FASTFLOAT_ASSERT(try_extend(s)); + } + + FASTFLOAT_CONSTEXPR14 limb &operator[](size_t index) noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + + FASTFLOAT_CONSTEXPR14 const limb &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return data[index]; + } + + // index from the end of the container + FASTFLOAT_CONSTEXPR14 const limb &rindex(size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + size_t rindex = length - index - 1; + return data[rindex]; + } + + // set the length, without bounds checking. + FASTFLOAT_CONSTEXPR14 void set_len(size_t len) noexcept { + length = uint16_t(len); + } + + constexpr size_t len() const noexcept { return length; } + + constexpr bool is_empty() const noexcept { return length == 0; } + + constexpr size_t capacity() const noexcept { return size; } + + // append item to vector, without bounds checking + FASTFLOAT_CONSTEXPR14 void push_unchecked(limb value) noexcept { + data[length] = value; + length++; + } + + // append item to vector, returning if item was added + FASTFLOAT_CONSTEXPR14 bool try_push(limb value) noexcept { + if (len() < capacity()) { + push_unchecked(value); + return true; + } else { + return false; + } + } + + // add items to the vector, from a span, without bounds checking + FASTFLOAT_CONSTEXPR20 void extend_unchecked(limb_span s) noexcept { + limb *ptr = data + length; + std::copy_n(s.ptr, s.len(), ptr); + set_len(len() + s.len()); + } + + // try to add items to the vector, returning if items were added + FASTFLOAT_CONSTEXPR20 bool try_extend(limb_span s) noexcept { + if (len() + s.len() <= capacity()) { + extend_unchecked(s); + return true; + } else { + return false; + } + } + + // resize the vector, without bounds checking + // if the new size is longer than the vector, assign value to each + // appended item. + FASTFLOAT_CONSTEXPR20 + void resize_unchecked(size_t new_len, limb value) noexcept { + if (new_len > len()) { + size_t count = new_len - len(); + limb *first = data + len(); + limb *last = first + count; + ::std::fill(first, last, value); + set_len(new_len); + } else { + set_len(new_len); + } + } + + // try to resize the vector, returning if the vector was resized. + FASTFLOAT_CONSTEXPR20 bool try_resize(size_t new_len, limb value) noexcept { + if (new_len > capacity()) { + return false; + } else { + resize_unchecked(new_len, value); + return true; + } + } + + // check if any limbs are non-zero after the given index. + // this needs to be done in reverse order, since the index + // is relative to the most significant limbs. + FASTFLOAT_CONSTEXPR14 bool nonzero(size_t index) const noexcept { + while (index < len()) { + if (rindex(index) != 0) { + return true; + } + index++; + } + return false; + } + + // normalize the big integer, so most-significant zero limbs are removed. + FASTFLOAT_CONSTEXPR14 void normalize() noexcept { + while (len() > 0 && rindex(0) == 0) { + length--; + } + } +}; + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +empty_hi64(bool &truncated) noexcept { + truncated = false; + return 0; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, bool &truncated) noexcept { + truncated = false; + int shl = leading_zeroes(r0); + return r0 << shl; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint64_hi64(uint64_t r0, uint64_t r1, bool &truncated) noexcept { + int shl = leading_zeroes(r0); + if (shl == 0) { + truncated = r1 != 0; + return r0; + } else { + int shr = 64 - shl; + truncated = (r1 << shl) != 0; + return (r0 << shl) | (r1 >> shr); + } +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, bool &truncated) noexcept { + return uint64_hi64(r0, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + return uint64_hi64((x0 << 32) | x1, truncated); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t +uint32_hi64(uint32_t r0, uint32_t r1, uint32_t r2, bool &truncated) noexcept { + uint64_t x0 = r0; + uint64_t x1 = r1; + uint64_t x2 = r2; + return uint64_hi64(x0, (x1 << 32) | x2, truncated); +} + +// add two small integers, checking for overflow. +// we want an efficient operation. for msvc, where +// we don't have built-in intrinsics, this is still +// pretty fast. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_add(limb x, limb y, bool &overflow) noexcept { + limb z; +// gcc and clang +#if defined(__has_builtin) +#if __has_builtin(__builtin_add_overflow) + if (!cpp20_and_in_constexpr()) { + overflow = __builtin_add_overflow(x, y, &z); + return z; + } +#endif +#endif + + // generic, this still optimizes correctly on MSVC. + z = x + y; + overflow = z < x; + return z; +} + +// multiply two small integers, getting both the high and low bits. +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 limb +scalar_mul(limb x, limb y, limb &carry) noexcept { +#ifdef FASTFLOAT_64BIT_LIMB +#if defined(__SIZEOF_INT128__) + // GCC and clang both define it as an extension. + __uint128_t z = __uint128_t(x) * __uint128_t(y) + __uint128_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#else + // fallback, no native 128-bit integer multiplication with carry. + // on msvc, this optimizes identically, somehow. + value128 z = full_multiplication(x, y); + bool overflow; + z.low = scalar_add(z.low, carry, overflow); + z.high += uint64_t(overflow); // cannot overflow + carry = z.high; + return z.low; +#endif +#else + uint64_t z = uint64_t(x) * uint64_t(y) + uint64_t(carry); + carry = limb(z >> limb_bits); + return limb(z); +#endif +} + +// add scalar value to bigint starting from offset. +// used in grade school multiplication +template +inline FASTFLOAT_CONSTEXPR20 bool small_add_from(stackvec &vec, limb y, + size_t start) noexcept { + size_t index = start; + limb carry = y; + bool overflow; + while (carry != 0 && index < vec.len()) { + vec[index] = scalar_add(vec[index], carry, overflow); + carry = limb(overflow); + index += 1; + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add scalar value to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +small_add(stackvec &vec, limb y) noexcept { + return small_add_from(vec, y, 0); +} + +// multiply bigint by scalar value. +template +inline FASTFLOAT_CONSTEXPR20 bool small_mul(stackvec &vec, + limb y) noexcept { + limb carry = 0; + for (size_t index = 0; index < vec.len(); index++) { + vec[index] = scalar_mul(vec[index], y, carry); + } + if (carry != 0) { + FASTFLOAT_TRY(vec.try_push(carry)); + } + return true; +} + +// add bigint to bigint starting from index. +// used in grade school multiplication +template +FASTFLOAT_CONSTEXPR20 bool large_add_from(stackvec &x, limb_span y, + size_t start) noexcept { + // the effective x buffer is from `xstart..x.len()`, so exit early + // if we can't get that current range. + if (x.len() < start || y.len() > x.len() - start) { + FASTFLOAT_TRY(x.try_resize(y.len() + start, 0)); + } + + bool carry = false; + for (size_t index = 0; index < y.len(); index++) { + limb xi = x[index + start]; + limb yi = y[index]; + bool c1 = false; + bool c2 = false; + xi = scalar_add(xi, yi, c1); + if (carry) { + xi = scalar_add(xi, 1, c2); + } + x[index + start] = xi; + carry = c1 | c2; + } + + // handle overflow + if (carry) { + FASTFLOAT_TRY(small_add_from(x, 1, y.len() + start)); + } + return true; +} + +// add bigint to bigint. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +large_add_from(stackvec &x, limb_span y) noexcept { + return large_add_from(x, y, 0); +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool long_mul(stackvec &x, limb_span y) noexcept { + limb_span xs = limb_span(x.data, x.len()); + stackvec z(xs); + limb_span zs = limb_span(z.data, z.len()); + + if (y.len() != 0) { + limb y0 = y[0]; + FASTFLOAT_TRY(small_mul(x, y0)); + for (size_t index = 1; index < y.len(); index++) { + limb yi = y[index]; + stackvec zi; + if (yi != 0) { + // re-use the same buffer throughout + zi.set_len(0); + FASTFLOAT_TRY(zi.try_extend(zs)); + FASTFLOAT_TRY(small_mul(zi, yi)); + limb_span zis = limb_span(zi.data, zi.len()); + FASTFLOAT_TRY(large_add_from(x, zis, index)); + } + } + } + + x.normalize(); + return true; +} + +// grade-school multiplication algorithm +template +FASTFLOAT_CONSTEXPR20 bool large_mul(stackvec &x, limb_span y) noexcept { + if (y.len() == 1) { + FASTFLOAT_TRY(small_mul(x, y[0])); + } else { + FASTFLOAT_TRY(long_mul(x, y)); + } + return true; +} + +template struct pow5_tables { + static constexpr uint32_t large_step = 135; + static constexpr uint64_t small_power_of_5[] = { + 1UL, + 5UL, + 25UL, + 125UL, + 625UL, + 3125UL, + 15625UL, + 78125UL, + 390625UL, + 1953125UL, + 9765625UL, + 48828125UL, + 244140625UL, + 1220703125UL, + 6103515625UL, + 30517578125UL, + 152587890625UL, + 762939453125UL, + 3814697265625UL, + 19073486328125UL, + 95367431640625UL, + 476837158203125UL, + 2384185791015625UL, + 11920928955078125UL, + 59604644775390625UL, + 298023223876953125UL, + 1490116119384765625UL, + 7450580596923828125UL, + }; +#ifdef FASTFLOAT_64BIT_LIMB + constexpr static limb large_power_of_5[] = { + 1414648277510068013UL, 9180637584431281687UL, 4539964771860779200UL, + 10482974169319127550UL, 198276706040285095UL}; +#else + constexpr static limb large_power_of_5[] = { + 4279965485U, 329373468U, 4020270615U, 2137533757U, 4287402176U, + 1057042919U, 1071430142U, 2440757623U, 381945767U, 46164893U}; +#endif +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint32_t pow5_tables::large_step; + +template constexpr uint64_t pow5_tables::small_power_of_5[]; + +template constexpr limb pow5_tables::large_power_of_5[]; + +#endif + +// big integer type. implements a small subset of big integer +// arithmetic, using simple algorithms since asymptotically +// faster algorithms are slower for a small number of limbs. +// all operations assume the big-integer is normalized. +struct bigint : pow5_tables<> { + // storage of the limbs, in little-endian order. + stackvec vec; + + FASTFLOAT_CONSTEXPR20 bigint() : vec() {} + + bigint(bigint const &) = delete; + bigint &operator=(bigint const &) = delete; + bigint(bigint &&) = delete; + bigint &operator=(bigint &&other) = delete; + + FASTFLOAT_CONSTEXPR20 bigint(uint64_t value) : vec() { +#ifdef FASTFLOAT_64BIT_LIMB + vec.push_unchecked(value); +#else + vec.push_unchecked(uint32_t(value)); + vec.push_unchecked(uint32_t(value >> 32)); +#endif + vec.normalize(); + } + + // get the high 64 bits from the vector, and if bits were truncated. + // this is to get the significant digits for the float. + FASTFLOAT_CONSTEXPR20 uint64_t hi64(bool &truncated) const noexcept { +#ifdef FASTFLOAT_64BIT_LIMB + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint64_hi64(vec.rindex(0), truncated); + } else { + uint64_t result = uint64_hi64(vec.rindex(0), vec.rindex(1), truncated); + truncated |= vec.nonzero(2); + return result; + } +#else + if (vec.len() == 0) { + return empty_hi64(truncated); + } else if (vec.len() == 1) { + return uint32_hi64(vec.rindex(0), truncated); + } else if (vec.len() == 2) { + return uint32_hi64(vec.rindex(0), vec.rindex(1), truncated); + } else { + uint64_t result = + uint32_hi64(vec.rindex(0), vec.rindex(1), vec.rindex(2), truncated); + truncated |= vec.nonzero(3); + return result; + } +#endif + } + + // compare two big integers, returning the large value. + // assumes both are normalized. if the return value is + // negative, other is larger, if the return value is + // positive, this is larger, otherwise they are equal. + // the limbs are stored in little-endian order, so we + // must compare the limbs in ever order. + FASTFLOAT_CONSTEXPR20 int compare(bigint const &other) const noexcept { + if (vec.len() > other.vec.len()) { + return 1; + } else if (vec.len() < other.vec.len()) { + return -1; + } else { + for (size_t index = vec.len(); index > 0; index--) { + limb xi = vec[index - 1]; + limb yi = other.vec[index - 1]; + if (xi > yi) { + return 1; + } else if (xi < yi) { + return -1; + } + } + return 0; + } + } + + // shift left each limb n bits, carrying over to the new limb + // returns true if we were able to shift all the digits. + FASTFLOAT_CONSTEXPR20 bool shl_bits(size_t n) noexcept { + // Internally, for each item, we shift left by n, and add the previous + // right shifted limb-bits. + // For example, we transform (for u8) shifted left 2, to: + // b10100100 b01000010 + // b10 b10010001 b00001000 + FASTFLOAT_DEBUG_ASSERT(n != 0); + FASTFLOAT_DEBUG_ASSERT(n < sizeof(limb) * 8); + + size_t shl = n; + size_t shr = limb_bits - shl; + limb prev = 0; + for (size_t index = 0; index < vec.len(); index++) { + limb xi = vec[index]; + vec[index] = (xi << shl) | (prev >> shr); + prev = xi; + } + + limb carry = prev >> shr; + if (carry != 0) { + return vec.try_push(carry); + } + return true; + } + + // move the limbs left by `n` limbs. + FASTFLOAT_CONSTEXPR20 bool shl_limbs(size_t n) noexcept { + FASTFLOAT_DEBUG_ASSERT(n != 0); + if (n + vec.len() > vec.capacity()) { + return false; + } else if (!vec.is_empty()) { + // move limbs + limb *dst = vec.data + n; + limb const *src = vec.data; + std::copy_backward(src, src + vec.len(), dst + vec.len()); + // fill in empty limbs + limb *first = vec.data; + limb *last = first + n; + ::std::fill(first, last, 0); + vec.set_len(n + vec.len()); + return true; + } else { + return true; + } + } + + // move the limbs left by `n` bits. + FASTFLOAT_CONSTEXPR20 bool shl(size_t n) noexcept { + size_t rem = n % limb_bits; + size_t div = n / limb_bits; + if (rem != 0) { + FASTFLOAT_TRY(shl_bits(rem)); + } + if (div != 0) { + FASTFLOAT_TRY(shl_limbs(div)); + } + return true; + } + + // get the number of leading zeros in the bigint. + FASTFLOAT_CONSTEXPR20 int ctlz() const noexcept { + if (vec.is_empty()) { + return 0; + } else { +#ifdef FASTFLOAT_64BIT_LIMB + return leading_zeroes(vec.rindex(0)); +#else + // no use defining a specialized leading_zeroes for a 32-bit type. + uint64_t r0 = vec.rindex(0); + return leading_zeroes(r0 << 32); +#endif + } + } + + // get the number of bits in the bigint. + FASTFLOAT_CONSTEXPR20 int bit_length() const noexcept { + int lz = ctlz(); + return int(limb_bits * vec.len()) - lz; + } + + FASTFLOAT_CONSTEXPR20 bool mul(limb y) noexcept { return small_mul(vec, y); } + + FASTFLOAT_CONSTEXPR20 bool add(limb y) noexcept { return small_add(vec, y); } + + // multiply as if by 2 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow2(uint32_t exp) noexcept { return shl(exp); } + + // multiply as if by 5 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow5(uint32_t exp) noexcept { + // multiply by a power of 5 + size_t large_length = sizeof(large_power_of_5) / sizeof(limb); + limb_span large = limb_span(large_power_of_5, large_length); + while (exp >= large_step) { + FASTFLOAT_TRY(large_mul(vec, large)); + exp -= large_step; + } +#ifdef FASTFLOAT_64BIT_LIMB + uint32_t small_step = 27; + limb max_native = 7450580596923828125UL; +#else + uint32_t small_step = 13; + limb max_native = 1220703125U; +#endif + while (exp >= small_step) { + FASTFLOAT_TRY(small_mul(vec, max_native)); + exp -= small_step; + } + if (exp != 0) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + // This is similar to https://github.com/llvm/llvm-project/issues/47746, + // except the workaround described there don't work here + FASTFLOAT_TRY(small_mul( + vec, limb(((void)small_power_of_5[0], small_power_of_5[exp])))); + } + + return true; + } + + // multiply as if by 10 raised to a power. + FASTFLOAT_CONSTEXPR20 bool pow10(uint32_t exp) noexcept { + FASTFLOAT_TRY(pow5(exp)); + return pow2(exp); + } +}; + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/constexpr_feature_detect.h b/3rdparty/fast_float/constexpr_feature_detect.h new file mode 100644 index 000000000000..6751afecd6bb --- /dev/null +++ b/3rdparty/fast_float/constexpr_feature_detect.h @@ -0,0 +1,53 @@ +#ifndef FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H +#define FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H + +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + +// Testing for https://wg21.link/N3652, adopted in C++14 +#if defined(__cpp_constexpr) && __cpp_constexpr >= 201304 +#define FASTFLOAT_CONSTEXPR14 constexpr +#else +#define FASTFLOAT_CONSTEXPR14 +#endif + +#if defined(__cpp_lib_bit_cast) && __cpp_lib_bit_cast >= 201806L +#define FASTFLOAT_HAS_BIT_CAST 1 +#else +#define FASTFLOAT_HAS_BIT_CAST 0 +#endif + +#if defined(__cpp_lib_is_constant_evaluated) && \ + __cpp_lib_is_constant_evaluated >= 201811L +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 1 +#else +#define FASTFLOAT_HAS_IS_CONSTANT_EVALUATED 0 +#endif + +#if defined(__cpp_if_constexpr) && __cpp_if_constexpr >= 201606L +#define FASTFLOAT_IF_CONSTEXPR17(x) if constexpr (x) +#else +#define FASTFLOAT_IF_CONSTEXPR17(x) if (x) +#endif + +// Testing for relevant C++20 constexpr library features +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST && \ + defined(__cpp_lib_constexpr_algorithms) && \ + __cpp_lib_constexpr_algorithms >= 201806L /*For std::copy and std::fill*/ +#define FASTFLOAT_CONSTEXPR20 constexpr +#define FASTFLOAT_IS_CONSTEXPR 1 +#else +#define FASTFLOAT_CONSTEXPR20 +#define FASTFLOAT_IS_CONSTEXPR 0 +#endif + +#if __cplusplus >= 201703L || (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 0 +#else +#define FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE 1 +#endif + +#endif // FASTFLOAT_CONSTEXPR_FEATURE_DETECT_H diff --git a/3rdparty/fast_float/decimal_to_binary.h b/3rdparty/fast_float/decimal_to_binary.h new file mode 100644 index 000000000000..948768265eb3 --- /dev/null +++ b/3rdparty/fast_float/decimal_to_binary.h @@ -0,0 +1,212 @@ +#ifndef FASTFLOAT_DECIMAL_TO_BINARY_H +#define FASTFLOAT_DECIMAL_TO_BINARY_H + +#include "float_common.h" +#include "fast_table.h" +#include +#include +#include +#include +#include +#include + +namespace fast_float { + +// This will compute or rather approximate w * 5**q and return a pair of 64-bit +// words approximating the result, with the "high" part corresponding to the +// most significant bits and the low part corresponding to the least significant +// bits. +// +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +compute_product_approximation(int64_t q, uint64_t w) { + int const index = 2 * int(q - powers::smallest_power_of_five); + // For small values of q, e.g., q in [0,27], the answer is always exact + // because The line value128 firstproduct = full_multiplication(w, + // power_of_five_128[index]); gives the exact answer. + value128 firstproduct = + full_multiplication(w, powers::power_of_five_128[index]); + static_assert((bit_precision >= 0) && (bit_precision <= 64), + " precision should be in (0,64]"); + constexpr uint64_t precision_mask = + (bit_precision < 64) ? (uint64_t(0xFFFFFFFFFFFFFFFF) >> bit_precision) + : uint64_t(0xFFFFFFFFFFFFFFFF); + if ((firstproduct.high & precision_mask) == + precision_mask) { // could further guard with (lower + w < lower) + // regarding the second product, we only need secondproduct.high, but our + // expectation is that the compiler will optimize this extra work away if + // needed. + value128 secondproduct = + full_multiplication(w, powers::power_of_five_128[index + 1]); + firstproduct.low += secondproduct.high; + if (secondproduct.high > firstproduct.low) { + firstproduct.high++; + } + } + return firstproduct; +} + +namespace detail { +/** + * For q in (0,350), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * floor(p) + q + * where + * p = log(5**q)/log(2) = q * log(5)/log(2) + * + * For negative values of q in (-400,0), we have that + * f = (((152170 + 65536) * q ) >> 16); + * is equal to + * -ceil(p) + q + * where + * p = log(5**-q)/log(2) = -q * log(5)/log(2) + */ +constexpr fastfloat_really_inline int32_t power(int32_t q) noexcept { + return (((152170 + 65536) * q) >> 16) + 63; +} +} // namespace detail + +// create an adjusted mantissa, biased by the invalid power2 +// for significant digits already multiplied by 10 ** q. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 adjusted_mantissa +compute_error_scaled(int64_t q, uint64_t w, int lz) noexcept { + int hilz = int(w >> 63) ^ 1; + adjusted_mantissa answer; + answer.mantissa = w << hilz; + int bias = binary::mantissa_explicit_bits() - binary::minimum_exponent(); + answer.power2 = int32_t(detail::power(int32_t(q)) + bias - hilz - lz - 62 + + invalid_am_bias); + return answer; +} + +// w * 10 ** q, without rounding the representation up. +// the power2 in the exponent will be adjusted by invalid_am_bias. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_error(int64_t q, uint64_t w) noexcept { + int lz = leading_zeroes(w); + w <<= lz; + value128 product = + compute_product_approximation(q, w); + return compute_error_scaled(q, product.high, lz); +} + +// Computers w * 10 ** q. +// The returned value should be a valid number that simply needs to be +// packed. However, in some very rare cases, the computation will fail. In such +// cases, we return an adjusted_mantissa with a negative power of 2: the caller +// should recompute in such cases. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +compute_float(int64_t q, uint64_t w) noexcept { + adjusted_mantissa answer; + if ((w == 0) || (q < binary::smallest_power_of_ten())) { + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + if (q > binary::largest_power_of_ten()) { + // we want to get infinity: + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + return answer; + } + // At this point in time q is in [powers::smallest_power_of_five, + // powers::largest_power_of_five]. + + // We want the most significant bit of i to be 1. Shift if needed. + int lz = leading_zeroes(w); + w <<= lz; + + // The required precision is binary::mantissa_explicit_bits() + 3 because + // 1. We need the implicit bit + // 2. We need an extra bit for rounding purposes + // 3. We might lose a bit due to the "upperbit" routine (result too small, + // requiring a shift) + + value128 product = + compute_product_approximation(q, w); + // The computed 'product' is always sufficient. + // Mathematical proof: + // Noble Mushtak and Daniel Lemire, Fast Number Parsing Without Fallback (to + // appear) See script/mushtak_lemire.py + + // The "compute_product_approximation" function can be slightly slower than a + // branchless approach: value128 product = compute_product(q, w); but in + // practice, we can win big with the compute_product_approximation if its + // additional branch is easily predicted. Which is best is data specific. + int upperbit = int(product.high >> 63); + int shift = upperbit + 64 - binary::mantissa_explicit_bits() - 3; + + answer.mantissa = product.high >> shift; + + answer.power2 = int32_t(detail::power(int32_t(q)) + upperbit - lz - + binary::minimum_exponent()); + if (answer.power2 <= 0) { // we have a subnormal? + // Here have that answer.power2 <= 0 so -answer.power2 >= 0 + if (-answer.power2 + 1 >= + 64) { // if we have more than 64 bits below the minimum exponent, you + // have a zero for sure. + answer.power2 = 0; + answer.mantissa = 0; + // result should be zero + return answer; + } + // next line is safe because -answer.power2 + 1 < 64 + answer.mantissa >>= -answer.power2 + 1; + // Thankfully, we can't have both "round-to-even" and subnormals because + // "round-to-even" only occurs for powers close to 0 in the 32-bit and + // and 64-bit case (with no more than 19 digits). + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + // There is a weird scenario where we don't have a subnormal but just. + // Suppose we start with 2.2250738585072013e-308, we end up + // with 0x3fffffffffffff x 2^-1023-53 which is technically subnormal + // whereas 0x40000000000000 x 2^-1023-53 is normal. Now, we need to round + // up 0x3fffffffffffff x 2^-1023-53 and once we do, we are no longer + // subnormal, but we can only know this after rounding. + // So we only declare a subnormal if we are smaller than the threshold. + answer.power2 = + (answer.mantissa < (uint64_t(1) << binary::mantissa_explicit_bits())) + ? 0 + : 1; + return answer; + } + + // usually, we round *up*, but if we fall right in between and and we have an + // even basis, we need to round down + // We are only concerned with the cases where 5**q fits in single 64-bit word. + if ((product.low <= 1) && (q >= binary::min_exponent_round_to_even()) && + (q <= binary::max_exponent_round_to_even()) && + ((answer.mantissa & 3) == 1)) { // we may fall between two floats! + // To be in-between two floats we need that in doing + // answer.mantissa = product.high >> (upperbit + 64 - + // binary::mantissa_explicit_bits() - 3); + // ... we dropped out only zeroes. But if this happened, then we can go + // back!!! + if ((answer.mantissa << shift) == product.high) { + answer.mantissa &= ~uint64_t(1); // flip it so that we do not round up + } + } + + answer.mantissa += (answer.mantissa & 1); // round up + answer.mantissa >>= 1; + if (answer.mantissa >= (uint64_t(2) << binary::mantissa_explicit_bits())) { + answer.mantissa = (uint64_t(1) << binary::mantissa_explicit_bits()); + answer.power2++; // undo previous addition + } + + answer.mantissa &= ~(uint64_t(1) << binary::mantissa_explicit_bits()); + if (answer.power2 >= binary::infinite_power()) { // infinity + answer.power2 = binary::infinite_power(); + answer.mantissa = 0; + } + return answer; +} + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/digit_comparison.h b/3rdparty/fast_float/digit_comparison.h new file mode 100644 index 000000000000..d7ef3d9acc16 --- /dev/null +++ b/3rdparty/fast_float/digit_comparison.h @@ -0,0 +1,457 @@ +#ifndef FASTFLOAT_DIGIT_COMPARISON_H +#define FASTFLOAT_DIGIT_COMPARISON_H + +#include +#include +#include +#include + +#include "float_common.h" +#include "bigint.h" +#include "ascii_number.h" + +namespace fast_float { + +// 1e0 to 1e19 +constexpr static uint64_t powers_of_ten_uint64[] = {1UL, + 10UL, + 100UL, + 1000UL, + 10000UL, + 100000UL, + 1000000UL, + 10000000UL, + 100000000UL, + 1000000000UL, + 10000000000UL, + 100000000000UL, + 1000000000000UL, + 10000000000000UL, + 100000000000000UL, + 1000000000000000UL, + 10000000000000000UL, + 100000000000000000UL, + 1000000000000000000UL, + 10000000000000000000UL}; + +// calculate the exponent, in scientific notation, of the number. +// this algorithm is not even close to optimized, but it has no practical +// effect on performance: in order to have a faster algorithm, we'd need +// to slow down performance for faster algorithms, and this is still fast. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int32_t +scientific_exponent(parsed_number_string_t &num) noexcept { + uint64_t mantissa = num.mantissa; + int32_t exponent = int32_t(num.exponent); + while (mantissa >= 10000) { + mantissa /= 10000; + exponent += 4; + } + while (mantissa >= 100) { + mantissa /= 100; + exponent += 2; + } + while (mantissa >= 10) { + mantissa /= 10; + exponent += 1; + } + return exponent; +} + +// this converts a native floating-point number to an extended-precision float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended(T value) noexcept { + using equiv_uint = equiv_uint_t; + constexpr equiv_uint exponent_mask = binary_format::exponent_mask(); + constexpr equiv_uint mantissa_mask = binary_format::mantissa_mask(); + constexpr equiv_uint hidden_bit_mask = binary_format::hidden_bit_mask(); + + adjusted_mantissa am; + int32_t bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + equiv_uint bits; +#if FASTFLOAT_HAS_BIT_CAST + bits = std::bit_cast(value); +#else + ::memcpy(&bits, &value, sizeof(T)); +#endif + if ((bits & exponent_mask) == 0) { + // denormal + am.power2 = 1 - bias; + am.mantissa = bits & mantissa_mask; + } else { + // normal + am.power2 = int32_t((bits & exponent_mask) >> + binary_format::mantissa_explicit_bits()); + am.power2 -= bias; + am.mantissa = (bits & mantissa_mask) | hidden_bit_mask; + } + + return am; +} + +// get the extended precision value of the halfway point between b and b+u. +// we are given a native float that represents b, so we need to adjust it +// halfway between b and b+u. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +to_extended_halfway(T value) noexcept { + adjusted_mantissa am = to_extended(value); + am.mantissa <<= 1; + am.mantissa += 1; + am.power2 -= 1; + return am; +} + +// round an extended-precision float to the nearest machine float. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void round(adjusted_mantissa &am, + callback cb) noexcept { + int32_t mantissa_shift = 64 - binary_format::mantissa_explicit_bits() - 1; + if (-am.power2 >= mantissa_shift) { + // have a denormal float + int32_t shift = -am.power2 + 1; + cb(am, std::min(shift, 64)); + // check for round-up: if rounding-nearest carried us to the hidden bit. + am.power2 = (am.mantissa < + (uint64_t(1) << binary_format::mantissa_explicit_bits())) + ? 0 + : 1; + return; + } + + // have a normal float, use the default shift. + cb(am, mantissa_shift); + + // check for carry + if (am.mantissa >= + (uint64_t(2) << binary_format::mantissa_explicit_bits())) { + am.mantissa = (uint64_t(1) << binary_format::mantissa_explicit_bits()); + am.power2++; + } + + // check for infinite: we could have carried to an infinite power + am.mantissa &= ~(uint64_t(1) << binary_format::mantissa_explicit_bits()); + if (am.power2 >= binary_format::infinite_power()) { + am.power2 = binary_format::infinite_power(); + am.mantissa = 0; + } +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_nearest_tie_even(adjusted_mantissa &am, int32_t shift, + callback cb) noexcept { + uint64_t const mask = (shift == 64) ? UINT64_MAX : (uint64_t(1) << shift) - 1; + uint64_t const halfway = (shift == 0) ? 0 : uint64_t(1) << (shift - 1); + uint64_t truncated_bits = am.mantissa & mask; + bool is_above = truncated_bits > halfway; + bool is_halfway = truncated_bits == halfway; + + // shift digits into position + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; + + bool is_odd = (am.mantissa & 1) == 1; + am.mantissa += uint64_t(cb(is_odd, is_halfway, is_above)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +round_down(adjusted_mantissa &am, int32_t shift) noexcept { + if (shift == 64) { + am.mantissa = 0; + } else { + am.mantissa >>= shift; + } + am.power2 += shift; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +skip_zeros(UC const *&first, UC const *last) noexcept { + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + break; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + break; + } + first++; + } +} + +// determine if any non-zero digits were truncated. +// all characters must be valid digits. +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(UC const *first, UC const *last) noexcept { + // do 8-bit optimizations, can just compare to 8 literal 0s. + uint64_t val; + while (!cpp20_and_in_constexpr() && + std::distance(first, last) >= int_cmp_len()) { + ::memcpy(&val, first, sizeof(uint64_t)); + if (val != int_cmp_zeros()) { + return true; + } + first += int_cmp_len(); + } + while (first != last) { + if (*first != UC('0')) { + return true; + } + ++first; + } + return false; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 bool +is_truncated(span s) noexcept { + return is_truncated(s.ptr, s.ptr + s.len()); +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +parse_eight_digits(UC const *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 100000000 + parse_eight_digits_unrolled(p); + p += 8; + counter += 8; + count += 8; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 void +parse_one_digit(UC const *&p, limb &value, size_t &counter, + size_t &count) noexcept { + value = value * 10 + limb(*p - UC('0')); + p++; + counter++; + count++; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +add_native(bigint &big, limb power, limb value) noexcept { + big.mul(power); + big.add(value); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +round_up_bigint(bigint &big, size_t &count) noexcept { + // need to round-up the digits, but need to avoid rounding + // ....9999 to ...10000, which could cause a false halfway point. + add_native(big, 10, 1); + count++; +} + +// parse the significant digits into a big integer +template +inline FASTFLOAT_CONSTEXPR20 void +parse_mantissa(bigint &result, parsed_number_string_t &num, + size_t max_digits, size_t &digits) noexcept { + // try to minimize the number of big integer and scalar multiplication. + // therefore, try to parse 8 digits at a time, and multiply by the largest + // scalar value (9 or 19 digits) for each step. + size_t counter = 0; + digits = 0; + limb value = 0; +#ifdef FASTFLOAT_64BIT_LIMB + size_t step = 19; +#else + size_t step = 9; +#endif + + // process all integer digits. + UC const *p = num.integer.ptr; + UC const *pend = p + num.integer.len(); + skip_zeros(p, pend); + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (num.fraction.ptr != nullptr) { + truncated |= is_truncated(num.fraction); + } + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + + // add our fraction digits, if they're available. + if (num.fraction.ptr != nullptr) { + p = num.fraction.ptr; + pend = p + num.fraction.len(); + if (digits == 0) { + skip_zeros(p, pend); + } + // process all digits, in increments of step per loop + while (p != pend) { + while ((std::distance(p, pend) >= 8) && (step - counter >= 8) && + (max_digits - digits >= 8)) { + parse_eight_digits(p, value, counter, digits); + } + while (counter < step && p != pend && digits < max_digits) { + parse_one_digit(p, value, counter, digits); + } + if (digits == max_digits) { + // add the temporary value, then check if we've truncated any digits + add_native(result, limb(powers_of_ten_uint64[counter]), value); + bool truncated = is_truncated(p, pend); + if (truncated) { + round_up_bigint(result, digits); + } + return; + } else { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + counter = 0; + value = 0; + } + } + } + + if (counter != 0) { + add_native(result, limb(powers_of_ten_uint64[counter]), value); + } +} + +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +positive_digit_comp(bigint &bigmant, int32_t exponent) noexcept { + FASTFLOAT_ASSERT(bigmant.pow10(uint32_t(exponent))); + adjusted_mantissa answer; + bool truncated; + answer.mantissa = bigmant.hi64(truncated); + int bias = binary_format::mantissa_explicit_bits() - + binary_format::minimum_exponent(); + answer.power2 = bigmant.bit_length() - 64 + bias; + + round(answer, [truncated](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, + [truncated](bool is_odd, bool is_halfway, bool is_above) -> bool { + return is_above || (is_halfway && truncated) || + (is_odd && is_halfway); + }); + }); + + return answer; +} + +// the scaling here is quite simple: we have, for the real digits `m * 10^e`, +// and for the theoretical digits `n * 2^f`. Since `e` is always negative, +// to scale them identically, we do `n * 2^f * 5^-f`, so we now have `m * 2^e`. +// we then need to scale by `2^(f- e)`, and then the two significant digits +// are of the same magnitude. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa negative_digit_comp( + bigint &bigmant, adjusted_mantissa am, int32_t exponent) noexcept { + bigint &real_digits = bigmant; + int32_t real_exp = exponent; + + // get the value of `b`, rounded down, and get a bigint representation of b+h + adjusted_mantissa am_b = am; + // gcc7 buf: use a lambda to remove the noexcept qualifier bug with + // -Wnoexcept-type. + round(am_b, + [](adjusted_mantissa &a, int32_t shift) { round_down(a, shift); }); + T b; + to_float(false, am_b, b); + adjusted_mantissa theor = to_extended_halfway(b); + bigint theor_digits(theor.mantissa); + int32_t theor_exp = theor.power2; + + // scale real digits and theor digits to be same power. + int32_t pow2_exp = theor_exp - real_exp; + uint32_t pow5_exp = uint32_t(-real_exp); + if (pow5_exp != 0) { + FASTFLOAT_ASSERT(theor_digits.pow5(pow5_exp)); + } + if (pow2_exp > 0) { + FASTFLOAT_ASSERT(theor_digits.pow2(uint32_t(pow2_exp))); + } else if (pow2_exp < 0) { + FASTFLOAT_ASSERT(real_digits.pow2(uint32_t(-pow2_exp))); + } + + // compare digits, and use it to director rounding + int ord = real_digits.compare(theor_digits); + adjusted_mantissa answer = am; + round(answer, [ord](adjusted_mantissa &a, int32_t shift) { + round_nearest_tie_even( + a, shift, [ord](bool is_odd, bool _, bool __) -> bool { + (void)_; // not needed, since we've done our comparison + (void)__; // not needed, since we've done our comparison + if (ord > 0) { + return true; + } else if (ord < 0) { + return false; + } else { + return is_odd; + } + }); + }); + + return answer; +} + +// parse the significant digits as a big integer to unambiguously round the +// the significant digits. here, we are trying to determine how to round +// an extended float representation close to `b+h`, halfway between `b` +// (the float rounded-down) and `b+u`, the next positive float. this +// algorithm is always correct, and uses one of two approaches. when +// the exponent is positive relative to the significant digits (such as +// 1234), we create a big-integer representation, get the high 64-bits, +// determine if any lower bits are truncated, and use that to direct +// rounding. in case of a negative exponent relative to the significant +// digits (such as 1.2345), we create a theoretical representation of +// `b` as a big-integer type, scaled to the same binary exponent as +// the actual digits. we then compare the big integer representations +// of both, and use that to direct rounding. +template +inline FASTFLOAT_CONSTEXPR20 adjusted_mantissa +digit_comp(parsed_number_string_t &num, adjusted_mantissa am) noexcept { + // remove the invalid exponent bias + am.power2 -= invalid_am_bias; + + int32_t sci_exp = scientific_exponent(num); + size_t max_digits = binary_format::max_digits(); + size_t digits = 0; + bigint bigmant; + parse_mantissa(bigmant, num, max_digits, digits); + // can't underflow, since digits is at most max_digits. + int32_t exponent = sci_exp + 1 - int32_t(digits); + if (exponent >= 0) { + return positive_digit_comp(bigmant, exponent); + } else { + return negative_digit_comp(bigmant, am, exponent); + } +} + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/fast_float.h b/3rdparty/fast_float/fast_float.h new file mode 100644 index 000000000000..af65c96bde37 --- /dev/null +++ b/3rdparty/fast_float/fast_float.h @@ -0,0 +1,59 @@ + +#ifndef FASTFLOAT_FAST_FLOAT_H +#define FASTFLOAT_FAST_FLOAT_H + +#include "float_common.h" + +namespace fast_float { +/** + * This function parses the character sequence [first,last) for a number. It + * parses floating-point numbers expecting a locale-indepent format equivalent + * to what is used by std::strtod in the default ("C") locale. The resulting + * floating-point value is the closest floating-point values (using either float + * or double), using the "round to even" convention for values that would + * otherwise fall right in-between two values. That is, we provide exact parsing + * according to the IEEE standard. + * + * Given a successful parse, the pointer (`ptr`) in the returned value is set to + * point right after the parsed number, and the `value` referenced is set to the + * parsed value. In case of error, the returned `ec` contains a representative + * error, otherwise the default (`std::errc()`) value is stored. + * + * The implementation does not throw and does not allocate memory (e.g., with + * `new` or `malloc`). + * + * Like the C++17 standard, the `fast_float::from_chars` functions take an + * optional last argument of the type `fast_float::chars_format`. It is a bitset + * value: we check whether `fmt & fast_float::chars_format::fixed` and `fmt & + * fast_float::chars_format::scientific` are set to determine whether we allow + * the fixed point and scientific notation respectively. The default is + * `fast_float::chars_format::general` which allows both `fixed` and + * `scientific`. + */ +template ::value)> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt = chars_format::general) noexcept; + +/** + * Like from_chars, but accepts an `options` argument to govern number parsing. + * Both for floating-point types and integer types. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept; + +/** + * from_chars for integer types. + */ +template ::value)> +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base = 10) noexcept; + +} // namespace fast_float + +#include "parse_number.h" +#endif // FASTFLOAT_FAST_FLOAT_H diff --git a/3rdparty/fast_float/fast_table.h b/3rdparty/fast_float/fast_table.h new file mode 100644 index 000000000000..69f9b2c9245f --- /dev/null +++ b/3rdparty/fast_float/fast_table.h @@ -0,0 +1,708 @@ +#ifndef FASTFLOAT_FAST_TABLE_H +#define FASTFLOAT_FAST_TABLE_H + +#include + +namespace fast_float { + +/** + * When mapping numbers from decimal to binary, + * we go from w * 10^q to m * 2^p but we have + * 10^q = 5^q * 2^q, so effectively + * we are trying to match + * w * 2^q * 5^q to m * 2^p. Thus the powers of two + * are not a concern since they can be represented + * exactly using the binary notation, only the powers of five + * affect the binary significand. + */ + +/** + * The smallest non-zero float (binary64) is 2^-1074. + * We take as input numbers of the form w x 10^q where w < 2^64. + * We have that w * 10^-343 < 2^(64-344) 5^-343 < 2^-1076. + * However, we have that + * (2^64-1) * 10^-342 = (2^64-1) * 2^-342 * 5^-342 > 2^-1074. + * Thus it is possible for a number of the form w * 10^-342 where + * w is a 64-bit value to be a non-zero floating-point number. + ********* + * Any number of form w * 10^309 where w>= 1 is going to be + * infinite in binary64 so we never need to worry about powers + * of 5 greater than 308. + */ +template struct powers_template { + + constexpr static int smallest_power_of_five = + binary_format::smallest_power_of_ten(); + constexpr static int largest_power_of_five = + binary_format::largest_power_of_ten(); + constexpr static int number_of_entries = + 2 * (largest_power_of_five - smallest_power_of_five + 1); + // Powers of five from 5^-342 all the way to 5^308 rounded toward one. + constexpr static uint64_t power_of_five_128[number_of_entries] = { + 0xeef453d6923bd65a, 0x113faa2906a13b3f, + 0x9558b4661b6565f8, 0x4ac7ca59a424c507, + 0xbaaee17fa23ebf76, 0x5d79bcf00d2df649, + 0xe95a99df8ace6f53, 0xf4d82c2c107973dc, + 0x91d8a02bb6c10594, 0x79071b9b8a4be869, + 0xb64ec836a47146f9, 0x9748e2826cdee284, + 0xe3e27a444d8d98b7, 0xfd1b1b2308169b25, + 0x8e6d8c6ab0787f72, 0xfe30f0f5e50e20f7, + 0xb208ef855c969f4f, 0xbdbd2d335e51a935, + 0xde8b2b66b3bc4723, 0xad2c788035e61382, + 0x8b16fb203055ac76, 0x4c3bcb5021afcc31, + 0xaddcb9e83c6b1793, 0xdf4abe242a1bbf3d, + 0xd953e8624b85dd78, 0xd71d6dad34a2af0d, + 0x87d4713d6f33aa6b, 0x8672648c40e5ad68, + 0xa9c98d8ccb009506, 0x680efdaf511f18c2, + 0xd43bf0effdc0ba48, 0x212bd1b2566def2, + 0x84a57695fe98746d, 0x14bb630f7604b57, + 0xa5ced43b7e3e9188, 0x419ea3bd35385e2d, + 0xcf42894a5dce35ea, 0x52064cac828675b9, + 0x818995ce7aa0e1b2, 0x7343efebd1940993, + 0xa1ebfb4219491a1f, 0x1014ebe6c5f90bf8, + 0xca66fa129f9b60a6, 0xd41a26e077774ef6, + 0xfd00b897478238d0, 0x8920b098955522b4, + 0x9e20735e8cb16382, 0x55b46e5f5d5535b0, + 0xc5a890362fddbc62, 0xeb2189f734aa831d, + 0xf712b443bbd52b7b, 0xa5e9ec7501d523e4, + 0x9a6bb0aa55653b2d, 0x47b233c92125366e, + 0xc1069cd4eabe89f8, 0x999ec0bb696e840a, + 0xf148440a256e2c76, 0xc00670ea43ca250d, + 0x96cd2a865764dbca, 0x380406926a5e5728, + 0xbc807527ed3e12bc, 0xc605083704f5ecf2, + 0xeba09271e88d976b, 0xf7864a44c633682e, + 0x93445b8731587ea3, 0x7ab3ee6afbe0211d, + 0xb8157268fdae9e4c, 0x5960ea05bad82964, + 0xe61acf033d1a45df, 0x6fb92487298e33bd, + 0x8fd0c16206306bab, 0xa5d3b6d479f8e056, + 0xb3c4f1ba87bc8696, 0x8f48a4899877186c, + 0xe0b62e2929aba83c, 0x331acdabfe94de87, + 0x8c71dcd9ba0b4925, 0x9ff0c08b7f1d0b14, + 0xaf8e5410288e1b6f, 0x7ecf0ae5ee44dd9, + 0xdb71e91432b1a24a, 0xc9e82cd9f69d6150, + 0x892731ac9faf056e, 0xbe311c083a225cd2, + 0xab70fe17c79ac6ca, 0x6dbd630a48aaf406, + 0xd64d3d9db981787d, 0x92cbbccdad5b108, + 0x85f0468293f0eb4e, 0x25bbf56008c58ea5, + 0xa76c582338ed2621, 0xaf2af2b80af6f24e, + 0xd1476e2c07286faa, 0x1af5af660db4aee1, + 0x82cca4db847945ca, 0x50d98d9fc890ed4d, + 0xa37fce126597973c, 0xe50ff107bab528a0, + 0xcc5fc196fefd7d0c, 0x1e53ed49a96272c8, + 0xff77b1fcbebcdc4f, 0x25e8e89c13bb0f7a, + 0x9faacf3df73609b1, 0x77b191618c54e9ac, + 0xc795830d75038c1d, 0xd59df5b9ef6a2417, + 0xf97ae3d0d2446f25, 0x4b0573286b44ad1d, + 0x9becce62836ac577, 0x4ee367f9430aec32, + 0xc2e801fb244576d5, 0x229c41f793cda73f, + 0xf3a20279ed56d48a, 0x6b43527578c1110f, + 0x9845418c345644d6, 0x830a13896b78aaa9, + 0xbe5691ef416bd60c, 0x23cc986bc656d553, + 0xedec366b11c6cb8f, 0x2cbfbe86b7ec8aa8, + 0x94b3a202eb1c3f39, 0x7bf7d71432f3d6a9, + 0xb9e08a83a5e34f07, 0xdaf5ccd93fb0cc53, + 0xe858ad248f5c22c9, 0xd1b3400f8f9cff68, + 0x91376c36d99995be, 0x23100809b9c21fa1, + 0xb58547448ffffb2d, 0xabd40a0c2832a78a, + 0xe2e69915b3fff9f9, 0x16c90c8f323f516c, + 0x8dd01fad907ffc3b, 0xae3da7d97f6792e3, + 0xb1442798f49ffb4a, 0x99cd11cfdf41779c, + 0xdd95317f31c7fa1d, 0x40405643d711d583, + 0x8a7d3eef7f1cfc52, 0x482835ea666b2572, + 0xad1c8eab5ee43b66, 0xda3243650005eecf, + 0xd863b256369d4a40, 0x90bed43e40076a82, + 0x873e4f75e2224e68, 0x5a7744a6e804a291, + 0xa90de3535aaae202, 0x711515d0a205cb36, + 0xd3515c2831559a83, 0xd5a5b44ca873e03, + 0x8412d9991ed58091, 0xe858790afe9486c2, + 0xa5178fff668ae0b6, 0x626e974dbe39a872, + 0xce5d73ff402d98e3, 0xfb0a3d212dc8128f, + 0x80fa687f881c7f8e, 0x7ce66634bc9d0b99, + 0xa139029f6a239f72, 0x1c1fffc1ebc44e80, + 0xc987434744ac874e, 0xa327ffb266b56220, + 0xfbe9141915d7a922, 0x4bf1ff9f0062baa8, + 0x9d71ac8fada6c9b5, 0x6f773fc3603db4a9, + 0xc4ce17b399107c22, 0xcb550fb4384d21d3, + 0xf6019da07f549b2b, 0x7e2a53a146606a48, + 0x99c102844f94e0fb, 0x2eda7444cbfc426d, + 0xc0314325637a1939, 0xfa911155fefb5308, + 0xf03d93eebc589f88, 0x793555ab7eba27ca, + 0x96267c7535b763b5, 0x4bc1558b2f3458de, + 0xbbb01b9283253ca2, 0x9eb1aaedfb016f16, + 0xea9c227723ee8bcb, 0x465e15a979c1cadc, + 0x92a1958a7675175f, 0xbfacd89ec191ec9, + 0xb749faed14125d36, 0xcef980ec671f667b, + 0xe51c79a85916f484, 0x82b7e12780e7401a, + 0x8f31cc0937ae58d2, 0xd1b2ecb8b0908810, + 0xb2fe3f0b8599ef07, 0x861fa7e6dcb4aa15, + 0xdfbdcece67006ac9, 0x67a791e093e1d49a, + 0x8bd6a141006042bd, 0xe0c8bb2c5c6d24e0, + 0xaecc49914078536d, 0x58fae9f773886e18, + 0xda7f5bf590966848, 0xaf39a475506a899e, + 0x888f99797a5e012d, 0x6d8406c952429603, + 0xaab37fd7d8f58178, 0xc8e5087ba6d33b83, + 0xd5605fcdcf32e1d6, 0xfb1e4a9a90880a64, + 0x855c3be0a17fcd26, 0x5cf2eea09a55067f, + 0xa6b34ad8c9dfc06f, 0xf42faa48c0ea481e, + 0xd0601d8efc57b08b, 0xf13b94daf124da26, + 0x823c12795db6ce57, 0x76c53d08d6b70858, + 0xa2cb1717b52481ed, 0x54768c4b0c64ca6e, + 0xcb7ddcdda26da268, 0xa9942f5dcf7dfd09, + 0xfe5d54150b090b02, 0xd3f93b35435d7c4c, + 0x9efa548d26e5a6e1, 0xc47bc5014a1a6daf, + 0xc6b8e9b0709f109a, 0x359ab6419ca1091b, + 0xf867241c8cc6d4c0, 0xc30163d203c94b62, + 0x9b407691d7fc44f8, 0x79e0de63425dcf1d, + 0xc21094364dfb5636, 0x985915fc12f542e4, + 0xf294b943e17a2bc4, 0x3e6f5b7b17b2939d, + 0x979cf3ca6cec5b5a, 0xa705992ceecf9c42, + 0xbd8430bd08277231, 0x50c6ff782a838353, + 0xece53cec4a314ebd, 0xa4f8bf5635246428, + 0x940f4613ae5ed136, 0x871b7795e136be99, + 0xb913179899f68584, 0x28e2557b59846e3f, + 0xe757dd7ec07426e5, 0x331aeada2fe589cf, + 0x9096ea6f3848984f, 0x3ff0d2c85def7621, + 0xb4bca50b065abe63, 0xfed077a756b53a9, + 0xe1ebce4dc7f16dfb, 0xd3e8495912c62894, + 0x8d3360f09cf6e4bd, 0x64712dd7abbbd95c, + 0xb080392cc4349dec, 0xbd8d794d96aacfb3, + 0xdca04777f541c567, 0xecf0d7a0fc5583a0, + 0x89e42caaf9491b60, 0xf41686c49db57244, + 0xac5d37d5b79b6239, 0x311c2875c522ced5, + 0xd77485cb25823ac7, 0x7d633293366b828b, + 0x86a8d39ef77164bc, 0xae5dff9c02033197, + 0xa8530886b54dbdeb, 0xd9f57f830283fdfc, + 0xd267caa862a12d66, 0xd072df63c324fd7b, + 0x8380dea93da4bc60, 0x4247cb9e59f71e6d, + 0xa46116538d0deb78, 0x52d9be85f074e608, + 0xcd795be870516656, 0x67902e276c921f8b, + 0x806bd9714632dff6, 0xba1cd8a3db53b6, + 0xa086cfcd97bf97f3, 0x80e8a40eccd228a4, + 0xc8a883c0fdaf7df0, 0x6122cd128006b2cd, + 0xfad2a4b13d1b5d6c, 0x796b805720085f81, + 0x9cc3a6eec6311a63, 0xcbe3303674053bb0, + 0xc3f490aa77bd60fc, 0xbedbfc4411068a9c, + 0xf4f1b4d515acb93b, 0xee92fb5515482d44, + 0x991711052d8bf3c5, 0x751bdd152d4d1c4a, + 0xbf5cd54678eef0b6, 0xd262d45a78a0635d, + 0xef340a98172aace4, 0x86fb897116c87c34, + 0x9580869f0e7aac0e, 0xd45d35e6ae3d4da0, + 0xbae0a846d2195712, 0x8974836059cca109, + 0xe998d258869facd7, 0x2bd1a438703fc94b, + 0x91ff83775423cc06, 0x7b6306a34627ddcf, + 0xb67f6455292cbf08, 0x1a3bc84c17b1d542, + 0xe41f3d6a7377eeca, 0x20caba5f1d9e4a93, + 0x8e938662882af53e, 0x547eb47b7282ee9c, + 0xb23867fb2a35b28d, 0xe99e619a4f23aa43, + 0xdec681f9f4c31f31, 0x6405fa00e2ec94d4, + 0x8b3c113c38f9f37e, 0xde83bc408dd3dd04, + 0xae0b158b4738705e, 0x9624ab50b148d445, + 0xd98ddaee19068c76, 0x3badd624dd9b0957, + 0x87f8a8d4cfa417c9, 0xe54ca5d70a80e5d6, + 0xa9f6d30a038d1dbc, 0x5e9fcf4ccd211f4c, + 0xd47487cc8470652b, 0x7647c3200069671f, + 0x84c8d4dfd2c63f3b, 0x29ecd9f40041e073, + 0xa5fb0a17c777cf09, 0xf468107100525890, + 0xcf79cc9db955c2cc, 0x7182148d4066eeb4, + 0x81ac1fe293d599bf, 0xc6f14cd848405530, + 0xa21727db38cb002f, 0xb8ada00e5a506a7c, + 0xca9cf1d206fdc03b, 0xa6d90811f0e4851c, + 0xfd442e4688bd304a, 0x908f4a166d1da663, + 0x9e4a9cec15763e2e, 0x9a598e4e043287fe, + 0xc5dd44271ad3cdba, 0x40eff1e1853f29fd, + 0xf7549530e188c128, 0xd12bee59e68ef47c, + 0x9a94dd3e8cf578b9, 0x82bb74f8301958ce, + 0xc13a148e3032d6e7, 0xe36a52363c1faf01, + 0xf18899b1bc3f8ca1, 0xdc44e6c3cb279ac1, + 0x96f5600f15a7b7e5, 0x29ab103a5ef8c0b9, + 0xbcb2b812db11a5de, 0x7415d448f6b6f0e7, + 0xebdf661791d60f56, 0x111b495b3464ad21, + 0x936b9fcebb25c995, 0xcab10dd900beec34, + 0xb84687c269ef3bfb, 0x3d5d514f40eea742, + 0xe65829b3046b0afa, 0xcb4a5a3112a5112, + 0x8ff71a0fe2c2e6dc, 0x47f0e785eaba72ab, + 0xb3f4e093db73a093, 0x59ed216765690f56, + 0xe0f218b8d25088b8, 0x306869c13ec3532c, + 0x8c974f7383725573, 0x1e414218c73a13fb, + 0xafbd2350644eeacf, 0xe5d1929ef90898fa, + 0xdbac6c247d62a583, 0xdf45f746b74abf39, + 0x894bc396ce5da772, 0x6b8bba8c328eb783, + 0xab9eb47c81f5114f, 0x66ea92f3f326564, + 0xd686619ba27255a2, 0xc80a537b0efefebd, + 0x8613fd0145877585, 0xbd06742ce95f5f36, + 0xa798fc4196e952e7, 0x2c48113823b73704, + 0xd17f3b51fca3a7a0, 0xf75a15862ca504c5, + 0x82ef85133de648c4, 0x9a984d73dbe722fb, + 0xa3ab66580d5fdaf5, 0xc13e60d0d2e0ebba, + 0xcc963fee10b7d1b3, 0x318df905079926a8, + 0xffbbcfe994e5c61f, 0xfdf17746497f7052, + 0x9fd561f1fd0f9bd3, 0xfeb6ea8bedefa633, + 0xc7caba6e7c5382c8, 0xfe64a52ee96b8fc0, + 0xf9bd690a1b68637b, 0x3dfdce7aa3c673b0, + 0x9c1661a651213e2d, 0x6bea10ca65c084e, + 0xc31bfa0fe5698db8, 0x486e494fcff30a62, + 0xf3e2f893dec3f126, 0x5a89dba3c3efccfa, + 0x986ddb5c6b3a76b7, 0xf89629465a75e01c, + 0xbe89523386091465, 0xf6bbb397f1135823, + 0xee2ba6c0678b597f, 0x746aa07ded582e2c, + 0x94db483840b717ef, 0xa8c2a44eb4571cdc, + 0xba121a4650e4ddeb, 0x92f34d62616ce413, + 0xe896a0d7e51e1566, 0x77b020baf9c81d17, + 0x915e2486ef32cd60, 0xace1474dc1d122e, + 0xb5b5ada8aaff80b8, 0xd819992132456ba, + 0xe3231912d5bf60e6, 0x10e1fff697ed6c69, + 0x8df5efabc5979c8f, 0xca8d3ffa1ef463c1, + 0xb1736b96b6fd83b3, 0xbd308ff8a6b17cb2, + 0xddd0467c64bce4a0, 0xac7cb3f6d05ddbde, + 0x8aa22c0dbef60ee4, 0x6bcdf07a423aa96b, + 0xad4ab7112eb3929d, 0x86c16c98d2c953c6, + 0xd89d64d57a607744, 0xe871c7bf077ba8b7, + 0x87625f056c7c4a8b, 0x11471cd764ad4972, + 0xa93af6c6c79b5d2d, 0xd598e40d3dd89bcf, + 0xd389b47879823479, 0x4aff1d108d4ec2c3, + 0x843610cb4bf160cb, 0xcedf722a585139ba, + 0xa54394fe1eedb8fe, 0xc2974eb4ee658828, + 0xce947a3da6a9273e, 0x733d226229feea32, + 0x811ccc668829b887, 0x806357d5a3f525f, + 0xa163ff802a3426a8, 0xca07c2dcb0cf26f7, + 0xc9bcff6034c13052, 0xfc89b393dd02f0b5, + 0xfc2c3f3841f17c67, 0xbbac2078d443ace2, + 0x9d9ba7832936edc0, 0xd54b944b84aa4c0d, + 0xc5029163f384a931, 0xa9e795e65d4df11, + 0xf64335bcf065d37d, 0x4d4617b5ff4a16d5, + 0x99ea0196163fa42e, 0x504bced1bf8e4e45, + 0xc06481fb9bcf8d39, 0xe45ec2862f71e1d6, + 0xf07da27a82c37088, 0x5d767327bb4e5a4c, + 0x964e858c91ba2655, 0x3a6a07f8d510f86f, + 0xbbe226efb628afea, 0x890489f70a55368b, + 0xeadab0aba3b2dbe5, 0x2b45ac74ccea842e, + 0x92c8ae6b464fc96f, 0x3b0b8bc90012929d, + 0xb77ada0617e3bbcb, 0x9ce6ebb40173744, + 0xe55990879ddcaabd, 0xcc420a6a101d0515, + 0x8f57fa54c2a9eab6, 0x9fa946824a12232d, + 0xb32df8e9f3546564, 0x47939822dc96abf9, + 0xdff9772470297ebd, 0x59787e2b93bc56f7, + 0x8bfbea76c619ef36, 0x57eb4edb3c55b65a, + 0xaefae51477a06b03, 0xede622920b6b23f1, + 0xdab99e59958885c4, 0xe95fab368e45eced, + 0x88b402f7fd75539b, 0x11dbcb0218ebb414, + 0xaae103b5fcd2a881, 0xd652bdc29f26a119, + 0xd59944a37c0752a2, 0x4be76d3346f0495f, + 0x857fcae62d8493a5, 0x6f70a4400c562ddb, + 0xa6dfbd9fb8e5b88e, 0xcb4ccd500f6bb952, + 0xd097ad07a71f26b2, 0x7e2000a41346a7a7, + 0x825ecc24c873782f, 0x8ed400668c0c28c8, + 0xa2f67f2dfa90563b, 0x728900802f0f32fa, + 0xcbb41ef979346bca, 0x4f2b40a03ad2ffb9, + 0xfea126b7d78186bc, 0xe2f610c84987bfa8, + 0x9f24b832e6b0f436, 0xdd9ca7d2df4d7c9, + 0xc6ede63fa05d3143, 0x91503d1c79720dbb, + 0xf8a95fcf88747d94, 0x75a44c6397ce912a, + 0x9b69dbe1b548ce7c, 0xc986afbe3ee11aba, + 0xc24452da229b021b, 0xfbe85badce996168, + 0xf2d56790ab41c2a2, 0xfae27299423fb9c3, + 0x97c560ba6b0919a5, 0xdccd879fc967d41a, + 0xbdb6b8e905cb600f, 0x5400e987bbc1c920, + 0xed246723473e3813, 0x290123e9aab23b68, + 0x9436c0760c86e30b, 0xf9a0b6720aaf6521, + 0xb94470938fa89bce, 0xf808e40e8d5b3e69, + 0xe7958cb87392c2c2, 0xb60b1d1230b20e04, + 0x90bd77f3483bb9b9, 0xb1c6f22b5e6f48c2, + 0xb4ecd5f01a4aa828, 0x1e38aeb6360b1af3, + 0xe2280b6c20dd5232, 0x25c6da63c38de1b0, + 0x8d590723948a535f, 0x579c487e5a38ad0e, + 0xb0af48ec79ace837, 0x2d835a9df0c6d851, + 0xdcdb1b2798182244, 0xf8e431456cf88e65, + 0x8a08f0f8bf0f156b, 0x1b8e9ecb641b58ff, + 0xac8b2d36eed2dac5, 0xe272467e3d222f3f, + 0xd7adf884aa879177, 0x5b0ed81dcc6abb0f, + 0x86ccbb52ea94baea, 0x98e947129fc2b4e9, + 0xa87fea27a539e9a5, 0x3f2398d747b36224, + 0xd29fe4b18e88640e, 0x8eec7f0d19a03aad, + 0x83a3eeeef9153e89, 0x1953cf68300424ac, + 0xa48ceaaab75a8e2b, 0x5fa8c3423c052dd7, + 0xcdb02555653131b6, 0x3792f412cb06794d, + 0x808e17555f3ebf11, 0xe2bbd88bbee40bd0, + 0xa0b19d2ab70e6ed6, 0x5b6aceaeae9d0ec4, + 0xc8de047564d20a8b, 0xf245825a5a445275, + 0xfb158592be068d2e, 0xeed6e2f0f0d56712, + 0x9ced737bb6c4183d, 0x55464dd69685606b, + 0xc428d05aa4751e4c, 0xaa97e14c3c26b886, + 0xf53304714d9265df, 0xd53dd99f4b3066a8, + 0x993fe2c6d07b7fab, 0xe546a8038efe4029, + 0xbf8fdb78849a5f96, 0xde98520472bdd033, + 0xef73d256a5c0f77c, 0x963e66858f6d4440, + 0x95a8637627989aad, 0xdde7001379a44aa8, + 0xbb127c53b17ec159, 0x5560c018580d5d52, + 0xe9d71b689dde71af, 0xaab8f01e6e10b4a6, + 0x9226712162ab070d, 0xcab3961304ca70e8, + 0xb6b00d69bb55c8d1, 0x3d607b97c5fd0d22, + 0xe45c10c42a2b3b05, 0x8cb89a7db77c506a, + 0x8eb98a7a9a5b04e3, 0x77f3608e92adb242, + 0xb267ed1940f1c61c, 0x55f038b237591ed3, + 0xdf01e85f912e37a3, 0x6b6c46dec52f6688, + 0x8b61313bbabce2c6, 0x2323ac4b3b3da015, + 0xae397d8aa96c1b77, 0xabec975e0a0d081a, + 0xd9c7dced53c72255, 0x96e7bd358c904a21, + 0x881cea14545c7575, 0x7e50d64177da2e54, + 0xaa242499697392d2, 0xdde50bd1d5d0b9e9, + 0xd4ad2dbfc3d07787, 0x955e4ec64b44e864, + 0x84ec3c97da624ab4, 0xbd5af13bef0b113e, + 0xa6274bbdd0fadd61, 0xecb1ad8aeacdd58e, + 0xcfb11ead453994ba, 0x67de18eda5814af2, + 0x81ceb32c4b43fcf4, 0x80eacf948770ced7, + 0xa2425ff75e14fc31, 0xa1258379a94d028d, + 0xcad2f7f5359a3b3e, 0x96ee45813a04330, + 0xfd87b5f28300ca0d, 0x8bca9d6e188853fc, + 0x9e74d1b791e07e48, 0x775ea264cf55347e, + 0xc612062576589dda, 0x95364afe032a819e, + 0xf79687aed3eec551, 0x3a83ddbd83f52205, + 0x9abe14cd44753b52, 0xc4926a9672793543, + 0xc16d9a0095928a27, 0x75b7053c0f178294, + 0xf1c90080baf72cb1, 0x5324c68b12dd6339, + 0x971da05074da7bee, 0xd3f6fc16ebca5e04, + 0xbce5086492111aea, 0x88f4bb1ca6bcf585, + 0xec1e4a7db69561a5, 0x2b31e9e3d06c32e6, + 0x9392ee8e921d5d07, 0x3aff322e62439fd0, + 0xb877aa3236a4b449, 0x9befeb9fad487c3, + 0xe69594bec44de15b, 0x4c2ebe687989a9b4, + 0x901d7cf73ab0acd9, 0xf9d37014bf60a11, + 0xb424dc35095cd80f, 0x538484c19ef38c95, + 0xe12e13424bb40e13, 0x2865a5f206b06fba, + 0x8cbccc096f5088cb, 0xf93f87b7442e45d4, + 0xafebff0bcb24aafe, 0xf78f69a51539d749, + 0xdbe6fecebdedd5be, 0xb573440e5a884d1c, + 0x89705f4136b4a597, 0x31680a88f8953031, + 0xabcc77118461cefc, 0xfdc20d2b36ba7c3e, + 0xd6bf94d5e57a42bc, 0x3d32907604691b4d, + 0x8637bd05af6c69b5, 0xa63f9a49c2c1b110, + 0xa7c5ac471b478423, 0xfcf80dc33721d54, + 0xd1b71758e219652b, 0xd3c36113404ea4a9, + 0x83126e978d4fdf3b, 0x645a1cac083126ea, + 0xa3d70a3d70a3d70a, 0x3d70a3d70a3d70a4, + 0xcccccccccccccccc, 0xcccccccccccccccd, + 0x8000000000000000, 0x0, + 0xa000000000000000, 0x0, + 0xc800000000000000, 0x0, + 0xfa00000000000000, 0x0, + 0x9c40000000000000, 0x0, + 0xc350000000000000, 0x0, + 0xf424000000000000, 0x0, + 0x9896800000000000, 0x0, + 0xbebc200000000000, 0x0, + 0xee6b280000000000, 0x0, + 0x9502f90000000000, 0x0, + 0xba43b74000000000, 0x0, + 0xe8d4a51000000000, 0x0, + 0x9184e72a00000000, 0x0, + 0xb5e620f480000000, 0x0, + 0xe35fa931a0000000, 0x0, + 0x8e1bc9bf04000000, 0x0, + 0xb1a2bc2ec5000000, 0x0, + 0xde0b6b3a76400000, 0x0, + 0x8ac7230489e80000, 0x0, + 0xad78ebc5ac620000, 0x0, + 0xd8d726b7177a8000, 0x0, + 0x878678326eac9000, 0x0, + 0xa968163f0a57b400, 0x0, + 0xd3c21bcecceda100, 0x0, + 0x84595161401484a0, 0x0, + 0xa56fa5b99019a5c8, 0x0, + 0xcecb8f27f4200f3a, 0x0, + 0x813f3978f8940984, 0x4000000000000000, + 0xa18f07d736b90be5, 0x5000000000000000, + 0xc9f2c9cd04674ede, 0xa400000000000000, + 0xfc6f7c4045812296, 0x4d00000000000000, + 0x9dc5ada82b70b59d, 0xf020000000000000, + 0xc5371912364ce305, 0x6c28000000000000, + 0xf684df56c3e01bc6, 0xc732000000000000, + 0x9a130b963a6c115c, 0x3c7f400000000000, + 0xc097ce7bc90715b3, 0x4b9f100000000000, + 0xf0bdc21abb48db20, 0x1e86d40000000000, + 0x96769950b50d88f4, 0x1314448000000000, + 0xbc143fa4e250eb31, 0x17d955a000000000, + 0xeb194f8e1ae525fd, 0x5dcfab0800000000, + 0x92efd1b8d0cf37be, 0x5aa1cae500000000, + 0xb7abc627050305ad, 0xf14a3d9e40000000, + 0xe596b7b0c643c719, 0x6d9ccd05d0000000, + 0x8f7e32ce7bea5c6f, 0xe4820023a2000000, + 0xb35dbf821ae4f38b, 0xdda2802c8a800000, + 0xe0352f62a19e306e, 0xd50b2037ad200000, + 0x8c213d9da502de45, 0x4526f422cc340000, + 0xaf298d050e4395d6, 0x9670b12b7f410000, + 0xdaf3f04651d47b4c, 0x3c0cdd765f114000, + 0x88d8762bf324cd0f, 0xa5880a69fb6ac800, + 0xab0e93b6efee0053, 0x8eea0d047a457a00, + 0xd5d238a4abe98068, 0x72a4904598d6d880, + 0x85a36366eb71f041, 0x47a6da2b7f864750, + 0xa70c3c40a64e6c51, 0x999090b65f67d924, + 0xd0cf4b50cfe20765, 0xfff4b4e3f741cf6d, + 0x82818f1281ed449f, 0xbff8f10e7a8921a4, + 0xa321f2d7226895c7, 0xaff72d52192b6a0d, + 0xcbea6f8ceb02bb39, 0x9bf4f8a69f764490, + 0xfee50b7025c36a08, 0x2f236d04753d5b4, + 0x9f4f2726179a2245, 0x1d762422c946590, + 0xc722f0ef9d80aad6, 0x424d3ad2b7b97ef5, + 0xf8ebad2b84e0d58b, 0xd2e0898765a7deb2, + 0x9b934c3b330c8577, 0x63cc55f49f88eb2f, + 0xc2781f49ffcfa6d5, 0x3cbf6b71c76b25fb, + 0xf316271c7fc3908a, 0x8bef464e3945ef7a, + 0x97edd871cfda3a56, 0x97758bf0e3cbb5ac, + 0xbde94e8e43d0c8ec, 0x3d52eeed1cbea317, + 0xed63a231d4c4fb27, 0x4ca7aaa863ee4bdd, + 0x945e455f24fb1cf8, 0x8fe8caa93e74ef6a, + 0xb975d6b6ee39e436, 0xb3e2fd538e122b44, + 0xe7d34c64a9c85d44, 0x60dbbca87196b616, + 0x90e40fbeea1d3a4a, 0xbc8955e946fe31cd, + 0xb51d13aea4a488dd, 0x6babab6398bdbe41, + 0xe264589a4dcdab14, 0xc696963c7eed2dd1, + 0x8d7eb76070a08aec, 0xfc1e1de5cf543ca2, + 0xb0de65388cc8ada8, 0x3b25a55f43294bcb, + 0xdd15fe86affad912, 0x49ef0eb713f39ebe, + 0x8a2dbf142dfcc7ab, 0x6e3569326c784337, + 0xacb92ed9397bf996, 0x49c2c37f07965404, + 0xd7e77a8f87daf7fb, 0xdc33745ec97be906, + 0x86f0ac99b4e8dafd, 0x69a028bb3ded71a3, + 0xa8acd7c0222311bc, 0xc40832ea0d68ce0c, + 0xd2d80db02aabd62b, 0xf50a3fa490c30190, + 0x83c7088e1aab65db, 0x792667c6da79e0fa, + 0xa4b8cab1a1563f52, 0x577001b891185938, + 0xcde6fd5e09abcf26, 0xed4c0226b55e6f86, + 0x80b05e5ac60b6178, 0x544f8158315b05b4, + 0xa0dc75f1778e39d6, 0x696361ae3db1c721, + 0xc913936dd571c84c, 0x3bc3a19cd1e38e9, + 0xfb5878494ace3a5f, 0x4ab48a04065c723, + 0x9d174b2dcec0e47b, 0x62eb0d64283f9c76, + 0xc45d1df942711d9a, 0x3ba5d0bd324f8394, + 0xf5746577930d6500, 0xca8f44ec7ee36479, + 0x9968bf6abbe85f20, 0x7e998b13cf4e1ecb, + 0xbfc2ef456ae276e8, 0x9e3fedd8c321a67e, + 0xefb3ab16c59b14a2, 0xc5cfe94ef3ea101e, + 0x95d04aee3b80ece5, 0xbba1f1d158724a12, + 0xbb445da9ca61281f, 0x2a8a6e45ae8edc97, + 0xea1575143cf97226, 0xf52d09d71a3293bd, + 0x924d692ca61be758, 0x593c2626705f9c56, + 0xb6e0c377cfa2e12e, 0x6f8b2fb00c77836c, + 0xe498f455c38b997a, 0xb6dfb9c0f956447, + 0x8edf98b59a373fec, 0x4724bd4189bd5eac, + 0xb2977ee300c50fe7, 0x58edec91ec2cb657, + 0xdf3d5e9bc0f653e1, 0x2f2967b66737e3ed, + 0x8b865b215899f46c, 0xbd79e0d20082ee74, + 0xae67f1e9aec07187, 0xecd8590680a3aa11, + 0xda01ee641a708de9, 0xe80e6f4820cc9495, + 0x884134fe908658b2, 0x3109058d147fdcdd, + 0xaa51823e34a7eede, 0xbd4b46f0599fd415, + 0xd4e5e2cdc1d1ea96, 0x6c9e18ac7007c91a, + 0x850fadc09923329e, 0x3e2cf6bc604ddb0, + 0xa6539930bf6bff45, 0x84db8346b786151c, + 0xcfe87f7cef46ff16, 0xe612641865679a63, + 0x81f14fae158c5f6e, 0x4fcb7e8f3f60c07e, + 0xa26da3999aef7749, 0xe3be5e330f38f09d, + 0xcb090c8001ab551c, 0x5cadf5bfd3072cc5, + 0xfdcb4fa002162a63, 0x73d9732fc7c8f7f6, + 0x9e9f11c4014dda7e, 0x2867e7fddcdd9afa, + 0xc646d63501a1511d, 0xb281e1fd541501b8, + 0xf7d88bc24209a565, 0x1f225a7ca91a4226, + 0x9ae757596946075f, 0x3375788de9b06958, + 0xc1a12d2fc3978937, 0x52d6b1641c83ae, + 0xf209787bb47d6b84, 0xc0678c5dbd23a49a, + 0x9745eb4d50ce6332, 0xf840b7ba963646e0, + 0xbd176620a501fbff, 0xb650e5a93bc3d898, + 0xec5d3fa8ce427aff, 0xa3e51f138ab4cebe, + 0x93ba47c980e98cdf, 0xc66f336c36b10137, + 0xb8a8d9bbe123f017, 0xb80b0047445d4184, + 0xe6d3102ad96cec1d, 0xa60dc059157491e5, + 0x9043ea1ac7e41392, 0x87c89837ad68db2f, + 0xb454e4a179dd1877, 0x29babe4598c311fb, + 0xe16a1dc9d8545e94, 0xf4296dd6fef3d67a, + 0x8ce2529e2734bb1d, 0x1899e4a65f58660c, + 0xb01ae745b101e9e4, 0x5ec05dcff72e7f8f, + 0xdc21a1171d42645d, 0x76707543f4fa1f73, + 0x899504ae72497eba, 0x6a06494a791c53a8, + 0xabfa45da0edbde69, 0x487db9d17636892, + 0xd6f8d7509292d603, 0x45a9d2845d3c42b6, + 0x865b86925b9bc5c2, 0xb8a2392ba45a9b2, + 0xa7f26836f282b732, 0x8e6cac7768d7141e, + 0xd1ef0244af2364ff, 0x3207d795430cd926, + 0x8335616aed761f1f, 0x7f44e6bd49e807b8, + 0xa402b9c5a8d3a6e7, 0x5f16206c9c6209a6, + 0xcd036837130890a1, 0x36dba887c37a8c0f, + 0x802221226be55a64, 0xc2494954da2c9789, + 0xa02aa96b06deb0fd, 0xf2db9baa10b7bd6c, + 0xc83553c5c8965d3d, 0x6f92829494e5acc7, + 0xfa42a8b73abbf48c, 0xcb772339ba1f17f9, + 0x9c69a97284b578d7, 0xff2a760414536efb, + 0xc38413cf25e2d70d, 0xfef5138519684aba, + 0xf46518c2ef5b8cd1, 0x7eb258665fc25d69, + 0x98bf2f79d5993802, 0xef2f773ffbd97a61, + 0xbeeefb584aff8603, 0xaafb550ffacfd8fa, + 0xeeaaba2e5dbf6784, 0x95ba2a53f983cf38, + 0x952ab45cfa97a0b2, 0xdd945a747bf26183, + 0xba756174393d88df, 0x94f971119aeef9e4, + 0xe912b9d1478ceb17, 0x7a37cd5601aab85d, + 0x91abb422ccb812ee, 0xac62e055c10ab33a, + 0xb616a12b7fe617aa, 0x577b986b314d6009, + 0xe39c49765fdf9d94, 0xed5a7e85fda0b80b, + 0x8e41ade9fbebc27d, 0x14588f13be847307, + 0xb1d219647ae6b31c, 0x596eb2d8ae258fc8, + 0xde469fbd99a05fe3, 0x6fca5f8ed9aef3bb, + 0x8aec23d680043bee, 0x25de7bb9480d5854, + 0xada72ccc20054ae9, 0xaf561aa79a10ae6a, + 0xd910f7ff28069da4, 0x1b2ba1518094da04, + 0x87aa9aff79042286, 0x90fb44d2f05d0842, + 0xa99541bf57452b28, 0x353a1607ac744a53, + 0xd3fa922f2d1675f2, 0x42889b8997915ce8, + 0x847c9b5d7c2e09b7, 0x69956135febada11, + 0xa59bc234db398c25, 0x43fab9837e699095, + 0xcf02b2c21207ef2e, 0x94f967e45e03f4bb, + 0x8161afb94b44f57d, 0x1d1be0eebac278f5, + 0xa1ba1ba79e1632dc, 0x6462d92a69731732, + 0xca28a291859bbf93, 0x7d7b8f7503cfdcfe, + 0xfcb2cb35e702af78, 0x5cda735244c3d43e, + 0x9defbf01b061adab, 0x3a0888136afa64a7, + 0xc56baec21c7a1916, 0x88aaa1845b8fdd0, + 0xf6c69a72a3989f5b, 0x8aad549e57273d45, + 0x9a3c2087a63f6399, 0x36ac54e2f678864b, + 0xc0cb28a98fcf3c7f, 0x84576a1bb416a7dd, + 0xf0fdf2d3f3c30b9f, 0x656d44a2a11c51d5, + 0x969eb7c47859e743, 0x9f644ae5a4b1b325, + 0xbc4665b596706114, 0x873d5d9f0dde1fee, + 0xeb57ff22fc0c7959, 0xa90cb506d155a7ea, + 0x9316ff75dd87cbd8, 0x9a7f12442d588f2, + 0xb7dcbf5354e9bece, 0xc11ed6d538aeb2f, + 0xe5d3ef282a242e81, 0x8f1668c8a86da5fa, + 0x8fa475791a569d10, 0xf96e017d694487bc, + 0xb38d92d760ec4455, 0x37c981dcc395a9ac, + 0xe070f78d3927556a, 0x85bbe253f47b1417, + 0x8c469ab843b89562, 0x93956d7478ccec8e, + 0xaf58416654a6babb, 0x387ac8d1970027b2, + 0xdb2e51bfe9d0696a, 0x6997b05fcc0319e, + 0x88fcf317f22241e2, 0x441fece3bdf81f03, + 0xab3c2fddeeaad25a, 0xd527e81cad7626c3, + 0xd60b3bd56a5586f1, 0x8a71e223d8d3b074, + 0x85c7056562757456, 0xf6872d5667844e49, + 0xa738c6bebb12d16c, 0xb428f8ac016561db, + 0xd106f86e69d785c7, 0xe13336d701beba52, + 0x82a45b450226b39c, 0xecc0024661173473, + 0xa34d721642b06084, 0x27f002d7f95d0190, + 0xcc20ce9bd35c78a5, 0x31ec038df7b441f4, + 0xff290242c83396ce, 0x7e67047175a15271, + 0x9f79a169bd203e41, 0xf0062c6e984d386, + 0xc75809c42c684dd1, 0x52c07b78a3e60868, + 0xf92e0c3537826145, 0xa7709a56ccdf8a82, + 0x9bbcc7a142b17ccb, 0x88a66076400bb691, + 0xc2abf989935ddbfe, 0x6acff893d00ea435, + 0xf356f7ebf83552fe, 0x583f6b8c4124d43, + 0x98165af37b2153de, 0xc3727a337a8b704a, + 0xbe1bf1b059e9a8d6, 0x744f18c0592e4c5c, + 0xeda2ee1c7064130c, 0x1162def06f79df73, + 0x9485d4d1c63e8be7, 0x8addcb5645ac2ba8, + 0xb9a74a0637ce2ee1, 0x6d953e2bd7173692, + 0xe8111c87c5c1ba99, 0xc8fa8db6ccdd0437, + 0x910ab1d4db9914a0, 0x1d9c9892400a22a2, + 0xb54d5e4a127f59c8, 0x2503beb6d00cab4b, + 0xe2a0b5dc971f303a, 0x2e44ae64840fd61d, + 0x8da471a9de737e24, 0x5ceaecfed289e5d2, + 0xb10d8e1456105dad, 0x7425a83e872c5f47, + 0xdd50f1996b947518, 0xd12f124e28f77719, + 0x8a5296ffe33cc92f, 0x82bd6b70d99aaa6f, + 0xace73cbfdc0bfb7b, 0x636cc64d1001550b, + 0xd8210befd30efa5a, 0x3c47f7e05401aa4e, + 0x8714a775e3e95c78, 0x65acfaec34810a71, + 0xa8d9d1535ce3b396, 0x7f1839a741a14d0d, + 0xd31045a8341ca07c, 0x1ede48111209a050, + 0x83ea2b892091e44d, 0x934aed0aab460432, + 0xa4e4b66b68b65d60, 0xf81da84d5617853f, + 0xce1de40642e3f4b9, 0x36251260ab9d668e, + 0x80d2ae83e9ce78f3, 0xc1d72b7c6b426019, + 0xa1075a24e4421730, 0xb24cf65b8612f81f, + 0xc94930ae1d529cfc, 0xdee033f26797b627, + 0xfb9b7cd9a4a7443c, 0x169840ef017da3b1, + 0x9d412e0806e88aa5, 0x8e1f289560ee864e, + 0xc491798a08a2ad4e, 0xf1a6f2bab92a27e2, + 0xf5b5d7ec8acb58a2, 0xae10af696774b1db, + 0x9991a6f3d6bf1765, 0xacca6da1e0a8ef29, + 0xbff610b0cc6edd3f, 0x17fd090a58d32af3, + 0xeff394dcff8a948e, 0xddfc4b4cef07f5b0, + 0x95f83d0a1fb69cd9, 0x4abdaf101564f98e, + 0xbb764c4ca7a4440f, 0x9d6d1ad41abe37f1, + 0xea53df5fd18d5513, 0x84c86189216dc5ed, + 0x92746b9be2f8552c, 0x32fd3cf5b4e49bb4, + 0xb7118682dbb66a77, 0x3fbc8c33221dc2a1, + 0xe4d5e82392a40515, 0xfabaf3feaa5334a, + 0x8f05b1163ba6832d, 0x29cb4d87f2a7400e, + 0xb2c71d5bca9023f8, 0x743e20e9ef511012, + 0xdf78e4b2bd342cf6, 0x914da9246b255416, + 0x8bab8eefb6409c1a, 0x1ad089b6c2f7548e, + 0xae9672aba3d0c320, 0xa184ac2473b529b1, + 0xda3c0f568cc4f3e8, 0xc9e5d72d90a2741e, + 0x8865899617fb1871, 0x7e2fa67c7a658892, + 0xaa7eebfb9df9de8d, 0xddbb901b98feeab7, + 0xd51ea6fa85785631, 0x552a74227f3ea565, + 0x8533285c936b35de, 0xd53a88958f87275f, + 0xa67ff273b8460356, 0x8a892abaf368f137, + 0xd01fef10a657842c, 0x2d2b7569b0432d85, + 0x8213f56a67f6b29b, 0x9c3b29620e29fc73, + 0xa298f2c501f45f42, 0x8349f3ba91b47b8f, + 0xcb3f2f7642717713, 0x241c70a936219a73, + 0xfe0efb53d30dd4d7, 0xed238cd383aa0110, + 0x9ec95d1463e8a506, 0xf4363804324a40aa, + 0xc67bb4597ce2ce48, 0xb143c6053edcd0d5, + 0xf81aa16fdc1b81da, 0xdd94b7868e94050a, + 0x9b10a4e5e9913128, 0xca7cf2b4191c8326, + 0xc1d4ce1f63f57d72, 0xfd1c2f611f63a3f0, + 0xf24a01a73cf2dccf, 0xbc633b39673c8cec, + 0x976e41088617ca01, 0xd5be0503e085d813, + 0xbd49d14aa79dbc82, 0x4b2d8644d8a74e18, + 0xec9c459d51852ba2, 0xddf8e7d60ed1219e, + 0x93e1ab8252f33b45, 0xcabb90e5c942b503, + 0xb8da1662e7b00a17, 0x3d6a751f3b936243, + 0xe7109bfba19c0c9d, 0xcc512670a783ad4, + 0x906a617d450187e2, 0x27fb2b80668b24c5, + 0xb484f9dc9641e9da, 0xb1f9f660802dedf6, + 0xe1a63853bbd26451, 0x5e7873f8a0396973, + 0x8d07e33455637eb2, 0xdb0b487b6423e1e8, + 0xb049dc016abc5e5f, 0x91ce1a9a3d2cda62, + 0xdc5c5301c56b75f7, 0x7641a140cc7810fb, + 0x89b9b3e11b6329ba, 0xa9e904c87fcb0a9d, + 0xac2820d9623bf429, 0x546345fa9fbdcd44, + 0xd732290fbacaf133, 0xa97c177947ad4095, + 0x867f59a9d4bed6c0, 0x49ed8eabcccc485d, + 0xa81f301449ee8c70, 0x5c68f256bfff5a74, + 0xd226fc195c6a2f8c, 0x73832eec6fff3111, + 0x83585d8fd9c25db7, 0xc831fd53c5ff7eab, + 0xa42e74f3d032f525, 0xba3e7ca8b77f5e55, + 0xcd3a1230c43fb26f, 0x28ce1bd2e55f35eb, + 0x80444b5e7aa7cf85, 0x7980d163cf5b81b3, + 0xa0555e361951c366, 0xd7e105bcc332621f, + 0xc86ab5c39fa63440, 0x8dd9472bf3fefaa7, + 0xfa856334878fc150, 0xb14f98f6f0feb951, + 0x9c935e00d4b9d8d2, 0x6ed1bf9a569f33d3, + 0xc3b8358109e84f07, 0xa862f80ec4700c8, + 0xf4a642e14c6262c8, 0xcd27bb612758c0fa, + 0x98e7e9cccfbd7dbd, 0x8038d51cb897789c, + 0xbf21e44003acdd2c, 0xe0470a63e6bd56c3, + 0xeeea5d5004981478, 0x1858ccfce06cac74, + 0x95527a5202df0ccb, 0xf37801e0c43ebc8, + 0xbaa718e68396cffd, 0xd30560258f54e6ba, + 0xe950df20247c83fd, 0x47c6b82ef32a2069, + 0x91d28b7416cdd27e, 0x4cdc331d57fa5441, + 0xb6472e511c81471d, 0xe0133fe4adf8e952, + 0xe3d8f9e563a198e5, 0x58180fddd97723a6, + 0x8e679c2f5e44ff8f, 0x570f09eaa7ea7648, + }; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr uint64_t + powers_template::power_of_five_128[number_of_entries]; + +#endif + +using powers = powers_template<>; + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/float_common.h b/3rdparty/fast_float/float_common.h new file mode 100644 index 000000000000..8fd056029629 --- /dev/null +++ b/3rdparty/fast_float/float_common.h @@ -0,0 +1,1240 @@ +#ifndef FASTFLOAT_FLOAT_COMMON_H +#define FASTFLOAT_FLOAT_COMMON_H + +#include +#include +#include +#include +#include +#include +#include +#ifdef __has_include +#if __has_include() && (__cplusplus > 202002L || (defined(_MSVC_LANG) && (_MSVC_LANG > 202002L))) +#include +#endif +#endif +#include "constexpr_feature_detect.h" + +#define FASTFLOAT_VERSION_MAJOR 8 +#define FASTFLOAT_VERSION_MINOR 0 +#define FASTFLOAT_VERSION_PATCH 2 + +#define FASTFLOAT_STRINGIZE_IMPL(x) #x +#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x) + +#define FASTFLOAT_VERSION_STR \ + FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MAJOR) \ + "." FASTFLOAT_STRINGIZE(FASTFLOAT_VERSION_MINOR) "." FASTFLOAT_STRINGIZE( \ + FASTFLOAT_VERSION_PATCH) + +#define FASTFLOAT_VERSION \ + (FASTFLOAT_VERSION_MAJOR * 10000 + FASTFLOAT_VERSION_MINOR * 100 + \ + FASTFLOAT_VERSION_PATCH) + +namespace fast_float { + +enum class chars_format : uint64_t; + +namespace detail { +constexpr chars_format basic_json_fmt = chars_format(1 << 5); +constexpr chars_format basic_fortran_fmt = chars_format(1 << 6); +} // namespace detail + +enum class chars_format : uint64_t { + scientific = 1 << 0, + fixed = 1 << 2, + hex = 1 << 3, + no_infnan = 1 << 4, + // RFC 8259: https://datatracker.ietf.org/doc/html/rfc8259#section-6 + json = uint64_t(detail::basic_json_fmt) | fixed | scientific | no_infnan, + // Extension of RFC 8259 where, e.g., "inf" and "nan" are allowed. + json_or_infnan = uint64_t(detail::basic_json_fmt) | fixed | scientific, + fortran = uint64_t(detail::basic_fortran_fmt) | fixed | scientific, + general = fixed | scientific, + allow_leading_plus = 1 << 7, + skip_white_space = 1 << 8, +}; + +template struct from_chars_result_t { + UC const *ptr; + std::errc ec; +}; + +using from_chars_result = from_chars_result_t; + +template struct parse_options_t { + constexpr explicit parse_options_t(chars_format fmt = chars_format::general, + UC dot = UC('.'), int b = 10) + : format(fmt), decimal_point(dot), base(b) {} + + /** Which number formats are accepted */ + chars_format format; + /** The character used as decimal point */ + UC decimal_point; + /** The base used for integers */ + int base; +}; + +using parse_options = parse_options_t; + +} // namespace fast_float + +#if FASTFLOAT_HAS_BIT_CAST +#include +#endif + +#if (defined(__x86_64) || defined(__x86_64__) || defined(_M_X64) || \ + defined(__amd64) || defined(__aarch64__) || defined(_M_ARM64) || \ + defined(__MINGW64__) || defined(__s390x__) || \ + (defined(__ppc64__) || defined(__PPC64__) || defined(__ppc64le__) || \ + defined(__PPC64LE__)) || \ + defined(__loongarch64)) +#define FASTFLOAT_64BIT 1 +#elif (defined(__i386) || defined(__i386__) || defined(_M_IX86) || \ + defined(__arm__) || defined(_M_ARM) || defined(__ppc__) || \ + defined(__MINGW32__) || defined(__EMSCRIPTEN__)) +#define FASTFLOAT_32BIT 1 +#else + // Need to check incrementally, since SIZE_MAX is a size_t, avoid overflow. +// We can never tell the register width, but the SIZE_MAX is a good +// approximation. UINTPTR_MAX and INTPTR_MAX are optional, so avoid them for max +// portability. +#if SIZE_MAX == 0xffff +#error Unknown platform (16-bit, unsupported) +#elif SIZE_MAX == 0xffffffff +#define FASTFLOAT_32BIT 1 +#elif SIZE_MAX == 0xffffffffffffffff +#define FASTFLOAT_64BIT 1 +#else +#error Unknown platform (not 32-bit, not 64-bit?) +#endif +#endif + +#if ((defined(_WIN32) || defined(_WIN64)) && !defined(__clang__)) || \ + (defined(_M_ARM64) && !defined(__MINGW32__)) +#include +#endif + +#if defined(_MSC_VER) && !defined(__clang__) +#define FASTFLOAT_VISUAL_STUDIO 1 +#endif + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(sun) || defined(__sun) +#include +#elif defined(__MVS__) +#include +#else +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define FASTFLOAT_IS_BIG_ENDIAN 0 +#else +#define FASTFLOAT_IS_BIG_ENDIAN 1 +#endif +#endif + +#if defined(__SSE2__) || (defined(FASTFLOAT_VISUAL_STUDIO) && \ + (defined(_M_AMD64) || defined(_M_X64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP == 2))) +#define FASTFLOAT_SSE2 1 +#endif + +#if defined(__aarch64__) || defined(_M_ARM64) +#define FASTFLOAT_NEON 1 +#endif + +#if defined(FASTFLOAT_SSE2) || defined(FASTFLOAT_NEON) +#define FASTFLOAT_HAS_SIMD 1 +#endif + +#if defined(__GNUC__) +// disable -Wcast-align=strict (GCC only) +#define FASTFLOAT_SIMD_DISABLE_WARNINGS \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wcast-align\"") +#else +#define FASTFLOAT_SIMD_DISABLE_WARNINGS +#endif + +#if defined(__GNUC__) +#define FASTFLOAT_SIMD_RESTORE_WARNINGS _Pragma("GCC diagnostic pop") +#else +#define FASTFLOAT_SIMD_RESTORE_WARNINGS +#endif + +#ifdef FASTFLOAT_VISUAL_STUDIO +#define fastfloat_really_inline __forceinline +#else +#define fastfloat_really_inline inline __attribute__((always_inline)) +#endif + +#ifndef FASTFLOAT_ASSERT +#define FASTFLOAT_ASSERT(x) \ + { ((void)(x)); } +#endif + +#ifndef FASTFLOAT_DEBUG_ASSERT +#define FASTFLOAT_DEBUG_ASSERT(x) \ + { ((void)(x)); } +#endif + +// rust style `try!()` macro, or `?` operator +#define FASTFLOAT_TRY(x) \ + { \ + if (!(x)) \ + return false; \ + } + +#define FASTFLOAT_ENABLE_IF(...) \ + typename std::enable_if<(__VA_ARGS__), int>::type + +namespace fast_float { + +fastfloat_really_inline constexpr bool cpp20_and_in_constexpr() { +#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED + return std::is_constant_evaluated(); +#else + return false; +#endif +} + +template +struct is_supported_float_type + : std::integral_constant< + bool, std::is_same::value || std::is_same::value +#ifdef __STDCPP_FLOAT64_T__ + || std::is_same::value +#endif +#ifdef __STDCPP_FLOAT32_T__ + || std::is_same::value +#endif +#ifdef __STDCPP_FLOAT16_T__ + || std::is_same::value +#endif +#ifdef __STDCPP_BFLOAT16_T__ + || std::is_same::value +#endif + > { +}; + +template +using equiv_uint_t = typename std::conditional< + sizeof(T) == 1, uint8_t, + typename std::conditional< + sizeof(T) == 2, uint16_t, + typename std::conditional::type>::type>::type; + +template struct is_supported_integer_type : std::is_integral {}; + +template +struct is_supported_char_type + : std::integral_constant::value || + std::is_same::value || + std::is_same::value || + std::is_same::value +#ifdef __cpp_char8_t + || std::is_same::value +#endif + > { +}; + +// Compares two ASCII strings in a case insensitive manner. +template +inline FASTFLOAT_CONSTEXPR14 bool +fastfloat_strncasecmp(UC const *actual_mixedcase, UC const *expected_lowercase, + size_t length) { + for (size_t i = 0; i < length; ++i) { + UC const actual = actual_mixedcase[i]; + if ((actual < 256 ? actual | 32 : actual) != expected_lowercase[i]) { + return false; + } + } + return true; +} + +#ifndef FLT_EVAL_METHOD +#error "FLT_EVAL_METHOD should be defined, please include cfloat." +#endif + +// a pointer and a length to a contiguous block of memory +template struct span { + T const *ptr; + size_t length; + + constexpr span(T const *_ptr, size_t _length) : ptr(_ptr), length(_length) {} + + constexpr span() : ptr(nullptr), length(0) {} + + constexpr size_t len() const noexcept { return length; } + + FASTFLOAT_CONSTEXPR14 const T &operator[](size_t index) const noexcept { + FASTFLOAT_DEBUG_ASSERT(index < length); + return ptr[index]; + } +}; + +struct value128 { + uint64_t low; + uint64_t high; + + constexpr value128(uint64_t _low, uint64_t _high) : low(_low), high(_high) {} + + constexpr value128() : low(0), high(0) {} +}; + +/* Helper C++14 constexpr generic implementation of leading_zeroes */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 int +leading_zeroes_generic(uint64_t input_num, int last_bit = 0) { + if (input_num & uint64_t(0xffffffff00000000)) { + input_num >>= 32; + last_bit |= 32; + } + if (input_num & uint64_t(0xffff0000)) { + input_num >>= 16; + last_bit |= 16; + } + if (input_num & uint64_t(0xff00)) { + input_num >>= 8; + last_bit |= 8; + } + if (input_num & uint64_t(0xf0)) { + input_num >>= 4; + last_bit |= 4; + } + if (input_num & uint64_t(0xc)) { + input_num >>= 2; + last_bit |= 2; + } + if (input_num & uint64_t(0x2)) { /* input_num >>= 1; */ + last_bit |= 1; + } + return 63 - last_bit; +} + +/* result might be undefined when input_num is zero */ +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 int +leading_zeroes(uint64_t input_num) { + assert(input_num > 0); + if (cpp20_and_in_constexpr()) { + return leading_zeroes_generic(input_num); + } +#ifdef FASTFLOAT_VISUAL_STUDIO +#if defined(_M_X64) || defined(_M_ARM64) + unsigned long leading_zero = 0; + // Search the mask data from most significant bit (MSB) + // to least significant bit (LSB) for a set bit (1). + _BitScanReverse64(&leading_zero, input_num); + return (int)(63 - leading_zero); +#else + return leading_zeroes_generic(input_num); +#endif +#else + return __builtin_clzll(input_num); +#endif +} + +// slow emulation routine for 32-bit +fastfloat_really_inline constexpr uint64_t emulu(uint32_t x, uint32_t y) { + return x * (uint64_t)y; +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t +umul128_generic(uint64_t ab, uint64_t cd, uint64_t *hi) { + uint64_t ad = emulu((uint32_t)(ab >> 32), (uint32_t)cd); + uint64_t bd = emulu((uint32_t)ab, (uint32_t)cd); + uint64_t adbc = ad + emulu((uint32_t)ab, (uint32_t)(cd >> 32)); + uint64_t adbc_carry = (uint64_t)(adbc < ad); + uint64_t lo = bd + (adbc << 32); + *hi = emulu((uint32_t)(ab >> 32), (uint32_t)(cd >> 32)) + (adbc >> 32) + + (adbc_carry << 32) + (uint64_t)(lo < bd); + return lo; +} + +#ifdef FASTFLOAT_32BIT + +// slow emulation routine for 32-bit +#if !defined(__MINGW64__) +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 uint64_t _umul128(uint64_t ab, + uint64_t cd, + uint64_t *hi) { + return umul128_generic(ab, cd, hi); +} +#endif // !__MINGW64__ + +#endif // FASTFLOAT_32BIT + +// compute 64-bit a*b +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 value128 +full_multiplication(uint64_t a, uint64_t b) { + if (cpp20_and_in_constexpr()) { + value128 answer; + answer.low = umul128_generic(a, b, &answer.high); + return answer; + } + value128 answer; +#if defined(_M_ARM64) && !defined(__MINGW32__) + // ARM64 has native support for 64-bit multiplications, no need to emulate + // But MinGW on ARM64 doesn't have native support for 64-bit multiplications + answer.high = __umulh(a, b); + answer.low = a * b; +#elif defined(FASTFLOAT_32BIT) || \ + (defined(_WIN64) && !defined(__clang__) && !defined(_M_ARM64)) + answer.low = _umul128(a, b, &answer.high); // _umul128 not available on ARM64 +#elif defined(FASTFLOAT_64BIT) && defined(__SIZEOF_INT128__) + __uint128_t r = ((__uint128_t)a) * b; + answer.low = uint64_t(r); + answer.high = uint64_t(r >> 64); +#else + answer.low = umul128_generic(a, b, &answer.high); +#endif + return answer; +} + +struct adjusted_mantissa { + uint64_t mantissa{0}; + int32_t power2{0}; // a negative value indicates an invalid result + adjusted_mantissa() = default; + + constexpr bool operator==(adjusted_mantissa const &o) const { + return mantissa == o.mantissa && power2 == o.power2; + } + + constexpr bool operator!=(adjusted_mantissa const &o) const { + return mantissa != o.mantissa || power2 != o.power2; + } +}; + +// Bias so we can get the real exponent with an invalid adjusted_mantissa. +constexpr static int32_t invalid_am_bias = -0x8000; + +// used for binary_format_lookup_tables::max_mantissa +constexpr uint64_t constant_55555 = 5 * 5 * 5 * 5 * 5; + +template struct binary_format_lookup_tables; + +template struct binary_format : binary_format_lookup_tables { + using equiv_uint = equiv_uint_t; + + static constexpr int mantissa_explicit_bits(); + static constexpr int minimum_exponent(); + static constexpr int infinite_power(); + static constexpr int sign_index(); + static constexpr int + min_exponent_fast_path(); // used when fegetround() == FE_TONEAREST + static constexpr int max_exponent_fast_path(); + static constexpr int max_exponent_round_to_even(); + static constexpr int min_exponent_round_to_even(); + static constexpr uint64_t max_mantissa_fast_path(int64_t power); + static constexpr uint64_t + max_mantissa_fast_path(); // used when fegetround() == FE_TONEAREST + static constexpr int largest_power_of_ten(); + static constexpr int smallest_power_of_ten(); + static constexpr T exact_power_of_ten(int64_t power); + static constexpr size_t max_digits(); + static constexpr equiv_uint exponent_mask(); + static constexpr equiv_uint mantissa_mask(); + static constexpr equiv_uint hidden_bit_mask(); +}; + +template struct binary_format_lookup_tables { + static constexpr double powers_of_ten[] = { + 1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10, 1e11, + 1e12, 1e13, 1e14, 1e15, 1e16, 1e17, 1e18, 1e19, 1e20, 1e21, 1e22}; + + // Largest integer value v so that (5**index * v) <= 1<<53. + // 0x20000000000000 == 1 << 53 + static constexpr uint64_t max_mantissa[] = { + 0x20000000000000, + 0x20000000000000 / 5, + 0x20000000000000 / (5 * 5), + 0x20000000000000 / (5 * 5 * 5), + 0x20000000000000 / (5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555), + 0x20000000000000 / (constant_55555 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * 5 * 5 * 5 * 5), + 0x20000000000000 / + (constant_55555 * constant_55555 * constant_55555 * constant_55555), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5), + 0x20000000000000 / (constant_55555 * constant_55555 * constant_55555 * + constant_55555 * 5 * 5 * 5 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr double binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template struct binary_format_lookup_tables { + static constexpr float powers_of_ten[] = {1e0f, 1e1f, 1e2f, 1e3f, 1e4f, 1e5f, + 1e6f, 1e7f, 1e8f, 1e9f, 1e10f}; + + // Largest integer value v so that (5**index * v) <= 1<<24. + // 0x1000000 == 1<<24 + static constexpr uint64_t max_mantissa[] = { + 0x1000000, + 0x1000000 / 5, + 0x1000000 / (5 * 5), + 0x1000000 / (5 * 5 * 5), + 0x1000000 / (5 * 5 * 5 * 5), + 0x1000000 / (constant_55555), + 0x1000000 / (constant_55555 * 5), + 0x1000000 / (constant_55555 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * 5 * 5 * 5 * 5), + 0x1000000 / (constant_55555 * constant_55555), + 0x1000000 / (constant_55555 * constant_55555 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr float binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t binary_format_lookup_tables::max_mantissa[]; + +#endif + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -22; +#endif +} + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return 0; +#else + return -10; +#endif +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 52; +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 23; +} + +template <> +inline constexpr int binary_format::max_exponent_round_to_even() { + return 10; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -4; +} + +template <> +inline constexpr int binary_format::min_exponent_round_to_even() { + return -17; +} + +template <> inline constexpr int binary_format::minimum_exponent() { + return -1023; +} + +template <> inline constexpr int binary_format::minimum_exponent() { + return -127; +} + +template <> inline constexpr int binary_format::infinite_power() { + return 0x7FF; +} + +template <> inline constexpr int binary_format::infinite_power() { + return 0xFF; +} + +template <> inline constexpr int binary_format::sign_index() { + return 63; +} + +template <> inline constexpr int binary_format::sign_index() { + return 31; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 22; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 10; +} + +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +template <> +inline constexpr uint64_t binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +// credit: Jakub Jelínek +#ifdef __STDCPP_FLOAT16_T__ +template struct binary_format_lookup_tables { + static constexpr std::float16_t powers_of_ten[] = {1e0f16, 1e1f16, 1e2f16, + 1e3f16, 1e4f16}; + + // Largest integer value v so that (5**index * v) <= 1<<11. + // 0x800 == 1<<11 + static constexpr uint64_t max_mantissa[] = {0x800, + 0x800 / 5, + 0x800 / (5 * 5), + 0x800 / (5 * 5 * 5), + 0x800 / (5 * 5 * 5 * 5), + 0x800 / (constant_55555)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr std::float16_t + binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t + binary_format_lookup_tables::max_mantissa[]; + +#endif + +template <> +inline constexpr std::float16_t +binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7C00; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x03FF; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x0400; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 4; +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 10; +} + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 4 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { + return 0; +} + +template <> +inline constexpr int +binary_format::max_exponent_round_to_even() { + return 5; +} + +template <> +inline constexpr int +binary_format::min_exponent_round_to_even() { + return -22; +} + +template <> +inline constexpr int binary_format::minimum_exponent() { + return -15; +} + +template <> +inline constexpr int binary_format::infinite_power() { + return 0x1F; +} + +template <> inline constexpr int binary_format::sign_index() { + return 15; +} + +template <> +inline constexpr int binary_format::largest_power_of_ten() { + return 4; +} + +template <> +inline constexpr int binary_format::smallest_power_of_ten() { + return -27; +} + +template <> +inline constexpr size_t binary_format::max_digits() { + return 22; +} +#endif // __STDCPP_FLOAT16_T__ + +// credit: Jakub Jelínek +#ifdef __STDCPP_BFLOAT16_T__ +template struct binary_format_lookup_tables { + static constexpr std::bfloat16_t powers_of_ten[] = {1e0bf16, 1e1bf16, 1e2bf16, + 1e3bf16}; + + // Largest integer value v so that (5**index * v) <= 1<<8. + // 0x100 == 1<<8 + static constexpr uint64_t max_mantissa[] = {0x100, 0x100 / 5, 0x100 / (5 * 5), + 0x100 / (5 * 5 * 5), + 0x100 / (5 * 5 * 5 * 5)}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template +constexpr std::bfloat16_t + binary_format_lookup_tables::powers_of_ten[]; + +template +constexpr uint64_t + binary_format_lookup_tables::max_mantissa[]; + +#endif + +template <> +inline constexpr std::bfloat16_t +binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> +inline constexpr int binary_format::max_exponent_fast_path() { + return 3; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7F80; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x007F; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x0080; +} + +template <> +inline constexpr int binary_format::mantissa_explicit_bits() { + return 7; +} + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path() { + return uint64_t(2) << mantissa_explicit_bits(); +} + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 3 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr int binary_format::min_exponent_fast_path() { + return 0; +} + +template <> +inline constexpr int +binary_format::max_exponent_round_to_even() { + return 3; +} + +template <> +inline constexpr int +binary_format::min_exponent_round_to_even() { + return -24; +} + +template <> +inline constexpr int binary_format::minimum_exponent() { + return -127; +} + +template <> +inline constexpr int binary_format::infinite_power() { + return 0xFF; +} + +template <> inline constexpr int binary_format::sign_index() { + return 15; +} + +template <> +inline constexpr int binary_format::largest_power_of_ten() { + return 38; +} + +template <> +inline constexpr int binary_format::smallest_power_of_ten() { + return -60; +} + +template <> +inline constexpr size_t binary_format::max_digits() { + return 98; +} +#endif // __STDCPP_BFLOAT16_T__ + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 22 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr uint64_t +binary_format::max_mantissa_fast_path(int64_t power) { + // caller is responsible to ensure that + // power >= 0 && power <= 10 + // + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)max_mantissa[0], max_mantissa[power]; +} + +template <> +inline constexpr double +binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> +inline constexpr float binary_format::exact_power_of_ten(int64_t power) { + // Work around clang bug https://godbolt.org/z/zedh7rrhc + return (void)powers_of_ten[0], powers_of_ten[power]; +} + +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 308; +} + +template <> inline constexpr int binary_format::largest_power_of_ten() { + return 38; +} + +template <> +inline constexpr int binary_format::smallest_power_of_ten() { + return -342; +} + +template <> inline constexpr int binary_format::smallest_power_of_ten() { + return -64; +} + +template <> inline constexpr size_t binary_format::max_digits() { + return 769; +} + +template <> inline constexpr size_t binary_format::max_digits() { + return 114; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7F800000; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::exponent_mask() { + return 0x7FF0000000000000; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x007FFFFF; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::mantissa_mask() { + return 0x000FFFFFFFFFFFFF; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x00800000; +} + +template <> +inline constexpr binary_format::equiv_uint +binary_format::hidden_bit_mask() { + return 0x0010000000000000; +} + +template +fastfloat_really_inline FASTFLOAT_CONSTEXPR20 void +to_float(bool negative, adjusted_mantissa am, T &value) { + using equiv_uint = equiv_uint_t; + equiv_uint word = equiv_uint(am.mantissa); + word = equiv_uint(word | equiv_uint(am.power2) + << binary_format::mantissa_explicit_bits()); + word = + equiv_uint(word | equiv_uint(negative) << binary_format::sign_index()); +#if FASTFLOAT_HAS_BIT_CAST + value = std::bit_cast(word); +#else + ::memcpy(&value, &word, sizeof(T)); +#endif +} + +template struct space_lut { + static constexpr bool value[] = { + 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr bool space_lut::value[]; + +#endif + +template constexpr bool is_space(UC c) { + return c < 256 && space_lut<>::value[uint8_t(c)]; +} + +template static constexpr uint64_t int_cmp_zeros() { + static_assert((sizeof(UC) == 1) || (sizeof(UC) == 2) || (sizeof(UC) == 4), + "Unsupported character size"); + return (sizeof(UC) == 1) ? 0x3030303030303030 + : (sizeof(UC) == 2) + ? (uint64_t(UC('0')) << 48 | uint64_t(UC('0')) << 32 | + uint64_t(UC('0')) << 16 | UC('0')) + : (uint64_t(UC('0')) << 32 | UC('0')); +} + +template static constexpr int int_cmp_len() { + return sizeof(uint64_t) / sizeof(UC); +} + +template constexpr UC const *str_const_nan(); + +template <> constexpr char const *str_const_nan() { return "nan"; } + +template <> constexpr wchar_t const *str_const_nan() { return L"nan"; } + +template <> constexpr char16_t const *str_const_nan() { + return u"nan"; +} + +template <> constexpr char32_t const *str_const_nan() { + return U"nan"; +} + +#ifdef __cpp_char8_t +template <> constexpr char8_t const *str_const_nan() { + return u8"nan"; +} +#endif + +template constexpr UC const *str_const_inf(); + +template <> constexpr char const *str_const_inf() { return "infinity"; } + +template <> constexpr wchar_t const *str_const_inf() { + return L"infinity"; +} + +template <> constexpr char16_t const *str_const_inf() { + return u"infinity"; +} + +template <> constexpr char32_t const *str_const_inf() { + return U"infinity"; +} + +#ifdef __cpp_char8_t +template <> constexpr char8_t const *str_const_inf() { + return u8"infinity"; +} +#endif + +template struct int_luts { + static constexpr uint8_t chdigit[] = { + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 255, 255, + 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, + 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, + 35, 255, 255, 255, 255, 255, 255, 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, + 33, 34, 35, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, + 255}; + + static constexpr size_t maxdigits_u64[] = { + 64, 41, 32, 28, 25, 23, 22, 21, 20, 19, 18, 18, 17, 17, 16, 16, 16, 16, + 15, 15, 15, 15, 14, 14, 14, 14, 14, 14, 14, 13, 13, 13, 13, 13, 13}; + + static constexpr uint64_t min_safe_u64[] = { + 9223372036854775808ull, 12157665459056928801ull, 4611686018427387904, + 7450580596923828125, 4738381338321616896, 3909821048582988049, + 9223372036854775808ull, 12157665459056928801ull, 10000000000000000000ull, + 5559917313492231481, 2218611106740436992, 8650415919381337933, + 2177953337809371136, 6568408355712890625, 1152921504606846976, + 2862423051509815793, 6746640616477458432, 15181127029874798299ull, + 1638400000000000000, 3243919932521508681, 6221821273427820544, + 11592836324538749809ull, 876488338465357824, 1490116119384765625, + 2481152873203736576, 4052555153018976267, 6502111422497947648, + 10260628712958602189ull, 15943230000000000000ull, 787662783788549761, + 1152921504606846976, 1667889514952984961, 2386420683693101056, + 3379220508056640625, 4738381338321616896}; +}; + +#if FASTFLOAT_DETAIL_MUST_DEFINE_CONSTEXPR_VARIABLE + +template constexpr uint8_t int_luts::chdigit[]; + +template constexpr size_t int_luts::maxdigits_u64[]; + +template constexpr uint64_t int_luts::min_safe_u64[]; + +#endif + +template +fastfloat_really_inline constexpr uint8_t ch_to_digit(UC c) { + return int_luts<>::chdigit[static_cast(c)]; +} + +fastfloat_really_inline constexpr size_t max_digits_u64(int base) { + return int_luts<>::maxdigits_u64[base - 2]; +} + +// If a u64 is exactly max_digits_u64() in length, this is +// the value below which it has definitely overflowed. +fastfloat_really_inline constexpr uint64_t min_safe_u64(int base) { + return int_luts<>::min_safe_u64[base - 2]; +} + +static_assert(std::is_same, uint64_t>::value, + "equiv_uint should be uint64_t for double"); +static_assert(std::numeric_limits::is_iec559, + "double must fulfill the requirements of IEC 559 (IEEE 754)"); + +static_assert(std::is_same, uint32_t>::value, + "equiv_uint should be uint32_t for float"); +static_assert(std::numeric_limits::is_iec559, + "float must fulfill the requirements of IEC 559 (IEEE 754)"); + +#ifdef __STDCPP_FLOAT64_T__ +static_assert(std::is_same, uint64_t>::value, + "equiv_uint should be uint64_t for std::float64_t"); +static_assert( + std::numeric_limits::is_iec559, + "std::float64_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT64_T__ + +#ifdef __STDCPP_FLOAT32_T__ +static_assert(std::is_same, uint32_t>::value, + "equiv_uint should be uint32_t for std::float32_t"); +static_assert( + std::numeric_limits::is_iec559, + "std::float32_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT32_T__ + +#ifdef __STDCPP_FLOAT16_T__ +static_assert( + std::is_same::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::float16_t"); +static_assert( + std::numeric_limits::is_iec559, + "std::float16_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_FLOAT16_T__ + +#ifdef __STDCPP_BFLOAT16_T__ +static_assert( + std::is_same::equiv_uint, uint16_t>::value, + "equiv_uint should be uint16_t for std::bfloat16_t"); +static_assert( + std::numeric_limits::is_iec559, + "std::bfloat16_t must fulfill the requirements of IEC 559 (IEEE 754)"); +#endif // __STDCPP_BFLOAT16_T__ + +constexpr chars_format operator~(chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(~static_cast(rhs)); +} + +constexpr chars_format operator&(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) & + static_cast(rhs)); +} + +constexpr chars_format operator|(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) | + static_cast(rhs)); +} + +constexpr chars_format operator^(chars_format lhs, chars_format rhs) noexcept { + using int_type = std::underlying_type::type; + return static_cast(static_cast(lhs) ^ + static_cast(rhs)); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator&=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs & rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator|=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs | rhs); +} + +fastfloat_really_inline FASTFLOAT_CONSTEXPR14 chars_format & +operator^=(chars_format &lhs, chars_format rhs) noexcept { + return lhs = (lhs ^ rhs); +} + +namespace detail { +// adjust for deprecated feature macros +constexpr chars_format adjust_for_feature_macros(chars_format fmt) { + return fmt +#ifdef FASTFLOAT_ALLOWS_LEADING_PLUS + | chars_format::allow_leading_plus +#endif +#ifdef FASTFLOAT_SKIP_WHITE_SPACE + | chars_format::skip_white_space +#endif + ; +} +} // namespace detail + +} // namespace fast_float + +#endif diff --git a/3rdparty/fast_float/parse_number.h b/3rdparty/fast_float/parse_number.h new file mode 100644 index 000000000000..e74c478f5da8 --- /dev/null +++ b/3rdparty/fast_float/parse_number.h @@ -0,0 +1,401 @@ +#ifndef FASTFLOAT_PARSE_NUMBER_H +#define FASTFLOAT_PARSE_NUMBER_H + +#include "ascii_number.h" +#include "decimal_to_binary.h" +#include "digit_comparison.h" +#include "float_common.h" + +#include +#include +#include +#include + +namespace fast_float { + +namespace detail { +/** + * Special case +inf, -inf, nan, infinity, -infinity. + * The case comparisons could be made much faster given that we know that the + * strings a null-free and fixed. + **/ +template +from_chars_result_t + FASTFLOAT_CONSTEXPR14 parse_infnan(UC const *first, UC const *last, + T &value, chars_format fmt) noexcept { + from_chars_result_t answer{}; + answer.ptr = first; + answer.ec = std::errc(); // be optimistic + // assume first < last, so dereference without checks; + bool const minusSign = (*first == UC('-')); + // C++17 20.19.3.(7.1) explicitly forbids '+' sign here + if ((*first == UC('-')) || + (uint64_t(fmt & chars_format::allow_leading_plus) && + (*first == UC('+')))) { + ++first; + } + if (last - first >= 3) { + if (fastfloat_strncasecmp(first, str_const_nan(), 3)) { + answer.ptr = (first += 3); + value = minusSign ? -std::numeric_limits::quiet_NaN() + : std::numeric_limits::quiet_NaN(); + // Check for possible nan(n-char-seq-opt), C++17 20.19.3.7, + // C11 7.20.1.3.3. At least MSVC produces nan(ind) and nan(snan). + if (first != last && *first == UC('(')) { + for (UC const *ptr = first + 1; ptr != last; ++ptr) { + if (*ptr == UC(')')) { + answer.ptr = ptr + 1; // valid nan(n-char-seq-opt) + break; + } else if (!((UC('a') <= *ptr && *ptr <= UC('z')) || + (UC('A') <= *ptr && *ptr <= UC('Z')) || + (UC('0') <= *ptr && *ptr <= UC('9')) || *ptr == UC('_'))) + break; // forbidden char, not nan(n-char-seq-opt) + } + } + return answer; + } + if (fastfloat_strncasecmp(first, str_const_inf(), 3)) { + if ((last - first >= 8) && + fastfloat_strncasecmp(first + 3, str_const_inf() + 3, 5)) { + answer.ptr = first + 8; + } else { + answer.ptr = first + 3; + } + value = minusSign ? -std::numeric_limits::infinity() + : std::numeric_limits::infinity(); + return answer; + } + } + answer.ec = std::errc::invalid_argument; + return answer; +} + +/** + * Returns true if the floating-pointing rounding mode is to 'nearest'. + * It is the default on most system. This function is meant to be inexpensive. + * Credit : @mwalcott3 + */ +fastfloat_really_inline bool rounds_to_nearest() noexcept { + // https://lemire.me/blog/2020/06/26/gcc-not-nearest/ +#if (FLT_EVAL_METHOD != 1) && (FLT_EVAL_METHOD != 0) + return false; +#endif + // See + // A fast function to check your floating-point rounding mode + // https://lemire.me/blog/2022/11/16/a-fast-function-to-check-your-floating-point-rounding-mode/ + // + // This function is meant to be equivalent to : + // prior: #include + // return fegetround() == FE_TONEAREST; + // However, it is expected to be much faster than the fegetround() + // function call. + // + // The volatile keyword prevents the compiler from computing the function + // at compile-time. + // There might be other ways to prevent compile-time optimizations (e.g., + // asm). The value does not need to be std::numeric_limits::min(), any + // small value so that 1 + x should round to 1 would do (after accounting for + // excess precision, as in 387 instructions). + static float volatile fmin = std::numeric_limits::min(); + float fmini = fmin; // we copy it so that it gets loaded at most once. +// +// Explanation: +// Only when fegetround() == FE_TONEAREST do we have that +// fmin + 1.0f == 1.0f - fmin. +// +// FE_UPWARD: +// fmin + 1.0f > 1 +// 1.0f - fmin == 1 +// +// FE_DOWNWARD or FE_TOWARDZERO: +// fmin + 1.0f == 1 +// 1.0f - fmin < 1 +// +// Note: This may fail to be accurate if fast-math has been +// enabled, as rounding conventions may not apply. +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(push) +// todo: is there a VS warning? +// see +// https://stackoverflow.com/questions/46079446/is-there-a-warning-for-floating-point-equality-checking-in-visual-studio-2013 +#elif defined(__clang__) +#pragma clang diagnostic push +#pragma clang diagnostic ignored "-Wfloat-equal" +#elif defined(__GNUC__) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wfloat-equal" +#endif + return (fmini + 1.0f == 1.0f - fmini); +#ifdef FASTFLOAT_VISUAL_STUDIO +#pragma warning(pop) +#elif defined(__clang__) +#pragma clang diagnostic pop +#elif defined(__GNUC__) +#pragma GCC diagnostic pop +#endif +} + +} // namespace detail + +template struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced(first, last, value, options); + } +}; + +#ifdef __STDCPP_FLOAT32_T__ +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float32_t &value, + parse_options_t options) noexcept { + // if std::float32_t is defined, and we are in C++23 mode; macro set for + // float32; set value to float due to equivalence between float and + // float32_t + float val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +#ifdef __STDCPP_FLOAT64_T__ +template <> struct from_chars_caller { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, std::float64_t &value, + parse_options_t options) noexcept { + // if std::float64_t is defined, and we are in C++23 mode; macro set for + // float64; set value as double due to equivalence between double and + // float64_t + double val; + auto ret = from_chars_advanced(first, last, val, options); + value = val; + return ret; + } +}; +#endif + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, + chars_format fmt /*= chars_format::general*/) noexcept { + return from_chars_caller::call(first, last, value, + parse_options_t(fmt)); +} + +/** + * This function overload takes parsed_number_string_t structure that is created + * and populated either by from_chars_advanced function taking chars range and + * parsing options or other parsing custom function implemented by user. + */ +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(parsed_number_string_t &pns, T &value) noexcept { + + static_assert(is_supported_float_type::value, + "only some floating-point types are supported"); + static_assert(is_supported_char_type::value, + "only char, wchar_t, char16_t and char32_t are supported"); + + from_chars_result_t answer; + + answer.ec = std::errc(); // be optimistic + answer.ptr = pns.lastmatch; + // The implementation of the Clinger's fast path is convoluted because + // we want round-to-nearest in all cases, irrespective of the rounding mode + // selected on the thread. + // We proceed optimistically, assuming that detail::rounds_to_nearest() + // returns true. + if (binary_format::min_exponent_fast_path() <= pns.exponent && + pns.exponent <= binary_format::max_exponent_fast_path() && + !pns.too_many_digits) { + // Unfortunately, the conventional Clinger's fast path is only possible + // when the system rounds to the nearest float. + // + // We expect the next branch to almost always be selected. + // We could check it first (before the previous branch), but + // there might be performance advantages at having the check + // be last. + if (!cpp20_and_in_constexpr() && detail::rounds_to_nearest()) { + // We have that fegetround() == FE_TONEAREST. + // Next is Clinger's fast path. + if (pns.mantissa <= binary_format::max_mantissa_fast_path()) { + value = T(pns.mantissa); + if (pns.exponent < 0) { + value = value / binary_format::exact_power_of_ten(-pns.exponent); + } else { + value = value * binary_format::exact_power_of_ten(pns.exponent); + } + if (pns.negative) { + value = -value; + } + return answer; + } + } else { + // We do not have that fegetround() == FE_TONEAREST. + // Next is a modified Clinger's fast path, inspired by Jakub Jelínek's + // proposal + if (pns.exponent >= 0 && + pns.mantissa <= + binary_format::max_mantissa_fast_path(pns.exponent)) { +#if defined(__clang__) || defined(FASTFLOAT_32BIT) + // Clang may map 0 to -0.0 when fegetround() == FE_DOWNWARD + if (pns.mantissa == 0) { + value = pns.negative ? T(-0.) : T(0.); + return answer; + } +#endif + value = T(pns.mantissa) * + binary_format::exact_power_of_ten(pns.exponent); + if (pns.negative) { + value = -value; + } + return answer; + } + } + } + adjusted_mantissa am = + compute_float>(pns.exponent, pns.mantissa); + if (pns.too_many_digits && am.power2 >= 0) { + if (am != compute_float>(pns.exponent, pns.mantissa + 1)) { + am = compute_error>(pns.exponent, pns.mantissa); + } + } + // If we called compute_float>(pns.exponent, pns.mantissa) + // and we have an invalid power (am.power2 < 0), then we need to go the long + // way around again. This is very uncommon. + if (am.power2 < 0) { + am = digit_comp(pns, am); + } + to_float(pns.negative, am, value); + // Test for over/underflow. + if ((pns.mantissa != 0 && am.mantissa == 0 && am.power2 == 0) || + am.power2 == binary_format::infinite_power()) { + answer.ec = std::errc::result_out_of_range; + } + return answer; +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_float_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(is_supported_float_type::value, + "only some floating-point types are supported"); + static_assert(is_supported_char_type::value, + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + parsed_number_string_t pns = + uint64_t(fmt & detail::basic_json_fmt) + ? parse_number_string(first, last, options) + : parse_number_string(first, last, options); + if (!pns.valid) { + if (uint64_t(fmt & chars_format::no_infnan)) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } else { + return detail::parse_infnan(first, last, value, fmt); + } + } + + // call overload that takes parsed_number_string_t directly. + return from_chars_advanced(pns, value); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars(UC const *first, UC const *last, T &value, int base) noexcept { + + static_assert(is_supported_integer_type::value, + "only integer types are supported"); + static_assert(is_supported_char_type::value, + "only char, wchar_t, char16_t and char32_t are supported"); + + parse_options_t options; + options.base = base; + return from_chars_advanced(first, last, value, options); +} + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_int_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + + static_assert(is_supported_integer_type::value, + "only integer types are supported"); + static_assert(is_supported_char_type::value, + "only char, wchar_t, char16_t and char32_t are supported"); + + chars_format const fmt = detail::adjust_for_feature_macros(options.format); + int const base = options.base; + + from_chars_result_t answer; + if (uint64_t(fmt & chars_format::skip_white_space)) { + while ((first != last) && fast_float::is_space(*first)) { + first++; + } + } + if (first == last || base < 2 || base > 36) { + answer.ec = std::errc::invalid_argument; + answer.ptr = first; + return answer; + } + + return parse_int_string(first, last, value, options); +} + +template struct from_chars_advanced_caller { + static_assert(TypeIx > 0, "unsupported type"); +}; + +template <> struct from_chars_advanced_caller<1> { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_float_advanced(first, last, value, options); + } +}; + +template <> struct from_chars_advanced_caller<2> { + template + FASTFLOAT_CONSTEXPR20 static from_chars_result_t + call(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_int_advanced(first, last, value, options); + } +}; + +template +FASTFLOAT_CONSTEXPR20 from_chars_result_t +from_chars_advanced(UC const *first, UC const *last, T &value, + parse_options_t options) noexcept { + return from_chars_advanced_caller< + size_t(is_supported_float_type::value) + + 2 * size_t(is_supported_integer_type::value)>::call(first, last, value, + options); +} + +} // namespace fast_float + +#endif diff --git a/3rdparty/lua/plainlua/CMakeLists.txt b/3rdparty/lua/plainlua/CMakeLists.txt index f24c197e6595..18e4ea76550f 100644 --- a/3rdparty/lua/plainlua/CMakeLists.txt +++ b/3rdparty/lua/plainlua/CMakeLists.txt @@ -1,6 +1,6 @@ cmake_minimum_required(VERSION 3.22) -set(_LUA_VERSION "5.4.8") +set (_LUA_VERSION "5.5.0") set(lib_name plainlua) set(LUA_SRC_PATH ${CMAKE_CURRENT_LIST_DIR}) diff --git a/3rdparty/lua/plainlua/lapi.c b/3rdparty/lua/plainlua/lapi.c index 04e09cff7e0d..769eba13b6df 100644 --- a/3rdparty/lua/plainlua/lapi.c +++ b/3rdparty/lua/plainlua/lapi.c @@ -40,10 +40,8 @@ const char lua_ident[] = /* ** Test for a valid index (one that is not the 'nilvalue'). -** '!ttisnil(o)' implies 'o != &G(L)->nilvalue', so it is not needed. -** However, it covers the most common cases in a faster way. */ -#define isvalid(L, o) (!ttisnil(o) || o != &G(L)->nilvalue) +#define isvalid(L, o) ((o) != &G(L)->nilvalue) /* test for pseudo index */ @@ -92,7 +90,7 @@ static TValue *index2value (lua_State *L, int idx) { /* ** Convert a valid actual index (not a pseudo-index) to its address. */ -l_sinline StkId index2stack (lua_State *L, int idx) { +static StkId index2stack (lua_State *L, int idx) { CallInfo *ci = L->ci; if (idx > 0) { StkId o = ci->func.p + idx; @@ -129,7 +127,7 @@ LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { int i; if (from == to) return; lua_lock(to); - api_checknelems(from, n); + api_checkpop(from, n); api_check(from, G(from) == G(to), "moving among independent states"); api_check(from, to->ci->top.p - to->top.p >= n, "stack overflow"); from->top.p -= n; @@ -195,10 +193,9 @@ LUA_API void lua_settop (lua_State *L, int idx) { api_check(L, -(idx+1) <= (L->top.p - (func + 1)), "invalid new top"); diff = idx + 1; /* will "subtract" index (as it is negative) */ } - api_check(L, L->tbclist.p < L->top.p, "previous pop of an unclosed slot"); newtop = L->top.p + diff; if (diff < 0 && L->tbclist.p >= newtop) { - lua_assert(hastocloseCfunc(ci->nresults)); + lua_assert(ci->callstatus & CIST_TBC); newtop = luaF_close(L, newtop, CLOSEKTOP, 0); } L->top.p = newtop; /* correct top only after closing any upvalue */ @@ -210,7 +207,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { StkId level; lua_lock(L); level = index2stack(L, idx); - api_check(L, hastocloseCfunc(L->ci->nresults) && L->tbclist.p == level, + api_check(L, (L->ci->callstatus & CIST_TBC) && (L->tbclist.p == level), "no variable to close at given level"); level = luaF_close(L, level, CLOSEKTOP, 0); setnilvalue(s2v(level)); @@ -224,7 +221,7 @@ LUA_API void lua_closeslot (lua_State *L, int idx) { ** Note that we move(copy) only the value inside the stack. ** (We do not move additional fields that may exist.) */ -l_sinline void reverse (lua_State *L, StkId from, StkId to) { +static void reverse (lua_State *L, StkId from, StkId to) { for (; from < to; from++, to--) { TValue temp; setobj(L, &temp, s2v(from)); @@ -243,6 +240,7 @@ LUA_API void lua_rotate (lua_State *L, int idx, int n) { lua_lock(L); t = L->top.p - 1; /* end of stack segment being rotated */ p = index2stack(L, idx); /* start of segment */ + api_check(L, L->tbclist.p < p, "moving a to-be-closed slot"); api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ reverse(L, p, m); /* reverse the prefix with length 'n' */ @@ -335,15 +333,15 @@ LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { LUA_API void lua_arith (lua_State *L, int op) { lua_lock(L); if (op != LUA_OPUNM && op != LUA_OPBNOT) - api_checknelems(L, 2); /* all other operations expect two operands */ + api_checkpop(L, 2); /* all other operations expect two operands */ else { /* for unary operations, add fake 2nd operand */ - api_checknelems(L, 1); + api_checkpop(L, 1); setobjs2s(L, L->top.p, L->top.p - 1); api_incr_top(L); } /* first operand at top - 2, second at top - 1; result go to top - 2 */ luaO_arith(L, op, s2v(L->top.p - 2), s2v(L->top.p - 1), L->top.p - 2); - L->top.p--; /* remove second operand */ + L->top.p--; /* pop second operand */ lua_unlock(L); } @@ -368,6 +366,18 @@ LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { } +LUA_API unsigned (lua_numbertocstring) (lua_State *L, int idx, char *buff) { + const TValue *o = index2value(L, idx); + if (ttisnumber(o)) { + unsigned len = luaO_tostringbuff(o, buff); + buff[len++] = '\0'; /* add final zero */ + return len; + } + else + return 0; +} + + LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { size_t sz = luaO_str2num(s, s2v(L->top.p)); if (sz != 0) @@ -416,19 +426,20 @@ LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { luaC_checkGC(L); o = index2value(L, idx); /* previous call may reallocate the stack */ } - if (len != NULL) - *len = tsslen(tsvalue(o)); lua_unlock(L); - return getstr(tsvalue(o)); + if (len != NULL) + return getlstr(tsvalue(o), *len); + else + return getstr(tsvalue(o)); } LUA_API lua_Unsigned lua_rawlen (lua_State *L, int idx) { const TValue *o = index2value(L, idx); switch (ttypetag(o)) { - case LUA_VSHRSTR: return tsvalue(o)->shrlen; - case LUA_VLNGSTR: return tsvalue(o)->u.lnglen; - case LUA_VUSERDATA: return uvalue(o)->len; + case LUA_VSHRSTR: return cast(lua_Unsigned, tsvalue(o)->shrlen); + case LUA_VLNGSTR: return cast(lua_Unsigned, tsvalue(o)->u.lnglen); + case LUA_VUSERDATA: return cast(lua_Unsigned, uvalue(o)->len); case LUA_VTABLE: return luaH_getn(hvalue(o)); default: return 0; } @@ -535,6 +546,21 @@ LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { } +LUA_API const char *lua_pushexternalstring (lua_State *L, + const char *s, size_t len, lua_Alloc falloc, void *ud) { + TString *ts; + lua_lock(L); + api_check(L, len <= MAX_SIZE, "string too large"); + api_check(L, s[len] == '\0', "string not ending with zero"); + ts = luaS_newextlstr (L, s, len, falloc, ud); + setsvalue2s(L, L->top.p, ts); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getstr(ts); +} + + LUA_API const char *lua_pushstring (lua_State *L, const char *s) { lua_lock(L); if (s == NULL) @@ -567,9 +593,7 @@ LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { const char *ret; va_list argp; lua_lock(L); - va_start(argp, fmt); - ret = luaO_pushvfstring(L, fmt, argp); - va_end(argp); + pushvfstring(L, argp, fmt, ret); luaC_checkGC(L); lua_unlock(L); return ret; @@ -583,17 +607,18 @@ LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { api_incr_top(L); } else { + int i; CClosure *cl; - api_checknelems(L, n); + api_checkpop(L, n); api_check(L, n <= MAXUPVAL, "upvalue index too large"); cl = luaF_newCclosure(L, n); cl->f = fn; - L->top.p -= n; - while (n--) { - setobj2n(L, &cl->upvalue[n], s2v(L->top.p + n)); + for (i = 0; i < n; i++) { + setobj2n(L, &cl->upvalue[i], s2v(L->top.p - n + i)); /* does not need barrier because closure is white */ lua_assert(iswhite(cl)); } + L->top.p -= n; setclCvalue(L, s2v(L->top.p), cl); api_incr_top(L); luaC_checkGC(L); @@ -626,7 +651,7 @@ LUA_API int lua_pushthread (lua_State *L) { setthvalue(L, s2v(L->top.p), L); api_incr_top(L); lua_unlock(L); - return (G(L)->mainthread == L); + return (mainthread(G(L)) == L); } @@ -636,53 +661,54 @@ LUA_API int lua_pushthread (lua_State *L) { */ -l_sinline int auxgetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + lu_byte tag; TString *str = luaS_new(L, k); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - setobj2s(L, L->top.p, slot); + luaV_fastget(t, str, s2v(L->top.p), luaH_getstr, tag); + if (!tagisempty(tag)) api_incr_top(L); - } else { setsvalue2s(L, L->top.p, str); api_incr_top(L); - luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); + tag = luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, tag); } lua_unlock(L); - return ttype(s2v(L->top.p - 1)); + return novariant(tag); } /* -** Get the global table in the registry. Since all predefined -** indices in the registry were inserted right when the registry -** was created and never removed, they must always be in the array -** part of the registry. +** The following function assumes that the registry cannot be a weak +** table, so that en mergency collection while using the global table +** cannot collect it. */ -#define getGtable(L) \ - (&hvalue(&G(L)->l_registry)->array[LUA_RIDX_GLOBALS - 1]) +static void getGlobalTable (lua_State *L, TValue *gt) { + Table *registry = hvalue(&G(L)->l_registry); + lu_byte tag = luaH_getint(registry, LUA_RIDX_GLOBALS, gt); + (void)tag; /* avoid not-used warnings when checks are off */ + api_check(L, novariant(tag) == LUA_TTABLE, "global table must exist"); +} LUA_API int lua_getglobal (lua_State *L, const char *name) { - const TValue *G; + TValue gt; lua_lock(L); - G = getGtable(L); - return auxgetstr(L, G, name); + getGlobalTable(L, >); + return auxgetstr(L, >, name); } LUA_API int lua_gettable (lua_State *L, int idx) { - const TValue *slot; + lu_byte tag; TValue *t; lua_lock(L); + api_checkpop(L, 1); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top.p - 1), slot, luaH_get)) { - setobj2s(L, L->top.p - 1, slot); - } - else - luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, slot); + luaV_fastget(t, s2v(L->top.p - 1), s2v(L->top.p - 1), luaH_get, tag); + if (tagisempty(tag)) + tag = luaV_finishget(L, t, s2v(L->top.p - 1), L->top.p - 1, tag); lua_unlock(L); - return ttype(s2v(L->top.p - 1)); + return novariant(tag); } @@ -694,35 +720,31 @@ LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { TValue *t; - const TValue *slot; + lu_byte tag; lua_lock(L); t = index2value(L, idx); - if (luaV_fastgeti(L, t, n, slot)) { - setobj2s(L, L->top.p, slot); - } - else { - TValue aux; - setivalue(&aux, n); - luaV_finishget(L, t, &aux, L->top.p, slot); + luaV_fastgeti(t, n, s2v(L->top.p), tag); + if (tagisempty(tag)) { + TValue key; + setivalue(&key, n); + tag = luaV_finishget(L, t, &key, L->top.p, tag); } api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top.p - 1)); + return novariant(tag); } -l_sinline int finishrawget (lua_State *L, const TValue *val) { - if (isempty(val)) /* avoid copying empty items to the stack */ +static int finishrawget (lua_State *L, lu_byte tag) { + if (tagisempty(tag)) /* avoid copying empty items to the stack */ setnilvalue(s2v(L->top.p)); - else - setobj2s(L, L->top.p, val); api_incr_top(L); lua_unlock(L); - return ttype(s2v(L->top.p - 1)); + return novariant(tag); } -static Table *gettable (lua_State *L, int idx) { +l_sinline Table *gettable (lua_State *L, int idx) { TValue *t = index2value(L, idx); api_check(L, ttistable(t), "table expected"); return hvalue(t); @@ -731,21 +753,23 @@ static Table *gettable (lua_State *L, int idx) { LUA_API int lua_rawget (lua_State *L, int idx) { Table *t; - const TValue *val; + lu_byte tag; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); t = gettable(L, idx); - val = luaH_get(t, s2v(L->top.p - 1)); - L->top.p--; /* remove key */ - return finishrawget(L, val); + tag = luaH_get(t, s2v(L->top.p - 1), s2v(L->top.p - 1)); + L->top.p--; /* pop key */ + return finishrawget(L, tag); } LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { Table *t; + lu_byte tag; lua_lock(L); t = gettable(L, idx); - return finishrawget(L, luaH_getint(t, n)); + luaH_fastgeti(t, n, s2v(L->top.p), tag); + return finishrawget(L, tag); } @@ -755,7 +779,7 @@ LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { lua_lock(L); t = gettable(L, idx); setpvalue(&k, cast_voidp(p)); - return finishrawget(L, luaH_get(t, &k)); + return finishrawget(L, luaH_get(t, &k, s2v(L->top.p))); } @@ -766,7 +790,7 @@ LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { sethvalue2s(L, L->top.p, t); api_incr_top(L); if (narray > 0 || nrec > 0) - luaH_resize(L, t, narray, nrec); + luaH_resize(L, t, cast_uint(narray), cast_uint(nrec)); luaC_checkGC(L); lua_unlock(L); } @@ -827,17 +851,18 @@ LUA_API int lua_getiuservalue (lua_State *L, int idx, int n) { ** t[k] = value at the top of the stack (where 'k' is a string) */ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { - const TValue *slot; + int hres; TString *str = luaS_new(L, k); - api_checknelems(L, 1); - if (luaV_fastget(L, t, str, slot, luaH_getstr)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); + api_checkpop(L, 1); + luaV_fastset(t, str, s2v(L->top.p - 1), hres, luaH_psetstr); + if (hres == HOK) { + luaV_finishfastset(L, t, s2v(L->top.p - 1)); L->top.p--; /* pop value */ } else { setsvalue2s(L, L->top.p, str); /* push 'str' (to make it a TValue) */ api_incr_top(L); - luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), slot); + luaV_finishset(L, t, s2v(L->top.p - 1), s2v(L->top.p - 2), hres); L->top.p -= 2; /* pop value and key */ } lua_unlock(L); /* lock done by caller */ @@ -845,24 +870,24 @@ static void auxsetstr (lua_State *L, const TValue *t, const char *k) { LUA_API void lua_setglobal (lua_State *L, const char *name) { - const TValue *G; + TValue gt; lua_lock(L); /* unlock done in 'auxsetstr' */ - G = getGtable(L); - auxsetstr(L, G, name); + getGlobalTable(L, >); + auxsetstr(L, >, name); } LUA_API void lua_settable (lua_State *L, int idx) { TValue *t; - const TValue *slot; + int hres; lua_lock(L); - api_checknelems(L, 2); + api_checkpop(L, 2); t = index2value(L, idx); - if (luaV_fastget(L, t, s2v(L->top.p - 2), slot, luaH_get)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); - } + luaV_fastset(t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres, luaH_pset); + if (hres == HOK) + luaV_finishfastset(L, t, s2v(L->top.p - 1)); else - luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), slot); + luaV_finishset(L, t, s2v(L->top.p - 2), s2v(L->top.p - 1), hres); L->top.p -= 2; /* pop index and value */ lua_unlock(L); } @@ -876,17 +901,17 @@ LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { TValue *t; - const TValue *slot; + int hres; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); t = index2value(L, idx); - if (luaV_fastgeti(L, t, n, slot)) { - luaV_finishfastset(L, t, slot, s2v(L->top.p - 1)); - } + luaV_fastseti(t, n, s2v(L->top.p - 1), hres); + if (hres == HOK) + luaV_finishfastset(L, t, s2v(L->top.p - 1)); else { - TValue aux; - setivalue(&aux, n); - luaV_finishset(L, t, &aux, s2v(L->top.p - 1), slot); + TValue temp; + setivalue(&temp, n); + luaV_finishset(L, t, &temp, s2v(L->top.p - 1), hres); } L->top.p--; /* pop value */ lua_unlock(L); @@ -896,7 +921,7 @@ LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { static void aux_rawset (lua_State *L, int idx, TValue *key, int n) { Table *t; lua_lock(L); - api_checknelems(L, n); + api_checkpop(L, n); t = gettable(L, idx); luaH_set(L, t, key, s2v(L->top.p - 1)); invalidateTMcache(t); @@ -921,7 +946,7 @@ LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { Table *t; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); t = gettable(L, idx); luaH_setint(L, t, n, s2v(L->top.p - 1)); luaC_barrierback(L, obj2gco(t), s2v(L->top.p - 1)); @@ -934,7 +959,7 @@ LUA_API int lua_setmetatable (lua_State *L, int objindex) { TValue *obj; Table *mt; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); obj = index2value(L, objindex); if (ttisnil(s2v(L->top.p - 1))) mt = NULL; @@ -974,7 +999,7 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { TValue *o; int res; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); o = index2value(L, idx); api_check(L, ttisfulluserdata(o), "full userdata expected"); if (!(cast_uint(n) - 1u < cast_uint(uvalue(o)->nuvalue))) @@ -996,9 +1021,11 @@ LUA_API int lua_setiuservalue (lua_State *L, int idx, int n) { #define checkresults(L,na,nr) \ - api_check(L, (nr) == LUA_MULTRET \ + (api_check(L, (nr) == LUA_MULTRET \ || (L->ci->top.p - L->top.p >= (nr) - (na)), \ - "results from function overflow current stack size") + "results from function overflow current stack size"), \ + api_check(L, LUA_MULTRET <= (nr) && (nr) <= MAXRESULTS, \ + "invalid number of results")) LUA_API void lua_callk (lua_State *L, int nargs, int nresults, @@ -1007,7 +1034,7 @@ LUA_API void lua_callk (lua_State *L, int nargs, int nresults, lua_lock(L); api_check(L, k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); + api_checkpop(L, nargs + 1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); func = L->top.p - (nargs+1); @@ -1043,12 +1070,12 @@ static void f_call (lua_State *L, void *ud) { LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, lua_KContext ctx, lua_KFunction k) { struct CallS c; - int status; + TStatus status; ptrdiff_t func; lua_lock(L); api_check(L, k == NULL || !isLua(L->ci), "cannot use continuations inside hooks"); - api_checknelems(L, nargs+1); + api_checkpop(L, nargs + 1); api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); checkresults(L, nargs, nresults); if (errfunc == 0) @@ -1071,7 +1098,7 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, ci->u2.funcidx = cast_int(savestack(L, c.func)); ci->u.c.old_errfunc = L->errfunc; L->errfunc = func; - setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + setoah(ci, L->allowhook); /* save value of 'allowhook' */ ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ luaD_call(L, c.func, nresults); /* do the call */ ci->callstatus &= ~CIST_YPCALL; @@ -1080,14 +1107,14 @@ LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, } adjustresults(L, nresults); lua_unlock(L); - return status; + return APIstatus(status); } LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, const char *chunkname, const char *mode) { ZIO z; - int status; + TStatus status; lua_lock(L); if (!chunkname) chunkname = "?"; luaZ_init(L, &z, reader, data); @@ -1096,34 +1123,38 @@ LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, LClosure *f = clLvalue(s2v(L->top.p - 1)); /* get new function */ if (f->nupvalues >= 1) { /* does it have an upvalue? */ /* get global table from registry */ - const TValue *gt = getGtable(L); + TValue gt; + getGlobalTable(L, >); /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ - setobj(L, f->upvals[0]->v.p, gt); - luaC_barrier(L, f->upvals[0], gt); + setobj(L, f->upvals[0]->v.p, >); + luaC_barrier(L, f->upvals[0], >); } } lua_unlock(L); - return status; + return APIstatus(status); } +/* +** Dump a Lua function, calling 'writer' to write its parts. Ensure +** the stack returns with its original size. +*/ LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { int status; - TValue *o; + ptrdiff_t otop = savestack(L, L->top.p); /* original top */ + TValue *f = s2v(L->top.p - 1); /* function to be dumped */ lua_lock(L); - api_checknelems(L, 1); - o = s2v(L->top.p - 1); - if (isLfunction(o)) - status = luaU_dump(L, getproto(o), writer, data, strip); - else - status = 1; + api_checkpop(L, 1); + api_check(L, isLfunction(f), "Lua function expected"); + status = luaU_dump(L, clLvalue(f)->p, writer, data, strip); + L->top.p = restorestack(L, otop); /* restore top */ lua_unlock(L); return status; } LUA_API int lua_status (lua_State *L) { - return L->status; + return APIstatus(L->status); } @@ -1134,7 +1165,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { va_list argp; int res = 0; global_State *g = G(L); - if (g->gcstp & GCSTPGC) /* internal stop? */ + if (g->gcstp & (GCSTPGC | GCSTPCLS)) /* internal stop? */ return -1; /* all options are invalid when stopped */ lua_lock(L); va_start(argp, what); @@ -1145,7 +1176,7 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { } case LUA_GCRESTART: { luaE_setdebt(g, 0); - g->gcstp = 0; /* (GCSTPGC must be already zero here) */ + g->gcstp = 0; /* (other bits must be zero here) */ break; } case LUA_GCCOLLECT: { @@ -1162,34 +1193,17 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { break; } case LUA_GCSTEP: { - int data = va_arg(argp, int); - l_mem debt = 1; /* =1 to signal that it did an actual step */ lu_byte oldstp = g->gcstp; - g->gcstp = 0; /* allow GC to run (GCSTPGC must be zero here) */ - if (data == 0) { - luaE_setdebt(g, 0); /* do a basic step */ - luaC_step(L); - } - else { /* add 'data' to total debt */ - debt = cast(l_mem, data) * 1024 + g->GCdebt; - luaE_setdebt(g, debt); - luaC_checkGC(L); - } - g->gcstp = oldstp; /* restore previous state */ - if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + l_mem n = cast(l_mem, va_arg(argp, size_t)); + int work = 0; /* true if GC did some work */ + g->gcstp = 0; /* allow GC to run (other bits must be zero here) */ + if (n <= 0) + n = g->GCdebt; /* force to run one basic step */ + luaE_setdebt(g, g->GCdebt - n); + luaC_condGC(L, (void)0, work = 1); + if (work && g->gcstate == GCSpause) /* end of cycle? */ res = 1; /* signal it */ - break; - } - case LUA_GCSETPAUSE: { - int data = va_arg(argp, int); - res = getgcparam(g->gcpause); - setgcparam(g->gcpause, data); - break; - } - case LUA_GCSETSTEPMUL: { - int data = va_arg(argp, int); - res = getgcparam(g->gcstepmul); - setgcparam(g->gcstepmul, data); + g->gcstp = oldstp; /* restore previous state */ break; } case LUA_GCISRUNNING: { @@ -1197,30 +1211,24 @@ LUA_API int lua_gc (lua_State *L, int what, ...) { break; } case LUA_GCGEN: { - int minormul = va_arg(argp, int); - int majormul = va_arg(argp, int); - res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; - if (minormul != 0) - g->genminormul = minormul; - if (majormul != 0) - setgcparam(g->genmajormul, majormul); - luaC_changemode(L, KGC_GEN); + res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; + luaC_changemode(L, KGC_GENMINOR); break; } case LUA_GCINC: { - int pause = va_arg(argp, int); - int stepmul = va_arg(argp, int); - int stepsize = va_arg(argp, int); - res = isdecGCmodegen(g) ? LUA_GCGEN : LUA_GCINC; - if (pause != 0) - setgcparam(g->gcpause, pause); - if (stepmul != 0) - setgcparam(g->gcstepmul, stepmul); - if (stepsize != 0) - g->gcstepsize = stepsize; + res = (g->gckind == KGC_INC) ? LUA_GCINC : LUA_GCGEN; luaC_changemode(L, KGC_INC); break; } + case LUA_GCPARAM: { + int param = va_arg(argp, int); + int value = va_arg(argp, int); + api_check(L, 0 <= param && param < LUA_GCPN, "invalid parameter"); + res = cast_int(luaO_applyparam(g->gcparams[param], 100)); + if (value >= 0) + g->gcparams[param] = luaO_codeparam(cast_uint(value)); + break; + } default: res = -1; /* invalid option */ } va_end(argp); @@ -1239,7 +1247,7 @@ LUA_API int lua_error (lua_State *L) { TValue *errobj; lua_lock(L); errobj = s2v(L->top.p - 1); - api_checknelems(L, 1); + api_checkpop(L, 1); /* error object is the memory error message? */ if (ttisshrstring(errobj) && eqshrstr(tsvalue(errobj), G(L)->memerrmsg)) luaM_error(L); /* raise a memory error */ @@ -1254,30 +1262,25 @@ LUA_API int lua_next (lua_State *L, int idx) { Table *t; int more; lua_lock(L); - api_checknelems(L, 1); + api_checkpop(L, 1); t = gettable(L, idx); more = luaH_next(L, t, L->top.p - 1); - if (more) { + if (more) api_incr_top(L); - } else /* no more elements */ - L->top.p -= 1; /* remove key */ + L->top.p--; /* pop key */ lua_unlock(L); return more; } LUA_API void lua_toclose (lua_State *L, int idx) { - int nresults; StkId o; lua_lock(L); o = index2stack(L, idx); - nresults = L->ci->nresults; api_check(L, L->tbclist.p < o, "given index below or equal a marked one"); luaF_newtbcupval(L, o); /* create new to-be-closed upvalue */ - if (!hastocloseCfunc(nresults)) /* function not marked yet? */ - L->ci->nresults = codeNresults(nresults); /* mark it */ - lua_assert(hastocloseCfunc(L->ci->nresults)); + L->ci->callstatus |= CIST_TBC; /* mark that function has TBC slots */ lua_unlock(L); } @@ -1285,13 +1288,14 @@ LUA_API void lua_toclose (lua_State *L, int idx) { LUA_API void lua_concat (lua_State *L, int n) { lua_lock(L); api_checknelems(L, n); - if (n > 0) + if (n > 0) { luaV_concat(L, n); + luaC_checkGC(L); + } else { /* nothing to concatenate */ setsvalue2s(L, L->top.p, luaS_newlstr(L, "", 0)); /* push empty string */ api_incr_top(L); } - luaC_checkGC(L); lua_unlock(L); } @@ -1344,7 +1348,7 @@ LUA_API void *lua_newuserdatauv (lua_State *L, size_t size, int nuvalue) { Udata *u; lua_lock(L); api_check(L, 0 <= nuvalue && nuvalue < SHRT_MAX, "invalid value"); - u = luaS_newudata(L, size, nuvalue); + u = luaS_newudata(L, size, cast(unsigned short, nuvalue)); setuvalue(L, s2v(L->top.p), u); api_incr_top(L); luaC_checkGC(L); diff --git a/3rdparty/lua/plainlua/lapi.h b/3rdparty/lua/plainlua/lapi.h index a742427cdc79..9b54534428e1 100644 --- a/3rdparty/lua/plainlua/lapi.h +++ b/3rdparty/lua/plainlua/lapi.h @@ -12,10 +12,29 @@ #include "lstate.h" +#if defined(LUA_USE_APICHECK) +#include +#define api_check(l,e,msg) assert(e) +#else /* for testing */ +#define api_check(l,e,msg) ((void)(l), lua_assert((e) && msg)) +#endif + + + /* Increments 'L->top.p', checking for stack overflows */ -#define api_incr_top(L) {L->top.p++; \ - api_check(L, L->top.p <= L->ci->top.p, \ - "stack overflow");} +#define api_incr_top(L) \ + (L->top.p++, api_check(L, L->top.p <= L->ci->top.p, "stack overflow")) + + +/* +** macros that are executed whenever program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + /* @@ -30,23 +49,17 @@ /* Ensure the stack has at least 'n' elements */ #define api_checknelems(L,n) \ - api_check(L, (n) < (L->top.p - L->ci->func.p), \ - "not enough elements in the stack") + api_check(L, (n) < (L->top.p - L->ci->func.p), \ + "not enough elements in the stack") -/* -** To reduce the overhead of returning from C functions, the presence of -** to-be-closed variables in these functions is coded in the CallInfo's -** field 'nresults', in a way that functions with no to-be-closed variables -** with zero, one, or "all" wanted results have no overhead. Functions -** with other number of wanted results, as well as functions with -** variables to be closed, have an extra check. +/* Ensure the stack has at least 'n' elements to be popped. (Some +** functions only update a slot after checking it for popping, but that +** is only an optimization for a pop followed by a push.) */ - -#define hastocloseCfunc(n) ((n) < LUA_MULTRET) - -/* Map [-1, inf) (range of 'nresults') into (-inf, -2] */ -#define codeNresults(n) (-(n) - 3) -#define decodeNresults(n) (-(n) - 3) +#define api_checkpop(L,n) \ + api_check(L, (n) < L->top.p - L->ci->func.p && \ + L->tbclist.p < L->top.p - (n), \ + "not enough free elements in the stack") #endif diff --git a/3rdparty/lua/plainlua/lauxlib.c b/3rdparty/lua/plainlua/lauxlib.c index 923105ed3176..7f33f0addb53 100644 --- a/3rdparty/lua/plainlua/lauxlib.c +++ b/3rdparty/lua/plainlua/lauxlib.c @@ -25,12 +25,7 @@ #include "lua.h" #include "lauxlib.h" - - -#if !defined(MAX_SIZET) -/* maximum value for size_t */ -#define MAX_SIZET ((size_t)(~(size_t)0)) -#endif +#include "llimits.h" /* @@ -99,14 +94,14 @@ static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { static void pushfuncname (lua_State *L, lua_Debug *ar) { - if (pushglobalfuncname(L, ar)) { /* try first a global name */ - lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); - lua_remove(L, -2); /* remove name */ - } - else if (*ar->namewhat != '\0') /* is there a name from code? */ + if (*ar->namewhat != '\0') /* is there a name from code? */ lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ else if (*ar->what == 'm') /* main? */ lua_pushliteral(L, "main chunk"); + else if (pushglobalfuncname(L, ar)) { /* try a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } else if (*ar->what != 'C') /* for Lua functions, use */ lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); else /* nothing left... */ @@ -175,19 +170,27 @@ LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { lua_Debug ar; + const char *argword; if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); - lua_getinfo(L, "n", &ar); - if (strcmp(ar.namewhat, "method") == 0) { - arg--; /* do not count 'self' */ - if (arg == 0) /* error is in the self argument itself? */ - return luaL_error(L, "calling '%s' on bad self (%s)", - ar.name, extramsg); + lua_getinfo(L, "nt", &ar); + if (arg <= ar.extraargs) /* error in an extra argument? */ + argword = "extra argument"; + else { + arg -= ar.extraargs; /* do not count extra arguments */ + if (strcmp(ar.namewhat, "method") == 0) { /* colon syntax? */ + arg--; /* do not count (extra) self argument */ + if (arg == 0) /* error in self argument? */ + return luaL_error(L, "calling '%s' on bad self (%s)", + ar.name, extramsg); + /* else go through; error in a regular argument */ + } + argword = "argument"; } if (ar.name == NULL) ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; - return luaL_error(L, "bad argument #%d to '%s' (%s)", - arg, ar.name, extramsg); + return luaL_error(L, "bad %s #%d to '%s' (%s)", + argword, arg, ar.name, extramsg); } @@ -230,7 +233,7 @@ LUALIB_API void luaL_where (lua_State *L, int level) { /* ** Again, the use of 'lua_pushvfstring' ensures this function does ** not need reserved stack space when called. (At worst, it generates -** an error with "stack overflow" instead of the given message.) +** a memory error instead of the given message.) */ LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { va_list argp; @@ -473,18 +476,27 @@ typedef struct UBox { } UBox; +/* Resize the buffer used by a box. Optimize for the common case of +** resizing to the old size. (For instance, __gc will resize the box +** to 0 even after it was closed. 'pushresult' may also resize it to a +** final size that is equal to the one set when the buffer was created.) +*/ static void *resizebox (lua_State *L, int idx, size_t newsize) { - void *ud; - lua_Alloc allocf = lua_getallocf(L, &ud); UBox *box = (UBox *)lua_touserdata(L, idx); - void *temp = allocf(ud, box->box, box->bsize, newsize); - if (l_unlikely(temp == NULL && newsize > 0)) { /* allocation error? */ - lua_pushliteral(L, "not enough memory"); - lua_error(L); /* raise a memory error */ + if (box->bsize == newsize) /* not changing size? */ + return box->box; /* keep the buffer */ + else { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (l_unlikely(temp == NULL && newsize > 0)) { /* allocation error? */ + lua_pushliteral(L, "not enough memory"); + lua_error(L); /* raise a memory error */ + } + box->box = temp; + box->bsize = newsize; + return temp; } - box->box = temp; - box->bsize = newsize; - return temp; } @@ -529,15 +541,17 @@ static void newbox (lua_State *L) { /* ** Compute new size for buffer 'B', enough to accommodate extra 'sz' -** bytes. (The test for "not big enough" also gets the case when the -** computation of 'newsize' overflows.) +** bytes plus one for a terminating zero. */ static size_t newbuffsize (luaL_Buffer *B, size_t sz) { - size_t newsize = (B->size / 2) * 3; /* buffer size * 1.5 */ - if (l_unlikely(MAX_SIZET - sz < B->n)) /* overflow in (B->n + sz)? */ - return luaL_error(B->L, "buffer too large"); - if (newsize < B->n + sz) /* not big enough? */ - newsize = B->n + sz; + size_t newsize = B->size; + if (l_unlikely(sz >= MAX_SIZE - B->n)) + return cast_sizet(luaL_error(B->L, "resulting string too large")); + /* else B->n + sz + 1 <= MAX_SIZE */ + if (newsize <= MAX_SIZE/3 * 2) /* no overflow? */ + newsize += (newsize >> 1); /* new size *= 1.5 */ + if (newsize < B->n + sz + 1) /* not big enough? */ + newsize = B->n + sz + 1; return newsize; } @@ -597,9 +611,23 @@ LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { LUALIB_API void luaL_pushresult (luaL_Buffer *B) { lua_State *L = B->L; checkbufferlevel(B, -1); - lua_pushlstring(L, B->b, B->n); - if (buffonstack(B)) + if (!buffonstack(B)) /* using static buffer? */ + lua_pushlstring(L, B->b, B->n); /* save result as regular string */ + else { /* reuse buffer already allocated */ + UBox *box = (UBox *)lua_touserdata(L, -1); + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); /* function to free buffer */ + size_t len = B->n; /* final string length */ + char *s; + resizebox(L, -1, len + 1); /* adjust box size to content size */ + s = (char*)box->box; /* final buffer address */ + s[len] = '\0'; /* add ending zero */ + /* clear box, as Lua will take control of the buffer */ + box->bsize = 0; box->box = NULL; + lua_pushexternalstring(L, s, len, allocf, ud); lua_closeslot(L, -2); /* close the box */ + lua_gc(L, LUA_GCSTEP, len); + } lua_remove(L, -2); /* remove box or placeholder from the stack */ } @@ -653,13 +681,10 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { ** ======================================================= */ -/* index of free-list header (after the predefined values) */ -#define freelist (LUA_RIDX_LAST + 1) - /* -** The previously freed references form a linked list: -** t[freelist] is the index of a first free index, or zero if list is -** empty; t[t[freelist]] is the index of the second element; etc. +** The previously freed references form a linked list: t[1] is the index +** of a first free index, t[t[1]] is the index of the second element, +** etc. A zero signals the end of the list. */ LUALIB_API int luaL_ref (lua_State *L, int t) { int ref; @@ -668,19 +693,18 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { return LUA_REFNIL; /* 'nil' has a unique fixed reference */ } t = lua_absindex(L, t); - if (lua_rawgeti(L, t, freelist) == LUA_TNIL) { /* first access? */ + if (lua_rawgeti(L, t, 1) == LUA_TNUMBER) /* already initialized? */ + ref = (int)lua_tointeger(L, -1); /* ref = t[1] */ + else { /* first access */ + lua_assert(!lua_toboolean(L, -1)); /* must be nil or false */ ref = 0; /* list is empty */ lua_pushinteger(L, 0); /* initialize as an empty list */ - lua_rawseti(L, t, freelist); /* ref = t[freelist] = 0 */ - } - else { /* already initialized */ - lua_assert(lua_isinteger(L, -1)); - ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + lua_rawseti(L, t, 1); /* ref = t[1] = 0 */ } lua_pop(L, 1); /* remove element from stack */ if (ref != 0) { /* any free element? */ lua_rawgeti(L, t, ref); /* remove it from list */ - lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + lua_rawseti(L, t, 1); /* (t[1] = t[ref]) */ } else /* no free elements */ ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ @@ -692,11 +716,11 @@ LUALIB_API int luaL_ref (lua_State *L, int t) { LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { if (ref >= 0) { t = lua_absindex(L, t); - lua_rawgeti(L, t, freelist); + lua_rawgeti(L, t, 1); lua_assert(lua_isinteger(L, -1)); - lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_rawseti(L, t, ref); /* t[ref] = t[1] */ lua_pushinteger(L, ref); - lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + lua_rawseti(L, t, 1); /* t[1] = ref */ } } @@ -710,7 +734,7 @@ LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { */ typedef struct LoadF { - int n; /* number of pre-read characters */ + unsigned n; /* number of pre-read characters */ FILE *f; /* file being read */ char buff[BUFSIZ]; /* area for reading file */ } LoadF; @@ -810,10 +834,10 @@ LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, } } if (c != EOF) - lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ - errno = 0; + lf.buff[lf.n++] = cast_char(c); /* 'c' is the first character */ status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); readstatus = ferror(lf.f); + errno = 0; /* no useful error number until here */ if (filename) fclose(lf.f); /* close file (even in case of errors) */ if (readstatus) { lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ @@ -904,10 +928,9 @@ LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { else { switch (lua_type(L, idx)) { case LUA_TNUMBER: { - if (lua_isinteger(L, idx)) - lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); - else - lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); + char buff[LUA_N2SBUFFSZ]; + lua_numbertocstring(L, idx, buff); + lua_pushstring(L, buff); break; } case LUA_TSTRING: @@ -1005,7 +1028,7 @@ LUALIB_API void luaL_addgsub (luaL_Buffer *b, const char *s, const char *wild; size_t l = strlen(p); while ((wild = strstr(s, p)) != NULL) { - luaL_addlstring(b, s, wild - s); /* push prefix */ + luaL_addlstring(b, s, ct_diff2sz(wild - s)); /* push prefix */ luaL_addstring(b, r); /* push replacement in place of pattern */ s = wild + l; /* continue after 'p' */ } @@ -1035,7 +1058,7 @@ static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { /* -** Standard panic funcion just prints an error message. The test +** Standard panic function just prints an error message. The test ** with 'lua_type' avoids possible memory errors in 'lua_tostring'. */ static int panic (lua_State *L) { @@ -1105,8 +1128,57 @@ static void warnfon (void *ud, const char *message, int tocont) { } + +/* +** A function to compute an unsigned int with some level of +** randomness. Rely on Address Space Layout Randomization (if present) +** and the current time. +*/ +#if !defined(luai_makeseed) + +#include + + +/* Size for the buffer, in bytes */ +#define BUFSEEDB (sizeof(void*) + sizeof(time_t)) + +/* Size for the buffer in int's, rounded up */ +#define BUFSEED ((BUFSEEDB + sizeof(int) - 1) / sizeof(int)) + +/* +** Copy the contents of variable 'v' into the buffer pointed by 'b'. +** (The '&b[0]' disguises 'b' to fix an absurd warning from clang.) +*/ +#define addbuff(b,v) (memcpy(&b[0], &(v), sizeof(v)), b += sizeof(v)) + + +static unsigned int luai_makeseed (void) { + unsigned int buff[BUFSEED]; + unsigned int res; + unsigned int i; + time_t t = time(NULL); + char *b = (char*)buff; + addbuff(b, b); /* local variable's address */ + addbuff(b, t); /* time */ + /* fill (rare but possible) remain of the buffer with zeros */ + memset(b, 0, sizeof(buff) - BUFSEEDB); + res = buff[0]; + for (i = 1; i < BUFSEED; i++) + res ^= (res >> 3) + (res << 7) + buff[i]; + return res; +} + +#endif + + +LUALIB_API unsigned int luaL_makeseed (lua_State *L) { + (void)L; /* unused */ + return luai_makeseed(); +} + + LUALIB_API lua_State *luaL_newstate (void) { - lua_State *L = lua_newstate(l_alloc, NULL); + lua_State *L = lua_newstate(l_alloc, NULL, luai_makeseed()); if (l_likely(L)) { lua_atpanic(L, &panic); lua_setwarnf(L, warnfoff, L); /* default is warnings off */ diff --git a/3rdparty/lua/plainlua/lauxlib.h b/3rdparty/lua/plainlua/lauxlib.h index 5b977e2a39f1..d8522098a728 100644 --- a/3rdparty/lua/plainlua/lauxlib.h +++ b/3rdparty/lua/plainlua/lauxlib.h @@ -100,6 +100,8 @@ LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); LUALIB_API lua_State *(luaL_newstate) (void); +LUALIB_API unsigned luaL_makeseed (lua_State *L); + LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); LUALIB_API void (luaL_addgsub) (luaL_Buffer *b, const char *s, @@ -163,21 +165,10 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, /* push the value used to represent failure/error */ -#define luaL_pushfail(L) lua_pushnil(L) - - -/* -** Internal assertions for in-house debugging -*/ -#if !defined(lua_assert) - -#if defined LUAI_ASSERT - #include - #define lua_assert(c) assert(c) +#if defined(LUA_FAILISFALSE) +#define luaL_pushfail(L) lua_pushboolean(L, 0) #else - #define lua_assert(c) ((void)0) -#endif - +#define luaL_pushfail(L) lua_pushnil(L) #endif @@ -249,30 +240,6 @@ typedef struct luaL_Stream { /* }====================================================== */ -/* -** {================================================================== -** "Abstraction Layer" for basic report of messages and errors -** =================================================================== -*/ - -/* print a string */ -#if !defined(lua_writestring) -#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#endif - -/* print a newline and flush the output */ -#if !defined(lua_writeline) -#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) -#endif - -/* print an error message */ -#if !defined(lua_writestringerror) -#define lua_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) -#endif - -/* }================================================================== */ - /* ** {============================================================ diff --git a/3rdparty/lua/plainlua/lbaselib.c b/3rdparty/lua/plainlua/lbaselib.c index 1d60c9dede59..b296c4b76146 100644 --- a/3rdparty/lua/plainlua/lbaselib.c +++ b/3rdparty/lua/plainlua/lbaselib.c @@ -19,6 +19,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" static int luaB_print (lua_State *L) { @@ -57,21 +58,22 @@ static int luaB_warn (lua_State *L) { #define SPACECHARS " \f\n\r\t\v" -static const char *b_str2int (const char *s, int base, lua_Integer *pn) { +static const char *b_str2int (const char *s, unsigned base, lua_Integer *pn) { lua_Unsigned n = 0; int neg = 0; s += strspn(s, SPACECHARS); /* skip initial spaces */ if (*s == '-') { s++; neg = 1; } /* handle sign */ else if (*s == '+') s++; - if (!isalnum((unsigned char)*s)) /* no digit? */ + if (!isalnum(cast_uchar(*s))) /* no digit? */ return NULL; do { - int digit = (isdigit((unsigned char)*s)) ? *s - '0' - : (toupper((unsigned char)*s) - 'A') + 10; + unsigned digit = cast_uint(isdigit(cast_uchar(*s)) + ? *s - '0' + : (toupper(cast_uchar(*s)) - 'A') + 10); if (digit >= base) return NULL; /* invalid numeral */ n = n * base + digit; s++; - } while (isalnum((unsigned char)*s)); + } while (isalnum(cast_uchar(*s))); s += strspn(s, SPACECHARS); /* skip trailing spaces */ *pn = (lua_Integer)((neg) ? (0u - n) : n); return s; @@ -101,7 +103,7 @@ static int luaB_tonumber (lua_State *L) { luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ s = lua_tolstring(L, 1, &l); luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); - if (b_str2int(s, (int)base, &n) == s + l) { + if (b_str2int(s, cast_uint(base), &n) == s + l) { lua_pushinteger(L, n); return 1; } /* else not a number */ @@ -158,7 +160,7 @@ static int luaB_rawlen (lua_State *L) { int t = lua_type(L, 1); luaL_argexpected(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, "table or string"); - lua_pushinteger(L, lua_rawlen(L, 1)); + lua_pushinteger(L, l_castU2S(lua_rawlen(L, 1))); return 1; } @@ -198,11 +200,11 @@ static int pushmode (lua_State *L, int oldmode) { static int luaB_collectgarbage (lua_State *L) { static const char *const opts[] = {"stop", "restart", "collect", - "count", "step", "setpause", "setstepmul", - "isrunning", "generational", "incremental", NULL}; - static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, - LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, - LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC}; + "count", "step", "isrunning", "generational", "incremental", + "param", NULL}; + static const char optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCISRUNNING, LUA_GCGEN, LUA_GCINC, + LUA_GCPARAM}; int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; switch (o) { case LUA_GCCOUNT: { @@ -213,20 +215,12 @@ static int luaB_collectgarbage (lua_State *L) { return 1; } case LUA_GCSTEP: { - int step = (int)luaL_optinteger(L, 2, 0); - int res = lua_gc(L, o, step); + lua_Integer n = luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, cast_sizet(n)); checkvalres(res); lua_pushboolean(L, res); return 1; } - case LUA_GCSETPAUSE: - case LUA_GCSETSTEPMUL: { - int p = (int)luaL_optinteger(L, 2, 0); - int previous = lua_gc(L, o, p); - checkvalres(previous); - lua_pushinteger(L, previous); - return 1; - } case LUA_GCISRUNNING: { int res = lua_gc(L, o); checkvalres(res); @@ -234,15 +228,22 @@ static int luaB_collectgarbage (lua_State *L) { return 1; } case LUA_GCGEN: { - int minormul = (int)luaL_optinteger(L, 2, 0); - int majormul = (int)luaL_optinteger(L, 3, 0); - return pushmode(L, lua_gc(L, o, minormul, majormul)); + return pushmode(L, lua_gc(L, o)); } case LUA_GCINC: { - int pause = (int)luaL_optinteger(L, 2, 0); - int stepmul = (int)luaL_optinteger(L, 3, 0); - int stepsize = (int)luaL_optinteger(L, 4, 0); - return pushmode(L, lua_gc(L, o, pause, stepmul, stepsize)); + return pushmode(L, lua_gc(L, o)); + } + case LUA_GCPARAM: { + static const char *const params[] = { + "minormul", "majorminor", "minormajor", + "pause", "stepmul", "stepsize", NULL}; + static const char pnum[] = { + LUA_GCPMINORMUL, LUA_GCPMAJORMINOR, LUA_GCPMINORMAJOR, + LUA_GCPPAUSE, LUA_GCPSTEPMUL, LUA_GCPSTEPSIZE}; + int p = pnum[luaL_checkoption(L, 2, NULL, params)]; + lua_Integer value = luaL_optinteger(L, 3, -1); + lua_pushinteger(L, lua_gc(L, o, p, (int)value)); + return 1; } default: { int res = lua_gc(L, o); @@ -337,9 +338,17 @@ static int load_aux (lua_State *L, int status, int envidx) { } +static const char *getMode (lua_State *L, int idx) { + const char *mode = luaL_optstring(L, idx, "bt"); + if (strchr(mode, 'B') != NULL) /* Lua code cannot use fixed buffers */ + luaL_argerror(L, idx, "invalid mode"); + return mode; +} + + static int luaB_loadfile (lua_State *L) { const char *fname = luaL_optstring(L, 1, NULL); - const char *mode = luaL_optstring(L, 2, NULL); + const char *mode = getMode(L, 2); int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ int status = luaL_loadfilex(L, fname, mode); return load_aux(L, status, env); @@ -388,7 +397,7 @@ static int luaB_load (lua_State *L) { int status; size_t l; const char *s = lua_tolstring(L, 1, &l); - const char *mode = luaL_optstring(L, 3, "bt"); + const char *mode = getMode(L, 3); int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ if (s != NULL) { /* loading a string? */ const char *chunkname = luaL_optstring(L, 2, s); diff --git a/3rdparty/lua/plainlua/lcode.c b/3rdparty/lua/plainlua/lcode.c index 3f78370c6eed..7ca895f14796 100644 --- a/3rdparty/lua/plainlua/lcode.c +++ b/3rdparty/lua/plainlua/lcode.c @@ -31,10 +31,6 @@ #include "lvm.h" -/* Maximum number of registers in a Lua function (must fit in 8 bits) */ -#define MAXREGS 255 - - /* (note that expressions VJMP also have jumps.) */ #define hasjumps(e) ((e)->t != (e)->f) @@ -44,7 +40,10 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k); /* semantic error */ -l_noret luaK_semerror (LexState *ls, const char *msg) { +l_noret luaK_semerror (LexState *ls, const char *fmt, ...) { + const char *msg; + va_list argp; + pushvfstring(ls->L, argp, fmt, msg); ls->t.token = 0; /* remove "near " from final message */ luaX_syntaxerror(ls, msg); } @@ -212,6 +211,7 @@ void luaK_ret (FuncState *fs, int first, int nret) { case 1: op = OP_RETURN1; break; default: op = OP_RETURN; break; } + luaY_checklimit(fs, nret + 1, MAXARG_B, "returns"); luaK_codeABC(fs, op, first, nret + 1, 0); } @@ -332,15 +332,15 @@ static void savelineinfo (FuncState *fs, Proto *f, int line) { int pc = fs->pc - 1; /* last instruction coded */ if (abs(linedif) >= LIMLINEDIFF || fs->iwthabs++ >= MAXIWTHABS) { luaM_growvector(fs->ls->L, f->abslineinfo, fs->nabslineinfo, - f->sizeabslineinfo, AbsLineInfo, MAX_INT, "lines"); + f->sizeabslineinfo, AbsLineInfo, INT_MAX, "lines"); f->abslineinfo[fs->nabslineinfo].pc = pc; f->abslineinfo[fs->nabslineinfo++].line = line; linedif = ABSLINEINFO; /* signal that there is absolute information */ fs->iwthabs = 1; /* restart counter */ } luaM_growvector(fs->ls->L, f->lineinfo, pc, f->sizelineinfo, ls_byte, - MAX_INT, "opcodes"); - f->lineinfo[pc] = linedif; + INT_MAX, "opcodes"); + f->lineinfo[pc] = cast(ls_byte, linedif); fs->previousline = line; /* last line saved */ } @@ -384,7 +384,7 @@ int luaK_code (FuncState *fs, Instruction i) { Proto *f = fs->f; /* put new instruction in code array */ luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, - MAX_INT, "opcodes"); + INT_MAX, "opcodes"); f->code[fs->pc++] = i; savelineinfo(fs, f, fs->ls->lastline); return fs->pc - 1; /* index of new instruction */ @@ -395,32 +395,40 @@ int luaK_code (FuncState *fs, Instruction i) { ** Format and emit an 'iABC' instruction. (Assertions check consistency ** of parameters versus opcode.) */ -int luaK_codeABCk (FuncState *fs, OpCode o, int a, int b, int c, int k) { +int luaK_codeABCk (FuncState *fs, OpCode o, int A, int B, int C, int k) { lua_assert(getOpMode(o) == iABC); - lua_assert(a <= MAXARG_A && b <= MAXARG_B && - c <= MAXARG_C && (k & ~1) == 0); - return luaK_code(fs, CREATE_ABCk(o, a, b, c, k)); + lua_assert(A <= MAXARG_A && B <= MAXARG_B && + C <= MAXARG_C && (k & ~1) == 0); + return luaK_code(fs, CREATE_ABCk(o, A, B, C, k)); +} + + +int luaK_codevABCk (FuncState *fs, OpCode o, int A, int B, int C, int k) { + lua_assert(getOpMode(o) == ivABC); + lua_assert(A <= MAXARG_A && B <= MAXARG_vB && + C <= MAXARG_vC && (k & ~1) == 0); + return luaK_code(fs, CREATE_vABCk(o, A, B, C, k)); } /* ** Format and emit an 'iABx' instruction. */ -int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { +int luaK_codeABx (FuncState *fs, OpCode o, int A, int Bc) { lua_assert(getOpMode(o) == iABx); - lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, bc)); + lua_assert(A <= MAXARG_A && Bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, A, Bc)); } /* ** Format and emit an 'iAsBx' instruction. */ -static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) { - unsigned int b = bc + OFFSET_sBx; +static int codeAsBx (FuncState *fs, OpCode o, int A, int Bc) { + int b = Bc + OFFSET_sBx; lua_assert(getOpMode(o) == iAsBx); - lua_assert(a <= MAXARG_A && b <= MAXARG_Bx); - return luaK_code(fs, CREATE_ABx(o, a, b)); + lua_assert(A <= MAXARG_A && b <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, A, b)); } @@ -428,7 +436,7 @@ static int codeAsBx (FuncState *fs, OpCode o, int a, int bc) { ** Format and emit an 'isJ' instruction. */ static int codesJ (FuncState *fs, OpCode o, int sj, int k) { - unsigned int j = sj + OFFSET_sJ; + int j = sj + OFFSET_sJ; lua_assert(getOpMode(o) == isJ); lua_assert(j <= MAXARG_sJ && (k & ~1) == 0); return luaK_code(fs, CREATE_sJ(o, j, k)); @@ -438,9 +446,9 @@ static int codesJ (FuncState *fs, OpCode o, int sj, int k) { /* ** Emit an "extra argument" instruction (format 'iAx') */ -static int codeextraarg (FuncState *fs, int a) { - lua_assert(a <= MAXARG_Ax); - return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +static int codeextraarg (FuncState *fs, int A) { + lua_assert(A <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, A)); } @@ -467,9 +475,7 @@ static int luaK_codek (FuncState *fs, int reg, int k) { void luaK_checkstack (FuncState *fs, int n) { int newstack = fs->freereg + n; if (newstack > fs->f->maxstacksize) { - if (newstack >= MAXREGS) - luaX_syntaxerror(fs->ls, - "function or expression needs too many registers"); + luaY_checklimit(fs, newstack, MAX_FSTACK, "registers"); fs->f->maxstacksize = cast_byte(newstack); } } @@ -480,7 +486,7 @@ void luaK_checkstack (FuncState *fs, int n) { */ void luaK_reserveregs (FuncState *fs, int n) { luaK_checkstack(fs, n); - fs->freereg += n; + fs->freereg = cast_byte(fs->freereg + n); } @@ -534,38 +540,44 @@ static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { /* ** Add constant 'v' to prototype's list of constants (field 'k'). +*/ +static int addk (FuncState *fs, Proto *f, TValue *v) { + lua_State *L = fs->ls->L; + int oldsize = f->sizek; + int k = fs->nk; + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) + setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +/* ** Use scanner's table to cache position of constants in constant list ** and try to reuse constants. Because some values should not be used ** as keys (nil cannot be a key, integer keys can collapse with float ** keys), the caller must provide a useful 'key' for indexing the cache. -** Note that all functions share the same table, so entering or exiting -** a function can make some indices wrong. */ -static int addk (FuncState *fs, TValue *key, TValue *v) { +static int k2proto (FuncState *fs, TValue *key, TValue *v) { TValue val; - lua_State *L = fs->ls->L; Proto *f = fs->f; - const TValue *idx = luaH_get(fs->ls->h, key); /* query scanner table */ - int k, oldsize; - if (ttisinteger(idx)) { /* is there an index there? */ - k = cast_int(ivalue(idx)); - /* correct value? (warning: must distinguish floats from integers!) */ - if (k < fs->nk && ttypetag(&f->k[k]) == ttypetag(v) && - luaV_rawequalobj(&f->k[k], v)) - return k; /* reuse index */ + int tag = luaH_get(fs->kcache, key, &val); /* query scanner table */ + int k; + if (!tagisempty(tag)) { /* is there an index there? */ + k = cast_int(ivalue(&val)); + /* collisions can happen only for float keys */ + lua_assert(ttisfloat(key) || luaV_rawequalobj(&f->k[k], v)); + return k; /* reuse index */ } /* constant not found; create a new entry */ - oldsize = f->sizek; - k = fs->nk; - /* numerical value does not need GC barrier; - table has no metatable, so it does not need to invalidate cache */ + k = addk(fs, f, v); + /* cache it for reuse; numerical value does not need GC barrier; + table is not a metatable, so it does not need to invalidate cache */ setivalue(&val, k); - luaH_finishset(L, fs->ls->h, key, idx, &val); - luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); - while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); - setobj(L, &f->k[k], v); - fs->nk++; - luaC_barrier(L, f, v); + luaH_set(fs->ls->L, fs->kcache, key, &val); return k; } @@ -576,7 +588,7 @@ static int addk (FuncState *fs, TValue *key, TValue *v) { static int stringK (FuncState *fs, TString *s) { TValue o; setsvalue(fs->ls->L, &o, s); - return addk(fs, &o, &o); /* use string itself as key */ + return k2proto(fs, &o, &o); /* use string itself as key */ } @@ -586,7 +598,7 @@ static int stringK (FuncState *fs, TString *s) { static int luaK_intK (FuncState *fs, lua_Integer n) { TValue o; setivalue(&o, n); - return addk(fs, &o, &o); /* use integer itself as key */ + return k2proto(fs, &o, &o); /* use integer itself as key */ } /* @@ -595,27 +607,32 @@ static int luaK_intK (FuncState *fs, lua_Integer n) { ** with actual integers. To that, we add to the number its smaller ** power-of-two fraction that is still significant in its scale. ** For doubles, that would be 1/2^52. -** (This method is not bulletproof: there may be another float -** with that value, and for floats larger than 2^53 the result is -** still an integer. At worst, this only wastes an entry with -** a duplicate.) +** This method is not bulletproof: different numbers may generate the +** same key (e.g., very large numbers will overflow to 'inf') and for +** floats larger than 2^53 the result is still an integer. At worst, +** this only wastes an entry with a duplicate. */ static int luaK_numberK (FuncState *fs, lua_Number r) { - TValue o; - lua_Integer ik; - setfltvalue(&o, r); - if (!luaV_flttointeger(r, &ik, F2Ieq)) /* not an integral value? */ - return addk(fs, &o, &o); /* use number itself as key */ - else { /* must build an alternative key */ + TValue o, kv; + setfltvalue(&o, r); /* value as a TValue */ + if (r == 0) { /* handle zero as a special case */ + setpvalue(&kv, fs); /* use FuncState as index */ + return k2proto(fs, &kv, &o); /* cannot collide */ + } + else { const int nbm = l_floatatt(MANT_DIG); const lua_Number q = l_mathop(ldexp)(l_mathop(1.0), -nbm + 1); - const lua_Number k = (ik == 0) ? q : r + r*q; /* new key */ - TValue kv; - setfltvalue(&kv, k); - /* result is not an integral value, unless value is too large */ - lua_assert(!luaV_flttointeger(k, &ik, F2Ieq) || - l_mathop(fabs)(r) >= l_mathop(1e6)); - return addk(fs, &kv, &o); + const lua_Number k = r * (1 + q); /* key */ + lua_Integer ik; + setfltvalue(&kv, k); /* key as a TValue */ + if (!luaV_flttointeger(k, &ik, F2Ieq)) { /* not an integral value? */ + int n = k2proto(fs, &kv, &o); /* use key */ + if (luaV_rawequalobj(&fs->f->k[n], &o)) /* correct value? */ + return n; + } + /* else, either key is still an integer or there was a collision; + anyway, do not try to reuse constant; instead, create a new one */ + return addk(fs, fs->f, &o); } } @@ -626,7 +643,7 @@ static int luaK_numberK (FuncState *fs, lua_Number r) { static int boolF (FuncState *fs) { TValue o; setbfvalue(&o); - return addk(fs, &o, &o); /* use boolean itself as key */ + return k2proto(fs, &o, &o); /* use boolean itself as key */ } @@ -636,7 +653,7 @@ static int boolF (FuncState *fs) { static int boolT (FuncState *fs) { TValue o; setbtvalue(&o); - return addk(fs, &o, &o); /* use boolean itself as key */ + return k2proto(fs, &o, &o); /* use boolean itself as key */ } @@ -646,9 +663,9 @@ static int boolT (FuncState *fs) { static int nilK (FuncState *fs) { TValue k, v; setnilvalue(&v); - /* cannot use nil as key; instead use table itself to represent nil */ - sethvalue(fs->ls->L, &k, fs->ls->h); - return addk(fs, &k, &v); + /* cannot use nil as key; instead use table itself */ + sethvalue(fs->ls->L, &k, fs->kcache); + return k2proto(fs, &k, &v); } @@ -721,6 +738,7 @@ static void const2exp (TValue *v, expdesc *e) { */ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { Instruction *pc = &getinstruction(fs, e); + luaY_checklimit(fs, nresults + 1, MAXARG_C, "multiple results"); if (e->k == VCALL) /* expression is an open function call? */ SETARG_C(*pc, nresults + 1); else { @@ -735,10 +753,11 @@ void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { /* ** Convert a VKSTR to a VK */ -static void str2K (FuncState *fs, expdesc *e) { +static int str2K (FuncState *fs, expdesc *e) { lua_assert(e->k == VKSTR); e->u.info = stringK(fs, e->u.strval); e->k = VK; + return e->u.info; } @@ -1037,10 +1056,10 @@ static int exp2RK (FuncState *fs, expdesc *e) { } -static void codeABRK (FuncState *fs, OpCode o, int a, int b, +static void codeABRK (FuncState *fs, OpCode o, int A, int B, expdesc *ec) { int k = exp2RK(fs, ec); - luaK_codeABCk(fs, o, a, b, ec->u.info, k); + luaK_codeABCk(fs, o, A, B, ec->u.info, k); } @@ -1081,22 +1100,6 @@ void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { } -/* -** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). -*/ -void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { - int ereg; - luaK_exp2anyreg(fs, e); - ereg = e->u.info; /* register where 'e' was placed */ - freeexp(fs, e); - e->u.info = fs->freereg; /* base register for op_self */ - e->k = VNONRELOC; /* self expression has a fixed register */ - luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ - codeABRK(fs, OP_SELF, e->u.info, ereg, key); - freeexp(fs, key); -} - - /* ** Negate condition 'e' (where 'e' is a comparison). */ @@ -1271,6 +1274,33 @@ static int isSCnumber (expdesc *e, int *pi, int *isfloat) { } +/* +** Emit SELF instruction or equivalent: the code will convert +** expression 'e' into 'e.key(e,'. +*/ +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int ereg, base; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' (the receiver) was placed */ + freeexp(fs, e); + base = e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* method and 'self' produced by op_self */ + lua_assert(key->k == VKSTR); + /* is method name a short string in a valid K index? */ + if (strisshr(key->u.strval) && luaK_exp2K(fs, key)) { + /* can use 'self' opcode */ + luaK_codeABCk(fs, OP_SELF, base, ereg, key->u.info, 0); + } + else { /* cannot use 'self' opcode; use move+gettable */ + luaK_exp2anyreg(fs, key); /* put method name in a register */ + luaK_codeABC(fs, OP_MOVE, base + 1, ereg, 0); /* copy self to base+1 */ + luaK_codeABC(fs, OP_GETTABLE, base, ereg, key->u.info); /* get method */ + } + freeexp(fs, key); +} + + /* ** Create expression 't[k]'. 't' must have its final result already in a ** register or upvalue. Upvalues can only be indexed by literal strings. @@ -1278,35 +1308,38 @@ static int isSCnumber (expdesc *e, int *pi, int *isfloat) { ** values in registers. */ void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + int keystr = -1; if (k->k == VKSTR) - str2K(fs, k); + keystr = str2K(fs, k); lua_assert(!hasjumps(t) && (t->k == VLOCAL || t->k == VNONRELOC || t->k == VUPVAL)); if (t->k == VUPVAL && !isKstr(fs, k)) /* upvalue indexed by non 'Kstr'? */ luaK_exp2anyreg(fs, t); /* put it in a register */ if (t->k == VUPVAL) { - int temp = t->u.info; /* upvalue index */ - lua_assert(isKstr(fs, k)); + lu_byte temp = cast_byte(t->u.info); /* upvalue index */ t->u.ind.t = temp; /* (can't do a direct assignment; values overlap) */ - t->u.ind.idx = k->u.info; /* literal short string */ + lua_assert(isKstr(fs, k)); + t->u.ind.idx = cast_short(k->u.info); /* literal short string */ t->k = VINDEXUP; } else { /* register index of the table */ - t->u.ind.t = (t->k == VLOCAL) ? t->u.var.ridx: t->u.info; + t->u.ind.t = cast_byte((t->k == VLOCAL) ? t->u.var.ridx: t->u.info); if (isKstr(fs, k)) { - t->u.ind.idx = k->u.info; /* literal short string */ + t->u.ind.idx = cast_short(k->u.info); /* literal short string */ t->k = VINDEXSTR; } - else if (isCint(k)) { - t->u.ind.idx = cast_int(k->u.ival); /* int. constant in proper range */ + else if (isCint(k)) { /* int. constant in proper range? */ + t->u.ind.idx = cast_short(k->u.ival); t->k = VINDEXI; } else { - t->u.ind.idx = luaK_exp2anyreg(fs, k); /* register */ + t->u.ind.idx = cast_short(luaK_exp2anyreg(fs, k)); /* register */ t->k = VINDEXED; } } + t->u.ind.keystr = keystr; /* string index in 'k' */ + t->u.ind.ro = 0; /* by default, not read-only */ } @@ -1413,7 +1446,7 @@ static void finishbinexpval (FuncState *fs, expdesc *e1, expdesc *e2, e1->u.info = pc; e1->k = VRELOC; /* all those operations are relocatable */ luaK_fixline(fs, line); - luaK_codeABCk(fs, mmop, v1, v2, event, flip); /* to call metamethod */ + luaK_codeABCk(fs, mmop, v1, v2, cast_int(event), flip); /* metamethod */ luaK_fixline(fs, line); } @@ -1618,7 +1651,7 @@ void luaK_prefix (FuncState *fs, UnOpr opr, expdesc *e, int line) { luaK_dischargevars(fs, e); switch (opr) { case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ - if (constfolding(fs, opr + LUA_OPUNM, e, &ef)) + if (constfolding(fs, cast_int(opr + LUA_OPUNM), e, &ef)) break; /* else */ /* FALLTHROUGH */ case OPR_LEN: @@ -1706,7 +1739,7 @@ static void codeconcat (FuncState *fs, expdesc *e1, expdesc *e2, int line) { void luaK_posfix (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2, int line) { luaK_dischargevars(fs, e2); - if (foldbinop(opr) && constfolding(fs, opr + LUA_OPADD, e1, e2)) + if (foldbinop(opr) && constfolding(fs, cast_int(opr + LUA_OPADD), e1, e2)) return; /* done by folding */ switch (opr) { case OPR_AND: { @@ -1792,11 +1825,11 @@ void luaK_fixline (FuncState *fs, int line) { void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { Instruction *inst = &fs->f->code[pc]; - int rb = (hsize != 0) ? luaO_ceillog2(hsize) + 1 : 0; /* hash size */ - int extra = asize / (MAXARG_C + 1); /* higher bits of array size */ - int rc = asize % (MAXARG_C + 1); /* lower bits of array size */ + int extra = asize / (MAXARG_vC + 1); /* higher bits of array size */ + int rc = asize % (MAXARG_vC + 1); /* lower bits of array size */ int k = (extra > 0); /* true iff needs extra argument */ - *inst = CREATE_ABCk(OP_NEWTABLE, ra, rb, rc, k); + hsize = (hsize != 0) ? luaO_ceillog2(cast_uint(hsize)) + 1 : 0; + *inst = CREATE_vABCk(OP_NEWTABLE, ra, hsize, rc, k); *(inst + 1) = CREATE_Ax(OP_EXTRAARG, extra); } @@ -1809,18 +1842,18 @@ void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize) { ** table (or LUA_MULTRET to add up to stack top). */ void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { - lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); + lua_assert(tostore != 0); if (tostore == LUA_MULTRET) tostore = 0; - if (nelems <= MAXARG_C) - luaK_codeABC(fs, OP_SETLIST, base, tostore, nelems); + if (nelems <= MAXARG_vC) + luaK_codevABCk(fs, OP_SETLIST, base, tostore, nelems, 0); else { - int extra = nelems / (MAXARG_C + 1); - nelems %= (MAXARG_C + 1); - luaK_codeABCk(fs, OP_SETLIST, base, tostore, nelems, 1); + int extra = nelems / (MAXARG_vC + 1); + nelems %= (MAXARG_vC + 1); + luaK_codevABCk(fs, OP_SETLIST, base, tostore, nelems, 1); codeextraarg(fs, extra); } - fs->freereg = base + 1; /* free registers with list values */ + fs->freereg = cast_byte(base + 1); /* free registers with list values */ } @@ -1833,8 +1866,8 @@ static int finaltarget (Instruction *code, int i) { Instruction pc = code[i]; if (GET_OPCODE(pc) != OP_JMP) break; - else - i += GETARG_sJ(pc) + 1; + else + i += GETARG_sJ(pc) + 1; } return i; } @@ -1844,15 +1877,18 @@ static int finaltarget (Instruction *code, int i) { ** Do a final pass over the code of a function, doing small peephole ** optimizations and adjustments. */ +#include "lopnames.h" void luaK_finish (FuncState *fs) { int i; Proto *p = fs->f; for (i = 0; i < fs->pc; i++) { Instruction *pc = &p->code[i]; - lua_assert(i == 0 || isOT(*(pc - 1)) == isIT(*pc)); + /* avoid "not used" warnings when assert is off (for 'onelua.c') */ + (void)luaP_isOT; (void)luaP_isIT; + lua_assert(i == 0 || luaP_isOT(*(pc - 1)) == luaP_isIT(*pc)); switch (GET_OPCODE(*pc)) { case OP_RETURN0: case OP_RETURN1: { - if (!(fs->needclose || p->is_vararg)) + if (!(fs->needclose || (p->flag & PF_ISVARARG))) break; /* no extra work */ /* else use OP_RETURN to do the extra work */ SET_OPCODE(*pc, OP_RETURN); @@ -1860,7 +1896,7 @@ void luaK_finish (FuncState *fs) { case OP_RETURN: case OP_TAILCALL: { if (fs->needclose) SETARG_k(*pc, 1); /* signal that it needs to close */ - if (p->is_vararg) + if (p->flag & PF_ISVARARG) SETARG_C(*pc, p->numparams + 1); /* signal that it is vararg */ break; } diff --git a/3rdparty/lua/plainlua/lcode.h b/3rdparty/lua/plainlua/lcode.h index 0b971fc4359b..94fc2417dded 100644 --- a/3rdparty/lua/plainlua/lcode.h +++ b/3rdparty/lua/plainlua/lcode.h @@ -60,9 +60,11 @@ typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; #define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) LUAI_FUNC int luaK_code (FuncState *fs, Instruction i); -LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); -LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, - int B, int C, int k); +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, int Bx); +LUAI_FUNC int luaK_codeABCk (FuncState *fs, OpCode o, int A, int B, int C, + int k); +LUAI_FUNC int luaK_codevABCk (FuncState *fs, OpCode o, int A, int B, int C, + int k); LUAI_FUNC int luaK_exp2const (FuncState *fs, const expdesc *e, TValue *v); LUAI_FUNC void luaK_fixline (FuncState *fs, int line); LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); @@ -95,7 +97,7 @@ LUAI_FUNC void luaK_settablesize (FuncState *fs, int pc, int ra, int asize, int hsize); LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); LUAI_FUNC void luaK_finish (FuncState *fs); -LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *msg); +LUAI_FUNC l_noret luaK_semerror (LexState *ls, const char *fmt, ...); #endif diff --git a/3rdparty/lua/plainlua/lcorolib.c b/3rdparty/lua/plainlua/lcorolib.c index c64adf08a8e1..23dd8441565a 100644 --- a/3rdparty/lua/plainlua/lcorolib.c +++ b/3rdparty/lua/plainlua/lcorolib.c @@ -16,6 +16,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" static lua_State *getco (lua_State *L) { @@ -153,8 +154,13 @@ static int luaB_costatus (lua_State *L) { } +static lua_State *getoptco (lua_State *L) { + return (lua_isnone(L, 1) ? L : getco(L)); +} + + static int luaB_yieldable (lua_State *L) { - lua_State *co = lua_isnone(L, 1) ? L : getco(L); + lua_State *co = getoptco(L); lua_pushboolean(L, lua_isyieldable(co)); return 1; } @@ -168,7 +174,7 @@ static int luaB_corunning (lua_State *L) { static int luaB_close (lua_State *L) { - lua_State *co = getco(L); + lua_State *co = getoptco(L); int status = auxstatus(L, co); switch (status) { case COS_DEAD: case COS_YIELD: { @@ -183,6 +189,13 @@ static int luaB_close (lua_State *L) { return 2; } } + case COS_RUN: /* running coroutine? */ + lua_geti(L, LUA_REGISTRYINDEX, LUA_RIDX_MAINTHREAD); /* get main */ + if (lua_tothread(L, -1) == co) + return luaL_error(L, "cannot close main thread"); + lua_closethread(co, L); /* close itself */ + lua_assert(0); /* previous call does not return */ + return 0; default: /* normal or running coroutine */ return luaL_error(L, "cannot close a %s coroutine", statname[status]); } diff --git a/3rdparty/lua/plainlua/ldblib.c b/3rdparty/lua/plainlua/ldblib.c index 6dcbaa9824ba..c7b74812e8e3 100644 --- a/3rdparty/lua/plainlua/ldblib.c +++ b/3rdparty/lua/plainlua/ldblib.c @@ -18,6 +18,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" /* @@ -190,8 +191,10 @@ static int db_getinfo (lua_State *L) { settabsi(L, "ftransfer", ar.ftransfer); settabsi(L, "ntransfer", ar.ntransfer); } - if (strchr(options, 't')) + if (strchr(options, 't')) { settabsb(L, "istailcall", ar.istailcall); + settabsi(L, "extraargs", ar.extraargs); + } if (strchr(options, 'L')) treatstackoption(L, L1, "activelines"); if (strchr(options, 'f')) @@ -446,14 +449,6 @@ static int db_traceback (lua_State *L) { } -static int db_setcstacklimit (lua_State *L) { - int limit = (int)luaL_checkinteger(L, 1); - int res = lua_setcstacklimit(L, limit); - lua_pushinteger(L, res); - return 1; -} - - static const luaL_Reg dblib[] = { {"debug", db_debug}, {"getuservalue", db_getuservalue}, @@ -471,7 +466,6 @@ static const luaL_Reg dblib[] = { {"setmetatable", db_setmetatable}, {"setupvalue", db_setupvalue}, {"traceback", db_traceback}, - {"setcstacklimit", db_setcstacklimit}, {NULL, NULL} }; diff --git a/3rdparty/lua/plainlua/ldebug.c b/3rdparty/lua/plainlua/ldebug.c index 7264fce8a55c..9110f437bf6e 100644 --- a/3rdparty/lua/plainlua/ldebug.c +++ b/3rdparty/lua/plainlua/ldebug.c @@ -33,13 +33,12 @@ #define LuaClosure(f) ((f) != NULL && (f)->c.tt == LUA_VLCL) +static const char strlocal[] = "local"; +static const char strupval[] = "upvalue"; static const char *funcnamefromcall (lua_State *L, CallInfo *ci, const char **name); -static const char strlocal[] = "local"; -static const char strupval[] = "upvalue"; - static int currentpc (CallInfo *ci) { lua_assert(isLua(ci)); @@ -66,7 +65,7 @@ static int getbaseline (const Proto *f, int pc, int *basepc) { return f->linedefined; } else { - int i = cast_uint(pc) / MAXIWTHABS - 1; /* get an estimate */ + int i = pc / MAXIWTHABS - 1; /* get an estimate */ /* estimate must be a lower bound of the correct base */ lua_assert(i < 0 || (i < f->sizeabslineinfo && f->abslineinfo[i].pc <= pc)); @@ -185,7 +184,7 @@ static const char *upvalname (const Proto *p, int uv) { static const char *findvararg (CallInfo *ci, int n, StkId *pos) { - if (clLvalue(s2v(ci->func.p))->p->is_vararg) { + if (clLvalue(s2v(ci->func.p))->p->flag & PF_ISVARARG) { int nextra = ci->u.l.nextraargs; if (n >= -nextra) { /* 'n' is negative */ *pos = ci->func.p - nextra - (n + 1); @@ -248,6 +247,7 @@ LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { lua_lock(L); name = luaG_findlocal(L, ar->i_ci, n, &pos); if (name) { + api_checkpop(L, 1); setobjs2s(L, pos, L->top.p - 1); L->top.p--; /* pop value */ } @@ -267,8 +267,7 @@ static void funcinfo (lua_Debug *ar, Closure *cl) { else { const Proto *p = cl->l.p; if (p->source) { - ar->source = getstr(p->source); - ar->srclen = tsslen(p->source); + ar->source = getlstr(p->source, ar->srclen); } else { ar->source = "=?"; @@ -305,7 +304,7 @@ static void collectvalidlines (lua_State *L, Closure *f) { int i; TValue v; setbtvalue(&v); /* boolean 'true' to be the value of all indices */ - if (!p->is_vararg) /* regular function? */ + if (!(p->flag & PF_ISVARARG)) /* regular function? */ i = 0; /* consider all instructions */ else { /* vararg function */ lua_assert(GET_OPCODE(p->code[0]) == OP_VARARGPREP); @@ -349,13 +348,21 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, ar->nparams = 0; } else { - ar->isvararg = f->l.p->is_vararg; + ar->isvararg = (f->l.p->flag & PF_ISVARARG) ? 1 : 0; ar->nparams = f->l.p->numparams; } break; } case 't': { - ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + if (ci != NULL) { + ar->istailcall = !!(ci->callstatus & CIST_TAIL); + ar->extraargs = + cast_uchar((ci->callstatus & MAX_CCMT) >> CIST_CCMT); + } + else { + ar->istailcall = 0; + ar->extraargs = 0; + } break; } case 'n': { @@ -367,11 +374,11 @@ static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, break; } case 'r': { - if (ci == NULL || !(ci->callstatus & CIST_TRAN)) + if (ci == NULL || !(ci->callstatus & CIST_HOOKED)) ar->ftransfer = ar->ntransfer = 0; else { - ar->ftransfer = ci->u2.transferinfo.ftransfer; - ar->ntransfer = ci->u2.transferinfo.ntransfer; + ar->ftransfer = L->transferinfo.ftransfer; + ar->ntransfer = L->transferinfo.ntransfer; } break; } @@ -536,24 +543,9 @@ static void rname (const Proto *p, int pc, int c, const char **name) { } -/* -** Find a "name" for a 'C' value in an RK instruction. -*/ -static void rkname (const Proto *p, int pc, Instruction i, const char **name) { - int c = GETARG_C(i); /* key index */ - if (GETARG_k(i)) /* is 'c' a constant? */ - kname(p, c, name); - else /* 'c' is a register */ - rname(p, pc, c, name); -} - - /* ** Check whether table being indexed by instruction 'i' is the -** environment '_ENV'. If the table is an upvalue, get its name; -** otherwise, find some "name" for the table and check whether -** that name is the name of a local variable (and not, for instance, -** a string). Then check that, if there is a name, it is '_ENV'. +** environment '_ENV' */ static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) { int t = GETARG_B(i); /* table index */ @@ -562,6 +554,8 @@ static const char *isEnv (const Proto *p, int pc, Instruction i, int isup) { name = upvalname(p, t); else { /* 't' is a register */ const char *what = basicgetobjname(p, &pc, t, &name); + /* 'name' must be the name of a local variable (at the current + level or an upvalue) */ if (what != strlocal && what != strupval) name = NULL; /* cannot be the variable _ENV */ } @@ -601,7 +595,8 @@ static const char *getobjname (const Proto *p, int lastpc, int reg, return isEnv(p, lastpc, i, 0); } case OP_SELF: { - rkname(p, lastpc, i, name); + int k = GETARG_C(i); /* key index */ + kname(p, k, name); return "method"; } default: break; /* go through to return NULL */ @@ -822,13 +817,15 @@ l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { /* add src:line information to 'msg' */ const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, int line) { - char buff[LUA_IDSIZE]; - if (src) - luaO_chunkid(buff, getstr(src), tsslen(src)); - else { /* no source available; use "?" instead */ - buff[0] = '?'; buff[1] = '\0'; + if (src == NULL) /* no debug information? */ + return luaO_pushfstring(L, "?:?: %s", msg); + else { + char buff[LUA_IDSIZE]; + size_t idlen; + const char *id = getlstr(src, idlen); + luaO_chunkid(buff, id, idlen); + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } - return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); } @@ -841,6 +838,10 @@ l_noret luaG_errormsg (lua_State *L) { L->top.p++; /* assume EXTRA_STACK */ luaD_callnoyield(L, L->top.p - 2, 1); /* call it */ } + if (ttisnil(s2v(L->top.p - 1))) { /* error object is nil? */ + /* change it to a proper message */ + setsvalue2s(L, L->top.p - 1, luaS_newliteral(L, "")); + } luaD_throw(L, LUA_ERRRUN); } @@ -850,10 +851,9 @@ l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { const char *msg; va_list argp; luaC_checkGC(L); /* error message uses memory */ - va_start(argp, fmt); - msg = luaO_pushvfstring(L, fmt, argp); /* format message */ - va_end(argp); - if (isLua(ci)) { /* if Lua function, add source:line information */ + pushvfstring(L, argp, fmt, msg); + if (isLua(ci)) { /* Lua function? */ + /* add source:line information */ luaG_addinfo(L, msg, ci_func(ci)->p->source, getcurrentline(ci)); setobjs2s(L, L->top.p - 2, L->top.p - 1); /* remove 'msg' */ L->top.p--; @@ -904,9 +904,9 @@ int luaG_tracecall (lua_State *L) { Proto *p = ci_func(ci)->p; ci->u.l.trap = 1; /* ensure hooks will be checked */ if (ci->u.l.savedpc == p->code) { /* first instruction (not resuming)? */ - if (p->is_vararg) + if (p->flag & PF_ISVARARG) return 0; /* hooks will start at VARARGPREP instruction */ - else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yieded? */ + else if (!(ci->callstatus & CIST_HOOKYIELD)) /* not yielded? */ luaD_hookcall(L, ci); /* check 'call' hook */ } return 1; /* keep 'trap' on */ @@ -927,7 +927,7 @@ int luaG_tracecall (lua_State *L) { */ int luaG_traceexec (lua_State *L, const Instruction *pc) { CallInfo *ci = L->ci; - lu_byte mask = L->hookmask; + lu_byte mask = cast_byte(L->hookmask); const Proto *p = ci_func(ci)->p; int counthook; if (!(mask & (LUA_MASKLINE | LUA_MASKCOUNT))) { /* no hooks? */ @@ -945,7 +945,7 @@ int luaG_traceexec (lua_State *L, const Instruction *pc) { ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ return 1; /* do not call hook again (VM yielded, so it did not move) */ } - if (!isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ + if (!luaP_isIT(*(ci->u.l.savedpc - 1))) /* top not being used? */ L->top.p = ci->top.p; /* correct top */ if (counthook) luaD_hook(L, LUA_HOOKCOUNT, -1, 0, 0); /* call count hook */ diff --git a/3rdparty/lua/plainlua/ldo.c b/3rdparty/lua/plainlua/ldo.c index c92573d6e699..776519dc9dae 100644 --- a/3rdparty/lua/plainlua/ldo.c +++ b/3rdparty/lua/plainlua/ldo.c @@ -38,6 +38,19 @@ #define errorstatus(s) ((s) > LUA_YIELD) +/* +** these macros allow user-specific actions when a thread is +** resumed/yielded. +*/ +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + + /* ** {====================================================== ** Error-recovery functions @@ -56,22 +69,22 @@ /* C++ exceptions */ #define LUAI_THROW(L,c) throw(c) -#define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ +#define LUAI_TRY(L,c,f,ud) \ + try { (f)(L, ud); } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy field */ #elif defined(LUA_USE_POSIX) /* }{ */ /* in POSIX, try _longjmp/_setjmp (more efficient) */ #define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define LUAI_TRY(L,c,f,ud) if (_setjmp((c)->b) == 0) ((f)(L, ud)) #define luai_jmpbuf jmp_buf #else /* }{ */ /* ISO C handling with long jumps */ #define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define LUAI_TRY(L,c,f,ud) if (setjmp((c)->b) == 0) ((f)(L, ud)) #define luai_jmpbuf jmp_buf #endif /* } */ @@ -84,42 +97,36 @@ struct lua_longjmp { struct lua_longjmp *previous; luai_jmpbuf b; - volatile int status; /* error code */ + volatile TStatus status; /* error code */ }; -void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop) { - switch (errcode) { - case LUA_ERRMEM: { /* memory error? */ - setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ - break; - } - case LUA_OK: { /* special case only for closing upvalues */ - setnilvalue(s2v(oldtop)); /* no error message */ - break; - } - default: { - lua_assert(errorstatus(errcode)); /* real error */ - setobjs2s(L, oldtop, L->top.p - 1); /* error message on current top */ - break; - } +void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop) { + if (errcode == LUA_ERRMEM) { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ } - L->top.p = oldtop + 1; + else { + lua_assert(errorstatus(errcode)); /* must be a real error */ + lua_assert(!ttisnil(s2v(L->top.p - 1))); /* with a non-nil object */ + setobjs2s(L, oldtop, L->top.p - 1); /* move it to 'oldtop' */ + } + L->top.p = oldtop + 1; /* top goes back to old top plus error object */ } -l_noret luaD_throw (lua_State *L, int errcode) { +l_noret luaD_throw (lua_State *L, TStatus errcode) { if (L->errorJmp) { /* thread has an error handler? */ L->errorJmp->status = errcode; /* set status */ LUAI_THROW(L, L->errorJmp); /* jump to it */ } else { /* thread has no error handler */ global_State *g = G(L); + lua_State *mainth = mainthread(g); errcode = luaE_resetthread(L, errcode); /* close all upvalues */ L->status = errcode; - if (g->mainthread->errorJmp) { /* main thread has a handler? */ - setobjs2s(L, g->mainthread->top.p++, L->top.p - 1); /* copy error obj. */ - luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + if (mainth->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, mainth->top.p++, L->top.p - 1); /* copy error obj. */ + luaD_throw(mainth, errcode); /* re-throw in main thread */ } else { /* no handler at all; abort */ if (g->panic) { /* panic function? */ @@ -132,15 +139,23 @@ l_noret luaD_throw (lua_State *L, int errcode) { } -int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { +l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode) { + if (L->errorJmp) { + /* unroll error entries up to the first level */ + while (L->errorJmp->previous != NULL) + L->errorJmp = L->errorJmp->previous; + } + luaD_throw(L, errcode); +} + + +TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { l_uint32 oldnCcalls = L->nCcalls; struct lua_longjmp lj; lj.status = LUA_OK; lj.previous = L->errorJmp; /* chain new error handler */ L->errorJmp = &lj; - LUAI_TRY(L, &lj, - (*f)(L, ud); - ); + LUAI_TRY(L, &lj, f, ud); /* call 'f' catching errors */ L->errorJmp = lj.previous; /* restore old error handler */ L->nCcalls = oldnCcalls; return lj.status; @@ -155,7 +170,49 @@ int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { ** =================================================================== */ +/* some stack space for error handling */ +#define STACKERRSPACE 200 + + +/* maximum stack size that respects size_t */ +#define MAXSTACK_BYSIZET ((MAX_SIZET / sizeof(StackValue)) - STACKERRSPACE) +/* +** Minimum between LUAI_MAXSTACK and MAXSTACK_BYSIZET +** (Maximum size for the stack must respect size_t.) +*/ +#define MAXSTACK cast_int(LUAI_MAXSTACK < MAXSTACK_BYSIZET \ + ? LUAI_MAXSTACK : MAXSTACK_BYSIZET) + + +/* stack size with extra space for error handling */ +#define ERRORSTACKSIZE (MAXSTACK + STACKERRSPACE) + + +/* raise an error while running the message handler */ +l_noret luaD_errerr (lua_State *L) { + TString *msg = luaS_newliteral(L, "error in error handling"); + setsvalue2s(L, L->top.p, msg); + L->top.p++; /* assume EXTRA_STACK */ + luaD_throw(L, LUA_ERRERR); +} + + +/* +** In ISO C, any pointer use after the pointer has been deallocated is +** undefined behavior. So, before a stack reallocation, all pointers +** should be changed to offsets, and after the reallocation they should +** be changed back to pointers. As during the reallocation the pointers +** are invalid, the reallocation cannot run emergency collections. +** Alternatively, we can use the old address after the deallocation. +** That is not strict ISO C, but seems to work fine everywhere. +** The following macro chooses how strict is the code. +*/ +#if !defined(LUAI_STRICT_ADDRESS) +#define LUAI_STRICT_ADDRESS 1 +#endif + +#if LUAI_STRICT_ADDRESS /* ** Change all pointers to the stack into offsets. */ @@ -176,9 +233,10 @@ static void relstack (lua_State *L) { /* ** Change back all offsets into pointers. */ -static void correctstack (lua_State *L) { +static void correctstack (lua_State *L, StkId oldstack) { CallInfo *ci; UpVal *up; + UNUSED(oldstack); L->top.p = restorestack(L, L->top.offset); L->tbclist.p = restorestack(L, L->tbclist.offset); for (up = L->openupval; up != NULL; up = up->u.open.next) @@ -191,28 +249,40 @@ static void correctstack (lua_State *L) { } } +#else +/* +** Assume that it is fine to use an address after its deallocation, +** as long as we do not dereference it. +*/ -/* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) +static void relstack (lua_State *L) { UNUSED(L); } /* do nothing */ -/* raise an error while running the message handler */ -l_noret luaD_errerr (lua_State *L) { - TString *msg = luaS_newliteral(L, "error in error handling"); - setsvalue2s(L, L->top.p, msg); - L->top.p++; /* assume EXTRA_STACK */ - luaD_throw(L, LUA_ERRERR); +/* +** Correct pointers into 'oldstack' to point into 'L->stack'. +*/ +static void correctstack (lua_State *L, StkId oldstack) { + CallInfo *ci; + UpVal *up; + StkId newstack = L->stack.p; + if (oldstack == newstack) + return; + L->top.p = L->top.p - oldstack + newstack; + L->tbclist.p = L->tbclist.p - oldstack + newstack; + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v.p = s2v(uplevel(up) - oldstack + newstack); + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top.p = ci->top.p - oldstack + newstack; + ci->func.p = ci->func.p - oldstack + newstack; + if (isLua(ci)) + ci->u.l.trap = 1; /* signal to update 'trap' in 'luaV_execute' */ + } } +#endif /* ** Reallocate the stack to a new size, correcting all pointers into it. -** In ISO C, any pointer use after the pointer has been deallocated is -** undefined behavior. So, before the reallocation, all pointers are -** changed to offsets, and after the reallocation they are changed back -** to pointers. As during the reallocation the pointers are invalid, the -** reallocation cannot run emergency collections. -** ** In case of allocation error, raise an error or return false according ** to 'raiseerror'. */ @@ -220,21 +290,22 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { int oldsize = stacksize(L); int i; StkId newstack; - int oldgcstop = G(L)->gcstopem; - lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + StkId oldstack = L->stack.p; + lu_byte oldgcstop = G(L)->gcstopem; + lua_assert(newsize <= MAXSTACK || newsize == ERRORSTACKSIZE); relstack(L); /* change pointers to offsets */ G(L)->gcstopem = 1; /* stop emergency collection */ - newstack = luaM_reallocvector(L, L->stack.p, oldsize + EXTRA_STACK, + newstack = luaM_reallocvector(L, oldstack, oldsize + EXTRA_STACK, newsize + EXTRA_STACK, StackValue); G(L)->gcstopem = oldgcstop; /* restore emergency collection */ if (l_unlikely(newstack == NULL)) { /* reallocation failed? */ - correctstack(L); /* change offsets back to pointers */ + correctstack(L, oldstack); /* change offsets back to pointers */ if (raiseerror) luaM_error(L); else return 0; /* do not raise an error */ } L->stack.p = newstack; - correctstack(L); /* change offsets back to pointers */ + correctstack(L, oldstack); /* change offsets back to pointers */ L->stack_last.p = L->stack.p + newsize; for (i = oldsize + EXTRA_STACK; i < newsize + EXTRA_STACK; i++) setnilvalue(s2v(newstack + i)); /* erase new segment */ @@ -248,7 +319,7 @@ int luaD_reallocstack (lua_State *L, int newsize, int raiseerror) { */ int luaD_growstack (lua_State *L, int n, int raiseerror) { int size = stacksize(L); - if (l_unlikely(size > LUAI_MAXSTACK)) { + if (l_unlikely(size > MAXSTACK)) { /* if stack is larger than maximum, thread is already using the extra space reserved for errors, that is, thread is handling a stack error; cannot grow further than that. */ @@ -257,14 +328,14 @@ int luaD_growstack (lua_State *L, int n, int raiseerror) { luaD_errerr(L); /* error inside message handler */ return 0; /* if not 'raiseerror', just signal it */ } - else if (n < LUAI_MAXSTACK) { /* avoids arithmetic overflows */ - int newsize = 2 * size; /* tentative new size */ + else if (n < MAXSTACK) { /* avoids arithmetic overflows */ + int newsize = size + (size >> 1); /* tentative new size (size * 1.5) */ int needed = cast_int(L->top.p - L->stack.p) + n; - if (newsize > LUAI_MAXSTACK) /* cannot cross the limit */ - newsize = LUAI_MAXSTACK; + if (newsize > MAXSTACK) /* cannot cross the limit */ + newsize = MAXSTACK; if (newsize < needed) /* but must respect what was asked for */ newsize = needed; - if (l_likely(newsize <= LUAI_MAXSTACK)) + if (l_likely(newsize <= MAXSTACK)) return luaD_reallocstack(L, newsize, raiseerror); } /* else stack overflow */ @@ -300,28 +371,28 @@ static int stackinuse (lua_State *L) { ** to twice the current use. (So, the final stack size is at most 2/3 the ** previous size, and half of its entries are empty.) ** As a particular case, if stack was handling a stack overflow and now -** it is not, 'max' (limited by LUAI_MAXSTACK) will be smaller than +** it is not, 'max' (limited by MAXSTACK) will be smaller than ** stacksize (equal to ERRORSTACKSIZE in this case), and so the stack ** will be reduced to a "regular" size. */ void luaD_shrinkstack (lua_State *L) { int inuse = stackinuse(L); - int max = (inuse > LUAI_MAXSTACK / 3) ? LUAI_MAXSTACK : inuse * 3; + int max = (inuse > MAXSTACK / 3) ? MAXSTACK : inuse * 3; /* if thread is currently not handling a stack overflow and its size is larger than maximum "reasonable" size, shrink it */ - if (inuse <= LUAI_MAXSTACK && stacksize(L) > max) { - int nsize = (inuse > LUAI_MAXSTACK / 2) ? LUAI_MAXSTACK : inuse * 2; + if (inuse <= MAXSTACK && stacksize(L) > max) { + int nsize = (inuse > MAXSTACK / 2) ? MAXSTACK : inuse * 2; luaD_reallocstack(L, nsize, 0); /* ok if that fails */ } else /* don't change stack */ - condmovestack(L,{},{}); /* (change only for debugging) */ + condmovestack(L,(void)0,(void)0); /* (change only for debugging) */ luaE_shrinkCI(L); /* shrink CI list */ } void luaD_inctop (lua_State *L) { - luaD_checkstack(L, 1); L->top.p++; + luaD_checkstack(L, 1); } /* }================================================================== */ @@ -336,7 +407,6 @@ void luaD_hook (lua_State *L, int event, int line, int ftransfer, int ntransfer) { lua_Hook hook = L->hook; if (hook && L->allowhook) { /* make sure there is a hook */ - int mask = CIST_HOOKED; CallInfo *ci = L->ci; ptrdiff_t top = savestack(L, L->top.p); /* preserve original 'top' */ ptrdiff_t ci_top = savestack(L, ci->top.p); /* idem for 'ci->top' */ @@ -344,18 +414,15 @@ void luaD_hook (lua_State *L, int event, int line, ar.event = event; ar.currentline = line; ar.i_ci = ci; - if (ntransfer != 0) { - mask |= CIST_TRAN; /* 'ci' has transfer information */ - ci->u2.transferinfo.ftransfer = ftransfer; - ci->u2.transferinfo.ntransfer = ntransfer; - } + L->transferinfo.ftransfer = ftransfer; + L->transferinfo.ntransfer = ntransfer; if (isLua(ci) && L->top.p < ci->top.p) L->top.p = ci->top.p; /* protect entire activation register */ luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ if (ci->top.p < L->top.p + LUA_MINSTACK) ci->top.p = L->top.p + LUA_MINSTACK; L->allowhook = 0; /* cannot call hooks inside a hook */ - ci->callstatus |= mask; + ci->callstatus |= CIST_HOOKED; lua_unlock(L); (*hook)(L, &ar); lua_lock(L); @@ -363,7 +430,7 @@ void luaD_hook (lua_State *L, int event, int line, L->allowhook = 1; ci->top.p = restorestack(L, ci_top); L->top.p = restorestack(L, top); - ci->callstatus &= ~mask; + ci->callstatus &= ~CIST_HOOKED; } } @@ -398,11 +465,11 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { int ftransfer; if (isLua(ci)) { Proto *p = ci_func(ci)->p; - if (p->is_vararg) + if (p->flag & PF_ISVARARG) delta = ci->u.l.nextraargs + p->numparams + 1; } ci->func.p += delta; /* if vararg, back to virtual 'func' */ - ftransfer = cast(unsigned short, firstres - ci->func.p); + ftransfer = cast_int(firstres - ci->func.p); luaD_hook(L, LUA_HOOKRET, -1, ftransfer, nres); /* call it */ ci->func.p -= delta; } @@ -413,51 +480,72 @@ static void rethook (lua_State *L, CallInfo *ci, int nres) { /* ** Check whether 'func' has a '__call' metafield. If so, put it in the -** stack, below original 'func', so that 'luaD_precall' can call it. Raise -** an error if there is no '__call' metafield. +** stack, below original 'func', so that 'luaD_precall' can call it. +** Raise an error if there is no '__call' metafield. +** Bits CIST_CCMT in status count how many _call metamethods were +** invoked and how many corresponding extra arguments were pushed. +** (This count will be saved in the 'callstatus' of the call). +** Raise an error if this counter overflows. */ -static StkId tryfuncTM (lua_State *L, StkId func) { +static unsigned tryfuncTM (lua_State *L, StkId func, unsigned status) { const TValue *tm; StkId p; - checkstackGCp(L, 1, func); /* space for metamethod */ - tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); /* (after previous GC) */ - if (l_unlikely(ttisnil(tm))) - luaG_callerror(L, s2v(func)); /* nothing to call */ + tm = luaT_gettmbyobj(L, s2v(func), TM_CALL); + if (l_unlikely(ttisnil(tm))) /* no metamethod? */ + luaG_callerror(L, s2v(func)); for (p = L->top.p; p > func; p--) /* open space for metamethod */ setobjs2s(L, p, p-1); L->top.p++; /* stack space pre-allocated by the caller */ setobj2s(L, func, tm); /* metamethod is the new function to be called */ - return func; + if ((status & MAX_CCMT) == MAX_CCMT) /* is counter full? */ + luaG_runerror(L, "'__call' chain too long"); + return status + (1u << CIST_CCMT); /* increment counter */ +} + + +/* Generic case for 'moveresult' */ +l_sinline void genmoveresults (lua_State *L, StkId res, int nres, + int wanted) { + StkId firstresult = L->top.p - nres; /* index of first result */ + int i; + if (nres > wanted) /* extra results? */ + nres = wanted; /* don't need them */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstresult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(s2v(res + i)); + L->top.p = res + wanted; /* top points after the last result */ } /* -** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. -** Handle most typical cases (zero results for commands, one result for -** expressions, multiple results for tail calls/single parameters) -** separated. +** Given 'nres' results at 'firstResult', move 'fwanted-1' of them +** to 'res'. Handle most typical cases (zero results for commands, +** one result for expressions, multiple results for tail calls/single +** parameters) separated. The flag CIST_TBC in 'fwanted', if set, +** forces the switch to go to the default case. */ -l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { - StkId firstresult; - int i; - switch (wanted) { /* handle typical cases separately */ - case 0: /* no values needed */ +l_sinline void moveresults (lua_State *L, StkId res, int nres, + l_uint32 fwanted) { + switch (fwanted) { /* handle typical cases separately */ + case 0 + 1: /* no values needed */ L->top.p = res; return; - case 1: /* one value needed */ + case 1 + 1: /* one value needed */ if (nres == 0) /* no results? */ setnilvalue(s2v(res)); /* adjust with nil */ else /* at least one result */ setobjs2s(L, res, L->top.p - nres); /* move it to proper place */ L->top.p = res + 1; return; - case LUA_MULTRET: - wanted = nres; /* we want all results */ + case LUA_MULTRET + 1: + genmoveresults(L, res, nres, nres); /* we want all results */ break; - default: /* two/more results and/or to-be-closed variables */ - if (hastocloseCfunc(wanted)) { /* to-be-closed variables? */ - L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ + default: { /* two/more results and/or to-be-closed variables */ + int wanted = get_nresults(fwanted); + if (fwanted & CIST_TBC) { /* to-be-closed variables? */ L->ci->u2.nres = nres; + L->ci->callstatus |= CIST_CLSRET; /* in case of yields */ res = luaF_close(L, res, CLOSEKTOP, 1); L->ci->callstatus &= ~CIST_CLSRET; if (L->hookmask) { /* if needed, call hook after '__close's */ @@ -465,21 +553,13 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { rethook(L, L->ci, nres); res = restorestack(L, savedres); /* hook can move stack */ } - wanted = decodeNresults(wanted); if (wanted == LUA_MULTRET) wanted = nres; /* we want all results */ } + genmoveresults(L, res, nres, wanted); break; + } } - /* generic case */ - firstresult = L->top.p - nres; /* index of first result */ - if (nres > wanted) /* extra results? */ - nres = wanted; /* don't need them */ - for (i = 0; i < nres; i++) /* move all results to correct place */ - setobjs2s(L, res + i, firstresult + i); - for (; i < wanted; i++) /* complete wanted number of results */ - setnilvalue(s2v(res + i)); - L->top.p = res + wanted; /* top points after the last result */ } @@ -490,14 +570,14 @@ l_sinline void moveresults (lua_State *L, StkId res, int nres, int wanted) { ** that. */ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { - int wanted = ci->nresults; - if (l_unlikely(L->hookmask && !hastocloseCfunc(wanted))) + l_uint32 fwanted = ci->callstatus & (CIST_TBC | CIST_NRESULTS); + if (l_unlikely(L->hookmask) && !(fwanted & CIST_TBC)) rethook(L, ci, nres); /* move results to proper place */ - moveresults(L, ci->func.p, nres, wanted); + moveresults(L, ci->func.p, nres, fwanted); /* function cannot be in any of these cases when returning */ lua_assert(!(ci->callstatus & - (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_TRAN | CIST_CLSRET))); + (CIST_HOOKED | CIST_YPCALL | CIST_FIN | CIST_CLSRET))); L->ci = ci->previous; /* back to caller (after closing variables) */ } @@ -506,12 +586,18 @@ void luaD_poscall (lua_State *L, CallInfo *ci, int nres) { #define next_ci(L) (L->ci->next ? L->ci->next : luaE_extendCI(L)) -l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, - int mask, StkId top) { +/* +** Allocate and initialize CallInfo structure. At this point, the +** only valid fields in the call status are number of results, +** CIST_C (if it's a C function), and number of extra arguments. +** (All these bit-fields fit in 16-bit values.) +*/ +l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, unsigned status, + StkId top) { CallInfo *ci = L->ci = next_ci(L); /* new frame */ ci->func.p = func; - ci->nresults = nret; - ci->callstatus = mask; + lua_assert((status & ~(CIST_NRESULTS | CIST_C | MAX_CCMT)) == 0); + ci->callstatus = status; ci->top.p = top; return ci; } @@ -520,12 +606,12 @@ l_sinline CallInfo *prepCallInfo (lua_State *L, StkId func, int nret, /* ** precall for C functions */ -l_sinline int precallC (lua_State *L, StkId func, int nresults, +l_sinline int precallC (lua_State *L, StkId func, unsigned status, lua_CFunction f) { int n; /* number of returns */ CallInfo *ci; - checkstackGCp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ - L->ci = ci = prepCallInfo(L, func, nresults, CIST_C, + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + L->ci = ci = prepCallInfo(L, func, status | CIST_C, L->top.p + LUA_MINSTACK); lua_assert(ci->top.p <= L->stack_last.p); if (l_unlikely(L->hookmask & LUA_MASKCALL)) { @@ -549,18 +635,19 @@ l_sinline int precallC (lua_State *L, StkId func, int nresults, */ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, int narg1, int delta) { + unsigned status = LUA_MULTRET + 1; retry: switch (ttypetag(s2v(func))) { case LUA_VCCL: /* C closure */ - return precallC(L, func, LUA_MULTRET, clCvalue(s2v(func))->f); + return precallC(L, func, status, clCvalue(s2v(func))->f); case LUA_VLCF: /* light C function */ - return precallC(L, func, LUA_MULTRET, fvalue(s2v(func))); + return precallC(L, func, status, fvalue(s2v(func))); case LUA_VLCL: { /* Lua function */ Proto *p = clLvalue(s2v(func))->p; int fsize = p->maxstacksize; /* frame size */ int nfixparams = p->numparams; int i; - checkstackGCp(L, fsize - delta, func); + checkstackp(L, fsize - delta, func); ci->func.p -= delta; /* restore 'func' (if vararg) */ for (i = 0; i < narg1; i++) /* move down function and arguments */ setobjs2s(L, ci->func.p + i, func + i); @@ -575,8 +662,8 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, return -1; } default: { /* not a function */ - func = tryfuncTM(L, func); /* try to get '__call' metamethod */ - /* return luaD_pretailcall(L, ci, func, narg1 + 1, delta); */ + checkstackp(L, 1, func); /* space for metamethod */ + status = tryfuncTM(L, func, status); /* try '__call' metamethod */ narg1++; goto retry; /* try again */ } @@ -593,13 +680,15 @@ int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, ** original function position. */ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { + unsigned status = cast_uint(nresults + 1); + lua_assert(status <= MAXRESULTS + 1); retry: switch (ttypetag(s2v(func))) { case LUA_VCCL: /* C closure */ - precallC(L, func, nresults, clCvalue(s2v(func))->f); + precallC(L, func, status, clCvalue(s2v(func))->f); return NULL; case LUA_VLCF: /* light C function */ - precallC(L, func, nresults, fvalue(s2v(func))); + precallC(L, func, status, fvalue(s2v(func))); return NULL; case LUA_VLCL: { /* Lua function */ CallInfo *ci; @@ -607,8 +696,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { int narg = cast_int(L->top.p - func) - 1; /* number of real arguments */ int nfixparams = p->numparams; int fsize = p->maxstacksize; /* frame size */ - checkstackGCp(L, fsize, func); - L->ci = ci = prepCallInfo(L, func, nresults, 0, func + 1 + fsize); + checkstackp(L, fsize, func); + L->ci = ci = prepCallInfo(L, func, status, func + 1 + fsize); ci->u.l.savedpc = p->code; /* starting point */ for (; narg < nfixparams; narg++) setnilvalue(s2v(L->top.p++)); /* complete missing arguments */ @@ -616,8 +705,8 @@ CallInfo *luaD_precall (lua_State *L, StkId func, int nresults) { return ci; } default: { /* not a function */ - func = tryfuncTM(L, func); /* try to get '__call' metamethod */ - /* return luaD_precall(L, func, nresults); */ + checkstackp(L, 1, func); /* space for metamethod */ + status = tryfuncTM(L, func, status); /* try '__call' metamethod */ goto retry; /* try again with metamethod */ } } @@ -640,7 +729,7 @@ l_sinline void ccall (lua_State *L, StkId func, int nResults, l_uint32 inc) { luaE_checkcstack(L); } if ((ci = luaD_precall(L, func, nResults)) != NULL) { /* Lua function? */ - ci->callstatus = CIST_FRESH; /* mark that it is a "fresh" execute */ + ci->callstatus |= CIST_FRESH; /* mark that it is a "fresh" execute */ luaV_execute(L, ci); /* call it */ } L->nCcalls -= inc; @@ -679,13 +768,13 @@ void luaD_callnoyield (lua_State *L, StkId func, int nResults) { ** particular, field CIST_RECST preserves the error status across these ** multiple runs, changing only if there is a new error. */ -static int finishpcallk (lua_State *L, CallInfo *ci) { - int status = getcistrecst(ci); /* get original status */ +static TStatus finishpcallk (lua_State *L, CallInfo *ci) { + TStatus status = getcistrecst(ci); /* get original status */ if (l_likely(status == LUA_OK)) /* no error? */ status = LUA_YIELD; /* was interrupted by an yield */ else { /* error */ StkId func = restorestack(L, ci->u2.funcidx); - L->allowhook = getoah(ci->callstatus); /* restore 'allowhook' */ + L->allowhook = getoah(ci); /* restore 'allowhook' */ func = luaF_close(L, func, status, 1); /* can yield or raise an error */ luaD_seterrorobj(L, status, func); luaD_shrinkstack(L); /* restore stack size in case of overflow */ @@ -714,20 +803,21 @@ static int finishpcallk (lua_State *L, CallInfo *ci) { */ static void finishCcall (lua_State *L, CallInfo *ci) { int n; /* actual number of results from C function */ - if (ci->callstatus & CIST_CLSRET) { /* was returning? */ - lua_assert(hastocloseCfunc(ci->nresults)); + if (ci->callstatus & CIST_CLSRET) { /* was closing TBC variable? */ + lua_assert(ci->callstatus & CIST_TBC); n = ci->u2.nres; /* just redo 'luaD_poscall' */ /* don't need to reset CIST_CLSRET, as it will be set again anyway */ } else { - int status = LUA_YIELD; /* default if there were no errors */ + TStatus status = LUA_YIELD; /* default if there were no errors */ + lua_KFunction kf = ci->u.c.k; /* continuation function */ /* must have a continuation and must be able to call it */ - lua_assert(ci->u.c.k != NULL && yieldable(L)); + lua_assert(kf != NULL && yieldable(L)); if (ci->callstatus & CIST_YPCALL) /* was inside a 'lua_pcallk'? */ status = finishpcallk(L, ci); /* finish it */ adjustresults(L, LUA_MULTRET); /* finish 'lua_callk' */ lua_unlock(L); - n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation */ + n = (*kf)(L, APIstatus(status), ci->u.c.ctx); /* call continuation */ lua_lock(L); api_checknelems(L, n); } @@ -774,6 +864,7 @@ static CallInfo *findpcall (lua_State *L) { ** coroutine error handler and should not kill the coroutine.) */ static int resume_error (lua_State *L, const char *msg, int narg) { + api_checkpop(L, narg); L->top.p -= narg; /* remove args from the stack */ setsvalue2s(L, L->top.p, luaS_new(L, msg)); /* push error message */ api_incr_top(L); @@ -828,7 +919,7 @@ static void resume (lua_State *L, void *ud) { ** (status == LUA_YIELD), or an unprotected error ('findpcall' doesn't ** find a recover point). */ -static int precover (lua_State *L, int status) { +static TStatus precover (lua_State *L, TStatus status) { CallInfo *ci; while (errorstatus(status) && (ci = findpcall(L)) != NULL) { L->ci = ci; /* go down to recovery functions */ @@ -841,7 +932,7 @@ static int precover (lua_State *L, int status) { LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, int *nresults) { - int status; + TStatus status; lua_lock(L); if (L->status == LUA_OK) { /* may be starting a coroutine */ if (L->ci != &L->base_ci) /* not in base level? */ @@ -856,21 +947,21 @@ LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs, return resume_error(L, "C stack overflow", nargs); L->nCcalls++; luai_userstateresume(L, nargs); - api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + api_checkpop(L, (L->status == LUA_OK) ? nargs + 1 : nargs); status = luaD_rawrunprotected(L, resume, &nargs); /* continue running after recoverable errors */ status = precover(L, status); if (l_likely(!errorstatus(status))) lua_assert(status == L->status); /* normal end or yield */ else { /* unrecoverable error */ - L->status = cast_byte(status); /* mark thread as 'dead' */ + L->status = status; /* mark thread as 'dead' */ luaD_seterrorobj(L, status, L->top.p); /* push error message */ L->ci->top.p = L->top.p; } *nresults = (status == LUA_YIELD) ? L->ci->u2.nyield : cast_int(L->top.p - (L->ci->func.p + 1)); lua_unlock(L); - return status; + return APIstatus(status); } @@ -885,9 +976,9 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, luai_userstateyield(L, nresults); lua_lock(L); ci = L->ci; - api_checknelems(L, nresults); + api_checkpop(L, nresults); if (l_unlikely(!yieldable(L))) { - if (L != G(L)->mainthread) + if (L != mainthread(G(L))) luaG_runerror(L, "attempt to yield across a C-call boundary"); else luaG_runerror(L, "attempt to yield from outside a coroutine"); @@ -915,7 +1006,7 @@ LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, */ struct CloseP { StkId level; - int status; + TStatus status; }; @@ -932,7 +1023,7 @@ static void closepaux (lua_State *L, void *ud) { ** Calls 'luaF_close' in protected mode. Return the original status ** or, in case of errors, the new status. */ -int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { +TStatus luaD_closeprotected (lua_State *L, ptrdiff_t level, TStatus status) { CallInfo *old_ci = L->ci; lu_byte old_allowhooks = L->allowhook; for (;;) { /* keep closing upvalues until no more errors */ @@ -954,9 +1045,9 @@ int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status) { ** thread information ('allowhook', etc.) and in particular ** its stack level in case of errors. */ -int luaD_pcall (lua_State *L, Pfunc func, void *u, - ptrdiff_t old_top, ptrdiff_t ef) { - int status; +TStatus luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t old_top, + ptrdiff_t ef) { + TStatus status; CallInfo *old_ci = L->ci; lu_byte old_allowhooks = L->allowhook; ptrdiff_t old_errfunc = L->errfunc; @@ -988,7 +1079,7 @@ struct SParser { /* data to 'f_parser' */ static void checkmode (lua_State *L, const char *mode, const char *x) { - if (mode && strchr(mode, x[0]) == NULL) { + if (strchr(mode, x[0]) == NULL) { luaO_pushfstring(L, "attempt to load a %s chunk (mode is '%s')", x, mode); luaD_throw(L, LUA_ERRSYNTAX); @@ -999,13 +1090,18 @@ static void checkmode (lua_State *L, const char *mode, const char *x) { static void f_parser (lua_State *L, void *ud) { LClosure *cl; struct SParser *p = cast(struct SParser *, ud); + const char *mode = p->mode ? p->mode : "bt"; int c = zgetc(p->z); /* read first character */ if (c == LUA_SIGNATURE[0]) { - checkmode(L, p->mode, "binary"); - cl = luaU_undump(L, p->z, p->name); + int fixed = 0; + if (strchr(mode, 'B') != NULL) + fixed = 1; + else + checkmode(L, mode, "binary"); + cl = luaU_undump(L, p->z, p->name, fixed); } else { - checkmode(L, p->mode, "text"); + checkmode(L, mode, "text"); cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); } lua_assert(cl->nupvalues == cl->p->sizeupvalues); @@ -1013,10 +1109,10 @@ static void f_parser (lua_State *L, void *ud) { } -int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, - const char *mode) { +TStatus luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { struct SParser p; - int status; + TStatus status; incnny(L); /* cannot yield during parsing */ p.z = z; p.name = name; p.mode = mode; p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; @@ -1025,9 +1121,9 @@ int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, luaZ_initbuffer(L, &p.buff); status = luaD_pcall(L, f_parser, &p, savestack(L, L->top.p), L->errfunc); luaZ_freebuffer(L, &p.buff); - luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); - luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); - luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + luaM_freearray(L, p.dyd.actvar.arr, cast_sizet(p.dyd.actvar.size)); + luaM_freearray(L, p.dyd.gt.arr, cast_sizet(p.dyd.gt.size)); + luaM_freearray(L, p.dyd.label.arr, cast_sizet(p.dyd.label.size)); decnny(L); return status; } diff --git a/3rdparty/lua/plainlua/ldo.h b/3rdparty/lua/plainlua/ldo.h index 4de9540ec807..2d4ca8be4679 100644 --- a/3rdparty/lua/plainlua/ldo.h +++ b/3rdparty/lua/plainlua/ldo.h @@ -23,10 +23,19 @@ ** 'condmovestack' is used in heavy tests to force a stack reallocation ** at every check. */ + +#if !defined(HARDSTACKTESTS) +#define condmovestack(L,pre,pos) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L,pre,pos) \ + { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } +#endif + #define luaD_checkstackaux(L,n,pre,pos) \ if (l_unlikely(L->stack_last.p - L->top.p <= (n))) \ { pre; luaD_growstack(L, n, 1); pos; } \ - else { condmovestack(L,pre,pos); } + else { condmovestack(L,pre,pos); } /* In general, 'pre'/'pos' are empty (nothing to save) */ #define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) @@ -44,25 +53,24 @@ p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ -/* macro to check stack size and GC, preserving 'p' */ -#define checkstackGCp(L,n,p) \ - luaD_checkstackaux(L, n, \ - ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ - luaC_checkGC(L), /* stack grow uses memory */ \ - p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ - - -/* macro to check stack size and GC */ -#define checkstackGC(L,fsize) \ - luaD_checkstackaux(L, (fsize), luaC_checkGC(L), (void)0) +/* +** Maximum depth for nested C calls, syntactical nested non-terminals, +** and other features implemented through recursion in C. (Value must +** fit in a 16-bit unsigned integer. It must also be compatible with +** the size of the C stack.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif /* type of protected functions, to be ran by 'runprotected' */ typedef void (*Pfunc) (lua_State *L, void *ud); LUAI_FUNC l_noret luaD_errerr (lua_State *L); -LUAI_FUNC void luaD_seterrorobj (lua_State *L, int errcode, StkId oldtop); -LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, +LUAI_FUNC void luaD_seterrorobj (lua_State *L, TStatus errcode, StkId oldtop); +LUAI_FUNC TStatus luaD_protectedparser (lua_State *L, ZIO *z, + const char *name, const char *mode); LUAI_FUNC void luaD_hook (lua_State *L, int event, int line, int fTransfer, int nTransfer); @@ -72,8 +80,9 @@ LUAI_FUNC int luaD_pretailcall (lua_State *L, CallInfo *ci, StkId func, LUAI_FUNC CallInfo *luaD_precall (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); -LUAI_FUNC int luaD_closeprotected (lua_State *L, ptrdiff_t level, int status); -LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, +LUAI_FUNC TStatus luaD_closeprotected (lua_State *L, ptrdiff_t level, + TStatus status); +LUAI_FUNC TStatus luaD_pcall (lua_State *L, Pfunc func, void *u, ptrdiff_t oldtop, ptrdiff_t ef); LUAI_FUNC void luaD_poscall (lua_State *L, CallInfo *ci, int nres); LUAI_FUNC int luaD_reallocstack (lua_State *L, int newsize, int raiseerror); @@ -81,8 +90,9 @@ LUAI_FUNC int luaD_growstack (lua_State *L, int n, int raiseerror); LUAI_FUNC void luaD_shrinkstack (lua_State *L); LUAI_FUNC void luaD_inctop (lua_State *L); -LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); -LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); +LUAI_FUNC l_noret luaD_throw (lua_State *L, TStatus errcode); +LUAI_FUNC l_noret luaD_throwbaselevel (lua_State *L, TStatus errcode); +LUAI_FUNC TStatus luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); #endif diff --git a/3rdparty/lua/plainlua/ldump.c b/3rdparty/lua/plainlua/ldump.c index f231691b7795..a75b20d247c0 100644 --- a/3rdparty/lua/plainlua/ldump.c +++ b/3rdparty/lua/plainlua/ldump.c @@ -15,8 +15,11 @@ #include "lua.h" +#include "lapi.h" +#include "lgc.h" #include "lobject.h" #include "lstate.h" +#include "ltable.h" #include "lundump.h" @@ -24,8 +27,11 @@ typedef struct { lua_State *L; lua_Writer writer; void *data; + size_t offset; /* current position relative to beginning of dump */ int strip; int status; + Table *h; /* table to track saved strings */ + lua_Unsigned nstr; /* counter for counting saved strings */ } DumpState; @@ -38,12 +44,33 @@ typedef struct { #define dumpLiteral(D, s) dumpBlock(D,s,sizeof(s) - sizeof(char)) +/* +** Dump the block of memory pointed by 'b' with given 'size'. +** 'b' should not be NULL, except for the last call signaling the end +** of the dump. +*/ static void dumpBlock (DumpState *D, const void *b, size_t size) { - if (D->status == 0 && size > 0) { + if (D->status == 0) { /* do not write anything after an error */ lua_unlock(D->L); D->status = (*D->writer)(D->L, b, size, D->data); lua_lock(D->L); + D->offset += size; + } +} + + +/* +** Dump enough zeros to ensure that current position is a multiple of +** 'align'. +*/ +static void dumpAlign (DumpState *D, unsigned align) { + unsigned padding = align - cast_uint(D->offset % align); + if (padding < align) { /* padding == align means no padding */ + static lua_Integer paddingContent = 0; + lua_assert(align <= sizeof(lua_Integer)); + dumpBlock(D, &paddingContent, padding); } + lua_assert(D->offset % align == 0); } @@ -57,25 +84,32 @@ static void dumpByte (DumpState *D, int y) { /* -** 'dumpSize' buffer size: each byte can store up to 7 bits. (The "+6" -** rounds up the division.) +** size for 'dumpVarint' buffer: each byte can store up to 7 bits. +** (The "+6" rounds up the division.) */ -#define DIBS ((sizeof(size_t) * CHAR_BIT + 6) / 7) +#define DIBS ((l_numbits(lua_Unsigned) + 6) / 7) -static void dumpSize (DumpState *D, size_t x) { +/* +** Dumps an unsigned integer using the MSB Varint encoding +*/ +static void dumpVarint (DumpState *D, lua_Unsigned x) { lu_byte buff[DIBS]; - int n = 0; - do { - buff[DIBS - (++n)] = x & 0x7f; /* fill buffer in reverse order */ - x >>= 7; - } while (x != 0); - buff[DIBS - 1] |= 0x80; /* mark last byte */ + unsigned n = 1; + buff[DIBS - 1] = x & 0x7f; /* fill least-significant byte */ + while ((x >>= 7) != 0) /* fill other bytes in reverse order */ + buff[DIBS - (++n)] = cast_byte((x & 0x7f) | 0x80); dumpVector(D, buff + DIBS - n, n); } +static void dumpSize (DumpState *D, size_t sz) { + dumpVarint(D, cast(lua_Unsigned, sz)); +} + + static void dumpInt (DumpState *D, int x) { - dumpSize(D, x); + lua_assert(x >= 0); + dumpVarint(D, cast_uint(x)); } @@ -84,30 +118,61 @@ static void dumpNumber (DumpState *D, lua_Number x) { } +/* +** Signed integers are coded to keep small values small. (Coding -1 as +** 0xfff...fff would use too many bytes to save a quite common value.) +** A non-negative x is coded as 2x; a negative x is coded as -2x - 1. +** (0 => 0; -1 => 1; 1 => 2; -2 => 3; 2 => 4; ...) +*/ static void dumpInteger (DumpState *D, lua_Integer x) { - dumpVar(D, x); + lua_Unsigned cx = (x >= 0) ? 2u * l_castS2U(x) + : (2u * ~l_castS2U(x)) + 1; + dumpVarint(D, cx); } -static void dumpString (DumpState *D, const TString *s) { - if (s == NULL) +/* +** Dump a String. First dump its "size": size==0 means NULL; +** size==1 is followed by an index and means "reuse saved string with +** that index"; size>=2 is followed by the string contents with real +** size==size-2 and means that string, which will be saved with +** the next available index. +*/ +static void dumpString (DumpState *D, TString *ts) { + if (ts == NULL) dumpSize(D, 0); else { - size_t size = tsslen(s); - const char *str = getstr(s); - dumpSize(D, size + 1); - dumpVector(D, str, size); + TValue idx; + int tag = luaH_getstr(D->h, ts, &idx); + if (!tagisempty(tag)) { /* string already saved? */ + dumpVarint(D, 1); /* reuse a saved string */ + dumpVarint(D, l_castS2U(ivalue(&idx))); /* index of saved string */ + } + else { /* must write and save the string */ + TValue key, value; /* to save the string in the hash */ + size_t size; + const char *s = getlstr(ts, size); + dumpSize(D, size + 2); + dumpVector(D, s, size + 1); /* include ending '\0' */ + D->nstr++; /* one more saved string */ + setsvalue(D->L, &key, ts); /* the string is the key */ + setivalue(&value, l_castU2S(D->nstr)); /* its index is the value */ + luaH_set(D->L, D->h, &key, &value); /* h[ts] = nstr */ + /* integer value does not need barrier */ + } } } static void dumpCode (DumpState *D, const Proto *f) { dumpInt(D, f->sizecode); - dumpVector(D, f->code, f->sizecode); + dumpAlign(D, sizeof(f->code[0])); + lua_assert(f->code != NULL); + dumpVector(D, f->code, cast_uint(f->sizecode)); } -static void dumpFunction(DumpState *D, const Proto *f, TString *psource); +static void dumpFunction (DumpState *D, const Proto *f); static void dumpConstants (DumpState *D, const Proto *f) { int i; @@ -140,7 +205,7 @@ static void dumpProtos (DumpState *D, const Proto *f) { int n = f->sizep; dumpInt(D, n); for (i = 0; i < n; i++) - dumpFunction(D, f->p[i], f->source); + dumpFunction(D, f->p[i]); } @@ -159,12 +224,14 @@ static void dumpDebug (DumpState *D, const Proto *f) { int i, n; n = (D->strip) ? 0 : f->sizelineinfo; dumpInt(D, n); - dumpVector(D, f->lineinfo, n); + if (f->lineinfo != NULL) + dumpVector(D, f->lineinfo, cast_uint(n)); n = (D->strip) ? 0 : f->sizeabslineinfo; dumpInt(D, n); - for (i = 0; i < n; i++) { - dumpInt(D, f->abslineinfo[i].pc); - dumpInt(D, f->abslineinfo[i].line); + if (n > 0) { + /* 'abslineinfo' is an array of structures of int's */ + dumpAlign(D, sizeof(int)); + dumpVector(D, f->abslineinfo, cast_uint(n)); } n = (D->strip) ? 0 : f->sizelocvars; dumpInt(D, n); @@ -180,51 +247,57 @@ static void dumpDebug (DumpState *D, const Proto *f) { } -static void dumpFunction (DumpState *D, const Proto *f, TString *psource) { - if (D->strip || f->source == psource) - dumpString(D, NULL); /* no debug info or same source as its parent */ - else - dumpString(D, f->source); +static void dumpFunction (DumpState *D, const Proto *f) { dumpInt(D, f->linedefined); dumpInt(D, f->lastlinedefined); dumpByte(D, f->numparams); - dumpByte(D, f->is_vararg); + dumpByte(D, f->flag); dumpByte(D, f->maxstacksize); dumpCode(D, f); dumpConstants(D, f); dumpUpvalues(D, f); dumpProtos(D, f); + dumpString(D, D->strip ? NULL : f->source); dumpDebug(D, f); } +#define dumpNumInfo(D, tvar, value) \ + { tvar i = value; dumpByte(D, sizeof(tvar)); dumpVar(D, i); } + + static void dumpHeader (DumpState *D) { dumpLiteral(D, LUA_SIGNATURE); dumpByte(D, LUAC_VERSION); dumpByte(D, LUAC_FORMAT); dumpLiteral(D, LUAC_DATA); - dumpByte(D, sizeof(Instruction)); - dumpByte(D, sizeof(lua_Integer)); - dumpByte(D, sizeof(lua_Number)); - dumpInteger(D, LUAC_INT); - dumpNumber(D, LUAC_NUM); + dumpNumInfo(D, int, LUAC_INT); + dumpNumInfo(D, Instruction, LUAC_INST); + dumpNumInfo(D, lua_Integer, LUAC_INT); + dumpNumInfo(D, lua_Number, LUAC_NUM); } /* ** dump Lua function as precompiled chunk */ -int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, - int strip) { +int luaU_dump (lua_State *L, const Proto *f, lua_Writer w, void *data, + int strip) { DumpState D; + D.h = luaH_new(L); /* aux. table to keep strings already dumped */ + sethvalue2s(L, L->top.p, D.h); /* anchor it */ + L->top.p++; D.L = L; D.writer = w; + D.offset = 0; D.data = data; D.strip = strip; D.status = 0; + D.nstr = 0; dumpHeader(&D); dumpByte(&D, f->sizeupvalues); - dumpFunction(&D, f, NULL); + dumpFunction(&D, f); + dumpBlock(&D, NULL, 0); /* signal end of dump */ return D.status; } diff --git a/3rdparty/lua/plainlua/lfunc.c b/3rdparty/lua/plainlua/lfunc.c index 0945f241de2d..da7c62397447 100644 --- a/3rdparty/lua/plainlua/lfunc.c +++ b/3rdparty/lua/plainlua/lfunc.c @@ -100,21 +100,23 @@ UpVal *luaF_findupval (lua_State *L, StkId level) { /* -** Call closing method for object 'obj' with error message 'err'. The +** Call closing method for object 'obj' with error object 'err'. The ** boolean 'yy' controls whether the call is yieldable. ** (This function assumes EXTRA_STACK.) */ static void callclosemethod (lua_State *L, TValue *obj, TValue *err, int yy) { StkId top = L->top.p; + StkId func = top; const TValue *tm = luaT_gettmbyobj(L, obj, TM_CLOSE); - setobj2s(L, top, tm); /* will call metamethod... */ - setobj2s(L, top + 1, obj); /* with 'self' as the 1st argument */ - setobj2s(L, top + 2, err); /* and error msg. as 2nd argument */ - L->top.p = top + 3; /* add function and arguments */ + setobj2s(L, top++, tm); /* will call metamethod... */ + setobj2s(L, top++, obj); /* with 'self' as the 1st argument */ + if (err != NULL) /* if there was an error... */ + setobj2s(L, top++, err); /* then error object will be 2nd argument */ + L->top.p = top; /* add function and arguments */ if (yy) - luaD_call(L, top, 0); + luaD_call(L, func, 0); else - luaD_callnoyield(L, top, 0); + luaD_callnoyield(L, func, 0); } @@ -140,26 +142,28 @@ static void checkclosemth (lua_State *L, StkId level) { ** the 'level' of the upvalue being closed, as everything after that ** won't be used again. */ -static void prepcallclosemth (lua_State *L, StkId level, int status, int yy) { +static void prepcallclosemth (lua_State *L, StkId level, TStatus status, + int yy) { TValue *uv = s2v(level); /* value being closed */ TValue *errobj; - if (status == CLOSEKTOP) - errobj = &G(L)->nilvalue; /* error object is nil */ - else { /* 'luaD_seterrorobj' will set top to level + 2 */ - errobj = s2v(level + 1); /* error object goes after 'uv' */ - luaD_seterrorobj(L, status, level + 1); /* set error object */ + switch (status) { + case LUA_OK: + L->top.p = level + 1; /* call will be at this level */ + /* FALLTHROUGH */ + case CLOSEKTOP: /* don't need to change top */ + errobj = NULL; /* no error object */ + break; + default: /* 'luaD_seterrorobj' will set top to level + 2 */ + errobj = s2v(level + 1); /* error object goes after 'uv' */ + luaD_seterrorobj(L, status, level + 1); /* set error object */ + break; } callclosemethod(L, uv, errobj, yy); } -/* -** Maximum value for deltas in 'tbclist', dependent on the type -** of delta. (This macro assumes that an 'L' is in scope where it -** is used.) -*/ -#define MAXDELTA \ - ((256ul << ((sizeof(L->stack.p->tbclist.delta) - 1) * 8)) - 1) +/* Maximum value for deltas in 'tbclist' */ +#define MAXDELTA USHRT_MAX /* @@ -224,7 +228,7 @@ static void poptbclist (lua_State *L) { ** Close all upvalues and to-be-closed variables up to the given stack ** level. Return restored 'level'. */ -StkId luaF_close (lua_State *L, StkId level, int status, int yy) { +StkId luaF_close (lua_State *L, StkId level, TStatus status, int yy) { ptrdiff_t levelrel = savestack(L, level); luaF_closeupval(L, level); /* first, close the upvalues */ while (L->tbclist.p >= level) { /* traverse tbc's down to that level */ @@ -253,7 +257,7 @@ Proto *luaF_newproto (lua_State *L) { f->upvalues = NULL; f->sizeupvalues = 0; f->numparams = 0; - f->is_vararg = 0; + f->flag = 0; f->maxstacksize = 0; f->locvars = NULL; f->sizelocvars = 0; @@ -264,14 +268,31 @@ Proto *luaF_newproto (lua_State *L) { } +lu_mem luaF_protosize (Proto *p) { + lu_mem sz = cast(lu_mem, sizeof(Proto)) + + cast_uint(p->sizep) * sizeof(Proto*) + + cast_uint(p->sizek) * sizeof(TValue) + + cast_uint(p->sizelocvars) * sizeof(LocVar) + + cast_uint(p->sizeupvalues) * sizeof(Upvaldesc); + if (!(p->flag & PF_FIXED)) { + sz += cast_uint(p->sizecode) * sizeof(Instruction); + sz += cast_uint(p->sizelineinfo) * sizeof(lu_byte); + sz += cast_uint(p->sizeabslineinfo) * sizeof(AbsLineInfo); + } + return sz; +} + + void luaF_freeproto (lua_State *L, Proto *f) { - luaM_freearray(L, f->code, f->sizecode); - luaM_freearray(L, f->p, f->sizep); - luaM_freearray(L, f->k, f->sizek); - luaM_freearray(L, f->lineinfo, f->sizelineinfo); - luaM_freearray(L, f->abslineinfo, f->sizeabslineinfo); - luaM_freearray(L, f->locvars, f->sizelocvars); - luaM_freearray(L, f->upvalues, f->sizeupvalues); + if (!(f->flag & PF_FIXED)) { + luaM_freearray(L, f->code, cast_sizet(f->sizecode)); + luaM_freearray(L, f->lineinfo, cast_sizet(f->sizelineinfo)); + luaM_freearray(L, f->abslineinfo, cast_sizet(f->sizeabslineinfo)); + } + luaM_freearray(L, f->p, cast_sizet(f->sizep)); + luaM_freearray(L, f->k, cast_sizet(f->sizek)); + luaM_freearray(L, f->locvars, cast_sizet(f->sizelocvars)); + luaM_freearray(L, f->upvalues, cast_sizet(f->sizeupvalues)); luaM_free(L, f); } diff --git a/3rdparty/lua/plainlua/lfunc.h b/3rdparty/lua/plainlua/lfunc.h index 3be265efb584..d6aad3a6df18 100644 --- a/3rdparty/lua/plainlua/lfunc.h +++ b/3rdparty/lua/plainlua/lfunc.h @@ -11,11 +11,11 @@ #include "lobject.h" -#define sizeCclosure(n) (cast_int(offsetof(CClosure, upvalue)) + \ - cast_int(sizeof(TValue)) * (n)) +#define sizeCclosure(n) \ + (offsetof(CClosure, upvalue) + sizeof(TValue) * cast_uint(n)) -#define sizeLclosure(n) (cast_int(offsetof(LClosure, upvals)) + \ - cast_int(sizeof(TValue *)) * (n)) +#define sizeLclosure(n) \ + (offsetof(LClosure, upvals) + sizeof(UpVal *) * cast_uint(n)) /* test whether thread is in 'twups' list */ @@ -44,7 +44,7 @@ /* special status to close upvalues preserving the top of the stack */ -#define CLOSEKTOP (-1) +#define CLOSEKTOP (LUA_ERRERR + 1) LUAI_FUNC Proto *luaF_newproto (lua_State *L); @@ -54,8 +54,9 @@ LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); LUAI_FUNC void luaF_newtbcupval (lua_State *L, StkId level); LUAI_FUNC void luaF_closeupval (lua_State *L, StkId level); -LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, int status, int yy); +LUAI_FUNC StkId luaF_close (lua_State *L, StkId level, TStatus status, int yy); LUAI_FUNC void luaF_unlinkupval (UpVal *uv); +LUAI_FUNC lu_mem luaF_protosize (Proto *p); LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, int pc); diff --git a/3rdparty/lua/plainlua/lgc.c b/3rdparty/lua/plainlua/lgc.c index 5817f9eec35a..bbaa5ff7e1b4 100644 --- a/3rdparty/lua/plainlua/lgc.c +++ b/3rdparty/lua/plainlua/lgc.c @@ -9,7 +9,6 @@ #include "lprefix.h" -#include #include @@ -32,32 +31,13 @@ ** (Large enough to dissipate fixed overheads but small enough ** to allow small steps for the collector.) */ -#define GCSWEEPMAX 100 - -/* -** Maximum number of finalizers to call in each single step. -*/ -#define GCFINMAX 10 - - -/* -** Cost of calling one finalizer. -*/ -#define GCFINALIZECOST 50 - - -/* -** The equivalent, in bytes, of one unit of "work" (visiting a slot, -** sweeping an object, etc.) -*/ -#define WORK2MEM sizeof(TValue) +#define GCSWEEPMAX 20 /* -** macro to adjust 'pause': 'pause' is actually used like -** 'pause / PAUSEADJ' (value chosen by tests) +** Cost (in work units) of running one finalizer. */ -#define PAUSEADJ 100 +#define CWUFIN 10 /* mask with all color bits */ @@ -91,7 +71,14 @@ #define gcvalueN(o) (iscollectable(o) ? gcvalue(o) : NULL) -#define markvalue(g,o) { checkliveness(g->mainthread,o); \ +/* +** Access to collectable objects in array part of tables +*/ +#define gcvalarr(t,i) \ + ((*getArrTag(t,i) & BIT_ISCOLLECTABLE) ? getArrVal(t,i)->gc : NULL) + + +#define markvalue(g,o) { checkliveness(mainthread(g),o); \ if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } #define markkey(g, n) { if keyiswhite(n) reallymarkobject(g,gckey(n)); } @@ -104,8 +91,9 @@ */ #define markobjectN(g,t) { if (t) markobject(g,t); } + static void reallymarkobject (global_State *g, GCObject *o); -static lu_mem atomic (lua_State *L); +static void atomic (lua_State *L); static void entersweep (lua_State *L); @@ -122,6 +110,56 @@ static void entersweep (lua_State *L); #define gnodelast(h) gnode(h, cast_sizet(sizenode(h))) +static l_mem objsize (GCObject *o) { + lu_mem res; + switch (o->tt) { + case LUA_VTABLE: { + res = luaH_size(gco2t(o)); + break; + } + case LUA_VLCL: { + LClosure *cl = gco2lcl(o); + res = sizeLclosure(cl->nupvalues); + break; + } + case LUA_VCCL: { + CClosure *cl = gco2ccl(o); + res = sizeCclosure(cl->nupvalues); + break; + } + case LUA_VUSERDATA: { + Udata *u = gco2u(o); + res = sizeudata(u->nuvalue, u->len); + break; + } + case LUA_VPROTO: { + res = luaF_protosize(gco2p(o)); + break; + } + case LUA_VTHREAD: { + res = luaE_threadsize(gco2th(o)); + break; + } + case LUA_VSHRSTR: { + TString *ts = gco2ts(o); + res = sizestrshr(cast_uint(ts->shrlen)); + break; + } + case LUA_VLNGSTR: { + TString *ts = gco2ts(o); + res = luaS_sizelngstr(ts->u.lnglen, ts->shrlen); + break; + } + case LUA_VUPVAL: { + res = sizeof(UpVal); + break; + } + default: res = 0; lua_assert(0); + } + return cast(l_mem, res); +} + + static GCObject **getgclist (GCObject *o) { switch (o->tt) { case LUA_VTABLE: return &gco2t(o)->gclist; @@ -203,7 +241,7 @@ static int iscleared (global_State *g, const GCObject *o) { ** incremental sweep phase, it clears the black object to white (sweep ** it) to avoid other barrier calls for this same object. (That cannot ** be done is generational mode, as its sweep does not distinguish -** whites from deads.) +** white from dead.) */ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { global_State *g = G(L); @@ -217,7 +255,7 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { } else { /* sweep phase */ lua_assert(issweepphase(g)); - if (g->gckind == KGC_INC) /* incremental mode? */ + if (g->gckind != KGC_GENMINOR) /* incremental mode? */ makewhite(g, o); /* mark 'o' as white to avoid other barriers */ } } @@ -230,7 +268,8 @@ void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { void luaC_barrierback_ (lua_State *L, GCObject *o) { global_State *g = G(L); lua_assert(isblack(o) && !isdead(g, o)); - lua_assert((g->gckind == KGC_GEN) == (isold(o) && getage(o) != G_TOUCHED1)); + lua_assert((g->gckind != KGC_GENMINOR) + || (isold(o) && getage(o) != G_TOUCHED1)); if (getage(o) == G_TOUCHED2) /* already in gray list? */ set2gray(o); /* make it gray to become touched1 */ else /* link it in 'grayagain' and paint it gray */ @@ -255,7 +294,7 @@ void luaC_fix (lua_State *L, GCObject *o) { ** create a new collectable object (with given type, size, and offset) ** and link it to 'allgc' list. */ -GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { +GCObject *luaC_newobjdt (lua_State *L, lu_byte tt, size_t sz, size_t offset) { global_State *g = G(L); char *p = cast_charp(luaM_newobject(L, novariant(tt), sz)); GCObject *o = cast(GCObject *, p + offset); @@ -267,7 +306,10 @@ GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, size_t offset) { } -GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { +/* +** create a new collectable object with no offset. +*/ +GCObject *luaC_newobj (lua_State *L, lu_byte tt, size_t sz) { return luaC_newobjdt(L, tt, sz, 0); } @@ -295,6 +337,7 @@ GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { ** (only closures can), and a userdata's metatable must be a table. */ static void reallymarkobject (global_State *g, GCObject *o) { + g->GCmarked += objsize(o); switch (o->tt) { case LUA_VSHRSTR: case LUA_VLNGSTR: { @@ -334,7 +377,7 @@ static void reallymarkobject (global_State *g, GCObject *o) { */ static void markmt (global_State *g) { int i; - for (i=0; i < LUA_NUMTAGS; i++) + for (i=0; i < LUA_NUMTYPES; i++) markobjectN(g, g->mt[i]); } @@ -342,14 +385,10 @@ static void markmt (global_State *g) { /* ** mark all objects in list of being-finalized */ -static lu_mem markbeingfnz (global_State *g) { +static void markbeingfnz (global_State *g) { GCObject *o; - lu_mem count = 0; - for (o = g->tobefnz; o != NULL; o = o->next) { - count++; + for (o = g->tobefnz; o != NULL; o = o->next) markobject(g, o); - } - return count; } @@ -364,12 +403,10 @@ static lu_mem markbeingfnz (global_State *g) { ** upvalues, as they have nothing to be checked. (If the thread gets an ** upvalue later, it will be linked in the list again.) */ -static int remarkupvals (global_State *g) { +static void remarkupvals (global_State *g) { lua_State *thread; lua_State **p = &g->twups; - int work = 0; /* estimate of how much work was done here */ while ((thread = *p) != NULL) { - work++; if (!iswhite(thread) && thread->openupval != NULL) p = &thread->twups; /* keep marked thread with upvalues in the list */ else { /* thread is not marked or without upvalues */ @@ -379,7 +416,6 @@ static int remarkupvals (global_State *g) { thread->twups = thread; /* mark that it is out of list */ for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { lua_assert(getage(uv) <= getage(thread)); - work++; if (!iswhite(uv)) { /* upvalue already visited? */ lua_assert(upisopen(uv) && isgray(uv)); markvalue(g, uv->v.p); /* mark its value */ @@ -387,7 +423,6 @@ static int remarkupvals (global_State *g) { } } } - return work; } @@ -398,11 +433,14 @@ static void cleargraylists (global_State *g) { /* -** mark root set and reset all gray lists, to start a new collection +** mark root set and reset all gray lists, to start a new collection. +** 'GCmarked' is initialized to count the total number of live bytes +** during a cycle. */ static void restartcollection (global_State *g) { cleargraylists(g); - markobject(g, g->mainthread); + g->GCmarked = 0; + markobject(g, mainthread(g)); markvalue(g, &g->l_registry); markmt(g); markbeingfnz(g); /* mark any finalizing object left from previous cycle */ @@ -426,6 +464,8 @@ static void restartcollection (global_State *g) { ** TOUCHED1 objects need to be in the list. TOUCHED2 doesn't need to go ** back to a gray list, but then it must become OLD. (That is what ** 'correctgraylist' does when it finds a TOUCHED2 object.) +** This function is a no-op in incremental mode, as objects cannot be +** marked as touched in that mode. */ static void genlink (global_State *g, GCObject *o) { lua_assert(isblack(o)); @@ -433,7 +473,7 @@ static void genlink (global_State *g, GCObject *o) { linkobjgclist(o, g->grayagain); /* link it back in 'grayagain' */ } /* everything else do not need to be linked back */ else if (getage(o) == G_TOUCHED2) - changeage(o, G_TOUCHED2, G_OLD); /* advance age */ + setage(o, G_OLD); /* advance age */ } @@ -441,13 +481,14 @@ static void genlink (global_State *g, GCObject *o) { ** Traverse a table with weak values and link it to proper list. During ** propagate phase, keep it in 'grayagain' list, to be revisited in the ** atomic phase. In the atomic phase, if table has any white value, -** put it in 'weak' list, to be cleared. +** put it in 'weak' list, to be cleared; otherwise, call 'genlink' +** to check table age in generational mode. */ static void traverseweakvalue (global_State *g, Table *h) { Node *n, *limit = gnodelast(h); /* if there is array part, assume it may have white values (it is not worth traversing it now just to check) */ - int hasclears = (h->alimit > 0); + int hasclears = (h->asize > 0); for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ if (isempty(gval(n))) /* entry is empty? */ clearkey(n); /* clear its key */ @@ -458,10 +499,30 @@ static void traverseweakvalue (global_State *g, Table *h) { hasclears = 1; /* table will have to be cleared */ } } - if (g->gcstate == GCSatomic && hasclears) - linkgclist(h, g->weak); /* has to be cleared later */ - else + if (g->gcstate == GCSpropagate) linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ + else + genlink(g, obj2gco(h)); +} + + +/* +** Traverse the array part of a table. +*/ +static int traversearray (global_State *g, Table *h) { + unsigned asize = h->asize; + int marked = 0; /* true if some object is marked in this traversal */ + unsigned i; + for (i = 0; i < asize; i++) { + GCObject *o = gcvalarr(h, i); + if (o != NULL && iswhite(o)) { + marked = 1; + reallymarkobject(g, o); + } + } + return marked; } @@ -478,19 +539,11 @@ static void traverseweakvalue (global_State *g, Table *h) { ** by 'genlink'. */ static int traverseephemeron (global_State *g, Table *h, int inv) { - int marked = 0; /* true if an object is marked in this traversal */ int hasclears = 0; /* true if table has white keys */ int hasww = 0; /* true if table has entry "white-key -> white-value" */ unsigned int i; - unsigned int asize = luaH_realasize(h); unsigned int nsize = sizenode(h); - /* traverse array part */ - for (i = 0; i < asize; i++) { - if (valiswhite(&h->array[i])) { - marked = 1; - reallymarkobject(g, gcvalue(&h->array[i])); - } - } + int marked = traversearray(g, h); /* traverse array part */ /* traverse hash part; if 'inv', traverse descending (see 'convergeephemerons') */ for (i = 0; i < nsize; i++) { @@ -522,10 +575,7 @@ static int traverseephemeron (global_State *g, Table *h, int inv) { static void traversestrongtable (global_State *g, Table *h) { Node *n, *limit = gnodelast(h); - unsigned int i; - unsigned int asize = luaH_realasize(h); - for (i = 0; i < asize; i++) /* traverse array part */ - markvalue(g, &h->array[i]); + traversearray(g, h); for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ if (isempty(gval(n))) /* entry is empty? */ clearkey(n); /* clear its key */ @@ -539,30 +589,46 @@ static void traversestrongtable (global_State *g, Table *h) { } -static lu_mem traversetable (global_State *g, Table *h) { - const char *weakkey, *weakvalue; +/* +** (result & 1) iff weak values; (result & 2) iff weak keys. +*/ +static int getmode (global_State *g, Table *h) { const TValue *mode = gfasttm(g, h->metatable, TM_MODE); - TString *smode; + if (mode == NULL || !ttisshrstring(mode)) + return 0; /* ignore non-(short)string modes */ + else { + const char *smode = getshrstr(tsvalue(mode)); + const char *weakkey = strchr(smode, 'k'); + const char *weakvalue = strchr(smode, 'v'); + return ((weakkey != NULL) << 1) | (weakvalue != NULL); + } +} + + +static l_mem traversetable (global_State *g, Table *h) { markobjectN(g, h->metatable); - if (mode && ttisshrstring(mode) && /* is there a weak mode? */ - (cast_void(smode = tsvalue(mode)), - cast_void(weakkey = strchr(getshrstr(smode), 'k')), - cast_void(weakvalue = strchr(getshrstr(smode), 'v')), - (weakkey || weakvalue))) { /* is really weak? */ - if (!weakkey) /* strong keys? */ + switch (getmode(g, h)) { + case 0: /* not weak */ + traversestrongtable(g, h); + break; + case 1: /* weak values */ traverseweakvalue(g, h); - else if (!weakvalue) /* strong values? */ + break; + case 2: /* weak keys */ traverseephemeron(g, h, 0); - else /* all weak */ - linkgclist(h, g->allweak); /* nothing to traverse now */ + break; + case 3: /* all weak; nothing to traverse */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must visit again its metatable */ + else + linkgclist(h, g->allweak); /* must clear collected entries */ + break; } - else /* not weak */ - traversestrongtable(g, h); - return 1 + h->alimit + 2 * allocsizenode(h); + return 1 + 2*sizenode(h) + h->asize; } -static int traverseudata (global_State *g, Udata *u) { +static l_mem traverseudata (global_State *g, Udata *u) { int i; markobjectN(g, u->metatable); /* mark its metatable */ for (i = 0; i < u->nuvalue; i++) @@ -577,7 +643,7 @@ static int traverseudata (global_State *g, Udata *u) { ** arrays can be larger than needed; the extra slots are filled with ** NULL, so the use of 'markobjectN') */ -static int traverseproto (global_State *g, Proto *f) { +static l_mem traverseproto (global_State *g, Proto *f) { int i; markobjectN(g, f->source); for (i = 0; i < f->sizek; i++) /* mark literals */ @@ -592,7 +658,7 @@ static int traverseproto (global_State *g, Proto *f) { } -static int traverseCclosure (global_State *g, CClosure *cl) { +static l_mem traverseCclosure (global_State *g, CClosure *cl) { int i; for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ markvalue(g, &cl->upvalue[i]); @@ -603,7 +669,7 @@ static int traverseCclosure (global_State *g, CClosure *cl) { ** Traverse a Lua closure, marking its prototype and its upvalues. ** (Both can be NULL while closure is being created.) */ -static int traverseLclosure (global_State *g, LClosure *cl) { +static l_mem traverseLclosure (global_State *g, LClosure *cl) { int i; markobjectN(g, cl->p); /* mark its prototype */ for (i = 0; i < cl->nupvalues; i++) { /* visit its upvalues */ @@ -626,13 +692,13 @@ static int traverseLclosure (global_State *g, LClosure *cl) { ** (which can only happen in generational mode) or if the traverse is in ** the propagate phase (which can only happen in incremental mode). */ -static int traversethread (global_State *g, lua_State *th) { +static l_mem traversethread (global_State *g, lua_State *th) { UpVal *uv; StkId o = th->stack.p; if (isold(th) || g->gcstate == GCSpropagate) linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ if (o == NULL) - return 1; /* stack not completely built yet */ + return 0; /* stack not completely built yet */ lua_assert(g->gcstate == GCSatomic || th->openupval == NULL || isintwups(th)); for (; o < th->top.p; o++) /* mark live elements in the stack */ @@ -650,14 +716,15 @@ static int traversethread (global_State *g, lua_State *th) { g->twups = th; } } - return 1 + stacksize(th); + return 1 + (th->top.p - th->stack.p); } /* -** traverse one gray object, turning it to black. +** traverse one gray object, turning it to black. Return an estimate +** of the number of slots traversed. */ -static lu_mem propagatemark (global_State *g) { +static l_mem propagatemark (global_State *g) { GCObject *o = g->gray; nw2black(o); g->gray = *getgclist(o); /* remove from 'gray' list */ @@ -673,11 +740,9 @@ static lu_mem propagatemark (global_State *g) { } -static lu_mem propagateall (global_State *g) { - lu_mem tot = 0; +static void propagateall (global_State *g) { while (g->gray) - tot += propagatemark(g); - return tot; + propagatemark(g); } @@ -686,7 +751,6 @@ static lu_mem propagateall (global_State *g) { ** Repeat until it converges, that is, nothing new is marked. 'dir' ** inverts the direction of the traversals, trying to speed up ** convergence on chains in the same table. -** */ static void convergeephemerons (global_State *g) { int changed; @@ -746,11 +810,11 @@ static void clearbyvalues (global_State *g, GCObject *l, GCObject *f) { Table *h = gco2t(l); Node *n, *limit = gnodelast(h); unsigned int i; - unsigned int asize = luaH_realasize(h); + unsigned int asize = h->asize; for (i = 0; i < asize; i++) { - TValue *o = &h->array[i]; - if (iscleared(g, gcvalueN(o))) /* value was collected? */ - setempty(o); /* remove entry */ + GCObject *o = gcvalarr(h, i); + if (iscleared(g, o)) /* value was collected? */ + *getArrTag(h, i) = LUA_VEMPTY; /* remove entry */ } for (n = gnode(h, 0); n < limit; n++) { if (iscleared(g, gcvalueN(gval(n)))) /* unmarked value? */ @@ -770,6 +834,7 @@ static void freeupval (lua_State *L, UpVal *uv) { static void freeobj (lua_State *L, GCObject *o) { + assert_code(l_mem newmem = gettotalbytes(G(L)) - objsize(o)); switch (o->tt) { case LUA_VPROTO: luaF_freeproto(L, gco2p(o)); @@ -801,46 +866,45 @@ static void freeobj (lua_State *L, GCObject *o) { case LUA_VSHRSTR: { TString *ts = gco2ts(o); luaS_remove(L, ts); /* remove it from hash table */ - luaM_freemem(L, ts, sizelstring(ts->shrlen)); + luaM_freemem(L, ts, sizestrshr(cast_uint(ts->shrlen))); break; } case LUA_VLNGSTR: { TString *ts = gco2ts(o); - luaM_freemem(L, ts, sizelstring(ts->u.lnglen)); + if (ts->shrlen == LSTRMEM) /* must free external string? */ + (*ts->falloc)(ts->ud, ts->contents, ts->u.lnglen + 1, 0); + luaM_freemem(L, ts, luaS_sizelngstr(ts->u.lnglen, ts->shrlen)); break; } default: lua_assert(0); } + lua_assert(gettotalbytes(G(L)) == newmem); } /* ** sweep at most 'countin' elements from a list of GCObjects erasing dead ** objects, where a dead object is one marked with the old (non current) -** white; change all non-dead objects back to white, preparing for next -** collection cycle. Return where to continue the traversal or NULL if -** list is finished. ('*countout' gets the number of elements traversed.) +** white; change all non-dead objects back to white (and new), preparing +** for next collection cycle. Return where to continue the traversal or +** NULL if list is finished. */ -static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, - int *countout) { +static GCObject **sweeplist (lua_State *L, GCObject **p, l_mem countin) { global_State *g = G(L); int ow = otherwhite(g); - int i; int white = luaC_white(g); /* current white */ - for (i = 0; *p != NULL && i < countin; i++) { + while (*p != NULL && countin-- > 0) { GCObject *curr = *p; int marked = curr->marked; if (isdeadm(ow, marked)) { /* is 'curr' dead? */ *p = curr->next; /* remove 'curr' from list */ freeobj(L, curr); /* erase 'curr' */ } - else { /* change mark to 'white' */ - curr->marked = cast_byte((marked & ~maskgcbits) | white); + else { /* change mark to 'white' and age to 'new' */ + curr->marked = cast_byte((marked & ~maskgcbits) | white | G_NEW); p = &curr->next; /* go to next element */ } } - if (countout) - *countout = i; /* number of elements traversed */ return (*p == NULL) ? NULL : p; } @@ -851,7 +915,7 @@ static GCObject **sweeplist (lua_State *L, GCObject **p, int countin, static GCObject **sweeptolive (lua_State *L, GCObject **p) { GCObject **old = p; do { - p = sweeplist(L, p, 1, NULL); + p = sweeplist(L, p, 1); } while (p == old); return p; } @@ -870,11 +934,8 @@ static GCObject **sweeptolive (lua_State *L, GCObject **p) { */ static void checkSizes (lua_State *L, global_State *g) { if (!g->gcemergency) { - if (g->strt.nuse < g->strt.size / 4) { /* string table too big? */ - l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ luaS_resize(L, g->strt.size / 2); - g->GCestimate += g->GCdebt - olddebt; /* correct estimate */ - } } } @@ -912,9 +973,9 @@ static void GCTM (lua_State *L) { setgcovalue(L, &v, udata2finalize(g)); tm = luaT_gettmbyobj(L, &v, TM_GC); if (!notm(tm)) { /* is there a finalizer? */ - int status; + TStatus status; lu_byte oldah = L->allowhook; - int oldgcstp = g->gcstp; + lu_byte oldgcstp = g->gcstp; g->gcstp |= GCSTPGC; /* avoid GC steps */ L->allowhook = 0; /* stop debug hooks during GC metamethod */ setobj2s(L, L->top.p++, tm); /* push finalizer... */ @@ -932,18 +993,6 @@ static void GCTM (lua_State *L) { } -/* -** Call a few finalizers -*/ -static int runafewfinalizers (lua_State *L, int n) { - global_State *g = G(L); - int i; - for (i = 0; i < n && g->tobefnz; i++) - GCTM(L); /* call one finalizer */ - return i; -} - - /* ** call all pending finalizers */ @@ -1049,23 +1098,31 @@ void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { ** ======================================================= */ +/* +** Fields 'GCmarked' and 'GCmajorminor' are used to control the pace and +** the mode of the collector. They play several roles, depending on the +** mode of the collector: +** * KGC_INC: +** GCmarked: number of marked bytes during a cycle. +** GCmajorminor: not used. +** * KGC_GENMINOR +** GCmarked: number of bytes that became old since last major collection. +** GCmajorminor: number of bytes marked in last major collection. +** * KGC_GENMAJOR +** GCmarked: number of bytes that became old since last major collection. +** GCmajorminor: number of bytes marked in last major collection. +*/ + /* -** Set the "time" to wait before starting a new GC cycle; cycle will -** start when memory use hits the threshold of ('estimate' * pause / -** PAUSEADJ). (Division by 'estimate' should be OK: it cannot be zero, -** because Lua cannot even start with less than PAUSEADJ bytes). +** Set the "time" to wait before starting a new incremental cycle; +** cycle will start when number of bytes in use hits the threshold of +** approximately (marked * pause / 100). */ static void setpause (global_State *g) { - l_mem threshold, debt; - int pause = getgcparam(g->gcpause); - l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ - lua_assert(estimate > 0); - threshold = (pause < MAX_LMEM / estimate) /* overflow? */ - ? estimate * pause /* no overflow */ - : MAX_LMEM; /* overflow; truncate to maximum */ - debt = gettotalbytes(g) - threshold; - if (debt > 0) debt = 0; + l_mem threshold = applygcparam(g, PAUSE, g->GCmarked); + l_mem debt = threshold - gettotalbytes(g); + if (debt < 0) debt = 0; luaE_setdebt(g, debt); } @@ -1113,7 +1170,8 @@ static void sweep2old (lua_State *L, GCObject **p) { ** will also remove objects turned white here from any gray list. */ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, - GCObject *limit, GCObject **pfirstold1) { + GCObject *limit, GCObject **pfirstold1, + l_mem *paddedold) { static const lu_byte nextage[] = { G_SURVIVAL, /* from G_NEW */ G_OLD1, /* from G_SURVIVAL */ @@ -1123,6 +1181,7 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, G_TOUCHED1, /* from G_TOUCHED1 (do not change) */ G_TOUCHED2 /* from G_TOUCHED2 (do not change) */ }; + l_mem addedold = 0; int white = luaC_white(g); GCObject *curr; while ((curr = *p) != limit) { @@ -1132,42 +1191,38 @@ static GCObject **sweepgen (lua_State *L, global_State *g, GCObject **p, freeobj(L, curr); /* erase 'curr' */ } else { /* correct mark and age */ - if (getage(curr) == G_NEW) { /* new objects go back to white */ + int age = getage(curr); + if (age == G_NEW) { /* new objects go back to white */ int marked = curr->marked & ~maskgcbits; /* erase GC bits */ curr->marked = cast_byte(marked | G_SURVIVAL | white); } else { /* all other objects will be old, and so keep their color */ - setage(curr, nextage[getage(curr)]); - if (getage(curr) == G_OLD1 && *pfirstold1 == NULL) - *pfirstold1 = curr; /* first OLD1 object in the list */ + lua_assert(age != G_OLD1); /* advanced in 'markold' */ + setage(curr, nextage[age]); + if (getage(curr) == G_OLD1) { + addedold += objsize(curr); /* bytes becoming old */ + if (*pfirstold1 == NULL) + *pfirstold1 = curr; /* first OLD1 object in the list */ + } } p = &curr->next; /* go to next element */ } } + *paddedold += addedold; return p; } /* -** Traverse a list making all its elements white and clearing their -** age. In incremental mode, all objects are 'new' all the time, -** except for fixed strings (which are always old). -*/ -static void whitelist (global_State *g, GCObject *p) { - int white = luaC_white(g); - for (; p != NULL; p = p->next) - p->marked = cast_byte((p->marked & ~maskgcbits) | white); -} - - -/* -** Correct a list of gray objects. Return pointer to where rest of the -** list should be linked. +** Correct a list of gray objects. Return a pointer to the last element +** left on the list, so that we can link another list to the end of +** this one. ** Because this correction is done after sweeping, young objects might ** be turned white and still be in the list. They are only removed. ** 'TOUCHED1' objects are advanced to 'TOUCHED2' and remain on the list; -** Non-white threads also remain on the list; 'TOUCHED2' objects become -** regular old; they and anything else are removed from the list. +** Non-white threads also remain on the list. 'TOUCHED2' objects and +** anything else become regular old, are marked black, and are removed +** from the list. */ static GCObject **correctgraylist (GCObject **p) { GCObject *curr; @@ -1178,7 +1233,7 @@ static GCObject **correctgraylist (GCObject **p) { else if (getage(curr) == G_TOUCHED1) { /* touched in this cycle? */ lua_assert(isgray(curr)); nw2black(curr); /* make it black, for next barrier */ - changeage(curr, G_TOUCHED1, G_TOUCHED2); + setage(curr, G_TOUCHED2); goto remain; /* keep it in the list and go to next element */ } else if (curr->tt == LUA_VTHREAD) { @@ -1188,7 +1243,7 @@ static GCObject **correctgraylist (GCObject **p) { else { /* everything else is removed */ lua_assert(isold(curr)); /* young objects should be white here */ if (getage(curr) == G_TOUCHED2) /* advance from TOUCHED2... */ - changeage(curr, G_TOUCHED2, G_OLD); /* ... to OLD */ + setage(curr, G_OLD); /* ... to OLD */ nw2black(curr); /* make object black (to be removed) */ goto remove; } @@ -1215,15 +1270,15 @@ static void correctgraylists (global_State *g) { /* ** Mark black 'OLD1' objects when starting a new young collection. -** Gray objects are already in some gray list, and so will be visited -** in the atomic step. +** Gray objects are already in some gray list, and so will be visited in +** the atomic step. */ static void markold (global_State *g, GCObject *from, GCObject *to) { GCObject *p; for (p = from; p != to; p = p->next) { if (getage(p) == G_OLD1) { lua_assert(!iswhite(p)); - changeage(p, G_OLD1, G_OLD); /* now they are old */ + setage(p, G_OLD); /* now they are old */ if (isblack(p)) reallymarkobject(g, p); } @@ -1243,12 +1298,43 @@ static void finishgencycle (lua_State *L, global_State *g) { } +/* +** Shifts from a minor collection to major collections. It starts in +** the "sweep all" state to clear all objects, which are mostly black +** in generational mode. +*/ +static void minor2inc (lua_State *L, global_State *g, lu_byte kind) { + g->GCmajorminor = g->GCmarked; /* number of live bytes */ + g->gckind = kind; + g->reallyold = g->old1 = g->survival = NULL; + g->finobjrold = g->finobjold1 = g->finobjsur = NULL; + entersweep(L); /* continue as an incremental cycle */ + /* set a debt equal to the step size */ + luaE_setdebt(g, applygcparam(g, STEPSIZE, 100)); +} + + +/* +** Decide whether to shift to major mode. It shifts if the accumulated +** number of added old bytes (counted in 'GCmarked') is larger than +** 'minormajor'% of the number of lived bytes after the last major +** collection. (This number is kept in 'GCmajorminor'.) +*/ +static int checkminormajor (global_State *g) { + l_mem limit = applygcparam(g, MINORMAJOR, g->GCmajorminor); + if (limit == 0) + return 0; /* special case: 'minormajor' 0 stops major collections */ + return (g->GCmarked >= limit); +} + /* ** Does a young collection. First, mark 'OLD1' objects. Then does the -** atomic step. Then, sweep all lists and advance pointers. Finally, -** finish the collection. +** atomic step. Then, check whether to continue in minor mode. If so, +** sweep all lists and advance pointers. Finally, finish the collection. */ static void youngcollection (lua_State *L, global_State *g) { + l_mem addedold1 = 0; + l_mem marked = g->GCmarked; /* preserve 'g->GCmarked' */ GCObject **psurvival; /* to point to first non-dead survival object */ GCObject *dummy; /* dummy out parameter to 'sweepgen' */ lua_assert(g->gcstate == GCSpropagate); @@ -1258,28 +1344,39 @@ static void youngcollection (lua_State *L, global_State *g) { } markold(g, g->finobj, g->finobjrold); markold(g, g->tobefnz, NULL); - atomic(L); + + atomic(L); /* will lose 'g->marked' */ /* sweep nursery and get a pointer to its last live element */ g->gcstate = GCSswpallgc; - psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1); + psurvival = sweepgen(L, g, &g->allgc, g->survival, &g->firstold1, &addedold1); /* sweep 'survival' */ - sweepgen(L, g, psurvival, g->old1, &g->firstold1); + sweepgen(L, g, psurvival, g->old1, &g->firstold1, &addedold1); g->reallyold = g->old1; g->old1 = *psurvival; /* 'survival' survivals are old now */ g->survival = g->allgc; /* all news are survivals */ /* repeat for 'finobj' lists */ dummy = NULL; /* no 'firstold1' optimization for 'finobj' lists */ - psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy); + psurvival = sweepgen(L, g, &g->finobj, g->finobjsur, &dummy, &addedold1); /* sweep 'survival' */ - sweepgen(L, g, psurvival, g->finobjold1, &dummy); + sweepgen(L, g, psurvival, g->finobjold1, &dummy, &addedold1); g->finobjrold = g->finobjold1; g->finobjold1 = *psurvival; /* 'survival' survivals are old now */ g->finobjsur = g->finobj; /* all news are survivals */ - sweepgen(L, g, &g->tobefnz, NULL, &dummy); - finishgencycle(L, g); + sweepgen(L, g, &g->tobefnz, NULL, &dummy, &addedold1); + + /* keep total number of added old1 bytes */ + g->GCmarked = marked + addedold1; + + /* decide whether to shift to major mode */ + if (checkminormajor(g)) { + minor2inc(L, g, KGC_GENMAJOR); /* go to major mode */ + g->GCmarked = 0; /* avoid pause in first major cycle (see 'setpause') */ + } + else + finishgencycle(L, g); /* still in minor mode; finish it */ } @@ -1304,19 +1401,21 @@ static void atomic2gen (lua_State *L, global_State *g) { sweep2old(L, &g->tobefnz); - g->gckind = KGC_GEN; - g->lastatomic = 0; - g->GCestimate = gettotalbytes(g); /* base for memory control */ + g->gckind = KGC_GENMINOR; + g->GCmajorminor = g->GCmarked; /* "base" for number of bytes */ + g->GCmarked = 0; /* to count the number of added old1 bytes */ finishgencycle(L, g); } /* ** Set debt for the next minor collection, which will happen when -** memory grows 'genminormul'%. +** total number of bytes grows 'genminormul'% in relation to +** the base, GCmajorminor, which is the number of bytes being used +** after the last major collection. */ static void setminordebt (global_State *g) { - luaE_setdebt(g, -(cast(l_mem, (gettotalbytes(g) / 100)) * g->genminormul)); + luaE_setdebt(g, applygcparam(g, MINORMUL, g->GCmajorminor)); } @@ -1326,31 +1425,12 @@ static void setminordebt (global_State *g) { ** are cleared. Then, turn all objects into old and finishes the ** collection. */ -static lu_mem entergen (lua_State *L, global_State *g) { - lu_mem numobjs; - luaC_runtilstate(L, bitmask(GCSpause)); /* prepare to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ - numobjs = atomic(L); /* propagates all and then do the atomic stuff */ +static void entergen (lua_State *L, global_State *g) { + luaC_runtilstate(L, GCSpause, 1); /* prepare to start a new cycle */ + luaC_runtilstate(L, GCSpropagate, 1); /* start new cycle */ + atomic(L); /* propagates all and then do the atomic stuff */ atomic2gen(L, g); setminordebt(g); /* set debt assuming next cycle will be minor */ - return numobjs; -} - - -/* -** Enter incremental mode. Turn all objects white, make all -** intermediate lists point to NULL (to avoid invalid pointers), -** and go to the pause state. -*/ -static void enterinc (global_State *g) { - whitelist(g, g->allgc); - g->reallyold = g->old1 = g->survival = NULL; - whitelist(g, g->finobj); - whitelist(g, g->tobefnz); - g->finobjrold = g->finobjold1 = g->finobjsur = NULL; - g->gcstate = GCSpause; - g->gckind = KGC_INC; - g->lastatomic = 0; } @@ -1359,111 +1439,49 @@ static void enterinc (global_State *g) { */ void luaC_changemode (lua_State *L, int newmode) { global_State *g = G(L); - if (newmode != g->gckind) { - if (newmode == KGC_GEN) /* entering generational mode? */ + if (g->gckind == KGC_GENMAJOR) /* doing major collections? */ + g->gckind = KGC_INC; /* already incremental but in name */ + if (newmode != g->gckind) { /* does it need to change? */ + if (newmode == KGC_INC) /* entering incremental mode? */ + minor2inc(L, g, KGC_INC); /* entering incremental mode */ + else { + lua_assert(newmode == KGC_GENMINOR); entergen(L, g); - else - enterinc(g); /* entering incremental mode */ + } } - g->lastatomic = 0; } /* ** Does a full collection in generational mode. */ -static lu_mem fullgen (lua_State *L, global_State *g) { - enterinc(g); - return entergen(L, g); -} - - -/* -** Does a major collection after last collection was a "bad collection". -** -** When the program is building a big structure, it allocates lots of -** memory but generates very little garbage. In those scenarios, -** the generational mode just wastes time doing small collections, and -** major collections are frequently what we call a "bad collection", a -** collection that frees too few objects. To avoid the cost of switching -** between generational mode and the incremental mode needed for full -** (major) collections, the collector tries to stay in incremental mode -** after a bad collection, and to switch back to generational mode only -** after a "good" collection (one that traverses less than 9/8 objects -** of the previous one). -** The collector must choose whether to stay in incremental mode or to -** switch back to generational mode before sweeping. At this point, it -** does not know the real memory in use, so it cannot use memory to -** decide whether to return to generational mode. Instead, it uses the -** number of objects traversed (returned by 'atomic') as a proxy. The -** field 'g->lastatomic' keeps this count from the last collection. -** ('g->lastatomic != 0' also means that the last collection was bad.) -*/ -static void stepgenfull (lua_State *L, global_State *g) { - lu_mem newatomic; /* count of traversed objects */ - lu_mem lastatomic = g->lastatomic; /* count from last collection */ - if (g->gckind == KGC_GEN) /* still in generational mode? */ - enterinc(g); /* enter incremental mode */ - luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ - newatomic = atomic(L); /* mark everybody */ - if (newatomic < lastatomic + (lastatomic >> 3)) { /* good collection? */ - atomic2gen(L, g); /* return to generational mode */ - setminordebt(g); - } - else { /* another bad collection; stay in incremental mode */ - g->GCestimate = gettotalbytes(g); /* first estimate */ - entersweep(L); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ - setpause(g); - g->lastatomic = newatomic; - } +static void fullgen (lua_State *L, global_State *g) { + minor2inc(L, g, KGC_INC); + entergen(L, g); } /* -** Does a generational "step". -** Usually, this means doing a minor collection and setting the debt to -** make another collection when memory grows 'genminormul'% larger. -** -** However, there are exceptions. If memory grows 'genmajormul'% -** larger than it was at the end of the last major collection (kept -** in 'g->GCestimate'), the function does a major collection. At the -** end, it checks whether the major collection was able to free a -** decent amount of memory (at least half the growth in memory since -** previous major collection). If so, the collector keeps its state, -** and the next collection will probably be minor again. Otherwise, -** we have what we call a "bad collection". In that case, set the field -** 'g->lastatomic' to signal that fact, so that the next collection will -** go to 'stepgenfull'. -** -** 'GCdebt <= 0' means an explicit call to GC step with "size" zero; -** in that case, do a minor collection. -*/ -static void genstep (lua_State *L, global_State *g) { - if (g->lastatomic != 0) /* last collection was a bad one? */ - stepgenfull(L, g); /* do a full step */ - else { - lu_mem majorbase = g->GCestimate; /* memory after last major collection */ - lu_mem majorinc = (majorbase / 100) * getgcparam(g->genmajormul); - if (g->GCdebt > 0 && gettotalbytes(g) > majorbase + majorinc) { - lu_mem numobjs = fullgen(L, g); /* do a major collection */ - if (gettotalbytes(g) < majorbase + (majorinc / 2)) { - /* collected at least half of memory growth since last major - collection; keep doing minor collections. */ - lua_assert(g->lastatomic == 0); - } - else { /* bad collection */ - g->lastatomic = numobjs; /* signal that last collection was bad */ - setpause(g); /* do a long wait for next (major) collection */ - } - } - else { /* regular case; do a minor collection */ - youngcollection(L, g); +** After an atomic incremental step from a major collection, +** check whether collector could return to minor collections. +** It checks whether the number of bytes 'tobecollected' +** is greater than 'majorminor'% of the number of bytes added +** since the last collection ('addedbytes'). +*/ +static int checkmajorminor (lua_State *L, global_State *g) { + if (g->gckind == KGC_GENMAJOR) { /* generational mode? */ + l_mem numbytes = gettotalbytes(g); + l_mem addedbytes = numbytes - g->GCmajorminor; + l_mem limit = applygcparam(g, MAJORMINOR, addedbytes); + l_mem tobecollected = numbytes - g->GCmarked; + if (tobecollected > limit) { + atomic2gen(L, g); /* return to generational mode */ setminordebt(g); - g->GCestimate = majorbase; /* preserve base value */ + return 1; /* exit incremental collection */ } } - lua_assert(isdecGCmodegen(g)); + g->GCmajorminor = g->GCmarked; /* prepare for next collection */ + return 0; /* stay doing incremental collections */ } /* }====================================================== */ @@ -1515,32 +1533,31 @@ void luaC_freeallobjects (lua_State *L) { separatetobefnz(g, 1); /* separate all objects with finalizers */ lua_assert(g->finobj == NULL); callallpendingfinalizers(L); - deletelist(L, g->allgc, obj2gco(g->mainthread)); + deletelist(L, g->allgc, obj2gco(mainthread(g))); lua_assert(g->finobj == NULL); /* no new finalizers */ deletelist(L, g->fixedgc, NULL); /* collect fixed objects */ lua_assert(g->strt.nuse == 0); } -static lu_mem atomic (lua_State *L) { +static void atomic (lua_State *L) { global_State *g = G(L); - lu_mem work = 0; GCObject *origweak, *origall; GCObject *grayagain = g->grayagain; /* save original list */ g->grayagain = NULL; lua_assert(g->ephemeron == NULL && g->weak == NULL); - lua_assert(!iswhite(g->mainthread)); + lua_assert(!iswhite(mainthread(g))); g->gcstate = GCSatomic; markobject(g, L); /* mark running thread */ /* registry and global metatables may be changed by API */ markvalue(g, &g->l_registry); markmt(g); /* mark global metatables */ - work += propagateall(g); /* empties 'gray' list */ + propagateall(g); /* empties 'gray' list */ /* remark occasional upvalues of (maybe) dead threads */ - work += remarkupvals(g); - work += propagateall(g); /* propagate changes */ + remarkupvals(g); + propagateall(g); /* propagate changes */ g->gray = grayagain; - work += propagateall(g); /* traverse 'grayagain' list */ + propagateall(g); /* traverse 'grayagain' list */ convergeephemerons(g); /* at this point, all strongly accessible objects are marked. */ /* Clear values from weak tables, before checking finalizers */ @@ -1548,154 +1565,196 @@ static lu_mem atomic (lua_State *L) { clearbyvalues(g, g->allweak, NULL); origweak = g->weak; origall = g->allweak; separatetobefnz(g, 0); /* separate objects to be finalized */ - work += markbeingfnz(g); /* mark objects that will be finalized */ - work += propagateall(g); /* remark, to propagate 'resurrection' */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate 'resurrection' */ convergeephemerons(g); /* at this point, all resurrected objects are marked. */ /* remove dead objects from weak tables */ - clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron tables */ - clearbykeys(g, g->allweak); /* clear keys from all 'allweak' tables */ + clearbykeys(g, g->ephemeron); /* clear keys from all ephemeron */ + clearbykeys(g, g->allweak); /* clear keys from all 'allweak' */ /* clear values from resurrected weak tables */ clearbyvalues(g, g->weak, origweak); clearbyvalues(g, g->allweak, origall); luaS_clearcache(g); g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ lua_assert(g->gray == NULL); - return work; /* estimate of slots marked by 'atomic' */ } -static int sweepstep (lua_State *L, global_State *g, - int nextstate, GCObject **nextlist) { - if (g->sweepgc) { - l_mem olddebt = g->GCdebt; - int count; - g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX, &count); - g->GCestimate += g->GCdebt - olddebt; /* update estimate */ - return count; - } +/* +** Do a sweep step. The normal case (not fast) sweeps at most GCSWEEPMAX +** elements. The fast case sweeps the whole list. +*/ +static void sweepstep (lua_State *L, global_State *g, + lu_byte nextstate, GCObject **nextlist, int fast) { + if (g->sweepgc) + g->sweepgc = sweeplist(L, g->sweepgc, fast ? MAX_LMEM : GCSWEEPMAX); else { /* enter next state */ g->gcstate = nextstate; g->sweepgc = nextlist; - return 0; /* no work done */ } } -static lu_mem singlestep (lua_State *L) { +/* +** Performs one incremental "step" in an incremental garbage collection. +** For indivisible work, a step goes to the next state. When marking +** (propagating), a step traverses one object. When sweeping, a step +** sweeps GCSWEEPMAX objects, to avoid a big overhead for sweeping +** objects one by one. (Sweeping is inexpensive, no matter the +** object.) When 'fast' is true, 'singlestep' tries to finish a state +** "as fast as possible". In particular, it skips the propagation +** phase and leaves all objects to be traversed by the atomic phase: +** That avoids traversing twice some objects, such as threads and +** weak tables. +*/ + +#define step2pause -3 /* finished collection; entered pause state */ +#define atomicstep -2 /* atomic step */ +#define step2minor -1 /* moved to minor collections */ + + +static l_mem singlestep (lua_State *L, int fast) { global_State *g = G(L); - lu_mem work; + l_mem stepresult; lua_assert(!g->gcstopem); /* collector is not reentrant */ g->gcstopem = 1; /* no emergency collections while collecting */ switch (g->gcstate) { case GCSpause: { restartcollection(g); g->gcstate = GCSpropagate; - work = 1; + stepresult = 1; break; } case GCSpropagate: { - if (g->gray == NULL) { /* no more gray objects? */ + if (fast || g->gray == NULL) { g->gcstate = GCSenteratomic; /* finish propagate phase */ - work = 0; + stepresult = 1; } else - work = propagatemark(g); /* traverse one gray object */ + stepresult = propagatemark(g); /* traverse one gray object */ break; } case GCSenteratomic: { - work = atomic(L); /* work is what was traversed by 'atomic' */ - entersweep(L); - g->GCestimate = gettotalbytes(g); /* first estimate */ + atomic(L); + if (checkmajorminor(L, g)) + stepresult = step2minor; + else { + entersweep(L); + stepresult = atomicstep; + } break; } case GCSswpallgc: { /* sweep "regular" objects */ - work = sweepstep(L, g, GCSswpfinobj, &g->finobj); + sweepstep(L, g, GCSswpfinobj, &g->finobj, fast); + stepresult = GCSWEEPMAX; break; } case GCSswpfinobj: { /* sweep objects with finalizers */ - work = sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + sweepstep(L, g, GCSswptobefnz, &g->tobefnz, fast); + stepresult = GCSWEEPMAX; break; } case GCSswptobefnz: { /* sweep objects to be finalized */ - work = sweepstep(L, g, GCSswpend, NULL); + sweepstep(L, g, GCSswpend, NULL, fast); + stepresult = GCSWEEPMAX; break; } case GCSswpend: { /* finish sweeps */ checkSizes(L, g); g->gcstate = GCScallfin; - work = 0; + stepresult = GCSWEEPMAX; break; } - case GCScallfin: { /* call remaining finalizers */ + case GCScallfin: { /* call finalizers */ if (g->tobefnz && !g->gcemergency) { g->gcstopem = 0; /* ok collections during finalizers */ - work = runafewfinalizers(L, GCFINMAX) * GCFINALIZECOST; + GCTM(L); /* call one finalizer */ + stepresult = CWUFIN; } else { /* emergency mode or no more finalizers */ g->gcstate = GCSpause; /* finish collection */ - work = 0; + stepresult = step2pause; } break; } default: lua_assert(0); return 0; } g->gcstopem = 0; - return work; + return stepresult; } /* -** advances the garbage collector until it reaches a state allowed -** by 'statemask' +** Advances the garbage collector until it reaches the given state. +** (The option 'fast' is only for testing; in normal code, 'fast' +** here is always true.) */ -void luaC_runtilstate (lua_State *L, int statesmask) { +void luaC_runtilstate (lua_State *L, int state, int fast) { global_State *g = G(L); - while (!testbit(statesmask, g->gcstate)) - singlestep(L); + lua_assert(g->gckind == KGC_INC); + while (state != g->gcstate) + singlestep(L, fast); } /* -** Performs a basic incremental step. The debt and step size are +** Performs a basic incremental step. The step size is ** converted from bytes to "units of work"; then the function loops ** running single steps until adding that many units of work or ** finishing a cycle (pause state). Finally, it sets the debt that ** controls when next step will be performed. */ static void incstep (lua_State *L, global_State *g) { - int stepmul = (getgcparam(g->gcstepmul) | 1); /* avoid division by 0 */ - l_mem debt = (g->GCdebt / WORK2MEM) * stepmul; - l_mem stepsize = (g->gcstepsize <= log2maxs(l_mem)) - ? ((cast(l_mem, 1) << g->gcstepsize) / WORK2MEM) * stepmul - : MAX_LMEM; /* overflow; keep maximum value */ - do { /* repeat until pause or enough "credit" (negative debt) */ - lu_mem work = singlestep(L); /* perform one single step */ - debt -= work; - } while (debt > -stepsize && g->gcstate != GCSpause); + l_mem stepsize = applygcparam(g, STEPSIZE, 100); + l_mem work2do = applygcparam(g, STEPMUL, stepsize / cast_int(sizeof(void*))); + l_mem stres; + int fast = (work2do == 0); /* special case: do a full collection */ + do { /* repeat until enough work */ + stres = singlestep(L, fast); /* perform one single step */ + if (stres == step2minor) /* returned to minor collections? */ + return; /* nothing else to be done here */ + else if (stres == step2pause || (stres == atomicstep && !fast)) + break; /* end of cycle or atomic */ + else + work2do -= stres; + } while (fast || work2do > 0); if (g->gcstate == GCSpause) setpause(g); /* pause until next cycle */ - else { - debt = (debt / stepmul) * WORK2MEM; /* convert 'work units' to bytes */ - luaE_setdebt(g, debt); - } + else + luaE_setdebt(g, stepsize); } + +#if !defined(luai_tracegc) +#define luai_tracegc(L,f) ((void)0) +#endif + /* -** Performs a basic GC step if collector is running. (If collector is -** not running, set a reasonable debt to avoid it being called at -** every single check.) +** Performs a basic GC step if collector is running. (If collector was +** stopped by the user, set a reasonable debt to avoid it being called +** at every single check.) */ void luaC_step (lua_State *L) { global_State *g = G(L); - if (!gcrunning(g)) /* not running? */ - luaE_setdebt(g, -2000); + lua_assert(!g->gcemergency); + if (!gcrunning(g)) { /* not running? */ + if (g->gcstp & GCSTPUSR) /* stopped by the user? */ + luaE_setdebt(g, 20000); + } else { - if(isdecGCmodegen(g)) - genstep(L, g); - else - incstep(L, g); + luai_tracegc(L, 1); /* for internal debugging */ + switch (g->gckind) { + case KGC_INC: case KGC_GENMAJOR: + incstep(L, g); + break; + case KGC_GENMINOR: + youngcollection(L, g); + setminordebt(g); + break; + } + luai_tracegc(L, 0); /* for internal debugging */ } } @@ -1711,13 +1770,9 @@ static void fullinc (lua_State *L, global_State *g) { if (keepinvariant(g)) /* black objects? */ entersweep(L); /* sweep everything to turn them back to white */ /* finish any pending sweep phase to start a new cycle */ - luaC_runtilstate(L, bitmask(GCSpause)); - luaC_runtilstate(L, bitmask(GCSpropagate)); /* start new cycle */ - g->gcstate = GCSenteratomic; /* go straight to atomic phase */ - luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ - /* estimate must be correct after a full GC cycle */ - lua_assert(g->GCestimate == gettotalbytes(g)); - luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + luaC_runtilstate(L, GCSpause, 1); + luaC_runtilstate(L, GCScallfin, 1); /* run up to finalizers */ + luaC_runtilstate(L, GCSpause, 1); /* finish collection */ setpause(g); } @@ -1730,11 +1785,16 @@ static void fullinc (lua_State *L, global_State *g) { void luaC_fullgc (lua_State *L, int isemergency) { global_State *g = G(L); lua_assert(!g->gcemergency); - g->gcemergency = isemergency; /* set flag */ - if (g->gckind == KGC_INC) - fullinc(L, g); - else - fullgen(L, g); + g->gcemergency = cast_byte(isemergency); /* set flag */ + switch (g->gckind) { + case KGC_GENMINOR: fullgen(L, g); break; + case KGC_INC: fullinc(L, g); break; + case KGC_GENMAJOR: + g->gckind = KGC_INC; + fullinc(L, g); + g->gckind = KGC_GENMAJOR; + break; + } g->gcemergency = 0; } diff --git a/3rdparty/lua/plainlua/lgc.h b/3rdparty/lua/plainlua/lgc.h index 538f6edcccf2..ee0541793bea 100644 --- a/3rdparty/lua/plainlua/lgc.h +++ b/3rdparty/lua/plainlua/lgc.h @@ -8,6 +8,9 @@ #define lgc_h +#include + + #include "lobject.h" #include "lstate.h" @@ -20,8 +23,9 @@ ** never point to a white one. Moreover, any gray object must be in a ** "gray list" (gray, grayagain, weak, allweak, ephemeron) so that it ** can be visited again before finishing the collection cycle. (Open -** upvalues are an exception to this rule.) These lists have no meaning -** when the invariant is not being enforced (e.g., sweep phase). +** upvalues are an exception to this rule, as they are attached to +** a corresponding thread.) These lists have no meaning when the +** invariant is not being enforced (e.g., sweep phase). */ @@ -45,10 +49,10 @@ /* ** macro to tell when main invariant (white objects cannot point to black -** ones) must be kept. During a collection, the sweep -** phase may break the invariant, as objects turned white may point to -** still-black objects. The invariant is restored when sweep ends and -** all objects are white again. +** ones) must be kept. During a collection, the sweep phase may break +** the invariant, as objects turned white may point to still-black +** objects. The invariant is restored when sweep ends and all objects +** are white again. */ #define keepinvariant(g) ((g)->gcstate <= GCSatomic) @@ -117,36 +121,90 @@ #define setage(o,a) ((o)->marked = cast_byte(((o)->marked & (~AGEBITS)) | a)) #define isold(o) (getage(o) > G_SURVIVAL) -#define changeage(o,f,t) \ - check_exp(getage(o) == (f), (o)->marked ^= ((f)^(t))) +/* +** In generational mode, objects are created 'new'. After surviving one +** cycle, they become 'survival'. Both 'new' and 'survival' can point +** to any other object, as they are traversed at the end of the cycle. +** We call them both 'young' objects. +** If a survival object survives another cycle, it becomes 'old1'. +** 'old1' objects can still point to survival objects (but not to +** new objects), so they still must be traversed. After another cycle +** (that, being old, 'old1' objects will "survive" no matter what) +** finally the 'old1' object becomes really 'old', and then they +** are no more traversed. +** +** To keep its invariants, the generational mode uses the same barriers +** also used by the incremental mode. If a young object is caught in a +** forward barrier, it cannot become old immediately, because it can +** still point to other young objects. Instead, it becomes 'old0', +** which in the next cycle becomes 'old1'. So, 'old0' objects is +** old but can point to new and survival objects; 'old1' is old +** but cannot point to new objects; and 'old' cannot point to any +** young object. +** +** If any old object ('old0', 'old1', 'old') is caught in a back +** barrier, it becomes 'touched1' and goes into a gray list, to be +** visited at the end of the cycle. There it evolves to 'touched2', +** which can point to survivals but not to new objects. In yet another +** cycle then it becomes 'old' again. +** +** The generational mode must also control the colors of objects, +** because of the barriers. While the mutator is running, young objects +** are kept white. 'old', 'old1', and 'touched2' objects are kept black, +** as they cannot point to new objects; exceptions are threads and open +** upvalues, which age to 'old1' and 'old' but are kept gray. 'old0' +** objects may be gray or black, as in the incremental mode. 'touched1' +** objects are kept gray, as they must be visited again at the end of +** the cycle. +*/ -/* Default Values for GC parameters */ -#define LUAI_GENMAJORMUL 100 -#define LUAI_GENMINORMUL 20 -/* wait memory to double before starting new cycle */ -#define LUAI_GCPAUSE 200 +/* +** {====================================================== +** Default Values for GC parameters +** ======================================================= +*/ /* -** some gc parameters are stored divided by 4 to allow a maximum value -** up to 1023 in a 'lu_byte'. +** Minor collections will shift to major ones after LUAI_MINORMAJOR% +** bytes become old. */ -#define getgcparam(p) ((p) * 4) -#define setgcparam(p,v) ((p) = (v) / 4) +#define LUAI_MINORMAJOR 70 -#define LUAI_GCMUL 100 +/* +** Major collections will shift to minor ones after a collection +** collects at least LUAI_MAJORMINOR% of the new bytes. +*/ +#define LUAI_MAJORMINOR 50 -/* how much to allocate before next GC step (log2) */ -#define LUAI_GCSTEPSIZE 13 /* 8 KB */ +/* +** A young (minor) collection will run after creating LUAI_GENMINORMUL% +** new bytes. +*/ +#define LUAI_GENMINORMUL 20 + + +/* incremental */ +/* Number of bytes must be LUAI_GCPAUSE% before starting new cycle */ +#define LUAI_GCPAUSE 250 /* -** Check whether the declared GC mode is generational. While in -** generational mode, the collector can go temporarily to incremental -** mode to improve performance. This is signaled by 'g->lastatomic != 0'. +** Step multiplier: The collector handles LUAI_GCMUL% work units for +** each new allocated word. (Each "work unit" corresponds roughly to +** sweeping one object or traversing one slot.) */ -#define isdecGCmodegen(g) (g->gckind == KGC_GEN || g->lastatomic != 0) +#define LUAI_GCMUL 200 + +/* How many bytes to allocate before next GC step */ +#define LUAI_GCSTEPSIZE (200 * sizeof(Table)) + + +#define setgcparam(g,p,v) (g->gcparams[LUA_GCP##p] = luaO_codeparam(v)) +#define applygcparam(g,p,x) luaO_applyparam(g->gcparams[LUA_GCP##p], x) + +/* }====================================================== */ /* @@ -159,14 +217,22 @@ /* -** Does one step of collection when debt becomes positive. 'pre'/'pos' +** Does one step of collection when debt becomes zero. 'pre'/'pos' ** allows some adjustments to be done only when needed. macro ** 'condchangemem' is used only for heavy tests (forcing a full ** GC cycle on every opportunity) */ + +#if !defined(HARDMEMTESTS) +#define condchangemem(L,pre,pos,emg) ((void)0) +#else +#define condchangemem(L,pre,pos,emg) \ + { if (gcrunning(G(L))) { pre; luaC_fullgc(L, emg); pos; } } +#endif + #define luaC_condGC(L,pre,pos) \ - { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ - condchangemem(L,pre,pos); } + { if (G(L)->GCdebt <= 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos,0); } /* more often than not, 'pre'/'pos' are empty */ #define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) @@ -188,10 +254,10 @@ LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); LUAI_FUNC void luaC_freeallobjects (lua_State *L); LUAI_FUNC void luaC_step (lua_State *L); -LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int state, int fast); LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); -LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); -LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, int tt, size_t sz, +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, lu_byte tt, size_t sz); +LUAI_FUNC GCObject *luaC_newobjdt (lua_State *L, lu_byte tt, size_t sz, size_t offset); LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); LUAI_FUNC void luaC_barrierback_ (lua_State *L, GCObject *o); diff --git a/3rdparty/lua/plainlua/linit.c b/3rdparty/lua/plainlua/linit.c index 69808f84f48a..00d06f7ecb62 100644 --- a/3rdparty/lua/plainlua/linit.c +++ b/3rdparty/lua/plainlua/linit.c @@ -8,21 +8,6 @@ #define linit_c #define LUA_LIB -/* -** If you embed Lua in your program and need to open the standard -** libraries, call luaL_openlibs in your program. If you need a -** different set of libraries, copy this file to your project and edit -** it to suit your needs. -** -** You can also *preload* libraries, so that a later 'require' can -** open the library, which is already linked to the application. -** For that, do the following code: -** -** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); -** lua_pushcfunction(L, luaopen_modname); -** lua_setfield(L, -2, modname); -** lua_pop(L, 1); // remove PRELOAD table -*/ #include "lprefix.h" @@ -33,33 +18,46 @@ #include "lualib.h" #include "lauxlib.h" +#include "llimits.h" /* -** these libs are loaded by lua.c and are readily available to any Lua -** program +** Standard Libraries. (Must be listed in the same ORDER of their +** respective constants LUA_K.) */ -static const luaL_Reg loadedlibs[] = { +static const luaL_Reg stdlibs[] = { {LUA_GNAME, luaopen_base}, {LUA_LOADLIBNAME, luaopen_package}, {LUA_COLIBNAME, luaopen_coroutine}, - {LUA_TABLIBNAME, luaopen_table}, + {LUA_DBLIBNAME, luaopen_debug}, {LUA_IOLIBNAME, luaopen_io}, + {LUA_MATHLIBNAME, luaopen_math}, {LUA_OSLIBNAME, luaopen_os}, {LUA_STRLIBNAME, luaopen_string}, - {LUA_MATHLIBNAME, luaopen_math}, + {LUA_TABLIBNAME, luaopen_table}, {LUA_UTF8LIBNAME, luaopen_utf8}, - {LUA_DBLIBNAME, luaopen_debug}, {NULL, NULL} }; -LUALIB_API void luaL_openlibs (lua_State *L) { +/* +** require and preload selected standard libraries +*/ +LUALIB_API void luaL_openselectedlibs (lua_State *L, int load, int preload) { + int mask; const luaL_Reg *lib; - /* "require" functions from 'loadedlibs' and set results to global table */ - for (lib = loadedlibs; lib->func; lib++) { - luaL_requiref(L, lib->name, lib->func, 1); - lua_pop(L, 1); /* remove lib */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + for (lib = stdlibs, mask = 1; lib->name != NULL; lib++, mask <<= 1) { + if (load & mask) { /* selected? */ + luaL_requiref(L, lib->name, lib->func, 1); /* require library */ + lua_pop(L, 1); /* remove result from the stack */ + } + else if (preload & mask) { /* selected? */ + lua_pushcfunction(L, lib->func); + lua_setfield(L, -2, lib->name); /* add library to PRELOAD table */ + } } + lua_assert((mask >> 1) == LUA_UTF8LIBK); + lua_pop(L, 1); /* remove PRELOAD table */ } diff --git a/3rdparty/lua/plainlua/liolib.c b/3rdparty/lua/plainlua/liolib.c index c5075f3e78a9..c8f165cb05e6 100644 --- a/3rdparty/lua/plainlua/liolib.c +++ b/3rdparty/lua/plainlua/liolib.c @@ -21,8 +21,7 @@ #include "lauxlib.h" #include "lualib.h" - - +#include "llimits.h" /* @@ -444,7 +443,7 @@ static int nextc (RN *rn) { return 0; /* fail */ } else { - rn->buff[rn->n++] = rn->c; /* save current char */ + rn->buff[rn->n++] = cast_char(rn->c); /* save current char */ rn->c = l_getc(rn->f); /* read next one */ return 1; } @@ -525,15 +524,15 @@ static int read_line (lua_State *L, FILE *f, int chop) { luaL_buffinit(L, &b); do { /* may need to read several chunks to get whole line */ char *buff = luaL_prepbuffer(&b); /* preallocate buffer space */ - int i = 0; + unsigned i = 0; l_lockfile(f); /* no memory errors can happen inside the lock */ while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') - buff[i++] = c; /* read up to end of line or buffer limit */ + buff[i++] = cast_char(c); /* read up to end of line or buffer limit */ l_unlockfile(f); luaL_addsize(&b, i); } while (c != EOF && c != '\n'); /* repeat until end of line */ if (!chop && c == '\n') /* want a newline and have one? */ - luaL_addchar(&b, c); /* add ending newline to result */ + luaL_addchar(&b, '\n'); /* add ending newline to result */ luaL_pushresult(&b); /* close buffer */ /* return ok if read something (either a newline or something else) */ return (c == '\n' || lua_rawlen(L, -1) > 0); @@ -663,28 +662,28 @@ static int io_readline (lua_State *L) { static int g_write (lua_State *L, FILE *f, int arg) { int nargs = lua_gettop(L) - arg; - int status = 1; + size_t totalbytes = 0; /* total number of bytes written */ errno = 0; - for (; nargs--; arg++) { - if (lua_type(L, arg) == LUA_TNUMBER) { - /* optimization: could be done exactly as for strings */ - int len = lua_isinteger(L, arg) - ? fprintf(f, LUA_INTEGER_FMT, - (LUAI_UACINT)lua_tointeger(L, arg)) - : fprintf(f, LUA_NUMBER_FMT, - (LUAI_UACNUMBER)lua_tonumber(L, arg)); - status = status && (len > 0); + for (; nargs--; arg++) { /* for each argument */ + char buff[LUA_N2SBUFFSZ]; + const char *s; + size_t numbytes; /* bytes written in one call to 'fwrite' */ + size_t len = lua_numbertocstring(L, arg, buff); /* try as a number */ + if (len > 0) { /* did conversion work (value was a number)? */ + s = buff; + len--; } - else { - size_t l; - const char *s = luaL_checklstring(L, arg, &l); - status = status && (fwrite(s, sizeof(char), l, f) == l); + else /* must be a string */ + s = luaL_checklstring(L, arg, &len); + numbytes = fwrite(s, sizeof(char), len, f); + totalbytes += numbytes; + if (numbytes < len) { /* write error? */ + int n = luaL_fileresult(L, 0, NULL); + lua_pushinteger(L, cast_st2S(totalbytes)); + return n + 1; /* return fail, error msg., error code, and counter */ } } - if (l_likely(status)) - return 1; /* file handle already on stack top */ - else - return luaL_fileresult(L, status, NULL); + return 1; /* no errors; file handle already on stack top */ } @@ -733,18 +732,19 @@ static int f_setvbuf (lua_State *L) { } - -static int io_flush (lua_State *L) { - FILE *f = getiofile(L, IO_OUTPUT); +static int aux_flush (lua_State *L, FILE *f) { errno = 0; return luaL_fileresult(L, fflush(f) == 0, NULL); } static int f_flush (lua_State *L) { - FILE *f = tofile(L); - errno = 0; - return luaL_fileresult(L, fflush(f) == 0, NULL); + return aux_flush(L, tofile(L)); +} + + +static int io_flush (lua_State *L) { + return aux_flush(L, getiofile(L, IO_OUTPUT)); } diff --git a/3rdparty/lua/plainlua/llex.c b/3rdparty/lua/plainlua/llex.c index 5fc39a5cdec1..f8bb3ea4b4a4 100644 --- a/3rdparty/lua/plainlua/llex.c +++ b/3rdparty/lua/plainlua/llex.c @@ -32,6 +32,11 @@ #define next(ls) (ls->current = zgetc(ls->z)) +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + #define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') @@ -39,7 +44,7 @@ /* ORDER RESERVED */ static const char *const luaX_tokens [] = { "and", "break", "do", "else", "elseif", - "end", "false", "for", "function", "goto", "if", + "end", "false", "for", "function", "global", "goto", "if", "in", "local", "nil", "not", "or", "repeat", "return", "then", "true", "until", "while", "//", "..", "...", "==", ">=", "<=", "~=", @@ -57,10 +62,10 @@ static l_noret lexerror (LexState *ls, const char *msg, int token); static void save (LexState *ls, int c) { Mbuffer *b = ls->buff; if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { - size_t newsize; - if (luaZ_sizebuffer(b) >= MAX_SIZE/2) + size_t newsize = luaZ_sizebuffer(b); /* get old size */; + if (newsize >= (MAX_SIZE/3 * 2)) /* larger than MAX_SIZE/1.5 ? */ lexerror(ls, "lexical element too long", 0); - newsize = luaZ_sizebuffer(b) * 2; + newsize += (newsize >> 1); /* new size is 1.5 times the old one */ luaZ_resizebuffer(ls->L, b, newsize); } b->buffer[luaZ_bufflen(b)++] = cast_char(c); @@ -122,30 +127,34 @@ l_noret luaX_syntaxerror (LexState *ls, const char *msg) { /* -** Creates a new string and anchors it in scanner's table so that it -** will not be collected until the end of the compilation; by that time -** it should be anchored somewhere. It also internalizes long strings, -** ensuring there is only one copy of each unique string. The table -** here is used as a set: the string enters as the key, while its value -** is irrelevant. We use the string itself as the value only because it -** is a TValue readily available. Later, the code generation can change -** this value. +** Anchors a string in scanner's table so that it will not be collected +** until the end of the compilation; by that time it should be anchored +** somewhere. It also internalizes long strings, ensuring there is only +** one copy of each unique string. */ -TString *luaX_newstring (LexState *ls, const char *str, size_t l) { +static TString *anchorstr (LexState *ls, TString *ts) { lua_State *L = ls->L; - TString *ts = luaS_newlstr(L, str, l); /* create new string */ - const TValue *o = luaH_getstr(ls->h, ts); - if (!ttisnil(o)) /* string already present? */ - ts = keystrval(nodefromval(o)); /* get saved copy */ - else { /* not in use yet */ + TValue oldts; + int tag = luaH_getstr(ls->h, ts, &oldts); + if (!tagisempty(tag)) /* string already present? */ + return tsvalue(&oldts); /* use stored value */ + else { /* create a new entry */ TValue *stv = s2v(L->top.p++); /* reserve stack space for string */ - setsvalue(L, stv, ts); /* temporarily anchor the string */ - luaH_finishset(L, ls->h, stv, o, stv); /* t[string] = string */ + setsvalue(L, stv, ts); /* push (anchor) the string on the stack */ + luaH_set(L, ls->h, stv, stv); /* t[string] = string */ /* table is not a metatable, so it does not need to invalidate cache */ luaC_checkGC(L); L->top.p--; /* remove string from stack */ + return ts; } - return ts; +} + + +/* +** Creates a new string and anchors it in scanner's table. +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + return anchorstr(ls, luaS_newlstr(ls->L, str, l)); } @@ -159,7 +168,7 @@ static void inclinenumber (LexState *ls) { next(ls); /* skip '\n' or '\r' */ if (currIsNewline(ls) && ls->current != old) next(ls); /* skip '\n\r' or '\r\n' */ - if (++ls->linenumber >= MAX_INT) + if (++ls->linenumber >= INT_MAX) lexerror(ls, "chunk has too many lines", 0); } @@ -175,7 +184,15 @@ void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, ls->linenumber = 1; ls->lastline = 1; ls->source = source; - ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ + /* all three strings here ("_ENV", "break", "global") were fixed, + so they cannot be collected */ + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env string */ + ls->brkn = luaS_newliteral(L, "break"); /* get "break" string */ +#if defined(LUA_COMPAT_GLOBAL) + /* compatibility mode: "global" is not a reserved word */ + ls->glbn = luaS_newliteral(L, "global"); /* get "global" string */ + ls->glbn->extra = 0; /* mark it as not reserved */ +#endif luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ } @@ -340,12 +357,17 @@ static int readhexaesc (LexState *ls) { } -static unsigned long readutf8esc (LexState *ls) { - unsigned long r; - int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ +/* +** When reading a UTF-8 escape sequence, save everything to the buffer +** for error reporting in case of errors; 'i' counts the number of +** saved characters, so that they can be removed if case of success. +*/ +static l_uint32 readutf8esc (LexState *ls) { + l_uint32 r; + int i = 4; /* number of chars to be removed: start with #"\u{X" */ save_and_next(ls); /* skip 'u' */ esccheck(ls, ls->current == '{', "missing '{'"); - r = gethexa(ls); /* must have at least one digit */ + r = cast_uint(gethexa(ls)); /* must have at least one digit */ while (cast_void(save_and_next(ls)), lisxdigit(ls->current)) { i++; esccheck(ls, r <= (0x7FFFFFFFu >> 4), "UTF-8 value too large"); @@ -542,12 +564,13 @@ static int llex (LexState *ls, SemInfo *seminfo) { do { save_and_next(ls); } while (lislalnum(ls->current)); - ts = luaX_newstring(ls, luaZ_buffer(ls->buff), - luaZ_bufflen(ls->buff)); - seminfo->ts = ts; - if (isreserved(ts)) /* reserved word? */ + /* find or create string */ + ts = luaS_newlstr(ls->L, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + if (isreserved(ts)) /* reserved word? */ return ts->extra - 1 + FIRST_RESERVED; else { + seminfo->ts = anchorstr(ls, ts); return TK_NAME; } } diff --git a/3rdparty/lua/plainlua/llex.h b/3rdparty/lua/plainlua/llex.h index 389d2f863592..37016e8a3f1f 100644 --- a/3rdparty/lua/plainlua/llex.h +++ b/3rdparty/lua/plainlua/llex.h @@ -33,8 +33,8 @@ enum RESERVED { /* terminal symbols denoted by reserved words */ TK_AND = FIRST_RESERVED, TK_BREAK, TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, - TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, - TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + TK_GLOBAL, TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, + TK_REPEAT, TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, /* other terminal symbols */ TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, TK_SHL, TK_SHR, @@ -59,7 +59,7 @@ typedef struct Token { } Token; -/* state of the lexer plus state of the parser when shared by all +/* state of the scanner plus state of the parser when shared by all functions */ typedef struct LexState { int current; /* current character (charint) */ @@ -75,6 +75,8 @@ typedef struct LexState { struct Dyndata *dyd; /* dynamic structures used by the parser */ TString *source; /* current source name */ TString *envn; /* environment variable name */ + TString *brkn; /* "break" name (used as a label) */ + TString *glbn; /* "global" name (when not a reserved word) */ } LexState; diff --git a/3rdparty/lua/plainlua/llimits.h b/3rdparty/lua/plainlua/llimits.h index 1c826f7be205..223b5e6c3418 100644 --- a/3rdparty/lua/plainlua/llimits.h +++ b/3rdparty/lua/plainlua/llimits.h @@ -15,49 +15,55 @@ #include "lua.h" +#define l_numbits(t) cast_int(sizeof(t) * CHAR_BIT) + /* -** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count -** the total memory used by Lua (in bytes). Usually, 'size_t' and -** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. +** 'l_mem' is a signed integer big enough to count the total memory +** used by Lua. (It is signed due to the use of debt in several +** computations.) Usually, 'ptrdiff_t' should work, but we use 'long' +** for 16-bit machines. */ #if defined(LUAI_MEM) /* { external definitions? */ -typedef LUAI_UMEM lu_mem; typedef LUAI_MEM l_mem; +typedef LUAI_UMEM lu_mem; #elif LUAI_IS32INT /* }{ */ -typedef size_t lu_mem; typedef ptrdiff_t l_mem; +typedef size_t lu_mem; #else /* 16-bit ints */ /* }{ */ -typedef unsigned long lu_mem; typedef long l_mem; +typedef unsigned long lu_mem; #endif /* } */ +#define MAX_LMEM \ + cast(l_mem, (cast(lu_mem, 1) << (l_numbits(l_mem) - 1)) - 1) + /* chars used as small naturals (so that 'char' is reserved for characters) */ typedef unsigned char lu_byte; typedef signed char ls_byte; +/* Type for thread status/error codes */ +typedef lu_byte TStatus; + +/* The C API still uses 'int' for status/error codes */ +#define APIstatus(st) cast_int(st) + /* maximum value for size_t */ #define MAX_SIZET ((size_t)(~(size_t)0)) -/* maximum size visible for Lua (must be representable in a lua_Integer) */ +/* +** Maximum size for strings and userdata visible for Lua; should be +** representable as a lua_Integer and as a size_t. +*/ #define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ - : (size_t)(LUA_MAXINTEGER)) - - -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) - -#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) - - -#define MAX_INT INT_MAX /* maximum value of an int */ - + : cast_sizet(LUA_MAXINTEGER)) /* ** floor of the log2 of the maximum signed value for integral type 't'. ** (That is, maximum 'n' such that '2^n' fits in the given signed type.) */ -#define log2maxs(t) (sizeof(t) * 8 - 2) +#define log2maxs(t) (l_numbits(t) - 2) /* @@ -88,7 +94,7 @@ typedef signed char ls_byte; #define L_P2I size_t #endif -#define point2uint(p) ((unsigned int)((L_P2I)(p) & UINT_MAX)) +#define point2uint(p) cast_uint((L_P2I)(p) & UINT_MAX) @@ -104,26 +110,18 @@ typedef LUAI_UACINT l_uacInt; #undef NDEBUG #include #define lua_assert(c) assert(c) +#define assert_code(c) c #endif #if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) -/* to avoid problems with conditions too long */ -#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) #else #define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) +#define assert_code(c) ((void)0) #endif -/* -** assertion for checking API calls -*/ -#if !defined(luai_apicheck) -#define luai_apicheck(l,e) ((void)l, lua_assert(e)) -#endif - -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) assert_code((c) ? (void)0 : lua_assert(0)) /* macro to avoid warnings about unused variables */ @@ -139,12 +137,15 @@ typedef LUAI_UACINT l_uacInt; #define cast_voidp(i) cast(void *, (i)) #define cast_num(i) cast(lua_Number, (i)) #define cast_int(i) cast(int, (i)) +#define cast_short(i) cast(short, (i)) #define cast_uint(i) cast(unsigned int, (i)) #define cast_byte(i) cast(lu_byte, (i)) #define cast_uchar(i) cast(unsigned char, (i)) #define cast_char(i) cast(char, (i)) #define cast_charp(i) cast(char *, (i)) #define cast_sizet(i) cast(size_t, (i)) +#define cast_Integer(i) cast(lua_Integer, (i)) +#define cast_Inst(i) cast(Instruction, (i)) /* cast a signed lua_Integer to lua_Unsigned */ @@ -161,6 +162,38 @@ typedef LUAI_UACINT l_uacInt; #define l_castU2S(i) ((lua_Integer)(i)) #endif +/* +** cast a size_t to lua_Integer: These casts are always valid for +** sizes of Lua objects (see MAX_SIZE) +*/ +#define cast_st2S(sz) ((lua_Integer)(sz)) + +/* Cast a ptrdiff_t to size_t, when it is known that the minuend +** comes from the subtrahend (the base) +*/ +#define ct_diff2sz(df) ((size_t)(df)) + +/* ptrdiff_t to lua_Integer */ +#define ct_diff2S(df) cast_st2S(ct_diff2sz(df)) + +/* +** Special type equivalent to '(void*)' for functions (to suppress some +** warnings when converting function pointers) +*/ +typedef void (*voidf)(void); + +/* +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. +** (The '__extension__' in gnu compilers is only to avoid warnings.) +*/ +#if defined(__GNUC__) +#define cast_func(p) (__extension__ (voidf)(p)) +#else +#define cast_func(p) ((voidf)(p)) +#endif + + /* ** non-return type @@ -193,8 +226,7 @@ typedef LUAI_UACINT l_uacInt; /* -** type for virtual-machine instructions; -** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +** An unsigned with (at least) 4 bytes */ #if LUAI_IS32INT typedef unsigned int l_uint32; @@ -202,107 +234,6 @@ typedef unsigned int l_uint32; typedef unsigned long l_uint32; #endif -typedef l_uint32 Instruction; - - - -/* -** Maximum length for short strings, that is, strings that are -** internalized. (Cannot be smaller than reserved words or tags for -** metamethods, as these strings must be internalized; -** #("function") = 8, #("__newindex") = 10.) -*/ -#if !defined(LUAI_MAXSHORTLEN) -#define LUAI_MAXSHORTLEN 40 -#endif - - -/* -** Initial size for the string table (must be power of 2). -** The Lua core alone registers ~50 strings (reserved words + -** metaevent keys + a few others). Libraries would typically add -** a few dozens more. -*/ -#if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 128 -#endif - - -/* -** Size of cache for strings in the API. 'N' is the number of -** sets (better be a prime) and "M" is the size of each set (M == 1 -** makes a direct cache.) -*/ -#if !defined(STRCACHE_N) -#define STRCACHE_N 53 -#define STRCACHE_M 2 -#endif - - -/* minimum size for string buffer */ -#if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 -#endif - - -/* -** Maximum depth for nested C calls, syntactical nested non-terminals, -** and other features implemented through recursion in C. (Value must -** fit in a 16-bit unsigned integer. It must also be compatible with -** the size of the C stack.) -*/ -#if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 -#endif - - -/* -** macros that are executed whenever program enters the Lua core -** ('lua_lock') and leaves the core ('lua_unlock') -*/ -#if !defined(lua_lock) -#define lua_lock(L) ((void) 0) -#define lua_unlock(L) ((void) 0) -#endif - -/* -** macro executed during Lua functions at points where the -** function can yield. -*/ -#if !defined(luai_threadyield) -#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} -#endif - - -/* -** these macros allow user-specific actions when a thread is -** created/deleted/resumed/yielded. -*/ -#if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) -#endif - -#if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) -#endif - -#if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) -#endif - -#if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) -#endif - -#if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) -#endif - -#if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) -#endif - - /* ** The luai_num* macros define the primitive operations over numbers. @@ -356,25 +287,29 @@ typedef l_uint32 Instruction; #endif - - - /* -** macro to control inclusion of some hard tests on stack reallocation +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== */ -#if !defined(HARDSTACKTESTS) -#define condmovestack(L,pre,pos) ((void)0) -#else -/* realloc stack keeping its size */ -#define condmovestack(L,pre,pos) \ - { int sz_ = stacksize(L); pre; luaD_reallocstack((L), sz_, 0); pos; } + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) #endif -#if !defined(HARDMEMTESTS) -#define condchangemem(L,pre,pos) ((void)0) -#else -#define condchangemem(L,pre,pos) \ - { if (gcrunning(G(L))) { pre; luaC_fullgc(L, 0); pos; } } +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) #endif +/* }================================================================== */ + #endif + diff --git a/3rdparty/lua/plainlua/lmathlib.c b/3rdparty/lua/plainlua/lmathlib.c index 438106348084..bd34c888602d 100644 --- a/3rdparty/lua/plainlua/lmathlib.c +++ b/3rdparty/lua/plainlua/lmathlib.c @@ -20,6 +20,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" #undef PI @@ -105,7 +106,7 @@ static int math_floor (lua_State *L) { static int math_ceil (lua_State *L) { if (lua_isinteger(L, 1)) - lua_settop(L, 1); /* integer is its own ceil */ + lua_settop(L, 1); /* integer is its own ceiling */ else { lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); pushnumint(L, d); @@ -366,25 +367,17 @@ static lua_Number I2d (Rand64 x) { #else /* no 'Rand64' }{ */ -/* get an integer with at least 32 bits */ -#if LUAI_IS32INT -typedef unsigned int lu_int32; -#else -typedef unsigned long lu_int32; -#endif - - /* ** Use two 32-bit integers to represent a 64-bit quantity. */ typedef struct Rand64 { - lu_int32 h; /* higher half */ - lu_int32 l; /* lower half */ + l_uint32 h; /* higher half */ + l_uint32 l; /* lower half */ } Rand64; /* -** If 'lu_int32' has more than 32 bits, the extra bits do not interfere +** If 'l_uint32' has more than 32 bits, the extra bits do not interfere ** with the 32 initial bits, except in a right shift and comparisons. ** Moreover, the final result has to discard the extra bits. */ @@ -398,7 +391,7 @@ typedef struct Rand64 { */ /* build a new Rand64 value */ -static Rand64 packI (lu_int32 h, lu_int32 l) { +static Rand64 packI (l_uint32 h, l_uint32 l) { Rand64 result; result.h = h; result.l = l; @@ -471,7 +464,7 @@ static Rand64 nextrand (Rand64 *state) { */ /* an unsigned 1 with proper type */ -#define UONE ((lu_int32)1) +#define UONE ((l_uint32)1) #if FIGS <= 32 @@ -522,7 +515,7 @@ static lua_Unsigned I2UInt (Rand64 x) { /* convert a 'lua_Unsigned' to a 'Rand64' */ static Rand64 Int2I (lua_Unsigned n) { - return packI((lu_int32)((n >> 31) >> 1), (lu_int32)n); + return packI((l_uint32)((n >> 31) >> 1), (l_uint32)n); } #endif /* } */ @@ -540,7 +533,7 @@ typedef struct { ** Project the random integer 'ran' into the interval [0, n]. ** Because 'ran' has 2^B possible values, the projection can only be ** uniform when the size of the interval is a power of 2 (exact -** division). Otherwise, to get a uniform projection into [0, n], we +** division). So, to get a uniform projection into [0, n], we ** first compute 'lim', the smallest Mersenne number not smaller than ** 'n'. We then project 'ran' into the interval [0, lim]. If the result ** is inside [0, n], we are done. Otherwise, we try with another 'ran', @@ -548,26 +541,14 @@ typedef struct { */ static lua_Unsigned project (lua_Unsigned ran, lua_Unsigned n, RanState *state) { - if ((n & (n + 1)) == 0) /* is 'n + 1' a power of 2? */ - return ran & n; /* no bias */ - else { - lua_Unsigned lim = n; - /* compute the smallest (2^b - 1) not smaller than 'n' */ - lim |= (lim >> 1); - lim |= (lim >> 2); - lim |= (lim >> 4); - lim |= (lim >> 8); - lim |= (lim >> 16); -#if (LUA_MAXUNSIGNED >> 31) >= 3 - lim |= (lim >> 32); /* integer type has more than 32 bits */ -#endif - lua_assert((lim & (lim + 1)) == 0 /* 'lim + 1' is a power of 2, */ - && lim >= n /* not smaller than 'n', */ - && (lim >> 1) < n); /* and it is the smallest one */ - while ((ran &= lim) > n) /* project 'ran' into [0..lim] */ - ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */ - return ran; - } + lua_Unsigned lim = n; /* to compute the Mersenne number */ + int sh; /* how much to spread bits to the right in 'lim' */ + /* spread '1' bits in 'lim' until it becomes a Mersenne number */ + for (sh = 1; (lim & (lim + 1)) != 0; sh *= 2) + lim |= (lim >> sh); /* spread '1's to the right */ + while ((ran &= lim) > n) /* project 'ran' into [0..lim] and test */ + ran = I2UInt(nextrand(state->s)); /* not inside [0..n]? try again */ + return ran; } @@ -585,7 +566,7 @@ static int math_random (lua_State *L) { low = 1; up = luaL_checkinteger(L, 1); if (up == 0) { /* single 0 as argument? */ - lua_pushinteger(L, I2UInt(rv)); /* full random integer */ + lua_pushinteger(L, l_castU2S(I2UInt(rv))); /* full random integer */ return 1; } break; @@ -600,8 +581,8 @@ static int math_random (lua_State *L) { /* random integer in the interval [low, up] */ luaL_argcheck(L, low <= up, 1, "interval is empty"); /* project random integer into the interval [0, up - low] */ - p = project(I2UInt(rv), (lua_Unsigned)up - (lua_Unsigned)low, state); - lua_pushinteger(L, p + (lua_Unsigned)low); + p = project(I2UInt(rv), l_castS2U(up) - l_castS2U(low), state); + lua_pushinteger(L, l_castU2S(p + l_castS2U(low))); return 1; } @@ -615,33 +596,23 @@ static void setseed (lua_State *L, Rand64 *state, state[3] = Int2I(0); for (i = 0; i < 16; i++) nextrand(state); /* discard initial values to "spread" seed */ - lua_pushinteger(L, n1); - lua_pushinteger(L, n2); -} - - -/* -** Set a "random" seed. To get some randomness, use the current time -** and the address of 'L' (in case the machine does address space layout -** randomization). -*/ -static void randseed (lua_State *L, RanState *state) { - lua_Unsigned seed1 = (lua_Unsigned)time(NULL); - lua_Unsigned seed2 = (lua_Unsigned)(size_t)L; - setseed(L, state->s, seed1, seed2); + lua_pushinteger(L, l_castU2S(n1)); + lua_pushinteger(L, l_castU2S(n2)); } static int math_randomseed (lua_State *L) { RanState *state = (RanState *)lua_touserdata(L, lua_upvalueindex(1)); + lua_Unsigned n1, n2; if (lua_isnone(L, 1)) { - randseed(L, state); + n1 = luaL_makeseed(L); /* "random" seed */ + n2 = I2UInt(nextrand(state->s)); /* in case seed is not that random... */ } else { - lua_Integer n1 = luaL_checkinteger(L, 1); - lua_Integer n2 = luaL_optinteger(L, 2, 0); - setseed(L, state->s, n1, n2); + n1 = l_castS2U(luaL_checkinteger(L, 1)); + n2 = l_castS2U(luaL_optinteger(L, 2, 0)); } + setseed(L, state->s, n1, n2); return 2; /* return seeds */ } @@ -658,7 +629,7 @@ static const luaL_Reg randfuncs[] = { */ static void setrandfunc (lua_State *L) { RanState *state = (RanState *)lua_newuserdatauv(L, sizeof(RanState), 0); - randseed(L, state); /* initialize with a "random" seed */ + setseed(L, state->s, luaL_makeseed(L), 0); /* initialize with random seed */ lua_pop(L, 2); /* remove pushed seeds */ luaL_setfuncs(L, randfuncs, 1); } diff --git a/3rdparty/lua/plainlua/lmem.c b/3rdparty/lua/plainlua/lmem.c index 9800a86fc024..de8503d91b9f 100644 --- a/3rdparty/lua/plainlua/lmem.c +++ b/3rdparty/lua/plainlua/lmem.c @@ -95,7 +95,7 @@ static void *firsttry (global_State *g, void *block, size_t os, size_t ns) { void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, - int size_elems, int limit, const char *what) { + unsigned size_elems, int limit, const char *what) { void *newblock; int size = *psize; if (nelems + 1 <= size) /* does one extra element still fit? */ @@ -126,10 +126,10 @@ void *luaM_growaux_ (lua_State *L, void *block, int nelems, int *psize, ** error. */ void *luaM_shrinkvector_ (lua_State *L, void *block, int *size, - int final_n, int size_elem) { + int final_n, unsigned size_elem) { void *newblock; - size_t oldsize = cast_sizet((*size) * size_elem); - size_t newsize = cast_sizet(final_n * size_elem); + size_t oldsize = cast_sizet(*size) * size_elem; + size_t newsize = cast_sizet(final_n) * size_elem; lua_assert(newsize <= oldsize); newblock = luaM_saferealloc_(L, block, oldsize, newsize); *size = final_n; @@ -151,7 +151,7 @@ void luaM_free_ (lua_State *L, void *block, size_t osize) { global_State *g = G(L); lua_assert((osize == 0) == (block == NULL)); callfrealloc(g, block, osize, 0); - g->GCdebt -= osize; + g->GCdebt += cast(l_mem, osize); } @@ -184,7 +184,7 @@ void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { return NULL; /* do not update 'GCdebt' */ } lua_assert((nsize == 0) == (newblock == NULL)); - g->GCdebt = (g->GCdebt + nsize) - osize; + g->GCdebt -= cast(l_mem, nsize) - cast(l_mem, osize); return newblock; } @@ -203,13 +203,13 @@ void *luaM_malloc_ (lua_State *L, size_t size, int tag) { return NULL; /* that's all */ else { global_State *g = G(L); - void *newblock = firsttry(g, NULL, tag, size); + void *newblock = firsttry(g, NULL, cast_sizet(tag), size); if (l_unlikely(newblock == NULL)) { - newblock = tryagain(L, NULL, tag, size); + newblock = tryagain(L, NULL, cast_sizet(tag), size); if (newblock == NULL) luaM_error(L); } - g->GCdebt += size; + g->GCdebt -= cast(l_mem, size); return newblock; } } diff --git a/3rdparty/lua/plainlua/lmem.h b/3rdparty/lua/plainlua/lmem.h index 8c75a44beb47..dc714fb2e489 100644 --- a/3rdparty/lua/plainlua/lmem.h +++ b/3rdparty/lua/plainlua/lmem.h @@ -39,11 +39,11 @@ ** Computes the minimum between 'n' and 'MAX_SIZET/sizeof(t)', so that ** the result is not larger than 'n' and cannot overflow a 'size_t' ** when multiplied by the size of type 't'. (Assumes that 'n' is an -** 'int' or 'unsigned int' and that 'int' is not larger than 'size_t'.) +** 'int' and that 'int' is not larger than 'size_t'.) */ #define luaM_limitN(n,t) \ ((cast_sizet(n) <= MAX_SIZET/sizeof(t)) ? (n) : \ - cast_uint((MAX_SIZET/sizeof(t)))) + cast_int((MAX_SIZET/sizeof(t)))) /* @@ -57,12 +57,15 @@ #define luaM_freearray(L, b, n) luaM_free_(L, (b), (n)*sizeof(*(b))) #define luaM_new(L,t) cast(t*, luaM_malloc_(L, sizeof(t), 0)) -#define luaM_newvector(L,n,t) cast(t*, luaM_malloc_(L, (n)*sizeof(t), 0)) +#define luaM_newvector(L,n,t) \ + cast(t*, luaM_malloc_(L, cast_sizet(n)*sizeof(t), 0)) #define luaM_newvectorchecked(L,n,t) \ (luaM_checksize(L,n,sizeof(t)), luaM_newvector(L,n,t)) #define luaM_newobject(L,tag,s) luaM_malloc_(L, (s), tag) +#define luaM_newblock(L, size) luaM_newvector(L, size, char) + #define luaM_growvector(L,v,nelems,size,t,limit,e) \ ((v)=cast(t *, luaM_growaux_(L,v,nelems,&(size),sizeof(t), \ luaM_limitN(limit,t),e))) @@ -83,10 +86,10 @@ LUAI_FUNC void *luaM_saferealloc_ (lua_State *L, void *block, size_t oldsize, size_t size); LUAI_FUNC void luaM_free_ (lua_State *L, void *block, size_t osize); LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int nelems, - int *size, int size_elem, int limit, + int *size, unsigned size_elem, int limit, const char *what); LUAI_FUNC void *luaM_shrinkvector_ (lua_State *L, void *block, int *nelem, - int final_n, int size_elem); + int final_n, unsigned size_elem); LUAI_FUNC void *luaM_malloc_ (lua_State *L, size_t size, int tag); #endif diff --git a/3rdparty/lua/plainlua/loadlib.c b/3rdparty/lua/plainlua/loadlib.c index 6d289fcebb8c..5f0c17029624 100644 --- a/3rdparty/lua/plainlua/loadlib.c +++ b/3rdparty/lua/plainlua/loadlib.c @@ -22,6 +22,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" /* @@ -58,11 +59,8 @@ static const char *const CLIBS = "_CLIBS"; #define setprogdir(L) ((void)0) -/* -** Special type equivalent to '(void*)' for functions in gcc -** (to suppress warnings when converting function pointers) -*/ -typedef void (*voidf)(void); +/* cast void* to a Lua function */ +#define cast_Lfunc(p) cast(lua_CFunction, cast_func(p)) /* @@ -95,26 +93,13 @@ static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); #if defined(LUA_USE_DLOPEN) /* { */ /* ** {======================================================================== -** This is an implementation of loadlib based on the dlfcn interface. -** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, -** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least -** as an emulation layer on top of native functions. +** This is an implementation of loadlib based on the dlfcn interface, +** which is available in all POSIX systems. ** ========================================================================= */ #include -/* -** Macro to convert pointer-to-void* to pointer-to-function. This cast -** is undefined according to ISO C, but POSIX assumes that it works. -** (The '__extension__' in gnu compilers is only to avoid warnings.) -*/ -#if defined(__GNUC__) -#define cast_func(p) (__extension__ (lua_CFunction)(p)) -#else -#define cast_func(p) ((lua_CFunction)(p)) -#endif - static void lsys_unloadlib (void *lib) { dlclose(lib); @@ -130,7 +115,7 @@ static void *lsys_load (lua_State *L, const char *path, int seeglb) { static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = cast_func(dlsym(lib, sym)); + lua_CFunction f = cast_Lfunc(dlsym(lib, sym)); if (l_unlikely(f == NULL)) lua_pushstring(L, dlerror()); return f; @@ -206,7 +191,7 @@ static void *lsys_load (lua_State *L, const char *path, int seeglb) { static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { - lua_CFunction f = (lua_CFunction)(voidf)GetProcAddress((HMODULE)lib, sym); + lua_CFunction f = cast_Lfunc(GetProcAddress((HMODULE)lib, sym)); if (f == NULL) pusherror(L); return f; } @@ -283,7 +268,8 @@ static int noenv (lua_State *L) { /* -** Set a path +** Set a path. (If using the default path, assume it is a string +** literal in C and create it as an external string.) */ static void setpath (lua_State *L, const char *fieldname, const char *envname, @@ -294,7 +280,7 @@ static void setpath (lua_State *L, const char *fieldname, if (path == NULL) /* no versioned environment variable? */ path = getenv(envname); /* try unversioned name */ if (path == NULL || noenv(L)) /* no environment variable? */ - lua_pushstring(L, dft); /* use default */ + lua_pushexternalstring(L, dft, strlen(dft), NULL, NULL); /* use default */ else if ((dftmark = strstr(path, LUA_PATH_SEP LUA_PATH_SEP)) == NULL) lua_pushstring(L, path); /* nothing to change */ else { /* path contains a ";;": insert default path in its place */ @@ -302,13 +288,13 @@ static void setpath (lua_State *L, const char *fieldname, luaL_Buffer b; luaL_buffinit(L, &b); if (path < dftmark) { /* is there a prefix before ';;'? */ - luaL_addlstring(&b, path, dftmark - path); /* add it */ + luaL_addlstring(&b, path, ct_diff2sz(dftmark - path)); /* add it */ luaL_addchar(&b, *LUA_PATH_SEP); } luaL_addstring(&b, dft); /* add default */ if (dftmark < path + len - 2) { /* is there a suffix after ';;'? */ luaL_addchar(&b, *LUA_PATH_SEP); - luaL_addlstring(&b, dftmark + 2, (path + len - 2) - dftmark); + luaL_addlstring(&b, dftmark + 2, ct_diff2sz((path + len - 2) - dftmark)); } luaL_pushresult(&b); } @@ -557,7 +543,7 @@ static int loadfunc (lua_State *L, const char *filename, const char *modname) { mark = strchr(modname, *LUA_IGMARK); if (mark) { int stat; - openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushlstring(L, modname, ct_diff2sz(mark - modname)); openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); stat = lookforfunc(L, filename, openfunc); if (stat != ERRFUNC) return stat; @@ -582,7 +568,7 @@ static int searcher_Croot (lua_State *L) { const char *p = strchr(name, '.'); int stat; if (p == NULL) return 0; /* is root */ - lua_pushlstring(L, name, p - name); + lua_pushlstring(L, name, ct_diff2sz(p - name)); filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); if (filename == NULL) return 1; /* root not found */ if ((stat = loadfunc(L, filename, name)) != 0) { @@ -620,12 +606,12 @@ static void findloader (lua_State *L, const char *name) { != LUA_TTABLE)) luaL_error(L, "'package.searchers' must be a table"); luaL_buffinit(L, &msg); + luaL_addstring(&msg, "\n\t"); /* error-message prefix for first message */ /* iterate over available searchers to find a loader */ for (i = 1; ; i++) { - luaL_addstring(&msg, "\n\t"); /* error-message prefix */ if (l_unlikely(lua_rawgeti(L, 3, i) == LUA_TNIL)) { /* no more searchers? */ lua_pop(L, 1); /* remove nil */ - luaL_buffsub(&msg, 2); /* remove prefix */ + luaL_buffsub(&msg, 2); /* remove last prefix */ luaL_pushresult(&msg); /* create error message */ luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); } @@ -636,11 +622,10 @@ static void findloader (lua_State *L, const char *name) { else if (lua_isstring(L, -2)) { /* searcher returned error message? */ lua_pop(L, 1); /* remove extra return */ luaL_addvalue(&msg); /* concatenate error message */ + luaL_addstring(&msg, "\n\t"); /* prefix for next message */ } - else { /* no error message */ + else /* no error message */ lua_pop(L, 2); /* remove both returns */ - luaL_buffsub(&msg, 2); /* remove prefix */ - } } } diff --git a/3rdparty/lua/plainlua/lobject.c b/3rdparty/lua/plainlua/lobject.c index 9cfa5227eb46..1c32ecf7a9c6 100644 --- a/3rdparty/lua/plainlua/lobject.c +++ b/3rdparty/lua/plainlua/lobject.c @@ -10,6 +10,7 @@ #include "lprefix.h" +#include #include #include #include @@ -32,8 +33,8 @@ /* ** Computes ceil(log2(x)) */ -int luaO_ceillog2 (unsigned int x) { - static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ +lu_byte luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { /* log_2[i - 1] = ceil(log2(i)) */ 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, @@ -46,7 +47,67 @@ int luaO_ceillog2 (unsigned int x) { int l = 0; x--; while (x >= 256) { l += 8; x >>= 8; } - return l + log_2[x]; + return cast_byte(l + log_2[x]); +} + +/* +** Encodes 'p'% as a floating-point byte, represented as (eeeexxxx). +** The exponent is represented using excess-7. Mimicking IEEE 754, the +** representation normalizes the number when possible, assuming an extra +** 1 before the mantissa (xxxx) and adding one to the exponent (eeee) +** to signal that. So, the real value is (1xxxx) * 2^(eeee - 7 - 1) if +** eeee != 0, and (xxxx) * 2^-7 otherwise (subnormal numbers). +*/ +lu_byte luaO_codeparam (unsigned int p) { + if (p >= (cast(lu_mem, 0x1F) << (0xF - 7 - 1)) * 100u) /* overflow? */ + return 0xFF; /* return maximum value */ + else { + p = (cast(l_uint32, p) * 128 + 99) / 100; /* round up the division */ + if (p < 0x10) { /* subnormal number? */ + /* exponent bits are already zero; nothing else to do */ + return cast_byte(p); + } + else { /* p >= 0x10 implies ceil(log2(p + 1)) >= 5 */ + /* preserve 5 bits in 'p' */ + unsigned log = luaO_ceillog2(p + 1) - 5u; + return cast_byte(((p >> log) - 0x10) | ((log + 1) << 4)); + } + } +} + + +/* +** Computes 'p' times 'x', where 'p' is a floating-point byte. Roughly, +** we have to multiply 'x' by the mantissa and then shift accordingly to +** the exponent. If the exponent is positive, both the multiplication +** and the shift increase 'x', so we have to care only about overflows. +** For negative exponents, however, multiplying before the shift keeps +** more significant bits, as long as the multiplication does not +** overflow, so we check which order is best. +*/ +l_mem luaO_applyparam (lu_byte p, l_mem x) { + unsigned int m = p & 0xF; /* mantissa */ + int e = (p >> 4); /* exponent */ + if (e > 0) { /* normalized? */ + e--; /* correct exponent */ + m += 0x10; /* correct mantissa; maximum value is 0x1F */ + } + e -= 7; /* correct excess-7 */ + if (e >= 0) { + if (x < (MAX_LMEM / 0x1F) >> e) /* no overflow? */ + return (x * m) << e; /* order doesn't matter here */ + else /* real overflow */ + return MAX_LMEM; + } + else { /* negative exponent */ + e = -e; + if (x < MAX_LMEM / 0x1F) /* multiplication cannot overflow? */ + return (x * m) >> e; /* multiplying first gives more precision */ + else if ((x >> e) < MAX_LMEM / 0x1F) /* cannot overflow after shift? */ + return (x >> e) * m; + else /* real overflow */ + return MAX_LMEM; + } } @@ -132,9 +193,10 @@ void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, } -int luaO_hexavalue (int c) { - if (lisdigit(c)) return c - '0'; - else return (ltolower(c) - 'a') + 10; +lu_byte luaO_hexavalue (int c) { + lua_assert(lisxdigit(c)); + if (lisdigit(c)) return cast_byte(c - '0'); + else return cast_byte((ltolower(c) - 'a') + 10); } @@ -185,7 +247,7 @@ static lua_Number lua_strx2number (const char *s, char **endptr) { nosigdig++; else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ r = (r * l_mathop(16.0)) + luaO_hexavalue(*s); - else e++; /* too many digits; ignore, but still count for exponent */ + else e++; /* too many digits; ignore, but still count for exponent */ if (hasdot) e--; /* decimal digit? correct exponent */ } else break; /* neither a dot nor a digit */ @@ -292,7 +354,7 @@ static const char *l_str2int (const char *s, lua_Integer *result) { int d = *s - '0'; if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ return NULL; /* do not accept it (as integer) */ - a = a * 10 + d; + a = a * 10 + cast_uint(d); empty = 0; } } @@ -316,11 +378,11 @@ size_t luaO_str2num (const char *s, TValue *o) { } else return 0; /* conversion failed */ - return (e - s) + 1; /* success; return string size */ + return ct_diff2sz(e - s) + 1; /* success; return string size */ } -int luaO_utf8esc (char *buff, unsigned long x) { +int luaO_utf8esc (char *buff, l_uint32 x) { int n = 1; /* number of bytes put in buffer (backwards) */ lua_assert(x <= 0x7FFFFFFFu); if (x < 0x80) /* ascii? */ @@ -339,32 +401,59 @@ int luaO_utf8esc (char *buff, unsigned long x) { /* -** Maximum length of the conversion of a number to a string. Must be -** enough to accommodate both LUA_INTEGER_FMT and LUA_NUMBER_FMT. -** (For a long long int, this is 19 digits plus a sign and a final '\0', -** adding to 21. For a long double, it can go to a sign, 33 digits, -** the dot, an exponent letter, an exponent sign, 5 exponent digits, -** and a final '\0', adding to 43.) +** The size of the buffer for the conversion of a number to a string +** 'LUA_N2SBUFFSZ' must be enough to accommodate both LUA_INTEGER_FMT +** and LUA_NUMBER_FMT. For a long long int, this is 19 digits plus a +** sign and a final '\0', adding to 21. For a long double, it can go to +** a sign, the dot, an exponent letter, an exponent sign, 4 exponent +** digits, the final '\0', plus the significant digits, which are +** approximately the *_DIG attribute. */ -#define MAXNUMBER2STR 44 +#if LUA_N2SBUFFSZ < (20 + l_floatatt(DIG)) +#error "invalid value for LUA_N2SBUFFSZ" +#endif /* -** Convert a number object to a string, adding it to a buffer +** Convert a float to a string, adding it to a buffer. First try with +** a not too large number of digits, to avoid noise (for instance, +** 1.1 going to "1.1000000000000001"). If that lose precision, so +** that reading the result back gives a different number, then do the +** conversion again with extra precision. Moreover, if the numeral looks +** like an integer (without a decimal point or an exponent), add ".0" to +** its end. */ -static int tostringbuff (TValue *obj, char *buff) { +static int tostringbuffFloat (lua_Number n, char *buff) { + /* first conversion */ + int len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT, + (LUAI_UACNUMBER)n); + lua_Number check = lua_str2number(buff, NULL); /* read it back */ + if (check != n) { /* not enough precision? */ + /* convert again with more precision */ + len = l_sprintf(buff, LUA_N2SBUFFSZ, LUA_NUMBER_FMT_N, + (LUAI_UACNUMBER)n); + } + /* looks like an integer? */ + if (buff[strspn(buff, "-0123456789")] == '\0') { + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } + return len; +} + + +/* +** Convert a number object to a string, adding it to a buffer. +*/ +unsigned luaO_tostringbuff (const TValue *obj, char *buff) { int len; lua_assert(ttisnumber(obj)); if (ttisinteger(obj)) - len = lua_integer2str(buff, MAXNUMBER2STR, ivalue(obj)); - else { - len = lua_number2str(buff, MAXNUMBER2STR, fltvalue(obj)); - if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ - buff[len++] = lua_getlocaledecpoint(); - buff[len++] = '0'; /* adds '.0' to result */ - } - } - return len; + len = lua_integer2str(buff, LUA_N2SBUFFSZ, ivalue(obj)); + else + len = tostringbuffFloat(fltvalue(obj), buff); + lua_assert(len < LUA_N2SBUFFSZ); + return cast_uint(len); } @@ -372,8 +461,8 @@ static int tostringbuff (TValue *obj, char *buff) { ** Convert a number object to a Lua string, replacing the value at 'obj' */ void luaO_tostring (lua_State *L, TValue *obj) { - char buff[MAXNUMBER2STR]; - int len = tostringbuff(obj, buff); + char buff[LUA_N2SBUFFSZ]; + unsigned len = luaO_tostringbuff(obj, buff); setsvalue(L, obj, luaS_newlstr(L, buff, len)); } @@ -388,78 +477,104 @@ void luaO_tostring (lua_State *L, TValue *obj) { /* ** Size for buffer space used by 'luaO_pushvfstring'. It should be -** (LUA_IDSIZE + MAXNUMBER2STR) + a minimal space for basic messages, -** so that 'luaG_addinfo' can work directly on the buffer. +** (LUA_IDSIZE + LUA_N2SBUFFSZ) + a minimal space for basic messages, +** so that 'luaG_addinfo' can work directly on the static buffer. */ -#define BUFVFS (LUA_IDSIZE + MAXNUMBER2STR + 95) +#define BUFVFS cast_uint(LUA_IDSIZE + LUA_N2SBUFFSZ + 95) -/* buffer used by 'luaO_pushvfstring' */ +/* +** Buffer used by 'luaO_pushvfstring'. 'err' signals an error while +** building result (memory error [1] or buffer overflow [2]). +*/ typedef struct BuffFS { lua_State *L; - int pushed; /* true if there is a part of the result on the stack */ - int blen; /* length of partial string in 'space' */ - char space[BUFVFS]; /* holds last part of the result */ + char *b; + size_t buffsize; + size_t blen; /* length of string in 'buff' */ + int err; + char space[BUFVFS]; /* initial buffer */ } BuffFS; -/* -** Push given string to the stack, as part of the result, and -** join it to previous partial result if there is one. -** It may call 'luaV_concat' while using one slot from EXTRA_STACK. -** This call cannot invoke metamethods, as both operands must be -** strings. It can, however, raise an error if the result is too -** long. In that case, 'luaV_concat' frees the extra slot before -** raising the error. -*/ -static void pushstr (BuffFS *buff, const char *str, size_t lstr) { - lua_State *L = buff->L; - setsvalue2s(L, L->top.p, luaS_newlstr(L, str, lstr)); - L->top.p++; /* may use one slot from EXTRA_STACK */ - if (!buff->pushed) /* no previous string on the stack? */ - buff->pushed = 1; /* now there is one */ - else /* join previous string with new one */ - luaV_concat(L, 2); +static void initbuff (lua_State *L, BuffFS *buff) { + buff->L = L; + buff->b = buff->space; + buff->buffsize = sizeof(buff->space); + buff->blen = 0; + buff->err = 0; } /* -** empty the buffer space into the stack +** Push final result from 'luaO_pushvfstring'. This function may raise +** errors explicitly or through memory errors, so it must run protected. */ -static void clearbuff (BuffFS *buff) { - pushstr(buff, buff->space, buff->blen); /* push buffer contents */ - buff->blen = 0; /* space now is empty */ +static void pushbuff (lua_State *L, void *ud) { + BuffFS *buff = cast(BuffFS*, ud); + switch (buff->err) { + case 1: /* memory error */ + luaD_throw(L, LUA_ERRMEM); + break; + case 2: /* length overflow: Add "..." at the end of result */ + if (buff->buffsize - buff->blen < 3) + strcpy(buff->b + buff->blen - 3, "..."); /* 'blen' must be > 3 */ + else { /* there is enough space left for the "..." */ + strcpy(buff->b + buff->blen, "..."); + buff->blen += 3; + } + /* FALLTHROUGH */ + default: { /* no errors, but it can raise one creating the new string */ + TString *ts = luaS_newlstr(L, buff->b, buff->blen); + setsvalue2s(L, L->top.p, ts); + L->top.p++; + } + } } -/* -** Get a space of size 'sz' in the buffer. If buffer has not enough -** space, empty it. 'sz' must fit in an empty buffer. -*/ -static char *getbuff (BuffFS *buff, int sz) { - lua_assert(buff->blen <= BUFVFS); lua_assert(sz <= BUFVFS); - if (sz > BUFVFS - buff->blen) /* not enough space? */ - clearbuff(buff); - return buff->space + buff->blen; +static const char *clearbuff (BuffFS *buff) { + lua_State *L = buff->L; + const char *res; + if (luaD_rawrunprotected(L, pushbuff, buff) != LUA_OK) /* errors? */ + res = NULL; /* error message is on the top of the stack */ + else + res = getstr(tsvalue(s2v(L->top.p - 1))); + if (buff->b != buff->space) /* using dynamic buffer? */ + luaM_freearray(L, buff->b, buff->buffsize); /* free it */ + return res; } -#define addsize(b,sz) ((b)->blen += (sz)) - - -/* -** Add 'str' to the buffer. If string is larger than the buffer space, -** push the string directly to the stack. -*/ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { - if (slen <= BUFVFS) { /* does string fit into buffer? */ - char *bf = getbuff(buff, cast_int(slen)); - memcpy(bf, str, slen); /* add string to buffer */ - addsize(buff, cast_int(slen)); - } - else { /* string larger than buffer */ - clearbuff(buff); /* string comes after buffer's content */ - pushstr(buff, str, slen); /* push string */ + size_t left = buff->buffsize - buff->blen; /* space left in the buffer */ + if (buff->err) /* do nothing else after an error */ + return; + if (slen > left) { /* new string doesn't fit into current buffer? */ + if (slen > ((MAX_SIZE/2) - buff->blen)) { /* overflow? */ + memcpy(buff->b + buff->blen, str, left); /* copy what it can */ + buff->blen = buff->buffsize; + buff->err = 2; /* doesn't add anything else */ + return; + } + else { + size_t newsize = buff->buffsize + slen; /* limited to MAX_SIZE/2 */ + char *newb = + (buff->b == buff->space) /* still using static space? */ + ? luaM_reallocvector(buff->L, NULL, 0, newsize, char) + : luaM_reallocvector(buff->L, buff->b, buff->buffsize, newsize, + char); + if (newb == NULL) { /* allocation error? */ + buff->err = 1; /* signal a memory error */ + return; + } + if (buff->b == buff->space) /* new buffer (not reallocated)? */ + memcpy(newb, buff->b, buff->blen); /* copy previous content */ + buff->b = newb; /* set new (larger) buffer... */ + buff->buffsize = newsize; /* ...and its new size */ + } } + memcpy(buff->b + buff->blen, str, slen); /* copy new content */ + buff->blen += slen; } @@ -467,9 +582,9 @@ static void addstr2buff (BuffFS *buff, const char *str, size_t slen) { ** Add a numeral to the buffer. */ static void addnum2buff (BuffFS *buff, TValue *num) { - char *numbuff = getbuff(buff, MAXNUMBER2STR); - int len = tostringbuff(num, numbuff); /* format number into 'numbuff' */ - addsize(buff, len); + char numbuff[LUA_N2SBUFFSZ]; + unsigned len = luaO_tostringbuff(num, numbuff); + addstr2buff(buff, numbuff, len); } @@ -480,10 +595,9 @@ static void addnum2buff (BuffFS *buff, TValue *num) { const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { BuffFS buff; /* holds last part of the result */ const char *e; /* points to next '%' */ - buff.pushed = buff.blen = 0; - buff.L = L; + initbuff(L, &buff); while ((e = strchr(fmt, '%')) != NULL) { - addstr2buff(&buff, fmt, e - fmt); /* add 'fmt' up to '%' */ + addstr2buff(&buff, fmt, ct_diff2sz(e - fmt)); /* add 'fmt' up to '%' */ switch (*(e + 1)) { /* conversion specifier */ case 's': { /* zero-terminated string */ const char *s = va_arg(argp, char *); @@ -492,7 +606,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'c': { /* an 'int' as a character */ - char c = cast_uchar(va_arg(argp, int)); + char c = cast_char(va_arg(argp, int)); addstr2buff(&buff, &c, sizeof(char)); break; } @@ -504,7 +618,7 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { } case 'I': { /* a 'lua_Integer' */ TValue num; - setivalue(&num, cast(lua_Integer, va_arg(argp, l_uacInt))); + setivalue(&num, cast_Integer(va_arg(argp, l_uacInt))); addnum2buff(&buff, &num); break; } @@ -515,17 +629,17 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } case 'p': { /* a pointer */ - const int sz = 3 * sizeof(void*) + 8; /* enough space for '%p' */ - char *bf = getbuff(&buff, sz); + char bf[LUA_N2SBUFFSZ]; /* enough space for '%p' */ void *p = va_arg(argp, void *); - int len = lua_pointer2str(bf, sz, p); - addsize(&buff, len); + int len = lua_pointer2str(bf, LUA_N2SBUFFSZ, p); + addstr2buff(&buff, bf, cast_uint(len)); break; } - case 'U': { /* a 'long' as a UTF-8 sequence */ + case 'U': { /* an 'unsigned long' as a UTF-8 sequence */ char bf[UTF8BUFFSZ]; - int len = luaO_utf8esc(bf, va_arg(argp, long)); - addstr2buff(&buff, bf + UTF8BUFFSZ - len, len); + unsigned long arg = va_arg(argp, unsigned long); + int len = luaO_utf8esc(bf, cast(l_uint32, arg)); + addstr2buff(&buff, bf + UTF8BUFFSZ - len, cast_uint(len)); break; } case '%': { @@ -533,16 +647,14 @@ const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { break; } default: { - luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", - *(e + 1)); + addstr2buff(&buff, e, 2); /* keep unknown format in the result */ + break; } } fmt = e + 2; /* skip '%' and the specifier */ } addstr2buff(&buff, fmt, strlen(fmt)); /* rest of 'fmt' */ - clearbuff(&buff); /* empty buffer into the stack */ - lua_assert(buff.pushed == 1); - return getstr(tsvalue(s2v(L->top.p - 1))); + return clearbuff(&buff); /* empty buffer into a new string */ } @@ -552,6 +664,8 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { va_start(argp, fmt); msg = luaO_pushvfstring(L, fmt, argp); va_end(argp); + if (msg == NULL) /* error? */ + luaD_throw(L, LUA_ERRMEM); return msg; } @@ -591,7 +705,8 @@ void luaO_chunkid (char *out, const char *source, size_t srclen) { addstr(out, source, srclen); /* keep it */ } else { - if (nl != NULL) srclen = nl - source; /* stop at first newline */ + if (nl != NULL) + srclen = ct_diff2sz(nl - source); /* stop at first newline */ if (srclen > bufflen) srclen = bufflen; addstr(out, source, srclen); addstr(out, RETS, LL(RETS)); diff --git a/3rdparty/lua/plainlua/lobject.h b/3rdparty/lua/plainlua/lobject.h index 980e42f8c27a..bc2f69ab4acc 100644 --- a/3rdparty/lua/plainlua/lobject.h +++ b/3rdparty/lua/plainlua/lobject.h @@ -188,10 +188,21 @@ typedef union { /* Value returned for a key not found in a table (absent key) */ #define LUA_VABSTKEY makevariant(LUA_TNIL, 2) +/* Special variant to signal that a fast get is accessing a non-table */ +#define LUA_VNOTABLE makevariant(LUA_TNIL, 3) + /* macro to test for (any kind of) nil */ #define ttisnil(v) checktype((v), LUA_TNIL) +/* +** Macro to test the result of a table access. Formally, it should +** distinguish between LUA_VEMPTY/LUA_VABSTKEY/LUA_VNOTABLE and +** other tags. As currently nil is equivalent to LUA_VEMPTY, it is +** simpler to just test whether the value is nil. +*/ +#define tagisempty(tag) (novariant(tag) == LUA_TNIL) + /* macro to test for a standard nil */ #define ttisstrictnil(o) checktag((o), LUA_VNIL) @@ -245,6 +256,8 @@ typedef union { #define l_isfalse(o) (ttisfalse(o) || ttisnil(o)) +#define tagisfalse(t) ((t) == LUA_VFALSE || novariant(t) == LUA_TNIL) + #define setbfvalue(obj) settt_(obj, LUA_VFALSE) @@ -380,35 +393,53 @@ typedef struct GCObject { #define setsvalue2n setsvalue +/* Kinds of long strings (stored in 'shrlen') */ +#define LSTRREG -1 /* regular long string */ +#define LSTRFIX -2 /* fixed external long string */ +#define LSTRMEM -3 /* external long string with deallocation */ + + /* ** Header for a string value. */ typedef struct TString { CommonHeader; lu_byte extra; /* reserved words for short strings; "has hash" for longs */ - lu_byte shrlen; /* length for short strings, 0xFF for long strings */ + ls_byte shrlen; /* length for short strings, negative for long strings */ unsigned int hash; union { size_t lnglen; /* length for long strings */ struct TString *hnext; /* linked list for hash table */ } u; - char contents[1]; + char *contents; /* pointer to content in long strings */ + lua_Alloc falloc; /* deallocation function for external strings */ + void *ud; /* user data for external strings */ } TString; +#define strisshr(ts) ((ts)->shrlen >= 0) + /* ** Get the actual string (array of bytes) from a 'TString'. (Generic ** version and specialized versions for long and short strings.) */ -#define getstr(ts) ((ts)->contents) -#define getlngstr(ts) check_exp((ts)->shrlen == 0xFF, (ts)->contents) -#define getshrstr(ts) check_exp((ts)->shrlen != 0xFF, (ts)->contents) +#define rawgetshrstr(ts) (cast_charp(&(ts)->contents)) +#define getshrstr(ts) check_exp(strisshr(ts), rawgetshrstr(ts)) +#define getlngstr(ts) check_exp(!strisshr(ts), (ts)->contents) +#define getstr(ts) (strisshr(ts) ? rawgetshrstr(ts) : (ts)->contents) + +/* get string length from 'TString *ts' */ +#define tsslen(ts) \ + (strisshr(ts) ? cast_sizet((ts)->shrlen) : (ts)->u.lnglen) -/* get string length from 'TString *s' */ -#define tsslen(s) \ - ((s)->shrlen != 0xFF ? (s)->shrlen : (s)->u.lnglen) +/* +** Get string and length */ +#define getlstr(ts, len) \ + (strisshr(ts) \ + ? (cast_void((len) = cast_sizet((ts)->shrlen)), rawgetshrstr(ts)) \ + : (cast_void((len) = (ts)->u.lnglen), (ts)->contents)) /* }================================================================== */ @@ -486,8 +517,8 @@ typedef struct Udata0 { /* compute the offset of the memory area of a userdata */ #define udatamemoffset(nuv) \ - ((nuv) == 0 ? offsetof(Udata0, bindata) \ - : offsetof(Udata, uv) + (sizeof(UValue) * (nuv))) + ((nuv) == 0 ? offsetof(Udata0, bindata) \ + : offsetof(Udata, uv) + (sizeof(UValue) * (nuv))) /* get the address of the memory block inside 'Udata' */ #define getudatamem(u) (cast_charp(u) + udatamemoffset((u)->nuvalue)) @@ -507,6 +538,9 @@ typedef struct Udata0 { #define LUA_VPROTO makevariant(LUA_TPROTO, 0) +typedef l_uint32 Instruction; + + /* ** Description of an upvalue for function prototypes */ @@ -544,13 +578,21 @@ typedef struct AbsLineInfo { int line; } AbsLineInfo; + +/* +** Flags in Prototypes +*/ +#define PF_ISVARARG 1 +#define PF_FIXED 2 /* prototype has parts in fixed memory */ + + /* ** Function Prototypes */ typedef struct Proto { CommonHeader; lu_byte numparams; /* number of fixed (named) parameters */ - lu_byte is_vararg; + lu_byte flag; lu_byte maxstacksize; /* number of registers needed by this function */ int sizeupvalues; /* size of 'upvalues' */ int sizek; /* size of 'k' */ @@ -708,10 +750,9 @@ typedef union Node { /* copy a value into a key */ -#define setnodekey(L,node,obj) \ +#define setnodekey(node,obj) \ { Node *n_=(node); const TValue *io_=(obj); \ - n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; \ - checkliveness(L,io_); } + n_->u.key_val = io_->value_; n_->u.key_tt = io_->tt_; } /* copy a value from a key */ @@ -721,27 +762,14 @@ typedef union Node { checkliveness(L,io_); } -/* -** About 'alimit': if 'isrealasize(t)' is true, then 'alimit' is the -** real size of 'array'. Otherwise, the real size of 'array' is the -** smallest power of two not smaller than 'alimit' (or zero iff 'alimit' -** is zero); 'alimit' is then used as a hint for #t. -*/ - -#define BITRAS (1 << 7) -#define isrealasize(t) (!((t)->flags & BITRAS)) -#define setrealasize(t) ((t)->flags &= cast_byte(~BITRAS)) -#define setnorealasize(t) ((t)->flags |= BITRAS) - typedef struct Table { CommonHeader; lu_byte flags; /* 1<

lsizenode)) /* size of buffer for 'luaO_utf8esc' function */ #define UTF8BUFFSZ 8 -LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); -LUAI_FUNC int luaO_ceillog2 (unsigned int x); + +/* macro to call 'luaO_pushvfstring' correctly */ +#define pushvfstring(L, argp, fmt, msg) \ + { va_start(argp, fmt); \ + msg = luaO_pushvfstring(L, fmt, argp); \ + va_end(argp); \ + if (msg == NULL) luaD_throw(L, LUA_ERRMEM); /* only after 'va_end' */ } + + +LUAI_FUNC int luaO_utf8esc (char *buff, l_uint32 x); +LUAI_FUNC lu_byte luaO_ceillog2 (unsigned int x); +LUAI_FUNC lu_byte luaO_codeparam (unsigned int p); +LUAI_FUNC l_mem luaO_applyparam (lu_byte p, l_mem x); + LUAI_FUNC int luaO_rawarith (lua_State *L, int op, const TValue *p1, const TValue *p2, TValue *res); LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, StkId res); LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); -LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC unsigned luaO_tostringbuff (const TValue *obj, char *buff); +LUAI_FUNC lu_byte luaO_hexavalue (int c); LUAI_FUNC void luaO_tostring (lua_State *L, TValue *obj); LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp); diff --git a/3rdparty/lua/plainlua/lopcodes.c b/3rdparty/lua/plainlua/lopcodes.c index c67aa227c587..092c39020640 100644 --- a/3rdparty/lua/plainlua/lopcodes.c +++ b/3rdparty/lua/plainlua/lopcodes.c @@ -13,6 +13,10 @@ #include "lopcodes.h" +#define opmode(mm,ot,it,t,a,m) \ + (((mm) << 7) | ((ot) << 6) | ((it) << 5) | ((t) << 4) | ((a) << 3) | (m)) + + /* ORDER OP */ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { @@ -36,7 +40,7 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETTABLE */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETI */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_SETFIELD */ - ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NEWTABLE */ + ,opmode(0, 0, 0, 0, 1, ivABC) /* OP_NEWTABLE */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SELF */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDI */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_ADDK */ @@ -64,8 +68,8 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHL */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_SHR */ ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBIN */ - ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI*/ - ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK*/ + ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINI */ + ,opmode(1, 0, 0, 0, 0, iABC) /* OP_MMBINK */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_UNM */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_BNOT */ ,opmode(0, 0, 0, 0, 1, iABC) /* OP_NOT */ @@ -95,10 +99,40 @@ LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { ,opmode(0, 0, 0, 0, 0, iABx) /* OP_TFORPREP */ ,opmode(0, 0, 0, 0, 0, iABC) /* OP_TFORCALL */ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_TFORLOOP */ - ,opmode(0, 0, 1, 0, 0, iABC) /* OP_SETLIST */ + ,opmode(0, 0, 1, 0, 0, ivABC) /* OP_SETLIST */ ,opmode(0, 0, 0, 0, 1, iABx) /* OP_CLOSURE */ ,opmode(0, 1, 0, 0, 1, iABC) /* OP_VARARG */ ,opmode(0, 0, 1, 0, 1, iABC) /* OP_VARARGPREP */ ,opmode(0, 0, 0, 0, 0, iAx) /* OP_EXTRAARG */ }; + + +/* +** Check whether instruction sets top for next instruction, that is, +** it results in multiple values. +*/ +int luaP_isOT (Instruction i) { + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_TAILCALL: return 1; + default: + return testOTMode(op) && GETARG_C(i) == 0; + } +} + + +/* +** Check whether instruction uses top from previous instruction, that is, +** it accepts multiple results. +*/ +int luaP_isIT (Instruction i) { + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_SETLIST: + return testITMode(GET_OPCODE(i)) && GETARG_vB(i) == 0; + default: + return testITMode(GET_OPCODE(i)) && GETARG_B(i) == 0; + } +} + diff --git a/3rdparty/lua/plainlua/lopcodes.h b/3rdparty/lua/plainlua/lopcodes.h index 46911cac14e0..9787003846ad 100644 --- a/3rdparty/lua/plainlua/lopcodes.h +++ b/3rdparty/lua/plainlua/lopcodes.h @@ -8,6 +8,7 @@ #define lopcodes_h #include "llimits.h" +#include "lobject.h" /*=========================================================================== @@ -18,25 +19,30 @@ 3 3 2 2 2 2 2 2 2 2 2 2 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 9 8 7 6 5 4 3 2 1 0 iABC C(8) | B(8) |k| A(8) | Op(7) | +ivABC vC(10) | vB(6) |k| A(8) | Op(7) | iABx Bx(17) | A(8) | Op(7) | iAsBx sBx (signed)(17) | A(8) | Op(7) | iAx Ax(25) | Op(7) | isJ sJ (signed)(25) | Op(7) | - A signed argument is represented in excess K: the represented value is - the written unsigned value minus K, where K is half the maximum for the - corresponding unsigned argument. + ('v' stands for "variant", 's' for "signed", 'x' for "extended".) + A signed argument is represented in excess K: The represented value is + the written unsigned value minus K, where K is half (rounded down) the + maximum value for the corresponding unsigned argument. ===========================================================================*/ -enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ +/* basic instruction formats */ +enum OpMode {iABC, ivABC, iABx, iAsBx, iAx, isJ}; /* ** size and position of opcode arguments. */ #define SIZE_C 8 +#define SIZE_vC 10 #define SIZE_B 8 +#define SIZE_vB 6 #define SIZE_Bx (SIZE_C + SIZE_B + 1) #define SIZE_A 8 #define SIZE_Ax (SIZE_Bx + SIZE_A) @@ -49,7 +55,9 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ #define POS_A (POS_OP + SIZE_OP) #define POS_k (POS_A + SIZE_A) #define POS_B (POS_k + 1) +#define POS_vB (POS_k + 1) #define POS_C (POS_B + SIZE_B) +#define POS_vC (POS_vB + SIZE_vB) #define POS_Bx POS_k @@ -64,14 +72,17 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ ** so they must fit in ints. */ -/* Check whether type 'int' has at least 'b' bits ('b' < 32) */ -#define L_INTHASBITS(b) ((UINT_MAX >> ((b) - 1)) >= 1) +/* +** Check whether type 'int' has at least 'b' + 1 bits. +** 'b' < 32; +1 for the sign bit. +*/ +#define L_INTHASBITS(b) ((UINT_MAX >> (b)) >= 1) #if L_INTHASBITS(SIZE_Bx) #define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ @@ -80,13 +91,13 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ #if L_INTHASBITS(SIZE_Ax) #define MAXARG_Ax ((1<> 1) @@ -94,7 +105,9 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ #define MAXARG_A ((1<> 1) #define int2sC(i) ((i) + OFFSET_sC) @@ -113,28 +126,36 @@ enum OpMode {iABC, iABx, iAsBx, iAx, isJ}; /* basic instruction formats */ #define GET_OPCODE(i) (cast(OpCode, ((i)>>POS_OP) & MASK1(SIZE_OP,0))) #define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>(pos)) & MASK1(size,0))) #define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ - ((cast(Instruction, v)< l) errorlimit(fs, l, what); +void luaY_checklimit (FuncState *fs, int v, int l, const char *what) { + if (l_unlikely(v > l)) errorlimit(fs, l, what); } @@ -172,7 +172,8 @@ static void codename (LexState *ls, expdesc *e) { ** Register a new local variable in the active 'Proto' (for debug ** information). */ -static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { +static short registerlocalvar (LexState *ls, FuncState *fs, + TString *varname) { Proto *f = fs->f; int oldsize = f->sizelocvars; luaM_growvector(ls->L, f->locvars, fs->ndebugvars, f->sizelocvars, @@ -187,24 +188,30 @@ static int registerlocalvar (LexState *ls, FuncState *fs, TString *varname) { /* -** Create a new local variable with the given 'name'. Return its index -** in the function. +** Create a new variable with the given 'name' and given 'kind'. +** Return its index in the function. */ -static int new_localvar (LexState *ls, TString *name) { +static int new_varkind (LexState *ls, TString *name, lu_byte kind) { lua_State *L = ls->L; FuncState *fs = ls->fs; Dyndata *dyd = ls->dyd; Vardesc *var; - checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, - MAXVARS, "local variables"); luaM_growvector(L, dyd->actvar.arr, dyd->actvar.n + 1, - dyd->actvar.size, Vardesc, SHRT_MAX, "local variables"); + dyd->actvar.size, Vardesc, SHRT_MAX, "variable declarationss"); var = &dyd->actvar.arr[dyd->actvar.n++]; - var->vd.kind = VDKREG; /* default */ + var->vd.kind = kind; /* default */ var->vd.name = name; return dyd->actvar.n - 1 - fs->firstlocal; } + +/* +** Create a new local variable with the given 'name' and regular kind. +*/ +static int new_localvar (LexState *ls, TString *name) { + return new_varkind(ls, name, VDKREG); +} + #define new_localvarliteral(ls,v) \ new_localvar(ls, \ luaX_newstring(ls, "" v, (sizeof(v)/sizeof(char)) - 1)); @@ -226,11 +233,11 @@ static Vardesc *getlocalvardesc (FuncState *fs, int vidx) { ** register. For that, search for the highest variable below that level ** that is in a register and uses its register index ('ridx') plus one. */ -static int reglevel (FuncState *fs, int nvar) { +static lu_byte reglevel (FuncState *fs, int nvar) { while (nvar-- > 0) { Vardesc *vd = getlocalvardesc(fs, nvar); /* get previous variable */ - if (vd->vd.kind != RDKCTC) /* is in a register? */ - return vd->vd.ridx + 1; + if (varinreg(vd)) /* is in a register? */ + return cast_byte(vd->vd.ridx + 1); } return 0; /* no variables in registers */ } @@ -240,7 +247,7 @@ static int reglevel (FuncState *fs, int nvar) { ** Return the number of variables in the register stack for the given ** function. */ -int luaY_nvarstack (FuncState *fs) { +lu_byte luaY_nvarstack (FuncState *fs) { return reglevel(fs, fs->nactvar); } @@ -250,7 +257,7 @@ int luaY_nvarstack (FuncState *fs) { */ static LocVar *localdebuginfo (FuncState *fs, int vidx) { Vardesc *vd = getlocalvardesc(fs, vidx); - if (vd->vd.kind == RDKCTC) + if (!varinreg(vd)) return NULL; /* no debug info. for constants */ else { int idx = vd->vd.pidx; @@ -266,7 +273,7 @@ static LocVar *localdebuginfo (FuncState *fs, int vidx) { static void init_var (FuncState *fs, expdesc *e, int vidx) { e->f = e->t = NO_JUMP; e->k = VLOCAL; - e->u.var.vidx = vidx; + e->u.var.vidx = cast_short(vidx); e->u.var.ridx = getlocalvardesc(fs, vidx)->vd.ridx; } @@ -294,14 +301,18 @@ static void check_readonly (LexState *ls, expdesc *e) { varname = up->name; break; } + case VINDEXUP: case VINDEXSTR: case VINDEXED: { /* global variable */ + if (e->u.ind.ro) /* read-only? */ + varname = tsvalue(&fs->f->k[e->u.ind.keystr]); + break; + } default: - return; /* other cases cannot be read-only */ - } - if (varname) { - const char *msg = luaO_pushfstring(ls->L, - "attempt to assign to const variable '%s'", getstr(varname)); - luaK_semerror(ls, msg); /* error */ + lua_assert(e->k == VINDEXI); /* this one doesn't need any check */ + return; /* integer index cannot be read-only */ } + if (varname) + luaK_semerror(ls, "attempt to assign to const variable '%s'", + getstr(varname)); } @@ -315,8 +326,9 @@ static void adjustlocalvars (LexState *ls, int nvars) { for (i = 0; i < nvars; i++) { int vidx = fs->nactvar++; Vardesc *var = getlocalvardesc(fs, vidx); - var->vd.ridx = reglevel++; + var->vd.ridx = cast_byte(reglevel++); var->vd.pidx = registerlocalvar(ls, fs, var->vd.name); + luaY_checklimit(fs, reglevel, MAXVARS, "local variables"); } } @@ -352,7 +364,7 @@ static int searchupvalue (FuncState *fs, TString *name) { static Upvaldesc *allocupvalue (FuncState *fs) { Proto *f = fs->f; int oldsize = f->sizeupvalues; - checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaY_checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, Upvaldesc, MAXUPVAL, "upvalues"); while (oldsize < f->sizeupvalues) @@ -383,20 +395,40 @@ static int newupvalue (FuncState *fs, TString *name, expdesc *v) { /* -** Look for an active local variable with the name 'n' in the +** Look for an active variable with the name 'n' in the ** function 'fs'. If found, initialize 'var' with it and return -** its expression kind; otherwise return -1. +** its expression kind; otherwise return -1. While searching, +** var->u.info==-1 means that the preambular global declaration is +** active (the default while there is no other global declaration); +** var->u.info==-2 means there is no active collective declaration +** (some previous global declaration but no collective declaration); +** and var->u.info>=0 points to the inner-most (the first one found) +** collective declaration, if there is one. */ static int searchvar (FuncState *fs, TString *n, expdesc *var) { int i; for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { Vardesc *vd = getlocalvardesc(fs, i); - if (eqstr(n, vd->vd.name)) { /* found? */ + if (varglobal(vd)) { /* global declaration? */ + if (vd->vd.name == NULL) { /* collective declaration? */ + if (var->u.info < 0) /* no previous collective declaration? */ + var->u.info = fs->firstlocal + i; /* this is the first one */ + } + else { /* global name */ + if (eqstr(n, vd->vd.name)) { /* found? */ + init_exp(var, VGLOBAL, fs->firstlocal + i); + return VGLOBAL; + } + else if (var->u.info == -1) /* active preambular declaration? */ + var->u.info = -2; /* invalidate preambular declaration */ + } + } + else if (eqstr(n, vd->vd.name)) { /* found? */ if (vd->vd.kind == RDKCTC) /* compile-time constant? */ init_exp(var, VCONST, fs->firstlocal + i); - else /* real variable */ + else /* local variable */ init_var(fs, var, i); - return var->k; + return cast_int(var->k); } } return -1; /* not found */ @@ -433,25 +465,22 @@ static void marktobeclosed (FuncState *fs) { ** 'var' as 'void' as a flag. */ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { - if (fs == NULL) /* no more levels? */ - init_exp(var, VVOID, 0); /* default is global */ - else { - int v = searchvar(fs, n, var); /* look up locals at current level */ - if (v >= 0) { /* found? */ - if (v == VLOCAL && !base) - markupval(fs, var->u.var.vidx); /* local will be used as an upval */ - } - else { /* not found as local at current level; try upvalues */ - int idx = searchupvalue(fs, n); /* try existing upvalues */ - if (idx < 0) { /* not found? */ + int v = searchvar(fs, n, var); /* look up variables at current level */ + if (v >= 0) { /* found? */ + if (v == VLOCAL && !base) + markupval(fs, var->u.var.vidx); /* local will be used as an upval */ + } + else { /* not found at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + if (fs->prev != NULL) /* more levels? */ singlevaraux(fs->prev, n, var, 0); /* try upper levels */ - if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ - idx = newupvalue(fs, n, var); /* will be a new upvalue */ - else /* it is a global or a constant */ - return; /* don't need to do anything at this level */ - } - init_exp(var, VUPVAL, idx); /* new or old upvalue */ + if (var->k == VLOCAL || var->k == VUPVAL) /* local or upvalue? */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + else /* it is a global or a constant */ + return; /* don't need to do anything at this level */ } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ } } @@ -460,21 +489,36 @@ static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { ** Find a variable with the given name 'n', handling global variables ** too. */ -static void singlevar (LexState *ls, expdesc *var) { - TString *varname = str_checkname(ls); +static void buildvar (LexState *ls, TString *varname, expdesc *var) { FuncState *fs = ls->fs; + init_exp(var, VGLOBAL, -1); /* global by default */ singlevaraux(fs, varname, var, 1); - if (var->k == VVOID) { /* global name? */ + if (var->k == VGLOBAL) { /* global name? */ expdesc key; + int info = var->u.info; + /* global by default in the scope of a global declaration? */ + if (info == -2) + luaK_semerror(ls, "variable '%s' not declared", getstr(varname)); singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ - lua_assert(var->k != VVOID); /* this one must exist */ + if (var->k == VGLOBAL) + luaK_semerror(ls, "_ENV is global when accessing variable '%s'", + getstr(varname)); luaK_exp2anyregup(fs, var); /* but could be a constant */ codestring(&key, varname); /* key is variable name */ luaK_indexed(fs, var, &key); /* env[varname] */ + if (info != -1 && ls->dyd->actvar.arr[info].vd.kind == GDKCONST) + var->u.ind.ro = 1; /* mark variable as read-only */ + else /* anyway must be a global */ + lua_assert(info == -1 || ls->dyd->actvar.arr[info].vd.kind == GDKREG); } } +static void singlevar (LexState *ls, expdesc *var) { + buildvar(ls, str_checkname(ls), var); +} + + /* ** Adjust the number of results from an expression list 'e' with 'nexps' ** expressions to 'nvars' values. @@ -497,7 +541,7 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { if (needed > 0) luaK_reserveregs(fs, needed); /* registers for extra values */ else /* adding 'needed' is actually a subtraction */ - fs->freereg += needed; /* remove extra values */ + fs->freereg = cast_byte(fs->freereg + needed); /* remove extra values */ } @@ -509,29 +553,43 @@ static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { /* ** Generates an error that a goto jumps into the scope of some -** local variable. +** variable declaration. */ static l_noret jumpscopeerror (LexState *ls, Labeldesc *gt) { - const char *varname = getstr(getlocalvardesc(ls->fs, gt->nactvar)->vd.name); - const char *msg = " at line %d jumps into the scope of local '%s'"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line, varname); - luaK_semerror(ls, msg); /* raise the error */ + TString *tsname = getlocalvardesc(ls->fs, gt->nactvar)->vd.name; + const char *varname = (tsname != NULL) ? getstr(tsname) : "*"; + luaK_semerror(ls, + " at line %d jumps into the scope of '%s'", + getstr(gt->name), gt->line, varname); /* raise the error */ } /* -** Solves the goto at index 'g' to given 'label' and removes it +** Closes the goto at index 'g' to given 'label' and removes it ** from the list of pending gotos. ** If it jumps into the scope of some variable, raises an error. +** The goto needs a CLOSE if it jumps out of a block with upvalues, +** or out of the scope of some variable and the block has upvalues +** (signaled by parameter 'bup'). */ -static void solvegoto (LexState *ls, int g, Labeldesc *label) { +static void closegoto (LexState *ls, int g, Labeldesc *label, int bup) { int i; + FuncState *fs = ls->fs; Labellist *gl = &ls->dyd->gt; /* list of gotos */ Labeldesc *gt = &gl->arr[g]; /* goto to be resolved */ lua_assert(eqstr(gt->name, label->name)); if (l_unlikely(gt->nactvar < label->nactvar)) /* enter some scope? */ jumpscopeerror(ls, gt); - luaK_patchlist(ls->fs, gt->pc, label->pc); + if (gt->close || + (label->nactvar < gt->nactvar && bup)) { /* needs close? */ + lu_byte stklevel = reglevel(fs, label->nactvar); + /* move jump to CLOSE position */ + fs->f->code[gt->pc + 1] = fs->f->code[gt->pc]; + /* put CLOSE instruction at original position */ + fs->f->code[gt->pc] = CREATE_ABCk(OP_CLOSE, stklevel, 0, 0, 0); + gt->pc++; /* must point to jump instruction */ + } + luaK_patchlist(ls->fs, gt->pc, label->pc); /* goto jumps to label */ for (i = g; i < gl->n - 1; i++) /* remove goto from pending list */ gl->arr[i] = gl->arr[i + 1]; gl->n--; @@ -539,14 +597,14 @@ static void solvegoto (LexState *ls, int g, Labeldesc *label) { /* -** Search for an active label with the given name. +** Search for an active label with the given name, starting at +** index 'ilb' (so that it can search for all labels in current block +** or all labels in current function). */ -static Labeldesc *findlabel (LexState *ls, TString *name) { - int i; +static Labeldesc *findlabel (LexState *ls, TString *name, int ilb) { Dyndata *dyd = ls->dyd; - /* check labels in current function for a match */ - for (i = ls->fs->firstlabel; i < dyd->label.n; i++) { - Labeldesc *lb = &dyd->label.arr[i]; + for (; ilb < dyd->label.n; ilb++) { + Labeldesc *lb = &dyd->label.arr[ilb]; if (eqstr(lb->name, name)) /* correct label? */ return lb; } @@ -572,29 +630,19 @@ static int newlabelentry (LexState *ls, Labellist *l, TString *name, } -static int newgotoentry (LexState *ls, TString *name, int line, int pc) { - return newlabelentry(ls, &ls->dyd->gt, name, line, pc); -} - - /* -** Solves forward jumps. Check whether new label 'lb' matches any -** pending gotos in current block and solves them. Return true -** if any of the gotos need to close upvalues. +** Create an entry for the goto and the code for it. As it is not known +** at this point whether the goto may need a CLOSE, the code has a jump +** followed by an CLOSE. (As the CLOSE comes after the jump, it is a +** dead instruction; it works as a placeholder.) When the goto is closed +** against a label, if it needs a CLOSE, the two instructions swap +** positions, so that the CLOSE comes before the jump. */ -static int solvegotos (LexState *ls, Labeldesc *lb) { - Labellist *gl = &ls->dyd->gt; - int i = ls->fs->bl->firstgoto; - int needsclose = 0; - while (i < gl->n) { - if (eqstr(gl->arr[i].name, lb->name)) { - needsclose |= gl->arr[i].close; - solvegoto(ls, i, lb); /* will remove 'i' from the list */ - } - else - i++; - } - return needsclose; +static int newgotoentry (LexState *ls, TString *name, int line) { + FuncState *fs = ls->fs; + int pc = luaK_jump(fs); /* create jump */ + luaK_codeABC(fs, OP_CLOSE, 0, 1, 0); /* spaceholder, marked as dead */ + return newlabelentry(ls, &ls->dyd->gt, name, line, pc); } @@ -605,8 +653,7 @@ static int solvegotos (LexState *ls, Labeldesc *lb) { ** a close instruction if necessary. ** Returns true iff it added a close instruction. */ -static int createlabel (LexState *ls, TString *name, int line, - int last) { +static void createlabel (LexState *ls, TString *name, int line, int last) { FuncState *fs = ls->fs; Labellist *ll = &ls->dyd->label; int l = newlabelentry(ls, ll, name, line, luaK_getlabel(fs)); @@ -614,28 +661,37 @@ static int createlabel (LexState *ls, TString *name, int line, /* assume that locals are already out of scope */ ll->arr[l].nactvar = fs->bl->nactvar; } - if (solvegotos(ls, &ll->arr[l])) { /* need close? */ - luaK_codeABC(fs, OP_CLOSE, luaY_nvarstack(fs), 0, 0); - return 1; - } - return 0; } /* -** Adjust pending gotos to outer level of a block. +** Traverse the pending goto's of the finishing block checking whether +** each match some label of that block. Those that do not match are +** "exported" to the outer block, to be solved there. In particular, +** its 'nactvar' is updated with the level of the inner block, +** as the variables of the inner block are now out of scope. */ -static void movegotosout (FuncState *fs, BlockCnt *bl) { - int i; - Labellist *gl = &fs->ls->dyd->gt; - /* correct pending gotos to current block */ - for (i = bl->firstgoto; i < gl->n; i++) { /* for each pending goto */ - Labeldesc *gt = &gl->arr[i]; - /* leaving a variable scope? */ - if (reglevel(fs, gt->nactvar) > reglevel(fs, bl->nactvar)) - gt->close |= bl->upval; /* jump may need a close */ - gt->nactvar = bl->nactvar; /* update goto level */ +static void solvegotos (FuncState *fs, BlockCnt *bl) { + LexState *ls = fs->ls; + Labellist *gl = &ls->dyd->gt; + int outlevel = reglevel(fs, bl->nactvar); /* level outside the block */ + int igt = bl->firstgoto; /* first goto in the finishing block */ + while (igt < gl->n) { /* for each pending goto */ + Labeldesc *gt = &gl->arr[igt]; + /* search for a matching label in the current block */ + Labeldesc *lb = findlabel(ls, gt->name, bl->firstlabel); + if (lb != NULL) /* found a match? */ + closegoto(ls, igt, lb, bl->upval); /* close and remove goto */ + else { /* adjust 'goto' for outer block */ + /* block has variables to be closed and goto escapes the scope of + some variable? */ + if (bl->upval && reglevel(fs, gt->nactvar) > outlevel) + gt->close = 1; /* jump may need a close */ + gt->nactvar = bl->nactvar; /* correct level for outer block */ + igt++; /* go to next goto */ + } } + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ } @@ -645,8 +701,9 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { bl->firstlabel = fs->ls->dyd->label.n; bl->firstgoto = fs->ls->dyd->gt.n; bl->upval = 0; + /* inherit 'insidetbc' from enclosing block */ bl->insidetbc = (fs->bl != NULL && fs->bl->insidetbc); - bl->previous = fs->bl; + bl->previous = fs->bl; /* link block in function's block list */ fs->bl = bl; lua_assert(fs->freereg == luaY_nvarstack(fs)); } @@ -656,39 +713,30 @@ static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { ** generates an error for an undefined 'goto'. */ static l_noret undefgoto (LexState *ls, Labeldesc *gt) { - const char *msg; - if (eqstr(gt->name, luaS_newliteral(ls->L, "break"))) { - msg = "break outside loop at line %d"; - msg = luaO_pushfstring(ls->L, msg, gt->line); - } - else { - msg = "no visible label '%s' for at line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); - } - luaK_semerror(ls, msg); + /* breaks are checked when created, cannot be undefined */ + lua_assert(!eqstr(gt->name, ls->brkn)); + luaK_semerror(ls, "no visible label '%s' for at line %d", + getstr(gt->name), gt->line); } static void leaveblock (FuncState *fs) { BlockCnt *bl = fs->bl; LexState *ls = fs->ls; - int hasclose = 0; - int stklevel = reglevel(fs, bl->nactvar); /* level outside the block */ - removevars(fs, bl->nactvar); /* remove block locals */ - lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ - if (bl->isloop) /* has to fix pending breaks? */ - hasclose = createlabel(ls, luaS_newliteral(ls->L, "break"), 0, 0); - if (!hasclose && bl->previous && bl->upval) /* still need a 'close'? */ + lu_byte stklevel = reglevel(fs, bl->nactvar); /* level outside block */ + if (bl->previous && bl->upval) /* need a 'close'? */ luaK_codeABC(fs, OP_CLOSE, stklevel, 0, 0); fs->freereg = stklevel; /* free registers */ - ls->dyd->label.n = bl->firstlabel; /* remove local labels */ - fs->bl = bl->previous; /* current block now is previous one */ - if (bl->previous) /* was it a nested block? */ - movegotosout(fs, bl); /* update pending gotos to enclosing block */ - else { + removevars(fs, bl->nactvar); /* remove block locals */ + lua_assert(bl->nactvar == fs->nactvar); /* back to level on entry */ + if (bl->isloop == 2) /* has to fix pending breaks? */ + createlabel(ls, ls->brkn, 0, 0); + solvegotos(fs, bl); + if (bl->previous == NULL) { /* was it the last block? */ if (bl->firstgoto < ls->dyd->gt.n) /* still pending gotos? */ undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ } + fs->bl = bl->previous; /* current block now is previous one */ } @@ -727,6 +775,7 @@ static void codeclosure (LexState *ls, expdesc *v) { static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + lua_State *L = ls->L; Proto *f = fs->f; fs->prev = ls->fs; /* linked list of funcstates */ fs->ls = ls; @@ -747,8 +796,11 @@ static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { fs->firstlabel = ls->dyd->label.n; fs->bl = NULL; f->source = ls->source; - luaC_objbarrier(ls->L, f, f->source); + luaC_objbarrier(L, f, f->source); f->maxstacksize = 2; /* registers 0/1 are always valid */ + fs->kcache = luaH_new(L); /* create table for function */ + sethvalue2s(L, L->top.p, fs->kcache); /* anchor it */ + luaD_inctop(L); enterblock(fs, bl, 0); } @@ -770,14 +822,16 @@ static void close_func (LexState *ls) { luaM_shrinkvector(L, f->locvars, f->sizelocvars, fs->ndebugvars, LocVar); luaM_shrinkvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); ls->fs = fs->prev; + L->top.p--; /* pop kcache table */ luaC_checkGC(L); } - -/*============================================================*/ -/* GRAMMAR RULES */ -/*============================================================*/ +/* +** {====================================================================== +** GRAMMAR RULES +** ======================================================================= +*/ /* @@ -834,26 +888,25 @@ static void yindex (LexState *ls, expdesc *v) { ** ======================================================================= */ - typedef struct ConsControl { expdesc v; /* last list item read */ expdesc *t; /* table descriptor */ int nh; /* total number of 'record' elements */ int na; /* number of array elements already stored */ int tostore; /* number of array elements pending to be stored */ + int maxtostore; /* maximum number of pending elements */ } ConsControl; static void recfield (LexState *ls, ConsControl *cc) { /* recfield -> (NAME | '['exp']') = exp */ FuncState *fs = ls->fs; - int reg = ls->fs->freereg; + lu_byte reg = ls->fs->freereg; expdesc tab, key, val; if (ls->t.token == TK_NAME) codename(ls, &key); else /* ls->t.token == '[' */ yindex(ls, &key); - checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); cc->nh++; checknext(ls, '='); tab = *cc->t; @@ -868,7 +921,7 @@ static void closelistfield (FuncState *fs, ConsControl *cc) { if (cc->v.k == VVOID) return; /* there is no list item */ luaK_exp2nextreg(fs, &cc->v); cc->v.k = VVOID; - if (cc->tostore == LFIELDS_PER_FLUSH) { + if (cc->tostore >= cc->maxtostore) { luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ cc->na += cc->tostore; cc->tostore = 0; /* no more items pending */ @@ -921,12 +974,28 @@ static void field (LexState *ls, ConsControl *cc) { } +/* +** Compute a limit for how many registers a constructor can use before +** emitting a 'SETLIST' instruction, based on how many registers are +** available. +*/ +static int maxtostore (FuncState *fs) { + int numfreeregs = MAX_FSTACK - fs->freereg; + if (numfreeregs >= 160) /* "lots" of registers? */ + return numfreeregs / 5; /* use up to 1/5 of them */ + else if (numfreeregs >= 80) /* still "enough" registers? */ + return 10; /* one 'SETLIST' instruction for each 10 values */ + else /* save registers for potential more nesting */ + return 1; +} + + static void constructor (LexState *ls, expdesc *t) { /* constructor -> '{' [ field { sep field } [sep] ] '}' sep -> ',' | ';' */ FuncState *fs = ls->fs; int line = ls->linenumber; - int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + int pc = luaK_codevABCk(fs, OP_NEWTABLE, 0, 0, 0, 0); ConsControl cc; luaK_code(fs, 0); /* space for extra arg. */ cc.na = cc.nh = cc.tostore = 0; @@ -934,14 +1003,15 @@ static void constructor (LexState *ls, expdesc *t) { init_exp(t, VNONRELOC, fs->freereg); /* table will be at stack top */ luaK_reserveregs(fs, 1); init_exp(&cc.v, VVOID, 0); /* no value (yet) */ - checknext(ls, '{'); + checknext(ls, '{' /*}*/); + cc.maxtostore = maxtostore(fs); do { lua_assert(cc.v.k == VVOID || cc.tostore > 0); - if (ls->t.token == '}') break; + if (ls->t.token == /*{*/ '}') break; closelistfield(fs, &cc); field(ls, &cc); } while (testnext(ls, ',') || testnext(ls, ';')); - check_match(ls, '}', '{', line); + check_match(ls, /*{*/ '}', '{' /*}*/, line); lastlistfield(fs, &cc); luaK_settablesize(fs, pc, t->u.info, cc.na, cc.nh); } @@ -950,7 +1020,7 @@ static void constructor (LexState *ls, expdesc *t) { static void setvararg (FuncState *fs, int nparams) { - fs->f->is_vararg = 1; + fs->f->flag |= PF_ISVARARG; luaK_codeABC(fs, OP_VARARGPREP, nparams, 0, 0); } @@ -1039,7 +1109,7 @@ static void funcargs (LexState *ls, expdesc *f) { check_match(ls, ')', '(', line); break; } - case '{': { /* funcargs -> constructor */ + case '{' /*}*/: { /* funcargs -> constructor */ constructor(ls, &args); break; } @@ -1063,8 +1133,9 @@ static void funcargs (LexState *ls, expdesc *f) { } init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); luaK_fixline(fs, line); - fs->freereg = base+1; /* call removes function and arguments and leaves - one result (unless changed later) */ + /* call removes function and arguments and leaves one result (unless + changed later) */ + fs->freereg = cast_byte(base + 1); } @@ -1125,7 +1196,7 @@ static void suffixedexp (LexState *ls, expdesc *v) { funcargs(ls, v); break; } - case '(': case TK_STRING: case '{': { /* funcargs */ + case '(': case TK_STRING: case '{' /*}*/: { /* funcargs */ luaK_exp2nextreg(fs, v); funcargs(ls, v); break; @@ -1168,12 +1239,12 @@ static void simpleexp (LexState *ls, expdesc *v) { } case TK_DOTS: { /* vararg */ FuncState *fs = ls->fs; - check_condition(ls, fs->f->is_vararg, + check_condition(ls, fs->f->flag & PF_ISVARARG, "cannot use '...' outside a vararg function"); init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 0, 1)); break; } - case '{': { /* constructor */ + case '{' /*}*/: { /* constructor */ constructor(ls, v); return; } @@ -1329,7 +1400,7 @@ struct LHS_assign { */ static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { FuncState *fs = ls->fs; - int extra = fs->freereg; /* eventual position to save local variable */ + lu_byte extra = fs->freereg; /* eventual position to save local variable */ int conflict = 0; for (; lh; lh = lh->prev) { /* check all previous assignments */ if (vkisindexed(lh->v.k)) { /* assignment to table field? */ @@ -1412,45 +1483,38 @@ static int cond (LexState *ls) { } -static void gotostat (LexState *ls) { - FuncState *fs = ls->fs; - int line = ls->linenumber; +static void gotostat (LexState *ls, int line) { TString *name = str_checkname(ls); /* label's name */ - Labeldesc *lb = findlabel(ls, name); - if (lb == NULL) /* no label? */ - /* forward jump; will be resolved when the label is declared */ - newgotoentry(ls, name, line, luaK_jump(fs)); - else { /* found a label */ - /* backward jump; will be resolved here */ - int lblevel = reglevel(fs, lb->nactvar); /* label level */ - if (luaY_nvarstack(fs) > lblevel) /* leaving the scope of a variable? */ - luaK_codeABC(fs, OP_CLOSE, lblevel, 0, 0); - /* create jump and link it to the label */ - luaK_patchlist(fs, luaK_jump(fs), lb->pc); - } + newgotoentry(ls, name, line); } /* ** Break statement. Semantically equivalent to "goto break". */ -static void breakstat (LexState *ls) { - int line = ls->linenumber; +static void breakstat (LexState *ls, int line) { + BlockCnt *bl; /* to look for an enclosing loop */ + for (bl = ls->fs->bl; bl != NULL; bl = bl->previous) { + if (bl->isloop) /* found one? */ + goto ok; + } + luaX_syntaxerror(ls, "break outside loop"); + ok: + bl->isloop = 2; /* signal that block has pending breaks */ luaX_next(ls); /* skip break */ - newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, luaK_jump(ls->fs)); + newgotoentry(ls, ls->brkn, line); } /* -** Check whether there is already a label with the given 'name'. +** Check whether there is already a label with the given 'name' at +** current function. */ static void checkrepeated (LexState *ls, TString *name) { - Labeldesc *lb = findlabel(ls, name); - if (l_unlikely(lb != NULL)) { /* already defined? */ - const char *msg = "label '%s' already defined on line %d"; - msg = luaO_pushfstring(ls->L, msg, getstr(name), lb->line); - luaK_semerror(ls, msg); /* error */ - } + Labeldesc *lb = findlabel(ls, name, ls->fs->firstlabel); + if (l_unlikely(lb != NULL)) /* already defined? */ + luaK_semerror(ls, "label '%s' already defined on line %d", + getstr(name), lb->line); /* error */ } @@ -1549,6 +1613,7 @@ static void forbody (LexState *ls, int base, int line, int nvars, int isgen) { int prep, endfor; checknext(ls, TK_DO); prep = luaK_codeABx(fs, forprep[isgen], base, 0); + fs->freereg--; /* both 'forprep' remove one register from the stack */ enterblock(fs, &bl, 0); /* scope for declared variables */ adjustlocalvars(ls, nvars); luaK_reserveregs(fs, nvars); @@ -1571,8 +1636,7 @@ static void fornum (LexState *ls, TString *varname, int line) { int base = fs->freereg; new_localvarliteral(ls, "(for state)"); new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvar(ls, varname); + new_varkind(ls, varname, RDKCONST); /* control variable */ checknext(ls, '='); exp1(ls); /* initial value */ checknext(ls, ','); @@ -1583,7 +1647,7 @@ static void fornum (LexState *ls, TString *varname, int line) { luaK_int(fs, fs->freereg, 1); luaK_reserveregs(fs, 1); } - adjustlocalvars(ls, 3); /* control variables */ + adjustlocalvars(ls, 2); /* start scope for internal variables */ forbody(ls, base, line, 1, 0); } @@ -1592,16 +1656,15 @@ static void forlist (LexState *ls, TString *indexname) { /* forlist -> NAME {,NAME} IN explist forbody */ FuncState *fs = ls->fs; expdesc e; - int nvars = 5; /* gen, state, control, toclose, 'indexname' */ + int nvars = 4; /* function, state, closing, control */ int line; int base = fs->freereg; - /* create control variables */ - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - new_localvarliteral(ls, "(for state)"); - /* create declared variables */ - new_localvar(ls, indexname); + /* create internal variables */ + new_localvarliteral(ls, "(for state)"); /* iterator function */ + new_localvarliteral(ls, "(for state)"); /* state */ + new_localvarliteral(ls, "(for state)"); /* closing var. (after swap) */ + new_varkind(ls, indexname, RDKCONST); /* control variable */ + /* other declared variables */ while (testnext(ls, ',')) { new_localvar(ls, str_checkname(ls)); nvars++; @@ -1609,10 +1672,10 @@ static void forlist (LexState *ls, TString *indexname) { checknext(ls, TK_IN); line = ls->linenumber; adjust_assign(ls, 4, explist(ls, &e), &e); - adjustlocalvars(ls, 4); /* control variables */ - marktobeclosed(fs); /* last control var. must be closed */ - luaK_checkstack(fs, 3); /* extra space to call generator */ - forbody(ls, base, line, nvars - 4, 1); + adjustlocalvars(ls, 3); /* start scope for internal variables */ + marktobeclosed(fs); /* last internal var. must be closed */ + luaK_checkstack(fs, 2); /* extra space to call iterator */ + forbody(ls, base, line, nvars - 3, 1); } @@ -1636,38 +1699,16 @@ static void forstat (LexState *ls, int line) { static void test_then_block (LexState *ls, int *escapelist) { /* test_then_block -> [IF | ELSEIF] cond THEN block */ - BlockCnt bl; FuncState *fs = ls->fs; - expdesc v; - int jf; /* instruction to skip 'then' code (if condition is false) */ + int condtrue; luaX_next(ls); /* skip IF or ELSEIF */ - expr(ls, &v); /* read condition */ + condtrue = cond(ls); /* read condition */ checknext(ls, TK_THEN); - if (ls->t.token == TK_BREAK) { /* 'if x then break' ? */ - int line = ls->linenumber; - luaK_goiffalse(ls->fs, &v); /* will jump if condition is true */ - luaX_next(ls); /* skip 'break' */ - enterblock(fs, &bl, 0); /* must enter block before 'goto' */ - newgotoentry(ls, luaS_newliteral(ls->L, "break"), line, v.t); - while (testnext(ls, ';')) {} /* skip semicolons */ - if (block_follow(ls, 0)) { /* jump is the entire block? */ - leaveblock(fs); - return; /* and that is it */ - } - else /* must skip over 'then' part if condition is false */ - jf = luaK_jump(fs); - } - else { /* regular case (not a break) */ - luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ - enterblock(fs, &bl, 0); - jf = v.f; - } - statlist(ls); /* 'then' part */ - leaveblock(fs); + block(ls); /* 'then' part */ if (ls->t.token == TK_ELSE || ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ - luaK_patchtohere(fs, jf); + luaK_patchtohere(fs, condtrue); } @@ -1697,20 +1738,20 @@ static void localfunc (LexState *ls) { } -static int getlocalattribute (LexState *ls) { - /* ATTRIB -> ['<' Name '>'] */ +static lu_byte getvarattribute (LexState *ls, lu_byte df) { + /* attrib -> ['<' NAME '>'] */ if (testnext(ls, '<')) { - const char *attr = getstr(str_checkname(ls)); + TString *ts = str_checkname(ls); + const char *attr = getstr(ts); checknext(ls, '>'); if (strcmp(attr, "const") == 0) return RDKCONST; /* read-only variable */ else if (strcmp(attr, "close") == 0) return RDKTOCLOSE; /* to-be-closed variable */ else - luaK_semerror(ls, - luaO_pushfstring(ls->L, "unknown attribute '%s'", attr)); + luaK_semerror(ls, "unknown attribute '%s'", attr); } - return VDKREG; /* regular variable */ + return df; /* return default value */ } @@ -1723,18 +1764,20 @@ static void checktoclose (FuncState *fs, int level) { static void localstat (LexState *ls) { - /* stat -> LOCAL NAME ATTRIB { ',' NAME ATTRIB } ['=' explist] */ + /* stat -> LOCAL NAME attrib { ',' NAME attrib } ['=' explist] */ FuncState *fs = ls->fs; int toclose = -1; /* index of to-be-closed variable (if any) */ Vardesc *var; /* last variable */ - int vidx, kind; /* index and kind of last variable */ + int vidx; /* index of last variable */ int nvars = 0; int nexps; expdesc e; - do { - vidx = new_localvar(ls, str_checkname(ls)); - kind = getlocalattribute(ls); - getlocalvardesc(fs, vidx)->vd.kind = kind; + /* get prefixed attribute (if any); default is regular local variable */ + lu_byte defkind = getvarattribute(ls, VDKREG); + do { /* for each variable */ + TString *vname = str_checkname(ls); /* get its name */ + lu_byte kind = getvarattribute(ls, defkind); /* postfixed attribute */ + vidx = new_varkind(ls, vname, kind); /* predeclare it */ if (kind == RDKTOCLOSE) { /* to-be-closed? */ if (toclose != -1) /* one already present? */ luaK_semerror(ls, "multiple to-be-closed variables in local list"); @@ -1742,13 +1785,13 @@ static void localstat (LexState *ls) { } nvars++; } while (testnext(ls, ',')); - if (testnext(ls, '=')) + if (testnext(ls, '=')) /* initialization? */ nexps = explist(ls, &e); else { e.k = VVOID; nexps = 0; } - var = getlocalvardesc(fs, vidx); /* get last variable */ + var = getlocalvardesc(fs, vidx); /* retrieve last variable */ if (nvars == nexps && /* no adjustments? */ var->vd.kind == RDKCONST && /* last variable is const? */ luaK_exp2const(fs, &e, &var->k)) { /* compile-time constant? */ @@ -1764,6 +1807,66 @@ static void localstat (LexState *ls) { } +static lu_byte getglobalattribute (LexState *ls, lu_byte df) { + lu_byte kind = getvarattribute(ls, df); + switch (kind) { + case RDKTOCLOSE: + luaK_semerror(ls, "global variables cannot be to-be-closed"); + break; /* to avoid warnings */ + case RDKCONST: + return GDKCONST; /* adjust kind for global variable */ + default: + return kind; + } +} + + +static void globalstat (LexState *ls) { + /* globalstat -> (GLOBAL) attrib '*' + globalstat -> (GLOBAL) attrib NAME attrib {',' NAME attrib} */ + FuncState *fs = ls->fs; + /* get prefixed attribute (if any); default is regular global variable */ + lu_byte defkind = getglobalattribute(ls, GDKREG); + if (testnext(ls, '*')) { + /* use NULL as name to represent '*' entries */ + new_varkind(ls, NULL, defkind); + fs->nactvar++; /* activate declaration */ + } + else { + do { /* list of names */ + TString *vname = str_checkname(ls); + lu_byte kind = getglobalattribute(ls, defkind); + new_varkind(ls, vname, kind); + fs->nactvar++; /* activate declaration */ + } while (testnext(ls, ',')); + } +} + + +static void globalfunc (LexState *ls, int line) { + /* globalfunc -> (GLOBAL FUNCTION) NAME body */ + expdesc var, b; + FuncState *fs = ls->fs; + TString *fname = str_checkname(ls); + new_varkind(ls, fname, GDKREG); /* declare global variable */ + fs->nactvar++; /* enter its scope */ + buildvar(ls, fname, &var); + body(ls, &b, 0, ls->linenumber); /* compile and return closure in 'b' */ + luaK_storevar(fs, &var, &b); + luaK_fixline(fs, line); /* definition "happens" in the first line */ +} + + +static void globalstatfunc (LexState *ls, int line) { + /* stat -> GLOBAL globalfunc | GLOBAL globalstat */ + luaX_next(ls); /* skip 'global' */ + if (testnext(ls, TK_FUNCTION)) + globalfunc(ls, line); + else + globalstat(ls); +} + + static int funcname (LexState *ls, expdesc *v) { /* funcname -> NAME {fieldsel} [':' NAME] */ int ismethod = 0; @@ -1784,8 +1887,8 @@ static void funcstat (LexState *ls, int line) { expdesc v, b; luaX_next(ls); /* skip FUNCTION */ ismethod = funcname(ls, &v); - body(ls, &b, ismethod, line); check_readonly(ls, &v); + body(ls, &b, ismethod, line); luaK_storevar(ls->fs, &v, &b); luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ } @@ -1883,6 +1986,10 @@ static void statement (LexState *ls) { localstat(ls); break; } + case TK_GLOBAL: { /* stat -> globalstatfunc */ + globalstatfunc(ls, line); + break; + } case TK_DBCOLON: { /* stat -> label */ luaX_next(ls); /* skip double colon */ labelstat(ls, str_checkname(ls), line); @@ -1894,14 +2001,30 @@ static void statement (LexState *ls) { break; } case TK_BREAK: { /* stat -> breakstat */ - breakstat(ls); + breakstat(ls, line); break; } case TK_GOTO: { /* stat -> 'goto' NAME */ luaX_next(ls); /* skip 'goto' */ - gotostat(ls); + gotostat(ls, line); break; } +#if defined(LUA_COMPAT_GLOBAL) + case TK_NAME: { + /* compatibility code to parse global keyword when "global" + is not reserved */ + if (ls->t.seminfo.ts == ls->glbn) { /* current = "global"? */ + int lk = luaX_lookahead(ls); + if (lk == '<' || lk == TK_NAME || lk == '*' || lk == TK_FUNCTION) { + /* 'global ' or 'global name' or 'global *' or + 'global function' */ + globalstatfunc(ls, line); + break; + } + } /* else... */ + } +#endif + /* FALLTHROUGH */ default: { /* stat -> func | assignment */ exprstat(ls); break; @@ -1915,6 +2038,8 @@ static void statement (LexState *ls) { /* }====================================================================== */ +/* }====================================================================== */ + /* ** compiles the main function, which is a regular vararg function with an diff --git a/3rdparty/lua/plainlua/lparser.h b/3rdparty/lua/plainlua/lparser.h index 5e4500f181a8..fdbb9b8a0bf0 100644 --- a/3rdparty/lua/plainlua/lparser.h +++ b/3rdparty/lua/plainlua/lparser.h @@ -32,26 +32,32 @@ typedef enum { VKFLT, /* floating constant; nval = numerical float value */ VKINT, /* integer constant; ival = numerical integer value */ VKSTR, /* string constant; strval = TString address; - (string is fixed by the lexer) */ + (string is fixed by the scanner) */ VNONRELOC, /* expression has its value in a fixed register; info = result register */ VLOCAL, /* local variable; var.ridx = register index; var.vidx = relative index in 'actvar.arr' */ + VGLOBAL, /* global variable; + info = relative index in 'actvar.arr' (or -1 for + implicit declaration) */ VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ VCONST, /* compile-time variable; info = absolute index in 'actvar.arr' */ VINDEXED, /* indexed variable; ind.t = table register; - ind.idx = key's R index */ + ind.idx = key's R index; + ind.ro = true if it represents a read-only global; + ind.keystr = if key is a string, index in 'k' of that string; + -1 if key is not a string */ VINDEXUP, /* indexed upvalue; - ind.t = table upvalue; - ind.idx = key's K index */ + ind.idx = key's K index; + ind.* as in VINDEXED */ VINDEXI, /* indexed variable with constant integer; ind.t = table register; ind.idx = key's value */ VINDEXSTR, /* indexed variable with literal string; - ind.t = table register; - ind.idx = key's K index */ + ind.idx = key's K index; + ind.* as in VINDEXED */ VJMP, /* expression is a test/comparison; info = pc of corresponding jump instruction */ VRELOC, /* expression can put result in any register; @@ -75,10 +81,12 @@ typedef struct expdesc { struct { /* for indexed variables */ short idx; /* index (R or "long" K) */ lu_byte t; /* table (register or upvalue) */ + lu_byte ro; /* true if variable is read-only */ + int keystr; /* index in 'k' of string key, or -1 if not a string */ } ind; struct { /* for local variables */ lu_byte ridx; /* register holding the variable */ - unsigned short vidx; /* compiler index (in 'actvar.arr') */ + short vidx; /* index in 'actvar.arr' */ } var; } u; int t; /* patch list of 'exit when true' */ @@ -87,12 +95,21 @@ typedef struct expdesc { /* kinds of variables */ -#define VDKREG 0 /* regular */ -#define RDKCONST 1 /* constant */ +#define VDKREG 0 /* regular local */ +#define RDKCONST 1 /* local constant */ #define RDKTOCLOSE 2 /* to-be-closed */ -#define RDKCTC 3 /* compile-time constant */ +#define RDKCTC 3 /* local compile-time constant */ +#define GDKREG 4 /* regular global */ +#define GDKCONST 5 /* global constant */ + +/* variables that live in registers */ +#define varinreg(v) ((v)->vd.kind <= RDKTOCLOSE) + +/* test for global variables */ +#define varglobal(v) ((v)->vd.kind >= GDKREG) + -/* description of an active local variable */ +/* description of an active variable */ typedef union Vardesc { struct { TValuefields; /* constant value (if it is a compile-time constant) */ @@ -111,8 +128,8 @@ typedef struct Labeldesc { TString *name; /* label identifier */ int pc; /* position in code */ int line; /* line where it appeared */ - lu_byte nactvar; /* number of active variables in that position */ - lu_byte close; /* goto that escapes upvalues */ + short nactvar; /* number of active variables in that position */ + lu_byte close; /* true for goto that escapes upvalues */ } Labeldesc; @@ -146,6 +163,7 @@ typedef struct FuncState { struct FuncState *prev; /* enclosing function */ struct LexState *ls; /* lexical state */ struct BlockCnt *bl; /* chain of current blocks */ + Table *kcache; /* cache for reusing constants */ int pc; /* next position to code (equivalent to 'ncode') */ int lasttarget; /* 'label' of last 'jump label' */ int previousline; /* last line that was saved in 'lineinfo' */ @@ -155,7 +173,7 @@ typedef struct FuncState { int firstlocal; /* index of first local var (in Dyndata array) */ int firstlabel; /* index of first label (in 'dyd->label->arr') */ short ndebugvars; /* number of elements in 'f->locvars' */ - lu_byte nactvar; /* number of active local variables */ + short nactvar; /* number of active variable declarations */ lu_byte nups; /* number of upvalues */ lu_byte freereg; /* first free register */ lu_byte iwthabs; /* instructions issued since last absolute line info */ @@ -163,7 +181,9 @@ typedef struct FuncState { } FuncState; -LUAI_FUNC int luaY_nvarstack (FuncState *fs); +LUAI_FUNC lu_byte luaY_nvarstack (FuncState *fs); +LUAI_FUNC void luaY_checklimit (FuncState *fs, int v, int l, + const char *what); LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, Dyndata *dyd, const char *name, int firstchar); diff --git a/3rdparty/lua/plainlua/lstate.c b/3rdparty/lua/plainlua/lstate.c index f3f2ccfdd5fb..70a11aaec649 100644 --- a/3rdparty/lua/plainlua/lstate.c +++ b/3rdparty/lua/plainlua/lstate.c @@ -29,79 +29,45 @@ -/* -** thread state + extra space -*/ -typedef struct LX { - lu_byte extra_[LUA_EXTRASPACE]; - lua_State l; -} LX; - - -/* -** Main thread combines a thread state and the global state -*/ -typedef struct LG { - LX l; - global_State g; -} LG; - - - #define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) /* -** A macro to create a "random" seed when a state is created; -** the seed is used to randomize string hashes. +** these macros allow user-specific actions when a thread is +** created/deleted */ -#if !defined(luai_makeseed) +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif -#include +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif -/* -** Compute an initial seed with some level of randomness. -** Rely on Address Space Layout Randomization (if present) and -** current time. -*/ -#define addbuff(b,p,e) \ - { size_t t = cast_sizet(e); \ - memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } - -static unsigned int luai_makeseed (lua_State *L) { - char buff[3 * sizeof(size_t)]; - unsigned int h = cast_uint(time(NULL)); - int p = 0; - addbuff(buff, p, L); /* heap variable */ - addbuff(buff, p, &h); /* local variable */ - addbuff(buff, p, &lua_newstate); /* public function */ - lua_assert(p == sizeof(buff)); - return luaS_hash(buff, p, h); -} +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) #endif /* -** set GCdebt to a new value keeping the value (totalbytes + GCdebt) -** invariant (and avoiding underflows in 'totalbytes') +** set GCdebt to a new value keeping the real number of allocated +** objects (GCtotalobjs - GCdebt) invariant and avoiding overflows in +** 'GCtotalobjs'. */ void luaE_setdebt (global_State *g, l_mem debt) { l_mem tb = gettotalbytes(g); lua_assert(tb > 0); - if (debt < tb - MAX_LMEM) - debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ - g->totalbytes = tb - debt; + if (debt > MAX_LMEM - tb) + debt = MAX_LMEM - tb; /* will make GCtotalbytes == MAX_LMEM */ + g->GCtotalbytes = tb + debt; g->GCdebt = debt; } -LUA_API int lua_setcstacklimit (lua_State *L, unsigned int limit) { - UNUSED(L); UNUSED(limit); - return LUAI_MAXCCALLS; /* warning?? */ -} - - CallInfo *luaE_extendCI (lua_State *L) { CallInfo *ci; lua_assert(L->ci->next == NULL); @@ -177,26 +143,29 @@ LUAI_FUNC void luaE_incCstack (lua_State *L) { } +static void resetCI (lua_State *L) { + CallInfo *ci = L->ci = &L->base_ci; + ci->func.p = L->stack.p; + setnilvalue(s2v(ci->func.p)); /* 'function' entry for basic 'ci' */ + ci->top.p = ci->func.p + 1 + LUA_MINSTACK; /* +1 for 'function' entry */ + ci->u.c.k = NULL; + ci->callstatus = CIST_C; + L->status = LUA_OK; + L->errfunc = 0; /* stack unwind can "throw away" the error function */ +} + + static void stack_init (lua_State *L1, lua_State *L) { - int i; CallInfo *ci; + int i; /* initialize stack array */ L1->stack.p = luaM_newvector(L, BASIC_STACK_SIZE + EXTRA_STACK, StackValue); L1->tbclist.p = L1->stack.p; for (i = 0; i < BASIC_STACK_SIZE + EXTRA_STACK; i++) setnilvalue(s2v(L1->stack.p + i)); /* erase new stack */ - L1->top.p = L1->stack.p; L1->stack_last.p = L1->stack.p + BASIC_STACK_SIZE; /* initialize first ci */ - ci = &L1->base_ci; - ci->next = ci->previous = NULL; - ci->callstatus = CIST_C; - ci->func.p = L1->top.p; - ci->u.c.k = NULL; - ci->nresults = 0; - setnilvalue(s2v(L1->top.p)); /* 'function' entry for this 'ci' */ - L1->top.p++; - ci->top.p = L1->top.p + LUA_MINSTACK; - L1->ci = ci; + resetCI(L1); + L1->top.p = L1->stack.p + 1; /* +1 for 'function' entry */ } @@ -206,7 +175,8 @@ static void freestack (lua_State *L) { L->ci = &L->base_ci; /* free the entire 'ci' list */ freeCI(L); lua_assert(L->nci == 0); - luaM_freearray(L, L->stack.p, stacksize(L) + EXTRA_STACK); /* free stack */ + /* free stack */ + luaM_freearray(L, L->stack.p, cast_sizet(stacksize(L) + EXTRA_STACK)); } @@ -215,13 +185,19 @@ static void freestack (lua_State *L) { */ static void init_registry (lua_State *L, global_State *g) { /* create registry */ + TValue aux; Table *registry = luaH_new(L); sethvalue(L, &g->l_registry, registry); luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[1] = false */ + setbfvalue(&aux); + luaH_setint(L, registry, 1, &aux); /* registry[LUA_RIDX_MAINTHREAD] = L */ - setthvalue(L, ®istry->array[LUA_RIDX_MAINTHREAD - 1], L); + setthvalue(L, &aux, L); + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &aux); /* registry[LUA_RIDX_GLOBALS] = new table (table of globals) */ - sethvalue(L, ®istry->array[LUA_RIDX_GLOBALS - 1], luaH_new(L)); + sethvalue(L, &aux, luaH_new(L)); + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &aux); } @@ -263,6 +239,16 @@ static void preinit_thread (lua_State *L, global_State *g) { L->status = LUA_OK; L->errfunc = 0; L->oldpc = 0; + L->base_ci.previous = L->base_ci.next = NULL; +} + + +lu_mem luaE_threadsize (lua_State *L) { + lu_mem sz = cast(lu_mem, sizeof(LX)) + + cast_uint(L->nci) * sizeof(CallInfo); + if (L->stack.p != NULL) + sz += cast_uint(stacksize(L) + EXTRA_STACK) * sizeof(StackValue); + return sz; } @@ -271,17 +257,16 @@ static void close_state (lua_State *L) { if (!completestate(g)) /* closing a partially built state? */ luaC_freeallobjects(L); /* just collect its objects */ else { /* closing a fully built state */ - L->ci = &L->base_ci; /* unwind CallInfo list */ - L->errfunc = 0; /* stack unwind can "throw away" the error function */ + resetCI(L); luaD_closeprotected(L, 1, LUA_OK); /* close all upvalues */ L->top.p = L->stack.p + 1; /* empty the stack to run finalizers */ luaC_freeallobjects(L); /* collect all objects */ luai_userstateclose(L); } - luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + luaM_freearray(L, G(L)->strt.hash, cast_sizet(G(L)->strt.size)); freestack(L); - lua_assert(gettotalbytes(g) == sizeof(LG)); - (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ + lua_assert(gettotalbytes(g) == sizeof(global_State)); + (*g->frealloc)(g->ud, g, sizeof(global_State), 0); /* free main block */ } @@ -303,7 +288,7 @@ LUA_API lua_State *lua_newthread (lua_State *L) { L1->hook = L->hook; resethookcount(L1); /* initialize L1 extra space */ - memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + memcpy(lua_getextraspace(L1), lua_getextraspace(mainthread(g)), LUA_EXTRASPACE); luai_userstatethread(L, L1); stack_init(L1, L); /* init stack */ @@ -322,52 +307,39 @@ void luaE_freethread (lua_State *L, lua_State *L1) { } -int luaE_resetthread (lua_State *L, int status) { - CallInfo *ci = L->ci = &L->base_ci; /* unwind CallInfo list */ - setnilvalue(s2v(L->stack.p)); /* 'function' entry for basic 'ci' */ - ci->func.p = L->stack.p; - ci->callstatus = CIST_C; +TStatus luaE_resetthread (lua_State *L, TStatus status) { + resetCI(L); if (status == LUA_YIELD) status = LUA_OK; - L->status = LUA_OK; /* so it can run __close metamethods */ - L->errfunc = 0; /* stack unwind can "throw away" the error function */ status = luaD_closeprotected(L, 1, status); if (status != LUA_OK) /* errors? */ luaD_seterrorobj(L, status, L->stack.p + 1); else L->top.p = L->stack.p + 1; - ci->top.p = L->top.p + LUA_MINSTACK; - luaD_reallocstack(L, cast_int(ci->top.p - L->stack.p), 0); + luaD_reallocstack(L, cast_int(L->ci->top.p - L->stack.p), 0); return status; } LUA_API int lua_closethread (lua_State *L, lua_State *from) { - int status; + TStatus status; lua_lock(L); L->nCcalls = (from) ? getCcalls(from) : 0; status = luaE_resetthread(L, L->status); + if (L == from) /* closing itself? */ + luaD_throwbaselevel(L, status); lua_unlock(L); - return status; -} - - -/* -** Deprecated! Use 'lua_closethread' instead. -*/ -LUA_API int lua_resetthread (lua_State *L) { - return lua_closethread(L, NULL); + return APIstatus(status); } -LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud, unsigned seed) { int i; lua_State *L; - global_State *g; - LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); - if (l == NULL) return NULL; - L = &l->l.l; - g = &l->g; + global_State *g = cast(global_State*, + (*f)(ud, NULL, LUA_TTHREAD, sizeof(global_State))); + if (g == NULL) return NULL; + L = &g->mainth.l; L->tt = LUA_VTHREAD; g->currentwhite = bitmask(WHITE0BIT); L->marked = luaC_white(g); @@ -379,8 +351,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->ud = ud; g->warnf = NULL; g->ud_warn = NULL; - g->mainthread = L; - g->seed = luai_makeseed(L); + g->seed = seed; g->gcstp = GCSTPGC; /* no GC while building state */ g->strt.size = g->strt.nuse = 0; g->strt.hash = NULL; @@ -397,16 +368,17 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { g->gray = g->grayagain = NULL; g->weak = g->ephemeron = g->allweak = NULL; g->twups = NULL; - g->totalbytes = sizeof(LG); + g->GCtotalbytes = sizeof(global_State); + g->GCmarked = 0; g->GCdebt = 0; - g->lastatomic = 0; setivalue(&g->nilvalue, 0); /* to signal that state is not yet built */ - setgcparam(g->gcpause, LUAI_GCPAUSE); - setgcparam(g->gcstepmul, LUAI_GCMUL); - g->gcstepsize = LUAI_GCSTEPSIZE; - setgcparam(g->genmajormul, LUAI_GENMAJORMUL); - g->genminormul = LUAI_GENMINORMUL; - for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + setgcparam(g, PAUSE, LUAI_GCPAUSE); + setgcparam(g, STEPMUL, LUAI_GCMUL); + setgcparam(g, STEPSIZE, LUAI_GCSTEPSIZE); + setgcparam(g, MINORMUL, LUAI_GENMINORMUL); + setgcparam(g, MINORMAJOR, LUAI_MINORMAJOR); + setgcparam(g, MAJORMINOR, LUAI_MAJORMINOR); + for (i=0; i < LUA_NUMTYPES; i++) g->mt[i] = NULL; if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { /* memory allocation error: free partial state */ close_state(L); @@ -418,7 +390,7 @@ LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { LUA_API void lua_close (lua_State *L) { lua_lock(L); - L = G(L)->mainthread; /* only the main thread can be closed */ + L = mainthread(G(L)); /* only the main thread can be closed */ close_state(L); } diff --git a/3rdparty/lua/plainlua/lstate.h b/3rdparty/lua/plainlua/lstate.h index 007704c826be..f841c2321ebe 100644 --- a/3rdparty/lua/plainlua/lstate.h +++ b/3rdparty/lua/plainlua/lstate.h @@ -142,6 +142,17 @@ struct lua_longjmp; /* defined in ldo.c */ #define EXTRA_STACK 5 +/* +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set. +** (M == 1 makes a direct cache.) +*/ +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 +#endif + + #define BASIC_STACK_SIZE (2*LUA_MINSTACK) #define stacksize(th) cast_int((th)->stack_last.p - (th)->stack.p) @@ -149,13 +160,14 @@ struct lua_longjmp; /* defined in ldo.c */ /* kinds of Garbage Collection */ #define KGC_INC 0 /* incremental gc */ -#define KGC_GEN 1 /* generational gc */ +#define KGC_GENMINOR 1 /* generational gc in minor (regular) mode */ +#define KGC_GENMAJOR 2 /* generational in major mode */ typedef struct stringtable { - TString **hash; + TString **hash; /* array of buckets (linked lists of strings) */ int nuse; /* number of elements */ - int size; + int size; /* number of buckets */ } stringtable; @@ -171,12 +183,10 @@ typedef struct stringtable { ** yield (from the yield until the next resume); ** - field 'nres' is used only while closing tbc variables when ** returning from a function; -** - field 'transferinfo' is used only during call/returnhooks, -** before the function starts or after it ends. */ struct CallInfo { StkIdRel func; /* function index in the stack */ - StkIdRel top; /* top for this function */ + StkIdRel top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ union { struct { /* only for Lua functions */ @@ -194,36 +204,59 @@ struct CallInfo { int funcidx; /* called-function index */ int nyield; /* number of values yielded */ int nres; /* number of values returned */ - struct { /* info about transferred values (for call/return hooks) */ - unsigned short ftransfer; /* offset of first value transferred */ - unsigned short ntransfer; /* number of values transferred */ - } transferinfo; } u2; - short nresults; /* expected number of results from this function */ - unsigned short callstatus; + l_uint32 callstatus; }; +/* +** Maximum expected number of results from a function +** (must fit in CIST_NRESULTS). +*/ +#define MAXRESULTS 250 + + /* ** Bits in CallInfo status */ -#define CIST_OAH (1<<0) /* original value of 'allowhook' */ -#define CIST_C (1<<1) /* call is running a C function */ -#define CIST_FRESH (1<<2) /* call is on a fresh "luaV_execute" frame */ -#define CIST_HOOKED (1<<3) /* call is running a debug hook */ -#define CIST_YPCALL (1<<4) /* doing a yieldable protected call */ -#define CIST_TAIL (1<<5) /* call was tail called */ -#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ -#define CIST_FIN (1<<7) /* function "called" a finalizer */ -#define CIST_TRAN (1<<8) /* 'ci' has transfer information */ -#define CIST_CLSRET (1<<9) /* function is closing tbc variables */ -/* Bits 10-12 are used for CIST_RECST (see below) */ -#define CIST_RECST 10 +/* bits 0-7 are the expected number of results from this function + 1 */ +#define CIST_NRESULTS 0xffu + +/* bits 8-11 count call metamethods (and their extra arguments) */ +#define CIST_CCMT 8 /* the offset, not the mask */ +#define MAX_CCMT (0xfu << CIST_CCMT) + +/* Bits 12-14 are used for CIST_RECST (see below) */ +#define CIST_RECST 12 /* the offset, not the mask */ + +/* call is running a C function (still in first 16 bits) */ +#define CIST_C (1u << (CIST_RECST + 3)) +/* call is on a fresh "luaV_execute" frame */ +#define CIST_FRESH cast(l_uint32, CIST_C << 1) +/* function is closing tbc variables */ +#define CIST_CLSRET (CIST_FRESH << 1) +/* function has tbc variables to close */ +#define CIST_TBC (CIST_CLSRET << 1) +/* original value of 'allowhook' */ +#define CIST_OAH (CIST_TBC << 1) +/* call is running a debug hook */ +#define CIST_HOOKED (CIST_OAH << 1) +/* doing a yieldable protected call */ +#define CIST_YPCALL (CIST_HOOKED << 1) +/* call was tail called */ +#define CIST_TAIL (CIST_YPCALL << 1) +/* last hook called yielded */ +#define CIST_HOOKYIELD (CIST_TAIL << 1) +/* function "called" a finalizer */ +#define CIST_FIN (CIST_HOOKYIELD << 1) #if defined(LUA_COMPAT_LT_LE) -#define CIST_LEQ (1<<13) /* using __lt for __le */ +/* using __lt for __le */ +#define CIST_LEQ (CIST_FIN << 1) #endif +#define get_nresults(cs) (cast_int((cs) & CIST_NRESULTS) - 1) + /* ** Field CIST_RECST stores the "recover status", used to keep the error ** status while closing to-be-closed variables in coroutines, so that @@ -233,8 +266,8 @@ struct CallInfo { #define getcistrecst(ci) (((ci)->callstatus >> CIST_RECST) & 7) #define setcistrecst(ci,st) \ check_exp(((st) & 7) == (st), /* status must fit in three bits */ \ - ((ci)->callstatus = ((ci)->callstatus & ~(7 << CIST_RECST)) \ - | ((st) << CIST_RECST))) + ((ci)->callstatus = ((ci)->callstatus & ~(7u << CIST_RECST)) \ + | (cast(l_uint32, st) << CIST_RECST))) /* active function is a Lua function */ @@ -243,9 +276,53 @@ struct CallInfo { /* call is running Lua code (not a hook) */ #define isLuacode(ci) (!((ci)->callstatus & (CIST_C | CIST_HOOKED))) -/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ -#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) -#define getoah(st) ((st) & CIST_OAH) + +#define setoah(ci,v) \ + ((ci)->callstatus = ((v) ? (ci)->callstatus | CIST_OAH \ + : (ci)->callstatus & ~CIST_OAH)) +#define getoah(ci) (((ci)->callstatus & CIST_OAH) ? 1 : 0) + + +/* +** 'per thread' state +*/ +struct lua_State { + CommonHeader; + lu_byte allowhook; + TStatus status; + StkIdRel top; /* first free slot in the stack */ + struct global_State *l_G; + CallInfo *ci; /* call info for current function */ + StkIdRel stack_last; /* end of stack (last element + 1) */ + StkIdRel stack; /* stack base */ + UpVal *openupval; /* list of open upvalues in this stack */ + StkIdRel tbclist; /* list of to-be-closed variables */ + GCObject *gclist; + struct lua_State *twups; /* list of threads with open upvalues */ + struct lua_longjmp *errorJmp; /* current error recover point */ + CallInfo base_ci; /* CallInfo for first level (C host) */ + volatile lua_Hook hook; + ptrdiff_t errfunc; /* current error handling function (stack index) */ + l_uint32 nCcalls; /* number of nested non-yieldable or C calls */ + int oldpc; /* last pc traced */ + int nci; /* number of items in 'ci' list */ + int basehookcount; + int hookcount; + volatile l_signalT hookmask; + struct { /* info about transferred values (for call/return hooks) */ + int ftransfer; /* offset of first value transferred */ + int ntransfer; /* number of values transferred */ + } transferinfo; +}; + + +/* +** thread state + extra space +*/ +typedef struct LX { + lu_byte extra_[LUA_EXTRASPACE]; + lua_State l; +} LX; /* @@ -254,25 +331,21 @@ struct CallInfo { typedef struct global_State { lua_Alloc frealloc; /* function to reallocate memory */ void *ud; /* auxiliary data to 'frealloc' */ - l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ - l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ - lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ - lu_mem lastatomic; /* see function 'genstep' in file 'lgc.c' */ + l_mem GCtotalbytes; /* number of bytes currently allocated + debt */ + l_mem GCdebt; /* bytes counted but not yet allocated */ + l_mem GCmarked; /* number of objects marked in a GC cycle */ + l_mem GCmajorminor; /* auxiliary counter to control major-minor shifts */ stringtable strt; /* hash table for strings */ TValue l_registry; TValue nilvalue; /* a nil value */ unsigned int seed; /* randomized seed for hashes */ + lu_byte gcparams[LUA_GCPN]; lu_byte currentwhite; lu_byte gcstate; /* state of garbage collector */ lu_byte gckind; /* kind of GC running */ lu_byte gcstopem; /* stops emergency collections */ - lu_byte genminormul; /* control for minor generational collections */ - lu_byte genmajormul; /* control for major generational collections */ lu_byte gcstp; /* control whether GC is running */ lu_byte gcemergency; /* true if this is an emergency collection */ - lu_byte gcpause; /* size of pause between successive GCs */ - lu_byte gcstepmul; /* GC "speed" */ - lu_byte gcstepsize; /* (log2 of) GC granularity */ GCObject *allgc; /* list of all collectable objects */ GCObject **sweepgc; /* current position of sweep in list */ GCObject *finobj; /* list of collectable objects with finalizers */ @@ -293,46 +366,18 @@ typedef struct global_State { GCObject *finobjrold; /* list of really old objects with finalizers */ struct lua_State *twups; /* list of threads with open upvalues */ lua_CFunction panic; /* to be called in unprotected errors */ - struct lua_State *mainthread; TString *memerrmsg; /* message for memory-allocation errors */ TString *tmname[TM_N]; /* array with tag-method names */ struct Table *mt[LUA_NUMTYPES]; /* metatables for basic types */ TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ lua_WarnFunction warnf; /* warning function */ void *ud_warn; /* auxiliary data to 'warnf' */ + LX mainth; /* main thread of this state */ } global_State; -/* -** 'per thread' state -*/ -struct lua_State { - CommonHeader; - lu_byte status; - lu_byte allowhook; - unsigned short nci; /* number of items in 'ci' list */ - StkIdRel top; /* first free slot in the stack */ - global_State *l_G; - CallInfo *ci; /* call info for current function */ - StkIdRel stack_last; /* end of stack (last element + 1) */ - StkIdRel stack; /* stack base */ - UpVal *openupval; /* list of open upvalues in this stack */ - StkIdRel tbclist; /* list of to-be-closed variables */ - GCObject *gclist; - struct lua_State *twups; /* list of threads with open upvalues */ - struct lua_longjmp *errorJmp; /* current error recover point */ - CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ - volatile lua_Hook hook; - ptrdiff_t errfunc; /* current error handling function (stack index) */ - l_uint32 nCcalls; /* number of nested (non-yieldable | C) calls */ - int oldpc; /* last pc traced */ - int basehookcount; - int hookcount; - volatile l_signalT hookmask; -}; - - #define G(L) (L->l_G) +#define mainthread(G) (&(G)->mainth.l) /* ** 'g->nilvalue' being a nil value flags that the state was completely @@ -390,18 +435,20 @@ union GCUnion { #define obj2gco(v) check_exp((v)->tt >= LUA_TSTRING, &(cast_u(v)->gc)) -/* actual number of total bytes allocated */ -#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) +/* actual number of total memory allocated */ +#define gettotalbytes(g) ((g)->GCtotalbytes - (g)->GCdebt) + LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC lu_mem luaE_threadsize (lua_State *L); LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); LUAI_FUNC void luaE_shrinkCI (lua_State *L); LUAI_FUNC void luaE_checkcstack (lua_State *L); LUAI_FUNC void luaE_incCstack (lua_State *L); LUAI_FUNC void luaE_warning (lua_State *L, const char *msg, int tocont); LUAI_FUNC void luaE_warnerror (lua_State *L, const char *where); -LUAI_FUNC int luaE_resetthread (lua_State *L, int status); +LUAI_FUNC TStatus luaE_resetthread (lua_State *L, TStatus status); #endif diff --git a/3rdparty/lua/plainlua/lstring.c b/3rdparty/lua/plainlua/lstring.c index 97757355c0b6..b5c8f89f0258 100644 --- a/3rdparty/lua/plainlua/lstring.c +++ b/3rdparty/lua/plainlua/lstring.c @@ -25,7 +25,17 @@ /* ** Maximum size for string table. */ -#define MAXSTRTB cast_int(luaM_limitN(MAX_INT, TString*)) +#define MAXSTRTB cast_int(luaM_limitN(INT_MAX, TString*)) + +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 128 +#endif /* @@ -40,7 +50,7 @@ int luaS_eqlngstr (TString *a, TString *b) { } -unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { +unsigned luaS_hash (const char *str, size_t l, unsigned seed) { unsigned int h = seed ^ cast_uint(l); for (; l > 0; l--) h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); @@ -48,7 +58,7 @@ unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { } -unsigned int luaS_hashlongstr (TString *ts) { +unsigned luaS_hashlongstr (TString *ts) { lua_assert(ts->tt == LUA_VLNGSTR); if (ts->extra == 0) { /* no hash? */ size_t len = ts->u.lnglen; @@ -136,28 +146,43 @@ void luaS_init (lua_State *L) { } +size_t luaS_sizelngstr (size_t len, int kind) { + switch (kind) { + case LSTRREG: /* regular long string */ + /* don't need 'falloc'/'ud', but need space for content */ + return offsetof(TString, falloc) + (len + 1) * sizeof(char); + case LSTRFIX: /* fixed external long string */ + /* don't need 'falloc'/'ud' */ + return offsetof(TString, falloc); + default: /* external long string with deallocation */ + lua_assert(kind == LSTRMEM); + return sizeof(TString); + } +} + /* ** creates a new string object */ -static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { +static TString *createstrobj (lua_State *L, size_t totalsize, lu_byte tag, + unsigned h) { TString *ts; GCObject *o; - size_t totalsize; /* total size of TString object */ - totalsize = sizelstring(l); o = luaC_newobj(L, tag, totalsize); ts = gco2ts(o); ts->hash = h; ts->extra = 0; - getstr(ts)[l] = '\0'; /* ending 0 */ return ts; } TString *luaS_createlngstrobj (lua_State *L, size_t l) { - TString *ts = createstrobj(L, l, LUA_VLNGSTR, G(L)->seed); + size_t totalsize = luaS_sizelngstr(l, LSTRREG); + TString *ts = createstrobj(L, totalsize, LUA_VLNGSTR, G(L)->seed); ts->u.lnglen = l; - ts->shrlen = 0xFF; /* signals that it is a long string */ + ts->shrlen = LSTRREG; /* signals that it is a regular long string */ + ts->contents = cast_charp(ts) + offsetof(TString, falloc); + ts->contents[l] = '\0'; /* ending 0 */ return ts; } @@ -173,9 +198,9 @@ void luaS_remove (lua_State *L, TString *ts) { static void growstrtab (lua_State *L, stringtable *tb) { - if (l_unlikely(tb->nuse == MAX_INT)) { /* too many strings? */ + if (l_unlikely(tb->nuse == INT_MAX)) { /* too many strings? */ luaC_fullgc(L, 1); /* try to free some... */ - if (tb->nuse == MAX_INT) /* still too many? */ + if (tb->nuse == INT_MAX) /* still too many? */ luaM_error(L); /* cannot even create a message... */ } if (tb->size <= MAXSTRTB / 2) /* can grow string table? */ @@ -194,7 +219,8 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { TString **list = &tb->hash[lmod(h, tb->size)]; lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ for (ts = *list; ts != NULL; ts = ts->u.hnext) { - if (l == ts->shrlen && (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) { + if (l == cast_uint(ts->shrlen) && + (memcmp(str, getshrstr(ts), l * sizeof(char)) == 0)) { /* found! */ if (isdead(g, ts)) /* dead (but not collected yet)? */ changewhite(ts); /* resurrect it */ @@ -206,8 +232,9 @@ static TString *internshrstr (lua_State *L, const char *str, size_t l) { growstrtab(L, tb); list = &tb->hash[lmod(h, tb->size)]; /* rehash with new size */ } - ts = createstrobj(L, l, LUA_VSHRSTR, h); - ts->shrlen = cast_byte(l); + ts = createstrobj(L, sizestrshr(l), LUA_VSHRSTR, h); + ts->shrlen = cast(ls_byte, l); + getshrstr(ts)[l] = '\0'; /* ending 0 */ memcpy(getshrstr(ts), str, l * sizeof(char)); ts->u.hnext = *list; *list = ts; @@ -256,7 +283,7 @@ TString *luaS_new (lua_State *L, const char *str) { } -Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { +Udata *luaS_newudata (lua_State *L, size_t s, unsigned short nuvalue) { Udata *u; int i; GCObject *o; @@ -272,3 +299,61 @@ Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue) { return u; } + +struct NewExt { + ls_byte kind; + const char *s; + size_t len; + TString *ts; /* output */ +}; + + +static void f_newext (lua_State *L, void *ud) { + struct NewExt *ne = cast(struct NewExt *, ud); + size_t size = luaS_sizelngstr(0, ne->kind); + ne->ts = createstrobj(L, size, LUA_VLNGSTR, G(L)->seed); +} + + +static void f_pintern (lua_State *L, void *ud) { + struct NewExt *ne = cast(struct NewExt *, ud); + ne->ts = internshrstr(L, ne->s, ne->len); +} + + +TString *luaS_newextlstr (lua_State *L, + const char *s, size_t len, lua_Alloc falloc, void *ud) { + struct NewExt ne; + if (len <= LUAI_MAXSHORTLEN) { /* short string? */ + ne.s = s; ne.len = len; + if (!falloc) + f_pintern(L, &ne); /* just internalize string */ + else { + TStatus status = luaD_rawrunprotected(L, f_pintern, &ne); + (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ + if (status != LUA_OK) /* memory error? */ + luaM_error(L); /* re-raise memory error */ + } + return ne.ts; + } + /* "normal" case: long strings */ + if (!falloc) { + ne.kind = LSTRFIX; + f_newext(L, &ne); /* just create header */ + } + else { + ne.kind = LSTRMEM; + if (luaD_rawrunprotected(L, f_newext, &ne) != LUA_OK) { /* mem. error? */ + (*falloc)(ud, cast_voidp(s), len + 1, 0); /* free external string */ + luaM_error(L); /* re-raise memory error */ + } + ne.ts->falloc = falloc; + ne.ts->ud = ud; + } + ne.ts->shrlen = ne.kind; + ne.ts->u.lnglen = len; + ne.ts->contents = cast_charp(s); + return ne.ts; +} + + diff --git a/3rdparty/lua/plainlua/lstring.h b/3rdparty/lua/plainlua/lstring.h index 450c2390d1bb..1751e0434e85 100644 --- a/3rdparty/lua/plainlua/lstring.h +++ b/3rdparty/lua/plainlua/lstring.h @@ -20,10 +20,23 @@ /* -** Size of a TString: Size of the header plus space for the string +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + + +/* +** Size of a short TString: Size of the header plus space for the string ** itself (including final '\0'). */ -#define sizelstring(l) (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) +#define sizestrshr(l) \ + (offsetof(TString, contents) + ((l) + 1) * sizeof(char)) + #define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) @@ -32,7 +45,7 @@ /* ** test whether a string is a reserved word */ -#define isreserved(s) ((s)->tt == LUA_VSHRSTR && (s)->extra > 0) +#define isreserved(s) (strisshr(s) && (s)->extra > 0) /* @@ -41,17 +54,20 @@ #define eqshrstr(a,b) check_exp((a)->tt == LUA_VSHRSTR, (a) == (b)) -LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); -LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); +LUAI_FUNC unsigned luaS_hash (const char *str, size_t l, unsigned seed); +LUAI_FUNC unsigned luaS_hashlongstr (TString *ts); LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); LUAI_FUNC void luaS_resize (lua_State *L, int newsize); LUAI_FUNC void luaS_clearcache (global_State *g); LUAI_FUNC void luaS_init (lua_State *L); LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); -LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, int nuvalue); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s, + unsigned short nuvalue); LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); - +LUAI_FUNC TString *luaS_newextlstr (lua_State *L, + const char *s, size_t len, lua_Alloc falloc, void *ud); +LUAI_FUNC size_t luaS_sizelngstr (size_t len, int kind); #endif diff --git a/3rdparty/lua/plainlua/lstrlib.c b/3rdparty/lua/plainlua/lstrlib.c index 03167161df18..306cd0bfeb29 100644 --- a/3rdparty/lua/plainlua/lstrlib.c +++ b/3rdparty/lua/plainlua/lstrlib.c @@ -24,6 +24,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" /* @@ -36,22 +37,6 @@ #endif -/* macro to 'unsign' a character */ -#define uchar(c) ((unsigned char)(c)) - - -/* -** Some sizes are better limited to fit in 'int', but must also fit in -** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) -*/ -#define MAX_SIZET ((size_t)(~(size_t)0)) - -#define MAXSIZE \ - (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) - - - - static int str_len (lua_State *L) { size_t l; luaL_checklstring(L, 1, &l); @@ -128,7 +113,7 @@ static int str_lower (lua_State *L) { const char *s = luaL_checklstring(L, 1, &l); char *p = luaL_buffinitsize(L, &b, l); for (i=0; i MAXSIZE / n)) + else if (l_unlikely(l + lsep < l || l + lsep > MAX_SIZE / cast_sizet(n))) return luaL_error(L, "resulting string too large"); else { - size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; + size_t totallen = ((size_t)n * (l + lsep)) - lsep; luaL_Buffer b; char *p = luaL_buffinitsize(L, &b, totallen); while (n-- > 1) { /* first n-1 copies (followed by separator) */ @@ -187,7 +172,7 @@ static int str_byte (lua_State *L) { n = (int)(pose - posi) + 1; luaL_checkstack(L, n, "string slice too long"); for (i=0; iinit = 1; luaL_buffinit(L, &state->B); } - luaL_addlstring(&state->B, (const char *)b, size); + if (b == NULL) { /* finishing dump? */ + luaL_pushresult(&state->B); /* push result */ + lua_replace(L, 1); /* move it to reserved slot */ + } + else + luaL_addlstring(&state->B, (const char *)b, size); return 0; } @@ -233,12 +223,13 @@ static int writer (lua_State *L, const void *b, size_t size, void *ud) { static int str_dump (lua_State *L) { struct str_Writer state; int strip = lua_toboolean(L, 2); - luaL_checktype(L, 1, LUA_TFUNCTION); - lua_settop(L, 1); /* ensure function is on the top of the stack */ + luaL_argcheck(L, lua_type(L, 1) == LUA_TFUNCTION && !lua_iscfunction(L, 1), + 1, "Lua function expected"); + /* ensure function is on the top of the stack and vacate slot 1 */ + lua_pushvalue(L, 1); state.init = 0; - if (l_unlikely(lua_dump(L, writer, &state, strip) != 0)) - return luaL_error(L, "unable to dump given function"); - luaL_pushresult(&state.B); + lua_dump(L, writer, &state, strip); + lua_settop(L, 1); /* leave final result on top */ return 1; } @@ -361,10 +352,10 @@ typedef struct MatchState { const char *p_end; /* end ('\0') of pattern */ lua_State *L; int matchdepth; /* control for recursive depth (to avoid C stack overflow) */ - unsigned char level; /* total number of captures (finished or unfinished) */ + int level; /* total number of captures (finished or unfinished) */ struct { const char *init; - ptrdiff_t len; + ptrdiff_t len; /* length or special value (CAP_*) */ } capture[LUA_MAXCAPTURES]; } MatchState; @@ -453,15 +444,15 @@ static int matchbracketclass (int c, const char *p, const char *ec) { while (++p < ec) { if (*p == L_ESC) { p++; - if (match_class(c, uchar(*p))) + if (match_class(c, cast_uchar(*p))) return sig; } else if ((*(p+1) == '-') && (p+2 < ec)) { p+=2; - if (uchar(*(p-2)) <= c && c <= uchar(*p)) + if (cast_uchar(*(p-2)) <= c && c <= cast_uchar(*p)) return sig; } - else if (uchar(*p) == c) return sig; + else if (cast_uchar(*p) == c) return sig; } return !sig; } @@ -472,12 +463,12 @@ static int singlematch (MatchState *ms, const char *s, const char *p, if (s >= ms->src_end) return 0; else { - int c = uchar(*s); + int c = cast_uchar(*s); switch (*p) { case '.': return 1; /* matches any char */ - case L_ESC: return match_class(c, uchar(*(p+1))); + case L_ESC: return match_class(c, cast_uchar(*(p+1))); case '[': return matchbracketclass(c, p, ep-1); - default: return (uchar(*p) == c); + default: return (cast_uchar(*p) == c); } } } @@ -559,7 +550,7 @@ static const char *end_capture (MatchState *ms, const char *s, static const char *match_capture (MatchState *ms, const char *s, int l) { size_t len; l = check_capture(ms, l); - len = ms->capture[l].len; + len = cast_sizet(ms->capture[l].len); if ((size_t)(ms->src_end-s) >= len && memcmp(ms->capture[l].init, s, len) == 0) return s+len; @@ -606,8 +597,8 @@ static const char *match (MatchState *ms, const char *s, const char *p) { luaL_error(ms->L, "missing '[' after '%%f' in pattern"); ep = classend(ms, p); /* points to what is next */ previous = (s == ms->src_init) ? '\0' : *(s - 1); - if (!matchbracketclass(uchar(previous), p, ep - 1) && - matchbracketclass(uchar(*s), p, ep - 1)) { + if (!matchbracketclass(cast_uchar(previous), p, ep - 1) && + matchbracketclass(cast_uchar(*s), p, ep - 1)) { p = ep; goto init; /* return match(ms, s, ep); */ } s = NULL; /* match failed */ @@ -616,7 +607,7 @@ static const char *match (MatchState *ms, const char *s, const char *p) { case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': { /* capture results (%0-%9)? */ - s = match_capture(ms, s, uchar(*(p + 1))); + s = match_capture(ms, s, cast_uchar(*(p + 1))); if (s != NULL) { p += 2; goto init; /* return match(ms, s, p + 2) */ } @@ -683,7 +674,7 @@ static const char *lmemfind (const char *s1, size_t l1, if (memcmp(init, s2+1, l2) == 0) return init-1; else { /* correct 'l1' and 's1' to try again */ - l1 -= init-s1; + l1 -= ct_diff2sz(init - s1); s1 = init; } } @@ -699,13 +690,13 @@ static const char *lmemfind (const char *s1, size_t l1, ** its length and put its address in '*cap'. If it is an integer ** (a position), push it on the stack and return CAP_POSITION. */ -static size_t get_onecapture (MatchState *ms, int i, const char *s, +static ptrdiff_t get_onecapture (MatchState *ms, int i, const char *s, const char *e, const char **cap) { if (i >= ms->level) { if (l_unlikely(i != 0)) luaL_error(ms->L, "invalid capture index %%%d", i + 1); *cap = s; - return e - s; + return (e - s); } else { ptrdiff_t capl = ms->capture[i].len; @@ -713,7 +704,8 @@ static size_t get_onecapture (MatchState *ms, int i, const char *s, if (l_unlikely(capl == CAP_UNFINISHED)) luaL_error(ms->L, "unfinished capture"); else if (capl == CAP_POSITION) - lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); + lua_pushinteger(ms->L, + ct_diff2S(ms->capture[i].init - ms->src_init) + 1); return capl; } } @@ -727,7 +719,7 @@ static void push_onecapture (MatchState *ms, int i, const char *s, const char *cap; ptrdiff_t l = get_onecapture(ms, i, s, e, &cap); if (l != CAP_POSITION) - lua_pushlstring(ms->L, cap, l); + lua_pushlstring(ms->L, cap, cast_sizet(l)); /* else position was already pushed */ } @@ -784,8 +776,8 @@ static int str_find_aux (lua_State *L, int find) { /* do a plain search */ const char *s2 = lmemfind(s + init, ls - init, p, lp); if (s2) { - lua_pushinteger(L, (s2 - s) + 1); - lua_pushinteger(L, (s2 - s) + lp); + lua_pushinteger(L, ct_diff2S(s2 - s) + 1); + lua_pushinteger(L, cast_st2S(ct_diff2sz(s2 - s) + lp)); return 2; } } @@ -802,8 +794,8 @@ static int str_find_aux (lua_State *L, int find) { reprepstate(&ms); if ((res=match(&ms, s1, p)) != NULL) { if (find) { - lua_pushinteger(L, (s1 - s) + 1); /* start */ - lua_pushinteger(L, res - s); /* end */ + lua_pushinteger(L, ct_diff2S(s1 - s) + 1); /* start */ + lua_pushinteger(L, ct_diff2S(res - s)); /* end */ return push_captures(&ms, NULL, 0) + 2; } else @@ -875,23 +867,23 @@ static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, const char *news = lua_tolstring(L, 3, &l); const char *p; while ((p = (char *)memchr(news, L_ESC, l)) != NULL) { - luaL_addlstring(b, news, p - news); + luaL_addlstring(b, news, ct_diff2sz(p - news)); p++; /* skip ESC */ if (*p == L_ESC) /* '%%' */ luaL_addchar(b, *p); else if (*p == '0') /* '%0' */ - luaL_addlstring(b, s, e - s); - else if (isdigit(uchar(*p))) { /* '%n' */ + luaL_addlstring(b, s, ct_diff2sz(e - s)); + else if (isdigit(cast_uchar(*p))) { /* '%n' */ const char *cap; ptrdiff_t resl = get_onecapture(ms, *p - '1', s, e, &cap); if (resl == CAP_POSITION) luaL_addvalue(b); /* add position to accumulated result */ else - luaL_addlstring(b, cap, resl); + luaL_addlstring(b, cap, cast_sizet(resl)); } else luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); - l -= p + 1 - news; + l -= ct_diff2sz(p + 1 - news); news = p + 1; } luaL_addlstring(b, news, l); @@ -926,7 +918,7 @@ static int add_value (MatchState *ms, luaL_Buffer *b, const char *s, } if (!lua_toboolean(L, -1)) { /* nil or false? */ lua_pop(L, 1); /* remove value */ - luaL_addlstring(b, s, e - s); /* keep original text */ + luaL_addlstring(b, s, ct_diff2sz(e - s)); /* keep original text */ return 0; /* no changes */ } else if (l_unlikely(!lua_isstring(L, -1))) @@ -945,7 +937,8 @@ static int str_gsub (lua_State *L) { const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ const char *lastmatch = NULL; /* end of last match */ int tr = lua_type(L, 3); /* replacement type */ - lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ + /* max replacements */ + lua_Integer max_s = luaL_optinteger(L, 4, cast_st2S(srcl) + 1); int anchor = (*p == '^'); lua_Integer n = 0; /* replacement count */ int changed = 0; /* change flag */ @@ -975,7 +968,7 @@ static int str_gsub (lua_State *L) { if (!changed) /* no changes? */ lua_pushvalue(L, 1); /* return original string */ else { /* something changed */ - luaL_addlstring(&b, src, ms.src_end-src); + luaL_addlstring(&b, src, ct_diff2sz(ms.src_end - src)); luaL_pushresult(&b); /* create and return new string */ } lua_pushinteger(L, n); /* number of substitutions */ @@ -1013,15 +1006,15 @@ static int str_gsub (lua_State *L) { /* ** Add integer part of 'x' to buffer and return new 'x' */ -static lua_Number adddigit (char *buff, int n, lua_Number x) { +static lua_Number adddigit (char *buff, unsigned n, lua_Number x) { lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ int d = (int)dd; - buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + buff[n] = cast_char(d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ return x - dd; /* return what is left */ } -static int num2straux (char *buff, int sz, lua_Number x) { +static int num2straux (char *buff, unsigned sz, lua_Number x) { /* if 'inf' or 'NaN', format it like '%g' */ if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); @@ -1032,7 +1025,7 @@ static int num2straux (char *buff, int sz, lua_Number x) { else { int e; lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ - int n = 0; /* character count */ + unsigned n = 0; /* character count */ if (m < 0) { /* is number negative? */ buff[n++] = '-'; /* add sign */ m = -m; /* make it positive */ @@ -1046,20 +1039,20 @@ static int num2straux (char *buff, int sz, lua_Number x) { m = adddigit(buff, n++, m * 16); } while (m > 0); } - n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + n += cast_uint(l_sprintf(buff + n, sz - n, "p%+d", e)); /* add exponent */ lua_assert(n < sz); - return n; + return cast_int(n); } } -static int lua_number2strx (lua_State *L, char *buff, int sz, +static int lua_number2strx (lua_State *L, char *buff, unsigned sz, const char *fmt, lua_Number x) { int n = num2straux(buff, sz, x); if (fmt[SIZELENMOD] == 'A') { int i; for (i = 0; i < n; i++) - buff[i] = toupper(uchar(buff[i])); + buff[i] = cast_char(toupper(cast_uchar(buff[i]))); } else if (l_unlikely(fmt[SIZELENMOD] != 'a')) return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); @@ -1126,12 +1119,12 @@ static void addquoted (luaL_Buffer *b, const char *s, size_t len) { luaL_addchar(b, '\\'); luaL_addchar(b, *s); } - else if (iscntrl(uchar(*s))) { + else if (iscntrl(cast_uchar(*s))) { char buff[10]; - if (!isdigit(uchar(*(s+1)))) - l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); + if (!isdigit(cast_uchar(*(s+1)))) + l_sprintf(buff, sizeof(buff), "\\%d", (int)cast_uchar(*s)); else - l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); + l_sprintf(buff, sizeof(buff), "\\%03d", (int)cast_uchar(*s)); luaL_addstring(b, buff); } else @@ -1160,9 +1153,9 @@ static int quotefloat (lua_State *L, char *buff, lua_Number n) { int nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); /* ensures that 'buff' string uses a dot as the radix character */ - if (memchr(buff, '.', nb) == NULL) { /* no dot? */ + if (memchr(buff, '.', cast_uint(nb)) == NULL) { /* no dot? */ char point = lua_getlocaledecpoint(); /* try locale point */ - char *ppoint = (char *)memchr(buff, point, nb); + char *ppoint = (char *)memchr(buff, point, cast_uint(nb)); if (ppoint) *ppoint = '.'; /* change it to a dot */ } return nb; @@ -1192,7 +1185,7 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { : LUA_INTEGER_FMT; /* else use default format */ nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); } - luaL_addsize(b, nb); + luaL_addsize(b, cast_uint(nb)); break; } case LUA_TNIL: case LUA_TBOOLEAN: { @@ -1208,9 +1201,9 @@ static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { static const char *get2digits (const char *s) { - if (isdigit(uchar(*s))) { + if (isdigit(cast_uchar(*s))) { s++; - if (isdigit(uchar(*s))) s++; /* (2 digits at most) */ + if (isdigit(cast_uchar(*s))) s++; /* (2 digits at most) */ } return s; } @@ -1233,7 +1226,7 @@ static void checkformat (lua_State *L, const char *form, const char *flags, spec = get2digits(spec); /* skip precision */ } } - if (!isalpha(uchar(*spec))) /* did not go to the end? */ + if (!isalpha(cast_uchar(*spec))) /* did not go to the end? */ luaL_error(L, "invalid conversion specification: '%s'", form); } @@ -1286,7 +1279,7 @@ static int str_format (lua_State *L) { luaL_addchar(&b, *strfrmt++); /* %% */ else { /* format item */ char form[MAX_FORMAT]; /* to store the format ('%...') */ - int maxitem = MAX_ITEM; /* maximum length for the result */ + unsigned maxitem = MAX_ITEM; /* maximum length for the result */ char *buff = luaL_prepbuffsize(&b, maxitem); /* to put result */ int nb = 0; /* number of bytes in result */ if (++arg > top) @@ -1369,8 +1362,8 @@ static int str_format (lua_State *L) { return luaL_error(L, "invalid conversion '%s' to 'format'", form); } } - lua_assert(nb < maxitem); - luaL_addsize(&b, nb); + lua_assert(cast_uint(nb) < maxitem); + luaL_addsize(&b, cast_uint(nb)); } } luaL_pushresult(&b); @@ -1418,7 +1411,7 @@ static const union { typedef struct Header { lua_State *L; int islittle; - int maxalign; + unsigned maxalign; } Header; @@ -1446,14 +1439,14 @@ typedef enum KOption { */ static int digit (int c) { return '0' <= c && c <= '9'; } -static int getnum (const char **fmt, int df) { +static size_t getnum (const char **fmt, size_t df) { if (!digit(**fmt)) /* no number? */ return df; /* return default value */ else { - int a = 0; + size_t a = 0; do { - a = a*10 + (*((*fmt)++) - '0'); - } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); + a = a*10 + cast_uint(*((*fmt)++) - '0'); + } while (digit(**fmt) && a <= (MAX_SIZE - 9)/10); return a; } } @@ -1461,14 +1454,14 @@ static int getnum (const char **fmt, int df) { /* ** Read an integer numeral and raises an error if it is larger -** than the maximum size for integers. +** than the maximum size of integers. */ -static int getnumlimit (Header *h, const char **fmt, int df) { - int sz = getnum(fmt, df); - if (l_unlikely(sz > MAXINTSIZE || sz <= 0)) - return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", - sz, MAXINTSIZE); - return sz; +static unsigned getnumlimit (Header *h, const char **fmt, size_t df) { + size_t sz = getnum(fmt, df); + if (l_unlikely((sz - 1u) >= MAXINTSIZE)) + return cast_uint(luaL_error(h->L, + "integral size (%d) out of limits [1,%d]", sz, MAXINTSIZE)); + return cast_uint(sz); } @@ -1485,7 +1478,7 @@ static void initheader (lua_State *L, Header *h) { /* ** Read and classify next option. 'size' is filled with option's size. */ -static KOption getoption (Header *h, const char **fmt, int *size) { +static KOption getoption (Header *h, const char **fmt, size_t *size) { /* dummy structure to get native alignment requirements */ struct cD { char c; union { LUAI_MAXALIGN; } u; }; int opt = *((*fmt)++); @@ -1507,8 +1500,8 @@ static KOption getoption (Header *h, const char **fmt, int *size) { case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; case 'c': - *size = getnum(fmt, -1); - if (l_unlikely(*size == -1)) + *size = getnum(fmt, cast_sizet(-1)); + if (l_unlikely(*size == cast_sizet(-1))) luaL_error(h->L, "missing size for format option 'c'"); return Kchar; case 'z': return Kzstr; @@ -1519,7 +1512,7 @@ static KOption getoption (Header *h, const char **fmt, int *size) { case '>': h->islittle = 0; break; case '=': h->islittle = nativeendian.little; break; case '!': { - const int maxalign = offsetof(struct cD, u); + const size_t maxalign = offsetof(struct cD, u); h->maxalign = getnumlimit(h, fmt, maxalign); break; } @@ -1538,10 +1531,10 @@ static KOption getoption (Header *h, const char **fmt, int *size) { ** the maximum alignment ('maxalign'). Kchar option needs no alignment ** despite its size. */ -static KOption getdetails (Header *h, size_t totalsize, - const char **fmt, int *psize, int *ntoalign) { +static KOption getdetails (Header *h, size_t totalsize, const char **fmt, + size_t *psize, unsigned *ntoalign) { KOption opt = getoption(h, fmt, psize); - int align = *psize; /* usually, alignment follows size */ + size_t align = *psize; /* usually, alignment follows size */ if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) luaL_argerror(h->L, 1, "invalid next option for option 'X'"); @@ -1551,9 +1544,15 @@ static KOption getdetails (Header *h, size_t totalsize, else { if (align > h->maxalign) /* enforce maximum alignment */ align = h->maxalign; - if (l_unlikely((align & (align - 1)) != 0)) /* not a power of 2? */ + if (l_unlikely(!ispow2(align))) { /* not a power of 2? */ + *ntoalign = 0; /* to avoid warnings */ luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); - *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); + } + else { + /* 'szmoda' = totalsize % align */ + unsigned szmoda = cast_uint(totalsize & (align - 1)); + *ntoalign = cast_uint((align - szmoda) & (align - 1)); + } } return opt; } @@ -1566,9 +1565,9 @@ static KOption getdetails (Header *h, size_t totalsize, ** bytes if necessary (by default they would be zeros). */ static void packint (luaL_Buffer *b, lua_Unsigned n, - int islittle, int size, int neg) { + int islittle, unsigned size, int neg) { char *buff = luaL_prepbuffsize(b, size); - int i; + unsigned i; buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ for (i = 1; i < size; i++) { n >>= NB; @@ -1587,7 +1586,7 @@ static void packint (luaL_Buffer *b, lua_Unsigned n, ** given 'islittle' is different from native endianness. */ static void copywithendian (char *dest, const char *src, - int size, int islittle) { + unsigned size, int islittle) { if (islittle == nativeendian.little) memcpy(dest, src, size); else { @@ -1608,8 +1607,11 @@ static int str_pack (lua_State *L) { lua_pushnil(L); /* mark to separate arguments from string buffer */ luaL_buffinit(L, &b); while (*fmt != '\0') { - int size, ntoalign; + unsigned ntoalign; + size_t size; KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + luaL_argcheck(L, size + ntoalign <= MAX_SIZE - totalsize, arg, + "result too long"); totalsize += ntoalign + size; while (ntoalign-- > 0) luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ @@ -1621,7 +1623,7 @@ static int str_pack (lua_State *L) { lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); } - packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); + packint(&b, (lua_Unsigned)n, h.islittle, cast_uint(size), (n < 0)); break; } case Kuint: { /* unsigned integers */ @@ -1629,7 +1631,7 @@ static int str_pack (lua_State *L) { if (size < SZINT) /* need overflow check? */ luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), arg, "unsigned overflow"); - packint(&b, (lua_Unsigned)n, h.islittle, size, 0); + packint(&b, (lua_Unsigned)n, h.islittle, cast_uint(size), 0); break; } case Kfloat: { /* C float */ @@ -1659,20 +1661,24 @@ static int str_pack (lua_State *L) { case Kchar: { /* fixed-size string */ size_t len; const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, len <= (size_t)size, arg, - "string longer than given size"); + luaL_argcheck(L, len <= size, arg, "string longer than given size"); luaL_addlstring(&b, s, len); /* add string */ - while (len++ < (size_t)size) /* pad extra space */ - luaL_addchar(&b, LUAL_PACKPADBYTE); + if (len < size) { /* does it need padding? */ + size_t psize = size - len; /* pad size */ + char *buff = luaL_prepbuffsize(&b, psize); + memset(buff, LUAL_PACKPADBYTE, psize); + luaL_addsize(&b, psize); + } break; } case Kstring: { /* strings with length count */ size_t len; const char *s = luaL_checklstring(L, arg, &len); - luaL_argcheck(L, size >= (int)sizeof(size_t) || - len < ((size_t)1 << (size * NB)), + luaL_argcheck(L, size >= sizeof(lua_Unsigned) || + len < ((lua_Unsigned)1 << (size * NB)), arg, "string length does not fit in given size"); - packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ + /* pack length */ + packint(&b, (lua_Unsigned)len, h.islittle, cast_uint(size), 0); luaL_addlstring(&b, s, len); totalsize += len; break; @@ -1703,16 +1709,17 @@ static int str_packsize (lua_State *L) { size_t totalsize = 0; /* accumulate total size of result */ initheader(L, &h); while (*fmt != '\0') { - int size, ntoalign; + unsigned ntoalign; + size_t size; KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); luaL_argcheck(L, opt != Kstring && opt != Kzstr, 1, "variable-length format"); size += ntoalign; /* total space used by option */ - luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, - "format result too large"); + luaL_argcheck(L, totalsize <= LUA_MAXINTEGER - size, + 1, "format result too large"); totalsize += size; } - lua_pushinteger(L, (lua_Integer)totalsize); + lua_pushinteger(L, cast_st2S(totalsize)); return 1; } @@ -1761,9 +1768,10 @@ static int str_unpack (lua_State *L) { luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); initheader(L, &h); while (*fmt != '\0') { - int size, ntoalign; + unsigned ntoalign; + size_t size; KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); - luaL_argcheck(L, (size_t)ntoalign + size <= ld - pos, 2, + luaL_argcheck(L, ntoalign + size <= ld - pos, 2, "data string too short"); pos += ntoalign; /* skip alignment */ /* stack space for item + next position */ @@ -1772,8 +1780,8 @@ static int str_unpack (lua_State *L) { switch (opt) { case Kint: case Kuint: { - lua_Integer res = unpackint(L, data + pos, h.islittle, size, - (opt == Kint)); + lua_Integer res = unpackint(L, data + pos, h.islittle, + cast_int(size), (opt == Kint)); lua_pushinteger(L, res); break; } @@ -1800,7 +1808,8 @@ static int str_unpack (lua_State *L) { break; } case Kstring: { - size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); + lua_Unsigned len = (lua_Unsigned)unpackint(L, data + pos, + h.islittle, cast_int(size), 0); luaL_argcheck(L, len <= ld - pos - size, 2, "data string too short"); lua_pushlstring(L, data + pos + size, len); pos += len; /* skip string */ @@ -1820,7 +1829,7 @@ static int str_unpack (lua_State *L) { } pos += size; } - lua_pushinteger(L, pos + 1); /* next position */ + lua_pushinteger(L, cast_st2S(pos) + 1); /* next position */ return n + 1; } diff --git a/3rdparty/lua/plainlua/ltable.c b/3rdparty/lua/plainlua/ltable.c index 3353c047939a..0b3ec1762cc0 100644 --- a/3rdparty/lua/plainlua/ltable.c +++ b/3rdparty/lua/plainlua/ltable.c @@ -25,6 +25,7 @@ #include #include +#include #include "lua.h" @@ -40,18 +41,48 @@ /* -** MAXABITS is the largest integer such that MAXASIZE fits in an +** Only hash parts with at least 2^LIMFORLAST have a 'lastfree' field +** that optimizes finding a free slot. That field is stored just before +** the array of nodes, in the same block. Smaller tables do a complete +** search when looking for a free slot. +*/ +#define LIMFORLAST 3 /* log2 of real limit (8) */ + +/* +** The union 'Limbox' stores 'lastfree' and ensures that what follows it +** is properly aligned to store a Node. +*/ +typedef struct { Node *dummy; Node follows_pNode; } Limbox_aux; + +typedef union { + Node *lastfree; + char padding[offsetof(Limbox_aux, follows_pNode)]; +} Limbox; + +#define haslastfree(t) ((t)->lsizenode >= LIMFORLAST) +#define getlastfree(t) ((cast(Limbox *, (t)->node) - 1)->lastfree) + + +/* +** MAXABITS is the largest integer such that 2^MAXABITS fits in an ** unsigned int. */ -#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) +#define MAXABITS (l_numbits(int) - 1) + + +/* +** MAXASIZEB is the maximum number of elements in the array part such +** that the size of the array fits in 'size_t'. +*/ +#define MAXASIZEB (MAX_SIZET/(sizeof(Value) + 1)) /* ** MAXASIZE is the maximum size of the array part. It is the minimum -** between 2^MAXABITS and the maximum size that, measured in bytes, -** fits in a 'size_t'. +** between 2^MAXABITS and MAXASIZEB. */ -#define MAXASIZE luaM_limitN(1u << MAXABITS, TValue) +#define MAXASIZE \ + (((1u << MAXABITS) < MAXASIZEB) ? (1u << MAXABITS) : cast_uint(MAXASIZEB)) /* ** MAXHBITS is the largest integer such that 2^MAXHBITS fits in a @@ -65,7 +96,7 @@ ** between 2^MAXHBITS and the maximum size such that, measured in bytes, ** it fits in a 'size_t'. */ -#define MAXHSIZE luaM_limitN(1u << MAXHBITS, Node) +#define MAXHSIZE luaM_limitN(1 << MAXHBITS, Node) /* @@ -78,7 +109,7 @@ ** for other types, it is better to avoid modulo by power of 2, as ** they can have many 2 factors. */ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1u)|1u)))) #define hashstr(t,str) hashpow2(t, (str)->hash) @@ -90,9 +121,15 @@ #define dummynode (&dummynode_) +/* +** Common hash part for tables with empty hash parts. That allows all +** tables to have a hash part, avoiding an extra check ("is there a hash +** part?") when indexing. Its sole node has an empty value and a key +** (DEADKEY, NULL) that is different from any valid TValue. +*/ static const Node dummynode_ = { {{NULL}, LUA_VEMPTY, /* value's value and type */ - LUA_VNIL, 0, {NULL}} /* key type, next, and key value */ + LUA_TDEADKEY, 0, {NULL}} /* key type, next, and key value */ }; @@ -108,7 +145,7 @@ static const TValue absentkey = {ABSTKEYCONSTANT}; static Node *hashint (const Table *t, lua_Integer i) { lua_Unsigned ui = l_castS2U(i); if (ui <= cast_uint(INT_MAX)) - return hashmod(t, cast_int(ui)); + return gnode(t, cast_int(ui) % cast_int((sizenode(t)-1) | 1)); else return hashmod(t, ui); } @@ -128,7 +165,7 @@ static Node *hashint (const Table *t, lua_Integer i) { ** INT_MIN. */ #if !defined(l_hashfloat) -static int l_hashfloat (lua_Number n) { +static unsigned l_hashfloat (lua_Number n) { int i; lua_Integer ni; n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); @@ -138,7 +175,7 @@ static int l_hashfloat (lua_Number n) { } else { /* normal case */ unsigned int u = cast_uint(i) + cast_uint(ni); - return cast_int(u <= cast_uint(INT_MAX) ? u : ~u); + return (u <= cast_uint(INT_MAX) ? u : ~u); } } #endif @@ -236,61 +273,6 @@ static int equalkey (const TValue *k1, const Node *n2, int deadok) { } -/* -** True if value of 'alimit' is equal to the real size of the array -** part of table 't'. (Otherwise, the array part must be larger than -** 'alimit'.) -*/ -#define limitequalsasize(t) (isrealasize(t) || ispow2((t)->alimit)) - - -/* -** Returns the real size of the 'array' array -*/ -LUAI_FUNC unsigned int luaH_realasize (const Table *t) { - if (limitequalsasize(t)) - return t->alimit; /* this is the size */ - else { - unsigned int size = t->alimit; - /* compute the smallest power of 2 not smaller than 'size' */ - size |= (size >> 1); - size |= (size >> 2); - size |= (size >> 4); - size |= (size >> 8); -#if (UINT_MAX >> 14) > 3 /* unsigned int has more than 16 bits */ - size |= (size >> 16); -#if (UINT_MAX >> 30) > 3 - size |= (size >> 32); /* unsigned int has more than 32 bits */ -#endif -#endif - size++; - lua_assert(ispow2(size) && size/2 < t->alimit && t->alimit < size); - return size; - } -} - - -/* -** Check whether real size of the array is a power of 2. -** (If it is not, 'alimit' cannot be changed to any other value -** without changing the real size.) -*/ -static int ispow2realasize (const Table *t) { - return (!isrealasize(t) || ispow2(t->alimit)); -} - - -static unsigned int setlimittosize (Table *t) { - t->alimit = luaH_realasize(t); - setrealasize(t); - return t->alimit; -} - - -#define limitasasize(t) check_exp(isrealasize(t), t->alimit) - - - /* ** "Generic" get version. (Not that generic: not valid for integers, ** which may be in array part, nor for floats with integral values.) @@ -312,14 +294,34 @@ static const TValue *getgeneric (Table *t, const TValue *key, int deadok) { /* -** returns the index for 'k' if 'k' is an appropriate key to live in -** the array part of a table, 0 otherwise. +** Return the index 'k' (converted to an unsigned) if it is inside +** the range [1, limit]. */ -static unsigned int arrayindex (lua_Integer k) { - if (l_castS2U(k) - 1u < MAXASIZE) /* 'k' in [1, MAXASIZE]? */ - return cast_uint(k); /* 'key' is an appropriate array index */ - else - return 0; +static unsigned checkrange (lua_Integer k, unsigned limit) { + return (l_castS2U(k) - 1u < limit) ? cast_uint(k) : 0; +} + + +/* +** Return the index 'k' if 'k' is an appropriate key to live in the +** array part of a table, 0 otherwise. +*/ +#define arrayindex(k) checkrange(k, MAXASIZE) + + +/* +** Check whether an integer key is in the array part of a table and +** return its index there, or zero. +*/ +#define ikeyinarray(t,k) checkrange(k, t->asize) + + +/* +** Check whether a key is in the array part of a table and return its +** index there, or zero. +*/ +static unsigned keyinarray (Table *t, const TValue *key) { + return (ttisinteger(key)) ? ikeyinarray(t, ivalue(key)) : 0; } @@ -328,18 +330,18 @@ static unsigned int arrayindex (lua_Integer k) { ** elements in the array part, then elements in the hash part. The ** beginning of a traversal is signaled by 0. */ -static unsigned int findindex (lua_State *L, Table *t, TValue *key, - unsigned int asize) { +static unsigned findindex (lua_State *L, Table *t, TValue *key, + unsigned asize) { unsigned int i; if (ttisnil(key)) return 0; /* first iteration */ - i = ttisinteger(key) ? arrayindex(ivalue(key)) : 0; - if (i - 1u < asize) /* is 'key' inside array part? */ + i = keyinarray(t, key); + if (i != 0) /* is 'key' inside array part? */ return i; /* yes; that's the index */ else { const TValue *n = getgeneric(t, key, 1); if (l_unlikely(isabstkey(n))) luaG_runerror(L, "invalid key to 'next'"); /* key not found */ - i = cast_int(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ + i = cast_uint(nodefromval(n) - gnode(t, 0)); /* key index in hash table */ /* hash elements are numbered after array ones */ return (i + 1) + asize; } @@ -347,16 +349,17 @@ static unsigned int findindex (lua_State *L, Table *t, TValue *key, int luaH_next (lua_State *L, Table *t, StkId key) { - unsigned int asize = luaH_realasize(t); + unsigned int asize = t->asize; unsigned int i = findindex(L, t, s2v(key), asize); /* find original key */ for (; i < asize; i++) { /* try first array part */ - if (!isempty(&t->array[i])) { /* a non-empty entry? */ - setivalue(s2v(key), i + 1); - setobj2s(L, key + 1, &t->array[i]); + lu_byte tag = *getArrTag(t, i); + if (!tagisempty(tag)) { /* a non-empty entry? */ + setivalue(s2v(key), cast_int(i) + 1); + farr2val(t, i, tag, s2v(key + 1)); return 1; } } - for (i -= asize; cast_int(i) < sizenode(t); i++) { /* hash part */ + for (i -= asize; i < sizenode(t); i++) { /* hash part */ if (!isempty(gval(gnode(t, i)))) { /* a non-empty entry? */ Node *n = gnode(t, i); getnodekey(L, s2v(key), n); @@ -368,9 +371,21 @@ int luaH_next (lua_State *L, Table *t, StkId key) { } +/* Extra space in Node array if it has a lastfree entry */ +#define extraLastfree(t) (haslastfree(t) ? sizeof(Limbox) : 0) + +/* 'node' size in bytes */ +static size_t sizehash (Table *t) { + return cast_sizet(sizenode(t)) * sizeof(Node) + extraLastfree(t); +} + + static void freehash (lua_State *L, Table *t) { - if (!isdummy(t)) - luaM_freearray(L, t->node, cast_sizet(sizenode(t))); + if (!isdummy(t)) { + /* get pointer to the beginning of Node array */ + char *arr = cast_charp(t->node) - extraLastfree(t); + luaM_freearray(L, arr, sizehash(t)); + } } @@ -380,58 +395,92 @@ static void freehash (lua_State *L, Table *t) { ** ============================================================== */ +static int insertkey (Table *t, const TValue *key, TValue *value); +static void newcheckedkey (Table *t, const TValue *key, TValue *value); + + /* -** Compute the optimal size for the array part of table 't'. 'nums' is a -** "count array" where 'nums[i]' is the number of integers in the table -** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of -** integer keys in the table and leaves with the number of keys that -** will go to the array part; return the optimal size. (The condition -** 'twotoi > 0' in the for loop stops the loop if 'twotoi' overflows.) +** Structure to count the keys in a table. +** 'total' is the total number of keys in the table. +** 'na' is the number of *array indices* in the table (see 'arrayindex'). +** 'deleted' is true if there are deleted nodes in the hash part. +** 'nums' is a "count array" where 'nums[i]' is the number of integer +** keys between 2^(i - 1) + 1 and 2^i. Note that 'na' is the summation +** of 'nums'. */ -static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { +typedef struct { + unsigned total; + unsigned na; + int deleted; + unsigned nums[MAXABITS + 1]; +} Counters; + + +/* +** Check whether it is worth to use 'na' array entries instead of 'nh' +** hash nodes. (A hash node uses ~3 times more memory than an array +** entry: Two values plus 'next' versus one value.) Evaluate with size_t +** to avoid overflows. +*/ +#define arrayXhash(na,nh) (cast_sizet(na) <= cast_sizet(nh) * 3) + +/* +** Compute the optimal size for the array part of table 't'. +** This size maximizes the number of elements going to the array part +** while satisfying the condition 'arrayXhash' with the use of memory if +** all those elements went to the hash part. +** 'ct->na' enters with the total number of array indices in the table +** and leaves with the number of keys that will go to the array part; +** return the optimal size for the array part. +*/ +static unsigned computesizes (Counters *ct) { int i; unsigned int twotoi; /* 2^i (candidate for optimal size) */ unsigned int a = 0; /* number of elements smaller than 2^i */ unsigned int na = 0; /* number of elements to go to array part */ unsigned int optimal = 0; /* optimal size for array part */ - /* loop while keys can fill more than half of total size */ + /* traverse slices while 'twotoi' does not overflow and total of array + indices still can satisfy 'arrayXhash' against the array size */ for (i = 0, twotoi = 1; - twotoi > 0 && *pna > twotoi / 2; + twotoi > 0 && arrayXhash(twotoi, ct->na); i++, twotoi *= 2) { - a += nums[i]; - if (a > twotoi/2) { /* more than half elements present? */ + unsigned nums = ct->nums[i]; + a += nums; + if (nums > 0 && /* grows array only if it gets more elements... */ + arrayXhash(twotoi, a)) { /* ...while using "less memory" */ optimal = twotoi; /* optimal size (till now) */ na = a; /* all elements up to 'optimal' will go to array part */ } } - lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); - *pna = na; + ct->na = na; return optimal; } -static int countint (lua_Integer key, unsigned int *nums) { +static void countint (lua_Integer key, Counters *ct) { unsigned int k = arrayindex(key); - if (k != 0) { /* is 'key' an appropriate array index? */ - nums[luaO_ceillog2(k)]++; /* count as such */ - return 1; + if (k != 0) { /* is 'key' an array index? */ + ct->nums[luaO_ceillog2(k)]++; /* count as such */ + ct->na++; } - else - return 0; +} + + +l_sinline int arraykeyisempty (const Table *t, unsigned key) { + int tag = *getArrTag(t, key - 1); + return tagisempty(tag); } /* -** Count keys in array part of table 't': Fill 'nums[i]' with -** number of keys that will go into corresponding slice and return -** total number of non-nil keys. +** Count keys in array part of table 't'. */ -static unsigned int numusearray (const Table *t, unsigned int *nums) { +static void numusearray (const Table *t, Counters *ct) { int lg; unsigned int ttlg; /* 2^lg */ unsigned int ause = 0; /* summation of 'nums' */ - unsigned int i = 1; /* count to traverse all array keys */ - unsigned int asize = limitasasize(t); /* real array size */ + unsigned int i = 1; /* index to traverse all array keys */ + unsigned int asize = t->asize; /* traverse each slice */ for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { unsigned int lc = 0; /* counter */ @@ -443,30 +492,93 @@ static unsigned int numusearray (const Table *t, unsigned int *nums) { } /* count elements in range (2^(lg - 1), 2^lg] */ for (; i <= lim; i++) { - if (!isempty(&t->array[i-1])) + if (!arraykeyisempty(t, i)) lc++; } - nums[lg] += lc; + ct->nums[lg] += lc; ause += lc; } - return ause; + ct->total += ause; + ct->na += ause; } -static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { - int totaluse = 0; /* total number of elements */ - int ause = 0; /* elements added to 'nums' (can go to array part) */ - int i = sizenode(t); +/* +** Count keys in hash part of table 't'. As this only happens during +** a rehash, all nodes have been used. A node can have a nil value only +** if it was deleted after being created. +*/ +static void numusehash (const Table *t, Counters *ct) { + unsigned i = sizenode(t); + unsigned total = 0; while (i--) { Node *n = &t->node[i]; - if (!isempty(gval(n))) { + if (isempty(gval(n))) { + lua_assert(!keyisnil(n)); /* entry was deleted; key cannot be nil */ + ct->deleted = 1; + } + else { + total++; if (keyisinteger(n)) - ause += countint(keyival(n), nums); - totaluse++; + countint(keyival(n), ct); + } + } + ct->total += total; +} + + +/* +** Convert an "abstract size" (number of slots in an array) to +** "concrete size" (number of bytes in the array). +*/ +static size_t concretesize (unsigned int size) { + if (size == 0) + return 0; + else /* space for the two arrays plus an unsigned in between */ + return size * (sizeof(Value) + 1) + sizeof(unsigned); +} + + +/* +** Resize the array part of a table. If new size is equal to the old, +** do nothing. Else, if new size is zero, free the old array. (It must +** be present, as the sizes are different.) Otherwise, allocate a new +** array, move the common elements to new proper position, and then +** frees the old array. +** We could reallocate the array, but we still would need to move the +** elements to their new position, so the copy implicit in realloc is a +** waste. Moreover, most allocators will move the array anyway when the +** new size is double the old one (the most common case). +*/ +static Value *resizearray (lua_State *L , Table *t, + unsigned oldasize, + unsigned newasize) { + if (oldasize == newasize) + return t->array; /* nothing to be done */ + else if (newasize == 0) { /* erasing array? */ + Value *op = t->array - oldasize; /* original array's real address */ + luaM_freemem(L, op, concretesize(oldasize)); /* free it */ + return NULL; + } + else { + size_t newasizeb = concretesize(newasize); + Value *np = cast(Value *, + luaM_reallocvector(L, NULL, 0, newasizeb, lu_byte)); + if (np == NULL) /* allocation error? */ + return NULL; + np += newasize; /* shift pointer to the end of value segment */ + if (oldasize > 0) { + /* move common elements to new position */ + size_t oldasizeb = concretesize(oldasize); + Value *op = t->array; /* original array */ + unsigned tomove = (oldasize < newasize) ? oldasize : newasize; + size_t tomoveb = (oldasize < newasize) ? oldasizeb : newasizeb; + lua_assert(tomoveb > 0); + memcpy(np - tomove, op - tomove, tomoveb); + luaM_freemem(L, op - oldasize, oldasizeb); /* free old block */ } + return np; } - *pna += ause; - return totaluse; } @@ -477,27 +589,34 @@ static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { ** comparison ensures that the shift in the second one does not ** overflow. */ -static void setnodevector (lua_State *L, Table *t, unsigned int size) { +static void setnodevector (lua_State *L, Table *t, unsigned size) { if (size == 0) { /* no elements to hash part? */ t->node = cast(Node *, dummynode); /* use common 'dummynode' */ t->lsizenode = 0; - t->lastfree = NULL; /* signal that it is using dummy node */ + setdummy(t); /* signal that it is using dummy node */ } else { int i; int lsize = luaO_ceillog2(size); - if (lsize > MAXHBITS || (1u << lsize) > MAXHSIZE) + if (lsize > MAXHBITS || (1 << lsize) > MAXHSIZE) luaG_runerror(L, "table overflow"); size = twoto(lsize); - t->node = luaM_newvector(L, size, Node); + if (lsize < LIMFORLAST) /* no 'lastfree' field? */ + t->node = luaM_newvector(L, size, Node); + else { + size_t bsize = size * sizeof(Node) + sizeof(Limbox); + char *node = luaM_newblock(L, bsize); + t->node = cast(Node *, node + sizeof(Limbox)); + getlastfree(t) = gnode(t, size); /* all positions are free */ + } + t->lsizenode = cast_byte(lsize); + setnodummy(t); for (i = 0; i < cast_int(size); i++) { Node *n = gnode(t, i); gnext(n) = 0; setnilkey(n); setempty(gval(n)); } - t->lsizenode = cast_byte(lsize); - t->lastfree = gnode(t, size); /* all positions are free */ } } @@ -505,9 +624,9 @@ static void setnodevector (lua_State *L, Table *t, unsigned int size) { /* ** (Re)insert all elements from the hash part of 'ot' into table 't'. */ -static void reinsert (lua_State *L, Table *ot, Table *t) { - int j; - int size = sizenode(ot); +static void reinserthash (lua_State *L, Table *ot, Table *t) { + unsigned j; + unsigned size = sizenode(ot); for (j = 0; j < size; j++) { Node *old = gnode(ot, j); if (!isempty(gval(old))) { @@ -515,25 +634,56 @@ static void reinsert (lua_State *L, Table *ot, Table *t) { already present in the table */ TValue k; getnodekey(L, &k, old); - luaH_set(L, t, &k, gval(old)); + newcheckedkey(t, &k, gval(old)); } } } /* -** Exchange the hash part of 't1' and 't2'. +** Exchange the hash part of 't1' and 't2'. (In 'flags', only the +** dummy bit must be exchanged: The 'isrealasize' is not related +** to the hash part, and the metamethod bits do not change during +** a resize, so the "real" table can keep their values.) */ static void exchangehashpart (Table *t1, Table *t2) { lu_byte lsizenode = t1->lsizenode; Node *node = t1->node; - Node *lastfree = t1->lastfree; + int bitdummy1 = t1->flags & BITDUMMY; t1->lsizenode = t2->lsizenode; t1->node = t2->node; - t1->lastfree = t2->lastfree; + t1->flags = cast_byte((t1->flags & NOTBITDUMMY) | (t2->flags & BITDUMMY)); t2->lsizenode = lsizenode; t2->node = node; - t2->lastfree = lastfree; + t2->flags = cast_byte((t2->flags & NOTBITDUMMY) | bitdummy1); +} + + +/* +** Re-insert into the new hash part of a table the elements from the +** vanishing slice of the array part. +*/ +static void reinsertOldSlice (Table *t, unsigned oldasize, + unsigned newasize) { + unsigned i; + for (i = newasize; i < oldasize; i++) { /* traverse vanishing slice */ + lu_byte tag = *getArrTag(t, i); + if (!tagisempty(tag)) { /* a non-empty entry? */ + TValue key, aux; + setivalue(&key, l_castU2S(i) + 1); /* make the key */ + farr2val(t, i, tag, &aux); /* copy value into 'aux' */ + insertkey(t, &key, &aux); /* insert entry into the hash part */ + } + } +} + + +/* +** Clear new slice of the array. +*/ +static void clearNewSlice (Table *t, unsigned oldasize, unsigned newasize) { + for (; oldasize < newasize; oldasize++) + *getArrTag(t, oldasize) = LUA_VEMPTY; } @@ -549,28 +699,28 @@ static void exchangehashpart (Table *t1, Table *t2) { ** into the table, initializes the new part of the array (if any) with ** nils and reinserts the elements of the old hash back into the new ** parts of the table. +** Note that if the new size for the array part ('newasize') is equal to +** the old one ('oldasize'), this function will do nothing with that +** part. */ -void luaH_resize (lua_State *L, Table *t, unsigned int newasize, - unsigned int nhsize) { - unsigned int i; +void luaH_resize (lua_State *L, Table *t, unsigned newasize, + unsigned nhsize) { Table newt; /* to keep the new hash part */ - unsigned int oldasize = setlimittosize(t); - TValue *newarray; + unsigned oldasize = t->asize; + Value *newarray; + if (newasize > MAXASIZE) + luaG_runerror(L, "table overflow"); /* create new hash part with appropriate size into 'newt' */ + newt.flags = 0; setnodevector(L, &newt, nhsize); if (newasize < oldasize) { /* will array shrink? */ - t->alimit = newasize; /* pretend array has new size... */ - exchangehashpart(t, &newt); /* and new hash */ /* re-insert into the new hash the elements from vanishing slice */ - for (i = newasize; i < oldasize; i++) { - if (!isempty(&t->array[i])) - luaH_setint(L, t, i + 1, &t->array[i]); - } - t->alimit = oldasize; /* restore current size... */ - exchangehashpart(t, &newt); /* and hash (in case of errors) */ + exchangehashpart(t, &newt); /* pretend table has new hash */ + reinsertOldSlice(t, oldasize, newasize); + exchangehashpart(t, &newt); /* restore old hash (in case of errors) */ } /* allocate new array */ - newarray = luaM_reallocvector(L, t->array, oldasize, newasize, TValue); + newarray = resizearray(L, t, oldasize, newasize); if (l_unlikely(newarray == NULL && newasize > 0)) { /* allocation failed? */ freehash(L, &newt); /* release new hash part */ luaM_error(L); /* raise error (with array unchanged) */ @@ -578,46 +728,59 @@ void luaH_resize (lua_State *L, Table *t, unsigned int newasize, /* allocation ok; initialize new part of the array */ exchangehashpart(t, &newt); /* 't' has the new hash ('newt' has the old) */ t->array = newarray; /* set new array part */ - t->alimit = newasize; - for (i = oldasize; i < newasize; i++) /* clear new slice of the array */ - setempty(&t->array[i]); + t->asize = newasize; + if (newarray != NULL) + *lenhint(t) = newasize / 2u; /* set an initial hint */ + clearNewSlice(t, oldasize, newasize); /* re-insert elements from old hash part into new parts */ - reinsert(L, &newt, t); /* 'newt' now has the old hash */ + reinserthash(L, &newt, t); /* 'newt' now has the old hash */ freehash(L, &newt); /* free old hash part */ } void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { - int nsize = allocsizenode(t); + unsigned nsize = allocsizenode(t); luaH_resize(L, t, nasize, nsize); } + /* -** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i +** Rehash a table. First, count its keys. If there are array indices +** outside the array part, compute the new best size for that part. +** Then, resize the table. */ static void rehash (lua_State *L, Table *t, const TValue *ek) { - unsigned int asize; /* optimal size for array part */ - unsigned int na; /* number of keys in the array part */ - unsigned int nums[MAXABITS + 1]; - int i; - int totaluse; - for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ - setlimittosize(t); - na = numusearray(t, nums); /* count keys in array part */ - totaluse = na; /* all those keys are integer keys */ - totaluse += numusehash(t, nums, &na); /* count keys in hash part */ - /* count extra key */ + unsigned asize; /* optimal size for array part */ + Counters ct; + unsigned i; + unsigned nsize; /* size for the hash part */ + /* reset counts */ + for (i = 0; i <= MAXABITS; i++) ct.nums[i] = 0; + ct.na = 0; + ct.deleted = 0; + ct.total = 1; /* count extra key */ if (ttisinteger(ek)) - na += countint(ivalue(ek), nums); - totaluse++; - /* compute new size for array part */ - asize = computesizes(nums, &na); + countint(ivalue(ek), &ct); /* extra key may go to array */ + numusehash(t, &ct); /* count keys in hash part */ + if (ct.na == 0) { + /* no new keys to enter array part; keep it with the same size */ + asize = t->asize; + } + else { /* compute best size for array part */ + numusearray(t, &ct); /* count keys in array part */ + asize = computesizes(&ct); /* compute new size for array part */ + } + /* all keys not in the array part go to the hash part */ + nsize = ct.total - ct.na; + if (ct.deleted) { /* table has deleted entries? */ + /* insertion-deletion-insertion: give hash some extra size to + avoid repeated resizings */ + nsize += nsize >> 2; + } /* resize the table to new computed sizes */ - luaH_resize(L, t, asize, totaluse - na); + luaH_resize(L, t, asize, nsize); } - - /* ** }============================================================= */ @@ -627,27 +790,47 @@ Table *luaH_new (lua_State *L) { GCObject *o = luaC_newobj(L, LUA_VTABLE, sizeof(Table)); Table *t = gco2t(o); t->metatable = NULL; - t->flags = cast_byte(maskflags); /* table has no metamethod fields */ + t->flags = maskflags; /* table has no metamethod fields */ t->array = NULL; - t->alimit = 0; + t->asize = 0; setnodevector(L, t, 0); return t; } +lu_mem luaH_size (Table *t) { + lu_mem sz = cast(lu_mem, sizeof(Table)) + concretesize(t->asize); + if (!isdummy(t)) + sz += sizehash(t); + return sz; +} + + +/* +** Frees a table. +*/ void luaH_free (lua_State *L, Table *t) { freehash(L, t); - luaM_freearray(L, t->array, luaH_realasize(t)); + resizearray(L, t, t->asize, 0); luaM_free(L, t); } static Node *getfreepos (Table *t) { - if (!isdummy(t)) { - while (t->lastfree > t->node) { - t->lastfree--; - if (keyisnil(t->lastfree)) - return t->lastfree; + if (haslastfree(t)) { /* does it have 'lastfree' information? */ + /* look for a spot before 'lastfree', updating 'lastfree' */ + while (getlastfree(t) > t->node) { + Node *free = --getlastfree(t); + if (keyisnil(free)) + return free; + } + } + else { /* no 'lastfree' information */ + unsigned i = sizenode(t); + while (i--) { /* do a linear search */ + Node *free = gnode(t, i); + if (keyisnil(free)) + return free; } } return NULL; /* could not find a free place */ @@ -656,40 +839,22 @@ static Node *getfreepos (Table *t) { /* -** inserts a new key into a hash table; first, check whether key's main +** Inserts a new key into a hash table; first, check whether key's main ** position is free. If not, check whether colliding node is in its main -** position or not: if it is not, move colliding node to an empty place and -** put new key in its main position; otherwise (colliding node is in its main -** position), new key goes to an empty position. +** position or not: if it is not, move colliding node to an empty place +** and put new key in its main position; otherwise (colliding node is in +** its main position), new key goes to an empty position. Return 0 if +** could not insert key (could not find a free space). */ -static void luaH_newkey (lua_State *L, Table *t, const TValue *key, - TValue *value) { - Node *mp; - TValue aux; - if (l_unlikely(ttisnil(key))) - luaG_runerror(L, "table index is nil"); - else if (ttisfloat(key)) { - lua_Number f = fltvalue(key); - lua_Integer k; - if (luaV_flttointeger(f, &k, F2Ieq)) { /* does key fit in an integer? */ - setivalue(&aux, k); - key = &aux; /* insert it as an integer */ - } - else if (l_unlikely(luai_numisnan(f))) - luaG_runerror(L, "table index is NaN"); - } - if (ttisnil(value)) - return; /* do not insert nil values */ - mp = mainpositionTV(t, key); +static int insertkey (Table *t, const TValue *key, TValue *value) { + Node *mp = mainpositionTV(t, key); + /* table cannot already contain the key */ + lua_assert(isabstkey(getgeneric(t, key, 0))); if (!isempty(gval(mp)) || isdummy(t)) { /* main position is taken? */ Node *othern; Node *f = getfreepos(t); /* get a free place */ - if (f == NULL) { /* cannot find a free place? */ - rehash(L, t, key); /* grow table */ - /* whatever called 'newkey' takes care of TM cache */ - luaH_set(L, t, key, value); /* insert key into grown table */ - return; - } + if (f == NULL) /* cannot find a free place? */ + return 0; lua_assert(!isdummy(t)); othern = mainpositionfromnode(t, mp); if (othern != mp) { /* is colliding node out of its main position? */ @@ -713,66 +878,93 @@ static void luaH_newkey (lua_State *L, Table *t, const TValue *key, mp = f; } } - setnodekey(L, mp, key); - luaC_barrierback(L, obj2gco(t), key); + setnodekey(mp, key); lua_assert(isempty(gval(mp))); - setobj2t(L, gval(mp), value); -} - - -/* -** Search function for integers. If integer is inside 'alimit', get it -** directly from the array part. Otherwise, if 'alimit' is not -** the real size of the array, the key still can be in the array part. -** In this case, do the "Xmilia trick" to check whether 'key-1' is -** smaller than the real size. -** The trick works as follow: let 'p' be an integer such that -** '2^(p+1) >= alimit > 2^p', or '2^(p+1) > alimit-1 >= 2^p'. -** That is, 2^(p+1) is the real size of the array, and 'p' is the highest -** bit on in 'alimit-1'. What we have to check becomes 'key-1 < 2^(p+1)'. -** We compute '(key-1) & ~(alimit-1)', which we call 'res'; it will -** have the 'p' bit cleared. If the key is outside the array, that is, -** 'key-1 >= 2^(p+1)', then 'res' will have some bit on higher than 'p', -** therefore it will be larger or equal to 'alimit', and the check -** will fail. If 'key-1 < 2^(p+1)', then 'res' has no bit on higher than -** 'p', and as the bit 'p' itself was cleared, 'res' will be smaller -** than 2^p, therefore smaller than 'alimit', and the check succeeds. -** As special cases, when 'alimit' is 0 the condition is trivially false, -** and when 'alimit' is 1 the condition simplifies to 'key-1 < alimit'. -** If key is 0 or negative, 'res' will have its higher bit on, so that -** if cannot be smaller than alimit. -*/ -const TValue *luaH_getint (Table *t, lua_Integer key) { - lua_Unsigned alimit = t->alimit; - if (l_castS2U(key) - 1u < alimit) /* 'key' in [1, t->alimit]? */ - return &t->array[key - 1]; - else if (!isrealasize(t) && /* key still may be in the array part? */ - (((l_castS2U(key) - 1u) & ~(alimit - 1u)) < alimit)) { - t->alimit = cast_uint(key); /* probably '#t' is here now */ - return &t->array[key - 1]; - } - else { /* key is not in the array part; check the hash */ - Node *n = hashint(t, key); - for (;;) { /* check whether 'key' is somewhere in the chain */ - if (keyisinteger(n) && keyival(n) == key) - return gval(n); /* that's it */ - else { - int nx = gnext(n); - if (nx == 0) break; - n += nx; - } + setobj2t(cast(lua_State *, 0), gval(mp), value); + return 1; +} + + +/* +** Insert a key in a table where there is space for that key, the +** key is valid, and the value is not nil. +*/ +static void newcheckedkey (Table *t, const TValue *key, TValue *value) { + unsigned i = keyinarray(t, key); + if (i > 0) /* is key in the array part? */ + obj2arr(t, i - 1, value); /* set value in the array */ + else { + int done = insertkey(t, key, value); /* insert key in the hash part */ + lua_assert(done); /* it cannot fail */ + cast(void, done); /* to avoid warnings */ + } +} + + +static void luaH_newkey (lua_State *L, Table *t, const TValue *key, + TValue *value) { + if (!ttisnil(value)) { /* do not insert nil values */ + int done = insertkey(t, key, value); + if (!done) { /* could not find a free place? */ + rehash(L, t, key); /* grow table */ + newcheckedkey(t, key, value); /* insert key in grown table */ + } + luaC_barrierback(L, obj2gco(t), key); + /* for debugging only: any new key may force an emergency collection */ + condchangemem(L, (void)0, (void)0, 1); + } +} + + +static const TValue *getintfromhash (Table *t, lua_Integer key) { + Node *n = hashint(t, key); + lua_assert(!ikeyinarray(t, key)); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (keyisinteger(n) && keyival(n) == key) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) break; + n += nx; } - return &absentkey; } + return &absentkey; +} + + +static int hashkeyisempty (Table *t, lua_Unsigned key) { + const TValue *val = getintfromhash(t, l_castU2S(key)); + return isempty(val); +} + + +static lu_byte finishnodeget (const TValue *val, TValue *res) { + if (!ttisnil(val)) { + setobj(((lua_State*)NULL), res, val); + } + return ttypetag(val); +} + + +lu_byte luaH_getint (Table *t, lua_Integer key, TValue *res) { + unsigned k = ikeyinarray(t, key); + if (k > 0) { + lu_byte tag = *getArrTag(t, k - 1); + if (!tagisempty(tag)) + farr2val(t, k - 1, tag, res); + return tag; + } + else + return finishnodeget(getintfromhash(t, key), res); } /* ** search function for short strings */ -const TValue *luaH_getshortstr (Table *t, TString *key) { +const TValue *luaH_Hgetshortstr (Table *t, TString *key) { Node *n = hashstr(t, key); - lua_assert(key->tt == LUA_VSHRSTR); + lua_assert(strisshr(key)); for (;;) { /* check whether 'key' is somewhere in the chain */ if (keyisshrstr(n) && eqshrstr(keystrval(n), key)) return gval(n); /* that's it */ @@ -786,49 +978,195 @@ const TValue *luaH_getshortstr (Table *t, TString *key) { } -const TValue *luaH_getstr (Table *t, TString *key) { - if (key->tt == LUA_VSHRSTR) - return luaH_getshortstr(t, key); - else { /* for long strings, use generic case */ - TValue ko; - setsvalue(cast(lua_State *, NULL), &ko, key); - return getgeneric(t, &ko, 0); - } +lu_byte luaH_getshortstr (Table *t, TString *key, TValue *res) { + return finishnodeget(luaH_Hgetshortstr(t, key), res); +} + + +static const TValue *Hgetlongstr (Table *t, TString *key) { + TValue ko; + lua_assert(!strisshr(key)); + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko, 0); /* for long strings, use generic case */ +} + + +static const TValue *Hgetstr (Table *t, TString *key) { + if (strisshr(key)) + return luaH_Hgetshortstr(t, key); + else + return Hgetlongstr(t, key); +} + + +lu_byte luaH_getstr (Table *t, TString *key, TValue *res) { + return finishnodeget(Hgetstr(t, key), res); } /* ** main search function */ -const TValue *luaH_get (Table *t, const TValue *key) { +lu_byte luaH_get (Table *t, const TValue *key, TValue *res) { + const TValue *slot; switch (ttypetag(key)) { - case LUA_VSHRSTR: return luaH_getshortstr(t, tsvalue(key)); - case LUA_VNUMINT: return luaH_getint(t, ivalue(key)); - case LUA_VNIL: return &absentkey; + case LUA_VSHRSTR: + slot = luaH_Hgetshortstr(t, tsvalue(key)); + break; + case LUA_VNUMINT: + return luaH_getint(t, ivalue(key), res); + case LUA_VNIL: + slot = &absentkey; + break; case LUA_VNUMFLT: { lua_Integer k; if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ - return luaH_getint(t, k); /* use specialized version */ + return luaH_getint(t, k, res); /* use specialized version */ /* else... */ } /* FALLTHROUGH */ default: - return getgeneric(t, key, 0); + slot = getgeneric(t, key, 0); + break; } + return finishnodeget(slot, res); } /* -** Finish a raw "set table" operation, where 'slot' is where the value -** should have been (the result of a previous "get table"). -** Beware: when using this function you probably need to check a GC -** barrier and invalidate the TM cache. +** When a 'pset' cannot be completed, this function returns an encoding +** of its result, to be used by 'luaH_finishset'. */ -void luaH_finishset (lua_State *L, Table *t, const TValue *key, - const TValue *slot, TValue *value) { +static int retpsetcode (Table *t, const TValue *slot) { if (isabstkey(slot)) - luaH_newkey(L, t, key, value); + return HNOTFOUND; /* no slot with that key */ + else /* return node encoded */ + return cast_int((cast(Node*, slot) - t->node)) + HFIRSTNODE; +} + + +static int finishnodeset (Table *t, const TValue *slot, TValue *val) { + if (!ttisnil(slot)) { + setobj(((lua_State*)NULL), cast(TValue*, slot), val); + return HOK; /* success */ + } else - setobj2t(L, cast(TValue *, slot), value); + return retpsetcode(t, slot); +} + + +static int rawfinishnodeset (const TValue *slot, TValue *val) { + if (isabstkey(slot)) + return 0; /* no slot with that key */ + else { + setobj(((lua_State*)NULL), cast(TValue*, slot), val); + return 1; /* success */ + } +} + + +int luaH_psetint (Table *t, lua_Integer key, TValue *val) { + lua_assert(!ikeyinarray(t, key)); + return finishnodeset(t, getintfromhash(t, key), val); +} + + +static int psetint (Table *t, lua_Integer key, TValue *val) { + int hres; + luaH_fastseti(t, key, val, hres); + return hres; +} + + +/* +** This function could be just this: +** return finishnodeset(t, luaH_Hgetshortstr(t, key), val); +** However, it optimizes the common case created by constructors (e.g., +** {x=1, y=2}), which creates a key in a table that has no metatable, +** it is not old/black, and it already has space for the key. +*/ + +int luaH_psetshortstr (Table *t, TString *key, TValue *val) { + const TValue *slot = luaH_Hgetshortstr(t, key); + if (!ttisnil(slot)) { /* key already has a value? (all too common) */ + setobj(((lua_State*)NULL), cast(TValue*, slot), val); /* update it */ + return HOK; /* done */ + } + else if (checknoTM(t->metatable, TM_NEWINDEX)) { /* no metamethod? */ + if (ttisnil(val)) /* new value is nil? */ + return HOK; /* done (value is already nil/absent) */ + if (isabstkey(slot) && /* key is absent? */ + !(isblack(t) && iswhite(key))) { /* and don't need barrier? */ + TValue tk; /* key as a TValue */ + setsvalue(cast(lua_State *, NULL), &tk, key); + if (insertkey(t, &tk, val)) { /* insert key, if there is space */ + invalidateTMcache(t); + return HOK; + } + } + } + /* Else, either table has new-index metamethod, or it needs barrier, + or it needs to rehash for the new key. In any of these cases, the + operation cannot be completed here. Return a code for the caller. */ + return retpsetcode(t, slot); +} + + +int luaH_psetstr (Table *t, TString *key, TValue *val) { + if (strisshr(key)) + return luaH_psetshortstr(t, key, val); + else + return finishnodeset(t, Hgetlongstr(t, key), val); +} + + +int luaH_pset (Table *t, const TValue *key, TValue *val) { + switch (ttypetag(key)) { + case LUA_VSHRSTR: return luaH_psetshortstr(t, tsvalue(key), val); + case LUA_VNUMINT: return psetint(t, ivalue(key), val); + case LUA_VNIL: return HNOTFOUND; + case LUA_VNUMFLT: { + lua_Integer k; + if (luaV_flttointeger(fltvalue(key), &k, F2Ieq)) /* integral index? */ + return psetint(t, k, val); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return finishnodeset(t, getgeneric(t, key, 0), val); + } +} + +/* +** Finish a raw "set table" operation, where 'hres' encodes where the +** value should have been (the result of a previous 'pset' operation). +** Beware: when using this function the caller probably need to check a +** GC barrier and invalidate the TM cache. +*/ +void luaH_finishset (lua_State *L, Table *t, const TValue *key, + TValue *value, int hres) { + lua_assert(hres != HOK); + if (hres == HNOTFOUND) { + TValue aux; + if (l_unlikely(ttisnil(key))) + luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Number f = fltvalue(key); + lua_Integer k; + if (luaV_flttointeger(f, &k, F2Ieq)) { + setivalue(&aux, k); /* key is equal to an integer */ + key = &aux; /* insert it as an integer */ + } + else if (l_unlikely(luai_numisnan(f))) + luaG_runerror(L, "table index is NaN"); + } + luaH_newkey(L, t, key, value); + } + else if (hres > 0) { /* regular Node? */ + setobj2t(L, gval(gnode(t, hres - HFIRSTNODE)), value); + } + else { /* array entry */ + hres = ~hres; /* real index */ + obj2arr(t, cast_uint(hres), value); + } } @@ -837,20 +1175,28 @@ void luaH_finishset (lua_State *L, Table *t, const TValue *key, ** barrier and invalidate the TM cache. */ void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value) { - const TValue *slot = luaH_get(t, key); - luaH_finishset(L, t, key, slot, value); + int hres = luaH_pset(t, key, value); + if (hres != HOK) + luaH_finishset(L, t, key, value, hres); } +/* +** Ditto for a GC barrier. (No need to invalidate the TM cache, as +** integers cannot be keys to metamethods.) +*/ void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { - const TValue *p = luaH_getint(t, key); - if (isabstkey(p)) { - TValue k; - setivalue(&k, key); - luaH_newkey(L, t, &k, value); + unsigned ik = ikeyinarray(t, key); + if (ik > 0) + obj2arr(t, ik - 1, value); + else { + int ok = rawfinishnodeset(getintfromhash(t, key), value); + if (!ok) { + TValue k; + setivalue(&k, key); + luaH_newkey(L, t, &k, value); + } } - else - setobj2t(L, cast(TValue *, p), value); } @@ -876,117 +1222,101 @@ static lua_Unsigned hash_search (Table *t, lua_Unsigned j) { j *= 2; else { j = LUA_MAXINTEGER; - if (isempty(luaH_getint(t, j))) /* t[j] not present? */ + if (hashkeyisempty(t, j)) /* t[j] not present? */ break; /* 'j' now is an absent index */ else /* weird case */ return j; /* well, max integer is a boundary... */ } - } while (!isempty(luaH_getint(t, j))); /* repeat until an absent t[j] */ + } while (!hashkeyisempty(t, j)); /* repeat until an absent t[j] */ /* i < j && t[i] present && t[j] absent */ while (j - i > 1u) { /* do a binary search between them */ lua_Unsigned m = (i + j) / 2; - if (isempty(luaH_getint(t, m))) j = m; + if (hashkeyisempty(t, m)) j = m; else i = m; } return i; } -static unsigned int binsearch (const TValue *array, unsigned int i, - unsigned int j) { +static unsigned int binsearch (Table *array, unsigned int i, unsigned int j) { + lua_assert(i <= j); while (j - i > 1u) { /* binary search */ unsigned int m = (i + j) / 2; - if (isempty(&array[m - 1])) j = m; + if (arraykeyisempty(array, m)) j = m; else i = m; } return i; } +/* return a border, saving it as a hint for next call */ +static lua_Unsigned newhint (Table *t, unsigned hint) { + lua_assert(hint <= t->asize); + *lenhint(t) = hint; + return hint; +} + + /* -** Try to find a boundary in table 't'. (A 'boundary' is an integer index -** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent -** and 'maxinteger' if t[maxinteger] is present.) -** (In the next explanation, we use Lua indices, that is, with base 1. -** The code itself uses base 0 when indexing the array part of the table.) -** The code starts with 'limit = t->alimit', a position in the array -** part that may be a boundary. -** -** (1) If 't[limit]' is empty, there must be a boundary before it. -** As a common case (e.g., after 't[#t]=nil'), check whether 'limit-1' -** is present. If so, it is a boundary. Otherwise, do a binary search -** between 0 and limit to find a boundary. In both cases, try to -** use this boundary as the new 'alimit', as a hint for the next call. -** -** (2) If 't[limit]' is not empty and the array has more elements -** after 'limit', try to find a boundary there. Again, try first -** the special case (which should be quite frequent) where 'limit+1' -** is empty, so that 'limit' is a boundary. Otherwise, check the -** last element of the array part. If it is empty, there must be a -** boundary between the old limit (present) and the last element -** (absent), which is found with a binary search. (This boundary always -** can be a new limit.) -** -** (3) The last case is when there are no elements in the array part -** (limit == 0) or its last element (the new limit) is present. -** In this case, must check the hash part. If there is no hash part -** or 'limit+1' is absent, 'limit' is a boundary. Otherwise, call -** 'hash_search' to find a boundary in the hash part of the table. -** (In those cases, the boundary is not inside the array part, and -** therefore cannot be used as a new limit.) +** Try to find a border in table 't'. (A 'border' is an integer index +** such that t[i] is present and t[i+1] is absent, or 0 if t[1] is absent, +** or 'maxinteger' if t[maxinteger] is present.) +** If there is an array part, try to find a border there. First try +** to find it in the vicinity of the previous result (hint), to handle +** cases like 't[#t + 1] = val' or 't[#t] = nil', that move the border +** by one entry. Otherwise, do a binary search to find the border. +** If there is no array part, or its last element is non empty, the +** border may be in the hash part. */ lua_Unsigned luaH_getn (Table *t) { - unsigned int limit = t->alimit; - if (limit > 0 && isempty(&t->array[limit - 1])) { /* (1)? */ - /* there must be a boundary before 'limit' */ - if (limit >= 2 && !isempty(&t->array[limit - 2])) { - /* 'limit - 1' is a boundary; can it be a new limit? */ - if (ispow2realasize(t) && !ispow2(limit - 1)) { - t->alimit = limit - 1; - setnorealasize(t); /* now 'alimit' is not the real size */ - } - return limit - 1; - } - else { /* must search for a boundary in [0, limit] */ - unsigned int boundary = binsearch(t->array, 0, limit); - /* can this boundary represent the real size of the array? */ - if (ispow2realasize(t) && boundary > luaH_realasize(t) / 2) { - t->alimit = boundary; /* use it as the new limit */ - setnorealasize(t); + unsigned asize = t->asize; + if (asize > 0) { /* is there an array part? */ + const unsigned maxvicinity = 4; + unsigned limit = *lenhint(t); /* start with the hint */ + if (limit == 0) + limit = 1; /* make limit a valid index in the array */ + if (arraykeyisempty(t, limit)) { /* t[limit] empty? */ + /* there must be a border before 'limit' */ + unsigned i; + /* look for a border in the vicinity of the hint */ + for (i = 0; i < maxvicinity && limit > 1; i++) { + limit--; + if (!arraykeyisempty(t, limit)) + return newhint(t, limit); /* 'limit' is a border */ } - return boundary; + /* t[limit] still empty; search for a border in [0, limit) */ + return newhint(t, binsearch(t, 0, limit)); } - } - /* 'limit' is zero or present in table */ - if (!limitequalsasize(t)) { /* (2)? */ - /* 'limit' > 0 and array has more elements after 'limit' */ - if (isempty(&t->array[limit])) /* 'limit + 1' is empty? */ - return limit; /* this is the boundary */ - /* else, try last element in the array */ - limit = luaH_realasize(t); - if (isempty(&t->array[limit - 1])) { /* empty? */ - /* there must be a boundary in the array after old limit, - and it must be a valid new limit */ - unsigned int boundary = binsearch(t->array, t->alimit, limit); - t->alimit = boundary; - return boundary; + else { /* 'limit' is present in table; look for a border after it */ + unsigned i; + /* look for a border in the vicinity of the hint */ + for (i = 0; i < maxvicinity && limit < asize; i++) { + limit++; + if (arraykeyisempty(t, limit)) + return newhint(t, limit - 1); /* 'limit - 1' is a border */ + } + if (arraykeyisempty(t, asize)) { /* last element empty? */ + /* t[limit] not empty; search for a border in [limit, asize) */ + return newhint(t, binsearch(t, limit, asize)); + } } - /* else, new limit is present in the table; check the hash part */ + /* last element non empty; set a hint to speed up finding that again */ + /* (keys in the hash part cannot be hints) */ + *lenhint(t) = asize; } - /* (3) 'limit' is the last element and either is zero or present in table */ - lua_assert(limit == luaH_realasize(t) && - (limit == 0 || !isempty(&t->array[limit - 1]))); - if (isdummy(t) || isempty(luaH_getint(t, cast(lua_Integer, limit + 1)))) - return limit; /* 'limit + 1' is absent */ - else /* 'limit + 1' is also present */ - return hash_search(t, limit); + /* no array part or t[asize] is not empty; check the hash part */ + lua_assert(asize == 0 || !arraykeyisempty(t, asize)); + if (isdummy(t) || hashkeyisempty(t, asize + 1)) + return asize; /* 'asize + 1' is empty */ + else /* 'asize + 1' is also non empty */ + return hash_search(t, asize); } #if defined(LUA_DEBUG) -/* export these functions for the test library */ +/* export this function for the test library */ Node *luaH_mainposition (const Table *t, const TValue *key) { return mainpositionTV(t, key); diff --git a/3rdparty/lua/plainlua/ltable.h b/3rdparty/lua/plainlua/ltable.h index 8e6890342348..ca21e6920205 100644 --- a/3rdparty/lua/plainlua/ltable.h +++ b/3rdparty/lua/plainlua/ltable.h @@ -20,11 +20,21 @@ ** may have any of these metamethods. (First access that fails after the ** clearing will set the bit again.) */ -#define invalidateTMcache(t) ((t)->flags &= ~maskflags) +#define invalidateTMcache(t) ((t)->flags &= cast_byte(~maskflags)) -/* true when 't' is using 'dummynode' as its hash part */ -#define isdummy(t) ((t)->lastfree == NULL) +/* +** Bit BITDUMMY set in 'flags' means the table is using the dummy node +** for its hash part. +*/ + +#define BITDUMMY (1 << 6) +#define NOTBITDUMMY cast_byte(~BITDUMMY) +#define isdummy(t) ((t)->flags & BITDUMMY) + +#define setnodummy(t) ((t)->flags &= NOTBITDUMMY) +#define setdummy(t) ((t)->flags |= BITDUMMY) + /* allocated size for hash nodes */ @@ -35,24 +45,135 @@ #define nodefromval(v) cast(Node *, (v)) -LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); + +#define luaH_fastgeti(t,k,res,tag) \ + { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \ + if ((u < h->asize)) { \ + tag = *getArrTag(h, u); \ + if (!tagisempty(tag)) { farr2val(h, u, tag, res); }} \ + else { tag = luaH_getint(h, (k), res); }} + + +#define luaH_fastseti(t,k,val,hres) \ + { Table *h = t; lua_Unsigned u = l_castS2U(k) - 1u; \ + if ((u < h->asize)) { \ + lu_byte *tag = getArrTag(h, u); \ + if (checknoTM(h->metatable, TM_NEWINDEX) || !tagisempty(*tag)) \ + { fval2arr(h, u, tag, val); hres = HOK; } \ + else hres = ~cast_int(u); } \ + else { hres = luaH_psetint(h, k, val); }} + + +/* results from pset */ +#define HOK 0 +#define HNOTFOUND 1 +#define HNOTATABLE 2 +#define HFIRSTNODE 3 + +/* +** 'luaH_get*' operations set 'res', unless the value is absent, and +** return the tag of the result. +** The 'luaH_pset*' (pre-set) operations set the given value and return +** HOK, unless the original value is absent. In that case, if the key +** is really absent, they return HNOTFOUND. Otherwise, if there is a +** slot with that key but with no value, 'luaH_pset*' return an encoding +** of where the key is (usually called 'hres'). (pset cannot set that +** value because there might be a metamethod.) If the slot is in the +** hash part, the encoding is (HFIRSTNODE + hash index); if the slot is +** in the array part, the encoding is (~array index), a negative value. +** The value HNOTATABLE is used by the fast macros to signal that the +** value being indexed is not a table. +** (The size for the array part is limited by the maximum power of two +** that fits in an unsigned integer; that is INT_MAX+1. So, the C-index +** ranges from 0, which encodes to -1, to INT_MAX, which encodes to +** INT_MIN. The size of the hash part is limited by the maximum power of +** two that fits in a signed integer; that is (INT_MAX+1)/2. So, it is +** safe to add HFIRSTNODE to any index there.) +*/ + + +/* +** The array part of a table is represented by an inverted array of +** values followed by an array of tags, to avoid wasting space with +** padding. In between them there is an unsigned int, explained later. +** The 'array' pointer points between the two arrays, so that values are +** indexed with negative indices and tags with non-negative indices. + + Values Tags + -------------------------------------------------------- + ... | Value 1 | Value 0 |unsigned|0|1|... + -------------------------------------------------------- + ^ t->array + +** All accesses to 't->array' should be through the macros 'getArrTag' +** and 'getArrVal'. +*/ + +/* Computes the address of the tag for the abstract C-index 'k' */ +#define getArrTag(t,k) (cast(lu_byte*, (t)->array) + sizeof(unsigned) + (k)) + +/* Computes the address of the value for the abstract C-index 'k' */ +#define getArrVal(t,k) ((t)->array - 1 - (k)) + + +/* +** The unsigned between the two arrays is used as a hint for #t; +** see luaH_getn. It is stored there to avoid wasting space in +** the structure Table for tables with no array part. +*/ +#define lenhint(t) cast(unsigned*, (t)->array) + + +/* +** Move TValues to/from arrays, using C indices +*/ +#define arr2obj(h,k,val) \ + ((val)->tt_ = *getArrTag(h,(k)), (val)->value_ = *getArrVal(h,(k))) + +#define obj2arr(h,k,val) \ + (*getArrTag(h,(k)) = (val)->tt_, *getArrVal(h,(k)) = (val)->value_) + + +/* +** Often, we need to check the tag of a value before moving it. The +** following macros also move TValues to/from arrays, but receive the +** precomputed tag value or address as an extra argument. +*/ +#define farr2val(h,k,tag,res) \ + ((res)->tt_ = tag, (res)->value_ = *getArrVal(h,(k))) + +#define fval2arr(h,k,tag,val) \ + (*tag = (val)->tt_, *getArrVal(h,(k)) = (val)->value_) + + +LUAI_FUNC lu_byte luaH_get (Table *t, const TValue *key, TValue *res); +LUAI_FUNC lu_byte luaH_getshortstr (Table *t, TString *key, TValue *res); +LUAI_FUNC lu_byte luaH_getstr (Table *t, TString *key, TValue *res); +LUAI_FUNC lu_byte luaH_getint (Table *t, lua_Integer key, TValue *res); + +/* Special get for metamethods */ +LUAI_FUNC const TValue *luaH_Hgetshortstr (Table *t, TString *key); + +LUAI_FUNC int luaH_psetint (Table *t, lua_Integer key, TValue *val); +LUAI_FUNC int luaH_psetshortstr (Table *t, TString *key, TValue *val); +LUAI_FUNC int luaH_psetstr (Table *t, TString *key, TValue *val); +LUAI_FUNC int luaH_pset (Table *t, const TValue *key, TValue *val); + LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value); -LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); -LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); LUAI_FUNC void luaH_set (lua_State *L, Table *t, const TValue *key, TValue *value); + LUAI_FUNC void luaH_finishset (lua_State *L, Table *t, const TValue *key, - const TValue *slot, TValue *value); + TValue *value, int hres); LUAI_FUNC Table *luaH_new (lua_State *L); -LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, - unsigned int nhsize); -LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned nasize, + unsigned nhsize); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned nasize); +LUAI_FUNC lu_mem luaH_size (Table *t); LUAI_FUNC void luaH_free (lua_State *L, Table *t); LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); LUAI_FUNC lua_Unsigned luaH_getn (Table *t); -LUAI_FUNC unsigned int luaH_realasize (const Table *t); #if defined(LUA_DEBUG) diff --git a/3rdparty/lua/plainlua/ltablib.c b/3rdparty/lua/plainlua/ltablib.c index e6bc4d04af47..46ecb5e024a6 100644 --- a/3rdparty/lua/plainlua/ltablib.c +++ b/3rdparty/lua/plainlua/ltablib.c @@ -18,6 +18,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" /* @@ -58,6 +59,16 @@ static void checktab (lua_State *L, int arg, int what) { } +static int tcreate (lua_State *L) { + lua_Unsigned sizeseq = (lua_Unsigned)luaL_checkinteger(L, 1); + lua_Unsigned sizerest = (lua_Unsigned)luaL_optinteger(L, 2, 0); + luaL_argcheck(L, sizeseq <= cast_uint(INT_MAX), 1, "out of range"); + luaL_argcheck(L, sizerest <= cast_uint(INT_MAX), 2, "out of range"); + lua_createtable(L, cast_int(sizeseq), cast_int(sizerest)); + return 1; +} + + static int tinsert (lua_State *L) { lua_Integer pos; /* where to insert new element */ lua_Integer e = aux_getn(L, 1, TAB_RW); @@ -196,7 +207,7 @@ static int tunpack (lua_State *L) { lua_Integer i = luaL_optinteger(L, 2, 1); lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); if (i > e) return 0; /* empty range */ - n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ + n = l_castS2U(e) - l_castS2U(i); /* number of elements minus 1 */ if (l_unlikely(n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n)))) return luaL_error(L, "too many results to unpack"); @@ -220,41 +231,26 @@ static int tunpack (lua_State *L) { */ -/* type for array indices */ +/* +** Type for array indices. These indices are always limited by INT_MAX, +** so it is safe to cast them to lua_Integer even for Lua 32 bits. +*/ typedef unsigned int IdxT; +/* Versions of lua_seti/lua_geti specialized for IdxT */ +#define geti(L,idt,idx) lua_geti(L, idt, l_castU2S(idx)) +#define seti(L,idt,idx) lua_seti(L, idt, l_castU2S(idx)) + + /* ** Produce a "random" 'unsigned int' to randomize pivot choice. This ** macro is used only when 'sort' detects a big imbalance in the result ** of a partition. (If you don't want/need this "randomness", ~0 is a ** good choice.) */ -#if !defined(l_randomizePivot) /* { */ - -#include - -/* size of 'e' measured in number of 'unsigned int's */ -#define sof(e) (sizeof(e) / sizeof(unsigned int)) - -/* -** Use 'time' and 'clock' as sources of "randomness". Because we don't -** know the types 'clock_t' and 'time_t', we cannot cast them to -** anything without risking overflows. A safe way to use their values -** is to copy them to an array of a known type and use the array values. -*/ -static unsigned int l_randomizePivot (void) { - clock_t c = clock(); - time_t t = time(NULL); - unsigned int buff[sof(c) + sof(t)]; - unsigned int i, rnd = 0; - memcpy(buff, &c, sof(c) * sizeof(unsigned int)); - memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); - for (i = 0; i < sof(buff); i++) - rnd += buff[i]; - return rnd; -} - +#if !defined(l_randomizePivot) +#define l_randomizePivot(L) luaL_makeseed(L) #endif /* } */ @@ -263,8 +259,8 @@ static unsigned int l_randomizePivot (void) { static void set2 (lua_State *L, IdxT i, IdxT j) { - lua_seti(L, 1, i); - lua_seti(L, 1, j); + seti(L, 1, i); + seti(L, 1, j); } @@ -301,15 +297,15 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) { /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ for (;;) { /* next loop: repeat ++i while a[i] < P */ - while ((void)lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { - if (l_unlikely(i == up - 1)) /* a[i] < P but a[up - 1] == P ?? */ + while ((void)geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (l_unlikely(i == up - 1)) /* a[up - 1] < P == a[up - 1] */ luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[i] */ } - /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* after the loop, a[i] >= P and a[lo .. i - 1] < P (a) */ /* next loop: repeat --j while P < a[j] */ - while ((void)lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { - if (l_unlikely(j < i)) /* j < i but a[j] > P ?? */ + while ((void)geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (l_unlikely(j < i)) /* j <= i - 1 and a[j] > P, contradicts (a) */ luaL_error(L, "invalid order function for sorting"); lua_pop(L, 1); /* remove a[j] */ } @@ -333,7 +329,7 @@ static IdxT partition (lua_State *L, IdxT lo, IdxT up) { */ static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { IdxT r4 = (up - lo) / 4; /* range/4 */ - IdxT p = rnd % (r4 * 2) + (lo + r4); + IdxT p = (rnd ^ lo ^ up) % (r4 * 2) + (lo + r4); lua_assert(lo + r4 <= p && p <= up - r4); return p; } @@ -342,14 +338,13 @@ static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { /* ** Quicksort algorithm (recursive function) */ -static void auxsort (lua_State *L, IdxT lo, IdxT up, - unsigned int rnd) { +static void auxsort (lua_State *L, IdxT lo, IdxT up, unsigned rnd) { while (lo < up) { /* loop for tail recursion */ IdxT p; /* Pivot index */ IdxT n; /* to be used later */ /* sort elements 'lo', 'p', and 'up' */ - lua_geti(L, 1, lo); - lua_geti(L, 1, up); + geti(L, 1, lo); + geti(L, 1, up); if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ set2(L, lo, up); /* swap a[lo] - a[up] */ else @@ -360,13 +355,13 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, p = (lo + up)/2; /* middle element is a good pivot */ else /* for larger intervals, it is worth a random pivot */ p = choosePivot(lo, up, rnd); - lua_geti(L, 1, p); - lua_geti(L, 1, lo); + geti(L, 1, p); + geti(L, 1, lo); if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ set2(L, p, lo); /* swap a[p] - a[lo] */ else { lua_pop(L, 1); /* remove a[lo] */ - lua_geti(L, 1, up); + geti(L, 1, up); if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ set2(L, p, up); /* swap a[up] - a[p] */ else @@ -374,9 +369,9 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, } if (up - lo == 2) /* only 3 elements? */ return; /* already sorted */ - lua_geti(L, 1, p); /* get middle element (Pivot) */ + geti(L, 1, p); /* get middle element (Pivot) */ lua_pushvalue(L, -1); /* push Pivot */ - lua_geti(L, 1, up - 1); /* push a[up - 1] */ + geti(L, 1, up - 1); /* push a[up - 1] */ set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ p = partition(L, lo, up); /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ @@ -391,7 +386,7 @@ static void auxsort (lua_State *L, IdxT lo, IdxT up, up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ } if ((up - lo) / 128 > n) /* partition too imbalanced? */ - rnd = l_randomizePivot(); /* try a new randomization */ + rnd = l_randomizePivot(L); /* try a new randomization */ } /* tail call auxsort(L, lo, up, rnd) */ } @@ -413,6 +408,7 @@ static int sort (lua_State *L) { static const luaL_Reg tab_funcs[] = { {"concat", tconcat}, + {"create", tcreate}, {"insert", tinsert}, {"pack", tpack}, {"unpack", tunpack}, diff --git a/3rdparty/lua/plainlua/ltm.c b/3rdparty/lua/plainlua/ltm.c index 07a060811d5c..8eca2d6e1fd7 100644 --- a/3rdparty/lua/plainlua/ltm.c +++ b/3rdparty/lua/plainlua/ltm.c @@ -58,7 +58,7 @@ void luaT_init (lua_State *L) { ** tag methods */ const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { - const TValue *tm = luaH_getshortstr(events, ename); + const TValue *tm = luaH_Hgetshortstr(events, ename); lua_assert(event <= TM_EQ); if (notm(tm)) { /* no tag method? */ events->flags |= cast_byte(1u<mt[ttype(o)]; } - return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); + return (mt ? luaH_Hgetshortstr(mt, G(L)->tmname[event]) : &G(L)->nilvalue); } @@ -92,7 +92,7 @@ const char *luaT_objtypename (lua_State *L, const TValue *o) { Table *mt; if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { - const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); + const TValue *name = luaH_Hgetshortstr(mt, luaS_new(L, "__name")); if (ttisstring(name)) /* is '__name' a string? */ return getstr(tsvalue(name)); /* use it as type name */ } @@ -116,8 +116,8 @@ void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, } -void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, - const TValue *p2, StkId res) { +lu_byte luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, StkId res) { ptrdiff_t result = savestack(L, res); StkId func = L->top.p; setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ @@ -131,6 +131,7 @@ void luaT_callTMres (lua_State *L, const TValue *f, const TValue *p1, luaD_callnoyield(L, func, 1); res = restorestack(L, result); setobjs2s(L, res, --L->top.p); /* move result to its place */ + return ttypetag(s2v(res)); /* return tag of the result */ } @@ -139,15 +140,16 @@ static int callbinTM (lua_State *L, const TValue *p1, const TValue *p2, const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ if (notm(tm)) tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ - if (notm(tm)) return 0; - luaT_callTMres(L, tm, p1, p2, res); - return 1; + if (notm(tm)) + return -1; /* tag method not found */ + else /* call tag method and return the tag of the result */ + return luaT_callTMres(L, tm, p1, p2, res); } void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event) { - if (l_unlikely(!callbinTM(L, p1, p2, res, event))) { + if (l_unlikely(callbinTM(L, p1, p2, res, event) < 0)) { switch (event) { case TM_BAND: case TM_BOR: case TM_BXOR: case TM_SHL: case TM_SHR: case TM_BNOT: { @@ -164,11 +166,14 @@ void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, } +/* +** The use of 'p1' after 'callbinTM' is safe because, when a tag +** method is not found, 'callbinTM' cannot change the stack. +*/ void luaT_tryconcatTM (lua_State *L) { - StkId top = L->top.p; - if (l_unlikely(!callbinTM(L, s2v(top - 2), s2v(top - 1), top - 2, - TM_CONCAT))) - luaG_concaterror(L, s2v(top - 2), s2v(top - 1)); + StkId p1 = L->top.p - 2; /* first argument */ + if (l_unlikely(callbinTM(L, s2v(p1), s2v(p1 + 1), p1, TM_CONCAT) < 0)) + luaG_concaterror(L, s2v(p1), s2v(p1 + 1)); } @@ -200,17 +205,17 @@ void luaT_trybiniTM (lua_State *L, const TValue *p1, lua_Integer i2, */ int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, TMS event) { - if (callbinTM(L, p1, p2, L->top.p, event)) /* try original event */ - return !l_isfalse(s2v(L->top.p)); + int tag = callbinTM(L, p1, p2, L->top.p, event); /* try original event */ + if (tag >= 0) /* found tag method? */ + return !tagisfalse(tag); #if defined(LUA_COMPAT_LT_LE) else if (event == TM_LE) { - /* try '!(p2 < p1)' for '(p1 <= p2)' */ - L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ - if (callbinTM(L, p2, p1, L->top.p, TM_LT)) { - L->ci->callstatus ^= CIST_LEQ; /* clear mark */ - return l_isfalse(s2v(L->top.p)); - } - /* else error will remove this 'ci'; no need to clear mark */ + /* try '!(p2 < p1)' for '(p1 <= p2)' */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + tag = callbinTM(L, p2, p1, L->top.p, TM_LT); + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + if (tag >= 0) /* found tag method? */ + return tagisfalse(tag); } #endif luaG_ordererror(L, p1, p2); /* no metamethod found */ @@ -260,7 +265,7 @@ void luaT_getvarargs (lua_State *L, CallInfo *ci, StkId where, int wanted) { int nextra = ci->u.l.nextraargs; if (wanted < 0) { wanted = nextra; /* get all extra arguments available */ - checkstackGCp(L, nextra, where); /* ensure stack space */ + checkstackp(L, nextra, where); /* ensure stack space */ L->top.p = where + nextra; /* next instruction will need top */ } for (i = 0; i < wanted && i < nextra; i++) diff --git a/3rdparty/lua/plainlua/ltm.h b/3rdparty/lua/plainlua/ltm.h index 73b833c605da..ba2e47606ee8 100644 --- a/3rdparty/lua/plainlua/ltm.h +++ b/3rdparty/lua/plainlua/ltm.h @@ -48,10 +48,10 @@ typedef enum { /* ** Mask with 1 in all fast-access methods. A 1 in any of these bits ** in the flag of a (meta)table means the metatable does not have the -** corresponding metamethod field. (Bit 7 of the flag is used for -** 'isrealasize'.) +** corresponding metamethod field. (Bit 6 of the flag indicates that +** the table is using the dummy node; bit 7 is used for 'isrealasize'.) */ -#define maskflags (~(~0u << (TM_EQ + 1))) +#define maskflags cast_byte(~(~0u << (TM_EQ + 1))) /* @@ -60,11 +60,12 @@ typedef enum { */ #define notm(tm) ttisnil(tm) +#define checknoTM(mt,e) ((mt) == NULL || (mt)->flags & (1u<<(e))) -#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ - ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) +#define gfasttm(g,mt,e) \ + (checknoTM(mt, e) ? NULL : luaT_gettm(mt, e, (g)->tmname[e])) -#define fasttm(l,et,e) gfasttm(G(l), et, e) +#define fasttm(l,mt,e) gfasttm(G(l), mt, e) #define ttypename(x) luaT_typenames_[(x) + 1] @@ -80,8 +81,8 @@ LUAI_FUNC void luaT_init (lua_State *L); LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, const TValue *p2, const TValue *p3); -LUAI_FUNC void luaT_callTMres (lua_State *L, const TValue *f, - const TValue *p1, const TValue *p2, StkId p3); +LUAI_FUNC lu_byte luaT_callTMres (lua_State *L, const TValue *f, + const TValue *p1, const TValue *p2, StkId p3); LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, StkId res, TMS event); LUAI_FUNC void luaT_tryconcatTM (lua_State *L); diff --git a/3rdparty/lua/plainlua/lua.c b/3rdparty/lua/plainlua/lua.c index 4a90e55dd94b..a90bf29b508f 100644 --- a/3rdparty/lua/plainlua/lua.c +++ b/3rdparty/lua/plainlua/lua.c @@ -19,6 +19,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" #if !defined(LUA_PROGNAME) @@ -431,32 +432,90 @@ static int handle_luainit (lua_State *L) { /* -** lua_readline defines how to show a prompt and then read a line from -** the standard input. -** lua_saveline defines how to "save" a read line in a "history". -** lua_freeline defines how to free a line read by lua_readline. +** * lua_initreadline initializes the readline system. +** * lua_readline defines how to show a prompt and then read a line from +** the standard input. +** * lua_saveline defines how to "save" a read line in a "history". +** * lua_freeline defines how to free a line read by lua_readline. +** +** If lua_readline is defined, all of them should be defined. */ + #if !defined(lua_readline) /* { */ +/* Code to use the readline library, either statically or dynamically linked */ + +/* pointer to 'readline' function (if any) */ +typedef char *(*l_readlineT) (const char *prompt); +static l_readlineT l_readline = NULL; + +/* pointer to 'add_history' function (if any) */ +typedef void (*l_addhistT) (const char *string); +static l_addhistT l_addhist = NULL; + + +static char *lua_readline (char *buff, const char *prompt) { + if (l_readline != NULL) /* is there a 'readline'? */ + return (*l_readline)(prompt); /* use it */ + else { /* emulate 'readline' over 'buff' */ + fputs(prompt, stdout); + fflush(stdout); /* show prompt */ + return fgets(buff, LUA_MAXINPUT, stdin); /* read line */ + } +} + + +static void lua_saveline (const char *line) { + if (l_addhist != NULL) /* is there an 'add_history'? */ + (*l_addhist)(line); /* use it */ + /* else nothing to be done */ +} + + +static void lua_freeline (char *line) { + if (l_readline != NULL) /* is there a 'readline'? */ + free(line); /* free line created by it */ + /* else 'lua_readline' used an automatic buffer; nothing to free */ +} + + #if defined(LUA_USE_READLINE) /* { */ +/* assume Lua will be linked with '-lreadline' */ #include #include -#define lua_initreadline(L) ((void)L, rl_readline_name="lua") -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) -#define lua_saveline(L,line) ((void)L, add_history(line)) -#define lua_freeline(L,b) ((void)L, free(b)) -#else /* }{ */ +static void lua_initreadline(lua_State *L) { + UNUSED(L); + rl_readline_name = "lua"; + l_readline = cast(l_readlineT, readline); + l_addhist = cast(l_addhistT, add_history); +} -#define lua_initreadline(L) ((void)L) -#define lua_readline(L,b,p) \ - ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ - fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,line) { (void)L; (void)line; } -#define lua_freeline(L,b) { (void)L; (void)b; } +#elif defined(LUA_USE_DLOPEN) && defined(LUA_READLINELIB) /* }{ */ -#endif /* } */ +/* try to load 'readline' dynamically */ +#include + +static void lua_initreadline (lua_State *L) { + void *lib = dlopen(LUA_READLINELIB, RTLD_NOW | RTLD_LOCAL); + if (lib == NULL) + lua_warning(L, "library '" LUA_READLINELIB "' not found", 0); + else { + const char **name = cast(const char**, dlsym(lib, "rl_readline_name")); + if (name != NULL) + *name = "lua"; + l_readline = cast(l_readlineT, cast_func(dlsym(lib, "readline"))); + l_addhist = cast(l_addhistT, cast_func(dlsym(lib, "add_history"))); + } +} + +#else /* }{ */ + +/* no readline; leave function pointers as NULL */ +#define lua_initreadline(L) cast(void, L) + +#endif /* } */ #endif /* } */ @@ -502,21 +561,17 @@ static int incomplete (lua_State *L, int status) { */ static int pushline (lua_State *L, int firstline) { char buffer[LUA_MAXINPUT]; - char *b = buffer; size_t l; const char *prmt = get_prompt(L, firstline); - int readstatus = lua_readline(L, b, prmt); + char *b = lua_readline(buffer, prmt); lua_pop(L, 1); /* remove prompt */ - if (readstatus == 0) + if (b == NULL) return 0; /* no input */ l = strlen(b); if (l > 0 && b[l-1] == '\n') /* line ends with newline? */ b[--l] = '\0'; /* remove it */ - if (firstline && b[0] == '=') /* for compatibility with 5.2, ... */ - lua_pushfstring(L, "return %s", b + 1); /* change '=' to 'return' */ - else - lua_pushlstring(L, b, l); - lua_freeline(L, b); + lua_pushlstring(L, b, l); + lua_freeline(b); return 1; } @@ -529,33 +584,44 @@ static int addreturn (lua_State *L) { const char *line = lua_tostring(L, -1); /* original line */ const char *retline = lua_pushfstring(L, "return %s;", line); int status = luaL_loadbuffer(L, retline, strlen(retline), "=stdin"); - if (status == LUA_OK) { + if (status == LUA_OK) lua_remove(L, -2); /* remove modified line */ - if (line[0] != '\0') /* non empty? */ - lua_saveline(L, line); /* keep history */ - } else lua_pop(L, 2); /* pop result from 'luaL_loadbuffer' and modified line */ return status; } +static void checklocal (const char *line) { + static const size_t szloc = sizeof("local") - 1; + static const char space[] = " \t"; + line += strspn(line, space); /* skip spaces */ + if (strncmp(line, "local", szloc) == 0 && /* "local"? */ + strchr(space, *(line + szloc)) != NULL) { /* followed by a space? */ + lua_writestringerror("%s\n", + "warning: locals do not survive across lines in interactive mode"); + } +} + + /* -** Read multiple lines until a complete Lua statement +** Read multiple lines until a complete Lua statement or an error not +** for an incomplete statement. Start with first line already read in +** the stack. */ static int multiline (lua_State *L) { + size_t len; + const char *line = lua_tolstring(L, 1, &len); /* get first line */ + checklocal(line); for (;;) { /* repeat until gets a complete statement */ - size_t len; - const char *line = lua_tolstring(L, 1, &len); /* get what it has */ int status = luaL_loadbuffer(L, line, len, "=stdin"); /* try it */ - if (!incomplete(L, status) || !pushline(L, 0)) { - lua_saveline(L, line); /* keep history */ + if (!incomplete(L, status) || !pushline(L, 0)) return status; /* should not or cannot try to add continuation line */ - } lua_remove(L, -2); /* remove error message (from incomplete line) */ lua_pushliteral(L, "\n"); /* add newline... */ lua_insert(L, -2); /* ...between the two lines */ lua_concat(L, 3); /* join them */ + line = lua_tolstring(L, 1, &len); /* get what is has */ } } @@ -567,12 +633,16 @@ static int multiline (lua_State *L) { ** in the top of the stack. */ static int loadline (lua_State *L) { + const char *line; int status; lua_settop(L, 0); if (!pushline(L, 1)) return -1; /* no input */ if ((status = addreturn(L)) != LUA_OK) /* 'return ...' did not work? */ status = multiline(L); /* try as command, maybe with continuation lines */ + line = lua_tostring(L, 1); + if (line[0] != '\0') /* non empty? */ + lua_saveline(line); /* keep history */ lua_remove(L, 1); /* remove line from the stack */ lua_assert(lua_gettop(L) == 1); return status; @@ -617,6 +687,10 @@ static void doREPL (lua_State *L) { /* }================================================================== */ +#if !defined(luai_openlibs) +#define luai_openlibs(L) luaL_openselectedlibs(L, ~0, 0) +#endif + /* ** Main body of stand-alone interpreter (to be called in protected mode). @@ -639,10 +713,10 @@ static int pmain (lua_State *L) { lua_pushboolean(L, 1); /* signal for libraries to ignore env. vars. */ lua_setfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); } - luaL_openlibs(L); /* open standard libraries */ + luai_openlibs(L); /* open standard libraries */ createargtable(L, argv, argc, script); /* create table 'arg' */ lua_gc(L, LUA_GCRESTART); /* start GC... */ - lua_gc(L, LUA_GCGEN, 0, 0); /* ...in generational mode */ + lua_gc(L, LUA_GCGEN); /* ...in generational mode */ if (!(args & has_E)) { /* no option '-E'? */ if (handle_luainit(L) != LUA_OK) /* run LUA_INIT */ return 0; /* error running LUA_INIT */ diff --git a/3rdparty/lua/plainlua/lua.h b/3rdparty/lua/plainlua/lua.h index f3ea590d9cd6..95e0db321a0d 100644 --- a/3rdparty/lua/plainlua/lua.h +++ b/3rdparty/lua/plainlua/lua.h @@ -1,7 +1,7 @@ /* ** $Id: lua.h $ ** Lua - A Scripting Language -** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** Lua.org, PUC-Rio, Brazil (www.lua.org) ** See Copyright Notice at the end of this file */ @@ -13,20 +13,19 @@ #include -#include "luaconf.h" +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2025 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "4" -#define LUA_VERSION_RELEASE "8" +#define LUA_VERSION_MAJOR_N 5 +#define LUA_VERSION_MINOR_N 5 +#define LUA_VERSION_RELEASE_N 0 -#define LUA_VERSION_NUM 504 -#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + 8) +#define LUA_VERSION_NUM (LUA_VERSION_MAJOR_N * 100 + LUA_VERSION_MINOR_N) +#define LUA_VERSION_RELEASE_NUM (LUA_VERSION_NUM * 100 + LUA_VERSION_RELEASE_N) -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2025 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + +#include "luaconf.h" /* mark for precompiled code ('Lua') */ @@ -81,9 +80,10 @@ typedef struct lua_State lua_State; /* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 +/* index 1 is reserved for the reference mechanism */ #define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS +#define LUA_RIDX_MAINTHREAD 3 +#define LUA_RIDX_LAST 3 /* type of numbers in Lua */ @@ -160,11 +160,10 @@ extern const char lua_ident[]; /* ** state manipulation */ -LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud, unsigned seed); LUA_API void (lua_close) (lua_State *L); LUA_API lua_State *(lua_newthread) (lua_State *L); LUA_API int (lua_closethread) (lua_State *L, lua_State *from); -LUA_API int (lua_resetthread) (lua_State *L); /* Deprecated! */ LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); @@ -245,6 +244,8 @@ LUA_API void (lua_pushnil) (lua_State *L); LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushexternalstring) (lua_State *L, + const char *s, size_t len, lua_Alloc falloc, void *ud); LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, va_list argp); @@ -324,7 +325,7 @@ LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont); /* -** garbage-collection function and options +** garbage-collection options */ #define LUA_GCSTOP 0 @@ -333,11 +334,28 @@ LUA_API void (lua_warning) (lua_State *L, const char *msg, int tocont); #define LUA_GCCOUNT 3 #define LUA_GCCOUNTB 4 #define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 +#define LUA_GCISRUNNING 6 +#define LUA_GCGEN 7 +#define LUA_GCINC 8 +#define LUA_GCPARAM 9 + + +/* +** garbage-collection parameters +*/ +/* parameters for generational mode */ +#define LUA_GCPMINORMUL 0 /* control minor collections */ +#define LUA_GCPMAJORMINOR 1 /* control shift major->minor */ +#define LUA_GCPMINORMAJOR 2 /* control shift minor->major */ + +/* parameters for incremental mode */ +#define LUA_GCPPAUSE 3 /* size of pause between successive GCs */ +#define LUA_GCPSTEPMUL 4 /* GC "speed" */ +#define LUA_GCPSTEPSIZE 5 /* GC granularity */ + +/* number of parameters */ +#define LUA_GCPN 6 + LUA_API int (lua_gc) (lua_State *L, int what, ...); @@ -353,7 +371,9 @@ LUA_API int (lua_next) (lua_State *L, int idx); LUA_API void (lua_concat) (lua_State *L, int n); LUA_API void (lua_len) (lua_State *L, int idx); -LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); +#define LUA_N2SBUFFSZ 64 +LUA_API unsigned (lua_numbertocstring) (lua_State *L, int idx, char *buff); +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); @@ -424,7 +444,7 @@ LUA_API void (lua_closeslot) (lua_State *L, int idx); #define lua_getuservalue(L,idx) lua_getiuservalue(L,idx,1) #define lua_setuservalue(L,idx) lua_setiuservalue(L,idx,1) -#define LUA_NUMTAGS LUA_NUMTYPES +#define lua_resetthread(L) lua_closethread(L,NULL) /* }============================================================== */ @@ -470,7 +490,6 @@ LUA_API lua_Hook (lua_gethook) (lua_State *L); LUA_API int (lua_gethookmask) (lua_State *L); LUA_API int (lua_gethookcount) (lua_State *L); -LUA_API int (lua_setcstacklimit) (lua_State *L, unsigned int limit); struct lua_Debug { int event; @@ -485,9 +504,10 @@ struct lua_Debug { unsigned char nups; /* (u) number of upvalues */ unsigned char nparams;/* (u) number of parameters */ char isvararg; /* (u) */ + unsigned char extraargs; /* (t) number of extra arguments */ char istailcall; /* (t) */ - unsigned short ftransfer; /* (r) index of first value transferred */ - unsigned short ntransfer; /* (r) number of transferred values */ + int ftransfer; /* (r) index of first value transferred */ + int ntransfer; /* (r) number of transferred values */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ struct CallInfo *i_ci; /* active function */ @@ -496,6 +516,17 @@ struct lua_Debug { /* }====================================================================== */ +#define LUAI_TOSTRAUX(x) #x +#define LUAI_TOSTR(x) LUAI_TOSTRAUX(x) + +#define LUA_VERSION_MAJOR LUAI_TOSTR(LUA_VERSION_MAJOR_N) +#define LUA_VERSION_MINOR LUAI_TOSTR(LUA_VERSION_MINOR_N) +#define LUA_VERSION_RELEASE LUAI_TOSTR(LUA_VERSION_RELEASE_N) + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE + + /****************************************************************************** * Copyright (C) 1994-2025 Lua.org, PUC-Rio. * diff --git a/3rdparty/lua/plainlua/lua.hpp b/3rdparty/lua/plainlua/lua.hpp index ec417f59469c..2853364f7679 100644 --- a/3rdparty/lua/plainlua/lua.hpp +++ b/3rdparty/lua/plainlua/lua.hpp @@ -1,6 +1,7 @@ // lua.hpp // Lua header files for C++ -// <> not supplied automatically because Lua also compiles as C++ +// 'extern "C" not supplied automatically in lua.h and other headers +// because Lua also compiles as C++ extern "C" { #include "lua.h" diff --git a/3rdparty/lua/plainlua/luac.c b/3rdparty/lua/plainlua/luac.c index 5f4a141bddd9..4b2524d50e5c 100644 --- a/3rdparty/lua/plainlua/luac.c +++ b/3rdparty/lua/plainlua/luac.c @@ -18,6 +18,7 @@ #include "lua.h" #include "lauxlib.h" +#include "lapi.h" #include "ldebug.h" #include "lobject.h" #include "lopcodes.h" @@ -679,7 +680,7 @@ static void PrintHeader(const Proto* f) f->linedefined,f->lastlinedefined, S(f->sizecode),VOID(f)); printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + (int)(f->numparams),(f->flag & PF_ISVARARG)?"+":"",SS(f->numparams), S(f->maxstacksize),S(f->sizeupvalues)); printf("%d local%s, %d constant%s, %d function%s\n", S(f->sizelocvars),S(f->sizek),S(f->sizep)); diff --git a/3rdparty/lua/plainlua/luaconf.h b/3rdparty/lua/plainlua/luaconf.h index 33bb580d17c5..51e77547beb5 100644 --- a/3rdparty/lua/plainlua/luaconf.h +++ b/3rdparty/lua/plainlua/luaconf.h @@ -58,15 +58,26 @@ #endif +/* +** When Posix DLL ('LUA_USE_DLOPEN') is enabled, the Lua stand-alone +** application will try to dynamically link a 'readline' facility +** for its REPL. In that case, LUA_READLINELIB is the name of the +** library it will look for those facilities. If lua.c cannot open +** the specified library, it will generate a warning and then run +** without 'readline'. If that macro is not defined, lua.c will not +** use 'readline'. +*/ #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX #define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_READLINELIB "libreadline.so" #endif #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX #define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_READLINELIB "libedit.dylib" #endif @@ -76,6 +87,11 @@ #endif +#if defined(LUA_USE_C89) && defined(LUA_USE_POSIX) +#error "Posix is not compatible with C89" +#endif + + /* @@ LUAI_IS32INT is true iff 'int' has (at least) 32 bits. */ @@ -339,6 +355,12 @@ ** =================================================================== */ +/* +@@ LUA_COMPAT_GLOBAL avoids 'global' being a reserved word +*/ +#define LUA_COMPAT_GLOBAL + + /* @@ LUA_COMPAT_5_3 controls other macros for compatibility with Lua 5.3. ** You can define it to get all options, or change specific options @@ -405,8 +427,13 @@ @@ l_floatatt(x) corrects float attribute 'x' to the proper float type ** by prefixing it with one of FLT/DBL/LDBL. @@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. -@@ LUA_NUMBER_FMT is the format for writing floats. -@@ lua_number2str converts a float to a string. +@@ LUA_NUMBER_FMT is the format for writing floats with the maximum +** number of digits that respects tostring(tonumber(numeral)) == numeral. +** (That would be floor(log10(2^n)), where n is the number of bits in +** the float mantissa.) +@@ LUA_NUMBER_FMT_N is the format for writing floats with the minimum +** number of digits that ensures tonumber(tostring(number)) == number. +** (That would be LUA_NUMBER_FMT+2.) @@ l_mathop allows the addition of an 'l' or 'f' to all math operations. @@ l_floor takes the floor of a float. @@ lua_str2number converts a decimal numeral to a number. @@ -417,8 +444,6 @@ #define l_floor(x) (l_mathop(floor)(x)) -#define lua_number2str(s,sz,n) \ - l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) /* @@ lua_numbertointeger converts a float number with an integral value @@ -447,6 +472,7 @@ #define LUA_NUMBER_FRMLEN "" #define LUA_NUMBER_FMT "%.7g" +#define LUA_NUMBER_FMT_N "%.9g" #define l_mathop(op) op##f @@ -463,6 +489,7 @@ #define LUA_NUMBER_FRMLEN "L" #define LUA_NUMBER_FMT "%.19Lg" +#define LUA_NUMBER_FMT_N "%.21Lg" #define l_mathop(op) op##l @@ -477,7 +504,8 @@ #define LUAI_UACNUMBER double #define LUA_NUMBER_FRMLEN "" -#define LUA_NUMBER_FMT "%.14g" +#define LUA_NUMBER_FMT "%.15g" +#define LUA_NUMBER_FMT_N "%.17g" #define l_mathop(op) op @@ -722,10 +750,7 @@ @@ LUA_USE_APICHECK turns on several consistency checks on the C API. ** Define it as a help when debugging C code. */ -#if defined(LUA_USE_APICHECK) -#include -#define luai_apicheck(l,e) assert(e) -#endif +/* #define LUA_USE_APICHECK */ /* }================================================================== */ @@ -742,13 +767,13 @@ @@ LUAI_MAXSTACK limits the size of the Lua stack. ** CHANGE it if you need a different limit. This limit is arbitrary; ** its only purpose is to stop Lua from consuming unlimited stack -** space (and to reserve some numbers for pseudo-indices). -** (It must fit into max(size_t)/32 and max(int)/2.) +** space and to reserve some numbers for pseudo-indices. +** (It must fit into max(int)/2.) */ -#if LUAI_IS32INT +#if 1000000 < (INT_MAX / 2) #define LUAI_MAXSTACK 1000000 #else -#define LUAI_MAXSTACK 15000 +#define LUAI_MAXSTACK (INT_MAX / 2u) #endif diff --git a/3rdparty/lua/plainlua/lualib.h b/3rdparty/lua/plainlua/lualib.h index 2625529076a8..068f60ab3b0a 100644 --- a/3rdparty/lua/plainlua/lualib.h +++ b/3rdparty/lua/plainlua/lualib.h @@ -14,39 +14,52 @@ /* version suffix for environment variable names */ #define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR - +#define LUA_GLIBK 1 LUAMOD_API int (luaopen_base) (lua_State *L); +#define LUA_LOADLIBNAME "package" +#define LUA_LOADLIBK (LUA_GLIBK << 1) +LUAMOD_API int (luaopen_package) (lua_State *L); + + #define LUA_COLIBNAME "coroutine" +#define LUA_COLIBK (LUA_LOADLIBK << 1) LUAMOD_API int (luaopen_coroutine) (lua_State *L); -#define LUA_TABLIBNAME "table" -LUAMOD_API int (luaopen_table) (lua_State *L); +#define LUA_DBLIBNAME "debug" +#define LUA_DBLIBK (LUA_COLIBK << 1) +LUAMOD_API int (luaopen_debug) (lua_State *L); #define LUA_IOLIBNAME "io" +#define LUA_IOLIBK (LUA_DBLIBK << 1) LUAMOD_API int (luaopen_io) (lua_State *L); +#define LUA_MATHLIBNAME "math" +#define LUA_MATHLIBK (LUA_IOLIBK << 1) +LUAMOD_API int (luaopen_math) (lua_State *L); + #define LUA_OSLIBNAME "os" +#define LUA_OSLIBK (LUA_MATHLIBK << 1) LUAMOD_API int (luaopen_os) (lua_State *L); #define LUA_STRLIBNAME "string" +#define LUA_STRLIBK (LUA_OSLIBK << 1) LUAMOD_API int (luaopen_string) (lua_State *L); +#define LUA_TABLIBNAME "table" +#define LUA_TABLIBK (LUA_STRLIBK << 1) +LUAMOD_API int (luaopen_table) (lua_State *L); + #define LUA_UTF8LIBNAME "utf8" +#define LUA_UTF8LIBK (LUA_TABLIBK << 1) LUAMOD_API int (luaopen_utf8) (lua_State *L); -#define LUA_MATHLIBNAME "math" -LUAMOD_API int (luaopen_math) (lua_State *L); - -#define LUA_DBLIBNAME "debug" -LUAMOD_API int (luaopen_debug) (lua_State *L); - -#define LUA_LOADLIBNAME "package" -LUAMOD_API int (luaopen_package) (lua_State *L); +/* open selected libraries */ +LUALIB_API void (luaL_openselectedlibs) (lua_State *L, int load, int preload); -/* open all previous libraries */ -LUALIB_API void (luaL_openlibs) (lua_State *L); +/* open all libraries */ +#define luaL_openlibs(L) luaL_openselectedlibs(L, ~0, 0) #endif diff --git a/3rdparty/lua/plainlua/lundump.c b/3rdparty/lua/plainlua/lundump.c index e8d92a8534ff..ade40384266f 100644 --- a/3rdparty/lua/plainlua/lundump.c +++ b/3rdparty/lua/plainlua/lundump.c @@ -21,6 +21,7 @@ #include "lmem.h" #include "lobject.h" #include "lstring.h" +#include "ltable.h" #include "lundump.h" #include "lzio.h" @@ -34,6 +35,10 @@ typedef struct { lua_State *L; ZIO *Z; const char *name; + Table *h; /* list for string reuse */ + size_t offset; /* current position relative to beginning of dump */ + lua_Unsigned nstr; /* number of strings in the list */ + lu_byte fixed; /* dump is fixed in memory */ } LoadState; @@ -47,11 +52,33 @@ static l_noret error (LoadState *S, const char *why) { ** All high-level loads go through loadVector; you can change it to ** adapt to the endianness of the input */ -#define loadVector(S,b,n) loadBlock(S,b,(n)*sizeof((b)[0])) +#define loadVector(S,b,n) loadBlock(S,b,cast_sizet(n)*sizeof((b)[0])) static void loadBlock (LoadState *S, void *b, size_t size) { if (luaZ_read(S->Z, b, size) != 0) error(S, "truncated chunk"); + S->offset += size; +} + + +static void loadAlign (LoadState *S, unsigned align) { + unsigned padding = align - cast_uint(S->offset % align); + if (padding < align) { /* (padding == align) means no padding */ + lua_Integer paddingContent; + loadBlock(S, &paddingContent, padding); + lua_assert(S->offset % align == 0); + } +} + + +#define getaddr(S,n,t) cast(t *, getaddr_(S,cast_sizet(n) * sizeof(t))) + +static const void *getaddr_ (LoadState *S, size_t size) { + const void *block = luaZ_getaddr(S->Z, size); + S->offset += size; + if (block == NULL) + error(S, "truncated fixed buffer"); + return block; } @@ -62,34 +89,36 @@ static lu_byte loadByte (LoadState *S) { int b = zgetc(S->Z); if (b == EOZ) error(S, "truncated chunk"); + S->offset++; return cast_byte(b); } -static size_t loadUnsigned (LoadState *S, size_t limit) { - size_t x = 0; +static lua_Unsigned loadVarint (LoadState *S, lua_Unsigned limit) { + lua_Unsigned x = 0; int b; limit >>= 7; do { b = loadByte(S); - if (x >= limit) + if (x > limit) error(S, "integer overflow"); x = (x << 7) | (b & 0x7f); - } while ((b & 0x80) == 0); + } while ((b & 0x80) != 0); return x; } static size_t loadSize (LoadState *S) { - return loadUnsigned(S, MAX_SIZET); + return loadVarint(S, MAX_SIZE); } static int loadInt (LoadState *S) { - return cast_int(loadUnsigned(S, INT_MAX)); + return cast_int(loadVarint(S, cast_sizet(INT_MAX))); } + static lua_Number loadNumber (LoadState *S) { lua_Number x; loadVar(S, x); @@ -98,58 +127,79 @@ static lua_Number loadNumber (LoadState *S) { static lua_Integer loadInteger (LoadState *S) { - lua_Integer x; - loadVar(S, x); - return x; + lua_Unsigned cx = loadVarint(S, LUA_MAXUNSIGNED); + /* decode unsigned to signed */ + if ((cx & 1) != 0) + return l_castU2S(~(cx >> 1)); + else + return l_castU2S(cx >> 1); } /* -** Load a nullable string into prototype 'p'. +** Load a nullable string into slot 'sl' from prototype 'p'. The +** assignment to the slot and the barrier must be performed before any +** possible GC activity, to anchor the string. (Both 'loadVector' and +** 'luaH_setint' can call the GC.) */ -static TString *loadStringN (LoadState *S, Proto *p) { +static void loadString (LoadState *S, Proto *p, TString **sl) { lua_State *L = S->L; TString *ts; + TValue sv; size_t size = loadSize(S); - if (size == 0) /* no string? */ - return NULL; - else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ - char buff[LUAI_MAXSHORTLEN]; - loadVector(S, buff, size); /* load string into buffer */ - ts = luaS_newlstr(L, buff, size); /* create string */ + if (size == 0) { /* no string? */ + lua_assert(*sl == NULL); /* must be prefilled */ + return; } - else { /* long string */ - ts = luaS_createlngstrobj(L, size); /* create string */ - setsvalue2s(L, L->top.p, ts); /* anchor it ('loadVector' can GC) */ - luaD_inctop(L); - loadVector(S, getlngstr(ts), size); /* load directly in final place */ - L->top.p--; /* pop string */ + else if (size == 1) { /* previously saved string? */ + lua_Unsigned idx = loadVarint(S, LUA_MAXUNSIGNED); /* get its index */ + TValue stv; + if (novariant(luaH_getint(S->h, l_castU2S(idx), &stv)) != LUA_TSTRING) + error(S, "invalid string index"); + *sl = ts = tsvalue(&stv); /* get its value */ + luaC_objbarrier(L, p, ts); + return; /* do not save it again */ } - luaC_objbarrier(L, p, ts); - return ts; -} - - -/* -** Load a non-nullable string into prototype 'p'. -*/ -static TString *loadString (LoadState *S, Proto *p) { - TString *st = loadStringN(S, p); - if (st == NULL) - error(S, "bad format for constant string"); - return st; + else if ((size -= 2) <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN + 1]; /* extra space for '\0' */ + loadVector(S, buff, size + 1); /* load string into buffer */ + *sl = ts = luaS_newlstr(L, buff, size); /* create string */ + luaC_objbarrier(L, p, ts); + } + else if (S->fixed) { /* for a fixed buffer, use a fixed string */ + const char *s = getaddr(S, size + 1, char); /* get content address */ + *sl = ts = luaS_newextlstr(L, s, size, NULL, NULL); + luaC_objbarrier(L, p, ts); + } + else { /* create internal copy */ + *sl = ts = luaS_createlngstrobj(L, size); /* create string */ + luaC_objbarrier(L, p, ts); + loadVector(S, getlngstr(ts), size + 1); /* load directly in final place */ + } + /* add string to list of saved strings */ + S->nstr++; + setsvalue(L, &sv, ts); + luaH_setint(L, S->h, l_castU2S(S->nstr), &sv); + luaC_objbarrierback(L, obj2gco(S->h), ts); } static void loadCode (LoadState *S, Proto *f) { int n = loadInt(S); - f->code = luaM_newvectorchecked(S->L, n, Instruction); - f->sizecode = n; - loadVector(S, f->code, n); + loadAlign(S, sizeof(f->code[0])); + if (S->fixed) { + f->code = getaddr(S, n, Instruction); + f->sizecode = n; + } + else { + f->code = luaM_newvectorchecked(S->L, n, Instruction); + f->sizecode = n; + loadVector(S, f->code, n); + } } -static void loadFunction(LoadState *S, Proto *f, TString *psource); +static void loadFunction(LoadState *S, Proto *f); static void loadConstants (LoadState *S, Proto *f) { @@ -179,10 +229,16 @@ static void loadConstants (LoadState *S, Proto *f) { setivalue(o, loadInteger(S)); break; case LUA_VSHRSTR: - case LUA_VLNGSTR: - setsvalue2n(S->L, o, loadString(S, f)); + case LUA_VLNGSTR: { + lua_assert(f->source == NULL); + loadString(S, f, &f->source); /* use 'source' to anchor string */ + if (f->source == NULL) + error(S, "bad format for constant string"); + setsvalue2n(S->L, o, f->source); /* save it in the right place */ + f->source = NULL; break; - default: lua_assert(0); + } + default: error(S, "invalid constant"); } } } @@ -198,7 +254,7 @@ static void loadProtos (LoadState *S, Proto *f) { for (i = 0; i < n; i++) { f->p[i] = luaF_newproto(S->L); luaC_objbarrier(S->L, f, f->p[i]); - loadFunction(S, f->p[i], f->source); + loadFunction(S, f->p[i]); } } @@ -210,8 +266,8 @@ static void loadProtos (LoadState *S, Proto *f) { ** in that case all prototypes must be consistent for the GC. */ static void loadUpvalues (LoadState *S, Proto *f) { - int i, n; - n = loadInt(S); + int i; + int n = loadInt(S); f->upvalues = luaM_newvectorchecked(S->L, n, Upvaldesc); f->sizeupvalues = n; for (i = 0; i < n; i++) /* make array valid for GC */ @@ -225,17 +281,29 @@ static void loadUpvalues (LoadState *S, Proto *f) { static void loadDebug (LoadState *S, Proto *f) { - int i, n; - n = loadInt(S); - f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); - f->sizelineinfo = n; - loadVector(S, f->lineinfo, n); + int i; + int n = loadInt(S); + if (S->fixed) { + f->lineinfo = getaddr(S, n, ls_byte); + f->sizelineinfo = n; + } + else { + f->lineinfo = luaM_newvectorchecked(S->L, n, ls_byte); + f->sizelineinfo = n; + loadVector(S, f->lineinfo, n); + } n = loadInt(S); - f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); - f->sizeabslineinfo = n; - for (i = 0; i < n; i++) { - f->abslineinfo[i].pc = loadInt(S); - f->abslineinfo[i].line = loadInt(S); + if (n > 0) { + loadAlign(S, sizeof(int)); + if (S->fixed) { + f->abslineinfo = getaddr(S, n, AbsLineInfo); + f->sizeabslineinfo = n; + } + else { + f->abslineinfo = luaM_newvectorchecked(S->L, n, AbsLineInfo); + f->sizeabslineinfo = n; + loadVector(S, f->abslineinfo, n); + } } n = loadInt(S); f->locvars = luaM_newvectorchecked(S->L, n, LocVar); @@ -243,7 +311,7 @@ static void loadDebug (LoadState *S, Proto *f) { for (i = 0; i < n; i++) f->locvars[i].varname = NULL; for (i = 0; i < n; i++) { - f->locvars[i].varname = loadStringN(S, f); + loadString(S, f, &f->locvars[i].varname); f->locvars[i].startpc = loadInt(S); f->locvars[i].endpc = loadInt(S); } @@ -251,23 +319,23 @@ static void loadDebug (LoadState *S, Proto *f) { if (n != 0) /* does it have debug information? */ n = f->sizeupvalues; /* must be this many */ for (i = 0; i < n; i++) - f->upvalues[i].name = loadStringN(S, f); + loadString(S, f, &f->upvalues[i].name); } -static void loadFunction (LoadState *S, Proto *f, TString *psource) { - f->source = loadStringN(S, f); - if (f->source == NULL) /* no source in dump? */ - f->source = psource; /* reuse parent's source */ +static void loadFunction (LoadState *S, Proto *f) { f->linedefined = loadInt(S); f->lastlinedefined = loadInt(S); f->numparams = loadByte(S); - f->is_vararg = loadByte(S); + f->flag = loadByte(S) & PF_ISVARARG; /* get only the meaningful flags */ + if (S->fixed) + f->flag |= PF_FIXED; /* signal that code is fixed */ f->maxstacksize = loadByte(S); loadCode(S, f); loadConstants(S, f); loadUpvalues(S, f); loadProtos(S, f); + loadString(S, f, &f->source); loadDebug(S, f); } @@ -281,13 +349,29 @@ static void checkliteral (LoadState *S, const char *s, const char *msg) { } -static void fchecksize (LoadState *S, size_t size, const char *tname) { - if (loadByte(S) != size) - error(S, luaO_pushfstring(S->L, "%s size mismatch", tname)); +static l_noret numerror (LoadState *S, const char *what, const char *tname) { + const char *msg = luaO_pushfstring(S->L, "%s %s mismatch", tname, what); + error(S, msg); +} + + +static void checknumsize (LoadState *S, int size, const char *tname) { + if (size != loadByte(S)) + numerror(S, "size", tname); +} + + +static void checknumformat (LoadState *S, int eq, const char *tname) { + if (!eq) + numerror(S, "format", tname); } -#define checksize(S,t) fchecksize(S,sizeof(t),#t) +#define checknum(S,tvar,value,tname) \ + { tvar i; checknumsize(S, sizeof(i), tname); \ + loadVar(S, i); \ + checknumformat(S, i == value, tname); } + static void checkHeader (LoadState *S) { /* skip 1st char (already read and checked) */ @@ -297,39 +381,43 @@ static void checkHeader (LoadState *S) { if (loadByte(S) != LUAC_FORMAT) error(S, "format mismatch"); checkliteral(S, LUAC_DATA, "corrupted chunk"); - checksize(S, Instruction); - checksize(S, lua_Integer); - checksize(S, lua_Number); - if (loadInteger(S) != LUAC_INT) - error(S, "integer format mismatch"); - if (loadNumber(S) != LUAC_NUM) - error(S, "float format mismatch"); + checknum(S, int, LUAC_INT, "int"); + checknum(S, Instruction, LUAC_INST, "instruction"); + checknum(S, lua_Integer, LUAC_INT, "Lua integer"); + checknum(S, lua_Number, LUAC_NUM, "Lua number"); } /* ** Load precompiled chunk. */ -LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { +LClosure *luaU_undump (lua_State *L, ZIO *Z, const char *name, int fixed) { LoadState S; LClosure *cl; if (*name == '@' || *name == '=') - S.name = name + 1; + name = name + 1; else if (*name == LUA_SIGNATURE[0]) - S.name = "binary string"; - else - S.name = name; + name = "binary string"; + S.name = name; S.L = L; S.Z = Z; + S.fixed = cast_byte(fixed); + S.offset = 1; /* fist byte was already read */ checkHeader(&S); cl = luaF_newLclosure(L, loadByte(&S)); setclLvalue2s(L, L->top.p, cl); luaD_inctop(L); + S.h = luaH_new(L); /* create list of saved strings */ + S.nstr = 0; + sethvalue2s(L, L->top.p, S.h); /* anchor it */ + luaD_inctop(L); cl->p = luaF_newproto(L); luaC_objbarrier(L, cl, cl->p); - loadFunction(&S, cl->p, NULL); - lua_assert(cl->nupvalues == cl->p->sizeupvalues); + loadFunction(&S, cl->p); + if (cl->nupvalues != cl->p->sizeupvalues) + error(&S, "corrupted chunk"); luai_verifycode(L, cl->p); + L->top.p--; /* pop table */ return cl; } diff --git a/3rdparty/lua/plainlua/lundump.h b/3rdparty/lua/plainlua/lundump.h index a97676ca1852..c4e06f9ebda6 100644 --- a/3rdparty/lua/plainlua/lundump.h +++ b/3rdparty/lua/plainlua/lundump.h @@ -7,6 +7,8 @@ #ifndef lundump_h #define lundump_h +#include + #include "llimits.h" #include "lobject.h" #include "lzio.h" @@ -15,18 +17,21 @@ /* data to catch conversion errors */ #define LUAC_DATA "\x19\x93\r\n\x1a\n" -#define LUAC_INT 0x5678 -#define LUAC_NUM cast_num(370.5) +#define LUAC_INT -0x5678 +#define LUAC_INST 0x12345678 +#define LUAC_NUM cast_num(-370.5) /* ** Encode major-minor version in one byte, one nibble for each */ -#define LUAC_VERSION (((LUA_VERSION_NUM / 100) * 16) + LUA_VERSION_NUM % 100) +#define LUAC_VERSION (LUA_VERSION_MAJOR_N*16+LUA_VERSION_MINOR_N) #define LUAC_FORMAT 0 /* this is the official format */ + /* load one chunk; from lundump.c */ -LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); +LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name, + int fixed); /* dump one chunk; from ldump.c */ LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, diff --git a/3rdparty/lua/plainlua/lutf8lib.c b/3rdparty/lua/plainlua/lutf8lib.c index 3a5b9bc38a5b..4c9784e09337 100644 --- a/3rdparty/lua/plainlua/lutf8lib.c +++ b/3rdparty/lua/plainlua/lutf8lib.c @@ -19,6 +19,7 @@ #include "lauxlib.h" #include "lualib.h" +#include "llimits.h" #define MAXUNICODE 0x10FFFFu @@ -28,15 +29,6 @@ #define MSGInvalid "invalid UTF-8 code" -/* -** Integer type for decoded UTF-8 values; MAXUTF needs 31 bits. -*/ -#if (UINT_MAX >> 30) >= 1 -typedef unsigned int utfint; -#else -typedef unsigned long utfint; -#endif - #define iscont(c) (((c) & 0xC0) == 0x80) #define iscontp(p) iscont(*(p)) @@ -58,11 +50,11 @@ static lua_Integer u_posrelat (lua_Integer pos, size_t len) { ** entry forces an error for non-ascii bytes with no continuation ** bytes (count == 0). */ -static const char *utf8_decode (const char *s, utfint *val, int strict) { - static const utfint limits[] = - {~(utfint)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; +static const char *utf8_decode (const char *s, l_uint32 *val, int strict) { + static const l_uint32 limits[] = + {~(l_uint32)0, 0x80, 0x800, 0x10000u, 0x200000u, 0x4000000u}; unsigned int c = (unsigned char)s[0]; - utfint res = 0; /* final result */ + l_uint32 res = 0; /* final result */ if (c < 0x80) /* ascii? */ res = c; else { @@ -73,7 +65,7 @@ static const char *utf8_decode (const char *s, utfint *val, int strict) { return NULL; /* invalid byte sequence */ res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ } - res |= ((utfint)(c & 0x7F) << (count * 5)); /* add first byte */ + res |= ((l_uint32)(c & 0x7F) << (count * 5)); /* add first byte */ if (count > 5 || res > MAXUTF || res < limits[count]) return NULL; /* invalid byte sequence */ s += count; /* skip continuation bytes read */ @@ -111,7 +103,7 @@ static int utflen (lua_State *L) { lua_pushinteger(L, posi + 1); /* ... and current position */ return 2; } - posi = s1 - s; + posi = ct_diff2S(s1 - s); n++; } lua_pushinteger(L, n); @@ -141,11 +133,11 @@ static int codepoint (lua_State *L) { n = 0; /* count the number of returns */ se = s + pose; /* string end */ for (s += posi - 1; s < se;) { - utfint code; + l_uint32 code; s = utf8_decode(s, &code, !lax); if (s == NULL) return luaL_error(L, MSGInvalid); - lua_pushinteger(L, code); + lua_pushinteger(L, l_castU2S(code)); n++; } return n; @@ -181,14 +173,14 @@ static int utfchar (lua_State *L) { /* -** offset(s, n, [i]) -> index where n-th character counting from -** position 'i' starts; 0 means character at 'i'. +** offset(s, n, [i]) -> indices where n-th character counting from +** position 'i' starts and ends; 0 means character at 'i'. */ static int byteoffset (lua_State *L) { size_t len; const char *s = luaL_checklstring(L, 1, &len); lua_Integer n = luaL_checkinteger(L, 2); - lua_Integer posi = (n >= 0) ? 1 : len + 1; + lua_Integer posi = (n >= 0) ? 1 : cast_st2S(len) + 1; posi = u_posrelat(luaL_optinteger(L, 3, posi), len); luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, "position out of bounds"); @@ -200,28 +192,36 @@ static int byteoffset (lua_State *L) { if (iscontp(s + posi)) return luaL_error(L, "initial position is a continuation byte"); if (n < 0) { - while (n < 0 && posi > 0) { /* move back */ - do { /* find beginning of previous character */ - posi--; - } while (posi > 0 && iscontp(s + posi)); - n++; - } - } - else { - n--; /* do not move for 1st character */ - while (n > 0 && posi < (lua_Integer)len) { - do { /* find beginning of next character */ - posi++; - } while (iscontp(s + posi)); /* (cannot pass final '\0') */ - n--; - } - } + while (n < 0 && posi > 0) { /* move back */ + do { /* find beginning of previous character */ + posi--; + } while (posi > 0 && iscontp(s + posi)); + n++; + } + } + else { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) { + do { /* find beginning of next character */ + posi++; + } while (iscontp(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } } - if (n == 0) /* did it find given character? */ - lua_pushinteger(L, posi + 1); - else /* no such character */ + if (n != 0) { /* did not find given character? */ luaL_pushfail(L); - return 1; + return 1; + } + lua_pushinteger(L, posi + 1); /* initial position */ + if ((s[posi] & 0x80) != 0) { /* multi-byte character? */ + do { + posi++; + } while (iscontp(s + posi + 1)); /* skip to final byte */ + } + /* else one-byte character: final position is the initial one */ + lua_pushinteger(L, posi + 1); /* 'posi' now is the final position */ + return 2; } @@ -235,12 +235,12 @@ static int iter_aux (lua_State *L, int strict) { if (n >= len) /* (also handles original 'n' being negative) */ return 0; /* no more codepoints */ else { - utfint code; + l_uint32 code; const char *next = utf8_decode(s + n, &code, strict); if (next == NULL || iscontp(next)) return luaL_error(L, MSGInvalid); - lua_pushinteger(L, n + 1); - lua_pushinteger(L, code); + lua_pushinteger(L, l_castU2S(n + 1)); + lua_pushinteger(L, l_castU2S(code)); return 2; } } diff --git a/3rdparty/lua/plainlua/lvm.c b/3rdparty/lua/plainlua/lvm.c index 7023a04da8dc..97dfe5ee624a 100644 --- a/3rdparty/lua/plainlua/lvm.c +++ b/3rdparty/lua/plainlua/lvm.c @@ -18,6 +18,7 @@ #include "lua.h" +#include "lapi.h" #include "ldebug.h" #include "ldo.h" #include "lfunc.h" @@ -93,7 +94,9 @@ static int l_strton (const TValue *obj, TValue *result) { return 0; else { TString *st = tsvalue(obj); - return (luaO_str2num(getstr(st), result) == tsslen(st) + 1); + size_t stlen; + const char *s = getlstr(st, stlen); + return (luaO_str2num(s, result) == stlen + 1); } } @@ -124,8 +127,8 @@ int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode) { lua_Number f = l_floor(n); if (n != f) { /* not an integral value? */ if (mode == F2Ieq) return 0; /* fails if mode demands integral value */ - else if (mode == F2Iceil) /* needs ceil? */ - f += 1; /* convert floor to ceil (remember: n != f) */ + else if (mode == F2Iceil) /* needs ceiling? */ + f += 1; /* convert floor to ceiling (remember: n != f) */ } return lua_numbertointeger(f, p); } @@ -198,12 +201,15 @@ static int forlimit (lua_State *L, lua_Integer init, const TValue *lim, /* ** Prepare a numerical for loop (opcode OP_FORPREP). +** Before execution, stack is as follows: +** ra : initial value +** ra + 1 : limit +** ra + 2 : step ** Return true to skip the loop. Otherwise, ** after preparation, stack will be as follows: -** ra : internal index (safe copy of the control variable) -** ra + 1 : loop counter (integer loops) or limit (float loops) -** ra + 2 : step -** ra + 3 : control variable +** ra : loop counter (integer loops) or limit (float loops) +** ra + 1 : step +** ra + 2 : control variable */ static int forprep (lua_State *L, StkId ra) { TValue *pinit = s2v(ra); @@ -215,7 +221,6 @@ static int forprep (lua_State *L, StkId ra) { lua_Integer limit; if (step == 0) luaG_runerror(L, "'for' step is zero"); - setivalue(s2v(ra + 3), init); /* control variable */ if (forlimit(L, init, plimit, &limit, step)) return 1; /* skip the loop */ else { /* prepare loop counter */ @@ -230,9 +235,10 @@ static int forprep (lua_State *L, StkId ra) { /* 'step+1' avoids negating 'mininteger' */ count /= l_castS2U(-(step + 1)) + 1u; } - /* store the counter in place of the limit (which won't be - needed anymore) */ - setivalue(plimit, l_castU2S(count)); + /* use 'chgivalue' for places that for sure had integers */ + chgivalue(s2v(ra), l_castU2S(count)); /* change init to count */ + setivalue(s2v(ra + 1), step); /* change limit to step */ + chgivalue(s2v(ra + 2), init); /* change step to init */ } } else { /* try making all values floats */ @@ -249,11 +255,10 @@ static int forprep (lua_State *L, StkId ra) { : luai_numlt(init, limit)) return 1; /* skip the loop */ else { - /* make sure internal values are all floats */ - setfltvalue(plimit, limit); - setfltvalue(pstep, step); - setfltvalue(s2v(ra), init); /* internal index */ - setfltvalue(s2v(ra + 3), init); /* control variable */ + /* make sure all values are floats */ + setfltvalue(s2v(ra), limit); + setfltvalue(s2v(ra + 1), step); + setfltvalue(s2v(ra + 2), init); /* control variable */ } } return 0; @@ -266,14 +271,13 @@ static int forprep (lua_State *L, StkId ra) { ** written online with opcode OP_FORLOOP, for performance.) */ static int floatforloop (StkId ra) { - lua_Number step = fltvalue(s2v(ra + 2)); - lua_Number limit = fltvalue(s2v(ra + 1)); - lua_Number idx = fltvalue(s2v(ra)); /* internal index */ + lua_Number step = fltvalue(s2v(ra + 1)); + lua_Number limit = fltvalue(s2v(ra)); + lua_Number idx = fltvalue(s2v(ra + 2)); /* control variable */ idx = luai_numadd(L, idx, step); /* increment index */ if (luai_numlt(0, step) ? luai_numle(idx, limit) : luai_numle(limit, idx)) { - chgfltvalue(s2v(ra), idx); /* update internal index */ - setfltvalue(s2v(ra + 3), idx); /* and control variable */ + chgfltvalue(s2v(ra + 2), idx); /* update control variable */ return 1; /* jump back */ } else @@ -282,16 +286,14 @@ static int floatforloop (StkId ra) { /* -** Finish the table access 'val = t[key]'. -** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to -** t[k] entry (which must be empty). +** Finish the table access 'val = t[key]' and return the tag of the result. */ -void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, - const TValue *slot) { +lu_byte luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, lu_byte tag) { int loop; /* counter to avoid infinite loops */ const TValue *tm; /* metamethod */ for (loop = 0; loop < MAXTAGLOOP; loop++) { - if (slot == NULL) { /* 't' is not a table? */ + if (tag == LUA_VNOTABLE) { /* 't' is not a table? */ lua_assert(!ttistable(t)); tm = luaT_gettmbyobj(L, t, TM_INDEX); if (l_unlikely(notm(tm))) @@ -299,49 +301,48 @@ void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, /* else will try the metamethod */ } else { /* 't' is a table */ - lua_assert(isempty(slot)); tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ if (tm == NULL) { /* no metamethod? */ setnilvalue(s2v(val)); /* result is nil */ - return; + return LUA_VNIL; } /* else will try the metamethod */ } if (ttisfunction(tm)) { /* is metamethod a function? */ - luaT_callTMres(L, tm, t, key, val); /* call it */ - return; + tag = luaT_callTMres(L, tm, t, key, val); /* call it */ + return tag; /* return tag of the result */ } t = tm; /* else try to access 'tm[key]' */ - if (luaV_fastget(L, t, key, slot, luaH_get)) { /* fast track? */ - setobj2s(L, val, slot); /* done */ - return; - } + luaV_fastget(t, key, s2v(val), luaH_get, tag); + if (!tagisempty(tag)) + return tag; /* done */ /* else repeat (tail call 'luaV_finishget') */ } luaG_runerror(L, "'__index' chain too long; possible loop"); + return 0; /* to avoid warnings */ } /* ** Finish a table assignment 't[key] = val'. -** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points -** to the entry 't[key]', or to a value with an absent key if there -** is no such entry. (The value at 'slot' must be empty, otherwise -** 'luaV_fastget' would have done the job.) +** About anchoring the table before the call to 'luaH_finishset': +** This call may trigger an emergency collection. When loop>0, +** the table being accessed is a field in some metatable. If this +** metatable is weak and the table is not anchored, this collection +** could collect that table while it is being updated. */ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - TValue *val, const TValue *slot) { + TValue *val, int hres) { int loop; /* counter to avoid infinite loops */ for (loop = 0; loop < MAXTAGLOOP; loop++) { const TValue *tm; /* '__newindex' metamethod */ - if (slot != NULL) { /* is 't' a table? */ + if (hres != HNOTATABLE) { /* is 't' a table? */ Table *h = hvalue(t); /* save 't' table */ - lua_assert(isempty(slot)); /* slot must be empty */ tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ if (tm == NULL) { /* no metamethod? */ sethvalue2s(L, L->top.p, h); /* anchor 't' */ L->top.p++; /* assume EXTRA_STACK */ - luaH_finishset(L, h, key, slot, val); /* set new value */ + luaH_finishset(L, h, key, val, hres); /* set new value */ L->top.p--; invalidateTMcache(h); luaC_barrierback(L, obj2gco(h), val); @@ -360,8 +361,9 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, return; } t = tm; /* else repeat assignment over 'tm' */ - if (luaV_fastget(L, t, key, slot, luaH_get)) { - luaV_finishfastset(L, t, slot, val); + luaV_fastset(t, key, val, hres, luaH_pset); + if (hres == HOK) { + luaV_finishfastset(L, t, val); return; /* done */ } /* else 'return luaV_finishset(L, t, key, val, slot)' (loop) */ @@ -379,10 +381,10 @@ void luaV_finishset (lua_State *L, const TValue *t, TValue *key, ** have different lengths. */ static int l_strcmp (const TString *ts1, const TString *ts2) { - const char *s1 = getstr(ts1); - size_t rl1 = tsslen(ts1); /* real length */ - const char *s2 = getstr(ts2); - size_t rl2 = tsslen(ts2); + size_t rl1; /* real length */ + const char *s1 = getlstr(ts1, rl1); + size_t rl2; + const char *s2 = getlstr(ts2, rl2); for (;;) { /* for each segment */ int temp = strcoll(s1, s2); if (temp != 0) /* not equal? */ @@ -615,8 +617,8 @@ int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { if (tm == NULL) /* no TM? */ return 0; /* objects are different */ else { - luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ - return !l_isfalse(s2v(L->top.p)); + int tag = luaT_callTMres(L, tm, t1, t2, L->top.p); /* call TM */ + return !tagisfalse(tag); } } @@ -632,8 +634,9 @@ static void copy2buff (StkId top, int n, char *buff) { size_t tl = 0; /* size already copied */ do { TString *st = tsvalue(s2v(top - n)); - size_t l = tsslen(st); /* length of string being copied */ - memcpy(buff + tl, getstr(st), l * sizeof(char)); + size_t l; /* length of string being copied */ + const char *s = getlstr(st, l); + memcpy(buff + tl, s, l * sizeof(char)); tl += l; } while (--n > 0); } @@ -697,7 +700,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { Table *h = hvalue(rb); tm = fasttm(L, h->metatable, TM_LEN); if (tm) break; /* metamethod? break switch to call it */ - setivalue(s2v(ra), luaH_getn(h)); /* else primitive len */ + setivalue(s2v(ra), l_castU2S(luaH_getn(h))); /* else primitive len */ return; } case LUA_VSHRSTR: { @@ -705,7 +708,7 @@ void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { return; } case LUA_VLNGSTR: { - setivalue(s2v(ra), tsvalue(rb)->u.lnglen); + setivalue(s2v(ra), cast_st2S(tsvalue(rb)->u.lnglen)); return; } default: { /* try metamethod */ @@ -771,7 +774,7 @@ lua_Number luaV_modf (lua_State *L, lua_Number m, lua_Number n) { /* number of bits in an integer */ -#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) +#define NBITS l_numbits(lua_Integer) /* @@ -922,7 +925,7 @@ void luaV_finishOp (lua_State *L) { /* ** Auxiliary function for arithmetic operations over floats and others -** with two register operands. +** with two operands. */ #define op_arithf_aux(L,v1,v2,fop) { \ lua_Number n1; lua_Number n2; \ @@ -1130,6 +1133,14 @@ void luaV_finishOp (lua_State *L) { */ #define halfProtect(exp) (savestate(L,ci), (exp)) +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + /* 'c' is the limit of live values in the stack */ #define checkGC(L,c) \ { luaC_condGC(L, (savepc(L), L->top.p = (c)), \ @@ -1174,13 +1185,17 @@ void luaV_execute (lua_State *L, CallInfo *ci) { Instruction i; /* instruction being executed */ vmfetch(); #if 0 - /* low-level line tracing for debugging Lua */ - printf("line: %d\n", luaG_getfuncline(cl->p, pcRel(pc, cl->p))); + { /* low-level line tracing for debugging Lua */ + #include "lopnames.h" + int pcrel = pcRel(pc, cl->p); + printf("line: %d; %s (%d)\n", luaG_getfuncline(cl->p, pcrel), + opnames[GET_OPCODE(i)], pcrel); + } #endif lua_assert(base == ci->func.p + 1); lua_assert(base <= L->top.p && L->top.p <= L->stack_last.p); - /* invalidate top for instructions not expecting it */ - lua_assert(isIT(i) || (cast_void(L->top.p = base), 1)); + /* for tests, invalidate top for instructions not expecting it */ + lua_assert(luaP_isIT(i) || (cast_void(L->top.p = base), 1)); vmdispatch (GET_OPCODE(i)) { vmcase(OP_MOVE) { StkId ra = RA(i); @@ -1251,126 +1266,123 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_GETTABUP) { StkId ra = RA(i); - const TValue *slot; TValue *upval = cl->upvals[GETARG_B(i)]->v.p; TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a short string */ - if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, upval, rc, ra, slot)); + lu_byte tag; + luaV_fastget(upval, key, s2v(ra), luaH_getshortstr, tag); + if (tagisempty(tag)) + Protect(luaV_finishget(L, upval, rc, ra, tag)); vmbreak; } vmcase(OP_GETTABLE) { StkId ra = RA(i); - const TValue *slot; TValue *rb = vRB(i); TValue *rc = vRC(i); - lua_Unsigned n; - if (ttisinteger(rc) /* fast track for integers? */ - ? (cast_void(n = ivalue(rc)), luaV_fastgeti(L, rb, n, slot)) - : luaV_fastget(L, rb, rc, slot, luaH_get)) { - setobj2s(L, ra, slot); + lu_byte tag; + if (ttisinteger(rc)) { /* fast track for integers? */ + luaV_fastgeti(rb, ivalue(rc), s2v(ra), tag); } else - Protect(luaV_finishget(L, rb, rc, ra, slot)); + luaV_fastget(rb, rc, s2v(ra), luaH_get, tag); + if (tagisempty(tag)) + Protect(luaV_finishget(L, rb, rc, ra, tag)); vmbreak; } vmcase(OP_GETI) { StkId ra = RA(i); - const TValue *slot; TValue *rb = vRB(i); int c = GETARG_C(i); - if (luaV_fastgeti(L, rb, c, slot)) { - setobj2s(L, ra, slot); - } - else { + lu_byte tag; + luaV_fastgeti(rb, c, s2v(ra), tag); + if (tagisempty(tag)) { TValue key; setivalue(&key, c); - Protect(luaV_finishget(L, rb, &key, ra, slot)); + Protect(luaV_finishget(L, rb, &key, ra, tag)); } vmbreak; } vmcase(OP_GETFIELD) { StkId ra = RA(i); - const TValue *slot; TValue *rb = vRB(i); TValue *rc = KC(i); TString *key = tsvalue(rc); /* key must be a short string */ - if (luaV_fastget(L, rb, key, slot, luaH_getshortstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, rb, rc, ra, slot)); + lu_byte tag; + luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, tag); + if (tagisempty(tag)) + Protect(luaV_finishget(L, rb, rc, ra, tag)); vmbreak; } vmcase(OP_SETTABUP) { - const TValue *slot; + int hres; TValue *upval = cl->upvals[GETARG_A(i)]->v.p; TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a short string */ - if (luaV_fastget(L, upval, key, slot, luaH_getshortstr)) { - luaV_finishfastset(L, upval, slot, rc); - } + luaV_fastset(upval, key, rc, hres, luaH_psetshortstr); + if (hres == HOK) + luaV_finishfastset(L, upval, rc); else - Protect(luaV_finishset(L, upval, rb, rc, slot)); + Protect(luaV_finishset(L, upval, rb, rc, hres)); vmbreak; } vmcase(OP_SETTABLE) { StkId ra = RA(i); - const TValue *slot; + int hres; TValue *rb = vRB(i); /* key (table is in 'ra') */ TValue *rc = RKC(i); /* value */ - lua_Unsigned n; - if (ttisinteger(rb) /* fast track for integers? */ - ? (cast_void(n = ivalue(rb)), luaV_fastgeti(L, s2v(ra), n, slot)) - : luaV_fastget(L, s2v(ra), rb, slot, luaH_get)) { - luaV_finishfastset(L, s2v(ra), slot, rc); + if (ttisinteger(rb)) { /* fast track for integers? */ + luaV_fastseti(s2v(ra), ivalue(rb), rc, hres); } + else { + luaV_fastset(s2v(ra), rb, rc, hres, luaH_pset); + } + if (hres == HOK) + luaV_finishfastset(L, s2v(ra), rc); else - Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); + Protect(luaV_finishset(L, s2v(ra), rb, rc, hres)); vmbreak; } vmcase(OP_SETI) { StkId ra = RA(i); - const TValue *slot; - int c = GETARG_B(i); + int hres; + int b = GETARG_B(i); TValue *rc = RKC(i); - if (luaV_fastgeti(L, s2v(ra), c, slot)) { - luaV_finishfastset(L, s2v(ra), slot, rc); - } + luaV_fastseti(s2v(ra), b, rc, hres); + if (hres == HOK) + luaV_finishfastset(L, s2v(ra), rc); else { TValue key; - setivalue(&key, c); - Protect(luaV_finishset(L, s2v(ra), &key, rc, slot)); + setivalue(&key, b); + Protect(luaV_finishset(L, s2v(ra), &key, rc, hres)); } vmbreak; } vmcase(OP_SETFIELD) { StkId ra = RA(i); - const TValue *slot; + int hres; TValue *rb = KB(i); TValue *rc = RKC(i); TString *key = tsvalue(rb); /* key must be a short string */ - if (luaV_fastget(L, s2v(ra), key, slot, luaH_getshortstr)) { - luaV_finishfastset(L, s2v(ra), slot, rc); - } + luaV_fastset(s2v(ra), key, rc, hres, luaH_psetshortstr); + if (hres == HOK) + luaV_finishfastset(L, s2v(ra), rc); else - Protect(luaV_finishset(L, s2v(ra), rb, rc, slot)); + Protect(luaV_finishset(L, s2v(ra), rb, rc, hres)); vmbreak; } vmcase(OP_NEWTABLE) { StkId ra = RA(i); - int b = GETARG_B(i); /* log2(hash size) + 1 */ - int c = GETARG_C(i); /* array size */ + unsigned b = cast_uint(GETARG_vB(i)); /* log2(hash size) + 1 */ + unsigned c = cast_uint(GETARG_vC(i)); /* array size */ Table *t; if (b > 0) - b = 1 << (b - 1); /* size is 2^(b - 1) */ - lua_assert((!TESTARG_k(i)) == (GETARG_Ax(*pc) == 0)); - if (TESTARG_k(i)) /* non-zero extra argument? */ - c += GETARG_Ax(*pc) * (MAXARG_C + 1); /* add it to size */ + b = 1u << (b - 1); /* hash size is 2^(b - 1) */ + if (TESTARG_k(i)) { /* non-zero extra argument? */ + lua_assert(GETARG_Ax(*pc) != 0); + /* add it to array size */ + c += cast_uint(GETARG_Ax(*pc)) * (MAXARG_vC + 1); + } pc++; /* skip extra argument */ L->top.p = ra + 1; /* correct top in case of emergency GC */ t = luaH_new(L); /* memory allocation */ @@ -1382,16 +1394,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_SELF) { StkId ra = RA(i); - const TValue *slot; + lu_byte tag; TValue *rb = vRB(i); - TValue *rc = RKC(i); - TString *key = tsvalue(rc); /* key must be a string */ + TValue *rc = KC(i); + TString *key = tsvalue(rc); /* key must be a short string */ setobj2s(L, ra + 1, rb); - if (luaV_fastget(L, rb, key, slot, luaH_getstr)) { - setobj2s(L, ra, slot); - } - else - Protect(luaV_finishget(L, rb, rc, ra, slot)); + luaV_fastget(rb, key, s2v(ra), luaH_getshortstr, tag); + if (tagisempty(tag)) + Protect(luaV_finishget(L, rb, rc, ra, tag)); vmbreak; } vmcase(OP_ADDI) { @@ -1590,6 +1600,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_CLOSE) { StkId ra = RA(i); + lua_assert(!GETARG_B(i)); /* 'close must be alive */ Protect(luaF_close(L, ra, LUA_OK, 1)); vmbreak; } @@ -1747,10 +1758,10 @@ void luaV_execute (lua_State *L, CallInfo *ci) { trap = 1; } else { /* do the 'poscall' here */ - int nres; + int nres = get_nresults(ci->callstatus); L->ci = ci->previous; /* back to caller */ L->top.p = base - 1; - for (nres = ci->nresults; l_unlikely(nres > 0); nres--) + for (; l_unlikely(nres > 0); nres--) setnilvalue(s2v(L->top.p++)); /* all results are nil */ } goto ret; @@ -1764,7 +1775,7 @@ void luaV_execute (lua_State *L, CallInfo *ci) { trap = 1; } else { /* do the 'poscall' here */ - int nres = ci->nresults; + int nres = get_nresults(ci->callstatus); L->ci = ci->previous; /* back to caller */ if (nres == 0) L->top.p = base - 1; /* asked for no results */ @@ -1786,15 +1797,14 @@ void luaV_execute (lua_State *L, CallInfo *ci) { } vmcase(OP_FORLOOP) { StkId ra = RA(i); - if (ttisinteger(s2v(ra + 2))) { /* integer loop? */ - lua_Unsigned count = l_castS2U(ivalue(s2v(ra + 1))); + if (ttisinteger(s2v(ra + 1))) { /* integer loop? */ + lua_Unsigned count = l_castS2U(ivalue(s2v(ra))); if (count > 0) { /* still more iterations? */ - lua_Integer step = ivalue(s2v(ra + 2)); - lua_Integer idx = ivalue(s2v(ra)); /* internal index */ - chgivalue(s2v(ra + 1), count - 1); /* update counter */ + lua_Integer step = ivalue(s2v(ra + 1)); + lua_Integer idx = ivalue(s2v(ra + 2)); /* control variable */ + chgivalue(s2v(ra), l_castU2S(count - 1)); /* update counter */ idx = intop(+, idx, step); /* add step to index */ - chgivalue(s2v(ra), idx); /* update internal index */ - setivalue(s2v(ra + 3), idx); /* and control variable */ + chgivalue(s2v(ra + 2), idx); /* update control variable */ pc -= GETARG_Bx(i); /* jump back */ } } @@ -1811,26 +1821,38 @@ void luaV_execute (lua_State *L, CallInfo *ci) { vmbreak; } vmcase(OP_TFORPREP) { + /* before: 'ra' has the iterator function, 'ra + 1' has the state, + 'ra + 2' has the initial value for the control variable, and + 'ra + 3' has the closing variable. This opcode then swaps the + control and the closing variables and marks the closing variable + as to-be-closed. + */ StkId ra = RA(i); - /* create to-be-closed upvalue (if needed) */ - halfProtect(luaF_newtbcupval(L, ra + 3)); - pc += GETARG_Bx(i); - i = *(pc++); /* go to next instruction */ + TValue temp; /* to swap control and closing variables */ + setobj(L, &temp, s2v(ra + 3)); + setobjs2s(L, ra + 3, ra + 2); + setobj2s(L, ra + 2, &temp); + /* create to-be-closed upvalue (if closing var. is not nil) */ + halfProtect(luaF_newtbcupval(L, ra + 2)); + pc += GETARG_Bx(i); /* go to end of the loop */ + i = *(pc++); /* fetch next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORCALL && ra == RA(i)); goto l_tforcall; } vmcase(OP_TFORCALL) { l_tforcall: { - StkId ra = RA(i); /* 'ra' has the iterator function, 'ra + 1' has the state, - 'ra + 2' has the control variable, and 'ra + 3' has the - to-be-closed variable. The call will use the stack after - these values (starting at 'ra + 4') + 'ra + 2' has the closing variable, and 'ra + 3' has the control + variable. The call will use the stack starting at 'ra + 3', + so that it preserves the first three values, and the first + return will be the new value for the control variable. */ - /* push function, state, and control variable */ - memcpy(ra + 4, ra, 3 * sizeof(*ra)); - L->top.p = ra + 4 + 3; - ProtectNT(luaD_call(L, ra + 4, GETARG_C(i))); /* do the call */ + StkId ra = RA(i); + setobjs2s(L, ra + 5, ra + 3); /* copy the control variable */ + setobjs2s(L, ra + 4, ra + 1); /* copy state */ + setobjs2s(L, ra + 3, ra); /* copy function */ + L->top.p = ra + 3 + 3; + ProtectNT(luaD_call(L, ra + 3, GETARG_C(i))); /* do the call */ updatestack(ci); /* stack may have changed */ i = *(pc++); /* go to next instruction */ lua_assert(GET_OPCODE(i) == OP_TFORLOOP && ra == RA(i)); @@ -1839,31 +1861,33 @@ void luaV_execute (lua_State *L, CallInfo *ci) { vmcase(OP_TFORLOOP) { l_tforloop: { StkId ra = RA(i); - if (!ttisnil(s2v(ra + 4))) { /* continue loop? */ - setobjs2s(L, ra + 2, ra + 4); /* save control variable */ + if (!ttisnil(s2v(ra + 3))) /* continue loop? */ pc -= GETARG_Bx(i); /* jump back */ - } vmbreak; }} vmcase(OP_SETLIST) { StkId ra = RA(i); - int n = GETARG_B(i); - unsigned int last = GETARG_C(i); + unsigned n = cast_uint(GETARG_vB(i)); + unsigned int last = cast_uint(GETARG_vC(i)); Table *h = hvalue(s2v(ra)); if (n == 0) - n = cast_int(L->top.p - ra) - 1; /* get up to the top */ + n = cast_uint(L->top.p - ra) - 1; /* get up to the top */ else L->top.p = ci->top.p; /* correct top in case of emergency GC */ last += n; if (TESTARG_k(i)) { - last += GETARG_Ax(*pc) * (MAXARG_C + 1); + last += cast_uint(GETARG_Ax(*pc)) * (MAXARG_vC + 1); pc++; } - if (last > luaH_realasize(h)) /* needs more space? */ + /* when 'n' is known, table should have proper size */ + if (last > h->asize) { /* needs more space? */ + /* fixed-size sets should have space preallocated */ + lua_assert(GETARG_vB(i) == 0); luaH_resizearray(L, h, last); /* preallocate it at once */ + } for (; n > 0; n--) { TValue *val = s2v(ra + n); - setobj2t(L, &h->array[last - 1], val); + obj2arr(h, last - 1, val); last--; luaC_barrierback(L, obj2gco(h), val); } diff --git a/3rdparty/lua/plainlua/lvm.h b/3rdparty/lua/plainlua/lvm.h index dba1ad277025..be7b9cb0ea81 100644 --- a/3rdparty/lua/plainlua/lvm.h +++ b/3rdparty/lua/plainlua/lvm.h @@ -43,7 +43,7 @@ typedef enum { F2Ieq, /* no rounding; accepts only integral values */ F2Ifloor, /* takes the floor of the number */ - F2Iceil /* takes the ceil of the number */ + F2Iceil /* takes the ceiling of the number */ } F2Imod; @@ -76,38 +76,33 @@ typedef enum { /* -** fast track for 'gettable': if 't' is a table and 't[k]' is present, -** return 1 with 'slot' pointing to 't[k]' (position of final result). -** Otherwise, return 0 (meaning it will have to check metamethod) -** with 'slot' pointing to an empty 't[k]' (if 't' is a table) or NULL -** (otherwise). 'f' is the raw get function to use. +** fast track for 'gettable' */ -#define luaV_fastget(L,t,k,slot,f) \ - (!ttistable(t) \ - ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ - : (slot = f(hvalue(t), k), /* else, do raw access */ \ - !isempty(slot))) /* result not empty? */ +#define luaV_fastget(t,k,res,f, tag) \ + (tag = (!ttistable(t) ? LUA_VNOTABLE : f(hvalue(t), k, res))) /* ** Special case of 'luaV_fastget' for integers, inlining the fast case ** of 'luaH_getint'. */ -#define luaV_fastgeti(L,t,k,slot) \ - (!ttistable(t) \ - ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ - : (slot = (l_castS2U(k) - 1u < hvalue(t)->alimit) \ - ? &hvalue(t)->array[k - 1] : luaH_getint(hvalue(t), k), \ - !isempty(slot))) /* result not empty? */ +#define luaV_fastgeti(t,k,res,tag) \ + if (!ttistable(t)) tag = LUA_VNOTABLE; \ + else { luaH_fastgeti(hvalue(t), k, res, tag); } + + +#define luaV_fastset(t,k,val,hres,f) \ + (hres = (!ttistable(t) ? HNOTATABLE : f(hvalue(t), k, val))) + +#define luaV_fastseti(t,k,val,hres) \ + if (!ttistable(t)) hres = HNOTATABLE; \ + else { luaH_fastseti(hvalue(t), k, val, hres); } /* -** Finish a fast set operation (when fast get succeeds). In that case, -** 'slot' points to the place to put the value. +** Finish a fast set operation (when fast set succeeds). */ -#define luaV_finishfastset(L,t,slot,v) \ - { setobj2t(L, cast(TValue *,slot), v); \ - luaC_barrierback(L, gcvalue(t), v); } +#define luaV_finishfastset(L,t,v) luaC_barrierback(L, gcvalue(t), v) /* @@ -125,10 +120,10 @@ LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, F2Imod mode); LUAI_FUNC int luaV_tointegerns (const TValue *obj, lua_Integer *p, F2Imod mode); LUAI_FUNC int luaV_flttointeger (lua_Number n, lua_Integer *p, F2Imod mode); -LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, - StkId val, const TValue *slot); +LUAI_FUNC lu_byte luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, lu_byte tag); LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, - TValue *val, const TValue *slot); + TValue *val, int aux); LUAI_FUNC void luaV_finishOp (lua_State *L); LUAI_FUNC void luaV_execute (lua_State *L, CallInfo *ci); LUAI_FUNC void luaV_concat (lua_State *L, int total); diff --git a/3rdparty/lua/plainlua/lzio.c b/3rdparty/lua/plainlua/lzio.c index cd0a02d5f9b9..301df4b94ecd 100644 --- a/3rdparty/lua/plainlua/lzio.c +++ b/3rdparty/lua/plainlua/lzio.c @@ -14,6 +14,7 @@ #include "lua.h" +#include "lapi.h" #include "llimits.h" #include "lmem.h" #include "lstate.h" @@ -45,17 +46,25 @@ void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { /* --------------------------------------------------------------- read --- */ + +static int checkbuffer (ZIO *z) { + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return 0; /* no more input */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + return 1; /* now buffer has something */ +} + + size_t luaZ_read (ZIO *z, void *b, size_t n) { while (n) { size_t m; - if (z->n == 0) { /* no bytes in buffer? */ - if (luaZ_fill(z) == EOZ) /* try to read more */ - return n; /* no more input; return number of missing bytes */ - else { - z->n++; /* luaZ_fill consumed first byte; put it back */ - z->p--; - } - } + if (!checkbuffer(z)) + return n; /* no more input; return number of missing bytes */ m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ memcpy(b, z->p, m); z->n -= m; @@ -66,3 +75,15 @@ size_t luaZ_read (ZIO *z, void *b, size_t n) { return 0; } + +const void *luaZ_getaddr (ZIO* z, size_t n) { + const void *res; + if (!checkbuffer(z)) + return NULL; /* no more input */ + if (z->n < n) /* not enough bytes? */ + return NULL; /* block not whole; cannot give an address */ + res = z->p; /* get block address */ + z->n -= n; /* consume these bytes */ + z->p += n; + return res; +} diff --git a/3rdparty/lua/plainlua/lzio.h b/3rdparty/lua/plainlua/lzio.h index 38f397fd284e..49047c98cb9f 100644 --- a/3rdparty/lua/plainlua/lzio.h +++ b/3rdparty/lua/plainlua/lzio.h @@ -32,7 +32,7 @@ typedef struct Mbuffer { #define luaZ_sizebuffer(buff) ((buff)->buffsize) #define luaZ_bufflen(buff) ((buff)->n) -#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) +#define luaZ_buffremove(buff,i) ((buff)->n -= cast_sizet(i)) #define luaZ_resetbuffer(buff) ((buff)->n = 0) @@ -48,6 +48,7 @@ LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ +LUAI_FUNC const void *luaZ_getaddr (ZIO* z, size_t n); /* --------- Private Part ------------------ */ diff --git a/3rdparty/lua/sol/sol.hpp b/3rdparty/lua/sol/sol.hpp index 615334c1477f..4ff339378b12 100644 --- a/3rdparty/lua/sol/sol.hpp +++ b/3rdparty/lua/sol/sol.hpp @@ -3535,11 +3535,11 @@ COMPAT53_API void luaL_requiref(lua_State *L, const char *modname, #endif /* Lua 5.2 only */ /* other Lua versions */ -#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 504 +#if !defined(LUA_VERSION_NUM) || LUA_VERSION_NUM < 501 || LUA_VERSION_NUM > 505 -# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, or 5.4)" +# error "unsupported Lua version (i.e. not Lua 5.1, 5.2, 5.3, 5.4 or 5.5)" -#endif /* other Lua versions except 5.1, 5.2, 5.3, and 5.4 */ +#endif /* other Lua versions except 5.1, 5.2, 5.3, 5.4, 5.5 */ /* helper macro for defining continuation functions (for every version * *except* Lua 5.2) */ @@ -4419,16 +4419,16 @@ extern "C" { } #endif -#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM == 504 +#if defined(LUA_VERSION_NUM) && LUA_VERSION_NUM >= 504 #if !defined(LUA_ERRGCMM) -/* So Lua 5.4 actually removes this, which breaks sol2... +/* So Lua 5.4 or later actually removes this, which breaks sol2... man, this API is quite unstable...! */ # define LUA_ERRGCMM (LUA_ERRERR + 2) #endif /* LUA_ERRGCMM define */ -#endif // Lua 5.4 only +#endif // Lua 5.4 or later #endif // NOT_KEPLER_PROJECT_COMPAT54_H_// end of sol/compatibility/compat-5.4.h @@ -28234,6 +28234,12 @@ namespace sol { // end of sol/thread.hpp +#if LUA_VERSION_NUM >= 505 +# define sol_lua_newstate(f, ud) lua_newstate(f, ud, 0) +#else +# define sol_lua_newstate(f, ud) lua_newstate(f, ud) +#endif + namespace sol { class state : private std::unique_ptr, public state_view { @@ -28246,7 +28252,7 @@ namespace sol { } state(lua_CFunction panic, lua_Alloc alfunc, void* alpointer = nullptr) - : unique_base(lua_newstate(alfunc, alpointer)), state_view(unique_base::get()) { + : unique_base(sol_lua_newstate(alfunc, alpointer)), state_view(unique_base::get()) { set_default_state(unique_base::get(), panic); } diff --git a/3rdparty/openal/CMakeLists.txt b/3rdparty/openal/CMakeLists.txt index e50863b8116b..61a13e488563 100644 --- a/3rdparty/openal/CMakeLists.txt +++ b/3rdparty/openal/CMakeLists.txt @@ -75,12 +75,12 @@ if(NOT CMAKE_DEBUG_POSTFIX) FORCE) endif() -set(DEFAULT_TARGET_PROPS +set(ALSOFT_STD_VERSION_PROPS # Require C++17. CXX_STANDARD 17 CXX_STANDARD_REQUIRED TRUE - # Prefer C11, but support C99 and earlier when possible. - C_STANDARD 11) + # Prefer C17, but support earlier when necessary. + C_STANDARD 17) set(CMAKE_MODULE_PATH "${OpenAL_SOURCE_DIR}/cmake") @@ -93,13 +93,13 @@ include(CheckCCompilerFlag) include(CheckCXXCompilerFlag) include(CheckCSourceCompiles) include(CheckCXXSourceCompiles) +include(CheckLinkerFlag) include(CheckStructHasMember) include(CMakePackageConfigHelpers) include(GNUInstallDirs) find_package(PkgConfig) -find_package(SDL2 QUIET) - +find_package(SDL3 QUIET) option(ALSOFT_DLOPEN "Check for the dlopen API for loading optional libs" ON) @@ -144,6 +144,24 @@ if(DEFINED ALSOFT_AMBDEC_PRESETS) message(WARNING "ALSOFT_AMBDEC_PRESETS is deprecated. Use ALSOFT_INSTALL_AMBDEC_PRESETS instead") endif() +if(MSVC) + option(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) + if(FORCE_STATIC_VCRT) + foreach(flag_var + CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE + CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO + CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE + CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) + if(${flag_var} MATCHES "/MD") + string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") + endif() + endforeach(flag_var) + endif() +endif() + +# Axmol MODIFY BEGIN +# add_subdirectory(fmt-11.1.1 EXCLUDE_FROM_ALL) +# Axmol MODIFY END set(CPP_DEFS ) # C pre-processor, not C++ set(INC_PATHS ) @@ -163,6 +181,21 @@ if(WIN32) if(MINGW) option(ALSOFT_BUILD_IMPORT_LIB "Build an import .lib using dlltool (requires sed)" ON) endif() + + if(NOT ALSOFT_UWP) + # Some systems may need NTDDI_VERSION defined to NTDDI_VISTA or later + check_c_source_compiles("#define INITGUID + #include + #include + int main() + { + SHGetKnownFolderPath(&FOLDERID_RoamingAppData, KF_FLAG_DONT_UNEXPAND, NULL, NULL); + return 0; + }" HAVE_SHGETKNOWNFOLDERPATH_NO_NTDDI) + if(NOT HAVE_SHGETKNOWNFOLDERPATH_NO_NTDDI) + set(CPP_DEFS ${CPP_DEFS} NTDDI_VERSION=NTDDI_VISTA) + endif() + endif() elseif(APPLE) option(ALSOFT_OSX_FRAMEWORK "Build as macOS framework" OFF) endif() @@ -181,8 +214,8 @@ if(NOT LIBTYPE) endif() set(LIB_MAJOR_VERSION "1") -set(LIB_MINOR_VERSION "23") -set(LIB_REVISION "1") +set(LIB_MINOR_VERSION "24") +set(LIB_REVISION "3") set(LIB_VERSION "${LIB_MAJOR_VERSION}.${LIB_MINOR_VERSION}.${LIB_REVISION}") set(LIB_VERSION_NUM ${LIB_MAJOR_VERSION},${LIB_MINOR_VERSION},${LIB_REVISION},0) @@ -203,31 +236,6 @@ if(NOT HAVE_STDC_FORMAT_MACROS) set(CPP_DEFS ${CPP_DEFS} __STDC_FORMAT_MACROS) endif() -if(NOT WIN32) - # Check if _POSIX_C_SOURCE and _XOPEN_SOURCE needs to be set for POSIX functions - check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN_DEFAULT) - if(NOT HAVE_POSIX_MEMALIGN_DEFAULT) - set(OLD_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS}) - set(CMAKE_REQUIRED_FLAGS "${CMAKE_REQUIRED_FLAGS} -D_POSIX_C_SOURCE=200112L -D_XOPEN_SOURCE=600") - check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN_POSIX) - if(NOT HAVE_POSIX_MEMALIGN_POSIX) - set(CMAKE_REQUIRED_FLAGS ${OLD_REQUIRED_FLAGS}) - else() - set(CPP_DEFS ${CPP_DEFS} _POSIX_C_SOURCE=200112L _XOPEN_SOURCE=600) - endif() - endif() - unset(OLD_REQUIRED_FLAGS) -endif() - -# C99 has restrict, but C++ does not, so we can only utilize __restrict. -check_cxx_source_compiles("int *__restrict foo; -int main() { return 0; }" HAVE___RESTRICT) -if(HAVE___RESTRICT) - set(CPP_DEFS ${CPP_DEFS} RESTRICT=__restrict) -else() - set(CPP_DEFS ${CPP_DEFS} "RESTRICT=") -endif() - # Some systems may need libatomic for atomic functions to work set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES} atomic) @@ -252,12 +260,18 @@ if(ANDROID) endif() if(MSVC) - set(CPP_DEFS ${CPP_DEFS} _CRT_SECURE_NO_WARNINGS) + # NOTE: _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR is temporary. When building on + # VS 2022 17.10 or newer, but using an older runtime, mutexes can crash + # when locked. Ideally the runtime should be updated on the system, but + # until the update becomes more widespread, this helps avoid some pain + # points. + set(CPP_DEFS ${CPP_DEFS} _CRT_SECURE_NO_WARNINGS _DISABLE_CONSTEXPR_MUTEX_CONSTRUCTOR) check_cxx_compiler_flag(/permissive- HAVE_PERMISSIVE_SWITCH) if(HAVE_PERMISSIVE_SWITCH) set(C_FLAGS ${C_FLAGS} $<$:/permissive->) endif() - set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030 /wd5051) + set(C_FLAGS ${C_FLAGS} /W4 /w14640 /wd4065 /wd4127 /wd4268 /wd4324 /wd5030 /wd5051 + $<$:/EHsc> /utf-8) if(NOT DXSDK_DIR) string(REGEX REPLACE "\\\\" "/" DXSDK_DIR "$ENV{DXSDK_DIR}") @@ -267,19 +281,6 @@ if(MSVC) if(DXSDK_DIR) message(STATUS "Using DirectX SDK directory: ${DXSDK_DIR}") endif() - - option(FORCE_STATIC_VCRT "Force /MT for static VC runtimes" OFF) - if(FORCE_STATIC_VCRT) - foreach(flag_var - CMAKE_C_FLAGS CMAKE_C_FLAGS_DEBUG CMAKE_C_FLAGS_RELEASE - CMAKE_C_FLAGS_MINSIZEREL CMAKE_C_FLAGS_RELWITHDEBINFO - CMAKE_CXX_FLAGS CMAKE_CXX_FLAGS_DEBUG CMAKE_CXX_FLAGS_RELEASE - CMAKE_CXX_FLAGS_MINSIZEREL CMAKE_CXX_FLAGS_RELWITHDEBINFO) - if(${flag_var} MATCHES "/MD") - string(REGEX REPLACE "/MD" "/MT" ${flag_var} "${${flag_var}}") - endif() - endforeach(flag_var) - endif() else() set(C_FLAGS ${C_FLAGS} -Winline -Wunused -Wall -Wextra -Wshadow -Wconversion -Wcast-align -Wpedantic @@ -295,9 +296,25 @@ else() endif() endif() + check_cxx_compiler_flag(-Wno-interference-size HAVE_WNO_INTERFERENCE_SIZE) + if(HAVE_WNO_INTERFERENCE_SIZE) + set(C_FLAGS ${C_FLAGS} $<$:-Wno-interference-size>) + endif() + + # Axmol MODIFY BEGIN if(ALSOFT_WERROR) set(C_FLAGS ${C_FLAGS} -Werror) endif() + # Axmol MODIFY END + + # NOTE: This essentially provides the equivalent of the C++26 feature to + # initialize all local variables with a non-0 bit pattern. Until C++26 is + # adopted, the [[gnu::uninitialized]] attribute will avoid the auto- + # initialization where necessary. + check_c_compiler_flag(-ftrivial-auto-var-init=pattern HAVE_FTRIVIAL_AUTO_VAR_INIT) + if(HAVE_FTRIVIAL_AUTO_VAR_INIT) + set(C_FLAGS ${C_FLAGS} -ftrivial-auto-var-init=pattern) + endif() check_c_compiler_flag(-fno-math-errno HAVE_FNO_MATH_ERRNO) if(HAVE_FNO_MATH_ERRNO) @@ -321,7 +338,7 @@ else() option(ALSOFT_STATIC_STDCXX "Static link libstdc++" OFF) if(ALSOFT_STATIC_STDCXX) set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--push-state,-Bstatic,-lstdc++,--pop-state") + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-static-libstdc++") check_cxx_source_compiles("int main() { }" HAVE_STATIC_LIBSTDCXX_SWITCH) set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES}) unset(OLD_REQUIRED_LIBRARIES) @@ -329,14 +346,14 @@ else() if(NOT HAVE_STATIC_LIBSTDCXX_SWITCH) message(FATAL_ERROR "Cannot static link libstdc++") endif() - set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,--push-state,-Bstatic,-lstdc++,--pop-state") + set(LINKER_FLAGS ${LINKER_FLAGS} "-static-libstdc++") endif() if(WIN32) option(ALSOFT_STATIC_WINPTHREAD "Static link libwinpthread" OFF) if(ALSOFT_STATIC_WINPTHREAD) set(OLD_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) - set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--push-state,-Bstatic,-lwinpthread,--pop-state") + set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} "-Wl,--push-state,-Bstatic,-lstdc++,-lwinpthread,--pop-state") check_cxx_source_compiles("int main() { }" HAVE_STATIC_LIBWINPTHREAD_SWITCH) set(CMAKE_REQUIRED_LIBRARIES ${OLD_REQUIRED_LIBRARIES}) unset(OLD_REQUIRED_LIBRARIES) @@ -344,7 +361,7 @@ else() if(NOT HAVE_STATIC_LIBWINPTHREAD_SWITCH) message(FATAL_ERROR "Cannot static link libwinpthread") endif() - set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,--push-state,-Bstatic,-lwinpthread,--pop-state") + set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,--push-state,-Bstatic,-lstdc++,-lwinpthread,--pop-state") endif() endif() endif() @@ -412,7 +429,7 @@ if(ALSOFT_CPUEXT_SSE AND HAVE_XMMINTRIN_H) set(HAVE_SSE 1) endif() if(ALSOFT_REQUIRE_SSE AND NOT HAVE_SSE) - message(FATAL_ERROR "Failed to enabled required SSE CPU extensions") + message(FATAL_ERROR "Failed to enable required SSE CPU extensions") endif() option(ALSOFT_CPUEXT_SSE2 "Enable SSE2 support" ON) @@ -457,7 +474,7 @@ if(ALSOFT_CPUEXT_NEON AND HAVE_ARM_NEON_H) endif() endif() if(ALSOFT_REQUIRE_NEON AND NOT HAVE_NEON) - message(FATAL_ERROR "Failed to enabled required ARM NEON CPU extensions") + message(FATAL_ERROR "Failed to enable required ARM NEON CPU extensions") endif() @@ -504,13 +521,9 @@ if(HAVE_SSE2) endif() -check_include_file(malloc.h HAVE_MALLOC_H) check_include_file(cpuid.h HAVE_CPUID_H) check_include_file(intrin.h HAVE_INTRIN_H) check_include_file(guiddef.h HAVE_GUIDDEF_H) -if(NOT HAVE_GUIDDEF_H) - check_include_file(initguid.h HAVE_INITGUID_H) -endif() # Some systems need libm for some math functions to work set(MATH_LIB ) @@ -557,8 +570,6 @@ if(HAVE_INTRIN_H) }" HAVE_CPUID_INTRINSIC) endif() -check_symbol_exists(posix_memalign stdlib.h HAVE_POSIX_MEMALIGN) -check_symbol_exists(_aligned_malloc malloc.h HAVE__ALIGNED_MALLOC) check_symbol_exists(proc_pidpath libproc.h HAVE_PROC_PIDPATH) if(NOT WIN32) @@ -593,19 +604,15 @@ if(NOT WIN32) endif() endif() -check_symbol_exists(getopt unistd.h HAVE_GETOPT) - # Common sources used by both the OpenAL implementation library, the OpenAL # router, and certain tools and examples. set(COMMON_OBJS + common/alassert.cpp + common/alassert.h common/albit.h common/alcomplex.cpp common/alcomplex.h - common/aldeque.h - common/alfstream.cpp - common/alfstream.h - common/almalloc.cpp common/almalloc.h common/alnumbers.h common/alnumeric.h @@ -616,13 +623,19 @@ set(COMMON_OBJS common/alstring.h common/althrd_setname.cpp common/althrd_setname.h + common/althreads.h common/altraits.h common/atomic.h common/comptr.h common/dynload.cpp common/dynload.h + common/filesystem.cpp + common/filesystem.h + common/flexarray.h common/intrusive_ptr.h common/opthelpers.h + common/pffft.cpp + common/pffft.h common/phase_shifter.h common/polyphase_resampler.cpp common/polyphase_resampler.h @@ -675,7 +688,6 @@ set(CORE_OBJS core/filters/nfc.h core/filters/splitter.cpp core/filters/splitter.h - core/fmt_traits.cpp core/fmt_traits.h core/fpu_ctrl.cpp core/fpu_ctrl.h @@ -691,6 +703,8 @@ set(CORE_OBJS core/mixer.cpp core/mixer.h core/resampler_limits.h + core/storage_formats.cpp + core/storage_formats.h core/uhjfilter.cpp core/uhjfilter.h core/uiddefs.cpp @@ -723,21 +737,21 @@ if(NOT WIN32) else() set(EXTRA_LIBS ${EXTRA_LIBS} ${DBus1_LIBRARIES}) endif() + else() + set(MISSING_VARS "") + if(NOT DBus1_INCLUDE_DIRS) + set(MISSING_VARS "${MISSING_VARS} DBus1_INCLUDE_DIRS") + endif() + if(NOT DBus1_LIBRARIES) + set(MISSING_VARS "${MISSING_VARS} DBus1_LIBRARIES") + endif() + message(STATUS "Could NOT find DBus1 (missing:${MISSING_VARS})") + unset(MISSING_VARS) endif() - else() - set(MISSING_VARS "") - if(NOT DBus1_INCLUDE_DIRS) - set(MISSING_VARS "${MISSING_VARS} DBus1_INCLUDE_DIRS") - endif() - if(NOT DBus1_LIBRARIES) - set(MISSING_VARS "${MISSING_VARS} DBus1_LIBRARIES") - endif() - message(STATUS "Could NOT find DBus1 (missing:${MISSING_VARS})") - unset(MISSING_VARS) endif() endif() if(ALSOFT_REQUIRE_RTKIT AND NOT HAVE_RTKIT) - message(FATAL_ERROR "Failed to enabled required RTKit support") + message(FATAL_ERROR "Failed to enable required RTKit support") endif() # Default mixers, always available @@ -876,8 +890,10 @@ set(HAVE_PULSEAUDIO 0) set(HAVE_COREAUDIO 0) set(HAVE_OPENSL 0) set(HAVE_OBOE 0) +set(HAVE_OTHERIO 0) set(HAVE_WAVE 0) set(HAVE_SDL2 0) +set(HAVE_SDL3 0) if(WIN32 OR HAVE_DLFCN_H) set(IS_LINKED "") @@ -915,7 +931,7 @@ if(ALSOFT_BACKEND_PIPEWIRE AND PkgConfig_FOUND) endif() endif() if(ALSOFT_REQUIRE_PIPEWIRE AND NOT HAVE_PIPEWIRE) - message(FATAL_ERROR "Failed to enabled required PipeWire backend") + message(FATAL_ERROR "Failed to enable required PipeWire backend") endif() # Check PulseAudio backend @@ -932,7 +948,7 @@ if(ALSOFT_BACKEND_PULSEAUDIO) endif() endif() if(ALSOFT_REQUIRE_PULSEAUDIO AND NOT HAVE_PULSEAUDIO) - message(FATAL_ERROR "Failed to enabled required PulseAudio backend") + message(FATAL_ERROR "Failed to enable required PulseAudio backend") endif() if(NOT WIN32) @@ -979,31 +995,35 @@ if(NOT WIN32) endif() endif() - # Check SndIO backend - option(ALSOFT_BACKEND_SNDIO "Enable SndIO backend" ON) + # Check SndIO backend (disabled by default on non-BSDs) + if(BSD) + option(ALSOFT_BACKEND_SNDIO "Enable SndIO backend" ON) + else() + option(ALSOFT_BACKEND_SNDIO "Enable SndIO backend" OFF) + endif() option(ALSOFT_REQUIRE_SNDIO "Require SndIO backend" OFF) if(ALSOFT_BACKEND_SNDIO) - find_package(SoundIO) - if(SOUNDIO_FOUND) + find_package(SndIO) + if(SNDIO_FOUND) set(HAVE_SNDIO 1) set(BACKENDS "${BACKENDS} SndIO (linked),") - set(ALC_OBJS ${ALC_OBJS} alc/backends/sndio.cpp alc/backends/sndio.h) - set(EXTRA_LIBS ${SOUNDIO_LIBRARIES} ${EXTRA_LIBS}) - set(INC_PATHS ${INC_PATHS} ${SOUNDIO_INCLUDE_DIRS}) + set(ALC_OBJS ${ALC_OBJS} alc/backends/sndio.cpp alc/backends/sndio.hpp) + set(EXTRA_LIBS ${SNDIO_LIBRARIES} ${EXTRA_LIBS}) + set(INC_PATHS ${INC_PATHS} ${SNDIO_INCLUDE_DIRS}) endif() endif() endif() if(ALSOFT_REQUIRE_ALSA AND NOT HAVE_ALSA) - message(FATAL_ERROR "Failed to enabled required ALSA backend") + message(FATAL_ERROR "Failed to enable required ALSA backend") endif() if(ALSOFT_REQUIRE_OSS AND NOT HAVE_OSS) - message(FATAL_ERROR "Failed to enabled required OSS backend") + message(FATAL_ERROR "Failed to enable required OSS backend") endif() if(ALSOFT_REQUIRE_SOLARIS AND NOT HAVE_SOLARIS) - message(FATAL_ERROR "Failed to enabled required Solaris backend") + message(FATAL_ERROR "Failed to enable required Solaris backend") endif() if(ALSOFT_REQUIRE_SNDIO AND NOT HAVE_SNDIO) - message(FATAL_ERROR "Failed to enabled required SndIO backend") + message(FATAL_ERROR "Failed to enable required SndIO backend") endif() # Check Windows-only backends @@ -1054,17 +1074,32 @@ if(WIN32) set(HAVE_WASAPI 1) set(BACKENDS "${BACKENDS} WASAPI,") set(ALC_OBJS ${ALC_OBJS} alc/backends/wasapi.cpp alc/backends/wasapi.h) + + if(NOT ALSOFT_UWP) + set(EXTRA_LIBS avrt ${EXTRA_LIBS}) + endif() endif() endif() + + option(ALSOFT_BACKEND_OTHERIO "Enable OtherIO backend" OFF) + option(ALSOFT_REQUIRE_OTHERIO "Require OtherIO backend" OFF) + if(ALSOFT_BACKEND_OTHERIO) + set(HAVE_OTHERIO 1) + set(BACKENDS "${BACKENDS} OtherIO,") + set(ALC_OBJS ${ALC_OBJS} alc/backends/otherio.cpp alc/backends/otherio.h) + endif() endif() if(ALSOFT_REQUIRE_WINMM AND NOT HAVE_WINMM) - message(FATAL_ERROR "Failed to enabled required WinMM backend") + message(FATAL_ERROR "Failed to enable required WinMM backend") endif() if(ALSOFT_REQUIRE_DSOUND AND NOT HAVE_DSOUND) - message(FATAL_ERROR "Failed to enabled required DSound backend") + message(FATAL_ERROR "Failed to enable required DSound backend") endif() if(ALSOFT_REQUIRE_WASAPI AND NOT HAVE_WASAPI) - message(FATAL_ERROR "Failed to enabled required WASAPI backend") + message(FATAL_ERROR "Failed to enable required WASAPI backend") +endif() +if(ALSOFT_REQUIRE_OTHERIO AND NOT HAVE_OTHERIO) + message(FATAL_ERROR "Failed to enable required OtherIO backend") endif() # Check JACK backend @@ -1081,7 +1116,7 @@ if(ALSOFT_BACKEND_JACK) endif() endif() if(ALSOFT_REQUIRE_JACK AND NOT HAVE_JACK) - message(FATAL_ERROR "Failed to enabled required JACK backend") + message(FATAL_ERROR "Failed to enable required JACK backend") endif() # Check CoreAudio backend @@ -1116,7 +1151,7 @@ if(ALSOFT_BACKEND_COREAUDIO) endif() endif() if(ALSOFT_REQUIRE_COREAUDIO AND NOT HAVE_COREAUDIO) - message(FATAL_ERROR "Failed to enabled required CoreAudio backend") + message(FATAL_ERROR "Failed to enable required CoreAudio backend") endif() # Check for Oboe (Android) backend @@ -1127,7 +1162,7 @@ if(ALSOFT_BACKEND_OBOE) if(ANDROID) set(OBOE_SOURCE "" CACHE STRING "Source directory for Oboe.") if(OBOE_SOURCE) - add_subdirectory(${OBOE_SOURCE} ./oboe) + add_subdirectory(${OBOE_SOURCE} ./oboe EXCLUDE_FROM_ALL) set(OBOE_TARGET oboe) else() find_package(oboe CONFIG) @@ -1148,7 +1183,7 @@ if(ALSOFT_BACKEND_OBOE) endif() endif() if(ALSOFT_REQUIRE_OBOE AND NOT HAVE_OBOE) - message(FATAL_ERROR "Failed to enabled required Oboe backend") + message(FATAL_ERROR "Failed to enable required Oboe backend") endif() # Check for OpenSL (Android) backend @@ -1159,13 +1194,13 @@ if(ALSOFT_BACKEND_OPENSL) if(OPENSL_FOUND) set(HAVE_OPENSL 1) set(ALC_OBJS ${ALC_OBJS} alc/backends/opensl.cpp alc/backends/opensl.h) - set(BACKENDS "${BACKENDS} OpenSL,") - set(EXTRA_LIBS ${OPENSL_LIBRARIES} ${EXTRA_LIBS}) + set(BACKENDS "${BACKENDS} OpenSL${IS_LINKED},") + add_backend_libs(${OPENSL_LIBRARIES}) set(INC_PATHS ${INC_PATHS} ${OPENSL_INCLUDE_DIRS}) endif() endif() if(ALSOFT_REQUIRE_OPENSL AND NOT HAVE_OPENSL) - message(FATAL_ERROR "Failed to enabled required OpenSL backend") + message(FATAL_ERROR "Failed to enable required OpenSL backend") endif() # Check PortAudio backend @@ -1176,20 +1211,38 @@ if(ALSOFT_BACKEND_PORTAUDIO) if(PORTAUDIO_FOUND) set(HAVE_PORTAUDIO 1) set(BACKENDS "${BACKENDS} PortAudio${IS_LINKED},") - set(ALC_OBJS ${ALC_OBJS} alc/backends/portaudio.cpp alc/backends/portaudio.h) + set(ALC_OBJS ${ALC_OBJS} alc/backends/portaudio.cpp alc/backends/portaudio.hpp) add_backend_libs(${PORTAUDIO_LIBRARIES}) set(INC_PATHS ${INC_PATHS} ${PORTAUDIO_INCLUDE_DIRS}) endif() endif() if(ALSOFT_REQUIRE_PORTAUDIO AND NOT HAVE_PORTAUDIO) - message(FATAL_ERROR "Failed to enabled required PortAudio backend") + message(FATAL_ERROR "Failed to enable required PortAudio backend") +endif() + +# Check for SDL2 or SDL3 backend +# Off by default, since it adds a runtime dependency. Additionally, both SDL2 +# and SDL3 can't be enabled simultaneously. +option(ALSOFT_BACKEND_SDL3 "Enable SDL3 backend" OFF) +option(ALSOFT_REQUIRE_SDL3 "Require SDL3 backend" OFF) +if(ALSOFT_BACKEND_SDL3) + if(SDL3_FOUND) + set(HAVE_SDL3 1) + set(ALC_OBJS ${ALC_OBJS} alc/backends/sdl3.cpp alc/backends/sdl3.h) + set(BACKENDS "${BACKENDS} SDL3,") + set(EXTRA_LIBS ${EXTRA_LIBS} SDL3::SDL3) + else() + message(STATUS "Could NOT find SDL3") + endif() +endif() +if(ALSOFT_REQUIRE_SDL3 AND NOT HAVE_SDL3) + message(FATAL_ERROR "Failed to enable required SDL3 backend") endif() -# Check for SDL2 backend -# Off by default, since it adds a runtime dependency option(ALSOFT_BACKEND_SDL2 "Enable SDL2 backend" OFF) option(ALSOFT_REQUIRE_SDL2 "Require SDL2 backend" OFF) -if(ALSOFT_BACKEND_SDL2) +if(ALSOFT_BACKEND_SDL2 AND NOT HAVE_SDL3) + find_package(SDL2) if(SDL2_FOUND) set(HAVE_SDL2 1) set(ALC_OBJS ${ALC_OBJS} alc/backends/sdl2.cpp alc/backends/sdl2.h) @@ -1199,8 +1252,8 @@ if(ALSOFT_BACKEND_SDL2) message(STATUS "Could NOT find SDL2") endif() endif() -if(ALSOFT_REQUIRE_SDL2 AND NOT SDL2_FOUND) - message(FATAL_ERROR "Failed to enabled required SDL2 backend") +if(ALSOFT_REQUIRE_SDL2 AND NOT HAVE_SDL2) + message(FATAL_ERROR "Failed to enable required SDL2 backend") endif() # Optionally enable the Wave Writer backend @@ -1241,7 +1294,7 @@ if(ALSOFT_UPDATE_BUILD_VERSION AND GIT_FOUND AND EXISTS "${OpenAL_SOURCE_DIR}/.g VERBATIM ) - add_custom_target(build_version DEPENDS "${OpenAL_BINARY_DIR}/version_witness.txt") + add_custom_target(alsoft.build_version DEPENDS "${OpenAL_BINARY_DIR}/version_witness.txt") else() set(GIT_BRANCH "UNKNOWN") set(GIT_COMMIT_HASH "unknown") @@ -1270,6 +1323,15 @@ if(ALSOFT_EMBED_HRTF_DATA) make_hrtf_header("Default HRTF.mhr" "default_hrtf") endif() +# Set a 16KB page size for Android +if(ANDROID) + set(CPP_DEFS ${CPP_DEFS} __BIONIC_NO_PAGE_SIZE_MACRO) + check_linker_flag(C "-Wl,-z,max-page-size=16384" HAS_MAX_PAGE_SIZE_16384) + if(HAS_MAX_PAGE_SIZE_16384) + set(LINKER_FLAGS ${LINKER_FLAGS} "-Wl,-z,max-page-size=16384") + endif() +endif() + if(ALSOFT_UTILS) find_package(MySOFA) @@ -1282,9 +1344,9 @@ if(ALSOFT_UTILS) endif() if(ALSOFT_UTILS OR ALSOFT_EXAMPLES) find_package(SndFile) - if(SDL2_FOUND) - find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE) - endif() +endif() +if(ALSOFT_EXAMPLES AND SDL3_FOUND) + find_package(FFmpeg COMPONENTS AVFORMAT AVCODEC AVUTIL SWSCALE SWRESAMPLE) endif() if(NOT WIN32) @@ -1306,12 +1368,14 @@ if(LIBTYPE STREQUAL "STATIC") set(PKG_CONFIG_CFLAGS -DAL_LIBTYPE_STATIC) foreach(FLAG ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) # If this is already a linker flag, or is a full path+file, add it - # as-is. If it's an SDL2 target, add the link flag for it. Otherwise, - # it's a name intended to be dressed as -lname. + # as-is. If it's an SDL2 or SDL3 target, add the link flag for it. + # Otherwise, it's a name intended to be dressed as -lname. if(FLAG MATCHES "^-.*" OR EXISTS "${FLAG}") set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} ${FLAG}") elseif(FLAG MATCHES "^SDL2::SDL2") set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -lSDL2") + elseif(FLAG MATCHES "^SDL3::SDL3") + set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -lSDL3") else() set(PKG_CONFIG_PRIVATE_LIBS "${PKG_CONFIG_PRIVATE_LIBS} -l${FLAG}") endif() @@ -1322,27 +1386,55 @@ endif() configure_file( "${OpenAL_SOURCE_DIR}/config.h.in" "${OpenAL_BINARY_DIR}/config.h") +configure_file( + "${OpenAL_SOURCE_DIR}/config_backends.h.in" + "${OpenAL_BINARY_DIR}/config_backends.h") +configure_file( + "${OpenAL_SOURCE_DIR}/config_simd.h.in" + "${OpenAL_BINARY_DIR}/config_simd.h") configure_file( "${OpenAL_SOURCE_DIR}/openal.pc.in" "${OpenAL_BINARY_DIR}/openal.pc" @ONLY) -add_library(alcommon STATIC EXCLUDE_FROM_ALL ${COMMON_OBJS}) -target_include_directories(alcommon PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/include) -target_compile_definitions(alcommon PRIVATE ${CPP_DEFS}) -target_compile_options(alcommon PRIVATE ${C_FLAGS}) -set_target_properties(alcommon PROPERTIES ${DEFAULT_TARGET_PROPS} POSITION_INDEPENDENT_CODE TRUE) +add_library(alsoft.common STATIC EXCLUDE_FROM_ALL ${COMMON_OBJS}) +target_include_directories(alsoft.common PRIVATE ${OpenAL_SOURCE_DIR}/include + PUBLIC ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/common) +target_compile_definitions(alsoft.common PRIVATE ${CPP_DEFS}) +target_compile_options(alsoft.common PRIVATE ${C_FLAGS}) +# Axmol MODIFY BEGIN +target_link_libraries(alsoft.common PRIVATE fmt::fmt) +# Axmol MODIFY END +set_target_properties(alsoft.common PROPERTIES ${ALSOFT_STD_VERSION_PROPS} + POSITION_INDEPENDENT_CODE TRUE) unset(HAS_ROUTER) set(IMPL_TARGET OpenAL) # Either OpenAL or soft_oal. + +set(NEED_ANALYZE_SOURCE_FILES "") +foreach(obj ${CORE_OBJS} ${OPENAL_OBJS} ${ALC_OBJS} ${COMMON_OBJS}) + IF (NOT ${obj} MATCHES "${CMAKE_BINARY_DIR}/default_hrtf.txt") + list(APPEND NEED_ANALYZE_SOURCE_FILES "${CMAKE_CURRENT_SOURCE_DIR}/${obj}") + endif() +endforeach() +IF (ALSOFT_UTILS) + list(APPEND NEED_ANALYZE_SOURCE_FILES "${CMAKE_SOURCE_DIR}/utils/openal-info.c") +endif() +SET(CLANG_TIDY_EXECUTABLE "clang-tidy") +if(DEFINED ENV{CLANG_TIDY_EXECUTABLE}) + SET(CLANG_TIDY_EXECUTABLE $ENV{CLANG_TIDY_EXECUTABLE}) +endif() +add_custom_target(clang-tidy-check ${CLANG_TIDY_EXECUTABLE} -format-style=file -p ${CMAKE_BINARY_DIR}/compile_commands.json ${NEED_ANALYZE_SOURCE_FILES} DEPENDS ${NEED_ANALYZE_SOURCE_FILES}) + # Build main library if(LIBTYPE STREQUAL "STATIC") add_library(${IMPL_TARGET} STATIC ${COMMON_OBJS} ${OPENAL_OBJS} ${ALC_OBJS} ${CORE_OBJS}) target_compile_definitions(${IMPL_TARGET} PUBLIC AL_LIBTYPE_STATIC) - target_link_libraries(${IMPL_TARGET} PRIVATE ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) + target_link_libraries(${IMPL_TARGET} PRIVATE ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB} + $) if(WIN32) # This option is for static linking OpenAL Soft into another project @@ -1367,7 +1459,7 @@ else() PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES "ALC_API=${EXPORT_DECL}" "AL_API=${EXPORT_DECL}" ${CPP_DEFS}) target_compile_options(OpenAL PRIVATE ${C_FLAGS}) - target_link_libraries(OpenAL PRIVATE alcommon ${LINKER_FLAGS}) + target_link_libraries(OpenAL PRIVATE alsoft.common ${LINKER_FLAGS} fmt::fmt) target_include_directories(OpenAL PUBLIC $ @@ -1376,10 +1468,10 @@ else() ${OpenAL_SOURCE_DIR}/common ${OpenAL_BINARY_DIR} ) - set_target_properties(OpenAL PROPERTIES ${DEFAULT_TARGET_PROPS} PREFIX "" + set_target_properties(OpenAL PROPERTIES ${ALSOFT_STD_VERSION_PROPS} PREFIX "" OUTPUT_NAME ${LIBNAME}) - if(TARGET build_version) - add_dependencies(OpenAL build_version) + if(TARGET alsoft.build_version) + add_dependencies(OpenAL alsoft.build_version) endif() set(HAS_ROUTER 1) @@ -1398,24 +1490,30 @@ else() if(WIN32) set_target_properties(${IMPL_TARGET} PROPERTIES PREFIX "") endif() - target_link_libraries(${IMPL_TARGET} PRIVATE alcommon ${LINKER_FLAGS} ${EXTRA_LIBS} ${MATH_LIB}) + target_link_libraries(${IMPL_TARGET} PRIVATE alsoft.common ${LINKER_FLAGS} ${EXTRA_LIBS} + ${MATH_LIB} fmt::fmt) if(ALSOFT_UWP) - set(ALSOFT_CPPWINRT_VERSION "2.0.230706.1" CACHE STRING "The soft-oal default cppwinrt version") - - find_program(NUGET_EXE NAMES nuget) - if(NOT NUGET_EXE) - message("NUGET.EXE not found.") - message(FATAL_ERROR "Please install this executable, and run CMake again.") - endif() + find_package(cppwinrt CONFIG) + if (TARGET Microsoft::CppWinRT) + target_link_libraries(${IMPL_TARGET} PRIVATE Microsoft::CppWinRT) + else() + set(ALSOFT_CPPWINRT_VERSION "2.0.230706.1" CACHE STRING "The soft-oal default cppwinrt version") + + find_program(NUGET_EXE NAMES nuget) + if(NOT NUGET_EXE) + message("NUGET.EXE not found.") + message(FATAL_ERROR "Please install this executable, and run CMake again.") + endif() - exec_program(${NUGET_EXE} - ARGS install "Microsoft.Windows.CppWinRT" -Version ${ALSOFT_CPPWINRT_VERSION} -ExcludeVersion -OutputDirectory "\"${CMAKE_BINARY_DIR}/packages\"") + exec_program(${NUGET_EXE} + ARGS install "Microsoft.Windows.CppWinRT" -Version ${ALSOFT_CPPWINRT_VERSION} -ExcludeVersion -OutputDirectory "\"${CMAKE_BINARY_DIR}/packages\"") - set_target_properties(${IMPL_TARGET} PROPERTIES - VS_PROJECT_IMPORT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.props - ) - target_link_libraries(${IMPL_TARGET} PRIVATE ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.targets) + set_target_properties(${IMPL_TARGET} PROPERTIES + VS_PROJECT_IMPORT ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.props + ) + target_link_libraries(${IMPL_TARGET} PRIVATE ${CMAKE_BINARY_DIR}/packages/Microsoft.Windows.CppWinRT/build/native/Microsoft.Windows.CppWinRT.targets) + endif() endif() if(NOT WIN32 AND NOT APPLE) @@ -1474,18 +1572,18 @@ target_include_directories(${IMPL_TARGET} ${OpenAL_SOURCE_DIR}/common ) -set_target_properties(${IMPL_TARGET} PROPERTIES ${DEFAULT_TARGET_PROPS} +set_target_properties(${IMPL_TARGET} PROPERTIES ${ALSOFT_STD_VERSION_PROPS} OUTPUT_NAME ${LIBNAME} VERSION ${LIB_VERSION} SOVERSION ${LIB_MAJOR_VERSION} ) target_compile_definitions(${IMPL_TARGET} - PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES "ALC_API=${EXPORT_DECL}" "AL_API=${EXPORT_DECL}" + PRIVATE AL_BUILD_LIBRARY AL_ALEXT_PROTOTYPES "ALC_API=${EXPORT_DECL}" "AL_API=${EXPORT_DECL}" ${CPP_DEFS}) target_compile_options(${IMPL_TARGET} PRIVATE ${C_FLAGS}) -if(TARGET build_version) - add_dependencies(${IMPL_TARGET} build_version) +if(TARGET alsoft.build_version) + add_dependencies(${IMPL_TARGET} alsoft.build_version) endif() if(WIN32 AND MINGW AND ALSOFT_BUILD_IMPORT_LIB AND NOT LIBTYPE STREQUAL "STATIC") @@ -1499,7 +1597,7 @@ if(WIN32 AND MINGW AND ALSOFT_BUILD_IMPORT_LIB AND NOT LIBTYPE STREQUAL "STATIC" message(STATUS "WARNING: Cannot find dlltool, disabling .def/.lib generation") endif() else() - target_link_options(OpenAL PRIVATE "-Wl,--output-def,OpenAL32.def") + target_link_options(OpenAL PRIVATE "-Wl,--output-def,${PROJECT_BINARY_DIR}/OpenAL32.def") add_custom_command(TARGET OpenAL POST_BUILD COMMAND "${SED_EXECUTABLE}" -i -e "s/ @[^ ]*//" OpenAL32.def COMMAND "${CMAKE_DLLTOOL}" -d OpenAL32.def -l OpenAL32.lib -D OpenAL32.dll @@ -1608,7 +1706,7 @@ if(ALSOFT_UTILS) target_include_directories(openal-info PRIVATE ${OpenAL_SOURCE_DIR}/common) target_compile_options(openal-info PRIVATE ${C_FLAGS}) target_link_libraries(openal-info PRIVATE ${LINKER_FLAGS} OpenAL ${UNICODE_FLAG}) - set_target_properties(openal-info PROPERTIES ${DEFAULT_TARGET_PROPS}) + set_target_properties(openal-info PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} openal-info) endif() @@ -1619,30 +1717,31 @@ if(ALSOFT_UTILS) target_include_directories(uhjdecoder PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/common) target_compile_options(uhjdecoder PRIVATE ${C_FLAGS}) - target_link_libraries(uhjdecoder PUBLIC alcommon - PRIVATE ${LINKER_FLAGS} SndFile::SndFile ${UNICODE_FLAG}) - set_target_properties(uhjdecoder PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(uhjdecoder PUBLIC alsoft.common + PRIVATE ${LINKER_FLAGS} SndFile::SndFile ${UNICODE_FLAG} fmt::fmt) + set_target_properties(uhjdecoder PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(uhjencoder utils/uhjencoder.cpp) target_compile_definitions(uhjencoder PRIVATE ${CPP_DEFS}) target_include_directories(uhjencoder PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/common) target_compile_options(uhjencoder PRIVATE ${C_FLAGS}) - target_link_libraries(uhjencoder PUBLIC alcommon - PRIVATE ${LINKER_FLAGS} SndFile::SndFile ${UNICODE_FLAG}) - set_target_properties(uhjencoder PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(uhjencoder PUBLIC alsoft.common + PRIVATE ${LINKER_FLAGS} SndFile::SndFile ${UNICODE_FLAG} fmt::fmt) + set_target_properties(uhjencoder PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) endif() if(MYSOFA_FOUND) set(SOFA_SUPPORT_SRCS utils/sofa-support.cpp utils/sofa-support.h) - add_library(sofa-support STATIC EXCLUDE_FROM_ALL ${SOFA_SUPPORT_SRCS}) - target_compile_definitions(sofa-support PRIVATE ${CPP_DEFS}) - target_include_directories(sofa-support PUBLIC ${OpenAL_SOURCE_DIR}/common) - target_compile_options(sofa-support PRIVATE ${C_FLAGS}) - target_link_libraries(sofa-support PUBLIC alcommon MySOFA::MySOFA PRIVATE ${LINKER_FLAGS}) - set_target_properties(sofa-support PROPERTIES ${DEFAULT_TARGET_PROPS}) + add_library(alsoft.sofa-support STATIC EXCLUDE_FROM_ALL ${SOFA_SUPPORT_SRCS}) + target_compile_definitions(alsoft.sofa-support PRIVATE ${CPP_DEFS}) + target_include_directories(alsoft.sofa-support PUBLIC ${OpenAL_SOURCE_DIR}/common) + target_compile_options(alsoft.sofa-support PRIVATE ${C_FLAGS}) + target_link_libraries(alsoft.sofa-support PUBLIC alsoft.common MySOFA::MySOFA + PRIVATE ${LINKER_FLAGS} fmt::fmt) + set_target_properties(alsoft.sofa-support PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) set(MAKEMHR_SRCS utils/makemhr/loaddef.cpp @@ -1651,16 +1750,14 @@ if(ALSOFT_UTILS) utils/makemhr/loadsofa.h utils/makemhr/makemhr.cpp utils/makemhr/makemhr.h) - if(NOT HAVE_GETOPT) - set(MAKEMHR_SRCS ${MAKEMHR_SRCS} utils/getopt.c utils/getopt.h) - endif() add_executable(makemhr ${MAKEMHR_SRCS}) target_compile_definitions(makemhr PRIVATE ${CPP_DEFS}) target_include_directories(makemhr PRIVATE ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/utils) target_compile_options(makemhr PRIVATE ${C_FLAGS}) - target_link_libraries(makemhr PRIVATE ${LINKER_FLAGS} sofa-support ${UNICODE_FLAG}) - set_target_properties(makemhr PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(makemhr PRIVATE ${LINKER_FLAGS} alsoft.sofa-support ${UNICODE_FLAG} + fmt::fmt) + set_target_properties(makemhr PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} makemhr) endif() @@ -1670,8 +1767,9 @@ if(ALSOFT_UTILS) target_compile_definitions(sofa-info PRIVATE ${CPP_DEFS}) target_include_directories(sofa-info PRIVATE ${OpenAL_SOURCE_DIR}/utils) target_compile_options(sofa-info PRIVATE ${C_FLAGS}) - target_link_libraries(sofa-info PRIVATE ${LINKER_FLAGS} sofa-support ${UNICODE_FLAG}) - set_target_properties(sofa-info PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(sofa-info PRIVATE ${LINKER_FLAGS} alsoft.sofa-support + ${UNICODE_FLAG} fmt::fmt) + set_target_properties(sofa-info PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) endif() message(STATUS "Building utility programs") @@ -1681,93 +1779,113 @@ if(ALSOFT_UTILS) message(STATUS "") endif() - +# Axmol MODIFY BEGIN +if(ALSOFT_EXAMPLES) # Add a static library with common functions used by multiple example targets -add_library(al-excommon STATIC EXCLUDE_FROM_ALL +add_library(alsoft.excommon STATIC EXCLUDE_FROM_ALL examples/common/alhelpers.c examples/common/alhelpers.h) -target_compile_definitions(al-excommon PUBLIC ${CPP_DEFS}) -target_include_directories(al-excommon PUBLIC ${OpenAL_SOURCE_DIR}/common) -target_compile_options(al-excommon PUBLIC ${C_FLAGS}) -target_link_libraries(al-excommon PUBLIC OpenAL PRIVATE ${RT_LIB}) -set_target_properties(al-excommon PROPERTIES ${DEFAULT_TARGET_PROPS}) +target_compile_definitions(alsoft.excommon PUBLIC ${CPP_DEFS}) +target_include_directories(alsoft.excommon PUBLIC ${OpenAL_BINARY_DIR} ${OpenAL_SOURCE_DIR}/common) +target_compile_options(alsoft.excommon PUBLIC ${C_FLAGS}) +target_link_libraries(alsoft.excommon PUBLIC OpenAL PRIVATE ${RT_LIB}) +set_target_properties(alsoft.excommon PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) +endif() +# Axmol MODIFY END if(ALSOFT_EXAMPLES) add_executable(altonegen examples/altonegen.c) - target_link_libraries(altonegen PRIVATE ${LINKER_FLAGS} ${MATH_LIB} al-excommon ${UNICODE_FLAG}) - set_target_properties(altonegen PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(altonegen PRIVATE ${LINKER_FLAGS} ${MATH_LIB} alsoft.excommon + ${UNICODE_FLAG}) + set_target_properties(altonegen PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alrecord examples/alrecord.c) - target_link_libraries(alrecord PRIVATE ${LINKER_FLAGS} al-excommon ${UNICODE_FLAG}) - set_target_properties(alrecord PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(alrecord PRIVATE ${LINKER_FLAGS} alsoft.excommon ${UNICODE_FLAG}) + set_target_properties(alrecord PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) + + add_executable(aldebug examples/aldebug.cpp) + target_link_libraries(aldebug PRIVATE ${LINKER_FLAGS} alsoft.excommon ${UNICODE_FLAG} + fmt::fmt) + set_target_properties(aldebug PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) + + add_executable(allafplay examples/allafplay.cpp) + target_link_libraries(allafplay PRIVATE ${LINKER_FLAGS} alsoft.common alsoft.excommon + ${UNICODE_FLAG} fmt::fmt) + set_target_properties(allafplay PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) - set(EXTRA_INSTALLS ${EXTRA_INSTALLS} altonegen alrecord) + set(EXTRA_INSTALLS ${EXTRA_INSTALLS} altonegen alrecord aldebug allafplay) endif() message(STATUS "Building example programs") if(SNDFILE_FOUND) add_executable(alplay examples/alplay.c) - target_link_libraries(alplay PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon + target_link_libraries(alplay PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${UNICODE_FLAG}) - set_target_properties(alplay PROPERTIES ${DEFAULT_TARGET_PROPS}) + set_target_properties(alplay PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alstream examples/alstream.c) - target_link_libraries(alstream PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon + target_link_libraries(alstream PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${UNICODE_FLAG}) - set_target_properties(alstream PROPERTIES ${DEFAULT_TARGET_PROPS}) + set_target_properties(alstream PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alreverb examples/alreverb.c) - target_link_libraries(alreverb PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon + target_link_libraries(alreverb PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${UNICODE_FLAG}) - set_target_properties(alreverb PROPERTIES ${DEFAULT_TARGET_PROPS}) + set_target_properties(alreverb PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(almultireverb examples/almultireverb.c) target_link_libraries(almultireverb - PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon ${MATH_LIB} ${UNICODE_FLAG}) - set_target_properties(almultireverb PROPERTIES ${DEFAULT_TARGET_PROPS}) + PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${MATH_LIB} ${UNICODE_FLAG}) + set_target_properties(almultireverb PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(allatency examples/allatency.c) - target_link_libraries(allatency PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon + target_link_libraries(allatency PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${UNICODE_FLAG}) - set_target_properties(allatency PROPERTIES ${DEFAULT_TARGET_PROPS}) + set_target_properties(allatency PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alhrtf examples/alhrtf.c) target_link_libraries(alhrtf - PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon ${MATH_LIB} ${UNICODE_FLAG}) - set_target_properties(alhrtf PROPERTIES ${DEFAULT_TARGET_PROPS}) + PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon ${MATH_LIB} ${UNICODE_FLAG}) + set_target_properties(alhrtf PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alstreamcb examples/alstreamcb.cpp) - target_link_libraries(alstreamcb PRIVATE ${LINKER_FLAGS} SndFile::SndFile al-excommon - ${UNICODE_FLAG}) - set_target_properties(alstreamcb PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(alstreamcb PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon + ${UNICODE_FLAG} fmt::fmt) + set_target_properties(alstreamcb PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) + + add_executable(aldirect examples/aldirect.cpp) + target_link_libraries(aldirect PRIVATE ${LINKER_FLAGS} SndFile::SndFile alsoft.excommon + ${UNICODE_FLAG} fmt::fmt) + set_target_properties(aldirect PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) add_executable(alconvolve examples/alconvolve.c) - target_link_libraries(alconvolve PRIVATE ${LINKER_FLAGS} alcommon SndFile::SndFile - al-excommon ${UNICODE_FLAG}) - set_target_properties(alconvolve PROPERTIES ${DEFAULT_TARGET_PROPS}) + target_link_libraries(alconvolve PRIVATE ${LINKER_FLAGS} alsoft.common SndFile::SndFile + alsoft.excommon ${UNICODE_FLAG}) + set_target_properties(alconvolve PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alplay alstream alreverb almultireverb allatency - alhrtf) + alhrtf aldirect) endif() message(STATUS "Building SndFile example programs") endif() - if(SDL2_FOUND) + # Can't safely use SDL3 and SDL2 together + if(SDL3_FOUND AND NOT HAVE_SDL2) + message(STATUS "Building SDL3 example programs") + add_executable(alloopback examples/alloopback.c) target_link_libraries(alloopback - PRIVATE ${LINKER_FLAGS} SDL2::SDL2 al-excommon ${MATH_LIB}) - set_target_properties(alloopback PROPERTIES ${DEFAULT_TARGET_PROPS}) + PRIVATE ${LINKER_FLAGS} SDL3::SDL3 alsoft.excommon ${MATH_LIB}) + set_target_properties(alloopback PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alloopback) endif() - message(STATUS "Building SDL example programs") - set(FFVER_OK FALSE) if(FFMPEG_FOUND) set(FFVER_OK TRUE) @@ -1796,19 +1914,19 @@ if(ALSOFT_EXAMPLES) add_executable(alffplay examples/alffplay.cpp) target_include_directories(alffplay PRIVATE ${FFMPEG_INCLUDE_DIRS}) target_link_libraries(alffplay - PRIVATE ${LINKER_FLAGS} SDL2::SDL2 ${FFMPEG_LIBRARIES} al-excommon) - set_target_properties(alffplay PROPERTIES ${DEFAULT_TARGET_PROPS}) + PRIVATE ${LINKER_FLAGS} SDL3::SDL3 ${FFMPEG_LIBRARIES} alsoft.excommon fmt::fmt) + set_target_properties(alffplay PROPERTIES ${ALSOFT_STD_VERSION_PROPS}) if(ALSOFT_INSTALL_EXAMPLES) set(EXTRA_INSTALLS ${EXTRA_INSTALLS} alffplay) endif() - message(STATUS "Building SDL+FFmpeg example programs") + message(STATUS "Building SDL3+FFmpeg example programs") endif() endif() message(STATUS "") endif() -if (ALSOFT_TESTS) +if(ALSOFT_TESTS) add_subdirectory(tests) endif() diff --git a/3rdparty/openal/ChangeLog b/3rdparty/openal/ChangeLog index e4236f85d224..c3a0ab6b1fbc 100644 --- a/3rdparty/openal/ChangeLog +++ b/3rdparty/openal/ChangeLog @@ -1,3 +1,137 @@ +openal-soft-1.24.3: + + Fixed using as a static library when linked into another project that uses + fmtlib. + + Fixed building with static VC runtimes. + + Fixed building with Windows headers that default to older targets. + + Fixed building on 32-bit targets that use 32-bit file offsets. + + Fixed handling WASAPI enumerated device changes. + + Fixed a crash with UWP builds when __wargv is null. + + Fixed using AL_FORMAT_BFORMAT3D_I32. + + Improved the bsinc resamplers' cutoff frequencies. + + Slightly reduced the aliasing noise in the cubic spline resampler. + + Added new bsinc48 and fast_bsinc48 resampler options. + + Added support for 16KB page sizes on Android. + + Added support for using NFC filters with UHJ output. + +openal-soft-1.24.2: + + Implemented the AL_SOFT_bformat_hoa extension. + + Implemented default device change events for the PulseAudio backend. + + Implemented an option for WASAPI exclusive mode playback. + + Fixed reverb being too quiet for sounds from different directions. + + Fixed compiling with certain versions of Clang. + + Fixed compiling for some older macOS versions. + + Fixed building alffplay on systems without pkg-config. + + Improved output format detection for CoreAudio. + + Changed the default resampler back to Cubic Spline. + + Added an SDL3 playback backend. Disabled by default to avoid a runtime + dependency and for compatibility; a single process can't safely use SDL2 + and SDL3 together on some OSs, so enable with care. + + Converted examples from SDL2 to SDL3. + + Integrated fmtlib into the main library and router for logging and string + formatting. + +openal-soft-1.24.1: + + Fixed compilation on PowerPC. + + Fixed compilation on some targets that lack lock-free 64-bit atomics. + + Fixed a crash when parsing certain option values. + + Fixed applying noexcept in the public headers with MSVC. + + Fixed building for UWP with vcpkg. + + Improved compatibility when compiling as C++20 or later. + + Integrated fmtlib for some examples and utilities. + +openal-soft-1.24.0: + + Updated library codebase to C++17. + + Implemented the ALC_SOFT_system_events extension. + + Implemented the AL_EXT_debug extension. + + Implemented the AL_EXT_direct_context extension. + + Implemented speaker configuration and headphones detection on CoreAudio. + + Fixed a potential crash with some extension functions on 32-bit Windows. + + Fixed a crash that can occur when stopping playback with the Oboe backend. + + Fixed calculating the reverb room rolloff. + + Fixed EAX occlusion, obstruction, and exclusion low-pass filter strength. + + Fixed EAX distance factor calculations. + + Fixed querying AL_EFFECTSLOT_EFFECT on auxiliary effect slots. + + Fixed compilation on some macOS systems that lack libdispatch. + + Fixed compilation as a subproject with MinGW. + + Changed the context error state to be thread-local. This is technically out + of spec, but necessary to avoid race conditions with multi-threaded use. + + Split the cubic resampler into 4-point spline and gaussian variants. The + latter prioritizing the suppression of aliasing distortion and harmonics, + the former not reducing high frequencies as much. + + Improved timing precision of starting delayed sources. + + Improved ring modulator quality. + + Improved performance of convolution reverb. + + Improved WASAPI device enumeration performance. + + Added UWP support. + + Added 'noexcept' to functions and function types when compiled as C++. As a + C API, OpenAL can't be expected to throw C++ exceptions, nor can it handle + them if they leave a callback. + + Added an experimental config option for using WASAPI spatial audio output. + + Added enumeration support to the PortAudio backend. + + Added compatibility options to override the AL_VENDOR, AL_VERSION, and + AL_RENDERER strings. + + Added an example to play LAF files. + + Disabled real-time mixing by default for PipeWire playback. + + Disabled the SndIO backend by default on non-BSD targets. + openal-soft-1.23.1: Implemented the AL_SOFT_UHJ_ex extension. diff --git a/3rdparty/openal/OpenALConfig.cmake.in b/3rdparty/openal/OpenALConfig.cmake.in new file mode 100644 index 000000000000..9704d3c496aa --- /dev/null +++ b/3rdparty/openal/OpenALConfig.cmake.in @@ -0,0 +1,9 @@ +cmake_minimum_required(VERSION 3.1...3.18) + +include("${CMAKE_CURRENT_LIST_DIR}/OpenALTargets.cmake") + +set(OPENAL_FOUND ON) +set(OPENAL_INCLUDE_DIR $) +set(OPENAL_LIBRARY $) +set(OPENAL_DEFINITIONS $) +set(OPENAL_VERSION_STRING @PACKAGE_VERSION@) diff --git a/3rdparty/openal/README.md b/3rdparty/openal/README.md index dac53e71edff..09f9ec24d909 100644 --- a/3rdparty/openal/README.md +++ b/3rdparty/openal/README.md @@ -78,15 +78,26 @@ API, including some extensions. It also includes utility libraries for math and linear algebra, which can be useful for 3D calculations. Java Bindings: +* [LWJGL](https://github.com/LWJGL/lwjgl3), the Lightweight Java Game Library, +includes Java bindings for the OpenAL API, usable with OpenAL Soft. * [JOAL](https://jogamp.org/joal/www/), part of the JogAmp project, includes Java bindings for the OpenAL API, usable with OpenAL Soft. It also includes a higher level Sound3D Toolkit API and utility functions to make easier use of OpenAL features and capabilities. +Kotlin Bindings: +* [Multiplatform OpenAL](https://git.karmakrafts.dev/kk/multiplatform-openal), developed for the Kleaver project, +includes Kotlin/Native bindings for the OpenAL API, based on OpenAL Soft with support +for Windows, Linux, macOS, iOS and Android. + Python Bindings: * [PyOpenAL](https://pypi.org/project/PyOpenAL/). Also includes methods to play wave files and, with PyOgg, also Vorbis, Opus, and FLAC. +FreePascal/Lazarus Bindings: +* [ALSound](https://github.com/Lulu04/ALSound). Also includes a higher level +API and libsndfile support to simplify loading and playing sounds. + Other bindings for these and other languages also exist. This list will grow as more bindings are found. diff --git a/3rdparty/openal/al/auxeffectslot.cpp b/3rdparty/openal/al/auxeffectslot.cpp index 332524101ab0..d405f18e2a8a 100644 --- a/3rdparty/openal/al/auxeffectslot.cpp +++ b/3rdparty/openal/al/auxeffectslot.cpp @@ -23,70 +23,82 @@ #include "auxeffectslot.h" #include -#include +#include #include +#include #include #include #include #include -#include +#include +#include +#include +#include #include "AL/al.h" #include "AL/alc.h" +#include "AL/alext.h" #include "AL/efx.h" #include "albit.h" #include "alc/alu.h" #include "alc/context.h" #include "alc/device.h" +#include "alc/effects/base.h" #include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" #include "alspan.h" +#include "atomic.h" #include "buffer.h" +#include "core/buffer_storage.h" +#include "core/device.h" #include "core/except.h" #include "core/fpu_ctrl.h" #include "core/logging.h" #include "direct_defs.h" #include "effect.h" +#include "flexarray.h" #include "opthelpers.h" +#if ALSOFT_EAX +#include "eax/api.h" +#include "eax/call.h" +#include "eax/effect.h" +#include "eax/fx_slot_index.h" +#endif + namespace { -struct FactoryItem { - EffectSlotType Type; - EffectStateFactory* (&GetFactory)(void); -}; -constexpr FactoryItem FactoryList[] = { - { EffectSlotType::None, NullStateFactory_getFactory }, - { EffectSlotType::EAXReverb, ReverbStateFactory_getFactory }, - { EffectSlotType::Reverb, StdReverbStateFactory_getFactory }, - { EffectSlotType::Autowah, AutowahStateFactory_getFactory }, - { EffectSlotType::Chorus, ChorusStateFactory_getFactory }, - { EffectSlotType::Compressor, CompressorStateFactory_getFactory }, - { EffectSlotType::Distortion, DistortionStateFactory_getFactory }, - { EffectSlotType::Echo, EchoStateFactory_getFactory }, - { EffectSlotType::Equalizer, EqualizerStateFactory_getFactory }, - { EffectSlotType::Flanger, FlangerStateFactory_getFactory }, - { EffectSlotType::FrequencyShifter, FshifterStateFactory_getFactory }, - { EffectSlotType::RingModulator, ModulatorStateFactory_getFactory }, - { EffectSlotType::PitchShifter, PshifterStateFactory_getFactory }, - { EffectSlotType::VocalMorpher, VmorpherStateFactory_getFactory }, - { EffectSlotType::DedicatedDialog, DedicatedStateFactory_getFactory }, - { EffectSlotType::DedicatedLFE, DedicatedStateFactory_getFactory }, - { EffectSlotType::Convolution, ConvolutionStateFactory_getFactory }, -}; - -EffectStateFactory *getFactoryByType(EffectSlotType type) +using SubListAllocator = al::allocator>; + +[[nodiscard]] +auto getFactoryByType(EffectSlotType type) -> EffectStateFactory* { - auto iter = std::find_if(std::begin(FactoryList), std::end(FactoryList), - [type](const FactoryItem &item) noexcept -> bool - { return item.Type == type; }); - return (iter != std::end(FactoryList)) ? iter->GetFactory() : nullptr; + switch(type) + { + case EffectSlotType::None: return NullStateFactory_getFactory(); + case EffectSlotType::Reverb: return ReverbStateFactory_getFactory(); + case EffectSlotType::Chorus: return ChorusStateFactory_getFactory(); + case EffectSlotType::Autowah: return AutowahStateFactory_getFactory(); + case EffectSlotType::Compressor: return CompressorStateFactory_getFactory(); + case EffectSlotType::Convolution: return ConvolutionStateFactory_getFactory(); + case EffectSlotType::Dedicated: return DedicatedStateFactory_getFactory(); + case EffectSlotType::Distortion: return DistortionStateFactory_getFactory(); + case EffectSlotType::Echo: return EchoStateFactory_getFactory(); + case EffectSlotType::Equalizer: return EqualizerStateFactory_getFactory(); + case EffectSlotType::Flanger: return ChorusStateFactory_getFactory(); + case EffectSlotType::FrequencyShifter: return FshifterStateFactory_getFactory(); + case EffectSlotType::RingModulator: return ModulatorStateFactory_getFactory(); + case EffectSlotType::PitchShifter: return PshifterStateFactory_getFactory(); + case EffectSlotType::VocalMorpher: return VmorpherStateFactory_getFactory(); + } + return nullptr; } -inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept +[[nodiscard]] +auto LookupEffectSlot(ALCcontext *context, ALuint id) noexcept -> ALeffectslot* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -96,10 +108,11 @@ inline ALeffectslot *LookupEffectSlot(ALCcontext *context, ALuint id) noexcept EffectSlotSubList &sublist{context->mEffectSlotList[lidx]}; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.EffectSlots + slidx; + return al::to_address(sublist.EffectSlots->begin() + slidx); } -inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) noexcept +[[nodiscard]] +inline auto LookupEffect(al::Device *device, ALuint id) noexcept -> ALeffect* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -109,10 +122,11 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) noexcept EffectSubList &sublist = device->EffectList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Effects + slidx; + return al::to_address(sublist.Effects->begin() + slidx); } -inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept +[[nodiscard]] +inline auto LookupBuffer(al::Device *device, ALuint id) noexcept -> ALbuffer* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -122,7 +136,7 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) noexcept BufferSubList &sublist = device->BufferList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Buffers + slidx; + return al::to_address(sublist.Buffers->begin() + slidx); } @@ -130,44 +144,44 @@ void AddActiveEffectSlots(const al::span auxslots, ALCcontext *co { if(auxslots.empty()) return; EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_acquire)}; - size_t newcount{curarray->size() + auxslots.size()}; + if((curarray->size()>>1) > std::numeric_limits::max()-auxslots.size()) + throw std::runtime_error{"Too many active effect slots"}; + + size_t newcount{(curarray->size()>>1) + auxslots.size()}; + if(newcount > std::numeric_limits::max()>>1) + throw std::runtime_error{"Too many active effect slots"}; - /* Insert the new effect slots into the head of the array, followed by the - * existing ones. + /* Insert the new effect slots into the head of the new array, followed by + * the existing ones. */ - EffectSlotArray *newarray = EffectSlot::CreatePtrArray(newcount); - auto slotiter = std::transform(auxslots.begin(), auxslots.end(), newarray->begin(), - [](ALeffectslot *auxslot) noexcept { return auxslot->mSlot; }); - std::copy(curarray->begin(), curarray->end(), slotiter); + auto newarray = EffectSlot::CreatePtrArray(newcount<<1); + auto new_end = std::transform(auxslots.begin(), auxslots.end(), newarray->begin(), + std::mem_fn(&ALeffectslot::mSlot)); + new_end = std::copy_n(curarray->begin(), curarray->size()>>1, new_end); /* Remove any duplicates (first instance of each will be kept). */ - auto last = newarray->end(); for(auto start=newarray->begin()+1;;) { - last = std::remove(start, last, *(start-1)); - if(start == last) break; + new_end = std::remove(start, new_end, *(start-1)); + if(start == new_end) break; ++start; } - newcount = static_cast(std::distance(newarray->begin(), last)); + newcount = static_cast(std::distance(newarray->begin(), new_end)); /* Reallocate newarray if the new size ended up smaller from duplicate * removal. */ - if(newcount < newarray->size()) UNLIKELY + if(newcount < newarray->size()>>1) UNLIKELY { - curarray = newarray; - newarray = EffectSlot::CreatePtrArray(newcount); - std::copy_n(curarray->begin(), newcount, newarray->begin()); - delete curarray; - curarray = nullptr; + auto oldarray = std::move(newarray); + newarray = EffectSlot::CreatePtrArray(newcount<<1); + new_end = std::copy_n(oldarray->begin(), newcount, newarray->begin()); } - std::uninitialized_fill_n(newarray->end(), newcount, nullptr); + std::fill(new_end, newarray->end(), nullptr); - curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); - context->mDevice->waitForMix(); - - std::destroy_n(curarray->end(), curarray->size()); - delete curarray; + auto oldarray = context->mActiveAuxSlots.exchange(std::move(newarray), + std::memory_order_acq_rel); + std::ignore = context->mDevice->waitForMix(); } void RemoveActiveEffectSlots(const al::span auxslots, ALCcontext *context) @@ -178,9 +192,9 @@ void RemoveActiveEffectSlots(const al::span auxslots, ALCcontext /* Don't shrink the allocated array size since we don't know how many (if * any) of the effect slots to remove are in the array. */ - EffectSlotArray *newarray = EffectSlot::CreatePtrArray(curarray->size()); + auto newarray = EffectSlot::CreatePtrArray(curarray->size()); - auto new_end = std::copy(curarray->begin(), curarray->end(), newarray->begin()); + auto new_end = std::copy_n(curarray->begin(), curarray->size()>>1, newarray->begin()); /* Remove elements from newarray that match any ID in slotids. */ for(const ALeffectslot *auxslot : auxslots) { @@ -191,26 +205,22 @@ void RemoveActiveEffectSlots(const al::span auxslots, ALCcontext /* Reallocate with the new size. */ auto newsize = static_cast(std::distance(newarray->begin(), new_end)); - if(newsize != newarray->size()) LIKELY + if(newsize < newarray->size()>>1) LIKELY { - curarray = newarray; - newarray = EffectSlot::CreatePtrArray(newsize); - std::copy_n(curarray->begin(), newsize, newarray->begin()); - - delete curarray; - curarray = nullptr; + auto oldarray = std::move(newarray); + newarray = EffectSlot::CreatePtrArray(newsize<<1); + new_end = std::copy_n(oldarray->begin(), newsize, newarray->begin()); } - std::uninitialized_fill_n(newarray->end(), newsize, nullptr); + std::fill(new_end, newarray->end(), nullptr); - curarray = context->mActiveAuxSlots.exchange(newarray, std::memory_order_acq_rel); - context->mDevice->waitForMix(); - - std::destroy_n(curarray->end(), curarray->size()); - delete curarray; + auto oldarray = context->mActiveAuxSlots.exchange(std::move(newarray), + std::memory_order_acq_rel); + std::ignore = context->mDevice->waitForMix(); } -EffectSlotType EffectSlotTypeFromEnum(ALenum type) +[[nodiscard]] +constexpr auto EffectSlotTypeFromEnum(ALenum type) noexcept -> EffectSlotType { switch(type) { @@ -227,17 +237,18 @@ EffectSlotType EffectSlotTypeFromEnum(ALenum type) case AL_EFFECT_AUTOWAH: return EffectSlotType::Autowah; case AL_EFFECT_COMPRESSOR: return EffectSlotType::Compressor; case AL_EFFECT_EQUALIZER: return EffectSlotType::Equalizer; - case AL_EFFECT_EAXREVERB: return EffectSlotType::EAXReverb; - case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return EffectSlotType::DedicatedLFE; - case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::DedicatedDialog; - case AL_EFFECT_CONVOLUTION_REVERB_SOFT: return EffectSlotType::Convolution; + case AL_EFFECT_EAXREVERB: return EffectSlotType::Reverb; + case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return EffectSlotType::Dedicated; + case AL_EFFECT_DEDICATED_DIALOGUE: return EffectSlotType::Dedicated; + case AL_EFFECT_CONVOLUTION_SOFT: return EffectSlotType::Convolution; } - ERR("Unhandled effect enum: 0x%04x\n", type); + ERR("Unhandled effect enum: {:#04x}", as_unsigned(type)); return EffectSlotType::None; } -bool EnsureEffectSlots(ALCcontext *context, size_t needed) -{ +[[nodiscard]] +auto EnsureEffectSlots(ALCcontext *context, size_t needed) noexcept -> bool +try { size_t count{std::accumulate(context->mEffectSlotList.cbegin(), context->mEffectSlotList.cend(), 0_uz, [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t @@ -248,22 +259,20 @@ bool EnsureEffectSlots(ALCcontext *context, size_t needed) if(context->mEffectSlotList.size() >= 1<<25) UNLIKELY return false; - context->mEffectSlotList.emplace_back(); - auto sublist = context->mEffectSlotList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->EffectSlots = static_cast( - al_calloc(alignof(ALeffectslot), sizeof(ALeffectslot)*64)); - if(!sublist->EffectSlots) UNLIKELY - { - context->mEffectSlotList.pop_back(); - return false; - } - count += 64; + EffectSlotSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.EffectSlots = SubListAllocator{}.allocate(1); + context->mEffectSlotList.emplace_back(std::move(sublist)); + count += std::tuple_size_v; } return true; } +catch(...) { + return false; +} -ALeffectslot *AllocEffectSlot(ALCcontext *context) +[[nodiscard]] +auto AllocEffectSlot(ALCcontext *context) -> ALeffectslot* { auto sublist = std::find_if(context->mEffectSlotList.begin(), context->mEffectSlotList.end(), [](const EffectSlotSubList &entry) noexcept -> bool @@ -272,7 +281,8 @@ ALeffectslot *AllocEffectSlot(ALCcontext *context) auto slidx = static_cast(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALeffectslot *slot{al::construct_at(sublist->EffectSlots + slidx, context)}; + ALeffectslot *slot{al::construct_at(al::to_address(sublist->EffectSlots->begin() + slidx), + context)}; aluInitEffectPanning(slot->mSlot, context); /* Add 1 to avoid ID 0. */ @@ -312,255 +322,186 @@ inline void UpdateProps(ALeffectslot *slot, ALCcontext *context) } // namespace -AL_API DECL_FUNC2(void, alGenAuxiliaryEffectSlots, ALsizei, ALuint*) +AL_API DECL_FUNC2(void, alGenAuxiliaryEffectSlots, ALsizei,n, ALuint*,effectslots) FORCE_ALIGN void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Generating %d effect slots", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Generating {} effect slots", n); if(n <= 0) UNLIKELY return; - std::lock_guard _{context->mEffectSlotLock}; - ALCdevice *device{context->mALDevice.get()}; - if(static_cast(n) > device->AuxiliaryEffectSlotMax-context->mNumEffectSlots) - { - context->setError(AL_OUT_OF_MEMORY, "Exceeding %u effect slot limit (%u + %d)", + auto slotlock = std::lock_guard{context->mEffectSlotLock}; + auto *device = context->mALDevice.get(); + + const al::span eids{effectslots, static_cast(n)}; + if(context->mNumEffectSlots > device->AuxiliaryEffectSlotMax + || eids.size() > device->AuxiliaryEffectSlotMax-context->mNumEffectSlots) + context->throw_error(AL_OUT_OF_MEMORY, "Exceeding {} effect slot limit ({} + {})", device->AuxiliaryEffectSlotMax, context->mNumEffectSlots, n); - return; - } - if(!EnsureEffectSlots(context, static_cast(n))) - { - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effectslot%s", n, + + if(!EnsureEffectSlots(context, eids.size())) + context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} effectslot{}", n, (n==1) ? "" : "s"); - return; - } - if(n == 1) - { - ALeffectslot *slot{AllocEffectSlot(context)}; - effectslots[0] = slot->id; + std::vector slots; + try { + if(eids.size() == 1) + { + /* Special handling for the easy and normal case. */ + eids[0] = AllocEffectSlot(context)->id; + } + else + { + slots.reserve(eids.size()); + std::generate_n(std::back_inserter(slots), eids.size(), + [context]{ return AllocEffectSlot(context); }); + + std::transform(slots.cbegin(), slots.cend(), eids.begin(), + [](ALeffectslot *slot) -> ALuint { return slot->id; }); + } } - else - { - std::vector ids; - ALsizei count{n}; - ids.reserve(static_cast(count)); - do { - ALeffectslot *slot{AllocEffectSlot(context)}; - ids.emplace_back(slot->id); - } while(--count); - std::copy(ids.cbegin(), ids.cend(), effectslots); + catch(std::exception& e) { + ERR("Exception allocating effectslot {} of {}: {}", slots.size()+1, n, e.what()); + auto delete_effectslot = [context](ALeffectslot *slot) -> void + { FreeEffectSlot(context, slot); }; + std::for_each(slots.begin(), slots.end(), delete_effectslot); + context->throw_error(AL_INVALID_OPERATION, "Exception allocating {} effectslots: {}", n, + e.what()); } } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC2(void, alDeleteAuxiliaryEffectSlots, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alDeleteAuxiliaryEffectSlots, ALsizei,n, const ALuint*,effectslots) FORCE_ALIGN void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) noexcept -{ +try { if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Deleting %d effect slots", n); + context->throw_error(AL_INVALID_VALUE, "Deleting {} effect slots", n); if(n <= 0) UNLIKELY return; - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; if(n == 1) { - ALeffectslot *slot{LookupEffectSlot(context, effectslots[0])}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[0]); - return; - } - if(ReadRef(slot->ref) != 0) UNLIKELY - { - context->setError(AL_INVALID_OPERATION, "Deleting in-use effect slot %u", - effectslots[0]); - return; - } + ALeffectslot *slot{LookupEffectSlot(context, *effectslots)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", *effectslots); + if(slot->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, "Deleting in-use effect slot {}", + *effectslots); + RemoveActiveEffectSlots({&slot, 1u}, context); FreeEffectSlot(context, slot); } else { - auto slots = std::vector(static_cast(n)); - for(size_t i{0};i < slots.size();++i) - { - ALeffectslot *slot{LookupEffectSlot(context, effectslots[i])}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslots[i]); - return; - } - if(ReadRef(slot->ref) != 0) UNLIKELY - { - context->setError(AL_INVALID_OPERATION, "Deleting in-use effect slot %u", - effectslots[i]); - return; - } - slots[i] = slot; - } - /* Remove any duplicates. */ - auto slots_end = slots.end(); - for(auto start=slots.begin()+1;start != slots_end;++start) + const al::span eids{effectslots, static_cast(n)}; + std::vector slots; + slots.reserve(eids.size()); + + auto lookupslot = [context](const ALuint eid) -> ALeffectslot* { - slots_end = std::remove(start, slots_end, *(start-1)); - if(start == slots_end) break; - } - slots.erase(slots_end, slots.end()); + ALeffectslot *slot{LookupEffectSlot(context, eid)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", eid); + if(slot->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, "Deleting in-use effect slot {}", eid); + return slot; + }; + std::transform(eids.cbegin(), eids.cend(), std::back_inserter(slots), lookupslot); /* All effectslots are valid, remove and delete them */ RemoveActiveEffectSlots(slots, context); - for(ALeffectslot *slot : slots) - FreeEffectSlot(context, slot); + + auto delete_effectslot = [context](const ALuint eid) -> void + { + if(ALeffectslot *slot{LookupEffectSlot(context, eid)}) + FreeEffectSlot(context, slot); + }; + std::for_each(eids.begin(), eids.end(), delete_effectslot); } } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC1(ALboolean, alIsAuxiliaryEffectSlot, ALuint) +AL_API DECL_FUNC1(ALboolean, alIsAuxiliaryEffectSlot, ALuint,effectslot) FORCE_ALIGN ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) noexcept { - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; if(LookupEffectSlot(context, effectslot) != nullptr) return AL_TRUE; return AL_FALSE; } -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) noexcept +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot{LookupEffectSlot(context.get(), slotid)}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotid); - return; - } - if(slot->mState == SlotState::Playing) - return; - - slot->mPropsDirty = false; - slot->updateProps(context.get()); - - AddActiveEffectSlots({&slot, 1}, context.get()); - slot->mState = SlotState::Playing; + context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotPlaySOFT not supported"); } -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) noexcept +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei, const ALuint*) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Playing %d effect slots", n); - if(n <= 0) UNLIKELY return; - - auto slots = std::vector(static_cast(n)); - std::lock_guard _{context->mEffectSlotLock}; - for(size_t i{0};i < slots.size();++i) - { - ALeffectslot *slot{LookupEffectSlot(context.get(), slotids[i])}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotids[i]); - return; - } - - if(slot->mState != SlotState::Playing) - { - slot->mPropsDirty = false; - slot->updateProps(context.get()); - } - slots[i] = slot; - }; - - AddActiveEffectSlots(slots, context.get()); - for(auto slot : slots) - slot->mState = SlotState::Playing; + context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotPlayvSOFT not supported"); } -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) noexcept +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot{LookupEffectSlot(context.get(), slotid)}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotid); - return; - } - - RemoveActiveEffectSlots({&slot, 1}, context.get()); - slot->mState = SlotState::Stopped; + context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotStopSOFT not supported"); } -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) noexcept +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei, const ALuint*) noexcept { ContextRef context{GetContextRef()}; if(!context) UNLIKELY return; - - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Stopping %d effect slots", n); - if(n <= 0) UNLIKELY return; - - auto slots = std::vector(static_cast(n)); - std::lock_guard _{context->mEffectSlotLock}; - for(size_t i{0};i < slots.size();++i) - { - ALeffectslot *slot{LookupEffectSlot(context.get(), slotids[i])}; - if(!slot) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", slotids[i]); - return; - } - - slots[i] = slot; - }; - - RemoveActiveEffectSlots(slots, context.get()); - for(auto slot : slots) - slot->mState = SlotState::Stopped; + context->setError(AL_INVALID_OPERATION, "alAuxiliaryEffectSlotStopvSOFT not supported"); } -AL_API DECL_FUNC3(void, alAuxiliaryEffectSloti, ALuint, ALenum, ALint) +AL_API DECL_FUNC3(void, alAuxiliaryEffectSloti, ALuint,effectslot, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; + + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); ALeffectslot *target{}; - ALCdevice *device{}; ALenum err{}; switch(param) { case AL_EFFECTSLOT_EFFECT: - device = context->mALDevice.get(); - { - std::lock_guard ___{device->EffectLock}; - ALeffect *effect{value ? LookupEffect(device, static_cast(value)) : nullptr}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; + auto *effect = value ? LookupEffect(device, static_cast(value)) : nullptr; if(effect) err = slot->initEffect(effect->id, effect->type, effect->Props, context); else { if(value != 0) - return context->setError(AL_INVALID_VALUE, "Invalid effect ID %u", value); + context->throw_error(AL_INVALID_VALUE, "Invalid effect ID {}", value); err = slot->initEffect(0, AL_EFFECT_NULL, EffectProps{}, context); } } - if(err != AL_NO_ERROR) UNLIKELY - { - context->setError(err, "Effect initialization failed"); - return; - } + if(err != AL_NO_ERROR) + context->throw_error(err, "Effect initialization failed"); + if(slot->mState == SlotState::Initial) UNLIKELY { slot->mPropsDirty = false; @@ -570,21 +511,23 @@ FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, A slot->mState = SlotState::Playing; return; } - break; + UpdateProps(slot, context); + return; case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: if(!(value == AL_TRUE || value == AL_FALSE)) - return context->setError(AL_INVALID_VALUE, - "Effect slot auxiliary send auto out of range"); - if(slot->AuxSendAuto == !!value) UNLIKELY - return; - slot->AuxSendAuto = !!value; - break; + context->throw_error(AL_INVALID_VALUE, "Effect slot auxiliary send auto out of range"); + if(!(slot->AuxSendAuto == !!value)) LIKELY + { + slot->AuxSendAuto = !!value; + UpdateProps(slot, context); + } + return; case AL_EFFECTSLOT_TARGET_SOFT: target = LookupEffectSlot(context, static_cast(value)); if(value && !target) - return context->setError(AL_INVALID_VALUE, "Invalid effect slot target ID"); + context->throw_error(AL_INVALID_VALUE, "Invalid effect slot target ID {}", value); if(slot->Target == target) UNLIKELY return; if(target) @@ -593,8 +536,8 @@ FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, A while(checker && checker != slot) checker = checker->Target; if(checker) - return context->setError(AL_INVALID_OPERATION, - "Setting target of effect slot ID %u to %u creates circular chain", slot->id, + context->throw_error(AL_INVALID_OPERATION, + "Setting target of effect slot ID {} to {} creates circular chain", slot->id, target->id); } @@ -612,61 +555,104 @@ FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, A if(target) IncrementRef(target->ref); slot->Target = target; - break; + UpdateProps(slot, context); + return; case AL_BUFFER: - device = context->mALDevice.get(); - - if(slot->mState == SlotState::Playing) - return context->setError(AL_INVALID_OPERATION, - "Setting buffer on playing effect slot %u", slot->id); - if(ALbuffer *buffer{slot->Buffer}) { - if(buffer->id == static_cast(value)) UNLIKELY + if(buffer->id == static_cast(value)) return; } - else if(value == 0) UNLIKELY + else if(value == 0) return; + if(slot->mState == SlotState::Playing) { - std::lock_guard ___{device->BufferLock}; + EffectStateFactory *factory{getFactoryByType(slot->Effect.Type)}; + assert(factory); + al::intrusive_ptr state{factory->create()}; + + auto *device = context->mALDevice.get(); + auto bufferlock = std::unique_lock{device->BufferLock}; ALbuffer *buffer{}; if(value) { buffer = LookupBuffer(device, static_cast(value)); - if(!buffer) return context->setError(AL_INVALID_VALUE, "Invalid buffer ID"); + if(!buffer) + context->throw_error(AL_INVALID_VALUE, "Invalid buffer ID {}", value); if(buffer->mCallback) - return context->setError(AL_INVALID_OPERATION, + context->throw_error(AL_INVALID_OPERATION, "Callback buffer not valid for effects"); IncrementRef(buffer->ref); } + /* Stop the effect slot from processing while we switch buffers. */ + RemoveActiveEffectSlots({&slot, 1}, context); + if(ALbuffer *oldbuffer{slot->Buffer}) DecrementRef(oldbuffer->ref); slot->Buffer = buffer; + bufferlock.unlock(); + + state->mOutTarget = device->Dry.Buffer; + { + FPUCtl mixer_mode{}; + state->deviceUpdate(device, buffer); + } + slot->Effect.State = std::move(state); + + slot->mPropsDirty = false; + slot->updateProps(context); + AddActiveEffectSlots({&slot, 1}, context); + } + else + { + auto *device = context->mALDevice.get(); + auto bufferlock = std::unique_lock{device->BufferLock}; + ALbuffer *buffer{}; + if(value) + { + buffer = LookupBuffer(device, static_cast(value)); + if(!buffer) + context->throw_error(AL_INVALID_VALUE, "Invalid buffer ID {}", value); + if(buffer->mCallback) + context->throw_error(AL_INVALID_OPERATION, + "Callback buffer not valid for effects"); + + IncrementRef(buffer->ref); + } + + if(ALbuffer *oldbuffer{slot->Buffer}) + DecrementRef(oldbuffer->ref); + slot->Buffer = buffer; + bufferlock.unlock(); FPUCtl mixer_mode{}; auto *state = slot->Effect.State.get(); state->deviceUpdate(device, buffer); + slot->mPropsDirty = true; } - break; + return; case AL_EFFECTSLOT_STATE_SOFT: - return context->setError(AL_INVALID_OPERATION, "AL_EFFECTSLOT_STATE_SOFT is read-only"); - - default: - return context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", - param); + context->throw_error(AL_INVALID_OPERATION, "AL_EFFECTSLOT_STATE_SOFT is read-only"); } - UpdateProps(slot, context); + + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotiv, ALuint, ALenum, const ALint*) +AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotiv, ALuint,effectslot, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) noexcept -{ +try { switch(param) { case AL_EFFECTSLOT_EFFECT: @@ -674,121 +660,134 @@ FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, case AL_EFFECTSLOT_TARGET_SOFT: case AL_EFFECTSLOT_STATE_SOFT: case AL_BUFFER: - alAuxiliaryEffectSlotiDirect(context, effectslot, param, values[0]); + alAuxiliaryEffectSlotiDirect(context, effectslot, param, *values); return; } - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); + std::lock_guard slotlock{context->mEffectSlotLock}; + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); - switch(param) - { - default: - return context->setError(AL_INVALID_ENUM, - "Invalid effect slot integer-vector property 0x%04x", param); - } + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat) +AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotf, ALuint,effectslot, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; + + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); switch(param) { case AL_EFFECTSLOT_GAIN: if(!(value >= 0.0f && value <= 1.0f)) - return context->setError(AL_INVALID_VALUE, "Effect slot gain out of range"); - if(slot->Gain == value) UNLIKELY - return; - slot->Gain = value; - break; - - default: - return context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", - param); + context->throw_error(AL_INVALID_VALUE, "Effect slot gain {} out of range", value); + if(!(slot->Gain == value)) LIKELY + { + slot->Gain = value; + UpdateProps(slot, context); + } + return; } - UpdateProps(slot, context); + + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotfv, ALuint, ALenum, const ALfloat*) +AL_API DECL_FUNC3(void, alAuxiliaryEffectSlotfv, ALuint,effectslot, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) noexcept -{ +try { switch(param) { case AL_EFFECTSLOT_GAIN: - alAuxiliaryEffectSlotfDirect(context, effectslot, param, values[0]); + alAuxiliaryEffectSlotfDirect(context, effectslot, param, *values); return; } - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); + std::lock_guard slotlock{context->mEffectSlotLock}; + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); - switch(param) - { - default: - return context->setError(AL_INVALID_ENUM, - "Invalid effect slot float-vector property 0x%04x", param); - } + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSloti, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSloti, ALuint,effectslot, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) noexcept -{ - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); +try { + std::lock_guard slotlock{context->mEffectSlotLock}; + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); switch(param) { case AL_EFFECTSLOT_EFFECT: *value = static_cast(slot->EffectId); - break; + return; case AL_EFFECTSLOT_AUXILIARY_SEND_AUTO: *value = slot->AuxSendAuto ? AL_TRUE : AL_FALSE; - break; + return; case AL_EFFECTSLOT_TARGET_SOFT: if(auto *target = slot->Target) *value = static_cast(target->id); else *value = 0; - break; + return; case AL_EFFECTSLOT_STATE_SOFT: *value = static_cast(slot->mState); - break; + return; case AL_BUFFER: if(auto *buffer = slot->Buffer) *value = static_cast(buffer->id); else *value = 0; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid effect slot integer property 0x%04x", param); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotiv, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotiv, ALuint,effectslot, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) noexcept -{ +try { switch(param) { case AL_EFFECTSLOT_EFFECT: @@ -800,43 +799,47 @@ FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *contex return; } - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); - switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid effect slot integer-vector property 0x%04x", - param); - } + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotf, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotf, ALuint,effectslot, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) noexcept -{ - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); +try { + std::lock_guard slotlock{context->mEffectSlotLock}; + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); switch(param) { - case AL_EFFECTSLOT_GAIN: - *value = slot->Gain; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid effect slot float property 0x%04x", param); + case AL_EFFECTSLOT_GAIN: *value = slot->Gain; return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotfv, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetAuxiliaryEffectSlotfv, ALuint,effectslot, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) noexcept -{ +try { switch(param) { case AL_EFFECTSLOT_GAIN: @@ -844,17 +847,18 @@ FORCE_ALIGN void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *contex return; } - std::lock_guard _{context->mEffectSlotLock}; - ALeffectslot *slot = LookupEffectSlot(context, effectslot); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", effectslot); + std::lock_guard slotlock{context->mEffectSlotLock}; + ALeffectslot *slot{LookupEffectSlot(context, effectslot)}; + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", effectslot); - switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid effect slot float-vector property 0x%04x", - param); - } + context->throw_error(AL_INVALID_ENUM, "Invalid effect slot float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } @@ -880,12 +884,8 @@ ALeffectslot::~ALeffectslot() DecrementRef(Buffer->ref); Buffer = nullptr; - if(EffectSlotProps *props{mSlot->Update.exchange(nullptr)}) - { - TRACE("Freed unapplied AuxiliaryEffectSlot update %p\n", - decltype(std::declval()){props}); - delete props; - } + if(auto *slot = mSlot->Update.exchange(nullptr, std::memory_order_relaxed)) + slot->State = nullptr; mSlot->mEffectState = nullptr; mSlot->InUse = false; @@ -900,13 +900,13 @@ ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const Effect EffectStateFactory *factory{getFactoryByType(newtype)}; if(!factory) { - ERR("Failed to find factory for effect slot type %d\n", static_cast(newtype)); + ERR("Failed to find factory for effect slot type {}", + int{al::to_underlying(newtype)}); return AL_INVALID_ENUM; } al::intrusive_ptr state{factory->create()}; - ALCdevice *device{context->mALDevice.get()}; - std::unique_lock statelock{device->StateLock}; + auto *device = context->mALDevice.get(); state->mOutTarget = device->Dry.Buffer; { FPUCtl mixer_mode{}; @@ -923,7 +923,7 @@ ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const Effect EffectId = effectId; /* Remove state references from old effect slot property updates. */ - EffectSlotProps *props{context->mFreeEffectslotProps.load()}; + EffectSlotProps *props{context->mFreeEffectSlotProps.load()}; while(props) { props->State = nullptr; @@ -933,20 +933,20 @@ ALenum ALeffectslot::initEffect(ALuint effectId, ALenum effectType, const Effect return AL_NO_ERROR; } -void ALeffectslot::updateProps(ALCcontext *context) +void ALeffectslot::updateProps(ALCcontext *context) const { /* Get an unused property container, or allocate a new one as needed. */ - EffectSlotProps *props{context->mFreeEffectslotProps.load(std::memory_order_relaxed)}; + EffectSlotProps *props{context->mFreeEffectSlotProps.load(std::memory_order_acquire)}; if(!props) - props = new EffectSlotProps{}; - else { - EffectSlotProps *next; - do { - next = props->next.load(std::memory_order_relaxed); - } while(context->mFreeEffectslotProps.compare_exchange_weak(props, next, - std::memory_order_seq_cst, std::memory_order_acquire) == 0); + context->allocEffectSlotProps(); + props = context->mFreeEffectSlotProps.load(std::memory_order_acquire); } + EffectSlotProps *next; + do { + next = props->next.load(std::memory_order_relaxed); + } while(!context->mFreeEffectSlotProps.compare_exchange_weak(props, next, + std::memory_order_acq_rel, std::memory_order_acquire)); /* Copy in current property values. */ props->Gain = Gain; @@ -965,35 +965,35 @@ void ALeffectslot::updateProps(ALCcontext *context) * freelist. */ props->State = nullptr; - AtomicReplaceHead(context->mFreeEffectslotProps, props); + AtomicReplaceHead(context->mFreeEffectSlotProps, props); } } void ALeffectslot::SetName(ALCcontext* context, ALuint id, std::string_view name) { - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; auto slot = LookupEffectSlot(context, id); - if(!slot) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect slot ID %u", id); + if(!slot) + context->throw_error(AL_INVALID_NAME, "Invalid effect slot ID {}", id); context->mEffectSlotNames.insert_or_assign(id, name); } void UpdateAllEffectSlotProps(ALCcontext *context) { - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; for(auto &sublist : context->mEffectSlotList) { uint64_t usemask{~sublist.FreeMask}; while(usemask) { - const int idx{al::countr_zero(usemask)}; + const auto idx = static_cast(al::countr_zero(usemask)); usemask &= ~(1_u64 << idx); - ALeffectslot *slot{sublist.EffectSlots + idx}; + auto &slot = (*sublist.EffectSlots)[idx]; - if(slot->mState != SlotState::Stopped && std::exchange(slot->mPropsDirty, false)) - slot->updateProps(context); + if(std::exchange(slot.mPropsDirty, false)) + slot.updateProps(context); } } } @@ -1007,59 +1007,59 @@ EffectSlotSubList::~EffectSlotSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - std::destroy_at(EffectSlots+idx); + std::destroy_at(al::to_address(EffectSlots->begin() + idx)); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; - al_free(EffectSlots); + SubListAllocator{}.deallocate(EffectSlots, 1); EffectSlots = nullptr; } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX void ALeffectslot::eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index) { if(index >= EAX_MAX_FXSLOTS) eax_fail("Index out of range."); - eax_al_context_ = &al_context; - eax_fx_slot_index_ = index; + mEaxALContext = &al_context; + mEaxFXSlotIndex = index; eax_fx_slot_set_defaults(); - eax_effect_ = std::make_unique(); - if(index == 0) eax_effect_->init(); - else if(index == 1) eax_effect_->init(); - else eax_effect_->init(); + mEaxEffect = std::make_unique(); + if(index == 0) mEaxEffect->init(); + else if(index == 1) mEaxEffect->init(); + else mEaxEffect->init(); } void ALeffectslot::eax_commit() { - if(eax_df_ != EaxDirtyFlags{}) + if(mEaxDf.any()) { - auto df = EaxDirtyFlags{}; - switch(eax_version_) + auto df = std::bitset{}; + switch(mEaxVersion) { case 1: case 2: case 3: - eax5_fx_slot_commit(eax123_, df); + eax5_fx_slot_commit(mEax123, df); break; case 4: eax4_fx_slot_commit(df); break; case 5: - eax5_fx_slot_commit(eax5_, df); + eax5_fx_slot_commit(mEax5, df); break; } - eax_df_ = EaxDirtyFlags{}; + mEaxDf.reset(); - if((df & eax_volume_dirty_bit) != EaxDirtyFlags{}) + if(df.test(eax_volume_dirty_bit)) eax_fx_slot_set_volume(); - if((df & eax_flags_dirty_bit) != EaxDirtyFlags{}) + if(df.test(eax_flags_dirty_bit)) eax_fx_slot_set_flags(); } - if(eax_effect_->commit(eax_version_)) - eax_set_efx_slot_effect(*eax_effect_); + if(mEaxEffect->commit(mEaxVersion)) + eax_set_efx_slot_effect(*mEaxEffect); } [[noreturn]] void ALeffectslot::eax_fail(const char* message) @@ -1122,7 +1122,7 @@ ALenum ALeffectslot::eax_get_efx_effect_type(const GUID& guid) const GUID& ALeffectslot::eax_get_eax_default_effect_guid() const noexcept { - switch(eax_fx_slot_index_) + switch(mEaxFXSlotIndex) { case 0: return EAX_REVERB_EFFECT; case 1: return EAX_CHORUS_EFFECT; @@ -1135,7 +1135,7 @@ long ALeffectslot::eax_get_eax_default_lock() const noexcept return eax4_fx_slot_is_legacy() ? EAXFXSLOT_LOCKED : EAXFXSLOT_UNLOCKED; } -void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) noexcept +void ALeffectslot::eax4_fx_slot_set_defaults(EAX40FXSLOTPROPERTIES& props) noexcept { props.guidLoadEffect = eax_get_eax_default_effect_guid(); props.lVolume = EAXFXSLOT_DEFAULTVOLUME; @@ -1143,7 +1143,7 @@ void ALeffectslot::eax4_fx_slot_set_defaults(Eax4Props& props) noexcept props.ulFlags = EAX40FXSLOT_DEFAULTFLAGS; } -void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept +void ALeffectslot::eax5_fx_slot_set_defaults(EAX50FXSLOTPROPERTIES& props) noexcept { props.guidLoadEffect = eax_get_eax_default_effect_guid(); props.lVolume = EAXFXSLOT_DEFAULTVOLUME; @@ -1155,14 +1155,14 @@ void ALeffectslot::eax5_fx_slot_set_defaults(Eax5Props& props) noexcept void ALeffectslot::eax_fx_slot_set_defaults() { - eax5_fx_slot_set_defaults(eax123_.i); - eax4_fx_slot_set_defaults(eax4_.i); - eax5_fx_slot_set_defaults(eax5_.i); - eax_ = eax5_.i; - eax_df_ = EaxDirtyFlags{}; + eax5_fx_slot_set_defaults(mEax123.i); + eax4_fx_slot_set_defaults(mEax4.i); + eax5_fx_slot_set_defaults(mEax5.i); + mEax = mEax5.i; + mEaxDf.reset(); } -void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const +void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const EAX40FXSLOTPROPERTIES& props) { switch(call.get_property_id()) { @@ -1186,7 +1186,7 @@ void ALeffectslot::eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) } } -void ALeffectslot::eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const +void ALeffectslot::eax5_fx_slot_get(const EaxCall& call, const EAX50FXSLOTPROPERTIES& props) { switch(call.get_property_id()) { @@ -1220,8 +1220,8 @@ void ALeffectslot::eax_fx_slot_get(const EaxCall& call) const { switch(call.get_version()) { - case 4: eax4_fx_slot_get(call, eax4_.i); break; - case 5: eax5_fx_slot_get(call, eax5_.i); break; + case 4: eax4_fx_slot_get(call, mEax4.i); break; + case 5: eax5_fx_slot_get(call, mEax5.i); break; default: eax_fail_unknown_version(); } } @@ -1234,7 +1234,7 @@ bool ALeffectslot::eax_get(const EaxCall& call) eax_fx_slot_get(call); break; case EaxCallPropertySetId::fx_slot_effect: - eax_effect_->get(call); + mEaxEffect->get(call); break; default: eax_fail_unknown_property_id(); @@ -1247,19 +1247,19 @@ void ALeffectslot::eax_fx_slot_load_effect(int version, ALenum altype) { if(!IsValidEffectType(altype)) altype = AL_EFFECT_NULL; - eax_effect_->set_defaults(version, altype); + mEaxEffect->set_defaults(version, altype); } void ALeffectslot::eax_fx_slot_set_volume() { - const auto volume = std::clamp(eax_.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME); + const auto volume = std::clamp(mEax.lVolume, EAXFXSLOT_MINVOLUME, EAXFXSLOT_MAXVOLUME); const auto gain = level_mb_to_gain(static_cast(volume)); eax_set_efx_slot_gain(gain); } void ALeffectslot::eax_fx_slot_set_environment_flag() { - eax_set_efx_slot_send_auto((eax_.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0u); + eax_set_efx_slot_send_auto((mEax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0u); } void ALeffectslot::eax_fx_slot_set_flags() @@ -1272,11 +1272,11 @@ void ALeffectslot::eax4_fx_slot_set_all(const EaxCall& call) eax4_fx_slot_ensure_unlocked(); const auto& src = call.get_value(); Eax4AllValidator{}(src); - auto& dst = eax4_.i; - eax_df_ |= eax_load_effect_dirty_bit; // Always reset the effect. - eax_df_ |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{}); + auto& dst = mEax4.i; + mEaxDf.set(eax_load_effect_dirty_bit); // Always reset the effect. + if(dst.lVolume != src.lVolume) mEaxDf.set(eax_volume_dirty_bit); + if(dst.lLock != src.lLock) mEaxDf.set(eax_lock_dirty_bit); + if(dst.ulFlags != src.ulFlags) mEaxDf.set(eax_flags_dirty_bit); dst = src; } @@ -1284,33 +1284,30 @@ void ALeffectslot::eax5_fx_slot_set_all(const EaxCall& call) { const auto& src = call.get_value(); Eax5AllValidator{}(src); - auto& dst = eax5_.i; - eax_df_ |= eax_load_effect_dirty_bit; // Always reset the effect. - eax_df_ |= (dst.lVolume != src.lVolume ? eax_volume_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.lLock != src.lLock ? eax_lock_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.ulFlags != src.ulFlags ? eax_flags_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.lOcclusion != src.lOcclusion ? eax_flags_dirty_bit : EaxDirtyFlags{}); - eax_df_ |= (dst.flOcclusionLFRatio != src.flOcclusionLFRatio ? eax_flags_dirty_bit : EaxDirtyFlags{}); + auto& dst = mEax5.i; + mEaxDf.set(eax_load_effect_dirty_bit); // Always reset the effect. + if(dst.lVolume != src.lVolume) mEaxDf.set(eax_volume_dirty_bit); + if(dst.lLock != src.lLock) mEaxDf.set(eax_lock_dirty_bit); + if(dst.ulFlags != src.ulFlags) mEaxDf.set(eax_flags_dirty_bit); + if(dst.lOcclusion != src.lOcclusion) mEaxDf.set(eax_flags_dirty_bit); + if(dst.flOcclusionLFRatio != src.flOcclusionLFRatio) mEaxDf.set(eax_flags_dirty_bit); dst = src; } bool ALeffectslot::eax_fx_slot_should_update_sources() const noexcept { - const auto dirty_bits = - eax_occlusion_dirty_bit | - eax_occlusion_lf_ratio_dirty_bit | - eax_flags_dirty_bit; - - if((eax_df_ & dirty_bits) != EaxDirtyFlags{}) - return true; - - return false; + static constexpr auto dirty_bits = std::bitset{ + (1u << eax_occlusion_dirty_bit) + | (1u << eax_occlusion_lf_ratio_dirty_bit) + | (1u << eax_flags_dirty_bit) + }; + return (mEaxDf & dirty_bits).any(); } // Returns `true` if all sources should be updated, or `false` otherwise. bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) { - auto& dst = eax4_.i; + auto& dst = mEax4.i; switch(call.get_property_id()) { @@ -1318,24 +1315,25 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) break; case EAXFXSLOT_ALLPARAMETERS: eax4_fx_slot_set_all(call); - if((eax_df_ & eax_load_effect_dirty_bit)) + if(mEaxDf.test(eax_load_effect_dirty_bit)) eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_LOADEFFECT: eax4_fx_slot_ensure_unlocked(); - eax_fx_slot_set_dirty(call, dst.guidLoadEffect, eax_df_); - if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_set_dirty(call, + dst.guidLoadEffect, mEaxDf); + if(mEaxDf.test(eax_load_effect_dirty_bit)) eax_fx_slot_load_effect(4, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_VOLUME: - eax_fx_slot_set(call, dst.lVolume, eax_df_); + eax_fx_slot_set(call, dst.lVolume, mEaxDf); break; case EAXFXSLOT_LOCK: eax4_fx_slot_ensure_unlocked(); - eax_fx_slot_set(call, dst.lLock, eax_df_); + eax_fx_slot_set(call, dst.lLock, mEaxDf); break; case EAXFXSLOT_FLAGS: - eax_fx_slot_set(call, dst.ulFlags, eax_df_); + eax_fx_slot_set(call, dst.ulFlags, mEaxDf); break; default: eax_fail_unknown_property_id(); @@ -1347,7 +1345,7 @@ bool ALeffectslot::eax4_fx_slot_set(const EaxCall& call) // Returns `true` if all sources should be updated, or `false` otherwise. bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) { - auto& dst = eax5_.i; + auto& dst = mEax5.i; switch(call.get_property_id()) { @@ -1355,28 +1353,31 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) break; case EAXFXSLOT_ALLPARAMETERS: eax5_fx_slot_set_all(call); - if((eax_df_ & eax_load_effect_dirty_bit)) + if(mEaxDf.test(eax_load_effect_dirty_bit)) eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_LOADEFFECT: - eax_fx_slot_set_dirty(call, dst.guidLoadEffect, eax_df_); - if((eax_df_ & eax_load_effect_dirty_bit)) + eax_fx_slot_set_dirty(call, + dst.guidLoadEffect, mEaxDf); + if(mEaxDf.test(eax_load_effect_dirty_bit)) eax_fx_slot_load_effect(5, eax_get_efx_effect_type(dst.guidLoadEffect)); break; case EAXFXSLOT_VOLUME: - eax_fx_slot_set(call, dst.lVolume, eax_df_); + eax_fx_slot_set(call, dst.lVolume, mEaxDf); break; case EAXFXSLOT_LOCK: - eax_fx_slot_set(call, dst.lLock, eax_df_); + eax_fx_slot_set(call, dst.lLock, mEaxDf); break; case EAXFXSLOT_FLAGS: - eax_fx_slot_set(call, dst.ulFlags, eax_df_); + eax_fx_slot_set(call, dst.ulFlags, mEaxDf); break; case EAXFXSLOT_OCCLUSION: - eax_fx_slot_set(call, dst.lOcclusion, eax_df_); + eax_fx_slot_set(call, dst.lOcclusion, + mEaxDf); break; case EAXFXSLOT_OCCLUSIONLFRATIO: - eax_fx_slot_set(call, dst.flOcclusionLFRatio, eax_df_); + eax_fx_slot_set(call, + dst.flOcclusionLFRatio, mEaxDf); break; default: eax_fail_unknown_property_id(); @@ -1388,7 +1389,7 @@ bool ALeffectslot::eax5_fx_slot_set(const EaxCall& call) // Returns `true` if all sources should be updated, or `false` otherwise. bool ALeffectslot::eax_fx_slot_set(const EaxCall& call) { - switch (call.get_version()) + switch(call.get_version()) { case 4: return eax4_fx_slot_set(call); case 5: return eax5_fx_slot_set(call); @@ -1404,39 +1405,41 @@ bool ALeffectslot::eax_set(const EaxCall& call) switch(call.get_property_set_id()) { case EaxCallPropertySetId::fx_slot: ret = eax_fx_slot_set(call); break; - case EaxCallPropertySetId::fx_slot_effect: eax_effect_->set(call); break; + case EaxCallPropertySetId::fx_slot_effect: mEaxEffect->set(call); break; default: eax_fail_unknown_property_id(); } const auto version = call.get_version(); - if(eax_version_ != version) - eax_df_ = ~EaxDirtyFlags{}; - eax_version_ = version; + if(mEaxVersion != version) + mEaxDf.set(); + mEaxVersion = version; return ret; } -void ALeffectslot::eax4_fx_slot_commit(EaxDirtyFlags& dst_df) +void ALeffectslot::eax4_fx_slot_commit(std::bitset& dst_df) { - eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect); - eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lVolume); - eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::lLock); - eax_fx_slot_commit_property(eax4_, dst_df, &EAX40FXSLOTPROPERTIES::ulFlags); + eax_fx_slot_commit_property(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::guidLoadEffect); + eax_fx_slot_commit_property(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::lVolume); + eax_fx_slot_commit_property(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::lLock); + eax_fx_slot_commit_property(mEax4, dst_df, &EAX40FXSLOTPROPERTIES::ulFlags); - auto& dst_i = eax_; + auto& dst_i = mEax; - if(dst_i.lOcclusion != EAXFXSLOT_DEFAULTOCCLUSION) { - dst_df |= eax_occlusion_dirty_bit; + if(dst_i.lOcclusion != EAXFXSLOT_DEFAULTOCCLUSION) + { + dst_df.set(eax_occlusion_dirty_bit); dst_i.lOcclusion = EAXFXSLOT_DEFAULTOCCLUSION; } - if(dst_i.flOcclusionLFRatio != EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO) { - dst_df |= eax_occlusion_lf_ratio_dirty_bit; + if(dst_i.flOcclusionLFRatio != EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO) + { + dst_df.set(eax_occlusion_lf_ratio_dirty_bit); dst_i.flOcclusionLFRatio = EAXFXSLOT_DEFAULTOCCLUSIONLFRATIO; } } -void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df) +void ALeffectslot::eax5_fx_slot_commit(Eax5State& state, std::bitset& dst_df) { eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::guidLoadEffect); eax_fx_slot_commit_property(state, dst_df, &EAX50FXSLOTPROPERTIES::lVolume); @@ -1451,18 +1454,19 @@ void ALeffectslot::eax_set_efx_slot_effect(EaxEffect &effect) #define EAX_PREFIX "[EAX_SET_EFFECT_SLOT_EFFECT] " const auto error = initEffect(0, effect.al_effect_type_, effect.al_effect_props_, - eax_al_context_); - - if(error != AL_NO_ERROR) { - ERR(EAX_PREFIX "%s\n", "Failed to initialize an effect."); + mEaxALContext); + if(error != AL_NO_ERROR) + { + ERR(EAX_PREFIX "Failed to initialize an effect."); return; } - if(mState == SlotState::Initial) { + if(mState == SlotState::Initial) + { mPropsDirty = false; - updateProps(eax_al_context_); + updateProps(mEaxALContext); auto effect_slot_ptr = this; - AddActiveEffectSlots({&effect_slot_ptr, 1}, eax_al_context_); + AddActiveEffectSlots({&effect_slot_ptr, 1}, mEaxALContext); mState = SlotState::Playing; return; } @@ -1488,9 +1492,9 @@ void ALeffectslot::eax_set_efx_slot_gain(ALfloat gain) if(gain == Gain) return; if(gain < 0.0f || gain > 1.0f) - ERR(EAX_PREFIX "Gain out of range (%f)\n", gain); + ERR(EAX_PREFIX "Slot gain out of range ({:f})", gain); - Gain = clampf(gain, 0.0f, 1.0f); + Gain = std::clamp(gain, 0.0f, 1.0f); mPropsDirty = true; #undef EAX_PREFIX @@ -1498,24 +1502,25 @@ void ALeffectslot::eax_set_efx_slot_gain(ALfloat gain) void ALeffectslot::EaxDeleter::operator()(ALeffectslot* effect_slot) { - assert(effect_slot); - eax_delete_al_effect_slot(*effect_slot->eax_al_context_, *effect_slot); + eax_delete_al_effect_slot(*effect_slot->mEaxALContext, *effect_slot); } EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context) { #define EAX_PREFIX "[EAX_MAKE_EFFECT_SLOT] " - std::unique_lock effect_slot_lock{context.mEffectSlotLock}; + std::lock_guard slotlock{context.mEffectSlotLock}; auto& device = *context.mALDevice; - if(context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) { - ERR(EAX_PREFIX "%s\n", "Out of memory."); + if(context.mNumEffectSlots == device.AuxiliaryEffectSlotMax) + { + ERR(EAX_PREFIX "Out of memory."); return nullptr; } - if(!EnsureEffectSlots(&context, 1)) { - ERR(EAX_PREFIX "%s\n", "Failed to ensure."); + if(!EnsureEffectSlots(&context, 1)) + { + ERR(EAX_PREFIX "Failed to ensure."); return nullptr; } @@ -1528,10 +1533,11 @@ void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot) { #define EAX_PREFIX "[EAX_DELETE_EFFECT_SLOT] " - std::lock_guard effect_slot_lock{context.mEffectSlotLock}; + std::lock_guard slotlock{context.mEffectSlotLock}; - if(ReadRef(effect_slot.ref) != 0) { - ERR(EAX_PREFIX "Deleting in-use effect slot %u.\n", effect_slot.id); + if(effect_slot.ref.load(std::memory_order_relaxed) != 0) + { + ERR(EAX_PREFIX "Deleting in-use effect slot {}.", effect_slot.id); return; } diff --git a/3rdparty/openal/al/auxeffectslot.h b/3rdparty/openal/al/auxeffectslot.h index 1ad0ffc4d549..9c903cf5a2d0 100644 --- a/3rdparty/openal/al/auxeffectslot.h +++ b/3rdparty/openal/al/auxeffectslot.h @@ -1,24 +1,27 @@ #ifndef AL_AUXEFFECTSLOT_H #define AL_AUXEFFECTSLOT_H +#include "config.h" + +#include #include -#include +#include +#include #include +#include #include "AL/al.h" #include "AL/alc.h" -#include "AL/efx.h" -#include "alc/device.h" -#include "alc/effects/base.h" #include "almalloc.h" -#include "atomic.h" +#include "alnumeric.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "intrusive_ptr.h" -#include "vector.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include +#include "eax/api.h" #include "eax/call.h" #include "eax/effect.h" #include "eax/exception.h" @@ -27,10 +30,8 @@ #endif // ALSOFT_EAX struct ALbuffer; -struct ALeffect; -struct WetBuffer; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX class EaxFxSlotException : public EaxException { public: explicit EaxFxSlotException(const char* message) @@ -39,10 +40,8 @@ class EaxFxSlotException : public EaxException { }; #endif // ALSOFT_EAX -enum class SlotState : ALenum { - Initial = AL_INITIAL, - Playing = AL_PLAYING, - Stopped = AL_STOPPED, +enum class SlotState : bool { + Initial, Playing, }; struct ALeffectslot { @@ -52,73 +51,71 @@ struct ALeffectslot { ALeffectslot *Target{nullptr}; ALbuffer *Buffer{nullptr}; - struct { + struct EffectData { EffectSlotType Type{EffectSlotType::None}; - EffectProps Props{}; + EffectProps Props; al::intrusive_ptr State; - } Effect; + }; + EffectData Effect; bool mPropsDirty{true}; SlotState mState{SlotState::Initial}; - RefCount ref{0u}; + std::atomic ref{0u}; EffectSlot *mSlot{nullptr}; /* Self ID */ ALuint id{}; - ALeffectslot(ALCcontext *context); + explicit ALeffectslot(ALCcontext *context); ALeffectslot(const ALeffectslot&) = delete; ALeffectslot& operator=(const ALeffectslot&) = delete; ~ALeffectslot(); ALenum initEffect(ALuint effectId, ALenum effectType, const EffectProps &effectProps, ALCcontext *context); - void updateProps(ALCcontext *context); + void updateProps(ALCcontext *context) const; static void SetName(ALCcontext *context, ALuint id, std::string_view name); - /* This can be new'd for the context's default effect slot. */ - DEF_NEWDEL(ALeffectslot) - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX public: void eax_initialize(ALCcontext& al_context, EaxFxSlotIndexValue index); - EaxFxSlotIndexValue eax_get_index() const noexcept { return eax_fx_slot_index_; } - const EAX50FXSLOTPROPERTIES& eax_get_eax_fx_slot() const noexcept - { return eax_; } + [[nodiscard]] + auto eax_get_index() const noexcept -> EaxFxSlotIndexValue { return mEaxFXSlotIndex; } + [[nodiscard]] + auto eax_get_eax_fx_slot() const noexcept -> const EAX50FXSLOTPROPERTIES& { return mEax; } // Returns `true` if all sources should be updated, or `false` otherwise. - bool eax_dispatch(const EaxCall& call) + [[nodiscard]] auto eax_dispatch(const EaxCall& call) -> bool { return call.is_get() ? eax_get(call) : eax_set(call); } void eax_commit(); private: - static constexpr auto eax_load_effect_dirty_bit = EaxDirtyFlags{1} << 0; - static constexpr auto eax_volume_dirty_bit = EaxDirtyFlags{1} << 1; - static constexpr auto eax_lock_dirty_bit = EaxDirtyFlags{1} << 2; - static constexpr auto eax_flags_dirty_bit = EaxDirtyFlags{1} << 3; - static constexpr auto eax_occlusion_dirty_bit = EaxDirtyFlags{1} << 4; - static constexpr auto eax_occlusion_lf_ratio_dirty_bit = EaxDirtyFlags{1} << 5; + enum { + eax_load_effect_dirty_bit, + eax_volume_dirty_bit, + eax_lock_dirty_bit, + eax_flags_dirty_bit, + eax_occlusion_dirty_bit, + eax_occlusion_lf_ratio_dirty_bit, + eax_dirty_bit_count + }; using Exception = EaxFxSlotException; - using Eax4Props = EAX40FXSLOTPROPERTIES; - struct Eax4State { - Eax4Props i; // Immediate. + EAX40FXSLOTPROPERTIES i; // Immediate. }; - using Eax5Props = EAX50FXSLOTPROPERTIES; - struct Eax5State { - Eax5Props i; // Immediate. + EAX50FXSLOTPROPERTIES i; // Immediate. }; struct EaxRangeValidator { @@ -198,6 +195,17 @@ struct ALeffectslot { } }; + struct Eax5FlagsValidator { + void operator()(unsigned long ulFlags) const + { + EaxRangeValidator{}( + "Flags", + ulFlags, + 0UL, + ~EAX50FXSLOTFLAGS_RESERVED); + } + }; + struct Eax5OcclusionValidator { void operator()(long lOcclusion) const { @@ -220,35 +228,27 @@ struct ALeffectslot { } }; - struct Eax5FlagsValidator { - void operator()(unsigned long ulFlags) const - { - EaxRangeValidator{}( - "Flags", - ulFlags, - 0UL, - ~EAX50FXSLOTFLAGS_RESERVED); - } - }; - struct Eax5AllValidator { void operator()(const EAX50FXSLOTPROPERTIES& all) const { - Eax4AllValidator{}(static_cast(all)); + Eax4GuidLoadEffectValidator{}(all.guidLoadEffect); + Eax4VolumeValidator{}(all.lVolume); + Eax4LockValidator{}(all.lLock); + Eax5FlagsValidator{}(all.ulFlags); Eax5OcclusionValidator{}(all.lOcclusion); Eax5OcclusionLfRatioValidator{}(all.flOcclusionLFRatio); } }; - ALCcontext* eax_al_context_{}; - EaxFxSlotIndexValue eax_fx_slot_index_{}; - int eax_version_{}; // Current EAX version. - EaxDirtyFlags eax_df_{}; // Dirty flags for the current EAX version. - EaxEffectUPtr eax_effect_{}; - Eax5State eax123_{}; // EAX1/EAX2/EAX3 state. - Eax4State eax4_{}; // EAX4 state. - Eax5State eax5_{}; // EAX5 state. - Eax5Props eax_{}; // Current EAX state. + ALCcontext* mEaxALContext{}; + EaxFxSlotIndexValue mEaxFXSlotIndex{}; + int mEaxVersion{}; // Current EAX version. + std::bitset mEaxDf; // Dirty flags for the current EAX version. + EaxEffectUPtr mEaxEffect; + Eax5State mEax123{}; // EAX1/EAX2/EAX3 state. + Eax4State mEax4{}; // EAX4 state. + Eax5State mEax5{}; // EAX5 state. + EAX50FXSLOTPROPERTIES mEax{}; // Current EAX state. [[noreturn]] static void eax_fail(const char* message); [[noreturn]] static void eax_fail_unknown_effect_id(); @@ -259,12 +259,14 @@ struct ALeffectslot { // validates it, // sets a dirty flag only if the new value differs form the old one, // and assigns the new value. - template - static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, EaxDirtyFlags& dirty_flags) + template + static void eax_fx_slot_set(const EaxCall& call, TProperties& dst, + std::bitset& dirty_flags) { const auto& src = call.get_value(); TValidator{}(src); - dirty_flags |= (dst != src ? TDirtyBit : EaxDirtyFlags{}); + if(dst != src) + dirty_flags.set(DirtyBit); dst = src; } @@ -272,34 +274,34 @@ struct ALeffectslot { // validates it, // sets a dirty flag without comparing the values, // and assigns the new value. - template + template static void eax_fx_slot_set_dirty(const EaxCall& call, TProperties& dst, - EaxDirtyFlags& dirty_flags) + std::bitset& dirty_flags) { const auto& src = call.get_value(); TValidator{}(src); - dirty_flags |= TDirtyBit; + dirty_flags.set(DirtyBit); dst = src; } - constexpr bool eax4_fx_slot_is_legacy() const noexcept - { return eax_fx_slot_index_ < 2; } + [[nodiscard]] constexpr auto eax4_fx_slot_is_legacy() const noexcept -> bool + { return mEaxFXSlotIndex < 2; } void eax4_fx_slot_ensure_unlocked() const; - static ALenum eax_get_efx_effect_type(const GUID& guid); - const GUID& eax_get_eax_default_effect_guid() const noexcept; - long eax_get_eax_default_lock() const noexcept; + [[nodiscard]] static auto eax_get_efx_effect_type(const GUID& guid) -> ALenum; + [[nodiscard]] auto eax_get_eax_default_effect_guid() const noexcept -> const GUID&; + [[nodiscard]] auto eax_get_eax_default_lock() const noexcept -> long; - void eax4_fx_slot_set_defaults(Eax4Props& props) noexcept; - void eax5_fx_slot_set_defaults(Eax5Props& props) noexcept; - void eax4_fx_slot_set_current_defaults(const Eax4Props& props) noexcept; - void eax5_fx_slot_set_current_defaults(const Eax5Props& props) noexcept; + void eax4_fx_slot_set_defaults(EAX40FXSLOTPROPERTIES& props) noexcept; + void eax5_fx_slot_set_defaults(EAX50FXSLOTPROPERTIES& props) noexcept; + void eax4_fx_slot_set_current_defaults(const EAX40FXSLOTPROPERTIES& props) noexcept; + void eax5_fx_slot_set_current_defaults(const EAX50FXSLOTPROPERTIES& props) noexcept; void eax_fx_slot_set_current_defaults(); void eax_fx_slot_set_defaults(); - void eax4_fx_slot_get(const EaxCall& call, const Eax4Props& props) const; - void eax5_fx_slot_get(const EaxCall& call, const Eax5Props& props) const; + static void eax4_fx_slot_get(const EaxCall& call, const EAX40FXSLOTPROPERTIES& props); + static void eax5_fx_slot_get(const EaxCall& call, const EAX50FXSLOTPROPERTIES& props); void eax_fx_slot_get(const EaxCall& call) const; // Returns `true` if all sources should be updated, or `false` otherwise. bool eax_get(const EaxCall& call); @@ -312,7 +314,7 @@ struct ALeffectslot { void eax4_fx_slot_set_all(const EaxCall& call); void eax5_fx_slot_set_all(const EaxCall& call); - bool eax_fx_slot_should_update_sources() const noexcept; + [[nodiscard]] auto eax_fx_slot_should_update_sources() const noexcept -> bool; // Returns `true` if all sources should be updated, or `false` otherwise. bool eax4_fx_slot_set(const EaxCall& call); @@ -324,25 +326,25 @@ struct ALeffectslot { bool eax_set(const EaxCall& call); template< - EaxDirtyFlags TDirtyBit, + size_t DirtyBit, typename TMemberResult, typename TProps, typename TState> - void eax_fx_slot_commit_property(TState& state, EaxDirtyFlags& dst_df, + void eax_fx_slot_commit_property(TState& state, std::bitset& dst_df, TMemberResult TProps::*member) noexcept { auto& src_i = state.i; - auto& dst_i = eax_; + auto& dst_i = mEax; - if((eax_df_ & TDirtyBit) != EaxDirtyFlags{}) + if(mEaxDf.test(DirtyBit)) { - dst_df |= TDirtyBit; + dst_df.set(DirtyBit); dst_i.*member = src_i.*member; } } - void eax4_fx_slot_commit(EaxDirtyFlags& dst_df); - void eax5_fx_slot_commit(Eax5State& state, EaxDirtyFlags& dst_df); + void eax4_fx_slot_commit(std::bitset& dst_df); + void eax5_fx_slot_commit(Eax5State& state, std::bitset& dst_df); // `alAuxiliaryEffectSloti(effect_slot, AL_EFFECTSLOT_EFFECT, effect)` void eax_set_efx_slot_effect(EaxEffect &effect); @@ -363,11 +365,27 @@ struct ALeffectslot { void UpdateAllEffectSlotProps(ALCcontext *context); -#ifdef ALSOFT_EAX +#if ALSOFT_EAX using EaxAlEffectSlotUPtr = std::unique_ptr; EaxAlEffectSlotUPtr eax_create_al_effect_slot(ALCcontext& context); void eax_delete_al_effect_slot(ALCcontext& context, ALeffectslot& effect_slot); #endif // ALSOFT_EAX +struct EffectSlotSubList { + uint64_t FreeMask{~0_u64}; + gsl::owner*> EffectSlots{nullptr}; + + EffectSlotSubList() noexcept = default; + EffectSlotSubList(const EffectSlotSubList&) = delete; + EffectSlotSubList(EffectSlotSubList&& rhs) noexcept + : FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots} + { rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; } + ~EffectSlotSubList(); + + EffectSlotSubList& operator=(const EffectSlotSubList&) = delete; + EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept + { std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; } +}; + #endif diff --git a/3rdparty/openal/al/buffer.cpp b/3rdparty/openal/al/buffer.cpp index 8ba874e4dd98..2450c7029565 100644 --- a/3rdparty/openal/al/buffer.cpp +++ b/3rdparty/openal/al/buffer.cpp @@ -28,16 +28,15 @@ #include #include #include -#include #include #include #include #include #include -#include #include #include #include +#include #include #include @@ -51,14 +50,17 @@ #include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" -#include "atomic.h" +#include "alspan.h" +#include "core/device.h" #include "core/except.h" #include "core/logging.h" +#include "core/resampler_limits.h" #include "core/voice.h" #include "direct_defs.h" +#include "intrusive_ptr.h" #include "opthelpers.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include #include "eax/globals.h" @@ -68,7 +70,9 @@ namespace { -std::optional AmbiLayoutFromEnum(ALenum layout) +using SubListAllocator = al::allocator>; + +constexpr auto AmbiLayoutFromEnum(ALenum layout) noexcept -> std::optional { switch(layout) { @@ -77,17 +81,18 @@ std::optional AmbiLayoutFromEnum(ALenum layout) } return std::nullopt; } -ALenum EnumFromAmbiLayout(AmbiLayout layout) +constexpr auto EnumFromAmbiLayout(AmbiLayout layout) -> ALenum { switch(layout) { case AmbiLayout::FuMa: return AL_FUMA_SOFT; case AmbiLayout::ACN: return AL_ACN_SOFT; } - throw std::runtime_error{"Invalid AmbiLayout: "+std::to_string(int(layout))}; + throw std::runtime_error{fmt::format("Invalid AmbiLayout: {}", + int{al::to_underlying(layout)})}; } -std::optional AmbiScalingFromEnum(ALenum scale) +constexpr auto AmbiScalingFromEnum(ALenum scale) noexcept -> std::optional { switch(scale) { @@ -97,7 +102,7 @@ std::optional AmbiScalingFromEnum(ALenum scale) } return std::nullopt; } -ALenum EnumFromAmbiScaling(AmbiScaling scale) +constexpr auto EnumFromAmbiScaling(AmbiScaling scale) -> ALenum { switch(scale) { @@ -106,11 +111,12 @@ ALenum EnumFromAmbiScaling(AmbiScaling scale) case AmbiScaling::N3D: return AL_N3D_SOFT; case AmbiScaling::UHJ: break; } - throw std::runtime_error{"Invalid AmbiScaling: "+std::to_string(int(scale))}; + throw std::runtime_error{fmt::format("Invalid AmbiScaling: {}", + int{al::to_underlying(scale)})}; } -#ifdef ALSOFT_EAX -std::optional EaxStorageFromEnum(ALenum scale) +#if ALSOFT_EAX +constexpr auto EaxStorageFromEnum(ALenum scale) noexcept -> std::optional { switch(scale) { @@ -120,7 +126,7 @@ std::optional EaxStorageFromEnum(ALenum scale) } return std::nullopt; } -ALenum EnumFromEaxStorage(EaxStorage storage) +constexpr auto EnumFromEaxStorage(EaxStorage storage) -> ALenum { switch(storage) { @@ -128,12 +134,13 @@ ALenum EnumFromEaxStorage(EaxStorage storage) case EaxStorage::Accessible: return AL_STORAGE_ACCESSIBLE; case EaxStorage::Hardware: return AL_STORAGE_HARDWARE; } - throw std::runtime_error{"Invalid EaxStorage: "+std::to_string(int(storage))}; + throw std::runtime_error{fmt::format("Invalid EaxStorage: {}", + int{al::to_underlying(storage)})}; } -bool eax_x_ram_check_availability(const ALCdevice &device, const ALbuffer &buffer, - const ALuint newsize) noexcept +auto eax_x_ram_check_availability(const al::Device &device, const ALbuffer &buffer, + const ALuint newsize) noexcept -> bool { ALuint freemem{device.eax_x_ram_free_size}; /* If the buffer is currently in "hardware", add its memory to the free @@ -144,7 +151,7 @@ bool eax_x_ram_check_availability(const ALCdevice &device, const ALbuffer &buffe return freemem >= newsize; } -void eax_x_ram_apply(ALCdevice &device, ALbuffer &buffer) noexcept +void eax_x_ram_apply(al::Device &device, ALbuffer &buffer) noexcept { if(buffer.eax_x_ram_is_hardware) return; @@ -156,7 +163,7 @@ void eax_x_ram_apply(ALCdevice &device, ALbuffer &buffer) noexcept } } -void eax_x_ram_clear(ALCdevice& al_device, ALbuffer& al_buffer) +void eax_x_ram_clear(al::Device& al_device, ALbuffer& al_buffer) noexcept { if(al_buffer.eax_x_ram_is_hardware) al_device.eax_x_ram_free_size += al_buffer.OriginalSize; @@ -172,8 +179,9 @@ constexpr ALbitfieldSOFT INVALID_MAP_FLAGS{~unsigned(AL_MAP_READ_BIT_SOFT | AL_M AL_MAP_PERSISTENT_BIT_SOFT)}; -bool EnsureBuffers(ALCdevice *device, size_t needed) -{ +[[nodiscard]] +auto EnsureBuffers(al::Device *device, size_t needed) noexcept -> bool +try { size_t count{std::accumulate(device->BufferList.cbegin(), device->BufferList.cend(), 0_uz, [](size_t cur, const BufferSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; @@ -183,21 +191,20 @@ bool EnsureBuffers(ALCdevice *device, size_t needed) if(device->BufferList.size() >= 1<<25) UNLIKELY return false; - device->BufferList.emplace_back(); - auto sublist = device->BufferList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Buffers = static_cast(al_calloc(alignof(ALbuffer), sizeof(ALbuffer)*64)); - if(!sublist->Buffers) UNLIKELY - { - device->BufferList.pop_back(); - return false; - } - count += 64; + BufferSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Buffers = SubListAllocator{}.allocate(1); + device->BufferList.emplace_back(std::move(sublist)); + count += std::tuple_size_v; } return true; } +catch(...) { + return false; +} -ALbuffer *AllocBuffer(ALCdevice *device) +[[nodiscard]] +auto AllocBuffer(al::Device *device) noexcept -> ALbuffer* { auto sublist = std::find_if(device->BufferList.begin(), device->BufferList.end(), [](const BufferSubList &entry) noexcept -> bool @@ -206,7 +213,7 @@ ALbuffer *AllocBuffer(ALCdevice *device) auto slidx = static_cast(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALbuffer *buffer{al::construct_at(sublist->Buffers + slidx)}; + ALbuffer *buffer{al::construct_at(al::to_address(sublist->Buffers->begin() + slidx))}; /* Add 1 to avoid buffer ID 0. */ buffer->id = ((lidx<<6) | slidx) + 1; @@ -216,9 +223,9 @@ ALbuffer *AllocBuffer(ALCdevice *device) return buffer; } -void FreeBuffer(ALCdevice *device, ALbuffer *buffer) +void FreeBuffer(al::Device *device, ALbuffer *buffer) { -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_x_ram_clear(*device, *buffer); #endif // ALSOFT_EAX @@ -233,7 +240,8 @@ void FreeBuffer(ALCdevice *device, ALbuffer *buffer) device->BufferList[lidx].FreeMask |= 1_u64 << slidx; } -inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) +[[nodiscard]] +auto LookupBuffer(al::Device *device, ALuint id) noexcept -> ALbuffer* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -243,11 +251,11 @@ inline ALbuffer *LookupBuffer(ALCdevice *device, ALuint id) BufferSubList &sublist = device->BufferList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Buffers + slidx; + return al::to_address(sublist.Buffers->begin() + slidx); } - -ALuint SanitizeAlignment(FmtType type, ALuint align) +[[nodiscard]] +constexpr auto SanitizeAlignment(FmtType type, ALuint align) noexcept -> ALuint { if(align == 0) { @@ -267,47 +275,58 @@ ALuint SanitizeAlignment(FmtType type, ALuint align) if(type == FmtIMA4) { /* IMA4 block alignment must be a multiple of 8, plus 1. */ - if((align&7) == 1) return static_cast(align); + if((align&7) == 1) return align; return 0; } if(type == FmtMSADPCM) { /* MSADPCM block alignment must be a multiple of 2. */ - if((align&1) == 0) return static_cast(align); + if((align&1) == 0) return align; return 0; } - return static_cast(align); + return align; } /** Loads the specified data into the buffer, using the specified format. */ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, - const FmtChannels DstChannels, const FmtType DstType, const std::byte *SrcData, + const FmtChannels DstChannels, const FmtType DstType, const al::span SrcData, ALbitfieldSOFT access) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY - return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) + context->throw_error(AL_INVALID_OPERATION, "Modifying storage for in-use buffer {}", ALBuf->id); const ALuint unpackalign{ALBuf->UnpackAlign}; const ALuint align{SanitizeAlignment(DstType, unpackalign)}; - if(align < 1) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u for %s samples", + if(align < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack alignment {} for {} samples", unpackalign, NameFromFormat(DstType)); const ALuint ambiorder{IsBFormat(DstChannels) ? ALBuf->UnpackAmbiOrder : (IsUHJ(DstChannels) ? 1 : 0)}; + if(ambiorder > 3) + { + if(ALBuf->mAmbiLayout == AmbiLayout::FuMa) + context->throw_error(AL_INVALID_OPERATION, + "Cannot load {}{} order B-Format data with FuMa layout", ALBuf->mAmbiOrder, + GetCounterSuffix(ALBuf->mAmbiOrder)); + if(ALBuf->mAmbiScaling == AmbiScaling::FuMa) + context->throw_error(AL_INVALID_OPERATION, + "Cannot load {}{} order B-Format data with FuMa scaling", ALBuf->mAmbiOrder, + GetCounterSuffix(ALBuf->mAmbiOrder)); + } if((access&AL_PRESERVE_DATA_BIT_SOFT)) { /* Can only preserve data with the same format and alignment. */ - if(ALBuf->mChannels != DstChannels || ALBuf->mType != DstType) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched format"); - if(ALBuf->mBlockAlign != align) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched alignment"); - if(ALBuf->mAmbiOrder != ambiorder) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Preserving data of mismatched order"); + if(ALBuf->mChannels != DstChannels || ALBuf->mType != DstType) + context->throw_error(AL_INVALID_VALUE, "Preserving data of mismatched format"); + if(ALBuf->mBlockAlign != align) + context->throw_error(AL_INVALID_VALUE, "Preserving data of mismatched alignment"); + if(ALBuf->mAmbiOrder != ambiorder) + context->throw_error(AL_INVALID_VALUE, "Preserving data of mismatched order"); } /* Convert the size in bytes to blocks using the unpack block alignment. */ @@ -316,28 +335,28 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, ((DstType == FmtIMA4) ? (align-1)/2 + 4 : (DstType == FmtMSADPCM) ? (align-2)/2 + 7 : (align * BytesFromFmt(DstType)))}; - if((size%BlockSize) != 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Data size %d is not a multiple of frame size %d (%d unpack alignment)", + if((size%BlockSize) != 0) + context->throw_error(AL_INVALID_VALUE, + "Data size {} is not a multiple of frame size {} ({} unpack alignment)", size, BlockSize, align); const ALuint blocks{size / BlockSize}; - if(blocks > std::numeric_limits::max()/align) UNLIKELY - return context->setError(AL_OUT_OF_MEMORY, - "Buffer size overflow, %d blocks x %d samples per block", blocks, align); - if(blocks > std::numeric_limits::max()/BlockSize) UNLIKELY - return context->setError(AL_OUT_OF_MEMORY, - "Buffer size overflow, %d frames x %d bytes per frame", blocks, BlockSize); + if(blocks > std::numeric_limits::max()/align) + context->throw_error(AL_OUT_OF_MEMORY, + "Buffer size overflow, {} blocks x {} samples per block", blocks, align); + if(blocks > std::numeric_limits::max()/BlockSize) + context->throw_error(AL_OUT_OF_MEMORY, + "Buffer size overflow, {} frames x {} bytes per frame", blocks, BlockSize); const size_t newsize{static_cast(blocks) * BlockSize}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(ALBuf->eax_x_ram_mode == EaxStorage::Hardware) { - ALCdevice &device = *context->mALDevice; + auto &device = *context->mALDevice; if(!eax_x_ram_check_availability(device, *ALBuf, size)) - return context->setError(AL_OUT_OF_MEMORY, - "Out of X-RAM memory (avail: %u, needed: %u)", device.eax_x_ram_free_size, size); + context->throw_error(AL_OUT_OF_MEMORY, "Out of X-RAM memory (avail: {}, needed: {})", + device.eax_x_ram_free_size, size); } #endif @@ -352,18 +371,18 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, auto newdata = decltype(ALBuf->mDataStorage)(newsize, std::byte{}); if((access&AL_PRESERVE_DATA_BIT_SOFT)) { - const size_t tocopy{minz(newdata.size(), ALBuf->mDataStorage.size())}; + const size_t tocopy{std::min(newdata.size(), ALBuf->mDataStorage.size())}; std::copy_n(ALBuf->mDataStorage.begin(), tocopy, newdata.begin()); } newdata.swap(ALBuf->mDataStorage); } ALBuf->mData = ALBuf->mDataStorage; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_x_ram_clear(*context->mALDevice, *ALBuf); #endif - if(SrcData != nullptr && !ALBuf->mData.empty()) - std::copy_n(SrcData, blocks*BlockSize, ALBuf->mData.begin()); + if(!SrcData.empty() && !ALBuf->mData.empty()) + std::copy_n(SrcData.begin(), blocks*BlockSize, ALBuf->mData.begin()); ALBuf->mBlockAlign = (DstType == FmtIMA4 || DstType == FmtMSADPCM) ? align : 1; ALBuf->OriginalSize = size; @@ -382,7 +401,7 @@ void LoadData(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALuint size, ALBuf->mLoopStart = 0; ALBuf->mLoopEnd = ALBuf->mSampleLen; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(eax_g_is_enabled && ALBuf->eax_x_ram_mode == EaxStorage::Hardware) eax_x_ram_apply(*context->mALDevice, *ALBuf); #endif @@ -393,8 +412,8 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, ALBUFFERCALLBACKTYPESOFT callback, void *userptr) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY - return context->setError(AL_INVALID_OPERATION, "Modifying callback for in-use buffer %u", + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) + context->throw_error(AL_INVALID_OPERATION, "Modifying callback for in-use buffer {}", ALBuf->id); const ALuint ambiorder{IsBFormat(DstChannels) ? ALBuf->UnpackAmbiOrder : @@ -402,6 +421,10 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, const ALuint unpackalign{ALBuf->UnpackAlign}; const ALuint align{SanitizeAlignment(DstType, unpackalign)}; + if(align < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack alignment {} for {} samples", + unpackalign, NameFromFormat(DstType)); + const ALuint BlockSize{ChannelsFromFmt(DstChannels, ambiorder) * ((DstType == FmtIMA4) ? (align-1)/2 + 4 : (DstType == FmtMSADPCM) ? (align-2)/2 + 7 : @@ -420,7 +443,7 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, BufferVectorType(line_blocks*BlockSize).swap(ALBuf->mDataStorage); ALBuf->mData = ALBuf->mDataStorage; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_x_ram_clear(*context->mALDevice, *ALBuf); #endif @@ -442,17 +465,17 @@ void PrepareCallback(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, } /** Prepares the buffer to use caller-specified storage. */ -void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, +void PrepareUserPtr(ALCcontext *context [[maybe_unused]], ALbuffer *ALBuf, ALsizei freq, const FmtChannels DstChannels, const FmtType DstType, std::byte *sdata, const ALuint sdatalen) { - if(ReadRef(ALBuf->ref) != 0 || ALBuf->MappedAccess != 0) UNLIKELY - return context->setError(AL_INVALID_OPERATION, "Modifying storage for in-use buffer %u", + if(ALBuf->ref.load(std::memory_order_relaxed) != 0 || ALBuf->MappedAccess != 0) + context->throw_error(AL_INVALID_OPERATION, "Modifying storage for in-use buffer {}", ALBuf->id); const ALuint unpackalign{ALBuf->UnpackAlign}; const ALuint align{SanitizeAlignment(DstType, unpackalign)}; - if(align < 1) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u for %s samples", + if(align < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack alignment {} for {} samples", unpackalign, NameFromFormat(DstType)); auto get_type_alignment = [](const FmtType type) noexcept -> ALuint @@ -464,6 +487,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, { case FmtUByte: return alignof(ALubyte); case FmtShort: return alignof(ALshort); + case FmtInt: return alignof(ALint); case FmtFloat: return alignof(ALfloat); case FmtDouble: return alignof(ALdouble); case FmtMulaw: return alignof(ALubyte); @@ -475,7 +499,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, }; const auto typealign = get_type_alignment(DstType); if((reinterpret_cast(sdata) & (typealign-1)) != 0) - return context->setError(AL_INVALID_VALUE, "Pointer %p is misaligned for %s samples (%u)", + context->throw_error(AL_INVALID_VALUE, "Pointer {} is misaligned for {} samples ({})", static_cast(sdata), NameFromFormat(DstType), typealign); const ALuint ambiorder{IsBFormat(DstChannels) ? ALBuf->UnpackAmbiOrder : @@ -487,34 +511,33 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ((DstType == FmtIMA4) ? (align-1)/2 + 4 : (DstType == FmtMSADPCM) ? (align-2)/2 + 7 : (align * BytesFromFmt(DstType)))}; - if((sdatalen%BlockSize) != 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Data size %u is not a multiple of frame size %u (%u unpack alignment)", + if((sdatalen%BlockSize) != 0) + context->throw_error(AL_INVALID_VALUE, + "Data size {} is not a multiple of frame size {} ({} unpack alignment)", sdatalen, BlockSize, align); const ALuint blocks{sdatalen / BlockSize}; - if(blocks > std::numeric_limits::max()/align) UNLIKELY - return context->setError(AL_OUT_OF_MEMORY, - "Buffer size overflow, %d blocks x %d samples per block", blocks, align); - if(blocks > std::numeric_limits::max()/BlockSize) UNLIKELY - return context->setError(AL_OUT_OF_MEMORY, - "Buffer size overflow, %d frames x %d bytes per frame", blocks, BlockSize); + if(blocks > std::numeric_limits::max()/align) + context->throw_error(AL_OUT_OF_MEMORY, + "Buffer size overflow, {} blocks x {} samples per block", blocks, align); + if(blocks > std::numeric_limits::max()/BlockSize) + context->throw_error(AL_OUT_OF_MEMORY, + "Buffer size overflow, {} frames x {} bytes per frame", blocks, BlockSize); -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(ALBuf->eax_x_ram_mode == EaxStorage::Hardware) { - ALCdevice &device = *context->mALDevice; + auto &device = *context->mALDevice; if(!eax_x_ram_check_availability(device, *ALBuf, sdatalen)) - return context->setError(AL_OUT_OF_MEMORY, - "Out of X-RAM memory (avail: %u, needed: %u)", device.eax_x_ram_free_size, - sdatalen); + context->throw_error(AL_OUT_OF_MEMORY, "Out of X-RAM memory (avail: {}, needed: {})", + device.eax_x_ram_free_size, sdatalen); } #endif decltype(ALBuf->mDataStorage){}.swap(ALBuf->mDataStorage); - ALBuf->mData = {static_cast(sdata), sdatalen}; + ALBuf->mData = al::span{sdata, sdatalen}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_x_ram_clear(*context->mALDevice, *ALBuf); #endif @@ -534,7 +557,7 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, ALBuf->mLoopStart = 0; ALBuf->mLoopEnd = ALBuf->mSampleLen; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(ALBuf->eax_x_ram_mode == EaxStorage::Hardware) eax_x_ram_apply(*context->mALDevice, *ALBuf); #endif @@ -542,184 +565,184 @@ void PrepareUserPtr(ALCcontext *context, ALbuffer *ALBuf, ALsizei freq, struct DecompResult { FmtChannels channels; FmtType type; }; -std::optional DecomposeUserFormat(ALenum format) +auto DecomposeUserFormat(ALenum format) noexcept -> std::optional { struct FormatMap { ALenum format; - FmtChannels channels; - FmtType type; + DecompResult result; }; - static const std::array UserFmtList{{ - { AL_FORMAT_MONO8, FmtMono, FmtUByte }, - { AL_FORMAT_MONO16, FmtMono, FmtShort }, - { AL_FORMAT_MONO_FLOAT32, FmtMono, FmtFloat }, - { AL_FORMAT_MONO_DOUBLE_EXT, FmtMono, FmtDouble }, - { AL_FORMAT_MONO_IMA4, FmtMono, FmtIMA4 }, - { AL_FORMAT_MONO_MSADPCM_SOFT, FmtMono, FmtMSADPCM }, - { AL_FORMAT_MONO_MULAW, FmtMono, FmtMulaw }, - { AL_FORMAT_MONO_ALAW_EXT, FmtMono, FmtAlaw }, - - { AL_FORMAT_STEREO8, FmtStereo, FmtUByte }, - { AL_FORMAT_STEREO16, FmtStereo, FmtShort }, - { AL_FORMAT_STEREO_FLOAT32, FmtStereo, FmtFloat }, - { AL_FORMAT_STEREO_DOUBLE_EXT, FmtStereo, FmtDouble }, - { AL_FORMAT_STEREO_IMA4, FmtStereo, FmtIMA4 }, - { AL_FORMAT_STEREO_MSADPCM_SOFT, FmtStereo, FmtMSADPCM }, - { AL_FORMAT_STEREO_MULAW, FmtStereo, FmtMulaw }, - { AL_FORMAT_STEREO_ALAW_EXT, FmtStereo, FmtAlaw }, - - { AL_FORMAT_REAR8, FmtRear, FmtUByte }, - { AL_FORMAT_REAR16, FmtRear, FmtShort }, - { AL_FORMAT_REAR32, FmtRear, FmtFloat }, - { AL_FORMAT_REAR_MULAW, FmtRear, FmtMulaw }, - - { AL_FORMAT_QUAD8_LOKI, FmtQuad, FmtUByte }, - { AL_FORMAT_QUAD16_LOKI, FmtQuad, FmtShort }, - - { AL_FORMAT_QUAD8, FmtQuad, FmtUByte }, - { AL_FORMAT_QUAD16, FmtQuad, FmtShort }, - { AL_FORMAT_QUAD32, FmtQuad, FmtFloat }, - { AL_FORMAT_QUAD_MULAW, FmtQuad, FmtMulaw }, - - { AL_FORMAT_51CHN8, FmtX51, FmtUByte }, - { AL_FORMAT_51CHN16, FmtX51, FmtShort }, - { AL_FORMAT_51CHN32, FmtX51, FmtFloat }, - { AL_FORMAT_51CHN_MULAW, FmtX51, FmtMulaw }, - - { AL_FORMAT_61CHN8, FmtX61, FmtUByte }, - { AL_FORMAT_61CHN16, FmtX61, FmtShort }, - { AL_FORMAT_61CHN32, FmtX61, FmtFloat }, - { AL_FORMAT_61CHN_MULAW, FmtX61, FmtMulaw }, - - { AL_FORMAT_71CHN8, FmtX71, FmtUByte }, - { AL_FORMAT_71CHN16, FmtX71, FmtShort }, - { AL_FORMAT_71CHN32, FmtX71, FmtFloat }, - { AL_FORMAT_71CHN_MULAW, FmtX71, FmtMulaw }, - - { AL_FORMAT_BFORMAT2D_8, FmtBFormat2D, FmtUByte }, - { AL_FORMAT_BFORMAT2D_16, FmtBFormat2D, FmtShort }, - { AL_FORMAT_BFORMAT2D_FLOAT32, FmtBFormat2D, FmtFloat }, - { AL_FORMAT_BFORMAT2D_MULAW, FmtBFormat2D, FmtMulaw }, - - { AL_FORMAT_BFORMAT3D_8, FmtBFormat3D, FmtUByte }, - { AL_FORMAT_BFORMAT3D_16, FmtBFormat3D, FmtShort }, - { AL_FORMAT_BFORMAT3D_FLOAT32, FmtBFormat3D, FmtFloat }, - { AL_FORMAT_BFORMAT3D_MULAW, FmtBFormat3D, FmtMulaw }, - - { AL_FORMAT_UHJ2CHN8_SOFT, FmtUHJ2, FmtUByte }, - { AL_FORMAT_UHJ2CHN16_SOFT, FmtUHJ2, FmtShort }, - { AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, FmtUHJ2, FmtFloat }, - { AL_FORMAT_UHJ2CHN_MULAW_SOFT, FmtUHJ2, FmtMulaw }, - { AL_FORMAT_UHJ2CHN_ALAW_SOFT, FmtUHJ2, FmtAlaw }, - { AL_FORMAT_UHJ2CHN_IMA4_SOFT, FmtUHJ2, FmtIMA4 }, - { AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, FmtUHJ2, FmtMSADPCM }, - - { AL_FORMAT_UHJ3CHN8_SOFT, FmtUHJ3, FmtUByte }, - { AL_FORMAT_UHJ3CHN16_SOFT, FmtUHJ3, FmtShort }, - { AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, FmtUHJ3, FmtFloat }, - { AL_FORMAT_UHJ3CHN_MULAW_SOFT, FmtUHJ3, FmtMulaw }, - { AL_FORMAT_UHJ3CHN_ALAW_SOFT, FmtUHJ3, FmtAlaw }, - - { AL_FORMAT_UHJ4CHN8_SOFT, FmtUHJ4, FmtUByte }, - { AL_FORMAT_UHJ4CHN16_SOFT, FmtUHJ4, FmtShort }, - { AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, FmtUHJ4, FmtFloat }, - { AL_FORMAT_UHJ4CHN_MULAW_SOFT, FmtUHJ4, FmtMulaw }, - { AL_FORMAT_UHJ4CHN_ALAW_SOFT, FmtUHJ4, FmtAlaw }, - }}; - - for(const auto &fmt : UserFmtList) - { - if(fmt.format == format) - return DecompResult{fmt.channels, fmt.type}; - } + static constexpr std::array UserFmtList{ + FormatMap{AL_FORMAT_MONO8, {FmtMono, FmtUByte} }, + FormatMap{AL_FORMAT_MONO16, {FmtMono, FmtShort} }, + FormatMap{AL_FORMAT_MONO_I32, {FmtMono, FmtInt} }, + FormatMap{AL_FORMAT_MONO_FLOAT32, {FmtMono, FmtFloat} }, + FormatMap{AL_FORMAT_MONO_DOUBLE_EXT, {FmtMono, FmtDouble} }, + FormatMap{AL_FORMAT_MONO_IMA4, {FmtMono, FmtIMA4} }, + FormatMap{AL_FORMAT_MONO_MSADPCM_SOFT, {FmtMono, FmtMSADPCM}}, + FormatMap{AL_FORMAT_MONO_MULAW, {FmtMono, FmtMulaw} }, + FormatMap{AL_FORMAT_MONO_ALAW_EXT, {FmtMono, FmtAlaw} }, + + FormatMap{AL_FORMAT_STEREO8, {FmtStereo, FmtUByte} }, + FormatMap{AL_FORMAT_STEREO16, {FmtStereo, FmtShort} }, + FormatMap{AL_FORMAT_STEREO_I32, {FmtStereo, FmtInt} }, + FormatMap{AL_FORMAT_STEREO_FLOAT32, {FmtStereo, FmtFloat} }, + FormatMap{AL_FORMAT_STEREO_DOUBLE_EXT, {FmtStereo, FmtDouble} }, + FormatMap{AL_FORMAT_STEREO_IMA4, {FmtStereo, FmtIMA4} }, + FormatMap{AL_FORMAT_STEREO_MSADPCM_SOFT, {FmtStereo, FmtMSADPCM}}, + FormatMap{AL_FORMAT_STEREO_MULAW, {FmtStereo, FmtMulaw} }, + FormatMap{AL_FORMAT_STEREO_ALAW_EXT, {FmtStereo, FmtAlaw} }, + + FormatMap{AL_FORMAT_REAR8, {FmtRear, FmtUByte}}, + FormatMap{AL_FORMAT_REAR16, {FmtRear, FmtShort}}, + FormatMap{AL_FORMAT_REAR32, {FmtRear, FmtFloat}}, + FormatMap{AL_FORMAT_REAR_I32, {FmtRear, FmtInt} }, + FormatMap{AL_FORMAT_REAR_FLOAT32, {FmtRear, FmtFloat}}, + FormatMap{AL_FORMAT_REAR_MULAW, {FmtRear, FmtMulaw}}, + + FormatMap{AL_FORMAT_QUAD8_LOKI, {FmtQuad, FmtUByte}}, + FormatMap{AL_FORMAT_QUAD16_LOKI, {FmtQuad, FmtShort}}, + + FormatMap{AL_FORMAT_QUAD8, {FmtQuad, FmtUByte}}, + FormatMap{AL_FORMAT_QUAD16, {FmtQuad, FmtShort}}, + FormatMap{AL_FORMAT_QUAD32, {FmtQuad, FmtFloat}}, + FormatMap{AL_FORMAT_QUAD_I32, {FmtQuad, FmtInt} }, + FormatMap{AL_FORMAT_QUAD_FLOAT32, {FmtQuad, FmtFloat}}, + FormatMap{AL_FORMAT_QUAD_MULAW, {FmtQuad, FmtMulaw}}, + + FormatMap{AL_FORMAT_51CHN8, {FmtX51, FmtUByte}}, + FormatMap{AL_FORMAT_51CHN16, {FmtX51, FmtShort}}, + FormatMap{AL_FORMAT_51CHN32, {FmtX51, FmtFloat}}, + FormatMap{AL_FORMAT_51CHN_I32, {FmtX51, FmtInt} }, + FormatMap{AL_FORMAT_51CHN_FLOAT32, {FmtX51, FmtFloat}}, + FormatMap{AL_FORMAT_51CHN_MULAW, {FmtX51, FmtMulaw}}, + + FormatMap{AL_FORMAT_61CHN8, {FmtX61, FmtUByte}}, + FormatMap{AL_FORMAT_61CHN16, {FmtX61, FmtShort}}, + FormatMap{AL_FORMAT_61CHN32, {FmtX61, FmtFloat}}, + FormatMap{AL_FORMAT_61CHN_I32, {FmtX61, FmtInt} }, + FormatMap{AL_FORMAT_61CHN_FLOAT32, {FmtX61, FmtFloat}}, + FormatMap{AL_FORMAT_61CHN_MULAW, {FmtX61, FmtMulaw}}, + + FormatMap{AL_FORMAT_71CHN8, {FmtX71, FmtUByte}}, + FormatMap{AL_FORMAT_71CHN16, {FmtX71, FmtShort}}, + FormatMap{AL_FORMAT_71CHN32, {FmtX71, FmtFloat}}, + FormatMap{AL_FORMAT_71CHN_I32, {FmtX71, FmtInt} }, + FormatMap{AL_FORMAT_71CHN_FLOAT32, {FmtX71, FmtFloat}}, + FormatMap{AL_FORMAT_71CHN_MULAW, {FmtX71, FmtMulaw}}, + + FormatMap{AL_FORMAT_BFORMAT2D_8, {FmtBFormat2D, FmtUByte}}, + FormatMap{AL_FORMAT_BFORMAT2D_16, {FmtBFormat2D, FmtShort}}, + FormatMap{AL_FORMAT_BFORMAT2D_I32, {FmtBFormat2D, FmtInt} }, + FormatMap{AL_FORMAT_BFORMAT2D_FLOAT32, {FmtBFormat2D, FmtFloat}}, + FormatMap{AL_FORMAT_BFORMAT2D_MULAW, {FmtBFormat2D, FmtMulaw}}, + + FormatMap{AL_FORMAT_BFORMAT3D_8, {FmtBFormat3D, FmtUByte}}, + FormatMap{AL_FORMAT_BFORMAT3D_16, {FmtBFormat3D, FmtShort}}, + FormatMap{AL_FORMAT_BFORMAT3D_I32, {FmtBFormat3D, FmtInt} }, + FormatMap{AL_FORMAT_BFORMAT3D_FLOAT32, {FmtBFormat3D, FmtFloat}}, + FormatMap{AL_FORMAT_BFORMAT3D_MULAW, {FmtBFormat3D, FmtMulaw}}, + + FormatMap{AL_FORMAT_UHJ2CHN8_SOFT, {FmtUHJ2, FmtUByte} }, + FormatMap{AL_FORMAT_UHJ2CHN16_SOFT, {FmtUHJ2, FmtShort} }, + FormatMap{AL_FORMAT_UHJ2CHN_I32_SOFT, {FmtUHJ2, FmtInt} }, + FormatMap{AL_FORMAT_UHJ2CHN_FLOAT32_SOFT, {FmtUHJ2, FmtFloat} }, + FormatMap{AL_FORMAT_UHJ2CHN_MULAW_SOFT, {FmtUHJ2, FmtMulaw} }, + FormatMap{AL_FORMAT_UHJ2CHN_ALAW_SOFT, {FmtUHJ2, FmtAlaw} }, + FormatMap{AL_FORMAT_UHJ2CHN_IMA4_SOFT, {FmtUHJ2, FmtIMA4} }, + FormatMap{AL_FORMAT_UHJ2CHN_MSADPCM_SOFT, {FmtUHJ2, FmtMSADPCM}}, + + FormatMap{AL_FORMAT_UHJ3CHN8_SOFT, {FmtUHJ3, FmtUByte}}, + FormatMap{AL_FORMAT_UHJ3CHN16_SOFT, {FmtUHJ3, FmtShort}}, + FormatMap{AL_FORMAT_UHJ3CHN_I32_SOFT, {FmtUHJ3, FmtInt} }, + FormatMap{AL_FORMAT_UHJ3CHN_FLOAT32_SOFT, {FmtUHJ3, FmtFloat}}, + FormatMap{AL_FORMAT_UHJ3CHN_MULAW_SOFT, {FmtUHJ3, FmtMulaw}}, + FormatMap{AL_FORMAT_UHJ3CHN_ALAW_SOFT, {FmtUHJ3, FmtAlaw} }, + + FormatMap{AL_FORMAT_UHJ4CHN8_SOFT, {FmtUHJ4, FmtUByte}}, + FormatMap{AL_FORMAT_UHJ4CHN16_SOFT, {FmtUHJ4, FmtShort}}, + FormatMap{AL_FORMAT_UHJ4CHN_I32_SOFT, {FmtUHJ4, FmtInt} }, + FormatMap{AL_FORMAT_UHJ4CHN_FLOAT32_SOFT, {FmtUHJ4, FmtFloat}}, + FormatMap{AL_FORMAT_UHJ4CHN_MULAW_SOFT, {FmtUHJ4, FmtMulaw}}, + FormatMap{AL_FORMAT_UHJ4CHN_ALAW_SOFT, {FmtUHJ4, FmtAlaw} }, + }; + + auto iter = std::find_if(UserFmtList.cbegin(), UserFmtList.cend(), + [format](const FormatMap &fmt) noexcept { return fmt.format == format; }); + if(iter != UserFmtList.cend()) + return iter->result; return std::nullopt; } } // namespace -AL_API DECL_FUNC2(void, alGenBuffers, ALsizei, ALuint*) +AL_API DECL_FUNC2(void, alGenBuffers, ALsizei,n, ALuint*,buffers) FORCE_ALIGN void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Generating %d buffers", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Generating {} buffers", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - if(!EnsureBuffers(device, static_cast(n))) - { - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d buffer%s", n, (n==1)?"":"s"); - return; - } + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - if(n == 1) LIKELY - { - /* Special handling for the easy and normal case. */ - ALbuffer *buffer{AllocBuffer(device)}; - buffers[0] = buffer->id; - } - else - { - /* Store the allocated buffer IDs in a separate local list, to avoid - * modifying the user storage in case of failure. - */ - std::vector ids; - ids.reserve(static_cast(n)); - do { - ALbuffer *buffer{AllocBuffer(device)}; - ids.emplace_back(buffer->id); - } while(--n); - std::copy(ids.begin(), ids.end(), buffers); - } + const al::span bids{buffers, static_cast(n)}; + if(!EnsureBuffers(device, bids.size())) + context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} buffer{}", n, + (n==1) ? "" : "s"); + + std::generate(bids.begin(), bids.end(), [device]{ return AllocBuffer(device)->id; }); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alDeleteBuffers, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alDeleteBuffers, ALsizei,n, const ALuint*,buffers) FORCE_ALIGN void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Deleting %d buffers", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Deleting {} buffers", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; /* First try to find any buffers that are invalid or in-use. */ - auto validate_buffer = [device, &context](const ALuint bid) -> bool + auto validate_buffer = [context,device](const ALuint bid) { - if(!bid) return true; + if(!bid) return; ALbuffer *ALBuf{LookupBuffer(device, bid)}; - if(!ALBuf) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", bid); - return false; - } - if(ReadRef(ALBuf->ref) != 0) UNLIKELY - { - context->setError(AL_INVALID_OPERATION, "Deleting in-use buffer %u", bid); - return false; - } - return true; + if(!ALBuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", bid); + if(ALBuf->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, "Deleting in-use buffer {}", bid); }; - const ALuint *buffers_end = buffers + n; - auto invbuf = std::find_if_not(buffers, buffers_end, validate_buffer); - if(invbuf != buffers_end) UNLIKELY return; + + const al::span bids{buffers, static_cast(n)}; + std::for_each(bids.begin(), bids.end(), validate_buffer); /* All good. Delete non-0 buffer IDs. */ auto delete_buffer = [device](const ALuint bid) -> void { - ALbuffer *buffer{bid ? LookupBuffer(device, bid) : nullptr}; - if(buffer) FreeBuffer(device, buffer); + if(ALbuffer *buffer{bid ? LookupBuffer(device, bid) : nullptr}) + FreeBuffer(device, buffer); }; - std::for_each(buffers, buffers_end, delete_buffer); + std::for_each(bids.begin(), bids.end(), delete_buffer); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC1(ALboolean, alIsBuffer, ALuint) +AL_API DECL_FUNC1(ALboolean, alIsBuffer, ALuint,buffer) FORCE_ALIGN ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) noexcept { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; if(!buffer || LookupBuffer(device, buffer)) return AL_TRUE; return AL_FALSE; @@ -736,192 +759,203 @@ AL_API void AL_APIENTRY alBufferData(ALuint buffer, ALenum format, const ALvoid FORCE_ALIGN void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq) noexcept { alBufferStorageDirectSOFT(context, buffer, format, data, size, freq, 0); } -AL_API DECL_FUNCEXT6(void, alBufferStorage,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei, ALbitfieldSOFT) +AL_API DECL_FUNCEXT6(void, alBufferStorage,SOFT, ALuint,buffer, ALenum,format, const ALvoid*,data, ALsizei,size, ALsizei,freq, ALbitfieldSOFT,flags) FORCE_ALIGN void AL_APIENTRY alBufferStorageDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei freq, ALbitfieldSOFT flags) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(size < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Negative storage size %d", size); - else if(freq < 1) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq); - else if((flags&INVALID_STORAGE_MASK) != 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid storage flags 0x%x", +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(size < 0) + context->throw_error(AL_INVALID_VALUE, "Negative storage size {}", size); + if(freq < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid sample rate {}", freq); + if((flags&INVALID_STORAGE_MASK) != 0) + context->throw_error(AL_INVALID_VALUE, "Invalid storage flags {:#x}", flags&INVALID_STORAGE_MASK); - else if((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)) UNLIKELY - context->setError(AL_INVALID_VALUE, + if((flags&AL_MAP_PERSISTENT_BIT_SOFT) && !(flags&MAP_READ_WRITE_FLAGS)) + context->throw_error(AL_INVALID_VALUE, "Declaring persistently mapped storage without read or write access"); - else - { - auto usrfmt = DecomposeUserFormat(format); - if(!usrfmt) UNLIKELY - context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); - else - { - LoadData(context, albuf, freq, static_cast(size), usrfmt->channels, - usrfmt->type, static_cast(data), flags); - } - } + + auto usrfmt = DecomposeUserFormat(format); + if(!usrfmt) + context->throw_error(AL_INVALID_ENUM, "Invalid format {:#04x}", as_unsigned(format)); + + auto bdata = static_cast(data); + LoadData(context, albuf, freq, static_cast(size), usrfmt->channels, usrfmt->type, + al::span{bdata, bdata ? static_cast(size) : 0u}, flags); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -DECL_FUNC5(void, alBufferDataStatic, ALuint, ALenum, ALvoid*, ALsizei, ALsizei) +FORCE_ALIGN DECL_FUNC5(void, alBufferDataStatic, ALuint,buffer, ALenum,format, ALvoid*,data, ALsizei,size, ALsizei,freq) FORCE_ALIGN void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, const ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - if(size < 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Negative storage size %d", size); - if(freq < 1) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq); +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(size < 0) + context->throw_error(AL_INVALID_VALUE, "Negative storage size {}", size); + if(freq < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid sample rate {}", freq); auto usrfmt = DecomposeUserFormat(format); - if(!usrfmt) UNLIKELY - return context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); + if(!usrfmt) + context->throw_error(AL_INVALID_ENUM, "Invalid format {:#04x}", as_unsigned(format)); PrepareUserPtr(context, albuf, freq, usrfmt->channels, usrfmt->type, static_cast(data), static_cast(size)); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNCEXT4(void*, alMapBuffer,SOFT, ALuint, ALsizei, ALsizei, ALbitfieldSOFT) +AL_API DECL_FUNCEXT4(void*, alMapBuffer,SOFT, ALuint,buffer, ALsizei,offset, ALsizei,length, ALbitfieldSOFT,access) FORCE_ALIGN void* AL_APIENTRY alMapBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length, ALbitfieldSOFT access) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if((access&INVALID_MAP_FLAGS) != 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid map flags 0x%x", access&INVALID_MAP_FLAGS); - else if(!(access&MAP_READ_WRITE_FLAGS)) UNLIKELY - context->setError(AL_INVALID_VALUE, "Mapping buffer %u without read or write access", +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if((access&INVALID_MAP_FLAGS) != 0) + context->throw_error(AL_INVALID_VALUE, "Invalid map flags {:#x}", + access&INVALID_MAP_FLAGS); + if(!(access&MAP_READ_WRITE_FLAGS)) + context->throw_error(AL_INVALID_VALUE, "Mapping buffer {} without read or write access", buffer); - else - { - ALbitfieldSOFT unavailable = (albuf->Access^access) & access; - if(ReadRef(albuf->ref) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY - context->setError(AL_INVALID_OPERATION, - "Mapping in-use buffer %u without persistent mapping", buffer); - else if(albuf->MappedAccess != 0) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Mapping already-mapped buffer %u", buffer); - else if((unavailable&AL_MAP_READ_BIT_SOFT)) UNLIKELY - context->setError(AL_INVALID_VALUE, - "Mapping buffer %u for reading without read access", buffer); - else if((unavailable&AL_MAP_WRITE_BIT_SOFT)) UNLIKELY - context->setError(AL_INVALID_VALUE, - "Mapping buffer %u for writing without write access", buffer); - else if((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY - context->setError(AL_INVALID_VALUE, - "Mapping buffer %u persistently without persistent access", buffer); - else if(offset < 0 || length <= 0 - || static_cast(offset) >= albuf->OriginalSize - || static_cast(length) > albuf->OriginalSize - static_cast(offset)) - UNLIKELY - context->setError(AL_INVALID_VALUE, "Mapping invalid range %d+%d for buffer %u", - offset, length, buffer); - else - { - void *retval{albuf->mData.data() + offset}; - albuf->MappedAccess = access; - albuf->MappedOffset = offset; - albuf->MappedSize = length; - return retval; - } - } + const ALbitfieldSOFT unavailable{(albuf->Access^access) & access}; + if(albuf->ref.load(std::memory_order_relaxed) != 0 && !(access&AL_MAP_PERSISTENT_BIT_SOFT)) + context->throw_error(AL_INVALID_OPERATION, + "Mapping in-use buffer {} without persistent mapping", buffer); + if(albuf->MappedAccess != 0) + context->throw_error(AL_INVALID_OPERATION, "Mapping already-mapped buffer {}", buffer); + if((unavailable&AL_MAP_READ_BIT_SOFT)) + context->throw_error(AL_INVALID_VALUE, "Mapping buffer {} for reading without read access", + buffer); + if((unavailable&AL_MAP_WRITE_BIT_SOFT)) + context->throw_error(AL_INVALID_VALUE, + "Mapping buffer {} for writing without write access", buffer); + if((unavailable&AL_MAP_PERSISTENT_BIT_SOFT)) + context->throw_error(AL_INVALID_VALUE, + "Mapping buffer {} persistently without persistent access", buffer); + if(offset < 0 || length <= 0 || static_cast(offset) >= albuf->OriginalSize + || static_cast(length) > albuf->OriginalSize - static_cast(offset)) + context->throw_error(AL_INVALID_VALUE, "Mapping invalid range {}+{} for buffer {}", offset, + length, buffer); + + void *retval{albuf->mData.data() + offset}; + albuf->MappedAccess = access; + albuf->MappedOffset = offset; + albuf->MappedSize = length; + return retval; +} +catch(al::base_exception&) { + return nullptr; +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); return nullptr; } -AL_API DECL_FUNCEXT1(void, alUnmapBuffer,SOFT, ALuint) +AL_API DECL_FUNCEXT1(void, alUnmapBuffer,SOFT, ALuint,buffer) FORCE_ALIGN void AL_APIENTRY alUnmapBufferDirectSOFT(ALCcontext *context, ALuint buffer) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(albuf->MappedAccess == 0) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Unmapping unmapped buffer %u", buffer); - else - { - albuf->MappedAccess = 0; - albuf->MappedOffset = 0; - albuf->MappedSize = 0; - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(albuf->MappedAccess == 0) + context->throw_error(AL_INVALID_OPERATION, "Unmapping unmapped buffer {}", buffer); + + albuf->MappedAccess = 0; + albuf->MappedOffset = 0; + albuf->MappedSize = 0; +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alFlushMappedBuffer,SOFT, ALuint, ALsizei, ALsizei) +AL_API DECL_FUNCEXT3(void, alFlushMappedBuffer,SOFT, ALuint,buffer, ALsizei,offset, ALsizei,length) FORCE_ALIGN void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffer, ALsizei offset, ALsizei length) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Flushing buffer %u while not mapped for writing", - buffer); - else if(offset < albuf->MappedOffset || length <= 0 +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!(albuf->MappedAccess&AL_MAP_WRITE_BIT_SOFT)) + context->throw_error(AL_INVALID_OPERATION, + "Flushing buffer {} while not mapped for writing", buffer); + if(offset < albuf->MappedOffset || length <= 0 || offset >= albuf->MappedOffset+albuf->MappedSize - || length > albuf->MappedOffset+albuf->MappedSize-offset) UNLIKELY - context->setError(AL_INVALID_VALUE, "Flushing invalid range %d+%d on buffer %u", offset, + || length > albuf->MappedOffset+albuf->MappedSize-offset) + context->throw_error(AL_INVALID_VALUE, "Flushing invalid range {}+{} on buffer {}", offset, length, buffer); - else - { - /* FIXME: Need to use some method of double-buffering for the mixer and - * app to hold separate memory, which can be safely transferred - * asynchronously. Currently we just say the app shouldn't write where - * OpenAL's reading, and hope for the best... - */ - std::atomic_thread_fence(std::memory_order_seq_cst); - } + + /* FIXME: Need to use some method of double-buffering for the mixer and app + * to hold separate memory, which can be safely transferred asynchronously. + * Currently we just say the app shouldn't write where OpenAL's reading, + * and hope for the best... + */ + std::atomic_thread_fence(std::memory_order_seq_cst); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alBufferSubData,SOFT, ALuint, ALenum, const ALvoid*, ALsizei, ALsizei) +AL_API DECL_FUNCEXT5(void, alBufferSubData,SOFT, ALuint,buffer, ALenum,format, const ALvoid*,data, ALsizei,offset, ALsizei,length) FORCE_ALIGN void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); auto usrfmt = DecomposeUserFormat(format); - if(!usrfmt) UNLIKELY - return context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); + if(!usrfmt) + context->throw_error(AL_INVALID_ENUM, "Invalid format {:#04x}", as_unsigned(format)); const ALuint unpack_align{albuf->UnpackAlign}; const ALuint align{SanitizeAlignment(usrfmt->type, unpack_align)}; - if(align < 1) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid unpack alignment %u", unpack_align); - if(usrfmt->channels != albuf->mChannels || usrfmt->type != albuf->mType) UNLIKELY - return context->setError(AL_INVALID_ENUM, "Unpacking data with mismatched format"); - if(align != albuf->mBlockAlign) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Unpacking data with alignment %u does not match original alignment %u", align, + if(align < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack alignment {}", unpack_align); + if(usrfmt->channels != albuf->mChannels || usrfmt->type != albuf->mType) + context->throw_error(AL_INVALID_ENUM, "Unpacking data with mismatched format"); + if(align != albuf->mBlockAlign) + context->throw_error(AL_INVALID_VALUE, + "Unpacking data with alignment {} does not match original alignment {}", align, albuf->mBlockAlign); - if(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Unpacking data with mismatched ambisonic order"); - if(albuf->MappedAccess != 0) UNLIKELY - return context->setError(AL_INVALID_OPERATION, "Unpacking data into mapped buffer %u", - buffer); + if(albuf->isBFormat() && albuf->UnpackAmbiOrder != albuf->mAmbiOrder) + context->throw_error(AL_INVALID_VALUE, "Unpacking data with mismatched ambisonic order"); + if(albuf->MappedAccess != 0) + context->throw_error(AL_INVALID_OPERATION, "Unpacking data into mapped buffer {}", buffer); const ALuint num_chans{albuf->channelsFromFmt()}; const ALuint byte_align{ @@ -931,154 +965,185 @@ FORCE_ALIGN void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALui if(offset < 0 || length < 0 || static_cast(offset) > albuf->OriginalSize || static_cast(length) > albuf->OriginalSize-static_cast(offset)) - UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid data sub-range %d+%d on buffer %u", - offset, length, buffer); - if((static_cast(offset)%byte_align) != 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Sub-range offset %d is not a multiple of frame size %d (%d unpack alignment)", + context->throw_error(AL_INVALID_VALUE, "Invalid data sub-range {}+{} on buffer {}", offset, + length, buffer); + if((static_cast(offset)%byte_align) != 0) + context->throw_error(AL_INVALID_VALUE, + "Sub-range offset {} is not a multiple of frame size {} ({} unpack alignment)", offset, byte_align, align); - if((static_cast(length)%byte_align) != 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, - "Sub-range length %d is not a multiple of frame size %d (%d unpack alignment)", + if((static_cast(length)%byte_align) != 0) + context->throw_error(AL_INVALID_VALUE, + "Sub-range length {} is not a multiple of frame size {} ({} unpack alignment)", length, byte_align, align); - assert(al::to_underlying(usrfmt->type) == al::to_underlying(albuf->mType)); - memcpy(albuf->mData.data()+offset, data, static_cast(length)); + std::memcpy(albuf->mData.data()+offset, data, static_cast(length)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alBufferf, ALuint, ALenum, ALfloat) +AL_API DECL_FUNC3(void, alBufferf, ALuint,buffer, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, - ALfloat /*value*/) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + ALfloat value [[maybe_unused]]) noexcept +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param); - } + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alBuffer3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat) +AL_API DECL_FUNC5(void, alBuffer3f, ALuint,buffer, ALenum,param, ALfloat,value1, ALfloat,value2, ALfloat,value3) FORCE_ALIGN void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, - ALfloat /*value1*/, ALfloat /*value2*/, ALfloat /*value3*/) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + ALfloat value1 [[maybe_unused]], ALfloat value2 [[maybe_unused]], + ALfloat value3 [[maybe_unused]]) noexcept +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param); - } + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer 3-float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alBufferfv, ALuint, ALenum, const ALfloat*) +AL_API DECL_FUNC3(void, alBufferfv, ALuint,buffer, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!values) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param); - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alBufferi, ALuint, ALenum, ALint) +AL_API DECL_FUNC3(void, alBufferi, ALuint,buffer, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else switch(param) + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + + switch(param) { case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: - if(value < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid unpack block alignment %d", value); - else - albuf->UnpackAlign = static_cast(value); - break; + if(value < 0) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack block alignment {}", value); + albuf->UnpackAlign = static_cast(value); + return; case AL_PACK_BLOCK_ALIGNMENT_SOFT: - if(value < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid pack block alignment %d", value); - else - albuf->PackAlign = static_cast(value); - break; + if(value < 0) + context->throw_error(AL_INVALID_VALUE, "Invalid pack block alignment {}", value); + albuf->PackAlign = static_cast(value); + return; case AL_AMBISONIC_LAYOUT_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic layout", - buffer); - else if(const auto layout = AmbiLayoutFromEnum(value)) + if(albuf->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, + "Modifying in-use buffer {}'s ambisonic layout", buffer); + if(const auto layout = AmbiLayoutFromEnum(value)) + { + if(layout.value() == AmbiLayout::FuMa && albuf->mAmbiOrder > 3) + context->throw_error(AL_INVALID_OPERATION, + "Cannot set FuMa layout for {}{} order B-Format data", albuf->mAmbiOrder, + GetCounterSuffix(albuf->mAmbiOrder)); albuf->mAmbiLayout = layout.value(); - else UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic layout %04x", value); - break; + return; + } + context->throw_error(AL_INVALID_VALUE, "Invalid unpack ambisonic layout {:#04x}", + as_unsigned(value)); case AL_AMBISONIC_SCALING_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's ambisonic scaling", - buffer); - else if(const auto scaling = AmbiScalingFromEnum(value)) + if(albuf->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, + "Modifying in-use buffer {}'s ambisonic scaling", buffer); + if(const auto scaling = AmbiScalingFromEnum(value)) + { + if(scaling.value() == AmbiScaling::FuMa && albuf->mAmbiOrder > 3) + context->throw_error(AL_INVALID_OPERATION, + "Cannot set FuMa scaling for {}{} order B-Format data", albuf->mAmbiOrder, + GetCounterSuffix(albuf->mAmbiOrder)); albuf->mAmbiScaling = scaling.value(); - else UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic scaling %04x", value); - break; + return; + } + context->throw_error(AL_INVALID_VALUE, "Invalid unpack ambisonic scaling {:#04x}", + as_unsigned(value)); case AL_UNPACK_AMBISONIC_ORDER_SOFT: - if(value < 1 || value > 14) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid unpack ambisonic order %d", value); - else - albuf->UnpackAmbiOrder = static_cast(value); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param); + if(value < 1 || value > 14) + context->throw_error(AL_INVALID_VALUE, "Invalid unpack ambisonic order {}", value); + albuf->UnpackAmbiOrder = static_cast(value); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alBuffer3i, ALuint, ALenum, ALint, ALint, ALint) +AL_API DECL_FUNC5(void, alBuffer3i, ALuint,buffer, ALenum,param, ALint,value1, ALint,value2, ALint,value3) FORCE_ALIGN void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, - ALint /*value1*/, ALint /*value2*/, ALint /*value3*/) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + ALint value1 [[maybe_unused]], ALint value2 [[maybe_unused]], ALint value3 [[maybe_unused]]) noexcept +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param); - } + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer 3-integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alBufferiv, ALuint, ALenum, const ALint*) +AL_API DECL_FUNC3(void, alBufferiv, ALuint,buffer, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) noexcept -{ - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); switch(param) { @@ -1087,85 +1152,98 @@ FORCE_ALIGN void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer case AL_AMBISONIC_LAYOUT_SOFT: case AL_AMBISONIC_SCALING_SOFT: case AL_UNPACK_AMBISONIC_ORDER_SOFT: - alBufferiDirect(context, buffer, param, values[0]); + alBufferiDirect(context, buffer, param, *values); return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else switch(param) + switch(param) { case AL_LOOP_POINTS_SOFT: - if(ReadRef(albuf->ref) != 0) UNLIKELY - context->setError(AL_INVALID_OPERATION, "Modifying in-use buffer %u's loop points", + auto vals = al::span{values, 2_uz}; + if(albuf->ref.load(std::memory_order_relaxed) != 0) + context->throw_error(AL_INVALID_OPERATION, "Modifying in-use buffer {}'s loop points", buffer); - else if(values[0] < 0 || values[0] >= values[1] - || static_cast(values[1]) > albuf->mSampleLen) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid loop point range %d -> %d on buffer %u", - values[0], values[1], buffer); - else - { - albuf->mLoopStart = static_cast(values[0]); - albuf->mLoopEnd = static_cast(values[1]); - } - break; + if(vals[0] < 0 || vals[0] >= vals[1] || static_cast(vals[1]) > albuf->mSampleLen) + context->throw_error(AL_INVALID_VALUE, + "Invalid loop point range {} -> {} on buffer {}", vals[0], vals[1], buffer); - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param); + albuf->mLoopStart = static_cast(vals[0]); + albuf->mLoopEnd = static_cast(vals[1]); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetBufferf, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetBufferf, ALuint,buffer, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + switch(param) { case AL_SEC_LENGTH_SOFT: *value = (albuf->mSampleRate < 1) ? 0.0f : (static_cast(albuf->mSampleLen) / static_cast(albuf->mSampleRate)); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer float property 0x%04x", param); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alGetBuffer3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*) +AL_API DECL_FUNC5(void, alGetBuffer3f, ALuint,buffer, ALenum,param, ALfloat*,value1, ALfloat*,value2, ALfloat*,value3) FORCE_ALIGN void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value1 || !value2 || !value3) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer 3-float property 0x%04x", param); - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value1 || !value2 || !value3) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer 3-float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetBufferfv, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetBufferfv, ALuint,buffer, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) noexcept -{ +try { switch(param) { case AL_SEC_LENGTH_SOFT: @@ -1173,106 +1251,120 @@ FORCE_ALIGN void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buf return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!values) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer float-vector property 0x%04x", param); - } + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetBufferi, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetBufferi, ALuint,buffer, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + switch(param) { case AL_FREQUENCY: *value = static_cast(albuf->mSampleRate); - break; + return; case AL_BITS: *value = (albuf->mType == FmtIMA4 || albuf->mType == FmtMSADPCM) ? 4 : static_cast(albuf->bytesFromFmt() * 8); - break; + return; case AL_CHANNELS: *value = static_cast(albuf->channelsFromFmt()); - break; + return; case AL_SIZE: *value = albuf->mCallback ? 0 : static_cast(albuf->mData.size()); - break; + return; case AL_BYTE_LENGTH_SOFT: *value = static_cast(albuf->mSampleLen / albuf->mBlockAlign * albuf->blockSizeFromFmt()); - break; + return; case AL_SAMPLE_LENGTH_SOFT: *value = static_cast(albuf->mSampleLen); - break; + return; case AL_UNPACK_BLOCK_ALIGNMENT_SOFT: *value = static_cast(albuf->UnpackAlign); - break; + return; case AL_PACK_BLOCK_ALIGNMENT_SOFT: *value = static_cast(albuf->PackAlign); - break; + return; case AL_AMBISONIC_LAYOUT_SOFT: *value = EnumFromAmbiLayout(albuf->mAmbiLayout); - break; + return; case AL_AMBISONIC_SCALING_SOFT: *value = EnumFromAmbiScaling(albuf->mAmbiScaling); - break; + return; case AL_UNPACK_AMBISONIC_ORDER_SOFT: *value = static_cast(albuf->UnpackAmbiOrder); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer integer property 0x%04x", param); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alGetBuffer3i, ALuint, ALenum, ALint*, ALint*, ALint*) +AL_API DECL_FUNC5(void, alGetBuffer3i, ALuint,buffer, ALenum,param, ALint*,value1, ALint*,value2, ALint*,value3) FORCE_ALIGN void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value1 || !value2 || !value3) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer 3-integer property 0x%04x", param); - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value1 || !value2 || !value3) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer 3-integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetBufferiv, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetBufferiv, ALuint,buffer, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) noexcept -{ +try { switch(param) { case AL_FREQUENCY: @@ -1291,97 +1383,118 @@ FORCE_ALIGN void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buf return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!values) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + switch(param) { case AL_LOOP_POINTS_SOFT: - values[0] = static_cast(albuf->mLoopStart); - values[1] = static_cast(albuf->mLoopEnd); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer integer-vector property 0x%04x", param); + auto vals = al::span{values, 2_uz}; + vals[0] = static_cast(albuf->mLoopStart); + vals[1] = static_cast(albuf->mLoopEnd); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alBufferCallback,SOFT, ALuint, ALenum, ALsizei, ALBUFFERCALLBACKTYPESOFT, ALvoid*) +AL_API DECL_FUNCEXT5(void, alBufferCallback,SOFT, ALuint,buffer, ALenum,format, ALsizei,freq, ALBUFFERCALLBACKTYPESOFT,callback, ALvoid*,userptr) FORCE_ALIGN void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(freq < 1) UNLIKELY - context->setError(AL_INVALID_VALUE, "Invalid sample rate %d", freq); - else if(callback == nullptr) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL callback"); - else - { - auto usrfmt = DecomposeUserFormat(format); - if(!usrfmt) UNLIKELY - context->setError(AL_INVALID_ENUM, "Invalid format 0x%04x", format); - else - PrepareCallback(context, albuf, freq, usrfmt->channels, usrfmt->type, callback, - userptr); - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(freq < 1) + context->throw_error(AL_INVALID_VALUE, "Invalid sample rate {}", freq); + if(callback == nullptr) + context->throw_error(AL_INVALID_VALUE, "NULL callback"); + + auto usrfmt = DecomposeUserFormat(format); + if(!usrfmt) + context->throw_error(AL_INVALID_ENUM, "Invalid format {:#04x}", as_unsigned(format)); + + PrepareCallback(context, albuf, freq, usrfmt->channels, usrfmt->type, callback, userptr); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetBufferPtr,SOFT, ALuint, ALenum, ALvoid**) +AL_API DECL_FUNCEXT3(void, alGetBufferPtr,SOFT, ALuint,buffer, ALenum,param, ALvoid**,value) FORCE_ALIGN void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - ALbuffer *albuf = LookupBuffer(device, buffer); - if(!albuf) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + ALbuffer *albuf{LookupBuffer(device, buffer)}; + if(!albuf) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + switch(param) { case AL_BUFFER_CALLBACK_FUNCTION_SOFT: - *value = al::bit_cast(albuf->mCallback); - break; + *value = reinterpret_cast(albuf->mCallback); + return; case AL_BUFFER_CALLBACK_USER_PARAM_SOFT: *value = albuf->mUserData; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer pointer property 0x%04x", param); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer pointer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alGetBuffer3Ptr,SOFT, ALuint, ALenum, ALvoid**, ALvoid**, ALvoid**) +AL_API DECL_FUNCEXT5(void, alGetBuffer3Ptr,SOFT, ALuint,buffer, ALenum,param, ALvoid**,value1, ALvoid**,value2, ALvoid**,value3) FORCE_ALIGN void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!value1 || !value2 || !value3) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer 3-pointer property 0x%04x", param); - } +try { + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!value1 || !value2 || !value3) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer 3-pointer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetBufferPtrv,SOFT, ALuint, ALenum, ALvoid**) +AL_API DECL_FUNCEXT3(void, alGetBufferPtrv,SOFT, ALuint,buffer, ALenum,param, ALvoid**,values) FORCE_ALIGN void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) noexcept -{ +try { switch(param) { case AL_BUFFER_CALLBACK_FUNCTION_SOFT: @@ -1390,17 +1503,21 @@ FORCE_ALIGN void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALui return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; - if(LookupBuffer(device, buffer) == nullptr) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", buffer); - else if(!values) UNLIKELY - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid buffer pointer-vector property 0x%04x", param); - } + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; + + if(LookupBuffer(device, buffer) == nullptr) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + context->throw_error(AL_INVALID_ENUM, "Invalid buffer pointer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } @@ -1444,12 +1561,12 @@ AL_API ALboolean AL_APIENTRY alIsBufferFormatSupportedSOFT(ALenum /*format*/) no void ALbuffer::SetName(ALCcontext *context, ALuint id, std::string_view name) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; auto buffer = LookupBuffer(device, id); - if(!buffer) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid buffer ID %u", id); + if(!buffer) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", id); device->mBufferNames.insert_or_assign(id, name); } @@ -1464,66 +1581,48 @@ BufferSubList::~BufferSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - std::destroy_at(Buffers+idx); + std::destroy_at(al::to_address(Buffers->begin() + idx)); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; - al_free(Buffers); + SubListAllocator{}.deallocate(Buffers, 1); Buffers = nullptr; } -#ifdef ALSOFT_EAX -FORCE_ALIGN DECL_FUNC3(ALboolean, EAXSetBufferMode, ALsizei, const ALuint*, ALint) +#if ALSOFT_EAX +FORCE_ALIGN DECL_FUNC3(ALboolean, EAXSetBufferMode, ALsizei,n, const ALuint*,buffers, ALint,value) FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) noexcept -{ -#define EAX_PREFIX "[EAXSetBufferMode] " - +try { if(!eax_g_is_enabled) - { - context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled."); - return AL_FALSE; - } + context->throw_error(AL_INVALID_OPERATION, "EAX not enabled"); const auto storage = EaxStorageFromEnum(value); if(!storage) - { - context->setError(AL_INVALID_ENUM, EAX_PREFIX "Unsupported X-RAM mode 0x%x", value); - return AL_FALSE; - } + context->throw_error(AL_INVALID_ENUM, "Unsupported X-RAM mode {:#x}", as_unsigned(value)); if(n == 0) return AL_TRUE; if(n < 0) - { - context->setError(AL_INVALID_VALUE, EAX_PREFIX "Buffer count %d out of range", n); - return AL_FALSE; - } - + context->throw_error(AL_INVALID_VALUE, "Buffer count {} out of range", n); if(!buffers) - { - context->setError(AL_INVALID_VALUE, EAX_PREFIX "%s", "Null AL buffers"); - return AL_FALSE; - } + context->throw_error(AL_INVALID_VALUE, "Null AL buffers"); auto device = context->mALDevice.get(); - std::lock_guard device_lock{device->BufferLock}; + std::lock_guard devlock{device->BufferLock}; /* Special-case setting a single buffer, to avoid extraneous allocations. */ if(n == 1) { - const auto bufid = buffers[0]; + const auto bufid = *buffers; if(bufid == AL_NONE) return AL_TRUE; const auto buffer = LookupBuffer(device, bufid); - if(!buffer) UNLIKELY - { - ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid); - return AL_FALSE; - } + if(!buffer) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", bufid); /* TODO: Is the store location allowed to change for in-use buffers, or * only when not set/queued on a source? @@ -1532,13 +1631,10 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, AL if(*storage == EaxStorage::Hardware) { if(!buffer->eax_x_ram_is_hardware - && buffer->OriginalSize > device->eax_x_ram_free_size) UNLIKELY - { - context->setError(AL_OUT_OF_MEMORY, - EAX_PREFIX "Out of X-RAM memory (need: %u, avail: %u)", buffer->OriginalSize, + && buffer->OriginalSize > device->eax_x_ram_free_size) + context->throw_error(AL_OUT_OF_MEMORY, + "Out of X-RAM memory (need: {}, avail: {})", buffer->OriginalSize, device->eax_x_ram_free_size); - return AL_FALSE; - } eax_x_ram_apply(*device, *buffer); } @@ -1550,18 +1646,14 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, AL /* Validate the buffers. */ std::unordered_set buflist; - for(auto i = 0;i < n;++i) + for(const ALuint bufid : al::span{buffers, static_cast(n)}) { - const auto bufid = buffers[i]; if(bufid == AL_NONE) continue; const auto buffer = LookupBuffer(device, bufid); - if(!buffer) UNLIKELY - { - ERR(EAX_PREFIX "Invalid buffer ID %u.\n", bufid); - return AL_FALSE; - } + if(!buffer) + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", bufid); /* TODO: Is the store location allowed to change for in-use buffers, or * only when not set/queued on a source? @@ -1577,22 +1669,16 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, AL { if(!buffer->eax_x_ram_is_hardware) { - if(std::numeric_limits::max()-buffer->OriginalSize < total_needed) UNLIKELY - { - context->setError(AL_OUT_OF_MEMORY, EAX_PREFIX "Size overflow (%u + %zu)\n", + if(std::numeric_limits::max() - buffer->OriginalSize < total_needed) + context->throw_error(AL_OUT_OF_MEMORY, "Size overflow ({} + {})", buffer->OriginalSize, total_needed); - return AL_FALSE; - } + total_needed += buffer->OriginalSize; } } if(total_needed > device->eax_x_ram_free_size) - { - context->setError(AL_OUT_OF_MEMORY, - EAX_PREFIX "Out of X-RAM memory (need: %zu, avail: %u)", total_needed, - device->eax_x_ram_free_size); - return AL_FALSE; - } + context->throw_error(AL_OUT_OF_MEMORY, "Out of X-RAM memory (need: {}, avail: {})", + total_needed, device->eax_x_ram_free_size); } /* Update the mode. */ @@ -1606,41 +1692,40 @@ FORCE_ALIGN ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, AL } return AL_TRUE; - -#undef EAX_PREFIX +} +catch(al::base_exception&) { + return AL_FALSE; +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); + return AL_FALSE; } -FORCE_ALIGN DECL_FUNC2(ALenum, EAXGetBufferMode, ALuint, ALint*) +FORCE_ALIGN DECL_FUNC2(ALenum, EAXGetBufferMode, ALuint,buffer, ALint*,pReserved) FORCE_ALIGN ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) noexcept -{ -#define EAX_PREFIX "[EAXGetBufferMode] " - +try { if(!eax_g_is_enabled) - { - context->setError(AL_INVALID_OPERATION, EAX_PREFIX "%s", "EAX not enabled."); - return AL_NONE; - } + context->throw_error(AL_INVALID_OPERATION, "EAX not enabled."); if(pReserved) - { - context->setError(AL_INVALID_VALUE, EAX_PREFIX "%s", "Non-null reserved parameter"); - return AL_NONE; - } + context->throw_error(AL_INVALID_VALUE, "Non-null reserved parameter"); auto device = context->mALDevice.get(); - std::lock_guard device_lock{device->BufferLock}; + std::lock_guard devlock{device->BufferLock}; const auto al_buffer = LookupBuffer(device, buffer); if(!al_buffer) - { - context->setError(AL_INVALID_NAME, EAX_PREFIX "Invalid buffer ID %u", buffer); - return AL_NONE; - } + context->throw_error(AL_INVALID_NAME, "Invalid buffer ID {}", buffer); return EnumFromEaxStorage(al_buffer->eax_x_ram_mode); - -#undef EAX_PREFIX +} +catch(al::base_exception&) { + return AL_NONE; +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); + return AL_NONE; } #endif // ALSOFT_EAX diff --git a/3rdparty/openal/al/buffer.h b/3rdparty/openal/al/buffer.h index f936cf98493f..187bc6bd1983 100644 --- a/3rdparty/openal/al/buffer.h +++ b/3rdparty/openal/al/buffer.h @@ -1,21 +1,25 @@ #ifndef AL_BUFFER_H #define AL_BUFFER_H +#include "config.h" + +#include #include #include +#include #include +#include #include "AL/al.h" +#include "AL/alc.h" #include "alc/inprogext.h" #include "almalloc.h" -#include "atomic.h" +#include "alnumeric.h" #include "core/buffer_storage.h" #include "vector.h" -#ifdef ALSOFT_EAX -#include "eax/x_ram.h" - +#if ALSOFT_EAX enum class EaxStorage : uint8_t { Automatic, Accessible, @@ -43,19 +47,34 @@ struct ALbuffer : public BufferStorage { ALuint mLoopEnd{0u}; /* Number of times buffer was attached to a source (deletion can only occur when 0) */ - RefCount ref{0u}; + std::atomic ref{0u}; /* Self ID */ ALuint id{0}; static void SetName(ALCcontext *context, ALuint id, std::string_view name); - DISABLE_ALLOC() + DISABLE_ALLOC -#ifdef ALSOFT_EAX +#if ALSOFT_EAX EaxStorage eax_x_ram_mode{EaxStorage::Automatic}; bool eax_x_ram_is_hardware{}; #endif // ALSOFT_EAX }; +struct BufferSubList { + uint64_t FreeMask{~0_u64}; + gsl::owner*> Buffers{nullptr}; + + BufferSubList() noexcept = default; + BufferSubList(const BufferSubList&) = delete; + BufferSubList(BufferSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Buffers{rhs.Buffers} + { rhs.FreeMask = ~0_u64; rhs.Buffers = nullptr; } + ~BufferSubList(); + + BufferSubList& operator=(const BufferSubList&) = delete; + BufferSubList& operator=(BufferSubList&& rhs) noexcept + { std::swap(FreeMask, rhs.FreeMask); std::swap(Buffers, rhs.Buffers); return *this; } +}; + #endif diff --git a/3rdparty/openal/al/debug.cpp b/3rdparty/openal/al/debug.cpp index f5914767a21e..bb742e746925 100644 --- a/3rdparty/openal/al/debug.cpp +++ b/3rdparty/openal/al/debug.cpp @@ -4,31 +4,48 @@ #include #include +#include #include +#include #include #include -#include #include #include +#include +#include #include #include "AL/al.h" +#include "AL/alc.h" +#include "AL/alext.h" #include "alc/context.h" -#include "alc/inprogext.h" +#include "alc/device.h" +#include "alnumeric.h" #include "alspan.h" #include "auxeffectslot.h" #include "buffer.h" +#include "core/except.h" #include "core/logging.h" +#include "core/voice.h" #include "direct_defs.h" #include "effect.h" #include "filter.h" +#include "fmt/core.h" +#include "intrusive_ptr.h" #include "opthelpers.h" #include "source.h" +/* Declared here to prevent compilers from thinking it should be inlined, which + * GCC warns about increasing code size. + */ +DebugGroup::~DebugGroup() = default; + namespace { +using namespace std::string_view_literals; + static_assert(DebugSeverityBase+DebugSeverityCount <= 32, "Too many debug bits"); template @@ -40,7 +57,7 @@ constexpr auto make_array_sequence() { return make_array_sequence(std::make_integer_sequence{}); } -constexpr std::optional GetDebugSource(ALenum source) noexcept +constexpr auto GetDebugSource(ALenum source) noexcept -> std::optional { switch(source) { @@ -53,7 +70,7 @@ constexpr std::optional GetDebugSource(ALenum source) noexcept return std::nullopt; } -constexpr std::optional GetDebugType(ALenum type) noexcept +constexpr auto GetDebugType(ALenum type) noexcept -> std::optional { switch(type) { @@ -70,7 +87,7 @@ constexpr std::optional GetDebugType(ALenum type) noexcept return std::nullopt; } -constexpr std::optional GetDebugSeverity(ALenum severity) noexcept +constexpr auto GetDebugSeverity(ALenum severity) noexcept -> std::optional { switch(severity) { @@ -83,7 +100,7 @@ constexpr std::optional GetDebugSeverity(ALenum severity) noexcep } -ALenum GetDebugSourceEnum(DebugSource source) +constexpr auto GetDebugSourceEnum(DebugSource source) -> ALenum { switch(source) { @@ -93,10 +110,11 @@ ALenum GetDebugSourceEnum(DebugSource source) case DebugSource::Application: return AL_DEBUG_SOURCE_APPLICATION_EXT; case DebugSource::Other: return AL_DEBUG_SOURCE_OTHER_EXT; } - throw std::runtime_error{"Unexpected debug source value "+std::to_string(al::to_underlying(source))}; + throw std::runtime_error{fmt::format("Unexpected debug source value: {}", + int{al::to_underlying(source)})}; } -ALenum GetDebugTypeEnum(DebugType type) +constexpr auto GetDebugTypeEnum(DebugType type) -> ALenum { switch(type) { @@ -110,10 +128,11 @@ ALenum GetDebugTypeEnum(DebugType type) case DebugType::PopGroup: return AL_DEBUG_TYPE_POP_GROUP_EXT; case DebugType::Other: return AL_DEBUG_TYPE_OTHER_EXT; } - throw std::runtime_error{"Unexpected debug type value "+std::to_string(al::to_underlying(type))}; + throw std::runtime_error{fmt::format("Unexpected debug type value: {}", + int{al::to_underlying(type)})}; } -ALenum GetDebugSeverityEnum(DebugSeverity severity) +constexpr auto GetDebugSeverityEnum(DebugSeverity severity) -> ALenum { switch(severity) { @@ -122,50 +141,51 @@ ALenum GetDebugSeverityEnum(DebugSeverity severity) case DebugSeverity::Low: return AL_DEBUG_SEVERITY_LOW_EXT; case DebugSeverity::Notification: return AL_DEBUG_SEVERITY_NOTIFICATION_EXT; } - throw std::runtime_error{"Unexpected debug severity value "+std::to_string(al::to_underlying(severity))}; + throw std::runtime_error{fmt::format("Unexpected debug severity value: {}", + int{al::to_underlying(severity)})}; } -const char *GetDebugSourceName(DebugSource source) +constexpr auto GetDebugSourceName(DebugSource source) noexcept -> std::string_view { switch(source) { - case DebugSource::API: return "API"; - case DebugSource::System: return "Audio System"; - case DebugSource::ThirdParty: return "Third Party"; - case DebugSource::Application: return "Application"; - case DebugSource::Other: return "Other"; + case DebugSource::API: return "API"sv; + case DebugSource::System: return "Audio System"sv; + case DebugSource::ThirdParty: return "Third Party"sv; + case DebugSource::Application: return "Application"sv; + case DebugSource::Other: return "Other"sv; } - return ""; + return ""sv; } -const char *GetDebugTypeName(DebugType type) +constexpr auto GetDebugTypeName(DebugType type) noexcept -> std::string_view { switch(type) { - case DebugType::Error: return "Error"; - case DebugType::DeprecatedBehavior: return "Deprecated Behavior"; - case DebugType::UndefinedBehavior: return "Undefined Behavior"; - case DebugType::Portability: return "Portability"; - case DebugType::Performance: return "Performance"; - case DebugType::Marker: return "Marker"; - case DebugType::PushGroup: return "Push Group"; - case DebugType::PopGroup: return "Pop Group"; - case DebugType::Other: return "Other"; + case DebugType::Error: return "Error"sv; + case DebugType::DeprecatedBehavior: return "Deprecated Behavior"sv; + case DebugType::UndefinedBehavior: return "Undefined Behavior"sv; + case DebugType::Portability: return "Portability"sv; + case DebugType::Performance: return "Performance"sv; + case DebugType::Marker: return "Marker"sv; + case DebugType::PushGroup: return "Push Group"sv; + case DebugType::PopGroup: return "Pop Group"sv; + case DebugType::Other: return "Other"sv; } - return ""; + return ""sv; } -const char *GetDebugSeverityName(DebugSeverity severity) +constexpr auto GetDebugSeverityName(DebugSeverity severity) noexcept -> std::string_view { switch(severity) { - case DebugSeverity::High: return "High"; - case DebugSeverity::Medium: return "Medium"; - case DebugSeverity::Low: return "Low"; - case DebugSeverity::Notification: return "Notification"; + case DebugSeverity::High: return "High"sv; + case DebugSeverity::Medium: return "Medium"sv; + case DebugSeverity::Low: return "Low"sv; + case DebugSeverity::Notification: return "Notification"sv; } - return ""; + return ""sv; } } // namespace @@ -174,13 +194,13 @@ const char *GetDebugSeverityName(DebugSeverity severity) void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, DebugSource source, DebugType type, ALuint id, DebugSeverity severity, std::string_view message) { - if(!mDebugEnabled.load()) UNLIKELY + if(!mDebugEnabled.load(std::memory_order_relaxed)) UNLIKELY return; if(message.length() >= MaxDebugMessageLength) UNLIKELY { - ERR("Debug message too long (%zu >= %d):\n-> %.*s\n", message.length(), - MaxDebugMessageLength, static_cast(message.length()), message.data()); + ERR("Debug message too long ({} >= {}):\n-> {}", message.length(), + MaxDebugMessageLength, message); return; } @@ -215,83 +235,89 @@ void ALCcontext::sendDebugMessage(std::unique_lock &debuglock, Debug mDebugLog.emplace_back(source, type, id, severity, message); else UNLIKELY ERR("Debug message log overflow. Lost message:\n" - " Source: %s\n" - " Type: %s\n" - " ID: %u\n" - " Severity: %s\n" - " Message: \"%.*s\"\n", + " Source: {}\n" + " Type: {}\n" + " ID: {}\n" + " Severity: {}\n" + " Message: \"{}\"", GetDebugSourceName(source), GetDebugTypeName(type), id, - GetDebugSeverityName(severity), static_cast(message.length()), - message.data()); + GetDebugSeverityName(severity), message); } } -FORCE_ALIGN DECL_FUNCEXT2(void, alDebugMessageCallback,EXT, ALDEBUGPROCEXT, void*) +FORCE_ALIGN DECL_FUNCEXT2(void, alDebugMessageCallback,EXT, ALDEBUGPROCEXT,callback, void*,userParam) FORCE_ALIGN void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) noexcept { - std::lock_guard _{context->mDebugCbLock}; + std::lock_guard debuglock{context->mDebugCbLock}; context->mDebugCb = callback; context->mDebugParam = userParam; } -FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageInsert,EXT, ALenum, ALenum, ALuint, ALenum, ALsizei, const ALchar*) +FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageInsert,EXT, ALenum,source, ALenum,type, ALuint,id, ALenum,severity, ALsizei,length, const ALchar*,message) FORCE_ALIGN void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) noexcept -{ +try { if(!context->mContextFlags.test(ContextFlags::DebugBit)) return; - if(!message) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Null message pointer"); + if(!message) + context->throw_error(AL_INVALID_VALUE, "Null message pointer"); auto msgview = (length < 0) ? std::string_view{message} : std::string_view{message, static_cast(length)}; - if(msgview.length() >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", - msgview.length(), MaxDebugMessageLength); + if(msgview.size() >= MaxDebugMessageLength) + context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", msgview.size(), + MaxDebugMessageLength); auto dsource = GetDebugSource(source); if(!dsource) - return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}", as_unsigned(source)); if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application) - return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source); + context->throw_error(AL_INVALID_ENUM, "Debug source {:#04x} not allowed", + as_unsigned(source)); auto dtype = GetDebugType(type); if(!dtype) - return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); + context->throw_error(AL_INVALID_ENUM, "Invalid debug type {:#04x}", as_unsigned(type)); auto dseverity = GetDebugSeverity(severity); if(!dseverity) - return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); + context->throw_error(AL_INVALID_ENUM, "Invalid debug severity {:#04x}", + as_unsigned(severity)); context->debugMessage(*dsource, *dtype, id, *dseverity, msgview); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageControl,EXT, ALenum, ALenum, ALenum, ALsizei, const ALuint*, ALboolean) +FORCE_ALIGN DECL_FUNCEXT6(void, alDebugMessageControl,EXT, ALenum,source, ALenum,type, ALenum,severity, ALsizei,count, const ALuint*,ids, ALboolean,enable) FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) noexcept -{ +try { if(count > 0) { if(!ids) - return context->setError(AL_INVALID_VALUE, "IDs is null with non-0 count"); + context->throw_error(AL_INVALID_VALUE, "IDs is null with non-0 count"); if(source == AL_DONT_CARE_EXT) - return context->setError(AL_INVALID_OPERATION, + context->throw_error(AL_INVALID_OPERATION, "Debug source cannot be AL_DONT_CARE_EXT with IDs"); if(type == AL_DONT_CARE_EXT) - return context->setError(AL_INVALID_OPERATION, + context->throw_error(AL_INVALID_OPERATION, "Debug type cannot be AL_DONT_CARE_EXT with IDs"); if(severity != AL_DONT_CARE_EXT) - return context->setError(AL_INVALID_OPERATION, + context->throw_error(AL_INVALID_OPERATION, "Debug severity must be AL_DONT_CARE_EXT with IDs"); } if(enable != AL_TRUE && enable != AL_FALSE) - return context->setError(AL_INVALID_ENUM, "Invalid debug enable %d", enable); + context->throw_error(AL_INVALID_ENUM, "Invalid debug enable {}", enable); static constexpr size_t ElemCount{DebugSourceCount + DebugTypeCount + DebugSeverityCount}; static constexpr auto Values = make_array_sequence(); @@ -301,7 +327,8 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, { auto dsource = GetDebugSource(source); if(!dsource) - return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}", + as_unsigned(source)); srcIndices = srcIndices.subspan(al::to_underlying(*dsource), 1); } @@ -310,7 +337,7 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, { auto dtype = GetDebugType(type); if(!dtype) - return context->setError(AL_INVALID_ENUM, "Invalid debug type 0x%04x", type); + context->throw_error(AL_INVALID_ENUM, "Invalid debug type {:#04x}", as_unsigned(type)); typeIndices = typeIndices.subspan(al::to_underlying(*dtype), 1); } @@ -319,11 +346,12 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, { auto dseverity = GetDebugSeverity(severity); if(!dseverity) - return context->setError(AL_INVALID_ENUM, "Invalid debug severity 0x%04x", severity); + context->throw_error(AL_INVALID_ENUM, "Invalid debug severity {:#04x}", + as_unsigned(severity)); svrIndices = svrIndices.subspan(al::to_underlying(*dseverity), 1); } - std::lock_guard _{context->mDebugCbLock}; + std::lock_guard debuglock{context->mDebugCbLock}; DebugGroup &debug = context->mDebugGroups.back(); if(count > 0) { @@ -365,36 +393,39 @@ FORCE_ALIGN void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, [apply_type](const uint idx){ apply_type(1<= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%zu >= %d)", - newlen, MaxDebugMessageLength); + if(newlen >= MaxDebugMessageLength) + context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", newlen, + MaxDebugMessageLength); length = static_cast(newlen); } - else if(length >= MaxDebugMessageLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Debug message too long (%d >= %d)", length, + else if(length >= MaxDebugMessageLength) + context->throw_error(AL_INVALID_VALUE, "Debug message too long ({} >= {})", length, MaxDebugMessageLength); auto dsource = GetDebugSource(source); if(!dsource) - return context->setError(AL_INVALID_ENUM, "Invalid debug source 0x%04x", source); + context->throw_error(AL_INVALID_ENUM, "Invalid debug source {:#04x}", as_unsigned(source)); if(*dsource != DebugSource::ThirdParty && *dsource != DebugSource::Application) - return context->setError(AL_INVALID_ENUM, "Debug source 0x%04x not allowed", source); + context->throw_error(AL_INVALID_ENUM, "Debug source {:#04x} not allowed", + as_unsigned(source)); std::unique_lock debuglock{context->mDebugCbLock}; if(context->mDebugGroups.size() >= MaxDebugGroupDepth) - { - debuglock.unlock(); - return context->setError(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups"); - } + context->throw_error(AL_STACK_OVERFLOW_EXT, "Pushing too many debug groups"); context->mDebugGroups.emplace_back(*dsource, id, std::string_view{message, static_cast(length)}); @@ -408,17 +439,18 @@ FORCE_ALIGN void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALen context->sendDebugMessage(debuglock, newback.mSource, DebugType::PushGroup, newback.mId, DebugSeverity::Notification, newback.mMessage); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} FORCE_ALIGN DECL_FUNCEXT(void, alPopDebugGroup,EXT) FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexcept -{ +try { std::unique_lock debuglock{context->mDebugCbLock}; if(context->mDebugGroups.size() <= 1) - { - debuglock.unlock(); - return context->setError(AL_STACK_UNDERFLOW_EXT, - "Attempting to pop the default debug group"); - } + context->throw_error(AL_STACK_UNDERFLOW_EXT, "Attempting to pop the default debug group"); DebugGroup &debug = context->mDebugGroups.back(); const auto source = debug.mSource; @@ -430,89 +462,120 @@ FORCE_ALIGN void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) noexc context->sendDebugMessage(debuglock, source, DebugType::PopGroup, id, DebugSeverity::Notification, message); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -FORCE_ALIGN DECL_FUNCEXT8(ALuint, alGetDebugMessageLog,EXT, ALuint, ALsizei, ALenum*, ALenum*, ALuint*, ALenum*, ALsizei*, ALchar*) +FORCE_ALIGN DECL_FUNCEXT8(ALuint, alGetDebugMessageLog,EXT, ALuint,count, ALsizei,logBufSize, ALenum*,sources, ALenum*,types, ALuint*,ids, ALenum*,severities, ALsizei*,lengths, ALchar*,logBuf) FORCE_ALIGN ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) noexcept -{ - if(logBufSize < 0) - { - context->setError(AL_INVALID_VALUE, "Negative debug log buffer size"); - return 0; - } - - std::lock_guard _{context->mDebugCbLock}; - ALsizei logBufWritten{0}; +try { + if(logBuf && logBufSize < 0) + context->throw_error(AL_INVALID_VALUE, "Negative debug log buffer size"); + + const auto sourcesSpan = al::span{sources, sources ? count : 0u}; + const auto typesSpan = al::span{types, types ? count : 0u}; + const auto idsSpan = al::span{ids, ids ? count : 0u}; + const auto severitiesSpan = al::span{severities, severities ? count : 0u}; + const auto lengthsSpan = al::span{lengths, lengths ? count : 0u}; + const auto logSpan = al::span{logBuf, logBuf ? static_cast(logBufSize) : 0u}; + + auto sourceiter = sourcesSpan.begin(); + auto typeiter = typesSpan.begin(); + auto iditer = idsSpan.begin(); + auto severityiter = severitiesSpan.begin(); + auto lengthiter = lengthsSpan.begin(); + auto logiter = logSpan.begin(); + + auto debuglock = std::lock_guard{context->mDebugCbLock}; for(ALuint i{0};i < count;++i) { if(context->mDebugLog.empty()) return i; auto &entry = context->mDebugLog.front(); - const size_t tocopy{entry.mMessage.size() + 1}; - if(logBuf) + const auto tocopy = size_t{entry.mMessage.size() + 1}; + if(al::to_address(logiter) != nullptr) { - const size_t avail{static_cast(logBufSize - logBufWritten)}; - if(avail < tocopy) + if(static_cast(std::distance(logiter, logSpan.end())) < tocopy) return i; - std::copy_n(entry.mMessage.data(), tocopy, logBuf+logBufWritten); - logBufWritten += static_cast(tocopy); + logiter = std::copy(entry.mMessage.cbegin(), entry.mMessage.cend(), logiter); + *(logiter++) = '\0'; } - if(sources) sources[i] = GetDebugSourceEnum(entry.mSource); - if(types) types[i] = GetDebugTypeEnum(entry.mType); - if(ids) ids[i] = entry.mId; - if(severities) severities[i] = GetDebugSeverityEnum(entry.mSeverity); - if(lengths) lengths[i] = static_cast(tocopy); + if(al::to_address(sourceiter) != nullptr) + *(sourceiter++) = GetDebugSourceEnum(entry.mSource); + if(al::to_address(typeiter) != nullptr) + *(typeiter++) = GetDebugTypeEnum(entry.mType); + if(al::to_address(iditer) != nullptr) + *(iditer++) = entry.mId; + if(al::to_address(severityiter) != nullptr) + *(severityiter++) = GetDebugSeverityEnum(entry.mSeverity); + if(al::to_address(lengthiter) != nullptr) + *(lengthiter++) = static_cast(tocopy); context->mDebugLog.pop_front(); } return count; } +catch(al::base_exception&) { + return 0; +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); + return 0; +} -FORCE_ALIGN DECL_FUNCEXT4(void, alObjectLabel,EXT, ALenum, ALuint, ALsizei, const ALchar*) +FORCE_ALIGN DECL_FUNCEXT4(void, alObjectLabel,EXT, ALenum,identifier, ALuint,name, ALsizei,length, const ALchar*,label) FORCE_ALIGN void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) noexcept -{ - if(!label && length != 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Null label pointer"); +try { + if(!label && length != 0) + context->throw_error(AL_INVALID_VALUE, "Null label pointer"); auto objname = (length < 0) ? std::string_view{label} : std::string_view{label, static_cast(length)}; - if(objname.length() >= MaxObjectLabelLength) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Object label length too long (%zu >= %d)", - objname.length(), MaxObjectLabelLength); + if(objname.size() >= MaxObjectLabelLength) + context->throw_error(AL_INVALID_VALUE, "Object label length too long ({} >= {})", + objname.size(), MaxObjectLabelLength); - if(identifier == AL_SOURCE_EXT) - return ALsource::SetName(context, name, objname); - if(identifier == AL_BUFFER) - return ALbuffer::SetName(context, name, objname); - if(identifier == AL_FILTER_EXT) - return ALfilter::SetName(context, name, objname); - if(identifier == AL_EFFECT_EXT) - return ALeffect::SetName(context, name, objname); - if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) - return ALeffectslot::SetName(context, name, objname); + switch(identifier) + { + case AL_SOURCE_EXT: ALsource::SetName(context, name, objname); return; + case AL_BUFFER: ALbuffer::SetName(context, name, objname); return; + case AL_FILTER_EXT: ALfilter::SetName(context, name, objname); return; + case AL_EFFECT_EXT: ALeffect::SetName(context, name, objname); return; + case AL_AUXILIARY_EFFECT_SLOT_EXT: ALeffectslot::SetName(context, name, objname); return; + } - return context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); + context->throw_error(AL_INVALID_ENUM, "Invalid name identifier {:#04x}", + as_unsigned(identifier)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum, ALuint, ALsizei, ALsizei*, ALchar*) +FORCE_ALIGN DECL_FUNCEXT5(void, alGetObjectLabel,EXT, ALenum,identifier, ALuint,name, ALsizei,bufSize, ALsizei*,length, ALchar*,label) FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) noexcept -{ - if(bufSize < 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Negative label bufSize"); +try { + if(bufSize < 0) + context->throw_error(AL_INVALID_VALUE, "Negative label bufSize"); - if(!label && !length) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Null length and label"); - if(label && bufSize == 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Zero label bufSize"); + if(!label && !length) + context->throw_error(AL_INVALID_VALUE, "Null length and label"); + if(label && bufSize == 0) + context->throw_error(AL_INVALID_VALUE, "Zero label bufSize"); - auto copy_name = [name,bufSize,length,label](std::unordered_map &names) + const auto labelOut = al::span{label, label ? static_cast(bufSize) : 0u}; + auto copy_name = [name,length,labelOut](std::unordered_map &names) { std::string_view objname; @@ -520,13 +583,13 @@ FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALen if(iter != names.end()) objname = iter->second; - if(!label) - *length = static_cast(objname.length()); + if(labelOut.empty()) + *length = static_cast(objname.size()); else { - const size_t tocopy{minz(objname.length(), static_cast(bufSize)-1)}; - std::memcpy(label, objname.data(), tocopy); - label[tocopy] = '\0'; + const size_t tocopy{std::min(objname.size(), labelOut.size()-1)}; + auto oiter = std::copy_n(objname.cbegin(), tocopy, labelOut.begin()); + *oiter = '\0'; if(length) *length = static_cast(tocopy); } @@ -534,32 +597,38 @@ FORCE_ALIGN void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALen if(identifier == AL_SOURCE_EXT) { - std::lock_guard _{context->mSourceLock}; + std::lock_guard srclock{context->mSourceLock}; copy_name(context->mSourceNames); } else if(identifier == AL_BUFFER) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->BufferLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->BufferLock}; copy_name(device->mBufferNames); } else if(identifier == AL_FILTER_EXT) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->FilterLock}; copy_name(device->mFilterNames); } else if(identifier == AL_EFFECT_EXT) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto buflock = std::lock_guard{device->EffectLock}; copy_name(device->mEffectNames); } else if(identifier == AL_AUXILIARY_EFFECT_SLOT_EXT) { - std::lock_guard _{context->mEffectSlotLock}; + std::lock_guard slotlock{context->mEffectSlotLock}; copy_name(context->mEffectSlotNames); } else - context->setError(AL_INVALID_ENUM, "Invalid name identifier 0x%04x", identifier); + context->throw_error(AL_INVALID_ENUM, "Invalid name identifier {:#04x}", + as_unsigned(identifier)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } diff --git a/3rdparty/openal/al/debug.h b/3rdparty/openal/al/debug.h index 2764bb7f794a..d1792adb41e6 100644 --- a/3rdparty/openal/al/debug.h +++ b/3rdparty/openal/al/debug.h @@ -1,8 +1,9 @@ #ifndef AL_DEBUG_H #define AL_DEBUG_H -#include +#include #include +#include #include using uint = unsigned int; @@ -11,14 +12,14 @@ using uint = unsigned int; /* Somewhat arbitrary. Avoid letting it get out of control if the app enables * logging but never reads it. */ -inline constexpr uint8_t MaxDebugLoggedMessages{64}; -inline constexpr uint16_t MaxDebugMessageLength{1024}; -inline constexpr uint8_t MaxDebugGroupDepth{64}; -inline constexpr uint16_t MaxObjectLabelLength{1024}; +inline constexpr std::uint8_t MaxDebugLoggedMessages{64}; +inline constexpr std::uint16_t MaxDebugMessageLength{1024}; +inline constexpr std::uint8_t MaxDebugGroupDepth{64}; +inline constexpr std::uint16_t MaxObjectLabelLength{1024}; inline constexpr uint DebugSourceBase{0}; -enum class DebugSource : uint8_t { +enum class DebugSource : std::uint8_t { API = 0, System, ThirdParty, @@ -28,7 +29,7 @@ enum class DebugSource : uint8_t { inline constexpr uint DebugSourceCount{5}; inline constexpr uint DebugTypeBase{DebugSourceBase + DebugSourceCount}; -enum class DebugType : uint8_t { +enum class DebugType : std::uint8_t { Error = 0, DeprecatedBehavior, UndefinedBehavior, @@ -42,7 +43,7 @@ enum class DebugType : uint8_t { inline constexpr uint DebugTypeCount{9}; inline constexpr uint DebugSeverityBase{DebugTypeBase + DebugTypeCount}; -enum class DebugSeverity : uint8_t { +enum class DebugSeverity : std::uint8_t { High = 0, Medium, Low, @@ -55,7 +56,7 @@ struct DebugGroup { const DebugSource mSource; std::string mMessage; std::vector mFilters; - std::vector mIdFilters; + std::vector mIdFilters; template DebugGroup(DebugSource source, uint id, T&& message) @@ -63,6 +64,7 @@ struct DebugGroup { { } DebugGroup(const DebugGroup&) = default; DebugGroup(DebugGroup&&) = default; + ~DebugGroup(); }; #endif /* AL_DEBUG_H */ diff --git a/3rdparty/openal/al/direct_defs.h b/3rdparty/openal/al/direct_defs.h index 7526b6112a4d..4119182f0158 100644 --- a/3rdparty/openal/al/direct_defs.h +++ b/3rdparty/openal/al/direct_defs.h @@ -12,116 +12,116 @@ constexpr void DefaultVal() noexcept { } } // namespace detail_ #define DECL_FUNC(R, Name) \ -R AL_APIENTRY Name(void) noexcept \ +auto AL_APIENTRY Name() noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct(context.get()); \ } -#define DECL_FUNC1(R, Name, T1) \ -R AL_APIENTRY Name(T1 a) noexcept \ +#define DECL_FUNC1(R, Name, T1,n1) \ +auto AL_APIENTRY Name(T1 n1) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct(context.get(), a); \ + return Name##Direct(context.get(), n1); \ } -#define DECL_FUNC2(R, Name, T1, T2) \ -R AL_APIENTRY Name(T1 a, T2 b) noexcept \ +#define DECL_FUNC2(R, Name, T1,n1, T2,n2) \ +auto AL_APIENTRY Name(T1 n1, T2 n2) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct(context.get(), a, b); \ + return Name##Direct(context.get(), n1, n2); \ } -#define DECL_FUNC3(R, Name, T1, T2, T3) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c) noexcept \ +#define DECL_FUNC3(R, Name, T1,n1, T2,n2, T3,n3) \ +auto AL_APIENTRY Name(T1 n1, T2 n2, T3 n3) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct(context.get(), a, b, c); \ + return Name##Direct(context.get(), n1, n2, n3); \ } -#define DECL_FUNC4(R, Name, T1, T2, T3, T4) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d) noexcept \ +#define DECL_FUNC4(R, Name, T1,n1, T2,n2, T3,n3, T4,n4) \ +auto AL_APIENTRY Name(T1 n1, T2 n2, T3 n3, T4 n4) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct(context.get(), a, b, c, d); \ + return Name##Direct(context.get(), n1, n2, n3, n4); \ } -#define DECL_FUNC5(R, Name, T1, T2, T3, T4, T5) \ -R AL_APIENTRY Name(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \ +#define DECL_FUNC5(R, Name, T1,n1, T2,n2, T3,n3, T4,n4, T5,n5) \ +auto AL_APIENTRY Name(T1 n1, T2 n2, T3 n3, T4 n4, T5 n5) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct(context.get(), a, b, c, d, e); \ + return Name##Direct(context.get(), n1, n2, n3, n4, n5); \ } #define DECL_FUNCEXT(R, Name,Ext) \ -R AL_APIENTRY Name##Ext(void) noexcept \ +auto AL_APIENTRY Name##Ext() noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ return Name##Direct##Ext(context.get()); \ } -#define DECL_FUNCEXT1(R, Name,Ext, T1) \ -R AL_APIENTRY Name##Ext(T1 a) noexcept \ +#define DECL_FUNCEXT1(R, Name,Ext, T1,n1) \ +auto AL_APIENTRY Name##Ext(T1 n1) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a); \ + return Name##Direct##Ext(context.get(), n1); \ } -#define DECL_FUNCEXT2(R, Name,Ext, T1, T2) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b) noexcept \ +#define DECL_FUNCEXT2(R, Name,Ext, T1,n1, T2,n2) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b); \ + return Name##Direct##Ext(context.get(), n1, n2); \ } -#define DECL_FUNCEXT3(R, Name,Ext, T1, T2, T3) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c) noexcept \ +#define DECL_FUNCEXT3(R, Name,Ext, T1,n1, T2,n2, T3,n3) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2, T3 n3) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b, c); \ + return Name##Direct##Ext(context.get(), n1, n2, n3); \ } -#define DECL_FUNCEXT4(R, Name,Ext, T1, T2, T3, T4) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d) noexcept \ +#define DECL_FUNCEXT4(R, Name,Ext, T1,n1, T2,n2, T3,n3, T4,n4) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2, T3 n3, T4 n4) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b, c, d); \ + return Name##Direct##Ext(context.get(), n1, n2, n3, n4); \ } -#define DECL_FUNCEXT5(R, Name,Ext, T1, T2, T3, T4, T5) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e) noexcept \ +#define DECL_FUNCEXT5(R, Name,Ext, T1,n1, T2,n2, T3,n3, T4,n4, T5,n5) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2, T3 n3, T4 n4, T5 n5) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b, c, d, e); \ + return Name##Direct##Ext(context.get(), n1, n2, n3, n4, n5); \ } -#define DECL_FUNCEXT6(R, Name,Ext, T1, T2, T3, T4, T5, T6) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f) noexcept \ +#define DECL_FUNCEXT6(R, Name,Ext, T1,n1, T2,n2, T3,n3, T4,n4, T5,n5, T6,n6) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2, T3 n3, T4 n4, T5 n5, T6 n6) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b, c, d, e, f); \ + return Name##Direct##Ext(context.get(), n1, n2, n3, n4, n5, n6); \ } -#define DECL_FUNCEXT8(R, Name,Ext, T1, T2, T3, T4, T5, T6, T7, T8) \ -R AL_APIENTRY Name##Ext(T1 a, T2 b, T3 c, T4 d, T5 e, T6 f, T7 g, T8 h) noexcept \ +#define DECL_FUNCEXT8(R, Name,Ext, T1,n1, T2,n2, T3,n3, T4,n4, T5,n5, T6,n6, T7,n7, T8,n8) \ +auto AL_APIENTRY Name##Ext(T1 n1, T2 n2, T3 n3, T4 n4, T5 n5, T6 n6, T7 n7, T8 n8) noexcept -> R \ { \ auto context = GetContextRef(); \ if(!context) UNLIKELY return detail_::DefaultVal(); \ - return Name##Direct##Ext(context.get(), a, b, c, d, e, f, g, h); \ + return Name##Direct##Ext(context.get(), n1, n2, n3, n4, n5, n6, n7, n8); \ } #endif /* AL_DIRECT_DEFS_H */ diff --git a/3rdparty/openal/al/eax/api.h b/3rdparty/openal/al/eax/api.h index 18d93ef83cc8..925e7b4c732d 100644 --- a/3rdparty/openal/al/eax/api.h +++ b/3rdparty/openal/al/eax/api.h @@ -14,20 +14,23 @@ #include #include #include +#include #ifdef _WIN32 #include #endif #include "AL/al.h" +#include "opthelpers.h" + #ifndef _WIN32 -typedef struct _GUID { +using GUID = struct _GUID { /* NOLINT(*-reserved-identifier) */ std::uint32_t Data1; std::uint16_t Data2; std::uint16_t Data3; - std::uint8_t Data4[8]; -} GUID; + std::array Data4; +}; inline bool operator==(const GUID& lhs, const GUID& rhs) noexcept { return std::memcmp(&lhs, &rhs, sizeof(GUID)) == 0; } @@ -36,11 +39,16 @@ inline bool operator!=(const GUID& lhs, const GUID& rhs) noexcept { return !(lhs == rhs); } #endif // _WIN32 -#define DECL_EQOP(T) \ -friend bool operator==(const T &lhs, const T &rhs) noexcept { return std::memcmp(&lhs, &rhs, sizeof(T)) == 0; } \ -friend bool operator!=(const T &lhs, const T &rhs) noexcept { return !(lhs == rhs); } +/* TODO: This seems to create very inefficient comparisons. C++20 should allow + * creating default comparison operators, avoiding the need for this. + */ +#define DECL_EQOP(T, ...) \ +[[nodiscard]] auto get_members() const noexcept { return std::forward_as_tuple(__VA_ARGS__); } \ +[[nodiscard]] friend bool operator==(const T &lhs, const T &rhs) noexcept \ +{ return lhs.get_members() == rhs.get_members(); } \ +[[nodiscard]] friend bool operator!=(const T &lhs, const T &rhs) noexcept { return !(lhs == rhs); } -extern const GUID DSPROPSETID_EAX_ReverbProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAX_ReverbProperties; enum DSPROPERTY_EAX_REVERBPROPERTY : unsigned int { DSPROPERTY_EAX_ALL, @@ -58,7 +66,7 @@ struct EAX_REVERBPROPERTIES { }; // EAX_REVERBPROPERTIES -extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAXBUFFER_ReverbProperties; enum DSPROPERTY_EAXBUFFER_REVERBPROPERTY : unsigned int { DSPROPERTY_EAXBUFFER_ALL, @@ -74,7 +82,7 @@ constexpr auto EAX_BUFFER_MAXREVERBMIX = 1.0F; constexpr auto EAX_REVERBMIX_USEDISTANCE = -1.0F; -extern const GUID DSPROPSETID_EAX20_ListenerProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAX20_ListenerProperties; enum DSPROPERTY_EAX20_LISTENERPROPERTY : unsigned int { DSPROPERTY_EAX20LISTENER_NONE, @@ -212,7 +220,7 @@ constexpr auto EAX2LISTENER_DEFAULTFLAGS = EAX2LISTENERFLAGS_DECAYHFLIMIT; -extern const GUID DSPROPSETID_EAX20_BufferProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAX20_BufferProperties; enum DSPROPERTY_EAX20_BUFFERPROPERTY : unsigned int { DSPROPERTY_EAX20BUFFER_NONE, @@ -248,9 +256,9 @@ struct EAX20BUFFERPROPERTIES { unsigned long dwFlags; // modifies the behavior of properties }; // EAX20BUFFERPROPERTIES -extern const GUID DSPROPSETID_EAX30_ListenerProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAX30_ListenerProperties; -extern const GUID DSPROPSETID_EAX30_BufferProperties; +DECL_HIDDEN extern const GUID DSPROPSETID_EAX30_BufferProperties; constexpr auto EAX_MAX_FXSLOTS = 4; @@ -268,27 +276,29 @@ constexpr auto EAXERR_INCOMPATIBLE_SOURCE_TYPE = -5L; constexpr auto EAXERR_INCOMPATIBLE_EAX_VERSION = -6L; -extern const GUID EAX_NULL_GUID; +DECL_HIDDEN extern const GUID EAX_NULL_GUID; -extern const GUID EAX_PrimaryFXSlotID; +DECL_HIDDEN extern const GUID EAX_PrimaryFXSlotID; struct EAXVECTOR { float x; float y; float z; -}; // EAXVECTOR +}; +[[nodiscard]] inline bool operator==(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept -{ return std::memcmp(&lhs, &rhs, sizeof(EAXVECTOR)) == 0; } +{ return lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z; } +[[nodiscard]] inline bool operator!=(const EAXVECTOR& lhs, const EAXVECTOR& rhs) noexcept { return !(lhs == rhs); } -extern const GUID EAXPROPERTYID_EAX40_Context; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_Context; -extern const GUID EAXPROPERTYID_EAX50_Context; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_Context; // EAX50 constexpr auto HEADPHONES = 0UL; @@ -362,18 +372,19 @@ constexpr auto EAXCONTEXT_MINMACROFXFACTOR = 0.0F; constexpr auto EAXCONTEXT_MAXMACROFXFACTOR = 1.0F; constexpr auto EAXCONTEXT_DEFAULTMACROFXFACTOR = 0.0F; +constexpr auto EAXCONTEXT_DEFAULTLASTERROR = EAX_OK; -extern const GUID EAXPROPERTYID_EAX40_FXSlot0; -extern const GUID EAXPROPERTYID_EAX50_FXSlot0; -extern const GUID EAXPROPERTYID_EAX40_FXSlot1; -extern const GUID EAXPROPERTYID_EAX50_FXSlot1; -extern const GUID EAXPROPERTYID_EAX40_FXSlot2; -extern const GUID EAXPROPERTYID_EAX50_FXSlot2; -extern const GUID EAXPROPERTYID_EAX40_FXSlot3; -extern const GUID EAXPROPERTYID_EAX50_FXSlot3; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot0; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot0; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot1; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot1; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot2; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot2; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_FXSlot3; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_FXSlot3; -extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID; -extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID; +DECL_HIDDEN extern const GUID EAX40CONTEXT_DEFAULTPRIMARYFXSLOTID; +DECL_HIDDEN extern const GUID EAX50CONTEXT_DEFAULTPRIMARYFXSLOTID; enum EAXFXSLOT_PROPERTY : unsigned int { EAXFXSLOT_PARAMETER = 0, @@ -436,8 +447,8 @@ struct EAX50FXSLOTPROPERTIES : public EAX40FXSLOTPROPERTIES { float flOcclusionLFRatio; }; // EAX50FXSLOTPROPERTIES -extern const GUID EAXPROPERTYID_EAX40_Source; -extern const GUID EAXPROPERTYID_EAX50_Source; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX40_Source; +DECL_HIDDEN extern const GUID EAXPROPERTYID_EAX50_Source; // Source object properties enum EAXSOURCE_PROPERTY : unsigned int { @@ -654,11 +665,11 @@ struct EAXSPEAKERLEVELPROPERTIES { }; // EAXSPEAKERLEVELPROPERTIES struct EAX40ACTIVEFXSLOTS { - GUID guidActiveFXSlots[EAX40_MAX_ACTIVE_FXSLOTS]; + std::array guidActiveFXSlots; }; // EAX40ACTIVEFXSLOTS struct EAX50ACTIVEFXSLOTS { - GUID guidActiveFXSlots[EAX50_MAX_ACTIVE_FXSLOTS]; + std::array guidActiveFXSlots; }; // EAX50ACTIVEFXSLOTS // Use this structure for EAXSOURCE_OBSTRUCTIONPARAMETERS property. @@ -704,16 +715,16 @@ struct EAXSOURCEEXCLUSIONSENDPROPERTIES { float flExclusionLFRatio; }; // EAXSOURCEEXCLUSIONSENDPROPERTIES -extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; +DECL_HIDDEN extern const EAX40ACTIVEFXSLOTS EAX40SOURCE_DEFAULTACTIVEFXSLOTID; -extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; +DECL_HIDDEN extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_3DDEFAULTACTIVEFXSLOTID; -extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; +DECL_HIDDEN extern const EAX50ACTIVEFXSLOTS EAX50SOURCE_2DDEFAULTACTIVEFXSLOTID; // EAX Reverb Effect -extern const GUID EAX_REVERB_EFFECT; +DECL_HIDDEN extern const GUID EAX_REVERB_EFFECT; // Reverb effect properties enum EAXREVERB_PROPERTY : unsigned int { @@ -837,7 +848,11 @@ struct EAXREVERBPROPERTIES { float flLFReference; // reference low frequency float flRoomRolloffFactor; // like DS3D flRolloffFactor but for room effect unsigned long ulFlags; // modifies the behavior of properties - DECL_EQOP(EAXREVERBPROPERTIES) + DECL_EQOP(EAXREVERBPROPERTIES, ulEnvironment, flEnvironmentSize, flEnvironmentDiffusion, lRoom, + lRoomHF, lRoomLF, flDecayTime, flDecayHFRatio, flDecayLFRatio, lReflections, + flReflectionsDelay, vReflectionsPan, lReverb, flReverbDelay, vReverbPan, flEchoTime, + flEchoDepth, flModulationTime, flModulationDepth, flAirAbsorptionHF, flHFReference, + flLFReference, flRoomRolloffFactor, ulFlags) }; // EAXREVERBPROPERTIES @@ -946,18 +961,18 @@ constexpr auto EAXREVERB_DEFAULTFLAGS = using Eax1ReverbPresets = std::array; -extern const Eax1ReverbPresets EAX1REVERB_PRESETS; +DECL_HIDDEN extern const Eax1ReverbPresets EAX1REVERB_PRESETS; using Eax2ReverbPresets = std::array; -extern const Eax2ReverbPresets EAX2REVERB_PRESETS; +DECL_HIDDEN extern const Eax2ReverbPresets EAX2REVERB_PRESETS; using EaxReverbPresets = std::array; -extern const EaxReverbPresets EAXREVERB_PRESETS; +DECL_HIDDEN extern const EaxReverbPresets EAXREVERB_PRESETS; // AGC Compressor Effect -extern const GUID EAX_AGCCOMPRESSOR_EFFECT; +DECL_HIDDEN extern const GUID EAX_AGCCOMPRESSOR_EFFECT; enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int { EAXAGCCOMPRESSOR_NONE, @@ -967,7 +982,7 @@ enum EAXAGCCOMPRESSOR_PROPERTY : unsigned int { struct EAXAGCCOMPRESSORPROPERTIES { unsigned long ulOnOff; // Switch Compressor on or off - DECL_EQOP(EAXAGCCOMPRESSORPROPERTIES) + DECL_EQOP(EAXAGCCOMPRESSORPROPERTIES, ulOnOff) }; // EAXAGCCOMPRESSORPROPERTIES @@ -978,7 +993,7 @@ constexpr auto EAXAGCCOMPRESSOR_DEFAULTONOFF = EAXAGCCOMPRESSOR_MAXONOFF; // Autowah Effect -extern const GUID EAX_AUTOWAH_EFFECT; +DECL_HIDDEN extern const GUID EAX_AUTOWAH_EFFECT; enum EAXAUTOWAH_PROPERTY : unsigned int { EAXAUTOWAH_NONE, @@ -994,7 +1009,7 @@ struct EAXAUTOWAHPROPERTIES { float flReleaseTime; // Release time (seconds) long lResonance; // Resonance (mB) long lPeakLevel; // Peak level (mB) - DECL_EQOP(EAXAUTOWAHPROPERTIES) + DECL_EQOP(EAXAUTOWAHPROPERTIES, flAttackTime, flReleaseTime, lResonance, lPeakLevel) }; // EAXAUTOWAHPROPERTIES @@ -1017,7 +1032,7 @@ constexpr auto EAXAUTOWAH_DEFAULTPEAKLEVEL = 2100L; // Chorus Effect -extern const GUID EAX_CHORUS_EFFECT; +DECL_HIDDEN extern const GUID EAX_CHORUS_EFFECT; enum EAXCHORUS_PROPERTY : unsigned int { EAXCHORUS_NONE, @@ -1042,7 +1057,7 @@ struct EAXCHORUSPROPERTIES { float flDepth; // Depth (0 to 1) float flFeedback; // Feedback (-1 to 1) float flDelay; // Delay (seconds) - DECL_EQOP(EAXCHORUSPROPERTIES) + DECL_EQOP(EAXCHORUSPROPERTIES, ulWaveform, lPhase, flRate, flDepth, flFeedback, flDelay) }; // EAXCHORUSPROPERTIES @@ -1073,7 +1088,7 @@ constexpr auto EAXCHORUS_DEFAULTDELAY = 0.016F; // Distortion Effect -extern const GUID EAX_DISTORTION_EFFECT; +DECL_HIDDEN extern const GUID EAX_DISTORTION_EFFECT; enum EAXDISTORTION_PROPERTY : unsigned int { EAXDISTORTION_NONE, @@ -1091,7 +1106,7 @@ struct EAXDISTORTIONPROPERTIES { float flLowPassCutOff; // Controls the cut-off of the filter pre-distortion (Hz) float flEQCenter; // Controls the center frequency of the EQ post-distortion (Hz) float flEQBandwidth; // Controls the bandwidth of the EQ post-distortion (Hz) - DECL_EQOP(EAXDISTORTIONPROPERTIES) + DECL_EQOP(EAXDISTORTIONPROPERTIES, flEdge, lGain, flLowPassCutOff, flEQCenter, flEQBandwidth) }; // EAXDISTORTIONPROPERTIES @@ -1118,7 +1133,7 @@ constexpr auto EAXDISTORTION_DEFAULTEQBANDWIDTH = 3600.0F; // Echo Effect -extern const GUID EAX_ECHO_EFFECT; +DECL_HIDDEN extern const GUID EAX_ECHO_EFFECT; enum EAXECHO_PROPERTY : unsigned int { EAXECHO_NONE, @@ -1136,7 +1151,7 @@ struct EAXECHOPROPERTIES { float flDamping; // Controls a low-pass filter that dampens the echoes (0 to 1) float flFeedback; // Controls the duration of echo repetition (0 to 1) float flSpread; // Controls the left-right spread of the echoes - DECL_EQOP(EAXECHOPROPERTIES) + DECL_EQOP(EAXECHOPROPERTIES, flDelay, flLRDelay, flDamping, flFeedback, flSpread) }; // EAXECHOPROPERTIES @@ -1163,7 +1178,7 @@ constexpr auto EAXECHO_DEFAULTSPREAD = -1.0F; // Equalizer Effect -extern const GUID EAX_EQUALIZER_EFFECT; +DECL_HIDDEN extern const GUID EAX_EQUALIZER_EFFECT; enum EAXEQUALIZER_PROPERTY : unsigned int { EAXEQUALIZER_NONE, @@ -1191,7 +1206,8 @@ struct EAXEQUALIZERPROPERTIES { float flMid2Width; // (octaves) long lHighGain; // (mB) float flHighCutOff; // (Hz) - DECL_EQOP(EAXEQUALIZERPROPERTIES) + DECL_EQOP(EAXEQUALIZERPROPERTIES, lLowGain, flLowCutOff, lMid1Gain, flMid1Center, flMid1Width, + lMid2Gain, flMid2Center, flMid2Width, lHighGain, flHighCutOff) }; // EAXEQUALIZERPROPERTIES @@ -1238,7 +1254,7 @@ constexpr auto EAXEQUALIZER_DEFAULTHIGHCUTOFF = 6000.0F; // Flanger Effect -extern const GUID EAX_FLANGER_EFFECT; +DECL_HIDDEN extern const GUID EAX_FLANGER_EFFECT; enum EAXFLANGER_PROPERTY : unsigned int { EAXFLANGER_NONE, @@ -1263,7 +1279,7 @@ struct EAXFLANGERPROPERTIES { float flDepth; // Depth (0 to 1) float flFeedback; // Feedback (0 to 1) float flDelay; // Delay (seconds) - DECL_EQOP(EAXFLANGERPROPERTIES) + DECL_EQOP(EAXFLANGERPROPERTIES, ulWaveform, lPhase, flRate, flDepth, flFeedback, flDelay) }; // EAXFLANGERPROPERTIES @@ -1294,7 +1310,7 @@ constexpr auto EAXFLANGER_DEFAULTDELAY = 0.002F; // Frequency Shifter Effect -extern const GUID EAX_FREQUENCYSHIFTER_EFFECT; +DECL_HIDDEN extern const GUID EAX_FREQUENCYSHIFTER_EFFECT; enum EAXFREQUENCYSHIFTER_PROPERTY : unsigned int { EAXFREQUENCYSHIFTER_NONE, @@ -1314,7 +1330,7 @@ struct EAXFREQUENCYSHIFTERPROPERTIES { float flFrequency; // (Hz) unsigned long ulLeftDirection; // see enum above unsigned long ulRightDirection; // see enum above - DECL_EQOP(EAXFREQUENCYSHIFTERPROPERTIES) + DECL_EQOP(EAXFREQUENCYSHIFTERPROPERTIES, flFrequency, ulLeftDirection, ulRightDirection) }; // EAXFREQUENCYSHIFTERPROPERTIES @@ -1333,7 +1349,7 @@ constexpr auto EAXFREQUENCYSHIFTER_DEFAULTRIGHTDIRECTION = EAXFREQUENCYSHIFTER_M // Vocal Morpher Effect -extern const GUID EAX_VOCALMORPHER_EFFECT; +DECL_HIDDEN extern const GUID EAX_VOCALMORPHER_EFFECT; enum EAXVOCALMORPHER_PROPERTY : unsigned int { EAXVOCALMORPHER_NONE, @@ -1393,7 +1409,8 @@ struct EAXVOCALMORPHERPROPERTIES { long lPhonemeBCoarseTuning; // (semitones) unsigned long ulWaveform; // Waveform selector - see enum above float flRate; // (Hz) - DECL_EQOP(EAXVOCALMORPHERPROPERTIES) + DECL_EQOP(EAXVOCALMORPHERPROPERTIES, ulPhonemeA, lPhonemeACoarseTuning, ulPhonemeB, + lPhonemeBCoarseTuning, ulWaveform, flRate) }; // EAXVOCALMORPHERPROPERTIES @@ -1424,7 +1441,7 @@ constexpr auto EAXVOCALMORPHER_DEFAULTRATE = 1.41F; // Pitch Shifter Effect -extern const GUID EAX_PITCHSHIFTER_EFFECT; +DECL_HIDDEN extern const GUID EAX_PITCHSHIFTER_EFFECT; enum EAXPITCHSHIFTER_PROPERTY : unsigned int { EAXPITCHSHIFTER_NONE, @@ -1436,7 +1453,7 @@ enum EAXPITCHSHIFTER_PROPERTY : unsigned int { struct EAXPITCHSHIFTERPROPERTIES { long lCoarseTune; // Amount of pitch shift (semitones) long lFineTune; // Amount of pitch shift (cents) - DECL_EQOP(EAXPITCHSHIFTERPROPERTIES) + DECL_EQOP(EAXPITCHSHIFTERPROPERTIES, lCoarseTune, lFineTune) }; // EAXPITCHSHIFTERPROPERTIES @@ -1451,7 +1468,7 @@ constexpr auto EAXPITCHSHIFTER_DEFAULTFINETUNE = 0L; // Ring Modulator Effect -extern const GUID EAX_RINGMODULATOR_EFFECT; +DECL_HIDDEN extern const GUID EAX_RINGMODULATOR_EFFECT; enum EAXRINGMODULATOR_PROPERTY : unsigned int { EAXRINGMODULATOR_NONE, @@ -1472,7 +1489,7 @@ struct EAXRINGMODULATORPROPERTIES { float flFrequency; // Frequency of modulation (Hz) float flHighPassCutOff; // Cut-off frequency of high-pass filter (Hz) unsigned long ulWaveform; // Waveform selector - see enum above - DECL_EQOP(EAXRINGMODULATORPROPERTIES) + DECL_EQOP(EAXRINGMODULATORPROPERTIES, flFrequency, flHighPassCutOff, ulWaveform) }; // EAXRINGMODULATORPROPERTIES diff --git a/3rdparty/openal/al/eax/call.cpp b/3rdparty/openal/al/eax/call.cpp index 689d5cf1d744..5c69d2e5ec97 100644 --- a/3rdparty/openal/al/eax/call.cpp +++ b/3rdparty/openal/al/eax/call.cpp @@ -15,15 +15,9 @@ class EaxCallException : public EaxException { } // namespace -EaxCall::EaxCall( - EaxCallType type, - const GUID& property_set_guid, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_buffer, - ALuint property_size) - : mCallType{type}, mVersion{0}, mPropertySetId{EaxCallPropertySetId::none} - , mIsDeferred{(property_id & deferred_flag) != 0} +EaxCall::EaxCall(EaxCallType type, const GUID &property_set_guid, ALuint property_id, + ALuint property_source_id, ALvoid *property_buffer, ALuint property_size) + : mCallType{type}, mIsDeferred{(property_id & deferred_flag) != 0} , mPropertyId{property_id & ~deferred_flag}, mPropertySourceId{property_source_id} , mPropertyBuffer{property_buffer}, mPropertyBufferSize{property_size} { @@ -146,23 +140,34 @@ EaxCall::EaxCall( fail("Unsupported property set id."); } - switch(mPropertyId) - { - case EAXCONTEXT_LASTERROR: - case EAXCONTEXT_SPEAKERCONFIG: - case EAXCONTEXT_EAXSESSION: - case EAXFXSLOT_NONE: - case EAXFXSLOT_ALLPARAMETERS: - case EAXFXSLOT_LOADEFFECT: - case EAXFXSLOT_VOLUME: - case EAXFXSLOT_LOCK: - case EAXFXSLOT_FLAGS: - case EAXFXSLOT_OCCLUSION: - case EAXFXSLOT_OCCLUSIONLFRATIO: - // EAX allow to set "defer" flag on immediate-only properties. - // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called. - mIsDeferred = false; - break; + if(mPropertySetId == EaxCallPropertySetId::context) + { + switch(mPropertyId) + { + case EAXCONTEXT_LASTERROR: + case EAXCONTEXT_SPEAKERCONFIG: + case EAXCONTEXT_EAXSESSION: + // EAX allow to set "defer" flag on immediate-only properties. + // If we don't clear our flag then "applyAllUpdates" in EAX context won't be called. + mIsDeferred = false; + break; + } + } + else if(mPropertySetId == EaxCallPropertySetId::fx_slot) + { + switch(mPropertyId) + { + case EAXFXSLOT_NONE: + case EAXFXSLOT_ALLPARAMETERS: + case EAXFXSLOT_LOADEFFECT: + case EAXFXSLOT_VOLUME: + case EAXFXSLOT_LOCK: + case EAXFXSLOT_FLAGS: + case EAXFXSLOT_OCCLUSION: + case EAXFXSLOT_OCCLUSIONLFRATIO: + mIsDeferred = false; + break; + } } if(!mIsDeferred) diff --git a/3rdparty/openal/al/eax/call.h b/3rdparty/openal/al/eax/call.h index 45ff328c04b6..72f96bbe4934 100644 --- a/3rdparty/openal/al/eax/call.h +++ b/3rdparty/openal/al/eax/call.h @@ -31,16 +31,16 @@ class EaxCall { ALvoid* property_buffer, ALuint property_size); - bool is_get() const noexcept { return mCallType == EaxCallType::get; } - bool is_deferred() const noexcept { return mIsDeferred; } - int get_version() const noexcept { return mVersion; } - EaxCallPropertySetId get_property_set_id() const noexcept { return mPropertySetId; } - ALuint get_property_id() const noexcept { return mPropertyId; } - ALuint get_property_al_name() const noexcept { return mPropertySourceId; } - EaxFxSlotIndex get_fx_slot_index() const noexcept { return mFxSlotIndex; } + [[nodiscard]] auto is_get() const noexcept -> bool { return mCallType == EaxCallType::get; } + [[nodiscard]] auto is_deferred() const noexcept -> bool { return mIsDeferred; } + [[nodiscard]] auto get_version() const noexcept -> int { return mVersion; } + [[nodiscard]] auto get_property_set_id() const noexcept -> EaxCallPropertySetId { return mPropertySetId; } + [[nodiscard]] auto get_property_id() const noexcept -> ALuint { return mPropertyId; } + [[nodiscard]] auto get_property_al_name() const noexcept -> ALuint { return mPropertySourceId; } + [[nodiscard]] auto get_fx_slot_index() const noexcept -> EaxFxSlotIndex { return mFxSlotIndex; } template - TValue& get_value() const + [[nodiscard]] auto get_value() const -> TValue& { if(mPropertyBufferSize < sizeof(TValue)) fail_too_small(); @@ -49,32 +49,32 @@ class EaxCall { } template - al::span get_values(size_t max_count) const + [[nodiscard]] auto get_values(size_t max_count) const -> al::span { if(max_count == 0 || mPropertyBufferSize < sizeof(TValue)) fail_too_small(); - const auto count = minz(mPropertyBufferSize / sizeof(TValue), max_count); + const auto count = std::min(mPropertyBufferSize/sizeof(TValue), max_count); return {static_cast(mPropertyBuffer), count}; } template - al::span get_values() const + [[nodiscard]] auto get_values() const -> al::span { return get_values(~0_uz); } template - void set_value(const TValue& value) const + auto set_value(const TValue& value) const -> void { get_value() = value; } private: const EaxCallType mCallType; - int mVersion; - EaxFxSlotIndex mFxSlotIndex; - EaxCallPropertySetId mPropertySetId; + int mVersion{}; + EaxFxSlotIndex mFxSlotIndex{}; + EaxCallPropertySetId mPropertySetId{EaxCallPropertySetId::none}; bool mIsDeferred; const ALuint mPropertyId; diff --git a/3rdparty/openal/al/eax/effect.h b/3rdparty/openal/al/eax/effect.h index afe4d94d0b0f..eead5b81378e 100644 --- a/3rdparty/openal/al/eax/effect.h +++ b/3rdparty/openal/al/eax/effect.h @@ -1,16 +1,17 @@ #ifndef EAX_EFFECT_INCLUDED #define EAX_EFFECT_INCLUDED - #include #include #include -#include "alnumeric.h" #include "AL/al.h" +#include "AL/alext.h" #include "core/effects/base.h" #include "call.h" +inline bool EaxTraceCommits{false}; + struct EaxEffectErrorMessages { static constexpr auto unknown_property_id() noexcept { return "Unknown property id."; } static constexpr auto unknown_version() noexcept { return "Unknown version."; } @@ -36,7 +37,7 @@ struct overloaded : Ts... { using Ts::operator()...; }; template overloaded(Ts...) -> overloaded; -constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props) noexcept +constexpr ALenum EnumFromEaxEffectType(const EaxEffectProps &props) { return std::visit(overloaded{ [](const std::monostate&) noexcept { return AL_EFFECT_NULL; }, @@ -100,7 +101,6 @@ struct EaxReverbCommitter { bool commit(const EAX_REVERBPROPERTIES &props); bool commit(const EAX20LISTENERPROPERTIES &props); bool commit(const EAXREVERBPROPERTIES &props); - bool commit(const EaxEffectProps &props); static void SetDefaults(EAX_REVERBPROPERTIES &props); static void SetDefaults(EAX20LISTENERPROPERTIES &props); @@ -110,26 +110,19 @@ struct EaxReverbCommitter { static void Get(const EaxCall &call, const EAX_REVERBPROPERTIES &props); static void Get(const EaxCall &call, const EAX20LISTENERPROPERTIES &props); static void Get(const EaxCall &call, const EAXREVERBPROPERTIES &props); - static void Get(const EaxCall &call, const EaxEffectProps &props); static void Set(const EaxCall &call, EAX_REVERBPROPERTIES &props); static void Set(const EaxCall &call, EAX20LISTENERPROPERTIES &props); static void Set(const EaxCall &call, EAXREVERBPROPERTIES &props); - static void Set(const EaxCall &call, EaxEffectProps &props); - static void translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept; - static void translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept; - static void translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& dst) noexcept; + static void translate(const EAX_REVERBPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept; + static void translate(const EAX20LISTENERPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept; }; template struct EaxCommitter { struct Exception; - EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) - : mEaxProps{eaxprops}, mAlProps{alprops} - { } - EaxEffectProps &mEaxProps; EffectProps &mAlProps; @@ -145,50 +138,155 @@ struct EaxCommitter { [[noreturn]] static void fail_unknown_property_id() { fail(EaxEffectErrorMessages::unknown_property_id()); } - bool commit(const EaxEffectProps &props); +private: + EaxCommitter(EaxEffectProps &eaxprops, EffectProps &alprops) + : mEaxProps{eaxprops}, mAlProps{alprops} + { } - static void SetDefaults(EaxEffectProps &props); - static void Get(const EaxCall &call, const EaxEffectProps &props); - static void Set(const EaxCall &call, EaxEffectProps &props); + friend T; }; struct EaxAutowahCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxAutowahCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXAUTOWAHPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXAUTOWAHPROPERTIES &props); + static void Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props); }; struct EaxChorusCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxChorusCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXCHORUSPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXCHORUSPROPERTIES &props); + static void Set(const EaxCall &call, EAXCHORUSPROPERTIES &props); }; struct EaxCompressorCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxCompressorCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXAGCCOMPRESSORPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXAGCCOMPRESSORPROPERTIES &props); + static void Set(const EaxCall &call, EAXAGCCOMPRESSORPROPERTIES &props); }; struct EaxDistortionCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxDistortionCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXDISTORTIONPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXDISTORTIONPROPERTIES &props); + static void Set(const EaxCall &call, EAXDISTORTIONPROPERTIES &props); }; struct EaxEchoCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxEchoCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXECHOPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXECHOPROPERTIES &props); + static void Set(const EaxCall &call, EAXECHOPROPERTIES &props); }; struct EaxEqualizerCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxEqualizerCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXEQUALIZERPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXEQUALIZERPROPERTIES &props); + static void Set(const EaxCall &call, EAXEQUALIZERPROPERTIES &props); }; struct EaxFlangerCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxFlangerCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXFLANGERPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXFLANGERPROPERTIES &props); + static void Set(const EaxCall &call, EAXFLANGERPROPERTIES &props); }; struct EaxFrequencyShifterCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxFrequencyShifterCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXFREQUENCYSHIFTERPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXFREQUENCYSHIFTERPROPERTIES &props); + static void Set(const EaxCall &call, EAXFREQUENCYSHIFTERPROPERTIES &props); }; struct EaxModulatorCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxModulatorCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXRINGMODULATORPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXRINGMODULATORPROPERTIES &props); + static void Set(const EaxCall &call, EAXRINGMODULATORPROPERTIES &props); }; struct EaxPitchShifterCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxPitchShifterCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXPITCHSHIFTERPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXPITCHSHIFTERPROPERTIES &props); + static void Set(const EaxCall &call, EAXPITCHSHIFTERPROPERTIES &props); }; struct EaxVocalMorpherCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxVocalMorpherCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const EAXVOCALMORPHERPROPERTIES &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const EAXVOCALMORPHERPROPERTIES &props); + static void Set(const EaxCall &call, EAXVOCALMORPHERPROPERTIES &props); }; struct EaxNullCommitter : public EaxCommitter { - using EaxCommitter::EaxCommitter; + template + explicit EaxNullCommitter(Args&& ...args) : EaxCommitter{std::forward(args)...} { } + + bool commit(const std::monostate &props); + + static void SetDefaults(EaxEffectProps &props); + static void Get(const EaxCall &call, const std::monostate &props); + static void Set(const EaxCall &call, std::monostate &props); }; +template +struct CommitterFromProps { }; + +template<> struct CommitterFromProps { using type = EaxNullCommitter; }; +template<> struct CommitterFromProps { using type = EaxReverbCommitter; }; +template<> struct CommitterFromProps { using type = EaxChorusCommitter; }; +template<> struct CommitterFromProps { using type = EaxCompressorCommitter; }; +template<> struct CommitterFromProps { using type = EaxAutowahCommitter; }; +template<> struct CommitterFromProps { using type = EaxDistortionCommitter; }; +template<> struct CommitterFromProps { using type = EaxEchoCommitter; }; +template<> struct CommitterFromProps { using type = EaxEqualizerCommitter; }; +template<> struct CommitterFromProps { using type = EaxFlangerCommitter; }; +template<> struct CommitterFromProps { using type = EaxFrequencyShifterCommitter; }; +template<> struct CommitterFromProps { using type = EaxModulatorCommitter; }; +template<> struct CommitterFromProps { using type = EaxPitchShifterCommitter; }; +template<> struct CommitterFromProps { using type = EaxVocalMorpherCommitter; }; + +template +using CommitterFor = typename CommitterFromProps>>::type; + class EaxEffect { public: @@ -196,7 +294,7 @@ class EaxEffect { ~EaxEffect() = default; ALenum al_effect_type_{AL_EFFECT_NULL}; - EffectProps al_effect_props_{}; + EffectProps al_effect_props_; using Props1 = EAX_REVERBPROPERTIES; using Props2 = EAX20LISTENERPROPERTIES; @@ -225,7 +323,7 @@ class EaxEffect { int version_{}; bool changed_{}; - Props4 props_{}; + Props4 props_; State1 state1_{}; State2 state2_{}; State3 state3_{}; @@ -233,51 +331,39 @@ class EaxEffect { State4 state5_{}; - template - void call_set_defaults(Args&& ...args) - { return T::SetDefaults(std::forward(args)...); } - - void call_set_defaults(const ALenum altype, EaxEffectProps &props) + static void call_set_defaults(const ALenum altype, EaxEffectProps &props) { - if(altype == AL_EFFECT_EAXREVERB) - return call_set_defaults(props); - if(altype == AL_EFFECT_CHORUS) - return call_set_defaults(props); - if(altype == AL_EFFECT_AUTOWAH) - return call_set_defaults(props); - if(altype == AL_EFFECT_COMPRESSOR) - return call_set_defaults(props); - if(altype == AL_EFFECT_DISTORTION) - return call_set_defaults(props); - if(altype == AL_EFFECT_ECHO) - return call_set_defaults(props); - if(altype == AL_EFFECT_EQUALIZER) - return call_set_defaults(props); - if(altype == AL_EFFECT_FLANGER) - return call_set_defaults(props); - if(altype == AL_EFFECT_FREQUENCY_SHIFTER) - return call_set_defaults(props); - if(altype == AL_EFFECT_RING_MODULATOR) - return call_set_defaults(props); - if(altype == AL_EFFECT_PITCH_SHIFTER) - return call_set_defaults(props); - if(altype == AL_EFFECT_VOCAL_MORPHER) - return call_set_defaults(props); - return call_set_defaults(props); + switch(altype) + { + case AL_EFFECT_EAXREVERB: return EaxReverbCommitter::SetDefaults(props); + case AL_EFFECT_CHORUS: return EaxChorusCommitter::SetDefaults(props); + case AL_EFFECT_AUTOWAH: return EaxAutowahCommitter::SetDefaults(props); + case AL_EFFECT_COMPRESSOR: return EaxCompressorCommitter::SetDefaults(props); + case AL_EFFECT_DISTORTION: return EaxDistortionCommitter::SetDefaults(props); + case AL_EFFECT_ECHO: return EaxEchoCommitter::SetDefaults(props); + case AL_EFFECT_EQUALIZER: return EaxEqualizerCommitter::SetDefaults(props); + case AL_EFFECT_FLANGER: return EaxFlangerCommitter::SetDefaults(props); + case AL_EFFECT_FREQUENCY_SHIFTER: return EaxFrequencyShifterCommitter::SetDefaults(props); + case AL_EFFECT_RING_MODULATOR: return EaxModulatorCommitter::SetDefaults(props); + case AL_EFFECT_PITCH_SHIFTER: return EaxPitchShifterCommitter::SetDefaults(props); + case AL_EFFECT_VOCAL_MORPHER: return EaxVocalMorpherCommitter::SetDefaults(props); + case AL_EFFECT_NULL: break; + } + return EaxNullCommitter::SetDefaults(props); } template void init() { - call_set_defaults(state1_.d); + EaxReverbCommitter::SetDefaults(state1_.d); state1_.i = state1_.d; - call_set_defaults(state2_.d); + EaxReverbCommitter::SetDefaults(state2_.d); state2_.i = state2_.d; - call_set_defaults(state3_.d); + EaxReverbCommitter::SetDefaults(state3_.d); state3_.i = state3_.d; - call_set_defaults(state4_.d); + T::SetDefaults(state4_.d); state4_.i = state4_.d; - call_set_defaults(state5_.d); + T::SetDefaults(state5_.d); state5_.i = state5_.d; } @@ -285,9 +371,9 @@ class EaxEffect { { switch(eax_version) { - case 1: call_set_defaults(state1_.d); break; - case 2: call_set_defaults(state2_.d); break; - case 3: call_set_defaults(state3_.d); break; + case 1: EaxReverbCommitter::SetDefaults(state1_.d); break; + case 2: EaxReverbCommitter::SetDefaults(state2_.d); break; + case 3: EaxReverbCommitter::SetDefaults(state3_.d); break; case 4: call_set_defaults(altype, state4_.d); break; case 5: call_set_defaults(altype, state5_.d); break; } @@ -295,47 +381,20 @@ class EaxEffect { } -#define EAXCALL(Props, Callable, ...) \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - if(std::holds_alternative(Props)) \ - return Callable(__VA_ARGS__); \ - return Callable(__VA_ARGS__) - - template - static void call_set(Args&& ...args) - { return T::Set(std::forward(args)...); } - static void call_set(const EaxCall &call, EaxEffectProps &props) - { EAXCALL(props, call_set, call, props); } + { + return std::visit([&](auto &arg) + { return CommitterFor::Set(call, arg); }, + props); + } void set(const EaxCall &call) { switch(call.get_version()) { - case 1: call_set(call, state1_.d); break; - case 2: call_set(call, state2_.d); break; - case 3: call_set(call, state3_.d); break; + case 1: EaxReverbCommitter::Set(call, state1_.d); break; + case 2: EaxReverbCommitter::Set(call, state2_.d); break; + case 3: EaxReverbCommitter::Set(call, state3_.d); break; case 4: call_set(call, state4_.d); break; case 5: call_set(call, state5_.d); break; } @@ -343,32 +402,32 @@ class EaxEffect { } - template - static void call_get(Args&& ...args) - { return T::Get(std::forward(args)...); } - static void call_get(const EaxCall &call, const EaxEffectProps &props) - { EAXCALL(props, call_get, call, props); } + { + return std::visit([&](auto &arg) + { return CommitterFor::Get(call, arg); }, + props); + } - void get(const EaxCall &call) + void get(const EaxCall &call) const { switch(call.get_version()) { - case 1: call_get(call, state1_.d); break; - case 2: call_get(call, state2_.d); break; - case 3: call_get(call, state3_.d); break; + case 1: EaxReverbCommitter::Get(call, state1_.d); break; + case 2: EaxReverbCommitter::Get(call, state2_.d); break; + case 3: EaxReverbCommitter::Get(call, state3_.d); break; case 4: call_get(call, state4_.d); break; case 5: call_get(call, state5_.d); break; } } - template - bool call_commit(Args&& ...args) - { return T{props_, al_effect_props_}.commit(std::forward(args)...); } - bool call_commit(const EaxEffectProps &props) - { EAXCALL(props, call_commit, props); } + { + return std::visit([&](auto &arg) + { return CommitterFor{props_, al_effect_props_}.commit(arg); }, + props); + } bool commit(int eax_version) { @@ -383,15 +442,15 @@ class EaxEffect { { case 1: state1_.i = state1_.d; - ret |= call_commit(state1_.d); + ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state1_.d); break; case 2: state2_.i = state2_.d; - ret |= call_commit(state2_.d); + ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state2_.d); break; case 3: state3_.i = state3_.d; - ret |= call_commit(state3_.d); + ret |= EaxReverbCommitter{props_, al_effect_props_}.commit(state3_.d); break; case 4: state4_.i = state4_.d; diff --git a/3rdparty/openal/al/eax/exception.h b/3rdparty/openal/al/eax/exception.h index 336654f08af5..64cf7c49e738 100644 --- a/3rdparty/openal/al/eax/exception.h +++ b/3rdparty/openal/al/eax/exception.h @@ -10,9 +10,14 @@ class EaxException : public std::runtime_error { static std::string make_message(std::string_view context, std::string_view message); public: + EaxException() = delete; + EaxException(const EaxException&) = default; + EaxException(EaxException&&) = default; EaxException(std::string_view context, std::string_view message); ~EaxException() override; -}; // EaxException + auto operator=(const EaxException&) -> EaxException& = default; + auto operator=(EaxException&&) -> EaxException& = default; +}; -#endif // !EAX_EXCEPTION_INCLUDED +#endif /* EAX_EXCEPTION_INCLUDED */ diff --git a/3rdparty/openal/al/eax/fx_slots.h b/3rdparty/openal/al/eax/fx_slots.h index 18b2d3ad432e..d2d90b24671c 100644 --- a/3rdparty/openal/al/eax/fx_slots.h +++ b/3rdparty/openal/al/eax/fx_slots.h @@ -6,13 +6,10 @@ #include "al/auxeffectslot.h" -#include "api.h" -#include "call.h" #include "fx_slot_index.h" -class EaxFxSlots -{ +class EaxFxSlots { public: void initialize(ALCcontext& al_context); @@ -25,11 +22,9 @@ class EaxFxSlots } - const ALeffectslot& get( - EaxFxSlotIndex index) const; + [[nodiscard]] auto get(EaxFxSlotIndex index) const -> const ALeffectslot&; - ALeffectslot& get( - EaxFxSlotIndex index); + [[nodiscard]] auto get(EaxFxSlotIndex index) -> ALeffectslot&; private: using Items = std::array; @@ -39,8 +34,7 @@ class EaxFxSlots [[noreturn]] - static void fail( - const char* message); + static void fail(const char* message); void initialize_fx_slots(ALCcontext& al_context); }; // EaxFxSlots diff --git a/3rdparty/openal/al/eax/globals.h b/3rdparty/openal/al/eax/globals.h index ff05d009ff3c..6f3e9078f89a 100644 --- a/3rdparty/openal/al/eax/globals.h +++ b/3rdparty/openal/al/eax/globals.h @@ -3,18 +3,4 @@ inline bool eax_g_is_enabled{true}; -inline constexpr char eax1_ext_name[]{"EAX"}; -inline constexpr char eax2_ext_name[]{"EAX2.0"}; -inline constexpr char eax3_ext_name[]{"EAX3.0"}; -inline constexpr char eax4_ext_name[]{"EAX4.0"}; -inline constexpr char eax5_ext_name[]{"EAX5.0"}; - -inline constexpr char eax_x_ram_ext_name[]{"EAX-RAM"}; - -inline constexpr char eax_eax_set_func_name[]{"EAXSet"}; -inline constexpr char eax_eax_get_func_name[]{"EAXGet"}; - -inline constexpr char eax_eax_set_buffer_mode_func_name[]{"EAXSetBufferMode"}; -inline constexpr char eax_eax_get_buffer_mode_func_name[]{"EAXGetBufferMode"}; - -#endif // !EAX_GLOBALS_INCLUDED +#endif /* EAX_GLOBALS_INCLUDED */ diff --git a/3rdparty/openal/al/eax/utils.cpp b/3rdparty/openal/al/eax/utils.cpp index 53599ac5af74..2eec42772f26 100644 --- a/3rdparty/openal/al/eax/utils.cpp +++ b/3rdparty/openal/al/eax/utils.cpp @@ -17,10 +17,9 @@ void eax_log_exception(std::string_view message) noexcept std::rethrow_exception(exception_ptr); } catch(const std::exception& ex) { - const auto ex_message = ex.what(); - ERR("%.*s %s\n", static_cast(message.length()), message.data(), ex_message); + ERR("{} {}", message, ex.what()); } catch(...) { - ERR("%.*s %s\n", static_cast(message.length()), message.data(), "Generic exception."); + ERR("{} {}", message, "Generic exception."); } } diff --git a/3rdparty/openal/al/eax/utils.h b/3rdparty/openal/al/eax/utils.h index 8e0f975f177c..fb0d87642501 100644 --- a/3rdparty/openal/al/eax/utils.h +++ b/3rdparty/openal/al/eax/utils.h @@ -1,15 +1,11 @@ #ifndef EAX_UTILS_INCLUDED #define EAX_UTILS_INCLUDED -#include -#include -#include #include -#include +#include "fmt/core.h" #include "opthelpers.h" -using EaxDirtyFlags = unsigned int; struct EaxAlLowPassParam { float gain; @@ -25,71 +21,9 @@ void eax_validate_range(std::string_view value_name, const TValue& value, const if(value >= min_value && value <= max_value) LIKELY return; - const auto message = - std::string{value_name} + - " out of range (value: " + - std::to_string(value) + "; min: " + - std::to_string(min_value) + "; max: " + - std::to_string(max_value) + ")."; - + const auto message = fmt::format("{} out of range (value: {}; min: {}; max: {}).", value_name, + value, min_value, max_value); throw TException{message.c_str()}; } -namespace detail { - -template -struct EaxIsBitFieldStruct { -private: - using yes = std::true_type; - using no = std::false_type; - - template - static auto test(int) -> decltype(std::declval(), yes{}); - - template - static no test(...); - -public: - static constexpr auto value = std::is_same(0)), yes>::value; -}; - -template -inline bool eax_bit_fields_are_equal(const T& lhs, const T& rhs) noexcept -{ - static_assert(sizeof(T) == sizeof(TValue), "Invalid type size."); - return reinterpret_cast(lhs) == reinterpret_cast(rhs); -} - -} // namespace detail - -template< - typename T, - std::enable_if_t::value, int> = 0 -> -inline bool operator==(const T& lhs, const T& rhs) noexcept -{ - using Value = std::conditional_t< - sizeof(T) == 1, - std::uint8_t, - std::conditional_t< - sizeof(T) == 2, - std::uint16_t, - std::conditional_t< - sizeof(T) == 4, - std::uint32_t, - void>>>; - - static_assert(!std::is_same::value, "Unsupported type."); - return detail::eax_bit_fields_are_equal(lhs, rhs); -} - -template< - typename T, - std::enable_if_t::value, int> = 0 -> -inline bool operator!=(const T& lhs, const T& rhs) noexcept -{ - return !(lhs == rhs); -} - #endif // !EAX_UTILS_INCLUDED diff --git a/3rdparty/openal/al/eax/x_ram.h b/3rdparty/openal/al/eax/x_ram.h index d10fe6973acb..3616550d2018 100644 --- a/3rdparty/openal/al/eax/x_ram.h +++ b/3rdparty/openal/al/eax/x_ram.h @@ -24,7 +24,6 @@ constexpr auto AL_STORAGE_AUTOMATIC_NAME = "AL_STORAGE_AUTOMATIC"; constexpr auto AL_STORAGE_HARDWARE_NAME = "AL_STORAGE_HARDWARE"; constexpr auto AL_STORAGE_ACCESSIBLE_NAME = "AL_STORAGE_ACCESSIBLE"; - ALboolean AL_APIENTRY EAXSetBufferMode(ALsizei n, const ALuint *buffers, ALint value) noexcept; ALenum AL_APIENTRY EAXGetBufferMode(ALuint buffer, ALint *pReserved) noexcept; diff --git a/3rdparty/openal/al/effect.cpp b/3rdparty/openal/al/effect.cpp index c4b064078a9e..0c549d8ab55c 100644 --- a/3rdparty/openal/al/effect.cpp +++ b/3rdparty/openal/al/effect.cpp @@ -28,9 +28,12 @@ #include #include #include -#include #include +#include +#include +#include #include +#include #include #include "AL/al.h" @@ -39,26 +42,23 @@ #include "AL/efx-presets.h" #include "AL/efx.h" +#include "al/effects/effects.h" #include "albit.h" #include "alc/context.h" #include "alc/device.h" -#include "alc/effects/base.h" #include "alc/inprogext.h" #include "almalloc.h" #include "alnumeric.h" +#include "alspan.h" #include "alstring.h" #include "core/except.h" #include "core/logging.h" #include "direct_defs.h" +#include "intrusive_ptr.h" #include "opthelpers.h" -#ifdef ALSOFT_EAX -#include -#include "eax/exception.h" -#endif // ALSOFT_EAX - -const EffectList gEffectList[16]{ +const std::array gEffectList{{ { "eaxreverb", EAXREVERB_EFFECT, AL_EFFECT_EAXREVERB }, { "reverb", REVERB_EFFECT, AL_EFFECT_REVERB }, { "autowah", AUTOWAH_EFFECT, AL_EFFECT_AUTOWAH }, @@ -74,94 +74,74 @@ const EffectList gEffectList[16]{ { "vmorpher", VMORPHER_EFFECT, AL_EFFECT_VOCAL_MORPHER }, { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT }, { "dedicated", DEDICATED_EFFECT, AL_EFFECT_DEDICATED_DIALOGUE }, - { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_REVERB_SOFT }, -}; + { "convolution", CONVOLUTION_EFFECT, AL_EFFECT_CONVOLUTION_SOFT }, +}}; -bool DisabledEffects[MAX_EFFECTS]; - - -effect_exception::effect_exception(ALenum code, const char *msg, ...) : mErrorCode{code} -{ - std::va_list args; - va_start(args, msg); - setMessage(msg, args); - va_end(args); -} -effect_exception::~effect_exception() = default; namespace { -struct EffectPropsItem { - ALenum Type; - const EffectProps &DefaultProps; - const EffectVtable &Vtable; -}; -constexpr EffectPropsItem EffectPropsList[] = { - { AL_EFFECT_NULL, NullEffectProps, NullEffectVtable }, - { AL_EFFECT_EAXREVERB, ReverbEffectProps, ReverbEffectVtable }, - { AL_EFFECT_REVERB, StdReverbEffectProps, StdReverbEffectVtable }, - { AL_EFFECT_AUTOWAH, AutowahEffectProps, AutowahEffectVtable }, - { AL_EFFECT_CHORUS, ChorusEffectProps, ChorusEffectVtable }, - { AL_EFFECT_COMPRESSOR, CompressorEffectProps, CompressorEffectVtable }, - { AL_EFFECT_DISTORTION, DistortionEffectProps, DistortionEffectVtable }, - { AL_EFFECT_ECHO, EchoEffectProps, EchoEffectVtable }, - { AL_EFFECT_EQUALIZER, EqualizerEffectProps, EqualizerEffectVtable }, - { AL_EFFECT_FLANGER, FlangerEffectProps, FlangerEffectVtable }, - { AL_EFFECT_FREQUENCY_SHIFTER, FshifterEffectProps, FshifterEffectVtable }, - { AL_EFFECT_RING_MODULATOR, ModulatorEffectProps, ModulatorEffectVtable }, - { AL_EFFECT_PITCH_SHIFTER, PshifterEffectProps, PshifterEffectVtable }, - { AL_EFFECT_VOCAL_MORPHER, VmorpherEffectProps, VmorpherEffectVtable }, - { AL_EFFECT_DEDICATED_DIALOGUE, DedicatedEffectProps, DedicatedEffectVtable }, - { AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT, DedicatedEffectProps, DedicatedEffectVtable }, - { AL_EFFECT_CONVOLUTION_REVERB_SOFT, ConvolutionEffectProps, ConvolutionEffectVtable }, -}; - - -void ALeffect_setParami(ALeffect *effect, ALenum param, int value) -{ effect->vtab->setParami(&effect->Props, param, value); } -void ALeffect_setParamiv(ALeffect *effect, ALenum param, const int *values) -{ effect->vtab->setParamiv(&effect->Props, param, values); } -void ALeffect_setParamf(ALeffect *effect, ALenum param, float value) -{ effect->vtab->setParamf(&effect->Props, param, value); } -void ALeffect_setParamfv(ALeffect *effect, ALenum param, const float *values) -{ effect->vtab->setParamfv(&effect->Props, param, values); } - -void ALeffect_getParami(const ALeffect *effect, ALenum param, int *value) -{ effect->vtab->getParami(&effect->Props, param, value); } -void ALeffect_getParamiv(const ALeffect *effect, ALenum param, int *values) -{ effect->vtab->getParamiv(&effect->Props, param, values); } -void ALeffect_getParamf(const ALeffect *effect, ALenum param, float *value) -{ effect->vtab->getParamf(&effect->Props, param, value); } -void ALeffect_getParamfv(const ALeffect *effect, ALenum param, float *values) -{ effect->vtab->getParamfv(&effect->Props, param, values); } +using SubListAllocator = al::allocator>; - -const EffectPropsItem *getEffectPropsItemByType(ALenum type) +constexpr auto GetDefaultProps(ALenum type) noexcept -> const EffectProps& { - auto iter = std::find_if(std::begin(EffectPropsList), std::end(EffectPropsList), - [type](const EffectPropsItem &item) noexcept -> bool - { return item.Type == type; }); - return (iter != std::end(EffectPropsList)) ? al::to_address(iter) : nullptr; + switch(type) + { + case AL_EFFECT_NULL: return NullEffectProps; + case AL_EFFECT_EAXREVERB: return ReverbEffectProps; + case AL_EFFECT_REVERB: return StdReverbEffectProps; + case AL_EFFECT_AUTOWAH: return AutowahEffectProps; + case AL_EFFECT_CHORUS: return ChorusEffectProps; + case AL_EFFECT_COMPRESSOR: return CompressorEffectProps; + case AL_EFFECT_DISTORTION: return DistortionEffectProps; + case AL_EFFECT_ECHO: return EchoEffectProps; + case AL_EFFECT_EQUALIZER: return EqualizerEffectProps; + case AL_EFFECT_FLANGER: return FlangerEffectProps; + case AL_EFFECT_FREQUENCY_SHIFTER: return FshifterEffectProps; + case AL_EFFECT_RING_MODULATOR: return ModulatorEffectProps; + case AL_EFFECT_PITCH_SHIFTER: return PshifterEffectProps; + case AL_EFFECT_VOCAL_MORPHER: return VmorpherEffectProps; + case AL_EFFECT_DEDICATED_DIALOGUE: return DedicatedDialogEffectProps; + case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: return DedicatedLfeEffectProps; + case AL_EFFECT_CONVOLUTION_SOFT: return ConvolutionEffectProps; + } + return NullEffectProps; } -void InitEffectParams(ALeffect *effect, ALenum type) +void InitEffectParams(ALeffect *effect, ALenum type) noexcept { - const EffectPropsItem *item{getEffectPropsItemByType(type)}; - if(item) + switch(type) { - effect->Props = item->DefaultProps; - effect->vtab = &item->Vtable; - } - else - { - effect->Props = EffectProps{}; - effect->vtab = &NullEffectVtable; + case AL_EFFECT_NULL: effect->PropsVariant.emplace(); break; + case AL_EFFECT_EAXREVERB: effect->PropsVariant.emplace(); break; + case AL_EFFECT_REVERB: effect->PropsVariant.emplace(); break; + case AL_EFFECT_AUTOWAH: effect->PropsVariant.emplace(); break; + case AL_EFFECT_CHORUS: effect->PropsVariant.emplace(); break; + case AL_EFFECT_COMPRESSOR: effect->PropsVariant.emplace(); break; + case AL_EFFECT_DISTORTION: effect->PropsVariant.emplace(); break; + case AL_EFFECT_ECHO: effect->PropsVariant.emplace(); break; + case AL_EFFECT_EQUALIZER: effect->PropsVariant.emplace(); break; + case AL_EFFECT_FLANGER: effect->PropsVariant.emplace(); break; + case AL_EFFECT_FREQUENCY_SHIFTER: effect->PropsVariant.emplace(); break; + case AL_EFFECT_RING_MODULATOR: effect->PropsVariant.emplace(); break; + case AL_EFFECT_PITCH_SHIFTER: effect->PropsVariant.emplace(); break; + case AL_EFFECT_VOCAL_MORPHER: effect->PropsVariant.emplace(); break; + case AL_EFFECT_DEDICATED_DIALOGUE: + effect->PropsVariant.emplace(); + break; + case AL_EFFECT_DEDICATED_LOW_FREQUENCY_EFFECT: + effect->PropsVariant.emplace(); + break; + case AL_EFFECT_CONVOLUTION_SOFT: + effect->PropsVariant.emplace(); + break; } + effect->Props = GetDefaultProps(type); effect->type = type; } -bool EnsureEffects(ALCdevice *device, size_t needed) -{ +[[nodiscard]] +auto EnsureEffects(al::Device *device, size_t needed) noexcept -> bool +try { size_t count{std::accumulate(device->EffectList.cbegin(), device->EffectList.cend(), 0_uz, [](size_t cur, const EffectSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; @@ -171,21 +151,20 @@ bool EnsureEffects(ALCdevice *device, size_t needed) if(device->EffectList.size() >= 1<<25) UNLIKELY return false; - device->EffectList.emplace_back(); - auto sublist = device->EffectList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Effects = static_cast(al_calloc(alignof(ALeffect), sizeof(ALeffect)*64)); - if(!sublist->Effects) UNLIKELY - { - device->EffectList.pop_back(); - return false; - } - count += 64; + EffectSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Effects = SubListAllocator{}.allocate(1); + device->EffectList.emplace_back(std::move(sublist)); + count += std::tuple_size_v; } return true; } +catch(...) { + return false; +} -ALeffect *AllocEffect(ALCdevice *device) +[[nodiscard]] +auto AllocEffect(al::Device *device) noexcept -> ALeffect* { auto sublist = std::find_if(device->EffectList.begin(), device->EffectList.end(), [](const EffectSubList &entry) noexcept -> bool @@ -194,7 +173,7 @@ ALeffect *AllocEffect(ALCdevice *device) auto slidx = static_cast(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALeffect *effect{al::construct_at(sublist->Effects + slidx)}; + ALeffect *effect{al::construct_at(al::to_address(sublist->Effects->begin() + slidx))}; InitEffectParams(effect, AL_EFFECT_NULL); /* Add 1 to avoid effect ID 0. */ @@ -205,7 +184,7 @@ ALeffect *AllocEffect(ALCdevice *device) return effect; } -void FreeEffect(ALCdevice *device, ALeffect *effect) +void FreeEffect(al::Device *device, ALeffect *effect) { device->mEffectNames.erase(effect->id); @@ -218,7 +197,8 @@ void FreeEffect(ALCdevice *device, ALeffect *effect) device->EffectList[lidx].FreeMask |= 1_u64 << slidx; } -inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) +[[nodiscard]] inline +auto LookupEffect(al::Device *device, ALuint id) noexcept -> ALeffect* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -228,222 +208,237 @@ inline ALeffect *LookupEffect(ALCdevice *device, ALuint id) EffectSubList &sublist = device->EffectList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Effects + slidx; + return al::to_address(sublist.Effects->begin() + slidx); } } // namespace -AL_API DECL_FUNC2(void, alGenEffects, ALsizei, ALuint*) +AL_API DECL_FUNC2(void, alGenEffects, ALsizei,n, ALuint*,effects) FORCE_ALIGN void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Generating %d effects", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Generating {} effects", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; - if(!EnsureEffects(device, static_cast(n))) - { - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d effect%s", n, (n==1)?"":"s"); - return; - } + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; - if(n == 1) LIKELY - { - /* Special handling for the easy and normal case. */ - ALeffect *effect{AllocEffect(device)}; - effects[0] = effect->id; - } - else - { - /* Store the allocated buffer IDs in a separate local list, to avoid - * modifying the user storage in case of failure. - */ - std::vector ids; - ids.reserve(static_cast(n)); - do { - ALeffect *effect{AllocEffect(device)}; - ids.emplace_back(effect->id); - } while(--n); - std::copy(ids.cbegin(), ids.cend(), effects); - } + const al::span eids{effects, static_cast(n)}; + if(!EnsureEffects(device, eids.size())) + context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} effect{}", n, + (n==1) ? "" : "s"); + + std::generate(eids.begin(), eids.end(), [device]{ return AllocEffect(device)->id; }); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alDeleteEffects, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alDeleteEffects, ALsizei,n, const ALuint*,effects) FORCE_ALIGN void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Deleting %d effects", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Deleting {} effects", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; /* First try to find any effects that are invalid. */ auto validate_effect = [device](const ALuint eid) -> bool { return !eid || LookupEffect(device, eid) != nullptr; }; - const ALuint *effects_end = effects + n; - auto inveffect = std::find_if_not(effects, effects_end, validate_effect); - if(inveffect != effects_end) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", *inveffect); - return; - } + const al::span eids{effects, static_cast(n)}; + auto inveffect = std::find_if_not(eids.begin(), eids.end(), validate_effect); + if(inveffect != eids.end()) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", *inveffect); /* All good. Delete non-0 effect IDs. */ auto delete_effect = [device](ALuint eid) -> void { - ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr}; - if(effect) FreeEffect(device, effect); + if(ALeffect *effect{eid ? LookupEffect(device, eid) : nullptr}) + FreeEffect(device, effect); }; - std::for_each(effects, effects_end, delete_effect); + std::for_each(eids.begin(), eids.end(), delete_effect); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC1(ALboolean, alIsEffect, ALuint) +AL_API DECL_FUNC1(ALboolean, alIsEffect, ALuint,effect) FORCE_ALIGN ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) noexcept { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; if(!effect || LookupEffect(device, effect)) return AL_TRUE; return AL_FALSE; } -AL_API DECL_FUNC3(void, alEffecti, ALuint, ALenum, ALint) +AL_API DECL_FUNC3(void, alEffecti, ALuint,effect, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else if(param == AL_EFFECT_TYPE) + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + switch(param) { - bool isOk{value == AL_EFFECT_NULL}; - if(!isOk) + case AL_EFFECT_TYPE: + if(value != AL_EFFECT_NULL) { - for(const EffectList &effectitem : gEffectList) - { - if(value == effectitem.val && !DisabledEffects[effectitem.type]) - { - isOk = true; - break; - } - } + auto check_effect = [value](const EffectList &item) -> bool + { return value == item.val && !DisabledEffects.test(item.type); }; + if(!std::any_of(gEffectList.cbegin(), gEffectList.cend(), check_effect)) + context->throw_error(AL_INVALID_VALUE, "Effect type {:#04x} not supported", + as_unsigned(value)); } - if(isOk) - InitEffectParams(aleffect, value); - else - context->setError(AL_INVALID_VALUE, "Effect type 0x%04x not supported", value); + InitEffectParams(aleffect, value); + return; } - else try + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,value](auto &arg) { - /* Call the appropriate handler */ - ALeffect_setParami(aleffect, param, value); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.SetParami(context, std::get(aleffect->Props), param, value); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alEffectiv, ALuint, ALenum, const ALint*) +AL_API DECL_FUNC3(void, alEffectiv, ALuint,effect, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) noexcept -{ +try { switch(param) { case AL_EFFECT_TYPE: - alEffectiDirect(context, effect, param, values[0]); + alEffectiDirect(context, effect, param, *values); return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,values](auto &arg) { - /* Call the appropriate handler */ - ALeffect_setParamiv(aleffect, param, values); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.SetParamiv(context, std::get(aleffect->Props), param, values); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alEffectf, ALuint, ALenum, ALfloat) +AL_API DECL_FUNC3(void, alEffectf, ALuint,effect, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,value](auto &arg) { - /* Call the appropriate handler */ - ALeffect_setParamf(aleffect, param, value); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.SetParamf(context, std::get(aleffect->Props), param, value); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alEffectfv, ALuint, ALenum, const ALfloat*) +AL_API DECL_FUNC3(void, alEffectfv, ALuint,effect, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,values](auto &arg) { - /* Call the appropriate handler */ - ALeffect_setParamfv(aleffect, param, values); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.SetParamfv(context, std::get(aleffect->Props), param, values); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetEffecti, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetEffecti, ALuint,effect, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; const ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else if(param == AL_EFFECT_TYPE) - *value = aleffect->type; - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + switch(param) { - /* Call the appropriate handler */ - ALeffect_getParami(aleffect, param, value); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); + case AL_EFFECT_TYPE: + *value = aleffect->type; + return; } + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,value](auto &arg) + { + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.GetParami(context, std::get(aleffect->Props), param, value); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetEffectiv, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetEffectiv, ALuint,effect, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *values) noexcept -{ +try { switch(param) { case AL_EFFECT_TYPE: @@ -451,60 +446,75 @@ FORCE_ALIGN void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint eff return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; const ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,values](auto &arg) { - /* Call the appropriate handler */ - ALeffect_getParamiv(aleffect, param, values); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.GetParamiv(context, std::get(aleffect->Props), param, values); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetEffectf, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetEffectf, ALuint,effect, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; const ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,value](auto &arg) { - /* Call the appropriate handler */ - ALeffect_getParamf(aleffect, param, value); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.GetParamf(context, std::get(aleffect->Props), param, value); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetEffectfv, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetEffectfv, ALuint,effect, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; +try { + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; const ALeffect *aleffect{LookupEffect(device, effect)}; - if(!aleffect) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid effect ID %u", effect); - else try + if(!aleffect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", effect); + + /* Call the appropriate handler */ + std::visit([context,aleffect,param,values](auto &arg) { - /* Call the appropriate handler */ - ALeffect_getParamfv(aleffect, param, values); - } - catch(effect_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + using Type = std::remove_cv_t>; + using PropType = typename Type::prop_type; + return arg.GetParamfv(context, std::get(aleffect->Props), param, values); + }, aleffect->PropsVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } @@ -515,12 +525,12 @@ void InitEffect(ALeffect *effect) void ALeffect::SetName(ALCcontext* context, ALuint id, std::string_view name) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->EffectLock}; + auto *device = context->mALDevice.get(); + auto effectlock = std::lock_guard{device->EffectLock}; auto effect = LookupEffect(device, id); - if(!effect) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid effect ID %u", id); + if(!effect) + context->throw_error(AL_INVALID_NAME, "Invalid effect ID {}", id); device->mEffectNames.insert_or_assign(id, name); } @@ -535,20 +545,21 @@ EffectSubList::~EffectSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - std::destroy_at(Effects+idx); + std::destroy_at(al::to_address(Effects->begin()+idx)); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; - al_free(Effects); + SubListAllocator{}.deallocate(Effects, 1); Effects = nullptr; } -#define DECL(x) { #x, EFX_REVERB_PRESET_##x } -static const struct { - const char name[32]; +struct EffectPreset { + const char name[32]; /* NOLINT(*-avoid-c-arrays) */ EFXEAXREVERBPROPERTIES props; -} reverblist[] = { +}; +#define DECL(x) EffectPreset{#x, EFX_REVERB_PRESET_##x} +static constexpr std::array reverblist{ DECL(GENERIC), DECL(PADDEDCELL), DECL(ROOM), @@ -678,61 +689,62 @@ static const struct { }; #undef DECL -void LoadReverbPreset(const char *name, ALeffect *effect) +void LoadReverbPreset(const std::string_view name, ALeffect *effect) { - if(al::strcasecmp(name, "NONE") == 0) + using namespace std::string_view_literals; + + if(al::case_compare(name, "NONE"sv) == 0) { InitEffectParams(effect, AL_EFFECT_NULL); - TRACE("Loading reverb '%s'\n", "NONE"); + TRACE("Loading reverb '{}'", "NONE"); return; } - if(!DisabledEffects[EAXREVERB_EFFECT]) + if(!DisabledEffects.test(EAXREVERB_EFFECT)) InitEffectParams(effect, AL_EFFECT_EAXREVERB); - else if(!DisabledEffects[REVERB_EFFECT]) + else if(!DisabledEffects.test(REVERB_EFFECT)) InitEffectParams(effect, AL_EFFECT_REVERB); else InitEffectParams(effect, AL_EFFECT_NULL); for(const auto &reverbitem : reverblist) { - const EFXEAXREVERBPROPERTIES *props; - - if(al::strcasecmp(name, reverbitem.name) != 0) + if(al::case_compare(name, std::data(reverbitem.name)) != 0) continue; - TRACE("Loading reverb '%s'\n", reverbitem.name); - props = &reverbitem.props; - effect->Props.Reverb.Density = props->flDensity; - effect->Props.Reverb.Diffusion = props->flDiffusion; - effect->Props.Reverb.Gain = props->flGain; - effect->Props.Reverb.GainHF = props->flGainHF; - effect->Props.Reverb.GainLF = props->flGainLF; - effect->Props.Reverb.DecayTime = props->flDecayTime; - effect->Props.Reverb.DecayHFRatio = props->flDecayHFRatio; - effect->Props.Reverb.DecayLFRatio = props->flDecayLFRatio; - effect->Props.Reverb.ReflectionsGain = props->flReflectionsGain; - effect->Props.Reverb.ReflectionsDelay = props->flReflectionsDelay; - effect->Props.Reverb.ReflectionsPan[0] = props->flReflectionsPan[0]; - effect->Props.Reverb.ReflectionsPan[1] = props->flReflectionsPan[1]; - effect->Props.Reverb.ReflectionsPan[2] = props->flReflectionsPan[2]; - effect->Props.Reverb.LateReverbGain = props->flLateReverbGain; - effect->Props.Reverb.LateReverbDelay = props->flLateReverbDelay; - effect->Props.Reverb.LateReverbPan[0] = props->flLateReverbPan[0]; - effect->Props.Reverb.LateReverbPan[1] = props->flLateReverbPan[1]; - effect->Props.Reverb.LateReverbPan[2] = props->flLateReverbPan[2]; - effect->Props.Reverb.EchoTime = props->flEchoTime; - effect->Props.Reverb.EchoDepth = props->flEchoDepth; - effect->Props.Reverb.ModulationTime = props->flModulationTime; - effect->Props.Reverb.ModulationDepth = props->flModulationDepth; - effect->Props.Reverb.AirAbsorptionGainHF = props->flAirAbsorptionGainHF; - effect->Props.Reverb.HFReference = props->flHFReference; - effect->Props.Reverb.LFReference = props->flLFReference; - effect->Props.Reverb.RoomRolloffFactor = props->flRoomRolloffFactor; - effect->Props.Reverb.DecayHFLimit = props->iDecayHFLimit ? AL_TRUE : AL_FALSE; + TRACE("Loading reverb '{}'", std::data(reverbitem.name)); + const auto &props = reverbitem.props; + auto &dst = std::get(effect->Props); + dst.Density = props.flDensity; + dst.Diffusion = props.flDiffusion; + dst.Gain = props.flGain; + dst.GainHF = props.flGainHF; + dst.GainLF = props.flGainLF; + dst.DecayTime = props.flDecayTime; + dst.DecayHFRatio = props.flDecayHFRatio; + dst.DecayLFRatio = props.flDecayLFRatio; + dst.ReflectionsGain = props.flReflectionsGain; + dst.ReflectionsDelay = props.flReflectionsDelay; + dst.ReflectionsPan[0] = props.flReflectionsPan[0]; + dst.ReflectionsPan[1] = props.flReflectionsPan[1]; + dst.ReflectionsPan[2] = props.flReflectionsPan[2]; + dst.LateReverbGain = props.flLateReverbGain; + dst.LateReverbDelay = props.flLateReverbDelay; + dst.LateReverbPan[0] = props.flLateReverbPan[0]; + dst.LateReverbPan[1] = props.flLateReverbPan[1]; + dst.LateReverbPan[2] = props.flLateReverbPan[2]; + dst.EchoTime = props.flEchoTime; + dst.EchoDepth = props.flEchoDepth; + dst.ModulationTime = props.flModulationTime; + dst.ModulationDepth = props.flModulationDepth; + dst.AirAbsorptionGainHF = props.flAirAbsorptionGainHF; + dst.HFReference = props.flHFReference; + dst.LFReference = props.flLFReference; + dst.RoomRolloffFactor = props.flRoomRolloffFactor; + dst.DecayHFLimit = props.iDecayHFLimit ? AL_TRUE : AL_FALSE; return; } - WARN("Reverb preset '%s' not found\n", name); + WARN("Reverb preset '{}' not found", name); } bool IsValidEffectType(ALenum type) noexcept @@ -740,10 +752,7 @@ bool IsValidEffectType(ALenum type) noexcept if(type == AL_EFFECT_NULL) return true; - for(const auto &effect_item : gEffectList) - { - if(type == effect_item.val && !DisabledEffects[effect_item.type]) - return true; - } - return false; + auto check_effect = [type](const EffectList &item) noexcept -> bool + { return type == item.val && !DisabledEffects.test(item.type); }; + return std::any_of(gEffectList.cbegin(), gEffectList.cend(), check_effect); } diff --git a/3rdparty/openal/al/effect.h b/3rdparty/openal/al/effect.h index 27e9dd72dc30..c7db522abc58 100644 --- a/3rdparty/openal/al/effect.h +++ b/3rdparty/openal/al/effect.h @@ -1,13 +1,21 @@ #ifndef AL_EFFECT_H #define AL_EFFECT_H +#include +#include +#include #include +#include +#include #include "AL/al.h" +#include "AL/alc.h" #include "AL/efx.h" -#include "al/effects/effects.h" -#include "alc/effects/base.h" +#include "almalloc.h" +#include "alnumeric.h" +#include "core/effects/base.h" +#include "effects/effects.h" enum { @@ -29,38 +37,55 @@ enum { MAX_EFFECTS }; -extern bool DisabledEffects[MAX_EFFECTS]; - -extern float ReverbBoost; +inline std::bitset DisabledEffects; struct EffectList { - const char name[16]; - int type; + const char name[16]; /* NOLINT(*-avoid-c-arrays) */ + ALuint type; ALenum val; }; -extern const EffectList gEffectList[16]; +DECL_HIDDEN extern const std::array gEffectList; +using EffectHandlerVariant = std::variant; struct ALeffect { // Effect type (AL_EFFECT_NULL, ...) ALenum type{AL_EFFECT_NULL}; - EffectProps Props{}; - - const EffectVtable *vtab{nullptr}; + EffectHandlerVariant PropsVariant; + EffectProps Props; /* Self ID */ ALuint id{0u}; static void SetName(ALCcontext *context, ALuint id, std::string_view name); - DISABLE_ALLOC() + DISABLE_ALLOC }; void InitEffect(ALeffect *effect); -void LoadReverbPreset(const char *name, ALeffect *effect); +void LoadReverbPreset(const std::string_view name, ALeffect *effect); bool IsValidEffectType(ALenum type) noexcept; +struct EffectSubList { + uint64_t FreeMask{~0_u64}; + gsl::owner*> Effects{nullptr}; /* 64 */ + + EffectSubList() noexcept = default; + EffectSubList(const EffectSubList&) = delete; + EffectSubList(EffectSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Effects{rhs.Effects} + { rhs.FreeMask = ~0_u64; rhs.Effects = nullptr; } + ~EffectSubList(); + + EffectSubList& operator=(const EffectSubList&) = delete; + EffectSubList& operator=(EffectSubList&& rhs) noexcept + { std::swap(FreeMask, rhs.FreeMask); std::swap(Effects, rhs.Effects); return *this; } +}; + #endif diff --git a/3rdparty/openal/al/effects/autowah.cpp b/3rdparty/openal/al/effects/autowah.cpp index 1a8b43fcfadb..7519d31bd17a 100644 --- a/3rdparty/openal/al/effects/autowah.cpp +++ b/3rdparty/openal/al/effects/autowah.cpp @@ -4,15 +4,14 @@ #include #include -#include - #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -20,102 +19,82 @@ namespace { -void Autowah_setParamf(EffectProps *props, ALenum param, float val) +constexpr EffectProps genDefaultProps() noexcept +{ + AutowahProps props{}; + props.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME; + props.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME; + props.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE; + props.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN; + return props; +} + +} // namespace + +const EffectProps AutowahEffectProps{genDefaultProps()}; + +void AutowahEffectHandler::SetParami(ALCcontext *context, AutowahProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer property {:#04x}", as_unsigned(param)); } +void AutowahEffectHandler::SetParamiv(ALCcontext *context, AutowahProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer vector property {:#04x}", as_unsigned(param)); } + +void AutowahEffectHandler::SetParamf(ALCcontext *context, AutowahProps &props, ALenum param, float val) { switch(param) { case AL_AUTOWAH_ATTACK_TIME: if(!(val >= AL_AUTOWAH_MIN_ATTACK_TIME && val <= AL_AUTOWAH_MAX_ATTACK_TIME)) - throw effect_exception{AL_INVALID_VALUE, "Autowah attack time out of range"}; - props->Autowah.AttackTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "Autowah attack time out of range"); + props.AttackTime = val; + return; case AL_AUTOWAH_RELEASE_TIME: if(!(val >= AL_AUTOWAH_MIN_RELEASE_TIME && val <= AL_AUTOWAH_MAX_RELEASE_TIME)) - throw effect_exception{AL_INVALID_VALUE, "Autowah release time out of range"}; - props->Autowah.ReleaseTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "Autowah release time out of range"); + props.ReleaseTime = val; + return; case AL_AUTOWAH_RESONANCE: if(!(val >= AL_AUTOWAH_MIN_RESONANCE && val <= AL_AUTOWAH_MAX_RESONANCE)) - throw effect_exception{AL_INVALID_VALUE, "Autowah resonance out of range"}; - props->Autowah.Resonance = val; - break; + context->throw_error(AL_INVALID_VALUE, "Autowah resonance out of range"); + props.Resonance = val; + return; case AL_AUTOWAH_PEAK_GAIN: if(!(val >= AL_AUTOWAH_MIN_PEAK_GAIN && val <= AL_AUTOWAH_MAX_PEAK_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Autowah peak gain out of range"}; - props->Autowah.PeakGain = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Autowah peak gain out of range"); + props.PeakGain = val; + return; } -} -void Autowah_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Autowah_setParamf(props, param, vals[0]); } -void Autowah_setParami(EffectProps*, ALenum param, int) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; } -void Autowah_setParamiv(EffectProps*, ALenum param, const int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x", - param}; + context->throw_error(AL_INVALID_ENUM, "Invalid autowah float property {:#04x}", + as_unsigned(param)); } +void AutowahEffectHandler::SetParamfv(ALCcontext *context, AutowahProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void AutowahEffectHandler::GetParami(ALCcontext *context, const AutowahProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer property {:#04x}", as_unsigned(param)); } +void AutowahEffectHandler::GetParamiv(ALCcontext *context, const AutowahProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid autowah integer vector property {:#04x}", as_unsigned(param)); } -void Autowah_getParamf(const EffectProps *props, ALenum param, float *val) +void AutowahEffectHandler::GetParamf(ALCcontext *context, const AutowahProps &props, ALenum param, float *val) { switch(param) { - case AL_AUTOWAH_ATTACK_TIME: - *val = props->Autowah.AttackTime; - break; - - case AL_AUTOWAH_RELEASE_TIME: - *val = props->Autowah.ReleaseTime; - break; - - case AL_AUTOWAH_RESONANCE: - *val = props->Autowah.Resonance; - break; - - case AL_AUTOWAH_PEAK_GAIN: - *val = props->Autowah.PeakGain; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid autowah float property 0x%04x", param}; + case AL_AUTOWAH_ATTACK_TIME: *val = props.AttackTime; return; + case AL_AUTOWAH_RELEASE_TIME: *val = props.ReleaseTime; return; + case AL_AUTOWAH_RESONANCE: *val = props.Resonance; return; + case AL_AUTOWAH_PEAK_GAIN: *val = props.PeakGain; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid autowah float property {:#04x}", + as_unsigned(param)); } -void Autowah_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Autowah_getParamf(props, param, vals); } - -void Autowah_getParami(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer property 0x%04x", param}; } -void Autowah_getParamiv(const EffectProps*, ALenum param, int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid autowah integer vector property 0x%04x", - param}; -} +void AutowahEffectHandler::GetParamfv(ALCcontext *context, const AutowahProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Autowah.AttackTime = AL_AUTOWAH_DEFAULT_ATTACK_TIME; - props.Autowah.ReleaseTime = AL_AUTOWAH_DEFAULT_RELEASE_TIME; - props.Autowah.Resonance = AL_AUTOWAH_DEFAULT_RESONANCE; - props.Autowah.PeakGain = AL_AUTOWAH_DEFAULT_PEAK_GAIN; - return props; -} - -} // namespace - -DEFINE_ALEFFECT_VTABLE(Autowah); - -const EffectProps AutowahEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using AutowahCommitter = EaxCommitter; @@ -189,25 +168,25 @@ template<> throw Exception{message}; } -template<> -bool AutowahCommitter::commit(const EaxEffectProps &props) +bool EaxAutowahCommitter::commit(const EAXAUTOWAHPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - - auto &eaxprops = std::get(props); - mAlProps.Autowah.AttackTime = eaxprops.flAttackTime; - mAlProps.Autowah.ReleaseTime = eaxprops.flReleaseTime; - mAlProps.Autowah.Resonance = level_mb_to_gain(static_cast(eaxprops.lResonance)); - mAlProps.Autowah.PeakGain = level_mb_to_gain(static_cast(eaxprops.lPeakLevel)); + mAlProps = [&]{ + AutowahProps ret{}; + ret.AttackTime = props.flAttackTime; + ret.ReleaseTime = props.flReleaseTime; + ret.Resonance = level_mb_to_gain(static_cast(props.lResonance)); + ret.PeakGain = level_mb_to_gain(static_cast(props.lPeakLevel)); + return ret; + }(); return true; } -template<> -void AutowahCommitter::SetDefaults(EaxEffectProps &props) +void EaxAutowahCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXAUTOWAHPROPERTIES defprops{[] { @@ -221,10 +200,8 @@ void AutowahCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxAutowahCommitter::Get(const EaxCall &call, const EAXAUTOWAHPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXAUTOWAH_NONE: break; @@ -237,10 +214,8 @@ void AutowahCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void AutowahCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxAutowahCommitter::Set(const EaxCall &call, EAXAUTOWAHPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXAUTOWAH_NONE: break; diff --git a/3rdparty/openal/al/effects/chorus.cpp b/3rdparty/openal/al/effects/chorus.cpp index 90b38e4d4eed..bb9600bf0ef2 100644 --- a/3rdparty/openal/al/effects/chorus.cpp +++ b/3rdparty/openal/al/effects/chorus.cpp @@ -7,13 +7,14 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "core/logging.h" #include "effects.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include -#include "alnumeric.h" +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -27,7 +28,7 @@ static_assert(FlangerMaxDelay >= AL_FLANGER_MAX_DELAY, "Flanger max delay too sm static_assert(AL_CHORUS_WAVEFORM_SINUSOID == AL_FLANGER_WAVEFORM_SINUSOID, "Chorus/Flanger waveform value mismatch"); static_assert(AL_CHORUS_WAVEFORM_TRIANGLE == AL_FLANGER_WAVEFORM_TRIANGLE, "Chorus/Flanger waveform value mismatch"); -inline std::optional WaveformFromEnum(ALenum type) +constexpr std::optional WaveformFromEnum(ALenum type) noexcept { switch(type) { @@ -36,263 +37,230 @@ inline std::optional WaveformFromEnum(ALenum type) } return std::nullopt; } -inline ALenum EnumFromWaveform(ChorusWaveform type) +constexpr ALenum EnumFromWaveform(ChorusWaveform type) { switch(type) { case ChorusWaveform::Sinusoid: return AL_CHORUS_WAVEFORM_SINUSOID; case ChorusWaveform::Triangle: return AL_CHORUS_WAVEFORM_TRIANGLE; } - throw std::runtime_error{"Invalid chorus waveform: "+std::to_string(static_cast(type))}; + throw std::runtime_error{fmt::format("Invalid chorus waveform: {}", + int{al::to_underlying(type)})}; +} + +constexpr EffectProps genDefaultChorusProps() noexcept +{ + ChorusProps props{}; + props.Waveform = WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM).value(); + props.Phase = AL_CHORUS_DEFAULT_PHASE; + props.Rate = AL_CHORUS_DEFAULT_RATE; + props.Depth = AL_CHORUS_DEFAULT_DEPTH; + props.Feedback = AL_CHORUS_DEFAULT_FEEDBACK; + props.Delay = AL_CHORUS_DEFAULT_DELAY; + return props; } -void Chorus_setParami(EffectProps *props, ALenum param, int val) +constexpr EffectProps genDefaultFlangerProps() noexcept +{ + ChorusProps props{}; + props.Waveform = WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM).value(); + props.Phase = AL_FLANGER_DEFAULT_PHASE; + props.Rate = AL_FLANGER_DEFAULT_RATE; + props.Depth = AL_FLANGER_DEFAULT_DEPTH; + props.Feedback = AL_FLANGER_DEFAULT_FEEDBACK; + props.Delay = AL_FLANGER_DEFAULT_DELAY; + return props; +} + +} // namespace + +const EffectProps ChorusEffectProps{genDefaultChorusProps()}; + +void ChorusEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val) { switch(param) { case AL_CHORUS_WAVEFORM: if(auto formopt = WaveformFromEnum(val)) - props->Chorus.Waveform = *formopt; + props.Waveform = *formopt; else - throw effect_exception{AL_INVALID_VALUE, "Invalid chorus waveform: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, "Invalid chorus waveform: {:#04x}", + as_unsigned(val)); + return; case AL_CHORUS_PHASE: if(!(val >= AL_CHORUS_MIN_PHASE && val <= AL_CHORUS_MAX_PHASE)) - throw effect_exception{AL_INVALID_VALUE, "Chorus phase out of range: %d", val}; - props->Chorus.Phase = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Chorus phase out of range: {}", val); + props.Phase = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid chorus integer property {:#04x}", + as_unsigned(param)); } -void Chorus_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Chorus_setParami(props, param, vals[0]); } -void Chorus_setParamf(EffectProps *props, ALenum param, float val) +void ChorusEffectHandler::SetParamiv(ALCcontext *context, ChorusProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void ChorusEffectHandler::SetParamf(ALCcontext *context, ChorusProps &props, ALenum param, float val) { switch(param) { case AL_CHORUS_RATE: if(!(val >= AL_CHORUS_MIN_RATE && val <= AL_CHORUS_MAX_RATE)) - throw effect_exception{AL_INVALID_VALUE, "Chorus rate out of range: %f", val}; - props->Chorus.Rate = val; - break; + context->throw_error(AL_INVALID_VALUE, "Chorus rate out of range: {:f}", val); + props.Rate = val; + return; case AL_CHORUS_DEPTH: if(!(val >= AL_CHORUS_MIN_DEPTH && val <= AL_CHORUS_MAX_DEPTH)) - throw effect_exception{AL_INVALID_VALUE, "Chorus depth out of range: %f", val}; - props->Chorus.Depth = val; - break; + context->throw_error(AL_INVALID_VALUE, "Chorus depth out of range: {:f}", val); + props.Depth = val; + return; case AL_CHORUS_FEEDBACK: if(!(val >= AL_CHORUS_MIN_FEEDBACK && val <= AL_CHORUS_MAX_FEEDBACK)) - throw effect_exception{AL_INVALID_VALUE, "Chorus feedback out of range: %f", val}; - props->Chorus.Feedback = val; - break; + context->throw_error(AL_INVALID_VALUE, "Chorus feedback out of range: {:f}", val); + props.Feedback = val; + return; case AL_CHORUS_DELAY: if(!(val >= AL_CHORUS_MIN_DELAY && val <= AL_CHORUS_MAX_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "Chorus delay out of range: %f", val}; - props->Chorus.Delay = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Chorus delay out of range: {:f}", val); + props.Delay = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid chorus float property {:#04x}", + as_unsigned(param)); } -void Chorus_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Chorus_setParamf(props, param, vals[0]); } +void ChorusEffectHandler::SetParamfv(ALCcontext *context, ChorusProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void Chorus_getParami(const EffectProps *props, ALenum param, int *val) +void ChorusEffectHandler::GetParami(ALCcontext *context, const ChorusProps &props, ALenum param, int *val) { switch(param) { - case AL_CHORUS_WAVEFORM: - *val = EnumFromWaveform(props->Chorus.Waveform); - break; - - case AL_CHORUS_PHASE: - *val = props->Chorus.Phase; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid chorus integer property 0x%04x", param}; + case AL_CHORUS_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return; + case AL_CHORUS_PHASE: *val = props.Phase; return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid chorus integer property {:#04x}", + as_unsigned(param)); } -void Chorus_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Chorus_getParami(props, param, vals); } -void Chorus_getParamf(const EffectProps *props, ALenum param, float *val) +void ChorusEffectHandler::GetParamiv(ALCcontext *context, const ChorusProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void ChorusEffectHandler::GetParamf(ALCcontext *context, const ChorusProps &props, ALenum param, float *val) { switch(param) { - case AL_CHORUS_RATE: - *val = props->Chorus.Rate; - break; - - case AL_CHORUS_DEPTH: - *val = props->Chorus.Depth; - break; - - case AL_CHORUS_FEEDBACK: - *val = props->Chorus.Feedback; - break; - - case AL_CHORUS_DELAY: - *val = props->Chorus.Delay; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid chorus float property 0x%04x", param}; + case AL_CHORUS_RATE: *val = props.Rate; return; + case AL_CHORUS_DEPTH: *val = props.Depth; return; + case AL_CHORUS_FEEDBACK: *val = props.Feedback; return; + case AL_CHORUS_DELAY: *val = props.Delay; return; } -} -void Chorus_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Chorus_getParamf(props, param, vals); } -EffectProps genDefaultChorusProps() noexcept -{ - EffectProps props{}; - props.Chorus.Waveform = *WaveformFromEnum(AL_CHORUS_DEFAULT_WAVEFORM); - props.Chorus.Phase = AL_CHORUS_DEFAULT_PHASE; - props.Chorus.Rate = AL_CHORUS_DEFAULT_RATE; - props.Chorus.Depth = AL_CHORUS_DEFAULT_DEPTH; - props.Chorus.Feedback = AL_CHORUS_DEFAULT_FEEDBACK; - props.Chorus.Delay = AL_CHORUS_DEFAULT_DELAY; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid chorus float property {:#04x}", + as_unsigned(param)); } +void ChorusEffectHandler::GetParamfv(ALCcontext *context, const ChorusProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -void Flanger_setParami(EffectProps *props, ALenum param, int val) +const EffectProps FlangerEffectProps{genDefaultFlangerProps()}; + +void FlangerEffectHandler::SetParami(ALCcontext *context, ChorusProps &props, ALenum param, int val) { switch(param) { case AL_FLANGER_WAVEFORM: if(auto formopt = WaveformFromEnum(val)) - props->Chorus.Waveform = *formopt; + props.Waveform = *formopt; else - throw effect_exception{AL_INVALID_VALUE, "Invalid flanger waveform: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, "Invalid flanger waveform: {:#04x}", + as_unsigned(val)); + return; case AL_FLANGER_PHASE: if(!(val >= AL_FLANGER_MIN_PHASE && val <= AL_FLANGER_MAX_PHASE)) - throw effect_exception{AL_INVALID_VALUE, "Flanger phase out of range: %d", val}; - props->Chorus.Phase = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Flanger phase out of range: {}", val); + props.Phase = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid flanger integer property {:#04x}", + as_unsigned(param)); } -void Flanger_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Flanger_setParami(props, param, vals[0]); } -void Flanger_setParamf(EffectProps *props, ALenum param, float val) +void FlangerEffectHandler::SetParamiv(ALCcontext *context, ChorusProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void FlangerEffectHandler::SetParamf(ALCcontext *context, ChorusProps &props, ALenum param, float val) { switch(param) { case AL_FLANGER_RATE: if(!(val >= AL_FLANGER_MIN_RATE && val <= AL_FLANGER_MAX_RATE)) - throw effect_exception{AL_INVALID_VALUE, "Flanger rate out of range: %f", val}; - props->Chorus.Rate = val; - break; + context->throw_error(AL_INVALID_VALUE, "Flanger rate out of range: {:f}", val); + props.Rate = val; + return; case AL_FLANGER_DEPTH: if(!(val >= AL_FLANGER_MIN_DEPTH && val <= AL_FLANGER_MAX_DEPTH)) - throw effect_exception{AL_INVALID_VALUE, "Flanger depth out of range: %f", val}; - props->Chorus.Depth = val; - break; + context->throw_error(AL_INVALID_VALUE, "Flanger depth out of range: {:f}", val); + props.Depth = val; + return; case AL_FLANGER_FEEDBACK: if(!(val >= AL_FLANGER_MIN_FEEDBACK && val <= AL_FLANGER_MAX_FEEDBACK)) - throw effect_exception{AL_INVALID_VALUE, "Flanger feedback out of range: %f", val}; - props->Chorus.Feedback = val; - break; + context->throw_error(AL_INVALID_VALUE, "Flanger feedback out of range: {:f}", val); + props.Feedback = val; + return; case AL_FLANGER_DELAY: if(!(val >= AL_FLANGER_MIN_DELAY && val <= AL_FLANGER_MAX_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "Flanger delay out of range: %f", val}; - props->Chorus.Delay = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Flanger delay out of range: {:f}", val); + props.Delay = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid flanger float property {:#04x}", + as_unsigned(param)); } -void Flanger_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Flanger_setParamf(props, param, vals[0]); } +void FlangerEffectHandler::SetParamfv(ALCcontext *context, ChorusProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void Flanger_getParami(const EffectProps *props, ALenum param, int *val) +void FlangerEffectHandler::GetParami(ALCcontext *context, const ChorusProps &props, ALenum param, int *val) { switch(param) { - case AL_FLANGER_WAVEFORM: - *val = EnumFromWaveform(props->Chorus.Waveform); - break; - - case AL_FLANGER_PHASE: - *val = props->Chorus.Phase; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid flanger integer property 0x%04x", param}; + case AL_FLANGER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return; + case AL_FLANGER_PHASE: *val = props.Phase; return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid flanger integer property {:#04x}", + as_unsigned(param)); } -void Flanger_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Flanger_getParami(props, param, vals); } -void Flanger_getParamf(const EffectProps *props, ALenum param, float *val) +void FlangerEffectHandler::GetParamiv(ALCcontext *context, const ChorusProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void FlangerEffectHandler::GetParamf(ALCcontext *context, const ChorusProps &props, ALenum param, float *val) { switch(param) { - case AL_FLANGER_RATE: - *val = props->Chorus.Rate; - break; - - case AL_FLANGER_DEPTH: - *val = props->Chorus.Depth; - break; - - case AL_FLANGER_FEEDBACK: - *val = props->Chorus.Feedback; - break; - - case AL_FLANGER_DELAY: - *val = props->Chorus.Delay; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid flanger float property 0x%04x", param}; + case AL_FLANGER_RATE: *val = props.Rate; return; + case AL_FLANGER_DEPTH: *val = props.Depth; return; + case AL_FLANGER_FEEDBACK: *val = props.Feedback; return; + case AL_FLANGER_DELAY: *val = props.Delay; return; } -} -void Flanger_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Flanger_getParamf(props, param, vals); } -EffectProps genDefaultFlangerProps() noexcept -{ - EffectProps props{}; - props.Chorus.Waveform = *WaveformFromEnum(AL_FLANGER_DEFAULT_WAVEFORM); - props.Chorus.Phase = AL_FLANGER_DEFAULT_PHASE; - props.Chorus.Rate = AL_FLANGER_DEFAULT_RATE; - props.Chorus.Depth = AL_FLANGER_DEFAULT_DEPTH; - props.Chorus.Feedback = AL_FLANGER_DEFAULT_FEEDBACK; - props.Chorus.Delay = AL_FLANGER_DEFAULT_DELAY; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid flanger float property {:#04x}", + as_unsigned(param)); } +void FlangerEffectHandler::GetParamfv(ALCcontext *context, const ChorusProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace -DEFINE_ALEFFECT_VTABLE(Chorus); - -const EffectProps ChorusEffectProps{genDefaultChorusProps()}; - -DEFINE_ALEFFECT_VTABLE(Flanger); - -const EffectProps FlangerEffectProps{genDefaultFlangerProps()}; - - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { struct EaxChorusTraits { - using Props = EAXCHORUSPROPERTIES; + using EaxProps = EAXCHORUSPROPERTIES; using Committer = EaxChorusCommitter; static constexpr auto efx_effect() { return AL_EFFECT_CHORUS; } @@ -357,7 +325,7 @@ struct EaxChorusTraits { }; // EaxChorusTraits struct EaxFlangerTraits { - using Props = EAXFLANGERPROPERTIES; + using EaxProps = EAXFLANGERPROPERTIES; using Committer = EaxFlangerCommitter; static constexpr auto efx_effect() { return AL_EFFECT_FLANGER; } @@ -424,6 +392,7 @@ struct EaxFlangerTraits { template struct ChorusFlangerEffect { using Traits = TTraits; + using EaxProps = typename Traits::EaxProps; using Committer = typename Traits::Committer; using Exception = typename Committer::Exception; @@ -494,7 +463,7 @@ struct ChorusFlangerEffect { }; // DelayValidator struct AllValidator { - void operator()(const typename Traits::Props& all) const + void operator()(const EaxProps& all) const { WaveformValidator{}(all.ulWaveform); PhaseValidator{}(all.lPhase); @@ -508,7 +477,7 @@ struct ChorusFlangerEffect { public: static void SetDefaults(EaxEffectProps &props) { - auto&& all = props.emplace(); + auto&& all = props.emplace(); all.ulWaveform = Traits::eax_default_waveform(); all.lPhase = Traits::eax_default_phase(); all.flRate = Traits::eax_default_rate(); @@ -518,102 +487,94 @@ struct ChorusFlangerEffect { } - static void Get(const EaxCall &call, const EaxEffectProps &props) + static void Get(const EaxCall &call, const EaxProps &all) { - auto&& all = std::get(props); switch(call.get_property_id()) { case Traits::eax_none_param_id(): break; - case Traits::eax_allparameters_param_id(): call.template set_value(all); break; - case Traits::eax_waveform_param_id(): call.template set_value(all.ulWaveform); break; - case Traits::eax_phase_param_id(): call.template set_value(all.lPhase); break; - case Traits::eax_rate_param_id(): call.template set_value(all.flRate); break; - case Traits::eax_depth_param_id(): call.template set_value(all.flDepth); break; - case Traits::eax_feedback_param_id(): call.template set_value(all.flFeedback); break; - case Traits::eax_delay_param_id(): call.template set_value(all.flDelay); break; - default: Committer::fail_unknown_property_id(); } } - static void Set(const EaxCall &call, EaxEffectProps &props) + static void Set(const EaxCall &call, EaxProps &all) { - auto&& all = std::get(props); switch(call.get_property_id()) { case Traits::eax_none_param_id(): break; - case Traits::eax_allparameters_param_id(): Committer::template defer(call, all); break; - case Traits::eax_waveform_param_id(): Committer::template defer(call, all.ulWaveform); break; - case Traits::eax_phase_param_id(): Committer::template defer(call, all.lPhase); break; - case Traits::eax_rate_param_id(): Committer::template defer(call, all.flRate); break; - case Traits::eax_depth_param_id(): Committer::template defer(call, all.flDepth); break; - case Traits::eax_feedback_param_id(): Committer::template defer(call, all.flFeedback); break; - case Traits::eax_delay_param_id(): Committer::template defer(call, all.flDelay); break; - default: Committer::fail_unknown_property_id(); } } - static bool Commit(const EaxEffectProps &props, EaxEffectProps &props_, EffectProps &al_props_) + static bool Commit(const EaxProps &props, EaxEffectProps &props_, ChorusProps &al_props_) { - if(props == props_) + if(auto *cur = std::get_if(&props_); cur && *cur == props) return false; props_ = props; - auto&& dst = std::get(props); - al_props_.Chorus.Waveform = Traits::eax_waveform(dst.ulWaveform); - al_props_.Chorus.Phase = static_cast(dst.lPhase); - al_props_.Chorus.Rate = dst.flRate; - al_props_.Chorus.Depth = dst.flDepth; - al_props_.Chorus.Feedback = dst.flFeedback; - al_props_.Chorus.Delay = dst.flDelay; + al_props_.Waveform = Traits::eax_waveform(props.ulWaveform); + al_props_.Phase = static_cast(props.lPhase); + al_props_.Rate = props.flRate; + al_props_.Depth = props.flDepth; + al_props_.Feedback = props.flFeedback; + al_props_.Delay = props.flDelay; + if(EaxTraceCommits) UNLIKELY + { + TRACE("Chorus/flanger commit:\n" + " Waveform: {}\n" + " Phase: {}\n" + " Rate: {:f}\n" + " Depth: {:f}\n" + " Feedback: {:f}\n" + " Delay: {:f}", al::to_underlying(al_props_.Waveform), al_props_.Phase, + al_props_.Rate, al_props_.Depth, al_props_.Feedback, al_props_.Delay); + } return true; } @@ -638,29 +599,25 @@ template<> throw Exception{message}; } -template<> -bool ChorusCommitter::commit(const EaxEffectProps &props) +bool EaxChorusCommitter::commit(const EAXCHORUSPROPERTIES &props) { using Committer = ChorusFlangerEffect; - return Committer::Commit(props, mEaxProps, mAlProps); + return Committer::Commit(props, mEaxProps, mAlProps.emplace()); } -template<> -void ChorusCommitter::SetDefaults(EaxEffectProps &props) +void EaxChorusCommitter::SetDefaults(EaxEffectProps &props) { using Committer = ChorusFlangerEffect; Committer::SetDefaults(props); } -template<> -void ChorusCommitter::Get(const EaxCall &call, const EaxEffectProps &props) +void EaxChorusCommitter::Get(const EaxCall &call, const EAXCHORUSPROPERTIES &props) { using Committer = ChorusFlangerEffect; Committer::Get(call, props); } -template<> -void ChorusCommitter::Set(const EaxCall &call, EaxEffectProps &props) +void EaxChorusCommitter::Set(const EaxCall &call, EAXCHORUSPROPERTIES &props) { using Committer = ChorusFlangerEffect; Committer::Set(call, props); @@ -679,29 +636,25 @@ template<> throw Exception{message}; } -template<> -bool FlangerCommitter::commit(const EaxEffectProps &props) +bool EaxFlangerCommitter::commit(const EAXFLANGERPROPERTIES &props) { using Committer = ChorusFlangerEffect; - return Committer::Commit(props, mEaxProps, mAlProps); + return Committer::Commit(props, mEaxProps, mAlProps.emplace()); } -template<> -void FlangerCommitter::SetDefaults(EaxEffectProps &props) +void EaxFlangerCommitter::SetDefaults(EaxEffectProps &props) { using Committer = ChorusFlangerEffect; Committer::SetDefaults(props); } -template<> -void FlangerCommitter::Get(const EaxCall &call, const EaxEffectProps &props) +void EaxFlangerCommitter::Get(const EaxCall &call, const EAXFLANGERPROPERTIES &props) { using Committer = ChorusFlangerEffect; Committer::Get(call, props); } -template<> -void FlangerCommitter::Set(const EaxCall &call, EaxEffectProps &props) +void EaxFlangerCommitter::Set(const EaxCall &call, EAXFLANGERPROPERTIES &props) { using Committer = ChorusFlangerEffect; Committer::Set(call, props); diff --git a/3rdparty/openal/al/effects/compressor.cpp b/3rdparty/openal/al/effects/compressor.cpp index ca8af84face0..f5c6786af140 100644 --- a/3rdparty/openal/al/effects/compressor.cpp +++ b/3rdparty/openal/al/effects/compressor.cpp @@ -4,11 +4,12 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -16,68 +17,57 @@ namespace { -void Compressor_setParami(EffectProps *props, ALenum param, int val) +constexpr EffectProps genDefaultProps() noexcept +{ + CompressorProps props{}; + props.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF; + return props; +} + +} // namespace + +const EffectProps CompressorEffectProps{genDefaultProps()}; + +void CompressorEffectHandler::SetParami(ALCcontext *context, CompressorProps &props, ALenum param, int val) { switch(param) { case AL_COMPRESSOR_ONOFF: if(!(val >= AL_COMPRESSOR_MIN_ONOFF && val <= AL_COMPRESSOR_MAX_ONOFF)) - throw effect_exception{AL_INVALID_VALUE, "Compressor state out of range"}; - props->Compressor.OnOff = (val != AL_FALSE); - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "Compressor state out of range"); + props.OnOff = (val != AL_FALSE); + return; } -} -void Compressor_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Compressor_setParami(props, param, vals[0]); } -void Compressor_setParamf(EffectProps*, ALenum param, float) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; } -void Compressor_setParamfv(EffectProps*, ALenum param, const float*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x", - param}; -} -void Compressor_getParami(const EffectProps *props, ALenum param, int *val) + context->throw_error(AL_INVALID_ENUM, "Invalid compressor integer property {:#04x}", + as_unsigned(param)); +} +void CompressorEffectHandler::SetParamiv(ALCcontext *context, CompressorProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void CompressorEffectHandler::SetParamf(ALCcontext *context, CompressorProps&, ALenum param, float) +{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float property {:#04x}", as_unsigned(param)); } +void CompressorEffectHandler::SetParamfv(ALCcontext *context, CompressorProps&, ALenum param, const float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float-vector property {:#04x}", as_unsigned(param)); } + +void CompressorEffectHandler::GetParami(ALCcontext *context, const CompressorProps &props, ALenum param, int *val) { switch(param) { - case AL_COMPRESSOR_ONOFF: - *val = props->Compressor.OnOff; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid compressor integer property 0x%04x", - param}; + case AL_COMPRESSOR_ONOFF: *val = props.OnOff; return; } -} -void Compressor_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Compressor_getParami(props, param, vals); } -void Compressor_getParamf(const EffectProps*, ALenum param, float*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float property 0x%04x", param}; } -void Compressor_getParamfv(const EffectProps*, ALenum param, float*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid compressor float-vector property 0x%04x", - param}; -} -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Compressor.OnOff = AL_COMPRESSOR_DEFAULT_ONOFF; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid compressor integer property {:#04x}", + as_unsigned(param)); } +void CompressorEffectHandler::GetParamiv(ALCcontext *context, const CompressorProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void CompressorEffectHandler::GetParamf(ALCcontext *context, const CompressorProps&, ALenum param, float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float property {:#04x}", as_unsigned(param)); } +void CompressorEffectHandler::GetParamfv(ALCcontext *context, const CompressorProps&, ALenum param, float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid compressor float-vector property {:#04x}", as_unsigned(param)); } -} // namespace -DEFINE_ALEFFECT_VTABLE(Compressor); - -const EffectProps CompressorEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using CompressorCommitter = EaxCommitter; @@ -115,28 +105,24 @@ template<> throw Exception{message}; } -template<> -bool CompressorCommitter::commit(const EaxEffectProps &props) +bool EaxCompressorCommitter::commit(const EAXAGCCOMPRESSORPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; + mAlProps = CompressorProps{props.ulOnOff != 0}; - mAlProps.Compressor.OnOff = (std::get(props).ulOnOff != 0); return true; } -template<> -void CompressorCommitter::SetDefaults(EaxEffectProps &props) +void EaxCompressorCommitter::SetDefaults(EaxEffectProps &props) { props = EAXAGCCOMPRESSORPROPERTIES{EAXAGCCOMPRESSOR_DEFAULTONOFF}; } -template<> -void CompressorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxCompressorCommitter::Get(const EaxCall &call, const EAXAGCCOMPRESSORPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; @@ -146,10 +132,8 @@ void CompressorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void CompressorCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxCompressorCommitter::Set(const EaxCall &call, EAXAGCCOMPRESSORPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXAGCCOMPRESSOR_NONE: break; diff --git a/3rdparty/openal/al/effects/convolution.cpp b/3rdparty/openal/al/effects/convolution.cpp index 8e850fd3e20b..84de06c18537 100644 --- a/3rdparty/openal/al/effects/convolution.cpp +++ b/3rdparty/openal/al/effects/convolution.cpp @@ -1,93 +1,76 @@ #include "config.h" +#include +#include +#include + #include "AL/al.h" -#include "alc/inprogext.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alc/inprogext.h" +#include "alnumeric.h" +#include "alspan.h" #include "effects.h" namespace { -void Convolution_setParami(EffectProps* /*props*/, ALenum param, int /*val*/) -{ - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", - param}; - } -} -void Convolution_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ - switch(param) - { - default: - Convolution_setParami(props, param, vals[0]); - } -} -void Convolution_setParamf(EffectProps* /*props*/, ALenum param, float /*val*/) +constexpr EffectProps genDefaultProps() noexcept { - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", - param}; - } -} -void Convolution_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ - switch(param) - { - default: - Convolution_setParamf(props, param, vals[0]); - } + ConvolutionProps props{}; + props.OrientAt = {0.0f, 0.0f, -1.0f}; + props.OrientUp = {0.0f, 1.0f, 0.0f}; + return props; } -void Convolution_getParami(const EffectProps* /*props*/, ALenum param, int* /*val*/) -{ - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", - param}; - } -} -void Convolution_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ - switch(param) - { - default: - Convolution_getParami(props, param, vals); - } -} -void Convolution_getParamf(const EffectProps* /*props*/, ALenum param, float* /*val*/) +} // namespace + +const EffectProps ConvolutionEffectProps{genDefaultProps()}; + +void ConvolutionEffectHandler::SetParami(ALCcontext *context, ConvolutionProps& /*props*/, ALenum param, int /*val*/) +{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect integer property {:#04x}", as_unsigned(param)); } +void ConvolutionEffectHandler::SetParamiv(ALCcontext *context, ConvolutionProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } + +void ConvolutionEffectHandler::SetParamf(ALCcontext *context, ConvolutionProps& /*props*/, ALenum param, float /*val*/) +{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect float property {:#04x}", as_unsigned(param)); } +void ConvolutionEffectHandler::SetParamfv(ALCcontext *context, ConvolutionProps &props, ALenum param, const float *values) { + static constexpr auto finite_checker = [](float val) -> bool { return std::isfinite(val); }; + switch(param) { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", - param}; + case AL_CONVOLUTION_ORIENTATION_SOFT: + auto vals = al::span{values, 6_uz}; + if(!std::all_of(vals.cbegin(), vals.cend(), finite_checker)) + context->throw_error(AL_INVALID_VALUE, "Convolution orientation out of range", param); + + std::copy_n(vals.cbegin(), props.OrientAt.size(), props.OrientAt.begin()); + std::copy_n(vals.cbegin()+3, props.OrientUp.size(), props.OrientUp.begin()); + return; } + + SetParamf(context, props, param, *values); } -void Convolution_getParamfv(const EffectProps *props, ALenum param, float *vals) + +void ConvolutionEffectHandler::GetParami(ALCcontext *context, const ConvolutionProps& /*props*/, ALenum param, int* /*val*/) +{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect integer property {:#04x}", as_unsigned(param)); } +void ConvolutionEffectHandler::GetParamiv(ALCcontext *context, const ConvolutionProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } + +void ConvolutionEffectHandler::GetParamf(ALCcontext *context, const ConvolutionProps& /*props*/, ALenum param, float* /*val*/) +{ context->throw_error(AL_INVALID_ENUM, "Invalid convolution effect float property {:#04x}", as_unsigned(param)); } +void ConvolutionEffectHandler::GetParamfv(ALCcontext *context, const ConvolutionProps &props, ALenum param, float *values) { switch(param) { - default: - Convolution_getParamf(props, param, vals); + case AL_CONVOLUTION_ORIENTATION_SOFT: + auto vals = al::span{values, 6_uz}; + std::copy(props.OrientAt.cbegin(), props.OrientAt.cend(), vals.begin()); + std::copy(props.OrientUp.cbegin(), props.OrientUp.cend(), vals.begin()+3); + return; } -} -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - return props; + GetParamf(context, props, param, values); } - -} // namespace - -DEFINE_ALEFFECT_VTABLE(Convolution); - -const EffectProps ConvolutionEffectProps{genDefaultProps()}; diff --git a/3rdparty/openal/al/effects/dedicated.cpp b/3rdparty/openal/al/effects/dedicated.cpp index db57003c2af9..5776b42be27c 100644 --- a/3rdparty/openal/al/effects/dedicated.cpp +++ b/3rdparty/openal/al/effects/dedicated.cpp @@ -6,67 +6,108 @@ #include "AL/al.h" #include "AL/alext.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" namespace { -void Dedicated_setParami(EffectProps*, ALenum param, int) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; } -void Dedicated_setParamiv(EffectProps*, ALenum param, const int*) +constexpr EffectProps genDefaultDialogProps() noexcept { - throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x", - param}; + DedicatedProps props{}; + props.Target = DedicatedProps::Dialog; + props.Gain = 1.0f; + return props; } -void Dedicated_setParamf(EffectProps *props, ALenum param, float val) + +constexpr EffectProps genDefaultLfeProps() noexcept +{ + DedicatedProps props{}; + props.Target = DedicatedProps::Lfe; + props.Gain = 1.0f; + return props; +} + +} // namespace + +const EffectProps DedicatedDialogEffectProps{genDefaultDialogProps()}; + +void DedicatedDialogEffectHandler::SetParami(ALCcontext *context, DedicatedProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); } +void DedicatedDialogEffectHandler::SetParamiv(ALCcontext *context, DedicatedProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); } +void DedicatedDialogEffectHandler::SetParamf(ALCcontext *context, DedicatedProps &props, ALenum param, float val) { switch(param) { case AL_DEDICATED_GAIN: if(!(val >= 0.0f && std::isfinite(val))) - throw effect_exception{AL_INVALID_VALUE, "Dedicated gain out of range"}; - props->Dedicated.Gain = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Dedicated gain out of range"); + props.Gain = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}", + as_unsigned(param)); } -void Dedicated_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Dedicated_setParamf(props, param, vals[0]); } +void DedicatedDialogEffectHandler::SetParamfv(ALCcontext *context, DedicatedProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void Dedicated_getParami(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer property 0x%04x", param}; } -void Dedicated_getParamiv(const EffectProps*, ALenum param, int*) +void DedicatedDialogEffectHandler::GetParami(ALCcontext *context, const DedicatedProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); } +void DedicatedDialogEffectHandler::GetParamiv(ALCcontext *context, const DedicatedProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); } +void DedicatedDialogEffectHandler::GetParamf(ALCcontext *context, const DedicatedProps &props, ALenum param, float *val) { - throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated integer-vector property 0x%04x", - param}; + switch(param) + { + case AL_DEDICATED_GAIN: *val = props.Gain; return; + } + + context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}", + as_unsigned(param)); } -void Dedicated_getParamf(const EffectProps *props, ALenum param, float *val) +void DedicatedDialogEffectHandler::GetParamfv(ALCcontext *context, const DedicatedProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } + + +const EffectProps DedicatedLfeEffectProps{genDefaultLfeProps()}; + +void DedicatedLfeEffectHandler::SetParami(ALCcontext *context, DedicatedProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); } +void DedicatedLfeEffectHandler::SetParamiv(ALCcontext *context, DedicatedProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); } +void DedicatedLfeEffectHandler::SetParamf(ALCcontext *context, DedicatedProps &props, ALenum param, float val) { switch(param) { case AL_DEDICATED_GAIN: - *val = props->Dedicated.Gain; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid dedicated float property 0x%04x", param}; + if(!(val >= 0.0f && std::isfinite(val))) + context->throw_error(AL_INVALID_VALUE, "Dedicated gain out of range"); + props.Gain = val; + return; } -} -void Dedicated_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Dedicated_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Dedicated.Gain = 1.0f; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}", + as_unsigned(param)); } +void DedicatedLfeEffectHandler::SetParamfv(ALCcontext *context, DedicatedProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Dedicated); +void DedicatedLfeEffectHandler::GetParami(ALCcontext *context, const DedicatedProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer property {:#04x}", as_unsigned(param)); } +void DedicatedLfeEffectHandler::GetParamiv(ALCcontext *context, const DedicatedProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid dedicated integer-vector property {:#04x}", as_unsigned(param)); } +void DedicatedLfeEffectHandler::GetParamf(ALCcontext *context, const DedicatedProps &props, ALenum param, float *val) +{ + switch(param) + { + case AL_DEDICATED_GAIN: *val = props.Gain; return; + } -const EffectProps DedicatedEffectProps{genDefaultProps()}; + context->throw_error(AL_INVALID_ENUM, "Invalid dedicated float property {:#04x}", + as_unsigned(param)); +} +void DedicatedLfeEffectHandler::GetParamfv(ALCcontext *context, const DedicatedProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } diff --git a/3rdparty/openal/al/effects/distortion.cpp b/3rdparty/openal/al/effects/distortion.cpp index e046d8e72490..2109e384bcd1 100644 --- a/3rdparty/openal/al/effects/distortion.cpp +++ b/3rdparty/openal/al/effects/distortion.cpp @@ -4,11 +4,12 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -16,110 +17,91 @@ namespace { -void Distortion_setParami(EffectProps*, ALenum param, int) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; } -void Distortion_setParamiv(EffectProps*, ALenum param, const int*) +constexpr EffectProps genDefaultProps() noexcept { - throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", - param}; + DistortionProps props{}; + props.Edge = AL_DISTORTION_DEFAULT_EDGE; + props.Gain = AL_DISTORTION_DEFAULT_GAIN; + props.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF; + props.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER; + props.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH; + return props; } -void Distortion_setParamf(EffectProps *props, ALenum param, float val) + +} // namespace + +const EffectProps DistortionEffectProps{genDefaultProps()}; + +void DistortionEffectHandler::SetParami(ALCcontext *context, DistortionProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer property {:#04x}", as_unsigned(param)); } +void DistortionEffectHandler::SetParamiv(ALCcontext *context, DistortionProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer-vector property {:#04x}", as_unsigned(param)); } + +void DistortionEffectHandler::SetParamf(ALCcontext *context, DistortionProps &props, ALenum param, float val) { switch(param) { case AL_DISTORTION_EDGE: if(!(val >= AL_DISTORTION_MIN_EDGE && val <= AL_DISTORTION_MAX_EDGE)) - throw effect_exception{AL_INVALID_VALUE, "Distortion edge out of range"}; - props->Distortion.Edge = val; - break; + context->throw_error(AL_INVALID_VALUE, "Distortion edge out of range"); + props.Edge = val; + return; case AL_DISTORTION_GAIN: if(!(val >= AL_DISTORTION_MIN_GAIN && val <= AL_DISTORTION_MAX_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Distortion gain out of range"}; - props->Distortion.Gain = val; - break; + context->throw_error(AL_INVALID_VALUE, "Distortion gain out of range"); + props.Gain = val; + return; case AL_DISTORTION_LOWPASS_CUTOFF: if(!(val >= AL_DISTORTION_MIN_LOWPASS_CUTOFF && val <= AL_DISTORTION_MAX_LOWPASS_CUTOFF)) - throw effect_exception{AL_INVALID_VALUE, "Distortion low-pass cutoff out of range"}; - props->Distortion.LowpassCutoff = val; - break; + context->throw_error(AL_INVALID_VALUE, "Distortion low-pass cutoff out of range"); + props.LowpassCutoff = val; + return; case AL_DISTORTION_EQCENTER: if(!(val >= AL_DISTORTION_MIN_EQCENTER && val <= AL_DISTORTION_MAX_EQCENTER)) - throw effect_exception{AL_INVALID_VALUE, "Distortion EQ center out of range"}; - props->Distortion.EQCenter = val; - break; + context->throw_error(AL_INVALID_VALUE, "Distortion EQ center out of range"); + props.EQCenter = val; + return; case AL_DISTORTION_EQBANDWIDTH: if(!(val >= AL_DISTORTION_MIN_EQBANDWIDTH && val <= AL_DISTORTION_MAX_EQBANDWIDTH)) - throw effect_exception{AL_INVALID_VALUE, "Distortion EQ bandwidth out of range"}; - props->Distortion.EQBandwidth = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Distortion EQ bandwidth out of range"); + props.EQBandwidth = val; + return; } -} -void Distortion_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Distortion_setParamf(props, param, vals[0]); } -void Distortion_getParami(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer property 0x%04x", param}; } -void Distortion_getParamiv(const EffectProps*, ALenum param, int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid distortion integer-vector property 0x%04x", - param}; + context->throw_error(AL_INVALID_ENUM, "Invalid distortion float property {:#04x}", + as_unsigned(param)); } -void Distortion_getParamf(const EffectProps *props, ALenum param, float *val) +void DistortionEffectHandler::SetParamfv(ALCcontext *context, DistortionProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void DistortionEffectHandler::GetParami(ALCcontext *context, const DistortionProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer property {:#04x}", as_unsigned(param)); } +void DistortionEffectHandler::GetParamiv(ALCcontext *context, const DistortionProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid distortion integer-vector property {:#04x}", as_unsigned(param)); } + +void DistortionEffectHandler::GetParamf(ALCcontext *context, const DistortionProps &props, ALenum param, float *val) { switch(param) { - case AL_DISTORTION_EDGE: - *val = props->Distortion.Edge; - break; - - case AL_DISTORTION_GAIN: - *val = props->Distortion.Gain; - break; - - case AL_DISTORTION_LOWPASS_CUTOFF: - *val = props->Distortion.LowpassCutoff; - break; - - case AL_DISTORTION_EQCENTER: - *val = props->Distortion.EQCenter; - break; - - case AL_DISTORTION_EQBANDWIDTH: - *val = props->Distortion.EQBandwidth; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid distortion float property 0x%04x", param}; + case AL_DISTORTION_EDGE: *val = props.Edge; return; + case AL_DISTORTION_GAIN: *val = props.Gain; return; + case AL_DISTORTION_LOWPASS_CUTOFF: *val = props.LowpassCutoff; return; + case AL_DISTORTION_EQCENTER: *val = props.EQCenter; return; + case AL_DISTORTION_EQBANDWIDTH: *val = props.EQBandwidth; return; } -} -void Distortion_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Distortion_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Distortion.Edge = AL_DISTORTION_DEFAULT_EDGE; - props.Distortion.Gain = AL_DISTORTION_DEFAULT_GAIN; - props.Distortion.LowpassCutoff = AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF; - props.Distortion.EQCenter = AL_DISTORTION_DEFAULT_EQCENTER; - props.Distortion.EQBandwidth = AL_DISTORTION_DEFAULT_EQBANDWIDTH; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid distortion float property {:#04x}", + as_unsigned(param)); } +void DistortionEffectHandler::GetParamfv(ALCcontext *context, const DistortionProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Distortion); - -const EffectProps DistortionEffectProps{genDefaultProps()}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using DistortionCommitter = EaxCommitter; @@ -204,26 +186,26 @@ template<> throw Exception{message}; } -template<> -bool DistortionCommitter::commit(const EaxEffectProps &props) +bool EaxDistortionCommitter::commit(const EAXDISTORTIONPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - - auto &eaxprops = std::get(props); - mAlProps.Distortion.Edge = eaxprops.flEdge; - mAlProps.Distortion.Gain = level_mb_to_gain(static_cast(eaxprops.lGain)); - mAlProps.Distortion.LowpassCutoff = eaxprops.flLowPassCutOff; - mAlProps.Distortion.EQCenter = eaxprops.flEQCenter; - mAlProps.Distortion.EQBandwidth = eaxprops.flEdge; + mAlProps = [&]{ + DistortionProps ret{}; + ret.Edge = props.flEdge; + ret.Gain = level_mb_to_gain(static_cast(props.lGain)); + ret.LowpassCutoff = props.flLowPassCutOff; + ret.EQCenter = props.flEQCenter; + ret.EQBandwidth = props.flEdge; + return ret; + }(); return true; } -template<> -void DistortionCommitter::SetDefaults(EaxEffectProps &props) +void EaxDistortionCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXDISTORTIONPROPERTIES defprops{[] { @@ -238,10 +220,8 @@ void DistortionCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxDistortionCommitter::Get(const EaxCall &call, const EAXDISTORTIONPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXDISTORTION_NONE: break; @@ -255,10 +235,8 @@ void DistortionCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void DistortionCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxDistortionCommitter::Set(const EaxCall &call, EAXDISTORTIONPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXDISTORTION_NONE: break; diff --git a/3rdparty/openal/al/effects/echo.cpp b/3rdparty/openal/al/effects/echo.cpp index 48aacef34b0f..2a5faf0d0a43 100644 --- a/3rdparty/openal/al/effects/echo.cpp +++ b/3rdparty/openal/al/effects/echo.cpp @@ -4,11 +4,12 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -19,104 +20,89 @@ namespace { static_assert(EchoMaxDelay >= AL_ECHO_MAX_DELAY, "Echo max delay too short"); static_assert(EchoMaxLRDelay >= AL_ECHO_MAX_LRDELAY, "Echo max left-right delay too short"); -void Echo_setParami(EffectProps*, ALenum param, int) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; } -void Echo_setParamiv(EffectProps*, ALenum param, const int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; } -void Echo_setParamf(EffectProps *props, ALenum param, float val) +constexpr EffectProps genDefaultProps() noexcept +{ + EchoProps props{}; + props.Delay = AL_ECHO_DEFAULT_DELAY; + props.LRDelay = AL_ECHO_DEFAULT_LRDELAY; + props.Damping = AL_ECHO_DEFAULT_DAMPING; + props.Feedback = AL_ECHO_DEFAULT_FEEDBACK; + props.Spread = AL_ECHO_DEFAULT_SPREAD; + return props; +} + +} // namespace + +const EffectProps EchoEffectProps{genDefaultProps()}; + +void EchoEffectHandler::SetParami(ALCcontext *context, EchoProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer property {:#04x}", as_unsigned(param)); } +void EchoEffectHandler::SetParamiv(ALCcontext *context, EchoProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer-vector property {:#04x}", as_unsigned(param)); } +void EchoEffectHandler::SetParamf(ALCcontext *context, EchoProps &props, ALenum param, float val) { switch(param) { case AL_ECHO_DELAY: if(!(val >= AL_ECHO_MIN_DELAY && val <= AL_ECHO_MAX_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "Echo delay out of range"}; - props->Echo.Delay = val; - break; + context->throw_error(AL_INVALID_VALUE, "Echo delay out of range"); + props.Delay = val; + return; case AL_ECHO_LRDELAY: if(!(val >= AL_ECHO_MIN_LRDELAY && val <= AL_ECHO_MAX_LRDELAY)) - throw effect_exception{AL_INVALID_VALUE, "Echo LR delay out of range"}; - props->Echo.LRDelay = val; - break; + context->throw_error(AL_INVALID_VALUE, "Echo LR delay out of range"); + props.LRDelay = val; + return; case AL_ECHO_DAMPING: if(!(val >= AL_ECHO_MIN_DAMPING && val <= AL_ECHO_MAX_DAMPING)) - throw effect_exception{AL_INVALID_VALUE, "Echo damping out of range"}; - props->Echo.Damping = val; - break; + context->throw_error(AL_INVALID_VALUE, "Echo damping out of range"); + props.Damping = val; + return; case AL_ECHO_FEEDBACK: if(!(val >= AL_ECHO_MIN_FEEDBACK && val <= AL_ECHO_MAX_FEEDBACK)) - throw effect_exception{AL_INVALID_VALUE, "Echo feedback out of range"}; - props->Echo.Feedback = val; - break; + context->throw_error(AL_INVALID_VALUE, "Echo feedback out of range"); + props.Feedback = val; + return; case AL_ECHO_SPREAD: if(!(val >= AL_ECHO_MIN_SPREAD && val <= AL_ECHO_MAX_SPREAD)) - throw effect_exception{AL_INVALID_VALUE, "Echo spread out of range"}; - props->Echo.Spread = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Echo spread out of range"); + props.Spread = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid echo float property {:#04x}", + as_unsigned(param)); } -void Echo_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Echo_setParamf(props, param, vals[0]); } - -void Echo_getParami(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer property 0x%04x", param}; } -void Echo_getParamiv(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid echo integer-vector property 0x%04x", param}; } -void Echo_getParamf(const EffectProps *props, ALenum param, float *val) +void EchoEffectHandler::SetParamfv(ALCcontext *context, EchoProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void EchoEffectHandler::GetParami(ALCcontext *context, const EchoProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer property {:#04x}", as_unsigned(param)); } +void EchoEffectHandler::GetParamiv(ALCcontext *context, const EchoProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid echo integer-vector property {:#04x}", as_unsigned(param)); } +void EchoEffectHandler::GetParamf(ALCcontext *context, const EchoProps &props, ALenum param, float *val) { switch(param) { - case AL_ECHO_DELAY: - *val = props->Echo.Delay; - break; - - case AL_ECHO_LRDELAY: - *val = props->Echo.LRDelay; - break; - - case AL_ECHO_DAMPING: - *val = props->Echo.Damping; - break; - - case AL_ECHO_FEEDBACK: - *val = props->Echo.Feedback; - break; - - case AL_ECHO_SPREAD: - *val = props->Echo.Spread; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid echo float property 0x%04x", param}; + case AL_ECHO_DELAY: *val = props.Delay; return; + case AL_ECHO_LRDELAY: *val = props.LRDelay; return; + case AL_ECHO_DAMPING: *val = props.Damping; return; + case AL_ECHO_FEEDBACK: *val = props.Feedback; return; + case AL_ECHO_SPREAD: *val = props.Spread; return; } -} -void Echo_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Echo_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Echo.Delay = AL_ECHO_DEFAULT_DELAY; - props.Echo.LRDelay = AL_ECHO_DEFAULT_LRDELAY; - props.Echo.Damping = AL_ECHO_DEFAULT_DAMPING; - props.Echo.Feedback = AL_ECHO_DEFAULT_FEEDBACK; - props.Echo.Spread = AL_ECHO_DEFAULT_SPREAD; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid echo float property {:#04x}", + as_unsigned(param)); } +void EchoEffectHandler::GetParamfv(ALCcontext *context, const EchoProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Echo); -const EffectProps EchoEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using EchoCommitter = EaxCommitter; @@ -201,26 +187,26 @@ template<> throw Exception{message}; } -template<> -bool EchoCommitter::commit(const EaxEffectProps &props) +bool EaxEchoCommitter::commit(const EAXECHOPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - - auto &eaxprops = std::get(props); - mAlProps.Echo.Delay = eaxprops.flDelay; - mAlProps.Echo.LRDelay = eaxprops.flLRDelay; - mAlProps.Echo.Damping = eaxprops.flDamping; - mAlProps.Echo.Feedback = eaxprops.flFeedback; - mAlProps.Echo.Spread = eaxprops.flSpread; + mAlProps = [&]{ + EchoProps ret{}; + ret.Delay = props.flDelay; + ret.LRDelay = props.flLRDelay; + ret.Damping = props.flDamping; + ret.Feedback = props.flFeedback; + ret.Spread = props.flSpread; + return ret; + }(); return true; } -template<> -void EchoCommitter::SetDefaults(EaxEffectProps &props) +void EaxEchoCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXECHOPROPERTIES defprops{[] { @@ -235,10 +221,8 @@ void EchoCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxEchoCommitter::Get(const EaxCall &call, const EAXECHOPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXECHO_NONE: break; @@ -252,10 +236,8 @@ void EchoCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void EchoCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxEchoCommitter::Set(const EaxCall &call, EAXECHOPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXECHO_NONE: break; diff --git a/3rdparty/openal/al/effects/effects.cpp b/3rdparty/openal/al/effects/effects.cpp index 4a67b5ffeb45..ace4e70665e1 100644 --- a/3rdparty/openal/al/effects/effects.cpp +++ b/3rdparty/openal/al/effects/effects.cpp @@ -1,9 +1,3 @@ #include "config.h" -#ifdef ALSOFT_EAX - -#include -#include "AL/efx.h" #include "effects.h" - -#endif // ALSOFT_EAX diff --git a/3rdparty/openal/al/effects/effects.h b/3rdparty/openal/al/effects/effects.h index 9d57dd820e8a..76e5c9105b17 100644 --- a/3rdparty/openal/al/effects/effects.h +++ b/3rdparty/openal/al/effects/effects.h @@ -1,88 +1,64 @@ #ifndef AL_EFFECTS_EFFECTS_H #define AL_EFFECTS_EFFECTS_H -#include "AL/al.h" - -#include "core/except.h" - -#ifdef ALSOFT_EAX -#include "al/eax/effect.h" -#endif // ALSOFT_EAX - -union EffectProps; - - -class effect_exception final : public al::base_exception { - ALenum mErrorCode; - -public: -#ifdef __USE_MINGW_ANSI_STDIO - [[gnu::format(gnu_printf, 3, 4)]] -#else - [[gnu::format(printf, 3, 4)]] -#endif - effect_exception(ALenum code, const char *msg, ...); - ~effect_exception() override; +#include - ALenum errorCode() const noexcept { return mErrorCode; } -}; - - -struct EffectVtable { - void (*const setParami)(EffectProps *props, ALenum param, int val); - void (*const setParamiv)(EffectProps *props, ALenum param, const int *vals); - void (*const setParamf)(EffectProps *props, ALenum param, float val); - void (*const setParamfv)(EffectProps *props, ALenum param, const float *vals); +#include "AL/alc.h" +#include "AL/al.h" - void (*const getParami)(const EffectProps *props, ALenum param, int *val); - void (*const getParamiv)(const EffectProps *props, ALenum param, int *vals); - void (*const getParamf)(const EffectProps *props, ALenum param, float *val); - void (*const getParamfv)(const EffectProps *props, ALenum param, float *vals); +#include "core/effects/base.h" +#include "opthelpers.h" + +#define DECL_HANDLER(N, T) \ +struct N { \ + using prop_type = T; \ + \ + static void SetParami(ALCcontext *context, prop_type &props, ALenum param, int val); \ + static void SetParamiv(ALCcontext *context, prop_type &props, ALenum param, const int *vals); \ + static void SetParamf(ALCcontext *context, prop_type &props, ALenum param, float val); \ + static void SetParamfv(ALCcontext *context, prop_type &props, ALenum param, const float *vals);\ + static void GetParami(ALCcontext *context, const prop_type &props, ALenum param, int *val); \ + static void GetParamiv(ALCcontext *context, const prop_type &props, ALenum param, int *vals); \ + static void GetParamf(ALCcontext *context, const prop_type &props, ALenum param, float *val); \ + static void GetParamfv(ALCcontext *context, const prop_type &props, ALenum param, float *vals);\ }; - -#define DEFINE_ALEFFECT_VTABLE(T) \ -const EffectVtable T##EffectVtable = { \ - T##_setParami, T##_setParamiv, \ - T##_setParamf, T##_setParamfv, \ - T##_getParami, T##_getParamiv, \ - T##_getParamf, T##_getParamfv, \ -} +DECL_HANDLER(NullEffectHandler, std::monostate) +DECL_HANDLER(ReverbEffectHandler, ReverbProps) +DECL_HANDLER(StdReverbEffectHandler, ReverbProps) +DECL_HANDLER(AutowahEffectHandler, AutowahProps) +DECL_HANDLER(ChorusEffectHandler, ChorusProps) +DECL_HANDLER(CompressorEffectHandler, CompressorProps) +DECL_HANDLER(DistortionEffectHandler, DistortionProps) +DECL_HANDLER(EchoEffectHandler, EchoProps) +DECL_HANDLER(EqualizerEffectHandler, EqualizerProps) +DECL_HANDLER(FlangerEffectHandler, ChorusProps) +DECL_HANDLER(FshifterEffectHandler, FshifterProps) +DECL_HANDLER(ModulatorEffectHandler, ModulatorProps) +DECL_HANDLER(PshifterEffectHandler, PshifterProps) +DECL_HANDLER(VmorpherEffectHandler, VmorpherProps) +DECL_HANDLER(DedicatedDialogEffectHandler, DedicatedProps) +DECL_HANDLER(DedicatedLfeEffectHandler, DedicatedProps) +DECL_HANDLER(ConvolutionEffectHandler, ConvolutionProps) +#undef DECL_HANDLER /* Default properties for the given effect types. */ -extern const EffectProps NullEffectProps; -extern const EffectProps ReverbEffectProps; -extern const EffectProps StdReverbEffectProps; -extern const EffectProps AutowahEffectProps; -extern const EffectProps ChorusEffectProps; -extern const EffectProps CompressorEffectProps; -extern const EffectProps DistortionEffectProps; -extern const EffectProps EchoEffectProps; -extern const EffectProps EqualizerEffectProps; -extern const EffectProps FlangerEffectProps; -extern const EffectProps FshifterEffectProps; -extern const EffectProps ModulatorEffectProps; -extern const EffectProps PshifterEffectProps; -extern const EffectProps VmorpherEffectProps; -extern const EffectProps DedicatedEffectProps; -extern const EffectProps ConvolutionEffectProps; - -/* Vtables to get/set properties for the given effect types. */ -extern const EffectVtable NullEffectVtable; -extern const EffectVtable ReverbEffectVtable; -extern const EffectVtable StdReverbEffectVtable; -extern const EffectVtable AutowahEffectVtable; -extern const EffectVtable ChorusEffectVtable; -extern const EffectVtable CompressorEffectVtable; -extern const EffectVtable DistortionEffectVtable; -extern const EffectVtable EchoEffectVtable; -extern const EffectVtable EqualizerEffectVtable; -extern const EffectVtable FlangerEffectVtable; -extern const EffectVtable FshifterEffectVtable; -extern const EffectVtable ModulatorEffectVtable; -extern const EffectVtable PshifterEffectVtable; -extern const EffectVtable VmorpherEffectVtable; -extern const EffectVtable DedicatedEffectVtable; -extern const EffectVtable ConvolutionEffectVtable; +DECL_HIDDEN extern const EffectProps NullEffectProps; +DECL_HIDDEN extern const EffectProps ReverbEffectProps; +DECL_HIDDEN extern const EffectProps StdReverbEffectProps; +DECL_HIDDEN extern const EffectProps AutowahEffectProps; +DECL_HIDDEN extern const EffectProps ChorusEffectProps; +DECL_HIDDEN extern const EffectProps CompressorEffectProps; +DECL_HIDDEN extern const EffectProps DistortionEffectProps; +DECL_HIDDEN extern const EffectProps EchoEffectProps; +DECL_HIDDEN extern const EffectProps EqualizerEffectProps; +DECL_HIDDEN extern const EffectProps FlangerEffectProps; +DECL_HIDDEN extern const EffectProps FshifterEffectProps; +DECL_HIDDEN extern const EffectProps ModulatorEffectProps; +DECL_HIDDEN extern const EffectProps PshifterEffectProps; +DECL_HIDDEN extern const EffectProps VmorpherEffectProps; +DECL_HIDDEN extern const EffectProps DedicatedDialogEffectProps; +DECL_HIDDEN extern const EffectProps DedicatedLfeEffectProps; +DECL_HIDDEN extern const EffectProps ConvolutionEffectProps; #endif /* AL_EFFECTS_EFFECTS_H */ diff --git a/3rdparty/openal/al/effects/equalizer.cpp b/3rdparty/openal/al/effects/equalizer.cpp index 76d5bdef07cc..360fd5d8f3e3 100644 --- a/3rdparty/openal/al/effects/equalizer.cpp +++ b/3rdparty/openal/al/effects/equalizer.cpp @@ -4,11 +4,12 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -16,165 +17,129 @@ namespace { -void Equalizer_setParami(EffectProps*, ALenum param, int) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; } -void Equalizer_setParamiv(EffectProps*, ALenum param, const int*) +constexpr EffectProps genDefaultProps() noexcept { - throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x", - param}; + EqualizerProps props{}; + props.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF; + props.LowGain = AL_EQUALIZER_DEFAULT_LOW_GAIN; + props.Mid1Center = AL_EQUALIZER_DEFAULT_MID1_CENTER; + props.Mid1Gain = AL_EQUALIZER_DEFAULT_MID1_GAIN; + props.Mid1Width = AL_EQUALIZER_DEFAULT_MID1_WIDTH; + props.Mid2Center = AL_EQUALIZER_DEFAULT_MID2_CENTER; + props.Mid2Gain = AL_EQUALIZER_DEFAULT_MID2_GAIN; + props.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH; + props.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF; + props.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN; + return props; } -void Equalizer_setParamf(EffectProps *props, ALenum param, float val) + +} // namespace + +const EffectProps EqualizerEffectProps{genDefaultProps()}; + +void EqualizerEffectHandler::SetParami(ALCcontext *context, EqualizerProps&, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer property {:#04x}", as_unsigned(param)); } +void EqualizerEffectHandler::SetParamiv(ALCcontext *context, EqualizerProps&, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer-vector property {:#04x}", as_unsigned(param)); } +void EqualizerEffectHandler::SetParamf(ALCcontext *context, EqualizerProps &props, ALenum param, float val) { switch(param) { case AL_EQUALIZER_LOW_GAIN: if(!(val >= AL_EQUALIZER_MIN_LOW_GAIN && val <= AL_EQUALIZER_MAX_LOW_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band gain out of range"}; - props->Equalizer.LowGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer low-band gain out of range"); + props.LowGain = val; + return; case AL_EQUALIZER_LOW_CUTOFF: if(!(val >= AL_EQUALIZER_MIN_LOW_CUTOFF && val <= AL_EQUALIZER_MAX_LOW_CUTOFF)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer low-band cutoff out of range"}; - props->Equalizer.LowCutoff = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer low-band cutoff out of range"); + props.LowCutoff = val; + return; case AL_EQUALIZER_MID1_GAIN: if(!(val >= AL_EQUALIZER_MIN_MID1_GAIN && val <= AL_EQUALIZER_MAX_MID1_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band gain out of range"}; - props->Equalizer.Mid1Gain = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band gain out of range"); + props.Mid1Gain = val; + return; case AL_EQUALIZER_MID1_CENTER: if(!(val >= AL_EQUALIZER_MIN_MID1_CENTER && val <= AL_EQUALIZER_MAX_MID1_CENTER)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band center out of range"}; - props->Equalizer.Mid1Center = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band center out of range"); + props.Mid1Center = val; + return; case AL_EQUALIZER_MID1_WIDTH: if(!(val >= AL_EQUALIZER_MIN_MID1_WIDTH && val <= AL_EQUALIZER_MAX_MID1_WIDTH)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid1-band width out of range"}; - props->Equalizer.Mid1Width = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid1-band width out of range"); + props.Mid1Width = val; + return; case AL_EQUALIZER_MID2_GAIN: if(!(val >= AL_EQUALIZER_MIN_MID2_GAIN && val <= AL_EQUALIZER_MAX_MID2_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band gain out of range"}; - props->Equalizer.Mid2Gain = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band gain out of range"); + props.Mid2Gain = val; + return; case AL_EQUALIZER_MID2_CENTER: if(!(val >= AL_EQUALIZER_MIN_MID2_CENTER && val <= AL_EQUALIZER_MAX_MID2_CENTER)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band center out of range"}; - props->Equalizer.Mid2Center = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band center out of range"); + props.Mid2Center = val; + return; case AL_EQUALIZER_MID2_WIDTH: if(!(val >= AL_EQUALIZER_MIN_MID2_WIDTH && val <= AL_EQUALIZER_MAX_MID2_WIDTH)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer mid2-band width out of range"}; - props->Equalizer.Mid2Width = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer mid2-band width out of range"); + props.Mid2Width = val; + return; case AL_EQUALIZER_HIGH_GAIN: if(!(val >= AL_EQUALIZER_MIN_HIGH_GAIN && val <= AL_EQUALIZER_MAX_HIGH_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band gain out of range"}; - props->Equalizer.HighGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "Equalizer high-band gain out of range"); + props.HighGain = val; + return; case AL_EQUALIZER_HIGH_CUTOFF: if(!(val >= AL_EQUALIZER_MIN_HIGH_CUTOFF && val <= AL_EQUALIZER_MAX_HIGH_CUTOFF)) - throw effect_exception{AL_INVALID_VALUE, "Equalizer high-band cutoff out of range"}; - props->Equalizer.HighCutoff = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "Equalizer high-band cutoff out of range"); + props.HighCutoff = val; + return; } -} -void Equalizer_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Equalizer_setParamf(props, param, vals[0]); } -void Equalizer_getParami(const EffectProps*, ALenum param, int*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer property 0x%04x", param}; } -void Equalizer_getParamiv(const EffectProps*, ALenum param, int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer integer-vector property 0x%04x", - param}; + context->throw_error(AL_INVALID_ENUM, "Invalid equalizer float property {:#04x}", + as_unsigned(param)); } -void Equalizer_getParamf(const EffectProps *props, ALenum param, float *val) +void EqualizerEffectHandler::SetParamfv(ALCcontext *context, EqualizerProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void EqualizerEffectHandler::GetParami(ALCcontext *context, const EqualizerProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer property {:#04x}", as_unsigned(param)); } +void EqualizerEffectHandler::GetParamiv(ALCcontext *context, const EqualizerProps&, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid equalizer integer-vector property {:#04x}", as_unsigned(param)); } +void EqualizerEffectHandler::GetParamf(ALCcontext *context, const EqualizerProps &props, ALenum param, float *val) { switch(param) { - case AL_EQUALIZER_LOW_GAIN: - *val = props->Equalizer.LowGain; - break; - - case AL_EQUALIZER_LOW_CUTOFF: - *val = props->Equalizer.LowCutoff; - break; - - case AL_EQUALIZER_MID1_GAIN: - *val = props->Equalizer.Mid1Gain; - break; - - case AL_EQUALIZER_MID1_CENTER: - *val = props->Equalizer.Mid1Center; - break; - - case AL_EQUALIZER_MID1_WIDTH: - *val = props->Equalizer.Mid1Width; - break; - - case AL_EQUALIZER_MID2_GAIN: - *val = props->Equalizer.Mid2Gain; - break; - - case AL_EQUALIZER_MID2_CENTER: - *val = props->Equalizer.Mid2Center; - break; - - case AL_EQUALIZER_MID2_WIDTH: - *val = props->Equalizer.Mid2Width; - break; - - case AL_EQUALIZER_HIGH_GAIN: - *val = props->Equalizer.HighGain; - break; - - case AL_EQUALIZER_HIGH_CUTOFF: - *val = props->Equalizer.HighCutoff; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid equalizer float property 0x%04x", param}; + case AL_EQUALIZER_LOW_GAIN: *val = props.LowGain; return; + case AL_EQUALIZER_LOW_CUTOFF: *val = props.LowCutoff; return; + case AL_EQUALIZER_MID1_GAIN: *val = props.Mid1Gain; return; + case AL_EQUALIZER_MID1_CENTER: *val = props.Mid1Center; return; + case AL_EQUALIZER_MID1_WIDTH: *val = props.Mid1Width; return; + case AL_EQUALIZER_MID2_GAIN: *val = props.Mid2Gain; return; + case AL_EQUALIZER_MID2_CENTER: *val = props.Mid2Center; return; + case AL_EQUALIZER_MID2_WIDTH: *val = props.Mid2Width; return; + case AL_EQUALIZER_HIGH_GAIN: *val = props.HighGain; return; + case AL_EQUALIZER_HIGH_CUTOFF: *val = props.HighCutoff; return; } -} -void Equalizer_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Equalizer_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Equalizer.LowCutoff = AL_EQUALIZER_DEFAULT_LOW_CUTOFF; - props.Equalizer.LowGain = AL_EQUALIZER_DEFAULT_LOW_GAIN; - props.Equalizer.Mid1Center = AL_EQUALIZER_DEFAULT_MID1_CENTER; - props.Equalizer.Mid1Gain = AL_EQUALIZER_DEFAULT_MID1_GAIN; - props.Equalizer.Mid1Width = AL_EQUALIZER_DEFAULT_MID1_WIDTH; - props.Equalizer.Mid2Center = AL_EQUALIZER_DEFAULT_MID2_CENTER; - props.Equalizer.Mid2Gain = AL_EQUALIZER_DEFAULT_MID2_GAIN; - props.Equalizer.Mid2Width = AL_EQUALIZER_DEFAULT_MID2_WIDTH; - props.Equalizer.HighCutoff = AL_EQUALIZER_DEFAULT_HIGH_CUTOFF; - props.Equalizer.HighGain = AL_EQUALIZER_DEFAULT_HIGH_GAIN; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid equalizer float property {:#04x}", + as_unsigned(param)); } +void EqualizerEffectHandler::GetParamfv(ALCcontext *context, const EqualizerProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Equalizer); -const EffectProps EqualizerEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using EqualizerCommitter = EaxCommitter; @@ -319,31 +284,31 @@ template<> throw Exception{message}; } -template<> -bool EqualizerCommitter::commit(const EaxEffectProps &props) +bool EaxEqualizerCommitter::commit(const EAXEQUALIZERPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - - auto &eaxprops = std::get(props); - mAlProps.Equalizer.LowGain = level_mb_to_gain(static_cast(eaxprops.lLowGain)); - mAlProps.Equalizer.LowCutoff = eaxprops.flLowCutOff; - mAlProps.Equalizer.Mid1Gain = level_mb_to_gain(static_cast(eaxprops.lMid1Gain)); - mAlProps.Equalizer.Mid1Center = eaxprops.flMid1Center; - mAlProps.Equalizer.Mid1Width = eaxprops.flMid1Width; - mAlProps.Equalizer.Mid2Gain = level_mb_to_gain(static_cast(eaxprops.lMid2Gain)); - mAlProps.Equalizer.Mid2Center = eaxprops.flMid2Center; - mAlProps.Equalizer.Mid2Width = eaxprops.flMid2Width; - mAlProps.Equalizer.HighGain = level_mb_to_gain(static_cast(eaxprops.lHighGain)); - mAlProps.Equalizer.HighCutoff = eaxprops.flHighCutOff; + mAlProps = [&]{ + EqualizerProps ret{}; + ret.LowGain = level_mb_to_gain(static_cast(props.lLowGain)); + ret.LowCutoff = props.flLowCutOff; + ret.Mid1Gain = level_mb_to_gain(static_cast(props.lMid1Gain)); + ret.Mid1Center = props.flMid1Center; + ret.Mid1Width = props.flMid1Width; + ret.Mid2Gain = level_mb_to_gain(static_cast(props.lMid2Gain)); + ret.Mid2Center = props.flMid2Center; + ret.Mid2Width = props.flMid2Width; + ret.HighGain = level_mb_to_gain(static_cast(props.lHighGain)); + ret.HighCutoff = props.flHighCutOff; + return ret; + }(); return true; } -template<> -void EqualizerCommitter::SetDefaults(EaxEffectProps &props) +void EaxEqualizerCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXEQUALIZERPROPERTIES defprops{[] { @@ -363,10 +328,8 @@ void EqualizerCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxEqualizerCommitter::Get(const EaxCall &call, const EAXEQUALIZERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXEQUALIZER_NONE: break; @@ -385,10 +348,8 @@ void EqualizerCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void EqualizerCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxEqualizerCommitter::Set(const EaxCall &call, EAXEQUALIZERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXEQUALIZER_NONE: break; diff --git a/3rdparty/openal/al/effects/fshifter.cpp b/3rdparty/openal/al/effects/fshifter.cpp index 37c372c35f78..d1c93921ffec 100644 --- a/3rdparty/openal/al/effects/fshifter.cpp +++ b/3rdparty/openal/al/effects/fshifter.cpp @@ -7,12 +7,14 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include -#include "alnumeric.h" + +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -20,7 +22,7 @@ namespace { -std::optional DirectionFromEmum(ALenum value) +constexpr std::optional DirectionFromEmum(ALenum value) noexcept { switch(value) { @@ -30,7 +32,7 @@ std::optional DirectionFromEmum(ALenum value) } return std::nullopt; } -ALenum EnumFromDirection(FShifterDirection dir) +constexpr ALenum EnumFromDirection(FShifterDirection dir) { switch(dir) { @@ -38,105 +40,99 @@ ALenum EnumFromDirection(FShifterDirection dir) case FShifterDirection::Up: return AL_FREQUENCY_SHIFTER_DIRECTION_UP; case FShifterDirection::Off: return AL_FREQUENCY_SHIFTER_DIRECTION_OFF; } - throw std::runtime_error{"Invalid direction: "+std::to_string(static_cast(dir))}; + throw std::runtime_error{fmt::format("Invalid direction: {}", int{al::to_underlying(dir)})}; } -void Fshifter_setParamf(EffectProps *props, ALenum param, float val) +constexpr EffectProps genDefaultProps() noexcept { - switch(param) - { - case AL_FREQUENCY_SHIFTER_FREQUENCY: - if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY)) - throw effect_exception{AL_INVALID_VALUE, "Frequency shifter frequency out of range"}; - props->Fshifter.Frequency = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x", - param}; - } + FshifterProps props{}; + props.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY; + props.LeftDirection = DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION).value(); + props.RightDirection = DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION).value(); + return props; } -void Fshifter_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Fshifter_setParamf(props, param, vals[0]); } -void Fshifter_setParami(EffectProps *props, ALenum param, int val) +} // namespace + +const EffectProps FshifterEffectProps{genDefaultProps()}; + +void FshifterEffectHandler::SetParami(ALCcontext *context, FshifterProps &props, ALenum param, int val) { switch(param) { case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION: if(auto diropt = DirectionFromEmum(val)) - props->Fshifter.LeftDirection = *diropt; + props.LeftDirection = *diropt; else - throw effect_exception{AL_INVALID_VALUE, - "Unsupported frequency shifter left direction: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, + "Unsupported frequency shifter left direction: {:#04x}", as_unsigned(val)); + return; case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION: if(auto diropt = DirectionFromEmum(val)) - props->Fshifter.RightDirection = *diropt; + props.RightDirection = *diropt; else - throw effect_exception{AL_INVALID_VALUE, - "Unsupported frequency shifter right direction: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, + "Unsupported frequency shifter right direction: {:#04x}", as_unsigned(val)); + return; + } - default: - throw effect_exception{AL_INVALID_ENUM, - "Invalid frequency shifter integer property 0x%04x", param}; + context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter integer property {:#04x}", + as_unsigned(param)); +} +void FshifterEffectHandler::SetParamiv(ALCcontext *context, FshifterProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } + +void FshifterEffectHandler::SetParamf(ALCcontext *context, FshifterProps &props, ALenum param, float val) +{ + switch(param) + { + case AL_FREQUENCY_SHIFTER_FREQUENCY: + if(!(val >= AL_FREQUENCY_SHIFTER_MIN_FREQUENCY && val <= AL_FREQUENCY_SHIFTER_MAX_FREQUENCY)) + context->throw_error(AL_INVALID_VALUE, "Frequency shifter frequency out of range"); + props.Frequency = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter float property {:#04x}", + as_unsigned(param)); } -void Fshifter_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Fshifter_setParami(props, param, vals[0]); } +void FshifterEffectHandler::SetParamfv(ALCcontext *context, FshifterProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void Fshifter_getParami(const EffectProps *props, ALenum param, int *val) +void FshifterEffectHandler::GetParami(ALCcontext *context, const FshifterProps &props, ALenum param, int *val) { switch(param) { case AL_FREQUENCY_SHIFTER_LEFT_DIRECTION: - *val = EnumFromDirection(props->Fshifter.LeftDirection); - break; + *val = EnumFromDirection(props.LeftDirection); + return; case AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION: - *val = EnumFromDirection(props->Fshifter.RightDirection); - break; - default: - throw effect_exception{AL_INVALID_ENUM, - "Invalid frequency shifter integer property 0x%04x", param}; + *val = EnumFromDirection(props.RightDirection); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter integer property {:#04x}", + as_unsigned(param)); } -void Fshifter_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Fshifter_getParami(props, param, vals); } +void FshifterEffectHandler::GetParamiv(ALCcontext *context, const FshifterProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } -void Fshifter_getParamf(const EffectProps *props, ALenum param, float *val) +void FshifterEffectHandler::GetParamf(ALCcontext *context, const FshifterProps &props, ALenum param, float *val) { switch(param) { - case AL_FREQUENCY_SHIFTER_FREQUENCY: - *val = props->Fshifter.Frequency; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid frequency shifter float property 0x%04x", - param}; + case AL_FREQUENCY_SHIFTER_FREQUENCY: *val = props.Frequency; return; } -} -void Fshifter_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Fshifter_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Fshifter.Frequency = AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY; - props.Fshifter.LeftDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION); - props.Fshifter.RightDirection = *DirectionFromEmum(AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION); - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid frequency shifter float property {:#04x}", + as_unsigned(param)); } +void FshifterEffectHandler::GetParamfv(ALCcontext *context, const FshifterProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Fshifter); -const EffectProps FshifterEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using FrequencyShifterCommitter = EaxCommitter; @@ -197,10 +193,9 @@ template<> throw Exception{message}; } -template<> -bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) +bool EaxFrequencyShifterCommitter::commit(const EAXFREQUENCYSHIFTERPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; @@ -214,16 +209,18 @@ bool FrequencyShifterCommitter::commit(const EaxEffectProps &props) return FShifterDirection::Off; }; - auto &eaxprops = std::get(props); - mAlProps.Fshifter.Frequency = eaxprops.flFrequency; - mAlProps.Fshifter.LeftDirection = get_direction(eaxprops.ulLeftDirection); - mAlProps.Fshifter.RightDirection = get_direction(eaxprops.ulRightDirection); + mAlProps = [&]{ + FshifterProps ret{}; + ret.Frequency = props.flFrequency; + ret.LeftDirection = get_direction(props.ulLeftDirection); + ret.RightDirection = get_direction(props.ulRightDirection); + return ret; + }(); return true; } -template<> -void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props) +void EaxFrequencyShifterCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXFREQUENCYSHIFTERPROPERTIES defprops{[] { @@ -236,10 +233,8 @@ void FrequencyShifterCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxFrequencyShifterCommitter::Get(const EaxCall &call, const EAXFREQUENCYSHIFTERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; @@ -251,10 +246,8 @@ void FrequencyShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &p } } -template<> -void FrequencyShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxFrequencyShifterCommitter::Set(const EaxCall &call, EAXFREQUENCYSHIFTERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXFREQUENCYSHIFTER_NONE: break; diff --git a/3rdparty/openal/al/effects/modulator.cpp b/3rdparty/openal/al/effects/modulator.cpp index 366e7ef71154..b3ca22138f9a 100644 --- a/3rdparty/openal/al/effects/modulator.cpp +++ b/3rdparty/openal/al/effects/modulator.cpp @@ -7,12 +7,14 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include -#include "alnumeric.h" + +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -20,7 +22,7 @@ namespace { -std::optional WaveformFromEmum(ALenum value) +constexpr std::optional WaveformFromEmum(ALenum value) noexcept { switch(value) { @@ -30,7 +32,7 @@ std::optional WaveformFromEmum(ALenum value) } return std::nullopt; } -ALenum EnumFromWaveform(ModulatorWaveform type) +constexpr ALenum EnumFromWaveform(ModulatorWaveform type) { switch(type) { @@ -38,111 +40,101 @@ ALenum EnumFromWaveform(ModulatorWaveform type) case ModulatorWaveform::Sawtooth: return AL_RING_MODULATOR_SAWTOOTH; case ModulatorWaveform::Square: return AL_RING_MODULATOR_SQUARE; } - throw std::runtime_error{"Invalid modulator waveform: " + - std::to_string(static_cast(type))}; + throw std::runtime_error{fmt::format("Invalid modulator waveform: {}", + int{al::to_underlying(type)})}; } -void Modulator_setParamf(EffectProps *props, ALenum param, float val) +constexpr EffectProps genDefaultProps() noexcept { - switch(param) - { - case AL_RING_MODULATOR_FREQUENCY: - if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY)) - throw effect_exception{AL_INVALID_VALUE, "Modulator frequency out of range: %f", val}; - props->Modulator.Frequency = val; - break; + ModulatorProps props{}; + props.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY; + props.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF; + props.Waveform = WaveformFromEmum(AL_RING_MODULATOR_DEFAULT_WAVEFORM).value(); + return props; +} - case AL_RING_MODULATOR_HIGHPASS_CUTOFF: - if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF)) - throw effect_exception{AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: %f", val}; - props->Modulator.HighPassCutoff = val; - break; +} // namespace - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param}; - } -} -void Modulator_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Modulator_setParamf(props, param, vals[0]); } -void Modulator_setParami(EffectProps *props, ALenum param, int val) +const EffectProps ModulatorEffectProps{genDefaultProps()}; + +void ModulatorEffectHandler::SetParami(ALCcontext *context, ModulatorProps &props, ALenum param, int val) { switch(param) { case AL_RING_MODULATOR_FREQUENCY: case AL_RING_MODULATOR_HIGHPASS_CUTOFF: - Modulator_setParamf(props, param, static_cast(val)); - break; + SetParamf(context, props, param, static_cast(val)); + return; case AL_RING_MODULATOR_WAVEFORM: if(auto formopt = WaveformFromEmum(val)) - props->Modulator.Waveform = *formopt; + props.Waveform = *formopt; else - throw effect_exception{AL_INVALID_VALUE, "Invalid modulator waveform: 0x%04x", val}; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "Invalid modulator waveform: {:#04x}", + as_unsigned(val)); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid modulator integer property {:#04x}", + as_unsigned(param)); } -void Modulator_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Modulator_setParami(props, param, vals[0]); } +void ModulatorEffectHandler::SetParamiv(ALCcontext *context, ModulatorProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } -void Modulator_getParami(const EffectProps *props, ALenum param, int *val) +void ModulatorEffectHandler::SetParamf(ALCcontext *context, ModulatorProps &props, ALenum param, float val) { switch(param) { case AL_RING_MODULATOR_FREQUENCY: - *val = static_cast(props->Modulator.Frequency); - break; - case AL_RING_MODULATOR_HIGHPASS_CUTOFF: - *val = static_cast(props->Modulator.HighPassCutoff); - break; - case AL_RING_MODULATOR_WAVEFORM: - *val = EnumFromWaveform(props->Modulator.Waveform); - break; + if(!(val >= AL_RING_MODULATOR_MIN_FREQUENCY && val <= AL_RING_MODULATOR_MAX_FREQUENCY)) + context->throw_error(AL_INVALID_VALUE, "Modulator frequency out of range: {:f}", val); + props.Frequency = val; + return; - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid modulator integer property 0x%04x", - param}; + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: + if(!(val >= AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF && val <= AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF)) + context->throw_error(AL_INVALID_VALUE, "Modulator high-pass cutoff out of range: {:f}", + val); + props.HighPassCutoff = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid modulator float property {:#04x}", + as_unsigned(param)); } -void Modulator_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Modulator_getParami(props, param, vals); } -void Modulator_getParamf(const EffectProps *props, ALenum param, float *val) +void ModulatorEffectHandler::SetParamfv(ALCcontext *context, ModulatorProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void ModulatorEffectHandler::GetParami(ALCcontext *context, const ModulatorProps &props, ALenum param, int *val) { switch(param) { - case AL_RING_MODULATOR_FREQUENCY: - *val = props->Modulator.Frequency; - break; - case AL_RING_MODULATOR_HIGHPASS_CUTOFF: - *val = props->Modulator.HighPassCutoff; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid modulator float property 0x%04x", param}; + case AL_RING_MODULATOR_FREQUENCY: *val = static_cast(props.Frequency); return; + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = static_cast(props.HighPassCutoff); return; + case AL_RING_MODULATOR_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return; } -} -void Modulator_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Modulator_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Modulator.Frequency = AL_RING_MODULATOR_DEFAULT_FREQUENCY; - props.Modulator.HighPassCutoff = AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF; - props.Modulator.Waveform = *WaveformFromEmum(AL_RING_MODULATOR_DEFAULT_WAVEFORM); - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid modulator integer property {:#04x}", + as_unsigned(param)); } +void ModulatorEffectHandler::GetParamiv(ALCcontext *context, const ModulatorProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void ModulatorEffectHandler::GetParamf(ALCcontext *context, const ModulatorProps &props, ALenum param, float *val) +{ + switch(param) + { + case AL_RING_MODULATOR_FREQUENCY: *val = props.Frequency; return; + case AL_RING_MODULATOR_HIGHPASS_CUTOFF: *val = props.HighPassCutoff; return; + } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Modulator); + context->throw_error(AL_INVALID_ENUM, "Invalid modulator float property {:#04x}", + as_unsigned(param)); +} +void ModulatorEffectHandler::GetParamfv(ALCcontext *context, const ModulatorProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -const EffectProps ModulatorEffectProps{genDefaultProps()}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using ModulatorCommitter = EaxCommitter; @@ -203,10 +195,9 @@ template<> throw Exception{message}; } -template<> -bool ModulatorCommitter::commit(const EaxEffectProps &props) +bool EaxModulatorCommitter::commit(const EAXRINGMODULATORPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; @@ -222,16 +213,18 @@ bool ModulatorCommitter::commit(const EaxEffectProps &props) return ModulatorWaveform::Sinusoid; }; - auto &eaxprops = std::get(props); - mAlProps.Modulator.Frequency = eaxprops.flFrequency; - mAlProps.Modulator.HighPassCutoff = eaxprops.flHighPassCutOff; - mAlProps.Modulator.Waveform = get_waveform(eaxprops.ulWaveform); + mAlProps = [&]{ + ModulatorProps ret{}; + ret.Frequency = props.flFrequency; + ret.HighPassCutoff = props.flHighPassCutOff; + ret.Waveform = get_waveform(props.ulWaveform); + return ret; + }(); return true; } -template<> -void ModulatorCommitter::SetDefaults(EaxEffectProps &props) +void EaxModulatorCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXRINGMODULATORPROPERTIES defprops{[] { @@ -244,10 +237,8 @@ void ModulatorCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void ModulatorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxModulatorCommitter::Get(const EaxCall &call, const EAXRINGMODULATORPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXRINGMODULATOR_NONE: break; @@ -259,11 +250,9 @@ void ModulatorCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) } } -template<> -void ModulatorCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxModulatorCommitter::Set(const EaxCall &call, EAXRINGMODULATORPROPERTIES &props) { - auto &props = std::get(props_); - switch (call.get_property_id()) + switch(call.get_property_id()) { case EAXRINGMODULATOR_NONE: break; case EAXRINGMODULATOR_ALLPARAMETERS: defer(call, props); break; diff --git a/3rdparty/openal/al/effects/null.cpp b/3rdparty/openal/al/effects/null.cpp index 1e8787e79381..ac522313f1c2 100644 --- a/3rdparty/openal/al/effects/null.cpp +++ b/3rdparty/openal/al/effects/null.cpp @@ -4,100 +4,67 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #endif // ALSOFT_EAX namespace { -void Null_setParami(EffectProps* /*props*/, ALenum param, int /*val*/) +constexpr EffectProps genDefaultProps() noexcept { - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", - param}; - } + return std::monostate{}; } -void Null_setParamiv(EffectProps *props, ALenum param, const int *vals) + +} // namespace + +const EffectProps NullEffectProps{genDefaultProps()}; + +void NullEffectHandler::SetParami(ALCcontext *context, std::monostate& /*props*/, ALenum param, int /*val*/) { - switch(param) - { - default: - Null_setParami(props, param, vals[0]); - } + context->throw_error(AL_INVALID_ENUM, "Invalid null effect integer property {:#04x}", + as_unsigned(param)); } -void Null_setParamf(EffectProps* /*props*/, ALenum param, float /*val*/) +void NullEffectHandler::SetParamiv(ALCcontext *context, std::monostate &props, ALenum param, const int *vals) { - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", - param}; - } + SetParami(context, props, param, *vals); } -void Null_setParamfv(EffectProps *props, ALenum param, const float *vals) +void NullEffectHandler::SetParamf(ALCcontext *context, std::monostate& /*props*/, ALenum param, float /*val*/) { - switch(param) - { - default: - Null_setParamf(props, param, vals[0]); - } + context->throw_error(AL_INVALID_ENUM, "Invalid null effect float property {:#04x}", + as_unsigned(param)); } - -void Null_getParami(const EffectProps* /*props*/, ALenum param, int* /*val*/) +void NullEffectHandler::SetParamfv(ALCcontext *context, std::monostate &props, ALenum param, const float *vals) { - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect integer property 0x%04x", - param}; - } + SetParamf(context, props, param, *vals); } -void Null_getParamiv(const EffectProps *props, ALenum param, int *vals) + +void NullEffectHandler::GetParami(ALCcontext *context, const std::monostate& /*props*/, ALenum param, int* /*val*/) { - switch(param) - { - default: - Null_getParami(props, param, vals); - } + context->throw_error(AL_INVALID_ENUM, "Invalid null effect integer property {:#04x}", + as_unsigned(param)); } -void Null_getParamf(const EffectProps* /*props*/, ALenum param, float* /*val*/) +void NullEffectHandler::GetParamiv(ALCcontext *context, const std::monostate &props, ALenum param, int *vals) { - switch(param) - { - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid null effect float property 0x%04x", - param}; - } + GetParami(context, props, param, vals); } -void Null_getParamfv(const EffectProps *props, ALenum param, float *vals) +void NullEffectHandler::GetParamf(ALCcontext *context, const std::monostate& /*props*/, ALenum param, float* /*val*/) { - switch(param) - { - default: - Null_getParamf(props, param, vals); - } + context->throw_error(AL_INVALID_ENUM, "Invalid null effect float property {:#04x}", + as_unsigned(param)); } - -EffectProps genDefaultProps() noexcept +void NullEffectHandler::GetParamfv(ALCcontext *context, const std::monostate &props, ALenum param, float *vals) { - EffectProps props{}; - return props; + GetParamf(context, props, param, vals); } -} // namespace -DEFINE_ALEFFECT_VTABLE(Null); - -const EffectProps NullEffectProps{genDefaultProps()}; - - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using NullCommitter = EaxCommitter; @@ -117,29 +84,26 @@ template<> throw Exception{message}; } -template<> -bool NullCommitter::commit(const EaxEffectProps &props) +bool EaxNullCommitter::commit(const std::monostate &props) { - const bool ret{props != mEaxProps}; + const bool ret{std::holds_alternative(mEaxProps)}; mEaxProps = props; + mAlProps = std::monostate{}; return ret; } -template<> -void NullCommitter::SetDefaults(EaxEffectProps &props) +void EaxNullCommitter::SetDefaults(EaxEffectProps &props) { - props.emplace(); + props = std::monostate{}; } -template<> -void NullCommitter::Get(const EaxCall &call, const EaxEffectProps&) +void EaxNullCommitter::Get(const EaxCall &call, const std::monostate&) { if(call.get_property_id() != 0) fail_unknown_property_id(); } -template<> -void NullCommitter::Set(const EaxCall &call, EaxEffectProps&) +void EaxNullCommitter::Set(const EaxCall &call, std::monostate&) { if(call.get_property_id() != 0) fail_unknown_property_id(); diff --git a/3rdparty/openal/al/effects/pshifter.cpp b/3rdparty/openal/al/effects/pshifter.cpp index 10824016b7d3..c07ef27532ff 100644 --- a/3rdparty/openal/al/effects/pshifter.cpp +++ b/3rdparty/openal/al/effects/pshifter.cpp @@ -4,11 +4,12 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX -#include "alnumeric.h" +#if ALSOFT_EAX +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -16,80 +17,67 @@ namespace { -void Pshifter_setParamf(EffectProps*, ALenum param, float) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; } -void Pshifter_setParamfv(EffectProps*, ALenum param, const float*) +constexpr EffectProps genDefaultProps() noexcept { - throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float-vector property 0x%04x", - param}; + PshifterProps props{}; + props.CoarseTune = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE; + props.FineTune = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE; + return props; } -void Pshifter_setParami(EffectProps *props, ALenum param, int val) +} // namespace + +const EffectProps PshifterEffectProps{genDefaultProps()}; + +void PshifterEffectHandler::SetParami(ALCcontext *context, PshifterProps &props, ALenum param, int val) { switch(param) { case AL_PITCH_SHIFTER_COARSE_TUNE: if(!(val >= AL_PITCH_SHIFTER_MIN_COARSE_TUNE && val <= AL_PITCH_SHIFTER_MAX_COARSE_TUNE)) - throw effect_exception{AL_INVALID_VALUE, "Pitch shifter coarse tune out of range"}; - props->Pshifter.CoarseTune = val; - break; + context->throw_error(AL_INVALID_VALUE, "Pitch shifter coarse tune out of range"); + props.CoarseTune = val; + return; case AL_PITCH_SHIFTER_FINE_TUNE: if(!(val >= AL_PITCH_SHIFTER_MIN_FINE_TUNE && val <= AL_PITCH_SHIFTER_MAX_FINE_TUNE)) - throw effect_exception{AL_INVALID_VALUE, "Pitch shifter fine tune out of range"}; - props->Pshifter.FineTune = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "Pitch shifter fine tune out of range"); + props.FineTune = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter integer property {:#04x}", + as_unsigned(param)); } -void Pshifter_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Pshifter_setParami(props, param, vals[0]); } +void PshifterEffectHandler::SetParamiv(ALCcontext *context, PshifterProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } -void Pshifter_getParami(const EffectProps *props, ALenum param, int *val) +void PshifterEffectHandler::SetParamf(ALCcontext *context, PshifterProps&, ALenum param, float) +{ context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter float property {:#04x}", as_unsigned(param)); } +void PshifterEffectHandler::SetParamfv(ALCcontext *context, PshifterProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } + +void PshifterEffectHandler::GetParami(ALCcontext *context, const PshifterProps &props, ALenum param, int *val) { switch(param) { - case AL_PITCH_SHIFTER_COARSE_TUNE: - *val = props->Pshifter.CoarseTune; - break; - case AL_PITCH_SHIFTER_FINE_TUNE: - *val = props->Pshifter.FineTune; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter integer property 0x%04x", - param}; + case AL_PITCH_SHIFTER_COARSE_TUNE: *val = props.CoarseTune; return; + case AL_PITCH_SHIFTER_FINE_TUNE: *val = props.FineTune; return; } -} -void Pshifter_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Pshifter_getParami(props, param, vals); } -void Pshifter_getParamf(const EffectProps*, ALenum param, float*) -{ throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float property 0x%04x", param}; } -void Pshifter_getParamfv(const EffectProps*, ALenum param, float*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid pitch shifter float vector-property 0x%04x", - param}; + context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter integer property {:#04x}", + as_unsigned(param)); } +void PshifterEffectHandler::GetParamiv(ALCcontext *context, const PshifterProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Pshifter.CoarseTune = AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE; - props.Pshifter.FineTune = AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE; - return props; -} +void PshifterEffectHandler::GetParamf(ALCcontext *context, const PshifterProps&, ALenum param, float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid pitch shifter float property {:#04x}", as_unsigned(param)); } +void PshifterEffectHandler::GetParamfv(ALCcontext *context, const PshifterProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Pshifter); -const EffectProps PshifterEffectProps{genDefaultProps()}; - -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using PitchShifterCommitter = EaxCommitter; @@ -138,32 +126,30 @@ template<> throw Exception{message}; } -template<> -bool PitchShifterCommitter::commit(const EaxEffectProps &props) +bool EaxPitchShifterCommitter::commit(const EAXPITCHSHIFTERPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - - auto &eaxprops = std::get(props); - mAlProps.Pshifter.CoarseTune = static_cast(eaxprops.lCoarseTune); - mAlProps.Pshifter.FineTune = static_cast(eaxprops.lFineTune); + mAlProps = [&]{ + PshifterProps ret{}; + ret.CoarseTune = static_cast(props.lCoarseTune); + ret.FineTune = static_cast(props.lFineTune); + return ret; + }(); return true; } -template<> -void PitchShifterCommitter::SetDefaults(EaxEffectProps &props) +void EaxPitchShifterCommitter::SetDefaults(EaxEffectProps &props) { props = EAXPITCHSHIFTERPROPERTIES{EAXPITCHSHIFTER_DEFAULTCOARSETUNE, EAXPITCHSHIFTER_DEFAULTFINETUNE}; } -template<> -void PitchShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxPitchShifterCommitter::Get(const EaxCall &call, const EAXPITCHSHIFTERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; @@ -174,10 +160,8 @@ void PitchShifterCommitter::Get(const EaxCall &call, const EaxEffectProps &props } } -template<> -void PitchShifterCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxPitchShifterCommitter::Set(const EaxCall &call, EAXPITCHSHIFTERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { case EAXPITCHSHIFTER_NONE: break; diff --git a/3rdparty/openal/al/effects/reverb.cpp b/3rdparty/openal/al/effects/reverb.cpp index b037443fafdf..d3b83a089e62 100644 --- a/3rdparty/openal/al/effects/reverb.cpp +++ b/3rdparty/openal/al/effects/reverb.cpp @@ -1,18 +1,28 @@ #include "config.h" +#include +#include #include +#include #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" +#include "alspan.h" +#include "core/logging.h" #include "effects.h" +#include "fmt/ranges.h" +#include "opthelpers.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include -#include "alnumeric.h" -#include "AL/efx-presets.h" + +#include "al/eax/api.h" +#include "al/eax/call.h" +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -20,550 +30,433 @@ namespace { -void Reverb_setParami(EffectProps *props, ALenum param, int val) +constexpr EffectProps genDefaultProps() noexcept +{ + ReverbProps props{}; + props.Density = AL_EAXREVERB_DEFAULT_DENSITY; + props.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION; + props.Gain = AL_EAXREVERB_DEFAULT_GAIN; + props.GainHF = AL_EAXREVERB_DEFAULT_GAINHF; + props.GainLF = AL_EAXREVERB_DEFAULT_GAINLF; + props.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME; + props.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO; + props.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO; + props.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN; + props.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY; + props.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + props.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + props.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; + props.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN; + props.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY; + props.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + props.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + props.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; + props.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME; + props.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH; + props.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME; + props.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH; + props.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF; + props.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE; + props.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE; + props.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; + props.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT; + return props; +} + +constexpr EffectProps genDefaultStdProps() noexcept +{ + ReverbProps props{}; + props.Density = AL_REVERB_DEFAULT_DENSITY; + props.Diffusion = AL_REVERB_DEFAULT_DIFFUSION; + props.Gain = AL_REVERB_DEFAULT_GAIN; + props.GainHF = AL_REVERB_DEFAULT_GAINHF; + props.GainLF = 1.0f; + props.DecayTime = AL_REVERB_DEFAULT_DECAY_TIME; + props.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO; + props.DecayLFRatio = 1.0f; + props.ReflectionsGain = AL_REVERB_DEFAULT_REFLECTIONS_GAIN; + props.ReflectionsDelay = AL_REVERB_DEFAULT_REFLECTIONS_DELAY; + props.ReflectionsPan = {0.0f, 0.0f, 0.0f}; + props.LateReverbGain = AL_REVERB_DEFAULT_LATE_REVERB_GAIN; + props.LateReverbDelay = AL_REVERB_DEFAULT_LATE_REVERB_DELAY; + props.LateReverbPan = {0.0f, 0.0f, 0.0f}; + props.EchoTime = 0.25f; + props.EchoDepth = 0.0f; + props.ModulationTime = 0.25f; + props.ModulationDepth = 0.0f; + props.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF; + props.HFReference = 5000.0f; + props.LFReference = 250.0f; + props.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; + props.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT; + return props; +} + +} // namespace + +const EffectProps ReverbEffectProps{genDefaultProps()}; + +void ReverbEffectHandler::SetParami(ALCcontext *context, ReverbProps &props, ALenum param, int val) { switch(param) { case AL_EAXREVERB_DECAY_HFLIMIT: if(!(val >= AL_EAXREVERB_MIN_DECAY_HFLIMIT && val <= AL_EAXREVERB_MAX_DECAY_HFLIMIT)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"}; - props->Reverb.DecayHFLimit = val != AL_FALSE; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"); + props.DecayHFLimit = val != AL_FALSE; + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}", + as_unsigned(param)); } -void Reverb_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ Reverb_setParami(props, param, vals[0]); } -void Reverb_setParamf(EffectProps *props, ALenum param, float val) +void ReverbEffectHandler::SetParamiv(ALCcontext *context, ReverbProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void ReverbEffectHandler::SetParamf(ALCcontext *context, ReverbProps &props, ALenum param, float val) { switch(param) { case AL_EAXREVERB_DENSITY: if(!(val >= AL_EAXREVERB_MIN_DENSITY && val <= AL_EAXREVERB_MAX_DENSITY)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb density out of range"}; - props->Reverb.Density = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb density out of range"); + props.Density = val; + return; case AL_EAXREVERB_DIFFUSION: if(!(val >= AL_EAXREVERB_MIN_DIFFUSION && val <= AL_EAXREVERB_MAX_DIFFUSION)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb diffusion out of range"}; - props->Reverb.Diffusion = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb diffusion out of range"); + props.Diffusion = val; + return; case AL_EAXREVERB_GAIN: if(!(val >= AL_EAXREVERB_MIN_GAIN && val <= AL_EAXREVERB_MAX_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gain out of range"}; - props->Reverb.Gain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb gain out of range"); + props.Gain = val; + return; case AL_EAXREVERB_GAINHF: if(!(val >= AL_EAXREVERB_MIN_GAINHF && val <= AL_EAXREVERB_MAX_GAINHF)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainhf out of range"}; - props->Reverb.GainHF = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainhf out of range"); + props.GainHF = val; + return; case AL_EAXREVERB_GAINLF: if(!(val >= AL_EAXREVERB_MIN_GAINLF && val <= AL_EAXREVERB_MAX_GAINLF)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb gainlf out of range"}; - props->Reverb.GainLF = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainlf out of range"); + props.GainLF = val; + return; case AL_EAXREVERB_DECAY_TIME: if(!(val >= AL_EAXREVERB_MIN_DECAY_TIME && val <= AL_EAXREVERB_MAX_DECAY_TIME)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay time out of range"}; - props->Reverb.DecayTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay time out of range"); + props.DecayTime = val; + return; case AL_EAXREVERB_DECAY_HFRATIO: if(!(val >= AL_EAXREVERB_MIN_DECAY_HFRATIO && val <= AL_EAXREVERB_MAX_DECAY_HFRATIO)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"}; - props->Reverb.DecayHFRatio = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"); + props.DecayHFRatio = val; + return; case AL_EAXREVERB_DECAY_LFRATIO: if(!(val >= AL_EAXREVERB_MIN_DECAY_LFRATIO && val <= AL_EAXREVERB_MAX_DECAY_LFRATIO)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb decay lfratio out of range"}; - props->Reverb.DecayLFRatio = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay lfratio out of range"); + props.DecayLFRatio = val; + return; case AL_EAXREVERB_REFLECTIONS_GAIN: if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_GAIN && val <= AL_EAXREVERB_MAX_REFLECTIONS_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"}; - props->Reverb.ReflectionsGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"); + props.ReflectionsGain = val; + return; case AL_EAXREVERB_REFLECTIONS_DELAY: if(!(val >= AL_EAXREVERB_MIN_REFLECTIONS_DELAY && val <= AL_EAXREVERB_MAX_REFLECTIONS_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"}; - props->Reverb.ReflectionsDelay = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"); + props.ReflectionsDelay = val; + return; case AL_EAXREVERB_LATE_REVERB_GAIN: if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_GAIN && val <= AL_EAXREVERB_MAX_LATE_REVERB_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"}; - props->Reverb.LateReverbGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"); + props.LateReverbGain = val; + return; case AL_EAXREVERB_LATE_REVERB_DELAY: if(!(val >= AL_EAXREVERB_MIN_LATE_REVERB_DELAY && val <= AL_EAXREVERB_MAX_LATE_REVERB_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"}; - props->Reverb.LateReverbDelay = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"); + props.LateReverbDelay = val; + return; case AL_EAXREVERB_ECHO_TIME: if(!(val >= AL_EAXREVERB_MIN_ECHO_TIME && val <= AL_EAXREVERB_MAX_ECHO_TIME)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo time out of range"}; - props->Reverb.EchoTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb echo time out of range"); + props.EchoTime = val; + return; case AL_EAXREVERB_ECHO_DEPTH: if(!(val >= AL_EAXREVERB_MIN_ECHO_DEPTH && val <= AL_EAXREVERB_MAX_ECHO_DEPTH)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb echo depth out of range"}; - props->Reverb.EchoDepth = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb echo depth out of range"); + props.EchoDepth = val; + return; case AL_EAXREVERB_MODULATION_TIME: if(!(val >= AL_EAXREVERB_MIN_MODULATION_TIME && val <= AL_EAXREVERB_MAX_MODULATION_TIME)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation time out of range"}; - props->Reverb.ModulationTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb modulation time out of range"); + props.ModulationTime = val; + return; case AL_EAXREVERB_MODULATION_DEPTH: if(!(val >= AL_EAXREVERB_MIN_MODULATION_DEPTH && val <= AL_EAXREVERB_MAX_MODULATION_DEPTH)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb modulation depth out of range"}; - props->Reverb.ModulationDepth = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb modulation depth out of range"); + props.ModulationDepth = val; + return; case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: if(!(val >= AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"}; - props->Reverb.AirAbsorptionGainHF = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"); + props.AirAbsorptionGainHF = val; + return; case AL_EAXREVERB_HFREFERENCE: if(!(val >= AL_EAXREVERB_MIN_HFREFERENCE && val <= AL_EAXREVERB_MAX_HFREFERENCE)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb hfreference out of range"}; - props->Reverb.HFReference = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb hfreference out of range"); + props.HFReference = val; + return; case AL_EAXREVERB_LFREFERENCE: if(!(val >= AL_EAXREVERB_MIN_LFREFERENCE && val <= AL_EAXREVERB_MAX_LFREFERENCE)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb lfreference out of range"}; - props->Reverb.LFReference = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb lfreference out of range"); + props.LFReference = val; + return; case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: if(!(val >= AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR)) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"}; - props->Reverb.RoomRolloffFactor = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"); + props.RoomRolloffFactor = val; + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}", + as_unsigned(param)); } -void Reverb_setParamfv(EffectProps *props, ALenum param, const float *vals) +void ReverbEffectHandler::SetParamfv(ALCcontext *context, ReverbProps &props, ALenum param, const float *vals) { + static constexpr auto finite_checker = [](float f) -> bool { return std::isfinite(f); }; + al::span values; switch(param) { case AL_EAXREVERB_REFLECTIONS_PAN: - if(!(std::isfinite(vals[0]) && std::isfinite(vals[1]) && std::isfinite(vals[2]))) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb reflections pan out of range"}; - props->Reverb.ReflectionsPan[0] = vals[0]; - props->Reverb.ReflectionsPan[1] = vals[1]; - props->Reverb.ReflectionsPan[2] = vals[2]; - break; + values = {vals, 3_uz}; + if(!std::all_of(values.cbegin(), values.cend(), finite_checker)) + context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections pan out of range"); + std::copy(values.cbegin(), values.cend(), props.ReflectionsPan.begin()); + return; case AL_EAXREVERB_LATE_REVERB_PAN: - if(!(std::isfinite(vals[0]) && std::isfinite(vals[1]) && std::isfinite(vals[2]))) - throw effect_exception{AL_INVALID_VALUE, "EAX Reverb late reverb pan out of range"}; - props->Reverb.LateReverbPan[0] = vals[0]; - props->Reverb.LateReverbPan[1] = vals[1]; - props->Reverb.LateReverbPan[2] = vals[2]; - break; - - default: - Reverb_setParamf(props, param, vals[0]); - break; + values = {vals, 3_uz}; + if(!std::all_of(values.cbegin(), values.cend(), finite_checker)) + context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb pan out of range"); + std::copy(values.cbegin(), values.cend(), props.LateReverbPan.begin()); + return; } + SetParamf(context, props, param, *vals); } -void Reverb_getParami(const EffectProps *props, ALenum param, int *val) +void ReverbEffectHandler::GetParami(ALCcontext *context, const ReverbProps &props, ALenum param, int *val) { switch(param) { - case AL_EAXREVERB_DECAY_HFLIMIT: - *val = props->Reverb.DecayHFLimit; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb integer property 0x%04x", - param}; + case AL_EAXREVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}", + as_unsigned(param)); } -void Reverb_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ Reverb_getParami(props, param, vals); } -void Reverb_getParamf(const EffectProps *props, ALenum param, float *val) +void ReverbEffectHandler::GetParamiv(ALCcontext *context, const ReverbProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void ReverbEffectHandler::GetParamf(ALCcontext *context, const ReverbProps &props, ALenum param, float *val) { switch(param) { - case AL_EAXREVERB_DENSITY: - *val = props->Reverb.Density; - break; - - case AL_EAXREVERB_DIFFUSION: - *val = props->Reverb.Diffusion; - break; - - case AL_EAXREVERB_GAIN: - *val = props->Reverb.Gain; - break; - - case AL_EAXREVERB_GAINHF: - *val = props->Reverb.GainHF; - break; - - case AL_EAXREVERB_GAINLF: - *val = props->Reverb.GainLF; - break; - - case AL_EAXREVERB_DECAY_TIME: - *val = props->Reverb.DecayTime; - break; - - case AL_EAXREVERB_DECAY_HFRATIO: - *val = props->Reverb.DecayHFRatio; - break; - - case AL_EAXREVERB_DECAY_LFRATIO: - *val = props->Reverb.DecayLFRatio; - break; - - case AL_EAXREVERB_REFLECTIONS_GAIN: - *val = props->Reverb.ReflectionsGain; - break; - - case AL_EAXREVERB_REFLECTIONS_DELAY: - *val = props->Reverb.ReflectionsDelay; - break; - - case AL_EAXREVERB_LATE_REVERB_GAIN: - *val = props->Reverb.LateReverbGain; - break; - - case AL_EAXREVERB_LATE_REVERB_DELAY: - *val = props->Reverb.LateReverbDelay; - break; - - case AL_EAXREVERB_ECHO_TIME: - *val = props->Reverb.EchoTime; - break; - - case AL_EAXREVERB_ECHO_DEPTH: - *val = props->Reverb.EchoDepth; - break; - - case AL_EAXREVERB_MODULATION_TIME: - *val = props->Reverb.ModulationTime; - break; - - case AL_EAXREVERB_MODULATION_DEPTH: - *val = props->Reverb.ModulationDepth; - break; - - case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: - *val = props->Reverb.AirAbsorptionGainHF; - break; - - case AL_EAXREVERB_HFREFERENCE: - *val = props->Reverb.HFReference; - break; - - case AL_EAXREVERB_LFREFERENCE: - *val = props->Reverb.LFReference; - break; - - case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: - *val = props->Reverb.RoomRolloffFactor; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid EAX reverb float property 0x%04x", param}; + case AL_EAXREVERB_DENSITY: *val = props.Density; return; + case AL_EAXREVERB_DIFFUSION: *val = props.Diffusion; return; + case AL_EAXREVERB_GAIN: *val = props.Gain; return; + case AL_EAXREVERB_GAINHF: *val = props.GainHF; return; + case AL_EAXREVERB_GAINLF: *val = props.GainLF; return; + case AL_EAXREVERB_DECAY_TIME: *val = props.DecayTime; return; + case AL_EAXREVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; return; + case AL_EAXREVERB_DECAY_LFRATIO: *val = props.DecayLFRatio; return; + case AL_EAXREVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; return; + case AL_EAXREVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; return; + case AL_EAXREVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; return; + case AL_EAXREVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; return; + case AL_EAXREVERB_ECHO_TIME: *val = props.EchoTime; return; + case AL_EAXREVERB_ECHO_DEPTH: *val = props.EchoDepth; return; + case AL_EAXREVERB_MODULATION_TIME: *val = props.ModulationTime; return; + case AL_EAXREVERB_MODULATION_DEPTH: *val = props.ModulationDepth; return; + case AL_EAXREVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; return; + case AL_EAXREVERB_HFREFERENCE: *val = props.HFReference; return; + case AL_EAXREVERB_LFREFERENCE: *val = props.LFReference; return; + case AL_EAXREVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}", + as_unsigned(param)); } -void Reverb_getParamfv(const EffectProps *props, ALenum param, float *vals) +void ReverbEffectHandler::GetParamfv(ALCcontext *context, const ReverbProps &props, ALenum param, float *vals) { + al::span values; switch(param) { case AL_EAXREVERB_REFLECTIONS_PAN: - vals[0] = props->Reverb.ReflectionsPan[0]; - vals[1] = props->Reverb.ReflectionsPan[1]; - vals[2] = props->Reverb.ReflectionsPan[2]; - break; + values = {vals, 3_uz}; + std::copy(props.ReflectionsPan.cbegin(), props.ReflectionsPan.cend(), values.begin()); + return; case AL_EAXREVERB_LATE_REVERB_PAN: - vals[0] = props->Reverb.LateReverbPan[0]; - vals[1] = props->Reverb.LateReverbPan[1]; - vals[2] = props->Reverb.LateReverbPan[2]; - break; - - default: - Reverb_getParamf(props, param, vals); - break; + values = {vals, 3_uz}; + std::copy(props.LateReverbPan.cbegin(), props.LateReverbPan.cend(), values.begin()); + return; } -} -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Reverb.Density = AL_EAXREVERB_DEFAULT_DENSITY; - props.Reverb.Diffusion = AL_EAXREVERB_DEFAULT_DIFFUSION; - props.Reverb.Gain = AL_EAXREVERB_DEFAULT_GAIN; - props.Reverb.GainHF = AL_EAXREVERB_DEFAULT_GAINHF; - props.Reverb.GainLF = AL_EAXREVERB_DEFAULT_GAINLF; - props.Reverb.DecayTime = AL_EAXREVERB_DEFAULT_DECAY_TIME; - props.Reverb.DecayHFRatio = AL_EAXREVERB_DEFAULT_DECAY_HFRATIO; - props.Reverb.DecayLFRatio = AL_EAXREVERB_DEFAULT_DECAY_LFRATIO; - props.Reverb.ReflectionsGain = AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN; - props.Reverb.ReflectionsDelay = AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY; - props.Reverb.ReflectionsPan[0] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; - props.Reverb.ReflectionsPan[1] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; - props.Reverb.ReflectionsPan[2] = AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN_XYZ; - props.Reverb.LateReverbGain = AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN; - props.Reverb.LateReverbDelay = AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY; - props.Reverb.LateReverbPan[0] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; - props.Reverb.LateReverbPan[1] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; - props.Reverb.LateReverbPan[2] = AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN_XYZ; - props.Reverb.EchoTime = AL_EAXREVERB_DEFAULT_ECHO_TIME; - props.Reverb.EchoDepth = AL_EAXREVERB_DEFAULT_ECHO_DEPTH; - props.Reverb.ModulationTime = AL_EAXREVERB_DEFAULT_MODULATION_TIME; - props.Reverb.ModulationDepth = AL_EAXREVERB_DEFAULT_MODULATION_DEPTH; - props.Reverb.AirAbsorptionGainHF = AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF; - props.Reverb.HFReference = AL_EAXREVERB_DEFAULT_HFREFERENCE; - props.Reverb.LFReference = AL_EAXREVERB_DEFAULT_LFREFERENCE; - props.Reverb.RoomRolloffFactor = AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; - props.Reverb.DecayHFLimit = AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT; - return props; + GetParamf(context, props, param, vals); } -void StdReverb_setParami(EffectProps *props, ALenum param, int val) +const EffectProps StdReverbEffectProps{genDefaultStdProps()}; + +void StdReverbEffectHandler::SetParami(ALCcontext *context, ReverbProps &props, ALenum param, int val) { switch(param) { case AL_REVERB_DECAY_HFLIMIT: if(!(val >= AL_REVERB_MIN_DECAY_HFLIMIT && val <= AL_REVERB_MAX_DECAY_HFLIMIT)) - throw effect_exception{AL_INVALID_VALUE, "Reverb decay hflimit out of range"}; - props->Reverb.DecayHFLimit = val != AL_FALSE; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid reverb integer property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hflimit out of range"); + props.DecayHFLimit = val != AL_FALSE; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}", + as_unsigned(param)); } -void StdReverb_setParamiv(EffectProps *props, ALenum param, const int *vals) -{ StdReverb_setParami(props, param, vals[0]); } -void StdReverb_setParamf(EffectProps *props, ALenum param, float val) +void StdReverbEffectHandler::SetParamiv(ALCcontext *context, ReverbProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void StdReverbEffectHandler::SetParamf(ALCcontext *context, ReverbProps &props, ALenum param, float val) { switch(param) { case AL_REVERB_DENSITY: if(!(val >= AL_REVERB_MIN_DENSITY && val <= AL_REVERB_MAX_DENSITY)) - throw effect_exception{AL_INVALID_VALUE, "Reverb density out of range"}; - props->Reverb.Density = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb density out of range"); + props.Density = val; + return; case AL_REVERB_DIFFUSION: if(!(val >= AL_REVERB_MIN_DIFFUSION && val <= AL_REVERB_MAX_DIFFUSION)) - throw effect_exception{AL_INVALID_VALUE, "Reverb diffusion out of range"}; - props->Reverb.Diffusion = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb diffusion out of range"); + props.Diffusion = val; + return; case AL_REVERB_GAIN: if(!(val >= AL_REVERB_MIN_GAIN && val <= AL_REVERB_MAX_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Reverb gain out of range"}; - props->Reverb.Gain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb gain out of range"); + props.Gain = val; + return; case AL_REVERB_GAINHF: if(!(val >= AL_REVERB_MIN_GAINHF && val <= AL_REVERB_MAX_GAINHF)) - throw effect_exception{AL_INVALID_VALUE, "Reverb gainhf out of range"}; - props->Reverb.GainHF = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb gainhf out of range"); + props.GainHF = val; + return; case AL_REVERB_DECAY_TIME: if(!(val >= AL_REVERB_MIN_DECAY_TIME && val <= AL_REVERB_MAX_DECAY_TIME)) - throw effect_exception{AL_INVALID_VALUE, "Reverb decay time out of range"}; - props->Reverb.DecayTime = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay time out of range"); + props.DecayTime = val; + return; case AL_REVERB_DECAY_HFRATIO: if(!(val >= AL_REVERB_MIN_DECAY_HFRATIO && val <= AL_REVERB_MAX_DECAY_HFRATIO)) - throw effect_exception{AL_INVALID_VALUE, "Reverb decay hfratio out of range"}; - props->Reverb.DecayHFRatio = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb decay hfratio out of range"); + props.DecayHFRatio = val; + return; case AL_REVERB_REFLECTIONS_GAIN: if(!(val >= AL_REVERB_MIN_REFLECTIONS_GAIN && val <= AL_REVERB_MAX_REFLECTIONS_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Reverb reflections gain out of range"}; - props->Reverb.ReflectionsGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections gain out of range"); + props.ReflectionsGain = val; + return; case AL_REVERB_REFLECTIONS_DELAY: if(!(val >= AL_REVERB_MIN_REFLECTIONS_DELAY && val <= AL_REVERB_MAX_REFLECTIONS_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "Reverb reflections delay out of range"}; - props->Reverb.ReflectionsDelay = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb reflections delay out of range"); + props.ReflectionsDelay = val; + return; case AL_REVERB_LATE_REVERB_GAIN: if(!(val >= AL_REVERB_MIN_LATE_REVERB_GAIN && val <= AL_REVERB_MAX_LATE_REVERB_GAIN)) - throw effect_exception{AL_INVALID_VALUE, "Reverb late reverb gain out of range"}; - props->Reverb.LateReverbGain = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb gain out of range"); + props.LateReverbGain = val; + return; case AL_REVERB_LATE_REVERB_DELAY: if(!(val >= AL_REVERB_MIN_LATE_REVERB_DELAY && val <= AL_REVERB_MAX_LATE_REVERB_DELAY)) - throw effect_exception{AL_INVALID_VALUE, "Reverb late reverb delay out of range"}; - props->Reverb.LateReverbDelay = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb late reverb delay out of range"); + props.LateReverbDelay = val; + return; case AL_REVERB_AIR_ABSORPTION_GAINHF: if(!(val >= AL_REVERB_MIN_AIR_ABSORPTION_GAINHF && val <= AL_REVERB_MAX_AIR_ABSORPTION_GAINHF)) - throw effect_exception{AL_INVALID_VALUE, "Reverb air absorption gainhf out of range"}; - props->Reverb.AirAbsorptionGainHF = val; - break; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb air absorption gainhf out of range"); + props.AirAbsorptionGainHF = val; + return; case AL_REVERB_ROOM_ROLLOFF_FACTOR: if(!(val >= AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR && val <= AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR)) - throw effect_exception{AL_INVALID_VALUE, "Reverb room rolloff factor out of range"}; - props->Reverb.RoomRolloffFactor = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid reverb float property 0x%04x", param}; + context->throw_error(AL_INVALID_VALUE, "EAX Reverb room rolloff factor out of range"); + props.RoomRolloffFactor = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}", + as_unsigned(param)); } -void StdReverb_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ StdReverb_setParamf(props, param, vals[0]); } +void StdReverbEffectHandler::SetParamfv(ALCcontext *context, ReverbProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void StdReverb_getParami(const EffectProps *props, ALenum param, int *val) +void StdReverbEffectHandler::GetParami(ALCcontext *context, const ReverbProps &props, ALenum param, int *val) { switch(param) { - case AL_REVERB_DECAY_HFLIMIT: - *val = props->Reverb.DecayHFLimit; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid reverb integer property 0x%04x", param}; + case AL_REVERB_DECAY_HFLIMIT: *val = props.DecayHFLimit; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb integer property {:#04x}", + as_unsigned(param)); } -void StdReverb_getParamiv(const EffectProps *props, ALenum param, int *vals) -{ StdReverb_getParami(props, param, vals); } -void StdReverb_getParamf(const EffectProps *props, ALenum param, float *val) +void StdReverbEffectHandler::GetParamiv(ALCcontext *context, const ReverbProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void StdReverbEffectHandler::GetParamf(ALCcontext *context, const ReverbProps &props, ALenum param, float *val) { switch(param) { - case AL_REVERB_DENSITY: - *val = props->Reverb.Density; - break; - - case AL_REVERB_DIFFUSION: - *val = props->Reverb.Diffusion; - break; - - case AL_REVERB_GAIN: - *val = props->Reverb.Gain; - break; - - case AL_REVERB_GAINHF: - *val = props->Reverb.GainHF; - break; - - case AL_REVERB_DECAY_TIME: - *val = props->Reverb.DecayTime; - break; - - case AL_REVERB_DECAY_HFRATIO: - *val = props->Reverb.DecayHFRatio; - break; - - case AL_REVERB_REFLECTIONS_GAIN: - *val = props->Reverb.ReflectionsGain; - break; - - case AL_REVERB_REFLECTIONS_DELAY: - *val = props->Reverb.ReflectionsDelay; - break; - - case AL_REVERB_LATE_REVERB_GAIN: - *val = props->Reverb.LateReverbGain; - break; - - case AL_REVERB_LATE_REVERB_DELAY: - *val = props->Reverb.LateReverbDelay; - break; - - case AL_REVERB_AIR_ABSORPTION_GAINHF: - *val = props->Reverb.AirAbsorptionGainHF; - break; - - case AL_REVERB_ROOM_ROLLOFF_FACTOR: - *val = props->Reverb.RoomRolloffFactor; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid reverb float property 0x%04x", param}; + case AL_REVERB_DENSITY: *val = props.Density; return; + case AL_REVERB_DIFFUSION: *val = props.Diffusion; return; + case AL_REVERB_GAIN: *val = props.Gain; return; + case AL_REVERB_GAINHF: *val = props.GainHF; return; + case AL_REVERB_DECAY_TIME: *val = props.DecayTime; return; + case AL_REVERB_DECAY_HFRATIO: *val = props.DecayHFRatio; return; + case AL_REVERB_REFLECTIONS_GAIN: *val = props.ReflectionsGain; return; + case AL_REVERB_REFLECTIONS_DELAY: *val = props.ReflectionsDelay; return; + case AL_REVERB_LATE_REVERB_GAIN: *val = props.LateReverbGain; return; + case AL_REVERB_LATE_REVERB_DELAY: *val = props.LateReverbDelay; return; + case AL_REVERB_AIR_ABSORPTION_GAINHF: *val = props.AirAbsorptionGainHF; return; + case AL_REVERB_ROOM_ROLLOFF_FACTOR: *val = props.RoomRolloffFactor; return; } -} -void StdReverb_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ StdReverb_getParamf(props, param, vals); } -EffectProps genDefaultStdProps() noexcept -{ - EffectProps props{}; - props.Reverb.Density = AL_REVERB_DEFAULT_DENSITY; - props.Reverb.Diffusion = AL_REVERB_DEFAULT_DIFFUSION; - props.Reverb.Gain = AL_REVERB_DEFAULT_GAIN; - props.Reverb.GainHF = AL_REVERB_DEFAULT_GAINHF; - props.Reverb.GainLF = 1.0f; - props.Reverb.DecayTime = AL_REVERB_DEFAULT_DECAY_TIME; - props.Reverb.DecayHFRatio = AL_REVERB_DEFAULT_DECAY_HFRATIO; - props.Reverb.DecayLFRatio = 1.0f; - props.Reverb.ReflectionsGain = AL_REVERB_DEFAULT_REFLECTIONS_GAIN; - props.Reverb.ReflectionsDelay = AL_REVERB_DEFAULT_REFLECTIONS_DELAY; - props.Reverb.ReflectionsPan[0] = 0.0f; - props.Reverb.ReflectionsPan[1] = 0.0f; - props.Reverb.ReflectionsPan[2] = 0.0f; - props.Reverb.LateReverbGain = AL_REVERB_DEFAULT_LATE_REVERB_GAIN; - props.Reverb.LateReverbDelay = AL_REVERB_DEFAULT_LATE_REVERB_DELAY; - props.Reverb.LateReverbPan[0] = 0.0f; - props.Reverb.LateReverbPan[1] = 0.0f; - props.Reverb.LateReverbPan[2] = 0.0f; - props.Reverb.EchoTime = 0.25f; - props.Reverb.EchoDepth = 0.0f; - props.Reverb.ModulationTime = 0.25f; - props.Reverb.ModulationDepth = 0.0f; - props.Reverb.AirAbsorptionGainHF = AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF; - props.Reverb.HFReference = 5000.0f; - props.Reverb.LFReference = 250.0f; - props.Reverb.RoomRolloffFactor = AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR; - props.Reverb.DecayHFLimit = AL_REVERB_DEFAULT_DECAY_HFLIMIT; - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid EAX reverb float property {:#04x}", + as_unsigned(param)); } +void StdReverbEffectHandler::GetParamfv(ALCcontext *context, const ReverbProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Reverb); - -const EffectProps ReverbEffectProps{genDefaultProps()}; - -DEFINE_ALEFFECT_VTABLE(StdReverb); - -const EffectProps StdReverbEffectProps{genDefaultStdProps()}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { class EaxReverbEffectException : public EaxException @@ -1086,98 +979,119 @@ struct EaxReverbCommitter::Exception : public EaxReverbEffectException throw Exception{message}; } -void EaxReverbCommitter::translate(const EAX_REVERBPROPERTIES& src, EaxEffectProps& dst) noexcept +void EaxReverbCommitter::translate(const EAX_REVERBPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept { assert(src.environment <= EAX1REVERB_MAXENVIRONMENT); - auto&& eaxprops = dst.emplace(EAXREVERB_PRESETS[src.environment]); - eaxprops.flDecayTime = src.fDecayTime_sec; - eaxprops.flDecayHFRatio = src.fDamping; - eaxprops.lReverb = mini(static_cast(gain_to_level_mb(src.fVolume)), 0); + dst = EAXREVERB_PRESETS[src.environment]; + dst.flDecayTime = src.fDecayTime_sec; + dst.flDecayHFRatio = src.fDamping; + dst.lReverb = static_cast(std::min(gain_to_level_mb(src.fVolume), 0.0f)); } -void EaxReverbCommitter::translate(const EAX20LISTENERPROPERTIES& src, EaxEffectProps& dst) noexcept +void EaxReverbCommitter::translate(const EAX20LISTENERPROPERTIES& src, EAXREVERBPROPERTIES& dst) noexcept { assert(src.dwEnvironment <= EAX1REVERB_MAXENVIRONMENT); - auto&& eaxprops = dst.emplace(EAXREVERB_PRESETS[src.dwEnvironment]); - eaxprops.ulEnvironment = src.dwEnvironment; - eaxprops.flEnvironmentSize = src.flEnvironmentSize; - eaxprops.flEnvironmentDiffusion = src.flEnvironmentDiffusion; - eaxprops.lRoom = src.lRoom; - eaxprops.lRoomHF = src.lRoomHF; - eaxprops.flDecayTime = src.flDecayTime; - eaxprops.flDecayHFRatio = src.flDecayHFRatio; - eaxprops.lReflections = src.lReflections; - eaxprops.flReflectionsDelay = src.flReflectionsDelay; - eaxprops.lReverb = src.lReverb; - eaxprops.flReverbDelay = src.flReverbDelay; - eaxprops.flAirAbsorptionHF = src.flAirAbsorptionHF; - eaxprops.flRoomRolloffFactor = src.flRoomRolloffFactor; - eaxprops.ulFlags = src.dwFlags; -} - -void EaxReverbCommitter::translate(const EAXREVERBPROPERTIES& src, EaxEffectProps& dst) noexcept -{ - dst = src; + dst = EAXREVERB_PRESETS[src.dwEnvironment]; + dst.ulEnvironment = src.dwEnvironment; + dst.flEnvironmentSize = src.flEnvironmentSize; + dst.flEnvironmentDiffusion = src.flEnvironmentDiffusion; + dst.lRoom = src.lRoom; + dst.lRoomHF = src.lRoomHF; + dst.flDecayTime = src.flDecayTime; + dst.flDecayHFRatio = src.flDecayHFRatio; + dst.lReflections = src.lReflections; + dst.flReflectionsDelay = src.flReflectionsDelay; + dst.lReverb = src.lReverb; + dst.flReverbDelay = src.flReverbDelay; + dst.flAirAbsorptionHF = src.flAirAbsorptionHF; + dst.flRoomRolloffFactor = src.flRoomRolloffFactor; + dst.ulFlags = src.dwFlags; } bool EaxReverbCommitter::commit(const EAX_REVERBPROPERTIES &props) { - EaxEffectProps dst{}; + EAXREVERBPROPERTIES dst{}; translate(props, dst); return commit(dst); } bool EaxReverbCommitter::commit(const EAX20LISTENERPROPERTIES &props) { - EaxEffectProps dst{}; + EAXREVERBPROPERTIES dst{}; translate(props, dst); return commit(dst); } bool EaxReverbCommitter::commit(const EAXREVERBPROPERTIES &props) { - EaxEffectProps dst{}; - translate(props, dst); - return commit(dst); -} - -bool EaxReverbCommitter::commit(const EaxEffectProps &props) -{ - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; - auto &eaxprops = std::get(props); - const auto size = eaxprops.flEnvironmentSize; - const auto density = (size * size * size) / 16.0F; - mAlProps.Reverb.Density = std::min(density, AL_EAXREVERB_MAX_DENSITY); - mAlProps.Reverb.Diffusion = eaxprops.flEnvironmentDiffusion; - mAlProps.Reverb.Gain = level_mb_to_gain(static_cast(eaxprops.lRoom)); - mAlProps.Reverb.GainHF = level_mb_to_gain(static_cast(eaxprops.lRoomHF)); - mAlProps.Reverb.GainLF = level_mb_to_gain(static_cast(eaxprops.lRoomLF)); - mAlProps.Reverb.DecayTime = eaxprops.flDecayTime; - mAlProps.Reverb.DecayHFRatio = eaxprops.flDecayHFRatio; - mAlProps.Reverb.DecayLFRatio = eaxprops.flDecayLFRatio; - mAlProps.Reverb.ReflectionsGain = level_mb_to_gain(static_cast(eaxprops.lReflections)); - mAlProps.Reverb.ReflectionsDelay = eaxprops.flReflectionsDelay; - mAlProps.Reverb.ReflectionsPan[0] = eaxprops.vReflectionsPan.x; - mAlProps.Reverb.ReflectionsPan[1] = eaxprops.vReflectionsPan.y; - mAlProps.Reverb.ReflectionsPan[2] = eaxprops.vReflectionsPan.z; - mAlProps.Reverb.LateReverbGain = level_mb_to_gain(static_cast(eaxprops.lReverb)); - mAlProps.Reverb.LateReverbDelay = eaxprops.flReverbDelay; - mAlProps.Reverb.LateReverbPan[0] = eaxprops.vReverbPan.x; - mAlProps.Reverb.LateReverbPan[1] = eaxprops.vReverbPan.y; - mAlProps.Reverb.LateReverbPan[2] = eaxprops.vReverbPan.z; - mAlProps.Reverb.EchoTime = eaxprops.flEchoTime; - mAlProps.Reverb.EchoDepth = eaxprops.flEchoDepth; - mAlProps.Reverb.ModulationTime = eaxprops.flModulationTime; - mAlProps.Reverb.ModulationDepth = eaxprops.flModulationDepth; - mAlProps.Reverb.AirAbsorptionGainHF = level_mb_to_gain(eaxprops.flAirAbsorptionHF); - mAlProps.Reverb.HFReference = eaxprops.flHFReference; - mAlProps.Reverb.LFReference = eaxprops.flLFReference; - mAlProps.Reverb.RoomRolloffFactor = eaxprops.flRoomRolloffFactor; - mAlProps.Reverb.DecayHFLimit = ((eaxprops.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + const auto size = props.flEnvironmentSize; + const auto density = (size * size * size) / 16.0f; + mAlProps = [&]{ + ReverbProps ret{}; + ret.Density = std::min(density, AL_EAXREVERB_MAX_DENSITY); + ret.Diffusion = props.flEnvironmentDiffusion; + ret.Gain = level_mb_to_gain(static_cast(props.lRoom)); + ret.GainHF = level_mb_to_gain(static_cast(props.lRoomHF)); + ret.GainLF = level_mb_to_gain(static_cast(props.lRoomLF)); + ret.DecayTime = props.flDecayTime; + ret.DecayHFRatio = props.flDecayHFRatio; + ret.DecayLFRatio = props.flDecayLFRatio; + ret.ReflectionsGain = level_mb_to_gain(static_cast(props.lReflections)); + ret.ReflectionsDelay = props.flReflectionsDelay; + ret.ReflectionsPan = {props.vReflectionsPan.x, props.vReflectionsPan.y, + props.vReflectionsPan.z}; + ret.LateReverbGain = level_mb_to_gain(static_cast(props.lReverb)); + ret.LateReverbDelay = props.flReverbDelay; + ret.LateReverbPan = {props.vReverbPan.x, props.vReverbPan.y, props.vReverbPan.z}; + ret.EchoTime = props.flEchoTime; + ret.EchoDepth = props.flEchoDepth; + ret.ModulationTime = props.flModulationTime; + ret.ModulationDepth = props.flModulationDepth; + ret.AirAbsorptionGainHF = level_mb_to_gain(props.flAirAbsorptionHF); + ret.HFReference = props.flHFReference; + ret.LFReference = props.flLFReference; + ret.RoomRolloffFactor = props.flRoomRolloffFactor; + ret.DecayHFLimit = ((props.ulFlags & EAXREVERBFLAGS_DECAYHFLIMIT) != 0); + if(EaxTraceCommits) UNLIKELY + { + TRACE("Reverb commit:\n" + " Density: {:f}\n" + " Diffusion: {:f}\n" + " Gain: {:f}\n" + " GainHF: {:f}\n" + " GainLF: {:f}\n" + " DecayTime: {:f}\n" + " DecayHFRatio: {:f}\n" + " DecayLFRatio: {:f}\n" + " ReflectionsGain: {:f}\n" + " ReflectionsDelay: {:f}\n" + " ReflectionsPan: {}\n" + " LateReverbGain: {:f}\n" + " LateReverbDelay: {:f}\n" + " LateRevernPan: {}\n" + " EchoTime: {:f}\n" + " EchoDepth: {:f}\n" + " ModulationTime: {:f}\n" + " ModulationDepth: {:f}\n" + " AirAbsorptionGainHF: {:f}\n" + " HFReference: {:f}\n" + " LFReference: {:f}\n" + " RoomRolloffFactor: {:f}\n" + " DecayHFLimit: {}", ret.Density, ret.Diffusion, ret.Gain, ret.GainHF, ret.GainLF, + ret.DecayTime, ret.DecayHFRatio, ret.DecayLFRatio, ret.ReflectionsGain, + ret.ReflectionsDelay, ret.ReflectionsPan, ret.LateReverbGain, ret.LateReverbDelay, + ret.LateReverbPan, ret.EchoTime, ret.EchoDepth, ret.ModulationTime, + ret.ModulationDepth, ret.AirAbsorptionGainHF, ret.HFReference, ret.LFReference, + ret.RoomRolloffFactor, ret.DecayHFLimit ? "true" : "false"); + } + return ret; + }(); + return true; } @@ -1274,11 +1188,6 @@ void EaxReverbCommitter::Get(const EaxCall &call, const EAXREVERBPROPERTIES &pro } } -void EaxReverbCommitter::Get(const EaxCall &call, const EaxEffectProps &props) -{ - Get(call, std::get(props)); -} - void EaxReverbCommitter::Set(const EaxCall &call, EAX_REVERBPROPERTIES &props) { @@ -1297,71 +1206,23 @@ void EaxReverbCommitter::Set(const EaxCall &call, EAX20LISTENERPROPERTIES &props { switch(call.get_property_id()) { - case DSPROPERTY_EAX20LISTENER_NONE: - break; - - case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: - defer(call, props); - break; - - case DSPROPERTY_EAX20LISTENER_ROOM: - defer(call, props.lRoom); - break; - - case DSPROPERTY_EAX20LISTENER_ROOMHF: - defer(call, props.lRoomHF); - break; - - case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: - defer(call, props.flRoomRolloffFactor); - break; - - case DSPROPERTY_EAX20LISTENER_DECAYTIME: - defer(call, props.flDecayTime); - break; - - case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: - defer(call, props.flDecayHFRatio); - break; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONS: - defer(call, props.lReflections); - break; - - case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: - defer(call, props.flReverbDelay); - break; - - case DSPROPERTY_EAX20LISTENER_REVERB: - defer(call, props.lReverb); - break; - - case DSPROPERTY_EAX20LISTENER_REVERBDELAY: - defer(call, props.flReverbDelay); - break; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: - defer(call, props, props.dwEnvironment); - break; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: - defer(call, props, props.flEnvironmentSize); - break; - - case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: - defer(call, props.flEnvironmentDiffusion); - break; - - case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: - defer(call, props.flAirAbsorptionHF); - break; - - case DSPROPERTY_EAX20LISTENER_FLAGS: - defer(call, props.dwFlags); - break; - - default: - fail_unknown_property_id(); + case DSPROPERTY_EAX20LISTENER_NONE: break; + case DSPROPERTY_EAX20LISTENER_ALLPARAMETERS: defer(call, props); break; + case DSPROPERTY_EAX20LISTENER_ROOM: defer(call, props.lRoom); break; + case DSPROPERTY_EAX20LISTENER_ROOMHF: defer(call, props.lRoomHF); break; + case DSPROPERTY_EAX20LISTENER_ROOMROLLOFFFACTOR: defer(call, props.flRoomRolloffFactor); break; + case DSPROPERTY_EAX20LISTENER_DECAYTIME: defer(call, props.flDecayTime); break; + case DSPROPERTY_EAX20LISTENER_DECAYHFRATIO: defer(call, props.flDecayHFRatio); break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONS: defer(call, props.lReflections); break; + case DSPROPERTY_EAX20LISTENER_REFLECTIONSDELAY: defer(call, props.flReverbDelay); break; + case DSPROPERTY_EAX20LISTENER_REVERB: defer(call, props.lReverb); break; + case DSPROPERTY_EAX20LISTENER_REVERBDELAY: defer(call, props.flReverbDelay); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENT: defer(call, props, props.dwEnvironment); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTSIZE: defer(call, props, props.flEnvironmentSize); break; + case DSPROPERTY_EAX20LISTENER_ENVIRONMENTDIFFUSION: defer(call, props.flEnvironmentDiffusion); break; + case DSPROPERTY_EAX20LISTENER_AIRABSORPTIONHF: defer(call, props.flAirAbsorptionHF); break; + case DSPROPERTY_EAX20LISTENER_FLAGS: defer(call, props.dwFlags); break; + default: fail_unknown_property_id(); } } @@ -1369,117 +1230,34 @@ void EaxReverbCommitter::Set(const EaxCall &call, EAXREVERBPROPERTIES &props) { switch(call.get_property_id()) { - case EAXREVERB_NONE: - break; - - case EAXREVERB_ALLPARAMETERS: - defer(call, props); - break; - - case EAXREVERB_ENVIRONMENT: - defer(call, props, props.ulEnvironment); - break; - - case EAXREVERB_ENVIRONMENTSIZE: - defer(call, props, props.flEnvironmentSize); - break; - - case EAXREVERB_ENVIRONMENTDIFFUSION: - defer3(call, props, props.flEnvironmentDiffusion); - break; - - case EAXREVERB_ROOM: - defer3(call, props, props.lRoom); - break; - - case EAXREVERB_ROOMHF: - defer3(call, props, props.lRoomHF); - break; - - case EAXREVERB_ROOMLF: - defer3(call, props, props.lRoomLF); - break; - - case EAXREVERB_DECAYTIME: - defer3(call, props, props.flDecayTime); - break; - - case EAXREVERB_DECAYHFRATIO: - defer3(call, props, props.flDecayHFRatio); - break; - - case EAXREVERB_DECAYLFRATIO: - defer3(call, props, props.flDecayLFRatio); - break; - - case EAXREVERB_REFLECTIONS: - defer3(call, props, props.lReflections); - break; - - case EAXREVERB_REFLECTIONSDELAY: - defer3(call, props, props.flReflectionsDelay); - break; - - case EAXREVERB_REFLECTIONSPAN: - defer3(call, props, props.vReflectionsPan); - break; - - case EAXREVERB_REVERB: - defer3(call, props, props.lReverb); - break; - - case EAXREVERB_REVERBDELAY: - defer3(call, props, props.flReverbDelay); - break; - - case EAXREVERB_REVERBPAN: - defer3(call, props, props.vReverbPan); - break; - - case EAXREVERB_ECHOTIME: - defer3(call, props, props.flEchoTime); - break; - - case EAXREVERB_ECHODEPTH: - defer3(call, props, props.flEchoDepth); - break; - - case EAXREVERB_MODULATIONTIME: - defer3(call, props, props.flModulationTime); - break; - - case EAXREVERB_MODULATIONDEPTH: - defer3(call, props, props.flModulationDepth); - break; - - case EAXREVERB_AIRABSORPTIONHF: - defer3(call, props, props.flAirAbsorptionHF); - break; - - case EAXREVERB_HFREFERENCE: - defer3(call, props, props.flHFReference); - break; - - case EAXREVERB_LFREFERENCE: - defer3(call, props, props.flLFReference); - break; - - case EAXREVERB_ROOMROLLOFFFACTOR: - defer3(call, props, props.flRoomRolloffFactor); - break; - - case EAXREVERB_FLAGS: - defer3(call, props, props.ulFlags); - break; - - default: - fail_unknown_property_id(); + case EAXREVERB_NONE: break; + case EAXREVERB_ALLPARAMETERS: defer(call, props); break; + case EAXREVERB_ENVIRONMENT: defer(call, props, props.ulEnvironment); break; + case EAXREVERB_ENVIRONMENTSIZE: defer(call, props, props.flEnvironmentSize); break; + case EAXREVERB_ENVIRONMENTDIFFUSION: defer3(call, props, props.flEnvironmentDiffusion); break; + case EAXREVERB_ROOM: defer3(call, props, props.lRoom); break; + case EAXREVERB_ROOMHF: defer3(call, props, props.lRoomHF); break; + case EAXREVERB_ROOMLF: defer3(call, props, props.lRoomLF); break; + case EAXREVERB_DECAYTIME: defer3(call, props, props.flDecayTime); break; + case EAXREVERB_DECAYHFRATIO: defer3(call, props, props.flDecayHFRatio); break; + case EAXREVERB_DECAYLFRATIO: defer3(call, props, props.flDecayLFRatio); break; + case EAXREVERB_REFLECTIONS: defer3(call, props, props.lReflections); break; + case EAXREVERB_REFLECTIONSDELAY: defer3(call, props, props.flReflectionsDelay); break; + case EAXREVERB_REFLECTIONSPAN: defer3(call, props, props.vReflectionsPan); break; + case EAXREVERB_REVERB: defer3(call, props, props.lReverb); break; + case EAXREVERB_REVERBDELAY: defer3(call, props, props.flReverbDelay); break; + case EAXREVERB_REVERBPAN: defer3(call, props, props.vReverbPan); break; + case EAXREVERB_ECHOTIME: defer3(call, props, props.flEchoTime); break; + case EAXREVERB_ECHODEPTH: defer3(call, props, props.flEchoDepth); break; + case EAXREVERB_MODULATIONTIME: defer3(call, props, props.flModulationTime); break; + case EAXREVERB_MODULATIONDEPTH: defer3(call, props, props.flModulationDepth); break; + case EAXREVERB_AIRABSORPTIONHF: defer3(call, props, props.flAirAbsorptionHF); break; + case EAXREVERB_HFREFERENCE: defer3(call, props, props.flHFReference); break; + case EAXREVERB_LFREFERENCE: defer3(call, props, props.flLFReference); break; + case EAXREVERB_ROOMROLLOFFFACTOR: defer3(call, props, props.flRoomRolloffFactor); break; + case EAXREVERB_FLAGS: defer3(call, props, props.ulFlags); break; + default: fail_unknown_property_id(); } } -void EaxReverbCommitter::Set(const EaxCall &call, EaxEffectProps &props) -{ - Set(call, std::get(props)); -} - #endif // ALSOFT_EAX diff --git a/3rdparty/openal/al/effects/vmorpher.cpp b/3rdparty/openal/al/effects/vmorpher.cpp index f255122910ba..982bc7e4a63c 100644 --- a/3rdparty/openal/al/effects/vmorpher.cpp +++ b/3rdparty/openal/al/effects/vmorpher.cpp @@ -7,12 +7,13 @@ #include "AL/al.h" #include "AL/efx.h" -#include "alc/effects/base.h" +#include "alc/context.h" +#include "alnumeric.h" #include "effects.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include -#include "alnumeric.h" +#include "al/eax/effect.h" #include "al/eax/exception.h" #include "al/eax/utils.h" #endif // ALSOFT_EAX @@ -20,7 +21,7 @@ namespace { -std::optional PhenomeFromEnum(ALenum val) +constexpr std::optional PhenomeFromEnum(ALenum val) noexcept { #define HANDLE_PHENOME(x) case AL_VOCAL_MORPHER_PHONEME_ ## x: \ return VMorpherPhenome::x @@ -60,7 +61,7 @@ std::optional PhenomeFromEnum(ALenum val) return std::nullopt; #undef HANDLE_PHENOME } -ALenum EnumFromPhenome(VMorpherPhenome phenome) +constexpr ALenum EnumFromPhenome(VMorpherPhenome phenome) { #define HANDLE_PHENOME(x) case VMorpherPhenome::x: return AL_VOCAL_MORPHER_PHONEME_ ## x switch(phenome) @@ -96,11 +97,11 @@ ALenum EnumFromPhenome(VMorpherPhenome phenome) HANDLE_PHENOME(V); HANDLE_PHENOME(Z); } - throw std::runtime_error{"Invalid phenome: "+std::to_string(static_cast(phenome))}; + throw std::runtime_error{fmt::format("Invalid phenome: {}", int{al::to_underlying(phenome)})}; #undef HANDLE_PHENOME } -std::optional WaveformFromEmum(ALenum value) +constexpr std::optional WaveformFromEmum(ALenum value) noexcept { switch(value) { @@ -110,7 +111,7 @@ std::optional WaveformFromEmum(ALenum value) } return std::nullopt; } -ALenum EnumFromWaveform(VMorpherWaveform type) +constexpr ALenum EnumFromWaveform(VMorpherWaveform type) { switch(type) { @@ -118,144 +119,122 @@ ALenum EnumFromWaveform(VMorpherWaveform type) case VMorpherWaveform::Triangle: return AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE; case VMorpherWaveform::Sawtooth: return AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH; } - throw std::runtime_error{"Invalid vocal morpher waveform: " + - std::to_string(static_cast(type))}; + throw std::runtime_error{fmt::format("Invalid vocal morpher waveform: {}", + int{al::to_underlying(type)})}; } -void Vmorpher_setParami(EffectProps *props, ALenum param, int val) +constexpr EffectProps genDefaultProps() noexcept +{ + VmorpherProps props{}; + props.Rate = AL_VOCAL_MORPHER_DEFAULT_RATE; + props.PhonemeA = PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA).value(); + props.PhonemeB = PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB).value(); + props.PhonemeACoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING; + props.PhonemeBCoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING; + props.Waveform = WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM).value(); + return props; +} + +} // namespace + +const EffectProps VmorpherEffectProps{genDefaultProps()}; + +void VmorpherEffectHandler::SetParami(ALCcontext *context, VmorpherProps &props, ALenum param, int val) { switch(param) { case AL_VOCAL_MORPHER_PHONEMEA: if(auto phenomeopt = PhenomeFromEnum(val)) - props->Vmorpher.PhonemeA = *phenomeopt; + props.PhonemeA = *phenomeopt; else - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a out of range: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, + "Vocal morpher phoneme-a out of range: {:#04x}", as_unsigned(val)); + return; case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING: if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING)) - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-a coarse tuning out of range"}; - props->Vmorpher.PhonemeACoarseTuning = val; - break; + context->throw_error(AL_INVALID_VALUE, + "Vocal morpher phoneme-a coarse tuning out of range"); + props.PhonemeACoarseTuning = val; + return; case AL_VOCAL_MORPHER_PHONEMEB: if(auto phenomeopt = PhenomeFromEnum(val)) - props->Vmorpher.PhonemeB = *phenomeopt; + props.PhonemeB = *phenomeopt; else - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b out of range: 0x%04x", val}; - break; + context->throw_error(AL_INVALID_VALUE, + "Vocal morpher phoneme-b out of range: {:#04x}", as_unsigned(val)); + return; case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING: if(!(val >= AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING && val <= AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING)) - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher phoneme-b coarse tuning out of range"}; - props->Vmorpher.PhonemeBCoarseTuning = val; - break; + context->throw_error(AL_INVALID_VALUE, + "Vocal morpher phoneme-b coarse tuning out of range"); + props.PhonemeBCoarseTuning = val; + return; case AL_VOCAL_MORPHER_WAVEFORM: if(auto formopt = WaveformFromEmum(val)) - props->Vmorpher.Waveform = *formopt; + props.Waveform = *formopt; else - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher waveform out of range: 0x%04x", val}; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "Vocal morpher waveform out of range: {:#04x}", + as_unsigned(val)); + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher integer property {:#04x}", + as_unsigned(param)); } -void Vmorpher_setParamiv(EffectProps*, ALenum param, const int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x", - param}; -} -void Vmorpher_setParamf(EffectProps *props, ALenum param, float val) +void VmorpherEffectHandler::SetParamiv(ALCcontext *context, VmorpherProps &props, ALenum param, const int *vals) +{ SetParami(context, props, param, *vals); } +void VmorpherEffectHandler::SetParamf(ALCcontext *context, VmorpherProps &props, ALenum param, float val) { switch(param) { case AL_VOCAL_MORPHER_RATE: if(!(val >= AL_VOCAL_MORPHER_MIN_RATE && val <= AL_VOCAL_MORPHER_MAX_RATE)) - throw effect_exception{AL_INVALID_VALUE, "Vocal morpher rate out of range"}; - props->Vmorpher.Rate = val; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x", - param}; + context->throw_error(AL_INVALID_VALUE, "Vocal morpher rate out of range"); + props.Rate = val; + return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher float property {:#04x}", + as_unsigned(param)); } -void Vmorpher_setParamfv(EffectProps *props, ALenum param, const float *vals) -{ Vmorpher_setParamf(props, param, vals[0]); } +void VmorpherEffectHandler::SetParamfv(ALCcontext *context, VmorpherProps &props, ALenum param, const float *vals) +{ SetParamf(context, props, param, *vals); } -void Vmorpher_getParami(const EffectProps *props, ALenum param, int* val) +void VmorpherEffectHandler::GetParami(ALCcontext *context, const VmorpherProps &props, ALenum param, int* val) { switch(param) { - case AL_VOCAL_MORPHER_PHONEMEA: - *val = EnumFromPhenome(props->Vmorpher.PhonemeA); - break; - - case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING: - *val = props->Vmorpher.PhonemeACoarseTuning; - break; - - case AL_VOCAL_MORPHER_PHONEMEB: - *val = EnumFromPhenome(props->Vmorpher.PhonemeB); - break; - - case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING: - *val = props->Vmorpher.PhonemeBCoarseTuning; - break; - - case AL_VOCAL_MORPHER_WAVEFORM: - *val = EnumFromWaveform(props->Vmorpher.Waveform); - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer property 0x%04x", - param}; + case AL_VOCAL_MORPHER_PHONEMEA: *val = EnumFromPhenome(props.PhonemeA); return; + case AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING: *val = props.PhonemeACoarseTuning; return; + case AL_VOCAL_MORPHER_PHONEMEB: *val = EnumFromPhenome(props.PhonemeB); return; + case AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING: *val = props.PhonemeBCoarseTuning; return; + case AL_VOCAL_MORPHER_WAVEFORM: *val = EnumFromWaveform(props.Waveform); return; } + + context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher integer property {:#04x}", + as_unsigned(param)); } -void Vmorpher_getParamiv(const EffectProps*, ALenum param, int*) -{ - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher integer-vector property 0x%04x", - param}; -} -void Vmorpher_getParamf(const EffectProps *props, ALenum param, float *val) +void VmorpherEffectHandler::GetParamiv(ALCcontext *context, const VmorpherProps &props, ALenum param, int *vals) +{ GetParami(context, props, param, vals); } +void VmorpherEffectHandler::GetParamf(ALCcontext *context, const VmorpherProps &props, ALenum param, float *val) { switch(param) { - case AL_VOCAL_MORPHER_RATE: - *val = props->Vmorpher.Rate; - break; - - default: - throw effect_exception{AL_INVALID_ENUM, "Invalid vocal morpher float property 0x%04x", - param}; + case AL_VOCAL_MORPHER_RATE: *val = props.Rate; return; } -} -void Vmorpher_getParamfv(const EffectProps *props, ALenum param, float *vals) -{ Vmorpher_getParamf(props, param, vals); } -EffectProps genDefaultProps() noexcept -{ - EffectProps props{}; - props.Vmorpher.Rate = AL_VOCAL_MORPHER_DEFAULT_RATE; - props.Vmorpher.PhonemeA = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEA); - props.Vmorpher.PhonemeB = *PhenomeFromEnum(AL_VOCAL_MORPHER_DEFAULT_PHONEMEB); - props.Vmorpher.PhonemeACoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING; - props.Vmorpher.PhonemeBCoarseTuning = AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING; - props.Vmorpher.Waveform = *WaveformFromEmum(AL_VOCAL_MORPHER_DEFAULT_WAVEFORM); - return props; + context->throw_error(AL_INVALID_ENUM, "Invalid vocal morpher float property {:#04x}", + as_unsigned(param)); } +void VmorpherEffectHandler::GetParamfv(ALCcontext *context, const VmorpherProps &props, ALenum param, float *vals) +{ GetParamf(context, props, param, vals); } -} // namespace - -DEFINE_ALEFFECT_VTABLE(Vmorpher); - -const EffectProps VmorpherEffectProps{genDefaultProps()}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { using VocalMorpherCommitter = EaxCommitter; @@ -352,10 +331,9 @@ template<> throw Exception{message}; } -template<> -bool VocalMorpherCommitter::commit(const EaxEffectProps &props) +bool EaxVocalMorpherCommitter::commit(const EAXVOCALMORPHERPROPERTIES &props) { - if(props == mEaxProps) + if(auto *cur = std::get_if(&mEaxProps); cur && *cur == props) return false; mEaxProps = props; @@ -407,19 +385,21 @@ bool VocalMorpherCommitter::commit(const EaxEffectProps &props) return VMorpherWaveform::Sinusoid; }; - auto &eaxprops = std::get(props); - mAlProps.Vmorpher.PhonemeA = get_phoneme(eaxprops.ulPhonemeA); - mAlProps.Vmorpher.PhonemeACoarseTuning = static_cast(eaxprops.lPhonemeACoarseTuning); - mAlProps.Vmorpher.PhonemeB = get_phoneme(eaxprops.ulPhonemeB); - mAlProps.Vmorpher.PhonemeBCoarseTuning = static_cast(eaxprops.lPhonemeBCoarseTuning); - mAlProps.Vmorpher.Waveform = get_waveform(eaxprops.ulWaveform); - mAlProps.Vmorpher.Rate = eaxprops.flRate; + mAlProps = [&]{ + VmorpherProps ret{}; + ret.PhonemeA = get_phoneme(props.ulPhonemeA); + ret.PhonemeACoarseTuning = static_cast(props.lPhonemeACoarseTuning); + ret.PhonemeB = get_phoneme(props.ulPhonemeB); + ret.PhonemeBCoarseTuning = static_cast(props.lPhonemeBCoarseTuning); + ret.Waveform = get_waveform(props.ulWaveform); + ret.Rate = props.flRate; + return ret; + }(); return true; } -template<> -void VocalMorpherCommitter::SetDefaults(EaxEffectProps &props) +void EaxVocalMorpherCommitter::SetDefaults(EaxEffectProps &props) { static constexpr EAXVOCALMORPHERPROPERTIES defprops{[] { @@ -435,87 +415,35 @@ void VocalMorpherCommitter::SetDefaults(EaxEffectProps &props) props = defprops; } -template<> -void VocalMorpherCommitter::Get(const EaxCall &call, const EaxEffectProps &props_) +void EaxVocalMorpherCommitter::Get(const EaxCall &call, const EAXVOCALMORPHERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { - case EAXVOCALMORPHER_NONE: - break; - - case EAXVOCALMORPHER_ALLPARAMETERS: - call.set_value(props); - break; - - case EAXVOCALMORPHER_PHONEMEA: - call.set_value(props.ulPhonemeA); - break; - - case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - call.set_value(props.lPhonemeACoarseTuning); - break; - - case EAXVOCALMORPHER_PHONEMEB: - call.set_value(props.ulPhonemeB); - break; - - case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - call.set_value(props.lPhonemeBCoarseTuning); - break; - - case EAXVOCALMORPHER_WAVEFORM: - call.set_value(props.ulWaveform); - break; - - case EAXVOCALMORPHER_RATE: - call.set_value(props.flRate); - break; - - default: - fail_unknown_property_id(); + case EAXVOCALMORPHER_NONE: break; + case EAXVOCALMORPHER_ALLPARAMETERS: call.set_value(props); break; + case EAXVOCALMORPHER_PHONEMEA: call.set_value(props.ulPhonemeA); break; + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: call.set_value(props.lPhonemeACoarseTuning); break; + case EAXVOCALMORPHER_PHONEMEB: call.set_value(props.ulPhonemeB); break; + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: call.set_value(props.lPhonemeBCoarseTuning); break; + case EAXVOCALMORPHER_WAVEFORM: call.set_value(props.ulWaveform); break; + case EAXVOCALMORPHER_RATE: call.set_value(props.flRate); break; + default: fail_unknown_property_id(); } } -template<> -void VocalMorpherCommitter::Set(const EaxCall &call, EaxEffectProps &props_) +void EaxVocalMorpherCommitter::Set(const EaxCall &call, EAXVOCALMORPHERPROPERTIES &props) { - auto &props = std::get(props_); switch(call.get_property_id()) { - case EAXVOCALMORPHER_NONE: - break; - - case EAXVOCALMORPHER_ALLPARAMETERS: - defer(call, props); - break; - - case EAXVOCALMORPHER_PHONEMEA: - defer(call, props.ulPhonemeA); - break; - - case EAXVOCALMORPHER_PHONEMEACOARSETUNING: - defer(call, props.lPhonemeACoarseTuning); - break; - - case EAXVOCALMORPHER_PHONEMEB: - defer(call, props.ulPhonemeB); - break; - - case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: - defer(call, props.lPhonemeBCoarseTuning); - break; - - case EAXVOCALMORPHER_WAVEFORM: - defer(call, props.ulWaveform); - break; - - case EAXVOCALMORPHER_RATE: - defer(call, props.flRate); - break; - - default: - fail_unknown_property_id(); + case EAXVOCALMORPHER_NONE: break; + case EAXVOCALMORPHER_ALLPARAMETERS: defer(call, props); break; + case EAXVOCALMORPHER_PHONEMEA: defer(call, props.ulPhonemeA); break; + case EAXVOCALMORPHER_PHONEMEACOARSETUNING: defer(call, props.lPhonemeACoarseTuning); break; + case EAXVOCALMORPHER_PHONEMEB: defer(call, props.ulPhonemeB); break; + case EAXVOCALMORPHER_PHONEMEBCOARSETUNING: defer(call, props.lPhonemeBCoarseTuning); break; + case EAXVOCALMORPHER_WAVEFORM: defer(call, props.ulWaveform); break; + case EAXVOCALMORPHER_RATE: defer(call, props.flRate); break; + default: fail_unknown_property_id(); } } diff --git a/3rdparty/openal/al/error.cpp b/3rdparty/openal/al/error.cpp index c23594770b18..4d2015ce2bd6 100644 --- a/3rdparty/openal/al/error.cpp +++ b/3rdparty/openal/al/error.cpp @@ -25,15 +25,14 @@ #include #endif -#include #include #include #include #include #include -#include -#include -#include +#include +#include +#include #include "AL/al.h" #include "AL/alc.h" @@ -41,43 +40,19 @@ #include "al/debug.h" #include "alc/alconfig.h" #include "alc/context.h" -#include "almalloc.h" -#include "alstring.h" +#include "alnumeric.h" #include "core/except.h" #include "core/logging.h" -#include "direct_defs.h" #include "opthelpers.h" #include "strutils.h" -bool TrapALError{false}; - -void ALCcontext::setError(ALenum errorCode, const char *msg, ...) +void ALCcontext::setErrorImpl(ALenum errorCode, const fmt::string_view fmt, fmt::format_args args) { - auto message = std::vector(256); - - va_list args, args2; - va_start(args, msg); - va_copy(args2, args); - int msglen{std::vsnprintf(message.data(), message.size(), msg, args)}; - if(msglen >= 0 && static_cast(msglen) >= message.size()) - { - message.resize(static_cast(msglen) + 1u); - msglen = std::vsnprintf(message.data(), message.size(), msg, args2); - } - va_end(args2); - va_end(args); - - if(msglen >= 0) - msg = message.data(); - else - { - msg = ""; - msglen = static_cast(strlen(msg)); - } + const auto msg = fmt::vformat(fmt, std::move(args)); - WARN("Error generated on context %p, code 0x%04x, \"%s\"\n", - decltype(std::declval()){this}, errorCode, msg); + WARN("Error generated on context {}, code {:#04x}, \"{}\"", + decltype(std::declval()){this}, as_unsigned(errorCode), msg); if(TrapALError) { #ifdef _WIN32 @@ -89,54 +64,66 @@ void ALCcontext::setError(ALenum errorCode, const char *msg, ...) #endif } - ALenum curerr{AL_NO_ERROR}; - mLastError.compare_exchange_strong(curerr, errorCode); + if(mLastThreadError.get() == AL_NO_ERROR) + mLastThreadError.set(errorCode); - debugMessage(DebugSource::API, DebugType::Error, 0, DebugSeverity::High, - {msg, static_cast(msglen)}); + debugMessage(DebugSource::API, DebugType::Error, static_cast(errorCode), + DebugSeverity::High, msg); +} + +void ALCcontext::throw_error_impl(ALenum errorCode, const fmt::string_view fmt, + fmt::format_args args) +{ + setErrorImpl(errorCode, fmt, std::move(args)); + throw al::base_exception{}; } + /* Special-case alGetError since it (potentially) raises a debug signal and * returns a non-default value for a null context. */ -AL_API ALenum AL_APIENTRY alGetError(void) noexcept +AL_API auto AL_APIENTRY alGetError() noexcept -> ALenum { - auto context = GetContextRef(); - if(!context) UNLIKELY + if(auto context = GetContextRef()) LIKELY + return alGetErrorDirect(context.get()); + + auto get_value = [](const char *envname, const char *optname) -> ALenum { - static const ALenum deferror{[](const char *envname, const char *optname) -> ALenum + auto optstr = al::getenv(envname); + if(!optstr) + optstr = ConfigValueStr({}, "game_compat", optname); + if(optstr) { - auto optstr = al::getenv(envname); - if(!optstr) - optstr = ConfigValueStr(nullptr, "game_compat", optname); - - if(optstr) - { - char *end{}; - auto value = std::strtoul(optstr->c_str(), &end, 0); - if(end && *end == '\0' && value <= std::numeric_limits::max()) + try { + auto idx = 0_uz; + auto value = std::stoi(*optstr, &idx, 0); + if(idx >= optstr->size() || std::isspace(optstr->at(idx))) return static_cast(value); - ERR("Invalid default error value: \"%s\"", optstr->c_str()); + } catch(...) { } - return AL_INVALID_OPERATION; - }("__ALSOFT_DEFAULT_ERROR", "default-error")}; + ERR("Invalid default error value: \"{}\"", *optstr); + } + return AL_INVALID_OPERATION; + }; + static const ALenum deferror{get_value("__ALSOFT_DEFAULT_ERROR", "default-error")}; - WARN("Querying error state on null context (implicitly 0x%04x)\n", deferror); - if(TrapALError) - { + WARN("Querying error state on null context (implicitly {:#04x})", as_unsigned(deferror)); + if(TrapALError) + { #ifdef _WIN32 - if(IsDebuggerPresent()) - DebugBreak(); + if(IsDebuggerPresent()) + DebugBreak(); #elif defined(SIGTRAP) - raise(SIGTRAP); + raise(SIGTRAP); #endif - } - return deferror; } - return alGetErrorDirect(context.get()); + return deferror; } FORCE_ALIGN ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) noexcept { - return context->mLastError.exchange(AL_NO_ERROR); + ALenum ret{context->mLastThreadError.get()}; + if(ret != AL_NO_ERROR) UNLIKELY + context->mLastThreadError.set(AL_NO_ERROR); + return ret; } diff --git a/3rdparty/openal/al/event.cpp b/3rdparty/openal/al/event.cpp index 8b76ceffde8f..9a8d50b69bf9 100644 --- a/3rdparty/openal/al/event.cpp +++ b/3rdparty/openal/al/event.cpp @@ -3,32 +3,35 @@ #include "event.h" -#include #include -#include +#include #include #include #include #include #include #include -#include #include -#include +#include +#include #include "AL/al.h" #include "AL/alc.h" +#include "AL/alext.h" #include "alc/context.h" -#include "alc/effects/base.h" -#include "alc/inprogext.h" -#include "almalloc.h" +#include "alnumeric.h" +#include "alsem.h" +#include "alspan.h" +#include "alstring.h" #include "core/async_event.h" +#include "core/context.h" +#include "core/effects/base.h" #include "core/except.h" #include "core/logging.h" -#include "core/voice_change.h" #include "debug.h" #include "direct_defs.h" +#include "intrusive_ptr.h" #include "opthelpers.h" #include "ringbuffer.h" @@ -47,27 +50,22 @@ int EventThread(ALCcontext *context) bool quitnow{false}; while(!quitnow) { - auto evt_data = ring->getReadVector().first; + auto evt_data = ring->getReadVector()[0]; if(evt_data.len == 0) { context->mEventSem.wait(); continue; } - std::lock_guard _{context->mEventCbLock}; - do { - auto *evt_ptr = std::launder(reinterpret_cast(evt_data.buf)); - evt_data.buf += sizeof(AsyncEvent); - evt_data.len -= 1; - - AsyncEvent event{std::move(*evt_ptr)}; - std::destroy_at(evt_ptr); - ring->readAdvance(1); - + auto eventlock = std::lock_guard{context->mEventCbLock}; + const auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire); + auto evt_span = al::span{std::launder(reinterpret_cast(evt_data.buf)), + evt_data.len}; + for(auto &event : evt_span) + { quitnow = std::holds_alternative(event); if(quitnow) UNLIKELY break; - auto enabledevts = context->mEnabledEvts.load(std::memory_order_acquire); auto proc_killthread = [](AsyncKillThread&) { }; auto proc_release = [](AsyncEffectReleaseEvent &evt) { @@ -102,7 +100,7 @@ int EventThread(ALCcontext *context) break; } context->mEventCb(AL_EVENT_TYPE_SOURCE_STATE_CHANGED_SOFT, evt.mId, state, - static_cast(msg.length()), msg.c_str(), context->mEventParam); + al::sizei(msg), msg.c_str(), context->mEventParam); }; auto proc_buffercomp = [context,enabledevts](AsyncBufferCompleteEvent &evt) { @@ -114,25 +112,23 @@ int EventThread(ALCcontext *context) if(evt.mCount == 1) msg += " buffer completed"; else msg += " buffers completed"; context->mEventCb(AL_EVENT_TYPE_BUFFER_COMPLETED_SOFT, evt.mId, evt.mCount, - static_cast(msg.length()), msg.c_str(), context->mEventParam); + al::sizei(msg), msg.c_str(), context->mEventParam); }; auto proc_disconnect = [context,enabledevts](AsyncDisconnectEvent &evt) { - const std::string_view message{evt.msg}; - - context->debugMessage(DebugSource::System, DebugType::Error, 0, - DebugSeverity::High, message); + if(!context->mEventCb + || !enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected))) + return; - if(context->mEventCb - && enabledevts.test(al::to_underlying(AsyncEnableBits::Disconnected))) - context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, - static_cast(message.length()), message.data(), - context->mEventParam); + context->mEventCb(AL_EVENT_TYPE_DISCONNECTED_SOFT, 0, 0, al::sizei(evt.msg), + evt.msg.c_str(), context->mEventParam); }; std::visit(overloaded{proc_srcstate, proc_buffercomp, proc_release, proc_disconnect, proc_killthread}, event); - } while(evt_data.len != 0); + } + std::destroy(evt_span.begin(), evt_span.end()); + ring->readAdvance(evt_span.size()); } return 0; } @@ -157,22 +153,22 @@ void StartEventThrd(ALCcontext *ctx) ctx->mEventThread = std::thread{EventThread, ctx}; } catch(std::exception& e) { - ERR("Failed to start event thread: %s\n", e.what()); + ERR("Failed to start event thread: {}", e.what()); } catch(...) { - ERR("Failed to start event thread! Expect problems.\n"); + ERR("Failed to start event thread! Expect problems."); } } void StopEventThrd(ALCcontext *ctx) { RingBuffer *ring{ctx->mAsyncEvents.get()}; - auto evt_data = ring->getWriteVector().first; + auto evt_data = ring->getWriteVector()[0]; if(evt_data.len == 0) { do { std::this_thread::yield(); - evt_data = ring->getWriteVector().first; + evt_data = ring->getWriteVector()[0]; } while(evt_data.len == 0); } std::ignore = InitAsyncEvent(evt_data.buf); @@ -183,20 +179,24 @@ void StopEventThrd(ALCcontext *ctx) ctx->mEventThread.join(); } -AL_API DECL_FUNCEXT3(void, alEventControl,SOFT, ALsizei, const ALenum*, ALboolean) +AL_API DECL_FUNCEXT3(void, alEventControl,SOFT, ALsizei,count, const ALenum*,types, ALboolean,enable) FORCE_ALIGN void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) noexcept -{ - if(count < 0) context->setError(AL_INVALID_VALUE, "Controlling %d events", count); - if(count <= 0) return; - if(!types) return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + if(count < 0) + context->throw_error(AL_INVALID_VALUE, "Controlling {} events", count); + if(count <= 0) UNLIKELY return; + + if(!types) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); ContextBase::AsyncEventBitset flags{}; for(ALenum evttype : al::span{types, static_cast(count)}) { auto etype = GetEventType(evttype); if(!etype) - return context->setError(AL_INVALID_ENUM, "Invalid event type 0x%04x", evttype); + context->throw_error(AL_INVALID_ENUM, "Invalid event type {:#04x}", + as_unsigned(evttype)); flags.set(al::to_underlying(*etype)); } @@ -221,15 +221,25 @@ FORCE_ALIGN void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsiz /* Wait to ensure the event handler sees the changed flags before * returning. */ - std::lock_guard _{context->mEventCbLock}; + std::lock_guard eventlock{context->mEventCbLock}; } } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNCEXT2(void, alEventCallback,SOFT, ALEVENTPROCSOFT, void*) +AL_API DECL_FUNCEXT2(void, alEventCallback,SOFT, ALEVENTPROCSOFT,callback, void*,userParam) FORCE_ALIGN void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) noexcept -{ - std::lock_guard _{context->mEventCbLock}; +try { + std::lock_guard eventlock{context->mEventCbLock}; context->mEventCb = callback; context->mEventParam = userParam; } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} diff --git a/3rdparty/openal/al/extension.cpp b/3rdparty/openal/al/extension.cpp index 6d1ac3275b61..061addc84625 100644 --- a/3rdparty/openal/al/extension.cpp +++ b/3rdparty/openal/al/extension.cpp @@ -20,21 +20,18 @@ #include "config.h" -#include -#include -#include +#include #include "AL/al.h" #include "AL/alc.h" #include "alc/context.h" #include "alstring.h" -#include "core/except.h" #include "direct_defs.h" #include "opthelpers.h" -AL_API DECL_FUNC1(ALboolean, alIsExtensionPresent, const ALchar*) +AL_API DECL_FUNC1(ALboolean, alIsExtensionPresent, const ALchar*,extName) FORCE_ALIGN ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extName) noexcept { if(!extName) UNLIKELY @@ -43,10 +40,10 @@ FORCE_ALIGN ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context return AL_FALSE; } - size_t len{strlen(extName)}; + const std::string_view tofind{extName}; for(std::string_view ext : context->mExtensions) { - if(len == ext.length() && al::strncasecmp(ext.data(), extName, len) == 0) + if(al::case_compare(ext, tofind) == 0) return AL_TRUE; } @@ -68,12 +65,12 @@ FORCE_ALIGN ALvoid* AL_APIENTRY alGetProcAddressDirect(ALCcontext*, const ALchar AL_API ALenum AL_APIENTRY alGetEnumValue(const ALchar *enumName) noexcept { - if(!enumName) return static_cast(0); + if(!enumName) return ALenum{0}; return alcGetEnumValue(nullptr, enumName); } FORCE_ALIGN ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext*, const ALchar *enumName) noexcept { - if(!enumName) return static_cast(0); + if(!enumName) return ALenum{0}; return alcGetEnumValue(nullptr, enumName); } diff --git a/3rdparty/openal/al/filter.cpp b/3rdparty/openal/al/filter.cpp index f0a078b7a6fa..938ac48cd65f 100644 --- a/3rdparty/openal/al/filter.cpp +++ b/3rdparty/openal/al/filter.cpp @@ -29,8 +29,8 @@ #include #include #include -#include #include +#include #include #include "AL/al.h" @@ -42,36 +42,17 @@ #include "alc/device.h" #include "almalloc.h" #include "alnumeric.h" +#include "alspan.h" #include "core/except.h" +#include "core/logging.h" #include "direct_defs.h" +#include "intrusive_ptr.h" #include "opthelpers.h" namespace { -class filter_exception final : public al::base_exception { - ALenum mErrorCode; - -public: -#ifdef __USE_MINGW_ANSI_STDIO - [[gnu::format(gnu_printf, 3, 4)]] -#else - [[gnu::format(printf, 3, 4)]] -#endif - filter_exception(ALenum code, const char *msg, ...); - ~filter_exception() override; - - ALenum errorCode() const noexcept { return mErrorCode; } -}; - -filter_exception::filter_exception(ALenum code, const char* msg, ...) : mErrorCode{code} -{ - std::va_list args; - va_start(args, msg); - setMessage(msg, args); - va_end(args); -} -filter_exception::~filter_exception() = default; +using SubListAllocator = al::allocator>; void InitFilterParams(ALfilter *filter, ALenum type) @@ -80,43 +61,44 @@ void InitFilterParams(ALfilter *filter, ALenum type) { filter->Gain = AL_LOWPASS_DEFAULT_GAIN; filter->GainHF = AL_LOWPASS_DEFAULT_GAINHF; - filter->HFReference = LOWPASSFREQREF; + filter->HFReference = LowPassFreqRef; filter->GainLF = 1.0f; - filter->LFReference = HIGHPASSFREQREF; + filter->LFReference = HighPassFreqRef; filter->mTypeVariant.emplace(); } else if(type == AL_FILTER_HIGHPASS) { filter->Gain = AL_HIGHPASS_DEFAULT_GAIN; filter->GainHF = 1.0f; - filter->HFReference = LOWPASSFREQREF; + filter->HFReference = LowPassFreqRef; filter->GainLF = AL_HIGHPASS_DEFAULT_GAINLF; - filter->LFReference = HIGHPASSFREQREF; + filter->LFReference = HighPassFreqRef; filter->mTypeVariant.emplace(); } else if(type == AL_FILTER_BANDPASS) { filter->Gain = AL_BANDPASS_DEFAULT_GAIN; filter->GainHF = AL_BANDPASS_DEFAULT_GAINHF; - filter->HFReference = LOWPASSFREQREF; + filter->HFReference = LowPassFreqRef; filter->GainLF = AL_BANDPASS_DEFAULT_GAINLF; - filter->LFReference = HIGHPASSFREQREF; + filter->LFReference = HighPassFreqRef; filter->mTypeVariant.emplace(); } else { filter->Gain = 1.0f; filter->GainHF = 1.0f; - filter->HFReference = LOWPASSFREQREF; + filter->HFReference = LowPassFreqRef; filter->GainLF = 1.0f; - filter->LFReference = HIGHPASSFREQREF; + filter->LFReference = HighPassFreqRef; filter->mTypeVariant.emplace(); } filter->type = type; } -bool EnsureFilters(ALCdevice *device, size_t needed) -{ +[[nodiscard]] +auto EnsureFilters(al::Device *device, size_t needed) noexcept -> bool +try { size_t count{std::accumulate(device->FilterList.cbegin(), device->FilterList.cend(), 0_uz, [](size_t cur, const FilterSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; @@ -126,22 +108,21 @@ bool EnsureFilters(ALCdevice *device, size_t needed) if(device->FilterList.size() >= 1<<25) UNLIKELY return false; - device->FilterList.emplace_back(); - auto sublist = device->FilterList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Filters = static_cast(al_calloc(alignof(ALfilter), sizeof(ALfilter)*64)); - if(!sublist->Filters) UNLIKELY - { - device->FilterList.pop_back(); - return false; - } - count += 64; + FilterSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Filters = SubListAllocator{}.allocate(1); + device->FilterList.emplace_back(std::move(sublist)); + count += std::tuple_size_v; } return true; } +catch(...) { + return false; +} -ALfilter *AllocFilter(ALCdevice *device) +[[nodiscard]] +auto AllocFilter(al::Device *device) noexcept -> ALfilter* { auto sublist = std::find_if(device->FilterList.begin(), device->FilterList.end(), [](const FilterSubList &entry) noexcept -> bool @@ -150,7 +131,7 @@ ALfilter *AllocFilter(ALCdevice *device) auto slidx = static_cast(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALfilter *filter{al::construct_at(sublist->Filters + slidx)}; + ALfilter *filter{al::construct_at(al::to_address(sublist->Filters->begin() + slidx))}; InitFilterParams(filter, AL_FILTER_NULL); /* Add 1 to avoid filter ID 0. */ @@ -161,7 +142,7 @@ ALfilter *AllocFilter(ALCdevice *device) return filter; } -void FreeFilter(ALCdevice *device, ALfilter *filter) +void FreeFilter(al::Device *device, ALfilter *filter) { device->mFilterNames.erase(filter->id); @@ -175,7 +156,8 @@ void FreeFilter(ALCdevice *device, ALfilter *filter) } -inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) +[[nodiscard]] +auto LookupFilter(al::Device *device, ALuint id) noexcept -> ALfilter* { const size_t lidx{(id-1) >> 6}; const ALuint slidx{(id-1) & 0x3f}; @@ -185,427 +167,398 @@ inline ALfilter *LookupFilter(ALCdevice *device, ALuint id) FilterSubList &sublist = device->FilterList[lidx]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Filters + slidx; + return al::to_address(sublist.Filters->begin() + slidx); } } // namespace /* Null filter parameter handlers */ template<> -void FilterTable::setParami(ALfilter*, ALenum param, int) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::setParami(ALCcontext *context, ALfilter*, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamiv(ALfilter*, ALenum param, const int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::setParamiv(ALCcontext *context, ALfilter*, ALenum param, const int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamf(ALfilter*, ALenum param, float) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::setParamf(ALCcontext *context, ALfilter*, ALenum param, float) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamfv(ALfilter*, ALenum param, const float*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::setParamfv(ALCcontext *context, ALfilter*, ALenum param, const float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParami(const ALfilter*, ALenum param, int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamiv(const ALfilter*, ALenum param, int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::getParamiv(ALCcontext *context, const ALfilter*, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamf(const ALfilter*, ALenum param, float*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::getParamf(ALCcontext *context, const ALfilter*, ALenum param, float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamfv(const ALfilter*, ALenum param, float*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid null filter property 0x%04x", param}; } +void FilterTable::getParamfv(ALCcontext *context, const ALfilter*, ALenum param, float*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid null filter property {:#04x}", as_unsigned(param)); } /* Lowpass parameter handlers */ template<> -void FilterTable::setParami(ALfilter*, ALenum param, int) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; } +void FilterTable::setParami(ALCcontext *context, ALfilter*, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid low-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamiv(ALfilter *filter, ALenum param, const int *values) -{ setParami(filter, param, values[0]); } +void FilterTable::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values) +{ setParami(context, filter, param, *values); } template<> -void FilterTable::setParamf(ALfilter *filter, ALenum param, float val) +void FilterTable::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val) { switch(param) { case AL_LOWPASS_GAIN: if(!(val >= AL_LOWPASS_MIN_GAIN && val <= AL_LOWPASS_MAX_GAIN)) - throw filter_exception{AL_INVALID_VALUE, "Low-pass gain %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "Low-pass gain {:f} out of range", val); filter->Gain = val; - break; + return; case AL_LOWPASS_GAINHF: if(!(val >= AL_LOWPASS_MIN_GAINHF && val <= AL_LOWPASS_MAX_GAINHF)) - throw filter_exception{AL_INVALID_VALUE, "Low-pass gainhf %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "Low-pass gainhf {:f} out of range", val); filter->GainHF = val; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param}; + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid low-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::setParamfv(ALfilter *filter, ALenum param, const float *vals) -{ setParamf(filter, param, vals[0]); } +void FilterTable::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals) +{ setParamf(context, filter, param, *vals); } template<> -void FilterTable::getParami(const ALfilter*, ALenum param, int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass integer property 0x%04x", param}; } +void FilterTable::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid low-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamiv(const ALfilter *filter, ALenum param, int *values) -{ getParami(filter, param, values); } +void FilterTable::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values) +{ getParami(context, filter, param, values); } template<> -void FilterTable::getParamf(const ALfilter *filter, ALenum param, float *val) +void FilterTable::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val) { switch(param) { - case AL_LOWPASS_GAIN: - *val = filter->Gain; - break; - - case AL_LOWPASS_GAINHF: - *val = filter->GainHF; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid low-pass float property 0x%04x", param}; + case AL_LOWPASS_GAIN: *val = filter->Gain; return; + case AL_LOWPASS_GAINHF: *val = filter->GainHF; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid low-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::getParamfv(const ALfilter *filter, ALenum param, float *vals) -{ getParamf(filter, param, vals); } +void FilterTable::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals) +{ getParamf(context, filter, param, vals); } /* Highpass parameter handlers */ template<> -void FilterTable::setParami(ALfilter*, ALenum param, int) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; } +void FilterTable::setParami(ALCcontext *context, ALfilter*, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid high-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamiv(ALfilter *filter, ALenum param, const int *values) -{ setParami(filter, param, values[0]); } +void FilterTable::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values) +{ setParami(context, filter, param, *values); } template<> -void FilterTable::setParamf(ALfilter *filter, ALenum param, float val) +void FilterTable::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val) { switch(param) { case AL_HIGHPASS_GAIN: if(!(val >= AL_HIGHPASS_MIN_GAIN && val <= AL_HIGHPASS_MAX_GAIN)) - throw filter_exception{AL_INVALID_VALUE, "High-pass gain %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "High-pass gain {:f} out of range", val); filter->Gain = val; - break; + return; case AL_HIGHPASS_GAINLF: if(!(val >= AL_HIGHPASS_MIN_GAINLF && val <= AL_HIGHPASS_MAX_GAINLF)) - throw filter_exception{AL_INVALID_VALUE, "High-pass gainlf %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "High-pass gainlf {:f} out of range", val); filter->GainLF = val; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param}; + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid high-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::setParamfv(ALfilter *filter, ALenum param, const float *vals) -{ setParamf(filter, param, vals[0]); } +void FilterTable::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals) +{ setParamf(context, filter, param, *vals); } template<> -void FilterTable::getParami(const ALfilter*, ALenum param, int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass integer property 0x%04x", param}; } +void FilterTable::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid high-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamiv(const ALfilter *filter, ALenum param, int *values) -{ getParami(filter, param, values); } +void FilterTable::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values) +{ getParami(context, filter, param, values); } template<> -void FilterTable::getParamf(const ALfilter *filter, ALenum param, float *val) +void FilterTable::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val) { switch(param) { - case AL_HIGHPASS_GAIN: - *val = filter->Gain; - break; - - case AL_HIGHPASS_GAINLF: - *val = filter->GainLF; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid high-pass float property 0x%04x", param}; + case AL_HIGHPASS_GAIN: *val = filter->Gain; return; + case AL_HIGHPASS_GAINLF: *val = filter->GainLF; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid high-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::getParamfv(const ALfilter *filter, ALenum param, float *vals) -{ getParamf(filter, param, vals); } +void FilterTable::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals) +{ getParamf(context, filter, param, vals); } /* Bandpass parameter handlers */ template<> -void FilterTable::setParami(ALfilter*, ALenum param, int) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; } +void FilterTable::setParami(ALCcontext *context, ALfilter*, ALenum param, int) +{ context->throw_error(AL_INVALID_ENUM, "Invalid band-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::setParamiv(ALfilter *filter, ALenum param, const int *values) -{ setParami(filter, param, values[0]); } +void FilterTable::setParamiv(ALCcontext *context, ALfilter *filter, ALenum param, const int *values) +{ setParami(context, filter, param, *values); } template<> -void FilterTable::setParamf(ALfilter *filter, ALenum param, float val) +void FilterTable::setParamf(ALCcontext *context, ALfilter *filter, ALenum param, float val) { switch(param) { case AL_BANDPASS_GAIN: if(!(val >= AL_BANDPASS_MIN_GAIN && val <= AL_BANDPASS_MAX_GAIN)) - throw filter_exception{AL_INVALID_VALUE, "Band-pass gain %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "Band-pass gain {:f} out of range", val); filter->Gain = val; - break; + return; case AL_BANDPASS_GAINHF: if(!(val >= AL_BANDPASS_MIN_GAINHF && val <= AL_BANDPASS_MAX_GAINHF)) - throw filter_exception{AL_INVALID_VALUE, "Band-pass gainhf %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "Band-pass gainhf {:f} out of range", val); filter->GainHF = val; - break; + return; case AL_BANDPASS_GAINLF: if(!(val >= AL_BANDPASS_MIN_GAINLF && val <= AL_BANDPASS_MAX_GAINLF)) - throw filter_exception{AL_INVALID_VALUE, "Band-pass gainlf %f out of range", val}; + context->throw_error(AL_INVALID_VALUE, "Band-pass gainlf {:f} out of range", val); filter->GainLF = val; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param}; + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid band-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::setParamfv(ALfilter *filter, ALenum param, const float *vals) -{ setParamf(filter, param, vals[0]); } +void FilterTable::setParamfv(ALCcontext *context, ALfilter *filter, ALenum param, const float *vals) +{ setParamf(context, filter, param, *vals); } template<> -void FilterTable::getParami(const ALfilter*, ALenum param, int*) -{ throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass integer property 0x%04x", param}; } +void FilterTable::getParami(ALCcontext *context, const ALfilter*, ALenum param, int*) +{ context->throw_error(AL_INVALID_ENUM, "Invalid band-pass integer property {:#04x}", as_unsigned(param)); } template<> -void FilterTable::getParamiv(const ALfilter *filter, ALenum param, int *values) -{ getParami(filter, param, values); } +void FilterTable::getParamiv(ALCcontext *context, const ALfilter *filter, ALenum param, int *values) +{ getParami(context, filter, param, values); } template<> -void FilterTable::getParamf(const ALfilter *filter, ALenum param, float *val) +void FilterTable::getParamf(ALCcontext *context, const ALfilter *filter, ALenum param, float *val) { switch(param) { - case AL_BANDPASS_GAIN: - *val = filter->Gain; - break; - - case AL_BANDPASS_GAINHF: - *val = filter->GainHF; - break; - - case AL_BANDPASS_GAINLF: - *val = filter->GainLF; - break; - - default: - throw filter_exception{AL_INVALID_ENUM, "Invalid band-pass float property 0x%04x", param}; + case AL_BANDPASS_GAIN: *val = filter->Gain; return; + case AL_BANDPASS_GAINHF: *val = filter->GainHF; return; + case AL_BANDPASS_GAINLF: *val = filter->GainLF; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid band-pass float property {:#04x}", + as_unsigned(param)); } template<> -void FilterTable::getParamfv(const ALfilter *filter, ALenum param, float *vals) -{ getParamf(filter, param, vals); } +void FilterTable::getParamfv(ALCcontext *context, const ALfilter *filter, ALenum param, float *vals) +{ getParamf(context, filter, param, vals); } -AL_API DECL_FUNC2(void, alGenFilters, ALsizei, ALuint*) +AL_API DECL_FUNC2(void, alGenFilters, ALsizei,n, ALuint*,filters) FORCE_ALIGN void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Generating %d filters", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Generating {} filters", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; - if(!EnsureFilters(device, static_cast(n))) - { - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d filter%s", n, (n==1)?"":"s"); - return; - } + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; - if(n == 1) LIKELY - { - /* Special handling for the easy and normal case. */ - ALfilter *filter{AllocFilter(device)}; - if(filter) filters[0] = filter->id; - } - else - { - /* Store the allocated buffer IDs in a separate local list, to avoid - * modifying the user storage in case of failure. - */ - std::vector ids; - ids.reserve(static_cast(n)); - do { - ALfilter *filter{AllocFilter(device)}; - ids.emplace_back(filter->id); - } while(--n); - std::copy(ids.begin(), ids.end(), filters); - } + const al::span fids{filters, static_cast(n)}; + if(!EnsureFilters(device, fids.size())) + context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} filter{}", n, + (n==1) ? "" : "s"); + + std::generate(fids.begin(), fids.end(), [device]{ return AllocFilter(device)->id; }); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alDeleteFilters, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alDeleteFilters, ALsizei,n, const ALuint*,filters) FORCE_ALIGN void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Deleting %d filters", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Deleting {} filters", n); if(n <= 0) UNLIKELY return; - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; /* First try to find any filters that are invalid. */ auto validate_filter = [device](const ALuint fid) -> bool { return !fid || LookupFilter(device, fid) != nullptr; }; - const ALuint *filters_end = filters + n; - auto invflt = std::find_if_not(filters, filters_end, validate_filter); - if(invflt != filters_end) UNLIKELY - { - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", *invflt); - return; - } + const al::span fids{filters, static_cast(n)}; + auto invflt = std::find_if_not(fids.begin(), fids.end(), validate_filter); + if(invflt != fids.end()) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", *invflt); /* All good. Delete non-0 filter IDs. */ auto delete_filter = [device](const ALuint fid) -> void { - ALfilter *filter{fid ? LookupFilter(device, fid) : nullptr}; - if(filter) FreeFilter(device, filter); + if(ALfilter *filter{fid ? LookupFilter(device, fid) : nullptr}) + FreeFilter(device, filter); }; - std::for_each(filters, filters_end, delete_filter); + std::for_each(fids.begin(), fids.end(), delete_filter); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC1(ALboolean, alIsFilter, ALuint) +AL_API DECL_FUNC1(ALboolean, alIsFilter, ALuint,filter) FORCE_ALIGN ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) noexcept { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; if(!filter || LookupFilter(device, filter)) return AL_TRUE; return AL_FALSE; } -AL_API DECL_FUNC3(void, alFilteri, ALuint, ALenum, ALint) +AL_API DECL_FUNC3(void, alFilteri, ALuint,filter, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else if(param == AL_FILTER_TYPE) - { - if(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS - || value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS) - InitFilterParams(alfilt, value); - else - context->setError(AL_INVALID_VALUE, "Invalid filter type 0x%04x", value); - } - else try + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + switch(param) { - /* Call the appropriate handler */ - std::visit([alfilt,param,value](auto&& thunk){thunk.setParami(alfilt, param, value);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); + case AL_FILTER_TYPE: + if(!(value == AL_FILTER_NULL || value == AL_FILTER_LOWPASS + || value == AL_FILTER_HIGHPASS || value == AL_FILTER_BANDPASS)) + context->throw_error(AL_INVALID_VALUE, "Invalid filter type {:#04x}", + as_unsigned(value)); + InitFilterParams(alfilt, value); + return; } + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,value](auto&& thunk) + { thunk.setParami(context, alfilt, param, value); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alFilteriv, ALuint, ALenum, const ALint*) +AL_API DECL_FUNC3(void, alFilteriv, ALuint,filter, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) noexcept -{ +try { switch(param) { case AL_FILTER_TYPE: - alFilteriDirect(context, filter, param, values[0]); + alFilteriDirect(context, filter, param, *values); return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,values](auto&& thunk){thunk.setParamiv(alfilt, param, values);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,values](auto&& thunk) + { thunk.setParamiv(context, alfilt, param, values); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alFilterf, ALuint, ALenum, ALfloat) +AL_API DECL_FUNC3(void, alFilterf, ALuint,filter, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,value](auto&& thunk){thunk.setParamf(alfilt, param, value);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,value](auto&& thunk) + { thunk.setParamf(context, alfilt, param, value); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alFilterfv, ALuint, ALenum, const ALfloat*) +AL_API DECL_FUNC3(void, alFilterfv, ALuint,filter, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,values](auto&& thunk){thunk.setParamfv(alfilt, param, values);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,values](auto&& thunk) + { thunk.setParamfv(context, alfilt, param, values); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetFilteri, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetFilteri, ALuint,filter, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; const ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else if(param == AL_FILTER_TYPE) - *value = alfilt->type; - else try + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + switch(param) { - /* Call the appropriate handler */ - std::visit([alfilt,param,value](auto&& thunk){thunk.getParami(alfilt, param, value);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); + case AL_FILTER_TYPE: *value = alfilt->type; return; } + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,value](auto&& thunk) + { thunk.getParami(context, alfilt, param, value); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetFilteriv, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetFilteriv, ALuint,filter, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *values) noexcept -{ +try { switch(param) { case AL_FILTER_TYPE: @@ -613,74 +566,74 @@ FORCE_ALIGN void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint fil return; } - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; const ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,values](auto&& thunk){thunk.getParamiv(alfilt, param, values);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,values](auto&& thunk) + { thunk.getParamiv(context, alfilt, param, values); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetFilterf, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetFilterf, ALuint,filter, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; const ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,value](auto&& thunk){thunk.getParamf(alfilt, param, value);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,value](auto&& thunk) + { thunk.getParamf(context, alfilt, param, value); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetFilterfv, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetFilterfv, ALuint,filter, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) noexcept -{ - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; +try { + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; const ALfilter *alfilt{LookupFilter(device, filter)}; - if(!alfilt) UNLIKELY - context->setError(AL_INVALID_NAME, "Invalid filter ID %u", filter); - else try - { - /* Call the appropriate handler */ - std::visit([alfilt,param,values](auto&& thunk){thunk.getParamfv(alfilt, param, values);}, - alfilt->mTypeVariant); - } - catch(filter_exception &e) { - context->setError(e.errorCode(), "%s", e.what()); - } + if(!alfilt) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", filter); + + /* Call the appropriate handler */ + std::visit([context,alfilt,param,values](auto&& thunk) + { thunk.getParamfv(context, alfilt, param, values); }, alfilt->mTypeVariant); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } void ALfilter::SetName(ALCcontext *context, ALuint id, std::string_view name) { - ALCdevice *device{context->mALDevice.get()}; - std::lock_guard _{device->FilterLock}; + auto *device = context->mALDevice.get(); + auto filterlock = std::lock_guard{device->FilterLock}; auto filter = LookupFilter(device, id); - if(!filter) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid filter ID %u", id); + if(!filter) + context->throw_error(AL_INVALID_NAME, "Invalid filter ID {}", id); device->mFilterNames.insert_or_assign(id, name); } @@ -695,10 +648,10 @@ FilterSubList::~FilterSubList() while(usemask) { const int idx{al::countr_zero(usemask)}; - std::destroy_at(Filters+idx); + std::destroy_at(al::to_address(Filters->begin() + idx)); usemask &= ~(1_u64 << idx); } FreeMask = ~usemask; - al_free(Filters); + SubListAllocator{}.deallocate(Filters, 1); Filters = nullptr; } diff --git a/3rdparty/openal/al/filter.h b/3rdparty/openal/al/filter.h index 505900d46597..70b78ca83227 100644 --- a/3rdparty/openal/al/filter.h +++ b/3rdparty/openal/al/filter.h @@ -1,30 +1,40 @@ #ifndef AL_FILTER_H #define AL_FILTER_H +#include +#include #include +#include #include #include "AL/al.h" #include "AL/alc.h" -#include "AL/alext.h" +#include "AL/efx.h" #include "almalloc.h" +#include "alnumeric.h" -#define LOWPASSFREQREF 5000.0f -#define HIGHPASSFREQREF 250.0f +struct ALfilter; +inline constexpr float LowPassFreqRef{5000.0f}; +inline constexpr float HighPassFreqRef{250.0f}; + template struct FilterTable { - static void setParami(struct ALfilter*, ALenum, int); - static void setParamiv(struct ALfilter*, ALenum, const int*); - static void setParamf(struct ALfilter*, ALenum, float); - static void setParamfv(struct ALfilter*, ALenum, const float*); - - static void getParami(const struct ALfilter*, ALenum, int*); - static void getParamiv(const struct ALfilter*, ALenum, int*); - static void getParamf(const struct ALfilter*, ALenum, float*); - static void getParamfv(const struct ALfilter*, ALenum, float*); + static void setParami(ALCcontext*, ALfilter*, ALenum, int); + static void setParamiv(ALCcontext*, ALfilter*, ALenum, const int*); + static void setParamf(ALCcontext*, ALfilter*, ALenum, float); + static void setParamfv(ALCcontext*, ALfilter*, ALenum, const float*); + + static void getParami(ALCcontext*, const ALfilter*, ALenum, int*); + static void getParamiv(ALCcontext*, const ALfilter*, ALenum, int*); + static void getParamf(ALCcontext*, const ALfilter*, ALenum, float*); + static void getParamfv(ALCcontext*, const ALfilter*, ALenum, float*); + +private: + FilterTable() = default; + friend T; }; struct NullFilterTable : public FilterTable { }; @@ -38,9 +48,9 @@ struct ALfilter { float Gain{1.0f}; float GainHF{1.0f}; - float HFReference{LOWPASSFREQREF}; + float HFReference{LowPassFreqRef}; float GainLF{1.0f}; - float LFReference{HIGHPASSFREQREF}; + float LFReference{HighPassFreqRef}; using TableTypes = std::variant; @@ -51,7 +61,22 @@ struct ALfilter { static void SetName(ALCcontext *context, ALuint id, std::string_view name); - DISABLE_ALLOC() + DISABLE_ALLOC +}; + +struct FilterSubList { + uint64_t FreeMask{~0_u64}; + gsl::owner*> Filters{nullptr}; + + FilterSubList() noexcept = default; + FilterSubList(const FilterSubList&) = delete; + FilterSubList(FilterSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Filters{rhs.Filters} + { rhs.FreeMask = ~0_u64; rhs.Filters = nullptr; } + ~FilterSubList(); + + FilterSubList& operator=(const FilterSubList&) = delete; + FilterSubList& operator=(FilterSubList&& rhs) noexcept + { std::swap(FreeMask, rhs.FreeMask); std::swap(Filters, rhs.Filters); return *this; } }; #endif diff --git a/3rdparty/openal/al/listener.cpp b/3rdparty/openal/al/listener.cpp index ea2ebb3f7e81..9addee0cd15d 100644 --- a/3rdparty/openal/al/listener.cpp +++ b/3rdparty/openal/al/listener.cpp @@ -22,6 +22,7 @@ #include "listener.h" +#include #include #include @@ -30,11 +31,11 @@ #include "AL/efx.h" #include "alc/context.h" -#include "almalloc.h" -#include "atomic.h" +#include "alnumeric.h" +#include "alspan.h" #include "core/except.h" +#include "core/logging.h" #include "direct_defs.h" -#include "opthelpers.h" namespace { @@ -53,7 +54,7 @@ inline void CommitAndUpdateProps(ALCcontext *context) { if(!context->mDeferUpdates) { -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(context->eaxNeedsCommit()) { context->mPropsDirty = true; @@ -69,122 +70,134 @@ inline void CommitAndUpdateProps(ALCcontext *context) } // namespace -AL_API DECL_FUNC2(void, alListenerf, ALenum, ALfloat) +AL_API DECL_FUNC2(void, alListenerf, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) noexcept -{ +try { ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; switch(param) { case AL_GAIN: if(!(value >= 0.0f && std::isfinite(value))) - return context->setError(AL_INVALID_VALUE, "Listener gain out of range"); + context->throw_error(AL_INVALID_VALUE, "Listener gain {:f} out of range", value); listener.Gain = value; UpdateProps(context); - break; + return; case AL_METERS_PER_UNIT: if(!(value >= AL_MIN_METERS_PER_UNIT && value <= AL_MAX_METERS_PER_UNIT)) - return context->setError(AL_INVALID_VALUE, "Listener meters per unit out of range"); + context->throw_error(AL_INVALID_VALUE, "Listener meters per unit {:f} out of range", + value); listener.mMetersPerUnit = value; UpdateProps(context); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener float property"); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC4(void, alListener3f, ALenum, ALfloat, ALfloat, ALfloat) +AL_API DECL_FUNC4(void, alListener3f, ALenum,param, ALfloat,value1, ALfloat,value2, ALfloat,value3) FORCE_ALIGN void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept -{ +try { ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; switch(param) { case AL_POSITION: if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3))) - return context->setError(AL_INVALID_VALUE, "Listener position out of range"); + context->throw_error(AL_INVALID_VALUE, "Listener position out of range"); listener.Position[0] = value1; listener.Position[1] = value2; listener.Position[2] = value3; CommitAndUpdateProps(context); - break; + return; case AL_VELOCITY: if(!(std::isfinite(value1) && std::isfinite(value2) && std::isfinite(value3))) - return context->setError(AL_INVALID_VALUE, "Listener velocity out of range"); + context->throw_error(AL_INVALID_VALUE, "Listener velocity out of range"); listener.Velocity[0] = value1; listener.Velocity[1] = value2; listener.Velocity[2] = value3; CommitAndUpdateProps(context); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property"); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alListenerfv, ALenum, const ALfloat*) +AL_API DECL_FUNC2(void, alListenerfv, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) noexcept -{ - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); switch(param) { case AL_GAIN: case AL_METERS_PER_UNIT: - alListenerfDirect(context, param, values[0]); + alListenerfDirect(context, param, *values); return; case AL_POSITION: case AL_VELOCITY: - alListener3fDirect(context, param, values[0], values[1], values[2]); + auto vals = al::span{values, 3_uz}; + alListener3fDirect(context, param, vals[0], vals[1], vals[2]); return; } ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; switch(param) { case AL_ORIENTATION: - if(!(std::isfinite(values[0]) && std::isfinite(values[1]) && std::isfinite(values[2]) && - std::isfinite(values[3]) && std::isfinite(values[4]) && std::isfinite(values[5]))) - return context->setError(AL_INVALID_VALUE, "Listener orientation out of range"); + auto vals = al::span{values, 6_uz}; + if(!std::all_of(vals.cbegin(), vals.cend(), [](float f) { return std::isfinite(f); })) + context->throw_error(AL_INVALID_VALUE, "Listener orientation out of range"); /* AT then UP */ - listener.OrientAt[0] = values[0]; - listener.OrientAt[1] = values[1]; - listener.OrientAt[2] = values[2]; - listener.OrientUp[0] = values[3]; - listener.OrientUp[1] = values[4]; - listener.OrientUp[2] = values[5]; + std::copy_n(vals.cbegin(), 3, listener.OrientAt.begin()); + std::copy_n(vals.cbegin()+3, 3, listener.OrientUp.begin()); CommitAndUpdateProps(context); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property"); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alListeneri, ALenum, ALint) +AL_API DECL_FUNC2(void, alListeneri, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint /*value*/) noexcept -{ - std::lock_guard _{context->mPropLock}; - switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid listener integer property"); - } +try { + std::lock_guard proplock{context->mPropLock}; + context->throw_error(AL_INVALID_ENUM, "Invalid listener integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC4(void, alListener3i, ALenum, ALint, ALint, ALint) +AL_API DECL_FUNC4(void, alListener3i, ALenum,param, ALint,value1, ALint,value2, ALint,value3) FORCE_ALIGN void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) noexcept -{ +try { switch(param) { case AL_POSITION: @@ -194,105 +207,116 @@ FORCE_ALIGN void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum para return; } - std::lock_guard _{context->mPropLock}; - switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property"); - } + std::lock_guard proplock{context->mPropLock}; + context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alListeneriv, ALenum, const ALint*) +AL_API DECL_FUNC2(void, alListeneriv, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) noexcept -{ - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + al::span vals; switch(param) { case AL_POSITION: case AL_VELOCITY: - alListener3fDirect(context, param, static_cast(values[0]), - static_cast(values[1]), static_cast(values[2])); + vals = {values, 3_uz}; + alListener3fDirect(context, param, static_cast(vals[0]), + static_cast(vals[1]), static_cast(vals[2])); return; case AL_ORIENTATION: - const ALfloat fvals[6]{ - static_cast(values[0]), - static_cast(values[1]), - static_cast(values[2]), - static_cast(values[3]), - static_cast(values[4]), - static_cast(values[5]), + vals = {values, 6_uz}; + const std::array fvals{static_cast(vals[0]), static_cast(vals[1]), + static_cast(vals[2]), static_cast(vals[3]), + static_cast(vals[4]), static_cast(vals[5]), }; - alListenerfvDirect(context, param, fvals); + alListenerfvDirect(context, param, fvals.data()); return; } - std::lock_guard _{context->mPropLock}; - switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property"); - } + std::lock_guard proplock{context->mPropLock}; + context->throw_error(AL_INVALID_ENUM, "Invalid listener integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alGetListenerf, ALenum, ALfloat*) +AL_API DECL_FUNC2(void, alGetListenerf, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) noexcept -{ - ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; +try { if(!value) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - case AL_GAIN: - *value = listener.Gain; - break; + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - case AL_METERS_PER_UNIT: - *value = listener.mMetersPerUnit; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener float property"); + ALlistener &listener = context->mListener; + std::lock_guard proplock{context->mPropLock}; + switch(param) + { + case AL_GAIN: *value = listener.Gain; return; + case AL_METERS_PER_UNIT: *value = listener.mMetersPerUnit; return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC4(void, alGetListener3f, ALenum, ALfloat*, ALfloat*, ALfloat*) +AL_API DECL_FUNC4(void, alGetListener3f, ALenum,param, ALfloat*,value1, ALfloat*,value2, ALfloat*,value3) FORCE_ALIGN void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept -{ - ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; +try { if(!value1 || !value2 || !value3) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + ALlistener &listener = context->mListener; + std::lock_guard proplock{context->mPropLock}; + switch(param) { case AL_POSITION: *value1 = listener.Position[0]; *value2 = listener.Position[1]; *value3 = listener.Position[2]; - break; + return; case AL_VELOCITY: *value1 = listener.Velocity[0]; *value2 = listener.Velocity[1]; *value3 = listener.Velocity[2]; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener 3-float property"); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-float property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alGetListenerfv, ALenum, ALfloat*) +AL_API DECL_FUNC2(void, alGetListenerfv, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) noexcept -{ +try { + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + switch(param) { case AL_GAIN: @@ -302,101 +326,112 @@ FORCE_ALIGN void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum p case AL_POSITION: case AL_VELOCITY: - alGetListener3fDirect(context, param, values+0, values+1, values+2); + auto vals = al::span{values, 3_uz}; + alGetListener3fDirect(context, param, &vals[0], &vals[1], &vals[2]); return; } ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) + std::lock_guard proplock{context->mPropLock}; + switch(param) { case AL_ORIENTATION: + al::span vals{values, 6_uz}; // AT then UP - values[0] = listener.OrientAt[0]; - values[1] = listener.OrientAt[1]; - values[2] = listener.OrientAt[2]; - values[3] = listener.OrientUp[0]; - values[4] = listener.OrientUp[1]; - values[5] = listener.OrientUp[2]; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener float-vector property"); + std::copy_n(listener.OrientAt.cbegin(), 3, vals.begin()); + std::copy_n(listener.OrientUp.cbegin(), 3, vals.begin()+3); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener float-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alGetListeneri, ALenum, ALint*) +AL_API DECL_FUNC2(void, alGetListeneri, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) noexcept -{ - std::lock_guard _{context->mPropLock}; - if(!value) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) - { - default: - context->setError(AL_INVALID_ENUM, "Invalid listener integer property"); - } +try { + if(!value) context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + std::lock_guard proplock{context->mPropLock}; + context->throw_error(AL_INVALID_ENUM, "Invalid listener integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC4(void, alGetListener3i, ALenum, ALint*, ALint*, ALint*) +AL_API DECL_FUNC4(void, alGetListener3i, ALenum,param, ALint*,value1, ALint*,value2, ALint*,value3) FORCE_ALIGN void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept -{ - ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; +try { if(!value1 || !value2 || !value3) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + ALlistener &listener = context->mListener; + std::lock_guard proplock{context->mPropLock}; + switch(param) { case AL_POSITION: *value1 = static_cast(listener.Position[0]); *value2 = static_cast(listener.Position[1]); *value3 = static_cast(listener.Position[2]); - break; + return; case AL_VELOCITY: *value1 = static_cast(listener.Velocity[0]); *value2 = static_cast(listener.Velocity[1]); *value3 = static_cast(listener.Velocity[2]); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener 3-integer property"); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener 3-integer property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alGetListeneriv, ALenum, ALint*) +AL_API DECL_FUNC2(void, alGetListeneriv, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) noexcept -{ +try { + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + switch(param) { case AL_POSITION: case AL_VELOCITY: - alGetListener3iDirect(context, param, values+0, values+1, values+2); + auto vals = al::span{values, 3_uz}; + alGetListener3iDirect(context, param, &vals[0], &vals[1], &vals[2]); return; } ALlistener &listener = context->mListener; - std::lock_guard _{context->mPropLock}; - if(!values) - context->setError(AL_INVALID_VALUE, "NULL pointer"); - else switch(param) + std::lock_guard proplock{context->mPropLock}; + + static constexpr auto f2i = [](const float val) noexcept { return static_cast(val); }; + switch(param) { case AL_ORIENTATION: + auto vals = al::span{values, 6_uz}; // AT then UP - values[0] = static_cast(listener.OrientAt[0]); - values[1] = static_cast(listener.OrientAt[1]); - values[2] = static_cast(listener.OrientAt[2]); - values[3] = static_cast(listener.OrientUp[0]); - values[4] = static_cast(listener.OrientUp[1]); - values[5] = static_cast(listener.OrientUp[2]); - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid listener integer-vector property"); + std::transform(listener.OrientAt.cbegin(), listener.OrientAt.cend(), vals.begin(), f2i); + std::transform(listener.OrientUp.cbegin(), listener.OrientUp.cend(), vals.begin()+3, f2i); + return; } + context->throw_error(AL_INVALID_ENUM, "Invalid listener integer-vector property {:#04x}", + as_unsigned(param)); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } diff --git a/3rdparty/openal/al/listener.h b/3rdparty/openal/al/listener.h index 8153287715e9..7a4ff530f72e 100644 --- a/3rdparty/openal/al/listener.h +++ b/3rdparty/openal/al/listener.h @@ -3,8 +3,6 @@ #include -#include "AL/al.h" -#include "AL/alc.h" #include "AL/efx.h" #include "almalloc.h" @@ -18,7 +16,7 @@ struct ALlistener { float Gain{1.0f}; float mMetersPerUnit{AL_DEFAULT_METERS_PER_UNIT}; - DISABLE_ALLOC() + DISABLE_ALLOC }; #endif diff --git a/3rdparty/openal/al/source.cpp b/3rdparty/openal/al/source.cpp index 2fbd1703aeec..77f8bfac60df 100644 --- a/3rdparty/openal/al/source.cpp +++ b/3rdparty/openal/al/source.cpp @@ -25,22 +25,25 @@ #include #include #include +#include #include #include -#include -#include #include #include -#include +#include #include +#include #include #include #include -#include #include #include #include -#include +#include +#include +#include +#include +#include #include #include @@ -50,7 +53,6 @@ #include "AL/efx.h" #include "albit.h" -#include "alc/alu.h" #include "alc/backends/base.h" #include "alc/context.h" #include "alc/device.h" @@ -61,30 +63,35 @@ #include "atomic.h" #include "auxeffectslot.h" #include "buffer.h" -#include "core/ambidefs.h" -#include "core/bformatdec.h" +#include "core/buffer_storage.h" #include "core/except.h" -#include "core/filters/nfc.h" -#include "core/filters/splitter.h" #include "core/logging.h" +#include "core/mixer/defs.h" #include "core/voice_change.h" #include "direct_defs.h" -#include "event.h" #include "filter.h" +#include "flexarray.h" +#include "intrusive_ptr.h" #include "opthelpers.h" -#include "ringbuffer.h" -#ifdef ALSOFT_EAX -#include -#endif // ALSOFT_EAX - -bool sBufferSubDataCompat{false}; +#if ALSOFT_EAX +#include "eax/api.h" +#include "eax/call.h" +#include "eax/fx_slot_index.h" +#include "eax/utils.h" +#endif namespace { -using namespace std::placeholders; +using SubListAllocator = al::allocator>; using std::chrono::nanoseconds; using seconds_d = std::chrono::duration; +using source_store_array = std::array; +using source_store_vector = std::vector; +using source_store_variant = std::variant; + +using namespace std::string_view_literals; + Voice *GetSourceVoice(ALsource *source, ALCcontext *context) { @@ -97,7 +104,7 @@ Voice *GetSourceVoice(ALsource *source, ALCcontext *context) if(voice->mSourceID.load(std::memory_order_acquire) == sid) return voice; } - source->VoiceIdx = INVALID_VOICE_IDX; + source->VoiceIdx = InvalidVoiceIndex; return nullptr; } @@ -127,7 +134,7 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context props->RefDistance = source->RefDistance; props->MaxDistance = source->MaxDistance; props->RolloffFactor = source->RolloffFactor -#ifdef ALSOFT_EAX +#if ALSOFT_EAX + source->RolloffFactor2 #endif ; @@ -155,6 +162,7 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context props->Radius = source->Radius; props->EnhWidth = source->EnhWidth; + props->Panning = source->mPanningEnabled ? source->mPan : 0.0f; props->Direct.Gain = source->Direct.Gain; props->Direct.GainHF = source->Direct.GainHF; @@ -173,7 +181,7 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context ret.LFReference = srcsend.LFReference; return ret; }; - std::transform(source->Send.cbegin(), source->Send.cend(), props->Send, copy_send); + std::transform(source->Send.cbegin(), source->Send.cend(), props->Send.begin(), copy_send); if(!props->Send[0].Slot && context->mDefaultSlot) props->Send[0].Slot = context->mDefaultSlot->mSlot; @@ -196,7 +204,7 @@ void UpdateSourceProps(const ALsource *source, Voice *voice, ALCcontext *context */ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds *clocktime) { - ALCdevice *device{context->mALDevice.get()}; + auto *device = context->mALDevice.get(); const VoiceBufferItem *Current{}; int64_t readPos{}; uint refcount{}; @@ -204,7 +212,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds do { refcount = device->waitForMix(); - *clocktime = GetDeviceClockTime(device); + *clocktime = device->getClockTime(); voice = GetSourceVoice(Source, context); if(voice) { @@ -214,7 +222,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0; @@ -236,7 +244,7 @@ int64_t GetSourceSampleOffset(ALsource *Source, ALCcontext *context, nanoseconds */ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *clocktime) { - ALCdevice *device{context->mALDevice.get()}; + auto *device = context->mALDevice.get(); const VoiceBufferItem *Current{}; int64_t readPos{}; uint refcount{}; @@ -244,7 +252,7 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl do { refcount = device->waitForMix(); - *clocktime = GetDeviceClockTime(device); + *clocktime = device->getClockTime(); voice = GetSourceVoice(Source, context); if(voice) { @@ -254,7 +262,7 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl readPos += voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return 0.0f; @@ -284,9 +292,9 @@ double GetSourceSecOffset(ALsource *Source, ALCcontext *context, nanoseconds *cl * queue (not the start of the current buffer). */ template -T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) +NOINLINE T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) { - ALCdevice *device{context->mALDevice.get()}; + auto *device = context->mALDevice.get(); const VoiceBufferItem *Current{}; int64_t readPos{}; uint readPosFrac{}; @@ -304,7 +312,7 @@ T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) readPosFrac = voice->mPositionFrac.load(std::memory_order_relaxed); } std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != device->MixCount.load(std::memory_order_relaxed)); + } while(refcount != device->mMixCount.load(std::memory_order_relaxed)); if(!voice) return T{0}; @@ -324,51 +332,45 @@ T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) } ASSUME(BufferFmt != nullptr); - T offset{}; switch(name) { case AL_SEC_OFFSET: if constexpr(std::is_floating_point_v) { - offset = static_cast(readPos) + static_cast(readPosFrac)/T{MixerFracOne}; - offset /= static_cast(BufferFmt->mSampleRate); + auto offset = static_cast(readPos) + static_cast(readPosFrac)/T{MixerFracOne}; + return offset / static_cast(BufferFmt->mSampleRate); } else { readPos /= BufferFmt->mSampleRate; - offset = static_cast(clampi64(readPos, std::numeric_limits::min(), + return static_cast(std::clamp(readPos, std::numeric_limits::min(), std::numeric_limits::max())); } - break; case AL_SAMPLE_OFFSET: if constexpr(std::is_floating_point_v) - offset = static_cast(readPos) + static_cast(readPosFrac)/T{MixerFracOne}; + return static_cast(readPos) + static_cast(readPosFrac)/T{MixerFracOne}; else - offset = static_cast(clampi64(readPos, std::numeric_limits::min(), + return static_cast(std::clamp(readPos, std::numeric_limits::min(), std::numeric_limits::max())); - break; case AL_BYTE_OFFSET: - const ALuint BlockSamples{BufferFmt->mBlockAlign}; - const ALuint BlockSize{BufferFmt->blockSizeFromFmt()}; /* Round down to the block boundary. */ - readPos = readPos / BlockSamples * BlockSize; + const auto BlockSize = ALuint{BufferFmt->blockSizeFromFmt()}; + readPos = readPos / BufferFmt->mBlockAlign * BlockSize; if constexpr(std::is_floating_point_v) - offset = static_cast(readPos); + return static_cast(readPos); else { if(readPos > std::numeric_limits::max()) - offset = RoundDown(std::numeric_limits::max(), static_cast(BlockSize)); - else if(readPos < std::numeric_limits::min()) - offset = RoundUp(std::numeric_limits::min(), static_cast(BlockSize)); - else - offset = static_cast(readPos); + return RoundDown(std::numeric_limits::max(), static_cast(BlockSize)); + if(readPos < std::numeric_limits::min()) + return RoundUp(std::numeric_limits::min(), static_cast(BlockSize)); + return static_cast(readPos); } - break; } - return offset; + return T{0}; } /* GetSourceLength @@ -377,7 +379,7 @@ T GetSourceOffset(ALsource *Source, ALenum name, ALCcontext *context) * format (Bytes, Samples or Seconds). */ template -T GetSourceLength(const ALsource *source, ALenum name) +NOINLINE T GetSourceLength(const ALsource *source, ALenum name) { uint64_t length{0}; const ALbuffer *BufferFmt{nullptr}; @@ -387,36 +389,34 @@ T GetSourceLength(const ALsource *source, ALenum name) BufferFmt = listitem.mBuffer; length += listitem.mSampleLen; } - if(length == 0) + if(length == 0 || !BufferFmt) return T{0}; - ASSUME(BufferFmt != nullptr); switch(name) { case AL_SEC_LENGTH_SOFT: if constexpr(std::is_floating_point_v) return static_cast(length) / static_cast(BufferFmt->mSampleRate); else - return static_cast(minu64(length/BufferFmt->mSampleRate, + return static_cast(std::min(length/BufferFmt->mSampleRate, std::numeric_limits::max())); case AL_SAMPLE_LENGTH_SOFT: if constexpr(std::is_floating_point_v) return static_cast(length); else - return static_cast(minu64(length, std::numeric_limits::max())); + return static_cast(std::min(length, std::numeric_limits::max())); case AL_BYTE_LENGTH_SOFT: - const ALuint BlockSamples{BufferFmt->mBlockAlign}; - const ALuint BlockSize{BufferFmt->blockSizeFromFmt()}; /* Round down to the block boundary. */ - length = length / BlockSamples * BlockSize; + const auto BlockSize = ALuint{BufferFmt->blockSizeFromFmt()}; + length = length / BufferFmt->mBlockAlign * BlockSize; if constexpr(std::is_floating_point_v) return static_cast(length); else { - if(length > std::numeric_limits::max()) + if(length > uint64_t{std::numeric_limits::max()}) return RoundDown(std::numeric_limits::max(), static_cast(BlockSize)); return static_cast(length); } @@ -438,7 +438,7 @@ struct VoicePos { * using the given offset type and offset. If the offset is out of range, * returns an empty optional. */ -std::optional GetSampleOffset(al::deque &BufferList, +std::optional GetSampleOffset(std::deque &BufferList, ALenum OffsetType, double Offset) { /* Find the first valid Buffer in the Queue */ @@ -452,44 +452,43 @@ std::optional GetSampleOffset(al::deque &BufferList return std::nullopt; /* Get sample frame offset */ - int64_t offset{}; - uint frac{}; - double dbloff, dblfrac; - switch(OffsetType) + auto [offset, frac] = std::invoke([OffsetType,Offset,BufferFmt]() -> std::pair { - case AL_SEC_OFFSET: - dblfrac = std::modf(Offset*BufferFmt->mSampleRate, &dbloff); - if(dblfrac < 0.0) + auto dbloff = double{}; + auto dblfrac = double{}; + switch(OffsetType) { - /* If there's a negative fraction, reduce the offset to "floor" it, - * and convert the fraction to a percentage to the next value (e.g. - * -2.75 -> -3 + 0.25). - */ - dbloff -= 1.0; - dblfrac += 1.0; - } - offset = static_cast(dbloff); - frac = static_cast(mind(dblfrac*MixerFracOne, MixerFracOne-1.0)); - break; + case AL_SEC_OFFSET: + dblfrac = std::modf(Offset*BufferFmt->mSampleRate, &dbloff); + if(dblfrac < 0.0) + { + /* If there's a negative fraction, reduce the offset to "floor" + * it, and convert the fraction to a percentage to the next + * greater value (e.g. -2.75 -> -2 + -0.75 -> -3 + 0.25). + */ + dbloff -= 1.0; + dblfrac += 1.0; + } + return {static_cast(dbloff), + static_cast(std::min(dblfrac*MixerFracOne, MixerFracOne-1.0))}; - case AL_SAMPLE_OFFSET: - dblfrac = std::modf(Offset, &dbloff); - if(dblfrac < 0.0) - { - dbloff -= 1.0; - dblfrac += 1.0; - } - offset = static_cast(dbloff); - frac = static_cast(mind(dblfrac*MixerFracOne, MixerFracOne-1.0)); - break; + case AL_SAMPLE_OFFSET: + dblfrac = std::modf(Offset, &dbloff); + if(dblfrac < 0.0) + { + dbloff -= 1.0; + dblfrac += 1.0; + } + return {static_cast(dbloff), + static_cast(std::min(dblfrac*MixerFracOne, MixerFracOne-1.0))}; - case AL_BYTE_OFFSET: - /* Determine the ByteOffset (and ensure it is block aligned) */ - Offset = std::floor(Offset / BufferFmt->blockSizeFromFmt()); - offset = static_cast(Offset) * BufferFmt->mBlockAlign; - frac = 0; - break; - } + case AL_BYTE_OFFSET: + /* Determine the ByteOffset (and ensure it is block aligned) */ + const auto blockoffset = std::floor(Offset / BufferFmt->blockSizeFromFmt()); + return {static_cast(blockoffset) * BufferFmt->mBlockAlign, 0u}; + } + return {0_i64, 0u}; + }); /* Find the bufferlist item this offset belongs to. */ if(offset < 0) @@ -502,17 +501,14 @@ std::optional GetSampleOffset(al::deque &BufferList if(BufferFmt->mCallback) return std::nullopt; - int64_t totalBufferLen{0}; for(auto &item : BufferList) { - if(totalBufferLen > offset) - break; - if(item.mSampleLen > offset-totalBufferLen) + if(item.mSampleLen > offset) { /* Offset is in this buffer */ - return VoicePos{static_cast(offset-totalBufferLen), frac, &item}; + return VoicePos{static_cast(offset), frac, &item}; } - totalBufferLen += item.mSampleLen; + offset -= item.mSampleLen; } /* Offset is out of range of the queue */ @@ -521,16 +517,19 @@ std::optional GetSampleOffset(al::deque &BufferList void InitVoice(Voice *voice, ALsource *source, ALbufferQueueItem *BufferList, ALCcontext *context, - ALCdevice *device) + al::Device *device) { voice->mLoopBuffer.store(source->Looping ? &source->mQueue.front() : nullptr, std::memory_order_relaxed); ALbuffer *buffer{BufferList->mBuffer}; voice->mFrequency = buffer->mSampleRate; - voice->mFmtChannels = - (buffer->mChannels == FmtStereo && source->mStereoMode == SourceStereo::Enhanced) ? - FmtSuperStereo : buffer->mChannels; + if(buffer->mChannels == FmtMono && source->mPanningEnabled) + voice->mFmtChannels = FmtMonoDup; + else if(buffer->mChannels == FmtStereo && source->mStereoMode == SourceStereo::Enhanced) + voice->mFmtChannels = FmtSuperStereo; + else + voice->mFmtChannels = buffer->mChannels; voice->mFmtType = buffer->mType; voice->mFrameStep = buffer->channelsFromFmt(); voice->mBytesPerBlock = buffer->blockSizeFromFmt(); @@ -569,7 +568,7 @@ VoiceChange *GetVoiceChanger(ALCcontext *ctx) void SendVoiceChanges(ALCcontext *ctx, VoiceChange *tail) { - ALCdevice *device{ctx->mALDevice.get()}; + auto *device = ctx->mALDevice.get(); VoiceChange *oldhead{ctx->mCurrentVoiceChange.load(std::memory_order_acquire)}; while(VoiceChange *next{oldhead->mNext.load(std::memory_order_relaxed)}) @@ -577,7 +576,7 @@ void SendVoiceChanges(ALCcontext *ctx, VoiceChange *tail) oldhead->mNext.store(tail, std::memory_order_release); const bool connected{device->Connected.load(std::memory_order_acquire)}; - device->waitForMix(); + std::ignore = device->waitForMix(); if(!connected) UNLIKELY { if(ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire)) @@ -598,8 +597,8 @@ void SendVoiceChanges(ALCcontext *ctx, VoiceChange *tail) } -bool SetVoiceOffset(Voice *oldvoice, const VoicePos &vpos, ALsource *source, ALCcontext *context, - ALCdevice *device) +auto SetVoiceOffset(Voice *oldvoice, const VoicePos &vpos, ALsource *source, ALCcontext *context, + al::Device *device) -> bool { /* First, get a free voice to start at the new offset. */ auto voicelist = context->getVoicesSpan(); @@ -683,7 +682,7 @@ bool SetVoiceOffset(Voice *oldvoice, const VoicePos &vpos, ALsource *source, ALC return true; /* Otherwise, wait for any current mix to finish and check one last time. */ - device->waitForMix(); + std::ignore = device->waitForMix(); if(newvoice->mPlayState.load(std::memory_order_acquire) != Voice::Pending) return true; /* The change-over failed because the old voice stopped before the new @@ -723,26 +722,26 @@ bool EnsureSources(ALCcontext *context, size_t needed) [](size_t cur, const SourceSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(sublist.FreeMask)); })}; - while(needed > count) - { - if(context->mSourceList.size() >= 1<<25) UNLIKELY - return false; - - context->mSourceList.emplace_back(); - auto sublist = context->mSourceList.end() - 1; - sublist->FreeMask = ~0_u64; - sublist->Sources = static_cast(al_calloc(alignof(ALsource), sizeof(ALsource)*64)); - if(!sublist->Sources) UNLIKELY + try { + while(needed > count) { - context->mSourceList.pop_back(); - return false; + if(context->mSourceList.size() >= 1<<25) UNLIKELY + return false; + + SourceSubList sublist{}; + sublist.FreeMask = ~0_u64; + sublist.Sources = SubListAllocator{}.allocate(1); + context->mSourceList.emplace_back(std::move(sublist)); + count += std::tuple_size_v; } - count += 64; + } + catch(...) { + return false; } return true; } -ALsource *AllocSource(ALCcontext *context) +ALsource *AllocSource(ALCcontext *context) noexcept { auto sublist = std::find_if(context->mSourceList.begin(), context->mSourceList.end(), [](const SourceSubList &entry) noexcept -> bool @@ -751,7 +750,10 @@ ALsource *AllocSource(ALCcontext *context) auto slidx = static_cast(al::countr_zero(sublist->FreeMask)); ASSUME(slidx < 64); - ALsource *source{al::construct_at(sublist->Sources + slidx)}; + ALsource *source{al::construct_at(al::to_address(sublist->Sources->begin() + slidx))}; +#if ALSOFT_EAX + source->eaxInitialize(context); +#endif // ALSOFT_EAX /* Add 1 to avoid source ID 0. */ source->id = ((lidx<<6) | slidx) + 1; @@ -799,10 +801,10 @@ inline ALsource *LookupSource(ALCcontext *context, ALuint id) noexcept SourceSubList &sublist{context->mSourceList[lidx]}; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Sources + slidx; + return al::to_address(sublist.Sources->begin() + slidx); } -auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer* +auto LookupBuffer = [](al::Device *device, auto id) noexcept -> ALbuffer* { const auto lidx{(id-1) >> 6}; const auto slidx{(id-1) & 0x3f}; @@ -812,10 +814,10 @@ auto LookupBuffer = [](ALCdevice *device, auto id) noexcept -> ALbuffer* BufferSubList &sublist = device->BufferList[static_cast(lidx)]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Buffers + static_cast(slidx); + return al::to_address(sublist.Buffers->begin() + static_cast(slidx)); }; -auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter* +auto LookupFilter = [](al::Device *device, auto id) noexcept -> ALfilter* { const auto lidx{(id-1) >> 6}; const auto slidx{(id-1) & 0x3f}; @@ -825,7 +827,7 @@ auto LookupFilter = [](ALCdevice *device, auto id) noexcept -> ALfilter* FilterSubList &sublist = device->FilterList[static_cast(lidx)]; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.Filters + static_cast(slidx); + return al::to_address(sublist.Filters->begin() + static_cast(slidx)); }; auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslot* @@ -838,7 +840,7 @@ auto LookupEffectSlot = [](ALCcontext *context, auto id) noexcept -> ALeffectslo EffectSlotSubList &sublist{context->mEffectSlotList[static_cast(lidx)]}; if(sublist.FreeMask & (1_u64 << slidx)) UNLIKELY return nullptr; - return sublist.EffectSlots + static_cast(slidx); + return al::to_address(sublist.EffectSlots->begin() + static_cast(slidx)); }; @@ -879,7 +881,8 @@ ALenum EnumFromSpatializeMode(SpatializeMode mode) case SpatializeMode::On: return AL_TRUE; case SpatializeMode::Auto: return AL_AUTO_SOFT; } - throw std::runtime_error{"Invalid SpatializeMode: "+std::to_string(int(mode))}; + throw std::runtime_error{fmt::format("Invalid SpatializeMode: {}", + int{al::to_underlying(mode)})}; } auto DirectModeFromEnum = [](auto mode) noexcept -> std::optional @@ -900,7 +903,7 @@ ALenum EnumFromDirectMode(DirectMode mode) case DirectMode::DropMismatch: return AL_DROP_UNMATCHED_SOFT; case DirectMode::RemixMismatch: return AL_REMIX_UNMATCHED_SOFT; } - throw std::runtime_error{"Invalid DirectMode: "+std::to_string(int(mode))}; + throw std::runtime_error{fmt::format("Invalid DirectMode: {}", int{al::to_underlying(mode)})}; } auto DistanceModelFromALenum = [](auto model) noexcept -> std::optional @@ -929,7 +932,8 @@ ALenum ALenumFromDistanceModel(DistanceModel model) case DistanceModel::Exponent: return AL_EXPONENT_DISTANCE; case DistanceModel::ExponentClamped: return AL_EXPONENT_DISTANCE_CLAMPED; } - throw std::runtime_error{"Unexpected distance model "+std::to_string(static_cast(model))}; + throw std::runtime_error{fmt::format("Unexpected distance model: {}", + int{al::to_underlying(model)})}; } enum SourceProp : ALenum { @@ -1011,6 +1015,10 @@ enum SourceProp : ALenum { /* AL_SOFT_buffer_sub_data */ srcByteRWOffsetsSOFT = AL_BYTE_RW_OFFSETS_SOFT, srcSampleRWOffsetsSOFT = AL_SAMPLE_RW_OFFSETS_SOFT, + + /* AL_SOFT_source_panning */ + srcPanningEnabledSOFT = AL_PANNING_ENABLED_SOFT, + srcPanSOFT = AL_PAN_SOFT, }; @@ -1038,6 +1046,8 @@ constexpr ALuint IntValsByProp(ALenum prop) case AL_SOURCE_RESAMPLER_SOFT: case AL_SOURCE_SPATIALIZE_SOFT: case AL_STEREO_MODE_SOFT: + case AL_PANNING_ENABLED_SOFT: + case AL_PAN_SOFT: return 1; case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ @@ -1115,6 +1125,8 @@ constexpr ALuint Int64ValsByProp(ALenum prop) case AL_SOURCE_RESAMPLER_SOFT: case AL_SOURCE_SPATIALIZE_SOFT: case AL_STEREO_MODE_SOFT: + case AL_PANNING_ENABLED_SOFT: + case AL_PAN_SOFT: return 1; case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ @@ -1208,6 +1220,8 @@ constexpr ALuint FloatValsByProp(ALenum prop) case AL_SEC_LENGTH_SOFT: case AL_STEREO_MODE_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: + case AL_PANNING_ENABLED_SOFT: + case AL_PAN_SOFT: return 1; case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ @@ -1281,6 +1295,8 @@ constexpr ALuint DoubleValsByProp(ALenum prop) case AL_SEC_LENGTH_SOFT: case AL_STEREO_MODE_SOFT: case AL_SUPER_STEREO_WIDTH_SOFT: + case AL_PANNING_ENABLED_SOFT: + case AL_PAN_SOFT: return 1; case AL_SOURCE_RADIUS: /*AL_BYTE_RW_OFFSETS_SOFT:*/ @@ -1315,18 +1331,6 @@ constexpr ALuint DoubleValsByProp(ALenum prop) } -struct check_exception : std::exception { -}; -struct check_size_exception final : check_exception { - const char *what() const noexcept override - { return "check_size_exception"; } -}; -struct check_value_exception final : check_exception { - const char *what() const noexcept override - { return "check_value_exception"; } -}; - - void UpdateSourceProps(ALsource *source, ALCcontext *context) { if(!context->mDeferUpdates) @@ -1339,7 +1343,7 @@ void UpdateSourceProps(ALsource *source, ALCcontext *context) } source->mPropsDirty = true; } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX void CommitAndUpdateSourceProps(ALsource *source, ALCcontext *context) { if(!context->mDeferUpdates) @@ -1363,70 +1367,56 @@ inline void CommitAndUpdateSourceProps(ALsource *source, ALCcontext *context) template -struct PropType { }; +auto PropTypeName() -> std::string_view = delete; template<> -struct PropType { static const char *Name() { return "integer"; } }; +auto PropTypeName() -> std::string_view { return "integer"sv; } template<> -struct PropType { static const char *Name() { return "int64"; } }; +auto PropTypeName() -> std::string_view { return "int64"sv; } template<> -struct PropType { static const char *Name() { return "float"; } }; +auto PropTypeName() -> std::string_view { return "float"sv; } template<> -struct PropType { static const char *Name() { return "double"; } }; - -template -struct HexPrinter { - char mStr[sizeof(T)*2 + 3]{}; - HexPrinter(T value) - { - using ST = std::make_signed_t>; - if constexpr(std::is_same_v) - std::snprintf(mStr, std::size(mStr), "0x%x", value); - else if constexpr(std::is_same_v) - std::snprintf(mStr, std::size(mStr), "0x%lx", value); - else if constexpr(std::is_same_v) - std::snprintf(mStr, std::size(mStr), "0x%llx", value); - } - - const char *c_str() const noexcept { return mStr; } -}; +auto PropTypeName() -> std::string_view { return "double"sv; } /** * Returns a pair of lambdas to check the following setter. * * The first lambda checks the size of the span is valid for the required size, - * setting the proper context error and throwing a check_size_exception if it - * fails. + * throwing a context error if it fails. * - * The second lambda tests the validity of the value check, setting the proper - * context error and throwing a check_value_exception if it failed. + * The second lambda tests the validity of the value check, throwing a context + * error if it failed. */ +template +struct PairStruct { T First; U Second; }; +template +PairStruct(T,U) -> PairStruct; + template -auto GetCheckers(ALCcontext *const Context, const SourceProp prop, const al::span values) +auto GetCheckers(ALCcontext *context, const SourceProp prop, const al::span values) { - return std::make_pair( + return PairStruct{ [=](size_t expect) -> void { - if(values.size() == expect) LIKELY return; - Context->setError(AL_INVALID_ENUM, "Property 0x%04x expects %zu value(s), got %zu", - prop, expect, values.size()); - throw check_size_exception{}; + if(values.size() == expect) return; + context->throw_error(AL_INVALID_ENUM, "Property {:#04x} expects {} value{}, got {}", + as_unsigned(al::to_underlying(prop)), expect, (expect==1) ? "" : "s", + values.size()); }, - [Context](bool passed) -> void + [context](bool passed) -> void { - if(passed) LIKELY return; - Context->setError(AL_INVALID_VALUE, "Value out of range"); - throw check_value_exception{}; + if(passed) return; + context->throw_error(AL_INVALID_VALUE, "Value out of range"); } - ); + }; } template NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, - const al::span values) try + const al::span values) { - auto&& [CheckSize, CheckValue] = GetCheckers(Context, prop, values); - ALCdevice *device{Context->mALDevice.get()}; + auto [CheckSize, CheckValue] = GetCheckers(Context, prop, values); + auto *device = Context->mALDevice.get(); switch(prop) { @@ -1437,8 +1427,8 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { /* Query only */ - return Context->setError(AL_INVALID_OPERATION, - "Setting read-only source property 0x%04x", prop); + Context->throw_error(AL_INVALID_OPERATION, + "Setting read-only source property {:#04x}", as_unsigned(al::to_underlying(prop))); } break; @@ -1450,12 +1440,15 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con case AL_SAMPLE_OFFSET_CLOCK_SOFT: case AL_SEC_OFFSET_CLOCK_SOFT: /* Query only */ - return Context->setError(AL_INVALID_OPERATION, - "Setting read-only source property 0x%04x", prop); + Context->throw_error(AL_INVALID_OPERATION, "Setting read-only source property {:#04x}", + as_unsigned(al::to_underlying(prop))); case AL_PITCH: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->Pitch = static_cast(values[0]); return UpdateSourceProps(Source, Context); @@ -1476,42 +1469,60 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con case AL_GAIN: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->Gain = static_cast(values[0]); return UpdateSourceProps(Source, Context); case AL_MAX_DISTANCE: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->MaxDistance = static_cast(values[0]); return CommitAndUpdateSourceProps(Source, Context); case AL_ROLLOFF_FACTOR: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->RolloffFactor = static_cast(values[0]); return CommitAndUpdateSourceProps(Source, Context); case AL_REFERENCE_DISTANCE: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->RefDistance = static_cast(values[0]); return CommitAndUpdateSourceProps(Source, Context); case AL_MIN_GAIN: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->MinGain = static_cast(values[0]); return UpdateSourceProps(Source, Context); case AL_MAX_GAIN: CheckSize(1); - CheckValue(values[0] >= T{0}); + if constexpr(std::is_floating_point_v) + CheckValue(values[0] >= T{0} && std::isfinite(static_cast(values[0]))); + else + CheckValue(values[0] >= T{0}); Source->MaxGain = static_cast(values[0]); return UpdateSourceProps(Source, Context); @@ -1581,7 +1592,7 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con * to ensure it isn't currently looping back or reaching the * end. */ - device->waitForMix(); + std::ignore = device->waitForMix(); } return; } @@ -1591,30 +1602,28 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { CheckSize(1); - { - const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))}; - if(state == AL_PLAYING || state == AL_PAUSED) - return Context->setError(AL_INVALID_OPERATION, - "Setting buffer on playing or paused source %u", Source->id); - } - al::deque oldlist; + if(const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))}; + state == AL_PLAYING || state == AL_PAUSED) + Context->throw_error(AL_INVALID_OPERATION, + "Setting buffer on playing or paused source {}", Source->id); + + std::deque oldlist; if(values[0]) { using UT = std::make_unsigned_t; - std::lock_guard _{device->BufferLock}; + std::lock_guard buflock{device->BufferLock}; ALbuffer *buffer{LookupBuffer(device, static_cast(values[0]))}; - if(!buffer) UNLIKELY - return Context->setError(AL_INVALID_VALUE, "Invalid buffer ID %s", - std::to_string(values[0]).c_str()); - if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) UNLIKELY - return Context->setError(AL_INVALID_OPERATION, - "Setting non-persistently mapped buffer %u", buffer->id); - if(buffer->mCallback && ReadRef(buffer->ref) != 0) UNLIKELY - return Context->setError(AL_INVALID_OPERATION, - "Setting already-set callback buffer %u", buffer->id); + if(!buffer) + Context->throw_error(AL_INVALID_VALUE, "Invalid buffer ID {}", values[0]); + if(buffer->MappedAccess && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + Context->throw_error(AL_INVALID_OPERATION, + "Setting non-persistently mapped buffer {}", buffer->id); + if(buffer->mCallback && buffer->ref.load(std::memory_order_relaxed) != 0) + Context->throw_error(AL_INVALID_OPERATION, + "Setting already-set callback buffer {}", buffer->id); /* Add the selected buffer to a one-item queue */ - al::deque newlist; + std::deque newlist; newlist.emplace_back(); newlist.back().mCallback = buffer->mCallback; newlist.back().mUserData = buffer->mUserData; @@ -1622,7 +1631,7 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con newlist.back().mSampleLen = buffer->mSampleLen; newlist.back().mLoopStart = buffer->mLoopStart; newlist.back().mLoopEnd = buffer->mLoopEnd; - newlist.back().mSamples = buffer->mData.data(); + newlist.back().mSamples = buffer->mData; newlist.back().mBuffer = buffer; IncrementRef(buffer->ref); @@ -1659,7 +1668,7 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if(Voice *voice{GetSourceVoice(Source, Context)}) { auto vpos = GetSampleOffset(Source->mQueue, prop, static_cast(values[0])); - if(!vpos) return Context->setError(AL_INVALID_VALUE, "Invalid offset"); + if(!vpos) Context->throw_error(AL_INVALID_VALUE, "Invalid offset"); if(SetVoiceOffset(voice, *vpos, Source, Context, Context->mALDevice.get())) return; @@ -1674,8 +1683,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { /* Query only */ - return Context->setError(AL_INVALID_OPERATION, - "Setting read-only source property 0x%04x", prop); + Context->throw_error(AL_INVALID_OPERATION, + "Setting read-only source property {:#04x}", + as_unsigned(al::to_underlying(prop))); } } break; @@ -1686,8 +1696,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { /* Query only */ - return Context->setError(AL_INVALID_OPERATION, - "Setting read-only source property 0x%04x", prop); + Context->throw_error(AL_INVALID_OPERATION, + "Setting read-only source property {:#04x}", + as_unsigned(al::to_underlying(prop))); } break; } @@ -1707,6 +1718,25 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con Source->EnhWidth = static_cast(values[0]); return UpdateSourceProps(Source, Context); + case AL_PANNING_ENABLED_SOFT: + CheckSize(1); + if(const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))}; + state == AL_PLAYING || state == AL_PAUSED) + Context->throw_error(AL_INVALID_OPERATION, + "Modifying panning enabled on playing or paused source {}", Source->id); + + CheckValue(values[0] == AL_FALSE || values[0] == AL_TRUE); + + Source->mPanningEnabled = values[0] != AL_FALSE; + return UpdateSourceProps(Source, Context); + + case AL_PAN_SOFT: + CheckSize(1); + CheckValue(values[0] >= T{-1} && values[0] <= T{1}); + + Source->mPan = static_cast(values[0]); + return UpdateSourceProps(Source, Context); + case AL_STEREO_ANGLES: CheckSize(2); if constexpr(std::is_floating_point_v) @@ -1780,11 +1810,10 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con const auto filterid = static_cast>(values[0]); if(values[0]) { - std::lock_guard _{device->FilterLock}; + std::lock_guard filterlock{device->FilterLock}; ALfilter *filter{LookupFilter(device, filterid)}; - if(!filter) UNLIKELY - return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s", - std::to_string(filterid).c_str()); + if(!filter) + Context->throw_error(AL_INVALID_VALUE, "Invalid filter ID {}", filterid); Source->Direct.Gain = filter->Gain; Source->Direct.GainHF = filter->GainHF; Source->Direct.HFReference = filter->HFReference; @@ -1795,9 +1824,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con { Source->Direct.Gain = 1.0f; Source->Direct.GainHF = 1.0f; - Source->Direct.HFReference = LOWPASSFREQREF; + Source->Direct.HFReference = LowPassFreqRef; Source->Direct.GainLF = 1.0f; - Source->Direct.LFReference = HIGHPASSFREQREF; + Source->Direct.LFReference = HighPassFreqRef; } return UpdateSourceProps(Source, Context); } @@ -1845,8 +1874,8 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con Source->DirectChannels = *mode; return UpdateSourceProps(Source, Context); } - return Context->setError(AL_INVALID_VALUE, "Invalid direct channels mode: %s\n", - HexPrinter{values[0]}.c_str()); + Context->throw_error(AL_INVALID_VALUE, "Invalid direct channels mode: {:#x}", + as_unsigned(values[0])); } break; @@ -1861,8 +1890,8 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con UpdateSourceProps(Source, Context); return; } - return Context->setError(AL_INVALID_VALUE, "Invalid distance model: %s\n", - HexPrinter{values[0]}.c_str()); + Context->throw_error(AL_INVALID_VALUE, "Invalid distance model: {:#x}", + as_unsigned(values[0])); } break; @@ -1870,7 +1899,7 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { CheckSize(1); - CheckValue(values[0] >= 0 && values[0] <= static_cast(Resampler::Max)); + CheckValue(values[0] >= 0 && values[0] <= al::to_underlying(Resampler::Max)); Source->mResampler = static_cast(values[0]); return UpdateSourceProps(Source, Context); @@ -1886,8 +1915,8 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con Source->mSpatialize = *mode; return UpdateSourceProps(Source, Context); } - return Context->setError(AL_INVALID_VALUE, "Invalid source spatialize mode: %s\n", - HexPrinter{values[0]}.c_str()); + Context->throw_error(AL_INVALID_VALUE, "Invalid source spatialize mode: {}", + values[0]); } break; @@ -1895,19 +1924,18 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con if constexpr(std::is_integral_v) { CheckSize(1); - { - const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))}; - if(state == AL_PLAYING || state == AL_PAUSED) - return Context->setError(AL_INVALID_OPERATION, - "Modifying stereo mode on playing or paused source %u", Source->id); - } + if(const ALenum state{GetSourceState(Source, GetSourceVoice(Source, Context))}; + state == AL_PLAYING || state == AL_PAUSED) + Context->throw_error(AL_INVALID_OPERATION, + "Modifying stereo mode on playing or paused source {}", Source->id); + if(auto mode = StereoModeFromEnum(values[0])) { Source->mStereoMode = *mode; return; } - return Context->setError(AL_INVALID_VALUE, "Invalid stereo mode: %s\n", - HexPrinter{values[0]}.c_str()); + Context->throw_error(AL_INVALID_VALUE, "Invalid stereo mode: {:#x}", + as_unsigned(values[0])); } break; @@ -1923,23 +1951,21 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con ALeffectslot *slot{}; if(values[0]) { - if((slot=LookupEffectSlot(Context, slotid)) == nullptr) UNLIKELY - return Context->setError(AL_INVALID_VALUE, "Invalid effect ID %s", - std::to_string(slotid).c_str()); + slot = LookupEffectSlot(Context, slotid); + if(!slot) + Context->throw_error(AL_INVALID_VALUE, "Invalid effect ID {}", slotid); } - if(sendidx >= device->NumAuxSends) UNLIKELY - return Context->setError(AL_INVALID_VALUE, "Invalid send %s", - std::to_string(sendidx).c_str()); + if(sendidx >= device->NumAuxSends) + Context->throw_error(AL_INVALID_VALUE, "Invalid send {}", sendidx); auto &send = Source->Send[static_cast(sendidx)]; if(values[2]) { - std::lock_guard _{device->FilterLock}; + std::lock_guard filterlock{device->FilterLock}; ALfilter *filter{LookupFilter(device, filterid)}; - if(!filter) UNLIKELY - return Context->setError(AL_INVALID_VALUE, "Invalid filter ID %s", - std::to_string(filterid).c_str()); + if(!filter) + Context->throw_error(AL_INVALID_VALUE, "Invalid filter ID {}", filterid); send.Gain = filter->Gain; send.GainHF = filter->GainHF; @@ -1952,9 +1978,9 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con /* Disable filter */ send.Gain = 1.0f; send.GainHF = 1.0f; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; } /* We must force an update if the current auxiliary slot is valid @@ -1986,113 +2012,108 @@ NOINLINE void SetProperty(ALsource *const Source, ALCcontext *const Context, con break; } - ERR("Unexpected %s property: 0x%04x\n", PropType::Name(), prop); - Context->setError(AL_INVALID_ENUM, "Invalid source %s property 0x%04x", PropType::Name(), - prop); -} -catch(check_exception&) { + Context->throw_error(AL_INVALID_ENUM, "Invalid source {} property {:#04x}", PropTypeName(), + as_unsigned(al::to_underlying(prop))); } template -auto GetSizeChecker(ALCcontext *const Context, const SourceProp prop, const al::span values) +auto GetSizeChecker(ALCcontext *context, const SourceProp prop, const al::span values) { return [=](size_t expect) -> void { if(values.size() == expect) LIKELY return; - Context->setError(AL_INVALID_ENUM, "Property 0x%04x expects %zu value(s), got %zu", - prop, expect, values.size()); - throw check_size_exception{}; + context->throw_error(AL_INVALID_ENUM, "Property {:#04x} expects {} value{}, got {}", + as_unsigned(al::to_underlying(prop)), expect, (expect==1) ? "" : "s", values.size()); }; } template -[[nodiscard]] NOINLINE -bool GetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, - const al::span values) try +NOINLINE void GetProperty(ALsource *const Source, ALCcontext *const Context, const SourceProp prop, + const al::span values) { using std::chrono::duration_cast; auto CheckSize = GetSizeChecker(Context, prop, values); - ALCdevice *device{Context->mALDevice.get()}; + auto *device = Context->mALDevice.get(); switch(prop) { case AL_GAIN: CheckSize(1); values[0] = static_cast(Source->Gain); - return true; + return; case AL_PITCH: CheckSize(1); values[0] = static_cast(Source->Pitch); - return true; + return; case AL_MAX_DISTANCE: CheckSize(1); values[0] = static_cast(Source->MaxDistance); - return true; + return; case AL_ROLLOFF_FACTOR: CheckSize(1); values[0] = static_cast(Source->RolloffFactor); - return true; + return; case AL_REFERENCE_DISTANCE: CheckSize(1); values[0] = static_cast(Source->RefDistance); - return true; + return; case AL_CONE_INNER_ANGLE: CheckSize(1); values[0] = static_cast(Source->InnerAngle); - return true; + return; case AL_CONE_OUTER_ANGLE: CheckSize(1); values[0] = static_cast(Source->OuterAngle); - return true; + return; case AL_MIN_GAIN: CheckSize(1); values[0] = static_cast(Source->MinGain); - return true; + return; case AL_MAX_GAIN: CheckSize(1); values[0] = static_cast(Source->MaxGain); - return true; + return; case AL_CONE_OUTER_GAIN: CheckSize(1); values[0] = static_cast(Source->OuterGain); - return true; + return; case AL_SEC_OFFSET: case AL_SAMPLE_OFFSET: case AL_BYTE_OFFSET: CheckSize(1); values[0] = GetSourceOffset(Source, prop, Context); - return true; + return; case AL_CONE_OUTER_GAINHF: CheckSize(1); values[0] = static_cast(Source->OuterGainHF); - return true; + return; case AL_AIR_ABSORPTION_FACTOR: CheckSize(1); values[0] = static_cast(Source->AirAbsorptionFactor); - return true; + return; case AL_ROOM_ROLLOFF_FACTOR: CheckSize(1); values[0] = static_cast(Source->RoomRolloffFactor); - return true; + return; case AL_DOPPLER_FACTOR: CheckSize(1); values[0] = static_cast(Source->DopplerFactor); - return true; + return; case AL_SAMPLE_RW_OFFSETS_SOFT: if constexpr(std::is_integral_v) @@ -2106,7 +2127,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source * buffer queue. */ values[1] = values[0]; - return true; + return; } } break; @@ -2118,7 +2139,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source CheckSize(1); values[0] = static_cast(Source->Radius); - return true; + return; } else { @@ -2131,7 +2152,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source * buffer queue. */ values[1] = values[0]; - return true; + return; } break; } @@ -2139,14 +2160,24 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source case AL_SUPER_STEREO_WIDTH_SOFT: CheckSize(1); values[0] = static_cast(Source->EnhWidth); - return true; + return; case AL_BYTE_LENGTH_SOFT: case AL_SAMPLE_LENGTH_SOFT: case AL_SEC_LENGTH_SOFT: CheckSize(1); values[0] = GetSourceLength(Source, prop); - return true; + return; + + case AL_PANNING_ENABLED_SOFT: + CheckSize(1); + values[0] = Source->mPanningEnabled; + return; + + case AL_PAN_SOFT: + CheckSize(1); + values[0] = static_cast(Source->mPan); + return; case AL_STEREO_ANGLES: if constexpr(std::is_floating_point_v) @@ -2154,7 +2185,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source CheckSize(2); values[0] = static_cast(Source->StereoPan[0]); values[1] = static_cast(Source->StereoPan[1]); - return true; + return; } break; @@ -2169,7 +2200,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source nanoseconds srcclock{}; values[0] = GetSourceSampleOffset(Source, Context, &srcclock); { - std::lock_guard _{device->StateLock}; + std::lock_guard statelock{device->StateLock}; clocktime = GetClockLatency(device, device->Backend.get()); } if(srcclock == clocktime.ClockTime) @@ -2183,7 +2214,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock); values[1] = nanoseconds{clocktime.Latency - diff}.count(); } - return true; + return; } break; @@ -2194,7 +2225,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source nanoseconds srcclock{}; values[0] = GetSourceSampleOffset(Source, Context, &srcclock); values[1] = srcclock.count(); - return true; + return; } break; @@ -2209,7 +2240,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source nanoseconds srcclock{}; values[0] = GetSourceSecOffset(Source, Context, &srcclock); { - std::lock_guard _{device->StateLock}; + std::lock_guard statelock{device->StateLock}; clocktime = GetClockLatency(device, device->Backend.get()); } if(srcclock == clocktime.ClockTime) @@ -2223,7 +2254,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source const auto diff = std::min(clocktime.Latency, clocktime.ClockTime-srcclock); values[1] = duration_cast(clocktime.Latency - diff).count(); } - return true; + return; } break; @@ -2234,7 +2265,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source nanoseconds srcclock{}; values[0] = GetSourceSecOffset(Source, Context, &srcclock); values[1] = duration_cast(srcclock).count(); - return true; + return; } break; @@ -2243,21 +2274,21 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source values[0] = static_cast(Source->Position[0]); values[1] = static_cast(Source->Position[1]); values[2] = static_cast(Source->Position[2]); - return true; + return; case AL_VELOCITY: CheckSize(3); values[0] = static_cast(Source->Velocity[0]); values[1] = static_cast(Source->Velocity[1]); values[2] = static_cast(Source->Velocity[2]); - return true; + return; case AL_DIRECTION: CheckSize(3); values[0] = static_cast(Source->Direction[0]); values[1] = static_cast(Source->Direction[1]); values[2] = static_cast(Source->Direction[2]); - return true; + return; case AL_ORIENTATION: CheckSize(6); @@ -2267,7 +2298,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source values[3] = static_cast(Source->OrientUp[0]); values[4] = static_cast(Source->OrientUp[1]); values[5] = static_cast(Source->OrientUp[2]); - return true; + return; case AL_SOURCE_RELATIVE: @@ -2275,7 +2306,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->HeadRelative; - return true; + return; } break; @@ -2284,7 +2315,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->Looping; - return true; + return; } break; @@ -2292,7 +2323,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source if constexpr(std::is_integral_v) { CheckSize(1); - ALbufferQueueItem *BufferList{}; + const ALbufferQueueItem *BufferList{}; /* HACK: This query should technically only return the buffer set * on a static source. However, some apps had used it to detect * when a streaming source changed buffers, so report the current @@ -2306,11 +2337,14 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source else if(Voice *voice{GetSourceVoice(Source, Context)}) { VoiceBufferItem *Current{voice->mCurrentBuffer.load(std::memory_order_relaxed)}; - BufferList = static_cast(Current); + const auto iter = std::find_if(Source->mQueue.cbegin(), Source->mQueue.cend(), + [Current](const ALbufferQueueItem &item) noexcept -> bool + { return &item == Current; }); + BufferList = (iter != Source->mQueue.cend()) ? al::to_address(iter) : nullptr; } ALbuffer *buffer{BufferList ? BufferList->mBuffer : nullptr}; values[0] = buffer ? static_cast(buffer->id) : T{0}; - return true; + return; } break; @@ -2319,7 +2353,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = GetSourceState(Source, GetSourceVoice(Source, Context)); - return true; + return; } break; @@ -2328,7 +2362,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = static_cast(Source->mQueue.size()); - return true; + return; } break; @@ -2360,7 +2394,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source } values[0] = played; } - return true; + return; } break; @@ -2369,7 +2403,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->SourceType; - return true; + return; } break; @@ -2378,7 +2412,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->DryGainHFAuto; - return true; + return; } break; @@ -2387,7 +2421,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->WetGainAuto; - return true; + return; } break; @@ -2396,7 +2430,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = Source->WetGainHFAuto; - return true; + return; } break; @@ -2405,7 +2439,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = EnumFromDirectMode(Source->DirectChannels); - return true; + return; } break; @@ -2414,7 +2448,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = ALenumFromDistanceModel(Source->mDistanceModel); - return true; + return; } break; @@ -2423,7 +2457,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = static_cast(Source->mResampler); - return true; + return; } break; @@ -2432,7 +2466,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = EnumFromSpatializeMode(Source->mSpatialize); - return true; + return; } break; @@ -2441,7 +2475,7 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source { CheckSize(1); values[0] = EnumFromStereoMode(Source->mStereoMode); - return true; + return; } break; @@ -2450,20 +2484,15 @@ bool GetProperty(ALsource *const Source, ALCcontext *const Context, const Source break; } - ERR("Unexpected %s query property: 0x%04x\n", PropType::Name(), prop); - Context->setError(AL_INVALID_ENUM, "Invalid source %s query property 0x%04x", - PropType::Name(), prop); - return false; -} -catch(check_exception&) { - return false; + Context->throw_error(AL_INVALID_ENUM, "Invalid source {} query property {:#04x}", + PropTypeName(), as_unsigned(al::to_underlying(prop))); } void StartSources(ALCcontext *const context, const al::span srchandles, const nanoseconds start_time=nanoseconds::min()) { - ALCdevice *device{context->mALDevice.get()}; + auto *device = context->mALDevice.get(); /* If the device is disconnected, and voices stop on disconnect, go right * to stopped. */ @@ -2552,7 +2581,7 @@ void StartSources(ALCcontext *const context, const al::span srchandle cur->mSourceID = source->id; cur->mState = VChangeState::Play; source->state = AL_PLAYING; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(context->hasEax()) source->eaxCommit(); #endif // ALSOFT_EAX @@ -2572,7 +2601,7 @@ void StartSources(ALCcontext *const context, const al::span srchandle default: assert(voice == nullptr); cur->mOldVoice = nullptr; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(context->hasEax()) source->eaxCommit(); #endif // ALSOFT_EAX @@ -2631,592 +2660,700 @@ void StartSources(ALCcontext *const context, const al::span srchandle } // namespace -AL_API DECL_FUNC2(void, alGenSources, ALsizei, ALuint*) +AL_API DECL_FUNC2(void, alGenSources, ALsizei,n, ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Generating %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Generating {} sources", n); if(n <= 0) UNLIKELY return; - std::unique_lock srclock{context->mSourceLock}; - ALCdevice *device{context->mALDevice.get()}; - if(static_cast(n) > device->SourcesMax-context->mNumSources) - { - context->setError(AL_OUT_OF_MEMORY, "Exceeding %u source limit (%u + %d)", - device->SourcesMax, context->mNumSources, n); - return; - } - if(!EnsureSources(context, static_cast(n))) - { - context->setError(AL_OUT_OF_MEMORY, "Failed to allocate %d source%s", n, (n==1)?"":"s"); - return; - } + auto srclock = std::unique_lock{context->mSourceLock}; + auto *device = context->mALDevice.get(); - if(n == 1) - { - ALsource *source{AllocSource(context)}; - sources[0] = source->id; + const al::span sids{sources, static_cast(n)}; + if(context->mNumSources > device->SourcesMax + || sids.size() > device->SourcesMax-context->mNumSources) + context->throw_error(AL_OUT_OF_MEMORY, "Exceeding {} source limit ({} + {})", + device->SourcesMax, context->mNumSources, n); + if(!EnsureSources(context, sids.size())) + context->throw_error(AL_OUT_OF_MEMORY, "Failed to allocate {} source{}", n, + (n==1) ? "" : "s"); -#ifdef ALSOFT_EAX - source->eaxInitialize(context); -#endif // ALSOFT_EAX - } - else - { - std::vector ids; - ids.reserve(static_cast(n)); - do { - ALsource *source{AllocSource(context)}; - ids.emplace_back(source->id); - -#ifdef ALSOFT_EAX - source->eaxInitialize(context); -#endif // ALSOFT_EAX - } while(--n); - std::copy(ids.cbegin(), ids.cend(), sources); - } + std::generate(sids.begin(), sids.end(), [context]{ return AllocSource(context)->id; }); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alDeleteSources, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alDeleteSources, ALsizei,n, const ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Deleting %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Deleting {} sources", n); if(n <= 0) UNLIKELY return; - std::lock_guard _{context->mSourceLock}; + std::lock_guard srclock{context->mSourceLock}; /* Check that all Sources are valid */ auto validate_source = [context](const ALuint sid) -> bool { return LookupSource(context, sid) != nullptr; }; - const ALuint *sources_end = sources + n; - auto invsrc = std::find_if_not(sources, sources_end, validate_source); - if(invsrc != sources_end) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *invsrc); + const al::span sids{sources, static_cast(n)}; + auto invsrc = std::find_if_not(sids.begin(), sids.end(), validate_source); + if(invsrc != sids.end()) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", *invsrc); /* All good. Delete source IDs. */ auto delete_source = [&context](const ALuint sid) -> void { - ALsource *src{LookupSource(context, sid)}; - if(src) FreeSource(context, src); + if(ALsource *src{LookupSource(context, sid)}) + FreeSource(context, src); }; - std::for_each(sources, sources_end, delete_source); + std::for_each(sids.begin(), sids.end(), delete_source); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC1(ALboolean, alIsSource, ALuint) +AL_API DECL_FUNC1(ALboolean, alIsSource, ALuint,source) FORCE_ALIGN ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) noexcept { - std::lock_guard _{context->mSourceLock}; + std::lock_guard srclock{context->mSourceLock}; if(LookupSource(context, source) != nullptr) return AL_TRUE; return AL_FALSE; } -AL_API DECL_FUNC3(void, alSourcef, ALuint, ALenum, ALfloat) +AL_API DECL_FUNC3(void, alSourcef, ALuint,source, ALenum,param, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - SetProperty(Source, context, static_cast(param), al::span{&value, 1u}); + SetProperty(Source, context, static_cast(param), {&value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alSource3f, ALuint, ALenum, ALfloat, ALfloat, ALfloat) +AL_API DECL_FUNC5(void, alSource3f, ALuint,source, ALenum,param, ALfloat,value1, ALfloat,value2, ALfloat,value3) FORCE_ALIGN void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - const float fvals[3]{ value1, value2, value3 }; - SetProperty(Source, context, static_cast(param), al::span{fvals}); + const std::array fvals{value1, value2, value3}; + SetProperty(Source, context, static_cast(param), fvals); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alSourcefv, ALuint, ALenum, const ALfloat*) +AL_API DECL_FUNC3(void, alSourcefv, ALuint,source, ALenum,param, const ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{FloatValsByProp(param)}; SetProperty(Source, context, static_cast(param), al::span{values, count}); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNCEXT3(void, alSourced,SOFT, ALuint, ALenum, ALdouble) +AL_API DECL_FUNCEXT3(void, alSourced,SOFT, ALuint,source, ALenum,param, ALdouble,value) FORCE_ALIGN void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - SetProperty(Source, context, static_cast(param), al::span{&value, 1}); + SetProperty(Source, context, static_cast(param), {&value, 1}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alSource3d,SOFT, ALuint, ALenum, ALdouble, ALdouble, ALdouble) +AL_API DECL_FUNCEXT5(void, alSource3d,SOFT, ALuint,source, ALenum,param, ALdouble,value1, ALdouble,value2, ALdouble,value3) FORCE_ALIGN void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - const double dvals[3]{value1, value2, value3}; - SetProperty(Source, context, static_cast(param), al::span{dvals}); + const std::array dvals{value1, value2, value3}; + SetProperty(Source, context, static_cast(param), dvals); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alSourcedv,SOFT, ALuint, ALenum, const ALdouble*) +AL_API DECL_FUNCEXT3(void, alSourcedv,SOFT, ALuint,source, ALenum,param, const ALdouble*,values) FORCE_ALIGN void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{DoubleValsByProp(param)}; SetProperty(Source, context, static_cast(param), al::span{values, count}); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC3(void, alSourcei, ALuint, ALenum, ALint) +AL_API DECL_FUNC3(void, alSourcei, ALuint,source, ALenum,param, ALint,value) FORCE_ALIGN void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - SetProperty(Source, context, static_cast(param), al::span{&value, 1u}); + SetProperty(Source, context, static_cast(param), {&value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alSource3i, ALuint, ALenum, ALint, ALint, ALint) +AL_API DECL_FUNC5(void, alSource3i, ALuint,buffer, ALenum,param, ALint,value1, ALint,value2, ALint,value3) FORCE_ALIGN void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - const int ivals[3]{ value1, value2, value3 }; - SetProperty(Source, context, static_cast(param), al::span{ivals}); + const std::array ivals{value1, value2, value3}; + SetProperty(Source, context, static_cast(param), ivals); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alSourceiv, ALuint, ALenum, const ALint*) +AL_API DECL_FUNC3(void, alSourceiv, ALuint,source, ALenum,param, const ALint*,values) FORCE_ALIGN void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; - ALsource *Source = LookupSource(context, source); - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{IntValsByProp(param)}; SetProperty(Source, context, static_cast(param), al::span{values, count}); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNCEXT3(void, alSourcei64,SOFT, ALuint, ALenum, ALint64SOFT) +AL_API DECL_FUNCEXT3(void, alSourcei64,SOFT, ALuint,source, ALenum,param, ALint64SOFT,value) FORCE_ALIGN void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - SetProperty(Source, context, static_cast(param), al::span{&value, 1u}); + SetProperty(Source, context, static_cast(param), {&value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alSource3i64,SOFT, ALuint, ALenum, ALint64SOFT, ALint64SOFT, ALint64SOFT) +AL_API DECL_FUNCEXT5(void, alSource3i64,SOFT, ALuint,source, ALenum,param, ALint64SOFT,value1, ALint64SOFT,value2, ALint64SOFT,value3) FORCE_ALIGN void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - const int64_t i64vals[3]{ value1, value2, value3 }; - SetProperty(Source, context, static_cast(param), al::span{i64vals}); + const std::array i64vals{value1, value2, value3}; + SetProperty(Source, context, static_cast(param), i64vals); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alSourcei64v,SOFT, ALuint, ALenum, const ALint64SOFT*) +AL_API DECL_FUNCEXT3(void, alSourcei64v,SOFT, ALuint,source, ALenum,param, const ALint64SOFT*,values) FORCE_ALIGN void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) noexcept -{ - std::lock_guard _{context->mPropLock}; - std::lock_guard __{context->mSourceLock}; +try { + std::lock_guard proplock{context->mPropLock}; + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{Int64ValsByProp(param)}; SetProperty(Source, context, static_cast(param), al::span{values, count}); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC3(void, alGetSourcef, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetSourcef, ALuint,source, ALenum,param, ALfloat*,value) FORCE_ALIGN void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!value) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - std::ignore = GetProperty(Source, context, static_cast(param), al::span{value, 1}); + GetProperty(Source, context, static_cast(param), al::span{value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alGetSource3f, ALuint, ALenum, ALfloat*, ALfloat*, ALfloat*) +AL_API DECL_FUNC5(void, alGetSource3f, ALuint,source, ALenum,param, ALfloat*,value1, ALfloat*,value2, ALfloat*,value3) FORCE_ALIGN void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!(value1 && value2 && value3)) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!(value1 && value2 && value3)) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - float fvals[3]; - if(GetProperty(Source, context, static_cast(param), al::span{fvals})) - { - *value1 = fvals[0]; - *value2 = fvals[1]; - *value3 = fvals[2]; - } + std::array fvals{}; + GetProperty(Source, context, static_cast(param), fvals); + *value1 = fvals[0]; + *value2 = fvals[1]; + *value3 = fvals[2]; +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetSourcefv, ALuint, ALenum, ALfloat*) +AL_API DECL_FUNC3(void, alGetSourcefv, ALuint,source, ALenum,param, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{FloatValsByProp(param)}; - std::ignore = GetProperty(Source, context, static_cast(param), - al::span{values, count}); + GetProperty(Source, context, static_cast(param), al::span{values, count}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetSourced,SOFT, ALuint, ALenum, ALdouble*) +AL_API DECL_FUNCEXT3(void, alGetSourced,SOFT, ALuint,source, ALenum,param, ALdouble*,value) FORCE_ALIGN void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!value) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - std::ignore = GetProperty(Source, context, static_cast(param), al::span{value, 1}); + GetProperty(Source, context, static_cast(param), al::span{value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alGetSource3d,SOFT, ALuint, ALenum, ALdouble*, ALdouble*, ALdouble*) +AL_API DECL_FUNCEXT5(void, alGetSource3d,SOFT, ALuint,source, ALenum,param, ALdouble*,value1, ALdouble*,value2, ALdouble*,value3) FORCE_ALIGN void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!(value1 && value2 && value3)) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!(value1 && value2 && value3)) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - double dvals[3]; - if(GetProperty(Source, context, static_cast(param), al::span{dvals})) - { - *value1 = dvals[0]; - *value2 = dvals[1]; - *value3 = dvals[2]; - } + std::array dvals{}; + GetProperty(Source, context, static_cast(param), dvals); + *value1 = dvals[0]; + *value2 = dvals[1]; + *value3 = dvals[2]; +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetSourcedv,SOFT, ALuint, ALenum, ALdouble*) +AL_API DECL_FUNCEXT3(void, alGetSourcedv,SOFT, ALuint,source, ALenum,param, ALdouble*,values) FORCE_ALIGN void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{DoubleValsByProp(param)}; - std::ignore = GetProperty(Source, context, static_cast(param), - al::span{values, count}); + GetProperty(Source, context, static_cast(param), al::span{values, count}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetSourcei, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetSourcei, ALuint,source, ALenum,param, ALint*,value) FORCE_ALIGN void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!value) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - std::ignore = GetProperty(Source, context, static_cast(param), al::span{value, 1}); + GetProperty(Source, context, static_cast(param), al::span{value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC5(void, alGetSource3i, ALuint, ALenum, ALint*, ALint*, ALint*) +AL_API DECL_FUNC5(void, alGetSource3i, ALuint,source, ALenum,param, ALint*,value1, ALint*,value2, ALint*,value3) FORCE_ALIGN void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!(value1 && value2 && value3)) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); - - int ivals[3]; - if(GetProperty(Source, context, static_cast(param), al::span{ivals})) - { - *value1 = ivals[0]; - *value2 = ivals[1]; - *value3 = ivals[2]; - } + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!(value1 && value2 && value3)) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); + + std::array ivals{}; + GetProperty(Source, context, static_cast(param), ivals); + *value1 = ivals[0]; + *value2 = ivals[1]; + *value3 = ivals[2]; +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC3(void, alGetSourceiv, ALuint, ALenum, ALint*) +AL_API DECL_FUNC3(void, alGetSourceiv, ALuint,source, ALenum,param, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{IntValsByProp(param)}; - std::ignore = GetProperty(Source, context, static_cast(param), - al::span{values, count}); + GetProperty(Source, context, static_cast(param), al::span{values, count}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetSourcei64,SOFT, ALuint, ALenum, ALint64SOFT*) +AL_API DECL_FUNCEXT3(void, alGetSourcei64,SOFT, ALuint,source, ALenum,param, ALint64SOFT*,value) FORCE_ALIGN void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!value) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!value) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - std::ignore = GetProperty(Source, context, static_cast(param), al::span{value, 1}); + GetProperty(Source, context, static_cast(param), al::span{value, 1u}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT5(void, alGetSource3i64,SOFT, ALuint, ALenum, ALint64SOFT*, ALint64SOFT*, ALint64SOFT*) +AL_API DECL_FUNCEXT5(void, alGetSource3i64,SOFT, ALuint,source, ALenum,param, ALint64SOFT*,value1, ALint64SOFT*,value2, ALint64SOFT*,value3) FORCE_ALIGN void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!(value1 && value2 && value3)) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!(value1 && value2 && value3)) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); - int64_t i64vals[3]; - if(GetProperty(Source, context, static_cast(param), al::span{i64vals})) - { - *value1 = i64vals[0]; - *value2 = i64vals[1]; - *value3 = i64vals[2]; - } + std::array i64vals{}; + GetProperty(Source, context, static_cast(param), i64vals); + *value1 = i64vals[0]; + *value2 = i64vals[1]; + *value3 = i64vals[2]; +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNCEXT3(void, alGetSourcei64v,SOFT, ALuint, ALenum, ALint64SOFT*) +AL_API DECL_FUNCEXT3(void, alGetSourcei64v,SOFT, ALuint,source, ALenum,param, ALint64SOFT*,values) FORCE_ALIGN void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) noexcept -{ - std::lock_guard _{context->mSourceLock}; +try { + std::lock_guard sourcelock{context->mSourceLock}; ALsource *Source{LookupSource(context, source)}; - if(!Source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); - if(!values) UNLIKELY - return context->setError(AL_INVALID_VALUE, "NULL pointer"); + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); + if(!values) + context->throw_error(AL_INVALID_VALUE, "NULL pointer"); const ALuint count{Int64ValsByProp(param)}; - std::ignore = GetProperty(Source, context, static_cast(param), - al::span{values, count}); + GetProperty(Source, context, static_cast(param), al::span{values, count}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC1(void, alSourcePlay, ALuint) +AL_API DECL_FUNC1(void, alSourcePlay, ALuint,source) FORCE_ALIGN void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) noexcept -{ - std::lock_guard _{context->mSourceLock}; - ALsource *srchandle{LookupSource(context, source)}; - if(!srchandle) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); +try { + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - StartSources(context, {&srchandle, 1}); + StartSources(context, {&Source, 1}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -FORCE_ALIGN DECL_FUNCEXT2(void, alSourcePlayAtTime,SOFT, ALuint, ALint64SOFT) +FORCE_ALIGN DECL_FUNCEXT2(void, alSourcePlayAtTime,SOFT, ALuint,source, ALint64SOFT,start_time) FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) noexcept -{ - if(start_time < 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time); +try { + if(start_time < 0) + context->throw_error(AL_INVALID_VALUE, "Invalid time point {}", start_time); - std::lock_guard _{context->mSourceLock}; - ALsource *srchandle{LookupSource(context, source)}; - if(!srchandle) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", source); + std::lock_guard sourcelock{context->mSourceLock}; + ALsource *Source{LookupSource(context, source)}; + if(!Source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", source); - StartSources(context, {&srchandle, 1}, nanoseconds{start_time}); + StartSources(context, {&Source, 1}, nanoseconds{start_time}); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } -AL_API DECL_FUNC2(void, alSourcePlayv, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alSourcePlayv, ALsizei,n, const ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Playing %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Playing {} sources", n); if(n <= 0) UNLIKELY return; - std::vector extra_sources; - std::array source_storage; - al::span srchandles; - if(static_cast(n) <= source_storage.size()) LIKELY - srchandles = al::span{source_storage}.first(static_cast(n)); - else + al::span sids{sources, static_cast(n)}; + source_store_variant source_store; + const auto srchandles = [&source_store](size_t count) -> al::span { - extra_sources.resize(static_cast(n)); - srchandles = extra_sources; - } + if(count > std::tuple_size_v) + return al::span{source_store.emplace(count)}; + return al::span{source_store.emplace()}.first(count); + }(sids.size()); - std::lock_guard _{context->mSourceLock}; - for(auto &srchdl : srchandles) + std::lock_guard sourcelock{context->mSourceLock}; + auto lookup_src = [context](const ALuint sid) -> ALsource* { - srchdl = LookupSource(context, *sources); - if(!srchdl) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources); - ++sources; - } + if(ALsource *src{LookupSource(context, sid)}) + return src; + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", sid); + }; + std::transform(sids.cbegin(), sids.cend(), srchandles.begin(), lookup_src); StartSources(context, srchandles); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -FORCE_ALIGN DECL_FUNCEXT3(void, alSourcePlayAtTimev,SOFT, ALsizei, const ALuint*, ALint64SOFT) +FORCE_ALIGN DECL_FUNCEXT3(void, alSourcePlayAtTimev,SOFT, ALsizei,n, const ALuint*,sources, ALint64SOFT,start_time) FORCE_ALIGN void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Playing %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Playing {} sources", n); if(n <= 0) UNLIKELY return; - if(start_time < 0) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Invalid time point %" PRId64, start_time); + if(start_time < 0) + context->throw_error(AL_INVALID_VALUE, "Invalid time point {}", start_time); - std::vector extra_sources; - std::array source_storage; - al::span srchandles; - if(static_cast(n) <= source_storage.size()) LIKELY - srchandles = al::span{source_storage}.first(static_cast(n)); - else + al::span sids{sources, static_cast(n)}; + source_store_variant source_store; + const auto srchandles = [&source_store](size_t count) -> al::span { - extra_sources.resize(static_cast(n)); - srchandles = extra_sources; - } + if(count > std::tuple_size_v) + return al::span{source_store.emplace(count)}; + return al::span{source_store.emplace()}.first(count); + }(sids.size()); - std::lock_guard _{context->mSourceLock}; - for(auto &srchdl : srchandles) + std::lock_guard sourcelock{context->mSourceLock}; + auto lookup_src = [context](const ALuint sid) -> ALsource* { - srchdl = LookupSource(context, *sources); - if(!srchdl) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources); - ++sources; - } + if(ALsource *src{LookupSource(context, sid)}) + return src; + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", sid); + }; + std::transform(sids.cbegin(), sids.cend(), srchandles.begin(), lookup_src); StartSources(context, srchandles, nanoseconds{start_time}); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC1(void, alSourcePause, ALuint) +AL_API DECL_FUNC1(void, alSourcePause, ALuint,source) FORCE_ALIGN void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) noexcept { alSourcePausevDirect(context, 1, &source); } -AL_API DECL_FUNC2(void, alSourcePausev, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alSourcePausev, ALsizei,n, const ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Pausing %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Pausing {} sources", n); if(n <= 0) UNLIKELY return; - std::vector extra_sources; - std::array source_storage; - al::span srchandles; - if(static_cast(n) <= source_storage.size()) LIKELY - srchandles = al::span{source_storage}.first(static_cast(n)); - else + al::span sids{sources, static_cast(n)}; + source_store_variant source_store; + const auto srchandles = [&source_store](size_t count) -> al::span { - extra_sources.resize(static_cast(n)); - srchandles = extra_sources; - } + if(count > std::tuple_size_v) + return al::span{source_store.emplace(count)}; + return al::span{source_store.emplace()}.first(count); + }(sids.size()); - std::lock_guard _{context->mSourceLock}; - for(auto &srchdl : srchandles) + std::lock_guard sourcelock{context->mSourceLock}; + auto lookup_src = [context](const ALuint sid) -> ALsource* { - srchdl = LookupSource(context, *sources); - if(!srchdl) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources); - ++sources; - } + if(ALsource *src{LookupSource(context, sid)}) + return src; + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", sid); + }; + std::transform(sids.cbegin(), sids.cend(), srchandles.begin(), lookup_src); /* Pausing has to be done in two steps. First, for each source that's * detected to be playing, chamge the voice (asynchronously) to @@ -3256,39 +3393,42 @@ FORCE_ALIGN void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n } } } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC1(void, alSourceStop, ALuint) +AL_API DECL_FUNC1(void, alSourceStop, ALuint,source) FORCE_ALIGN void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) noexcept { alSourceStopvDirect(context, 1, &source); } -AL_API DECL_FUNC2(void, alSourceStopv, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alSourceStopv, ALsizei,n, const ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Stopping %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Stopping {} sources", n); if(n <= 0) UNLIKELY return; - std::vector extra_sources; - std::array source_storage; - al::span srchandles; - if(static_cast(n) <= source_storage.size()) LIKELY - srchandles = al::span{source_storage}.first(static_cast(n)); - else + al::span sids{sources, static_cast(n)}; + source_store_variant source_store; + const auto srchandles = [&source_store](size_t count) -> al::span { - extra_sources.resize(static_cast(n)); - srchandles = extra_sources; - } + if(count > std::tuple_size_v) + return al::span{source_store.emplace(count)}; + return al::span{source_store.emplace()}.first(count); + }(sids.size()); - std::lock_guard _{context->mSourceLock}; - for(auto &srchdl : srchandles) + std::lock_guard sourcelock{context->mSourceLock}; + auto lookup_src = [context](const ALuint sid) -> ALsource* { - srchdl = LookupSource(context, *sources); - if(!srchdl) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources); - ++sources; - } + if(ALsource *src{LookupSource(context, sid)}) + return src; + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", sid); + }; + std::transform(sids.cbegin(), sids.cend(), srchandles.begin(), lookup_src); VoiceChange *tail{}, *cur{}; for(ALsource *source : srchandles) @@ -3310,44 +3450,47 @@ FORCE_ALIGN void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, } source->Offset = 0.0; source->OffsetType = AL_NONE; - source->VoiceIdx = INVALID_VOICE_IDX; + source->VoiceIdx = InvalidVoiceIndex; } if(tail) LIKELY SendVoiceChanges(context, tail); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC1(void, alSourceRewind, ALuint) +AL_API DECL_FUNC1(void, alSourceRewind, ALuint,source) FORCE_ALIGN void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) noexcept { alSourceRewindvDirect(context, 1, &source); } -AL_API DECL_FUNC2(void, alSourceRewindv, ALsizei, const ALuint*) +AL_API DECL_FUNC2(void, alSourceRewindv, ALsizei,n, const ALuint*,sources) FORCE_ALIGN void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) noexcept -{ - if(n < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Rewinding %d sources", n); +try { + if(n < 0) + context->throw_error(AL_INVALID_VALUE, "Rewinding {} sources", n); if(n <= 0) UNLIKELY return; - std::vector extra_sources; - std::array source_storage; - al::span srchandles; - if(static_cast(n) <= source_storage.size()) LIKELY - srchandles = al::span{source_storage}.first(static_cast(n)); - else + al::span sids{sources, static_cast(n)}; + source_store_variant source_store; + const auto srchandles = [&source_store](size_t count) -> al::span { - extra_sources.resize(static_cast(n)); - srchandles = extra_sources; - } + if(count > std::tuple_size_v) + return al::span{source_store.emplace(count)}; + return al::span{source_store.emplace()}.first(count); + }(sids.size()); - std::lock_guard _{context->mSourceLock}; - for(auto &srchdl : srchandles) + std::lock_guard sourcelock{context->mSourceLock}; + auto lookup_src = [context](const ALuint sid) -> ALsource* { - srchdl = LookupSource(context, *sources); - if(!srchdl) - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", *sources); - ++sources; - } + if(ALsource *src{LookupSource(context, sid)}) + return src; + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", sid); + }; + std::transform(sids.cbegin(), sids.cend(), srchandles.begin(), lookup_src); VoiceChange *tail{}, *cur{}; for(ALsource *source : srchandles) @@ -3371,32 +3514,37 @@ FORCE_ALIGN void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei } source->Offset = 0.0; source->OffsetType = AL_NONE; - source->VoiceIdx = INVALID_VOICE_IDX; + source->VoiceIdx = InvalidVoiceIndex; } if(tail) LIKELY SendVoiceChanges(context, tail); } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC3(void, alSourceQueueBuffers, ALuint, ALsizei, const ALuint*) +AL_API DECL_FUNC3(void, alSourceQueueBuffers, ALuint,source, ALsizei,nb, const ALuint*,buffers) FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint src, ALsizei nb, const ALuint *buffers) noexcept -{ - if(nb < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Queueing %d buffers", nb); +try { + if(nb < 0) + context->throw_error(AL_INVALID_VALUE, "Queueing {} buffers", nb); if(nb <= 0) UNLIKELY return; - std::lock_guard _{context->mSourceLock}; + std::lock_guard sourcelock{context->mSourceLock}; ALsource *source{LookupSource(context,src)}; - if(!source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src); + if(!source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", src); /* Can't queue on a Static Source */ - if(source->SourceType == AL_STATIC) UNLIKELY - return context->setError(AL_INVALID_OPERATION, "Queueing onto static source %u", src); + if(source->SourceType == AL_STATIC) + context->throw_error(AL_INVALID_OPERATION, "Queueing onto static source {}", src); /* Check for a valid Buffer, for its frequency and format */ - ALCdevice *device{context->mALDevice.get()}; + auto *device = context->mALDevice.get(); ALbuffer *BufferFmt{nullptr}; for(auto &item : source->mQueue) { @@ -3405,90 +3553,85 @@ FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALu } std::unique_lock buflock{device->BufferLock}; + const auto bids = al::span{buffers, static_cast(nb)}; const size_t NewListStart{source->mQueue.size()}; - ALbufferQueueItem *BufferList{nullptr}; - for(ALsizei i{0};i < nb;i++) - { - bool fmt_mismatch{false}; - ALbuffer *buffer{nullptr}; - if(buffers[i] && (buffer=LookupBuffer(device, buffers[i])) == nullptr) - { - context->setError(AL_INVALID_NAME, "Queueing invalid buffer ID %u", buffers[i]); - goto buffer_error; - } - if(buffer) + try { + ALbufferQueueItem *BufferList{nullptr}; + auto append_buffer = [context,source,device,&BufferFmt,&BufferList](const ALuint bid) { - if(buffer->mSampleRate < 1) - { - context->setError(AL_INVALID_OPERATION, "Queueing buffer %u with no format", - buffer->id); - goto buffer_error; - } - if(buffer->mCallback) - { - context->setError(AL_INVALID_OPERATION, "Queueing callback buffer %u", buffer->id); - goto buffer_error; - } - if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + ALbuffer *buffer{bid ? LookupBuffer(device, bid) : nullptr}; + if(bid && !buffer) + context->throw_error(AL_INVALID_NAME, "Queueing invalid buffer ID {}", bid); + + if(buffer) { - context->setError(AL_INVALID_OPERATION, - "Queueing non-persistently mapped buffer %u", buffer->id); - goto buffer_error; + if(buffer->mSampleRate < 1) + context->throw_error(AL_INVALID_OPERATION, + "Queueing buffer {} with no format", buffer->id); + + if(buffer->mCallback) + context->throw_error(AL_INVALID_OPERATION, "Queueing callback buffer {}", + buffer->id); + + if(buffer->MappedAccess != 0 && !(buffer->MappedAccess&AL_MAP_PERSISTENT_BIT_SOFT)) + context->throw_error(AL_INVALID_OPERATION, + "Queueing non-persistently mapped buffer {}", buffer->id); } - } - source->mQueue.emplace_back(); - if(!BufferList) - BufferList = &source->mQueue.back(); - else - { - auto &item = source->mQueue.back(); - BufferList->mNext.store(&item, std::memory_order_relaxed); - BufferList = &item; - } - if(!buffer) continue; - BufferList->mBlockAlign = buffer->mBlockAlign; - BufferList->mSampleLen = buffer->mSampleLen; - BufferList->mLoopEnd = buffer->mSampleLen; - BufferList->mSamples = buffer->mData.data(); - BufferList->mBuffer = buffer; - IncrementRef(buffer->ref); - - if(BufferFmt == nullptr) - BufferFmt = buffer; - else - { - fmt_mismatch |= BufferFmt->mSampleRate != buffer->mSampleRate; - fmt_mismatch |= BufferFmt->mChannels != buffer->mChannels; - fmt_mismatch |= BufferFmt->mType != buffer->mType; - if(BufferFmt->isBFormat()) + source->mQueue.emplace_back(); + if(!BufferList) + BufferList = &source->mQueue.back(); + else { - fmt_mismatch |= BufferFmt->mAmbiLayout != buffer->mAmbiLayout; - fmt_mismatch |= BufferFmt->mAmbiScaling != buffer->mAmbiScaling; + auto &item = source->mQueue.back(); + BufferList->mNext.store(&item, std::memory_order_relaxed); + BufferList = &item; } - fmt_mismatch |= BufferFmt->mAmbiOrder != buffer->mAmbiOrder; - } - if(fmt_mismatch) UNLIKELY - { - context->setError(AL_INVALID_OPERATION, "Queueing buffer with mismatched format\n" - " Expected: %uhz, %s, %s ; Got: %uhz, %s, %s\n", BufferFmt->mSampleRate, - NameFromFormat(BufferFmt->mType), NameFromFormat(BufferFmt->mChannels), - buffer->mSampleRate, NameFromFormat(buffer->mType), - NameFromFormat(buffer->mChannels)); - - buffer_error: - /* A buffer failed (invalid ID or format), so unlock and release - * each buffer we had. - */ - auto iter = source->mQueue.begin() + ptrdiff_t(NewListStart); - for(;iter != source->mQueue.end();++iter) + if(!buffer) return; + BufferList->mBlockAlign = buffer->mBlockAlign; + BufferList->mSampleLen = buffer->mSampleLen; + BufferList->mLoopEnd = buffer->mSampleLen; + BufferList->mSamples = buffer->mData; + BufferList->mBuffer = buffer; + IncrementRef(buffer->ref); + + if(BufferFmt == nullptr) + BufferFmt = buffer; + else { - if(ALbuffer *buf{iter->mBuffer}) - DecrementRef(buf->ref); + auto fmt_mismatch = false; + fmt_mismatch |= BufferFmt->mSampleRate != buffer->mSampleRate; + fmt_mismatch |= BufferFmt->mChannels != buffer->mChannels; + fmt_mismatch |= BufferFmt->mType != buffer->mType; + if(BufferFmt->isBFormat()) + { + fmt_mismatch |= BufferFmt->mAmbiLayout != buffer->mAmbiLayout; + fmt_mismatch |= BufferFmt->mAmbiScaling != buffer->mAmbiScaling; + } + fmt_mismatch |= BufferFmt->mAmbiOrder != buffer->mAmbiOrder; + if(fmt_mismatch) + context->throw_error(AL_INVALID_OPERATION, + "Queueing buffer with mismatched format\n" + " Expected: {}hz, {}, {} ; Got: {}hz, {}, {}\n", BufferFmt->mSampleRate, + NameFromFormat(BufferFmt->mType), NameFromFormat(BufferFmt->mChannels), + buffer->mSampleRate, NameFromFormat(buffer->mType), + NameFromFormat(buffer->mChannels)); } - source->mQueue.resize(NewListStart); - return; + }; + std::for_each(bids.cbegin(), bids.cend(), append_buffer); + } + catch(...) { + /* A buffer failed (invalid ID or format), or there was some other + * unexpected error, so unlock and release each buffer we had. + */ + auto iter = source->mQueue.begin() + ptrdiff_t(NewListStart); + for(;iter != source->mQueue.end();++iter) + { + if(ALbuffer *buf{iter->mBuffer}) + DecrementRef(buf->ref); } + source->mQueue.resize(NewListStart); + throw; } /* All buffers good. */ buflock.unlock(); @@ -3502,28 +3645,33 @@ FORCE_ALIGN void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALu (iter-1)->mNext.store(al::to_address(iter), std::memory_order_release); } } +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); +} -AL_API DECL_FUNC3(void, alSourceUnqueueBuffers, ALuint, ALsizei, ALuint*) +AL_API DECL_FUNC3(void, alSourceUnqueueBuffers, ALuint,source, ALsizei,nb, ALuint*,buffers) FORCE_ALIGN void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint src, ALsizei nb, ALuint *buffers) noexcept -{ - if(nb < 0) UNLIKELY - context->setError(AL_INVALID_VALUE, "Unqueueing %d buffers", nb); +try { + if(nb < 0) + context->throw_error(AL_INVALID_VALUE, "Unqueueing {} buffers", nb); if(nb <= 0) UNLIKELY return; - std::lock_guard _{context->mSourceLock}; + std::lock_guard sourcelock{context->mSourceLock}; ALsource *source{LookupSource(context,src)}; - if(!source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", src); + if(!source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", src); - if(source->SourceType != AL_STREAMING) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Unqueueing from a non-streaming source %u", - src); - if(source->Looping) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Unqueueing from looping source %u", src); + if(source->SourceType != AL_STREAMING) + context->throw_error(AL_INVALID_VALUE, "Unqueueing from a non-streaming source {}", src); + if(source->Looping) + context->throw_error(AL_INVALID_VALUE, "Unqueueing from looping source {}", src); /* Make sure enough buffers have been processed to unqueue. */ - uint processed{0u}; + const al::span bids{buffers, static_cast(nb)}; + size_t processed{0}; if(source->state != AL_INITIAL) LIKELY { VoiceBufferItem *Current{nullptr}; @@ -3536,21 +3684,27 @@ FORCE_ALIGN void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, A ++processed; } } - if(processed < static_cast(nb)) UNLIKELY - return context->setError(AL_INVALID_VALUE, "Unqueueing %d buffer%s (only %u processed)", - nb, (nb==1)?"":"s", processed); + if(processed < bids.size()) + context->throw_error(AL_INVALID_VALUE, "Unqueueing {} buffer{} (only {} processed)", + nb, (nb==1) ? "" : "s", processed); - do { + std::generate(bids.begin(), bids.end(), [source]() noexcept -> ALuint + { auto &head = source->mQueue.front(); + ALuint bid{0}; if(ALbuffer *buffer{head.mBuffer}) { - *(buffers++) = buffer->id; + bid = buffer->id; DecrementRef(buffer->ref); } - else - *(buffers++) = 0; source->mQueue.pop_front(); - } while(--nb); + return bid; + }); +} +catch(al::base_exception&) { +} +catch(std::exception &e) { + ERR("Caught exception: {}", e.what()); } @@ -3563,21 +3717,21 @@ AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint, ALsizei, const ALu } -ALsource::ALsource() +ALsource::ALsource() noexcept { Direct.Gain = 1.0f; Direct.GainHF = 1.0f; - Direct.HFReference = LOWPASSFREQREF; + Direct.HFReference = LowPassFreqRef; Direct.GainLF = 1.0f; - Direct.LFReference = HIGHPASSFREQREF; + Direct.LFReference = HighPassFreqRef; for(auto &send : Send) { send.Slot = nullptr; send.Gain = 1.0f; send.GainHF = 1.0f; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; } } @@ -3596,13 +3750,13 @@ ALsource::~ALsource() void UpdateAllSourceProps(ALCcontext *context) { - std::lock_guard _{context->mSourceLock}; + std::lock_guard srclock{context->mSourceLock}; auto voicelist = context->getVoicesSpan(); ALuint vidx{0u}; for(Voice *voice : voicelist) { ALuint sid{voice->mSourceID.load(std::memory_order_acquire)}; - ALsource *source = sid ? LookupSource(context, sid) : nullptr; + ALsource *source{sid ? LookupSource(context, sid) : nullptr}; if(source && source->VoiceIdx == vidx) { if(std::exchange(source->mPropsDirty, false)) @@ -3614,11 +3768,11 @@ void UpdateAllSourceProps(ALCcontext *context) void ALsource::SetName(ALCcontext *context, ALuint id, std::string_view name) { - std::lock_guard _{context->mSourceLock}; + std::lock_guard srclock{context->mSourceLock}; auto source = LookupSource(context, id); - if(!source) UNLIKELY - return context->setError(AL_INVALID_NAME, "Invalid source ID %u", id); + if(!source) + context->throw_error(AL_INVALID_NAME, "Invalid source ID {}", id); context->mSourceNames.insert_or_assign(id, name); } @@ -3634,18 +3788,15 @@ SourceSubList::~SourceSubList() { const int idx{al::countr_zero(usemask)}; usemask &= ~(1_u64 << idx); - std::destroy_at(Sources+idx); + std::destroy_at(al::to_address(Sources->begin() + idx)); } FreeMask = ~usemask; - al_free(Sources); + SubListAllocator{}.deallocate(Sources, 1); Sources = nullptr; } -#ifdef ALSOFT_EAX -constexpr const ALsource::EaxFxSlotIds ALsource::eax4_fx_slot_ids; -constexpr const ALsource::EaxFxSlotIds ALsource::eax5_fx_slot_ids; - +#if ALSOFT_EAX void ALsource::eaxInitialize(ALCcontext *context) noexcept { assert(context != nullptr); @@ -3659,11 +3810,6 @@ void ALsource::eaxInitialize(ALCcontext *context) noexcept mEaxChanged = true; } -void ALsource::eaxDispatch(const EaxCall& call) -{ - call.is_get() ? eax_get(call) : eax_set(call); -} - ALsource* ALsource::EaxLookupSource(ALCcontext& al_context, ALuint source_id) noexcept { return LookupSource(&al_context, source_id); @@ -3711,7 +3857,7 @@ void ALsource::eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) } } -void ALsource::eax1_set_defaults(Eax1Props& props) noexcept +void ALsource::eax1_set_defaults(EAXBUFFER_REVERBPROPERTIES& props) noexcept { props.fMix = EAX_REVERBMIX_USEDISTANCE; } @@ -3722,7 +3868,7 @@ void ALsource::eax1_set_defaults() noexcept mEax1.d = mEax1.i; } -void ALsource::eax2_set_defaults(Eax2Props& props) noexcept +void ALsource::eax2_set_defaults(EAX20BUFFERPROPERTIES& props) noexcept { props.lDirect = EAXSOURCE_DEFAULTDIRECT; props.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF; @@ -3745,7 +3891,7 @@ void ALsource::eax2_set_defaults() noexcept mEax2.d = mEax2.i; } -void ALsource::eax3_set_defaults(Eax3Props& props) noexcept +void ALsource::eax3_set_defaults(EAX30SOURCEPROPERTIES& props) noexcept { props.lDirect = EAXSOURCE_DEFAULTDIRECT; props.lDirectHF = EAXSOURCE_DEFAULTDIRECTHF; @@ -3793,7 +3939,7 @@ void ALsource::eax4_set_defaults() noexcept void ALsource::eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept { - eax3_set_defaults(static_cast(props)); + eax3_set_defaults(static_cast(props)); props.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR; } @@ -3840,7 +3986,7 @@ void ALsource::eax_set_defaults() noexcept eax5_set_defaults(); } -void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept +void ALsource::eax1_translate(const EAXBUFFER_REVERBPROPERTIES& src, Eax5Props& dst) noexcept { eax5_set_defaults(dst); @@ -3857,7 +4003,7 @@ void ALsource::eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept } } -void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept +void ALsource::eax2_translate(const EAX20BUFFERPROPERTIES& src, Eax5Props& dst) noexcept { // Source. // @@ -3888,11 +4034,11 @@ void ALsource::eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept eax5_set_speaker_levels_defaults(dst.speaker_levels); } -void ALsource::eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept +void ALsource::eax3_translate(const EAX30SOURCEPROPERTIES& src, Eax5Props& dst) noexcept { // Source. // - static_cast(dst.source) = src; + static_cast(dst.source) = src; dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR; // Set everything else to defaults. @@ -3906,7 +4052,7 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept { // Source. // - static_cast(dst.source) = src.source; + static_cast(dst.source) = src.source; dst.source.flMacroFXFactor = EAXSOURCE_DEFAULTMACROFXFACTOR; // Sends. @@ -3918,29 +4064,30 @@ void ALsource::eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept // Active FX slots. // - for (auto i = 0; i < EAX50_MAX_ACTIVE_FXSLOTS; ++i) { - auto& dst_id = dst.active_fx_slots.guidActiveFXSlots[i]; - - if (i < EAX40_MAX_ACTIVE_FXSLOTS) { - const auto& src_id = src.active_fx_slots.guidActiveFXSlots[i]; - - if (src_id == EAX_NULL_GUID) - dst_id = EAX_NULL_GUID; - else if (src_id == EAX_PrimaryFXSlotID) - dst_id = EAX_PrimaryFXSlotID; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot0) - dst_id = EAXPROPERTYID_EAX50_FXSlot0; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot1) - dst_id = EAXPROPERTYID_EAX50_FXSlot1; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot2) - dst_id = EAXPROPERTYID_EAX50_FXSlot2; - else if (src_id == EAXPROPERTYID_EAX40_FXSlot3) - dst_id = EAXPROPERTYID_EAX50_FXSlot3; - else - assert(false && "Unknown active FX slot ID."); - } else - dst_id = EAX_NULL_GUID; - } + auto translate_slotid = [](const GUID &src_id) -> GUID + { + if(src_id == EAX_NULL_GUID) + return EAX_NULL_GUID; + if(src_id == EAX_PrimaryFXSlotID) + return EAX_PrimaryFXSlotID; + if(src_id == EAXPROPERTYID_EAX40_FXSlot0) + return EAXPROPERTYID_EAX50_FXSlot0; + if(src_id == EAXPROPERTYID_EAX40_FXSlot1) + return EAXPROPERTYID_EAX50_FXSlot1; + if(src_id == EAXPROPERTYID_EAX40_FXSlot2) + return EAXPROPERTYID_EAX50_FXSlot2; + if(src_id == EAXPROPERTYID_EAX40_FXSlot3) + return EAXPROPERTYID_EAX50_FXSlot3; + + UNLIKELY + ERR("Unexpected active FX slot ID"); + return EAX_NULL_GUID; + }; + const auto src_slots = al::span{src.active_fx_slots.guidActiveFXSlots}; + const auto dst_slots = al::span{dst.active_fx_slots.guidActiveFXSlots}; + auto dstiter = std::transform(src_slots.cbegin(), src_slots.cend(), dst_slots.begin(), + translate_slotid); + std::fill(dstiter, dst_slots.end(), EAX_NULL_GUID); // Speaker levels. // @@ -3961,62 +4108,55 @@ float ALsource::eax_calculate_dst_occlusion_mb( EaxAlLowPassParam ALsource::eax_create_direct_filter_param() const noexcept { - auto gain_mb = - static_cast(mEax.source.lDirect) + - (static_cast(mEax.source.lObstruction) * mEax.source.flObstructionLFRatio) + - eax_calculate_dst_occlusion_mb( - mEax.source.lOcclusion, - mEax.source.flOcclusionDirectRatio, - mEax.source.flOcclusionLFRatio); + const auto &source = mEax.source; - const auto has_source_occlusion = (mEax.source.lOcclusion != 0); - - auto gain_hf_mb = - static_cast(mEax.source.lDirectHF) + - static_cast(mEax.source.lObstruction); + auto gain_mb = static_cast(source.lObstruction) * source.flObstructionLFRatio; + auto gainhf_mb = static_cast(source.lObstruction); for(size_t i{0};i < EAX_MAX_FXSLOTS;++i) { if(!mEaxActiveFxSlots[i]) continue; - if(has_source_occlusion) + if(source.lOcclusion != 0) { const auto& fx_slot = mEaxAlContext->eaxGetFxSlot(i); const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); - const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); + const auto is_environmental_fx = ((fx_slot_eax.ulFlags&EAXFXSLOTFLAGS_ENVIRONMENT) != 0); const auto is_primary = (mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index()); - const auto is_listener_environment = (is_environmental_fx && is_primary); - if(is_listener_environment) + if(is_environmental_fx && is_primary) { - gain_mb += eax_calculate_dst_occlusion_mb( - mEax.source.lOcclusion, - mEax.source.flOcclusionDirectRatio, - mEax.source.flOcclusionLFRatio); + gain_mb += eax_calculate_dst_occlusion_mb(source.lOcclusion, + source.flOcclusionDirectRatio, source.flOcclusionLFRatio); - gain_hf_mb += static_cast(mEax.source.lOcclusion) * mEax.source.flOcclusionDirectRatio; + gainhf_mb += static_cast(source.lOcclusion) * source.flOcclusionDirectRatio; } } const auto& send = mEax.sends[i]; - if(send.lOcclusion != 0) { - gain_mb += eax_calculate_dst_occlusion_mb( - send.lOcclusion, - send.flOcclusionDirectRatio, + gain_mb += eax_calculate_dst_occlusion_mb(send.lOcclusion, send.flOcclusionDirectRatio, send.flOcclusionLFRatio); - gain_hf_mb += static_cast(send.lOcclusion) * send.flOcclusionDirectRatio; + gainhf_mb += static_cast(send.lOcclusion) * send.flOcclusionDirectRatio; } } - const auto al_low_pass_param = EaxAlLowPassParam{ - level_mb_to_gain(gain_mb), - minf(level_mb_to_gain(gain_hf_mb), 1.0f)}; + /* gainhf_mb is the absolute mBFS of the filter's high-frequency volume, + * and gain_mb is the absolute mBFS of the filter's low-frequency volume. + * Adjust the HF volume to be relative to the LF volume, to make the + * appropriate main and relative HF filter volumes. + * + * Also add the Direct and DirectHF properties to the filter, which are + * already the main and relative HF volumes. + */ + gainhf_mb -= gain_mb - static_cast(source.lDirectHF); + gain_mb += static_cast(source.lDirect); - return al_low_pass_param; + return EaxAlLowPassParam{level_mb_to_gain(gain_mb), + std::min(level_mb_to_gain(gainhf_mb), 1.0f)}; } EaxAlLowPassParam ALsource::eax_create_room_filter_param( @@ -4024,44 +4164,40 @@ EaxAlLowPassParam ALsource::eax_create_room_filter_param( const EAXSOURCEALLSENDPROPERTIES& send) const noexcept { const auto& fx_slot_eax = fx_slot.eax_get_eax_fx_slot(); - const auto is_environmental_fx = ((fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0); - const auto is_primary = (mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index()); - const auto is_listener_environment = (is_environmental_fx && is_primary); - - const auto gain_mb = - (static_cast(fx_slot_eax.lOcclusion) * fx_slot_eax.flOcclusionLFRatio) + - static_cast((is_environmental_fx ? mEax.source.lRoom : 0) + send.lSend) + - (is_listener_environment ? - eax_calculate_dst_occlusion_mb( - mEax.source.lOcclusion, - mEax.source.flOcclusionRoomRatio, - mEax.source.flOcclusionLFRatio) : - 0.0f) + - eax_calculate_dst_occlusion_mb( - send.lOcclusion, - send.flOcclusionRoomRatio, - send.flOcclusionLFRatio) + - (is_listener_environment ? - (static_cast(mEax.source.lExclusion) * mEax.source.flExclusionLFRatio) : - 0.0f) + - (static_cast(send.lExclusion) * send.flExclusionLFRatio); - - const auto gain_hf_mb = - static_cast(fx_slot_eax.lOcclusion) + - static_cast((is_environmental_fx ? mEax.source.lRoomHF : 0) + send.lSendHF) + - (is_listener_environment ? - ((static_cast(mEax.source.lOcclusion) * mEax.source.flOcclusionRoomRatio)) : - 0.0f) + - (static_cast(send.lOcclusion) * send.flOcclusionRoomRatio) + - (is_listener_environment ? - static_cast(mEax.source.lExclusion + send.lExclusion) : - 0.0f); - - const auto al_low_pass_param = EaxAlLowPassParam{ - level_mb_to_gain(gain_mb), - minf(level_mb_to_gain(gain_hf_mb), 1.0f)}; - - return al_low_pass_param; + const auto is_environmental_fx = bool{(fx_slot_eax.ulFlags & EAXFXSLOTFLAGS_ENVIRONMENT) != 0}; + const auto is_primary = bool{mEaxPrimaryFxSlotId.value_or(-1) == fx_slot.eax_get_index()}; + + auto gain_mb = (static_cast(fx_slot_eax.lOcclusion) * fx_slot_eax.flOcclusionLFRatio) + + eax_calculate_dst_occlusion_mb(send.lOcclusion, send.flOcclusionRoomRatio, + send.flOcclusionLFRatio) + + (static_cast(send.lExclusion) * send.flExclusionLFRatio); + + auto gainhf_mb = static_cast(fx_slot_eax.lOcclusion) + + (static_cast(send.lOcclusion) * send.flOcclusionRoomRatio); + + if(is_environmental_fx && is_primary) + { + const auto &source = mEax.source; + + gain_mb += eax_calculate_dst_occlusion_mb(source.lOcclusion, source.flOcclusionRoomRatio, + source.flOcclusionLFRatio); + gain_mb += static_cast(source.lExclusion) * source.flExclusionLFRatio; + + gainhf_mb += static_cast(source.lOcclusion) * source.flOcclusionRoomRatio; + gainhf_mb += static_cast(source.lExclusion + send.lExclusion); + } + + gainhf_mb -= gain_mb - static_cast(send.lSendHF); + gain_mb += static_cast(send.lSend); + if(is_environmental_fx) + { + const auto &source = mEax.source; + gain_mb += static_cast(source.lRoom); + gainhf_mb += static_cast(source.lRoomHF); + } + + return EaxAlLowPassParam{level_mb_to_gain(gain_mb), + std::min(level_mb_to_gain(gainhf_mb), 1.0f)}; } void ALsource::eax_update_direct_filter() @@ -4069,9 +4205,9 @@ void ALsource::eax_update_direct_filter() const auto& direct_param = eax_create_direct_filter_param(); Direct.Gain = direct_param.gain; Direct.GainHF = direct_param.gain_hf; - Direct.HFReference = LOWPASSFREQREF; + Direct.HFReference = LowPassFreqRef; Direct.GainLF = 1.0f; - Direct.LFReference = HIGHPASSFREQREF; + Direct.LFReference = HighPassFreqRef; mPropsDirty = true; } @@ -4132,7 +4268,7 @@ void ALsource::eax_set_efx_wet_gain_hf_auto() WetGainHFAuto = ((mEax.source.ulFlags & EAXSOURCEFLAGS_ROOMHFAUTO) != 0); } -void ALsource::eax1_set(const EaxCall& call, Eax1Props& props) +void ALsource::eax1_set(const EaxCall& call, EAXBUFFER_REVERBPROPERTIES& props) { switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: @@ -4148,7 +4284,7 @@ void ALsource::eax1_set(const EaxCall& call, Eax1Props& props) } } -void ALsource::eax2_set(const EaxCall& call, Eax2Props& props) +void ALsource::eax2_set(const EaxCall& call, EAX20BUFFERPROPERTIES& props) { switch (call.get_property_id()) { case DSPROPERTY_EAX20BUFFER_NONE: @@ -4215,7 +4351,7 @@ void ALsource::eax2_set(const EaxCall& call, Eax2Props& props) } } -void ALsource::eax3_set(const EaxCall& call, Eax3Props& props) +void ALsource::eax3_set(const EaxCall& call, EAX30SOURCEPROPERTIES& props) { switch (call.get_property_id()) { case EAXSOURCE_NONE: @@ -4360,7 +4496,7 @@ void ALsource::eax4_set(const EaxCall& call, Eax4Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax4_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); + eax4_defer_active_fx_slot_id(call, al::span{props.active_fx_slots.guidActiveFXSlots}); break; default: @@ -4420,10 +4556,13 @@ void ALsource::eax5_set(const EaxCall& call, Eax5Props& props) case EAXSOURCE_ROLLOFFFACTOR: case EAXSOURCE_ROOMROLLOFFFACTOR: case EAXSOURCE_AIRABSORPTIONFACTOR: - case EAXSOURCE_FLAGS: eax3_set(call, props.source); break; + case EAXSOURCE_FLAGS: + eax_defer(call, props.source.ulFlags); + break; + case EAXSOURCE_SENDPARAMETERS: eax5_defer_sends(call, props.sends); break; @@ -4441,7 +4580,7 @@ void ALsource::eax5_set(const EaxCall& call, Eax5Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax5_defer_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); + eax5_defer_active_fx_slot_id(call, al::span{props.active_fx_slots.guidActiveFXSlots}); break; case EAXSOURCE_MACROFXFACTOR: @@ -4477,16 +4616,14 @@ void ALsource::eax_set(const EaxCall& call) mEaxVersion = eax_version; } -void ALsource::eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, size_t max_count) +void ALsource::eax_get_active_fx_slot_id(const EaxCall& call, const al::span src_ids) { - assert(ids != nullptr); - assert(max_count == EAX40_MAX_ACTIVE_FXSLOTS || max_count == EAX50_MAX_ACTIVE_FXSLOTS); - const auto dst_ids = call.get_values(max_count); - const auto count = dst_ids.size(); - std::uninitialized_copy_n(ids, count, dst_ids.begin()); + assert(src_ids.size()==EAX40_MAX_ACTIVE_FXSLOTS || src_ids.size()==EAX50_MAX_ACTIVE_FXSLOTS); + const auto dst_ids = call.get_values(src_ids.size()); + std::uninitialized_copy_n(src_ids.begin(), dst_ids.size(), dst_ids.begin()); } -void ALsource::eax1_get(const EaxCall& call, const Eax1Props& props) +void ALsource::eax1_get(const EaxCall& call, const EAXBUFFER_REVERBPROPERTIES& props) { switch (call.get_property_id()) { case DSPROPERTY_EAXBUFFER_ALL: @@ -4499,7 +4636,7 @@ void ALsource::eax1_get(const EaxCall& call, const Eax1Props& props) } } -void ALsource::eax2_get(const EaxCall& call, const Eax2Props& props) +void ALsource::eax2_get(const EaxCall& call, const EAX20BUFFERPROPERTIES& props) { switch (call.get_property_id()) { case DSPROPERTY_EAX20BUFFER_NONE: @@ -4566,25 +4703,25 @@ void ALsource::eax2_get(const EaxCall& call, const Eax2Props& props) } } -void ALsource::eax3_get_obstruction(const EaxCall& call, const Eax3Props& props) +void ALsource::eax3_get_obstruction(const EaxCall& call, const EAX30SOURCEPROPERTIES& props) { const auto& subprops = reinterpret_cast(props.lObstruction); call.set_value(subprops); } -void ALsource::eax3_get_occlusion(const EaxCall& call, const Eax3Props& props) +void ALsource::eax3_get_occlusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props) { const auto& subprops = reinterpret_cast(props.lOcclusion); call.set_value(subprops); } -void ALsource::eax3_get_exclusion(const EaxCall& call, const Eax3Props& props) +void ALsource::eax3_get_exclusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props) { const auto& subprops = reinterpret_cast(props.lExclusion); call.set_value(subprops); } -void ALsource::eax3_get(const EaxCall& call, const Eax3Props& props) +void ALsource::eax3_get(const EaxCall& call, const EAX30SOURCEPROPERTIES& props) { switch (call.get_property_id()) { case EAXSOURCE_NONE: @@ -4731,7 +4868,7 @@ void ALsource::eax4_get(const EaxCall& call, const Eax4Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX40_MAX_ACTIVE_FXSLOTS); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); break; default: @@ -4803,7 +4940,7 @@ void ALsource::eax5_get(const EaxCall& call, const Eax5Props& props) break; case EAXSOURCE_ACTIVEFXSLOTID: - eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots, EAX50_MAX_ACTIVE_FXSLOTS); + eax_get_active_fx_slot_id(call, props.active_fx_slots.guidActiveFXSlots); break; case EAXSOURCE_MACROFXFACTOR: @@ -4843,9 +4980,9 @@ void ALsource::eax_set_al_source_send(ALeffectslot *slot, size_t sendidx, const auto &send = Send[sendidx]; send.Gain = filter.gain; send.GainHF = filter.gain_hf; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; if(slot != nullptr) IncrementRef(slot->ref); diff --git a/3rdparty/openal/al/source.h b/3rdparty/openal/al/source.h index 2bdeb2a385b1..7d56e3a57a67 100644 --- a/3rdparty/openal/al/source.h +++ b/3rdparty/openal/al/source.h @@ -1,28 +1,29 @@ #ifndef AL_SOURCE_H #define AL_SOURCE_H +#include "config.h" + #include -#include #include +#include #include -#include #include #include +#include #include "AL/al.h" #include "AL/alc.h" +#include "AL/alext.h" -#include "alc/alu.h" -#include "alc/context.h" -#include "alc/inprogext.h" -#include "aldeque.h" #include "almalloc.h" +#include "alnumbers.h" #include "alnumeric.h" -#include "atomic.h" +#include "alspan.h" +#include "core/context.h" #include "core/voice.h" -#include "vector.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX +#include "eax/api.h" #include "eax/call.h" #include "eax/exception.h" #include "eax/fx_slot_index.h" @@ -31,27 +32,25 @@ struct ALbuffer; struct ALeffectslot; - +enum class Resampler : uint8_t; enum class SourceStereo : bool { Normal = AL_NORMAL_SOFT, Enhanced = AL_SUPER_STEREO_SOFT }; -#define DEFAULT_SENDS 2 +inline constexpr size_t DefaultSendCount{2}; -#define INVALID_VOICE_IDX static_cast(-1) +inline constexpr ALuint InvalidVoiceIndex{std::numeric_limits::max()}; -extern bool sBufferSubDataCompat; +inline bool sBufferSubDataCompat{false}; struct ALbufferQueueItem : public VoiceBufferItem { ALbuffer *mBuffer{nullptr}; - - DISABLE_ALLOC() }; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX class EaxSourceException : public EaxException { public: explicit EaxSourceException(const char* message) @@ -72,7 +71,7 @@ struct ALsource { float RefDistance{1.0f}; float MaxDistance{std::numeric_limits::max()}; float RolloffFactor{1.0f}; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX // For EAXSOURCE_ROLLOFFFACTOR, which is distinct from and added to // AL_ROLLOFF_FACTOR float RolloffFactor2{0.0f}; @@ -89,6 +88,7 @@ struct ALsource { DirectMode DirectChannels{DirectMode::Off}; SpatializeMode mSpatialize{SpatializeMode::Auto}; SourceStereo mStereoMode{SourceStereo::Normal}; + bool mPanningEnabled{false}; bool DryGainHFAuto{true}; bool WetGainAuto{true}; @@ -106,24 +106,27 @@ struct ALsource { float Radius{0.0f}; float EnhWidth{0.593f}; + float mPan{0.0f}; /** Direct filter and auxiliary send info. */ - struct { - float Gain; - float GainHF; - float HFReference; - float GainLF; - float LFReference; - } Direct; + struct DirectData { + float Gain{}; + float GainHF{}; + float HFReference{}; + float GainLF{}; + float LFReference{}; + }; + DirectData Direct; + struct SendData { - ALeffectslot *Slot; - float Gain; - float GainHF; - float HFReference; - float GainLF; - float LFReference; + ALeffectslot *Slot{}; + float Gain{}; + float GainHF{}; + float HFReference{}; + float GainLF{}; + float LFReference{}; }; - std::array Send; + std::array Send; /** * Last user-specified offset, and the offset type (bytes, samples, or @@ -139,20 +142,20 @@ struct ALsource { ALenum state{AL_INITIAL}; /** Source Buffer Queue head. */ - al::deque mQueue; + std::deque mQueue; bool mPropsDirty{true}; /* Index into the context's Voices array. Lazily updated, only checked and * reset when looking up the voice. */ - ALuint VoiceIdx{INVALID_VOICE_IDX}; + ALuint VoiceIdx{InvalidVoiceIndex}; /** Self ID */ ALuint id{0}; - ALsource(); + ALsource() noexcept; ~ALsource(); ALsource(const ALsource&) = delete; @@ -160,12 +163,12 @@ struct ALsource { static void SetName(ALCcontext *context, ALuint id, std::string_view name); - DISABLE_ALLOC() + DISABLE_ALLOC -#ifdef ALSOFT_EAX +#if ALSOFT_EAX public: void eaxInitialize(ALCcontext *context) noexcept; - void eaxDispatch(const EaxCall& call); + void eaxDispatch(const EaxCall& call) { call.is_get() ? eax_get(call) : eax_set(call); } void eaxCommit(); void eaxMarkAsChanged() noexcept { mEaxChanged = true; } @@ -174,18 +177,18 @@ struct ALsource { private: using Exception = EaxSourceException; - static constexpr auto eax_max_speakers = 9; + static constexpr auto eax_max_speakers{9u}; - using EaxFxSlotIds = const GUID* [EAX_MAX_FXSLOTS]; + using EaxFxSlotIds = std::array; - static constexpr const EaxFxSlotIds eax4_fx_slot_ids = { + static constexpr const EaxFxSlotIds eax4_fx_slot_ids{ &EAXPROPERTYID_EAX40_FXSlot0, &EAXPROPERTYID_EAX40_FXSlot1, &EAXPROPERTYID_EAX40_FXSlot2, &EAXPROPERTYID_EAX40_FXSlot3, }; - static constexpr const EaxFxSlotIds eax5_fx_slot_ids = { + static constexpr const EaxFxSlotIds eax5_fx_slot_ids{ &EAXPROPERTYID_EAX50_FXSlot0, &EAXPROPERTYID_EAX50_FXSlot1, &EAXPROPERTYID_EAX50_FXSlot2, @@ -196,33 +199,25 @@ struct ALsource { using EaxSpeakerLevels = std::array; using EaxSends = std::array; - using Eax1Props = EAXBUFFER_REVERBPROPERTIES; struct Eax1State { - Eax1Props i; // Immediate. - Eax1Props d; // Deferred. + EAXBUFFER_REVERBPROPERTIES i; // Immediate. + EAXBUFFER_REVERBPROPERTIES d; // Deferred. }; - using Eax2Props = EAX20BUFFERPROPERTIES; struct Eax2State { - Eax2Props i; // Immediate. - Eax2Props d; // Deferred. + EAX20BUFFERPROPERTIES i; // Immediate. + EAX20BUFFERPROPERTIES d; // Deferred. }; - using Eax3Props = EAX30SOURCEPROPERTIES; struct Eax3State { - Eax3Props i; // Immediate. - Eax3Props d; // Deferred. + EAX30SOURCEPROPERTIES i; // Immediate. + EAX30SOURCEPROPERTIES d; // Deferred. }; struct Eax4Props { - Eax3Props source; + EAX30SOURCEPROPERTIES source; EaxSends sends; EAX40ACTIVEFXSLOTS active_fx_slots; - - bool operator==(const Eax4Props& rhs) noexcept - { - return std::memcmp(this, &rhs, sizeof(Eax4Props)) == 0; - } }; struct Eax4State { @@ -235,11 +230,6 @@ struct ALsource { EaxSends sends; EAX50ACTIVEFXSLOTS active_fx_slots; EaxSpeakerLevels speaker_levels; - - bool operator==(const Eax5Props& rhs) noexcept - { - return std::memcmp(this, &rhs, sizeof(Eax5Props)) == 0; - } }; struct Eax5State { @@ -497,14 +487,14 @@ struct ALsource { }; struct Eax1SourceAllValidator { - void operator()(const Eax1Props& props) const + void operator()(const EAXBUFFER_REVERBPROPERTIES& props) const { Eax1SourceReverbMixValidator{}(props.fMix); } }; struct Eax2SourceAllValidator { - void operator()(const Eax2Props& props) const + void operator()(const EAX20BUFFERPROPERTIES& props) const { Eax2SourceDirectValidator{}(props.lDirect); Eax2SourceDirectHfValidator{}(props.lDirectHF); @@ -523,7 +513,7 @@ struct ALsource { }; struct Eax3SourceAllValidator { - void operator()(const Eax3Props& props) const + void operator()(const EAX30SOURCEPROPERTIES& props) const { Eax2SourceDirectValidator{}(props.lDirect); Eax2SourceDirectHfValidator{}(props.lDirectHF); @@ -549,7 +539,24 @@ struct ALsource { struct Eax5SourceAllValidator { void operator()(const EAX50SOURCEPROPERTIES& props) const { - Eax3SourceAllValidator{}(static_cast(props)); + Eax2SourceDirectValidator{}(props.lDirect); + Eax2SourceDirectHfValidator{}(props.lDirectHF); + Eax2SourceRoomValidator{}(props.lRoom); + Eax2SourceRoomHfValidator{}(props.lRoomHF); + Eax2SourceObstructionValidator{}(props.lObstruction); + Eax2SourceObstructionLfRatioValidator{}(props.flObstructionLFRatio); + Eax2SourceOcclusionValidator{}(props.lOcclusion); + Eax2SourceOcclusionLfRatioValidator{}(props.flOcclusionLFRatio); + Eax2SourceOcclusionRoomRatioValidator{}(props.flOcclusionRoomRatio); + Eax3SourceOcclusionDirectRatioValidator{}(props.flOcclusionDirectRatio); + Eax3SourceExclusionValidator{}(props.lExclusion); + Eax3SourceExclusionLfRatioValidator{}(props.flExclusionLFRatio); + Eax2SourceOutsideVolumeHfValidator{}(props.lOutsideVolumeHF); + Eax3SourceDopplerFactorValidator{}(props.flDopplerFactor); + Eax3SourceRolloffFactorValidator{}(props.flRolloffFactor); + Eax2SourceRoomRolloffFactorValidator{}(props.flRoomRolloffFactor); + Eax2SourceAirAbsorptionFactorValidator{}(props.flAirAbsorptionFactor); + Eax5SourceFlagsValidator{}(props.ulFlags); Eax5SourceMacroFXFactorValidator{}(props.flMacroFXFactor); } }; @@ -812,39 +819,38 @@ struct ALsource { [[noreturn]] static void eax_fail_unknown_active_fx_slot_id(); [[noreturn]] static void eax_fail_unknown_receiving_fx_slot_id(); - void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept; - void eax1_set_defaults(Eax1Props& props) noexcept; + static void eax_set_sends_defaults(EaxSends& sends, const EaxFxSlotIds& ids) noexcept; + static void eax1_set_defaults(EAXBUFFER_REVERBPROPERTIES& props) noexcept; void eax1_set_defaults() noexcept; - void eax2_set_defaults(Eax2Props& props) noexcept; + static void eax2_set_defaults(EAX20BUFFERPROPERTIES& props) noexcept; void eax2_set_defaults() noexcept; - void eax3_set_defaults(Eax3Props& props) noexcept; + static void eax3_set_defaults(EAX30SOURCEPROPERTIES& props) noexcept; void eax3_set_defaults() noexcept; - void eax4_set_sends_defaults(EaxSends& sends) noexcept; - void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept; + static void eax4_set_sends_defaults(EaxSends& sends) noexcept; + static void eax4_set_active_fx_slots_defaults(EAX40ACTIVEFXSLOTS& slots) noexcept; void eax4_set_defaults() noexcept; - void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept; - void eax5_set_sends_defaults(EaxSends& sends) noexcept; - void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept; - void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept; - void eax5_set_defaults(Eax5Props& props) noexcept; + static void eax5_set_source_defaults(EAX50SOURCEPROPERTIES& props) noexcept; + static void eax5_set_sends_defaults(EaxSends& sends) noexcept; + static void eax5_set_active_fx_slots_defaults(EAX50ACTIVEFXSLOTS& slots) noexcept; + static void eax5_set_speaker_levels_defaults(EaxSpeakerLevels& speaker_levels) noexcept; + static void eax5_set_defaults(Eax5Props& props) noexcept; void eax5_set_defaults() noexcept; void eax_set_defaults() noexcept; - void eax1_translate(const Eax1Props& src, Eax5Props& dst) noexcept; - void eax2_translate(const Eax2Props& src, Eax5Props& dst) noexcept; - void eax3_translate(const Eax3Props& src, Eax5Props& dst) noexcept; - void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept; + static void eax1_translate(const EAXBUFFER_REVERBPROPERTIES& src, Eax5Props& dst) noexcept; + static void eax2_translate(const EAX20BUFFERPROPERTIES& src, Eax5Props& dst) noexcept; + static void eax3_translate(const EAX30SOURCEPROPERTIES& src, Eax5Props& dst) noexcept; + static void eax4_translate(const Eax4Props& src, Eax5Props& dst) noexcept; static float eax_calculate_dst_occlusion_mb( long src_occlusion_mb, float path_ratio, float lf_ratio) noexcept; - EaxAlLowPassParam eax_create_direct_filter_param() const noexcept; + [[nodiscard]] auto eax_create_direct_filter_param() const noexcept -> EaxAlLowPassParam; - EaxAlLowPassParam eax_create_room_filter_param( - const ALeffectslot& fx_slot, - const EAXSOURCEALLSENDPROPERTIES& send) const noexcept; + [[nodiscard]] auto eax_create_room_filter_param(const ALeffectslot& fx_slot, + const EAXSOURCEALLSENDPROPERTIES& send) const noexcept -> EaxAlLowPassParam; void eax_update_direct_filter(); void eax_update_room_filters(); @@ -897,16 +903,16 @@ struct ALsource { } } - void eax_get_active_fx_slot_id(const EaxCall& call, const GUID* ids, size_t max_count); - void eax1_get(const EaxCall& call, const Eax1Props& props); - void eax2_get(const EaxCall& call, const Eax2Props& props); - void eax3_get_obstruction(const EaxCall& call, const Eax3Props& props); - void eax3_get_occlusion(const EaxCall& call, const Eax3Props& props); - void eax3_get_exclusion(const EaxCall& call, const Eax3Props& props); - void eax3_get(const EaxCall& call, const Eax3Props& props); + static void eax_get_active_fx_slot_id(const EaxCall& call, const al::span src_ids); + static void eax1_get(const EaxCall& call, const EAXBUFFER_REVERBPROPERTIES& props); + static void eax2_get(const EaxCall& call, const EAX20BUFFERPROPERTIES& props); + static void eax3_get_obstruction(const EaxCall& call, const EAX30SOURCEPROPERTIES& props); + static void eax3_get_occlusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props); + static void eax3_get_exclusion(const EaxCall& call, const EAX30SOURCEPROPERTIES& props); + static void eax3_get(const EaxCall& call, const EAX30SOURCEPROPERTIES& props); void eax4_get(const EaxCall& call, const Eax4Props& props); - void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props); - void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props); + static void eax5_get_all_2d(const EaxCall& call, const EAX50SOURCEPROPERTIES& props); + static void eax5_get_speaker_levels(const EaxCall& call, const EaxSpeakerLevels& props); void eax5_get(const EaxCall& call, const Eax5Props& props); void eax_get(const EaxCall& call); @@ -979,21 +985,21 @@ struct ALsource { } template - void eax_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount]) + void eax_defer_active_fx_slot_id(const EaxCall& call, const al::span dst_ids) { const auto src_ids = call.get_values(TIdCount); std::for_each(src_ids.cbegin(), src_ids.cend(), TValidator{}); - std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids); + std::uninitialized_copy(src_ids.cbegin(), src_ids.cend(), dst_ids.begin()); } template - void eax4_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount]) + void eax4_defer_active_fx_slot_id(const EaxCall& call, const al::span dst_ids) { eax_defer_active_fx_slot_id(call, dst_ids); } template - void eax5_defer_active_fx_slot_id(const EaxCall& call, GUID (&dst_ids)[TIdCount]) + void eax5_defer_active_fx_slot_id(const EaxCall& call, const al::span dst_ids) { eax_defer_active_fx_slot_id(call, dst_ids); } @@ -1025,12 +1031,12 @@ struct ALsource { void eax_set_efx_wet_gain_auto(); void eax_set_efx_wet_gain_hf_auto(); - void eax1_set(const EaxCall& call, Eax1Props& props); - void eax2_set(const EaxCall& call, Eax2Props& props); - void eax3_set(const EaxCall& call, Eax3Props& props); + static void eax1_set(const EaxCall& call, EAXBUFFER_REVERBPROPERTIES& props); + static void eax2_set(const EaxCall& call, EAX20BUFFERPROPERTIES& props); + void eax3_set(const EaxCall& call, EAX30SOURCEPROPERTIES& props); void eax4_set(const EaxCall& call, Eax4Props& props); - void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props); - void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props); + static void eax5_defer_all_2d(const EaxCall& call, EAX50SOURCEPROPERTIES& props); + static void eax5_defer_speaker_levels(const EaxCall& call, EaxSpeakerLevels& props); void eax5_set(const EaxCall& call, Eax5Props& props); void eax_set(const EaxCall& call); @@ -1044,4 +1050,19 @@ struct ALsource { void UpdateAllSourceProps(ALCcontext *context); +struct SourceSubList { + uint64_t FreeMask{~0_u64}; + gsl::owner*> Sources{nullptr}; + + SourceSubList() noexcept = default; + SourceSubList(const SourceSubList&) = delete; + SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources} + { rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; } + ~SourceSubList(); + + SourceSubList& operator=(const SourceSubList&) = delete; + SourceSubList& operator=(SourceSubList&& rhs) noexcept + { std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; } +}; + #endif diff --git a/3rdparty/openal/al/state.cpp b/3rdparty/openal/al/state.cpp index 5131edd93a51..e30b7a89e465 100644 --- a/3rdparty/openal/al/state.cpp +++ b/3rdparty/openal/al/state.cpp @@ -22,27 +22,30 @@ #include "version.h" +#include #include #include -#include +#include #include #include #include #include +#include #include "AL/al.h" #include "AL/alc.h" #include "AL/alext.h" #include "al/debug.h" -#include "albit.h" +#include "al/listener.h" #include "alc/alu.h" #include "alc/context.h" +#include "alc/device.h" #include "alc/inprogext.h" #include "alnumeric.h" #include "atomic.h" #include "core/context.h" -#include "core/except.h" +#include "core/logging.h" #include "core/mixer/defs.h" #include "core/voice.h" #include "direct_defs.h" @@ -50,9 +53,7 @@ #include "opthelpers.h" #include "strutils.h" -#ifdef ALSOFT_EAX -#include "alc/device.h" - +#if ALSOFT_EAX #include "eax/globals.h" #include "eax/x_ram.h" #endif // ALSOFT_EAX @@ -60,19 +61,21 @@ namespace { -constexpr ALchar alVendor[] = "OpenAL Community"; -constexpr ALchar alVersion[] = "1.1 ALSOFT " ALSOFT_VERSION; -constexpr ALchar alRenderer[] = "OpenAL Soft"; +using ALvoidptr = ALvoid*; -// Error Messages -constexpr ALchar alNoError[] = "No Error"; -constexpr ALchar alErrInvalidName[] = "Invalid Name"; -constexpr ALchar alErrInvalidEnum[] = "Invalid Enum"; -constexpr ALchar alErrInvalidValue[] = "Invalid Value"; -constexpr ALchar alErrInvalidOp[] = "Invalid Operation"; -constexpr ALchar alErrOutOfMemory[] = "Out of Memory"; -constexpr ALchar alStackOverflow[] = "Stack Overflow"; -constexpr ALchar alStackUnderflow[] = "Stack Underflow"; +[[nodiscard]] constexpr auto GetVendorString() noexcept { return "OpenAL Community"; } +[[nodiscard]] constexpr auto GetVersionString() noexcept { return "1.1 ALSOFT " ALSOFT_VERSION; } +[[nodiscard]] constexpr auto GetRendererString() noexcept { return "OpenAL Soft"; } + +/* Error Messages */ +[[nodiscard]] constexpr auto GetNoErrorString() noexcept { return "No Error"; } +[[nodiscard]] constexpr auto GetInvalidNameString() noexcept { return "Invalid Name"; } +[[nodiscard]] constexpr auto GetInvalidEnumString() noexcept { return "Invalid Enum"; } +[[nodiscard]] constexpr auto GetInvalidValueString() noexcept { return "Invalid Value"; } +[[nodiscard]] constexpr auto GetInvalidOperationString() noexcept { return "Invalid Operation"; } +[[nodiscard]] constexpr auto GetOutOfMemoryString() noexcept { return "Out of Memory"; } +[[nodiscard]] constexpr auto GetStackOverflowString() noexcept { return "Stack Overflow"; } +[[nodiscard]] constexpr auto GetStackUnderflowString() noexcept { return "Stack Underflow"; } /* Resampler strings */ template struct ResamplerName { }; @@ -80,8 +83,10 @@ template<> struct ResamplerName { static constexpr const ALchar *Get() noexcept { return "Nearest"; } }; template<> struct ResamplerName { static constexpr const ALchar *Get() noexcept { return "Linear"; } }; -template<> struct ResamplerName -{ static constexpr const ALchar *Get() noexcept { return "Cubic"; } }; +template<> struct ResamplerName +{ static constexpr const ALchar *Get() noexcept { return "Cubic Spline"; } }; +template<> struct ResamplerName +{ static constexpr const ALchar *Get() noexcept { return "4-point Gaussian"; } }; template<> struct ResamplerName { static constexpr const ALchar *Get() noexcept { return "11th order Sinc (fast)"; } }; template<> struct ResamplerName @@ -90,6 +95,10 @@ template<> struct ResamplerName { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc (fast)"; } }; template<> struct ResamplerName { static constexpr const ALchar *Get() noexcept { return "23rd order Sinc"; } }; +template<> struct ResamplerName +{ static constexpr const ALchar *Get() noexcept { return "47th order Sinc (fast)"; } }; +template<> struct ResamplerName +{ static constexpr const ALchar *Get() noexcept { return "47th order Sinc"; } }; const ALchar *GetResamplerName(const Resampler rtype) { @@ -98,18 +107,21 @@ const ALchar *GetResamplerName(const Resampler rtype) { HANDLE_RESAMPLER(Resampler::Point); HANDLE_RESAMPLER(Resampler::Linear); - HANDLE_RESAMPLER(Resampler::Cubic); + HANDLE_RESAMPLER(Resampler::Spline); + HANDLE_RESAMPLER(Resampler::Gaussian); HANDLE_RESAMPLER(Resampler::FastBSinc12); HANDLE_RESAMPLER(Resampler::BSinc12); HANDLE_RESAMPLER(Resampler::FastBSinc24); HANDLE_RESAMPLER(Resampler::BSinc24); + HANDLE_RESAMPLER(Resampler::FastBSinc48); + HANDLE_RESAMPLER(Resampler::BSinc48); } #undef HANDLE_RESAMPLER /* Should never get here. */ throw std::runtime_error{"Unexpected resampler index"}; } -std::optional DistanceModelFromALenum(ALenum model) +constexpr auto DistanceModelFromALenum(ALenum model) noexcept -> std::optional { switch(model) { @@ -123,7 +135,7 @@ std::optional DistanceModelFromALenum(ALenum model) } return std::nullopt; } -ALenum ALenumFromDistanceModel(DistanceModel model) +constexpr auto ALenumFromDistanceModel(DistanceModel model) -> ALenum { switch(model) { @@ -139,24 +151,24 @@ ALenum ALenumFromDistanceModel(DistanceModel model) } enum PropertyValue : ALenum { - DopplerFactor = AL_DOPPLER_FACTOR, - DopplerVelocity = AL_DOPPLER_VELOCITY, - DistanceModel = AL_DISTANCE_MODEL, - SpeedOfSound = AL_SPEED_OF_SOUND, - DeferredUpdates = AL_DEFERRED_UPDATES_SOFT, - GainLimit = AL_GAIN_LIMIT_SOFT, - NumResamplers = AL_NUM_RESAMPLERS_SOFT, - DefaultResampler = AL_DEFAULT_RESAMPLER_SOFT, - DebugLoggedMessages = AL_DEBUG_LOGGED_MESSAGES_EXT, - DebugNextLoggedMessageLength = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT, - MaxDebugMessageLength = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, - MaxDebugLoggedMessages = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, - MaxDebugGroupDepth = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, - MaxLabelLength = AL_MAX_LABEL_LENGTH_EXT, - ContextFlags = AL_CONTEXT_FLAGS_EXT, -#ifdef ALSOFT_EAX - EaxRamSize = AL_EAX_RAM_SIZE, - EaxRamFree = AL_EAX_RAM_FREE, + DopplerFactorProp = AL_DOPPLER_FACTOR, + DopplerVelocityProp = AL_DOPPLER_VELOCITY, + DistanceModelProp = AL_DISTANCE_MODEL, + SpeedOfSoundProp = AL_SPEED_OF_SOUND, + DeferredUpdatesProp = AL_DEFERRED_UPDATES_SOFT, + GainLimitProp = AL_GAIN_LIMIT_SOFT, + NumResamplersProp = AL_NUM_RESAMPLERS_SOFT, + DefaultResamplerProp = AL_DEFAULT_RESAMPLER_SOFT, + DebugLoggedMessagesProp = AL_DEBUG_LOGGED_MESSAGES_EXT, + DebugNextLoggedMessageLengthProp = AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT, + MaxDebugMessageLengthProp = AL_MAX_DEBUG_MESSAGE_LENGTH_EXT, + MaxDebugLoggedMessagesProp = AL_MAX_DEBUG_LOGGED_MESSAGES_EXT, + MaxDebugGroupDepthProp = AL_MAX_DEBUG_GROUP_STACK_DEPTH_EXT, + MaxLabelLengthProp = AL_MAX_LABEL_LENGTH_EXT, + ContextFlagsProp = AL_CONTEXT_FLAGS_EXT, +#if ALSOFT_EAX + EaxRamSizeProp = AL_EAX_RAM_SIZE, + EaxRamFreeProp = AL_EAX_RAM_FREE, #endif }; @@ -221,14 +233,14 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) case AL_DEBUG_LOGGED_MESSAGES_EXT: { - std::lock_guard _{context->mDebugCbLock}; + std::lock_guard debuglock{context->mDebugCbLock}; *values = cast_value(context->mDebugLog.size()); return; } case AL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_EXT: { - std::lock_guard _{context->mDebugCbLock}; + std::lock_guard debuglock{context->mDebugCbLock}; *values = cast_value(context->mDebugLog.empty() ? 0_uz : (context->mDebugLog.front().mMessage.size()+1)); return; @@ -254,9 +266,8 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(context->mContextFlags.to_ulong()); return; -#ifdef ALSOFT_EAX - -#define EAX_ERROR "[alGetInteger] EAX not enabled." +#if ALSOFT_EAX +#define EAX_ERROR "[alGetInteger] EAX not enabled" case AL_EAX_RAM_SIZE: if(eax_g_is_enabled) @@ -264,8 +275,8 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(eax_x_ram_max_size); return; } - context->setError(AL_INVALID_ENUM, EAX_ERROR); - return; + ERR(EAX_ERROR); + break; case AL_EAX_RAM_FREE: if(eax_g_is_enabled) @@ -275,14 +286,13 @@ void GetValue(ALCcontext *context, ALenum pname, T *values) *values = cast_value(device->eax_x_ram_free_size); return; } - context->setError(AL_INVALID_ENUM, EAX_ERROR); - return; + ERR(EAX_ERROR); + break; #undef EAX_ERROR - #endif // ALSOFT_EAX } - context->setError(AL_INVALID_ENUM, "Invalid context property 0x%04x", pname); + context->setError(AL_INVALID_ENUM, "Invalid context property {:#04x}", as_unsigned(pname)); } @@ -299,7 +309,7 @@ inline void UpdateProps(ALCcontext *context) /* WARNING: Non-standard export! Not part of any extension, or exposed in the * alcFunctions list. */ -AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept +AL_API auto AL_APIENTRY alsoft_get_version() noexcept -> const ALchar* { static const auto spoof = al::getenv("ALSOFT_SPOOF_VERSION"); if(spoof) return spoof->c_str(); @@ -307,112 +317,101 @@ AL_API const ALchar* AL_APIENTRY alsoft_get_version(void) noexcept } -AL_API DECL_FUNC1(void, alEnable, ALenum) +AL_API DECL_FUNC1(void, alEnable, ALenum,capability) FORCE_ALIGN void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) noexcept { switch(capability) { case AL_SOURCE_DISTANCE_MODEL: { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mSourceDistanceModel = true; UpdateProps(context); } - break; + return; case AL_DEBUG_OUTPUT_EXT: - context->mDebugEnabled = true; - break; + context->mDebugEnabled.store(true); + return; case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: context->setError(AL_INVALID_OPERATION, "Re-enabling AL_STOP_SOURCES_ON_DISCONNECT_SOFT not yet supported"); - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid enable property 0x%04x", capability); + return; } + context->setError(AL_INVALID_VALUE, "Invalid enable property {:#04x}", + as_unsigned(capability)); } -AL_API DECL_FUNC1(void, alDisable, ALenum) +AL_API DECL_FUNC1(void, alDisable, ALenum,capability) FORCE_ALIGN void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) noexcept { switch(capability) { case AL_SOURCE_DISTANCE_MODEL: { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mSourceDistanceModel = false; UpdateProps(context); } - break; + return; case AL_DEBUG_OUTPUT_EXT: - context->mDebugEnabled = false; - break; + context->mDebugEnabled.store(false); + return; case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: - context->mStopVoicesOnDisconnect = false; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid disable property 0x%04x", capability); + context->mStopVoicesOnDisconnect.store(false); + return; } + context->setError(AL_INVALID_VALUE, "Invalid disable property {:#04x}", + as_unsigned(capability)); } -AL_API DECL_FUNC1(ALboolean, alIsEnabled, ALenum) +AL_API DECL_FUNC1(ALboolean, alIsEnabled, ALenum,capability) FORCE_ALIGN ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) noexcept { - std::lock_guard _{context->mPropLock}; - ALboolean value{AL_FALSE}; + std::lock_guard proplock{context->mPropLock}; switch(capability) { - case AL_SOURCE_DISTANCE_MODEL: - value = context->mSourceDistanceModel ? AL_TRUE : AL_FALSE; - break; - - case AL_DEBUG_OUTPUT_EXT: - value = context->mDebugEnabled ? AL_TRUE : AL_FALSE; - break; - + case AL_SOURCE_DISTANCE_MODEL: return context->mSourceDistanceModel ? AL_TRUE : AL_FALSE; + case AL_DEBUG_OUTPUT_EXT: return context->mDebugEnabled ? AL_TRUE : AL_FALSE; case AL_STOP_SOURCES_ON_DISCONNECT_SOFT: - value = context->mStopVoicesOnDisconnect ? AL_TRUE : AL_FALSE; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid is enabled property 0x%04x", capability); + return context->mStopVoicesOnDisconnect.load() ? AL_TRUE : AL_FALSE; } - - return value; + context->setError(AL_INVALID_VALUE, "Invalid is enabled property {:#04x}", + as_unsigned(capability)); + return AL_FALSE; } #define DECL_GETFUNC(R, Name, Ext) \ -AL_API R AL_APIENTRY Name##Ext(ALenum pname) noexcept \ +auto AL_APIENTRY Name##Ext(ALenum pname) noexcept -> R \ { \ - R value{}; \ + auto value = R{}; \ auto context = GetContextRef(); \ if(!context) UNLIKELY return value; \ Name##vDirect##Ext(GetContextRef().get(), pname, &value); \ return value; \ } \ -FORCE_ALIGN R AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept \ +FORCE_ALIGN auto AL_APIENTRY Name##Direct##Ext(ALCcontext *context, ALenum pname) noexcept -> R \ { \ - R value{}; \ + auto value = R{}; \ Name##vDirect##Ext(context, pname, &value); \ return value; \ } -DECL_GETFUNC(ALboolean, alGetBoolean,) -DECL_GETFUNC(ALdouble, alGetDouble,) -DECL_GETFUNC(ALfloat, alGetFloat,) -DECL_GETFUNC(ALint, alGetInteger,) +AL_API DECL_GETFUNC(ALboolean, alGetBoolean,) +AL_API DECL_GETFUNC(ALdouble, alGetDouble,) +AL_API DECL_GETFUNC(ALfloat, alGetFloat,) +AL_API DECL_GETFUNC(ALint, alGetInteger,) -DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT) -DECL_GETFUNC(ALvoid*, alGetPointer,SOFT) +DECL_GETFUNC(ALvoidptr, alGetPointer,EXT) +AL_API DECL_GETFUNC(ALint64SOFT, alGetInteger64,SOFT) +AL_API DECL_GETFUNC(ALvoidptr, alGetPointer,SOFT) #undef DECL_GETFUNC -AL_API DECL_FUNC2(void, alGetBooleanv, ALenum, ALboolean*) +AL_API DECL_FUNC2(void, alGetBooleanv, ALenum,pname, ALboolean*,values) FORCE_ALIGN void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum pname, ALboolean *values) noexcept { if(!values) UNLIKELY @@ -420,7 +419,7 @@ FORCE_ALIGN void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum pna GetValue(context, pname, values); } -AL_API DECL_FUNC2(void, alGetDoublev, ALenum, ALdouble*) +AL_API DECL_FUNC2(void, alGetDoublev, ALenum,pname, ALdouble*,values) FORCE_ALIGN void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum pname, ALdouble *values) noexcept { if(!values) UNLIKELY @@ -428,7 +427,7 @@ FORCE_ALIGN void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum pnam GetValue(context, pname, values); } -AL_API DECL_FUNC2(void, alGetFloatv, ALenum, ALfloat*) +AL_API DECL_FUNC2(void, alGetFloatv, ALenum,pname, ALfloat*,values) FORCE_ALIGN void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum pname, ALfloat *values) noexcept { if(!values) UNLIKELY @@ -436,7 +435,7 @@ FORCE_ALIGN void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum pname GetValue(context, pname, values); } -AL_API DECL_FUNC2(void, alGetIntegerv, ALenum, ALint*) +AL_API DECL_FUNC2(void, alGetIntegerv, ALenum,pname, ALint*,values) FORCE_ALIGN void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum pname, ALint *values) noexcept { if(!values) UNLIKELY @@ -444,7 +443,7 @@ FORCE_ALIGN void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum pna GetValue(context, pname, values); } -AL_API DECL_FUNCEXT2(void, alGetInteger64v,SOFT, ALenum, ALint64SOFT*) +AL_API DECL_FUNCEXT2(void, alGetInteger64v,SOFT, ALenum,pname, ALint64SOFT*,values) FORCE_ALIGN void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) noexcept { if(!values) UNLIKELY @@ -452,8 +451,12 @@ FORCE_ALIGN void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALen GetValue(context, pname, values); } -AL_API DECL_FUNCEXT2(void, alGetPointerv,SOFT, ALenum, ALvoid**) +AL_API DECL_FUNCEXT2(void, alGetPointerv,SOFT, ALenum,pname, ALvoid**,values) FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept +{ return alGetPointervDirectEXT(context, pname, values); } + +FORCE_ALIGN DECL_FUNCEXT2(void, alGetPointerv,EXT, ALenum,pname, ALvoid**,values) +FORCE_ALIGN void AL_APIENTRY alGetPointervDirectEXT(ALCcontext *context, ALenum pname, ALvoid **values) noexcept { if(!values) UNLIKELY return context->setError(AL_INVALID_VALUE, "NULL pointer"); @@ -461,159 +464,127 @@ FORCE_ALIGN void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum switch(pname) { case AL_EVENT_CALLBACK_FUNCTION_SOFT: - *values = al::bit_cast(context->mEventCb); - break; + *values = reinterpret_cast(context->mEventCb); + return; case AL_EVENT_CALLBACK_USER_PARAM_SOFT: *values = context->mEventParam; - break; + return; case AL_DEBUG_CALLBACK_FUNCTION_EXT: - *values = al::bit_cast(context->mDebugCb); - break; + *values = reinterpret_cast(context->mDebugCb); + return; case AL_DEBUG_CALLBACK_USER_PARAM_EXT: *values = context->mDebugParam; - break; - - default: - context->setError(AL_INVALID_ENUM, "Invalid context pointer property 0x%04x", pname); + return; } + context->setError(AL_INVALID_ENUM, "Invalid context pointer property {:#04x}", + as_unsigned(pname)); } -AL_API DECL_FUNC1(const ALchar*, alGetString, ALenum) +AL_API DECL_FUNC1(const ALchar*, alGetString, ALenum,pname) FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum pname) noexcept { - const ALchar *value{nullptr}; switch(pname) { case AL_VENDOR: - value = alVendor; - break; - + if(auto device = context->mALDevice.get(); !device->mVendorOverride.empty()) + return device->mVendorOverride.c_str(); + return GetVendorString(); case AL_VERSION: - value = alVersion; - break; - + if(auto device = context->mALDevice.get(); !device->mVersionOverride.empty()) + return device->mVersionOverride.c_str(); + return GetVersionString(); case AL_RENDERER: - value = alRenderer; - break; - - case AL_EXTENSIONS: - value = context->mExtensionsString.c_str(); - break; - - case AL_NO_ERROR: - value = alNoError; - break; - - case AL_INVALID_NAME: - value = alErrInvalidName; - break; - - case AL_INVALID_ENUM: - value = alErrInvalidEnum; - break; - - case AL_INVALID_VALUE: - value = alErrInvalidValue; - break; - - case AL_INVALID_OPERATION: - value = alErrInvalidOp; - break; - - case AL_OUT_OF_MEMORY: - value = alErrOutOfMemory; - break; - - case AL_STACK_OVERFLOW_EXT: - value = alStackOverflow; - break; - - case AL_STACK_UNDERFLOW_EXT: - value = alStackUnderflow; - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid string property 0x%04x", pname); + if(auto device = context->mALDevice.get(); !device->mRendererOverride.empty()) + return device->mRendererOverride.c_str(); + return GetRendererString(); + case AL_EXTENSIONS: return context->mExtensionsString.c_str(); + case AL_NO_ERROR: return GetNoErrorString(); + case AL_INVALID_NAME: return GetInvalidNameString(); + case AL_INVALID_ENUM: return GetInvalidEnumString(); + case AL_INVALID_VALUE: return GetInvalidValueString(); + case AL_INVALID_OPERATION: return GetInvalidOperationString(); + case AL_OUT_OF_MEMORY: return GetOutOfMemoryString(); + case AL_STACK_OVERFLOW_EXT: return GetStackOverflowString(); + case AL_STACK_UNDERFLOW_EXT: return GetStackUnderflowString(); } - return value; + context->setError(AL_INVALID_VALUE, "Invalid string property {:#04x}", as_unsigned(pname)); + return nullptr; } -AL_API DECL_FUNC1(void, alDopplerFactor, ALfloat) +AL_API DECL_FUNC1(void, alDopplerFactor, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) noexcept { if(!(value >= 0.0f && std::isfinite(value))) - context->setError(AL_INVALID_VALUE, "Doppler factor %f out of range", value); + context->setError(AL_INVALID_VALUE, "Doppler factor {:f} out of range", value); else { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mDopplerFactor = value; UpdateProps(context); } } -AL_API DECL_FUNC1(void, alSpeedOfSound, ALfloat) +AL_API DECL_FUNC1(void, alSpeedOfSound, ALfloat,value) FORCE_ALIGN void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) noexcept { if(!(value > 0.0f && std::isfinite(value))) - context->setError(AL_INVALID_VALUE, "Speed of sound %f out of range", value); + context->setError(AL_INVALID_VALUE, "Speed of sound {:f} out of range", value); else { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mSpeedOfSound = value; UpdateProps(context); } } -AL_API DECL_FUNC1(void, alDistanceModel, ALenum) +AL_API DECL_FUNC1(void, alDistanceModel, ALenum,value) FORCE_ALIGN void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum value) noexcept { if(auto model = DistanceModelFromALenum(value)) { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mDistanceModel = *model; if(!context->mSourceDistanceModel) UpdateProps(context); } else - context->setError(AL_INVALID_VALUE, "Distance model 0x%04x out of range", value); + context->setError(AL_INVALID_VALUE, "Distance model {:#04x} out of range", + as_unsigned(value)); } AL_API DECL_FUNCEXT(void, alDeferUpdates,SOFT) FORCE_ALIGN void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) noexcept { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->deferUpdates(); } AL_API DECL_FUNCEXT(void, alProcessUpdates,SOFT) FORCE_ALIGN void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) noexcept { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->processUpdates(); } -AL_API DECL_FUNCEXT2(const ALchar*, alGetStringi,SOFT, ALenum,ALsizei) +AL_API DECL_FUNCEXT2(const ALchar*, alGetStringi,SOFT, ALenum,pname, ALsizei,index) FORCE_ALIGN const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) noexcept { - const ALchar *value{nullptr}; switch(pname) { case AL_RESAMPLER_NAME_SOFT: - if(index < 0 || index > static_cast(Resampler::Max)) - context->setError(AL_INVALID_VALUE, "Resampler name index %d out of range", index); - else - value = GetResamplerName(static_cast(index)); - break; - - default: - context->setError(AL_INVALID_VALUE, "Invalid string indexed property"); + if(index >= 0 && index <= al::to_underlying(Resampler::Max)) + return GetResamplerName(static_cast(index)); + context->setError(AL_INVALID_VALUE, "Resampler name index {} out of range", index); + return nullptr; } - return value; + context->setError(AL_INVALID_VALUE, "Invalid string indexed property {:#04x}", + as_unsigned(pname)); + return nullptr; } @@ -623,16 +594,16 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept if(!context) UNLIKELY return; if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY - context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 0, + context->debugMessage(DebugSource::API, DebugType::DeprecatedBehavior, 1, DebugSeverity::Medium, "alDopplerVelocity is deprecated in AL 1.1, use alSpeedOfSound; " "alDopplerVelocity(x) -> alSpeedOfSound(343.3f * x)"); if(!(value >= 0.0f && std::isfinite(value))) - context->setError(AL_INVALID_VALUE, "Doppler velocity %f out of range", value); + context->setError(AL_INVALID_VALUE, "Doppler velocity {:f} out of range", value); else { - std::lock_guard _{context->mPropLock}; + std::lock_guard proplock{context->mPropLock}; context->mDopplerVelocity = value; UpdateProps(context.get()); } @@ -641,21 +612,21 @@ AL_API void AL_APIENTRY alDopplerVelocity(ALfloat value) noexcept void UpdateContextProps(ALCcontext *context) { - /* Get an unused proprty container, or allocate a new one as needed. */ + /* Get an unused property container, or allocate a new one as needed. */ ContextProps *props{context->mFreeContextProps.load(std::memory_order_acquire)}; if(!props) - props = new ContextProps{}; - else { - ContextProps *next; - do { - next = props->next.load(std::memory_order_relaxed); - } while(context->mFreeContextProps.compare_exchange_weak(props, next, - std::memory_order_seq_cst, std::memory_order_acquire) == 0); + context->allocContextProps(); + props = context->mFreeContextProps.load(std::memory_order_acquire); } + ContextProps *next; + do { + next = props->next.load(std::memory_order_relaxed); + } while(context->mFreeContextProps.compare_exchange_weak(props, next, + std::memory_order_acq_rel, std::memory_order_acquire) == false); /* Copy in current property values. */ - ALlistener &listener = context->mListener; + const auto &listener = context->mListener; props->Position = listener.Position; props->Velocity = listener.Velocity; props->OrientAt = listener.OrientAt; @@ -667,6 +638,9 @@ void UpdateContextProps(ALCcontext *context) props->DopplerFactor = context->mDopplerFactor; props->DopplerVelocity = context->mDopplerVelocity; props->SpeedOfSound = context->mSpeedOfSound; +#if ALSOFT_EAX + props->DistanceFactor = context->eaxGetDistanceFactor(); +#endif props->SourceDistanceModel = context->mSourceDistanceModel; props->mDistanceModel = context->mDistanceModel; diff --git a/3rdparty/openal/alc/alc.cpp b/3rdparty/openal/alc/alc.cpp index baa4788f3d7e..b55fce800da8 100644 --- a/3rdparty/openal/alc/alc.cpp +++ b/3rdparty/openal/alc/alc.cpp @@ -19,6 +19,8 @@ */ #include "config.h" +#include "config_backends.h" +#include "config_simd.h" #include "version.h" @@ -34,15 +36,14 @@ #include #include #include -#include #include #include #include #include -#include #include #include #include +#include #include #include #include @@ -50,10 +51,10 @@ #include #include #include -#include #include #include -#include +#include +#include #include #include @@ -67,11 +68,12 @@ #include "al/debug.h" #include "al/effect.h" #include "al/filter.h" -#include "al/listener.h" #include "al/source.h" +#include "alc/events.h" #include "albit.h" #include "alconfig.h" #include "almalloc.h" +#include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" #include "alstring.h" @@ -85,13 +87,12 @@ #include "core/cpu_caps.h" #include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" -#include "core/except.h" +#include "core/filters/nfc.h" #include "core/helpers.h" #include "core/mastering.h" -#include "core/mixer/hrtfdefs.h" #include "core/fpu_ctrl.h" -#include "core/front_stablizer.h" #include "core/logging.h" #include "core/uhjfilter.h" #include "core/voice.h" @@ -99,6 +100,8 @@ #include "device.h" #include "effects/base.h" #include "export_list.h" +#include "flexarray.h" +#include "fmt/core.h" #include "inprogext.h" #include "intrusive_ptr.h" #include "opthelpers.h" @@ -107,59 +110,65 @@ #include "backends/base.h" #include "backends/null.h" #include "backends/loopback.h" -#ifdef HAVE_PIPEWIRE +#if HAVE_PIPEWIRE #include "backends/pipewire.h" #endif -#ifdef HAVE_JACK +#if HAVE_JACK #include "backends/jack.h" #endif -#ifdef HAVE_PULSEAUDIO +#if HAVE_PULSEAUDIO #include "backends/pulseaudio.h" #endif -#ifdef HAVE_ALSA +#if HAVE_ALSA #include "backends/alsa.h" #endif -#ifdef HAVE_WASAPI +#if HAVE_WASAPI #include "backends/wasapi.h" #endif -#ifdef HAVE_COREAUDIO +#if HAVE_COREAUDIO #include "backends/coreaudio.h" #endif -#ifdef HAVE_OPENSL +#if HAVE_OPENSL #include "backends/opensl.h" #endif -#ifdef HAVE_OBOE +#if HAVE_OBOE #include "backends/oboe.h" #endif -#ifdef HAVE_SOLARIS +#if HAVE_SOLARIS #include "backends/solaris.h" #endif -#ifdef HAVE_SNDIO -#include "backends/sndio.h" +#if HAVE_SNDIO +#include "backends/sndio.hpp" #endif -#ifdef HAVE_OSS +#if HAVE_OSS #include "backends/oss.h" #endif -#ifdef HAVE_DSOUND +#if HAVE_DSOUND #include "backends/dsound.h" #endif -#ifdef HAVE_WINMM +#if HAVE_WINMM #include "backends/winmm.h" #endif -#ifdef HAVE_PORTAUDIO -#include "backends/portaudio.h" +#if HAVE_PORTAUDIO +#include "backends/portaudio.hpp" +#endif +#if HAVE_SDL3 +#include "backends/sdl3.h" #endif -#ifdef HAVE_SDL2 +#if HAVE_SDL2 #include "backends/sdl2.h" #endif -#ifdef HAVE_WAVE +#if HAVE_OTHERIO +#include "backends/otherio.h" +#endif +#if HAVE_WAVE #include "backends/wave.h" #endif -#ifdef ALSOFT_EAX +#if ALSOFT_EAX +#include "al/eax/api.h" #include "al/eax/globals.h" -#include "al/eax/x_ram.h" -#endif // ALSOFT_EAX +#endif /************************************************ @@ -173,7 +182,7 @@ BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/) case DLL_PROCESS_ATTACH: /* Pin the DLL so we won't get unloaded until the process terminates */ GetModuleHandleExW(GET_MODULE_HANDLE_EX_FLAG_PIN | GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, - al::bit_cast(module), &module); + reinterpret_cast(module), &module); break; } return TRUE; @@ -182,7 +191,7 @@ BOOL APIENTRY DllMain(HINSTANCE module, DWORD reason, LPVOID /*reserved*/) namespace { -using namespace std::placeholders; +using namespace std::string_view_literals; using std::chrono::seconds; using std::chrono::nanoseconds; @@ -190,64 +199,79 @@ using voidp = void*; using float2 = std::array; +auto gProcessRunning = true; +struct ProcessWatcher { + ProcessWatcher() = default; + ProcessWatcher(const ProcessWatcher&) = delete; + ProcessWatcher& operator=(const ProcessWatcher&) = delete; + ~ProcessWatcher() { gProcessRunning = false; } +}; +ProcessWatcher gProcessWatcher; + /************************************************ * Backends ************************************************/ struct BackendInfo { const char *name; - BackendFactory& (*getFactory)(void); + BackendFactory& (*getFactory)(); }; -BackendInfo BackendList[] = { -#ifdef HAVE_PIPEWIRE - { "pipewire", PipeWireBackendFactory::getFactory }, +std::array BackendList{ +#if HAVE_PIPEWIRE + BackendInfo{"pipewire", PipeWireBackendFactory::getFactory}, #endif -#ifdef HAVE_PULSEAUDIO - { "pulse", PulseBackendFactory::getFactory }, +#if HAVE_PULSEAUDIO + BackendInfo{"pulse", PulseBackendFactory::getFactory}, #endif -#ifdef HAVE_WASAPI - { "wasapi", WasapiBackendFactory::getFactory }, +#if HAVE_WASAPI + BackendInfo{"wasapi", WasapiBackendFactory::getFactory}, +#endif +#if HAVE_COREAUDIO + BackendInfo{"core", CoreAudioBackendFactory::getFactory}, #endif -#ifdef HAVE_COREAUDIO - { "core", CoreAudioBackendFactory::getFactory }, +#if HAVE_OBOE + BackendInfo{"oboe", OboeBackendFactory::getFactory}, #endif -#ifdef HAVE_OBOE - { "oboe", OboeBackendFactory::getFactory }, +#if HAVE_OPENSL + BackendInfo{"opensl", OSLBackendFactory::getFactory}, #endif -#ifdef HAVE_OPENSL - { "opensl", OSLBackendFactory::getFactory }, +#if HAVE_ALSA + BackendInfo{"alsa", AlsaBackendFactory::getFactory}, #endif -#ifdef HAVE_ALSA - { "alsa", AlsaBackendFactory::getFactory }, +#if HAVE_SOLARIS + BackendInfo{"solaris", SolarisBackendFactory::getFactory}, #endif -#ifdef HAVE_SOLARIS - { "solaris", SolarisBackendFactory::getFactory }, +#if HAVE_SNDIO + BackendInfo{"sndio", SndIOBackendFactory::getFactory}, #endif -#ifdef HAVE_SNDIO - { "sndio", SndIOBackendFactory::getFactory }, +#if HAVE_OSS + BackendInfo{"oss", OSSBackendFactory::getFactory}, #endif -#ifdef HAVE_OSS - { "oss", OSSBackendFactory::getFactory }, +#if HAVE_DSOUND + BackendInfo{"dsound", DSoundBackendFactory::getFactory}, #endif -#ifdef HAVE_JACK - { "jack", JackBackendFactory::getFactory }, +#if HAVE_WINMM + BackendInfo{"winmm", WinMMBackendFactory::getFactory}, #endif -#ifdef HAVE_DSOUND - { "dsound", DSoundBackendFactory::getFactory }, +#if HAVE_PORTAUDIO + BackendInfo{"port", PortBackendFactory::getFactory}, #endif -#ifdef HAVE_WINMM - { "winmm", WinMMBackendFactory::getFactory }, +#if HAVE_SDL3 + BackendInfo{"sdl3", SDL3BackendFactory::getFactory}, #endif -#ifdef HAVE_PORTAUDIO - { "port", PortBackendFactory::getFactory }, +#if HAVE_SDL2 + BackendInfo{"sdl2", SDL2BackendFactory::getFactory}, #endif -#ifdef HAVE_SDL2 - { "sdl2", SDL2BackendFactory::getFactory }, +#if HAVE_JACK + BackendInfo{"jack", JackBackendFactory::getFactory}, +#endif +#if HAVE_OTHERIO + BackendInfo{"otherio", OtherIOBackendFactory::getFactory}, #endif - { "null", NullBackendFactory::getFactory }, -#ifdef HAVE_WAVE - { "wave", WaveBackendFactory::getFactory }, + BackendInfo{"null", NullBackendFactory::getFactory}, +#if HAVE_WAVE + BackendInfo{"wave", WaveBackendFactory::getFactory}, #endif }; @@ -255,21 +279,28 @@ BackendFactory *PlaybackFactory{}; BackendFactory *CaptureFactory{}; -constexpr ALCchar alcNoError[] = "No Error"; -constexpr ALCchar alcErrInvalidDevice[] = "Invalid Device"; -constexpr ALCchar alcErrInvalidContext[] = "Invalid Context"; -constexpr ALCchar alcErrInvalidEnum[] = "Invalid Enum"; -constexpr ALCchar alcErrInvalidValue[] = "Invalid Value"; -constexpr ALCchar alcErrOutOfMemory[] = "Out of Memory"; +[[nodiscard]] constexpr auto GetNoErrorString() noexcept { return "No Error"; } +[[nodiscard]] constexpr auto GetInvalidDeviceString() noexcept { return "Invalid Device"; } +[[nodiscard]] constexpr auto GetInvalidContextString() noexcept { return "Invalid Context"; } +[[nodiscard]] constexpr auto GetInvalidEnumString() noexcept { return "Invalid Enum"; } +[[nodiscard]] constexpr auto GetInvalidValueString() noexcept { return "Invalid Value"; } +[[nodiscard]] constexpr auto GetOutOfMemoryString() noexcept { return "Out of Memory"; } +[[nodiscard]] constexpr auto GetDefaultName() noexcept { return "OpenAL Soft\0"; } + +#ifdef _WIN32 +[[nodiscard]] constexpr auto GetDevicePrefix() noexcept { return "OpenAL Soft on "sv; } +#else +[[nodiscard]] constexpr auto GetDevicePrefix() noexcept { return std::string_view{}; } +#endif /************************************************ * Global variables ************************************************/ /* Enumerated device names */ -constexpr ALCchar alcDefaultName[] = "OpenAL Soft\0"; - +std::vector alcAllDevicesArray; +std::vector alcCaptureDeviceArray; std::string alcAllDevicesList; std::string alcCaptureDeviceList; @@ -297,36 +328,41 @@ constexpr uint DitherRNGSeed{22222u}; /************************************************ * ALC information ************************************************/ -constexpr ALCchar alcNoDeviceExtList[] = - "ALC_ENUMERATE_ALL_EXT " - "ALC_ENUMERATION_EXT " - "ALC_EXT_CAPTURE " - "ALC_EXTX_direct_context " - "ALC_EXT_EFX " - "ALC_EXT_thread_local_context " - "ALC_SOFT_loopback " - "ALC_SOFT_loopback_bformat " - "ALC_SOFT_reopen_device " - "ALC_SOFT_system_events"; -constexpr ALCchar alcExtensionList[] = - "ALC_ENUMERATE_ALL_EXT " - "ALC_ENUMERATION_EXT " - "ALC_EXT_CAPTURE " - "ALC_EXT_debug " - "ALC_EXT_DEDICATED " - "ALC_EXTX_direct_context " - "ALC_EXT_disconnect " - "ALC_EXT_EFX " - "ALC_EXT_thread_local_context " - "ALC_SOFT_device_clock " - "ALC_SOFT_HRTF " - "ALC_SOFT_loopback " - "ALC_SOFT_loopback_bformat " - "ALC_SOFT_output_limiter " - "ALC_SOFT_output_mode " - "ALC_SOFT_pause_device " - "ALC_SOFT_reopen_device " - "ALC_SOFT_system_events"; +[[nodiscard]] constexpr auto GetNoDeviceExtList() noexcept -> const char* +{ + return "ALC_ENUMERATE_ALL_EXT " + "ALC_ENUMERATION_EXT " + "ALC_EXT_CAPTURE " + "ALC_EXT_direct_context " + "ALC_EXT_EFX " + "ALC_EXT_thread_local_context " + "ALC_SOFT_loopback " + "ALC_SOFT_loopback_bformat " + "ALC_SOFT_reopen_device " + "ALC_SOFT_system_events"; +} +[[nodiscard]] constexpr auto GetExtensionList() noexcept -> const char* +{ + return "ALC_ENUMERATE_ALL_EXT " + "ALC_ENUMERATION_EXT " + "ALC_EXT_CAPTURE " + "ALC_EXT_debug " + "ALC_EXT_DEDICATED " + "ALC_EXT_direct_context " + "ALC_EXT_disconnect " + "ALC_EXT_EFX " + "ALC_EXT_thread_local_context " + "ALC_SOFT_device_clock " + "ALC_SOFT_HRTF " + "ALC_SOFT_loopback " + "ALC_SOFT_loopback_bformat " + "ALC_SOFT_output_limiter " + "ALC_SOFT_output_mode " + "ALC_SOFT_pause_device " + "ALC_SOFT_reopen_device " + "ALC_SOFT_system_events"; +} + constexpr int alcMajorVersion{1}; constexpr int alcMinorVersion{1}; @@ -334,19 +370,19 @@ constexpr int alcEFXMajorVersion{1}; constexpr int alcEFXMinorVersion{0}; -using DeviceRef = al::intrusive_ptr; +using DeviceRef = al::intrusive_ptr; /************************************************ * Device lists ************************************************/ -std::vector DeviceList; +std::vector DeviceList; std::vector ContextList; std::recursive_mutex ListLock; -void alc_initconfig(void) +void alc_initconfig() { if(auto loglevel = al::getenv("ALSOFT_LOGLEVEL")) { @@ -367,7 +403,7 @@ void alc_initconfig(void) else { auto u8name = wstr_to_utf8(*logfile); - ERR("Failed to open log file '%s'\n", u8name.c_str()); + ERR("Failed to open log file '{}'", u8name); } } #else @@ -375,11 +411,11 @@ void alc_initconfig(void) { FILE *logf{fopen(logfile->c_str(), "wt")}; if(logf) gLogFile = logf; - else ERR("Failed to open log file '%s'\n", logfile->c_str()); + else ERR("Failed to open log file '{}'", *logfile); } #endif - TRACE("Initializing library v%s-%s %s\n", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH, + TRACE("Initializing library v{}-{} {}", ALSOFT_VERSION, ALSOFT_GIT_COMMIT_HASH, ALSOFT_GIT_BRANCH); { std::string names; @@ -395,139 +431,137 @@ void alc_initconfig(void) names += backend.name; } } - TRACE("Supported backends: %s\n", names.c_str()); + TRACE("Supported backends: {}", names); } ReadALConfig(); if(auto suspendmode = al::getenv("__ALSOFT_SUSPEND_CONTEXT")) { - if(al::strcasecmp(suspendmode->c_str(), "ignore") == 0) + if(al::case_compare(*suspendmode, "ignore"sv) == 0) { SuspendDefers = false; - TRACE("Selected context suspend behavior, \"ignore\"\n"); + TRACE("Selected context suspend behavior, \"ignore\""); } else - ERR("Unhandled context suspend behavior setting: \"%s\"\n", suspendmode->c_str()); + ERR("Unhandled context suspend behavior setting: \"{}\"", *suspendmode); } int capfilter{0}; -#if defined(HAVE_SSE4_1) +#if HAVE_SSE4_1 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1; -#elif defined(HAVE_SSE3) +#elif HAVE_SSE3 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3; -#elif defined(HAVE_SSE2) +#elif HAVE_SSE2 capfilter |= CPU_CAP_SSE | CPU_CAP_SSE2; -#elif defined(HAVE_SSE) +#elif HAVE_SSE capfilter |= CPU_CAP_SSE; #endif -#ifdef HAVE_NEON +#if HAVE_NEON capfilter |= CPU_CAP_NEON; #endif - if(auto cpuopt = ConfigValueStr(nullptr, nullptr, "disable-cpu-exts")) + if(auto cpuopt = ConfigValueStr({}, {}, "disable-cpu-exts"sv)) { - const char *str{cpuopt->c_str()}; - if(al::strcasecmp(str, "all") == 0) + std::string_view cpulist{*cpuopt}; + if(al::case_compare(cpulist, "all"sv) == 0) capfilter = 0; - else + else while(!cpulist.empty()) { - const char *next = str; - do { - str = next; - while(isspace(str[0])) - str++; - next = strchr(str, ','); - - if(!str[0] || str[0] == ',') - continue; - - size_t len{next ? static_cast(next-str) : strlen(str)}; - while(len > 0 && isspace(str[len-1])) - len--; - if(len == 3 && al::strncasecmp(str, "sse", len) == 0) - capfilter &= ~CPU_CAP_SSE; - else if(len == 4 && al::strncasecmp(str, "sse2", len) == 0) - capfilter &= ~CPU_CAP_SSE2; - else if(len == 4 && al::strncasecmp(str, "sse3", len) == 0) - capfilter &= ~CPU_CAP_SSE3; - else if(len == 6 && al::strncasecmp(str, "sse4.1", len) == 0) - capfilter &= ~CPU_CAP_SSE4_1; - else if(len == 4 && al::strncasecmp(str, "neon", len) == 0) - capfilter &= ~CPU_CAP_NEON; - else - WARN("Invalid CPU extension \"%s\"\n", str); - } while(next++); + auto nextpos = std::min(cpulist.find(','), cpulist.size()); + auto entry = cpulist.substr(0, nextpos); + + while(nextpos < cpulist.size() && cpulist[nextpos] == ',') + ++nextpos; + cpulist.remove_prefix(nextpos); + + while(!entry.empty() && std::isspace(entry.front())) + entry.remove_prefix(1); + while(!entry.empty() && std::isspace(entry.back())) + entry.remove_suffix(1); + if(entry.empty()) + continue; + + if(al::case_compare(entry, "sse"sv) == 0) + capfilter &= ~CPU_CAP_SSE; + else if(al::case_compare(entry, "sse2"sv) == 0) + capfilter &= ~CPU_CAP_SSE2; + else if(al::case_compare(entry, "sse3"sv) == 0) + capfilter &= ~CPU_CAP_SSE3; + else if(al::case_compare(entry, "sse4.1"sv) == 0) + capfilter &= ~CPU_CAP_SSE4_1; + else if(al::case_compare(entry, "neon"sv) == 0) + capfilter &= ~CPU_CAP_NEON; + else + WARN("Invalid CPU extension \"{}\"", entry); } } if(auto cpuopt = GetCPUInfo()) { if(!cpuopt->mVendor.empty() || !cpuopt->mName.empty()) { - TRACE("Vendor ID: \"%s\"\n", cpuopt->mVendor.c_str()); - TRACE("Name: \"%s\"\n", cpuopt->mName.c_str()); + TRACE("Vendor ID: \"{}\"", cpuopt->mVendor); + TRACE("Name: \"{}\"", cpuopt->mName); } const int caps{cpuopt->mCaps}; - TRACE("Extensions:%s%s%s%s%s%s\n", - ((capfilter&CPU_CAP_SSE) ? ((caps&CPU_CAP_SSE) ? " +SSE" : " -SSE") : ""), - ((capfilter&CPU_CAP_SSE2) ? ((caps&CPU_CAP_SSE2) ? " +SSE2" : " -SSE2") : ""), - ((capfilter&CPU_CAP_SSE3) ? ((caps&CPU_CAP_SSE3) ? " +SSE3" : " -SSE3") : ""), - ((capfilter&CPU_CAP_SSE4_1) ? ((caps&CPU_CAP_SSE4_1) ? " +SSE4.1" : " -SSE4.1") : ""), - ((capfilter&CPU_CAP_NEON) ? ((caps&CPU_CAP_NEON) ? " +NEON" : " -NEON") : ""), - ((!capfilter) ? " -none-" : "")); + TRACE("Extensions:{}{}{}{}{}{}", + ((capfilter&CPU_CAP_SSE) ?(caps&CPU_CAP_SSE) ?" +SSE"sv : " -SSE"sv : ""sv), + ((capfilter&CPU_CAP_SSE2) ?(caps&CPU_CAP_SSE2) ?" +SSE2"sv : " -SSE2"sv : ""sv), + ((capfilter&CPU_CAP_SSE3) ?(caps&CPU_CAP_SSE3) ?" +SSE3"sv : " -SSE3"sv : ""sv), + ((capfilter&CPU_CAP_SSE4_1)?(caps&CPU_CAP_SSE4_1)?" +SSE4.1"sv : " -SSE4.1"sv : ""sv), + ((capfilter&CPU_CAP_NEON) ?(caps&CPU_CAP_NEON) ?" +NEON"sv : " -NEON"sv : ""sv), + (!capfilter) ? " -none-"sv : ""sv); CPUCapFlags = caps & capfilter; } - if(auto priopt = ConfigValueInt(nullptr, nullptr, "rt-prio")) + if(auto priopt = ConfigValueInt({}, {}, "rt-prio"sv)) RTPrioLevel = *priopt; - if(auto limopt = ConfigValueBool(nullptr, nullptr, "rt-time-limit")) + if(auto limopt = ConfigValueBool({}, {}, "rt-time-limit"sv)) AllowRTTimeLimit = *limopt; { CompatFlagBitset compatflags{}; - auto checkflag = [](const char *envname, const char *optname) -> bool + auto checkflag = [](const char *envname, const std::string_view optname) -> bool { if(auto optval = al::getenv(envname)) { - if(al::strcasecmp(optval->c_str(), "true") == 0 - || strtol(optval->c_str(), nullptr, 0) == 1) - return true; - return false; + return al::case_compare(*optval, "true"sv) == 0 + || strtol(optval->c_str(), nullptr, 0) == 1; } - return GetConfigValueBool(nullptr, "game_compat", optname, false); + return GetConfigValueBool({}, "game_compat", optname, false); }; - sBufferSubDataCompat = checkflag("__ALSOFT_ENABLE_SUB_DATA_EXT", "enable-sub-data-ext"); - compatflags.set(CompatFlags::ReverseX, checkflag("__ALSOFT_REVERSE_X", "reverse-x")); - compatflags.set(CompatFlags::ReverseY, checkflag("__ALSOFT_REVERSE_Y", "reverse-y")); - compatflags.set(CompatFlags::ReverseZ, checkflag("__ALSOFT_REVERSE_Z", "reverse-z")); + sBufferSubDataCompat = checkflag("__ALSOFT_ENABLE_SUB_DATA_EXT", "enable-sub-data-ext"sv); + compatflags.set(CompatFlags::ReverseX, checkflag("__ALSOFT_REVERSE_X", "reverse-x"sv)); + compatflags.set(CompatFlags::ReverseY, checkflag("__ALSOFT_REVERSE_Y", "reverse-y"sv)); + compatflags.set(CompatFlags::ReverseZ, checkflag("__ALSOFT_REVERSE_Z", "reverse-z"sv)); - aluInit(compatflags, ConfigValueFloat(nullptr, "game_compat", "nfc-scale").value_or(1.0f)); + aluInit(compatflags, ConfigValueFloat({}, "game_compat"sv, "nfc-scale"sv).value_or(1.0f)); } - Voice::InitMixer(ConfigValueStr(nullptr, nullptr, "resampler")); + Voice::InitMixer(ConfigValueStr({}, {}, "resampler"sv)); - if(auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "decode-filter")) + if(auto uhjfiltopt = ConfigValueStr({}, "uhj"sv, "decode-filter"sv)) { - if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0) + if(al::case_compare(*uhjfiltopt, "fir256"sv) == 0) UhjDecodeQuality = UhjQualityType::FIR256; - else if(al::strcasecmp(uhjfiltopt->c_str(), "fir512") == 0) + else if(al::case_compare(*uhjfiltopt, "fir512"sv) == 0) UhjDecodeQuality = UhjQualityType::FIR512; - else if(al::strcasecmp(uhjfiltopt->c_str(), "iir") == 0) + else if(al::case_compare(*uhjfiltopt, "iir"sv) == 0) UhjDecodeQuality = UhjQualityType::IIR; else - WARN("Unsupported uhj/decode-filter: %s\n", uhjfiltopt->c_str()); + WARN("Unsupported uhj/decode-filter: {}", *uhjfiltopt); } - if(auto uhjfiltopt = ConfigValueStr(nullptr, "uhj", "encode-filter")) + if(auto uhjfiltopt = ConfigValueStr({}, "uhj"sv, "encode-filter"sv)) { - if(al::strcasecmp(uhjfiltopt->c_str(), "fir256") == 0) + if(al::case_compare(*uhjfiltopt, "fir256"sv) == 0) UhjEncodeQuality = UhjQualityType::FIR256; - else if(al::strcasecmp(uhjfiltopt->c_str(), "fir512") == 0) + else if(al::case_compare(*uhjfiltopt, "fir512"sv) == 0) UhjEncodeQuality = UhjQualityType::FIR512; - else if(al::strcasecmp(uhjfiltopt->c_str(), "iir") == 0) + else if(al::case_compare(*uhjfiltopt, "iir"sv) == 0) UhjEncodeQuality = UhjQualityType::IIR; else - WARN("Unsupported uhj/encode-filter: %s\n", uhjfiltopt->c_str()); + WARN("Unsupported uhj/encode-filter: {}", *uhjfiltopt); } - auto traperr = al::getenv("ALSOFT_TRAP_ERROR"); - if(traperr && (al::strcasecmp(traperr->c_str(), "true") == 0 + if(auto traperr = al::getenv("ALSOFT_TRAP_ERROR"); traperr + && (al::case_compare(*traperr, "true"sv) == 0 || std::strtol(traperr->c_str(), nullptr, 0) == 1)) { TrapALError = true; @@ -537,66 +571,69 @@ void alc_initconfig(void) { traperr = al::getenv("ALSOFT_TRAP_AL_ERROR"); if(traperr) - TrapALError = al::strcasecmp(traperr->c_str(), "true") == 0 + TrapALError = al::case_compare(*traperr, "true"sv) == 0 || strtol(traperr->c_str(), nullptr, 0) == 1; else - TrapALError = !!GetConfigValueBool(nullptr, nullptr, "trap-al-error", false); + TrapALError = GetConfigValueBool({}, {}, "trap-al-error"sv, false); traperr = al::getenv("ALSOFT_TRAP_ALC_ERROR"); if(traperr) - TrapALCError = al::strcasecmp(traperr->c_str(), "true") == 0 + TrapALCError = al::case_compare(*traperr, "true"sv) == 0 || strtol(traperr->c_str(), nullptr, 0) == 1; else - TrapALCError = !!GetConfigValueBool(nullptr, nullptr, "trap-alc-error", false); + TrapALCError = GetConfigValueBool({}, {}, "trap-alc-error"sv, false); } - if(auto boostopt = ConfigValueFloat(nullptr, "reverb", "boost")) + if(auto boostopt = ConfigValueFloat({}, "reverb"sv, "boost"sv)) { - const float valf{std::isfinite(*boostopt) ? clampf(*boostopt, -24.0f, 24.0f) : 0.0f}; + const float valf{std::isfinite(*boostopt) ? std::clamp(*boostopt, -24.0f, 24.0f) : 0.0f}; ReverbBoost *= std::pow(10.0f, valf / 20.0f); } - auto BackendListEnd = std::end(BackendList); + auto BackendListEnd = BackendList.end(); auto devopt = al::getenv("ALSOFT_DRIVERS"); - if(devopt || (devopt=ConfigValueStr(nullptr, nullptr, "drivers"))) + if(!devopt) devopt = ConfigValueStr({}, {}, "drivers"sv); + if(devopt) { - auto backendlist_cur = std::begin(BackendList); + auto backendlist_cur = BackendList.begin(); bool endlist{true}; - const char *next{devopt->c_str()}; - do { - const char *devs{next}; - while(isspace(devs[0])) - devs++; - next = strchr(devs, ','); - - const bool delitem{devs[0] == '-'}; - if(devs[0] == '-') devs++; + std::string_view drvlist{*devopt}; + while(!drvlist.empty()) + { + auto nextpos = std::min(drvlist.find(','), drvlist.size()); + auto entry = drvlist.substr(0, nextpos); - if(!devs[0] || devs[0] == ',') + endlist = true; + if(nextpos < drvlist.size()) { endlist = false; - continue; + while(nextpos < drvlist.size() && drvlist[nextpos] == ',') + ++nextpos; } - endlist = true; + drvlist.remove_prefix(nextpos); + + while(!entry.empty() && std::isspace(entry.front())) + entry.remove_prefix(1); + const bool delitem{!entry.empty() && entry.front() == '-'}; + if(delitem) entry.remove_prefix(1); + + while(!entry.empty() && std::isspace(entry.back())) + entry.remove_suffix(1); + if(entry.empty()) + continue; - size_t len{next ? (static_cast(next-devs)) : strlen(devs)}; - while(len > 0 && isspace(devs[len-1])) --len; #ifdef HAVE_WASAPI /* HACK: For backwards compatibility, convert backend references of * mmdevapi to wasapi. This should eventually be removed. */ - if(len == 8 && strncmp(devs, "mmdevapi", len) == 0) - { - devs = "wasapi"; - len = 6; - } + if(entry == "mmdevapi"sv) + entry = "wasapi"sv; #endif - auto find_backend = [devs,len](const BackendInfo &backend) -> bool - { return len == strlen(backend.name) && strncmp(backend.name, devs, len) == 0; }; - auto this_backend = std::find_if(std::begin(BackendList), BackendListEnd, - find_backend); + auto find_backend = [entry](const BackendInfo &backend) -> bool + { return entry == backend.name; }; + auto this_backend = std::find_if(BackendList.begin(), BackendListEnd, find_backend); if(this_backend == BackendListEnd) continue; @@ -605,11 +642,25 @@ void alc_initconfig(void) BackendListEnd = std::move(this_backend+1, BackendListEnd, this_backend); else backendlist_cur = std::rotate(backendlist_cur, this_backend, this_backend+1); - } while(next++); + } if(endlist) BackendListEnd = backendlist_cur; } + else + { + /* Exclude the null and wave writer backends from being considered by + * default. This ensures there will be no available devices if none of + * the normal backends are usable, rather than pretending there is a + * device but outputs nowhere. + */ + while(BackendListEnd != BackendList.begin()) + { + --BackendListEnd; + if(BackendListEnd->name == "null"sv) + break; + } + } auto init_backend = [](BackendInfo &backend) -> void { @@ -619,79 +670,84 @@ void alc_initconfig(void) BackendFactory &factory = backend.getFactory(); if(!factory.init()) { - WARN("Failed to initialize backend \"%s\"\n", backend.name); + WARN("Failed to initialize backend \"{}\"", backend.name); return; } - TRACE("Initialized backend \"%s\"\n", backend.name); + TRACE("Initialized backend \"{}\"", backend.name); if(!PlaybackFactory && factory.querySupport(BackendType::Playback)) { PlaybackFactory = &factory; - TRACE("Added \"%s\" for playback\n", backend.name); + TRACE("Added \"{}\" for playback", backend.name); } if(!CaptureFactory && factory.querySupport(BackendType::Capture)) { CaptureFactory = &factory; - TRACE("Added \"%s\" for capture\n", backend.name); + TRACE("Added \"{}\" for capture", backend.name); } }; - std::for_each(std::begin(BackendList), BackendListEnd, init_backend); + std::for_each(BackendList.begin(), BackendListEnd, init_backend); LoopbackBackendFactory::getFactory().init(); if(!PlaybackFactory) - WARN("No playback backend available!\n"); + WARN("No playback backend available!"); if(!CaptureFactory) - WARN("No capture backend available!\n"); + WARN("No capture backend available!"); - if(auto exclopt = ConfigValueStr(nullptr, nullptr, "excludefx")) + if(auto exclopt = ConfigValueStr({}, {}, "excludefx"sv)) { - const char *next{exclopt->c_str()}; - do { - const char *str{next}; - next = strchr(str, ','); - - if(!str[0] || next == str) - continue; + std::string_view exclude{*exclopt}; + while(!exclude.empty()) + { + const auto nextpos = exclude.find(','); + const auto entry = exclude.substr(0, nextpos); + exclude.remove_prefix((nextpos < exclude.size()) ? nextpos+1 : exclude.size()); - size_t len{next ? static_cast(next-str) : strlen(str)}; - for(const EffectList &effectitem : gEffectList) - { - if(len == strlen(effectitem.name) && - strncmp(effectitem.name, str, len) == 0) - DisabledEffects[effectitem.type] = true; - } - } while(next++); + std::for_each(gEffectList.cbegin(), gEffectList.cend(), + [entry](const EffectList &effectitem) noexcept + { + if(entry == std::data(effectitem.name)) + DisabledEffects.set(effectitem.type); + }); + } } InitEffect(&ALCcontext::sDefaultEffect); auto defrevopt = al::getenv("ALSOFT_DEFAULT_REVERB"); - if(defrevopt || (defrevopt=ConfigValueStr(nullptr, nullptr, "default-reverb"))) - LoadReverbPreset(defrevopt->c_str(), &ALCcontext::sDefaultEffect); + if(!defrevopt) defrevopt = ConfigValueStr({}, {}, "default-reverb"sv); + if(defrevopt) LoadReverbPreset(*defrevopt, &ALCcontext::sDefaultEffect); -#ifdef ALSOFT_EAX +#if ALSOFT_EAX + if(const auto eax_enable_opt = ConfigValueBool({}, "eax", "enable")) { - static constexpr char eax_block_name[] = "eax"; + eax_g_is_enabled = *eax_enable_opt; + if(!eax_g_is_enabled) + TRACE("EAX disabled by a configuration."); + } + else + eax_g_is_enabled = true; - if(const auto eax_enable_opt = ConfigValueBool(nullptr, eax_block_name, "enable")) - { - eax_g_is_enabled = *eax_enable_opt; - if(!eax_g_is_enabled) - TRACE("%s\n", "EAX disabled by a configuration."); - } - else - eax_g_is_enabled = true; + if((DisabledEffects.test(EAXREVERB_EFFECT) || DisabledEffects.test(CHORUS_EFFECT)) + && eax_g_is_enabled) + { + eax_g_is_enabled = false; + TRACE("EAX disabled because {} disabled.", + (DisabledEffects.test(EAXREVERB_EFFECT) && DisabledEffects.test(CHORUS_EFFECT)) + ? "EAXReverb and Chorus are"sv : + DisabledEffects.test(EAXREVERB_EFFECT) ? "EAXReverb is"sv : + DisabledEffects.test(CHORUS_EFFECT) ? "Chorus is"sv : ""sv); + } - if((DisabledEffects[EAXREVERB_EFFECT] || DisabledEffects[CHORUS_EFFECT]) - && eax_g_is_enabled) + if(eax_g_is_enabled) + { + if(auto optval = al::getenv("ALSOFT_EAX_TRACE_COMMITS")) { - eax_g_is_enabled = false; - TRACE("EAX disabled because %s disabled.\n", - (DisabledEffects[EAXREVERB_EFFECT] && DisabledEffects[CHORUS_EFFECT]) - ? "EAXReverb and Chorus are" : - DisabledEffects[EAXREVERB_EFFECT] ? "EAXReverb is" : - DisabledEffects[CHORUS_EFFECT] ? "Chorus is" : ""); + EaxTraceCommits = al::case_compare(*optval, "true"sv) == 0 + || strtol(optval->c_str(), nullptr, 0) == 1; } + else + EaxTraceCommits = GetConfigValueBool({}, "eax"sv, "trace-commits"sv, false); } #endif // ALSOFT_EAX } @@ -706,63 +762,107 @@ void ProbeAllDevicesList() { InitConfig(); - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; if(!PlaybackFactory) + { + decltype(alcAllDevicesArray){}.swap(alcAllDevicesArray); decltype(alcAllDevicesList){}.swap(alcAllDevicesList); + } else { - std::string names{PlaybackFactory->probe(BackendType::Playback)}; - if(names.empty()) names += '\0'; - names.swap(alcAllDevicesList); + alcAllDevicesArray = PlaybackFactory->enumerate(BackendType::Playback); + if(const auto prefix = GetDevicePrefix(); !prefix.empty()) + std::for_each(alcAllDevicesArray.begin(), alcAllDevicesArray.end(), + [prefix](std::string &name) { name.insert(0, prefix); }); + + decltype(alcAllDevicesList){}.swap(alcAllDevicesList); + if(alcAllDevicesArray.empty()) + alcAllDevicesList += '\0'; + else for(auto &devname : alcAllDevicesArray) + alcAllDevicesList.append(devname) += '\0'; } } void ProbeCaptureDeviceList() { InitConfig(); - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; if(!CaptureFactory) + { + decltype(alcCaptureDeviceArray){}.swap(alcCaptureDeviceArray); decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList); + } else { - std::string names{CaptureFactory->probe(BackendType::Capture)}; - if(names.empty()) names += '\0'; - names.swap(alcCaptureDeviceList); + alcCaptureDeviceArray = CaptureFactory->enumerate(BackendType::Capture); + if(const auto prefix = GetDevicePrefix(); !prefix.empty()) + std::for_each(alcCaptureDeviceArray.begin(), alcCaptureDeviceArray.end(), + [prefix](std::string &name) { name.insert(0, prefix); }); + + decltype(alcCaptureDeviceList){}.swap(alcCaptureDeviceList); + if(alcCaptureDeviceArray.empty()) + alcCaptureDeviceList += '\0'; + else for(auto &devname : alcCaptureDeviceArray) + alcCaptureDeviceList.append(devname) += '\0'; } } +al::span SpanFromAttributeList(const ALCint *attribs) noexcept +{ + al::span attrSpan; + if(attribs) + { + const ALCint *attrEnd{attribs}; + while(*attrEnd != 0) + attrEnd += 2; /* NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + attrSpan = {attribs, attrEnd}; + } + return attrSpan; +} + struct DevFmtPair { DevFmtChannels chans; DevFmtType type; }; std::optional DecomposeDevFormat(ALenum format) { - static const struct { + struct FormatType { ALenum format; DevFmtChannels channels; DevFmtType type; - } list[] = { - { AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte }, - { AL_FORMAT_MONO16, DevFmtMono, DevFmtShort }, - { AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat }, - - { AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte }, - { AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort }, - { AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat }, - - { AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte }, - { AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort }, - { AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat }, - - { AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte }, - { AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort }, - { AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat }, - - { AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte }, - { AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort }, - { AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat }, - - { AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte }, - { AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort }, - { AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat }, + }; + static constexpr std::array list{ + FormatType{AL_FORMAT_MONO8, DevFmtMono, DevFmtUByte}, + FormatType{AL_FORMAT_MONO16, DevFmtMono, DevFmtShort}, + FormatType{AL_FORMAT_MONO_I32, DevFmtMono, DevFmtInt}, + FormatType{AL_FORMAT_MONO_FLOAT32, DevFmtMono, DevFmtFloat}, + + FormatType{AL_FORMAT_STEREO8, DevFmtStereo, DevFmtUByte}, + FormatType{AL_FORMAT_STEREO16, DevFmtStereo, DevFmtShort}, + FormatType{AL_FORMAT_STEREO_I32, DevFmtStereo, DevFmtInt}, + FormatType{AL_FORMAT_STEREO_FLOAT32, DevFmtStereo, DevFmtFloat}, + + FormatType{AL_FORMAT_QUAD8, DevFmtQuad, DevFmtUByte}, + FormatType{AL_FORMAT_QUAD16, DevFmtQuad, DevFmtShort}, + FormatType{AL_FORMAT_QUAD32, DevFmtQuad, DevFmtFloat}, + FormatType{AL_FORMAT_QUAD_I32, DevFmtQuad, DevFmtInt}, + FormatType{AL_FORMAT_QUAD_FLOAT32, DevFmtQuad, DevFmtFloat}, + + FormatType{AL_FORMAT_51CHN8, DevFmtX51, DevFmtUByte}, + FormatType{AL_FORMAT_51CHN16, DevFmtX51, DevFmtShort}, + FormatType{AL_FORMAT_51CHN32, DevFmtX51, DevFmtFloat}, + FormatType{AL_FORMAT_51CHN_I32, DevFmtX51, DevFmtInt}, + FormatType{AL_FORMAT_51CHN_FLOAT32, DevFmtX51, DevFmtFloat}, + + FormatType{AL_FORMAT_61CHN8, DevFmtX61, DevFmtUByte}, + FormatType{AL_FORMAT_61CHN16, DevFmtX61, DevFmtShort}, + FormatType{AL_FORMAT_61CHN32, DevFmtX61, DevFmtFloat}, + FormatType{AL_FORMAT_61CHN_I32, DevFmtX61, DevFmtInt}, + FormatType{AL_FORMAT_61CHN_FLOAT32, DevFmtX61, DevFmtFloat}, + + FormatType{AL_FORMAT_71CHN8, DevFmtX71, DevFmtUByte}, + FormatType{AL_FORMAT_71CHN16, DevFmtX71, DevFmtShort}, + FormatType{AL_FORMAT_71CHN32, DevFmtX71, DevFmtFloat}, + FormatType{AL_FORMAT_71CHN_I32, DevFmtX71, DevFmtInt}, + FormatType{AL_FORMAT_71CHN_FLOAT32, DevFmtX71, DevFmtFloat}, }; for(const auto &item : list) @@ -786,7 +886,7 @@ std::optional DevFmtTypeFromEnum(ALCenum type) case ALC_UNSIGNED_INT_SOFT: return DevFmtUInt; case ALC_FLOAT_SOFT: return DevFmtFloat; } - WARN("Unsupported format type: 0x%04x\n", type); + WARN("Unsupported format type: {:#04x}", as_unsigned(type)); return std::nullopt; } ALCenum EnumFromDevFmt(DevFmtType type) @@ -801,7 +901,7 @@ ALCenum EnumFromDevFmt(DevFmtType type) case DevFmtUInt: return ALC_UNSIGNED_INT_SOFT; case DevFmtFloat: return ALC_FLOAT_SOFT; } - throw std::runtime_error{"Invalid DevFmtType: "+std::to_string(int(type))}; + throw std::runtime_error{fmt::format("Invalid DevFmtType: {}", int{al::to_underlying(type)})}; } std::optional DevFmtChannelsFromEnum(ALCenum channels) @@ -816,7 +916,7 @@ std::optional DevFmtChannelsFromEnum(ALCenum channels) case ALC_7POINT1_SOFT: return DevFmtX71; case ALC_BFORMAT3D_SOFT: return DevFmtAmbi3D; } - WARN("Unsupported format channels: 0x%04x\n", channels); + WARN("Unsupported format channels: {:#04x}", as_unsigned(channels)); return std::nullopt; } ALCenum EnumFromDevFmt(DevFmtChannels channels) @@ -832,9 +932,11 @@ ALCenum EnumFromDevFmt(DevFmtChannels channels) case DevFmtAmbi3D: return ALC_BFORMAT3D_SOFT; /* FIXME: Shouldn't happen. */ case DevFmtX714: + case DevFmtX7144: case DevFmtX3D71: break; } - throw std::runtime_error{"Invalid DevFmtChannels: "+std::to_string(int(channels))}; + throw std::runtime_error{fmt::format("Invalid DevFmtChannels: {}", + int{al::to_underlying(channels)})}; } std::optional DevAmbiLayoutFromEnum(ALCenum layout) @@ -844,7 +946,7 @@ std::optional DevAmbiLayoutFromEnum(ALCenum layout) case ALC_FUMA_SOFT: return DevAmbiLayout::FuMa; case ALC_ACN_SOFT: return DevAmbiLayout::ACN; } - WARN("Unsupported ambisonic layout: 0x%04x\n", layout); + WARN("Unsupported ambisonic layout: {:#04x}", as_unsigned(layout)); return std::nullopt; } ALCenum EnumFromDevAmbi(DevAmbiLayout layout) @@ -854,7 +956,8 @@ ALCenum EnumFromDevAmbi(DevAmbiLayout layout) case DevAmbiLayout::FuMa: return ALC_FUMA_SOFT; case DevAmbiLayout::ACN: return ALC_ACN_SOFT; } - throw std::runtime_error{"Invalid DevAmbiLayout: "+std::to_string(int(layout))}; + throw std::runtime_error{fmt::format("Invalid DevAmbiLayout: {}", + int{al::to_underlying(layout)})}; } std::optional DevAmbiScalingFromEnum(ALCenum scaling) @@ -865,7 +968,7 @@ std::optional DevAmbiScalingFromEnum(ALCenum scaling) case ALC_SN3D_SOFT: return DevAmbiScaling::SN3D; case ALC_N3D_SOFT: return DevAmbiScaling::N3D; } - WARN("Unsupported ambisonic scaling: 0x%04x\n", scaling); + WARN("Unsupported ambisonic scaling: {:#04x}", as_unsigned(scaling)); return std::nullopt; } ALCenum EnumFromDevAmbi(DevAmbiScaling scaling) @@ -876,86 +979,70 @@ ALCenum EnumFromDevAmbi(DevAmbiScaling scaling) case DevAmbiScaling::SN3D: return ALC_SN3D_SOFT; case DevAmbiScaling::N3D: return ALC_N3D_SOFT; } - throw std::runtime_error{"Invalid DevAmbiScaling: "+std::to_string(int(scaling))}; + throw std::runtime_error{fmt::format("Invalid DevAmbiScaling: {}", + int{al::to_underlying(scaling)})}; } -/* Downmixing channel arrays, to map the given format's missing channels to - * existing ones. Based on Wine's DSound downmix values, which are based on - * PulseAudio's. +/* Downmixing channel arrays, to map a device format's missing channels to + * existing ones. Based on what PipeWire does, though simplified. */ -constexpr std::array FrontStereoSplit{{ - {FrontLeft, 0.5f}, {FrontRight, 0.5f} -}}; -constexpr std::array FrontLeft9{{ - {FrontLeft, 1.0f/9.0f} -}}; -constexpr std::array FrontRight9{{ - {FrontRight, 1.0f/9.0f} -}}; -constexpr std::array BackMonoToFrontSplit{{ - {FrontLeft, 0.5f/9.0f}, {FrontRight, 0.5f/9.0f} -}}; -constexpr std::array LeftStereoSplit{{ - {FrontLeft, 0.5f}, {BackLeft, 0.5f} -}}; -constexpr std::array RightStereoSplit{{ - {FrontRight, 0.5f}, {BackRight, 0.5f} -}}; -constexpr std::array BackStereoSplit{{ - {BackLeft, 0.5f}, {BackRight, 0.5f} -}}; -constexpr std::array SideStereoSplit{{ - {SideLeft, 0.5f}, {SideRight, 0.5f} -}}; -constexpr std::array ToSideLeft{{ - {SideLeft, 1.0f} -}}; -constexpr std::array ToSideRight{{ - {SideRight, 1.0f} -}}; -constexpr std::array BackLeftSplit{{ - {SideLeft, 0.5f}, {BackCenter, 0.5f} -}}; -constexpr std::array BackRightSplit{{ - {SideRight, 0.5f}, {BackCenter, 0.5f} -}}; - -const std::array StereoDownmix{{ - { FrontCenter, FrontStereoSplit }, - { SideLeft, FrontLeft9 }, - { SideRight, FrontRight9 }, - { BackLeft, FrontLeft9 }, - { BackRight, FrontRight9 }, - { BackCenter, BackMonoToFrontSplit }, -}}; -const std::array QuadDownmix{{ - { FrontCenter, FrontStereoSplit }, - { SideLeft, LeftStereoSplit }, - { SideRight, RightStereoSplit }, - { BackCenter, BackStereoSplit }, -}}; -const std::array X51Downmix{{ - { BackLeft, ToSideLeft }, - { BackRight, ToSideRight }, - { BackCenter, SideStereoSplit }, -}}; -const std::array X61Downmix{{ - { BackLeft, BackLeftSplit }, - { BackRight, BackRightSplit }, -}}; -const std::array X71Downmix{{ - { BackCenter, BackStereoSplit }, -}}; - - -std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const float threshold) +constexpr float inv_sqrt2f{static_cast(1.0 / al::numbers::sqrt2)}; +constexpr std::array FrontStereo3dB{ + InputRemixMap::TargetMix{FrontLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{FrontRight, inv_sqrt2f} +}; +constexpr std::array FrontStereo6dB{ + InputRemixMap::TargetMix{FrontLeft, 0.5f}, + InputRemixMap::TargetMix{FrontRight, 0.5f} +}; +constexpr std::array SideStereo3dB{ + InputRemixMap::TargetMix{SideLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{SideRight, inv_sqrt2f} +}; +constexpr std::array BackStereo3dB{ + InputRemixMap::TargetMix{BackLeft, inv_sqrt2f}, + InputRemixMap::TargetMix{BackRight, inv_sqrt2f} +}; +constexpr std::array FrontLeft3dB{InputRemixMap::TargetMix{FrontLeft, inv_sqrt2f}}; +constexpr std::array FrontRight3dB{InputRemixMap::TargetMix{FrontRight, inv_sqrt2f}}; +constexpr std::array SideLeft0dB{InputRemixMap::TargetMix{SideLeft, 1.0f}}; +constexpr std::array SideRight0dB{InputRemixMap::TargetMix{SideRight, 1.0f}}; +constexpr std::array BackLeft0dB{InputRemixMap::TargetMix{BackLeft, 1.0f}}; +constexpr std::array BackRight0dB{InputRemixMap::TargetMix{BackRight, 1.0f}}; +constexpr std::array BackCenter3dB{InputRemixMap::TargetMix{BackCenter, inv_sqrt2f}}; + +constexpr std::array StereoDownmix{ + InputRemixMap{FrontCenter, FrontStereo3dB}, + InputRemixMap{SideLeft, FrontLeft3dB}, + InputRemixMap{SideRight, FrontRight3dB}, + InputRemixMap{BackLeft, FrontLeft3dB}, + InputRemixMap{BackRight, FrontRight3dB}, + InputRemixMap{BackCenter, FrontStereo6dB}, +}; +constexpr std::array QuadDownmix{ + InputRemixMap{FrontCenter, FrontStereo3dB}, + InputRemixMap{SideLeft, BackLeft0dB}, + InputRemixMap{SideRight, BackRight0dB}, + InputRemixMap{BackCenter, BackStereo3dB}, +}; +constexpr std::array X51Downmix{ + InputRemixMap{BackLeft, SideLeft0dB}, + InputRemixMap{BackRight, SideRight0dB}, + InputRemixMap{BackCenter, SideStereo3dB}, +}; +constexpr std::array X61Downmix{ + InputRemixMap{BackLeft, BackCenter3dB}, + InputRemixMap{BackRight, BackCenter3dB}, +}; +constexpr std::array X71Downmix{ + InputRemixMap{BackCenter, BackStereo3dB}, +}; + + +auto CreateDeviceLimiter(const al::Device *device, const float threshold) + -> std::unique_ptr { - static constexpr bool AutoKnee{true}; - static constexpr bool AutoAttack{true}; - static constexpr bool AutoRelease{true}; - static constexpr bool AutoPostGain{true}; - static constexpr bool AutoDeclip{true}; static constexpr float LookAheadTime{0.001f}; static constexpr float HoldTime{0.002f}; static constexpr float PreGainDb{0.0f}; @@ -965,9 +1052,12 @@ std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const f static constexpr float AttackTime{0.02f}; static constexpr float ReleaseTime{0.2f}; - return Compressor::Create(device->RealOut.Buffer.size(), static_cast(device->Frequency), - AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, LookAheadTime, HoldTime, - PreGainDb, PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime); + const auto flags = Compressor::FlagBits{}.set(Compressor::AutoKnee).set(Compressor::AutoAttack) + .set(Compressor::AutoRelease).set(Compressor::AutoPostGain).set(Compressor::AutoDeclip); + + return Compressor::Create(device->RealOut.Buffer.size(), + static_cast(device->mSampleRate), flags, LookAheadTime, HoldTime, PreGainDb, + PostGainDb, threshold, Ratio, KneeDb, AttackTime, ReleaseTime); } /** @@ -976,23 +1066,35 @@ std::unique_ptr CreateDeviceLimiter(const ALCdevice *device, const f * to jump forward or back. Must not be called while the device is running/ * mixing. */ -inline void UpdateClockBase(ALCdevice *device) +inline void UpdateClockBase(al::Device *device) { - IncrementRef(device->MixCount); - device->ClockBase += nanoseconds{seconds{device->SamplesDone}} / device->Frequency; - device->SamplesDone = 0; - IncrementRef(device->MixCount); + using std::chrono::duration_cast; + + const auto mixLock = device->getWriteMixLock(); + + auto clockBaseSec = device->mClockBaseSec.load(std::memory_order_relaxed); + auto clockBaseNSec = nanoseconds{device->mClockBaseNSec.load(std::memory_order_relaxed)}; + clockBaseNSec += nanoseconds{seconds{device->mSamplesDone.load(std::memory_order_relaxed)}} + / device->mSampleRate; + + clockBaseSec += duration_cast(clockBaseNSec); + clockBaseNSec %= seconds{1}; + + device->mClockBaseSec.store(clockBaseSec, std::memory_order_relaxed); + device->mClockBaseNSec.store(duration_cast(clockBaseNSec), + std::memory_order_relaxed); + device->mSamplesDone.store(0, std::memory_order_relaxed); } /** * Updates device parameters according to the attribute list (caller is * responsible for holding the list lock). */ -ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) +auto UpdateDeviceParams(al::Device *device, const al::span attrList) -> ALCenum { - if((!attrList || !attrList[0]) && device->Type == DeviceType::Loopback) + if(attrList.empty() && device->Type == DeviceType::Loopback) { - WARN("Missing attributes for loopback device\n"); + WARN("Missing attributes for loopback device"); return ALC_INVALID_VALUE; } @@ -1006,8 +1108,8 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) std::optional opttype; std::optional optlayout; std::optional optscale; - uint period_size{DEFAULT_UPDATE_SIZE}; - uint buffer_size{DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES}; + uint period_size{DefaultUpdateSize}; + uint buffer_size{DefaultUpdateSize * DefaultNumUpdates}; int hrtf_id{-1}; uint aorder{0u}; @@ -1015,154 +1117,153 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) { /* Get default settings from the user configuration */ - if(auto freqopt = device->configValue(nullptr, "frequency")) + if(auto freqopt = device->configValue({}, "frequency")) { - optsrate = clampu(*freqopt, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE); + optsrate = std::clamp(*freqopt, MinOutputRate, MaxOutputRate); - const double scale{static_cast(*optsrate) / DEFAULT_OUTPUT_RATE}; - period_size = static_cast(period_size*scale + 0.5); + const double scale{static_cast(*optsrate) / double{DefaultOutputRate}}; + period_size = static_cast(std::lround(period_size * scale)); } - if(auto persizeopt = device->configValue(nullptr, "period_size")) - period_size = clampu(*persizeopt, 64, 8192); - if(auto numperopt = device->configValue(nullptr, "periods")) - buffer_size = clampu(*numperopt, 2, 16) * period_size; + if(auto persizeopt = device->configValue({}, "period_size")) + period_size = std::clamp(*persizeopt, 64u, 8192u); + if(auto numperopt = device->configValue({}, "periods")) + buffer_size = std::clamp(*numperopt, 2u, 16u) * period_size; else - buffer_size = period_size * DEFAULT_NUM_UPDATES; + buffer_size = period_size * uint{DefaultNumUpdates}; - if(auto typeopt = device->configValue(nullptr, "sample-type")) + if(auto typeopt = device->configValue({}, "sample-type")) { - static constexpr struct TypeMap { - const char name[8]; + struct TypeMap { + std::string_view name; DevFmtType type; - } typelist[] = { - { "int8", DevFmtByte }, - { "uint8", DevFmtUByte }, - { "int16", DevFmtShort }, - { "uint16", DevFmtUShort }, - { "int32", DevFmtInt }, - { "uint32", DevFmtUInt }, - { "float32", DevFmtFloat }, + }; + constexpr std::array typelist{ + TypeMap{"int8"sv, DevFmtByte }, + TypeMap{"uint8"sv, DevFmtUByte }, + TypeMap{"int16"sv, DevFmtShort }, + TypeMap{"uint16"sv, DevFmtUShort}, + TypeMap{"int32"sv, DevFmtInt }, + TypeMap{"uint32"sv, DevFmtUInt }, + TypeMap{"float32"sv, DevFmtFloat }, }; - const ALCchar *fmt{typeopt->c_str()}; - auto iter = std::find_if(std::begin(typelist), std::end(typelist), - [fmt](const TypeMap &entry) -> bool - { return al::strcasecmp(entry.name, fmt) == 0; }); - if(iter == std::end(typelist)) - ERR("Unsupported sample-type: %s\n", fmt); + auto iter = std::find_if(typelist.begin(), typelist.end(), + [svfmt=std::string_view{*typeopt}](const TypeMap &entry) -> bool + { return al::case_compare(entry.name, svfmt) == 0; }); + if(iter == typelist.end()) + ERR("Unsupported sample-type: {}", *typeopt); else opttype = iter->type; } - if(auto chanopt = device->configValue(nullptr, "channels")) + if(auto chanopt = device->configValue({}, "channels")) { - static constexpr struct ChannelMap { - const char name[16]; + struct ChannelMap { + std::string_view name; DevFmtChannels chans; uint8_t order; - } chanlist[] = { - { "mono", DevFmtMono, 0 }, - { "stereo", DevFmtStereo, 0 }, - { "quad", DevFmtQuad, 0 }, - { "surround51", DevFmtX51, 0 }, - { "surround61", DevFmtX61, 0 }, - { "surround71", DevFmtX71, 0 }, - { "surround714", DevFmtX714, 0 }, - { "surround3d71", DevFmtX3D71, 0 }, - { "surround51rear", DevFmtX51, 0 }, - { "ambi1", DevFmtAmbi3D, 1 }, - { "ambi2", DevFmtAmbi3D, 2 }, - { "ambi3", DevFmtAmbi3D, 3 }, + }; + constexpr std::array chanlist{ + ChannelMap{"mono"sv, DevFmtMono, 0}, + ChannelMap{"stereo"sv, DevFmtStereo, 0}, + ChannelMap{"quad"sv, DevFmtQuad, 0}, + ChannelMap{"surround51"sv, DevFmtX51, 0}, + ChannelMap{"surround61"sv, DevFmtX61, 0}, + ChannelMap{"surround71"sv, DevFmtX71, 0}, + ChannelMap{"surround714"sv, DevFmtX714, 0}, + ChannelMap{"surround7144"sv, DevFmtX7144, 0}, + ChannelMap{"surround3d71"sv, DevFmtX3D71, 0}, + ChannelMap{"surround51rear"sv, DevFmtX51, 0}, + ChannelMap{"ambi1"sv, DevFmtAmbi3D, 1}, + ChannelMap{"ambi2"sv, DevFmtAmbi3D, 2}, + ChannelMap{"ambi3"sv, DevFmtAmbi3D, 3}, }; - const ALCchar *fmt{chanopt->c_str()}; - auto iter = std::find_if(std::begin(chanlist), std::end(chanlist), - [fmt](const ChannelMap &entry) -> bool - { return al::strcasecmp(entry.name, fmt) == 0; }); - if(iter == std::end(chanlist)) - ERR("Unsupported channels: %s\n", fmt); + auto iter = std::find_if(chanlist.begin(), chanlist.end(), + [svfmt=std::string_view{*chanopt}](const ChannelMap &entry) -> bool + { return al::case_compare(entry.name, svfmt) == 0; }); + if(iter == chanlist.end()) + ERR("Unsupported channels: {}", *chanopt); else { optchans = iter->chans; aorder = iter->order; } } - if(auto ambiopt = device->configValue(nullptr, "ambi-format")) + if(auto ambiopt = device->configValue({}, "ambi-format"sv)) { - const ALCchar *fmt{ambiopt->c_str()}; - if(al::strcasecmp(fmt, "fuma") == 0) + if(al::case_compare(*ambiopt, "fuma"sv) == 0) { optlayout = DevAmbiLayout::FuMa; optscale = DevAmbiScaling::FuMa; } - else if(al::strcasecmp(fmt, "acn+fuma") == 0) + else if(al::case_compare(*ambiopt, "acn+fuma"sv) == 0) { optlayout = DevAmbiLayout::ACN; optscale = DevAmbiScaling::FuMa; } - else if(al::strcasecmp(fmt, "ambix") == 0 || al::strcasecmp(fmt, "acn+sn3d") == 0) + else if(al::case_compare(*ambiopt, "ambix"sv) == 0 + || al::case_compare(*ambiopt, "acn+sn3d"sv) == 0) { optlayout = DevAmbiLayout::ACN; optscale = DevAmbiScaling::SN3D; } - else if(al::strcasecmp(fmt, "acn+n3d") == 0) + else if(al::case_compare(*ambiopt, "acn+n3d"sv) == 0) { optlayout = DevAmbiLayout::ACN; optscale = DevAmbiScaling::N3D; } else - ERR("Unsupported ambi-format: %s\n", fmt); + ERR("Unsupported ambi-format: {}", *ambiopt); } - if(auto hrtfopt = device->configValue(nullptr, "hrtf")) + if(auto hrtfopt = device->configValue({}, "hrtf"sv)) { - WARN("general/hrtf is deprecated, please use stereo-encoding instead\n"); + WARN("general/hrtf is deprecated, please use stereo-encoding instead"); - const char *hrtf{hrtfopt->c_str()}; - if(al::strcasecmp(hrtf, "true") == 0) + if(al::case_compare(*hrtfopt, "true"sv) == 0) stereomode = StereoEncoding::Hrtf; - else if(al::strcasecmp(hrtf, "false") == 0) + else if(al::case_compare(*hrtfopt, "false"sv) == 0) { if(!stereomode || *stereomode == StereoEncoding::Hrtf) stereomode = StereoEncoding::Default; } - else if(al::strcasecmp(hrtf, "auto") != 0) - ERR("Unexpected hrtf value: %s\n", hrtf); + else if(al::case_compare(*hrtfopt, "auto"sv) != 0) + ERR("Unexpected hrtf value: {}", *hrtfopt); } } - if(auto encopt = device->configValue(nullptr, "stereo-encoding")) + if(auto encopt = device->configValue({}, "stereo-encoding"sv)) { - const char *mode{encopt->c_str()}; - if(al::strcasecmp(mode, "basic") == 0 || al::strcasecmp(mode, "panpot") == 0) + if(al::case_compare(*encopt, "basic"sv) == 0 || al::case_compare(*encopt, "panpot"sv) == 0) stereomode = StereoEncoding::Basic; - else if(al::strcasecmp(mode, "uhj") == 0) + else if(al::case_compare(*encopt, "uhj") == 0) stereomode = StereoEncoding::Uhj; - else if(al::strcasecmp(mode, "hrtf") == 0) + else if(al::case_compare(*encopt, "hrtf") == 0) stereomode = StereoEncoding::Hrtf; else - ERR("Unexpected stereo-encoding: %s\n", mode); + ERR("Unexpected stereo-encoding: {}", *encopt); } // Check for app-specified attributes - if(attrList && attrList[0]) + if(!attrList.empty()) { ALenum outmode{ALC_ANY_SOFT}; std::optional opthrtf; int freqAttr{}; -#define ATTRIBUTE(a) a: TRACE("%s = %d\n", #a, attrList[attrIdx + 1]); - size_t attrIdx{0}; - while(attrList[attrIdx]) +#define ATTRIBUTE(a) a: TRACE("{} = {}", #a, attrList[attrIdx + 1]); +#define ATTRIBUTE_HEX(a) a: TRACE("{} = {:#x}", #a, as_unsigned(attrList[attrIdx + 1])); + for(size_t attrIdx{0};attrIdx < attrList.size();attrIdx+=2) { switch(attrList[attrIdx]) { - case ATTRIBUTE(ALC_FORMAT_CHANNELS_SOFT) + case ATTRIBUTE_HEX(ALC_FORMAT_CHANNELS_SOFT) if(device->Type == DeviceType::Loopback) optchans = DevFmtChannelsFromEnum(attrList[attrIdx + 1]); break; - case ATTRIBUTE(ALC_FORMAT_TYPE_SOFT) + case ATTRIBUTE_HEX(ALC_FORMAT_TYPE_SOFT) if(device->Type == DeviceType::Loopback) opttype = DevFmtTypeFromEnum(attrList[attrIdx + 1]); break; @@ -1171,12 +1272,12 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) freqAttr = attrList[attrIdx + 1]; break; - case ATTRIBUTE(ALC_AMBISONIC_LAYOUT_SOFT) + case ATTRIBUTE_HEX(ALC_AMBISONIC_LAYOUT_SOFT) if(device->Type == DeviceType::Loopback) optlayout = DevAmbiLayoutFromEnum(attrList[attrIdx + 1]); break; - case ATTRIBUTE(ALC_AMBISONIC_SCALING_SOFT) + case ATTRIBUTE_HEX(ALC_AMBISONIC_SCALING_SOFT) if(device->Type == DeviceType::Loopback) optscale = DevAmbiScalingFromEnum(attrList[attrIdx + 1]); break; @@ -1198,8 +1299,8 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) case ATTRIBUTE(ALC_MAX_AUXILIARY_SENDS) numSends = static_cast(attrList[attrIdx + 1]); - if(numSends > INT_MAX) numSends = 0; - else numSends = minu(numSends, MAX_SENDS); + if(numSends > uint{std::numeric_limits::max()}) numSends = 0; + else numSends = std::min(numSends, uint{MaxSendCount}); break; case ATTRIBUTE(ALC_HRTF_SOFT) @@ -1224,25 +1325,32 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) optlimit = std::nullopt; break; - case ATTRIBUTE(ALC_OUTPUT_MODE_SOFT) + case ATTRIBUTE_HEX(ALC_OUTPUT_MODE_SOFT) outmode = attrList[attrIdx + 1]; break; + case ATTRIBUTE_HEX(ALC_CONTEXT_FLAGS_EXT) + /* Handled in alcCreateContext */ + break; + + case ATTRIBUTE(ALC_SYNC) + /* Ignored attribute */ + break; + default: - TRACE("0x%04X = %d (0x%x)\n", attrList[attrIdx], - attrList[attrIdx + 1], attrList[attrIdx + 1]); + TRACE("{:#04x} = {} ({:#x})", as_unsigned(attrList[attrIdx]), + attrList[attrIdx + 1], as_unsigned(attrList[attrIdx + 1])); break; } - - attrIdx += 2; } +#undef ATTRIBUTE_HEX #undef ATTRIBUTE if(device->Type == DeviceType::Loopback) { if(!optchans || !opttype) return ALC_INVALID_VALUE; - if(freqAttr < MIN_OUTPUT_RATE || freqAttr > MAX_OUTPUT_RATE) + if(freqAttr < int{MinOutputRate} || freqAttr > int{MaxOutputRate}) return ALC_INVALID_VALUE; if(*optchans == DevFmtAmbi3D) { @@ -1292,7 +1400,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) if(outmode != ALC_ANY_SOFT) { - using OutputMode = ALCdevice::OutputMode; + using OutputMode = al::Device::OutputMode; switch(OutputMode(outmode)) { case OutputMode::Any: break; @@ -1319,12 +1427,12 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) if(freqAttr) { - uint oldrate = optsrate.value_or(DEFAULT_OUTPUT_RATE); - freqAttr = clampi(freqAttr, MIN_OUTPUT_RATE, MAX_OUTPUT_RATE); + uint oldrate = optsrate.value_or(DefaultOutputRate); + freqAttr = std::clamp(freqAttr, MinOutputRate, MaxOutputRate); const double scale{static_cast(freqAttr) / oldrate}; - period_size = static_cast(period_size*scale + 0.5); - buffer_size = static_cast(buffer_size*scale + 0.5); + period_size = static_cast(std::lround(period_size * scale)); + buffer_size = static_cast(std::lround(buffer_size * scale)); optsrate = static_cast(freqAttr); } } @@ -1332,16 +1440,19 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) /* If a context is already running on the device, stop playback so the * device attributes can be updated. */ - if(device->Flags.test(DeviceRunning)) + if(device->mDeviceState == DeviceState::Playing) + { device->Backend->stop(); - device->Flags.reset(DeviceRunning); + device->mDeviceState = DeviceState::Unprepared; + } UpdateClockBase(device); } - if(device->Flags.test(DeviceRunning)) + if(device->mDeviceState == DeviceState::Playing) return ALC_NO_ERROR; + device->mDeviceState = DeviceState::Unprepared; device->AvgSpeakerDist = 0.0f; device->mNFCtrlFilter = NfcFilter{}; device->mUhjEncoder = nullptr; @@ -1377,7 +1488,7 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) if(device->Type == DeviceType::Loopback) { - device->Frequency = *optsrate; + device->mSampleRate = *optsrate; device->FmtChans = *optchans; device->FmtType = *opttype; if(device->FmtChans == DevFmtAmbi3D) @@ -1393,40 +1504,36 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) device->FmtType = opttype.value_or(DevFmtTypeDefault); device->FmtChans = optchans.value_or(DevFmtChannelsDefault); device->mAmbiOrder = 0; - device->BufferSize = buffer_size; - device->UpdateSize = period_size; - device->Frequency = optsrate.value_or(DEFAULT_OUTPUT_RATE); + device->mBufferSize = buffer_size; + device->mUpdateSize = period_size; + device->mSampleRate = optsrate.value_or(DefaultOutputRate); device->Flags.set(FrequencyRequest, optsrate.has_value()) .set(ChannelsRequest, optchans.has_value()) .set(SampleTypeRequest, opttype.has_value()); if(device->FmtChans == DevFmtAmbi3D) { - device->mAmbiOrder = clampu(aorder, 1, MaxAmbiOrder); + device->mAmbiOrder = std::clamp(aorder, 1u, uint{MaxAmbiOrder}); device->mAmbiLayout = optlayout.value_or(DevAmbiLayout::Default); device->mAmbiScale = optscale.value_or(DevAmbiScaling::Default); if(device->mAmbiOrder > 3 && (device->mAmbiLayout == DevAmbiLayout::FuMa || device->mAmbiScale == DevAmbiScaling::FuMa)) { - ERR("FuMa is incompatible with %d%s order ambisonics (up to 3rd order only)\n", - device->mAmbiOrder, - (((device->mAmbiOrder%100)/10) == 1) ? "th" : - ((device->mAmbiOrder%10) == 1) ? "st" : - ((device->mAmbiOrder%10) == 2) ? "nd" : - ((device->mAmbiOrder%10) == 3) ? "rd" : "th"); + ERR("FuMa is incompatible with {}{} order ambisonics (up to 3rd order only)", + device->mAmbiOrder, GetCounterSuffix(device->mAmbiOrder)); device->mAmbiOrder = 3; } } } - TRACE("Pre-reset: %s%s, %s%s, %s%uhz, %u / %u buffer\n", + TRACE("Pre-reset: {}{}, {}{}, {}{}hz, {} / {} buffer", device->Flags.test(ChannelsRequest)?"*":"", DevFmtChannelsString(device->FmtChans), device->Flags.test(SampleTypeRequest)?"*":"", DevFmtTypeString(device->FmtType), - device->Flags.test(FrequencyRequest)?"*":"", device->Frequency, - device->UpdateSize, device->BufferSize); + device->Flags.test(FrequencyRequest)?"*":"", device->mSampleRate, + device->mUpdateSize, device->mBufferSize); - const uint oldFreq{device->Frequency}; + const uint oldFreq{device->mSampleRate}; const DevFmtChannels oldChans{device->FmtChans}; const DevFmtType oldType{device->FmtType}; try { @@ -1435,44 +1542,43 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) throw al::backend_exception{al::backend_error::DeviceError, "Device reset failure"}; } catch(std::exception &e) { - ERR("Device error: %s\n", e.what()); - device->handleDisconnect("%s", e.what()); + ERR("Device error: {}", e.what()); + device->handleDisconnect("{}", e.what()); return ALC_INVALID_DEVICE; } if(device->FmtChans != oldChans && device->Flags.test(ChannelsRequest)) { - ERR("Failed to set %s, got %s instead\n", DevFmtChannelsString(oldChans), + ERR("Failed to set {}, got {} instead", DevFmtChannelsString(oldChans), DevFmtChannelsString(device->FmtChans)); device->Flags.reset(ChannelsRequest); } if(device->FmtType != oldType && device->Flags.test(SampleTypeRequest)) { - ERR("Failed to set %s, got %s instead\n", DevFmtTypeString(oldType), + ERR("Failed to set {}, got {} instead", DevFmtTypeString(oldType), DevFmtTypeString(device->FmtType)); device->Flags.reset(SampleTypeRequest); } - if(device->Frequency != oldFreq && device->Flags.test(FrequencyRequest)) + if(device->mSampleRate != oldFreq && device->Flags.test(FrequencyRequest)) { - WARN("Failed to set %uhz, got %uhz instead\n", oldFreq, device->Frequency); + WARN("Failed to set {}hz, got {}hz instead", oldFreq, device->mSampleRate); device->Flags.reset(FrequencyRequest); } - TRACE("Post-reset: %s, %s, %uhz, %u / %u buffer\n", + TRACE("Post-reset: {}, {}, {}hz, {} / {} buffer", DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, device->UpdateSize, device->BufferSize); + device->mSampleRate, device->mUpdateSize, device->mBufferSize); if(device->Type != DeviceType::Loopback) { - if(auto modeopt = device->configValue(nullptr, "stereo-mode")) + if(auto modeopt = device->configValue({}, "stereo-mode")) { - const char *mode{modeopt->c_str()}; - if(al::strcasecmp(mode, "headphones") == 0) + if(al::case_compare(*modeopt, "headphones"sv) == 0) device->Flags.set(DirectEar); - else if(al::strcasecmp(mode, "speakers") == 0) + else if(al::case_compare(*modeopt, "speakers"sv) == 0) device->Flags.reset(DirectEar); - else if(al::strcasecmp(mode, "auto") != 0) - ERR("Unexpected stereo-mode: %s\n", mode); + else if(al::case_compare(*modeopt, "auto"sv) != 0) + ERR("Unexpected stereo-mode: {}", *modeopt); } } @@ -1481,27 +1587,27 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) /* Calculate the max number of sources, and split them between the mono and * stereo count given the requested number of stereo sources. */ - if(auto srcsopt = device->configValue(nullptr, "sources")) + if(auto srcsopt = device->configValue({}, "sources"sv)) { if(*srcsopt <= 0) numMono = 256; - else numMono = maxu(*srcsopt, 16); + else numMono = std::max(*srcsopt, 16u); } else { - numMono = minu(numMono, INT_MAX-numStereo); - numMono = maxu(numMono+numStereo, 256); + numMono = std::min(numMono, std::numeric_limits::max()-numStereo); + numMono = std::max(numMono+numStereo, 256u); } - numStereo = minu(numStereo, numMono); + numStereo = std::min(numStereo, numMono); numMono -= numStereo; device->SourcesMax = numMono + numStereo; device->NumMonoSources = numMono; device->NumStereoSources = numStereo; - if(auto sendsopt = device->configValue(nullptr, "sends")) - numSends = minu(numSends, static_cast(clampi(*sendsopt, 0, MAX_SENDS))); + if(auto sendsopt = device->configValue({}, "sends"sv)) + numSends = std::min(numSends, std::clamp(*sendsopt, 0u, uint{MaxSendCount})); device->NumAuxSends = numSends; - TRACE("Max sources: %d (%d + %d), effect slots: %d, sends: %d\n", + TRACE("Max sources: {} ({} + {}), effect slots: {}, sends: {}", device->SourcesMax, device->NumMonoSources, device->NumStereoSources, device->AuxiliaryEffectSlotMax, device->NumAuxSends); @@ -1517,17 +1623,18 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) case DevFmtX61: device->RealOut.RemixMap = X61Downmix; break; case DevFmtX71: device->RealOut.RemixMap = X71Downmix; break; case DevFmtX714: device->RealOut.RemixMap = X71Downmix; break; + case DevFmtX7144: device->RealOut.RemixMap = X71Downmix; break; case DevFmtX3D71: device->RealOut.RemixMap = X51Downmix; break; case DevFmtAmbi3D: break; } - nanoseconds::rep sample_delay{0}; + size_t sample_delay{0}; if(auto *encoder{device->mUhjEncoder.get()}) sample_delay += encoder->getDelay(); - if(device->getConfigValueBool(nullptr, "dither", true)) + if(device->getConfigValueBool({}, "dither"sv, true)) { - int depth{device->configValue(nullptr, "dither-depth").value_or(0)}; + int depth{device->configValue({}, "dither-depth"sv).value_or(0)}; if(depth <= 0) { switch(device->FmtType) @@ -1549,18 +1656,18 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) if(depth > 0) { - depth = clampi(depth, 2, 24); + depth = std::clamp(depth, 2, 24); device->DitherDepth = std::pow(2.0f, static_cast(depth-1)); } } if(!(device->DitherDepth > 0.0f)) - TRACE("Dithering disabled\n"); + TRACE("Dithering disabled"); else - TRACE("Dithering enabled (%d-bit, %g)\n", float2int(std::log2(device->DitherDepth)+0.5f)+1, - device->DitherDepth); + TRACE("Dithering enabled ({}-bit, {:g})", + float2int(std::log2(device->DitherDepth)+0.5f)+1, device->DitherDepth); if(!optlimit) - optlimit = device->configValue(nullptr, "output-limiter"); + optlimit = device->configValue({}, "output-limiter"); /* If the gain limiter is unset, use the limiter for integer-based output * (where samples must be clamped), and don't for floating-point (which can @@ -1582,8 +1689,8 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) break; } } - if(optlimit.value_or(false) == false) - TRACE("Output limiter disabled\n"); + if(!optlimit.value_or(false)) + TRACE("Output limiter disabled"); else { float thrshld{1.0f}; @@ -1610,88 +1717,104 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) sample_delay += limiter->getLookAhead(); device->Limiter = std::move(limiter); - TRACE("Output limiter enabled, %.4fdB limit\n", thrshld_dB); + TRACE("Output limiter enabled, {:.4f}dB limit", thrshld_dB); } /* Convert the sample delay from samples to nanosamples to nanoseconds. */ - device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->Frequency; - TRACE("Fixed device latency: %" PRId64 "ns\n", int64_t{device->FixedLatency.count()}); + sample_delay = std::min(sample_delay, std::numeric_limits::max()); + device->FixedLatency += nanoseconds{seconds{sample_delay}} / device->mSampleRate; + TRACE("Fixed device latency: {}ns", device->FixedLatency.count()); FPUCtl mixer_mode{}; - for(ContextBase *ctxbase : *device->mContexts.load()) + auto reset_context = [device](ContextBase *ctxbase) { - auto *context = static_cast(ctxbase); + auto *context = dynamic_cast(ctxbase); + assert(context != nullptr); + if(!context) return; std::unique_lock proplock{context->mPropLock}; std::unique_lock slotlock{context->mEffectSlotLock}; /* Clear out unused effect slot clusters. */ - auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &cluster) + auto slot_cluster_not_in_use = [](ContextBase::EffectSlotCluster &clusterptr) -> bool { - for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i) - { - if(cluster[i].InUse) - return false; - } - return true; + return std::none_of(clusterptr->begin(), clusterptr->end(), + std::mem_fn(&EffectSlot::InUse)); }; - auto slotcluster_iter = std::remove_if(context->mEffectSlotClusters.begin(), + auto slotcluster_end = std::remove_if(context->mEffectSlotClusters.begin(), context->mEffectSlotClusters.end(), slot_cluster_not_in_use); - context->mEffectSlotClusters.erase(slotcluster_iter, context->mEffectSlotClusters.end()); + context->mEffectSlotClusters.erase(slotcluster_end, context->mEffectSlotClusters.end()); /* Free all wet buffers. Any in use will be reallocated with an updated * configuration in aluInitEffectPanning. */ - for(auto&& slots : context->mEffectSlotClusters) + auto clear_wetbuffers = [](ContextBase::EffectSlotCluster &clusterptr) { - for(size_t i{0};i < ContextBase::EffectSlotClusterSize;++i) + auto clear_buffer = [](EffectSlot &slot) { - slots[i].mWetBuffer.clear(); - slots[i].mWetBuffer.shrink_to_fit(); - slots[i].Wet.Buffer = {}; - } - } + slot.mWetBuffer.clear(); + slot.mWetBuffer.shrink_to_fit(); + slot.Wet.Buffer = {}; + }; + std::for_each(clusterptr->begin(), clusterptr->end(), clear_buffer); + }; + std::for_each(context->mEffectSlotClusters.begin(), context->mEffectSlotClusters.end(), + clear_wetbuffers); if(ALeffectslot *slot{context->mDefaultSlot.get()}) { - aluInitEffectPanning(slot->mSlot, context); + auto *slotbase = slot->mSlot; + aluInitEffectPanning(slotbase, context); + + if(auto *props = slotbase->Update.exchange(nullptr, std::memory_order_relaxed)) + AtomicReplaceHead(context->mFreeEffectSlotProps, props); EffectState *state{slot->Effect.State.get()}; state->mOutTarget = device->Dry.Buffer; state->deviceUpdate(device, slot->Buffer); - slot->updateProps(context); + slot->mPropsDirty = true; } if(EffectSlotArray *curarray{context->mActiveAuxSlots.load(std::memory_order_relaxed)}) - std::fill_n(curarray->end(), curarray->size(), nullptr); - for(auto &sublist : context->mEffectSlotList) + std::fill(curarray->begin()+ptrdiff_t(curarray->size()>>1), curarray->end(), nullptr); + auto reset_slots = [device,context](EffectSlotSubList &sublist) { uint64_t usemask{~sublist.FreeMask}; while(usemask) { - const int idx{al::countr_zero(usemask)}; - ALeffectslot *slot{sublist.EffectSlots + idx}; + const auto idx = static_cast(al::countr_zero(usemask)); + auto &slot = (*sublist.EffectSlots)[idx]; usemask &= ~(1_u64 << idx); - aluInitEffectPanning(slot->mSlot, context); + auto *slotbase = slot.mSlot; + aluInitEffectPanning(slotbase, context); + + if(auto *props = slotbase->Update.exchange(nullptr, std::memory_order_relaxed)) + AtomicReplaceHead(context->mFreeEffectSlotProps, props); - EffectState *state{slot->Effect.State.get()}; + EffectState *state{slot.Effect.State.get()}; state->mOutTarget = device->Dry.Buffer; - state->deviceUpdate(device, slot->Buffer); - slot->updateProps(context); + state->deviceUpdate(device, slot.Buffer); + slot.mPropsDirty = true; } - } + }; + std::for_each(context->mEffectSlotList.begin(), context->mEffectSlotList.end(), + reset_slots); + + /* Clear all effect slot props to let them get allocated again. */ + context->mEffectSlotPropClusters.clear(); + context->mFreeEffectSlotProps.store(nullptr, std::memory_order_relaxed); slotlock.unlock(); - const uint num_sends{device->NumAuxSends}; std::unique_lock srclock{context->mSourceLock}; - for(auto &sublist : context->mSourceList) + const uint num_sends{device->NumAuxSends}; + auto reset_sources = [num_sends](SourceSubList &sublist) { uint64_t usemask{~sublist.FreeMask}; while(usemask) { - const int idx{al::countr_zero(usemask)}; - ALsource *source{sublist.Sources + idx}; + const auto idx = static_cast(al::countr_zero(usemask)); + auto &source = (*sublist.Sources)[idx]; usemask &= ~(1_u64 << idx); auto clear_send = [](ALsource::SendData &send) -> void @@ -1701,30 +1824,31 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) send.Slot = nullptr; send.Gain = 1.0f; send.GainHF = 1.0f; - send.HFReference = LOWPASSFREQREF; + send.HFReference = LowPassFreqRef; send.GainLF = 1.0f; - send.LFReference = HIGHPASSFREQREF; + send.LFReference = HighPassFreqRef; }; - auto send_begin = source->Send.begin() + static_cast(num_sends); - std::for_each(send_begin, source->Send.end(), clear_send); + const auto sends = al::span{source.Send}.subspan(num_sends); + std::for_each(sends.begin(), sends.end(), clear_send); - source->mPropsDirty = true; + source.mPropsDirty = true; } - } + }; + std::for_each(context->mSourceList.begin(), context->mSourceList.end(), reset_sources); - auto voicelist = context->getVoicesSpan(); - for(Voice *voice : voicelist) + auto reset_voice = [device,num_sends,context](Voice *voice) { /* Clear extraneous property set sends. */ - std::fill(std::begin(voice->mProps.Send)+num_sends, std::end(voice->mProps.Send), - VoiceProps::SendData{}); + const auto sendparams = al::span{voice->mProps.Send}.subspan(num_sends); + std::fill(sendparams.begin(), sendparams.end(), VoiceProps::SendData{}); std::fill(voice->mSend.begin()+num_sends, voice->mSend.end(), Voice::TargetData{}); - for(auto &chandata : voice->mChans) + auto clear_wetparams = [num_sends](Voice::ChannelData &chandata) { - std::fill(chandata.mWetParams.begin()+num_sends, chandata.mWetParams.end(), - SendParams{}); - } + const auto wetparams = al::span{chandata.mWetParams}.subspan(num_sends); + std::fill(wetparams.begin(), wetparams.end(), SendParams{}); + }; + std::for_each(voice->mChans.begin(), voice->mChans.end(), clear_wetparams); if(VoicePropsItem *props{voice->mUpdate.exchange(nullptr, std::memory_order_relaxed)}) AtomicReplaceHead(context->mFreeVoiceProps, props); @@ -1734,10 +1858,13 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) voice->mPlayState.compare_exchange_strong(vstate, Voice::Stopped, std::memory_order_acquire, std::memory_order_acquire); if(voice->mSourceID.load(std::memory_order_relaxed) == 0u) - continue; + return; voice->prepare(device); - } + }; + const auto voicespan = context->getVoicesSpan(); + std::for_each(voicespan.begin(), voicespan.end(), reset_voice); + /* Clear all voice props to let them get allocated again. */ context->mVoicePropClusters.clear(); context->mFreeVoiceProps.store(nullptr, std::memory_order_relaxed); @@ -1745,25 +1872,29 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) context->mPropsDirty = false; UpdateContextProps(context); + UpdateAllEffectSlotProps(context); UpdateAllSourceProps(context); - } + }; + auto ctxspan = al::span{*device->mContexts.load()}; + std::for_each(ctxspan.begin(), ctxspan.end(), reset_context); mixer_mode.leave(); + device->mDeviceState = DeviceState::Configured; if(!device->Flags.test(DevicePaused)) { try { auto backend = device->Backend.get(); backend->start(); - device->Flags.set(DeviceRunning); + device->mDeviceState = DeviceState::Playing; } catch(al::backend_exception& e) { - ERR("%s\n", e.what()); - device->handleDisconnect("%s", e.what()); + ERR("{}", e.what()); + device->handleDisconnect("{}", e.what()); return ALC_INVALID_DEVICE; } - TRACE("Post-start: %s, %s, %uhz, %u / %u buffer\n", + TRACE("Post-start: {}, {}, {}hz, {} / {} buffer", DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, device->UpdateSize, device->BufferSize); + device->mSampleRate, device->mUpdateSize, device->mBufferSize); } return ALC_NO_ERROR; @@ -1773,24 +1904,25 @@ ALCenum UpdateDeviceParams(ALCdevice *device, const int *attrList) * Updates device parameters as above, and also first clears the disconnected * status, if set. */ -bool ResetDeviceParams(ALCdevice *device, const int *attrList) +auto ResetDeviceParams(al::Device *device, const al::span attrList) -> bool { /* If the device was disconnected, reset it since we're opened anew. */ if(!device->Connected.load(std::memory_order_relaxed)) UNLIKELY { /* Make sure disconnection is finished before continuing on. */ - device->waitForMix(); + std::ignore = device->waitForMix(); for(ContextBase *ctxbase : *device->mContexts.load(std::memory_order_acquire)) { - auto *ctx = static_cast(ctxbase); - if(!ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire)) + auto *ctx = dynamic_cast(ctxbase); + assert(ctx != nullptr); + if(!ctx || !ctx->mStopVoicesOnDisconnect.load(std::memory_order_acquire)) continue; /* Clear any pending voice changes and reallocate voices to get a * clean restart. */ - std::lock_guard __{ctx->mSourceLock}; + std::lock_guard sourcelock{ctx->mSourceLock}; auto *vchg = ctx->mCurrentVoiceChange.load(std::memory_order_acquire); while(auto *next = vchg->mNext.load(std::memory_order_acquire)) vchg = next; @@ -1818,7 +1950,7 @@ bool ResetDeviceParams(ALCdevice *device, const int *attrList) /** Checks if the device handle is valid, and returns a new reference if so. */ DeviceRef VerifyDevice(ALCdevice *device) { - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device); if(iter != DeviceList.end() && *iter == device) { @@ -1834,7 +1966,7 @@ DeviceRef VerifyDevice(ALCdevice *device) */ ContextRef VerifyContext(ALCcontext *context) { - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context); if(iter != ContextList.end() && *iter == context) { @@ -1852,7 +1984,7 @@ FORCE_ALIGN void ALC_APIENTRY alsoft_set_log_callback(LPALSOFTLOGCALLBACK callba } /** Returns a new reference to the currently active context for this thread. */ -ContextRef GetContextRef(void) +ContextRef GetContextRef() noexcept { ALCcontext *context{ALCcontext::getThreadContext()}; if(context) @@ -1871,9 +2003,9 @@ ContextRef GetContextRef(void) return ContextRef{context}; } -void alcSetError(ALCdevice *device, ALCenum errorCode) +void alcSetError(al::Device *device, ALCenum errorCode) { - WARN("Error generated on device %p, code 0x%04x\n", voidp{device}, errorCode); + WARN("Error generated on device {}, code {:#04x}", voidp{device}, as_unsigned(errorCode)); if(TrapALCError) { #ifdef _WIN32 @@ -1897,6 +2029,9 @@ void alcSetError(ALCdevice *device, ALCenum errorCode) ALC_API ALCenum ALC_APIENTRY alcGetError(ALCdevice *device) noexcept { + if(!gProcessRunning) + return ALC_INVALID_DEVICE; + DeviceRef dev{VerifyDevice(device)}; if(dev) return dev->LastError.exchange(ALC_NO_ERROR); return LastNullDeviceError.exchange(ALC_NO_ERROR); @@ -1912,7 +2047,7 @@ ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) noexcept return; } - if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + if(ctx->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, "alcSuspendContext behavior is not portable -- some implementations suspend all " "rendering, some only defer property changes, and some are completely no-op; consider " @@ -1921,7 +2056,7 @@ ALC_API void ALC_APIENTRY alcSuspendContext(ALCcontext *context) noexcept if(SuspendDefers) { - std::lock_guard _{ctx->mPropLock}; + std::lock_guard proplock{ctx->mPropLock}; ctx->deferUpdates(); } } @@ -1935,8 +2070,8 @@ ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) noexcept return; } - if(context->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY - ctx->debugMessage(DebugSource::API, DebugType::Portability, 0, DebugSeverity::Medium, + if(ctx->mContextFlags.test(ContextFlags::DebugBit)) UNLIKELY + ctx->debugMessage(DebugSource::API, DebugType::Portability, 1, DebugSeverity::Medium, "alcProcessContext behavior is not portable -- some implementations resume rendering, " "some apply deferred property changes, and some are completely no-op; consider using " "alcDeviceResumeSOFT to resume rendering, or alProcessUpdatesSOFT to apply deferred " @@ -1944,137 +2079,108 @@ ALC_API void ALC_APIENTRY alcProcessContext(ALCcontext *context) noexcept if(SuspendDefers) { - std::lock_guard _{ctx->mPropLock}; + std::lock_guard proplock{ctx->mPropLock}; ctx->processUpdates(); } } -ALC_API const ALCchar* ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param) noexcept +ALC_API auto ALC_APIENTRY alcGetString(ALCdevice *Device, ALCenum param) noexcept -> const ALCchar* { - const ALCchar *value{nullptr}; - switch(param) { - case ALC_NO_ERROR: - value = alcNoError; - break; - - case ALC_INVALID_ENUM: - value = alcErrInvalidEnum; - break; - - case ALC_INVALID_VALUE: - value = alcErrInvalidValue; - break; - - case ALC_INVALID_DEVICE: - value = alcErrInvalidDevice; - break; - - case ALC_INVALID_CONTEXT: - value = alcErrInvalidContext; - break; - - case ALC_OUT_OF_MEMORY: - value = alcErrOutOfMemory; - break; + case ALC_NO_ERROR: return GetNoErrorString(); + case ALC_INVALID_ENUM: return GetInvalidEnumString(); + case ALC_INVALID_VALUE: return GetInvalidValueString(); + case ALC_INVALID_DEVICE: return GetInvalidDeviceString(); + case ALC_INVALID_CONTEXT: return GetInvalidContextString(); + case ALC_OUT_OF_MEMORY: return GetOutOfMemoryString(); case ALC_DEVICE_SPECIFIER: - value = alcDefaultName; - break; + return GetDefaultName(); case ALC_ALL_DEVICES_SPECIFIER: if(DeviceRef dev{VerifyDevice(Device)}) { if(dev->Type == DeviceType::Capture) - alcSetError(dev.get(), ALC_INVALID_ENUM); - else if(dev->Type == DeviceType::Loopback) - value = alcDefaultName; - else { - std::lock_guard _{dev->StateLock}; - value = dev->DeviceName.c_str(); + alcSetError(dev.get(), ALC_INVALID_ENUM); + return nullptr; } + if(dev->Type == DeviceType::Loopback) + return GetDefaultName(); + + auto statelock = std::lock_guard{dev->StateLock}; + return dev->mDeviceName.c_str(); } - else - { - ProbeAllDevicesList(); - value = alcAllDevicesList.c_str(); - } - break; + ProbeAllDevicesList(); + return alcAllDevicesList.c_str(); case ALC_CAPTURE_DEVICE_SPECIFIER: if(DeviceRef dev{VerifyDevice(Device)}) { if(dev->Type != DeviceType::Capture) - alcSetError(dev.get(), ALC_INVALID_ENUM); - else { - std::lock_guard _{dev->StateLock}; - value = dev->DeviceName.c_str(); + alcSetError(dev.get(), ALC_INVALID_ENUM); + return nullptr; } + + auto statelock = std::lock_guard{dev->StateLock}; + return dev->mDeviceName.c_str(); } - else - { - ProbeCaptureDeviceList(); - value = alcCaptureDeviceList.c_str(); - } - break; + ProbeCaptureDeviceList(); + return alcCaptureDeviceList.c_str(); /* Default devices are always first in the list */ case ALC_DEFAULT_DEVICE_SPECIFIER: - value = alcDefaultName; - break; + return GetDefaultName(); case ALC_DEFAULT_ALL_DEVICES_SPECIFIER: if(alcAllDevicesList.empty()) ProbeAllDevicesList(); /* Copy first entry as default. */ - alcDefaultAllDevicesSpecifier = alcAllDevicesList.c_str(); - value = alcDefaultAllDevicesSpecifier.c_str(); - break; + if(!alcAllDevicesArray.empty()) + alcDefaultAllDevicesSpecifier = alcAllDevicesArray.front(); + else + alcDefaultAllDevicesSpecifier.clear(); + return alcDefaultAllDevicesSpecifier.c_str(); case ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER: if(alcCaptureDeviceList.empty()) ProbeCaptureDeviceList(); /* Copy first entry as default. */ - alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceList.c_str(); - value = alcCaptureDefaultDeviceSpecifier.c_str(); - break; + if(!alcCaptureDeviceArray.empty()) + alcCaptureDefaultDeviceSpecifier = alcCaptureDeviceArray.front(); + else + alcCaptureDefaultDeviceSpecifier.clear(); + return alcCaptureDefaultDeviceSpecifier.c_str(); case ALC_EXTENSIONS: if(VerifyDevice(Device)) - value = alcExtensionList; - else - value = alcNoDeviceExtList; - break; + return GetExtensionList(); + return GetNoDeviceExtList(); case ALC_HRTF_SPECIFIER_SOFT: if(DeviceRef dev{VerifyDevice(Device)}) { - std::lock_guard _{dev->StateLock}; - value = (dev->mHrtf ? dev->mHrtfName.c_str() : ""); + std::lock_guard statelock{dev->StateLock}; + return dev->mHrtf ? dev->mHrtfName.c_str() : ""; } - else - alcSetError(nullptr, ALC_INVALID_DEVICE); - break; + alcSetError(nullptr, ALC_INVALID_DEVICE); + return nullptr; default: alcSetError(VerifyDevice(Device).get(), ALC_INVALID_ENUM); - break; } - return value; + return nullptr; } - -static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values) +namespace { +auto GetIntegerv(al::Device *device, ALCenum param, const al::span values) -> size_t { - size_t i; - if(values.empty()) { alcSetError(device, ALC_INVALID_VALUE); @@ -2099,7 +2205,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values[0] = alcEFXMinorVersion; return 1; case ALC_MAX_AUXILIARY_SENDS: - values[0] = MAX_SENDS; + values[0] = MaxSendCount; return 1; case ALC_ATTRIBUTES_SIZE: @@ -2125,7 +2231,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span return 0; } - std::lock_guard _{device->StateLock}; + std::lock_guard statelock{device->StateLock}; if(device->Type == DeviceType::Capture) { static constexpr int MaxCaptureAttributes{9}; @@ -2135,11 +2241,9 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values[0] = MaxCaptureAttributes; return 1; case ALC_ALL_ATTRIBUTES: - i = 0; - if(values.size() < MaxCaptureAttributes) - alcSetError(device, ALC_INVALID_VALUE); - else + if(values.size() >= MaxCaptureAttributes) { + size_t i{0}; values[i++] = ALC_MAJOR_VERSION; values[i++] = alcMajorVersion; values[i++] = ALC_MINOR_VERSION; @@ -2150,8 +2254,10 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values[i++] = device->Connected.load(std::memory_order_relaxed); values[i++] = 0; assert(i == MaxCaptureAttributes); + return i; } - return i; + alcSetError(device, ALC_INVALID_VALUE); + return 0; case ALC_MAJOR_VERSION: values[0] = alcMajorVersion; @@ -2175,24 +2281,22 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span } /* render device */ - auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept + auto NumAttrsForDevice = [device]() noexcept -> uint8_t { - if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D) + if(device->Type == DeviceType::Loopback && device->FmtChans == DevFmtAmbi3D) return 37; return 31; }; switch(param) { case ALC_ATTRIBUTES_SIZE: - values[0] = NumAttrsForDevice(device); + values[0] = NumAttrsForDevice(); return 1; case ALC_ALL_ATTRIBUTES: - i = 0; - if(values.size() < static_cast(NumAttrsForDevice(device))) - alcSetError(device, ALC_INVALID_VALUE); - else + if(values.size() >= NumAttrsForDevice()) { + size_t i{0}; values[i++] = ALC_MAJOR_VERSION; values[i++] = alcMajorVersion; values[i++] = ALC_MINOR_VERSION; @@ -2203,11 +2307,11 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values[i++] = alcEFXMinorVersion; values[i++] = ALC_FREQUENCY; - values[i++] = static_cast(device->Frequency); + values[i++] = static_cast(device->mSampleRate); if(device->Type != DeviceType::Loopback) { values[i++] = ALC_REFRESH; - values[i++] = static_cast(device->Frequency / device->UpdateSize); + values[i++] = static_cast(device->mSampleRate / device->mUpdateSize); values[i++] = ALC_SYNC; values[i++] = ALC_FALSE; @@ -2258,8 +2362,11 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span values[i++] = static_cast(device->getOutputMode1()); values[i++] = 0; + assert(i == NumAttrsForDevice()); + return i; } - return i; + alcSetError(device, ALC_INVALID_VALUE); + return 0; case ALC_MAJOR_VERSION: values[0] = alcMajorVersion; @@ -2278,7 +2385,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span return 1; case ALC_FREQUENCY: - values[0] = static_cast(device->Frequency); + values[0] = static_cast(device->mSampleRate); return 1; case ALC_REFRESH: @@ -2287,7 +2394,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span alcSetError(device, ALC_INVALID_DEVICE); return 0; } - values[0] = static_cast(device->Frequency / device->UpdateSize); + values[0] = static_cast(device->mSampleRate / device->mUpdateSize); return 1; case ALC_SYNC: @@ -2370,8 +2477,8 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span case ALC_NUM_HRTF_SPECIFIERS_SOFT: device->enumerateHrtfs(); - values[0] = static_cast(minz(device->mHrtfList.size(), - std::numeric_limits::max())); + values[0] = static_cast(std::min(device->mHrtfList.size(), + size_t{std::numeric_limits::max()})); return 1; case ALC_OUTPUT_LIMITER_SOFT: @@ -2391,6 +2498,7 @@ static size_t GetIntegerv(ALCdevice *device, ALCenum param, const al::span } return 0; } +} // namespace ALC_API void ALC_APIENTRY alcGetIntegerv(ALCdevice *device, ALCenum param, ALCsizei size, ALCint *values) noexcept { @@ -2409,113 +2517,118 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, alcSetError(dev.get(), ALC_INVALID_VALUE); return; } + const auto valuespan = al::span{values, static_cast(size)}; if(!dev || dev->Type == DeviceType::Capture) { - auto ivals = std::vector(static_cast(size)); + auto ivals = std::vector(valuespan.size()); if(size_t got{GetIntegerv(dev.get(), pname, ivals)}) - std::copy_n(ivals.begin(), got, values); + std::copy_n(ivals.cbegin(), got, valuespan.begin()); return; } /* render device */ - auto NumAttrsForDevice = [](ALCdevice *aldev) noexcept + auto NumAttrsForDevice = [](al::Device *aldev) noexcept -> size_t { if(aldev->Type == DeviceType::Loopback && aldev->FmtChans == DevFmtAmbi3D) return 41; return 35; }; - std::lock_guard _{dev->StateLock}; + std::lock_guard statelock{dev->StateLock}; switch(pname) { case ALC_ATTRIBUTES_SIZE: - *values = NumAttrsForDevice(dev.get()); + valuespan[0] = static_cast(NumAttrsForDevice(dev.get())); break; case ALC_ALL_ATTRIBUTES: - if(size < NumAttrsForDevice(dev.get())) + if(valuespan.size() < NumAttrsForDevice(dev.get())) alcSetError(dev.get(), ALC_INVALID_VALUE); else { size_t i{0}; - values[i++] = ALC_FREQUENCY; - values[i++] = dev->Frequency; + valuespan[i++] = ALC_FREQUENCY; + valuespan[i++] = dev->mSampleRate; if(dev->Type != DeviceType::Loopback) { - values[i++] = ALC_REFRESH; - values[i++] = dev->Frequency / dev->UpdateSize; + valuespan[i++] = ALC_REFRESH; + valuespan[i++] = dev->mSampleRate / dev->mUpdateSize; - values[i++] = ALC_SYNC; - values[i++] = ALC_FALSE; + valuespan[i++] = ALC_SYNC; + valuespan[i++] = ALC_FALSE; } else { - values[i++] = ALC_FORMAT_CHANNELS_SOFT; - values[i++] = EnumFromDevFmt(dev->FmtChans); + valuespan[i++] = ALC_FORMAT_CHANNELS_SOFT; + valuespan[i++] = EnumFromDevFmt(dev->FmtChans); - values[i++] = ALC_FORMAT_TYPE_SOFT; - values[i++] = EnumFromDevFmt(dev->FmtType); + valuespan[i++] = ALC_FORMAT_TYPE_SOFT; + valuespan[i++] = EnumFromDevFmt(dev->FmtType); if(dev->FmtChans == DevFmtAmbi3D) { - values[i++] = ALC_AMBISONIC_LAYOUT_SOFT; - values[i++] = EnumFromDevAmbi(dev->mAmbiLayout); + valuespan[i++] = ALC_AMBISONIC_LAYOUT_SOFT; + valuespan[i++] = EnumFromDevAmbi(dev->mAmbiLayout); - values[i++] = ALC_AMBISONIC_SCALING_SOFT; - values[i++] = EnumFromDevAmbi(dev->mAmbiScale); + valuespan[i++] = ALC_AMBISONIC_SCALING_SOFT; + valuespan[i++] = EnumFromDevAmbi(dev->mAmbiScale); - values[i++] = ALC_AMBISONIC_ORDER_SOFT; - values[i++] = dev->mAmbiOrder; + valuespan[i++] = ALC_AMBISONIC_ORDER_SOFT; + valuespan[i++] = dev->mAmbiOrder; } } - values[i++] = ALC_MONO_SOURCES; - values[i++] = dev->NumMonoSources; + valuespan[i++] = ALC_MONO_SOURCES; + valuespan[i++] = dev->NumMonoSources; - values[i++] = ALC_STEREO_SOURCES; - values[i++] = dev->NumStereoSources; + valuespan[i++] = ALC_STEREO_SOURCES; + valuespan[i++] = dev->NumStereoSources; - values[i++] = ALC_MAX_AUXILIARY_SENDS; - values[i++] = dev->NumAuxSends; + valuespan[i++] = ALC_MAX_AUXILIARY_SENDS; + valuespan[i++] = dev->NumAuxSends; - values[i++] = ALC_HRTF_SOFT; - values[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE); + valuespan[i++] = ALC_HRTF_SOFT; + valuespan[i++] = (dev->mHrtf ? ALC_TRUE : ALC_FALSE); - values[i++] = ALC_HRTF_STATUS_SOFT; - values[i++] = dev->mHrtfStatus; + valuespan[i++] = ALC_HRTF_STATUS_SOFT; + valuespan[i++] = dev->mHrtfStatus; - values[i++] = ALC_OUTPUT_LIMITER_SOFT; - values[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE; + valuespan[i++] = ALC_OUTPUT_LIMITER_SOFT; + valuespan[i++] = dev->Limiter ? ALC_TRUE : ALC_FALSE; ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())}; - values[i++] = ALC_DEVICE_CLOCK_SOFT; - values[i++] = clock.ClockTime.count(); + valuespan[i++] = ALC_DEVICE_CLOCK_SOFT; + valuespan[i++] = clock.ClockTime.count(); - values[i++] = ALC_DEVICE_LATENCY_SOFT; - values[i++] = clock.Latency.count(); + valuespan[i++] = ALC_DEVICE_LATENCY_SOFT; + valuespan[i++] = clock.Latency.count(); - values[i++] = ALC_OUTPUT_MODE_SOFT; - values[i++] = static_cast(device->getOutputMode1()); + valuespan[i++] = ALC_OUTPUT_MODE_SOFT; + valuespan[i++] = al::to_underlying(dev->getOutputMode1()); - values[i++] = 0; + valuespan[i++] = 0; } break; case ALC_DEVICE_CLOCK_SOFT: { uint samplecount, refcount; - nanoseconds basecount; + seconds clocksec; + nanoseconds clocknsec; do { refcount = dev->waitForMix(); - basecount = dev->ClockBase; - samplecount = dev->SamplesDone; - } while(refcount != ReadRef(dev->MixCount)); - basecount += nanoseconds{seconds{samplecount}} / dev->Frequency; - *values = basecount.count(); + samplecount = dev->mSamplesDone.load(std::memory_order_relaxed); + clocksec = dev->mClockBaseSec.load(std::memory_order_relaxed); + clocknsec = dev->mClockBaseNSec.load(std::memory_order_relaxed); + std::atomic_thread_fence(std::memory_order_acquire); + } while(refcount != dev->mMixCount.load(std::memory_order_relaxed)); + + valuespan[0] = nanoseconds{clocksec + nanoseconds{clocknsec} + + nanoseconds{seconds{samplecount}}/dev->mSampleRate}.count(); } break; case ALC_DEVICE_LATENCY_SOFT: - *values = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count(); + valuespan[0] = GetClockLatency(dev.get(), dev->Backend.get()).Latency.count(); break; case ALC_DEVICE_CLOCK_LATENCY_SOFT: @@ -2524,15 +2637,15 @@ ALC_API void ALC_APIENTRY alcGetInteger64vSOFT(ALCdevice *device, ALCenum pname, else { ClockLatency clock{GetClockLatency(dev.get(), dev->Backend.get())}; - values[0] = clock.ClockTime.count(); - values[1] = clock.Latency.count(); + valuespan[0] = clock.ClockTime.count(); + valuespan[1] = clock.Latency.count(); } break; default: - auto ivals = std::vector(static_cast(size)); + auto ivals = std::vector(valuespan.size()); if(size_t got{GetIntegerv(dev.get(), pname, ivals)}) - std::copy_n(ivals.begin(), got, values); + std::copy_n(ivals.cbegin(), got, valuespan.begin()); break; } } @@ -2542,23 +2655,22 @@ ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent(ALCdevice *device, const A { DeviceRef dev{VerifyDevice(device)}; if(!extName) - alcSetError(dev.get(), ALC_INVALID_VALUE); - else { - size_t len = strlen(extName); - const char *ptr = (dev ? alcExtensionList : alcNoDeviceExtList); - while(ptr && *ptr) - { - if(al::strncasecmp(ptr, extName, len) == 0 && (ptr[len] == '\0' || isspace(ptr[len]))) - return ALC_TRUE; + alcSetError(dev.get(), ALC_INVALID_VALUE); + return ALC_FALSE; + } - if((ptr=strchr(ptr, ' ')) != nullptr) - { - do { - ++ptr; - } while(isspace(*ptr)); - } - } + const std::string_view tofind{extName}; + const auto extlist = dev ? std::string_view{GetExtensionList()} + : std::string_view{GetNoDeviceExtList()}; + auto matchpos = extlist.find(tofind); + while(matchpos != std::string_view::npos) + { + const auto endpos = matchpos + tofind.size(); + if((matchpos == 0 || std::isspace(extlist[matchpos-1])) + && (endpos == extlist.size() || std::isspace(extlist[endpos]))) + return ALC_TRUE; + matchpos = extlist.find(tofind, matchpos+1); } return ALC_FALSE; } @@ -2576,7 +2688,7 @@ ALC_API ALCvoid* ALC_APIENTRY alcGetProcAddress(ALCdevice *device, const ALCchar return nullptr; } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(eax_g_is_enabled) { for(const auto &func : eaxFunctions) @@ -2604,7 +2716,7 @@ ALC_API ALCenum ALC_APIENTRY alcGetEnumValue(ALCdevice *device, const ALCchar *e return 0; } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(eax_g_is_enabled) { for(const auto &enm : eaxEnumerations) @@ -2643,7 +2755,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin dev->LastError.store(ALC_NO_ERROR); - ALCenum err{UpdateDeviceParams(dev.get(), attrList)}; + const auto attrSpan = SpanFromAttributeList(attrList); + ALCenum err{UpdateDeviceParams(dev.get(), attrSpan)}; if(err != ALC_NO_ERROR) { alcSetError(dev.get(), err); @@ -2651,28 +2764,16 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin } ContextFlagBitset ctxflags{0}; - if(attrList) + for(size_t i{0};i < attrSpan.size();i+=2) { - for(size_t i{0};attrList[i];i+=2) + if(attrSpan[i] == ALC_CONTEXT_FLAGS_EXT) { - if(attrList[i] == ALC_CONTEXT_FLAGS_EXT) - { - ctxflags = static_cast(attrList[i+1]); - break; - } + ctxflags = static_cast(attrSpan[i+1]); + break; } } - ContextRef context{[](auto&& ...args) -> ContextRef - { - try { - return ContextRef{new ALCcontext{std::forward(args)...}}; - } - catch(std::exception& e) { - ERR("Failed to create ALCcontext: %s\n", e.what()); - return ContextRef{}; - } - }(dev, ctxflags)}; + auto context = ContextRef{new(std::nothrow) ALCcontext{dev, ctxflags}}; if(!context) { alcSetError(dev.get(), ALC_OUT_OF_MEMORY); @@ -2680,18 +2781,18 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin } context->init(); - if(auto volopt = dev->configValue(nullptr, "volume-adjust")) + if(auto volopt = dev->configValue({}, "volume-adjust")) { const float valf{*volopt}; if(!std::isfinite(valf)) - ERR("volume-adjust must be finite: %f\n", valf); + ERR("volume-adjust must be finite: {:f}", valf); else { - const float db{clampf(valf, -24.0f, 24.0f)}; + const float db{std::clamp(valf, -24.0f, 24.0f)}; if(db != valf) - WARN("volume-adjust clamped: %f, range: +/-%f\n", valf, 24.0f); + WARN("volume-adjust clamped: {:f}, range: +/-24", valf); context->mGainBoost = std::pow(10.0f, db/20.0f); - TRACE("volume-adjust gain: %f\n", context->mGainBoost); + TRACE("volume-adjust gain: {:f}", context->mGainBoost); } } @@ -2701,9 +2802,8 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin /* Allocate a new context array, which holds 1 more than the current/ * old array. */ - auto *oldarray = device->mContexts.load(); - const size_t newcount{oldarray->size()+1}; - std::unique_ptr newarray{ContextArray::Create(newcount)}; + auto *oldarray = dev->mContexts.load(); + auto newarray = ContextArray::Create(oldarray->size() + 1); /* Copy the current/old context handles to the new array, appending the * new context. @@ -2714,19 +2814,16 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin /* Store the new context array in the device. Wait for any current mix * to finish before deleting the old array. */ - dev->mContexts.store(newarray.release()); - if(oldarray != &DeviceBase::sEmptyContextArray) - { - dev->waitForMix(); - delete oldarray; - } + auto prevarray = dev->mContexts.exchange(std::move(newarray)); + std::ignore = dev->waitForMix(); } statelock.unlock(); { - std::lock_guard _{ListLock}; + listlock.lock(); auto iter = std::lower_bound(ContextList.cbegin(), ContextList.cend(), context.get()); ContextList.emplace(iter, context.get()); + listlock.unlock(); } if(ALeffectslot *slot{context->mDefaultSlot.get()}) @@ -2736,15 +2833,18 @@ ALC_API ALCcontext* ALC_APIENTRY alcCreateContext(ALCdevice *device, const ALCin if(sloterr == AL_NO_ERROR) slot->updateProps(context.get()); else - ERR("Failed to initialize the default effect\n"); + ERR("Failed to initialize the default effect"); } - TRACE("Created context %p\n", voidp{context.get()}); + TRACE("Created context {}", voidp{context.get()}); return context.release(); } ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) noexcept { + if(!gProcessRunning) + return; + std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(ContextList.begin(), ContextList.end(), context); if(iter == ContextList.end() || *iter != context) @@ -2760,18 +2860,13 @@ ALC_API void ALC_APIENTRY alcDestroyContext(ALCcontext *context) noexcept ContextRef ctx{*iter}; ContextList.erase(iter); - ALCdevice *Device{ctx->mALDevice.get()}; - - std::lock_guard _{Device->StateLock}; - if(!ctx->deinit() && Device->Flags.test(DeviceRunning)) - { - Device->Backend->stop(); - Device->Flags.reset(DeviceRunning); - } + auto *Device = ctx->mALDevice.get(); + std::lock_guard statelock{Device->StateLock}; + ctx->deinit(); } -ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) noexcept +ALC_API auto ALC_APIENTRY alcGetCurrentContext() noexcept -> ALCcontext* { ALCcontext *Context{ALCcontext::getThreadContext()}; if(!Context) Context = ALCcontext::sGlobalContext.load(); @@ -2779,7 +2874,7 @@ ALC_API ALCcontext* ALC_APIENTRY alcGetCurrentContext(void) noexcept } /** Returns the currently active thread-local context. */ -ALC_API ALCcontext* ALC_APIENTRY alcGetThreadContext(void) noexcept +ALC_API auto ALC_APIENTRY alcGetThreadContext() noexcept -> ALCcontext* { return ALCcontext::getThreadContext(); } ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) noexcept @@ -2804,7 +2899,7 @@ ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent(ALCcontext *context) noexc * the current context as its refcount is decremented. */ } - ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())}; + ctx = ContextRef{ALCcontext::sGlobalContext.exchange(ctx.release())}; ALCcontext::sGlobalContextLock.store(false, std::memory_order_release); /* Take ownership of the thread-local context reference (if any), clearing @@ -2861,45 +2956,59 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) noexcep return nullptr; } - if(deviceName) + std::string_view devname{deviceName ? deviceName : ""}; + if(!devname.empty()) { - TRACE("Opening playback device \"%s\"\n", deviceName); - if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0 + TRACE("Opening playback device \"{}\"", devname); + if(al::case_compare(devname, GetDefaultName()) == 0 #ifdef _WIN32 /* Some old Windows apps hardcode these expecting OpenAL to use a * specific audio API, even when they're not enumerated. Creative's * router effectively ignores them too. */ - || al::strcasecmp(deviceName, "DirectSound3D") == 0 - || al::strcasecmp(deviceName, "DirectSound") == 0 - || al::strcasecmp(deviceName, "MMSYSTEM") == 0 + || al::case_compare(devname, "DirectSound3D"sv) == 0 + || al::case_compare(devname, "DirectSound"sv) == 0 + || al::case_compare(devname, "MMSYSTEM"sv) == 0 #endif /* Some old Linux apps hardcode configuration strings that were * supported by the OpenAL SI. We can't really do anything useful * with them, so just ignore. */ - || (deviceName[0] == '\'' && deviceName[1] == '(') - || al::strcasecmp(deviceName, "openal-soft") == 0) - deviceName = nullptr; + || al::starts_with(devname, "'("sv) + || al::case_compare(devname, "openal-soft"sv) == 0) + devname = {}; + else + { + const auto prefix = GetDevicePrefix(); + if(!prefix.empty() && devname.size() > prefix.size() + && al::starts_with(devname, prefix)) + devname = devname.substr(prefix.size()); + } } else - TRACE("Opening default playback device\n"); + TRACE("Opening default playback device"); const uint DefaultSends{ -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} : #endif // ALSOFT_EAX - DEFAULT_SENDS + uint{DefaultSendCount} }; - DeviceRef device{new ALCdevice{DeviceType::Playback}}; + auto device = DeviceRef{new(std::nothrow) al::Device{DeviceType::Playback}}; + if(!device) + { + WARN("Failed to create playback device handle"); + alcSetError(nullptr, ALC_OUT_OF_MEMORY); + return nullptr; + } /* Set output format */ device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; - device->Frequency = DEFAULT_OUTPUT_RATE; - device->UpdateSize = DEFAULT_UPDATE_SIZE; - device->BufferSize = DEFAULT_UPDATE_SIZE * DEFAULT_NUM_UPDATES; + device->mSampleRate = DefaultOutputRate; + device->mUpdateSize = DefaultUpdateSize; + device->mBufferSize = DefaultUpdateSize * DefaultNumUpdates; device->SourcesMax = 256; device->NumStereoSources = 1; @@ -2908,47 +3017,55 @@ ALC_API ALCdevice* ALC_APIENTRY alcOpenDevice(const ALCchar *deviceName) noexcep device->NumAuxSends = DefaultSends; try { - /* We need to ensure the device name isn't too long. The string_view is - * printed using the "%.*s" formatter, which uses an int for the - * precision/length. It wouldn't be a significant problem if larger - * values simply printed fewer characters due to truncation, but - * negative values are ignored, treating it like a normal null- - * terminated string, and string_views don't need to be null- - * terminated. - * - * Other than the annoyance of checking, this shouldn't be a problem. - * Two billion bytes is enough for a device name. - */ - const std::string_view devname{deviceName ? deviceName : ""}; - if(devname.length() >= std::numeric_limits::max()) - throw al::backend_exception{al::backend_error::NoDevice, - "Device name too long (%zu >= %d)", devname.length(), - std::numeric_limits::max()}; - auto backend = PlaybackFactory->createBackend(device.get(), BackendType::Playback); - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; backend->open(devname); + device->mDeviceName = std::string{GetDevicePrefix()}+backend->mDeviceName; device->Backend = std::move(backend); } catch(al::backend_exception &e) { - WARN("Failed to open playback device: %s\n", e.what()); + WARN("Failed to open playback device: {}", e.what()); alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory) ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE); return nullptr; } + auto checkopt = [&device](const char *envname, const std::string_view optname) + { + if(auto optval = al::getenv(envname)) return optval; + return device->configValue("game_compat", optname); + }; + if(auto overrideopt = checkopt("__ALSOFT_VENDOR_OVERRIDE", "vendor-override"sv)) + { + device->mVendorOverride = std::move(*overrideopt); + TRACE("Overriding vendor string: \"{}\"", device->mVendorOverride); + } + if(auto overrideopt = checkopt("__ALSOFT_VERSION_OVERRIDE", "version-override"sv)) + { + device->mVersionOverride = std::move(*overrideopt); + TRACE("Overriding version string: \"{}\"", device->mVersionOverride); + } + if(auto overrideopt = checkopt("__ALSOFT_RENDERER_OVERRIDE", "renderer-override"sv)) + { + device->mRendererOverride = std::move(*overrideopt); + TRACE("Overriding renderer string: \"{}\"", device->mRendererOverride); + } + { - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get()); DeviceList.emplace(iter, device.get()); } - TRACE("Created device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str()); + TRACE("Created device {}, \"{}\"", voidp{device.get()}, device->mDeviceName); return device.release(); } ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept { + if(!gProcessRunning) + return ALC_FALSE; + std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device); if(iter == DeviceList.end() || *iter != device) @@ -2975,7 +3092,7 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept auto ctxiter = std::lower_bound(ContextList.begin(), ContextList.end(), ctx); if(ctxiter != ContextList.end() && *ctxiter == ctx) { - orphanctxs.emplace_back(ContextRef{*ctxiter}); + orphanctxs.emplace_back(*ctxiter); ContextList.erase(ctxiter); } } @@ -2983,14 +3100,16 @@ ALC_API ALCboolean ALC_APIENTRY alcCloseDevice(ALCdevice *device) noexcept for(ContextRef &context : orphanctxs) { - WARN("Releasing orphaned context %p\n", voidp{context.get()}); + WARN("Releasing orphaned context {}", voidp{context.get()}); context->deinit(); } orphanctxs.clear(); - if(dev->Flags.test(DeviceRunning)) + if(dev->mDeviceState == DeviceState::Playing) + { dev->Backend->stop(); - dev->Flags.reset(DeviceRunning); + dev->mDeviceState = DeviceState::Configured; + } return ALC_TRUE; } @@ -3015,17 +3134,31 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return nullptr; } - if(deviceName) + std::string_view devname{deviceName ? deviceName : ""}; + if(!devname.empty()) { - TRACE("Opening capture device \"%s\"\n", deviceName); - if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0 - || al::strcasecmp(deviceName, "openal-soft") == 0) - deviceName = nullptr; + TRACE("Opening capture device \"{}\"", devname); + if(al::case_compare(devname, GetDefaultName()) == 0 + || al::case_compare(devname, "openal-soft"sv) == 0) + devname = {}; + else + { + const auto prefix = GetDevicePrefix(); + if(!prefix.empty() && devname.size() > prefix.size() + && al::starts_with(devname, prefix)) + devname = devname.substr(prefix.size()); + } } else - TRACE("Opening default capture device\n"); + TRACE("Opening default capture device"); - DeviceRef device{new ALCdevice{DeviceType::Capture}}; + auto device = DeviceRef{new(std::nothrow) al::Device{DeviceType::Capture}}; + if(!device) + { + WARN("Failed to create capture device handle"); + alcSetError(nullptr, ALC_OUT_OF_MEMORY); + return nullptr; + } auto decompfmt = DecomposeDevFormat(format); if(!decompfmt) @@ -3034,51 +3167,50 @@ ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice(const ALCchar *deviceName, return nullptr; } - device->Frequency = frequency; + device->mSampleRate = frequency; device->FmtChans = decompfmt->chans; device->FmtType = decompfmt->type; device->Flags.set(FrequencyRequest); device->Flags.set(ChannelsRequest); device->Flags.set(SampleTypeRequest); - device->UpdateSize = static_cast(samples); - device->BufferSize = static_cast(samples); + device->mUpdateSize = static_cast(samples); + device->mBufferSize = static_cast(samples); - TRACE("Capture format: %s, %s, %uhz, %u / %u buffer\n", DevFmtChannelsString(device->FmtChans), - DevFmtTypeString(device->FmtType), device->Frequency, device->UpdateSize, - device->BufferSize); + TRACE("Capture format: {}, {}, {}hz, {} / {} buffer", + DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), + device->mSampleRate, device->mUpdateSize, device->mBufferSize); try { - const std::string_view devname{deviceName ? deviceName : ""}; - if(devname.length() >= std::numeric_limits::max()) - throw al::backend_exception{al::backend_error::NoDevice, - "Device name too long (%zu >= %d)", devname.length(), - std::numeric_limits::max()}; - auto backend = CaptureFactory->createBackend(device.get(), BackendType::Capture); - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; backend->open(devname); + device->mDeviceName = std::string{GetDevicePrefix()}+backend->mDeviceName; device->Backend = std::move(backend); } catch(al::backend_exception &e) { - WARN("Failed to open capture device: %s\n", e.what()); + WARN("Failed to open capture device: {}", e.what()); alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory) ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE); return nullptr; } { - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get()); DeviceList.emplace(iter, device.get()); } + device->mDeviceState = DeviceState::Configured; - TRACE("Created capture device %p, \"%s\"\n", voidp{device.get()}, device->DeviceName.c_str()); + TRACE("Created capture device {}, \"{}\"", voidp{device.get()}, device->mDeviceName); return device.release(); } ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) noexcept { + if(!gProcessRunning) + return ALC_FALSE; + std::unique_lock listlock{ListLock}; auto iter = std::lower_bound(DeviceList.begin(), DeviceList.end(), device); if(iter == DeviceList.end() || *iter != device) @@ -3096,10 +3228,12 @@ ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice(ALCdevice *device) noexcep DeviceList.erase(iter); listlock.unlock(); - std::lock_guard _{dev->StateLock}; - if(dev->Flags.test(DeviceRunning)) + std::lock_guard statelock{dev->StateLock}; + if(dev->mDeviceState == DeviceState::Playing) + { dev->Backend->stop(); - dev->Flags.reset(DeviceRunning); + dev->mDeviceState = DeviceState::Configured; + } return ALC_TRUE; } @@ -3113,19 +3247,20 @@ ALC_API void ALC_APIENTRY alcCaptureStart(ALCdevice *device) noexcept return; } - std::lock_guard _{dev->StateLock}; - if(!dev->Connected.load(std::memory_order_acquire)) + std::lock_guard statelock{dev->StateLock}; + if(!dev->Connected.load(std::memory_order_acquire) + || dev->mDeviceState < DeviceState::Configured) alcSetError(dev.get(), ALC_INVALID_DEVICE); - else if(!dev->Flags.test(DeviceRunning)) + else if(dev->mDeviceState != DeviceState::Playing) { try { auto backend = dev->Backend.get(); backend->start(); - dev->Flags.set(DeviceRunning); + dev->mDeviceState = DeviceState::Playing; } catch(al::backend_exception& e) { - ERR("%s\n", e.what()); - dev->handleDisconnect("%s", e.what()); + ERR("{}", e.what()); + dev->handleDisconnect("{}", e.what()); alcSetError(dev.get(), ALC_INVALID_DEVICE); } } @@ -3138,10 +3273,12 @@ ALC_API void ALC_APIENTRY alcCaptureStop(ALCdevice *device) noexcept alcSetError(dev.get(), ALC_INVALID_DEVICE); else { - std::lock_guard _{dev->StateLock}; - if(dev->Flags.test(DeviceRunning)) + std::lock_guard statelock{dev->StateLock}; + if(dev->mDeviceState == DeviceState::Playing) + { dev->Backend->stop(); - dev->Flags.reset(DeviceRunning); + dev->mDeviceState = DeviceState::Configured; + } } } @@ -3162,7 +3299,7 @@ ALC_API void ALC_APIENTRY alcCaptureSamples(ALCdevice *device, ALCvoid *buffer, if(samples < 1) return; - std::lock_guard _{dev->StateLock}; + std::lock_guard statelock{dev->StateLock}; BackendBase *backend{dev->Backend.get()}; const auto usamples = static_cast(samples); @@ -3186,30 +3323,36 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN InitConfig(); /* Make sure the device name, if specified, is us. */ - if(deviceName && strcmp(deviceName, alcDefaultName) != 0) + if(deviceName && strcmp(deviceName, GetDefaultName()) != 0) { alcSetError(nullptr, ALC_INVALID_VALUE); return nullptr; } const uint DefaultSends{ -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_g_is_enabled ? uint{EAX_MAX_FXSLOTS} : #endif // ALSOFT_EAX - DEFAULT_SENDS + uint{DefaultSendCount} }; - DeviceRef device{new ALCdevice{DeviceType::Loopback}}; + auto device = DeviceRef{new(std::nothrow) al::Device{DeviceType::Loopback}}; + if(!device) + { + WARN("Failed to create loopback device handle"); + alcSetError(nullptr, ALC_OUT_OF_MEMORY); + return nullptr; + } device->SourcesMax = 256; device->AuxiliaryEffectSlotMax = 64; device->NumAuxSends = DefaultSends; //Set output format - device->BufferSize = 0; - device->UpdateSize = 0; + device->mBufferSize = 0; + device->mUpdateSize = 0; - device->Frequency = DEFAULT_OUTPUT_RATE; + device->mSampleRate = DefaultOutputRate; device->FmtChans = DevFmtChannelsDefault; device->FmtType = DevFmtTypeDefault; @@ -3220,22 +3363,23 @@ ALC_API ALCdevice* ALC_APIENTRY alcLoopbackOpenDeviceSOFT(const ALCchar *deviceN auto backend = LoopbackBackendFactory::getFactory().createBackend(device.get(), BackendType::Playback); backend->open("Loopback"); + device->mDeviceName = std::string{GetDevicePrefix()}+backend->mDeviceName; device->Backend = std::move(backend); } catch(al::backend_exception &e) { - WARN("Failed to open loopback device: %s\n", e.what()); + WARN("Failed to open loopback device: {}", e.what()); alcSetError(nullptr, (e.errorCode() == al::backend_error::OutOfMemory) ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE); return nullptr; } { - std::lock_guard _{ListLock}; + std::lock_guard listlock{ListLock}; auto iter = std::lower_bound(DeviceList.cbegin(), DeviceList.cend(), device.get()); DeviceList.emplace(iter, device.get()); } - TRACE("Created loopback device %p\n", voidp{device.get()}); + TRACE("Created loopback device {}", voidp{device.get()}); return device.release(); } @@ -3252,7 +3396,7 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device else { if(DevFmtTypeFromEnum(type).has_value() && DevFmtChannelsFromEnum(channels).has_value() - && freq >= MIN_OUTPUT_RATE && freq <= MAX_OUTPUT_RATE) + && freq >= int{MinOutputRate} && freq <= int{MaxOutputRate}) return ALC_TRUE; } @@ -3271,12 +3415,13 @@ ALC_API ALCboolean ALC_APIENTRY alcIsRenderFormatSupportedSOFT(ALCdevice *device #endif ALC_API void ALC_APIENTRY alcRenderSamplesSOFT(ALCdevice *device, ALCvoid *buffer, ALCsizei samples) noexcept { - if(!device || device->Type != DeviceType::Loopback) UNLIKELY - alcSetError(device, ALC_INVALID_DEVICE); + auto aldev = dynamic_cast(device); + if(!aldev || aldev->Type != DeviceType::Loopback) UNLIKELY + alcSetError(aldev, ALC_INVALID_DEVICE); else if(samples < 0 || (samples > 0 && buffer == nullptr)) UNLIKELY - alcSetError(device, ALC_INVALID_VALUE); + alcSetError(aldev, ALC_INVALID_VALUE); else - device->renderSamples(buffer, static_cast(samples), device->channelsFromFmt()); + aldev->renderSamples(buffer, static_cast(samples), aldev->channelsFromFmt()); } @@ -3292,10 +3437,12 @@ ALC_API void ALC_APIENTRY alcDevicePauseSOFT(ALCdevice *device) noexcept alcSetError(dev.get(), ALC_INVALID_DEVICE); else { - std::lock_guard _{dev->StateLock}; - if(dev->Flags.test(DeviceRunning)) + std::lock_guard statelock{dev->StateLock}; + if(dev->mDeviceState == DeviceState::Playing) + { dev->Backend->stop(); - dev->Flags.reset(DeviceRunning); + dev->mDeviceState = DeviceState::Configured; + } dev->Flags.set(DevicePaused); } } @@ -3310,9 +3457,21 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) noexcept return; } - std::lock_guard _{dev->StateLock}; + std::lock_guard statelock{dev->StateLock}; if(!dev->Flags.test(DevicePaused)) return; + if(dev->mDeviceState < DeviceState::Configured) + { + WARN("Cannot resume unconfigured device"); + alcSetError(dev.get(), ALC_INVALID_DEVICE); + return; + } + if(!dev->Connected.load()) + { + WARN("Cannot resume a disconnected device"); + alcSetError(dev.get(), ALC_INVALID_DEVICE); + return; + } dev->Flags.reset(DevicePaused); if(dev->mContexts.load()->empty()) return; @@ -3320,17 +3479,17 @@ ALC_API void ALC_APIENTRY alcDeviceResumeSOFT(ALCdevice *device) noexcept try { auto backend = dev->Backend.get(); backend->start(); - dev->Flags.set(DeviceRunning); + dev->mDeviceState = DeviceState::Playing; } catch(al::backend_exception& e) { - ERR("%s\n", e.what()); - dev->handleDisconnect("%s", e.what()); + ERR("{}", e.what()); + dev->handleDisconnect("{}", e.what()); alcSetError(dev.get(), ALC_INVALID_DEVICE); return; } - TRACE("Post-resume: %s, %s, %uhz, %u / %u buffer\n", - DevFmtChannelsString(device->FmtChans), DevFmtTypeString(device->FmtType), - device->Frequency, device->UpdateSize, device->BufferSize); + TRACE("Post-resume: {}, {}, {}hz, {} / {} buffer", + DevFmtChannelsString(dev->FmtChans), DevFmtTypeString(dev->FmtType), + dev->mSampleRate, dev->mUpdateSize, dev->mBufferSize); } @@ -3371,17 +3530,19 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi alcSetError(dev.get(), ALC_INVALID_DEVICE); return ALC_FALSE; } - std::lock_guard _{dev->StateLock}; + std::lock_guard statelock{dev->StateLock}; listlock.unlock(); /* Force the backend to stop mixing first since we're resetting. Also reset * the connected state so lost devices can attempt recover. */ - if(dev->Flags.test(DeviceRunning)) + if(dev->mDeviceState == DeviceState::Playing) + { dev->Backend->stop(); - dev->Flags.reset(DeviceRunning); + dev->mDeviceState = DeviceState::Configured; + } - return ResetDeviceParams(dev.get(), attribs) ? ALC_TRUE : ALC_FALSE; + return ResetDeviceParams(dev.get(), SpanFromAttributeList(attribs)) ? ALC_TRUE : ALC_FALSE; } @@ -3393,12 +3554,6 @@ ALC_API ALCboolean ALC_APIENTRY alcResetDeviceSOFT(ALCdevice *device, const ALCi FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, const ALCchar *deviceName, const ALCint *attribs) noexcept { - if(deviceName) - { - if(!deviceName[0] || al::strcasecmp(deviceName, alcDefaultName) == 0) - deviceName = nullptr; - } - std::unique_lock listlock{ListLock}; DeviceRef dev{VerifyDevice(device)}; if(!dev || dev->Type != DeviceType::Playback) @@ -3407,24 +3562,39 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, alcSetError(dev.get(), ALC_INVALID_DEVICE); return ALC_FALSE; } - std::lock_guard _{dev->StateLock}; + std::lock_guard statelock{dev->StateLock}; - /* Force the backend to stop mixing first since we're reopening. */ - if(dev->Flags.test(DeviceRunning)) + std::string_view devname{deviceName ? deviceName : ""}; + if(!devname.empty()) { - auto backend = dev->Backend.get(); - backend->stop(); - dev->Flags.reset(DeviceRunning); + if(devname.length() >= size_t{std::numeric_limits::max()}) + { + ERR("Device name too long ({} >= {})", devname.length(), + std::numeric_limits::max()); + alcSetError(dev.get(), ALC_INVALID_VALUE); + return ALC_FALSE; + } + if(al::case_compare(devname, GetDefaultName()) == 0) + devname = {}; + else + { + const auto prefix = GetDevicePrefix(); + if(!prefix.empty() && devname.size() > prefix.size() + && al::starts_with(devname, prefix)) + devname = devname.substr(prefix.size()); + } + } + + /* Force the backend device to stop first since we're opening another one. */ + const bool wasPlaying{dev->mDeviceState == DeviceState::Playing}; + if(wasPlaying) + { + dev->Backend->stop(); + dev->mDeviceState = DeviceState::Configured; } BackendPtr newbackend; try { - const std::string_view devname{deviceName ? deviceName : ""}; - if(devname.length() >= std::numeric_limits::max()) - throw al::backend_exception{al::backend_error::NoDevice, - "Device name too long (%zu >= %d)", devname.length(), - std::numeric_limits::max()}; - newbackend = PlaybackFactory->createBackend(dev.get(), BackendType::Playback); newbackend->open(devname); } @@ -3432,31 +3602,53 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, listlock.unlock(); newbackend = nullptr; - WARN("Failed to reopen playback device: %s\n", e.what()); + WARN("Failed to reopen playback device: {}", e.what()); alcSetError(dev.get(), (e.errorCode() == al::backend_error::OutOfMemory) ? ALC_OUT_OF_MEMORY : ALC_INVALID_VALUE); - /* If the device is connected, not paused, and has contexts, ensure it - * continues playing. - */ - if(dev->Connected.load(std::memory_order_relaxed) && !dev->Flags.test(DevicePaused) - && !dev->mContexts.load(std::memory_order_relaxed)->empty()) + if(dev->Connected.load(std::memory_order_relaxed) && wasPlaying) { try { auto backend = dev->Backend.get(); backend->start(); - dev->Flags.set(DeviceRunning); + dev->mDeviceState = DeviceState::Playing; } catch(al::backend_exception &be) { - ERR("%s\n", be.what()); - dev->handleDisconnect("%s", be.what()); + ERR("{}", be.what()); + dev->handleDisconnect("{}", be.what()); } } return ALC_FALSE; } listlock.unlock(); + dev->mDeviceName = std::string{GetDevicePrefix()}+newbackend->mDeviceName; dev->Backend = std::move(newbackend); - TRACE("Reopened device %p, \"%s\"\n", voidp{dev.get()}, dev->DeviceName.c_str()); + dev->mDeviceState = DeviceState::Unprepared; + TRACE("Reopened device {}, \"{}\"", voidp{dev.get()}, dev->mDeviceName); + + std::string{}.swap(dev->mVendorOverride); + std::string{}.swap(dev->mVersionOverride); + std::string{}.swap(dev->mRendererOverride); + auto checkopt = [&dev](const char *envname, const std::string_view optname) + { + if(auto optval = al::getenv(envname)) return optval; + return dev->configValue("game_compat", optname); + }; + if(auto overrideopt = checkopt("__ALSOFT_VENDOR_OVERRIDE", "vendor-override"sv)) + { + dev->mVendorOverride = std::move(*overrideopt); + TRACE("Overriding vendor string: \"{}\"", dev->mVendorOverride); + } + if(auto overrideopt = checkopt("__ALSOFT_VERSION_OVERRIDE", "version-override"sv)) + { + dev->mVersionOverride = std::move(*overrideopt); + TRACE("Overriding version string: \"{}\"", dev->mVersionOverride); + } + if(auto overrideopt = checkopt("__ALSOFT_RENDERER_OVERRIDE", "renderer-override"sv)) + { + dev->mRendererOverride = std::move(*overrideopt); + TRACE("Overriding renderer string: \"{}\"", dev->mRendererOverride); + } /* Always return true even if resetting fails. It shouldn't fail, but this * is primarily to avoid confusion by the app seeing the function return @@ -3469,6 +3661,38 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcReopenDeviceSOFT(ALCdevice *device, * In this way, we essentially act as if the function succeeded, but * immediately disconnects following it. */ - ResetDeviceParams(dev.get(), attribs); + ResetDeviceParams(dev.get(), SpanFromAttributeList(attribs)); return ALC_TRUE; } + +/************************************************ + * ALC event query functions + ************************************************/ + +FORCE_ALIGN ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) noexcept +{ + auto etype = alc::GetEventType(eventType); + if(!etype) + { + WARN("Invalid event type: {:#04x}", as_unsigned(eventType)); + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; + } + + auto supported = alc::EventSupport::NoSupport; + switch(deviceType) + { + case ALC_PLAYBACK_DEVICE_SOFT: + if(PlaybackFactory) + supported = PlaybackFactory->queryEventSupport(*etype, BackendType::Playback); + return al::to_underlying(supported); + + case ALC_CAPTURE_DEVICE_SOFT: + if(CaptureFactory) + supported = CaptureFactory->queryEventSupport(*etype, BackendType::Capture); + return al::to_underlying(supported); + } + WARN("Invalid device type: {:#04x}", as_unsigned(deviceType)); + alcSetError(nullptr, ALC_INVALID_ENUM); + return ALC_FALSE; +} diff --git a/3rdparty/openal/alc/alconfig.cpp b/3rdparty/openal/alc/alconfig.cpp index 097ba3a0ca1a..e0a3920ce1b1 100644 --- a/3rdparty/openal/alc/alconfig.cpp +++ b/3rdparty/openal/alc/alconfig.cpp @@ -22,9 +22,6 @@ #include "alconfig.h" -#include -#include -#include #ifdef _WIN32 #include #include @@ -34,18 +31,25 @@ #endif #include -#include +#include +#include +#include +#include +#include +#include #include +#include #include +#include -#include "alfstream.h" +#include "almalloc.h" #include "alstring.h" #include "core/helpers.h" #include "core/logging.h" +#include "filesystem.h" #include "strutils.h" -#include "vector.h" -#if defined(ALSOFT_UWP) +#if ALSOFT_UWP #include // !!This is important!! #include #include @@ -55,6 +59,14 @@ using namespace winrt; namespace { +using namespace std::string_view_literals; + +#if defined(_WIN32) && !defined(_GAMING_XBOX) && !ALSOFT_UWP +struct CoTaskMemDeleter { + void operator()(void *mem) const { CoTaskMemFree(mem); } +}; +#endif + struct ConfigEntry { std::string key; std::string value; @@ -79,57 +91,48 @@ bool readline(std::istream &f, std::string &output) return std::getline(f, output) && !output.empty(); } -std::string expdup(const char *str) +std::string expdup(std::string_view str) { std::string output; - std::string envval; - while(*str != '\0') + while(!str.empty()) { - const char *addstr; - size_t addstrlen; - - if(str[0] != '$') + if(auto nextpos = str.find('$')) { - const char *next = std::strchr(str, '$'); - addstr = str; - addstrlen = next ? static_cast(next-str) : std::strlen(str); + output += str.substr(0, nextpos); + if(nextpos == std::string_view::npos) + break; - str += addstrlen; + str.remove_prefix(nextpos); } - else - { - str++; - if(*str == '$') - { - const char *next = std::strchr(str+1, '$'); - addstr = str; - addstrlen = next ? static_cast(next-str) : std::strlen(str); - str += addstrlen; - } - else - { - const bool hasbraces{(*str == '{')}; + str.remove_prefix(1); + if(str.empty()) + { + output += '$'; + break; + } + if(str.front() == '$') + { + output += '$'; + str.remove_prefix(1); + continue; + } - if(hasbraces) str++; - const char *envstart = str; - while(std::isalnum(*str) || *str == '_') - ++str; - if(hasbraces && *str != '}') - continue; - const std::string envname{envstart, str}; - if(hasbraces) str++; + const bool hasbraces{str.front() == '{'}; + if(hasbraces) str.remove_prefix(1); - envval = al::getenv(envname.c_str()).value_or(std::string{}); - addstr = envval.data(); - addstrlen = envval.length(); - } - } - if(addstrlen == 0) + size_t envend{0}; + while(envend < str.size() && (std::isalnum(str[envend]) || str[envend] == '_')) + ++envend; + if(hasbraces && (envend == str.size() || str[envend] != '}')) continue; + const std::string envname{str.substr(0, envend)}; + if(hasbraces) ++envend; + str.remove_prefix(envend); - output.append(addstr, addstrlen); + if(auto envval = al::getenv(envname.c_str())) + output += *envval; } return output; @@ -147,44 +150,43 @@ void LoadConfigFromFile(std::istream &f) if(buffer[0] == '[') { - auto line = const_cast(buffer.data()); - char *section = line+1; - char *endsection; - - endsection = std::strchr(section, ']'); - if(!endsection || section == endsection) + auto endpos = buffer.find(']', 1); + if(endpos == 1 || endpos == std::string::npos) { - ERR(" config parse error: bad line \"%s\"\n", line); + ERR(" config parse error: bad line \"{}\"", buffer); continue; } - if(endsection[1] != 0) + if(buffer[endpos+1] != '\0') { - char *end = endsection+1; - while(std::isspace(*end)) - ++end; - if(*end != 0 && *end != '#') + size_t last{endpos+1}; + while(last < buffer.size() && std::isspace(buffer[last])) + ++last; + + if(last < buffer.size() && buffer[last] != '#') { - ERR(" config parse error: bad line \"%s\"\n", line); + ERR(" config parse error: bad line \"{}\"", buffer); continue; } } - *endsection = 0; + + auto section = std::string_view{buffer}.substr(1, endpos-1); curSection.clear(); - if(al::strcasecmp(section, "general") != 0) + if(al::case_compare(section, "general"sv) != 0) { do { - char *nextp = std::strchr(section, '%'); - if(!nextp) + auto nextp = section.find('%'); + if(nextp == std::string_view::npos) { curSection += section; break; } - curSection.append(section, nextp); - section = nextp; + curSection += section.substr(0, nextp); + section.remove_prefix(nextp); - if(((section[1] >= '0' && section[1] <= '9') || + if(section.size() > 2 && + ((section[1] >= '0' && section[1] <= '9') || (section[1] >= 'a' && section[1] <= 'f') || (section[1] >= 'A' && section[1] <= 'F')) && ((section[2] >= '0' && section[2] <= '9') || @@ -205,19 +207,19 @@ void LoadConfigFromFile(std::istream &f) else if(section[2] >= 'A' && section[2] <= 'F') b |= (section[2]-'A'+0x0a); curSection += static_cast(b); - section += 3; + section.remove_prefix(3); } - else if(section[1] == '%') + else if(section.size() > 1 && section[1] == '%') { curSection += '%'; - section += 2; + section.remove_prefix(2); } else { curSection += '%'; - section += 1; + section.remove_prefix(1); } - } while(*section != 0); + } while(!section.empty()); } continue; @@ -232,19 +234,20 @@ void LoadConfigFromFile(std::istream &f) auto sep = buffer.find('='); if(sep == std::string::npos) { - ERR(" config parse error: malformed option line: \"%s\"\n", buffer.c_str()); + ERR(" config parse error: malformed option line: \"{}\"", buffer); continue; } - auto keyend = sep++; - while(keyend > 0 && std::isspace(buffer[keyend-1])) - --keyend; - if(!keyend) + auto keypart = std::string_view{buffer}.substr(0, sep++); + while(!keypart.empty() && std::isspace(keypart.back())) + keypart.remove_suffix(1); + if(keypart.empty()) { - ERR(" config parse error: malformed option line: \"%s\"\n", buffer.c_str()); + ERR(" config parse error: malformed option line: \"{}\"", buffer); continue; } - while(sep < buffer.size() && std::isspace(buffer[sep])) - sep++; + auto valpart = std::string_view{buffer}.substr(sep); + while(!valpart.empty() && std::isspace(valpart.front())) + valpart.remove_prefix(1); std::string fullKey; if(!curSection.empty()) @@ -252,20 +255,24 @@ void LoadConfigFromFile(std::istream &f) fullKey += curSection; fullKey += '/'; } - fullKey += buffer.substr(0u, keyend); + fullKey += keypart; - std::string value{(sep < buffer.size()) ? buffer.substr(sep) : std::string{}}; - if(value.size() > 1) + if(valpart.size() > size_t{std::numeric_limits::max()}) + { + ERR(" config parse error: value too long in line \"{}\"", buffer); + continue; + } + if(valpart.size() > 1) { - if((value.front() == '"' && value.back() == '"') - || (value.front() == '\'' && value.back() == '\'')) + if((valpart.front() == '"' && valpart.back() == '"') + || (valpart.front() == '\'' && valpart.back() == '\'')) { - value.pop_back(); - value.erase(value.begin()); + valpart.remove_prefix(1); + valpart.remove_suffix(1); } } - TRACE(" found '%s' = '%s'\n", fullKey.c_str(), value.c_str()); + TRACE(" setting '{}' = '{}'", fullKey, valpart); /* Check if we already have this option set */ auto find_key = [&fullKey](const ConfigEntry &entry) -> bool @@ -273,61 +280,50 @@ void LoadConfigFromFile(std::istream &f) auto ent = std::find_if(ConfOpts.begin(), ConfOpts.end(), find_key); if(ent != ConfOpts.end()) { - if(!value.empty()) - ent->value = expdup(value.c_str()); + if(!valpart.empty()) + ent->value = expdup(valpart); else ConfOpts.erase(ent); } - else if(!value.empty()) - ConfOpts.emplace_back(ConfigEntry{std::move(fullKey), expdup(value.c_str())}); + else if(!valpart.empty()) + ConfOpts.emplace_back(ConfigEntry{std::move(fullKey), expdup(valpart)}); } ConfOpts.shrink_to_fit(); } -const char *GetConfigValue(const char *devName, const char *blockName, const char *keyName) +auto GetConfigValue(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> const std::string& { - if(!keyName) - return nullptr; + static const auto emptyString = std::string{}; + if(keyName.empty()) + return emptyString; std::string key; - if(blockName && al::strcasecmp(blockName, "general") != 0) + if(!blockName.empty() && al::case_compare(blockName, "general"sv) != 0) { key = blockName; - if(devName) - { - key += '/'; - key += devName; - } key += '/'; - key += keyName; } - else + if(!devName.empty()) { - if(devName) - { - key = devName; - key += '/'; - } - key += keyName; + key += devName; + key += '/'; } + key += keyName; auto iter = std::find_if(ConfOpts.cbegin(), ConfOpts.cend(), - [&key](const ConfigEntry &entry) -> bool - { return entry.key == key; }); + [&key](const ConfigEntry &entry) -> bool { return entry.key == key; }); if(iter != ConfOpts.cend()) { - TRACE("Found %s = \"%s\"\n", key.c_str(), iter->value.c_str()); + TRACE("Found option {} = \"{}\"", key, iter->value); if(!iter->value.empty()) - return iter->value.c_str(); - return nullptr; + return iter->value; + return emptyString; } - if(!devName) - { - TRACE("Key %s not found\n", key.c_str()); - return nullptr; - } - return GetConfigValue(nullptr, blockName, keyName); + if(devName.empty()) + return emptyString; + return GetConfigValue({}, blockName, keyName); } } // namespace @@ -336,42 +332,47 @@ const char *GetConfigValue(const char *devName, const char *blockName, const cha #ifdef _WIN32 void ReadALConfig() { + fs::path path; + #if !defined(_GAMING_XBOX) { -#if !defined(ALSOFT_UWP) - WCHAR buffer[MAX_PATH]; - if (!SHGetSpecialFolderPathW(nullptr, buffer, CSIDL_APPDATA, FALSE)) - return; +#if !ALSOFT_UWP + std::unique_ptr bufstore; + const HRESULT hr{SHGetKnownFolderPath(FOLDERID_RoamingAppData, KF_FLAG_DONT_UNEXPAND, + nullptr, al::out_ptr(bufstore))}; + if(SUCCEEDED(hr)) + { + const std::wstring_view buffer{bufstore.get()}; #else winrt::Windows::Storage::ApplicationDataContainer localSettings = winrt::Windows::Storage::ApplicationData::Current().LocalSettings(); - auto buffer = Windows::Storage::ApplicationData::Current().RoamingFolder().Path(); + auto bufstore = Windows::Storage::ApplicationData::Current().RoamingFolder().Path(); + std::wstring_view buffer{bufstore}; + { #endif - std::string filepath{wstr_to_utf8(buffer)}; - filepath += "\\alsoft.ini"; + path = fs::path{buffer}; + path /= L"alsoft.ini"; - TRACE("Loading config %s...\n", filepath.c_str()); - al::ifstream f{filepath}; - if(f.is_open()) - LoadConfigFromFile(f); + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(fs::ifstream f{path}; f.is_open()) + LoadConfigFromFile(f); + } } #endif - - std::string ppath{GetProcBinary().path}; - if(!ppath.empty()) + path = fs::u8path(GetProcBinary().path); + if(!path.empty()) { - ppath += "\\alsoft.ini"; - TRACE("Loading config %s...\n", ppath.c_str()); - al::ifstream f{ppath}; - if(f.is_open()) + path /= L"alsoft.ini"; + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(fs::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } if(auto confpath = al::getenv(L"ALSOFT_CONF")) { - TRACE("Loading config %s...\n", wstr_to_utf8(confpath->c_str()).c_str()); - al::ifstream f{*confpath}; - if(f.is_open()) + path = *confpath; + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(fs::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } } @@ -380,13 +381,11 @@ void ReadALConfig() void ReadALConfig() { - const char *str{"/etc/openal/alsoft.conf"}; + fs::path path{"/etc/openal/alsoft.conf"}; - TRACE("Loading config %s...\n", str); - al::ifstream f{str}; - if(f.is_open()) + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(fs::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); - f.close(); std::string confpaths{al::getenv("XDG_CONFIG_DIRS").value_or("/etc/xdg")}; /* Go through the list in reverse, since "the order of base directories @@ -394,48 +393,43 @@ void ReadALConfig() * important". Ergo, we need to load the settings from the later dirs * first so that the settings in the earlier dirs override them. */ - std::string fname; while(!confpaths.empty()) { - auto next = confpaths.find_last_of(':'); + auto next = confpaths.rfind(':'); if(next < confpaths.length()) { - fname = confpaths.substr(next+1); + path = fs::path{std::string_view{confpaths}.substr(next+1)}.lexically_normal(); confpaths.erase(next); } else { - fname = confpaths; + path = fs::path{confpaths}.lexically_normal(); confpaths.clear(); } - if(fname.empty() || fname.front() != '/') - WARN("Ignoring XDG config dir: %s\n", fname.c_str()); + if(!path.is_absolute()) + WARN("Ignoring XDG config dir: {}", al::u8_as_char(path.u8string())); else { - if(fname.back() != '/') fname += "/alsoft.conf"; - else fname += "alsoft.conf"; + path /= "alsoft.conf"; - TRACE("Loading config %s...\n", fname.c_str()); - f = al::ifstream{fname}; - if(f.is_open()) + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(fs::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } - fname.clear(); } #ifdef __APPLE__ CFBundleRef mainBundle = CFBundleGetMainBundle(); if(mainBundle) { - unsigned char fileName[PATH_MAX]; - CFURLRef configURL; + CFURLRef configURL{CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""), + nullptr)}; - if((configURL=CFBundleCopyResourceURL(mainBundle, CFSTR(".alsoftrc"), CFSTR(""), nullptr)) && - CFURLGetFileSystemRepresentation(configURL, true, fileName, sizeof(fileName))) + std::array fileName{}; + if(configURL && CFURLGetFileSystemRepresentation(configURL, true, fileName.data(), fileName.size())) { - f = al::ifstream{reinterpret_cast(fileName)}; - if(f.is_open()) + if(std::ifstream f{reinterpret_cast(fileName.data())}; f.is_open()) LoadConfigFromFile(f); } } @@ -443,102 +437,133 @@ void ReadALConfig() if(auto homedir = al::getenv("HOME")) { - fname = *homedir; - if(fname.back() != '/') fname += "/.alsoftrc"; - else fname += ".alsoftrc"; + path = *homedir; + path /= ".alsoftrc"; - TRACE("Loading config %s...\n", fname.c_str()); - f = al::ifstream{fname}; - if(f.is_open()) + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(std::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } if(auto configdir = al::getenv("XDG_CONFIG_HOME")) { - fname = *configdir; - if(fname.back() != '/') fname += "/alsoft.conf"; - else fname += "alsoft.conf"; + path = *configdir; + path /= "alsoft.conf"; } else { - fname.clear(); + path.clear(); if(auto homedir = al::getenv("HOME")) { - fname = *homedir; - if(fname.back() != '/') fname += "/.config/alsoft.conf"; - else fname += ".config/alsoft.conf"; + path = *homedir; + path /= ".config/alsoft.conf"; } } - if(!fname.empty()) + if(!path.empty()) { - TRACE("Loading config %s...\n", fname.c_str()); - f = al::ifstream{fname}; - if(f.is_open()) + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(std::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } - std::string ppath{GetProcBinary().path}; - if(!ppath.empty()) + path = GetProcBinary().path; + if(!path.empty()) { - if(ppath.back() != '/') ppath += "/alsoft.conf"; - else ppath += "alsoft.conf"; + path /= "alsoft.conf"; - TRACE("Loading config %s...\n", ppath.c_str()); - f = al::ifstream{ppath}; - if(f.is_open()) + TRACE("Loading config {}...", al::u8_as_char(path.u8string())); + if(std::ifstream f{path}; f.is_open()) LoadConfigFromFile(f); } if(auto confname = al::getenv("ALSOFT_CONF")) { - TRACE("Loading config %s...\n", confname->c_str()); - f = al::ifstream{*confname}; - if(f.is_open()) + TRACE("Loading config {}...", *confname); + if(std::ifstream f{*confname}; f.is_open()) LoadConfigFromFile(f); } } #endif -std::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName) +auto ConfigValueStr(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> std::optional { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) return val; return std::nullopt; } -std::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName) +auto ConfigValueInt(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> std::optional { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) - return static_cast(std::strtol(val, nullptr, 0)); + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) try { + return static_cast(std::stol(val, nullptr, 0)); + } + catch(std::exception&) { + WARN("Option is not an int: {} = {}", keyName, val); + } + return std::nullopt; } -std::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName) +auto ConfigValueUInt(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> std::optional { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) - return static_cast(std::strtoul(val, nullptr, 0)); + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) try { + return static_cast(std::stoul(val, nullptr, 0)); + } + catch(std::exception&) { + WARN("Option is not an unsigned int: {} = {}", keyName, val); + } return std::nullopt; } -std::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName) +auto ConfigValueFloat(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> std::optional { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) - return std::strtof(val, nullptr); + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) try { + return std::stof(val); + } + catch(std::exception&) { + WARN("Option is not a float: {} = {}", keyName, val); + } return std::nullopt; } -std::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName) +auto ConfigValueBool(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName) -> std::optional { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) - return al::strcasecmp(val, "on") == 0 || al::strcasecmp(val, "yes") == 0 - || al::strcasecmp(val, "true")==0 || atoi(val) != 0; + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) try { + return al::case_compare(val, "on"sv) == 0 || al::case_compare(val, "yes"sv) == 0 + || al::case_compare(val, "true"sv) == 0 || std::stoll(val) != 0; + } + catch(std::out_of_range&) { + /* If out of range, the value is some non-0 (true) value and it doesn't + * matter that it's too big or small. + */ + return true; + } + catch(std::exception&) { + /* If stoll fails to convert for any other reason, it's some other word + * that's treated as false. + */ + return false; + } return std::nullopt; } -bool GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, bool def) +auto GetConfigValueBool(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName, bool def) -> bool { - if(const char *val{GetConfigValue(devName, blockName, keyName)}) - return (al::strcasecmp(val, "on") == 0 || al::strcasecmp(val, "yes") == 0 - || al::strcasecmp(val, "true") == 0 || atoi(val) != 0); + if(auto&& val = GetConfigValue(devName, blockName, keyName); !val.empty()) try { + return al::case_compare(val, "on"sv) == 0 || al::case_compare(val, "yes"sv) == 0 + || al::case_compare(val, "true"sv) == 0 || std::stoll(val) != 0; + } + catch(std::out_of_range&) { + return true; + } + catch(std::exception&) { + return false; + } return def; } diff --git a/3rdparty/openal/alc/alconfig.h b/3rdparty/openal/alc/alconfig.h index 1eb44405bcae..e7daac28ef93 100644 --- a/3rdparty/openal/alc/alconfig.h +++ b/3rdparty/openal/alc/alconfig.h @@ -3,16 +3,23 @@ #include #include +#include void ReadALConfig(); -bool GetConfigValueBool(const char *devName, const char *blockName, const char *keyName, bool def); +bool GetConfigValueBool(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName, bool def); -std::optional ConfigValueStr(const char *devName, const char *blockName, const char *keyName); -std::optional ConfigValueInt(const char *devName, const char *blockName, const char *keyName); -std::optional ConfigValueUInt(const char *devName, const char *blockName, const char *keyName); -std::optional ConfigValueFloat(const char *devName, const char *blockName, const char *keyName); -std::optional ConfigValueBool(const char *devName, const char *blockName, const char *keyName); +std::optional ConfigValueStr(const std::string_view devName, + const std::string_view blockName, const std::string_view keyName); +std::optional ConfigValueInt(const std::string_view devName, const std::string_view blockName, + const std::string_view keyName); +std::optional ConfigValueUInt(const std::string_view devName, + const std::string_view blockName, const std::string_view keyName); +std::optional ConfigValueFloat(const std::string_view devName, + const std::string_view blockName, const std::string_view keyName); +std::optional ConfigValueBool(const std::string_view devName, + const std::string_view blockName, const std::string_view keyName); #endif /* ALCONFIG_H */ diff --git a/3rdparty/openal/alc/alu.cpp b/3rdparty/openal/alc/alu.cpp index 6eb4691edfa3..aab7eeeca5e7 100644 --- a/3rdparty/openal/alc/alu.cpp +++ b/3rdparty/openal/alc/alu.cpp @@ -19,6 +19,7 @@ */ #include "config.h" +#include "config_simd.h" #include "alu.h" @@ -26,23 +27,25 @@ #include #include #include -#include -#include +#include #include +#include +#include #include #include -#include #include #include #include -#include #include -#include +#include +#include #include +#include #include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" +#include "alsem.h" #include "alspan.h" #include "alstring.h" #include "atomic.h" @@ -70,6 +73,7 @@ #include "core/mixer/defs.h" #include "core/mixer/hrtfdefs.h" #include "core/resampler_limits.h" +#include "core/storage_formats.h" #include "core/uhjfilter.h" #include "core/voice.h" #include "core/voice_change.h" @@ -78,19 +82,18 @@ #include "ringbuffer.h" #include "strutils.h" #include "vecmat.h" -#include "vector.h" struct CTag; -#ifdef HAVE_SSE +#if HAVE_SSE struct SSETag; #endif -#ifdef HAVE_SSE2 +#if HAVE_SSE2 struct SSE2Tag; #endif -#ifdef HAVE_SSE4_1 +#if HAVE_SSE4_1 struct SSE4Tag; #endif -#ifdef HAVE_NEON +#if HAVE_NEON struct NEONTag; #endif struct PointTag; @@ -107,15 +110,14 @@ namespace { using uint = unsigned int; using namespace std::chrono; - -using namespace std::placeholders; +using namespace std::string_view_literals; float InitConeScale() { float ret{1.0f}; if(auto optval = al::getenv("__ALSOFT_HALF_ANGLE_CONES")) { - if(al::strcasecmp(optval->c_str(), "true") == 0 + if(al::case_compare(*optval, "true"sv) == 0 || strtol(optval->c_str(), nullptr, 0) == 1) ret *= 0.5f; } @@ -136,18 +138,19 @@ float NfcScale{1.0f}; using HrtfDirectMixerFunc = void(*)(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *AccumSamples, float *TempBuf, - HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize); + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChanState, + const size_t IrSize, const size_t SamplesToDo); HrtfDirectMixerFunc MixDirectHrtf{MixDirectHrtf_}; -inline HrtfDirectMixerFunc SelectHrtfMixer(void) +inline HrtfDirectMixerFunc SelectHrtfMixer() { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return MixDirectHrtf_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return MixDirectHrtf_; #endif @@ -164,7 +167,7 @@ inline void BsincPrepare(const uint increment, BsincState *state, const BSincTab if(increment > MixerFracOne) { sf = MixerFracOne/static_cast(increment) - table->scaleBase; - sf = maxf(0.0f, BSincScaleCount*sf*table->scaleRange - 1.0f); + sf = std::max(0.0f, BSincScaleCount*sf*table->scaleRange - 1.0f); si = float2uint(sf); /* The interpolation factor is fit to this diagonally-symmetric curve * to reduce the transition ripple caused by interpolating different @@ -176,7 +179,7 @@ inline void BsincPrepare(const uint increment, BsincState *state, const BSincTab state->sf = sf; state->m = table->m[si]; state->l = (state->m/2) - 1; - state->filter = table->Tab + table->filterOffset[si]; + state->filter = table->Tab.subspan(table->filterOffset[si]); } inline ResamplerFunc SelectResampler(Resampler resampler, uint increment) @@ -186,51 +189,62 @@ inline ResamplerFunc SelectResampler(Resampler resampler, uint increment) case Resampler::Point: return Resample_; case Resampler::Linear: -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Resample_; #endif -#ifdef HAVE_SSE4_1 +#if HAVE_SSE4_1 if((CPUCapFlags&CPU_CAP_SSE4_1)) return Resample_; #endif -#ifdef HAVE_SSE2 +#if HAVE_SSE2 if((CPUCapFlags&CPU_CAP_SSE2)) return Resample_; #endif return Resample_; - case Resampler::Cubic: -#ifdef HAVE_NEON + case Resampler::Spline: + case Resampler::Gaussian: +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Resample_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE4_1 + if((CPUCapFlags&CPU_CAP_SSE4_1)) + return Resample_; +#endif +#if HAVE_SSE2 + if((CPUCapFlags&CPU_CAP_SSE2)) + return Resample_; +#endif +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return Resample_; #endif return Resample_; case Resampler::BSinc12: case Resampler::BSinc24: + case Resampler::BSinc48: if(increment > MixerFracOne) { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Resample_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return Resample_; #endif return Resample_; } - /* fall-through */ + [[fallthrough]]; case Resampler::FastBSinc12: case Resampler::FastBSinc24: -#ifdef HAVE_NEON + case Resampler::FastBSinc48: +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Resample_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return Resample_; #endif @@ -249,7 +263,7 @@ void aluInit(CompatFlagBitset flags, const float nfcscale) YScale = flags.test(CompatFlags::ReverseY) ? -1.0f : 1.0f; ZScale = flags.test(CompatFlags::ReverseZ) ? -1.0f : 1.0f; - NfcScale = clampf(nfcscale, 0.0001f, 10000.0f); + NfcScale = std::clamp(nfcscale, 0.0001f, 10000.0f); } @@ -260,16 +274,23 @@ ResamplerFunc PrepareResampler(Resampler resampler, uint increment, InterpState case Resampler::Point: case Resampler::Linear: break; - case Resampler::Cubic: - state->cubic.filter = gCubicSpline.Tab.data(); + case Resampler::Spline: + state->emplace(al::span{gSplineFilter.mTable}); + break; + case Resampler::Gaussian: + state->emplace(al::span{gGaussianFilter.mTable}); break; case Resampler::FastBSinc12: case Resampler::BSinc12: - BsincPrepare(increment, &state->bsinc, &gBSinc12); + BsincPrepare(increment, &state->emplace(), &gBSinc12); break; case Resampler::FastBSinc24: case Resampler::BSinc24: - BsincPrepare(increment, &state->bsinc, &gBSinc24); + BsincPrepare(increment, &state->emplace(), &gBSinc24); + break; + case Resampler::FastBSinc48: + case Resampler::BSinc48: + BsincPrepare(increment, &state->emplace(), &gBSinc48); break; } return SelectResampler(resampler, increment); @@ -279,34 +300,33 @@ ResamplerFunc PrepareResampler(Resampler resampler, uint increment, InterpState void DeviceBase::ProcessHrtf(const size_t SamplesToDo) { /* HRTF is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; MixDirectHrtf(RealOut.Buffer[lidx], RealOut.Buffer[ridx], Dry.Buffer, HrtfAccumData, - mHrtfState->mTemp.data(), mHrtfState->mChannels.data(), mHrtfState->mIrSize, SamplesToDo); + mHrtfState->mTemp, mHrtfState->mChannels, mHrtfState->mIrSize, SamplesToDo); } void DeviceBase::ProcessAmbiDec(const size_t SamplesToDo) { - AmbiDecoder->process(RealOut.Buffer, Dry.Buffer.data(), SamplesToDo); + AmbiDecoder->process(RealOut.Buffer, Dry.Buffer, SamplesToDo); } void DeviceBase::ProcessAmbiDecStablized(const size_t SamplesToDo) { /* Decode with front image stablization. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; - const uint cidx{RealOut.ChannelIndex[FrontCenter]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t cidx{RealOut.ChannelIndex[FrontCenter]}; - AmbiDecoder->processStablize(RealOut.Buffer, Dry.Buffer.data(), lidx, ridx, cidx, - SamplesToDo); + AmbiDecoder->processStablize(RealOut.Buffer, Dry.Buffer, lidx, ridx, cidx, SamplesToDo); } void DeviceBase::ProcessUhj(const size_t SamplesToDo) { /* UHJ is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; /* Encode to stereo-compatible 2-channel UHJ output. */ mUhjEncoder->encode(RealOut.Buffer[lidx].data(), RealOut.Buffer[ridx].data(), @@ -316,15 +336,15 @@ void DeviceBase::ProcessUhj(const size_t SamplesToDo) void DeviceBase::ProcessBs2b(const size_t SamplesToDo) { /* First, decode the ambisonic mix to the "real" output. */ - AmbiDecoder->process(RealOut.Buffer, Dry.Buffer.data(), SamplesToDo); + AmbiDecoder->process(RealOut.Buffer, Dry.Buffer, SamplesToDo); /* BS2B is stereo output only. */ - const uint lidx{RealOut.ChannelIndex[FrontLeft]}; - const uint ridx{RealOut.ChannelIndex[FrontRight]}; + const size_t lidx{RealOut.ChannelIndex[FrontLeft]}; + const size_t ridx{RealOut.ChannelIndex[FrontRight]}; /* Now apply the BS2B binaural/crossfeed filter. */ - bs2b_cross_feed(Bs2b.get(), RealOut.Buffer[lidx].data(), RealOut.Buffer[ridx].data(), - SamplesToDo); + Bs2b->cross_feed(al::span{RealOut.Buffer[lidx]}.first(SamplesToDo), + al::span{RealOut.Buffer[ridx]}.first(SamplesToDo)); } @@ -350,21 +370,22 @@ inline uint dither_rng(uint *seed) noexcept void UpsampleBFormatTransform( const al::span,MaxAmbiChannels> output, const al::span> upsampler, - const al::span,MaxAmbiChannels> rotator, size_t coeffs_order) + const al::span,MaxAmbiChannels> rotator, + size_t ambi_order) { - const size_t num_chans{AmbiChannelsFromOrder(coeffs_order)}; + const size_t num_chans{AmbiChannelsFromOrder(ambi_order)}; for(size_t i{0};i < upsampler.size();++i) output[i].fill(0.0f); for(size_t i{0};i < upsampler.size();++i) { for(size_t k{0};k < num_chans;++k) { - float *RESTRICT out{output[i].data()}; + const float a{upsampler[i][k]}; /* Write the full number of channels. The compiler will have an * easier time optimizing if it has a fixed length. */ - for(size_t j{0};j < MaxAmbiChannels;++j) - out[j] += upsampler[i][k] * rotator[k][j]; + std::transform(rotator[k].cbegin(), rotator[k].cend(), output[i].cbegin(), + output[i].begin(), [a](float rot, float dst) noexcept { return rot*a + dst; }); } } } @@ -423,11 +444,19 @@ bool CalcContextParams(ContextBase *ctx) ctx->mParams.Velocity = rot * vel; ctx->mParams.Gain = props->Gain * ctx->mGainBoost; - ctx->mParams.MetersPerUnit = props->MetersPerUnit; + ctx->mParams.MetersPerUnit = props->MetersPerUnit +#if ALSOFT_EAX + * props->DistanceFactor +#endif + ; ctx->mParams.AirAbsorptionGainHF = props->AirAbsorptionGainHF; ctx->mParams.DopplerFactor = props->DopplerFactor; - ctx->mParams.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity; + ctx->mParams.SpeedOfSound = props->SpeedOfSound * props->DopplerVelocity +#if ALSOFT_EAX + / props->DistanceFactor +#endif + ; ctx->mParams.SourceDistanceModel = props->SourceDistanceModel; ctx->mParams.mDistanceModel = props->mDistanceModel; @@ -451,23 +480,27 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa slot->Target = props->Target; slot->EffectType = props->Type; slot->mEffectProps = props->Props; - if(props->Type == EffectSlotType::Reverb || props->Type == EffectSlotType::EAXReverb) - { - slot->RoomRolloff = props->Props.Reverb.RoomRolloffFactor; - slot->DecayTime = props->Props.Reverb.DecayTime; - slot->DecayLFRatio = props->Props.Reverb.DecayLFRatio; - slot->DecayHFRatio = props->Props.Reverb.DecayHFRatio; - slot->DecayHFLimit = props->Props.Reverb.DecayHFLimit; - slot->AirAbsorptionGainHF = props->Props.Reverb.AirAbsorptionGainHF; - } - else + + slot->RoomRolloff = 0.0f; + slot->DecayTime = 0.0f; + slot->DecayLFRatio = 0.0f; + slot->DecayHFRatio = 0.0f; + slot->DecayHFLimit = false; + slot->AirAbsorptionGainHF = 1.0f; + if(auto *reverbprops = std::get_if(&props->Props)) { - slot->RoomRolloff = 0.0f; - slot->DecayTime = 0.0f; - slot->DecayLFRatio = 0.0f; - slot->DecayHFRatio = 0.0f; - slot->DecayHFLimit = false; - slot->AirAbsorptionGainHF = 1.0f; + slot->RoomRolloff = reverbprops->RoomRolloffFactor; + slot->AirAbsorptionGainHF = reverbprops->AirAbsorptionGainHF; + /* If this effect slot's Auxiliary Send Auto is off, don't apply the + * automatic send adjustments based on source distance. + */ + if(slot->AuxSendAuto) + { + slot->DecayTime = reverbprops->DecayTime; + slot->DecayLFRatio = reverbprops->DecayLFRatio; + slot->DecayHFRatio = reverbprops->DecayHFRatio; + slot->DecayHFLimit = reverbprops->DecayHFLimit; + } } EffectState *state{props->State.release()}; @@ -482,9 +515,9 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa /* Otherwise, if it would be deleted send it off with a release event. */ RingBuffer *ring{context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); - if(evt_vec.first.len > 0) LIKELY + if(evt_vec[0].len > 0) LIKELY { - auto &evt = InitAsyncEvent(evt_vec.first.buf); + auto &evt = InitAsyncEvent(evt_vec[0].buf); evt.mEffectState = oldstate; ring->writeAdvance(1); } @@ -499,16 +532,15 @@ bool CalcEffectSlotParams(EffectSlot *slot, EffectSlot **sorted_slots, ContextBa } } - AtomicReplaceHead(context->mFreeEffectslotProps, props); + AtomicReplaceHead(context->mFreeEffectSlotProps, props); - EffectTarget output; - if(EffectSlot *target{slot->Target}) - output = EffectTarget{&target->Wet, nullptr}; - else + const auto output = [slot,context]() -> EffectTarget { + if(EffectSlot *target{slot->Target}) + return EffectTarget{&target->Wet, nullptr}; DeviceBase *device{context->mDevice}; - output = EffectTarget{&device->Dry, &device->RealOut}; - } + return EffectTarget{&device->Dry, &device->RealOut}; + }(); state->update(context, slot, &slot->mEffectProps, output); return true; } @@ -603,19 +635,18 @@ inline std::array ScaleAzimuthFront3_2(std::array pos) * precomputed since they're constant. The second-order coefficients are * followed by the third-order coefficients, etc. */ -template -constexpr size_t CalcRotatorSize() -{ return (L*2 + 1)*(L*2 + 1) + CalcRotatorSize(); } - -template<> constexpr size_t CalcRotatorSize<0>() = delete; -template<> constexpr size_t CalcRotatorSize<1>() = delete; -template<> constexpr size_t CalcRotatorSize<2>() { return 5*5; } +constexpr size_t CalcRotatorSize(size_t l) noexcept +{ + if(l >= 2) + return (l*2 + 1)*(l*2 + 1) + CalcRotatorSize(l-1); + return 0; +} struct RotatorCoeffs { struct CoeffValues { float u, v, w; }; - std::array()> mCoeffs{}; + std::array mCoeffs{}; RotatorCoeffs() { @@ -627,17 +658,38 @@ struct RotatorCoeffs { { for(int m{-l};m <= l;++m) { - // compute u,v,w terms of Eq.8.1 (Table I) - const bool d{m == 0}; // the delta function d_m0 - const float denom{static_cast((std::abs(n) == l) ? - (2*l) * (2*l - 1) : (l*l - n*n))}; - - const int abs_m{std::abs(m)}; - coeffs->u = std::sqrt(static_cast(l*l - m*m)/denom); - coeffs->v = std::sqrt(static_cast(l+abs_m-1) * - static_cast(l+abs_m) / denom) * (1.0f+d) * (1.0f - 2.0f*d) * 0.5f; - coeffs->w = std::sqrt(static_cast(l-abs_m-1) * - static_cast(l-abs_m) / denom) * (1.0f-d) * -0.5f; + /* compute u,v,w terms of Eq.8.1 (Table I) + * + * const bool d{m == 0}; // the delta function d_m0 + * const double denom{(std::abs(n) == l) ? + * (2*l) * (2*l - 1) : (l*l - n*n)}; + * + * const int abs_m{std::abs(m)}; + * coeffs->u = std::sqrt((l*l - m*m) / denom); + * coeffs->v = std::sqrt((l+abs_m-1) * (l+abs_m) / denom) * + * (1.0+d) * (1.0 - 2.0*d) * 0.5; + * coeffs->w = std::sqrt((l-abs_m-1) * (l-abs_m) / denom) * + * (1.0-d) * -0.5; + */ + + const double denom{static_cast((std::abs(n) == l) ? + (2*l) * (2*l - 1) : (l*l - n*n))}; + + if(m == 0) + { + coeffs->u = static_cast(std::sqrt(l * l / denom)); + coeffs->v = static_cast(std::sqrt((l-1) * l / denom) * -1.0); + coeffs->w = 0.0f; + } + else + { + const int abs_m{std::abs(m)}; + coeffs->u = static_cast(std::sqrt((l*l - m*m) / denom)); + coeffs->v = static_cast(std::sqrt((l+abs_m-1) * (l+abs_m) / denom) * + 0.5); + coeffs->w = static_cast(std::sqrt((l-abs_m-1) * (l-abs_m) / denom) * + -0.5); + } ++coeffs; } } @@ -656,27 +708,27 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) /* Don't do anything for < 2nd order. */ if(order < 2) return; - auto P = [](const int i, const int l, const int a, const int n, const size_t last_band, - const AmbiRotateMatrix &R) + static constexpr auto P = [](const int i, const int l, const int a, const int n, + const size_t last_band, const AmbiRotateMatrix &R) { - const float ri1{ R[ 1+2][static_cast(i+2)]}; - const float rim1{R[-1+2][static_cast(i+2)]}; - const float ri0{ R[ 0+2][static_cast(i+2)]}; + const float ri1{ R[ 1+2][static_cast(i+2_z)]}; + const float rim1{R[-1+2][static_cast(i+2_z)]}; + const float ri0{ R[ 0+2][static_cast(i+2_z)]}; const size_t y{last_band + static_cast(a+l-1)}; if(n == -l) - return ri1*R[last_band][y] + rim1*R[last_band + static_cast(l-1)*2][y]; + return ri1*R[last_band][y] + rim1*R[last_band + static_cast(l-1_z)*2][y]; if(n == l) - return ri1*R[last_band + static_cast(l-1)*2][y] - rim1*R[last_band][y]; - return ri0*R[last_band + static_cast(n+l-1)][y]; + return ri1*R[last_band + static_cast(l-1_z)*2][y] - rim1*R[last_band][y]; + return ri0*R[last_band + static_cast(l-1_z+n)][y]; }; - auto U = [P](const int l, const int m, const int n, const size_t last_band, + static constexpr auto U = [](const int l, const int m, const int n, const size_t last_band, const AmbiRotateMatrix &R) { return P(0, l, m, n, last_band, R); }; - auto V = [P](const int l, const int m, const int n, const size_t last_band, + static constexpr auto V = [](const int l, const int m, const int n, const size_t last_band, const AmbiRotateMatrix &R) { using namespace al::numbers; @@ -692,7 +744,7 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) const float p1{P(-1, l, -m-1, n, last_band, R)}; return d ? p1*sqrt2_v : (p0 + p1); }; - auto W = [P](const int l, const int m, const int n, const size_t last_band, + static constexpr auto W = [](const int l, const int m, const int n, const size_t last_band, const AmbiRotateMatrix &R) { assert(m != 0); @@ -721,12 +773,12 @@ void AmbiRotator(AmbiRotateMatrix &matrix, const int order) float r{0.0f}; // computes Eq.8.1 - const float u{coeffs->u}; - if(u != 0.0f) r += u * U(l, m, n, last_band, matrix); - const float v{coeffs->v}; - if(v != 0.0f) r += v * V(l, m, n, last_band, matrix); - const float w{coeffs->w}; - if(w != 0.0f) r += w * W(l, m, n, last_band, matrix); + if(const float u{coeffs->u}; u != 0.0f) + r += u * U(l, m, n, last_band, matrix); + if(const float v{coeffs->v}; v != 0.0f) + r += v * V(l, m, n, last_band, matrix); + if(const float w{coeffs->w}; w != 0.0f) + r += w * W(l, m, n, last_band, matrix); matrix[y][x] = r; ++coeffs; @@ -756,51 +808,57 @@ struct GainTriplet { float Base, HF, LF; }; void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, const float zpos, const float Distance, const float Spread, const GainTriplet &DryGain, - const al::span WetGain, EffectSlot *(&SendSlots)[MAX_SENDS], - const VoiceProps *props, const ContextParams &Context, DeviceBase *Device) + const al::span WetGain, + const al::span SendSlots, const VoiceProps *props, + const ContextParams &Context, DeviceBase *Device) { - static constexpr ChanPosMap MonoMap[1]{ - { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } - }, RearMap[2]{ - { BackLeft, std::array{-sin30, 0.0f, cos30} }, - { BackRight, std::array{ sin30, 0.0f, cos30} }, - }, QuadMap[4]{ - { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, - { FrontRight, std::array{ sin45, 0.0f, -cos45} }, - { BackLeft, std::array{-sin45, 0.0f, cos45} }, - { BackRight, std::array{ sin45, 0.0f, cos45} }, - }, X51Map[6]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { SideLeft, std::array{-sin110, 0.0f, -cos110} }, - { SideRight, std::array{ sin110, 0.0f, -cos110} }, - }, X61Map[7]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, - { SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, - }, X71Map[8]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackLeft, std::array{-sin30, 0.0f, cos30} }, - { BackRight, std::array{ sin30, 0.0f, cos30} }, - { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, + static constexpr std::array MonoMap{ + ChanPosMap{FrontCenter, std::array{0.0f, 0.0f, -1.0f}} + }; + static constexpr std::array RearMap{ + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + }; + static constexpr std::array QuadMap{ + ChanPosMap{FrontLeft, std::array{-sin45, 0.0f, -cos45}}, + ChanPosMap{FrontRight, std::array{ sin45, 0.0f, -cos45}}, + ChanPosMap{BackLeft, std::array{-sin45, 0.0f, cos45}}, + ChanPosMap{BackRight, std::array{ sin45, 0.0f, cos45}}, + }; + static constexpr std::array X51Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{SideLeft, std::array{-sin110, 0.0f, -cos110}}, + ChanPosMap{SideRight, std::array{ sin110, 0.0f, -cos110}}, + }; + static constexpr std::array X61Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackCenter, std::array{ 0.0f, 0.0f, 1.0f}}, + ChanPosMap{SideLeft, std::array{-1.0f, 0.0f, 0.0f}}, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f}}, + }; + static constexpr std::array X71Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + ChanPosMap{SideLeft, std::array{ -1.0f, 0.0f, 0.0f}}, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f}}, }; - ChanPosMap StereoMap[2]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, + std::array StereoMap{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, }; - const auto Frequency = static_cast(Device->Frequency); + const auto Frequency = static_cast(Device->mSampleRate); const uint NumSends{Device->NumAuxSends}; const size_t num_channels{voice->mChans.size()}; @@ -814,49 +872,84 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con [](SendParams ¶ms) -> void { params.Gains.Target.fill(0.0f); }); } - DirectMode DirectChannels{props->DirectChannels}; - const ChanPosMap *chans{nullptr}; - switch(voice->mFmtChannels) + const auto getChans = [props,&StereoMap](FmtChannels chanfmt) noexcept + -> std::pair> { - case FmtMono: - chans = MonoMap; - /* Mono buffers are never played direct. */ - DirectChannels = DirectMode::Off; - break; - - case FmtStereo: - if(DirectChannels == DirectMode::Off) + switch(chanfmt) { - for(size_t i{0};i < 2;++i) + case FmtMono: + /* Mono buffers are never played direct. */ + return {DirectMode::Off, al::span{MonoMap}}; + + case FmtStereo: + case FmtMonoDup: + if(props->DirectChannels == DirectMode::Off) { - /* StereoPan is counter-clockwise in radians. */ - const float a{props->StereoPan[i]}; - StereoMap[i].pos[0] = -std::sin(a); - StereoMap[i].pos[2] = -std::cos(a); + for(size_t i{0};i < 2;++i) + { + /* StereoPan is counter-clockwise in radians. */ + const float a{props->StereoPan[i]}; + StereoMap[i].pos[0] = -std::sin(a); + StereoMap[i].pos[2] = -std::cos(a); + } } + return {props->DirectChannels, al::span{StereoMap}}; + + case FmtRear: return {props->DirectChannels, al::span{RearMap}}; + case FmtQuad: return {props->DirectChannels, al::span{QuadMap}}; + case FmtX51: return {props->DirectChannels, al::span{X51Map}}; + case FmtX61: return {props->DirectChannels, al::span{X61Map}}; + case FmtX71: return {props->DirectChannels, al::span{X71Map}}; + + case FmtBFormat2D: + case FmtBFormat3D: + case FmtUHJ2: + case FmtUHJ3: + case FmtUHJ4: + case FmtSuperStereo: + return {DirectMode::Off, {}}; } - chans = StereoMap; - break; - - case FmtRear: chans = RearMap; break; - case FmtQuad: chans = QuadMap; break; - case FmtX51: chans = X51Map; break; - case FmtX61: chans = X61Map; break; - case FmtX71: chans = X71Map; break; - - case FmtBFormat2D: - case FmtBFormat3D: - case FmtUHJ2: - case FmtUHJ3: - case FmtUHJ4: - case FmtSuperStereo: - DirectChannels = DirectMode::Off; - break; - } + return {props->DirectChannels, {}}; + }; + const auto [DirectChannels,chans] = getChans(voice->mFmtChannels); voice->mFlags.reset(VoiceHasHrtf).reset(VoiceHasNfc); if(auto *decoder{voice->mDecoder.get()}) - decoder->mWidthControl = minf(props->EnhWidth, 0.7f); + decoder->mWidthControl = std::min(props->EnhWidth, 0.7f); + + const float lgain{std::min(1.0f-props->Panning, 1.0f)}; + const float rgain{std::min(1.0f+props->Panning, 1.0f)}; + const float mingain{std::min(lgain, rgain)}; + auto SelectChannelGain = [lgain,rgain,mingain](const Channel chan) noexcept + { + switch(chan) + { + case FrontLeft: return lgain; + case FrontRight: return rgain; + case FrontCenter: break; + case LFE: break; + case BackLeft: return lgain; + case BackRight: return rgain; + case BackCenter: break; + case SideLeft: return lgain; + case SideRight: return rgain; + case TopCenter: break; + case TopFrontLeft: return lgain; + case TopFrontCenter: break; + case TopFrontRight: return rgain; + case TopBackLeft: return lgain; + case TopBackCenter: break; + case TopBackRight: return rgain; + case BottomFrontLeft: return lgain; + case BottomFrontRight: return rgain; + case BottomBackLeft: return lgain; + case BottomBackRight: return rgain; + case Aux0: case Aux1: case Aux2: case Aux3: case Aux4: case Aux5: case Aux6: case Aux7: + case Aux8: case Aux9: case Aux10: case Aux11: case Aux12: case Aux13: case Aux14: + case Aux15: case MaxChannels: break; + } + return mingain; + }; if(IsAmbisonic(voice->mFmtChannels)) { @@ -878,7 +971,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con /* Clamp the distance for really close sources, to prevent * excessive bass. */ - const float mdist{maxf(Distance*NfcScale, Device->AvgSpeakerDist/4.0f)}; + const float mdist{std::max(Distance*NfcScale, Device->AvgSpeakerDist/4.0f)}; const float w0{SpeedOfSoundMetersPerSec / (mdist * Frequency)}; /* Only need to adjust the first channel of a B-Format source. */ @@ -908,12 +1001,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con if(!(coverage > 0.0f)) { - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base*scales[0], + ComputePanGains(&Device->Dry, coeffs, DryGain.Base*scales[0], voice->mChans[0].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base*scales[0], + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base*scales[0], voice->mChans[0].mWetParams[i].Gains.Target); } } @@ -995,9 +1088,9 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con /* Convert the rotation matrix for input ordering and scaling, and * whether input is 2D or 3D. */ - const uint8_t *index_map{Is2DAmbisonic(voice->mFmtChannels) ? - GetAmbi2DLayout(voice->mAmbiLayout).data() : - GetAmbiLayout(voice->mAmbiLayout).data()}; + const auto index_map = Is2DAmbisonic(voice->mFmtChannels) ? + GetAmbi2DLayout(voice->mAmbiLayout).subspan(0) : + GetAmbiLayout(voice->mAmbiLayout).subspan(0); /* Scale the panned W signal inversely to coverage (full coverage * means no panned signal), and according to the channel scaling. @@ -1014,16 +1107,17 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con * to the coverage amount) with the directional pan. For all * other channels, use just the (scaled) B-Format signal. */ - for(size_t x{0};x < MaxAmbiChannels;++x) - coeffs[x] += mixmatrix[acn][x] * scale; + std::transform(mixmatrix[acn].cbegin(), mixmatrix[acn].cend(), coeffs.begin(), + coeffs.begin(), [scale](const float in, const float coeff) noexcept + { return in*scale + coeff; }); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[c].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[c].mWetParams[i].Gains.Target); } @@ -1040,13 +1134,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(size_t c{0};c < num_channels;c++) { - uint idx{Device->channelIdxByName(chans[c].channel)}; - if(idx != InvalidChannelIndex) - voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base; + const float pangain{SelectChannelGain(chans[c].channel)}; + if(uint idx{Device->channelIdxByName(chans[c].channel)}; idx != InvalidChannelIndex) + voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base * pangain; else if(DirectChannels == DirectMode::RemixMismatch) { - auto match_channel = [chans,c](const InputRemixMap &map) noexcept -> bool - { return chans[c].channel == map.channel; }; + auto match_channel = [channel=chans[c].channel](const InputRemixMap &map) noexcept + { return channel == map.channel; }; auto remap = std::find_if(Device->RealOut.RemixMap.cbegin(), Device->RealOut.RemixMap.cend(), match_channel); if(remap != Device->RealOut.RemixMap.cend()) @@ -1055,8 +1149,8 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con { idx = Device->channelIdxByName(target.channel); if(idx != InvalidChannelIndex) - voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base * - target.mix; + voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base * pangain + * target.mix; } } } @@ -1071,12 +1165,13 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con if(chans[c].channel == LFE) continue; + const float pangain{SelectChannelGain(chans[c].channel)}; const auto coeffs = CalcDirectionCoeffs(chans[c].pos, 0.0f); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base * pangain, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1092,7 +1187,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con { if(voice->mFmtChannels == FmtMono) { - const float src_ev{std::asin(clampf(ypos, -1.0f, 1.0f))}; + const float src_ev{std::asin(std::clamp(ypos, -1.0f, 1.0f))}; const float src_az{std::atan2(xpos, -zpos)}; Device->mHrtf->getCoeffs(src_ev, src_az, Distance*NfcScale, Spread, @@ -1104,23 +1199,22 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[0].mWetParams[i].Gains.Target); } } else for(size_t c{0};c < num_channels;c++) { - using namespace al::numbers; - /* Skip LFE */ if(chans[c].channel == LFE) continue; + const float pangain{SelectChannelGain(chans[c].channel)}; /* Warp the channel position toward the source position as the * source spread decreases. With no spread, all channels are at * the source position, at full spread (pi*2), each channel is * left unchanged. */ - const float a{1.0f - (inv_pi_v/2.0f)*Spread}; + const float a{1.0f - (al::numbers::inv_pi_v/2.0f)*Spread}; std::array pos{ lerpf(chans[c].pos[0], xpos, a), lerpf(chans[c].pos[1], ypos, a), @@ -1133,19 +1227,19 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con pos[2] /= len; } - const float ev{std::asin(clampf(pos[1], -1.0f, 1.0f))}; + const float ev{std::asin(std::clamp(pos[1], -1.0f, 1.0f))}; const float az{std::atan2(pos[0], -pos[2])}; Device->mHrtf->getCoeffs(ev, az, Distance*NfcScale, 0.0f, voice->mChans[c].mDryParams.Hrtf.Target.Coeffs, voice->mChans[c].mDryParams.Hrtf.Target.Delay); - voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base; + voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base * pangain; const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base * pangain, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1156,7 +1250,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con * where it can be 0 or full (non-mono sources are always full * spread here). */ - const float spread{Spread * (voice->mFmtChannels == FmtMono)}; + const float spread{Spread * float(voice->mFmtChannels == FmtMono)}; /* Local sources on HRTF play with each channel panned to its * relative location around the listener, providing "virtual @@ -1167,6 +1261,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con /* Skip LFE */ if(chans[c].channel == LFE) continue; + const float pangain{SelectChannelGain(chans[c].channel)}; /* Get the HRIR coefficients and delays for this channel * position. @@ -1177,7 +1272,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con Device->mHrtf->getCoeffs(ev, az, std::numeric_limits::infinity(), spread, voice->mChans[c].mDryParams.Hrtf.Target.Coeffs, voice->mChans[c].mDryParams.Hrtf.Target.Delay); - voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base; + voice->mChans[c].mDryParams.Hrtf.Target.Gain = DryGain.Base * pangain; /* Normal panning for auxiliary sends. */ const auto coeffs = CalcDirectionCoeffs(chans[c].pos, spread); @@ -1185,7 +1280,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base * pangain, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1205,7 +1300,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con /* Clamp the distance for really close sources, to prevent * excessive bass. */ - const float mdist{maxf(Distance*NfcScale, Device->AvgSpeakerDist/4.0f)}; + const float mdist{std::max(Distance*NfcScale, Device->AvgSpeakerDist/4.0f)}; const float w0{SpeedOfSoundMetersPerSec / (mdist * Frequency)}; /* Adjust NFC filters. */ @@ -1226,63 +1321,60 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con }; const auto coeffs = calc_coeffs(Device->mRenderMode); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base, voice->mChans[0].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base, voice->mChans[0].mWetParams[i].Gains.Target); } } - else + else for(size_t c{0};c < num_channels;c++) { - using namespace al::numbers; + const auto pangain = SelectChannelGain(chans[c].channel); - for(size_t c{0};c < num_channels;c++) + /* Special-case LFE */ + if(chans[c].channel == LFE) { - /* Special-case LFE */ - if(chans[c].channel == LFE) + if(Device->Dry.Buffer.data() == Device->RealOut.Buffer.data()) { - if(Device->Dry.Buffer.data() == Device->RealOut.Buffer.data()) - { - const uint idx{Device->channelIdxByName(chans[c].channel)}; - if(idx != InvalidChannelIndex) - voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base; - } - continue; + const auto idx = uint{Device->channelIdxByName(chans[c].channel)}; + if(idx != InvalidChannelIndex) + voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base * pangain; } + continue; + } - /* Warp the channel position toward the source position as - * the spread decreases. With no spread, all channels are - * at the source position, at full spread (pi*2), each - * channel position is left unchanged. - */ - const float a{1.0f - (inv_pi_v/2.0f)*Spread}; - std::array pos{ - lerpf(chans[c].pos[0], xpos, a), - lerpf(chans[c].pos[1], ypos, a), - lerpf(chans[c].pos[2], zpos, a)}; - const float len{std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2])}; - if(len < 1.0f) - { - pos[0] /= len; - pos[1] /= len; - pos[2] /= len; - } + /* Warp the channel position toward the source position as the + * spread decreases. With no spread, all channels are at the + * source position, at full spread (pi*2), each channel + * position is left unchanged. + */ + const auto a = 1.0f - (al::numbers::inv_pi_v/2.0f)*Spread; + auto pos = std::array{ + lerpf(chans[c].pos[0], xpos, a), + lerpf(chans[c].pos[1], ypos, a), + lerpf(chans[c].pos[2], zpos, a)}; + const auto len = std::sqrt(pos[0]*pos[0] + pos[1]*pos[1] + pos[2]*pos[2]); + if(len < 1.0f) + { + pos[0] /= len; + pos[1] /= len; + pos[2] /= len; + } - if(Device->mRenderMode == RenderMode::Pairwise) - pos = ScaleAzimuthFront3(pos); - const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); + if(Device->mRenderMode == RenderMode::Pairwise) + pos = ScaleAzimuthFront3(pos); + const auto coeffs = CalcDirectionCoeffs(pos, 0.0f); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, - voice->mChans[c].mDryParams.Gains.Target); - for(uint i{0};i < NumSends;i++) - { - if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, - voice->mChans[c].mWetParams[i].Gains.Target); - } + ComputePanGains(&Device->Dry, coeffs, DryGain.Base * pangain, + voice->mChans[c].mDryParams.Gains.Target); + for(uint i{0};i < NumSends;i++) + { + if(const EffectSlot *Slot{SendSlots[i]}) + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base * pangain, + voice->mChans[c].mWetParams[i].Gains.Target); } } } @@ -1304,9 +1396,11 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con * where it can be 0 or full (non-mono sources are always full * spread here). */ - const float spread{Spread * (voice->mFmtChannels == FmtMono)}; + const float spread{Spread * float(voice->mFmtChannels == FmtMono)}; for(size_t c{0};c < num_channels;c++) { + const float pangain{SelectChannelGain(chans[c].channel)}; + /* Special-case LFE */ if(chans[c].channel == LFE) { @@ -1314,7 +1408,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con { const uint idx{Device->channelIdxByName(chans[c].channel)}; if(idx != InvalidChannelIndex) - voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base; + voice->mChans[c].mDryParams.Gains.Target[idx] = DryGain.Base * pangain; } continue; } @@ -1322,12 +1416,12 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con const auto coeffs = CalcDirectionCoeffs((Device->mRenderMode==RenderMode::Pairwise) ? ScaleAzimuthFront3(chans[c].pos) : chans[c].pos, spread); - ComputePanGains(&Device->Dry, coeffs.data(), DryGain.Base, + ComputePanGains(&Device->Dry, coeffs, DryGain.Base * pangain, voice->mChans[c].mDryParams.Gains.Target); for(uint i{0};i < NumSends;i++) { if(const EffectSlot *Slot{SendSlots[i]}) - ComputePanGains(&Slot->Wet, coeffs.data(), WetGain[i].Base, + ComputePanGains(&Slot->Wet, coeffs, WetGain[i].Base * pangain, voice->mChans[c].mWetParams[i].Gains.Target); } } @@ -1376,7 +1470,7 @@ void CalcPanningAndFilters(Voice *voice, const float xpos, const float ypos, con void CalcNonAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBase *context) { DeviceBase *Device{context->mDevice}; - EffectSlot *SendSlots[MAX_SENDS]; + std::array SendSlots{}; voice->mDirect.Buffer = Device->Dry.Buffer; for(uint i{0};i < Device->NumAuxSends;i++) @@ -1393,23 +1487,24 @@ void CalcNonAttnSourceParams(Voice *voice, const VoiceProps *props, const Contex /* Calculate the stepping value */ const auto Pitch = static_cast(voice->mFrequency) / - static_cast(Device->Frequency) * props->Pitch; + static_cast(Device->mSampleRate) * props->Pitch; if(Pitch > float{MaxPitch}) voice->mStep = MaxPitch<mStep = maxu(fastf2u(Pitch * MixerFracOne), 1); + voice->mStep = std::max(fastf2u(Pitch * MixerFracOne), 1u); voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState); /* Calculate gains */ - GainTriplet DryGain; - DryGain.Base = minf(clampf(props->Gain, props->MinGain, props->MaxGain) * props->Direct.Gain * - context->mParams.Gain, GainMixMax); + GainTriplet DryGain{}; + DryGain.Base = std::min(std::clamp(props->Gain, props->MinGain, props->MaxGain) * + props->Direct.Gain * context->mParams.Gain, GainMixMax); DryGain.HF = props->Direct.GainHF; DryGain.LF = props->Direct.GainLF; - GainTriplet WetGain[MAX_SENDS]; + + std::array WetGain{}; for(uint i{0};i < Device->NumAuxSends;i++) { - WetGain[i].Base = minf(clampf(props->Gain, props->MinGain, props->MaxGain) * + WetGain[i].Base = std::min(std::clamp(props->Gain, props->MinGain, props->MaxGain) * props->Send[i].Gain * context->mParams.Gain, GainMixMax); WetGain[i].HF = props->Send[i].GainHF; WetGain[i].LF = props->Send[i].GainLF; @@ -1426,25 +1521,26 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBa /* Set mixing buffers and get send parameters. */ voice->mDirect.Buffer = Device->Dry.Buffer; - EffectSlot *SendSlots[MAX_SENDS]; - uint UseDryAttnForRoom{0}; + std::array SendSlots{}; + std::array RoomRolloff{}; for(uint i{0};i < NumSends;i++) { SendSlots[i] = props->Send[i].Slot; if(!SendSlots[i] || SendSlots[i]->EffectType == EffectSlotType::None) + { SendSlots[i] = nullptr; - else if(!SendSlots[i]->AuxSendAuto) + voice->mSend[i].Buffer = {}; + } + else { - /* If the slot's auxiliary send auto is off, the data sent to the - * effect slot is the same as the dry path, sans filter effects. + /* NOTE: Contrary to the EFX docs, the effect's room rolloff factor + * applies to the selected distance model along with the source's + * room rolloff factor, not necessarily the inverse distance model. */ - UseDryAttnForRoom |= 1u<RoomRolloffFactor + SendSlots[i]->RoomRolloff; - if(!SendSlots[i]) - voice->mSend[i].Buffer = {}; - else voice->mSend[i].Buffer = SendSlots[i]->Wet.Buffer; + } } /* Transform source to listener space (convert to head relative) */ @@ -1471,62 +1567,77 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBa /* Calculate distance attenuation */ float ClampedDist{Distance}; float DryGainBase{props->Gain}; - float WetGainBase{props->Gain}; + std::array WetGainBase{}; + WetGainBase.fill(props->Gain); + float DryAttnBase{1.0f}; switch(context->mParams.SourceDistanceModel ? props->mDistanceModel : context->mParams.mDistanceModel) { - case DistanceModel::InverseClamped: - if(props->MaxDistance < props->RefDistance) break; - ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance); - /*fall-through*/ - case DistanceModel::Inverse: - if(props->RefDistance > 0.0f) + case DistanceModel::InverseClamped: + if(props->MaxDistance < props->RefDistance) break; + ClampedDist = std::clamp(ClampedDist, props->RefDistance, props->MaxDistance); + /*fall-through*/ + case DistanceModel::Inverse: + if(props->RefDistance > 0.0f) + { + float dist{lerpf(props->RefDistance, ClampedDist, props->RolloffFactor)}; + if(dist > 0.0f) { - float dist{lerpf(props->RefDistance, ClampedDist, props->RolloffFactor)}; - if(dist > 0.0f) DryGainBase *= props->RefDistance / dist; - - dist = lerpf(props->RefDistance, ClampedDist, props->RoomRolloffFactor); - if(dist > 0.0f) WetGainBase *= props->RefDistance / dist; + DryAttnBase = props->RefDistance / dist; + DryGainBase *= DryAttnBase; } - break; - - case DistanceModel::LinearClamped: - if(props->MaxDistance < props->RefDistance) break; - ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance); - /*fall-through*/ - case DistanceModel::Linear: - if(props->MaxDistance != props->RefDistance) - { - float attn{(ClampedDist-props->RefDistance) / - (props->MaxDistance-props->RefDistance) * props->RolloffFactor}; - DryGainBase *= maxf(1.0f - attn, 0.0f); - attn = (ClampedDist-props->RefDistance) / - (props->MaxDistance-props->RefDistance) * props->RoomRolloffFactor; - WetGainBase *= maxf(1.0f - attn, 0.0f); + for(size_t i{0};i < NumSends;++i) + { + dist = lerpf(props->RefDistance, ClampedDist, RoomRolloff[i]); + if(dist > 0.0f) WetGainBase[i] *= props->RefDistance / dist; } - break; - - case DistanceModel::ExponentClamped: - if(props->MaxDistance < props->RefDistance) break; - ClampedDist = clampf(ClampedDist, props->RefDistance, props->MaxDistance); - /*fall-through*/ - case DistanceModel::Exponent: - if(ClampedDist > 0.0f && props->RefDistance > 0.0f) + } + break; + + case DistanceModel::LinearClamped: + if(props->MaxDistance < props->RefDistance) break; + ClampedDist = std::clamp(ClampedDist, props->RefDistance, props->MaxDistance); + /*fall-through*/ + case DistanceModel::Linear: + if(props->MaxDistance != props->RefDistance) + { + float attn{(ClampedDist-props->RefDistance) / + (props->MaxDistance-props->RefDistance) * props->RolloffFactor}; + DryAttnBase = std::max(1.0f - attn, 0.0f); + DryGainBase *= DryAttnBase; + + for(size_t i{0};i < NumSends;++i) { - const float dist_ratio{ClampedDist/props->RefDistance}; - DryGainBase *= std::pow(dist_ratio, -props->RolloffFactor); - WetGainBase *= std::pow(dist_ratio, -props->RoomRolloffFactor); + attn = (ClampedDist-props->RefDistance) / + (props->MaxDistance-props->RefDistance) * RoomRolloff[i]; + WetGainBase[i] *= std::max(1.0f - attn, 0.0f); } - break; + } + break; + + case DistanceModel::ExponentClamped: + if(props->MaxDistance < props->RefDistance) break; + ClampedDist = std::clamp(ClampedDist, props->RefDistance, props->MaxDistance); + /*fall-through*/ + case DistanceModel::Exponent: + if(ClampedDist > 0.0f && props->RefDistance > 0.0f) + { + const float dist_ratio{ClampedDist/props->RefDistance}; + DryAttnBase = std::pow(dist_ratio, -props->RolloffFactor); + DryGainBase *= DryAttnBase; + for(size_t i{0};i < NumSends;++i) + WetGainBase[i] *= std::pow(dist_ratio, -RoomRolloff[i]); + } + break; - case DistanceModel::Disable: - break; + case DistanceModel::Disable: + break; } /* Calculate directional soundcones */ - float ConeHF{1.0f}, WetConeHF{1.0f}; + float ConeHF{1.0f}, WetCone{1.0f}, WetConeHF{1.0f}; if(directional && props->InnerAngle < 360.0f) { static constexpr float Rad2Deg{static_cast(180.0 / al::numbers::pi)}; @@ -1536,52 +1647,62 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBa if(Angle >= props->OuterAngle) { ConeGain = props->OuterGain; - ConeHF = lerpf(1.0f, props->OuterGainHF, props->DryGainHFAuto); + if(props->DryGainHFAuto) + ConeHF = props->OuterGainHF; } else if(Angle >= props->InnerAngle) { const float scale{(Angle-props->InnerAngle) / (props->OuterAngle-props->InnerAngle)}; ConeGain = lerpf(1.0f, props->OuterGain, scale); - ConeHF = lerpf(1.0f, props->OuterGainHF, scale * props->DryGainHFAuto); + if(props->DryGainHFAuto) + ConeHF = lerpf(1.0f, props->OuterGainHF, scale); } DryGainBase *= ConeGain; - WetGainBase *= lerpf(1.0f, ConeGain, props->WetGainAuto); - - WetConeHF = lerpf(1.0f, ConeHF, props->WetGainHFAuto); + if(props->WetGainAuto) + WetCone = ConeGain; + if(props->WetGainHFAuto) + WetConeHF = ConeHF; } /* Apply gain and frequency filters */ - DryGainBase = clampf(DryGainBase, props->MinGain, props->MaxGain) * context->mParams.Gain; - WetGainBase = clampf(WetGainBase, props->MinGain, props->MaxGain) * context->mParams.Gain; - GainTriplet DryGain{}; - DryGain.Base = minf(DryGainBase * props->Direct.Gain, GainMixMax); + DryGainBase = std::clamp(DryGainBase, props->MinGain, props->MaxGain) * context->mParams.Gain; + DryGain.Base = std::min(DryGainBase * props->Direct.Gain, GainMixMax); DryGain.HF = ConeHF * props->Direct.GainHF; DryGain.LF = props->Direct.GainLF; - GainTriplet WetGain[MAX_SENDS]{}; + + std::array WetGain{}; for(uint i{0};i < NumSends;i++) { - /* If this effect slot's Auxiliary Send Auto is off, then use the dry - * path distance and cone attenuation, otherwise use the wet (room) - * path distance and cone attenuation. The send filter is used instead - * of the direct filter, regardless. - */ - const bool use_room{!(UseDryAttnForRoom&(1u<Send[i].Gain, GainMixMax); - WetGain[i].HF = (use_room ? WetConeHF : ConeHF) * props->Send[i].GainHF; + const auto gain = std::clamp(WetGainBase[i]*WetCone, props->MinGain, props->MaxGain) * + context->mParams.Gain; + WetGain[i].Base = std::min(gain * props->Send[i].Gain, GainMixMax); + WetGain[i].HF = WetConeHF * props->Send[i].GainHF; WetGain[i].LF = props->Send[i].GainLF; } /* Distance-based air absorption and initial send decay. */ if(Distance > props->RefDistance) LIKELY { - const float distance_base{(Distance-props->RefDistance) * props->RolloffFactor}; - const float distance_meters{distance_base * context->mParams.MetersPerUnit}; - const float dryabsorb{distance_meters * props->AirAbsorptionFactor}; - if(dryabsorb > std::numeric_limits::epsilon()) - DryGain.HF *= std::pow(context->mParams.AirAbsorptionGainHF, dryabsorb); + /* FIXME: In keeping with EAX, the base air absorption gain should be + * taken from the reverb property in the "primary fx slot" when it has + * a reverb effect and the environment flag set, and be applied to the + * direct path and all environment sends, rather than each path using + * the air absorption gain associated with the given slot's effect. At + * this point in the mixer, and even in EFX itself, there's no concept + * of a "primary fx slot" so it's unclear which effect slot should be + * checked. + * + * The HF reference is also intended to be handled the same way, but + * again, there's no concept of a "primary fx slot" here and no way to + * know which effect slot to look at for the reference frequency. + */ + const auto distance_units = float{(Distance-props->RefDistance) * props->RolloffFactor}; + const auto distance_meters = float{distance_units * context->mParams.MetersPerUnit}; + const auto absorb = float{distance_meters * props->AirAbsorptionFactor}; + if(absorb > std::numeric_limits::epsilon()) + DryGain.HF *= std::pow(context->mParams.AirAbsorptionGainHF, absorb); /* If the source's Auxiliary Send Filter Gain Auto is off, no extra * adjustment is applied to the send gains. @@ -1591,72 +1712,25 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBa if(!SendSlots[i] || !(SendSlots[i]->DecayTime > 0.0f)) continue; - auto calc_attenuation = [](float distance, float refdist, float rolloff) noexcept - { - const float dist{lerpf(refdist, distance, rolloff)}; - if(dist > refdist) return refdist / dist; - return 1.0f; - }; - - /* The reverb effect's room rolloff factor always applies to an - * inverse distance rolloff model. - */ - WetGain[i].Base *= calc_attenuation(Distance, props->RefDistance, - SendSlots[i]->RoomRolloff); - - if(distance_meters > std::numeric_limits::epsilon()) - WetGain[i].HF *= std::pow(SendSlots[i]->AirAbsorptionGainHF, distance_meters); - - /* If this effect slot's Auxiliary Send Auto is off, don't apply - * the automatic initial reverb decay (should the reverb's room - * rolloff still apply?). - */ - if(!SendSlots[i]->AuxSendAuto) - continue; - - GainTriplet DecayDistance; - /* Calculate the distances to where this effect's decay reaches - * -60dB. - */ - DecayDistance.Base = SendSlots[i]->DecayTime * SpeedOfSoundMetersPerSec; - DecayDistance.LF = DecayDistance.Base * SendSlots[i]->DecayLFRatio; - DecayDistance.HF = DecayDistance.Base * SendSlots[i]->DecayHFRatio; - if(SendSlots[i]->DecayHFLimit) - { - const float airAbsorption{SendSlots[i]->AirAbsorptionGainHF}; - if(airAbsorption < 1.0f) - { - /* Calculate the distance to where this effect's air - * absorption reaches -60dB, and limit the effect's HF - * decay distance (so it doesn't take any longer to decay - * than the air would allow). - */ - static constexpr float log10_decaygain{-3.0f/*std::log10(ReverbDecayGain)*/}; - const float absorb_dist{log10_decaygain / std::log10(airAbsorption)}; - DecayDistance.HF = minf(absorb_dist, DecayDistance.HF); - } - } + if(SendSlots[i]->AirAbsorptionGainHF < 1.0f + && absorb > std::numeric_limits::epsilon()) + WetGain[i].HF *= std::pow(SendSlots[i]->AirAbsorptionGainHF, absorb); - const float baseAttn = calc_attenuation(Distance, props->RefDistance, - props->RolloffFactor); + const float DecayDistance{SendSlots[i]->DecayTime * SpeedOfSoundMetersPerSec}; /* Apply a decay-time transformation to the wet path, based on the * source distance. The initial decay of the reverb effect is * calculated and applied to the wet path. + * + * FIXME: This is very likely not correct. It more likely should + * work by calculating a rolloff dynamically based on the reverb + * parameters (and source distance?) and add it to the room rolloff + * with the reverb and source rolloff parameters. */ - const float fact{distance_base / DecayDistance.Base}; + const float baseAttn{DryAttnBase}; + const float fact{distance_meters / DecayDistance}; const float gain{std::pow(ReverbDecayGain, fact)*(1.0f-baseAttn) + baseAttn}; WetGain[i].Base *= gain; - - if(gain > 0.0f) - { - const float hffact{distance_base / DecayDistance.HF}; - const float gainhf{std::pow(ReverbDecayGain, hffact)*(1.0f-baseAttn) + baseAttn}; - WetGain[i].HF *= minf(gainhf/gain, 1.0f); - const float lffact{distance_base / DecayDistance.LF}; - const float gainlf{std::pow(ReverbDecayGain, lffact)*(1.0f-baseAttn) + baseAttn}; - WetGain[i].LF *= minf(gainlf/gain, 1.0f); - } } } @@ -1699,11 +1773,11 @@ void CalcAttnSourceParams(Voice *voice, const VoiceProps *props, const ContextBa /* Adjust pitch based on the buffer and output frequencies, and calculate * fixed-point stepping value. */ - Pitch *= static_cast(voice->mFrequency) / static_cast(Device->Frequency); + Pitch *= static_cast(voice->mFrequency) / static_cast(Device->mSampleRate); if(Pitch > float{MaxPitch}) voice->mStep = MaxPitch<mStep = maxu(fastf2u(Pitch * MixerFracOne), 1); + voice->mStep = std::max(fastf2u(Pitch * MixerFracOne), 1u); voice->mResampler = PrepareResampler(props->mResampler, voice->mStep, &voice->mResampleState); float spread{0.0f}; @@ -1723,7 +1797,7 @@ void CalcSourceParams(Voice *voice, ContextBase *context, bool force) if(props) { - voice->mProps = *props; + voice->mProps = static_cast(*props); AtomicReplaceHead(context->mFreeVoiceProps, props); } @@ -1742,9 +1816,9 @@ void SendSourceStateEvent(ContextBase *context, uint id, VChangeState state) { RingBuffer *ring{context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); - if(evt_vec.first.len < 1) return; + if(evt_vec[0].len < 1) return; - auto &evt = InitAsyncEvent(evt_vec.first.buf); + auto &evt = InitAsyncEvent(evt_vec[0].buf); evt.mId = id; switch(state) { @@ -1863,8 +1937,8 @@ void ProcessVoiceChanges(ContextBase *ctx) ctx->mCurrentVoiceChange.store(cur, std::memory_order_release); } -void ProcessParamUpdates(ContextBase *ctx, const EffectSlotArray &slots, - const al::span voices) +void ProcessParamUpdates(ContextBase *ctx, const al::span slots, + const al::span sorted_slots, const al::span voices) { ProcessVoiceChanges(ctx); @@ -1872,9 +1946,9 @@ void ProcessParamUpdates(ContextBase *ctx, const EffectSlotArray &slots, if(!ctx->mHoldUpdates.load(std::memory_order_acquire)) LIKELY { bool force{CalcContextParams(ctx)}; - auto sorted_slots = const_cast(slots.data() + slots.size()); + auto sorted_slot_base = al::to_address(sorted_slots.begin()); for(EffectSlot *slot : slots) - force |= CalcEffectSlotParams(slot, sorted_slots, ctx); + force |= CalcEffectSlotParams(slot, sorted_slot_base, ctx); for(Voice *voice : voices) { @@ -1890,142 +1964,137 @@ void ProcessContexts(DeviceBase *device, const uint SamplesToDo) { ASSUME(SamplesToDo > 0); - const nanoseconds curtime{device->ClockBase + - nanoseconds{seconds{device->SamplesDone}}/device->Frequency}; + const auto curtime = device->getClockTime(); - for(ContextBase *ctx : *device->mContexts.load(std::memory_order_acquire)) + auto proc_context = [SamplesToDo,curtime](ContextBase *ctx) { - const EffectSlotArray &auxslots = *ctx->mActiveAuxSlots.load(std::memory_order_acquire); - const al::span voices{ctx->getVoicesSpanAcquired()}; + const auto auxslotspan = al::span{*ctx->mActiveAuxSlots.load(std::memory_order_acquire)}; + const auto auxslots = auxslotspan.first(auxslotspan.size()>>1); + const auto sorted_slots = auxslotspan.last(auxslotspan.size()>>1); + const auto voices = ctx->getVoicesSpanAcquired(); /* Process pending property updates for objects on the context. */ - ProcessParamUpdates(ctx, auxslots, voices); + ProcessParamUpdates(ctx, auxslots, sorted_slots, voices); /* Clear auxiliary effect slot mixing buffers. */ - for(EffectSlot *slot : auxslots) + auto clear_wetbuffers = [](EffectSlot *slot) { - for(auto &buffer : slot->Wet.Buffer) - buffer.fill(0.0f); - } + auto clear_buffer = [](const FloatBufferSpan buffer) + { std::fill(buffer.begin(), buffer.end(), 0.0f); }; + std::for_each(slot->Wet.Buffer.begin(), slot->Wet.Buffer.end(), clear_buffer); + }; + std::for_each(auxslots.begin(), auxslots.end(), clear_wetbuffers); /* Process voices that have a playing source. */ - for(Voice *voice : voices) + auto proc_voice = [ctx,curtime,SamplesToDo](Voice *voice) { const Voice::State vstate{voice->mPlayState.load(std::memory_order_acquire)}; if(vstate != Voice::Stopped && vstate != Voice::Pending) voice->mix(vstate, ctx, curtime, SamplesToDo); - } + }; + std::for_each(voices.begin(), voices.end(), proc_voice); /* Process effects. */ - if(const size_t num_slots{auxslots.size()}) + if(!auxslots.empty()) { - auto slots = auxslots.data(); - auto slots_end = slots + num_slots; - /* Sort the slots into extra storage, so that effect slots come - * before their effect slot target (or their targets' target). + * before their effect slot target (or their targets' target). Skip + * sorting if it has already been done. */ - const al::span sorted_slots{const_cast(slots_end), - num_slots}; - /* Skip sorting if it has already been done. */ if(!sorted_slots[0]) { - /* First, copy the slots to the sorted list, then partition the - * sorted list so that all slots without a target slot go to - * the end. + /* First, copy the slots to the sorted list and partition them, + * so that all slots without a target slot go to the end. */ - std::copy(slots, slots_end, sorted_slots.begin()); - auto split_point = std::partition(sorted_slots.begin(), sorted_slots.end(), - [](const EffectSlot *slot) noexcept -> bool - { return slot->Target != nullptr; }); + auto has_target = [](const EffectSlot *slot) noexcept -> bool + { return slot->Target != nullptr; }; + auto split_point = std::partition_copy(auxslots.rbegin(), auxslots.rend(), + sorted_slots.begin(), sorted_slots.rbegin(), has_target).first; /* There must be at least one slot without a slot target. */ assert(split_point != sorted_slots.end()); - /* Simple case: no more than 1 slot has a target slot. Either - * all slots go right to the output, or the remaining one must - * target an already-partitioned slot. + /* Starting from the back of the sorted list, continue + * partitioning the front of the list given each target until + * all targets are accounted for. This ensures all slots + * without a target go last, all slots directly targeting those + * last slots go second-to-last, all slots directly targeting + * those second-last slots go third-to-last, etc. */ - if(split_point - sorted_slots.begin() > 1) + auto next_target = sorted_slots.end(); + while(std::distance(sorted_slots.begin(), split_point) > 1) { - /* At least two slots target other slots. Starting from the - * back of the sorted list, continue partitioning the front - * of the list given each target until all targets are - * accounted for. This ensures all slots without a target - * go last, all slots directly targeting those last slots - * go second-to-last, all slots directly targeting those - * second-last slots go third-to-last, etc. + /* This shouldn't happen, but if there's unsorted slots + * left that don't target any sorted slots, they can't + * contribute to the output, so leave them. */ - auto next_target = sorted_slots.end(); - do { - /* This shouldn't happen, but if there's unsorted slots - * left that don't target any sorted slots, they can't - * contribute to the output, so leave them. - */ - if(next_target == split_point) UNLIKELY - break; - - --next_target; - split_point = std::partition(sorted_slots.begin(), split_point, - [next_target](const EffectSlot *slot) noexcept -> bool - { return slot->Target != *next_target; }); - } while(split_point - sorted_slots.begin() > 1); + if(next_target == split_point) UNLIKELY + break; + + --next_target; + auto not_next = [next_target](const EffectSlot *slot) noexcept -> bool + { return slot->Target != *next_target; }; + split_point = std::partition(sorted_slots.begin(), split_point, not_next); } } - for(const EffectSlot *slot : sorted_slots) + auto proc_slot = [SamplesToDo](const EffectSlot *slot) { EffectState *state{slot->mEffectState.get()}; state->process(SamplesToDo, slot->Wet.Buffer, state->mOutTarget); - } + }; + std::for_each(sorted_slots.begin(), sorted_slots.end(), proc_slot); } /* Signal the event handler if there are any events to read. */ - RingBuffer *ring{ctx->mAsyncEvents.get()}; - if(ring->readSpace() > 0) + if(RingBuffer *ring{ctx->mAsyncEvents.get()}; ring->readSpace() > 0) ctx->mEventSem.post(); - } + }; + const auto contexts = al::span{*device->mContexts.load(std::memory_order_acquire)}; + std::for_each(contexts.begin(), contexts.end(), proc_context); } void ApplyDistanceComp(const al::span Samples, const size_t SamplesToDo, - const DistanceComp::ChanData *distcomp) + const al::span chandata) { ASSUME(SamplesToDo > 0); + auto distcomp = chandata.begin(); for(auto &chanbuffer : Samples) { const float gain{distcomp->Gain}; - const size_t base{distcomp->Length}; - float *distbuf{al::assume_aligned<16>(distcomp->Buffer)}; + auto distbuf = al::span{al::assume_aligned<16>(distcomp->Buffer.data()), + distcomp->Buffer.size()}; ++distcomp; - if(base < 1) - continue; + const size_t base{distbuf.size()}; + if(base < 1) continue; - float *inout{al::assume_aligned<16>(chanbuffer.data())}; - auto inout_end = inout + SamplesToDo; + const auto inout = al::span{al::assume_aligned<16>(chanbuffer.data()), SamplesToDo}; if(SamplesToDo >= base) LIKELY { - auto delay_end = std::rotate(inout, inout_end - base, inout_end); - std::swap_ranges(inout, delay_end, distbuf); + auto delay_end = std::rotate(inout.begin(), inout.end()-ptrdiff_t(base), inout.end()); + std::swap_ranges(inout.begin(), delay_end, distbuf.begin()); } else { - auto delay_start = std::swap_ranges(inout, inout_end, distbuf); - std::rotate(distbuf, delay_start, distbuf + base); + auto delay_start = std::swap_ranges(inout.begin(), inout.end(), distbuf.begin()); + std::rotate(distbuf.begin(), delay_start, distbuf.begin()+ptrdiff_t(base)); } - std::transform(inout, inout_end, inout, [gain](float s) { return s * gain; }); + std::transform(inout.begin(), inout.end(), inout.begin(), + [gain](float s) { return s*gain; }); } } void ApplyDither(const al::span Samples, uint *dither_seed, const float quant_scale, const size_t SamplesToDo) { + static constexpr double invRNGRange{1.0 / std::numeric_limits::max()}; ASSUME(SamplesToDo > 0); /* Dithering. Generate whitenoise (uniform distribution of random values * between -1 and +1) and add it to the sample values, after scaling up to - * the desired quantization depth amd before rounding. + * the desired quantization depth and before rounding. */ const float invscale{1.0f / quant_scale}; uint seed{*dither_seed}; @@ -2034,7 +2103,7 @@ void ApplyDither(const al::span Samples, uint *dither_seed, float val{sample * quant_scale}; uint rng0{dither_rng(&seed)}; uint rng1{dither_rng(&seed)}; - val += static_cast(rng0*(1.0/UINT_MAX) - rng1*(1.0/UINT_MAX)); + val += static_cast(rng0*invRNGRange - rng1*invRNGRange); return fast_roundf(val) * invscale; }; for(FloatBufferLine &inout : Samples) @@ -2058,12 +2127,12 @@ template<> inline int32_t SampleConv(float val) noexcept * When scaling and clamping for a signed 32-bit integer, these following * values are the best a float can give. */ - return fastf2i(clampf(val*2147483648.0f, -2147483648.0f, 2147483520.0f)); + return fastf2i(std::clamp(val*2147483648.0f, -2147483648.0f, 2147483520.0f)); } template<> inline int16_t SampleConv(float val) noexcept -{ return static_cast(fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f))); } +{ return static_cast(fastf2i(std::clamp(val*32768.0f, -32768.0f, 32767.0f))); } template<> inline int8_t SampleConv(float val) noexcept -{ return static_cast(fastf2i(clampf(val*128.0f, -128.0f, 127.0f))); } +{ return static_cast(fastf2i(std::clamp(val*128.0f, -128.0f, 127.0f))); } /* Define unsigned output variations. */ template<> inline uint32_t SampleConv(float val) noexcept @@ -2073,34 +2142,54 @@ template<> inline uint16_t SampleConv(float val) noexcept template<> inline uint8_t SampleConv(float val) noexcept { return static_cast(SampleConv(val) + 128); } -template +template void Write(const al::span InBuffer, void *OutBuffer, const size_t Offset, const size_t SamplesToDo, const size_t FrameStep) { ASSUME(FrameStep > 0); ASSUME(SamplesToDo > 0); - DevFmtType_t *outbase{static_cast*>(OutBuffer) + Offset*FrameStep}; - size_t c{0}; - for(const FloatBufferLine &inbuf : InBuffer) + /* Some Clang versions don't like calling subspan on an rvalue here. */ + const auto output_ = al::span{static_cast(OutBuffer), (Offset+SamplesToDo)*FrameStep}; + const auto output = output_.subspan(Offset*FrameStep); + + /* If there's extra channels in the interleaved output buffer to skip, + * clear the whole output buffer. This is simpler to ensure the extra + * channels are silent than trying to clear just the extra channels. + */ + if(FrameStep > InBuffer.size()) + std::fill(output.begin(), output.end(), SampleConv(0.0f)); + + auto outbase = output.begin(); + for(const auto &srcbuf : InBuffer) { - DevFmtType_t *out{outbase++}; - auto conv_sample = [FrameStep,&out](const float s) noexcept -> void + const auto src = al::span{srcbuf}.first(SamplesToDo); + auto out = outbase++; + + *out = SampleConv(src.front()); + std::for_each(src.begin()+1, src.end(), [FrameStep,&out](const float s) noexcept { - *out = SampleConv>(s); - out += FrameStep; - }; - std::for_each(inbuf.begin(), inbuf.begin()+SamplesToDo, conv_sample); - ++c; + out += ptrdiff_t(FrameStep); + *out = SampleConv(s); + }); } - if(const size_t extra{FrameStep - c}) +} + +template +void Write(const al::span InBuffer, al::span OutBuffers, + const size_t Offset, const size_t SamplesToDo) +{ + ASSUME(SamplesToDo > 0); + + auto srcbuf = InBuffer.cbegin(); + for(auto *dstbuf : OutBuffers) { - const auto silence = SampleConv>(0.0f); - for(size_t i{0};i < SamplesToDo;++i) - { - std::fill_n(outbase, extra, silence); - outbase += FrameStep; - } + const auto src = al::span{*srcbuf}.first(SamplesToDo); + /* Some Clang versions don't like calling subspan on an rvalue here. */ + const auto dst_ = al::span{static_cast(dstbuf), Offset+SamplesToDo}; + const auto dst = dst_.subspan(Offset); + std::transform(src.begin(), src.end(), dst.begin(), SampleConv); + ++srcbuf; } } @@ -2108,28 +2197,28 @@ void Write(const al::span InBuffer, void *OutBuffer, cons uint DeviceBase::renderSamples(const uint numSamples) { - const uint samplesToDo{minu(numSamples, BufferLineSize)}; + const uint samplesToDo{std::min(numSamples, uint{BufferLineSize})}; /* Clear main mixing buffers. */ for(FloatBufferLine &buffer : MixBuffer) buffer.fill(0.0f); - /* Increment the mix count at the start (lsb should now be 1). */ - IncrementRef(MixCount); - - /* Process and mix each context's sources and effects. */ - ProcessContexts(this, samplesToDo); + { + const auto mixLock = getWriteMixLock(); - /* Increment the clock time. Every second's worth of samples is converted - * and added to clock base so that large sample counts don't overflow - * during conversion. This also guarantees a stable conversion. - */ - SamplesDone += samplesToDo; - ClockBase += std::chrono::seconds{SamplesDone / Frequency}; - SamplesDone %= Frequency; + /* Process and mix each context's sources and effects. */ + ProcessContexts(this, samplesToDo); - /* Increment the mix count at the end (lsb should now be 0). */ - IncrementRef(MixCount); + /* Every second's worth of samples is converted and added to clock base + * so that large sample counts don't overflow during conversion. This + * also guarantees a stable conversion. + */ + auto samplesDone = mSamplesDone.load(std::memory_order_relaxed) + samplesToDo; + auto clockBaseSec = mClockBaseSec.load(std::memory_order_relaxed) + + seconds32{samplesDone/mSampleRate}; + mSamplesDone.store(samplesDone%mSampleRate, std::memory_order_relaxed); + mClockBaseSec.store(clockBaseSec, std::memory_order_relaxed); + } /* Apply any needed post-process for finalizing the Dry mix to the RealOut * (Ambisonic decode, UHJ encode, etc). @@ -2137,11 +2226,11 @@ uint DeviceBase::renderSamples(const uint numSamples) postProcess(samplesToDo); /* Apply compression, limiting sample amplitude if needed or desired. */ - if(Limiter) Limiter->process(samplesToDo, RealOut.Buffer.data()); + if(Limiter) Limiter->process(samplesToDo, RealOut.Buffer); /* Apply delays and attenuation for mismatched speaker distances. */ if(ChannelDelays) - ApplyDistanceComp(RealOut.Buffer, samplesToDo, ChannelDelays->mChannels.data()); + ApplyDistanceComp(RealOut.Buffer, samplesToDo, ChannelDelays->mChannels); /* Apply dithering. The compressor should have left enough headroom for the * dither noise to not saturate. @@ -2152,7 +2241,7 @@ uint DeviceBase::renderSamples(const uint numSamples) return samplesToDo; } -void DeviceBase::renderSamples(const al::span outBuffers, const uint numSamples) +void DeviceBase::renderSamples(const al::span outBuffers, const uint numSamples) { FPUCtl mixer_mode{}; uint total{0}; @@ -2160,12 +2249,19 @@ void DeviceBase::renderSamples(const al::span outBuffers, const uint num { const uint samplesToDo{renderSamples(todo)}; - auto *srcbuf = RealOut.Buffer.data(); - for(auto *dstbuf : outBuffers) + switch(FmtType) { - std::copy_n(srcbuf->data(), samplesToDo, dstbuf + total); - ++srcbuf; +#define HANDLE_WRITE(T) case T: \ + Write>(RealOut.Buffer, outBuffers, total, samplesToDo); break; + HANDLE_WRITE(DevFmtByte) + HANDLE_WRITE(DevFmtUByte) + HANDLE_WRITE(DevFmtShort) + HANDLE_WRITE(DevFmtUShort) + HANDLE_WRITE(DevFmtInt) + HANDLE_WRITE(DevFmtUInt) + HANDLE_WRITE(DevFmtFloat) } +#undef HANDLE_WRITE total += samplesToDo; } @@ -2187,7 +2283,7 @@ void DeviceBase::renderSamples(void *outBuffer, const uint numSamples, const siz switch(FmtType) { #define HANDLE_WRITE(T) case T: \ - Write(RealOut.Buffer, outBuffer, total, samplesToDo, frameStep); break; + Write>(RealOut.Buffer, outBuffer, total, samplesToDo, frameStep); break; HANDLE_WRITE(DevFmtByte) HANDLE_WRITE(DevFmtUByte) HANDLE_WRITE(DevFmtShort) @@ -2203,26 +2299,20 @@ void DeviceBase::renderSamples(void *outBuffer, const uint numSamples, const siz } } -void DeviceBase::handleDisconnect(const char *msg, ...) +void DeviceBase::doDisconnect(std::string msg) { - IncrementRef(MixCount); + const auto mixLock = getWriteMixLock(); + if(Connected.exchange(false, std::memory_order_acq_rel)) { AsyncEvent evt{std::in_place_type}; auto &disconnect = std::get(evt); - - va_list args; - va_start(args, msg); - int msglen{vsnprintf(disconnect.msg, sizeof(disconnect.msg), msg, args)}; - va_end(args); - - if(msglen < 0 || static_cast(msglen) >= sizeof(disconnect.msg)) - disconnect.msg[sizeof(disconnect.msg)-1] = 0; + disconnect.msg = std::move(msg); for(ContextBase *ctx : *mContexts.load()) { RingBuffer *ring{ctx->mAsyncEvents.get()}; - auto evt_data = ring->getWriteVector().first; + auto evt_data = ring->getWriteVector()[0]; if(evt_data.len > 0) { al::construct_at(reinterpret_cast(evt_data.buf), evt); @@ -2230,7 +2320,7 @@ void DeviceBase::handleDisconnect(const char *msg, ...) ctx->mEventSem.post(); } - if(!ctx->mStopVoicesOnDisconnect) + if(!ctx->mStopVoicesOnDisconnect.load()) { ProcessVoiceChanges(ctx); continue; @@ -2247,5 +2337,4 @@ void DeviceBase::handleDisconnect(const char *msg, ...) std::for_each(voicelist.begin(), voicelist.end(), stop_voice); } } - IncrementRef(MixCount); } diff --git a/3rdparty/openal/alc/alu.h b/3rdparty/openal/alc/alu.h index 33453487b1f4..6da8d9174064 100644 --- a/3rdparty/openal/alc/alu.h +++ b/3rdparty/openal/alc/alu.h @@ -2,20 +2,23 @@ #define ALU_H #include +#include #include -#include struct ALCcontext; struct ALCdevice; struct EffectSlot; -enum class StereoEncoding : uint8_t; +enum class StereoEncoding : std::uint8_t; +namespace al { +struct Device; +} // namespace al constexpr float GainMixMax{1000.0f}; /* +60dB */ -enum CompatFlags : uint8_t { +enum CompatFlags : std::uint8_t { ReverseX, ReverseY, ReverseZ, @@ -31,7 +34,7 @@ void aluInit(CompatFlagBitset flags, const float nfcscale); * Set up the appropriate panning method and mixing method given the device * properties. */ -void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional stereomode); +void aluInitRenderer(al::Device *device, int hrtf_id, std::optional stereomode); void aluInitEffectPanning(EffectSlot *slot, ALCcontext *context); diff --git a/3rdparty/openal/alc/backends/alsa.cpp b/3rdparty/openal/alc/backends/alsa.cpp index 0d9ff30dff63..a241be7ab413 100644 --- a/3rdparty/openal/alc/backends/alsa.cpp +++ b/3rdparty/openal/alc/backends/alsa.cpp @@ -29,15 +29,14 @@ #include #include #include -#include #include #include #include +#include #include #include #include -#include "albit.h" #include "alc/alconfig.h" #include "almalloc.h" #include "alnumeric.h" @@ -46,6 +45,7 @@ #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" +#include "fmt/core.h" #include "ringbuffer.h" #include @@ -53,10 +53,12 @@ namespace { -constexpr char alsaDevice[] = "ALSA Default"; +using namespace std::string_view_literals; +[[nodiscard]] constexpr auto GetDefaultName() noexcept { return "ALSA Default"sv; } -#ifdef HAVE_DYNLOAD + +#if HAVE_DYNLOAD #define ALSA_FUNCS(MAGIC) \ MAGIC(snd_strerror); \ MAGIC(snd_pcm_open); \ @@ -252,55 +254,93 @@ std::vector PlaybackDevices; std::vector CaptureDevices; -const char *prefix_name(snd_pcm_stream_t stream) +std::string_view prefix_name(snd_pcm_stream_t stream) noexcept { - assert(stream == SND_PCM_STREAM_PLAYBACK || stream == SND_PCM_STREAM_CAPTURE); - return (stream==SND_PCM_STREAM_PLAYBACK) ? "device-prefix" : "capture-prefix"; + if(stream == SND_PCM_STREAM_PLAYBACK) + return "device-prefix"sv; + return "capture-prefix"sv; } +struct SndCtlCardInfo { + snd_ctl_card_info_t *mInfo{}; + + SndCtlCardInfo() { snd_ctl_card_info_malloc(&mInfo); } + ~SndCtlCardInfo() { if(mInfo) snd_ctl_card_info_free(mInfo); } + SndCtlCardInfo(const SndCtlCardInfo&) = delete; + SndCtlCardInfo& operator=(const SndCtlCardInfo&) = delete; + + [[nodiscard]] + operator snd_ctl_card_info_t*() const noexcept { return mInfo; } /* NOLINT(google-explicit-constructor) */ +}; + +struct SndPcmInfo { + snd_pcm_info_t *mInfo{}; + + SndPcmInfo() { snd_pcm_info_malloc(&mInfo); } + ~SndPcmInfo() { if(mInfo) snd_pcm_info_free(mInfo); } + SndPcmInfo(const SndPcmInfo&) = delete; + SndPcmInfo& operator=(const SndPcmInfo&) = delete; + + [[nodiscard]] + operator snd_pcm_info_t*() const noexcept { return mInfo; } /* NOLINT(google-explicit-constructor) */ +}; + +struct SndCtl { + snd_ctl_t *mHandle{}; + + SndCtl() = default; + ~SndCtl() { if(mHandle) snd_ctl_close(mHandle); } + SndCtl(const SndCtl&) = delete; + SndCtl& operator=(const SndCtl&) = delete; + + [[nodiscard]] + auto open(const char *name, int mode) { return snd_ctl_open(&mHandle, name, mode); } + + [[nodiscard]] + operator snd_ctl_t*() const noexcept { return mHandle; } /* NOLINT(google-explicit-constructor) */ +}; + + std::vector probe_devices(snd_pcm_stream_t stream) { std::vector devlist; - snd_ctl_card_info_t *info; - snd_ctl_card_info_malloc(&info); - snd_pcm_info_t *pcminfo; - snd_pcm_info_malloc(&pcminfo); + SndCtlCardInfo info; + SndPcmInfo pcminfo; - auto defname = ConfigValueStr(nullptr, "alsa", - (stream == SND_PCM_STREAM_PLAYBACK) ? "device" : "capture"); - devlist.emplace_back(alsaDevice, defname ? defname->c_str() : "default"); + auto defname = ConfigValueStr({}, "alsa"sv, + (stream == SND_PCM_STREAM_PLAYBACK) ? "device"sv : "capture"sv); + devlist.emplace_back(GetDefaultName(), defname ? std::string_view{*defname} : "default"sv); - if(auto customdevs = ConfigValueStr(nullptr, "alsa", - (stream == SND_PCM_STREAM_PLAYBACK) ? "custom-devices" : "custom-captures")) + if(auto customdevs = ConfigValueStr({}, "alsa"sv, + (stream == SND_PCM_STREAM_PLAYBACK) ? "custom-devices"sv : "custom-captures"sv)) { - size_t nextpos{customdevs->find_first_not_of(';')}; - size_t curpos; - while((curpos=nextpos) < customdevs->length()) + size_t curpos{customdevs->find_first_not_of(';')}; + while(curpos < customdevs->length()) { - nextpos = customdevs->find_first_of(';', curpos+1); - - size_t seppos{customdevs->find_first_of('=', curpos)}; + size_t nextpos{customdevs->find(';', curpos+1)}; + const size_t seppos{customdevs->find('=', curpos)}; if(seppos == curpos || seppos >= nextpos) { - std::string spec{customdevs->substr(curpos, nextpos-curpos)}; - ERR("Invalid ALSA device specification \"%s\"\n", spec.c_str()); + const auto spec = std::string_view{*customdevs}.substr(curpos, nextpos-curpos); + ERR("Invalid ALSA device specification \"{}\"", spec); } else { - devlist.emplace_back(customdevs->substr(curpos, seppos-curpos), - customdevs->substr(seppos+1, nextpos-seppos-1)); - const auto &entry = devlist.back(); - TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str()); + const std::string_view strview{*customdevs}; + const auto &entry = devlist.emplace_back(strview.substr(curpos, seppos-curpos), + strview.substr(seppos+1, nextpos-seppos-1)); + TRACE("Got device \"{}\", \"{}\"", entry.name, entry.device_name); } if(nextpos < customdevs->length()) nextpos = customdevs->find_first_not_of(';', nextpos+1); + curpos = nextpos; } } - const std::string main_prefix{ - ConfigValueStr(nullptr, "alsa", prefix_name(stream)).value_or("plughw:")}; + const std::string main_prefix{ConfigValueStr({}, "alsa"sv, prefix_name(stream)) + .value_or("plughw:")}; int card{-1}; int err{snd_card_next(&card)}; @@ -308,16 +348,17 @@ std::vector probe_devices(snd_pcm_stream_t stream) { std::string name{"hw:" + std::to_string(card)}; - snd_ctl_t *handle; - if((err=snd_ctl_open(&handle, name.c_str(), 0)) < 0) + SndCtl handle; + err = handle.open(name.c_str(), 0); + if(err < 0) { - ERR("control open (hw:%d): %s\n", card, snd_strerror(err)); + ERR("control open (hw:{}): {}", card, snd_strerror(err)); continue; } - if((err=snd_ctl_card_info(handle, info)) < 0) + err = snd_ctl_card_info(handle, info); + if(err < 0) { - ERR("control hardware info (hw:%d): %s\n", card, snd_strerror(err)); - snd_ctl_close(handle); + ERR("control hardware info (hw:{}): {}", card, snd_strerror(err)); continue; } @@ -326,63 +367,44 @@ std::vector probe_devices(snd_pcm_stream_t stream) name = prefix_name(stream); name += '-'; name += cardid; - const std::string card_prefix{ - ConfigValueStr(nullptr, "alsa", name.c_str()).value_or(main_prefix)}; + const std::string card_prefix{ConfigValueStr({}, "alsa"sv, name).value_or(main_prefix)}; int dev{-1}; while(true) { if(snd_ctl_pcm_next_device(handle, &dev) < 0) - ERR("snd_ctl_pcm_next_device failed\n"); + ERR("snd_ctl_pcm_next_device failed"); if(dev < 0) break; snd_pcm_info_set_device(pcminfo, static_cast(dev)); snd_pcm_info_set_subdevice(pcminfo, 0); snd_pcm_info_set_stream(pcminfo, stream); - if((err=snd_ctl_pcm_info(handle, pcminfo)) < 0) + err = snd_ctl_pcm_info(handle, pcminfo); + if(err < 0) { if(err != -ENOENT) - ERR("control digital audio info (hw:%d): %s\n", card, snd_strerror(err)); + ERR("control digital audio info (hw:{}): {}", card, snd_strerror(err)); continue; } /* "prefix-cardid-dev" */ - name = prefix_name(stream); - name += '-'; - name += cardid; - name += '-'; - name += std::to_string(dev); - const std::string device_prefix{ - ConfigValueStr(nullptr, "alsa", name.c_str()).value_or(card_prefix)}; + name = fmt::format("{}-{}-{}", prefix_name(stream), cardid, dev); + const auto device_prefix = std::string{ConfigValueStr({}, "alsa"sv, name) + .value_or(card_prefix)}; /* "CardName, PcmName (CARD=cardid,DEV=dev)" */ - name = cardname; - name += ", "; - name += snd_pcm_info_get_name(pcminfo); - name += " (CARD="; - name += cardid; - name += ",DEV="; - name += std::to_string(dev); - name += ')'; + name = fmt::format("{}, {} (CARD={},DEV={})", cardname, snd_pcm_info_get_name(pcminfo), + cardid, dev); /* "devprefixCARD=cardid,DEV=dev" */ - std::string device{device_prefix}; - device += "CARD="; - device += cardid; - device += ",DEV="; - device += std::to_string(dev); + auto device = fmt::format("{}CARD={},DEV={}", device_prefix, cardid, dev); - devlist.emplace_back(std::move(name), std::move(device)); - const auto &entry = devlist.back(); - TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str()); + const auto &entry = devlist.emplace_back(std::move(name), std::move(device)); + TRACE("Got device \"{}\", \"{}\"", entry.name, entry.device_name); } - snd_ctl_close(handle); } if(err < 0) - ERR("snd_card_next failed: %s\n", snd_strerror(err)); - - snd_pcm_info_free(pcminfo); - snd_ctl_card_info_free(info); + ERR("snd_card_next failed: {}", snd_strerror(err)); return devlist; } @@ -392,7 +414,6 @@ int verify_state(snd_pcm_t *handle) { snd_pcm_state_t state{snd_pcm_state(handle)}; - int err; switch(state) { case SND_PCM_STATE_OPEN: @@ -405,15 +426,27 @@ int verify_state(snd_pcm_t *handle) break; case SND_PCM_STATE_XRUN: - if((err=snd_pcm_recover(handle, -EPIPE, 1)) < 0) + if(int err{snd_pcm_recover(handle, -EPIPE, 1)}; err < 0) return err; break; case SND_PCM_STATE_SUSPENDED: - if((err=snd_pcm_recover(handle, -ESTRPIPE, 1)) < 0) + if(int err{snd_pcm_recover(handle, -ESTRPIPE, 1)}; err < 0) return err; break; + case SND_PCM_STATE_DISCONNECTED: return -ENODEV; + + /* ALSA headers have made this enum public, leaving us in a bind: use + * the enum despite being private and internal to the libasound, or + * ignore when an enum value isn't handled. We can't rely on it being + * declared either, since older headers don't have it and it could be + * removed in the future. We can't even really rely on its value, since + * being private/internal means it's subject to change, but this is the + * best we can do. + */ + case 1024 /*SND_PCM_STATE_PRIVATE1*/: + assert(state != 1024); } return state; @@ -421,7 +454,7 @@ int verify_state(snd_pcm_t *handle) struct AlsaPlayback final : public BackendBase { - AlsaPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit AlsaPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~AlsaPlayback() override; int mixerProc(); @@ -443,8 +476,6 @@ struct AlsaPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(AlsaPlayback) }; AlsaPlayback::~AlsaPlayback() @@ -458,31 +489,31 @@ AlsaPlayback::~AlsaPlayback() int AlsaPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); - const snd_pcm_uframes_t update_size{mDevice->UpdateSize}; - const snd_pcm_uframes_t buffer_size{mDevice->BufferSize}; + const snd_pcm_uframes_t update_size{mDevice->mUpdateSize}; + const snd_pcm_uframes_t buffer_size{mDevice->mBufferSize}; while(!mKillNow.load(std::memory_order_acquire)) { int state{verify_state(mPcmHandle)}; if(state < 0) { - ERR("Invalid state detected: %s\n", snd_strerror(state)); - mDevice->handleDisconnect("Bad state: %s", snd_strerror(state)); + ERR("Invalid state detected: {}", snd_strerror(state)); + mDevice->handleDisconnect("Bad state: {}", snd_strerror(state)); break; } snd_pcm_sframes_t avails{snd_pcm_avail_update(mPcmHandle)}; if(avails < 0) { - ERR("available update failed: %s\n", snd_strerror(static_cast(avails))); + ERR("available update failed: {}", snd_strerror(static_cast(avails))); continue; } snd_pcm_uframes_t avail{static_cast(avails)}; if(avail > buffer_size) { - WARN("available samples exceeds the buffer size\n"); + WARN("available samples exceeds the buffer size"); snd_pcm_reset(mPcmHandle); continue; } @@ -495,18 +526,18 @@ int AlsaPlayback::mixerProc() int err{snd_pcm_start(mPcmHandle)}; if(err < 0) { - ERR("start failed: %s\n", snd_strerror(err)); + ERR("start failed: {}", snd_strerror(err)); continue; } } if(snd_pcm_wait(mPcmHandle, 1000) == 0) - ERR("Wait timeout... buffer size too low?\n"); + ERR("Wait timeout... buffer size too low?"); continue; } avail -= avail%update_size; // it is possible that contiguous areas are smaller, thus we use a loop - std::lock_guard _{mMutex}; + std::lock_guard dlock{mMutex}; while(avail > 0) { snd_pcm_uframes_t frames{avail}; @@ -516,17 +547,18 @@ int AlsaPlayback::mixerProc() int err{snd_pcm_mmap_begin(mPcmHandle, &areas, &offset, &frames)}; if(err < 0) { - ERR("mmap begin error: %s\n", snd_strerror(err)); + ERR("mmap begin error: {}", snd_strerror(err)); break; } + /* NOLINTNEXTLINE(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ char *WritePtr{static_cast(areas->addr) + (offset * areas->step / 8)}; mDevice->renderSamples(WritePtr, static_cast(frames), mFrameStep); snd_pcm_sframes_t commitres{snd_pcm_mmap_commit(mPcmHandle, offset, frames)}; if(commitres < 0 || static_cast(commitres) != frames) { - ERR("mmap commit error: %s\n", + ERR("mmap commit error: {}", snd_strerror(commitres >= 0 ? -EPIPE : static_cast(commitres))); break; } @@ -541,30 +573,30 @@ int AlsaPlayback::mixerProc() int AlsaPlayback::mixerNoMMapProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); - const snd_pcm_uframes_t update_size{mDevice->UpdateSize}; - const snd_pcm_uframes_t buffer_size{mDevice->BufferSize}; + const snd_pcm_uframes_t update_size{mDevice->mUpdateSize}; + const snd_pcm_uframes_t buffer_size{mDevice->mBufferSize}; while(!mKillNow.load(std::memory_order_acquire)) { int state{verify_state(mPcmHandle)}; if(state < 0) { - ERR("Invalid state detected: %s\n", snd_strerror(state)); - mDevice->handleDisconnect("Bad state: %s", snd_strerror(state)); + ERR("Invalid state detected: {}", snd_strerror(state)); + mDevice->handleDisconnect("Bad state: {}", snd_strerror(state)); break; } snd_pcm_sframes_t avail{snd_pcm_avail_update(mPcmHandle)}; if(avail < 0) { - ERR("available update failed: %s\n", snd_strerror(static_cast(avail))); + ERR("available update failed: {}", snd_strerror(static_cast(avail))); continue; } if(static_cast(avail) > buffer_size) { - WARN("available samples exceeds the buffer size\n"); + WARN("available samples exceeds the buffer size"); snd_pcm_reset(mPcmHandle); continue; } @@ -576,22 +608,22 @@ int AlsaPlayback::mixerNoMMapProc() int err{snd_pcm_start(mPcmHandle)}; if(err < 0) { - ERR("start failed: %s\n", snd_strerror(err)); + ERR("start failed: {}", snd_strerror(err)); continue; } } if(snd_pcm_wait(mPcmHandle, 1000) == 0) - ERR("Wait timeout... buffer size too low?\n"); + ERR("Wait timeout... buffer size too low?"); continue; } - std::byte *WritePtr{mBuffer.data()}; + auto WritePtr = mBuffer.begin(); avail = snd_pcm_bytes_to_frames(mPcmHandle, static_cast(mBuffer.size())); - std::lock_guard _{mMutex}; - mDevice->renderSamples(WritePtr, static_cast(avail), mFrameStep); + std::lock_guard dlock{mMutex}; + mDevice->renderSamples(al::to_address(WritePtr), static_cast(avail), mFrameStep); while(avail > 0) { - snd_pcm_sframes_t ret{snd_pcm_writei(mPcmHandle, WritePtr, + snd_pcm_sframes_t ret{snd_pcm_writei(mPcmHandle, al::to_address(WritePtr), static_cast(avail))}; switch(ret) { @@ -638,22 +670,22 @@ void AlsaPlayback::open(std::string_view name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; driver = iter->device_name; } else { - name = alsaDevice; - if(auto driveropt = ConfigValueStr(nullptr, "alsa", "device")) + name = GetDefaultName(); + if(auto driveropt = ConfigValueStr({}, "alsa"sv, "device"sv)) driver = std::move(driveropt).value(); } - TRACE("Opening device \"%s\"\n", driver.c_str()); + TRACE("Opening device \"{}\"", driver); snd_pcm_t *pcmHandle{}; int err{snd_pcm_open(&pcmHandle, driver.c_str(), SND_PCM_STREAM_PLAYBACK, SND_PCM_NONBLOCK)}; if(err < 0) throw al::backend_exception{al::backend_error::NoDevice, - "Could not open ALSA device \"%s\"", driver.c_str()}; + "Could not open ALSA device \"{}\"", driver}; if(mPcmHandle) snd_pcm_close(mPcmHandle); mPcmHandle = pcmHandle; @@ -661,7 +693,7 @@ void AlsaPlayback::open(std::string_view name) /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); - mDevice->DeviceName = name; + mDeviceName = name; } bool AlsaPlayback::reset() @@ -692,16 +724,15 @@ bool AlsaPlayback::reset() break; } - bool allowmmap{!!GetConfigValueBool(mDevice->DeviceName.c_str(), "alsa", "mmap", true)}; - uint periodLen{static_cast(mDevice->UpdateSize * 1000000_u64 / mDevice->Frequency)}; - uint bufferLen{static_cast(mDevice->BufferSize * 1000000_u64 / mDevice->Frequency)}; - uint rate{mDevice->Frequency}; + bool allowmmap{GetConfigValueBool(mDevice->mDeviceName, "alsa"sv, "mmap"sv, true)}; + uint periodLen{static_cast(mDevice->mUpdateSize * 1000000_u64 / mDevice->mSampleRate)}; + uint bufferLen{static_cast(mDevice->mBufferSize * 1000000_u64 / mDevice->mSampleRate)}; + uint rate{mDevice->mSampleRate}; - int err{}; HwParamsPtr hp{CreateHwParams()}; #define CHECK(x) do { \ - if((err=(x)) < 0) \ - throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \ + if(int err{x}; err < 0) \ + throw al::backend_exception{al::backend_error::DeviceError, #x " failed: {}", \ snd_strerror(err)}; \ } while(0) CHECK(snd_pcm_hw_params_any(mPcmHandle, hp.get())); @@ -715,17 +746,18 @@ bool AlsaPlayback::reset() /* test and set format (implicitly sets sample bits) */ if(snd_pcm_hw_params_test_format(mPcmHandle, hp.get(), format) < 0) { - static const struct { + struct FormatMap { snd_pcm_format_t format; DevFmtType fmttype; - } formatlist[] = { - { SND_PCM_FORMAT_FLOAT, DevFmtFloat }, - { SND_PCM_FORMAT_S32, DevFmtInt }, - { SND_PCM_FORMAT_U32, DevFmtUInt }, - { SND_PCM_FORMAT_S16, DevFmtShort }, - { SND_PCM_FORMAT_U16, DevFmtUShort }, - { SND_PCM_FORMAT_S8, DevFmtByte }, - { SND_PCM_FORMAT_U8, DevFmtUByte }, + }; + static constexpr std::array formatlist{ + FormatMap{SND_PCM_FORMAT_FLOAT, DevFmtFloat }, + FormatMap{SND_PCM_FORMAT_S32, DevFmtInt }, + FormatMap{SND_PCM_FORMAT_U32, DevFmtUInt }, + FormatMap{SND_PCM_FORMAT_S16, DevFmtShort }, + FormatMap{SND_PCM_FORMAT_U16, DevFmtUShort}, + FormatMap{SND_PCM_FORMAT_S8, DevFmtByte }, + FormatMap{SND_PCM_FORMAT_U8, DevFmtUByte }, }; for(const auto &fmt : formatlist) @@ -750,21 +782,21 @@ bool AlsaPlayback::reset() else mDevice->FmtChans = DevFmtStereo; } /* set rate (implicitly constrains period/buffer parameters) */ - if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "alsa", "allow-resampler", false) + if(!GetConfigValueBool(mDevice->mDeviceName, "alsa", "allow-resampler", false) || !mDevice->Flags.test(FrequencyRequest)) { if(snd_pcm_hw_params_set_rate_resample(mPcmHandle, hp.get(), 0) < 0) - WARN("Failed to disable ALSA resampler\n"); + WARN("Failed to disable ALSA resampler"); } else if(snd_pcm_hw_params_set_rate_resample(mPcmHandle, hp.get(), 1) < 0) - WARN("Failed to enable ALSA resampler\n"); + WARN("Failed to enable ALSA resampler"); CHECK(snd_pcm_hw_params_set_rate_near(mPcmHandle, hp.get(), &rate, nullptr)); /* set period time (implicitly constrains period/buffer parameters) */ - if((err=snd_pcm_hw_params_set_period_time_near(mPcmHandle, hp.get(), &periodLen, nullptr)) < 0) - ERR("snd_pcm_hw_params_set_period_time_near failed: %s\n", snd_strerror(err)); + if(int err{snd_pcm_hw_params_set_period_time_near(mPcmHandle, hp.get(), &periodLen, nullptr)}; err < 0) + ERR("snd_pcm_hw_params_set_period_time_near failed: {}", snd_strerror(err)); /* set buffer time (implicitly sets buffer size/bytes/time and period size/bytes) */ - if((err=snd_pcm_hw_params_set_buffer_time_near(mPcmHandle, hp.get(), &bufferLen, nullptr)) < 0) - ERR("snd_pcm_hw_params_set_buffer_time_near failed: %s\n", snd_strerror(err)); + if(int err{snd_pcm_hw_params_set_buffer_time_near(mPcmHandle, hp.get(), &bufferLen, nullptr)}; err < 0) + ERR("snd_pcm_hw_params_set_buffer_time_near failed: {}", snd_strerror(err)); /* install and prepare hardware configuration */ CHECK(snd_pcm_hw_params(mPcmHandle, hp.get())); @@ -787,9 +819,9 @@ bool AlsaPlayback::reset() #undef CHECK sp = nullptr; - mDevice->BufferSize = static_cast(bufferSizeInFrames); - mDevice->UpdateSize = static_cast(periodSizeInFrames); - mDevice->Frequency = rate; + mDevice->mBufferSize = static_cast(bufferSizeInFrames); + mDevice->mUpdateSize = static_cast(periodSizeInFrames); + mDevice->mSampleRate = rate; setDefaultChannelOrder(); @@ -798,12 +830,11 @@ bool AlsaPlayback::reset() void AlsaPlayback::start() { - int err{}; snd_pcm_access_t access{}; HwParamsPtr hp{CreateHwParams()}; #define CHECK(x) do { \ - if((err=(x)) < 0) \ - throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \ + if(int err{x}; err < 0) \ + throw al::backend_exception{al::backend_error::DeviceError, #x " failed: {}", \ snd_strerror(err)}; \ } while(0) CHECK(snd_pcm_hw_params_current(mPcmHandle, hp.get())); @@ -814,7 +845,7 @@ void AlsaPlayback::start() int (AlsaPlayback::*thread_func)(){}; if(access == SND_PCM_ACCESS_RW_INTERLEAVED) { - auto datalen = snd_pcm_frames_to_bytes(mPcmHandle, mDevice->UpdateSize); + auto datalen = snd_pcm_frames_to_bytes(mPcmHandle, mDevice->mUpdateSize); mBuffer.resize(static_cast(datalen)); thread_func = &AlsaPlayback::mixerNoMMapProc; } @@ -827,11 +858,11 @@ void AlsaPlayback::start() try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(thread_func), this}; + mThread = std::thread{thread_func, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -844,31 +875,30 @@ void AlsaPlayback::stop() mBuffer.clear(); int err{snd_pcm_drop(mPcmHandle)}; if(err < 0) - ERR("snd_pcm_drop failed: %s\n", snd_strerror(err)); + ERR("snd_pcm_drop failed: {}", snd_strerror(err)); } ClockLatency AlsaPlayback::getClockLatency() { - ClockLatency ret; - - std::lock_guard _{mMutex}; - ret.ClockTime = GetDeviceClockTime(mDevice); + std::lock_guard dlock{mMutex}; + ClockLatency ret{}; + ret.ClockTime = mDevice->getClockTime(); snd_pcm_sframes_t delay{}; int err{snd_pcm_delay(mPcmHandle, &delay)}; if(err < 0) { - ERR("Failed to get pcm delay: %s\n", snd_strerror(err)); + ERR("Failed to get pcm delay: {}", snd_strerror(err)); delay = 0; } ret.Latency = std::chrono::seconds{std::max(0, delay)}; - ret.Latency /= mDevice->Frequency; + ret.Latency /= mDevice->mSampleRate; return ret; } struct AlsaCapture final : public BackendBase { - AlsaCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit AlsaCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~AlsaCapture() override; void open(std::string_view name) override; @@ -886,8 +916,6 @@ struct AlsaCapture final : public BackendBase { RingBufferPtr mRing{nullptr}; snd_pcm_sframes_t mLastAvail{0}; - - DEF_NEWDEL(AlsaCapture) }; AlsaCapture::~AlsaCapture() @@ -910,21 +938,20 @@ void AlsaCapture::open(std::string_view name) [name](const DevMap &entry) -> bool { return entry.name == name; }); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; driver = iter->device_name; } else { - name = alsaDevice; - if(auto driveropt = ConfigValueStr(nullptr, "alsa", "capture")) + name = GetDefaultName(); + if(auto driveropt = ConfigValueStr({}, "alsa"sv, "capture"sv)) driver = std::move(driveropt).value(); } - TRACE("Opening device \"%s\"\n", driver.c_str()); - int err{snd_pcm_open(&mPcmHandle, driver.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)}; - if(err < 0) + TRACE("Opening device \"{}\"", driver); + if(int err{snd_pcm_open(&mPcmHandle, driver.c_str(), SND_PCM_STREAM_CAPTURE, SND_PCM_NONBLOCK)}; err < 0) throw al::backend_exception{al::backend_error::NoDevice, - "Could not open ALSA device \"%s\"", driver.c_str()}; + "Could not open ALSA device \"{}\"", driver}; /* Free alsa's global config tree. Otherwise valgrind reports a ton of leaks. */ snd_config_update_free_global(); @@ -955,14 +982,16 @@ void AlsaCapture::open(std::string_view name) break; } - snd_pcm_uframes_t bufferSizeInFrames{maxu(mDevice->BufferSize, 100*mDevice->Frequency/1000)}; - snd_pcm_uframes_t periodSizeInFrames{minu(mDevice->BufferSize, 25*mDevice->Frequency/1000)}; + snd_pcm_uframes_t bufferSizeInFrames{std::max(mDevice->mBufferSize, + 100u*mDevice->mSampleRate/1000u)}; + snd_pcm_uframes_t periodSizeInFrames{std::min(mDevice->mBufferSize, + 25u*mDevice->mSampleRate/1000u)}; bool needring{false}; HwParamsPtr hp{CreateHwParams()}; #define CHECK(x) do { \ - if((err=(x)) < 0) \ - throw al::backend_exception{al::backend_error::DeviceError, #x " failed: %s", \ + if(int err{x}; err < 0) \ + throw al::backend_exception{al::backend_error::DeviceError, #x " failed: {}", \ snd_strerror(err)}; \ } while(0) CHECK(snd_pcm_hw_params_any(mPcmHandle, hp.get())); @@ -973,11 +1002,11 @@ void AlsaCapture::open(std::string_view name) /* set channels (implicitly sets frame bits) */ CHECK(snd_pcm_hw_params_set_channels(mPcmHandle, hp.get(), mDevice->channelsFromFmt())); /* set rate (implicitly constrains period/buffer parameters) */ - CHECK(snd_pcm_hw_params_set_rate(mPcmHandle, hp.get(), mDevice->Frequency, 0)); + CHECK(snd_pcm_hw_params_set_rate(mPcmHandle, hp.get(), mDevice->mSampleRate, 0)); /* set buffer size in frame units (implicitly sets period size/bytes/time and buffer time/bytes) */ if(snd_pcm_hw_params_set_buffer_size_min(mPcmHandle, hp.get(), &bufferSizeInFrames) < 0) { - TRACE("Buffer too large, using intermediate ring buffer\n"); + TRACE("Buffer too large, using intermediate ring buffer"); needring = true; CHECK(snd_pcm_hw_params_set_buffer_size_near(mPcmHandle, hp.get(), &bufferSizeInFrames)); } @@ -991,22 +1020,20 @@ void AlsaCapture::open(std::string_view name) hp = nullptr; if(needring) - mRing = RingBuffer::Create(mDevice->BufferSize, mDevice->frameSizeFromFmt(), false); + mRing = RingBuffer::Create(mDevice->mBufferSize, mDevice->frameSizeFromFmt(), false); - mDevice->DeviceName = name; + mDeviceName = name; } void AlsaCapture::start() { - int err{snd_pcm_prepare(mPcmHandle)}; - if(err < 0) - throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_prepare failed: %s", + if(int err{snd_pcm_prepare(mPcmHandle)}; err < 0) + throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_prepare failed: {}", snd_strerror(err)}; - err = snd_pcm_start(mPcmHandle); - if(err < 0) - throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_start failed: %s", + if(int err{snd_pcm_start(mPcmHandle)}; err < 0) + throw al::backend_exception{al::backend_error::DeviceError, "snd_pcm_start failed: {}", snd_strerror(err)}; mDoCapture = true; @@ -1029,9 +1056,8 @@ void AlsaCapture::stop() captureSamples(temp.data(), avail); mBuffer = std::move(temp); } - int err{snd_pcm_drop(mPcmHandle)}; - if(err < 0) - ERR("drop failed: %s\n", snd_strerror(err)); + if(int err{snd_pcm_drop(mPcmHandle)}; err < 0) + ERR("snd_pcm_drop failed: {}", snd_strerror(err)); mDoCapture = false; } @@ -1039,10 +1065,13 @@ void AlsaCapture::captureSamples(std::byte *buffer, uint samples) { if(mRing) { - mRing->read(buffer, samples); + std::ignore = mRing->read(buffer, samples); return; } + const auto outspan = al::span{buffer, + static_cast(snd_pcm_frames_to_bytes(mPcmHandle, samples))}; + auto outiter = outspan.begin(); mLastAvail -= samples; while(mDevice->Connected.load(std::memory_order_acquire) && samples > 0) { @@ -1055,20 +1084,21 @@ void AlsaCapture::captureSamples(std::byte *buffer, uint samples) if(static_cast(amt) > samples) amt = samples; amt = snd_pcm_frames_to_bytes(mPcmHandle, amt); - std::copy_n(mBuffer.begin(), amt, buffer); + std::copy_n(mBuffer.begin(), amt, outiter); mBuffer.erase(mBuffer.begin(), mBuffer.begin()+amt); amt = snd_pcm_bytes_to_frames(mPcmHandle, amt); } else if(mDoCapture) - amt = snd_pcm_readi(mPcmHandle, buffer, samples); + amt = snd_pcm_readi(mPcmHandle, al::to_address(outiter), samples); if(amt < 0) { - ERR("read error: %s\n", snd_strerror(static_cast(amt))); + ERR("read error: {}", snd_strerror(static_cast(amt))); if(amt == -EAGAIN) continue; - if((amt=snd_pcm_recover(mPcmHandle, static_cast(amt), 1)) >= 0) + amt = snd_pcm_recover(mPcmHandle, static_cast(amt), 1); + if(amt >= 0) { amt = snd_pcm_start(mPcmHandle); if(amt >= 0) @@ -1077,8 +1107,8 @@ void AlsaCapture::captureSamples(std::byte *buffer, uint samples) if(amt < 0) { const char *err{snd_strerror(static_cast(amt))}; - ERR("restore error: %s\n", err); - mDevice->handleDisconnect("Capture recovery failure: %s", err); + ERR("restore error: {}", err); + mDevice->handleDisconnect("Capture recovery failure: {}", err); break; } /* If the amount available is less than what's asked, we lost it @@ -1088,11 +1118,11 @@ void AlsaCapture::captureSamples(std::byte *buffer, uint samples) continue; } - buffer = buffer + amt; + outiter += amt; samples -= static_cast(amt); } if(samples > 0) - std::fill_n(buffer, snd_pcm_frames_to_bytes(mPcmHandle, samples), + std::fill_n(outiter, snd_pcm_frames_to_bytes(mPcmHandle, samples), std::byte((mDevice->FmtType == DevFmtUByte) ? 0x80 : 0)); } @@ -1103,9 +1133,10 @@ uint AlsaCapture::availableSamples() avail = snd_pcm_avail_update(mPcmHandle); if(avail < 0) { - ERR("avail update failed: %s\n", snd_strerror(static_cast(avail))); + ERR("snd_pcm_avail_update failed: {}", snd_strerror(static_cast(avail))); - if((avail=snd_pcm_recover(mPcmHandle, static_cast(avail), 1)) >= 0) + avail = snd_pcm_recover(mPcmHandle, static_cast(avail), 1); + if(avail >= 0) { if(mDoCapture) avail = snd_pcm_start(mPcmHandle); @@ -1115,33 +1146,34 @@ uint AlsaCapture::availableSamples() if(avail < 0) { const char *err{snd_strerror(static_cast(avail))}; - ERR("restore error: %s\n", err); - mDevice->handleDisconnect("Capture recovery failure: %s", err); + ERR("restore error: {}", err); + mDevice->handleDisconnect("Capture recovery failure: {}", err); } } if(!mRing) { - if(avail < 0) avail = 0; + avail = std::max(avail, 0); avail += snd_pcm_bytes_to_frames(mPcmHandle, static_cast(mBuffer.size())); - if(avail > mLastAvail) mLastAvail = avail; + mLastAvail = std::max(mLastAvail, avail); return static_cast(mLastAvail); } while(avail > 0) { auto vec = mRing->getWriteVector(); - if(vec.first.len == 0) break; + if(vec[0].len == 0) break; - snd_pcm_sframes_t amt{std::min(static_cast(vec.first.len), avail)}; - amt = snd_pcm_readi(mPcmHandle, vec.first.buf, static_cast(amt)); + snd_pcm_sframes_t amt{std::min(static_cast(vec[0].len), avail)}; + amt = snd_pcm_readi(mPcmHandle, vec[0].buf, static_cast(amt)); if(amt < 0) { - ERR("read error: %s\n", snd_strerror(static_cast(amt))); + ERR("read error: {}", snd_strerror(static_cast(amt))); if(amt == -EAGAIN) continue; - if((amt=snd_pcm_recover(mPcmHandle, static_cast(amt), 1)) >= 0) + amt = snd_pcm_recover(mPcmHandle, static_cast(amt), 1); + if(amt >= 0) { if(mDoCapture) amt = snd_pcm_start(mPcmHandle); @@ -1151,8 +1183,8 @@ uint AlsaCapture::availableSamples() if(amt < 0) { const char *err{snd_strerror(static_cast(amt))}; - ERR("restore error: %s\n", err); - mDevice->handleDisconnect("Capture recovery failure: %s", err); + ERR("restore error: {}", err); + mDevice->handleDisconnect("Capture recovery failure: {}", err); break; } avail = amt; @@ -1168,18 +1200,17 @@ uint AlsaCapture::availableSamples() ClockLatency AlsaCapture::getClockLatency() { - ClockLatency ret; - - ret.ClockTime = GetDeviceClockTime(mDevice); + ClockLatency ret{}; + ret.ClockTime = mDevice->getClockTime(); snd_pcm_sframes_t delay{}; int err{snd_pcm_delay(mPcmHandle, &delay)}; if(err < 0) { - ERR("Failed to get pcm delay: %s\n", snd_strerror(err)); + ERR("Failed to get pcm delay: {}", snd_strerror(err)); delay = 0; } ret.Latency = std::chrono::seconds{std::max(0, delay)}; - ret.Latency /= mDevice->Frequency; + ret.Latency /= mDevice->mSampleRate; return ret; } @@ -1189,66 +1220,57 @@ ClockLatency AlsaCapture::getClockLatency() bool AlsaBackendFactory::init() { - bool error{false}; - -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD if(!alsa_handle) { - std::string missing_funcs; - alsa_handle = LoadLib("libasound.so.2"); if(!alsa_handle) { - WARN("Failed to load %s\n", "libasound.so.2"); + WARN("Failed to load {}", "libasound.so.2"); return false; } - error = false; + std::string missing_funcs; #define LOAD_FUNC(f) do { \ - p##f = al::bit_cast(GetSymbol(alsa_handle, #f)); \ - if(p##f == nullptr) { \ - error = true; \ - missing_funcs += "\n" #f; \ - } \ + p##f = reinterpret_cast(GetSymbol(alsa_handle, #f)); \ + if(p##f == nullptr) missing_funcs += "\n" #f; \ } while(0) ALSA_FUNCS(LOAD_FUNC); #undef LOAD_FUNC - if(error) + if(!missing_funcs.empty()) { - WARN("Missing expected functions:%s\n", missing_funcs.c_str()); + WARN("Missing expected functions:{}", missing_funcs); CloseLib(alsa_handle); alsa_handle = nullptr; + return false; } } #endif - return !error; + return true; } bool AlsaBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string AlsaBackendFactory::probe(BackendType type) +auto AlsaBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; - + std::vector outnames; auto add_device = [&outnames](const DevMap &entry) -> void - { - /* +1 to also append the null char (to ensure a null-separated list and - * double-null terminated list). - */ - outnames.append(entry.name.c_str(), entry.name.length()+1); - }; + { outnames.emplace_back(entry.name); }; + switch(type) { case BackendType::Playback: PlaybackDevices = probe_devices(SND_PCM_STREAM_PLAYBACK); + outnames.reserve(PlaybackDevices.size()); std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device); break; case BackendType::Capture: CaptureDevices = probe_devices(SND_PCM_STREAM_CAPTURE); + outnames.reserve(CaptureDevices.size()); std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); break; } diff --git a/3rdparty/openal/alc/backends/alsa.h b/3rdparty/openal/alc/backends/alsa.h index b256dcf5a996..1327db8a4e82 100644 --- a/3rdparty/openal/alc/backends/alsa.h +++ b/3rdparty/openal/alc/backends/alsa.h @@ -5,15 +5,15 @@ struct AlsaBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_ALSA_H */ diff --git a/3rdparty/openal/alc/backends/base.cpp b/3rdparty/openal/alc/backends/base.cpp index ab3ad028d1d4..9d9ce4a06074 100644 --- a/3rdparty/openal/alc/backends/base.cpp +++ b/3rdparty/openal/alc/backends/base.cpp @@ -3,34 +3,18 @@ #include "base.h" -#include #include #include +#include -#ifdef _WIN32 -#define WIN32_LEAN_AND_MEAN -#include -#include - -#include "albit.h" -#include "core/logging.h" -#endif - -#include "atomic.h" #include "core/devformat.h" namespace al { +auto backend_exception::make_string(fmt::string_view fmt, fmt::format_args args) -> std::string +{ return fmt::vformat(fmt, std::move(args)); } -backend_exception::backend_exception(backend_error code, const char *msg, ...) : mErrorCode{code} -{ - std::va_list args; - va_start(args, msg); - setMessage(msg, args); - va_end(args); -} backend_exception::~backend_exception() = default; - } // namespace al @@ -45,27 +29,26 @@ uint BackendBase::availableSamples() ClockLatency BackendBase::getClockLatency() { - ClockLatency ret; + ClockLatency ret{}; uint refcount; do { refcount = mDevice->waitForMix(); - ret.ClockTime = GetDeviceClockTime(mDevice); + ret.ClockTime = mDevice->getClockTime(); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != ReadRef(mDevice->MixCount)); + } while(refcount != mDevice->mMixCount.load(std::memory_order_relaxed)); /* NOTE: The device will generally have about all but one periods filled at * any given time during playback. Without a more accurate measurement from * the output, this is an okay approximation. */ - ret.Latency = std::max(std::chrono::seconds{mDevice->BufferSize-mDevice->UpdateSize}, - std::chrono::seconds::zero()); - ret.Latency /= mDevice->Frequency; + ret.Latency = std::chrono::seconds{mDevice->mBufferSize - mDevice->mUpdateSize}; + ret.Latency /= mDevice->mSampleRate; return ret; } -void BackendBase::setDefaultWFXChannelOrder() +void BackendBase::setDefaultWFXChannelOrder() const { mDevice->RealOut.ChannelIndex.fill(InvalidChannelIndex); @@ -125,6 +108,24 @@ void BackendBase::setDefaultWFXChannelOrder() mDevice->RealOut.ChannelIndex[TopBackLeft] = 10; mDevice->RealOut.ChannelIndex[TopBackRight] = 11; break; + case DevFmtX7144: + mDevice->RealOut.ChannelIndex[FrontLeft] = 0; + mDevice->RealOut.ChannelIndex[FrontRight] = 1; + mDevice->RealOut.ChannelIndex[FrontCenter] = 2; + mDevice->RealOut.ChannelIndex[LFE] = 3; + mDevice->RealOut.ChannelIndex[BackLeft] = 4; + mDevice->RealOut.ChannelIndex[BackRight] = 5; + mDevice->RealOut.ChannelIndex[SideLeft] = 6; + mDevice->RealOut.ChannelIndex[SideRight] = 7; + mDevice->RealOut.ChannelIndex[TopFrontLeft] = 8; + mDevice->RealOut.ChannelIndex[TopFrontRight] = 9; + mDevice->RealOut.ChannelIndex[TopBackLeft] = 10; + mDevice->RealOut.ChannelIndex[TopBackRight] = 11; + mDevice->RealOut.ChannelIndex[BottomFrontLeft] = 12; + mDevice->RealOut.ChannelIndex[BottomFrontRight] = 13; + mDevice->RealOut.ChannelIndex[BottomBackLeft] = 14; + mDevice->RealOut.ChannelIndex[BottomBackRight] = 15; + break; case DevFmtX3D71: mDevice->RealOut.ChannelIndex[FrontLeft] = 0; mDevice->RealOut.ChannelIndex[FrontRight] = 1; @@ -140,7 +141,7 @@ void BackendBase::setDefaultWFXChannelOrder() } } -void BackendBase::setDefaultChannelOrder() +void BackendBase::setDefaultChannelOrder() const { mDevice->RealOut.ChannelIndex.fill(InvalidChannelIndex); @@ -178,6 +179,24 @@ void BackendBase::setDefaultChannelOrder() mDevice->RealOut.ChannelIndex[TopBackLeft] = 10; mDevice->RealOut.ChannelIndex[TopBackRight] = 11; break; + case DevFmtX7144: + mDevice->RealOut.ChannelIndex[FrontLeft] = 0; + mDevice->RealOut.ChannelIndex[FrontRight] = 1; + mDevice->RealOut.ChannelIndex[BackLeft] = 2; + mDevice->RealOut.ChannelIndex[BackRight] = 3; + mDevice->RealOut.ChannelIndex[FrontCenter] = 4; + mDevice->RealOut.ChannelIndex[LFE] = 5; + mDevice->RealOut.ChannelIndex[SideLeft] = 6; + mDevice->RealOut.ChannelIndex[SideRight] = 7; + mDevice->RealOut.ChannelIndex[TopFrontLeft] = 8; + mDevice->RealOut.ChannelIndex[TopFrontRight] = 9; + mDevice->RealOut.ChannelIndex[TopBackLeft] = 10; + mDevice->RealOut.ChannelIndex[TopBackRight] = 11; + mDevice->RealOut.ChannelIndex[BottomFrontLeft] = 12; + mDevice->RealOut.ChannelIndex[BottomFrontRight] = 13; + mDevice->RealOut.ChannelIndex[BottomBackLeft] = 14; + mDevice->RealOut.ChannelIndex[BottomBackRight] = 15; + break; case DevFmtX3D71: mDevice->RealOut.ChannelIndex[FrontLeft] = 0; mDevice->RealOut.ChannelIndex[FrontRight] = 1; diff --git a/3rdparty/openal/alc/backends/base.h b/3rdparty/openal/alc/backends/base.h index a4079fe42064..4e59836d1961 100644 --- a/3rdparty/openal/alc/backends/base.h +++ b/3rdparty/openal/alc/backends/base.h @@ -5,12 +5,14 @@ #include #include #include -#include #include #include +#include +#include "alc/events.h" #include "core/device.h" #include "core/except.h" +#include "fmt/core.h" using uint = unsigned int; @@ -33,15 +35,22 @@ struct BackendBase { virtual ClockLatency getClockLatency(); DeviceBase *const mDevice; + std::string mDeviceName; - BackendBase(DeviceBase *device) noexcept : mDevice{device} { } + BackendBase() = delete; + BackendBase(const BackendBase&) = delete; + BackendBase(BackendBase&&) = delete; + explicit BackendBase(DeviceBase *device) noexcept : mDevice{device} { } virtual ~BackendBase() = default; + void operator=(const BackendBase&) = delete; + void operator=(BackendBase&&) = delete; + protected: /** Sets the default channel order used by most non-WaveFormatEx-based APIs. */ - void setDefaultChannelOrder(); + void setDefaultChannelOrder() const; /** Sets the default channel order used by WaveFormatEx. */ - void setDefaultWFXChannelOrder(); + void setDefaultWFXChannelOrder() const; }; using BackendPtr = std::unique_ptr; @@ -51,18 +60,6 @@ enum class BackendType { }; -/* Helper to get the current clock time from the device's ClockBase, and - * SamplesDone converted from the sample rate. - */ -inline std::chrono::nanoseconds GetDeviceClockTime(DeviceBase *device) -{ - using std::chrono::seconds; - using std::chrono::nanoseconds; - - auto ns = nanoseconds{seconds{device->SamplesDone}} / device->Frequency; - return device->ClockBase + ns; -} - /* Helper to get the device latency from the backend, including any fixed * latency from post-processing. */ @@ -75,16 +72,24 @@ inline ClockLatency GetClockLatency(DeviceBase *device, BackendBase *backend) struct BackendFactory { - virtual bool init() = 0; + BackendFactory() = default; + BackendFactory(const BackendFactory&) = delete; + BackendFactory(BackendFactory&&) = delete; + virtual ~BackendFactory() = default; - virtual bool querySupport(BackendType type) = 0; + void operator=(const BackendFactory&) = delete; + void operator=(BackendFactory&&) = delete; - virtual std::string probe(BackendType type) = 0; + virtual auto init() -> bool = 0; - virtual BackendPtr createBackend(DeviceBase *device, BackendType type) = 0; + virtual auto querySupport(BackendType type) -> bool = 0; -protected: - virtual ~BackendFactory() = default; + virtual auto queryEventSupport(alc::EventType, BackendType) -> alc::EventSupport + { return alc::EventSupport::NoSupport; } + + virtual auto enumerate(BackendType type) -> std::vector = 0; + + virtual auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr = 0; }; namespace al { @@ -98,16 +103,21 @@ enum class backend_error { class backend_exception final : public base_exception { backend_error mErrorCode; + static auto make_string(fmt::string_view fmt, fmt::format_args args) -> std::string; + public: -#ifdef __USE_MINGW_ANSI_STDIO - [[gnu::format(gnu_printf, 3, 4)]] -#else - [[gnu::format(printf, 3, 4)]] -#endif - backend_exception(backend_error code, const char *msg, ...); + template + backend_exception(backend_error code, fmt::format_string fmt, Args&& ...args) + : base_exception{make_string(fmt, fmt::make_format_args(args...))}, mErrorCode{code} + { } + backend_exception(const backend_exception&) = default; + backend_exception(backend_exception&&) = default; ~backend_exception() override; - backend_error errorCode() const noexcept { return mErrorCode; } + backend_exception& operator=(const backend_exception&) = default; + backend_exception& operator=(backend_exception&&) = default; + + [[nodiscard]] auto errorCode() const noexcept -> backend_error { return mErrorCode; } }; } // namespace al diff --git a/3rdparty/openal/alc/backends/coreaudio.cpp b/3rdparty/openal/alc/backends/coreaudio.cpp index 1684545b9665..138859cbca11 100644 --- a/3rdparty/openal/alc/backends/coreaudio.cpp +++ b/3rdparty/openal/alc/backends/coreaudio.cpp @@ -24,7 +24,9 @@ #include #include +#include #include +#include #include #include #include @@ -32,14 +34,14 @@ #include #include #include -#include #include "alnumeric.h" +#include "alstring.h" #include "core/converter.h" #include "core/device.h" #include "core/logging.h" +#include "fmt/core.h" #include "ringbuffer.h" -#include "alc/events.h" #include #include @@ -56,10 +58,40 @@ namespace { constexpr auto OutputElement = 0; constexpr auto InputElement = 1; +// These following arrays should always be defined in ascending AudioChannelLabel value order +constexpr std::array MonoChanMap { kAudioChannelLabel_Mono }; +constexpr std::array StereoChanMap { kAudioChannelLabel_Left, kAudioChannelLabel_Right}; +constexpr std::array QuadChanMap { + kAudioChannelLabel_Left, kAudioChannelLabel_Right, + kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround +}; +constexpr std::array X51ChanMap { + kAudioChannelLabel_Left, kAudioChannelLabel_Right, + kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, + kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround +}; +constexpr std::array X51RearChanMap { + kAudioChannelLabel_Left, kAudioChannelLabel_Right, + kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, + kAudioChannelLabel_RearSurroundRight, kAudioChannelLabel_RearSurroundLeft +}; +constexpr std::array X61ChanMap { + kAudioChannelLabel_Left, kAudioChannelLabel_Right, + kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, + kAudioChannelLabel_CenterSurround, + kAudioChannelLabel_RearSurroundRight, kAudioChannelLabel_RearSurroundLeft +}; +constexpr std::array X71ChanMap { + kAudioChannelLabel_Left, kAudioChannelLabel_Right, + kAudioChannelLabel_Center, kAudioChannelLabel_LFEScreen, + kAudioChannelLabel_LeftSurround, kAudioChannelLabel_RightSurround, + kAudioChannelLabel_LeftCenter, kAudioChannelLabel_RightCenter +}; + struct FourCCPrinter { char mString[sizeof(UInt32) + 1]{}; - constexpr FourCCPrinter(UInt32 code) noexcept + explicit constexpr FourCCPrinter(UInt32 code) noexcept { for(size_t i{0};i < sizeof(UInt32);++i) { @@ -73,7 +105,7 @@ struct FourCCPrinter { code >>= 8; } } - constexpr FourCCPrinter(int code) noexcept : FourCCPrinter{static_cast(code)} { } + explicit constexpr FourCCPrinter(OSStatus code) noexcept : FourCCPrinter{static_cast(code)} { } constexpr const char *c_str() const noexcept { return mString; } }; @@ -159,19 +191,19 @@ std::string GetDeviceName(AudioDeviceID devId) /* Clear extraneous nul chars that may have been written with the name * string, and return it. */ - while(!devname.back()) + while(!devname.empty() && !devname.back()) devname.pop_back(); return devname; } -UInt32 GetDeviceChannelCount(AudioDeviceID devId, bool isCapture) +auto GetDeviceChannelCount(AudioDeviceID devId, bool isCapture) -> UInt32 { - UInt32 propSize{}; + auto propSize = UInt32{}; auto err = GetDevPropertySize(devId, kAudioDevicePropertyStreamConfiguration, isCapture, 0, &propSize); if(err) { - ERR("kAudioDevicePropertyStreamConfiguration size query failed: '%s' (%u)\n", + ERR("kAudioDevicePropertyStreamConfiguration size query failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return 0; } @@ -183,15 +215,14 @@ UInt32 GetDeviceChannelCount(AudioDeviceID devId, bool isCapture) buflist); if(err) { - ERR("kAudioDevicePropertyStreamConfiguration query failed: '%s' (%u)\n", + ERR("kAudioDevicePropertyStreamConfiguration query failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return 0; } - UInt32 numChannels{0}; + auto numChannels = UInt32{0}; for(size_t i{0};i < buflist->mNumberBuffers;++i) numChannels += buflist->mBuffers[i].mNumberChannels; - return numChannels; } @@ -201,14 +232,14 @@ void EnumerateDevices(std::vector &list, bool isCapture) UInt32 propSize{}; if(auto err = GetHwPropertySize(kAudioHardwarePropertyDevices, &propSize)) { - ERR("Failed to get device list size: %u\n", err); + ERR("Failed to get device list size: {}", err); return; } auto devIds = std::vector(propSize/sizeof(AudioDeviceID), kAudioDeviceUnknown); if(auto err = GetHwProperty(kAudioHardwarePropertyDevices, propSize, devIds.data())) { - ERR("Failed to get device list: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("Failed to get device list: '{}' ({})", FourCCPrinter{err}.c_str(), err); return; } @@ -223,7 +254,7 @@ void EnumerateDevices(std::vector &list, bool isCapture) { newdevs.emplace_back(DeviceEntry{defaultId, GetDeviceName(defaultId)}); const auto &entry = newdevs.back(); - TRACE("Got device: %s = ID %u\n", entry.mName.c_str(), entry.mId); + TRACE("Got device: {} = ID {}", entry.mName, entry.mId); } for(const AudioDeviceID devId : devIds) { @@ -240,7 +271,7 @@ void EnumerateDevices(std::vector &list, bool isCapture) { newdevs.emplace_back(DeviceEntry{devId, GetDeviceName(devId)}); const auto &entry = newdevs.back(); - TRACE("Got device: %s = ID %u\n", entry.mName.c_str(), entry.mId); + TRACE("Got device: {} = ID {}", entry.mName, entry.mId); } } @@ -255,14 +286,12 @@ void EnumerateDevices(std::vector &list, bool isCapture) { return entry.mName == curitem->mName; }; if(std::find_if(newdevs.begin(), curitem, check_match) != curitem) { - std::string name{curitem->mName}; - size_t count{1}; + auto name = std::string{curitem->mName}; + auto count = 1_uz; auto check_name = [&name](const DeviceEntry &entry) -> bool { return entry.mName == name; }; do { - name = curitem->mName; - name += " #"; - name += std::to_string(++count); + name = fmt::format("{} #{}", curitem->mName, ++count); } while(std::find_if(newdevs.begin(), curitem, check_name) != curitem); curitem->mName = std::move(name); } @@ -277,18 +306,18 @@ struct DeviceHelper { DeviceHelper() { AudioObjectPropertyAddress addr{kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster}; OSStatus status = AudioObjectAddPropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); if (status != noErr) - ERR("AudioObjectAddPropertyListener fail: %d", status); + ERR("AudioObjectAddPropertyListener fail: {}", status); } ~DeviceHelper() { AudioObjectPropertyAddress addr{kAudioHardwarePropertyDefaultOutputDevice, - kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMain}; + kAudioObjectPropertyScopeGlobal, kAudioObjectPropertyElementMaster}; OSStatus status = AudioObjectRemovePropertyListener(kAudioObjectSystemObject, &addr, DeviceListenerProc, nil); if (status != noErr) - ERR("AudioObjectRemovePropertyListener fail: %d", status); + ERR("AudioObjectRemovePropertyListener fail: {}", status); } static OSStatus DeviceListenerProc(AudioObjectID /*inObjectID*/, UInt32 inNumberAddresses, @@ -322,7 +351,7 @@ static constexpr char ca_device[] = "CoreAudio Default"; struct CoreAudioPlayback final : public BackendBase { - CoreAudioPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit CoreAudioPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~CoreAudioPlayback() override; OSStatus MixerProc(AudioUnitRenderActionFlags *ioActionFlags, @@ -338,8 +367,6 @@ struct CoreAudioPlayback final : public BackendBase { uint mFrameSize{0u}; AudioStreamBasicDescription mFormat{}; // This is the OpenAL format as a CoreAudio ASBD - - DEF_NEWDEL(CoreAudioPlayback) }; CoreAudioPlayback::~CoreAudioPlayback() @@ -379,7 +406,7 @@ void CoreAudioPlayback::open(std::string_view name) auto devmatch = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), find_name); if(devmatch == PlaybackList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; audioDevice = devmatch->mId; } @@ -387,8 +414,8 @@ void CoreAudioPlayback::open(std::string_view name) if(name.empty()) name = ca_device; else if(name != ca_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; #endif /* open the default output unit */ @@ -412,7 +439,7 @@ void CoreAudioPlayback::open(std::string_view name) OSStatus err{AudioComponentInstanceNew(comp, &audioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::NoDevice, - "Could not create component instance: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not create component instance: '{}' ({})", FourCCPrinter{err}.c_str(), err}; #if CAN_ENUMERATE if(audioDevice != kAudioDeviceUnknown) @@ -423,7 +450,7 @@ void CoreAudioPlayback::open(std::string_view name) err = AudioUnitInitialize(audioUnit); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not initialize audio unit: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not initialize audio unit: '{}' ({})", FourCCPrinter{err}.c_str(), err}; /* WARNING: I don't know if "valid" audio unit values are guaranteed to be * non-0. If not, this logic is broken. @@ -437,7 +464,7 @@ void CoreAudioPlayback::open(std::string_view name) #if CAN_ENUMERATE if(!name.empty()) - mDevice->DeviceName = name; + mDeviceName = name; else { UInt32 propSize{sizeof(audioDevice)}; @@ -446,8 +473,8 @@ void CoreAudioPlayback::open(std::string_view name) kAudioUnitScope_Global, OutputElement, &audioDevice, &propSize); std::string devname{GetDeviceName(audioDevice)}; - if(!devname.empty()) mDevice->DeviceName = std::move(devname); - else mDevice->DeviceName = "Unknown Device Name"; + if(!devname.empty()) mDeviceName = std::move(devname); + else mDeviceName = "Unknown Device Name"; } if(audioDevice != kAudioDeviceUnknown) @@ -456,16 +483,16 @@ void CoreAudioPlayback::open(std::string_view name) err = GetDevProperty(audioDevice, kAudioDevicePropertyDataSource, false, kAudioObjectPropertyElementMaster, sizeof(type), &type); if(err != noErr) - ERR("Failed to get audio device type: %u\n", err); + WARN("Failed to get audio device type: '{}' ({})", FourCCPrinter{err}.c_str(), err); else { - TRACE("Got device type '%s'\n", FourCCPrinter{type}.c_str()); + TRACE("Got device type '{}'", FourCCPrinter{type}.c_str()); mDevice->Flags.set(DirectEar, (type == kIOAudioOutputPortSubTypeHeadphones)); } } #else - mDevice->DeviceName = name; + mDeviceName = name; #endif } @@ -473,7 +500,7 @@ bool CoreAudioPlayback::reset() { OSStatus err{AudioUnitUninitialize(mAudioUnit)}; if(err != noErr) - ERR("AudioUnitUninitialize failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("AudioUnitUninitialize failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); /* retrieve default output unit's properties (output side) */ AudioStreamBasicDescription streamFormat{}; @@ -482,33 +509,75 @@ bool CoreAudioPlayback::reset() OutputElement, &streamFormat, &size); if(err != noErr || size != sizeof(streamFormat)) { - ERR("AudioUnitGetProperty(StreamFormat) failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), + ERR("AudioUnitGetProperty(StreamFormat) failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return false; } -#if 0 - TRACE("Output streamFormat of default output unit -\n"); - TRACE(" streamFormat.mFramesPerPacket = %d\n", streamFormat.mFramesPerPacket); - TRACE(" streamFormat.mChannelsPerFrame = %d\n", streamFormat.mChannelsPerFrame); - TRACE(" streamFormat.mBitsPerChannel = %d\n", streamFormat.mBitsPerChannel); - TRACE(" streamFormat.mBytesPerPacket = %d\n", streamFormat.mBytesPerPacket); - TRACE(" streamFormat.mBytesPerFrame = %d\n", streamFormat.mBytesPerFrame); - TRACE(" streamFormat.mSampleRate = %5.0f\n", streamFormat.mSampleRate); -#endif - /* Use the sample rate from the output unit's current parameters, but reset * everything else. */ - if(mDevice->Frequency != streamFormat.mSampleRate) + if(mDevice->mSampleRate != streamFormat.mSampleRate) { - mDevice->BufferSize = static_cast(mDevice->BufferSize*streamFormat.mSampleRate/ - mDevice->Frequency + 0.5); - mDevice->Frequency = static_cast(streamFormat.mSampleRate); + mDevice->mBufferSize = static_cast(mDevice->mBufferSize*streamFormat.mSampleRate/ + mDevice->mSampleRate + 0.5); + mDevice->mSampleRate = static_cast(streamFormat.mSampleRate); } - /* FIXME: How to tell what channels are what in the output device, and how - * to specify what we're giving? e.g. 6.0 vs 5.1 + struct ChannelMap { + DevFmtChannels fmt; + al::span map; + bool is_51rear; + }; + + static constexpr std::array chanmaps{{ + { DevFmtX71, X71ChanMap, false }, + { DevFmtX61, X61ChanMap, false }, + { DevFmtX51, X51ChanMap, false }, + { DevFmtX51, X51RearChanMap, true }, + { DevFmtQuad, QuadChanMap, false }, + { DevFmtStereo, StereoChanMap, false }, + { DevFmtMono, MonoChanMap, false } + }}; + + if(!mDevice->Flags.test(ChannelsRequest)) + { + auto propSize = UInt32{}; + auto writable = Boolean{}; + + err = AudioUnitGetPropertyInfo(mAudioUnit, kAudioUnitProperty_AudioChannelLayout, + kAudioUnitScope_Output, OutputElement, &propSize, &writable); + if(err == noErr) + { + auto layout_data = std::make_unique(propSize); + auto *layout = reinterpret_cast(layout_data.get()); + + err = AudioUnitGetProperty(mAudioUnit, kAudioUnitProperty_AudioChannelLayout, + kAudioUnitScope_Output, OutputElement, layout, &propSize); + if(err == noErr) + { + auto descs = al::span{std::data(layout->mChannelDescriptions), + layout->mNumberChannelDescriptions}; + auto labels = std::vector(descs.size()); + + std::transform(descs.begin(), descs.end(), labels.begin(), + std::mem_fn(&AudioChannelDescription::mChannelLabel)); + sort(labels.begin(), labels.end()); + + auto check_labels = [&labels](const ChannelMap &chanmap) -> bool + { + return std::includes(labels.begin(), labels.end(), chanmap.map.begin(), + chanmap.map.end()); + }; + auto chaniter = std::find_if(chanmaps.cbegin(), chanmaps.cend(), check_labels); + if(chaniter != chanmaps.cend()) + mDevice->FmtChans = chaniter->fmt; + } + } + } + + /* TODO: Also set kAudioUnitProperty_AudioChannelLayout according to the AL + * device's channel configuration. */ streamFormat.mChannelsPerFrame = mDevice->channelsFromFmt(); @@ -550,7 +619,7 @@ bool CoreAudioPlayback::reset() OutputElement, &streamFormat, sizeof(streamFormat)); if(err != noErr) { - ERR("AudioUnitSetProperty(StreamFormat) failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), + ERR("AudioUnitSetProperty(StreamFormat) failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return false; } @@ -568,7 +637,7 @@ bool CoreAudioPlayback::reset() kAudioUnitScope_Input, OutputElement, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) { - ERR("AudioUnitSetProperty(SetRenderCallback) failed: '%s' (%u)\n", + ERR("AudioUnitSetProperty(SetRenderCallback) failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return false; } @@ -577,7 +646,7 @@ bool CoreAudioPlayback::reset() err = AudioUnitInitialize(mAudioUnit); if(err != noErr) { - ERR("AudioUnitInitialize failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("AudioUnitInitialize failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); return false; } @@ -589,19 +658,19 @@ void CoreAudioPlayback::start() const OSStatus err{AudioOutputUnitStart(mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "AudioOutputUnitStart failed: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "AudioOutputUnitStart failed: '{}' ({})", FourCCPrinter{err}.c_str(), err}; } void CoreAudioPlayback::stop() { OSStatus err{AudioOutputUnitStop(mAudioUnit)}; if(err != noErr) - ERR("AudioOutputUnitStop failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("AudioOutputUnitStop failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); } struct CoreAudioCapture final : public BackendBase { - CoreAudioCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit CoreAudioCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~CoreAudioCapture() override; OSStatus RecordProc(AudioUnitRenderActionFlags *ioActionFlags, @@ -624,8 +693,6 @@ struct CoreAudioCapture final : public BackendBase { std::vector mCaptureData; RingBufferPtr mRing{nullptr}; - - DEF_NEWDEL(CoreAudioCapture) }; CoreAudioCapture::~CoreAudioCapture() @@ -641,7 +708,7 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags, AudioBufferList*) noexcept { union { - std::byte _[maxz(sizeof(AudioBufferList), offsetof(AudioBufferList, mBuffers[1]))]; + std::byte buf[std::max(sizeof(AudioBufferList), offsetof(AudioBufferList, mBuffers[1]))]; AudioBufferList list; } audiobuf{}; @@ -654,11 +721,11 @@ OSStatus CoreAudioCapture::RecordProc(AudioUnitRenderActionFlags *ioActionFlags, inNumberFrames, &audiobuf.list)}; if(err != noErr) { - ERR("AudioUnitRender capture error: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("AudioUnitRender capture error: '{}' ({})", FourCCPrinter{err}.c_str(), err); return err; } - mRing->write(mCaptureData.data(), inNumberFrames); + std::ignore = mRing->write(mCaptureData.data(), inNumberFrames); return noErr; } @@ -680,7 +747,7 @@ void CoreAudioCapture::open(std::string_view name) auto devmatch = std::find_if(CaptureList.cbegin(), CaptureList.cend(), find_name); if(devmatch == CaptureList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; audioDevice = devmatch->mId; } @@ -688,8 +755,8 @@ void CoreAudioCapture::open(std::string_view name) if(name.empty()) name = ca_device; else if(name != ca_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; #endif AudioComponentDescription desc{}; @@ -713,7 +780,7 @@ void CoreAudioCapture::open(std::string_view name) OSStatus err{AudioComponentInstanceNew(comp, &mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::NoDevice, - "Could not create component instance: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not create component instance: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Turn off AudioUnit output UInt32 enableIO{0}; @@ -721,7 +788,7 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Output, OutputElement, &enableIO, sizeof(enableIO)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not disable audio unit output property: '%s' (%u)", FourCCPrinter{err}.c_str(), + "Could not disable audio unit output property: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Turn on AudioUnit input @@ -730,7 +797,7 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Input, InputElement, &enableIO, sizeof(enableIO)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not enable audio unit input property: '%s' (%u)", FourCCPrinter{err}.c_str(), + "Could not enable audio unit input property: '{}' ({})", FourCCPrinter{err}.c_str(), err}; #if CAN_ENUMERATE @@ -749,7 +816,7 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Global, InputElement, &input, sizeof(AURenderCallbackStruct)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not set capture callback: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not set capture callback: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Disable buffer allocation for capture UInt32 flag{0}; @@ -757,14 +824,14 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Output, InputElement, &flag, sizeof(flag)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not disable buffer allocation property: '%s' (%u)", FourCCPrinter{err}.c_str(), + "Could not disable buffer allocation property: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Initialize the device err = AudioUnitInitialize(mAudioUnit); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not initialize audio unit: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not initialize audio unit: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Get the hardware format AudioStreamBasicDescription hardwareFormat{}; @@ -773,7 +840,7 @@ void CoreAudioCapture::open(std::string_view name) InputElement, &hardwareFormat, &propertySize); if(err != noErr || propertySize != sizeof(hardwareFormat)) throw al::backend_exception{al::backend_error::DeviceError, - "Could not get input format: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not get input format: '{}' ({})", FourCCPrinter{err}.c_str(), err}; // Set up the requested format description AudioStreamBasicDescription requestedFormat{}; @@ -826,15 +893,16 @@ void CoreAudioCapture::open(std::string_view name) case DevFmtX61: case DevFmtX71: case DevFmtX714: + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: - throw al::backend_exception{al::backend_error::DeviceError, "%s not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} not supported", DevFmtChannelsString(mDevice->FmtChans)}; } requestedFormat.mBytesPerFrame = requestedFormat.mChannelsPerFrame * requestedFormat.mBitsPerChannel / 8; requestedFormat.mBytesPerPacket = requestedFormat.mBytesPerFrame; - requestedFormat.mSampleRate = mDevice->Frequency; + requestedFormat.mSampleRate = mDevice->mSampleRate; requestedFormat.mFormatID = kAudioFormatLinearPCM; requestedFormat.mReserved = 0; requestedFormat.mFramesPerPacket = 1; @@ -854,18 +922,18 @@ void CoreAudioCapture::open(std::string_view name) InputElement, &outputFormat, sizeof(outputFormat)); if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "Could not set input format: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not set input format: '{}' ({})", FourCCPrinter{err}.c_str(), err}; /* Calculate the minimum AudioUnit output format frame count for the pre- * conversion ring buffer. Ensure at least 100ms for the total buffer. */ - double srateScale{outputFormat.mSampleRate / mDevice->Frequency}; - auto FrameCount64 = maxu64(static_cast(std::ceil(mDevice->BufferSize*srateScale)), - static_cast(outputFormat.mSampleRate)/10); + double srateScale{outputFormat.mSampleRate / mDevice->mSampleRate}; + auto FrameCount64 = std::max(static_cast(std::ceil(mDevice->mBufferSize*srateScale)), + static_cast(outputFormat.mSampleRate)/10_u64); FrameCount64 += MaxResamplerPadding; if(FrameCount64 > std::numeric_limits::max()) throw al::backend_exception{al::backend_error::DeviceError, - "Calculated frame count is too large: %" PRIu64, FrameCount64}; + "Calculated frame count is too large: {}", FrameCount64}; UInt32 outputFrameCount{}; propertySize = sizeof(outputFrameCount); @@ -873,22 +941,22 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Global, OutputElement, &outputFrameCount, &propertySize); if(err != noErr || propertySize != sizeof(outputFrameCount)) throw al::backend_exception{al::backend_error::DeviceError, - "Could not get input frame count: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "Could not get input frame count: '{}' ({})", FourCCPrinter{err}.c_str(), err}; mCaptureData.resize(outputFrameCount * mFrameSize); - outputFrameCount = static_cast(maxu64(outputFrameCount, FrameCount64)); + outputFrameCount = static_cast(std::max(uint64_t{outputFrameCount}, FrameCount64)); mRing = RingBuffer::Create(outputFrameCount, mFrameSize, false); /* Set up sample converter if needed */ - if(outputFormat.mSampleRate != mDevice->Frequency) + if(outputFormat.mSampleRate != mDevice->mSampleRate) mConverter = SampleConverter::Create(mDevice->FmtType, mDevice->FmtType, mFormat.mChannelsPerFrame, static_cast(hardwareFormat.mSampleRate), - mDevice->Frequency, Resampler::FastBSinc24); + mDevice->mSampleRate, Resampler::FastBSinc24); #if CAN_ENUMERATE if(!name.empty()) - mDevice->DeviceName = name; + mDeviceName = name; else { UInt32 propSize{sizeof(audioDevice)}; @@ -897,11 +965,11 @@ void CoreAudioCapture::open(std::string_view name) kAudioUnitScope_Global, InputElement, &audioDevice, &propSize); std::string devname{GetDeviceName(audioDevice)}; - if(!devname.empty()) mDevice->DeviceName = std::move(devname); - else mDevice->DeviceName = "Unknown Device Name"; + if(!devname.empty()) mDeviceName = std::move(devname); + else mDeviceName = "Unknown Device Name"; } #else - mDevice->DeviceName = name; + mDeviceName = name; #endif } @@ -911,35 +979,35 @@ void CoreAudioCapture::start() OSStatus err{AudioOutputUnitStart(mAudioUnit)}; if(err != noErr) throw al::backend_exception{al::backend_error::DeviceError, - "AudioOutputUnitStart failed: '%s' (%u)", FourCCPrinter{err}.c_str(), err}; + "AudioOutputUnitStart failed: '{}' ({})", FourCCPrinter{err}.c_str(), err}; } void CoreAudioCapture::stop() { OSStatus err{AudioOutputUnitStop(mAudioUnit)}; if(err != noErr) - ERR("AudioOutputUnitStop failed: '%s' (%u)\n", FourCCPrinter{err}.c_str(), err); + ERR("AudioOutputUnitStop failed: '{}' ({})", FourCCPrinter{err}.c_str(), err); } void CoreAudioCapture::captureSamples(std::byte *buffer, uint samples) { if(!mConverter) { - mRing->read(buffer, samples); + std::ignore = mRing->read(buffer, samples); return; } auto rec_vec = mRing->getReadVector(); - const void *src0{rec_vec.first.buf}; - auto src0len = static_cast(rec_vec.first.len); + const void *src0{rec_vec[0].buf}; + auto src0len = static_cast(rec_vec[0].len); uint got{mConverter->convert(&src0, &src0len, buffer, samples)}; - size_t total_read{rec_vec.first.len - src0len}; - if(got < samples && !src0len && rec_vec.second.len > 0) + size_t total_read{rec_vec[0].len - src0len}; + if(got < samples && !src0len && rec_vec[1].len > 0) { - const void *src1{rec_vec.second.buf}; - auto src1len = static_cast(rec_vec.second.len); + const void *src1{rec_vec[1].buf}; + auto src1len = static_cast(rec_vec[1].len); got += mConverter->convert(&src1, &src1len, buffer + got*mFrameSize, samples-got); - total_read += rec_vec.second.len - src1len; + total_read += rec_vec[1].len - src1len; } mRing->readAdvance(total_read); @@ -970,23 +1038,23 @@ bool CoreAudioBackendFactory::init() bool CoreAudioBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string CoreAudioBackendFactory::probe(BackendType type) +auto CoreAudioBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; #if CAN_ENUMERATE auto append_name = [&outnames](const DeviceEntry &entry) -> void - { - /* Includes null char. */ - outnames.append(entry.mName.c_str(), entry.mName.length()+1); - }; + { outnames.emplace_back(entry.mName); }; + switch(type) { case BackendType::Playback: EnumerateDevices(PlaybackList, false); + outnames.reserve(PlaybackList.size()); std::for_each(PlaybackList.cbegin(), PlaybackList.cend(), append_name); break; case BackendType::Capture: EnumerateDevices(CaptureList, true); + outnames.reserve(CaptureList.size()); std::for_each(CaptureList.cbegin(), CaptureList.cend(), append_name); break; } @@ -997,8 +1065,7 @@ std::string CoreAudioBackendFactory::probe(BackendType type) { case BackendType::Playback: case BackendType::Capture: - /* Includes null char. */ - outnames.append(ca_device, sizeof(ca_device)); + outnames.emplace_back(ca_device); break; } #endif @@ -1013,3 +1080,18 @@ BackendPtr CoreAudioBackendFactory::createBackend(DeviceBase *device, BackendTyp return BackendPtr{new CoreAudioCapture{device}}; return nullptr; } + +alc::EventSupport CoreAudioBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) +{ + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + return alc::EventSupport::FullSupport; + + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + case alc::EventType::Count: + break; + } + return alc::EventSupport::NoSupport; +} diff --git a/3rdparty/openal/alc/backends/coreaudio.h b/3rdparty/openal/alc/backends/coreaudio.h index 1252edde381c..26c2aaf98ad4 100644 --- a/3rdparty/openal/alc/backends/coreaudio.h +++ b/3rdparty/openal/alc/backends/coreaudio.h @@ -5,15 +5,17 @@ struct CoreAudioBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto queryEventSupport(alc::EventType eventType, BackendType type) -> alc::EventSupport final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - static BackendFactory &getFactory(); + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_COREAUDIO_H */ diff --git a/3rdparty/openal/alc/backends/dsound.cpp b/3rdparty/openal/alc/backends/dsound.cpp index b5596f1c8051..2bb7f5f5c3f2 100644 --- a/3rdparty/openal/alc/backends/dsound.cpp +++ b/3rdparty/openal/alc/backends/dsound.cpp @@ -35,16 +35,13 @@ #include #include #include -#include +#include +#include #include -#include -#include -#include #include #include #include -#include "albit.h" #include "alnumeric.h" #include "alspan.h" #include "althrd_setname.h" @@ -53,6 +50,7 @@ #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" +#include "fmt/core.h" #include "ringbuffer.h" #include "strutils.h" @@ -91,10 +89,7 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0 namespace { -#define DEVNAME_HEAD "OpenAL Soft on " - - -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD void *ds_handle; HRESULT (WINAPI *pDirectSoundCreate)(const GUID *pcGuidDevice, IDirectSound **ppDS, IUnknown *pUnkOuter); HRESULT (WINAPI *pDirectSoundEnumerateW)(LPDSENUMCALLBACKW pDSEnumCallback, void *pContext); @@ -147,24 +142,19 @@ BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR*, voi return TRUE; auto& devices = *static_cast*>(data); - const std::string basename{DEVNAME_HEAD + wstr_to_utf8(desc)}; + const auto basename = wstr_to_utf8(desc); - int count{1}; - std::string newname{basename}; + auto count = 1; + auto newname = basename; while(checkName(devices, newname)) - { - newname = basename; - newname += " #"; - newname += std::to_string(++count); - } - devices.emplace_back(std::move(newname), *guid); - const DevMap &newentry = devices.back(); + newname = fmt::format("{} #{}", basename, ++count); + const DevMap &newentry = devices.emplace_back(std::move(newname), *guid); OLECHAR *guidstr{nullptr}; HRESULT hr{StringFromCLSID(*guid, &guidstr)}; if(SUCCEEDED(hr)) { - TRACE("Got device \"%s\", GUID \"%ls\"\n", newentry.name.c_str(), guidstr); + TRACE("Got device \"{}\", GUID \"{}\"", newentry.name, wstr_to_utf8(guidstr)); CoTaskMemFree(guidstr); } @@ -173,7 +163,7 @@ BOOL CALLBACK DSoundEnumDevices(GUID *guid, const WCHAR *desc, const WCHAR*, voi struct DSoundPlayback final : public BackendBase { - DSoundPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit DSoundPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~DSoundPlayback() override; int mixerProc(); @@ -191,8 +181,6 @@ struct DSoundPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(DSoundPlayback) }; DSoundPlayback::~DSoundPlayback() @@ -211,21 +199,22 @@ DSoundPlayback::~DSoundPlayback() FORCE_ALIGN int DSoundPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); DSBCAPS DSBCaps{}; DSBCaps.dwSize = sizeof(DSBCaps); HRESULT err{mBuffer->GetCaps(&DSBCaps)}; if(FAILED(err)) { - ERR("Failed to get buffer caps: 0x%lx\n", err); - mDevice->handleDisconnect("Failure retrieving playback buffer info: 0x%lx", err); + ERR("Failed to get buffer caps: {:#x}", as_unsigned(err)); + mDevice->handleDisconnect("Failure retrieving playback buffer info: {:#x}", + as_unsigned(err)); return 1; } const size_t FrameStep{mDevice->channelsFromFmt()}; uint FrameSize{mDevice->frameSizeFromFmt()}; - DWORD FragSize{mDevice->UpdateSize * FrameSize}; + DWORD FragSize{mDevice->mUpdateSize * FrameSize}; bool Playing{false}; DWORD LastCursor{0u}; @@ -245,8 +234,9 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() err = mBuffer->Play(0, 0, DSBPLAY_LOOPING); if(FAILED(err)) { - ERR("Failed to play buffer: 0x%lx\n", err); - mDevice->handleDisconnect("Failure starting playback: 0x%lx", err); + ERR("Failed to play buffer: {:#x}", as_unsigned(err)); + mDevice->handleDisconnect("Failure starting playback: {:#x}", + as_unsigned(err)); return 1; } Playing = true; @@ -254,7 +244,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() avail = WaitForSingleObjectEx(mNotifyEvent, 2000, FALSE); if(avail != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", avail); + ERR("WaitForSingleObjectEx error: {:#x}", avail); continue; } avail -= avail%FragSize; @@ -267,7 +257,7 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() // If the buffer is lost, restore it and lock if(err == DSERR_BUFFERLOST) { - WARN("Buffer lost, restoring...\n"); + WARN("Buffer lost, restoring..."); err = mBuffer->Restore(); if(SUCCEEDED(err)) { @@ -277,22 +267,19 @@ FORCE_ALIGN int DSoundPlayback::mixerProc() &WritePtr2, &WriteCnt2, 0); } } - - if(SUCCEEDED(err)) + if(FAILED(err)) { - mDevice->renderSamples(WritePtr1, WriteCnt1/FrameSize, FrameStep); - if(WriteCnt2 > 0) - mDevice->renderSamples(WritePtr2, WriteCnt2/FrameSize, FrameStep); - - mBuffer->Unlock(WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); - } - else - { - ERR("Buffer lock error: %#lx\n", err); - mDevice->handleDisconnect("Failed to lock output buffer: 0x%lx", err); + ERR("Buffer lock error: {:#x}", as_unsigned(err)); + mDevice->handleDisconnect("Failed to lock output buffer: {:#x}", as_unsigned(err)); return 1; } + mDevice->renderSamples(WritePtr1, WriteCnt1/FrameSize, FrameStep); + if(WriteCnt2 > 0) + mDevice->renderSamples(WritePtr2, WriteCnt2/FrameSize, FrameStep); + + mBuffer->Unlock(WritePtr1, WriteCnt1, WritePtr2, WriteCnt2); + // Update old write cursor location LastCursor += WriteCnt1+WriteCnt2; LastCursor %= DSBCaps.dwBufferBytes; @@ -307,12 +294,10 @@ void DSoundPlayback::open(std::string_view name) if(PlaybackDevices.empty()) { /* Initialize COM to prevent name truncation */ - HRESULT hrcom{CoInitialize(nullptr)}; + ComWrapper com{}; hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); - if(SUCCEEDED(hrcom)) - CoUninitialize(); + ERR("Error enumerating DirectSound devices: {:#x}", as_unsigned(hr)); } const GUID *guid{nullptr}; @@ -334,8 +319,7 @@ void DSoundPlayback::open(std::string_view name) [&id](const DevMap &entry) -> bool { return entry.guid == id; }); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), - name.data()}; + "Device name \"{}\" not found", name}; } guid = &iter->guid; } @@ -354,15 +338,15 @@ void DSoundPlayback::open(std::string_view name) if(SUCCEEDED(hr)) hr = ds->SetCooperativeLevel(GetForegroundWindow(), DSSCL_PRIORITY); if(FAILED(hr)) - throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", - hr}; + throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: {:#x}", + as_unsigned(hr)}; mNotifies = nullptr; mBuffer = nullptr; mPrimaryBuffer = nullptr; mDS = std::move(ds); - mDevice->DeviceName = name; + mDeviceName = name; } bool DSoundPlayback::reset() @@ -397,7 +381,7 @@ bool DSoundPlayback::reset() HRESULT hr{mDS->GetSpeakerConfig(&speakers)}; if(FAILED(hr)) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to get speaker config: 0x%08lx", hr}; + "Failed to get speaker config: {:#x}", as_unsigned(hr)}; speakers = DSSPEAKER_CONFIG(speakers); if(!mDevice->Flags.test(ChannelsRequest)) @@ -413,7 +397,7 @@ bool DSoundPlayback::reset() else if(speakers == DSSPEAKER_7POINT1 || speakers == DSSPEAKER_7POINT1_SURROUND) mDevice->FmtChans = DevFmtX71; else - ERR("Unknown system speaker config: 0x%lx\n", speakers); + ERR("Unknown system speaker config: {:#x}", speakers); } mDevice->Flags.set(DirectEar, (speakers == DSSPEAKER_HEADPHONE)); const bool isRear51{speakers == DSSPEAKER_5POINT1_BACK}; @@ -428,81 +412,83 @@ bool DSoundPlayback::reset() case DevFmtX51: OutputType.dwChannelMask = isRear51 ? X5DOT1REAR : X5DOT1; break; case DevFmtX61: OutputType.dwChannelMask = X6DOT1; break; case DevFmtX71: OutputType.dwChannelMask = X7DOT1; break; + case DevFmtX7144: mDevice->FmtChans = DevFmtX714; + /* fall-through */ case DevFmtX714: OutputType.dwChannelMask = X7DOT1DOT4; break; case DevFmtX3D71: OutputType.dwChannelMask = X7DOT1; break; } -retry_open: - hr = S_OK; - OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; - OutputType.Format.nChannels = static_cast(mDevice->channelsFromFmt()); - OutputType.Format.wBitsPerSample = static_cast(mDevice->bytesFromFmt() * 8); - OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nChannels * - OutputType.Format.wBitsPerSample / 8); - OutputType.Format.nSamplesPerSec = mDevice->Frequency; - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * - OutputType.Format.nBlockAlign; - OutputType.Format.cbSize = 0; - - if(OutputType.Format.nChannels > 2 || mDevice->FmtType == DevFmtFloat) - { - OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); - if(mDevice->FmtType == DevFmtFloat) - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - else - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + do { + hr = S_OK; + OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; + OutputType.Format.nChannels = static_cast(mDevice->channelsFromFmt()); + OutputType.Format.wBitsPerSample = static_cast(mDevice->bytesFromFmt() * 8); + OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nChannels * + OutputType.Format.wBitsPerSample / 8); + OutputType.Format.nSamplesPerSec = mDevice->mSampleRate; + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * + OutputType.Format.nBlockAlign; + OutputType.Format.cbSize = 0; - mPrimaryBuffer = nullptr; - } - else - { - if(SUCCEEDED(hr) && !mPrimaryBuffer) + if(OutputType.Format.nChannels > 2 || mDevice->FmtType == DevFmtFloat) { - DSBUFFERDESC DSBDescription{}; - DSBDescription.dwSize = sizeof(DSBDescription); - DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; - hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mPrimaryBuffer), nullptr); + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); + if(mDevice->FmtType == DevFmtFloat) + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + else + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + + mPrimaryBuffer = nullptr; + } + else + { + if(SUCCEEDED(hr) && !mPrimaryBuffer) + { + DSBUFFERDESC DSBDescription{}; + DSBDescription.dwSize = sizeof(DSBDescription); + DSBDescription.dwFlags = DSBCAPS_PRIMARYBUFFER; + hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mPrimaryBuffer), nullptr); + } + if(SUCCEEDED(hr)) + hr = mPrimaryBuffer->SetFormat(&OutputType.Format); } - if(SUCCEEDED(hr)) - hr = mPrimaryBuffer->SetFormat(&OutputType.Format); - } - if(SUCCEEDED(hr)) - { - uint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; + if(FAILED(hr)) + break; + + uint num_updates{mDevice->mBufferSize / mDevice->mUpdateSize}; if(num_updates > MAX_UPDATES) num_updates = MAX_UPDATES; - mDevice->BufferSize = mDevice->UpdateSize * num_updates; + mDevice->mBufferSize = mDevice->mUpdateSize * num_updates; DSBUFFERDESC DSBDescription{}; DSBDescription.dwSize = sizeof(DSBDescription); DSBDescription.dwFlags = DSBCAPS_CTRLPOSITIONNOTIFY | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_GLOBALFOCUS; - DSBDescription.dwBufferBytes = mDevice->BufferSize * OutputType.Format.nBlockAlign; + DSBDescription.dwBufferBytes = mDevice->mBufferSize * OutputType.Format.nBlockAlign; DSBDescription.lpwfxFormat = &OutputType.Format; hr = mDS->CreateSoundBuffer(&DSBDescription, al::out_ptr(mBuffer), nullptr); - if(FAILED(hr) && mDevice->FmtType == DevFmtFloat) - { - mDevice->FmtType = DevFmtShort; - goto retry_open; - } - } + if(SUCCEEDED(hr) || mDevice->FmtType != DevFmtFloat) + break; + mDevice->FmtType = DevFmtShort; + } while(FAILED(hr)); if(SUCCEEDED(hr)) { hr = mBuffer->QueryInterface(IID_IDirectSoundNotify, al::out_ptr(mNotifies)); if(SUCCEEDED(hr)) { - uint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; + uint num_updates{mDevice->mBufferSize / mDevice->mUpdateSize}; assert(num_updates <= MAX_UPDATES); - std::array nots; + std::array nots{}; for(uint i{0};i < num_updates;++i) { - nots[i].dwOffset = i * mDevice->UpdateSize * OutputType.Format.nBlockAlign; + nots[i].dwOffset = i * mDevice->mUpdateSize * OutputType.Format.nBlockAlign; nots[i].hEventNotify = mNotifyEvent; } if(mNotifies->SetNotificationPositions(num_updates, nots.data()) != DS_OK) @@ -528,11 +514,11 @@ void DSoundPlayback::start() { try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&DSoundPlayback::mixerProc), this}; + mThread = std::thread{&DSoundPlayback::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -547,7 +533,7 @@ void DSoundPlayback::stop() struct DSoundCapture final : public BackendBase { - DSoundCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit DSoundCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~DSoundCapture() override; void open(std::string_view name) override; @@ -562,8 +548,6 @@ struct DSoundCapture final : public BackendBase { DWORD mCursor{0u}; RingBufferPtr mRing; - - DEF_NEWDEL(DSoundCapture) }; DSoundCapture::~DSoundCapture() @@ -583,12 +567,10 @@ void DSoundCapture::open(std::string_view name) if(CaptureDevices.empty()) { /* Initialize COM to prevent name truncation */ - HRESULT hrcom{CoInitialize(nullptr)}; + ComWrapper com{}; hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); if(FAILED(hr)) - ERR("Error enumerating DirectSound devices (0x%lx)!\n", hr); - if(SUCCEEDED(hrcom)) - CoUninitialize(); + ERR("Error enumerating DirectSound devices: {:#x}", as_unsigned(hr)); } const GUID *guid{nullptr}; @@ -610,8 +592,7 @@ void DSoundCapture::open(std::string_view name) [&id](const DevMap &entry) -> bool { return entry.guid == id; }); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), - name.data()}; + "Device name \"{}\" not found", name}; } guid = &iter->guid; } @@ -621,9 +602,9 @@ void DSoundCapture::open(std::string_view name) case DevFmtByte: case DevFmtUShort: case DevFmtUInt: - WARN("%s capture samples not supported\n", DevFmtTypeString(mDevice->FmtType)); + WARN("{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)); throw al::backend_exception{al::backend_error::DeviceError, - "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; + "{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; case DevFmtUByte: case DevFmtShort: @@ -642,10 +623,11 @@ void DSoundCapture::open(std::string_view name) case DevFmtX61: InputType.dwChannelMask = X6DOT1; break; case DevFmtX71: InputType.dwChannelMask = X7DOT1; break; case DevFmtX714: InputType.dwChannelMask = X7DOT1DOT4; break; + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: - WARN("%s capture not supported\n", DevFmtChannelsString(mDevice->FmtChans)); - throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported", + WARN("{} capture not supported", DevFmtChannelsString(mDevice->FmtChans)); + throw al::backend_exception{al::backend_error::DeviceError, "{} capture not supported", DevFmtChannelsString(mDevice->FmtChans)}; } @@ -654,10 +636,11 @@ void DSoundCapture::open(std::string_view name) InputType.Format.wBitsPerSample = static_cast(mDevice->bytesFromFmt() * 8); InputType.Format.nBlockAlign = static_cast(InputType.Format.nChannels * InputType.Format.wBitsPerSample / 8); - InputType.Format.nSamplesPerSec = mDevice->Frequency; + InputType.Format.nSamplesPerSec = mDevice->mSampleRate; InputType.Format.nAvgBytesPerSec = InputType.Format.nSamplesPerSec * InputType.Format.nBlockAlign; InputType.Format.cbSize = 0; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample; if(mDevice->FmtType == DevFmtFloat) InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; @@ -670,8 +653,7 @@ void DSoundCapture::open(std::string_view name) InputType.Format.cbSize = sizeof(WAVEFORMATEXTENSIBLE) - sizeof(WAVEFORMATEX); } - uint samples{mDevice->BufferSize}; - samples = maxu(samples, 100 * mDevice->Frequency / 1000); + const uint samples{std::max(mDevice->mBufferSize, mDevice->mSampleRate/10u)}; DSCBUFFERDESC DSCBDescription{}; DSCBDescription.dwSize = sizeof(DSCBDescription); @@ -684,7 +666,7 @@ void DSoundCapture::open(std::string_view name) if(SUCCEEDED(hr)) mDSC->CreateCaptureBuffer(&DSCBDescription, al::out_ptr(mDSCbuffer), nullptr); if(SUCCEEDED(hr)) - mRing = RingBuffer::Create(mDevice->BufferSize, InputType.Format.nBlockAlign, false); + mRing = RingBuffer::Create(mDevice->mBufferSize, InputType.Format.nBlockAlign, false); if(FAILED(hr)) { @@ -692,14 +674,14 @@ void DSoundCapture::open(std::string_view name) mDSCbuffer = nullptr; mDSC = nullptr; - throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", - hr}; + throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: {:#x}", + as_unsigned(hr)}; } mBufferBytes = DSCBDescription.dwBufferBytes; setDefaultWFXChannelOrder(); - mDevice->DeviceName = name; + mDeviceName = name; } void DSoundCapture::start() @@ -707,7 +689,7 @@ void DSoundCapture::start() const HRESULT hr{mDSCbuffer->Start(DSCBSTART_LOOPING)}; if(FAILED(hr)) throw al::backend_exception{al::backend_error::DeviceError, - "Failure starting capture: 0x%lx", hr}; + "Failure starting capture: {:#x}", as_unsigned(hr)}; } void DSoundCapture::stop() @@ -715,13 +697,13 @@ void DSoundCapture::stop() HRESULT hr{mDSCbuffer->Stop()}; if(FAILED(hr)) { - ERR("stop failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("Failure stopping capture: 0x%lx", hr); + ERR("stop failed: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failure stopping capture: {:#x}", as_unsigned(hr)); } } void DSoundCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } uint DSoundCapture::availableSamples() { @@ -744,17 +726,17 @@ uint DSoundCapture::availableSamples() } if(SUCCEEDED(hr)) { - mRing->write(ReadPtr1, ReadCnt1/FrameSize); + std::ignore = mRing->write(ReadPtr1, ReadCnt1/FrameSize); if(ReadPtr2 != nullptr && ReadCnt2 > 0) - mRing->write(ReadPtr2, ReadCnt2/FrameSize); + std::ignore = mRing->write(ReadPtr2, ReadCnt2/FrameSize); hr = mDSCbuffer->Unlock(ReadPtr1, ReadCnt1, ReadPtr2, ReadCnt2); mCursor = ReadCursor; } if(FAILED(hr)) { - ERR("update failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("Failure retrieving capture data: 0x%lx", hr); + ERR("update failed: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failure retrieving capture data: {:#x}", as_unsigned(hr)); } return static_cast(mRing->readSpace()); @@ -771,18 +753,18 @@ BackendFactory &DSoundBackendFactory::getFactory() bool DSoundBackendFactory::init() { -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD if(!ds_handle) { ds_handle = LoadLib("dsound.dll"); if(!ds_handle) { - ERR("Failed to load dsound.dll\n"); + ERR("Failed to load dsound.dll"); return false; } #define LOAD_FUNC(f) do { \ - p##f = al::bit_cast(GetSymbol(ds_handle, #f)); \ + p##f = reinterpret_cast(GetSymbol(ds_handle, #f)); \ if(!p##f) \ { \ CloseLib(ds_handle); \ @@ -803,40 +785,32 @@ bool DSoundBackendFactory::init() bool DSoundBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string DSoundBackendFactory::probe(BackendType type) +auto DSoundBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; auto add_device = [&outnames](const DevMap &entry) -> void - { - /* +1 to also append the null char (to ensure a null-separated list and - * double-null terminated list). - */ - outnames.append(entry.name.c_str(), entry.name.length()+1); - }; + { outnames.emplace_back(entry.name); }; /* Initialize COM to prevent name truncation */ - HRESULT hr; - HRESULT hrcom{CoInitialize(nullptr)}; + ComWrapper com{}; switch(type) { case BackendType::Playback: PlaybackDevices.clear(); - hr = DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices); - if(FAILED(hr)) - ERR("Error enumerating DirectSound playback devices (0x%lx)!\n", hr); + if(HRESULT hr{DirectSoundEnumerateW(DSoundEnumDevices, &PlaybackDevices)}; FAILED(hr)) + ERR("Error enumerating DirectSound playback devices: {:#x}", as_unsigned(hr)); + outnames.reserve(PlaybackDevices.size()); std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device); break; case BackendType::Capture: CaptureDevices.clear(); - hr = DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices); - if(FAILED(hr)) - ERR("Error enumerating DirectSound capture devices (0x%lx)!\n", hr); + if(HRESULT hr{DirectSoundCaptureEnumerateW(DSoundEnumDevices, &CaptureDevices)};FAILED(hr)) + ERR("Error enumerating DirectSound capture devices: {:#x}", as_unsigned(hr)); + outnames.reserve(CaptureDevices.size()); std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); break; } - if(SUCCEEDED(hrcom)) - CoUninitialize(); return outnames; } diff --git a/3rdparty/openal/alc/backends/dsound.h b/3rdparty/openal/alc/backends/dsound.h index 787f227a0a20..33adbf2971fe 100644 --- a/3rdparty/openal/alc/backends/dsound.h +++ b/3rdparty/openal/alc/backends/dsound.h @@ -5,15 +5,15 @@ struct DSoundBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_DSOUND_H */ diff --git a/3rdparty/openal/alc/backends/jack.cpp b/3rdparty/openal/alc/backends/jack.cpp index a0a5c4402f72..fb84287f7f04 100644 --- a/3rdparty/openal/alc/backends/jack.cpp +++ b/3rdparty/openal/alc/backends/jack.cpp @@ -29,10 +29,8 @@ #include #include #include -#include #include -#include "albit.h" #include "alc/alconfig.h" #include "alnumeric.h" #include "alsem.h" @@ -41,6 +39,7 @@ #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" +#include "fmt/format.h" #include "ringbuffer.h" #include @@ -49,7 +48,9 @@ namespace { -#ifdef HAVE_DYNLOAD +using namespace std::string_view_literals; + +#if HAVE_DYNLOAD #define JACK_FUNCS(MAGIC) \ MAGIC(jack_client_open); \ MAGIC(jack_client_close); \ @@ -102,20 +103,16 @@ decltype(jack_error_callback) * pjack_error_callback; #endif -constexpr char JackDefaultAudioType[] = JACK_DEFAULT_AUDIO_TYPE; - jack_options_t ClientOptions = JackNullOption; bool jack_load() { - bool error{false}; - -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD if(!jack_handle) { - std::string missing_funcs; - -#ifdef _WIN32 +#if defined(_WIN64) +#define JACKLIB "libjack64.dll" +#elif defined(_WIN32) #define JACKLIB "libjack.dll" #else #define JACKLIB "libjack.so.0" @@ -123,52 +120,58 @@ bool jack_load() jack_handle = LoadLib(JACKLIB); if(!jack_handle) { - WARN("Failed to load %s\n", JACKLIB); + WARN("Failed to load {}", JACKLIB); return false; } - error = false; + std::string missing_funcs; #define LOAD_FUNC(f) do { \ - p##f = al::bit_cast(GetSymbol(jack_handle, #f)); \ - if(p##f == nullptr) { \ - error = true; \ - missing_funcs += "\n" #f; \ - } \ + p##f = reinterpret_cast(GetSymbol(jack_handle, #f)); \ + if(p##f == nullptr) missing_funcs += "\n" #f; \ } while(0) JACK_FUNCS(LOAD_FUNC); #undef LOAD_FUNC /* Optional symbols. These don't exist in all versions of JACK. */ -#define LOAD_SYM(f) p##f = al::bit_cast(GetSymbol(jack_handle, #f)) +#define LOAD_SYM(f) p##f = reinterpret_cast(GetSymbol(jack_handle, #f)) LOAD_SYM(jack_error_callback); #undef LOAD_SYM - if(error) + if(!missing_funcs.empty()) { - WARN("Missing expected functions:%s\n", missing_funcs.c_str()); + WARN("Missing expected functions:{}", missing_funcs); CloseLib(jack_handle); jack_handle = nullptr; + return false; } } #endif - return !error; + return true; } struct JackDeleter { void operator()(void *ptr) { jack_free(ptr); } }; -using JackPortsPtr = std::unique_ptr; +using JackPortsPtr = std::unique_ptr; /* NOLINT(*-avoid-c-arrays) */ struct DeviceEntry { std::string mName; std::string mPattern; + DeviceEntry() = default; + DeviceEntry(const DeviceEntry&) = default; + DeviceEntry(DeviceEntry&&) = default; template DeviceEntry(T&& name, U&& pattern) : mName{std::forward(name)}, mPattern{std::forward(pattern)} { } + ~DeviceEntry(); + + DeviceEntry& operator=(const DeviceEntry&) = default; + DeviceEntry& operator=(DeviceEntry&&) = default; }; +DeviceEntry::~DeviceEntry() = default; std::vector PlaybackList; @@ -177,39 +180,35 @@ void EnumerateDevices(jack_client_t *client, std::vector &list) { std::remove_reference_t{}.swap(list); - if(JackPortsPtr ports{jack_get_ports(client, nullptr, JackDefaultAudioType, JackPortIsInput)}) + if(JackPortsPtr ports{jack_get_ports(client, nullptr, JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput)}) { for(size_t i{0};ports[i];++i) { - const char *sep{std::strchr(ports[i], ':')}; - if(!sep || ports[i] == sep) continue; + const std::string_view portname{ports[i]}; + const size_t seppos{portname.find(':')}; + if(seppos == 0 || seppos >= portname.size()) + continue; - const al::span portdev{ports[i], sep}; + const auto portdev = portname.substr(0, seppos); auto check_name = [portdev](const DeviceEntry &entry) -> bool - { - const size_t len{portdev.size()}; - return entry.mName.length() == len - && entry.mName.compare(0, len, portdev.data(), len) == 0; - }; + { return entry.mName == portdev; }; if(std::find_if(list.cbegin(), list.cend(), check_name) != list.cend()) continue; - std::string name{portdev.data(), portdev.size()}; - list.emplace_back(name, name+":"); - const auto &entry = list.back(); - TRACE("Got device: %s = %s\n", entry.mName.c_str(), entry.mPattern.c_str()); + const auto &entry = list.emplace_back(portdev, fmt::format("{}:", portdev)); + TRACE("Got device: {} = {}", entry.mName, entry.mPattern); } /* There are ports but couldn't get device names from them. Add a * generic entry. */ if(ports[0] && list.empty()) { - WARN("No device names found in available ports, adding a generic name.\n"); - list.emplace_back("JACK", ""); + WARN("No device names found in available ports, adding a generic name."); + list.emplace_back("JACK"sv, ""sv); } } - if(auto listopt = ConfigValueStr(nullptr, "jack", "custom-devices")) + if(auto listopt = ConfigValueStr({}, "jack", "custom-devices")) { for(size_t strpos{0};strpos < listopt->size();) { @@ -217,39 +216,32 @@ void EnumerateDevices(jack_client_t *client, std::vector &list) size_t seppos{listopt->find('=', strpos)}; if(seppos >= nextpos || seppos == strpos) { - const std::string entry{listopt->substr(strpos, nextpos-strpos)}; - ERR("Invalid device entry: \"%s\"\n", entry.c_str()); + const auto entry = std::string_view{*listopt}.substr(strpos, nextpos-strpos); + ERR("Invalid device entry: \"{}\"", entry); if(nextpos != std::string::npos) ++nextpos; strpos = nextpos; continue; } - const al::span name{listopt->data()+strpos, seppos-strpos}; - const al::span pattern{listopt->data()+(seppos+1), - std::min(nextpos, listopt->size())-(seppos+1)}; + const auto name = std::string_view{*listopt}.substr(strpos, seppos-strpos); + const auto pattern = std::string_view{*listopt}.substr(seppos+1, + std::min(nextpos, listopt->size())-(seppos+1)); /* Check if this custom pattern already exists in the list. */ auto check_pattern = [pattern](const DeviceEntry &entry) -> bool - { - const size_t len{pattern.size()}; - return entry.mPattern.length() == len - && entry.mPattern.compare(0, len, pattern.data(), len) == 0; - }; + { return entry.mPattern == pattern; }; auto itemmatch = std::find_if(list.begin(), list.end(), check_pattern); if(itemmatch != list.end()) { /* If so, replace the name with this custom one. */ - itemmatch->mName.assign(name.data(), name.size()); - TRACE("Customized device name: %s = %s\n", itemmatch->mName.c_str(), - itemmatch->mPattern.c_str()); + itemmatch->mName = name; + TRACE("Customized device name: {} = {}", itemmatch->mName, itemmatch->mPattern); } else { /* Otherwise, add a new device entry. */ - list.emplace_back(std::string{name.data(), name.size()}, - std::string{pattern.data(), pattern.size()}); - const auto &entry = list.back(); - TRACE("Got custom device: %s = %s\n", entry.mName.c_str(), entry.mPattern.c_str()); + const auto &entry = list.emplace_back(name, pattern); + TRACE("Got custom device: {} = {}", entry.mName, entry.mPattern); } if(nextpos != std::string::npos) ++nextpos; @@ -285,7 +277,7 @@ void EnumerateDevices(jack_client_t *client, std::vector &list) struct JackPlayback final : public BackendBase { - JackPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit JackPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~JackPlayback() override; int processRt(jack_nframes_t numframes) noexcept; @@ -307,7 +299,7 @@ struct JackPlayback final : public BackendBase { std::string mPortPattern; jack_client_t *mClient{nullptr}; - std::array mPort{}; + std::array mPort{}; std::mutex mMutex; @@ -318,8 +310,6 @@ struct JackPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(JackPlayback) }; JackPlayback::~JackPlayback() @@ -339,22 +329,22 @@ JackPlayback::~JackPlayback() int JackPlayback::processRt(jack_nframes_t numframes) noexcept { - std::array out; - size_t numchans{0}; + auto outptrs = std::array{}; + auto numchans = size_t{0}; for(auto port : mPort) { if(!port || numchans == mDevice->RealOut.Buffer.size()) break; - out[numchans++] = static_cast(jack_port_get_buffer(port, numframes)); + outptrs[numchans++] = jack_port_get_buffer(port, numframes); } + const auto dst = al::span{outptrs}.first(numchans); if(mPlaying.load(std::memory_order_acquire)) LIKELY - mDevice->renderSamples({out.data(), numchans}, static_cast(numframes)); + mDevice->renderSamples(dst, static_cast(numframes)); else { - auto clear_buf = [numframes](float *outbuf) -> void - { std::fill_n(outbuf, numframes, 0.0f); }; - std::for_each(out.begin(), out.begin()+numchans, clear_buf); + std::for_each(dst.begin(), dst.end(), [numframes](void *outbuf) -> void + { std::fill_n(static_cast(outbuf), numframes, 0.0f); }); } return 0; @@ -363,53 +353,46 @@ int JackPlayback::processRt(jack_nframes_t numframes) noexcept int JackPlayback::process(jack_nframes_t numframes) noexcept { - std::array out; + std::array,MaxOutputChannels> out; size_t numchans{0}; for(auto port : mPort) { if(!port) break; - out[numchans++] = static_cast(jack_port_get_buffer(port, numframes)); + out[numchans++] = {static_cast(jack_port_get_buffer(port, numframes)), numframes}; } - jack_nframes_t total{0}; + size_t total{0}; if(mPlaying.load(std::memory_order_acquire)) LIKELY { auto data = mRing->getReadVector(); - jack_nframes_t todo{minu(numframes, static_cast(data.first.len))}; - auto write_first = [&data,numchans,todo](float *outbuf) -> float* + const auto update_size = size_t{mDevice->mUpdateSize}; + + const auto outlen = size_t{numframes / update_size}; + const auto len1 = size_t{std::min(data[0].len/update_size, outlen)}; + const auto len2 = size_t{std::min(data[1].len/update_size, outlen-len1)}; + + auto src = al::span{reinterpret_cast(data[0].buf), update_size*len1*numchans}; + for(size_t i{0};i < len1;++i) { - const float *RESTRICT in = reinterpret_cast(data.first.buf); - auto deinterlace_input = [&in,numchans]() noexcept -> float + for(size_t c{0};c < numchans;++c) { - float ret{*in}; - in += numchans; - return ret; - }; - std::generate_n(outbuf, todo, deinterlace_input); - data.first.buf += sizeof(float); - return outbuf + todo; - }; - std::transform(out.begin(), out.begin()+numchans, out.begin(), write_first); - total += todo; - - todo = minu(numframes-total, static_cast(data.second.len)); - if(todo > 0) + const auto iter = std::copy_n(src.begin(), update_size, out[c].begin()); + out[c] = {iter, out[c].end()}; + src = src.subspan(update_size); + } + total += update_size; + } + + src = al::span{reinterpret_cast(data[1].buf), update_size*len2*numchans}; + for(size_t i{0};i < len2;++i) { - auto write_second = [&data,numchans,todo](float *outbuf) -> float* + for(size_t c{0};c < numchans;++c) { - const float *RESTRICT in = reinterpret_cast(data.second.buf); - auto deinterlace_input = [&in,numchans]() noexcept -> float - { - float ret{*in}; - in += numchans; - return ret; - }; - std::generate_n(outbuf, todo, deinterlace_input); - data.second.buf += sizeof(float); - return outbuf + todo; - }; - std::transform(out.begin(), out.begin()+numchans, out.begin(), write_second); - total += todo; + const auto iter = std::copy_n(src.begin(), update_size, out[c].begin()); + out[c] = {iter, out[c].end()}; + src = src.subspan(update_size); + } + total += update_size; } mRing->readAdvance(total); @@ -418,8 +401,8 @@ int JackPlayback::process(jack_nframes_t numframes) noexcept if(numframes > total) { - const jack_nframes_t todo{numframes - total}; - auto clear_buf = [todo](float *outbuf) -> void { std::fill_n(outbuf, todo, 0.0f); }; + auto clear_buf = [](const al::span outbuf) -> void + { std::fill(outbuf.begin(), outbuf.end(), 0.0f); }; std::for_each(out.begin(), out.begin()+numchans, clear_buf); } @@ -429,31 +412,54 @@ int JackPlayback::process(jack_nframes_t numframes) noexcept int JackPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); - const size_t frame_step{mDevice->channelsFromFmt()}; + const auto update_size = uint{mDevice->mUpdateSize}; + const auto num_channels = size_t{mDevice->channelsFromFmt()}; + auto outptrs = std::vector(num_channels); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) { - if(mRing->writeSpace() < mDevice->UpdateSize) + if(mRing->writeSpace() < update_size) { mSem.wait(); continue; } auto data = mRing->getWriteVector(); - size_t todo{data.first.len + data.second.len}; - todo -= todo%mDevice->UpdateSize; + const auto len1 = size_t{data[0].len / update_size}; + const auto len2 = size_t{data[1].len / update_size}; - const auto len1 = static_cast(minz(data.first.len, todo)); - const auto len2 = static_cast(minz(data.second.len, todo-len1)); - - std::lock_guard _{mMutex}; - mDevice->renderSamples(data.first.buf, len1, frame_step); + std::lock_guard dlock{mMutex}; + auto buffer = al::span{reinterpret_cast(data[0].buf), data[0].len*num_channels}; + auto bufiter = buffer.begin(); + for(size_t i{0};i < len1;++i) + { + std::generate_n(outptrs.begin(), outptrs.size(), [&bufiter,update_size] + { + auto ret = al::to_address(bufiter); + bufiter += ptrdiff_t(update_size); + return ret; + }); + mDevice->renderSamples(outptrs, update_size); + } if(len2 > 0) - mDevice->renderSamples(data.second.buf, len2, frame_step); - mRing->writeAdvance(todo); + { + buffer = al::span{reinterpret_cast(data[1].buf), data[1].len*num_channels}; + bufiter = buffer.begin(); + for(size_t i{0};i < len2;++i) + { + std::generate_n(outptrs.begin(), outptrs.size(), [&bufiter,update_size] + { + auto ret = al::to_address(bufiter); + bufiter += ptrdiff_t(update_size); + return ret; + }); + mDevice->renderSamples(outptrs, update_size); + } + } + mRing->writeAdvance((len1+len2) * update_size); } return 0; @@ -467,17 +473,18 @@ void JackPlayback::open(std::string_view name) const PathNamePair &binname = GetProcBinary(); const char *client_name{binname.fname.empty() ? "alsoft" : binname.fname.c_str()}; - jack_status_t status; + jack_status_t status{}; mClient = jack_client_open(client_name, ClientOptions, &status, nullptr); if(mClient == nullptr) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to open client connection: 0x%02x", status}; + "Failed to open client connection: {:#02x}", + as_unsigned(al::to_underlying(status))}; if((status&JackServerStarted)) - TRACE("JACK server started\n"); + TRACE("JACK server started"); if((status&JackNameNotUnique)) { client_name = jack_get_client_name(mClient); - TRACE("Client name not unique, got '%s' instead\n", client_name); + TRACE("Client name not unique, got '{}' instead", client_name); } } @@ -496,11 +503,11 @@ void JackPlayback::open(std::string_view name) auto iter = std::find_if(PlaybackList.cbegin(), PlaybackList.cend(), check_name); if(iter == PlaybackList.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; mPortPattern = iter->mPattern; } - mDevice->DeviceName = name; + mDeviceName = name; } bool JackPlayback::reset() @@ -510,55 +517,56 @@ bool JackPlayback::reset() std::for_each(mPort.begin(), mPort.end(), unregister_port); mPort.fill(nullptr); - mRTMixing = GetConfigValueBool(mDevice->DeviceName.c_str(), "jack", "rt-mix", true); + mRTMixing = GetConfigValueBool(mDevice->mDeviceName, "jack", "rt-mix", true); jack_set_process_callback(mClient, mRTMixing ? &JackPlayback::processRtC : &JackPlayback::processC, this); /* Ignore the requested buffer metrics and just keep one JACK-sized buffer * ready for when requested. */ - mDevice->Frequency = jack_get_sample_rate(mClient); - mDevice->UpdateSize = jack_get_buffer_size(mClient); + mDevice->mSampleRate = jack_get_sample_rate(mClient); + mDevice->mUpdateSize = jack_get_buffer_size(mClient); if(mRTMixing) { /* Assume only two periods when directly mixing. Should try to query * the total port latency when connected. */ - mDevice->BufferSize = mDevice->UpdateSize * 2; + mDevice->mBufferSize = mDevice->mUpdateSize * 2; } else { - const char *devname{mDevice->DeviceName.c_str()}; - uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)}; - bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize); - mDevice->BufferSize = bufsize + mDevice->UpdateSize; + const auto devname = std::string_view{mDevice->mDeviceName}; + auto bufsize = ConfigValueUInt(devname, "jack", "buffer-size") + .value_or(mDevice->mUpdateSize); + bufsize = std::max(NextPowerOf2(bufsize), mDevice->mUpdateSize); + mDevice->mBufferSize = bufsize + mDevice->mUpdateSize; } /* Force 32-bit float output. */ mDevice->FmtType = DevFmtFloat; int port_num{0}; - auto ports_end = mPort.begin() + mDevice->channelsFromFmt(); - auto bad_port = mPort.begin(); - while(bad_port != ports_end) + auto ports = al::span{mPort}.first(mDevice->channelsFromFmt()); + auto bad_port = ports.begin(); + while(bad_port != ports.end()) { std::string name{"channel_" + std::to_string(++port_num)}; - *bad_port = jack_port_register(mClient, name.c_str(), JackDefaultAudioType, + *bad_port = jack_port_register(mClient, name.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsOutput | JackPortIsTerminal, 0); if(!*bad_port) break; ++bad_port; } - if(bad_port != ports_end) + if(bad_port != ports.end()) { - ERR("Failed to register enough JACK ports for %s output\n", + ERR("Failed to register enough JACK ports for {} output", DevFmtChannelsString(mDevice->FmtChans)); - if(bad_port == mPort.begin()) return false; + if(bad_port == ports.begin()) return false; - if(bad_port == mPort.begin()+1) + if(bad_port == ports.begin()+1) mDevice->FmtChans = DevFmtMono; else { - ports_end = mPort.begin()+2; + const auto ports_end = ports.begin()+2; while(bad_port != ports_end) { jack_port_unregister(mClient, *(--bad_port)); @@ -578,10 +586,10 @@ void JackPlayback::start() if(jack_activate(mClient)) throw al::backend_exception{al::backend_error::DeviceError, "Failed to activate client"}; - const char *devname{mDevice->DeviceName.c_str()}; + const auto devname = std::string_view{mDevice->mDeviceName}; if(ConfigValueBool(devname, "jack", "connect-ports").value_or(true)) { - JackPortsPtr pnames{jack_get_ports(mClient, mPortPattern.c_str(), JackDefaultAudioType, + JackPortsPtr pnames{jack_get_ports(mClient, mPortPattern.c_str(), JACK_DEFAULT_AUDIO_TYPE, JackPortIsInput)}; if(!pnames) { @@ -593,11 +601,11 @@ void JackPlayback::start() { if(!pnames[i]) { - ERR("No physical playback port for \"%s\"\n", jack_port_name(mPort[i])); + ERR("No physical playback port for \"{}\"", jack_port_name(mPort[i])); break; } if(jack_connect(mClient, jack_port_name(mPort[i]), pnames[i])) - ERR("Failed to connect output port \"%s\" to \"%s\"\n", jack_port_name(mPort[i]), + ERR("Failed to connect output port \"{}\" to \"{}\"", jack_port_name(mPort[i]), pnames[i]); } } @@ -606,31 +614,32 @@ void JackPlayback::start() * (it won't change again after jack_activate), then allocate the ring * buffer with the appropriate size. */ - mDevice->Frequency = jack_get_sample_rate(mClient); - mDevice->UpdateSize = jack_get_buffer_size(mClient); - mDevice->BufferSize = mDevice->UpdateSize * 2; + mDevice->mSampleRate = jack_get_sample_rate(mClient); + mDevice->mUpdateSize = jack_get_buffer_size(mClient); + mDevice->mBufferSize = mDevice->mUpdateSize * 2; mRing = nullptr; if(mRTMixing) mPlaying.store(true, std::memory_order_release); else { - uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size").value_or(mDevice->UpdateSize)}; - bufsize = maxu(NextPowerOf2(bufsize), mDevice->UpdateSize); - mDevice->BufferSize = bufsize + mDevice->UpdateSize; + uint bufsize{ConfigValueUInt(devname, "jack", "buffer-size") + .value_or(mDevice->mUpdateSize)}; + bufsize = std::max(NextPowerOf2(bufsize), mDevice->mUpdateSize); + mDevice->mBufferSize = bufsize + mDevice->mUpdateSize; mRing = RingBuffer::Create(bufsize, mDevice->frameSizeFromFmt(), true); try { mPlaying.store(true, std::memory_order_release); mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&JackPlayback::mixerProc), this}; + mThread = std::thread{&JackPlayback::mixerProc, this}; } catch(std::exception& e) { jack_deactivate(mClient); mPlaying.store(false, std::memory_order_release); throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } } @@ -654,12 +663,11 @@ void JackPlayback::stop() ClockLatency JackPlayback::getClockLatency() { - ClockLatency ret; - - std::lock_guard _{mMutex}; - ret.ClockTime = GetDeviceClockTime(mDevice); - ret.Latency = std::chrono::seconds{mRing ? mRing->readSpace() : mDevice->UpdateSize}; - ret.Latency /= mDevice->Frequency; + std::lock_guard dlock{mMutex}; + ClockLatency ret{}; + ret.ClockTime = mDevice->getClockTime(); + ret.Latency = std::chrono::seconds{mRing ? mRing->readSpace() : mDevice->mUpdateSize}; + ret.Latency /= mDevice->mSampleRate; return ret; } @@ -667,7 +675,7 @@ ClockLatency JackPlayback::getClockLatency() void jack_msg_handler(const char *message) { - WARN("%s\n", message); + WARN("{}", message); } } // namespace @@ -677,7 +685,7 @@ bool JackBackendFactory::init() if(!jack_load()) return false; - if(!GetConfigValueBool(nullptr, "jack", "spawn-server", false)) + if(!GetConfigValueBool({}, "jack", "spawn-server", false)) ClientOptions = static_cast(ClientOptions | JackNoStartServer); const PathNamePair &binname = GetProcBinary(); @@ -685,14 +693,14 @@ bool JackBackendFactory::init() void (*old_error_cb)(const char*){&jack_error_callback ? jack_error_callback : nullptr}; jack_set_error_function(jack_msg_handler); - jack_status_t status; + jack_status_t status{}; jack_client_t *client{jack_client_open(client_name, ClientOptions, &status, nullptr)}; jack_set_error_function(old_error_cb); if(!client) { - WARN("jack_client_open() failed, 0x%02x\n", status); + WARN("jack_client_open() failed, {:#02x}", as_unsigned(al::to_underlying(status))); if((status&JackServerFailed) && !(ClientOptions&JackNoStartServer)) - ERR("Unable to connect to JACK server\n"); + ERR("Unable to connect to JACK server"); return false; } @@ -703,18 +711,15 @@ bool JackBackendFactory::init() bool JackBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback); } -std::string JackBackendFactory::probe(BackendType type) +auto JackBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; auto append_name = [&outnames](const DeviceEntry &entry) -> void - { - /* Includes null char. */ - outnames.append(entry.mName.c_str(), entry.mName.length()+1); - }; + { outnames.emplace_back(entry.mName); }; const PathNamePair &binname = GetProcBinary(); const char *client_name{binname.fname.empty() ? "alsoft" : binname.fname.c_str()}; - jack_status_t status; + jack_status_t status{}; switch(type) { case BackendType::Playback: @@ -724,7 +729,8 @@ std::string JackBackendFactory::probe(BackendType type) jack_client_close(client); } else - WARN("jack_client_open() failed, 0x%02x\n", status); + WARN("jack_client_open() failed, {:#02x}", as_unsigned(al::to_underlying(status))); + outnames.reserve(PlaybackList.size()); std::for_each(PlaybackList.cbegin(), PlaybackList.cend(), append_name); break; case BackendType::Capture: diff --git a/3rdparty/openal/alc/backends/jack.h b/3rdparty/openal/alc/backends/jack.h index b83f24dda16f..1e4c9f05b1f4 100644 --- a/3rdparty/openal/alc/backends/jack.h +++ b/3rdparty/openal/alc/backends/jack.h @@ -5,15 +5,15 @@ struct JackBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_JACK_H */ diff --git a/3rdparty/openal/alc/backends/loopback.cpp b/3rdparty/openal/alc/backends/loopback.cpp index 2972fc0145d1..66b58bc23b34 100644 --- a/3rdparty/openal/alc/backends/loopback.cpp +++ b/3rdparty/openal/alc/backends/loopback.cpp @@ -28,20 +28,18 @@ namespace { struct LoopbackBackend final : public BackendBase { - LoopbackBackend(DeviceBase *device) noexcept : BackendBase{device} { } + explicit LoopbackBackend(DeviceBase *device) noexcept : BackendBase{device} { } void open(std::string_view name) override; bool reset() override; void start() override; void stop() override; - - DEF_NEWDEL(LoopbackBackend) }; void LoopbackBackend::open(std::string_view name) { - mDevice->DeviceName = name; + mDeviceName = name; } bool LoopbackBackend::reset() @@ -65,8 +63,8 @@ bool LoopbackBackendFactory::init() bool LoopbackBackendFactory::querySupport(BackendType) { return true; } -std::string LoopbackBackendFactory::probe(BackendType) -{ return std::string{}; } +auto LoopbackBackendFactory::enumerate(BackendType) -> std::vector +{ return {}; } BackendPtr LoopbackBackendFactory::createBackend(DeviceBase *device, BackendType) { return BackendPtr{new LoopbackBackend{device}}; } diff --git a/3rdparty/openal/alc/backends/loopback.h b/3rdparty/openal/alc/backends/loopback.h index cb42b3c8e81b..876a052cb566 100644 --- a/3rdparty/openal/alc/backends/loopback.h +++ b/3rdparty/openal/alc/backends/loopback.h @@ -5,15 +5,15 @@ struct LoopbackBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_LOOPBACK_H */ diff --git a/3rdparty/openal/alc/backends/null.cpp b/3rdparty/openal/alc/backends/null.cpp index 3c68e4cec9a8..25511d7fe182 100644 --- a/3rdparty/openal/alc/backends/null.cpp +++ b/3rdparty/openal/alc/backends/null.cpp @@ -27,11 +27,9 @@ #include #include #include -#include #include #include "althrd_setname.h" -#include "almalloc.h" #include "core/device.h" #include "core/helpers.h" @@ -41,12 +39,13 @@ namespace { using std::chrono::seconds; using std::chrono::milliseconds; using std::chrono::nanoseconds; +using namespace std::string_view_literals; -constexpr char nullDevice[] = "No Output"; +[[nodiscard]] constexpr auto GetDeviceName() noexcept { return "No Output"sv; } struct NullBackend final : public BackendBase { - NullBackend(DeviceBase *device) noexcept : BackendBase{device} { } + explicit NullBackend(DeviceBase *device) noexcept : BackendBase{device} { } int mixerProc(); @@ -57,16 +56,14 @@ struct NullBackend final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(NullBackend) }; int NullBackend::mixerProc() { - const milliseconds restTime{mDevice->UpdateSize*1000/mDevice->Frequency / 2}; + const milliseconds restTime{mDevice->mUpdateSize*1000/mDevice->mSampleRate / 2}; SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); int64_t done{0}; auto start = std::chrono::steady_clock::now(); @@ -76,16 +73,17 @@ int NullBackend::mixerProc() auto now = std::chrono::steady_clock::now(); /* This converts from nanoseconds to nanosamples, then to samples. */ - int64_t avail{std::chrono::duration_cast((now-start) * mDevice->Frequency).count()}; - if(avail-done < mDevice->UpdateSize) + const auto avail = int64_t{std::chrono::duration_cast((now-start) + * mDevice->mSampleRate).count()}; + if(avail-done < mDevice->mUpdateSize) { std::this_thread::sleep_for(restTime); continue; } - while(avail-done >= mDevice->UpdateSize) + while(avail-done >= mDevice->mUpdateSize) { - mDevice->renderSamples(nullptr, mDevice->UpdateSize, 0u); - done += mDevice->UpdateSize; + mDevice->renderSamples(nullptr, mDevice->mUpdateSize, 0u); + done += mDevice->mUpdateSize; } /* For every completed second, increment the start time and reduce the @@ -93,11 +91,11 @@ int NullBackend::mixerProc() * and current time from growing too large, while maintaining the * correct number of samples to render. */ - if(done >= mDevice->Frequency) + if(done >= mDevice->mSampleRate) { - seconds s{done/mDevice->Frequency}; + seconds s{done/mDevice->mSampleRate}; start += s; - done -= mDevice->Frequency*s.count(); + done -= mDevice->mSampleRate*s.count(); } } @@ -108,12 +106,12 @@ int NullBackend::mixerProc() void NullBackend::open(std::string_view name) { if(name.empty()) - name = nullDevice; - else if(name != nullDevice) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; - mDevice->DeviceName = name; + mDeviceName = name; } bool NullBackend::reset() @@ -126,11 +124,11 @@ void NullBackend::start() { try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&NullBackend::mixerProc), this}; + mThread = std::thread{&NullBackend::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -150,19 +148,17 @@ bool NullBackendFactory::init() bool NullBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback); } -std::string NullBackendFactory::probe(BackendType type) +auto NullBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; switch(type) { case BackendType::Playback: - /* Includes null char. */ - outnames.append(nullDevice, sizeof(nullDevice)); - break; + /* Include null char. */ + return std::vector{std::string{GetDeviceName()}}; case BackendType::Capture: break; } - return outnames; + return {}; } BackendPtr NullBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/null.h b/3rdparty/openal/alc/backends/null.h index 7048cad6f09a..213842af7e51 100644 --- a/3rdparty/openal/alc/backends/null.h +++ b/3rdparty/openal/alc/backends/null.h @@ -5,15 +5,15 @@ struct NullBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_NULL_H */ diff --git a/3rdparty/openal/alc/backends/oboe.cpp b/3rdparty/openal/alc/backends/oboe.cpp index b7bab19ae4ea..2aa9960cbad0 100644 --- a/3rdparty/openal/alc/backends/oboe.cpp +++ b/3rdparty/openal/alc/backends/oboe.cpp @@ -4,10 +4,11 @@ #include "oboe.h" #include +#include #include -#include #include "alnumeric.h" +#include "alstring.h" #include "core/device.h" #include "core/logging.h" #include "ringbuffer.h" @@ -17,11 +18,13 @@ namespace { -constexpr char device_name[] = "Oboe Default"; +using namespace std::string_view_literals; + +[[nodiscard]] constexpr auto GetDeviceName() noexcept { return "Oboe Default"sv; } struct OboePlayback final : public BackendBase, public oboe::AudioStreamCallback { - OboePlayback(DeviceBase *device) : BackendBase{device} { } + explicit OboePlayback(DeviceBase *device) : BackendBase{device} { } oboe::ManagedStream mStream; @@ -48,21 +51,21 @@ oboe::DataCallbackResult OboePlayback::onAudioReady(oboe::AudioStream *oboeStrea return oboe::DataCallbackResult::Continue; } -void OboePlayback::onErrorAfterClose(oboe::AudioStream* audioStream, oboe::Result error) +void OboePlayback::onErrorAfterClose(oboe::AudioStream*, oboe::Result error) { - if (error == oboe::Result::ErrorDisconnected) { - mDevice->handleDisconnect("Oboe AudioStream was disconnected: %s", oboe::convertToText(error)); - } - TRACE("Error was %s", oboe::convertToText(error)); + if(error == oboe::Result::ErrorDisconnected) + mDevice->handleDisconnect("Oboe AudioStream was disconnected: {}", + oboe::convertToText(error)); + TRACE("Error was {}", oboe::convertToText(error)); } void OboePlayback::open(std::string_view name) { if(name.empty()) - name = device_name; - else if(name != device_name) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; /* Open a basic output stream, just to ensure it can work. */ oboe::ManagedStream stream; @@ -70,10 +73,10 @@ void OboePlayback::open(std::string_view name) ->setPerformanceMode(oboe::PerformanceMode::LowLatency) ->openManagedStream(stream)}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: %s", + throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: {}", oboe::convertToText(result)}; - mDevice->DeviceName = name; + mDeviceName = name; } bool OboePlayback::reset() @@ -81,6 +84,7 @@ bool OboePlayback::reset() oboe::AudioStreamBuilder builder; builder.setDirection(oboe::Direction::Output); builder.setPerformanceMode(oboe::PerformanceMode::LowLatency); + builder.setUsage(oboe::Usage::Game); /* Don't let Oboe convert. We should be able to handle anything it gives * back. */ @@ -92,7 +96,7 @@ bool OboePlayback::reset() if(mDevice->Flags.test(FrequencyRequest)) { builder.setSampleRateConversionQuality(oboe::SampleRateConversionQuality::High); - builder.setSampleRate(static_cast(mDevice->Frequency)); + builder.setSampleRate(static_cast(mDevice->mSampleRate)); } if(mDevice->Flags.test(ChannelsRequest)) { @@ -142,11 +146,11 @@ bool OboePlayback::reset() result = builder.openManagedStream(mStream); } if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: %s", + throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: {}", oboe::convertToText(result)}; - mStream->setBufferSizeInFrames(mini(static_cast(mDevice->BufferSize), + mStream->setBufferSizeInFrames(std::min(static_cast(mDevice->mBufferSize), mStream->getBufferCapacityInFrames())); - TRACE("Got stream with properties:\n%s", oboe::convertToText(mStream.get())); + TRACE("Got stream with properties:\n{}", oboe::convertToText(mStream.get())); if(static_cast(mStream->getChannelCount()) != mDevice->channelsFromFmt()) { @@ -156,7 +160,7 @@ bool OboePlayback::reset() mDevice->FmtChans = DevFmtMono; else throw al::backend_exception{al::backend_error::DeviceError, - "Got unhandled channel count: %d", mStream->getChannelCount()}; + "Got unhandled channel count: {}", mStream->getChannelCount()}; } setDefaultWFXChannelOrder(); @@ -173,22 +177,25 @@ bool OboePlayback::reset() mDevice->FmtType = DevFmtInt; break; case oboe::AudioFormat::I24: +#endif +#if OBOE_VERSION_MAJOR > 1 || (OBOE_VERSION_MAJOR == 1 && OBOE_VERSION_MINOR >= 8) + case oboe::AudioFormat::IEC61937: #endif case oboe::AudioFormat::Unspecified: case oboe::AudioFormat::Invalid: throw al::backend_exception{al::backend_error::DeviceError, - "Got unhandled sample type: %s", oboe::convertToText(mStream->getFormat())}; + "Got unhandled sample type: {}", oboe::convertToText(mStream->getFormat())}; } - mDevice->Frequency = static_cast(mStream->getSampleRate()); + mDevice->mSampleRate = static_cast(mStream->getSampleRate()); /* Ensure the period size is no less than 10ms. It's possible for FramesPerCallback to be 0 * indicating variable updates, but OpenAL should have a reasonable minimum update size set. * FramesPerBurst may not necessarily be correct, but hopefully it can act as a minimum * update size. */ - mDevice->UpdateSize = maxu(mDevice->Frequency / 100, + mDevice->mUpdateSize = std::max(mDevice->mSampleRate/100u, static_cast(mStream->getFramesPerBurst())); - mDevice->BufferSize = maxu(mDevice->UpdateSize * 2, + mDevice->mBufferSize = std::max(mDevice->mUpdateSize*2u, static_cast(mStream->getBufferSizeInFrames())); return true; @@ -198,7 +205,7 @@ void OboePlayback::start() { const oboe::Result result{mStream->start()}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to start stream: %s", + throw al::backend_exception{al::backend_error::DeviceError, "Failed to start stream: {}", oboe::convertToText(result)}; } @@ -206,12 +213,12 @@ void OboePlayback::stop() { oboe::Result result{mStream->stop()}; if(result != oboe::Result::OK) - ERR("Failed to stop stream: %s\n", oboe::convertToText(result)); + ERR("Failed to stop stream: {}", oboe::convertToText(result)); } struct OboeCapture final : public BackendBase, public oboe::AudioStreamCallback { - OboeCapture(DeviceBase *device) : BackendBase{device} { } + explicit OboeCapture(DeviceBase *device) : BackendBase{device} { } oboe::ManagedStream mStream; @@ -230,7 +237,7 @@ struct OboeCapture final : public BackendBase, public oboe::AudioStreamCallback oboe::DataCallbackResult OboeCapture::onAudioReady(oboe::AudioStream*, void *audioData, int32_t numFrames) { - mRing->write(audioData, static_cast(numFrames)); + std::ignore = mRing->write(audioData, static_cast(numFrames)); return oboe::DataCallbackResult::Continue; } @@ -238,10 +245,10 @@ oboe::DataCallbackResult OboeCapture::onAudioReady(oboe::AudioStream*, void *aud void OboeCapture::open(std::string_view name) { if(name.empty()) - name = device_name; - else if(name != device_name) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; oboe::AudioStreamBuilder builder; builder.setDirection(oboe::Direction::Input) @@ -249,7 +256,7 @@ void OboeCapture::open(std::string_view name) ->setSampleRateConversionQuality(oboe::SampleRateConversionQuality::High) ->setChannelConversionAllowed(true) ->setFormatConversionAllowed(true) - ->setSampleRate(static_cast(mDevice->Frequency)) + ->setSampleRate(static_cast(mDevice->mSampleRate)) ->setCallback(this); /* Only use mono or stereo at user request. There's no telling what * other counts may be inferred as. @@ -267,9 +274,10 @@ void OboeCapture::open(std::string_view name) case DevFmtX61: case DevFmtX71: case DevFmtX714: + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: - throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} capture not supported", DevFmtChannelsString(mDevice->FmtChans)}; } @@ -294,28 +302,28 @@ void OboeCapture::open(std::string_view name) case DevFmtUShort: case DevFmtUInt: throw al::backend_exception{al::backend_error::DeviceError, - "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; + "{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; } oboe::Result result{builder.openManagedStream(mStream)}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: %s", + throw al::backend_exception{al::backend_error::DeviceError, "Failed to create stream: {}", oboe::convertToText(result)}; - TRACE("Got stream with properties:\n%s", oboe::convertToText(mStream.get())); + TRACE("Got stream with properties:\n{}", oboe::convertToText(mStream.get())); /* Ensure a minimum ringbuffer size of 100ms. */ - mRing = RingBuffer::Create(maxu(mDevice->BufferSize, mDevice->Frequency/10), + mRing = RingBuffer::Create(std::max(mDevice->mBufferSize, mDevice->mSampleRate/10u), static_cast(mStream->getBytesPerFrame()), false); - mDevice->DeviceName = name; + mDeviceName = name; } void OboeCapture::start() { const oboe::Result result{mStream->start()}; if(result != oboe::Result::OK) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to start stream: %s", + throw al::backend_exception{al::backend_error::DeviceError, "Failed to start stream: {}", oboe::convertToText(result)}; } @@ -323,14 +331,14 @@ void OboeCapture::stop() { const oboe::Result result{mStream->stop()}; if(result != oboe::Result::OK) - ERR("Failed to stop stream: %s\n", oboe::convertToText(result)); + ERR("Failed to stop stream: {}", oboe::convertToText(result)); } uint OboeCapture::availableSamples() { return static_cast(mRing->readSpace()); } void OboeCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } } // namespace @@ -339,16 +347,15 @@ bool OboeBackendFactory::init() { return true; } bool OboeBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string OboeBackendFactory::probe(BackendType type) +auto OboeBackendFactory::enumerate(BackendType type) -> std::vector { switch(type) { case BackendType::Playback: case BackendType::Capture: - /* Includes null char. */ - return std::string{device_name, sizeof(device_name)}; + return std::vector{std::string{GetDeviceName()}}; } - return std::string{}; + return {}; } BackendPtr OboeBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/oboe.h b/3rdparty/openal/alc/backends/oboe.h index a39c24454f7d..d277cfe7cf84 100644 --- a/3rdparty/openal/alc/backends/oboe.h +++ b/3rdparty/openal/alc/backends/oboe.h @@ -5,15 +5,15 @@ struct OboeBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_OBOE_H */ diff --git a/3rdparty/openal/alc/backends/opensl.cpp b/3rdparty/openal/alc/backends/opensl.cpp index 61e3c9a76792..155972b98f78 100644 --- a/3rdparty/openal/alc/backends/opensl.cpp +++ b/3rdparty/openal/alc/backends/opensl.cpp @@ -23,10 +23,10 @@ #include "opensl.h" -#include #include #include +#include #include #include #include @@ -36,10 +36,12 @@ #include "albit.h" #include "alnumeric.h" #include "alsem.h" +#include "alstring.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" +#include "dynload.h" #include "opthelpers.h" #include "ringbuffer.h" @@ -50,15 +52,43 @@ namespace { +using namespace std::string_view_literals; + + +#if HAVE_DYNLOAD +#define SLES_SYMBOLS(MAGIC) \ + MAGIC(slCreateEngine); \ + MAGIC(SL_IID_ANDROIDCONFIGURATION); \ + MAGIC(SL_IID_ANDROIDSIMPLEBUFFERQUEUE); \ + MAGIC(SL_IID_ENGINE); \ + MAGIC(SL_IID_PLAY); \ + MAGIC(SL_IID_RECORD); + +void *sles_handle; +#define MAKE_SYMBOL(f) decltype(f) * p##f +SLES_SYMBOLS(MAKE_SYMBOL) +#undef MAKE_SYMBOL + +#ifndef IN_IDE_PARSER +#define slCreateEngine (*pslCreateEngine) +#define SL_IID_ANDROIDCONFIGURATION (*pSL_IID_ANDROIDCONFIGURATION) +#define SL_IID_ANDROIDSIMPLEBUFFERQUEUE (*pSL_IID_ANDROIDSIMPLEBUFFERQUEUE) +#define SL_IID_ENGINE (*pSL_IID_ENGINE) +#define SL_IID_PLAY (*pSL_IID_PLAY) +#define SL_IID_RECORD (*pSL_IID_RECORD) +#endif +#endif + + /* Helper macros */ #define EXTRACT_VCALL_ARGS(...) __VA_ARGS__)) #define VCALL(obj, func) ((*(obj))->func((obj), EXTRACT_VCALL_ARGS #define VCALL0(obj, func) ((*(obj))->func((obj) EXTRACT_VCALL_ARGS -constexpr char opensl_device[] = "OpenSL"; - +[[nodiscard]] constexpr auto GetDeviceName() noexcept { return "OpenSL"sv; } +[[nodiscard]] constexpr SLuint32 GetChannelMask(DevFmtChannels chans) noexcept { switch(chans) @@ -82,6 +112,7 @@ constexpr SLuint32 GetChannelMask(DevFmtChannels chans) noexcept SL_SPEAKER_BACK_RIGHT | SL_SPEAKER_SIDE_LEFT | SL_SPEAKER_SIDE_RIGHT | SL_SPEAKER_TOP_FRONT_LEFT | SL_SPEAKER_TOP_FRONT_RIGHT | SL_SPEAKER_TOP_BACK_LEFT | SL_SPEAKER_TOP_BACK_RIGHT; + case DevFmtX7144: case DevFmtAmbi3D: break; } @@ -152,12 +183,12 @@ constexpr const char *res_str(SLresult result) noexcept inline void PrintErr(SLresult res, const char *str) { if(res != SL_RESULT_SUCCESS) UNLIKELY - ERR("%s: %s\n", str, res_str(res)); + ERR("{}: {}", str, res_str(res)); } struct OpenSLPlayback final : public BackendBase { - OpenSLPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit OpenSLPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~OpenSLPlayback() override; void process(SLAndroidSimpleBufferQueueItf bq) noexcept; @@ -189,8 +220,6 @@ struct OpenSLPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(OpenSLPlayback) }; OpenSLPlayback::~OpenSLPlayback() @@ -229,7 +258,7 @@ void OpenSLPlayback::process(SLAndroidSimpleBufferQueueItf) noexcept int OpenSLPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); SLPlayItf player; SLAndroidSimpleBufferQueueItf bufferQueue; @@ -245,7 +274,7 @@ int OpenSLPlayback::mixerProc() const size_t frame_step{mDevice->channelsFromFmt()}; if(SL_RESULT_SUCCESS != result) - mDevice->handleDisconnect("Failed to get playback buffer: 0x%08x", result); + mDevice->handleDisconnect("Failed to get playback buffer: {:#08x}", result); while(SL_RESULT_SUCCESS == result && !mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) @@ -263,7 +292,7 @@ int OpenSLPlayback::mixerProc() } if(SL_RESULT_SUCCESS != result) { - mDevice->handleDisconnect("Failed to start playback: 0x%08x", result); + mDevice->handleDisconnect("Failed to start playback: {:#08x}", result); break; } @@ -276,35 +305,35 @@ int OpenSLPlayback::mixerProc() std::unique_lock dlock{mMutex}; auto data = mRing->getWriteVector(); - mDevice->renderSamples(data.first.buf, - static_cast(data.first.len)*mDevice->UpdateSize, frame_step); - if(data.second.len > 0) - mDevice->renderSamples(data.second.buf, - static_cast(data.second.len)*mDevice->UpdateSize, frame_step); + mDevice->renderSamples(data[0].buf, + static_cast(data[0].len)*mDevice->mUpdateSize, frame_step); + if(data[1].len > 0) + mDevice->renderSamples(data[1].buf, + static_cast(data[1].len)*mDevice->mUpdateSize, frame_step); - size_t todo{data.first.len + data.second.len}; + const auto todo = size_t{data[0].len + data[1].len}; mRing->writeAdvance(todo); dlock.unlock(); for(size_t i{0};i < todo;i++) { - if(!data.first.len) + if(!data[0].len) { - data.first = data.second; - data.second.buf = nullptr; - data.second.len = 0; + data[0] = data[1]; + data[1].buf = nullptr; + data[1].len = 0; } - result = VCALL(bufferQueue,Enqueue)(data.first.buf, mDevice->UpdateSize*mFrameSize); + result = VCALL(bufferQueue,Enqueue)(data[0].buf, mDevice->mUpdateSize*mFrameSize); PrintErr(result, "bufferQueue->Enqueue"); if(SL_RESULT_SUCCESS != result) { - mDevice->handleDisconnect("Failed to queue audio: 0x%08x", result); + mDevice->handleDisconnect("Failed to queue audio: {:#08x}", result); break; } - data.first.len--; - data.first.buf += mDevice->UpdateSize*mFrameSize; + data[0].len--; + data[0].buf += mDevice->mUpdateSize*mFrameSize; } } @@ -315,10 +344,10 @@ int OpenSLPlayback::mixerProc() void OpenSLPlayback::open(std::string_view name) { if(name.empty()) - name = opensl_device; - else if(name != opensl_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; /* There's only one device, so if it's already open, there's nothing to do. */ if(mEngineObj) return; @@ -359,10 +388,10 @@ void OpenSLPlayback::open(std::string_view name) mEngine = nullptr; throw al::backend_exception{al::backend_error::DeviceError, - "Failed to initialize OpenSL device: 0x%08x", result}; + "Failed to initialize OpenSL device: {:#08x}", result}; } - mDevice->DeviceName = name; + mDeviceName = name; } bool OpenSLPlayback::reset() @@ -375,74 +404,6 @@ bool OpenSLPlayback::reset() mRing = nullptr; -#if 0 - if(!mDevice->Flags.get()) - { - /* FIXME: Disabled until I figure out how to get the Context needed for - * the getSystemService call. - */ - JNIEnv *env = Android_GetJNIEnv(); - jobject jctx = Android_GetContext(); - - /* Get necessary stuff for using java.lang.Integer, - * android.content.Context, and android.media.AudioManager. - */ - jclass int_cls = JCALL(env,FindClass)("java/lang/Integer"); - jmethodID int_parseint = JCALL(env,GetStaticMethodID)(int_cls, - "parseInt", "(Ljava/lang/String;)I" - ); - TRACE("Integer: %p, parseInt: %p\n", int_cls, int_parseint); - - jclass ctx_cls = JCALL(env,FindClass)("android/content/Context"); - jfieldID ctx_audsvc = JCALL(env,GetStaticFieldID)(ctx_cls, - "AUDIO_SERVICE", "Ljava/lang/String;" - ); - jmethodID ctx_getSysSvc = JCALL(env,GetMethodID)(ctx_cls, - "getSystemService", "(Ljava/lang/String;)Ljava/lang/Object;" - ); - TRACE("Context: %p, AUDIO_SERVICE: %p, getSystemService: %p\n", - ctx_cls, ctx_audsvc, ctx_getSysSvc); - - jclass audmgr_cls = JCALL(env,FindClass)("android/media/AudioManager"); - jfieldID audmgr_prop_out_srate = JCALL(env,GetStaticFieldID)(audmgr_cls, - "PROPERTY_OUTPUT_SAMPLE_RATE", "Ljava/lang/String;" - ); - jmethodID audmgr_getproperty = JCALL(env,GetMethodID)(audmgr_cls, - "getProperty", "(Ljava/lang/String;)Ljava/lang/String;" - ); - TRACE("AudioManager: %p, PROPERTY_OUTPUT_SAMPLE_RATE: %p, getProperty: %p\n", - audmgr_cls, audmgr_prop_out_srate, audmgr_getproperty); - - const char *strchars; - jstring strobj; - - /* Now make the calls. */ - //AudioManager audMgr = (AudioManager)getSystemService(Context.AUDIO_SERVICE); - strobj = JCALL(env,GetStaticObjectField)(ctx_cls, ctx_audsvc); - jobject audMgr = JCALL(env,CallObjectMethod)(jctx, ctx_getSysSvc, strobj); - strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr); - TRACE("Context.getSystemService(%s) = %p\n", strchars, audMgr); - JCALL(env,ReleaseStringUTFChars)(strobj, strchars); - - //String srateStr = audMgr.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE); - strobj = JCALL(env,GetStaticObjectField)(audmgr_cls, audmgr_prop_out_srate); - jstring srateStr = JCALL(env,CallObjectMethod)(audMgr, audmgr_getproperty, strobj); - strchars = JCALL(env,GetStringUTFChars)(strobj, nullptr); - TRACE("audMgr.getProperty(%s) = %p\n", strchars, srateStr); - JCALL(env,ReleaseStringUTFChars)(strobj, strchars); - - //int sampleRate = Integer.parseInt(srateStr); - sampleRate = JCALL(env,CallStaticIntMethod)(int_cls, int_parseint, srateStr); - - strchars = JCALL(env,GetStringUTFChars)(srateStr, nullptr); - TRACE("Got system sample rate %uhz (%s)\n", sampleRate, strchars); - JCALL(env,ReleaseStringUTFChars)(srateStr, strchars); - - if(!sampleRate) sampleRate = device->Frequency; - else sampleRate = maxu(sampleRate, MIN_OUTPUT_RATE); - } -#endif - mDevice->FmtChans = DevFmtStereo; mDevice->FmtType = DevFmtShort; @@ -463,14 +424,14 @@ bool OpenSLPlayback::reset() SLDataLocator_AndroidSimpleBufferQueue loc_bufq{}; loc_bufq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bufq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize; + loc_bufq.numBuffers = mDevice->mBufferSize / mDevice->mUpdateSize; SLDataSource audioSrc{}; #ifdef SL_ANDROID_DATAFORMAT_PCM_EX SLAndroidDataFormat_PCM_EX format_pcm_ex{}; format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; format_pcm_ex.numChannels = mDevice->channelsFromFmt(); - format_pcm_ex.sampleRate = mDevice->Frequency * 1000; + format_pcm_ex.sampleRate = mDevice->mSampleRate * 1000; format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8; format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample; format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans); @@ -501,7 +462,7 @@ bool OpenSLPlayback::reset() SLDataFormat_PCM format_pcm{}; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.samplesPerSec = mDevice->Frequency * 1000; + format_pcm.samplesPerSec = mDevice->mSampleRate * 1000; format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; format_pcm.containerSize = format_pcm.bitsPerSample; format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); @@ -538,8 +499,8 @@ bool OpenSLPlayback::reset() } if(SL_RESULT_SUCCESS == result) { - const uint num_updates{mDevice->BufferSize / mDevice->UpdateSize}; - mRing = RingBuffer::Create(num_updates, mFrameSize*mDevice->UpdateSize, true); + const uint num_updates{mDevice->mBufferSize / mDevice->mUpdateSize}; + mRing = RingBuffer::Create(num_updates, mFrameSize*mDevice->mUpdateSize, true); } if(SL_RESULT_SUCCESS != result) @@ -571,15 +532,15 @@ void OpenSLPlayback::start() } if(SL_RESULT_SUCCESS != result) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to register callback: 0x%08x", result}; + "Failed to register callback: {:#08x}", result}; try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread(std::mem_fn(&OpenSLPlayback::mixerProc), this); + mThread = std::thread(&OpenSLPlayback::mixerProc, this); } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -630,17 +591,17 @@ ClockLatency OpenSLPlayback::getClockLatency() { ClockLatency ret; - std::lock_guard _{mMutex}; - ret.ClockTime = GetDeviceClockTime(mDevice); - ret.Latency = std::chrono::seconds{mRing->readSpace() * mDevice->UpdateSize}; - ret.Latency /= mDevice->Frequency; + std::lock_guard dlock{mMutex}; + ret.ClockTime = mDevice->getClockTime(); + ret.Latency = std::chrono::seconds{mRing->readSpace() * mDevice->mUpdateSize}; + ret.Latency /= mDevice->mSampleRate; return ret; } struct OpenSLCapture final : public BackendBase { - OpenSLCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit OpenSLCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~OpenSLCapture() override; void process(SLAndroidSimpleBufferQueueItf bq) noexcept; @@ -662,8 +623,6 @@ struct OpenSLCapture final : public BackendBase { uint mSplOffset{0u}; uint mFrameSize{0}; - - DEF_NEWDEL(OpenSLCapture) }; OpenSLCapture::~OpenSLCapture() @@ -689,10 +648,10 @@ void OpenSLCapture::process(SLAndroidSimpleBufferQueueItf) noexcept void OpenSLCapture::open(std::string_view name) { if(name.empty()) - name = opensl_device; - else if(name != opensl_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; SLresult result{slCreateEngine(&mEngineObj, 0, nullptr, 0, nullptr, nullptr)}; PrintErr(result, "slCreateEngine"); @@ -710,16 +669,16 @@ void OpenSLCapture::open(std::string_view name) { mFrameSize = mDevice->frameSizeFromFmt(); /* Ensure the total length is at least 100ms */ - uint length{maxu(mDevice->BufferSize, mDevice->Frequency/10)}; + uint length{std::max(mDevice->mBufferSize, mDevice->mSampleRate/10u)}; /* Ensure the per-chunk length is at least 10ms, and no more than 50ms. */ - uint update_len{clampu(mDevice->BufferSize/3, mDevice->Frequency/100, - mDevice->Frequency/100*5)}; + uint update_len{std::clamp(mDevice->mBufferSize/3u, mDevice->mSampleRate/100u, + mDevice->mSampleRate/100u*5u)}; uint num_updates{(length+update_len-1) / update_len}; mRing = RingBuffer::Create(num_updates, update_len*mFrameSize, false); - mDevice->UpdateSize = update_len; - mDevice->BufferSize = static_cast(mRing->writeSpace() * update_len); + mDevice->mUpdateSize = update_len; + mDevice->mBufferSize = static_cast(mRing->writeSpace() * update_len); } if(SL_RESULT_SUCCESS == result) { @@ -738,14 +697,14 @@ void OpenSLCapture::open(std::string_view name) SLDataLocator_AndroidSimpleBufferQueue loc_bq{}; loc_bq.locatorType = SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE; - loc_bq.numBuffers = mDevice->BufferSize / mDevice->UpdateSize; + loc_bq.numBuffers = mDevice->mBufferSize / mDevice->mUpdateSize; SLDataSink audioSnk{}; #ifdef SL_ANDROID_DATAFORMAT_PCM_EX SLAndroidDataFormat_PCM_EX format_pcm_ex{}; format_pcm_ex.formatType = SL_ANDROID_DATAFORMAT_PCM_EX; format_pcm_ex.numChannels = mDevice->channelsFromFmt(); - format_pcm_ex.sampleRate = mDevice->Frequency * 1000; + format_pcm_ex.sampleRate = mDevice->mSampleRate * 1000; format_pcm_ex.bitsPerSample = mDevice->bytesFromFmt() * 8; format_pcm_ex.containerSize = format_pcm_ex.bitsPerSample; format_pcm_ex.channelMask = GetChannelMask(mDevice->FmtChans); @@ -768,7 +727,7 @@ void OpenSLCapture::open(std::string_view name) SLDataFormat_PCM format_pcm{}; format_pcm.formatType = SL_DATAFORMAT_PCM; format_pcm.numChannels = mDevice->channelsFromFmt(); - format_pcm.samplesPerSec = mDevice->Frequency * 1000; + format_pcm.samplesPerSec = mDevice->mSampleRate * 1000; format_pcm.bitsPerSample = mDevice->bytesFromFmt() * 8; format_pcm.containerSize = format_pcm.bitsPerSample; format_pcm.channelMask = GetChannelMask(mDevice->FmtChans); @@ -820,20 +779,20 @@ void OpenSLCapture::open(std::string_view name) } if(SL_RESULT_SUCCESS == result) { - const uint chunk_size{mDevice->UpdateSize * mFrameSize}; + const uint chunk_size{mDevice->mUpdateSize * mFrameSize}; const auto silence = (mDevice->FmtType == DevFmtUByte) ? std::byte{0x80} : std::byte{0}; auto data = mRing->getWriteVector(); - std::fill_n(data.first.buf, data.first.len*chunk_size, silence); - std::fill_n(data.second.buf, data.second.len*chunk_size, silence); - for(size_t i{0u};i < data.first.len && SL_RESULT_SUCCESS == result;i++) + std::fill_n(data[0].buf, data[0].len*chunk_size, silence); + std::fill_n(data[1].buf, data[1].len*chunk_size, silence); + for(size_t i{0u};i < data[0].len && SL_RESULT_SUCCESS == result;i++) { - result = VCALL(bufferQueue,Enqueue)(data.first.buf + chunk_size*i, chunk_size); + result = VCALL(bufferQueue,Enqueue)(data[0].buf + chunk_size*i, chunk_size); PrintErr(result, "bufferQueue->Enqueue"); } - for(size_t i{0u};i < data.second.len && SL_RESULT_SUCCESS == result;i++) + for(size_t i{0u};i < data[1].len && SL_RESULT_SUCCESS == result;i++) { - result = VCALL(bufferQueue,Enqueue)(data.second.buf + chunk_size*i, chunk_size); + result = VCALL(bufferQueue,Enqueue)(data[1].buf + chunk_size*i, chunk_size); PrintErr(result, "bufferQueue->Enqueue"); } } @@ -850,10 +809,10 @@ void OpenSLCapture::open(std::string_view name) mEngine = nullptr; throw al::backend_exception{al::backend_error::DeviceError, - "Failed to initialize OpenSL device: 0x%08x", result}; + "Failed to initialize OpenSL device: {:#08x}", result}; } - mDevice->DeviceName = name; + mDeviceName = name; } void OpenSLCapture::start() @@ -869,7 +828,7 @@ void OpenSLCapture::start() } if(SL_RESULT_SUCCESS != result) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start capture: 0x%08x", result}; + "Failed to start capture: {:#08x}", result}; } void OpenSLCapture::stop() @@ -887,7 +846,7 @@ void OpenSLCapture::stop() void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) { - const uint update_size{mDevice->UpdateSize}; + const uint update_size{mDevice->mUpdateSize}; const uint chunk_size{update_size * mFrameSize}; /* Read the desired samples from the ring buffer then advance its read @@ -897,8 +856,8 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) auto rdata = mRing->getReadVector(); for(uint i{0};i < samples;) { - const uint rem{minu(samples - i, update_size - mSplOffset)}; - std::copy_n(rdata.first.buf + mSplOffset*size_t{mFrameSize}, rem*size_t{mFrameSize}, + const uint rem{std::min(samples - i, update_size - mSplOffset)}; + std::copy_n(rdata[0].buf + mSplOffset*size_t{mFrameSize}, rem*size_t{mFrameSize}, buffer + i*size_t{mFrameSize}); mSplOffset += rem; @@ -908,11 +867,11 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) mSplOffset = 0; ++adv_count; - rdata.first.len -= 1; - if(!rdata.first.len) - rdata.first = rdata.second; + rdata[0].len -= 1; + if(!rdata[0].len) + rdata[0] = rdata[1]; else - rdata.first.buf += chunk_size; + rdata[0].buf += chunk_size; } i += rem; @@ -926,7 +885,7 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) PrintErr(result, "recordObj->GetInterface"); if(SL_RESULT_SUCCESS != result) UNLIKELY { - mDevice->handleDisconnect("Failed to get capture buffer queue: 0x%08x", result); + mDevice->handleDisconnect("Failed to get capture buffer queue: {:#08x}", result); bufferQueue = nullptr; } } @@ -945,20 +904,20 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) SLresult result{SL_RESULT_SUCCESS}; auto wdata = mRing->getWriteVector(); - if(adv_count > wdata.second.len) LIKELY + if(adv_count > wdata[1].len) LIKELY { - auto len1 = std::min(wdata.first.len, adv_count-wdata.second.len); - auto buf1 = wdata.first.buf + chunk_size*(wdata.first.len-len1); + auto len1 = std::min(wdata[0].len, adv_count-wdata[1].len); + auto buf1 = wdata[0].buf + chunk_size*(wdata[0].len-len1); for(size_t i{0u};i < len1 && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(buf1 + chunk_size*i, chunk_size); PrintErr(result, "bufferQueue->Enqueue"); } } - if(wdata.second.len > 0) + if(wdata[1].len > 0) { - auto len2 = std::min(wdata.second.len, adv_count); - auto buf2 = wdata.second.buf + chunk_size*(wdata.second.len-len2); + auto len2 = std::min(wdata[1].len, adv_count); + auto buf2 = wdata[1].buf + chunk_size*(wdata[1].len-len2); for(size_t i{0u};i < len2 && SL_RESULT_SUCCESS == result;i++) { result = VCALL(bufferQueue,Enqueue)(buf2 + chunk_size*i, chunk_size); @@ -968,27 +927,56 @@ void OpenSLCapture::captureSamples(std::byte *buffer, uint samples) } uint OpenSLCapture::availableSamples() -{ return static_cast(mRing->readSpace()*mDevice->UpdateSize - mSplOffset); } +{ return static_cast(mRing->readSpace()*mDevice->mUpdateSize - mSplOffset); } } // namespace -bool OSLBackendFactory::init() { return true; } +bool OSLBackendFactory::init() +{ +#if HAVE_DYNLOAD + if(!sles_handle) + { +#define SLES_LIBNAME "libOpenSLES.so" + sles_handle = LoadLib(SLES_LIBNAME); + if(!sles_handle) + { + WARN("Failed to load {}", SLES_LIBNAME); + return false; + } + + std::string missing_syms; +#define LOAD_SYMBOL(f) do { \ + p##f = reinterpret_cast(GetSymbol(sles_handle, #f)); \ + if(p##f == nullptr) missing_syms += "\n" #f; \ +} while(0) + SLES_SYMBOLS(LOAD_SYMBOL); +#undef LOAD_SYMBOL + + if(!missing_syms.empty()) + { + WARN("Missing expected symbols:{}", missing_syms); + CloseLib(sles_handle); + sles_handle = nullptr; + return false; + } + } +#endif + + return true; +} bool OSLBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string OSLBackendFactory::probe(BackendType type) +auto OSLBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; switch(type) { case BackendType::Playback: case BackendType::Capture: - /* Includes null char. */ - outnames.append(opensl_device, sizeof(opensl_device)); - break; + return std::vector{std::string{GetDeviceName()}}; } - return outnames; + return {}; } BackendPtr OSLBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/opensl.h b/3rdparty/openal/alc/backends/opensl.h index b81624476cc0..9f13dd71f9d0 100644 --- a/3rdparty/openal/alc/backends/opensl.h +++ b/3rdparty/openal/alc/backends/opensl.h @@ -5,15 +5,15 @@ struct OSLBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_OSL_H */ diff --git a/3rdparty/openal/alc/backends/oss.cpp b/3rdparty/openal/alc/backends/oss.cpp index 87d3ba35b9d2..cf73c18cab9b 100644 --- a/3rdparty/openal/alc/backends/oss.cpp +++ b/3rdparty/openal/alc/backends/oss.cpp @@ -33,20 +33,21 @@ #include #include #include -#include #include #include +#include +#include #include #include #include #include "alc/alconfig.h" -#include "almalloc.h" #include "alnumeric.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" +#include "fmt/core.h" #include "ringbuffer.h" #include @@ -79,13 +80,22 @@ namespace { -constexpr char DefaultName[] = "OSS Default"; -std::string DefaultPlayback{"/dev/dsp"}; -std::string DefaultCapture{"/dev/dsp"}; +using namespace std::string_literals; +using namespace std::string_view_literals; + +[[nodiscard]] constexpr auto GetDefaultName() noexcept { return "OSS Default"sv; } + +std::string DefaultPlayback{"/dev/dsp"s}; +std::string DefaultCapture{"/dev/dsp"s}; struct DevMap { std::string name; std::string device_name; + + template + DevMap(T&& name_, U&& devname_) + : name{std::forward(name_)}, device_name{std::forward(devname_)} + { } }; std::vector PlaybackDevices; @@ -98,98 +108,114 @@ std::vector CaptureDevices; #define DSP_CAP_INPUT 0x00010000 void ALCossListPopulate(std::vector &devlist, int type) { - devlist.emplace_back(DevMap{DefaultName, (type==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback}); + devlist.emplace_back(GetDefaultName(), (type==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback); } #else -void ALCossListAppend(std::vector &list, al::span handle, al::span path) +class FileHandle { + int mFd{-1}; + +public: + FileHandle() = default; + FileHandle(const FileHandle&) = delete; + FileHandle& operator=(const FileHandle&) = delete; + ~FileHandle() { if(mFd != -1) ::close(mFd); } + + template + [[nodiscard]] auto open(const char *fname, Args&& ...args) -> bool + { + close(); + mFd = ::open(fname, std::forward(args)...); + return mFd != -1; + } + void close() + { + if(mFd != -1) + ::close(mFd); + mFd = -1; + } + + [[nodiscard]] + auto get() const noexcept -> int { return mFd; } +}; + +void ALCossListAppend(std::vector &list, std::string_view handle, std::string_view path) { #ifdef ALC_OSS_DEVNODE_TRUC for(size_t i{0};i < path.size();++i) { - if(path[i] == '.' && handle.size() + i >= path.size()) + if(path[i] == '.' && handle.size() >= path.size() - i) { const size_t hoffset{handle.size() + i - path.size()}; if(strncmp(path.data() + i, handle.data() + hoffset, path.size() - i) == 0) - handle = handle.first(hoffset); - path = path.first(i); + handle = handle.substr(0, hoffset); + path = path.substr(0, i); } } #endif if(handle.empty()) handle = path; - std::string basename{handle.data(), handle.size()}; - std::string devname{path.data(), path.size()}; - - auto match_devname = [&devname](const DevMap &entry) -> bool - { return entry.device_name == devname; }; + auto match_devname = [path](const DevMap &entry) -> bool + { return entry.device_name == path; }; if(std::find_if(list.cbegin(), list.cend(), match_devname) != list.cend()) return; - auto checkName = [&list](const std::string &name) -> bool + auto checkName = [&list](const std::string_view name) -> bool { - auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; }; + auto match_name = [name](const DevMap &entry) -> bool { return entry.name == name; }; return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); }; - int count{1}; - std::string newname{basename}; + auto count = 1; + auto newname = std::string{handle}; while(checkName(newname)) - { - newname = basename; - newname += " #"; - newname += std::to_string(++count); - } + newname = fmt::format("{} #{}", handle, ++count); - list.emplace_back(DevMap{std::move(newname), std::move(devname)}); - const DevMap &entry = list.back(); - - TRACE("Got device \"%s\", \"%s\"\n", entry.name.c_str(), entry.device_name.c_str()); + const auto &entry = list.emplace_back(std::move(newname), path); + TRACE("Got device \"{}\", \"{}\"", entry.name, entry.device_name); } void ALCossListPopulate(std::vector &devlist, int type_flag) { - int fd{open("/dev/mixer", O_RDONLY)}; - if(fd < 0) + oss_sysinfo si{}; + FileHandle file; + if(!file.open("/dev/mixer", O_RDONLY)) { - TRACE("Could not open /dev/mixer: %s\n", strerror(errno)); + TRACE("Could not open /dev/mixer: {}", std::generic_category().message(errno)); goto done; } - oss_sysinfo si; - if(ioctl(fd, SNDCTL_SYSINFO, &si) == -1) + if(ioctl(file.get(), SNDCTL_SYSINFO, &si) == -1) { - TRACE("SNDCTL_SYSINFO failed: %s\n", strerror(errno)); + TRACE("SNDCTL_SYSINFO failed: {}", std::generic_category().message(errno)); goto done; } for(int i{0};i < si.numaudios;i++) { - oss_audioinfo ai; + oss_audioinfo ai{}; ai.dev = i; - if(ioctl(fd, SNDCTL_AUDIOINFO, &ai) == -1) + if(ioctl(file.get(), SNDCTL_AUDIOINFO, &ai) == -1) { - ERR("SNDCTL_AUDIOINFO (%d) failed: %s\n", i, strerror(errno)); + ERR("SNDCTL_AUDIOINFO ({}) failed: {}", i, std::generic_category().message(errno)); continue; } if(!(ai.caps&type_flag) || ai.devnode[0] == '\0') continue; - al::span handle; + std::string_view handle; if(ai.handle[0] != '\0') handle = {ai.handle, strnlen(ai.handle, sizeof(ai.handle))}; else handle = {ai.name, strnlen(ai.name, sizeof(ai.name))}; - al::span devnode{ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))}; + const std::string_view devnode{ai.devnode, strnlen(ai.devnode, sizeof(ai.devnode))}; ALCossListAppend(devlist, handle, devnode); } done: - if(fd >= 0) - close(fd); - fd = -1; + file.close(); const char *defdev{((type_flag==DSP_CAP_INPUT) ? DefaultCapture : DefaultPlayback).c_str()}; auto iter = std::find_if(devlist.cbegin(), devlist.cend(), @@ -197,7 +223,7 @@ void ALCossListPopulate(std::vector &devlist, int type_flag) { return entry.device_name == defdev; } ); if(iter == devlist.cend()) - devlist.insert(devlist.begin(), DevMap{DefaultName, defdev}); + devlist.insert(devlist.begin(), DevMap{GetDefaultName(), defdev}); else { DevMap entry{std::move(*iter)}; @@ -222,7 +248,7 @@ uint log2i(uint x) struct OSSPlayback final : public BackendBase { - OSSPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit OSSPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~OSSPlayback() override; int mixerProc(); @@ -238,8 +264,6 @@ struct OSSPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(OSSPlayback) }; OSSPlayback::~OSSPlayback() @@ -253,7 +277,7 @@ OSSPlayback::~OSSPlayback() int OSSPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); const size_t frame_step{mDevice->channelsFromFmt()}; const size_t frame_size{mDevice->frameSizeFromFmt()}; @@ -265,38 +289,38 @@ int OSSPlayback::mixerProc() pollitem.fd = mFd; pollitem.events = POLLOUT; - int pret{poll(&pollitem, 1, 1000)}; - if(pret < 0) + if(int pret{poll(&pollitem, 1, 1000)}; pret < 0) { if(errno == EINTR || errno == EAGAIN) continue; - ERR("poll failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed waiting for playback buffer: %s", strerror(errno)); + const auto errstr = std::generic_category().message(errno); + ERR("poll failed: {}", errstr); + mDevice->handleDisconnect("Failed waiting for playback buffer: {}", errstr); break; } - else if(pret == 0) + else if(pret == 0) /* NOLINT(*-else-after-return) 'pret' is local to the if/else blocks */ { - WARN("poll timeout\n"); + WARN("poll timeout"); continue; } - std::byte *write_ptr{mMixData.data()}; - size_t to_write{mMixData.size()}; - mDevice->renderSamples(write_ptr, static_cast(to_write/frame_size), frame_step); - while(to_write > 0 && !mKillNow.load(std::memory_order_acquire)) + al::span write_buf{mMixData}; + mDevice->renderSamples(write_buf.data(), static_cast(write_buf.size()/frame_size), + frame_step); + while(!write_buf.empty() && !mKillNow.load(std::memory_order_acquire)) { - ssize_t wrote{write(mFd, write_ptr, to_write)}; + ssize_t wrote{write(mFd, write_buf.data(), write_buf.size())}; if(wrote < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) continue; - ERR("write failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed writing playback samples: %s", strerror(errno)); + const auto errstr = std::generic_category().message(errno); + ERR("write failed: {}", errstr); + mDevice->handleDisconnect("Failed writing playback samples: {}", errstr); break; } - to_write -= static_cast(wrote); - write_ptr += wrote; + write_buf = write_buf.subspan(static_cast(wrote)); } } @@ -308,7 +332,7 @@ void OSSPlayback::open(std::string_view name) { const char *devname{DefaultPlayback.c_str()}; if(name.empty()) - name = DefaultName; + name = GetDefaultName(); else { if(PlaybackDevices.empty()) @@ -320,20 +344,20 @@ void OSSPlayback::open(std::string_view name) ); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; devname = iter->device_name.c_str(); } - int fd{::open(devname, O_WRONLY)}; + const auto fd = ::open(devname, O_WRONLY); /* NOLINT(cppcoreguidelines-pro-type-vararg) */ if(fd == -1) - throw al::backend_exception{al::backend_error::NoDevice, "Could not open %s: %s", devname, - strerror(errno)}; + throw al::backend_exception{al::backend_error::NoDevice, "Could not open {}: {}", devname, + std::generic_category().message(errno)}; if(mFd != -1) ::close(mFd); mFd = fd; - mDevice->DeviceName = name; + mDeviceName = name; } bool OSSPlayback::reset() @@ -358,38 +382,33 @@ bool OSSPlayback::reset() break; } - uint periods{mDevice->BufferSize / mDevice->UpdateSize}; + uint periods{mDevice->mBufferSize / mDevice->mUpdateSize}; uint numChannels{mDevice->channelsFromFmt()}; - uint ossSpeed{mDevice->Frequency}; + uint ossSpeed{mDevice->mSampleRate}; uint frameSize{numChannels * mDevice->bytesFromFmt()}; /* According to the OSS spec, 16 bytes (log2(16)) is the minimum. */ - uint log2FragmentSize{maxu(log2i(mDevice->UpdateSize*frameSize), 4)}; + uint log2FragmentSize{std::max(log2i(mDevice->mUpdateSize*frameSize), 4u)}; uint numFragmentsLogSize{(periods << 16) | log2FragmentSize}; audio_buf_info info{}; - const char *err; -#define CHECKERR(func) if((func) < 0) { \ - err = #func; \ - goto err; \ -} +#define CHECKERR(func) if((func) < 0) \ + throw al::backend_exception{al::backend_error::DeviceError, #func " failed: {}", \ + std::generic_category().message(errno)}; + /* Don't fail if SETFRAGMENT fails. We can handle just about anything * that's reported back via GETOSPACE */ + /* NOLINTBEGIN(cppcoreguidelines-pro-type-vararg) */ ioctl(mFd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize); CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFMT, &ossFormat)); CHECKERR(ioctl(mFd, SNDCTL_DSP_CHANNELS, &numChannels)); CHECKERR(ioctl(mFd, SNDCTL_DSP_SPEED, &ossSpeed)); CHECKERR(ioctl(mFd, SNDCTL_DSP_GETOSPACE, &info)); - if(0) - { - err: - ERR("%s failed: %s\n", err, strerror(errno)); - return false; - } + /* NOLINTEND(cppcoreguidelines-pro-type-vararg) */ #undef CHECKERR if(mDevice->channelsFromFmt() != numChannels) { - ERR("Failed to set %s, got %d channels instead\n", DevFmtChannelsString(mDevice->FmtChans), + ERR("Failed to set {}, got {} channels instead", DevFmtChannelsString(mDevice->FmtChans), numChannels); return false; } @@ -398,18 +417,18 @@ bool OSSPlayback::reset() (ossFormat == AFMT_U8 && mDevice->FmtType == DevFmtUByte) || (ossFormat == AFMT_S16_NE && mDevice->FmtType == DevFmtShort))) { - ERR("Failed to set %s samples, got OSS format %#x\n", DevFmtTypeString(mDevice->FmtType), - ossFormat); + ERR("Failed to set {} samples, got OSS format {:#x}", DevFmtTypeString(mDevice->FmtType), + as_unsigned(ossFormat)); return false; } - mDevice->Frequency = ossSpeed; - mDevice->UpdateSize = static_cast(info.fragsize) / frameSize; - mDevice->BufferSize = static_cast(info.fragments) * mDevice->UpdateSize; + mDevice->mSampleRate = ossSpeed; + mDevice->mUpdateSize = static_cast(info.fragsize) / frameSize; + mDevice->mBufferSize = static_cast(info.fragments) * mDevice->mUpdateSize; setDefaultChannelOrder(); - mMixData.resize(mDevice->UpdateSize * mDevice->frameSizeFromFmt()); + mMixData.resize(size_t{mDevice->mUpdateSize} * mDevice->frameSizeFromFmt()); return true; } @@ -418,11 +437,11 @@ void OSSPlayback::start() { try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&OSSPlayback::mixerProc), this}; + mThread = std::thread{&OSSPlayback::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -432,13 +451,13 @@ void OSSPlayback::stop() return; mThread.join(); - if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) - ERR("Error resetting device: %s\n", strerror(errno)); + if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ + ERR("Error resetting device: {}", std::generic_category().message(errno)); } struct OSScapture final : public BackendBase { - OSScapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit OSScapture(DeviceBase *device) noexcept : BackendBase{device} { } ~OSScapture() override; int recordProc(); @@ -455,8 +474,6 @@ struct OSScapture final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(OSScapture) }; OSScapture::~OSScapture() @@ -470,7 +487,7 @@ OSScapture::~OSScapture() int OSScapture::recordProc() { SetRTPriority(); - althrd_setname(RECORD_THREAD_NAME); + althrd_setname(GetRecordThreadName()); const size_t frame_size{mDevice->frameSizeFromFmt()}; while(!mKillNow.load(std::memory_order_acquire)) @@ -479,29 +496,30 @@ int OSScapture::recordProc() pollitem.fd = mFd; pollitem.events = POLLIN; - int sret{poll(&pollitem, 1, 1000)}; - if(sret < 0) + if(int pret{poll(&pollitem, 1, 1000)}; pret < 0) { if(errno == EINTR || errno == EAGAIN) continue; - ERR("poll failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed to check capture samples: %s", strerror(errno)); + const auto errstr = std::generic_category().message(errno); + ERR("poll failed: {}", errstr); + mDevice->handleDisconnect("Failed to check capture samples: {}", errstr); break; } - else if(sret == 0) + else if(pret == 0) /* NOLINT(*-else-after-return) 'pret' is local to the if/else blocks */ { - WARN("poll timeout\n"); + WARN("poll timeout"); continue; } auto vec = mRing->getWriteVector(); - if(vec.first.len > 0) + if(vec[0].len > 0) { - ssize_t amt{read(mFd, vec.first.buf, vec.first.len*frame_size)}; + ssize_t amt{read(mFd, vec[0].buf, vec[0].len*frame_size)}; if(amt < 0) { - ERR("read failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed reading capture samples: %s", strerror(errno)); + const auto errstr = std::generic_category().message(errno); + ERR("read failed: {}", errstr); + mDevice->handleDisconnect("Failed reading capture samples: {}", errstr); break; } mRing->writeAdvance(static_cast(amt)/frame_size); @@ -516,7 +534,7 @@ void OSScapture::open(std::string_view name) { const char *devname{DefaultCapture.c_str()}; if(name.empty()) - name = DefaultName; + name = GetDefaultName(); else { if(CaptureDevices.empty()) @@ -528,14 +546,14 @@ void OSScapture::open(std::string_view name) ); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; devname = iter->device_name.c_str(); } - mFd = ::open(devname, O_RDONLY); + mFd = ::open(devname, O_RDONLY); /* NOLINT(cppcoreguidelines-pro-type-vararg) */ if(mFd == -1) - throw al::backend_exception{al::backend_error::NoDevice, "Could not open %s: %s", devname, - strerror(errno)}; + throw al::backend_exception{al::backend_error::NoDevice, "Could not open {}: {}", devname, + std::generic_category().message(errno)}; int ossFormat{}; switch(mDevice->FmtType) @@ -554,55 +572,57 @@ void OSScapture::open(std::string_view name) case DevFmtUInt: case DevFmtFloat: throw al::backend_exception{al::backend_error::DeviceError, - "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; + "{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; } uint periods{4}; uint numChannels{mDevice->channelsFromFmt()}; uint frameSize{numChannels * mDevice->bytesFromFmt()}; - uint ossSpeed{mDevice->Frequency}; + uint ossSpeed{mDevice->mSampleRate}; /* according to the OSS spec, 16 bytes are the minimum */ - uint log2FragmentSize{maxu(log2i(mDevice->BufferSize * frameSize / periods), 4)}; + uint log2FragmentSize{std::max(log2i(mDevice->mBufferSize * frameSize / periods), 4u)}; uint numFragmentsLogSize{(periods << 16) | log2FragmentSize}; audio_buf_info info{}; #define CHECKERR(func) if((func) < 0) { \ - throw al::backend_exception{al::backend_error::DeviceError, #func " failed: %s", \ - strerror(errno)}; \ + throw al::backend_exception{al::backend_error::DeviceError, #func " failed: {}", \ + std::generic_category().message(errno)}; \ } + /* NOLINTBEGIN(cppcoreguidelines-pro-type-vararg) */ CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFRAGMENT, &numFragmentsLogSize)); CHECKERR(ioctl(mFd, SNDCTL_DSP_SETFMT, &ossFormat)); CHECKERR(ioctl(mFd, SNDCTL_DSP_CHANNELS, &numChannels)); CHECKERR(ioctl(mFd, SNDCTL_DSP_SPEED, &ossSpeed)); CHECKERR(ioctl(mFd, SNDCTL_DSP_GETISPACE, &info)); + /* NOLINTEND(cppcoreguidelines-pro-type-vararg) */ #undef CHECKERR if(mDevice->channelsFromFmt() != numChannels) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to set %s, got %d channels instead", DevFmtChannelsString(mDevice->FmtChans), + "Failed to set {}, got {} channels instead", DevFmtChannelsString(mDevice->FmtChans), numChannels}; if(!((ossFormat == AFMT_S8 && mDevice->FmtType == DevFmtByte) || (ossFormat == AFMT_U8 && mDevice->FmtType == DevFmtUByte) || (ossFormat == AFMT_S16_NE && mDevice->FmtType == DevFmtShort))) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to set %s samples, got OSS format %#x", DevFmtTypeString(mDevice->FmtType), - ossFormat}; + "Failed to set {} samples, got OSS format {:#x}", DevFmtTypeString(mDevice->FmtType), + as_unsigned(ossFormat)}; - mRing = RingBuffer::Create(mDevice->BufferSize, frameSize, false); + mRing = RingBuffer::Create(mDevice->mBufferSize, frameSize, false); - mDevice->DeviceName = name; + mDeviceName = name; } void OSScapture::start() { try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&OSScapture::recordProc), this}; + mThread = std::thread{&OSScapture::recordProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start recording thread: %s", e.what()}; + "Failed to start recording thread: {}", e.what()}; } } @@ -612,12 +632,12 @@ void OSScapture::stop() return; mThread.join(); - if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) - ERR("Error resetting device: %s\n", strerror(errno)); + if(ioctl(mFd, SNDCTL_DSP_RESET) != 0) /* NOLINT(cppcoreguidelines-pro-type-vararg) */ + ERR("Error resetting device: {}", std::generic_category().message(errno)); } void OSScapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } uint OSScapture::availableSamples() { return static_cast(mRing->readSpace()); } @@ -633,9 +653,9 @@ BackendFactory &OSSBackendFactory::getFactory() bool OSSBackendFactory::init() { - if(auto devopt = ConfigValueStr(nullptr, "oss", "device")) + if(auto devopt = ConfigValueStr({}, "oss", "device")) DefaultPlayback = std::move(*devopt); - if(auto capopt = ConfigValueStr(nullptr, "oss", "capture")) + if(auto capopt = ConfigValueStr({}, "oss", "capture")) DefaultCapture = std::move(*capopt); return true; @@ -644,18 +664,13 @@ bool OSSBackendFactory::init() bool OSSBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string OSSBackendFactory::probe(BackendType type) +auto OSSBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; - + std::vector outnames; auto add_device = [&outnames](const DevMap &entry) -> void { - struct stat buf; - if(stat(entry.device_name.c_str(), &buf) == 0) - { - /* Includes null char. */ - outnames.append(entry.name.c_str(), entry.name.length()+1); - } + if(struct stat buf{}; stat(entry.device_name.c_str(), &buf) == 0) + outnames.emplace_back(entry.name); }; switch(type) @@ -663,12 +678,14 @@ std::string OSSBackendFactory::probe(BackendType type) case BackendType::Playback: PlaybackDevices.clear(); ALCossListPopulate(PlaybackDevices, DSP_CAP_OUTPUT); + outnames.reserve(PlaybackDevices.size()); std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device); break; case BackendType::Capture: CaptureDevices.clear(); ALCossListPopulate(CaptureDevices, DSP_CAP_INPUT); + outnames.reserve(CaptureDevices.size()); std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); break; } diff --git a/3rdparty/openal/alc/backends/oss.h b/3rdparty/openal/alc/backends/oss.h index 4f2c00b96990..b5faf96a5784 100644 --- a/3rdparty/openal/alc/backends/oss.h +++ b/3rdparty/openal/alc/backends/oss.h @@ -5,15 +5,15 @@ struct OSSBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_OSS_H */ diff --git a/3rdparty/openal/alc/backends/otherio.cpp b/3rdparty/openal/alc/backends/otherio.cpp new file mode 100644 index 000000000000..e7b33a78b55e --- /dev/null +++ b/3rdparty/openal/alc/backends/otherio.cpp @@ -0,0 +1,700 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2024 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include "otherio.h" + +#define WIN32_LEAN_AND_MEAN +#include +#include + +#include +#include +#include + +#include +#include +#include +#include +#include +#include +#include +#ifndef _WAVEFORMATEXTENSIBLE_ +#include +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "albit.h" +#include "alnumeric.h" +#include "althrd_setname.h" +#include "comptr.h" +#include "core/converter.h" +#include "core/device.h" +#include "core/helpers.h" +#include "core/logging.h" +#include "strutils.h" + + +/* A custom C++ interface that should be capable of interoperating with ASIO + * drivers. + */ +enum class ORIOError : LONG { + Okay = 0, + Success = 0x3f4847a0, + NotPresent = -1000, + HWMalfunction, + InvalidParameter, + InvalidMode, + SPNotAdvancing, + NoClock, + NoMemory, +}; + +/* A 64-bit integer or double, which has the most significant 32-bit word first. */ +struct ORIO64Bit { + uint32_t hi; + uint32_t lo; + + template + auto as() const -> T = delete; +}; + +template<> [[nodiscard]] +auto ORIO64Bit::as() const -> uint64_t { return (uint64_t{hi}<<32) | lo; } +template<> [[nodiscard]] +auto ORIO64Bit::as() const -> int64_t { return static_cast(as()); } +template<> [[nodiscard]] +auto ORIO64Bit::as() const -> double { return al::bit_cast(as()); } + + +enum class ORIOSampleType : LONG { + Int16BE = 0, + Int24BE = 1, + Int32BE = 2, + Float32BE = 3, + Float64BE = 4, + Int32BE16 = 8, + Int32BE18 = 9, + Int32BE20 = 10, + Int32BE24 = 11, + + Int16LE = 16, + Int24LE = 17, + Int32LE = 18, + Float32LE = 19, + Float64LE = 20, + Int32LE16 = 24, + Int32LE18 = 25, + Int32LE20 = 26, + Int32LE24 = 27, + + DSDInt8LSB1 = 32, + DSDInt8MSB1 = 33, + + DSDInt8 = 40, +}; + +struct ORIOClockSource { + LONG mIndex; + LONG mAssocChannel; + LONG mAssocGroup; + LONG mIsCurrent; + std::array mName; +}; + +struct ORIOChannelInfo { + LONG mChannel; + LONG mIsInput; + LONG mIsActive; + LONG mGroup; + ORIOSampleType mSampleType; + std::array mName; +}; + +struct ORIOBufferInfo { + LONG mIsInput; + LONG mChannelNum; + std::array mBuffers; +}; + +struct ORIOTime { + struct TimeInfo { + double mSpeed; + ORIO64Bit mSystemTime; + ORIO64Bit mSamplePosition; + double mSampleRate; + ULONG mFlags; + std::array mReserved; + }; + struct TimeCode { + double mSpeed; + ORIO64Bit mTimeCodeSamples; + ULONG mFlags; + std::array mFuture; + }; + + std::array mReserved; + TimeInfo mTimeInfo; + TimeCode mTimeCode; +}; + +#ifdef _WIN64 +#define ORIO_CALLBACK CALLBACK +#else +#define ORIO_CALLBACK +#endif + +struct ORIOCallbacks { + void (ORIO_CALLBACK*BufferSwitch)(LONG bufferIndex, LONG directProcess) noexcept; + void (ORIO_CALLBACK*SampleRateDidChange)(double srate) noexcept; + auto (ORIO_CALLBACK*Message)(LONG selector, LONG value, void *message, double *opt) noexcept -> LONG; + auto (ORIO_CALLBACK*BufferSwitchTimeInfo)(ORIOTime *timeInfo, LONG bufferIndex, LONG directProcess) noexcept -> ORIOTime*; +}; + +/* COM interfaces don't include a virtual destructor in their pure-virtual + * classes, and we can't add one without breaking ABI. + */ +#ifdef __GNUC__ +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wnon-virtual-dtor\"") +#endif +/* NOLINTNEXTLINE(cppcoreguidelines-virtual-class-destructor) */ +struct ORIOiface : public IUnknown { + STDMETHOD_(LONG, Init)(void *sysHandle) = 0; + /* A fixed-length span should be passed exactly the same as one pointer. + * This ensures an appropriately-sized buffer for the driver. + */ + STDMETHOD_(void, GetDriverName)(al::span name) = 0; + STDMETHOD_(LONG, GetDriverVersion)() = 0; + STDMETHOD_(void, GetErrorMessage)(al::span message) = 0; + STDMETHOD_(ORIOError, Start)() = 0; + STDMETHOD_(ORIOError, Stop)() = 0; + STDMETHOD_(ORIOError, GetChannels)(LONG *numInput, LONG *numOutput) = 0; + STDMETHOD_(ORIOError, GetLatencies)(LONG *inputLatency, LONG *outputLatency) = 0; + STDMETHOD_(ORIOError, GetBufferSize)(LONG *minSize, LONG *maxSize, LONG *preferredSize, LONG *granularity) = 0; + STDMETHOD_(ORIOError, CanSampleRate)(double srate) = 0; + STDMETHOD_(ORIOError, GetSampleRate)(double *srate) = 0; + STDMETHOD_(ORIOError, SetSampleRate)(double srate) = 0; + STDMETHOD_(ORIOError, GetClockSources)(ORIOClockSource *clocks, LONG *numSources) = 0; + STDMETHOD_(ORIOError, SetClockSource)(LONG index) = 0; + STDMETHOD_(ORIOError, GetSamplePosition)(ORIO64Bit *splPos, ORIO64Bit *tstampNS) = 0; + STDMETHOD_(ORIOError, GetChannelInfo)(ORIOChannelInfo *info) = 0; + STDMETHOD_(ORIOError, CreateBuffers)(ORIOBufferInfo *infos, LONG numInfos, LONG bufferSize, ORIOCallbacks *callbacks) = 0; + STDMETHOD_(ORIOError, DisposeBuffers)() = 0; + STDMETHOD_(ORIOError, ControlPanel)() = 0; + STDMETHOD_(ORIOError, Future)(LONG selector, void *opt) = 0; + STDMETHOD_(ORIOError, OutputReady)() = 0; + + ORIOiface() = default; + ORIOiface(const ORIOiface&) = delete; + auto operator=(const ORIOiface&) -> ORIOiface& = delete; + ~ORIOiface() = delete; +}; +#ifdef __GNUC__ +_Pragma("GCC diagnostic pop") +#endif + +namespace { + +using namespace std::string_view_literals; +using std::chrono::nanoseconds; +using std::chrono::milliseconds; +using std::chrono::seconds; + + +struct DeviceEntry { + std::string mDrvName; + CLSID mDrvGuid{}; +}; + +std::vector gDeviceList; + + +struct KeyCloser { + void operator()(HKEY key) { RegCloseKey(key); } +}; +using KeyPtr = std::unique_ptr,KeyCloser>; + +[[nodiscard]] +auto PopulateDeviceList() -> HRESULT +{ + auto regbase = KeyPtr{}; + auto res = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\ASIO", 0, KEY_READ, + al::out_ptr(regbase)); + if(res != ERROR_SUCCESS) + { + ERR("Error opening HKLM\\Software\\ASIO: {}", res); + return E_NOINTERFACE; + } + + auto numkeys = DWORD{}; + auto maxkeylen = DWORD{}; + res = RegQueryInfoKeyW(regbase.get(), nullptr, nullptr, nullptr, &numkeys, &maxkeylen, nullptr, + nullptr, nullptr, nullptr, nullptr, nullptr); + if(res != ERROR_SUCCESS) + { + ERR("Error querying HKLM\\Software\\ASIO info: {}", res); + return E_FAIL; + } + + /* maxkeylen is the max number of unicode characters a subkey is. A unicode + * character can occupy two WCHARs, so ensure there's enough space for them + * and the null char. + */ + auto keyname = std::vector(maxkeylen*2 + 1); + for(DWORD i{0};i < numkeys;++i) + { + auto namelen = static_cast(keyname.size()); + res = RegEnumKeyExW(regbase.get(), i, keyname.data(), &namelen, nullptr, nullptr, nullptr, + nullptr); + if(res != ERROR_SUCCESS) + { + ERR("Error querying HKLM\\Software\\ASIO subkey {}: {}", i, res); + continue; + } + if(namelen == 0) + { + ERR("HKLM\\Software\\ASIO subkey {} is blank?", i); + continue; + } + auto subkeyname = wstr_to_utf8({keyname.data(), namelen}); + + auto subkey = KeyPtr{}; + res = RegOpenKeyExW(regbase.get(), keyname.data(), 0, KEY_READ, al::out_ptr(subkey)); + if(res != ERROR_SUCCESS) + { + ERR("Error opening HKLM\\Software\\ASIO\\{}: {}", subkeyname, res); + continue; + } + + auto idstr = std::array{}; + auto readsize = DWORD{idstr.size()*sizeof(WCHAR)}; + res = RegGetValueW(subkey.get(), L"", L"CLSID", RRF_RT_REG_SZ, nullptr, idstr.data(), + &readsize); + if(res != ERROR_SUCCESS) + { + ERR("Failed to read HKLM\\Software\\ASIO\\{}\\CLSID: {}", subkeyname, res); + continue; + } + idstr.back() = 0; + + auto guid = CLSID{}; + if(auto hr = CLSIDFromString(idstr.data(), &guid); FAILED(hr)) + { + ERR("Failed to parse CLSID \"{}\": {:#x}", wstr_to_utf8(idstr.data()), + as_unsigned(hr)); + continue; + } + + /* The CLSID is also used for the IID. */ + auto iface = ComPtr{}; + auto hr = CoCreateInstance(guid, nullptr, CLSCTX_INPROC_SERVER, guid, al::out_ptr(iface)); + if(SUCCEEDED(hr)) + { +#if !ALSOFT_UWP + if(!iface->Init(GetForegroundWindow())) +#else + if(!iface->Init(nullptr)) +#endif + { + ERR("Failed to initialize {}", subkeyname); + continue; + } + auto drvname = std::array{}; + iface->GetDriverName(drvname); + auto drvver = iface->GetDriverVersion(); + + auto &entry = gDeviceList.emplace_back(); + entry.mDrvName = drvname.data(); + entry.mDrvGuid = guid; + + TRACE("Got {} v{}, CLSID {{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}", + entry.mDrvName, drvver, guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], + guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], + guid.Data4[6], guid.Data4[7]); + } + else + ERR("Failed to create {} instance for CLSID {{{:08X}-{:04X}-{:04X}-{:02X}{:02X}-{:02X}{:02X}{:02X}{:02X}{:02X}{:02X}}}: {:#x}", + subkeyname.c_str(), guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], + guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], + guid.Data4[6], guid.Data4[7], as_unsigned(hr)); + } + + return S_OK; +} + + +enum class MsgType { + OpenDevice, + ResetDevice, + StartDevice, + StopDevice, + CloseDevice, + + QuitThread +}; + +constexpr const char *GetMessageTypeName(MsgType type) noexcept +{ + switch(type) + { + case MsgType::OpenDevice: return "Open Device"; + case MsgType::ResetDevice: return "Reset Device"; + case MsgType::StartDevice: return "Start Device"; + case MsgType::StopDevice: return "Stop Device"; + case MsgType::CloseDevice: return "Close Device"; + case MsgType::QuitThread: break; + } + return ""; +} + + +/* Proxy interface used by the message handler, to ensure COM objects are used + * on a thread where COM is initialized. + */ +struct OtherIOProxy { + OtherIOProxy() = default; + OtherIOProxy(const OtherIOProxy&) = delete; + OtherIOProxy(OtherIOProxy&&) = delete; + virtual ~OtherIOProxy() = default; + + void operator=(const OtherIOProxy&) = delete; + void operator=(OtherIOProxy&&) = delete; + + virtual HRESULT openProxy(std::string_view name) = 0; + virtual void closeProxy() = 0; + + virtual HRESULT resetProxy() = 0; + virtual HRESULT startProxy() = 0; + virtual void stopProxy() = 0; + + struct Msg { + MsgType mType; + OtherIOProxy *mProxy; + std::string_view mParam; + std::promise mPromise; + + explicit operator bool() const noexcept { return mType != MsgType::QuitThread; } + }; + static inline std::deque mMsgQueue; + static inline std::mutex mMsgQueueLock; + static inline std::condition_variable mMsgQueueCond; + + auto pushMessage(MsgType type, std::string_view param={}) -> std::future + { + auto promise = std::promise{}; + auto future = std::future{promise.get_future()}; + { + auto msglock = std::lock_guard{mMsgQueueLock}; + mMsgQueue.emplace_back(Msg{type, this, param, std::move(promise)}); + } + mMsgQueueCond.notify_one(); + return future; + } + + static auto popMessage() -> Msg + { + auto lock = std::unique_lock{mMsgQueueLock}; + mMsgQueueCond.wait(lock, []{return !mMsgQueue.empty();}); + auto msg = Msg{std::move(mMsgQueue.front())}; + mMsgQueue.pop_front(); + return msg; + } + + static void messageHandler(std::promise *promise); +}; + +void OtherIOProxy::messageHandler(std::promise *promise) +{ + TRACE("Starting COM message thread"); + + auto com = ComWrapper{COINIT_APARTMENTTHREADED}; + if(!com) + { + WARN("Failed to initialize COM: {:#x}", as_unsigned(com.status())); + promise->set_value(com.status()); + return; + } + + auto hr = PopulateDeviceList(); + if(FAILED(hr)) + { + promise->set_value(hr); + return; + } + + promise->set_value(S_OK); + promise = nullptr; + + TRACE("Starting message loop"); + while(Msg msg{popMessage()}) + { + TRACE("Got message \"{}\" ({:#04x}, this={}, param=\"{}\")", + GetMessageTypeName(msg.mType), static_cast(msg.mType), + static_cast(msg.mProxy), msg.mParam); + + switch(msg.mType) + { + case MsgType::OpenDevice: + hr = msg.mProxy->openProxy(msg.mParam); + msg.mPromise.set_value(hr); + continue; + + case MsgType::ResetDevice: + hr = msg.mProxy->resetProxy(); + msg.mPromise.set_value(hr); + continue; + + case MsgType::StartDevice: + hr = msg.mProxy->startProxy(); + msg.mPromise.set_value(hr); + continue; + + case MsgType::StopDevice: + msg.mProxy->stopProxy(); + msg.mPromise.set_value(S_OK); + continue; + + case MsgType::CloseDevice: + msg.mProxy->closeProxy(); + msg.mPromise.set_value(S_OK); + continue; + + case MsgType::QuitThread: + break; + } + ERR("Unexpected message: {}", int{al::to_underlying(msg.mType)}); + msg.mPromise.set_value(E_FAIL); + } + TRACE("Message loop finished"); +} + + +struct OtherIOPlayback final : public BackendBase, OtherIOProxy { + explicit OtherIOPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + ~OtherIOPlayback() final; + + void mixerProc(); + + void open(std::string_view name) final; + auto openProxy(std::string_view name) -> HRESULT final; + void closeProxy() final; + auto reset() -> bool final; + auto resetProxy() -> HRESULT final; + void start() final; + auto startProxy() -> HRESULT final; + void stop() final; + void stopProxy() final; + + HRESULT mOpenStatus{E_FAIL}; + + std::atomic mKillNow{true}; + std::thread mThread; +}; + +OtherIOPlayback::~OtherIOPlayback() +{ + if(SUCCEEDED(mOpenStatus)) + pushMessage(MsgType::CloseDevice).wait(); +} + +void OtherIOPlayback::mixerProc() +{ + const auto restTime = milliseconds{mDevice->mUpdateSize*1000/mDevice->mSampleRate / 2}; + + SetRTPriority(); + althrd_setname(GetMixerThreadName()); + + auto done = int64_t{0}; + auto start = std::chrono::steady_clock::now(); + while(!mKillNow.load(std::memory_order_acquire) + && mDevice->Connected.load(std::memory_order_acquire)) + { + auto now = std::chrono::steady_clock::now(); + + /* This converts from nanoseconds to nanosamples, then to samples. */ + const auto avail = int64_t{std::chrono::duration_cast((now-start) + * mDevice->mSampleRate).count()}; + if(avail-done < mDevice->mUpdateSize) + { + std::this_thread::sleep_for(restTime); + continue; + } + while(avail-done >= mDevice->mUpdateSize) + { + mDevice->renderSamples(nullptr, mDevice->mUpdateSize, 0u); + done += mDevice->mUpdateSize; + } + + if(done >= mDevice->mSampleRate) + { + auto s = seconds{done/mDevice->mSampleRate}; + start += s; + done -= mDevice->mSampleRate*s.count(); + } + } +} + + +void OtherIOPlayback::open(std::string_view name) +{ + if(name.empty() && !gDeviceList.empty()) + name = gDeviceList[0].mDrvName; + else + { + auto iter = std::find_if(gDeviceList.cbegin(), gDeviceList.cend(), + [name](const DeviceEntry &entry) { return entry.mDrvName == name; }); + if(iter == gDeviceList.cend()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name \"{}\" not found", name}; + } + + mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); + if(FAILED(mOpenStatus)) + throw al::backend_exception{al::backend_error::DeviceError, "Failed to open \"{}\"", name}; + + mDeviceName = name; +} + +auto OtherIOPlayback::openProxy(std::string_view name [[maybe_unused]]) -> HRESULT +{ + return S_OK; +} + +void OtherIOPlayback::closeProxy() +{ +} + +auto OtherIOPlayback::reset() -> bool +{ + return SUCCEEDED(pushMessage(MsgType::ResetDevice).get()); +} + +auto OtherIOPlayback::resetProxy() -> HRESULT +{ + setDefaultWFXChannelOrder(); + return S_OK; +} + +void OtherIOPlayback::start() +{ + auto hr = pushMessage(MsgType::StartDevice).get(); + if(FAILED(hr)) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to start playback: {:#x}", as_unsigned(hr)}; +} + +auto OtherIOPlayback::startProxy() -> HRESULT +{ + try { + mKillNow.store(false, std::memory_order_release); + mThread = std::thread{&OtherIOPlayback::mixerProc, this}; + return S_OK; + } + catch(std::exception& e) { + ERR("Failed to start mixing thread: {}", e.what()); + } + return E_FAIL; +} + +void OtherIOPlayback::stop() +{ + pushMessage(MsgType::StopDevice).wait(); +} + +void OtherIOPlayback::stopProxy() +{ + if(mKillNow.exchange(true, std::memory_order_acq_rel) || !mThread.joinable()) + return; + mThread.join(); +} + +} // namespace + + +auto OtherIOBackendFactory::init() -> bool +{ + static HRESULT InitResult{E_FAIL}; + if(FAILED(InitResult)) try + { + auto promise = std::promise{}; + auto future = promise.get_future(); + + std::thread{&OtherIOProxy::messageHandler, &promise}.detach(); + InitResult = future.get(); + } + catch(...) { + } + + return SUCCEEDED(InitResult); +} + +auto OtherIOBackendFactory::querySupport(BackendType type) -> bool +{ return type == BackendType::Playback; } + +auto OtherIOBackendFactory::enumerate(BackendType type) -> std::vector +{ + std::vector outnames; + + switch(type) + { + case BackendType::Playback: + std::for_each(gDeviceList.cbegin(), gDeviceList.cend(), + [&outnames](const DeviceEntry &entry) { outnames.emplace_back(entry.mDrvName); }); + break; + + case BackendType::Capture: + break; + } + + return outnames; +} + +auto OtherIOBackendFactory::createBackend(DeviceBase *device, BackendType type) -> BackendPtr +{ + if(type == BackendType::Playback) + return BackendPtr{new OtherIOPlayback{device}}; + return nullptr; +} + +auto OtherIOBackendFactory::getFactory() -> BackendFactory& +{ + static auto factory = OtherIOBackendFactory{}; + return factory; +} + +auto OtherIOBackendFactory::queryEventSupport(alc::EventType, BackendType) -> alc::EventSupport +{ + return alc::EventSupport::NoSupport; +} diff --git a/3rdparty/openal/alc/backends/otherio.h b/3rdparty/openal/alc/backends/otherio.h new file mode 100644 index 000000000000..64cb436ea7ec --- /dev/null +++ b/3rdparty/openal/alc/backends/otherio.h @@ -0,0 +1,21 @@ +#ifndef BACKENDS_OTHERIO_H +#define BACKENDS_OTHERIO_H + +#include "base.h" + +struct OtherIOBackendFactory final : public BackendFactory { +public: + auto init() -> bool final; + + auto querySupport(BackendType type) -> bool final; + + auto queryEventSupport(alc::EventType eventType, BackendType type) -> alc::EventSupport final; + + auto enumerate(BackendType type) -> std::vector final; + + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; +}; + +#endif /* BACKENDS_OTHERIO_H */ diff --git a/3rdparty/openal/alc/backends/pipewire.cpp b/3rdparty/openal/alc/backends/pipewire.cpp index 1c4e2cc4933b..12951bb8096b 100644 --- a/3rdparty/openal/alc/backends/pipewire.cpp +++ b/3rdparty/openal/alc/backends/pipewire.cpp @@ -23,26 +23,31 @@ #include "pipewire.h" #include +#include #include +#include +#include +#include #include +#include +#include #include #include #include #include -#include +#include +#include #include #include #include -#include +#include #include -#include +#include #include -#include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" +#include "alc/backends/base.h" #include "almalloc.h" -#include "alnumeric.h" #include "alspan.h" #include "alstring.h" #include "core/devformat.h" @@ -50,6 +55,8 @@ #include "core/helpers.h" #include "core/logging.h" #include "dynload.h" +#include "fmt/core.h" +#include "fmt/ranges.h" #include "opthelpers.h" #include "ringbuffer.h" @@ -73,10 +80,15 @@ _Pragma("GCC diagnostic ignored \"-Weverything\"") #include "spa/buffer/buffer.h" #include "spa/param/audio/format-utils.h" #include "spa/param/audio/raw.h" +#include "spa/param/format.h" #include "spa/param/param.h" #include "spa/pod/builder.h" #include "spa/utils/json.h" +/* NOLINTBEGIN : All kinds of unsafe C stuff here from PipeWire headers + * (function-like macros, C style casts in macros, etc), which we can't do + * anything about except wrap into inline functions. + */ namespace { /* Wrap some nasty macros here too... */ template @@ -109,32 +121,72 @@ template constexpr auto get_pod_body(const spa_pod *pod) noexcept { return al::span{static_cast(SPA_POD_BODY(pod)), N}; } -constexpr auto make_pod_builder(void *data, uint32_t size) noexcept -{ return SPA_POD_BUILDER_INIT(data, size); } - constexpr auto get_array_value_type(const spa_pod *pod) noexcept { return SPA_POD_ARRAY_VALUE_TYPE(pod); } +constexpr auto make_pod_builder(void *data, uint32_t size) noexcept +{ return SPA_POD_BUILDER_INIT(data, size); } + constexpr auto PwIdAny = PW_ID_ANY; } // namespace +/* NOLINTEND */ _Pragma("GCC diagnostic pop") namespace { +template [[nodiscard]] constexpr +auto as_const_ptr(T *ptr) noexcept -> std::add_const_t* { return ptr; } + +struct PodDynamicBuilder { +private: + std::vector mStorage; + spa_pod_builder mPod{}; + + int overflow(uint32_t size) noexcept + { + try { + mStorage.resize(size); + } + catch(...) { + ERR("Failed to resize POD storage"); + return -ENOMEM; + } + mPod.data = mStorage.data(); + mPod.size = size; + return 0; + } + +public: + explicit PodDynamicBuilder(uint32_t initSize=1024) : mStorage(initSize) + , mPod{make_pod_builder(mStorage.data(), initSize)} + { + static constexpr auto callbacks{[] + { + spa_pod_builder_callbacks cb{}; + cb.version = SPA_VERSION_POD_BUILDER_CALLBACKS; + cb.overflow = [](void *data, uint32_t size) noexcept + { return static_cast(data)->overflow(size); }; + return cb; + }()}; + + spa_pod_builder_set_callbacks(&mPod, &callbacks, this); + } + + spa_pod_builder *get() noexcept { return &mPod; } +}; + /* Added in 0.3.33, but we currently only require 0.3.23. */ #ifndef PW_KEY_NODE_RATE #define PW_KEY_NODE_RATE "node.rate" #endif +using namespace std::string_view_literals; using std::chrono::seconds; using std::chrono::milliseconds; using std::chrono::nanoseconds; using uint = unsigned int; -constexpr char pwireDevice[] = "PipeWire Output"; -constexpr char pwireInput[] = "PipeWire Input"; - bool check_version(const char *version) { @@ -143,14 +195,13 @@ bool check_version(const char *version) * future. */ int major{0}, minor{0}, revision{0}; + /* NOLINTNEXTLINE(cert-err34-c,cppcoreguidelines-pro-type-vararg) */ int ret{sscanf(version, "%d.%d.%d", &major, &minor, &revision)}; - if(ret == 3 && (major > PW_MAJOR || (major == PW_MAJOR && minor > PW_MINOR) - || (major == PW_MAJOR && minor == PW_MINOR && revision >= PW_MICRO))) - return true; - return false; + return ret == 3 && (major > PW_MAJOR || (major == PW_MAJOR && minor > PW_MINOR) + || (major == PW_MAJOR && minor == PW_MINOR && revision >= PW_MICRO)); } -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD #define PWIRE_FUNCS(MAGIC) \ MAGIC(pw_context_connect) \ MAGIC(pw_context_destroy) \ @@ -201,18 +252,18 @@ bool pwire_load() if(pwire_handle) return true; - static constexpr char pwire_library[] = "libpipewire-0.3.so.0"; + const char *pwire_library{"libpipewire-0.3.so.0"}; std::string missing_funcs; pwire_handle = LoadLib(pwire_library); if(!pwire_handle) { - WARN("Failed to load %s\n", pwire_library); + WARN("Failed to load {}", pwire_library); return false; } #define LOAD_FUNC(f) do { \ - p##f = al::bit_cast(GetSymbol(pwire_handle, #f)); \ + p##f = reinterpret_cast(GetSymbol(pwire_handle, #f)); \ if(p##f == nullptr) missing_funcs += "\n" #f; \ } while(0); PWIRE_FUNCS(LOAD_FUNC) @@ -221,7 +272,7 @@ bool pwire_load() if(!missing_funcs.empty()) { - WARN("Missing expected functions:%s\n", missing_funcs.c_str()); + WARN("Missing expected functions:{}", missing_funcs); CloseLib(pwire_handle); pwire_handle = nullptr; return false; @@ -296,7 +347,7 @@ using Pod_t = typename PodInfo::Type; template al::span> get_array_span(const spa_pod *pod) { - uint32_t nvals; + uint32_t nvals{}; if(void *v{spa_pod_get_array(pod, &nvals)}) { if(get_array_value_type(pod) == T) @@ -330,11 +381,11 @@ To as(From) noexcept = delete; * - pw_metadata */ template<> -pw_proxy* as(pw_registry *reg) noexcept { return al::bit_cast(reg); } +pw_proxy* as(pw_registry *reg) noexcept { return reinterpret_cast(reg); } template<> -pw_proxy* as(pw_node *node) noexcept { return al::bit_cast(node); } +pw_proxy* as(pw_node *node) noexcept { return reinterpret_cast(node); } template<> -pw_proxy* as(pw_metadata *mdata) noexcept { return al::bit_cast(mdata); } +pw_proxy* as(pw_metadata *mdata) noexcept { return reinterpret_cast(mdata); } struct PwContextDeleter { @@ -367,9 +418,10 @@ struct PwStreamDeleter { }; using PwStreamPtr = std::unique_ptr; -/* Enums for bitflags... again... *sigh* */ +/* NOLINTBEGIN(*EnumCastOutOfRange) Enums for bitflags... again... *sigh* */ constexpr pw_stream_flags operator|(pw_stream_flags lhs, pw_stream_flags rhs) noexcept { return static_cast(lhs | al::to_underlying(rhs)); } +/* NOLINTEND(*EnumCastOutOfRange) */ constexpr pw_stream_flags& operator|=(pw_stream_flags &lhs, pw_stream_flags rhs) noexcept { lhs = lhs | rhs; return lhs; } @@ -397,9 +449,11 @@ class ThreadMainloop { explicit operator bool() const noexcept { return mLoop != nullptr; } + [[nodiscard]] auto start() const { return pw_thread_loop_start(mLoop); } auto stop() const { return pw_thread_loop_stop(mLoop); } + [[nodiscard]] auto getLoop() const { return pw_thread_loop_get_loop(mLoop); } auto lock() const { return pw_thread_loop_lock(mLoop); } @@ -407,7 +461,7 @@ class ThreadMainloop { auto signal(bool wait) const { return pw_thread_loop_signal(mLoop, wait); } - auto newContext(pw_properties *props=nullptr, size_t user_data_size=0) + auto newContext(pw_properties *props=nullptr, size_t user_data_size=0) const { return PwContextPtr{pw_context_new(getLoop(), props, user_data_size)}; } static auto Create(const char *name, spa_dict *props=nullptr) @@ -443,8 +497,7 @@ struct NodeProxy { { pw_node_events ret{}; ret.version = PW_VERSION_NODE_EVENTS; - ret.info = [](void *object, const pw_node_info *info) noexcept - { static_cast(object)->infoCallback(info); }; + ret.info = infoCallback; ret.param = [](void *object, int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept { static_cast(object)->paramCallback(seq, id, index, next, param); }; return ret; @@ -452,7 +505,7 @@ struct NodeProxy { uint32_t mId{}; - PwNodePtr mNode{}; + PwNodePtr mNode; spa_hook mListener{}; NodeProxy(uint32_t id, PwNodePtr node) @@ -464,16 +517,15 @@ struct NodeProxy { /* Track changes to the enumerable and current formats (indicates the * default and active format, which is what we're interested in). */ - uint32_t fmtids[]{SPA_PARAM_EnumFormat, SPA_PARAM_Format}; - ppw_node_subscribe_params(mNode.get(), std::data(fmtids), std::size(fmtids)); + std::array fmtids{{SPA_PARAM_EnumFormat, SPA_PARAM_Format}}; + ppw_node_subscribe_params(mNode.get(), fmtids.data(), fmtids.size()); } ~NodeProxy() { spa_hook_remove(&mListener); } - void infoCallback(const pw_node_info *info) noexcept; - - void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) noexcept; + static void infoCallback(void *object, const pw_node_info *info) noexcept; + void paramCallback(int seq, uint32_t id, uint32_t index, uint32_t next, const spa_pod *param) const noexcept; }; /* A metadata proxy object used to query the default sink and source. */ @@ -482,14 +534,13 @@ struct MetadataProxy { { pw_metadata_events ret{}; ret.version = PW_VERSION_METADATA_EVENTS; - ret.property = [](void *object, uint32_t id, const char *key, const char *type, const char *value) noexcept - { return static_cast(object)->propertyCallback(id, key, type, value); }; + ret.property = propertyCallback; return ret; } uint32_t mId{}; - PwMetadataPtr mMetadata{}; + PwMetadataPtr mMetadata; spa_hook mListener{}; MetadataProxy(uint32_t id, PwMetadataPtr mdata) @@ -501,7 +552,8 @@ struct MetadataProxy { ~MetadataProxy() { spa_hook_remove(&mListener); } - int propertyCallback(uint32_t id, const char *key, const char *type, const char *value) noexcept; + static auto propertyCallback(void *object, uint32_t id, const char *key, const char *type, + const char *value) noexcept -> int; }; @@ -509,10 +561,10 @@ struct MetadataProxy { * to objects being added to or removed from the registry. */ struct EventManager { - ThreadMainloop mLoop{}; - PwContextPtr mContext{}; - PwCorePtr mCore{}; - PwRegistryPtr mRegistry{}; + ThreadMainloop mLoop; + PwContextPtr mContext; + PwCorePtr mCore; + PwRegistryPtr mRegistry; spa_hook mRegistryListener{}; spa_hook mCoreListener{}; @@ -541,7 +593,8 @@ struct EventManager { auto lock() const { return mLoop.lock(); } auto unlock() const { return mLoop.unlock(); } - inline bool initIsDone(std::memory_order m=std::memory_order_seq_cst) noexcept + [[nodiscard]] + auto initIsDone(std::memory_order m=std::memory_order_seq_cst) const noexcept -> bool { return mInitDone.load(m); } /** @@ -647,7 +700,7 @@ struct DeviceNode { void parsePositions(const spa_pod *value, bool force_update) noexcept; void parseChannelCount(const spa_pod *value, bool force_update) noexcept; - void callEvent(alc::EventType type, std::string_view message) + void callEvent(alc::EventType type, std::string_view message) const { /* Source nodes aren't recognized for playback, only Sink and Duplex * nodes are. All node types are recognized for capture. @@ -714,7 +767,7 @@ void DeviceNode::Remove(uint32_t id) { if(n.mId != id) return false; - TRACE("Removing device \"%s\"\n", n.mDevName.c_str()); + TRACE("Removing device \"{}\"", n.mDevName); if(gEventHandler.initIsDone(std::memory_order_relaxed)) { const std::string msg{"Device removed: "+n.mName}; @@ -728,25 +781,32 @@ void DeviceNode::Remove(uint32_t id) } -const spa_audio_channel MonoMap[]{ +constexpr std::array MonoMap{ SPA_AUDIO_CHANNEL_MONO -}, StereoMap[] { +}; +constexpr std::array StereoMap{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR -}, QuadMap[]{ +}; +constexpr std::array QuadMap{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR -}, X51Map[]{ +}; +constexpr std::array X51Map{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR -}, X51RearMap[]{ +}; +constexpr std::array X51RearMap{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR -}, X61Map[]{ +}; +constexpr std::array X61Map{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RC, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR -}, X71Map[]{ +}; +constexpr std::array X71Map{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR -}, X714Map[]{ +}; +constexpr std::array X714Map{ SPA_AUDIO_CHANNEL_FL, SPA_AUDIO_CHANNEL_FR, SPA_AUDIO_CHANNEL_FC, SPA_AUDIO_CHANNEL_LFE, SPA_AUDIO_CHANNEL_RL, SPA_AUDIO_CHANNEL_RR, SPA_AUDIO_CHANNEL_SL, SPA_AUDIO_CHANNEL_SR, SPA_AUDIO_CHANNEL_TFL, SPA_AUDIO_CHANNEL_TFR, SPA_AUDIO_CHANNEL_TRL, SPA_AUDIO_CHANNEL_TRR @@ -756,17 +816,15 @@ const spa_audio_channel MonoMap[]{ * Checks if every channel in 'map1' exists in 'map0' (that is, map0 is equal * to or a superset of map1). */ -template -bool MatchChannelMap(const al::span map0, const spa_audio_channel (&map1)[N]) +bool MatchChannelMap(const al::span map0, + const al::span map1) { - if(map0.size() < N) + if(map0.size() < map1.size()) return false; - for(const spa_audio_channel chid : map1) - { - if(std::find(map0.begin(), map0.end(), chid) == map0.end()) - return false; - } - return true; + + auto find_channel = [map0](const spa_audio_channel chid) -> bool + { return std::find(map0.begin(), map0.end(), chid) != map0.end(); }; + return std::all_of(map1.cbegin(), map1.cend(), find_channel); } void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexcept @@ -778,7 +836,7 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce const uint podType{get_pod_type(value)}; if(podType != SPA_TYPE_Int) { - WARN(" Unhandled sample rate POD type: %u\n", podType); + WARN(" Unhandled sample rate POD type: {}", podType); return; } @@ -786,15 +844,16 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce { if(nvals != 3) { - WARN(" Unexpected SPA_CHOICE_Range count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_Range count: {}", nvals); return; } auto srates = get_pod_body(value); /* [0] is the default, [1] is the min, and [2] is the max. */ - TRACE(" sample rate: %d (range: %d -> %d)\n", srates[0], srates[1], srates[2]); + TRACE(" sample rate: {}, range: {}", srates[0], srates.subspan<1>()); if(!mSampleRate || force_update) - mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); + mSampleRate = static_cast(std::clamp(srates[0], MinOutputRate, + MaxOutputRate)); return; } @@ -802,25 +861,19 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce { if(nvals == 0) { - WARN(" Unexpected SPA_CHOICE_Enum count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_Enum count: {}", nvals); return; } auto srates = get_pod_body(value, nvals); /* [0] is the default, [1...size()-1] are available selections. */ - std::string others{(srates.size() > 1) ? std::to_string(srates[1]) : std::string{}}; - for(size_t i{2};i < srates.size();++i) - { - others += ", "; - others += std::to_string(srates[i]); - } - TRACE(" sample rate: %d (%s)\n", srates[0], others.c_str()); + TRACE(" sample rate: {}, list: {}", srates[0], srates.subspan(1)); /* Pick the first rate listed that's within the allowed range (default * rate if possible). */ for(const auto &rate : srates) { - if(rate >= MIN_OUTPUT_RATE && rate <= MAX_OUTPUT_RATE) + if(rate >= int{MinOutputRate} && rate <= int{MaxOutputRate}) { if(!mSampleRate || force_update) mSampleRate = static_cast(rate); @@ -834,18 +887,19 @@ void DeviceNode::parseSampleRate(const spa_pod *value, bool force_update) noexce { if(nvals != 1) { - WARN(" Unexpected SPA_CHOICE_None count: %u\n", nvals); + WARN(" Unexpected SPA_CHOICE_None count: {}", nvals); return; } auto srates = get_pod_body(value); - TRACE(" sample rate: %d\n", srates[0]); + TRACE(" sample rate: {}", srates[0]); if(!mSampleRate || force_update) - mSampleRate = static_cast(clampi(srates[0], MIN_OUTPUT_RATE, MAX_OUTPUT_RATE)); + mSampleRate = static_cast(std::clamp(srates[0], MinOutputRate, + MaxOutputRate)); return; } - WARN(" Unhandled sample rate choice type: %u\n", choiceType); + WARN(" Unhandled sample rate choice type: {}", choiceType); } void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcept @@ -855,7 +909,7 @@ void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcep if(choiceType != SPA_CHOICE_None || choiceCount != 1) { - ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount); + ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount); return; } @@ -886,7 +940,7 @@ void DeviceNode::parsePositions(const spa_pod *value, bool force_update) noexcep else mChannels = DevFmtMono; } - TRACE(" %zu position%s for %s%s\n", chanmap.size(), (chanmap.size()==1)?"":"s", + TRACE(" {} position{} for {}{}", chanmap.size(), (chanmap.size()==1)?"":"s", DevFmtChannelsString(mChannels), mIs51Rear?"(rear)":""); } @@ -898,7 +952,7 @@ void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noex if(choiceType != SPA_CHOICE_None || choiceCount != 1) { - ERR(" Unexpected positions choice: type=%u, count=%u\n", choiceType, choiceCount); + ERR(" Unexpected positions choice: type={}, count={}", choiceType, choiceCount); return; } @@ -914,20 +968,21 @@ void DeviceNode::parseChannelCount(const spa_pod *value, bool force_update) noex else if(*chancount >= 1) mChannels = DevFmtMono; } - TRACE(" %d channel%s for %s\n", *chancount, (*chancount==1)?"":"s", + TRACE(" {} channel{} for {}", *chancount, (*chancount==1)?"":"s", DevFmtChannelsString(mChannels)); } -constexpr char MonitorPrefix[]{"Monitor of "}; -constexpr auto MonitorPrefixLen = std::size(MonitorPrefix) - 1; -constexpr char AudioSinkClass[]{"Audio/Sink"}; -constexpr char AudioSourceClass[]{"Audio/Source"}; -constexpr char AudioSourceVirtualClass[]{"Audio/Source/Virtual"}; -constexpr char AudioDuplexClass[]{"Audio/Duplex"}; -constexpr char StreamClass[]{"Stream/"}; +[[nodiscard]] constexpr auto GetMonitorPrefix() noexcept { return "Monitor of "sv; } +[[nodiscard]] constexpr auto GetMonitorSuffix() noexcept { return ".monitor"sv; } +[[nodiscard]] constexpr auto GetAudioSinkClassName() noexcept { return "Audio/Sink"sv; } +[[nodiscard]] constexpr auto GetAudioSourceClassName() noexcept { return "Audio/Source"sv; } +[[nodiscard]] constexpr auto GetAudioDuplexClassName() noexcept { return "Audio/Duplex"sv; } +[[nodiscard]] constexpr auto GetAudioSourceVirtualClassName() noexcept +{ return "Audio/Source/Virtual"sv; } -void NodeProxy::infoCallback(const pw_node_info *info) noexcept + +void NodeProxy::infoCallback(void*, const pw_node_info *info) noexcept { /* We only care about property changes here (media class, name/desc). * Format changes will automatically invoke the param callback. @@ -940,18 +995,19 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept /* Can this actually change? */ const char *media_class{spa_dict_lookup(info->props, PW_KEY_MEDIA_CLASS)}; if(!media_class) UNLIKELY return; + const std::string_view className{media_class}; NodeType ntype{}; - if(al::strcasecmp(media_class, AudioSinkClass) == 0) + if(al::case_compare(className, GetAudioSinkClassName()) == 0) ntype = NodeType::Sink; - else if(al::strcasecmp(media_class, AudioSourceClass) == 0 - || al::strcasecmp(media_class, AudioSourceVirtualClass) == 0) + else if(al::case_compare(className, GetAudioSourceClassName()) == 0 + || al::case_compare(className, GetAudioSourceVirtualClassName()) == 0) ntype = NodeType::Source; - else if(al::strcasecmp(media_class, AudioDuplexClass) == 0) + else if(al::case_compare(className, GetAudioDuplexClassName()) == 0) ntype = NodeType::Duplex; else { - TRACE("Dropping device node %u which became type \"%s\"\n", info->id, media_class); + TRACE("Dropping device node {} which became type \"{}\"", info->id, media_class); DeviceNode::Remove(info->id); return; } @@ -970,32 +1026,40 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept serial_id = std::strtoull(serial_str, &serial_end, 0); if(*serial_end != '\0' || errno == ERANGE) { - ERR("Unexpected object serial: %s\n", serial_str); + ERR("Unexpected object serial: {}", serial_str); serial_id = info->id; } } #endif - std::string name; - if(nodeName && *nodeName) name = nodeName; - else name = "PipeWire node #"+std::to_string(info->id); + auto name = std::invoke([nodeName,info]() -> std::string + { + if(nodeName && *nodeName) + return std::string{nodeName}; + return fmt::format("PipeWire node #{}", info->id); + }); const char *form_factor{spa_dict_lookup(info->props, PW_KEY_DEVICE_FORM_FACTOR)}; - TRACE("Got %s device \"%s\"%s%s%s\n", AsString(ntype), devName ? devName : "(nil)", + TRACE("Got {} device \"{}\"{}{}{}", AsString(ntype), devName ? devName : "(nil)", form_factor?" (":"", form_factor?form_factor:"", form_factor?")":""); - TRACE(" \"%s\" = ID %" PRIu64 "\n", name.c_str(), serial_id); + TRACE(" \"{}\" = ID {}", name, serial_id); DeviceNode &node = DeviceNode::Add(info->id); node.mSerial = serial_id; /* This method is called both to notify about a new sink/source node, * and update properties for the node. It's unclear what properties can * change for an existing node without being removed first, so err on - * the side of caution: send a DeviceAdded event when the name differs, - * and send a DeviceRemoved event if it had a name that's being - * replaced. + * the side of caution: send a DeviceRemoved event if it had a name + * that's being changed, and send a DeviceAdded event when the name + * differs or it didn't have one. + * + * The DeviceRemoved event needs to be called before the potentially + * new NodeType is set, so the removal event is called for the previous + * device type, while the DeviceAdded event needs to be called after. * - * This is overkill if the name or devname can't change. + * This is overkill if the node type, name, and devname can't change. */ + bool notifyAdd{false}; if(node.mName != name) { if(gEventHandler.initIsDone(std::memory_order_relaxed)) @@ -1005,27 +1069,32 @@ void NodeProxy::infoCallback(const pw_node_info *info) noexcept const std::string msg{"Device removed: "+node.mName}; node.callEvent(alc::EventType::DeviceRemoved, msg); } - const std::string msg{"Device added: "+name}; - node.callEvent(alc::EventType::DeviceAdded, msg); + notifyAdd = true; } node.mName = std::move(name); } node.mDevName = devName ? devName : ""; node.mType = ntype; - node.mIsHeadphones = form_factor && (al::strcasecmp(form_factor, "headphones") == 0 - || al::strcasecmp(form_factor, "headset") == 0); + node.mIsHeadphones = form_factor && (al::case_compare(form_factor, "headphones"sv) == 0 + || al::case_compare(form_factor, "headset"sv) == 0); + if(notifyAdd) + { + const std::string msg{"Device added: "+node.mName}; + node.callEvent(alc::EventType::DeviceAdded, msg); + } } } -void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) noexcept +void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_pod *param) const noexcept { if(id == SPA_PARAM_EnumFormat || id == SPA_PARAM_Format) { DeviceNode *node{DeviceNode::Find(mId)}; if(!node) UNLIKELY return; - TRACE("Device ID %" PRIu64 " %s format:\n", node->mSerial, - (id == SPA_PARAM_EnumFormat) ? "enumerable" : "current"); + TRACE("Device ID {} {} format{}:", node->mSerial, + (id == SPA_PARAM_EnumFormat) ? "available" : "current", + (id == SPA_PARAM_EnumFormat) ? "s" : ""); const bool force_update{id == SPA_PARAM_Format}; if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_rate)}) @@ -1033,42 +1102,45 @@ void NodeProxy::paramCallback(int, uint32_t id, uint32_t, uint32_t, const spa_po if(const spa_pod_prop *prop{spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_position)}) node->parsePositions(&prop->value, force_update); - else if((prop=spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_channels)) != nullptr) - node->parseChannelCount(&prop->value, force_update); + else + { + prop = spa_pod_find_prop(param, nullptr, SPA_FORMAT_AUDIO_channels); + if(prop) node->parseChannelCount(&prop->value, force_update); + } } } -int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *type, - const char *value) noexcept +auto MetadataProxy::propertyCallback(void*, uint32_t id, const char *key, const char *type, + const char *value) noexcept -> int { if(id != PW_ID_CORE) return 0; bool isCapture{}; - if(std::strcmp(key, "default.audio.sink") == 0) + if("default.audio.sink"sv == key) isCapture = false; - else if(std::strcmp(key, "default.audio.source") == 0) + else if("default.audio.source"sv == key) isCapture = true; else return 0; if(!type) { - TRACE("Default %s device cleared\n", isCapture ? "capture" : "playback"); + TRACE("Default {} device cleared", isCapture ? "capture" : "playback"); if(!isCapture) DefaultSinkDevice.clear(); else DefaultSourceDevice.clear(); return 0; } - if(std::strcmp(type, "Spa:String:JSON") != 0) + if("Spa:String:JSON"sv != type) { - ERR("Unexpected %s property type: %s\n", key, type); + ERR("Unexpected {} property type: {}", key, type); return 0; } - spa_json it[2]{}; - spa_json_init(&it[0], value, strlen(value)); - if(spa_json_enter_object(&it[0], &it[1]) <= 0) + std::array it{}; + spa_json_init(it.data(), value, strlen(value)); + if(spa_json_enter_object(&std::get<0>(it), &std::get<1>(it)) <= 0) return 0; auto get_json_string = [](spa_json *iter) @@ -1079,57 +1151,51 @@ int MetadataProxy::propertyCallback(uint32_t id, const char *key, const char *ty int len{spa_json_next(iter, &val)}; if(len <= 0) return str; - str.emplace().resize(static_cast(len), '\0'); - if(spa_json_parse_string(val, len, &str->front()) <= 0) + str.emplace(static_cast(len), '\0'); + if(spa_json_parse_string(val, len, str->data()) <= 0) str.reset(); else while(!str->empty() && str->back() == '\0') str->pop_back(); return str; }; - while(auto propKey = get_json_string(&it[1])) + while(auto propKey = get_json_string(&std::get<1>(it))) { - if(*propKey == "name") + if("name"sv == *propKey) { - auto propValue = get_json_string(&it[1]); + auto propValue = get_json_string(&std::get<1>(it)); if(!propValue) break; - TRACE("Got default %s device \"%s\"\n", isCapture ? "capture" : "playback", - propValue->c_str()); - if(!isCapture) + TRACE("Got default {} device \"{}\"", isCapture ? "capture" : "playback", + *propValue); + if(!isCapture && DefaultSinkDevice != *propValue) { - if(DefaultSinkDevice != *propValue) + if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) { - if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) - { - auto entry = DeviceNode::FindByDevName(*propValue); - const std::string msg{"Default playback device changed: "+ - (entry ? entry->mName : std::string{})}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, - msg); - } - DefaultSinkDevice = std::move(*propValue); + auto entry = DeviceNode::FindByDevName(*propValue); + const std::string message{"Default playback device changed: "+ + (entry ? entry->mName : std::string{})}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, + message); } + DefaultSinkDevice = std::move(*propValue); } - else + else if(isCapture && DefaultSourceDevice != *propValue) { - if(DefaultSourceDevice != *propValue) + if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) { - if(gEventHandler.mInitDone.load(std::memory_order_relaxed)) - { - auto entry = DeviceNode::FindByDevName(*propValue); - const std::string msg{"Default capture device changed: "+ - (entry ? entry->mName : std::string{})}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, - msg); - } - DefaultSourceDevice = std::move(*propValue); + auto entry = DeviceNode::FindByDevName(*propValue); + const std::string message{"Default capture device changed: "+ + (entry ? entry->mName : std::string{})}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, + message); } + DefaultSourceDevice = std::move(*propValue); } } else { const char *v{}; - if(spa_json_next(&it[1], &v) <= 0) + if(spa_json_next(&std::get<1>(it), &v) <= 0) break; } } @@ -1142,28 +1208,28 @@ bool EventManager::init() mLoop = ThreadMainloop::Create("PWEventThread"); if(!mLoop) { - ERR("Failed to create PipeWire event thread loop (errno: %d)\n", errno); + ERR("Failed to create PipeWire event thread loop (errno: {})", errno); return false; } mContext = mLoop.newContext(); if(!mContext) { - ERR("Failed to create PipeWire event context (errno: %d)\n", errno); + ERR("Failed to create PipeWire event context (errno: {})", errno); return false; } mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)}; if(!mCore) { - ERR("Failed to connect PipeWire event context (errno: %d)\n", errno); + ERR("Failed to connect PipeWire event context (errno: {})", errno); return false; } mRegistry = PwRegistryPtr{pw_core_get_registry(mCore.get(), PW_VERSION_REGISTRY, 0)}; if(!mRegistry) { - ERR("Failed to get PipeWire event registry (errno: %d)\n", errno); + ERR("Failed to get PipeWire event registry (errno: {})", errno); return false; } @@ -1180,7 +1246,7 @@ bool EventManager::init() if(int res{mLoop.start()}) { - ERR("Failed to start PipeWire event thread loop (res: %d)\n", res); + ERR("Failed to start PipeWire event thread loop (res: {})", res); return false; } @@ -1208,17 +1274,17 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t { const char *media_class{spa_dict_lookup(props, PW_KEY_MEDIA_CLASS)}; if(!media_class) return; + const std::string_view className{media_class}; /* Specifically, audio sinks and sources (and duplexes). */ - const bool isGood{al::strcasecmp(media_class, AudioSinkClass) == 0 - || al::strcasecmp(media_class, AudioSourceClass) == 0 - || al::strcasecmp(media_class, AudioSourceVirtualClass) == 0 - || al::strcasecmp(media_class, AudioDuplexClass) == 0}; + const bool isGood{al::case_compare(className, GetAudioSinkClassName()) == 0 + || al::case_compare(className, GetAudioSourceClassName()) == 0 + || al::case_compare(className, GetAudioSourceVirtualClassName()) == 0 + || al::case_compare(className, GetAudioDuplexClassName()) == 0}; if(!isGood) { - if(std::strstr(media_class, "/Video") == nullptr - && std::strncmp(media_class, StreamClass, sizeof(StreamClass)-1) != 0) - TRACE("Ignoring node class %s\n", media_class); + if(!al::contains(className, "/Video"sv) && !al::starts_with(className, "Stream/"sv)) + TRACE("Ignoring node class {}", media_class); return; } @@ -1227,7 +1293,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t version, 0))}; if(!node) { - ERR("Failed to create node proxy object (errno: %d)\n", errno); + ERR("Failed to create node proxy object (errno: {})", errno); return; } @@ -1248,15 +1314,15 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t const char *data_class{spa_dict_lookup(props, PW_KEY_METADATA_NAME)}; if(!data_class) return; - if(std::strcmp(data_class, "default") != 0) + if("default"sv != data_class) { - TRACE("Ignoring metadata \"%s\"\n", data_class); + TRACE("Ignoring metadata \"{}\"", data_class); return; } if(mDefaultMetadata) { - ERR("Duplicate default metadata\n"); + ERR("Duplicate default metadata"); return; } @@ -1264,7 +1330,7 @@ void EventManager::addCallback(uint32_t id, uint32_t, const char *type, uint32_t type, version, 0))}; if(!mdata) { - ERR("Failed to create metadata proxy object (errno: %d)\n", errno); + ERR("Failed to create metadata proxy object (errno: {})", errno); return; } @@ -1321,7 +1387,7 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u case DevFmtFloat: info.format = SPA_AUDIO_FORMAT_F32; break; } - info.rate = device->Frequency; + info.rate = device->mSampleRate; al::span map{}; switch(device->FmtChans) @@ -1337,6 +1403,7 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u case DevFmtX71: map = X71Map; break; case DevFmtX714: map = X714Map; break; case DevFmtX3D71: map = X71Map; break; + case DevFmtX7144: case DevFmtAmbi3D: info.flags |= SPA_AUDIO_FLAG_UNPOSITIONED; info.channels = device->channelsFromFmt(); @@ -1345,7 +1412,7 @@ spa_audio_info_raw make_spa_info(DeviceBase *device, bool is51rear, use_f32p_e u if(!map.empty()) { info.channels = static_cast(map.size()); - std::copy(map.begin(), map.end(), info.position); + std::copy(map.begin(), map.end(), std::begin(info.position)); } return info; @@ -1370,8 +1437,7 @@ class PipeWirePlayback final : public BackendBase { PwStreamPtr mStream; spa_hook mStreamListener{}; spa_io_rate_match *mRateMatch{}; - std::unique_ptr mChannelPtrs; - uint mNumChannels{}; + std::vector mChannelPtrs; static constexpr pw_stream_events CreateEvents() { @@ -1387,14 +1453,12 @@ class PipeWirePlayback final : public BackendBase { } public: - PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { } - ~PipeWirePlayback() + explicit PipeWirePlayback(DeviceBase *device) noexcept : BackendBase{device} { } + ~PipeWirePlayback() final { /* Stop the mainloop so the stream can be properly destroyed. */ if(mLoop) mLoop.stop(); } - - DEF_NEWDEL(PipeWirePlayback) }; @@ -1408,6 +1472,8 @@ void PipeWirePlayback::ioChangedCallback(uint32_t id, void *area, uint32_t size) case SPA_IO_RateMatch: if(size >= sizeof(spa_io_rate_match)) mRateMatch = static_cast(area); + else + mRateMatch = nullptr; break; } } @@ -1418,7 +1484,7 @@ void PipeWirePlayback::outputCallback() noexcept if(!pw_buf) UNLIKELY return; const al::span datas{pw_buf->buffer->datas, - minu(mNumChannels, pw_buf->buffer->n_datas)}; + std::min(mChannelPtrs.size(), size_t{pw_buf->buffer->n_datas})}; #if PW_CHECK_VERSION(0,3,49) /* In 0.3.49, pw_buffer::requested specifies the number of samples needed * by the resampler/graph for this audio update. @@ -1431,18 +1497,18 @@ void PipeWirePlayback::outputCallback() noexcept uint length{mRateMatch ? mRateMatch->size : 0u}; #endif /* If no length is specified, use the device's update size as a fallback. */ - if(!length) UNLIKELY length = mDevice->UpdateSize; + if(!length) UNLIKELY length = mDevice->mUpdateSize; /* For planar formats, each datas[] seems to contain one channel, so store * the pointers in an array. Limit the render length in case the available * buffer length in any one channel is smaller than we wanted (shouldn't * be, but just in case). */ - float **chanptr_end{mChannelPtrs.get()}; + auto chanptr_end = mChannelPtrs.begin(); for(const auto &data : datas) { - length = minu(length, data.maxsize/sizeof(float)); - *chanptr_end = static_cast(data.data); + length = std::min(length, data.maxsize/uint{sizeof(float)}); + *chanptr_end = data.data; ++chanptr_end; data.chunk->offset = 0; @@ -1450,7 +1516,7 @@ void PipeWirePlayback::outputCallback() noexcept data.chunk->size = length * sizeof(float); } - mDevice->renderSamples({mChannelPtrs.get(), chanptr_end}, length); + mDevice->renderSamples(mChannelPtrs, length); pw_buf->size = length; pw_stream_queue_buffer(mStream.get(), pw_buf); @@ -1466,7 +1532,7 @@ void PipeWirePlayback::open(std::string_view name) gEventHandler.waitForInit(); if(name.empty()) { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match = devlist.cend(); @@ -1491,15 +1557,15 @@ void PipeWirePlayback::open(std::string_view name) } else { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match_name = [name](const DeviceNode &n) -> bool - { return n.mType != NodeType::Source && n.mName == name; }; + { return n.mType != NodeType::Source && (n.mName == name || n.mDevName == name); }; auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name); if(match == devlist.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; targetid = match->mSerial; devname = match->mName; @@ -1507,15 +1573,15 @@ void PipeWirePlayback::open(std::string_view name) if(!mLoop) { - const uint count{OpenCount.fetch_add(1, std::memory_order_relaxed)}; - const std::string thread_name{"ALSoftP" + std::to_string(count)}; + const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed); + const auto thread_name = fmt::format("ALSoftP{}", count); mLoop = ThreadMainloop::Create(thread_name.c_str()); if(!mLoop) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire mainloop (errno: %d)", errno}; + "Failed to create PipeWire mainloop (errno: {})", errno}; if(int res{mLoop.start()}) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start PipeWire mainloop (res: %d)", res}; + "Failed to start PipeWire mainloop (res: {})", res}; } MainloopUniqueLock mlock{mLoop}; if(!mContext) @@ -1524,14 +1590,14 @@ void PipeWirePlayback::open(std::string_view name) mContext = mLoop.newContext(cprops); if(!mContext) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire event context (errno: %d)\n", errno}; + "Failed to create PipeWire event context (errno: {})\n", errno}; } if(!mCore) { mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)}; if(!mCore) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to connect PipeWire event context (errno: %d)\n", errno}; + "Failed to connect PipeWire event context (errno: {})\n", errno}; } mlock.unlock(); @@ -1539,21 +1605,21 @@ void PipeWirePlayback::open(std::string_view name) mTargetId = targetid; if(!devname.empty()) - mDevice->DeviceName = std::move(devname); + mDeviceName = std::move(devname); else - mDevice->DeviceName = pwireDevice; + mDeviceName = "PipeWire Output"sv; } bool PipeWirePlayback::reset() { if(mStream) { - MainloopLockGuard _{mLoop}; + MainloopLockGuard looplock{mLoop}; mStream = nullptr; } mStreamListener = {}; mRateMatch = nullptr; - mTimeBase = GetDeviceClockTime(mDevice); + mTimeBase = mDevice->getClockTime(); /* If connecting to a specific device, update various device parameters to * match its format. @@ -1562,7 +1628,7 @@ bool PipeWirePlayback::reset() mDevice->Flags.reset(DirectEar); if(mTargetId != PwIdAny) { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match_id = [targetid=mTargetId](const DeviceNode &n) -> bool @@ -1573,12 +1639,13 @@ bool PipeWirePlayback::reset() if(!mDevice->Flags.test(FrequencyRequest) && match->mSampleRate > 0) { /* Scale the update size if the sample rate changes. */ - const double scale{static_cast(match->mSampleRate) / mDevice->Frequency}; - const double numbufs{static_cast(mDevice->BufferSize)/mDevice->UpdateSize}; - mDevice->Frequency = match->mSampleRate; - mDevice->UpdateSize = static_cast(clampd(mDevice->UpdateSize*scale + 0.5, - 64.0, 8192.0)); - mDevice->BufferSize = static_cast(numbufs*mDevice->UpdateSize + 0.5); + const double scale{static_cast(match->mSampleRate) / mDevice->mSampleRate}; + const double updatesize{std::round(mDevice->mUpdateSize * scale)}; + const double buffersize{std::round(mDevice->mBufferSize * scale)}; + + mDevice->mSampleRate = match->mSampleRate; + mDevice->mUpdateSize = static_cast(std::clamp(updatesize, 64.0, 8192.0)); + mDevice->mBufferSize = static_cast(std::max(buffersize, 128.0)); } if(!mDevice->Flags.test(ChannelsRequest) && match->mChannels != InvalidChannelConfig) mDevice->FmtChans = match->mChannels; @@ -1590,16 +1657,10 @@ bool PipeWirePlayback::reset() /* Force planar 32-bit float output for playback. This is what PipeWire * handles internally, and it's easier for us too. */ - spa_audio_info_raw info{make_spa_info(mDevice, is51rear, ForceF32Planar)}; - - /* TODO: How to tell what an appropriate size is? Examples just use this - * magic value. - */ - constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); - spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; + auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, ForceF32Planar)}; - const spa_pod *params{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; + auto b = PodDynamicBuilder{}; + auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)); if(!params) throw al::backend_exception{al::backend_error::DeviceError, "Failed to set PipeWire audio format parameters"}; @@ -1608,7 +1669,7 @@ bool PipeWirePlayback::reset() * be useful? */ auto&& binary = GetProcBinary(); - const char *appname{binary.fname.length() ? binary.fname.c_str() : "OpenAL Soft"}; + const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"}; pw_properties *props{pw_properties_new(PW_KEY_NODE_NAME, appname, PW_KEY_NODE_DESCRIPTION, appname, PW_KEY_MEDIA_TYPE, "Audio", @@ -1618,11 +1679,11 @@ bool PipeWirePlayback::reset() nullptr)}; if(!props) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire stream properties (errno: %d)", errno}; + "Failed to create PipeWire stream properties (errno: {})", errno}; - pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", mDevice->UpdateSize, - mDevice->Frequency); - pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->Frequency); + pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", mDevice->mUpdateSize, + mDevice->mSampleRate); + pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate); #ifdef PW_KEY_TARGET_OBJECT pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId); #else @@ -1634,17 +1695,17 @@ bool PipeWirePlayback::reset() mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Playback Stream", props)}; if(!mStream) throw al::backend_exception{al::backend_error::NoDevice, - "Failed to create PipeWire stream (errno: %d)", errno}; + "Failed to create PipeWire stream (errno: {})", errno}; static constexpr pw_stream_events streamEvents{CreateEvents()}; pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this); pw_stream_flags flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_MAP_BUFFERS}; - if(GetConfigValueBool(mDevice->DeviceName.c_str(), "pipewire", "rt-mix", true)) + if(GetConfigValueBool(mDevice->mDeviceName, "pipewire", "rt-mix", false)) flags |= PW_STREAM_FLAG_RT_PROCESS; if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_OUTPUT, PwIdAny, flags, ¶ms, 1)}) throw al::backend_exception{al::backend_error::DeviceError, - "Error connecting PipeWire stream (res: %d)", res}; + "Error connecting PipeWire stream (res: {})", res}; /* Wait for the stream to become paused (ready to start streaming). */ plock.wait([stream=mStream.get()]() @@ -1653,20 +1714,19 @@ bool PipeWirePlayback::reset() pw_stream_state state{pw_stream_get_state(stream, &error)}; if(state == PW_STREAM_STATE_ERROR) throw al::backend_exception{al::backend_error::DeviceError, - "Error connecting PipeWire stream: \"%s\"", error}; + "Error connecting PipeWire stream: \"{}\"", error}; return state == PW_STREAM_STATE_PAUSED; }); - /* TODO: Update mDevice->UpdateSize with the stream's quantum, and - * mDevice->BufferSize with the total known buffering delay from the head + /* TODO: Update mDevice->mUpdateSize with the stream's quantum, and + * mDevice->mBufferSize with the total known buffering delay from the head * of this playback stream to the tail of the device output. * * This info is apparently not available until after the stream starts. */ plock.unlock(); - mNumChannels = mDevice->channelsFromFmt(); - mChannelPtrs = std::make_unique(mNumChannels); + mChannelPtrs.resize(mDevice->channelsFromFmt()); setDefaultWFXChannelOrder(); @@ -1678,7 +1738,7 @@ void PipeWirePlayback::start() MainloopUniqueLock plock{mLoop}; if(int res{pw_stream_set_active(mStream.get(), true)}) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start PipeWire stream (res: %d)", res}; + "Failed to start PipeWire stream (res: {})", res}; /* Wait for the stream to start playing (would be nice to not, but we need * the actual update size which is only available after starting). @@ -1689,7 +1749,7 @@ void PipeWirePlayback::start() pw_stream_state state{pw_stream_get_state(stream, &error)}; if(state == PW_STREAM_STATE_ERROR) throw al::backend_exception{al::backend_error::DeviceError, - "PipeWire stream error: %s", error ? error : "(unknown)"}; + "PipeWire stream error: {}", error ? error : "(unknown)"}; return state == PW_STREAM_STATE_STREAMING; }); @@ -1704,7 +1764,7 @@ void PipeWirePlayback::start() pw_time ptime{}; if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))}) { - ERR("Failed to get PipeWire stream time (res: %d)\n", res); + ERR("Failed to get PipeWire stream time (res: {})", res); break; } @@ -1719,12 +1779,12 @@ void PipeWirePlayback::start() const uint totalbuffers{ptime.avail_buffers + ptime.queued_buffers}; /* Ensure the delay is in sample frames. */ - const uint64_t delay{static_cast(ptime.delay) * mDevice->Frequency * + const uint64_t delay{static_cast(ptime.delay) * mDevice->mSampleRate * ptime.rate.num / ptime.rate.denom}; - mDevice->UpdateSize = updatesize; - mDevice->BufferSize = static_cast(ptime.buffered + delay + - totalbuffers*updatesize); + mDevice->mUpdateSize = updatesize; + mDevice->mBufferSize = static_cast(ptime.buffered + delay + + uint64_t{totalbuffers}*updatesize); break; } #else @@ -1734,17 +1794,17 @@ void PipeWirePlayback::start() if(ptime.rate.denom > 0 && updatesize > 0) { /* Ensure the delay is in sample frames. */ - const uint64_t delay{static_cast(ptime.delay) * mDevice->Frequency * + const uint64_t delay{static_cast(ptime.delay) * mDevice->mSampleRate * ptime.rate.num / ptime.rate.denom}; - mDevice->UpdateSize = updatesize; - mDevice->BufferSize = static_cast(delay + updatesize); + mDevice->mUpdateSize = updatesize; + mDevice->mBufferSize = static_cast(delay + updatesize); break; } #endif if(!--wait_count) { - ERR("Timeout getting PipeWire stream buffering info\n"); + ERR("Timeout getting PipeWire stream buffering info"); break; } @@ -1758,8 +1818,7 @@ void PipeWirePlayback::stop() { MainloopUniqueLock plock{mLoop}; if(int res{pw_stream_set_active(mStream.get(), false)}) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to stop PipeWire stream (res: %d)", res}; + ERR("Failed to stop PipeWire stream (res: {})", res); /* Wait for the stream to stop playing. */ plock.wait([stream=mStream.get()]() @@ -1778,9 +1837,9 @@ ClockLatency PipeWirePlayback::getClockLatency() pw_time ptime{}; if(mStream) { - MainloopLockGuard _{mLoop}; + MainloopLockGuard looplock{mLoop}; if(int res{pw_stream_get_time_n(mStream.get(), &ptime, sizeof(ptime))}) - ERR("Failed to get PipeWire stream time (res: %d)\n", res); + ERR("Failed to get PipeWire stream time (res: {})", res); } /* Now get the mixer time and the CLOCK_MONOTONIC time atomically (i.e. the @@ -1791,10 +1850,10 @@ ClockLatency PipeWirePlayback::getClockLatency() uint refcount; do { refcount = mDevice->waitForMix(); - mixtime = GetDeviceClockTime(mDevice); + mixtime = mDevice->getClockTime(); clock_gettime(CLOCK_MONOTONIC, &tspec); std::atomic_thread_fence(std::memory_order_acquire); - } while(refcount != ReadRef(mDevice->MixCount)); + } while(refcount != mDevice->mMixCount.load(std::memory_order_relaxed)); /* Convert the monotonic clock, stream ticks, and stream delay to * nanoseconds. @@ -1808,7 +1867,7 @@ ClockLatency PipeWirePlayback::getClockLatency() */ ptime.now = monoclock.count(); curtic = mixtime; - delay = nanoseconds{seconds{mDevice->BufferSize}} / mDevice->Frequency; + delay = nanoseconds{seconds{mDevice->mBufferSize}} / mDevice->mSampleRate; } else { @@ -1868,7 +1927,7 @@ class PipeWireCapture final : public BackendBase { PwStreamPtr mStream; spa_hook mStreamListener{}; - RingBufferPtr mRing{}; + RingBufferPtr mRing; static constexpr pw_stream_events CreateEvents() { @@ -1882,10 +1941,8 @@ class PipeWireCapture final : public BackendBase { } public: - PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { } - ~PipeWireCapture() { if(mLoop) mLoop.stop(); } - - DEF_NEWDEL(PipeWireCapture) + explicit PipeWireCapture(DeviceBase *device) noexcept : BackendBase{device} { } + ~PipeWireCapture() final { if(mLoop) mLoop.stop(); } }; @@ -1898,10 +1955,11 @@ void PipeWireCapture::inputCallback() noexcept if(!pw_buf) UNLIKELY return; spa_data *bufdata{pw_buf->buffer->datas}; - const uint offset{minu(bufdata->chunk->offset, bufdata->maxsize)}; - const uint size{minu(bufdata->chunk->size, bufdata->maxsize - offset)}; + const uint offset{bufdata->chunk->offset % bufdata->maxsize}; + const auto input = al::span{static_cast(bufdata->data), bufdata->maxsize} + .subspan(offset, std::min(bufdata->chunk->size, bufdata->maxsize - offset)); - mRing->write(static_cast(bufdata->data) + offset, size / mRing->getElemSize()); + std::ignore = mRing->write(input.data(), input.size() / mRing->getElemSize()); pw_stream_queue_buffer(mStream.get(), pw_buf); } @@ -1916,7 +1974,7 @@ void PipeWireCapture::open(std::string_view name) gEventHandler.waitForInit(); if(name.empty()) { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match = devlist.cend(); @@ -1942,43 +2000,52 @@ void PipeWireCapture::open(std::string_view name) targetid = match->mSerial; if(match->mType != NodeType::Sink) devname = match->mName; - else devname = MonitorPrefix+match->mName; + else devname = std::string{GetMonitorPrefix()}+match->mName; } else { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); + const std::string_view prefix{GetMonitorPrefix()}; + const std::string_view suffix{GetMonitorSuffix()}; auto match_name = [name](const DeviceNode &n) -> bool { return n.mType != NodeType::Sink && n.mName == name; }; auto match = std::find_if(devlist.cbegin(), devlist.cend(), match_name); - if(match == devlist.cend() && name.length() >= MonitorPrefixLen - && std::strncmp(name.data(), MonitorPrefix, MonitorPrefixLen) == 0) + if(match == devlist.cend() && al::starts_with(name, prefix)) { - const std::string_view sinkname{name.substr(MonitorPrefixLen)}; + const std::string_view sinkname{name.substr(prefix.length())}; auto match_sinkname = [sinkname](const DeviceNode &n) -> bool { return n.mType == NodeType::Sink && n.mName == sinkname; }; match = std::find_if(devlist.cbegin(), devlist.cend(), match_sinkname); } + else if(match == devlist.cend() && al::ends_with(name, suffix)) + { + const std::string_view sinkname{name.substr(0, name.size()-suffix.size())}; + auto match_sinkname = [sinkname](const DeviceNode &n) -> bool + { return n.mType == NodeType::Sink && n.mDevName == sinkname; }; + match = std::find_if(devlist.cbegin(), devlist.cend(), match_sinkname); + } if(match == devlist.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; + "Device name \"{}\" not found", name}; targetid = match->mSerial; - devname = name; + if(match->mType != NodeType::Sink) devname = match->mName; + else devname = std::string{GetMonitorPrefix()}+match->mName; } if(!mLoop) { - const uint count{OpenCount.fetch_add(1, std::memory_order_relaxed)}; - const std::string thread_name{"ALSoftC" + std::to_string(count)}; + const auto count = OpenCount.fetch_add(1u, std::memory_order_relaxed); + const auto thread_name = fmt::format("ALSoftC{}", count); mLoop = ThreadMainloop::Create(thread_name.c_str()); if(!mLoop) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire mainloop (errno: %d)", errno}; + "Failed to create PipeWire mainloop (errno: {})", errno}; if(int res{mLoop.start()}) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start PipeWire mainloop (res: %d)", res}; + "Failed to start PipeWire mainloop (res: {})", res}; } MainloopUniqueLock mlock{mLoop}; if(!mContext) @@ -1987,14 +2054,14 @@ void PipeWireCapture::open(std::string_view name) mContext = mLoop.newContext(cprops); if(!mContext) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire event context (errno: %d)\n", errno}; + "Failed to create PipeWire event context (errno: {})\n", errno}; } if(!mCore) { mCore = PwCorePtr{pw_context_connect(mContext.get(), nullptr, 0)}; if(!mCore) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to connect PipeWire event context (errno: %d)\n", errno}; + "Failed to connect PipeWire event context (errno: {})\n", errno}; } mlock.unlock(); @@ -2002,15 +2069,15 @@ void PipeWireCapture::open(std::string_view name) mTargetId = targetid; if(!devname.empty()) - mDevice->DeviceName = std::move(devname); + mDeviceName = std::move(devname); else - mDevice->DeviceName = pwireInput; + mDeviceName = "PipeWire Input"sv; bool is51rear{false}; if(mTargetId != PwIdAny) { - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match_id = [targetid=mTargetId](const DeviceNode &n) -> bool @@ -2019,19 +2086,16 @@ void PipeWireCapture::open(std::string_view name) if(match != devlist.cend()) is51rear = match->mIs51Rear; } - spa_audio_info_raw info{make_spa_info(mDevice, is51rear, UseDevType)}; + auto info = spa_audio_info_raw{make_spa_info(mDevice, is51rear, UseDevType)}; - constexpr uint32_t pod_buffer_size{1024}; - auto pod_buffer = std::make_unique(pod_buffer_size); - spa_pod_builder b{make_pod_builder(pod_buffer.get(), pod_buffer_size)}; - - const spa_pod *params[]{spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat, &info)}; - if(!params[0]) + auto b = PodDynamicBuilder{}; + auto params = as_const_ptr(spa_format_audio_raw_build(b.get(), SPA_PARAM_EnumFormat, &info)); + if(!params) throw al::backend_exception{al::backend_error::DeviceError, "Failed to set PipeWire audio format parameters"}; auto&& binary = GetProcBinary(); - const char *appname{binary.fname.length() ? binary.fname.c_str() : "OpenAL Soft"}; + const char *appname{!binary.fname.empty() ? binary.fname.c_str() : "OpenAL Soft"}; pw_properties *props{pw_properties_new( PW_KEY_NODE_NAME, appname, PW_KEY_NODE_DESCRIPTION, appname, @@ -2042,15 +2106,15 @@ void PipeWireCapture::open(std::string_view name) nullptr)}; if(!props) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to create PipeWire stream properties (errno: %d)", errno}; + "Failed to create PipeWire stream properties (errno: {})", errno}; /* We don't actually care what the latency/update size is, as long as it's * reasonable. Unfortunately, when unspecified PipeWire seems to default to * around 40ms, which isn't great. So request 20ms instead. */ - pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", (mDevice->Frequency+25) / 50, - mDevice->Frequency); - pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->Frequency); + pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%u/%u", (mDevice->mSampleRate+25) / 50, + mDevice->mSampleRate); + pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%u", mDevice->mSampleRate); #ifdef PW_KEY_TARGET_OBJECT pw_properties_setf(props, PW_KEY_TARGET_OBJECT, "%" PRIu64, mTargetId); #else @@ -2061,15 +2125,15 @@ void PipeWireCapture::open(std::string_view name) mStream = PwStreamPtr{pw_stream_new(mCore.get(), "Capture Stream", props)}; if(!mStream) throw al::backend_exception{al::backend_error::NoDevice, - "Failed to create PipeWire stream (errno: %d)", errno}; + "Failed to create PipeWire stream (errno: {})", errno}; static constexpr pw_stream_events streamEvents{CreateEvents()}; pw_stream_add_listener(mStream.get(), &mStreamListener, &streamEvents, this); constexpr pw_stream_flags Flags{PW_STREAM_FLAG_AUTOCONNECT | PW_STREAM_FLAG_INACTIVE | PW_STREAM_FLAG_MAP_BUFFERS | PW_STREAM_FLAG_RT_PROCESS}; - if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, params, 1)}) + if(int res{pw_stream_connect(mStream.get(), PW_DIRECTION_INPUT, PwIdAny, Flags, ¶ms, 1)}) throw al::backend_exception{al::backend_error::DeviceError, - "Error connecting PipeWire stream (res: %d)", res}; + "Error connecting PipeWire stream (res: {})", res}; /* Wait for the stream to become paused (ready to start streaming). */ plock.wait([stream=mStream.get()]() @@ -2078,7 +2142,7 @@ void PipeWireCapture::open(std::string_view name) pw_stream_state state{pw_stream_get_state(stream, &error)}; if(state == PW_STREAM_STATE_ERROR) throw al::backend_exception{al::backend_error::DeviceError, - "Error connecting PipeWire stream: \"%s\"", error}; + "Error connecting PipeWire stream: \"{}\"", error}; return state == PW_STREAM_STATE_PAUSED; }); plock.unlock(); @@ -2086,7 +2150,7 @@ void PipeWireCapture::open(std::string_view name) setDefaultWFXChannelOrder(); /* Ensure at least a 100ms capture buffer. */ - mRing = RingBuffer::Create(maxu(mDevice->Frequency/10, mDevice->BufferSize), + mRing = RingBuffer::Create(std::max(mDevice->mSampleRate/10u, mDevice->mBufferSize), mDevice->frameSizeFromFmt(), false); } @@ -2096,7 +2160,7 @@ void PipeWireCapture::start() MainloopUniqueLock plock{mLoop}; if(int res{pw_stream_set_active(mStream.get(), true)}) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start PipeWire stream (res: %d)", res}; + "Failed to start PipeWire stream (res: {})", res}; plock.wait([stream=mStream.get()]() { @@ -2104,7 +2168,7 @@ void PipeWireCapture::start() pw_stream_state state{pw_stream_get_state(stream, &error)}; if(state == PW_STREAM_STATE_ERROR) throw al::backend_exception{al::backend_error::DeviceError, - "PipeWire stream error: %s", error ? error : "(unknown)"}; + "PipeWire stream error: {}", error ? error : "(unknown)"}; return state == PW_STREAM_STATE_STREAMING; }); } @@ -2113,8 +2177,7 @@ void PipeWireCapture::stop() { MainloopUniqueLock plock{mLoop}; if(int res{pw_stream_set_active(mStream.get(), false)}) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to stop PipeWire stream (res: %d)", res}; + ERR("Failed to stop PipeWire stream (res: {})", res); plock.wait([stream=mStream.get()]() { return pw_stream_get_state(stream, nullptr) != PW_STREAM_STATE_STREAMING; }); @@ -2124,7 +2187,7 @@ uint PipeWireCapture::availableSamples() { return static_cast(mRing->readSpace()); } void PipeWireCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } } // namespace @@ -2137,24 +2200,24 @@ bool PipeWireBackendFactory::init() const char *version{pw_get_library_version()}; if(!check_version(version)) { - WARN("PipeWire version \"%s\" too old (%s or newer required)\n", version, + WARN("PipeWire version \"{}\" too old ({} or newer required)", version, pw_get_headers_version()); return false; } - TRACE("Found PipeWire version \"%s\" (%s or newer)\n", version, pw_get_headers_version()); + TRACE("Found PipeWire version \"{}\" ({} or newer)", version, pw_get_headers_version()); - pw_init(0, nullptr); + pw_init(nullptr, nullptr); if(!gEventHandler.init()) return false; - if(!GetConfigValueBool(nullptr, "pipewire", "assume-audio", false) + if(!GetConfigValueBool({}, "pipewire", "assume-audio", false) && !gEventHandler.waitForAudio()) { gEventHandler.kill(); /* TODO: Temporary warning, until PipeWire gets a proper way to report * audio support. */ - WARN("No audio support detected in PipeWire. See the PipeWire options in alsoftrc.sample if this is wrong.\n"); + WARN("No audio support detected in PipeWire. See the PipeWire options in alsoftrc.sample if this is wrong."); return false; } return true; @@ -2163,12 +2226,12 @@ bool PipeWireBackendFactory::init() bool PipeWireBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string PipeWireBackendFactory::probe(BackendType type) +auto PipeWireBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; gEventHandler.waitForInit(); - EventWatcherLockGuard _{gEventHandler}; + EventWatcherLockGuard evtlock{gEventHandler}; auto&& devlist = DeviceNode::GetList(); auto match_defsink = [](const DeviceNode &n) -> bool @@ -2186,31 +2249,31 @@ std::string PipeWireBackendFactory::probe(BackendType type) case BackendType::Playback: defmatch = std::find_if(defmatch, devlist.cend(), match_defsink); if(defmatch != devlist.cend()) - { - /* Includes null char. */ - outnames.append(defmatch->mName.c_str(), defmatch->mName.length()+1); - } + outnames.emplace_back(defmatch->mName); for(auto iter = devlist.cbegin();iter != devlist.cend();++iter) { if(iter != defmatch && iter->mType != NodeType::Source) - outnames.append(iter->mName.c_str(), iter->mName.length()+1); + outnames.emplace_back(iter->mName); } break; case BackendType::Capture: + outnames.reserve(devlist.size()); defmatch = std::find_if(defmatch, devlist.cend(), match_defsource); if(defmatch != devlist.cend()) { if(defmatch->mType == NodeType::Sink) - outnames.append(MonitorPrefix); - outnames.append(defmatch->mName.c_str(), defmatch->mName.length()+1); + outnames.emplace_back(std::string{GetMonitorPrefix()}+defmatch->mName); + else + outnames.emplace_back(defmatch->mName); } for(auto iter = devlist.cbegin();iter != devlist.cend();++iter) { if(iter != defmatch) { if(iter->mType == NodeType::Sink) - outnames.append(MonitorPrefix); - outnames.append(iter->mName.c_str(), iter->mName.length()+1); + outnames.emplace_back(std::string{GetMonitorPrefix()}+iter->mName); + else + outnames.emplace_back(iter->mName); } } break; @@ -2219,6 +2282,7 @@ std::string PipeWireBackendFactory::probe(BackendType type) return outnames; } + BackendPtr PipeWireBackendFactory::createBackend(DeviceBase *device, BackendType type) { if(type == BackendType::Playback) @@ -2233,3 +2297,18 @@ BackendFactory &PipeWireBackendFactory::getFactory() static PipeWireBackendFactory factory{}; return factory; } + +alc::EventSupport PipeWireBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) +{ + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + return alc::EventSupport::FullSupport; + + case alc::EventType::Count: + break; + } + return alc::EventSupport::NoSupport; +} diff --git a/3rdparty/openal/alc/backends/pipewire.h b/3rdparty/openal/alc/backends/pipewire.h index 5f930239c607..567d18eddd0a 100644 --- a/3rdparty/openal/alc/backends/pipewire.h +++ b/3rdparty/openal/alc/backends/pipewire.h @@ -2,22 +2,26 @@ #define BACKENDS_PIPEWIRE_H #include +#include +#include "alc/events.h" #include "base.h" struct DeviceBase; struct PipeWireBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto queryEventSupport(alc::EventType eventType, BackendType type) -> alc::EventSupport final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - static BackendFactory &getFactory(); + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_PIPEWIRE_H */ diff --git a/3rdparty/openal/alc/backends/portaudio.cpp b/3rdparty/openal/alc/backends/portaudio.cpp index 979a54d616bc..75497c3f3ae2 100644 --- a/3rdparty/openal/alc/backends/portaudio.cpp +++ b/3rdparty/openal/alc/backends/portaudio.cpp @@ -20,15 +20,14 @@ #include "config.h" -#include "portaudio.h" +#include "portaudio.hpp" +#include #include #include #include -#include "albit.h" #include "alc/alconfig.h" -#include "alnumeric.h" #include "core/device.h" #include "core/logging.h" #include "dynload.h" @@ -39,10 +38,7 @@ namespace { -constexpr char pa_device[] = "PortAudio Default"; - - -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD void *pa_handle; #define MAKE_FUNC(x) decltype(x) * p##x MAKE_FUNC(Pa_Initialize); @@ -52,6 +48,8 @@ MAKE_FUNC(Pa_StartStream); MAKE_FUNC(Pa_StopStream); MAKE_FUNC(Pa_OpenStream); MAKE_FUNC(Pa_CloseStream); +MAKE_FUNC(Pa_GetDeviceCount); +MAKE_FUNC(Pa_GetDeviceInfo); MAKE_FUNC(Pa_GetDefaultOutputDevice); MAKE_FUNC(Pa_GetDefaultInputDevice); MAKE_FUNC(Pa_GetStreamInfo); @@ -65,26 +63,56 @@ MAKE_FUNC(Pa_GetStreamInfo); #define Pa_StopStream pPa_StopStream #define Pa_OpenStream pPa_OpenStream #define Pa_CloseStream pPa_CloseStream +#define Pa_GetDeviceCount pPa_GetDeviceCount +#define Pa_GetDeviceInfo pPa_GetDeviceInfo #define Pa_GetDefaultOutputDevice pPa_GetDefaultOutputDevice #define Pa_GetDefaultInputDevice pPa_GetDefaultInputDevice #define Pa_GetStreamInfo pPa_GetStreamInfo #endif #endif +struct DeviceEntry { + std::string mName; + uint mPlaybackChannels{}; + uint mCaptureChannels{}; +}; +std::vector DeviceNames; + +void EnumerateDevices() +{ + const auto devcount = Pa_GetDeviceCount(); + if(devcount < 0) + { + ERR("Error getting device count: {}", Pa_GetErrorText(devcount)); + return; + } + + std::vector(static_cast(devcount)).swap(DeviceNames); + PaDeviceIndex idx{0}; + for(auto &entry : DeviceNames) + { + if(auto info = Pa_GetDeviceInfo(idx); info && info->name) + { + entry.mName = info->name; + entry.mPlaybackChannels = static_cast(std::max(info->maxOutputChannels, 0)); + entry.mCaptureChannels = static_cast(std::max(info->maxInputChannels, 0)); + TRACE("Device {} \"{}\": {} playback, {} capture channels", idx, entry.mName, + info->maxOutputChannels, info->maxInputChannels); + } + ++idx; + } +} + +struct StreamParamsExt : public PaStreamParameters { uint updateSize; }; struct PortPlayback final : public BackendBase { - PortPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit PortPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~PortPlayback() override; int writeCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags) noexcept; - static int writeCallbackC(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData) noexcept - { - return static_cast(userData)->writeCallback(inputBuffer, outputBuffer, - framesPerBuffer, timeInfo, statusFlags); - } + + void createStream(PaDeviceIndex deviceid); void open(std::string_view name) override; bool reset() override; @@ -92,17 +120,15 @@ struct PortPlayback final : public BackendBase { void stop() override; PaStream *mStream{nullptr}; - PaStreamParameters mParams{}; - uint mUpdateSize{0u}; - - DEF_NEWDEL(PortPlayback) + StreamParamsExt mParams{}; + PaDeviceIndex mDeviceIdx{-1}; }; PortPlayback::~PortPlayback() { PaError err{mStream ? Pa_CloseStream(mStream) : paNoError}; if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); + ERR("Error closing stream: {}", Pa_GetErrorText(err)); mStream = nullptr; } @@ -116,100 +142,134 @@ int PortPlayback::writeCallback(const void*, void *outputBuffer, unsigned long f } -void PortPlayback::open(std::string_view name) +void PortPlayback::createStream(PaDeviceIndex deviceid) { - if(name.empty()) - name = pa_device; - else if(name != pa_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; - - PaStreamParameters params{}; - auto devidopt = ConfigValueInt(nullptr, "port", "device"); - if(devidopt && *devidopt >= 0) params.device = *devidopt; - else params.device = Pa_GetDefaultOutputDevice(); - params.suggestedLatency = mDevice->BufferSize / static_cast(mDevice->Frequency); - params.hostApiSpecificStreamInfo = nullptr; - - params.channelCount = ((mDevice->FmtChans == DevFmtMono) ? 1 : 2); + auto &devinfo = DeviceNames.at(static_cast(deviceid)); + auto params = StreamParamsExt{}; + params.device = deviceid; + params.suggestedLatency = mDevice->mBufferSize / static_cast(mDevice->mSampleRate); + params.hostApiSpecificStreamInfo = nullptr; + params.channelCount = static_cast(std::min(devinfo.mPlaybackChannels, + mDevice->channelsFromFmt())); switch(mDevice->FmtType) { - case DevFmtByte: - params.sampleFormat = paInt8; - break; - case DevFmtUByte: - params.sampleFormat = paUInt8; - break; - case DevFmtUShort: - /* fall-through */ - case DevFmtShort: - params.sampleFormat = paInt16; - break; - case DevFmtUInt: - /* fall-through */ - case DevFmtInt: - params.sampleFormat = paInt32; - break; - case DevFmtFloat: - params.sampleFormat = paFloat32; - break; + case DevFmtByte: params.sampleFormat = paInt8; break; + case DevFmtUByte: params.sampleFormat = paUInt8; break; + case DevFmtUShort: [[fallthrough]]; + case DevFmtShort: params.sampleFormat = paInt16; break; + case DevFmtUInt: [[fallthrough]]; + case DevFmtInt: params.sampleFormat = paInt32; break; + case DevFmtFloat: params.sampleFormat = paFloat32; break; } + params.updateSize = mDevice->mUpdateSize; -retry_open: - PaStream *stream{}; - PaError err{Pa_OpenStream(&stream, nullptr, ¶ms, mDevice->Frequency, mDevice->UpdateSize, - paNoFlag, &PortPlayback::writeCallbackC, this)}; - if(err != paNoError) + auto srate = uint{mDevice->mSampleRate}; + + static constexpr auto writeCallback = [](const void *inputBuffer, void *outputBuffer, + unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, + const PaStreamCallbackFlags statusFlags, void *userData) noexcept { - if(params.sampleFormat == paFloat32) - { + return static_cast(userData)->writeCallback(inputBuffer, outputBuffer, + framesPerBuffer, timeInfo, statusFlags); + }; + while(PaError err{Pa_OpenStream(&mStream, nullptr, ¶ms, srate, params.updateSize, paNoFlag, + writeCallback, this)}) + { + if(params.updateSize != DefaultUpdateSize) + params.updateSize = DefaultUpdateSize; + else if(srate != 48000u) + srate = (srate != 44100u) ? 44100u : 48000u; + else if(params.sampleFormat != paInt16) params.sampleFormat = paInt16; - goto retry_open; - } - throw al::backend_exception{al::backend_error::NoDevice, "Failed to open stream: %s", - Pa_GetErrorText(err)}; + else if(params.channelCount != 2) + params.channelCount = 2; + else + throw al::backend_exception{al::backend_error::NoDevice, "Failed to open stream: {}", + Pa_GetErrorText(err)}; } - Pa_CloseStream(mStream); - mStream = stream; mParams = params; - mUpdateSize = mDevice->UpdateSize; +} + +void PortPlayback::open(std::string_view name) +{ + if(DeviceNames.empty()) + EnumerateDevices(); + + PaDeviceIndex deviceid{-1}; + if(name.empty()) + { + if(auto devidopt = ConfigValueInt({}, "port", "device")) + deviceid = *devidopt; + if(deviceid < 0 || static_cast(deviceid) >= DeviceNames.size()) + deviceid = Pa_GetDefaultOutputDevice(); + name = DeviceNames.at(static_cast(deviceid)).mName; + } + else + { + auto iter = std::find_if(DeviceNames.cbegin(), DeviceNames.cend(), + [name](const DeviceEntry &entry) + { return entry.mPlaybackChannels > 0 && name == entry.mName; }); + if(iter == DeviceNames.cend()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name \"{}\" not found", name}; + deviceid = static_cast(std::distance(DeviceNames.cbegin(), iter)); + } + + createStream(deviceid); + mDeviceIdx = deviceid; - mDevice->DeviceName = name; + mDeviceName = name; } bool PortPlayback::reset() { - const PaStreamInfo *streamInfo{Pa_GetStreamInfo(mStream)}; - mDevice->Frequency = static_cast(streamInfo->sampleRate); - mDevice->UpdateSize = mUpdateSize; - - if(mParams.sampleFormat == paInt8) - mDevice->FmtType = DevFmtByte; - else if(mParams.sampleFormat == paUInt8) - mDevice->FmtType = DevFmtUByte; - else if(mParams.sampleFormat == paInt16) - mDevice->FmtType = DevFmtShort; - else if(mParams.sampleFormat == paInt32) - mDevice->FmtType = DevFmtInt; - else if(mParams.sampleFormat == paFloat32) - mDevice->FmtType = DevFmtFloat; - else + if(mStream) { - ERR("Unexpected sample format: 0x%lx\n", mParams.sampleFormat); - return false; + auto err = Pa_CloseStream(mStream); + if(err != paNoError) + ERR("Error closing stream: {}", Pa_GetErrorText(err)); + mStream = nullptr; } - if(mParams.channelCount >= 2) - mDevice->FmtChans = DevFmtStereo; - else if(mParams.channelCount == 1) - mDevice->FmtChans = DevFmtMono; - else + createStream(mDeviceIdx); + + switch(mParams.sampleFormat) { - ERR("Unexpected channel count: %u\n", mParams.channelCount); - return false; + case paFloat32: mDevice->FmtType = DevFmtFloat; break; + case paInt32: mDevice->FmtType = DevFmtInt; break; + case paInt16: mDevice->FmtType = DevFmtShort; break; + case paInt8: mDevice->FmtType = DevFmtByte; break; + case paUInt8: mDevice->FmtType = DevFmtUByte; break; + default: + ERR("Unexpected PortAudio sample format: {}", mParams.sampleFormat); + throw al::backend_exception{al::backend_error::NoDevice, "Invalid sample format: {}", + mParams.sampleFormat}; + } + + if(mParams.channelCount != static_cast(mDevice->channelsFromFmt())) + { + if(mParams.channelCount >= 2) + mDevice->FmtChans = DevFmtStereo; + else if(mParams.channelCount == 1) + mDevice->FmtChans = DevFmtMono; + mDevice->mAmbiOrder = 0; } + + const PaStreamInfo *streamInfo{Pa_GetStreamInfo(mStream)}; + mDevice->mSampleRate = static_cast(std::lround(streamInfo->sampleRate)); + mDevice->mUpdateSize = mParams.updateSize; + mDevice->mBufferSize = mDevice->mUpdateSize * 2; + if(streamInfo->outputLatency > 0.0f) + { + const double sampleLatency{streamInfo->outputLatency * streamInfo->sampleRate}; + TRACE("Reported stream latency: {:f} sec ({:f} samples)", streamInfo->outputLatency, + sampleLatency); + mDevice->mBufferSize = static_cast(std::clamp(sampleLatency, + double(mDevice->mBufferSize), double{std::numeric_limits::max()})); + } + setDefaultChannelOrder(); return true; @@ -217,33 +277,24 @@ bool PortPlayback::reset() void PortPlayback::start() { - const PaError err{Pa_StartStream(mStream)}; - if(err == paNoError) - throw al::backend_exception{al::backend_error::DeviceError, "Failed to start playback: %s", + if(const PaError err{Pa_StartStream(mStream)}; err != paNoError) + throw al::backend_exception{al::backend_error::DeviceError, "Failed to start playback: {}", Pa_GetErrorText(err)}; } void PortPlayback::stop() { - PaError err{Pa_StopStream(mStream)}; - if(err != paNoError) - ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); + if(PaError err{Pa_StopStream(mStream)}; err != paNoError) + ERR("Error stopping stream: {}", Pa_GetErrorText(err)); } struct PortCapture final : public BackendBase { - PortCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit PortCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~PortCapture() override; int readCallback(const void *inputBuffer, void *outputBuffer, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags) noexcept; - static int readCallbackC(const void *inputBuffer, void *outputBuffer, - unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, - const PaStreamCallbackFlags statusFlags, void *userData) noexcept - { - return static_cast(userData)->readCallback(inputBuffer, outputBuffer, - framesPerBuffer, timeInfo, statusFlags); - } + const PaStreamCallbackTimeInfo *timeInfo, const PaStreamCallbackFlags statusFlags) const noexcept; void open(std::string_view name) override; void start() override; @@ -252,47 +303,59 @@ struct PortCapture final : public BackendBase { uint availableSamples() override; PaStream *mStream{nullptr}; - PaStreamParameters mParams; + PaStreamParameters mParams{}; RingBufferPtr mRing{nullptr}; - - DEF_NEWDEL(PortCapture) }; PortCapture::~PortCapture() { PaError err{mStream ? Pa_CloseStream(mStream) : paNoError}; if(err != paNoError) - ERR("Error closing stream: %s\n", Pa_GetErrorText(err)); + ERR("Error closing stream: {}", Pa_GetErrorText(err)); mStream = nullptr; } int PortCapture::readCallback(const void *inputBuffer, void*, unsigned long framesPerBuffer, - const PaStreamCallbackTimeInfo*, const PaStreamCallbackFlags) noexcept + const PaStreamCallbackTimeInfo*, const PaStreamCallbackFlags) const noexcept { - mRing->write(inputBuffer, framesPerBuffer); + std::ignore = mRing->write(inputBuffer, framesPerBuffer); return 0; } void PortCapture::open(std::string_view name) { + if(DeviceNames.empty()) + EnumerateDevices(); + + int deviceid{}; if(name.empty()) - name = pa_device; - else if(name != pa_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + { + if(auto devidopt = ConfigValueInt({}, "port", "capture")) + deviceid = *devidopt; + if(deviceid < 0 || static_cast(deviceid) >= DeviceNames.size()) + deviceid = Pa_GetDefaultInputDevice(); + name = DeviceNames.at(static_cast(deviceid)).mName; + } + else + { + auto iter = std::find_if(DeviceNames.cbegin(), DeviceNames.cend(), + [name](const DeviceEntry &entry) + { return entry.mCaptureChannels > 0 && name == entry.mName; }); + if(iter == DeviceNames.cend()) + throw al::backend_exception{al::backend_error::NoDevice, + "Device name \"{}\" not found", name}; + deviceid = static_cast(std::distance(DeviceNames.cbegin(), iter)); + } - uint samples{mDevice->BufferSize}; - samples = maxu(samples, 100 * mDevice->Frequency / 1000); - uint frame_size{mDevice->frameSizeFromFmt()}; + const uint samples{std::max(mDevice->mBufferSize, mDevice->mSampleRate/10u)}; + const uint frame_size{mDevice->frameSizeFromFmt()}; mRing = RingBuffer::Create(samples, frame_size, false); - auto devidopt = ConfigValueInt(nullptr, "port", "capture"); - if(devidopt && *devidopt >= 0) mParams.device = *devidopt; - else mParams.device = Pa_GetDefaultOutputDevice(); + mParams.device = deviceid; mParams.suggestedLatency = 0.0f; mParams.hostApiSpecificStreamInfo = nullptr; @@ -315,34 +378,39 @@ void PortCapture::open(std::string_view name) break; case DevFmtUInt: case DevFmtUShort: - throw al::backend_exception{al::backend_error::DeviceError, "%s samples not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} samples not supported", DevFmtTypeString(mDevice->FmtType)}; } mParams.channelCount = static_cast(mDevice->channelsFromFmt()); - PaError err{Pa_OpenStream(&mStream, &mParams, nullptr, mDevice->Frequency, - paFramesPerBufferUnspecified, paNoFlag, &PortCapture::readCallbackC, this)}; + static constexpr auto readCallback = [](const void *inputBuffer, void *outputBuffer, + unsigned long framesPerBuffer, const PaStreamCallbackTimeInfo *timeInfo, + const PaStreamCallbackFlags statusFlags, void *userData) noexcept + { + return static_cast(userData)->readCallback(inputBuffer, outputBuffer, + framesPerBuffer, timeInfo, statusFlags); + }; + PaError err{Pa_OpenStream(&mStream, &mParams, nullptr, mDevice->mSampleRate, + paFramesPerBufferUnspecified, paNoFlag, readCallback, this)}; if(err != paNoError) - throw al::backend_exception{al::backend_error::NoDevice, "Failed to open stream: %s", + throw al::backend_exception{al::backend_error::NoDevice, "Failed to open stream: {}", Pa_GetErrorText(err)}; - mDevice->DeviceName = name; + mDeviceName = name; } void PortCapture::start() { - const PaError err{Pa_StartStream(mStream)}; - if(err != paNoError) + if(const PaError err{Pa_StartStream(mStream)}; err != paNoError) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start recording: %s", Pa_GetErrorText(err)}; + "Failed to start recording: {}", Pa_GetErrorText(err)}; } void PortCapture::stop() { - PaError err{Pa_StopStream(mStream)}; - if(err != paNoError) - ERR("Error stopping stream: %s\n", Pa_GetErrorText(err)); + if(PaError err{Pa_StopStream(mStream)}; err != paNoError) + ERR("Error stopping stream: {}", Pa_GetErrorText(err)); } @@ -350,16 +418,14 @@ uint PortCapture::availableSamples() { return static_cast(mRing->readSpace()); } void PortCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } } // namespace bool PortBackendFactory::init() { - PaError err; - -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD if(!pa_handle) { #ifdef _WIN32 @@ -377,7 +443,7 @@ bool PortBackendFactory::init() return false; #define LOAD_FUNC(f) do { \ - p##f = al::bit_cast(GetSymbol(pa_handle, #f)); \ + p##f = reinterpret_cast(GetSymbol(pa_handle, #f)); \ if(p##f == nullptr) \ { \ CloseLib(pa_handle); \ @@ -392,23 +458,27 @@ bool PortBackendFactory::init() LOAD_FUNC(Pa_StopStream); LOAD_FUNC(Pa_OpenStream); LOAD_FUNC(Pa_CloseStream); + LOAD_FUNC(Pa_GetDeviceCount); + LOAD_FUNC(Pa_GetDeviceInfo); LOAD_FUNC(Pa_GetDefaultOutputDevice); LOAD_FUNC(Pa_GetDefaultInputDevice); LOAD_FUNC(Pa_GetStreamInfo); #undef LOAD_FUNC - if((err=Pa_Initialize()) != paNoError) + const PaError err{Pa_Initialize()}; + if(err != paNoError) { - ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err)); + ERR("Pa_Initialize() returned an error: {}", Pa_GetErrorText(err)); CloseLib(pa_handle); pa_handle = nullptr; return false; } } #else - if((err=Pa_Initialize()) != paNoError) + const PaError err{Pa_Initialize()}; + if(err != paNoError) { - ERR("Pa_Initialize() returned an error: %s\n", Pa_GetErrorText(err)); + ERR("Pa_Initialize() returned an error: {}", Pa_GetErrorText(err)); return false; } #endif @@ -418,18 +488,52 @@ bool PortBackendFactory::init() bool PortBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string PortBackendFactory::probe(BackendType type) +auto PortBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector devices; + + EnumerateDevices(); + int defaultid{-1}; switch(type) { case BackendType::Playback: + defaultid = Pa_GetDefaultOutputDevice(); + if(auto devidopt = ConfigValueInt({}, "port", "device"); devidopt && *devidopt >= 0 + && static_cast(*devidopt) < DeviceNames.size()) + defaultid = *devidopt; + + for(size_t i{0};i < DeviceNames.size();++i) + { + if(DeviceNames[i].mPlaybackChannels > 0) + { + if(defaultid >= 0 && static_cast(defaultid) == i) + devices.emplace(devices.cbegin(), DeviceNames[i].mName); + else + devices.emplace_back(DeviceNames[i].mName); + } + } + break; + case BackendType::Capture: - /* Includes null char. */ - outnames.append(pa_device, sizeof(pa_device)); + defaultid = Pa_GetDefaultInputDevice(); + if(auto devidopt = ConfigValueInt({}, "port", "capture"); devidopt && *devidopt >= 0 + && static_cast(*devidopt) < DeviceNames.size()) + defaultid = *devidopt; + + for(size_t i{0};i < DeviceNames.size();++i) + { + if(DeviceNames[i].mCaptureChannels > 0) + { + if(defaultid >= 0 && static_cast(defaultid) == i) + devices.emplace(devices.cbegin(), DeviceNames[i].mName); + else + devices.emplace_back(DeviceNames[i].mName); + } + } break; } - return outnames; + + return devices; } BackendPtr PortBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/portaudio.h b/3rdparty/openal/alc/backends/portaudio.h deleted file mode 100644 index c35ccff2d625..000000000000 --- a/3rdparty/openal/alc/backends/portaudio.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef BACKENDS_PORTAUDIO_H -#define BACKENDS_PORTAUDIO_H - -#include "base.h" - -struct PortBackendFactory final : public BackendFactory { -public: - bool init() override; - - bool querySupport(BackendType type) override; - - std::string probe(BackendType type) override; - - BackendPtr createBackend(DeviceBase *device, BackendType type) override; - - static BackendFactory &getFactory(); -}; - -#endif /* BACKENDS_PORTAUDIO_H */ diff --git a/3rdparty/openal/alc/backends/portaudio.hpp b/3rdparty/openal/alc/backends/portaudio.hpp new file mode 100644 index 000000000000..69c78ea9df7c --- /dev/null +++ b/3rdparty/openal/alc/backends/portaudio.hpp @@ -0,0 +1,19 @@ +#ifndef BACKENDS_PORTAUDIO_HPP +#define BACKENDS_PORTAUDIO_HPP + +#include "base.h" + +struct PortBackendFactory final : public BackendFactory { +public: + auto init() -> bool final; + + auto querySupport(BackendType type) -> bool final; + + auto enumerate(BackendType type) -> std::vector final; + + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; +}; + +#endif /* BACKENDS_PORTAUDIO_HPP */ diff --git a/3rdparty/openal/alc/backends/pulseaudio.cpp b/3rdparty/openal/alc/backends/pulseaudio.cpp index e2cea8a8e596..aac014157518 100644 --- a/3rdparty/openal/alc/backends/pulseaudio.cpp +++ b/3rdparty/openal/alc/backends/pulseaudio.cpp @@ -28,27 +28,28 @@ #include #include #include +#include +#include +#include #include #include #include #include -#include -#include #include +#include #include #include #include -#include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" -#include "almalloc.h" #include "alnumeric.h" #include "alspan.h" +#include "base.h" #include "core/devformat.h" #include "core/device.h" #include "core/logging.h" #include "dynload.h" +#include "fmt/core.h" #include "opthelpers.h" #include "strutils.h" @@ -57,9 +58,10 @@ namespace { +using namespace std::string_view_literals; using uint = unsigned int; -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD #define PULSE_FUNCS(MAGIC) \ MAGIC(pa_context_new); \ MAGIC(pa_context_unref); \ @@ -71,8 +73,10 @@ using uint = unsigned int; MAGIC(pa_context_errno); \ MAGIC(pa_context_connect); \ MAGIC(pa_context_get_server_info); \ + MAGIC(pa_context_get_sink_info_by_index); \ MAGIC(pa_context_get_sink_info_by_name); \ MAGIC(pa_context_get_sink_info_list); \ + MAGIC(pa_context_get_source_info_by_index); \ MAGIC(pa_context_get_source_info_by_name); \ MAGIC(pa_context_get_source_info_list); \ MAGIC(pa_stream_new); \ @@ -144,8 +148,10 @@ PULSE_FUNCS(MAKE_FUNC) #define pa_context_errno ppa_context_errno #define pa_context_connect ppa_context_connect #define pa_context_get_server_info ppa_context_get_server_info +#define pa_context_get_sink_info_by_index ppa_context_get_sink_info_by_index #define pa_context_get_sink_info_by_name ppa_context_get_sink_info_by_name #define pa_context_get_sink_info_list ppa_context_get_sink_info_list +#define pa_context_get_source_info_by_index ppa_context_get_source_info_by_index #define pa_context_get_source_info_by_name ppa_context_get_source_info_by_name #define pa_context_get_source_info_list ppa_context_get_source_info_list #define pa_stream_new ppa_stream_new @@ -251,7 +257,7 @@ constexpr pa_channel_map MonoChanMap{ }; -/* *grumble* Don't use enums for bitflags. */ +/* NOLINTBEGIN(*EnumCastOutOfRange) *grumble* Don't use enums for bitflags. */ constexpr pa_stream_flags_t operator|(pa_stream_flags_t lhs, pa_stream_flags_t rhs) { return pa_stream_flags_t(lhs | al::to_underlying(rhs)); } constexpr pa_stream_flags_t& operator|=(pa_stream_flags_t &lhs, pa_stream_flags_t rhs) @@ -277,11 +283,13 @@ constexpr pa_context_flags_t& operator|=(pa_context_flags_t &lhs, pa_context_fla constexpr pa_subscription_mask_t operator|(pa_subscription_mask_t lhs, pa_subscription_mask_t rhs) { return pa_subscription_mask_t(lhs | al::to_underlying(rhs)); } +/* NOLINTEND(*EnumCastOutOfRange) */ struct DevMap { std::string name; std::string device_name; + uint32_t index{}; }; bool checkName(const al::span list, const std::string &name) @@ -293,6 +301,9 @@ bool checkName(const al::span list, const std::string &name) std::vector PlaybackDevices; std::vector CaptureDevices; +std::string DefaultPlaybackDevName; +std::string DefaultCaptureDevName; + /* Global flags and properties */ pa_context_flags_t pulse_ctx_flags; @@ -321,11 +332,12 @@ class PulseMainloop { explicit operator bool() const noexcept { return mLoop != nullptr; } + [[nodiscard]] auto start() const { return pa_threaded_mainloop_start(mLoop); } auto stop() const { return pa_threaded_mainloop_stop(mLoop); } - auto getApi() const { return pa_threaded_mainloop_get_api(mLoop); } - auto getContext() const noexcept { return mContext; } + [[nodiscard]] auto getApi() const { return pa_threaded_mainloop_get_api(mLoop); } + [[nodiscard]] auto getContext() const noexcept { return mContext; } auto lock() const { return pa_threaded_mainloop_lock(mLoop); } auto unlock() const { return pa_threaded_mainloop_unlock(mLoop); } @@ -335,14 +347,40 @@ class PulseMainloop { static auto Create() { return PulseMainloop{pa_threaded_mainloop_new()}; } - void streamSuccessCallback(pa_stream*, int) noexcept { signal(); } + void streamSuccessCallback(pa_stream*, int) const noexcept { signal(); } static void streamSuccessCallbackC(pa_stream *stream, int success, void *pdata) noexcept { static_cast(pdata)->streamSuccessCallback(stream, success); } void close(pa_stream *stream=nullptr); - void deviceSinkCallback(pa_context*, const pa_sink_info *info, int eol) noexcept + void updateDefaultDevice(pa_context*, const pa_server_info *info) const + { + auto default_sink = info->default_sink_name ? std::string_view{info->default_sink_name} + : std::string_view{}; + auto default_src = info->default_source_name ? std::string_view{info->default_source_name} + : std::string_view{}; + + if(default_sink != DefaultPlaybackDevName) + { + TRACE("Default playback device: {}", default_sink); + DefaultPlaybackDevName = default_sink; + + const auto msg = fmt::format("Default playback device changed: {}", default_sink); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, msg); + } + if(default_src != DefaultCaptureDevName) + { + TRACE("Default capture device: {}", default_src); + DefaultCaptureDevName = default_src; + + const auto msg = fmt::format("Default capture device changed: {}", default_src); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, msg); + } + signal(); + } + + void deviceSinkCallback(pa_context*, const pa_sink_info *info, int eol) const noexcept { if(eol) { @@ -359,21 +397,21 @@ class PulseMainloop { /* Make sure the display name (description) is unique. Append a number * counter as needed. */ - int count{1}; - std::string newname{info->description}; + auto count = 1; + auto newname = std::string{info->description}; while(checkName(PlaybackDevices, newname)) - { - newname = info->description; - newname += " #"; - newname += std::to_string(++count); - } - PlaybackDevices.emplace_back(DevMap{std::move(newname), info->name}); - DevMap &newentry = PlaybackDevices.back(); + newname = fmt::format("{} #{}", info->description, ++count); - TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str()); + const auto &newentry = PlaybackDevices.emplace_back(DevMap{std::move(newname), + info->name, info->index}); + TRACE("Got device \"{}\", \"{}\" ({})", newentry.name, newentry.device_name, + newentry.index); + + const auto msg = fmt::format("Device added: {}", newentry.device_name); + alc::Event(alc::EventType::DeviceAdded, alc::DeviceType::Playback, msg); } - void deviceSourceCallback(pa_context*, const pa_source_info *info, int eol) noexcept + void deviceSourceCallback(pa_context*, const pa_source_info *info, int eol) const noexcept { if(eol) { @@ -390,22 +428,77 @@ class PulseMainloop { /* Make sure the display name (description) is unique. Append a number * counter as needed. */ - int count{1}; - std::string newname{info->description}; + auto count = 1; + auto newname = std::string{info->description}; while(checkName(CaptureDevices, newname)) + newname = fmt::format("{} #{}", info->description, ++count); + + const auto &newentry = CaptureDevices.emplace_back(DevMap{std::move(newname), info->name, + info->index}); + TRACE("Got device \"{}\", \"{}\" ({})", newentry.name, newentry.device_name, + newentry.index); + + const auto msg = fmt::format("Device added: {}", newentry.device_name); + alc::Event(alc::EventType::DeviceAdded, alc::DeviceType::Capture, msg); + } + + void eventCallback(pa_context *context, pa_subscription_event_type_t t, uint32_t idx) noexcept + { + const auto eventFacility = (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK); + const auto eventType = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); + + if(eventFacility == PA_SUBSCRIPTION_EVENT_SERVER + && eventType == PA_SUBSCRIPTION_EVENT_CHANGE) { - newname = info->description; - newname += " #"; - newname += std::to_string(++count); + static constexpr auto server_cb = [](pa_context *ctx, const pa_server_info *info, + void *pdata) noexcept + { return static_cast(pdata)->updateDefaultDevice(ctx, info); }; + auto *op = pa_context_get_server_info(context, server_cb, this); + if(op) pa_operation_unref(op); } - CaptureDevices.emplace_back(DevMap{std::move(newname), info->name}); - DevMap &newentry = CaptureDevices.back(); - TRACE("Got device \"%s\", \"%s\"\n", newentry.name.c_str(), newentry.device_name.c_str()); - } + if(eventFacility != PA_SUBSCRIPTION_EVENT_SINK + && eventFacility != PA_SUBSCRIPTION_EVENT_SOURCE) + return; - void probePlaybackDevices(); - void probeCaptureDevices(); + const auto devtype = (eventFacility == PA_SUBSCRIPTION_EVENT_SINK) + ? alc::DeviceType::Playback : alc::DeviceType::Capture; + + if(eventType == PA_SUBSCRIPTION_EVENT_NEW) + { + if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK) + { + static constexpr auto devcallback = [](pa_context *ctx, const pa_sink_info *info, + int eol, void *pdata) noexcept + { return static_cast(pdata)->deviceSinkCallback(ctx, info, eol); }; + auto *op = pa_context_get_sink_info_by_index(context, idx, devcallback, this); + if(op) pa_operation_unref(op); + } + else + { + static constexpr auto devcallback = [](pa_context *ctx, const pa_source_info *info, + int eol, void *pdata) noexcept + { return static_cast(pdata)->deviceSourceCallback(ctx,info,eol); }; + auto *op = pa_context_get_source_info_by_index(context, idx, devcallback, this); + if(op) pa_operation_unref(op); + } + } + else if(eventType == PA_SUBSCRIPTION_EVENT_REMOVE) + { + auto find_index = [idx](const DevMap &entry) noexcept { return entry.index == idx; }; + + auto &devlist = (eventFacility == PA_SUBSCRIPTION_EVENT_SINK) + ? PlaybackDevices : CaptureDevices; + auto iter = std::find_if(devlist.cbegin(), devlist.cend(), find_index); + if(iter != devlist.cend()) + { + devlist.erase(iter); + + const auto msg = fmt::format("Device removed: {}", idx); + alc::Event(alc::EventType::DeviceRemoved, devtype, msg); + } + } + } friend struct MainloopUniqueLock; }; @@ -420,7 +513,7 @@ struct MainloopUniqueLock : public std::unique_lock { auto wait(Predicate done_waiting) const -> void { while(!done_waiting()) wait(); } - void waitForOperation(pa_operation *op) + void waitForOperation(pa_operation *op) const { if(op) { @@ -432,36 +525,38 @@ struct MainloopUniqueLock : public std::unique_lock { void setEventHandler() { - pa_operation *op{pa_context_subscribe(mutex()->mContext, - PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE, - [](pa_context*, int, void *pdata) noexcept - { static_cast(pdata)->signal(); }, - mutex())}; + auto *context = mutex()->mContext; + + /* Watch for device added/removed and server changed events. */ + static constexpr auto submask = PA_SUBSCRIPTION_MASK_SINK | PA_SUBSCRIPTION_MASK_SOURCE + | PA_SUBSCRIPTION_MASK_SERVER; + static constexpr auto do_signal = [](pa_context*, int, void *pdata) noexcept + { static_cast(pdata)->signal(); }; + auto *op = pa_context_subscribe(context, submask, do_signal, mutex()); waitForOperation(op); - /* Watch for device added/removed events. - * - * TODO: Also track the "default" device, in as much as PulseAudio has - * the concept of a default device (whatever device is opened when not - * specifying a specific sink or source name). There doesn't seem to be - * an event for this. - */ - auto handler = [](pa_context*, pa_subscription_event_type_t t, uint32_t, void*) noexcept - { - const auto eventFacility = (t & PA_SUBSCRIPTION_EVENT_FACILITY_MASK); - if(eventFacility == PA_SUBSCRIPTION_EVENT_SINK - || eventFacility == PA_SUBSCRIPTION_EVENT_SOURCE) - { - const auto deviceType = (eventFacility == PA_SUBSCRIPTION_EVENT_SINK) - ? alc::DeviceType::Playback : alc::DeviceType::Capture; - const auto eventType = (t & PA_SUBSCRIPTION_EVENT_TYPE_MASK); - if(eventType == PA_SUBSCRIPTION_EVENT_NEW) - alc::Event(alc::EventType::DeviceAdded, deviceType, "Device added"); - else if(eventType == PA_SUBSCRIPTION_EVENT_REMOVE) - alc::Event(alc::EventType::DeviceRemoved, deviceType, "Device removed"); - } - }; - pa_context_set_subscribe_callback(mutex()->mContext, handler, nullptr); + static constexpr auto handler = [](pa_context *ctx, pa_subscription_event_type_t t, + uint32_t index, void *pdata) noexcept + { return static_cast(pdata)->eventCallback(ctx, t, index); }; + pa_context_set_subscribe_callback(context, handler, mutex()); + + /* Fill in the initial device lists, and get the defaults. */ + auto sink_callback = [](pa_context *ctx, const pa_sink_info *info, int eol, void *pdata) noexcept + { return static_cast(pdata)->deviceSinkCallback(ctx, info, eol); }; + + auto src_callback = [](pa_context *ctx, const pa_source_info *info, int eol, void *pdata) noexcept + { return static_cast(pdata)->deviceSourceCallback(ctx, info, eol); }; + + auto server_callback = [](pa_context *ctx, const pa_server_info *info, void *pdata) noexcept + { return static_cast(pdata)->updateDefaultDevice(ctx, info); }; + + auto *sinkop = pa_context_get_sink_info_list(context, sink_callback, mutex()); + auto *srcop = pa_context_get_source_info_list(context, src_callback, mutex()); + auto *serverop = pa_context_get_server_info(context, server_callback, mutex()); + + waitForOperation(sinkop); + waitForOperation(srcop); + waitForOperation(serverop); } @@ -482,6 +577,13 @@ struct MainloopUniqueLock : public std::unique_lock { void connectContext(); pa_stream *connectStream(const char *device_name, pa_stream_flags_t flags, pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, BackendType type); + + pa_stream *connectStream(const std::string &device_name, pa_stream_flags_t flags, + pa_buffer_attr *attr, pa_sample_spec *spec, pa_channel_map *chanmap, BackendType type) + { + return connectStream(device_name.empty() ? nullptr : device_name.c_str(), flags, attr, + spec, chanmap, type); + } }; using MainloopLockGuard = std::lock_guard; @@ -489,7 +591,7 @@ PulseMainloop::~PulseMainloop() { if(mContext) { - MainloopUniqueLock _{*this}; + MainloopUniqueLock looplock{*this}; pa_context_disconnect(mContext); pa_context_unref(mContext); } @@ -510,21 +612,20 @@ void MainloopUniqueLock::connectContext() pa_context_set_state_callback(mutex()->mContext, [](pa_context *ctx, void *pdata) noexcept { return static_cast(pdata)->contextStateCallback(ctx); }, this); - int err; - if((err=pa_context_connect(mutex()->mContext, nullptr, pulse_ctx_flags, nullptr)) >= 0) + int err{pa_context_connect(mutex()->mContext, nullptr, pulse_ctx_flags, nullptr)}; + if(err >= 0) { - pa_context_state_t state; - while((state=pa_context_get_state(mutex()->mContext)) != PA_CONTEXT_READY) + wait([&err,this]() { + pa_context_state_t state{pa_context_get_state(mutex()->mContext)}; if(!PA_CONTEXT_IS_GOOD(state)) { err = pa_context_errno(mutex()->mContext); - if(err > 0) err = -err; - break; + if(err > 0) err = -err; + return true; } - - wait(); - } + return state == PA_CONTEXT_READY; + }); } pa_context_set_state_callback(mutex()->mContext, nullptr, nullptr); @@ -532,7 +633,7 @@ void MainloopUniqueLock::connectContext() { pa_context_unref(mutex()->mContext); mutex()->mContext = nullptr; - throw al::backend_exception{al::backend_error::DeviceError, "Context did not connect (%s)", + throw al::backend_exception{al::backend_error::DeviceError, "Context did not connect ({})", pa_strerror(err)}; } } @@ -543,7 +644,7 @@ pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_stream_ const char *stream_id{(type==BackendType::Playback) ? "Playback Stream" : "Capture Stream"}; pa_stream *stream{pa_stream_new(mutex()->mContext, stream_id, spec, chanmap)}; if(!stream) - throw al::backend_exception{al::backend_error::OutOfMemory, "pa_stream_new() failed (%s)", + throw al::backend_exception{al::backend_error::OutOfMemory, "pa_stream_new() failed ({})", pa_strerror(pa_context_errno(mutex()->mContext))}; pa_stream_set_state_callback(stream, [](pa_stream *strm, void *pdata) noexcept @@ -555,23 +656,23 @@ pa_stream *MainloopUniqueLock::connectStream(const char *device_name, pa_stream_ if(err < 0) { pa_stream_unref(stream); - throw al::backend_exception{al::backend_error::DeviceError, "%s did not connect (%s)", + throw al::backend_exception{al::backend_error::DeviceError, "%s did not connect ({})", stream_id, pa_strerror(err)}; } - pa_stream_state_t state; - while((state=pa_stream_get_state(stream)) != PA_STREAM_READY) + wait([&err,stream,stream_id,this]() { + pa_stream_state_t state{pa_stream_get_state(stream)}; if(!PA_STREAM_IS_GOOD(state)) { err = pa_context_errno(mutex()->mContext); pa_stream_unref(stream); throw al::backend_exception{al::backend_error::DeviceError, - "%s did not get ready (%s)", stream_id, pa_strerror(err)}; + "{} did not get ready ({})", stream_id, pa_strerror(err)}; } + return state == PA_STREAM_READY; + }); - wait(); - } pa_stream_set_state_callback(stream, nullptr, nullptr); return stream; @@ -582,7 +683,7 @@ void PulseMainloop::close(pa_stream *stream) if(!stream) return; - MainloopUniqueLock _{*this}; + MainloopUniqueLock looplock{*this}; pa_stream_set_state_callback(stream, nullptr, nullptr); pa_stream_set_moved_callback(stream, nullptr, nullptr); pa_stream_set_write_callback(stream, nullptr, nullptr); @@ -592,52 +693,12 @@ void PulseMainloop::close(pa_stream *stream) } -void PulseMainloop::probePlaybackDevices() -{ - PlaybackDevices.clear(); - try { - MainloopUniqueLock plock{*this}; - auto sink_callback = [](pa_context *ctx, const pa_sink_info *info, int eol, void *pdata) noexcept - { return static_cast(pdata)->deviceSinkCallback(ctx, info, eol); }; - - pa_operation *op{pa_context_get_sink_info_by_name(mContext, nullptr, sink_callback, this)}; - plock.waitForOperation(op); - - op = pa_context_get_sink_info_list(mContext, sink_callback, this); - plock.waitForOperation(op); - } - catch(std::exception &e) { - ERR("Error enumerating devices: %s\n", e.what()); - } -} - -void PulseMainloop::probeCaptureDevices() -{ - CaptureDevices.clear(); - try { - MainloopUniqueLock plock{*this}; - auto src_callback = [](pa_context *ctx, const pa_source_info *info, int eol, void *pdata) noexcept - { return static_cast(pdata)->deviceSourceCallback(ctx, info, eol); }; - - pa_operation *op{pa_context_get_source_info_by_name(mContext, nullptr, src_callback, - this)}; - plock.waitForOperation(op); - - op = pa_context_get_source_info_list(mContext, src_callback, this); - plock.waitForOperation(op); - } - catch(std::exception &e) { - ERR("Error enumerating devices: %s\n", e.what()); - } -} - - /* Used for initial connection test and enumeration. */ PulseMainloop gGlobalMainloop; struct PulsePlayback final : public BackendBase { - PulsePlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit PulsePlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~PulsePlayback() override; void bufferAttrCallback(pa_stream *stream) noexcept; @@ -655,17 +716,15 @@ struct PulsePlayback final : public BackendBase { PulseMainloop mMainloop; - std::optional mDeviceName{std::nullopt}; + std::optional mDeviceId{std::nullopt}; bool mIs51Rear{false}; - pa_buffer_attr mAttr; - pa_sample_spec mSpec; + pa_buffer_attr mAttr{}; + pa_sample_spec mSpec{}; pa_stream *mStream{nullptr}; uint mFrameSize{0u}; - - DEF_NEWDEL(PulsePlayback) }; PulsePlayback::~PulsePlayback() @@ -680,14 +739,14 @@ void PulsePlayback::bufferAttrCallback(pa_stream *stream) noexcept * leaving it alone means ALC_REFRESH will be off. */ mAttr = *(pa_stream_get_buffer_attr(stream)); - TRACE("minreq=%d, tlength=%d, prebuf=%d\n", mAttr.minreq, mAttr.tlength, mAttr.prebuf); + TRACE("minreq={}, tlength={}, prebuf={}", mAttr.minreq, mAttr.tlength, mAttr.prebuf); } void PulsePlayback::streamStateCallback(pa_stream *stream) noexcept { if(pa_stream_get_state(stream) == PA_STREAM_FAILED) { - ERR("Received stream failure!\n"); + ERR("Received stream failure!"); mDevice->handleDisconnect("Playback stream failure"); } mMainloop.signal(); @@ -706,14 +765,14 @@ void PulsePlayback::streamWriteCallback(pa_stream *stream, size_t nbytes) noexce free_func = pa_xfree; } else - buflen = minz(buflen, nbytes); + buflen = std::min(buflen, nbytes); nbytes -= buflen; mDevice->renderSamples(buf, static_cast(buflen/mFrameSize), mSpec.channels); int ret{pa_stream_write(stream, buf, buflen, free_func, 0, PA_SEEK_RELATIVE)}; if(ret != PA_OK) UNLIKELY - ERR("Failed to write to stream: %d, %s\n", ret, pa_strerror(ret)); + ERR("Failed to write to stream: {}, {}", ret, pa_strerror(ret)); } while(nbytes > 0); } @@ -754,13 +813,13 @@ void PulsePlayback::sinkInfoCallback(pa_context*, const pa_sink_info *info, int else { mIs51Rear = false; - char chanmap_str[PA_CHANNEL_MAP_SNPRINT_MAX]{}; - pa_channel_map_snprint(chanmap_str, sizeof(chanmap_str), &info->channel_map); - WARN("Failed to find format for channel map:\n %s\n", chanmap_str); + std::array chanmap_str{}; + pa_channel_map_snprint(chanmap_str.data(), chanmap_str.size(), &info->channel_map); + WARN("Failed to find format for channel map:\n {}", chanmap_str.data()); } if(info->active_port) - TRACE("Active port: %s (%s)\n", info->active_port->name, info->active_port->description); + TRACE("Active port: {} ({})", info->active_port->name, info->active_port->description); mDevice->Flags.set(DirectEar, (info->active_port && strcmp(info->active_port->name, "analog-output-headphones") == 0)); } @@ -772,35 +831,37 @@ void PulsePlayback::sinkNameCallback(pa_context*, const pa_sink_info *info, int mMainloop.signal(); return; } - mDevice->DeviceName = info->description; + mDeviceName = info->description; } void PulsePlayback::streamMovedCallback(pa_stream *stream) noexcept { - mDeviceName = pa_stream_get_device_name(stream); - TRACE("Stream moved to %s\n", mDeviceName->c_str()); + mDeviceId = pa_stream_get_device_name(stream); + TRACE("Stream moved to {}", *mDeviceId); } void PulsePlayback::open(std::string_view name) { mMainloop = PulseMainloop::Create(); - mMainloop.start(); + if(mMainloop.start() != 0) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to start device mainloop"}; - const char *pulse_name{nullptr}; - const char *dev_name{nullptr}; + auto pulse_name = std::string{}; if(!name.empty()) { - if(PlaybackDevices.empty()) - mMainloop.probePlaybackDevices(); + auto match_name = [name](const DevMap &entry) -> bool + { return entry.name == name || entry.device_name == name; }; - auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(), - [name](const DevMap &entry) -> bool { return entry.name == name; }); + auto plock = MainloopUniqueLock{gGlobalMainloop}; + auto iter = std::find_if(PlaybackDevices.cbegin(), PlaybackDevices.cend(), match_name); if(iter == PlaybackDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; - pulse_name = iter->device_name.c_str(); - dev_name = iter->name.c_str(); + "Device name \"{}\" not found", name}; + + pulse_name = iter->device_name; + mDeviceName = iter->name; } MainloopUniqueLock plock{mMainloop}; @@ -808,7 +869,7 @@ void PulsePlayback::open(std::string_view name) pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_FIX_FORMAT | PA_STREAM_FIX_RATE | PA_STREAM_FIX_CHANNELS}; - if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", true)) + if(!GetConfigValueBool({}, "pulse", "allow-moves", true)) flags |= PA_STREAM_DONT_MOVE; pa_sample_spec spec{}; @@ -816,37 +877,38 @@ void PulsePlayback::open(std::string_view name) spec.rate = 44100; spec.channels = 2; - if(!pulse_name) + if(pulse_name.empty()) { static const auto defname = al::getenv("ALSOFT_PULSE_DEFAULT"); - if(defname) pulse_name = defname->c_str(); + if(defname) pulse_name = *defname; } - TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); + TRACE("Connecting to \"{}\"", pulse_name.empty() ? "(default)"sv:std::string_view{pulse_name}); mStream = plock.connectStream(pulse_name, flags, nullptr, &spec, nullptr, BackendType::Playback); - pa_stream_set_moved_callback(mStream, [](pa_stream *stream, void *pdata) noexcept - { return static_cast(pdata)->streamMovedCallback(stream); }, this); + static constexpr auto move_callback = [](pa_stream *stream, void *pdata) noexcept + { return static_cast(pdata)->streamMovedCallback(stream); }; + pa_stream_set_moved_callback(mStream, move_callback, this); mFrameSize = static_cast(pa_frame_size(pa_stream_get_sample_spec(mStream))); - if(pulse_name) mDeviceName.emplace(pulse_name); - else mDeviceName.reset(); - if(!dev_name) + if(!pulse_name.empty()) + mDeviceId.emplace(std::move(pulse_name)); + + if(mDeviceName.empty()) { - auto name_callback = [](pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept + static constexpr auto name_callback = [](pa_context *context, const pa_sink_info *info, + int eol, void *pdata) noexcept { return static_cast(pdata)->sinkNameCallback(context, info, eol); }; pa_operation *op{pa_context_get_sink_info_by_name(mMainloop.getContext(), pa_stream_get_device_name(mStream), name_callback, this)}; plock.waitForOperation(op); } - else - mDevice->DeviceName = dev_name; } bool PulsePlayback::reset() { MainloopUniqueLock plock{mMainloop}; - const auto deviceName = mDeviceName ? mDeviceName->c_str() : nullptr; + const auto deviceName = mDeviceId ? mDeviceId->c_str() : nullptr; if(mStream) { @@ -859,17 +921,17 @@ bool PulsePlayback::reset() mStream = nullptr; } - auto info_callback = [](pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept + auto info_cb = [](pa_context *context, const pa_sink_info *info, int eol, void *pdata) noexcept { return static_cast(pdata)->sinkInfoCallback(context, info, eol); }; - pa_operation *op{pa_context_get_sink_info_by_name(mMainloop.getContext(), deviceName, - info_callback, this)}; + pa_operation *op{pa_context_get_sink_info_by_name(mMainloop.getContext(), deviceName, info_cb, + this)}; plock.waitForOperation(op); pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_INTERPOLATE_TIMING | PA_STREAM_AUTO_TIMING_UPDATE | PA_STREAM_EARLY_REQUESTS}; - if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", true)) + if(!GetConfigValueBool({}, "pulse", "allow-moves", true)) flags |= PA_STREAM_DONT_MOVE; - if(GetConfigValueBool(mDevice->DeviceName.c_str(), "pulse", "adjust-latency", false)) + if(GetConfigValueBool(mDevice->mDeviceName, "pulse", "adjust-latency", false)) { /* ADJUST_LATENCY can't be specified with EARLY_REQUESTS, for some * reason. So if the user wants to adjust the overall device latency, @@ -878,7 +940,7 @@ bool PulsePlayback::reset() flags &= ~PA_STREAM_EARLY_REQUESTS; flags |= PA_STREAM_ADJUST_LATENCY; } - if(GetConfigValueBool(mDevice->DeviceName.c_str(), "pulse", "fix-rate", false) + if(GetConfigValueBool(mDevice->mDeviceName, "pulse", "fix-rate", false) || !mDevice->Flags.test(FrequencyRequest)) flags |= PA_STREAM_FIX_RATE; @@ -907,6 +969,9 @@ bool PulsePlayback::reset() case DevFmtX3D71: chanmap = X71ChanMap; break; + case DevFmtX7144: + mDevice->FmtChans = DevFmtX714; + /*fall-through*/ case DevFmtX714: chanmap = X714ChanMap; break; @@ -937,59 +1002,62 @@ bool PulsePlayback::reset() mSpec.format = PA_SAMPLE_FLOAT32NE; break; } - mSpec.rate = mDevice->Frequency; + mSpec.rate = mDevice->mSampleRate; mSpec.channels = static_cast(mDevice->channelsFromFmt()); if(pa_sample_spec_valid(&mSpec) == 0) throw al::backend_exception{al::backend_error::DeviceError, "Invalid sample spec"}; const auto frame_size = static_cast(pa_frame_size(&mSpec)); mAttr.maxlength = ~0u; - mAttr.tlength = mDevice->BufferSize * frame_size; + mAttr.tlength = mDevice->mBufferSize * frame_size; mAttr.prebuf = 0u; - mAttr.minreq = mDevice->UpdateSize * frame_size; + mAttr.minreq = mDevice->mUpdateSize * frame_size; mAttr.fragsize = ~0u; mStream = plock.connectStream(deviceName, flags, &mAttr, &mSpec, &chanmap, BackendType::Playback); - pa_stream_set_state_callback(mStream, [](pa_stream *stream, void *pdata) noexcept - { return static_cast(pdata)->streamStateCallback(stream); }, this); - pa_stream_set_moved_callback(mStream, [](pa_stream *stream, void *pdata) noexcept - { return static_cast(pdata)->streamMovedCallback(stream); }, this); + constexpr auto state_callback = [](pa_stream *stream, void *pdata) noexcept + { return static_cast(pdata)->streamStateCallback(stream); }; + pa_stream_set_state_callback(mStream, state_callback, this); + + constexpr auto move_callback = [](pa_stream *stream, void *pdata) noexcept + { return static_cast(pdata)->streamMovedCallback(stream); }; + pa_stream_set_moved_callback(mStream, move_callback, this); mSpec = *(pa_stream_get_sample_spec(mStream)); mFrameSize = static_cast(pa_frame_size(&mSpec)); - if(mDevice->Frequency != mSpec.rate) + if(mDevice->mSampleRate != mSpec.rate) { /* Server updated our playback rate, so modify the buffer attribs * accordingly. */ - const auto scale = static_cast(mSpec.rate) / mDevice->Frequency; - const auto perlen = static_cast(clampd(scale*mDevice->UpdateSize + 0.5, 64.0, - 8192.0)); - const auto buflen = static_cast(clampd(scale*mDevice->BufferSize + 0.5, perlen*2, - std::numeric_limits::max()/mFrameSize)); + const auto scale = static_cast(mSpec.rate) / mDevice->mSampleRate; + const auto perlen = std::clamp(std::round(scale*mDevice->mUpdateSize), 64.0, 8192.0); + const auto bufmax = uint{std::numeric_limits::max()} / mFrameSize; + const auto buflen = std::clamp(std::round(scale*mDevice->mBufferSize), perlen*2.0, + static_cast(bufmax)); mAttr.maxlength = ~0u; - mAttr.tlength = buflen * mFrameSize; + mAttr.tlength = static_cast(buflen) * mFrameSize; mAttr.prebuf = 0u; - mAttr.minreq = perlen * mFrameSize; + mAttr.minreq = static_cast(perlen) * mFrameSize; op = pa_stream_set_buffer_attr(mStream, &mAttr, &PulseMainloop::streamSuccessCallbackC, &mMainloop); plock.waitForOperation(op); - mDevice->Frequency = mSpec.rate; + mDevice->mSampleRate = mSpec.rate; } - auto attr_callback = [](pa_stream *stream, void *pdata) noexcept + constexpr auto attr_callback = [](pa_stream *stream, void *pdata) noexcept { return static_cast(pdata)->bufferAttrCallback(stream); }; pa_stream_set_buffer_attr_callback(mStream, attr_callback, this); bufferAttrCallback(mStream); - mDevice->BufferSize = mAttr.tlength / mFrameSize; - mDevice->UpdateSize = mAttr.minreq / mFrameSize; + mDevice->mBufferSize = mAttr.tlength / mFrameSize; + mDevice->mUpdateSize = mAttr.minreq / mFrameSize; return true; } @@ -1008,8 +1076,9 @@ void PulsePlayback::start() pa_stream_write(mStream, buf, todo, pa_xfree, 0, PA_SEEK_RELATIVE); } - pa_stream_set_write_callback(mStream, [](pa_stream *stream, size_t nbytes, void *pdata)noexcept - { return static_cast(pdata)->streamWriteCallback(stream, nbytes); }, this); + constexpr auto stream_write = [](pa_stream *stream, size_t nbytes, void *pdata) noexcept + { return static_cast(pdata)->streamWriteCallback(stream, nbytes); }; + pa_stream_set_write_callback(mStream, stream_write, this); pa_operation *op{pa_stream_cork(mStream, 0, &PulseMainloop::streamSuccessCallbackC, &mMainloop)}; @@ -1029,13 +1098,13 @@ void PulsePlayback::stop() ClockLatency PulsePlayback::getClockLatency() { - ClockLatency ret; - pa_usec_t latency; - int neg, err; + ClockLatency ret{}; + pa_usec_t latency{}; + int neg{}, err{}; { MainloopUniqueLock plock{mMainloop}; - ret.ClockTime = GetDeviceClockTime(mDevice); + ret.ClockTime = mDevice->getClockTime(); err = pa_stream_get_latency(mStream, &latency, &neg); } @@ -1046,8 +1115,8 @@ ClockLatency PulsePlayback::getClockLatency() * server yet. Give a generic value since nothing better is available. */ if(err != -PA_ERR_NODATA) - ERR("Failed to get stream latency: 0x%x\n", err); - latency = mDevice->BufferSize - mDevice->UpdateSize; + ERR("Failed to get stream latency: {:#x}", as_unsigned(err)); + latency = mDevice->mBufferSize - mDevice->mUpdateSize; neg = 0; } else if(neg) UNLIKELY @@ -1059,7 +1128,7 @@ ClockLatency PulsePlayback::getClockLatency() struct PulseCapture final : public BackendBase { - PulseCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit PulseCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~PulseCapture() override; void streamStateCallback(pa_stream *stream) noexcept; @@ -1075,7 +1144,7 @@ struct PulseCapture final : public BackendBase { PulseMainloop mMainloop; - std::optional mDeviceName{std::nullopt}; + std::optional mDeviceId{std::nullopt}; al::span mCapBuffer; size_t mHoleLength{0}; @@ -1088,8 +1157,6 @@ struct PulseCapture final : public BackendBase { pa_sample_spec mSpec{}; pa_stream *mStream{nullptr}; - - DEF_NEWDEL(PulseCapture) }; PulseCapture::~PulseCapture() @@ -1100,7 +1167,7 @@ void PulseCapture::streamStateCallback(pa_stream *stream) noexcept { if(pa_stream_get_state(stream) == PA_STREAM_FAILED) { - ERR("Received stream failure!\n"); + ERR("Received stream failure!"); mDevice->handleDisconnect("Capture stream failure"); } mMainloop.signal(); @@ -1113,13 +1180,13 @@ void PulseCapture::sourceNameCallback(pa_context*, const pa_source_info *info, i mMainloop.signal(); return; } - mDevice->DeviceName = info->description; + mDeviceName = info->description; } void PulseCapture::streamMovedCallback(pa_stream *stream) noexcept { - mDeviceName = pa_stream_get_device_name(stream); - TRACE("Stream moved to %s\n", mDeviceName->c_str()); + mDeviceId = pa_stream_get_device_name(stream); + TRACE("Stream moved to {}", *mDeviceId); } @@ -1128,22 +1195,25 @@ void PulseCapture::open(std::string_view name) if(!mMainloop) { mMainloop = PulseMainloop::Create(); - mMainloop.start(); + if(mMainloop.start() != 0) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to start device mainloop"}; } - const char *pulse_name{nullptr}; + auto pulse_name = std::string{}; if(!name.empty()) { - if(CaptureDevices.empty()) - mMainloop.probeCaptureDevices(); + auto match_name = [name](const DevMap &entry) -> bool + { return entry.name == name || entry.device_name == name; }; - auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(), - [name](const DevMap &entry) -> bool { return entry.name == name; }); + auto plock = MainloopUniqueLock{gGlobalMainloop}; + auto iter = std::find_if(CaptureDevices.cbegin(), CaptureDevices.cend(), match_name); if(iter == CaptureDevices.cend()) throw al::backend_exception{al::backend_error::NoDevice, - "Device name \"%.*s\" not found", static_cast(name.length()), name.data()}; - pulse_name = iter->device_name.c_str(); - mDevice->DeviceName = iter->name; + "Device name \"{}\" not found", name}; + + pulse_name = iter->device_name; + mDeviceName = iter->name; } MainloopUniqueLock plock{mMainloop}; @@ -1152,30 +1222,17 @@ void PulseCapture::open(std::string_view name) pa_channel_map chanmap{}; switch(mDevice->FmtChans) { - case DevFmtMono: - chanmap = MonoChanMap; - break; - case DevFmtStereo: - chanmap = StereoChanMap; - break; - case DevFmtQuad: - chanmap = QuadChanMap; - break; - case DevFmtX51: - chanmap = X51ChanMap; - break; - case DevFmtX61: - chanmap = X61ChanMap; - break; - case DevFmtX71: - chanmap = X71ChanMap; - break; - case DevFmtX714: - chanmap = X714ChanMap; - break; + case DevFmtMono: chanmap = MonoChanMap; break; + case DevFmtStereo: chanmap = StereoChanMap; break; + case DevFmtQuad: chanmap = QuadChanMap; break; + case DevFmtX51: chanmap = X51ChanMap; break; + case DevFmtX61: chanmap = X61ChanMap; break; + case DevFmtX71: chanmap = X71ChanMap; break; + case DevFmtX714: chanmap = X714ChanMap; break; + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: - throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} capture not supported", DevFmtChannelsString(mDevice->FmtChans)}; } setDefaultWFXChannelOrder(); @@ -1199,39 +1256,44 @@ void PulseCapture::open(std::string_view name) case DevFmtUShort: case DevFmtUInt: throw al::backend_exception{al::backend_error::DeviceError, - "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; + "{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; } - mSpec.rate = mDevice->Frequency; + mSpec.rate = mDevice->mSampleRate; mSpec.channels = static_cast(mDevice->channelsFromFmt()); if(pa_sample_spec_valid(&mSpec) == 0) throw al::backend_exception{al::backend_error::DeviceError, "Invalid sample format"}; const auto frame_size = static_cast(pa_frame_size(&mSpec)); - const uint samples{maxu(mDevice->BufferSize, 100 * mDevice->Frequency / 1000)}; + const uint samples{std::max(mDevice->mBufferSize, mDevice->mSampleRate*100u/1000u)}; mAttr.minreq = ~0u; mAttr.prebuf = ~0u; mAttr.maxlength = samples * frame_size; mAttr.tlength = ~0u; - mAttr.fragsize = minu(samples, 50*mDevice->Frequency/1000) * frame_size; + mAttr.fragsize = std::min(samples, mDevice->mSampleRate*50u/1000u) * frame_size; pa_stream_flags_t flags{PA_STREAM_START_CORKED | PA_STREAM_ADJUST_LATENCY}; - if(!GetConfigValueBool(nullptr, "pulse", "allow-moves", true)) + if(!GetConfigValueBool({}, "pulse", "allow-moves", true)) flags |= PA_STREAM_DONT_MOVE; - TRACE("Connecting to \"%s\"\n", pulse_name ? pulse_name : "(default)"); + TRACE("Connecting to \"{}\"", pulse_name.empty() ? "(default)"sv:std::string_view{pulse_name}); mStream = plock.connectStream(pulse_name, flags, &mAttr, &mSpec, &chanmap, BackendType::Capture); - pa_stream_set_moved_callback(mStream, [](pa_stream *stream, void *pdata) noexcept - { return static_cast(pdata)->streamMovedCallback(stream); }, this); - pa_stream_set_state_callback(mStream, [](pa_stream *stream, void *pdata) noexcept - { return static_cast(pdata)->streamStateCallback(stream); }, this); + constexpr auto move_callback = [](pa_stream *stream, void *pdata) noexcept + { return static_cast(pdata)->streamMovedCallback(stream); }; + pa_stream_set_moved_callback(mStream, move_callback, this); - if(pulse_name) mDeviceName.emplace(pulse_name); - else mDeviceName.reset(); - if(mDevice->DeviceName.empty()) + constexpr auto state_callback = [](pa_stream *stream, void *pdata) noexcept + { return static_cast(pdata)->streamStateCallback(stream); }; + pa_stream_set_state_callback(mStream, state_callback, this); + + if(!pulse_name.empty()) + mDeviceId.emplace(std::move(pulse_name)); + + if(mDeviceName.empty()) { - auto name_callback = [](pa_context *context, const pa_source_info *info, int eol, void *pdata) noexcept + constexpr auto name_callback = [](pa_context *context, const pa_source_info *info, int eol, + void *pdata) noexcept { return static_cast(pdata)->sourceNameCallback(context, info, eol); }; pa_operation *op{pa_context_get_source_info_by_name(mMainloop.getContext(), pa_stream_get_device_name(mStream), name_callback, this)}; @@ -1267,7 +1329,7 @@ void PulseCapture::captureSamples(std::byte *buffer, uint samples) { if(mHoleLength > 0) UNLIKELY { - const size_t rem{minz(dstbuf.size(), mHoleLength)}; + const size_t rem{std::min(dstbuf.size(), mHoleLength)}; std::fill_n(dstbuf.begin(), rem, mSilentVal); dstbuf = dstbuf.subspan(rem); mHoleLength -= rem; @@ -1276,7 +1338,7 @@ void PulseCapture::captureSamples(std::byte *buffer, uint samples) } if(!mCapBuffer.empty()) { - const size_t rem{minz(dstbuf.size(), mCapBuffer.size())}; + const size_t rem{std::min(dstbuf.size(), mCapBuffer.size())}; std::copy_n(mCapBuffer.begin(), rem, dstbuf.begin()); dstbuf = dstbuf.subspan(rem); mCapBuffer = mCapBuffer.subspan(rem); @@ -1297,15 +1359,15 @@ void PulseCapture::captureSamples(std::byte *buffer, uint samples) const pa_stream_state_t state{pa_stream_get_state(mStream)}; if(!PA_STREAM_IS_GOOD(state)) UNLIKELY { - mDevice->handleDisconnect("Bad capture state: %u", state); + mDevice->handleDisconnect("Bad capture state: {}", al::to_underlying(state)); break; } - const void *capbuf; - size_t caplen; + const void *capbuf{}; + size_t caplen{}; if(pa_stream_peek(mStream, &capbuf, &caplen) < 0) UNLIKELY { - mDevice->handleDisconnect("Failed retrieving capture samples: %s", + mDevice->handleDisconnect("Failed retrieving capture samples: {}", pa_strerror(pa_context_errno(mMainloop.getContext()))); break; } @@ -1324,7 +1386,7 @@ void PulseCapture::captureSamples(std::byte *buffer, uint samples) uint PulseCapture::availableSamples() { - size_t readable{maxz(mCapBuffer.size(), mHoleLength)}; + size_t readable{std::max(mCapBuffer.size(), mHoleLength)}; if(mDevice->Connected.load(std::memory_order_acquire)) { @@ -1333,8 +1395,8 @@ uint PulseCapture::availableSamples() if(static_cast(got) < 0) UNLIKELY { const char *err{pa_strerror(static_cast(got))}; - ERR("pa_stream_readable_size() failed: %s\n", err); - mDevice->handleDisconnect("Failed getting readable size: %s", err); + ERR("pa_stream_readable_size() failed: {}", err); + mDevice->handleDisconnect("Failed getting readable size: {}", err); } else { @@ -1357,19 +1419,19 @@ uint PulseCapture::availableSamples() ClockLatency PulseCapture::getClockLatency() { - ClockLatency ret; - pa_usec_t latency; - int neg, err; + ClockLatency ret{}; + pa_usec_t latency{}; + int neg{}, err{}; { MainloopUniqueLock plock{mMainloop}; - ret.ClockTime = GetDeviceClockTime(mDevice); + ret.ClockTime = mDevice->getClockTime(); err = pa_stream_get_latency(mStream, &latency, &neg); } if(err != 0) UNLIKELY { - ERR("Failed to get stream latency: 0x%x\n", err); + ERR("Failed to get stream latency: {:#x}", as_unsigned(err)); latency = 0; neg = 0; } @@ -1385,12 +1447,9 @@ ClockLatency PulseCapture::getClockLatency() bool PulseBackendFactory::init() { -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD if(!pulse_handle) { - bool ret{true}; - std::string missing_funcs; - #ifdef _WIN32 #define PALIB "libpulse-0.dll" #elif defined(__APPLE__) && defined(__MACH__) @@ -1401,39 +1460,41 @@ bool PulseBackendFactory::init() pulse_handle = LoadLib(PALIB); if(!pulse_handle) { - WARN("Failed to load %s\n", PALIB); + WARN("Failed to load {}", PALIB); return false; } + std::string missing_funcs; #define LOAD_FUNC(x) do { \ - p##x = al::bit_cast(GetSymbol(pulse_handle, #x)); \ - if(!(p##x)) { \ - ret = false; \ - missing_funcs += "\n" #x; \ - } \ + p##x = reinterpret_cast(GetSymbol(pulse_handle, #x)); \ + if(!(p##x)) missing_funcs += "\n" #x; \ } while(0) PULSE_FUNCS(LOAD_FUNC) #undef LOAD_FUNC - if(!ret) + if(!missing_funcs.empty()) { - WARN("Missing expected functions:%s\n", missing_funcs.c_str()); + WARN("Missing expected functions:{}", missing_funcs); CloseLib(pulse_handle); pulse_handle = nullptr; return false; } } -#endif /* HAVE_DYNLOAD */ +#endif pulse_ctx_flags = PA_CONTEXT_NOFLAGS; - if(!GetConfigValueBool(nullptr, "pulse", "spawn-server", false)) + if(!GetConfigValueBool({}, "pulse", "spawn-server", false)) pulse_ctx_flags |= PA_CONTEXT_NOAUTOSPAWN; try { if(!gGlobalMainloop) { gGlobalMainloop = PulseMainloop::Create(); - gGlobalMainloop.start(); + if(gGlobalMainloop.start() != 0) + { + gGlobalMainloop = nullptr; + return false; + } } MainloopUniqueLock plock{gGlobalMainloop}; @@ -1449,28 +1510,36 @@ bool PulseBackendFactory::init() bool PulseBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string PulseBackendFactory::probe(BackendType type) +auto PulseBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; - auto add_device = [&outnames](const DevMap &entry) -> void + auto add_playback_device = [&outnames](const DevMap &entry) -> void { - /* +1 to also append the null char (to ensure a null-separated list and - * double-null terminated list). - */ - outnames.append(entry.name.c_str(), entry.name.length()+1); + if(entry.device_name == DefaultPlaybackDevName) + outnames.emplace(outnames.cbegin(), entry.name); + else + outnames.push_back(entry.name); + }; + auto add_capture_device = [&outnames](const DevMap &entry) -> void + { + if(entry.device_name == DefaultCaptureDevName) + outnames.emplace(outnames.cbegin(), entry.name); + else + outnames.push_back(entry.name); }; + auto plock = MainloopUniqueLock{gGlobalMainloop}; switch(type) { case BackendType::Playback: - gGlobalMainloop.probePlaybackDevices(); - std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device); + outnames.reserve(PlaybackDevices.size()); + std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_playback_device); break; case BackendType::Capture: - gGlobalMainloop.probeCaptureDevices(); - std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); + outnames.reserve(CaptureDevices.size()); + std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_capture_device); break; } @@ -1491,3 +1560,18 @@ BackendFactory &PulseBackendFactory::getFactory() static PulseBackendFactory factory{}; return factory; } + +alc::EventSupport PulseBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) +{ + switch(eventType) + { + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: + case alc::EventType::DefaultDeviceChanged: + return alc::EventSupport::FullSupport; + + case alc::EventType::Count: + break; + } + return alc::EventSupport::NoSupport; +} diff --git a/3rdparty/openal/alc/backends/pulseaudio.h b/3rdparty/openal/alc/backends/pulseaudio.h index 6690fe8a9f6d..c183d4794e28 100644 --- a/3rdparty/openal/alc/backends/pulseaudio.h +++ b/3rdparty/openal/alc/backends/pulseaudio.h @@ -1,19 +1,27 @@ #ifndef BACKENDS_PULSEAUDIO_H #define BACKENDS_PULSEAUDIO_H +#include +#include + +#include "alc/events.h" #include "base.h" +struct DeviceBase; + class PulseBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; + + auto querySupport(BackendType type) -> bool final; - bool querySupport(BackendType type) override; + auto queryEventSupport(alc::EventType eventType, BackendType type) -> alc::EventSupport final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_PULSEAUDIO_H */ diff --git a/3rdparty/openal/alc/backends/sdl2.cpp b/3rdparty/openal/alc/backends/sdl2.cpp index f5ed4316a87e..a0e41f4a0e24 100644 --- a/3rdparty/openal/alc/backends/sdl2.cpp +++ b/3rdparty/openal/alc/backends/sdl2.cpp @@ -26,11 +26,10 @@ #include #include #include +#include -#include "almalloc.h" #include "alnumeric.h" #include "core/device.h" -#include "core/logging.h" _Pragma("GCC diagnostic push") _Pragma("GCC diagnostic ignored \"-Wold-style-cast\"") @@ -40,16 +39,13 @@ _Pragma("GCC diagnostic pop") namespace { -#ifdef _WIN32 -#define DEVNAME_PREFIX "OpenAL Soft on " -#else -#define DEVNAME_PREFIX "" -#endif +using namespace std::string_view_literals; -constexpr char defaultDeviceName[] = DEVNAME_PREFIX "Default Device"; +[[nodiscard]] constexpr auto getDefaultDeviceName() noexcept -> std::string_view +{ return "Default Device"sv; } struct Sdl2Backend final : public BackendBase { - Sdl2Backend(DeviceBase *device) noexcept : BackendBase{device} { } + explicit Sdl2Backend(DeviceBase *device) noexcept : BackendBase{device} { } ~Sdl2Backend() override; void audioCallback(Uint8 *stream, int len) noexcept; @@ -59,15 +55,9 @@ struct Sdl2Backend final : public BackendBase { void start() override; void stop() override; + std::string mSDLName; SDL_AudioDeviceID mDeviceID{0u}; uint mFrameSize{0}; - - uint mFrequency{0u}; - DevFmtChannels mFmtChans{}; - DevFmtType mFmtType{}; - uint mUpdateSize{0u}; - - DEF_NEWDEL(Sdl2Backend) }; Sdl2Backend::~Sdl2Backend() @@ -88,7 +78,7 @@ void Sdl2Backend::open(std::string_view name) { SDL_AudioSpec want{}, have{}; - want.freq = static_cast(mDevice->Frequency); + want.freq = static_cast(mDevice->mSampleRate); switch(mDevice->FmtType) { case DevFmtUByte: want.format = AUDIO_U8; break; @@ -99,8 +89,9 @@ void Sdl2Backend::open(std::string_view name) case DevFmtInt: want.format = AUDIO_S32SYS; break; case DevFmtFloat: want.format = AUDIO_F32; break; } - want.channels = (mDevice->FmtChans == DevFmtMono) ? 1 : 2; - want.samples = static_cast(minu(mDevice->UpdateSize, 8192)); + want.channels = static_cast(std::min(mDevice->channelsFromFmt(), + std::numeric_limits::max())); + want.samples = static_cast(std::min(mDevice->mUpdateSize, 8192u)); want.callback = [](void *ptr, Uint8 *stream, int len) noexcept { return static_cast(ptr)->audioCallback(stream, len); }; want.userdata = this; @@ -108,45 +99,22 @@ void Sdl2Backend::open(std::string_view name) /* Passing nullptr to SDL_OpenAudioDevice opens a default, which isn't * necessarily the first in the list. */ - SDL_AudioDeviceID devid; + const auto defaultDeviceName = getDefaultDeviceName(); if(name.empty() || name == defaultDeviceName) { name = defaultDeviceName; - devid = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &want, &have, SDL_AUDIO_ALLOW_ANY_CHANGE); + mSDLName.clear(); + mDeviceID = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); } else { - const size_t prefix_len = strlen(DEVNAME_PREFIX); - if(name.length() >= prefix_len && strncmp(name.data(), DEVNAME_PREFIX, prefix_len) == 0) - { - /* Copy the string_view to a string to ensure it's null terminated - * for this call. - */ - const std::string devname{name.substr(prefix_len)}; - devid = SDL_OpenAudioDevice(devname.c_str(), SDL_FALSE, &want, &have, - SDL_AUDIO_ALLOW_ANY_CHANGE); - } - else - { - const std::string devname{name}; - devid = SDL_OpenAudioDevice(devname.c_str(), SDL_FALSE, &want, &have, - SDL_AUDIO_ALLOW_ANY_CHANGE); - } - } - if(!devid) - throw al::backend_exception{al::backend_error::NoDevice, "%s", SDL_GetError()}; - - DevFmtChannels devchans{}; - if(have.channels >= 2) - devchans = DevFmtStereo; - else if(have.channels == 1) - devchans = DevFmtMono; - else - { - SDL_CloseAudioDevice(devid); - throw al::backend_exception{al::backend_error::DeviceError, - "Unhandled SDL channel count: %d", int{have.channels}}; + mSDLName = name; + mDeviceID = SDL_OpenAudioDevice(mSDLName.c_str(), SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); } + if(!mDeviceID) + throw al::backend_exception{al::backend_error::NoDevice, "{}", SDL_GetError()}; DevFmtType devtype{}; switch(have.format) @@ -158,32 +126,100 @@ void Sdl2Backend::open(std::string_view name) case AUDIO_S32SYS: devtype = DevFmtInt; break; case AUDIO_F32SYS: devtype = DevFmtFloat; break; default: - SDL_CloseAudioDevice(devid); - throw al::backend_exception{al::backend_error::DeviceError, "Unhandled SDL format: 0x%04x", - have.format}; + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL format: {:#04x}", have.format}; } - if(mDeviceID) - SDL_CloseAudioDevice(mDeviceID); - mDeviceID = devid; - mFrameSize = BytesFromDevFmt(devtype) * have.channels; - mFrequency = static_cast(have.freq); - mFmtChans = devchans; - mFmtType = devtype; - mUpdateSize = have.samples; - mDevice->DeviceName = name; + mDeviceName = name; } bool Sdl2Backend::reset() { - mDevice->Frequency = mFrequency; - mDevice->FmtChans = mFmtChans; - mDevice->FmtType = mFmtType; - mDevice->UpdateSize = mUpdateSize; - mDevice->BufferSize = mUpdateSize * 2; /* SDL always (tries to) use two periods. */ + if(mDeviceID) + SDL_CloseAudioDevice(mDeviceID); + mDeviceID = 0; + + auto want = SDL_AudioSpec{}; + want.freq = static_cast(mDevice->mSampleRate); + switch(mDevice->FmtType) + { + case DevFmtUByte: want.format = AUDIO_U8; break; + case DevFmtByte: want.format = AUDIO_S8; break; + case DevFmtUShort: want.format = AUDIO_U16SYS; break; + case DevFmtShort: want.format = AUDIO_S16SYS; break; + case DevFmtUInt: [[fallthrough]]; + case DevFmtInt: want.format = AUDIO_S32SYS; break; + case DevFmtFloat: want.format = AUDIO_F32; break; + } + want.channels = static_cast(std::min(mDevice->channelsFromFmt(), + std::numeric_limits::max())); + want.samples = static_cast(std::min(mDevice->mUpdateSize, 8192u)); + want.callback = [](void *ptr, Uint8 *stream, int len) noexcept + { return static_cast(ptr)->audioCallback(stream, len); }; + want.userdata = this; + + auto have = SDL_AudioSpec{}; + if(mSDLName.empty()) + { + mDeviceID = SDL_OpenAudioDevice(nullptr, SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + } + else + { + mDeviceID = SDL_OpenAudioDevice(mSDLName.c_str(), SDL_FALSE, &want, &have, + SDL_AUDIO_ALLOW_ANY_CHANGE); + } + if(!mDeviceID) + throw al::backend_exception{al::backend_error::NoDevice, "{}", SDL_GetError()}; + + if(have.channels != mDevice->channelsFromFmt()) + { + /* SDL guarantees these layouts for the given channel count. */ + if(have.channels == 8) + mDevice->FmtChans = DevFmtX71; + else if(have.channels == 7) + mDevice->FmtChans = DevFmtX61; + else if(have.channels == 6) + mDevice->FmtChans = DevFmtX51; + else if(have.channels == 4) + mDevice->FmtChans = DevFmtQuad; + else if(have.channels >= 2) + mDevice->FmtChans = DevFmtStereo; + else if(have.channels == 1) + mDevice->FmtChans = DevFmtMono; + else + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL channel count: {}", int{have.channels}}; + mDevice->mAmbiOrder = 0; + } + + switch(have.format) + { + case AUDIO_U8: mDevice->FmtType = DevFmtUByte; break; + case AUDIO_S8: mDevice->FmtType = DevFmtByte; break; + case AUDIO_U16SYS: mDevice->FmtType = DevFmtUShort; break; + case AUDIO_S16SYS: mDevice->FmtType = DevFmtShort; break; + case AUDIO_S32SYS: mDevice->FmtType = DevFmtInt; break; + case AUDIO_F32SYS: mDevice->FmtType = DevFmtFloat; break; + default: + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL format: {:#04x}", have.format}; + } + + mFrameSize = BytesFromDevFmt(mDevice->FmtType) * have.channels; + + if(have.freq < int{MinOutputRate}) + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL sample rate: {}", have.freq}; + + mDevice->mSampleRate = static_cast(have.freq); + mDevice->mUpdateSize = have.samples; + mDevice->mBufferSize = std::max(have.size/mFrameSize, mDevice->mUpdateSize*2u); + setDefaultWFXChannelOrder(); + return true; } @@ -207,23 +243,25 @@ bool SDL2BackendFactory::init() bool SDL2BackendFactory::querySupport(BackendType type) { return type == BackendType::Playback; } -std::string SDL2BackendFactory::probe(BackendType type) +auto SDL2BackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; if(type != BackendType::Playback) return outnames; int num_devices{SDL_GetNumAudioDevices(SDL_FALSE)}; + if(num_devices <= 0) + return outnames; - /* Includes null char. */ - outnames.append(defaultDeviceName, sizeof(defaultDeviceName)); + outnames.reserve(static_cast(num_devices)+1_uz); + outnames.emplace_back(getDefaultDeviceName()); for(int i{0};i < num_devices;++i) { - std::string name{DEVNAME_PREFIX}; - name += SDL_GetAudioDeviceName(i, SDL_FALSE); - if(!name.empty()) - outnames.append(name.c_str(), name.length()+1); + if(const char *name = SDL_GetAudioDeviceName(i, SDL_FALSE)) + outnames.emplace_back(name); + else + outnames.emplace_back("Unknown Device Name #"+std::to_string(i)); } return outnames; } diff --git a/3rdparty/openal/alc/backends/sdl2.h b/3rdparty/openal/alc/backends/sdl2.h index 3bd8df8633e3..8c5829121607 100644 --- a/3rdparty/openal/alc/backends/sdl2.h +++ b/3rdparty/openal/alc/backends/sdl2.h @@ -5,15 +5,15 @@ struct SDL2BackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_SDL2_H */ diff --git a/3rdparty/openal/alc/backends/sdl3.cpp b/3rdparty/openal/alc/backends/sdl3.cpp new file mode 100644 index 000000000000..b10ad591e0da --- /dev/null +++ b/3rdparty/openal/alc/backends/sdl3.cpp @@ -0,0 +1,393 @@ +/** + * OpenAL cross platform audio library + * Copyright (C) 2024 by authors. + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * Or go to http://www.gnu.org/copyleft/lgpl.html + */ + +#include "config.h" + +#include "sdl3.h" + +#include +#include +#include +#include +#include +#include + +#include "almalloc.h" +#include "core/device.h" +#include "core/logging.h" + +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wold-style-cast\"") +#include "SDL3/SDL_audio.h" +#include "SDL3/SDL_init.h" +#include "SDL3/SDL_stdinc.h" +_Pragma("GCC diagnostic pop") + + +namespace { + +using namespace std::string_view_literals; + +_Pragma("GCC diagnostic push") +_Pragma("GCC diagnostic ignored \"-Wold-style-cast\"") +constexpr auto DefaultPlaybackDeviceID = SDL_AUDIO_DEVICE_DEFAULT_PLAYBACK; +_Pragma("GCC diagnostic pop") + + +template +struct SdlDeleter { + /* NOLINTNEXTLINE(cppcoreguidelines-no-malloc) */ + void operator()(gsl::owner ptr) const { SDL_free(ptr); } +}; +template +using unique_sdl_ptr = std::unique_ptr>; + + +struct DeviceEntry { + std::string mName; + SDL_AudioDeviceID mPhysDeviceID{}; +}; + +std::vector gPlaybackDevices; + +void EnumeratePlaybackDevices() +{ + auto numdevs = int{}; + auto devicelist = unique_sdl_ptr{SDL_GetAudioPlaybackDevices(&numdevs)}; + if(!devicelist || numdevs < 0) + { + ERR("Failed to get playback devices: {}", SDL_GetError()); + return; + } + + auto devids = al::span{devicelist.get(), static_cast(numdevs)}; + auto newlist = std::vector{}; + + newlist.reserve(devids.size()); + std::transform(devids.begin(), devids.end(), std::back_inserter(newlist), + [](SDL_AudioDeviceID id) + { + auto *name = SDL_GetAudioDeviceName(id); + if(!name) return DeviceEntry{}; + TRACE("Got device \"{}\", ID {}", name, id); + return DeviceEntry{name, id}; + }); + + gPlaybackDevices.swap(newlist); +} + +[[nodiscard]] constexpr auto getDefaultDeviceName() noexcept -> std::string_view +{ return "Default Device"sv; } + + +struct Sdl3Backend final : public BackendBase { + explicit Sdl3Backend(DeviceBase *device) noexcept : BackendBase{device} { } + ~Sdl3Backend() final; + + void audioCallback(SDL_AudioStream *stream, int additional_amount, int total_amount) noexcept; + + void open(std::string_view name) final; + auto reset() -> bool final; + void start() final; + void stop() final; + + SDL_AudioDeviceID mDeviceID{0}; + SDL_AudioStream *mStream{nullptr}; + uint mNumChannels{0}; + uint mFrameSize{0}; + std::vector mBuffer; +}; + +Sdl3Backend::~Sdl3Backend() +{ + if(mStream) + SDL_DestroyAudioStream(mStream); + mStream = nullptr; +} + +void Sdl3Backend::audioCallback(SDL_AudioStream *stream, int additional_amount, int total_amount) + noexcept +{ + if(additional_amount < 0) + additional_amount = total_amount; + if(additional_amount <= 0) + return; + + const auto ulen = static_cast(additional_amount); + assert((ulen % mFrameSize) == 0); + + if(ulen > mBuffer.size()) + { + mBuffer.resize(ulen); + std::fill(mBuffer.begin(), mBuffer.end(), (mDevice->FmtType == DevFmtUByte) + ? std::byte{0x80} : std::byte{}); + } + + mDevice->renderSamples(mBuffer.data(), ulen / mFrameSize, mNumChannels); + SDL_PutAudioStreamData(stream, mBuffer.data(), additional_amount); +} + +void Sdl3Backend::open(std::string_view name) +{ + const auto defaultDeviceName = getDefaultDeviceName(); + if(name.empty() || name == defaultDeviceName) + { + name = defaultDeviceName; + mDeviceID = DefaultPlaybackDeviceID; + } + else + { + if(gPlaybackDevices.empty()) + EnumeratePlaybackDevices(); + + const auto iter = std::find_if(gPlaybackDevices.cbegin(), gPlaybackDevices.cend(), + [name](const DeviceEntry &entry) { return name == entry.mName; }); + if(iter == gPlaybackDevices.cend()) + throw al::backend_exception{al::backend_error::NoDevice, "No device named {}", name}; + + mDeviceID = iter->mPhysDeviceID; + } + + mStream = SDL_OpenAudioDeviceStream(mDeviceID, nullptr, nullptr, nullptr); + if(!mStream) + throw al::backend_exception{al::backend_error::NoDevice, "{}", SDL_GetError()}; + + auto have = SDL_AudioSpec{}; + auto update_size = int{}; + if(SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(mStream), &have, &update_size)) + { + auto devtype = mDevice->FmtType; + switch(have.format) + { + case SDL_AUDIO_U8: devtype = DevFmtUByte; break; + case SDL_AUDIO_S8: devtype = DevFmtByte; break; + case SDL_AUDIO_S16: devtype = DevFmtShort; break; + case SDL_AUDIO_S32: devtype = DevFmtInt; break; + case SDL_AUDIO_F32: devtype = DevFmtFloat; break; + default: break; + } + mDevice->FmtType = devtype; + + if(have.freq >= int{MinOutputRate} && have.freq <= int{MaxOutputRate}) + mDevice->mSampleRate = static_cast(have.freq); + + /* SDL guarantees these layouts for the given channel count. */ + if(have.channels == 8) + mDevice->FmtChans = DevFmtX71; + else if(have.channels == 7) + mDevice->FmtChans = DevFmtX61; + else if(have.channels == 6) + mDevice->FmtChans = DevFmtX51; + else if(have.channels == 4) + mDevice->FmtChans = DevFmtQuad; + else if(have.channels >= 2) + mDevice->FmtChans = DevFmtStereo; + else if(have.channels == 1) + mDevice->FmtChans = DevFmtMono; + mDevice->mAmbiOrder = 0; + + mNumChannels = static_cast(have.channels); + mFrameSize = mDevice->bytesFromFmt() * mNumChannels; + + if(update_size >= 64) + { + /* We have to assume the total buffer size is just twice the update + * size. SDL doesn't tell us the full end-to-end buffer latency. + */ + mDevice->mUpdateSize = static_cast(update_size); + mDevice->mBufferSize = mDevice->mUpdateSize*2u; + } + else + ERR("Invalid update size from SDL stream: {}", update_size); + } + else + ERR("Failed to get format from SDL stream: {}", SDL_GetError()); + + mDeviceName = name; +} + +auto Sdl3Backend::reset() -> bool +{ + static constexpr auto callback = [](void *ptr, SDL_AudioStream *stream, int additional_amount, + int total_amount) noexcept + { + return static_cast(ptr)->audioCallback(stream, additional_amount, + total_amount); + }; + + if(mStream) + SDL_DestroyAudioStream(mStream); + mStream = nullptr; + + mBuffer.clear(); + mBuffer.shrink_to_fit(); + + auto want = SDL_AudioSpec{}; + if(!SDL_GetAudioDeviceFormat(mDeviceID, &want, nullptr)) + ERR("Failed to get device format: {}", SDL_GetError()); + + if(mDevice->Flags.test(FrequencyRequest) || want.freq < int{MinOutputRate}) + want.freq = static_cast(mDevice->mSampleRate); + if(mDevice->Flags.test(SampleTypeRequest) + || !(want.format == SDL_AUDIO_U8 || want.format == SDL_AUDIO_S8 + || want.format == SDL_AUDIO_S16 || want.format == SDL_AUDIO_S32 + || want.format == SDL_AUDIO_F32)) + { + switch(mDevice->FmtType) + { + case DevFmtUByte: want.format = SDL_AUDIO_U8; break; + case DevFmtByte: want.format = SDL_AUDIO_S8; break; + case DevFmtUShort: [[fallthrough]]; + case DevFmtShort: want.format = SDL_AUDIO_S16; break; + case DevFmtUInt: [[fallthrough]]; + case DevFmtInt: want.format = SDL_AUDIO_S32; break; + case DevFmtFloat: want.format = SDL_AUDIO_F32; break; + } + } + if(mDevice->Flags.test(ChannelsRequest) || want.channels < 1) + want.channels = static_cast(std::min(mDevice->channelsFromFmt(), + std::numeric_limits::max())); + + mStream = SDL_OpenAudioDeviceStream(mDeviceID, &want, callback, this); + if(!mStream) + { + /* If creating the stream failed, try again without a specific format. */ + mStream = SDL_OpenAudioDeviceStream(mDeviceID, nullptr, callback, this); + if(!mStream) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to recreate stream: {}", SDL_GetError()}; + } + + auto update_size = int{}; + auto have = SDL_AudioSpec{}; + SDL_GetAudioDeviceFormat(SDL_GetAudioStreamDevice(mStream), &have, &update_size); + + have = SDL_AudioSpec{}; + if(!SDL_GetAudioStreamFormat(mStream, &have, nullptr)) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to get stream format: {}", SDL_GetError()}; + + if(!mDevice->Flags.test(ChannelsRequest) + || (static_cast(have.channels) != mDevice->channelsFromFmt() + && !(mDevice->FmtChans == DevFmtStereo && have.channels >= 2))) + { + /* SDL guarantees these layouts for the given channel count. */ + if(have.channels == 8) + mDevice->FmtChans = DevFmtX71; + else if(have.channels == 7) + mDevice->FmtChans = DevFmtX61; + else if(have.channels == 6) + mDevice->FmtChans = DevFmtX51; + else if(have.channels == 4) + mDevice->FmtChans = DevFmtQuad; + else if(have.channels >= 2) + mDevice->FmtChans = DevFmtStereo; + else if(have.channels == 1) + mDevice->FmtChans = DevFmtMono; + else + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL channel count: {}", have.channels}; + mDevice->mAmbiOrder = 0; + } + mNumChannels = static_cast(have.channels); + + switch(have.format) + { + case SDL_AUDIO_U8: mDevice->FmtType = DevFmtUByte; break; + case SDL_AUDIO_S8: mDevice->FmtType = DevFmtByte; break; + case SDL_AUDIO_S16: mDevice->FmtType = DevFmtShort; break; + case SDL_AUDIO_S32: mDevice->FmtType = DevFmtInt; break; + case SDL_AUDIO_F32: mDevice->FmtType = DevFmtFloat; break; + default: + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL format: {:#04x}", al::to_underlying(have.format)}; + } + + mFrameSize = mDevice->bytesFromFmt() * mNumChannels; + + if(have.freq < int{MinOutputRate}) + throw al::backend_exception{al::backend_error::DeviceError, + "Unhandled SDL sample rate: {}", have.freq}; + mDevice->mSampleRate = static_cast(have.freq); + + if(update_size >= 64) + { + mDevice->mUpdateSize = static_cast(update_size); + mDevice->mBufferSize = mDevice->mUpdateSize*2u; + + mBuffer.resize(size_t{mDevice->mUpdateSize} * mFrameSize); + std::fill(mBuffer.begin(), mBuffer.end(), (mDevice->FmtType == DevFmtUByte) + ? std::byte{0x80} : std::byte{}); + } + else + ERR("Invalid update size from SDL stream: {}", update_size); + + setDefaultWFXChannelOrder(); + + return true; +} + +void Sdl3Backend::start() +{ SDL_ResumeAudioStreamDevice(mStream); } + +void Sdl3Backend::stop() +{ SDL_PauseAudioStreamDevice(mStream); } + +} // namespace + +auto SDL3BackendFactory::getFactory() -> BackendFactory& +{ + static SDL3BackendFactory factory{}; + return factory; +} + +auto SDL3BackendFactory::init() -> bool +{ + if(!SDL_InitSubSystem(SDL_INIT_AUDIO)) + return false; + TRACE("Current SDL3 audio driver: \"{}\"", SDL_GetCurrentAudioDriver()); + return true; +} + +auto SDL3BackendFactory::querySupport(BackendType type) -> bool +{ return type == BackendType::Playback; } + +auto SDL3BackendFactory::enumerate(BackendType type) -> std::vector +{ + auto outnames = std::vector{}; + + if(type != BackendType::Playback) + return outnames; + + EnumeratePlaybackDevices(); + outnames.reserve(gPlaybackDevices.size()+1); + outnames.emplace_back(getDefaultDeviceName()); + std::transform(gPlaybackDevices.begin(), gPlaybackDevices.end(), std::back_inserter(outnames), + std::mem_fn(&DeviceEntry::mName)); + + return outnames; +} + +auto SDL3BackendFactory::createBackend(DeviceBase *device, BackendType type) -> BackendPtr +{ + if(type == BackendType::Playback) + return BackendPtr{new Sdl3Backend{device}}; + return nullptr; +} diff --git a/3rdparty/openal/alc/backends/sdl3.h b/3rdparty/openal/alc/backends/sdl3.h new file mode 100644 index 000000000000..4d6730658509 --- /dev/null +++ b/3rdparty/openal/alc/backends/sdl3.h @@ -0,0 +1,19 @@ +#ifndef BACKENDS_SDL3_H +#define BACKENDS_SDL3_H + +#include "base.h" + +struct SDL3BackendFactory final : public BackendFactory { +public: + auto init() -> bool final; + + auto querySupport(BackendType type) -> bool final; + + auto enumerate(BackendType type) -> std::vector final; + + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; +}; + +#endif /* BACKENDS_SDL3_H */ diff --git a/3rdparty/openal/alc/backends/sndio.cpp b/3rdparty/openal/alc/backends/sndio.cpp index d54c337b2c89..187e1305781f 100644 --- a/3rdparty/openal/alc/backends/sndio.cpp +++ b/3rdparty/openal/alc/backends/sndio.cpp @@ -20,18 +20,16 @@ #include "config.h" -#include "sndio.h" +#include "sndio.hpp" -#include -#include +#include +#include +#include #include -#include -#include -#include +#include #include #include -#include "alnumeric.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" @@ -43,16 +41,18 @@ namespace { -static const char sndio_device[] = "SndIO Default"; +using namespace std::string_view_literals; + +[[nodiscard]] constexpr auto GetDefaultName() noexcept { return "SndIO Default"sv; } struct SioPar : public sio_par { - SioPar() { sio_initpar(this); } + SioPar() : sio_par{} { sio_initpar(this); } void clear() { sio_initpar(this); } }; struct SndioPlayback final : public BackendBase { - SndioPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit SndioPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~SndioPlayback() override; int mixerProc(); @@ -69,8 +69,6 @@ struct SndioPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(SndioPlayback) }; SndioPlayback::~SndioPlayback() @@ -86,7 +84,7 @@ int SndioPlayback::mixerProc() const size_t frameSize{frameStep * mDevice->bytesFromFmt()}; SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) @@ -100,7 +98,7 @@ int SndioPlayback::mixerProc() size_t wrote{sio_write(mSndHandle, buffer.data(), buffer.size())}; if(wrote > buffer.size() || wrote == 0) { - ERR("sio_write failed: 0x%" PRIx64 "\n", wrote); + ERR("sio_write failed: {:#x}", wrote); mDevice->handleDisconnect("Failed to write playback samples"); break; } @@ -115,10 +113,10 @@ int SndioPlayback::mixerProc() void SndioPlayback::open(std::string_view name) { if(name.empty()) - name = sndio_device; - else if(name != sndio_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDefaultName(); + else if(name != GetDefaultName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; sio_hdl *sndHandle{sio_open(nullptr, SIO_PLAY, 0)}; if(!sndHandle) @@ -128,7 +126,7 @@ void SndioPlayback::open(std::string_view name) sio_close(mSndHandle); mSndHandle = sndHandle; - mDevice->DeviceName = name; + mDeviceName = name; } bool SndioPlayback::reset() @@ -136,72 +134,75 @@ bool SndioPlayback::reset() SioPar par; auto tryfmt = mDevice->FmtType; -retry_params: - switch(tryfmt) + while(true) { - case DevFmtByte: - par.bits = 8; - par.sig = 1; - break; - case DevFmtUByte: - par.bits = 8; - par.sig = 0; - break; - case DevFmtShort: - par.bits = 16; - par.sig = 1; - break; - case DevFmtUShort: - par.bits = 16; - par.sig = 0; - break; - case DevFmtFloat: - case DevFmtInt: - par.bits = 32; - par.sig = 1; - break; - case DevFmtUInt: - par.bits = 32; - par.sig = 0; - break; - } - par.bps = SIO_BPS(par.bits); - par.le = SIO_LE_NATIVE; - par.msb = 1; - - par.rate = mDevice->Frequency; - par.pchan = mDevice->channelsFromFmt(); - - par.round = mDevice->UpdateSize; - par.appbufsz = mDevice->BufferSize - mDevice->UpdateSize; - if(!par.appbufsz) par.appbufsz = mDevice->UpdateSize; + switch(tryfmt) + { + case DevFmtByte: + par.bits = 8; + par.sig = 1; + break; + case DevFmtUByte: + par.bits = 8; + par.sig = 0; + break; + case DevFmtShort: + par.bits = 16; + par.sig = 1; + break; + case DevFmtUShort: + par.bits = 16; + par.sig = 0; + break; + case DevFmtFloat: + case DevFmtInt: + par.bits = 32; + par.sig = 1; + break; + case DevFmtUInt: + par.bits = 32; + par.sig = 0; + break; + } + par.bps = SIO_BPS(par.bits); + par.le = SIO_LE_NATIVE; + par.msb = 1; + + par.rate = mDevice->mSampleRate; + par.pchan = mDevice->channelsFromFmt(); + + par.round = mDevice->mUpdateSize; + par.appbufsz = mDevice->mBufferSize - mDevice->mUpdateSize; + if(!par.appbufsz) par.appbufsz = mDevice->mUpdateSize; + + try { + if(!sio_setpar(mSndHandle, &par)) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to set device parameters"}; + + par.clear(); + if(!sio_getpar(mSndHandle, &par)) + throw al::backend_exception{al::backend_error::DeviceError, + "Failed to get device parameters"}; + + if(par.bps > 1 && par.le != SIO_LE_NATIVE) + throw al::backend_exception{al::backend_error::DeviceError, + "{}-endian samples not supported", par.le ? "Little" : "Big"}; + if(par.bits < par.bps*8 && !par.msb) + throw al::backend_exception{al::backend_error::DeviceError, + "MSB-padded samples not supported ({} of {} bits)", par.bits, par.bps*8}; + if(par.pchan < 1) + throw al::backend_exception{al::backend_error::DeviceError, + "No playback channels on device"}; - try { - if(!sio_setpar(mSndHandle, &par)) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to set device parameters"}; - - par.clear(); - if(!sio_getpar(mSndHandle, &par)) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to get device parameters"}; - - if(par.bps > 1 && par.le != SIO_LE_NATIVE) - throw al::backend_exception{al::backend_error::DeviceError, - "%s-endian samples not supported", par.le ? "Little" : "Big"}; - if(par.bits < par.bps*8 && !par.msb) - throw al::backend_exception{al::backend_error::DeviceError, - "MSB-padded samples not supported (%u of %u bits)", par.bits, par.bps*8}; - if(par.pchan < 1) - throw al::backend_exception{al::backend_error::DeviceError, - "No playback channels on device"}; - } - catch(al::backend_exception &e) { - if(tryfmt == DevFmtShort) - throw; - par.clear(); - tryfmt = DevFmtShort; - goto retry_params; + break; + } + catch(al::backend_exception &e) { + if(tryfmt == DevFmtShort) + throw; + par.clear(); + tryfmt = DevFmtShort; + } } if(par.bps == 1) @@ -212,24 +213,24 @@ bool SndioPlayback::reset() mDevice->FmtType = (par.sig==1) ? DevFmtInt : DevFmtUInt; else throw al::backend_exception{al::backend_error::DeviceError, - "Unhandled sample format: %s %u-bit", (par.sig?"signed":"unsigned"), par.bps*8}; + "Unhandled sample format: {} {}-bit", (par.sig?"signed":"unsigned"), par.bps*8}; mFrameStep = par.pchan; if(par.pchan != mDevice->channelsFromFmt()) { - WARN("Got %u channel%s for %s\n", par.pchan, (par.pchan==1)?"":"s", + WARN("Got {} channel{} for {}", par.pchan, (par.pchan==1)?"":"s", DevFmtChannelsString(mDevice->FmtChans)); if(par.pchan < 2) mDevice->FmtChans = DevFmtMono; else mDevice->FmtChans = DevFmtStereo; } - mDevice->Frequency = par.rate; + mDevice->mSampleRate = par.rate; setDefaultChannelOrder(); - mDevice->UpdateSize = par.round; - mDevice->BufferSize = par.bufsz + par.round; + mDevice->mUpdateSize = par.round; + mDevice->mBufferSize = par.bufsz + par.round; - mBuffer.resize(mDevice->UpdateSize * par.pchan*par.bps); + mBuffer.resize(size_t{mDevice->mUpdateSize} * par.pchan*par.bps); if(par.sig == 1) std::fill(mBuffer.begin(), mBuffer.end(), std::byte{}); else if(par.bits == 8) @@ -249,12 +250,12 @@ void SndioPlayback::start() try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&SndioPlayback::mixerProc), this}; + mThread = std::thread{&SndioPlayback::mixerProc, this}; } catch(std::exception& e) { sio_stop(mSndHandle); throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -265,7 +266,7 @@ void SndioPlayback::stop() mThread.join(); if(!sio_stop(mSndHandle)) - ERR("Error stopping device\n"); + ERR("Error stopping device"); } @@ -275,7 +276,7 @@ void SndioPlayback::stop() * capture buffer sizes apps may request. */ struct SndioCapture final : public BackendBase { - SndioCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit SndioCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~SndioCapture() override; int recordProc(); @@ -292,8 +293,6 @@ struct SndioCapture final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(SndioCapture) }; SndioCapture::~SndioCapture() @@ -306,40 +305,40 @@ SndioCapture::~SndioCapture() int SndioCapture::recordProc() { SetRTPriority(); - althrd_setname(RECORD_THREAD_NAME); + althrd_setname(GetRecordThreadName()); const uint frameSize{mDevice->frameSizeFromFmt()}; int nfds_pre{sio_nfds(mSndHandle)}; if(nfds_pre <= 0) { - mDevice->handleDisconnect("Incorrect return value from sio_nfds(): %d", nfds_pre); + mDevice->handleDisconnect("Incorrect return value from sio_nfds(): {}", nfds_pre); return 1; } - auto fds = std::make_unique(static_cast(nfds_pre)); + auto fds = std::vector(static_cast(nfds_pre)); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) { /* Wait until there's some samples to read. */ - const int nfds{sio_pollfd(mSndHandle, fds.get(), POLLIN)}; + const int nfds{sio_pollfd(mSndHandle, fds.data(), POLLIN)}; if(nfds <= 0) { - mDevice->handleDisconnect("Failed to get polling fds: %d", nfds); + mDevice->handleDisconnect("Failed to get polling fds: {}", nfds); break; } - int pollres{::poll(fds.get(), static_cast(nfds), 2000)}; + int pollres{::poll(fds.data(), fds.size(), 2000)}; if(pollres < 0) { if(errno == EINTR) continue; - mDevice->handleDisconnect("Poll error: %s", strerror(errno)); + mDevice->handleDisconnect("Poll error: {}", std::generic_category().message(errno)); break; } if(pollres == 0) continue; - const int revents{sio_revents(mSndHandle, fds.get())}; + const int revents{sio_revents(mSndHandle, fds.data())}; if((revents&POLLHUP)) { mDevice->handleDisconnect("Got POLLHUP from poll events"); @@ -349,7 +348,7 @@ int SndioCapture::recordProc() continue; auto data = mRing->getWriteVector(); - al::span buffer{data.first.buf, data.first.len*frameSize}; + al::span buffer{data[0].buf, data[0].len*frameSize}; while(!buffer.empty()) { size_t got{sio_read(mSndHandle, buffer.data(), buffer.size())}; @@ -357,8 +356,8 @@ int SndioCapture::recordProc() break; if(got > buffer.size()) { - ERR("sio_read failed: 0x%" PRIx64 "\n", got); - mDevice->handleDisconnect("sio_read failed: 0x%" PRIx64, got); + ERR("sio_read failed: {:#x}", got); + mDevice->handleDisconnect("sio_read failed: {:#x}", got); break; } @@ -367,14 +366,14 @@ int SndioCapture::recordProc() if(buffer.empty()) { data = mRing->getWriteVector(); - buffer = {data.first.buf, data.first.len*frameSize}; + buffer = {data[0].buf, data[0].len*frameSize}; } } if(buffer.empty()) { /* Got samples to read, but no place to store it. Drop it. */ - static char junk[4096]; - sio_read(mSndHandle, junk, sizeof(junk) - (sizeof(junk)%frameSize)); + static std::array junk; + sio_read(mSndHandle, junk.data(), junk.size() - (junk.size()%frameSize)); } } @@ -385,10 +384,10 @@ int SndioCapture::recordProc() void SndioCapture::open(std::string_view name) { if(name.empty()) - name = sndio_device; - else if(name != sndio_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDefaultName(); + else if(name != GetDefaultName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; mSndHandle = sio_open(nullptr, SIO_REC, true); if(mSndHandle == nullptr) @@ -423,16 +422,16 @@ void SndioCapture::open(std::string_view name) break; case DevFmtFloat: throw al::backend_exception{al::backend_error::DeviceError, - "%s capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; + "{} capture samples not supported", DevFmtTypeString(mDevice->FmtType)}; } par.bps = SIO_BPS(par.bits); par.le = SIO_LE_NATIVE; par.msb = 1; par.rchan = mDevice->channelsFromFmt(); - par.rate = mDevice->Frequency; + par.rate = mDevice->mSampleRate; - par.appbufsz = maxu(mDevice->BufferSize, mDevice->Frequency/10); - par.round = minu(par.appbufsz/2, mDevice->Frequency/40); + par.appbufsz = std::max(mDevice->mBufferSize, mDevice->mSampleRate/10u); + par.round = std::min(par.appbufsz/2u, mDevice->mSampleRate/40u); if(!sio_setpar(mSndHandle, &par) || !sio_getpar(mSndHandle, &par)) throw al::backend_exception{al::backend_error::DeviceError, @@ -440,10 +439,10 @@ void SndioCapture::open(std::string_view name) if(par.bps > 1 && par.le != SIO_LE_NATIVE) throw al::backend_exception{al::backend_error::DeviceError, - "%s-endian samples not supported", par.le ? "Little" : "Big"}; + "{}-endian samples not supported", par.le ? "Little" : "Big"}; if(par.bits < par.bps*8 && !par.msb) throw al::backend_exception{al::backend_error::DeviceError, - "Padded samples not supported (got %u of %u bits)", par.bits, par.bps*8}; + "Padded samples not supported (got {} of {} bits)", par.bits, par.bps*8}; auto match_fmt = [](DevFmtType fmttype, const sio_par &p) -> bool { @@ -455,19 +454,19 @@ void SndioCapture::open(std::string_view name) || (fmttype == DevFmtUInt && p.bps == 4 && p.sig == 0); }; if(!match_fmt(mDevice->FmtType, par) || mDevice->channelsFromFmt() != par.rchan - || mDevice->Frequency != par.rate) + || mDevice->mSampleRate != par.rate) throw al::backend_exception{al::backend_error::DeviceError, - "Failed to set format %s %s %uhz, got %c%u %u-channel %uhz instead", + "Failed to set format {} {} {}hz, got {}{} {}-channel {}hz instead", DevFmtTypeString(mDevice->FmtType), DevFmtChannelsString(mDevice->FmtChans), - mDevice->Frequency, par.sig?'s':'u', par.bps*8, par.rchan, par.rate}; + mDevice->mSampleRate, par.sig?'s':'u', par.bps*8, par.rchan, par.rate}; - mRing = RingBuffer::Create(mDevice->BufferSize, par.bps*par.rchan, false); - mDevice->BufferSize = static_cast(mRing->writeSpace()); - mDevice->UpdateSize = par.round; + mRing = RingBuffer::Create(mDevice->mBufferSize, size_t{par.bps}*par.rchan, false); + mDevice->mBufferSize = static_cast(mRing->writeSpace()); + mDevice->mUpdateSize = par.round; setDefaultChannelOrder(); - mDevice->DeviceName = name; + mDeviceName = name; } void SndioCapture::start() @@ -477,12 +476,12 @@ void SndioCapture::start() try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&SndioCapture::recordProc), this}; + mThread = std::thread{&SndioCapture::recordProc, this}; } catch(std::exception& e) { sio_stop(mSndHandle); throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start capture thread: %s", e.what()}; + "Failed to start capture thread: {}", e.what()}; } } @@ -493,11 +492,11 @@ void SndioCapture::stop() mThread.join(); if(!sio_stop(mSndHandle)) - ERR("Error stopping device\n"); + ERR("Error stopping device"); } void SndioCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } uint SndioCapture::availableSamples() { return static_cast(mRing->readSpace()); } @@ -516,18 +515,15 @@ bool SndIOBackendFactory::init() bool SndIOBackendFactory::querySupport(BackendType type) { return (type == BackendType::Playback || type == BackendType::Capture); } -std::string SndIOBackendFactory::probe(BackendType type) +auto SndIOBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; switch(type) { case BackendType::Playback: case BackendType::Capture: - /* Includes null char. */ - outnames.append(sndio_device, sizeof(sndio_device)); - break; + return std::vector{std::string{GetDefaultName()}}; } - return outnames; + return {}; } BackendPtr SndIOBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/sndio.h b/3rdparty/openal/alc/backends/sndio.h deleted file mode 100644 index d94331911790..000000000000 --- a/3rdparty/openal/alc/backends/sndio.h +++ /dev/null @@ -1,19 +0,0 @@ -#ifndef BACKENDS_SNDIO_H -#define BACKENDS_SNDIO_H - -#include "base.h" - -struct SndIOBackendFactory final : public BackendFactory { -public: - bool init() override; - - bool querySupport(BackendType type) override; - - std::string probe(BackendType type) override; - - BackendPtr createBackend(DeviceBase *device, BackendType type) override; - - static BackendFactory &getFactory(); -}; - -#endif /* BACKENDS_SNDIO_H */ diff --git a/3rdparty/openal/alc/backends/sndio.hpp b/3rdparty/openal/alc/backends/sndio.hpp new file mode 100644 index 000000000000..4327524ffe08 --- /dev/null +++ b/3rdparty/openal/alc/backends/sndio.hpp @@ -0,0 +1,19 @@ +#ifndef BACKENDS_SNDIO_HPP +#define BACKENDS_SNDIO_HPP + +#include "base.h" + +struct SndIOBackendFactory final : public BackendFactory { +public: + auto init() -> bool final; + + auto querySupport(BackendType type) -> bool final; + + auto enumerate(BackendType type) -> std::vector final; + + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; +}; + +#endif /* BACKENDS_SNDIO_HPP */ diff --git a/3rdparty/openal/alc/backends/solaris.cpp b/3rdparty/openal/alc/backends/solaris.cpp index 38f9db19b603..c42015e745f9 100644 --- a/3rdparty/openal/alc/backends/solaris.cpp +++ b/3rdparty/openal/alc/backends/solaris.cpp @@ -41,6 +41,7 @@ #include #include "alc/alconfig.h" +#include "alstring.h" #include "althrd_setname.h" #include "core/device.h" #include "core/helpers.h" @@ -51,13 +52,15 @@ namespace { -constexpr char solaris_device[] = "Solaris Default"; +using namespace std::string_view_literals; + +[[nodiscard]] constexpr auto GetDefaultName() noexcept { return "Solaris Default"sv; } std::string solaris_driver{"/dev/audio"}; struct SolarisBackend final : public BackendBase { - SolarisBackend(DeviceBase *device) noexcept : BackendBase{device} { } + explicit SolarisBackend(DeviceBase *device) noexcept : BackendBase{device} { } ~SolarisBackend() override; int mixerProc(); @@ -74,8 +77,6 @@ struct SolarisBackend final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(SolarisBackend) }; SolarisBackend::~SolarisBackend() @@ -88,10 +89,10 @@ SolarisBackend::~SolarisBackend() int SolarisBackend::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); const size_t frame_step{mDevice->channelsFromFmt()}; - const uint frame_size{mDevice->frameSizeFromFmt()}; + const size_t frame_size{mDevice->frameSizeFromFmt()}; while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) @@ -105,33 +106,32 @@ int SolarisBackend::mixerProc() { if(errno == EINTR || errno == EAGAIN) continue; - ERR("poll failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed to wait for playback buffer: %s", strerror(errno)); + ERR("poll failed: {}", strerror(errno)); + mDevice->handleDisconnect("Failed to wait for playback buffer: {}", strerror(errno)); break; } else if(pret == 0) { - WARN("poll timeout\n"); + WARN("poll timeout"); continue; } - std::byte *write_ptr{mBuffer.data()}; - size_t to_write{mBuffer.size()}; - mDevice->renderSamples(write_ptr, static_cast(to_write/frame_size), frame_step); - while(to_write > 0 && !mKillNow.load(std::memory_order_acquire)) + al::span buffer{mBuffer}; + mDevice->renderSamples(buffer.data(), static_cast(buffer.size()/frame_size), + frame_step); + while(!buffer.empty() && !mKillNow.load(std::memory_order_acquire)) { - ssize_t wrote{write(mFd, write_ptr, to_write)}; + ssize_t wrote{write(mFd, buffer.data(), buffer.size())}; if(wrote < 0) { if(errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) continue; - ERR("write failed: %s\n", strerror(errno)); - mDevice->handleDisconnect("Failed to write playback samples: %s", strerror(errno)); + ERR("write failed: {}", strerror(errno)); + mDevice->handleDisconnect("Failed to write playback samples: {}", strerror(errno)); break; } - to_write -= static_cast(wrote); - write_ptr += wrote; + buffer = buffer.subspan(static_cast(wrote)); } } @@ -142,21 +142,21 @@ int SolarisBackend::mixerProc() void SolarisBackend::open(std::string_view name) { if(name.empty()) - name = solaris_device; - else if(name != solaris_device) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDefaultName(); + else if(name != GetDefaultName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; int fd{::open(solaris_driver.c_str(), O_WRONLY)}; if(fd == -1) - throw al::backend_exception{al::backend_error::NoDevice, "Could not open %s: %s", - solaris_driver.c_str(), strerror(errno)}; + throw al::backend_exception{al::backend_error::NoDevice, "Could not open {}: {}", + solaris_driver, strerror(errno)}; if(mFd != -1) ::close(mFd); mFd = fd; - mDevice->DeviceName = name; + mDeviceName = name; } bool SolarisBackend::reset() @@ -164,7 +164,7 @@ bool SolarisBackend::reset() audio_info_t info; AUDIO_INITINFO(&info); - info.play.sample_rate = mDevice->Frequency; + info.play.sample_rate = mDevice->mSampleRate; info.play.channels = mDevice->channelsFromFmt(); switch(mDevice->FmtType) { @@ -187,11 +187,11 @@ bool SolarisBackend::reset() info.play.encoding = AUDIO_ENCODING_LINEAR; break; } - info.play.buffer_size = mDevice->BufferSize * mDevice->frameSizeFromFmt(); + info.play.buffer_size = mDevice->mBufferSize * mDevice->frameSizeFromFmt(); if(ioctl(mFd, AUDIO_SETINFO, &info) < 0) { - ERR("ioctl failed: %s\n", strerror(errno)); + ERR("ioctl failed: {}", strerror(errno)); return false; } @@ -203,7 +203,7 @@ bool SolarisBackend::reset() mDevice->FmtChans = DevFmtMono; else throw al::backend_exception{al::backend_error::DeviceError, - "Got %u device channels", info.play.channels}; + "Got {} device channels", info.play.channels}; } if(info.play.precision == 8 && info.play.encoding == AUDIO_ENCODING_LINEAR8) @@ -216,20 +216,20 @@ bool SolarisBackend::reset() mDevice->FmtType = DevFmtInt; else { - ERR("Got unhandled sample type: %d (0x%x)\n", info.play.precision, info.play.encoding); + ERR("Got unhandled sample type: {} ({:#x})", info.play.precision, info.play.encoding); return false; } uint frame_size{mDevice->bytesFromFmt() * info.play.channels}; mFrameStep = info.play.channels; - mDevice->Frequency = info.play.sample_rate; - mDevice->BufferSize = info.play.buffer_size / frame_size; + mDevice->mSampleRate = info.play.sample_rate; + mDevice->mBufferSize = info.play.buffer_size / frame_size; /* How to get the actual period size/count? */ - mDevice->UpdateSize = mDevice->BufferSize / 2; + mDevice->mUpdateSize = mDevice->mBufferSize / 2; setDefaultChannelOrder(); - mBuffer.resize(mDevice->UpdateSize * size_t{frame_size}); + mBuffer.resize(mDevice->mUpdateSize * size_t{frame_size}); std::fill(mBuffer.begin(), mBuffer.end(), std::byte{}); return true; @@ -239,11 +239,11 @@ void SolarisBackend::start() { try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&SolarisBackend::mixerProc), this}; + mThread = std::thread{&SolarisBackend::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -254,7 +254,7 @@ void SolarisBackend::stop() mThread.join(); if(ioctl(mFd, AUDIO_DRAIN) < 0) - ERR("Error draining device: %s\n", strerror(errno)); + ERR("Error draining device: {}", strerror(errno)); } } // namespace @@ -267,7 +267,7 @@ BackendFactory &SolarisBackendFactory::getFactory() bool SolarisBackendFactory::init() { - if(auto devopt = ConfigValueStr(nullptr, "solaris", "device")) + if(auto devopt = ConfigValueStr({}, "solaris", "device")) solaris_driver = std::move(*devopt); return true; } @@ -275,23 +275,19 @@ bool SolarisBackendFactory::init() bool SolarisBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback; } -std::string SolarisBackendFactory::probe(BackendType type) +auto SolarisBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; switch(type) { case BackendType::Playback: - { - struct stat buf; - if(stat(solaris_driver.c_str(), &buf) == 0) - outnames.append(solaris_device, sizeof(solaris_device)); - } - break; + if(struct stat buf{}; stat(solaris_driver.c_str(), &buf) == 0) + return std::vector{std::string{GetDefaultName()}}; + break; case BackendType::Capture: break; } - return outnames; + return {}; } BackendPtr SolarisBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/solaris.h b/3rdparty/openal/alc/backends/solaris.h index 5da6ad3a95a2..8415c362b8fb 100644 --- a/3rdparty/openal/alc/backends/solaris.h +++ b/3rdparty/openal/alc/backends/solaris.h @@ -5,15 +5,15 @@ struct SolarisBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_SOLARIS_H */ diff --git a/3rdparty/openal/alc/backends/wasapi.cpp b/3rdparty/openal/alc/backends/wasapi.cpp index e26af7c9c60f..9f9449689bb0 100644 --- a/3rdparty/openal/alc/backends/wasapi.cpp +++ b/3rdparty/openal/alc/backends/wasapi.cpp @@ -25,10 +25,11 @@ #define WIN32_LEAN_AND_MEAN #include -#include -#include +#include +#include #include +#include #include #include #include @@ -50,30 +51,30 @@ #include #include #include -#include #include #include #include #include +#include #include #include #include "albit.h" #include "alc/alconfig.h" -#include "alc/events.h" #include "alnumeric.h" #include "alspan.h" +#include "alstring.h" #include "althrd_setname.h" #include "comptr.h" #include "core/converter.h" #include "core/device.h" -#include "core/helpers.h" #include "core/logging.h" +#include "fmt/core.h" +#include "fmt/chrono.h" #include "ringbuffer.h" #include "strutils.h" -#if defined(ALSOFT_UWP) - +#if ALSOFT_UWP #include // !!This is important!! #include #include @@ -81,11 +82,7 @@ #include #include -using namespace winrt; -using namespace Windows::Foundation; -using namespace Windows::Media::Devices; -using namespace Windows::Devices::Enumeration; -using namespace Windows::Media::Devices; +#include "alstring.h" #endif /* Some headers seem to define these as macros for __uuidof, which is annoying @@ -98,7 +95,7 @@ DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80, 0x00, 0x #ifndef KSDATAFORMAT_SUBTYPE_IEEE_FLOAT DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71); #endif -#if !defined(ALSOFT_UWP) +#if !ALSOFT_UWP DEFINE_DEVPROPKEY(DEVPKEY_Device_FriendlyName, 0xa45c254e, 0xdf1c, 0x4efd, 0x80,0x20, 0x67,0xd1,0x46,0xa8,0x50,0xe0, 14); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_FormFactor, 0x1da5d803, 0xd492, 0x4edd, 0x8c,0x23, 0xe0,0xc0,0xff,0xee,0x7f,0x0e, 0); DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x23,0xe0, 0xc0,0xff,0xee,0x7f,0x0e, 4 ); @@ -106,14 +103,23 @@ DEFINE_PROPERTYKEY(PKEY_AudioEndpoint_GUID, 0x1da5d803, 0xd492, 0x4edd, 0x8c, 0x namespace { +#if ALSOFT_UWP +using namespace winrt; +using namespace Windows::Foundation; +using namespace Windows::Media::Devices; +using namespace Windows::Devices::Enumeration; +using namespace Windows::Media::Devices; +#endif +#ifndef E_NOTFOUND +#define E_NOTFOUND E_NOINTERFACE +#endif + +using namespace std::string_view_literals; using std::chrono::nanoseconds; using std::chrono::milliseconds; using std::chrono::seconds; -using ReferenceTime = std::chrono::duration>; - -inline constexpr ReferenceTime operator "" _reftime(unsigned long long int n) noexcept -{ return ReferenceTime{static_cast(n)}; } +using ReferenceTime = std::chrono::duration>; #define MONO SPEAKER_FRONT_CENTER @@ -125,7 +131,7 @@ inline constexpr ReferenceTime operator "" _reftime(unsigned long long int n) no #define X7DOT1 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT) #define X7DOT1DOT4 (SPEAKER_FRONT_LEFT|SPEAKER_FRONT_RIGHT|SPEAKER_FRONT_CENTER|SPEAKER_LOW_FREQUENCY|SPEAKER_BACK_LEFT|SPEAKER_BACK_RIGHT|SPEAKER_SIDE_LEFT|SPEAKER_SIDE_RIGHT|SPEAKER_TOP_FRONT_LEFT|SPEAKER_TOP_FRONT_RIGHT|SPEAKER_TOP_BACK_LEFT|SPEAKER_TOP_BACK_RIGHT) -constexpr inline DWORD MaskFromTopBits(DWORD b) noexcept +constexpr auto MaskFromTopBits(DWORD b) noexcept -> DWORD { b |= b>>1; b |= b>>2; @@ -157,9 +163,6 @@ constexpr AudioObjectType ChannelMask_Quad{AudioObjectType_FrontLeft | AudioObje constexpr AudioObjectType ChannelMask_X51{AudioObjectType_FrontLeft | AudioObjectType_FrontRight | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft | AudioObjectType_SideRight}; -constexpr AudioObjectType ChannelMask_X51Rear{AudioObjectType_FrontLeft - | AudioObjectType_FrontRight | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency - | AudioObjectType_BackLeft | AudioObjectType_BackRight}; constexpr AudioObjectType ChannelMask_X61{AudioObjectType_FrontLeft | AudioObjectType_FrontRight | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft | AudioObjectType_SideRight | AudioObjectType_BackCenter}; @@ -171,10 +174,13 @@ constexpr AudioObjectType ChannelMask_X714{AudioObjectType_FrontLeft | AudioObje | AudioObjectType_SideRight | AudioObjectType_BackLeft | AudioObjectType_BackRight | AudioObjectType_TopFrontLeft | AudioObjectType_TopFrontRight | AudioObjectType_TopBackLeft | AudioObjectType_TopBackRight}; - - -constexpr char DevNameHead[] = "OpenAL Soft on "; -constexpr size_t DevNameHeadLen{std::size(DevNameHead) - 1}; +constexpr AudioObjectType ChannelMask_X7144{AudioObjectType_FrontLeft | AudioObjectType_FrontRight + | AudioObjectType_FrontCenter | AudioObjectType_LowFrequency | AudioObjectType_SideLeft + | AudioObjectType_SideRight | AudioObjectType_BackLeft | AudioObjectType_BackRight + | AudioObjectType_TopFrontLeft | AudioObjectType_TopFrontRight | AudioObjectType_TopBackLeft + | AudioObjectType_TopBackRight | AudioObjectType_BottomFrontLeft + | AudioObjectType_BottomFrontRight | AudioObjectType_BottomBackLeft + | AudioObjectType_BottomBackRight}; template @@ -185,16 +191,15 @@ overloaded(Ts...) -> overloaded; template -auto as_unsigned(T value) noexcept -{ - using UT = std::make_unsigned_t; - return static_cast(value); -} +struct CoTaskMemDeleter { + void operator()(T *ptr) const { CoTaskMemFree(ptr); } +}; +template +using unique_coptr = std::unique_ptr>; /* Scales the given reftime value, rounding the result. */ -template -constexpr uint RefTime2Samples(const ReferenceTime &val, T srate) noexcept +constexpr auto RefTime2Samples(const ReferenceTime &val, DWORD srate) noexcept -> uint { const auto retval = (val*srate + ReferenceTime{seconds{1}}/2) / seconds{1}; return static_cast(std::min(retval, std::numeric_limits::max())); @@ -202,34 +207,66 @@ constexpr uint RefTime2Samples(const ReferenceTime &val, T srate) noexcept class GuidPrinter { - char mMsg[64]; + std::string mMsg; public: - GuidPrinter(const GUID &guid) - { - std::snprintf(mMsg, std::size(mMsg), "{%08lx-%04x-%04x-%02x%02x-%02x%02x%02x%02x%02x%02x}", - DWORD{guid.Data1}, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], - guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); - } - const char *c_str() const { return mMsg; } + explicit GuidPrinter(const GUID &guid) + : mMsg{fmt::format( + "{{{:08x}-{:04x}-{:04x}-{:02x}{:02x}-{:02x}{:02x}{:02x}{:02x}{:02x}{:02x}}}", + guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], + guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7])} + { } + [[nodiscard]] auto str() const noexcept -> const std::string& { return mMsg; } }; struct PropVariant { - PROPVARIANT mProp; + PROPVARIANT mProp{}; public: PropVariant() { PropVariantInit(&mProp); } + PropVariant(const PropVariant &rhs) : PropVariant{} { PropVariantCopy(&mProp, &rhs.mProp); } ~PropVariant() { clear(); } + auto operator=(const PropVariant &rhs) -> PropVariant& + { + if(this != &rhs) + PropVariantCopy(&mProp, &rhs.mProp); + return *this; + } + void clear() { PropVariantClear(&mProp); } PROPVARIANT* get() noexcept { return &mProp; } - PROPVARIANT& operator*() noexcept { return mProp; } - const PROPVARIANT& operator*() const noexcept { return mProp; } + /* NOLINTBEGIN(cppcoreguidelines-pro-type-union-access) */ + [[nodiscard]] + auto type() const noexcept -> VARTYPE { return mProp.vt; } - PROPVARIANT* operator->() noexcept { return &mProp; } - const PROPVARIANT* operator->() const noexcept { return &mProp; } + template [[nodiscard]] + auto value() const -> T + { + if constexpr(std::is_same_v) + { + alassert(mProp.vt == VT_UI4 || mProp.vt == VT_UINT); + return mProp.uintVal; + } + else if constexpr(std::is_same_v || std::is_same_v + || std::is_same_v || std::is_same_v) + { + alassert(mProp.vt == VT_LPWSTR); + return mProp.pwszVal; + } + } + + void setBlob(const al::span data) + { + if constexpr(sizeof(size_t) > sizeof(ULONG)) + alassert(data.size() <= std::numeric_limits::max()); + mProp.vt = VT_BLOB; + mProp.blob.cbSize = static_cast(data.size()); + mProp.blob.pBlobData = data.data(); + } + /* NOLINTEND(cppcoreguidelines-pro-type-union-access) */ }; struct DevMap { @@ -248,9 +285,9 @@ struct DevMap { }; DevMap::~DevMap() = default; -bool checkName(const al::span list, const std::string &name) +bool checkName(const al::span list, const std::string_view name) { - auto match_name = [&name](const DevMap &entry) -> bool { return entry.name == name; }; + auto match_name = [name](const DevMap &entry) -> bool { return entry.name == name; }; return std::find_if(list.cbegin(), list.cend(), match_name) != list.cend(); } @@ -271,19 +308,28 @@ struct DeviceList { struct DeviceListLock : public std::unique_lock { using std::unique_lock::unique_lock; - auto& getPlaybackList() const noexcept { return mutex()->mPlayback; } - auto& getCaptureList() const noexcept { return mutex()->mCapture; } + [[nodiscard]] auto& getPlaybackList() const noexcept { return mutex()->mPlayback; } + [[nodiscard]] auto& getCaptureList() const noexcept { return mutex()->mCapture; } void setPlaybackDefaultId(std::wstring_view devid) const { mutex()->mPlaybackDefaultId = devid; } - std::wstring_view getPlaybackDefaultId() const noexcept { return mutex()->mPlaybackDefaultId; } + [[nodiscard]] auto getPlaybackDefaultId() const noexcept -> std::wstring_view { return mutex()->mPlaybackDefaultId; } void setCaptureDefaultId(std::wstring_view devid) const { mutex()->mCaptureDefaultId = devid; } - std::wstring_view getCaptureDefaultId() const noexcept { return mutex()->mCaptureDefaultId; } + [[nodiscard]] auto getCaptureDefaultId() const noexcept -> std::wstring_view { return mutex()->mCaptureDefaultId; } }; DeviceList gDeviceList; +std::condition_variable_any gInitCV; +std::atomic gInitDone{false}; + +#ifdef AVRTAPI +struct AvrtHandleCloser { + void operator()(HANDLE handle) { AvRevertMmThreadCharacteristics(handle); } +}; +using AvrtHandlePtr = std::unique_ptr,AvrtHandleCloser>; +#endif -#if defined(ALSOFT_UWP) +#if ALSOFT_UWP enum EDataFlow { eRender = 0, eCapture = (eRender + 1), @@ -292,7 +338,7 @@ enum EDataFlow { }; #endif -#if defined(ALSOFT_UWP) +#if ALSOFT_UWP using DeviceHandle = Windows::Devices::Enumeration::DeviceInformation; using EventRegistrationToken = winrt::event_token; #else @@ -300,54 +346,42 @@ using DeviceHandle = ComPtr; #endif -using NameGUIDPair = std::pair; -static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) +struct NameGUIDPair { std::string mName; std::string mGuid; }; +auto GetDeviceNameAndGuid(const DeviceHandle &device) -> NameGUIDPair { - static constexpr char UnknownName[]{"Unknown Device Name"}; - static constexpr char UnknownGuid[]{"Unknown Device GUID"}; -#if !defined(ALSOFT_UWP) - std::string name, guid; + constexpr auto UnknownName = "Unknown Device Name"sv; + constexpr auto UnknownGuid = "Unknown Device GUID"sv; - ComPtr ps; - HRESULT hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); +#if !ALSOFT_UWP + auto ps = ComPtr{}; + auto hr = device->OpenPropertyStore(STGM_READ, al::out_ptr(ps)); if(FAILED(hr)) { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); - return std::make_pair(UnknownName, UnknownGuid); + WARN("OpenPropertyStore failed: {:#x}", as_unsigned(hr)); + return NameGUIDPair{std::string{UnknownName}, std::string{UnknownGuid}}; } - PropVariant pvprop; + auto ret = NameGUIDPair{}; + auto pvprop = PropVariant{}; hr = ps->GetValue(al::bit_cast(DEVPKEY_Device_FriendlyName), pvprop.get()); if(FAILED(hr)) - { - WARN("GetValue Device_FriendlyName failed: 0x%08lx\n", hr); - name = UnknownName; - } - else if(pvprop->vt == VT_LPWSTR) - name = wstr_to_utf8(pvprop->pwszVal); + WARN("GetValue Device_FriendlyName failed: {:#x}", as_unsigned(hr)); + else if(pvprop.type() == VT_LPWSTR) + ret.mName = wstr_to_utf8(pvprop.value()); else - { - WARN("Unexpected Device_FriendlyName PROPVARIANT type: 0x%04x\n", pvprop->vt); - name = UnknownName; - } + WARN("Unexpected Device_FriendlyName PROPVARIANT type: {:#04x}", pvprop.type()); pvprop.clear(); hr = ps->GetValue(al::bit_cast(PKEY_AudioEndpoint_GUID), pvprop.get()); if(FAILED(hr)) - { - WARN("GetValue AudioEndpoint_GUID failed: 0x%08lx\n", hr); - guid = UnknownGuid; - } - else if(pvprop->vt == VT_LPWSTR) - guid = wstr_to_utf8(pvprop->pwszVal); + WARN("GetValue AudioEndpoint_GUID failed: {:#x}", as_unsigned(hr)); + else if(pvprop.type() == VT_LPWSTR) + ret.mGuid = wstr_to_utf8(pvprop.value()); else - { - WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: 0x%04x\n", pvprop->vt); - guid = UnknownGuid; - } + WARN("Unexpected AudioEndpoint_GUID PROPVARIANT type: {:#04x}", pvprop.type()); #else - std::string name{wstr_to_utf8(device.Name())}; - std::string guid; + auto ret = NameGUIDPair{wstr_to_utf8(device.Name()), {}}; + // device->Id is DeviceInterfacePath: \\?\SWD#MMDEVAPI#{0.0.0.00000000}.{a21c17a0-fc1d-405e-ab5a-b513422b57d1}#{e6327cad-dcec-4949-ae8a-991e976a79d2} auto devIfPath = device.Id(); if(auto devIdStart = wcsstr(devIfPath.data(), L"}.")) @@ -355,25 +389,25 @@ static NameGUIDPair GetDeviceNameAndGuid(const DeviceHandle &device) devIdStart += 2; // L"}." if(auto devIdStartEnd = wcschr(devIdStart, L'#')) { - std::wstring wDevId{devIdStart, static_cast(devIdStartEnd - devIdStart)}; - guid = wstr_to_utf8(wDevId.c_str()); - std::transform(guid.begin(), guid.end(), guid.begin(), + ret.mGuid = wstr_to_utf8(std::wstring_view{devIdStart, + static_cast(devIdStartEnd - devIdStart)}); + std::transform(ret.mGuid.begin(), ret.mGuid.end(), ret.mGuid.begin(), [](char ch) { return static_cast(std::toupper(ch)); }); } } - if(name.empty()) name = UnknownName; - if(guid.empty()) guid = UnknownGuid; #endif - return std::make_pair(std::move(name), std::move(guid)); + if(ret.mName.empty()) ret.mName = UnknownName; + if(ret.mGuid.empty()) ret.mGuid = UnknownGuid; + return ret; } -#if !defined(ALSOFT_UWP) +#if !ALSOFT_UWP EndpointFormFactor GetDeviceFormfactor(IMMDevice *device) { ComPtr ps; HRESULT hr{device->OpenPropertyStore(STGM_READ, al::out_ptr(ps))}; if(FAILED(hr)) { - WARN("OpenPropertyStore failed: 0x%08lx\n", hr); + WARN("OpenPropertyStore failed: {:#x}", as_unsigned(hr)); return UnknownFormFactor; } @@ -381,66 +415,73 @@ EndpointFormFactor GetDeviceFormfactor(IMMDevice *device) PropVariant pvform; hr = ps->GetValue(PKEY_AudioEndpoint_FormFactor, pvform.get()); if(FAILED(hr)) - WARN("GetValue AudioEndpoint_FormFactor failed: 0x%08lx\n", hr); - else if(pvform->vt == VT_UI4) - formfactor = static_cast(pvform->ulVal); - else if(pvform->vt != VT_EMPTY) - WARN("Unexpected PROPVARIANT type: 0x%04x\n", pvform->vt); + WARN("GetValue AudioEndpoint_FormFactor failed: {:#x}", as_unsigned(hr)); + else if(pvform.type() == VT_UI4) + formfactor = static_cast(pvform.value()); + else if(pvform.type() != VT_EMPTY) + WARN("Unexpected PROPVARIANT type: {:#04x}", pvform.type()); return formfactor; } #endif -#if defined(ALSOFT_UWP) -struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler -#else -struct DeviceHelper final : private IMMNotificationClient -#endif -{ - DeviceHelper() +#if ALSOFT_UWP +struct DeviceEnumHelper final : public IActivateAudioInterfaceCompletionHandler { + DeviceEnumHelper() { -#if defined(ALSOFT_UWP) /* TODO: UWP also needs to watch for device added/removed events and * dynamically add/remove devices from the lists. */ mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); - mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioRenderDeviceChangedEventArgs& args) { - if (args.Role() == AudioDeviceRole::Default) + static constexpr auto playback_cb = [](const IInspectable &sender [[maybe_unused]], + const DefaultAudioRenderDeviceChangedEventArgs &args) + { + if(args.Role() == AudioDeviceRole::Default) { - const std::string msg{ "Default playback device changed: " + + const auto msg = std::string{"Default playback device changed: " + wstr_to_utf8(args.Id())}; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, - msg); + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Playback, msg); } - }); + }; + mRenderDeviceChangedToken = MediaDevice::DefaultAudioRenderDeviceChanged(playback_cb); - mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged([this](const IInspectable& /*sender*/, const DefaultAudioCaptureDeviceChangedEventArgs& args) { - if (args.Role() == AudioDeviceRole::Default) + static constexpr auto capture_cb = [](const IInspectable &sender [[maybe_unused]], + const DefaultAudioCaptureDeviceChangedEventArgs &args) + { + if(args.Role() == AudioDeviceRole::Default) { - const std::string msg{ "Default capture device changed: " + - wstr_to_utf8(args.Id()) }; - alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, - msg); + const auto msg = std::string{"Default capture device changed: " + + wstr_to_utf8(args.Id())}; + alc::Event(alc::EventType::DefaultDeviceChanged, alc::DeviceType::Capture, msg); } - }); -#endif + }; + mCaptureDeviceChangedToken = MediaDevice::DefaultAudioCaptureDeviceChanged(capture_cb); } - ~DeviceHelper() + + ~DeviceEnumHelper() { -#if defined(ALSOFT_UWP) MediaDevice::DefaultAudioRenderDeviceChanged(mRenderDeviceChangedToken); MediaDevice::DefaultAudioCaptureDeviceChanged(mCaptureDeviceChangedToken); if(mActiveClientEvent != nullptr) CloseHandle(mActiveClientEvent); mActiveClientEvent = nullptr; + } #else + +struct DeviceEnumHelper final : private IMMNotificationClient { + DeviceEnumHelper() = default; + ~DeviceEnumHelper() + { if(mEnumerator) mEnumerator->UnregisterEndpointNotificationCallback(this); mEnumerator = nullptr; -#endif } +#endif + + template + auto as() noexcept -> T { return T{this}; } /** -------------------------- IUnknown ----------------------------- */ std::atomic mRefCount{1}; @@ -466,24 +507,24 @@ struct DeviceHelper final : private IMMNotificationClient // that, from the client's point of view, has a reference count of one. If the client then calls AddRef on the // interface pointer, the reference count becomes two. The client must call Release twice on the interface // pointer to drop all of its references to the object. -#if defined(ALSOFT_UWP) +#if ALSOFT_UWP if(IId == __uuidof(IActivateAudioInterfaceCompletionHandler)) { - *UnknownPtrPtr = static_cast(this); + *UnknownPtrPtr = as(); AddRef(); return S_OK; } #else if(IId == __uuidof(IMMNotificationClient)) { - *UnknownPtrPtr = static_cast(this); + *UnknownPtrPtr = as(); AddRef(); return S_OK; } #endif else if(IId == __uuidof(IAgileObject) || IId == __uuidof(IUnknown)) { - *UnknownPtrPtr = static_cast(this); + *UnknownPtrPtr = as(); AddRef(); return S_OK; } @@ -493,7 +534,7 @@ struct DeviceHelper final : private IMMNotificationClient return E_NOINTERFACE; } -#if defined(ALSOFT_UWP) +#if ALSOFT_UWP /** ----------------------- IActivateAudioInterfaceCompletionHandler ------------ */ HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation*) override { @@ -504,82 +545,42 @@ struct DeviceHelper final : private IMMNotificationClient } #else /** ----------------------- IMMNotificationClient ------------ */ - STDMETHODIMP OnDeviceStateChanged(LPCWSTR /*pwstrDeviceId*/, DWORD /*dwNewState*/) noexcept override { return S_OK; } - - STDMETHODIMP OnDeviceAdded(LPCWSTR pwstrDeviceId) noexcept override + STDMETHODIMP OnDeviceStateChanged(LPCWSTR deviceId, DWORD newState) noexcept override { - ComPtr device; - HRESULT hr{mEnumerator->GetDevice(pwstrDeviceId, al::out_ptr(device))}; - if(FAILED(hr)) - { - ERR("Failed to get device: 0x%08lx\n", hr); - return S_OK; - } - - ComPtr endpoint; - hr = device->QueryInterface(__uuidof(IMMEndpoint), al::out_ptr(endpoint)); - if(FAILED(hr)) - { - ERR("Failed to get device endpoint: 0x%08lx\n", hr); - return S_OK; - } - - EDataFlow flowdir{}; - hr = endpoint->GetDataFlow(&flowdir); - if(FAILED(hr)) - { - ERR("Failed to get endpoint data flow: 0x%08lx\n", hr); - return S_OK; - } - - auto devlock = DeviceListLock{gDeviceList}; - auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); - - if(AddDevice(device, pwstrDeviceId, list)) - { - const auto devtype = (flowdir==eRender) ? alc::DeviceType::Playback - : alc::DeviceType::Capture; - const std::string msg{"Device added: "+list.back().name}; - alc::Event(alc::EventType::DeviceAdded, devtype, msg); - } + TRACE("OnDeviceStateChanged({}, {:#x})", deviceId ? wstr_to_utf8(deviceId) + : std::string{""}, newState); - return S_OK; + if(!(newState&DEVICE_STATE_ACTIVE)) + return DeviceRemoved(deviceId); + return DeviceAdded(deviceId); } - STDMETHODIMP OnDeviceRemoved(LPCWSTR pwstrDeviceId) noexcept override + STDMETHODIMP OnDeviceAdded(LPCWSTR deviceId) noexcept override { - auto devlock = DeviceListLock{gDeviceList}; - for(auto flowdir : std::array{eRender, eCapture}) - { - auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); - auto devtype = (flowdir==eRender)?alc::DeviceType::Playback : alc::DeviceType::Capture; - - /* Find the ID in the list to remove. */ - auto iter = std::find_if(list.begin(), list.end(), - [pwstrDeviceId](const DevMap &entry) noexcept - { return pwstrDeviceId == entry.devid; }); - if(iter == list.end()) continue; - - TRACE("Removing device \"%s\", \"%s\", \"%ls\"\n", iter->name.c_str(), - iter->endpoint_guid.c_str(), iter->devid.c_str()); - - std::string msg{"Device removed: "+std::move(iter->name)}; - list.erase(iter); + TRACE("OnDeviceAdded({})", deviceId ? wstr_to_utf8(deviceId) : std::string{""}); + return DeviceAdded(deviceId); + } - alc::Event(alc::EventType::DeviceRemoved, devtype, msg); - } - return S_OK; + STDMETHODIMP OnDeviceRemoved(LPCWSTR deviceId) noexcept override + { + TRACE("OnDeviceRemoved({})", deviceId ? wstr_to_utf8(deviceId) : std::string{""}); + return DeviceRemoved(deviceId); } + /* NOLINTNEXTLINE(clazy-function-args-by-ref) */ STDMETHODIMP OnPropertyValueChanged(LPCWSTR /*pwstrDeviceId*/, const PROPERTYKEY /*key*/) noexcept override { return S_OK; } - STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR pwstrDefaultDeviceId) noexcept override + STDMETHODIMP OnDefaultDeviceChanged(EDataFlow flow, ERole role, LPCWSTR defaultDeviceId) noexcept override { + TRACE("OnDefaultDeviceChanged({}, {}, {})", al::to_underlying(flow), + al::to_underlying(role), defaultDeviceId ? wstr_to_utf8(defaultDeviceId) + : std::string{""}); + if(role != eMultimedia) return S_OK; - const std::wstring_view devid{pwstrDefaultDeviceId ? pwstrDefaultDeviceId - : std::wstring_view{}}; + const auto devid = defaultDeviceId ? std::wstring_view{defaultDeviceId} + : std::wstring_view{}; if(flow == eRender) { DeviceListLock{gDeviceList}.setPlaybackDefaultId(devid); @@ -596,95 +597,34 @@ struct DeviceHelper final : private IMMNotificationClient } #endif - /** -------------------------- DeviceHelper ----------------------------- */ + /** ------------------------ DeviceEnumHelper -------------------------- */ HRESULT init() { -#if !defined(ALSOFT_UWP) +#if !ALSOFT_UWP HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, __uuidof(IMMDeviceEnumerator), al::out_ptr(mEnumerator))}; if(SUCCEEDED(hr)) mEnumerator->RegisterEndpointNotificationCallback(this); else - WARN("Failed to create IMMDeviceEnumerator instance: 0x%08lx\n", hr); - return hr; -#else - return S_OK; -#endif - } - - HRESULT openDevice(std::wstring_view devid, EDataFlow flow, DeviceHandle& device) - { -#if !defined(ALSOFT_UWP) - HRESULT hr{E_FAIL}; - if(mEnumerator) - { - if(devid.empty()) - hr = mEnumerator->GetDefaultAudioEndpoint(flow, eMultimedia, al::out_ptr(device)); - else - hr = mEnumerator->GetDevice(devid.data(), al::out_ptr(device)); - } + WARN("Failed to create IMMDeviceEnumerator instance: {:#x}", as_unsigned(hr)); return hr; #else - const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; - auto devIfPath = - devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) - : winrt::hstring(devid.data()); - if (devIfPath.empty()) - return E_POINTER; - - auto&& deviceInfo = DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, DeviceInformationKind::DeviceInterface).get(); - if (!deviceInfo) - return E_NOINTERFACE; - device = deviceInfo; return S_OK; #endif } -#if !defined(ALSOFT_UWP) - static HRESULT activateAudioClient(_In_ DeviceHandle &device, REFIID iid, void **ppv) - { return device->Activate(iid, CLSCTX_INPROC_SERVER, nullptr, ppv); } -#else - HRESULT activateAudioClient(_In_ DeviceHandle &device, _In_ REFIID iid, void **ppv) - { - ComPtr asyncOp; - HRESULT hr{ActivateAudioInterfaceAsync(device.Id().data(), iid, nullptr, this, - al::out_ptr(asyncOp))}; - if(FAILED(hr)) - return hr; - - /* I don't like waiting for INFINITE time, but the activate operation - * can take an indefinite amount of time since it can require user - * input. - */ - DWORD res{WaitForSingleObjectEx(mActiveClientEvent, INFINITE, FALSE)}; - if(res != WAIT_OBJECT_0) - { - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - return E_FAIL; - } - - HRESULT hrActivateRes{E_FAIL}; - ComPtr punkAudioIface; - hr = asyncOp->GetActivateResult(&hrActivateRes, al::out_ptr(punkAudioIface)); - if(SUCCEEDED(hr)) hr = hrActivateRes; - if(FAILED(hr)) return hr; - - return punkAudioIface->QueryInterface(iid, ppv); - } -#endif - std::wstring probeDevices(EDataFlow flowdir, std::vector &list) { std::wstring defaultId; std::vector{}.swap(list); -#if !defined(ALSOFT_UWP) +#if !ALSOFT_UWP ComPtr coll; HRESULT hr{mEnumerator->EnumAudioEndpoints(flowdir, DEVICE_STATE_ACTIVE, al::out_ptr(coll))}; if(FAILED(hr)) { - ERR("Failed to enumerate audio endpoints: 0x%08lx\n", hr); + ERR("Failed to enumerate audio endpoints: {:#x}", as_unsigned(hr)); return defaultId; } @@ -697,11 +637,11 @@ struct DeviceHelper final : private IMMNotificationClient hr = mEnumerator->GetDefaultAudioEndpoint(flowdir, eMultimedia, al::out_ptr(device)); if(SUCCEEDED(hr)) { - if(WCHAR *devid{GetDeviceId(device.get())}) - { - defaultId = devid; - CoTaskMemFree(devid); - } + auto devid = unique_coptr{}; + if(auto hr2 = device->GetId(al::out_ptr(devid)); SUCCEEDED(hr2)) + defaultId = devid.get(); + else + ERR("Failed to get device id: {:#x}", as_unsigned(hr)); device = nullptr; } @@ -711,23 +651,24 @@ struct DeviceHelper final : private IMMNotificationClient if(FAILED(hr)) continue; - if(WCHAR *devid{GetDeviceId(device.get())}) - { - std::ignore = AddDevice(device, devid, list); - CoTaskMemFree(devid); - } + auto devid = unique_coptr{}; + if(auto hr2 = device->GetId(al::out_ptr(devid)); SUCCEEDED(hr2)) + std::ignore = AddDevice(device, devid.get(), list); + else + ERR("Failed to get device id: {:#x}", as_unsigned(hr)); device = nullptr; } #else const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; auto DefaultAudioId = flowdir == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) : MediaDevice::GetDefaultAudioCaptureId(deviceRole); - if (DefaultAudioId.empty()) - return defaultId; - - auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, DeviceInformationKind::DeviceInterface).get(); - if(!deviceInfo) - return defaultId; + if(!DefaultAudioId.empty()) + { + auto deviceInfo = DeviceInformation::CreateFromIdAsync(DefaultAudioId, nullptr, + DeviceInformationKind::DeviceInterface).get(); + if(deviceInfo) + defaultId = deviceInfo.Id().data(); + } // Get the string identifier of the audio renderer auto AudioSelector = flowdir == eRender ? MediaDevice::GetAudioRenderSelector() : MediaDevice::GetAudioCaptureSelector(); @@ -740,7 +681,7 @@ struct DeviceHelper final : private IMMNotificationClient auto deviceCount = DeviceInfoCollection.Size(); for(unsigned int i{0};i < deviceCount;++i) { - deviceInfo = DeviceInfoCollection.GetAt(i); + auto deviceInfo = DeviceInfoCollection.GetAt(i); if(deviceInfo) std::ignore = AddDevice(deviceInfo, deviceInfo.Id().data(), list); } @@ -762,37 +703,93 @@ struct DeviceHelper final : private IMMNotificationClient return false; } - auto name_guid = GetDeviceNameAndGuid(device); - int count{1}; - std::string newname{name_guid.first}; + auto [name, guid] = GetDeviceNameAndGuid(device); + auto count = 1; + auto newname = name; while(checkName(list, newname)) - { - newname = name_guid.first; - newname += " #"; - newname += std::to_string(++count); - } - list.emplace_back(std::move(newname), std::move(name_guid.second), devid); - const DevMap &newentry = list.back(); + newname = fmt::format("{} #{}", name, ++count); + const auto &newentry = list.emplace_back(std::move(newname), std::move(guid), devid); - TRACE("Got device \"%s\", \"%s\", \"%ls\"\n", newentry.name.c_str(), - newentry.endpoint_guid.c_str(), newentry.devid.c_str()); + TRACE("Got device \"{}\", \"{}\", \"{}\"", newentry.name, newentry.endpoint_guid, + wstr_to_utf8(newentry.devid)); return true; } -#if !defined(ALSOFT_UWP) - static WCHAR *GetDeviceId(IMMDevice *device) +#if !ALSOFT_UWP + STDMETHODIMP DeviceAdded(LPCWSTR deviceId) noexcept { - WCHAR *devid; + auto device = ComPtr{}; + auto hr = mEnumerator->GetDevice(deviceId, al::out_ptr(device)); + if(FAILED(hr)) + { + ERR("Failed to get device: {:#x}", as_unsigned(hr)); + return S_OK; + } + + auto state = DWORD{}; + hr = device->GetState(&state); + if(FAILED(hr)) + { + ERR("Failed to get device state: {:#x}", as_unsigned(hr)); + return S_OK; + } + if(!(state&DEVICE_STATE_ACTIVE)) + return S_OK; - const HRESULT hr{device->GetId(&devid)}; + auto endpoint = ComPtr{}; + hr = device->QueryInterface(__uuidof(IMMEndpoint), al::out_ptr(endpoint)); + if(FAILED(hr)) + { + ERR("Failed to get device endpoint: {:#x}", as_unsigned(hr)); + return S_OK; + } + + auto flowdir = EDataFlow{}; + hr = endpoint->GetDataFlow(&flowdir); if(FAILED(hr)) { - ERR("Failed to get device id: %lx\n", hr); - return nullptr; + ERR("Failed to get endpoint data flow: {:#x}", as_unsigned(hr)); + return S_OK; + } + + auto devlock = DeviceListLock{gDeviceList}; + auto &list = (flowdir == eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + + if(AddDevice(device, deviceId, list)) + { + const auto devtype = (flowdir == eRender) ? alc::DeviceType::Playback + : alc::DeviceType::Capture; + const auto msg = "Device added: "+list.back().name; + alc::Event(alc::EventType::DeviceAdded, devtype, msg); } - return devid; + return S_OK; + } + + STDMETHODIMP DeviceRemoved(LPCWSTR deviceId) noexcept + { + auto devlock = DeviceListLock{gDeviceList}; + for(auto flowdir : std::array{eRender, eCapture}) + { + auto &list = (flowdir==eRender) ? devlock.getPlaybackList() : devlock.getCaptureList(); + auto devtype = (flowdir==eRender)?alc::DeviceType::Playback : alc::DeviceType::Capture; + + /* Find the ID in the list to remove. */ + auto iter = std::find_if(list.begin(), list.end(), + [deviceId](const DevMap &entry) noexcept { return deviceId == entry.devid; }); + if(iter == list.end()) continue; + + TRACE("Removing device \"{}\", \"{}\", \"{}\"", iter->name, iter->endpoint_guid, + wstr_to_utf8(iter->devid)); + + std::string msg{"Device removed: "+std::move(iter->name)}; + list.erase(iter); + + alc::Event(alc::EventType::DeviceRemoved, devtype, msg); + } + return S_OK; } + ComPtr mEnumerator{nullptr}; #else @@ -802,308 +799,458 @@ struct DeviceHelper final : private IMMNotificationClient EventRegistrationToken mRenderDeviceChangedToken; EventRegistrationToken mCaptureDeviceChangedToken; #endif -}; -bool MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) -{ - *out = WAVEFORMATEXTENSIBLE{}; - if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + static inline std::mutex mMsgLock; + static inline std::condition_variable mMsgCond; + static inline bool mQuit{false}; + + [[nodiscard]] + static bool quit() { - *out = *CONTAINING_RECORD(in, const WAVEFORMATEXTENSIBLE, Format); - out->Format.cbSize = sizeof(*out) - sizeof(out->Format); + auto lock = std::unique_lock{mMsgLock}; + mMsgCond.wait(lock, []{return mQuit;}); + return mQuit; } - else if(in->wFormatTag == WAVE_FORMAT_PCM) + +public: + static void messageHandler(std::promise *promise); +}; + +/* Manages a DeviceEnumHelper on its own thread, to track available devices. */ +void DeviceEnumHelper::messageHandler(std::promise *promise) +{ + TRACE("Starting watcher thread"); + + ComWrapper com{COINIT_MULTITHREADED}; + if(!com) { - out->Format = *in; - out->Format.cbSize = 0; - out->Samples.wValidBitsPerSample = out->Format.wBitsPerSample; - if(out->Format.nChannels == 1) - out->dwChannelMask = MONO; - else if(out->Format.nChannels == 2) - out->dwChannelMask = STEREO; - else - ERR("Unhandled PCM channel count: %d\n", out->Format.nChannels); - out->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + WARN("Failed to initialize COM: {:#x}", as_unsigned(com.status())); + promise->set_value(com.status()); + return; } - else if(in->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) - { + + auto helper = std::optional{}; + try { + auto devlock = DeviceListLock{gDeviceList}; + + auto hr = helper.emplace().init(); + promise->set_value(hr); + promise = nullptr; + if(FAILED(hr)) + return; + + auto defaultId = helper->probeDevices(eRender, devlock.getPlaybackList()); + if(!defaultId.empty()) devlock.setPlaybackDefaultId(defaultId); + + defaultId = helper->probeDevices(eCapture, devlock.getCaptureList()); + if(!defaultId.empty()) devlock.setCaptureDefaultId(defaultId); + + gInitDone.store(true, std::memory_order_relaxed); + } + catch(std::exception &e) { + ERR("Exception probing devices: {}", e.what()); + if(promise) + promise->set_value(E_FAIL); + return; + } + + TRACE("Watcher thread started"); + gInitCV.notify_all(); + + while(!quit()) { + /* Do nothing. */ + } +} + + +#if ALSOFT_UWP +struct DeviceHelper final : public IActivateAudioInterfaceCompletionHandler { + DeviceHelper() + { + mActiveClientEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); + } + ~DeviceHelper() + { + if(mActiveClientEvent != nullptr) + CloseHandle(mActiveClientEvent); + mActiveClientEvent = nullptr; + } + + template + auto as() noexcept -> T { return T{this}; } + + /** -------------------------- IUnknown ----------------------------- */ + std::atomic mRefCount{1}; + STDMETHODIMP_(ULONG) AddRef() noexcept override { return mRefCount.fetch_add(1u) + 1u; } + STDMETHODIMP_(ULONG) Release() noexcept override { return mRefCount.fetch_sub(1u) - 1u; } + + STDMETHODIMP QueryInterface(const IID& IId, void **UnknownPtrPtr) noexcept override + { + // Three rules of QueryInterface: + // https://docs.microsoft.com/en-us/windows/win32/com/rules-for-implementing-queryinterface + // 1. Objects must have identity. + // 2. The set of interfaces on an object instance must be static. + // 3. It must be possible to query successfully for any interface on an object from any other interface. + + // If ppvObject(the address) is nullptr, then this method returns E_POINTER. + if(!UnknownPtrPtr) + return E_POINTER; + + if(IId == __uuidof(IActivateAudioInterfaceCompletionHandler)) + { + *UnknownPtrPtr = as(); + AddRef(); + return S_OK; + } + else if(IId == __uuidof(IAgileObject) || IId == __uuidof(IUnknown)) + { + *UnknownPtrPtr = as(); + AddRef(); + return S_OK; + } + + // This method returns S_OK if the interface is supported, and E_NOINTERFACE otherwise. + *UnknownPtrPtr = nullptr; + return E_NOINTERFACE; + } + + /** ----------------------- IActivateAudioInterfaceCompletionHandler ------------ */ + HRESULT ActivateCompleted(IActivateAudioInterfaceAsyncOperation*) override + { + SetEvent(mActiveClientEvent); + + // Need to return S_OK + return S_OK; + } + + /** -------------------------- DeviceHelper ----------------------------- */ + [[nodiscard]] constexpr + auto init() -> HRESULT { return S_OK; } + + [[nodiscard]] + auto openDevice(const std::wstring &devid, EDataFlow flow, DeviceHandle &device) -> HRESULT + { + const auto deviceRole = Windows::Media::Devices::AudioDeviceRole::Default; + auto devIfPath = + devid.empty() ? (flow == eRender ? MediaDevice::GetDefaultAudioRenderId(deviceRole) + : MediaDevice::GetDefaultAudioCaptureId(deviceRole)) + : winrt::hstring(devid.c_str()); + if (devIfPath.empty()) + return E_POINTER; + + auto&& deviceInfo = DeviceInformation::CreateFromIdAsync(devIfPath, nullptr, + DeviceInformationKind::DeviceInterface).get(); + if(!deviceInfo) + return E_NOINTERFACE; + device = deviceInfo; + return S_OK; + } + + [[nodiscard]] + auto activateAudioClient(_In_ DeviceHandle &device, _In_ REFIID iid, void **ppv) -> HRESULT + { + ComPtr asyncOp; + HRESULT hr{ActivateAudioInterfaceAsync(device.Id().data(), iid, nullptr, this, + al::out_ptr(asyncOp))}; + if(FAILED(hr)) + return hr; + + /* I don't like waiting for INFINITE time, but the activate operation + * can take an indefinite amount of time since it can require user + * input. + */ + DWORD res{WaitForSingleObjectEx(mActiveClientEvent, INFINITE, FALSE)}; + if(res != WAIT_OBJECT_0) + { + ERR("WaitForSingleObjectEx error: {:#x}", res); + return E_FAIL; + } + + HRESULT hrActivateRes{E_FAIL}; + ComPtr punkAudioIface; + hr = asyncOp->GetActivateResult(&hrActivateRes, al::out_ptr(punkAudioIface)); + if(SUCCEEDED(hr)) hr = hrActivateRes; + if(FAILED(hr)) return hr; + + return punkAudioIface->QueryInterface(iid, ppv); + } + + HANDLE mActiveClientEvent{nullptr}; +}; + +#else + +struct DeviceHelper { + DeviceHelper() = default; + ~DeviceHelper() = default; + + [[nodiscard]] + auto init() -> HRESULT + { + HRESULT hr{CoCreateInstance(CLSID_MMDeviceEnumerator, nullptr, CLSCTX_INPROC_SERVER, + __uuidof(IMMDeviceEnumerator), al::out_ptr(mEnumerator))}; + if(FAILED(hr)) + WARN("Failed to create IMMDeviceEnumerator instance: {:#x}", as_unsigned(hr)); + return hr; + } + + [[nodiscard]] + auto openDevice(const std::wstring &devid, EDataFlow flow, DeviceHandle &device) const + -> HRESULT + { + HRESULT hr{E_FAIL}; + if(mEnumerator) + { + if(devid.empty()) + hr = mEnumerator->GetDefaultAudioEndpoint(flow, eMultimedia, al::out_ptr(device)); + else + hr = mEnumerator->GetDevice(devid.c_str(), al::out_ptr(device)); + } + return hr; + } + + [[nodiscard]] + static auto activateAudioClient(_In_ DeviceHandle &device, REFIID iid, void **ppv) -> HRESULT + { + if(iid == __uuidof(IAudioClient)) + { + /* Always (try) to activate an IAudioClient3, even if giving back + * an IAudioClient iface. This may(?) offer more features even if + * not using its new methods. + */ + auto ac3 = ComPtr{}; + const auto hr = device->Activate(__uuidof(IAudioClient3), CLSCTX_INPROC_SERVER, + nullptr, al::out_ptr(ac3)); + if(SUCCEEDED(hr)) + return ac3->QueryInterface(iid, ppv); + } + return device->Activate(iid, CLSCTX_INPROC_SERVER, nullptr, ppv); + } + + ComPtr mEnumerator{nullptr}; +}; +#endif + + +bool MakeExtensible(WAVEFORMATEXTENSIBLE *out, const WAVEFORMATEX *in) +{ + *out = WAVEFORMATEXTENSIBLE{}; + if(in->wFormatTag == WAVE_FORMAT_EXTENSIBLE) + { + *out = *CONTAINING_RECORD(in, const WAVEFORMATEXTENSIBLE, Format); + out->Format.cbSize = sizeof(*out) - sizeof(out->Format); + } + else if(in->wFormatTag == WAVE_FORMAT_PCM) + { out->Format = *in; out->Format.cbSize = 0; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ out->Samples.wValidBitsPerSample = out->Format.wBitsPerSample; if(out->Format.nChannels == 1) out->dwChannelMask = MONO; else if(out->Format.nChannels == 2) out->dwChannelMask = STEREO; else - ERR("Unhandled IEEE float channel count: %d\n", out->Format.nChannels); + ERR("Unhandled PCM channel count: {}", out->Format.nChannels); + out->SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + } + else if(in->wFormatTag == WAVE_FORMAT_IEEE_FLOAT) + { + out->Format = *in; + out->Format.cbSize = 0; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ + out->Samples.wValidBitsPerSample = out->Format.wBitsPerSample; + if(out->Format.nChannels == 1) + out->dwChannelMask = MONO; + else if(out->Format.nChannels == 2) + out->dwChannelMask = STEREO; + else + ERR("Unhandled IEEE float channel count: {}", out->Format.nChannels); out->SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; } else { - ERR("Unhandled format tag: 0x%04x\n", in->wFormatTag); + ERR("Unhandled format tag: {:#06x}", in->wFormatTag); return false; } return true; } -void TraceFormat(const char *msg, const WAVEFORMATEX *format) +void TraceFormat(const std::string_view msg, const WAVEFORMATEX *format) { constexpr size_t fmtex_extra_size{sizeof(WAVEFORMATEXTENSIBLE)-sizeof(WAVEFORMATEX)}; if(format->wFormatTag == WAVE_FORMAT_EXTENSIBLE && format->cbSize >= fmtex_extra_size) { - const WAVEFORMATEXTENSIBLE *fmtex{ - CONTAINING_RECORD(format, const WAVEFORMATEXTENSIBLE, Format)}; - TRACE("%s:\n" - " FormatTag = 0x%04x\n" - " Channels = %d\n" - " SamplesPerSec = %lu\n" - " AvgBytesPerSec = %lu\n" - " BlockAlign = %d\n" - " BitsPerSample = %d\n" - " Size = %d\n" - " Samples = %d\n" - " ChannelMask = 0x%lx\n" - " SubFormat = %s\n", + const auto *fmtex = CONTAINING_RECORD(format, const WAVEFORMATEXTENSIBLE, Format); + /* NOLINTBEGIN(cppcoreguidelines-pro-type-union-access) */ + TRACE("{}:\n" + " FormatTag = {:#06x}\n" + " Channels = {}\n" + " SamplesPerSec = {}\n" + " AvgBytesPerSec = {}\n" + " BlockAlign = {}\n" + " BitsPerSample = {}\n" + " Size = {}\n" + " Samples = {}\n" + " ChannelMask = {:#x}\n" + " SubFormat = {}", msg, fmtex->Format.wFormatTag, fmtex->Format.nChannels, fmtex->Format.nSamplesPerSec, fmtex->Format.nAvgBytesPerSec, fmtex->Format.nBlockAlign, fmtex->Format.wBitsPerSample, fmtex->Format.cbSize, fmtex->Samples.wReserved, fmtex->dwChannelMask, - GuidPrinter{fmtex->SubFormat}.c_str()); + GuidPrinter{fmtex->SubFormat}.str()); + /* NOLINTEND(cppcoreguidelines-pro-type-union-access) */ } else - TRACE("%s:\n" - " FormatTag = 0x%04x\n" - " Channels = %d\n" - " SamplesPerSec = %lu\n" - " AvgBytesPerSec = %lu\n" - " BlockAlign = %d\n" - " BitsPerSample = %d\n" - " Size = %d\n", + TRACE("{}:\n" + " FormatTag = {:#06x}\n" + " Channels = {}\n" + " SamplesPerSec = {}\n" + " AvgBytesPerSec = {}\n" + " BlockAlign = {}\n" + " BitsPerSample = {}\n" + " Size = {}", msg, format->wFormatTag, format->nChannels, format->nSamplesPerSec, format->nAvgBytesPerSec, format->nBlockAlign, format->wBitsPerSample, format->cbSize); } -enum class MsgType { - OpenDevice, - ResetDevice, - StartDevice, - StopDevice, - CloseDevice, - - QuitThread -}; - -constexpr const char *GetMessageTypeName(MsgType type) noexcept +/* Duplicates the first sample of each sample frame to the second sample, at + * half volume. Essentially converting mono to stereo. + */ +template +void DuplicateSamples(al::span insamples, size_t step) { - switch(type) - { - case MsgType::OpenDevice: return "Open Device"; - case MsgType::ResetDevice: return "Reset Device"; - case MsgType::StartDevice: return "Start Device"; - case MsgType::StopDevice: return "Stop Device"; - case MsgType::CloseDevice: return "Close Device"; - case MsgType::QuitThread: break; - } - return ""; -} - - -/* Proxy interface used by the message handler. */ -struct WasapiProxy { - virtual ~WasapiProxy() = default; - - virtual HRESULT openProxy(std::string_view name) = 0; - virtual void closeProxy() = 0; - - virtual HRESULT resetProxy() = 0; - virtual HRESULT startProxy() = 0; - virtual void stopProxy() = 0; - - struct Msg { - MsgType mType; - WasapiProxy *mProxy; - std::string_view mParam; - std::promise mPromise; - - explicit operator bool() const noexcept { return mType != MsgType::QuitThread; } - }; - static inline std::deque mMsgQueue; - static inline std::mutex mMsgQueueLock; - static inline std::condition_variable mMsgQueueCond; - - static inline std::optional sDeviceHelper; - - std::future pushMessage(MsgType type, std::string_view param={}) + auto samples = al::span{reinterpret_cast(insamples.data()), insamples.size()/sizeof(T)}; + if constexpr(std::is_floating_point_v) { - std::promise promise; - std::future future{promise.get_future()}; + for(size_t i{0};i < samples.size();i+=step) { - std::lock_guard _{mMsgQueueLock}; - mMsgQueue.emplace_back(Msg{type, this, param, std::move(promise)}); + const auto s = samples[i] * T{0.5}; + samples[i+1] = samples[i] = s; } - mMsgQueueCond.notify_one(); - return future; } - - static std::future pushMessageStatic(MsgType type) + else if constexpr(std::is_signed_v) { - std::promise promise; - std::future future{promise.get_future()}; + for(size_t i{0};i < samples.size();i+=step) { - std::lock_guard _{mMsgQueueLock}; - mMsgQueue.emplace_back(Msg{type, nullptr, {}, std::move(promise)}); + const auto s = samples[i] / 2; + samples[i+1] = samples[i] = T(s); } - mMsgQueueCond.notify_one(); - return future; } - - static Msg popMessage() + else { - std::unique_lock lock{mMsgQueueLock}; - mMsgQueueCond.wait(lock, []{return !mMsgQueue.empty();}); - Msg msg{std::move(mMsgQueue.front())}; - mMsgQueue.pop_front(); - return msg; + using ST = std::make_signed_t; + static constexpr auto SignBit = T{1u << (sizeof(T)*8 - 1)}; + for(size_t i{0};i < samples.size();i+=step) + { + const auto s = static_cast(samples[i]^SignBit) / 2; + samples[i+1] = samples[i] = T(s)^SignBit; + } } +} - static int messageHandler(std::promise *promise); -}; - -int WasapiProxy::messageHandler(std::promise *promise) +void DuplicateSamples(al::span insamples, DevFmtType sampletype, size_t step) { - TRACE("Starting message thread\n"); - - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) - { - WARN("Failed to initialize COM: 0x%08lx\n", hr); - promise->set_value(hr); - return 0; - } - - hr = sDeviceHelper.emplace().init(); - promise->set_value(hr); - promise = nullptr; - if(FAILED(hr)) - goto skip_loop; - + switch(sampletype) { - auto devlock = DeviceListLock{gDeviceList}; - auto defaultId = sDeviceHelper->probeDevices(eRender, devlock.getPlaybackList()); - if(!defaultId.empty()) devlock.setPlaybackDefaultId(defaultId); - defaultId = sDeviceHelper->probeDevices(eCapture, devlock.getCaptureList()); - if(!defaultId.empty()) devlock.setCaptureDefaultId(defaultId); + case DevFmtByte: return DuplicateSamples(insamples, step); + case DevFmtUByte: return DuplicateSamples(insamples, step); + case DevFmtShort: return DuplicateSamples(insamples, step); + case DevFmtUShort: return DuplicateSamples(insamples, step); + case DevFmtInt: return DuplicateSamples(insamples, step); + case DevFmtUInt: return DuplicateSamples(insamples, step); + case DevFmtFloat: return DuplicateSamples(insamples, step); } +} - TRACE("Starting message loop\n"); - while(Msg msg{popMessage()}) - { - TRACE("Got message \"%s\" (0x%04x, this=%p, param=\"%.*s\")\n", - GetMessageTypeName(msg.mType), static_cast(msg.mType), - static_cast(msg.mProxy), static_cast(msg.mParam.length()), - msg.mParam.data()); - - switch(msg.mType) - { - case MsgType::OpenDevice: - hr = msg.mProxy->openProxy(msg.mParam); - msg.mPromise.set_value(hr); - continue; - - case MsgType::ResetDevice: - hr = msg.mProxy->resetProxy(); - msg.mPromise.set_value(hr); - continue; - - case MsgType::StartDevice: - hr = msg.mProxy->startProxy(); - msg.mPromise.set_value(hr); - continue; - - case MsgType::StopDevice: - msg.mProxy->stopProxy(); - msg.mPromise.set_value(S_OK); - continue; - case MsgType::CloseDevice: - msg.mProxy->closeProxy(); - msg.mPromise.set_value(S_OK); - continue; +struct WasapiPlayback final : public BackendBase { + explicit WasapiPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + ~WasapiPlayback() override; - case MsgType::QuitThread: - break; - } - ERR("Unexpected message: %u\n", static_cast(msg.mType)); - msg.mPromise.set_value(E_FAIL); - } - TRACE("Message loop finished\n"); + struct PlainDevice { + ComPtr mClient{nullptr}; + ComPtr mRender{nullptr}; + }; + struct SpatialDevice { + ComPtr mClient{nullptr}; + ComPtr mRender{nullptr}; + AudioObjectType mStaticMask{}; + }; -skip_loop: - sDeviceHelper.reset(); - CoUninitialize(); + void mixerProc(PlainDevice &audio); + void mixerProc(SpatialDevice &audio); - return 0; -} + auto openProxy(const std::string_view name, DeviceHelper &helper, DeviceHandle &mmdev) + -> HRESULT; + void finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType); + auto initSpatial(DeviceHelper &helper, DeviceHandle &mmdev, SpatialDevice &audio) -> bool; + auto resetProxy(DeviceHelper &helper, DeviceHandle &mmdev, + std::variant &audiodev) -> HRESULT; -struct WasapiPlayback final : public BackendBase, WasapiProxy { - WasapiPlayback(DeviceBase *device) noexcept : BackendBase{device} { } - ~WasapiPlayback() override; + void proc_thread(std::string&& name); - int mixerProc(); - int mixerSpatialProc(); void open(std::string_view name) override; - HRESULT openProxy(std::string_view name) override; - void closeProxy() override; - bool reset() override; - HRESULT resetProxy() override; void start() override; - HRESULT startProxy() override; void stop() override; - void stopProxy() override; ClockLatency getClockLatency() override; - void prepareFormat(WAVEFORMATEXTENSIBLE &OutputType); - void finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType); - HRESULT mOpenStatus{E_FAIL}; - DeviceHandle mMMDev{nullptr}; + std::thread mProcThread; + std::mutex mProcMutex; + std::condition_variable mProcCond; + HRESULT mProcResult{E_FAIL}; - struct PlainDevice { - ComPtr mClient{nullptr}; - ComPtr mRender{nullptr}; + enum class ThreadState : uint8_t { + Initializing, + Waiting, + Playing, + Done }; - struct SpatialDevice { - ComPtr mClient{nullptr}; - ComPtr mRender{nullptr}; - AudioObjectType mStaticMask{}; + ThreadState mState{ThreadState::Initializing}; + + enum class ThreadAction : uint8_t { + Nothing, + Configure, + Play, + Quit }; - std::variant mAudio; + ThreadAction mAction{ThreadAction::Nothing}; + + + static inline DWORD sAvIndex{}; + HANDLE mNotifyEvent{nullptr}; - UINT32 mOrigBufferSize{}, mOrigUpdateSize{}; - std::unique_ptr mResampleBuffer{}; + UINT32 mOutBufferSize{}, mOutUpdateSize{}; + std::vector mResampleBuffer; uint mBufferFilled{0}; SampleConverterPtr mResampler; + bool mMonoUpsample{false}; + bool mExclusiveMode{false}; WAVEFORMATEXTENSIBLE mFormat{}; std::atomic mPadding{0u}; std::mutex mMutex; - std::atomic mKillNow{true}; - std::thread mThread; - - DEF_NEWDEL(WasapiPlayback) }; WasapiPlayback::~WasapiPlayback() { - if(SUCCEEDED(mOpenStatus)) - pushMessage(MsgType::CloseDevice).wait(); - mOpenStatus = E_FAIL; + if(mProcThread.joinable()) + { + { + auto plock = std::lock_guard{mProcMutex}; + mKillNow = true; + mAction = ThreadAction::Quit; + } + mProcCond.notify_all(); + mProcThread.join(); + } if(mNotifyEvent != nullptr) CloseHandle(mNotifyEvent); @@ -1111,163 +1258,194 @@ WasapiPlayback::~WasapiPlayback() } -FORCE_ALIGN int WasapiPlayback::mixerProc() +FORCE_ALIGN void WasapiPlayback::mixerProc(PlainDevice &audio) { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) - { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); - return 1; - } - - auto &audio = std::get(mAudio); + class PriorityControl { + const int mOldPriority; - SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + public: + PriorityControl() : mOldPriority{GetThreadPriority(GetCurrentThread())} + { + if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) + ERR("Failed to set priority level for thread"); + } + ~PriorityControl() + { SetThreadPriority(GetCurrentThread(), mOldPriority); } + }; + auto prioctrl = PriorityControl{}; const uint frame_size{mFormat.Format.nChannels * mFormat.Format.wBitsPerSample / 8u}; - const uint update_size{mOrigUpdateSize}; - const UINT32 buffer_len{mOrigBufferSize}; + const UINT32 buffer_len{mOutBufferSize}; + const void *resbufferptr{}; + + assert(buffer_len > 0); + +#ifdef AVRTAPI + /* TODO: "Audio" or "Pro Audio"? The suggestion is to use "Pro Audio" for + * device periods less than 10ms, and "Audio" for greater than or equal to + * 10ms. + */ + auto taskname = (mOutUpdateSize < mFormat.Format.nSamplesPerSec/100) ? L"Pro Audio" : L"Audio"; + auto avhandle = AvrtHandlePtr{AvSetMmThreadCharacteristicsW(taskname, &sAvIndex)}; +#endif + + auto prefilling = true; + mBufferFilled = 0; while(!mKillNow.load(std::memory_order_relaxed)) { - UINT32 written; - hr = audio.mClient->GetCurrentPadding(&written); - if(FAILED(hr)) - { - ERR("Failed to get padding: 0x%08lx\n", hr); - mDevice->handleDisconnect("Failed to retrieve buffer padding: 0x%08lx", hr); - break; - } - mPadding.store(written, std::memory_order_relaxed); - - uint len{buffer_len - written}; - if(len < update_size) + /* For exclusive mode, assume buffer_len sample frames are writable. + * The first pass will be a prefill of the buffer, while subsequent + * passes will only occur after notify events. + * IAudioClient::GetCurrentPadding shouldn't be used with exclusive + * streams that use event notifications, according to the docs, we + * should just assume a buffer length is writable after notification. + */ + auto written = UINT32{}; + if(!mExclusiveMode) { - DWORD res{WaitForSingleObjectEx(mNotifyEvent, 2000, FALSE)}; - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - continue; + if(auto hr = audio.mClient->GetCurrentPadding(&written); FAILED(hr)) + { + ERR("Failed to get padding: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failed to retrieve buffer padding: {:#x}", + as_unsigned(hr)); + break; + } + mPadding.store(written, std::memory_order_relaxed); } - BYTE *buffer; - hr = audio.mRender->GetBuffer(len, &buffer); - if(SUCCEEDED(hr)) + if(const auto len = uint{buffer_len - written}) { - if(mResampler) + auto buffer = LPBYTE{}; + auto hr = audio.mRender->GetBuffer(len, &buffer); + if(SUCCEEDED(hr)) { - std::lock_guard _{mMutex}; - for(UINT32 done{0};done < len;) + if(mResampler) { - if(mBufferFilled == 0) + auto dlock = std::lock_guard{mMutex}; + auto dst = al::span{buffer, size_t{len}*frame_size}; + for(UINT32 done{0};done < len;) { - mDevice->renderSamples(mResampleBuffer.get(), mDevice->UpdateSize, - mFormat.Format.nChannels); - mBufferFilled = mDevice->UpdateSize; + if(mBufferFilled == 0) + { + mDevice->renderSamples(mResampleBuffer.data(), mDevice->mUpdateSize, + mFormat.Format.nChannels); + resbufferptr = mResampleBuffer.data(); + mBufferFilled = mDevice->mUpdateSize; + } + + const auto got = mResampler->convert(&resbufferptr, &mBufferFilled, + dst.data(), len-done); + dst = dst.subspan(size_t{got}*frame_size); + done += got; } + mPadding.store(written + len, std::memory_order_relaxed); + } + else + { + auto dlock = std::lock_guard{mMutex}; + mDevice->renderSamples(buffer, len, mFormat.Format.nChannels); + mPadding.store(written + len, std::memory_order_relaxed); + } - const void *src{mResampleBuffer.get()}; - uint srclen{mBufferFilled}; - uint got{mResampler->convert(&src, &srclen, buffer, len-done)}; - buffer += got*frame_size; - done += got; - - mPadding.store(written + done, std::memory_order_relaxed); - if(srclen) - { - const char *bsrc{static_cast(src)}; - std::copy(bsrc, bsrc + srclen*frame_size, mResampleBuffer.get()); - } - mBufferFilled = srclen; + if(mMonoUpsample) + { + DuplicateSamples(al::span{buffer, size_t{len}*frame_size}, mDevice->FmtType, + mFormat.Format.nChannels); } + + hr = audio.mRender->ReleaseBuffer(len, 0); } - else + if(FAILED(hr)) { - std::lock_guard _{mMutex}; - mDevice->renderSamples(buffer, len, mFormat.Format.nChannels); - mPadding.store(written + len, std::memory_order_relaxed); + ERR("Failed to buffer data: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failed to send playback samples: {:#x}", + as_unsigned(hr)); + break; } - hr = audio.mRender->ReleaseBuffer(len, 0); } - if(FAILED(hr)) + + if(prefilling) { - ERR("Failed to buffer data: 0x%08lx\n", hr); - mDevice->handleDisconnect("Failed to send playback samples: 0x%08lx", hr); - break; + prefilling = false; + ResetEvent(mNotifyEvent); + if(auto hr = audio.mClient->Start(); FAILED(hr)) + { + ERR("Failed to start audio client: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failed to start audio client: {:#x}", + as_unsigned(hr)); + break; + } } + + if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 2000, FALSE)}; res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: {:#x}", res); } mPadding.store(0u, std::memory_order_release); - - CoUninitialize(); - return 0; + audio.mClient->Stop(); } -FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() +FORCE_ALIGN void WasapiPlayback::mixerProc(SpatialDevice &audio) { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) - { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); - return 1; - } - - auto &audio = std::get(mAudio); + class PriorityControl { + int mOldPriority; + public: + PriorityControl() : mOldPriority{GetThreadPriority(GetCurrentThread())} + { + if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) + ERR("Failed to set priority level for thread"); + } + ~PriorityControl() + { SetThreadPriority(GetCurrentThread(), mOldPriority); } + }; + auto prioctrl = PriorityControl{}; - SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); +#ifdef AVRTAPI + auto taskname = (mOutUpdateSize < mFormat.Format.nSamplesPerSec/100) ? L"Pro Audio" : L"Audio"; + auto avhandle = AvrtHandlePtr{AvSetMmThreadCharacteristicsW(taskname, &sAvIndex)}; +#endif std::vector> channels; - std::vector buffers; - std::vector resbuffers; + std::vector buffers; + std::vector resbuffers; std::vector tmpbuffers; /* TODO: Set mPadding appropriately. There doesn't seem to be a way to * update it dynamically based on the stream, so a fixed size may be the * best we can do. */ - mPadding.store(mDevice->BufferSize-mDevice->UpdateSize, std::memory_order_release); + mPadding.store(mOutBufferSize-mOutUpdateSize, std::memory_order_release); + mBufferFilled = 0; + auto firstupdate = true; while(!mKillNow.load(std::memory_order_relaxed)) { - if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 1000, FALSE)}; res != WAIT_OBJECT_0) - { - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); - - hr = audio.mRender->Reset(); - if(FAILED(hr)) - { - ERR("ISpatialAudioObjectRenderStream::Reset failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("Device lost: 0x%08lx", hr); - break; - } - } - UINT32 dynamicCount{}, framesToDo{}; - hr = audio.mRender->BeginUpdatingAudioObjects(&dynamicCount, &framesToDo); + HRESULT hr{audio.mRender->BeginUpdatingAudioObjects(&dynamicCount, &framesToDo)}; if(SUCCEEDED(hr)) { if(channels.empty()) UNLIKELY { - auto flags = as_unsigned(audio.mStaticMask); + auto flags = as_unsigned(al::to_underlying(audio.mStaticMask)); channels.reserve(as_unsigned(al::popcount(flags))); while(flags) { auto id = decltype(flags){1} << al::countr_zero(flags); flags &= ~id; - channels.emplace_back(); audio.mRender->ActivateSpatialAudioObject(static_cast(id), - al::out_ptr(channels.back())); + al::out_ptr(channels.emplace_back())); } buffers.resize(channels.size()); if(mResampler) { tmpbuffers.resize(buffers.size()); resbuffers.resize(buffers.size()); + auto bufptr = mResampleBuffer.begin(); for(size_t i{0};i < tmpbuffers.size();++i) - resbuffers[i] = reinterpret_cast(mResampleBuffer.get()) + - mDevice->UpdateSize*i; + { + resbuffers[i] = al::to_address(bufptr); + bufptr += ptrdiff_t(mDevice->mUpdateSize*sizeof(float)); + } } } @@ -1275,32 +1453,32 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() * update, unfortunately. */ std::transform(channels.cbegin(), channels.cend(), buffers.begin(), - [](const ComPtr &obj) -> float* + [](const ComPtr &obj) -> void* { - BYTE *buffer{}; - UINT32 size{}; + auto buffer = LPBYTE{}; + auto size = UINT32{}; obj->GetBuffer(&buffer, &size); - return reinterpret_cast(buffer); + return buffer; }); if(!mResampler) mDevice->renderSamples(buffers, framesToDo); else { - std::lock_guard _{mMutex}; + std::lock_guard dlock{mMutex}; for(UINT32 pos{0};pos < framesToDo;) { if(mBufferFilled == 0) { - mDevice->renderSamples(resbuffers, mDevice->UpdateSize); + mDevice->renderSamples(resbuffers, mDevice->mUpdateSize); std::copy(resbuffers.cbegin(), resbuffers.cend(), tmpbuffers.begin()); - mBufferFilled = mDevice->UpdateSize; + mBufferFilled = mDevice->mUpdateSize; } const uint got{mResampler->convertPlanar(tmpbuffers.data(), &mBufferFilled, - reinterpret_cast(buffers.data()), framesToDo-pos)}; + buffers.data(), framesToDo-pos)}; for(auto &buf : buffers) - buf += got; + buf = static_cast(buf) + got; /* NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ pos += got; } } @@ -1308,216 +1486,217 @@ FORCE_ALIGN int WasapiPlayback::mixerSpatialProc() hr = audio.mRender->EndUpdatingAudioObjects(); } + if(firstupdate) + { + firstupdate = false; + ResetEvent(mNotifyEvent); + hr = audio.mRender->Start(); + if(FAILED(hr)) + { + ERR("Failed to start spatial audio stream: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failed to start spatial audio stream: {:#x}", + as_unsigned(hr)); + return; + } + } + + if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 1000, FALSE)}; res != WAIT_OBJECT_0) + { + ERR("WaitForSingleObjectEx error: {:#x}", res); + + hr = audio.mRender->Reset(); + if(FAILED(hr)) + { + ERR("ISpatialAudioObjectRenderStream::Reset failed: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Device lost: {:#x}", as_unsigned(hr)); + break; + } + firstupdate = true; + } + if(FAILED(hr)) - ERR("Failed to update playback objects: 0x%08lx\n", hr); + ERR("Failed to update playback objects: {:#x}", as_unsigned(hr)); } mPadding.store(0u, std::memory_order_release); + audio.mRender->Stop(); + audio.mRender->Reset(); +} + + +void WasapiPlayback::proc_thread(std::string&& name) +try { + auto com = ComWrapper{COINIT_MULTITHREADED}; + if(!com) + { + const auto hr = as_unsigned(com.status()); + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: {:#x}", hr); + mDevice->handleDisconnect("COM init failed: {:#x}", hr); + + auto plock = std::lock_guard{mProcMutex}; + mProcResult = com.status(); + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + if(!gInitDone.load(std::memory_order_relaxed)) + { + auto devlock = DeviceListLock{gDeviceList}; + gInitCV.wait(devlock, []() -> bool { return gInitDone; }); + } + + auto helper = DeviceHelper{}; + if(HRESULT hr{helper.init()}; FAILED(hr)) + { + mDevice->handleDisconnect("Helper init failed: {:#x}", as_unsigned(hr)); + + auto plock = std::lock_guard{mProcMutex}; + mProcResult = hr; + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + althrd_setname(GetMixerThreadName()); + + auto mmdev = DeviceHandle{nullptr}; + if(auto hr = openProxy(name, helper, mmdev); FAILED(hr)) + { + auto plock = std::lock_guard{mProcMutex}; + mProcResult = hr; + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + auto audiodev = std::variant{}; + + auto plock = std::unique_lock{mProcMutex}; + mProcResult = S_OK; + while(mState != ThreadState::Done) + { + mAction = ThreadAction::Nothing; + mState = ThreadState::Waiting; + mProcCond.notify_all(); + + mProcCond.wait(plock, [this]() noexcept { return mAction != ThreadAction::Nothing; }); + switch(mAction) + { + case ThreadAction::Nothing: + break; - CoUninitialize(); - return 0; + case ThreadAction::Configure: + { + plock.unlock(); + const auto hr = resetProxy(helper, mmdev, audiodev); + plock.lock(); + mProcResult = hr; + } + break; + + case ThreadAction::Play: + mKillNow.store(false, std::memory_order_release); + + mAction = ThreadAction::Nothing; + mState = ThreadState::Playing; + mProcResult = S_OK; + plock.unlock(); + mProcCond.notify_all(); + + std::visit([this](auto &audio) -> void { mixerProc(audio); }, audiodev); + + plock.lock(); + break; + + case ThreadAction::Quit: + mAction = ThreadAction::Nothing; + mState = ThreadState::Done; + mProcCond.notify_all(); + break; + } + } +} +catch(...) { + auto plock = std::lock_guard{mProcMutex}; + mProcResult = E_FAIL; + mAction = ThreadAction::Nothing; + mState = ThreadState::Done; + mProcCond.notify_all(); } void WasapiPlayback::open(std::string_view name) { - if(SUCCEEDED(mOpenStatus)) - throw al::backend_exception{al::backend_error::DeviceError, - "Unexpected duplicate open call"}; - mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); if(mNotifyEvent == nullptr) { - ERR("Failed to create notify events: %lu\n", GetLastError()); + ERR("Failed to create notify events: {}", GetLastError()); throw al::backend_exception{al::backend_error::DeviceError, "Failed to create notify events"}; } - if(name.length() >= DevNameHeadLen - && std::strncmp(name.data(), DevNameHead, DevNameHeadLen) == 0) - { - name = name.substr(DevNameHeadLen); - } + mProcThread = std::thread{&WasapiPlayback::proc_thread, this, std::string{name}}; - mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); - if(FAILED(mOpenStatus)) - throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", - mOpenStatus}; + auto plock = std::unique_lock{mProcMutex}; + mProcCond.wait(plock, [this]() noexcept { return mState != ThreadState::Initializing; }); + + if(mProcResult == E_NOTFOUND) + throw al::backend_exception{al::backend_error::NoDevice, "Device \"{}\" not found", name}; + if(FAILED(mProcResult) || mState == ThreadState::Done) + throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: {:#x}", + as_unsigned(mProcResult)}; } -HRESULT WasapiPlayback::openProxy(std::string_view name) +auto WasapiPlayback::openProxy(const std::string_view name, DeviceHelper &helper, + DeviceHandle &mmdev) -> HRESULT { - std::string devname; - std::wstring devid; + auto devname = std::string{}; + auto devid = std::wstring{}; if(!name.empty()) { auto devlock = DeviceListLock{gDeviceList}; auto list = al::span{devlock.getPlaybackList()}; auto iter = std::find_if(list.cbegin(), list.cend(), [name](const DevMap &entry) -> bool - { return entry.name == name || entry.endpoint_guid == name; }); + { return entry.name == name || al::case_compare(entry.endpoint_guid, name) == 0; }); if(iter == list.cend()) { const std::wstring wname{utf8_to_wstr(name)}; iter = std::find_if(list.cbegin(), list.cend(), - [&wname](const DevMap &entry) -> bool - { return entry.devid == wname; }); - } - if(iter == list.cend()) - { - WARN("Failed to find device name matching \"%.*s\"\n", static_cast(name.length()), - name.data()); - return E_FAIL; - } - devname = iter->name; - devid = iter->devid; - } - - HRESULT hr{sDeviceHelper->openDevice(devid, eRender, mMMDev)}; - if(FAILED(hr)) - { - WARN("Failed to open device \"%s\"\n", devname.empty() ? "(default)" : devname.c_str()); - return hr; - } - if(!devname.empty()) - mDevice->DeviceName = DevNameHead + std::move(devname); - else - mDevice->DeviceName = DevNameHead + GetDeviceNameAndGuid(mMMDev).first; - - return S_OK; -} - -void WasapiPlayback::closeProxy() -{ - mAudio.emplace(); - mMMDev = nullptr; -} - - -void WasapiPlayback::prepareFormat(WAVEFORMATEXTENSIBLE &OutputType) -{ - bool isRear51{false}; - - if(!mDevice->Flags.test(FrequencyRequest)) - mDevice->Frequency = OutputType.Format.nSamplesPerSec; - if(!mDevice->Flags.test(ChannelsRequest)) - { - /* If not requesting a channel configuration, auto-select given what - * fits the mask's lsb (to ensure no gaps in the output channels). If - * there's no mask, we can only assume mono or stereo. - */ - const uint32_t chancount{OutputType.Format.nChannels}; - const DWORD chanmask{OutputType.dwChannelMask}; - if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) - mDevice->FmtChans = DevFmtX714; - else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) - mDevice->FmtChans = DevFmtX71; - else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) - mDevice->FmtChans = DevFmtX61; - else if(chancount >= 6 && (chanmask&X51Mask) == X5DOT1) - mDevice->FmtChans = DevFmtX51; - else if(chancount >= 6 && (chanmask&X51RearMask) == X5DOT1REAR) - { - mDevice->FmtChans = DevFmtX51; - isRear51 = true; - } - else if(chancount >= 4 && (chanmask&QuadMask) == QUAD) - mDevice->FmtChans = DevFmtQuad; - else if(chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)) - mDevice->FmtChans = DevFmtStereo; - else if(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)) - mDevice->FmtChans = DevFmtMono; - else - ERR("Unhandled channel config: %d -- 0x%08lx\n", chancount, chanmask); - } - else - { - const uint32_t chancount{OutputType.Format.nChannels}; - const DWORD chanmask{OutputType.dwChannelMask}; - isRear51 = (chancount == 6 && (chanmask&X51RearMask) == X5DOT1REAR); + [&wname](const DevMap &entry) -> bool + { return al::case_compare(entry.devid, wname) == 0; }); + } + if(iter == list.cend()) + { + WARN("Failed to find device name matching \"{}\"", name); + return E_NOTFOUND; + } + devname = iter->name; + devid = iter->devid; } - OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; - switch(mDevice->FmtChans) - { - case DevFmtMono: - OutputType.Format.nChannels = 1; - OutputType.dwChannelMask = MONO; - break; - case DevFmtAmbi3D: - mDevice->FmtChans = DevFmtStereo; - /*fall-through*/ - case DevFmtStereo: - OutputType.Format.nChannels = 2; - OutputType.dwChannelMask = STEREO; - break; - case DevFmtQuad: - OutputType.Format.nChannels = 4; - OutputType.dwChannelMask = QUAD; - break; - case DevFmtX51: - OutputType.Format.nChannels = 6; - OutputType.dwChannelMask = isRear51 ? X5DOT1REAR : X5DOT1; - break; - case DevFmtX61: - OutputType.Format.nChannels = 7; - OutputType.dwChannelMask = X6DOT1; - break; - case DevFmtX71: - case DevFmtX3D71: - OutputType.Format.nChannels = 8; - OutputType.dwChannelMask = X7DOT1; - break; - case DevFmtX714: - OutputType.Format.nChannels = 12; - OutputType.dwChannelMask = X7DOT1DOT4; - break; - } - switch(mDevice->FmtType) + if(HRESULT hr{helper.openDevice(devid, eRender, mmdev)}; FAILED(hr)) { - case DevFmtByte: - mDevice->FmtType = DevFmtUByte; - /* fall-through */ - case DevFmtUByte: - OutputType.Format.wBitsPerSample = 8; - OutputType.Samples.wValidBitsPerSample = 8; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtUShort: - mDevice->FmtType = DevFmtShort; - /* fall-through */ - case DevFmtShort: - OutputType.Format.wBitsPerSample = 16; - OutputType.Samples.wValidBitsPerSample = 16; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtUInt: - mDevice->FmtType = DevFmtInt; - /* fall-through */ - case DevFmtInt: - OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; - break; - case DevFmtFloat: - OutputType.Format.wBitsPerSample = 32; - OutputType.Samples.wValidBitsPerSample = 32; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; - break; + WARN("Failed to open device \"{}\": {:#x}", devname.empty() + ? "(default)"sv : std::string_view{devname}, as_unsigned(hr)); + return hr; } - OutputType.Format.nSamplesPerSec = mDevice->Frequency; + if(!devname.empty()) + mDeviceName = std::move(devname); + else + mDeviceName = GetDeviceNameAndGuid(mmdev).mName; - OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nChannels * - OutputType.Format.wBitsPerSample / 8); - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec * - OutputType.Format.nBlockAlign; + return S_OK; } + void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) { - if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "allow-resampler", true)) - mDevice->Frequency = OutputType.Format.nSamplesPerSec; + if(!GetConfigValueBool(mDevice->mDeviceName, "wasapi", "allow-resampler", true)) + mDevice->mSampleRate = uint(OutputType.Format.nSamplesPerSec); else - mDevice->Frequency = minu(mDevice->Frequency, OutputType.Format.nSamplesPerSec); + mDevice->mSampleRate = std::min(mDevice->mSampleRate, + uint(OutputType.Format.nSamplesPerSec)); const uint32_t chancount{OutputType.Format.nChannels}; const DWORD chanmask{OutputType.dwChannelMask}; @@ -1535,6 +1714,12 @@ void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) { case DevFmtMono: chansok = (chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)); + if(!chansok && chancount >= 2 && (chanmask&StereoMask) == STEREO) + { + /* Mono rendering with stereo+ output is handled specially. */ + chansok = true; + mMonoUpsample = true; + } break; case DevFmtStereo: chansok = (chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)); @@ -1555,6 +1740,7 @@ void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) break; case DevFmtX714: chansok = (chancount >= 12 && ((chanmask&X714Mask) == X7DOT1DOT4 || !chanmask)); + case DevFmtX7144: case DevFmtAmbi3D: break; } @@ -1578,7 +1764,7 @@ void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) mDevice->FmtChans = DevFmtMono; else { - ERR("Unhandled extensible channels: %d -- 0x%08lx\n", OutputType.Format.nChannels, + ERR("Unhandled extensible channels: {} -- {:#08x}", OutputType.Format.nChannels, OutputType.dwChannelMask); mDevice->FmtChans = DevFmtStereo; OutputType.Format.nChannels = 2; @@ -1607,381 +1793,547 @@ void WasapiPlayback::finalizeFormat(WAVEFORMATEXTENSIBLE &OutputType) } else { - ERR("Unhandled format sub-type: %s\n", GuidPrinter{OutputType.SubFormat}.c_str()); + ERR("Unhandled format sub-type: {}", GuidPrinter{OutputType.SubFormat}.str()); mDevice->FmtType = DevFmtShort; if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE) OutputType.Format.wFormatTag = WAVE_FORMAT_PCM; OutputType.Format.wBitsPerSample = 16; OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; } + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; } -bool WasapiPlayback::reset() +auto WasapiPlayback::initSpatial(DeviceHelper &helper, DeviceHandle &mmdev, SpatialDevice &audio) + -> bool { - HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; + HRESULT hr{helper.activateAudioClient(mmdev, __uuidof(ISpatialAudioClient), + al::out_ptr(audio.mClient))}; if(FAILED(hr)) - throw al::backend_exception{al::backend_error::DeviceError, "0x%08lx", hr}; - return true; -} - -HRESULT WasapiPlayback::resetProxy() -{ - if(GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "spatial-api", false)) { - auto &audio = mAudio.emplace(); - HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(ISpatialAudioClient), - al::out_ptr(audio.mClient))}; - if(FAILED(hr)) - { - ERR("Failed to activate spatial audio client: 0x%08lx\n", hr); - goto no_spatial; - } + ERR("Failed to activate spatial audio client: {:#x}", as_unsigned(hr)); + return false; + } - ComPtr fmtenum; - hr = audio.mClient->GetSupportedAudioObjectFormatEnumerator(al::out_ptr(fmtenum)); - if(FAILED(hr)) - { - ERR("Failed to get format enumerator: 0x%08lx\n", hr); - goto no_spatial; - } + ComPtr fmtenum; + hr = audio.mClient->GetSupportedAudioObjectFormatEnumerator(al::out_ptr(fmtenum)); + if(FAILED(hr)) + { + ERR("Failed to get format enumerator: {:#x}", as_unsigned(hr)); + return false; + } - UINT32 fmtcount{}; - hr = fmtenum->GetCount(&fmtcount); - if(FAILED(hr) || fmtcount == 0) - { - ERR("Failed to get format count: 0x%08lx\n", hr); - goto no_spatial; - } + UINT32 fmtcount{}; + hr = fmtenum->GetCount(&fmtcount); + if(FAILED(hr) || fmtcount == 0) + { + ERR("Failed to get format count: {:#08x}", as_unsigned(hr)); + return false; + } - WAVEFORMATEX *preferredFormat{}; - hr = fmtenum->GetFormat(0, &preferredFormat); - if(FAILED(hr)) - { - ERR("Failed to get preferred format: 0x%08lx\n", hr); - goto no_spatial; - } - TraceFormat("Preferred mix format", preferredFormat); + WAVEFORMATEX *preferredFormat{}; + hr = fmtenum->GetFormat(0, &preferredFormat); + if(FAILED(hr)) + { + ERR("Failed to get preferred format: {:#x}", as_unsigned(hr)); + return false; + } + TraceFormat("Preferred mix format", preferredFormat); - UINT32 maxFrames{}; - hr = audio.mClient->GetMaxFrameCount(preferredFormat, &maxFrames); + UINT32 maxFrames{}; + hr = audio.mClient->GetMaxFrameCount(preferredFormat, &maxFrames); + if(FAILED(hr)) + ERR("Failed to get max frames: {:#x}", as_unsigned(hr)); + else + TRACE("Max sample frames: {}", maxFrames); + for(UINT32 i{1};i < fmtcount;++i) + { + WAVEFORMATEX *otherFormat{}; + hr = fmtenum->GetFormat(i, &otherFormat); if(FAILED(hr)) - ERR("Failed to get max frames: 0x%08lx\n", hr); + ERR("Failed to get format {}: {:#x}", i+1, as_unsigned(hr)); else - TRACE("Max sample frames: %u\n", maxFrames); - for(UINT32 i{1};i < fmtcount;++i) { - WAVEFORMATEX *otherFormat{}; - hr = fmtenum->GetFormat(i, &otherFormat); + TraceFormat("Other mix format", otherFormat); + UINT32 otherMaxFrames{}; + hr = audio.mClient->GetMaxFrameCount(otherFormat, &otherMaxFrames); if(FAILED(hr)) - ERR("Failed to format %u: 0x%08lx\n", i+1, hr); + ERR("Failed to get max frames: {:#x}", as_unsigned(hr)); else - { - TraceFormat("Other mix format", otherFormat); - UINT32 otherMaxFrames{}; - hr = audio.mClient->GetMaxFrameCount(otherFormat, &otherMaxFrames); - if(FAILED(hr)) - ERR("Failed to get max frames: 0x%08lx\n", hr); - else - TRACE("Max sample frames: %u\n", otherMaxFrames); - } + TRACE("Max sample frames: {}", otherMaxFrames); } + } - WAVEFORMATEXTENSIBLE OutputType; - if(!MakeExtensible(&OutputType, preferredFormat)) - goto no_spatial; + WAVEFORMATEXTENSIBLE OutputType; + if(!MakeExtensible(&OutputType, preferredFormat)) + return false; - /* Force 32-bit float. This is currently required for planar output. */ - if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE - && OutputType.Format.wFormatTag != WAVE_FORMAT_IEEE_FLOAT) - { - OutputType.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; - OutputType.Format.cbSize = 0; - } - if(OutputType.Format.wBitsPerSample != 32) - { - OutputType.Format.nAvgBytesPerSec = OutputType.Format.nAvgBytesPerSec * 32u - / OutputType.Format.wBitsPerSample; - OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nBlockAlign * 32 - / OutputType.Format.wBitsPerSample); - OutputType.Format.wBitsPerSample = 32; - } - OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; - OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + /* This seems to be the format of each "object", which should be mono. */ + if(!(OutputType.Format.nChannels == 1 + && (OutputType.dwChannelMask == MONO || !OutputType.dwChannelMask))) + ERR("Unhandled channel config: {} -- {:#08x}", OutputType.Format.nChannels, + OutputType.dwChannelMask); - /* Match the output rate if not requesting anything specific. */ - if(!mDevice->Flags.test(FrequencyRequest)) - mDevice->Frequency = OutputType.Format.nSamplesPerSec; - - bool isRear51{false}; - if(!mDevice->Flags.test(ChannelsRequest)) - { - const uint32_t chancount{OutputType.Format.nChannels}; - const DWORD chanmask{OutputType.dwChannelMask}; - if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) - mDevice->FmtChans = DevFmtX714; - else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) - mDevice->FmtChans = DevFmtX71; - else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) - mDevice->FmtChans = DevFmtX61; - else if(chancount >= 6 && (chanmask&X51Mask) == X5DOT1) - mDevice->FmtChans = DevFmtX51; - else if(chancount >= 6 && (chanmask&X51RearMask) == X5DOT1REAR) - { - mDevice->FmtChans = DevFmtX51; - isRear51 = true; - } - else if(chancount >= 4 && (chanmask&QuadMask) == QUAD) - mDevice->FmtChans = DevFmtQuad; - else if(chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)) - mDevice->FmtChans = DevFmtStereo; - /* HACK: Don't autoselect mono. Wine returns this and makes the - * audio terrible. - */ - else if(!(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask))) - ERR("Unhandled channel config: %d -- 0x%08lx\n", chancount, chanmask); - } - else + /* Force 32-bit float. This is currently required for planar output. */ + if(OutputType.Format.wFormatTag != WAVE_FORMAT_EXTENSIBLE + && OutputType.Format.wFormatTag != WAVE_FORMAT_IEEE_FLOAT) + { + OutputType.Format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + OutputType.Format.cbSize = 0; + } + if(OutputType.Format.wBitsPerSample != 32) + { + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nAvgBytesPerSec * 32u + / OutputType.Format.wBitsPerSample; + OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nBlockAlign * 32 + / OutputType.Format.wBitsPerSample); + OutputType.Format.wBitsPerSample = 32; + } + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + + /* Match the output rate if not requesting anything specific. */ + if(!mDevice->Flags.test(FrequencyRequest)) + mDevice->mSampleRate = OutputType.Format.nSamplesPerSec; + + auto getTypeMask = [](DevFmtChannels chans) noexcept + { + switch(chans) { - const uint32_t chancount{OutputType.Format.nChannels}; - const DWORD chanmask{OutputType.dwChannelMask}; - isRear51 = (chancount == 6 && (chanmask&X51RearMask) == X5DOT1REAR); + case DevFmtMono: return ChannelMask_Mono; + case DevFmtStereo: return ChannelMask_Stereo; + case DevFmtQuad: return ChannelMask_Quad; + case DevFmtX51: return ChannelMask_X51; + case DevFmtX61: return ChannelMask_X61; + case DevFmtX3D71: [[fallthrough]]; + case DevFmtX71: return ChannelMask_X71; + case DevFmtX714: return ChannelMask_X714; + case DevFmtX7144: return ChannelMask_X7144; + case DevFmtAmbi3D: + break; } + return ChannelMask_Stereo; + }; - auto getTypeMask = [isRear51](DevFmtChannels chans) noexcept - { - switch(chans) - { - case DevFmtMono: return ChannelMask_Mono; - case DevFmtStereo: return ChannelMask_Stereo; - case DevFmtQuad: return ChannelMask_Quad; - case DevFmtX51: return isRear51 ? ChannelMask_X51Rear : ChannelMask_X51; - case DevFmtX61: return ChannelMask_X61; - case DevFmtX3D71: - case DevFmtX71: return ChannelMask_X71; - case DevFmtX714: return ChannelMask_X714; - case DevFmtAmbi3D: - break; - } - return ChannelMask_Stereo; - }; + SpatialAudioObjectRenderStreamActivationParams streamParams{}; + streamParams.ObjectFormat = &OutputType.Format; + streamParams.StaticObjectTypeMask = getTypeMask(mDevice->FmtChans); + streamParams.Category = AudioCategory_Media; + streamParams.EventHandle = mNotifyEvent; - SpatialAudioObjectRenderStreamActivationParams streamParams{}; - streamParams.ObjectFormat = &OutputType.Format; - streamParams.StaticObjectTypeMask = getTypeMask(mDevice->FmtChans); - streamParams.Category = AudioCategory_Media; - streamParams.EventHandle = mNotifyEvent; + PropVariant paramProp{}; + paramProp.setBlob({reinterpret_cast(&streamParams), sizeof(streamParams)}); - PropVariant paramProp{}; - paramProp->vt = VT_BLOB; - paramProp->blob.cbSize = sizeof(streamParams); - paramProp->blob.pBlobData = reinterpret_cast(&streamParams); + hr = audio.mClient->ActivateSpatialAudioStream(paramProp.get(), + __uuidof(ISpatialAudioObjectRenderStream), al::out_ptr(audio.mRender)); + if(FAILED(hr)) + { + ERR("Failed to activate spatial audio stream: {:#x}", as_unsigned(hr)); + return false; + } - hr = audio.mClient->ActivateSpatialAudioStream(paramProp.get(), - __uuidof(ISpatialAudioObjectRenderStream), al::out_ptr(audio.mRender)); - if(FAILED(hr)) - { - ERR("Failed to activate spatial audio stream: 0x%08lx\n", hr); - goto no_spatial; - } + audio.mStaticMask = streamParams.StaticObjectTypeMask; + mFormat = OutputType; - audio.mStaticMask = streamParams.StaticObjectTypeMask; - mFormat = OutputType; + mDevice->FmtType = DevFmtFloat; + mDevice->Flags.reset(DirectEar).set(Virtualization); + if(streamParams.StaticObjectTypeMask == ChannelMask_Stereo) + mDevice->FmtChans = DevFmtStereo; + if(!GetConfigValueBool(mDevice->mDeviceName, "wasapi", "allow-resampler", true)) + mDevice->mSampleRate = uint(OutputType.Format.nSamplesPerSec); + else + mDevice->mSampleRate = std::min(mDevice->mSampleRate, + uint(OutputType.Format.nSamplesPerSec)); - mDevice->FmtType = DevFmtFloat; - mDevice->Flags.reset(DirectEar).set(Virtualization); - if(streamParams.StaticObjectTypeMask == ChannelMask_Stereo) - mDevice->FmtChans = DevFmtStereo; - if(!GetConfigValueBool(mDevice->DeviceName.c_str(), "wasapi", "allow-resampler", true)) - mDevice->Frequency = OutputType.Format.nSamplesPerSec; - else - mDevice->Frequency = minu(mDevice->Frequency, OutputType.Format.nSamplesPerSec); - - setDefaultWFXChannelOrder(); - - /* FIXME: Get the real update and buffer size. Presumably the actual - * device is configured once ActivateSpatialAudioStream succeeds, and - * an IAudioClient from the same IMMDevice accesses the same device - * configuration. This isn't obviously correct, but for now assume - * IAudioClient::GetDevicePeriod returns the current device period time - * that ISpatialAudioObjectRenderStream will try to wake up at. - * - * Unfortunately this won't get the buffer size of the - * ISpatialAudioObjectRenderStream, so we only assume there's two - * periods. - */ - mOrigUpdateSize = mDevice->UpdateSize; - mOrigBufferSize = mOrigUpdateSize*2; - ReferenceTime per_time{ReferenceTime{seconds{mDevice->UpdateSize}} / mDevice->Frequency}; + setDefaultWFXChannelOrder(); - ComPtr tmpClient; - hr = sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), - al::out_ptr(tmpClient)); - if(FAILED(hr)) - ERR("Failed to activate audio client: 0x%08lx\n", hr); - else - { - hr = tmpClient->GetDevicePeriod(&reinterpret_cast(per_time), nullptr); - if(FAILED(hr)) - ERR("Failed to get device period: 0x%08lx\n", hr); - else - { - mOrigUpdateSize = RefTime2Samples(per_time, mFormat.Format.nSamplesPerSec); - mOrigBufferSize = mOrigUpdateSize*2; - } - } - tmpClient = nullptr; + /* TODO: ISpatialAudioClient::GetMaxFrameCount returns the maximum number + * of frames per processing pass, which is ostensibly the period size. This + * should be checked on a real Windows system. + * + * In either case, this won't get the buffer size of the + * ISpatialAudioObjectRenderStream, so we only assume there's two periods. + */ + mOutUpdateSize = maxFrames; + mOutBufferSize = mOutUpdateSize*2; - mDevice->UpdateSize = RefTime2Samples(per_time, mDevice->Frequency); - mDevice->BufferSize = mDevice->UpdateSize*2; + mDevice->mUpdateSize = static_cast((uint64_t{mOutUpdateSize}*mDevice->mSampleRate + + (mFormat.Format.nSamplesPerSec-1)) / mFormat.Format.nSamplesPerSec); + mDevice->mBufferSize = mDevice->mUpdateSize*2; - mResampler = nullptr; - mResampleBuffer = nullptr; - mBufferFilled = 0; - if(mDevice->Frequency != mFormat.Format.nSamplesPerSec) - { - const auto flags = as_unsigned(streamParams.StaticObjectTypeMask); - const auto channelCount = as_unsigned(al::popcount(flags)); - mResampler = SampleConverter::Create(mDevice->FmtType, mDevice->FmtType, - channelCount, mDevice->Frequency, mFormat.Format.nSamplesPerSec, - Resampler::FastBSinc24); - mResampleBuffer = std::make_unique(size_t{mDevice->UpdateSize} * channelCount * - mFormat.Format.wBitsPerSample / 8); + mResampler = nullptr; + mResampleBuffer.clear(); + mResampleBuffer.shrink_to_fit(); + mBufferFilled = 0; + if(mDevice->mSampleRate != mFormat.Format.nSamplesPerSec) + { + const auto flags = as_unsigned(al::to_underlying(streamParams.StaticObjectTypeMask)); + const auto channelCount = as_unsigned(al::popcount(flags)); + mResampler = SampleConverter::Create(mDevice->FmtType, mDevice->FmtType, channelCount, + mDevice->mSampleRate, mFormat.Format.nSamplesPerSec, Resampler::FastBSinc24); + mResampleBuffer.resize(size_t{mDevice->mUpdateSize} * channelCount * + mFormat.Format.wBitsPerSample / 8); - TRACE("Created converter for %s/%s format, dst: %luhz (%u), src: %uhz (%u)\n", - DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), - mFormat.Format.nSamplesPerSec, mOrigUpdateSize, mDevice->Frequency, - mDevice->UpdateSize); - } + TRACE("Created converter for {}/{} format, dst: {}hz ({}), src: {}hz ({})", + DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), + mFormat.Format.nSamplesPerSec, mOutUpdateSize, mDevice->mSampleRate, + mDevice->mUpdateSize); + } - return S_OK; + return true; +} + +bool WasapiPlayback::reset() +{ + auto plock = std::unique_lock{mProcMutex}; + if(mState != ThreadState::Waiting) + throw al::backend_exception{al::backend_error::DeviceError, "Invalid state: {}", + unsigned{al::to_underlying(mState)}}; + + mAction = ThreadAction::Configure; + mProcCond.notify_all(); + mProcCond.wait(plock, [this]() noexcept { return mAction != ThreadAction::Configure; }); + + if(FAILED(mProcResult) || mState != ThreadState::Waiting) + throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: {:#x}", + as_unsigned(mProcResult)}; + return true; +} + +auto WasapiPlayback::resetProxy(DeviceHelper &helper, DeviceHandle &mmdev, + std::variant &audiodev) -> HRESULT +{ + if(GetConfigValueBool(mDevice->mDeviceName, "wasapi", "spatial-api", false)) + { + if(initSpatial(helper, mmdev, audiodev.emplace())) + return S_OK; } -no_spatial: mDevice->Flags.reset(Virtualization); + mMonoUpsample = false; + mExclusiveMode = false; - auto &audio = mAudio.emplace(); - HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), - al::out_ptr(audio.mClient))}; + auto &audio = audiodev.emplace(); + auto hr = helper.activateAudioClient(mmdev, __uuidof(IAudioClient), + al::out_ptr(audio.mClient)); if(FAILED(hr)) { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + ERR("Failed to reactivate audio client: {:#x}", as_unsigned(hr)); return hr; } - WAVEFORMATEX *wfx; - hr = audio.mClient->GetMixFormat(&wfx); + auto wfx = unique_coptr{}; + hr = audio.mClient->GetMixFormat(al::out_ptr(wfx)); if(FAILED(hr)) { - ERR("Failed to get mix format: 0x%08lx\n", hr); + ERR("Failed to get mix format: {:#x}", as_unsigned(hr)); return hr; } - TraceFormat("Device mix format", wfx); - - WAVEFORMATEXTENSIBLE OutputType; - if(!MakeExtensible(&OutputType, wfx)) + TraceFormat("Device mix format", wfx.get()); + + auto OutputType = WAVEFORMATEXTENSIBLE{}; + if(!MakeExtensible(&OutputType, wfx.get())) + return E_FAIL; + wfx = nullptr; + + /* Get the buffer and update sizes as a ReferenceTime before potentially + * altering the sample rate. + */ + const auto buf_time = ReferenceTime{seconds{mDevice->mBufferSize}} / mDevice->mSampleRate; + const auto per_time = ReferenceTime{seconds{mDevice->mUpdateSize}} / mDevice->mSampleRate; + + /* Update the mDevice format for non-requested properties. */ + bool isRear51{false}; + if(!mDevice->Flags.test(FrequencyRequest)) + mDevice->mSampleRate = OutputType.Format.nSamplesPerSec; + if(!mDevice->Flags.test(ChannelsRequest)) + { + /* If not requesting a channel configuration, auto-select given what + * fits the mask's lsb (to ensure no gaps in the output channels). If + * there's no mask, we can only assume mono or stereo. + */ + const uint32_t chancount{OutputType.Format.nChannels}; + const DWORD chanmask{OutputType.dwChannelMask}; + if(chancount >= 12 && (chanmask&X714Mask) == X7DOT1DOT4) + mDevice->FmtChans = DevFmtX714; + else if(chancount >= 8 && (chanmask&X71Mask) == X7DOT1) + mDevice->FmtChans = DevFmtX71; + else if(chancount >= 7 && (chanmask&X61Mask) == X6DOT1) + mDevice->FmtChans = DevFmtX61; + else if(chancount >= 6 && (chanmask&X51Mask) == X5DOT1) + mDevice->FmtChans = DevFmtX51; + else if(chancount >= 6 && (chanmask&X51RearMask) == X5DOT1REAR) + { + mDevice->FmtChans = DevFmtX51; + isRear51 = true; + } + else if(chancount >= 4 && (chanmask&QuadMask) == QUAD) + mDevice->FmtChans = DevFmtQuad; + else if(chancount >= 2 && ((chanmask&StereoMask) == STEREO || !chanmask)) + mDevice->FmtChans = DevFmtStereo; + else if(chancount >= 1 && ((chanmask&MonoMask) == MONO || !chanmask)) + mDevice->FmtChans = DevFmtMono; + else + ERR("Unhandled channel config: {} -- {:#08x}", chancount, chanmask); + } + else + { + const uint32_t chancount{OutputType.Format.nChannels}; + const DWORD chanmask{OutputType.dwChannelMask}; + isRear51 = (chancount == 6 && (chanmask&X51RearMask) == X5DOT1REAR); + } + + /* Request a format matching the mDevice. */ + OutputType.Format.wFormatTag = WAVE_FORMAT_EXTENSIBLE; + switch(mDevice->FmtChans) + { + case DevFmtMono: + OutputType.Format.nChannels = 1; + OutputType.dwChannelMask = MONO; + break; + case DevFmtAmbi3D: + mDevice->FmtChans = DevFmtStereo; + [[fallthrough]]; + case DevFmtStereo: + OutputType.Format.nChannels = 2; + OutputType.dwChannelMask = STEREO; + break; + case DevFmtQuad: + OutputType.Format.nChannels = 4; + OutputType.dwChannelMask = QUAD; + break; + case DevFmtX51: + OutputType.Format.nChannels = 6; + OutputType.dwChannelMask = isRear51 ? X5DOT1REAR : X5DOT1; + break; + case DevFmtX61: + OutputType.Format.nChannels = 7; + OutputType.dwChannelMask = X6DOT1; + break; + case DevFmtX71: + case DevFmtX3D71: + OutputType.Format.nChannels = 8; + OutputType.dwChannelMask = X7DOT1; + break; + case DevFmtX7144: + mDevice->FmtChans = DevFmtX714; + [[fallthrough]]; + case DevFmtX714: + OutputType.Format.nChannels = 12; + OutputType.dwChannelMask = X7DOT1DOT4; + break; + } + switch(mDevice->FmtType) { - CoTaskMemFree(wfx); - return E_FAIL; + case DevFmtByte: + mDevice->FmtType = DevFmtUByte; + [[fallthrough]]; + case DevFmtUByte: + OutputType.Format.wBitsPerSample = 8; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtUShort: + mDevice->FmtType = DevFmtShort; + [[fallthrough]]; + case DevFmtShort: + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtUInt: + mDevice->FmtType = DevFmtInt; + [[fallthrough]]; + case DevFmtInt: + OutputType.Format.wBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + break; + case DevFmtFloat: + OutputType.Format.wBitsPerSample = 32; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; + break; } - CoTaskMemFree(wfx); - wfx = nullptr; - - const ReferenceTime per_time{ReferenceTime{seconds{mDevice->UpdateSize}} / mDevice->Frequency}; - const ReferenceTime buf_time{ReferenceTime{seconds{mDevice->BufferSize}} / mDevice->Frequency}; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.Format.nSamplesPerSec = mDevice->mSampleRate; + OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nChannels + * OutputType.Format.wBitsPerSample / 8); + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec + * OutputType.Format.nBlockAlign; - prepareFormat(OutputType); + const auto sharemode = + GetConfigValueBool(mDevice->mDeviceName, "wasapi", "exclusive-mode", false) + ? AUDCLNT_SHAREMODE_EXCLUSIVE : AUDCLNT_SHAREMODE_SHARED; + mExclusiveMode = (sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE); TraceFormat("Requesting playback format", &OutputType.Format); - hr = audio.mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &OutputType.Format, &wfx); + hr = audio.mClient->IsFormatSupported(sharemode, &OutputType.Format, al::out_ptr(wfx)); if(FAILED(hr)) { - WARN("Failed to check format support: 0x%08lx\n", hr); - hr = audio.mClient->GetMixFormat(&wfx); + if(sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) + { + /* For exclusive mode, IAudioClient::IsFormatSupported won't give + * back a supported format. However, a common failure is an + * unsupported sample type, so try a fallback to 16-bit int. + */ + if(hr == AUDCLNT_E_UNSUPPORTED_FORMAT && mDevice->FmtType != DevFmtShort) + { + mDevice->FmtType = DevFmtShort; + + OutputType.Format.wBitsPerSample = 16; + OutputType.SubFormat = KSDATAFORMAT_SUBTYPE_PCM; + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ + OutputType.Samples.wValidBitsPerSample = OutputType.Format.wBitsPerSample; + OutputType.Format.nBlockAlign = static_cast(OutputType.Format.nChannels + * OutputType.Format.wBitsPerSample / 8); + OutputType.Format.nAvgBytesPerSec = OutputType.Format.nSamplesPerSec + * OutputType.Format.nBlockAlign; + + hr = audio.mClient->IsFormatSupported(sharemode, &OutputType.Format, + al::out_ptr(wfx)); + } + } + else + { + WARN("Failed to check format support: {:#x}", as_unsigned(hr)); + hr = audio.mClient->GetMixFormat(al::out_ptr(wfx)); + } } if(FAILED(hr)) { - ERR("Failed to find a supported format: 0x%08lx\n", hr); + ERR("Failed to find a supported format: {:#x}", as_unsigned(hr)); return hr; } - if(wfx != nullptr) + if(wfx) { - TraceFormat("Got playback format", wfx); - if(!MakeExtensible(&OutputType, wfx)) - { - CoTaskMemFree(wfx); + TraceFormat("Got playback format", wfx.get()); + if(!MakeExtensible(&OutputType, wfx.get())) return E_FAIL; - } - CoTaskMemFree(wfx); wfx = nullptr; finalizeFormat(OutputType); } mFormat = OutputType; -#if !defined(ALSOFT_UWP) - const EndpointFormFactor formfactor{GetDeviceFormfactor(mMMDev.get())}; +#if !ALSOFT_UWP + const EndpointFormFactor formfactor{GetDeviceFormfactor(mmdev.get())}; mDevice->Flags.set(DirectEar, (formfactor == Headphones || formfactor == Headset)); #else mDevice->Flags.set(DirectEar, false); #endif setDefaultWFXChannelOrder(); - hr = audio.mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, - buf_time.count(), 0, &OutputType.Format, nullptr); + if(sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) + { + auto period_time = per_time; + auto min_period = ReferenceTime{}; + hr = audio.mClient->GetDevicePeriod(nullptr, + &reinterpret_cast(min_period)); + if(FAILED(hr)) + ERR("Failed to get minimum period time: {:#x}", as_unsigned(hr)); + else if(min_period > period_time) + { + period_time = min_period; + WARN("Clamping to minimum period time, {}", nanoseconds{min_period}); + } + + hr = audio.mClient->Initialize(sharemode, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + period_time.count(), period_time.count(), &OutputType.Format, nullptr); + if(hr == AUDCLNT_E_BUFFER_SIZE_NOT_ALIGNED) + { + auto newsize = UINT32{}; + hr = audio.mClient->GetBufferSize(&newsize); + if(SUCCEEDED(hr)) + { + period_time = ReferenceTime{seconds{newsize}} + / OutputType.Format.nSamplesPerSec; + WARN("Adjusting to supported period time, {}", nanoseconds{period_time}); + + audio.mClient = nullptr; + hr = helper.activateAudioClient(mmdev, __uuidof(IAudioClient), + al::out_ptr(audio.mClient)); + if(FAILED(hr)) + { + ERR("Failed to reactivate audio client: {:#x}", as_unsigned(hr)); + return hr; + } + hr = audio.mClient->Initialize(sharemode, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + period_time.count(), period_time.count(), &OutputType.Format, nullptr); + } + } + } + else + hr = audio.mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + buf_time.count(), 0, &OutputType.Format, nullptr); if(FAILED(hr)) { - ERR("Failed to initialize audio client: 0x%08lx\n", hr); + ERR("Failed to initialize audio client: {:#x}", as_unsigned(hr)); return hr; } - UINT32 buffer_len{}; - ReferenceTime min_per{}; - hr = audio.mClient->GetDevicePeriod(&reinterpret_cast(min_per), nullptr); + auto buffer_len = UINT32{}; + auto period_time = ReferenceTime{}; + hr = audio.mClient->GetDevicePeriod(&reinterpret_cast(period_time), nullptr); if(SUCCEEDED(hr)) hr = audio.mClient->GetBufferSize(&buffer_len); if(FAILED(hr)) { - ERR("Failed to get audio buffer info: 0x%08lx\n", hr); + ERR("Failed to get audio buffer info: {:#x}", as_unsigned(hr)); return hr; } hr = audio.mClient->SetEventHandle(mNotifyEvent); if(FAILED(hr)) { - ERR("Failed to set event handle: 0x%08lx\n", hr); + ERR("Failed to set event handle: {:#x}", as_unsigned(hr)); return hr; } - /* Find the nearest multiple of the period size to the update size */ - if(min_per < per_time) - min_per *= maxi64((per_time + min_per/2) / min_per, 1); + hr = audio.mClient->GetService(__uuidof(IAudioRenderClient), al::out_ptr(audio.mRender)); + if(FAILED(hr)) + { + ERR("Failed to get IAudioRenderClient: {:#x}", as_unsigned(hr)); + return hr; + } - mOrigBufferSize = buffer_len; - mOrigUpdateSize = minu(RefTime2Samples(min_per, mFormat.Format.nSamplesPerSec), buffer_len/2); + mOutBufferSize = buffer_len; + if(sharemode == AUDCLNT_SHAREMODE_EXCLUSIVE) + { + /* For exclusive mode, the buffer size is the update size, and there's + * implicitly two update periods on the device. + */ + mOutUpdateSize = buffer_len; + mDevice->mUpdateSize = static_cast(uint64_t{buffer_len} * mDevice->mSampleRate / + mFormat.Format.nSamplesPerSec); + mDevice->mBufferSize = mDevice->mUpdateSize * 2; + } + else + { + mOutUpdateSize = RefTime2Samples(period_time, mFormat.Format.nSamplesPerSec); - mDevice->BufferSize = static_cast(uint64_t{buffer_len} * mDevice->Frequency / - mFormat.Format.nSamplesPerSec); - mDevice->UpdateSize = minu(RefTime2Samples(min_per, mDevice->Frequency), - mDevice->BufferSize/2); + mDevice->mBufferSize = static_cast(uint64_t{buffer_len} * mDevice->mSampleRate / + mFormat.Format.nSamplesPerSec); + mDevice->mUpdateSize = std::min(RefTime2Samples(period_time, mDevice->mSampleRate), + mDevice->mBufferSize/2u); + } mResampler = nullptr; - mResampleBuffer = nullptr; + mResampleBuffer.clear(); + mResampleBuffer.shrink_to_fit(); mBufferFilled = 0; - if(mDevice->Frequency != mFormat.Format.nSamplesPerSec) + if(mDevice->mSampleRate != mFormat.Format.nSamplesPerSec) { mResampler = SampleConverter::Create(mDevice->FmtType, mDevice->FmtType, - mFormat.Format.nChannels, mDevice->Frequency, mFormat.Format.nSamplesPerSec, + mFormat.Format.nChannels, mDevice->mSampleRate, mFormat.Format.nSamplesPerSec, Resampler::FastBSinc24); - mResampleBuffer = std::make_unique(size_t{mDevice->UpdateSize} * - mFormat.Format.nChannels * mFormat.Format.wBitsPerSample / 8); + mResampleBuffer.resize(size_t{mDevice->mUpdateSize} * mFormat.Format.nChannels * + mFormat.Format.wBitsPerSample / 8); - TRACE("Created converter for %s/%s format, dst: %luhz (%u), src: %uhz (%u)\n", + TRACE("Created converter for {}/{} format, dst: {}hz ({}), src: {}hz ({})", DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), - mFormat.Format.nSamplesPerSec, mOrigUpdateSize, mDevice->Frequency, - mDevice->UpdateSize); + mFormat.Format.nSamplesPerSec, mOutUpdateSize, mDevice->mSampleRate, + mDevice->mUpdateSize); } return hr; @@ -1990,143 +2342,90 @@ HRESULT WasapiPlayback::resetProxy() void WasapiPlayback::start() { - const HRESULT hr{pushMessage(MsgType::StartDevice).get()}; - if(FAILED(hr)) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start playback: 0x%lx", hr}; -} - -HRESULT WasapiPlayback::startProxy() -{ - ResetEvent(mNotifyEvent); - - auto mstate_fallback = [](std::monostate) -> HRESULT - { return E_FAIL; }; - auto start_plain = [&](PlainDevice &audio) -> HRESULT - { - HRESULT hr{audio.mClient->Start()}; - if(FAILED(hr)) - { - ERR("Failed to start audio client: 0x%08lx\n", hr); - return hr; - } - - hr = audio.mClient->GetService(__uuidof(IAudioRenderClient), al::out_ptr(audio.mRender)); - if(SUCCEEDED(hr)) - { - try { - mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerProc), this}; - } - catch(...) { - audio.mRender = nullptr; - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - } - if(FAILED(hr)) - audio.mClient->Stop(); - return hr; - }; - auto start_spatial = [&](SpatialDevice &audio) -> HRESULT - { - HRESULT hr{audio.mRender->Start()}; - if(FAILED(hr)) - { - ERR("Failed to start spatial audio stream: 0x%08lx\n", hr); - return hr; - } - - try { - mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WasapiPlayback::mixerSpatialProc), this}; - } - catch(...) { - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - - if(FAILED(hr)) - { - audio.mRender->Stop(); - audio.mRender->Reset(); - } - return hr; - }; - - return std::visit(overloaded{mstate_fallback, start_plain, start_spatial}, mAudio); + auto plock = std::unique_lock{mProcMutex}; + if(mState != ThreadState::Waiting) + throw al::backend_exception{al::backend_error::DeviceError, "Invalid state: {}", + unsigned{al::to_underlying(mState)}}; + + mAction = ThreadAction::Play; + mProcCond.notify_all(); + mProcCond.wait(plock, [this]() noexcept { return mAction != ThreadAction::Play; }); + + if(FAILED(mProcResult) || mState != ThreadState::Playing) + throw al::backend_exception{al::backend_error::DeviceError, "Device playback failed: {:#x}", + as_unsigned(mProcResult)}; } - void WasapiPlayback::stop() -{ pushMessage(MsgType::StopDevice).wait(); } - -void WasapiPlayback::stopProxy() { - if(!mThread.joinable()) - return; - - mKillNow.store(true, std::memory_order_release); - mThread.join(); - - auto mstate_fallback = [](std::monostate) -> void - { }; - auto stop_plain = [](PlainDevice &audio) -> void + auto plock = std::unique_lock{mProcMutex}; + if(mState == ThreadState::Playing) { - audio.mRender = nullptr; - audio.mClient->Stop(); - }; - auto stop_spatial = [](SpatialDevice &audio) -> void - { - audio.mRender->Stop(); - audio.mRender->Reset(); - }; - std::visit(overloaded{mstate_fallback, stop_plain, stop_spatial}, mAudio); + mKillNow = true; + mProcCond.wait(plock, [this]() noexcept { return mState != ThreadState::Playing; }); + } } ClockLatency WasapiPlayback::getClockLatency() { - ClockLatency ret; - - std::lock_guard _{mMutex}; - ret.ClockTime = GetDeviceClockTime(mDevice); + std::lock_guard dlock{mMutex}; + ClockLatency ret{}; + ret.ClockTime = mDevice->getClockTime(); ret.Latency = seconds{mPadding.load(std::memory_order_relaxed)}; ret.Latency /= mFormat.Format.nSamplesPerSec; if(mResampler) { auto extra = mResampler->currentInputDelay(); - ret.Latency += std::chrono::duration_cast(extra) / mDevice->Frequency; - ret.Latency += nanoseconds{seconds{mBufferFilled}} / mDevice->Frequency; + ret.Latency += std::chrono::duration_cast(extra) / mDevice->mSampleRate; + ret.Latency += nanoseconds{seconds{mBufferFilled}} / mDevice->mSampleRate; } return ret; } -struct WasapiCapture final : public BackendBase, WasapiProxy { - WasapiCapture(DeviceBase *device) noexcept : BackendBase{device} { } +struct WasapiCapture final : public BackendBase { + explicit WasapiCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~WasapiCapture() override; - int recordProc(); + void recordProc(IAudioClient *client, IAudioCaptureClient *capture); - void open(std::string_view name) override; - HRESULT openProxy(std::string_view name) override; - void closeProxy() override; + void proc_thread(std::string&& name); - HRESULT resetProxy() override; + auto openProxy(const std::string_view name, DeviceHelper &helper, DeviceHandle &mmdev) + -> HRESULT; + auto resetProxy(DeviceHelper &helper, DeviceHandle &mmdev, ComPtr &client, + ComPtr &capture) -> HRESULT; + + void open(std::string_view name) override; void start() override; - HRESULT startProxy() override; void stop() override; - void stopProxy() override; - void captureSamples(std::byte *buffer, uint samples) override; uint availableSamples() override; - HRESULT mOpenStatus{E_FAIL}; - DeviceHandle mMMDev{nullptr}; - ComPtr mClient{nullptr}; - ComPtr mCapture{nullptr}; + + std::thread mProcThread; + std::mutex mProcMutex; + std::condition_variable mProcCond; + HRESULT mProcResult{E_FAIL}; + + enum class ThreadState : uint8_t { + Initializing, + Waiting, + Recording, + Done + }; + ThreadState mState{ThreadState::Initializing}; + + enum class ThreadAction : uint8_t { + Nothing, + Record, + Quit + }; + ThreadAction mAction{ThreadAction::Nothing}; + + HANDLE mNotifyEvent{nullptr}; ChannelConverter mChannelConv{}; @@ -2135,15 +2434,20 @@ struct WasapiCapture final : public BackendBase, WasapiProxy { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(WasapiCapture) }; WasapiCapture::~WasapiCapture() { - if(SUCCEEDED(mOpenStatus)) - pushMessage(MsgType::CloseDevice).wait(); - mOpenStatus = E_FAIL; + if(mProcThread.joinable()) + { + { + auto plock = std::lock_guard{mProcMutex}; + mKillNow = true; + mAction = ThreadAction::Quit; + } + mProcCond.notify_all(); + mProcThread.join(); + } if(mNotifyEvent != nullptr) CloseHandle(mNotifyEvent); @@ -2151,39 +2455,37 @@ WasapiCapture::~WasapiCapture() } -FORCE_ALIGN int WasapiCapture::recordProc() +FORCE_ALIGN void WasapiCapture::recordProc(IAudioClient *client, IAudioCaptureClient *capture) { - HRESULT hr{CoInitializeEx(nullptr, COINIT_MULTITHREADED)}; - if(FAILED(hr)) + ResetEvent(mNotifyEvent); + if(HRESULT hr{client->Start()}; FAILED(hr)) { - ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: 0x%08lx\n", hr); - mDevice->handleDisconnect("COM init failed: 0x%08lx", hr); - return 1; + ERR("Failed to start audio client: {:#x}", as_unsigned(hr)); + mDevice->handleDisconnect("Failed to start audio client: {:#x}", as_unsigned(hr)); + return; } - althrd_setname(RECORD_THREAD_NAME); - std::vector samples; while(!mKillNow.load(std::memory_order_relaxed)) { - UINT32 avail; - hr = mCapture->GetNextPacketSize(&avail); + auto avail = UINT32{}; + auto hr = capture->GetNextPacketSize(&avail); if(FAILED(hr)) - ERR("Failed to get next packet size: 0x%08lx\n", hr); + ERR("Failed to get next packet size: {:#x}", as_unsigned(hr)); else if(avail > 0) { - UINT32 numsamples; - DWORD flags; - BYTE *rdata; + auto numsamples = UINT32{}; + auto flags = DWORD{}; + BYTE *rdata{}; - hr = mCapture->GetBuffer(&rdata, &numsamples, &flags, nullptr, nullptr); + hr = capture->GetBuffer(&rdata, &numsamples, &flags, nullptr, nullptr); if(FAILED(hr)) - ERR("Failed to get capture buffer: 0x%08lx\n", hr); + ERR("Failed to get capture buffer: {:#x}", as_unsigned(hr)); else { if(mChannelConv.is_active()) { - samples.resize(numsamples*2); + samples.resize(numsamples*2_uz); mChannelConv.convert(rdata, samples.data(), numsamples); rdata = reinterpret_cast(samples.data()); } @@ -2193,174 +2495,261 @@ FORCE_ALIGN int WasapiCapture::recordProc() size_t dstframes; if(mSampleConv) { + static constexpr auto lenlimit = size_t{std::numeric_limits::max()}; const void *srcdata{rdata}; uint srcframes{numsamples}; - dstframes = mSampleConv->convert(&srcdata, &srcframes, data.first.buf, - static_cast(minz(data.first.len, INT_MAX))); - if(srcframes > 0 && dstframes == data.first.len && data.second.len > 0) + dstframes = mSampleConv->convert(&srcdata, &srcframes, data[0].buf, + static_cast(std::min(data[0].len, lenlimit))); + if(srcframes > 0 && dstframes == data[0].len && data[1].len > 0) { /* If some source samples remain, all of the first dest * block was filled, and there's space in the second * dest block, do another run for the second block. */ - dstframes += mSampleConv->convert(&srcdata, &srcframes, data.second.buf, - static_cast(minz(data.second.len, INT_MAX))); + dstframes += mSampleConv->convert(&srcdata, &srcframes, data[1].buf, + static_cast(std::min(data[1].len, lenlimit))); } } else { const uint framesize{mDevice->frameSizeFromFmt()}; - size_t len1{minz(data.first.len, numsamples)}; - size_t len2{minz(data.second.len, numsamples-len1)}; + auto dst = al::span{rdata, size_t{numsamples}*framesize}; + size_t len1{std::min(data[0].len, size_t{numsamples})}; + size_t len2{std::min(data[1].len, numsamples-len1)}; - memcpy(data.first.buf, rdata, len1*framesize); + memcpy(data[0].buf, dst.data(), len1*framesize); if(len2 > 0) - memcpy(data.second.buf, rdata+len1*framesize, len2*framesize); + { + dst = dst.subspan(len1*framesize); + memcpy(data[1].buf, dst.data(), len2*framesize); + } dstframes = len1 + len2; } mRing->writeAdvance(dstframes); - hr = mCapture->ReleaseBuffer(numsamples); - if(FAILED(hr)) ERR("Failed to release capture buffer: 0x%08lx\n", hr); + hr = capture->ReleaseBuffer(numsamples); + if(FAILED(hr)) ERR("Failed to release capture buffer: {:#x}", as_unsigned(hr)); } } if(FAILED(hr)) { - mDevice->handleDisconnect("Failed to capture samples: 0x%08lx", hr); + mDevice->handleDisconnect("Failed to capture samples: {:#x}", as_unsigned(hr)); break; } - DWORD res{WaitForSingleObjectEx(mNotifyEvent, 2000, FALSE)}; - if(res != WAIT_OBJECT_0) - ERR("WaitForSingleObjectEx error: 0x%lx\n", res); + if(DWORD res{WaitForSingleObjectEx(mNotifyEvent, 2000, FALSE)}; res != WAIT_OBJECT_0) + ERR("WaitForSingleObjectEx error: {:#x}", res); + } + + client->Stop(); + client->Reset(); +} + + +void WasapiCapture::proc_thread(std::string&& name) +try { + auto com = ComWrapper{COINIT_MULTITHREADED}; + if(!com) + { + const auto hr = as_unsigned(com.status()); + ERR("CoInitializeEx(nullptr, COINIT_MULTITHREADED) failed: {:#x}", hr); + mDevice->handleDisconnect("COM init failed: {:#x}", hr); + + auto plock = std::lock_guard{mProcMutex}; + mProcResult = com.status(); + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + if(!gInitDone.load(std::memory_order_relaxed)) + { + auto devlock = DeviceListLock{gDeviceList}; + gInitCV.wait(devlock, []() -> bool { return gInitDone; }); } - CoUninitialize(); - return 0; + auto helper = DeviceHelper{}; + if(HRESULT hr{helper.init()}; FAILED(hr)) + { + mDevice->handleDisconnect("Helper init failed: {:#x}", as_unsigned(hr)); + + auto plock = std::lock_guard{mProcMutex}; + mProcResult = hr; + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + althrd_setname(GetRecordThreadName()); + + auto mmdev = DeviceHandle{nullptr}; + if(auto hr = openProxy(name, helper, mmdev); FAILED(hr)) + { + auto plock = std::lock_guard{mProcMutex}; + mProcResult = hr; + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + auto client = ComPtr{}; + auto capture = ComPtr{}; + if(auto hr = resetProxy(helper, mmdev, client, capture); FAILED(hr)) + { + auto plock = std::lock_guard{mProcMutex}; + mProcResult = hr; + mState = ThreadState::Done; + mProcCond.notify_all(); + return; + } + + auto plock = std::unique_lock{mProcMutex}; + mProcResult = S_OK; + while(mState != ThreadState::Done) + { + mAction = ThreadAction::Nothing; + mState = ThreadState::Waiting; + mProcCond.notify_all(); + + mProcCond.wait(plock, [this]() noexcept { return mAction != ThreadAction::Nothing; }); + switch(mAction) + { + case ThreadAction::Nothing: + break; + + case ThreadAction::Record: + mKillNow.store(false, std::memory_order_release); + + mAction = ThreadAction::Nothing; + mState = ThreadState::Recording; + mProcResult = S_OK; + plock.unlock(); + mProcCond.notify_all(); + + recordProc(client.get(), capture.get()); + + plock.lock(); + break; + + case ThreadAction::Quit: + mAction = ThreadAction::Nothing; + mState = ThreadState::Done; + mProcCond.notify_all(); + break; + } + } +} +catch(...) { + auto plock = std::lock_guard{mProcMutex}; + mProcResult = E_FAIL; + mAction = ThreadAction::Nothing; + mState = ThreadState::Done; + mProcCond.notify_all(); } void WasapiCapture::open(std::string_view name) { - if(SUCCEEDED(mOpenStatus)) - throw al::backend_exception{al::backend_error::DeviceError, - "Unexpected duplicate open call"}; - mNotifyEvent = CreateEventW(nullptr, FALSE, FALSE, nullptr); if(mNotifyEvent == nullptr) { - ERR("Failed to create notify events: %lu\n", GetLastError()); + ERR("Failed to create notify events: {}", GetLastError()); throw al::backend_exception{al::backend_error::DeviceError, "Failed to create notify events"}; } - if(name.length() >= DevNameHeadLen - && std::strncmp(name.data(), DevNameHead, DevNameHeadLen) == 0) - { - name = name.substr(DevNameHeadLen); - } + mProcThread = std::thread{&WasapiCapture::proc_thread, this, std::string{name}}; - mOpenStatus = pushMessage(MsgType::OpenDevice, name).get(); - if(FAILED(mOpenStatus)) - throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: 0x%08lx", - mOpenStatus}; + auto plock = std::unique_lock{mProcMutex}; + mProcCond.wait(plock, [this]() noexcept { return mState != ThreadState::Initializing; }); - HRESULT hr{pushMessage(MsgType::ResetDevice).get()}; - if(FAILED(hr)) - { - if(hr == E_OUTOFMEMORY) - throw al::backend_exception{al::backend_error::OutOfMemory, "Out of memory"}; - throw al::backend_exception{al::backend_error::DeviceError, "Device reset failed"}; - } + if(mProcResult == E_NOTFOUND) + throw al::backend_exception{al::backend_error::NoDevice, "Device \"{}\" not found", name}; + if(mProcResult == E_OUTOFMEMORY) + throw al::backend_exception{al::backend_error::OutOfMemory, "Out of memory"}; + if(FAILED(mProcResult) || mState == ThreadState::Done) + throw al::backend_exception{al::backend_error::DeviceError, "Device init failed: {:#x}", + as_unsigned(mProcResult)}; } -HRESULT WasapiCapture::openProxy(std::string_view name) +auto WasapiCapture::openProxy(const std::string_view name, DeviceHelper &helper, + DeviceHandle &mmdev) -> HRESULT { - std::string devname; - std::wstring devid; + auto devname = std::string{}; + auto devid = std::wstring{}; if(!name.empty()) { auto devlock = DeviceListLock{gDeviceList}; auto devlist = al::span{devlock.getCaptureList()}; auto iter = std::find_if(devlist.cbegin(), devlist.cend(), [name](const DevMap &entry) -> bool - { return entry.name == name || entry.endpoint_guid == name; }); + { return entry.name == name || al::case_compare(entry.endpoint_guid, name) == 0; }); if(iter == devlist.cend()) { const std::wstring wname{utf8_to_wstr(name)}; iter = std::find_if(devlist.cbegin(), devlist.cend(), [&wname](const DevMap &entry) -> bool - { return entry.devid == wname; }); + { return al::case_compare(entry.devid, wname) == 0; }); } if(iter == devlist.cend()) { - WARN("Failed to find device name matching \"%.*s\"\n", static_cast(name.length()), - name.data()); - return E_FAIL; + WARN("Failed to find device name matching \"{}\"", name); + return E_NOTFOUND; } devname = iter->name; devid = iter->devid; } - HRESULT hr{sDeviceHelper->openDevice(devid, eCapture, mMMDev)}; + auto hr = helper.openDevice(devid, eCapture, mmdev); if(FAILED(hr)) { - WARN("Failed to open device \"%s\"\n", devname.empty() ? "(default)" : devname.c_str()); + WARN("Failed to open device \"{}\": {:#x}", devname.empty() + ? "(default)"sv : std::string_view{devname}, as_unsigned(hr)); return hr; } - mClient = nullptr; if(!devname.empty()) - mDevice->DeviceName = DevNameHead + std::move(devname); + mDeviceName = std::move(devname); else - mDevice->DeviceName = DevNameHead + GetDeviceNameAndGuid(mMMDev).first; + mDeviceName = GetDeviceNameAndGuid(mmdev).mName; return S_OK; } -void WasapiCapture::closeProxy() -{ - mClient = nullptr; - mMMDev = nullptr; -} - -HRESULT WasapiCapture::resetProxy() +auto WasapiCapture::resetProxy(DeviceHelper &helper, DeviceHandle &mmdev, + ComPtr &client, ComPtr &capture) -> HRESULT { - mClient = nullptr; + capture = nullptr; + client = nullptr; - HRESULT hr{sDeviceHelper->activateAudioClient(mMMDev, __uuidof(IAudioClient), - al::out_ptr(mClient))}; + auto hr = helper.activateAudioClient(mmdev, __uuidof(IAudioClient), al::out_ptr(client)); if(FAILED(hr)) { - ERR("Failed to reactivate audio client: 0x%08lx\n", hr); + ERR("Failed to reactivate audio client: {:#x}", as_unsigned(hr)); return hr; } - WAVEFORMATEX *wfx; - hr = mClient->GetMixFormat(&wfx); + auto wfx = unique_coptr{}; + hr = client->GetMixFormat(al::out_ptr(wfx)); if(FAILED(hr)) { - ERR("Failed to get capture format: 0x%08lx\n", hr); + ERR("Failed to get capture format: {:#x}", as_unsigned(hr)); return hr; } - TraceFormat("Device capture format", wfx); + TraceFormat("Device capture format", wfx.get()); - WAVEFORMATEXTENSIBLE InputType{}; - if(!MakeExtensible(&InputType, wfx)) - { - CoTaskMemFree(wfx); + auto InputType = WAVEFORMATEXTENSIBLE{}; + if(!MakeExtensible(&InputType, wfx.get())) return E_FAIL; - } - CoTaskMemFree(wfx); wfx = nullptr; const bool isRear51{InputType.Format.nChannels == 6 && (InputType.dwChannelMask&X51RearMask) == X5DOT1REAR}; // Make sure buffer is at least 100ms in size - ReferenceTime buf_time{ReferenceTime{seconds{mDevice->BufferSize}} / mDevice->Frequency}; + ReferenceTime buf_time{ReferenceTime{seconds{mDevice->mBufferSize}} / mDevice->mSampleRate}; buf_time = std::max(buf_time, ReferenceTime{milliseconds{100}}); InputType = {}; @@ -2396,6 +2785,7 @@ HRESULT WasapiCapture::resetProxy() InputType.dwChannelMask = X7DOT1DOT4; break; + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: return E_FAIL; @@ -2423,8 +2813,9 @@ HRESULT WasapiCapture::resetProxy() InputType.SubFormat = KSDATAFORMAT_SUBTYPE_IEEE_FLOAT; break; } + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-union-access) */ InputType.Samples.wValidBitsPerSample = InputType.Format.wBitsPerSample; - InputType.Format.nSamplesPerSec = mDevice->Frequency; + InputType.Format.nSamplesPerSec = mDevice->mSampleRate; InputType.Format.nBlockAlign = static_cast(InputType.Format.nChannels * InputType.Format.wBitsPerSample / 8); @@ -2433,15 +2824,15 @@ HRESULT WasapiCapture::resetProxy() InputType.Format.cbSize = sizeof(InputType) - sizeof(InputType.Format); TraceFormat("Requesting capture format", &InputType.Format); - hr = mClient->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &InputType.Format, &wfx); + hr = client->IsFormatSupported(AUDCLNT_SHAREMODE_SHARED, &InputType.Format, al::out_ptr(wfx)); if(FAILED(hr)) { - WARN("Failed to check capture format support: 0x%08lx\n", hr); - hr = mClient->GetMixFormat(&wfx); + WARN("Failed to check capture format support: {:#x}", as_unsigned(hr)); + hr = client->GetMixFormat(al::out_ptr(wfx)); } if(FAILED(hr)) { - ERR("Failed to find a supported capture format: 0x%08lx\n", hr); + ERR("Failed to find a supported capture format: {:#x}", as_unsigned(hr)); return hr; } @@ -2450,13 +2841,9 @@ HRESULT WasapiCapture::resetProxy() if(wfx != nullptr) { - TraceFormat("Got capture format", wfx); - if(!MakeExtensible(&InputType, wfx)) - { - CoTaskMemFree(wfx); + TraceFormat("Got capture format", wfx.get()); + if(!MakeExtensible(&InputType, wfx.get())) return E_FAIL; - } - CoTaskMemFree(wfx); wfx = nullptr; auto validate_fmt = [](DeviceBase *device, uint32_t chancount, DWORD chanmask) noexcept @@ -2485,6 +2872,8 @@ HRESULT WasapiCapture::resetProxy() return (chancount == 8 && (chanmask == 0 || (chanmask&X71Mask) == X7DOT1)); case DevFmtX714: return (chancount == 12 && (chanmask == 0 || (chanmask&X714Mask) == X7DOT1DOT4)); + case DevFmtX7144: + return (chancount == 16 && chanmask == 0); case DevFmtAmbi3D: return (chanmask == 0 && chancount == device->channelsFromFmt()); } @@ -2492,9 +2881,9 @@ HRESULT WasapiCapture::resetProxy() }; if(!validate_fmt(mDevice, InputType.Format.nChannels, InputType.dwChannelMask)) { - ERR("Failed to match format, wanted: %s %s %uhz, got: 0x%08lx mask %d channel%s %d-bit %luhz\n", + ERR("Failed to match format, wanted: {} {} {}hz, got: {:#08x} mask {} channel{} {}-bit {}hz", DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), - mDevice->Frequency, InputType.dwChannelMask, InputType.Format.nChannels, + mDevice->mSampleRate, InputType.dwChannelMask, InputType.Format.nChannels, (InputType.Format.nChannels==1)?"":"s", InputType.Format.wBitsPerSample, InputType.Format.nSamplesPerSec); return E_FAIL; @@ -2512,7 +2901,7 @@ HRESULT WasapiCapture::resetProxy() srcType = DevFmtInt; else { - ERR("Unhandled integer bit depth: %d\n", InputType.Format.wBitsPerSample); + ERR("Unhandled integer bit depth: {}", InputType.Format.wBitsPerSample); return E_FAIL; } } @@ -2522,13 +2911,13 @@ HRESULT WasapiCapture::resetProxy() srcType = DevFmtFloat; else { - ERR("Unhandled float bit depth: %d\n", InputType.Format.wBitsPerSample); + ERR("Unhandled float bit depth: {}", InputType.Format.wBitsPerSample); return E_FAIL; } } else { - ERR("Unhandled format sub-type: %s\n", GuidPrinter{InputType.SubFormat}.c_str()); + ERR("Unhandled format sub-type: {}", GuidPrinter{InputType.SubFormat}.str()); return E_FAIL; } @@ -2545,7 +2934,7 @@ HRESULT WasapiCapture::resetProxy() mChannelConv = ChannelConverter{srcType, InputType.Format.nChannels, chanmask, mDevice->FmtChans}; - TRACE("Created %s multichannel-to-mono converter\n", DevFmtTypeString(srcType)); + TRACE("Created {} multichannel-to-mono converter", DevFmtTypeString(srcType)); /* The channel converter always outputs float, so change the input type * for the resampler/type-converter. */ @@ -2554,54 +2943,61 @@ HRESULT WasapiCapture::resetProxy() else if(mDevice->FmtChans == DevFmtStereo && InputType.Format.nChannels == 1) { mChannelConv = ChannelConverter{srcType, 1, 0x1, mDevice->FmtChans}; - TRACE("Created %s mono-to-stereo converter\n", DevFmtTypeString(srcType)); + TRACE("Created {} mono-to-stereo converter", DevFmtTypeString(srcType)); srcType = DevFmtFloat; } - if(mDevice->Frequency != InputType.Format.nSamplesPerSec || mDevice->FmtType != srcType) + if(mDevice->mSampleRate != InputType.Format.nSamplesPerSec || mDevice->FmtType != srcType) { mSampleConv = SampleConverter::Create(srcType, mDevice->FmtType, - mDevice->channelsFromFmt(), InputType.Format.nSamplesPerSec, mDevice->Frequency, + mDevice->channelsFromFmt(), InputType.Format.nSamplesPerSec, mDevice->mSampleRate, Resampler::FastBSinc24); if(!mSampleConv) { - ERR("Failed to create converter for %s format, dst: %s %uhz, src: %s %luhz\n", + ERR("Failed to create converter for {} format, dst: {} {}hz, src: {} {}hz", DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), - mDevice->Frequency, DevFmtTypeString(srcType), InputType.Format.nSamplesPerSec); + mDevice->mSampleRate, DevFmtTypeString(srcType), InputType.Format.nSamplesPerSec); return E_FAIL; } - TRACE("Created converter for %s format, dst: %s %uhz, src: %s %luhz\n", + TRACE("Created converter for {} format, dst: {} {}hz, src: {} {}hz", DevFmtChannelsString(mDevice->FmtChans), DevFmtTypeString(mDevice->FmtType), - mDevice->Frequency, DevFmtTypeString(srcType), InputType.Format.nSamplesPerSec); + mDevice->mSampleRate, DevFmtTypeString(srcType), InputType.Format.nSamplesPerSec); } - hr = mClient->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, + hr = client->Initialize(AUDCLNT_SHAREMODE_SHARED, AUDCLNT_STREAMFLAGS_EVENTCALLBACK, buf_time.count(), 0, &InputType.Format, nullptr); if(FAILED(hr)) { - ERR("Failed to initialize audio client: 0x%08lx\n", hr); + ERR("Failed to initialize audio client: {:#x}", as_unsigned(hr)); + return hr; + } + + hr = client->GetService(__uuidof(IAudioCaptureClient), al::out_ptr(capture)); + if(FAILED(hr)) + { + ERR("Failed to get IAudioCaptureClient: {:#x}", as_unsigned(hr)); return hr; } UINT32 buffer_len{}; ReferenceTime min_per{}; - hr = mClient->GetDevicePeriod(&reinterpret_cast(min_per), nullptr); + hr = client->GetDevicePeriod(&reinterpret_cast(min_per), nullptr); if(SUCCEEDED(hr)) - hr = mClient->GetBufferSize(&buffer_len); + hr = client->GetBufferSize(&buffer_len); if(FAILED(hr)) { - ERR("Failed to get buffer size: 0x%08lx\n", hr); + ERR("Failed to get buffer size: {:#x}", as_unsigned(hr)); return hr; } - mDevice->UpdateSize = RefTime2Samples(min_per, mDevice->Frequency); - mDevice->BufferSize = buffer_len; + mDevice->mUpdateSize = RefTime2Samples(min_per, mDevice->mSampleRate); + mDevice->mBufferSize = buffer_len; mRing = RingBuffer::Create(buffer_len, mDevice->frameSizeFromFmt(), false); - hr = mClient->SetEventHandle(mNotifyEvent); + hr = client->SetEventHandle(mNotifyEvent); if(FAILED(hr)) { - ERR("Failed to set event handle: 0x%08lx\n", hr); + ERR("Failed to set event handle: {:#x}", as_unsigned(hr)); return hr; } @@ -2611,66 +3007,33 @@ HRESULT WasapiCapture::resetProxy() void WasapiCapture::start() { - const HRESULT hr{pushMessage(MsgType::StartDevice).get()}; - if(FAILED(hr)) - throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start recording: 0x%lx", hr}; + auto plock = std::unique_lock{mProcMutex}; + if(mState != ThreadState::Waiting) + throw al::backend_exception{al::backend_error::DeviceError, "Invalid state: {}", + unsigned{al::to_underlying(mState)}}; + + mAction = ThreadAction::Record; + mProcCond.notify_all(); + mProcCond.wait(plock, [this]() noexcept { return mAction != ThreadAction::Record; }); + + if(FAILED(mProcResult) || mState != ThreadState::Recording) + throw al::backend_exception{al::backend_error::DeviceError, "Device capture failed: {:#x}", + as_unsigned(mProcResult)}; } -HRESULT WasapiCapture::startProxy() +void WasapiCapture::stop() { - ResetEvent(mNotifyEvent); - - HRESULT hr{mClient->Start()}; - if(FAILED(hr)) - { - ERR("Failed to start audio client: 0x%08lx\n", hr); - return hr; - } - - hr = mClient->GetService(__uuidof(IAudioCaptureClient), al::out_ptr(mCapture)); - if(SUCCEEDED(hr)) - { - try { - mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WasapiCapture::recordProc), this}; - } - catch(...) { - mCapture = nullptr; - ERR("Failed to start thread\n"); - hr = E_FAIL; - } - } - - if(FAILED(hr)) + auto plock = std::unique_lock{mProcMutex}; + if(mState == ThreadState::Recording) { - mClient->Stop(); - mClient->Reset(); + mKillNow = true; + mProcCond.wait(plock, [this]() noexcept { return mState != ThreadState::Recording; }); } - - return hr; -} - - -void WasapiCapture::stop() -{ pushMessage(MsgType::StopDevice).wait(); } - -void WasapiCapture::stopProxy() -{ - if(!mCapture || !mThread.joinable()) - return; - - mKillNow.store(true, std::memory_order_release); - mThread.join(); - - mCapture = nullptr; - mClient->Stop(); - mClient->Reset(); } void WasapiCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } uint WasapiCapture::availableSamples() { return static_cast(mRing->readSpace()); } @@ -2686,7 +3049,7 @@ bool WasapiBackendFactory::init() std::promise promise; auto future = promise.get_future(); - std::thread{&WasapiProxy::messageHandler, &promise}.detach(); + std::thread{&DeviceEnumHelper::messageHandler, &promise}.detach(); InitResult = future.get(); } catch(...) { @@ -2698,9 +3061,9 @@ bool WasapiBackendFactory::init() bool WasapiBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string WasapiBackendFactory::probe(BackendType type) +auto WasapiBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; auto devlock = DeviceListLock{gDeviceList}; switch(type) @@ -2708,19 +3071,19 @@ std::string WasapiBackendFactory::probe(BackendType type) case BackendType::Playback: { auto defaultId = devlock.getPlaybackDefaultId(); - for(const DevMap &entry : devlock.getPlaybackList()) + auto &devlist = devlock.getPlaybackList(); + + outnames.reserve(devlist.size()); + std::transform(devlist.cbegin(), devlist.cend(), std::back_inserter(outnames), + std::mem_fn(&DevMap::name)); + + /* Default device goes first. */ + const auto defiter = std::find_if(devlist.cbegin(), devlist.cend(), + [defaultId](const DevMap &entry) -> bool { return entry.devid == defaultId; }); + if(defiter != devlist.cend()) { - if(entry.devid != defaultId) - { - /* +1 to also append the null char (to ensure a null- - * separated list and double-null terminated list). - */ - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); - continue; - } - /* Default device goes first. */ - std::string name{DevNameHead + entry.name}; - outnames.insert(0, name.c_str(), name.length()+1); + const auto defname = outnames.begin() + std::distance(devlist.cbegin(), defiter); + std::rotate(outnames.begin(), defname, defname+1); } } break; @@ -2728,15 +3091,19 @@ std::string WasapiBackendFactory::probe(BackendType type) case BackendType::Capture: { auto defaultId = devlock.getCaptureDefaultId(); - for(const DevMap &entry : devlock.getCaptureList()) + auto &devlist = devlock.getCaptureList(); + + outnames.reserve(devlist.size()); + std::transform(devlist.cbegin(), devlist.cend(), std::back_inserter(outnames), + std::mem_fn(&DevMap::name)); + + /* Default device goes first. */ + const auto defiter = std::find_if(devlist.cbegin(), devlist.cend(), + [defaultId](const DevMap &entry) -> bool { return entry.devid == defaultId; }); + if(defiter != devlist.cend()) { - if(entry.devid != defaultId) - { - outnames.append(DevNameHead).append(entry.name.c_str(), entry.name.length()+1); - continue; - } - std::string name{DevNameHead + entry.name}; - outnames.insert(0, name.c_str(), name.length()+1); + const auto defname = outnames.begin() + std::distance(devlist.cbegin(), defiter); + std::rotate(outnames.begin(), defname, defname+1); } } break; @@ -2759,3 +3126,22 @@ BackendFactory &WasapiBackendFactory::getFactory() static WasapiBackendFactory factory{}; return factory; } + +alc::EventSupport WasapiBackendFactory::queryEventSupport(alc::EventType eventType, BackendType) +{ + switch(eventType) + { + case alc::EventType::DefaultDeviceChanged: + return alc::EventSupport::FullSupport; + + case alc::EventType::DeviceAdded: + case alc::EventType::DeviceRemoved: +#if !ALSOFT_UWP + return alc::EventSupport::FullSupport; +#endif + + case alc::EventType::Count: + break; + } + return alc::EventSupport::NoSupport; +} diff --git a/3rdparty/openal/alc/backends/wasapi.h b/3rdparty/openal/alc/backends/wasapi.h index bb2671ee84a8..f3cb85413658 100644 --- a/3rdparty/openal/alc/backends/wasapi.h +++ b/3rdparty/openal/alc/backends/wasapi.h @@ -5,15 +5,17 @@ struct WasapiBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto queryEventSupport(alc::EventType eventType, BackendType type) -> alc::EventSupport final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - static BackendFactory &getFactory(); + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; + + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_WASAPI_H */ diff --git a/3rdparty/openal/alc/backends/wave.cpp b/3rdparty/openal/alc/backends/wave.cpp index 794d5cb87880..153e61452bf4 100644 --- a/3rdparty/openal/alc/backends/wave.cpp +++ b/3rdparty/openal/alc/backends/wave.cpp @@ -30,7 +30,7 @@ #include #include #include -#include +#include #include #include @@ -40,14 +40,13 @@ #include "alnumeric.h" #include "althrd_setname.h" #include "core/device.h" -#include "core/helpers.h" #include "core/logging.h" -#include "opthelpers.h" #include "strutils.h" namespace { +using namespace std::string_view_literals; using std::chrono::seconds; using std::chrono::milliseconds; using std::chrono::nanoseconds; @@ -55,43 +54,48 @@ using std::chrono::nanoseconds; using ubyte = unsigned char; using ushort = unsigned short; -constexpr char waveDevice[] = "Wave File Writer"; +struct FileDeleter { + void operator()(gsl::owner f) { fclose(f); } +}; +using FilePtr = std::unique_ptr; + +[[nodiscard]] constexpr auto GetDeviceName() noexcept { return "Wave File Writer"sv; } -constexpr ubyte SUBTYPE_PCM[]{ +constexpr std::array SUBTYPE_PCM{{ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -}; -constexpr ubyte SUBTYPE_FLOAT[]{ +}}; +constexpr std::array SUBTYPE_FLOAT{{ 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x00, 0x80, 0x00, 0x00, 0xaa, 0x00, 0x38, 0x9b, 0x71 -}; +}}; -constexpr ubyte SUBTYPE_BFORMAT_PCM[]{ +constexpr std::array SUBTYPE_BFORMAT_PCM{{ 0x01, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 -}; +}}; -constexpr ubyte SUBTYPE_BFORMAT_FLOAT[]{ +constexpr std::array SUBTYPE_BFORMAT_FLOAT{{ 0x03, 0x00, 0x00, 0x00, 0x21, 0x07, 0xd3, 0x11, 0x86, 0x44, 0xc8, 0xc1, 0xca, 0x00, 0x00, 0x00 -}; +}}; void fwrite16le(ushort val, FILE *f) { - ubyte data[2]{ static_cast(val&0xff), static_cast((val>>8)&0xff) }; - fwrite(data, 1, 2, f); + std::array data{static_cast(val&0xff), static_cast((val>>8)&0xff)}; + fwrite(data.data(), 1, data.size(), f); } void fwrite32le(uint val, FILE *f) { - ubyte data[4]{ static_cast(val&0xff), static_cast((val>>8)&0xff), - static_cast((val>>16)&0xff), static_cast((val>>24)&0xff) }; - fwrite(data, 1, 4, f); + std::array data{static_cast(val&0xff), static_cast((val>>8)&0xff), + static_cast((val>>16)&0xff), static_cast((val>>24)&0xff)}; + fwrite(data.data(), 1, data.size(), f); } struct WaveBackend final : public BackendBase { - WaveBackend(DeviceBase *device) noexcept : BackendBase{device} { } + explicit WaveBackend(DeviceBase *device) noexcept : BackendBase{device} { } ~WaveBackend() override; int mixerProc(); @@ -101,29 +105,22 @@ struct WaveBackend final : public BackendBase { void start() override; void stop() override; - FILE *mFile{nullptr}; + FilePtr mFile{nullptr}; long mDataStart{-1}; std::vector mBuffer; std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(WaveBackend) }; -WaveBackend::~WaveBackend() -{ - if(mFile) - fclose(mFile); - mFile = nullptr; -} +WaveBackend::~WaveBackend() = default; int WaveBackend::mixerProc() { - const milliseconds restTime{mDevice->UpdateSize*1000/mDevice->Frequency / 2}; + const milliseconds restTime{mDevice->mUpdateSize*1000/mDevice->mSampleRate / 2}; - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); const size_t frameStep{mDevice->channelsFromFmt()}; const size_t frameSize{mDevice->frameSizeFromFmt()}; @@ -136,17 +133,17 @@ int WaveBackend::mixerProc() auto now = std::chrono::steady_clock::now(); /* This converts from nanoseconds to nanosamples, then to samples. */ - int64_t avail{std::chrono::duration_cast((now-start) * - mDevice->Frequency).count()}; - if(avail-done < mDevice->UpdateSize) + const auto avail = int64_t{std::chrono::duration_cast((now-start) * + mDevice->mSampleRate).count()}; + if(avail-done < mDevice->mUpdateSize) { std::this_thread::sleep_for(restTime); continue; } - while(avail-done >= mDevice->UpdateSize) + while(avail-done >= mDevice->mUpdateSize) { - mDevice->renderSamples(mBuffer.data(), mDevice->UpdateSize, frameStep); - done += mDevice->UpdateSize; + mDevice->renderSamples(mBuffer.data(), mDevice->mUpdateSize, frameStep); + done += mDevice->mUpdateSize; if(al::endian::native != al::endian::little) { @@ -169,10 +166,10 @@ int WaveBackend::mixerProc() } } - const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->UpdateSize, mFile)}; - if(fs < mDevice->UpdateSize || ferror(mFile)) + const size_t fs{fwrite(mBuffer.data(), frameSize, mDevice->mUpdateSize, mFile.get())}; + if(fs < mDevice->mUpdateSize || ferror(mFile.get())) { - ERR("Error writing to file\n"); + ERR("Error writing to file"); mDevice->handleDisconnect("Failed to write playback samples"); break; } @@ -183,10 +180,10 @@ int WaveBackend::mixerProc() * and current time from growing too large, while maintaining the * correct number of samples to render. */ - if(done >= mDevice->Frequency) + if(done >= mDevice->mSampleRate) { - seconds s{done/mDevice->Frequency}; - done %= mDevice->Frequency; + seconds s{done/mDevice->mSampleRate}; + done %= mDevice->mSampleRate; start += s; } } @@ -196,15 +193,15 @@ int WaveBackend::mixerProc() void WaveBackend::open(std::string_view name) { - auto fname = ConfigValueStr(nullptr, "wave", "file"); + auto fname = ConfigValueStr({}, "wave", "file"); if(!fname) throw al::backend_exception{al::backend_error::NoDevice, "No wave output filename"}; if(name.empty()) - name = waveDevice; - else if(name != waveDevice) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + name = GetDeviceName(); + else if(name != GetDeviceName()) + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; /* There's only one "device", so if it's already open, we're done. */ if(mFile) return; @@ -212,28 +209,21 @@ void WaveBackend::open(std::string_view name) #ifdef _WIN32 { std::wstring wname{utf8_to_wstr(fname.value())}; - mFile = _wfopen(wname.c_str(), L"wb"); + mFile = FilePtr{_wfopen(wname.c_str(), L"wb")}; } #else - mFile = fopen(fname->c_str(), "wb"); + mFile = FilePtr{fopen(fname->c_str(), "wb")}; #endif if(!mFile) - throw al::backend_exception{al::backend_error::DeviceError, "Could not open file '%s': %s", - fname->c_str(), strerror(errno)}; + throw al::backend_exception{al::backend_error::DeviceError, "Could not open file '{}': {}", + *fname, std::generic_category().message(errno)}; - mDevice->DeviceName = name; + mDeviceName = name; } bool WaveBackend::reset() { - uint channels{0}, bytes{0}, chanmask{0}; - bool isbformat{false}; - size_t val; - - fseek(mFile, 0, SEEK_SET); - clearerr(mFile); - - if(GetConfigValueBool(nullptr, "wave", "bformat", false)) + if(GetConfigValueBool({}, "wave", "bformat", false)) { mDevice->FmtChans = DevFmtAmbi3D; mDevice->mAmbiOrder = 1; @@ -256,6 +246,8 @@ bool WaveBackend::reset() case DevFmtFloat: break; } + auto chanmask = 0u; + auto isbformat = false; switch(mDevice->FmtChans) { case DevFmtMono: chanmask = 0x04; break; @@ -264,6 +256,9 @@ bool WaveBackend::reset() case DevFmtX51: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x200 | 0x400; break; case DevFmtX61: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x100 | 0x200 | 0x400; break; case DevFmtX71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break; + case DevFmtX7144: + mDevice->FmtChans = DevFmtX714; + [[fallthrough]]; case DevFmtX714: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400 | 0x1000 | 0x4000 | 0x8000 | 0x20000; @@ -272,63 +267,73 @@ bool WaveBackend::reset() case DevFmtX3D71: chanmask = 0x01 | 0x02 | 0x04 | 0x08 | 0x010 | 0x020 | 0x200 | 0x400; break; case DevFmtAmbi3D: /* .amb output requires FuMa */ - mDevice->mAmbiOrder = minu(mDevice->mAmbiOrder, 3); + mDevice->mAmbiOrder = std::min(mDevice->mAmbiOrder, 3u); mDevice->mAmbiLayout = DevAmbiLayout::FuMa; mDevice->mAmbiScale = DevAmbiScaling::FuMa; isbformat = true; chanmask = 0; break; } - bytes = mDevice->bytesFromFmt(); - channels = mDevice->channelsFromFmt(); + const auto bytes = mDevice->bytesFromFmt(); + const auto channels = mDevice->channelsFromFmt(); - rewind(mFile); + if(fseek(mFile.get(), 0, SEEK_CUR) != 0) + { + /* ESPIPE means the underlying file isn't seekable, which is fine for + * piped output. + */ + if(auto errcode = errno; errcode != ESPIPE) + { + ERR("Failed to reset file offset: {} ({})", std::generic_category().message(errcode), + errcode); + } + } + clearerr(mFile.get()); - fputs("RIFF", mFile); - fwrite32le(0xFFFFFFFF, mFile); // 'RIFF' header len; filled in at close + fputs("RIFF", mFile.get()); + fwrite32le(0xFFFFFFFF, mFile.get()); // 'RIFF' header len; filled in at stop - fputs("WAVE", mFile); + fputs("WAVE", mFile.get()); - fputs("fmt ", mFile); - fwrite32le(40, mFile); // 'fmt ' header len; 40 bytes for EXTENSIBLE + fputs("fmt ", mFile.get()); + fwrite32le(40, mFile.get()); // 'fmt ' header len; 40 bytes for EXTENSIBLE // 16-bit val, format type id (extensible: 0xFFFE) - fwrite16le(0xFFFE, mFile); + fwrite16le(0xFFFE, mFile.get()); // 16-bit val, channel count - fwrite16le(static_cast(channels), mFile); + fwrite16le(static_cast(channels), mFile.get()); // 32-bit val, frequency - fwrite32le(mDevice->Frequency, mFile); + fwrite32le(mDevice->mSampleRate, mFile.get()); // 32-bit val, bytes per second - fwrite32le(mDevice->Frequency * channels * bytes, mFile); + fwrite32le(mDevice->mSampleRate * channels * bytes, mFile.get()); // 16-bit val, frame size - fwrite16le(static_cast(channels * bytes), mFile); + fwrite16le(static_cast(channels * bytes), mFile.get()); // 16-bit val, bits per sample - fwrite16le(static_cast(bytes * 8), mFile); + fwrite16le(static_cast(bytes * 8), mFile.get()); // 16-bit val, extra byte count - fwrite16le(22, mFile); + fwrite16le(22, mFile.get()); // 16-bit val, valid bits per sample - fwrite16le(static_cast(bytes * 8), mFile); + fwrite16le(static_cast(bytes * 8), mFile.get()); // 32-bit val, channel mask - fwrite32le(chanmask, mFile); + fwrite32le(chanmask, mFile.get()); // 16 byte GUID, sub-type format - val = fwrite((mDevice->FmtType == DevFmtFloat) ? - (isbformat ? SUBTYPE_BFORMAT_FLOAT : SUBTYPE_FLOAT) : - (isbformat ? SUBTYPE_BFORMAT_PCM : SUBTYPE_PCM), 1, 16, mFile); - (void)val; + std::ignore = fwrite((mDevice->FmtType == DevFmtFloat) ? + (isbformat ? SUBTYPE_BFORMAT_FLOAT.data() : SUBTYPE_FLOAT.data()) : + (isbformat ? SUBTYPE_BFORMAT_PCM.data() : SUBTYPE_PCM.data()), 1, 16, mFile.get()); - fputs("data", mFile); - fwrite32le(0xFFFFFFFF, mFile); // 'data' header len; filled in at close + fputs("data", mFile.get()); + fwrite32le(0xFFFFFFFF, mFile.get()); // 'data' header len; filled in at stop - if(ferror(mFile)) + if(ferror(mFile.get())) { - ERR("Error writing header: %s\n", strerror(errno)); + ERR("Error writing header: {}", std::generic_category().message(errno)); return false; } - mDataStart = ftell(mFile); + mDataStart = ftell(mFile.get()); setDefaultWFXChannelOrder(); - const uint bufsize{mDevice->frameSizeFromFmt() * mDevice->UpdateSize}; + const uint bufsize{mDevice->frameSizeFromFmt() * mDevice->mUpdateSize}; mBuffer.resize(bufsize); return true; @@ -336,15 +341,15 @@ bool WaveBackend::reset() void WaveBackend::start() { - if(mDataStart > 0 && fseek(mFile, 0, SEEK_END) != 0) - WARN("Failed to seek on output file\n"); + if(mDataStart > 0 && fseek(mFile.get(), 0, SEEK_END) != 0) + WARN("Failed to seek on output file"); try { mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WaveBackend::mixerProc), this}; + mThread = std::thread{&WaveBackend::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -356,14 +361,14 @@ void WaveBackend::stop() if(mDataStart > 0) { - long size{ftell(mFile)}; + long size{ftell(mFile.get())}; if(size > 0) { long dataLen{size - mDataStart}; - if(fseek(mFile, 4, SEEK_SET) == 0) - fwrite32le(static_cast(size-8), mFile); // 'WAVE' header len - if(fseek(mFile, mDataStart-4, SEEK_SET) == 0) - fwrite32le(static_cast(dataLen), mFile); // 'data' header len + if(fseek(mFile.get(), 4, SEEK_SET) == 0) + fwrite32le(static_cast(size-8), mFile.get()); // 'WAVE' header len + if(fseek(mFile.get(), mDataStart-4, SEEK_SET) == 0) + fwrite32le(static_cast(dataLen), mFile.get()); // 'data' header len } } } @@ -377,19 +382,16 @@ bool WaveBackendFactory::init() bool WaveBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback; } -std::string WaveBackendFactory::probe(BackendType type) +auto WaveBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; switch(type) { case BackendType::Playback: - /* Includes null char. */ - outnames.append(waveDevice, sizeof(waveDevice)); - break; + return std::vector{std::string{GetDeviceName()}}; case BackendType::Capture: break; } - return outnames; + return {}; } BackendPtr WaveBackendFactory::createBackend(DeviceBase *device, BackendType type) diff --git a/3rdparty/openal/alc/backends/wave.h b/3rdparty/openal/alc/backends/wave.h index e768d33617ca..85f4c76ff788 100644 --- a/3rdparty/openal/alc/backends/wave.h +++ b/3rdparty/openal/alc/backends/wave.h @@ -5,15 +5,15 @@ struct WaveBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_WAVE_H */ diff --git a/3rdparty/openal/alc/backends/winmm.cpp b/3rdparty/openal/alc/backends/winmm.cpp index f0fb0a1c2e0d..349a244de843 100644 --- a/3rdparty/openal/alc/backends/winmm.cpp +++ b/3rdparty/openal/alc/backends/winmm.cpp @@ -22,8 +22,8 @@ #include "winmm.h" -#include -#include +#include +#include #include #include @@ -36,7 +36,6 @@ #include #include #include -#include #include "alnumeric.h" #include "alsem.h" @@ -44,8 +43,10 @@ #include "core/device.h" #include "core/helpers.h" #include "core/logging.h" +#include "fmt/core.h" #include "ringbuffer.h" #include "strutils.h" +#include "vector.h" #ifndef WAVE_FORMAT_IEEE_FLOAT #define WAVE_FORMAT_IEEE_FLOAT 0x0003 @@ -53,16 +54,13 @@ namespace { -#define DEVNAME_HEAD "OpenAL Soft on " - - std::vector PlaybackDevices; std::vector CaptureDevices; bool checkName(const std::vector &list, const std::string &name) { return std::find(list.cbegin(), list.cend(), name) != list.cend(); } -void ProbePlaybackDevices(void) +void ProbePlaybackDevices() { PlaybackDevices.clear(); @@ -75,25 +73,21 @@ void ProbePlaybackDevices(void) WAVEOUTCAPSW WaveCaps{}; if(waveOutGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - const std::string basename{DEVNAME_HEAD + wstr_to_utf8(WaveCaps.szPname)}; + const auto basename = wstr_to_utf8(std::data(WaveCaps.szPname)); - int count{1}; - std::string newname{basename}; + auto count = 1; + auto newname = basename; while(checkName(PlaybackDevices, newname)) - { - newname = basename; - newname += " #"; - newname += std::to_string(++count); - } + newname = fmt::format("{} #{}", basename, ++count); dname = std::move(newname); - TRACE("Got device \"%s\", ID %u\n", dname.c_str(), i); + TRACE("Got device \"{}\", ID {}", dname, i); } PlaybackDevices.emplace_back(std::move(dname)); } } -void ProbeCaptureDevices(void) +void ProbeCaptureDevices() { CaptureDevices.clear(); @@ -106,19 +100,15 @@ void ProbeCaptureDevices(void) WAVEINCAPSW WaveCaps{}; if(waveInGetDevCapsW(i, &WaveCaps, sizeof(WaveCaps)) == MMSYSERR_NOERROR) { - const std::string basename{DEVNAME_HEAD + wstr_to_utf8(WaveCaps.szPname)}; + const auto basename = wstr_to_utf8(std::data(WaveCaps.szPname)); - int count{1}; - std::string newname{basename}; + auto count = 1; + auto newname = basename; while(checkName(CaptureDevices, newname)) - { - newname = basename; - newname += " #"; - newname += std::to_string(++count); - } + newname = fmt::format("{} #{}", basename, ++count); dname = std::move(newname); - TRACE("Got device \"%s\", ID %u\n", dname.c_str(), i); + TRACE("Got device \"{}\", ID {}", dname, i); } CaptureDevices.emplace_back(std::move(dname)); } @@ -126,7 +116,7 @@ void ProbeCaptureDevices(void) struct WinMMPlayback final : public BackendBase { - WinMMPlayback(DeviceBase *device) noexcept : BackendBase{device} { } + explicit WinMMPlayback(DeviceBase *device) noexcept : BackendBase{device} { } ~WinMMPlayback() override; void CALLBACK waveOutProc(HWAVEOUT device, UINT msg, DWORD_PTR param1, DWORD_PTR param2) noexcept; @@ -144,6 +134,7 @@ struct WinMMPlayback final : public BackendBase { al::semaphore mSem; uint mIdx{0u}; std::array mWaveBuffer{}; + al::vector mBuffer; HWAVEOUT mOutHdl{nullptr}; @@ -151,8 +142,6 @@ struct WinMMPlayback final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(WinMMPlayback) }; WinMMPlayback::~WinMMPlayback() @@ -160,9 +149,6 @@ WinMMPlayback::~WinMMPlayback() if(mOutHdl) waveOutClose(mOutHdl); mOutHdl = nullptr; - - al_free(mWaveBuffer[0].lpData); - std::fill(mWaveBuffer.begin(), mWaveBuffer.end(), WAVEHDR{}); } /* WinMMPlayback::waveOutProc @@ -180,7 +166,7 @@ void CALLBACK WinMMPlayback::waveOutProc(HWAVEOUT, UINT msg, DWORD_PTR, DWORD_PT FORCE_ALIGN int WinMMPlayback::mixerProc() { SetRTPriority(); - althrd_setname(MIXER_THREAD_NAME); + althrd_setname(GetMixerThreadName()); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) @@ -197,7 +183,7 @@ FORCE_ALIGN int WinMMPlayback::mixerProc() WAVEHDR &waveHdr = mWaveBuffer[widx]; if(++widx == mWaveBuffer.size()) widx = 0; - mDevice->renderSamples(waveHdr.lpData, mDevice->UpdateSize, mFormat.nChannels); + mDevice->renderSamples(waveHdr.lpData, mDevice->mUpdateSize, mFormat.nChannels); mWritable.fetch_sub(1, std::memory_order_acq_rel); waveOutWrite(mOutHdl, &waveHdr, sizeof(WAVEHDR)); } while(--todo); @@ -218,61 +204,57 @@ void WinMMPlayback::open(std::string_view name) std::find(PlaybackDevices.cbegin(), PlaybackDevices.cend(), name) : PlaybackDevices.cbegin(); if(iter == PlaybackDevices.cend()) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; auto DeviceID = static_cast(std::distance(PlaybackDevices.cbegin(), iter)); DevFmtType fmttype{mDevice->FmtType}; -retry_open: WAVEFORMATEX format{}; - if(fmttype == DevFmtFloat) - { - format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; - format.wBitsPerSample = 32; - } - else - { - format.wFormatTag = WAVE_FORMAT_PCM; - if(fmttype == DevFmtUByte || fmttype == DevFmtByte) - format.wBitsPerSample = 8; - else - format.wBitsPerSample = 16; - } - format.nChannels = ((mDevice->FmtChans == DevFmtMono) ? 1 : 2); - format.nBlockAlign = static_cast(format.wBitsPerSample * format.nChannels / 8); - format.nSamplesPerSec = mDevice->Frequency; - format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; - format.cbSize = 0; - - HWAVEOUT outHandle{}; - MMRESULT res{waveOutOpen(&outHandle, DeviceID, &format, - reinterpret_cast(&WinMMPlayback::waveOutProcC), - reinterpret_cast(this), CALLBACK_FUNCTION)}; - if(res != MMSYSERR_NOERROR) - { + do { + format = WAVEFORMATEX{}; if(fmttype == DevFmtFloat) { - fmttype = DevFmtShort; - goto retry_open; + format.wFormatTag = WAVE_FORMAT_IEEE_FLOAT; + format.wBitsPerSample = 32; } - throw al::backend_exception{al::backend_error::DeviceError, "waveOutOpen failed: %u", res}; - } + else + { + format.wFormatTag = WAVE_FORMAT_PCM; + if(fmttype == DevFmtUByte || fmttype == DevFmtByte) + format.wBitsPerSample = 8; + else + format.wBitsPerSample = 16; + } + format.nChannels = ((mDevice->FmtChans == DevFmtMono) ? 1 : 2); + format.nBlockAlign = static_cast(format.wBitsPerSample * format.nChannels / 8); + format.nSamplesPerSec = mDevice->mSampleRate; + format.nAvgBytesPerSec = format.nSamplesPerSec * format.nBlockAlign; + format.cbSize = 0; + + MMRESULT res{waveOutOpen(&mOutHdl, DeviceID, &format, + reinterpret_cast(&WinMMPlayback::waveOutProcC), + reinterpret_cast(this), CALLBACK_FUNCTION)}; + if(res == MMSYSERR_NOERROR) break; + + if(fmttype != DevFmtFloat) + throw al::backend_exception{al::backend_error::DeviceError, "waveOutOpen failed: {}", + res}; + + fmttype = DevFmtShort; + } while(true); - if(mOutHdl) - waveOutClose(mOutHdl); - mOutHdl = outHandle; mFormat = format; - mDevice->DeviceName = PlaybackDevices[DeviceID]; + mDeviceName = PlaybackDevices[DeviceID]; } bool WinMMPlayback::reset() { - mDevice->BufferSize = static_cast(uint64_t{mDevice->BufferSize} * - mFormat.nSamplesPerSec / mDevice->Frequency); - mDevice->BufferSize = (mDevice->BufferSize+3) & ~0x3u; - mDevice->UpdateSize = mDevice->BufferSize / 4; - mDevice->Frequency = mFormat.nSamplesPerSec; + mDevice->mBufferSize = static_cast(uint64_t{mDevice->mBufferSize} * + mFormat.nSamplesPerSec / mDevice->mSampleRate); + mDevice->mBufferSize = (mDevice->mBufferSize+3) & ~0x3u; + mDevice->mUpdateSize = mDevice->mBufferSize / 4; + mDevice->mSampleRate = mFormat.nSamplesPerSec; if(mFormat.wFormatTag == WAVE_FORMAT_IEEE_FLOAT) { @@ -280,7 +262,7 @@ bool WinMMPlayback::reset() mDevice->FmtType = DevFmtFloat; else { - ERR("Unhandled IEEE float sample depth: %d\n", mFormat.wBitsPerSample); + ERR("Unhandled IEEE float sample depth: {}", mFormat.wBitsPerSample); return false; } } @@ -292,13 +274,13 @@ bool WinMMPlayback::reset() mDevice->FmtType = DevFmtUByte; else { - ERR("Unhandled PCM sample depth: %d\n", mFormat.wBitsPerSample); + ERR("Unhandled PCM sample depth: {}", mFormat.wBitsPerSample); return false; } } else { - ERR("Unhandled format tag: 0x%04x\n", mFormat.wFormatTag); + ERR("Unhandled format tag: {:#04x}", as_unsigned(mFormat.wFormatTag)); return false; } @@ -308,16 +290,16 @@ bool WinMMPlayback::reset() mDevice->FmtChans = DevFmtMono; else { - ERR("Unhandled channel count: %d\n", mFormat.nChannels); + ERR("Unhandled channel count: {}", mFormat.nChannels); return false; } setDefaultWFXChannelOrder(); - uint BufferSize{mDevice->UpdateSize * mFormat.nChannels * mDevice->bytesFromFmt()}; + const uint BufferSize{mDevice->mUpdateSize * mFormat.nChannels * mDevice->bytesFromFmt()}; - al_free(mWaveBuffer[0].lpData); + decltype(mBuffer)(BufferSize*mWaveBuffer.size()).swap(mBuffer); mWaveBuffer[0] = WAVEHDR{}; - mWaveBuffer[0].lpData = static_cast(al_calloc(16, BufferSize * mWaveBuffer.size())); + mWaveBuffer[0].lpData = mBuffer.data(); mWaveBuffer[0].dwBufferLength = BufferSize; for(size_t i{1};i < mWaveBuffer.size();i++) { @@ -338,11 +320,11 @@ void WinMMPlayback::start() mWritable.store(static_cast(mWaveBuffer.size()), std::memory_order_release); mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WinMMPlayback::mixerProc), this}; + mThread = std::thread{&WinMMPlayback::mixerProc, this}; } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start mixing thread: %s", e.what()}; + "Failed to start mixing thread: {}", e.what()}; } } @@ -361,7 +343,7 @@ void WinMMPlayback::stop() struct WinMMCapture final : public BackendBase { - WinMMCapture(DeviceBase *device) noexcept : BackendBase{device} { } + explicit WinMMCapture(DeviceBase *device) noexcept : BackendBase{device} { } ~WinMMCapture() override; void CALLBACK waveInProc(HWAVEIN device, UINT msg, DWORD_PTR param1, DWORD_PTR param2) noexcept; @@ -380,6 +362,7 @@ struct WinMMCapture final : public BackendBase { al::semaphore mSem; uint mIdx{0}; std::array mWaveBuffer{}; + al::vector mBuffer; HWAVEIN mInHdl{nullptr}; @@ -389,8 +372,6 @@ struct WinMMCapture final : public BackendBase { std::atomic mKillNow{true}; std::thread mThread; - - DEF_NEWDEL(WinMMCapture) }; WinMMCapture::~WinMMCapture() @@ -399,9 +380,6 @@ WinMMCapture::~WinMMCapture() if(mInHdl) waveInClose(mInHdl); mInHdl = nullptr; - - al_free(mWaveBuffer[0].lpData); - std::fill(mWaveBuffer.begin(), mWaveBuffer.end(), WAVEHDR{}); } /* WinMMCapture::waveInProc @@ -418,7 +396,7 @@ void CALLBACK WinMMCapture::waveInProc(HWAVEIN, UINT msg, DWORD_PTR, DWORD_PTR) int WinMMCapture::captureProc() { - althrd_setname(RECORD_THREAD_NAME); + althrd_setname(GetRecordThreadName()); while(!mKillNow.load(std::memory_order_acquire) && mDevice->Connected.load(std::memory_order_acquire)) @@ -435,7 +413,8 @@ int WinMMCapture::captureProc() WAVEHDR &waveHdr = mWaveBuffer[widx]; widx = (widx+1) % mWaveBuffer.size(); - mRing->write(waveHdr.lpData, waveHdr.dwBytesRecorded / mFormat.nBlockAlign); + std::ignore = mRing->write(waveHdr.lpData, + waveHdr.dwBytesRecorded / mFormat.nBlockAlign); mReadable.fetch_sub(1, std::memory_order_acq_rel); waveInAddBuffer(mInHdl, &waveHdr, sizeof(WAVEHDR)); } while(--todo); @@ -456,8 +435,8 @@ void WinMMCapture::open(std::string_view name) std::find(CaptureDevices.cbegin(), CaptureDevices.cend(), name) : CaptureDevices.cbegin(); if(iter == CaptureDevices.cend()) - throw al::backend_exception{al::backend_error::NoDevice, "Device name \"%.*s\" not found", - static_cast(name.length()), name.data()}; + throw al::backend_exception{al::backend_error::NoDevice, "Device name \"{}\" not found", + name}; auto DeviceID = static_cast(std::distance(CaptureDevices.cbegin(), iter)); switch(mDevice->FmtChans) @@ -471,9 +450,10 @@ void WinMMCapture::open(std::string_view name) case DevFmtX61: case DevFmtX71: case DevFmtX714: + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: - throw al::backend_exception{al::backend_error::DeviceError, "%s capture not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} capture not supported", DevFmtChannelsString(mDevice->FmtChans)}; } @@ -488,7 +468,7 @@ void WinMMCapture::open(std::string_view name) case DevFmtByte: case DevFmtUShort: case DevFmtUInt: - throw al::backend_exception{al::backend_error::DeviceError, "%s samples not supported", + throw al::backend_exception{al::backend_error::DeviceError, "{} samples not supported", DevFmtTypeString(mDevice->FmtType)}; } @@ -498,7 +478,7 @@ void WinMMCapture::open(std::string_view name) mFormat.nChannels = static_cast(mDevice->channelsFromFmt()); mFormat.wBitsPerSample = static_cast(mDevice->bytesFromFmt() * 8); mFormat.nBlockAlign = static_cast(mFormat.wBitsPerSample * mFormat.nChannels / 8); - mFormat.nSamplesPerSec = mDevice->Frequency; + mFormat.nSamplesPerSec = mDevice->mSampleRate; mFormat.nAvgBytesPerSec = mFormat.nSamplesPerSec * mFormat.nBlockAlign; mFormat.cbSize = 0; @@ -506,7 +486,7 @@ void WinMMCapture::open(std::string_view name) reinterpret_cast(&WinMMCapture::waveInProcC), reinterpret_cast(this), CALLBACK_FUNCTION)}; if(res != MMSYSERR_NOERROR) - throw al::backend_exception{al::backend_error::DeviceError, "waveInOpen failed: %u", res}; + throw al::backend_exception{al::backend_error::DeviceError, "waveInOpen failed: {}", res}; // Ensure each buffer is 50ms each DWORD BufferSize{mFormat.nAvgBytesPerSec / 20u}; @@ -514,14 +494,14 @@ void WinMMCapture::open(std::string_view name) // Allocate circular memory buffer for the captured audio // Make sure circular buffer is at least 100ms in size - uint CapturedDataSize{mDevice->BufferSize}; - CapturedDataSize = static_cast(maxz(CapturedDataSize, BufferSize*mWaveBuffer.size())); + const auto CapturedDataSize = std::max(mDevice->mBufferSize, + BufferSize*mWaveBuffer.size()); mRing = RingBuffer::Create(CapturedDataSize, mFormat.nBlockAlign, false); - al_free(mWaveBuffer[0].lpData); + decltype(mBuffer)(BufferSize*mWaveBuffer.size()).swap(mBuffer); mWaveBuffer[0] = WAVEHDR{}; - mWaveBuffer[0].lpData = static_cast(al_calloc(16, BufferSize * mWaveBuffer.size())); + mWaveBuffer[0].lpData = mBuffer.data(); mWaveBuffer[0].dwBufferLength = BufferSize; for(size_t i{1};i < mWaveBuffer.size();++i) { @@ -530,7 +510,7 @@ void WinMMCapture::open(std::string_view name) mWaveBuffer[i].dwBufferLength = mWaveBuffer[i-1].dwBufferLength; } - mDevice->DeviceName = CaptureDevices[DeviceID]; + mDeviceName = CaptureDevices[DeviceID]; } void WinMMCapture::start() @@ -543,13 +523,13 @@ void WinMMCapture::start() } mKillNow.store(false, std::memory_order_release); - mThread = std::thread{std::mem_fn(&WinMMCapture::captureProc), this}; + mThread = std::thread{&WinMMCapture::captureProc, this}; waveInStart(mInHdl); } catch(std::exception& e) { throw al::backend_exception{al::backend_error::DeviceError, - "Failed to start recording thread: %s", e.what()}; + "Failed to start recording thread: {}", e.what()}; } } @@ -573,7 +553,7 @@ void WinMMCapture::stop() } void WinMMCapture::captureSamples(std::byte *buffer, uint samples) -{ mRing->read(buffer, samples); } +{ std::ignore = mRing->read(buffer, samples); } uint WinMMCapture::availableSamples() { return static_cast(mRing->readSpace()); } @@ -587,26 +567,23 @@ bool WinMMBackendFactory::init() bool WinMMBackendFactory::querySupport(BackendType type) { return type == BackendType::Playback || type == BackendType::Capture; } -std::string WinMMBackendFactory::probe(BackendType type) +auto WinMMBackendFactory::enumerate(BackendType type) -> std::vector { - std::string outnames; + std::vector outnames; auto add_device = [&outnames](const std::string &dname) -> void - { - /* +1 to also append the null char (to ensure a null-separated list and - * double-null terminated list). - */ - if(!dname.empty()) - outnames.append(dname.c_str(), dname.length()+1); - }; + { if(!dname.empty()) outnames.emplace_back(dname); }; + switch(type) { case BackendType::Playback: ProbePlaybackDevices(); + outnames.reserve(PlaybackDevices.size()); std::for_each(PlaybackDevices.cbegin(), PlaybackDevices.cend(), add_device); break; case BackendType::Capture: ProbeCaptureDevices(); + outnames.reserve(CaptureDevices.size()); std::for_each(CaptureDevices.cbegin(), CaptureDevices.cend(), add_device); break; } diff --git a/3rdparty/openal/alc/backends/winmm.h b/3rdparty/openal/alc/backends/winmm.h index 45a706aa341e..51ce432ca346 100644 --- a/3rdparty/openal/alc/backends/winmm.h +++ b/3rdparty/openal/alc/backends/winmm.h @@ -5,15 +5,15 @@ struct WinMMBackendFactory final : public BackendFactory { public: - bool init() override; + auto init() -> bool final; - bool querySupport(BackendType type) override; + auto querySupport(BackendType type) -> bool final; - std::string probe(BackendType type) override; + auto enumerate(BackendType type) -> std::vector final; - BackendPtr createBackend(DeviceBase *device, BackendType type) override; + auto createBackend(DeviceBase *device, BackendType type) -> BackendPtr final; - static BackendFactory &getFactory(); + static auto getFactory() -> BackendFactory&; }; #endif /* BACKENDS_WINMM_H */ diff --git a/3rdparty/openal/alc/context.cpp b/3rdparty/openal/alc/context.cpp index 8c930056fdaf..3e1c5f870a56 100644 --- a/3rdparty/openal/alc/context.cpp +++ b/3rdparty/openal/alc/context.cpp @@ -5,13 +5,13 @@ #include #include -#include +#include #include -#include +#include #include -#include -#include +#include #include +#include #include #include "AL/efx.h" @@ -24,75 +24,78 @@ #include "al/listener.h" #include "albit.h" #include "alc/alu.h" +#include "alc/backends/base.h" +#include "alnumeric.h" #include "alspan.h" +#include "atomic.h" #include "core/async_event.h" +#include "core/devformat.h" #include "core/device.h" #include "core/effectslot.h" #include "core/logging.h" -#include "core/voice.h" #include "core/voice_change.h" #include "device.h" +#include "flexarray.h" #include "ringbuffer.h" #include "vecmat.h" -#ifdef ALSOFT_EAX -#include -#include "alstring.h" +#if ALSOFT_EAX +#include "al/eax/call.h" #include "al/eax/globals.h" #endif // ALSOFT_EAX namespace { -using namespace std::placeholders; - +using namespace std::string_view_literals; using voidp = void*; /* Default context extensions */ std::vector getContextExtensions() noexcept { return std::vector{ - "AL_EXT_ALAW", - "AL_EXT_BFORMAT", - "AL_EXT_debug", - "AL_EXTX_direct_context", - "AL_EXT_DOUBLE", - "AL_EXT_EXPONENT_DISTANCE", - "AL_EXT_FLOAT32", - "AL_EXT_IMA4", - "AL_EXT_LINEAR_DISTANCE", - "AL_EXT_MCFORMATS", - "AL_EXT_MULAW", - "AL_EXT_MULAW_BFORMAT", - "AL_EXT_MULAW_MCFORMATS", - "AL_EXT_OFFSET", - "AL_EXT_source_distance_model", - "AL_EXT_SOURCE_RADIUS", - "AL_EXT_STATIC_BUFFER", - "AL_EXT_STEREO_ANGLES", - "AL_LOKI_quadriphonic", - "AL_SOFT_bformat_ex", - "AL_SOFTX_bformat_hoa", - "AL_SOFT_block_alignment", - "AL_SOFT_buffer_length_query", - "AL_SOFT_callback_buffer", - "AL_SOFTX_convolution_reverb", - "AL_SOFT_deferred_updates", - "AL_SOFT_direct_channels", - "AL_SOFT_direct_channels_remix", - "AL_SOFT_effect_target", - "AL_SOFT_events", - "AL_SOFT_gain_clamp_ex", - "AL_SOFTX_hold_on_disconnect", - "AL_SOFT_loop_points", - "AL_SOFTX_map_buffer", - "AL_SOFT_MSADPCM", - "AL_SOFT_source_latency", - "AL_SOFT_source_length", - "AL_SOFT_source_resampler", - "AL_SOFT_source_spatialize", - "AL_SOFT_source_start_delay", - "AL_SOFT_UHJ", - "AL_SOFT_UHJ_ex", + "AL_EXT_ALAW"sv, + "AL_EXT_BFORMAT"sv, + "AL_EXT_debug"sv, + "AL_EXT_direct_context"sv, + "AL_EXT_DOUBLE"sv, + "AL_EXT_EXPONENT_DISTANCE"sv, + "AL_EXT_FLOAT32"sv, + "AL_EXT_IMA4"sv, + "AL_EXT_LINEAR_DISTANCE"sv, + "AL_EXT_MCFORMATS"sv, + "AL_EXT_MULAW"sv, + "AL_EXT_MULAW_BFORMAT"sv, + "AL_EXT_MULAW_MCFORMATS"sv, + "AL_EXT_OFFSET"sv, + "AL_EXT_source_distance_model"sv, + "AL_EXT_SOURCE_RADIUS"sv, + "AL_EXT_STATIC_BUFFER"sv, + "AL_EXT_STEREO_ANGLES"sv, + "AL_LOKI_quadriphonic"sv, + "AL_SOFT_bformat_ex"sv, + "AL_SOFT_bformat_hoa"sv, + "AL_SOFT_block_alignment"sv, + "AL_SOFT_buffer_length_query"sv, + "AL_SOFT_callback_buffer"sv, + "AL_SOFTX_convolution_effect"sv, + "AL_SOFT_deferred_updates"sv, + "AL_SOFT_direct_channels"sv, + "AL_SOFT_direct_channels_remix"sv, + "AL_SOFT_effect_target"sv, + "AL_SOFT_events"sv, + "AL_SOFT_gain_clamp_ex"sv, + "AL_SOFTX_hold_on_disconnect"sv, + "AL_SOFT_loop_points"sv, + "AL_SOFTX_map_buffer"sv, + "AL_SOFT_MSADPCM"sv, + "AL_SOFT_source_latency"sv, + "AL_SOFT_source_length"sv, + "AL_SOFTX_source_panning"sv, + "AL_SOFT_source_resampler"sv, + "AL_SOFT_source_spatialize"sv, + "AL_SOFT_source_start_delay"sv, + "AL_SOFT_UHJ"sv, + "AL_SOFT_UHJ_ex"sv, }; } @@ -107,7 +110,7 @@ ALCcontext::ThreadCtx::~ThreadCtx() if(ALCcontext *ctx{std::exchange(ALCcontext::sLocalContext, nullptr)}) { const bool result{ctx->releaseIfNoDelete()}; - ERR("Context %p current for thread being destroyed%s!\n", voidp{ctx}, + ERR("Context {} current for thread being destroyed{}!", voidp{ctx}, result ? "" : ", leak detected"); } } @@ -116,26 +119,30 @@ thread_local ALCcontext::ThreadCtx ALCcontext::sThreadContext; ALeffect ALCcontext::sDefaultEffect; -ALCcontext::ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags) +ALCcontext::ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags) : ContextBase{device.get()}, mALDevice{std::move(device)}, mContextFlags{flags} { mDebugGroups.emplace_back(DebugSource::Other, 0, std::string{}); mDebugEnabled.store(mContextFlags.test(ContextFlags::DebugBit), std::memory_order_relaxed); + + /* Low-severity debug messages are disabled by default. */ + alDebugMessageControlDirectEXT(this, AL_DONT_CARE_EXT, AL_DONT_CARE_EXT, + AL_DEBUG_SEVERITY_LOW_EXT, 0, nullptr, AL_FALSE); } ALCcontext::~ALCcontext() { - TRACE("Freeing context %p\n", voidp{this}); + TRACE("Freeing context {}", voidp{this}); size_t count{std::accumulate(mSourceList.cbegin(), mSourceList.cend(), 0_uz, [](size_t cur, const SourceSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); })}; if(count > 0) - WARN("%zu Source%s not deleted\n", count, (count==1)?"":"s"); + WARN("{} Source{} not deleted", count, (count==1)?"":"s"); mSourceList.clear(); mNumSources = 0; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eaxUninitialize(); #endif // ALSOFT_EAX @@ -144,7 +151,7 @@ ALCcontext::~ALCcontext() [](size_t cur, const EffectSlotSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) - WARN("%zu AuxiliaryEffectSlot%s not deleted\n", count, (count==1)?"":"s"); + WARN("{} AuxiliaryEffectSlot{} not deleted", count, (count==1)?"":"s"); mEffectSlotList.clear(); mNumEffectSlots = 0; } @@ -157,16 +164,17 @@ void ALCcontext::init() aluInitEffectPanning(mDefaultSlot->mSlot, this); } - EffectSlotArray *auxslots; + std::unique_ptr auxslots; if(!mDefaultSlot) auxslots = EffectSlot::CreatePtrArray(0); else { - auxslots = EffectSlot::CreatePtrArray(1); + auxslots = EffectSlot::CreatePtrArray(2); (*auxslots)[0] = mDefaultSlot->mSlot; + (*auxslots)[1] = mDefaultSlot->mSlot; mDefaultSlot->mState = SlotState::Playing; } - mActiveAuxSlots.store(auxslots, std::memory_order_relaxed); + mActiveAuxSlots.store(std::move(auxslots), std::memory_order_relaxed); allocVoiceChanges(); { @@ -180,15 +188,17 @@ void ALCcontext::init() if(sBufferSubDataCompat) { - auto iter = std::find(mExtensions.begin(), mExtensions.end(), "AL_EXT_SOURCE_RADIUS"); + auto iter = std::find(mExtensions.begin(), mExtensions.end(), "AL_EXT_SOURCE_RADIUS"sv); if(iter != mExtensions.end()) mExtensions.erase(iter); - /* TODO: Would be nice to sort this alphabetically. Needs case- - * insensitive searching. + + /* Insert the AL_SOFT_buffer_sub_data extension string between + * AL_SOFT_buffer_length_query and AL_SOFT_callback_buffer. */ - mExtensions.emplace_back("AL_SOFT_buffer_sub_data"); + iter = std::find(mExtensions.begin(), mExtensions.end(), "AL_SOFT_callback_buffer"sv); + mExtensions.emplace(iter, "AL_SOFT_buffer_sub_data"sv); } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX eax_initialize_extensions(); #endif // ALSOFT_EAX @@ -211,19 +221,31 @@ void ALCcontext::init() mExtensionsString = std::move(extensions); } +#if ALSOFT_EAX + eax_set_defaults(); +#endif + mParams.Position = alu::Vector{0.0f, 0.0f, 0.0f, 1.0f}; mParams.Matrix = alu::Matrix::Identity(); mParams.Velocity = alu::Vector{}; mParams.Gain = mListener.Gain; - mParams.MetersPerUnit = mListener.mMetersPerUnit; + mParams.MetersPerUnit = mListener.mMetersPerUnit +#if ALSOFT_EAX + * eaxGetDistanceFactor() +#endif + ; mParams.AirAbsorptionGainHF = mAirAbsorptionGainHF; mParams.DopplerFactor = mDopplerFactor; - mParams.SpeedOfSound = mSpeedOfSound * mDopplerVelocity; + mParams.SpeedOfSound = mSpeedOfSound * mDopplerVelocity +#if ALSOFT_EAX + / eaxGetDistanceFactor() +#endif + ; mParams.SourceDistanceModel = mSourceDistanceModel; mParams.mDistanceModel = mDistanceModel; - mAsyncEvents = RingBuffer::Create(511, sizeof(AsyncEvent), false); + mAsyncEvents = RingBuffer::Create(1024, sizeof(AsyncEvent), false); StartEventThrd(this); @@ -231,63 +253,58 @@ void ALCcontext::init() mActiveVoiceCount.store(64, std::memory_order_relaxed); } -bool ALCcontext::deinit() +void ALCcontext::deinit() { if(sLocalContext == this) { - WARN("%p released while current on thread\n", voidp{this}); + WARN("{} released while current on thread", voidp{this}); + auto _ = ContextRef{sLocalContext}; sThreadContext.set(nullptr); - dec_ref(); } - ALCcontext *origctx{this}; - if(sGlobalContext.compare_exchange_strong(origctx, nullptr)) + if(ALCcontext *origctx{this}; sGlobalContext.compare_exchange_strong(origctx, nullptr)) { + auto _ = ContextRef{origctx}; while(sGlobalContextLock.load()) { /* Wait to make sure another thread didn't get the context and is * trying to increment its refcount. */ } - dec_ref(); } - bool ret{}; + bool stopPlayback{}; /* First make sure this context exists in the device's list. */ - auto *oldarray = mDevice->mContexts.load(std::memory_order_acquire); - if(auto toremove = static_cast(std::count(oldarray->begin(), oldarray->end(), this))) + auto oldarray = al::span{*mDevice->mContexts.load(std::memory_order_acquire)}; + if(auto toremove = static_cast(std::count(oldarray.begin(), oldarray.end(), this))) { using ContextArray = al::FlexArray; - auto alloc_ctx_array = [](const size_t count) -> ContextArray* - { - if(count == 0) return &DeviceBase::sEmptyContextArray; - return ContextArray::Create(count).release(); - }; - auto *newarray = alloc_ctx_array(oldarray->size() - toremove); + const auto newsize = size_t{oldarray.size() - toremove}; + auto newarray = ContextArray::Create(newsize); /* Copy the current/old context handles to the new array, excluding the * given context. */ - std::copy_if(oldarray->begin(), oldarray->end(), newarray->begin(), + std::copy_if(oldarray.begin(), oldarray.end(), newarray->begin(), [this](ContextBase *ctx) { return ctx != this; }); /* Store the new context array in the device. Wait for any current mix * to finish before deleting the old array. */ - mDevice->mContexts.store(newarray); - if(oldarray != &DeviceBase::sEmptyContextArray) - { - mDevice->waitForMix(); - delete oldarray; - } + auto prevarray = mDevice->mContexts.exchange(std::move(newarray)); + std::ignore = mDevice->waitForMix(); - ret = !newarray->empty(); + stopPlayback = (newsize == 0); } else - ret = !oldarray->empty(); + stopPlayback = oldarray.empty(); StopEventThrd(this); - return ret; + if(stopPlayback && mALDevice->mDeviceState == DeviceState::Playing) + { + mALDevice->Backend->stop(); + mALDevice->mDeviceState = DeviceState::Configured; + } } void ALCcontext::applyAllUpdates() @@ -300,7 +317,7 @@ void ALCcontext::applyAllUpdates() /* busy-wait */ } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX if(mEaxNeedsCommit) eaxCommit(); #endif @@ -317,7 +334,7 @@ void ALCcontext::applyAllUpdates() } -#ifdef ALSOFT_EAX +#if ALSOFT_EAX namespace { template @@ -328,10 +345,10 @@ void ForEachSource(ALCcontext *context, F func) uint64_t usemask{~sublist.FreeMask}; while(usemask) { - const int idx{al::countr_zero(usemask)}; + const auto idx = static_cast(al::countr_zero(usemask)); usemask &= ~(1_u64 << idx); - func(sublist.Sources[idx]); + func((*sublist.Sources)[idx]); } } } @@ -469,14 +486,14 @@ void ALCcontext::eax_initialize_extensions() if(!eax_g_is_enabled) return; - mExtensions.emplace(mExtensions.begin(), eax_x_ram_ext_name); + mExtensions.emplace(mExtensions.begin(), "EAX-RAM"sv); if(eaxIsCapable()) { - mExtensions.emplace(mExtensions.begin(), eax5_ext_name); - mExtensions.emplace(mExtensions.begin(), eax4_ext_name); - mExtensions.emplace(mExtensions.begin(), eax3_ext_name); - mExtensions.emplace(mExtensions.begin(), eax2_ext_name); - mExtensions.emplace(mExtensions.begin(), eax1_ext_name); + mExtensions.emplace(mExtensions.begin(), "EAX5.0"sv); + mExtensions.emplace(mExtensions.begin(), "EAX4.0"sv); + mExtensions.emplace(mExtensions.begin(), "EAX3.0"sv); + mExtensions.emplace(mExtensions.begin(), "EAX2.0"sv); + mExtensions.emplace(mExtensions.begin(), "EAX"sv); } } @@ -495,7 +512,7 @@ void ALCcontext::eax_initialize() eax_ensure_compatibility(); eax_set_defaults(); - eax_context_commit_air_absorbtion_hf(); + eax_context_commit_air_absorption_hf(); eax_update_speaker_configuration(); eax_initialize_fx_slots(); @@ -549,10 +566,11 @@ unsigned long ALCcontext::eax_detect_speaker_configuration() const case DevFmtX51: return SPEAKERS_5; case DevFmtX61: return SPEAKERS_6; case DevFmtX71: return SPEAKERS_7; - /* 7.1.4 is compatible with 7.1. This could instead be HEADPHONES to + /* 7.1.4(.4) is compatible with 7.1. This could instead be HEADPHONES to * suggest with-height surround sound (like HRTF). */ case DevFmtX714: return SPEAKERS_7; + case DevFmtX7144: return SPEAKERS_7; /* 3D7.1 is only compatible with 5.1. This could instead be HEADPHONES to * suggest full-sphere surround sound (like HRTF). */ @@ -563,7 +581,8 @@ unsigned long ALCcontext::eax_detect_speaker_configuration() const */ case DevFmtAmbi3D: return SPEAKERS_7; } - ERR(EAX_PREFIX "Unexpected device channel format 0x%x.\n", mDevice->FmtChans); + ERR(EAX_PREFIX "Unexpected device channel format {:#x}.", + uint{al::to_underlying(mDevice->FmtChans)}); return HEADPHONES; #undef EAX_PREFIX @@ -576,7 +595,7 @@ void ALCcontext::eax_update_speaker_configuration() void ALCcontext::eax_set_last_error_defaults() noexcept { - mEaxLastError = EAX_OK; + mEaxLastError = EAXCONTEXT_DEFAULTLASTERROR; } void ALCcontext::eax_session_set_defaults() noexcept @@ -621,7 +640,7 @@ void ALCcontext::eax_context_set_defaults() eax5_context_set_defaults(mEax5); mEax = mEax5.i; mEaxVersion = 5; - mEaxDf = EaxDirtyFlags{}; + mEaxDf.reset(); } void ALCcontext::eax_set_defaults() @@ -665,6 +684,7 @@ void ALCcontext::eax_get_misc(const EaxCall& call) break; case EAXCONTEXT_LASTERROR: call.set_value(mEaxLastError); + mEaxLastError = EAX_OK; break; case EAXCONTEXT_SPEAKERCONFIG: call.set_value(mEaxSpeakerConfig); @@ -747,14 +767,11 @@ void ALCcontext::eax_context_commit_primary_fx_slot_id() void ALCcontext::eax_context_commit_distance_factor() { - if(mListener.mMetersPerUnit == mEax.flDistanceFactor) - return; - - mListener.mMetersPerUnit = mEax.flDistanceFactor; + /* mEax.flDistanceFactor was changed, so the context props are dirty. */ mPropsDirty = true; } -void ALCcontext::eax_context_commit_air_absorbtion_hf() +void ALCcontext::eax_context_commit_air_absorption_hf() { const auto new_value = level_mb_to_gain(mEax.flAirAbsorptionHF); @@ -815,16 +832,16 @@ void ALCcontext::eax4_defer_all(const EaxCall& call, Eax4State& state) dst_d = src; if(dst_i.guidPrimaryFXSlotID != dst_d.guidPrimaryFXSlotID) - mEaxDf |= eax_primary_fx_slot_id_dirty_bit; + mEaxDf.set(eax_primary_fx_slot_id_dirty_bit); if(dst_i.flDistanceFactor != dst_d.flDistanceFactor) - mEaxDf |= eax_distance_factor_dirty_bit; + mEaxDf.set(eax_distance_factor_dirty_bit); if(dst_i.flAirAbsorptionHF != dst_d.flAirAbsorptionHF) - mEaxDf |= eax_air_absorption_hf_dirty_bit; + mEaxDf.set(eax_air_absorption_hf_dirty_bit); if(dst_i.flHFReference != dst_d.flHFReference) - mEaxDf |= eax_hf_reference_dirty_bit; + mEaxDf.set(eax_hf_reference_dirty_bit); } void ALCcontext::eax4_defer(const EaxCall& call, Eax4State& state) @@ -835,20 +852,20 @@ void ALCcontext::eax4_defer(const EaxCall& call, Eax4State& state) eax4_defer_all(call, state); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_defer( - call, state, &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID); + eax_defer(call, state, + &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_defer( - call, state, &EAX40CONTEXTPROPERTIES::flDistanceFactor); + eax_defer(call, state, + &EAX40CONTEXTPROPERTIES::flDistanceFactor); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_defer( - call, state, &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF); + eax_defer(call, state, + &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF); break; case EAXCONTEXT_HFREFERENCE: - eax_defer( - call, state, &EAX40CONTEXTPROPERTIES::flHFReference); + eax_defer(call, state, + &EAX40CONTEXTPROPERTIES::flHFReference); break; default: eax_set_misc(call); @@ -865,19 +882,19 @@ void ALCcontext::eax5_defer_all(const EaxCall& call, Eax5State& state) dst_d = src; if(dst_i.guidPrimaryFXSlotID != dst_d.guidPrimaryFXSlotID) - mEaxDf |= eax_primary_fx_slot_id_dirty_bit; + mEaxDf.set(eax_primary_fx_slot_id_dirty_bit); if(dst_i.flDistanceFactor != dst_d.flDistanceFactor) - mEaxDf |= eax_distance_factor_dirty_bit; + mEaxDf.set(eax_distance_factor_dirty_bit); if(dst_i.flAirAbsorptionHF != dst_d.flAirAbsorptionHF) - mEaxDf |= eax_air_absorption_hf_dirty_bit; + mEaxDf.set(eax_air_absorption_hf_dirty_bit); if(dst_i.flHFReference != dst_d.flHFReference) - mEaxDf |= eax_hf_reference_dirty_bit; + mEaxDf.set(eax_hf_reference_dirty_bit); if(dst_i.flMacroFXFactor != dst_d.flMacroFXFactor) - mEaxDf |= eax_macro_fx_factor_dirty_bit; + mEaxDf.set(eax_macro_fx_factor_dirty_bit); } void ALCcontext::eax5_defer(const EaxCall& call, Eax5State& state) @@ -888,24 +905,24 @@ void ALCcontext::eax5_defer(const EaxCall& call, Eax5State& state) eax5_defer_all(call, state); break; case EAXCONTEXT_PRIMARYFXSLOTID: - eax_defer( - call, state, &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID); + eax_defer(call, state, + &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID); break; case EAXCONTEXT_DISTANCEFACTOR: - eax_defer( - call, state, &EAX50CONTEXTPROPERTIES::flDistanceFactor); + eax_defer(call, state, + &EAX50CONTEXTPROPERTIES::flDistanceFactor); break; case EAXCONTEXT_AIRABSORPTIONHF: - eax_defer( - call, state, &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF); + eax_defer(call, state, + &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF); break; case EAXCONTEXT_HFREFERENCE: - eax_defer( - call, state, &EAX50CONTEXTPROPERTIES::flHFReference); + eax_defer(call, state, + &EAX50CONTEXTPROPERTIES::flHFReference); break; case EAXCONTEXT_MACROFXFACTOR: - eax_defer( - call, state, &EAX50CONTEXTPROPERTIES::flMacroFXFactor); + eax_defer(call, state, + &EAX50CONTEXTPROPERTIES::flMacroFXFactor); break; default: eax_set_misc(call); @@ -923,49 +940,49 @@ void ALCcontext::eax_set(const EaxCall& call) default: eax_fail_unknown_version(); } if(version != mEaxVersion) - mEaxDf = ~EaxDirtyFlags(); + mEaxDf.set(); mEaxVersion = version; } -void ALCcontext::eax4_context_commit(Eax4State& state, EaxDirtyFlags& dst_df) +void ALCcontext::eax4_context_commit(Eax4State& state, std::bitset& dst_df) { - if(mEaxDf == EaxDirtyFlags{}) + if(mEaxDf.none()) return; - eax_context_commit_property( - state, dst_df, &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID); - eax_context_commit_property( - state, dst_df, &EAX40CONTEXTPROPERTIES::flDistanceFactor); - eax_context_commit_property( - state, dst_df, &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF); - eax_context_commit_property( - state, dst_df, &EAX40CONTEXTPROPERTIES::flHFReference); + eax_context_commit_property(state, dst_df, + &EAX40CONTEXTPROPERTIES::guidPrimaryFXSlotID); + eax_context_commit_property(state, dst_df, + &EAX40CONTEXTPROPERTIES::flDistanceFactor); + eax_context_commit_property(state, dst_df, + &EAX40CONTEXTPROPERTIES::flAirAbsorptionHF); + eax_context_commit_property(state, dst_df, + &EAX40CONTEXTPROPERTIES::flHFReference); - mEaxDf = EaxDirtyFlags{}; + mEaxDf.reset(); } -void ALCcontext::eax5_context_commit(Eax5State& state, EaxDirtyFlags& dst_df) +void ALCcontext::eax5_context_commit(Eax5State& state, std::bitset& dst_df) { - if(mEaxDf == EaxDirtyFlags{}) + if(mEaxDf.none()) return; - eax_context_commit_property( - state, dst_df, &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID); - eax_context_commit_property( - state, dst_df, &EAX50CONTEXTPROPERTIES::flDistanceFactor); - eax_context_commit_property( - state, dst_df, &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF); - eax_context_commit_property( - state, dst_df, &EAX50CONTEXTPROPERTIES::flHFReference); - eax_context_commit_property( - state, dst_df, &EAX50CONTEXTPROPERTIES::flMacroFXFactor); + eax_context_commit_property(state, dst_df, + &EAX50CONTEXTPROPERTIES::guidPrimaryFXSlotID); + eax_context_commit_property(state, dst_df, + &EAX50CONTEXTPROPERTIES::flDistanceFactor); + eax_context_commit_property(state, dst_df, + &EAX50CONTEXTPROPERTIES::flAirAbsorptionHF); + eax_context_commit_property(state, dst_df, + &EAX50CONTEXTPROPERTIES::flHFReference); + eax_context_commit_property(state, dst_df, + &EAX50CONTEXTPROPERTIES::flMacroFXFactor); - mEaxDf = EaxDirtyFlags{}; + mEaxDf.reset(); } void ALCcontext::eax_context_commit() { - auto dst_df = EaxDirtyFlags{}; + auto dst_df = std::bitset{}; switch(mEaxVersion) { @@ -982,25 +999,25 @@ void ALCcontext::eax_context_commit() break; } - if(dst_df == EaxDirtyFlags{}) + if(dst_df.none()) return; - if((dst_df & eax_primary_fx_slot_id_dirty_bit) != EaxDirtyFlags{}) + if(dst_df.test(eax_primary_fx_slot_id_dirty_bit)) eax_context_commit_primary_fx_slot_id(); - if((dst_df & eax_distance_factor_dirty_bit) != EaxDirtyFlags{}) + if(dst_df.test(eax_distance_factor_dirty_bit)) eax_context_commit_distance_factor(); - if((dst_df & eax_air_absorption_hf_dirty_bit) != EaxDirtyFlags{}) - eax_context_commit_air_absorbtion_hf(); + if(dst_df.test(eax_air_absorption_hf_dirty_bit)) + eax_context_commit_air_absorption_hf(); - if((dst_df & eax_hf_reference_dirty_bit) != EaxDirtyFlags{}) + if(dst_df.test(eax_hf_reference_dirty_bit)) eax_context_commit_hf_reference(); - if((dst_df & eax_macro_fx_factor_dirty_bit) != EaxDirtyFlags{}) + if(dst_df.test(eax_macro_fx_factor_dirty_bit)) eax_context_commit_macro_fx_factor(); - if((dst_df & eax_primary_fx_slot_id_dirty_bit) != EaxDirtyFlags{}) + if(dst_df.test(eax_primary_fx_slot_id_dirty_bit)) eax_update_sources(); } @@ -1013,56 +1030,48 @@ void ALCcontext::eaxCommit() } -FORCE_ALIGN ALenum AL_APIENTRY EAXSet(const GUID *a, ALuint b, ALuint c, ALvoid *d, ALuint e) noexcept +FORCE_ALIGN auto AL_APIENTRY EAXSet(const GUID *property_set_id, ALuint property_id, + ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum { auto context = GetContextRef(); if(!context) UNLIKELY return AL_INVALID_OPERATION; - return EAXSetDirect(context.get(), a, b, c, d, e); + return EAXSetDirect(context.get(), property_set_id, property_id, source_id, value, value_size); } -FORCE_ALIGN ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const GUID *property_set_id, - ALuint property_id, ALuint property_source_id, ALvoid *property_value, - ALuint property_value_size) noexcept +FORCE_ALIGN auto AL_APIENTRY EAXSetDirect(ALCcontext *context, const GUID *property_set_id, + ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum try { std::lock_guard prop_lock{context->mPropLock}; - return context->eax_eax_set( - property_set_id, - property_id, - property_source_id, - property_value, - property_value_size); + return context->eax_eax_set(property_set_id, property_id, source_id, value, value_size); } catch(...) { - eax_log_exception(__func__); + context->eaxSetLastError(); + eax_log_exception(std::data(__func__)); return AL_INVALID_OPERATION; } -FORCE_ALIGN ALenum AL_APIENTRY EAXGet(const GUID *a, ALuint b, ALuint c, ALvoid *d, ALuint e) noexcept +FORCE_ALIGN auto AL_APIENTRY EAXGet(const GUID *property_set_id, ALuint property_id, + ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum { auto context = GetContextRef(); if(!context) UNLIKELY return AL_INVALID_OPERATION; - return EAXGetDirect(context.get(), a, b, c, d, e); + return EAXGetDirect(context.get(), property_set_id, property_id, source_id, value, value_size); } -FORCE_ALIGN ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const GUID *property_set_id, - ALuint property_id, ALuint property_source_id, ALvoid *property_value, - ALuint property_value_size) noexcept +FORCE_ALIGN auto AL_APIENTRY EAXGetDirect(ALCcontext *context, const GUID *property_set_id, + ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum try { std::lock_guard prop_lock{context->mPropLock}; - return context->eax_eax_get( - property_set_id, - property_id, - property_source_id, - property_value, - property_value_size); + return context->eax_eax_get(property_set_id, property_id, source_id, value, value_size); } catch(...) { - eax_log_exception(__func__); + context->eaxSetLastError(); + eax_log_exception(std::data(__func__)); return AL_INVALID_OPERATION; } #endif // ALSOFT_EAX diff --git a/3rdparty/openal/alc/context.h b/3rdparty/openal/alc/context.h index 201c88730adc..3791e0b6d9fe 100644 --- a/3rdparty/openal/alc/context.h +++ b/3rdparty/openal/alc/context.h @@ -1,11 +1,14 @@ #ifndef ALC_CONTEXT_H #define ALC_CONTEXT_H +#include "config.h" + #include +#include +#include #include #include #include -#include #include #include #include @@ -17,29 +20,31 @@ #include "AL/alext.h" #include "al/listener.h" -#include "almalloc.h" -#include "alnumeric.h" -#include "atomic.h" +#include "althreads.h" #include "core/context.h" -#include "inprogext.h" +#include "fmt/core.h" #include "intrusive_ptr.h" +#include "opthelpers.h" -#ifdef ALSOFT_EAX -#include "al/eax/call.h" +#if ALSOFT_EAX +#include "al/eax/api.h" #include "al/eax/exception.h" #include "al/eax/fx_slot_index.h" #include "al/eax/fx_slots.h" #include "al/eax/utils.h" + +class EaxCall; #endif // ALSOFT_EAX struct ALeffect; struct ALeffectslot; -struct ALsource; struct DebugGroup; +struct EffectSlotSubList; +struct SourceSubList; -enum class DebugSource : uint8_t; -enum class DebugType : uint8_t; -enum class DebugSeverity : uint8_t; +enum class DebugSource : std::uint8_t; +enum class DebugType : std::uint8_t; +enum class DebugSeverity : std::uint8_t; using uint = unsigned int; @@ -68,47 +73,19 @@ struct DebugLogEntry { }; -struct SourceSubList { - uint64_t FreeMask{~0_u64}; - ALsource *Sources{nullptr}; /* 64 */ - - SourceSubList() noexcept = default; - SourceSubList(const SourceSubList&) = delete; - SourceSubList(SourceSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Sources{rhs.Sources} - { rhs.FreeMask = ~0_u64; rhs.Sources = nullptr; } - ~SourceSubList(); - - SourceSubList& operator=(const SourceSubList&) = delete; - SourceSubList& operator=(SourceSubList&& rhs) noexcept - { std::swap(FreeMask, rhs.FreeMask); std::swap(Sources, rhs.Sources); return *this; } -}; - -struct EffectSlotSubList { - uint64_t FreeMask{~0_u64}; - ALeffectslot *EffectSlots{nullptr}; /* 64 */ - - EffectSlotSubList() noexcept = default; - EffectSlotSubList(const EffectSlotSubList&) = delete; - EffectSlotSubList(EffectSlotSubList&& rhs) noexcept - : FreeMask{rhs.FreeMask}, EffectSlots{rhs.EffectSlots} - { rhs.FreeMask = ~0_u64; rhs.EffectSlots = nullptr; } - ~EffectSlotSubList(); - - EffectSlotSubList& operator=(const EffectSlotSubList&) = delete; - EffectSlotSubList& operator=(EffectSlotSubList&& rhs) noexcept - { std::swap(FreeMask, rhs.FreeMask); std::swap(EffectSlots, rhs.EffectSlots); return *this; } -}; - -struct ALCcontext : public al::intrusive_ref, ContextBase { - const al::intrusive_ptr mALDevice; +namespace al { +struct Device; +} // namespace al +struct ALCcontext final : public al::intrusive_ref, ContextBase { + const al::intrusive_ptr mALDevice; bool mPropsDirty{true}; bool mDeferUpdates{false}; std::mutex mPropLock; - std::atomic mLastError{AL_NO_ERROR}; + al::tss mLastThreadError{AL_NO_ERROR}; const ContextFlagBitset mContextFlags; std::atomic mDebugEnabled{false}; @@ -145,23 +122,23 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { std::unique_ptr mDefaultSlot; std::vector mExtensions; - std::string mExtensionsString{}; + std::string mExtensionsString; std::unordered_map mSourceNames; std::unordered_map mEffectSlotNames; - ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); + ALCcontext(al::intrusive_ptr device, ContextFlagBitset flags); ALCcontext(const ALCcontext&) = delete; ALCcontext& operator=(const ALCcontext&) = delete; - ~ALCcontext(); + ~ALCcontext() final; void init(); /** * Removes the context from its device and removes it from being current on - * the running thread or globally. Returns true if other contexts still - * exist on the device. + * the running thread or globally. Stops device playback if this was the + * last context on its device. */ - bool deinit(); + void deinit(); /** * Defers/suspends updates for the given context's listener and sources. @@ -186,12 +163,18 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { */ void applyAllUpdates(); -#ifdef __USE_MINGW_ANSI_STDIO - [[gnu::format(gnu_printf, 3, 4)]] -#else - [[gnu::format(printf, 3, 4)]] -#endif - void setError(ALenum errorCode, const char *msg, ...); + void setErrorImpl(ALenum errorCode, const fmt::string_view fmt, fmt::format_args args); + + template + void setError(ALenum errorCode, fmt::format_string msg, Args&& ...args) + { setErrorImpl(errorCode, msg, fmt::make_format_args(args...)); } + + [[noreturn]] + void throw_error_impl(ALenum errorCode, const fmt::string_view fmt, fmt::format_args args); + + template [[noreturn]] + void throw_error(ALenum errorCode, fmt::format_string fmt, Args&&... args) + { throw_error_impl(errorCode, fmt, fmt::make_format_args(args...)); } void sendDebugMessage(std::unique_lock &debuglock, DebugSource source, DebugType type, ALuint id, DebugSeverity severity, std::string_view message); @@ -218,8 +201,19 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { */ class ThreadCtx { public: + ThreadCtx() = default; + ThreadCtx(const ThreadCtx&) = delete; + auto operator=(const ThreadCtx&) -> ThreadCtx& = delete; + ~ThreadCtx(); + /* NOLINTBEGIN(readability-convert-member-functions-to-static) + * This should be non-static to invoke construction of the thread-local + * sThreadContext, so that it's destructor gets run at thread exit to + * clear sLocalContext (which isn't a member variable to make read + * access efficient). + */ void set(ALCcontext *ctx) const noexcept { sLocalContext = ctx; } + /* NOLINTEND(readability-convert-member-functions-to-static) */ }; static thread_local ThreadCtx sThreadContext; @@ -230,10 +224,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { /* Default effect that applies to sources that don't have an effect on send 0. */ static ALeffect sDefaultEffect; - DEF_NEWDEL(ALCcontext) - -#ifdef ALSOFT_EAX -public: +#if ALSOFT_EAX bool hasEax() const noexcept { return mEaxIsInitialized; } bool eaxIsCapable() const noexcept; @@ -255,7 +246,11 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { void eaxSetLastError() noexcept; - EaxFxSlotIndex eaxGetPrimaryFxSlotIndex() const noexcept + [[nodiscard]] + auto eaxGetDistanceFactor() const noexcept -> float { return mEax.flDistanceFactor; } + + [[nodiscard]] + auto eaxGetPrimaryFxSlotIndex() const noexcept -> EaxFxSlotIndex { return mEaxPrimaryFxSlotIndex; } const ALeffectslot& eaxGetFxSlot(EaxFxSlotIndexValue fx_slot_index) const @@ -270,11 +265,14 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { { mEaxFxSlots.commit(); } private: - static constexpr auto eax_primary_fx_slot_id_dirty_bit = EaxDirtyFlags{1} << 0; - static constexpr auto eax_distance_factor_dirty_bit = EaxDirtyFlags{1} << 1; - static constexpr auto eax_air_absorption_hf_dirty_bit = EaxDirtyFlags{1} << 2; - static constexpr auto eax_hf_reference_dirty_bit = EaxDirtyFlags{1} << 3; - static constexpr auto eax_macro_fx_factor_dirty_bit = EaxDirtyFlags{1} << 4; + enum { + eax_primary_fx_slot_id_dirty_bit, + eax_distance_factor_dirty_bit, + eax_air_absorption_hf_dirty_bit, + eax_hf_reference_dirty_bit, + eax_macro_fx_factor_dirty_bit, + eax_dirty_bit_count + }; using Eax4Props = EAX40CONTEXTPROPERTIES; @@ -290,12 +288,11 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { Eax5Props d; // Deferred. }; - class ContextException : public EaxException - { + class ContextException final : public EaxException { public: - explicit ContextException(const char* message) + explicit ContextException(const char *message) : EaxException{"EAX_CONTEXT", message} - {} + { } }; struct Eax4PrimaryFxSlotIdValidator { @@ -443,7 +440,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { int mEaxVersion{}; // Current EAX version. bool mEaxNeedsCommit{}; - EaxDirtyFlags mEaxDf{}; // Dirty flags for the current EAX version. + std::bitset mEaxDf; // Dirty flags for the current EAX version. Eax5State mEax123{}; // EAX1/EAX2/EAX3 state. Eax4State mEax4{}; // EAX4 state. Eax5State mEax5{}; // EAX5 state. @@ -473,11 +470,11 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { // updates a dirty flag. template< typename TValidator, - EaxDirtyFlags TDirtyBit, + size_t DirtyBit, typename TMemberResult, typename TProps, typename TState> - void eax_defer(const EaxCall& call, TState& state, TMemberResult TProps::*member) noexcept + void eax_defer(const EaxCall& call, TState& state, TMemberResult TProps::*member) { const auto& src = call.get_value(); TValidator{}(src); @@ -486,20 +483,20 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { dst_d = src; if(dst_i != dst_d) - mEaxDf |= TDirtyBit; + mEaxDf.set(DirtyBit); } template< - EaxDirtyFlags TDirtyBit, + size_t DirtyBit, typename TMemberResult, typename TProps, typename TState> - void eax_context_commit_property(TState& state, EaxDirtyFlags& dst_df, + void eax_context_commit_property(TState& state, std::bitset& dst_df, TMemberResult TProps::*member) noexcept { - if((mEaxDf & TDirtyBit) != EaxDirtyFlags{}) + if(mEaxDf.test(DirtyBit)) { - dst_df |= TDirtyBit; + dst_df.set(DirtyBit); const auto& src_d = state.d.*member; state.i.*member = src_d; mEax.*member = src_d; @@ -537,7 +534,7 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { void eax_context_commit_primary_fx_slot_id(); void eax_context_commit_distance_factor(); - void eax_context_commit_air_absorbtion_hf(); + void eax_context_commit_air_absorption_hf(); void eax_context_commit_hf_reference(); void eax_context_commit_macro_fx_factor(); @@ -552,36 +549,28 @@ struct ALCcontext : public al::intrusive_ref, ContextBase { void eax5_defer(const EaxCall& call, Eax5State& state); void eax_set(const EaxCall& call); - void eax4_context_commit(Eax4State& state, EaxDirtyFlags& dst_df); - void eax5_context_commit(Eax5State& state, EaxDirtyFlags& dst_df); + void eax4_context_commit(Eax4State& state, std::bitset& dst_df); + void eax5_context_commit(Eax5State& state, std::bitset& dst_df); void eax_context_commit(); #endif // ALSOFT_EAX }; using ContextRef = al::intrusive_ptr; -ContextRef GetContextRef(void); +ContextRef GetContextRef() noexcept; void UpdateContextProps(ALCcontext *context); -extern bool TrapALError; +inline bool TrapALError{false}; -#ifdef ALSOFT_EAX -ALenum AL_APIENTRY EAXSet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, - ALuint property_value_size) noexcept; +#if ALSOFT_EAX +auto AL_APIENTRY EAXSet(const GUID *property_set_id, ALuint property_id, + ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum; -ALenum AL_APIENTRY EAXGet( - const GUID* property_set_id, - ALuint property_id, - ALuint property_source_id, - ALvoid* property_value, - ALuint property_value_size) noexcept; +auto AL_APIENTRY EAXGet(const GUID *property_set_id, ALuint property_id, + ALuint source_id, ALvoid *value, ALuint value_size) noexcept -> ALenum; #endif // ALSOFT_EAX #endif /* ALC_CONTEXT_H */ diff --git a/3rdparty/openal/alc/device.cpp b/3rdparty/openal/alc/device.cpp index 27aa6f36e349..ad6071605d2f 100644 --- a/3rdparty/openal/alc/device.cpp +++ b/3rdparty/openal/alc/device.cpp @@ -3,19 +3,22 @@ #include "device.h" +#include +#include #include -#include +#include "al/buffer.h" +#include "al/effect.h" +#include "al/filter.h" #include "albit.h" -#include "alconfig.h" +#include "alnumeric.h" +#include "atomic.h" #include "backends/base.h" -#include "core/bformatdec.h" -#include "core/bs2b.h" -#include "core/front_stablizer.h" +#include "core/devformat.h" #include "core/hrtf.h" #include "core/logging.h" #include "core/mastering.h" -#include "core/uhjfilter.h" +#include "flexarray.h" namespace { @@ -24,13 +27,14 @@ using voidp = void*; } // namespace +namespace al { -ALCdevice::ALCdevice(DeviceType type) : DeviceBase{type} +Device::Device(DeviceType type) : DeviceBase{type} { } -ALCdevice::~ALCdevice() +Device::~Device() { - TRACE("Freeing device %p\n", voidp{this}); + TRACE("Freeing device {}", voidp{this}); Backend = nullptr; @@ -38,35 +42,35 @@ ALCdevice::~ALCdevice() [](size_t cur, const BufferSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); })}; if(count > 0) - WARN("%zu Buffer%s not deleted\n", count, (count==1)?"":"s"); + WARN("{} Buffer{} not deleted", count, (count==1)?"":"s"); count = std::accumulate(EffectList.cbegin(), EffectList.cend(), 0_uz, [](size_t cur, const EffectSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) - WARN("%zu Effect%s not deleted\n", count, (count==1)?"":"s"); + WARN("{} Effect{} not deleted", count, (count==1)?"":"s"); count = std::accumulate(FilterList.cbegin(), FilterList.cend(), 0_uz, [](size_t cur, const FilterSubList &sublist) noexcept -> size_t { return cur + static_cast(al::popcount(~sublist.FreeMask)); }); if(count > 0) - WARN("%zu Filter%s not deleted\n", count, (count==1)?"":"s"); + WARN("{} Filter{} not deleted", count, (count==1)?"":"s"); } -void ALCdevice::enumerateHrtfs() +void Device::enumerateHrtfs() { - mHrtfList = EnumerateHrtf(configValue(nullptr, "hrtf-paths")); - if(auto defhrtfopt = configValue(nullptr, "default-hrtf")) + mHrtfList = EnumerateHrtf(configValue({}, "hrtf-paths")); + if(auto defhrtfopt = configValue({}, "default-hrtf")) { auto iter = std::find(mHrtfList.begin(), mHrtfList.end(), *defhrtfopt); if(iter == mHrtfList.end()) - WARN("Failed to find default HRTF \"%s\"\n", defhrtfopt->c_str()); + WARN("Failed to find default HRTF \"{}\"", *defhrtfopt); else if(iter != mHrtfList.begin()) std::rotate(mHrtfList.begin(), iter, iter+1); } } -auto ALCdevice::getOutputMode1() const noexcept -> OutputMode1 +auto Device::getOutputMode1() const noexcept -> OutputMode1 { if(mContexts.load(std::memory_order_relaxed)->empty()) return OutputMode1::Any; @@ -85,9 +89,12 @@ auto ALCdevice::getOutputMode1() const noexcept -> OutputMode1 case DevFmtX61: return OutputMode1::X61; case DevFmtX71: return OutputMode1::X71; case DevFmtX714: + case DevFmtX7144: case DevFmtX3D71: case DevFmtAmbi3D: break; } return OutputMode1::Any; } + +} // namespace al diff --git a/3rdparty/openal/alc/device.h b/3rdparty/openal/alc/device.h index 66f37a7ec534..1ca800c8be5c 100644 --- a/3rdparty/openal/alc/device.h +++ b/3rdparty/openal/alc/device.h @@ -1,85 +1,42 @@ #ifndef ALC_DEVICE_H #define ALC_DEVICE_H +#include "config.h" + #include #include #include #include -#include #include #include -#include +#include #include +#include "AL/al.h" #include "AL/alc.h" #include "AL/alext.h" #include "alconfig.h" -#include "almalloc.h" -#include "alnumeric.h" #include "core/device.h" -#include "inprogext.h" #include "intrusive_ptr.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include "al/eax/x_ram.h" #endif // ALSOFT_EAX -struct ALbuffer; -struct ALeffect; -struct ALfilter; struct BackendBase; +struct BufferSubList; +struct EffectSubList; +struct FilterSubList; using uint = unsigned int; -struct BufferSubList { - uint64_t FreeMask{~0_u64}; - ALbuffer *Buffers{nullptr}; /* 64 */ - - BufferSubList() noexcept = default; - BufferSubList(const BufferSubList&) = delete; - BufferSubList(BufferSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Buffers{rhs.Buffers} - { rhs.FreeMask = ~0_u64; rhs.Buffers = nullptr; } - ~BufferSubList(); - - BufferSubList& operator=(const BufferSubList&) = delete; - BufferSubList& operator=(BufferSubList&& rhs) noexcept - { std::swap(FreeMask, rhs.FreeMask); std::swap(Buffers, rhs.Buffers); return *this; } -}; - -struct EffectSubList { - uint64_t FreeMask{~0_u64}; - ALeffect *Effects{nullptr}; /* 64 */ - - EffectSubList() noexcept = default; - EffectSubList(const EffectSubList&) = delete; - EffectSubList(EffectSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Effects{rhs.Effects} - { rhs.FreeMask = ~0_u64; rhs.Effects = nullptr; } - ~EffectSubList(); - - EffectSubList& operator=(const EffectSubList&) = delete; - EffectSubList& operator=(EffectSubList&& rhs) noexcept - { std::swap(FreeMask, rhs.FreeMask); std::swap(Effects, rhs.Effects); return *this; } -}; - -struct FilterSubList { - uint64_t FreeMask{~0_u64}; - ALfilter *Filters{nullptr}; /* 64 */ +struct ALCdevice { virtual ~ALCdevice() = default; }; - FilterSubList() noexcept = default; - FilterSubList(const FilterSubList&) = delete; - FilterSubList(FilterSubList&& rhs) noexcept : FreeMask{rhs.FreeMask}, Filters{rhs.Filters} - { rhs.FreeMask = ~0_u64; rhs.Filters = nullptr; } - ~FilterSubList(); - - FilterSubList& operator=(const FilterSubList&) = delete; - FilterSubList& operator=(FilterSubList&& rhs) noexcept - { std::swap(FreeMask, rhs.FreeMask); std::swap(Filters, rhs.Filters); return *this; } -}; +namespace al { - -struct ALCdevice : public al::intrusive_ref, DeviceBase { +struct Device final : public ALCdevice, al::intrusive_ref, DeviceBase { /* This lock protects the device state (format, update size, etc) from * being from being changed in multiple threads, or being accessed while * being changed. It's also used to serialize calls to the backend. @@ -129,7 +86,7 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { std::mutex FilterLock; std::vector FilterList; -#ifdef ALSOFT_EAX +#if ALSOFT_EAX ALuint eax_x_ram_free_size{eax_x_ram_max_size}; #endif // ALSOFT_EAX @@ -138,37 +95,41 @@ struct ALCdevice : public al::intrusive_ref, DeviceBase { std::unordered_map mEffectNames; std::unordered_map mFilterNames; - ALCdevice(DeviceType type); - ~ALCdevice(); + std::string mVendorOverride; + std::string mVersionOverride; + std::string mRendererOverride; + + explicit Device(DeviceType type); + ~Device() final; void enumerateHrtfs(); - bool getConfigValueBool(const char *block, const char *key, bool def) - { return GetConfigValueBool(DeviceName.c_str(), block, key, def); } + bool getConfigValueBool(const std::string_view block, const std::string_view key, bool def) + { return GetConfigValueBool(mDeviceName, block, key, def); } template - inline std::optional configValue(const char *block, const char *key) = delete; - - DEF_NEWDEL(ALCdevice) + auto configValue(const std::string_view block, const std::string_view key) -> std::optional = delete; }; -template<> -inline std::optional ALCdevice::configValue(const char *block, const char *key) -{ return ConfigValueStr(DeviceName.c_str(), block, key); } -template<> -inline std::optional ALCdevice::configValue(const char *block, const char *key) -{ return ConfigValueInt(DeviceName.c_str(), block, key); } -template<> -inline std::optional ALCdevice::configValue(const char *block, const char *key) -{ return ConfigValueUInt(DeviceName.c_str(), block, key); } -template<> -inline std::optional ALCdevice::configValue(const char *block, const char *key) -{ return ConfigValueFloat(DeviceName.c_str(), block, key); } -template<> -inline std::optional ALCdevice::configValue(const char *block, const char *key) -{ return ConfigValueBool(DeviceName.c_str(), block, key); } +template<> inline +auto Device::configValue(const std::string_view block, const std::string_view key) -> std::optional +{ return ConfigValueStr(mDeviceName, block, key); } +template<> inline +auto Device::configValue(const std::string_view block, const std::string_view key) -> std::optional +{ return ConfigValueInt(mDeviceName, block, key); } +template<> inline +auto Device::configValue(const std::string_view block, const std::string_view key) -> std::optional +{ return ConfigValueUInt(mDeviceName, block, key); } +template<> inline +auto Device::configValue(const std::string_view block, const std::string_view key) -> std::optional +{ return ConfigValueFloat(mDeviceName, block, key); } +template<> inline +auto Device::configValue(const std::string_view block, const std::string_view key) -> std::optional +{ return ConfigValueBool(mDeviceName, block, key); } + +} // namespace al /** Stores the latest ALC device error. */ -void alcSetError(ALCdevice *device, ALCenum errorCode); +void alcSetError(al::Device *device, ALCenum errorCode); #endif diff --git a/3rdparty/openal/alc/effects/autowah.cpp b/3rdparty/openal/alc/effects/autowah.cpp index 4f874ef29262..90006c157d9c 100644 --- a/3rdparty/openal/alc/effects/autowah.cpp +++ b/3rdparty/openal/alc/effects/autowah.cpp @@ -22,24 +22,24 @@ #include #include +#include #include -#include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "intrusive_ptr.h" +struct BufferStorage; namespace { @@ -50,35 +50,37 @@ constexpr float QFactor{5.0f}; struct AutowahState final : public EffectState { /* Effect parameters */ - float mAttackRate; - float mReleaseRate; - float mResonanceGain; - float mPeakGain; - float mFreqMinNorm; - float mBandwidthNorm; - float mEnvDelay; + float mAttackRate{}; + float mReleaseRate{}; + float mResonanceGain{}; + float mPeakGain{}; + float mFreqMinNorm{}; + float mBandwidthNorm{}; + float mEnvDelay{}; /* Filter components derived from the envelope. */ - struct { - float cos_w0; - float alpha; - } mEnv[BufferLineSize]; + struct FilterParam { + float cos_w0{}; + float alpha{}; + }; + std::array mEnv; - struct { + struct ChannelData { uint mTargetChannel{InvalidChannelIndex}; - /* Effect filters' history. */ - struct { - float z1, z2; - } mFilter; + struct FilterHistory { + float z1{}, z2{}; + }; + FilterHistory mFilter; /* Effect gains for each output channel */ - float mCurrentGain; - float mTargetGain; - } mChans[MaxAmbiChannels]; + float mCurrentGain{}; + float mTargetGain{}; + }; + std::array mChans; /* Effects buffers */ - alignas(16) float mBufferOut[BufferLineSize]; + alignas(16) FloatBufferLine mBufferOut{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -86,8 +88,6 @@ struct AutowahState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(AutowahState) }; void AutowahState::deviceUpdate(const DeviceBase*, const BufferStorage*) @@ -118,18 +118,19 @@ void AutowahState::deviceUpdate(const DeviceBase*, const BufferStorage*) } void AutowahState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; - const auto frequency = static_cast(device->Frequency); + const auto frequency = static_cast(device->mSampleRate); - const float ReleaseTime{clampf(props->Autowah.ReleaseTime, 0.001f, 1.0f)}; + const float ReleaseTime{std::clamp(props.ReleaseTime, 0.001f, 1.0f)}; - mAttackRate = std::exp(-1.0f / (props->Autowah.AttackTime*frequency)); + mAttackRate = std::exp(-1.0f / (props.AttackTime*frequency)); mReleaseRate = std::exp(-1.0f / (ReleaseTime*frequency)); /* 0-20dB Resonance Peak gain */ - mResonanceGain = std::sqrt(std::log10(props->Autowah.Resonance)*10.0f / 3.0f); - mPeakGain = 1.0f - std::log10(props->Autowah.PeakGain / GainScale); + mResonanceGain = std::sqrt(std::log10(props.Resonance)*10.0f / 3.0f); + mPeakGain = 1.0f - std::log10(props.PeakGain / GainScale); mFreqMinNorm = MinFreq / frequency; mBandwidthNorm = (MaxFreq-MinFreq) / frequency; @@ -155,23 +156,22 @@ void AutowahState::process(const size_t samplesToDo, float env_delay{mEnvDelay}; for(size_t i{0u};i < samplesToDo;i++) { - float w0, sample, a; - /* Envelope follower described on the book: Audio Effects, Theory, * Implementation and Application. */ - sample = peak_gain * std::fabs(samplesIn[0][i]); - a = (sample > env_delay) ? attack_rate : release_rate; + const float sample{peak_gain * std::fabs(samplesIn[0][i])}; + const float a{(sample > env_delay) ? attack_rate : release_rate}; env_delay = lerpf(sample, env_delay, a); /* Calculate the cos and alpha components for this sample's filter. */ - w0 = minf((bandwidth*env_delay + freq_min), 0.46f) * (al::numbers::pi_v*2.0f); + const float w0{std::min(bandwidth*env_delay + freq_min, 0.46f) * + (al::numbers::pi_v*2.0f)}; mEnv[i].cos_w0 = std::cos(w0); mEnv[i].alpha = std::sin(w0)/(2.0f * QFactor); } mEnvDelay = env_delay; - auto chandata = std::begin(mChans); + auto chandata = mChans.begin(); for(const auto &insamples : samplesIn) { const size_t outidx{chandata->mTargetChannel}; @@ -194,18 +194,18 @@ void AutowahState::process(const size_t samplesToDo, { const float alpha{mEnv[i].alpha}; const float cos_w0{mEnv[i].cos_w0}; - float input, output; - float a[3], b[3]; - - b[0] = 1.0f + alpha*res_gain; - b[1] = -2.0f * cos_w0; - b[2] = 1.0f - alpha*res_gain; - a[0] = 1.0f + alpha/res_gain; - a[1] = -2.0f * cos_w0; - a[2] = 1.0f - alpha/res_gain; - - input = insamples[i]; - output = input*(b[0]/a[0]) + z1; + + const std::array b{ + 1.0f + alpha*res_gain, + -2.0f * cos_w0, + 1.0f - alpha*res_gain}; + const std::array a{ + 1.0f + alpha/res_gain, + -2.0f * cos_w0, + 1.0f - alpha/res_gain}; + + const float input{insamples[i]}; + const float output{input*(b[0]/a[0]) + z1}; z1 = input*(b[1]/a[0]) - output*(a[1]/a[0]) + z2; z2 = input*(b[2]/a[0]) - output*(a[2]/a[0]); mBufferOut[i] = output; @@ -214,8 +214,8 @@ void AutowahState::process(const size_t samplesToDo, chandata->mFilter.z2 = z2; /* Now, mix the processed sound data to the output. */ - MixSamples({mBufferOut, samplesToDo}, samplesOut[outidx].data(), chandata->mCurrentGain, - chandata->mTargetGain, samplesToDo); + MixSamples(al::span{mBufferOut}.first(samplesToDo), samplesOut[outidx], + chandata->mCurrentGain, chandata->mTargetGain, samplesToDo); ++chandata; } } diff --git a/3rdparty/openal/alc/effects/base.h b/3rdparty/openal/alc/effects/base.h index 95695857a4d7..a64880d26a54 100644 --- a/3rdparty/openal/alc/effects/base.h +++ b/3rdparty/openal/alc/effects/base.h @@ -4,23 +4,27 @@ #include "core/effects/base.h" -EffectStateFactory *NullStateFactory_getFactory(void); -EffectStateFactory *ReverbStateFactory_getFactory(void); -EffectStateFactory *StdReverbStateFactory_getFactory(void); -EffectStateFactory *AutowahStateFactory_getFactory(void); -EffectStateFactory *ChorusStateFactory_getFactory(void); -EffectStateFactory *CompressorStateFactory_getFactory(void); -EffectStateFactory *DistortionStateFactory_getFactory(void); -EffectStateFactory *EchoStateFactory_getFactory(void); -EffectStateFactory *EqualizerStateFactory_getFactory(void); -EffectStateFactory *FlangerStateFactory_getFactory(void); -EffectStateFactory *FshifterStateFactory_getFactory(void); -EffectStateFactory *ModulatorStateFactory_getFactory(void); -EffectStateFactory *PshifterStateFactory_getFactory(void); -EffectStateFactory* VmorpherStateFactory_getFactory(void); - -EffectStateFactory *DedicatedStateFactory_getFactory(void); - -EffectStateFactory *ConvolutionStateFactory_getFactory(void); +/* This is a user config option for modifying the overall output of the reverb + * effect. + */ +inline float ReverbBoost{1.0f}; + + +EffectStateFactory *NullStateFactory_getFactory(); +EffectStateFactory *ReverbStateFactory_getFactory(); +EffectStateFactory *ChorusStateFactory_getFactory(); +EffectStateFactory *AutowahStateFactory_getFactory(); +EffectStateFactory *CompressorStateFactory_getFactory(); +EffectStateFactory *DistortionStateFactory_getFactory(); +EffectStateFactory *EchoStateFactory_getFactory(); +EffectStateFactory *EqualizerStateFactory_getFactory(); +EffectStateFactory *FshifterStateFactory_getFactory(); +EffectStateFactory *ModulatorStateFactory_getFactory(); +EffectStateFactory *PshifterStateFactory_getFactory(); +EffectStateFactory* VmorpherStateFactory_getFactory(); + +EffectStateFactory *DedicatedStateFactory_getFactory(); + +EffectStateFactory *ConvolutionStateFactory_getFactory(); #endif /* EFFECTS_BASE_H */ diff --git a/3rdparty/openal/alc/effects/chorus.cpp b/3rdparty/openal/alc/effects/chorus.cpp index c84531d4411d..414dd458c464 100644 --- a/3rdparty/openal/alc/effects/chorus.cpp +++ b/3rdparty/openal/alc/effects/chorus.cpp @@ -22,20 +22,22 @@ #include #include -#include +#include #include -#include +#include +#include #include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" +#include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" +#include "core/cubic_tables.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "core/mixer/defs.h" @@ -43,11 +45,19 @@ #include "intrusive_ptr.h" #include "opthelpers.h" +struct BufferStorage; namespace { using uint = unsigned int; +constexpr auto inv_sqrt2 = static_cast(1.0 / al::numbers::sqrt2); +constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f}); +constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f}); +constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2}); +constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2}); + + struct ChorusState final : public EffectState { std::vector mDelayBuffer; uint mOffset{0}; @@ -58,16 +68,17 @@ struct ChorusState final : public EffectState { uint mLfoDisp{0}; /* Calculated delays to apply to the left and right outputs. */ - uint mModDelays[2][BufferLineSize]; + std::array,2> mModDelays{}; /* Temp storage for the modulated left and right outputs. */ - alignas(16) float mBuffer[2][BufferLineSize]; + alignas(16) std::array mBuffer{}; /* Gains for left and right outputs. */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array Current{}; + std::array Target{}; + }; + std::array mGains; /* effect parameters */ ChorusWaveform mWaveform{}; @@ -78,66 +89,70 @@ struct ChorusState final : public EffectState { void calcTriangleDelays(const size_t todo); void calcSinusoidDelays(const size_t todo); - void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; - void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, - const EffectTarget target) override; - void process(const size_t samplesToDo, const al::span samplesIn, - const al::span samplesOut) override; + void deviceUpdate(const DeviceBase *device, const float MaxDelay); + void update(const ContextBase *context, const EffectSlot *slot, const ChorusWaveform waveform, + const float delay, const float depth, const float feedback, const float rate, + int phase, const EffectTarget target); - DEF_NEWDEL(ChorusState) + void deviceUpdate(const DeviceBase *device, const BufferStorage*) final; + void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props_, + const EffectTarget target) final; + void process(const size_t samplesToDo, const al::span samplesIn, + const al::span samplesOut) final; }; + void ChorusState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) { - constexpr float max_delay{maxf(ChorusMaxDelay, FlangerMaxDelay)}; - - const auto frequency = static_cast(Device->Frequency); - const size_t maxlen{NextPowerOf2(float2uint(max_delay*2.0f*frequency) + 1u)}; + constexpr auto MaxDelay = std::max(ChorusMaxDelay, FlangerMaxDelay); + const auto frequency = static_cast(Device->mSampleRate); + const size_t maxlen{NextPowerOf2(float2uint(MaxDelay*2.0f*frequency) + 1u)}; if(maxlen != mDelayBuffer.size()) decltype(mDelayBuffer)(maxlen).swap(mDelayBuffer); std::fill(mDelayBuffer.begin(), mDelayBuffer.end(), 0.0f); for(auto &e : mGains) { - std::fill(std::begin(e.Current), std::end(e.Current), 0.0f); - std::fill(std::begin(e.Target), std::end(e.Target), 0.0f); + e.Current.fill(0.0f); + e.Target.fill(0.0f); } } -void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot, - const EffectProps *props, const EffectTarget target) +void ChorusState::update(const ContextBase *context, const EffectSlot *slot, + const EffectProps *props_, const EffectTarget target) { - constexpr int mindelay{(MaxResamplerPadding>>1) << MixerFracBits}; + static constexpr int mindelay{MaxResamplerEdge << gCubicTable.sTableBits}; + auto &props = std::get(*props_); /* The LFO depth is scaled to be relative to the sample delay. Clamp the * delay and depth to allow enough padding for resampling. */ - const DeviceBase *device{Context->mDevice}; - const auto frequency = static_cast(device->Frequency); + const DeviceBase *device{context->mDevice}; + const auto frequency = static_cast(device->mSampleRate); - mWaveform = props->Chorus.Waveform; + mWaveform = props.Waveform; - mDelay = maxi(float2int(props->Chorus.Delay*frequency*MixerFracOne + 0.5f), mindelay); - mDepth = minf(props->Chorus.Depth * static_cast(mDelay), + const auto stepscale = float{frequency * gCubicTable.sTableSteps}; + mDelay = std::max(float2int(std::round(props.Delay * stepscale)), mindelay); + mDepth = std::min(static_cast(mDelay) * props.Depth, static_cast(mDelay - mindelay)); - mFeedback = props->Chorus.Feedback; + mFeedback = props.Feedback; /* Gains for left and right sides */ - static constexpr auto inv_sqrt2 = static_cast(1.0 / al::numbers::sqrt2); - static constexpr auto lcoeffs_pw = CalcDirectionCoeffs(std::array{-1.0f, 0.0f, 0.0f}); - static constexpr auto rcoeffs_pw = CalcDirectionCoeffs(std::array{ 1.0f, 0.0f, 0.0f}); - static constexpr auto lcoeffs_nrml = CalcDirectionCoeffs(std::array{-inv_sqrt2, 0.0f, inv_sqrt2}); - static constexpr auto rcoeffs_nrml = CalcDirectionCoeffs(std::array{ inv_sqrt2, 0.0f, inv_sqrt2}); - auto &lcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? lcoeffs_nrml : lcoeffs_pw; - auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; + const bool ispairwise{device->mRenderMode == RenderMode::Pairwise}; + const auto lcoeffs = (!ispairwise) ? al::span{lcoeffs_nrml} : al::span{lcoeffs_pw}; + const auto rcoeffs = (!ispairwise) ? al::span{rcoeffs_nrml} : al::span{rcoeffs_pw}; + /* Attenuate the outputs by -3dB, since we duplicate a single mono input to + * separate left/right outputs. + */ + const auto gain = slot->Gain * (1.0f/al::numbers::sqrt2_v); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), Slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), Slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs, gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs, gain, mGains[1].Target); - float rate{props->Chorus.Rate}; - if(!(rate > 0.0f)) + if(!(props.Rate > 0.0f)) { mLfoOffset = 0; mLfoRange = 1; @@ -149,7 +164,9 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot, /* Calculate LFO coefficient (number of samples per cycle). Limit the * max range to avoid overflow when calculating the displacement. */ - uint lfo_range{float2uint(minf(frequency/rate + 0.5f, float{INT_MAX/360 - 180}))}; + static constexpr int range_limit{std::numeric_limits::max()/360 - 180}; + const auto range = std::round(frequency / props.Rate); + const uint lfo_range{float2uint(std::min(range, float{range_limit}))}; mLfoOffset = mLfoOffset * lfo_range / mLfoRange; mLfoRange = lfo_range; @@ -164,8 +181,8 @@ void ChorusState::update(const ContextBase *Context, const EffectSlot *Slot, } /* Calculate lfo phase displacement */ - int phase{props->Chorus.Phase}; - if(phase < 0) phase = 360 + phase; + auto phase = props.Phase; + if(phase < 0) phase += 360; mLfoDisp = (mLfoRange*static_cast(phase) + 180) / 360; } } @@ -178,9 +195,6 @@ void ChorusState::calcTriangleDelays(const size_t todo) const float depth{mDepth}; const int delay{mDelay}; - ASSUME(lfo_range > 0); - ASSUME(todo > 0); - auto gen_lfo = [lfo_scale,depth,delay](const uint offset) -> uint { const float offset_norm{static_cast(offset) * lfo_scale}; @@ -188,25 +202,24 @@ void ChorusState::calcTriangleDelays(const size_t todo) }; uint offset{mLfoOffset}; + ASSUME(lfo_range > offset); + auto ldelays = mModDelays[0].begin(); for(size_t i{0};i < todo;) { - size_t rem{minz(todo-i, lfo_range-offset)}; - do { - mModDelays[0][i++] = gen_lfo(offset++); - } while(--rem); - if(offset == lfo_range) - offset = 0; + const size_t rem{std::min(todo-i, size_t{lfo_range-offset})}; + ldelays = std::generate_n(ldelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); }); + if(offset == lfo_range) offset = 0; + i += rem; } offset = (mLfoOffset+mLfoDisp) % lfo_range; + auto rdelays = mModDelays[1].begin(); for(size_t i{0};i < todo;) { - size_t rem{minz(todo-i, lfo_range-offset)}; - do { - mModDelays[1][i++] = gen_lfo(offset++); - } while(--rem); - if(offset == lfo_range) - offset = 0; + const size_t rem{std::min(todo-i, size_t{lfo_range-offset})}; + rdelays = std::generate_n(rdelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); }); + if(offset == lfo_range) offset = 0; + i += rem; } mLfoOffset = static_cast(mLfoOffset+todo) % lfo_range; @@ -219,9 +232,6 @@ void ChorusState::calcSinusoidDelays(const size_t todo) const float depth{mDepth}; const int delay{mDelay}; - ASSUME(lfo_range > 0); - ASSUME(todo > 0); - auto gen_lfo = [lfo_scale,depth,delay](const uint offset) -> uint { const float offset_norm{static_cast(offset) * lfo_scale}; @@ -229,25 +239,24 @@ void ChorusState::calcSinusoidDelays(const size_t todo) }; uint offset{mLfoOffset}; + ASSUME(lfo_range > offset); + auto ldelays = mModDelays[0].begin(); for(size_t i{0};i < todo;) { - size_t rem{minz(todo-i, lfo_range-offset)}; - do { - mModDelays[0][i++] = gen_lfo(offset++); - } while(--rem); - if(offset == lfo_range) - offset = 0; + const size_t rem{std::min(todo-i, size_t{lfo_range-offset})}; + ldelays = std::generate_n(ldelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); }); + if(offset == lfo_range) offset = 0; + i += rem; } offset = (mLfoOffset+mLfoDisp) % lfo_range; + auto rdelays = mModDelays[1].begin(); for(size_t i{0};i < todo;) { - size_t rem{minz(todo-i, lfo_range-offset)}; - do { - mModDelays[1][i++] = gen_lfo(offset++); - } while(--rem); - if(offset == lfo_range) - offset = 0; + const size_t rem{std::min(todo-i, size_t{lfo_range-offset})}; + rdelays = std::generate_n(rdelays, rem, [&offset,gen_lfo] { return gen_lfo(offset++); }); + if(offset == lfo_range) offset = 0; + i += rem; } mLfoOffset = static_cast(mLfoOffset+todo) % lfo_range; @@ -255,10 +264,10 @@ void ChorusState::calcSinusoidDelays(const size_t todo) void ChorusState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - const size_t bufmask{mDelayBuffer.size()-1}; + const auto delaybuf = al::span{mDelayBuffer}; + const size_t bufmask{delaybuf.size()-1}; const float feedback{mFeedback}; const uint avgdelay{(static_cast(mDelay) + MixerFracHalf) >> MixerFracBits}; - float *RESTRICT delaybuf{mDelayBuffer.data()}; uint offset{mOffset}; if(mWaveform == ChorusWaveform::Sinusoid) @@ -266,35 +275,39 @@ void ChorusState::process(const size_t samplesToDo, const al::span(mBuffer[0])}; - float *RESTRICT rbuffer{al::assume_aligned<16>(mBuffer[1])}; + const auto ldelays = al::span{mModDelays[0]}; + const auto rdelays = al::span{mModDelays[1]}; + const auto lbuffer = al::span{mBuffer[0]}; + const auto rbuffer = al::span{mBuffer[1]}; for(size_t i{0u};i < samplesToDo;++i) { // Feed the buffer's input first (necessary for delays < 1). delaybuf[offset&bufmask] = samplesIn[0][i]; // Tap for the left output. - uint delay{offset - (ldelays[i]>>MixerFracBits)}; - float mu{static_cast(ldelays[i]&MixerFracMask) * (1.0f/MixerFracOne)}; - lbuffer[i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], - delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], mu); + size_t delay{offset - (ldelays[i] >> gCubicTable.sTableBits)}; + size_t phase{ldelays[i] & gCubicTable.sTableMask}; + lbuffer[i] = delaybuf[(delay+1) & bufmask]*gCubicTable.getCoeff0(phase) + + delaybuf[(delay ) & bufmask]*gCubicTable.getCoeff1(phase) + + delaybuf[(delay-1) & bufmask]*gCubicTable.getCoeff2(phase) + + delaybuf[(delay-2) & bufmask]*gCubicTable.getCoeff3(phase); // Tap for the right output. - delay = offset - (rdelays[i]>>MixerFracBits); - mu = static_cast(rdelays[i]&MixerFracMask) * (1.0f/MixerFracOne); - rbuffer[i] = cubic(delaybuf[(delay+1) & bufmask], delaybuf[(delay ) & bufmask], - delaybuf[(delay-1) & bufmask], delaybuf[(delay-2) & bufmask], mu); + delay = offset - (rdelays[i] >> gCubicTable.sTableBits); + phase = rdelays[i] & gCubicTable.sTableMask; + rbuffer[i] = delaybuf[(delay+1) & bufmask]*gCubicTable.getCoeff0(phase) + + delaybuf[(delay ) & bufmask]*gCubicTable.getCoeff1(phase) + + delaybuf[(delay-1) & bufmask]*gCubicTable.getCoeff2(phase) + + delaybuf[(delay-2) & bufmask]*gCubicTable.getCoeff3(phase); // Accumulate feedback from the average delay of the taps. delaybuf[offset&bufmask] += delaybuf[(offset-avgdelay) & bufmask] * feedback; ++offset; } - MixSamples({lbuffer, samplesToDo}, samplesOut, mGains[0].Current, mGains[0].Target, + MixSamples(lbuffer.first(samplesToDo), samplesOut, mGains[0].Current, mGains[0].Target, samplesToDo, 0); - MixSamples({rbuffer, samplesToDo}, samplesOut, mGains[1].Current, mGains[1].Target, + MixSamples(rbuffer.first(samplesToDo), samplesOut, mGains[1].Current, mGains[1].Target, samplesToDo, 0); mOffset = offset; @@ -306,15 +319,6 @@ struct ChorusStateFactory final : public EffectStateFactory { { return al::intrusive_ptr{new ChorusState{}}; } }; - -/* Flanger is basically a chorus with a really short delay. They can both use - * the same processing functions, so piggyback flanger on the chorus functions. - */ -struct FlangerStateFactory final : public EffectStateFactory { - al::intrusive_ptr create() override - { return al::intrusive_ptr{new ChorusState{}}; } -}; - } // namespace EffectStateFactory *ChorusStateFactory_getFactory() @@ -322,9 +326,3 @@ EffectStateFactory *ChorusStateFactory_getFactory() static ChorusStateFactory ChorusFactory{}; return &ChorusFactory; } - -EffectStateFactory *FlangerStateFactory_getFactory() -{ - static FlangerStateFactory FlangerFactory{}; - return &FlangerFactory; -} diff --git a/3rdparty/openal/alc/effects/compressor.cpp b/3rdparty/openal/alc/effects/compressor.cpp index 0a7ed67a78fb..27245b69c42f 100644 --- a/3rdparty/openal/alc/effects/compressor.cpp +++ b/3rdparty/openal/alc/effects/compressor.cpp @@ -32,48 +32,49 @@ #include "config.h" +#include #include +#include #include -#include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" -#include "alnumeric.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" -#include "core/mixer.h" #include "core/mixer/defs.h" #include "intrusive_ptr.h" +struct BufferStorage; struct ContextBase; namespace { -#define AMP_ENVELOPE_MIN 0.5f -#define AMP_ENVELOPE_MAX 2.0f +constexpr float AmpEnvelopeMin{0.5f}; +constexpr float AmpEnvelopeMax{2.0f}; -#define ATTACK_TIME 0.1f /* 100ms to rise from min to max */ -#define RELEASE_TIME 0.2f /* 200ms to drop from max to min */ +constexpr float AttackTime{0.1f}; /* 100ms to rise from min to max */ +constexpr float ReleaseTime{0.2f}; /* 200ms to drop from max to min */ struct CompressorState final : public EffectState { /* Effect gains for each channel */ - struct { + struct TargetGain { uint mTarget{InvalidChannelIndex}; float mGain{1.0f}; - } mChans[MaxAmbiChannels]; + }; + std::array mChans; /* Effect parameters */ bool mEnabled{true}; float mAttackMult{1.0f}; float mReleaseMult{1.0f}; float mEnvFollower{1.0f}; + alignas(16) FloatBufferLine mGains{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -81,8 +82,6 @@ struct CompressorState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(CompressorState) }; void CompressorState::deviceUpdate(const DeviceBase *device, const BufferStorage*) @@ -90,20 +89,20 @@ void CompressorState::deviceUpdate(const DeviceBase *device, const BufferStorage /* Number of samples to do a full attack and release (non-integer sample * counts are okay). */ - const float attackCount{static_cast(device->Frequency) * ATTACK_TIME}; - const float releaseCount{static_cast(device->Frequency) * RELEASE_TIME}; + const float attackCount{static_cast(device->mSampleRate) * AttackTime}; + const float releaseCount{static_cast(device->mSampleRate) * ReleaseTime}; /* Calculate per-sample multipliers to attack and release at the desired * rates. */ - mAttackMult = std::pow(AMP_ENVELOPE_MAX/AMP_ENVELOPE_MIN, 1.0f/attackCount); - mReleaseMult = std::pow(AMP_ENVELOPE_MIN/AMP_ENVELOPE_MAX, 1.0f/releaseCount); + mAttackMult = std::pow(AmpEnvelopeMax/AmpEnvelopeMin, 1.0f/attackCount); + mReleaseMult = std::pow(AmpEnvelopeMin/AmpEnvelopeMax, 1.0f/releaseCount); } void CompressorState::update(const ContextBase*, const EffectSlot *slot, const EffectProps *props, const EffectTarget target) { - mEnabled = props->Compressor.OnOff; + mEnabled = std::get(*props).OnOff; mOutTarget = target.Main->Buffer; auto set_channel = [this](size_t idx, uint outchan, float outgain) @@ -117,72 +116,62 @@ void CompressorState::update(const ContextBase*, const EffectSlot *slot, void CompressorState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - for(size_t base{0u};base < samplesToDo;) + /* Generate the per-sample gains from the signal envelope. */ + float env{mEnvFollower}; + if(mEnabled) { - float gains[256]; - const size_t td{minz(256, samplesToDo-base)}; - - /* Generate the per-sample gains from the signal envelope. */ - float env{mEnvFollower}; - if(mEnabled) + for(size_t i{0u};i < samplesToDo;++i) { - for(size_t i{0u};i < td;++i) - { - /* Clamp the absolute amplitude to the defined envelope limits, - * then attack or release the envelope to reach it. - */ - const float amplitude{clampf(std::fabs(samplesIn[0][base+i]), AMP_ENVELOPE_MIN, - AMP_ENVELOPE_MAX)}; - if(amplitude > env) - env = minf(env*mAttackMult, amplitude); - else if(amplitude < env) - env = maxf(env*mReleaseMult, amplitude); - - /* Apply the reciprocal of the envelope to normalize the volume - * (compress the dynamic range). - */ - gains[i] = 1.0f / env; - } + /* Clamp the absolute amplitude to the defined envelope limits, + * then attack or release the envelope to reach it. + */ + const float amplitude{std::clamp(std::fabs(samplesIn[0][i]), AmpEnvelopeMin, + AmpEnvelopeMax)}; + if(amplitude > env) + env = std::min(env*mAttackMult, amplitude); + else if(amplitude < env) + env = std::max(env*mReleaseMult, amplitude); + + /* Apply the reciprocal of the envelope to normalize the volume + * (compress the dynamic range). + */ + mGains[i] = 1.0f / env; } - else + } + else + { + /* Same as above, except the amplitude is forced to 1. This helps + * ensure smooth gain changes when the compressor is turned on and off. + */ + for(size_t i{0u};i < samplesToDo;++i) { - /* Same as above, except the amplitude is forced to 1. This helps - * ensure smooth gain changes when the compressor is turned on and - * off. - */ - for(size_t i{0u};i < td;++i) - { - const float amplitude{1.0f}; - if(amplitude > env) - env = minf(env*mAttackMult, amplitude); - else if(amplitude < env) - env = maxf(env*mReleaseMult, amplitude); + const float amplitude{1.0f}; + if(amplitude > env) + env = std::min(env*mAttackMult, amplitude); + else if(amplitude < env) + env = std::max(env*mReleaseMult, amplitude); - gains[i] = 1.0f / env; - } + mGains[i] = 1.0f / env; } - mEnvFollower = env; + } + mEnvFollower = env; - /* Now compress the signal amplitude to output. */ - auto chan = std::cbegin(mChans); - for(const auto &input : samplesIn) + /* Now compress the signal amplitude to output. */ + auto chan = mChans.cbegin(); + for(const auto &input : samplesIn) + { + const size_t outidx{chan->mTarget}; + if(outidx != InvalidChannelIndex) { - const size_t outidx{chan->mTarget}; - if(outidx != InvalidChannelIndex) + const auto dst = al::span{samplesOut[outidx]}; + const float gain{chan->mGain}; + if(!(std::fabs(gain) > GainSilenceThreshold)) { - const float *RESTRICT src{input.data() + base}; - float *RESTRICT dst{samplesOut[outidx].data() + base}; - const float gain{chan->mGain}; - if(!(std::fabs(gain) > GainSilenceThreshold)) - { - for(size_t i{0u};i < td;i++) - dst[i] += src[i] * gains[i] * gain; - } + for(size_t i{0u};i < samplesToDo;++i) + dst[i] += input[i] * mGains[i] * gain; } - ++chan; } - - base += td; + ++chan; } } diff --git a/3rdparty/openal/alc/effects/convolution.cpp b/3rdparty/openal/alc/effects/convolution.cpp index f46422d40d94..cafa4e6f1cff 100644 --- a/3rdparty/openal/alc/effects/convolution.cpp +++ b/3rdparty/openal/alc/effects/convolution.cpp @@ -1,19 +1,21 @@ #include "config.h" +#include "config_simd.h" #include #include +#include +#include #include #include +#include #include -#include #include -#include -#include +#include -#ifdef HAVE_SSE_INTRINSICS +#if HAVE_SSE_INTRINSICS #include -#elif defined(HAVE_NEON) +#elif HAVE_NEON #include #endif @@ -29,56 +31,85 @@ #include "core/context.h" #include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/splitter.h" #include "core/fmt_traits.h" #include "core/mixer.h" +#include "core/uhjfilter.h" #include "intrusive_ptr.h" +#include "opthelpers.h" +#include "pffft.h" #include "polyphase_resampler.h" +#include "vecmat.h" #include "vector.h" namespace { -/* Convolution reverb is implemented using a segmented overlap-add method. The - * impulse response is broken up into multiple segments of 128 samples, and - * each segment has an FFT applied with a 256-sample buffer (the latter half - * left silent) to get its frequency-domain response. The resulting response - * has its positive/non-mirrored frequencies saved (129 bins) in each segment. +/* Convolution is implemented using a segmented overlap-add method. The impulse + * response is split into multiple segments of 128 samples, and each segment + * has an FFT applied with a 256-sample buffer (the latter half left silent) to + * get its frequency-domain response. The resulting response has its positive/ + * non-mirrored frequencies saved (129 bins) in each segment. Note that since + * the 0- and half-frequency bins are real for a real signal, their imaginary + * components are always 0 and can be dropped, allowing their real components + * to be combined so only 128 complex values are stored for the 129 bins. * - * Input samples are similarly broken up into 128-sample segments, with an FFT - * applied to each new incoming segment to get its 129 bins. A history of FFT'd - * input segments is maintained, equal to the length of the impulse response. + * Input samples are similarly broken up into 128-sample segments, with a 256- + * sample FFT applied to each new incoming segment to get its 129 bins. A + * history of FFT'd input segments is maintained, equal to the number of + * impulse response segments. * - * To apply the reverberation, each impulse response segment is convolved with + * To apply the convolution, each impulse response segment is convolved with * its paired input segment (using complex multiplies, far cheaper than FIRs), - * accumulating into a 256-bin FFT buffer. The input history is then shifted to - * align with later impulse response segments for next time. + * accumulating into a 129-bin FFT buffer. The input history is then shifted to + * align with later impulse response segments for the next input segment. * * An inverse FFT is then applied to the accumulated FFT buffer to get a 256- * sample time-domain response for output, which is split in two halves. The * first half is the 128-sample output, and the second half is a 128-sample * (really, 127) delayed extension, which gets added to the output next time. - * Convolving two time-domain responses of lengths N and M results in a time- - * domain signal of length N+M-1, and this holds true regardless of the - * convolution being applied in the frequency domain, so these "overflow" - * samples need to be accounted for. + * Convolving two time-domain responses of length N results in a time-domain + * signal of length N*2 - 1, and this holds true regardless of the convolution + * being applied in the frequency domain, so these "overflow" samples need to + * be accounted for. * - * To avoid a delay with gathering enough input samples to apply an FFT with, - * the first segment is applied directly in the time-domain as the samples come - * in. Once enough have been retrieved, the FFT is applied on the input and - * it's paired with the remaining (FFT'd) filter segments for processing. + * To avoid a delay with gathering enough input samples for the FFT, the first + * segment is applied directly in the time-domain as the samples come in. Once + * enough have been retrieved, the FFT is applied on the input and it's paired + * with the remaining (FFT'd) filter segments for processing. */ -void LoadSamples(float *RESTRICT dst, const std::byte *src, const size_t srcstep, FmtType srctype, - const size_t samples) noexcept +template +inline void LoadSampleArray(const al::span dst, const std::byte *src, + const std::size_t channel, const std::size_t srcstep) noexcept { -#define HANDLE_FMT(T) case T: al::LoadSampleArray(dst, src, srcstep, samples); break + using TypeTraits = al::FmtTypeTraits; + using SampleType = typename TypeTraits::Type; + const auto converter = TypeTraits{}; + assert(channel < srcstep); + + const auto srcspan = al::span{reinterpret_cast(src), dst.size()*srcstep}; + auto ssrc = srcspan.cbegin(); + std::generate(dst.begin(), dst.end(), [converter,channel,srcstep,&ssrc] + { + const auto ret = converter(ssrc[channel]); + ssrc += ptrdiff_t(srcstep); + return ret; + }); +} + +void LoadSamples(const al::span dst, const std::byte *src, const size_t channel, + const size_t srcstep, const FmtType srctype) noexcept +{ +#define HANDLE_FMT(T) case T: LoadSampleArray(dst, src, channel, srcstep); break switch(srctype) { HANDLE_FMT(FmtUByte); HANDLE_FMT(FmtShort); + HANDLE_FMT(FmtInt); HANDLE_FMT(FmtFloat); HANDLE_FMT(FmtDouble); HANDLE_FMT(FmtMulaw); @@ -86,7 +117,7 @@ void LoadSamples(float *RESTRICT dst, const std::byte *src, const size_t srcstep /* FIXME: Handle ADPCM decoding here. */ case FmtIMA4: case FmtMSADPCM: - std::fill_n(dst, samples, 0.0f); + std::fill(dst.begin(), dst.end(), 0.0f); break; } #undef HANDLE_FMT @@ -137,10 +168,11 @@ constexpr size_t ConvolveUpdateSize{256}; constexpr size_t ConvolveUpdateSamples{ConvolveUpdateSize / 2}; -void apply_fir(al::span dst, const float *RESTRICT src, const float *RESTRICT filter) +void apply_fir(al::span dst, const al::span input, const al::span filter) { -#ifdef HAVE_SSE_INTRINSICS - for(float &output : dst) + auto src = input.begin(); +#if HAVE_SSE_INTRINSICS + std::generate(dst.begin(), dst.end(), [&src,filter] { __m128 r4{_mm_setzero_ps()}; for(size_t j{0};j < ConvolveUpdateSamples;j+=4) @@ -150,39 +182,40 @@ void apply_fir(al::span dst, const float *RESTRICT src, const float *REST r4 = _mm_add_ps(r4, _mm_mul_ps(s, coeffs)); } + ++src; + r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); - output = _mm_cvtss_f32(r4); + return _mm_cvtss_f32(r4); + }); - ++src; - } - -#elif defined(HAVE_NEON) +#elif HAVE_NEON - for(float &output : dst) + std::generate(dst.begin(), dst.end(), [&src,filter] { float32x4_t r4{vdupq_n_f32(0.0f)}; for(size_t j{0};j < ConvolveUpdateSamples;j+=4) r4 = vmlaq_f32(r4, vld1q_f32(&src[j]), vld1q_f32(&filter[j])); - r4 = vaddq_f32(r4, vrev64q_f32(r4)); - output = vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); - ++src; - } + + r4 = vaddq_f32(r4, vrev64q_f32(r4)); + return vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + }); #else - for(float &output : dst) + std::generate(dst.begin(), dst.end(), [&src,filter] { float ret{0.0f}; for(size_t j{0};j < ConvolveUpdateSamples;++j) ret += src[j] * filter[j]; - output = ret; ++src; - } + return ret; + }); #endif } + struct ConvolutionState final : public EffectState { FmtChannels mChannels{}; AmbiLayout mAmbiLayout{}; @@ -190,11 +223,13 @@ struct ConvolutionState final : public EffectState { uint mAmbiOrder{}; size_t mFifoPos{0}; - std::array mInput{}; + alignas(16) std::array mInput{}; al::vector,16> mFilter; al::vector,16> mOutput; - alignas(16) std::array mFftBuffer{}; + PFFFTSetup mFft; + alignas(16) std::array mFftBuffer{}; + alignas(16) std::array mFftWorkBuffer{}; size_t mCurrentSegment{0}; size_t mNumConvolveSegs{0}; @@ -202,13 +237,12 @@ struct ConvolutionState final : public EffectState { struct ChannelData { alignas(16) FloatBufferLine mBuffer{}; float mHfScale{}, mLfScale{}; - BandSplitter mFilter{}; - float Current[MAX_OUTPUT_CHANNELS]{}; - float Target[MAX_OUTPUT_CHANNELS]{}; + BandSplitter mFilter; + std::array Current{}; + std::array Target{}; }; - using ChannelDataArray = al::FlexArray; - std::unique_ptr mChans; - std::unique_ptr mComplexData; + std::vector mChans; + al::vector mComplexData; ConvolutionState() = default; @@ -224,24 +258,22 @@ struct ConvolutionState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(ConvolutionState) }; void ConvolutionState::NormalMix(const al::span samplesOut, const size_t samplesToDo) { - for(auto &chan : *mChans) - MixSamples({chan.mBuffer.data(), samplesToDo}, samplesOut, chan.Current, chan.Target, - samplesToDo, 0); + for(auto &chan : mChans) + MixSamples(al::span{chan.mBuffer}.first(samplesToDo), samplesOut, chan.Current, + chan.Target, samplesToDo, 0); } void ConvolutionState::UpsampleMix(const al::span samplesOut, const size_t samplesToDo) { - for(auto &chan : *mChans) + for(auto &chan : mChans) { - const al::span src{chan.mBuffer.data(), samplesToDo}; + const auto src = al::span{chan.mBuffer}.first(samplesToDo); chan.mFilter.processScale(src, chan.mHfScale, chan.mLfScale); MixSamples(src, samplesOut, chan.Current, chan.Target, samplesToDo, 0); } @@ -253,19 +285,23 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag using UhjDecoderType = UhjDecoder<512>; static constexpr auto DecoderPadding = UhjDecoderType::sInputPadding; - constexpr uint MaxConvolveAmbiOrder{1u}; + static constexpr uint MaxConvolveAmbiOrder{1u}; + + if(!mFft) + mFft = PFFFTSetup{ConvolveUpdateSize, PFFFT_REAL}; mFifoPos = 0; mInput.fill(0.0f); decltype(mFilter){}.swap(mFilter); decltype(mOutput){}.swap(mOutput); - mFftBuffer.fill(complex_f{}); + mFftBuffer.fill(0.0f); + mFftWorkBuffer.fill(0.0f); mCurrentSegment = 0; mNumConvolveSegs = 0; - mChans = nullptr; - mComplexData = nullptr; + decltype(mChans){}.swap(mChans); + decltype(mComplexData){}.swap(mComplexData); /* An empty buffer doesn't need a convolution filter. */ if(!buffer || buffer->mSampleLen < 1) return; @@ -273,14 +309,12 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag mChannels = buffer->mChannels; mAmbiLayout = IsUHJ(mChannels) ? AmbiLayout::FuMa : buffer->mAmbiLayout; mAmbiScaling = IsUHJ(mChannels) ? AmbiScaling::UHJ : buffer->mAmbiScaling; - mAmbiOrder = minu(buffer->mAmbiOrder, MaxConvolveAmbiOrder); + mAmbiOrder = std::min(buffer->mAmbiOrder, MaxConvolveAmbiOrder); - constexpr size_t m{ConvolveUpdateSize/2 + 1}; - const auto bytesPerSample = BytesFromFmt(buffer->mType); const auto realChannels = buffer->channelsFromFmt(); const auto numChannels = (mChannels == FmtUHJ2) ? 3u : ChannelsFromFmt(mChannels, mAmbiOrder); - mChans = ChannelDataArray::Create(numChannels); + mChans.resize(numChannels); /* The impulse response needs to have the same sample rate as the input and * output. The bsinc24 resampler is decent, but there is high-frequency @@ -288,14 +322,14 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag * called very infrequently, go ahead and use the polyphase resampler. */ PPhaseResampler resampler; - if(device->Frequency != buffer->mSampleRate) - resampler.init(buffer->mSampleRate, device->Frequency); + if(device->mSampleRate != buffer->mSampleRate) + resampler.init(buffer->mSampleRate, device->mSampleRate); const auto resampledCount = static_cast( - (uint64_t{buffer->mSampleLen}*device->Frequency+(buffer->mSampleRate-1)) / + (uint64_t{buffer->mSampleLen}*device->mSampleRate+(buffer->mSampleRate-1)) / buffer->mSampleRate); - const BandSplitter splitter{device->mXOverFreq / static_cast(device->Frequency)}; - for(auto &e : *mChans) + const BandSplitter splitter{device->mXOverFreq / static_cast(device->mSampleRate)}; + for(auto &e : mChans) e.mFilter = splitter; mFilter.resize(numChannels, {}); @@ -307,126 +341,150 @@ void ConvolutionState::deviceUpdate(const DeviceBase *device, const BufferStorag * segment is allocated to simplify handling. */ mNumConvolveSegs = (resampledCount+(ConvolveUpdateSamples-1)) / ConvolveUpdateSamples; - mNumConvolveSegs = maxz(mNumConvolveSegs, 2) - 1; + mNumConvolveSegs = std::max(mNumConvolveSegs, 2_uz) - 1_uz; - const size_t complex_length{mNumConvolveSegs * m * (numChannels+1)}; - mComplexData = std::make_unique(complex_length); - std::fill_n(mComplexData.get(), complex_length, complex_f{}); + const size_t complex_length{mNumConvolveSegs * ConvolveUpdateSize * (numChannels+1)}; + mComplexData.resize(complex_length, 0.0f); /* Load the samples from the buffer. */ const size_t srclinelength{RoundUp(buffer->mSampleLen+DecoderPadding, 16)}; - auto srcsamples = std::make_unique(srclinelength * numChannels); - std::fill_n(srcsamples.get(), srclinelength * numChannels, 0.0f); + auto srcsamples = std::vector(srclinelength * numChannels); + std::fill(srcsamples.begin(), srcsamples.end(), 0.0f); for(size_t c{0};c < numChannels && c < realChannels;++c) - LoadSamples(srcsamples.get() + srclinelength*c, buffer->mData.data() + bytesPerSample*c, - realChannels, buffer->mType, buffer->mSampleLen); + LoadSamples(al::span{srcsamples}.subspan(srclinelength*c, buffer->mSampleLen), + buffer->mData.data(), c, realChannels, buffer->mType); if(IsUHJ(mChannels)) { auto decoder = std::make_unique(); std::array samples{}; for(size_t c{0};c < numChannels;++c) - samples[c] = srcsamples.get() + srclinelength*c; + samples[c] = al::to_address(srcsamples.begin() + ptrdiff_t(srclinelength*c)); decoder->decode({samples.data(), numChannels}, buffer->mSampleLen, buffer->mSampleLen); } - auto ressamples = std::make_unique(buffer->mSampleLen + - (resampler ? resampledCount : 0)); - complex_f *filteriter = mComplexData.get() + mNumConvolveSegs*m; + auto ressamples = std::vector(buffer->mSampleLen + (resampler ? resampledCount : 0)); + auto ffttmp = al::vector(ConvolveUpdateSize); + auto fftbuffer = std::vector>(ConvolveUpdateSize); + + auto filteriter = mComplexData.begin() + ptrdiff_t(mNumConvolveSegs*ConvolveUpdateSize); for(size_t c{0};c < numChannels;++c) { + auto bufsamples = al::span{srcsamples}.subspan(srclinelength*c, buffer->mSampleLen); /* Resample to match the device. */ if(resampler) { - std::copy_n(srcsamples.get() + srclinelength*c, buffer->mSampleLen, - ressamples.get() + resampledCount); - resampler.process(buffer->mSampleLen, ressamples.get()+resampledCount, - resampledCount, ressamples.get()); + auto restmp = al::span{ressamples}.subspan(resampledCount, buffer->mSampleLen); + std::copy(bufsamples.cbegin(), bufsamples.cend(), restmp.begin()); + resampler.process(restmp, al::span{ressamples}.first(resampledCount)); } else - std::copy_n(srcsamples.get() + srclinelength*c, buffer->mSampleLen, ressamples.get()); + std::copy(bufsamples.cbegin(), bufsamples.cend(), ressamples.begin()); /* Store the first segment's samples in reverse in the time-domain, to * apply as a FIR filter. */ - const size_t first_size{minz(resampledCount, ConvolveUpdateSamples)}; - std::transform(ressamples.get(), ressamples.get()+first_size, mFilter[c].rbegin(), + const size_t first_size{std::min(size_t{resampledCount}, ConvolveUpdateSamples)}; + auto sampleseg = al::span{ressamples.cbegin(), first_size}; + std::transform(sampleseg.cbegin(), sampleseg.cend(), mFilter[c].rbegin(), [](const double d) noexcept -> float { return static_cast(d); }); - auto fftbuffer = std::vector>(ConvolveUpdateSize); size_t done{first_size}; for(size_t s{0};s < mNumConvolveSegs;++s) { - const size_t todo{minz(resampledCount-done, ConvolveUpdateSamples)}; + const size_t todo{std::min(resampledCount-done, ConvolveUpdateSamples)}; + sampleseg = al::span{ressamples}.subspan(done, todo); - auto iter = std::copy_n(&ressamples[done], todo, fftbuffer.begin()); + /* Apply a double-precision forward FFT for more precise frequency + * measurements. + */ + auto iter = std::copy(sampleseg.cbegin(), sampleseg.cend(), fftbuffer.begin()); done += todo; std::fill(iter, fftbuffer.end(), std::complex{}); - forward_fft(al::span{fftbuffer}); - filteriter = std::copy_n(fftbuffer.cbegin(), m, filteriter); + + /* Convert to, and pack in, a float buffer for PFFFT. Note that the + * first bin stores the real component of the half-frequency bin in + * the imaginary component. Also scale the FFT by its length so the + * iFFT'd output will be normalized. + */ + static constexpr float fftscale{1.0f / float{ConvolveUpdateSize}}; + for(size_t i{0};i < ConvolveUpdateSamples;++i) + { + ffttmp[i*2 ] = static_cast(fftbuffer[i].real()) * fftscale; + ffttmp[i*2 + 1] = static_cast((i == 0) ? + fftbuffer[ConvolveUpdateSamples].real() : fftbuffer[i].imag()) * fftscale; + } + /* Reorder backward to make it suitable for pffft_zconvolve and the + * subsequent pffft_transform(..., PFFFT_BACKWARD). + */ + mFft.zreorder(ffttmp.data(), al::to_address(filteriter), PFFFT_BACKWARD); + filteriter += ConvolveUpdateSize; } } } void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps* /*props*/, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { - /* NOTE: Stereo and Rear are slightly different from normal mixing (as - * defined in alu.cpp). These are 45 degrees from center, rather than the - * 30 degrees used there. - * - * TODO: LFE is not mixed to output. This will require each buffer channel + /* TODO: LFE is not mixed to output. This will require each buffer channel * to have its own output target since the main mixing buffer won't have an * LFE channel (due to being B-Format). */ - static constexpr ChanPosMap MonoMap[1]{ - { FrontCenter, std::array{0.0f, 0.0f, -1.0f} } - }, StereoMap[2]{ - { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, - { FrontRight, std::array{ sin45, 0.0f, -cos45} }, - }, RearMap[2]{ - { BackLeft, std::array{-sin45, 0.0f, cos45} }, - { BackRight, std::array{ sin45, 0.0f, cos45} }, - }, QuadMap[4]{ - { FrontLeft, std::array{-sin45, 0.0f, -cos45} }, - { FrontRight, std::array{ sin45, 0.0f, -cos45} }, - { BackLeft, std::array{-sin45, 0.0f, cos45} }, - { BackRight, std::array{ sin45, 0.0f, cos45} }, - }, X51Map[6]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { SideLeft, std::array{-sin110, 0.0f, -cos110} }, - { SideRight, std::array{ sin110, 0.0f, -cos110} }, - }, X61Map[7]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, - { SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, - }, X71Map[8]{ - { FrontLeft, std::array{-sin30, 0.0f, -cos30} }, - { FrontRight, std::array{ sin30, 0.0f, -cos30} }, - { FrontCenter, std::array{ 0.0f, 0.0f, -1.0f} }, - { LFE, {} }, - { BackLeft, std::array{-sin30, 0.0f, cos30} }, - { BackRight, std::array{ sin30, 0.0f, cos30} }, - { SideLeft, std::array{ -1.0f, 0.0f, 0.0f} }, - { SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, + static constexpr std::array MonoMap{ + ChanPosMap{FrontCenter, std::array{0.0f, 0.0f, -1.0f}} + }; + static constexpr std::array StereoMap{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + }; + static constexpr std::array RearMap{ + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + }; + static constexpr std::array QuadMap{ + ChanPosMap{FrontLeft, std::array{-sin45, 0.0f, -cos45}}, + ChanPosMap{FrontRight, std::array{ sin45, 0.0f, -cos45}}, + ChanPosMap{BackLeft, std::array{-sin45, 0.0f, cos45}}, + ChanPosMap{BackRight, std::array{ sin45, 0.0f, cos45}}, + }; + static constexpr std::array X51Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{SideLeft, std::array{-sin110, 0.0f, -cos110}}, + ChanPosMap{SideRight, std::array{ sin110, 0.0f, -cos110}}, + }; + static constexpr std::array X61Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackCenter, std::array{ 0.0f, 0.0f, 1.0f} }, + ChanPosMap{SideLeft, std::array{-1.0f, 0.0f, 0.0f} }, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f} }, + }; + static constexpr std::array X71Map{ + ChanPosMap{FrontLeft, std::array{-sin30, 0.0f, -cos30}}, + ChanPosMap{FrontRight, std::array{ sin30, 0.0f, -cos30}}, + ChanPosMap{FrontCenter, std::array{ 0.0f, 0.0f, -1.0f}}, + ChanPosMap{LFE, {}}, + ChanPosMap{BackLeft, std::array{-sin30, 0.0f, cos30}}, + ChanPosMap{BackRight, std::array{ sin30, 0.0f, cos30}}, + ChanPosMap{SideLeft, std::array{ -1.0f, 0.0f, 0.0f}}, + ChanPosMap{SideRight, std::array{ 1.0f, 0.0f, 0.0f}}, }; if(mNumConvolveSegs < 1) UNLIKELY return; + auto &props = std::get(*props_); mMix = &ConvolutionState::NormalMix; - for(auto &chan : *mChans) - std::fill(std::begin(chan.Target), std::end(chan.Target), 0.0f); + for(auto &chan : mChans) + std::fill(chan.Target.begin(), chan.Target.end(), 0.0f); const float gain{slot->Gain}; if(IsAmbisonic(mChannels)) { @@ -434,40 +492,58 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot if(mChannels == FmtUHJ2 && !device->mUhjEncoder) { mMix = &ConvolutionState::UpsampleMix; - (*mChans)[0].mHfScale = 1.0f; - (*mChans)[0].mLfScale = DecoderBase::sWLFScale; - (*mChans)[1].mHfScale = 1.0f; - (*mChans)[1].mLfScale = DecoderBase::sXYLFScale; - (*mChans)[2].mHfScale = 1.0f; - (*mChans)[2].mLfScale = DecoderBase::sXYLFScale; + mChans[0].mHfScale = 1.0f; + mChans[0].mLfScale = DecoderBase::sWLFScale; + mChans[1].mHfScale = 1.0f; + mChans[1].mLfScale = DecoderBase::sXYLFScale; + mChans[2].mHfScale = 1.0f; + mChans[2].mLfScale = DecoderBase::sXYLFScale; } else if(device->mAmbiOrder > mAmbiOrder) { mMix = &ConvolutionState::UpsampleMix; const auto scales = AmbiScale::GetHFOrderScales(mAmbiOrder, device->mAmbiOrder, device->m2DMixing); - (*mChans)[0].mHfScale = scales[0]; - (*mChans)[0].mLfScale = 1.0f; - for(size_t i{1};i < mChans->size();++i) + mChans[0].mHfScale = scales[0]; + mChans[0].mLfScale = 1.0f; + for(size_t i{1};i < mChans.size();++i) { - (*mChans)[i].mHfScale = scales[1]; - (*mChans)[i].mLfScale = 1.0f; + mChans[i].mHfScale = scales[1]; + mChans[i].mLfScale = 1.0f; } } mOutTarget = target.Main->Buffer; + alu::Vector N{props.OrientAt[0], props.OrientAt[1], props.OrientAt[2], 0.0f}; + N.normalize(); + alu::Vector V{props.OrientUp[0], props.OrientUp[1], props.OrientUp[2], 0.0f}; + V.normalize(); + /* Build and normalize right-vector */ + alu::Vector U{N.cross_product(V)}; + U.normalize(); + + const std::array mixmatrix{ + std::array{1.0f, 0.0f, 0.0f, 0.0f}, + std::array{0.0f, U[0], -U[1], U[2]}, + std::array{0.0f, -V[0], V[1], -V[2]}, + std::array{0.0f, -N[0], N[1], -N[2]}, + }; + const auto scales = GetAmbiScales(mAmbiScaling); - const uint8_t *index_map{Is2DAmbisonic(mChannels) ? - GetAmbi2DLayout(mAmbiLayout).data() : - GetAmbiLayout(mAmbiLayout).data()}; + const auto index_map = Is2DAmbisonic(mChannels) ? + al::span{GetAmbi2DLayout(mAmbiLayout)}.subspan(0) : + al::span{GetAmbiLayout(mAmbiLayout)}.subspan(0); std::array coeffs{}; - for(size_t c{0u};c < mChans->size();++c) + for(size_t c{0u};c < mChans.size();++c) { const size_t acn{index_map[c]}; - coeffs[acn] = scales[acn]; - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[c].Target); - coeffs[acn] = 0.0f; + const float scale{scales[acn]}; + + std::transform(mixmatrix[acn].cbegin(), mixmatrix[acn].cend(), coeffs.begin(), + [scale](const float in) noexcept -> float { return in * scale; }); + + ComputePanGains(target.Main, coeffs, gain, mChans[c].Target); } } else @@ -477,6 +553,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot switch(mChannels) { case FmtMono: chanmap = MonoMap; break; + case FmtMonoDup: chanmap = MonoMap; break; case FmtSuperStereo: case FmtStereo: chanmap = StereoMap; break; case FmtRear: chanmap = RearMap; break; @@ -496,7 +573,7 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot if(device->mRenderMode == RenderMode::Pairwise) { /* Scales the azimuth of the given vector by 3 if it's in front. - * Effectively scales +/-45 degrees to +/-90 degrees, leaving > +90 + * Effectively scales +/-30 degrees to +/-90 degrees, leaving > +90 * and < -90 alone. */ auto ScaleAzimuthFront = [](std::array pos) -> std::array @@ -511,20 +588,20 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot float x{pos[0] / len2d}; float z{-pos[2] / len2d}; - /* Z > cos(pi/4) = -45 < azimuth < 45 degrees. */ - if(z > cos45) + /* Z > cos(pi/6) = -30 < azimuth < 30 degrees. */ + if(z > cos30) { - /* Double the angle represented by x,z. */ - const float resx{2.0f*x * z}; - const float resz{z*z - x*x}; + /* Triple the angle represented by x,z. */ + x = x*3.0f - x*x*x*4.0f; + z = z*z*z*4.0f - z*3.0f; /* Scale the vector back to fit in 3D. */ - pos[0] = resx * len2d; - pos[2] = -resz * len2d; + pos[0] = x * len2d; + pos[2] = -z * len2d; } else { - /* If azimuth >= 45 degrees, clamp to 90 degrees. */ + /* If azimuth >= 30 degrees, clamp to 90 degrees. */ pos[0] = std::copysign(len2d, pos[0]); pos[2] = 0.0f; } @@ -536,14 +613,14 @@ void ConvolutionState::update(const ContextBase *context, const EffectSlot *slot { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(ScaleAzimuthFront(chanmap[i].pos), 0.0f); - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, mChans[i].Target); } } else for(size_t i{0};i < chanmap.size();++i) { if(chanmap[i].channel == LFE) continue; const auto coeffs = CalcDirectionCoeffs(chanmap[i].pos, 0.0f); - ComputePanGains(target.Main, coeffs.data(), gain, (*mChans)[i].Target); + ComputePanGains(target.Main, coeffs, gain, mChans[i].Target); } } } @@ -554,27 +631,26 @@ void ConvolutionState::process(const size_t samplesToDo, if(mNumConvolveSegs < 1) UNLIKELY return; - constexpr size_t m{ConvolveUpdateSize/2 + 1}; size_t curseg{mCurrentSegment}; - auto &chans = *mChans; for(size_t base{0u};base < samplesToDo;) { - const size_t todo{minz(ConvolveUpdateSamples-mFifoPos, samplesToDo-base)}; + const size_t todo{std::min(ConvolveUpdateSamples-mFifoPos, samplesToDo-base)}; - std::copy_n(samplesIn[0].begin() + base, todo, - mInput.begin()+ConvolveUpdateSamples+mFifoPos); + std::copy_n(samplesIn[0].begin() + ptrdiff_t(base), todo, + mInput.begin()+ptrdiff_t(ConvolveUpdateSamples+mFifoPos)); /* Apply the FIR for the newly retrieved input samples, and combine it * with the inverse FFT'd output samples. */ - for(size_t c{0};c < chans.size();++c) + for(size_t c{0};c < mChans.size();++c) { - auto buf_iter = chans[c].mBuffer.begin() + base; - apply_fir({buf_iter, todo}, mInput.data()+1 + mFifoPos, mFilter[c].data()); + auto outspan = al::span{mChans[c].mBuffer}.subspan(base, todo); + apply_fir(outspan, al::span{mInput}.subspan(1+mFifoPos), mFilter[c]); - auto fifo_iter = mOutput[c].begin() + mFifoPos; - std::transform(fifo_iter, fifo_iter+todo, buf_iter, buf_iter, std::plus<>{}); + auto fifospan = al::span{mOutput[c]}.subspan(mFifoPos, todo); + std::transform(fifospan.cbegin(), fifospan.cend(), outspan.cbegin(), outspan.begin(), + std::plus{}); } mFifoPos += todo; @@ -586,59 +662,51 @@ void ConvolutionState::process(const size_t samplesToDo, /* Move the newest input to the front for the next iteration's history. */ std::copy(mInput.cbegin()+ConvolveUpdateSamples, mInput.cend(), mInput.begin()); + std::fill(mInput.begin()+ConvolveUpdateSamples, mInput.end(), 0.0f); - /* Calculate the frequency domain response and add the relevant + /* Calculate the frequency-domain response and add the relevant * frequency bins to the FFT history. */ - auto fftiter = std::copy_n(mInput.cbegin(), ConvolveUpdateSamples, mFftBuffer.begin()); - std::fill(fftiter, mFftBuffer.end(), complex_f{}); - forward_fft(al::span{mFftBuffer}); + mFft.transform(mInput.data(), &mComplexData[curseg*ConvolveUpdateSize], + mFftWorkBuffer.data(), PFFFT_FORWARD); - std::copy_n(mFftBuffer.cbegin(), m, &mComplexData[curseg*m]); - - const complex_f *RESTRICT filter{mComplexData.get() + mNumConvolveSegs*m}; - for(size_t c{0};c < chans.size();++c) + auto filter = mComplexData.cbegin() + ptrdiff_t(mNumConvolveSegs*ConvolveUpdateSize); + for(size_t c{0};c < mChans.size();++c) { - std::fill_n(mFftBuffer.begin(), m, complex_f{}); - /* Convolve each input segment with its IR filter counterpart * (aligned in time). */ - const complex_f *RESTRICT input{&mComplexData[curseg*m]}; + mFftBuffer.fill(0.0f); + auto input = mComplexData.cbegin() + ptrdiff_t(curseg*ConvolveUpdateSize); for(size_t s{curseg};s < mNumConvolveSegs;++s) { - for(size_t i{0};i < m;++i,++input,++filter) - mFftBuffer[i] += *input * *filter; + mFft.zconvolve_accumulate(al::to_address(input), al::to_address(filter), + mFftBuffer.data()); + input += ConvolveUpdateSize; + filter += ConvolveUpdateSize; } - input = mComplexData.get(); + input = mComplexData.cbegin(); for(size_t s{0};s < curseg;++s) { - for(size_t i{0};i < m;++i,++input,++filter) - mFftBuffer[i] += *input * *filter; + mFft.zconvolve_accumulate(al::to_address(input), al::to_address(filter), + mFftBuffer.data()); + input += ConvolveUpdateSize; + filter += ConvolveUpdateSize; } - /* Reconstruct the mirrored/negative frequencies to do a proper - * inverse FFT. - */ - for(size_t i{m};i < ConvolveUpdateSize;++i) - mFftBuffer[i] = std::conj(mFftBuffer[ConvolveUpdateSize-i]); - /* Apply iFFT to get the 256 (really 255) samples for output. The * 128 output samples are combined with the last output's 127 * second-half samples (and this output's second half is * subsequently saved for next time). */ - inverse_fft(al::span{mFftBuffer}); - - /* The iFFT'd response is scaled up by the number of bins, so apply - * the inverse to normalize the output. - */ - for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][i] = - (mFftBuffer[i].real()+mOutput[c][ConvolveUpdateSamples+i]) * - (1.0f/float{ConvolveUpdateSize}); - for(size_t i{0};i < ConvolveUpdateSamples;++i) - mOutput[c][ConvolveUpdateSamples+i] = mFftBuffer[ConvolveUpdateSamples+i].real(); + mFft.transform(mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(), + PFFFT_BACKWARD); + + /* The filter was attenuated, so the response is already scaled. */ + std::transform(mFftBuffer.cbegin(), mFftBuffer.cbegin()+ConvolveUpdateSamples, + mOutput[c].cbegin()+ConvolveUpdateSamples, mOutput[c].begin(), std::plus{}); + std::copy(mFftBuffer.cbegin()+ConvolveUpdateSamples, mFftBuffer.cend(), + mOutput[c].begin()+ConvolveUpdateSamples); } /* Shift the input history. */ diff --git a/3rdparty/openal/alc/effects/dedicated.cpp b/3rdparty/openal/alc/effects/dedicated.cpp index e82b13d9b968..df1bd5ed0788 100644 --- a/3rdparty/openal/alc/effects/dedicated.cpp +++ b/3rdparty/openal/alc/effects/dedicated.cpp @@ -23,18 +23,19 @@ #include #include #include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alspan.h" #include "core/bufferline.h" #include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "intrusive_ptr.h" +struct BufferStorage; struct ContextBase; @@ -47,45 +48,36 @@ struct DedicatedState final : public EffectState { * gains for all possible output channels and not just the main ambisonic * buffer. */ - float mCurrentGains[MAX_OUTPUT_CHANNELS]; - float mTargetGains[MAX_OUTPUT_CHANNELS]; + std::array mCurrentGains{}; + std::array mTargetGains{}; - void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; - void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, - const EffectTarget target) override; + void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) final; + void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props_, + const EffectTarget target) final; void process(const size_t samplesToDo, const al::span samplesIn, - const al::span samplesOut) override; - - DEF_NEWDEL(DedicatedState) + const al::span samplesOut) final; }; void DedicatedState::deviceUpdate(const DeviceBase*, const BufferStorage*) { - std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); + std::fill(mCurrentGains.begin(), mCurrentGains.end(), 0.0f); } void DedicatedState::update(const ContextBase*, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { - std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); + std::fill(mTargetGains.begin(), mTargetGains.end(), 0.0f); - const float Gain{slot->Gain * props->Dedicated.Gain}; + auto &props = std::get(*props_); + const float Gain{slot->Gain * props.Gain}; - if(slot->EffectType == EffectSlotType::DedicatedLFE) - { - const uint idx{target.RealOut ? target.RealOut->ChannelIndex[LFE] : InvalidChannelIndex}; - if(idx != InvalidChannelIndex) - { - mOutTarget = target.RealOut->Buffer; - mTargetGains[idx] = Gain; - } - } - else if(slot->EffectType == EffectSlotType::DedicatedDialog) + if(props.Target == DedicatedProps::Dialog) { /* Dialog goes to the front-center speaker if it exists, otherwise it - * plays from the front-center location. */ - const uint idx{target.RealOut ? target.RealOut->ChannelIndex[FrontCenter] + * plays from the front-center location. + */ + const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[FrontCenter] : InvalidChannelIndex}; if(idx != InvalidChannelIndex) { @@ -97,14 +89,23 @@ void DedicatedState::update(const ContextBase*, const EffectSlot *slot, static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), Gain, mTargetGains); + ComputePanGains(target.Main, coeffs, Gain, mTargetGains); + } + } + else if(props.Target == DedicatedProps::Lfe) + { + const size_t idx{target.RealOut ? target.RealOut->ChannelIndex[LFE] : InvalidChannelIndex}; + if(idx != InvalidChannelIndex) + { + mOutTarget = target.RealOut->Buffer; + mTargetGains[idx] = Gain; } } } void DedicatedState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - MixSamples({samplesIn[0].data(), samplesToDo}, samplesOut, mCurrentGains, mTargetGains, + MixSamples(al::span{samplesIn[0]}.first(samplesToDo), samplesOut, mCurrentGains, mTargetGains, samplesToDo, 0); } diff --git a/3rdparty/openal/alc/effects/distortion.cpp b/3rdparty/openal/alc/effects/distortion.cpp index 392d81c8101a..963ddad11195 100644 --- a/3rdparty/openal/alc/effects/distortion.cpp +++ b/3rdparty/openal/alc/effects/distortion.cpp @@ -22,30 +22,32 @@ #include #include +#include #include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" +#include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/biquad.h" #include "core/mixer.h" #include "core/mixer/defs.h" #include "intrusive_ptr.h" +struct BufferStorage; namespace { struct DistortionState final : public EffectState { /* Effect gains for each channel */ - float mGain[MaxAmbiChannels]{}; + std::array mGain{}; /* Effect parameters */ BiquadFilter mLowpass; @@ -53,7 +55,7 @@ struct DistortionState final : public EffectState { float mAttenuation{}; float mEdgeCoeff{}; - alignas(16) float mBuffer[2][BufferLineSize]{}; + alignas(16) std::array mBuffer{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -61,8 +63,6 @@ struct DistortionState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(DistortionState) }; void DistortionState::deviceUpdate(const DeviceBase*, const BufferStorage*) @@ -72,33 +72,33 @@ void DistortionState::deviceUpdate(const DeviceBase*, const BufferStorage*) } void DistortionState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; /* Store waveshaper edge settings. */ - const float edge{minf(std::sin(al::numbers::pi_v*0.5f * props->Distortion.Edge), - 0.99f)}; + const float edge{std::min(std::sin(al::numbers::pi_v*0.5f * props.Edge), 0.99f)}; mEdgeCoeff = 2.0f * edge / (1.0f-edge); - float cutoff{props->Distortion.LowpassCutoff}; + float cutoff{props.LowpassCutoff}; /* Bandwidth value is constant in octaves. */ float bandwidth{(cutoff / 2.0f) / (cutoff * 0.67f)}; /* Divide normalized frequency by the amount of oversampling done during * processing. */ - auto frequency = static_cast(device->Frequency); + auto frequency = static_cast(device->mSampleRate); mLowpass.setParamsFromBandwidth(BiquadType::LowPass, cutoff/frequency/4.0f, 1.0f, bandwidth); - cutoff = props->Distortion.EQCenter; + cutoff = props.EQCenter; /* Convert bandwidth in Hz to octaves. */ - bandwidth = props->Distortion.EQBandwidth / (cutoff * 0.67f); + bandwidth = props.EQBandwidth / (cutoff * 0.67f); mBandpass.setParamsFromBandwidth(BiquadType::BandPass, cutoff/frequency/4.0f, 1.0f, bandwidth); static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Gain*props->Distortion.Gain, mGain); + ComputePanGains(target.Main, coeffs, slot->Gain*props.Gain, mGain); } void DistortionState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) @@ -111,7 +111,7 @@ void DistortionState::process(const size_t samplesToDo, const al::span float { - smp = (1.0f + fc) * smp/(1.0f + fc*std::abs(smp)); - smp = (1.0f + fc) * smp/(1.0f + fc*std::abs(smp)) * -1.0f; - smp = (1.0f + fc) * smp/(1.0f + fc*std::abs(smp)); + smp = (1.0f + fc) * smp/(1.0f + fc*std::fabs(smp)); + smp = (1.0f + fc) * smp/(1.0f + fc*std::fabs(smp)) * -1.0f; + smp = (1.0f + fc) * smp/(1.0f + fc*std::fabs(smp)); return smp; }; - std::transform(std::begin(mBuffer[1]), std::begin(mBuffer[1])+todo, std::begin(mBuffer[0]), + std::transform(mBuffer[1].begin(), mBuffer[1].begin()+todo, mBuffer[0].begin(), proc_sample); /* Third step, do bandpass filtering of distorted signal. */ - mBandpass.process({mBuffer[0], todo}, mBuffer[1]); + mBandpass.process(al::span{mBuffer[0]}.first(todo), mBuffer[1]); todo >>= 2; - const float *outgains{mGain}; - for(FloatBufferLine &output : samplesOut) + auto outgains = mGain.cbegin(); + auto proc_bufline = [this,base,todo,&outgains](FloatBufferSpan output) { /* Fourth step, final, do attenuation and perform decimation, * storing only one sample out of four. */ const float gain{*(outgains++)}; if(!(std::fabs(gain) > GainSilenceThreshold)) - continue; - - for(size_t i{0u};i < todo;i++) - output[base+i] += gain * mBuffer[1][i*4]; - } + return; + + auto src = mBuffer[1].cbegin(); + const auto dst = al::span{output}.subspan(base, todo); + auto dec_sample = [gain,&src](float sample) noexcept -> float + { + sample += *src * gain; + src += 4; + return sample; + }; + std::transform(dst.begin(), dst.end(), dst.begin(), dec_sample); + }; + std::for_each(samplesOut.begin(), samplesOut.end(), proc_bufline); base += todo; } diff --git a/3rdparty/openal/alc/effects/echo.cpp b/3rdparty/openal/alc/effects/echo.cpp index 7824c24694c4..6809ddcbbda7 100644 --- a/3rdparty/openal/alc/effects/echo.cpp +++ b/3rdparty/openal/alc/effects/echo.cpp @@ -22,25 +22,26 @@ #include #include +#include #include -#include -#include +#include #include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumeric.h" #include "alspan.h" +#include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/biquad.h" #include "core/mixer.h" #include "intrusive_ptr.h" #include "opthelpers.h" +struct BufferStorage; namespace { @@ -53,34 +54,31 @@ struct EchoState final : public EffectState { // The echo is two tap. The delay is the number of samples from before the // current offset - struct { - size_t delay{0u}; - } mTap[2]; + std::array mDelayTap{}; size_t mOffset{0u}; /* The panning gains for the two taps */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array Current{}; + std::array Target{}; + }; + std::array mGains; BiquadFilter mFilter; float mFeedGain{0.0f}; - alignas(16) float mTempBuffer[2][BufferLineSize]; + alignas(16) std::array mTempBuffer{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(EchoState) }; void EchoState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) { - const auto frequency = static_cast(Device->Frequency); + const auto frequency = static_cast(Device->mSampleRate); // Use the next power of 2 for the buffer length, so the tap offsets can be // wrapped using a mask instead of a modulo @@ -92,56 +90,57 @@ void EchoState::deviceUpdate(const DeviceBase *Device, const BufferStorage*) std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), 0.0f); for(auto &e : mGains) { - std::fill(std::begin(e.Current), std::end(e.Current), 0.0f); - std::fill(std::begin(e.Target), std::end(e.Target), 0.0f); + std::fill(e.Current.begin(), e.Current.end(), 0.0f); + std::fill(e.Target.begin(), e.Target.end(), 0.0f); } } void EchoState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; - const auto frequency = static_cast(device->Frequency); + const auto frequency = static_cast(device->mSampleRate); - mTap[0].delay = maxu(float2uint(props->Echo.Delay*frequency + 0.5f), 1); - mTap[1].delay = float2uint(props->Echo.LRDelay*frequency + 0.5f) + mTap[0].delay; + mDelayTap[0] = std::max(float2uint(std::round(props.Delay*frequency)), 1u); + mDelayTap[1] = float2uint(std::round(props.LRDelay*frequency)) + mDelayTap[0]; - const float gainhf{maxf(1.0f - props->Echo.Damping, 0.0625f)}; /* Limit -24dB */ + const float gainhf{std::max(1.0f - props.Damping, 0.0625f)}; /* Limit -24dB */ mFilter.setParamsFromSlope(BiquadType::HighShelf, LowpassFreqRef/frequency, gainhf, 1.0f); - mFeedGain = props->Echo.Feedback; + mFeedGain = props.Feedback; - /* Convert echo spread (where 0 = center, +/-1 = sides) to angle. */ - const float angle{std::asin(props->Echo.Spread)}; + /* Convert echo spread (where 0 = center, +/-1 = sides) to a 2D vector. */ + const float x{props.Spread}; /* +x = left */ + const float z{std::sqrt(1.0f - x*x)}; - const auto coeffs0 = CalcAngleCoeffs(-angle, 0.0f, 0.0f); - const auto coeffs1 = CalcAngleCoeffs( angle, 0.0f, 0.0f); + const auto coeffs0 = CalcAmbiCoeffs( x, 0.0f, z, 0.0f); + const auto coeffs1 = CalcAmbiCoeffs(-x, 0.0f, z, 0.0f); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs0.data(), slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, coeffs1.data(), slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, coeffs0, slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, coeffs1, slot->Gain, mGains[1].Target); } void EchoState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - const size_t mask{mSampleBuffer.size()-1}; - float *RESTRICT delaybuf{mSampleBuffer.data()}; + const auto delaybuf = al::span{mSampleBuffer}; + const size_t mask{delaybuf.size()-1}; size_t offset{mOffset}; - size_t tap1{offset - mTap[0].delay}; - size_t tap2{offset - mTap[1].delay}; - float z1, z2; + size_t tap1{offset - mDelayTap[0]}; + size_t tap2{offset - mDelayTap[1]}; ASSUME(samplesToDo > 0); const BiquadFilter filter{mFilter}; - std::tie(z1, z2) = mFilter.getComponents(); + auto [z1, z2] = mFilter.getComponents(); for(size_t i{0u};i < samplesToDo;) { offset &= mask; tap1 &= mask; tap2 &= mask; - size_t td{minz(mask+1 - maxz(offset, maxz(tap1, tap2)), samplesToDo-i)}; + size_t td{std::min(mask+1 - std::max(offset, std::max(tap1, tap2)), samplesToDo-i)}; do { /* Feed the delay buffer's input first. */ delaybuf[offset] = samplesIn[0][i]; @@ -161,8 +160,8 @@ void EchoState::process(const size_t samplesToDo, const al::span #include +#include #include #include -#include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/biquad.h" #include "core/mixer.h" #include "intrusive_ptr.h" +struct BufferStorage; namespace { @@ -86,16 +86,17 @@ namespace { struct EqualizerState final : public EffectState { - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; /* Effect parameters */ - BiquadFilter mFilter[4]; + std::array mFilter; /* Effect gains for each channel */ float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array mChans; alignas(16) FloatBufferLine mSampleBuffer{}; @@ -105,8 +106,6 @@ struct EqualizerState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(EqualizerState) }; void EqualizerState::deviceUpdate(const DeviceBase*, const BufferStorage*) @@ -114,18 +113,17 @@ void EqualizerState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &e : mChans) { e.mTargetChannel = InvalidChannelIndex; - std::for_each(std::begin(e.mFilter), std::end(e.mFilter), - std::mem_fn(&BiquadFilter::clear)); + std::for_each(e.mFilter.begin(), e.mFilter.end(), std::mem_fn(&BiquadFilter::clear)); e.mCurrentGain = 0.0f; } } void EqualizerState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; - auto frequency = static_cast(device->Frequency); - float gain, f0norm; + auto frequency = static_cast(device->mSampleRate); /* Calculate coefficients for the each type of filter. Note that the shelf * and peaking filters' gain is for the centerpoint of the transition band, @@ -133,22 +131,22 @@ void EqualizerState::update(const ContextBase *context, const EffectSlot *slot, * property gains need their dB halved (sqrt of linear gain) for the * shelf/peak to reach the provided gain. */ - gain = std::sqrt(props->Equalizer.LowGain); - f0norm = props->Equalizer.LowCutoff / frequency; + float gain{std::sqrt(props.LowGain)}; + float f0norm{props.LowCutoff / frequency}; mChans[0].mFilter[0].setParamsFromSlope(BiquadType::LowShelf, f0norm, gain, 0.75f); - gain = std::sqrt(props->Equalizer.Mid1Gain); - f0norm = props->Equalizer.Mid1Center / frequency; + gain = std::sqrt(props.Mid1Gain); + f0norm = props.Mid1Center / frequency; mChans[0].mFilter[1].setParamsFromBandwidth(BiquadType::Peaking, f0norm, gain, - props->Equalizer.Mid1Width); + props.Mid1Width); - gain = std::sqrt(props->Equalizer.Mid2Gain); - f0norm = props->Equalizer.Mid2Center / frequency; + gain = std::sqrt(props.Mid2Gain); + f0norm = props.Mid2Center / frequency; mChans[0].mFilter[2].setParamsFromBandwidth(BiquadType::Peaking, f0norm, gain, - props->Equalizer.Mid2Width); + props.Mid2Width); - gain = std::sqrt(props->Equalizer.HighGain); - f0norm = props->Equalizer.HighCutoff / frequency; + gain = std::sqrt(props.HighGain); + f0norm = props.HighCutoff / frequency; mChans[0].mFilter[3].setParamsFromSlope(BiquadType::HighShelf, f0norm, gain, 0.75f); /* Copy the filter coefficients for the other input channels. */ @@ -171,18 +169,17 @@ void EqualizerState::update(const ContextBase *context, const EffectSlot *slot, void EqualizerState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - const al::span buffer{mSampleBuffer.data(), samplesToDo}; - auto chan = std::begin(mChans); + const auto buffer = al::span{mSampleBuffer}.first(samplesToDo); + auto chan = mChans.begin(); for(const auto &input : samplesIn) { - const size_t outidx{chan->mTargetChannel}; - if(outidx != InvalidChannelIndex) + if(const size_t outidx{chan->mTargetChannel}; outidx != InvalidChannelIndex) { - const al::span inbuf{input.data(), samplesToDo}; - DualBiquad{chan->mFilter[0], chan->mFilter[1]}.process(inbuf, buffer.begin()); - DualBiquad{chan->mFilter[2], chan->mFilter[3]}.process(buffer, buffer.begin()); + const auto inbuf = al::span{input}.first(samplesToDo); + DualBiquad{chan->mFilter[0], chan->mFilter[1]}.process(inbuf, buffer); + DualBiquad{chan->mFilter[2], chan->mFilter[3]}.process(buffer, buffer); - MixSamples(buffer, samplesOut[outidx].data(), chan->mCurrentGain, chan->mTargetGain, + MixSamples(buffer, samplesOut[outidx], chan->mCurrentGain, chan->mTargetGain, samplesToDo); } ++chan; diff --git a/3rdparty/openal/alc/effects/fshifter.cpp b/3rdparty/openal/alc/effects/fshifter.cpp index ec0cc29fc339..ee04fd71f940 100644 --- a/3rdparty/openal/alc/effects/fshifter.cpp +++ b/3rdparty/openal/alc/effects/fshifter.cpp @@ -25,23 +25,25 @@ #include #include #include -#include +#include #include "alc/effects/base.h" #include "alcomplex.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" +#include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "core/mixer/defs.h" #include "intrusive_ptr.h" +#include "opthelpers.h" +struct BufferStorage; namespace { @@ -57,7 +59,7 @@ constexpr size_t HilStep{HilSize / OversampleFactor}; /* Define a Hann window, used to filter the HIL input and output. */ struct Windower { - alignas(16) std::array mData; + alignas(16) std::array mData{}; Windower() { @@ -91,10 +93,11 @@ struct FshifterState final : public EffectState { alignas(16) FloatBufferLine mBufferOut{}; /* Effect gains for each output channel */ - struct { - float Current[MaxAmbiChannels]{}; - float Target[MaxAmbiChannels]{}; - } mGains[2]; + struct OutGains { + std::array Current{}; + std::array Target{}; + }; + std::array mGains; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -102,8 +105,6 @@ struct FshifterState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(FshifterState) }; void FshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) @@ -122,20 +123,21 @@ void FshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &gain : mGains) { - std::fill(std::begin(gain.Current), std::end(gain.Current), 0.0f); - std::fill(std::begin(gain.Target), std::end(gain.Target), 0.0f); + gain.Current.fill(0.0f); + gain.Target.fill(0.0f); } } void FshifterState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; - const float step{props->Fshifter.Frequency / static_cast(device->Frequency)}; - mPhaseStep[0] = mPhaseStep[1] = fastf2u(minf(step, 1.0f) * MixerFracOne); + const float step{props.Frequency / static_cast(device->mSampleRate)}; + mPhaseStep[0] = mPhaseStep[1] = fastf2u(std::min(step, 1.0f) * MixerFracOne); - switch(props->Fshifter.LeftDirection) + switch(props.LeftDirection) { case FShifterDirection::Down: mSign[0] = -1.0; @@ -149,7 +151,7 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot, break; } - switch(props->Fshifter.RightDirection) + switch(props.RightDirection) { case FShifterDirection::Down: mSign[1] = -1.0; @@ -172,15 +174,15 @@ void FshifterState::update(const ContextBase *context, const EffectSlot *slot, auto &rcoeffs = (device->mRenderMode != RenderMode::Pairwise) ? rcoeffs_nrml : rcoeffs_pw; mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, lcoeffs.data(), slot->Gain, mGains[0].Target); - ComputePanGains(target.Main, rcoeffs.data(), slot->Gain, mGains[1].Target); + ComputePanGains(target.Main, lcoeffs, slot->Gain, mGains[0].Target); + ComputePanGains(target.Main, rcoeffs, slot->Gain, mGains[1].Target); } void FshifterState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { for(size_t base{0u};base < samplesToDo;) { - size_t todo{minz(HilStep-mCount, samplesToDo-base)}; + size_t todo{std::min(HilStep-mCount, samplesToDo-base)}; /* Fill FIFO buffer with samples data */ const size_t pos{mPos}; @@ -218,25 +220,27 @@ void FshifterState::process(const size_t samplesToDo, const al::span(mBufferOut.data())}; for(size_t c{0};c < 2;++c) { + const double sign{mSign[c]}; const uint phase_step{mPhaseStep[c]}; uint phase_idx{mPhase[c]}; - for(size_t k{0};k < samplesToDo;++k) - { - const double phase{phase_idx * (al::numbers::pi*2.0 / MixerFracOne)}; - BufferOut[k] = static_cast(mOutdata[k].real()*std::cos(phase) + - mOutdata[k].imag()*std::sin(phase)*mSign[c]); - - phase_idx += phase_step; - phase_idx &= MixerFracMask; - } + std::transform(mOutdata.cbegin(), mOutdata.cbegin()+samplesToDo, mBufferOut.begin(), + [&phase_idx,phase_step,sign](const complex_d &in) -> float + { + const double phase{phase_idx * (al::numbers::pi*2.0 / MixerFracOne)}; + const auto out = static_cast(in.real()*std::cos(phase) + + in.imag()*std::sin(phase)*sign); + + phase_idx += phase_step; + phase_idx &= MixerFracMask; + return out; + }); mPhase[c] = phase_idx; /* Now, mix the processed sound data to the output. */ - MixSamples({BufferOut, samplesToDo}, samplesOut, mGains[c].Current, mGains[c].Target, - maxz(samplesToDo, 512), 0); + MixSamples(al::span{mBufferOut}.first(samplesToDo), samplesOut, mGains[c].Current, + mGains[c].Target, std::max(samplesToDo, 512_uz), 0); } } diff --git a/3rdparty/openal/alc/effects/modulator.cpp b/3rdparty/openal/alc/effects/modulator.cpp index f99ba19c03f2..983a945dd712 100644 --- a/3rdparty/openal/alc/effects/modulator.cpp +++ b/3rdparty/openal/alc/effects/modulator.cpp @@ -22,65 +22,56 @@ #include #include +#include +#include #include -#include +#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/biquad.h" #include "core/mixer.h" #include "intrusive_ptr.h" +#include "opthelpers.h" +struct BufferStorage; namespace { using uint = unsigned int; -inline float Sin(uint index, float scale) -{ return std::sin(static_cast(index) * scale); } - -inline float Saw(uint index, float scale) -{ return static_cast(index)*scale - 1.0f; } - -inline float Square(uint index, float scale) -{ return (static_cast(index)*scale < 0.5f)*2.0f - 1.0f; } +struct SinFunc { + static auto Get(uint index, float scale) noexcept(noexcept(std::sin(0.0f))) -> float + { return std::sin(static_cast(index) * scale); } +}; -inline float One(uint, float) -{ return 1.0f; } +struct SawFunc { + static constexpr auto Get(uint index, float scale) noexcept -> float + { return static_cast(index)*scale - 1.0f; } +}; -struct ModulatorState final : public EffectState { - template - void Modulate(size_t todo) - { - const uint range{mRange}; - const float scale{mIndexScale}; - uint index{mIndex}; +struct SquareFunc { + static constexpr auto Get(uint index, float scale) noexcept -> float + { return float(static_cast(index)*scale < 0.5f)*2.0f - 1.0f; } +}; - ASSUME(range > 1); - ASSUME(todo > 0); +struct OneFunc { + static constexpr auto Get(uint, float) noexcept -> float + { return 1.0f; } +}; - for(size_t i{0};i < todo;) - { - size_t rem{minz(todo-i, range-index)}; - do { - mModSamples[i++] = func(index++, scale); - } while(--rem); - if(index == range) - index = 0; - } - mIndex = index; - } - void (ModulatorState::*mGenModSamples)(size_t){}; +struct ModulatorState final : public EffectState { + std::variant mSampleGen; uint mIndex{0}; uint mRange{1}; @@ -89,14 +80,15 @@ struct ModulatorState final : public EffectState { alignas(16) FloatBufferLine mModSamples{}; alignas(16) FloatBufferLine mBuffer{}; - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; BiquadFilter mFilter; float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array mChans; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -104,17 +96,8 @@ struct ModulatorState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(ModulatorState) }; -template<> -void ModulatorState::Modulate(size_t todo) -{ - std::fill_n(mModSamples.begin(), todo, 1.0f); - mIndex = 0; -} - void ModulatorState::deviceUpdate(const DeviceBase*, const BufferStorage*) { for(auto &e : mChans) @@ -126,8 +109,9 @@ void ModulatorState::deviceUpdate(const DeviceBase*, const BufferStorage*) } void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; /* The effective frequency will be adjusted to have a whole number of @@ -137,30 +121,30 @@ void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, * but that may need a more efficient sin function since it needs to do * many iterations per sample. */ - const float samplesPerCycle{props->Modulator.Frequency > 0.0f - ? static_cast(device->Frequency)/props->Modulator.Frequency + 0.5f + const float samplesPerCycle{props.Frequency > 0.0f + ? static_cast(device->mSampleRate)/props.Frequency + 0.5f : 1.0f}; - const uint range{static_cast(clampf(samplesPerCycle, 1.0f, - static_cast(device->Frequency)))}; + const uint range{static_cast(std::clamp(samplesPerCycle, 1.0f, + static_cast(device->mSampleRate)))}; mIndex = static_cast(uint64_t{mIndex} * range / mRange); mRange = range; if(mRange == 1) { mIndexScale = 0.0f; - mGenModSamples = &ModulatorState::Modulate; + mSampleGen.emplace(); } - else if(props->Modulator.Waveform == ModulatorWaveform::Sinusoid) + else if(props.Waveform == ModulatorWaveform::Sinusoid) { mIndexScale = al::numbers::pi_v*2.0f / static_cast(mRange); - mGenModSamples = &ModulatorState::Modulate; + mSampleGen.emplace(); } - else if(props->Modulator.Waveform == ModulatorWaveform::Sawtooth) + else if(props.Waveform == ModulatorWaveform::Sawtooth) { mIndexScale = 2.0f / static_cast(mRange-1); - mGenModSamples = &ModulatorState::Modulate; + mSampleGen.emplace(); } - else /*if(props->Modulator.Waveform == ModulatorWaveform::Square)*/ + else if(props.Waveform == ModulatorWaveform::Square) { /* For square wave, the range should be even (there should be an equal * number of high and low samples). An odd number of samples per cycle @@ -168,11 +152,11 @@ void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, */ mRange = (mRange+1) & ~1u; mIndexScale = 1.0f / static_cast(mRange-1); - mGenModSamples = &ModulatorState::Modulate; + mSampleGen.emplace(); } - float f0norm{props->Modulator.HighPassCutoff / static_cast(device->Frequency)}; - f0norm = clampf(f0norm, 1.0f/512.0f, 0.49f); + float f0norm{props.HighPassCutoff / static_cast(device->mSampleRate)}; + f0norm = std::clamp(f0norm, 1.0f/512.0f, 0.49f); /* Bandwidth value is constant in octaves. */ mChans[0].mFilter.setParamsFromBandwidth(BiquadType::HighPass, f0norm, 1.0f, 0.75f); for(size_t i{1u};i < slot->Wet.Buffer.size();++i) @@ -189,20 +173,39 @@ void ModulatorState::update(const ContextBase *context, const EffectSlot *slot, void ModulatorState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { - (this->*mGenModSamples)(samplesToDo); + ASSUME(samplesToDo > 0); + + std::visit([this,samplesToDo](auto&& type) + { + const uint range{mRange}; + const float scale{mIndexScale}; + uint index{mIndex}; + + ASSUME(range > 1); + + for(size_t i{0};i < samplesToDo;) + { + size_t rem{std::min(samplesToDo-i, size_t{range-index})}; + do { + mModSamples[i++] = type.Get(index++, scale); + } while(--rem); + if(index == range) + index = 0; + } + mIndex = index; + }, mSampleGen); - auto chandata = std::begin(mChans); + auto chandata = mChans.begin(); for(const auto &input : samplesIn) { - const size_t outidx{chandata->mTargetChannel}; - if(outidx != InvalidChannelIndex) + if(const size_t outidx{chandata->mTargetChannel}; outidx != InvalidChannelIndex) { - chandata->mFilter.process({input.data(), samplesToDo}, mBuffer.data()); - for(size_t i{0u};i < samplesToDo;++i) - mBuffer[i] *= mModSamples[i]; + chandata->mFilter.process(al::span{input}.first(samplesToDo), mBuffer); + std::transform(mBuffer.cbegin(), mBuffer.cbegin()+samplesToDo, mModSamples.cbegin(), + mBuffer.begin(), std::multiplies<>{}); - MixSamples({mBuffer.data(), samplesToDo}, samplesOut[outidx].data(), - chandata->mCurrentGain, chandata->mTargetGain, minz(samplesToDo, 64)); + MixSamples(al::span{mBuffer}.first(samplesToDo), samplesOut[outidx], + chandata->mCurrentGain, chandata->mTargetGain, std::min(samplesToDo, 64_uz)); } ++chandata; } diff --git a/3rdparty/openal/alc/effects/null.cpp b/3rdparty/openal/alc/effects/null.cpp index 1f9ae67bc34a..217181a8e710 100644 --- a/3rdparty/openal/alc/effects/null.cpp +++ b/3rdparty/openal/alc/effects/null.cpp @@ -1,14 +1,15 @@ #include "config.h" -#include +#include -#include "almalloc.h" #include "alspan.h" #include "base.h" #include "core/bufferline.h" +#include "core/effects/base.h" #include "intrusive_ptr.h" +struct BufferStorage; struct ContextBase; struct DeviceBase; struct EffectSlot; @@ -25,8 +26,6 @@ struct NullState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(NullState) }; /* This constructs the effect state. It's called when the object is first diff --git a/3rdparty/openal/alc/effects/pshifter.cpp b/3rdparty/openal/alc/effects/pshifter.cpp index 2460cf782751..8b3c6d291cf5 100644 --- a/3rdparty/openal/alc/effects/pshifter.cpp +++ b/3rdparty/openal/alc/effects/pshifter.cpp @@ -25,22 +25,23 @@ #include #include #include -#include +#include #include "alc/effects/base.h" -#include "alcomplex.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" +#include "core/ambidefs.h" #include "core/bufferline.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "core/mixer/defs.h" #include "intrusive_ptr.h" +#include "pffft.h" +struct BufferStorage; struct ContextBase; @@ -58,7 +59,7 @@ constexpr size_t StftStep{StftSize / OversampleFactor}; /* Define a Hann window, used to filter the STFT input and output. */ struct Windower { - alignas(16) std::array mData; + alignas(16) std::array mData{}; Windower() { @@ -82,27 +83,29 @@ struct FrequencyBin { struct PshifterState final : public EffectState { /* Effect parameters */ - size_t mCount; - size_t mPos; - uint mPitchShiftI; - float mPitchShift; + size_t mCount{}; + size_t mPos{}; + uint mPitchShiftI{}; + float mPitchShift{}; /* Effects buffers */ - std::array mFIFO; - std::array mLastPhase; - std::array mSumPhase; - std::array mOutputAccum; + std::array mFIFO{}; + std::array mLastPhase{}; + std::array mSumPhase{}; + std::array mOutputAccum{}; - std::array mFftBuffer; + PFFFTSetup mFft; + alignas(16) std::array mFftBuffer{}; + alignas(16) std::array mFftWorkBuffer{}; - std::array mAnalysisBuffer; - std::array mSynthesisBuffer; + std::array mAnalysisBuffer{}; + std::array mSynthesisBuffer{}; - alignas(16) FloatBufferLine mBufferOut; + alignas(16) FloatBufferLine mBufferOut{}; /* Effect gains for each output channel */ - float mCurrentGains[MaxAmbiChannels]; - float mTargetGains[MaxAmbiChannels]; + std::array mCurrentGains{}; + std::array mTargetGains{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; @@ -110,8 +113,6 @@ struct PshifterState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(PshifterState) }; void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) @@ -126,26 +127,31 @@ void PshifterState::deviceUpdate(const DeviceBase*, const BufferStorage*) mLastPhase.fill(0.0f); mSumPhase.fill(0.0f); mOutputAccum.fill(0.0f); - mFftBuffer.fill(complex_f{}); + mFftBuffer.fill(0.0f); mAnalysisBuffer.fill(FrequencyBin{}); mSynthesisBuffer.fill(FrequencyBin{}); - std::fill(std::begin(mCurrentGains), std::end(mCurrentGains), 0.0f); - std::fill(std::begin(mTargetGains), std::end(mTargetGains), 0.0f); + mCurrentGains.fill(0.0f); + mTargetGains.fill(0.0f); + + if(!mFft) + mFft = PFFFTSetup{StftSize, PFFFT_REAL}; } void PshifterState::update(const ContextBase*, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { - const int tune{props->Pshifter.CoarseTune*100 + props->Pshifter.FineTune}; + auto &props = std::get(*props_); + const int tune{props.CoarseTune*100 + props.FineTune}; const float pitch{std::pow(2.0f, static_cast(tune) / 1200.0f)}; - mPitchShiftI = clampu(fastf2u(pitch*MixerFracOne), MixerFracHalf, MixerFracOne*2); + mPitchShiftI = std::clamp(fastf2u(pitch*MixerFracOne), uint{MixerFracHalf}, + uint{MixerFracOne}*2u); mPitchShift = static_cast(mPitchShiftI) * float{1.0f/MixerFracOne}; static constexpr auto coeffs = CalcDirectionCoeffs(std::array{0.0f, 0.0f, -1.0f}); mOutTarget = target.Main->Buffer; - ComputePanGains(target.Main, coeffs.data(), slot->Gain, mTargetGains); + ComputePanGains(target.Main, coeffs, slot->Gain, mTargetGains); } void PshifterState::process(const size_t samplesToDo, @@ -162,7 +168,7 @@ void PshifterState::process(const size_t samplesToDo, for(size_t base{0u};base < samplesToDo;) { - const size_t todo{minz(StftStep-mCount, samplesToDo-base)}; + const size_t todo{std::min(StftStep-mCount, samplesToDo-base)}; /* Retrieve the output samples from the FIFO and fill in the new input * samples. @@ -186,15 +192,19 @@ void PshifterState::process(const size_t samplesToDo, mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; for(size_t src{0u}, k{StftSize-mPos};src < mPos;++src,++k) mFftBuffer[k] = mFIFO[src] * gWindow.mData[k]; - forward_fft(al::span{mFftBuffer}); + mFft.transform_ordered(mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(), + PFFFT_FORWARD); /* Analyze the obtained data. Since the real FFT is symmetric, only * StftHalfSize+1 samples are needed. */ - for(size_t k{0u};k < StftHalfSize+1;k++) + for(size_t k{0u};k < StftHalfSize+1;++k) { - const float magnitude{std::abs(mFftBuffer[k])}; - const float phase{std::arg(mFftBuffer[k])}; + const auto cplx = (k == 0) ? complex_f{mFftBuffer[0]} : + (k == StftHalfSize) ? complex_f{mFftBuffer[1]} : + complex_f{mFftBuffer[k*2], mFftBuffer[k*2 + 1]}; + const float magnitude{std::abs(cplx)}; + const float phase{std::arg(cplx)}; /* Compute the phase difference from the last update and subtract * the expected phase difference for this bin. @@ -232,8 +242,8 @@ void PshifterState::process(const size_t samplesToDo, */ std::fill(mSynthesisBuffer.begin(), mSynthesisBuffer.end(), FrequencyBin{}); - constexpr size_t bin_limit{((StftHalfSize+1)<> MixerFracBits}; @@ -266,21 +276,29 @@ void PshifterState::process(const size_t samplesToDo, tmp -= static_cast(qpd + (qpd%2)); mSumPhase[k] = tmp * al::numbers::pi_v; - mFftBuffer[k] = std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k]); + const complex_f cplx{std::polar(mSynthesisBuffer[k].Magnitude, mSumPhase[k])}; + if(k == 0) + mFftBuffer[0] = cplx.real(); + else if(k == StftHalfSize) + mFftBuffer[1] = cplx.real(); + else + { + mFftBuffer[k*2 + 0] = cplx.real(); + mFftBuffer[k*2 + 1] = cplx.imag(); + } } - for(size_t k{StftHalfSize+1};k < StftSize;++k) - mFftBuffer[k] = std::conj(mFftBuffer[StftSize-k]); /* Apply an inverse FFT to get the time-domain signal, and accumulate * for the output with windowing. */ - inverse_fft(al::span{mFftBuffer}); + mFft.transform_ordered(mFftBuffer.data(), mFftBuffer.data(), mFftWorkBuffer.data(), + PFFFT_BACKWARD); static constexpr float scale{3.0f / OversampleFactor / StftSize}; for(size_t dst{mPos}, k{0u};dst < StftSize;++dst,++k) - mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale; + mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale; for(size_t dst{0u}, k{StftSize-mPos};dst < mPos;++dst,++k) - mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k].real() * scale; + mOutputAccum[dst] += gWindow.mData[k]*mFftBuffer[k] * scale; /* Copy out the accumulated result, then clear for the next iteration. */ std::copy_n(mOutputAccum.begin() + mPos, StftStep, mFIFO.begin() + mPos); @@ -288,8 +306,8 @@ void PshifterState::process(const size_t samplesToDo, } /* Now, mix the processed sound data to the output. */ - MixSamples({mBufferOut.data(), samplesToDo}, samplesOut, mCurrentGains, mTargetGains, - maxz(samplesToDo, 512), 0); + MixSamples(al::span{mBufferOut}.first(samplesToDo), samplesOut, mCurrentGains, mTargetGains, + std::max(samplesToDo, 512_uz), 0); } diff --git a/3rdparty/openal/alc/effects/reverb.cpp b/3rdparty/openal/alc/effects/reverb.cpp index b00f638b27a7..7e907911bc86 100644 --- a/3rdparty/openal/alc/effects/reverb.cpp +++ b/3rdparty/openal/alc/effects/reverb.cpp @@ -22,22 +22,23 @@ #include #include +#include +#include +#include #include #include -#include #include -#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" +#include "core/cubic_tables.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/filters/biquad.h" #include "core/filters/splitter.h" @@ -45,13 +46,9 @@ #include "core/mixer/defs.h" #include "intrusive_ptr.h" #include "opthelpers.h" -#include "vecmat.h" #include "vector.h" -/* This is a user config option for modifying the overall output of the reverb - * effect. - */ -float ReverbBoost = 1.0f; +struct BufferStorage; namespace { @@ -65,41 +62,6 @@ constexpr float DefaultModulationTime{0.25f}; #define MOD_FRACMASK (MOD_FRACONE-1) -struct CubicFilter { - static constexpr size_t sTableBits{8}; - static constexpr size_t sTableSteps{1 << sTableBits}; - static constexpr size_t sTableMask{sTableSteps - 1}; - - float mFilter[sTableSteps*2 + 1]{}; - - constexpr CubicFilter() - { - /* This creates a lookup table for a cubic spline filter, with 256 - * steps between samples. Only half the coefficients are needed, since - * Coeff2 is just Coeff1 in reverse and Coeff3 is just Coeff0 in - * reverse. - */ - for(size_t i{0};i < sTableSteps;++i) - { - const double mu{static_cast(i) / double{sTableSteps}}; - const double mu2{mu*mu}, mu3{mu2*mu}; - const double a0{-0.5*mu3 + mu2 + -0.5*mu}; - const double a1{ 1.5*mu3 + -2.5*mu2 + 1.0f}; - mFilter[i] = static_cast(a1); - mFilter[sTableSteps+i] = static_cast(a0); - } - } - - constexpr float getCoeff0(size_t i) const noexcept { return mFilter[sTableSteps+i]; } - constexpr float getCoeff1(size_t i) const noexcept { return mFilter[i]; } - constexpr float getCoeff2(size_t i) const noexcept { return mFilter[sTableSteps-i]; } - constexpr float getCoeff3(size_t i) const noexcept { return mFilter[sTableSteps*2-i]; } -}; -constexpr CubicFilter gCubicTable; - - -using namespace std::placeholders; - /* Max samples per process iteration. Used to limit the size needed for * temporary buffers. Must be a multiple of 4 for SIMD alignment. */ @@ -122,35 +84,41 @@ constexpr size_t NUM_LINES{4u}; constexpr float MODULATION_DEPTH_COEFF{0.05f}; -/* The B-Format to A-Format conversion matrix. The arrangement of rows is - * deliberately chosen to align the resulting lines to their spatial opposites - * (0:above front left <-> 3:above back right, 1:below front right <-> 2:below - * back left). It's not quite opposite, since the A-Format results in a - * tetrahedron, but it's close enough. Should the model be extended to 8-lines - * in the future, true opposites can be used. +/* The B-Format to (W-normalized) A-Format conversion matrix. This produces a + * tetrahedral array of discrete signals (boosted by a factor of sqrt(3), to + * reduce the error introduced in the conversion). */ -alignas(16) constexpr float B2A[NUM_LINES][NUM_LINES]{ - { 0.5f, 0.5f, 0.5f, 0.5f }, - { 0.5f, -0.5f, -0.5f, 0.5f }, - { 0.5f, 0.5f, -0.5f, -0.5f }, - { 0.5f, -0.5f, 0.5f, -0.5f } -}; +alignas(16) constexpr std::array,NUM_LINES> B2A{{ + /* W Y Z X */ + {{ 0.5f, 0.5f, 0.5f, 0.5f }}, /* A0 */ + {{ 0.5f, -0.5f, -0.5f, 0.5f }}, /* A1 */ + {{ 0.5f, 0.5f, -0.5f, -0.5f }}, /* A2 */ + {{ 0.5f, -0.5f, 0.5f, -0.5f }} /* A3 */ +}}; -/* Converts A-Format to B-Format for early reflections. */ +/* Converts (W-normalized) A-Format to B-Format for early reflections (scaled + * by 1/sqrt(3) to compensate for the boost in the B2A matrix). + */ alignas(16) constexpr std::array,NUM_LINES> EarlyA2B{{ - {{ 0.5f, 0.5f, 0.5f, 0.5f }}, - {{ 0.5f, -0.5f, 0.5f, -0.5f }}, - {{ 0.5f, -0.5f, -0.5f, 0.5f }}, - {{ 0.5f, 0.5f, -0.5f, -0.5f }} + /* A0 A1 A2 A3 */ + {{ 0.5f, 0.5f, 0.5f, 0.5f }}, /* W */ + {{ 0.5f, -0.5f, 0.5f, -0.5f }}, /* Y */ + {{ 0.5f, -0.5f, -0.5f, 0.5f }}, /* Z */ + {{ 0.5f, 0.5f, -0.5f, -0.5f }} /* X */ }}; -/* Converts A-Format to B-Format for late reverb. */ +/* Converts (W-normalized) A-Format to B-Format for late reverb (scaled + * by 1/sqrt(3) to compensate for the boost in the B2A matrix). The response + * is rotated around Z (ambisonic X) so that the front lines are placed + * horizontally in front, and the rear lines are placed vertically in back. + */ constexpr auto InvSqrt2 = static_cast(1.0/al::numbers::sqrt2); alignas(16) constexpr std::array,NUM_LINES> LateA2B{{ - {{ 0.5f, 0.5f, 0.5f, 0.5f }}, - {{ InvSqrt2, -InvSqrt2, 0.0f, 0.0f }}, - {{ 0.0f, 0.0f, InvSqrt2, -InvSqrt2 }}, - {{ 0.5f, 0.5f, -0.5f, -0.5f }} + /* A0 A1 A2 A3 */ + {{ 0.5f, 0.5f, 0.5f, 0.5f }}, /* W */ + {{ InvSqrt2, -InvSqrt2, 0.0f, 0.0f }}, /* Y */ + {{ 0.0f, 0.0f, -InvSqrt2, InvSqrt2 }}, /* Z */ + {{ 0.5f, 0.5f, -0.5f, -0.5f }} /* X */ }}; /* The all-pass and delay lines have a variable length dependent on the @@ -251,7 +219,7 @@ constexpr std::array EARLY_ALLPASS_LENGTHS{{ * Using an average dimension of 1m, we get: */ constexpr std::array EARLY_LINE_LENGTHS{{ - 5.9850400e-4f, 1.0913150e-3f, 1.5376658e-3f, 1.9419362e-3f + 0.0000000e+0f, 4.9281100e-4f, 9.3916180e-4f, 1.3434322e-3f }}; /* The late all-pass filter lengths are based on the late line lengths: @@ -288,21 +256,17 @@ struct DelayLineI { /* The delay lines use interleaved samples, with the lengths being powers * of 2 to allow the use of bit-masking instead of a modulus for wrapping. */ - size_t Mask{0u}; - union { - uintptr_t LineOffset{0u}; - std::array *Line; - }; + al::span mLine; /* Given the allocated sample buffer, this function updates each delay line * offset. */ - void realizeLineOffset(std::array *sampleBuffer) noexcept - { Line = sampleBuffer + LineOffset; } + void realizeLineOffset(al::span sampleBuffer) noexcept + { mLine = sampleBuffer; } /* Calculate the length of a delay line and store its mask and offset. */ - uint calcLineLength(const float length, const uintptr_t offset, const float frequency, - const uint extra) + static + auto calcLineLength(const float length, const float frequency, const uint extra) -> size_t { /* All line lengths are powers of 2, calculated from their lengths in * seconds, rounded up. @@ -310,23 +274,85 @@ struct DelayLineI { uint samples{float2uint(std::ceil(length*frequency))}; samples = NextPowerOf2(samples + extra); - /* All lines share a single sample buffer. */ - Mask = samples - 1; - LineOffset = offset; - /* Return the sample count for accumulation. */ - return samples; + return samples*NUM_LINES; + } +}; + +struct DelayLineU { + al::span mLine; + + void realizeLineOffset(al::span sampleBuffer) noexcept + { + assert(sampleBuffer.size() > 4 && !(sampleBuffer.size() & (sampleBuffer.size()-1))); + mLine = sampleBuffer; } - void write(size_t offset, const size_t c, const float *RESTRICT in, const size_t count) const noexcept + static + auto calcLineLength(const float length, const float frequency, const uint extra) -> size_t { - ASSUME(count > 0); + uint samples{float2uint(std::ceil(length*frequency))}; + samples = NextPowerOf2(samples + extra); + + return samples*NUM_LINES; + } + + [[nodiscard]] + auto get(size_t chan) const noexcept + { + const size_t stride{mLine.size() / NUM_LINES}; + return mLine.subspan(chan*stride, stride); + } + + void write(size_t offset, const size_t c, al::span in) const noexcept + { + const size_t stride{mLine.size() / NUM_LINES}; + const auto output = mLine.subspan(c*stride); + while(!in.empty()) + { + offset &= stride-1; + const size_t td{std::min(stride - offset, in.size())}; + std::copy_n(in.begin(), td, output.begin() + ptrdiff_t(offset)); + offset += td; + in = in.subspan(td); + } + } + + /* Writes the given input lines to the delay buffer, applying a geometric + * reflection. This effectively applies the matrix + * + * [ +1/2 -1/2 -1/2 -1/2 ] + * [ -1/2 +1/2 -1/2 -1/2 ] + * [ -1/2 -1/2 +1/2 -1/2 ] + * [ -1/2 -1/2 -1/2 +1/2 ] + * + * to the four input lines when writing to the delay buffer. The effect on + * the B-Format signal is negating W, applying a 180-degree phase shift and + * moving each response to its spatially opposite location. + */ + void writeReflected(size_t offset, const al::span in, + const size_t count) const noexcept + { + const size_t stride{mLine.size() / NUM_LINES}; for(size_t i{0u};i < count;) { - offset &= Mask; - size_t td{minz(Mask+1 - offset, count - i)}; + offset &= stride-1; + size_t td{std::min(stride - offset, count - i)}; do { - Line[offset++][c] = in[i++]; + const std::array src{in[0][i], in[1][i], in[2][i], in[3][i]}; + ++i; + + const std::array f{ + (src[0] - src[1] - src[2] - src[3]) * 0.5f, + (src[1] - src[0] - src[2] - src[3]) * 0.5f, + (src[2] - src[0] - src[1] - src[3]) * 0.5f, + (src[3] - src[0] - src[1] - src[2] ) * 0.5f + }; + mLine[0*stride + offset] = f[0]; + mLine[1*stride + offset] = f[1]; + mLine[2*stride + offset] = f[2]; + mLine[3*stride + offset] = f[3]; + ++offset; } while(--td); } } @@ -335,10 +361,19 @@ struct DelayLineI { struct VecAllpass { DelayLineI Delay; float Coeff{0.0f}; - size_t Offset[NUM_LINES]{}; + std::array Offset{}; void process(const al::span samples, size_t offset, - const float xCoeff, const float yCoeff, const size_t todo); + const float xCoeff, const float yCoeff, const size_t todo) const noexcept; +}; + +struct Allpass4 { + DelayLineU Delay; + float Coeff{0.0f}; + std::array Offset{}; + + void process(const al::span samples, const size_t offset, + const size_t todo) const noexcept; }; struct T60Filter { @@ -353,30 +388,37 @@ struct T60Filter { /* Applies the two T60 damping filter sections. */ void process(const al::span samples) - { DualBiquad{HFFilter, LFFilter}.process(samples, samples.data()); } + { DualBiquad{HFFilter, LFFilter}.process(samples, samples); } void clear() noexcept { HFFilter.clear(); LFFilter.clear(); } }; struct EarlyReflections { - /* A Gerzon vector all-pass filter is used to simulate initial diffusion. - * The spread from this filter also helps smooth out the reverb tail. - */ - VecAllpass VecAp; + Allpass4 VecAp; /* An echo line is used to complete the second half of the early * reflections. */ - DelayLineI Delay; - size_t Offset[NUM_LINES]{}; - float Coeff[NUM_LINES]{}; + DelayLineU Delay; + std::array Offset{}; + float Coeff{}; /* The gain for each output channel based on 3D panning. */ - float CurrentGains[NUM_LINES][MaxAmbiChannels]{}; - float TargetGains[NUM_LINES][MaxAmbiChannels]{}; + struct OutGains { + std::array Current{}; + std::array Target{}; + + void clear() { Current.fill(0.0f); Target.fill(0.0); } + }; + std::array Gains{}; void updateLines(const float density_mult, const float diffusion, const float decayTime, const float frequency); + + void clear() + { + std::for_each(Gains.begin(), Gains.end(), std::mem_fn(&OutGains::clear)); + } }; @@ -384,22 +426,29 @@ struct Modulation { /* The vibrato time is tracked with an index over a (MOD_FRACONE) * normalized range. */ - uint Index, Step; + uint Index{0u}, Step{1u}; /* The depth of frequency change, in samples. */ - float Depth; + float Depth{0.0f}; - float ModDelays[MAX_UPDATE_SAMPLES]; + std::array ModDelays{}; void updateModulator(float modTime, float modDepth, float frequency); - void calcDelays(size_t todo); + auto calcDelays(size_t todo) -> al::span; + + void clear() noexcept + { + Index = 0u; + Step = 1u; + Depth = 0.0f; + } }; struct LateReverb { /* A recursive delay line is used fill in the reverb tail. */ - DelayLineI Delay; - size_t Offset[NUM_LINES]{}; + DelayLineU Delay; + std::array Offset{}; /* Attenuation to compensate for the modal density and decay rate of the * late lines. @@ -407,7 +456,7 @@ struct LateReverb { float DensityGain{0.0f}; /* T60 decay filters are used to simulate absorption. */ - T60Filter T60[NUM_LINES]; + std::array T60; Modulation Mod; @@ -415,40 +464,49 @@ struct LateReverb { VecAllpass VecAp; /* The gain for each output channel based on 3D panning. */ - float CurrentGains[NUM_LINES][MaxAmbiChannels]{}; - float TargetGains[NUM_LINES][MaxAmbiChannels]{}; + struct OutGains { + std::array Current{}; + std::array Target{}; + + void clear() { Current.fill(0.0f); Target.fill(0.0); } + }; + std::array Gains{}; void updateLines(const float density_mult, const float diffusion, const float lfDecayTime, const float mfDecayTime, const float hfDecayTime, const float lf0norm, const float hf0norm, const float frequency); - void clear() noexcept + void clear() { - for(auto &filter : T60) - filter.clear(); + std::for_each(T60.begin(), T60.end(), std::mem_fn(&T60Filter::clear)); + Mod.clear(); + std::for_each(Gains.begin(), Gains.end(), std::mem_fn(&OutGains::clear)); } }; struct ReverbPipeline { /* Master effect filters */ - struct { + struct FilterPair { BiquadFilter Lp; BiquadFilter Hp; - } mFilter[NUM_LINES]; + void clear() noexcept { Lp.clear(); Hp.clear(); } + }; + std::array mFilter; - /* Core delay line (early reflections and late reverb tap from this). */ - DelayLineI mEarlyDelayIn; - DelayLineI mLateDelayIn; + /* Late reverb input delay line (early reflections feed this, and late + * reverb taps from it). + */ + DelayLineU mLateDelayIn; - /* Tap points for early reflection delay. */ - size_t mEarlyDelayTap[NUM_LINES][2]{}; - float mEarlyDelayCoeff[NUM_LINES]{}; + /* Tap points for early reflection input delay. */ + std::array,NUM_LINES> mEarlyDelayTap{}; + std::array mEarlyDelayCoeff{}; /* Tap points for late reverb feed and delay. */ - size_t mLateDelayTap[NUM_LINES][2]{}; + std::array,NUM_LINES> mLateDelayTap{}; /* Coefficients for the all-pass and line scattering matrices. */ - float mMixX{0.0f}; + float mMixX{1.0f}; float mMixY{0.0f}; EarlyReflections mEarly; @@ -459,13 +517,13 @@ struct ReverbPipeline { size_t mFadeSampleCount{1}; - void updateDelayLine(const float earlyDelay, const float lateDelay, const float density_mult, - const float decayTime, const float frequency); + void updateDelayLine(const float gain, const float earlyDelay, const float lateDelay, + const float density_mult, const float frequency); void update3DPanning(const al::span ReflectionsPan, const al::span LateReverbPan, const float earlyGain, const float lateGain, const bool doUpmix, const MixParams *mainMix); - void processEarly(size_t offset, const size_t samplesToDo, + void processEarly(const DelayLineU &main_delay, size_t offset, const size_t samplesToDo, const al::span tempSamples, const al::span outSamples); void processLate(size_t offset, const size_t samplesToDo, @@ -474,17 +532,15 @@ struct ReverbPipeline { void clear() noexcept { - for(auto &filter : mFilter) - { - filter.Lp.clear(); - filter.Hp.clear(); - } + std::for_each(mFilter.begin(), mFilter.end(), std::mem_fn(&FilterPair::clear)); + mEarlyDelayTap = {}; + mEarlyDelayCoeff = {}; + mLateDelayTap = {}; + mEarly.clear(); mLate.clear(); - for(auto &filters : mAmbiSplitter) - { - for(auto &filter : filters) - filter.clear(); - } + auto clear_filters = [](const al::span filters) + { std::for_each(filters.begin(), filters.end(), std::mem_fn(&BandSplitter::clear)); }; + std::for_each(mAmbiSplitter.begin(), mAmbiSplitter.end(), clear_filters); } }; @@ -492,9 +548,9 @@ struct ReverbState final : public EffectState { /* All delay lines are allocated as a single buffer to reduce memory * fragmentation and management code. */ - al::vector,16> mSampleBuffer; + al::vector mSampleBuffer; - struct { + struct Params { /* Calculated parameters which indicate if cross-fading is needed after * an update. */ @@ -507,7 +563,8 @@ struct ReverbState final : public EffectState { float ModulationDepth{0.0f}; float HFReference{5000.0f}; float LFReference{250.0f}; - } mParams; + }; + Params mParams; enum PipelineState : uint8_t { DeviceClear, @@ -517,18 +574,20 @@ struct ReverbState final : public EffectState { Normal, }; PipelineState mPipelineState{DeviceClear}; - uint8_t mCurrentPipeline{0}; + bool mCurrentPipeline{false}; + + /* Core delay line (early reflections tap from this). */ + DelayLineU mMainDelay; - ReverbPipeline mPipelines[2]; + std::array mPipelines; /* The current write offset for all delay lines. */ size_t mOffset{}; /* Temporary storage used when processing. */ - union { - alignas(16) FloatBufferLine mTempLine{}; - alignas(16) std::array mTempSamples; - }; + alignas(16) FloatBufferLine mTempLine{}; + alignas(16) std::array mTempSamples{}; + alignas(16) std::array mEarlySamples{}; alignas(16) std::array mLateSamples{}; @@ -538,48 +597,43 @@ struct ReverbState final : public EffectState { void MixOutPlain(ReverbPipeline &pipeline, const al::span samplesOut, - const size_t todo) + const size_t todo) const { - ASSUME(todo > 0); - /* When not upsampling, the panning gains convert to B-Format and pan * at the same time. */ - for(size_t c{0u};c < NUM_LINES;c++) + auto inBuffer = mEarlySamples.cbegin(); + for(auto &gains : pipeline.mEarly.Gains) { - const al::span tmpspan{mEarlySamples[c].data(), todo}; - MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c], - pipeline.mEarly.TargetGains[c], todo, 0); + MixSamples(al::span{*inBuffer++}.first(todo), samplesOut, gains.Current, gains.Target, + todo, 0); } - for(size_t c{0u};c < NUM_LINES;c++) + inBuffer = mLateSamples.cbegin(); + for(auto &gains : pipeline.mLate.Gains) { - const al::span tmpspan{mLateSamples[c].data(), todo}; - MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c], - pipeline.mLate.TargetGains[c], todo, 0); + MixSamples(al::span{*inBuffer++}.first(todo), samplesOut, gains.Current, gains.Target, + todo, 0); } } void MixOutAmbiUp(ReverbPipeline &pipeline, const al::span samplesOut, const size_t todo) { - ASSUME(todo > 0); - auto DoMixRow = [](const al::span OutBuffer, const al::span Gains, - const float *InSamples, const size_t InStride) + const al::span InSamples) { + auto inBuffer = InSamples.cbegin(); std::fill(OutBuffer.begin(), OutBuffer.end(), 0.0f); for(const float gain : Gains) { - const float *RESTRICT input{al::assume_aligned<16>(InSamples)}; - InSamples += InStride; - - if(!(std::fabs(gain) > GainSilenceThreshold)) - continue; - - auto mix_sample = [gain](const float sample, const float in) noexcept -> float - { return sample + in*gain; }; - std::transform(OutBuffer.begin(), OutBuffer.end(), input, OutBuffer.begin(), - mix_sample); + if(std::fabs(gain) > GainSilenceThreshold) + { + auto mix_sample = [gain](const float sample, const float in) noexcept -> float + { return sample + in*gain; }; + std::transform(OutBuffer.begin(), OutBuffer.end(), inBuffer->cbegin(), + OutBuffer.begin(), mix_sample); + } + ++inBuffer; } }; @@ -587,29 +641,33 @@ struct ReverbState final : public EffectState { * so the proper HF scaling can be applied to each B-Format channel. * The panning gains then pan and upsample the B-Format channels. */ - const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), todo}; - for(size_t c{0u};c < NUM_LINES;c++) + const auto tmpspan = al::span{mTempLine}.first(todo); + auto hfscale = float{mOrderScales[0]}; + auto splitter = pipeline.mAmbiSplitter[0].begin(); + auto a2bcoeffs = EarlyA2B.cbegin(); + for(auto &gains : pipeline.mEarly.Gains) { - DoMixRow(tmpspan, EarlyA2B[c], mEarlySamples[0].data(), mEarlySamples[0].size()); + DoMixRow(tmpspan, *(a2bcoeffs++), mEarlySamples); /* Apply scaling to the B-Format's HF response to "upsample" it to * higher-order output. */ - const float hfscale{(c==0) ? mOrderScales[0] : mOrderScales[1]}; - pipeline.mAmbiSplitter[0][c].processHfScale(tmpspan, hfscale); + (splitter++)->processHfScale(tmpspan, hfscale); + hfscale = mOrderScales[1]; - MixSamples(tmpspan, samplesOut, pipeline.mEarly.CurrentGains[c], - pipeline.mEarly.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, gains.Current, gains.Target, todo, 0); } - for(size_t c{0u};c < NUM_LINES;c++) + hfscale = mOrderScales[0]; + splitter = pipeline.mAmbiSplitter[1].begin(); + a2bcoeffs = LateA2B.cbegin(); + for(auto &gains : pipeline.mLate.Gains) { - DoMixRow(tmpspan, LateA2B[c], mLateSamples[0].data(), mLateSamples[0].size()); + DoMixRow(tmpspan, *(a2bcoeffs++), mLateSamples); - const float hfscale{(c==0) ? mOrderScales[0] : mOrderScales[1]}; - pipeline.mAmbiSplitter[1][c].processHfScale(tmpspan, hfscale); + (splitter++)->processHfScale(tmpspan, hfscale); + hfscale = mOrderScales[1]; - MixSamples(tmpspan, samplesOut, pipeline.mLate.CurrentGains[c], - pipeline.mLate.TargetGains[c], todo, 0); + MixSamples(tmpspan, samplesOut, gains.Current, gains.Target, todo, 0); } } @@ -628,8 +686,6 @@ struct ReverbState final : public EffectState { const EffectTarget target) override; void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - - DEF_NEWDEL(ReverbState) }; /************************************** @@ -637,18 +693,13 @@ struct ReverbState final : public EffectState { **************************************/ inline float CalcDelayLengthMult(float density) -{ return maxf(5.0f, std::cbrt(density*DENSITY_SCALE)); } +{ return std::max(5.0f, std::cbrt(density*DENSITY_SCALE)); } /* Calculates the delay line metrics and allocates the shared sample buffer * for all lines given the sample rate (frequency). */ void ReverbState::allocLines(const float frequency) { - /* All delay line lengths are calculated to accommodate the full range of - * lengths given their respective parameters. - */ - size_t totalSamples{0u}; - /* Multiplier for the maximum density value, i.e. density=1, which is * actually the least density... */ @@ -658,108 +709,93 @@ void ReverbState::allocLines(const float frequency) * time and depth coefficient, and halfed for the low-to-high frequency * swing. */ - constexpr float max_mod_delay{MaxModulationTime*MODULATION_DEPTH_COEFF / 2.0f}; + static constexpr float max_mod_delay{MaxModulationTime*MODULATION_DEPTH_COEFF / 2.0f}; + + std::array linelengths{}; + size_t oidx{0}; + size_t totalSamples{0u}; + /* The main delay length includes the maximum early reflection delay and + * the largest early tap width. It must also be extended by the update size + * (BufferLineSize) for block processing. + */ + float length{ReverbMaxReflectionsDelay + EARLY_TAP_LENGTHS.back()*multiplier}; + size_t count{mMainDelay.calcLineLength(length, frequency, BufferLineSize)}; + linelengths[oidx++] = count; + totalSamples += count; for(auto &pipeline : mPipelines) { - /* The main delay length includes the maximum early reflection delay, - * the largest early tap width, the maximum late reverb delay, and the - * largest late tap width. Finally, it must also be extended by the - * update size (BufferLineSize) for block processing. - */ - float length{ReverbMaxReflectionsDelay + EARLY_TAP_LENGTHS.back()*multiplier}; - totalSamples += pipeline.mEarlyDelayIn.calcLineLength(length, totalSamples, frequency, - BufferLineSize); - - constexpr float LateLineDiffAvg{(LATE_LINE_LENGTHS.back()-LATE_LINE_LENGTHS.front()) / + static constexpr float LateDiffAvg{(LATE_LINE_LENGTHS.back()-LATE_LINE_LENGTHS.front()) / float{NUM_LINES}}; - length = ReverbMaxLateReverbDelay + LateLineDiffAvg*multiplier; - totalSamples += pipeline.mLateDelayIn.calcLineLength(length, totalSamples, frequency, - BufferLineSize); + length = ReverbMaxLateReverbDelay + LateDiffAvg*multiplier; + count = pipeline.mLateDelayIn.calcLineLength(length, frequency, BufferLineSize); + linelengths[oidx++] = count; + totalSamples += count; /* The early vector all-pass line. */ length = EARLY_ALLPASS_LENGTHS.back() * multiplier; - totalSamples += pipeline.mEarly.VecAp.Delay.calcLineLength(length, totalSamples, frequency, - 0); + count = pipeline.mEarly.VecAp.Delay.calcLineLength(length, frequency, 0); + linelengths[oidx++] = count; + totalSamples += count; /* The early reflection line. */ length = EARLY_LINE_LENGTHS.back() * multiplier; - totalSamples += pipeline.mEarly.Delay.calcLineLength(length, totalSamples, frequency, - MAX_UPDATE_SAMPLES); + count = pipeline.mEarly.Delay.calcLineLength(length, frequency, MAX_UPDATE_SAMPLES); + linelengths[oidx++] = count; + totalSamples += count; /* The late vector all-pass line. */ length = LATE_ALLPASS_LENGTHS.back() * multiplier; - totalSamples += pipeline.mLate.VecAp.Delay.calcLineLength(length, totalSamples, frequency, - 0); + count = pipeline.mLate.VecAp.Delay.calcLineLength(length, frequency, 0); + linelengths[oidx++] = count; + totalSamples += count; /* The late delay lines are calculated from the largest maximum density * line length, and the maximum modulation delay. Four additional * samples are needed for resampling the modulator delay. */ length = LATE_LINE_LENGTHS.back()*multiplier + max_mod_delay; - totalSamples += pipeline.mLate.Delay.calcLineLength(length, totalSamples, frequency, 4); + count = pipeline.mLate.Delay.calcLineLength(length, frequency, 4); + linelengths[oidx++] = count; + totalSamples += count; } + assert(oidx == linelengths.size()); if(totalSamples != mSampleBuffer.size()) decltype(mSampleBuffer)(totalSamples).swap(mSampleBuffer); /* Clear the sample buffer. */ - std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), decltype(mSampleBuffer)::value_type{}); + std::fill(mSampleBuffer.begin(), mSampleBuffer.end(), 0.0f); /* Update all delays to reflect the new sample buffer. */ + auto bufferspan = al::span{mSampleBuffer}; + oidx = 0; + mMainDelay.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); for(auto &pipeline : mPipelines) { - pipeline.mEarlyDelayIn.realizeLineOffset(mSampleBuffer.data()); - pipeline.mLateDelayIn.realizeLineOffset(mSampleBuffer.data()); - pipeline.mEarly.VecAp.Delay.realizeLineOffset(mSampleBuffer.data()); - pipeline.mEarly.Delay.realizeLineOffset(mSampleBuffer.data()); - pipeline.mLate.VecAp.Delay.realizeLineOffset(mSampleBuffer.data()); - pipeline.mLate.Delay.realizeLineOffset(mSampleBuffer.data()); + pipeline.mLateDelayIn.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); + pipeline.mEarly.VecAp.Delay.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); + pipeline.mEarly.Delay.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); + pipeline.mLate.VecAp.Delay.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); + pipeline.mLate.Delay.realizeLineOffset(bufferspan.first(linelengths[oidx])); + bufferspan = bufferspan.subspan(linelengths[oidx++]); } + assert(oidx == linelengths.size()); } void ReverbState::deviceUpdate(const DeviceBase *device, const BufferStorage*) { - const auto frequency = static_cast(device->Frequency); + const auto frequency = static_cast(device->mSampleRate); /* Allocate the delay lines. */ allocLines(frequency); - for(auto &pipeline : mPipelines) - { - /* Clear filters and gain coefficients since the delay lines were all just - * cleared (if not reallocated). - */ - for(auto &filter : pipeline.mFilter) - { - filter.Lp.clear(); - filter.Hp.clear(); - } - - std::fill(std::begin(pipeline.mEarlyDelayCoeff),std::end(pipeline.mEarlyDelayCoeff), 0.0f); - std::fill(std::begin(pipeline.mEarlyDelayCoeff),std::end(pipeline.mEarlyDelayCoeff), 0.0f); - - pipeline.mLate.DensityGain = 0.0f; - for(auto &t60 : pipeline.mLate.T60) - { - t60.MidGain = 0.0f; - t60.HFFilter.clear(); - t60.LFFilter.clear(); - } - - pipeline.mLate.Mod.Index = 0; - pipeline.mLate.Mod.Step = 1; - pipeline.mLate.Mod.Depth = 0.0f; - - for(auto &gains : pipeline.mEarly.CurrentGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); - for(auto &gains : pipeline.mEarly.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); - for(auto &gains : pipeline.mLate.CurrentGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); - for(auto &gains : pipeline.mLate.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); - } + std::for_each(mPipelines.begin(), mPipelines.end(), std::mem_fn(&ReverbPipeline::clear)); mPipelineState = DeviceClear; /* Reset offset base. */ @@ -775,14 +811,14 @@ void ReverbState::deviceUpdate(const DeviceBase *device, const BufferStorage*) mUpmixOutput = false; mOrderScales.fill(1.0f); } - mPipelines[0].mAmbiSplitter[0][0].init(device->mXOverFreq / frequency); - for(auto &pipeline : mPipelines) + + auto splitter = BandSplitter{device->mXOverFreq / frequency}; + auto set_splitters = [&splitter](ReverbPipeline &pipeline) { - std::fill(pipeline.mAmbiSplitter[0].begin(), pipeline.mAmbiSplitter[0].end(), - pipeline.mAmbiSplitter[0][0]); - std::fill(pipeline.mAmbiSplitter[1].begin(), pipeline.mAmbiSplitter[1].end(), - pipeline.mAmbiSplitter[0][0]); - } + std::fill(pipeline.mAmbiSplitter[0].begin(), pipeline.mAmbiSplitter[0].end(), splitter); + std::fill(pipeline.mAmbiSplitter[1].begin(), pipeline.mAmbiSplitter[1].end(), splitter); + }; + std::for_each(mPipelines.begin(), mPipelines.end(), set_splitters); } /************************************** @@ -853,7 +889,7 @@ float CalcLimitedHfRatio(const float hfRatio, const float airAbsorptionGainHF, CalcDecayLength(airAbsorptionGainHF, decayTime)}; /* Using the limit calculated above, apply the upper bound to the HF ratio. */ - return minf(limitRatio, hfRatio); + return std::min(limitRatio, hfRatio); } @@ -890,10 +926,15 @@ void EarlyReflections::updateLines(const float density_mult, const float diffusi /* Calculate the delay length of each delay line. */ length = EARLY_LINE_LENGTHS[i] * density_mult; Offset[i] = float2uint(length * frequency); - - /* Calculate the gain (coefficient) for each line. */ - Coeff[i] = CalcDecayCoeff(length, decayTime); } + + /* Calculate the gain (coefficient) for the secondary reflections based on + * the average delay and decay time. + */ + const auto length = std::reduce(EARLY_LINE_LENGTHS.begin(), EARLY_LINE_LENGTHS.end(), 0.0f) + / float{EARLY_LINE_LENGTHS.size()} * density_mult; + Coeff = CalcDecayCoeff(length, decayTime); + } /* Update the EAX modulation step and depth. Keep in mind that this kind of @@ -909,7 +950,7 @@ void Modulation::updateModulator(float modTime, float modDepth, float frequency) * appropriate step size to generate an LFO, which will vary the feedback * delay over time. */ - Step = maxu(fastf2u(MOD_FRACONE / (frequency * modTime)), 1); + Step = std::max(fastf2u(MOD_FRACONE / (frequency * modTime)), 1u); /* The modulation depth effects the amount of frequency change over the * range of the sinus. It needs to be scaled by the modulation time so that @@ -982,7 +1023,7 @@ void LateReverb::updateLines(const float density_mult, const float diffusion, * includes one sample of delay. Reduce by one to compensate. */ length = LATE_LINE_LENGTHS[i] * density_mult; - Offset[i] = maxu(float2uint(length*frequency + 0.5f), 1u) - 1u; + Offset[i] = std::max(float2uint(length*frequency + 0.5f), 1u) - 1u; /* Approximate the absorption that the vector all-pass would exhibit * given the current diffusion so we don't have to process a full T60 @@ -999,8 +1040,8 @@ void LateReverb::updateLines(const float density_mult, const float diffusion, /* Update the offsets for the main effect delay line. */ -void ReverbPipeline::updateDelayLine(const float earlyDelay, const float lateDelay, - const float density_mult, const float decayTime, const float frequency) +void ReverbPipeline::updateDelayLine(const float gain, const float earlyDelay, + const float lateDelay, const float density_mult, const float frequency) { /* Early reflection taps are decorrelated by means of an average room * reflection approximation described above the definition of the taps. @@ -1012,12 +1053,16 @@ void ReverbPipeline::updateDelayLine(const float earlyDelay, const float lateDel * delay path and offsets that would continue the propagation naturally * into the late lines. */ + mEarlyDelayCoeff[1] = gain; for(size_t i{0u};i < NUM_LINES;i++) { float length{EARLY_TAP_LENGTHS[i]*density_mult}; mEarlyDelayTap[i][1] = float2uint((earlyDelay+length) * frequency); - mEarlyDelayCoeff[i] = CalcDecayCoeff(length, decayTime); + /* Reduce the late delay tap by the shortest early delay line length to + * compensate for the late line input being fed by the delayed early + * output. + */ length = (LATE_LINE_LENGTHS[i] - LATE_LINE_LENGTHS.front())/float{NUM_LINES}*density_mult + lateDelay; mLateDelayTap[i][1] = float2uint(length * frequency); @@ -1038,14 +1083,14 @@ std::array,4> GetTransformFromVector(const al::span norm{{vec[0], vec[1], vec[2]}}; float mag{std::sqrt(vec[0]*vec[0] + vec[1]*vec[1] + vec[2]*vec[2])}; if(mag > 1.0f) { const float scale{al::numbers::sqrt3_v / mag}; - norm[0] = vec[0] * -scale; - norm[1] = vec[1] * scale; - norm[2] = vec[2] * scale; + norm[0] *= -scale; + norm[1] *= scale; + norm[2] *= scale; mag = 1.0f; } else @@ -1054,9 +1099,9 @@ std::array,4> GetTransformFromVector(const al::span; - norm[1] = vec[1] * al::numbers::sqrt3_v; - norm[2] = vec[2] * al::numbers::sqrt3_v; + norm[0] *= -al::numbers::sqrt3_v; + norm[1] *= al::numbers::sqrt3_v; + norm[2] *= al::numbers::sqrt3_v; } return std::array,4>{{ @@ -1075,45 +1120,41 @@ void ReverbPipeline::update3DPanning(const al::span ReflectionsPa /* Create matrices that transform a B-Format signal according to the * panning vectors. */ - const std::array,4> earlymat{GetTransformFromVector(ReflectionsPan)}; - const std::array,4> latemat{GetTransformFromVector(LateReverbPan)}; + const auto earlymat = GetTransformFromVector(ReflectionsPan); + const auto latemat = GetTransformFromVector(LateReverbPan); - if(doUpmix) + const auto get_coeffs = [&] { - /* When upsampling, combine the early and late transforms with the - * first-order upsample matrix. This results in panning gains that - * apply the panning transform to first-order B-Format, which is then - * upsampled. - */ - auto mult_matrix = [](const al::span,4> mtx1) + if(doUpmix) { - auto&& mtx2 = AmbiScale::FirstOrderUp; - std::array,NUM_LINES> res{}; - - for(size_t i{0};i < mtx1[0].size();++i) + /* When upsampling, combine the early and late transforms with the + * first-order upsample matrix. This results in panning gains that + * apply the panning transform to first-order B-Format, which is + * then upsampled. + */ + auto mult_matrix = [](const al::span,4> mtx1) { - float *RESTRICT dst{res[i].data()}; - for(size_t k{0};k < mtx1.size();++k) + std::array,NUM_LINES> res{}; + const auto mtx2 = al::span{AmbiScale::FirstOrderUp}; + + for(size_t i{0};i < mtx1[0].size();++i) { - const float *RESTRICT src{mtx2[k].data()}; - const float a{mtx1[k][i]}; - for(size_t j{0};j < mtx2[0].size();++j) - dst[j] += a * src[j]; + const al::span dst{res[i]}; + static_assert(dst.size() >= std::tuple_size_v); + for(size_t k{0};k < mtx1.size();++k) + { + const float a{mtx1[k][i]}; + std::transform(mtx2[k].begin(), mtx2[k].end(), dst.begin(), dst.begin(), + [a](const float in, const float out) noexcept -> float + { return a*in + out; }); + } } - } - return res; - }; - auto earlycoeffs = mult_matrix(earlymat); - auto latecoeffs = mult_matrix(latemat); + return res; + }; + return std::array{mult_matrix(earlymat), mult_matrix(latemat)}; + } - for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]); - for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]); - } - else - { /* When not upsampling, combine the early and late A-to-B-Format * conversions with their respective transform. This results panning * gains that convert A-Format to B-Format, which is then panned. @@ -1125,158 +1166,154 @@ void ReverbPipeline::update3DPanning(const al::span ReflectionsPa for(size_t i{0};i < mtx1[0].size();++i) { - float *RESTRICT dst{res[i].data()}; + const al::span dst{res[i]}; + static_assert(dst.size() >= std::tuple_size_v); for(size_t k{0};k < mtx1.size();++k) { const float a{mtx1[k][i]}; - for(size_t j{0};j < mtx2.size();++j) - dst[j] += a * mtx2[j][k]; + std::transform(mtx2[k].begin(), mtx2[k].end(), dst.begin(), dst.begin(), + [a](const float in, const float out) noexcept -> float + { return a*in + out; }); } } return res; }; - auto earlycoeffs = mult_matrix(EarlyA2B, earlymat); - auto latecoeffs = mult_matrix(LateA2B, latemat); - - for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, earlycoeffs[i].data(), earlyGain, mEarly.TargetGains[i]); - for(size_t i{0u};i < NUM_LINES;i++) - ComputePanGains(mainMix, latecoeffs[i].data(), lateGain, mLate.TargetGains[i]); - } + return std::array{mult_matrix(EarlyA2B, earlymat), mult_matrix(LateA2B, latemat)}; + }; + const auto [earlycoeffs, latecoeffs] = get_coeffs(); + + auto earlygains = mEarly.Gains.begin(); + for(auto &coeffs : earlycoeffs) + ComputePanGains(mainMix, coeffs, earlyGain, (earlygains++)->Target); + auto lategains = mLate.Gains.begin(); + for(auto &coeffs : latecoeffs) + ComputePanGains(mainMix, coeffs, lateGain, (lategains++)->Target); } void ReverbState::update(const ContextBase *Context, const EffectSlot *Slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *Device{Context->mDevice}; - const auto frequency = static_cast(Device->Frequency); + const auto frequency = static_cast(Device->mSampleRate); /* If the HF limit parameter is flagged, calculate an appropriate limit * based on the air absorption parameter. */ - float hfRatio{props->Reverb.DecayHFRatio}; - if(props->Reverb.DecayHFLimit && props->Reverb.AirAbsorptionGainHF < 1.0f) - hfRatio = CalcLimitedHfRatio(hfRatio, props->Reverb.AirAbsorptionGainHF, - props->Reverb.DecayTime); + float hfRatio{props.DecayHFRatio}; + if(props.DecayHFLimit && props.AirAbsorptionGainHF < 1.0f) + hfRatio = CalcLimitedHfRatio(hfRatio, props.AirAbsorptionGainHF, props.DecayTime); /* Calculate the LF/HF decay times. */ constexpr float MinDecayTime{0.1f}, MaxDecayTime{20.0f}; - const float lfDecayTime{clampf(props->Reverb.DecayTime*props->Reverb.DecayLFRatio, - MinDecayTime, MaxDecayTime)}; - const float hfDecayTime{clampf(props->Reverb.DecayTime*hfRatio, MinDecayTime, MaxDecayTime)}; + const float lfDecayTime{std::clamp(props.DecayTime*props.DecayLFRatio, MinDecayTime, + MaxDecayTime)}; + const float hfDecayTime{std::clamp(props.DecayTime*hfRatio, MinDecayTime, MaxDecayTime)}; /* Determine if a full update is required. */ const bool fullUpdate{mPipelineState == DeviceClear || /* Density is essentially a master control for the feedback delays, so * changes the offsets of many delay lines. */ - mParams.Density != props->Reverb.Density || + mParams.Density != props.Density || /* Diffusion and decay times influences the decay rate (gain) of the * late reverb T60 filter. */ - mParams.Diffusion != props->Reverb.Diffusion || - mParams.DecayTime != props->Reverb.DecayTime || + mParams.Diffusion != props.Diffusion || + mParams.DecayTime != props.DecayTime || mParams.HFDecayTime != hfDecayTime || mParams.LFDecayTime != lfDecayTime || /* Modulation time and depth both require fading the modulation delay. */ - mParams.ModulationTime != props->Reverb.ModulationTime || - mParams.ModulationDepth != props->Reverb.ModulationDepth || + mParams.ModulationTime != props.ModulationTime || + mParams.ModulationDepth != props.ModulationDepth || /* HF/LF References control the weighting used to calculate the density * gain. */ - mParams.HFReference != props->Reverb.HFReference || - mParams.LFReference != props->Reverb.LFReference}; + mParams.HFReference != props.HFReference || + mParams.LFReference != props.LFReference}; if(fullUpdate) { - mParams.Density = props->Reverb.Density; - mParams.Diffusion = props->Reverb.Diffusion; - mParams.DecayTime = props->Reverb.DecayTime; + mParams.Density = props.Density; + mParams.Diffusion = props.Diffusion; + mParams.DecayTime = props.DecayTime; mParams.HFDecayTime = hfDecayTime; mParams.LFDecayTime = lfDecayTime; - mParams.ModulationTime = props->Reverb.ModulationTime; - mParams.ModulationDepth = props->Reverb.ModulationDepth; - mParams.HFReference = props->Reverb.HFReference; - mParams.LFReference = props->Reverb.LFReference; + mParams.ModulationTime = props.ModulationTime; + mParams.ModulationDepth = props.ModulationDepth; + mParams.HFReference = props.HFReference; + mParams.LFReference = props.LFReference; mPipelineState = (mPipelineState != DeviceClear) ? StartFade : Normal; - mCurrentPipeline ^= 1; + mCurrentPipeline = !mCurrentPipeline; + + auto &oldpipeline = mPipelines[!mCurrentPipeline]; + oldpipeline.mEarlyDelayCoeff[1] = 0.0f; } auto &pipeline = mPipelines[mCurrentPipeline]; + /* The density-based room size (delay length) multiplier. */ + const float density_mult{CalcDelayLengthMult(props.Density)}; + + /* Update the main effect delay and associated taps. */ + pipeline.updateDelayLine(props.Gain, props.ReflectionsDelay, props.LateReverbDelay, + density_mult, frequency); + /* Update early and late 3D panning. */ mOutTarget = target.Main->Buffer; - const float gain{props->Reverb.Gain * Slot->Gain * ReverbBoost}; - pipeline.update3DPanning(props->Reverb.ReflectionsPan, props->Reverb.LateReverbPan, - props->Reverb.ReflectionsGain*gain, props->Reverb.LateReverbGain*gain, mUpmixOutput, - target.Main); + const float gain{Slot->Gain * ReverbBoost}; + pipeline.update3DPanning(props.ReflectionsPan, props.LateReverbPan, props.ReflectionsGain*gain, + props.LateReverbGain*gain, mUpmixOutput, target.Main); /* Calculate the master filters */ - float hf0norm{minf(props->Reverb.HFReference/frequency, 0.49f)}; - pipeline.mFilter[0].Lp.setParamsFromSlope(BiquadType::HighShelf, hf0norm, props->Reverb.GainHF, 1.0f); - float lf0norm{minf(props->Reverb.LFReference/frequency, 0.49f)}; - pipeline.mFilter[0].Hp.setParamsFromSlope(BiquadType::LowShelf, lf0norm, props->Reverb.GainLF, 1.0f); + float hf0norm{std::min(props.HFReference/frequency, 0.49f)}; + pipeline.mFilter[0].Lp.setParamsFromSlope(BiquadType::HighShelf, hf0norm, props.GainHF, 1.0f); + float lf0norm{std::min(props.LFReference/frequency, 0.49f)}; + pipeline.mFilter[0].Hp.setParamsFromSlope(BiquadType::LowShelf, lf0norm, props.GainLF, 1.0f); for(size_t i{1u};i < NUM_LINES;i++) { pipeline.mFilter[i].Lp.copyParamsFrom(pipeline.mFilter[0].Lp); pipeline.mFilter[i].Hp.copyParamsFrom(pipeline.mFilter[0].Hp); } - /* The density-based room size (delay length) multiplier. */ - const float density_mult{CalcDelayLengthMult(props->Reverb.Density)}; - - /* Update the main effect delay and associated taps. */ - pipeline.updateDelayLine(props->Reverb.ReflectionsDelay, props->Reverb.LateReverbDelay, - density_mult, props->Reverb.DecayTime, frequency); - if(fullUpdate) { /* Update the early lines. */ - pipeline.mEarly.updateLines(density_mult, props->Reverb.Diffusion, props->Reverb.DecayTime, - frequency); + pipeline.mEarly.updateLines(density_mult, props.Diffusion, props.DecayTime, frequency); /* Get the mixing matrix coefficients. */ - CalcMatrixCoeffs(props->Reverb.Diffusion, &pipeline.mMixX, &pipeline.mMixY); + CalcMatrixCoeffs(props.Diffusion, &pipeline.mMixX, &pipeline.mMixY); /* Update the modulator rate and depth. */ - pipeline.mLate.Mod.updateModulator(props->Reverb.ModulationTime, - props->Reverb.ModulationDepth, frequency); + pipeline.mLate.Mod.updateModulator(props.ModulationTime, props.ModulationDepth, frequency); /* Update the late lines. */ - pipeline.mLate.updateLines(density_mult, props->Reverb.Diffusion, lfDecayTime, - props->Reverb.DecayTime, hfDecayTime, lf0norm, hf0norm, frequency); + pipeline.mLate.updateLines(density_mult, props.Diffusion, lfDecayTime, props.DecayTime, + hfDecayTime, lf0norm, hf0norm, frequency); } /* Calculate the gain at the start of the late reverb stage, and the gain * difference from the decay target (0.001, or -60dB). */ - const float decayBase{props->Reverb.ReflectionsGain * props->Reverb.LateReverbGain}; + const float decayBase{props.ReflectionsGain * props.LateReverbGain}; const float decayDiff{ReverbDecayGain / decayBase}; - if(decayDiff < 1.0f) - { - /* Given the DecayTime (the amount of time for the late reverb to decay - * by -60dB), calculate the time to decay to -60dB from the start of - * the late reverb. - */ - const float diffTime{std::log10(decayDiff)*(20.0f / -60.0f) * props->Reverb.DecayTime}; + /* Given the DecayTime (the amount of time for the late reverb to decay by + * -60dB), calculate the time to decay to -60dB from the start of the late + * reverb. + * + * Otherwise, if the late reverb already starts at -60dB or less, only + * include the time to get to the late reverb. + */ + const float diffTime{!(decayDiff < 1.0f) ? 0.0f + : (std::log10(decayDiff)*(20.0f / -60.0f) * props.DecayTime)}; - const float decaySamples{(props->Reverb.ReflectionsDelay + props->Reverb.LateReverbDelay - + diffTime) * frequency}; - /* Limit to 100,000 samples (a touch over 2 seconds at 48khz) to - * avoid excessive double-processing. - */ - pipeline.mFadeSampleCount = static_cast(minf(decaySamples, 100'000.0f)); - } - else - { - /* Otherwise, if the late reverb already starts at -60dB or less, only - * include the time to get to the late reverb. - */ - const float decaySamples{(props->Reverb.ReflectionsDelay + props->Reverb.LateReverbDelay) - * frequency}; - pipeline.mFadeSampleCount = static_cast(minf(decaySamples, 100'000.0f)); - } + const float decaySamples{(props.ReflectionsDelay+props.LateReverbDelay+diffTime) + * frequency}; + /* Limit to 100,000 samples (a touch over 2 seconds at 48khz) to avoid + * excessive double-processing. + */ + pipeline.mFadeSampleCount = static_cast(std::min(decaySamples, 100'000.0f)); } @@ -1322,35 +1359,34 @@ void ReverbState::update(const ContextBase *Context, const EffectSlot *Slot, * Where D is a diagonal matrix (of x), and S is a triangular matrix (of y) * whose combination of signs are being iterated. */ -inline auto VectorPartialScatter(const std::array &RESTRICT in, - const float xCoeff, const float yCoeff) -> std::array +inline auto VectorPartialScatter(const std::array &in, const float xCoeff, + const float yCoeff) noexcept -> std::array { - return std::array{{ + return std::array{ xCoeff*in[0] + yCoeff*( in[1] + -in[2] + in[3]), xCoeff*in[1] + yCoeff*(-in[0] + in[2] + in[3]), xCoeff*in[2] + yCoeff*( in[0] + -in[1] + in[3]), xCoeff*in[3] + yCoeff*(-in[0] + -in[1] + -in[2] ) - }}; + }; } -/* Utilizes the above, but reverses the input channels. */ -void VectorScatterRevDelayIn(const DelayLineI delay, size_t offset, const float xCoeff, - const float yCoeff, const al::span in, const size_t count) +/* Utilizes the above, but also applies a line-based reflection on the input + * channels (swapping 0<->3 and 1<->2). + */ +void VectorScatterRev(const float xCoeff, const float yCoeff, + const al::span samples, const size_t count) noexcept { ASSUME(count > 0); - for(size_t i{0u};i < count;) + for(size_t i{0u};i < count;++i) { - offset &= delay.Mask; - size_t td{minz(delay.Mask+1 - offset, count-i)}; - do { - std::array f; - for(size_t j{0u};j < NUM_LINES;j++) - f[NUM_LINES-1-j] = in[j][i]; - ++i; + std::array src{samples[0][i], samples[1][i], samples[2][i], samples[3][i]}; - delay.Line[offset++] = VectorPartialScatter(f, xCoeff, yCoeff); - } while(--td); + src = VectorPartialScatter(std::array{src[3], src[2], src[1], src[0]}, xCoeff, yCoeff); + samples[0][i] = src[0]; + samples[1][i] = src[1]; + samples[2][i] = src[2]; + samples[3][i] = src[3]; } } @@ -1360,167 +1396,229 @@ void VectorScatterRevDelayIn(const DelayLineI delay, size_t offset, const float * It works by vectorizing a regular all-pass filter and replacing the delay * element with a scattering matrix (like the one above) and a diagonal * matrix of delay elements. - * - * Two static specializations are used for transitional (cross-faded) delay - * line processing and non-transitional processing. */ -void VecAllpass::process(const al::span samples, size_t offset, - const float xCoeff, const float yCoeff, const size_t todo) +void VecAllpass::process(const al::span samples, size_t main_offset, + const float xCoeff, const float yCoeff, const size_t todo) const noexcept { - const DelayLineI delay{Delay}; + const auto linelen = size_t{Delay.mLine.size()/NUM_LINES}; const float feedCoeff{Coeff}; ASSUME(todo > 0); - size_t vap_offset[NUM_LINES]; - for(size_t j{0u};j < NUM_LINES;j++) - vap_offset[j] = offset - Offset[j]; for(size_t i{0u};i < todo;) { - for(size_t j{0u};j < NUM_LINES;j++) - vap_offset[j] &= delay.Mask; - offset &= delay.Mask; + std::array vap_offset{}; + std::transform(Offset.cbegin(), Offset.cend(), vap_offset.begin(), + [main_offset,mask=linelen-1](const size_t delay) noexcept -> size_t + { return (main_offset-delay) & mask; }); + main_offset &= linelen-1; + + const auto maxoff = std::accumulate(vap_offset.cbegin(), vap_offset.cend(), main_offset, + [](const size_t offset, const size_t apoffset) { return std::max(offset, apoffset); }); + size_t td{std::min(linelen - maxoff, todo - i)}; - size_t maxoff{offset}; - for(size_t j{0u};j < NUM_LINES;j++) - maxoff = maxz(maxoff, vap_offset[j]); - size_t td{minz(delay.Mask+1 - maxoff, todo - i)}; + auto delayIn = Delay.mLine.begin(); + auto delayOut = Delay.mLine.begin() + ptrdiff_t(main_offset*NUM_LINES); + main_offset += td; do { - std::array f; + std::array f{}; for(size_t j{0u};j < NUM_LINES;j++) { const float input{samples[j][i]}; - const float out{delay.Line[vap_offset[j]++][j] - feedCoeff*input}; + const float out{delayIn[vap_offset[j]*NUM_LINES + j] - feedCoeff*input}; f[j] = input + feedCoeff*out; samples[j][i] = out; } + delayIn += NUM_LINES; ++i; - delay.Line[offset++] = VectorPartialScatter(f, xCoeff, yCoeff); + f = VectorPartialScatter(f, xCoeff, yCoeff); + delayOut = std::copy_n(f.cbegin(), f.size(), delayOut); } while(--td); } } +/* This applies a more typical all-pass to each line, without the scattering + * matrix. + */ +void Allpass4::process(const al::span samples, const size_t offset, + const size_t todo) const noexcept +{ + const DelayLineU delay{Delay}; + const float feedCoeff{Coeff}; + + ASSUME(todo > 0); + + for(size_t j{0u};j < NUM_LINES;j++) + { + auto smpiter = samples[j].begin(); + const auto buffer = delay.get(j); + size_t dstoffset{offset}; + size_t vap_offset{offset - Offset[j]}; + for(size_t i{0u};i < todo;) + { + vap_offset &= buffer.size()-1; + dstoffset &= buffer.size()-1; + + const size_t maxoff{std::max(dstoffset, vap_offset)}; + const size_t td{std::min(buffer.size() - maxoff, todo - i)}; + + auto proc_sample = [buffer,feedCoeff,&vap_offset,&dstoffset](const float x) -> float + { + const float y{buffer[vap_offset++] - feedCoeff*x}; + buffer[dstoffset++] = x + feedCoeff*y; + return y; + }; + smpiter = std::transform(smpiter, smpiter+td, smpiter, proc_sample); + i += td; + } + } +} + + /* This generates early reflections. * * This is done by obtaining the primary reflections (those arriving from the * same direction as the source) from the main delay line. These are * attenuated and all-pass filtered (based on the diffusion parameter). * - * The early lines are then fed in reverse (according to the approximately - * opposite spatial location of the A-Format lines) to create the secondary + * The early lines are then reflected about the origin to create the secondary * reflections (those arriving from the opposite direction as the source). * * The early response is then completed by combining the primary reflections * with the delayed and attenuated output from the early lines. * - * Finally, the early response is reversed, scattered (based on diffusion), + * Finally, the early response is reflected, scattered (based on diffusion), * and fed into the late reverb section of the main delay line. */ -void ReverbPipeline::processEarly(size_t offset, const size_t samplesToDo, - const al::span tempSamples, +void ReverbPipeline::processEarly(const DelayLineU &main_delay, size_t offset, + const size_t samplesToDo, const al::span tempSamples, const al::span outSamples) { - const DelayLineI early_delay{mEarly.Delay}; - const DelayLineI in_delay{mEarlyDelayIn}; + const DelayLineU early_delay{mEarly.Delay}; + const DelayLineU in_delay{main_delay}; const float mixX{mMixX}; const float mixY{mMixY}; - ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); for(size_t base{0};base < samplesToDo;) { - const size_t todo{minz(samplesToDo-base, MAX_UPDATE_SAMPLES)}; + const size_t todo{std::min(samplesToDo-base, MAX_UPDATE_SAMPLES)}; /* First, load decorrelated samples from the main delay line as the * primary reflections. */ - const float fadeStep{1.0f / static_cast(todo)}; - for(size_t j{0u};j < NUM_LINES;j++) + const auto fadeStep = 1.0f / static_cast(todo); + const auto earlycoeff0 = float{mEarlyDelayCoeff[0]}; + const auto earlycoeff1 = float{mEarlyDelayCoeff[1]}; + mEarlyDelayCoeff[0] = mEarlyDelayCoeff[1]; + for(size_t j{0_uz};j < NUM_LINES;j++) { - size_t early_delay_tap0{offset - mEarlyDelayTap[j][0]}; - size_t early_delay_tap1{offset - mEarlyDelayTap[j][1]}; - const float coeff{mEarlyDelayCoeff[j]}; - const float coeffStep{early_delay_tap0 != early_delay_tap1 ? coeff*fadeStep : 0.0f}; - float fadeCount{0.0f}; + const auto input = in_delay.get(j); + auto early_delay_tap0 = size_t{offset - mEarlyDelayTap[j][0]}; + auto early_delay_tap1 = size_t{offset - mEarlyDelayTap[j][1]}; + mEarlyDelayTap[j][0] = mEarlyDelayTap[j][1]; + auto fadeCount = 0.0f; - for(size_t i{0u};i < todo;) + auto tmp = tempSamples[j].begin(); + for(size_t i{0_uz};i < todo;) { - early_delay_tap0 &= in_delay.Mask; - early_delay_tap1 &= in_delay.Mask; - const size_t max_tap{maxz(early_delay_tap0, early_delay_tap1)}; - size_t td{minz(in_delay.Mask+1 - max_tap, todo-i)}; - do { - const float fade0{coeff - coeffStep*fadeCount}; - const float fade1{coeffStep*fadeCount}; + early_delay_tap0 &= input.size()-1; + early_delay_tap1 &= input.size()-1; + const auto max_tap = size_t{std::max(early_delay_tap0, early_delay_tap1)}; + const auto td = size_t{std::min(input.size()-max_tap, todo-i)}; + const auto intap0 = input.subspan(early_delay_tap0, td); + const auto intap1 = input.subspan(early_delay_tap1, td); + + auto do_blend = [earlycoeff0,earlycoeff1,fadeStep,&fadeCount](const float in0, + const float in1) noexcept -> float + { + const auto ret = lerpf(in0*earlycoeff0, in1*earlycoeff1, fadeStep*fadeCount); fadeCount += 1.0f; - tempSamples[j][i++] = in_delay.Line[early_delay_tap0++][j]*fade0 + - in_delay.Line[early_delay_tap1++][j]*fade1; - } while(--td); + return ret; + }; + tmp = std::transform(intap0.begin(), intap0.end(), intap1.begin(), tmp, do_blend); + early_delay_tap0 += td; + early_delay_tap1 += td; + i += td; } - mEarlyDelayTap[j][0] = mEarlyDelayTap[j][1]; + /* Band-pass the incoming samples. */ + auto&& filter = DualBiquad{mFilter[j].Lp, mFilter[j].Hp}; + filter.process(al::span{tempSamples[j]}.first(todo), tempSamples[j]); } - /* Apply a vector all-pass, to help color the initial reflections based - * on the diffusion strength. - */ - mEarly.VecAp.process(tempSamples, offset, mixX, mixY, todo); + /* Apply an all-pass, to help color the initial reflections. */ + mEarly.VecAp.process(tempSamples, offset, todo); - /* Apply a delay and bounce to generate secondary reflections, combine - * with the primary reflections and write out the result for mixing. - */ - for(size_t j{0u};j < NUM_LINES;j++) - early_delay.write(offset, NUM_LINES-1-j, tempSamples[j].data(), todo); - for(size_t j{0u};j < NUM_LINES;j++) + /* Apply a delay and bounce to generate secondary reflections. */ + early_delay.writeReflected(offset, tempSamples, todo); + const auto feedb_coeff = mEarly.Coeff; + for(size_t j{0_uz};j < NUM_LINES;j++) { - size_t feedb_tap{offset - mEarly.Offset[j]}; - const float feedb_coeff{mEarly.Coeff[j]}; - float *RESTRICT out{al::assume_aligned<16>(outSamples[j].data() + base)}; + const auto input = early_delay.get(j); + auto feedb_tap = size_t{offset - mEarly.Offset[j]}; + auto out = outSamples[j].begin() + base; + auto tmp = tempSamples[j].begin(); - for(size_t i{0u};i < todo;) + for(size_t i{0_uz};i < todo;) { - feedb_tap &= early_delay.Mask; - size_t td{minz(early_delay.Mask+1 - feedb_tap, todo - i)}; - do { - tempSamples[j][i] += early_delay.Line[feedb_tap++][j]*feedb_coeff; - out[i] = tempSamples[j][i]; - ++i; - } while(--td); + feedb_tap &= input.size()-1; + + const auto td = size_t{std::min(input.size() - feedb_tap, todo - i)}; + const auto delaySrc = input.subspan(feedb_tap, td); + + /* Combine the main input with the attenuated delayed echo for + * the early output. + */ + out = std::transform(delaySrc.begin(), delaySrc.end(), tmp, out, + [feedb_coeff](const float delayspl, const float mainspl) noexcept -> float + { return delayspl*feedb_coeff + mainspl; }); + + /* Move the (non-attenuated) delayed echo to the temp buffer + * for feeding the late reverb. + */ + tmp = std::copy_n(delaySrc.begin(), delaySrc.size(), tmp); + feedb_tap += td; + i += td; } } - /* Finally, write the result to the late delay line input for the late - * reverb stage to pick up at the appropriate time, applying a scatter - * and bounce to improve the initial diffusion in the late reverb. + /* Finally, apply a scatter and bounce to improve the initial diffusion + * in the late reverb, writing the result to the late delay line input. */ - VectorScatterRevDelayIn(mLateDelayIn, offset, mixX, mixY, tempSamples, todo); + VectorScatterRev(mixX, mixY, tempSamples, todo); + for(size_t j{0_uz};j < NUM_LINES;j++) + mLateDelayIn.write(offset, j, al::span{tempSamples[j]}.first(todo)); base += todo; offset += todo; } } -void Modulation::calcDelays(size_t todo) +auto Modulation::calcDelays(size_t todo) -> al::span { - uint idx{Index}; - const uint step{Step}; - const float depth{Depth}; - for(size_t i{0};i < todo;++i) + auto idx = Index; + const auto step = Step; + const auto depth = Depth * float{gCubicTable.sTableSteps}; + const auto delays = al::span{ModDelays}.first(todo); + std::generate(delays.begin(), delays.end(), [step,depth,&idx] { idx += step; - const float x{static_cast(idx&MOD_FRACMASK) * (1.0f/MOD_FRACONE)}; + const auto x = static_cast(idx&MOD_FRACMASK) * (1.0f/MOD_FRACONE); /* Approximate sin(x*2pi). As long as it roughly fits a sinusoid shape * and stays within [-1...+1], it needn't be perfect. */ - const float lfo{!(idx&(MOD_FRACONE>>1)) + const auto lfo = !(idx&(MOD_FRACONE>>1)) ? ((-16.0f * x * x) + (8.0f * x)) - : ((16.0f * x * x) + (-8.0f * x) + (-16.0f * x) + 8.0f)}; - ModDelays[i] = (lfo+1.0f) * depth; - } + : ((16.0f * x * x) + (-8.0f * x) + (-16.0f * x) + 8.0f); + return float2uint((lfo+1.0f) * depth); + }); Index = idx; + return delays; } @@ -1539,88 +1637,105 @@ void ReverbPipeline::processLate(size_t offset, const size_t samplesToDo, const al::span tempSamples, const al::span outSamples) { - const DelayLineI late_delay{mLate.Delay}; - const DelayLineI in_delay{mLateDelayIn}; + const DelayLineU late_delay{mLate.Delay}; + const DelayLineU in_delay{mLateDelayIn}; const float mixX{mMixX}; const float mixY{mMixY}; - ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); for(size_t base{0};base < samplesToDo;) { - const size_t todo{minz(samplesToDo-base, minz(mLate.Offset[0], MAX_UPDATE_SAMPLES))}; + const size_t todo{std::min(std::min(mLate.Offset[0], MAX_UPDATE_SAMPLES), + samplesToDo-base)}; ASSUME(todo > 0); /* First, calculate the modulated delays for the late feedback. */ - mLate.Mod.calcDelays(todo); + const auto delays = mLate.Mod.calcDelays(todo); - /* Next, load decorrelated samples from the main and feedback delay - * lines. Filter the signal to apply its frequency-dependent decay. + /* Now load samples from the feedback delay lines. Filter the signal to + * apply its frequency-dependent decay. */ + for(size_t j{0_uz};j < NUM_LINES;++j) + { + const auto input = late_delay.get(j); + const auto midGain = mLate.T60[j].MidGain; + auto late_feedb_tap = size_t{offset - mLate.Offset[j]}; + + auto proc_sample = [input,midGain,&late_feedb_tap](const size_t idelay) -> float + { + /* Calculate the read sample offset and sub-sample offset + * between it and the next sample. + */ + const auto delay = late_feedb_tap - (idelay>>gCubicTable.sTableBits); + const auto delayoffset = size_t{idelay & gCubicTable.sTableMask}; + ++late_feedb_tap; + + /* Get the samples around the delayed offset, interpolated for + * output. + */ + const auto out0 = float{input[(delay ) & (input.size()-1)]}; + const auto out1 = float{input[(delay-1) & (input.size()-1)]}; + const auto out2 = float{input[(delay-2) & (input.size()-1)]}; + const auto out3 = float{input[(delay-3) & (input.size()-1)]}; + + const auto out = out0*gCubicTable.getCoeff0(delayoffset) + + out1*gCubicTable.getCoeff1(delayoffset) + + out2*gCubicTable.getCoeff2(delayoffset) + + out3*gCubicTable.getCoeff3(delayoffset); + return out * midGain; + }; + std::transform(delays.begin(), delays.end(), tempSamples[j].begin(), proc_sample); + + mLate.T60[j].process(al::span{tempSamples[j]}.first(todo)); + } + + /* Next load decorrelated samples from the main delay lines. */ const float fadeStep{1.0f / static_cast(todo)}; - for(size_t j{0u};j < NUM_LINES;j++) + for(size_t j{0_uz};j < NUM_LINES;++j) { - size_t late_delay_tap0{offset - mLateDelayTap[j][0]}; - size_t late_delay_tap1{offset - mLateDelayTap[j][1]}; - size_t late_feedb_tap{offset - mLate.Offset[j]}; - const float midGain{mLate.T60[j].MidGain}; - const float densityGain{mLate.DensityGain * midGain}; - const float densityStep{late_delay_tap0 != late_delay_tap1 ? - densityGain*fadeStep : 0.0f}; - float fadeCount{0.0f}; + const auto input = in_delay.get(j); + auto late_delay_tap0 = size_t{offset - mLateDelayTap[j][0]}; + auto late_delay_tap1 = size_t{offset - mLateDelayTap[j][1]}; + mLateDelayTap[j][0] = mLateDelayTap[j][1]; + const auto densityGain = mLate.DensityGain; + const auto densityStep = late_delay_tap0 != late_delay_tap1 + ? densityGain*fadeStep : 0.0f; + auto fadeCount = 0.0f; + auto samples = tempSamples[j].begin(); for(size_t i{0u};i < todo;) { - late_delay_tap0 &= in_delay.Mask; - late_delay_tap1 &= in_delay.Mask; - size_t td{minz(todo-i, in_delay.Mask+1 - maxz(late_delay_tap0, late_delay_tap1))}; - do { - /* Calculate the read offset and offset between it and the - * next sample. - */ - const float fdelay{mLate.Mod.ModDelays[i]}; - const size_t idelay{float2uint(fdelay * float{gCubicTable.sTableSteps})}; - const size_t delay{late_feedb_tap - (idelay>>gCubicTable.sTableBits)}; - const size_t delayoffset{idelay & gCubicTable.sTableMask}; - ++late_feedb_tap; - - /* Get the samples around by the delayed offset. */ - const float out0{late_delay.Line[(delay ) & late_delay.Mask][j]}; - const float out1{late_delay.Line[(delay-1) & late_delay.Mask][j]}; - const float out2{late_delay.Line[(delay-2) & late_delay.Mask][j]}; - const float out3{late_delay.Line[(delay-3) & late_delay.Mask][j]}; - - /* The output is obtained by interpolating the four samples - * that were acquired above, and combined with the main - * delay tap. - */ - const float out{out0*gCubicTable.getCoeff0(delayoffset) - + out1*gCubicTable.getCoeff1(delayoffset) - + out2*gCubicTable.getCoeff2(delayoffset) - + out3*gCubicTable.getCoeff3(delayoffset)}; - const float fade0{densityGain - densityStep*fadeCount}; - const float fade1{densityStep*fadeCount}; + late_delay_tap0 &= input.size()-1; + late_delay_tap1 &= input.size()-1; + const auto td = size_t{std::min(todo - i, + input.size() - std::max(late_delay_tap0, late_delay_tap1))}; + + auto proc_sample = [input,densityGain,densityStep,&late_delay_tap0, + &late_delay_tap1,&fadeCount](const float sample) noexcept -> float + { + const auto fade0 = float{densityGain - densityStep*fadeCount}; + const auto fade1 = float{densityStep*fadeCount}; fadeCount += 1.0f; - tempSamples[j][i] = out*midGain + - in_delay.Line[late_delay_tap0++][j]*fade0 + - in_delay.Line[late_delay_tap1++][j]*fade1; - ++i; - } while(--td); + return input[late_delay_tap0++]*fade0 + input[late_delay_tap1++]*fade1 + + sample; + }; + samples = std::transform(samples, samples+ptrdiff_t(td), samples, proc_sample); + i += td; } - mLateDelayTap[j][0] = mLateDelayTap[j][1]; - - mLate.T60[j].process({tempSamples[j].data(), todo}); } /* Apply a vector all-pass to improve micro-surface diffusion, and * write out the results for mixing. */ mLate.VecAp.process(tempSamples, offset, mixX, mixY, todo); - for(size_t j{0u};j < NUM_LINES;j++) + for(size_t j{0_uz};j < NUM_LINES;++j) std::copy_n(tempSamples[j].begin(), todo, outSamples[j].begin()+base); /* Finally, scatter and bounce the results to refeed the feedback buffer. */ - VectorScatterRevDelayIn(late_delay, offset, mixX, mixY, tempSamples, todo); + VectorScatterRev(mixX, mixY, tempSamples, todo); + for(size_t j{0_uz};j < NUM_LINES;++j) + late_delay.write(offset, j, al::span{tempSamples[j]}.first(todo)); base += todo; offset += todo; @@ -1631,110 +1746,34 @@ void ReverbState::process(const size_t samplesToDo, const al::span 0); + ASSUME(samplesToDo <= BufferLineSize); - auto &oldpipeline = mPipelines[mCurrentPipeline^1]; + auto &oldpipeline = mPipelines[!mCurrentPipeline]; auto &pipeline = mPipelines[mCurrentPipeline]; - if(mPipelineState >= Fading) + /* Convert B-Format to A-Format for processing. */ + const size_t numInput{std::min(samplesIn.size(), NUM_LINES)}; + const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo}; + for(size_t c{0u};c < NUM_LINES;++c) { - /* Convert B-Format to A-Format for processing. */ - const size_t numInput{minz(samplesIn.size(), NUM_LINES)}; - const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo}; - for(size_t c{0u};c < NUM_LINES;c++) + std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); + for(size_t i{0};i < numInput;++i) { - std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); - for(size_t i{0};i < numInput;++i) - { - const float gain{B2A[c][i]}; - const float *RESTRICT input{al::assume_aligned<16>(samplesIn[i].data())}; - - auto mix_sample = [gain](const float sample, const float in) noexcept -> float - { return sample + in*gain; }; - std::transform(tmpspan.begin(), tmpspan.end(), input, tmpspan.begin(), - mix_sample); - } + const float gain{B2A[c][i]}; - /* Band-pass the incoming samples and feed the initial delay line. */ - auto&& filter = DualBiquad{pipeline.mFilter[c].Lp, pipeline.mFilter[c].Hp}; - filter.process(tmpspan, tmpspan.data()); - pipeline.mEarlyDelayIn.write(offset, c, tmpspan.cbegin(), samplesToDo); + auto mix_sample = [gain](const float sample, const float in) noexcept -> float + { return sample + in*gain; }; + std::transform(tmpspan.begin(), tmpspan.end(), samplesIn[i].begin(), tmpspan.begin(), + mix_sample); } - if(mPipelineState == Fading) - { - /* Give the old pipeline silence if it's still fading out. */ - for(size_t c{0u};c < NUM_LINES;c++) - { - std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); - auto&& filter = DualBiquad{oldpipeline.mFilter[c].Lp, oldpipeline.mFilter[c].Hp}; - filter.process(tmpspan, tmpspan.data()); - oldpipeline.mEarlyDelayIn.write(offset, c, tmpspan.cbegin(), samplesToDo); - } - } + mMainDelay.write(offset, c, tmpspan); } - else - { - /* At the start of a fade, fade in input for the current pipeline, and - * fade out input for the old pipeline. - */ - const size_t numInput{minz(samplesIn.size(), NUM_LINES)}; - const al::span tmpspan{al::assume_aligned<16>(mTempLine.data()), samplesToDo}; - const float fadeStep{1.0f / static_cast(samplesToDo)}; - - for(size_t c{0u};c < NUM_LINES;c++) - { - std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); - for(size_t i{0};i < numInput;++i) - { - const float gain{B2A[c][i]}; - const float *RESTRICT input{al::assume_aligned<16>(samplesIn[i].data())}; - - auto mix_sample = [gain](const float sample, const float in) noexcept -> float - { return sample + in*gain; }; - std::transform(tmpspan.begin(), tmpspan.end(), input, tmpspan.begin(), - mix_sample); - } - float stepCount{0.0f}; - for(float &sample : tmpspan) - { - stepCount += 1.0f; - sample *= stepCount*fadeStep; - } - - auto&& filter = DualBiquad{pipeline.mFilter[c].Lp, pipeline.mFilter[c].Hp}; - filter.process(tmpspan, tmpspan.data()); - pipeline.mEarlyDelayIn.write(offset, c, tmpspan.cbegin(), samplesToDo); - } - for(size_t c{0u};c < NUM_LINES;c++) - { - std::fill(tmpspan.begin(), tmpspan.end(), 0.0f); - for(size_t i{0};i < numInput;++i) - { - const float gain{B2A[c][i]}; - const float *RESTRICT input{al::assume_aligned<16>(samplesIn[i].data())}; - auto mix_sample = [gain](const float sample, const float in) noexcept -> float - { return sample + in*gain; }; - std::transform(tmpspan.begin(), tmpspan.end(), input, tmpspan.begin(), - mix_sample); - } - float stepCount{0.0f}; - for(float &sample : tmpspan) - { - stepCount += 1.0f; - sample *= 1.0f - stepCount*fadeStep; - } - - auto&& filter = DualBiquad{oldpipeline.mFilter[c].Lp, oldpipeline.mFilter[c].Hp}; - filter.process(tmpspan, tmpspan.data()); - oldpipeline.mEarlyDelayIn.write(offset, c, tmpspan.cbegin(), samplesToDo); - } - mPipelineState = Fading; - } + mPipelineState = std::max(Fading, mPipelineState); /* Process reverb for these samples. and mix them to the output. */ - pipeline.processEarly(offset, samplesToDo, mTempSamples, mEarlySamples); + pipeline.processEarly(mMainDelay, offset, samplesToDo, mTempSamples, mEarlySamples); pipeline.processLate(offset, samplesToDo, mTempSamples, mLateSamples); mixOut(pipeline, samplesOut, samplesToDo); @@ -1743,9 +1782,9 @@ void ReverbState::process(const size_t samplesToDo, const al::span= oldpipeline.mFadeSampleCount) { - for(auto &gains : oldpipeline.mEarly.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); - for(auto &gains : oldpipeline.mLate.TargetGains) - std::fill(std::begin(gains), std::end(gains), 0.0f); + for(auto &gains : oldpipeline.mEarly.Gains) + std::fill(gains.Target.begin(), gains.Target.end(), 0.0f); + for(auto &gains : oldpipeline.mLate.Gains) + std::fill(gains.Target.begin(), gains.Target.end(), 0.0f); oldpipeline.mFadeSampleCount = 0; mPipelineState = Cleanup; } @@ -1770,7 +1809,7 @@ void ReverbState::process(const size_t samplesToDo, const al::span{new ReverbState{}}; } }; -struct StdReverbStateFactory final : public EffectStateFactory { - al::intrusive_ptr create() override - { return al::intrusive_ptr{new ReverbState{}}; } -}; - } // namespace EffectStateFactory *ReverbStateFactory_getFactory() @@ -1797,9 +1831,3 @@ EffectStateFactory *ReverbStateFactory_getFactory() static ReverbStateFactory ReverbFactory{}; return &ReverbFactory; } - -EffectStateFactory *StdReverbStateFactory_getFactory() -{ - static StdReverbStateFactory ReverbFactory{}; - return &ReverbFactory; -} diff --git a/3rdparty/openal/alc/effects/vmorpher.cpp b/3rdparty/openal/alc/effects/vmorpher.cpp index 872c7add1698..d9141bb6edcd 100644 --- a/3rdparty/openal/alc/effects/vmorpher.cpp +++ b/3rdparty/openal/alc/effects/vmorpher.cpp @@ -34,68 +34,69 @@ #include #include +#include #include #include -#include +#include #include "alc/effects/base.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" #include "core/ambidefs.h" #include "core/bufferline.h" #include "core/context.h" -#include "core/devformat.h" #include "core/device.h" +#include "core/effects/base.h" #include "core/effectslot.h" #include "core/mixer.h" #include "intrusive_ptr.h" +struct BufferStorage; namespace { using uint = unsigned int; -#define MAX_UPDATE_SAMPLES 256 -#define NUM_FORMANTS 4 -#define NUM_FILTERS 2 -#define Q_FACTOR 5.0f - -#define VOWEL_A_INDEX 0 -#define VOWEL_B_INDEX 1 +constexpr size_t MaxUpdateSamples{256}; +constexpr size_t NumFormants{4}; +constexpr float RcpQFactor{1.0f / 5.0f}; +enum : size_t { + VowelAIndex, + VowelBIndex, + NumFilters +}; -#define WAVEFORM_FRACBITS 24 -#define WAVEFORM_FRACONE (1<*2.0f / WAVEFORM_FRACONE}; + constexpr float scale{al::numbers::pi_v*2.0f / float{WaveformFracOne}}; return std::sin(static_cast(index) * scale)*0.5f + 0.5f; } inline float Saw(uint index) -{ return static_cast(index) / float{WAVEFORM_FRACONE}; } +{ return static_cast(index) / float{WaveformFracOne}; } inline float Triangle(uint index) -{ return std::fabs(static_cast(index)*(2.0f/WAVEFORM_FRACONE) - 1.0f); } +{ return std::fabs(static_cast(index)*(2.0f/WaveformFracOne) - 1.0f); } inline float Half(uint) { return 0.5f; } template -void Oscillate(float *RESTRICT dst, uint index, const uint step, size_t todo) +void Oscillate(const al::span dst, uint index, const uint step) { - for(size_t i{0u};i < todo;i++) + std::generate(dst.begin(), dst.end(), [&index,step] { index += step; - index &= WAVEFORM_FRACMASK; - dst[i] = func(index); - } + index &= WaveformFracMask; + return func(index); + }); } -struct FormantFilter -{ +struct FormantFilter { float mCoeff{0.0f}; float mGain{1.0f}; float mS1{0.0f}; @@ -106,34 +107,38 @@ struct FormantFilter : mCoeff{std::tan(al::numbers::pi_v * f0norm)}, mGain{gain} { } - inline void process(const float *samplesIn, float *samplesOut, const size_t numInput) + void process(const float *samplesIn, float *samplesOut, const size_t numInput) noexcept { /* A state variable filter from a topology-preserving transform. * Based on a talk given by Ivan Cohen: https://www.youtube.com/watch?v=esjHXGPyrhg */ const float g{mCoeff}; const float gain{mGain}; - const float h{1.0f / (1.0f + (g/Q_FACTOR) + (g*g))}; + const float h{1.0f / (1.0f + (g*RcpQFactor) + (g*g))}; + const float coeff{RcpQFactor + g}; float s1{mS1}; float s2{mS2}; - for(size_t i{0u};i < numInput;i++) - { - const float H{(samplesIn[i] - (1.0f/Q_FACTOR + g)*s1 - s2)*h}; - const float B{g*H + s1}; - const float L{g*B + s2}; + const auto input = al::span{samplesIn, numInput}; + const auto output = al::span{samplesOut, numInput}; + std::transform(input.cbegin(), input.cend(), output.cbegin(), output.begin(), + [g,gain,h,coeff,&s1,&s2](const float in, const float out) noexcept -> float + { + const float H{(in - coeff*s1 - s2)*h}; + const float B{g*H + s1}; + const float L{g*B + s2}; - s1 = g*H + B; - s2 = g*B + L; + s1 = g*H + B; + s2 = g*B + L; - // Apply peak and accumulate samples. - samplesOut[i] += B * gain; - } + // Apply peak and accumulate samples. + return out + B*gain; + }); mS1 = s1; mS2 = s2; } - inline void clear() + void clear() noexcept { mS1 = 0.0f; mS2 = 0.0f; @@ -142,26 +147,27 @@ struct FormantFilter struct VmorpherState final : public EffectState { - struct { + struct OutParams { uint mTargetChannel{InvalidChannelIndex}; /* Effect parameters */ - FormantFilter mFormants[NUM_FILTERS][NUM_FORMANTS]; + std::array,NumFilters> mFormants; /* Effect gains for each channel */ float mCurrentGain{}; float mTargetGain{}; - } mChans[MaxAmbiChannels]; + }; + std::array mChans; - void (*mGetSamples)(float*RESTRICT, uint, const uint, size_t){}; + void (*mGetSamples)(const al::span dst, uint index, const uint step){}; uint mIndex{0}; uint mStep{1}; /* Effects buffers */ - alignas(16) float mSampleBufferA[MAX_UPDATE_SAMPLES]{}; - alignas(16) float mSampleBufferB[MAX_UPDATE_SAMPLES]{}; - alignas(16) float mLfo[MAX_UPDATE_SAMPLES]{}; + alignas(16) std::array mSampleBufferA{}; + alignas(16) std::array mSampleBufferB{}; + alignas(16) std::array mLfo{}; void deviceUpdate(const DeviceBase *device, const BufferStorage *buffer) override; void update(const ContextBase *context, const EffectSlot *slot, const EffectProps *props, @@ -169,14 +175,12 @@ struct VmorpherState final : public EffectState { void process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) override; - static std::array getFiltersByPhoneme(VMorpherPhenome phoneme, - float frequency, float pitch); - - DEF_NEWDEL(VmorpherState) + static std::array getFiltersByPhoneme(VMorpherPhenome phoneme, + float frequency, float pitch) noexcept; }; -std::array VmorpherState::getFiltersByPhoneme(VMorpherPhenome phoneme, - float frequency, float pitch) +std::array VmorpherState::getFiltersByPhoneme(VMorpherPhenome phoneme, + float frequency, float pitch) noexcept { /* Using soprano formant set of values to * better match mid-range frequency space. @@ -232,44 +236,43 @@ void VmorpherState::deviceUpdate(const DeviceBase*, const BufferStorage*) for(auto &e : mChans) { e.mTargetChannel = InvalidChannelIndex; - std::for_each(std::begin(e.mFormants[VOWEL_A_INDEX]), std::end(e.mFormants[VOWEL_A_INDEX]), + std::for_each(e.mFormants[VowelAIndex].begin(), e.mFormants[VowelAIndex].end(), std::mem_fn(&FormantFilter::clear)); - std::for_each(std::begin(e.mFormants[VOWEL_B_INDEX]), std::end(e.mFormants[VOWEL_B_INDEX]), + std::for_each(e.mFormants[VowelBIndex].begin(), e.mFormants[VowelBIndex].end(), std::mem_fn(&FormantFilter::clear)); e.mCurrentGain = 0.0f; } } void VmorpherState::update(const ContextBase *context, const EffectSlot *slot, - const EffectProps *props, const EffectTarget target) + const EffectProps *props_, const EffectTarget target) { + auto &props = std::get(*props_); const DeviceBase *device{context->mDevice}; - const float frequency{static_cast(device->Frequency)}; - const float step{props->Vmorpher.Rate / frequency}; - mStep = fastf2u(clampf(step*WAVEFORM_FRACONE, 0.0f, float{WAVEFORM_FRACONE-1})); + const float frequency{static_cast(device->mSampleRate)}; + const float step{props.Rate / frequency}; + mStep = fastf2u(std::clamp(step*WaveformFracOne, 0.0f, WaveformFracOne-1.0f)); if(mStep == 0) mGetSamples = Oscillate; - else if(props->Vmorpher.Waveform == VMorpherWaveform::Sinusoid) + else if(props.Waveform == VMorpherWaveform::Sinusoid) mGetSamples = Oscillate; - else if(props->Vmorpher.Waveform == VMorpherWaveform::Triangle) + else if(props.Waveform == VMorpherWaveform::Triangle) mGetSamples = Oscillate; - else /*if(props->Vmorpher.Waveform == VMorpherWaveform::Sawtooth)*/ + else /*if(props.Waveform == VMorpherWaveform::Sawtooth)*/ mGetSamples = Oscillate; - const float pitchA{std::pow(2.0f, - static_cast(props->Vmorpher.PhonemeACoarseTuning) / 12.0f)}; - const float pitchB{std::pow(2.0f, - static_cast(props->Vmorpher.PhonemeBCoarseTuning) / 12.0f)}; + const float pitchA{std::pow(2.0f, static_cast(props.PhonemeACoarseTuning) / 12.0f)}; + const float pitchB{std::pow(2.0f, static_cast(props.PhonemeBCoarseTuning) / 12.0f)}; - auto vowelA = getFiltersByPhoneme(props->Vmorpher.PhonemeA, frequency, pitchA); - auto vowelB = getFiltersByPhoneme(props->Vmorpher.PhonemeB, frequency, pitchB); + auto vowelA = getFiltersByPhoneme(props.PhonemeA, frequency, pitchA); + auto vowelB = getFiltersByPhoneme(props.PhonemeB, frequency, pitchB); /* Copy the filter coefficients to the input channels. */ for(size_t i{0u};i < slot->Wet.Buffer.size();++i) { - std::copy(vowelA.begin(), vowelA.end(), std::begin(mChans[i].mFormants[VOWEL_A_INDEX])); - std::copy(vowelB.begin(), vowelB.end(), std::begin(mChans[i].mFormants[VOWEL_B_INDEX])); + std::copy(vowelA.begin(), vowelA.end(), mChans[i].mFormants[VowelAIndex].begin()); + std::copy(vowelB.begin(), vowelB.end(), mChans[i].mFormants[VowelBIndex].begin()); } mOutTarget = target.Main->Buffer; @@ -283,18 +286,20 @@ void VmorpherState::update(const ContextBase *context, const EffectSlot *slot, void VmorpherState::process(const size_t samplesToDo, const al::span samplesIn, const al::span samplesOut) { + alignas(16) std::array blended{}; + /* Following the EFX specification for a conformant implementation which describes * the effect as a pair of 4-band formant filters blended together using an LFO. */ for(size_t base{0u};base < samplesToDo;) { - const size_t td{minz(MAX_UPDATE_SAMPLES, samplesToDo-base)}; + const size_t td{std::min(MaxUpdateSamples, samplesToDo-base)}; - mGetSamples(mLfo, mIndex, mStep, td); + mGetSamples(al::span{mLfo}.first(td), mIndex, mStep); mIndex += static_cast(mStep * td); - mIndex &= WAVEFORM_FRACMASK; + mIndex &= WaveformFracMask; - auto chandata = std::begin(mChans); + auto chandata = mChans.begin(); for(const auto &input : samplesIn) { const size_t outidx{chandata->mTargetChannel}; @@ -304,30 +309,29 @@ void VmorpherState::process(const size_t samplesToDo, const al::spanmFormants[VOWEL_A_INDEX]; - auto& vowelB = chandata->mFormants[VOWEL_B_INDEX]; + const auto vowelA = al::span{chandata->mFormants[VowelAIndex]}; + const auto vowelB = al::span{chandata->mFormants[VowelBIndex]}; /* Process first vowel. */ - std::fill_n(std::begin(mSampleBufferA), td, 0.0f); - vowelA[0].process(&input[base], mSampleBufferA, td); - vowelA[1].process(&input[base], mSampleBufferA, td); - vowelA[2].process(&input[base], mSampleBufferA, td); - vowelA[3].process(&input[base], mSampleBufferA, td); + std::fill_n(mSampleBufferA.begin(), td, 0.0f); + vowelA[0].process(&input[base], mSampleBufferA.data(), td); + vowelA[1].process(&input[base], mSampleBufferA.data(), td); + vowelA[2].process(&input[base], mSampleBufferA.data(), td); + vowelA[3].process(&input[base], mSampleBufferA.data(), td); /* Process second vowel. */ - std::fill_n(std::begin(mSampleBufferB), td, 0.0f); - vowelB[0].process(&input[base], mSampleBufferB, td); - vowelB[1].process(&input[base], mSampleBufferB, td); - vowelB[2].process(&input[base], mSampleBufferB, td); - vowelB[3].process(&input[base], mSampleBufferB, td); + std::fill_n(mSampleBufferB.begin(), td, 0.0f); + vowelB[0].process(&input[base], mSampleBufferB.data(), td); + vowelB[1].process(&input[base], mSampleBufferB.data(), td); + vowelB[2].process(&input[base], mSampleBufferB.data(), td); + vowelB[3].process(&input[base], mSampleBufferB.data(), td); - alignas(16) float blended[MAX_UPDATE_SAMPLES]; for(size_t i{0u};i < td;i++) blended[i] = lerpf(mSampleBufferA[i], mSampleBufferB[i], mLfo[i]); /* Now, mix the processed sound data to the output. */ - MixSamples({blended, td}, samplesOut[outidx].data()+base, chandata->mCurrentGain, - chandata->mTargetGain, samplesToDo-base); + MixSamples(al::span{blended}.first(td), al::span{samplesOut[outidx]}.subspan(base), + chandata->mCurrentGain, chandata->mTargetGain, samplesToDo-base); ++chandata; } diff --git a/3rdparty/openal/alc/events.cpp b/3rdparty/openal/alc/events.cpp index a80faf8aa075..dfabcf897f0e 100644 --- a/3rdparty/openal/alc/events.cpp +++ b/3rdparty/openal/alc/events.cpp @@ -3,26 +3,15 @@ #include "events.h" -#include - +#include "alnumeric.h" #include "alspan.h" #include "core/logging.h" #include "device.h" +#include "fmt/core.h" namespace { -std::optional GetEventType(ALCenum type) -{ - switch(type) - { - case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; - case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; - case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; - } - return std::nullopt; -} - ALCenum EnumFromEventType(const alc::EventType type) { switch(type) @@ -32,13 +21,24 @@ ALCenum EnumFromEventType(const alc::EventType type) case alc::EventType::DeviceRemoved: return ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT; case alc::EventType::Count: break; } - throw std::runtime_error{"Invalid EventType: "+std::to_string(al::to_underlying(type))}; + throw std::runtime_error{fmt::format("Invalid EventType: {}", int{al::to_underlying(type)})}; } } // namespace namespace alc { +std::optional GetEventType(ALCenum type) +{ + switch(type) + { + case ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT: return alc::EventType::DefaultDeviceChanged; + case ALC_EVENT_TYPE_DEVICE_ADDED_SOFT: return alc::EventType::DeviceAdded; + case ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT: return alc::EventType::DeviceRemoved; + } + return std::nullopt; +} + void Event(EventType eventType, DeviceType deviceType, ALCdevice *device, std::string_view message) noexcept { auto eventlock = std::unique_lock{EventMutex}; @@ -73,10 +73,10 @@ FORCE_ALIGN ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const AL alc::EventBitSet eventSet{0}; for(ALCenum type : al::span{events, static_cast(count)}) { - auto etype = GetEventType(type); + auto etype = alc::GetEventType(type); if(!etype) { - WARN("Invalid event type: 0x%04x\n", type); + WARN("Invalid event type: {:#04x}", as_unsigned(type)); alcSetError(nullptr, ALC_INVALID_ENUM); return ALC_FALSE; } diff --git a/3rdparty/openal/alc/events.h b/3rdparty/openal/alc/events.h index 4acc505df64a..3f53ec76265b 100644 --- a/3rdparty/openal/alc/events.h +++ b/3rdparty/openal/alc/events.h @@ -6,6 +6,7 @@ #include #include +#include #include @@ -19,6 +20,13 @@ enum class EventType : uint8_t { Count }; +std::optional GetEventType(ALCenum type); + +enum class EventSupport : ALCenum { + FullSupport = ALC_EVENT_SUPPORTED_SOFT, + NoSupport = ALC_EVENT_NOT_SUPPORTED_SOFT, +}; + enum class DeviceType : ALCenum { Playback = ALC_PLAYBACK_DEVICE_SOFT, Capture = ALC_CAPTURE_DEVICE_SOFT, diff --git a/3rdparty/openal/alc/export_list.h b/3rdparty/openal/alc/export_list.h index cefe7a099bce..b83f2c38a3fc 100644 --- a/3rdparty/openal/alc/export_list.h +++ b/3rdparty/openal/alc/export_list.h @@ -1,12 +1,14 @@ #ifndef ALC_EXPORT_LIST_H #define ALC_EXPORT_LIST_H +#include "config.h" + #include "AL/alc.h" #include "AL/al.h" #include "AL/alext.h" #include "inprogext.h" -#ifdef ALSOFT_EAX +#if ALSOFT_EAX #include "context.h" #include "al/eax/x_ram.h" #endif @@ -16,7 +18,8 @@ struct FuncExport { const char *funcName; void *address; }; -#define DECL(x) { #x, reinterpret_cast(x) } +#define DECL(x) FuncExport{#x, reinterpret_cast(x)} +/* NOLINTNEXTLINE(*-avoid-c-arrays) Too large for std::array auto-deduction :( */ inline const FuncExport alcFunctions[]{ DECL(alcCreateContext), DECL(alcMakeContextCurrent), @@ -56,6 +59,7 @@ inline const FuncExport alcFunctions[]{ DECL(alcReopenDeviceSOFT), + DECL(alcEventIsSupportedSOFT), DECL(alcEventControlSOFT), DECL(alcEventCallbackSOFT), @@ -200,11 +204,6 @@ inline const FuncExport alcFunctions[]{ DECL(alGetBuffer3PtrSOFT), DECL(alGetBufferPtrvSOFT), - DECL(alAuxiliaryEffectSlotPlaySOFT), - DECL(alAuxiliaryEffectSlotPlayvSOFT), - DECL(alAuxiliaryEffectSlotStopSOFT), - DECL(alAuxiliaryEffectSlotStopvSOFT), - DECL(alSourcePlayAtTimeSOFT), DECL(alSourcePlayAtTimevSOFT), @@ -218,6 +217,10 @@ inline const FuncExport alcFunctions[]{ DECL(alPushDebugGroupEXT), DECL(alPopDebugGroupEXT), DECL(alGetDebugMessageLogEXT), + DECL(alObjectLabelEXT), + DECL(alGetObjectLabelEXT), + DECL(alGetPointerEXT), + DECL(alGetPointervEXT), /* Direct Context functions */ DECL(alcGetProcAddress2), @@ -368,15 +371,16 @@ inline const FuncExport alcFunctions[]{ DECL(alPushDebugGroupDirectEXT), DECL(alPopDebugGroupDirectEXT), DECL(alGetDebugMessageLogDirectEXT), - DECL(alObjectLabelEXT), DECL(alObjectLabelDirectEXT), - DECL(alGetObjectLabelEXT), DECL(alGetObjectLabelDirectEXT), + DECL(alGetPointerDirectEXT), + DECL(alGetPointervDirectEXT), /* Extra functions */ DECL(alsoft_set_log_callback), -#ifdef ALSOFT_EAX -}, eaxFunctions[]{ +}; +#if ALSOFT_EAX +inline const std::array eaxFunctions{ DECL(EAXGet), DECL(EAXSet), DECL(EAXGetBufferMode), @@ -386,15 +390,16 @@ inline const FuncExport alcFunctions[]{ DECL(EAXSetDirect), DECL(EAXGetBufferModeDirect), DECL(EAXSetBufferModeDirect), -#endif }; +#endif #undef DECL struct EnumExport { const char *enumName; int value; }; -#define DECL(x) { #x, (x) } +#define DECL(x) EnumExport{#x, (x)} +/* NOLINTNEXTLINE(*-avoid-c-arrays) Too large for std::array auto-deduction :( */ inline const EnumExport alcEnumerations[]{ DECL(ALC_INVALID), DECL(ALC_FALSE), @@ -598,6 +603,48 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_FORMAT_BFORMAT3D_FLOAT32), DECL(AL_FORMAT_BFORMAT3D_MULAW), + DECL(AL_FORMAT_UHJ2CHN8_SOFT), + DECL(AL_FORMAT_UHJ2CHN16_SOFT), + DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ3CHN8_SOFT), + DECL(AL_FORMAT_UHJ3CHN16_SOFT), + DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), + DECL(AL_FORMAT_UHJ4CHN8_SOFT), + DECL(AL_FORMAT_UHJ4CHN16_SOFT), + DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), + DECL(AL_STEREO_MODE_SOFT), + DECL(AL_NORMAL_SOFT), + DECL(AL_SUPER_STEREO_SOFT), + DECL(AL_SUPER_STEREO_WIDTH_SOFT), + + DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), + DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), + DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), + DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), + + DECL(AL_FORMAT_MONO_I32), + DECL(AL_FORMAT_STEREO_I32), + DECL(AL_FORMAT_REAR_I32), + DECL(AL_FORMAT_QUAD_I32), + DECL(AL_FORMAT_51CHN_I32), + DECL(AL_FORMAT_61CHN_I32), + DECL(AL_FORMAT_71CHN_I32), + DECL(AL_FORMAT_BFORMAT2D_I32), + DECL(AL_FORMAT_BFORMAT3D_I32), + DECL(AL_FORMAT_UHJ2CHN_I32_SOFT), + DECL(AL_FORMAT_UHJ3CHN_I32_SOFT), + DECL(AL_FORMAT_UHJ4CHN_I32_SOFT), + + DECL(AL_FORMAT_REAR_FLOAT32), + DECL(AL_FORMAT_QUAD_FLOAT32), + DECL(AL_FORMAT_51CHN_FLOAT32), + DECL(AL_FORMAT_61CHN_FLOAT32), + DECL(AL_FORMAT_71CHN_FLOAT32), + DECL(AL_FREQUENCY), DECL(AL_BITS), DECL(AL_CHANNELS), @@ -820,32 +867,9 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_UNPACK_AMBISONIC_ORDER_SOFT), - DECL(AL_EFFECT_CONVOLUTION_REVERB_SOFT), + DECL(AL_EFFECT_CONVOLUTION_SOFT), DECL(AL_EFFECTSLOT_STATE_SOFT), - DECL(AL_FORMAT_UHJ2CHN8_SOFT), - DECL(AL_FORMAT_UHJ2CHN16_SOFT), - DECL(AL_FORMAT_UHJ2CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ3CHN8_SOFT), - DECL(AL_FORMAT_UHJ3CHN16_SOFT), - DECL(AL_FORMAT_UHJ3CHN_FLOAT32_SOFT), - DECL(AL_FORMAT_UHJ4CHN8_SOFT), - DECL(AL_FORMAT_UHJ4CHN16_SOFT), - DECL(AL_FORMAT_UHJ4CHN_FLOAT32_SOFT), - DECL(AL_STEREO_MODE_SOFT), - DECL(AL_NORMAL_SOFT), - DECL(AL_SUPER_STEREO_SOFT), - DECL(AL_SUPER_STEREO_WIDTH_SOFT), - - DECL(AL_FORMAT_UHJ2CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ2CHN_IMA4_SOFT), - DECL(AL_FORMAT_UHJ2CHN_MSADPCM_SOFT), - DECL(AL_FORMAT_UHJ3CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ3CHN_ALAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_MULAW_SOFT), - DECL(AL_FORMAT_UHJ4CHN_ALAW_SOFT), - DECL(AL_DONT_CARE_EXT), DECL(AL_DEBUG_OUTPUT_EXT), DECL(AL_DEBUG_CALLBACK_FUNCTION_EXT), @@ -882,16 +906,20 @@ inline const EnumExport alcEnumerations[]{ DECL(AL_EFFECT_EXT), DECL(AL_AUXILIARY_EFFECT_SLOT_EXT), + DECL(AL_PANNING_ENABLED_SOFT), + DECL(AL_PAN_SOFT), + DECL(AL_STOP_SOURCES_ON_DISCONNECT_SOFT), -#ifdef ALSOFT_EAX -}, eaxEnumerations[]{ +}; +#if ALSOFT_EAX +inline const std::array eaxEnumerations{ DECL(AL_EAX_RAM_SIZE), DECL(AL_EAX_RAM_FREE), DECL(AL_STORAGE_AUTOMATIC), DECL(AL_STORAGE_HARDWARE), DECL(AL_STORAGE_ACCESSIBLE), -#endif // ALSOFT_EAX }; +#endif #undef DECL #endif /* ALC_EXPORT_LIST_H */ diff --git a/3rdparty/openal/alc/inprogext.h b/3rdparty/openal/alc/inprogext.h index 2fa425bbbcb6..eb421fd6350f 100644 --- a/3rdparty/openal/alc/inprogext.h +++ b/3rdparty/openal/alc/inprogext.h @@ -1,6 +1,7 @@ #ifndef INPROGEXT_H #define INPROGEXT_H +/* NOLINTBEGIN */ #include "AL/al.h" #include "AL/alc.h" #include "AL/alext.h" @@ -36,25 +37,11 @@ void AL_APIENTRY alFlushMappedBufferDirectSOFT(ALCcontext *context, ALuint buffe #endif #endif -#ifndef AL_SOFT_bformat_hoa -#define AL_SOFT_bformat_hoa -#define AL_UNPACK_AMBISONIC_ORDER_SOFT 0x199D -#endif - -#ifndef AL_SOFT_convolution_reverb -#define AL_SOFT_convolution_reverb -#define AL_EFFECT_CONVOLUTION_REVERB_SOFT 0xA000 -#define AL_EFFECTSLOT_STATE_SOFT 0x199D -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYSOFT)(ALuint slotid) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTPLAYVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPSOFT)(ALuint slotid) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALAUXILIARYEFFECTSLOTSTOPVSOFT)(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT17; -#ifdef AL_ALEXT_PROTOTYPES -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) AL_API_NOEXCEPT; -AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT; -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) AL_API_NOEXCEPT; -AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) AL_API_NOEXCEPT; -#endif +#ifndef AL_SOFT_convolution_effect +#define AL_SOFT_convolution_effect +#define AL_EFFECT_CONVOLUTION_SOFT 0xA000 +#define AL_CONVOLUTION_ORIENTATION_SOFT 0x100F /* same as AL_ORIENTATION */ +#define AL_EFFECTSLOT_STATE_SOFT 0x199E #endif #ifndef AL_SOFT_hold_on_disconnect @@ -63,338 +50,33 @@ AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint * #endif -#ifndef AL_EXT_direct_context -#define AL_EXT_direct_context -typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS2)(ALCdevice *device, const ALCchar *funcname) AL_API_NOEXCEPT17; - -typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT17; -typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; -typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; -typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; -typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; -typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT17; -typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT17; -typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; -/* ALC_EXT_EFX */ -typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; -/* AL_EXT_BUFFER_DATA_STATIC */ -typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; -/* AL_EXT_debug */ -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; -typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; -/* AL_EXT_FOLDBACK */ -typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; -/* AL_SOFT_buffer_sub_data */ -typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; -/* AL_SOFT_source_latency */ -typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; -/* AL_SOFT_deferred_updates */ -typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; -/* AL_SOFT_source_resampler */ -typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT17; -/* AL_SOFT_events */ -typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; -typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; -/* AL_SOFT_callback_buffer */ -typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; -/* AL_SOFT_source_start_delay */ -typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; -typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; -/* EAX */ -typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_buffer, ALuint property_size) AL_API_NOEXCEPT17; -typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT17; -typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; -typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; -#ifdef AL_ALEXT_PROTOTYPES -ALCvoid* AL_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALchar *funcName) AL_API_NOEXCEPT; - -void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; -void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; - -void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; -void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; -void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT; - -const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; -ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; -ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; -ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; - -ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT; -void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT; -ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT; - -void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT; -void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; -void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT; -void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; -void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; - -void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT; -void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; -void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; -void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; -void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; - -void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; -void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; -void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; -void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; -void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; - -void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT; -void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT; -void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; -void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; -void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; - -void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT; -void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT; -void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; -void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; -void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; - -void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; -void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT; -void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; -void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; -void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; -void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; -void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; - -void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; - -void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; -void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; -ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; -void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; -void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; - -void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; -void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; - -void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; - -void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; -void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; -void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; -void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; - -void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; -void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; - -const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT; - -void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; -void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; -void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; -void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; - -void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; -void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; - -void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; -void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; - -ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT; -ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint property_source_id, ALvoid *property_value, ALuint property_value_size) AL_API_NOEXCEPT; -ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT; -ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT; +#ifndef AL_EXT_32bit_formats +#define AL_EXT_32bit_formats +#define AL_FORMAT_MONO_I32 0x19DB +#define AL_FORMAT_STEREO_I32 0x19DC +#define AL_FORMAT_REAR_I32 0x19DD +#define AL_FORMAT_REAR_FLOAT32 0x19DE +#define AL_FORMAT_QUAD_I32 0x19DF +#define AL_FORMAT_QUAD_FLOAT32 0x19E0 +#define AL_FORMAT_51CHN_I32 0x19E1 +#define AL_FORMAT_51CHN_FLOAT32 0x19E2 +#define AL_FORMAT_61CHN_I32 0x19E3 +#define AL_FORMAT_61CHN_FLOAT32 0x19E4 +#define AL_FORMAT_71CHN_I32 0x19E5 +#define AL_FORMAT_71CHN_FLOAT32 0x19E6 + +#define AL_FORMAT_BFORMAT2D_I32 0x19E7 +#define AL_FORMAT_BFORMAT3D_I32 0x19E8 + +#define AL_FORMAT_UHJ2CHN_I32_SOFT 0x19E9 +#define AL_FORMAT_UHJ3CHN_I32_SOFT 0x19EA +#define AL_FORMAT_UHJ4CHN_I32_SOFT 0x19EB #endif + +#ifndef AL_SOFT_source_panning +#define AL_SOFT_source_panning +#define AL_PANNING_ENABLED_SOFT 0x19EC +#define AL_PAN_SOFT 0x19ED #endif /* Non-standard exports. Not part of any extension. */ @@ -407,13 +89,25 @@ void ALC_APIENTRY alsoft_set_log_callback(LPALSOFTLOGCALLBACK callback, void *us AL_API void AL_APIENTRY alSourceQueueBufferLayersSOFT(ALuint src, ALsizei nb, const ALuint *buffers) noexcept; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlaySOFT(ALuint slotid) noexcept; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotPlayvSOFT(ALsizei n, const ALuint *slotids) noexcept; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopSOFT(ALuint slotid) noexcept; +AL_API void AL_APIENTRY alAuxiliaryEffectSlotStopvSOFT(ALsizei n, const ALuint *slotids) noexcept; + AL_API ALint64SOFT AL_APIENTRY alGetInteger64SOFT(ALenum pname) AL_API_NOEXCEPT; AL_API void AL_APIENTRY alGetInteger64vSOFT(ALenum pname, ALint64SOFT *values) AL_API_NOEXCEPT; ALint64SOFT AL_APIENTRY alGetInteger64DirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; void AL_APIENTRY alGetInteger64vDirectSOFT(ALCcontext *context, ALenum pname, ALint64SOFT *values) AL_API_NOEXCEPT; +/* Not included in the public headers or export list, as a precaution for apps + * that check these to determine the behavior of the multi-channel *32 formats. + */ +#define AL_FORMAT_MONO32 0x1202 +#define AL_FORMAT_STEREO32 0x1203 + #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* INPROGEXT_H */ diff --git a/3rdparty/openal/alc/panning.cpp b/3rdparty/openal/alc/panning.cpp index 871fef65e906..bf0736de9e02 100644 --- a/3rdparty/openal/alc/panning.cpp +++ b/3rdparty/openal/alc/panning.cpp @@ -22,29 +22,26 @@ #include #include +#include #include #include #include +#include #include -#include +#include #include -#include #include -#include #include #include #include +#include +#include #include -#include "AL/al.h" #include "AL/alc.h" #include "AL/alext.h" -#include "al/auxeffectslot.h" -#include "albit.h" -#include "alconfig.h" #include "alc/context.h" -#include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" @@ -53,64 +50,103 @@ #include "core/ambdec.h" #include "core/ambidefs.h" #include "core/bformatdec.h" +#include "core/bufferline.h" #include "core/bs2b.h" +#include "core/context.h" #include "core/devformat.h" +#include "core/device.h" +#include "core/effectslot.h" +#include "core/filters/nfc.h" +#include "core/filters/splitter.h" #include "core/front_stablizer.h" #include "core/hrtf.h" #include "core/logging.h" +#include "core/mixer/hrtfdefs.h" #include "core/uhjfilter.h" #include "device.h" +#include "flexarray.h" +#include "intrusive_ptr.h" #include "opthelpers.h" +#include "vector.h" namespace { -using namespace std::placeholders; +using namespace std::string_view_literals; using std::chrono::seconds; using std::chrono::nanoseconds; -inline const char *GetLabelFromChannel(Channel channel) +[[nodiscard]] +auto GetLabelFromChannel(Channel channel) -> std::string_view { switch(channel) { - case FrontLeft: return "front-left"; - case FrontRight: return "front-right"; - case FrontCenter: return "front-center"; - case LFE: return "lfe"; - case BackLeft: return "back-left"; - case BackRight: return "back-right"; - case BackCenter: return "back-center"; - case SideLeft: return "side-left"; - case SideRight: return "side-right"; - - case TopFrontLeft: return "top-front-left"; - case TopFrontCenter: return "top-front-center"; - case TopFrontRight: return "top-front-right"; - case TopCenter: return "top-center"; - case TopBackLeft: return "top-back-left"; - case TopBackCenter: return "top-back-center"; - case TopBackRight: return "top-back-right"; - - case Aux0: return "Aux0"; - case Aux1: return "Aux1"; - case Aux2: return "Aux2"; - case Aux3: return "Aux3"; - case Aux4: return "Aux4"; - case Aux5: return "Aux5"; - case Aux6: return "Aux6"; - case Aux7: return "Aux7"; - case Aux8: return "Aux8"; - case Aux9: return "Aux9"; - case Aux10: return "Aux10"; - case Aux11: return "Aux11"; - case Aux12: return "Aux12"; - case Aux13: return "Aux13"; - case Aux14: return "Aux14"; - case Aux15: return "Aux15"; - - case MaxChannels: break; + case FrontLeft: return "front-left"sv; + case FrontRight: return "front-right"sv; + case FrontCenter: return "front-center"sv; + case LFE: return "lfe"sv; + case BackLeft: return "back-left"sv; + case BackRight: return "back-right"sv; + case BackCenter: return "back-center"sv; + case SideLeft: return "side-left"sv; + case SideRight: return "side-right"sv; + + case TopFrontLeft: return "top-front-left"sv; + case TopFrontCenter: return "top-front-center"sv; + case TopFrontRight: return "top-front-right"sv; + case TopCenter: return "top-center"sv; + case TopBackLeft: return "top-back-left"sv; + case TopBackCenter: return "top-back-center"sv; + case TopBackRight: return "top-back-right"sv; + + case BottomFrontLeft: return "bottom-front-left"sv; + case BottomFrontRight: return "bottom-front-right"sv; + case BottomBackLeft: return "bottom-back-left"sv; + case BottomBackRight: return "bottom-back-right"sv; + + case Aux0: return "Aux0"sv; + case Aux1: return "Aux1"sv; + case Aux2: return "Aux2"sv; + case Aux3: return "Aux3"sv; + case Aux4: return "Aux4"sv; + case Aux5: return "Aux5"sv; + case Aux6: return "Aux6"sv; + case Aux7: return "Aux7"sv; + case Aux8: return "Aux8"sv; + case Aux9: return "Aux9"sv; + case Aux10: return "Aux10"sv; + case Aux11: return "Aux11"sv; + case Aux12: return "Aux12"sv; + case Aux13: return "Aux13"sv; + case Aux14: return "Aux14"sv; + case Aux15: return "Aux15"sv; + + case MaxChannels: break; } - return "(unknown)"; + return "(unknown)"sv; +} + +[[nodiscard]] +auto GetLayoutName(DevAmbiLayout layout) noexcept -> std::string_view +{ + switch(layout) + { + case DevAmbiLayout::FuMa: return "FuMa"sv; + case DevAmbiLayout::ACN: return "ACN"sv; + } + return ""sv; +} + +[[nodiscard]] +auto GetScalingName(DevAmbiScaling scaling) noexcept -> std::string_view +{ + switch(scaling) + { + case DevAmbiScaling::FuMa: return "FuMa"sv; + case DevAmbiScaling::SN3D: return "SN3D"sv; + case DevAmbiScaling::N3D: return "N3D"sv; + } + return ""sv; } @@ -128,14 +164,14 @@ std::unique_ptr CreateStablizer(const size_t outchans, const uin return stablizer; } -void AllocChannels(ALCdevice *device, const size_t main_chans, const size_t real_chans) +void AllocChannels(al::Device *device, const size_t main_chans, const size_t real_chans) { - TRACE("Channel config, Main: %zu, Real: %zu\n", main_chans, real_chans); + TRACE("Channel config, Main: {}, Real: {}", main_chans, real_chans); /* Allocate extra channels for any post-filter output. */ const size_t num_chans{main_chans + real_chans}; - TRACE("Allocating %zu channels, %zu bytes\n", num_chans, + TRACE("Allocating {} channels, {} bytes", num_chans, num_chans*sizeof(device->MixBuffer[0])); device->MixBuffer.resize(num_chans); al::span buffer{device->MixBuffer}; @@ -227,43 +263,48 @@ struct DecoderConfig { using DecoderView = DecoderConfig; -void InitNearFieldCtrl(ALCdevice *device, float ctrl_dist, uint order, bool is3d) +void InitNearFieldCtrl(al::Device *device, const float ctrl_dist, const uint order, + const bool is3d) { - static const uint chans_per_order2d[MaxAmbiOrder+1]{ 1, 2, 2, 2 }; - static const uint chans_per_order3d[MaxAmbiOrder+1]{ 1, 3, 5, 7 }; + static const std::array chans_per_order2d{{1, 2, 2, 2}}; + static const std::array chans_per_order3d{{1, 3, 5, 7}}; /* NFC is only used when AvgSpeakerDist is greater than 0. */ if(!device->getConfigValueBool("decoder", "nfc", false) || !(ctrl_dist > 0.0f)) return; - device->AvgSpeakerDist = clampf(ctrl_dist, 0.1f, 10.0f); - TRACE("Using near-field reference distance: %.2f meters\n", device->AvgSpeakerDist); + device->AvgSpeakerDist = std::clamp(ctrl_dist, 0.1f, 10.0f); + TRACE("Using near-field reference distance: {:.2f} meters", device->AvgSpeakerDist); const float w1{SpeedOfSoundMetersPerSec / - (device->AvgSpeakerDist * static_cast(device->Frequency))}; + (device->AvgSpeakerDist * static_cast(device->mSampleRate))}; device->mNFCtrlFilter.init(w1); - auto iter = std::copy_n(is3d ? chans_per_order3d : chans_per_order2d, order+1u, - std::begin(device->NumChannelsPerOrder)); - std::fill(iter, std::end(device->NumChannelsPerOrder), 0u); + auto iter = std::copy_n(is3d ? chans_per_order3d.begin() : chans_per_order2d.begin(), order+1u, + device->NumChannelsPerOrder.begin()); + std::fill(iter, device->NumChannelsPerOrder.end(), 0u); } -void InitDistanceComp(ALCdevice *device, const al::span channels, - const al::span dists) +void InitDistanceComp(al::Device *device, const al::span channels, + const al::span dists) { - const float maxdist{std::accumulate(std::begin(dists), std::end(dists), 0.0f, maxf)}; + const float maxdist{std::accumulate(dists.begin(), dists.end(), 0.0f, + [](const float a, const float b) noexcept -> float { return std::max(a, b); })}; if(!device->getConfigValueBool("decoder", "distance-comp", true) || !(maxdist > 0.0f)) return; - const auto distSampleScale = static_cast(device->Frequency) / SpeedOfSoundMetersPerSec; - std::vector ChanDelay; + const auto distSampleScale = static_cast(device->mSampleRate)/SpeedOfSoundMetersPerSec; + + struct DistCoeffs { uint Length{}; float Gain{}; }; + std::vector ChanDelay; ChanDelay.reserve(device->RealOut.Buffer.size()); + size_t total{0u}; for(size_t chidx{0};chidx < channels.size();++chidx) { const Channel ch{channels[chidx]}; - const uint idx{device->RealOut.ChannelIndex[ch]}; + const size_t idx{device->RealOut.ChannelIndex[ch]}; if(idx == InvalidChannelIndex) continue; @@ -278,15 +319,15 @@ void InitDistanceComp(ALCdevice *device, const al::span channels, float delay{std::floor((maxdist - distance)*distSampleScale + 0.5f)}; if(delay > float{DistanceComp::MaxDelay-1}) { - ERR("Delay for channel %u (%s) exceeds buffer length (%f > %d)\n", idx, + ERR("Delay for channel {} ({}) exceeds buffer length ({:f} > {})", idx, GetLabelFromChannel(ch), delay, DistanceComp::MaxDelay-1); delay = float{DistanceComp::MaxDelay-1}; } - ChanDelay.resize(maxz(ChanDelay.size(), idx+1)); + ChanDelay.resize(std::max(ChanDelay.size(), idx+1_uz)); ChanDelay[idx].Length = static_cast(delay); ChanDelay[idx].Gain = distance / maxdist; - TRACE("Channel %s distance comp: %u samples, %f gain\n", GetLabelFromChannel(ch), + TRACE("Channel {} distance comp: {} samples, {:f} gain", GetLabelFromChannel(ch), ChanDelay[idx].Length, ChanDelay[idx].Gain); /* Round up to the next 4th sample, so each channel buffer starts @@ -298,16 +339,17 @@ void InitDistanceComp(ALCdevice *device, const al::span channels, if(total > 0) { auto chandelays = DistanceComp::Create(total); + auto chanbuffer = chandelays->mSamples.begin(); - ChanDelay[0].Buffer = chandelays->mSamples.data(); - auto set_bufptr = [](const DistanceComp::ChanData &last, const DistanceComp::ChanData &cur) - -> DistanceComp::ChanData + auto set_bufptr = [&chanbuffer](const DistCoeffs &data) { - DistanceComp::ChanData ret{cur}; - ret.Buffer = last.Buffer + RoundUp(last.Length, 4); + DistanceComp::ChanData ret{}; + ret.Buffer = al::span{chanbuffer, data.Length}; + ret.Gain = data.Gain; + chanbuffer += ptrdiff_t(RoundUp(data.Length, 4)); return ret; }; - std::partial_sum(ChanDelay.begin(), ChanDelay.end(), chandelays->mChannels.begin(), + std::transform(ChanDelay.begin(), ChanDelay.end(), chandelays->mChannels.begin(), set_bufptr); device->ChannelDelays = std::move(chandelays); } @@ -328,8 +370,8 @@ constexpr auto GetAmbiLayout(DevAmbiLayout layouttype) noexcept } -DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, - DecoderConfig &decoder) +auto MakeDecoderView(al::Device *device, const AmbDecConf *conf, + DecoderConfig &decoder) -> DecoderView { DecoderView ret{}; @@ -346,23 +388,20 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, case AmbDecScale::FuMa: decoder.mScaling = DevAmbiScaling::FuMa; break; } - std::copy_n(std::begin(conf->HFOrderGain), - std::min(std::size(conf->HFOrderGain), std::size(decoder.mOrderGain)), - std::begin(decoder.mOrderGain)); - std::copy_n(std::begin(conf->LFOrderGain), - std::min(std::size(conf->LFOrderGain), std::size(decoder.mOrderGainLF)), - std::begin(decoder.mOrderGainLF)); + const auto hfordermin = std::min(conf->HFOrderGain.size(), decoder.mOrderGain.size()); + std::copy_n(conf->HFOrderGain.begin(), hfordermin, decoder.mOrderGain.begin()); + const auto lfordermin = std::min(conf->LFOrderGain.size(), decoder.mOrderGainLF.size()); + std::copy_n(conf->LFOrderGain.begin(), lfordermin, decoder.mOrderGainLF.begin()); const auto num_coeffs = decoder.mIs3D ? AmbiChannelsFromOrder(decoder.mOrder) : Ambi2DChannelsFromOrder(decoder.mOrder); - const auto idx_map = decoder.mIs3D ? AmbiIndex::FromACN.data() - : AmbiIndex::FromACN2D.data(); + const auto idx_map = decoder.mIs3D ? al::span{AmbiIndex::FromACN} + : al::span{AmbiIndex::FromACN2D}; const auto hfmatrix = conf->HFMatrix; const auto lfmatrix = conf->LFMatrix; uint chan_count{0}; - using const_speaker_span = al::span; - for(auto &speaker : const_speaker_span{conf->Speakers.get(), conf->NumSpeakers}) + for(auto &speaker : al::span{std::as_const(conf->Speakers)}) { /* NOTE: AmbDec does not define any standard speaker names, however * for this to work we have to by able to find the output channel @@ -381,44 +420,57 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, * RFT = Top front right * LBT = Top back left * RBT = Top back right + * LFB = Bottom front left + * RFB = Bottom front right + * LBB = Bottom back left + * RBB = Bottom back right * * Additionally, surround51 will acknowledge back speakers for side * channels, to avoid issues with an ambdec expecting 5.1 to use the * back channels. */ Channel ch{}; - if(speaker.Name == "LF") + if(speaker.Name == "LF"sv) ch = FrontLeft; - else if(speaker.Name == "RF") + else if(speaker.Name == "RF"sv) ch = FrontRight; - else if(speaker.Name == "CE") + else if(speaker.Name == "CE"sv) ch = FrontCenter; - else if(speaker.Name == "LS") + else if(speaker.Name == "LS"sv) ch = SideLeft; - else if(speaker.Name == "RS") + else if(speaker.Name == "RS"sv) ch = SideRight; - else if(speaker.Name == "LB") + else if(speaker.Name == "LB"sv) ch = (device->FmtChans == DevFmtX51) ? SideLeft : BackLeft; - else if(speaker.Name == "RB") + else if(speaker.Name == "RB"sv) ch = (device->FmtChans == DevFmtX51) ? SideRight : BackRight; - else if(speaker.Name == "CB") + else if(speaker.Name == "CB"sv) ch = BackCenter; - else if(speaker.Name == "LFT") + else if(speaker.Name == "LFT"sv) ch = TopFrontLeft; - else if(speaker.Name == "RFT") + else if(speaker.Name == "RFT"sv) ch = TopFrontRight; - else if(speaker.Name == "LBT") + else if(speaker.Name == "LBT"sv) ch = TopBackLeft; - else if(speaker.Name == "RBT") + else if(speaker.Name == "RBT"sv) ch = TopBackRight; + else if(speaker.Name == "LFB"sv) + ch = BottomFrontLeft; + else if(speaker.Name == "RFB"sv) + ch = BottomFrontRight; + else if(speaker.Name == "LBB"sv) + ch = BottomBackLeft; + else if(speaker.Name == "RBB"sv) + ch = BottomBackRight; else { int idx{}; char c{}; + /* NOLINTNEXTLINE(cert-err34-c,cppcoreguidelines-pro-type-vararg) */ if(sscanf(speaker.Name.c_str(), "AUX%d%c", &idx, &c) != 1 || idx < 0 || idx >= MaxChannels-Aux0) { - ERR("AmbDec speaker label \"%s\" not recognized\n", speaker.Name.c_str()); + ERR("AmbDec speaker label \"{}\" not recognized", speaker.Name); continue; } ch = static_cast(Aux0+idx); @@ -446,13 +498,13 @@ DecoderView MakeDecoderView(ALCdevice *device, const AmbDecConf *conf, ret.mOrder = decoder.mOrder; ret.mIs3D = decoder.mIs3D; ret.mScaling = decoder.mScaling; - ret.mChannels = {decoder.mChannels.data(), chan_count}; + ret.mChannels = al::span{decoder.mChannels}.first(chan_count); ret.mOrderGain = decoder.mOrderGain; - ret.mCoeffs = {decoder.mCoeffs.data(), chan_count}; + ret.mCoeffs = al::span{decoder.mCoeffs}.first(chan_count); if(conf->FreqBands > 1) { ret.mOrderGainLF = decoder.mOrderGainLF; - ret.mCoeffsLF = {decoder.mCoeffsLF.data(), chan_count}; + ret.mCoeffsLF = al::span{decoder.mCoeffsLF}.first(chan_count); } } return ret; @@ -584,8 +636,46 @@ constexpr DecoderConfig X714Config{ {{8.80892603e-02f, -7.48948724e-02f, 9.08779842e-02f, -6.22480443e-02f}}, }} }; +constexpr DecoderConfig X7144Config{ + 1, true, {{BackLeft, SideLeft, FrontLeft, FrontRight, SideRight, BackRight, TopBackLeft, TopFrontLeft, TopFrontRight, TopBackRight, BottomBackLeft, BottomFrontLeft, BottomFrontRight, BottomBackRight}}, + DevAmbiScaling::N3D, + /*HF*/{{2.64575131e+0f, 1.52752523e+0f}}, + {{ + {{7.14285714e-02f, 5.09426708e-02f, 0.00000000e+00f, -8.82352941e-02f}}, + {{7.14285714e-02f, 1.01885342e-01f, 0.00000000e+00f, 0.00000000e+00f}}, + {{7.14285714e-02f, 5.09426708e-02f, 0.00000000e+00f, 8.82352941e-02f}}, + {{7.14285714e-02f, -5.09426708e-02f, 0.00000000e+00f, 8.82352941e-02f}}, + {{7.14285714e-02f, -1.01885342e-01f, 0.00000000e+00f, 0.00000000e+00f}}, + {{7.14285714e-02f, -5.09426708e-02f, 0.00000000e+00f, -8.82352941e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, 1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, 1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, 1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, 1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, -1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, -1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, -1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, -1.25000000e-01f, -5.88235294e-02f}}, + }}, + /*LF*/{{1.00000000e+0f, 1.00000000e+0f}}, + {{ + {{7.14285714e-02f, 5.09426708e-02f, 0.00000000e+00f, -8.82352941e-02f}}, + {{7.14285714e-02f, 1.01885342e-01f, 0.00000000e+00f, 0.00000000e+00f}}, + {{7.14285714e-02f, 5.09426708e-02f, 0.00000000e+00f, 8.82352941e-02f}}, + {{7.14285714e-02f, -5.09426708e-02f, 0.00000000e+00f, 8.82352941e-02f}}, + {{7.14285714e-02f, -1.01885342e-01f, 0.00000000e+00f, 0.00000000e+00f}}, + {{7.14285714e-02f, -5.09426708e-02f, 0.00000000e+00f, -8.82352941e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, 1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, 1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, 1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, 1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, -1.25000000e-01f, -5.88235294e-02f}}, + {{7.14285714e-02f, 5.88235294e-02f, -1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, -1.25000000e-01f, 5.88235294e-02f}}, + {{7.14285714e-02f, -5.88235294e-02f, -1.25000000e-01f, -5.88235294e-02f}}, + }} +}; -void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize=false, +void InitPanning(al::Device *device, const bool hqdec=false, const bool stablize=false, DecoderView decoder={}) { if(!decoder) @@ -599,14 +689,15 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= case DevFmtX61: decoder = X61Config; break; case DevFmtX71: decoder = X71Config; break; case DevFmtX714: decoder = X714Config; break; + case DevFmtX7144: decoder = X7144Config; break; case DevFmtX3D71: decoder = X3D71Config; break; case DevFmtAmbi3D: - const auto acnmap = GetAmbiLayout(device->mAmbiLayout); - const auto n3dscale = GetAmbiScales(device->mAmbiScale); - /* For DevFmtAmbi3D, the ambisonic order is already set. */ const size_t count{AmbiChannelsFromOrder(device->mAmbiOrder)}; - std::transform(acnmap.begin(), acnmap.begin()+count, std::begin(device->Dry.AmbiMap), + const auto acnmap = GetAmbiLayout(device->mAmbiLayout).first(count); + const auto n3dscale = GetAmbiScales(device->mAmbiScale); + + std::transform(acnmap.cbegin(), acnmap.cend(), device->Dry.AmbiMap.begin(), [n3dscale](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f/n3dscale[acn], acn}; }); AllocChannels(device, count, 0); @@ -617,10 +708,13 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= avg_dist = *distopt; else if(auto delayopt = device->configValue("decoder", "nfc-ref-delay")) { - WARN("nfc-ref-delay is deprecated, use speaker-dist instead\n"); + WARN("nfc-ref-delay is deprecated, use speaker-dist instead"); avg_dist = *delayopt * SpeedOfSoundMetersPerSec; } + TRACE("{}{} order ambisonic output ({} layout, {} scaling)", device->mAmbiOrder, + GetCounterSuffix(device->mAmbiOrder), GetLayoutName(device->mAmbiLayout), + GetScalingName(device->mAmbiScale)); InitNearFieldCtrl(device, avg_dist, device->mAmbiOrder, true); return; } @@ -632,18 +726,18 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= std::vector chancoeffs, chancoeffslf; for(size_t i{0u};i < decoder.mChannels.size();++i) { - const uint idx{device->channelIdxByName(decoder.mChannels[i])}; + const size_t idx{device->channelIdxByName(decoder.mChannels[i])}; if(idx == InvalidChannelIndex) { - ERR("Failed to find %s channel in device\n", + ERR("Failed to find {} channel in device", GetLabelFromChannel(decoder.mChannels[i])); continue; } - auto ordermap = decoder.mIs3D ? AmbiIndex::OrderFromChannel.data() - : AmbiIndex::OrderFrom2DChannel.data(); + auto ordermap = decoder.mIs3D ? al::span{AmbiIndex::OrderFromChannel} + : al::span{AmbiIndex::OrderFrom2DChannel}; - chancoeffs.resize(maxz(chancoeffs.size(), idx+1u), ChannelDec{}); + chancoeffs.resize(std::max(chancoeffs.size(), idx+1_zu), ChannelDec{}); al::span src{decoder.mCoeffs[i]}; al::span dst{chancoeffs[idx]}; for(size_t ambichan{0};ambichan < ambicount;++ambichan) @@ -652,7 +746,7 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= if(!dual_band) continue; - chancoeffslf.resize(maxz(chancoeffslf.size(), idx+1u), ChannelDec{}); + chancoeffslf.resize(std::max(chancoeffslf.size(), idx+1_zu), ChannelDec{}); src = decoder.mCoeffsLF[i]; dst = chancoeffslf[idx]; for(size_t ambichan{0};ambichan < ambicount;++ambichan) @@ -663,10 +757,10 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= device->mAmbiOrder = decoder.mOrder; device->m2DMixing = !decoder.mIs3D; - const al::span acnmap{decoder.mIs3D ? AmbiIndex::FromACN.data() : - AmbiIndex::FromACN2D.data(), ambicount}; + const auto acnmap = decoder.mIs3D ? al::span{AmbiIndex::FromACN}.first(ambicount) + : al::span{AmbiIndex::FromACN2D}.first(ambicount); const auto coeffscale = GetAmbiScales(decoder.mScaling); - std::transform(acnmap.begin(), acnmap.end(), std::begin(device->Dry.AmbiMap), + std::transform(acnmap.begin(), acnmap.end(), device->Dry.AmbiMap.begin(), [coeffscale](const uint8_t &acn) noexcept { return BFChannelConfig{1.0f/coeffscale[acn], acn}; }); AllocChannels(device, ambicount, device->channelsFromFmt()); @@ -677,7 +771,7 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= /* Only enable the stablizer if the decoder does not output to the * front-center channel. */ - const auto cidx = device->RealOut.ChannelIndex[FrontCenter]; + const size_t cidx{device->RealOut.ChannelIndex[FrontCenter]}; bool hasfc{false}; if(cidx < chancoeffs.size()) { @@ -691,137 +785,142 @@ void InitPanning(ALCdevice *device, const bool hqdec=false, const bool stablize= } if(!hasfc) { - stablizer = CreateStablizer(device->channelsFromFmt(), device->Frequency); - TRACE("Front stablizer enabled\n"); + stablizer = CreateStablizer(device->channelsFromFmt(), device->mSampleRate); + TRACE("Front stablizer enabled"); } } - TRACE("Enabling %s-band %s-order%s ambisonic decoder\n", - !dual_band ? "single" : "dual", + TRACE("Enabling {}-band {}-order{} ambisonic decoder", !dual_band ? "single" : "dual", (decoder.mOrder > 3) ? "fourth" : (decoder.mOrder > 2) ? "third" : (decoder.mOrder > 1) ? "second" : "first", decoder.mIs3D ? " periphonic" : ""); device->AmbiDecoder = BFormatDec::Create(ambicount, chancoeffs, chancoeffslf, - device->mXOverFreq/static_cast(device->Frequency), std::move(stablizer)); + device->mXOverFreq/static_cast(device->mSampleRate), std::move(stablizer)); } -void InitHrtfPanning(ALCdevice *device) +void InitHrtfPanning(al::Device *device) { - constexpr float Deg180{al::numbers::pi_v}; - constexpr float Deg_90{Deg180 / 2.0f /* 90 degrees*/}; - constexpr float Deg_45{Deg_90 / 2.0f /* 45 degrees*/}; - constexpr float Deg135{Deg_45 * 3.0f /*135 degrees*/}; - constexpr float Deg_21{3.648638281e-01f /* 20~ 21 degrees*/}; - constexpr float Deg_32{5.535743589e-01f /* 31~ 32 degrees*/}; - constexpr float Deg_35{6.154797087e-01f /* 35~ 36 degrees*/}; - constexpr float Deg_58{1.017221968e+00f /* 58~ 59 degrees*/}; - constexpr float Deg_69{1.205932499e+00f /* 69~ 70 degrees*/}; - constexpr float Deg111{1.935660155e+00f /*110~111 degrees*/}; - constexpr float Deg122{2.124370686e+00f /*121~122 degrees*/}; - static const AngularPoint AmbiPoints1O[]{ - { EvRadians{ Deg_35}, AzRadians{-Deg_45} }, - { EvRadians{ Deg_35}, AzRadians{-Deg135} }, - { EvRadians{ Deg_35}, AzRadians{ Deg_45} }, - { EvRadians{ Deg_35}, AzRadians{ Deg135} }, - { EvRadians{-Deg_35}, AzRadians{-Deg_45} }, - { EvRadians{-Deg_35}, AzRadians{-Deg135} }, - { EvRadians{-Deg_35}, AzRadians{ Deg_45} }, - { EvRadians{-Deg_35}, AzRadians{ Deg135} }, - }, AmbiPoints2O[]{ - { EvRadians{-Deg_32}, AzRadians{ 0.0f} }, - { EvRadians{ 0.0f}, AzRadians{ Deg_58} }, - { EvRadians{ Deg_58}, AzRadians{ Deg_90} }, - { EvRadians{ Deg_32}, AzRadians{ 0.0f} }, - { EvRadians{ 0.0f}, AzRadians{ Deg122} }, - { EvRadians{-Deg_58}, AzRadians{-Deg_90} }, - { EvRadians{-Deg_32}, AzRadians{ Deg180} }, - { EvRadians{ 0.0f}, AzRadians{-Deg122} }, - { EvRadians{ Deg_58}, AzRadians{-Deg_90} }, - { EvRadians{ Deg_32}, AzRadians{ Deg180} }, - { EvRadians{ 0.0f}, AzRadians{-Deg_58} }, - { EvRadians{-Deg_58}, AzRadians{ Deg_90} }, - }, AmbiPoints3O[]{ - { EvRadians{ Deg_69}, AzRadians{-Deg_90} }, - { EvRadians{ Deg_69}, AzRadians{ Deg_90} }, - { EvRadians{-Deg_69}, AzRadians{-Deg_90} }, - { EvRadians{-Deg_69}, AzRadians{ Deg_90} }, - { EvRadians{ 0.0f}, AzRadians{-Deg_69} }, - { EvRadians{ 0.0f}, AzRadians{-Deg111} }, - { EvRadians{ 0.0f}, AzRadians{ Deg_69} }, - { EvRadians{ 0.0f}, AzRadians{ Deg111} }, - { EvRadians{ Deg_21}, AzRadians{ 0.0f} }, - { EvRadians{ Deg_21}, AzRadians{ Deg180} }, - { EvRadians{-Deg_21}, AzRadians{ 0.0f} }, - { EvRadians{-Deg_21}, AzRadians{ Deg180} }, - { EvRadians{ Deg_35}, AzRadians{-Deg_45} }, - { EvRadians{ Deg_35}, AzRadians{-Deg135} }, - { EvRadians{ Deg_35}, AzRadians{ Deg_45} }, - { EvRadians{ Deg_35}, AzRadians{ Deg135} }, - { EvRadians{-Deg_35}, AzRadians{-Deg_45} }, - { EvRadians{-Deg_35}, AzRadians{-Deg135} }, - { EvRadians{-Deg_35}, AzRadians{ Deg_45} }, - { EvRadians{-Deg_35}, AzRadians{ Deg135} }, + static constexpr float Deg180{al::numbers::pi_v}; + static constexpr float Deg_90{Deg180 / 2.0f /* 90 degrees*/}; + static constexpr float Deg_45{Deg_90 / 2.0f /* 45 degrees*/}; + static constexpr float Deg135{Deg_45 * 3.0f /*135 degrees*/}; + static constexpr float Deg_21{3.648638281e-01f /* 20~ 21 degrees*/}; + static constexpr float Deg_32{5.535743589e-01f /* 31~ 32 degrees*/}; + static constexpr float Deg_35{6.154797087e-01f /* 35~ 36 degrees*/}; + static constexpr float Deg_58{1.017221968e+00f /* 58~ 59 degrees*/}; + static constexpr float Deg_69{1.205932499e+00f /* 69~ 70 degrees*/}; + static constexpr float Deg111{1.935660155e+00f /*110~111 degrees*/}; + static constexpr float Deg122{2.124370686e+00f /*121~122 degrees*/}; + static constexpr std::array AmbiPoints1O{ + AngularPoint{EvRadians{ Deg_35}, AzRadians{-Deg_45}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{-Deg135}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{ Deg_45}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{ Deg135}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{-Deg_45}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{-Deg135}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{ Deg_45}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{ Deg135}}, + }; + static constexpr std::array AmbiPoints2O{ + AngularPoint{EvRadians{-Deg_32}, AzRadians{ 0.0f}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{ Deg_58}}, + AngularPoint{EvRadians{ Deg_58}, AzRadians{ Deg_90}}, + AngularPoint{EvRadians{ Deg_32}, AzRadians{ 0.0f}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{ Deg122}}, + AngularPoint{EvRadians{-Deg_58}, AzRadians{-Deg_90}}, + AngularPoint{EvRadians{-Deg_32}, AzRadians{ Deg180}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{-Deg122}}, + AngularPoint{EvRadians{ Deg_58}, AzRadians{-Deg_90}}, + AngularPoint{EvRadians{ Deg_32}, AzRadians{ Deg180}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{-Deg_58}}, + AngularPoint{EvRadians{-Deg_58}, AzRadians{ Deg_90}}, + }; + static constexpr std::array AmbiPoints3O{ + AngularPoint{EvRadians{ Deg_69}, AzRadians{-Deg_90}}, + AngularPoint{EvRadians{ Deg_69}, AzRadians{ Deg_90}}, + AngularPoint{EvRadians{-Deg_69}, AzRadians{-Deg_90}}, + AngularPoint{EvRadians{-Deg_69}, AzRadians{ Deg_90}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{-Deg_69}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{-Deg111}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{ Deg_69}}, + AngularPoint{EvRadians{ 0.0f}, AzRadians{ Deg111}}, + AngularPoint{EvRadians{ Deg_21}, AzRadians{ 0.0f}}, + AngularPoint{EvRadians{ Deg_21}, AzRadians{ Deg180}}, + AngularPoint{EvRadians{-Deg_21}, AzRadians{ 0.0f}}, + AngularPoint{EvRadians{-Deg_21}, AzRadians{ Deg180}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{-Deg_45}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{-Deg135}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{ Deg_45}}, + AngularPoint{EvRadians{ Deg_35}, AzRadians{ Deg135}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{-Deg_45}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{-Deg135}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{ Deg_45}}, + AngularPoint{EvRadians{-Deg_35}, AzRadians{ Deg135}}, }; - static const float AmbiMatrix1O[][MaxAmbiChannels]{ - { 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f }, - { 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f }, - { 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f }, - { 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f }, - { 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f }, - { 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f }, - { 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f }, - { 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f }, - }, AmbiMatrix2O[][MaxAmbiChannels]{ - { 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }, - { 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }, - { 8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }, - { 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }, - { 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }, - { 8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }, - { 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }, - { 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }, - { 8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }, - { 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }, - { 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }, - { 8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }, - }, AmbiMatrix3O[][MaxAmbiChannels]{ - { 5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }, - { 5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }, - { 5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }, - { 5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }, - { 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }, - { 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }, - { 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }, - { 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }, - { 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f, }, - { 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f, }, - { 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f, }, - { 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f, }, - { 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }, - { 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }, - { 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }, - { 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }, - { 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }, - { 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }, - { 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }, - { 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }, + static constexpr std::array AmbiMatrix1O{ + ChannelCoeffs{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + ChannelCoeffs{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, }; - static const float AmbiOrderHFGain1O[MaxAmbiOrder+1]{ + static constexpr std::array AmbiMatrix2O{ + ChannelCoeffs{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + ChannelCoeffs{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + ChannelCoeffs{8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + ChannelCoeffs{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + ChannelCoeffs{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + ChannelCoeffs{8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + ChannelCoeffs{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + ChannelCoeffs{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + ChannelCoeffs{8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + ChannelCoeffs{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + ChannelCoeffs{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + ChannelCoeffs{8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + }; + static constexpr std::array AmbiMatrix3O{ + ChannelCoeffs{5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + ChannelCoeffs{5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + ChannelCoeffs{5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + ChannelCoeffs{5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + ChannelCoeffs{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + ChannelCoeffs{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + ChannelCoeffs{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + ChannelCoeffs{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + ChannelCoeffs{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f}, + ChannelCoeffs{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f}, + ChannelCoeffs{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f}, + ChannelCoeffs{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f}, + ChannelCoeffs{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + ChannelCoeffs{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, + }; + static constexpr std::array AmbiOrderHFGain1O{ /*ENRGY*/ 2.000000000e+00f, 1.154700538e+00f - }, AmbiOrderHFGain2O[MaxAmbiOrder+1]{ + }; + static constexpr std::array AmbiOrderHFGain2O{ /*ENRGY*/ 1.825741858e+00f, 1.414213562e+00f, 7.302967433e-01f /*AMP 1.000000000e+00f, 7.745966692e-01f, 4.000000000e-01f*/ /*RMS 9.128709292e-01f, 7.071067812e-01f, 3.651483717e-01f*/ - }, AmbiOrderHFGain3O[MaxAmbiOrder+1]{ + }; + static constexpr std::array AmbiOrderHFGain3O{ /*ENRGY 1.865086714e+00f, 1.606093894e+00f, 1.142055301e+00f, 5.683795528e-01f*/ /*AMP*/ 1.000000000e+00f, 8.611363116e-01f, 6.123336207e-01f, 3.047469850e-01f /*RMS 8.340921354e-01f, 7.182670250e-01f, 5.107426573e-01f, 2.541870634e-01f*/ }; - static_assert(std::size(AmbiPoints1O) == std::size(AmbiMatrix1O), "First-Order Ambisonic HRTF mismatch"); - static_assert(std::size(AmbiPoints2O) == std::size(AmbiMatrix2O), "Second-Order Ambisonic HRTF mismatch"); - static_assert(std::size(AmbiPoints3O) == std::size(AmbiMatrix3O), "Third-Order Ambisonic HRTF mismatch"); + static_assert(AmbiPoints1O.size() == AmbiMatrix1O.size(), "First-Order Ambisonic HRTF mismatch"); + static_assert(AmbiPoints2O.size() == AmbiMatrix2O.size(), "Second-Order Ambisonic HRTF mismatch"); + static_assert(AmbiPoints3O.size() == AmbiMatrix3O.size(), "Third-Order Ambisonic HRTF mismatch"); /* A 700hz crossover frequency provides tighter sound imaging at the sweet * spot with ambisonic decoding, as the distance between the ears is closer @@ -841,50 +940,46 @@ void InitHrtfPanning(ALCdevice *device) */ device->mRenderMode = RenderMode::Hrtf; uint ambi_order{1}; - if(auto modeopt = device->configValue(nullptr, "hrtf-mode")) + if(auto modeopt = device->configValue({}, "hrtf-mode")) { struct HrtfModeEntry { - char name[8]; + std::string_view name; RenderMode mode; uint order; }; - static const HrtfModeEntry hrtf_modes[]{ - { "full", RenderMode::Hrtf, 1 }, - { "ambi1", RenderMode::Normal, 1 }, - { "ambi2", RenderMode::Normal, 2 }, - { "ambi3", RenderMode::Normal, 3 }, + constexpr std::array hrtf_modes{ + HrtfModeEntry{"full"sv, RenderMode::Hrtf, 1}, + HrtfModeEntry{"ambi1"sv, RenderMode::Normal, 1}, + HrtfModeEntry{"ambi2"sv, RenderMode::Normal, 2}, + HrtfModeEntry{"ambi3"sv, RenderMode::Normal, 3}, }; - const char *mode{modeopt->c_str()}; - if(al::strcasecmp(mode, "basic") == 0) + std::string_view mode{*modeopt}; + if(al::case_compare(mode, "basic"sv) == 0) { - ERR("HRTF mode \"%s\" deprecated, substituting \"%s\"\n", mode, "ambi2"); + ERR("HRTF mode \"{}\" deprecated, substituting \"{}\"", *modeopt, "ambi2"); mode = "ambi2"; } auto match_entry = [mode](const HrtfModeEntry &entry) -> bool - { return al::strcasecmp(mode, entry.name) == 0; }; - auto iter = std::find_if(std::begin(hrtf_modes), std::end(hrtf_modes), match_entry); - if(iter == std::end(hrtf_modes)) - ERR("Unexpected hrtf-mode: %s\n", mode); + { return al::case_compare(mode, entry.name) == 0; }; + auto iter = std::find_if(hrtf_modes.begin(), hrtf_modes.end(), match_entry); + if(iter == hrtf_modes.end()) + ERR("Unexpected hrtf-mode: {}", *modeopt); else { device->mRenderMode = iter->mode; ambi_order = iter->order; } } - TRACE("%u%s order %sHRTF rendering enabled, using \"%s\"\n", ambi_order, - (((ambi_order%100)/10) == 1) ? "th" : - ((ambi_order%10) == 1) ? "st" : - ((ambi_order%10) == 2) ? "nd" : - ((ambi_order%10) == 3) ? "rd" : "th", - (device->mRenderMode == RenderMode::Hrtf) ? "+ Full " : "", - device->mHrtfName.c_str()); + TRACE("{}{} order {}HRTF rendering enabled, using \"{}\"", ambi_order, + GetCounterSuffix(ambi_order), (device->mRenderMode == RenderMode::Hrtf) ? "+ Full " : "", + device->mHrtfName); bool perHrirMin{false}; - al::span AmbiPoints{AmbiPoints1O}; - const float (*AmbiMatrix)[MaxAmbiChannels]{AmbiMatrix1O}; - al::span AmbiOrderHFGain{AmbiOrderHFGain1O}; + auto AmbiPoints = al::span{AmbiPoints1O}.subspan(0); + auto AmbiMatrix = al::span{AmbiMatrix1O}.subspan(0); + auto AmbiOrderHFGain = al::span{AmbiOrderHFGain1O}; if(ambi_order >= 3) { perHrirMin = true; @@ -902,10 +997,9 @@ void InitHrtfPanning(ALCdevice *device) device->m2DMixing = false; const size_t count{AmbiChannelsFromOrder(ambi_order)}; - std::transform(AmbiIndex::FromACN.begin(), AmbiIndex::FromACN.begin()+count, - std::begin(device->Dry.AmbiMap), - [](const uint8_t &index) noexcept { return BFChannelConfig{1.0f, index}; } - ); + const auto acnmap = al::span{AmbiIndex::FromACN}.first(count); + std::transform(acnmap.begin(), acnmap.end(), device->Dry.AmbiMap.begin(), + [](const uint8_t &index) noexcept { return BFChannelConfig{1.0f, index}; }); AllocChannels(device, count, device->channelsFromFmt()); HrtfStore *Hrtf{device->mHrtf.get()}; @@ -917,24 +1011,34 @@ void InitHrtfPanning(ALCdevice *device) InitNearFieldCtrl(device, Hrtf->mFields[0].distance, ambi_order, true); } -void InitUhjPanning(ALCdevice *device) +void InitUhjPanning(al::Device *device) { /* UHJ is always 2D first-order. */ - constexpr size_t count{Ambi2DChannelsFromOrder(1)}; + static constexpr size_t count{Ambi2DChannelsFromOrder(1)}; device->mAmbiOrder = 1; device->m2DMixing = true; - auto acnmap_begin = AmbiIndex::FromFuMa2D.begin(); - std::transform(acnmap_begin, acnmap_begin + count, std::begin(device->Dry.AmbiMap), + const auto acnmap = al::span{AmbiIndex::FromFuMa2D}.first(); + std::transform(acnmap.cbegin(), acnmap.cend(), device->Dry.AmbiMap.begin(), [](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f/AmbiScale::FromUHJ[acn], acn}; }); AllocChannels(device, count, device->channelsFromFmt()); + + /* TODO: Should this default to something else? This is simply a regular + * (first-order) B-Format mixing which just happens to be UHJ-encoded. As I + * understand it, a proper first-order B-Format signal essentially has an + * infinite control distance, which we can't really do. However, from what + * I've read, 2 meters or so should be sufficient as the near-field + * reference becomes inconsequential beyond that. + */ + const auto spkr_dist = ConfigValueFloat({}, "uhj"sv, "distance-ref"sv).value_or(2.0f); + InitNearFieldCtrl(device, spkr_dist, device->mAmbiOrder, !device->m2DMixing); } } // namespace -void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional stereomode) +void aluInitRenderer(al::Device *device, int hrtf_id, std::optional stereomode) { /* Hold the HRTF the device last used, in case it's used again. */ HrtfStorePtr old_hrtf{std::move(device->mHrtf)}; @@ -961,6 +1065,7 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional> decoder_store; + std::unique_ptr> decoder_store; DecoderView decoder{}; - float speakerdists[MAX_OUTPUT_CHANNELS]{}; + std::array speakerdists{}; auto load_config = [device,&decoder_store,&decoder,&speakerdists](const char *config) { AmbDecConf conf{}; if(auto err = conf.load(config)) { - ERR("Failed to load layout file %s\n", config); - ERR(" %s\n", err->c_str()); + ERR("Failed to load layout file {}", config); + ERR(" {}", *err); return false; } - else if(conf.NumSpeakers > MAX_OUTPUT_CHANNELS) + if(conf.Speakers.size() > MaxOutputChannels) { - ERR("Unsupported decoder speaker count %zu (max %d)\n", conf.NumSpeakers, - MAX_OUTPUT_CHANNELS); + ERR("Unsupported decoder speaker count {} (max {})", conf.Speakers.size(), + MaxOutputChannels); return false; } - else if(conf.ChanMask > Ambi3OrderMask) + if(conf.ChanMask > Ambi3OrderMask) { - ERR("Unsupported decoder channel mask 0x%04x (max 0x%x)\n", conf.ChanMask, + ERR("Unsupported decoder channel mask {:#x} (max {:#x})", conf.ChanMask, Ambi3OrderMask); return false; } - TRACE("Using %s decoder: \"%s\"\n", DevFmtChannelsString(device->FmtChans), - conf.Description.c_str()); - device->mXOverFreq = clampf(conf.XOverFreq, 100.0f, 1000.0f); + TRACE("Using {} decoder: \"{}\"", DevFmtChannelsString(device->FmtChans), + conf.Description); + device->mXOverFreq = std::clamp(conf.XOverFreq, 100.0f, 1000.0f); - decoder_store = std::make_unique>(); + decoder_store = std::make_unique>(); decoder = MakeDecoderView(device, &conf, *decoder_store); - for(size_t i{0};i < decoder.mChannels.size();++i) - speakerdists[i] = conf.Speakers[i].Distance; + + const auto confspeakers = al::span{std::as_const(conf.Speakers)} + .first(decoder.mChannels.size()); + std::transform(confspeakers.cbegin(), confspeakers.cend(), speakerdists.begin(), + std::mem_fn(&AmbDecConf::SpeakerConf::Distance)); return true; }; bool usingCustom{false}; @@ -1011,7 +1119,7 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalc_str()); } if(!usingCustom && device->FmtChans != DevFmtAmbi3D) - TRACE("Using built-in %s decoder\n", DevFmtChannelsString(device->FmtChans)); + TRACE("Using built-in {} decoder", DevFmtChannelsString(device->FmtChans)); /* Enable the stablizer only for formats that have front-left, front- * right, and front-center outputs. @@ -1019,8 +1127,8 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalRealOut.ChannelIndex[FrontCenter] != InvalidChannelIndex && device->RealOut.ChannelIndex[FrontLeft] != InvalidChannelIndex && device->RealOut.ChannelIndex[FrontRight] != InvalidChannelIndex - && device->getConfigValueBool(nullptr, "front-stablizer", false) != 0}; - const bool hqdec{device->getConfigValueBool("decoder", "hq-mode", true) != 0}; + && device->getConfigValueBool({}, "front-stablizer", false)}; + const bool hqdec{device->getConfigValueBool("decoder", "hq-mode", true)}; InitPanning(device, hqdec, stablize, decoder); if(decoder) { @@ -1043,8 +1151,8 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalAmbiDecoder.get()}) { - device->PostProcess = ambidec->hasStablizer() ? &ALCdevice::ProcessAmbiDecStablized - : &ALCdevice::ProcessAmbiDec; + device->PostProcess = ambidec->hasStablizer() ? &al::Device::ProcessAmbiDecStablized + : &al::Device::ProcessAmbiDec; } return; } @@ -1061,8 +1169,8 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optional= 0 && static_cast(hrtf_id) < device->mHrtfList.size()) { - const std::string &hrtfname = device->mHrtfList[static_cast(hrtf_id)]; - if(HrtfStorePtr hrtf{GetLoadedHrtf(hrtfname, device->Frequency)}) + const std::string_view hrtfname{device->mHrtfList[static_cast(hrtf_id)]}; + if(HrtfStorePtr hrtf{GetLoadedHrtf(hrtfname, device->mSampleRate)}) { device->mHrtf = std::move(hrtf); device->mHrtfName = hrtfname; @@ -1071,9 +1179,9 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalmHrtf) { - for(const auto &hrtfname : device->mHrtfList) + for(const std::string_view hrtfname : device->mHrtfList) { - if(HrtfStorePtr hrtf{GetLoadedHrtf(hrtfname, device->Frequency)}) + if(HrtfStorePtr hrtf{GetLoadedHrtf(hrtfname, device->mSampleRate)}) { device->mHrtf = std::move(hrtf); device->mHrtfName = hrtfname; @@ -1088,14 +1196,14 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalmHrtf.get()}; device->mIrSize = hrtf->mIrSize; - if(auto hrtfsizeopt = device->configValue(nullptr, "hrtf-size")) + if(auto hrtfsizeopt = device->configValue({}, "hrtf-size")) { if(*hrtfsizeopt > 0 && *hrtfsizeopt < device->mIrSize) - device->mIrSize = maxu(*hrtfsizeopt, MinIrLength); + device->mIrSize = std::max(*hrtfsizeopt, MinIrLength); } InitHrtfPanning(device); - device->PostProcess = &ALCdevice::ProcessHrtf; + device->PostProcess = &al::Device::ProcessHrtf; device->mHrtfStatus = ALC_HRTF_ENABLED_SOFT; return; } @@ -1104,47 +1212,51 @@ void aluInitRenderer(ALCdevice *device, int hrtf_id, std::optionalmUhjEncoder = std::make_unique(); + ftype = "IIR"sv; break; case UhjQualityType::FIR256: device->mUhjEncoder = std::make_unique>(); + ftype = "FIR-256"sv; break; case UhjQualityType::FIR512: device->mUhjEncoder = std::make_unique>(); + ftype = "FIR-512"sv; break; } assert(device->mUhjEncoder != nullptr); - TRACE("UHJ enabled\n"); + TRACE("UHJ enabled ({} encoder)", ftype); InitUhjPanning(device); - device->PostProcess = &ALCdevice::ProcessUhj; + device->PostProcess = &al::Device::ProcessUhj; return; } device->mRenderMode = RenderMode::Pairwise; if(device->Type != DeviceType::Loopback) { - if(auto cflevopt = device->configValue(nullptr, "cf_level")) + if(auto cflevopt = device->configValue({}, "cf_level")) { if(*cflevopt > 0 && *cflevopt <= 6) { - device->Bs2b = std::make_unique(); - bs2b_set_params(device->Bs2b.get(), *cflevopt, - static_cast(device->Frequency)); - TRACE("BS2B enabled\n"); + auto bs2b = std::make_unique(); + bs2b->set_params(*cflevopt, static_cast(device->mSampleRate)); + device->Bs2b = std::move(bs2b); + TRACE("BS2B enabled"); InitPanning(device); - device->PostProcess = &ALCdevice::ProcessBs2b; + device->PostProcess = &al::Device::ProcessBs2b; return; } } } - TRACE("Stereo rendering\n"); + TRACE("Stereo rendering"); InitPanning(device); - device->PostProcess = &ALCdevice::ProcessAmbiDec; + device->PostProcess = &al::Device::ProcessAmbiDec; } @@ -1155,10 +1267,9 @@ void aluInitEffectPanning(EffectSlot *slot, ALCcontext *context) slot->mWetBuffer.resize(count); - auto acnmap_begin = AmbiIndex::FromACN.begin(); - auto iter = std::transform(acnmap_begin, acnmap_begin + count, slot->Wet.AmbiMap.begin(), - [](const uint8_t &acn) noexcept -> BFChannelConfig - { return BFChannelConfig{1.0f, acn}; }); + const auto acnmap = al::span{AmbiIndex::FromACN}.first(count); + const auto iter = std::transform(acnmap.cbegin(), acnmap.cend(), slot->Wet.AmbiMap.begin(), + [](const uint8_t &acn) noexcept -> BFChannelConfig { return BFChannelConfig{1.0f, acn}; }); std::fill(iter, slot->Wet.AmbiMap.end(), BFChannelConfig{}); slot->Wet.Buffer = slot->mWetBuffer; } diff --git a/3rdparty/openal/cmake/FindFFmpeg.cmake b/3rdparty/openal/cmake/FindFFmpeg.cmake index 26ed4d2faf30..d243defdc16f 100644 --- a/3rdparty/openal/cmake/FindFFmpeg.cmake +++ b/3rdparty/openal/cmake/FindFFmpeg.cmake @@ -80,8 +80,37 @@ macro(find_component _component _pkgconfig _library _header) ${PC_LIB${_component}_LIBRARY_DIRS} ) - set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING "The ${_component} version number." FORCE) - set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING "The ${_component} CFLAGS." FORCE) + if(DEFINED ${PC_${_component}_VERSION}) + set(${_component}_VERSION ${PC_${_component}_VERSION} CACHE STRING + "The ${_component} version number." FORCE) + elseif(EXISTS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version.h") + if(EXISTS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version_major.h") + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version_major.h" majorver + REGEX "^#define[ \t]+LIB${_component}_VERSION_MAJOR[ \t]+[0-9]+$") + else() + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version.h" majorver + REGEX "^#define[ \t]+LIB${_component}_VERSION_MAJOR[ \t]+[0-9]+$") + endif() + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version.h" minorver + REGEX "^#define[ \t]+LIB${_component}_VERSION_MINOR[ \t]+[0-9]+$") + file(STRINGS "${${_component}_INCLUDE_DIRS}/${_pkgconfig}/version.h" microver + REGEX "^#define[ \t]+LIB${_component}_VERSION_MICRO[ \t]+[0-9]+$") + + string(REGEX REPLACE "^#define[ \t]+LIB${_component}_VERSION_MAJOR[ \t]+([0-9]+)$" "\\1" + majorver "${majorver}") + string(REGEX REPLACE "^#define[ \t]+LIB${_component}_VERSION_MINOR[ \t]+([0-9]+)$" "\\1" + minorver "${minorver}") + string(REGEX REPLACE "^#define[ \t]+LIB${_component}_VERSION_MICRO[ \t]+([0-9]+)$" "\\1" + microver "${microver}") + + set(${_component}_VERSION "${majorver}.${minorver}.${microver}" CACHE STRING + "The ${_component} version number." FORCE) + unset(microver) + unset(minorver) + unset(majorver) + endif() + set(${_component}_DEFINITIONS ${PC_${_component}_CFLAGS_OTHER} CACHE STRING + "The ${_component} CFLAGS." FORCE) set_component_found(${_component}) diff --git a/3rdparty/openal/cmake/FindJACK.cmake b/3rdparty/openal/cmake/FindJACK.cmake index b72fe3f9a91e..c85d0643f392 100644 --- a/3rdparty/openal/cmake/FindJACK.cmake +++ b/3rdparty/openal/cmake/FindJACK.cmake @@ -43,7 +43,7 @@ find_path(JACK_INCLUDE_DIR NAMES jack/jack.h DOC "The JACK include directory" ) -find_library(JACK_LIBRARY NAMES jack +find_library(JACK_LIBRARY NAMES jack jack64 DOC "The JACK library" ) diff --git a/3rdparty/openal/cmake/FindSndIO.cmake b/3rdparty/openal/cmake/FindSndIO.cmake new file mode 100644 index 000000000000..eb4a2587be6b --- /dev/null +++ b/3rdparty/openal/cmake/FindSndIO.cmake @@ -0,0 +1,31 @@ +# - Find SndIO includes and libraries +# +# SNDIO_FOUND - True if SNDIO_INCLUDE_DIR & SNDIO_LIBRARY are found +# SNDIO_LIBRARIES - Set when SNDIO_LIBRARY is found +# SNDIO_INCLUDE_DIRS - Set when SNDIO_INCLUDE_DIR is found +# +# SNDIO_INCLUDE_DIR - where to find sndio.h, etc. +# SNDIO_LIBRARY - the sndio library +# + +find_path(SNDIO_INCLUDE_DIR + NAMES sndio.h + DOC "The SndIO include directory" +) + +find_library(SNDIO_LIBRARY + NAMES sndio + DOC "The SndIO library" +) + +include(FindPackageHandleStandardArgs) +find_package_handle_standard_args(SndIO + REQUIRED_VARS SNDIO_LIBRARY SNDIO_INCLUDE_DIR +) + +if(SNDIO_FOUND) + set(SNDIO_LIBRARIES ${SNDIO_LIBRARY}) + set(SNDIO_INCLUDE_DIRS ${SNDIO_INCLUDE_DIR}) +endif() + +mark_as_advanced(SNDIO_INCLUDE_DIR SNDIO_LIBRARY) diff --git a/3rdparty/openal/cmake/FindSoundIO.cmake b/3rdparty/openal/cmake/FindSoundIO.cmake deleted file mode 100644 index 10450254d213..000000000000 --- a/3rdparty/openal/cmake/FindSoundIO.cmake +++ /dev/null @@ -1,32 +0,0 @@ -# - Find SoundIO (sndio) includes and libraries -# -# SOUNDIO_FOUND - True if SOUNDIO_INCLUDE_DIR & SOUNDIO_LIBRARY are -# found -# SOUNDIO_LIBRARIES - Set when SOUNDIO_LIBRARY is found -# SOUNDIO_INCLUDE_DIRS - Set when SOUNDIO_INCLUDE_DIR is found -# -# SOUNDIO_INCLUDE_DIR - where to find sndio.h, etc. -# SOUNDIO_LIBRARY - the sndio library -# - -find_path(SOUNDIO_INCLUDE_DIR - NAMES sndio.h - DOC "The SoundIO include directory" -) - -find_library(SOUNDIO_LIBRARY - NAMES sndio - DOC "The SoundIO library" -) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(SoundIO - REQUIRED_VARS SOUNDIO_LIBRARY SOUNDIO_INCLUDE_DIR -) - -if(SOUNDIO_FOUND) - set(SOUNDIO_LIBRARIES ${SOUNDIO_LIBRARY}) - set(SOUNDIO_INCLUDE_DIRS ${SOUNDIO_INCLUDE_DIR}) -endif() - -mark_as_advanced(SOUNDIO_INCLUDE_DIR SOUNDIO_LIBRARY) diff --git a/3rdparty/openal/common/alassert.cpp b/3rdparty/openal/common/alassert.cpp new file mode 100644 index 000000000000..aa44841e428b --- /dev/null +++ b/3rdparty/openal/common/alassert.cpp @@ -0,0 +1,44 @@ + +#include "alassert.h" + +#include +#include + +namespace { + +[[noreturn]] +void throw_error(const std::string &message) +{ + throw std::runtime_error{message}; +} + +} /* namespace */ + +namespace al { + +[[noreturn]] +void do_assert(const char *message, int linenum, const char *filename, const char *funcname) noexcept +{ + /* Throwing an exception that tries to leave a noexcept function will + * hopefully cause the system to provide info about the caught exception in + * an error dialog. At least on Linux, this results in the process printing + * + * terminate called after throwing an instance of 'std::runtime_error' + * what(): + * + * before terminating from a SIGABRT. Hopefully Windows and Mac will do the + * appropriate things with the message to alert the user about an abnormal + * termination. + */ + auto errstr = std::string{filename}; + errstr += ':'; + errstr += std::to_string(linenum); + errstr += ": "; + errstr += funcname; + errstr += ": "; + errstr += message; + + throw_error(errstr); +} + +} /* namespace al */ diff --git a/3rdparty/openal/common/alassert.h b/3rdparty/openal/common/alassert.h new file mode 100644 index 000000000000..3797e96d5bd1 --- /dev/null +++ b/3rdparty/openal/common/alassert.h @@ -0,0 +1,24 @@ +#ifndef AL_ASSERT_H +#define AL_ASSERT_H + +#include + +#include "opthelpers.h" + +namespace al { + +[[noreturn]] +void do_assert(const char *message, int linenum, const char *filename, const char *funcname) noexcept; + +} /* namespace al */ + +/* A custom assert macro that is not compiled out for Release/NDEBUG builds, + * making it an appropriate replacement for assert() checks that must not be + * ignored. + */ +#define alassert(cond) do { \ + if(!(cond)) UNLIKELY \ + al::do_assert("Assertion '" #cond "' failed", __LINE__, __FILE__, std::data(__func__)); \ +} while(0) + +#endif /* AL_ASSERT_H */ diff --git a/3rdparty/openal/common/albit.h b/3rdparty/openal/common/albit.h index 962eb0aae458..b5c10d718066 100644 --- a/3rdparty/openal/common/albit.h +++ b/3rdparty/openal/common/albit.h @@ -1,7 +1,11 @@ #ifndef AL_BIT_H #define AL_BIT_H +#include +#include +#ifndef __GNUC__ #include +#endif #include #include #include @@ -17,9 +21,19 @@ std::enable_if_t, To> bit_cast(const From &src) noexcept { - std::aligned_storage_t dst; - std::memcpy(&dst, &src, sizeof(To)); - return *std::launder(reinterpret_cast(&dst)); + alignas(To) std::array dst; + std::memcpy(dst.data(), &src, sizeof(To)); + return *std::launder(reinterpret_cast(dst.data())); +} + +template +std::enable_if_t, +T> byteswap(T value) noexcept +{ + static_assert(std::has_unique_object_representations_v); + auto bytes = al::bit_cast>(value); + std::reverse(bytes.begin(), bytes.end()); + return al::bit_cast(bytes); } #ifdef __BYTE_ORDER__ diff --git a/3rdparty/openal/common/alcomplex.cpp b/3rdparty/openal/common/alcomplex.cpp index dad62d0a1910..ae8bc41cef4b 100644 --- a/3rdparty/openal/common/alcomplex.cpp +++ b/3rdparty/openal/common/alcomplex.cpp @@ -4,10 +4,11 @@ #include "alcomplex.h" #include +#include #include -#include #include #include +#include #include #include "albit.h" @@ -19,32 +20,33 @@ namespace { using ushort = unsigned short; -using ushort2 = std::pair; +using ushort2 = std::array; +using complex_d = std::complex; -constexpr size_t BitReverseCounter(size_t log2_size) noexcept +constexpr std::size_t BitReverseCounter(std::size_t log2_size) noexcept { /* Some magic math that calculates the number of swaps needed for a * sequence of bit-reversed indices when index < reversed_index. */ - return (1u<<(log2_size-1)) - (1u<<((log2_size-1u)/2u)); + return (1_zu<<(log2_size-1)) - (1_zu<<((log2_size-1_zu)/2_zu)); } -template +template struct BitReverser { static_assert(N <= sizeof(ushort)*8, "Too many bits for the bit-reversal table."); - ushort2 mData[BitReverseCounter(N)]{}; + std::array mData{}; constexpr BitReverser() { - const size_t fftsize{1u << N}; - size_t ret_i{0}; + const std::size_t fftsize{1u << N}; + std::size_t ret_i{0}; /* Bit-reversal permutation applied to a sequence of fftsize items. */ - for(size_t idx{1u};idx < fftsize-1;++idx) + for(std::size_t idx{1u};idx < fftsize-1;++idx) { - size_t revidx{idx}; + std::size_t revidx{idx}; revidx = ((revidx&0xaaaaaaaa) >> 1) | ((revidx&0x55555555) << 1); revidx = ((revidx&0xcccccccc) >> 2) | ((revidx&0x33333333) << 2); revidx = ((revidx&0xf0f0f0f0) >> 4) | ((revidx&0x0f0f0f0f) << 4); @@ -54,8 +56,8 @@ struct BitReverser { if(idx < revidx) { - mData[ret_i].first = static_cast(idx); - mData[ret_i].second = static_cast(revidx); + mData[ret_i][0] = static_cast(idx); + mData[ret_i][1] = static_cast(revidx); ++ret_i; } } @@ -109,43 +111,41 @@ constexpr std::array,gBitReverses.size()-1> gArgAngle{{ } // namespace -template -std::enable_if_t::value> -complex_fft(const al::span> buffer, const al::type_identity_t sign) +void complex_fft(const al::span> buffer, const double sign) { - const size_t fftsize{buffer.size()}; + const std::size_t fftsize{buffer.size()}; /* Get the number of bits used for indexing. Simplifies bit-reversal and * the main loop count. */ - const size_t log2_size{static_cast(al::countr_zero(fftsize))}; + const std::size_t log2_size{static_cast(al::countr_zero(fftsize))}; if(log2_size < gBitReverses.size()) LIKELY { for(auto &rev : gBitReverses[log2_size]) - std::swap(buffer[rev.first], buffer[rev.second]); + std::swap(buffer[rev[0]], buffer[rev[1]]); /* Iterative form of Danielson-Lanczos lemma */ - for(size_t i{0};i < log2_size;++i) + for(std::size_t i{0};i < log2_size;++i) { - const size_t step2{1_uz << i}; - const size_t step{2_uz << i}; + const std::size_t step2{1_uz << i}; + const std::size_t step{2_uz << i}; /* The first iteration of the inner loop would have u=1, which we * can simplify to remove a number of complex multiplies. */ - for(size_t k{0};k < fftsize;k+=step) + for(std::size_t k{0};k < fftsize;k+=step) { - std::complex temp{buffer[k+step2]}; + const complex_d temp{buffer[k+step2]}; buffer[k+step2] = buffer[k] - temp; buffer[k] += temp; } - const std::complex w{gArgAngle[i].real(), gArgAngle[i].imag()*sign}; - std::complex u{w}; - for(size_t j{1};j < step2;j++) + const complex_d w{gArgAngle[i].real(), gArgAngle[i].imag()*sign}; + complex_d u{w}; + for(std::size_t j{1};j < step2;j++) { - for(size_t k{j};k < fftsize;k+=step) + for(std::size_t k{j};k < fftsize;k+=step) { - std::complex temp{buffer[k+step2] * u}; + const complex_d temp{buffer[k+step2] * u}; buffer[k+step2] = buffer[k] - temp; buffer[k] += temp; } @@ -155,9 +155,11 @@ complex_fft(const al::span> buffer, const al::type_identity_t } else { - for(size_t idx{1u};idx < fftsize-1;++idx) + assert(log2_size < 32); + + for(std::size_t idx{1u};idx < fftsize-1;++idx) { - size_t revidx{idx}; + std::size_t revidx{idx}; revidx = ((revidx&0xaaaaaaaa) >> 1) | ((revidx&0x55555555) << 1); revidx = ((revidx&0xcccccccc) >> 2) | ((revidx&0x33333333) << 2); revidx = ((revidx&0xf0f0f0f0) >> 4) | ((revidx&0x0f0f0f0f) << 4); @@ -169,26 +171,26 @@ complex_fft(const al::span> buffer, const al::type_identity_t std::swap(buffer[idx], buffer[revidx]); } - const Real pi{al::numbers::pi_v * sign}; - for(size_t i{0};i < log2_size;++i) + const double pi{al::numbers::pi * sign}; + for(std::size_t i{0};i < log2_size;++i) { - const size_t step2{1_uz << i}; - const size_t step{2_uz << i}; - for(size_t k{0};k < fftsize;k+=step) + const std::size_t step2{1_uz << i}; + const std::size_t step{2_uz << i}; + for(std::size_t k{0};k < fftsize;k+=step) { - std::complex temp{buffer[k+step2]}; + const complex_d temp{buffer[k+step2]}; buffer[k+step2] = buffer[k] - temp; buffer[k] += temp; } - const Real arg{pi / static_cast(step2)}; - const std::complex w{std::polar(Real{1}, arg)}; - std::complex u{w}; - for(size_t j{1};j < step2;j++) + const double arg{pi / static_cast(step2)}; + const complex_d w{std::polar(1.0, arg)}; + complex_d u{w}; + for(std::size_t j{1};j < step2;j++) { - for(size_t k{j};k < fftsize;k+=step) + for(std::size_t k{j};k < fftsize;k+=step) { - std::complex temp{buffer[k+step2] * u}; + const complex_d temp{buffer[k+step2] * u}; buffer[k+step2] = buffer[k] - temp; buffer[k] += temp; } @@ -200,13 +202,11 @@ complex_fft(const al::span> buffer, const al::type_identity_t void complex_hilbert(const al::span> buffer) { - using namespace std::placeholders; - inverse_fft(buffer); const double inverse_size = 1.0/static_cast(buffer.size()); auto bufiter = buffer.begin(); - const auto halfiter = bufiter + (buffer.size()>>1); + const auto halfiter = bufiter + ptrdiff_t(buffer.size()>>1); *bufiter *= inverse_size; ++bufiter; bufiter = std::transform(bufiter, halfiter, bufiter, @@ -217,7 +217,3 @@ void complex_hilbert(const al::span> buffer) forward_fft(buffer); } - - -template void complex_fft<>(const al::span> buffer, const float sign); -template void complex_fft<>(const al::span> buffer, const double sign); diff --git a/3rdparty/openal/common/alcomplex.h b/3rdparty/openal/common/alcomplex.h index 042a323266b5..9f12cef32cd2 100644 --- a/3rdparty/openal/common/alcomplex.h +++ b/3rdparty/openal/common/alcomplex.h @@ -2,7 +2,6 @@ #define ALCOMPLEX_H #include -#include #include "alspan.h" @@ -11,25 +10,21 @@ * FFT and 1 is inverse FFT. Applies the Discrete Fourier Transform (DFT) to * the data supplied in the buffer, which MUST BE power of two. */ -template -std::enable_if_t::value> -complex_fft(const al::span> buffer, const al::type_identity_t sign); +void complex_fft(const al::span> buffer, const double sign); /** * Calculate the frequency-domain response of the time-domain signal in the * provided buffer, which MUST BE power of two. */ -template -void forward_fft(const al::span buffer) -{ complex_fft(al::span{buffer}, -1); } +inline void forward_fft(const al::span> buffer) +{ complex_fft(buffer, -1.0); } /** * Calculate the time-domain signal of the frequency-domain response in the * provided buffer, which MUST BE power of two. */ -template -void inverse_fft(const al::span buffer) -{ complex_fft(al::span{buffer}, 1); } +inline void inverse_fft(const al::span> buffer) +{ complex_fft(buffer, +1.0); } /** * Calculate the complex helical sequence (discrete-time analytical signal) of diff --git a/3rdparty/openal/common/aldeque.h b/3rdparty/openal/common/aldeque.h deleted file mode 100644 index 3f99bf007469..000000000000 --- a/3rdparty/openal/common/aldeque.h +++ /dev/null @@ -1,16 +0,0 @@ -#ifndef ALDEQUE_H -#define ALDEQUE_H - -#include - -#include "almalloc.h" - - -namespace al { - -template -using deque = std::deque>; - -} // namespace al - -#endif /* ALDEQUE_H */ diff --git a/3rdparty/openal/common/alfstream.cpp b/3rdparty/openal/common/alfstream.cpp deleted file mode 100644 index 8991ce0352a0..000000000000 --- a/3rdparty/openal/common/alfstream.cpp +++ /dev/null @@ -1,26 +0,0 @@ - -#include "config.h" - -#include "alfstream.h" - -#include "strutils.h" - -#ifdef _WIN32 - -namespace al { - -ifstream::ifstream(const char *filename, std::ios_base::openmode mode) - : std::ifstream{utf8_to_wstr(filename).c_str(), mode} -{ } - -void ifstream::open(const char *filename, std::ios_base::openmode mode) -{ - std::wstring wstr{utf8_to_wstr(filename)}; - std::ifstream::open(wstr.c_str(), mode); -} - -ifstream::~ifstream() = default; - -} // namespace al - -#endif diff --git a/3rdparty/openal/common/alfstream.h b/3rdparty/openal/common/alfstream.h deleted file mode 100644 index 62b2e12c7568..000000000000 --- a/3rdparty/openal/common/alfstream.h +++ /dev/null @@ -1,45 +0,0 @@ -#ifndef AL_FSTREAM_H -#define AL_FSTREAM_H - -#ifdef _WIN32 - -#include -#include - - -namespace al { - -// Inherit from std::ifstream to accept UTF-8 filenames -class ifstream final : public std::ifstream { -public: - explicit ifstream(const char *filename, std::ios_base::openmode mode=std::ios_base::in); - explicit ifstream(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in) - : ifstream{filename.c_str(), mode} { } - - explicit ifstream(const wchar_t *filename, std::ios_base::openmode mode=std::ios_base::in) - : std::ifstream{filename, mode} { } - explicit ifstream(const std::wstring &filename, std::ios_base::openmode mode=std::ios_base::in) - : ifstream{filename.c_str(), mode} { } - - void open(const char *filename, std::ios_base::openmode mode=std::ios_base::in); - void open(const std::string &filename, std::ios_base::openmode mode=std::ios_base::in) - { open(filename.c_str(), mode); } - - ~ifstream() override; -}; - -} // namespace al - -#else /* _WIN32 */ - -#include - -namespace al { - -using ifstream = std::ifstream; - -} // namespace al - -#endif /* _WIN32 */ - -#endif /* AL_FSTREAM_H */ diff --git a/3rdparty/openal/common/almalloc.cpp b/3rdparty/openal/common/almalloc.cpp deleted file mode 100644 index ad1dc6be082e..000000000000 --- a/3rdparty/openal/common/almalloc.cpp +++ /dev/null @@ -1,61 +0,0 @@ - -#include "config.h" - -#include "almalloc.h" - -#include -#include -#include -#include -#include -#ifdef HAVE_MALLOC_H -#include -#endif - - -void *al_malloc(size_t alignment, size_t size) -{ - assert((alignment & (alignment-1)) == 0); - alignment = std::max(alignment, alignof(std::max_align_t)); - -#if defined(HAVE_POSIX_MEMALIGN) - void *ret{}; - if(posix_memalign(&ret, alignment, size) == 0) - return ret; - return nullptr; -#elif defined(HAVE__ALIGNED_MALLOC) - return _aligned_malloc(size, alignment); -#else - size_t total_size{size + alignment-1 + sizeof(void*)}; - void *base{std::malloc(total_size)}; - if(base != nullptr) - { - void *aligned_ptr{static_cast(base) + sizeof(void*)}; - total_size -= sizeof(void*); - - std::align(alignment, size, aligned_ptr, total_size); - *(static_cast(aligned_ptr)-1) = base; - base = aligned_ptr; - } - return base; -#endif -} - -void *al_calloc(size_t alignment, size_t size) -{ - void *ret{al_malloc(alignment, size)}; - if(ret) std::memset(ret, 0, size); - return ret; -} - -void al_free(void *ptr) noexcept -{ -#if defined(HAVE_POSIX_MEMALIGN) - std::free(ptr); -#elif defined(HAVE__ALIGNED_MALLOC) - _aligned_free(ptr); -#else - if(ptr != nullptr) - std::free(*(static_cast(ptr) - 1)); -#endif -} diff --git a/3rdparty/openal/common/almalloc.h b/3rdparty/openal/common/almalloc.h index 873473cacafe..bd30fe1565a0 100644 --- a/3rdparty/openal/common/almalloc.h +++ b/3rdparty/openal/common/almalloc.h @@ -3,49 +3,24 @@ #include #include -#include #include -#include #include #include #include +#include -#include "pragmadefs.h" - -void al_free(void *ptr) noexcept; -[[gnu::alloc_align(1), gnu::alloc_size(2), gnu::malloc]] -void *al_malloc(size_t alignment, size_t size); -[[gnu::alloc_align(1), gnu::alloc_size(2), gnu::malloc]] -void *al_calloc(size_t alignment, size_t size); +namespace gsl { +template using owner = T; +} -#define DISABLE_ALLOC() \ +#define DISABLE_ALLOC \ void *operator new(size_t) = delete; \ void *operator new[](size_t) = delete; \ void operator delete(void*) noexcept = delete; \ void operator delete[](void*) noexcept = delete; -#define DEF_NEWDEL(T) \ - void *operator new(size_t size) \ - { \ - static_assert(&operator new == &T::operator new, \ - "Incorrect container type specified"); \ - if(void *ret{al_malloc(alignof(T), size)}) \ - return ret; \ - throw std::bad_alloc(); \ - } \ - void *operator new[](size_t size) { return operator new(size); } \ - void operator delete(void *block) noexcept { al_free(block); } \ - void operator delete[](void *block) noexcept { operator delete(block); } - -#define DEF_PLACE_NEWDEL() \ - void *operator new(size_t /*size*/, void *ptr) noexcept { return ptr; } \ - void *operator new[](size_t /*size*/, void *ptr) noexcept { return ptr; } \ - void operator delete(void *block, void*) noexcept { al_free(block); } \ - void operator delete(void *block) noexcept { al_free(block); } \ - void operator delete[](void *block, void*) noexcept { al_free(block); } \ - void operator delete[](void *block) noexcept { al_free(block); } enum FamCount : size_t { }; @@ -58,56 +33,64 @@ enum FamCount : size_t { }; sizeof(T)); \ } \ \ - void *operator new(size_t /*size*/, FamCount count) \ + gsl::owner operator new(size_t /*size*/, FamCount count) \ { \ - if(void *ret{al_malloc(alignof(T), T::Sizeof(count))}) \ - return ret; \ - throw std::bad_alloc(); \ + const auto alignment = std::align_val_t{alignof(T)}; \ + return ::operator new[](T::Sizeof(count), alignment); \ } \ + void operator delete(gsl::owner block, FamCount) noexcept \ + { ::operator delete[](block, std::align_val_t{alignof(T)}); } \ + void operator delete(gsl::owner block) noexcept \ + { ::operator delete[](block, std::align_val_t{alignof(T)}); } \ void *operator new[](size_t /*size*/) = delete; \ - void operator delete(void *block, FamCount) { al_free(block); } \ - void operator delete(void *block) noexcept { al_free(block); } \ void operator delete[](void* /*block*/) = delete; namespace al { -template +template struct allocator { - static constexpr std::size_t alignment{std::max(Align, alignof(T))}; - - using value_type = T; - using reference = T&; - using const_reference = const T&; - using pointer = T*; - using const_pointer = const T*; + static constexpr auto Alignment = std::max(AlignV, alignof(T)); + static constexpr auto AlignVal = std::align_val_t{Alignment}; + + using value_type = std::remove_cv_t>; + using reference = value_type&; + using const_reference = const value_type&; + using pointer = value_type*; + using const_pointer = const value_type*; using size_type = std::size_t; using difference_type = std::ptrdiff_t; using is_always_equal = std::true_type; - template + template = true> struct rebind { - using other = allocator; + using other = allocator; }; constexpr explicit allocator() noexcept = default; template - constexpr explicit allocator(const allocator&) noexcept { } + constexpr explicit allocator(const allocator&) noexcept + { static_assert(Alignment == allocator::Alignment); } - T *allocate(std::size_t n) + gsl::owner allocate(std::size_t n) { if(n > std::numeric_limits::max()/sizeof(T)) throw std::bad_alloc(); - if(auto p = al_malloc(alignment, n*sizeof(T))) return static_cast(p); - throw std::bad_alloc(); + return static_cast>(::operator new[](n*sizeof(T), AlignVal)); } - void deallocate(T *p, std::size_t) noexcept { al_free(p); } + void deallocate(gsl::owner p, std::size_t) noexcept + { ::operator delete[](gsl::owner{p}, AlignVal); } }; template -constexpr bool operator==(const allocator&, const allocator&) noexcept { return true; } +constexpr bool operator==(const allocator&, const allocator&) noexcept +{ return allocator::Alignment == allocator::Alignment; } template -constexpr bool operator!=(const allocator&, const allocator&) noexcept { return false; } +constexpr bool operator!=(const allocator&, const allocator&) noexcept +{ return allocator::Alignment != allocator::Alignment; } +#ifdef __cpp_lib_to_address +using std::to_address; +#else template constexpr T *to_address(T *p) noexcept { @@ -120,129 +103,96 @@ constexpr auto to_address(const T &p) noexcept { return ::al::to_address(p.operator->()); } - +#endif template constexpr T* construct_at(T *ptr, Args&& ...args) - noexcept(std::is_nothrow_constructible::value) -{ return ::new(static_cast(ptr)) T{std::forward(args)...}; } - - -/* Storage for flexible array data. This is trivially destructible if type T is - * trivially destructible. - */ -template::value> -struct FlexArrayStorage { - const size_t mSize; - union { - char mDummy; - alignas(alignment) T mArray[1]; - }; + noexcept(std::is_nothrow_constructible_v) +{ + /* NOLINTBEGIN(cppcoreguidelines-owning-memory) construct_at doesn't + * necessarily handle the address from an owner, while placement new + * expects to. + */ + return ::new(static_cast(ptr)) T{std::forward(args)...}; + /* NOLINTEND(cppcoreguidelines-owning-memory) */ +} - static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept - { - const size_t len{sizeof(T)*count}; - return std::max(offsetof(FlexArrayStorage,mArray)+len, sizeof(FlexArrayStorage)) + base; - } - FlexArrayStorage(size_t size) : mSize{size} - { std::uninitialized_default_construct_n(mArray, mSize); } - ~FlexArrayStorage() = default; +template +class out_ptr_t { + static_assert(!std::is_same_v); - FlexArrayStorage(const FlexArrayStorage&) = delete; - FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; -}; + SP &mRes; + std::variant mPtr; -template -struct FlexArrayStorage { - const size_t mSize; - union { - char mDummy; - alignas(alignment) T mArray[1]; - }; +public: + explicit out_ptr_t(SP &res) : mRes{res} { } + ~out_ptr_t() { std::visit([this](auto &ptr) { mRes.reset(static_cast(ptr)); }, mPtr); } - static constexpr size_t Sizeof(size_t count, size_t base) noexcept - { - const size_t len{sizeof(T)*count}; - return std::max(offsetof(FlexArrayStorage,mArray)+len, sizeof(FlexArrayStorage)) + base; - } + out_ptr_t() = delete; + out_ptr_t(const out_ptr_t&) = delete; + out_ptr_t& operator=(const out_ptr_t&) = delete; - FlexArrayStorage(size_t size) : mSize{size} - { std::uninitialized_default_construct_n(mArray, mSize); } - ~FlexArrayStorage() { std::destroy_n(mArray, mSize); } + operator PT*() noexcept /* NOLINT(google-explicit-constructor) */ + { return &std::get(mPtr); } - FlexArrayStorage(const FlexArrayStorage&) = delete; - FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; + operator void**() noexcept /* NOLINT(google-explicit-constructor) */ + { return &mPtr.template emplace(); } }; -/* A flexible array type. Used either standalone or at the end of a parent - * struct, with placement new, to have a run-time-sized array that's embedded - * with its size. - */ -template -struct FlexArray { - using element_type = T; - using value_type = std::remove_cv_t; - using index_type = size_t; - using difference_type = ptrdiff_t; - - using pointer = T*; - using const_pointer = const T*; - using reference = T&; - using const_reference = const T&; - - using iterator = pointer; - using const_iterator = const_pointer; - using reverse_iterator = std::reverse_iterator; - using const_reverse_iterator = std::reverse_iterator; - - using Storage_t_ = FlexArrayStorage; - - Storage_t_ mStore; - - static constexpr index_type Sizeof(index_type count, index_type base=0u) noexcept - { return Storage_t_::Sizeof(count, base); } - static std::unique_ptr Create(index_type count) +template +auto out_ptr(SP &res, Args&& ...args) +{ + static_assert(sizeof...(args) == 0); + if constexpr(std::is_same_v) { - void *ptr{al_calloc(alignof(FlexArray), Sizeof(count))}; - return std::unique_ptr{al::construct_at(static_cast(ptr), count)}; + using ptype = typename SP::element_type*; + return out_ptr_t{res}; } + else + return out_ptr_t{res}; +} - FlexArray(index_type size) : mStore{size} { } - ~FlexArray() = default; - - index_type size() const noexcept { return mStore.mSize; } - bool empty() const noexcept { return mStore.mSize == 0; } - - pointer data() noexcept { return mStore.mArray; } - const_pointer data() const noexcept { return mStore.mArray; } - reference operator[](index_type i) noexcept { return mStore.mArray[i]; } - const_reference operator[](index_type i) const noexcept { return mStore.mArray[i]; } +template +class inout_ptr_t { + static_assert(!std::is_same_v); - reference front() noexcept { return mStore.mArray[0]; } - const_reference front() const noexcept { return mStore.mArray[0]; } + SP &mRes; + std::variant mPtr; - reference back() noexcept { return mStore.mArray[mStore.mSize-1]; } - const_reference back() const noexcept { return mStore.mArray[mStore.mSize-1]; } +public: + explicit inout_ptr_t(SP &res) : mRes{res}, mPtr{res.get()} { } + ~inout_ptr_t() + { + mRes.release(); + std::visit([this](auto &ptr) { mRes.reset(static_cast(ptr)); }, mPtr); + } - iterator begin() noexcept { return mStore.mArray; } - const_iterator begin() const noexcept { return mStore.mArray; } - const_iterator cbegin() const noexcept { return mStore.mArray; } - iterator end() noexcept { return mStore.mArray + mStore.mSize; } - const_iterator end() const noexcept { return mStore.mArray + mStore.mSize; } - const_iterator cend() const noexcept { return mStore.mArray + mStore.mSize; } + inout_ptr_t() = delete; + inout_ptr_t(const inout_ptr_t&) = delete; + inout_ptr_t& operator=(const inout_ptr_t&) = delete; - reverse_iterator rbegin() noexcept { return end(); } - const_reverse_iterator rbegin() const noexcept { return end(); } - const_reverse_iterator crbegin() const noexcept { return cend(); } - reverse_iterator rend() noexcept { return begin(); } - const_reverse_iterator rend() const noexcept { return begin(); } - const_reverse_iterator crend() const noexcept { return cbegin(); } + operator PT*() noexcept /* NOLINT(google-explicit-constructor) */ + { return &std::get(mPtr); } - DEF_PLACE_NEWDEL() + operator void**() noexcept /* NOLINT(google-explicit-constructor) */ + { return &mPtr.template emplace(mRes.get()); } }; +template +auto inout_ptr(SP &res, Args&& ...args) +{ + static_assert(sizeof...(args) == 0); + if constexpr(std::is_same_v) + { + using ptype = typename SP::element_type*; + return inout_ptr_t{res}; + } + else + return inout_ptr_t{res}; +} + } // namespace al #endif /* AL_MALLOC_H */ diff --git a/3rdparty/openal/common/alnumbers.h b/3rdparty/openal/common/alnumbers.h index e92d7b871ee5..6d201ad4f50a 100644 --- a/3rdparty/openal/common/alnumbers.h +++ b/3rdparty/openal/common/alnumbers.h @@ -1,11 +1,9 @@ #ifndef COMMON_ALNUMBERS_H #define COMMON_ALNUMBERS_H -#include +#include -namespace al { - -namespace numbers { +namespace al::numbers { namespace detail_ { template @@ -29,8 +27,6 @@ inline constexpr auto inv_pi = inv_pi_v; inline constexpr auto sqrt2 = sqrt2_v; inline constexpr auto sqrt3 = sqrt3_v; -} // namespace numbers - -} // namespace al +} // namespace al::numbers #endif /* COMMON_ALNUMBERS_H */ diff --git a/3rdparty/openal/common/alnumeric.h b/3rdparty/openal/common/alnumeric.h index 759dbc126f0d..cd9c55cfcb8a 100644 --- a/3rdparty/openal/common/alnumeric.h +++ b/3rdparty/openal/common/alnumeric.h @@ -1,15 +1,19 @@ #ifndef AL_NUMERIC_H #define AL_NUMERIC_H +#include "config_simd.h" + #include +#include #include #include #include +#include #include #ifdef HAVE_INTRIN_H #include #endif -#ifdef HAVE_SSE_INTRINSICS +#if HAVE_SSE_INTRINSICS #include #endif @@ -18,78 +22,39 @@ #include "opthelpers.h" -constexpr auto operator "" _i64(unsigned long long n) noexcept { return static_cast(n); } -constexpr auto operator "" _u64(unsigned long long n) noexcept { return static_cast(n); } +constexpr auto operator "" _i64(unsigned long long n) noexcept { return static_cast(n); } +constexpr auto operator "" _u64(unsigned long long n) noexcept { return static_cast(n); } constexpr auto operator "" _z(unsigned long long n) noexcept -{ return static_cast>(n); } -constexpr auto operator "" _uz(unsigned long long n) noexcept { return static_cast(n); } -constexpr auto operator "" _zu(unsigned long long n) noexcept { return static_cast(n); } - - -constexpr inline float minf(float a, float b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline float maxf(float a, float b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline float clampf(float val, float min, float max) noexcept -{ return minf(max, maxf(min, val)); } - -constexpr inline double mind(double a, double b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline double maxd(double a, double b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline double clampd(double val, double min, double max) noexcept -{ return mind(max, maxd(min, val)); } - -constexpr inline unsigned int minu(unsigned int a, unsigned int b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline unsigned int maxu(unsigned int a, unsigned int b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline unsigned int clampu(unsigned int val, unsigned int min, unsigned int max) noexcept -{ return minu(max, maxu(min, val)); } - -constexpr inline int mini(int a, int b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline int maxi(int a, int b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline int clampi(int val, int min, int max) noexcept -{ return mini(max, maxi(min, val)); } - -constexpr inline int64_t mini64(int64_t a, int64_t b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline int64_t maxi64(int64_t a, int64_t b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline int64_t clampi64(int64_t val, int64_t min, int64_t max) noexcept -{ return mini64(max, maxi64(min, val)); } - -constexpr inline uint64_t minu64(uint64_t a, uint64_t b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline uint64_t maxu64(uint64_t a, uint64_t b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline uint64_t clampu64(uint64_t val, uint64_t min, uint64_t max) noexcept -{ return minu64(max, maxu64(min, val)); } - -constexpr inline size_t minz(size_t a, size_t b) noexcept -{ return ((a > b) ? b : a); } -constexpr inline size_t maxz(size_t a, size_t b) noexcept -{ return ((a > b) ? a : b); } -constexpr inline size_t clampz(size_t val, size_t min, size_t max) noexcept -{ return minz(max, maxz(min, val)); } - - -constexpr inline float lerpf(float val1, float val2, float mu) noexcept -{ return val1 + (val2-val1)*mu; } -constexpr inline float cubic(float val1, float val2, float val3, float val4, float mu) noexcept +{ return static_cast>(n); } +constexpr auto operator "" _uz(unsigned long long n) noexcept { return static_cast(n); } +constexpr auto operator "" _zu(unsigned long long n) noexcept { return static_cast(n); } + + +template,bool> = true> +constexpr auto as_unsigned(T value) noexcept { - const float mu2{mu*mu}, mu3{mu2*mu}; - const float a0{-0.5f*mu3 + mu2 + -0.5f*mu}; - const float a1{ 1.5f*mu3 + -2.5f*mu2 + 1.0f}; - const float a2{-1.5f*mu3 + 2.0f*mu2 + 0.5f*mu}; - const float a3{ 0.5f*mu3 + -0.5f*mu2}; - return val1*a0 + val2*a1 + val3*a2 + val4*a3; + using UT = std::make_unsigned_t; + return static_cast(value); } +constexpr auto GetCounterSuffix(size_t count) noexcept -> std::string_view +{ + using namespace std::string_view_literals; + return (((count%100)/10) == 1) ? "th"sv : + ((count%10) == 1) ? "st"sv : + ((count%10) == 2) ? "nd"sv : + ((count%10) == 3) ? "rd"sv : "th"sv; +} + + +constexpr auto lerpf(float val1, float val2, float mu) noexcept -> float +{ return val1 + (val2-val1)*mu; } +constexpr auto lerpd(double val1, double val2, double mu) noexcept -> double +{ return val1 + (val2-val1)*mu; } + + /** Find the next power-of-2 for non-power-of-2 numbers. */ inline uint32_t NextPowerOf2(uint32_t value) noexcept { @@ -129,24 +94,21 @@ constexpr T RoundUp(T value, al::type_identity_t r) noexcept */ inline int fastf2i(float f) noexcept { -#if defined(HAVE_SSE_INTRINSICS) +#if HAVE_SSE_INTRINSICS return _mm_cvt_ss2si(_mm_set_ss(f)); -#elif defined(_MSC_VER) && defined(_M_IX86_FP) +#elif defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0 int i; __asm fld f __asm fistp i return i; -#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) +#elif (defined(__GNUC__) || defined(__clang__)) && (defined(__i386__) || defined(__x86_64__)) \ + && !defined(__SSE_MATH__) int i; -#ifdef __SSE_MATH__ - __asm__("cvtss2si %1, %0" : "=r"(i) : "x"(f)); -#else __asm__ __volatile__("fistpl %0" : "=m"(i) : "t"(f) : "st"); -#endif return i; #else @@ -160,7 +122,7 @@ inline unsigned int fastf2u(float f) noexcept /** Converts float-to-int using standard behavior (truncation). */ inline int float2int(float f) noexcept { -#if defined(HAVE_SSE_INTRINSICS) +#if HAVE_SSE_INTRINSICS return _mm_cvtt_ss2si(_mm_set_ss(f)); #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP == 0) \ @@ -191,7 +153,7 @@ inline unsigned int float2uint(float f) noexcept /** Converts double-to-int using standard behavior (truncation). */ inline int double2int(double d) noexcept { -#if defined(HAVE_SSE_INTRINSICS) +#if HAVE_SSE_INTRINSICS return _mm_cvttsd_si32(_mm_set_sd(d)); #elif (defined(_MSC_VER) && defined(_M_IX86_FP) && _M_IX86_FP < 2) \ @@ -242,7 +204,7 @@ inline float fast_roundf(float f) noexcept /* Integral limit, where sub-integral precision is not available for * floats. */ - static constexpr float ilim[2]{ + static constexpr std::array ilim{ 8388608.0f /* 0x1.0p+23 */, -8388608.0f /* -0x1.0p+23 */ }; @@ -266,11 +228,15 @@ inline float fast_roundf(float f) noexcept * optimize this out because of non-associative rules on floating-point * math (as long as you don't use -fassociative-math, * -funsafe-math-optimizations, -ffast-math, or -Ofast, in which case this - * may break). + * may break without __builtin_assoc_barrier support). */ +#if HAS_BUILTIN(__builtin_assoc_barrier) + return __builtin_assoc_barrier(f + ilim[sign]) - ilim[sign]; +#else f += ilim[sign]; return f - ilim[sign]; #endif +#endif } @@ -285,9 +251,9 @@ inline float level_mb_to_gain(float x) // Converts gain to level (mB). inline float gain_to_level_mb(float x) { - if (x <= 0.0f) + if(x <= 1e-05f) return -10'000.0f; - return maxf(std::log10(x) * 2'000.0f, -10'000.0f); + return std::max(std::log10(x) * 2'000.0f, -10'000.0f); } #endif /* AL_NUMERIC_H */ diff --git a/3rdparty/openal/common/alsem.cpp b/3rdparty/openal/common/alsem.cpp index 6a92b35cf252..2eeed5929d84 100644 --- a/3rdparty/openal/common/alsem.cpp +++ b/3rdparty/openal/common/alsem.cpp @@ -24,8 +24,6 @@ #include -#include "opthelpers.h" - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN @@ -39,7 +37,8 @@ semaphore::semaphore(unsigned int initial) { if(initial > static_cast(std::numeric_limits::max())) throw std::system_error(std::make_error_code(std::errc::value_too_large)); - mSem = CreateSemaphore(nullptr, initial, std::numeric_limits::max(), nullptr); + mSem = CreateSemaphoreW(nullptr, static_cast(initial), std::numeric_limits::max(), + nullptr); if(mSem == nullptr) throw std::system_error(std::make_error_code(std::errc::resource_unavailable_try_again)); } diff --git a/3rdparty/openal/common/alsem.h b/3rdparty/openal/common/alsem.h index 9f72d1c6510d..b23a54a1738b 100644 --- a/3rdparty/openal/common/alsem.h +++ b/3rdparty/openal/common/alsem.h @@ -24,10 +24,10 @@ class semaphore { #else using native_type = sem_t; #endif - native_type mSem; + native_type mSem{}; public: - semaphore(unsigned int initial=0); + explicit semaphore(unsigned int initial=0); semaphore(const semaphore&) = delete; ~semaphore(); diff --git a/3rdparty/openal/common/alspan.h b/3rdparty/openal/common/alspan.h index d5e42324b8c6..33587e6e1109 100644 --- a/3rdparty/openal/common/alspan.h +++ b/3rdparty/openal/common/alspan.h @@ -1,157 +1,255 @@ #ifndef AL_SPAN_H #define AL_SPAN_H -#include +#include #include -#include #include +#include +#include #include +#include +#include "alassert.h" #include "almalloc.h" #include "altraits.h" namespace al { -constexpr size_t dynamic_extent{static_cast(-1)}; +/* This is here primarily to help ensure proper behavior for span's iterators, + * being an actual object with member functions instead of a raw pointer (which + * has requirements like + and - working with ptrdiff_t). This also helps + * silence clang-tidy's pointer arithmetic warnings for span and FlexArray + * iterators. It otherwise behaves like a plain pointer and should optimize + * accordingly. + * + * Shouldn't be needed once we use std::span in C++20. + */ +template +class ptr_wrapper { + static_assert(std::is_pointer_v); + T mPointer{}; + +public: + using value_type = std::remove_pointer_t; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; + using pointer = value_type*; + using reference = value_type&; + using iterator_category = std::random_access_iterator_tag; + + explicit constexpr ptr_wrapper(T ptr) : mPointer{ptr} { } + + /* NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + constexpr auto operator++() noexcept -> ptr_wrapper& { ++mPointer; return *this; } + constexpr auto operator--() noexcept -> ptr_wrapper& { --mPointer; return *this; } + constexpr auto operator++(int) noexcept -> ptr_wrapper + { + auto temp = *this; + ++*this; + return temp; + } + constexpr auto operator--(int) noexcept -> ptr_wrapper + { + auto temp = *this; + --*this; + return temp; + } + + constexpr + auto operator+=(std::ptrdiff_t n) noexcept -> ptr_wrapper& { mPointer += n; return *this; } + constexpr + auto operator-=(std::ptrdiff_t n) noexcept -> ptr_wrapper& { mPointer -= n; return *this; } + + [[nodiscard]] constexpr auto operator*() const noexcept -> value_type& { return *mPointer; } + [[nodiscard]] constexpr auto operator->() const noexcept -> value_type* { return mPointer; } + [[nodiscard]] constexpr + auto operator[](std::size_t idx) const noexcept -> value_type& {return mPointer[idx];} + + [[nodiscard]] friend constexpr + auto operator+(const ptr_wrapper &lhs, std::ptrdiff_t n) noexcept -> ptr_wrapper + { return ptr_wrapper{lhs.mPointer + n}; } + [[nodiscard]] friend constexpr + auto operator+(std::ptrdiff_t n, const ptr_wrapper &rhs) noexcept -> ptr_wrapper + { return ptr_wrapper{n + rhs.mPointer}; } + [[nodiscard]] friend constexpr + auto operator-(const ptr_wrapper &lhs, std::ptrdiff_t n) noexcept -> ptr_wrapper + { return ptr_wrapper{lhs.mPointer - n}; } + + [[nodiscard]] friend constexpr + auto operator-(const ptr_wrapper &lhs, const ptr_wrapper &rhs)noexcept->std::ptrdiff_t + { return lhs.mPointer - rhs.mPointer; } + + [[nodiscard]] friend constexpr + auto operator==(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer == rhs.mPointer; } + [[nodiscard]] friend constexpr + auto operator!=(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer != rhs.mPointer; } + [[nodiscard]] friend constexpr + auto operator<=(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer <= rhs.mPointer; } + [[nodiscard]] friend constexpr + auto operator>=(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer >= rhs.mPointer; } + [[nodiscard]] friend constexpr + auto operator<(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer < rhs.mPointer; } + [[nodiscard]] friend constexpr + auto operator>(const ptr_wrapper &lhs, const ptr_wrapper &rhs) noexcept -> bool + { return lhs.mPointer > rhs.mPointer; } + /* NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ +}; + -template +inline constexpr std::size_t dynamic_extent{static_cast(-1)}; + +template class span; namespace detail_ { template struct is_span_ : std::false_type { }; - template + template struct is_span_> : std::true_type { }; template - constexpr bool is_span_v = is_span_>::value; + inline constexpr bool is_span_v = is_span_>::value; template struct is_std_array_ : std::false_type { }; - template + template struct is_std_array_> : std::true_type { }; template - constexpr bool is_std_array_v = is_std_array_>::value; + inline constexpr bool is_std_array_v = is_std_array_>::value; template - constexpr bool has_size_and_data = false; + inline constexpr bool has_size_and_data = false; template - constexpr bool has_size_and_data())),decltype(std::data(std::declval()))>> = true; template - constexpr bool is_valid_container_type = !is_span_v && !is_std_array_v + inline constexpr bool is_valid_container_type = !is_span_v && !is_std_array_v && !std::is_array::value && has_size_and_data; template - constexpr bool is_array_compatible = std::is_convertible::value; + inline constexpr bool is_array_compatible = std::is_convertible::value; /* NOLINT(*-avoid-c-arrays) */ template - constexpr bool is_valid_container = is_valid_container_type + inline constexpr bool is_valid_container = is_valid_container_type && is_array_compatible()))>,T>; } // namespace detail_ #define REQUIRES(...) std::enable_if_t<(__VA_ARGS__),bool> = true -template +/* NOLINTBEGIN(google-explicit-constructor) This largely follows std::span's + * constructor behavior, and should be replaced once C++20 is used. + */ +template class span { public: using element_type = T; using value_type = std::remove_cv_t; - using index_type = size_t; - using difference_type = ptrdiff_t; + using size_type = std::size_t; + using difference_type = std::ptrdiff_t; using pointer = T*; using const_pointer = const T*; using reference = T&; using const_reference = const T&; - using iterator = pointer; - using const_iterator = const_pointer; + using iterator = ptr_wrapper; + using const_iterator = ptr_wrapper; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr size_t extent{E}; + static constexpr std::size_t extent{E}; template constexpr span() noexcept { } template - constexpr explicit span(U iter, index_type) : mData{::al::to_address(iter)} { } - template::value)> - constexpr explicit span(U first, V) : mData{::al::to_address(first)} - {} - - constexpr span(type_identity_t (&arr)[E]) noexcept - : span{std::data(arr), std::size(arr)} - { } - constexpr span(std::array &arr) noexcept - : span{std::data(arr), std::size(arr)} - { } - template::value)> - constexpr span(const std::array &arr) noexcept - : span{std::data(arr), std::size(arr)} - { } + constexpr explicit span(U iter, size_type size_) : mData{::al::to_address(iter)} + { alassert(size_ == extent); } + template::value)> + constexpr explicit span(U first, V last) : mData{::al::to_address(first)} + { alassert(static_cast(last-first) == extent); } + + template + constexpr span(type_identity_t (&arr)[N]) noexcept /* NOLINT(*-avoid-c-arrays) */ + : mData{std::data(arr)} + { static_assert(N == extent); } + template + constexpr span(std::array &arr) noexcept : mData{std::data(arr)} + { static_assert(N == extent); } + template::value)> + constexpr span(const std::array &arr) noexcept : mData{std::data(arr)} + { static_assert(N == extent); } template)> constexpr explicit span(U&& cont) : span{std::data(cont), std::size(cont)} { } - template::value + template::value && detail_::is_array_compatible && N == dynamic_extent)> - constexpr explicit span(const span &span_) noexcept - : span{std::data(span_), std::size(span_)} - { } - template::value + constexpr explicit span(const span &span_) noexcept : mData{std::data(span_)} + { alassert(std::size(span_) == extent); } + template::value && detail_::is_array_compatible && N == extent)> - constexpr span(const span &span_) noexcept : span{std::data(span_), std::size(span_)} { } + constexpr span(const span &span_) noexcept : mData{std::data(span_)} { } constexpr span(const span&) noexcept = default; constexpr span& operator=(const span &rhs) noexcept = default; - constexpr reference front() const { return *mData; } - constexpr reference back() const { return *(mData+E-1); } - constexpr reference operator[](index_type idx) const { return mData[idx]; } - constexpr pointer data() const noexcept { return mData; } - - constexpr index_type size() const noexcept { return E; } - constexpr index_type size_bytes() const noexcept { return E * sizeof(value_type); } - constexpr bool empty() const noexcept { return E == 0; } - - constexpr iterator begin() const noexcept { return mData; } - constexpr iterator end() const noexcept { return mData+E; } - constexpr const_iterator cbegin() const noexcept { return mData; } - constexpr const_iterator cend() const noexcept { return mData+E; } - - constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } - constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } - constexpr const_reverse_iterator crbegin() const noexcept - { return const_reverse_iterator{cend()}; } - constexpr const_reverse_iterator crend() const noexcept - { return const_reverse_iterator{cbegin()}; } - - template - constexpr span first() const + [[nodiscard]] constexpr auto front() const -> reference { return mData[0]; } + [[nodiscard]] constexpr auto back() const -> reference { return mData[E-1]; } + [[nodiscard]] constexpr auto operator[](size_type idx) const -> reference { return mData[idx]; } + [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; } + + [[nodiscard]] constexpr auto size() const noexcept -> size_type { return E; } + [[nodiscard]] constexpr auto size_bytes() const noexcept -> size_type { return E * sizeof(value_type); } + [[nodiscard]] constexpr auto empty() const noexcept -> bool { return E == 0; } + + [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return iterator{mData}; } + [[nodiscard]] constexpr auto end() const noexcept -> iterator { return iterator{mData+E}; } + [[nodiscard]] constexpr + auto cbegin() const noexcept -> const_iterator { return const_iterator{mData}; } + [[nodiscard]] constexpr + auto cend() const noexcept -> const_iterator { return const_iterator{mData+E}; } + + [[nodiscard]] constexpr + auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator{end()}; } + [[nodiscard]] constexpr + auto rend() const noexcept -> reverse_iterator { return reverse_iterator{begin()}; } + [[nodiscard]] constexpr + auto crbegin() const noexcept -> const_reverse_iterator { return cend(); } + [[nodiscard]] constexpr + auto crend() const noexcept -> const_reverse_iterator { return cbegin(); } + + template + [[nodiscard]] constexpr auto first() const noexcept -> span { static_assert(E >= C, "New size exceeds original capacity"); return span{mData, C}; } - template - constexpr span last() const + template + [[nodiscard]] constexpr auto last() const noexcept -> span { static_assert(E >= C, "New size exceeds original capacity"); return span{mData+(E-C), C}; } - template - constexpr auto subspan() const -> std::enable_if_t> + template + [[nodiscard]] constexpr + auto subspan() const noexcept -> std::enable_if_t> { static_assert(E >= O, "Offset exceeds extent"); static_assert(E-O >= C, "New size exceeds original capacity"); return span{mData+O, C}; } - template - constexpr auto subspan() const -> std::enable_if_t> + template + [[nodiscard]] constexpr + auto subspan() const noexcept -> std::enable_if_t> { static_assert(E >= O, "Offset exceeds extent"); return span{mData+O, E-O}; @@ -161,10 +259,13 @@ class span { * defining the specialization. As a result, these methods need to be * defined later. */ - constexpr span first(size_t count) const; - constexpr span last(size_t count) const; - constexpr span subspan(size_t offset, - size_t count=dynamic_extent) const; + [[nodiscard]] constexpr + auto first(std::size_t count) const noexcept -> span; + [[nodiscard]] constexpr + auto last(std::size_t count) const noexcept -> span; + [[nodiscard]] constexpr + auto subspan(std::size_t offset, std::size_t count=dynamic_extent) const noexcept + -> span; private: pointer mData{nullptr}; @@ -175,7 +276,7 @@ class span { public: using element_type = T; using value_type = std::remove_cv_t; - using index_type = size_t; + using size_type = std::size_t; using difference_type = ptrdiff_t; using pointer = T*; @@ -183,129 +284,168 @@ class span { using reference = T&; using const_reference = const T&; - using iterator = pointer; - using const_iterator = const_pointer; + using iterator = ptr_wrapper; + using const_iterator = ptr_wrapper; using reverse_iterator = std::reverse_iterator; using const_reverse_iterator = std::reverse_iterator; - static constexpr size_t extent{dynamic_extent}; + static constexpr std::size_t extent{dynamic_extent}; constexpr span() noexcept = default; template - constexpr span(U iter, index_type count) : mData{::al::to_address(iter)}, mDataEnd{::al::to_address(iter) + count} + constexpr span(U iter, size_type count) : mData{::al::to_address(iter)}, mDataLength{count} { } - template::value)> - constexpr span(U first, V last) : span{::al::to_address(first), static_cast(last - first)} + template::value)> + constexpr span(U first, V last) + : span{::al::to_address(first), static_cast(last-first)} { } - template - constexpr span(type_identity_t (&arr)[N]) noexcept - : span{std::data(arr), std::size(arr)} + template + constexpr span(type_identity_t (&arr)[N]) noexcept /* NOLINT(*-avoid-c-arrays) */ + : mData{std::data(arr)}, mDataLength{std::size(arr)} { } - template + template constexpr span(std::array &arr) noexcept - : span{std::data(arr), std::size(arr)} + : mData{std::data(arr)}, mDataLength{std::size(arr)} { } - template::value)> + template::value)> constexpr span(const std::array &arr) noexcept - : span{std::data(arr), std::size(arr)} + : mData{std::data(arr)}, mDataLength{std::size(arr)} { } template)> constexpr span(U&& cont) : span{std::data(cont), std::size(cont)} { } - template::value || extent != N) - && detail_::is_array_compatible)> + template + && (!std::is_same::value || extent != N))> constexpr span(const span &span_) noexcept : span{std::data(span_), std::size(span_)} { } constexpr span(const span&) noexcept = default; constexpr span& operator=(const span &rhs) noexcept = default; - constexpr reference front() const { return *mData; } - constexpr reference back() const { return *(mDataEnd-1); } - constexpr reference operator[](index_type idx) const { return mData[idx]; } - constexpr pointer data() const noexcept { return mData; } - - constexpr index_type size() const noexcept { return static_cast(mDataEnd-mData); } - constexpr index_type size_bytes() const noexcept - { return static_cast(mDataEnd-mData) * sizeof(value_type); } - constexpr bool empty() const noexcept { return mData == mDataEnd; } - - constexpr iterator begin() const noexcept { return mData; } - constexpr iterator end() const noexcept { return mDataEnd; } - constexpr const_iterator cbegin() const noexcept { return mData; } - constexpr const_iterator cend() const noexcept { return mDataEnd; } - - constexpr reverse_iterator rbegin() const noexcept { return reverse_iterator{end()}; } - constexpr reverse_iterator rend() const noexcept { return reverse_iterator{begin()}; } - constexpr const_reverse_iterator crbegin() const noexcept - { return const_reverse_iterator{cend()}; } - constexpr const_reverse_iterator crend() const noexcept - { return const_reverse_iterator{cbegin()}; } - - template - constexpr span first() const - { return span{mData, C}; } + [[nodiscard]] constexpr auto front() const -> reference { return mData[0]; } + [[nodiscard]] constexpr auto back() const -> reference { return mData[mDataLength-1]; } + [[nodiscard]] constexpr auto operator[](size_type idx) const -> reference {return mData[idx];} + [[nodiscard]] constexpr auto data() const noexcept -> pointer { return mData; } + + [[nodiscard]] constexpr auto size() const noexcept -> size_type { return mDataLength; } + [[nodiscard]] constexpr + auto size_bytes() const noexcept -> size_type { return mDataLength * sizeof(value_type); } + [[nodiscard]] constexpr auto empty() const noexcept -> bool { return mDataLength == 0; } + + [[nodiscard]] constexpr auto begin() const noexcept -> iterator { return iterator{mData}; } + [[nodiscard]] constexpr + auto end() const noexcept -> iterator { return iterator{mData+mDataLength}; } + [[nodiscard]] constexpr + auto cbegin() const noexcept -> const_iterator { return const_iterator{mData}; } + [[nodiscard]] constexpr + auto cend() const noexcept -> const_iterator { return const_iterator{mData+mDataLength}; } + + [[nodiscard]] constexpr + auto rbegin() const noexcept -> reverse_iterator { return reverse_iterator{end()}; } + [[nodiscard]] constexpr + auto rend() const noexcept -> reverse_iterator { return reverse_iterator{begin()}; } + [[nodiscard]] constexpr + auto crbegin() const noexcept -> const_reverse_iterator { return cend(); } + [[nodiscard]] constexpr + auto crend() const noexcept -> const_reverse_iterator { return cbegin(); } + + template + [[nodiscard]] constexpr auto first() const noexcept -> span + { + assert(C <= mDataLength); + return span{mData, C}; + } - constexpr span first(size_t count) const - { return (count >= size()) ? *this : span{mData, mData+count}; } + [[nodiscard]] constexpr auto first(std::size_t count) const noexcept -> span + { + assert(count <= mDataLength); + return span{mData, count}; + } - template - constexpr span last() const - { return span{mDataEnd-C, C}; } + template + [[nodiscard]] constexpr auto last() const noexcept -> span + { + assert(C <= mDataLength); + return span{mData+mDataLength-C, C}; + } - constexpr span last(size_t count) const - { return (count >= size()) ? *this : span{mDataEnd-count, mDataEnd}; } + [[nodiscard]] constexpr auto last(std::size_t count) const noexcept -> span + { + assert(count <= mDataLength); + return span{mData+mDataLength-count, count}; + } - template - constexpr auto subspan() const -> std::enable_if_t> - { return span{mData+O, C}; } + template + [[nodiscard]] constexpr + auto subspan() const noexcept -> std::enable_if_t> + { + assert(O <= mDataLength); + assert(C <= mDataLength-O); + return span{mData+O, C}; + } - template - constexpr auto subspan() const -> std::enable_if_t> - { return span{mData+O, mDataEnd}; } + template + [[nodiscard]] constexpr + auto subspan() const noexcept -> std::enable_if_t> + { + assert(O <= mDataLength); + return span{mData+O, mDataLength-O}; + } - constexpr span subspan(size_t offset, size_t count=dynamic_extent) const + [[nodiscard]] constexpr + auto subspan(std::size_t offset, std::size_t count=dynamic_extent) const noexcept -> span { - return (offset > size()) ? span{} : - (count >= size()-offset) ? span{mData+offset, mDataEnd} : - span{mData+offset, mData+offset+count}; + assert(offset <= mDataLength); + if(count != dynamic_extent) + { + assert(count <= mDataLength-offset); + return span{mData+offset, count}; + } + return span{mData+offset, mDataLength-offset}; } private: pointer mData{nullptr}; - pointer mDataEnd{nullptr}; + size_type mDataLength{0}; }; -template -constexpr inline auto span::first(size_t count) const -> span +template +[[nodiscard]] constexpr +auto span::first(std::size_t count) const noexcept -> span { - return (count >= size()) ? span{mData, extent} : - span{mData, count}; + assert(count <= size()); + return span{mData, count}; } -template -constexpr inline auto span::last(size_t count) const -> span +template +[[nodiscard]] constexpr +auto span::last(std::size_t count) const noexcept -> span { - return (count >= size()) ? span{mData, extent} : - span{mData+extent-count, count}; + assert(count <= size()); + return span{mData+size()-count, count}; } -template -constexpr inline auto span::subspan(size_t offset, size_t count) const +template +[[nodiscard]] constexpr +auto span::subspan(std::size_t offset, std::size_t count) const noexcept -> span { - return (offset > size()) ? span{} : - (count >= size()-offset) ? span{mData+offset, mData+extent} : - span{mData+offset, mData+offset+count}; + assert(offset <= size()); + if(count != dynamic_extent) + { + assert(count <= size()-offset); + return span{mData+offset, count}; + } + return span{mData+offset, size()-offset}; } - +/* NOLINTEND(google-explicit-constructor) */ template span(T, EndOrSize) -> span())>>; template -span(T (&)[N]) -> span; +span(T (&)[N]) -> span; /* NOLINT(*-avoid-c-arrays) */ template span(std::array&) -> span; @@ -314,7 +454,7 @@ template span(const std::array&) -> span; template)> -span(C&&) -> span()))>>; +span(C&&) -> span()))>>; #undef REQUIRES diff --git a/3rdparty/openal/common/alstring.cpp b/3rdparty/openal/common/alstring.cpp index 4a84be1db24a..d609823dfc48 100644 --- a/3rdparty/openal/common/alstring.cpp +++ b/3rdparty/openal/common/alstring.cpp @@ -3,42 +3,51 @@ #include "alstring.h" +#include #include -#include +#include +#include -namespace { +namespace al { -int to_upper(const char ch) +int case_compare(const std::string_view str0, const std::string_view str1) noexcept { - using char8_traits = std::char_traits; - return std::toupper(char8_traits::to_int_type(ch)); -} - -} // namespace + using Traits = std::string_view::traits_type; -namespace al { + auto ch0 = str0.cbegin(); + auto ch1 = str1.cbegin(); + auto ch1end = ch1 + std::min(str0.size(), str1.size()); + while(ch1 != ch1end) + { + const int u0{std::toupper(Traits::to_int_type(*ch0))}; + const int u1{std::toupper(Traits::to_int_type(*ch1))}; + if(const int diff{u0-u1}) return diff; + ++ch0; ++ch1; + } -int strcasecmp(const char *str0, const char *str1) noexcept -{ - do { - const int diff{to_upper(*str0) - to_upper(*str1)}; - if(diff < 0) return -1; - if(diff > 0) return 1; - } while(*(str0++) && *(str1++)); + if(str0.size() < str1.size()) return -1; + if(str0.size() > str1.size()) return 1; return 0; } -int strncasecmp(const char *str0, const char *str1, std::size_t len) noexcept +int case_compare(const std::wstring_view str0, const std::wstring_view str1) noexcept { - if(len > 0) + using Traits = std::wstring_view::traits_type; + + auto ch0 = str0.cbegin(); + auto ch1 = str1.cbegin(); + auto ch1end = ch1 + std::min(str0.size(), str1.size()); + while(ch1 != ch1end) { - do { - const int diff{to_upper(*str0) - to_upper(*str1)}; - if(diff < 0) return -1; - if(diff > 0) return 1; - } while(--len && *(str0++) && *(str1++)); + const auto u0 = std::towupper(Traits::to_int_type(*ch0)); + const auto u1 = std::towupper(Traits::to_int_type(*ch1)); + if(const auto diff = static_cast(u0-u1)) return diff; + ++ch0; ++ch1; } + + if(str0.size() < str1.size()) return -1; + if(str0.size() > str1.size()) return 1; return 0; } diff --git a/3rdparty/openal/common/alstring.h b/3rdparty/openal/common/alstring.h index 6c5004ee1abe..c03936136724 100644 --- a/3rdparty/openal/common/alstring.h +++ b/3rdparty/openal/common/alstring.h @@ -1,17 +1,58 @@ #ifndef AL_STRING_H #define AL_STRING_H +#include #include -#include +#include +#include +#include namespace al { -/* These would be better served by using a string_view-like span/view with - * case-insensitive char traits. +template +[[nodiscard]] constexpr +auto sizei(const std::basic_string_view str) noexcept -> int +{ return static_cast(std::min(str.size(), std::numeric_limits::max())); } + +template +[[nodiscard]] constexpr +auto sizei(const std::basic_string &str) noexcept -> int +{ return static_cast(std::min(str.size(), std::numeric_limits::max())); } + + +[[nodiscard]] +constexpr bool contains(const std::string_view str0, const std::string_view str1) noexcept +{ return str0.find(str1) != std::string_view::npos; } + +[[nodiscard]] +constexpr bool starts_with(const std::string_view str0, const std::string_view str1) noexcept +{ return str0.substr(0, std::min(str0.size(), str1.size())) == str1; } + +[[nodiscard]] +constexpr bool ends_with(const std::string_view str0, const std::string_view str1) noexcept +{ return str0.substr(str0.size() - std::min(str0.size(), str1.size())) == str1; } + +[[nodiscard]] +int case_compare(const std::string_view str0, const std::string_view str1) noexcept; + +[[nodiscard]] +int case_compare(const std::wstring_view str0, const std::wstring_view str1) noexcept; + +/* C++20 changes path::u8string() to return a string using a new/distinct + * char8_t type for UTF-8 strings. However, support for this with standard + * string functions is totally inadequate, and we already hold UTF-8 with plain + * char strings. So this function is used to reinterpret a char8_t string as a + * char string_view. */ -int strcasecmp(const char *str0, const char *str1) noexcept; -int strncasecmp(const char *str0, const char *str1, std::size_t len) noexcept; +#if defined(__cpp_lib_char8_t) && __cpp_lib_char8_t >= 201907L +inline auto u8_as_char(const std::u8string_view str) -> std::string_view +#else +inline auto u8_as_char(const std::string_view str) -> std::string_view +#endif +{ + return std::string_view{reinterpret_cast(str.data()), str.size()}; +} } // namespace al diff --git a/3rdparty/openal/common/althrd_setname.cpp b/3rdparty/openal/common/althrd_setname.cpp index 22d330923f4f..b92b05d1c91f 100644 --- a/3rdparty/openal/common/althrd_setname.cpp +++ b/3rdparty/openal/common/althrd_setname.cpp @@ -14,13 +14,14 @@ void althrd_setname(const char *name [[maybe_unused]]) #define MS_VC_EXCEPTION 0x406D1388 #pragma pack(push,8) - struct { + struct InfoStruct { DWORD dwType; // Must be 0x1000. LPCSTR szName; // Pointer to name (in user addr space). DWORD dwThreadID; // Thread ID (-1=caller thread). DWORD dwFlags; // Reserved for future use, must be zero. - } info; + }; #pragma pack(pop) + InfoStruct info{}; info.dwType = 0x1000; info.szName = name; info.dwThreadID = ~DWORD{0}; @@ -60,7 +61,7 @@ using setname_t4 = int(*)(pthread_t, const char*, void*); { func(pthread_self(), name); } [[maybe_unused]] void setname_caller(setname_t4 func, const char *name) -{ func(pthread_self(), "%s", static_cast(const_cast(name))); } +{ func(pthread_self(), "%s", const_cast(name)); /* NOLINT(*-const-cast) */ } } // namespace diff --git a/3rdparty/openal/common/althreads.h b/3rdparty/openal/common/althreads.h new file mode 100644 index 000000000000..66e62e555680 --- /dev/null +++ b/3rdparty/openal/common/althreads.h @@ -0,0 +1,143 @@ +#ifndef AL_THREADS_H +#define AL_THREADS_H + +#include +#include +#include + +#ifdef _WIN32 +#define WIN32_LEAN_AND_MEAN +#include + +#elif defined(__STDC_NO_THREADS__) || !__has_include() + +#include + +#else + +#include +#endif + +#include "albit.h" + +namespace al { + +template +class tss { + static_assert(sizeof(T) <= sizeof(void*)); + static_assert(std::is_trivially_destructible_v && std::is_trivially_copy_constructible_v); + + [[nodiscard]] + static auto to_ptr(const T &value) noexcept -> void* + { + if constexpr(std::is_pointer_v) + { + if constexpr(std::is_const_v>) + return const_cast(static_cast(value)); /* NOLINT(*-const-cast) */ + else + return static_cast(value); + } + else if constexpr(sizeof(T) == sizeof(void*)) + return al::bit_cast(value); + else if constexpr(std::is_integral_v) + return al::bit_cast(static_cast(value)); + } + + [[nodiscard]] + static auto from_ptr(void *ptr) noexcept -> T + { + if constexpr(std::is_pointer_v) + return static_cast(ptr); + else if constexpr(sizeof(T) == sizeof(void*)) + return al::bit_cast(ptr); + else if constexpr(std::is_integral_v) + return static_cast(al::bit_cast(ptr)); + } + +#ifdef _WIN32 + DWORD mTss{TLS_OUT_OF_INDEXES}; + +public: + tss() : mTss{TlsAlloc()} + { + if(mTss == TLS_OUT_OF_INDEXES) + throw std::runtime_error{"al::tss::tss()"}; + } + explicit tss(const T &init) : tss{} + { + if(TlsSetValue(mTss, to_ptr(init)) == FALSE) + throw std::runtime_error{"al::tss::tss(T)"}; + } + ~tss() { TlsFree(mTss); } + + void set(const T &value) const + { + if(TlsSetValue(mTss, to_ptr(value)) == FALSE) + throw std::runtime_error{"al::tss::set(T)"}; + } + + [[nodiscard]] + auto get() const noexcept -> T { return from_ptr(TlsGetValue(mTss)); } + +#elif defined(__STDC_NO_THREADS__) || !__has_include() + + pthread_key_t mTss{}; + +public: + tss() + { + if(int res{pthread_key_create(&mTss, nullptr)}; res != 0) + throw std::runtime_error{"al::tss::tss()"}; + } + explicit tss(const T &init) : tss{} + { + if(int res{pthread_setspecific(mTss, to_ptr(init))}; res != 0) + throw std::runtime_error{"al::tss::tss(T)"}; + } + ~tss() { pthread_key_delete(mTss); } + + void set(const T &value) const + { + if(int res{pthread_setspecific(mTss, to_ptr(value))}; res != 0) + throw std::runtime_error{"al::tss::set(T)"}; + } + + [[nodiscard]] + auto get() const noexcept -> T { return from_ptr(pthread_getspecific(mTss)); } + +#else + + tss_t mTss{}; + +public: + tss() + { + if(int res{tss_create(&mTss, nullptr)}; res != thrd_success) + throw std::runtime_error{"al::tss::tss()"}; + } + explicit tss(const T &init) : tss{} + { + if(int res{tss_set(mTss, to_ptr(init))}; res != thrd_success) + throw std::runtime_error{"al::tss::tss(T)"}; + } + ~tss() { tss_delete(mTss); } + + void set(const T &value) const + { + if(int res{tss_set(mTss, to_ptr(value))}; res != thrd_success) + throw std::runtime_error{"al::tss::set(T)"}; + } + + [[nodiscard]] + auto get() const noexcept -> T { return from_ptr(tss_get(mTss)); } +#endif /* _WIN32 */ + + tss(const tss&) = delete; + tss(tss&&) = delete; + void operator=(const tss&) = delete; + void operator=(tss&&) = delete; +}; + +} // namespace al + +#endif /* AL_THREADS_H */ diff --git a/3rdparty/openal/common/atomic.h b/3rdparty/openal/common/atomic.h index 5e9b04c6975f..7075b15892f8 100644 --- a/3rdparty/openal/common/atomic.h +++ b/3rdparty/openal/common/atomic.h @@ -2,17 +2,17 @@ #define AL_ATOMIC_H #include +#include +#include +#include "almalloc.h" -using RefCount = std::atomic; - -inline void InitRef(RefCount &ref, unsigned int value) -{ ref.store(value, std::memory_order_relaxed); } -inline unsigned int ReadRef(RefCount &ref) -{ return ref.load(std::memory_order_acquire); } -inline unsigned int IncrementRef(RefCount &ref) +template +auto IncrementRef(std::atomic &ref) noexcept { return ref.fetch_add(1u, std::memory_order_acq_rel)+1u; } -inline unsigned int DecrementRef(RefCount &ref) + +template +auto DecrementRef(std::atomic &ref) noexcept { return ref.fetch_sub(1u, std::memory_order_acq_rel)-1u; } @@ -30,4 +30,75 @@ inline void AtomicReplaceHead(std::atomic &head, T newhead) std::memory_order_acq_rel, std::memory_order_acquire)); } +namespace al { + +template> +class atomic_unique_ptr { + std::atomic> mPointer{}; + + using unique_ptr_t = std::unique_ptr; + +public: + atomic_unique_ptr() = default; + atomic_unique_ptr(const atomic_unique_ptr&) = delete; + explicit atomic_unique_ptr(std::nullptr_t) noexcept { } + explicit atomic_unique_ptr(gsl::owner ptr) noexcept : mPointer{ptr} { } + explicit atomic_unique_ptr(unique_ptr_t&& rhs) noexcept : mPointer{rhs.release()} { } + ~atomic_unique_ptr() + { + if(auto ptr = mPointer.exchange(nullptr, std::memory_order_relaxed)) + D{}(ptr); + } + + auto operator=(const atomic_unique_ptr&) -> atomic_unique_ptr& = delete; + auto operator=(std::nullptr_t) noexcept -> atomic_unique_ptr& + { + if(auto ptr = mPointer.exchange(nullptr)) + D{}(ptr); + return *this; + } + auto operator=(unique_ptr_t&& rhs) noexcept -> atomic_unique_ptr& + { + if(auto ptr = mPointer.exchange(rhs.release())) + D{}(ptr); + return *this; + } + + [[nodiscard]] + auto load(std::memory_order m=std::memory_order_seq_cst) const noexcept -> T* + { return mPointer.load(m); } + void store(std::nullptr_t, std::memory_order m=std::memory_order_seq_cst) noexcept + { + if(auto oldptr = mPointer.exchange(nullptr, m)) + D{}(oldptr); + } + void store(gsl::owner ptr, std::memory_order m=std::memory_order_seq_cst) noexcept + { + if(auto oldptr = mPointer.exchange(ptr, m)) + D{}(oldptr); + } + void store(unique_ptr_t&& ptr, std::memory_order m=std::memory_order_seq_cst) noexcept + { + if(auto oldptr = mPointer.exchange(ptr.release(), m)) + D{}(oldptr); + } + + [[nodiscard]] + auto exchange(std::nullptr_t, std::memory_order m=std::memory_order_seq_cst) noexcept -> unique_ptr_t + { return unique_ptr_t{mPointer.exchange(nullptr, m)}; } + [[nodiscard]] + auto exchange(gsl::owner ptr, std::memory_order m=std::memory_order_seq_cst) noexcept -> unique_ptr_t + { return unique_ptr_t{mPointer.exchange(ptr, m)}; } + [[nodiscard]] + auto exchange(std::unique_ptr&& ptr, std::memory_order m=std::memory_order_seq_cst) noexcept -> unique_ptr_t + { return unique_ptr_t{mPointer.exchange(ptr.release(), m)}; } + + [[nodiscard]] + auto is_lock_free() const noexcept -> bool { return mPointer.is_lock_free(); } + + static constexpr auto is_always_lock_free = std::atomic>::is_always_lock_free; +}; + +} // namespace al + #endif /* AL_ATOMIC_H */ diff --git a/3rdparty/openal/common/comptr.h b/3rdparty/openal/common/comptr.h index 5a733ea2e824..c592f1d051e1 100644 --- a/3rdparty/openal/common/comptr.h +++ b/3rdparty/openal/common/comptr.h @@ -1,13 +1,50 @@ #ifndef COMMON_COMPTR_H #define COMMON_COMPTR_H +#ifdef _WIN32 #include -#include -#include #include -#include -template +#define WIN32_LEAN_AND_MEAN +#include +#include + +struct ComWrapper { + HRESULT mStatus{}; + + ComWrapper(void *reserved, DWORD coinit) + : mStatus{CoInitializeEx(reserved, coinit)} + { } + explicit ComWrapper(DWORD coinit=COINIT_APARTMENTTHREADED) + : mStatus{CoInitializeEx(nullptr, coinit)} + { } + ComWrapper(ComWrapper&& rhs) { mStatus = std::exchange(rhs.mStatus, E_FAIL); } + ComWrapper(const ComWrapper&) = delete; + ~ComWrapper() { if(SUCCEEDED(mStatus)) CoUninitialize(); } + + ComWrapper& operator=(ComWrapper&& rhs) + { + if(SUCCEEDED(mStatus)) + CoUninitialize(); + mStatus = std::exchange(rhs.mStatus, E_FAIL); + return *this; + } + ComWrapper& operator=(const ComWrapper&) = delete; + + [[nodiscard]] + HRESULT status() const noexcept { return mStatus; } + explicit operator bool() const noexcept { return SUCCEEDED(status()); } + + void uninit() + { + if(SUCCEEDED(mStatus)) + CoUninitialize(); + mStatus = E_FAIL; + } +}; + + +template /* NOLINTNEXTLINE(clazy-rule-of-three) False positive */ struct ComPtr { using element_type = T; @@ -18,10 +55,11 @@ struct ComPtr { ComPtr(const ComPtr &rhs) noexcept(RefIsNoexcept) : mPtr{rhs.mPtr} { if(mPtr) mPtr->AddRef(); } ComPtr(ComPtr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; } - ComPtr(std::nullptr_t) noexcept { } + ComPtr(std::nullptr_t) noexcept { } /* NOLINT(google-explicit-constructor) */ explicit ComPtr(T *ptr) noexcept : mPtr{ptr} { } ~ComPtr() { if(mPtr) mPtr->Release(); } + /* NOLINTNEXTLINE(bugprone-unhandled-self-assignment) Yes it is. */ ComPtr& operator=(const ComPtr &rhs) noexcept(RefIsNoexcept) { if constexpr(RefIsNoexcept) @@ -69,43 +107,6 @@ struct ComPtr { private: T *mPtr{nullptr}; }; - - -namespace al { - -template -class out_ptr_t { - static_assert(!std::is_same_v); - - SP &mRes; - std::variant mPtr{}; - -public: - out_ptr_t(SP &res) : mRes{res} { } - ~out_ptr_t() - { - auto set_res = [this](auto &ptr) - { mRes.reset(static_cast(ptr)); }; - std::visit(set_res, mPtr); - } - out_ptr_t(const out_ptr_t&) = delete; - - out_ptr_t& operator=(const out_ptr_t&) = delete; - - operator PT*() noexcept - { return &std::get(mPtr); } - - operator void**() noexcept - { return &mPtr.template emplace(); } -}; - -template -auto out_ptr(SP &res) -{ - using ptype = typename SP::element_type*; - return out_ptr_t{res}; -} - -} // namespace al +#endif /* _WIN32 */ #endif diff --git a/3rdparty/openal/common/dynload.cpp b/3rdparty/openal/common/dynload.cpp index 86c36e003a72..333a9435ee07 100644 --- a/3rdparty/openal/common/dynload.cpp +++ b/3rdparty/openal/common/dynload.cpp @@ -3,13 +3,12 @@ #include "dynload.h" -#include "albit.h" -#include "strutils.h" - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include "strutils.h" + void *LoadLib(const char *name) { std::wstring wname{utf8_to_wstr(name)}; @@ -18,7 +17,7 @@ void *LoadLib(const char *name) void CloseLib(void *handle) { FreeLibrary(static_cast(handle)); } void *GetSymbol(void *handle, const char *name) -{ return al::bit_cast(GetProcAddress(static_cast(handle), name)); } +{ return reinterpret_cast(GetProcAddress(static_cast(handle), name)); } #elif defined(HAVE_DLFCN_H) diff --git a/3rdparty/openal/common/dynload.h b/3rdparty/openal/common/dynload.h index bd9e86f7907f..ce7c8f030076 100644 --- a/3rdparty/openal/common/dynload.h +++ b/3rdparty/openal/common/dynload.h @@ -3,12 +3,16 @@ #if defined(_WIN32) || defined(HAVE_DLFCN_H) -#define HAVE_DYNLOAD +#define HAVE_DYNLOAD 1 void *LoadLib(const char *name); void CloseLib(void *handle); void *GetSymbol(void *handle, const char *name); +#else + +#define HAVE_DYNLOAD 0 + #endif #endif /* AL_DYNLOAD_H */ diff --git a/3rdparty/openal/common/filesystem.cpp b/3rdparty/openal/common/filesystem.cpp new file mode 100644 index 000000000000..58da22a7daed --- /dev/null +++ b/3rdparty/openal/common/filesystem.cpp @@ -0,0 +1,61 @@ +//--------------------------------------------------------------------------------------- +// +// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 +// +//--------------------------------------------------------------------------------------- +// +// Copyright (c) 2018, Steffen Schümann +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//--------------------------------------------------------------------------------------- +// fs_std_impl.hpp - The implementation header for the header/implementation separated usage of +// ghc::filesystem that does nothing if std::filesystem is detected. +// This file can be used to hide the implementation of ghc::filesystem into a single cpp. +// The cpp has to include this before including fs_std_fwd.hpp directly or via a different +// header to work. +//--------------------------------------------------------------------------------------- +#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) + // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus + // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ + #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html + #define GHC_USE_STD_FS + + // Old Apple OSs don't support std::filesystem, though the header is available at compile + // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, + // and watchOS 6.0. + #ifdef __APPLE__ + #include + // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS + // released after std::filesystem, where std::filesystem is always available. + // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ + || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ + || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ + || defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 + #undef GHC_USE_STD_FS + #endif + #endif + #endif +#endif + +#ifndef GHC_USE_STD_FS + #define GHC_FILESYSTEM_IMPLEMENTATION + #include "ghc_filesystem.h" +#endif diff --git a/3rdparty/openal/common/filesystem.h b/3rdparty/openal/common/filesystem.h new file mode 100644 index 000000000000..8d556e87ffb5 --- /dev/null +++ b/3rdparty/openal/common/filesystem.h @@ -0,0 +1,81 @@ +//--------------------------------------------------------------------------------------- +// +// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14 +// +//--------------------------------------------------------------------------------------- +// +// Copyright (c) 2018, Steffen Schümann +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//--------------------------------------------------------------------------------------- +// fs_std_fwd.hpp - The forwarding header for the header/implementation separated usage of +// ghc::filesystem that uses std::filesystem if it detects it. +// This file can be include at any place, where fs::filesystem api is needed while +// not bleeding implementation details (e.g. system includes) into the global namespace, +// as long as one cpp includes fs_std_impl.hpp to deliver the matching implementations. +//--------------------------------------------------------------------------------------- +#ifndef GHC_FILESYSTEM_STD_FWD_H +#define GHC_FILESYSTEM_STD_FWD_H + +#if defined(_MSVC_LANG) && _MSVC_LANG >= 201703L || __cplusplus >= 201703L && defined(__has_include) + // ^ Supports MSVC prior to 15.7 without setting /Zc:__cplusplus to fix __cplusplus + // _MSVC_LANG works regardless. But without the switch, the compiler always reported 199711L: https://blogs.msdn.microsoft.com/vcblog/2018/04/09/msvc-now-correctly-reports-__cplusplus/ + #if __has_include() // Two stage __has_include needed for MSVC 2015 and per https://gcc.gnu.org/onlinedocs/cpp/_005f_005fhas_005finclude.html + #define GHC_USE_STD_FS + + // Old Apple OSs don't support std::filesystem, though the header is available at compile + // time. In particular, std::filesystem is unavailable before macOS 10.15, iOS/tvOS 13.0, + // and watchOS 6.0. + #ifdef __APPLE__ + #include + // Note: This intentionally uses std::filesystem on any new Apple OS, like visionOS + // released after std::filesystem, where std::filesystem is always available. + // (All other ___VERSION_MIN_REQUIREDs will be undefined and thus 0.) + #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500 \ + || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000 \ + || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TV_OS_VERSION_MIN_REQUIRED < 130000 \ + || defined(__WATCH_OS_VERSION_MAX_ALLOWED) && __WATCH_OS_VERSION_MAX_ALLOWED < 60000 + #undef GHC_USE_STD_FS + #endif + #endif + #endif +#endif + +#ifdef GHC_USE_STD_FS + #include + namespace fs { + using namespace std::filesystem; + using ifstream = std::ifstream; + using ofstream = std::ofstream; + using fstream = std::fstream; + } +#else + #define GHC_FILESYSTEM_FWD + #include "ghc_filesystem.h" + + namespace fs { + using namespace ghc::filesystem; + using ifstream = ghc::filesystem::ifstream; + using ofstream = ghc::filesystem::ofstream; + using fstream = ghc::filesystem::fstream; + } +#endif + +#endif // GHC_FILESYSTEM_STD_FWD_H diff --git a/3rdparty/openal/common/flexarray.h b/3rdparty/openal/common/flexarray.h new file mode 100644 index 000000000000..b6f09c20dbd5 --- /dev/null +++ b/3rdparty/openal/common/flexarray.h @@ -0,0 +1,140 @@ +#ifndef AL_FLEXARRAY_H +#define AL_FLEXARRAY_H + +#include +#include +#include +#include +#include +#include + +#include "almalloc.h" +#include "alspan.h" + +namespace al { + +/* Storage for flexible array data. This is trivially destructible if type T is + * trivially destructible. + */ +template::value> +struct alignas(alignment) FlexArrayStorage : al::span { + /* NOLINTBEGIN(bugprone-sizeof-expression) clang-tidy warns about the + * sizeof(T) being suspicious when T is a pointer type, which it will be + * for flexible arrays of pointers. + */ + static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept + { return sizeof(FlexArrayStorage) + sizeof(T)*count + base; } + /* NOLINTEND(bugprone-sizeof-expression) */ + + /* NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) Flexible + * arrays store their payloads after the end of the object, which must be + * the last in the whole parent chain. + */ + explicit FlexArrayStorage(size_t size) noexcept(std::is_nothrow_constructible_v) + : al::span{::new(static_cast(this+1)) T[size], size} + { } + /* NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + ~FlexArrayStorage() = default; + + FlexArrayStorage(const FlexArrayStorage&) = delete; + FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; +}; + +template +struct alignas(alignment) FlexArrayStorage : al::span { + static constexpr size_t Sizeof(size_t count, size_t base=0u) noexcept + { return sizeof(FlexArrayStorage) + sizeof(T)*count + base; } + + /* NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + explicit FlexArrayStorage(size_t size) noexcept(std::is_nothrow_constructible_v) + : al::span{::new(static_cast(this+1)) T[size], size} + { } + /* NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ + ~FlexArrayStorage() { std::destroy(this->begin(), this->end()); } + + FlexArrayStorage(const FlexArrayStorage&) = delete; + FlexArrayStorage& operator=(const FlexArrayStorage&) = delete; +}; + +/* A flexible array type. Used either standalone or at the end of a parent + * struct, to have a run-time-sized array that's embedded with its size. Should + * be used delicately, ensuring there's no additional data after the FlexArray + * member. + */ +template +struct FlexArray { + using element_type = T; + using value_type = std::remove_cv_t; + using index_type = size_t; + using difference_type = ptrdiff_t; + + using pointer = T*; + using const_pointer = const T*; + using reference = T&; + using const_reference = const T&; + + static constexpr std::size_t StorageAlign{std::max(alignof(T), Align)}; + using Storage_t_ = FlexArrayStorage), StorageAlign)>; + + using iterator = typename Storage_t_::iterator; + using const_iterator = typename Storage_t_::const_iterator; + using reverse_iterator = typename Storage_t_::reverse_iterator; + using const_reverse_iterator = typename Storage_t_::const_reverse_iterator; + + const Storage_t_ mStore; + + static constexpr index_type Sizeof(index_type count, index_type base=0u) noexcept + { return Storage_t_::Sizeof(count, base); } + static std::unique_ptr Create(index_type count) + { return std::unique_ptr{new(FamCount{count}) FlexArray{count}}; } + + explicit FlexArray(index_type size) + noexcept(std::is_nothrow_constructible_v) + : mStore{size} + { } + ~FlexArray() = default; + + [[nodiscard]] auto size() const noexcept -> index_type { return mStore.size(); } + [[nodiscard]] auto empty() const noexcept -> bool { return mStore.empty(); } + + [[nodiscard]] auto data() noexcept -> pointer { return mStore.data(); } + [[nodiscard]] auto data() const noexcept -> const_pointer { return mStore.data(); } + + [[nodiscard]] auto operator[](index_type i) noexcept -> reference { return mStore[i]; } + [[nodiscard]] auto operator[](index_type i) const noexcept -> const_reference { return mStore[i]; } + + [[nodiscard]] auto front() noexcept -> reference { return mStore.front(); } + [[nodiscard]] auto front() const noexcept -> const_reference { return mStore.front(); } + + [[nodiscard]] auto back() noexcept -> reference { return mStore.back(); } + [[nodiscard]] auto back() const noexcept -> const_reference { return mStore.back(); } + + [[nodiscard]] auto begin() noexcept -> iterator { return mStore.begin(); } + [[nodiscard]] auto begin() const noexcept -> const_iterator { return mStore.cbegin(); } + [[nodiscard]] auto cbegin() const noexcept -> const_iterator { return mStore.cbegin(); } + [[nodiscard]] auto end() noexcept -> iterator { return mStore.end(); } + [[nodiscard]] auto end() const noexcept -> const_iterator { return mStore.cend(); } + [[nodiscard]] auto cend() const noexcept -> const_iterator { return mStore.cend(); } + + [[nodiscard]] auto rbegin() noexcept -> reverse_iterator { return mStore.rbegin(); } + [[nodiscard]] auto rbegin() const noexcept -> const_reverse_iterator { return mStore.crbegin(); } + [[nodiscard]] auto crbegin() const noexcept -> const_reverse_iterator { return mStore.crbegin(); } + [[nodiscard]] auto rend() noexcept -> reverse_iterator { return mStore.rend(); } + [[nodiscard]] auto rend() const noexcept -> const_reverse_iterator { return mStore.crend(); } + [[nodiscard]] auto crend() const noexcept -> const_reverse_iterator { return mStore.crend(); } + + gsl::owner operator new(size_t, FamCount count) + { return ::operator new[](Sizeof(count), std::align_val_t{alignof(FlexArray)}); } + void operator delete(gsl::owner block, FamCount) noexcept + { ::operator delete[](block, std::align_val_t{alignof(FlexArray)}); } + void operator delete(gsl::owner block) noexcept + { ::operator delete[](block, std::align_val_t{alignof(FlexArray)}); } + + void *operator new(size_t size) = delete; + void *operator new[](size_t size) = delete; + void operator delete[](void *block) = delete; +}; + +} // namespace al + +#endif /* AL_FLEXARRAY_H */ diff --git a/3rdparty/openal/common/ghc_filesystem.h b/3rdparty/openal/common/ghc_filesystem.h new file mode 100644 index 000000000000..b4848b36e202 --- /dev/null +++ b/3rdparty/openal/common/ghc_filesystem.h @@ -0,0 +1,6076 @@ +//--------------------------------------------------------------------------------------- +// +// ghc::filesystem - A C++17-like filesystem implementation for C++11/C++14/C++17/C++20 +// +//--------------------------------------------------------------------------------------- +// +// Copyright (c) 2018, Steffen Schümann +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. +// +//--------------------------------------------------------------------------------------- +#ifndef GHC_FILESYSTEM_H +#define GHC_FILESYSTEM_H + +// #define BSD manifest constant only in +// sys/param.h +#ifndef _WIN32 +#include +#endif + +#ifndef GHC_OS_DETECTED +#if defined(__APPLE__) && defined(__MACH__) +#define GHC_OS_APPLE +#elif defined(__linux__) +#define GHC_OS_LINUX +#if defined(__ANDROID__) +#define GHC_OS_ANDROID +#endif +#elif defined(_WIN64) +#define GHC_OS_WINDOWS +#define GHC_OS_WIN64 +#elif defined(_WIN32) +#define GHC_OS_WINDOWS +#define GHC_OS_WIN32 +#elif defined(__CYGWIN__) +#define GHC_OS_CYGWIN +#elif defined(__sun) && defined(__SVR4) +#define GHC_OS_SOLARIS +#elif defined(__svr4__) +#define GHC_OS_SYS5R4 +#elif defined(BSD) +#define GHC_OS_BSD +#elif defined(__EMSCRIPTEN__) +#define GHC_OS_WEB +#include +#elif defined(__QNX__) +#define GHC_OS_QNX +#elif defined(__HAIKU__) +#define GHC_OS_HAIKU +#else +#error "Operating system currently not supported!" +#endif +#define GHC_OS_DETECTED +#if (defined(_MSVC_LANG) && _MSVC_LANG >= 201703L) +#if _MSVC_LANG == 201703L +#define GHC_FILESYSTEM_RUNNING_CPP17 +#else +#define GHC_FILESYSTEM_RUNNING_CPP20 +#endif +#elif (defined(__cplusplus) && __cplusplus >= 201703L) +#if __cplusplus == 201703L +#define GHC_FILESYSTEM_RUNNING_CPP17 +#else +#define GHC_FILESYSTEM_RUNNING_CPP20 +#endif +#endif +#endif + +#if defined(GHC_FILESYSTEM_IMPLEMENTATION) +#define GHC_EXPAND_IMPL +#define GHC_INLINE +#ifdef GHC_OS_WINDOWS +#ifndef GHC_FS_API +#define GHC_FS_API +#endif +#ifndef GHC_FS_API_CLASS +#define GHC_FS_API_CLASS +#endif +#else +#ifndef GHC_FS_API +#define GHC_FS_API __attribute__((visibility("default"))) +#endif +#ifndef GHC_FS_API_CLASS +#define GHC_FS_API_CLASS __attribute__((visibility("default"))) +#endif +#endif +#elif defined(GHC_FILESYSTEM_FWD) +#define GHC_INLINE +#ifdef GHC_OS_WINDOWS +#ifndef GHC_FS_API +#define GHC_FS_API extern +#endif +#ifndef GHC_FS_API_CLASS +#define GHC_FS_API_CLASS +#endif +#else +#ifndef GHC_FS_API +#define GHC_FS_API extern +#endif +#ifndef GHC_FS_API_CLASS +#define GHC_FS_API_CLASS +#endif +#endif +#else +#define GHC_EXPAND_IMPL +#define GHC_INLINE inline +#ifndef GHC_FS_API +#define GHC_FS_API +#endif +#ifndef GHC_FS_API_CLASS +#define GHC_FS_API_CLASS +#endif +#endif + +#ifdef GHC_EXPAND_IMPL + +#ifdef GHC_OS_WINDOWS +#include +// additional includes +#include +#include +#include +#include +#include +#else +#include +#include +#include +#include +#include +#include +#include +#include +#ifdef GHC_OS_ANDROID +#include +#if __ANDROID_API__ < 12 +#include +#endif +#include +#define statvfs statfs +#else +#include +#endif +#ifdef GHC_OS_CYGWIN +#include +#endif +#if !defined(__ANDROID__) || __ANDROID_API__ >= 26 +#include +#endif +#endif +#ifdef GHC_OS_APPLE +#include +#endif + +#if defined(__cpp_impl_three_way_comparison) && defined(__has_include) +#if __has_include() +#define GHC_HAS_THREEWAY_COMP +#include +#endif +#endif + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#else // GHC_EXPAND_IMPL + +#if defined(__cpp_impl_three_way_comparison) && defined(__has_include) +#if __has_include() +#define GHC_HAS_THREEWAY_COMP +#include +#endif +#endif +#include +#include +#include +#include +#include +#include +#include +#ifdef GHC_OS_WINDOWS +#include +#endif +#endif // GHC_EXPAND_IMPL + +// After standard library includes. +// Standard library support for std::string_view. +#if defined(__cpp_lib_string_view) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 4000) && (__cplusplus >= 201402) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_GLIBCXX_RELEASE) && (_GLIBCXX_RELEASE >= 7) && (__cplusplus >= 201703) +#define GHC_HAS_STD_STRING_VIEW +#elif defined(_MSC_VER) && (_MSC_VER >= 1910 && _MSVC_LANG >= 201703) +#define GHC_HAS_STD_STRING_VIEW +#endif + +// Standard library support for std::experimental::string_view. +#if defined(_LIBCPP_VERSION) && (_LIBCPP_VERSION >= 3700 && _LIBCPP_VERSION < 7000) && (__cplusplus >= 201402) +#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW +#elif defined(__GNUC__) && (((__GNUC__ == 4) && (__GNUC_MINOR__ >= 9)) || (__GNUC__ > 4)) && (__cplusplus >= 201402) +#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW +#elif defined(__GLIBCXX__) && defined(_GLIBCXX_USE_DUAL_ABI) && (__cplusplus >= 201402) +// macro _GLIBCXX_USE_DUAL_ABI is always defined in libstdc++ from gcc-5 and newer +#define GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW +#endif + +#if defined(GHC_HAS_STD_STRING_VIEW) +#include +#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) +#include +#endif + +#if !defined(GHC_OS_WINDOWS) && !defined(PATH_MAX) +#define PATH_MAX 4096 +#endif + +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Behaviour Switches (see README.md, should match the config in test/filesystem_test.cpp): +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Enforce C++17 API where possible when compiling for C++20, handles the following cases: +// * fs::path::u8string() returns std::string instead of std::u8string +// #define GHC_FILESYSTEM_ENFORCE_CPP17_API +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// LWG #2682 disables the since then invalid use of the copy option create_symlinks on directories +// configure LWG conformance () +#define LWG_2682_BEHAVIOUR +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// LWG #2395 makes crate_directory/create_directories not emit an error if there is a regular +// file with that name, it is superseded by P1164R1, so only activate if really needed +// #define LWG_2935_BEHAVIOUR +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// LWG #2936 enables new element wise (more expensive) path comparison +// * if this->root_name().native().compare(p.root_name().native()) != 0 return result +// * if this->has_root_directory() and !p.has_root_directory() return -1 +// * if !this->has_root_directory() and p.has_root_directory() return -1 +// * else result of element wise comparison of path iteration where first comparison is != 0 or 0 +// if all comparisons are 0 (on Windows this implementation does case-insensitive root_name() +// comparison) +#define LWG_2936_BEHAVIOUR +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// LWG #2937 enforces that fs::equivalent emits an error, if !fs::exists(p1)||!exists(p2) +#define LWG_2937_BEHAVIOUR +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// UTF8-Everywhere is the original behaviour of ghc::filesystem. But since v1.5 the Windows +// version defaults to std::wstring storage backend. Still all std::string will be interpreted +// as UTF-8 encoded. With this define you can enforce the old behavior on Windows, using +// std::string as backend and for fs::path::native() and char for fs::path::c_str(). This +// needs more conversions, so it is (and was before v1.5) slower, bot might help keeping source +// homogeneous in a multi-platform project. +// #define GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Raise errors/exceptions when invalid unicode codepoints or UTF-8 sequences are found, +// instead of replacing them with the unicode replacement character (U+FFFD). +// #define GHC_RAISE_UNICODE_ERRORS +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - +// Automatic prefix windows path with "\\?\" if they would break the MAX_PATH length. +// instead of replacing them with the unicode replacement character (U+FFFD). +#ifndef GHC_WIN_DISABLE_AUTO_PREFIXES +#define GHC_WIN_AUTO_PREFIX_LONG_PATH +#endif // GHC_WIN_DISABLE_AUTO_PREFIXES +//- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +// ghc::filesystem version in decimal (major * 10000 + minor * 100 + patch) +#define GHC_FILESYSTEM_VERSION 10515L + +#if !defined(GHC_WITH_EXCEPTIONS) && (defined(__EXCEPTIONS) || defined(__cpp_exceptions) || defined(_CPPUNWIND)) +#define GHC_WITH_EXCEPTIONS +#endif +#if !defined(GHC_WITH_EXCEPTIONS) && defined(GHC_RAISE_UNICODE_ERRORS) +#error "Can't raise unicode errors with exception support disabled" +#endif + +namespace ghc { +namespace filesystem { + +#if defined(GHC_HAS_CUSTOM_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +#elif defined(GHC_HAS_STD_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +using std::basic_string_view; +#elif defined(GHC_HAS_STD_EXPERIMENTAL_STRING_VIEW) +#define GHC_WITH_STRING_VIEW +using std::experimental::basic_string_view; +#endif + +// temporary existing exception type for yet unimplemented parts +class GHC_FS_API_CLASS not_implemented_exception : public std::logic_error +{ +public: + not_implemented_exception() + : std::logic_error("function not implemented yet.") + { + } +}; + +template +class path_helper_base +{ +public: + using value_type = char_type; +#ifdef GHC_OS_WINDOWS + static constexpr value_type preferred_separator = '\\'; +#else + static constexpr value_type preferred_separator = '/'; +#endif +}; + +#if __cplusplus < 201703L +template +constexpr char_type path_helper_base::preferred_separator; +#endif + +#ifdef GHC_OS_WINDOWS +class path; +namespace detail { +bool has_executable_extension(const path& p); +} +#endif + +// [fs.class.path] class path +class GHC_FS_API_CLASS path +#if defined(GHC_OS_WINDOWS) && !defined(GHC_WIN_DISABLE_WSTRING_STORAGE_TYPE) +#define GHC_USE_WCHAR_T +#define GHC_NATIVEWP(p) p.c_str() +#define GHC_PLATFORM_LITERAL(str) L##str + : private path_helper_base +{ +public: + using path_helper_base::value_type; +#else +#define GHC_NATIVEWP(p) p.wstring().c_str() +#define GHC_PLATFORM_LITERAL(str) str + : private path_helper_base +{ +public: + using path_helper_base::value_type; +#endif + using string_type = std::basic_string; + using path_helper_base::preferred_separator; + + // [fs.enum.path.format] enumeration format + /// The path format in which the constructor argument is given. + enum format { + generic_format, ///< The generic format, internally used by + ///< ghc::filesystem::path with slashes + native_format, ///< The format native to the current platform this code + ///< is build for + auto_format, ///< Try to auto-detect the format, fallback to native + }; + + template + struct _is_basic_string : std::false_type + { + }; + template + struct _is_basic_string> : std::true_type + { + }; + template + struct _is_basic_string, std::allocator>> : std::true_type + { + }; +#ifdef GHC_WITH_STRING_VIEW + template + struct _is_basic_string> : std::true_type + { + }; + template + struct _is_basic_string>> : std::true_type + { + }; +#endif + + template + using path_type = typename std::enable_if::value, path>::type; + template +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) + using path_from_string = + typename std::enable_if<_is_basic_string::value || std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || + std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || + std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || + std::is_same::type>::value, + path>::type; + template + using path_type_EcharT = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value || std::is_same::value, path>::type; +#else + using path_from_string = + typename std::enable_if<_is_basic_string::value || std::is_same::type>::value || std::is_same::type>::value || + std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value || + std::is_same::type>::value || std::is_same::type>::value || std::is_same::type>::value, + path>::type; + template + using path_type_EcharT = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, path>::type; +#endif + // [fs.path.construct] constructors and destructor + path() noexcept; + path(const path& p); + path(path&& p) noexcept; + path(string_type&& source, format fmt = auto_format); + template > + path(const Source& source, format fmt = auto_format); + template + path(InputIterator first, InputIterator last, format fmt = auto_format); +#ifdef GHC_WITH_EXCEPTIONS + template > + path(const Source& source, const std::locale& loc, format fmt = auto_format); + template + path(InputIterator first, InputIterator last, const std::locale& loc, format fmt = auto_format); +#endif + ~path(); + + // [fs.path.assign] assignments + path& operator=(const path& p); + path& operator=(path&& p) noexcept; + path& operator=(string_type&& source); + path& assign(string_type&& source); + template + path& operator=(const Source& source); + template + path& assign(const Source& source); + template + path& assign(InputIterator first, InputIterator last); + + // [fs.path.append] appends + path& operator/=(const path& p); + template + path& operator/=(const Source& source); + template + path& append(const Source& source); + template + path& append(InputIterator first, InputIterator last); + + // [fs.path.concat] concatenation + path& operator+=(const path& x); + path& operator+=(const string_type& x); +#ifdef GHC_WITH_STRING_VIEW + path& operator+=(basic_string_view x); +#endif + path& operator+=(const value_type* x); + path& operator+=(value_type x); + template + path_from_string& operator+=(const Source& x); + template + path_type_EcharT& operator+=(EcharT x); + template + path& concat(const Source& x); + template + path& concat(InputIterator first, InputIterator last); + + // [fs.path.modifiers] modifiers + void clear() noexcept; + path& make_preferred(); + path& remove_filename(); + path& replace_filename(const path& replacement); + path& replace_extension(const path& replacement = path()); + void swap(path& rhs) noexcept; + + // [fs.path.native.obs] native format observers + const string_type& native() const noexcept; + const value_type* c_str() const noexcept; + operator string_type() const; + template , class Allocator = std::allocator> + std::basic_string string(const Allocator& a = Allocator()) const; + std::string string() const; + std::wstring wstring() const; +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) + std::u8string u8string() const; +#else + std::string u8string() const; +#endif + std::u16string u16string() const; + std::u32string u32string() const; + + // [fs.path.generic.obs] generic format observers + template , class Allocator = std::allocator> + std::basic_string generic_string(const Allocator& a = Allocator()) const; + std::string generic_string() const; + std::wstring generic_wstring() const; +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) + std::u8string generic_u8string() const; +#else + std::string generic_u8string() const; +#endif + std::u16string generic_u16string() const; + std::u32string generic_u32string() const; + + // [fs.path.compare] compare + int compare(const path& p) const noexcept; + int compare(const string_type& s) const; +#ifdef GHC_WITH_STRING_VIEW + int compare(basic_string_view s) const; +#endif + int compare(const value_type* s) const; + + // [fs.path.decompose] decomposition + path root_name() const; + path root_directory() const; + path root_path() const; + path relative_path() const; + path parent_path() const; + path filename() const; + path stem() const; + path extension() const; + + // [fs.path.query] query + bool empty() const noexcept; + bool has_root_name() const; + bool has_root_directory() const; + bool has_root_path() const; + bool has_relative_path() const; + bool has_parent_path() const; + bool has_filename() const; + bool has_stem() const; + bool has_extension() const; + bool is_absolute() const; + bool is_relative() const; + + // [fs.path.gen] generation + path lexically_normal() const; + path lexically_relative(const path& base) const; + path lexically_proximate(const path& base) const; + + // [fs.path.itr] iterators + class iterator; + using const_iterator = iterator; + iterator begin() const; + iterator end() const; + +private: + using impl_value_type = value_type; + using impl_string_type = std::basic_string; + friend class directory_iterator; + void append_name(const value_type* name); + static constexpr impl_value_type generic_separator = '/'; + template + class input_iterator_range + { + public: + typedef InputIterator iterator; + typedef InputIterator const_iterator; + typedef typename InputIterator::difference_type difference_type; + + input_iterator_range(const InputIterator& first, const InputIterator& last) + : _first(first) + , _last(last) + { + } + + InputIterator begin() const { return _first; } + InputIterator end() const { return _last; } + + private: + InputIterator _first; + InputIterator _last; + }; + friend void swap(path& lhs, path& rhs) noexcept; + friend size_t hash_value(const path& p) noexcept; + friend path canonical(const path& p, std::error_code& ec); + friend bool create_directories(const path& p, std::error_code& ec) noexcept; + string_type::size_type root_name_length() const noexcept; + void postprocess_path_with_format(format fmt); + void check_long_path(); + impl_string_type _path; +#ifdef GHC_OS_WINDOWS + void handle_prefixes(); + friend bool detail::has_executable_extension(const path& p); +#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH + string_type::size_type _prefixLength{0}; +#else // GHC_WIN_AUTO_PREFIX_LONG_PATH + static const string_type::size_type _prefixLength{0}; +#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH +#else + static const string_type::size_type _prefixLength{0}; +#endif +}; + +// [fs.path.nonmember] path non-member functions +GHC_FS_API void swap(path& lhs, path& rhs) noexcept; +GHC_FS_API size_t hash_value(const path& p) noexcept; +#ifdef GHC_HAS_THREEWAY_COMP +GHC_FS_API std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept; +#endif +GHC_FS_API bool operator==(const path& lhs, const path& rhs) noexcept; +GHC_FS_API bool operator!=(const path& lhs, const path& rhs) noexcept; +GHC_FS_API bool operator<(const path& lhs, const path& rhs) noexcept; +GHC_FS_API bool operator<=(const path& lhs, const path& rhs) noexcept; +GHC_FS_API bool operator>(const path& lhs, const path& rhs) noexcept; +GHC_FS_API bool operator>=(const path& lhs, const path& rhs) noexcept; +GHC_FS_API path operator/(const path& lhs, const path& rhs); + +// [fs.path.io] path inserter and extractor +template +std::basic_ostream& operator<<(std::basic_ostream& os, const path& p); +template +std::basic_istream& operator>>(std::basic_istream& is, path& p); + +// [pfs.path.factory] path factory functions +template > +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) +[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]] +#endif +path u8path(const Source& source); +template +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) +[[deprecated("use ghc::filesystem::path::path() with std::u8string instead")]] +#endif +path u8path(InputIterator first, InputIterator last); + +// [fs.class.filesystem_error] class filesystem_error +class GHC_FS_API_CLASS filesystem_error : public std::system_error +{ +public: + filesystem_error(const std::string& what_arg, std::error_code ec); + filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec); + filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec); + const path& path1() const noexcept; + const path& path2() const noexcept; + const char* what() const noexcept override; + +private: + std::string _what_arg; + std::error_code _ec; + path _p1, _p2; +}; + +class GHC_FS_API_CLASS path::iterator +{ +public: + using value_type = const path; + using difference_type = std::ptrdiff_t; + using pointer = const path*; + using reference = const path&; + using iterator_category = std::bidirectional_iterator_tag; + + iterator(); + iterator(const path& p, const impl_string_type::const_iterator& pos); + iterator& operator++(); + iterator operator++(int); + iterator& operator--(); + iterator operator--(int); + bool operator==(const iterator& other) const; + bool operator!=(const iterator& other) const; + reference operator*() const; + pointer operator->() const; + +private: + friend class path; + impl_string_type::const_iterator increment(const impl_string_type::const_iterator& pos) const; + impl_string_type::const_iterator decrement(const impl_string_type::const_iterator& pos) const; + void updateCurrent(); + impl_string_type::const_iterator _first; + impl_string_type::const_iterator _last; + impl_string_type::const_iterator _prefix; + impl_string_type::const_iterator _root; + impl_string_type::const_iterator _iter; + path _current; +}; + +struct space_info +{ + uintmax_t capacity; + uintmax_t free; + uintmax_t available; +}; + +// [fs.enum] enumerations +// [fs.enum.file_type] +enum class file_type { + none, + not_found, + regular, + directory, + symlink, + block, + character, + fifo, + socket, + unknown, +}; + +// [fs.enum.perms] +enum class perms : uint16_t { + none = 0, + + owner_read = 0400, + owner_write = 0200, + owner_exec = 0100, + owner_all = 0700, + + group_read = 040, + group_write = 020, + group_exec = 010, + group_all = 070, + + others_read = 04, + others_write = 02, + others_exec = 01, + others_all = 07, + + all = 0777, + set_uid = 04000, + set_gid = 02000, + sticky_bit = 01000, + + mask = 07777, + unknown = 0xffff +}; + +// [fs.enum.perm.opts] +enum class perm_options : uint16_t { + replace = 3, + add = 1, + remove = 2, + nofollow = 4, +}; + +// [fs.enum.copy.opts] +enum class copy_options : uint16_t { + none = 0, + + skip_existing = 1, + overwrite_existing = 2, + update_existing = 4, + + recursive = 8, + + copy_symlinks = 0x10, + skip_symlinks = 0x20, + + directories_only = 0x40, + create_symlinks = 0x80, +#ifndef GHC_OS_WEB + create_hard_links = 0x100 +#endif +}; + +// [fs.enum.dir.opts] +enum class directory_options : uint16_t { + none = 0, + follow_directory_symlink = 1, + skip_permission_denied = 2, +}; + +// [fs.class.file_status] class file_status +class GHC_FS_API_CLASS file_status +{ +public: + // [fs.file_status.cons] constructors and destructor + file_status() noexcept; + explicit file_status(file_type ft, perms prms = perms::unknown) noexcept; + file_status(const file_status&) noexcept; + file_status(file_status&&) noexcept; + ~file_status(); + // assignments: + file_status& operator=(const file_status&) noexcept; + file_status& operator=(file_status&&) noexcept; + // [fs.file_status.mods] modifiers + void type(file_type ft) noexcept; + void permissions(perms prms) noexcept; + // [fs.file_status.obs] observers + file_type type() const noexcept; + perms permissions() const noexcept; + friend bool operator==(const file_status& lhs, const file_status& rhs) noexcept { return lhs.type() == rhs.type() && lhs.permissions() == rhs.permissions(); } + +private: + file_type _type; + perms _perms; +}; + +using file_time_type = std::chrono::time_point; + +// [fs.class.directory_entry] Class directory_entry +class GHC_FS_API_CLASS directory_entry +{ +public: + // [fs.dir.entry.cons] constructors and destructor + directory_entry() noexcept = default; + directory_entry(const directory_entry&) = default; + directory_entry(directory_entry&&) noexcept = default; +#ifdef GHC_WITH_EXCEPTIONS + explicit directory_entry(const path& p); +#endif + directory_entry(const path& p, std::error_code& ec); + ~directory_entry(); + + // assignments: + directory_entry& operator=(const directory_entry&) = default; + directory_entry& operator=(directory_entry&&) noexcept = default; + + // [fs.dir.entry.mods] modifiers +#ifdef GHC_WITH_EXCEPTIONS + void assign(const path& p); + void replace_filename(const path& p); + void refresh(); +#endif + void assign(const path& p, std::error_code& ec); + void replace_filename(const path& p, std::error_code& ec); + void refresh(std::error_code& ec) noexcept; + + // [fs.dir.entry.obs] observers + const filesystem::path& path() const noexcept; + operator const filesystem::path&() const noexcept; +#ifdef GHC_WITH_EXCEPTIONS + bool exists() const; + bool is_block_file() const; + bool is_character_file() const; + bool is_directory() const; + bool is_fifo() const; + bool is_other() const; + bool is_regular_file() const; + bool is_socket() const; + bool is_symlink() const; + uintmax_t file_size() const; + file_time_type last_write_time() const; + file_status status() const; + file_status symlink_status() const; +#endif + bool exists(std::error_code& ec) const noexcept; + bool is_block_file(std::error_code& ec) const noexcept; + bool is_character_file(std::error_code& ec) const noexcept; + bool is_directory(std::error_code& ec) const noexcept; + bool is_fifo(std::error_code& ec) const noexcept; + bool is_other(std::error_code& ec) const noexcept; + bool is_regular_file(std::error_code& ec) const noexcept; + bool is_socket(std::error_code& ec) const noexcept; + bool is_symlink(std::error_code& ec) const noexcept; + uintmax_t file_size(std::error_code& ec) const noexcept; + file_time_type last_write_time(std::error_code& ec) const noexcept; + file_status status(std::error_code& ec) const noexcept; + file_status symlink_status(std::error_code& ec) const noexcept; + +#ifndef GHC_OS_WEB +#ifdef GHC_WITH_EXCEPTIONS + uintmax_t hard_link_count() const; +#endif + uintmax_t hard_link_count(std::error_code& ec) const noexcept; +#endif + +#ifdef GHC_HAS_THREEWAY_COMP + std::strong_ordering operator<=>(const directory_entry& rhs) const noexcept; +#endif + bool operator<(const directory_entry& rhs) const noexcept; + bool operator==(const directory_entry& rhs) const noexcept; + bool operator!=(const directory_entry& rhs) const noexcept; + bool operator<=(const directory_entry& rhs) const noexcept; + bool operator>(const directory_entry& rhs) const noexcept; + bool operator>=(const directory_entry& rhs) const noexcept; + +private: + friend class directory_iterator; +#ifdef GHC_WITH_EXCEPTIONS + file_type status_file_type() const; +#endif + file_type status_file_type(std::error_code& ec) const noexcept; + filesystem::path _path; + file_status _status; + file_status _symlink_status; + uintmax_t _file_size = static_cast(-1); +#ifndef GHC_OS_WINDOWS + uintmax_t _hard_link_count = static_cast(-1); +#endif + time_t _last_write_time = 0; +}; + +// [fs.class.directory.iterator] Class directory_iterator +class GHC_FS_API_CLASS directory_iterator +{ +public: + class GHC_FS_API_CLASS proxy + { + public: + const directory_entry& operator*() const& noexcept { return _dir_entry; } + directory_entry operator*() && noexcept { return std::move(_dir_entry); } + + private: + explicit proxy(const directory_entry& dir_entry) + : _dir_entry(dir_entry) + { + } + friend class directory_iterator; + friend class recursive_directory_iterator; + directory_entry _dir_entry; + }; + using iterator_category = std::input_iterator_tag; + using value_type = directory_entry; + using difference_type = std::ptrdiff_t; + using pointer = const directory_entry*; + using reference = const directory_entry&; + + // [fs.dir.itr.members] member functions + directory_iterator() noexcept; +#ifdef GHC_WITH_EXCEPTIONS + explicit directory_iterator(const path& p); + directory_iterator(const path& p, directory_options options); +#endif + directory_iterator(const path& p, std::error_code& ec) noexcept; + directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept; + directory_iterator(const directory_iterator& rhs); + directory_iterator(directory_iterator&& rhs) noexcept; + ~directory_iterator(); + directory_iterator& operator=(const directory_iterator& rhs); + directory_iterator& operator=(directory_iterator&& rhs) noexcept; + const directory_entry& operator*() const; + const directory_entry* operator->() const; +#ifdef GHC_WITH_EXCEPTIONS + directory_iterator& operator++(); +#endif + directory_iterator& increment(std::error_code& ec) noexcept; + + // other members as required by [input.iterators] +#ifdef GHC_WITH_EXCEPTIONS + proxy operator++(int) + { + proxy p{**this}; + ++*this; + return p; + } +#endif + bool operator==(const directory_iterator& rhs) const; + bool operator!=(const directory_iterator& rhs) const; + +private: + friend class recursive_directory_iterator; + class impl; + std::shared_ptr _impl; +}; + +// [fs.dir.itr.nonmembers] directory_iterator non-member functions +GHC_FS_API directory_iterator begin(directory_iterator iter) noexcept; +GHC_FS_API directory_iterator end(const directory_iterator&) noexcept; + +// [fs.class.re.dir.itr] class recursive_directory_iterator +class GHC_FS_API_CLASS recursive_directory_iterator +{ +public: + using iterator_category = std::input_iterator_tag; + using value_type = directory_entry; + using difference_type = std::ptrdiff_t; + using pointer = const directory_entry*; + using reference = const directory_entry&; + + // [fs.rec.dir.itr.members] constructors and destructor + recursive_directory_iterator() noexcept; +#ifdef GHC_WITH_EXCEPTIONS + explicit recursive_directory_iterator(const path& p); + recursive_directory_iterator(const path& p, directory_options options); +#endif + recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept; + recursive_directory_iterator(const path& p, std::error_code& ec) noexcept; + recursive_directory_iterator(const recursive_directory_iterator& rhs); + recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept; + ~recursive_directory_iterator(); + + // [fs.rec.dir.itr.members] observers + directory_options options() const; + int depth() const; + bool recursion_pending() const; + + const directory_entry& operator*() const; + const directory_entry* operator->() const; + + // [fs.rec.dir.itr.members] modifiers recursive_directory_iterator& + recursive_directory_iterator& operator=(const recursive_directory_iterator& rhs); + recursive_directory_iterator& operator=(recursive_directory_iterator&& rhs) noexcept; +#ifdef GHC_WITH_EXCEPTIONS + recursive_directory_iterator& operator++(); +#endif + recursive_directory_iterator& increment(std::error_code& ec) noexcept; + +#ifdef GHC_WITH_EXCEPTIONS + void pop(); +#endif + void pop(std::error_code& ec); + void disable_recursion_pending(); + + // other members as required by [input.iterators] +#ifdef GHC_WITH_EXCEPTIONS + directory_iterator::proxy operator++(int) + { + directory_iterator::proxy proxy{**this}; + ++*this; + return proxy; + } +#endif + bool operator==(const recursive_directory_iterator& rhs) const; + bool operator!=(const recursive_directory_iterator& rhs) const; + +private: + struct recursive_directory_iterator_impl + { + directory_options _options; + bool _recursion_pending; + std::stack _dir_iter_stack; + recursive_directory_iterator_impl(directory_options options, bool recursion_pending) + : _options(options) + , _recursion_pending(recursion_pending) + { + } + }; + std::shared_ptr _impl; +}; + +// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions +GHC_FS_API recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept; +GHC_FS_API recursive_directory_iterator end(const recursive_directory_iterator&) noexcept; + +// [fs.op.funcs] filesystem operations +#ifdef GHC_WITH_EXCEPTIONS +GHC_FS_API path absolute(const path& p); +GHC_FS_API path canonical(const path& p); +GHC_FS_API void copy(const path& from, const path& to); +GHC_FS_API void copy(const path& from, const path& to, copy_options options); +GHC_FS_API bool copy_file(const path& from, const path& to); +GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option); +GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink); +GHC_FS_API bool create_directories(const path& p); +GHC_FS_API bool create_directory(const path& p); +GHC_FS_API bool create_directory(const path& p, const path& attributes); +GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink); +GHC_FS_API void create_symlink(const path& to, const path& new_symlink); +GHC_FS_API path current_path(); +GHC_FS_API void current_path(const path& p); +GHC_FS_API bool exists(const path& p); +GHC_FS_API bool equivalent(const path& p1, const path& p2); +GHC_FS_API uintmax_t file_size(const path& p); +GHC_FS_API bool is_block_file(const path& p); +GHC_FS_API bool is_character_file(const path& p); +GHC_FS_API bool is_directory(const path& p); +GHC_FS_API bool is_empty(const path& p); +GHC_FS_API bool is_fifo(const path& p); +GHC_FS_API bool is_other(const path& p); +GHC_FS_API bool is_regular_file(const path& p); +GHC_FS_API bool is_socket(const path& p); +GHC_FS_API bool is_symlink(const path& p); +GHC_FS_API file_time_type last_write_time(const path& p); +GHC_FS_API void last_write_time(const path& p, file_time_type new_time); +GHC_FS_API void permissions(const path& p, perms prms, perm_options opts = perm_options::replace); +GHC_FS_API path proximate(const path& p, const path& base = current_path()); +GHC_FS_API path read_symlink(const path& p); +GHC_FS_API path relative(const path& p, const path& base = current_path()); +GHC_FS_API bool remove(const path& p); +GHC_FS_API uintmax_t remove_all(const path& p); +GHC_FS_API void rename(const path& from, const path& to); +GHC_FS_API void resize_file(const path& p, uintmax_t size); +GHC_FS_API space_info space(const path& p); +GHC_FS_API file_status status(const path& p); +GHC_FS_API file_status symlink_status(const path& p); +GHC_FS_API path temp_directory_path(); +GHC_FS_API path weakly_canonical(const path& p); +#endif +GHC_FS_API path absolute(const path& p, std::error_code& ec); +GHC_FS_API path canonical(const path& p, std::error_code& ec); +GHC_FS_API void copy(const path& from, const path& to, std::error_code& ec) noexcept; +GHC_FS_API void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept; +GHC_FS_API bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept; +GHC_FS_API bool copy_file(const path& from, const path& to, copy_options option, std::error_code& ec) noexcept; +GHC_FS_API void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API bool create_directories(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool create_directory(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept; +GHC_FS_API void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept; +GHC_FS_API path current_path(std::error_code& ec); +GHC_FS_API void current_path(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool exists(file_status s) noexcept; +GHC_FS_API bool exists(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept; +GHC_FS_API uintmax_t file_size(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_block_file(file_status s) noexcept; +GHC_FS_API bool is_block_file(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_character_file(file_status s) noexcept; +GHC_FS_API bool is_character_file(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_directory(file_status s) noexcept; +GHC_FS_API bool is_directory(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_empty(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_fifo(file_status s) noexcept; +GHC_FS_API bool is_fifo(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_other(file_status s) noexcept; +GHC_FS_API bool is_other(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_regular_file(file_status s) noexcept; +GHC_FS_API bool is_regular_file(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_socket(file_status s) noexcept; +GHC_FS_API bool is_socket(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool is_symlink(file_status s) noexcept; +GHC_FS_API bool is_symlink(const path& p, std::error_code& ec) noexcept; +GHC_FS_API file_time_type last_write_time(const path& p, std::error_code& ec) noexcept; +GHC_FS_API void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept; +GHC_FS_API void permissions(const path& p, perms prms, std::error_code& ec) noexcept; +GHC_FS_API void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept; +GHC_FS_API path proximate(const path& p, std::error_code& ec); +GHC_FS_API path proximate(const path& p, const path& base, std::error_code& ec); +GHC_FS_API path read_symlink(const path& p, std::error_code& ec); +GHC_FS_API path relative(const path& p, std::error_code& ec); +GHC_FS_API path relative(const path& p, const path& base, std::error_code& ec); +GHC_FS_API bool remove(const path& p, std::error_code& ec) noexcept; +GHC_FS_API uintmax_t remove_all(const path& p, std::error_code& ec) noexcept; +GHC_FS_API void rename(const path& from, const path& to, std::error_code& ec) noexcept; +GHC_FS_API void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept; +GHC_FS_API space_info space(const path& p, std::error_code& ec) noexcept; +GHC_FS_API file_status status(const path& p, std::error_code& ec) noexcept; +GHC_FS_API bool status_known(file_status s) noexcept; +GHC_FS_API file_status symlink_status(const path& p, std::error_code& ec) noexcept; +GHC_FS_API path temp_directory_path(std::error_code& ec) noexcept; +GHC_FS_API path weakly_canonical(const path& p, std::error_code& ec) noexcept; + +#ifndef GHC_OS_WEB +#ifdef GHC_WITH_EXCEPTIONS +GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link); +GHC_FS_API uintmax_t hard_link_count(const path& p); +#endif +GHC_FS_API void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept; +GHC_FS_API uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept; +#endif + +#if defined(GHC_OS_WINDOWS) && (!defined(__GLIBCXX__) || (defined(_GLIBCXX_HAVE__WFOPEN) && defined(_GLIBCXX_USE_WCHAR_T))) +#define GHC_HAS_FSTREAM_OPEN_WITH_WCHAR +#endif + +// Non-C++17 add-on std::fstream wrappers with path +template > +class basic_filebuf : public std::basic_filebuf +{ +public: + basic_filebuf() {} + ~basic_filebuf() override {} + basic_filebuf(const basic_filebuf&) = delete; + const basic_filebuf& operator=(const basic_filebuf&) = delete; + basic_filebuf* open(const path& p, std::ios_base::openmode mode) + { +#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR + return std::basic_filebuf::open(p.wstring().c_str(), mode) ? this : 0; +#else + return std::basic_filebuf::open(p.string().c_str(), mode) ? this : 0; +#endif + } +}; + +template > +class basic_ifstream : public std::basic_ifstream +{ +public: + basic_ifstream() {} +#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR + explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in) + : std::basic_ifstream(p.wstring().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream::open(p.wstring().c_str(), mode); } +#else + explicit basic_ifstream(const path& p, std::ios_base::openmode mode = std::ios_base::in) + : std::basic_ifstream(p.string().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in) { std::basic_ifstream::open(p.string().c_str(), mode); } +#endif + basic_ifstream(const basic_ifstream&) = delete; + const basic_ifstream& operator=(const basic_ifstream&) = delete; + ~basic_ifstream() override {} +}; + +template > +class basic_ofstream : public std::basic_ofstream +{ +public: + basic_ofstream() {} +#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR + explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out) + : std::basic_ofstream(p.wstring().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream::open(p.wstring().c_str(), mode); } +#else + explicit basic_ofstream(const path& p, std::ios_base::openmode mode = std::ios_base::out) + : std::basic_ofstream(p.string().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::out) { std::basic_ofstream::open(p.string().c_str(), mode); } +#endif + basic_ofstream(const basic_ofstream&) = delete; + const basic_ofstream& operator=(const basic_ofstream&) = delete; + ~basic_ofstream() override {} +}; + +template > +class basic_fstream : public std::basic_fstream +{ +public: + basic_fstream() {} +#ifdef GHC_HAS_FSTREAM_OPEN_WITH_WCHAR + explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + : std::basic_fstream(p.wstring().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream::open(p.wstring().c_str(), mode); } +#else + explicit basic_fstream(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) + : std::basic_fstream(p.string().c_str(), mode) + { + } + void open(const path& p, std::ios_base::openmode mode = std::ios_base::in | std::ios_base::out) { std::basic_fstream::open(p.string().c_str(), mode); } +#endif + basic_fstream(const basic_fstream&) = delete; + const basic_fstream& operator=(const basic_fstream&) = delete; + ~basic_fstream() override {} +}; + +typedef basic_filebuf filebuf; +typedef basic_filebuf wfilebuf; +typedef basic_ifstream ifstream; +typedef basic_ifstream wifstream; +typedef basic_ofstream ofstream; +typedef basic_ofstream wofstream; +typedef basic_fstream fstream; +typedef basic_fstream wfstream; + +class GHC_FS_API_CLASS u8arguments +{ +public: + u8arguments(int& argc, char**& argv); + ~u8arguments() + { + _refargc = _argc; + _refargv = _argv; + } + + bool valid() const { return _isvalid; } + +private: + int _argc; + char** _argv; + int& _refargc; + char**& _refargv; + bool _isvalid; +#ifdef GHC_OS_WINDOWS + std::vector _args; + std::vector _argp; +#endif +}; + +//------------------------------------------------------------------------------------------------- +// Implementation +//------------------------------------------------------------------------------------------------- + +namespace detail { +enum utf8_states_t { S_STRT = 0, S_RJCT = 8 }; +GHC_FS_API void appendUTF8(std::string& str, uint32_t unicode); +GHC_FS_API bool is_surrogate(uint32_t c); +GHC_FS_API bool is_high_surrogate(uint32_t c); +GHC_FS_API bool is_low_surrogate(uint32_t c); +GHC_FS_API unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint); +enum class portable_error { + none = 0, + exists, + not_found, + not_supported, + not_implemented, + invalid_argument, + is_a_directory, +}; +GHC_FS_API std::error_code make_error_code(portable_error err); +#ifdef GHC_OS_WINDOWS +GHC_FS_API std::error_code make_system_error(uint32_t err = 0); +#else +GHC_FS_API std::error_code make_system_error(int err = 0); + +template +struct has_d_type : std::false_type{}; + +template +struct has_d_type : std::true_type {}; + +template +GHC_INLINE file_type file_type_from_dirent_impl(const T&, std::false_type) +{ + return file_type::none; +} + +template +GHC_INLINE file_type file_type_from_dirent_impl(const T& t, std::true_type) +{ + switch (t.d_type) { +#ifdef DT_BLK + case DT_BLK: + return file_type::block; +#endif +#ifdef DT_CHR + case DT_CHR: + return file_type::character; +#endif +#ifdef DT_DIR + case DT_DIR: + return file_type::directory; +#endif +#ifdef DT_FIFO + case DT_FIFO: + return file_type::fifo; +#endif +#ifdef DT_LNK + case DT_LNK: + return file_type::symlink; +#endif +#ifdef DT_REG + case DT_REG: + return file_type::regular; +#endif +#ifdef DT_SOCK + case DT_SOCK: + return file_type::socket; +#endif +#ifdef DT_UNKNOWN + case DT_UNKNOWN: + return file_type::none; +#endif + default: + return file_type::unknown; + } +} + +template +GHC_INLINE file_type file_type_from_dirent(const T& t) +{ + return file_type_from_dirent_impl(t, has_d_type{}); +} +#endif +} // namespace detail + +namespace detail { + +#ifdef GHC_EXPAND_IMPL + +GHC_INLINE std::error_code make_error_code(portable_error err) +{ +#ifdef GHC_OS_WINDOWS + switch (err) { + case portable_error::none: + return std::error_code(); + case portable_error::exists: + return std::error_code(ERROR_ALREADY_EXISTS, std::system_category()); + case portable_error::not_found: + return std::error_code(ERROR_PATH_NOT_FOUND, std::system_category()); + case portable_error::not_supported: + return std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); + case portable_error::not_implemented: + return std::error_code(ERROR_CALL_NOT_IMPLEMENTED, std::system_category()); + case portable_error::invalid_argument: + return std::error_code(ERROR_INVALID_PARAMETER, std::system_category()); + case portable_error::is_a_directory: +#ifdef ERROR_DIRECTORY_NOT_SUPPORTED + return std::error_code(ERROR_DIRECTORY_NOT_SUPPORTED, std::system_category()); +#else + return std::error_code(ERROR_NOT_SUPPORTED, std::system_category()); +#endif + } +#else + switch (err) { + case portable_error::none: + return std::error_code(); + case portable_error::exists: + return std::error_code(EEXIST, std::system_category()); + case portable_error::not_found: + return std::error_code(ENOENT, std::system_category()); + case portable_error::not_supported: + return std::error_code(ENOTSUP, std::system_category()); + case portable_error::not_implemented: + return std::error_code(ENOSYS, std::system_category()); + case portable_error::invalid_argument: + return std::error_code(EINVAL, std::system_category()); + case portable_error::is_a_directory: + return std::error_code(EISDIR, std::system_category()); + } +#endif + return std::error_code(); +} + +#ifdef GHC_OS_WINDOWS +GHC_INLINE std::error_code make_system_error(uint32_t err) +{ + return std::error_code(err ? static_cast(err) : static_cast(::GetLastError()), std::system_category()); +} +#else +GHC_INLINE std::error_code make_system_error(int err) +{ + return std::error_code(err ? err : errno, std::system_category()); +} +#endif + +#endif // GHC_EXPAND_IMPL + +template +using EnableBitmask = typename std::enable_if::value || std::is_same::value || std::is_same::value || std::is_same::value, Enum>::type; +} // namespace detail + +template +constexpr detail::EnableBitmask operator&(Enum X, Enum Y) +{ + using underlying = typename std::underlying_type::type; + return static_cast(static_cast(X) & static_cast(Y)); +} + +template +constexpr detail::EnableBitmask operator|(Enum X, Enum Y) +{ + using underlying = typename std::underlying_type::type; + return static_cast(static_cast(X) | static_cast(Y)); +} + +template +constexpr detail::EnableBitmask operator^(Enum X, Enum Y) +{ + using underlying = typename std::underlying_type::type; + return static_cast(static_cast(X) ^ static_cast(Y)); +} + +template +constexpr detail::EnableBitmask operator~(Enum X) +{ + using underlying = typename std::underlying_type::type; + return static_cast(~static_cast(X)); +} + +template +detail::EnableBitmask& operator&=(Enum& X, Enum Y) +{ + X = X & Y; + return X; +} + +template +detail::EnableBitmask& operator|=(Enum& X, Enum Y) +{ + X = X | Y; + return X; +} + +template +detail::EnableBitmask& operator^=(Enum& X, Enum Y) +{ + X = X ^ Y; + return X; +} + +#ifdef GHC_EXPAND_IMPL + +namespace detail { + +GHC_INLINE bool in_range(uint32_t c, uint32_t lo, uint32_t hi) +{ + return (static_cast(c - lo) < (hi - lo + 1)); +} + +GHC_INLINE bool is_surrogate(uint32_t c) +{ + return in_range(c, 0xd800, 0xdfff); +} + +GHC_INLINE bool is_high_surrogate(uint32_t c) +{ + return (c & 0xfffffc00) == 0xd800; +} + +GHC_INLINE bool is_low_surrogate(uint32_t c) +{ + return (c & 0xfffffc00) == 0xdc00; +} + +GHC_INLINE void appendUTF8(std::string& str, uint32_t unicode) +{ + if (unicode <= 0x7f) { + str.push_back(static_cast(unicode)); + } + else if (unicode >= 0x80 && unicode <= 0x7ff) { + str.push_back(static_cast((unicode >> 6) + 192)); + str.push_back(static_cast((unicode & 0x3f) + 128)); + } + else if ((unicode >= 0x800 && unicode <= 0xd7ff) || (unicode >= 0xe000 && unicode <= 0xffff)) { + str.push_back(static_cast((unicode >> 12) + 224)); + str.push_back(static_cast(((unicode & 0xfff) >> 6) + 128)); + str.push_back(static_cast((unicode & 0x3f) + 128)); + } + else if (unicode >= 0x10000 && unicode <= 0x10ffff) { + str.push_back(static_cast((unicode >> 18) + 240)); + str.push_back(static_cast(((unicode & 0x3ffff) >> 12) + 128)); + str.push_back(static_cast(((unicode & 0xfff) >> 6) + 128)); + str.push_back(static_cast((unicode & 0x3f) + 128)); + } + else { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal code point for unicode character.", str, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + appendUTF8(str, 0xfffd); +#endif + } +} + +// Thanks to Bjoern Hoehrmann (https://bjoern.hoehrmann.de/utf-8/decoder/dfa/) +// and Taylor R Campbell for the ideas to this DFA approach of UTF-8 decoding; +// Generating debugging and shrinking my own DFA from scratch was a day of fun! +GHC_INLINE unsigned consumeUtf8Fragment(const unsigned state, const uint8_t fragment, uint32_t& codepoint) +{ + static const uint32_t utf8_state_info[] = { + // encoded states + 0x11111111u, 0x11111111u, 0x77777777u, 0x77777777u, 0x88888888u, 0x88888888u, 0x88888888u, 0x88888888u, 0x22222299u, 0x22222222u, 0x22222222u, 0x22222222u, 0x3333333au, 0x33433333u, 0x9995666bu, 0x99999999u, + 0x88888880u, 0x22818108u, 0x88888881u, 0x88888882u, 0x88888884u, 0x88888887u, 0x88888886u, 0x82218108u, 0x82281108u, 0x88888888u, 0x88888883u, 0x88888885u, 0u, 0u, 0u, 0u, + }; + uint8_t category = fragment < 128 ? 0 : (utf8_state_info[(fragment >> 3) & 0xf] >> ((fragment & 7) << 2)) & 0xf; + codepoint = (state ? (codepoint << 6) | (fragment & 0x3fu) : (0xffu >> category) & fragment); + return state == S_RJCT ? static_cast(S_RJCT) : static_cast((utf8_state_info[category + 16] >> (state << 2)) & 0xf); +} + +GHC_INLINE bool validUtf8(const std::string& utf8String) +{ + std::string::const_iterator iter = utf8String.begin(); + unsigned utf8_state = S_STRT; + std::uint32_t codepoint = 0; + while (iter < utf8String.end()) { + if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_RJCT) { + return false; + } + } + if (utf8_state) { + return false; + } + return true; +} + +} // namespace detail + +#endif + +namespace detail { + +template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 1)>::type* = nullptr> +inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + return StringType(utf8String.begin(), utf8String.end(), alloc); +} + +template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 2)>::type* = nullptr> +inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + StringType result(alloc); + result.reserve(utf8String.length()); + auto iter = utf8String.cbegin(); + unsigned utf8_state = S_STRT; + std::uint32_t codepoint = 0; + while (iter < utf8String.cend()) { + if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_STRT) { + if (codepoint <= 0xffff) { + result += static_cast(codepoint); + } + else { + codepoint -= 0x10000; + result += static_cast((codepoint >> 10) + 0xd800); + result += static_cast((codepoint & 0x3ff) + 0xdc00); + } + codepoint = 0; + } + else if (utf8_state == S_RJCT) { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + result += static_cast(0xfffd); + utf8_state = S_STRT; + codepoint = 0; +#endif + } + } + if (utf8_state) { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + result += static_cast(0xfffd); +#endif + } + return result; +} + +template ::value && (sizeof(typename Utf8String::value_type) == 1) && (sizeof(typename StringType::value_type) == 4)>::type* = nullptr> +inline StringType fromUtf8(const Utf8String& utf8String, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + StringType result(alloc); + result.reserve(utf8String.length()); + auto iter = utf8String.cbegin(); + unsigned utf8_state = S_STRT; + std::uint32_t codepoint = 0; + while (iter < utf8String.cend()) { + if ((utf8_state = consumeUtf8Fragment(utf8_state, static_cast(*iter++), codepoint)) == S_STRT) { + result += static_cast(codepoint); + codepoint = 0; + } + else if (utf8_state == S_RJCT) { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + result += static_cast(0xfffd); + utf8_state = S_STRT; + codepoint = 0; +#endif + } + } + if (utf8_state) { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal byte sequence for unicode character.", utf8String, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + result += static_cast(0xfffd); +#endif + } + return result; +} + +template +inline StringType fromUtf8(const charT (&utf8String)[N]) +{ +#ifdef GHC_WITH_STRING_VIEW + return fromUtf8(basic_string_view(utf8String, N - 1)); +#else + return fromUtf8(std::basic_string(utf8String, N - 1)); +#endif +} + +template ::value && (sizeof(typename strT::value_type) == 1), int>::type size = 1> +inline std::string toUtf8(const strT& unicodeString) +{ + return std::string(unicodeString.begin(), unicodeString.end()); +} + +template ::value && (sizeof(typename strT::value_type) == 2), int>::type size = 2> +inline std::string toUtf8(const strT& unicodeString) +{ + std::string result; + for (auto iter = unicodeString.begin(); iter != unicodeString.end(); ++iter) { + char32_t c = *iter; + if (is_surrogate(c)) { + ++iter; + if (iter != unicodeString.end() && is_high_surrogate(c) && is_low_surrogate(*iter)) { + appendUTF8(result, (char32_t(c) << 10) + *iter - 0x35fdc00); + } + else { +#ifdef GHC_RAISE_UNICODE_ERRORS + throw filesystem_error("Illegal code point for unicode character.", result, std::make_error_code(std::errc::illegal_byte_sequence)); +#else + appendUTF8(result, 0xfffd); + if (iter == unicodeString.end()) { + break; + } +#endif + } + } + else { + appendUTF8(result, c); + } + } + return result; +} + +template ::value && (sizeof(typename strT::value_type) == 4), int>::type size = 4> +inline std::string toUtf8(const strT& unicodeString) +{ + std::string result; + for (auto c : unicodeString) { + appendUTF8(result, static_cast(c)); + } + return result; +} + +template +inline std::string toUtf8(const charT* unicodeString) +{ +#ifdef GHC_WITH_STRING_VIEW + return toUtf8(basic_string_view>(unicodeString)); +#else + return toUtf8(std::basic_string>(unicodeString)); +#endif +} + +#ifdef GHC_USE_WCHAR_T +template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 1), bool>::type = false> +inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + auto temp = toUtf8(wString); + return StringType(temp.begin(), temp.end(), alloc); +} + +template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 2), bool>::type = false> +inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + return StringType(wString.begin(), wString.end(), alloc); +} + +template ::value && (sizeof(typename WString::value_type) == 2) && (sizeof(typename StringType::value_type) == 4), bool>::type = false> +inline StringType fromWChar(const WString& wString, const typename StringType::allocator_type& alloc = typename StringType::allocator_type()) +{ + auto temp = toUtf8(wString); + return fromUtf8(temp, alloc); +} + +template ::value && (sizeof(typename strT::value_type) == 1), bool>::type = false> +inline std::wstring toWChar(const strT& unicodeString) +{ + return fromUtf8(unicodeString); +} + +template ::value && (sizeof(typename strT::value_type) == 2), bool>::type = false> +inline std::wstring toWChar(const strT& unicodeString) +{ + return std::wstring(unicodeString.begin(), unicodeString.end()); +} + +template ::value && (sizeof(typename strT::value_type) == 4), bool>::type = false> +inline std::wstring toWChar(const strT& unicodeString) +{ + auto temp = toUtf8(unicodeString); + return fromUtf8(temp); +} + +template +inline std::wstring toWChar(const charT* unicodeString) +{ +#ifdef GHC_WITH_STRING_VIEW + return toWChar(basic_string_view>(unicodeString)); +#else + return toWChar(std::basic_string>(unicodeString)); +#endif +} +#endif // GHC_USE_WCHAR_T + +} // namespace detail + +#ifdef GHC_EXPAND_IMPL + +namespace detail { + +template ::value, bool>::type = true> +GHC_INLINE bool startsWith(const strT& what, const strT& with) +{ + return with.length() <= what.length() && equal(with.begin(), with.end(), what.begin()); +} + +template ::value, bool>::type = true> +GHC_INLINE bool endsWith(const strT& what, const strT& with) +{ + return with.length() <= what.length() && what.compare(what.length() - with.length(), with.size(), with) == 0; +} + +} // namespace detail + +GHC_INLINE void path::check_long_path() +{ +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) { + postprocess_path_with_format(native_format); + } +#endif +} + +GHC_INLINE void path::postprocess_path_with_format(path::format fmt) +{ +#ifdef GHC_RAISE_UNICODE_ERRORS + if (!detail::validUtf8(_path)) { + path t; + t._path = _path; + throw filesystem_error("Illegal byte sequence for unicode character.", t, std::make_error_code(std::errc::illegal_byte_sequence)); + } +#endif + switch (fmt) { +#ifdef GHC_OS_WINDOWS + case path::native_format: + case path::auto_format: + case path::generic_format: + for (auto& c : _path) { + if (c == generic_separator) { + c = preferred_separator; + } + } +#ifdef GHC_WIN_AUTO_PREFIX_LONG_PATH + if (is_absolute() && _path.length() >= MAX_PATH - 12 && !detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\")))) { + _path = GHC_PLATFORM_LITERAL("\\\\?\\") + _path; + } +#endif + handle_prefixes(); + break; +#else + case path::auto_format: + case path::native_format: + case path::generic_format: + // nothing to do + break; +#endif + } + if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator) { + impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast(_prefixLength) + 2, _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; }); + _path.erase(new_end, _path.end()); + } + else { + impl_string_type::iterator new_end = std::unique(_path.begin() + static_cast(_prefixLength), _path.end(), [](path::value_type lhs, path::value_type rhs) { return lhs == rhs && lhs == preferred_separator; }); + _path.erase(new_end, _path.end()); + } +} + +#endif // GHC_EXPAND_IMPL + +template +inline path::path(const Source& source, format fmt) +#ifdef GHC_USE_WCHAR_T + : _path(detail::toWChar(source)) +#else + : _path(detail::toUtf8(source)) +#endif +{ + postprocess_path_with_format(fmt); +} + +template +inline path u8path(const Source& source) +{ + return path(source); +} +template +inline path u8path(InputIterator first, InputIterator last) +{ + return path(first, last); +} + +template +inline path::path(InputIterator first, InputIterator last, format fmt) + : path(std::basic_string::value_type>(first, last), fmt) +{ + // delegated +} + +#ifdef GHC_EXPAND_IMPL + +namespace detail { + +GHC_INLINE bool equals_simple_insensitive(const path::value_type* str1, const path::value_type* str2) +{ +#ifdef GHC_OS_WINDOWS +#ifdef __GNUC__ + while (::tolower((unsigned char)*str1) == ::tolower((unsigned char)*str2++)) { + if (*str1++ == 0) + return true; + } + return false; +#else // __GNUC__ +#ifdef GHC_USE_WCHAR_T + return 0 == ::_wcsicmp(str1, str2); +#else // GHC_USE_WCHAR_T + return 0 == ::_stricmp(str1, str2); +#endif // GHC_USE_WCHAR_T +#endif // __GNUC__ +#else // GHC_OS_WINDOWS + return 0 == ::strcasecmp(str1, str2); +#endif // GHC_OS_WINDOWS +} + +GHC_INLINE int compare_simple_insensitive(const path::value_type* str1, size_t len1, const path::value_type* str2, size_t len2) +{ + while (len1 > 0 && len2 > 0 && ::tolower(static_cast(*str1)) == ::tolower(static_cast(*str2))) { + --len1; + --len2; + ++str1; + ++str2; + } + if (len1 && len2) { + return *str1 < *str2 ? -1 : 1; + } + if (len1 == 0 && len2 == 0) { + return 0; + } + return len1 == 0 ? -1 : 1; +} + +GHC_INLINE const char* strerror_adapter(char* gnu, char*) +{ + return gnu; +} + +GHC_INLINE const char* strerror_adapter(int posix, char* buffer) +{ + if (posix) { + return "Error in strerror_r!"; + } + return buffer; +} + +template +GHC_INLINE std::string systemErrorText(ErrorNumber code = 0) +{ +#if defined(GHC_OS_WINDOWS) + LPVOID msgBuf; + DWORD dw = code ? static_cast(code) : ::GetLastError(); + FormatMessageW(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, dw, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPWSTR)&msgBuf, 0, NULL); + std::string msg = toUtf8(std::wstring((LPWSTR)msgBuf)); + LocalFree(msgBuf); + return msg; +#else + char buffer[512]; + return strerror_adapter(strerror_r(code ? code : errno, buffer, sizeof(buffer)), buffer); +#endif +} + +#ifdef GHC_OS_WINDOWS +using CreateSymbolicLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, DWORD); +using CreateHardLinkW_fp = BOOLEAN(WINAPI*)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES); + +GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool to_directory, std::error_code& ec) +{ + std::error_code tec; + auto fs = status(target_name, tec); + if ((fs.type() == file_type::directory && !to_directory) || (fs.type() == file_type::regular && to_directory)) { + ec = detail::make_error_code(detail::portable_error::not_supported); + return; + } +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) +#pragma warning(push) +#pragma warning(disable : 4191) +#endif + static CreateSymbolicLinkW_fp api_call = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateSymbolicLinkW")); +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) +#pragma warning(pop) +#endif + if (api_call) { + if (api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 1 : 0) == 0) { + auto result = ::GetLastError(); + if (result == ERROR_PRIVILEGE_NOT_HELD && api_call(GHC_NATIVEWP(new_symlink), GHC_NATIVEWP(target_name), to_directory ? 3 : 2) != 0) { + return; + } + ec = detail::make_system_error(result); + } + } + else { + ec = detail::make_system_error(ERROR_NOT_SUPPORTED); + } +} + +GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec) +{ +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wcast-function-type" +#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) +#pragma warning(push) +#pragma warning(disable : 4191) +#endif + static CreateHardLinkW_fp api_call = reinterpret_cast(GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "CreateHardLinkW")); +#if defined(__GNUC__) && __GNUC__ >= 8 +#pragma GCC diagnostic pop +#elif defined(_MSC_VER) && !defined(__INTEL_COMPILER) && !defined(__clang__) +#pragma warning(pop) +#endif + if (api_call) { + if (api_call(GHC_NATIVEWP(new_hardlink), GHC_NATIVEWP(target_name), NULL) == 0) { + ec = detail::make_system_error(); + } + } + else { + ec = detail::make_system_error(ERROR_NOT_SUPPORTED); + } +} + +GHC_INLINE path getFullPathName(const wchar_t* p, std::error_code& ec) +{ + ULONG size = ::GetFullPathNameW(p, 0, 0, 0); + if (size) { + std::vector buf(size, 0); + ULONG s2 = GetFullPathNameW(p, size, buf.data(), nullptr); + if (s2 && s2 < size) { + return path(std::wstring(buf.data(), s2)); + } + } + ec = detail::make_system_error(); + return path(); +} + +#else +GHC_INLINE void create_symlink(const path& target_name, const path& new_symlink, bool, std::error_code& ec) +{ + if (::symlink(target_name.c_str(), new_symlink.c_str()) != 0) { + ec = detail::make_system_error(); + } +} + +#ifndef GHC_OS_WEB +GHC_INLINE void create_hardlink(const path& target_name, const path& new_hardlink, std::error_code& ec) +{ + if (::link(target_name.c_str(), new_hardlink.c_str()) != 0) { + ec = detail::make_system_error(); + } +} +#endif +#endif + +template +GHC_INLINE file_status file_status_from_st_mode(T mode) +{ +#ifdef GHC_OS_WINDOWS + file_type ft = file_type::unknown; + if ((mode & _S_IFDIR) == _S_IFDIR) { + ft = file_type::directory; + } + else if ((mode & _S_IFREG) == _S_IFREG) { + ft = file_type::regular; + } + else if ((mode & _S_IFCHR) == _S_IFCHR) { + ft = file_type::character; + } + perms prms = static_cast(mode & 0xfff); + return file_status(ft, prms); +#else + file_type ft = file_type::unknown; + if (S_ISDIR(mode)) { + ft = file_type::directory; + } + else if (S_ISREG(mode)) { + ft = file_type::regular; + } + else if (S_ISCHR(mode)) { + ft = file_type::character; + } + else if (S_ISBLK(mode)) { + ft = file_type::block; + } + else if (S_ISFIFO(mode)) { + ft = file_type::fifo; + } + else if (S_ISLNK(mode)) { + ft = file_type::symlink; + } + else if (S_ISSOCK(mode)) { + ft = file_type::socket; + } + perms prms = static_cast(mode & 0xfff); + return file_status(ft, prms); +#endif +} + +#ifdef GHC_OS_WINDOWS + +class unique_handle +{ +public: + typedef HANDLE element_type; + + unique_handle() noexcept + : _handle(INVALID_HANDLE_VALUE) + { + } + explicit unique_handle(element_type h) noexcept + : _handle(h) + { + } + unique_handle(unique_handle&& u) noexcept + : _handle(u.release()) + { + } + ~unique_handle() { reset(); } + unique_handle& operator=(unique_handle&& u) noexcept + { + reset(u.release()); + return *this; + } + element_type get() const noexcept { return _handle; } + explicit operator bool() const noexcept { return _handle != INVALID_HANDLE_VALUE; } + element_type release() noexcept + { + element_type tmp = _handle; + _handle = INVALID_HANDLE_VALUE; + return tmp; + } + void reset(element_type h = INVALID_HANDLE_VALUE) noexcept + { + element_type tmp = _handle; + _handle = h; + if (tmp != INVALID_HANDLE_VALUE) { + CloseHandle(tmp); + } + } + void swap(unique_handle& u) noexcept { std::swap(_handle, u._handle); } + +private: + element_type _handle; +}; + +#ifndef REPARSE_DATA_BUFFER_HEADER_SIZE +typedef struct _REPARSE_DATA_BUFFER +{ + ULONG ReparseTag; + USHORT ReparseDataLength; + USHORT Reserved; + union + { + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + ULONG Flags; + WCHAR PathBuffer[1]; + } SymbolicLinkReparseBuffer; + struct + { + USHORT SubstituteNameOffset; + USHORT SubstituteNameLength; + USHORT PrintNameOffset; + USHORT PrintNameLength; + WCHAR PathBuffer[1]; + } MountPointReparseBuffer; + struct + { + UCHAR DataBuffer[1]; + } GenericReparseBuffer; + } DUMMYUNIONNAME; +} REPARSE_DATA_BUFFER; +#ifndef MAXIMUM_REPARSE_DATA_BUFFER_SIZE +#define MAXIMUM_REPARSE_DATA_BUFFER_SIZE (16 * 1024) +#endif +#endif + +template +struct free_deleter +{ + void operator()(T* p) const { std::free(p); } +}; + +GHC_INLINE std::unique_ptr> getReparseData(const path& p, std::error_code& ec) +{ + unique_handle file(CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_OPEN_REPARSE_POINT | FILE_FLAG_BACKUP_SEMANTICS, 0)); + if (!file) { + ec = detail::make_system_error(); + return nullptr; + } + + std::unique_ptr> reparseData(reinterpret_cast(std::calloc(1, MAXIMUM_REPARSE_DATA_BUFFER_SIZE))); + ULONG bufferUsed; + if (DeviceIoControl(file.get(), FSCTL_GET_REPARSE_POINT, 0, 0, reparseData.get(), MAXIMUM_REPARSE_DATA_BUFFER_SIZE, &bufferUsed, 0)) { + return reparseData; + } + else { + ec = detail::make_system_error(); + } + return nullptr; +} +#endif + +GHC_INLINE path resolveSymlink(const path& p, std::error_code& ec) +{ +#ifdef GHC_OS_WINDOWS + path result; + auto reparseData = detail::getReparseData(p, ec); + if (!ec) { + if (reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag)) { + switch (reparseData->ReparseTag) { + case IO_REPARSE_TAG_SYMLINK: { + auto printName = std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.PrintNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.PrintNameLength / sizeof(WCHAR)); + auto substituteName = + std::wstring(&reparseData->SymbolicLinkReparseBuffer.PathBuffer[reparseData->SymbolicLinkReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->SymbolicLinkReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); + if (detail::endsWith(substituteName, printName) && detail::startsWith(substituteName, std::wstring(L"\\??\\"))) { + result = printName; + } + else { + result = substituteName; + } + if (reparseData->SymbolicLinkReparseBuffer.Flags & 0x1 /*SYMLINK_FLAG_RELATIVE*/) { + result = p.parent_path() / result; + } + break; + } + case IO_REPARSE_TAG_MOUNT_POINT: + result = detail::getFullPathName(GHC_NATIVEWP(p), ec); + // result = std::wstring(&reparseData->MountPointReparseBuffer.PathBuffer[reparseData->MountPointReparseBuffer.SubstituteNameOffset / sizeof(WCHAR)], reparseData->MountPointReparseBuffer.SubstituteNameLength / sizeof(WCHAR)); + break; + default: + break; + } + } + } + return result; +#else + size_t bufferSize = 256; + while (true) { + std::vector buffer(bufferSize, static_cast(0)); + auto rc = ::readlink(p.c_str(), buffer.data(), buffer.size()); + if (rc < 0) { + ec = detail::make_system_error(); + return path(); + } + else if (rc < static_cast(bufferSize)) { + return path(std::string(buffer.data(), static_cast(rc))); + } + bufferSize *= 2; + } + return path(); +#endif +} + +#ifdef GHC_OS_WINDOWS +GHC_INLINE time_t timeFromFILETIME(const FILETIME& ft) +{ + ULARGE_INTEGER ull; + ull.LowPart = ft.dwLowDateTime; + ull.HighPart = ft.dwHighDateTime; + return static_cast(ull.QuadPart / 10000000ULL - 11644473600ULL); +} + +GHC_INLINE void timeToFILETIME(time_t t, FILETIME& ft) +{ + ULARGE_INTEGER ull; + ull.QuadPart = static_cast((t * 10000000LL) + 116444736000000000LL); + ft.dwLowDateTime = ull.LowPart; + ft.dwHighDateTime = ull.HighPart; +} + +template +GHC_INLINE uintmax_t hard_links_from_INFO(const INFO* info) +{ + return static_cast(-1); +} + +template <> +GHC_INLINE uintmax_t hard_links_from_INFO(const BY_HANDLE_FILE_INFORMATION* info) +{ + return info->nNumberOfLinks; +} + +template +GHC_INLINE bool is_symlink_from_INFO(const path &p, const INFO* info, std::error_code& ec) +{ + if ((info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)) { + auto reparseData = detail::getReparseData(p, ec); + if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + return true; + } + } + return false; +} + +template <> +GHC_INLINE bool is_symlink_from_INFO(const path &, const WIN32_FIND_DATAW* info, std::error_code&) +{ + // dwReserved0 is undefined unless dwFileAttributes includes the + // FILE_ATTRIBUTE_REPARSE_POINT attribute according to microsoft + // documentation. In practice, dwReserved0 is not reset which + // causes it to report the incorrect symlink status. + // Note that microsoft documentation does not say whether there is + // a null value for dwReserved0, so we test for symlink directly + // instead of returning the tag which requires returning a null + // value for non-reparse-point files. + return (info->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) && info->dwReserved0 == IO_REPARSE_TAG_SYMLINK; +} + +template +GHC_INLINE file_status status_from_INFO(const path& p, const INFO* info, std::error_code& ec, uintmax_t* sz = nullptr, time_t* lwt = nullptr) +{ + file_type ft = file_type::unknown; + if (is_symlink_from_INFO(p, info, ec)) { + ft = file_type::symlink; + } + else if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)) { + ft = file_type::directory; + } + else { + ft = file_type::regular; + } + perms prms = perms::owner_read | perms::group_read | perms::others_read; + if (!(info->dwFileAttributes & FILE_ATTRIBUTE_READONLY)) { + prms = prms | perms::owner_write | perms::group_write | perms::others_write; + } + if (has_executable_extension(p)) { + prms = prms | perms::owner_exec | perms::group_exec | perms::others_exec; + } + if (sz) { + *sz = static_cast(info->nFileSizeHigh) << (sizeof(info->nFileSizeHigh) * 8) | info->nFileSizeLow; + } + if (lwt) { + *lwt = detail::timeFromFILETIME(info->ftLastWriteTime); + } + return file_status(ft, prms); +} + +#endif + +GHC_INLINE bool is_not_found_error(std::error_code& ec) +{ +#ifdef GHC_OS_WINDOWS + return ec.value() == ERROR_FILE_NOT_FOUND || ec.value() == ERROR_PATH_NOT_FOUND || ec.value() == ERROR_INVALID_NAME; +#else + return ec.value() == ENOENT || ec.value() == ENOTDIR; +#endif +} + +GHC_INLINE file_status symlink_status_ex(const path& p, std::error_code& ec, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr) noexcept +{ +#ifdef GHC_OS_WINDOWS + file_status fs; + WIN32_FILE_ATTRIBUTE_DATA attr; + if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { + ec = detail::make_system_error(); + } + else { + ec.clear(); + fs = detail::status_from_INFO(p, &attr, ec, sz, lwt); + if (nhl) { + *nhl = 0; + } + } + if (detail::is_not_found_error(ec)) { + return file_status(file_type::not_found); + } + return ec ? file_status(file_type::none) : fs; +#else + (void)sz; + (void)nhl; + (void)lwt; + struct ::stat fs; + auto result = ::lstat(p.c_str(), &fs); + if (result == 0) { + ec.clear(); + file_status f_s = detail::file_status_from_st_mode(fs.st_mode); + return f_s; + } + ec = detail::make_system_error(); + if (detail::is_not_found_error(ec)) { + return file_status(file_type::not_found, perms::unknown); + } + return file_status(file_type::none); +#endif +} + +GHC_INLINE file_status status_ex(const path& p, std::error_code& ec, file_status* sls = nullptr, uintmax_t* sz = nullptr, uintmax_t* nhl = nullptr, time_t* lwt = nullptr, int recurse_count = 0) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + if (recurse_count > 16) { + ec = detail::make_system_error(0x2A9 /*ERROR_STOPPED_ON_SYMLINK*/); + return file_status(file_type::unknown); + } + WIN32_FILE_ATTRIBUTE_DATA attr; + if (!::GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { + ec = detail::make_system_error(); + } + else if (attr.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + auto reparseData = detail::getReparseData(p, ec); + if (!ec && reparseData && IsReparseTagMicrosoft(reparseData->ReparseTag) && reparseData->ReparseTag == IO_REPARSE_TAG_SYMLINK) { + path target = resolveSymlink(p, ec); + file_status result; + if (!ec && !target.empty()) { + if (sls) { + *sls = status_from_INFO(p, &attr, ec); + } + return detail::status_ex(target, ec, nullptr, sz, nhl, lwt, recurse_count + 1); + } + return file_status(file_type::unknown); + } + } + if (ec) { + if (detail::is_not_found_error(ec)) { + return file_status(file_type::not_found); + } + return file_status(file_type::none); + } + if (nhl) { + *nhl = 0; + } + return detail::status_from_INFO(p, &attr, ec, sz, lwt); +#else + (void)recurse_count; + struct ::stat st; + auto result = ::lstat(p.c_str(), &st); + if (result == 0) { + ec.clear(); + file_status fs = detail::file_status_from_st_mode(st.st_mode); + if (sls) { + *sls = fs; + } + if (fs.type() == file_type::symlink) { + result = ::stat(p.c_str(), &st); + if (result == 0) { + fs = detail::file_status_from_st_mode(st.st_mode); + } + else { + ec = detail::make_system_error(); + if (detail::is_not_found_error(ec)) { + return file_status(file_type::not_found, perms::unknown); + } + return file_status(file_type::none); + } + } + if (sz) { + *sz = static_cast(st.st_size); + } + if (nhl) { + *nhl = st.st_nlink; + } + if (lwt) { + *lwt = st.st_mtime; + } + return fs; + } + else { + ec = detail::make_system_error(); + if (detail::is_not_found_error(ec)) { + return file_status(file_type::not_found, perms::unknown); + } + return file_status(file_type::none); + } +#endif +} + +} // namespace detail + +GHC_INLINE u8arguments::u8arguments(int& argc, char**& argv) + : _argc(argc) + , _argv(argv) + , _refargc(argc) + , _refargv(argv) + , _isvalid(false) +{ +#ifdef GHC_OS_WINDOWS + LPWSTR* p; + p = ::CommandLineToArgvW(::GetCommandLineW(), &argc); + _args.reserve(static_cast(argc)); + _argp.reserve(static_cast(argc)); + for (size_t i = 0; i < static_cast(argc); ++i) { + _args.push_back(detail::toUtf8(std::wstring(p[i]))); + _argp.push_back((char*)_args[i].data()); + } + argv = _argp.data(); + ::LocalFree(p); + _isvalid = true; +#else + std::setlocale(LC_ALL, ""); +#if defined(__ANDROID__) && __ANDROID_API__ < 26 + _isvalid = true; +#else + if (detail::equals_simple_insensitive(::nl_langinfo(CODESET), "UTF-8")) { + _isvalid = true; + } +#endif +#endif +} + +//----------------------------------------------------------------------------- +// [fs.path.construct] constructors and destructor + +GHC_INLINE path::path() noexcept {} + +GHC_INLINE path::path(const path& p) + : _path(p._path) +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + , _prefixLength(p._prefixLength) +#endif +{ +} + +GHC_INLINE path::path(path&& p) noexcept + : _path(std::move(p._path)) +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + , _prefixLength(p._prefixLength) +#endif +{ +} + +GHC_INLINE path::path(string_type&& source, format fmt) + : _path(std::move(source)) +{ + postprocess_path_with_format(fmt); +} + +#endif // GHC_EXPAND_IMPL + +#ifdef GHC_WITH_EXCEPTIONS +template +inline path::path(const Source& source, const std::locale& loc, format fmt) + : path(source, fmt) +{ + std::string locName = loc.name(); + if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) { + throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported)); + } +} + +template +inline path::path(InputIterator first, InputIterator last, const std::locale& loc, format fmt) + : path(std::basic_string::value_type>(first, last), fmt) +{ + std::string locName = loc.name(); + if (!(locName.length() >= 5 && (locName.substr(locName.length() - 5) == "UTF-8" || locName.substr(locName.length() - 5) == "utf-8"))) { + throw filesystem_error("This implementation only supports UTF-8 locales!", path(_path), detail::make_error_code(detail::portable_error::not_supported)); + } +} +#endif + +#ifdef GHC_EXPAND_IMPL + +GHC_INLINE path::~path() {} + +//----------------------------------------------------------------------------- +// [fs.path.assign] assignments + +GHC_INLINE path& path::operator=(const path& p) +{ + _path = p._path; +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + _prefixLength = p._prefixLength; +#endif + return *this; +} + +GHC_INLINE path& path::operator=(path&& p) noexcept +{ + _path = std::move(p._path); +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + _prefixLength = p._prefixLength; +#endif + return *this; +} + +GHC_INLINE path& path::operator=(path::string_type&& source) +{ + return assign(source); +} + +GHC_INLINE path& path::assign(path::string_type&& source) +{ + _path = std::move(source); + postprocess_path_with_format(native_format); + return *this; +} + +#endif // GHC_EXPAND_IMPL + +template +inline path& path::operator=(const Source& source) +{ + return assign(source); +} + +template +inline path& path::assign(const Source& source) +{ +#ifdef GHC_USE_WCHAR_T + _path.assign(detail::toWChar(source)); +#else + _path.assign(detail::toUtf8(source)); +#endif + postprocess_path_with_format(native_format); + return *this; +} + +template <> +inline path& path::assign(const path& source) +{ + _path = source._path; +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + _prefixLength = source._prefixLength; +#endif + return *this; +} + +template +inline path& path::assign(InputIterator first, InputIterator last) +{ + _path.assign(first, last); + postprocess_path_with_format(native_format); + return *this; +} + +#ifdef GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.path.append] appends + +GHC_INLINE path& path::operator/=(const path& p) +{ + if (p.empty()) { + // was: if ((!has_root_directory() && is_absolute()) || has_filename()) + if (!_path.empty() && _path[_path.length() - 1] != preferred_separator && _path[_path.length() - 1] != ':') { + _path += preferred_separator; + } + return *this; + } + if ((p.is_absolute() && (_path != root_name()._path || p._path != "/")) || (p.has_root_name() && p.root_name() != root_name())) { + assign(p); + return *this; + } + if (p.has_root_directory()) { + assign(root_name()); + } + else if ((!has_root_directory() && is_absolute()) || has_filename()) { + _path += preferred_separator; + } + auto iter = p.begin(); + bool first = true; + if (p.has_root_name()) { + ++iter; + } + while (iter != p.end()) { + if (!first && !(!_path.empty() && _path[_path.length() - 1] == preferred_separator)) { + _path += preferred_separator; + } + first = false; + _path += (*iter++).native(); + } + check_long_path(); + return *this; +} + +GHC_INLINE void path::append_name(const value_type* name) +{ + if (_path.empty()) { + this->operator/=(path(name)); + } + else { + if (_path.back() != path::preferred_separator) { + _path.push_back(path::preferred_separator); + } + _path += name; + check_long_path(); + } +} + +#endif // GHC_EXPAND_IMPL + +template +inline path& path::operator/=(const Source& source) +{ + return append(source); +} + +template +inline path& path::append(const Source& source) +{ + return this->operator/=(path(source)); +} + +template <> +inline path& path::append(const path& p) +{ + return this->operator/=(p); +} + +template +inline path& path::append(InputIterator first, InputIterator last) +{ + std::basic_string::value_type> part(first, last); + return append(part); +} + +#ifdef GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.path.concat] concatenation + +GHC_INLINE path& path::operator+=(const path& x) +{ + return concat(x._path); +} + +GHC_INLINE path& path::operator+=(const string_type& x) +{ + return concat(x); +} + +#ifdef GHC_WITH_STRING_VIEW +GHC_INLINE path& path::operator+=(basic_string_view x) +{ + return concat(x); +} +#endif + +GHC_INLINE path& path::operator+=(const value_type* x) +{ +#ifdef GHC_WITH_STRING_VIEW + basic_string_view part(x); +#else + string_type part(x); +#endif + return concat(part); +} + +GHC_INLINE path& path::operator+=(value_type x) +{ +#ifdef GHC_OS_WINDOWS + if (x == generic_separator) { + x = preferred_separator; + } +#endif + if (_path.empty() || _path.back() != preferred_separator) { + _path += x; + } + check_long_path(); + return *this; +} + +#endif // GHC_EXPAND_IMPL + +template +inline path::path_from_string& path::operator+=(const Source& x) +{ + return concat(x); +} + +template +inline path::path_type_EcharT& path::operator+=(EcharT x) +{ +#ifdef GHC_WITH_STRING_VIEW + basic_string_view part(&x, 1); +#else + std::basic_string part(1, x); +#endif + concat(part); + return *this; +} + +template +inline path& path::concat(const Source& x) +{ + path p(x); + _path += p._path; + postprocess_path_with_format(native_format); + return *this; +} +template +inline path& path::concat(InputIterator first, InputIterator last) +{ + _path.append(first, last); + postprocess_path_with_format(native_format); + return *this; +} + +#ifdef GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.path.modifiers] modifiers +GHC_INLINE void path::clear() noexcept +{ + _path.clear(); +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + _prefixLength = 0; +#endif +} + +GHC_INLINE path& path::make_preferred() +{ + // as this filesystem implementation only uses generic_format + // internally, this must be a no-op + return *this; +} + +GHC_INLINE path& path::remove_filename() +{ + if (has_filename()) { + _path.erase(_path.size() - filename()._path.size()); + } + return *this; +} + +GHC_INLINE path& path::replace_filename(const path& replacement) +{ + remove_filename(); + return append(replacement); +} + +GHC_INLINE path& path::replace_extension(const path& replacement) +{ + if (has_extension()) { + _path.erase(_path.size() - extension()._path.size()); + } + if (!replacement.empty() && replacement._path[0] != '.') { + _path += '.'; + } + return concat(replacement); +} + +GHC_INLINE void path::swap(path& rhs) noexcept +{ + _path.swap(rhs._path); +#if defined(GHC_OS_WINDOWS) && defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + std::swap(_prefixLength, rhs._prefixLength); +#endif +} + +//----------------------------------------------------------------------------- +// [fs.path.native.obs] native format observers +GHC_INLINE const path::string_type& path::native() const noexcept +{ + return _path; +} + +GHC_INLINE const path::value_type* path::c_str() const noexcept +{ + return native().c_str(); +} + +GHC_INLINE path::operator path::string_type() const +{ + return native(); +} + +#endif // GHC_EXPAND_IMPL + +template +inline std::basic_string path::string(const Allocator& a) const +{ +#ifdef GHC_USE_WCHAR_T + return detail::fromWChar>(_path, a); +#else + return detail::fromUtf8>(_path, a); +#endif +} + +#ifdef GHC_EXPAND_IMPL + +GHC_INLINE std::string path::string() const +{ +#ifdef GHC_USE_WCHAR_T + return detail::toUtf8(native()); +#else + return native(); +#endif +} + +GHC_INLINE std::wstring path::wstring() const +{ +#ifdef GHC_USE_WCHAR_T + return native(); +#else + return detail::fromUtf8(native()); +#endif +} + +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) +GHC_INLINE std::u8string path::u8string() const +{ +#ifdef GHC_USE_WCHAR_T + return std::u8string(reinterpret_cast(detail::toUtf8(native()).c_str())); +#else + return std::u8string(reinterpret_cast(c_str())); +#endif +} +#else +GHC_INLINE std::string path::u8string() const +{ +#ifdef GHC_USE_WCHAR_T + return detail::toUtf8(native()); +#else + return native(); +#endif +} +#endif + +GHC_INLINE std::u16string path::u16string() const +{ + // TODO: optimize + return detail::fromUtf8(string()); +} + +GHC_INLINE std::u32string path::u32string() const +{ + // TODO: optimize + return detail::fromUtf8(string()); +} + +#endif // GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.path.generic.obs] generic format observers +template +inline std::basic_string path::generic_string(const Allocator& a) const +{ +#ifdef GHC_OS_WINDOWS +#ifdef GHC_USE_WCHAR_T + auto result = detail::fromWChar, path::string_type>(_path, a); +#else + auto result = detail::fromUtf8>(_path, a); +#endif + for (auto& c : result) { + if (c == preferred_separator) { + c = generic_separator; + } + } + return result; +#else + return detail::fromUtf8>(_path, a); +#endif +} + +#ifdef GHC_EXPAND_IMPL + +GHC_INLINE std::string path::generic_string() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return _path; +#endif +} + +GHC_INLINE std::wstring path::generic_wstring() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return detail::fromUtf8(_path); +#endif +} // namespace filesystem + +#if defined(__cpp_lib_char8_t) && !defined(GHC_FILESYSTEM_ENFORCE_CPP17_API) +GHC_INLINE std::u8string path::generic_u8string() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return std::u8string(reinterpret_cast(_path.c_str())); +#endif +} +#else +GHC_INLINE std::string path::generic_u8string() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return _path; +#endif +} +#endif + +GHC_INLINE std::u16string path::generic_u16string() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return detail::fromUtf8(_path); +#endif +} + +GHC_INLINE std::u32string path::generic_u32string() const +{ +#ifdef GHC_OS_WINDOWS + return generic_string(); +#else + return detail::fromUtf8(_path); +#endif +} + +//----------------------------------------------------------------------------- +// [fs.path.compare] compare +GHC_INLINE int path::compare(const path& p) const noexcept +{ +#ifdef LWG_2936_BEHAVIOUR + auto rnl1 = root_name_length(); + auto rnl2 = p.root_name_length(); +#ifdef GHC_OS_WINDOWS + auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); +#else + auto rnc = _path.compare(0, rnl1, p._path, 0, (std::min(rnl1, rnl2))); +#endif + if (rnc) { + return rnc; + } + bool hrd1 = has_root_directory(), hrd2 = p.has_root_directory(); + if (hrd1 != hrd2) { + return hrd1 ? 1 : -1; + } + if (hrd1) { + ++rnl1; + ++rnl2; + } + auto iter1 = _path.begin() + static_cast(rnl1); + auto iter2 = p._path.begin() + static_cast(rnl2); + while (iter1 != _path.end() && iter2 != p._path.end() && *iter1 == *iter2) { + ++iter1; + ++iter2; + } + if (iter1 == _path.end()) { + return iter2 == p._path.end() ? 0 : -1; + } + if (iter2 == p._path.end()) { + return 1; + } + if (*iter1 == preferred_separator) { + return -1; + } + if (*iter2 == preferred_separator) { + return 1; + } + return *iter1 < *iter2 ? -1 : 1; +#else // LWG_2936_BEHAVIOUR +#ifdef GHC_OS_WINDOWS + auto rnl1 = root_name_length(); + auto rnl2 = p.root_name_length(); + auto rnc = detail::compare_simple_insensitive(_path.c_str(), rnl1, p._path.c_str(), rnl2); + if (rnc) { + return rnc; + } + return _path.compare(rnl1, std::string::npos, p._path, rnl2, std::string::npos); +#else + return _path.compare(p._path); +#endif +#endif +} + +GHC_INLINE int path::compare(const string_type& s) const +{ + return compare(path(s)); +} + +#ifdef GHC_WITH_STRING_VIEW +GHC_INLINE int path::compare(basic_string_view s) const +{ + return compare(path(s)); +} +#endif + +GHC_INLINE int path::compare(const value_type* s) const +{ + return compare(path(s)); +} + +//----------------------------------------------------------------------------- +// [fs.path.decompose] decomposition +#ifdef GHC_OS_WINDOWS +GHC_INLINE void path::handle_prefixes() +{ +#if defined(GHC_WIN_AUTO_PREFIX_LONG_PATH) + _prefixLength = 0; + if (_path.length() >= 6 && _path[2] == '?' && std::toupper(static_cast(_path[4])) >= 'A' && std::toupper(static_cast(_path[4])) <= 'Z' && _path[5] == ':') { + if (detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\\\?\\"))) || detail::startsWith(_path, impl_string_type(GHC_PLATFORM_LITERAL("\\??\\")))) { + _prefixLength = 4; + } + } +#endif // GHC_WIN_AUTO_PREFIX_LONG_PATH +} +#endif + +GHC_INLINE path::string_type::size_type path::root_name_length() const noexcept +{ +#ifdef GHC_OS_WINDOWS + if (_path.length() >= _prefixLength + 2 && std::toupper(static_cast(_path[_prefixLength])) >= 'A' && std::toupper(static_cast(_path[_prefixLength])) <= 'Z' && _path[_prefixLength + 1] == ':') { + return 2; + } +#endif + if (_path.length() > _prefixLength + 2 && _path[_prefixLength] == preferred_separator && _path[_prefixLength + 1] == preferred_separator && _path[_prefixLength + 2] != preferred_separator && std::isprint(_path[_prefixLength + 2])) { + impl_string_type::size_type pos = _path.find(preferred_separator, _prefixLength + 3); + if (pos == impl_string_type::npos) { + return _path.length(); + } + else { + return pos; + } + } + return 0; +} + +GHC_INLINE path path::root_name() const +{ + return path(_path.substr(_prefixLength, root_name_length()), native_format); +} + +GHC_INLINE path path::root_directory() const +{ + if (has_root_directory()) { + static const path _root_dir(std::string(1, preferred_separator), native_format); + return _root_dir; + } + return path(); +} + +GHC_INLINE path path::root_path() const +{ + return path(root_name().string() + root_directory().string(), native_format); +} + +GHC_INLINE path path::relative_path() const +{ + auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); + return path(_path.substr((std::min)(rootPathLen, _path.length())), generic_format); +} + +GHC_INLINE path path::parent_path() const +{ + auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); + if (rootPathLen < _path.length()) { + if (empty()) { + return path(); + } + else { + auto piter = end(); + auto iter = piter.decrement(_path.end()); + if (iter > _path.begin() + static_cast(rootPathLen) && *iter != preferred_separator) { + --iter; + } + return path(_path.begin(), iter, native_format); + } + } + else { + return *this; + } +} + +GHC_INLINE path path::filename() const +{ + return !has_relative_path() ? path() : path(*--end()); +} + +GHC_INLINE path path::stem() const +{ + impl_string_type fn = filename().native(); + if (fn != "." && fn != "..") { + impl_string_type::size_type pos = fn.rfind('.'); + if (pos != impl_string_type::npos && pos > 0) { + return path{fn.substr(0, pos), native_format}; + } + } + return path{fn, native_format}; +} + +GHC_INLINE path path::extension() const +{ + if (has_relative_path()) { + auto iter = end(); + const auto& fn = *--iter; + impl_string_type::size_type pos = fn._path.rfind('.'); + if (pos != std::string::npos && pos > 0 && fn._path != "..") { + return path(fn._path.substr(pos), native_format); + } + } + return path(); +} + +#ifdef GHC_OS_WINDOWS +namespace detail { +GHC_INLINE bool has_executable_extension(const path& p) +{ + if (p.has_relative_path()) { + auto iter = p.end(); + const auto& fn = *--iter; + auto pos = fn._path.find_last_of('.'); + if (pos == std::string::npos || pos == 0 || fn._path.length() - pos != 3) { + return false; + } + const path::value_type* ext = fn._path.c_str() + pos + 1; + if (detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("exe")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("cmd")) || detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("bat")) || + detail::equals_simple_insensitive(ext, GHC_PLATFORM_LITERAL("com"))) { + return true; + } + } + return false; +} +} // namespace detail +#endif + +//----------------------------------------------------------------------------- +// [fs.path.query] query +GHC_INLINE bool path::empty() const noexcept +{ + return _path.empty(); +} + +GHC_INLINE bool path::has_root_name() const +{ + return root_name_length() > 0; +} + +GHC_INLINE bool path::has_root_directory() const +{ + auto rootLen = _prefixLength + root_name_length(); + return (_path.length() > rootLen && _path[rootLen] == preferred_separator); +} + +GHC_INLINE bool path::has_root_path() const +{ + return has_root_name() || has_root_directory(); +} + +GHC_INLINE bool path::has_relative_path() const +{ + auto rootPathLen = _prefixLength + root_name_length() + (has_root_directory() ? 1 : 0); + return rootPathLen < _path.length(); +} + +GHC_INLINE bool path::has_parent_path() const +{ + return !parent_path().empty(); +} + +GHC_INLINE bool path::has_filename() const +{ + return has_relative_path() && !filename().empty(); +} + +GHC_INLINE bool path::has_stem() const +{ + return !stem().empty(); +} + +GHC_INLINE bool path::has_extension() const +{ + return !extension().empty(); +} + +GHC_INLINE bool path::is_absolute() const +{ +#ifdef GHC_OS_WINDOWS + return has_root_name() && has_root_directory(); +#else + return has_root_directory(); +#endif +} + +GHC_INLINE bool path::is_relative() const +{ + return !is_absolute(); +} + +//----------------------------------------------------------------------------- +// [fs.path.gen] generation +GHC_INLINE path path::lexically_normal() const +{ + path dest; + bool lastDotDot = false; + for (string_type s : *this) { + if (s == ".") { + dest /= ""; + continue; + } + else if (s == ".." && !dest.empty()) { + auto root = root_path(); + if (dest == root) { + continue; + } + else if (*(--dest.end()) != "..") { + if (dest._path.back() == preferred_separator) { + dest._path.pop_back(); + } + dest.remove_filename(); + continue; + } + } + if (!(s.empty() && lastDotDot)) { + dest /= s; + } + lastDotDot = s == ".."; + } + if (dest.empty()) { + dest = "."; + } + return dest; +} + +GHC_INLINE path path::lexically_relative(const path& base) const +{ + if (root_name() != base.root_name() || is_absolute() != base.is_absolute() || (!has_root_directory() && base.has_root_directory())) { + return path(); + } + const_iterator a = begin(), b = base.begin(); + while (a != end() && b != base.end() && *a == *b) { + ++a; + ++b; + } + if (a == end() && b == base.end()) { + return path("."); + } + int count = 0; + for (const auto& element : input_iterator_range(b, base.end())) { + if (element != "." && element != "" && element != "..") { + ++count; + } + else if (element == "..") { + --count; + } + } + if (count == 0 && (a == end() || a->empty())) { + return path("."); + } + if (count < 0) { + return path(); + } + path result; + for (int i = 0; i < count; ++i) { + result /= ".."; + } + for (const auto& element : input_iterator_range(a, end())) { + result /= element; + } + return result; +} + +GHC_INLINE path path::lexically_proximate(const path& base) const +{ + path result = lexically_relative(base); + return result.empty() ? *this : result; +} + +//----------------------------------------------------------------------------- +// [fs.path.itr] iterators +GHC_INLINE path::iterator::iterator() {} + +GHC_INLINE path::iterator::iterator(const path& p, const impl_string_type::const_iterator& pos) + : _first(p._path.begin()) + , _last(p._path.end()) + , _prefix(_first + static_cast(p._prefixLength)) + , _root(p.has_root_directory() ? _first + static_cast(p._prefixLength + p.root_name_length()) : _last) + , _iter(pos) +{ + if (pos != _last) { + updateCurrent(); + } +} + +GHC_INLINE path::impl_string_type::const_iterator path::iterator::increment(const path::impl_string_type::const_iterator& pos) const +{ + path::impl_string_type::const_iterator i = pos; + bool fromStart = i == _first || i == _prefix; + if (i != _last) { + if (fromStart && i == _first && _prefix > _first) { + i = _prefix; + } + else if (*i++ == preferred_separator) { + // we can only sit on a slash if it is a network name or a root + if (i != _last && *i == preferred_separator) { + if (fromStart && !(i + 1 != _last && *(i + 1) == preferred_separator)) { + // leadind double slashes detected, treat this and the + // following until a slash as one unit + i = std::find(++i, _last, preferred_separator); + } + else { + // skip redundant slashes + while (i != _last && *i == preferred_separator) { + ++i; + } + } + } + } + else { +#ifdef GHC_OS_WINDOWS + if (fromStart && i != _last && *i == ':') { + ++i; + } + else { +#else + { +#endif + i = std::find(i, _last, preferred_separator); + } + } + } + return i; +} + +GHC_INLINE path::impl_string_type::const_iterator path::iterator::decrement(const path::impl_string_type::const_iterator& pos) const +{ + path::impl_string_type::const_iterator i = pos; + if (i != _first) { + --i; + // if this is now the root slash or the trailing slash, we are done, + // else check for network name + if (i != _root && (pos != _last || *i != preferred_separator)) { +#ifdef GHC_OS_WINDOWS + static const impl_string_type seps = GHC_PLATFORM_LITERAL("\\:"); + i = std::find_first_of(std::reverse_iterator(i), std::reverse_iterator(_first), seps.begin(), seps.end()).base(); + if (i > _first && *i == ':') { + i++; + } +#else + i = std::find(std::reverse_iterator(i), std::reverse_iterator(_first), preferred_separator).base(); +#endif + // Now we have to check if this is a network name + if (i - _first == 2 && *_first == preferred_separator && *(_first + 1) == preferred_separator) { + i -= 2; + } + } + } + return i; +} + +GHC_INLINE void path::iterator::updateCurrent() +{ + if ((_iter == _last) || (_iter != _first && _iter != _last && (*_iter == preferred_separator && _iter != _root) && (_iter + 1 == _last))) { + _current.clear(); + } + else { + _current.assign(_iter, increment(_iter)); + } +} + +GHC_INLINE path::iterator& path::iterator::operator++() +{ + _iter = increment(_iter); + while (_iter != _last && // we didn't reach the end + _iter != _root && // this is not a root position + *_iter == preferred_separator && // we are on a separator + (_iter + 1) != _last // the slash is not the last char + ) { + ++_iter; + } + updateCurrent(); + return *this; +} + +GHC_INLINE path::iterator path::iterator::operator++(int) +{ + path::iterator i{*this}; + ++(*this); + return i; +} + +GHC_INLINE path::iterator& path::iterator::operator--() +{ + _iter = decrement(_iter); + updateCurrent(); + return *this; +} + +GHC_INLINE path::iterator path::iterator::operator--(int) +{ + auto i = *this; + --(*this); + return i; +} + +GHC_INLINE bool path::iterator::operator==(const path::iterator& other) const +{ + return _iter == other._iter; +} + +GHC_INLINE bool path::iterator::operator!=(const path::iterator& other) const +{ + return _iter != other._iter; +} + +GHC_INLINE path::iterator::reference path::iterator::operator*() const +{ + return _current; +} + +GHC_INLINE path::iterator::pointer path::iterator::operator->() const +{ + return &_current; +} + +GHC_INLINE path::iterator path::begin() const +{ + return iterator(*this, _path.begin()); +} + +GHC_INLINE path::iterator path::end() const +{ + return iterator(*this, _path.end()); +} + +//----------------------------------------------------------------------------- +// [fs.path.nonmember] path non-member functions +GHC_INLINE void swap(path& lhs, path& rhs) noexcept +{ + swap(lhs._path, rhs._path); +} + +GHC_INLINE size_t hash_value(const path& p) noexcept +{ + return std::hash()(p.generic_string()); +} + +#ifdef GHC_HAS_THREEWAY_COMP +GHC_INLINE std::strong_ordering operator<=>(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) <=> 0; +} +#endif + +GHC_INLINE bool operator==(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) == 0; +} + +GHC_INLINE bool operator!=(const path& lhs, const path& rhs) noexcept +{ + return !(lhs == rhs); +} + +GHC_INLINE bool operator<(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) < 0; +} + +GHC_INLINE bool operator<=(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) <= 0; +} + +GHC_INLINE bool operator>(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) > 0; +} + +GHC_INLINE bool operator>=(const path& lhs, const path& rhs) noexcept +{ + return lhs.compare(rhs) >= 0; +} + +GHC_INLINE path operator/(const path& lhs, const path& rhs) +{ + path result(lhs); + result /= rhs; + return result; +} + +#endif // GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.path.io] path inserter and extractor +template +inline std::basic_ostream& operator<<(std::basic_ostream& os, const path& p) +{ + os << "\""; + auto ps = p.string(); + for (auto c : ps) { + if (c == '"' || c == '\\') { + os << '\\'; + } + os << c; + } + os << "\""; + return os; +} + +template +inline std::basic_istream& operator>>(std::basic_istream& is, path& p) +{ + std::basic_string tmp; + charT c; + is >> c; + if (c == '"') { + auto sf = is.flags(); + is >> std::noskipws; + while (is) { + auto c2 = is.get(); + if (is) { + if (c2 == '\\') { + c2 = is.get(); + if (is) { + tmp += static_cast(c2); + } + } + else if (c2 == '"') { + break; + } + else { + tmp += static_cast(c2); + } + } + } + if ((sf & std::ios_base::skipws) == std::ios_base::skipws) { + is >> std::skipws; + } + p = path(tmp); + } + else { + is >> tmp; + p = path(static_cast(c) + tmp); + } + return is; +} + +#ifdef GHC_EXPAND_IMPL + +//----------------------------------------------------------------------------- +// [fs.class.filesystem_error] Class filesystem_error +GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, std::error_code ec) + : std::system_error(ec, what_arg) + , _what_arg(what_arg) + , _ec(ec) +{ +} + +GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, std::error_code ec) + : std::system_error(ec, what_arg) + , _what_arg(what_arg) + , _ec(ec) + , _p1(p1) +{ + if (!_p1.empty()) { + _what_arg += ": '" + _p1.string() + "'"; + } +} + +GHC_INLINE filesystem_error::filesystem_error(const std::string& what_arg, const path& p1, const path& p2, std::error_code ec) + : std::system_error(ec, what_arg) + , _what_arg(what_arg) + , _ec(ec) + , _p1(p1) + , _p2(p2) +{ + if (!_p1.empty()) { + _what_arg += ": '" + _p1.string() + "'"; + } + if (!_p2.empty()) { + _what_arg += ", '" + _p2.string() + "'"; + } +} + +GHC_INLINE const path& filesystem_error::path1() const noexcept +{ + return _p1; +} + +GHC_INLINE const path& filesystem_error::path2() const noexcept +{ + return _p2; +} + +GHC_INLINE const char* filesystem_error::what() const noexcept +{ + return _what_arg.c_str(); +} + +//----------------------------------------------------------------------------- +// [fs.op.funcs] filesystem operations +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path absolute(const path& p) +{ + std::error_code ec; + path result = absolute(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE path absolute(const path& p, std::error_code& ec) +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + if (p.empty()) { + return absolute(current_path(ec), ec) / ""; + } + ULONG size = ::GetFullPathNameW(GHC_NATIVEWP(p), 0, 0, 0); + if (size) { + std::vector buf(size, 0); + ULONG s2 = GetFullPathNameW(GHC_NATIVEWP(p), size, buf.data(), nullptr); + if (s2 && s2 < size) { + path result = path(std::wstring(buf.data(), s2)); + if (p.filename() == ".") { + result /= "."; + } + return result; + } + } + ec = detail::make_system_error(); + return path(); +#else + path base = current_path(ec); + if (!ec) { + if (p.empty()) { + return base / p; + } + if (p.has_root_name()) { + if (p.has_root_directory()) { + return p; + } + else { + return p.root_name() / base.root_directory() / base.relative_path() / p.relative_path(); + } + } + else { + if (p.has_root_directory()) { + return base.root_name() / p; + } + else { + return base / p; + } + } + } + ec = detail::make_system_error(); + return path(); +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path canonical(const path& p) +{ + std::error_code ec; + auto result = canonical(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE path canonical(const path& p, std::error_code& ec) +{ + if (p.empty()) { + ec = detail::make_error_code(detail::portable_error::not_found); + return path(); + } + path work = p.is_absolute() ? p : absolute(p, ec); + path result; + + auto fs = status(work, ec); + if (ec) { + return path(); + } + if (fs.type() == file_type::not_found) { + ec = detail::make_error_code(detail::portable_error::not_found); + return path(); + } + bool redo; + do { + auto rootPathLen = work._prefixLength + work.root_name_length() + (work.has_root_directory() ? 1 : 0); + redo = false; + result.clear(); + for (auto pe : work) { + if (pe.empty() || pe == ".") { + continue; + } + else if (pe == "..") { + result = result.parent_path(); + continue; + } + else if ((result / pe).string().length() <= rootPathLen) { + result /= pe; + continue; + } + auto sls = symlink_status(result / pe, ec); + if (ec) { + return path(); + } + if (is_symlink(sls)) { + redo = true; + auto target = read_symlink(result / pe, ec); + if (ec) { + return path(); + } + if (target.is_absolute()) { + result = target; + continue; + } + else { + result /= target; + continue; + } + } + else { + result /= pe; + } + } + work = result; + } while (redo); + ec.clear(); + return result; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void copy(const path& from, const path& to) +{ + copy(from, to, copy_options::none); +} + +GHC_INLINE void copy(const path& from, const path& to, copy_options options) +{ + std::error_code ec; + copy(from, to, options, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); + } +} +#endif + +GHC_INLINE void copy(const path& from, const path& to, std::error_code& ec) noexcept +{ + copy(from, to, copy_options::none, ec); +} + +GHC_INLINE void copy(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept +{ + std::error_code tec; + file_status fs_from, fs_to; + ec.clear(); + if ((options & (copy_options::skip_symlinks | copy_options::copy_symlinks | copy_options::create_symlinks)) != copy_options::none) { + fs_from = symlink_status(from, ec); + } + else { + fs_from = status(from, ec); + } + if (!exists(fs_from)) { + if (!ec) { + ec = detail::make_error_code(detail::portable_error::not_found); + } + return; + } + if ((options & (copy_options::skip_symlinks | copy_options::create_symlinks)) != copy_options::none) { + fs_to = symlink_status(to, tec); + } + else { + fs_to = status(to, tec); + } + if (is_other(fs_from) || is_other(fs_to) || (is_directory(fs_from) && is_regular_file(fs_to)) || (exists(fs_to) && equivalent(from, to, ec))) { + ec = detail::make_error_code(detail::portable_error::invalid_argument); + } + else if (is_symlink(fs_from)) { + if ((options & copy_options::skip_symlinks) == copy_options::none) { + if (!exists(fs_to) && (options & copy_options::copy_symlinks) != copy_options::none) { + copy_symlink(from, to, ec); + } + else { + ec = detail::make_error_code(detail::portable_error::invalid_argument); + } + } + } + else if (is_regular_file(fs_from)) { + if ((options & copy_options::directories_only) == copy_options::none) { + if ((options & copy_options::create_symlinks) != copy_options::none) { + create_symlink(from.is_absolute() ? from : canonical(from, ec), to, ec); + } +#ifndef GHC_OS_WEB + else if ((options & copy_options::create_hard_links) != copy_options::none) { + create_hard_link(from, to, ec); + } +#endif + else if (is_directory(fs_to)) { + copy_file(from, to / from.filename(), options, ec); + } + else { + copy_file(from, to, options, ec); + } + } + } +#ifdef LWG_2682_BEHAVIOUR + else if (is_directory(fs_from) && (options & copy_options::create_symlinks) != copy_options::none) { + ec = detail::make_error_code(detail::portable_error::is_a_directory); + } +#endif + else if (is_directory(fs_from) && (options == copy_options::none || (options & copy_options::recursive) != copy_options::none)) { + if (!exists(fs_to)) { + create_directory(to, from, ec); + if (ec) { + return; + } + } + for (auto iter = directory_iterator(from, ec); iter != directory_iterator(); iter.increment(ec)) { + if (!ec) { + copy(iter->path(), to / iter->path().filename(), options | static_cast(0x8000), ec); + } + if (ec) { + return; + } + } + } + return; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool copy_file(const path& from, const path& to) +{ + return copy_file(from, to, copy_options::none); +} + +GHC_INLINE bool copy_file(const path& from, const path& to, copy_options option) +{ + std::error_code ec; + auto result = copy_file(from, to, option, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); + } + return result; +} +#endif + +GHC_INLINE bool copy_file(const path& from, const path& to, std::error_code& ec) noexcept +{ + return copy_file(from, to, copy_options::none, ec); +} + +GHC_INLINE bool copy_file(const path& from, const path& to, copy_options options, std::error_code& ec) noexcept +{ + std::error_code tecf, tect; + auto sf = status(from, tecf); + auto st = status(to, tect); + bool overwrite = false; + ec.clear(); + if (!is_regular_file(sf)) { + ec = tecf; + return false; + } + if (exists(st)) { + if ((options & copy_options::skip_existing) == copy_options::skip_existing) { + return false; + } + if (!is_regular_file(st) || equivalent(from, to, ec) || (options & (copy_options::overwrite_existing | copy_options::update_existing)) == copy_options::none) { + ec = tect ? tect : detail::make_error_code(detail::portable_error::exists); + return false; + } + if ((options & copy_options::update_existing) == copy_options::update_existing) { + auto from_time = last_write_time(from, ec); + if (ec) { + ec = detail::make_system_error(); + return false; + } + auto to_time = last_write_time(to, ec); + if (ec) { + ec = detail::make_system_error(); + return false; + } + if (from_time <= to_time) { + return false; + } + } + overwrite = true; + } +#ifdef GHC_OS_WINDOWS + if (!::CopyFileW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), !overwrite)) { + ec = detail::make_system_error(); + return false; + } + return true; +#else + std::vector buffer(16384, '\0'); + int in = -1, out = -1; + if ((in = ::open(from.c_str(), O_RDONLY)) < 0) { + ec = detail::make_system_error(); + return false; + } + int mode = O_CREAT | O_WRONLY | O_TRUNC; + if (!overwrite) { + mode |= O_EXCL; + } + if ((out = ::open(to.c_str(), mode, static_cast(sf.permissions() & perms::all))) < 0) { + ec = detail::make_system_error(); + ::close(in); + return false; + } + if (st.permissions() != sf.permissions()) { + if (::fchmod(out, static_cast(sf.permissions() & perms::all)) != 0) { + ec = detail::make_system_error(); + ::close(in); + ::close(out); + return false; + } + } + ssize_t br, bw; + while (true) { + do { br = ::read(in, buffer.data(), buffer.size()); } while(errno == EINTR && !br); + if(!br) { + break; + } + if(br < 0) { + ec = detail::make_system_error(); + ::close(in); + ::close(out); + return false; + } + ssize_t offset = 0; + do { + if ((bw = ::write(out, buffer.data() + offset, static_cast(br))) > 0) { + br -= bw; + offset += bw; + } + else if (bw < 0 && errno != EINTR) { + ec = detail::make_system_error(); + ::close(in); + ::close(out); + return false; + } + } while (br); + } + ::close(in); + ::close(out); + return true; +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink) +{ + std::error_code ec; + copy_symlink(existing_symlink, new_symlink, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), existing_symlink, new_symlink, ec); + } +} +#endif + +GHC_INLINE void copy_symlink(const path& existing_symlink, const path& new_symlink, std::error_code& ec) noexcept +{ + ec.clear(); + auto to = read_symlink(existing_symlink, ec); + if (!ec) { + if (exists(to, ec) && is_directory(to, ec)) { + create_directory_symlink(to, new_symlink, ec); + } + else { + create_symlink(to, new_symlink, ec); + } + } +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool create_directories(const path& p) +{ + std::error_code ec; + auto result = create_directories(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE bool create_directories(const path& p, std::error_code& ec) noexcept +{ + path current; + ec.clear(); + bool didCreate = false; + auto rootPathLen = p._prefixLength + p.root_name_length() + (p.has_root_directory() ? 1 : 0); + current = p.native().substr(0, rootPathLen); + path folders(p._path.substr(rootPathLen)); + for (path::string_type part : folders) { + current /= part; + std::error_code tec; + auto fs = status(current, tec); + if (tec && fs.type() != file_type::not_found) { + ec = tec; + return false; + } + if (!exists(fs)) { + create_directory(current, ec); + if (ec) { + std::error_code tmp_ec; + if (is_directory(current, tmp_ec)) { + ec.clear(); + } + else { + return false; + } + } + didCreate = true; + } +#ifndef LWG_2935_BEHAVIOUR + else if (!is_directory(fs)) { + ec = detail::make_error_code(detail::portable_error::exists); + return false; + } +#endif + } + return didCreate; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool create_directory(const path& p) +{ + std::error_code ec; + auto result = create_directory(p, path(), ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE bool create_directory(const path& p, std::error_code& ec) noexcept +{ + return create_directory(p, path(), ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool create_directory(const path& p, const path& attributes) +{ + std::error_code ec; + auto result = create_directory(p, attributes, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE bool create_directory(const path& p, const path& attributes, std::error_code& ec) noexcept +{ + std::error_code tec; + ec.clear(); + auto fs = status(p, tec); +#ifdef LWG_2935_BEHAVIOUR + if (status_known(fs) && exists(fs)) { + return false; + } +#else + if (status_known(fs) && exists(fs) && is_directory(fs)) { + return false; + } +#endif +#ifdef GHC_OS_WINDOWS + if (!attributes.empty()) { + if (!::CreateDirectoryExW(GHC_NATIVEWP(attributes), GHC_NATIVEWP(p), NULL)) { + ec = detail::make_system_error(); + return false; + } + } + else if (!::CreateDirectoryW(GHC_NATIVEWP(p), NULL)) { + ec = detail::make_system_error(); + return false; + } +#else + ::mode_t attribs = static_cast(perms::all); + if (!attributes.empty()) { + struct ::stat fileStat; + if (::stat(attributes.c_str(), &fileStat) != 0) { + ec = detail::make_system_error(); + return false; + } + attribs = fileStat.st_mode; + } + if (::mkdir(p.c_str(), attribs) != 0) { + ec = detail::make_system_error(); + return false; + } +#endif + return true; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink) +{ + std::error_code ec; + create_directory_symlink(to, new_symlink, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec); + } +} +#endif + +GHC_INLINE void create_directory_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept +{ + detail::create_symlink(to, new_symlink, true, ec); +} + +#ifndef GHC_OS_WEB +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link) +{ + std::error_code ec; + create_hard_link(to, new_hard_link, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), to, new_hard_link, ec); + } +} +#endif + +GHC_INLINE void create_hard_link(const path& to, const path& new_hard_link, std::error_code& ec) noexcept +{ + detail::create_hardlink(to, new_hard_link, ec); +} +#endif + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void create_symlink(const path& to, const path& new_symlink) +{ + std::error_code ec; + create_symlink(to, new_symlink, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), to, new_symlink, ec); + } +} +#endif + +GHC_INLINE void create_symlink(const path& to, const path& new_symlink, std::error_code& ec) noexcept +{ + detail::create_symlink(to, new_symlink, false, ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path current_path() +{ + std::error_code ec; + auto result = current_path(ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), ec); + } + return result; +} +#endif + +GHC_INLINE path current_path(std::error_code& ec) +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + DWORD pathlen = ::GetCurrentDirectoryW(0, 0); + std::unique_ptr buffer(new wchar_t[size_t(pathlen) + 1]); + if (::GetCurrentDirectoryW(pathlen, buffer.get()) == 0) { + ec = detail::make_system_error(); + return path(); + } + return path(std::wstring(buffer.get()), path::native_format); +#elif defined(__GLIBC__) + std::unique_ptr buffer { ::getcwd(NULL, 0), std::free }; + if (buffer == nullptr) { + ec = detail::make_system_error(); + return path(); + } + return path(buffer.get()); +#else + size_t pathlen = static_cast(std::max(int(::pathconf(".", _PC_PATH_MAX)), int(PATH_MAX))); + std::unique_ptr buffer(new char[pathlen + 1]); + if (::getcwd(buffer.get(), pathlen) == nullptr) { + ec = detail::make_system_error(); + return path(); + } + return path(buffer.get()); +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void current_path(const path& p) +{ + std::error_code ec; + current_path(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } +} +#endif + +GHC_INLINE void current_path(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + if (!::SetCurrentDirectoryW(GHC_NATIVEWP(p))) { + ec = detail::make_system_error(); + } +#else + if (::chdir(p.string().c_str()) == -1) { + ec = detail::make_system_error(); + } +#endif +} + +GHC_INLINE bool exists(file_status s) noexcept +{ + return status_known(s) && s.type() != file_type::not_found; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool exists(const path& p) +{ + return exists(status(p)); +} +#endif + +GHC_INLINE bool exists(const path& p, std::error_code& ec) noexcept +{ + file_status s = status(p, ec); + if (status_known(s)) { + ec.clear(); + } + return exists(s); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool equivalent(const path& p1, const path& p2) +{ + std::error_code ec; + bool result = equivalent(p1, p2, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p1, p2, ec); + } + return result; +} +#endif + +GHC_INLINE bool equivalent(const path& p1, const path& p2, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + detail::unique_handle file1(::CreateFileW(GHC_NATIVEWP(p1), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); + auto e1 = ::GetLastError(); + detail::unique_handle file2(::CreateFileW(GHC_NATIVEWP(p2), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); + if (!file1 || !file2) { +#ifdef LWG_2937_BEHAVIOUR + ec = detail::make_system_error(e1 ? e1 : ::GetLastError()); +#else + if (file1 == file2) { + ec = detail::make_system_error(e1 ? e1 : ::GetLastError()); + } +#endif + return false; + } + BY_HANDLE_FILE_INFORMATION inf1, inf2; + if (!::GetFileInformationByHandle(file1.get(), &inf1)) { + ec = detail::make_system_error(); + return false; + } + if (!::GetFileInformationByHandle(file2.get(), &inf2)) { + ec = detail::make_system_error(); + return false; + } + return inf1.ftLastWriteTime.dwLowDateTime == inf2.ftLastWriteTime.dwLowDateTime && inf1.ftLastWriteTime.dwHighDateTime == inf2.ftLastWriteTime.dwHighDateTime && inf1.nFileIndexHigh == inf2.nFileIndexHigh && inf1.nFileIndexLow == inf2.nFileIndexLow && + inf1.nFileSizeHigh == inf2.nFileSizeHigh && inf1.nFileSizeLow == inf2.nFileSizeLow && inf1.dwVolumeSerialNumber == inf2.dwVolumeSerialNumber; +#else + struct ::stat s1, s2; + auto rc1 = ::stat(p1.c_str(), &s1); + auto e1 = errno; + auto rc2 = ::stat(p2.c_str(), &s2); + if (rc1 || rc2) { +#ifdef LWG_2937_BEHAVIOUR + ec = detail::make_system_error(e1 ? e1 : errno); +#else + if (rc1 && rc2) { + ec = detail::make_system_error(e1 ? e1 : errno); + } +#endif + return false; + } + return s1.st_dev == s2.st_dev && s1.st_ino == s2.st_ino && s1.st_size == s2.st_size && s1.st_mtime == s2.st_mtime; +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE uintmax_t file_size(const path& p) +{ + std::error_code ec; + auto result = file_size(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE uintmax_t file_size(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + WIN32_FILE_ATTRIBUTE_DATA attr; + if (!GetFileAttributesExW(GHC_NATIVEWP(p), GetFileExInfoStandard, &attr)) { + ec = detail::make_system_error(); + return static_cast(-1); + } + return static_cast(attr.nFileSizeHigh) << (sizeof(attr.nFileSizeHigh) * 8) | attr.nFileSizeLow; +#else + struct ::stat fileStat; + if (::stat(p.c_str(), &fileStat) == -1) { + ec = detail::make_system_error(); + return static_cast(-1); + } + return static_cast(fileStat.st_size); +#endif +} + +#ifndef GHC_OS_WEB +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE uintmax_t hard_link_count(const path& p) +{ + std::error_code ec; + auto result = hard_link_count(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE uintmax_t hard_link_count(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + uintmax_t result = static_cast(-1); + detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), 0, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, 0, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, 0)); + BY_HANDLE_FILE_INFORMATION inf; + if (!file) { + ec = detail::make_system_error(); + } + else { + if (!::GetFileInformationByHandle(file.get(), &inf)) { + ec = detail::make_system_error(); + } + else { + result = inf.nNumberOfLinks; + } + } + return result; +#else + uintmax_t result = 0; + file_status fs = detail::status_ex(p, ec, nullptr, nullptr, &result, nullptr); + if (fs.type() == file_type::not_found) { + ec = detail::make_error_code(detail::portable_error::not_found); + } + return ec ? static_cast(-1) : result; +#endif +} +#endif + +GHC_INLINE bool is_block_file(file_status s) noexcept +{ + return s.type() == file_type::block; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_block_file(const path& p) +{ + return is_block_file(status(p)); +} +#endif + +GHC_INLINE bool is_block_file(const path& p, std::error_code& ec) noexcept +{ + return is_block_file(status(p, ec)); +} + +GHC_INLINE bool is_character_file(file_status s) noexcept +{ + return s.type() == file_type::character; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_character_file(const path& p) +{ + return is_character_file(status(p)); +} +#endif + +GHC_INLINE bool is_character_file(const path& p, std::error_code& ec) noexcept +{ + return is_character_file(status(p, ec)); +} + +GHC_INLINE bool is_directory(file_status s) noexcept +{ + return s.type() == file_type::directory; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_directory(const path& p) +{ + return is_directory(status(p)); +} +#endif + +GHC_INLINE bool is_directory(const path& p, std::error_code& ec) noexcept +{ + return is_directory(status(p, ec)); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_empty(const path& p) +{ + if (is_directory(p)) { + return directory_iterator(p) == directory_iterator(); + } + else { + return file_size(p) == 0; + } +} +#endif + +GHC_INLINE bool is_empty(const path& p, std::error_code& ec) noexcept +{ + auto fs = status(p, ec); + if (ec) { + return false; + } + if (is_directory(fs)) { + directory_iterator iter(p, ec); + if (ec) { + return false; + } + return iter == directory_iterator(); + } + else { + auto sz = file_size(p, ec); + if (ec) { + return false; + } + return sz == 0; + } +} + +GHC_INLINE bool is_fifo(file_status s) noexcept +{ + return s.type() == file_type::fifo; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_fifo(const path& p) +{ + return is_fifo(status(p)); +} +#endif + +GHC_INLINE bool is_fifo(const path& p, std::error_code& ec) noexcept +{ + return is_fifo(status(p, ec)); +} + +GHC_INLINE bool is_other(file_status s) noexcept +{ + return exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_other(const path& p) +{ + return is_other(status(p)); +} +#endif + +GHC_INLINE bool is_other(const path& p, std::error_code& ec) noexcept +{ + return is_other(status(p, ec)); +} + +GHC_INLINE bool is_regular_file(file_status s) noexcept +{ + return s.type() == file_type::regular; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_regular_file(const path& p) +{ + return is_regular_file(status(p)); +} +#endif + +GHC_INLINE bool is_regular_file(const path& p, std::error_code& ec) noexcept +{ + return is_regular_file(status(p, ec)); +} + +GHC_INLINE bool is_socket(file_status s) noexcept +{ + return s.type() == file_type::socket; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_socket(const path& p) +{ + return is_socket(status(p)); +} +#endif + +GHC_INLINE bool is_socket(const path& p, std::error_code& ec) noexcept +{ + return is_socket(status(p, ec)); +} + +GHC_INLINE bool is_symlink(file_status s) noexcept +{ + return s.type() == file_type::symlink; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool is_symlink(const path& p) +{ + return is_symlink(symlink_status(p)); +} +#endif + +GHC_INLINE bool is_symlink(const path& p, std::error_code& ec) noexcept +{ + return is_symlink(symlink_status(p, ec)); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_time_type last_write_time(const path& p) +{ + std::error_code ec; + auto result = last_write_time(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE file_time_type last_write_time(const path& p, std::error_code& ec) noexcept +{ + time_t result = 0; + ec.clear(); + file_status fs = detail::status_ex(p, ec, nullptr, nullptr, nullptr, &result); + return ec ? (file_time_type::min)() : std::chrono::system_clock::from_time_t(result); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void last_write_time(const path& p, file_time_type new_time) +{ + std::error_code ec; + last_write_time(p, new_time, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } +} +#endif + +GHC_INLINE void last_write_time(const path& p, file_time_type new_time, std::error_code& ec) noexcept +{ + ec.clear(); + auto d = new_time.time_since_epoch(); +#ifdef GHC_OS_WINDOWS + detail::unique_handle file(::CreateFileW(GHC_NATIVEWP(p), FILE_WRITE_ATTRIBUTES, FILE_SHARE_DELETE | FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS, NULL)); + FILETIME ft; + auto tt = std::chrono::duration_cast(d).count() * 10 + 116444736000000000; + ft.dwLowDateTime = static_cast(tt); + ft.dwHighDateTime = static_cast(tt >> 32); + if (!::SetFileTime(file.get(), 0, 0, &ft)) { + ec = detail::make_system_error(); + } +#elif defined(GHC_OS_APPLE) && \ + (defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101300 \ + || defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 110000 \ + || defined(__TV_OS_VERSION_MIN_REQUIRED) && __TVOS_VERSION_MIN_REQUIRED < 110000 \ + || defined(__WATCH_OS_VERSION_MIN_REQUIRED) && __WATCHOS_VERSION_MIN_REQUIRED < 40000) + struct ::stat fs; + if (::stat(p.c_str(), &fs) == 0) { + struct ::timeval tv[2]; + tv[0].tv_sec = fs.st_atimespec.tv_sec; + tv[0].tv_usec = static_cast(fs.st_atimespec.tv_nsec / 1000); + tv[1].tv_sec = std::chrono::duration_cast(d).count(); + tv[1].tv_usec = static_cast(std::chrono::duration_cast(d).count() % 1000000); + if (::utimes(p.c_str(), tv) == 0) { + return; + } + } + ec = detail::make_system_error(); + return; +#else +#ifndef UTIME_OMIT +#define UTIME_OMIT ((1l << 30) - 2l) +#endif + struct ::timespec times[2]; + times[0].tv_sec = 0; + times[0].tv_nsec = UTIME_OMIT; + times[1].tv_sec = static_cast(std::chrono::duration_cast(d).count()); + times[1].tv_nsec = static_cast(std::chrono::duration_cast(d).count() % 1000000000); +#if defined(__ANDROID_API__) && __ANDROID_API__ < 12 + if (syscall(__NR_utimensat, AT_FDCWD, p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { +#else + if (::utimensat(static_cast(AT_FDCWD), p.c_str(), times, AT_SYMLINK_NOFOLLOW) != 0) { +#endif + ec = detail::make_system_error(); + } + return; +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void permissions(const path& p, perms prms, perm_options opts) +{ + std::error_code ec; + permissions(p, prms, opts, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } +} +#endif + +GHC_INLINE void permissions(const path& p, perms prms, std::error_code& ec) noexcept +{ + permissions(p, prms, perm_options::replace, ec); +} + +GHC_INLINE void permissions(const path& p, perms prms, perm_options opts, std::error_code& ec) noexcept +{ + if (static_cast(opts & (perm_options::replace | perm_options::add | perm_options::remove)) == 0) { + ec = detail::make_error_code(detail::portable_error::invalid_argument); + return; + } + auto fs = symlink_status(p, ec); + if ((opts & perm_options::replace) != perm_options::replace) { + if ((opts & perm_options::add) == perm_options::add) { + prms = fs.permissions() | prms; + } + else { + prms = fs.permissions() & ~prms; + } + } +#ifdef GHC_OS_WINDOWS +#ifdef __GNUC__ + auto oldAttr = GetFileAttributesW(GHC_NATIVEWP(p)); + if (oldAttr != INVALID_FILE_ATTRIBUTES) { + DWORD newAttr = ((prms & perms::owner_write) == perms::owner_write) ? oldAttr & ~(static_cast(FILE_ATTRIBUTE_READONLY)) : oldAttr | FILE_ATTRIBUTE_READONLY; + if (oldAttr == newAttr || SetFileAttributesW(GHC_NATIVEWP(p), newAttr)) { + return; + } + } + ec = detail::make_system_error(); +#else + int mode = 0; + if ((prms & perms::owner_read) == perms::owner_read) { + mode |= _S_IREAD; + } + if ((prms & perms::owner_write) == perms::owner_write) { + mode |= _S_IWRITE; + } + if (::_wchmod(p.wstring().c_str(), mode) != 0) { + ec = detail::make_system_error(); + } +#endif +#else + if ((opts & perm_options::nofollow) != perm_options::nofollow) { + if (::chmod(p.c_str(), static_cast(prms)) != 0) { + ec = detail::make_system_error(); + } + } +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path proximate(const path& p, std::error_code& ec) +{ + auto cp = current_path(ec); + if (!ec) { + return proximate(p, cp, ec); + } + return path(); +} +#endif + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path proximate(const path& p, const path& base) +{ + return weakly_canonical(p).lexically_proximate(weakly_canonical(base)); +} +#endif + +GHC_INLINE path proximate(const path& p, const path& base, std::error_code& ec) +{ + return weakly_canonical(p, ec).lexically_proximate(weakly_canonical(base, ec)); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path read_symlink(const path& p) +{ + std::error_code ec; + auto result = read_symlink(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE path read_symlink(const path& p, std::error_code& ec) +{ + file_status fs = symlink_status(p, ec); + if (fs.type() != file_type::symlink) { + ec = detail::make_error_code(detail::portable_error::invalid_argument); + return path(); + } + auto result = detail::resolveSymlink(p, ec); + return ec ? path() : result; +} + +GHC_INLINE path relative(const path& p, std::error_code& ec) +{ + return relative(p, current_path(ec), ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path relative(const path& p, const path& base) +{ + return weakly_canonical(p).lexically_relative(weakly_canonical(base)); +} +#endif + +GHC_INLINE path relative(const path& p, const path& base, std::error_code& ec) +{ + return weakly_canonical(p, ec).lexically_relative(weakly_canonical(base, ec)); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool remove(const path& p) +{ + std::error_code ec; + auto result = remove(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE bool remove(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS +#ifdef GHC_USE_WCHAR_T + auto cstr = p.c_str(); +#else + std::wstring np = detail::fromUtf8(p.u8string()); + auto cstr = np.c_str(); +#endif + DWORD attr = GetFileAttributesW(cstr); + if (attr == INVALID_FILE_ATTRIBUTES) { + auto error = ::GetLastError(); + if (error == ERROR_FILE_NOT_FOUND || error == ERROR_PATH_NOT_FOUND) { + return false; + } + ec = detail::make_system_error(error); + } + else if (attr & FILE_ATTRIBUTE_READONLY) { + auto new_attr = attr & ~static_cast(FILE_ATTRIBUTE_READONLY); + if (!SetFileAttributesW(cstr, new_attr)) { + auto error = ::GetLastError(); + ec = detail::make_system_error(error); + } + } + if (!ec) { + if (attr & FILE_ATTRIBUTE_DIRECTORY) { + if (!RemoveDirectoryW(cstr)) { + ec = detail::make_system_error(); + } + } + else { + if (!DeleteFileW(cstr)) { + ec = detail::make_system_error(); + } + } + } +#else + if (::remove(p.c_str()) == -1) { + auto error = errno; + if (error == ENOENT) { + return false; + } + ec = detail::make_system_error(); + } +#endif + return ec ? false : true; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE uintmax_t remove_all(const path& p) +{ + std::error_code ec; + auto result = remove_all(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE uintmax_t remove_all(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); + uintmax_t count = 0; + if (p == "/") { + ec = detail::make_error_code(detail::portable_error::not_supported); + return static_cast(-1); + } + std::error_code tec; + auto fs = symlink_status(p, tec); + if (exists(fs) && is_directory(fs)) { + for (auto iter = directory_iterator(p, ec); iter != directory_iterator(); iter.increment(ec)) { + if (ec && !detail::is_not_found_error(ec)) { + break; + } + bool is_symlink_result = iter->is_symlink(ec); + if (ec) + return static_cast(-1); + if (!is_symlink_result && iter->is_directory(ec)) { + count += remove_all(iter->path(), ec); + if (ec) { + return static_cast(-1); + } + } + else { + if (!ec) { + remove(iter->path(), ec); + } + if (ec) { + return static_cast(-1); + } + ++count; + } + } + } + if (!ec) { + if (remove(p, ec)) { + ++count; + } + } + if (ec) { + return static_cast(-1); + } + return count; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void rename(const path& from, const path& to) +{ + std::error_code ec; + rename(from, to, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), from, to, ec); + } +} +#endif + +GHC_INLINE void rename(const path& from, const path& to, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + if (from != to) { + if (!MoveFileExW(GHC_NATIVEWP(from), GHC_NATIVEWP(to), (DWORD)MOVEFILE_REPLACE_EXISTING)) { + ec = detail::make_system_error(); + } + } +#else + if (from != to) { + if (::rename(from.c_str(), to.c_str()) != 0) { + ec = detail::make_system_error(); + } + } +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void resize_file(const path& p, uintmax_t size) +{ + std::error_code ec; + resize_file(p, size, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } +} +#endif + +GHC_INLINE void resize_file(const path& p, uintmax_t size, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + LARGE_INTEGER lisize; + lisize.QuadPart = static_cast(size); + if (lisize.QuadPart < 0) { +#ifdef ERROR_FILE_TOO_LARGE + ec = detail::make_system_error(ERROR_FILE_TOO_LARGE); +#else + ec = detail::make_system_error(223); +#endif + return; + } + detail::unique_handle file(CreateFileW(GHC_NATIVEWP(p), GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL)); + if (!file) { + ec = detail::make_system_error(); + } + else if (SetFilePointerEx(file.get(), lisize, NULL, FILE_BEGIN) == 0 || SetEndOfFile(file.get()) == 0) { + ec = detail::make_system_error(); + } +#else + if (::truncate(p.c_str(), static_cast(size)) != 0) { + ec = detail::make_system_error(); + } +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE space_info space(const path& p) +{ + std::error_code ec; + auto result = space(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE space_info space(const path& p, std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + ULARGE_INTEGER freeBytesAvailableToCaller = {{ 0, 0 }}; + ULARGE_INTEGER totalNumberOfBytes = {{ 0, 0 }}; + ULARGE_INTEGER totalNumberOfFreeBytes = {{ 0, 0 }}; + if (!GetDiskFreeSpaceExW(GHC_NATIVEWP(p), &freeBytesAvailableToCaller, &totalNumberOfBytes, &totalNumberOfFreeBytes)) { + ec = detail::make_system_error(); + return {static_cast(-1), static_cast(-1), static_cast(-1)}; + } + return {static_cast(totalNumberOfBytes.QuadPart), static_cast(totalNumberOfFreeBytes.QuadPart), static_cast(freeBytesAvailableToCaller.QuadPart)}; +#else + struct ::statvfs sfs; + if (::statvfs(p.c_str(), &sfs) != 0) { + ec = detail::make_system_error(); + return {static_cast(-1), static_cast(-1), static_cast(-1)}; + } + return {static_cast(sfs.f_blocks) * static_cast(sfs.f_frsize), static_cast(sfs.f_bfree) * static_cast(sfs.f_frsize), static_cast(sfs.f_bavail) * static_cast(sfs.f_frsize)}; +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_status status(const path& p) +{ + std::error_code ec; + auto result = status(p, ec); + if (result.type() == file_type::none) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE file_status status(const path& p, std::error_code& ec) noexcept +{ + return detail::status_ex(p, ec); +} + +GHC_INLINE bool status_known(file_status s) noexcept +{ + return s.type() != file_type::none; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_status symlink_status(const path& p) +{ + std::error_code ec; + auto result = symlink_status(p, ec); + if (result.type() == file_type::none) { + throw filesystem_error(detail::systemErrorText(ec.value()), ec); + } + return result; +} +#endif + +GHC_INLINE file_status symlink_status(const path& p, std::error_code& ec) noexcept +{ + return detail::symlink_status_ex(p, ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path temp_directory_path() +{ + std::error_code ec; + path result = temp_directory_path(ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), ec); + } + return result; +} +#endif + +GHC_INLINE path temp_directory_path(std::error_code& ec) noexcept +{ + ec.clear(); +#ifdef GHC_OS_WINDOWS + wchar_t buffer[512]; + auto rc = GetTempPathW(511, buffer); + if (!rc || rc > 511) { + ec = detail::make_system_error(); + return path(); + } + return path(std::wstring(buffer)); +#else + static const char* temp_vars[] = {"TMPDIR", "TMP", "TEMP", "TEMPDIR", nullptr}; + const char* temp_path = nullptr; + for (auto temp_name = temp_vars; *temp_name != nullptr; ++temp_name) { + temp_path = std::getenv(*temp_name); + if (temp_path) { + return path(temp_path); + } + } + return path("/tmp"); +#endif +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE path weakly_canonical(const path& p) +{ + std::error_code ec; + auto result = weakly_canonical(p, ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), p, ec); + } + return result; +} +#endif + +GHC_INLINE path weakly_canonical(const path& p, std::error_code& ec) noexcept +{ + path result; + ec.clear(); + bool scan = true; + for (auto pe : p) { + if (scan) { + std::error_code tec; + if (exists(result / pe, tec)) { + result /= pe; + } + else { + if (ec) { + return path(); + } + scan = false; + if (!result.empty()) { + result = canonical(result, ec) / pe; + if (ec) { + break; + } + } + else { + result /= pe; + } + } + } + else { + result /= pe; + } + } + if (scan) { + if (!result.empty()) { + result = canonical(result, ec); + } + } + return ec ? path() : result.lexically_normal(); +} + +//----------------------------------------------------------------------------- +// [fs.class.file_status] class file_status +// [fs.file_status.cons] constructors and destructor +GHC_INLINE file_status::file_status() noexcept + : file_status(file_type::none) +{ +} + +GHC_INLINE file_status::file_status(file_type ft, perms prms) noexcept + : _type(ft) + , _perms(prms) +{ +} + +GHC_INLINE file_status::file_status(const file_status& other) noexcept + : _type(other._type) + , _perms(other._perms) +{ +} + +GHC_INLINE file_status::file_status(file_status&& other) noexcept + : _type(other._type) + , _perms(other._perms) +{ +} + +GHC_INLINE file_status::~file_status() {} + +// assignments: +GHC_INLINE file_status& file_status::operator=(const file_status& rhs) noexcept +{ + _type = rhs._type; + _perms = rhs._perms; + return *this; +} + +GHC_INLINE file_status& file_status::operator=(file_status&& rhs) noexcept +{ + _type = rhs._type; + _perms = rhs._perms; + return *this; +} + +// [fs.file_status.mods] modifiers +GHC_INLINE void file_status::type(file_type ft) noexcept +{ + _type = ft; +} + +GHC_INLINE void file_status::permissions(perms prms) noexcept +{ + _perms = prms; +} + +// [fs.file_status.obs] observers +GHC_INLINE file_type file_status::type() const noexcept +{ + return _type; +} + +GHC_INLINE perms file_status::permissions() const noexcept +{ + return _perms; +} + +//----------------------------------------------------------------------------- +// [fs.class.directory_entry] class directory_entry +// [fs.dir.entry.cons] constructors and destructor +// directory_entry::directory_entry() noexcept = default; +// directory_entry::directory_entry(const directory_entry&) = default; +// directory_entry::directory_entry(directory_entry&&) noexcept = default; +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE directory_entry::directory_entry(const filesystem::path& p) + : _path(p) + , _file_size(static_cast(-1)) +#ifndef GHC_OS_WINDOWS + , _hard_link_count(static_cast(-1)) +#endif + , _last_write_time(0) +{ + refresh(); +} +#endif + +GHC_INLINE directory_entry::directory_entry(const filesystem::path& p, std::error_code& ec) + : _path(p) + , _file_size(static_cast(-1)) +#ifndef GHC_OS_WINDOWS + , _hard_link_count(static_cast(-1)) +#endif + , _last_write_time(0) +{ + refresh(ec); +} + +GHC_INLINE directory_entry::~directory_entry() {} + +// assignments: +// directory_entry& directory_entry::operator=(const directory_entry&) = default; +// directory_entry& directory_entry::operator=(directory_entry&&) noexcept = default; + +// [fs.dir.entry.mods] directory_entry modifiers +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void directory_entry::assign(const filesystem::path& p) +{ + _path = p; + refresh(); +} +#endif + +GHC_INLINE void directory_entry::assign(const filesystem::path& p, std::error_code& ec) +{ + _path = p; + refresh(ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p) +{ + _path.replace_filename(p); + refresh(); +} +#endif + +GHC_INLINE void directory_entry::replace_filename(const filesystem::path& p, std::error_code& ec) +{ + _path.replace_filename(p); + refresh(ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void directory_entry::refresh() +{ + std::error_code ec; + refresh(ec); + if (ec && (_status.type() == file_type::none || _symlink_status.type() != file_type::symlink)) { + throw filesystem_error(detail::systemErrorText(ec.value()), _path, ec); + } +} +#endif + +GHC_INLINE void directory_entry::refresh(std::error_code& ec) noexcept +{ +#ifdef GHC_OS_WINDOWS + _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, nullptr, &_last_write_time); +#else + _status = detail::status_ex(_path, ec, &_symlink_status, &_file_size, &_hard_link_count, &_last_write_time); +#endif +} + +// [fs.dir.entry.obs] directory_entry observers +GHC_INLINE const filesystem::path& directory_entry::path() const noexcept +{ + return _path; +} + +GHC_INLINE directory_entry::operator const filesystem::path&() const noexcept +{ + return _path; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_type directory_entry::status_file_type() const +{ + return _status.type() != file_type::none ? _status.type() : filesystem::status(path()).type(); +} +#endif + +GHC_INLINE file_type directory_entry::status_file_type(std::error_code& ec) const noexcept +{ + if (_status.type() != file_type::none) { + ec.clear(); + return _status.type(); + } + return filesystem::status(path(), ec).type(); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::exists() const +{ + return status_file_type() != file_type::not_found; +} +#endif + +GHC_INLINE bool directory_entry::exists(std::error_code& ec) const noexcept +{ + return status_file_type(ec) != file_type::not_found; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_block_file() const +{ + return status_file_type() == file_type::block; +} +#endif +GHC_INLINE bool directory_entry::is_block_file(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::block; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_character_file() const +{ + return status_file_type() == file_type::character; +} +#endif + +GHC_INLINE bool directory_entry::is_character_file(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::character; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_directory() const +{ + return status_file_type() == file_type::directory; +} +#endif + +GHC_INLINE bool directory_entry::is_directory(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::directory; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_fifo() const +{ + return status_file_type() == file_type::fifo; +} +#endif + +GHC_INLINE bool directory_entry::is_fifo(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::fifo; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_other() const +{ + auto ft = status_file_type(); + return ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(); +} +#endif + +GHC_INLINE bool directory_entry::is_other(std::error_code& ec) const noexcept +{ + auto ft = status_file_type(ec); + bool other = ft != file_type::none && ft != file_type::not_found && ft != file_type::regular && ft != file_type::directory && !is_symlink(ec); + return !ec && other; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_regular_file() const +{ + return status_file_type() == file_type::regular; +} +#endif + +GHC_INLINE bool directory_entry::is_regular_file(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::regular; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_socket() const +{ + return status_file_type() == file_type::socket; +} +#endif + +GHC_INLINE bool directory_entry::is_socket(std::error_code& ec) const noexcept +{ + return status_file_type(ec) == file_type::socket; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE bool directory_entry::is_symlink() const +{ + return _symlink_status.type() != file_type::none ? _symlink_status.type() == file_type::symlink : filesystem::is_symlink(symlink_status()); +} +#endif + +GHC_INLINE bool directory_entry::is_symlink(std::error_code& ec) const noexcept +{ + if (_symlink_status.type() != file_type::none) { + ec.clear(); + return _symlink_status.type() == file_type::symlink; + } + return filesystem::is_symlink(symlink_status(ec)); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE uintmax_t directory_entry::file_size() const +{ + if (_file_size != static_cast(-1)) { + return _file_size; + } + return filesystem::file_size(path()); +} +#endif + +GHC_INLINE uintmax_t directory_entry::file_size(std::error_code& ec) const noexcept +{ + if (_file_size != static_cast(-1)) { + ec.clear(); + return _file_size; + } + return filesystem::file_size(path(), ec); +} + +#ifndef GHC_OS_WEB +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE uintmax_t directory_entry::hard_link_count() const +{ +#ifndef GHC_OS_WINDOWS + if (_hard_link_count != static_cast(-1)) { + return _hard_link_count; + } +#endif + return filesystem::hard_link_count(path()); +} +#endif + +GHC_INLINE uintmax_t directory_entry::hard_link_count(std::error_code& ec) const noexcept +{ +#ifndef GHC_OS_WINDOWS + if (_hard_link_count != static_cast(-1)) { + ec.clear(); + return _hard_link_count; + } +#endif + return filesystem::hard_link_count(path(), ec); +} +#endif + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_time_type directory_entry::last_write_time() const +{ + if (_last_write_time != 0) { + return std::chrono::system_clock::from_time_t(_last_write_time); + } + return filesystem::last_write_time(path()); +} +#endif + +GHC_INLINE file_time_type directory_entry::last_write_time(std::error_code& ec) const noexcept +{ + if (_last_write_time != 0) { + ec.clear(); + return std::chrono::system_clock::from_time_t(_last_write_time); + } + return filesystem::last_write_time(path(), ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_status directory_entry::status() const +{ + if (_status.type() != file_type::none && _status.permissions() != perms::unknown) { + return _status; + } + return filesystem::status(path()); +} +#endif + +GHC_INLINE file_status directory_entry::status(std::error_code& ec) const noexcept +{ + if (_status.type() != file_type::none && _status.permissions() != perms::unknown) { + ec.clear(); + return _status; + } + return filesystem::status(path(), ec); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE file_status directory_entry::symlink_status() const +{ + if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) { + return _symlink_status; + } + return filesystem::symlink_status(path()); +} +#endif + +GHC_INLINE file_status directory_entry::symlink_status(std::error_code& ec) const noexcept +{ + if (_symlink_status.type() != file_type::none && _symlink_status.permissions() != perms::unknown) { + ec.clear(); + return _symlink_status; + } + return filesystem::symlink_status(path(), ec); +} + +#ifdef GHC_HAS_THREEWAY_COMP +GHC_INLINE std::strong_ordering directory_entry::operator<=>(const directory_entry& rhs) const noexcept +{ + return _path <=> rhs._path; +} +#endif + +GHC_INLINE bool directory_entry::operator<(const directory_entry& rhs) const noexcept +{ + return _path < rhs._path; +} + +GHC_INLINE bool directory_entry::operator==(const directory_entry& rhs) const noexcept +{ + return _path == rhs._path; +} + +GHC_INLINE bool directory_entry::operator!=(const directory_entry& rhs) const noexcept +{ + return _path != rhs._path; +} + +GHC_INLINE bool directory_entry::operator<=(const directory_entry& rhs) const noexcept +{ + return _path <= rhs._path; +} + +GHC_INLINE bool directory_entry::operator>(const directory_entry& rhs) const noexcept +{ + return _path > rhs._path; +} + +GHC_INLINE bool directory_entry::operator>=(const directory_entry& rhs) const noexcept +{ + return _path >= rhs._path; +} + +//----------------------------------------------------------------------------- +// [fs.class.directory_iterator] class directory_iterator + +#ifdef GHC_OS_WINDOWS +class directory_iterator::impl +{ +public: + impl(const path& p, directory_options options) + : _base(p) + , _options(options) + , _dirHandle(INVALID_HANDLE_VALUE) + { + if (!_base.empty()) { + ZeroMemory(&_findData, sizeof(WIN32_FIND_DATAW)); + if ((_dirHandle = FindFirstFileW(GHC_NATIVEWP((_base / "*")), &_findData)) != INVALID_HANDLE_VALUE) { + if (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L"..") { + increment(_ec); + } + else { + _dir_entry._path = _base / std::wstring(_findData.cFileName); + copyToDirEntry(_ec); + } + } + else { + auto error = ::GetLastError(); + _base = filesystem::path(); + if (error != ERROR_ACCESS_DENIED || (options & directory_options::skip_permission_denied) == directory_options::none) { + _ec = detail::make_system_error(); + } + } + } + } + impl(const impl& other) = delete; + ~impl() + { + if (_dirHandle != INVALID_HANDLE_VALUE) { + FindClose(_dirHandle); + _dirHandle = INVALID_HANDLE_VALUE; + } + } + void increment(std::error_code& ec) + { + if (_dirHandle != INVALID_HANDLE_VALUE) { + do { + if (FindNextFileW(_dirHandle, &_findData)) { + _dir_entry._path = _base; +#ifdef GHC_USE_WCHAR_T + _dir_entry._path.append_name(_findData.cFileName); +#else +#ifdef GHC_RAISE_UNICODE_ERRORS + try { + _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str()); + } + catch (filesystem_error& fe) { + ec = fe.code(); + return; + } +#else + _dir_entry._path.append_name(detail::toUtf8(_findData.cFileName).c_str()); +#endif +#endif + copyToDirEntry(ec); + } + else { + auto err = ::GetLastError(); + if (err != ERROR_NO_MORE_FILES) { + _ec = ec = detail::make_system_error(err); + } + FindClose(_dirHandle); + _dirHandle = INVALID_HANDLE_VALUE; + _dir_entry._path.clear(); + break; + } + } while (std::wstring(_findData.cFileName) == L"." || std::wstring(_findData.cFileName) == L".."); + } + else { + ec = _ec; + } + } + void copyToDirEntry(std::error_code& ec) + { + if (_findData.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT) { + _dir_entry._status = detail::status_ex(_dir_entry._path, ec, &_dir_entry._symlink_status, &_dir_entry._file_size, nullptr, &_dir_entry._last_write_time); + } + else { + _dir_entry._status = detail::status_from_INFO(_dir_entry._path, &_findData, ec, &_dir_entry._file_size, &_dir_entry._last_write_time); + _dir_entry._symlink_status = _dir_entry._status; + } + if (ec) { + if (_dir_entry._status.type() != file_type::none && _dir_entry._symlink_status.type() != file_type::none) { + ec.clear(); + } + else { + _dir_entry._file_size = static_cast(-1); + _dir_entry._last_write_time = 0; + } + } + } + path _base; + directory_options _options; + WIN32_FIND_DATAW _findData; + HANDLE _dirHandle; + directory_entry _dir_entry; + std::error_code _ec; +}; +#else +// POSIX implementation +class directory_iterator::impl +{ +public: + impl(const path& path, directory_options options) + : _base(path) + , _options(options) + , _dir(nullptr) + , _entry(nullptr) + { + if (!path.empty()) { + do { _dir = ::opendir(path.native().c_str()); } while(errno == EINTR && !_dir); + if (!_dir) { + auto error = errno; + _base = filesystem::path(); + if ((error != EACCES && error != EPERM) || (options & directory_options::skip_permission_denied) == directory_options::none) { + _ec = detail::make_system_error(); + } + } + else { + increment(_ec); + } + } + } + impl(const impl& other) = delete; + ~impl() + { + if (_dir) { + ::closedir(_dir); + } + } + void increment(std::error_code& ec) + { + if (_dir) { + bool skip; + do { + skip = false; + errno = 0; + do { _entry = ::readdir(_dir); } while(errno == EINTR && !_entry); + if (_entry) { + _dir_entry._path = _base; + _dir_entry._path.append_name(_entry->d_name); + copyToDirEntry(); + if (ec && (ec.value() == EACCES || ec.value() == EPERM) && (_options & directory_options::skip_permission_denied) == directory_options::skip_permission_denied) { + ec.clear(); + skip = true; + } + } + else { + ::closedir(_dir); + _dir = nullptr; + _dir_entry._path.clear(); + if (errno && errno != EINTR) { + ec = detail::make_system_error(); + } + break; + } + } while (skip || std::strcmp(_entry->d_name, ".") == 0 || std::strcmp(_entry->d_name, "..") == 0); + } + } + + void copyToDirEntry() + { + _dir_entry._symlink_status.permissions(perms::unknown); + auto ft = detail::file_type_from_dirent(*_entry); + _dir_entry._symlink_status.type(ft); + if (ft != file_type::symlink) { + _dir_entry._status = _dir_entry._symlink_status; + } + else { + _dir_entry._status.type(file_type::none); + _dir_entry._status.permissions(perms::unknown); + } + _dir_entry._file_size = static_cast(-1); + _dir_entry._hard_link_count = static_cast(-1); + _dir_entry._last_write_time = 0; + } + path _base; + directory_options _options; + DIR* _dir; + struct ::dirent* _entry; + directory_entry _dir_entry; + std::error_code _ec; +}; +#endif + +// [fs.dir.itr.members] member functions +GHC_INLINE directory_iterator::directory_iterator() noexcept + : _impl(new impl(path(), directory_options::none)) +{ +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE directory_iterator::directory_iterator(const path& p) + : _impl(new impl(p, directory_options::none)) +{ + if (_impl->_ec) { + throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec); + } + _impl->_ec.clear(); +} + +GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options) + : _impl(new impl(p, options)) +{ + if (_impl->_ec) { + throw filesystem_error(detail::systemErrorText(_impl->_ec.value()), p, _impl->_ec); + } +} +#endif + +GHC_INLINE directory_iterator::directory_iterator(const path& p, std::error_code& ec) noexcept + : _impl(new impl(p, directory_options::none)) +{ + if (_impl->_ec) { + ec = _impl->_ec; + } +} + +GHC_INLINE directory_iterator::directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept + : _impl(new impl(p, options)) +{ + if (_impl->_ec) { + ec = _impl->_ec; + } +} + +GHC_INLINE directory_iterator::directory_iterator(const directory_iterator& rhs) + : _impl(rhs._impl) +{ +} + +GHC_INLINE directory_iterator::directory_iterator(directory_iterator&& rhs) noexcept + : _impl(std::move(rhs._impl)) +{ +} + +GHC_INLINE directory_iterator::~directory_iterator() {} + +GHC_INLINE directory_iterator& directory_iterator::operator=(const directory_iterator& rhs) +{ + _impl = rhs._impl; + return *this; +} + +GHC_INLINE directory_iterator& directory_iterator::operator=(directory_iterator&& rhs) noexcept +{ + _impl = std::move(rhs._impl); + return *this; +} + +GHC_INLINE const directory_entry& directory_iterator::operator*() const +{ + return _impl->_dir_entry; +} + +GHC_INLINE const directory_entry* directory_iterator::operator->() const +{ + return &_impl->_dir_entry; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE directory_iterator& directory_iterator::operator++() +{ + std::error_code ec; + _impl->increment(ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_entry._path, ec); + } + return *this; +} +#endif + +GHC_INLINE directory_iterator& directory_iterator::increment(std::error_code& ec) noexcept +{ + _impl->increment(ec); + return *this; +} + +GHC_INLINE bool directory_iterator::operator==(const directory_iterator& rhs) const +{ + return _impl->_dir_entry._path == rhs._impl->_dir_entry._path; +} + +GHC_INLINE bool directory_iterator::operator!=(const directory_iterator& rhs) const +{ + return _impl->_dir_entry._path != rhs._impl->_dir_entry._path; +} + +// [fs.dir.itr.nonmembers] directory_iterator non-member functions + +GHC_INLINE directory_iterator begin(directory_iterator iter) noexcept +{ + return iter; +} + +GHC_INLINE directory_iterator end(const directory_iterator&) noexcept +{ + return directory_iterator(); +} + +//----------------------------------------------------------------------------- +// [fs.class.rec.dir.itr] class recursive_directory_iterator + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator() noexcept + : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) +{ + _impl->_dir_iter_stack.push(directory_iterator()); +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p) + : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) +{ + _impl->_dir_iter_stack.push(directory_iterator(p)); +} + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options) + : _impl(new recursive_directory_iterator_impl(options, true)) +{ + _impl->_dir_iter_stack.push(directory_iterator(p, options)); +} +#endif + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, directory_options options, std::error_code& ec) noexcept + : _impl(new recursive_directory_iterator_impl(options, true)) +{ + _impl->_dir_iter_stack.push(directory_iterator(p, options, ec)); +} + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const path& p, std::error_code& ec) noexcept + : _impl(new recursive_directory_iterator_impl(directory_options::none, true)) +{ + _impl->_dir_iter_stack.push(directory_iterator(p, ec)); +} + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(const recursive_directory_iterator& rhs) + : _impl(rhs._impl) +{ +} + +GHC_INLINE recursive_directory_iterator::recursive_directory_iterator(recursive_directory_iterator&& rhs) noexcept + : _impl(std::move(rhs._impl)) +{ +} + +GHC_INLINE recursive_directory_iterator::~recursive_directory_iterator() {} + +// [fs.rec.dir.itr.members] observers +GHC_INLINE directory_options recursive_directory_iterator::options() const +{ + return _impl->_options; +} + +GHC_INLINE int recursive_directory_iterator::depth() const +{ + return static_cast(_impl->_dir_iter_stack.size() - 1); +} + +GHC_INLINE bool recursive_directory_iterator::recursion_pending() const +{ + return _impl->_recursion_pending; +} + +GHC_INLINE const directory_entry& recursive_directory_iterator::operator*() const +{ + return *(_impl->_dir_iter_stack.top()); +} + +GHC_INLINE const directory_entry* recursive_directory_iterator::operator->() const +{ + return &(*(_impl->_dir_iter_stack.top())); +} + +// [fs.rec.dir.itr.members] modifiers recursive_directory_iterator& +GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(const recursive_directory_iterator& rhs) +{ + _impl = rhs._impl; + return *this; +} + +GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator=(recursive_directory_iterator&& rhs) noexcept +{ + _impl = std::move(rhs._impl); + return *this; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::operator++() +{ + std::error_code ec; + increment(ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec); + } + return *this; +} +#endif + +GHC_INLINE recursive_directory_iterator& recursive_directory_iterator::increment(std::error_code& ec) noexcept +{ + bool isSymLink = (*this)->is_symlink(ec); + bool isDir = !ec && (*this)->is_directory(ec); + if (isSymLink && detail::is_not_found_error(ec)) { + ec.clear(); + } + if (!ec) { + if (recursion_pending() && isDir && (!isSymLink || (options() & directory_options::follow_directory_symlink) != directory_options::none)) { + _impl->_dir_iter_stack.push(directory_iterator((*this)->path(), _impl->_options, ec)); + } + else { + _impl->_dir_iter_stack.top().increment(ec); + } + if (!ec) { + while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()) { + _impl->_dir_iter_stack.pop(); + _impl->_dir_iter_stack.top().increment(ec); + } + } + else if (!_impl->_dir_iter_stack.empty()) { + _impl->_dir_iter_stack.pop(); + } + _impl->_recursion_pending = true; + } + return *this; +} + +#ifdef GHC_WITH_EXCEPTIONS +GHC_INLINE void recursive_directory_iterator::pop() +{ + std::error_code ec; + pop(ec); + if (ec) { + throw filesystem_error(detail::systemErrorText(ec.value()), _impl->_dir_iter_stack.empty() ? path() : _impl->_dir_iter_stack.top()->path(), ec); + } +} +#endif + +GHC_INLINE void recursive_directory_iterator::pop(std::error_code& ec) +{ + if (depth() == 0) { + *this = recursive_directory_iterator(); + } + else { + do { + _impl->_dir_iter_stack.pop(); + _impl->_dir_iter_stack.top().increment(ec); + } while (depth() && _impl->_dir_iter_stack.top() == directory_iterator()); + } +} + +GHC_INLINE void recursive_directory_iterator::disable_recursion_pending() +{ + _impl->_recursion_pending = false; +} + +// other members as required by [input.iterators] +GHC_INLINE bool recursive_directory_iterator::operator==(const recursive_directory_iterator& rhs) const +{ + return _impl->_dir_iter_stack.top() == rhs._impl->_dir_iter_stack.top(); +} + +GHC_INLINE bool recursive_directory_iterator::operator!=(const recursive_directory_iterator& rhs) const +{ + return _impl->_dir_iter_stack.top() != rhs._impl->_dir_iter_stack.top(); +} + +// [fs.rec.dir.itr.nonmembers] directory_iterator non-member functions +GHC_INLINE recursive_directory_iterator begin(recursive_directory_iterator iter) noexcept +{ + return iter; +} + +GHC_INLINE recursive_directory_iterator end(const recursive_directory_iterator&) noexcept +{ + return recursive_directory_iterator(); +} + +#endif // GHC_EXPAND_IMPL + +} // namespace filesystem +} // namespace ghc + +// cleanup some macros +#undef GHC_INLINE +#undef GHC_EXPAND_IMPL + +#endif // GHC_FILESYSTEM_H + diff --git a/3rdparty/openal/common/intrusive_ptr.h b/3rdparty/openal/common/intrusive_ptr.h index 27075347998e..1a446f44b87f 100644 --- a/3rdparty/openal/common/intrusive_ptr.h +++ b/3rdparty/openal/common/intrusive_ptr.h @@ -1,6 +1,8 @@ #ifndef INTRUSIVE_PTR_H #define INTRUSIVE_PTR_H +#include +#include #include #include "atomic.h" @@ -11,7 +13,10 @@ namespace al { template class intrusive_ref { - RefCount mRef{1u}; + std::atomic mRef{1u}; + +protected: + ~intrusive_ref() = default; public: unsigned int add_ref() noexcept { return IncrementRef(mRef); } @@ -46,7 +51,7 @@ class intrusive_ref { }; -template +template /* NOLINTNEXTLINE(clazy-rule-of-three) False positive */ class intrusive_ptr { T *mPtr{nullptr}; @@ -56,10 +61,13 @@ class intrusive_ptr { { if(mPtr) mPtr->add_ref(); } intrusive_ptr(intrusive_ptr&& rhs) noexcept : mPtr{rhs.mPtr} { rhs.mPtr = nullptr; } - intrusive_ptr(std::nullptr_t) noexcept { } + intrusive_ptr(std::nullptr_t) noexcept { } /* NOLINT(google-explicit-constructor) */ explicit intrusive_ptr(T *ptr) noexcept : mPtr{ptr} { } ~intrusive_ptr() { if(mPtr) mPtr->dec_ref(); } + /* NOLINTBEGIN(bugprone-unhandled-self-assignment) + * Self-assignment is handled properly here. + */ intrusive_ptr& operator=(const intrusive_ptr &rhs) noexcept { static_assert(noexcept(std::declval()->dec_ref()), "dec_ref must be noexcept"); @@ -69,6 +77,7 @@ class intrusive_ptr { mPtr = rhs.mPtr; return *this; } + /* NOLINTEND(bugprone-unhandled-self-assignment) */ intrusive_ptr& operator=(intrusive_ptr&& rhs) noexcept { if(&rhs != this) LIKELY @@ -81,9 +90,9 @@ class intrusive_ptr { explicit operator bool() const noexcept { return mPtr != nullptr; } - T& operator*() const noexcept { return *mPtr; } - T* operator->() const noexcept { return mPtr; } - T* get() const noexcept { return mPtr; } + [[nodiscard]] auto operator*() const noexcept -> T& { return *mPtr; } + [[nodiscard]] auto operator->() const noexcept -> T* { return mPtr; } + [[nodiscard]] auto get() const noexcept -> T* { return mPtr; } void reset(T *ptr=nullptr) noexcept { @@ -98,23 +107,6 @@ class intrusive_ptr { void swap(intrusive_ptr&& rhs) noexcept { std::swap(mPtr, rhs.mPtr); } }; -#define AL_DECL_OP(op) \ -template \ -inline bool operator op(const intrusive_ptr &lhs, const T *rhs) noexcept \ -{ return lhs.get() op rhs; } \ -template \ -inline bool operator op(const T *lhs, const intrusive_ptr &rhs) noexcept \ -{ return lhs op rhs.get(); } - -AL_DECL_OP(==) -AL_DECL_OP(!=) -AL_DECL_OP(<=) -AL_DECL_OP(>=) -AL_DECL_OP(<) -AL_DECL_OP(>) - -#undef AL_DECL_OP - } // namespace al #endif /* INTRUSIVE_PTR_H */ diff --git a/3rdparty/openal/common/opthelpers.h b/3rdparty/openal/common/opthelpers.h index dc43ccdb5301..e22f220fedbb 100644 --- a/3rdparty/openal/common/opthelpers.h +++ b/3rdparty/openal/common/opthelpers.h @@ -28,6 +28,24 @@ #define NOINLINE #endif +#if defined(__MINGW32__) && defined(__i386__) +/* 32-bit MinGW targets have a bug where __STDCPP_DEFAULT_NEW_ALIGNMENT__ + * reports 16, despite the default operator new calling standard malloc which + * only guarantees 8-byte alignment. As a result, structs that need and specify + * 16-byte alignment only get 8-byte alignment. Explicitly specifying 32-byte + * alignment forces the over-aligned operator new to be called, giving the + * correct (if larger than necessary) alignment. + * + * Technically this bug affects 32-bit GCC more generally, but typically only + * with fairly old glibc versions as newer versions do guarantee the 16-byte + * alignment as specified. MinGW is reliant on msvcrt.dll's malloc however, + * which can't be updated to give that guarantee. + */ +#define SIMDALIGN alignas(32) +#else +#define SIMDALIGN +#endif + /* Unlike the likely attribute, ASSUME requires the condition to be true or * else it invokes undefined behavior. It's essentially an assert without * actually checking the condition at run-time, allowing for stronger @@ -42,7 +60,7 @@ #elif HAS_BUILTIN(__builtin_unreachable) #define ASSUME(x) do { if(x) break; __builtin_unreachable(); } while(0) #else -#define ASSUME(x) ((void)0) +#define ASSUME(x) (static_cast(0)) #endif /* This shouldn't be needed since unknown attributes are ignored, but older @@ -56,6 +74,12 @@ #define UNLIKELY #endif +#if !defined(_WIN32) && HAS_ATTRIBUTE(gnu::visibility) +#define DECL_HIDDEN [[gnu::visibility("hidden")]] +#else +#define DECL_HIDDEN +#endif + namespace al { template diff --git a/3rdparty/openal/common/pffft.cpp b/3rdparty/openal/common/pffft.cpp new file mode 100644 index 000000000000..07b6fbccfd5c --- /dev/null +++ b/3rdparty/openal/common/pffft.cpp @@ -0,0 +1,2308 @@ +//$ nobt + +/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) + * Copyright (c) 2023 Christopher Robinson + * + * Based on original fortran 77 code from FFTPACKv4 from NETLIB + * (http://www.netlib.org/fftpack), authored by Dr Paul Swarztrauber + * of NCAR, in 1985. + * + * As confirmed by the NCAR fftpack software curators, the following + * FFTPACKv5 license applies to FFTPACKv4 sources. My changes are + * released under the same terms. + * + * FFTPACK license: + * + * http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html + * + * Copyright (c) 2004 the University Corporation for Atmospheric + * Research ("UCAR"). All rights reserved. Developed by NCAR's + * Computational and Information Systems Laboratory, UCAR, + * www.cisl.ucar.edu. + * + * Redistribution and use of the Software in source and binary forms, + * with or without modification, is permitted provided that the + * following conditions are met: + * + * - Neither the names of NCAR's Computational and Information Systems + * Laboratory, the University Corporation for Atmospheric Research, + * nor the names of its sponsors or contributors may be used to + * endorse or promote products derived from this Software without + * specific prior written permission. + * + * - Redistributions of source code must retain the above copyright + * notices, this list of conditions, and the disclaimer below. + * + * - Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions, and the disclaimer below in the + * documentation and/or other materials provided with the + * distribution. + * + * THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + * HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + * SOFTWARE. + * + * + * PFFFT : a Pretty Fast FFT. + * + * This file is largerly based on the original FFTPACK implementation, modified + * in order to take advantage of SIMD instructions of modern CPUs. + */ + +#include "pffft.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "albit.h" +#include "almalloc.h" +#include "alnumbers.h" +#include "alnumeric.h" +#include "alspan.h" +#include "fmt/core.h" +#include "fmt/ranges.h" +#include "opthelpers.h" + + +using uint = unsigned int; + +namespace { + +#if defined(__GNUC__) || defined(_MSC_VER) +#define RESTRICT __restrict +#else +#define RESTRICT +#endif + +/* Vector support macros: the rest of the code is independent of + * SSE/Altivec/NEON -- adding support for other platforms with 4-element + * vectors should be limited to these macros + */ + +/* Define PFFFT_SIMD_DISABLE if you want to use scalar code instead of SIMD code */ +//#define PFFFT_SIMD_DISABLE + +#ifndef PFFFT_SIMD_DISABLE +/* + * Altivec support macros + */ +#if (defined(__ppc__) || defined(__ppc64__) || defined(__powerpc__) || defined(__powerpc64__)) \ + && (defined(__VEC__) || defined(__ALTIVEC__)) +#include +using v4sf = vector float; +constexpr uint SimdSize{4}; +force_inline v4sf vzero() noexcept { return (vector float)vec_splat_u8(0); } +force_inline v4sf vmul(v4sf a, v4sf b) noexcept { return vec_madd(a, b, vzero()); } +force_inline v4sf vadd(v4sf a, v4sf b) noexcept { return vec_add(a, b); } +force_inline v4sf vmadd(v4sf a, v4sf b, v4sf c) noexcept { return vec_madd(a, b, c); } +force_inline v4sf vsub(v4sf a, v4sf b) noexcept { return vec_sub(a, b); } +force_inline v4sf ld_ps1(float a) noexcept { return vec_splats(a); } + +force_inline v4sf vset4(float a, float b, float c, float d) noexcept +{ + /* There a more efficient way to do this? */ + alignas(16) std::array vals{{a, b, c, d}}; + return vec_ld(0, vals.data()); +} +force_inline v4sf vinsert0(v4sf v, float a) noexcept { return vec_insert(a, v, 0); } +force_inline float vextract0(v4sf v) noexcept { return vec_extract(v, 0); } + +force_inline void interleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = vec_mergeh(in1, in2); + out2 = vec_mergel(in1, in2); +} +force_inline void uninterleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = vec_perm(in1, in2, (vector unsigned char){0,1,2,3,8,9,10,11,16,17,18,19,24,25,26,27}); + out2 = vec_perm(in1, in2, (vector unsigned char){4,5,6,7,12,13,14,15,20,21,22,23,28,29,30,31}); +} + +force_inline void vtranspose4(v4sf &x0, v4sf &x1, v4sf &x2, v4sf &x3) noexcept +{ + v4sf y0{vec_mergeh(x0, x2)}; + v4sf y1{vec_mergel(x0, x2)}; + v4sf y2{vec_mergeh(x1, x3)}; + v4sf y3{vec_mergel(x1, x3)}; + x0 = vec_mergeh(y0, y2); + x1 = vec_mergel(y0, y2); + x2 = vec_mergeh(y1, y3); + x3 = vec_mergel(y1, y3); +} + +force_inline v4sf vswaphl(v4sf a, v4sf b) noexcept +{ return vec_perm(a,b, (vector unsigned char){16,17,18,19,20,21,22,23,8,9,10,11,12,13,14,15}); } + +/* + * SSE1 support macros + */ +#elif defined(__x86_64__) || defined(__SSE__) || defined(_M_X64) || \ + (defined(_M_IX86_FP) && _M_IX86_FP >= 1) + +#include +using v4sf = __m128; +/* 4 floats by simd vector -- this is pretty much hardcoded in the preprocess/ + * finalize functions anyway so you will have to work if you want to enable AVX + * with its 256-bit vectors. + */ +constexpr uint SimdSize{4}; +force_inline v4sf vzero() noexcept { return _mm_setzero_ps(); } +force_inline v4sf vmul(v4sf a, v4sf b) noexcept { return _mm_mul_ps(a, b); } +force_inline v4sf vadd(v4sf a, v4sf b) noexcept { return _mm_add_ps(a, b); } +force_inline v4sf vmadd(v4sf a, v4sf b, v4sf c) noexcept { return _mm_add_ps(_mm_mul_ps(a,b), c); } +force_inline v4sf vsub(v4sf a, v4sf b) noexcept { return _mm_sub_ps(a, b); } +force_inline v4sf ld_ps1(float a) noexcept { return _mm_set1_ps(a); } + +force_inline v4sf vset4(float a, float b, float c, float d) noexcept +{ return _mm_setr_ps(a, b, c, d); } +force_inline v4sf vinsert0(const v4sf v, const float a) noexcept +{ return _mm_move_ss(v, _mm_set_ss(a)); } +force_inline float vextract0(v4sf v) noexcept +{ return _mm_cvtss_f32(v); } + +force_inline void interleave2(const v4sf in1, const v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = _mm_unpacklo_ps(in1, in2); + out2 = _mm_unpackhi_ps(in1, in2); +} +force_inline void uninterleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(2,0,2,0)); + out2 = _mm_shuffle_ps(in1, in2, _MM_SHUFFLE(3,1,3,1)); +} + +force_inline void vtranspose4(v4sf &x0, v4sf &x1, v4sf &x2, v4sf &x3) noexcept +{ _MM_TRANSPOSE4_PS(x0, x1, x2, x3); } + +force_inline v4sf vswaphl(v4sf a, v4sf b) noexcept +{ return _mm_shuffle_ps(b, a, _MM_SHUFFLE(3,2,1,0)); } + +/* + * ARM NEON support macros + */ +#elif defined(__ARM_NEON) || defined(__aarch64__) || defined(__arm64) || defined(_M_ARM64) + +#include +using v4sf = float32x4_t; +constexpr uint SimdSize{4}; +force_inline v4sf vzero() noexcept { return vdupq_n_f32(0.0f); } +force_inline v4sf vmul(v4sf a, v4sf b) noexcept { return vmulq_f32(a, b); } +force_inline v4sf vadd(v4sf a, v4sf b) noexcept { return vaddq_f32(a, b); } +force_inline v4sf vmadd(v4sf a, v4sf b, v4sf c) noexcept { return vmlaq_f32(c, a, b); } +force_inline v4sf vsub(v4sf a, v4sf b) noexcept { return vsubq_f32(a, b); } +force_inline v4sf ld_ps1(float a) noexcept { return vdupq_n_f32(a); } + +force_inline v4sf vset4(float a, float b, float c, float d) noexcept +{ + float32x4_t ret{vmovq_n_f32(a)}; + ret = vsetq_lane_f32(b, ret, 1); + ret = vsetq_lane_f32(c, ret, 2); + ret = vsetq_lane_f32(d, ret, 3); + return ret; +} +force_inline v4sf vinsert0(v4sf v, float a) noexcept +{ return vsetq_lane_f32(a, v, 0); } +force_inline float vextract0(v4sf v) noexcept +{ return vgetq_lane_f32(v, 0); } + +force_inline void interleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + float32x4x2_t tmp{vzipq_f32(in1, in2)}; + out1 = tmp.val[0]; + out2 = tmp.val[1]; +} +force_inline void uninterleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + float32x4x2_t tmp{vuzpq_f32(in1, in2)}; + out1 = tmp.val[0]; + out2 = tmp.val[1]; +} + +force_inline void vtranspose4(v4sf &x0, v4sf &x1, v4sf &x2, v4sf &x3) noexcept +{ + /* marginally faster version: + * asm("vtrn.32 %q0, %q1;\n" + * "vtrn.32 %q2, %q3\n + * "vswp %f0, %e2\n + * "vswp %f1, %e3" + * : "+w"(x0), "+w"(x1), "+w"(x2), "+w"(x3)::); + */ + float32x4x2_t t0_{vzipq_f32(x0, x2)}; + float32x4x2_t t1_{vzipq_f32(x1, x3)}; + float32x4x2_t u0_{vzipq_f32(t0_.val[0], t1_.val[0])}; + float32x4x2_t u1_{vzipq_f32(t0_.val[1], t1_.val[1])}; + x0 = u0_.val[0]; + x1 = u0_.val[1]; + x2 = u1_.val[0]; + x3 = u1_.val[1]; +} + +force_inline v4sf vswaphl(v4sf a, v4sf b) noexcept +{ return vcombine_f32(vget_low_f32(b), vget_high_f32(a)); } + +/* + * Generic GCC vector macros + */ +#elif defined(__GNUC__) + +using v4sf [[gnu::vector_size(16), gnu::aligned(16)]] = float; +constexpr uint SimdSize{4}; +force_inline constexpr v4sf vzero() noexcept { return v4sf{0.0f, 0.0f, 0.0f, 0.0f}; } +force_inline constexpr v4sf vmul(v4sf a, v4sf b) noexcept { return a * b; } +force_inline constexpr v4sf vadd(v4sf a, v4sf b) noexcept { return a + b; } +force_inline constexpr v4sf vmadd(v4sf a, v4sf b, v4sf c) noexcept { return a*b + c; } +force_inline constexpr v4sf vsub(v4sf a, v4sf b) noexcept { return a - b; } +force_inline constexpr v4sf ld_ps1(float a) noexcept { return v4sf{a, a, a, a}; } + +force_inline constexpr v4sf vset4(float a, float b, float c, float d) noexcept +{ return v4sf{a, b, c, d}; } +force_inline constexpr v4sf vinsert0(v4sf v, float a) noexcept +{ return v4sf{a, v[1], v[2], v[3]}; } +force_inline float vextract0(v4sf v) noexcept +{ return v[0]; } + +force_inline v4sf unpacklo(v4sf a, v4sf b) noexcept +{ return v4sf{a[0], b[0], a[1], b[1]}; } +force_inline v4sf unpackhi(v4sf a, v4sf b) noexcept +{ return v4sf{a[2], b[2], a[3], b[3]}; } + +force_inline void interleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = unpacklo(in1, in2); + out2 = unpackhi(in1, in2); +} +force_inline void uninterleave2(v4sf in1, v4sf in2, v4sf &out1, v4sf &out2) noexcept +{ + out1 = v4sf{in1[0], in1[2], in2[0], in2[2]}; + out2 = v4sf{in1[1], in1[3], in2[1], in2[3]}; +} + +force_inline void vtranspose4(v4sf &x0, v4sf &x1, v4sf &x2, v4sf &x3) noexcept +{ + v4sf tmp0{unpacklo(x0, x1)}; + v4sf tmp2{unpacklo(x2, x3)}; + v4sf tmp1{unpackhi(x0, x1)}; + v4sf tmp3{unpackhi(x2, x3)}; + x0 = v4sf{tmp0[0], tmp0[1], tmp2[0], tmp2[1]}; + x1 = v4sf{tmp0[2], tmp0[3], tmp2[2], tmp2[3]}; + x2 = v4sf{tmp1[0], tmp1[1], tmp3[0], tmp3[1]}; + x3 = v4sf{tmp1[2], tmp1[3], tmp3[2], tmp3[3]}; +} + +force_inline v4sf vswaphl(v4sf a, v4sf b) noexcept +{ return v4sf{b[0], b[1], a[2], a[3]}; } + +#else + +#warning "building with simd disabled !\n"; +#define PFFFT_SIMD_DISABLE // fallback to scalar code +#endif + +#endif /* PFFFT_SIMD_DISABLE */ + +// fallback mode for situations where SIMD is not available, use scalar mode instead +#ifdef PFFFT_SIMD_DISABLE +using v4sf = float; +constexpr uint SimdSize{1}; +force_inline constexpr v4sf vmul(v4sf a, v4sf b) noexcept { return a * b; } +force_inline constexpr v4sf vadd(v4sf a, v4sf b) noexcept { return a + b; } +force_inline constexpr v4sf vmadd(v4sf a, v4sf b, v4sf c) noexcept { return a*b + c; } +force_inline constexpr v4sf vsub(v4sf a, v4sf b) noexcept { return a - b; } +force_inline constexpr v4sf ld_ps1(float a) noexcept { return a; } + +#else + +[[maybe_unused, nodiscard]] inline +auto valigned(const float *ptr) noexcept -> bool +{ + static constexpr uintptr_t alignmask{SimdSize*sizeof(float) - 1}; + return (reinterpret_cast(ptr) & alignmask) == 0; +} +#endif + +// shortcuts for complex multiplications +force_inline void vcplxmul(v4sf &ar, v4sf &ai, v4sf br, v4sf bi) noexcept +{ + v4sf tmp{vmul(ar, bi)}; + ar = vsub(vmul(ar, br), vmul(ai, bi)); + ai = vmadd(ai, br, tmp); +} +force_inline void vcplxmulconj(v4sf &ar, v4sf &ai, v4sf br, v4sf bi) noexcept +{ + v4sf tmp{vmul(ar, bi)}; + ar = vmadd(ai, bi, vmul(ar, br)); + ai = vsub(vmul(ai, br), tmp); +} + +#if !defined(PFFFT_SIMD_DISABLE) + +inline void assertv4(const al::span v_f [[maybe_unused]], + const float f0 [[maybe_unused]], const float f1 [[maybe_unused]], + const float f2 [[maybe_unused]], const float f3 [[maybe_unused]]) +{ assert(v_f[0] == f0 && v_f[1] == f1 && v_f[2] == f2 && v_f[3] == f3); } + +template +constexpr auto make_float_array(std::integer_sequence) +{ return std::array{static_cast(N)...}; } + +/* detect bugs with the vector support macros */ +[[maybe_unused]] auto validate_pffft_simd() -> bool +{ + using float4 = std::array; + static constexpr auto f = make_float_array(std::make_index_sequence<16>{}); + + auto a0_v = vset4(f[ 0], f[ 1], f[ 2], f[ 3]); + auto a1_v = vset4(f[ 4], f[ 5], f[ 6], f[ 7]); + auto a2_v = vset4(f[ 8], f[ 9], f[10], f[11]); + auto a3_v = vset4(f[12], f[13], f[14], f[15]); + + auto t_v = vzero(); + auto t_f = al::bit_cast(t_v); + fmt::println("VZERO={}", t_f); + assertv4(t_f, 0, 0, 0, 0); + + t_v = vadd(a1_v, a2_v); + t_f = al::bit_cast(t_v); + fmt::println("VADD(4:7,8:11)={}", t_f); + assertv4(t_f, 12, 14, 16, 18); + + t_v = vmul(a1_v, a2_v); + t_f = al::bit_cast(t_v); + fmt::println("VMUL(4:7,8:11)={}", t_f); + assertv4(t_f, 32, 45, 60, 77); + + t_v = vmadd(a1_v, a2_v, a0_v); + t_f = al::bit_cast(t_v); + fmt::println("VMADD(4:7,8:11,0:3)={}", t_f); + assertv4(t_f, 32, 46, 62, 80); + + auto u_v = v4sf{}; + interleave2(a1_v, a2_v, t_v, u_v); + t_f = al::bit_cast(t_v); + auto u_f = al::bit_cast(u_v); + fmt::println("INTERLEAVE2(4:7,8:11)={} {}", t_f, u_f); + assertv4(t_f, 4, 8, 5, 9); + assertv4(u_f, 6, 10, 7, 11); + + uninterleave2(a1_v, a2_v, t_v, u_v); + t_f = al::bit_cast(t_v); + u_f = al::bit_cast(u_v); + fmt::println("UNINTERLEAVE2(4:7,8:11)={} {}", t_f, u_f); + assertv4(t_f, 4, 6, 8, 10); + assertv4(u_f, 5, 7, 9, 11); + + t_v = ld_ps1(f[15]); + t_f = al::bit_cast(t_v); + fmt::println("LD_PS1(15)={}", t_f); + assertv4(t_f, 15, 15, 15, 15); + + t_v = vswaphl(a1_v, a2_v); + t_f = al::bit_cast(t_v); + fmt::println("VSWAPHL(4:7,8:11)={}", t_f); + assertv4(t_f, 8, 9, 6, 7); + + vtranspose4(a0_v, a1_v, a2_v, a3_v); + auto a0_f = al::bit_cast(a0_v); + auto a1_f = al::bit_cast(a1_v); + auto a2_f = al::bit_cast(a2_v); + auto a3_f = al::bit_cast(a3_v); + fmt::println("VTRANSPOSE4(0:3,4:7,8:11,12:15)={} {} {} {}", a0_f, a1_f, a2_f, a3_f); + assertv4(a0_f, 0, 4, 8, 12); + assertv4(a1_f, 1, 5, 9, 13); + assertv4(a2_f, 2, 6, 10, 14); + assertv4(a3_f, 3, 7, 11, 15); + + return true; +} +#endif //!PFFFT_SIMD_DISABLE + +/* SSE and co like 16-bytes aligned pointers */ +/* with a 64-byte alignment, we are even aligned on L2 cache lines... */ +constexpr auto V4sfAlignment = size_t(64); +constexpr auto V4sfAlignVal = std::align_val_t(V4sfAlignment); + +/* NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) + * FIXME: Converting this from raw pointers to spans or something will probably + * need significant work to maintain performance, given non-sequential range- + * checked accesses and lack of 'restrict' to indicate non-aliased memory. At + * least, some tests should be done to check the impact of using range-checked + * spans here before blindly switching. + */ +/* + passf2 and passb2 has been merged here, fsign = -1 for passf2, +1 for passb2 +*/ +NOINLINE void passf2_ps(const size_t ido, const size_t l1, const v4sf *cc, v4sf *RESTRICT ch, + const float *const wa1, const float fsign) +{ + const size_t l1ido{l1*ido}; + if(ido <= 2) + { + for(size_t k{0};k < l1ido;k += ido, ch += ido, cc += 2*ido) + { + ch[0] = vadd(cc[0], cc[ido+0]); + ch[l1ido] = vsub(cc[0], cc[ido+0]); + ch[1] = vadd(cc[1], cc[ido+1]); + ch[l1ido + 1] = vsub(cc[1], cc[ido+1]); + } + } + else + { + for(size_t k{0};k < l1ido;k += ido, ch += ido, cc += 2*ido) + { + for(size_t i{0};i < ido-1;i += 2) + { + v4sf tr2{vsub(cc[i+0], cc[i+ido+0])}; + v4sf ti2{vsub(cc[i+1], cc[i+ido+1])}; + v4sf wr{ld_ps1(wa1[i])}, wi{ld_ps1(wa1[i+1]*fsign)}; + ch[i] = vadd(cc[i+0], cc[i+ido+0]); + ch[i+1] = vadd(cc[i+1], cc[i+ido+1]); + vcplxmul(tr2, ti2, wr, wi); + ch[i+l1ido] = tr2; + ch[i+l1ido+1] = ti2; + } + } + } +} + +/* + passf3 and passb3 has been merged here, fsign = -1 for passf3, +1 for passb3 +*/ +NOINLINE void passf3_ps(const size_t ido, const size_t l1, const v4sf *cc, v4sf *RESTRICT ch, + const float *const wa1, const float fsign) +{ + assert(ido > 2); + + const v4sf taur{ld_ps1(-0.5f)}; + const v4sf taui{ld_ps1(0.866025403784439f*fsign)}; + const size_t l1ido{l1*ido}; + const auto wa2 = wa1 + ido; + for(size_t k{0};k < l1ido;k += ido, cc += 3*ido, ch +=ido) + { + for(size_t i{0};i < ido-1;i += 2) + { + v4sf tr2{vadd(cc[i+ido], cc[i+2*ido])}; + v4sf cr2{vmadd(taur, tr2, cc[i])}; + ch[i] = vadd(tr2, cc[i]); + v4sf ti2{vadd(cc[i+ido+1], cc[i+2*ido+1])}; + v4sf ci2{vmadd(taur, ti2, cc[i+1])}; + ch[i+1] = vadd(cc[i+1], ti2); + v4sf cr3{vmul(taui, vsub(cc[i+ido], cc[i+2*ido]))}; + v4sf ci3{vmul(taui, vsub(cc[i+ido+1], cc[i+2*ido+1]))}; + v4sf dr2{vsub(cr2, ci3)}; + v4sf dr3{vadd(cr2, ci3)}; + v4sf di2{vadd(ci2, cr3)}; + v4sf di3{vsub(ci2, cr3)}; + float wr1{wa1[i]}, wi1{fsign*wa1[i+1]}, wr2{wa2[i]}, wi2{fsign*wa2[i+1]}; + vcplxmul(dr2, di2, ld_ps1(wr1), ld_ps1(wi1)); + ch[i+l1ido] = dr2; + ch[i+l1ido + 1] = di2; + vcplxmul(dr3, di3, ld_ps1(wr2), ld_ps1(wi2)); + ch[i+2*l1ido] = dr3; + ch[i+2*l1ido+1] = di3; + } + } +} /* passf3 */ + +NOINLINE void passf4_ps(const size_t ido, const size_t l1, const v4sf *cc, v4sf *RESTRICT ch, + const float *const wa1, const float fsign) +{ + /* fsign == -1 for forward transform and +1 for backward transform */ + const v4sf vsign{ld_ps1(fsign)}; + const size_t l1ido{l1*ido}; + if(ido == 2) + { + for(size_t k{0};k < l1ido;k += ido, ch += ido, cc += 4*ido) + { + v4sf tr1{vsub(cc[0], cc[2*ido + 0])}; + v4sf tr2{vadd(cc[0], cc[2*ido + 0])}; + v4sf ti1{vsub(cc[1], cc[2*ido + 1])}; + v4sf ti2{vadd(cc[1], cc[2*ido + 1])}; + v4sf ti4{vmul(vsub(cc[1*ido + 0], cc[3*ido + 0]), vsign)}; + v4sf tr4{vmul(vsub(cc[3*ido + 1], cc[1*ido + 1]), vsign)}; + v4sf tr3{vadd(cc[ido + 0], cc[3*ido + 0])}; + v4sf ti3{vadd(cc[ido + 1], cc[3*ido + 1])}; + + ch[0*l1ido + 0] = vadd(tr2, tr3); + ch[0*l1ido + 1] = vadd(ti2, ti3); + ch[1*l1ido + 0] = vadd(tr1, tr4); + ch[1*l1ido + 1] = vadd(ti1, ti4); + ch[2*l1ido + 0] = vsub(tr2, tr3); + ch[2*l1ido + 1] = vsub(ti2, ti3); + ch[3*l1ido + 0] = vsub(tr1, tr4); + ch[3*l1ido + 1] = vsub(ti1, ti4); + } + } + else + { + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + for(size_t k{0};k < l1ido;k += ido, ch+=ido, cc += 4*ido) + { + for(size_t i{0};i < ido-1;i+=2) + { + v4sf tr1{vsub(cc[i + 0], cc[i + 2*ido + 0])}; + v4sf tr2{vadd(cc[i + 0], cc[i + 2*ido + 0])}; + v4sf ti1{vsub(cc[i + 1], cc[i + 2*ido + 1])}; + v4sf ti2{vadd(cc[i + 1], cc[i + 2*ido + 1])}; + v4sf tr4{vmul(vsub(cc[i + 3*ido + 1], cc[i + 1*ido + 1]), vsign)}; + v4sf ti4{vmul(vsub(cc[i + 1*ido + 0], cc[i + 3*ido + 0]), vsign)}; + v4sf tr3{vadd(cc[i + ido + 0], cc[i + 3*ido + 0])}; + v4sf ti3{vadd(cc[i + ido + 1], cc[i + 3*ido + 1])}; + + ch[i] = vadd(tr2, tr3); + v4sf cr3{vsub(tr2, tr3)}; + ch[i + 1] = vadd(ti2, ti3); + v4sf ci3{vsub(ti2, ti3)}; + + v4sf cr2{vadd(tr1, tr4)}; + v4sf cr4{vsub(tr1, tr4)}; + v4sf ci2{vadd(ti1, ti4)}; + v4sf ci4{vsub(ti1, ti4)}; + float wr1{wa1[i]}, wi1{fsign*wa1[i+1]}; + vcplxmul(cr2, ci2, ld_ps1(wr1), ld_ps1(wi1)); + float wr2{wa2[i]}, wi2{fsign*wa2[i+1]}; + ch[i + l1ido] = cr2; + ch[i + l1ido + 1] = ci2; + + vcplxmul(cr3, ci3, ld_ps1(wr2), ld_ps1(wi2)); + float wr3{wa3[i]}, wi3{fsign*wa3[i+1]}; + ch[i + 2*l1ido] = cr3; + ch[i + 2*l1ido + 1] = ci3; + + vcplxmul(cr4, ci4, ld_ps1(wr3), ld_ps1(wi3)); + ch[i + 3*l1ido] = cr4; + ch[i + 3*l1ido + 1] = ci4; + } + } + } +} /* passf4 */ + +/* + * passf5 and passb5 has been merged here, fsign = -1 for passf5, +1 for passb5 + */ +NOINLINE void passf5_ps(const size_t ido, const size_t l1, const v4sf *cc, v4sf *RESTRICT ch, + const float *const wa1, const float fsign) +{ + const v4sf tr11{ld_ps1(0.309016994374947f)}; + const v4sf tr12{ld_ps1(-0.809016994374947f)}; + const v4sf ti11{ld_ps1(0.951056516295154f*fsign)}; + const v4sf ti12{ld_ps1(0.587785252292473f*fsign)}; + + auto cc_ref = [&cc,ido](size_t a_1, size_t a_2) noexcept -> auto& + { return cc[(a_2-1)*ido + a_1 + 1]; }; + auto ch_ref = [&ch,ido,l1](size_t a_1, size_t a_3) noexcept -> auto& + { return ch[(a_3-1)*l1*ido + a_1 + 1]; }; + + assert(ido > 2); + + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + const auto wa4 = wa3 + ido; + for(size_t k{0};k < l1;++k, cc += 5*ido, ch += ido) + { + for(size_t i{0};i < ido-1;i += 2) + { + v4sf ti5{vsub(cc_ref(i , 2), cc_ref(i , 5))}; + v4sf ti2{vadd(cc_ref(i , 2), cc_ref(i , 5))}; + v4sf ti4{vsub(cc_ref(i , 3), cc_ref(i , 4))}; + v4sf ti3{vadd(cc_ref(i , 3), cc_ref(i , 4))}; + v4sf tr5{vsub(cc_ref(i-1, 2), cc_ref(i-1, 5))}; + v4sf tr2{vadd(cc_ref(i-1, 2), cc_ref(i-1, 5))}; + v4sf tr4{vsub(cc_ref(i-1, 3), cc_ref(i-1, 4))}; + v4sf tr3{vadd(cc_ref(i-1, 3), cc_ref(i-1, 4))}; + ch_ref(i-1, 1) = vadd(cc_ref(i-1, 1), vadd(tr2, tr3)); + ch_ref(i , 1) = vadd(cc_ref(i , 1), vadd(ti2, ti3)); + v4sf cr2{vadd(cc_ref(i-1, 1), vmadd(tr11, tr2, vmul(tr12, tr3)))}; + v4sf ci2{vadd(cc_ref(i , 1), vmadd(tr11, ti2, vmul(tr12, ti3)))}; + v4sf cr3{vadd(cc_ref(i-1, 1), vmadd(tr12, tr2, vmul(tr11, tr3)))}; + v4sf ci3{vadd(cc_ref(i , 1), vmadd(tr12, ti2, vmul(tr11, ti3)))}; + v4sf cr5{vmadd(ti11, tr5, vmul(ti12, tr4))}; + v4sf ci5{vmadd(ti11, ti5, vmul(ti12, ti4))}; + v4sf cr4{vsub(vmul(ti12, tr5), vmul(ti11, tr4))}; + v4sf ci4{vsub(vmul(ti12, ti5), vmul(ti11, ti4))}; + v4sf dr3{vsub(cr3, ci4)}; + v4sf dr4{vadd(cr3, ci4)}; + v4sf di3{vadd(ci3, cr4)}; + v4sf di4{vsub(ci3, cr4)}; + v4sf dr5{vadd(cr2, ci5)}; + v4sf dr2{vsub(cr2, ci5)}; + v4sf di5{vsub(ci2, cr5)}; + v4sf di2{vadd(ci2, cr5)}; + float wr1{wa1[i]}, wi1{fsign*wa1[i+1]}, wr2{wa2[i]}, wi2{fsign*wa2[i+1]}; + float wr3{wa3[i]}, wi3{fsign*wa3[i+1]}, wr4{wa4[i]}, wi4{fsign*wa4[i+1]}; + vcplxmul(dr2, di2, ld_ps1(wr1), ld_ps1(wi1)); + ch_ref(i - 1, 2) = dr2; + ch_ref(i, 2) = di2; + vcplxmul(dr3, di3, ld_ps1(wr2), ld_ps1(wi2)); + ch_ref(i - 1, 3) = dr3; + ch_ref(i, 3) = di3; + vcplxmul(dr4, di4, ld_ps1(wr3), ld_ps1(wi3)); + ch_ref(i - 1, 4) = dr4; + ch_ref(i, 4) = di4; + vcplxmul(dr5, di5, ld_ps1(wr4), ld_ps1(wi4)); + ch_ref(i - 1, 5) = dr5; + ch_ref(i, 5) = di5; + } + } +} + +NOINLINE void radf2_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, + v4sf *RESTRICT ch, const float *const wa1) +{ + const size_t l1ido{l1*ido}; + for(size_t k{0};k < l1ido;k += ido) + { + v4sf a{cc[k]}, b{cc[k + l1ido]}; + ch[2*k] = vadd(a, b); + ch[2*(k+ido)-1] = vsub(a, b); + } + if(ido < 2) + return; + if(ido != 2) + { + for(size_t k{0};k < l1ido;k += ido) + { + for(size_t i{2};i < ido;i += 2) + { + v4sf tr2{cc[i - 1 + k + l1ido]}, ti2{cc[i + k + l1ido]}; + v4sf br{cc[i - 1 + k]}, bi{cc[i + k]}; + vcplxmulconj(tr2, ti2, ld_ps1(wa1[i - 2]), ld_ps1(wa1[i - 1])); + ch[i + 2*k] = vadd(bi, ti2); + ch[2*(k+ido) - i] = vsub(ti2, bi); + ch[i - 1 + 2*k] = vadd(br, tr2); + ch[2*(k+ido) - i -1] = vsub(br, tr2); + } + } + if((ido&1) == 1) + return; + } + const v4sf minus_one{ld_ps1(-1.0f)}; + for(size_t k{0};k < l1ido;k += ido) + { + ch[2*k + ido] = vmul(minus_one, cc[ido-1 + k + l1ido]); + ch[2*k + ido-1] = cc[k + ido-1]; + } +} /* radf2 */ + + +NOINLINE void radb2_ps(const size_t ido, const size_t l1, const v4sf *cc, v4sf *RESTRICT ch, + const float *const wa1) +{ + const size_t l1ido{l1*ido}; + for(size_t k{0};k < l1ido;k += ido) + { + v4sf a{cc[2*k]}; + v4sf b{cc[2*(k+ido) - 1]}; + ch[k] = vadd(a, b); + ch[k + l1ido] = vsub(a, b); + } + if(ido < 2) + return; + if(ido != 2) + { + for(size_t k{0};k < l1ido;k += ido) + { + for(size_t i{2};i < ido;i += 2) + { + v4sf a{cc[i-1 + 2*k]}; + v4sf b{cc[2*(k + ido) - i - 1]}; + v4sf c{cc[i+0 + 2*k]}; + v4sf d{cc[2*(k + ido) - i + 0]}; + ch[i-1 + k] = vadd(a, b); + v4sf tr2{vsub(a, b)}; + ch[i+0 + k] = vsub(c, d); + v4sf ti2{vadd(c, d)}; + vcplxmul(tr2, ti2, ld_ps1(wa1[i - 2]), ld_ps1(wa1[i - 1])); + ch[i-1 + k + l1ido] = tr2; + ch[i+0 + k + l1ido] = ti2; + } + } + if((ido&1) == 1) + return; + } + const v4sf minus_two{ld_ps1(-2.0f)}; + for(size_t k{0};k < l1ido;k += ido) + { + v4sf a{cc[2*k + ido-1]}; + v4sf b{cc[2*k + ido]}; + ch[k + ido-1] = vadd(a,a); + ch[k + ido-1 + l1ido] = vmul(minus_two, b); + } +} /* radb2 */ + +void radf3_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, v4sf *RESTRICT ch, + const float *const wa1) +{ + const v4sf taur{ld_ps1(-0.5f)}; + const v4sf taui{ld_ps1(0.866025403784439f)}; + for(size_t k{0};k < l1;++k) + { + v4sf cr2{vadd(cc[(k + l1)*ido], cc[(k + 2*l1)*ido])}; + ch[ (3*k )*ido] = vadd(cc[k*ido], cr2); + ch[ (3*k + 2)*ido] = vmul(taui, vsub(cc[(k + l1*2)*ido], cc[(k + l1)*ido])); + ch[ido-1 + (3*k + 1)*ido] = vmadd(taur, cr2, cc[k*ido]); + } + if(ido == 1) + return; + + const auto wa2 = wa1 + ido; + for(size_t k{0};k < l1;++k) + { + for(size_t i{2};i < ido;i += 2) + { + const size_t ic{ido - i}; + v4sf wr1{ld_ps1(wa1[i - 2])}; + v4sf wi1{ld_ps1(wa1[i - 1])}; + v4sf dr2{cc[i - 1 + (k + l1)*ido]}; + v4sf di2{cc[i + (k + l1)*ido]}; + vcplxmulconj(dr2, di2, wr1, wi1); + + v4sf wr2{ld_ps1(wa2[i - 2])}; + v4sf wi2{ld_ps1(wa2[i - 1])}; + v4sf dr3{cc[i - 1 + (k + l1*2)*ido]}; + v4sf di3{cc[i + (k + l1*2)*ido]}; + vcplxmulconj(dr3, di3, wr2, wi2); + + v4sf cr2{vadd(dr2, dr3)}; + v4sf ci2{vadd(di2, di3)}; + ch[i - 1 + 3*k*ido] = vadd(cc[i - 1 + k*ido], cr2); + ch[i + 3*k*ido] = vadd(cc[i + k*ido], ci2); + v4sf tr2{vmadd(taur, cr2, cc[i - 1 + k*ido])}; + v4sf ti2{vmadd(taur, ci2, cc[i + k*ido])}; + v4sf tr3{vmul(taui, vsub(di2, di3))}; + v4sf ti3{vmul(taui, vsub(dr3, dr2))}; + ch[i - 1 + (3*k + 2)*ido] = vadd(tr2, tr3); + ch[ic - 1 + (3*k + 1)*ido] = vsub(tr2, tr3); + ch[i + (3*k + 2)*ido] = vadd(ti2, ti3); + ch[ic + (3*k + 1)*ido] = vsub(ti3, ti2); + } + } +} /* radf3 */ + + +void radb3_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, v4sf *RESTRICT ch, + const float *const wa1) +{ + static constexpr float taur{-0.5f}; + static constexpr float taui{0.866025403784439f}; + static constexpr float taui_2{taui*2.0f}; + + const v4sf vtaur{ld_ps1(taur)}; + const v4sf vtaui_2{ld_ps1(taui_2)}; + for(size_t k{0};k < l1;++k) + { + v4sf tr2 = cc[ido-1 + (3*k + 1)*ido]; + tr2 = vadd(tr2,tr2); + v4sf cr2 = vmadd(vtaur, tr2, cc[3*k*ido]); + ch[k*ido] = vadd(cc[3*k*ido], tr2); + v4sf ci3 = vmul(vtaui_2, cc[(3*k + 2)*ido]); + ch[(k + l1)*ido] = vsub(cr2, ci3); + ch[(k + 2*l1)*ido] = vadd(cr2, ci3); + } + if(ido == 1) + return; + + const auto wa2 = wa1 + ido; + const v4sf vtaui{ld_ps1(taui)}; + for(size_t k{0};k < l1;++k) + { + for(size_t i{2};i < ido;i += 2) + { + const size_t ic{ido - i}; + v4sf tr2{vadd(cc[i - 1 + (3*k + 2)*ido], cc[ic - 1 + (3*k + 1)*ido])}; + v4sf cr2{vmadd(vtaur, tr2, cc[i - 1 + 3*k*ido])}; + ch[i - 1 + k*ido] = vadd(cc[i - 1 + 3*k*ido], tr2); + v4sf ti2{vsub(cc[i + (3*k + 2)*ido], cc[ic + (3*k + 1)*ido])}; + v4sf ci2{vmadd(vtaur, ti2, cc[i + 3*k*ido])}; + ch[i + k*ido] = vadd(cc[i + 3*k*ido], ti2); + v4sf cr3{vmul(vtaui, vsub(cc[i - 1 + (3*k + 2)*ido], cc[ic - 1 + (3*k + 1)*ido]))}; + v4sf ci3{vmul(vtaui, vadd(cc[i + (3*k + 2)*ido], cc[ic + (3*k + 1)*ido]))}; + v4sf dr2{vsub(cr2, ci3)}; + v4sf dr3{vadd(cr2, ci3)}; + v4sf di2{vadd(ci2, cr3)}; + v4sf di3{vsub(ci2, cr3)}; + vcplxmul(dr2, di2, ld_ps1(wa1[i-2]), ld_ps1(wa1[i-1])); + ch[i - 1 + (k + l1)*ido] = dr2; + ch[i + (k + l1)*ido] = di2; + vcplxmul(dr3, di3, ld_ps1(wa2[i-2]), ld_ps1(wa2[i-1])); + ch[i - 1 + (k + 2*l1)*ido] = dr3; + ch[i + (k + 2*l1)*ido] = di3; + } + } +} /* radb3 */ + +NOINLINE void radf4_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, + v4sf *RESTRICT ch, const float *const wa1) +{ + const size_t l1ido{l1*ido}; + { + const v4sf *RESTRICT cc_{cc}, *RESTRICT cc_end{cc + l1ido}; + v4sf *RESTRICT ch_{ch}; + while(cc != cc_end) + { + // this loop represents between 25% and 40% of total radf4_ps cost ! + v4sf a0{cc[0]}, a1{cc[l1ido]}; + v4sf a2{cc[2*l1ido]}, a3{cc[3*l1ido]}; + v4sf tr1{vadd(a1, a3)}; + v4sf tr2{vadd(a0, a2)}; + ch[2*ido-1] = vsub(a0, a2); + ch[2*ido ] = vsub(a3, a1); + ch[0 ] = vadd(tr1, tr2); + ch[4*ido-1] = vsub(tr2, tr1); + cc += ido; ch += 4*ido; + } + cc = cc_; + ch = ch_; + } + if(ido < 2) + return; + if(ido != 2) + { + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + + for(size_t k{0};k < l1ido;k += ido) + { + const v4sf *RESTRICT pc{cc + 1 + k}; + for(size_t i{2};i < ido;i += 2, pc += 2) + { + const size_t ic{ido - i}; + + v4sf cr2{pc[1*l1ido+0]}; + v4sf ci2{pc[1*l1ido+1]}; + v4sf wr{ld_ps1(wa1[i - 2])}; + v4sf wi{ld_ps1(wa1[i - 1])}; + vcplxmulconj(cr2,ci2,wr,wi); + + v4sf cr3{pc[2*l1ido+0]}; + v4sf ci3{pc[2*l1ido+1]}; + wr = ld_ps1(wa2[i-2]); + wi = ld_ps1(wa2[i-1]); + vcplxmulconj(cr3, ci3, wr, wi); + + v4sf cr4{pc[3*l1ido]}; + v4sf ci4{pc[3*l1ido+1]}; + wr = ld_ps1(wa3[i-2]); + wi = ld_ps1(wa3[i-1]); + vcplxmulconj(cr4, ci4, wr, wi); + + /* at this point, on SSE, five of "cr2 cr3 cr4 ci2 ci3 ci4" should be loaded in registers */ + + v4sf tr1{vadd(cr2,cr4)}; + v4sf tr4{vsub(cr4,cr2)}; + v4sf tr2{vadd(pc[0],cr3)}; + v4sf tr3{vsub(pc[0],cr3)}; + ch[i - 1 + 4*k ] = vadd(tr2,tr1); + ch[ic - 1 + 4*k + 3*ido] = vsub(tr2,tr1); // at this point tr1 and tr2 can be disposed + v4sf ti1{vadd(ci2,ci4)}; + v4sf ti4{vsub(ci2,ci4)}; + ch[i - 1 + 4*k + 2*ido] = vadd(tr3,ti4); + ch[ic - 1 + 4*k + 1*ido] = vsub(tr3,ti4); // dispose tr3, ti4 + v4sf ti2{vadd(pc[1],ci3)}; + v4sf ti3{vsub(pc[1],ci3)}; + ch[i + 4*k ] = vadd(ti1, ti2); + ch[ic + 4*k + 3*ido] = vsub(ti1, ti2); + ch[i + 4*k + 2*ido] = vadd(tr4, ti3); + ch[ic + 4*k + 1*ido] = vsub(tr4, ti3); + } + } + if((ido&1) == 1) + return; + } + const v4sf minus_hsqt2{ld_ps1(al::numbers::sqrt2_v * -0.5f)}; + for(size_t k{0};k < l1ido;k += ido) + { + v4sf a{cc[ido-1 + k + l1ido]}, b{cc[ido-1 + k + 3*l1ido]}; + v4sf c{cc[ido-1 + k]}, d{cc[ido-1 + k + 2*l1ido]}; + v4sf ti1{vmul(minus_hsqt2, vadd(b, a))}; + v4sf tr1{vmul(minus_hsqt2, vsub(b, a))}; + ch[ido-1 + 4*k ] = vadd(c, tr1); + ch[ido-1 + 4*k + 2*ido] = vsub(c, tr1); + ch[ 4*k + 1*ido] = vsub(ti1, d); + ch[ 4*k + 3*ido] = vadd(ti1, d); + } +} /* radf4 */ + + +NOINLINE void radb4_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, + v4sf *RESTRICT ch, const float *const wa1) +{ + const v4sf two{ld_ps1(2.0f)}; + const size_t l1ido{l1*ido}; + { + const v4sf *RESTRICT cc_{cc}, *RESTRICT ch_end{ch + l1ido}; + v4sf *ch_{ch}; + while(ch != ch_end) + { + v4sf a{cc[0]}, b{cc[4*ido-1]}; + v4sf c{cc[2*ido]}, d{cc[2*ido-1]}; + v4sf tr3{vmul(two,d)}; + v4sf tr2{vadd(a,b)}; + v4sf tr1{vsub(a,b)}; + v4sf tr4{vmul(two,c)}; + ch[0*l1ido] = vadd(tr2, tr3); + ch[2*l1ido] = vsub(tr2, tr3); + ch[1*l1ido] = vsub(tr1, tr4); + ch[3*l1ido] = vadd(tr1, tr4); + + cc += 4*ido; ch += ido; + } + cc = cc_; ch = ch_; + } + if(ido < 2) + return; + if(ido != 2) + { + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + + for(size_t k{0};k < l1ido;k += ido) + { + const v4sf *RESTRICT pc{cc - 1 + 4*k}; + v4sf *RESTRICT ph{ch + k + 1}; + for(size_t i{2};i < ido;i += 2) + { + v4sf tr1{vsub(pc[ i], pc[4*ido - i])}; + v4sf tr2{vadd(pc[ i], pc[4*ido - i])}; + v4sf ti4{vsub(pc[2*ido + i], pc[2*ido - i])}; + v4sf tr3{vadd(pc[2*ido + i], pc[2*ido - i])}; + ph[0] = vadd(tr2, tr3); + v4sf cr3{vsub(tr2, tr3)}; + + v4sf ti3{vsub(pc[2*ido + i + 1], pc[2*ido - i + 1])}; + v4sf tr4{vadd(pc[2*ido + i + 1], pc[2*ido - i + 1])}; + v4sf cr2{vsub(tr1, tr4)}; + v4sf cr4{vadd(tr1, tr4)}; + + v4sf ti1{vadd(pc[i + 1], pc[4*ido - i + 1])}; + v4sf ti2{vsub(pc[i + 1], pc[4*ido - i + 1])}; + + ph[1] = vadd(ti2, ti3); ph += l1ido; + v4sf ci3{vsub(ti2, ti3)}; + v4sf ci2{vadd(ti1, ti4)}; + v4sf ci4{vsub(ti1, ti4)}; + vcplxmul(cr2, ci2, ld_ps1(wa1[i-2]), ld_ps1(wa1[i-1])); + ph[0] = cr2; + ph[1] = ci2; ph += l1ido; + vcplxmul(cr3, ci3, ld_ps1(wa2[i-2]), ld_ps1(wa2[i-1])); + ph[0] = cr3; + ph[1] = ci3; ph += l1ido; + vcplxmul(cr4, ci4, ld_ps1(wa3[i-2]), ld_ps1(wa3[i-1])); + ph[0] = cr4; + ph[1] = ci4; ph = ph - 3*l1ido + 2; + } + } + if((ido&1) == 1) + return; + } + const v4sf minus_sqrt2{ld_ps1(-1.414213562373095f)}; + for(size_t k{0};k < l1ido;k += ido) + { + const size_t i0{4*k + ido}; + v4sf c{cc[i0-1]}, d{cc[i0 + 2*ido-1]}; + v4sf a{cc[i0+0]}, b{cc[i0 + 2*ido+0]}; + v4sf tr1{vsub(c,d)}; + v4sf tr2{vadd(c,d)}; + v4sf ti1{vadd(b,a)}; + v4sf ti2{vsub(b,a)}; + ch[ido-1 + k + 0*l1ido] = vadd(tr2,tr2); + ch[ido-1 + k + 1*l1ido] = vmul(minus_sqrt2, vsub(ti1, tr1)); + ch[ido-1 + k + 2*l1ido] = vadd(ti2, ti2); + ch[ido-1 + k + 3*l1ido] = vmul(minus_sqrt2, vadd(ti1, tr1)); + } +} /* radb4 */ + +void radf5_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, v4sf *RESTRICT ch, + const float *const wa1) +{ + const v4sf tr11{ld_ps1(0.309016994374947f)}; + const v4sf ti11{ld_ps1(0.951056516295154f)}; + const v4sf tr12{ld_ps1(-0.809016994374947f)}; + const v4sf ti12{ld_ps1(0.587785252292473f)}; + + auto cc_ref = [&cc,l1,ido](size_t a_1, size_t a_2, size_t a_3) noexcept -> auto& + { return cc[(a_3*l1 + a_2)*ido + a_1]; }; + auto ch_ref = [&ch,ido](size_t a_1, size_t a_2, size_t a_3) noexcept -> auto& + { return ch[(a_3*5 + a_2)*ido + a_1]; }; + + /* Parameter adjustments */ + ch -= 1 + ido * 6; + cc -= 1 + ido * (1 + l1); + + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + const auto wa4 = wa3 + ido; + + /* Function Body */ + for(size_t k{1};k <= l1;++k) + { + v4sf cr2{vadd(cc_ref(1, k, 5), cc_ref(1, k, 2))}; + v4sf ci5{vsub(cc_ref(1, k, 5), cc_ref(1, k, 2))}; + v4sf cr3{vadd(cc_ref(1, k, 4), cc_ref(1, k, 3))}; + v4sf ci4{vsub(cc_ref(1, k, 4), cc_ref(1, k, 3))}; + ch_ref(1, 1, k) = vadd(cc_ref(1, k, 1), vadd(cr2, cr3)); + ch_ref(ido, 2, k) = vadd(cc_ref(1, k, 1), vmadd(tr11, cr2, vmul(tr12, cr3))); + ch_ref(1, 3, k) = vmadd(ti11, ci5, vmul(ti12, ci4)); + ch_ref(ido, 4, k) = vadd(cc_ref(1, k, 1), vmadd(tr12, cr2, vmul(tr11, cr3))); + ch_ref(1, 5, k) = vsub(vmul(ti12, ci5), vmul(ti11, ci4)); + //fmt::println("pffft: radf5, k={} ch_ref={:f}, ci4={:f}", k, ch_ref(1, 5, k), ci4); + } + if(ido == 1) + return; + + const size_t idp2{ido + 2}; + for(size_t k{1};k <= l1;++k) + { + for(size_t i{3};i <= ido;i += 2) + { + const size_t ic{idp2 - i}; + v4sf dr2{ld_ps1(wa1[i-3])}; + v4sf di2{ld_ps1(wa1[i-2])}; + v4sf dr3{ld_ps1(wa2[i-3])}; + v4sf di3{ld_ps1(wa2[i-2])}; + v4sf dr4{ld_ps1(wa3[i-3])}; + v4sf di4{ld_ps1(wa3[i-2])}; + v4sf dr5{ld_ps1(wa4[i-3])}; + v4sf di5{ld_ps1(wa4[i-2])}; + vcplxmulconj(dr2, di2, cc_ref(i-1, k, 2), cc_ref(i, k, 2)); + vcplxmulconj(dr3, di3, cc_ref(i-1, k, 3), cc_ref(i, k, 3)); + vcplxmulconj(dr4, di4, cc_ref(i-1, k, 4), cc_ref(i, k, 4)); + vcplxmulconj(dr5, di5, cc_ref(i-1, k, 5), cc_ref(i, k, 5)); + v4sf cr2{vadd(dr2, dr5)}; + v4sf ci5{vsub(dr5, dr2)}; + v4sf cr5{vsub(di2, di5)}; + v4sf ci2{vadd(di2, di5)}; + v4sf cr3{vadd(dr3, dr4)}; + v4sf ci4{vsub(dr4, dr3)}; + v4sf cr4{vsub(di3, di4)}; + v4sf ci3{vadd(di3, di4)}; + ch_ref(i - 1, 1, k) = vadd(cc_ref(i - 1, k, 1), vadd(cr2, cr3)); + ch_ref(i, 1, k) = vsub(cc_ref(i, k, 1), vadd(ci2, ci3)); + v4sf tr2{vadd(cc_ref(i - 1, k, 1), vmadd(tr11, cr2, vmul(tr12, cr3)))}; + v4sf ti2{vsub(cc_ref(i, k, 1), vmadd(tr11, ci2, vmul(tr12, ci3)))}; + v4sf tr3{vadd(cc_ref(i - 1, k, 1), vmadd(tr12, cr2, vmul(tr11, cr3)))}; + v4sf ti3{vsub(cc_ref(i, k, 1), vmadd(tr12, ci2, vmul(tr11, ci3)))}; + v4sf tr5{vmadd(ti11, cr5, vmul(ti12, cr4))}; + v4sf ti5{vmadd(ti11, ci5, vmul(ti12, ci4))}; + v4sf tr4{vsub(vmul(ti12, cr5), vmul(ti11, cr4))}; + v4sf ti4{vsub(vmul(ti12, ci5), vmul(ti11, ci4))}; + ch_ref(i - 1, 3, k) = vsub(tr2, tr5); + ch_ref(ic - 1, 2, k) = vadd(tr2, tr5); + ch_ref(i , 3, k) = vadd(ti5, ti2); + ch_ref(ic , 2, k) = vsub(ti5, ti2); + ch_ref(i - 1, 5, k) = vsub(tr3, tr4); + ch_ref(ic - 1, 4, k) = vadd(tr3, tr4); + ch_ref(i , 5, k) = vadd(ti4, ti3); + ch_ref(ic , 4, k) = vsub(ti4, ti3); + } + } +} /* radf5 */ + +void radb5_ps(const size_t ido, const size_t l1, const v4sf *RESTRICT cc, v4sf *RESTRICT ch, + const float *const wa1) +{ + const v4sf tr11{ld_ps1(0.309016994374947f)}; + const v4sf ti11{ld_ps1(0.951056516295154f)}; + const v4sf tr12{ld_ps1(-0.809016994374947f)}; + const v4sf ti12{ld_ps1(0.587785252292473f)}; + + auto cc_ref = [&cc,ido](size_t a_1, size_t a_2, size_t a_3) noexcept -> auto& + { return cc[(a_3*5 + a_2)*ido + a_1]; }; + auto ch_ref = [&ch,ido,l1](size_t a_1, size_t a_2, size_t a_3) noexcept -> auto& + { return ch[(a_3*l1 + a_2)*ido + a_1]; }; + + /* Parameter adjustments */ + ch -= 1 + ido*(1 + l1); + cc -= 1 + ido*6; + + const auto wa2 = wa1 + ido; + const auto wa3 = wa2 + ido; + const auto wa4 = wa3 + ido; + + /* Function Body */ + for(size_t k{1};k <= l1;++k) + { + v4sf ti5{vadd(cc_ref( 1, 3, k), cc_ref(1, 3, k))}; + v4sf ti4{vadd(cc_ref( 1, 5, k), cc_ref(1, 5, k))}; + v4sf tr2{vadd(cc_ref(ido, 2, k), cc_ref(ido, 2, k))}; + v4sf tr3{vadd(cc_ref(ido, 4, k), cc_ref(ido, 4, k))}; + ch_ref(1, k, 1) = vadd(cc_ref(1, 1, k), vadd(tr2, tr3)); + v4sf cr2{vadd(cc_ref(1, 1, k), vmadd(tr11, tr2, vmul(tr12, tr3)))}; + v4sf cr3{vadd(cc_ref(1, 1, k), vmadd(tr12, tr2, vmul(tr11, tr3)))}; + v4sf ci5{vmadd(ti11, ti5, vmul(ti12, ti4))}; + v4sf ci4{vsub(vmul(ti12, ti5), vmul(ti11, ti4))}; + ch_ref(1, k, 2) = vsub(cr2, ci5); + ch_ref(1, k, 3) = vsub(cr3, ci4); + ch_ref(1, k, 4) = vadd(cr3, ci4); + ch_ref(1, k, 5) = vadd(cr2, ci5); + } + if(ido == 1) + return; + + const size_t idp2{ido + 2}; + for(size_t k{1};k <= l1;++k) + { + for(size_t i{3};i <= ido;i += 2) + { + const size_t ic{idp2 - i}; + v4sf ti5{vadd(cc_ref(i , 3, k), cc_ref(ic , 2, k))}; + v4sf ti2{vsub(cc_ref(i , 3, k), cc_ref(ic , 2, k))}; + v4sf ti4{vadd(cc_ref(i , 5, k), cc_ref(ic , 4, k))}; + v4sf ti3{vsub(cc_ref(i , 5, k), cc_ref(ic , 4, k))}; + v4sf tr5{vsub(cc_ref(i-1, 3, k), cc_ref(ic-1, 2, k))}; + v4sf tr2{vadd(cc_ref(i-1, 3, k), cc_ref(ic-1, 2, k))}; + v4sf tr4{vsub(cc_ref(i-1, 5, k), cc_ref(ic-1, 4, k))}; + v4sf tr3{vadd(cc_ref(i-1, 5, k), cc_ref(ic-1, 4, k))}; + ch_ref(i - 1, k, 1) = vadd(cc_ref(i-1, 1, k), vadd(tr2, tr3)); + ch_ref(i , k, 1) = vadd(cc_ref(i , 1, k), vadd(ti2, ti3)); + v4sf cr2{vadd(cc_ref(i-1, 1, k), vmadd(tr11, tr2, vmul(tr12, tr3)))}; + v4sf ci2{vadd(cc_ref(i , 1, k), vmadd(tr11, ti2, vmul(tr12, ti3)))}; + v4sf cr3{vadd(cc_ref(i-1, 1, k), vmadd(tr12, tr2, vmul(tr11, tr3)))}; + v4sf ci3{vadd(cc_ref(i , 1, k), vmadd(tr12, ti2, vmul(tr11, ti3)))}; + v4sf cr5{vmadd(ti11, tr5, vmul(ti12, tr4))}; + v4sf ci5{vmadd(ti11, ti5, vmul(ti12, ti4))}; + v4sf cr4{vsub(vmul(ti12, tr5), vmul(ti11, tr4))}; + v4sf ci4{vsub(vmul(ti12, ti5), vmul(ti11, ti4))}; + v4sf dr3{vsub(cr3, ci4)}; + v4sf dr4{vadd(cr3, ci4)}; + v4sf di3{vadd(ci3, cr4)}; + v4sf di4{vsub(ci3, cr4)}; + v4sf dr5{vadd(cr2, ci5)}; + v4sf dr2{vsub(cr2, ci5)}; + v4sf di5{vsub(ci2, cr5)}; + v4sf di2{vadd(ci2, cr5)}; + vcplxmul(dr2, di2, ld_ps1(wa1[i-3]), ld_ps1(wa1[i-2])); + vcplxmul(dr3, di3, ld_ps1(wa2[i-3]), ld_ps1(wa2[i-2])); + vcplxmul(dr4, di4, ld_ps1(wa3[i-3]), ld_ps1(wa3[i-2])); + vcplxmul(dr5, di5, ld_ps1(wa4[i-3]), ld_ps1(wa4[i-2])); + + ch_ref(i-1, k, 2) = dr2; ch_ref(i, k, 2) = di2; + ch_ref(i-1, k, 3) = dr3; ch_ref(i, k, 3) = di3; + ch_ref(i-1, k, 4) = dr4; ch_ref(i, k, 4) = di4; + ch_ref(i-1, k, 5) = dr5; ch_ref(i, k, 5) = di5; + } + } +} /* radb5 */ + +NOINLINE v4sf *rfftf1_ps(const size_t n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, + const float *wa, const al::span ifac) +{ + assert(work1 != work2); + + const v4sf *in{input_readonly}; + v4sf *out{in == work2 ? work1 : work2}; + const size_t nf{ifac[1]}; + size_t l2{n}; + size_t iw{n-1}; + size_t k1{1}; + while(true) + { + const size_t kh{nf - k1}; + const size_t ip{ifac[kh + 2]}; + const size_t l1{l2 / ip}; + const size_t ido{n / l2}; + iw -= (ip - 1)*ido; + switch(ip) + { + case 5: + radf5_ps(ido, l1, in, out, &wa[iw]); + break; + case 4: + radf4_ps(ido, l1, in, out, &wa[iw]); + break; + case 3: + radf3_ps(ido, l1, in, out, &wa[iw]); + break; + case 2: + radf2_ps(ido, l1, in, out, &wa[iw]); + break; + default: + assert(0); + } + if(++k1 > nf) + return out; + + l2 = l1; + if(out == work2) + { + out = work1; + in = work2; + } + else + { + out = work2; + in = work1; + } + } +} /* rfftf1 */ + +NOINLINE v4sf *rfftb1_ps(const size_t n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, + const float *wa, const al::span ifac) +{ + assert(work1 != work2); + + const v4sf *in{input_readonly}; + v4sf *out{in == work2 ? work1 : work2}; + const size_t nf{ifac[1]}; + size_t l1{1}; + size_t iw{0}; + size_t k1{1}; + while(true) + { + const size_t ip{ifac[k1 + 1]}; + const size_t l2{ip*l1}; + const size_t ido{n / l2}; + switch(ip) + { + case 5: + radb5_ps(ido, l1, in, out, &wa[iw]); + break; + case 4: + radb4_ps(ido, l1, in, out, &wa[iw]); + break; + case 3: + radb3_ps(ido, l1, in, out, &wa[iw]); + break; + case 2: + radb2_ps(ido, l1, in, out, &wa[iw]); + break; + default: + assert(0); + } + if(++k1 > nf) + return out; + + l1 = l2; + iw += (ip - 1)*ido; + + if(out == work2) + { + out = work1; + in = work2; + } + else + { + out = work2; + in = work1; + } + } +} + +v4sf *cfftf1_ps(const size_t n, const v4sf *input_readonly, v4sf *work1, v4sf *work2, + const float *wa, const al::span ifac, const float fsign) +{ + assert(work1 != work2); + + const v4sf *in{input_readonly}; + v4sf *out{in == work2 ? work1 : work2}; + const size_t nf{ifac[1]}; + size_t l1{1}, iw{0}; + size_t k1{2}; + while(true) + { + const size_t ip{ifac[k1]}; + const size_t l2{ip*l1}; + const size_t ido{n / l2}; + const size_t idot{ido + ido}; + switch(ip) + { + case 5: + passf5_ps(idot, l1, in, out, &wa[iw], fsign); + break; + case 4: + passf4_ps(idot, l1, in, out, &wa[iw], fsign); + break; + case 3: + passf3_ps(idot, l1, in, out, &wa[iw], fsign); + break; + case 2: + passf2_ps(idot, l1, in, out, &wa[iw], fsign); + break; + default: + assert(0); + } + if(++k1 > nf+1) + return out; + + l1 = l2; + iw += (ip - 1)*idot; + if(out == work2) + { + out = work1; + in = work2; + } + else + { + out = work2; + in = work1; + } + } +} + + +uint decompose(const uint n, const al::span ifac, const al::span ntryh) +{ + uint nl{n}, nf{0}; + for(const uint ntry : ntryh) + { + while(nl != 1) + { + const uint nq{nl / ntry}; + const uint nr{nl % ntry}; + if(nr != 0) break; + + ifac[2+nf++] = ntry; + nl = nq; + if(ntry == 2 && nf != 1) + { + for(size_t i{2};i <= nf;++i) + { + size_t ib{nf - i + 2}; + ifac[ib + 1] = ifac[ib]; + } + ifac[2] = 2; + } + } + } + ifac[0] = n; + ifac[1] = nf; + return nf; +} + +void rffti1_ps(const uint n, float *wa, const al::span ifac) +{ + static constexpr std::array ntryh{4u,2u,3u,5u}; + + const uint nf{decompose(n, ifac, ntryh)}; + const double argh{2.0*al::numbers::pi / n}; + size_t is{0}; + size_t nfm1{nf - 1}; + size_t l1{1}; + for(size_t k1{0};k1 < nfm1;++k1) + { + const size_t ip{ifac[k1+2]}; + const size_t l2{l1*ip}; + const size_t ido{n / l2}; + const size_t ipm{ip - 1}; + size_t ld{0}; + for(size_t j{0};j < ipm;++j) + { + size_t i{is}; + ld += l1; + const double argld{static_cast(ld)*argh}; + double fi{0.0}; + for(size_t ii{2};ii < ido;ii += 2) + { + fi += 1.0; + wa[i++] = static_cast(std::cos(fi*argld)); + wa[i++] = static_cast(std::sin(fi*argld)); + } + is += ido; + } + l1 = l2; + } +} /* rffti1 */ + +void cffti1_ps(const uint n, float *wa, const al::span ifac) +{ + static constexpr std::array ntryh{5u,3u,4u,2u}; + + const uint nf{decompose(n, ifac, ntryh)}; + const double argh{2.0*al::numbers::pi / n}; + size_t i{1}; + size_t l1{1}; + for(size_t k1{0};k1 < nf;++k1) + { + const size_t ip{ifac[k1+2]}; + const size_t l2{l1*ip}; + const size_t ido{n / l2}; + const size_t idot{ido + ido + 2}; + const size_t ipm{ip - 1}; + size_t ld{0}; + for(size_t j{0};j < ipm;++j) + { + size_t i1{i}; + wa[i-1] = 1; + wa[i] = 0; + ld += l1; + const double argld{static_cast(ld)*argh}; + double fi{0.0}; + for(size_t ii{3};ii < idot;ii += 2) + { + fi += 1.0; + wa[++i] = static_cast(std::cos(fi*argld)); + wa[++i] = static_cast(std::sin(fi*argld)); + } + if(ip > 5) + { + wa[i1-1] = wa[i-1]; + wa[i1] = wa[i]; + } + } + l1 = l2; + } +} /* cffti1 */ + +} // namespace + +/* NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding) */ +struct PFFFT_Setup { + uint N{}; + uint Ncvec{}; /* nb of complex simd vectors (N/4 if PFFFT_COMPLEX, N/8 if PFFFT_REAL) */ + std::array ifac{}; + pffft_transform_t transform{}; + + float *twiddle{}; /* N/4 elements */ + al::span e; /* N/4*3 elements */ + + alignas(V4sfAlignment) std::byte end; +}; + +PFFFTSetupPtr pffft_new_setup(unsigned int N, pffft_transform_t transform) +{ + assert(transform == PFFFT_REAL || transform == PFFFT_COMPLEX); + assert(N > 0); + /* unfortunately, the fft size must be a multiple of 16 for complex FFTs + * and 32 for real FFTs -- a lot of stuff would need to be rewritten to + * handle other cases (or maybe just switch to a scalar fft, I don't know..) + */ + if(transform == PFFFT_REAL) + assert((N%(2*SimdSize*SimdSize)) == 0); + else + assert((N%(SimdSize*SimdSize)) == 0); + + const uint Ncvec{(transform == PFFFT_REAL ? N/2 : N) / SimdSize}; + + const size_t storelen{std::max(offsetof(PFFFT_Setup, end) + 2_zu*Ncvec*sizeof(v4sf), + sizeof(PFFFT_Setup))}; + auto storage = static_cast>(::operator new[](storelen, V4sfAlignVal)); + al::span extrastore{&storage[offsetof(PFFFT_Setup, end)], 2_zu*Ncvec*sizeof(v4sf)}; + + PFFFTSetupPtr s{::new(storage) PFFFT_Setup{}}; + s->N = N; + s->transform = transform; + s->Ncvec = Ncvec; + + const size_t ecount{2_zu*Ncvec*(SimdSize-1)/SimdSize}; + s->e = {std::launder(reinterpret_cast(extrastore.data())), ecount}; + s->twiddle = std::launder(reinterpret_cast(&extrastore[ecount*sizeof(v4sf)])); + + if constexpr(SimdSize > 1) + { + auto e = std::vector(s->e.size()*SimdSize, 0.0f); + for(size_t k{0};k < s->Ncvec;++k) + { + const size_t i{k / SimdSize}; + const size_t j{k % SimdSize}; + for(size_t m{0};m < SimdSize-1;++m) + { + const double A{-2.0*al::numbers::pi*static_cast((m+1)*k) / N}; + e[((i*3 + m)*2 + 0)*SimdSize + j] = static_cast(std::cos(A)); + e[((i*3 + m)*2 + 1)*SimdSize + j] = static_cast(std::sin(A)); + } + } + std::memcpy(s->e.data(), e.data(), e.size()*sizeof(float)); + } + if(transform == PFFFT_REAL) + rffti1_ps(N/SimdSize, s->twiddle, s->ifac); + else + cffti1_ps(N/SimdSize, s->twiddle, s->ifac); + + /* check that N is decomposable with allowed prime factors */ + size_t m{1}; + for(size_t k{0};k < s->ifac[1];++k) + m *= s->ifac[2+k]; + + if(m != N/SimdSize) + s = nullptr; + + return s; +} + + +void PFFFTSetupDeleter::operator()(gsl::owner setup) const noexcept +{ + std::destroy_at(setup); + ::operator delete[](gsl::owner{setup}, V4sfAlignVal); +} + +#if !defined(PFFFT_SIMD_DISABLE) + +namespace { + +/* [0 0 1 2 3 4 5 6 7 8] -> [0 8 7 6 5 4 3 2 1] */ +void reversed_copy(const size_t N, const v4sf *in, const int in_stride, v4sf *RESTRICT out) +{ + v4sf g0, g1; + interleave2(in[0], in[1], g0, g1); + in += in_stride; + + *--out = vswaphl(g0, g1); // [g0l, g0h], [g1l g1h] -> [g1l, g0h] + for(size_t k{1};k < N;++k) + { + v4sf h0, h1; + interleave2(in[0], in[1], h0, h1); + in += in_stride; + *--out = vswaphl(g1, h0); + *--out = vswaphl(h0, h1); + g1 = h1; + } + *--out = vswaphl(g1, g0); +} + +void unreversed_copy(const size_t N, const v4sf *in, v4sf *RESTRICT out, const int out_stride) +{ + v4sf g0{in[0]}, g1{g0}; + ++in; + for(size_t k{1};k < N;++k) + { + v4sf h0{*in++}; v4sf h1{*in++}; + g1 = vswaphl(g1, h0); + h0 = vswaphl(h0, h1); + uninterleave2(h0, g1, out[0], out[1]); + out += out_stride; + g1 = h1; + } + v4sf h0{*in++}, h1{g0}; + g1 = vswaphl(g1, h0); + h0 = vswaphl(h0, h1); + uninterleave2(h0, g1, out[0], out[1]); +} + +void pffft_cplx_finalize(const size_t Ncvec, const v4sf *in, v4sf *RESTRICT out, const v4sf *e) +{ + assert(in != out); + + const size_t dk{Ncvec/SimdSize}; // number of 4x4 matrix blocks + for(size_t k{0};k < dk;++k) + { + v4sf r0{in[8*k+0]}, i0{in[8*k+1]}; + v4sf r1{in[8*k+2]}, i1{in[8*k+3]}; + v4sf r2{in[8*k+4]}, i2{in[8*k+5]}; + v4sf r3{in[8*k+6]}, i3{in[8*k+7]}; + vtranspose4(r0,r1,r2,r3); + vtranspose4(i0,i1,i2,i3); + vcplxmul(r1,i1,e[k*6+0],e[k*6+1]); + vcplxmul(r2,i2,e[k*6+2],e[k*6+3]); + vcplxmul(r3,i3,e[k*6+4],e[k*6+5]); + + v4sf sr0{vadd(r0,r2)}, dr0{vsub(r0, r2)}; + v4sf sr1{vadd(r1,r3)}, dr1{vsub(r1, r3)}; + v4sf si0{vadd(i0,i2)}, di0{vsub(i0, i2)}; + v4sf si1{vadd(i1,i3)}, di1{vsub(i1, i3)}; + + /* transformation for each column is: + * + * [1 1 1 1 0 0 0 0] [r0] + * [1 0 -1 0 0 -1 0 1] [r1] + * [1 -1 1 -1 0 0 0 0] [r2] + * [1 0 -1 0 0 1 0 -1] [r3] + * [0 0 0 0 1 1 1 1] * [i0] + * [0 1 0 -1 1 0 -1 0] [i1] + * [0 0 0 0 1 -1 1 -1] [i2] + * [0 -1 0 1 1 0 -1 0] [i3] + */ + + r0 = vadd(sr0, sr1); i0 = vadd(si0, si1); + r1 = vadd(dr0, di1); i1 = vsub(di0, dr1); + r2 = vsub(sr0, sr1); i2 = vsub(si0, si1); + r3 = vsub(dr0, di1); i3 = vadd(di0, dr1); + + *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; + *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; + } +} + +void pffft_cplx_preprocess(const size_t Ncvec, const v4sf *in, v4sf *RESTRICT out, const v4sf *e) +{ + assert(in != out); + + const size_t dk{Ncvec/SimdSize}; // number of 4x4 matrix blocks + for(size_t k{0};k < dk;++k) + { + v4sf r0{in[8*k+0]}, i0{in[8*k+1]}; + v4sf r1{in[8*k+2]}, i1{in[8*k+3]}; + v4sf r2{in[8*k+4]}, i2{in[8*k+5]}; + v4sf r3{in[8*k+6]}, i3{in[8*k+7]}; + + v4sf sr0{vadd(r0,r2)}, dr0{vsub(r0, r2)}; + v4sf sr1{vadd(r1,r3)}, dr1{vsub(r1, r3)}; + v4sf si0{vadd(i0,i2)}, di0{vsub(i0, i2)}; + v4sf si1{vadd(i1,i3)}, di1{vsub(i1, i3)}; + + r0 = vadd(sr0, sr1); i0 = vadd(si0, si1); + r1 = vsub(dr0, di1); i1 = vadd(di0, dr1); + r2 = vsub(sr0, sr1); i2 = vsub(si0, si1); + r3 = vadd(dr0, di1); i3 = vsub(di0, dr1); + + vcplxmulconj(r1,i1,e[k*6+0],e[k*6+1]); + vcplxmulconj(r2,i2,e[k*6+2],e[k*6+3]); + vcplxmulconj(r3,i3,e[k*6+4],e[k*6+5]); + + vtranspose4(r0,r1,r2,r3); + vtranspose4(i0,i1,i2,i3); + + *out++ = r0; *out++ = i0; *out++ = r1; *out++ = i1; + *out++ = r2; *out++ = i2; *out++ = r3; *out++ = i3; + } +} + + +force_inline void pffft_real_finalize_4x4(const v4sf *in0, const v4sf *in1, const v4sf *in, + const v4sf *e, v4sf *RESTRICT out) +{ + v4sf r0{*in0}, i0{*in1}; + v4sf r1{*in++}; v4sf i1{*in++}; + v4sf r2{*in++}; v4sf i2{*in++}; + v4sf r3{*in++}; v4sf i3{*in++}; + vtranspose4(r0,r1,r2,r3); + vtranspose4(i0,i1,i2,i3); + + /* transformation for each column is: + * + * [1 1 1 1 0 0 0 0] [r0] + * [1 0 -1 0 0 -1 0 1] [r1] + * [1 0 -1 0 0 1 0 -1] [r2] + * [1 -1 1 -1 0 0 0 0] [r3] + * [0 0 0 0 1 1 1 1] * [i0] + * [0 -1 0 1 -1 0 1 0] [i1] + * [0 -1 0 1 1 0 -1 0] [i2] + * [0 0 0 0 -1 1 -1 1] [i3] + */ + + //cerr << "matrix initial, before e , REAL:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; + //cerr << "matrix initial, before e, IMAG :\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; + + vcplxmul(r1,i1,e[0],e[1]); + vcplxmul(r2,i2,e[2],e[3]); + vcplxmul(r3,i3,e[4],e[5]); + + //cerr << "matrix initial, real part:\n 1: " << r0 << "\n 1: " << r1 << "\n 1: " << r2 << "\n 1: " << r3 << "\n"; + //cerr << "matrix initial, imag part:\n 1: " << i0 << "\n 1: " << i1 << "\n 1: " << i2 << "\n 1: " << i3 << "\n"; + + v4sf sr0{vadd(r0,r2)}, dr0{vsub(r0,r2)}; + v4sf sr1{vadd(r1,r3)}, dr1{vsub(r3,r1)}; + v4sf si0{vadd(i0,i2)}, di0{vsub(i0,i2)}; + v4sf si1{vadd(i1,i3)}, di1{vsub(i3,i1)}; + + r0 = vadd(sr0, sr1); + r3 = vsub(sr0, sr1); + i0 = vadd(si0, si1); + i3 = vsub(si1, si0); + r1 = vadd(dr0, di1); + r2 = vsub(dr0, di1); + i1 = vsub(dr1, di0); + i2 = vadd(dr1, di0); + + *out++ = r0; + *out++ = i0; + *out++ = r1; + *out++ = i1; + *out++ = r2; + *out++ = i2; + *out++ = r3; + *out++ = i3; +} + +NOINLINE void pffft_real_finalize(const size_t Ncvec, const v4sf *in, v4sf *RESTRICT out, + const v4sf *e) +{ + static constexpr float s{al::numbers::sqrt2_v/2.0f}; + + assert(in != out); + const size_t dk{Ncvec/SimdSize}; // number of 4x4 matrix blocks + /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ + + const v4sf zero{vzero()}; + const auto cr = al::bit_cast>(in[0]); + const auto ci = al::bit_cast>(in[Ncvec*2-1]); + pffft_real_finalize_4x4(&zero, &zero, in+1, e, out); + + /* [cr0 cr1 cr2 cr3 ci0 ci1 ci2 ci3] + * + * [Xr(1)] ] [1 1 1 1 0 0 0 0] + * [Xr(N/4) ] [0 0 0 0 1 s 0 -s] + * [Xr(N/2) ] [1 0 -1 0 0 0 0 0] + * [Xr(3N/4)] [0 0 0 0 1 -s 0 s] + * [Xi(1) ] [1 -1 1 -1 0 0 0 0] + * [Xi(N/4) ] [0 0 0 0 0 -s -1 -s] + * [Xi(N/2) ] [0 -1 0 1 0 0 0 0] + * [Xi(3N/4)] [0 0 0 0 0 -s 1 -s] + */ + + const float xr0{(cr[0]+cr[2]) + (cr[1]+cr[3])}; out[0] = vinsert0(out[0], xr0); + const float xi0{(cr[0]+cr[2]) - (cr[1]+cr[3])}; out[1] = vinsert0(out[1], xi0); + const float xr2{(cr[0]-cr[2])}; out[4] = vinsert0(out[4], xr2); + const float xi2{(cr[3]-cr[1])}; out[5] = vinsert0(out[5], xi2); + const float xr1{ ci[0] + s*(ci[1]-ci[3])}; out[2] = vinsert0(out[2], xr1); + const float xi1{-ci[2] - s*(ci[1]+ci[3])}; out[3] = vinsert0(out[3], xi1); + const float xr3{ ci[0] - s*(ci[1]-ci[3])}; out[6] = vinsert0(out[6], xr3); + const float xi3{ ci[2] - s*(ci[1]+ci[3])}; out[7] = vinsert0(out[7], xi3); + + for(size_t k{1};k < dk;++k) + pffft_real_finalize_4x4(&in[8*k-1], &in[8*k+0], in + 8*k+1, e + k*6, out + k*8); +} + +force_inline void pffft_real_preprocess_4x4(const v4sf *in, const v4sf *e, v4sf *RESTRICT out, + const bool first) +{ + v4sf r0{in[0]}, i0{in[1]}, r1{in[2]}, i1{in[3]}; + v4sf r2{in[4]}, i2{in[5]}, r3{in[6]}, i3{in[7]}; + + /* transformation for each column is: + * + * [1 1 1 1 0 0 0 0] [r0] + * [1 0 0 -1 0 -1 -1 0] [r1] + * [1 -1 -1 1 0 0 0 0] [r2] + * [1 0 0 -1 0 1 1 0] [r3] + * [0 0 0 0 1 -1 1 -1] * [i0] + * [0 -1 1 0 1 0 0 1] [i1] + * [0 0 0 0 1 1 -1 -1] [i2] + * [0 1 -1 0 1 0 0 1] [i3] + */ + + v4sf sr0{vadd(r0,r3)}, dr0{vsub(r0,r3)}; + v4sf sr1{vadd(r1,r2)}, dr1{vsub(r1,r2)}; + v4sf si0{vadd(i0,i3)}, di0{vsub(i0,i3)}; + v4sf si1{vadd(i1,i2)}, di1{vsub(i1,i2)}; + + r0 = vadd(sr0, sr1); + r2 = vsub(sr0, sr1); + r1 = vsub(dr0, si1); + r3 = vadd(dr0, si1); + i0 = vsub(di0, di1); + i2 = vadd(di0, di1); + i1 = vsub(si0, dr1); + i3 = vadd(si0, dr1); + + vcplxmulconj(r1,i1,e[0],e[1]); + vcplxmulconj(r2,i2,e[2],e[3]); + vcplxmulconj(r3,i3,e[4],e[5]); + + vtranspose4(r0,r1,r2,r3); + vtranspose4(i0,i1,i2,i3); + + if(!first) + { + *out++ = r0; + *out++ = i0; + } + *out++ = r1; + *out++ = i1; + *out++ = r2; + *out++ = i2; + *out++ = r3; + *out++ = i3; +} + +NOINLINE void pffft_real_preprocess(const size_t Ncvec, const v4sf *in, v4sf *RESTRICT out, + const v4sf *e) +{ + static constexpr float sqrt2{al::numbers::sqrt2_v}; + + assert(in != out); + const size_t dk{Ncvec/SimdSize}; // number of 4x4 matrix blocks + /* fftpack order is f0r f1r f1i f2r f2i ... f(n-1)r f(n-1)i f(n)r */ + + std::array Xr{}, Xi{}; + for(size_t k{0};k < SimdSize;++k) + { + Xr[k] = vextract0(in[2*k]); + Xi[k] = vextract0(in[2*k + 1]); + } + + pffft_real_preprocess_4x4(in, e, out+1, true); // will write only 6 values + + /* [Xr0 Xr1 Xr2 Xr3 Xi0 Xi1 Xi2 Xi3] + * + * [cr0] [1 0 2 0 1 0 0 0] + * [cr1] [1 0 0 0 -1 0 -2 0] + * [cr2] [1 0 -2 0 1 0 0 0] + * [cr3] [1 0 0 0 -1 0 2 0] + * [ci0] [0 2 0 2 0 0 0 0] + * [ci1] [0 s 0 -s 0 -s 0 -s] + * [ci2] [0 0 0 0 0 -2 0 2] + * [ci3] [0 -s 0 s 0 -s 0 -s] + */ + for(size_t k{1};k < dk;++k) + pffft_real_preprocess_4x4(in+8*k, e + k*6, out-1+k*8, false); + + const float cr0{(Xr[0]+Xi[0]) + 2*Xr[2]}; + const float cr1{(Xr[0]-Xi[0]) - 2*Xi[2]}; + const float cr2{(Xr[0]+Xi[0]) - 2*Xr[2]}; + const float cr3{(Xr[0]-Xi[0]) + 2*Xi[2]}; + out[0] = vset4(cr0, cr1, cr2, cr3); + const float ci0{ 2*(Xr[1]+Xr[3])}; + const float ci1{ sqrt2*(Xr[1]-Xr[3]) - sqrt2*(Xi[1]+Xi[3])}; + const float ci2{ 2*(Xi[3]-Xi[1])}; + const float ci3{-sqrt2*(Xr[1]-Xr[3]) - sqrt2*(Xi[1]+Xi[3])}; + out[2*Ncvec-1] = vset4(ci0, ci1, ci2, ci3); +} + + +void pffft_transform_internal(const PFFFT_Setup *setup, const v4sf *vinput, v4sf *voutput, + v4sf *scratch, const pffft_direction_t direction, const bool ordered) +{ + assert(scratch != nullptr); + assert(voutput != scratch); + + const size_t Ncvec{setup->Ncvec}; + const bool nf_odd{(setup->ifac[1]&1) != 0}; + + std::array buff{voutput, scratch}; + bool ib{nf_odd != ordered}; + if(direction == PFFFT_FORWARD) + { + /* Swap the initial work buffer for forward FFTs, which helps avoid an + * extra copy for output. + */ + ib = !ib; + if(setup->transform == PFFFT_REAL) + { + ib = (rfftf1_ps(Ncvec*2, vinput, buff[ib], buff[!ib], setup->twiddle, setup->ifac) == buff[1]); + pffft_real_finalize(Ncvec, buff[ib], buff[!ib], setup->e.data()); + } + else + { + v4sf *tmp{buff[ib]}; + for(size_t k=0; k < Ncvec; ++k) + uninterleave2(vinput[k*2], vinput[k*2+1], tmp[k*2], tmp[k*2+1]); + + ib = (cfftf1_ps(Ncvec, buff[ib], buff[!ib], buff[ib], setup->twiddle, setup->ifac, -1.0f) == buff[1]); + pffft_cplx_finalize(Ncvec, buff[ib], buff[!ib], setup->e.data()); + } + if(ordered) + pffft_zreorder(setup, reinterpret_cast(buff[!ib]), + reinterpret_cast(buff[ib]), PFFFT_FORWARD); + else + ib = !ib; + } + else + { + if(vinput == buff[ib]) + ib = !ib; // may happen when finput == foutput + + if(ordered) + { + pffft_zreorder(setup, reinterpret_cast(vinput), + reinterpret_cast(buff[ib]), PFFFT_BACKWARD); + vinput = buff[ib]; + ib = !ib; + } + if(setup->transform == PFFFT_REAL) + { + pffft_real_preprocess(Ncvec, vinput, buff[ib], setup->e.data()); + ib = (rfftb1_ps(Ncvec*2, buff[ib], buff[0], buff[1], setup->twiddle, setup->ifac) == buff[1]); + } + else + { + pffft_cplx_preprocess(Ncvec, vinput, buff[ib], setup->e.data()); + ib = (cfftf1_ps(Ncvec, buff[ib], buff[0], buff[1], setup->twiddle, setup->ifac, +1.0f) == buff[1]); + for(size_t k{0};k < Ncvec;++k) + interleave2(buff[ib][k*2], buff[ib][k*2+1], buff[ib][k*2], buff[ib][k*2+1]); + } + } + + if(buff[ib] != voutput) + { + /* extra copy required -- this situation should only happen when finput == foutput */ + assert(vinput==voutput); + for(size_t k{0};k < Ncvec;++k) + { + v4sf a{buff[ib][2*k]}, b{buff[ib][2*k+1]}; + voutput[2*k] = a; voutput[2*k+1] = b; + } + } +} + +} // namespace + +void pffft_zreorder(const PFFFT_Setup *setup, const float *in, float *out, + pffft_direction_t direction) +{ + assert(in != out); + + const size_t N{setup->N}, Ncvec{setup->Ncvec}; + const v4sf *vin{reinterpret_cast(in)}; + v4sf *RESTRICT vout{reinterpret_cast(out)}; + if(setup->transform == PFFFT_REAL) + { + const size_t dk{N/32}; + if(direction == PFFFT_FORWARD) + { + for(size_t k{0};k < dk;++k) + { + interleave2(vin[k*8 + 0], vin[k*8 + 1], vout[2*(0*dk + k) + 0], vout[2*(0*dk + k) + 1]); + interleave2(vin[k*8 + 4], vin[k*8 + 5], vout[2*(2*dk + k) + 0], vout[2*(2*dk + k) + 1]); + } + reversed_copy(dk, vin+2, 8, vout + N/SimdSize/2); + reversed_copy(dk, vin+6, 8, vout + N/SimdSize); + } + else + { + for(size_t k{0};k < dk;++k) + { + uninterleave2(vin[2*(0*dk + k) + 0], vin[2*(0*dk + k) + 1], vout[k*8 + 0], vout[k*8 + 1]); + uninterleave2(vin[2*(2*dk + k) + 0], vin[2*(2*dk + k) + 1], vout[k*8 + 4], vout[k*8 + 5]); + } + unreversed_copy(dk, vin + N/SimdSize/4, vout + N/SimdSize - 6, -8); + unreversed_copy(dk, vin + 3_uz*N/SimdSize/4, vout + N/SimdSize - 2, -8); + } + } + else + { + if(direction == PFFFT_FORWARD) + { + for(size_t k{0};k < Ncvec;++k) + { + size_t kk{(k/4) + (k%4)*(Ncvec/4)}; + interleave2(vin[k*2], vin[k*2+1], vout[kk*2], vout[kk*2+1]); + } + } + else + { + for(size_t k{0};k < Ncvec;++k) + { + size_t kk{(k/4) + (k%4)*(Ncvec/4)}; + uninterleave2(vin[kk*2], vin[kk*2+1], vout[k*2], vout[k*2+1]); + } + } + } +} + +void pffft_zconvolve_scale_accumulate(const PFFFT_Setup *s, const float *a, const float *b, + float *ab, float scaling) +{ + const size_t Ncvec{s->Ncvec}; + const v4sf *RESTRICT va{reinterpret_cast(a)}; + const v4sf *RESTRICT vb{reinterpret_cast(b)}; + v4sf *RESTRICT vab{reinterpret_cast(ab)}; + +#ifdef __arm__ + __builtin_prefetch(va); + __builtin_prefetch(vb); + __builtin_prefetch(vab); + __builtin_prefetch(va+2); + __builtin_prefetch(vb+2); + __builtin_prefetch(vab+2); + __builtin_prefetch(va+4); + __builtin_prefetch(vb+4); + __builtin_prefetch(vab+4); + __builtin_prefetch(va+6); + __builtin_prefetch(vb+6); + __builtin_prefetch(vab+6); +#ifndef __clang__ +#define ZCONVOLVE_USING_INLINE_NEON_ASM +#endif +#endif + + const float ar1{vextract0(va[0])}; + const float ai1{vextract0(va[1])}; + const float br1{vextract0(vb[0])}; + const float bi1{vextract0(vb[1])}; + const float abr1{vextract0(vab[0])}; + const float abi1{vextract0(vab[1])}; + +#ifdef ZCONVOLVE_USING_INLINE_ASM + /* Inline asm version, unfortunately miscompiled by clang 3.2, at least on + * Ubuntu. So this will be restricted to GCC. + * + * Does it still miscompile with Clang? Is it even needed with today's + * optimizers? + */ + const float *a_{a}, *b_{b}; float *ab_{ab}; + size_t N{Ncvec}; + asm volatile("mov r8, %2 \n" + "vdup.f32 q15, %4 \n" + "1: \n" + "pld [%0,#64] \n" + "pld [%1,#64] \n" + "pld [%2,#64] \n" + "pld [%0,#96] \n" + "pld [%1,#96] \n" + "pld [%2,#96] \n" + "vld1.f32 {q0,q1}, [%0,:128]! \n" + "vld1.f32 {q4,q5}, [%1,:128]! \n" + "vld1.f32 {q2,q3}, [%0,:128]! \n" + "vld1.f32 {q6,q7}, [%1,:128]! \n" + "vld1.f32 {q8,q9}, [r8,:128]! \n" + + "vmul.f32 q10, q0, q4 \n" + "vmul.f32 q11, q0, q5 \n" + "vmul.f32 q12, q2, q6 \n" + "vmul.f32 q13, q2, q7 \n" + "vmls.f32 q10, q1, q5 \n" + "vmla.f32 q11, q1, q4 \n" + "vld1.f32 {q0,q1}, [r8,:128]! \n" + "vmls.f32 q12, q3, q7 \n" + "vmla.f32 q13, q3, q6 \n" + "vmla.f32 q8, q10, q15 \n" + "vmla.f32 q9, q11, q15 \n" + "vmla.f32 q0, q12, q15 \n" + "vmla.f32 q1, q13, q15 \n" + "vst1.f32 {q8,q9},[%2,:128]! \n" + "vst1.f32 {q0,q1},[%2,:128]! \n" + "subs %3, #2 \n" + "bne 1b \n" + : "+r"(a_), "+r"(b_), "+r"(ab_), "+r"(N) : "r"(scaling) : "r8", "q0","q1","q2","q3","q4","q5","q6","q7","q8","q9", "q10","q11","q12","q13","q15","memory"); + +#else + + /* Default routine, works fine for non-arm cpus with current compilers. */ + const v4sf vscal{ld_ps1(scaling)}; + for(size_t i{0};i < Ncvec;i += 2) + { + v4sf ar4{va[2*i+0]}, ai4{va[2*i+1]}; + v4sf br4{vb[2*i+0]}, bi4{vb[2*i+1]}; + vcplxmul(ar4, ai4, br4, bi4); + vab[2*i+0] = vmadd(ar4, vscal, vab[2*i+0]); + vab[2*i+1] = vmadd(ai4, vscal, vab[2*i+1]); + ar4 = va[2*i+2]; ai4 = va[2*i+3]; + br4 = vb[2*i+2]; bi4 = vb[2*i+3]; + vcplxmul(ar4, ai4, br4, bi4); + vab[2*i+2] = vmadd(ar4, vscal, vab[2*i+2]); + vab[2*i+3] = vmadd(ai4, vscal, vab[2*i+3]); + } +#endif + + if(s->transform == PFFFT_REAL) + { + vab[0] = vinsert0(vab[0], abr1 + ar1*br1*scaling); + vab[1] = vinsert0(vab[1], abi1 + ai1*bi1*scaling); + } +} + +void pffft_zconvolve_accumulate(const PFFFT_Setup *s, const float *a, const float *b, float *ab) +{ + const size_t Ncvec{s->Ncvec}; + const v4sf *RESTRICT va{reinterpret_cast(a)}; + const v4sf *RESTRICT vb{reinterpret_cast(b)}; + v4sf *RESTRICT vab{reinterpret_cast(ab)}; + +#ifdef __arm__ + __builtin_prefetch(va); + __builtin_prefetch(vb); + __builtin_prefetch(vab); + __builtin_prefetch(va+2); + __builtin_prefetch(vb+2); + __builtin_prefetch(vab+2); + __builtin_prefetch(va+4); + __builtin_prefetch(vb+4); + __builtin_prefetch(vab+4); + __builtin_prefetch(va+6); + __builtin_prefetch(vb+6); + __builtin_prefetch(vab+6); +#endif + + const float ar1{vextract0(va[0])}; + const float ai1{vextract0(va[1])}; + const float br1{vextract0(vb[0])}; + const float bi1{vextract0(vb[1])}; + const float abr1{vextract0(vab[0])}; + const float abi1{vextract0(vab[1])}; + + /* No inline assembly for this version. I'm not familiar enough with NEON + * assembly, and I don't know that it's needed with today's optimizers. + */ + for(size_t i{0};i < Ncvec;i += 2) + { + v4sf ar4{va[2*i+0]}, ai4{va[2*i+1]}; + v4sf br4{vb[2*i+0]}, bi4{vb[2*i+1]}; + vcplxmul(ar4, ai4, br4, bi4); + vab[2*i+0] = vadd(ar4, vab[2*i+0]); + vab[2*i+1] = vadd(ai4, vab[2*i+1]); + ar4 = va[2*i+2]; ai4 = va[2*i+3]; + br4 = vb[2*i+2]; bi4 = vb[2*i+3]; + vcplxmul(ar4, ai4, br4, bi4); + vab[2*i+2] = vadd(ar4, vab[2*i+2]); + vab[2*i+3] = vadd(ai4, vab[2*i+3]); + } + + if(s->transform == PFFFT_REAL) + { + vab[0] = vinsert0(vab[0], abr1 + ar1*br1); + vab[1] = vinsert0(vab[1], abi1 + ai1*bi1); + } +} + + +void pffft_transform(const PFFFT_Setup *setup, const float *input, float *output, float *work, + pffft_direction_t direction) +{ + assert(valigned(input) && valigned(output) && valigned(work)); + pffft_transform_internal(setup, reinterpret_cast(al::assume_aligned<16>(input)), + reinterpret_cast(al::assume_aligned<16>(output)), + reinterpret_cast(al::assume_aligned<16>(work)), direction, false); +} + +void pffft_transform_ordered(const PFFFT_Setup *setup, const float *input, float *output, + float *work, pffft_direction_t direction) +{ + assert(valigned(input) && valigned(output) && valigned(work)); + pffft_transform_internal(setup, reinterpret_cast(al::assume_aligned<16>(input)), + reinterpret_cast(al::assume_aligned<16>(output)), + reinterpret_cast(al::assume_aligned<16>(work)), direction, true); +} + +#else // defined(PFFFT_SIMD_DISABLE) + +// standard routine using scalar floats, without SIMD stuff. + +namespace { + +void pffft_transform_internal(const PFFFT_Setup *setup, const float *input, float *output, + float *scratch, const pffft_direction_t direction, bool ordered) +{ + const size_t Ncvec{setup->Ncvec}; + const bool nf_odd{(setup->ifac[1]&1) != 0}; + + assert(scratch != nullptr); + + /* z-domain data for complex transforms is already ordered without SIMD. */ + if(setup->transform == PFFFT_COMPLEX) + ordered = false; + + float *buff[2]{output, scratch}; + bool ib{nf_odd != ordered}; + if(direction == PFFFT_FORWARD) + { + if(setup->transform == PFFFT_REAL) + ib = (rfftf1_ps(Ncvec*2, input, buff[ib], buff[!ib], setup->twiddle, setup->ifac) == buff[1]); + else + ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], setup->twiddle, setup->ifac, -1.0f) == buff[1]); + if(ordered) + { + pffft_zreorder(setup, buff[ib], buff[!ib], PFFFT_FORWARD); + ib = !ib; + } + } + else + { + if (input == buff[ib]) + ib = !ib; // may happen when finput == foutput + + if(ordered) + { + pffft_zreorder(setup, input, buff[ib], PFFFT_BACKWARD); + input = buff[ib]; + ib = !ib; + } + if(setup->transform == PFFFT_REAL) + ib = (rfftb1_ps(Ncvec*2, input, buff[ib], buff[!ib], setup->twiddle, setup->ifac) == buff[1]); + else + ib = (cfftf1_ps(Ncvec, input, buff[ib], buff[!ib], setup->twiddle, setup->ifac, +1.0f) == buff[1]); + } + if(buff[ib] != output) + { + // extra copy required -- this situation should happens only when finput == foutput + assert(input==output); + for(size_t k{0};k < Ncvec;++k) + { + float a{buff[ib][2*k]}, b{buff[ib][2*k+1]}; + output[2*k] = a; output[2*k+1] = b; + } + } +} + +} // namespace + +void pffft_zreorder(const PFFFT_Setup *setup, const float *in, float *RESTRICT out, + pffft_direction_t direction) +{ + const size_t N{setup->N}; + if(setup->transform == PFFFT_COMPLEX) + { + for(size_t k{0};k < 2*N;++k) + out[k] = in[k]; + return; + } + else if(direction == PFFFT_FORWARD) + { + float x_N{in[N-1]}; + for(size_t k{N-1};k > 1;--k) + out[k] = in[k-1]; + out[0] = in[0]; + out[1] = x_N; + } + else + { + float x_N{in[1]}; + for(size_t k{1};k < N-1;++k) + out[k] = in[k+1]; + out[0] = in[0]; + out[N-1] = x_N; + } +} + +void pffft_zconvolve_scale_accumulate(const PFFFT_Setup *s, const float *a, const float *b, + float *ab, float scaling) +{ + size_t Ncvec{s->Ncvec}; + + if(s->transform == PFFFT_REAL) + { + // take care of the fftpack ordering + ab[0] += a[0]*b[0]*scaling; + ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]*scaling; + ++ab; ++a; ++b; --Ncvec; + } + for(size_t i{0};i < Ncvec;++i) + { + float ar{a[2*i+0]}, ai{a[2*i+1]}; + const float br{b[2*i+0]}, bi{b[2*i+1]}; + vcplxmul(ar, ai, br, bi); + ab[2*i+0] += ar*scaling; + ab[2*i+1] += ai*scaling; + } +} + +void pffft_zconvolve_accumulate(const PFFFT_Setup *s, const float *a, const float *b, float *ab) +{ + size_t Ncvec{s->Ncvec}; + + if(s->transform == PFFFT_REAL) + { + // take care of the fftpack ordering + ab[0] += a[0]*b[0]; + ab[2*Ncvec-1] += a[2*Ncvec-1]*b[2*Ncvec-1]; + ++ab; ++a; ++b; --Ncvec; + } + for(size_t i{0};i < Ncvec;++i) + { + float ar{a[2*i+0]}, ai{a[2*i+1]}; + const float br{b[2*i+0]}, bi{b[2*i+1]}; + vcplxmul(ar, ai, br, bi); + ab[2*i+0] += ar; + ab[2*i+1] += ai; + } +} + + +void pffft_transform(const PFFFT_Setup *setup, const float *input, float *output, float *work, + pffft_direction_t direction) +{ + pffft_transform_internal(setup, input, output, work, direction, false); +} + +void pffft_transform_ordered(const PFFFT_Setup *setup, const float *input, float *output, + float *work, pffft_direction_t direction) +{ + pffft_transform_internal(setup, input, output, work, direction, true); +} + +#endif /* defined(PFFFT_SIMD_DISABLE) */ +/* NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ diff --git a/3rdparty/openal/common/pffft.h b/3rdparty/openal/common/pffft.h new file mode 100644 index 000000000000..4c8fa587bc62 --- /dev/null +++ b/3rdparty/openal/common/pffft.h @@ -0,0 +1,211 @@ +/* Copyright (c) 2013 Julien Pommier ( pommier@modartt.com ) + + Based on original fortran 77 code from FFTPACKv4 from NETLIB, + authored by Dr Paul Swarztrauber of NCAR, in 1985. + + As confirmed by the NCAR fftpack software curators, the following + FFTPACKv5 license applies to FFTPACKv4 sources. My changes are + released under the same terms. + + FFTPACK license: + + http://www.cisl.ucar.edu/css/software/fftpack5/ftpk.html + + Copyright (c) 2004 the University Corporation for Atmospheric + Research ("UCAR"). All rights reserved. Developed by NCAR's + Computational and Information Systems Laboratory, UCAR, + www.cisl.ucar.edu. + + Redistribution and use of the Software in source and binary forms, + with or without modification, is permitted provided that the + following conditions are met: + + - Neither the names of NCAR's Computational and Information Systems + Laboratory, the University Corporation for Atmospheric Research, + nor the names of its sponsors or contributors may be used to + endorse or promote products derived from this Software without + specific prior written permission. + + - Redistributions of source code must retain the above copyright + notices, this list of conditions, and the disclaimer below. + + - Redistributions in binary form must reproduce the above copyright + notice, this list of conditions, and the disclaimer below in the + documentation and/or other materials provided with the + distribution. + + THIS SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING, BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE CONTRIBUTORS OR COPYRIGHT + HOLDERS BE LIABLE FOR ANY CLAIM, INDIRECT, INCIDENTAL, SPECIAL, + EXEMPLARY, OR CONSEQUENTIAL DAMAGES OR OTHER LIABILITY, WHETHER IN AN + ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS WITH THE + SOFTWARE. +*/ + +/* PFFFT : a Pretty Fast FFT. + * + * This is basically an adaptation of the single precision fftpack (v4) as + * found on netlib taking advantage of SIMD instructions found on CPUs such as + * Intel x86 (SSE1), PowerPC (Altivec), and Arm (NEON). + * + * For architectures where SIMD instructions aren't available, the code falls + * back to a scalar version. + * + * Restrictions: + * + * - 1D transforms only, with 32-bit single precision. + * + * - supports only transforms for inputs of length N of the form + * N=(2^a)*(3^b)*(5^c), given a >= 5, b >=0, c >= 0 (32, 48, 64, 96, 128, 144, + * 160, etc are all acceptable lengths). Performance is best for 128<=N<=8192. + * + * - all (float*) pointers for the functions below are expected to have a + * "SIMD-compatible" alignment, that is 16 bytes. + * + * You can allocate such buffers with the pffft_aligned_malloc function, and + * deallocate them with pffft_aligned_free (or with stuff like posix_memalign, + * aligned_alloc, etc). + * + * Note that for the z-domain data of real transforms, when in the canonical + * order (as interleaved complex numbers) both 0-frequency and half-frequency + * components, which are real, are assembled in the first entry as + * F(0)+i*F(n/2+1). The original fftpack placed F(n/2+1) at the end of the + * arrays instead. + */ + +#ifndef PFFFT_H +#define PFFFT_H + +#include +#include + +#include "almalloc.h" + + +/* opaque struct holding internal stuff (precomputed twiddle factors) this + * struct can be shared by many threads as it contains only read-only data. + */ +struct PFFFT_Setup; + +/* direction of the transform */ +enum pffft_direction_t { PFFFT_FORWARD, PFFFT_BACKWARD }; + +/* type of transform */ +enum pffft_transform_t { PFFFT_REAL, PFFFT_COMPLEX }; + +struct PFFFTSetupDeleter { + void operator()(gsl::owner setup) const noexcept; +}; +using PFFFTSetupPtr = std::unique_ptr; + +/** + * Prepare for performing transforms of size N -- the returned PFFFT_Setup + * structure is read-only so it can safely be shared by multiple concurrent + * threads. + */ +PFFFTSetupPtr pffft_new_setup(unsigned int N, pffft_transform_t transform); + +/** + * Perform a Fourier transform. The z-domain data is stored in the most + * efficient order for transforming back or using for convolution, and as + * such, there's no guarantee to the order of the values. If you need to have + * its content sorted in the usual way, that is as an array of interleaved + * complex numbers, either use pffft_transform_ordered, or call pffft_zreorder + * after the forward fft and before the backward fft. + * + * Transforms are not scaled: PFFFT_BACKWARD(PFFFT_FORWARD(x)) = N*x. Typically + * you will want to scale the backward transform by 1/N. + * + * The 'work' pointer must point to an area of N (2*N for complex fft) floats, + * properly aligned. It cannot be NULL. + * + * The input and output parameters may alias. + */ +void pffft_transform(const PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); + +/** + * Similar to pffft_transform, but handles the complex values in the usual form + * (interleaved complex numbers). This is similar to calling + * pffft_transform(..., PFFFT_FORWARD) followed by + * pffft_zreorder(..., PFFFT_FORWARD), or + * pffft_zreorder(..., PFFFT_BACKWARD) followed by + * pffft_transform(..., PFFFT_BACKWARD), for the given direction. + * + * The input and output parameters may alias. + */ +void pffft_transform_ordered(const PFFFT_Setup *setup, const float *input, float *output, float *work, pffft_direction_t direction); + +/** + * Reorder the z-domain data. For PFFFT_FORWARD, it reorders from the internal + * representation to the "canonical" order (as interleaved complex numbers). + * For PFFFT_BACKWARD, it reorders from the canonical order to the internal + * order suitable for pffft_transform(..., PFFFT_BACKWARD) or + * pffft_zconvolve_accumulate. + * + * The input and output parameters should not alias. + */ +void pffft_zreorder(const PFFFT_Setup *setup, const float *input, float *output, pffft_direction_t direction); + +/** + * Perform a multiplication of the z-domain data in dft_a and dft_b, and scale + * and accumulate into dft_ab. The arrays should have been obtained with + * pffft_transform(..., PFFFT_FORWARD) or pffft_zreorder(..., PFFFT_BACKWARD) + * and should *not* be in the usual order (otherwise just perform the operation + * yourself as the dft coeffs are stored as interleaved complex numbers). + * + * The operation performed is: dft_ab += (dft_a * dft_b)*scaling + * + * The dft_a, dft_b, and dft_ab parameters may alias. + */ +void pffft_zconvolve_scale_accumulate(const PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab, float scaling); + +/** + * Perform a multiplication of the z-domain data in dft_a and dft_b, and + * accumulate into dft_ab. + * + * The operation performed is: dft_ab += dft_a * dft_b + * + * The dft_a, dft_b, and dft_ab parameters may alias. + */ +void pffft_zconvolve_accumulate(const PFFFT_Setup *setup, const float *dft_a, const float *dft_b, float *dft_ab); + + +struct PFFFTSetup { + PFFFTSetupPtr mSetup; + + PFFFTSetup() = default; + PFFFTSetup(const PFFFTSetup&) = delete; + PFFFTSetup(PFFFTSetup&& rhs) noexcept = default; + explicit PFFFTSetup(std::nullptr_t) noexcept { } + explicit PFFFTSetup(unsigned int n, pffft_transform_t transform) + : mSetup{pffft_new_setup(n, transform)} + { } + ~PFFFTSetup() = default; + + PFFFTSetup& operator=(const PFFFTSetup&) = delete; + PFFFTSetup& operator=(PFFFTSetup&& rhs) noexcept = default; + + [[nodiscard]] explicit operator bool() const noexcept { return mSetup != nullptr; } + + void transform(const float *input, float *output, float *work, pffft_direction_t direction) const + { pffft_transform(mSetup.get(), input, output, work, direction); } + + void transform_ordered(const float *input, float *output, float *work, + pffft_direction_t direction) const + { pffft_transform_ordered(mSetup.get(), input, output, work, direction); } + + void zreorder(const float *input, float *output, pffft_direction_t direction) const + { pffft_zreorder(mSetup.get(), input, output, direction); } + + void zconvolve_scale_accumulate(const float *dft_a, const float *dft_b, float *dft_ab, + float scaling) const + { pffft_zconvolve_scale_accumulate(mSetup.get(), dft_a, dft_b, dft_ab, scaling); } + + void zconvolve_accumulate(const float *dft_a, const float *dft_b, float *dft_ab) const + { pffft_zconvolve_accumulate(mSetup.get(), dft_a, dft_b, dft_ab); } +}; + +#endif // PFFFT_H diff --git a/3rdparty/openal/common/phase_shifter.h b/3rdparty/openal/common/phase_shifter.h index 061e91769813..b06e9275771a 100644 --- a/3rdparty/openal/common/phase_shifter.h +++ b/3rdparty/openal/common/phase_shifter.h @@ -1,106 +1,59 @@ #ifndef PHASE_SHIFTER_H #define PHASE_SHIFTER_H -#ifdef HAVE_SSE_INTRINSICS +#include "config_simd.h" + +#if HAVE_SSE_INTRINSICS #include -#elif defined(HAVE_NEON) +#elif HAVE_NEON #include #endif #include -#include +#include +#include -#include "alcomplex.h" +#include "alnumbers.h" #include "alspan.h" +#include "opthelpers.h" /* Implements a wide-band +90 degree phase-shift. Note that this should be * given one sample less of a delay (FilterSize/2 - 1) compared to the direct * signal delay (FilterSize/2) to properly align. */ -template -struct PhaseShifterT { +template +struct SIMDALIGN PhaseShifterT { static_assert(FilterSize >= 16, "FilterSize needs to be at least 16"); static_assert((FilterSize&(FilterSize-1)) == 0, "FilterSize needs to be power-of-two"); alignas(16) std::array mCoeffs{}; - /* Some notes on this filter construction. - * - * A wide-band phase-shift filter needs a delay to maintain linearity. A - * dirac impulse in the center of a time-domain buffer represents a filter - * passing all frequencies through as-is with a pure delay. Converting that - * to the frequency domain, adjusting the phase of each frequency bin by - * +90 degrees, then converting back to the time domain, results in a FIR - * filter that applies a +90 degree wide-band phase-shift. - * - * A particularly notable aspect of the time-domain filter response is that - * every other coefficient is 0. This allows doubling the effective size of - * the filter, by storing only the non-0 coefficients and double-stepping - * over the input to apply it. - * - * Additionally, the resulting filter is independent of the sample rate. - * The same filter can be applied regardless of the device's sample rate - * and achieve the same effect. - */ PhaseShifterT() { - using complex_d = std::complex; - constexpr size_t fft_size{FilterSize}; - constexpr size_t half_size{fft_size / 2}; - - auto fftBuffer = std::make_unique(fft_size); - std::fill_n(fftBuffer.get(), fft_size, complex_d{}); - fftBuffer[half_size] = 1.0; - - forward_fft(al::span{fftBuffer.get(), fft_size}); - for(size_t i{0};i < half_size+1;++i) - fftBuffer[i] = complex_d{-fftBuffer[i].imag(), fftBuffer[i].real()}; - for(size_t i{half_size+1};i < fft_size;++i) - fftBuffer[i] = std::conj(fftBuffer[fft_size - i]); - inverse_fft(al::span{fftBuffer.get(), fft_size}); - - auto fftiter = fftBuffer.get() + half_size + (FilterSize/2 - 1); - for(float &coeff : mCoeffs) + /* Every other coefficient is 0, so we only need to calculate and store + * the non-0 terms and double-step over the input to apply it. The + * calculated coefficients are in reverse to make applying in the time- + * domain more efficient. + */ + for(std::size_t i{0};i < FilterSize/2;++i) { - coeff = static_cast(fftiter->real() / double{fft_size}); - fftiter -= 2; + const auto k = static_cast(i*2 + 1) - int{FilterSize/2}; + + /* Calculate the Blackman window value for this coefficient. */ + const auto w = 2.0*al::numbers::pi/double{FilterSize} * static_cast(i*2 + 1); + const auto window = 0.3635819 - 0.4891775*std::cos(w) + 0.1365995*std::cos(2.0*w) + - 0.0106411*std::cos(3.0*w); + + const auto pk = al::numbers::pi * static_cast(k); + mCoeffs[i] = static_cast(window * (1.0-std::cos(pk)) / pk); } } - void process(al::span dst, const float *RESTRICT src) const; + void process(const al::span dst, const al::span src) const; private: -#if defined(HAVE_NEON) - /* There doesn't seem to be NEON intrinsics to do this kind of stipple - * shuffling, so there's two custom methods for it. - */ - static auto shuffle_2020(float32x4_t a, float32x4_t b) - { - float32x4_t ret{vmovq_n_f32(vgetq_lane_f32(a, 0))}; - ret = vsetq_lane_f32(vgetq_lane_f32(a, 2), ret, 1); - ret = vsetq_lane_f32(vgetq_lane_f32(b, 0), ret, 2); - ret = vsetq_lane_f32(vgetq_lane_f32(b, 2), ret, 3); - return ret; - } - static auto shuffle_3131(float32x4_t a, float32x4_t b) - { - float32x4_t ret{vmovq_n_f32(vgetq_lane_f32(a, 1))}; - ret = vsetq_lane_f32(vgetq_lane_f32(a, 3), ret, 1); - ret = vsetq_lane_f32(vgetq_lane_f32(b, 1), ret, 2); - ret = vsetq_lane_f32(vgetq_lane_f32(b, 3), ret, 3); - return ret; - } - static auto unpacklo(float32x4_t a, float32x4_t b) - { - float32x2x2_t result{vzip_f32(vget_low_f32(a), vget_low_f32(b))}; - return vcombine_f32(result.val[0], result.val[1]); - } - static auto unpackhi(float32x4_t a, float32x4_t b) - { - float32x2x2_t result{vzip_f32(vget_high_f32(a), vget_high_f32(b))}; - return vcombine_f32(result.val[0], result.val[1]); - } +#if HAVE_NEON static auto load4(float32_t a, float32_t b, float32_t c, float32_t d) { float32x4_t ret{vmovq_n_f32(a)}; @@ -109,105 +62,141 @@ struct PhaseShifterT { ret = vsetq_lane_f32(d, ret, 3); return ret; } + static void vtranspose4(float32x4_t &x0, float32x4_t &x1, float32x4_t &x2, float32x4_t &x3) + { + float32x4x2_t t0_{vzipq_f32(x0, x2)}; + float32x4x2_t t1_{vzipq_f32(x1, x3)}; + float32x4x2_t u0_{vzipq_f32(t0_.val[0], t1_.val[0])}; + float32x4x2_t u1_{vzipq_f32(t0_.val[1], t1_.val[1])}; + x0 = u0_.val[0]; + x1 = u0_.val[1]; + x2 = u1_.val[0]; + x3 = u1_.val[1]; + } #endif }; -template -inline void PhaseShifterT::process(al::span dst, const float *RESTRICT src) const +template +NOINLINE inline +void PhaseShifterT::process(const al::span dst, const al::span src) const { -#ifdef HAVE_SSE_INTRINSICS - if(size_t todo{dst.size()>>1}) + auto in = src.begin(); +#if HAVE_SSE_INTRINSICS + if(const std::size_t todo{dst.size()>>2}) { - auto *out = reinterpret_cast<__m64*>(dst.data()); - do { - __m128 r04{_mm_setzero_ps()}; - __m128 r14{_mm_setzero_ps()}; - for(size_t j{0};j < mCoeffs.size();j+=4) + auto out = al::span{reinterpret_cast<__m128*>(dst.data()), todo}; + std::generate(out.begin(), out.end(), [&in,this] + { + __m128 r0{_mm_setzero_ps()}; + __m128 r1{_mm_setzero_ps()}; + __m128 r2{_mm_setzero_ps()}; + __m128 r3{_mm_setzero_ps()}; + for(std::size_t j{0};j < mCoeffs.size();j+=4) { const __m128 coeffs{_mm_load_ps(&mCoeffs[j])}; - const __m128 s0{_mm_loadu_ps(&src[j*2])}; - const __m128 s1{_mm_loadu_ps(&src[j*2 + 4])}; + const __m128 s0{_mm_loadu_ps(&in[j*2])}; + const __m128 s1{_mm_loadu_ps(&in[j*2 + 4])}; + const __m128 s2{_mm_movehl_ps(_mm_movelh_ps(s1, s1), s0)}; + const __m128 s3{_mm_loadh_pi(_mm_movehl_ps(s1, s1), + reinterpret_cast(&in[j*2 + 8]))}; __m128 s{_mm_shuffle_ps(s0, s1, _MM_SHUFFLE(2, 0, 2, 0))}; - r04 = _mm_add_ps(r04, _mm_mul_ps(s, coeffs)); + r0 = _mm_add_ps(r0, _mm_mul_ps(s, coeffs)); s = _mm_shuffle_ps(s0, s1, _MM_SHUFFLE(3, 1, 3, 1)); - r14 = _mm_add_ps(r14, _mm_mul_ps(s, coeffs)); - } - src += 2; + r1 = _mm_add_ps(r1, _mm_mul_ps(s, coeffs)); - __m128 r4{_mm_add_ps(_mm_unpackhi_ps(r04, r14), _mm_unpacklo_ps(r04, r14))}; - r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); + s = _mm_shuffle_ps(s2, s3, _MM_SHUFFLE(2, 0, 2, 0)); + r2 = _mm_add_ps(r2, _mm_mul_ps(s, coeffs)); - _mm_storel_pi(out, r4); - ++out; - } while(--todo); + s = _mm_shuffle_ps(s2, s3, _MM_SHUFFLE(3, 1, 3, 1)); + r3 = _mm_add_ps(r3, _mm_mul_ps(s, coeffs)); + } + in += 4; + + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + return _mm_add_ps(_mm_add_ps(r0, r1), _mm_add_ps(r2, r3)); + }); } - if((dst.size()&1)) + if(const std::size_t todo{dst.size()&3}) { - __m128 r4{_mm_setzero_ps()}; - for(size_t j{0};j < mCoeffs.size();j+=4) + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&in,this] { - const __m128 coeffs{_mm_load_ps(&mCoeffs[j])}; - const __m128 s{_mm_setr_ps(src[j*2], src[j*2 + 2], src[j*2 + 4], src[j*2 + 6])}; - r4 = _mm_add_ps(r4, _mm_mul_ps(s, coeffs)); - } - r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); - r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); - - dst.back() = _mm_cvtss_f32(r4); + __m128 r4{_mm_setzero_ps()}; + for(std::size_t j{0};j < mCoeffs.size();j+=4) + { + const __m128 coeffs{_mm_load_ps(&mCoeffs[j])}; + const __m128 s{_mm_setr_ps(in[j*2], in[j*2 + 2], in[j*2 + 4], in[j*2 + 6])}; + r4 = _mm_add_ps(r4, _mm_mul_ps(s, coeffs)); + } + ++in; + r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); + r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); + return _mm_cvtss_f32(r4); + }); } -#elif defined(HAVE_NEON) +#elif HAVE_NEON - size_t pos{0}; - if(size_t todo{dst.size()>>1}) + if(const std::size_t todo{dst.size()>>2}) { - do { - float32x4_t r04{vdupq_n_f32(0.0f)}; - float32x4_t r14{vdupq_n_f32(0.0f)}; - for(size_t j{0};j < mCoeffs.size();j+=4) + auto out = al::span{reinterpret_cast(dst.data()), todo}; + std::generate(out.begin(), out.end(), [&in,this] + { + float32x4_t r0{vdupq_n_f32(0.0f)}; + float32x4_t r1{vdupq_n_f32(0.0f)}; + float32x4_t r2{vdupq_n_f32(0.0f)}; + float32x4_t r3{vdupq_n_f32(0.0f)}; + for(std::size_t j{0};j < mCoeffs.size();j+=4) { const float32x4_t coeffs{vld1q_f32(&mCoeffs[j])}; - const float32x4_t s0{vld1q_f32(&src[j*2])}; - const float32x4_t s1{vld1q_f32(&src[j*2 + 4])}; - - r04 = vmlaq_f32(r04, shuffle_2020(s0, s1), coeffs); - r14 = vmlaq_f32(r14, shuffle_3131(s0, s1), coeffs); + const float32x4_t s0{vld1q_f32(&in[j*2])}; + const float32x4_t s1{vld1q_f32(&in[j*2 + 4])}; + const float32x4_t s2{vcombine_f32(vget_high_f32(s0), vget_low_f32(s1))}; + const float32x4_t s3{vcombine_f32(vget_high_f32(s1), vld1_f32(&in[j*2 + 8]))}; + const float32x4x2_t values0{vuzpq_f32(s0, s1)}; + const float32x4x2_t values1{vuzpq_f32(s2, s3)}; + + r0 = vmlaq_f32(r0, values0.val[0], coeffs); + r1 = vmlaq_f32(r1, values0.val[1], coeffs); + r2 = vmlaq_f32(r2, values1.val[0], coeffs); + r3 = vmlaq_f32(r3, values1.val[1], coeffs); } - src += 2; - - float32x4_t r4{vaddq_f32(unpackhi(r04, r14), unpacklo(r04, r14))}; - float32x2_t r2{vadd_f32(vget_low_f32(r4), vget_high_f32(r4))}; + in += 4; - vst1_f32(&dst[pos], r2); - pos += 2; - } while(--todo); + vtranspose4(r0, r1, r2, r3); + return vaddq_f32(vaddq_f32(r0, r1), vaddq_f32(r2, r3)); + }); } - if((dst.size()&1)) + if(const std::size_t todo{dst.size()&3}) { - float32x4_t r4{vdupq_n_f32(0.0f)}; - for(size_t j{0};j < mCoeffs.size();j+=4) + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&in,this] { - const float32x4_t coeffs{vld1q_f32(&mCoeffs[j])}; - const float32x4_t s{load4(src[j*2], src[j*2 + 2], src[j*2 + 4], src[j*2 + 6])}; - r4 = vmlaq_f32(r4, s, coeffs); - } - r4 = vaddq_f32(r4, vrev64q_f32(r4)); - dst[pos] = vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + float32x4_t r4{vdupq_n_f32(0.0f)}; + for(std::size_t j{0};j < mCoeffs.size();j+=4) + { + const float32x4_t coeffs{vld1q_f32(&mCoeffs[j])}; + const float32x4_t s{load4(in[j*2], in[j*2 + 2], in[j*2 + 4], in[j*2 + 6])}; + r4 = vmlaq_f32(r4, s, coeffs); + } + ++in; + r4 = vaddq_f32(r4, vrev64q_f32(r4)); + return vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + }); } #else - for(float &output : dst) + std::generate(dst.begin(), dst.end(), [&in,this] { float ret{0.0f}; - for(size_t j{0};j < mCoeffs.size();++j) - ret += src[j*2] * mCoeffs[j]; - - output = ret; - ++src; - } + for(std::size_t j{0};j < mCoeffs.size();++j) + ret += in[j*2] * mCoeffs[j]; + ++in; + return ret; + }); #endif } diff --git a/3rdparty/openal/common/polyphase_resampler.cpp b/3rdparty/openal/common/polyphase_resampler.cpp index 14f7e40d877a..d9f727ef9b39 100644 --- a/3rdparty/openal/common/polyphase_resampler.cpp +++ b/3rdparty/openal/common/polyphase_resampler.cpp @@ -3,45 +3,46 @@ #include #include +#include +#include +#include #include "alnumbers.h" #include "opthelpers.h" +using uint = unsigned int; + namespace { constexpr double Epsilon{1e-9}; -using uint = unsigned int; - -/* This is the normalized cardinal sine (sinc) function. - * - * sinc(x) = { 1, x = 0 - * { sin(pi x) / (pi x), otherwise. - */ -double Sinc(const double x) -{ - if(std::abs(x) < Epsilon) UNLIKELY - return 1.0; - return std::sin(al::numbers::pi*x) / (al::numbers::pi*x); -} /* The zero-order modified Bessel function of the first kind, used for the * Kaiser window. * * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k) * = sum_{k=0}^inf ((x / 2)^k / k!)^2 + * + * This implementation only handles nu = 0, and isn't the most precise (it + * starts with the largest value and accumulates successively smaller values, + * compounding the rounding and precision error), but it's good enough. */ -constexpr double BesselI_0(const double x) +template +constexpr auto cyl_bessel_i(T nu, U x) -> U { - // Start at k=1 since k=0 is trivial. + if(nu != T{0}) + throw std::runtime_error{"cyl_bessel_i: nu != 0"}; + + /* Start at k=1 since k=0 is trivial. */ const double x2{x/2.0}; double term{1.0}; double sum{1.0}; int k{1}; - // Let the integration converge until the term of the sum is no longer - // significant. + /* Let the integration converge until the term of the sum is no longer + * significant. + */ double last_sum{}; do { const double y{x2 / k}; @@ -50,7 +51,19 @@ constexpr double BesselI_0(const double x) term *= y * y; sum += term; } while(sum != last_sum); - return sum; + return static_cast(sum); +} + +/* This is the normalized cardinal sine (sinc) function. + * + * sinc(x) = { 1, x = 0 + * { sin(pi x) / (pi x), otherwise. + */ +double Sinc(const double x) +{ + if(std::abs(x) < Epsilon) UNLIKELY + return 1.0; + return std::sin(al::numbers::pi*x) / (al::numbers::pi*x); } /* Calculate a Kaiser window from the given beta value and a normalized k @@ -67,23 +80,11 @@ constexpr double BesselI_0(const double x) * * k = 2 i / M - 1, where 0 <= i <= M. */ -double Kaiser(const double b, const double k) +double Kaiser(const double beta, const double k, const double besseli_0_beta) { if(!(k >= -1.0 && k <= 1.0)) return 0.0; - return BesselI_0(b * std::sqrt(1.0 - k*k)) / BesselI_0(b); -} - -// Calculates the greatest common divisor of a and b. -constexpr uint Gcd(uint x, uint y) -{ - while(y > 0) - { - const uint z{y}; - y = x % y; - x = z; - } - return x; + return ::cyl_bessel_i(0, beta * std::sqrt(1.0 - k*k)) / besseli_0_beta; } /* Calculates the size (order) of the Kaiser window. Rejection is in dB and @@ -124,11 +125,11 @@ constexpr double CalcKaiserBeta(const double rejection) * p -- gain compensation factor when sampling * f_t -- normalized center frequency (or cutoff; 0.5 is nyquist) */ -double SincFilter(const uint l, const double b, const double gain, const double cutoff, - const uint i) +auto SincFilter(const uint l, const double beta, const double besseli_0_beta, const double gain, + const double cutoff, const uint i) -> double { - const double x{static_cast(i) - l}; - return Kaiser(b, x / l) * 2.0 * gain * cutoff * Sinc(2.0 * cutoff * x); + const auto x = static_cast(i) - l; + return Kaiser(beta, x/l, besseli_0_beta) * 2.0 * gain * cutoff * Sinc(2.0 * cutoff * x); } } // namespace @@ -137,86 +138,84 @@ double SincFilter(const uint l, const double b, const double gain, const double // that's used to cut frequencies above the destination nyquist. void PPhaseResampler::init(const uint srcRate, const uint dstRate) { - const uint gcd{Gcd(srcRate, dstRate)}; + const auto gcd = std::gcd(srcRate, dstRate); mP = dstRate / gcd; mQ = srcRate / gcd; - /* The cutoff is adjusted by half the transition width, so the transition - * ends before the nyquist (0.5). Both are scaled by the downsampling - * factor. + /* The cutoff is adjusted by the transition width, so the transition ends + * at nyquist (0.5). Both are scaled by the downsampling factor. */ - double cutoff, width; - if(mP > mQ) - { - cutoff = 0.475 / mP; - width = 0.05 / mP; - } - else - { - cutoff = 0.475 / mQ; - width = 0.05 / mQ; - } + const auto [cutoff, width] = (mP > mQ) ? std::make_tuple(0.47 / mP, 0.03 / mP) + : std::make_tuple(0.47 / mQ, 0.03 / mQ); + // A rejection of -180 dB is used for the stop band. Round up when // calculating the left offset to avoid increasing the transition width. - const uint l{(CalcKaiserOrder(180.0, width)+1) / 2}; - const double beta{CalcKaiserBeta(180.0)}; - mM = l*2 + 1; + static constexpr auto rejection = 180.0; + const auto l = (CalcKaiserOrder(rejection, width)+1u) / 2u; + const auto beta = CalcKaiserBeta(rejection); + const auto besseli_0_beta = ::cyl_bessel_i(0, beta); + mM = l*2u + 1u; mL = l; mF.resize(mM); for(uint i{0};i < mM;i++) - mF[i] = SincFilter(l, beta, mP, cutoff, i); + mF[i] = SincFilter(mL, beta, besseli_0_beta, mP, cutoff, i); } // Perform the upsample-filter-downsample resampling operation using a // polyphase filter implementation. -void PPhaseResampler::process(const uint inN, const double *in, const uint outN, double *out) +void PPhaseResampler::process(const al::span in, const al::span out) const { - if(outN == 0) UNLIKELY + if(out.empty()) UNLIKELY return; // Handle in-place operation. - std::vector workspace; - double *work{out}; - if(work == in) UNLIKELY + auto workspace = std::vector{}; + auto work = al::span{out}; + if(work.data() == in.data()) UNLIKELY { - workspace.resize(outN); - work = workspace.data(); + workspace.resize(out.size()); + work = workspace; } - // Resample the input. - const uint p{mP}, q{mQ}, m{mM}, l{mL}; - const double *f{mF.data()}; - for(uint i{0};i < outN;i++) + const auto f = al::span{mF}; + const auto p = size_t{mP}; + const auto q = size_t{mQ}; + const auto m = size_t{mM}; + /* Input starts at l to compensate for the filter delay. This will drop any + * build-up from the first half of the filter. + */ + auto l = size_t{mL}; + std::generate(work.begin(), work.end(), [in,f,p,q,m,&l] { - // Input starts at l to compensate for the filter delay. This will - // drop any build-up from the first half of the filter. - size_t j_f{(l + q*i) % p}; - size_t j_s{(l + q*i) / p}; - - // Only take input when 0 <= j_s < inN. - double r{0.0}; - if(j_f < m) LIKELY + auto j_s = l / p; + auto j_f = l % p; + l += q; + + // Only take input when 0 <= j_s < in.size(). + if(j_f >= m) UNLIKELY + return 0.0; + + auto filt_len = (m - j_f - 1)/p + 1; + if(j_s+1 > in.size()) LIKELY { - size_t filt_len{(m-j_f+p-1) / p}; - if(j_s+1 > inN) LIKELY - { - size_t skip{std::min(j_s+1 - inN, filt_len)}; - j_f += p*skip; - j_s -= skip; - filt_len -= skip; - } - if(size_t todo{std::min(j_s+1, filt_len)}) LIKELY - { - do { - r += f[j_f] * in[j_s]; - j_f += p; - --j_s; - } while(--todo); - } + const auto skip = std::min(j_s+1-in.size(), filt_len); + j_f += p*skip; + j_s -= skip; + filt_len -= skip; } - work[i] = r; - } + /* Get the range of input samples being used for this output sample. + * j_s is the first sample and iterates backwards toward 0. + */ + const auto src = in.first(j_s+1).last(std::min(j_s+1, filt_len)); + return std::accumulate(src.rbegin(), src.rend(), 0.0, [p,f,&j_f](const double cur, + const double smp) -> double + { + const auto ret = cur + f[j_f]*smp; + j_f += p; + return ret; + }); + }); // Clean up after in-place operation. - if(work != out) - std::copy_n(work, outN, out); + if(work.data() != out.data()) + std::copy(work.cbegin(), work.cend(), out.begin()); } diff --git a/3rdparty/openal/common/polyphase_resampler.h b/3rdparty/openal/common/polyphase_resampler.h index 557485bb2f61..53fb6f81cf66 100644 --- a/3rdparty/openal/common/polyphase_resampler.h +++ b/3rdparty/openal/common/polyphase_resampler.h @@ -3,6 +3,8 @@ #include +#include "alspan.h" + using uint = unsigned int; @@ -35,12 +37,12 @@ using uint = unsigned int; struct PPhaseResampler { void init(const uint srcRate, const uint dstRate); - void process(const uint inN, const double *in, const uint outN, double *out); + void process(const al::span in, const al::span out) const; explicit operator bool() const noexcept { return !mF.empty(); } private: - uint mP, mQ, mM, mL; + uint mP{}, mQ{}, mM{}, mL{}; std::vector mF; }; diff --git a/3rdparty/openal/common/ringbuffer.cpp b/3rdparty/openal/common/ringbuffer.cpp index af1f36695e93..23c48806a6cd 100644 --- a/3rdparty/openal/common/ringbuffer.cpp +++ b/3rdparty/openal/common/ringbuffer.cpp @@ -23,201 +23,151 @@ #include "ringbuffer.h" #include -#include +#include +#include +#include #include -#include "almalloc.h" +#include "alnumeric.h" +#include "alspan.h" -RingBufferPtr RingBuffer::Create(std::size_t sz, std::size_t elem_sz, int limit_writes) +auto RingBuffer::Create(std::size_t sz, std::size_t elem_sz, bool limit_writes) -> RingBufferPtr { std::size_t power_of_two{0u}; if(sz > 0) { - power_of_two = sz; + power_of_two = sz - 1; power_of_two |= power_of_two>>1; power_of_two |= power_of_two>>2; power_of_two |= power_of_two>>4; power_of_two |= power_of_two>>8; power_of_two |= power_of_two>>16; - if constexpr(SIZE_MAX > UINT_MAX) + if constexpr(sizeof(size_t) > sizeof(uint32_t)) power_of_two |= power_of_two>>32; } ++power_of_two; - if(power_of_two <= sz || power_of_two > std::numeric_limits::max()/elem_sz) + if(power_of_two < sz || power_of_two > std::numeric_limits::max()>>1 + || power_of_two > std::numeric_limits::max()/elem_sz) throw std::overflow_error{"Ring buffer size overflow"}; const std::size_t bufbytes{power_of_two * elem_sz}; - RingBufferPtr rb{new(FamCount(bufbytes)) RingBuffer{bufbytes}}; - rb->mWriteSize = limit_writes ? sz : (power_of_two-1); - rb->mSizeMask = power_of_two - 1; - rb->mElemSize = elem_sz; + RingBufferPtr rb{new(FamCount(bufbytes)) RingBuffer{limit_writes ? sz : power_of_two, + power_of_two-1, elem_sz, bufbytes}}; return rb; } void RingBuffer::reset() noexcept { - mWritePtr.store(0, std::memory_order_relaxed); - mReadPtr.store(0, std::memory_order_relaxed); + mWriteCount.store(0, std::memory_order_relaxed); + mReadCount.store(0, std::memory_order_relaxed); std::fill_n(mBuffer.begin(), (mSizeMask+1)*mElemSize, std::byte{}); } -std::size_t RingBuffer::read(void *dest, std::size_t cnt) noexcept +auto RingBuffer::read(void *dest, std::size_t count) noexcept -> std::size_t { - const std::size_t free_cnt{readSpace()}; - if(free_cnt == 0) return 0; + const std::size_t w{mWriteCount.load(std::memory_order_acquire)}; + const std::size_t r{mReadCount.load(std::memory_order_relaxed)}; + const std::size_t readable{w - r}; + if(readable == 0) return 0; - const std::size_t to_read{std::min(cnt, free_cnt)}; - std::size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_read{std::min(count, readable)}; + const std::size_t read_idx{r & mSizeMask}; - std::size_t n1, n2; - const std::size_t cnt2{read_ptr + to_read}; - if(cnt2 > mSizeMask+1) - { - n1 = mSizeMask+1 - read_ptr; - n2 = cnt2 & mSizeMask; - } - else - { - n1 = to_read; - n2 = 0; - } + const std::size_t rdend{read_idx + to_read}; + const auto [n1, n2] = (rdend <= mSizeMask+1) ? std::array{to_read, 0_uz} + : std::array{mSizeMask+1 - read_idx, rdend&mSizeMask}; - auto outiter = std::copy_n(mBuffer.begin() + read_ptr*mElemSize, n1*mElemSize, - static_cast(dest)); - read_ptr += n1; + auto dstbytes = al::span{static_cast(dest), count*mElemSize}; + auto outiter = std::copy_n(mBuffer.begin() + ptrdiff_t(read_idx*mElemSize), n1*mElemSize, + dstbytes.begin()); if(n2 > 0) - { std::copy_n(mBuffer.begin(), n2*mElemSize, outiter); - read_ptr += n2; - } - mReadPtr.store(read_ptr, std::memory_order_release); + mReadCount.store(r+n1+n2, std::memory_order_release); return to_read; } -std::size_t RingBuffer::peek(void *dest, std::size_t cnt) const noexcept +auto RingBuffer::peek(void *dest, std::size_t count) const noexcept -> std::size_t { - const std::size_t free_cnt{readSpace()}; - if(free_cnt == 0) return 0; + const std::size_t w{mWriteCount.load(std::memory_order_acquire)}; + const std::size_t r{mReadCount.load(std::memory_order_relaxed)}; + const std::size_t readable{w - r}; + if(readable == 0) return 0; - const std::size_t to_read{std::min(cnt, free_cnt)}; - std::size_t read_ptr{mReadPtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_read{std::min(count, readable)}; + const std::size_t read_idx{r & mSizeMask}; - std::size_t n1, n2; - const std::size_t cnt2{read_ptr + to_read}; - if(cnt2 > mSizeMask+1) - { - n1 = mSizeMask+1 - read_ptr; - n2 = cnt2 & mSizeMask; - } - else - { - n1 = to_read; - n2 = 0; - } + const std::size_t rdend{read_idx + to_read}; + const auto [n1, n2] = (rdend <= mSizeMask+1) ? std::array{to_read, 0_uz} + : std::array{mSizeMask+1 - read_idx, rdend&mSizeMask}; - auto outiter = std::copy_n(mBuffer.begin() + read_ptr*mElemSize, n1*mElemSize, - static_cast(dest)); + auto dstbytes = al::span{static_cast(dest), count*mElemSize}; + auto outiter = std::copy_n(mBuffer.begin() + ptrdiff_t(read_idx*mElemSize), n1*mElemSize, + dstbytes.begin()); if(n2 > 0) std::copy_n(mBuffer.begin(), n2*mElemSize, outiter); return to_read; } -std::size_t RingBuffer::write(const void *src, std::size_t cnt) noexcept +auto RingBuffer::write(const void *src, std::size_t count) noexcept -> std::size_t { - const std::size_t free_cnt{writeSpace()}; - if(free_cnt == 0) return 0; + const std::size_t w{mWriteCount.load(std::memory_order_relaxed)}; + const std::size_t r{mReadCount.load(std::memory_order_acquire)}; + const std::size_t writable{mWriteSize - (w - r)}; + if(writable == 0) return 0; - const std::size_t to_write{std::min(cnt, free_cnt)}; - std::size_t write_ptr{mWritePtr.load(std::memory_order_relaxed) & mSizeMask}; + const std::size_t to_write{std::min(count, writable)}; + const std::size_t write_idx{w & mSizeMask}; - std::size_t n1, n2; - const std::size_t cnt2{write_ptr + to_write}; - if(cnt2 > mSizeMask+1) - { - n1 = mSizeMask+1 - write_ptr; - n2 = cnt2 & mSizeMask; - } - else - { - n1 = to_write; - n2 = 0; - } + const std::size_t wrend{write_idx + to_write}; + const auto [n1, n2] = (wrend <= mSizeMask+1) ? std::array{to_write, 0_uz} + : std::array{mSizeMask+1 - write_idx, wrend&mSizeMask}; - auto srcbytes = static_cast(src); - std::copy_n(srcbytes, n1*mElemSize, mBuffer.begin() + write_ptr*mElemSize); - write_ptr += n1; + auto srcbytes = al::span{static_cast(src), count*mElemSize}; + std::copy_n(srcbytes.cbegin(), n1*mElemSize, mBuffer.begin() + ptrdiff_t(write_idx*mElemSize)); if(n2 > 0) - { - std::copy_n(srcbytes + n1*mElemSize, n2*mElemSize, mBuffer.begin()); - write_ptr += n2; - } - mWritePtr.store(write_ptr, std::memory_order_release); + std::copy_n(srcbytes.cbegin() + ptrdiff_t(n1*mElemSize), n2*mElemSize, mBuffer.begin()); + mWriteCount.store(w+n1+n2, std::memory_order_release); return to_write; } -auto RingBuffer::getReadVector() const noexcept -> DataPair +auto RingBuffer::getReadVector() noexcept -> DataPair { - DataPair ret; - - std::size_t w{mWritePtr.load(std::memory_order_acquire)}; - std::size_t r{mReadPtr.load(std::memory_order_acquire)}; - w &= mSizeMask; - r &= mSizeMask; - const std::size_t free_cnt{(w-r) & mSizeMask}; + const std::size_t w{mWriteCount.load(std::memory_order_acquire)}; + const std::size_t r{mReadCount.load(std::memory_order_relaxed)}; + const std::size_t readable{w - r}; + const std::size_t read_idx{r & mSizeMask}; - const std::size_t cnt2{r + free_cnt}; - if(cnt2 > mSizeMask+1) + const std::size_t rdend{read_idx + readable}; + if(rdend > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current read ptr, - * plus some from the start of the buffer. */ - ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); - ret.first.len = mSizeMask+1 - r; - ret.second.buf = const_cast(mBuffer.data()); - ret.second.len = cnt2 & mSizeMask; - } - else - { - /* Single part vector: just the rest of the buffer */ - ret.first.buf = const_cast(mBuffer.data() + r*mElemSize); - ret.first.len = free_cnt; - ret.second.buf = nullptr; - ret.second.len = 0; + * plus some from the start of the buffer. + */ + return DataPair{{{mBuffer.data() + read_idx*mElemSize, mSizeMask+1 - read_idx}, + {mBuffer.data(), rdend&mSizeMask}}}; } - - return ret; + return DataPair{{{mBuffer.data() + read_idx*mElemSize, readable}, {}}}; } -auto RingBuffer::getWriteVector() const noexcept -> DataPair +auto RingBuffer::getWriteVector() noexcept -> DataPair { - DataPair ret; - - std::size_t w{mWritePtr.load(std::memory_order_acquire)}; - std::size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask}; - w &= mSizeMask; - r &= mSizeMask; - const std::size_t free_cnt{(r-w-1) & mSizeMask}; + const std::size_t w{mWriteCount.load(std::memory_order_relaxed)}; + const std::size_t r{mReadCount.load(std::memory_order_acquire)}; + const std::size_t writable{mWriteSize - (w - r)}; + const std::size_t write_idx{w & mSizeMask}; - const std::size_t cnt2{w + free_cnt}; - if(cnt2 > mSizeMask+1) + const std::size_t wrend{write_idx + writable}; + if(wrend > mSizeMask+1) { /* Two part vector: the rest of the buffer after the current write ptr, - * plus some from the start of the buffer. */ - ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); - ret.first.len = mSizeMask+1 - w; - ret.second.buf = const_cast(mBuffer.data()); - ret.second.len = cnt2 & mSizeMask; + * plus some from the start of the buffer. + */ + return DataPair{{{mBuffer.data() + write_idx*mElemSize, mSizeMask+1 - write_idx}, + {mBuffer.data(), wrend&mSizeMask}}}; } - else - { - ret.first.buf = const_cast(mBuffer.data() + w*mElemSize); - ret.first.len = free_cnt; - ret.second.buf = nullptr; - ret.second.len = 0; - } - - return ret; + return DataPair{{{mBuffer.data() + write_idx*mElemSize, writable}, {}}}; } diff --git a/3rdparty/openal/common/ringbuffer.h b/3rdparty/openal/common/ringbuffer.h index 8c65c3af9ac8..59b0a0ac7d86 100644 --- a/3rdparty/openal/common/ringbuffer.h +++ b/3rdparty/openal/common/ringbuffer.h @@ -2,26 +2,35 @@ #define RINGBUFFER_H #include +#include #include #include #include #include "almalloc.h" +#include "flexarray.h" /* NOTE: This lockless ringbuffer implementation is copied from JACK, extended * to include an element size. Consequently, parameters and return values for a - * size or count is in 'elements', not bytes. Additionally, it only supports + * size or count are in 'elements', not bytes. Additionally, it only supports * single-consumer/single-provider operation. */ struct RingBuffer { private: - std::atomic mWritePtr{0u}; - std::atomic mReadPtr{0u}; - std::size_t mWriteSize{0u}; - std::size_t mSizeMask{0u}; - std::size_t mElemSize{0u}; +#if defined(__cpp_lib_hardware_interference_size) && !defined(_LIBCPP_VERSION) + static constexpr std::size_t sCacheAlignment{std::hardware_destructive_interference_size}; +#else + /* Assume a 64-byte cache line, the most common/likely value. */ + static constexpr std::size_t sCacheAlignment{64}; +#endif + alignas(sCacheAlignment) std::atomic mWriteCount{0u}; + alignas(sCacheAlignment) std::atomic mReadCount{0u}; + + alignas(sCacheAlignment) const std::size_t mWriteSize; + const std::size_t mSizeMask; + const std::size_t mElemSize; al::FlexArray mBuffer; @@ -30,82 +39,95 @@ struct RingBuffer { std::byte *buf; std::size_t len; }; - using DataPair = std::pair; + using DataPair = std::array; - - RingBuffer(const std::size_t count) : mBuffer{count} { } + RingBuffer(const std::size_t writesize, const std::size_t mask, const std::size_t elemsize, + const std::size_t numbytes) + : mWriteSize{writesize}, mSizeMask{mask}, mElemSize{elemsize}, mBuffer{numbytes} + { } /** Reset the read and write pointers to zero. This is not thread safe. */ - void reset() noexcept; - - /** - * The non-copying data reader. Returns two ringbuffer data pointers that - * hold the current readable data. If the readable data is in one segment - * the second segment has zero length. - */ - DataPair getReadVector() const noexcept; - /** - * The non-copying data writer. Returns two ringbuffer data pointers that - * hold the current writeable data. If the writeable data is in one segment - * the second segment has zero length. - */ - DataPair getWriteVector() const noexcept; + auto reset() noexcept -> void; /** * Return the number of elements available for reading. This is the number * of elements in front of the read pointer and behind the write pointer. */ - std::size_t readSpace() const noexcept + [[nodiscard]] auto readSpace() const noexcept -> std::size_t { - const size_t w{mWritePtr.load(std::memory_order_acquire)}; - const size_t r{mReadPtr.load(std::memory_order_acquire)}; - return (w-r) & mSizeMask; + const std::size_t w{mWriteCount.load(std::memory_order_acquire)}; + const std::size_t r{mReadCount.load(std::memory_order_acquire)}; + /* mWriteCount is never more than mWriteSize greater than mReadCount. */ + return w - r; } /** - * The copying data reader. Copy at most `cnt' elements into `dest'. + * The copying data reader. Copy at most `count' elements into `dest'. * Returns the actual number of elements copied. */ - std::size_t read(void *dest, std::size_t cnt) noexcept; + [[nodiscard]] auto read(void *dest, std::size_t count) noexcept -> std::size_t; /** - * The copying data reader w/o read pointer advance. Copy at most `cnt' + * The copying data reader w/o read pointer advance. Copy at most `count' * elements into `dest'. Returns the actual number of elements copied. */ - std::size_t peek(void *dest, std::size_t cnt) const noexcept; - /** Advance the read pointer `cnt' places. */ - void readAdvance(std::size_t cnt) noexcept - { mReadPtr.fetch_add(cnt, std::memory_order_acq_rel); } - + [[nodiscard]] auto peek(void *dest, std::size_t count) const noexcept -> std::size_t; /** - * Return the number of elements available for writing. This is the number - * of elements in front of the write pointer and behind the read pointer. + * The non-copying data reader. Returns two ringbuffer data pointers that + * hold the current readable data. If the readable data is in one segment + * the second segment has zero length. */ - std::size_t writeSpace() const noexcept + [[nodiscard]] auto getReadVector() noexcept -> DataPair; + /** Advance the read pointer `count' places. */ + auto readAdvance(std::size_t count) noexcept -> void { - const size_t w{mWritePtr.load(std::memory_order_acquire)}; - const size_t r{mReadPtr.load(std::memory_order_acquire) + mWriteSize - mSizeMask}; - return (r-w-1) & mSizeMask; + const std::size_t w{mWriteCount.load(std::memory_order_acquire)}; + const std::size_t r{mReadCount.load(std::memory_order_relaxed)}; + [[maybe_unused]] const std::size_t readable{w - r}; + assert(readable >= count); + mReadCount.store(r+count, std::memory_order_release); } + /** - * The copying data writer. Copy at most `cnt' elements from `src'. Returns + * Return the number of elements available for writing. This is the total + * number of writable elements excluding what's readable (already written). + */ + [[nodiscard]] auto writeSpace() const noexcept -> std::size_t + { return mWriteSize - readSpace(); } + + /** + * The copying data writer. Copy at most `count' elements from `src'. Returns * the actual number of elements copied. */ - std::size_t write(const void *src, std::size_t cnt) noexcept; - /** Advance the write pointer `cnt' places. */ - void writeAdvance(std::size_t cnt) noexcept - { mWritePtr.fetch_add(cnt, std::memory_order_acq_rel); } + [[nodiscard]] auto write(const void *src, std::size_t count) noexcept -> std::size_t; + + /** + * The non-copying data writer. Returns two ringbuffer data pointers that + * hold the current writeable data. If the writeable data is in one segment + * the second segment has zero length. + */ + [[nodiscard]] auto getWriteVector() noexcept -> DataPair; + /** Advance the write pointer `count' places. */ + auto writeAdvance(std::size_t count) noexcept -> void + { + const std::size_t w{mWriteCount.load(std::memory_order_relaxed)}; + const std::size_t r{mReadCount.load(std::memory_order_acquire)}; + [[maybe_unused]] const std::size_t writable{mWriteSize - (w - r)}; + assert(writable >= count); + mWriteCount.store(w+count, std::memory_order_release); + } - std::size_t getElemSize() const noexcept { return mElemSize; } + [[nodiscard]] auto getElemSize() const noexcept -> std::size_t { return mElemSize; } /** * Create a new ringbuffer to hold at least `sz' elements of `elem_sz' - * bytes. The number of elements is rounded up to the next power of two - * (even if it is already a power of two, to ensure the requested amount - * can be written). + * bytes. The number of elements is rounded up to a power of two. If + * `limit_writes' is true, the writable space will be limited to `sz' + * elements regardless of the rounded size. */ - static std::unique_ptr Create(std::size_t sz, std::size_t elem_sz, int limit_writes); + [[nodiscard]] static + auto Create(std::size_t sz, std::size_t elem_sz, bool limit_writes) -> std::unique_ptr; DEF_FAM_NEWDEL(RingBuffer, mBuffer) }; diff --git a/3rdparty/openal/common/strutils.cpp b/3rdparty/openal/common/strutils.cpp index f7868e2e147b..5b1b6af19073 100644 --- a/3rdparty/openal/common/strutils.cpp +++ b/3rdparty/openal/common/strutils.cpp @@ -5,21 +5,23 @@ #include - #ifdef _WIN32 #define WIN32_LEAN_AND_MEAN #include +#include "alstring.h" + +/* NOLINTBEGIN(bugprone-suspicious-stringview-data-usage) */ std::string wstr_to_utf8(std::wstring_view wstr) { std::string ret; - int len{WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.length()), nullptr, - 0, nullptr, nullptr)}; + const int len{WideCharToMultiByte(CP_UTF8, 0, wstr.data(), al::sizei(wstr), nullptr, 0, + nullptr, nullptr)}; if(len > 0) { - ret.resize(len); - WideCharToMultiByte(CP_UTF8, 0, wstr.data(), static_cast(wstr.length()), &ret[0], len, + ret.resize(static_cast(len)); + WideCharToMultiByte(CP_UTF8, 0, wstr.data(), al::sizei(wstr), ret.data(), len, nullptr, nullptr); } @@ -30,16 +32,16 @@ std::wstring utf8_to_wstr(std::string_view str) { std::wstring ret; - int len{MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.length()), nullptr, - 0)}; + const int len{MultiByteToWideChar(CP_UTF8, 0, str.data(), al::sizei(str), nullptr, 0)}; if(len > 0) { - ret.resize(len); - MultiByteToWideChar(CP_UTF8, 0, str.data(), static_cast(str.length()), &ret[0], len); + ret.resize(static_cast(len)); + MultiByteToWideChar(CP_UTF8, 0, str.data(), al::sizei(str), ret.data(), len); } return ret; } +/* NOLINTEND(bugprone-suspicious-stringview-data-usage) */ #endif namespace al { @@ -51,7 +53,7 @@ std::optional getenv(const char *envname) #else const char *str{std::getenv(envname)}; #endif - if(str && str[0] != '\0') + if(str && *str != '\0') return str; return std::nullopt; } @@ -60,7 +62,7 @@ std::optional getenv(const char *envname) std::optional getenv(const WCHAR *envname) { const WCHAR *str{_wgetenv(envname)}; - if(str && str[0] != L'\0') + if(str && *str != L'\0') return str; return std::nullopt; } diff --git a/3rdparty/openal/common/strutils.h b/3rdparty/openal/common/strutils.h index 7eee0c1d1269..3644847c2bca 100644 --- a/3rdparty/openal/common/strutils.h +++ b/3rdparty/openal/common/strutils.h @@ -5,8 +5,8 @@ #include #ifdef _WIN32 +#include #include -#include std::string wstr_to_utf8(std::wstring_view wstr); std::wstring utf8_to_wstr(std::string_view str); diff --git a/3rdparty/openal/common/vecmat.h b/3rdparty/openal/common/vecmat.h index a45f262f6ded..7ac6afe32701 100644 --- a/3rdparty/openal/common/vecmat.h +++ b/3rdparty/openal/common/vecmat.h @@ -1,6 +1,7 @@ #ifndef COMMON_VECMAT_H #define COMMON_VECMAT_H +#include #include #include #include @@ -11,22 +12,24 @@ namespace alu { -template -class VectorR { - static_assert(std::is_floating_point::value, "Must use floating-point types"); - alignas(16) T mVals[4]; +class Vector { + alignas(16) std::array mVals{}; public: - constexpr VectorR() noexcept = default; - constexpr VectorR(const VectorR&) noexcept = default; - constexpr explicit VectorR(T a, T b, T c, T d) noexcept : mVals{a, b, c, d} { } + constexpr Vector() noexcept = default; + constexpr Vector(const Vector&) noexcept = default; + constexpr Vector(Vector&&) noexcept = default; + constexpr explicit Vector(float a, float b, float c, float d) noexcept : mVals{{a,b,c,d}} { } - constexpr VectorR& operator=(const VectorR&) noexcept = default; + constexpr auto operator=(const Vector&) noexcept -> Vector& = default; + constexpr auto operator=(Vector&&) noexcept -> Vector& = default; - constexpr T& operator[](size_t idx) noexcept { return mVals[idx]; } - constexpr const T& operator[](size_t idx) const noexcept { return mVals[idx]; } + [[nodiscard]] constexpr + auto operator[](std::size_t idx) noexcept -> float& { return mVals[idx]; } + [[nodiscard]] constexpr + auto operator[](std::size_t idx) const noexcept -> const float& { return mVals[idx]; } - constexpr VectorR& operator+=(const VectorR &rhs) noexcept + constexpr auto operator+=(const Vector &rhs) noexcept -> Vector& { mVals[0] += rhs.mVals[0]; mVals[1] += rhs.mVals[1]; @@ -35,85 +38,84 @@ class VectorR { return *this; } - constexpr VectorR operator-(const VectorR &rhs) const noexcept + [[nodiscard]] constexpr + auto operator-(const Vector &rhs) const noexcept -> Vector { - return VectorR{mVals[0] - rhs.mVals[0], mVals[1] - rhs.mVals[1], + return Vector{mVals[0] - rhs.mVals[0], mVals[1] - rhs.mVals[1], mVals[2] - rhs.mVals[2], mVals[3] - rhs.mVals[3]}; } - constexpr T normalize(T limit = std::numeric_limits::epsilon()) + constexpr auto normalize() -> float { - limit = std::max(limit, std::numeric_limits::epsilon()); - const T length_sqr{mVals[0]*mVals[0] + mVals[1]*mVals[1] + mVals[2]*mVals[2]}; - if(length_sqr > limit*limit) + const auto length_sqr = float{mVals[0]*mVals[0] + mVals[1]*mVals[1] + mVals[2]*mVals[2]}; + if(length_sqr > std::numeric_limits::epsilon()) { - const T length{std::sqrt(length_sqr)}; - T inv_length{T{1}/length}; + const auto length = std::sqrt(length_sqr); + auto inv_length = float{1.0f / length}; mVals[0] *= inv_length; mVals[1] *= inv_length; mVals[2] *= inv_length; return length; } - mVals[0] = mVals[1] = mVals[2] = T{0}; - return T{0}; + mVals[0] = mVals[1] = mVals[2] = 0.0f; + return 0.0f; } - constexpr VectorR cross_product(const alu::VectorR &rhs) const noexcept + [[nodiscard]] constexpr auto cross_product(const Vector &rhs) const noexcept -> Vector { - return VectorR{ + return Vector{ mVals[1]*rhs.mVals[2] - mVals[2]*rhs.mVals[1], mVals[2]*rhs.mVals[0] - mVals[0]*rhs.mVals[2], mVals[0]*rhs.mVals[1] - mVals[1]*rhs.mVals[0], - T{0}}; + 0.0f}; } - constexpr T dot_product(const alu::VectorR &rhs) const noexcept + [[nodiscard]] constexpr auto dot_product(const Vector &rhs) const noexcept -> float { return mVals[0]*rhs.mVals[0] + mVals[1]*rhs.mVals[1] + mVals[2]*rhs.mVals[2]; } }; -using Vector = VectorR; -template -class MatrixR { - static_assert(std::is_floating_point::value, "Must use floating-point types"); - alignas(16) T mVals[16]; +class Matrix { + alignas(16) std::array mVals{}; public: - constexpr MatrixR() noexcept = default; - constexpr MatrixR(const MatrixR&) noexcept = default; - constexpr explicit MatrixR( - T aa, T ab, T ac, T ad, - T ba, T bb, T bc, T bd, - T ca, T cb, T cc, T cd, - T da, T db, T dc, T dd) noexcept - : mVals{aa,ab,ac,ad, ba,bb,bc,bd, ca,cb,cc,cd, da,db,dc,dd} + constexpr Matrix() noexcept = default; + constexpr Matrix(const Matrix&) noexcept = default; + constexpr Matrix(Matrix&&) noexcept = default; + constexpr explicit Matrix( + float aa, float ab, float ac, float ad, + float ba, float bb, float bc, float bd, + float ca, float cb, float cc, float cd, + float da, float db, float dc, float dd) noexcept + : mVals{{aa,ab,ac,ad, ba,bb,bc,bd, ca,cb,cc,cd, da,db,dc,dd}} { } - constexpr MatrixR& operator=(const MatrixR&) noexcept = default; + constexpr auto operator=(const Matrix&) noexcept -> Matrix& = default; + constexpr auto operator=(Matrix&&) noexcept -> Matrix& = default; - constexpr auto operator[](size_t idx) noexcept { return al::span{&mVals[idx*4], 4}; } - constexpr auto operator[](size_t idx) const noexcept - { return al::span{&mVals[idx*4], 4}; } + [[nodiscard]] constexpr auto operator[](std::size_t idx) noexcept + { return al::span{&mVals[idx*4], 4}; } + [[nodiscard]] constexpr auto operator[](std::size_t idx) const noexcept + { return al::span{&mVals[idx*4], 4}; } - static constexpr MatrixR Identity() noexcept + [[nodiscard]] static constexpr auto Identity() noexcept -> Matrix { - return MatrixR{ - T{1}, T{0}, T{0}, T{0}, - T{0}, T{1}, T{0}, T{0}, - T{0}, T{0}, T{1}, T{0}, - T{0}, T{0}, T{0}, T{1}}; + return Matrix{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f}; + } + + [[nodiscard]] friend constexpr + auto operator*(const Matrix &mtx, const Vector &vec) noexcept -> Vector + { + return Vector{ + vec[0]*mtx[0][0] + vec[1]*mtx[1][0] + vec[2]*mtx[2][0] + vec[3]*mtx[3][0], + vec[0]*mtx[0][1] + vec[1]*mtx[1][1] + vec[2]*mtx[2][1] + vec[3]*mtx[3][1], + vec[0]*mtx[0][2] + vec[1]*mtx[1][2] + vec[2]*mtx[2][2] + vec[3]*mtx[3][2], + vec[0]*mtx[0][3] + vec[1]*mtx[1][3] + vec[2]*mtx[2][3] + vec[3]*mtx[3][3]}; } }; -using Matrix = MatrixR; - -template -constexpr VectorR operator*(const MatrixR &mtx, const VectorR &vec) noexcept -{ - return VectorR{ - vec[0]*mtx[0][0] + vec[1]*mtx[1][0] + vec[2]*mtx[2][0] + vec[3]*mtx[3][0], - vec[0]*mtx[0][1] + vec[1]*mtx[1][1] + vec[2]*mtx[2][1] + vec[3]*mtx[3][1], - vec[0]*mtx[0][2] + vec[1]*mtx[1][2] + vec[2]*mtx[2][2] + vec[3]*mtx[3][2], - vec[0]*mtx[0][3] + vec[1]*mtx[1][3] + vec[2]*mtx[2][3] + vec[3]*mtx[3][3]}; -} } // namespace alu diff --git a/3rdparty/openal/common/vector.h b/3rdparty/openal/common/vector.h index 1b69d6a77fea..364735c67da4 100644 --- a/3rdparty/openal/common/vector.h +++ b/3rdparty/openal/common/vector.h @@ -1,13 +1,14 @@ #ifndef AL_VECTOR_H #define AL_VECTOR_H +#include #include #include "almalloc.h" namespace al { -template +template using vector = std::vector>; } // namespace al diff --git a/3rdparty/openal/config.h.in b/3rdparty/openal/config.h.in index 20df5b467079..fb61fcf284ca 100644 --- a/3rdparty/openal/config.h.in +++ b/3rdparty/openal/config.h.in @@ -1,93 +1,18 @@ /* Define the alignment attribute for externally callable functions. */ #define FORCE_ALIGN @ALSOFT_FORCE_ALIGN@ -/* Define if deprecated EAX extensions are enabled */ -#cmakedefine ALSOFT_EAX - /* Define if HRTF data is embedded in the library */ #cmakedefine ALSOFT_EMBED_HRTF_DATA -/* Define if we have the posix_memalign function */ -#cmakedefine HAVE_POSIX_MEMALIGN - -/* Define if we have the _aligned_malloc function */ -#cmakedefine HAVE__ALIGNED_MALLOC - /* Define if we have the proc_pidpath function */ #cmakedefine HAVE_PROC_PIDPATH -/* Define if we have the getopt function */ -#cmakedefine HAVE_GETOPT - -/* Define if we have DBus/RTKit */ -#cmakedefine HAVE_RTKIT - -/* Define if we have SSE CPU extensions */ -#cmakedefine HAVE_SSE -#cmakedefine HAVE_SSE2 -#cmakedefine HAVE_SSE3 -#cmakedefine HAVE_SSE4_1 - -/* Define if we have ARM Neon CPU extensions */ -#cmakedefine HAVE_NEON - -/* Define if we have the ALSA backend */ -#cmakedefine HAVE_ALSA - -/* Define if we have the OSS backend */ -#cmakedefine HAVE_OSS - -/* Define if we have the PipeWire backend */ -#cmakedefine HAVE_PIPEWIRE - -/* Define if we have the Solaris backend */ -#cmakedefine HAVE_SOLARIS - -/* Define if we have the SndIO backend */ -#cmakedefine HAVE_SNDIO - -/* Define if we have the WASAPI backend */ -#cmakedefine HAVE_WASAPI - -/* Define if we have the DSound backend */ -#cmakedefine HAVE_DSOUND - -/* Define if we have the Windows Multimedia backend */ -#cmakedefine HAVE_WINMM - -/* Define if we have the PortAudio backend */ -#cmakedefine HAVE_PORTAUDIO - -/* Define if we have the PulseAudio backend */ -#cmakedefine HAVE_PULSEAUDIO - -/* Define if we have the JACK backend */ -#cmakedefine HAVE_JACK - -/* Define if we have the CoreAudio backend */ -#cmakedefine HAVE_COREAUDIO - -/* Define if we have the OpenSL backend */ -#cmakedefine HAVE_OPENSL - -/* Define if we have the Oboe backend */ -#cmakedefine HAVE_OBOE - -/* Define if we have the Wave Writer backend */ -#cmakedefine HAVE_WAVE - -/* Define if we have the SDL2 backend */ -#cmakedefine HAVE_SDL2 - /* Define if we have dlfcn.h */ #cmakedefine HAVE_DLFCN_H /* Define if we have pthread_np.h */ #cmakedefine HAVE_PTHREAD_NP_H -/* Define if we have malloc.h */ -#cmakedefine HAVE_MALLOC_H - /* Define if we have cpuid.h */ #cmakedefine HAVE_CPUID_H @@ -97,18 +22,12 @@ /* Define if we have guiddef.h */ #cmakedefine HAVE_GUIDDEF_H -/* Define if we have initguid.h */ -#cmakedefine HAVE_INITGUID_H - /* Define if we have GCC's __get_cpuid() */ #cmakedefine HAVE_GCC_GET_CPUID /* Define if we have the __cpuid() intrinsic */ #cmakedefine HAVE_CPUID_INTRINSIC -/* Define if we have SSE intrinsics */ -#cmakedefine HAVE_SSE_INTRINSICS - /* Define if we have pthread_setschedparam() */ #cmakedefine HAVE_PTHREAD_SETSCHEDPARAM @@ -121,5 +40,11 @@ /* Define the installation data directory */ #cmakedefine ALSOFT_INSTALL_DATADIR "@ALSOFT_INSTALL_DATADIR@" -/* Define whether build alsoft for winuwp */ -#cmakedefine ALSOFT_UWP +/* Define to 1 if we have DBus/RTKit, else 0 */ +#cmakedefine01 HAVE_RTKIT + +/* Define to 1 if building for winuwp, else 0 */ +#cmakedefine01 ALSOFT_UWP + +/* Define to 1 if building with legacy EAX API support, else 0 */ +#cmakedefine01 ALSOFT_EAX diff --git a/3rdparty/openal/config_backends.h.in b/3rdparty/openal/config_backends.h.in new file mode 100644 index 000000000000..96eb79ca7c35 --- /dev/null +++ b/3rdparty/openal/config_backends.h.in @@ -0,0 +1,37 @@ +/* Define to 1 if the given backend is enabled, else 0 */ + +#cmakedefine01 HAVE_ALSA + +#cmakedefine01 HAVE_OSS + +#cmakedefine01 HAVE_PIPEWIRE + +#cmakedefine01 HAVE_SOLARIS + +#cmakedefine01 HAVE_SNDIO + +#cmakedefine01 HAVE_WASAPI + +#cmakedefine01 HAVE_DSOUND + +#cmakedefine01 HAVE_WINMM + +#cmakedefine01 HAVE_PORTAUDIO + +#cmakedefine01 HAVE_PULSEAUDIO + +#cmakedefine01 HAVE_JACK + +#cmakedefine01 HAVE_COREAUDIO + +#cmakedefine01 HAVE_OPENSL + +#cmakedefine01 HAVE_OBOE + +#cmakedefine01 HAVE_OTHERIO + +#cmakedefine01 HAVE_WAVE + +#cmakedefine01 HAVE_SDL3 + +#cmakedefine01 HAVE_SDL2 diff --git a/3rdparty/openal/config_simd.h.in b/3rdparty/openal/config_simd.h.in new file mode 100644 index 000000000000..3d284cc7bf1b --- /dev/null +++ b/3rdparty/openal/config_simd.h.in @@ -0,0 +1,10 @@ +/* Define to 1 if we have SSE CPU extensions, else 0 */ +#cmakedefine01 HAVE_SSE +#cmakedefine01 HAVE_SSE2 +#cmakedefine01 HAVE_SSE3 +#cmakedefine01 HAVE_SSE4_1 + +#cmakedefine01 HAVE_SSE_INTRINSICS + +/* Define to 1 if we have ARM Neon CPU extensions, else 0 */ +#cmakedefine01 HAVE_NEON diff --git a/3rdparty/openal/core/ambdec.cpp b/3rdparty/openal/core/ambdec.cpp index f98e1098f012..c1ba4c31b683 100644 --- a/3rdparty/openal/core/ambdec.cpp +++ b/3rdparty/openal/core/ambdec.cpp @@ -8,14 +8,15 @@ #include #include #include +#include #include #include #include #include "albit.h" -#include "alfstream.h" #include "alspan.h" -#include "opthelpers.h" +#include "filesystem.h" +#include "fmt/core.h" namespace { @@ -42,33 +43,13 @@ enum class ReaderScope { HFMatrix, }; -#ifdef __USE_MINGW_ANSI_STDIO -[[gnu::format(gnu_printf,2,3)]] -#else -[[gnu::format(printf,2,3)]] -#endif -std::optional make_error(size_t linenum, const char *fmt, ...) +template +auto make_error(size_t linenum, fmt::format_string fmt, Args&& ...args) + -> std::optional { std::optional ret; - auto &str = ret.emplace(); - - str.resize(256); - int printed{std::snprintf(const_cast(str.data()), str.length(), "Line %zu: ", linenum)}; - if(printed < 0) printed = 0; - auto plen = std::min(static_cast(printed), str.length()); - - std::va_list args, args2; - va_start(args, fmt); - va_copy(args2, args); - const int msglen{std::vsnprintf(&str[plen], str.size()-plen, fmt, args)}; - if(msglen >= 0 && static_cast(msglen) >= str.size()-plen) - { - str.resize(static_cast(msglen) + plen + 1u); - std::vsnprintf(&str[plen], str.size()-plen, fmt, args2); - } - va_end(args2); - va_end(args); - + auto &str = ret.emplace(fmt::format("Line {}: ", linenum)); + str += fmt::format(std::move(fmt), std::forward(args)...); return ret; } @@ -79,7 +60,7 @@ AmbDecConf::~AmbDecConf() = default; std::optional AmbDecConf::load(const char *fname) noexcept { - al::ifstream f{fname}; + fs::ifstream f{fs::u8path(fname)}; if(!f.is_open()) return std::string("Failed to open file \"")+fname+"\""; @@ -102,7 +83,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept if(command == "/}") { if(scope == ReaderScope::Global) - return make_error(linenum, "Unexpected /} in global scope"); + return make_error(linenum, "Unexpected /}} in global scope"); scope = ReaderScope::Global; continue; } @@ -111,7 +92,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept { if(command == "add_spkr") { - if(speaker_pos == NumSpeakers) + if(speaker_pos == Speakers.size()) return make_error(linenum, "Too many speakers specified"); AmbDecConf::SpeakerConf &spkr = Speakers[speaker_pos++]; @@ -122,12 +103,12 @@ std::optional AmbDecConf::load(const char *fname) noexcept istr >> spkr.Connection; } else - return make_error(linenum, "Unexpected speakers command: %s", command.c_str()); + return make_error(linenum, "Unexpected speakers command: {}", command); } else if(scope == ReaderScope::LFMatrix || scope == ReaderScope::HFMatrix) { auto &gains = (scope == ReaderScope::LFMatrix) ? LFOrderGain : HFOrderGain; - auto *matrix = (scope == ReaderScope::LFMatrix) ? LFMatrix : HFMatrix; + auto matrix = (scope == ReaderScope::LFMatrix) ? LFMatrix : HFMatrix; auto &pos = (scope == ReaderScope::LFMatrix) ? lfmatrix_pos : hfmatrix_pos; if(command == "order_gain") @@ -145,7 +126,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept } else if(command == "add_row") { - if(pos == NumSpeakers) + if(pos == Speakers.size()) return make_error(linenum, "Too many matrix rows specified"); unsigned int mask{ChanMask}; @@ -165,7 +146,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept } } else - return make_error(linenum, "Unexpected matrix command: %s", command.c_str()); + return make_error(linenum, "Unexpected matrix command: {}", command); } // Global scope commands else if(command == "/description") @@ -182,7 +163,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept return make_error(linenum, "Duplicate version definition"); istr >> Version; if(Version != 3) - return make_error(linenum, "Unsupported version: %d", Version); + return make_error(linenum, "Unsupported version: {}", Version); } else if(command == "/dec/chan_mask") { @@ -191,7 +172,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept istr >> std::hex >> ChanMask >> std::dec; if(!ChanMask || ChanMask > Ambi4OrderMask) - return make_error(linenum, "Invalid chan_mask: 0x%x", ChanMask); + return make_error(linenum, "Invalid chan_mask: {:#x}", ChanMask); if(ChanMask > Ambi3OrderMask && CoeffScale == AmbDecScale::FuMa) return make_error(linenum, "FuMa not compatible with over third-order"); } @@ -201,16 +182,17 @@ std::optional AmbDecConf::load(const char *fname) noexcept return make_error(linenum, "Duplicate freq_bands"); istr >> FreqBands; if(FreqBands != 1 && FreqBands != 2) - return make_error(linenum, "Invalid freq_bands: %u", FreqBands); + return make_error(linenum, "Invalid freq_bands: {}", FreqBands); } else if(command == "/dec/speakers") { - if(NumSpeakers) + if(!Speakers.empty()) return make_error(linenum, "Duplicate speakers"); - istr >> NumSpeakers; - if(!NumSpeakers) - return make_error(linenum, "Invalid speakers: %zu", NumSpeakers); - Speakers = std::make_unique(NumSpeakers); + size_t numspeakers{}; + istr >> numspeakers; + if(!numspeakers) + return make_error(linenum, "Invalid speakers: {}", numspeakers); + Speakers.resize(numspeakers); } else if(command == "/dec/coeff_scale") { @@ -222,7 +204,7 @@ std::optional AmbDecConf::load(const char *fname) noexcept else if(scale == "sn3d") CoeffScale = AmbDecScale::SN3D; else if(scale == "fuma") CoeffScale = AmbDecScale::FuMa; else - return make_error(linenum, "Unexpected coeff_scale: %s", scale.c_str()); + return make_error(linenum, "Unexpected coeff_scale: {}", scale); if(ChanMask > Ambi3OrderMask && CoeffScale == AmbDecScale::FuMa) return make_error(linenum, "FuMa not compatible with over third-order"); @@ -243,29 +225,29 @@ std::optional AmbDecConf::load(const char *fname) noexcept } else if(command == "/speakers/{") { - if(!NumSpeakers) + if(Speakers.empty()) return make_error(linenum, "Speakers defined without a count"); scope = ReaderScope::Speakers; } else if(command == "/lfmatrix/{" || command == "/hfmatrix/{" || command == "/matrix/{") { - if(!NumSpeakers) + if(Speakers.empty()) return make_error(linenum, "Matrix defined without a speaker count"); if(!ChanMask) return make_error(linenum, "Matrix defined without a channel mask"); - if(!Matrix) + if(Matrix.empty()) { - Matrix = std::make_unique(NumSpeakers * FreqBands); - LFMatrix = Matrix.get(); - HFMatrix = LFMatrix + NumSpeakers*(FreqBands-1); + Matrix.resize(Speakers.size() * FreqBands); + LFMatrix = al::span{Matrix}.first(Speakers.size()); + HFMatrix = al::span{Matrix}.subspan(Speakers.size()*(FreqBands-1)); } if(FreqBands == 1) { if(command != "/matrix/{") - return make_error(linenum, "Unexpected \"%s\" for a single-band decoder", - command.c_str()); + return make_error(linenum, "Unexpected \"{}\" for a single-band decoder", + command); scope = ReaderScope::HFMatrix; } else @@ -275,18 +257,19 @@ std::optional AmbDecConf::load(const char *fname) noexcept else if(command == "/hfmatrix/{") scope = ReaderScope::HFMatrix; else - return make_error(linenum, "Unexpected \"%s\" for a dual-band decoder", - command.c_str()); + return make_error(linenum, "Unexpected \"{}\" for a dual-band decoder", + command); } } else if(command == "/end") { const auto endpos = static_cast(istr.tellg()); if(!is_at_end(buffer, endpos)) - return make_error(linenum, "Extra junk on end: %s", buffer.substr(endpos).c_str()); + return make_error(linenum, "Extra junk on end: {}", + std::string_view{buffer}.substr(endpos)); - if(speaker_pos < NumSpeakers || hfmatrix_pos < NumSpeakers - || (FreqBands == 2 && lfmatrix_pos < NumSpeakers)) + if(speaker_pos < Speakers.size() || hfmatrix_pos < Speakers.size() + || (FreqBands == 2 && lfmatrix_pos < Speakers.size())) return make_error(linenum, "Incomplete decoder definition"); if(CoeffScale == AmbDecScale::Unset) return make_error(linenum, "No coefficient scaling defined"); @@ -294,12 +277,13 @@ std::optional AmbDecConf::load(const char *fname) noexcept return std::nullopt; } else - return make_error(linenum, "Unexpected command: %s", command.c_str()); + return make_error(linenum, "Unexpected command: {}", command); istr.clear(); const auto endpos = static_cast(istr.tellg()); if(!is_at_end(buffer, endpos)) - return make_error(linenum, "Extra junk on line: %s", buffer.substr(endpos).c_str()); + return make_error(linenum, "Extra junk on line: {}", + std::string_view{buffer}.substr(endpos)); buffer.clear(); } return make_error(linenum, "Unexpected end of file"); diff --git a/3rdparty/openal/core/ambdec.h b/3rdparty/openal/core/ambdec.h index 19f68697114c..587a30c666ce 100644 --- a/3rdparty/openal/core/ambdec.h +++ b/3rdparty/openal/core/ambdec.h @@ -5,7 +5,9 @@ #include #include #include +#include +#include "alspan.h" #include "core/ambidefs.h" /* Helpers to read .ambdec configuration files. */ @@ -34,18 +36,17 @@ struct AmbDecConf { float Elevation{0.0f}; std::string Connection; }; - size_t NumSpeakers{0}; - std::unique_ptr Speakers; + std::vector Speakers; using CoeffArray = std::array; - std::unique_ptr Matrix; + std::vector Matrix; /* Unused when FreqBands == 1 */ - float LFOrderGain[MaxAmbiOrder+1]{}; - CoeffArray *LFMatrix; + std::array LFOrderGain{}; + al::span LFMatrix; - float HFOrderGain[MaxAmbiOrder+1]{}; - CoeffArray *HFMatrix; + std::array HFOrderGain{}; + al::span HFMatrix; ~AmbDecConf(); diff --git a/3rdparty/openal/core/ambidefs.cpp b/3rdparty/openal/core/ambidefs.cpp index c1bb5c81e8b6..4a72e34f3808 100644 --- a/3rdparty/openal/core/ambidefs.cpp +++ b/3rdparty/openal/core/ambidefs.cpp @@ -10,7 +10,6 @@ namespace { using AmbiChannelFloatArray = std::array; -constexpr auto inv_sqrt2f = static_cast(1.0/al::numbers::sqrt2); constexpr auto inv_sqrt3f = static_cast(1.0/al::numbers::sqrt3); @@ -21,25 +20,25 @@ constexpr auto inv_sqrt3f = static_cast(1.0/al::numbers::sqrt3); * will result in that channel being subsequently decoded for second-order as * if it was a first-order decoder for that same speaker array. */ -constexpr std::array,MaxAmbiOrder+1> HFScales{{ - {{ 4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 2.981423970e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f }}, - {{ 2.359168820e+00f, 2.031565936e+00f, 1.444598386e+00f, 7.189495850e-01f }}, - /* 1.947005434e+00f, 1.764337084e+00f, 1.424707344e+00f, 9.755104127e-01f, 4.784482742e-01f */ -}}; +constexpr std::array HFScales{ + std::array{4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{4.000000000e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{2.981423970e+00f, 2.309401077e+00f, 1.192569588e+00f, 7.189495850e-01f}, + std::array{2.359168820e+00f, 2.031565936e+00f, 1.444598386e+00f, 7.189495850e-01f}, + /*std::array{1.947005434e+00f, 1.764337084e+00f, 1.424707344e+00f, 9.755104127e-01f, 4.784482742e-01f}, */ +}; /* Same as above, but using a 10-point horizontal-only speaker array. Should * only be used when the device is mixing in 2D B-Format for horizontal-only * output. */ -constexpr std::array,MaxAmbiOrder+1> HFScales2D{{ - {{ 2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 1.825741858e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f }}, - {{ 1.581138830e+00f, 1.460781803e+00f, 1.118033989e+00f, 6.050756345e-01f }}, - /* 1.414213562e+00f, 1.344997024e+00f, 1.144122806e+00f, 8.312538756e-01f, 4.370160244e-01f */ -}}; +constexpr std::array HFScales2D{ + std::array{2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{2.236067977e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{1.825741858e+00f, 1.581138830e+00f, 9.128709292e-01f, 6.050756345e-01f}, + std::array{1.581138830e+00f, 1.460781803e+00f, 1.118033989e+00f, 6.050756345e-01f}, + /*std::array{1.414213562e+00f, 1.344997024e+00f, 1.144122806e+00f, 8.312538756e-01f, 4.370160244e-01f}, */ +}; /* This calculates a first-order "upsampler" matrix. It combines a first-order @@ -49,17 +48,17 @@ constexpr std::array,MaxAmbiOrder+1> HFScales2D * signal. While not perfect, this should accurately encode a lower-order * signal into a higher-order signal. */ -constexpr std::array,8> FirstOrderDecoder{{ - {{ 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, }}, - {{ 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, }}, -}}; -constexpr std::array FirstOrderEncoder{{ +constexpr std::array FirstOrderDecoder{ + std::array{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, 1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, 1.250000000e-01f}, + std::array{1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f, -1.250000000e-01f}, +}; +constexpr std::array FirstOrderEncoder{ CalcAmbiCoeffs( inv_sqrt3f, inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs( inv_sqrt3f, inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, inv_sqrt3f, inv_sqrt3f), @@ -68,25 +67,29 @@ constexpr std::array FirstOrderEncoder{{ CalcAmbiCoeffs( inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, -inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs(-inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), -}}; +}; static_assert(FirstOrderDecoder.size() == FirstOrderEncoder.size(), "First-order mismatch"); /* This calculates a 2D first-order "upsampler" matrix. Same as the first-order * matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,4> FirstOrder2DDecoder{{ - {{ 2.500000000e-01f, 2.041241452e-01f, 0.0f, 2.041241452e-01f, }}, - {{ 2.500000000e-01f, 2.041241452e-01f, 0.0f, -2.041241452e-01f, }}, - {{ 2.500000000e-01f, -2.041241452e-01f, 0.0f, 2.041241452e-01f, }}, - {{ 2.500000000e-01f, -2.041241452e-01f, 0.0f, -2.041241452e-01f, }}, -}}; -constexpr std::array FirstOrder2DEncoder{{ - CalcAmbiCoeffs( inv_sqrt2f, 0.0f, inv_sqrt2f), - CalcAmbiCoeffs( inv_sqrt2f, 0.0f, -inv_sqrt2f), - CalcAmbiCoeffs(-inv_sqrt2f, 0.0f, inv_sqrt2f), - CalcAmbiCoeffs(-inv_sqrt2f, 0.0f, -inv_sqrt2f), -}}; +constexpr std::array FirstOrder2DDecoder{ + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, 1.666666667e-01f}, + std::array{1.666666667e-01f, -1.924500897e-01f, 0.0f, 0.000000000e+00f}, + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, -1.666666667e-01f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, -1.666666667e-01f}, + std::array{1.666666667e-01f, 1.924500897e-01f, 0.0f, 0.000000000e+00f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, 1.666666667e-01f}, +}; +constexpr std::array FirstOrder2DEncoder{ + CalcAmbiCoeffs(-0.50000000000f, 0.0f, 0.86602540379f), + CalcAmbiCoeffs(-1.00000000000f, 0.0f, 0.00000000000f), + CalcAmbiCoeffs(-0.50000000000f, 0.0f, -0.86602540379f), + CalcAmbiCoeffs( 0.50000000000f, 0.0f, -0.86602540379f), + CalcAmbiCoeffs( 1.00000000000f, 0.0f, 0.00000000000f), + CalcAmbiCoeffs( 0.50000000000f, 0.0f, 0.86602540379f), +}; static_assert(FirstOrder2DDecoder.size() == FirstOrder2DEncoder.size(), "First-order 2D mismatch"); @@ -94,21 +97,21 @@ static_assert(FirstOrder2DDecoder.size() == FirstOrder2DEncoder.size(), "First-o * matrix, just using a slightly more dense speaker array suitable for second- * order content. */ -constexpr std::array,12> SecondOrderDecoder{{ - {{ 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, - {{ 8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f, }}, - {{ 8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f, }}, - {{ 8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f, }}, -}}; -constexpr std::array SecondOrderEncoder{{ +constexpr std::array SecondOrderDecoder{ + std::array{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, -7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, -1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, 1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, -7.588274978e-02f, -1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, 7.588274978e-02f, 1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, + std::array{8.333333333e-02f, 0.000000000e+00f, 7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, -1.591525047e-02f, -1.443375673e-01f, 1.167715449e-01f}, + std::array{8.333333333e-02f, 1.227808683e-01f, 0.000000000e+00f, 7.588274978e-02f, 1.443375673e-01f, 0.000000000e+00f, -9.316949906e-02f, 0.000000000e+00f, -7.216878365e-02f}, + std::array{8.333333333e-02f, -7.588274978e-02f, -1.227808683e-01f, 0.000000000e+00f, 0.000000000e+00f, 1.443375673e-01f, 1.090847495e-01f, 0.000000000e+00f, -4.460276122e-02f}, +}; +constexpr std::array SecondOrderEncoder{ CalcAmbiCoeffs( 0.000000000e+00f, -5.257311121e-01f, 8.506508084e-01f), CalcAmbiCoeffs(-8.506508084e-01f, 0.000000000e+00f, 5.257311121e-01f), CalcAmbiCoeffs(-5.257311121e-01f, 8.506508084e-01f, 0.000000000e+00f), @@ -121,29 +124,29 @@ constexpr std::array SecondOrderEncoder{{ CalcAmbiCoeffs( 0.000000000e+00f, 5.257311121e-01f, -8.506508084e-01f), CalcAmbiCoeffs( 8.506508084e-01f, 0.000000000e+00f, 5.257311121e-01f), CalcAmbiCoeffs(-5.257311121e-01f, -8.506508084e-01f, 0.000000000e+00f), -}}; +}; static_assert(SecondOrderDecoder.size() == SecondOrderEncoder.size(), "Second-order mismatch"); /* This calculates a 2D second-order "upsampler" matrix. Same as the second- * order matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,6> SecondOrder2DDecoder{{ - {{ 1.666666667e-01f, -9.622504486e-02f, 0.0f, 1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, -1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f, }}, - {{ 1.666666667e-01f, -9.622504486e-02f, 0.0f, -1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, 9.622504486e-02f, 0.0f, -1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, - {{ 1.666666667e-01f, 1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f, }}, - {{ 1.666666667e-01f, 9.622504486e-02f, 0.0f, 1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f, }}, -}}; -constexpr std::array SecondOrder2DEncoder{{ +constexpr std::array SecondOrder2DDecoder{ + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, 1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, -1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f}, + std::array{1.666666667e-01f, -9.622504486e-02f, 0.0f, -1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, -1.666666667e-01f, -1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, + std::array{1.666666667e-01f, 1.924500897e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.721325932e-01f}, + std::array{1.666666667e-01f, 9.622504486e-02f, 0.0f, 1.666666667e-01f, 1.490711985e-01f, 0.0f, 0.0f, 0.0f, 8.606629658e-02f}, +}; +constexpr std::array SecondOrder2DEncoder{ CalcAmbiCoeffs(-0.50000000000f, 0.0f, 0.86602540379f), CalcAmbiCoeffs(-1.00000000000f, 0.0f, 0.00000000000f), CalcAmbiCoeffs(-0.50000000000f, 0.0f, -0.86602540379f), CalcAmbiCoeffs( 0.50000000000f, 0.0f, -0.86602540379f), CalcAmbiCoeffs( 1.00000000000f, 0.0f, 0.00000000000f), CalcAmbiCoeffs( 0.50000000000f, 0.0f, 0.86602540379f), -}}; +}; static_assert(SecondOrder2DDecoder.size() == SecondOrder2DEncoder.size(), "Second-order 2D mismatch"); @@ -152,29 +155,29 @@ static_assert(SecondOrder2DDecoder.size() == SecondOrder2DEncoder.size(), * matrix, just using a more dense speaker array suitable for third-order * content. */ -constexpr std::array,20> ThirdOrderDecoder{{ - {{ 5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f, }}, - {{ 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }}, - {{ 5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }}, - {{ 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f, }}, - {{ 5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f, }}, - {{ 5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f, }}, - {{ 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f, }}, -}}; -constexpr std::array ThirdOrderEncoder{{ +constexpr std::array ThirdOrderDecoder{ + std::array{5.000000000e-02f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, 7.944389175e-02f, 0.000000000e+00f, 2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, -1.256118221e-01f, 0.000000000e+00f, 1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, 6.454972244e-02f, 9.045084972e-02f, 0.000000000e+00f, -1.232790000e-02f, 1.256118221e-01f, 0.000000000e+00f, -1.126112056e-01f, -7.944389175e-02f, 0.000000000e+00f, -2.421151497e-02f, 0.000000000e+00f}, + std::array{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + std::array{5.000000000e-02f, 8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, -7.763237543e-02f, 0.000000000e+00f, -2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + std::array{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, 3.090169944e-02f, -6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, -1.497759251e-01f, 0.000000000e+00f, -7.763237543e-02f}, + std::array{5.000000000e-02f, -8.090169944e-02f, 0.000000000e+00f, -3.090169944e-02f, 6.454972244e-02f, 0.000000000e+00f, -5.590169944e-02f, 0.000000000e+00f, -7.216878365e-02f, 7.763237543e-02f, 0.000000000e+00f, 2.950836627e-02f, 0.000000000e+00f, 1.497759251e-01f, 0.000000000e+00f, 7.763237543e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, -6.779013272e-02f, 1.659481923e-01f, 4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, 3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, 3.034486645e-02f, 6.779013272e-02f, 1.659481923e-01f, -4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, 8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, -6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, -6.779013272e-02f, -1.659481923e-01f, 4.797944664e-02f}, + std::array{5.000000000e-02f, 0.000000000e+00f, -3.090169944e-02f, -8.090169944e-02f, 0.000000000e+00f, 0.000000000e+00f, -3.454915028e-02f, 6.454972244e-02f, 8.449668365e-02f, 0.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f, -3.034486645e-02f, 6.779013272e-02f, -1.659481923e-01f, -4.797944664e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, 1.011266756e-01f, -7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, -7.364853795e-02f, -1.011266756e-01f, -7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, 6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, -6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, 5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -6.454972244e-02f, -6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, 1.016220987e-01f, 6.338656910e-02f, -1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 5.000000000e-02f, -6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, -6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, 6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, 1.011266756e-01f, 7.086833869e-02f, -1.482646439e-02f}, + std::array{5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, -5.000000000e-02f, 6.454972244e-02f, 6.454972244e-02f, 0.000000000e+00f, 6.454972244e-02f, 0.000000000e+00f, -1.016220987e-01f, -6.338656910e-02f, 1.092600649e-02f, 7.364853795e-02f, -1.011266756e-01f, 7.086833869e-02f, 1.482646439e-02f}, +}; +constexpr std::array ThirdOrderEncoder{ CalcAmbiCoeffs( 0.35682208976f, 0.93417235897f, 0.00000000000f), CalcAmbiCoeffs(-0.35682208976f, 0.93417235897f, 0.00000000000f), CalcAmbiCoeffs( 0.35682208976f, -0.93417235897f, 0.00000000000f), @@ -195,24 +198,24 @@ constexpr std::array ThirdOrderEncoder{{ CalcAmbiCoeffs( inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), CalcAmbiCoeffs( -inv_sqrt3f, -inv_sqrt3f, inv_sqrt3f), CalcAmbiCoeffs( -inv_sqrt3f, -inv_sqrt3f, -inv_sqrt3f), -}}; +}; static_assert(ThirdOrderDecoder.size() == ThirdOrderEncoder.size(), "Third-order mismatch"); /* This calculates a 2D third-order "upsampler" matrix. Same as the third-order * matrix, just using a more optimized speaker array for horizontal-only * content. */ -constexpr std::array,8> ThirdOrder2DDecoder{{ - {{ 1.250000000e-01f, -5.523559567e-02f, 0.0f, 1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f, }}, - {{ 1.250000000e-01f, -1.333505242e-01f, 0.0f, 5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f, }}, - {{ 1.250000000e-01f, -1.333505242e-01f, 0.0f, -5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f, }}, - {{ 1.250000000e-01f, -5.523559567e-02f, 0.0f, -1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f, }}, - {{ 1.250000000e-01f, 5.523559567e-02f, 0.0f, -1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f, }}, - {{ 1.250000000e-01f, 1.333505242e-01f, 0.0f, -5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f, }}, - {{ 1.250000000e-01f, 1.333505242e-01f, 0.0f, 5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f, }}, - {{ 1.250000000e-01f, 5.523559567e-02f, 0.0f, 1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f, }}, -}}; -constexpr std::array ThirdOrder2DEncoder{{ +constexpr std::array ThirdOrder2DDecoder{ + std::array{1.250000000e-01f, -5.523559567e-02f, 0.0f, 1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f}, + std::array{1.250000000e-01f, -1.333505242e-01f, 0.0f, 5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f}, + std::array{1.250000000e-01f, -1.333505242e-01f, 0.0f, -5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, 4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f}, + std::array{1.250000000e-01f, -5.523559567e-02f, 0.0f, -1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, -1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f}, + std::array{1.250000000e-01f, 5.523559567e-02f, 0.0f, -1.333505242e-01f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -4.573941867e-02f}, + std::array{1.250000000e-01f, 1.333505242e-01f, 0.0f, -5.523559567e-02f, -9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 1.104247249e-01f}, + std::array{1.250000000e-01f, 1.333505242e-01f, 0.0f, 5.523559567e-02f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, -9.128709292e-02f, -4.573941867e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -1.104247249e-01f}, + std::array{1.250000000e-01f, 5.523559567e-02f, 0.0f, 1.333505242e-01f, 9.128709292e-02f, 0.0f, 0.0f, 0.0f, 9.128709292e-02f, 1.104247249e-01f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 4.573941867e-02f}, +}; +constexpr std::array ThirdOrder2DEncoder{ CalcAmbiCoeffs(-0.38268343237f, 0.0f, 0.92387953251f), CalcAmbiCoeffs(-0.92387953251f, 0.0f, 0.38268343237f), CalcAmbiCoeffs(-0.92387953251f, 0.0f, -0.38268343237f), @@ -221,7 +224,7 @@ constexpr std::array ThirdOrder2DEncoder{{ CalcAmbiCoeffs( 0.92387953251f, 0.0f, -0.38268343237f), CalcAmbiCoeffs( 0.92387953251f, 0.0f, 0.38268343237f), CalcAmbiCoeffs( 0.38268343237f, 0.0f, 0.92387953251f), -}}; +}; static_assert(ThirdOrder2DDecoder.size() == ThirdOrder2DEncoder.size(), "Third-order 2D mismatch"); @@ -230,19 +233,19 @@ static_assert(ThirdOrder2DDecoder.size() == ThirdOrder2DEncoder.size(), "Third-o * the foreseeable future. This is only necessary for mixing horizontal-only * fourth-order content to 3D. */ -constexpr std::array,10> FourthOrder2DDecoder{{ - {{ 1.000000000e-01f, 3.568220898e-02f, 0.0f, 1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, 9.341723590e-02f, 0.0f, 6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, 1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, -9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f, }}, - {{ 1.000000000e-01f, 9.341723590e-02f, 0.0f, -6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, 3.568220898e-02f, 0.0f, -1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, -3.568220898e-02f, 0.0f, -1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, - {{ 1.000000000e-01f, -9.341723590e-02f, 0.0f, -6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, -1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, 9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f, }}, - {{ 1.000000000e-01f, -9.341723590e-02f, 0.0f, 6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f, }}, - {{ 1.000000000e-01f, -3.568220898e-02f, 0.0f, 1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f, }}, -}}; -constexpr std::array FourthOrder2DEncoder{{ +constexpr std::array FourthOrder2DDecoder{ + std::array{1.000000000e-01f, 3.568220898e-02f, 0.0f, 1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, 9.341723590e-02f, 0.0f, 6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, 1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, -9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f}, + std::array{1.000000000e-01f, 9.341723590e-02f, 0.0f, -6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, 2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, 3.568220898e-02f, 0.0f, -1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, 7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, -3.568220898e-02f, 0.0f, -1.098185471e-01f, 6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -5.620301997e-02f, 8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, + std::array{1.000000000e-01f, -9.341723590e-02f, 0.0f, -6.787159473e-02f, 9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.093839659e-02f, -5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, -1.154700538e-01f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, -1.032795559e-01f, 9.561828875e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.000000000e+00f, 0.000000000e+00f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 9.014978717e-02f}, + std::array{1.000000000e-01f, -9.341723590e-02f, 0.0f, 6.787159473e-02f, -9.822469464e-02f, 0.0f, 0.0f, 0.0f, -3.191513794e-02f, -2.954767620e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -9.093839659e-02f, 5.298871540e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, -7.293270986e-02f}, + std::array{1.000000000e-01f, -3.568220898e-02f, 0.0f, 1.098185471e-01f, -6.070619982e-02f, 0.0f, 0.0f, 0.0f, 8.355491589e-02f, -7.735682057e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 5.620301997e-02f, -8.573754253e-02f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 2.785781628e-02f}, +}; +constexpr std::array FourthOrder2DEncoder{ CalcAmbiCoeffs( 3.090169944e-01f, 0.000000000e+00f, 9.510565163e-01f), CalcAmbiCoeffs( 8.090169944e-01f, 0.000000000e+00f, 5.877852523e-01f), CalcAmbiCoeffs( 1.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f), @@ -253,7 +256,7 @@ constexpr std::array FourthOrder2DEncoder{{ CalcAmbiCoeffs(-1.000000000e+00f, 0.000000000e+00f, 0.000000000e+00f), CalcAmbiCoeffs(-8.090169944e-01f, 0.000000000e+00f, 5.877852523e-01f), CalcAmbiCoeffs(-3.090169944e-01f, 0.000000000e+00f, 9.510565163e-01f), -}}; +}; static_assert(FourthOrder2DDecoder.size() == FourthOrder2DEncoder.size(), "Fourth-order 2D mismatch"); @@ -279,13 +282,13 @@ constexpr auto CalcAmbiUpsampler(const std::array,M> &decode } // namespace -const std::array AmbiScale::FirstOrderUp{CalcAmbiUpsampler(FirstOrderDecoder, FirstOrderEncoder)}; -const std::array AmbiScale::FirstOrder2DUp{CalcAmbiUpsampler(FirstOrder2DDecoder, FirstOrder2DEncoder)}; -const std::array AmbiScale::SecondOrderUp{CalcAmbiUpsampler(SecondOrderDecoder, SecondOrderEncoder)}; -const std::array AmbiScale::SecondOrder2DUp{CalcAmbiUpsampler(SecondOrder2DDecoder, SecondOrder2DEncoder)}; -const std::array AmbiScale::ThirdOrderUp{CalcAmbiUpsampler(ThirdOrderDecoder, ThirdOrderEncoder)}; -const std::array AmbiScale::ThirdOrder2DUp{CalcAmbiUpsampler(ThirdOrder2DDecoder, ThirdOrder2DEncoder)}; -const std::array AmbiScale::FourthOrder2DUp{CalcAmbiUpsampler(FourthOrder2DDecoder, FourthOrder2DEncoder)}; +const std::array,4> AmbiScale::FirstOrderUp{CalcAmbiUpsampler(FirstOrderDecoder, FirstOrderEncoder)}; +const std::array,4> AmbiScale::FirstOrder2DUp{CalcAmbiUpsampler(FirstOrder2DDecoder, FirstOrder2DEncoder)}; +const std::array,9> AmbiScale::SecondOrderUp{CalcAmbiUpsampler(SecondOrderDecoder, SecondOrderEncoder)}; +const std::array,9> AmbiScale::SecondOrder2DUp{CalcAmbiUpsampler(SecondOrder2DDecoder, SecondOrder2DEncoder)}; +const std::array,16> AmbiScale::ThirdOrderUp{CalcAmbiUpsampler(ThirdOrderDecoder, ThirdOrderEncoder)}; +const std::array,16> AmbiScale::ThirdOrder2DUp{CalcAmbiUpsampler(ThirdOrder2DDecoder, ThirdOrder2DEncoder)}; +const std::array,25> AmbiScale::FourthOrder2DUp{CalcAmbiUpsampler(FourthOrder2DDecoder, FourthOrder2DEncoder)}; std::array AmbiScale::GetHFOrderScales(const uint src_order, diff --git a/3rdparty/openal/core/ambidefs.h b/3rdparty/openal/core/ambidefs.h index bea1a312079b..2e7774a957ba 100644 --- a/3rdparty/openal/core/ambidefs.h +++ b/3rdparty/openal/core/ambidefs.h @@ -2,8 +2,8 @@ #define CORE_AMBIDEFS_H #include -#include -#include +#include +#include #include "alnumbers.h" @@ -14,10 +14,10 @@ using uint = unsigned int; * needed will be (o+1)**2, thus zero-order has 1, first-order has 4, second- * order has 9, third-order has 16, and fourth-order has 25. */ -inline constexpr uint8_t MaxAmbiOrder{3}; -constexpr inline size_t AmbiChannelsFromOrder(size_t order) noexcept +constexpr auto AmbiChannelsFromOrder(std::size_t order) noexcept -> std::size_t { return (order+1) * (order+1); } -inline constexpr size_t MaxAmbiChannels{AmbiChannelsFromOrder(MaxAmbiOrder)}; +inline constexpr auto MaxAmbiOrder = std::uint8_t{3}; +inline constexpr auto MaxAmbiChannels = size_t{AmbiChannelsFromOrder(MaxAmbiOrder)}; /* A bitmask of ambisonic channels for 0 to 4th order. This only specifies up * to 4th order, which is the highest order a 32-bit mask value can specify (a @@ -39,20 +39,20 @@ inline constexpr uint AmbiPeriphonicMask{0xfe7ce4}; * representation. This is 2 per each order above zero-order, plus 1 for zero- * order. Or simply, o*2 + 1. */ -constexpr inline size_t Ambi2DChannelsFromOrder(size_t order) noexcept +constexpr auto Ambi2DChannelsFromOrder(std::size_t order) noexcept -> std::size_t { return order*2 + 1; } -inline constexpr size_t MaxAmbi2DChannels{Ambi2DChannelsFromOrder(MaxAmbiOrder)}; +inline constexpr auto MaxAmbi2DChannels = Ambi2DChannelsFromOrder(MaxAmbiOrder); /* NOTE: These are scale factors as applied to Ambisonics content. Decoder * coefficients should be divided by these values to get proper scalings. */ struct AmbiScale { - static inline constexpr std::array FromN3D{{ + static constexpr auto FromN3D = std::array{ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f - }}; - static inline constexpr std::array FromSN3D{{ + }; + static constexpr auto FromSN3D = std::array{ 1.000000000f, /* ACN 0, sqrt(1) */ 1.732050808f, /* ACN 1, sqrt(3) */ 1.732050808f, /* ACN 2, sqrt(3) */ @@ -69,8 +69,8 @@ struct AmbiScale { 2.645751311f, /* ACN 13, sqrt(7) */ 2.645751311f, /* ACN 14, sqrt(7) */ 2.645751311f, /* ACN 15, sqrt(7) */ - }}; - static inline constexpr std::array FromFuMa{{ + }; + static constexpr auto FromFuMa = std::array{ 1.414213562f, /* ACN 0 (W), sqrt(2) */ 1.732050808f, /* ACN 1 (Y), sqrt(3) */ 1.732050808f, /* ACN 2 (Z), sqrt(3) */ @@ -87,15 +87,15 @@ struct AmbiScale { 2.231093404f, /* ACN 13 (L), sqrt(224/45) */ 1.972026594f, /* ACN 14 (N), sqrt(35)/3 */ 2.091650066f, /* ACN 15 (P), sqrt(35/8) */ - }}; - static inline constexpr std::array FromUHJ{{ + }; + static constexpr auto FromUHJ = std::array{ 1.000000000f, /* ACN 0 (W), sqrt(1) */ 1.224744871f, /* ACN 1 (Y), sqrt(3/2) */ 1.224744871f, /* ACN 2 (Z), sqrt(3/2) */ 1.224744871f, /* ACN 3 (X), sqrt(3/2) */ /* Higher orders not relevant for UHJ. */ 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, 1.0f, - }}; + }; /* Retrieves per-order HF scaling factors for "upsampling" ambisonic data. */ static std::array GetHFOrderScales(const uint src_order, @@ -111,7 +111,7 @@ struct AmbiScale { }; struct AmbiIndex { - static inline constexpr std::array FromFuMa{{ + static constexpr auto FromFuMa = std::array{ 0, /* W */ 3, /* X */ 1, /* Y */ @@ -128,8 +128,8 @@ struct AmbiIndex { 10, /* O */ 15, /* P */ 9, /* Q */ - }}; - static inline constexpr std::array FromFuMa2D{{ + }; + static constexpr auto FromFuMa2D = std::array{ 0, /* W */ 3, /* X */ 1, /* Y */ @@ -137,23 +137,23 @@ struct AmbiIndex { 4, /* V */ 15, /* P */ 9, /* Q */ - }}; + }; - static inline constexpr std::array FromACN{{ + static constexpr auto FromACN = std::array{ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 - }}; - static inline constexpr std::array FromACN2D{{ + }; + static constexpr auto FromACN2D = std::array{ 0, 1,3, 4,8, 9,15 - }}; + }; - static inline constexpr std::array OrderFromChannel{{ + static constexpr auto OrderFromChannel = std::array{ 0, 1,1,1, 2,2,2,2,2, 3,3,3,3,3,3,3, - }}; - static inline constexpr std::array OrderFrom2DChannel{{ + }; + static constexpr auto OrderFrom2DChannel = std::array{ 0, 1,1, 2,2, 3,3, - }}; + }; }; diff --git a/3rdparty/openal/core/async_event.h b/3rdparty/openal/core/async_event.h index f1ca0c7b6251..f865fd8a809b 100644 --- a/3rdparty/openal/core/async_event.h +++ b/3rdparty/openal/core/async_event.h @@ -1,7 +1,9 @@ #ifndef CORE_EVENT_H #define CORE_EVENT_H -#include +#include +#include +#include #include #include "almalloc.h" @@ -11,7 +13,7 @@ struct EffectState; using uint = unsigned int; -enum class AsyncEnableBits : uint8_t { +enum class AsyncEnableBits : std::uint8_t { SourceState, BufferCompleted, Disconnected, @@ -19,7 +21,7 @@ enum class AsyncEnableBits : uint8_t { }; -enum class AsyncSrcState : uint8_t { +enum class AsyncSrcState : std::uint8_t { Reset, Stop, Play, @@ -39,7 +41,7 @@ struct AsyncBufferCompleteEvent { }; struct AsyncDisconnectEvent { - char msg[244]; + std::string msg; }; struct AsyncEffectReleaseEvent { diff --git a/3rdparty/openal/core/bformatdec.cpp b/3rdparty/openal/core/bformatdec.cpp index a308e1856967..1e46e9508ced 100644 --- a/3rdparty/openal/core/bformatdec.cpp +++ b/3rdparty/openal/core/bformatdec.cpp @@ -6,11 +6,13 @@ #include #include #include +#include #include -#include "almalloc.h" #include "alnumbers.h" +#include "bufferline.h" #include "filters/splitter.h" +#include "flexarray.h" #include "front_stablizer.h" #include "mixer.h" #include "opthelpers.h" @@ -36,9 +38,8 @@ BFormatDec::BFormatDec(const size_t inchans, const al::span co auto &decoder = mChannelDec.emplace>(inchans); for(size_t j{0};j < decoder.size();++j) { - float *outcoeffs{decoder[j].mGains}; - for(const ChannelDec &incoeffs : coeffs) - *(outcoeffs++) = incoeffs[j]; + std::transform(coeffs.cbegin(), coeffs.cend(), decoder[j].mGains.begin(), + [j](const ChannelDec &incoeffs) { return incoeffs[j]; }); } } else @@ -50,45 +51,40 @@ BFormatDec::BFormatDec(const size_t inchans, const al::span co for(size_t j{0};j < decoder.size();++j) { - float *outcoeffs{decoder[j].mGains[sHFBand]}; - for(const ChannelDec &incoeffs : coeffs) - *(outcoeffs++) = incoeffs[j]; + std::transform(coeffs.cbegin(), coeffs.cend(), decoder[j].mGains[sHFBand].begin(), + [j](const ChannelDec &incoeffs) { return incoeffs[j]; }); - outcoeffs = decoder[j].mGains[sLFBand]; - for(const ChannelDec &incoeffs : coeffslf) - *(outcoeffs++) = incoeffs[j]; + std::transform(coeffslf.cbegin(), coeffslf.cend(), decoder[j].mGains[sLFBand].begin(), + [j](const ChannelDec &incoeffs) { return incoeffs[j]; }); } } } void BFormatDec::process(const al::span OutBuffer, - const FloatBufferLine *InSamples, const size_t SamplesToDo) + const al::span InSamples, const size_t SamplesToDo) { ASSUME(SamplesToDo > 0); auto decode_dualband = [=](std::vector &decoder) { - auto *input = InSamples; - const al::span hfSamples{mSamples[sHFBand].data(), SamplesToDo}; - const al::span lfSamples{mSamples[sLFBand].data(), SamplesToDo}; + auto input = InSamples.cbegin(); + const auto hfSamples = al::span{mSamples[sHFBand]}.first(SamplesToDo); + const auto lfSamples = al::span{mSamples[sLFBand]}.first(SamplesToDo); for(auto &chandec : decoder) { - chandec.mXOver.process({input->data(), SamplesToDo}, hfSamples.data(), - lfSamples.data()); + chandec.mXOver.process(al::span{*input++}.first(SamplesToDo), hfSamples, lfSamples); MixSamples(hfSamples, OutBuffer, chandec.mGains[sHFBand], chandec.mGains[sHFBand],0,0); MixSamples(lfSamples, OutBuffer, chandec.mGains[sLFBand], chandec.mGains[sLFBand],0,0); - ++input; } }; auto decode_singleband = [=](std::vector &decoder) { - auto *input = InSamples; + auto input = InSamples.cbegin(); for(auto &chandec : decoder) { - MixSamples({input->data(), SamplesToDo}, OutBuffer, chandec.mGains, chandec.mGains, - 0, 0); - ++input; + MixSamples(al::span{*input++}.first(SamplesToDo), OutBuffer, chandec.mGains, + chandec.mGains, 0, 0); } }; @@ -96,38 +92,36 @@ void BFormatDec::process(const al::span OutBuffer, } void BFormatDec::processStablize(const al::span OutBuffer, - const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx, - const size_t SamplesToDo) + const al::span InSamples, const size_t lidx, const size_t ridx, + const size_t cidx, const size_t SamplesToDo) { ASSUME(SamplesToDo > 0); /* Move the existing direct L/R signal out so it doesn't get processed by * the stablizer. */ - float *RESTRICT mid{al::assume_aligned<16>(mStablizer->MidDirect.data())}; - float *RESTRICT side{al::assume_aligned<16>(mStablizer->Side.data())}; - for(size_t i{0};i < SamplesToDo;++i) - { - mid[i] = OutBuffer[lidx][i] + OutBuffer[ridx][i]; - side[i] = OutBuffer[lidx][i] - OutBuffer[ridx][i]; - } - std::fill_n(OutBuffer[lidx].begin(), SamplesToDo, 0.0f); - std::fill_n(OutBuffer[ridx].begin(), SamplesToDo, 0.0f); + const auto leftout = al::span{OutBuffer[lidx]}.first(SamplesToDo); + const auto rightout = al::span{OutBuffer[ridx]}.first(SamplesToDo); + const auto mid = al::span{mStablizer->MidDirect}.first(SamplesToDo); + const auto side = al::span{mStablizer->Side}.first(SamplesToDo); + std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), mid.begin(),std::plus{}); + std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), side.begin(),std::minus{}); + std::fill_n(leftout.begin(), leftout.size(), 0.0f); + std::fill_n(rightout.begin(), rightout.size(), 0.0f); /* Decode the B-Format input to OutBuffer. */ process(OutBuffer, InSamples, SamplesToDo); /* Include the decoded side signal with the direct side signal. */ for(size_t i{0};i < SamplesToDo;++i) - side[i] += OutBuffer[lidx][i] - OutBuffer[ridx][i]; + side[i] += leftout[i] - rightout[i]; /* Get the decoded mid signal and band-split it. */ - std::transform(OutBuffer[lidx].cbegin(), OutBuffer[lidx].cbegin()+SamplesToDo, - OutBuffer[ridx].cbegin(), mStablizer->Temp.begin(), - [](const float l, const float r) noexcept { return l + r; }); + const auto tmpsamples = al::span{mStablizer->Temp}.first(SamplesToDo); + std::transform(leftout.cbegin(), leftout.cend(), rightout.cbegin(), tmpsamples.begin(), + std::plus{}); - mStablizer->MidFilter.process({mStablizer->Temp.data(), SamplesToDo}, mStablizer->MidHF.data(), - mStablizer->MidLF.data()); + mStablizer->MidFilter.process(tmpsamples, mStablizer->MidHF, mStablizer->MidLF); /* Apply an all-pass to all channels to match the band-splitter's phase * shift. This is to keep the phase synchronized between the existing @@ -140,9 +134,9 @@ void BFormatDec::processStablize(const al::span OutBuffer, * and substitute the direct mid signal and direct+decoded side signal. */ if(i == lidx) - mStablizer->ChannelFilters[i].processAllPass({mid, SamplesToDo}); + mStablizer->ChannelFilters[i].processAllPass(mid); else if(i == ridx) - mStablizer->ChannelFilters[i].processAllPass({side, SamplesToDo}); + mStablizer->ChannelFilters[i].processAllPass(side); else mStablizer->ChannelFilters[i].processAllPass({OutBuffer[i].data(), SamplesToDo}); } @@ -156,6 +150,7 @@ void BFormatDec::processStablize(const al::span OutBuffer, const float cos_hf{std::cos(1.0f/4.0f * (al::numbers::pi_v*0.5f))}; const float sin_lf{std::sin(1.0f/3.0f * (al::numbers::pi_v*0.5f))}; const float sin_hf{std::sin(1.0f/4.0f * (al::numbers::pi_v*0.5f))}; + const auto centerout = al::span{OutBuffer[cidx]}.first(SamplesToDo); for(size_t i{0};i < SamplesToDo;i++) { /* Add the direct mid signal to the processed mid signal so it can be @@ -168,9 +163,9 @@ void BFormatDec::processStablize(const al::span OutBuffer, /* The generated center channel signal adds to the existing signal, * while the modified left and right channels replace. */ - OutBuffer[lidx][i] = (m + s) * 0.5f; - OutBuffer[ridx][i] = (m - s) * 0.5f; - OutBuffer[cidx][i] += c * 0.5f; + leftout[i] = (m + s) * 0.5f; + rightout[i] = (m - s) * 0.5f; + centerout[i] += c * 0.5f; } } diff --git a/3rdparty/openal/core/bformatdec.h b/3rdparty/openal/core/bformatdec.h index 3bb7f544899b..b86f771da15c 100644 --- a/3rdparty/openal/core/bformatdec.h +++ b/3rdparty/openal/core/bformatdec.h @@ -7,33 +7,32 @@ #include #include -#include "almalloc.h" #include "alspan.h" #include "ambidefs.h" #include "bufferline.h" #include "devformat.h" #include "filters/splitter.h" - -struct FrontStablizer; +#include "front_stablizer.h" +#include "opthelpers.h" using ChannelDec = std::array; -class BFormatDec { +class SIMDALIGN BFormatDec { static constexpr size_t sHFBand{0}; static constexpr size_t sLFBand{1}; static constexpr size_t sNumBands{2}; struct ChannelDecoderSingle { - float mGains[MAX_OUTPUT_CHANNELS]; + std::array mGains{}; }; struct ChannelDecoderDual { BandSplitter mXOver; - float mGains[sNumBands][MAX_OUTPUT_CHANNELS]; + std::array,sNumBands> mGains{}; }; - alignas(16) std::array mSamples; + alignas(16) std::array mSamples{}; const std::unique_ptr mStablizer; @@ -44,22 +43,20 @@ class BFormatDec { const al::span coeffslf, const float xover_f0norm, std::unique_ptr stablizer); - bool hasStablizer() const noexcept { return mStablizer != nullptr; } + [[nodiscard]] auto hasStablizer() const noexcept -> bool { return mStablizer != nullptr; } /* Decodes the ambisonic input to the given output channels. */ - void process(const al::span OutBuffer, const FloatBufferLine *InSamples, - const size_t SamplesToDo); + void process(const al::span OutBuffer, + const al::span InSamples, const size_t SamplesToDo); /* Decodes the ambisonic input to the given output channels with stablization. */ void processStablize(const al::span OutBuffer, - const FloatBufferLine *InSamples, const size_t lidx, const size_t ridx, const size_t cidx, - const size_t SamplesToDo); + const al::span InSamples, const size_t lidx, const size_t ridx, + const size_t cidx, const size_t SamplesToDo); static std::unique_ptr Create(const size_t inchans, const al::span coeffs, const al::span coeffslf, const float xover_f0norm, std::unique_ptr stablizer); - - DEF_NEWDEL(BFormatDec) }; #endif /* CORE_BFORMATDEC_H */ diff --git a/3rdparty/openal/core/bs2b.cpp b/3rdparty/openal/core/bs2b.cpp index 303bf9bd9300..68b0d575fba3 100644 --- a/3rdparty/openal/core/bs2b.cpp +++ b/3rdparty/openal/core/bs2b.cpp @@ -26,72 +26,75 @@ #include #include #include +#include #include "alnumbers.h" +#include "alspan.h" #include "bs2b.h" +namespace { /* Set up all data. */ -static void init(struct bs2b *bs2b) +void init(Bs2b::bs2b *bs2b) { float Fc_lo, Fc_hi; float G_lo, G_hi; - float x, g; switch(bs2b->level) { - case BS2B_LOW_CLEVEL: /* Low crossfeed level */ + case Bs2b::LowCLevel: /* Low crossfeed level */ Fc_lo = 360.0f; Fc_hi = 501.0f; G_lo = 0.398107170553497f; G_hi = 0.205671765275719f; break; - case BS2B_MIDDLE_CLEVEL: /* Middle crossfeed level */ + case Bs2b::MiddleCLevel: /* Middle crossfeed level */ Fc_lo = 500.0f; Fc_hi = 711.0f; G_lo = 0.459726988530872f; G_hi = 0.228208484414988f; break; - case BS2B_HIGH_CLEVEL: /* High crossfeed level (virtual speakers are closer to itself) */ + case Bs2b::HighCLevel: /* High crossfeed level (virtual speakers are closer to itself) */ Fc_lo = 700.0f; Fc_hi = 1021.0f; G_lo = 0.530884444230988f; G_hi = 0.250105790667544f; break; - case BS2B_LOW_ECLEVEL: /* Low easy crossfeed level */ + case Bs2b::LowECLevel: /* Low easy crossfeed level */ Fc_lo = 360.0f; Fc_hi = 494.0f; G_lo = 0.316227766016838f; G_hi = 0.168236228897329f; break; - case BS2B_MIDDLE_ECLEVEL: /* Middle easy crossfeed level */ + case Bs2b::MiddleECLevel: /* Middle easy crossfeed level */ Fc_lo = 500.0f; Fc_hi = 689.0f; G_lo = 0.354813389233575f; G_hi = 0.187169483835901f; break; - default: /* High easy crossfeed level */ - bs2b->level = BS2B_HIGH_ECLEVEL; + case Bs2b::HighECLevel: /* High easy crossfeed level */ + default: + bs2b->level = Bs2b::HighECLevel; Fc_lo = 700.0f; Fc_hi = 975.0f; G_lo = 0.398107170553497f; G_hi = 0.205671765275719f; break; - } /* switch */ + } - g = 1.0f / (1.0f - G_hi + G_lo); + float g{1.0f / (1.0f - G_hi + G_lo)}; /* $fc = $Fc / $s; * $d = 1 / 2 / pi / $fc; * $x = exp(-1 / $d); */ - x = std::exp(-al::numbers::pi_v*2.0f*Fc_lo/static_cast(bs2b->srate)); + float x{ std::exp(-al::numbers::pi_v*2.0f*Fc_lo/static_cast(bs2b->srate))}; bs2b->b1_lo = x; bs2b->a0_lo = G_lo * (1.0f - x) * g; @@ -99,85 +102,86 @@ static void init(struct bs2b *bs2b) bs2b->b1_hi = x; bs2b->a0_hi = (1.0f - G_hi * (1.0f - x)) * g; bs2b->a1_hi = -x * g; -} /* init */ +} +} // namespace /* Exported functions. * See descriptions in "bs2b.h" */ +namespace Bs2b { -void bs2b_set_params(struct bs2b *bs2b, int level, int srate) -{ - if(srate <= 0) srate = 1; - - bs2b->level = level; - bs2b->srate = srate; - init(bs2b); -} /* bs2b_set_params */ - -int bs2b_get_level(struct bs2b *bs2b) +void bs2b::set_params(int level_, int srate_) { - return bs2b->level; -} /* bs2b_get_level */ + if(srate_ < 1) + throw std::runtime_error{"BS2B srate < 1"}; -int bs2b_get_srate(struct bs2b *bs2b) -{ - return bs2b->srate; -} /* bs2b_get_srate */ + level = level_; + srate = srate_; + init(this); +} -void bs2b_clear(struct bs2b *bs2b) +void bs2b::clear() { - std::fill(std::begin(bs2b->history), std::end(bs2b->history), bs2b::t_last_sample{}); -} /* bs2b_clear */ + history.fill(bs2b::t_last_sample{}); +} -void bs2b_cross_feed(struct bs2b *bs2b, float *Left, float *Right, size_t SamplesToDo) +void bs2b::cross_feed(const al::span Left, const al::span Right) { - const float a0_lo{bs2b->a0_lo}; - const float b1_lo{bs2b->b1_lo}; - const float a0_hi{bs2b->a0_hi}; - const float a1_hi{bs2b->a1_hi}; - const float b1_hi{bs2b->b1_hi}; - float lsamples[128][2]; - float rsamples[128][2]; - - for(size_t base{0};base < SamplesToDo;) + const auto a0lo = a0_lo; + const auto b1lo = b1_lo; + const auto a0hi = a0_hi; + const auto a1hi = a1_hi; + const auto b1hi = b1_hi; + auto lsamples = Left.first(std::min(Left.size(), Right.size())); + auto rsamples = Right.first(lsamples.size()); + auto samples = std::array,128>{}; + + auto leftio = lsamples.begin(); + auto rightio = rsamples.begin(); + while(auto rem = std::distance(leftio, lsamples.end())) { - const size_t todo{std::min(128, SamplesToDo-base)}; + const auto todo = std::min(samples.size(), rem); /* Process left input */ - float z_lo{bs2b->history[0].lo}; - float z_hi{bs2b->history[0].hi}; - for(size_t i{0};i < todo;i++) - { - lsamples[i][0] = a0_lo*Left[i] + z_lo; - z_lo = b1_lo*lsamples[i][0]; - - lsamples[i][1] = a0_hi*Left[i] + z_hi; - z_hi = a1_hi*Left[i] + b1_hi*lsamples[i][1]; - } - bs2b->history[0].lo = z_lo; - bs2b->history[0].hi = z_hi; + auto z_lo = history[0].lo; + auto z_hi = history[0].hi; + std::transform(leftio, leftio+todo, samples.begin(), + [a0hi,a1hi,b1hi,a0lo,b1lo,&z_lo,&z_hi](const float x) noexcept + { + const auto y0 = a0hi*x + z_hi; + z_hi = a1hi*x + b1hi*y0; + + const auto y1 = a0lo*x + z_lo; + z_lo = b1lo*y1; + + return std::array{y0, y1}; + }); + history[0].lo = z_lo; + history[0].hi = z_hi; /* Process right input */ - z_lo = bs2b->history[1].lo; - z_hi = bs2b->history[1].hi; - for(size_t i{0};i < todo;i++) - { - rsamples[i][0] = a0_lo*Right[i] + z_lo; - z_lo = b1_lo*rsamples[i][0]; - - rsamples[i][1] = a0_hi*Right[i] + z_hi; - z_hi = a1_hi*Right[i] + b1_hi*rsamples[i][1]; - } - bs2b->history[1].lo = z_lo; - bs2b->history[1].hi = z_hi; - - /* Crossfeed */ - for(size_t i{0};i < todo;i++) - *(Left++) = lsamples[i][1] + rsamples[i][0]; - for(size_t i{0};i < todo;i++) - *(Right++) = rsamples[i][1] + lsamples[i][0]; - - base += todo; + z_lo = history[1].lo; + z_hi = history[1].hi; + std::transform(rightio, rightio+todo, samples.cbegin(), samples.begin(), + [a0hi,a1hi,b1hi,a0lo,b1lo,&z_lo,&z_hi](const float x, const std::array &out) noexcept + { + const auto y0 = a0lo*x + z_lo; + z_lo = b1lo*y0; + + const auto y1 = a0hi*x + z_hi; + z_hi = a1hi*x + b1hi*y1; + + return std::array{out[0]+y0, out[1]+y1}; + }); + history[1].lo = z_lo; + history[1].hi = z_hi; + + leftio = std::transform(samples.cbegin(), samples.cbegin()+todo, leftio, + [](const std::array &in) { return in[0]; }); + rightio = std::transform(samples.cbegin(), samples.cbegin()+todo, rightio, + [](const std::array &in) { return in[1]; }); } -} /* bs2b_cross_feed */ +} + +} // namespace Bs2b diff --git a/3rdparty/openal/core/bs2b.h b/3rdparty/openal/core/bs2b.h index 4d0b9dd8e14e..dd6d3ce24573 100644 --- a/3rdparty/openal/core/bs2b.h +++ b/3rdparty/openal/core/bs2b.h @@ -24,66 +24,68 @@ #ifndef CORE_BS2B_H #define CORE_BS2B_H -#include "almalloc.h" +#include +#include -/* Number of crossfeed levels */ -#define BS2B_CLEVELS 3 +#include "alspan.h" -/* Normal crossfeed levels */ -#define BS2B_HIGH_CLEVEL 3 -#define BS2B_MIDDLE_CLEVEL 2 -#define BS2B_LOW_CLEVEL 1 +namespace Bs2b { -/* Easy crossfeed levels */ -#define BS2B_HIGH_ECLEVEL BS2B_HIGH_CLEVEL + BS2B_CLEVELS -#define BS2B_MIDDLE_ECLEVEL BS2B_MIDDLE_CLEVEL + BS2B_CLEVELS -#define BS2B_LOW_ECLEVEL BS2B_LOW_CLEVEL + BS2B_CLEVELS +enum { + /* Normal crossfeed levels */ + LowCLevel = 1, + MiddleCLevel = 2, + HighCLevel = 3, -/* Default crossfeed levels */ -#define BS2B_DEFAULT_CLEVEL BS2B_HIGH_ECLEVEL -/* Default sample rate (Hz) */ -#define BS2B_DEFAULT_SRATE 44100 + /* Easy crossfeed levels */ + LowECLevel = 4, + MiddleECLevel = 5, + HighECLevel = 6, + + DefaultCLevel = HighECLevel +}; struct bs2b { - int level; /* Crossfeed level */ - int srate; /* Sample rate (Hz) */ + int level{}; /* Crossfeed level */ + int srate{}; /* Sample rate (Hz) */ /* Lowpass IIR filter coefficients */ - float a0_lo; - float b1_lo; + float a0_lo{}; + float b1_lo{}; /* Highboost IIR filter coefficients */ - float a0_hi; - float a1_hi; - float b1_hi; + float a0_hi{}; + float a1_hi{}; + float b1_hi{}; /* Buffer of filter history * [0] - first channel, [1] - second channel */ struct t_last_sample { - float lo; - float hi; - } history[2]; - - DEF_NEWDEL(bs2b) -}; + float lo{}; + float hi{}; + }; + std::array history{}; + + /* Clear buffers and set new coefficients with new crossfeed level and + * sample rate values. + * level - crossfeed level of *Level enum values. + * srate - sample rate by Hz. + */ + void set_params(int level, int srate); -/* Clear buffers and set new coefficients with new crossfeed level and sample - * rate values. - * level - crossfeed level of *LEVEL values. - * srate - sample rate by Hz. - */ -void bs2b_set_params(bs2b *bs2b, int level, int srate); + /* Return current crossfeed level value */ + [[nodiscard]] auto get_level() const noexcept -> int { return level; } -/* Return current crossfeed level value */ -int bs2b_get_level(bs2b *bs2b); + /* Return current sample rate value */ + [[nodiscard]] auto get_srate() const noexcept -> int { return srate; } -/* Return current sample rate value */ -int bs2b_get_srate(bs2b *bs2b); + /* Clear buffer */ + void clear(); -/* Clear buffer */ -void bs2b_clear(bs2b *bs2b); + void cross_feed(const al::span Left, const al::span Right); +}; -void bs2b_cross_feed(bs2b *bs2b, float *Left, float *Right, size_t SamplesToDo); +} // namespace Bs2b #endif /* CORE_BS2B_H */ diff --git a/3rdparty/openal/core/bsinc_tables.cpp b/3rdparty/openal/core/bsinc_tables.cpp index 1b3f57841a2f..35b197a85afe 100644 --- a/3rdparty/openal/core/bsinc_tables.cpp +++ b/3rdparty/openal/core/bsinc_tables.cpp @@ -5,12 +5,16 @@ #include #include #include +#include #include -#include -#include +#include +#include #include "alnumbers.h" +#include "alnumeric.h" +#include "alspan.h" #include "bsinc_defs.h" +#include "opthelpers.h" #include "resampler_limits.h" @@ -19,37 +23,32 @@ namespace { using uint = unsigned int; -/* This is the normalized cardinal sine (sinc) function. - * - * sinc(x) = { 1, x = 0 - * { sin(pi x) / (pi x), otherwise. - */ -constexpr double Sinc(const double x) -{ - constexpr double epsilon{std::numeric_limits::epsilon()}; - if(!(x > epsilon || x < -epsilon)) - return 1.0; - return std::sin(al::numbers::pi*x) / (al::numbers::pi*x); -} - /* The zero-order modified Bessel function of the first kind, used for the * Kaiser window. * * I_0(x) = sum_{k=0}^inf (1 / k!)^2 (x / 2)^(2 k) * = sum_{k=0}^inf ((x / 2)^k / k!)^2 + * + * This implementation only handles nu = 0, and isn't the most precise (it + * starts with the largest value and accumulates successively smaller values, + * compounding the rounding and precision error), but it's good enough. */ -constexpr double BesselI_0(const double x) noexcept +template +constexpr auto cyl_bessel_i(T nu, U x) -> U { + if(nu != T{0}) + throw std::runtime_error{"cyl_bessel_i: nu != 0"}; + /* Start at k=1 since k=0 is trivial. */ - const double x2{x / 2.0}; + const double x2{x/2.0}; double term{1.0}; double sum{1.0}; - double last_sum{}; int k{1}; /* Let the integration converge until the term of the sum is no longer * significant. */ + double last_sum{}; do { const double y{x2 / k}; ++k; @@ -57,8 +56,20 @@ constexpr double BesselI_0(const double x) noexcept term *= y * y; sum += term; } while(sum != last_sum); + return static_cast(sum); +} - return sum; +/* This is the normalized cardinal sine (sinc) function. + * + * sinc(x) = { 1, x = 0 + * { sin(pi x) / (pi x), otherwise. + */ +constexpr double Sinc(const double x) +{ + constexpr double epsilon{std::numeric_limits::epsilon()}; + if(!(x > epsilon || x < -epsilon)) + return 1.0; + return std::sin(al::numbers::pi*x) / (al::numbers::pi*x); } /* Calculate a Kaiser window from the given beta value and a normalized k @@ -79,7 +90,7 @@ constexpr double Kaiser(const double beta, const double k, const double besseli_ { if(!(k >= -1.0 && k <= 1.0)) return 0.0; - return BesselI_0(beta * std::sqrt(1.0 - k*k)) / besseli_0_beta; + return ::cyl_bessel_i(0, beta * std::sqrt(1.0 - k*k)) / besseli_0_beta; } /* Calculates the (normalized frequency) transition width of the Kaiser window. @@ -98,87 +109,146 @@ constexpr double CalcKaiserBeta(const double rejection) { if(rejection > 50.0) return 0.1102 * (rejection-8.7); - else if(rejection >= 21.0) + if(rejection >= 21.0) return (0.5842 * std::pow(rejection-21.0, 0.4)) + (0.07886 * (rejection-21.0)); return 0.0; } struct BSincHeader { - double width{}; double beta{}; double scaleBase{}; - double scaleRange{}; - double besseli_0_beta{}; + double scaleLimit{}; - uint a[BSincScaleCount]{}; + std::array a{}; + std::array m{}; uint total_size{}; - constexpr BSincHeader(uint Rejection, uint Order) noexcept + constexpr BSincHeader(uint rejection, uint order, uint maxScale) noexcept + : beta{CalcKaiserBeta(rejection)}, scaleBase{CalcKaiserWidth(rejection, order) / 2.0} + , scaleLimit{1.0 / maxScale} { - width = CalcKaiserWidth(Rejection, Order); - beta = CalcKaiserBeta(Rejection); - scaleBase = width / 2.0; - scaleRange = 1.0 - scaleBase; - besseli_0_beta = BesselI_0(beta); - - uint num_points{Order+1}; + const auto base_a = (order+1.0) / 2.0; for(uint si{0};si < BSincScaleCount;++si) { - const double scale{scaleBase + (scaleRange * (si+1) / BSincScaleCount)}; - const uint a_{std::min(static_cast(num_points / 2.0 / scale), num_points)}; - const uint m{2 * a_}; + const auto scale = lerpd(scaleBase, 1.0, (si+1u) / double{BSincScaleCount}); + a[si] = std::min(base_a/scale, base_a*maxScale); + /* std::ceil() isn't constexpr until C++23, this should behave the + * same. + */ + auto a_ = static_cast(a[si]); + a_ += (static_cast(a_) != a[si]); + m[si] = a_ * 2u; - a[si] = a_; - total_size += 4 * BSincPhaseCount * ((m+3) & ~3u); + total_size += 4u * BSincPhaseCount * ((m[si]+3u) & ~3u); } } }; /* 11th and 23rd order filters (12 and 24-point respectively) with a 60dB drop - * at nyquist. Each filter will scale up the order when downsampling, to 23rd - * and 47th order respectively. + * at nyquist. Each filter will scale up to double size when downsampling, to + * 23rd and 47th order respectively. */ -constexpr BSincHeader bsinc12_hdr{60, 11}; -constexpr BSincHeader bsinc24_hdr{60, 23}; +constexpr auto bsinc12_hdr = BSincHeader{60, 11, 2}; +constexpr auto bsinc24_hdr = BSincHeader{60, 23, 2}; +/* 47th order filter (48-point) with an 80dB drop at nyquist. The filter order + * doesn't increase when downsampling. + */ +constexpr auto bsinc48_hdr = BSincHeader{80, 47, 1}; template -struct BSincFilterArray { +struct SIMDALIGN BSincFilterArray { alignas(16) std::array mTable{}; BSincFilterArray() { - constexpr uint BSincPointsMax{(hdr.a[0]*2 + 3) & ~3u}; + static constexpr auto BSincPointsMax = (hdr.m[0]+3u) & ~3u; static_assert(BSincPointsMax <= MaxResamplerPadding, "MaxResamplerPadding is too small"); - using filter_type = double[BSincPhaseCount+1][BSincPointsMax]; - auto filter = std::make_unique(BSincScaleCount); + using filter_type = std::array,BSincPhaseCount>; + auto filter = std::vector(BSincScaleCount); + + static constexpr auto besseli_0_beta = ::cyl_bessel_i(0, hdr.beta); /* Calculate the Kaiser-windowed Sinc filter coefficients for each * scale and phase index. */ for(uint si{0};si < BSincScaleCount;++si) { - const uint m{hdr.a[si] * 2}; - const size_t o{(BSincPointsMax-m) / 2}; - const double scale{hdr.scaleBase + (hdr.scaleRange * (si+1) / BSincScaleCount)}; - const double cutoff{scale - (hdr.scaleBase * std::max(1.0, scale*2.0))}; - const auto a = static_cast(hdr.a[si]); - const double l{a - 1.0/BSincPhaseCount}; - - /* Do one extra phase index so that the phase delta has a proper - * target for its last index. + const auto a = hdr.a[si]; + const auto m = hdr.m[si]; + const auto l = std::floor(m*0.5) - 1.0; + const auto o = size_t{BSincPointsMax-m} / 2u; + const auto scale = lerpd(hdr.scaleBase, 1.0, (si+1u) / double{BSincScaleCount}); + + /* Calculate an appropriate cutoff frequency. An explanation may be + * in order here. + * + * When up-sampling, or down-sampling by less than the max scaling + * factor (when scale >= scaleLimit), the filter order increases as + * the down-sampling factor is reduced, enabling a consistent + * filter response output. + * + * When down-sampling by more than the max scale factor, the filter + * order stays constant to avoid further increasing the processing + * cost, causing the transition width to increase. This would + * normally be compensated for by reducing the cutoff frequency, + * to keep the transition band under the nyquist frequency and + * avoid aliasing. However, this has the side-effect of attenuating + * more of the original high frequency content, which can be + * significant with more extreme down-sampling scales. + * + * To combat this, we can allow for some aliasing to keep the + * cutoff frequency higher than it would otherwise be. We can allow + * the transition band to "wrap around" the nyquist frequency, so + * the output would have some low-level aliasing that overlays with + * the attenuated frequencies in the transition band. This allows + * the cutoff frequency to remain fixed as the transition width + * increases, until the stop frequency aliases back to the cutoff + * frequency and the transition band becomes fully wrapped over + * itself, at which point the cutoff frequency will lower at half + * the rate the transition width increases. + * + * This has an additional benefit when dealing with typical output + * rates like 44 or 48khz. Since human hearing maxes out at 20khz, + * and these rates handle frequencies up to 22 or 24khz, this lets + * some aliasing get masked. For example, the bsinc24 filter with + * 48khz output has a cutoff of 20khz when down-sampling, and a + * 4khz transition band. When down-sampling by more extreme scales, + * the cutoff frequency can stay at 20khz while the transition + * width doubles before any aliasing noise may become audible. + * + * This is what we do here. + * + * 'max_cutoff` is the upper bound normalized cutoff frequency for + * this scale factor, that aligns with the same absolute frequency + * as nominal resample factors. When up-sampling (scale == 1), the + * cutoff can't be raised further than this, or else it would + * prematurely add audible aliasing noise. + * + * 'width' is the normalized transition width for this scale + * factor. + * + * '(scale - width)*0.5' calculates the cutoff frequency necessary + * for the transition band to fully wrap on itself around the + * nyquist frequency. If this is larger than max_cutoff, the + * transition band is not fully wrapped at this scale and the + * cutoff doesn't need adjustment. */ - for(uint pi{0};pi <= BSincPhaseCount;++pi) + const auto max_cutoff = (0.5 - hdr.scaleBase)*scale; + const auto width = hdr.scaleBase * std::max(hdr.scaleLimit, scale); + const auto cutoff2 = std::min(max_cutoff, (scale - width)*0.5) * 2.0; + + for(uint pi{0};pi < BSincPhaseCount;++pi) { - const double phase{std::floor(l) + (pi/double{BSincPhaseCount})}; + const auto phase = l + (pi/double{BSincPhaseCount}); for(uint i{0};i < m;++i) { - const double x{i - phase}; - filter[si][pi][o+i] = Kaiser(hdr.beta, x/l, hdr.besseli_0_beta) * cutoff * - Sinc(cutoff*x); + const auto x = static_cast(i) - phase; + filter[si][pi][o+i] = Kaiser(hdr.beta, x/a, besseli_0_beta) * cutoff2 * + Sinc(cutoff2*x); } } } @@ -186,8 +256,8 @@ struct BSincFilterArray { size_t idx{0}; for(size_t si{0};si < BSincScaleCount;++si) { - const size_t m{((hdr.a[si]*2) + 3) & ~3u}; - const size_t o{(BSincPointsMax-m) / 2}; + const auto m = (hdr.m[si]+3_uz) & ~3_uz; + const auto o = size_t{BSincPointsMax-m} / 2u; /* Write out each phase index's filter and phase delta for this * quality scale. @@ -200,54 +270,83 @@ struct BSincFilterArray { /* Linear interpolation between phases is simplified by pre- * calculating the delta (b - a) in: x = a + f (b - a) */ - for(size_t i{0};i < m;++i) + if(pi < BSincPhaseCount-1) { - const double phDelta{filter[si][pi+1][o+i] - filter[si][pi][o+i]}; - mTable[idx++] = static_cast(phDelta); + for(size_t i{0};i < m;++i) + { + const double phDelta{filter[si][pi+1][o+i] - filter[si][pi][o+i]}; + mTable[idx++] = static_cast(phDelta); + } } - } - /* Calculate and write out each phase index's filter quality scale - * deltas. The last scale index doesn't have any scale or scale- - * phase deltas. - */ - if(si == BSincScaleCount-1) - { - for(size_t i{0};i < BSincPhaseCount*m*2;++i) - mTable[idx++] = 0.0f; - } - else for(size_t pi{0};pi < BSincPhaseCount;++pi) - { - /* Linear interpolation between scales is also simplified. - * - * Given a difference in the number of points between scales, - * the destination points will be 0, thus: x = a + f (-a) - */ - for(size_t i{0};i < m;++i) + else { - const double scDelta{filter[si+1][pi][o+i] - filter[si][pi][o+i]}; - mTable[idx++] = static_cast(scDelta); + /* The delta target for the last phase index is the first + * phase index with the coefficients offset by one. The + * first delta targets 0, as it represents a coefficient + * for a sample that won't be part of the filter. + */ + mTable[idx++] = static_cast(0.0 - filter[si][pi][o]); + for(size_t i{1};i < m;++i) + { + const double phDelta{filter[si][0][o+i-1] - filter[si][pi][o+i]}; + mTable[idx++] = static_cast(phDelta); + } } + } - /* This last simplification is done to complete the bilinear - * equation for the combination of phase and scale. - */ - for(size_t i{0};i < m;++i) + /* Now write out each phase index's scale and phase+scale deltas, + * to complete the bilinear equation for the combination of phase + * and scale. + */ + if(si < BSincScaleCount-1) + { + for(size_t pi{0};pi < BSincPhaseCount;++pi) { - const double spDelta{(filter[si+1][pi+1][o+i] - filter[si+1][pi][o+i]) - - (filter[si][pi+1][o+i] - filter[si][pi][o+i])}; - mTable[idx++] = static_cast(spDelta); + for(size_t i{0};i < m;++i) + { + const double scDelta{filter[si+1][pi][o+i] - filter[si][pi][o+i]}; + mTable[idx++] = static_cast(scDelta); + } + + if(pi < BSincPhaseCount-1) + { + for(size_t i{0};i < m;++i) + { + const double spDelta{(filter[si+1][pi+1][o+i]-filter[si+1][pi][o+i]) - + (filter[si][pi+1][o+i]-filter[si][pi][o+i])}; + mTable[idx++] = static_cast(spDelta); + } + } + else + { + mTable[idx++] = static_cast((0.0 - filter[si+1][pi][o]) - + (0.0 - filter[si][pi][o])); + for(size_t i{1};i < m;++i) + { + const double spDelta{(filter[si+1][0][o+i-1] - filter[si+1][pi][o+i]) - + (filter[si][0][o+i-1] - filter[si][pi][o+i])}; + mTable[idx++] = static_cast(spDelta); + } + } } } + else + { + /* The last scale index doesn't have scale-related deltas. */ + for(size_t i{0};i < BSincPhaseCount*m*2;++i) + mTable[idx++] = 0.0f; + } } assert(idx == hdr.total_size); } - constexpr const BSincHeader &getHeader() const noexcept { return hdr; } - constexpr const float *getTable() const noexcept { return &mTable.front(); } + [[nodiscard]] constexpr auto getHeader() const noexcept -> const BSincHeader& { return hdr; } + [[nodiscard]] constexpr auto getTable() const noexcept { return al::span{mTable}; } }; -const BSincFilterArray bsinc12_filter{}; -const BSincFilterArray bsinc24_filter{}; +const auto bsinc12_filter = BSincFilterArray{}; +const auto bsinc24_filter = BSincFilterArray{}; +const auto bsinc48_filter = BSincFilterArray{}; template constexpr BSincTable GenerateBSincTable(const T &filter) @@ -255,9 +354,9 @@ constexpr BSincTable GenerateBSincTable(const T &filter) BSincTable ret{}; const BSincHeader &hdr = filter.getHeader(); ret.scaleBase = static_cast(hdr.scaleBase); - ret.scaleRange = static_cast(1.0 / hdr.scaleRange); + ret.scaleRange = static_cast(1.0 / (1.0 - hdr.scaleBase)); for(size_t i{0};i < BSincScaleCount;++i) - ret.m[i] = ((hdr.a[i]*2) + 3) & ~3u; + ret.m[i] = (hdr.m[i]+3u) & ~3u; ret.filterOffset[0] = 0; for(size_t i{1};i < BSincScaleCount;++i) ret.filterOffset[i] = ret.filterOffset[i-1] + ret.m[i-1]*4*BSincPhaseCount; @@ -269,3 +368,4 @@ constexpr BSincTable GenerateBSincTable(const T &filter) const BSincTable gBSinc12{GenerateBSincTable(bsinc12_filter)}; const BSincTable gBSinc24{GenerateBSincTable(bsinc24_filter)}; +const BSincTable gBSinc48{GenerateBSincTable(bsinc48_filter)}; diff --git a/3rdparty/openal/core/bsinc_tables.h b/3rdparty/openal/core/bsinc_tables.h index aca4b274420a..516e1ed0fc0d 100644 --- a/3rdparty/openal/core/bsinc_tables.h +++ b/3rdparty/openal/core/bsinc_tables.h @@ -1,17 +1,21 @@ #ifndef CORE_BSINC_TABLES_H #define CORE_BSINC_TABLES_H -#include "bsinc_defs.h" +#include +#include "alspan.h" +#include "bsinc_defs.h" +#include "opthelpers.h" struct BSincTable { float scaleBase, scaleRange; - unsigned int m[BSincScaleCount]; - unsigned int filterOffset[BSincScaleCount]; - const float *Tab; + std::array m; + std::array filterOffset; + al::span Tab; }; -extern const BSincTable gBSinc12; -extern const BSincTable gBSinc24; +DECL_HIDDEN extern const BSincTable gBSinc12; +DECL_HIDDEN extern const BSincTable gBSinc24; +DECL_HIDDEN extern const BSincTable gBSinc48; #endif /* CORE_BSINC_TABLES_H */ diff --git a/3rdparty/openal/core/buffer_storage.cpp b/3rdparty/openal/core/buffer_storage.cpp index 98ca2c1b3fe5..780e388adeb7 100644 --- a/3rdparty/openal/core/buffer_storage.cpp +++ b/3rdparty/openal/core/buffer_storage.cpp @@ -3,79 +3,3 @@ #include "buffer_storage.h" -#include - - -const char *NameFromFormat(FmtType type) noexcept -{ - switch(type) - { - case FmtUByte: return "UInt8"; - case FmtShort: return "Int16"; - case FmtFloat: return "Float"; - case FmtDouble: return "Double"; - case FmtMulaw: return "muLaw"; - case FmtAlaw: return "aLaw"; - case FmtIMA4: return "IMA4 ADPCM"; - case FmtMSADPCM: return "MS ADPCM"; - } - return ""; -} - -const char *NameFromFormat(FmtChannels channels) noexcept -{ - switch(channels) - { - case FmtMono: return "Mono"; - case FmtStereo: return "Stereo"; - case FmtRear: return "Rear"; - case FmtQuad: return "Quadraphonic"; - case FmtX51: return "Surround 5.1"; - case FmtX61: return "Surround 6.1"; - case FmtX71: return "Surround 7.1"; - case FmtBFormat2D: return "B-Format 2D"; - case FmtBFormat3D: return "B-Format 3D"; - case FmtUHJ2: return "UHJ2"; - case FmtUHJ3: return "UHJ3"; - case FmtUHJ4: return "UHJ4"; - case FmtSuperStereo: return "Super Stereo"; - } - return ""; -} - -uint BytesFromFmt(FmtType type) noexcept -{ - switch(type) - { - case FmtUByte: return sizeof(uint8_t); - case FmtShort: return sizeof(int16_t); - case FmtFloat: return sizeof(float); - case FmtDouble: return sizeof(double); - case FmtMulaw: return sizeof(uint8_t); - case FmtAlaw: return sizeof(uint8_t); - case FmtIMA4: break; - case FmtMSADPCM: break; - } - return 0; -} - -uint ChannelsFromFmt(FmtChannels chans, uint ambiorder) noexcept -{ - switch(chans) - { - case FmtMono: return 1; - case FmtStereo: return 2; - case FmtRear: return 2; - case FmtQuad: return 4; - case FmtX51: return 6; - case FmtX61: return 7; - case FmtX71: return 8; - case FmtBFormat2D: return (ambiorder*2) + 1; - case FmtBFormat3D: return (ambiorder+1) * (ambiorder+1); - case FmtUHJ2: return 2; - case FmtUHJ3: return 3; - case FmtUHJ4: return 4; - case FmtSuperStereo: return 2; - } - return 0; -} diff --git a/3rdparty/openal/core/buffer_storage.h b/3rdparty/openal/core/buffer_storage.h index d8ab0b670d02..3ffc1f0be289 100644 --- a/3rdparty/openal/core/buffer_storage.h +++ b/3rdparty/openal/core/buffer_storage.h @@ -1,62 +1,15 @@ #ifndef CORE_BUFFER_STORAGE_H #define CORE_BUFFER_STORAGE_H -#include #include -#include "alnumeric.h" #include "alspan.h" #include "ambidefs.h" +#include "storage_formats.h" using uint = unsigned int; -/* Storable formats */ -enum FmtType : unsigned char { - FmtUByte, - FmtShort, - FmtFloat, - FmtDouble, - FmtMulaw, - FmtAlaw, - FmtIMA4, - FmtMSADPCM, -}; -enum FmtChannels : unsigned char { - FmtMono, - FmtStereo, - FmtRear, - FmtQuad, - FmtX51, /* (WFX order) */ - FmtX61, /* (WFX order) */ - FmtX71, /* (WFX order) */ - FmtBFormat2D, - FmtBFormat3D, - FmtUHJ2, /* 2-channel UHJ, aka "BHJ", stereo-compatible */ - FmtUHJ3, /* 3-channel UHJ, aka "THJ" */ - FmtUHJ4, /* 4-channel UHJ, aka "PHJ" */ - FmtSuperStereo, /* Stereo processed with Super Stereo. */ -}; - -enum class AmbiLayout : unsigned char { - FuMa, - ACN, -}; -enum class AmbiScaling : unsigned char { - FuMa, - SN3D, - N3D, - UHJ, -}; - -const char *NameFromFormat(FmtType type) noexcept; -const char *NameFromFormat(FmtChannels channels) noexcept; - -uint BytesFromFmt(FmtType type) noexcept; -uint ChannelsFromFmt(FmtChannels chans, uint ambiorder) noexcept; -inline uint FrameSizeFromFmt(FmtChannels chans, FmtType type, uint ambiorder) noexcept -{ return ChannelsFromFmt(chans, ambiorder) * BytesFromFmt(type); } - constexpr bool IsBFormat(FmtChannels chans) noexcept { return chans == FmtBFormat2D || chans == FmtBFormat3D; } @@ -79,7 +32,7 @@ constexpr bool Is2DAmbisonic(FmtChannels chans) noexcept } -using CallbackType = int(*)(void*, void*, int); +using CallbackType = int(*)(void*, void*, int) noexcept; struct BufferStorage { CallbackType mCallback{nullptr}; @@ -97,19 +50,20 @@ struct BufferStorage { AmbiScaling mAmbiScaling{AmbiScaling::FuMa}; uint mAmbiOrder{0u}; - inline uint bytesFromFmt() const noexcept { return BytesFromFmt(mType); } - inline uint channelsFromFmt() const noexcept + [[nodiscard]] auto bytesFromFmt() const noexcept -> uint { return BytesFromFmt(mType); } + [[nodiscard]] auto channelsFromFmt() const noexcept -> uint { return ChannelsFromFmt(mChannels, mAmbiOrder); } - inline uint frameSizeFromFmt() const noexcept { return channelsFromFmt() * bytesFromFmt(); } + [[nodiscard]] auto frameSizeFromFmt() const noexcept -> uint + { return channelsFromFmt() * bytesFromFmt(); } - inline uint blockSizeFromFmt() const noexcept + [[nodiscard]] auto blockSizeFromFmt() const noexcept -> uint { if(mType == FmtIMA4) return ((mBlockAlign-1)/2 + 4) * channelsFromFmt(); if(mType == FmtMSADPCM) return ((mBlockAlign-2)/2 + 7) * channelsFromFmt(); return frameSizeFromFmt(); }; - inline bool isBFormat() const noexcept { return IsBFormat(mChannels); } + [[nodiscard]] auto isBFormat() const noexcept -> bool { return IsBFormat(mChannels); } }; #endif /* CORE_BUFFER_STORAGE_H */ diff --git a/3rdparty/openal/core/bufferline.h b/3rdparty/openal/core/bufferline.h index 8b445f3ff58a..309fb778f841 100644 --- a/3rdparty/openal/core/bufferline.h +++ b/3rdparty/openal/core/bufferline.h @@ -9,7 +9,7 @@ * more memory and are harder on cache, while smaller values may need more * iterations for mixing. */ -constexpr int BufferLineSize{1024}; +inline constexpr size_t BufferLineSize{1024}; using FloatBufferLine = std::array; using FloatBufferSpan = al::span; diff --git a/3rdparty/openal/core/context.cpp b/3rdparty/openal/core/context.cpp index 2ebbc7b13ed8..68f6dc38d89e 100644 --- a/3rdparty/openal/core/context.cpp +++ b/3rdparty/openal/core/context.cpp @@ -2,6 +2,7 @@ #include "config.h" #include +#include #include #include #include @@ -26,58 +27,22 @@ ContextBase::ContextBase(DeviceBase *device) : mDevice{device} ContextBase::~ContextBase() { - size_t count{0}; - ContextProps *cprops{mParams.ContextUpdate.exchange(nullptr, std::memory_order_relaxed)}; - if(cprops) - { - ++count; - delete cprops; - } - cprops = mFreeContextProps.exchange(nullptr, std::memory_order_acquire); - while(cprops) - { - std::unique_ptr old{cprops}; - cprops = old->next.load(std::memory_order_relaxed); - ++count; - } - TRACE("Freed %zu context property object%s\n", count, (count==1)?"":"s"); - - count = 0; - EffectSlotProps *eprops{mFreeEffectslotProps.exchange(nullptr, std::memory_order_acquire)}; - while(eprops) - { - std::unique_ptr old{eprops}; - eprops = old->next.load(std::memory_order_relaxed); - ++count; - } - TRACE("Freed %zu AuxiliaryEffectSlot property object%s\n", count, (count==1)?"":"s"); - - if(EffectSlotArray *curarray{mActiveAuxSlots.exchange(nullptr, std::memory_order_relaxed)}) - { - std::destroy_n(curarray->end(), curarray->size()); - delete curarray; - } - - delete mVoices.exchange(nullptr, std::memory_order_relaxed); + mActiveAuxSlots.store(nullptr, std::memory_order_relaxed); + mVoices.store(nullptr, std::memory_order_relaxed); if(mAsyncEvents) { - count = 0; - auto evt_vec = mAsyncEvents->getReadVector(); - if(evt_vec.first.len > 0) + size_t count{0}; + for(auto &evt : mAsyncEvents->getReadVector()) { - std::destroy_n(std::launder(reinterpret_cast(evt_vec.first.buf)), - evt_vec.first.len); - count += evt_vec.first.len; - } - if(evt_vec.second.len > 0) - { - std::destroy_n(std::launder(reinterpret_cast(evt_vec.second.buf)), - evt_vec.second.len); - count += evt_vec.second.len; + if(evt.len > 0) + { + std::destroy_n(std::launder(reinterpret_cast(evt.buf)), evt.len); + count += evt.len; + } } if(count > 0) - TRACE("Destructed %zu orphaned event%s\n", count, (count==1)?"":"s"); + TRACE("Destructed {} orphaned event{}", count, (count==1)?"":"s"); mAsyncEvents->readAdvance(count); } } @@ -85,85 +50,131 @@ ContextBase::~ContextBase() void ContextBase::allocVoiceChanges() { - constexpr size_t clustersize{128}; + static constexpr size_t clustersize{std::tuple_size_v}; + + VoiceChangeCluster clusterptr{std::make_unique()}; + const auto cluster = al::span{*clusterptr}; - VoiceChangeCluster cluster{std::make_unique(clustersize)}; for(size_t i{1};i < clustersize;++i) cluster[i-1].mNext.store(std::addressof(cluster[i]), std::memory_order_relaxed); cluster[clustersize-1].mNext.store(mVoiceChangeTail, std::memory_order_relaxed); - mVoiceChangeClusters.emplace_back(std::move(cluster)); - mVoiceChangeTail = mVoiceChangeClusters.back().get(); + mVoiceChangeClusters.emplace_back(std::move(clusterptr)); + mVoiceChangeTail = mVoiceChangeClusters.back()->data(); } void ContextBase::allocVoiceProps() { - constexpr size_t clustersize{32}; + static constexpr size_t clustersize{std::tuple_size_v}; - TRACE("Increasing allocated voice properties to %zu\n", + TRACE("Increasing allocated voice properties to {}", (mVoicePropClusters.size()+1) * clustersize); - VoicePropsCluster cluster{std::make_unique(clustersize)}; + auto clusterptr = std::make_unique(); + auto cluster = al::span{*clusterptr}; for(size_t i{1};i < clustersize;++i) cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed); - mVoicePropClusters.emplace_back(std::move(cluster)); + mVoicePropClusters.emplace_back(std::move(clusterptr)); VoicePropsItem *oldhead{mFreeVoiceProps.load(std::memory_order_acquire)}; do { - mVoicePropClusters.back()[clustersize-1].next.store(oldhead, std::memory_order_relaxed); - } while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back().get(), + mVoicePropClusters.back()->back().next.store(oldhead, std::memory_order_relaxed); + } while(mFreeVoiceProps.compare_exchange_weak(oldhead, mVoicePropClusters.back()->data(), std::memory_order_acq_rel, std::memory_order_acquire) == false); } void ContextBase::allocVoices(size_t addcount) { - constexpr size_t clustersize{32}; + static constexpr size_t clustersize{std::tuple_size_v}; /* Convert element count to cluster count. */ addcount = (addcount+(clustersize-1)) / clustersize; + if(!addcount) + { + if(!mVoiceClusters.empty()) + return; + ++addcount; + } + if(addcount >= std::numeric_limits::max()/clustersize - mVoiceClusters.size()) throw std::runtime_error{"Allocating too many voices"}; const size_t totalcount{(mVoiceClusters.size()+addcount) * clustersize}; - TRACE("Increasing allocated voices to %zu\n", totalcount); + TRACE("Increasing allocated voices to {}", totalcount); - auto newarray = VoiceArray::Create(totalcount); while(addcount) { - mVoiceClusters.emplace_back(std::make_unique(clustersize)); + mVoiceClusters.emplace_back(std::make_unique()); --addcount; } + auto newarray = VoiceArray::Create(totalcount); auto voice_iter = newarray->begin(); for(VoiceCluster &cluster : mVoiceClusters) - { - for(size_t i{0};i < clustersize;++i) - *(voice_iter++) = &cluster[i]; - } + voice_iter = std::transform(cluster->begin(), cluster->end(), voice_iter, + [](Voice &voice) noexcept -> Voice* { return &voice; }); - if(auto *oldvoices = mVoices.exchange(newarray.release(), std::memory_order_acq_rel)) - { - mDevice->waitForMix(); - delete oldvoices; - } + if(auto oldvoices = mVoices.exchange(std::move(newarray), std::memory_order_acq_rel)) + std::ignore = mDevice->waitForMix(); } +void ContextBase::allocEffectSlotProps() +{ + static constexpr size_t clustersize{std::tuple_size_v}; + + TRACE("Increasing allocated effect slot properties to {}", + (mEffectSlotPropClusters.size()+1) * clustersize); + + auto clusterptr = std::make_unique(); + auto cluster = al::span{*clusterptr}; + for(size_t i{1};i < clustersize;++i) + cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed); + auto *newcluster = mEffectSlotPropClusters.emplace_back(std::move(clusterptr)).get(); + + EffectSlotProps *oldhead{mFreeEffectSlotProps.load(std::memory_order_acquire)}; + do { + newcluster->back().next.store(oldhead, std::memory_order_relaxed); + } while(mFreeEffectSlotProps.compare_exchange_weak(oldhead, newcluster->data(), + std::memory_order_acq_rel, std::memory_order_acquire) == false); +} + EffectSlot *ContextBase::getEffectSlot() { - for(auto& cluster : mEffectSlotClusters) + for(auto& clusterptr : mEffectSlotClusters) { - for(size_t i{0};i < EffectSlotClusterSize;++i) - { - if(!cluster[i].InUse) - return &cluster[i]; - } + const auto cluster = al::span{*clusterptr}; + auto iter = std::find_if_not(cluster.begin(), cluster.end(), + std::mem_fn(&EffectSlot::InUse)); + if(iter != cluster.end()) return al::to_address(iter); } - if(1 >= std::numeric_limits::max()/EffectSlotClusterSize - mEffectSlotClusters.size()) + auto clusterptr = std::make_unique(); + if(1 >= std::numeric_limits::max()/clusterptr->size() - mEffectSlotClusters.size()) throw std::runtime_error{"Allocating too many effect slots"}; - const size_t totalcount{(mEffectSlotClusters.size()+1) * EffectSlotClusterSize}; - TRACE("Increasing allocated effect slots to %zu\n", totalcount); + const size_t totalcount{(mEffectSlotClusters.size()+1) * clusterptr->size()}; + TRACE("Increasing allocated effect slots to {}", totalcount); - mEffectSlotClusters.emplace_back(std::make_unique(EffectSlotClusterSize)); - return getEffectSlot(); + mEffectSlotClusters.emplace_back(std::move(clusterptr)); + return mEffectSlotClusters.back()->data(); +} + + +void ContextBase::allocContextProps() +{ + static constexpr size_t clustersize{std::tuple_size_v}; + + TRACE("Increasing allocated context properties to {}", + (mContextPropClusters.size()+1) * clustersize); + + auto clusterptr = std::make_unique(); + auto cluster = al::span{*clusterptr}; + for(size_t i{1};i < clustersize;++i) + cluster[i-1].next.store(std::addressof(cluster[i]), std::memory_order_relaxed); + auto *newcluster = mContextPropClusters.emplace_back(std::move(clusterptr)).get(); + + ContextProps *oldhead{mFreeContextProps.load(std::memory_order_acquire)}; + do { + newcluster->back().next.store(oldhead, std::memory_order_relaxed); + } while(mFreeContextProps.compare_exchange_weak(oldhead, newcluster->data(), + std::memory_order_acq_rel, std::memory_order_acquire) == false); } diff --git a/3rdparty/openal/core/context.h b/3rdparty/openal/core/context.h index ccb7dd3bfbec..7d98ee8f769c 100644 --- a/3rdparty/openal/core/context.h +++ b/3rdparty/openal/core/context.h @@ -1,6 +1,8 @@ #ifndef CORE_CONTEXT_H #define CORE_CONTEXT_H +#include "config.h" + #include #include #include @@ -9,11 +11,11 @@ #include #include -#include "almalloc.h" #include "alsem.h" #include "alspan.h" #include "async_event.h" #include "atomic.h" +#include "flexarray.h" #include "opthelpers.h" #include "vecmat.h" @@ -26,9 +28,9 @@ struct VoiceChange; struct VoicePropsItem; -constexpr float SpeedOfSoundMetersPerSec{343.3f}; +inline constexpr float SpeedOfSoundMetersPerSec{343.3f}; -constexpr float AirAbsorbGainHF{0.99426f}; /* -0.05dB */ +inline constexpr float AirAbsorbGainHF{0.99426f}; /* -0.05dB */ enum class DistanceModel : unsigned char { Disable, @@ -52,21 +54,22 @@ struct ContextProps { float DopplerFactor; float DopplerVelocity; float SpeedOfSound; +#if ALSOFT_EAX + float DistanceFactor; +#endif bool SourceDistanceModel; DistanceModel mDistanceModel; - std::atomic next; - - DEF_NEWDEL(ContextProps) + std::atomic next{}; }; struct ContextParams { /* Pointer to the most recent property values that are awaiting an update. */ std::atomic ContextUpdate{nullptr}; - alu::Vector Position{}; + alu::Vector Position; alu::Matrix Matrix{alu::Matrix::Identity()}; - alu::Vector Velocity{}; + alu::Vector Velocity; float Gain{1.0f}; float MetersPerUnit{1.0f}; @@ -85,7 +88,7 @@ struct ContextBase { /* Counter for the pre-mixing updates, in 31.1 fixed point (lowest bit * indicates if updates are currently happening). */ - RefCount mUpdateCount{0u}; + std::atomic mUpdateCount{0u}; std::atomic mHoldUpdates{false}; std::atomic mStopVoicesOnDisconnect{true}; @@ -96,7 +99,7 @@ struct ContextBase { */ std::atomic mFreeContextProps{nullptr}; std::atomic mFreeVoiceProps{nullptr}; - std::atomic mFreeEffectslotProps{nullptr}; + std::atomic mFreeEffectSlotProps{nullptr}; /* The voice change tail is the beginning of the "free" elements, up to and * *excluding* the current. If tail==current, there's no free elements and @@ -108,21 +111,22 @@ struct ContextBase { void allocVoiceChanges(); void allocVoiceProps(); - + void allocEffectSlotProps(); + void allocContextProps(); ContextParams mParams; using VoiceArray = al::FlexArray; - std::atomic mVoices{}; + al::atomic_unique_ptr mVoices; std::atomic mActiveVoiceCount{}; void allocVoices(size_t addcount); - al::span getVoicesSpan() const noexcept + [[nodiscard]] auto getVoicesSpan() const noexcept -> al::span { return {mVoices.load(std::memory_order_relaxed)->data(), mActiveVoiceCount.load(std::memory_order_relaxed)}; } - al::span getVoicesSpanAcquired() const noexcept + [[nodiscard]] auto getVoicesSpanAcquired() const noexcept -> al::span { return {mVoices.load(std::memory_order_acquire)->data(), mActiveVoiceCount.load(std::memory_order_acquire)}; @@ -130,7 +134,11 @@ struct ContextBase { using EffectSlotArray = al::FlexArray; - std::atomic mActiveAuxSlots{nullptr}; + /* This array is split in half. The front half is the list of activated + * effect slots as set by the app, and the back half is the same list but + * sorted to ensure later effect slots are fed by earlier ones. + */ + al::atomic_unique_ptr mActiveAuxSlots; std::thread mEventThread; al::semaphore mEventSem; @@ -143,27 +151,35 @@ struct ContextBase { * However, to avoid allocating each object individually, they're allocated * in clusters that are stored in a vector for easy automatic cleanup. */ - using VoiceChangeCluster = std::unique_ptr; + using VoiceChangeCluster = std::unique_ptr>; std::vector mVoiceChangeClusters; - using VoiceCluster = std::unique_ptr; + using VoiceCluster = std::unique_ptr>; std::vector mVoiceClusters; - using VoicePropsCluster = std::unique_ptr; + using VoicePropsCluster = std::unique_ptr>; std::vector mVoicePropClusters; - static constexpr size_t EffectSlotClusterSize{4}; EffectSlot *getEffectSlot(); - using EffectSlotCluster = std::unique_ptr; + using EffectSlotCluster = std::unique_ptr>; std::vector mEffectSlotClusters; + using EffectSlotPropsCluster = std::unique_ptr>; + std::vector mEffectSlotPropClusters; + + /* This could be greater than 2, but there should be no way there can be + * more than two context property updates in use simultaneously. + */ + using ContextPropsCluster = std::unique_ptr>; + std::vector mContextPropClusters; + - ContextBase(DeviceBase *device); + explicit ContextBase(DeviceBase *device); ContextBase(const ContextBase&) = delete; ContextBase& operator=(const ContextBase&) = delete; - ~ContextBase(); + virtual ~ContextBase(); }; #endif /* CORE_CONTEXT_H */ diff --git a/3rdparty/openal/core/converter.cpp b/3rdparty/openal/core/converter.cpp index dea31bd57f6b..97fffc161b82 100644 --- a/3rdparty/openal/core/converter.cpp +++ b/3rdparty/openal/core/converter.cpp @@ -9,7 +9,7 @@ #include #include #include -#include +#include #include "albit.h" #include "alnumeric.h" @@ -24,43 +24,46 @@ static_assert((BufferLineSize-1)/MaxPitch > 0, "MaxPitch is too large for Buffer static_assert((INT_MAX>>MixerFracBits)/MaxPitch > BufferLineSize, "MaxPitch and/or BufferLineSize are too large for MixerFracBits!"); -/* Base template left undefined. Should be marked =delete, but Clang 3.8.1 - * chokes on that given the inline specializations. - */ template -inline float LoadSample(DevFmtType_t val) noexcept; +constexpr float LoadSample(DevFmtType_t val) noexcept = delete; -template<> inline float LoadSample(DevFmtType_t val) noexcept -{ return val * (1.0f/128.0f); } -template<> inline float LoadSample(DevFmtType_t val) noexcept -{ return val * (1.0f/32768.0f); } -template<> inline float LoadSample(DevFmtType_t val) noexcept +template<> constexpr float LoadSample(DevFmtType_t val) noexcept +{ return float(val) * (1.0f/128.0f); } +template<> constexpr float LoadSample(DevFmtType_t val) noexcept +{ return float(val) * (1.0f/32768.0f); } +template<> constexpr float LoadSample(DevFmtType_t val) noexcept { return static_cast(val) * (1.0f/2147483648.0f); } -template<> inline float LoadSample(DevFmtType_t val) noexcept +template<> constexpr float LoadSample(DevFmtType_t val) noexcept { return val; } -template<> inline float LoadSample(DevFmtType_t val) noexcept +template<> constexpr float LoadSample(DevFmtType_t val) noexcept { return LoadSample(static_cast(val - 128)); } -template<> inline float LoadSample(DevFmtType_t val) noexcept +template<> constexpr float LoadSample(DevFmtType_t val) noexcept { return LoadSample(static_cast(val - 32768)); } -template<> inline float LoadSample(DevFmtType_t val) noexcept +template<> constexpr float LoadSample(DevFmtType_t val) noexcept { return LoadSample(static_cast(val - 2147483648u)); } template -inline void LoadSampleArray(float *RESTRICT dst, const void *src, const size_t srcstep, - const size_t samples) noexcept +inline void LoadSampleArray(const al::span dst, const void *src, const size_t channel, + const size_t srcstep) noexcept { - const DevFmtType_t *ssrc = static_cast*>(src); - for(size_t i{0u};i < samples;i++) - dst[i] = LoadSample(ssrc[i*srcstep]); + assert(channel < srcstep); + const auto srcspan = al::span{static_cast*>(src), dst.size()*srcstep}; + auto ssrc = srcspan.cbegin(); + std::generate(dst.begin(), dst.end(), [&ssrc,channel,srcstep] + { + const float ret{LoadSample(ssrc[channel])}; + ssrc += ptrdiff_t(srcstep); + return ret; + }); } -void LoadSamples(float *dst, const void *src, const size_t srcstep, const DevFmtType srctype, - const size_t samples) noexcept +void LoadSamples(const al::span dst, const void *src, const size_t channel, + const size_t srcstep, const DevFmtType srctype) noexcept { #define HANDLE_FMT(T) \ - case T: LoadSampleArray(dst, src, srcstep, samples); break + case T: LoadSampleArray(dst, src, channel, srcstep); break switch(srctype) { HANDLE_FMT(DevFmtByte); @@ -81,11 +84,11 @@ inline DevFmtType_t StoreSample(float) noexcept; template<> inline float StoreSample(float val) noexcept { return val; } template<> inline int32_t StoreSample(float val) noexcept -{ return fastf2i(clampf(val*2147483648.0f, -2147483648.0f, 2147483520.0f)); } +{ return fastf2i(std::clamp(val*2147483648.0f, -2147483648.0f, 2147483520.0f)); } template<> inline int16_t StoreSample(float val) noexcept -{ return static_cast(fastf2i(clampf(val*32768.0f, -32768.0f, 32767.0f))); } +{ return static_cast(fastf2i(std::clamp(val*32768.0f, -32768.0f, 32767.0f))); } template<> inline int8_t StoreSample(float val) noexcept -{ return static_cast(fastf2i(clampf(val*128.0f, -128.0f, 127.0f))); } +{ return static_cast(fastf2i(std::clamp(val*128.0f, -128.0f, 127.0f))); } /* Define unsigned output variations. */ template<> inline uint32_t StoreSample(float val) noexcept @@ -96,20 +99,25 @@ template<> inline uint8_t StoreSample(float val) noexcept { return static_cast(StoreSample(val) + 128); } template -inline void StoreSampleArray(void *dst, const float *RESTRICT src, const size_t dststep, - const size_t samples) noexcept +inline void StoreSampleArray(void *dst, const al::span src, const size_t channel, + const size_t dststep) noexcept { - DevFmtType_t *sdst = static_cast*>(dst); - for(size_t i{0u};i < samples;i++) - sdst[i*dststep] = StoreSample(src[i]); + assert(channel < dststep); + const auto dstspan = al::span{static_cast*>(dst), src.size()*dststep}; + auto sdst = dstspan.begin(); + std::for_each(src.cbegin(), src.cend(), [&sdst,channel,dststep](const float in) + { + sdst[channel] = StoreSample(in); + sdst += ptrdiff_t(dststep); + }); } -void StoreSamples(void *dst, const float *src, const size_t dststep, const DevFmtType dsttype, - const size_t samples) noexcept +void StoreSamples(void *dst, const al::span src, const size_t channel, + const size_t dststep, const DevFmtType dsttype) noexcept { #define HANDLE_FMT(T) \ - case T: StoreSampleArray(dst, src, dststep, samples); break + case T: StoreSampleArray(dst, src, channel, dststep); break switch(dsttype) { HANDLE_FMT(DevFmtByte); @@ -125,30 +133,35 @@ void StoreSamples(void *dst, const float *src, const size_t dststep, const DevFm template -void Mono2Stereo(float *RESTRICT dst, const void *src, const size_t frames) noexcept +void Mono2Stereo(const al::span dst, const void *src) noexcept { - const DevFmtType_t *ssrc = static_cast*>(src); - for(size_t i{0u};i < frames;i++) - dst[i*2 + 1] = dst[i*2 + 0] = LoadSample(ssrc[i]) * 0.707106781187f; + const auto srcspan = al::span{static_cast*>(src), dst.size()>>1}; + auto sdst = dst.begin(); + std::for_each(srcspan.cbegin(), srcspan.cend(), [&sdst](const auto in) + { sdst = std::fill_n(sdst, 2, LoadSample(in)*0.707106781187f); }); } template -void Multi2Mono(uint chanmask, const size_t step, const float scale, float *RESTRICT dst, - const void *src, const size_t frames) noexcept +void Multi2Mono(uint chanmask, const size_t step, const float scale, const al::span dst, + const void *src) noexcept { - const DevFmtType_t *ssrc = static_cast*>(src); - std::fill_n(dst, frames, 0.0f); + const auto srcspan = al::span{static_cast*>(src), step*dst.size()}; + std::fill_n(dst.begin(), dst.size(), 0.0f); for(size_t c{0};chanmask;++c) { if((chanmask&1)) LIKELY { - for(size_t i{0u};i < frames;i++) - dst[i] += LoadSample(ssrc[i*step + c]); + auto ssrc = srcspan.cbegin(); + std::for_each(dst.begin(), dst.end(), [&ssrc,step,c](float &sample) + { + const float s{LoadSample(ssrc[c])}; + ssrc += ptrdiff_t(step); + sample += s; + }); } chanmask >>= 1; } - for(size_t i{0u};i < frames;i++) - dst[i] *= scale; + std::for_each(dst.begin(), dst.end(), [scale](float &sample) noexcept { sample *= scale; }); } } // namespace @@ -156,10 +169,11 @@ void Multi2Mono(uint chanmask, const size_t step, const float scale, float *REST SampleConverterPtr SampleConverter::Create(DevFmtType srcType, DevFmtType dstType, size_t numchans, uint srcRate, uint dstRate, Resampler resampler) { + SampleConverterPtr converter; if(numchans < 1 || srcRate < 1 || dstRate < 1) - return nullptr; + return converter; - SampleConverterPtr converter{new(FamCount(numchans)) SampleConverter{numchans}}; + converter = SampleConverterPtr{new(FamCount(numchans)) SampleConverter{numchans}}; converter->mSrcType = srcType; converter->mDstType = dstType; converter->mSrcTypeSize = BytesFromDevFmt(srcType); @@ -168,19 +182,19 @@ SampleConverterPtr SampleConverter::Create(DevFmtType srcType, DevFmtType dstTyp converter->mSrcPrepCount = MaxResamplerPadding; converter->mFracOffset = 0; for(auto &chan : converter->mChan) - { - const al::span buffer{chan.PrevSamples}; - std::fill(buffer.begin(), buffer.end(), 0.0f); - } + chan.PrevSamples.fill(0.0f); /* Have to set the mixer FPU mode since that's what the resampler code expects. */ FPUCtl mixer_mode{}; - auto step = static_cast( - mind(srcRate*double{MixerFracOne}/dstRate + 0.5, MaxPitch*MixerFracOne)); - converter->mIncrement = maxu(step, 1); + const auto step = std::min(std::round(srcRate*double{MixerFracOne}/dstRate), + MaxPitch*double{MixerFracOne}); + converter->mIncrement = std::max(static_cast(step), 1u); if(converter->mIncrement == MixerFracOne) - converter->mResample = [](const InterpState*, const float *RESTRICT src, uint, const uint, - const al::span dst) { std::copy_n(src, dst.size(), dst.begin()); }; + { + converter->mResample = [](const InterpState*, const al::span src, uint, + const uint, const al::span dst) + { std::copy_n(src.begin()+MaxResamplerEdge, dst.size(), dst.begin()); }; + } else converter->mResample = PrepareResampler(resampler, converter->mIncrement, &converter->mState); @@ -210,24 +224,25 @@ uint SampleConverter::availableOut(uint srcframes) const DataSize64 -= mFracOffset; /* If we have a full prep, we can generate at least one sample. */ - return static_cast(clampu64((DataSize64 + mIncrement-1)/mIncrement, 1, - std::numeric_limits::max())); + return static_cast(std::clamp((DataSize64 + mIncrement-1)/mIncrement, 1_u64, + uint64_t{std::numeric_limits::max()})); } uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint dstframes) { - const uint SrcFrameSize{static_cast(mChan.size()) * mSrcTypeSize}; - const uint DstFrameSize{static_cast(mChan.size()) * mDstTypeSize}; + const size_t SrcFrameSize{mChan.size() * mSrcTypeSize}; + const size_t DstFrameSize{mChan.size() * mDstTypeSize}; const uint increment{mIncrement}; - auto SamplesIn = static_cast(*src); uint NumSrcSamples{*srcframes}; + auto SamplesIn = al::span{static_cast(*src), NumSrcSamples*SrcFrameSize}; + auto SamplesOut = al::span{static_cast(dst), dstframes*DstFrameSize}; FPUCtl mixer_mode{}; uint pos{0}; while(pos < dstframes && NumSrcSamples > 0) { const uint prepcount{mSrcPrepCount}; - const uint readable{minu(NumSrcSamples, BufferLineSize - prepcount)}; + const uint readable{std::min(NumSrcSamples, uint{BufferLineSize} - prepcount)}; if(prepcount < MaxResamplerPadding && MaxResamplerPadding-prepcount >= readable) { @@ -235,16 +250,16 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint * what we're given for later. */ for(size_t chan{0u};chan < mChan.size();chan++) - LoadSamples(&mChan[chan].PrevSamples[prepcount], SamplesIn + mSrcTypeSize*chan, - mChan.size(), mSrcType, readable); + LoadSamples(al::span{mChan[chan].PrevSamples}.subspan(prepcount, readable), + SamplesIn.data(), chan, mChan.size(), mSrcType); mSrcPrepCount = prepcount + readable; NumSrcSamples = 0; break; } - float *RESTRICT SrcData{mSrcSamples}; - float *RESTRICT DstData{mDstSamples}; + const auto SrcData = al::span{mSrcSamples}; + const auto DstData = al::span{mDstSamples}; uint DataPosFrac{mFracOffset}; uint64_t DataSize64{prepcount}; DataSize64 += readable; @@ -253,39 +268,36 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint DataSize64 -= DataPosFrac; /* If we have a full prep, we can generate at least one sample. */ - auto DstSize = static_cast( - clampu64((DataSize64 + increment-1)/increment, 1, BufferLineSize)); - DstSize = minu(DstSize, dstframes-pos); + auto DstSize = static_cast(std::clamp((DataSize64 + increment-1)/increment, 1_u64, + uint64_t{BufferLineSize})); + DstSize = std::min(DstSize, dstframes-pos); const uint DataPosEnd{DstSize*increment + DataPosFrac}; const uint SrcDataEnd{DataPosEnd>>MixerFracBits}; assert(prepcount+readable >= SrcDataEnd); - const uint nextprep{minu(prepcount + readable - SrcDataEnd, MaxResamplerPadding)}; + const uint nextprep{std::min(prepcount+readable-SrcDataEnd, MaxResamplerPadding)}; for(size_t chan{0u};chan < mChan.size();chan++) { - const std::byte *SrcSamples{SamplesIn + mSrcTypeSize*chan}; - std::byte *DstSamples = static_cast(dst) + mDstTypeSize*chan; - /* Load the previous samples into the source data first, then the * new samples from the input buffer. */ - std::copy_n(mChan[chan].PrevSamples, prepcount, SrcData); - LoadSamples(SrcData + prepcount, SrcSamples, mChan.size(), mSrcType, readable); + std::copy_n(mChan[chan].PrevSamples.cbegin(), prepcount, SrcData.begin()); + LoadSamples(SrcData.subspan(prepcount, readable), SamplesIn.data(), chan, mChan.size(), + mSrcType); /* Store as many prep samples for next time as possible, given the * number of output samples being generated. */ - std::copy_n(SrcData+SrcDataEnd, nextprep, mChan[chan].PrevSamples); - std::fill(std::begin(mChan[chan].PrevSamples)+nextprep, - std::end(mChan[chan].PrevSamples), 0.0f); + auto previter = std::copy_n(SrcData.begin()+ptrdiff_t(SrcDataEnd), nextprep, + mChan[chan].PrevSamples.begin()); + std::fill(previter, mChan[chan].PrevSamples.end(), 0.0f); /* Now resample, and store the result in the output buffer. */ - mResample(&mState, SrcData+MaxResamplerEdge, DataPosFrac, increment, - {DstData, DstSize}); + mResample(&mState, SrcData, DataPosFrac, increment, DstData.first(DstSize)); - StoreSamples(DstSamples, DstData, mChan.size(), mDstType, DstSize); + StoreSamples(SamplesOut.data(), DstData.first(DstSize), chan, mChan.size(), mDstType); } /* Update the number of prep samples still available, as well as the @@ -295,22 +307,24 @@ uint SampleConverter::convert(const void **src, uint *srcframes, void *dst, uint mFracOffset = DataPosEnd & MixerFracMask; /* Update the src and dst pointers in case there's still more to do. */ - const uint srcread{minu(NumSrcSamples, SrcDataEnd + mSrcPrepCount - prepcount)}; - SamplesIn += SrcFrameSize*srcread; + const uint srcread{std::min(NumSrcSamples, SrcDataEnd + mSrcPrepCount - prepcount)}; + SamplesIn = SamplesIn.subspan(SrcFrameSize*srcread); NumSrcSamples -= srcread; - dst = static_cast(dst) + DstFrameSize*DstSize; + SamplesOut = SamplesOut.subspan(DstFrameSize*DstSize); pos += DstSize; } - *src = SamplesIn; + *src = SamplesIn.data(); *srcframes = NumSrcSamples; return pos; } -uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **dst, uint dstframes) +uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void *const*dst, uint dstframes) { + const auto srcs = al::span{src, mChan.size()}; + const auto dsts = al::span{dst, mChan.size()}; const uint increment{mIncrement}; uint NumSrcSamples{*srcframes}; @@ -319,7 +333,7 @@ uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **ds while(pos < dstframes && NumSrcSamples > 0) { const uint prepcount{mSrcPrepCount}; - const uint readable{minu(NumSrcSamples, BufferLineSize - prepcount)}; + const uint readable{std::min(NumSrcSamples, uint{BufferLineSize} - prepcount)}; if(prepcount < MaxResamplerPadding && MaxResamplerPadding-prepcount >= readable) { @@ -328,9 +342,11 @@ uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **ds */ for(size_t chan{0u};chan < mChan.size();chan++) { - LoadSamples(&mChan[chan].PrevSamples[prepcount], - static_cast(src[chan]), 1, mSrcType, readable); - src[chan] = static_cast(src[chan]) + mSrcTypeSize*readable; + auto samples = al::span{static_cast(srcs[chan]), + NumSrcSamples*size_t{mSrcTypeSize}}; + LoadSamples(al::span{mChan[chan].PrevSamples}.subspan(prepcount, readable), + samples.data(), 0, 1, mSrcType); + srcs[chan] = samples.subspan(size_t{mSrcTypeSize}*readable).data(); } mSrcPrepCount = prepcount + readable; @@ -338,8 +354,8 @@ uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **ds break; } - float *RESTRICT SrcData{mSrcSamples}; - float *RESTRICT DstData{mDstSamples}; + const auto SrcData = al::span{mSrcSamples}; + const auto DstData = al::span{mDstSamples}; uint DataPosFrac{mFracOffset}; uint64_t DataSize64{prepcount}; DataSize64 += readable; @@ -348,37 +364,37 @@ uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **ds DataSize64 -= DataPosFrac; /* If we have a full prep, we can generate at least one sample. */ - auto DstSize = static_cast( - clampu64((DataSize64 + increment-1)/increment, 1, BufferLineSize)); - DstSize = minu(DstSize, dstframes-pos); + auto DstSize = static_cast(std::clamp((DataSize64 + increment-1)/increment, 1_u64, + uint64_t{BufferLineSize})); + DstSize = std::min(DstSize, dstframes-pos); const uint DataPosEnd{DstSize*increment + DataPosFrac}; const uint SrcDataEnd{DataPosEnd>>MixerFracBits}; assert(prepcount+readable >= SrcDataEnd); - const uint nextprep{minu(prepcount + readable - SrcDataEnd, MaxResamplerPadding)}; + const uint nextprep{std::min(prepcount+readable-SrcDataEnd, MaxResamplerPadding)}; for(size_t chan{0u};chan < mChan.size();chan++) { /* Load the previous samples into the source data first, then the * new samples from the input buffer. */ - std::copy_n(mChan[chan].PrevSamples, prepcount, SrcData); - LoadSamples(SrcData + prepcount, src[chan], 1, mSrcType, readable); + auto srciter = std::copy_n(mChan[chan].PrevSamples.cbegin(),prepcount,SrcData.begin()); + LoadSamples({srciter, readable}, srcs[chan], 0, 1, mSrcType); /* Store as many prep samples for next time as possible, given the * number of output samples being generated. */ - std::copy_n(SrcData+SrcDataEnd, nextprep, mChan[chan].PrevSamples); - std::fill(std::begin(mChan[chan].PrevSamples)+nextprep, - std::end(mChan[chan].PrevSamples), 0.0f); + auto previter = std::copy_n(SrcData.begin()+ptrdiff_t(SrcDataEnd), nextprep, + mChan[chan].PrevSamples.begin()); + std::fill(previter, mChan[chan].PrevSamples.end(), 0.0f); /* Now resample, and store the result in the output buffer. */ - mResample(&mState, SrcData+MaxResamplerEdge, DataPosFrac, increment, - {DstData, DstSize}); + mResample(&mState, SrcData, DataPosFrac, increment, DstData.first(DstSize)); - std::byte *DstSamples = static_cast(dst[chan]) + pos*mDstTypeSize; - StoreSamples(DstSamples, DstData, 1, mDstType, DstSize); + auto DstSamples = al::span{static_cast(dsts[chan]), + size_t{mDstTypeSize}*dstframes}.subspan(pos*size_t{mDstTypeSize}); + StoreSamples(DstSamples.data(), DstData.first(DstSize), 0, 1, mDstType); } /* Update the number of prep samples still available, as well as the @@ -388,9 +404,13 @@ uint SampleConverter::convertPlanar(const void **src, uint *srcframes, void **ds mFracOffset = DataPosEnd & MixerFracMask; /* Update the src and dst pointers in case there's still more to do. */ - const uint srcread{minu(NumSrcSamples, SrcDataEnd + mSrcPrepCount - prepcount)}; - for(size_t chan{0u};chan < mChan.size();chan++) - src[chan] = static_cast(src[chan]) + mSrcTypeSize*srcread; + const uint srcread{std::min(NumSrcSamples, SrcDataEnd + mSrcPrepCount - prepcount)}; + std::for_each(srcs.begin(), srcs.end(), [this,NumSrcSamples,srcread](const void *&srcref) + { + auto srcspan = al::span{static_cast(srcref), + size_t{mSrcTypeSize}*NumSrcSamples}; + srcref = srcspan.subspan(size_t{mSrcTypeSize}*srcread).data(); + }); NumSrcSamples -= srcread; pos += DstSize; @@ -409,7 +429,7 @@ void ChannelConverter::convert(const void *src, float *dst, uint frames) const const float scale{std::sqrt(1.0f / static_cast(al::popcount(mChanMask)))}; switch(mSrcType) { -#define HANDLE_FMT(T) case T: Multi2Mono(mChanMask, mSrcStep, scale, dst, src, frames); break +#define HANDLE_FMT(T) case T: Multi2Mono(mChanMask, mSrcStep, scale, {dst, frames}, src); break HANDLE_FMT(DevFmtByte); HANDLE_FMT(DevFmtUByte); HANDLE_FMT(DevFmtShort); @@ -424,7 +444,7 @@ void ChannelConverter::convert(const void *src, float *dst, uint frames) const { switch(mSrcType) { -#define HANDLE_FMT(T) case T: Mono2Stereo(dst, src, frames); break +#define HANDLE_FMT(T) case T: Mono2Stereo({dst, frames*2_uz}, src); break HANDLE_FMT(DevFmtByte); HANDLE_FMT(DevFmtUByte); HANDLE_FMT(DevFmtShort); diff --git a/3rdparty/openal/core/converter.h b/3rdparty/openal/core/converter.h index d811b46b42fe..45dc4aa98888 100644 --- a/3rdparty/openal/core/converter.h +++ b/3rdparty/openal/core/converter.h @@ -7,7 +7,9 @@ #include "almalloc.h" #include "devformat.h" +#include "flexarray.h" #include "mixer/defs.h" +#include "resampler_limits.h" using uint = unsigned int; @@ -22,25 +24,25 @@ struct SampleConverter { uint mFracOffset{}; uint mIncrement{}; - InterpState mState{}; + InterpState mState; ResamplerFunc mResample{}; - alignas(16) float mSrcSamples[BufferLineSize]{}; - alignas(16) float mDstSamples[BufferLineSize]{}; + alignas(16) FloatBufferLine mSrcSamples{}; + alignas(16) FloatBufferLine mDstSamples{}; struct ChanSamples { - alignas(16) float PrevSamples[MaxResamplerPadding]; + alignas(16) std::array PrevSamples; }; al::FlexArray mChan; - SampleConverter(size_t numchans) : mChan{numchans} { } + explicit SampleConverter(size_t numchans) : mChan{numchans} { } - uint convert(const void **src, uint *srcframes, void *dst, uint dstframes); - uint convertPlanar(const void **src, uint *srcframes, void **dst, uint dstframes); - uint availableOut(uint srcframes) const; + [[nodiscard]] auto convert(const void **src, uint *srcframes, void *dst, uint dstframes) -> uint; + [[nodiscard]] auto convertPlanar(const void **src, uint *srcframes, void *const*dst, uint dstframes) -> uint; + [[nodiscard]] auto availableOut(uint srcframes) const -> uint; using SampleOffset = std::chrono::duration>; - SampleOffset currentInputDelay() const noexcept + [[nodiscard]] auto currentInputDelay() const noexcept -> SampleOffset { const int64_t prep{int64_t{mSrcPrepCount} - MaxResamplerEdge}; return SampleOffset{(prep< bool { return mChanMask != 0; } void convert(const void *src, float *dst, uint frames) const; }; diff --git a/3rdparty/openal/core/cpu_caps.cpp b/3rdparty/openal/core/cpu_caps.cpp index 1a064cf466a0..6f901d24eac4 100644 --- a/3rdparty/openal/core/cpu_caps.cpp +++ b/3rdparty/openal/core/cpu_caps.cpp @@ -1,5 +1,6 @@ #include "config.h" +#include "config_simd.h" #include "cpu_caps.h" @@ -23,8 +24,6 @@ #include -int CPUCapFlags{0}; - namespace { #if defined(HAVE_GCC_GET_CPUID) \ @@ -111,22 +110,22 @@ std::optional GetCPUInfo() #else /* Assume support for whatever's supported if we can't check for it */ -#if defined(HAVE_SSE4_1) +#if HAVE_SSE4_1 #warning "Assuming SSE 4.1 run-time support!" ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3 | CPU_CAP_SSE4_1; -#elif defined(HAVE_SSE3) +#elif HAVE_SSE3 #warning "Assuming SSE 3 run-time support!" ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2 | CPU_CAP_SSE3; -#elif defined(HAVE_SSE2) +#elif HAVE_SSE2 #warning "Assuming SSE 2 run-time support!" ret.mCaps |= CPU_CAP_SSE | CPU_CAP_SSE2; -#elif defined(HAVE_SSE) +#elif HAVE_SSE #warning "Assuming SSE run-time support!" ret.mCaps |= CPU_CAP_SSE; #endif #endif /* CAN_GET_CPUID */ -#ifdef HAVE_NEON +#if HAVE_NEON #ifdef __ARM_NEON ret.mCaps |= CPU_CAP_NEON; #elif defined(_WIN32) && (defined(_M_ARM) || defined(_M_ARM64)) diff --git a/3rdparty/openal/core/cpu_caps.h b/3rdparty/openal/core/cpu_caps.h index 0826a49bd12a..31096e015396 100644 --- a/3rdparty/openal/core/cpu_caps.h +++ b/3rdparty/openal/core/cpu_caps.h @@ -5,7 +5,7 @@ #include -extern int CPUCapFlags; +inline int CPUCapFlags{0}; enum { CPU_CAP_SSE = 1<<0, CPU_CAP_SSE2 = 1<<1, diff --git a/3rdparty/openal/core/cubic_defs.h b/3rdparty/openal/core/cubic_defs.h index 33751c9743c6..a382081640f9 100644 --- a/3rdparty/openal/core/cubic_defs.h +++ b/3rdparty/openal/core/cubic_defs.h @@ -1,13 +1,15 @@ #ifndef CORE_CUBIC_DEFS_H #define CORE_CUBIC_DEFS_H +#include + /* The number of distinct phase intervals within the cubic filter tables. */ constexpr unsigned int CubicPhaseBits{5}; constexpr unsigned int CubicPhaseCount{1 << CubicPhaseBits}; struct CubicCoefficients { - float mCoeffs[4]; - float mDeltas[4]; + alignas(16) std::array mCoeffs; + alignas(16) std::array mDeltas; }; #endif /* CORE_CUBIC_DEFS_H */ diff --git a/3rdparty/openal/core/cubic_tables.cpp b/3rdparty/openal/core/cubic_tables.cpp index 5e7aafad6386..a7cb101915e2 100644 --- a/3rdparty/openal/core/cubic_tables.cpp +++ b/3rdparty/openal/core/cubic_tables.cpp @@ -2,50 +2,123 @@ #include "cubic_tables.h" #include -#include +#include +#include +#include "alnumbers.h" +#include "alnumeric.h" #include "cubic_defs.h" - +/* These gaussian filter tables are inspired by the gaussian-like filter found + * in the SNES. This is based on the public domain code developed by Near, with + * the help of Ryphecha and nocash, from the nesdev.org forums. + * + * + * + * Additional changes were made here, the most obvious being that it has full + * floating-point precision instead of 11-bit fixed-point, but also an offset + * adjustment for the coefficients to better preserve phase. + */ namespace { -struct SplineFilterArray { - alignas(16) std::array mTable{}; +[[nodiscard]] +auto GetCoeff(double idx) noexcept -> double +{ + const double k{0.5 + idx}; + if(k > 512.0) return 0.0; + const double s{ std::sin(al::numbers::pi*1.280/1024.0 * k)}; + const double t{(std::cos(al::numbers::pi*2.000/1023.0 * k) - 1.0) * 0.50}; + const double u{(std::cos(al::numbers::pi*4.000/1023.0 * k) - 1.0) * 0.08}; + return s * (t + u + 1.0) / k; +} + +} // namespace - constexpr SplineFilterArray() +GaussianTable::GaussianTable() +{ + static constexpr double IndexScale{512.0 / double{CubicPhaseCount*2}}; + /* Fill in the main coefficients. */ + for(std::size_t pi{0};pi < CubicPhaseCount;++pi) { - /* Fill in the main coefficients. */ - for(size_t pi{0};pi < CubicPhaseCount;++pi) - { - const double mu{static_cast(pi) / CubicPhaseCount}; - const double mu2{mu*mu}, mu3{mu2*mu}; - mTable[pi].mCoeffs[0] = static_cast(-0.5*mu3 + mu2 + -0.5*mu); - mTable[pi].mCoeffs[1] = static_cast( 1.5*mu3 + -2.5*mu2 + 1.0); - mTable[pi].mCoeffs[2] = static_cast(-1.5*mu3 + 2.0*mu2 + 0.5*mu); - mTable[pi].mCoeffs[3] = static_cast( 0.5*mu3 + -0.5*mu2); - } - - /* Fill in the coefficient deltas. */ - for(size_t pi{0};pi < CubicPhaseCount-1;++pi) - { - mTable[pi].mDeltas[0] = mTable[pi+1].mCoeffs[0] - mTable[pi].mCoeffs[0]; - mTable[pi].mDeltas[1] = mTable[pi+1].mCoeffs[1] - mTable[pi].mCoeffs[1]; - mTable[pi].mDeltas[2] = mTable[pi+1].mCoeffs[2] - mTable[pi].mCoeffs[2]; - mTable[pi].mDeltas[3] = mTable[pi+1].mCoeffs[3] - mTable[pi].mCoeffs[3]; - } - - const size_t pi{CubicPhaseCount - 1}; - mTable[pi].mDeltas[0] = -mTable[pi].mCoeffs[0]; - mTable[pi].mDeltas[1] = -mTable[pi].mCoeffs[1]; - mTable[pi].mDeltas[2] = 1.0f - mTable[pi].mCoeffs[2]; - mTable[pi].mDeltas[3] = -mTable[pi].mCoeffs[3]; + const double coeff0{GetCoeff(static_cast(CubicPhaseCount + pi)*IndexScale)}; + const double coeff1{GetCoeff(static_cast(pi)*IndexScale)}; + const double coeff2{GetCoeff(static_cast(CubicPhaseCount - pi)*IndexScale)}; + const double coeff3{GetCoeff(static_cast(CubicPhaseCount*2_uz-pi)*IndexScale)}; + + const double scale{1.0 / (coeff0 + coeff1 + coeff2 + coeff3)}; + mTable[pi].mCoeffs[0] = static_cast(coeff0 * scale); + mTable[pi].mCoeffs[1] = static_cast(coeff1 * scale); + mTable[pi].mCoeffs[2] = static_cast(coeff2 * scale); + mTable[pi].mCoeffs[3] = static_cast(coeff3 * scale); } - constexpr auto& getTable() const noexcept { return mTable; } -}; + /* Fill in the coefficient deltas. */ + for(std::size_t pi{0};pi < CubicPhaseCount-1;++pi) + { + mTable[pi].mDeltas[0] = mTable[pi+1].mCoeffs[0] - mTable[pi].mCoeffs[0]; + mTable[pi].mDeltas[1] = mTable[pi+1].mCoeffs[1] - mTable[pi].mCoeffs[1]; + mTable[pi].mDeltas[2] = mTable[pi+1].mCoeffs[2] - mTable[pi].mCoeffs[2]; + mTable[pi].mDeltas[3] = mTable[pi+1].mCoeffs[3] - mTable[pi].mCoeffs[3]; + } -constexpr SplineFilterArray SplineFilter{}; + const std::size_t pi{CubicPhaseCount - 1}; + mTable[pi].mDeltas[0] = 0.0f - mTable[pi].mCoeffs[0]; + mTable[pi].mDeltas[1] = mTable[0].mCoeffs[0] - mTable[pi].mCoeffs[1]; + mTable[pi].mDeltas[2] = mTable[0].mCoeffs[1] - mTable[pi].mCoeffs[2]; + mTable[pi].mDeltas[3] = mTable[0].mCoeffs[2] - mTable[pi].mCoeffs[3]; +} -} // namespace +SplineTable::SplineTable() +{ + static constexpr auto third = 1.0/3.0; + static constexpr auto sixth = 1.0/6.0; + /* This filter table is based on a Catmull-Rom spline. It retains more of + * the original high-frequency content, at the cost of increased harmonics. + */ + for(std::size_t pi{0};pi < CubicPhaseCount;++pi) + { + const auto mu = static_cast(pi) / double{CubicPhaseCount}; + const auto mu2 = mu*mu; + const auto mu3 = mu*mu2; + mTable[pi].mCoeffs[0] = static_cast( -third*mu + 0.5*mu2 - sixth*mu3); + mTable[pi].mCoeffs[1] = static_cast(1.0 - 0.5*mu - mu2 + 0.5*mu3); + mTable[pi].mCoeffs[2] = static_cast( mu + 0.5*mu2 - 0.5*mu3); + mTable[pi].mCoeffs[3] = static_cast( -sixth*mu + sixth*mu3); + } -const CubicTable gCubicSpline{SplineFilter.getTable()}; + for(std::size_t pi{0};pi < CubicPhaseCount-1;++pi) + { + mTable[pi].mDeltas[0] = mTable[pi+1].mCoeffs[0] - mTable[pi].mCoeffs[0]; + mTable[pi].mDeltas[1] = mTable[pi+1].mCoeffs[1] - mTable[pi].mCoeffs[1]; + mTable[pi].mDeltas[2] = mTable[pi+1].mCoeffs[2] - mTable[pi].mCoeffs[2]; + mTable[pi].mDeltas[3] = mTable[pi+1].mCoeffs[3] - mTable[pi].mCoeffs[3]; + } + + static constexpr auto pi = std::size_t{CubicPhaseCount - 1}; + mTable[pi].mDeltas[0] = 0.0f - mTable[pi].mCoeffs[0]; + mTable[pi].mDeltas[1] = mTable[0].mCoeffs[0] - mTable[pi].mCoeffs[1]; + mTable[pi].mDeltas[2] = mTable[0].mCoeffs[1] - mTable[pi].mCoeffs[2]; + mTable[pi].mDeltas[3] = mTable[0].mCoeffs[2] - mTable[pi].mCoeffs[3]; +} + + +CubicFilter::CubicFilter() +{ + static constexpr double IndexScale{512.0 / double{sTableSteps*2}}; + /* Only half the coefficients need to be iterated here, since Coeff2 and + * Coeff3 are just Coeff1 and Coeff0 in reverse respectively. + */ + for(size_t i{0};i < sTableSteps/2 + 1;++i) + { + const double coeff0{GetCoeff(static_cast(sTableSteps + i)*IndexScale)}; + const double coeff1{GetCoeff(static_cast(i)*IndexScale)}; + const double coeff2{GetCoeff(static_cast(sTableSteps - i)*IndexScale)}; + const double coeff3{GetCoeff(static_cast(sTableSteps*2_uz - i)*IndexScale)}; + + const double scale{1.0 / (coeff0 + coeff1 + coeff2 + coeff3)}; + mFilter[sTableSteps + i] = static_cast(coeff0 * scale); + mFilter[i] = static_cast(coeff1 * scale); + mFilter[sTableSteps - i] = static_cast(coeff2 * scale); + mFilter[sTableSteps*2 - i] = static_cast(coeff3 * scale); + } +} diff --git a/3rdparty/openal/core/cubic_tables.h b/3rdparty/openal/core/cubic_tables.h index 88097ae2f153..b32764451737 100644 --- a/3rdparty/openal/core/cubic_tables.h +++ b/3rdparty/openal/core/cubic_tables.h @@ -1,17 +1,42 @@ #ifndef CORE_CUBIC_TABLES_H #define CORE_CUBIC_TABLES_H -#include "alspan.h" +#include +#include + #include "cubic_defs.h" +#include "opthelpers.h" -struct CubicTable { - al::span Tab; +struct SIMDALIGN CubicTable { + std::array mTable{}; }; -/* A Catmull-Rom spline. The spline passes through the center two samples, - * ensuring no discontinuity while moving through a series of samples. - */ -extern const CubicTable gCubicSpline; +struct GaussianTable : CubicTable { GaussianTable(); }; +inline const GaussianTable gGaussianFilter; + +struct SplineTable : CubicTable { SplineTable(); }; +inline const SplineTable gSplineFilter; + + +struct CubicFilter { + static constexpr std::size_t sTableBits{8}; + static constexpr std::size_t sTableSteps{1 << sTableBits}; + static constexpr std::size_t sTableMask{sTableSteps - 1}; + + std::array mFilter{}; + + CubicFilter(); + + [[nodiscard]] constexpr + auto getCoeff0(std::size_t i) const noexcept -> float { return mFilter[sTableSteps+i]; } + [[nodiscard]] constexpr + auto getCoeff1(std::size_t i) const noexcept -> float { return mFilter[i]; } + [[nodiscard]] constexpr + auto getCoeff2(std::size_t i) const noexcept -> float { return mFilter[sTableSteps-i]; } + [[nodiscard]] constexpr + auto getCoeff3(std::size_t i) const noexcept -> float { return mFilter[sTableSteps*2-i]; } +}; +inline const CubicFilter gCubicTable; #endif /* CORE_CUBIC_TABLES_H */ diff --git a/3rdparty/openal/core/dbus_wrap.cpp b/3rdparty/openal/core/dbus_wrap.cpp index 4841956686b6..eccfb2c0b716 100644 --- a/3rdparty/openal/core/dbus_wrap.cpp +++ b/3rdparty/openal/core/dbus_wrap.cpp @@ -3,40 +3,40 @@ #include "dbus_wrap.h" -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD #include #include -#include "albit.h" #include "logging.h" void PrepareDBus() { - static constexpr char libname[] = "libdbus-1.so.3"; + const char *libname{"libdbus-1.so.3"}; + + dbus_handle = LoadLib(libname); + if(!dbus_handle) + { + WARN("Failed to load {}", libname); + return; + } auto load_func = [](auto &f, const char *name) -> void - { f = al::bit_cast>(GetSymbol(dbus_handle, name)); }; + { f = reinterpret_cast>(GetSymbol(dbus_handle, name)); }; #define LOAD_FUNC(x) do { \ load_func(p##x, #x); \ if(!p##x) \ { \ - WARN("Failed to load function %s\n", #x); \ + WARN("Failed to load function {}", #x); \ CloseLib(dbus_handle); \ dbus_handle = nullptr; \ return; \ } \ } while(0); - dbus_handle = LoadLib(libname); - if(!dbus_handle) - { - WARN("Failed to load %s\n", libname); - return; - } + DBUS_FUNCTIONS(LOAD_FUNC) -DBUS_FUNCTIONS(LOAD_FUNC) #undef LOAD_FUNC } #endif diff --git a/3rdparty/openal/core/dbus_wrap.h b/3rdparty/openal/core/dbus_wrap.h index 65f08942409e..85a996eb375e 100644 --- a/3rdparty/openal/core/dbus_wrap.h +++ b/3rdparty/openal/core/dbus_wrap.h @@ -7,7 +7,7 @@ #include "dynload.h" -#ifdef HAVE_DYNLOAD +#if HAVE_DYNLOAD #include @@ -63,16 +63,23 @@ inline auto HasDBus() #else constexpr bool HasDBus() noexcept { return true; } -#endif /* HAVE_DYNLOAD */ +#endif namespace dbus { struct Error { Error() { dbus_error_init(&mError); } + Error(const Error&) = delete; + Error(Error&&) = delete; ~Error() { dbus_error_free(&mError); } + + void operator=(const Error&) = delete; + void operator=(Error&&) = delete; + DBusError* operator->() { return &mError; } DBusError &get() { return mError; } + private: DBusError mError{}; }; diff --git a/3rdparty/openal/core/devformat.cpp b/3rdparty/openal/core/devformat.cpp index acdabc4f1f43..fc4a490aeec4 100644 --- a/3rdparty/openal/core/devformat.cpp +++ b/3rdparty/openal/core/devformat.cpp @@ -3,6 +3,11 @@ #include "devformat.h" +#include + +namespace { +using namespace std::string_view_literals; +} // namespace uint BytesFromDevFmt(DevFmtType type) noexcept { @@ -29,39 +34,41 @@ uint ChannelsFromDevFmt(DevFmtChannels chans, uint ambiorder) noexcept case DevFmtX61: return 7; case DevFmtX71: return 8; case DevFmtX714: return 12; + case DevFmtX7144: return 16; case DevFmtX3D71: return 8; case DevFmtAmbi3D: return (ambiorder+1) * (ambiorder+1); } return 0; } -const char *DevFmtTypeString(DevFmtType type) noexcept +auto DevFmtTypeString(DevFmtType type) noexcept -> std::string_view { switch(type) { - case DevFmtByte: return "Int8"; - case DevFmtUByte: return "UInt8"; - case DevFmtShort: return "Int16"; - case DevFmtUShort: return "UInt16"; - case DevFmtInt: return "Int32"; - case DevFmtUInt: return "UInt32"; - case DevFmtFloat: return "Float32"; + case DevFmtByte: return "Int8"sv; + case DevFmtUByte: return "UInt8"sv; + case DevFmtShort: return "Int16"sv; + case DevFmtUShort: return "UInt16"sv; + case DevFmtInt: return "Int32"sv; + case DevFmtUInt: return "UInt32"sv; + case DevFmtFloat: return "Float32"sv; } - return "(unknown type)"; + return "(unknown type)"sv; } -const char *DevFmtChannelsString(DevFmtChannels chans) noexcept +auto DevFmtChannelsString(DevFmtChannels chans) noexcept -> std::string_view { switch(chans) { - case DevFmtMono: return "Mono"; - case DevFmtStereo: return "Stereo"; - case DevFmtQuad: return "Quadraphonic"; - case DevFmtX51: return "5.1 Surround"; - case DevFmtX61: return "6.1 Surround"; - case DevFmtX71: return "7.1 Surround"; - case DevFmtX714: return "7.1.4 Surround"; - case DevFmtX3D71: return "3D7.1 Surround"; - case DevFmtAmbi3D: return "Ambisonic 3D"; + case DevFmtMono: return "Mono"sv; + case DevFmtStereo: return "Stereo"sv; + case DevFmtQuad: return "Quadraphonic"sv; + case DevFmtX51: return "5.1 Surround"sv; + case DevFmtX61: return "6.1 Surround"sv; + case DevFmtX71: return "7.1 Surround"sv; + case DevFmtX714: return "7.1.4 Surround"sv; + case DevFmtX7144: return "7.1.4.4 Surround"sv; + case DevFmtX3D71: return "3D7.1 Surround"sv; + case DevFmtAmbi3D: return "Ambisonic 3D"sv; } - return "(unknown channels)"; + return "(unknown channels)"sv; } diff --git a/3rdparty/openal/core/devformat.h b/3rdparty/openal/core/devformat.h index 485826a397e7..beff40de347a 100644 --- a/3rdparty/openal/core/devformat.h +++ b/3rdparty/openal/core/devformat.h @@ -2,6 +2,8 @@ #define CORE_DEVFORMAT_H #include +#include +#include using uint = unsigned int; @@ -25,6 +27,11 @@ enum Channel : unsigned char { TopBackCenter, TopBackRight, + BottomFrontLeft, + BottomFrontRight, + BottomBackLeft, + BottomBackRight, + Aux0, Aux1, Aux2, @@ -66,12 +73,13 @@ enum DevFmtChannels : unsigned char { DevFmtX61, DevFmtX71, DevFmtX714, + DevFmtX7144, DevFmtX3D71, DevFmtAmbi3D, DevFmtChannelsDefault = DevFmtStereo }; -#define MAX_OUTPUT_CHANNELS 16 +inline constexpr std::size_t MaxOutputChannels{16}; /* DevFmtType traits, providing the type, etc given a DevFmtType. */ template @@ -101,8 +109,8 @@ uint ChannelsFromDevFmt(DevFmtChannels chans, uint ambiorder) noexcept; inline uint FrameSizeFromDevFmt(DevFmtChannels chans, DevFmtType type, uint ambiorder) noexcept { return ChannelsFromDevFmt(chans, ambiorder) * BytesFromDevFmt(type); } -const char *DevFmtTypeString(DevFmtType type) noexcept; -const char *DevFmtChannelsString(DevFmtChannels chans) noexcept; +auto DevFmtTypeString(DevFmtType type) noexcept -> std::string_view; +auto DevFmtChannelsString(DevFmtChannels chans) noexcept -> std::string_view; enum class DevAmbiLayout : bool { FuMa, diff --git a/3rdparty/openal/core/device.cpp b/3rdparty/openal/core/device.cpp index 2766c5e4ea7e..4c2dc2a38864 100644 --- a/3rdparty/openal/core/device.cpp +++ b/3rdparty/openal/core/device.cpp @@ -9,15 +9,9 @@ #include "mastering.h" -al::FlexArray DeviceBase::sEmptyContextArray{0u}; - - -DeviceBase::DeviceBase(DeviceType type) : Type{type}, mContexts{&sEmptyContextArray} +DeviceBase::DeviceBase(DeviceType type) + : Type{type}, mContexts{al::FlexArray::Create(0)} { } -DeviceBase::~DeviceBase() -{ - auto *oldarray = mContexts.exchange(nullptr, std::memory_order_relaxed); - if(oldarray != &sEmptyContextArray) delete oldarray; -} +DeviceBase::~DeviceBase() = default; diff --git a/3rdparty/openal/core/device.h b/3rdparty/openal/core/device.h index b088e130ef04..c01888c8eff3 100644 --- a/3rdparty/openal/core/device.h +++ b/3rdparty/openal/core/device.h @@ -5,9 +5,9 @@ #include #include #include +#include +#include #include -#include -#include #include #include "almalloc.h" @@ -17,6 +17,8 @@ #include "bufferline.h" #include "devformat.h" #include "filters/nfc.h" +#include "flexarray.h" +#include "fmt/core.h" #include "intrusive_ptr.h" #include "mixer/hrtfdefs.h" #include "opthelpers.h" @@ -25,8 +27,10 @@ #include "vector.h" class BFormatDec; +namespace Bs2b { struct bs2b; -struct Compressor; +} // namespace Bs2b +class Compressor; struct ContextBase; struct DirectHrtfState; struct HrtfStore; @@ -34,28 +38,28 @@ struct HrtfStore; using uint = unsigned int; -#define MIN_OUTPUT_RATE 8000 -#define MAX_OUTPUT_RATE 192000 -#define DEFAULT_OUTPUT_RATE 48000 +inline constexpr std::size_t MinOutputRate{8000}; +inline constexpr std::size_t MaxOutputRate{192000}; +inline constexpr std::size_t DefaultOutputRate{48000}; -#define DEFAULT_UPDATE_SIZE 960 /* 20ms */ -#define DEFAULT_NUM_UPDATES 3 +inline constexpr std::size_t DefaultUpdateSize{960}; /* 20ms */ +inline constexpr std::size_t DefaultNumUpdates{3}; -enum class DeviceType : uint8_t { +enum class DeviceType : std::uint8_t { Playback, Capture, Loopback }; -enum class RenderMode : uint8_t { +enum class RenderMode : std::uint8_t { Normal, Pairwise, Hrtf }; -enum class StereoEncoding : uint8_t { +enum class StereoEncoding : std::uint8_t { Basic, Uhj, Hrtf, @@ -77,24 +81,23 @@ struct DistanceComp { static constexpr uint MaxDelay{1024}; struct ChanData { + al::span Buffer; /* Valid size is [0...MaxDelay). */ float Gain{1.0f}; - uint Length{0u}; /* Valid range is [0...MaxDelay). */ - float *Buffer{nullptr}; }; - std::array mChannels; + std::array mChannels; al::FlexArray mSamples; - DistanceComp(size_t count) : mSamples{count} { } + explicit DistanceComp(std::size_t count) : mSamples{count} { } - static std::unique_ptr Create(size_t numsamples) + static std::unique_ptr Create(std::size_t numsamples) { return std::unique_ptr{new(FamCount(numsamples)) DistanceComp{numsamples}}; } DEF_FAM_NEWDEL(DistanceComp, mSamples) }; -constexpr uint InvalidChannelIndex{~0u}; +constexpr auto InvalidChannelIndex = static_cast(~0u); struct BFChannelConfig { float Scale; @@ -112,24 +115,24 @@ struct MixParams { * source is expected to be a 3D ACN/N3D ambisonic buffer, and for each * channel [0...count), the given functor is called with the source channel * index, destination channel index, and the gain for that channel. If the - * destination channel is INVALID_CHANNEL_INDEX, the given source channel - * is not used for output. + * destination channel is InvalidChannelIndex, the given source channel is + * not used for output. */ template void setAmbiMixParams(const MixParams &inmix, const float gainbase, F func) const { - const size_t numIn{inmix.Buffer.size()}; - const size_t numOut{Buffer.size()}; - for(size_t i{0};i < numIn;++i) + const std::size_t numIn{inmix.Buffer.size()}; + const std::size_t numOut{Buffer.size()}; + for(std::size_t i{0};i < numIn;++i) { - auto idx = InvalidChannelIndex; - auto gain = 0.0f; + std::uint8_t idx{InvalidChannelIndex}; + float gain{0.0f}; - for(size_t j{0};j < numOut;++j) + for(std::size_t j{0};j < numOut;++j) { if(AmbiMap[j].Index == inmix.AmbiMap[i].Index) { - idx = static_cast(j); + idx = static_cast(j); gain = AmbiMap[j].Scale * gainbase; break; } @@ -141,7 +144,7 @@ struct MixParams { struct RealMixParams { al::span RemixMap; - std::array ChannelIndex{}; + std::array ChannelIndex{}; al::span Buffer; }; @@ -158,8 +161,6 @@ enum { // Specifies if the DSP is paused at user request DevicePaused, - // Specifies if the device is currently running - DeviceRunning, // Specifies if the output plays directly on/in ears (headphones, headset, // ear buds, etc). @@ -173,18 +174,22 @@ enum { DeviceFlagsCount }; -struct DeviceBase { - /* To avoid extraneous allocations, a 0-sized FlexArray is - * defined globally as a sharable object. - */ - static al::FlexArray sEmptyContextArray; +enum class DeviceState : std::uint8_t { + Unprepared, + Configured, + Playing +}; +/* NOLINTNEXTLINE(clang-analyzer-optin.performance.Padding) */ +struct SIMDALIGN DeviceBase { std::atomic Connected{true}; const DeviceType Type{}; - uint Frequency{}; - uint UpdateSize{}; - uint BufferSize{}; + std::string mDeviceName; + + uint mSampleRate{}; + uint mUpdateSize{}; + uint mBufferSize{}; DevFmtChannels FmtChans{}; DevFmtType FmtType{}; @@ -198,10 +203,9 @@ struct DeviceBase { DevAmbiLayout mAmbiLayout{DevAmbiLayout::Default}; DevAmbiScaling mAmbiScale{DevAmbiScaling::Default}; - std::string DeviceName; - // Device flags - std::bitset Flags{}; + std::bitset Flags; + DeviceState mDeviceState{DeviceState::Unprepared}; uint NumAuxSends{}; @@ -218,35 +222,36 @@ struct DeviceBase { */ NfcFilter mNFCtrlFilter{}; - uint SamplesDone{0u}; - std::chrono::nanoseconds ClockBase{0}; + using seconds32 = std::chrono::duration; + using nanoseconds32 = std::chrono::duration; + + std::atomic mSamplesDone{0u}; + /* Split the clock to avoid a 64-bit atomic for certain 32-bit targets. */ + std::atomic mClockBaseSec{seconds32{}}; + std::atomic mClockBaseNSec{nanoseconds32{}}; std::chrono::nanoseconds FixedLatency{0}; AmbiRotateMatrix mAmbiRotateMatrix{}; AmbiRotateMatrix mAmbiRotateMatrix2{}; /* Temp storage used for mixer processing. */ - static constexpr size_t MixerLineSize{BufferLineSize + DecoderBase::sMaxPadding}; - static constexpr size_t MixerChannelsMax{16}; - using MixerBufferLine = std::array; - alignas(16) std::array mSampleData; - alignas(16) std::array mResampleData; - - alignas(16) float FilteredData[BufferLineSize]; - union { - alignas(16) float HrtfSourceData[BufferLineSize + HrtfHistoryLength]; - alignas(16) float NfcSampleData[BufferLineSize]; - }; + static constexpr std::size_t MixerLineSize{BufferLineSize + DecoderBase::sMaxPadding}; + static constexpr std::size_t MixerChannelsMax{16}; + alignas(16) std::array mSampleData{}; + alignas(16) std::array mResampleData{}; + + alignas(16) std::array FilteredData{}; + alignas(16) std::array ExtraSampleData{}; /* Persistent storage for HRTF mixing. */ - alignas(16) float2 HrtfAccumData[BufferLineSize + HrirLength]; + alignas(16) std::array HrtfAccumData{}; /* Mixing buffer used by the Dry mix and Real output. */ al::vector MixBuffer; /* The "dry" path corresponds to the main output. */ MixParams Dry; - uint NumChannelsPerOrder[MaxAmbiOrder+1]{}; + std::array NumChannelsPerOrder{}; /* "Real" output, which will be written to the device buffer. May alias the * dry buffer. @@ -265,7 +270,7 @@ struct DeviceBase { std::unique_ptr AmbiDecoder; /* Stereo-to-binaural filter */ - std::unique_ptr Bs2b; + std::unique_ptr Bs2b; using PostProc = void(DeviceBase::*)(const size_t SamplesToDo); PostProc PostProcess{nullptr}; @@ -284,66 +289,104 @@ struct DeviceBase { * the end, so the bottom bit indicates if the device is currently mixing * and the upper bits indicates how many mixes have been done. */ - RefCount MixCount{0u}; + std::atomic mMixCount{0u}; // Contexts created on this device - std::atomic*> mContexts{nullptr}; + al::atomic_unique_ptr> mContexts; - DeviceBase(DeviceType type); - DeviceBase(const DeviceBase&) = delete; - DeviceBase& operator=(const DeviceBase&) = delete; - ~DeviceBase(); + [[nodiscard]] auto bytesFromFmt() const noexcept -> uint { return BytesFromDevFmt(FmtType); } + [[nodiscard]] auto channelsFromFmt() const noexcept -> uint { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); } + [[nodiscard]] auto frameSizeFromFmt() const noexcept -> uint { return bytesFromFmt() * channelsFromFmt(); } - uint bytesFromFmt() const noexcept { return BytesFromDevFmt(FmtType); } - uint channelsFromFmt() const noexcept { return ChannelsFromDevFmt(FmtChans, mAmbiOrder); } - uint frameSizeFromFmt() const noexcept { return bytesFromFmt() * channelsFromFmt(); } + struct MixLock { + DeviceBase *const self; + const uint mEndVal; - uint waitForMix() const noexcept + MixLock(DeviceBase *device, const uint endval) noexcept : self{device}, mEndVal{endval} { } + MixLock(const MixLock&) = delete; + void operator=(const MixLock&) = delete; + /* Update the mix count when the lock goes out of scope to "release" it + * (lsb should be 0). + */ + ~MixLock() { self->mMixCount.store(mEndVal, std::memory_order_release); } + }; + auto getWriteMixLock() noexcept -> MixLock { - uint refcount; - while((refcount=MixCount.load(std::memory_order_acquire))&1) { - } + /* Increment the mix count at the start of mixing and writing clock + * info (lsb should be 1). + */ + const auto oldCount = mMixCount.fetch_add(1u, std::memory_order_acq_rel); + return MixLock{this, oldCount+2}; + } + + /** Waits for the mixer to not be mixing or updating the clock. */ + [[nodiscard]] auto waitForMix() const noexcept -> uint + { + uint refcount{mMixCount.load(std::memory_order_acquire)}; + while((refcount&1)) refcount = mMixCount.load(std::memory_order_acquire); return refcount; } - void ProcessHrtf(const size_t SamplesToDo); - void ProcessAmbiDec(const size_t SamplesToDo); - void ProcessAmbiDecStablized(const size_t SamplesToDo); - void ProcessUhj(const size_t SamplesToDo); - void ProcessBs2b(const size_t SamplesToDo); + /** + * Helper to get the current clock time from the device's ClockBase, and + * SamplesDone converted from the sample rate. Should only be called while + * watching the MixCount. + */ + [[nodiscard]] auto getClockTime() const noexcept -> std::chrono::nanoseconds + { + using std::chrono::seconds; + using std::chrono::nanoseconds; + + auto ns = nanoseconds{seconds{mSamplesDone.load(std::memory_order_relaxed)}} / mSampleRate; + return nanoseconds{mClockBaseNSec.load(std::memory_order_relaxed)} + + mClockBaseSec.load(std::memory_order_relaxed) + ns; + } + + void ProcessHrtf(const std::size_t SamplesToDo); + void ProcessAmbiDec(const std::size_t SamplesToDo); + void ProcessAmbiDecStablized(const std::size_t SamplesToDo); + void ProcessUhj(const std::size_t SamplesToDo); + void ProcessBs2b(const std::size_t SamplesToDo); - inline void postProcess(const size_t SamplesToDo) + void postProcess(const std::size_t SamplesToDo) { if(PostProcess) LIKELY (this->*PostProcess)(SamplesToDo); } - void renderSamples(const al::span outBuffers, const uint numSamples); - void renderSamples(void *outBuffer, const uint numSamples, const size_t frameStep); + void renderSamples(const al::span outBuffers, const uint numSamples); + void renderSamples(void *outBuffer, const uint numSamples, const std::size_t frameStep); /* Caller must lock the device state, and the mixer must not be running. */ -#ifdef __USE_MINGW_ANSI_STDIO - [[gnu::format(gnu_printf,2,3)]] -#else - [[gnu::format(printf,2,3)]] -#endif - void handleDisconnect(const char *msg, ...); + void doDisconnect(std::string msg); + + template + void handleDisconnect(fmt::format_string fmt, Args&& ...args) + { doDisconnect(fmt::format(std::move(fmt), std::forward(args)...)); } /** * Returns the index for the given channel name (e.g. FrontCenter), or - * INVALID_CHANNEL_INDEX if it doesn't exist. + * InvalidChannelIndex if it doesn't exist. */ - uint channelIdxByName(Channel chan) const noexcept + [[nodiscard]] auto channelIdxByName(Channel chan) const noexcept -> std::uint8_t { return RealOut.ChannelIndex[chan]; } - DISABLE_ALLOC() - private: uint renderSamples(const uint numSamples); + +protected: + explicit DeviceBase(DeviceType type); + ~DeviceBase(); + +public: + DeviceBase(const DeviceBase&) = delete; + DeviceBase& operator=(const DeviceBase&) = delete; }; /* Must be less than 15 characters (16 including terminating null) for * compatibility with pthread_setname_np limitations. */ -#define MIXER_THREAD_NAME "alsoft-mixer" +[[nodiscard]] constexpr +auto GetMixerThreadName() noexcept -> const char* { return "alsoft-mixer"; } -#define RECORD_THREAD_NAME "alsoft-record" +[[nodiscard]] constexpr +auto GetRecordThreadName() noexcept -> const char* { return "alsoft-record"; } #endif /* CORE_DEVICE_H */ diff --git a/3rdparty/openal/core/effects/base.h b/3rdparty/openal/core/effects/base.h index b02d33b7b1ae..879f83900549 100644 --- a/3rdparty/openal/core/effects/base.h +++ b/3rdparty/openal/core/effects/base.h @@ -1,13 +1,14 @@ #ifndef CORE_EFFECTS_BASE_H #define CORE_EFFECTS_BASE_H -#include +#include +#include +#include -#include "almalloc.h" #include "alspan.h" -#include "atomic.h" #include "core/bufferline.h" #include "intrusive_ptr.h" +#include "opthelpers.h" struct BufferStorage; struct ContextBase; @@ -18,21 +19,21 @@ struct RealMixParams; /** Target gain for the reverb decay feedback reaching the decay time. */ -constexpr float ReverbDecayGain{0.001f}; /* -60 dB */ +inline constexpr float ReverbDecayGain{0.001f}; /* -60 dB */ -constexpr float ReverbMaxReflectionsDelay{0.3f}; -constexpr float ReverbMaxLateReverbDelay{0.1f}; +inline constexpr float ReverbMaxReflectionsDelay{0.3f}; +inline constexpr float ReverbMaxLateReverbDelay{0.1f}; enum class ChorusWaveform { Sinusoid, Triangle }; -constexpr float ChorusMaxDelay{0.016f}; -constexpr float FlangerMaxDelay{0.004f}; +inline constexpr float ChorusMaxDelay{0.016f}; +inline constexpr float FlangerMaxDelay{0.004f}; -constexpr float EchoMaxDelay{0.207f}; -constexpr float EchoMaxLRDelay{0.404f}; +inline constexpr float EchoMaxDelay{0.207f}; +inline constexpr float EchoMaxLRDelay{0.404f}; enum class FShifterDirection { Down, @@ -58,122 +59,142 @@ enum class VMorpherWaveform { Sawtooth }; -union EffectProps { - struct { - float Density; - float Diffusion; - float Gain; - float GainHF; - float GainLF; - float DecayTime; - float DecayHFRatio; - float DecayLFRatio; - float ReflectionsGain; - float ReflectionsDelay; - float ReflectionsPan[3]; - float LateReverbGain; - float LateReverbDelay; - float LateReverbPan[3]; - float EchoTime; - float EchoDepth; - float ModulationTime; - float ModulationDepth; - float AirAbsorptionGainHF; - float HFReference; - float LFReference; - float RoomRolloffFactor; - bool DecayHFLimit; - } Reverb; - - struct { - float AttackTime; - float ReleaseTime; - float Resonance; - float PeakGain; - } Autowah; - - struct { - ChorusWaveform Waveform; - int Phase; - float Rate; - float Depth; - float Feedback; - float Delay; - } Chorus; /* Also Flanger */ - - struct { - bool OnOff; - } Compressor; - - struct { - float Edge; - float Gain; - float LowpassCutoff; - float EQCenter; - float EQBandwidth; - } Distortion; - - struct { - float Delay; - float LRDelay; - - float Damping; - float Feedback; - - float Spread; - } Echo; - - struct { - float LowCutoff; - float LowGain; - float Mid1Center; - float Mid1Gain; - float Mid1Width; - float Mid2Center; - float Mid2Gain; - float Mid2Width; - float HighCutoff; - float HighGain; - } Equalizer; - - struct { - float Frequency; - FShifterDirection LeftDirection; - FShifterDirection RightDirection; - } Fshifter; - - struct { - float Frequency; - float HighPassCutoff; - ModulatorWaveform Waveform; - } Modulator; - - struct { - int CoarseTune; - int FineTune; - } Pshifter; - - struct { - float Rate; - VMorpherPhenome PhonemeA; - VMorpherPhenome PhonemeB; - int PhonemeACoarseTuning; - int PhonemeBCoarseTuning; - VMorpherWaveform Waveform; - } Vmorpher; - - struct { - float Gain; - } Dedicated; +struct ReverbProps { + float Density; + float Diffusion; + float Gain; + float GainHF; + float GainLF; + float DecayTime; + float DecayHFRatio; + float DecayLFRatio; + float ReflectionsGain; + float ReflectionsDelay; + std::array ReflectionsPan; + float LateReverbGain; + float LateReverbDelay; + std::array LateReverbPan; + float EchoTime; + float EchoDepth; + float ModulationTime; + float ModulationDepth; + float AirAbsorptionGainHF; + float HFReference; + float LFReference; + float RoomRolloffFactor; + bool DecayHFLimit; }; +struct AutowahProps { + float AttackTime; + float ReleaseTime; + float Resonance; + float PeakGain; +}; + +struct ChorusProps { + ChorusWaveform Waveform; + int Phase; + float Rate; + float Depth; + float Feedback; + float Delay; +}; + +struct CompressorProps { + bool OnOff; +}; + +struct DistortionProps { + float Edge; + float Gain; + float LowpassCutoff; + float EQCenter; + float EQBandwidth; +}; + +struct EchoProps { + float Delay; + float LRDelay; + + float Damping; + float Feedback; + + float Spread; +}; + +struct EqualizerProps { + float LowCutoff; + float LowGain; + float Mid1Center; + float Mid1Gain; + float Mid1Width; + float Mid2Center; + float Mid2Gain; + float Mid2Width; + float HighCutoff; + float HighGain; +}; + +struct FshifterProps { + float Frequency; + FShifterDirection LeftDirection; + FShifterDirection RightDirection; +}; + +struct ModulatorProps { + float Frequency; + float HighPassCutoff; + ModulatorWaveform Waveform; +}; + +struct PshifterProps { + int CoarseTune; + int FineTune; +}; + +struct VmorpherProps { + float Rate; + VMorpherPhenome PhonemeA; + VMorpherPhenome PhonemeB; + int PhonemeACoarseTuning; + int PhonemeBCoarseTuning; + VMorpherWaveform Waveform; +}; + +struct DedicatedProps { + enum TargetType : bool { Dialog, Lfe }; + TargetType Target; + float Gain; +}; + +struct ConvolutionProps { + std::array OrientAt; + std::array OrientUp; +}; + +using EffectProps = std::variant; + struct EffectTarget { MixParams *Main; RealMixParams *RealOut; }; -struct EffectState : public al::intrusive_ref { +struct SIMDALIGN EffectState : public al::intrusive_ref { al::span mOutTarget; @@ -188,8 +209,14 @@ struct EffectState : public al::intrusive_ref { struct EffectStateFactory { + EffectStateFactory() = default; + EffectStateFactory(const EffectStateFactory&) = delete; + EffectStateFactory(EffectStateFactory&&) = delete; virtual ~EffectStateFactory() = default; + void operator=(const EffectStateFactory&) = delete; + void operator=(EffectStateFactory&&) = delete; + virtual al::intrusive_ptr create() = 0; }; diff --git a/3rdparty/openal/core/effectslot.cpp b/3rdparty/openal/core/effectslot.cpp index db8aa078c223..d07c79a546a0 100644 --- a/3rdparty/openal/core/effectslot.cpp +++ b/3rdparty/openal/core/effectslot.cpp @@ -3,17 +3,13 @@ #include "effectslot.h" -#include +#include #include "almalloc.h" #include "context.h" -EffectSlotArray *EffectSlot::CreatePtrArray(size_t count) noexcept +std::unique_ptr EffectSlot::CreatePtrArray(size_t count) { - /* Allocate space for twice as many pointers, so the mixer has scratch - * space to store a sorted list during mixing. - */ - void *ptr{al_calloc(alignof(EffectSlotArray), EffectSlotArray::Sizeof(count*2))}; - return al::construct_at(static_cast(ptr), count); + return std::unique_ptr{new(FamCount{count}) EffectSlotArray(count)}; } diff --git a/3rdparty/openal/core/effectslot.h b/3rdparty/openal/core/effectslot.h index 2624ae5fd306..4825670a5d7c 100644 --- a/3rdparty/openal/core/effectslot.h +++ b/3rdparty/openal/core/effectslot.h @@ -2,10 +2,11 @@ #define CORE_EFFECTSLOT_H #include +#include -#include "almalloc.h" #include "device.h" #include "effects/base.h" +#include "flexarray.h" #include "intrusive_ptr.h" struct EffectSlot; @@ -18,20 +19,18 @@ enum class EffectSlotType : unsigned char { None, Reverb, Chorus, + Autowah, + Compressor, + Convolution, + Dedicated, Distortion, Echo, + Equalizer, Flanger, FrequencyShifter, - VocalMorpher, PitchShifter, RingModulator, - Autowah, - Compressor, - Equalizer, - EAXReverb, - DedicatedLFE, - DedicatedDialog, - Convolution + VocalMorpher, }; struct EffectSlotProps { @@ -44,9 +43,7 @@ struct EffectSlotProps { al::intrusive_ptr State; - std::atomic next; - - DEF_NEWDEL(EffectSlotProps) + std::atomic next{}; }; @@ -67,7 +64,7 @@ struct EffectSlot { EffectSlot *Target{nullptr}; EffectSlotType EffectType{EffectSlotType::None}; - EffectProps mEffectProps{}; + EffectProps mEffectProps; al::intrusive_ptr mEffectState; float RoomRolloff{0.0f}; /* Added to the source's room rolloff, not multiplied. */ @@ -81,9 +78,7 @@ struct EffectSlot { al::vector mWetBuffer; - static EffectSlotArray *CreatePtrArray(size_t count) noexcept; - - DEF_NEWDEL(EffectSlot) + static std::unique_ptr CreatePtrArray(size_t count); }; #endif /* CORE_EFFECTSLOT_H */ diff --git a/3rdparty/openal/core/except.cpp b/3rdparty/openal/core/except.cpp index 45fd4eb5f7a0..50c085e5573e 100644 --- a/3rdparty/openal/core/except.cpp +++ b/3rdparty/openal/core/except.cpp @@ -3,28 +3,9 @@ #include "except.h" -#include -#include - -#include "opthelpers.h" - namespace al { base_exception::~base_exception() = default; -void base_exception::setMessage(const char* msg, std::va_list args) -{ - std::va_list args2; - va_copy(args2, args); - int msglen{std::vsnprintf(nullptr, 0, msg, args)}; - if(msglen > 0) LIKELY - { - mMessage.resize(static_cast(msglen)+1); - std::vsnprintf(const_cast(mMessage.data()), mMessage.length(), msg, args2); - mMessage.pop_back(); - } - va_end(args2); -} - } // namespace al diff --git a/3rdparty/openal/core/except.h b/3rdparty/openal/core/except.h index 0e28e9dfede6..53e6a1c9f926 100644 --- a/3rdparty/openal/core/except.h +++ b/3rdparty/openal/core/except.h @@ -1,10 +1,9 @@ #ifndef CORE_EXCEPT_H #define CORE_EXCEPT_H -#include #include #include -#include +#include namespace al { @@ -12,20 +11,20 @@ namespace al { class base_exception : public std::exception { std::string mMessage; -protected: +public: base_exception() = default; - virtual ~base_exception(); + template,bool> = true> + explicit base_exception(T&& msg) : mMessage{std::forward(msg)} { } + base_exception(const base_exception&) = default; + base_exception(base_exception&&) = default; + ~base_exception() override; - void setMessage(const char *msg, std::va_list args); + auto operator=(const base_exception&) -> base_exception& = default; + auto operator=(base_exception&&) -> base_exception& = default; -public: - const char *what() const noexcept override { return mMessage.c_str(); } + [[nodiscard]] auto what() const noexcept -> const char* override { return mMessage.c_str(); } }; } // namespace al -#define START_API_FUNC try - -#define END_API_FUNC catch(...) { std::terminate(); } - #endif /* CORE_EXCEPT_H */ diff --git a/3rdparty/openal/core/filters/biquad.cpp b/3rdparty/openal/core/filters/biquad.cpp index a0a62eb8bde4..c1faf5e9fe05 100644 --- a/3rdparty/openal/core/filters/biquad.cpp +++ b/3rdparty/openal/core/filters/biquad.cpp @@ -3,6 +3,7 @@ #include "biquad.h" +#include #include #include #include @@ -27,8 +28,8 @@ void BiquadFilterR::setParams(BiquadType type, Real f0norm, Real gain, Rea const Real alpha{sin_w0/2.0f * rcpQ}; Real sqrtgain_alpha_2; - Real a[3]{ 1.0f, 0.0f, 0.0f }; - Real b[3]{ 1.0f, 0.0f, 0.0f }; + std::array a{{1.0f, 0.0f, 0.0f}}; + std::array b{{1.0f, 0.0f, 0.0f}}; /* Calculate filter coefficients depending on filter type */ switch(type) @@ -94,7 +95,7 @@ void BiquadFilterR::setParams(BiquadType type, Real f0norm, Real gain, Rea } template -void BiquadFilterR::process(const al::span src, Real *dst) +void BiquadFilterR::process(const al::span src, const al::span dst) { const Real b0{mB0}; const Real b1{mB1}; @@ -119,7 +120,7 @@ void BiquadFilterR::process(const al::span src, Real *dst) z2 = input*b2 - output*a2; return output; }; - std::transform(src.cbegin(), src.cend(), dst, proc_sample); + std::transform(src.cbegin(), src.cend(), dst.begin(), proc_sample); mZ1 = z1; mZ2 = z2; @@ -127,7 +128,7 @@ void BiquadFilterR::process(const al::span src, Real *dst) template void BiquadFilterR::dualProcess(BiquadFilterR &other, const al::span src, - Real *dst) + const al::span dst) { const Real b00{mB0}; const Real b01{mB1}; @@ -156,7 +157,7 @@ void BiquadFilterR::dualProcess(BiquadFilterR &other, const al::span src, Real *dst); + void process(const al::span src, const al::span dst); /** Processes this filter and the other at the same time. */ - void dualProcess(BiquadFilterR &other, const al::span src, Real *dst); + void dualProcess(BiquadFilterR &other, const al::span src, + const al::span dst); /* Rather hacky. It's just here to support "manual" processing. */ - std::pair getComponents() const noexcept { return {mZ1, mZ2}; } + [[nodiscard]] auto getComponents() const noexcept -> std::array { return {{mZ1,mZ2}}; } void setComponents(Real z1, Real z2) noexcept { mZ1 = z1; mZ2 = z2; } - Real processOne(const Real in, Real &z1, Real &z2) const noexcept + [[nodiscard]] auto processOne(const Real in, Real &z1, Real &z2) const noexcept -> Real { const Real out{in*mB0 + z1}; z1 = in*mB1 - out*mA1 + z2; @@ -134,7 +135,7 @@ template struct DualBiquadR { BiquadFilterR &f0, &f1; - void process(const al::span src, Real *dst) + void process(const al::span src, const al::span dst) { f0.dualProcess(f1, src, dst); } }; diff --git a/3rdparty/openal/core/filters/nfc.cpp b/3rdparty/openal/core/filters/nfc.cpp index aa64c6130728..fe65098973a3 100644 --- a/3rdparty/openal/core/filters/nfc.cpp +++ b/3rdparty/openal/core/filters/nfc.cpp @@ -5,8 +5,6 @@ #include -#include "opthelpers.h" - /* Near-field control filters are the basis for handling the near-field effect. * The near-field effect is a bass-boost present in the directional components @@ -48,31 +46,26 @@ namespace { -constexpr float B[5][4] = { - { 0.0f }, - { 1.0f }, - { 3.0f, 3.0f }, - { 3.6778f, 6.4595f, 2.3222f }, - { 4.2076f, 11.4877f, 5.7924f, 9.1401f } -}; +constexpr auto B1 = std::array{ 1.0f}; +constexpr auto B2 = std::array{ 3.0f, 3.0f}; +constexpr auto B3 = std::array{3.6778f, 6.4595f, 2.3222f}; +constexpr auto B4 = std::array{4.2076f, 11.4877f, 5.7924f, 9.1401f}; NfcFilter1 NfcFilterCreate1(const float w0, const float w1) noexcept { - NfcFilter1 nfc{}; - float b_00, g_0; - float r; + auto nfc = NfcFilter1{}; /* Calculate bass-cut coefficients. */ - r = 0.5f * w1; - b_00 = B[1][0] * r; - g_0 = 1.0f + b_00; + auto r = 0.5f * w1; + auto b_00 = B1[0] * r; + auto g_0 = 1.0f + b_00; nfc.base_gain = 1.0f / g_0; nfc.a1 = 2.0f * b_00 / g_0; /* Calculate bass-boost coefficients. */ r = 0.5f * w0; - b_00 = B[1][0] * r; + b_00 = B1[0] * r; g_0 = 1.0f + b_00; nfc.gain = nfc.base_gain * g_0; @@ -83,9 +76,9 @@ NfcFilter1 NfcFilterCreate1(const float w0, const float w1) noexcept void NfcFilterAdjust1(NfcFilter1 *nfc, const float w0) noexcept { - const float r{0.5f * w0}; - const float b_00{B[1][0] * r}; - const float g_0{1.0f + b_00}; + const auto r = 0.5f * w0; + const auto b_00 = B1[0] * r; + const auto g_0 = 1.0f + b_00; nfc->gain = nfc->base_gain * g_0; nfc->b1 = 2.0f * b_00 / g_0; @@ -94,15 +87,13 @@ void NfcFilterAdjust1(NfcFilter1 *nfc, const float w0) noexcept NfcFilter2 NfcFilterCreate2(const float w0, const float w1) noexcept { - NfcFilter2 nfc{}; - float b_10, b_11, g_1; - float r; + auto nfc = NfcFilter2{}; /* Calculate bass-cut coefficients. */ - r = 0.5f * w1; - b_10 = B[2][0] * r; - b_11 = B[2][1] * r * r; - g_1 = 1.0f + b_10 + b_11; + auto r = 0.5f * w1; + auto b_10 = B2[0] * r; + auto b_11 = B2[1] * (r*r); + auto g_1 = 1.0f + b_10 + b_11; nfc.base_gain = 1.0f / g_1; nfc.a1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -110,8 +101,8 @@ NfcFilter2 NfcFilterCreate2(const float w0, const float w1) noexcept /* Calculate bass-boost coefficients. */ r = 0.5f * w0; - b_10 = B[2][0] * r; - b_11 = B[2][1] * r * r; + b_10 = B2[0] * r; + b_11 = B2[1] * r * r; g_1 = 1.0f + b_10 + b_11; nfc.gain = nfc.base_gain * g_1; @@ -123,10 +114,10 @@ NfcFilter2 NfcFilterCreate2(const float w0, const float w1) noexcept void NfcFilterAdjust2(NfcFilter2 *nfc, const float w0) noexcept { - const float r{0.5f * w0}; - const float b_10{B[2][0] * r}; - const float b_11{B[2][1] * r * r}; - const float g_1{1.0f + b_10 + b_11}; + const auto r = 0.5f * w0; + const auto b_10 = B2[0] * r; + const auto b_11 = B2[1] * (r*r); + const auto g_1 = 1.0f + b_10 + b_11; nfc->gain = nfc->base_gain * g_1; nfc->b1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -136,18 +127,15 @@ void NfcFilterAdjust2(NfcFilter2 *nfc, const float w0) noexcept NfcFilter3 NfcFilterCreate3(const float w0, const float w1) noexcept { - NfcFilter3 nfc{}; - float b_10, b_11, g_1; - float b_00, g_0; - float r; + auto nfc = NfcFilter3{}; /* Calculate bass-cut coefficients. */ - r = 0.5f * w1; - b_10 = B[3][0] * r; - b_11 = B[3][1] * r * r; - b_00 = B[3][2] * r; - g_1 = 1.0f + b_10 + b_11; - g_0 = 1.0f + b_00; + auto r = 0.5f * w1; + auto b_10 = B3[0] * r; + auto b_11 = B3[1] * (r*r); + auto b_00 = B3[2] * r; + auto g_1 = 1.0f + b_10 + b_11; + auto g_0 = 1.0f + b_00; nfc.base_gain = 1.0f / (g_1 * g_0); nfc.a1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -156,9 +144,9 @@ NfcFilter3 NfcFilterCreate3(const float w0, const float w1) noexcept /* Calculate bass-boost coefficients. */ r = 0.5f * w0; - b_10 = B[3][0] * r; - b_11 = B[3][1] * r * r; - b_00 = B[3][2] * r; + b_10 = B3[0] * r; + b_11 = B3[1] * (r*r); + b_00 = B3[2] * r; g_1 = 1.0f + b_10 + b_11; g_0 = 1.0f + b_00; @@ -172,12 +160,12 @@ NfcFilter3 NfcFilterCreate3(const float w0, const float w1) noexcept void NfcFilterAdjust3(NfcFilter3 *nfc, const float w0) noexcept { - const float r{0.5f * w0}; - const float b_10{B[3][0] * r}; - const float b_11{B[3][1] * r * r}; - const float b_00{B[3][2] * r}; - const float g_1{1.0f + b_10 + b_11}; - const float g_0{1.0f + b_00}; + const auto r = 0.5f * w0; + const auto b_10 = B3[0] * r; + const auto b_11 = B3[1] * (r*r); + const auto b_00 = B3[2] * r; + const auto g_1 = 1.0f + b_10 + b_11; + const auto g_0 = 1.0f + b_00; nfc->gain = nfc->base_gain * (g_1 * g_0); nfc->b1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -188,19 +176,16 @@ void NfcFilterAdjust3(NfcFilter3 *nfc, const float w0) noexcept NfcFilter4 NfcFilterCreate4(const float w0, const float w1) noexcept { - NfcFilter4 nfc{}; - float b_10, b_11, g_1; - float b_00, b_01, g_0; - float r; + auto nfc = NfcFilter4{}; /* Calculate bass-cut coefficients. */ - r = 0.5f * w1; - b_10 = B[4][0] * r; - b_11 = B[4][1] * r * r; - b_00 = B[4][2] * r; - b_01 = B[4][3] * r * r; - g_1 = 1.0f + b_10 + b_11; - g_0 = 1.0f + b_00 + b_01; + auto r = 0.5f * w1; + auto b_10 = B4[0] * r; + auto b_11 = B4[1] * (r*r); + auto b_00 = B4[2] * r; + auto b_01 = B4[3] * (r*r); + auto g_1 = 1.0f + b_10 + b_11; + auto g_0 = 1.0f + b_00 + b_01; nfc.base_gain = 1.0f / (g_1 * g_0); nfc.a1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -210,10 +195,10 @@ NfcFilter4 NfcFilterCreate4(const float w0, const float w1) noexcept /* Calculate bass-boost coefficients. */ r = 0.5f * w0; - b_10 = B[4][0] * r; - b_11 = B[4][1] * r * r; - b_00 = B[4][2] * r; - b_01 = B[4][3] * r * r; + b_10 = B4[0] * r; + b_11 = B4[1] * (r*r); + b_00 = B4[2] * r; + b_01 = B4[3] * (r*r); g_1 = 1.0f + b_10 + b_11; g_0 = 1.0f + b_00 + b_01; @@ -228,13 +213,13 @@ NfcFilter4 NfcFilterCreate4(const float w0, const float w1) noexcept void NfcFilterAdjust4(NfcFilter4 *nfc, const float w0) noexcept { - const float r{0.5f * w0}; - const float b_10{B[4][0] * r}; - const float b_11{B[4][1] * r * r}; - const float b_00{B[4][2] * r}; - const float b_01{B[4][3] * r * r}; - const float g_1{1.0f + b_10 + b_11}; - const float g_0{1.0f + b_00 + b_01}; + const auto r = 0.5f * w0; + const auto b_10 = B4[0] * r; + const auto b_11 = B4[1] * (r*r); + const auto b_00 = B4[2] * r; + const auto b_01 = B4[3] * (r*r); + const auto g_1 = 1.0f + b_10 + b_11; + const auto g_0 = 1.0f + b_00 + b_01; nfc->gain = nfc->base_gain * (g_1 * g_0); nfc->b1 = (2.0f*b_10 + 4.0f*b_11) / g_1; @@ -262,7 +247,7 @@ void NfcFilter::adjust(const float w0) noexcept } -void NfcFilter::process1(const al::span src, float *RESTRICT dst) +void NfcFilter::process1(const al::span src, const al::span dst) { const float gain{first.gain}; const float b1{first.b1}; @@ -275,11 +260,11 @@ void NfcFilter::process1(const al::span src, float *RESTRICT dst) z1 += y; return out; }; - std::transform(src.cbegin(), src.cend(), dst, proc_sample); + std::transform(src.cbegin(), src.cend(), dst.begin(), proc_sample); first.z[0] = z1; } -void NfcFilter::process2(const al::span src, float *RESTRICT dst) +void NfcFilter::process2(const al::span src, const al::span dst) { const float gain{second.gain}; const float b1{second.b1}; @@ -296,12 +281,12 @@ void NfcFilter::process2(const al::span src, float *RESTRICT dst) z1 += y; return out; }; - std::transform(src.cbegin(), src.cend(), dst, proc_sample); + std::transform(src.cbegin(), src.cend(), dst.begin(), proc_sample); second.z[0] = z1; second.z[1] = z2; } -void NfcFilter::process3(const al::span src, float *RESTRICT dst) +void NfcFilter::process3(const al::span src, const al::span dst) { const float gain{third.gain}; const float b1{third.b1}; @@ -325,13 +310,13 @@ void NfcFilter::process3(const al::span src, float *RESTRICT dst) z3 += y; return out; }; - std::transform(src.cbegin(), src.cend(), dst, proc_sample); + std::transform(src.cbegin(), src.cend(), dst.begin(), proc_sample); third.z[0] = z1; third.z[1] = z2; third.z[2] = z3; } -void NfcFilter::process4(const al::span src, float *RESTRICT dst) +void NfcFilter::process4(const al::span src, const al::span dst) { const float gain{fourth.gain}; const float b1{fourth.b1}; @@ -359,7 +344,7 @@ void NfcFilter::process4(const al::span src, float *RESTRICT dst) z3 += y; return out; }; - std::transform(src.cbegin(), src.cend(), dst, proc_sample); + std::transform(src.cbegin(), src.cend(), dst.begin(), proc_sample); fourth.z[0] = z1; fourth.z[1] = z2; fourth.z[2] = z3; diff --git a/3rdparty/openal/core/filters/nfc.h b/3rdparty/openal/core/filters/nfc.h index 4b8e68b5dc0f..00ab4dd76540 100644 --- a/3rdparty/openal/core/filters/nfc.h +++ b/3rdparty/openal/core/filters/nfc.h @@ -1,30 +1,31 @@ #ifndef CORE_FILTERS_NFC_H #define CORE_FILTERS_NFC_H +#include #include #include "alspan.h" struct NfcFilter1 { - float base_gain, gain; - float b1, a1; - float z[1]; + float base_gain{1.0f}, gain{1.0f}; + float b1{}, a1{}; + std::array z{}; }; struct NfcFilter2 { - float base_gain, gain; - float b1, b2, a1, a2; - float z[2]; + float base_gain{1.0f}, gain{1.0f}; + float b1{}, b2{}, a1{}, a2{}; + std::array z{}; }; struct NfcFilter3 { - float base_gain, gain; - float b1, b2, b3, a1, a2, a3; - float z[3]; + float base_gain{1.0f}, gain{1.0f}; + float b1{}, b2{}, b3{}, a1{}, a2{}, a3{}; + std::array z{}; }; struct NfcFilter4 { - float base_gain, gain; - float b1, b2, b3, b4, a1, a2, a3, a4; - float z[4]; + float base_gain{1.0f}, gain{1.0f}; + float b1{}, b2{}, b3{}, b4{}, a1{}, a2{}, a3{}, a4{}; + std::array z{}; }; class NfcFilter { @@ -48,16 +49,16 @@ class NfcFilter { void adjust(const float w0) noexcept; /* Near-field control filter for first-order ambisonic channels (1-3). */ - void process1(const al::span src, float *RESTRICT dst); + void process1(const al::span src, const al::span dst); /* Near-field control filter for second-order ambisonic channels (4-8). */ - void process2(const al::span src, float *RESTRICT dst); + void process2(const al::span src, const al::span dst); /* Near-field control filter for third-order ambisonic channels (9-15). */ - void process3(const al::span src, float *RESTRICT dst); + void process3(const al::span src, const al::span dst); /* Near-field control filter for fourth-order ambisonic channels (16-24). */ - void process4(const al::span src, float *RESTRICT dst); + void process4(const al::span src, const al::span dst); }; #endif /* CORE_FILTERS_NFC_H */ diff --git a/3rdparty/openal/core/filters/splitter.cpp b/3rdparty/openal/core/filters/splitter.cpp index 983ba36f15dd..fbb6b2b7ef00 100644 --- a/3rdparty/openal/core/filters/splitter.cpp +++ b/3rdparty/openal/core/filters/splitter.cpp @@ -4,6 +4,7 @@ #include "splitter.h" #include +#include #include #include @@ -27,14 +28,17 @@ void BandSplitterR::init(Real f0norm) } template -void BandSplitterR::process(const al::span input, Real *hpout, Real *lpout) +void BandSplitterR::process(const al::span input, const al::span hpout, + const al::span lpout) { const Real ap_coeff{mCoeff}; const Real lp_coeff{mCoeff*0.5f + 0.5f}; Real lp_z1{mLpZ1}; Real lp_z2{mLpZ2}; Real ap_z1{mApZ1}; - auto proc_sample = [ap_coeff,lp_coeff,&lp_z1,&lp_z2,&ap_z1,&lpout](const Real in) noexcept -> Real + assert(lpout.size() <= input.size()); + auto lpiter = lpout.begin(); + auto proc_sample = [ap_coeff,lp_coeff,&lp_z1,&lp_z2,&ap_z1,&lpiter](const Real in) noexcept -> Real { /* Low-pass sample processing. */ Real d{(in - lp_z1) * lp_coeff}; @@ -45,7 +49,7 @@ void BandSplitterR::process(const al::span input, Real *hpout, lp_y = lp_z2 + d; lp_z2 = lp_y + d; - *(lpout++) = lp_y; + *(lpiter++) = lp_y; /* All-pass sample processing. */ Real ap_y{in*ap_coeff + ap_z1}; @@ -54,15 +58,15 @@ void BandSplitterR::process(const al::span input, Real *hpout, /* High-pass generated from removing low-passed output. */ return ap_y - lp_y; }; - std::transform(input.cbegin(), input.cend(), hpout, proc_sample); + std::transform(input.cbegin(), input.cend(), hpout.begin(), proc_sample); mLpZ1 = lp_z1; mLpZ2 = lp_z2; mApZ1 = ap_z1; } template -void BandSplitterR::processHfScale(const al::span input, Real *RESTRICT output, - const Real hfscale) +void BandSplitterR::processHfScale(const al::span input, + const al::span output, const Real hfscale) { const Real ap_coeff{mCoeff}; const Real lp_coeff{mCoeff*0.5f + 0.5f}; @@ -89,7 +93,7 @@ void BandSplitterR::processHfScale(const al::span input, Real */ return (ap_y-lp_y)*hfscale + lp_y; }; - std::transform(input.begin(), input.end(), output, proc_sample); + std::transform(input.cbegin(), input.cend(), output.begin(), proc_sample); mLpZ1 = lp_z1; mLpZ2 = lp_z2; mApZ1 = ap_z1; diff --git a/3rdparty/openal/core/filters/splitter.h b/3rdparty/openal/core/filters/splitter.h index e853eb385b8d..fdbf07f7459d 100644 --- a/3rdparty/openal/core/filters/splitter.h +++ b/3rdparty/openal/core/filters/splitter.h @@ -17,14 +17,16 @@ class BandSplitterR { public: BandSplitterR() = default; BandSplitterR(const BandSplitterR&) = default; - BandSplitterR(Real f0norm) { init(f0norm); } + explicit BandSplitterR(Real f0norm) { init(f0norm); } BandSplitterR& operator=(const BandSplitterR&) = default; void init(Real f0norm); void clear() noexcept { mLpZ1 = mLpZ2 = mApZ1 = 0.0f; } - void process(const al::span input, Real *hpout, Real *lpout); + void process(const al::span input, const al::span hpout, + const al::span lpout); - void processHfScale(const al::span input, Real *output, const Real hfscale); + void processHfScale(const al::span input, const al::span output, + const Real hfscale); void processHfScale(const al::span samples, const Real hfscale); void processScale(const al::span samples, const Real hfscale, const Real lfscale); diff --git a/3rdparty/openal/core/fmt_traits.cpp b/3rdparty/openal/core/fmt_traits.cpp deleted file mode 100644 index 054d87669f0f..000000000000 --- a/3rdparty/openal/core/fmt_traits.cpp +++ /dev/null @@ -1,79 +0,0 @@ - -#include "config.h" - -#include "fmt_traits.h" - - -namespace al { - -const int16_t muLawDecompressionTable[256] = { - -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, - -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, - -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, - -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316, - -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, - -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, - -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, - -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, - -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, - -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, - -876, -844, -812, -780, -748, -716, -684, -652, - -620, -588, -556, -524, -492, -460, -428, -396, - -372, -356, -340, -324, -308, -292, -276, -260, - -244, -228, -212, -196, -180, -164, -148, -132, - -120, -112, -104, -96, -88, -80, -72, -64, - -56, -48, -40, -32, -24, -16, -8, 0, - 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, - 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, - 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, - 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, - 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, - 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, - 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, - 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, - 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, - 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, - 876, 844, 812, 780, 748, 716, 684, 652, - 620, 588, 556, 524, 492, 460, 428, 396, - 372, 356, 340, 324, 308, 292, 276, 260, - 244, 228, 212, 196, 180, 164, 148, 132, - 120, 112, 104, 96, 88, 80, 72, 64, - 56, 48, 40, 32, 24, 16, 8, 0 -}; - -const int16_t aLawDecompressionTable[256] = { - -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, - -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, - -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, - -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, - -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, - -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, - -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, - -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, - -344, -328, -376, -360, -280, -264, -312, -296, - -472, -456, -504, -488, -408, -392, -440, -424, - -88, -72, -120, -104, -24, -8, -56, -40, - -216, -200, -248, -232, -152, -136, -184, -168, - -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, - -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, - -688, -656, -752, -720, -560, -528, -624, -592, - -944, -912, -1008, -976, -816, -784, -880, -848, - 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, - 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, - 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, - 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, - 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, - 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, - 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, - 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, - 344, 328, 376, 360, 280, 264, 312, 296, - 472, 456, 504, 488, 408, 392, 440, 424, - 88, 72, 120, 104, 24, 8, 56, 40, - 216, 200, 248, 232, 152, 136, 184, 168, - 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, - 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, - 688, 656, 752, 720, 560, 528, 624, 592, - 944, 912, 1008, 976, 816, 784, 880, 848 -}; - -} // namespace al diff --git a/3rdparty/openal/core/fmt_traits.h b/3rdparty/openal/core/fmt_traits.h index 1879c81b1187..b16f4a3d13e4 100644 --- a/3rdparty/openal/core/fmt_traits.h +++ b/3rdparty/openal/core/fmt_traits.h @@ -1,16 +1,83 @@ #ifndef CORE_FMT_TRAITS_H #define CORE_FMT_TRAITS_H -#include -#include +#include +#include -#include "buffer_storage.h" +#include "storage_formats.h" namespace al { -extern const int16_t muLawDecompressionTable[256]; -extern const int16_t aLawDecompressionTable[256]; +inline constexpr auto muLawDecompressionTable = std::array{{ + -32124,-31100,-30076,-29052,-28028,-27004,-25980,-24956, + -23932,-22908,-21884,-20860,-19836,-18812,-17788,-16764, + -15996,-15484,-14972,-14460,-13948,-13436,-12924,-12412, + -11900,-11388,-10876,-10364, -9852, -9340, -8828, -8316, + -7932, -7676, -7420, -7164, -6908, -6652, -6396, -6140, + -5884, -5628, -5372, -5116, -4860, -4604, -4348, -4092, + -3900, -3772, -3644, -3516, -3388, -3260, -3132, -3004, + -2876, -2748, -2620, -2492, -2364, -2236, -2108, -1980, + -1884, -1820, -1756, -1692, -1628, -1564, -1500, -1436, + -1372, -1308, -1244, -1180, -1116, -1052, -988, -924, + -876, -844, -812, -780, -748, -716, -684, -652, + -620, -588, -556, -524, -492, -460, -428, -396, + -372, -356, -340, -324, -308, -292, -276, -260, + -244, -228, -212, -196, -180, -164, -148, -132, + -120, -112, -104, -96, -88, -80, -72, -64, + -56, -48, -40, -32, -24, -16, -8, 0, + 32124, 31100, 30076, 29052, 28028, 27004, 25980, 24956, + 23932, 22908, 21884, 20860, 19836, 18812, 17788, 16764, + 15996, 15484, 14972, 14460, 13948, 13436, 12924, 12412, + 11900, 11388, 10876, 10364, 9852, 9340, 8828, 8316, + 7932, 7676, 7420, 7164, 6908, 6652, 6396, 6140, + 5884, 5628, 5372, 5116, 4860, 4604, 4348, 4092, + 3900, 3772, 3644, 3516, 3388, 3260, 3132, 3004, + 2876, 2748, 2620, 2492, 2364, 2236, 2108, 1980, + 1884, 1820, 1756, 1692, 1628, 1564, 1500, 1436, + 1372, 1308, 1244, 1180, 1116, 1052, 988, 924, + 876, 844, 812, 780, 748, 716, 684, 652, + 620, 588, 556, 524, 492, 460, 428, 396, + 372, 356, 340, 324, 308, 292, 276, 260, + 244, 228, 212, 196, 180, 164, 148, 132, + 120, 112, 104, 96, 88, 80, 72, 64, + 56, 48, 40, 32, 24, 16, 8, 0 +}}; + +inline constexpr auto aLawDecompressionTable = std::array{{ + -5504, -5248, -6016, -5760, -4480, -4224, -4992, -4736, + -7552, -7296, -8064, -7808, -6528, -6272, -7040, -6784, + -2752, -2624, -3008, -2880, -2240, -2112, -2496, -2368, + -3776, -3648, -4032, -3904, -3264, -3136, -3520, -3392, + -22016,-20992,-24064,-23040,-17920,-16896,-19968,-18944, + -30208,-29184,-32256,-31232,-26112,-25088,-28160,-27136, + -11008,-10496,-12032,-11520, -8960, -8448, -9984, -9472, + -15104,-14592,-16128,-15616,-13056,-12544,-14080,-13568, + -344, -328, -376, -360, -280, -264, -312, -296, + -472, -456, -504, -488, -408, -392, -440, -424, + -88, -72, -120, -104, -24, -8, -56, -40, + -216, -200, -248, -232, -152, -136, -184, -168, + -1376, -1312, -1504, -1440, -1120, -1056, -1248, -1184, + -1888, -1824, -2016, -1952, -1632, -1568, -1760, -1696, + -688, -656, -752, -720, -560, -528, -624, -592, + -944, -912, -1008, -976, -816, -784, -880, -848, + 5504, 5248, 6016, 5760, 4480, 4224, 4992, 4736, + 7552, 7296, 8064, 7808, 6528, 6272, 7040, 6784, + 2752, 2624, 3008, 2880, 2240, 2112, 2496, 2368, + 3776, 3648, 4032, 3904, 3264, 3136, 3520, 3392, + 22016, 20992, 24064, 23040, 17920, 16896, 19968, 18944, + 30208, 29184, 32256, 31232, 26112, 25088, 28160, 27136, + 11008, 10496, 12032, 11520, 8960, 8448, 9984, 9472, + 15104, 14592, 16128, 15616, 13056, 12544, 14080, 13568, + 344, 328, 376, 360, 280, 264, 312, 296, + 472, 456, 504, 488, 408, 392, 440, 424, + 88, 72, 120, 104, 24, 8, 56, 40, + 216, 200, 248, 232, 152, 136, 184, 168, + 1376, 1312, 1504, 1440, 1120, 1056, 1248, 1184, + 1888, 1824, 2016, 1952, 1632, 1568, 1760, 1696, + 688, 656, 752, 720, 560, 528, 624, 592, + 944, 912, 1008, 976, 816, 784, 880, 848 +}}; template @@ -18,62 +85,52 @@ struct FmtTypeTraits { }; template<> struct FmtTypeTraits { - using Type = uint8_t; + using Type = std::uint8_t; - template - static constexpr OutT to(const Type val) noexcept { return val*OutT{1.0/128.0} - OutT{1.0}; } + constexpr float operator()(const Type val) const noexcept + { return float(val)*(1.0f/128.0f) - 1.0f; } }; template<> struct FmtTypeTraits { - using Type = int16_t; + using Type = std::int16_t; - template - static constexpr OutT to(const Type val) noexcept { return val*OutT{1.0/32768.0}; } + constexpr float operator()(const Type val) const noexcept + { return float(val) * (1.0f/32768.0f); } +}; +template<> +struct FmtTypeTraits { + using Type = std::int32_t; + + constexpr float operator()(const Type val) const noexcept + { return static_cast(val)*(1.0f/2147483648.0f); } }; template<> struct FmtTypeTraits { using Type = float; - template - static constexpr OutT to(const Type val) noexcept { return val; } + constexpr float operator()(const Type val) const noexcept { return val; } }; template<> struct FmtTypeTraits { using Type = double; - template - static constexpr OutT to(const Type val) noexcept { return static_cast(val); } + constexpr float operator()(const Type val) const noexcept { return static_cast(val); } }; template<> struct FmtTypeTraits { - using Type = uint8_t; + using Type = std::uint8_t; - template - static constexpr OutT to(const Type val) noexcept - { return muLawDecompressionTable[val] * OutT{1.0/32768.0}; } + constexpr float operator()(const Type val) const noexcept + { return float(muLawDecompressionTable[val]) * (1.0f/32768.0f); } }; template<> struct FmtTypeTraits { - using Type = uint8_t; + using Type = std::uint8_t; - template - static constexpr OutT to(const Type val) noexcept - { return aLawDecompressionTable[val] * OutT{1.0/32768.0}; } + constexpr float operator()(const Type val) const noexcept + { return float(aLawDecompressionTable[val]) * (1.0f/32768.0f); } }; - -template -inline void LoadSampleArray(DstT *RESTRICT dst, const std::byte *src, const std::size_t srcstep, - const std::size_t samples) noexcept -{ - using TypeTraits = FmtTypeTraits; - using SampleType = typename TypeTraits::Type; - - const SampleType *RESTRICT ssrc{reinterpret_cast(src)}; - for(size_t i{0u};i < samples;i++) - dst[i] = TypeTraits::template to(ssrc[i*srcstep]); -} - } // namespace al #endif /* CORE_FMT_TRAITS_H */ diff --git a/3rdparty/openal/core/fpu_ctrl.cpp b/3rdparty/openal/core/fpu_ctrl.cpp index 0cf0d6e72d10..7a4f147fa30d 100644 --- a/3rdparty/openal/core/fpu_ctrl.cpp +++ b/3rdparty/openal/core/fpu_ctrl.cpp @@ -1,61 +1,90 @@ #include "config.h" +#include "config_simd.h" #include "fpu_ctrl.h" #ifdef HAVE_INTRIN_H #include #endif -#ifdef HAVE_SSE_INTRINSICS +#if HAVE_SSE_INTRINSICS #include -#ifndef _MM_DENORMALS_ZERO_MASK +#elif HAVE_SSE +#include +#endif + +#if HAVE_SSE && !defined(_MM_DENORMALS_ZERO_MASK) /* Some headers seem to be missing these? */ #define _MM_DENORMALS_ZERO_MASK 0x0040u #define _MM_DENORMALS_ZERO_ON 0x0040u #endif -#endif +#if !HAVE_SSE_INTRINSICS && HAVE_SSE #include "cpu_caps.h" +#endif +namespace { -void FPUCtl::enter() noexcept +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +[[gnu::target("sse")]] +#endif +[[maybe_unused]] +void disable_denormals(unsigned int *state [[maybe_unused]]) { - if(this->in_mode) return; - -#if defined(HAVE_SSE_INTRINSICS) - this->sse_state = _mm_getcsr(); - unsigned int sseState{this->sse_state}; +#if HAVE_SSE_INTRINSICS + *state = _mm_getcsr(); + unsigned int sseState{*state}; sseState &= ~(_MM_FLUSH_ZERO_MASK | _MM_DENORMALS_ZERO_MASK); sseState |= _MM_FLUSH_ZERO_ON | _MM_DENORMALS_ZERO_ON; _mm_setcsr(sseState); -#elif defined(__GNUC__) && defined(HAVE_SSE) +#elif HAVE_SSE - if((CPUCapFlags&CPU_CAP_SSE)) + *state = _mm_getcsr(); + unsigned int sseState{*state}; + sseState &= ~_MM_FLUSH_ZERO_MASK; + sseState |= _MM_FLUSH_ZERO_ON; + if((CPUCapFlags&CPU_CAP_SSE2)) { - __asm__ __volatile__("stmxcsr %0" : "=m" (*&this->sse_state)); - unsigned int sseState{this->sse_state}; - sseState |= 0x8000; /* set flush-to-zero */ - if((CPUCapFlags&CPU_CAP_SSE2)) - sseState |= 0x0040; /* set denormals-are-zero */ - __asm__ __volatile__("ldmxcsr %0" : : "m" (*&sseState)); + sseState &= ~_MM_DENORMALS_ZERO_MASK; + sseState |= _MM_DENORMALS_ZERO_ON; } + _mm_setcsr(sseState); #endif - - this->in_mode = true; } -void FPUCtl::leave() noexcept +#if defined(__GNUC__) && (defined(__i386__) || defined(__x86_64__)) +[[gnu::target("sse")]] +#endif +[[maybe_unused]] +void reset_fpu(unsigned int state [[maybe_unused]]) { - if(!this->in_mode) return; +#if HAVE_SSE_INTRINSICS || HAVE_SSE + _mm_setcsr(state); +#endif +} -#if defined(HAVE_SSE_INTRINSICS) - _mm_setcsr(this->sse_state); +} // namespace -#elif defined(__GNUC__) && defined(HAVE_SSE) +unsigned int FPUCtl::Set() noexcept +{ + unsigned int state{}; +#if HAVE_SSE_INTRINSICS + disable_denormals(&state); +#elif HAVE_SSE + if((CPUCapFlags&CPU_CAP_SSE)) + disable_denormals(&state); +#endif + return state; +} + +void FPUCtl::Reset(unsigned int state [[maybe_unused]]) noexcept +{ +#if HAVE_SSE_INTRINSICS + reset_fpu(state); +#elif HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) - __asm__ __volatile__("ldmxcsr %0" : : "m" (*&this->sse_state)); + reset_fpu(state); #endif - this->in_mode = false; } diff --git a/3rdparty/openal/core/fpu_ctrl.h b/3rdparty/openal/core/fpu_ctrl.h index 9554313ae047..d4f75ec3146c 100644 --- a/3rdparty/openal/core/fpu_ctrl.h +++ b/3rdparty/openal/core/fpu_ctrl.h @@ -2,20 +2,31 @@ #define CORE_FPU_CTRL_H class FPUCtl { -#if defined(HAVE_SSE_INTRINSICS) || (defined(__GNUC__) && defined(HAVE_SSE)) unsigned int sse_state{}; -#endif bool in_mode{}; + static unsigned int Set() noexcept; + static void Reset(unsigned int state) noexcept; + public: - FPUCtl() noexcept { enter(); in_mode = true; } - ~FPUCtl() { if(in_mode) leave(); } + FPUCtl() noexcept : sse_state{Set()}, in_mode{true} { } + ~FPUCtl() { if(in_mode) Reset(sse_state); } FPUCtl(const FPUCtl&) = delete; FPUCtl& operator=(const FPUCtl&) = delete; - void enter() noexcept; - void leave() noexcept; + void enter() noexcept + { + if(!in_mode) + sse_state = Set(); + in_mode = true; + } + void leave() noexcept + { + if(in_mode) + Reset(sse_state); + in_mode = false; + } }; #endif /* CORE_FPU_CTRL_H */ diff --git a/3rdparty/openal/core/front_stablizer.h b/3rdparty/openal/core/front_stablizer.h index 6825111a7c6a..62652699da9c 100644 --- a/3rdparty/openal/core/front_stablizer.h +++ b/3rdparty/openal/core/front_stablizer.h @@ -7,10 +7,11 @@ #include "almalloc.h" #include "bufferline.h" #include "filters/splitter.h" +#include "flexarray.h" struct FrontStablizer { - FrontStablizer(size_t numchans) : ChannelFilters{numchans} { } + explicit FrontStablizer(size_t numchans) : ChannelFilters{numchans} { } alignas(16) std::array MidDirect{}; alignas(16) std::array Side{}; diff --git a/3rdparty/openal/core/helpers.cpp b/3rdparty/openal/core/helpers.cpp index b353da2e1012..96fca1065e4b 100644 --- a/3rdparty/openal/core/helpers.cpp +++ b/3rdparty/openal/core/helpers.cpp @@ -15,20 +15,59 @@ #include #include #include +#include +#include +#include "almalloc.h" #include "alnumeric.h" #include "alspan.h" #include "alstring.h" +#include "filesystem.h" #include "logging.h" #include "strutils.h" -/* Mixing thread priority level */ -int RTPrioLevel{1}; +namespace { + +using namespace std::string_view_literals; + +std::mutex gSearchLock; -/* Allow reducing the process's RTTime limit for RTKit. */ -bool AllowRTTimeLimit{true}; +void DirectorySearch(const fs::path &path, const std::string_view ext, + std::vector *const results) +{ + const auto base = results->size(); + try { + auto fpath = path.lexically_normal(); + if(!fs::exists(fpath)) + return; + + TRACE("Searching {} for *{}", al::u8_as_char(fpath.u8string()), ext); + for(auto&& dirent : fs::directory_iterator{fpath}) + { + auto&& entrypath = dirent.path(); + if(!entrypath.has_extension()) + continue; + + if(fs::status(entrypath).type() != fs::file_type::regular) + continue; + const auto u8ext = entrypath.extension().u8string(); + if(al::case_compare(al::u8_as_char(u8ext), ext) == 0) + results->emplace_back(al::u8_as_char(entrypath.u8string())); + } + } + catch(std::exception& e) { + ERR("Exception enumerating files: {}", e.what()); + } + + const auto newlist = al::span{*results}.subspan(base); + std::sort(newlist.begin(), newlist.end()); + for(const auto &name : newlist) + TRACE(" got {}", name); +} + +} // namespace #ifdef _WIN32 @@ -37,153 +76,126 @@ bool AllowRTTimeLimit{true}; const PathNamePair &GetProcBinary() { - static std::optional procbin; - if(procbin) return *procbin; -#if !defined(ALSOFT_UWP) - auto fullpath = std::vector(256); - DWORD len{GetModuleFileNameW(nullptr, fullpath.data(), static_cast(fullpath.size()))}; - while(len == fullpath.size()) + auto get_procbin = [] { - fullpath.resize(fullpath.size() << 1); - len = GetModuleFileNameW(nullptr, fullpath.data(), static_cast(fullpath.size())); - } - if(len == 0) - { - ERR("Failed to get process name: error %lu\n", GetLastError()); - procbin.emplace(); - return *procbin; - } +#if !ALSOFT_UWP + DWORD pathlen{256}; + auto fullpath = std::wstring(pathlen, L'\0'); + DWORD len{GetModuleFileNameW(nullptr, fullpath.data(), pathlen)}; + while(len == fullpath.size()) + { + pathlen <<= 1; + if(pathlen == 0) + { + /* pathlen overflow (more than 4 billion characters??) */ + len = 0; + break; + } + fullpath.resize(pathlen); + len = GetModuleFileNameW(nullptr, fullpath.data(), pathlen); + } + if(len == 0) + { + ERR("Failed to get process name: error {}", GetLastError()); + return PathNamePair{}; + } - fullpath.resize(len); - if(fullpath.back() != 0) - fullpath.push_back(0); + fullpath.resize(len); #else - auto exePath = __wargv[0]; - if (!exePath) - { - ERR("Failed to get process name: error %lu\n", GetLastError()); - procbin.emplace(); - return *procbin; - } - std::vector fullpath{exePath, exePath + wcslen(exePath) + 1}; + if(__argc < 1 || !__wargv) + { + ERR("Failed to get process name: __argc = {}, __wargv = {}", __argc, + static_cast(__wargv)); + return PathNamePair{}; + } + const WCHAR *exePath{__wargv[0]}; + if(!exePath) + { + ERR("Failed to get process name: __wargv[0] == nullptr"); + return PathNamePair{}; + } + std::wstring fullpath{exePath}; #endif - std::replace(fullpath.begin(), fullpath.end(), '/', '\\'); - auto sep = std::find(fullpath.rbegin()+1, fullpath.rend(), '\\'); - if(sep != fullpath.rend()) - { - *sep = 0; - procbin.emplace(wstr_to_utf8(fullpath.data()), wstr_to_utf8(al::to_address(sep.base()))); - } - else - procbin.emplace(std::string{}, wstr_to_utf8(fullpath.data())); + std::replace(fullpath.begin(), fullpath.end(), L'/', L'\\'); + + PathNamePair res{}; + if(auto seppos = fullpath.rfind(L'\\'); seppos < fullpath.size()) + { + res.path = wstr_to_utf8(std::wstring_view{fullpath}.substr(0, seppos)); + res.fname = wstr_to_utf8(std::wstring_view{fullpath}.substr(seppos+1)); + } + else + res.fname = wstr_to_utf8(fullpath); - TRACE("Got binary: %s, %s\n", procbin->path.c_str(), procbin->fname.c_str()); - return *procbin; + TRACE("Got binary: {}, {}", res.path, res.fname); + return res; + }; + static const PathNamePair procbin{get_procbin()}; + return procbin; } namespace { -void DirectorySearch(const char *path, const char *ext, std::vector *const results) -{ - std::string pathstr{path}; - pathstr += "\\*"; - pathstr += ext; - TRACE("Searching %s\n", pathstr.c_str()); +#if !ALSOFT_UWP && !defined(_GAMING_XBOX) +struct CoTaskMemDeleter { + void operator()(void *mem) const { CoTaskMemFree(mem); } +}; +#endif - std::wstring wpath{utf8_to_wstr(pathstr.c_str())}; - WIN32_FIND_DATAW fdata; - HANDLE hdl{FindFirstFileExW(wpath.c_str(), FindExInfoStandard, &fdata, FindExSearchNameMatch, NULL, 0)}; - if(hdl == INVALID_HANDLE_VALUE) return; +} // namespace - const auto base = results->size(); +auto SearchDataFiles(const std::string_view ext) -> std::vector +{ + auto srchlock = std::lock_guard{gSearchLock}; - do { - results->emplace_back(); - std::string &str = results->back(); - str = path; - str += '\\'; - str += wstr_to_utf8(fdata.cFileName); - } while(FindNextFileW(hdl, &fdata)); - FindClose(hdl); - const al::span newlist{results->data()+base, results->size()-base}; - std::sort(newlist.begin(), newlist.end()); - for(const auto &name : newlist) - TRACE(" got %s\n", name.c_str()); -} + /* Search the app-local directory. */ + auto results = std::vector{}; + if(auto localpath = al::getenv(L"ALSOFT_LOCAL_PATH")) + DirectorySearch(*localpath, ext, &results); + else if(auto curpath = fs::current_path(); !curpath.empty()) + DirectorySearch(curpath, ext, &results); -} // namespace + return results; +} -std::vector SearchDataFiles(const char *ext, const char *subdir) +auto SearchDataFiles(const std::string_view ext, const std::string_view subdir) + -> std::vector { - auto is_slash = [](int c) noexcept { return (c == '\\' || c == '/'); }; - - static std::mutex search_lock; - std::lock_guard _{search_lock}; + std::lock_guard srchlock{gSearchLock}; /* If the path is absolute, use it directly. */ std::vector results; - if(std::isalpha(subdir[0]) && subdir[1] == ':' && is_slash(subdir[2])) - { - std::string path{subdir}; - std::replace(path.begin(), path.end(), '/', '\\'); - DirectorySearch(path.c_str(), ext, &results); - return results; - } - if(subdir[0] == '\\' && subdir[1] == '\\' && subdir[2] == '?' && subdir[3] == '\\') + auto path = fs::u8path(subdir); + if(path.is_absolute()) { - DirectorySearch(subdir, ext, &results); + DirectorySearch(path, ext, &results); return results; } - std::string path; - - /* Search the app-local directory. */ - if(auto localpath = al::getenv(L"ALSOFT_LOCAL_PATH")) - { - path = wstr_to_utf8(localpath->c_str()); - if(is_slash(path.back())) - path.pop_back(); - } - else if(WCHAR *cwdbuf{_wgetcwd(nullptr, 0)}) - { - path = wstr_to_utf8(cwdbuf); - if(is_slash(path.back())) - path.pop_back(); - free(cwdbuf); - } - else - path = "."; - std::replace(path.begin(), path.end(), '/', '\\'); - DirectorySearch(path.c_str(), ext, &results); - -#if !defined(ALSOFT_UWP) && !defined(_GAMING_XBOX) +#if !ALSOFT_UWP && !defined(_GAMING_XBOX) /* Search the local and global data dirs. */ - for(auto id : std::array{CSIDL_APPDATA, CSIDL_COMMON_APPDATA}) + for(const auto &folderid : std::array{FOLDERID_RoamingAppData, FOLDERID_ProgramData}) { - WCHAR buffer[MAX_PATH]; - if(SHGetSpecialFolderPathW(nullptr, buffer, id, FALSE) == FALSE) + std::unique_ptr buffer; + const HRESULT hr{SHGetKnownFolderPath(folderid, KF_FLAG_DONT_UNEXPAND, nullptr, + al::out_ptr(buffer))}; + if(FAILED(hr) || !buffer || !*buffer) continue; - path = wstr_to_utf8(buffer); - if(!is_slash(path.back())) - path += '\\'; - path += subdir; - std::replace(path.begin(), path.end(), '/', '\\'); - - DirectorySearch(path.c_str(), ext, &results); + DirectorySearch(fs::path{buffer.get()}/path, ext, &results); } #endif return results; } -void SetRTPriority(void) +void SetRTPriority() { -#if !defined(ALSOFT_UWP) +#if !ALSOFT_UWP if(RTPrioLevel > 0) { if(!SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_TIME_CRITICAL)) - ERR("Failed to set priority level for thread\n"); + ERR("Failed to set priority level for thread"); } #endif } @@ -206,7 +218,7 @@ void SetRTPriority(void) #include #include #endif -#ifdef HAVE_RTKIT +#if HAVE_RTKIT #include #include "dbus_wrap.h" @@ -218,184 +230,120 @@ void SetRTPriority(void) const PathNamePair &GetProcBinary() { - static std::optional procbin; - if(procbin) return *procbin; - - std::vector pathname; -#ifdef __FreeBSD__ - size_t pathlen; - int mib[4] = { CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1 }; - if(sysctl(mib, 4, nullptr, &pathlen, nullptr, 0) == -1) - WARN("Failed to sysctl kern.proc.pathname: %s\n", strerror(errno)); - else + auto get_procbin = [] { - pathname.resize(pathlen + 1); - sysctl(mib, 4, pathname.data(), &pathlen, nullptr, 0); - pathname.resize(pathlen); - } + std::string pathname; +#ifdef __FreeBSD__ + size_t pathlen{}; + std::array mib{{CTL_KERN, KERN_PROC, KERN_PROC_PATHNAME, -1}}; + if(sysctl(mib.data(), mib.size(), nullptr, &pathlen, nullptr, 0) == -1) + WARN("Failed to sysctl kern.proc.pathname: {}", + std::generic_category().message(errno)); + else + { + auto procpath = std::vector(pathlen+1, '\0'); + sysctl(mib.data(), mib.size(), procpath.data(), &pathlen, nullptr, 0); + pathname = procpath.data(); + } #endif #ifdef HAVE_PROC_PIDPATH - if(pathname.empty()) - { - char procpath[PROC_PIDPATHINFO_MAXSIZE]{}; - const pid_t pid{getpid()}; - if(proc_pidpath(pid, procpath, sizeof(procpath)) < 1) - ERR("proc_pidpath(%d, ...) failed: %s\n", pid, strerror(errno)); - else - pathname.insert(pathname.end(), procpath, procpath+strlen(procpath)); - } + if(pathname.empty()) + { + std::array procpath{}; + const pid_t pid{getpid()}; + if(proc_pidpath(pid, procpath.data(), procpath.size()) < 1) + ERR("proc_pidpath({}, ...) failed: {}", pid, + std::generic_category().message(errno)); + else + pathname = procpath.data(); + } #endif #ifdef __HAIKU__ - if(pathname.empty()) - { - char procpath[PATH_MAX]; - if(find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, procpath, sizeof(procpath)) == B_OK) - pathname.insert(pathname.end(), procpath, procpath+strlen(procpath)); - } + if(pathname.empty()) + { + std::array procpath{}; + if(find_path(B_APP_IMAGE_SYMBOL, B_FIND_PATH_IMAGE_PATH, NULL, procpath.data(), procpath.size()) == B_OK) + pathname = procpath.data(); + } #endif #ifndef __SWITCH__ - if(pathname.empty()) - { - const char *SelfLinkNames[]{ - "/proc/self/exe", - "/proc/self/file", - "/proc/curproc/exe", - "/proc/curproc/file" - }; - - pathname.resize(256); - - const char *selfname{}; - ssize_t len{}; - for(const char *name : SelfLinkNames) + if(pathname.empty()) { - selfname = name; - len = readlink(selfname, pathname.data(), pathname.size()); - if(len >= 0 || errno != ENOENT) break; + const std::array SelfLinkNames{ + "/proc/self/exe"sv, + "/proc/self/file"sv, + "/proc/curproc/exe"sv, + "/proc/curproc/file"sv, + }; + + for(const std::string_view name : SelfLinkNames) + { + try { + if(!fs::exists(name)) + continue; + if(auto path = fs::read_symlink(name); !path.empty()) + { + pathname = al::u8_as_char(path.u8string()); + break; + } + } + catch(std::exception& e) { + WARN("Exception getting symlink {}: {}", name, e.what()); + } + } } +#endif - while(len > 0 && static_cast(len) == pathname.size()) - { - pathname.resize(pathname.size() << 1); - len = readlink(selfname, pathname.data(), pathname.size()); - } - if(len <= 0) + PathNamePair res{}; + if(auto seppos = pathname.rfind('/'); seppos < pathname.size()) { - WARN("Failed to readlink %s: %s\n", selfname, strerror(errno)); - len = 0; + res.path = std::string_view{pathname}.substr(0, seppos); + res.fname = std::string_view{pathname}.substr(seppos+1); } + else + res.fname = pathname; - pathname.resize(static_cast(len)); - } -#endif - while(!pathname.empty() && pathname.back() == 0) - pathname.pop_back(); - - auto sep = std::find(pathname.crbegin(), pathname.crend(), '/'); - if(sep != pathname.crend()) - procbin.emplace(std::string(pathname.cbegin(), sep.base()-1), - std::string(sep.base(), pathname.cend())); - else - procbin.emplace(std::string{}, std::string(pathname.cbegin(), pathname.cend())); - - TRACE("Got binary: \"%s\", \"%s\"\n", procbin->path.c_str(), procbin->fname.c_str()); - return *procbin; + TRACE("Got binary: \"{}\", \"{}\"", res.path, res.fname); + return res; + }; + static const PathNamePair procbin{get_procbin()}; + return procbin; } -namespace { - -void DirectorySearch(const char *path, const char *ext, std::vector *const results) +auto SearchDataFiles(const std::string_view ext) -> std::vector { - TRACE("Searching %s for *%s\n", path, ext); - DIR *dir{opendir(path)}; - if(!dir) return; - - const auto base = results->size(); - const size_t extlen{strlen(ext)}; - - while(struct dirent *dirent{readdir(dir)}) - { - if(strcmp(dirent->d_name, ".") == 0 || strcmp(dirent->d_name, "..") == 0) - continue; + auto srchlock = std::lock_guard{gSearchLock}; - const size_t len{strlen(dirent->d_name)}; - if(len <= extlen) continue; - if(al::strcasecmp(dirent->d_name+len-extlen, ext) != 0) - continue; - - results->emplace_back(); - std::string &str = results->back(); - str = path; - if(str.back() != '/') - str.push_back('/'); - str += dirent->d_name; - } - closedir(dir); + /* Search the app-local directory. */ + auto results = std::vector{}; + if(auto localpath = al::getenv("ALSOFT_LOCAL_PATH")) + DirectorySearch(*localpath, ext, &results); + else if(auto curpath = fs::current_path(); !curpath.empty()) + DirectorySearch(curpath, ext, &results); - const al::span newlist{results->data()+base, results->size()-base}; - std::sort(newlist.begin(), newlist.end()); - for(const auto &name : newlist) - TRACE(" got %s\n", name.c_str()); + return results; } -} // namespace - -std::vector SearchDataFiles(const char *ext, const char *subdir) +auto SearchDataFiles(const std::string_view ext, const std::string_view subdir) + -> std::vector { - static std::mutex search_lock; - std::lock_guard _{search_lock}; + std::lock_guard srchlock{gSearchLock}; std::vector results; - if(subdir[0] == '/') + auto path = fs::u8path(subdir); + if(path.is_absolute()) { - DirectorySearch(subdir, ext, &results); + DirectorySearch(path, ext, &results); return results; } - /* Search the app-local directory. */ - if(auto localpath = al::getenv("ALSOFT_LOCAL_PATH")) - DirectorySearch(localpath->c_str(), ext, &results); - else - { - std::vector cwdbuf(256); - while(!getcwd(cwdbuf.data(), cwdbuf.size())) - { - if(errno != ERANGE) - { - cwdbuf.clear(); - break; - } - cwdbuf.resize(cwdbuf.size() << 1); - } - if(cwdbuf.empty()) - DirectorySearch(".", ext, &results); - else - { - DirectorySearch(cwdbuf.data(), ext, &results); - cwdbuf.clear(); - } - } - - // Search local data dir + /* Search local data dir */ if(auto datapath = al::getenv("XDG_DATA_HOME")) - { - std::string &path = *datapath; - if(path.back() != '/') - path += '/'; - path += subdir; - DirectorySearch(path.c_str(), ext, &results); - } + DirectorySearch(fs::path{*datapath}/path, ext, &results); else if(auto homepath = al::getenv("HOME")) - { - std::string &path = *homepath; - if(path.back() == '/') - path.pop_back(); - path += "/.local/share/"; - path += subdir; - DirectorySearch(path.c_str(), ext, &results); - } + DirectorySearch(fs::path{*homepath}/".local/share"/path, ext, &results); - // Search global data dirs + /* Search global data dirs */ std::string datadirs{al::getenv("XDG_DATA_DIRS").value_or("/usr/local/share/:/usr/share/")}; size_t curpos{0u}; @@ -403,30 +351,19 @@ std::vector SearchDataFiles(const char *ext, const char *subdir) { size_t nextpos{datadirs.find(':', curpos)}; - std::string path{(nextpos != std::string::npos) ? - datadirs.substr(curpos, nextpos++ - curpos) : datadirs.substr(curpos)}; + std::string_view pathname{(nextpos != std::string::npos) + ? std::string_view{datadirs}.substr(curpos, nextpos++ - curpos) + : std::string_view{datadirs}.substr(curpos)}; curpos = nextpos; - if(path.empty()) continue; - if(path.back() != '/') - path += '/'; - path += subdir; - - DirectorySearch(path.c_str(), ext, &results); + if(!pathname.empty()) + DirectorySearch(fs::path{pathname}/path, ext, &results); } #ifdef ALSOFT_INSTALL_DATADIR - // Search the installation data directory - { - std::string path{ALSOFT_INSTALL_DATADIR}; - if(!path.empty()) - { - if(path.back() != '/') - path += '/'; - path += subdir; - DirectorySearch(path.c_str(), ext, &results); - } - } + /* Search the installation data directory */ + if(auto instpath = fs::path{ALSOFT_INSTALL_DATADIR}; !instpath.empty()) + DirectorySearch(instpath/path, ext, &results); #endif return results; @@ -447,7 +384,7 @@ bool SetRTPriorityPthread(int prio [[maybe_unused]]) rtmax = (rtmax-rtmin)/2 + rtmin; struct sched_param param{}; - param.sched_priority = clampi(prio, rtmin, rtmax); + param.sched_priority = std::clamp(prio, rtmin, rtmax); #ifdef SCHED_RESET_ON_FORK err = pthread_setschedparam(pthread_self(), SCHED_RR|SCHED_RESET_ON_FORK, ¶m); if(err == EINVAL) @@ -455,23 +392,23 @@ bool SetRTPriorityPthread(int prio [[maybe_unused]]) err = pthread_setschedparam(pthread_self(), SCHED_RR, ¶m); if(err == 0) return true; #endif - WARN("pthread_setschedparam failed: %s (%d)\n", std::strerror(err), err); + WARN("pthread_setschedparam failed: {} ({})", std::generic_category().message(err), err); return false; } bool SetRTPriorityRTKit(int prio [[maybe_unused]]) { -#ifdef HAVE_RTKIT +#if HAVE_RTKIT if(!HasDBus()) { - WARN("D-Bus not available\n"); + WARN("D-Bus not available"); return false; } dbus::Error error; dbus::ConnectionPtr conn{dbus_bus_get(DBUS_BUS_SYSTEM, &error.get())}; if(!conn) { - WARN("D-Bus connection failed with %s: %s\n", error->name, error->message); + WARN("D-Bus connection failed with {}: {}", error->name, error->message); return false; } @@ -483,11 +420,11 @@ bool SetRTPriorityRTKit(int prio [[maybe_unused]]) if(err == -ENOENT) { err = std::abs(err); - ERR("Could not query RTKit: %s (%d)\n", std::strerror(err), err); + ERR("Could not query RTKit: {} ({})", std::generic_category().message(err), err); return false; } int rtmax{rtkit_get_max_realtime_priority(conn.get())}; - TRACE("Maximum real-time priority: %d, minimum niceness: %d\n", rtmax, nicemin); + TRACE("Maximum real-time priority: {}, minimum niceness: {}", rtmax, nicemin); auto limit_rttime = [](DBusConnection *c) -> int { @@ -500,8 +437,7 @@ bool SetRTPriorityRTKit(int prio [[maybe_unused]]) if(getrlimit(RLIMIT_RTTIME, &rlim) != 0) return errno; - TRACE("RTTime max: %llu (hard: %llu, soft: %llu)\n", umaxtime, - static_cast(rlim.rlim_max), static_cast(rlim.rlim_cur)); + TRACE("RTTime max: {} (hard: {}, soft: {})", umaxtime, rlim.rlim_max, rlim.rlim_cur); if(rlim.rlim_max > umaxtime) { rlim.rlim_max = static_cast(std::min(umaxtime, @@ -518,20 +454,21 @@ bool SetRTPriorityRTKit(int prio [[maybe_unused]]) { err = limit_rttime(conn.get()); if(err != 0) - WARN("Failed to set RLIMIT_RTTIME for RTKit: %s (%d)\n", - std::strerror(err), err); + WARN("Failed to set RLIMIT_RTTIME for RTKit: {} ({})", + std::generic_category().message(err), err); } /* Limit the maximum real-time priority to half. */ rtmax = (rtmax+1)/2; - prio = clampi(prio, 1, rtmax); + prio = std::clamp(prio, 1, rtmax); - TRACE("Making real-time with priority %d (max: %d)\n", prio, rtmax); + TRACE("Making real-time with priority {} (max: {})", prio, rtmax); err = rtkit_make_realtime(conn.get(), 0, prio); if(err == 0) return true; err = std::abs(err); - WARN("Failed to set real-time priority: %s (%d)\n", std::strerror(err), err); + WARN("Failed to set real-time priority: {} ({})", + std::generic_category().message(err), err); } /* Don't try to set the niceness for non-Linux systems. Standard POSIX has * niceness as a per-process attribute, while the intent here is for the @@ -541,18 +478,18 @@ bool SetRTPriorityRTKit(int prio [[maybe_unused]]) #ifdef __linux__ if(nicemin < 0) { - TRACE("Making high priority with niceness %d\n", nicemin); + TRACE("Making high priority with niceness {}", nicemin); err = rtkit_make_high_priority(conn.get(), 0, nicemin); if(err == 0) return true; err = std::abs(err); - WARN("Failed to set high priority: %s (%d)\n", std::strerror(err), err); + WARN("Failed to set high priority: {} ({})", std::generic_category().message(err), err); } #endif /* __linux__ */ #else - WARN("D-Bus not supported\n"); + WARN("D-Bus not supported"); #endif return false; } diff --git a/3rdparty/openal/core/helpers.h b/3rdparty/openal/core/helpers.h index df51c1161de4..96987a2e8743 100644 --- a/3rdparty/openal/core/helpers.h +++ b/3rdparty/openal/core/helpers.h @@ -1,26 +1,26 @@ #ifndef CORE_HELPERS_H #define CORE_HELPERS_H -#include #include +#include #include struct PathNamePair { std::string path, fname; - - PathNamePair() = default; - template - PathNamePair(T&& path_, U&& fname_) - : path{std::forward(path_)}, fname{std::forward(fname_)} - { } }; -const PathNamePair &GetProcBinary(void); +const PathNamePair &GetProcBinary(); + +/* Mixing thread priority level */ +inline int RTPrioLevel{1}; + +/* Allow reducing the process's RTTime limit for RTKit. */ +inline bool AllowRTTimeLimit{true}; -extern int RTPrioLevel; -extern bool AllowRTTimeLimit; -void SetRTPriority(void); +void SetRTPriority(); -std::vector SearchDataFiles(const char *match, const char *subdir); +auto SearchDataFiles(const std::string_view ext) -> std::vector; +auto SearchDataFiles(const std::string_view ext, const std::string_view subdir) + -> std::vector; #endif /* CORE_HELPERS_H */ diff --git a/3rdparty/openal/core/hrtf.cpp b/3rdparty/openal/core/hrtf.cpp index 9a13a0045056..ccd0a11a6d65 100644 --- a/3rdparty/openal/core/hrtf.cpp +++ b/3rdparty/openal/core/hrtf.cpp @@ -18,18 +18,21 @@ #include #include #include +#include #include #include #include #include "albit.h" -#include "alfstream.h" #include "almalloc.h" #include "alnumbers.h" #include "alnumeric.h" #include "alspan.h" +#include "alstring.h" #include "ambidefs.h" +#include "filesystem.h" #include "filters/splitter.h" +#include "fmt/core.h" #include "helpers.h" #include "logging.h" #include "mixer/hrtfdefs.h" @@ -39,10 +42,16 @@ namespace { +using namespace std::string_view_literals; + struct HrtfEntry { std::string mDispName; std::string mFilename; + template + HrtfEntry(T&& dispname, U&& fname) + : mDispName{std::forward(dispname)}, mFilename{std::forward(fname)} + { } /* GCC warns when it tries to inline this. */ ~HrtfEntry(); }; @@ -50,11 +59,12 @@ HrtfEntry::~HrtfEntry() = default; struct LoadedHrtf { std::string mFilename; + uint mSampleRate{}; std::unique_ptr mEntry; template - LoadedHrtf(T&& name, U&& entry) - : mFilename{std::forward(name)}, mEntry{std::forward(entry)} + LoadedHrtf(T&& name, uint srate, U&& entry) + : mFilename{std::forward(name)}, mSampleRate{srate}, mEntry{std::forward(entry)} { } LoadedHrtf(LoadedHrtf&&) = default; /* GCC warns when it tries to inline this. */ @@ -86,12 +96,24 @@ constexpr uint HrirDelayFracBits{2}; constexpr uint HrirDelayFracOne{1 << HrirDelayFracBits}; constexpr uint HrirDelayFracHalf{HrirDelayFracOne >> 1}; +/* The sample rate is stored as a 24-bit integer, so 16MHz is the largest + * supported. + */ +constexpr uint MaxSampleRate{0xff'ff'ff}; + static_assert(MaxHrirDelay*HrirDelayFracOne < 256, "MAX_HRIR_DELAY or DELAY_FRAC too large"); -constexpr char magicMarker00[8]{'M','i','n','P','H','R','0','0'}; -constexpr char magicMarker01[8]{'M','i','n','P','H','R','0','1'}; -constexpr char magicMarker02[8]{'M','i','n','P','H','R','0','2'}; -constexpr char magicMarker03[8]{'M','i','n','P','H','R','0','3'}; + +constexpr auto HeaderMarkerSize = 8_uz; +[[nodiscard]] constexpr auto GetMarker00Name() noexcept { return "MinPHR00"sv; } +[[nodiscard]] constexpr auto GetMarker01Name() noexcept { return "MinPHR01"sv; } +[[nodiscard]] constexpr auto GetMarker02Name() noexcept { return "MinPHR02"sv; } +[[nodiscard]] constexpr auto GetMarker03Name() noexcept { return "MinPHR03"sv; } + +static_assert(GetMarker00Name().size() == HeaderMarkerSize); +static_assert(GetMarker01Name().size() == HeaderMarkerSize); +static_assert(GetMarker02Name().size() == HeaderMarkerSize); +static_assert(GetMarker03Name().size() == HeaderMarkerSize); /* First value for pass-through coefficients (remaining are 0), used for omni- * directional sounds. */ @@ -104,6 +126,11 @@ std::mutex EnumeratedHrtfLock; std::vector EnumeratedHrtfs; +/* NOLINTBEGIN(cppcoreguidelines-pro-bounds-pointer-arithmetic) + * To access a memory buffer through the std::istream interface, a custom + * std::streambuf implementation is needed that has to do pointer manipulation + * for seeking. With C++23, we may be able to use std::spanstream instead. + */ class databuf final : public std::streambuf { int_type underflow() override { return traits_type::eof(); } @@ -113,34 +140,32 @@ class databuf final : public std::streambuf { if((mode&std::ios_base::out) || !(mode&std::ios_base::in)) return traits_type::eof(); - char_type *cur; switch(whence) { - case std::ios_base::beg: - if(offset < 0 || offset > egptr()-eback()) - return traits_type::eof(); - cur = eback() + offset; - break; - - case std::ios_base::cur: - if((offset >= 0 && offset > egptr()-gptr()) || - (offset < 0 && -offset > gptr()-eback())) - return traits_type::eof(); - cur = gptr() + offset; - break; + case std::ios_base::beg: + if(offset < 0 || offset > egptr()-eback()) + return traits_type::eof(); + setg(eback(), eback()+offset, egptr()); + break; - case std::ios_base::end: - if(offset > 0 || -offset > egptr()-eback()) - return traits_type::eof(); - cur = egptr() + offset; - break; + case std::ios_base::cur: + if((offset >= 0 && offset > egptr()-gptr()) || + (offset < 0 && -offset > gptr()-eback())) + return traits_type::eof(); + setg(eback(), gptr()+offset, egptr()); + break; - default: + case std::ios_base::end: + if(offset > 0 || -offset > egptr()-eback()) return traits_type::eof(); + setg(eback(), egptr()+offset, egptr()); + break; + + default: + return traits_type::eof(); } - setg(eback(), cur, egptr()); - return cur - eback(); + return gptr() - eback(); } pos_type seekpos(pos_type pos, std::ios_base::openmode mode) override @@ -152,24 +177,23 @@ class databuf final : public std::streambuf { if(pos < 0 || pos > egptr()-eback()) return traits_type::eof(); - setg(eback(), eback() + static_cast(pos), egptr()); + setg(eback(), eback()+static_cast(pos), egptr()); return pos; } public: - databuf(const char_type *start_, const char_type *end_) noexcept + explicit databuf(const al::span data) noexcept { - setg(const_cast(start_), const_cast(start_), - const_cast(end_)); + setg(data.data(), data.data(), al::to_address(data.end())); } }; +/* NOLINTEND(cppcoreguidelines-pro-bounds-pointer-arithmetic) */ class idstream final : public std::istream { databuf mStreamBuf; public: - idstream(const char *start_, const char *end_) - : std::istream{nullptr}, mStreamBuf{start_, end_} + explicit idstream(const al::span data) : std::istream{nullptr}, mStreamBuf{data} { init(&mStreamBuf); } }; @@ -180,11 +204,10 @@ struct IdxBlend { uint idx; float blend; }; */ IdxBlend CalcEvIndex(uint evcount, float ev) { - ev = (al::numbers::pi_v*0.5f + ev) * static_cast(evcount-1) * - al::numbers::inv_pi_v; - uint idx{float2uint(ev)}; + ev = (al::numbers::inv_pi_v*ev + 0.5f) * static_cast(evcount-1); - return IdxBlend{minu(idx, evcount-1), ev-static_cast(idx)}; + const auto idx = float2uint(ev); + return IdxBlend{std::min(idx, evcount-1u), ev-static_cast(idx)}; } /* Calculate the azimuth index given the polar azimuth in radians. This will @@ -192,10 +215,9 @@ IdxBlend CalcEvIndex(uint evcount, float ev) */ IdxBlend CalcAzIndex(uint azcount, float az) { - az = (al::numbers::pi_v*2.0f + az) * static_cast(azcount) * - (al::numbers::inv_pi_v*0.5f); - uint idx{float2uint(az)}; + az = (al::numbers::inv_pi_v*0.5f*az + 1.0f) * static_cast(azcount); + const auto idx = float2uint(az); return IdxBlend{idx%azcount, az-static_cast(idx)}; } @@ -206,7 +228,7 @@ IdxBlend CalcAzIndex(uint azcount, float az) * and azimuth in radians. The coefficients are normalized. */ void HrtfStore::getCoeffs(float elevation, float azimuth, float distance, float spread, - HrirArray &coeffs, const al::span delays) + const HrirSpan coeffs, const al::span delays) const { const float dirfact{1.0f - (al::numbers::inv_pi_v/2.0f * spread)}; @@ -222,7 +244,7 @@ void HrtfStore::getCoeffs(float elevation, float azimuth, float distance, float /* Calculate the elevation indices. */ const auto elev0 = CalcEvIndex(field->evCount, elevation); - const size_t elev1_idx{minu(elev0.idx+1, field->evCount-1)}; + const size_t elev1_idx{std::min(elev0.idx+1u, field->evCount-1u)}; const size_t ir0offset{mElev[ebase + elev0.idx].irOffset}; const size_t ir1offset{mElev[ebase + elev1_idx].irOffset}; @@ -231,43 +253,43 @@ void HrtfStore::getCoeffs(float elevation, float azimuth, float distance, float const auto az1 = CalcAzIndex(mElev[ebase + elev1_idx].azCount, azimuth); /* Calculate the HRIR indices to blend. */ - const size_t idx[4]{ + const std::array idx{{ ir0offset + az0.idx, ir0offset + ((az0.idx+1) % mElev[ebase + elev0.idx].azCount), ir1offset + az1.idx, ir1offset + ((az1.idx+1) % mElev[ebase + elev1_idx].azCount) - }; + }}; /* Calculate bilinear blending weights, attenuated according to the * directional panning factor. */ - const float blend[4]{ + const std::array blend{{ (1.0f-elev0.blend) * (1.0f-az0.blend) * dirfact, (1.0f-elev0.blend) * ( az0.blend) * dirfact, ( elev0.blend) * (1.0f-az1.blend) * dirfact, ( elev0.blend) * ( az1.blend) * dirfact - }; + }}; /* Calculate the blended HRIR delays. */ - float d{mDelays[idx[0]][0]*blend[0] + mDelays[idx[1]][0]*blend[1] + mDelays[idx[2]][0]*blend[2] - + mDelays[idx[3]][0]*blend[3]}; + float d{float(mDelays[idx[0]][0])*blend[0] + float(mDelays[idx[1]][0])*blend[1] + + float(mDelays[idx[2]][0])*blend[2] + float(mDelays[idx[3]][0])*blend[3]}; delays[0] = fastf2u(d * float{1.0f/HrirDelayFracOne}); - d = mDelays[idx[0]][1]*blend[0] + mDelays[idx[1]][1]*blend[1] + mDelays[idx[2]][1]*blend[2] - + mDelays[idx[3]][1]*blend[3]; + d = float(mDelays[idx[0]][1])*blend[0] + float(mDelays[idx[1]][1])*blend[1] + + float(mDelays[idx[2]][1])*blend[2] + float(mDelays[idx[3]][1])*blend[3]; delays[1] = fastf2u(d * float{1.0f/HrirDelayFracOne}); /* Calculate the blended HRIR coefficients. */ - float *coeffout{al::assume_aligned<16>(coeffs[0].data())}; - coeffout[0] = PassthruCoeff * (1.0f-dirfact); - coeffout[1] = PassthruCoeff * (1.0f-dirfact); - std::fill_n(coeffout+2, size_t{HrirLength-1}*2, 0.0f); + auto coeffout = coeffs.begin(); + coeffout[0][0] = PassthruCoeff * (1.0f-dirfact); + coeffout[0][1] = PassthruCoeff * (1.0f-dirfact); + std::fill_n(coeffout+1, size_t{HrirLength-1}, std::array{0.0f, 0.0f}); for(size_t c{0};c < 4;c++) { - const float *srccoeffs{al::assume_aligned<16>(mCoeffs[idx[c]][0].data())}; const float mult{blend[c]}; - auto blend_coeffs = [mult](const float src, const float coeff) noexcept -> float - { return src*mult + coeff; }; - std::transform(srccoeffs, srccoeffs + HrirLength*2, coeffout, coeffout, blend_coeffs); + auto blend_coeffs = [mult](const float2 &src, const float2 &coeff) noexcept -> float2 + { return float2{{src[0]*mult + coeff[0], src[1]*mult + coeff[1]}}; }; + std::transform(mCoeffs[idx[c]].cbegin(), mCoeffs[idx[c]].cend(), coeffout, coeffout, + blend_coeffs); } } @@ -276,7 +298,8 @@ std::unique_ptr DirectHrtfState::Create(size_t num_chans) { return std::unique_ptr{new(FamCount(num_chans)) DirectHrtfState{num_chans}}; } void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool perHrirMin, - const al::span AmbiPoints, const float (*AmbiMatrix)[MaxAmbiChannels], + const al::span AmbiPoints, + const al::span> AmbiMatrix, const float XOverFreq, const al::span AmbiOrderHFGain) { using double2 = std::array; @@ -287,7 +310,8 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool const double xover_norm{double{XOverFreq} / Hrtf->mSampleRate}; mChannels[0].mSplitter.init(static_cast(xover_norm)); - for(size_t i{0};i < mChannels.size();++i) + mChannels[0].mHfScale = AmbiOrderHFGain[0]; + for(size_t i{1};i < mChannels.size();++i) { const size_t order{AmbiIndex::OrderFromChannel[i]}; mChannels[i].mSplitter = mChannels[0].mSplitter; @@ -300,14 +324,14 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool { auto &field = Hrtf->mFields[0]; const auto elev0 = CalcEvIndex(field.evCount, pt.Elev.value); - const size_t elev1_idx{minu(elev0.idx+1, field.evCount-1)}; + const size_t elev1_idx{std::min(elev0.idx+1u, field.evCount-1u)}; const size_t ir0offset{Hrtf->mElev[elev0.idx].irOffset}; const size_t ir1offset{Hrtf->mElev[elev1_idx].irOffset}; const auto az0 = CalcAzIndex(Hrtf->mElev[elev0.idx].azCount, pt.Azim.value); const auto az1 = CalcAzIndex(Hrtf->mElev[elev1_idx].azCount, pt.Azim.value); - const size_t idx[4]{ + const std::array idx{ ir0offset + az0.idx, ir0offset + ((az0.idx+1) % Hrtf->mElev[elev0.idx].azCount), ir1offset + az1.idx, @@ -319,8 +343,8 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool ImpulseResponse res{Hrtf->mCoeffs[irOffset], Hrtf->mDelays[irOffset][0], Hrtf->mDelays[irOffset][1]}; - min_delay = minu(min_delay, minu(res.ldelay, res.rdelay)); - max_delay = maxu(max_delay, maxu(res.ldelay, res.rdelay)); + min_delay = std::min(min_delay, std::min(res.ldelay, res.rdelay)); + max_delay = std::max(max_delay, std::max(res.ldelay, res.rdelay)); return res; }; @@ -328,44 +352,48 @@ void DirectHrtfState::build(const HrtfStore *Hrtf, const uint irSize, const bool auto hrir_delay_round = [](const uint d) noexcept -> uint { return (d+HrirDelayFracHalf) >> HrirDelayFracBits; }; - TRACE("Min delay: %.2f, max delay: %.2f, FIR length: %u\n", + TRACE("Min delay: {:.2f}, max delay: {:.2f}, FIR length: {}", min_delay/double{HrirDelayFracOne}, max_delay/double{HrirDelayFracOne}, irSize); auto tmpres = std::vector>(mChannels.size()); max_delay = 0; - for(size_t c{0u};c < AmbiPoints.size();++c) + auto matrixline = AmbiMatrix.cbegin(); + for(auto &impulse : impres) { - const ConstHrirSpan hrir{impres[c].hrir}; - const uint base_delay{perHrirMin ? minu(impres[c].ldelay, impres[c].rdelay) : min_delay}; - const uint ldelay{hrir_delay_round(impres[c].ldelay - base_delay)}; - const uint rdelay{hrir_delay_round(impres[c].rdelay - base_delay)}; - max_delay = maxu(max_delay, maxu(impres[c].ldelay, impres[c].rdelay) - base_delay); - - for(size_t i{0u};i < mChannels.size();++i) + const ConstHrirSpan hrir{impulse.hrir}; + const uint base_delay{perHrirMin ? std::min(impulse.ldelay, impulse.rdelay) : min_delay}; + const uint ldelay{hrir_delay_round(impulse.ldelay - base_delay)}; + const uint rdelay{hrir_delay_round(impulse.rdelay - base_delay)}; + max_delay = std::max(max_delay, std::max(impulse.ldelay, impulse.rdelay) - base_delay); + + auto gains = matrixline->cbegin(); + ++matrixline; + for(auto &result : tmpres) { - const double mult{AmbiMatrix[c][i]}; - const size_t numirs{HrirLength - maxz(ldelay, rdelay)}; + const double mult{*(gains++)}; + const size_t numirs{HrirLength - std::max(ldelay, rdelay)}; size_t lidx{ldelay}, ridx{rdelay}; for(size_t j{0};j < numirs;++j) { - tmpres[i][lidx++][0] += hrir[j][0] * mult; - tmpres[i][ridx++][1] += hrir[j][1] * mult; + result[lidx++][0] += hrir[j][0] * mult; + result[ridx++][1] += hrir[j][1] * mult; } } } impres.clear(); - for(size_t i{0u};i < mChannels.size();++i) + auto output = mChannels.begin(); + for(auto &result : tmpres) { - auto copy_arr = [](const double2 &in) noexcept -> float2 + auto cast_array2 = [](const double2 &in) noexcept -> float2 { return float2{{static_cast(in[0]), static_cast(in[1])}}; }; - std::transform(tmpres[i].cbegin(), tmpres[i].cend(), mChannels[i].mCoeffs.begin(), - copy_arr); + std::transform(result.cbegin(), result.cend(), output->mCoeffs.begin(), cast_array2); + ++output; } tmpres.clear(); - const uint max_length{minu(hrir_delay_round(max_delay) + irSize, HrirLength)}; - TRACE("New max delay: %.2f, FIR length: %u\n", max_delay/double{HrirDelayFracOne}, + const uint max_length{std::min(hrir_delay_round(max_delay) + irSize, HrirLength)}; + TRACE("New max delay: {:.2f}, FIR length: {}", max_delay/double{HrirDelayFracOne}, max_length); mIrSize = max_length; } @@ -376,8 +404,15 @@ namespace { std::unique_ptr CreateHrtfStore(uint rate, uint8_t irSize, const al::span fields, const al::span elevs, const HrirArray *coeffs, - const ubyte2 *delays, const char *filename) + const ubyte2 *delays) { + static_assert(alignof(HrtfStore::Field) <= alignof(HrtfStore)); + static_assert(alignof(HrtfStore::Elevation) <= alignof(HrtfStore)); + static_assert(16 <= alignof(HrtfStore)); + + if(rate > MaxSampleRate) + throw std::runtime_error{"Sample rate is too large (max: "+std::to_string(MaxSampleRate)+"hz)"}; + const size_t irCount{size_t{elevs.back().azCount} + elevs.back().irOffset}; size_t total{sizeof(HrtfStore)}; total = RoundUp(total, alignof(HrtfStore::Field)); /* Align for field infos */ @@ -388,56 +423,54 @@ std::unique_ptr CreateHrtfStore(uint rate, uint8_t irSize, total += sizeof(std::declval().mCoeffs[0])*irCount; total += sizeof(std::declval().mDelays[0])*irCount; - std::unique_ptr Hrtf{}; - if(void *ptr{al_calloc(16, total)}) - { - Hrtf.reset(al::construct_at(static_cast(ptr))); - InitRef(Hrtf->mRef, 1u); - Hrtf->mSampleRate = rate & 0xff'ff'ff; - Hrtf->mIrSize = irSize; - - /* Set up pointers to storage following the main HRTF struct. */ - char *base = reinterpret_cast(Hrtf.get()); - size_t offset{sizeof(HrtfStore)}; - - offset = RoundUp(offset, alignof(HrtfStore::Field)); /* Align for field infos */ - auto field_ = reinterpret_cast(base + offset); - offset += sizeof(field_[0])*fields.size(); - - offset = RoundUp(offset, alignof(HrtfStore::Elevation)); /* Align for elevation infos */ - auto elev_ = reinterpret_cast(base + offset); - offset += sizeof(elev_[0])*elevs.size(); - - offset = RoundUp(offset, 16); /* Align for coefficients using SIMD */ - auto coeffs_ = reinterpret_cast(base + offset); - offset += sizeof(coeffs_[0])*irCount; - - auto delays_ = reinterpret_cast(base + offset); - offset += sizeof(delays_[0])*irCount; - - if(offset != total) - throw std::runtime_error{"HrtfStore allocation size mismatch"}; - - /* Copy input data to storage. */ - std::uninitialized_copy(fields.cbegin(), fields.cend(), field_); - std::uninitialized_copy(elevs.cbegin(), elevs.cend(), elev_); - std::uninitialized_copy_n(coeffs, irCount, coeffs_); - std::uninitialized_copy_n(delays, irCount, delays_); - - /* Finally, assign the storage pointers. */ - Hrtf->mFields = {field_, fields.size()}; - Hrtf->mElev = elev_; - Hrtf->mCoeffs = coeffs_; - Hrtf->mDelays = delays_; - } - else - ERR("Out of memory allocating storage for %s.\n", filename); + static constexpr auto AlignVal = std::align_val_t{alignof(HrtfStore)}; + std::unique_ptr Hrtf{::new(::operator new[](total, AlignVal)) HrtfStore{}}; + Hrtf->mRef.store(1u, std::memory_order_relaxed); + Hrtf->mSampleRate = rate & 0xff'ff'ff; + Hrtf->mIrSize = irSize; + + /* Set up pointers to storage following the main HRTF struct. */ + auto storage = al::span{reinterpret_cast(Hrtf.get()), total}; + auto base = storage.begin(); + ptrdiff_t offset{sizeof(HrtfStore)}; + + offset = RoundUp(offset, alignof(HrtfStore::Field)); /* Align for field infos */ + auto field_ = al::span{reinterpret_cast(al::to_address(base + offset)), + fields.size()}; + offset += ptrdiff_t(sizeof(field_[0])*fields.size()); + + offset = RoundUp(offset, alignof(HrtfStore::Elevation)); /* Align for elevation infos */ + auto elev_ = al::span{reinterpret_cast(al::to_address(base + offset)), + elevs.size()}; + offset += ptrdiff_t(sizeof(elev_[0])*elevs.size()); + + offset = RoundUp(offset, 16); /* Align for coefficients using SIMD */ + auto coeffs_ = al::span{reinterpret_cast(al::to_address(base + offset)), irCount}; + offset += ptrdiff_t(sizeof(coeffs_[0])*irCount); + + auto delays_ = al::span{reinterpret_cast(al::to_address(base + offset)), irCount}; + offset += ptrdiff_t(sizeof(delays_[0])*irCount); + + if(size_t(offset) != total) + throw std::runtime_error{"HrtfStore allocation size mismatch"}; + + /* Copy input data to storage. */ + std::uninitialized_copy(fields.cbegin(), fields.cend(), field_.begin()); + std::uninitialized_copy(elevs.cbegin(), elevs.cend(), elev_.begin()); + std::uninitialized_copy_n(coeffs, irCount, coeffs_.begin()); + std::uninitialized_copy_n(delays, irCount, delays_.begin()); + + /* Finally, assign the storage pointers. */ + Hrtf->mFields = field_; + Hrtf->mElev = elev_; + Hrtf->mCoeffs = coeffs_; + Hrtf->mDelays = delays_; return Hrtf; } -void MirrorLeftHrirs(const al::span elevs, HrirArray *coeffs, - ubyte2 *delays) +void MirrorLeftHrirs(const al::span elevs, al::span coeffs, + al::span delays) { for(const auto &elev : elevs) { @@ -477,11 +510,11 @@ T> readle(std::istream &data) static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8"); static_assert(num_bits <= sizeof(T)*8, "num_bits is too large for the type"); - T ret{}; - if(!data.read(reinterpret_cast(&ret), num_bits/8)) + alignas(T) std::array ret{}; + if(!data.read(ret.data(), num_bits/8)) return static_cast(EOF); - return fixsign(ret); + return fixsign(al::bit_cast(ret)); } template @@ -491,13 +524,12 @@ T> readle(std::istream &data) static_assert((num_bits&7) == 0, "num_bits must be a multiple of 8"); static_assert(num_bits <= sizeof(T)*8, "num_bits is too large for the type"); - T ret{}; - std::byte b[sizeof(T)]{}; - if(!data.read(reinterpret_cast(b), num_bits/8)) + alignas(T) std::array ret{}; + if(!data.read(ret.data(), num_bits/8)) return static_cast(EOF); - std::reverse_copy(std::begin(b), std::end(b), reinterpret_cast(&ret)); + std::reverse(ret.begin(), ret.end()); - return fixsign(ret); + return fixsign(al::bit_cast(ret)); } template<> @@ -505,27 +537,24 @@ inline uint8_t readle(std::istream &data) { return static_cast(data.get()); } -std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) +std::unique_ptr LoadHrtf00(std::istream &data) { uint rate{readle(data)}; ushort irCount{readle(data)}; ushort irSize{readle(data)}; ubyte evCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(irSize < MinIrLength || irSize > HrirLength) { - ERR("Unsupported HRIR size, irSize=%d (%d to %d)\n", irSize, MinIrLength, HrirLength); + ERR("Unsupported HRIR size, irSize={} ({} to {})", irSize, MinIrLength, HrirLength); return nullptr; } if(evCount < MinEvCount || evCount > MaxEvCount) { - ERR("Unsupported elevation count: evCount=%d (%d to %d)\n", - evCount, MinEvCount, MaxEvCount); + ERR("Unsupported elevation count: evCount={} ({} to {})", evCount, MinEvCount, + MaxEvCount); return nullptr; } @@ -533,23 +562,21 @@ std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) for(auto &elev : elevs) elev.irOffset = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{1};i < evCount;i++) { if(elevs[i].irOffset <= elevs[i-1].irOffset) { - ERR("Invalid evOffset: evOffset[%zu]=%d (last=%d)\n", i, elevs[i].irOffset, + ERR("Invalid evOffset: evOffset[{}]={} (last={})", i, elevs[i].irOffset, elevs[i-1].irOffset); return nullptr; } } if(irCount <= elevs.back().irOffset) { - ERR("Invalid evOffset: evOffset[%zu]=%d (irCount=%d)\n", - elevs.size()-1, elevs.back().irOffset, irCount); + ERR("Invalid evOffset: evOffset[{}]={} (irCount={})", elevs.size()-1, + elevs.back().irOffset, irCount); return nullptr; } @@ -558,16 +585,16 @@ std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) elevs[i-1].azCount = static_cast(elevs[i].irOffset - elevs[i-1].irOffset); if(elevs[i-1].azCount < MinAzCount || elevs[i-1].azCount > MaxAzCount) { - ERR("Unsupported azimuth count: azCount[%zd]=%d (%d to %d)\n", - i-1, elevs[i-1].azCount, MinAzCount, MaxAzCount); + ERR("Unsupported azimuth count: azCount[{}]={} ({} to {})", i-1, elevs[i-1].azCount, + MinAzCount, MaxAzCount); return nullptr; } } elevs.back().azCount = static_cast(irCount - elevs.back().irOffset); if(elevs.back().azCount < MinAzCount || elevs.back().azCount > MaxAzCount) { - ERR("Unsupported azimuth count: azCount[%zu]=%d (%d to %d)\n", - elevs.size()-1, elevs.back().azCount, MinAzCount, MaxAzCount); + ERR("Unsupported azimuth count: azCount[{}]={} ({} to {})", elevs.size()-1, + elevs.back().azCount, MinAzCount, MaxAzCount); return nullptr; } @@ -575,54 +602,49 @@ std::unique_ptr LoadHrtf00(std::istream &data, const char *filename) auto delays = std::vector(irCount); for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) - val[0] = readle(data) / 32768.0f; + for(auto &val : al::span{hrir}.first(irSize)) + val[0] = float(readle(data)) / 32768.0f; } for(auto &val : delays) val[0] = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{0};i < irCount;i++) { if(delays[i][0] > MaxHrirDelay) { - ERR("Invalid delays[%zd]: %d (%d)\n", i, delays[i][0], MaxHrirDelay); + ERR("Invalid delays[{}]: {} ({})", i, delays[i][0], MaxHrirDelay); return nullptr; } delays[i][0] <<= HrirDelayFracBits; } /* Mirror the left ear responses to the right ear. */ - MirrorLeftHrirs({elevs.data(), elevs.size()}, coeffs.data(), delays.data()); + MirrorLeftHrirs(elevs, coeffs, delays); - const HrtfStore::Field field[1]{{0.0f, evCount}}; - return CreateHrtfStore(rate, static_cast(irSize), field, {elevs.data(), elevs.size()}, - coeffs.data(), delays.data(), filename); + const std::array field{HrtfStore::Field{0.0f, evCount}}; + return CreateHrtfStore(rate, static_cast(irSize), field, elevs, coeffs.data(), + delays.data()); } -std::unique_ptr LoadHrtf01(std::istream &data, const char *filename) +std::unique_ptr LoadHrtf01(std::istream &data) { uint rate{readle(data)}; uint8_t irSize{readle(data)}; ubyte evCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(irSize < MinIrLength || irSize > HrirLength) { - ERR("Unsupported HRIR size, irSize=%d (%d to %d)\n", irSize, MinIrLength, HrirLength); + ERR("Unsupported HRIR size, irSize={} ({} to {})", irSize, MinIrLength, HrirLength); return nullptr; } if(evCount < MinEvCount || evCount > MaxEvCount) { - ERR("Unsupported elevation count: evCount=%d (%d to %d)\n", - evCount, MinEvCount, MaxEvCount); + ERR("Unsupported elevation count: evCount={} ({} to {})", evCount, MinEvCount, + MaxEvCount); return nullptr; } @@ -630,15 +652,13 @@ std::unique_ptr LoadHrtf01(std::istream &data, const char *filename) for(auto &elev : elevs) elev.azCount = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{0};i < evCount;++i) { if(elevs[i].azCount < MinAzCount || elevs[i].azCount > MaxAzCount) { - ERR("Unsupported azimuth count: azCount[%zd]=%d (%d to %d)\n", i, elevs[i].azCount, + ERR("Unsupported azimuth count: azCount[{}]={} ({} to {})", i, elevs[i].azCount, MinAzCount, MaxAzCount); return nullptr; } @@ -653,40 +673,37 @@ std::unique_ptr LoadHrtf01(std::istream &data, const char *filename) auto delays = std::vector(irCount); for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) - val[0] = readle(data) / 32768.0f; + for(auto &val : al::span{hrir}.first(irSize)) + val[0] = float(readle(data)) / 32768.0f; } for(auto &val : delays) val[0] = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{0};i < irCount;i++) { if(delays[i][0] > MaxHrirDelay) { - ERR("Invalid delays[%zd]: %d (%d)\n", i, delays[i][0], MaxHrirDelay); + ERR("Invalid delays[{}]: {} ({})", i, delays[i][0], MaxHrirDelay); return nullptr; } delays[i][0] <<= HrirDelayFracBits; } /* Mirror the left ear responses to the right ear. */ - MirrorLeftHrirs({elevs.data(), elevs.size()}, coeffs.data(), delays.data()); + MirrorLeftHrirs(elevs, coeffs, delays); - const HrtfStore::Field field[1]{{0.0f, evCount}}; - return CreateHrtfStore(rate, irSize, field, {elevs.data(), elevs.size()}, coeffs.data(), - delays.data(), filename); + const std::array field{HrtfStore::Field{0.0f, evCount}}; + return CreateHrtfStore(rate, irSize, field, elevs, coeffs.data(), delays.data()); } -std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) +std::unique_ptr LoadHrtf02(std::istream &data) { - constexpr ubyte SampleType_S16{0}; - constexpr ubyte SampleType_S24{1}; - constexpr ubyte ChanType_LeftOnly{0}; - constexpr ubyte ChanType_LeftRight{1}; + static constexpr ubyte SampleType_S16{0}; + static constexpr ubyte SampleType_S24{1}; + static constexpr ubyte ChanType_LeftOnly{0}; + static constexpr ubyte ChanType_LeftRight{1}; uint rate{readle(data)}; ubyte sampleType{readle(data)}; @@ -694,30 +711,27 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) uint8_t irSize{readle(data)}; ubyte fdCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(sampleType > SampleType_S24) { - ERR("Unsupported sample type: %d\n", sampleType); + ERR("Unsupported sample type: {}", sampleType); return nullptr; } if(channelType > ChanType_LeftRight) { - ERR("Unsupported channel type: %d\n", channelType); + ERR("Unsupported channel type: {}", channelType); return nullptr; } if(irSize < MinIrLength || irSize > HrirLength) { - ERR("Unsupported HRIR size, irSize=%d (%d to %d)\n", irSize, MinIrLength, HrirLength); + ERR("Unsupported HRIR size, irSize={} ({} to {})", irSize, MinIrLength, HrirLength); return nullptr; } if(fdCount < 1 || fdCount > MaxFdCount) { - ERR("Unsupported number of field-depths: fdCount=%d (%d to %d)\n", fdCount, MinFdCount, + ERR("Unsupported number of field-depths: fdCount={} ({} to {})", fdCount, MinFdCount, MaxFdCount); return nullptr; } @@ -729,48 +743,42 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) const ushort distance{readle(data)}; const ubyte evCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(distance < MinFdDistance || distance > MaxFdDistance) { - ERR("Unsupported field distance[%zu]=%d (%d to %d millimeters)\n", f, distance, + ERR("Unsupported field distance[{}]={} ({} to {} millimeters)", f, distance, MinFdDistance, MaxFdDistance); return nullptr; } if(evCount < MinEvCount || evCount > MaxEvCount) { - ERR("Unsupported elevation count: evCount[%zu]=%d (%d to %d)\n", f, evCount, + ERR("Unsupported elevation count: evCount[{}]={} ({} to {})", f, evCount, MinEvCount, MaxEvCount); return nullptr; } - fields[f].distance = distance / 1000.0f; + fields[f].distance = float(distance) / 1000.0f; fields[f].evCount = evCount; if(f > 0 && fields[f].distance <= fields[f-1].distance) { - ERR("Field distance[%zu] is not after previous (%f > %f)\n", f, fields[f].distance, + ERR("Field distance[{}] is not after previous ({:f} > {:f})", f, fields[f].distance, fields[f-1].distance); return nullptr; } const size_t ebase{elevs.size()}; elevs.resize(ebase + evCount); - for(auto &elev : al::span(elevs.data()+ebase, evCount)) + for(auto &elev : al::span{elevs}.subspan(ebase, evCount)) elev.azCount = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; for(size_t e{0};e < evCount;e++) { if(elevs[ebase+e].azCount < MinAzCount || elevs[ebase+e].azCount > MaxAzCount) { - ERR("Unsupported azimuth count: azCount[%zu][%zu]=%d (%d to %d)\n", f, e, + ERR("Unsupported azimuth count: azCount[{}][{}]={} ({} to {})", f, e, elevs[ebase+e].azCount, MinAzCount, MaxAzCount); return nullptr; } @@ -795,37 +803,35 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) { for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) - val[0] = readle(data) / 32768.0f; + for(auto &val : al::span{hrir}.first(irSize)) + val[0] = float(readle(data)) / 32768.0f; } } else if(sampleType == SampleType_S24) { for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) + for(auto &val : al::span{hrir}.first(irSize)) val[0] = static_cast(readle(data)) / 8388608.0f; } } for(auto &val : delays) val[0] = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{0};i < irTotal;++i) { if(delays[i][0] > MaxHrirDelay) { - ERR("Invalid delays[%zu][0]: %d (%d)\n", i, delays[i][0], MaxHrirDelay); + ERR("Invalid delays[{}][0]: {} ({})", i, delays[i][0], MaxHrirDelay); return nullptr; } delays[i][0] <<= HrirDelayFracBits; } /* Mirror the left ear responses to the right ear. */ - MirrorLeftHrirs({elevs.data(), elevs.size()}, coeffs.data(), delays.data()); + MirrorLeftHrirs(elevs, coeffs, delays); } else if(channelType == ChanType_LeftRight) { @@ -833,10 +839,10 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) { for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) + for(auto &val : al::span{hrir}.first(irSize)) { - val[0] = readle(data) / 32768.0f; - val[1] = readle(data) / 32768.0f; + val[0] = float(readle(data)) / 32768.0f; + val[1] = float(readle(data)) / 32768.0f; } } } @@ -844,7 +850,7 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) { for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) + for(auto &val : al::span{hrir}.first(irSize)) { val[0] = static_cast(readle(data)) / 8388608.0f; val[1] = static_cast(readle(data)) / 8388608.0f; @@ -857,21 +863,18 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) val[1] = readle(data); } if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; for(size_t i{0};i < irTotal;++i) { if(delays[i][0] > MaxHrirDelay) { - ERR("Invalid delays[%zu][0]: %d (%d)\n", i, delays[i][0], MaxHrirDelay); + ERR("Invalid delays[{}][0]: {} ({})", i, delays[i][0], MaxHrirDelay); return nullptr; } if(delays[i][1] > MaxHrirDelay) { - ERR("Invalid delays[%zu][1]: %d (%d)\n", i, delays[i][1], MaxHrirDelay); + ERR("Invalid delays[{}][1]: {} ({})", i, delays[i][1], MaxHrirDelay); return nullptr; } delays[i][0] <<= HrirDelayFracBits; @@ -893,16 +896,16 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) * count. Reverse the order of the groups, keeping the relative order * of per-group azimuth counts. */ - auto elevs__end = elevs_.end(); - auto copy_azs = [&elevs,&elevs__end](const ptrdiff_t ebase, const HrtfStore::Field &field) + auto elevs_end = elevs_.end(); + auto copy_azs = [&elevs,&elevs_end](const ptrdiff_t ebase, const HrtfStore::Field &field) -> ptrdiff_t { auto elevs_src = elevs.begin()+ebase; - elevs__end = std::copy_backward(elevs_src, elevs_src+field.evCount, elevs__end); + elevs_end = std::copy_backward(elevs_src, elevs_src+field.evCount, elevs_end); return ebase + field.evCount; }; - (void)std::accumulate(fields.cbegin(), fields.cend(), ptrdiff_t{0}, copy_azs); - assert(elevs_.begin() == elevs__end); + std::ignore = std::accumulate(fields.cbegin(), fields.cend(), ptrdiff_t{0}, copy_azs); + assert(elevs_.begin() == elevs_end); /* Reestablish the IR offset for each elevation index, given the new * ordering of elevations. @@ -922,12 +925,13 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) auto copy_irs = [&elevs,&coeffs,&delays,&coeffs_end,&delays_end]( const ptrdiff_t ebase, const HrtfStore::Field &field) -> ptrdiff_t { - auto accum_az = [](int count, const HrtfStore::Elevation &elev) noexcept -> int + auto accum_az = [](const ptrdiff_t count, const HrtfStore::Elevation &elev) noexcept + -> ptrdiff_t { return count + elev.azCount; }; - const auto elevs_mid = elevs.cbegin() + ebase; - const auto elevs_end = elevs_mid + field.evCount; - const int abase{std::accumulate(elevs.cbegin(), elevs_mid, 0, accum_az)}; - const int num_azs{std::accumulate(elevs_mid, elevs_end, 0, accum_az)}; + const auto elev_mid = elevs.cbegin() + ebase; + const auto abase = std::accumulate(elevs.cbegin(), elev_mid, ptrdiff_t{0}, accum_az); + const auto num_azs = std::accumulate(elev_mid, elev_mid + field.evCount, ptrdiff_t{0}, + accum_az); coeffs_end = std::copy_backward(coeffs.cbegin() + abase, coeffs.cbegin() + (abase+num_azs), coeffs_end); @@ -936,7 +940,7 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) return ebase + field.evCount; }; - (void)std::accumulate(fields.cbegin(), fields.cend(), ptrdiff_t{0}, copy_irs); + std::ignore = std::accumulate(fields.cbegin(), fields.cend(), ptrdiff_t{0}, copy_irs); assert(coeffs_.begin() == coeffs_end); assert(delays_.begin() == delays_end); @@ -946,39 +950,35 @@ std::unique_ptr LoadHrtf02(std::istream &data, const char *filename) delays = std::move(delays_); } - return CreateHrtfStore(rate, irSize, {fields.data(), fields.size()}, - {elevs.data(), elevs.size()}, coeffs.data(), delays.data(), filename); + return CreateHrtfStore(rate, irSize, fields, elevs, coeffs.data(), delays.data()); } -std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) +std::unique_ptr LoadHrtf03(std::istream &data) { - constexpr ubyte ChanType_LeftOnly{0}; - constexpr ubyte ChanType_LeftRight{1}; + static constexpr ubyte ChanType_LeftOnly{0}; + static constexpr ubyte ChanType_LeftRight{1}; uint rate{readle(data)}; ubyte channelType{readle(data)}; uint8_t irSize{readle(data)}; ubyte fdCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(channelType > ChanType_LeftRight) { - ERR("Unsupported channel type: %d\n", channelType); + ERR("Unsupported channel type: {}", channelType); return nullptr; } if(irSize < MinIrLength || irSize > HrirLength) { - ERR("Unsupported HRIR size, irSize=%d (%d to %d)\n", irSize, MinIrLength, HrirLength); + ERR("Unsupported HRIR size, irSize={} ({} to {})", irSize, MinIrLength, HrirLength); return nullptr; } if(fdCount < 1 || fdCount > MaxFdCount) { - ERR("Unsupported number of field-depths: fdCount=%d (%d to %d)\n", fdCount, MinFdCount, + ERR("Unsupported number of field-depths: fdCount={} ({} to {})", fdCount, MinFdCount, MaxFdCount); return nullptr; } @@ -990,48 +990,42 @@ std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) const ushort distance{readle(data)}; const ubyte evCount{readle(data)}; if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; if(distance < MinFdDistance || distance > MaxFdDistance) { - ERR("Unsupported field distance[%zu]=%d (%d to %d millimeters)\n", f, distance, + ERR("Unsupported field distance[{}]={} ({} to {} millimeters)", f, distance, MinFdDistance, MaxFdDistance); return nullptr; } if(evCount < MinEvCount || evCount > MaxEvCount) { - ERR("Unsupported elevation count: evCount[%zu]=%d (%d to %d)\n", f, evCount, + ERR("Unsupported elevation count: evCount[{}]={} ({} to {})", f, evCount, MinEvCount, MaxEvCount); return nullptr; } - fields[f].distance = distance / 1000.0f; + fields[f].distance = float(distance) / 1000.0f; fields[f].evCount = evCount; if(f > 0 && fields[f].distance > fields[f-1].distance) { - ERR("Field distance[%zu] is not before previous (%f <= %f)\n", f, fields[f].distance, - fields[f-1].distance); + ERR("Field distance[{}] is not before previous ({:f} <= {:f})", f, + fields[f].distance, fields[f-1].distance); return nullptr; } const size_t ebase{elevs.size()}; elevs.resize(ebase + evCount); - for(auto &elev : al::span(elevs.data()+ebase, evCount)) + for(auto &elev : al::span{elevs}.subspan(ebase, evCount)) elev.azCount = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; for(size_t e{0};e < evCount;e++) { if(elevs[ebase+e].azCount < MinAzCount || elevs[ebase+e].azCount > MaxAzCount) { - ERR("Unsupported azimuth count: azCount[%zu][%zu]=%d (%d to %d)\n", f, e, + ERR("Unsupported azimuth count: azCount[{}][{}]={} ({} to {})", f, e, elevs[ebase+e].azCount, MinAzCount, MaxAzCount); return nullptr; } @@ -1054,34 +1048,32 @@ std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) { for(auto &hrir : coeffs) { - for(auto &val : al::span{hrir.data(), irSize}) + for(auto &val : al::span{hrir}.first(irSize)) val[0] = static_cast(readle(data)) / 8388608.0f; } for(auto &val : delays) val[0] = readle(data); if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; + for(size_t i{0};i < irTotal;++i) { if(delays[i][0] > MaxHrirDelay<{hrir.data(), irSize}) + for(auto &val : al::span{hrir}.first(irSize)) { val[0] = static_cast(readle(data)) / 8388608.0f; val[1] = static_cast(readle(data)) / 8388608.0f; @@ -1093,107 +1085,90 @@ std::unique_ptr LoadHrtf03(std::istream &data, const char *filename) val[1] = readle(data); } if(!data || data.eof()) - { - ERR("Failed reading %s\n", filename); - return nullptr; - } + throw std::runtime_error{"Premature end of file"}; for(size_t i{0};i < irTotal;++i) { if(delays[i][0] > MaxHrirDelay< MaxHrirDelay< bool { return name == entry.mDispName; }; + auto match_name = [name](const HrtfEntry &entry) -> bool { return name == entry.mDispName; }; auto &enum_names = EnumeratedHrtfs; return std::find_if(enum_names.cbegin(), enum_names.cend(), match_name) != enum_names.cend(); } -void AddFileEntry(const std::string &filename) +void AddFileEntry(const std::string_view filename) { /* Check if this file has already been enumerated. */ auto enum_iter = std::find_if(EnumeratedHrtfs.cbegin(), EnumeratedHrtfs.cend(), - [&filename](const HrtfEntry &entry) -> bool - { return entry.mFilename == filename; }); + [filename](const HrtfEntry &entry) -> bool { return entry.mFilename == filename; }); if(enum_iter != EnumeratedHrtfs.cend()) { - TRACE("Skipping duplicate file entry %s\n", filename.c_str()); + TRACE("Skipping duplicate file entry {}", filename); return; } /* TODO: Get a human-readable name from the HRTF data (possibly coming in a - * format update). */ - size_t namepos{filename.find_last_of('/')+1}; - if(!namepos) namepos = filename.find_last_of('\\')+1; + * format update). + */ + const auto namepos = std::max(filename.rfind('/')+1, filename.rfind('\\')+1); + const auto extpos = filename.substr(namepos).rfind('.'); - size_t extpos{filename.find_last_of('.')}; - if(extpos <= namepos) extpos = std::string::npos; + const auto basename = (extpos == std::string::npos) ? + filename.substr(namepos) : filename.substr(namepos, extpos); - const std::string basename{(extpos == std::string::npos) ? - filename.substr(namepos) : filename.substr(namepos, extpos-namepos)}; - std::string newname{basename}; - int count{1}; + auto count = 1; + auto newname = std::string{basename}; while(checkName(newname)) - { - newname = basename; - newname += " #"; - newname += std::to_string(++count); - } - EnumeratedHrtfs.emplace_back(HrtfEntry{newname, filename}); - const HrtfEntry &entry = EnumeratedHrtfs.back(); + newname = fmt::format("{} #{}", basename, ++count); - TRACE("Adding file entry \"%s\"\n", entry.mFilename.c_str()); + const auto &entry = EnumeratedHrtfs.emplace_back(newname, filename); + TRACE("Adding file entry \"{}\"", entry.mFilename); } /* Unfortunate that we have to duplicate AddFileEntry to take a memory buffer * for input instead of opening the given filename. */ -void AddBuiltInEntry(const std::string &dispname, uint residx) +void AddBuiltInEntry(const std::string_view dispname, uint residx) { - const std::string filename{'!'+std::to_string(residx)+'_'+dispname}; + auto filename = fmt::format("!{}_{}", residx, dispname); auto enum_iter = std::find_if(EnumeratedHrtfs.cbegin(), EnumeratedHrtfs.cend(), - [&filename](const HrtfEntry &entry) -> bool - { return entry.mFilename == filename; }); + [&filename](const HrtfEntry &entry) -> bool { return entry.mFilename == filename; }); if(enum_iter != EnumeratedHrtfs.cend()) { - TRACE("Skipping duplicate file entry %s\n", filename.c_str()); + TRACE("Skipping duplicate file entry {}", filename); return; } /* TODO: Get a human-readable name from the HRTF data (possibly coming in a * format update). */ - std::string newname{dispname}; - int count{1}; + auto count = 1; + auto newname = std::string{dispname}; while(checkName(newname)) - { - newname = dispname; - newname += " #"; - newname += std::to_string(++count); - } - EnumeratedHrtfs.emplace_back(HrtfEntry{newname, filename}); - const HrtfEntry &entry = EnumeratedHrtfs.back(); + newname = fmt::format("{} #{}", dispname, ++count); - TRACE("Adding built-in entry \"%s\"\n", entry.mFilename.c_str()); + const auto &entry = EnumeratedHrtfs.emplace_back(std::move(newname), std::move(filename)); + TRACE("Adding built-in entry \"{}\"", entry.mFilename); } @@ -1206,6 +1181,7 @@ al::span GetResource(int /*name*/) #else +/* NOLINTNEXTLINE(*-avoid-c-arrays) */ constexpr unsigned char hrtf_default[]{ #include "default_hrtf.txt" }; @@ -1223,47 +1199,46 @@ al::span GetResource(int name) std::vector EnumerateHrtf(std::optional pathopt) { - std::lock_guard _{EnumeratedHrtfLock}; + std::lock_guard enumlock{EnumeratedHrtfLock}; EnumeratedHrtfs.clear(); + for(const auto &fname : SearchDataFiles(".mhr"sv)) + AddFileEntry(fname); + bool usedefaults{true}; if(pathopt) { - const char *pathlist{pathopt->c_str()}; - while(pathlist && *pathlist) + std::string_view pathlist{*pathopt}; + while(!pathlist.empty()) { - const char *next, *end; - - while(isspace(*pathlist) || *pathlist == ',') - pathlist++; - if(*pathlist == '\0') - continue; + while(!pathlist.empty() && (std::isspace(pathlist.front()) || pathlist.front() == ',')) + pathlist.remove_prefix(1); + if(pathlist.empty()) + break; - next = strchr(pathlist, ','); - if(next) - end = next++; + auto endpos = std::min(pathlist.find(','), pathlist.size()); + auto entry = pathlist.substr(0, endpos); + if(endpos < pathlist.size()) + pathlist.remove_prefix(++endpos); else { - end = pathlist + strlen(pathlist); + pathlist.remove_prefix(endpos); usedefaults = false; } - while(end != pathlist && isspace(*(end-1))) - --end; - if(end != pathlist) + while(!entry.empty() && std::isspace(entry.back())) + entry.remove_suffix(1); + if(!entry.empty()) { - const std::string pname{pathlist, end}; - for(const auto &fname : SearchDataFiles(".mhr", pname.c_str())) + for(const auto &fname : SearchDataFiles(".mhr"sv, entry)) AddFileEntry(fname); } - - pathlist = next; } } if(usedefaults) { - for(const auto &fname : SearchDataFiles(".mhr", "openal/hrtf")) + for(const auto &fname : SearchDataFiles(".mhr"sv, "openal/hrtf"sv)) AddFileEntry(fname); if(!GetResource(IDR_DEFAULT_HRTF_MHR).empty()) @@ -1278,94 +1253,101 @@ std::vector EnumerateHrtf(std::optional pathopt) return list; } -HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) -{ - std::lock_guard _{EnumeratedHrtfLock}; +HrtfStorePtr GetLoadedHrtf(const std::string_view name, const uint devrate) +try { + if(devrate > MaxSampleRate) + { + WARN("Device sample rate too large for HRTF ({}hz > {}hz)", devrate, MaxSampleRate); + return nullptr; + } + std::lock_guard enumlock{EnumeratedHrtfLock}; auto entry_iter = std::find_if(EnumeratedHrtfs.cbegin(), EnumeratedHrtfs.cend(), - [&name](const HrtfEntry &entry) -> bool { return entry.mDispName == name; }); + [name](const HrtfEntry &entry) -> bool { return entry.mDispName == name; }); if(entry_iter == EnumeratedHrtfs.cend()) return nullptr; const std::string &fname = entry_iter->mFilename; - std::lock_guard __{LoadedHrtfLock}; - auto hrtf_lt_fname = [](LoadedHrtf &hrtf, const std::string &filename) -> bool - { return hrtf.mFilename < filename; }; + std::lock_guard loadlock{LoadedHrtfLock}; + auto hrtf_lt_fname = [devrate](LoadedHrtf &hrtf, const std::string_view filename) -> bool + { + return hrtf.mSampleRate < devrate + || (hrtf.mSampleRate == devrate && hrtf.mFilename < filename); + }; auto handle = std::lower_bound(LoadedHrtfs.begin(), LoadedHrtfs.end(), fname, hrtf_lt_fname); - while(handle != LoadedHrtfs.end() && handle->mFilename == fname) + if(handle != LoadedHrtfs.end() && handle->mSampleRate == devrate && handle->mFilename == fname) { - HrtfStore *hrtf{handle->mEntry.get()}; - if(hrtf && hrtf->mSampleRate == devrate) + if(HrtfStore *hrtf{handle->mEntry.get()}) { + assert(hrtf->mSampleRate == devrate); hrtf->add_ref(); return HrtfStorePtr{hrtf}; } - ++handle; } std::unique_ptr stream; int residx{}; char ch{}; + /* NOLINTNEXTLINE(cert-err34-c,cppcoreguidelines-pro-type-vararg) */ if(sscanf(fname.c_str(), "!%d%c", &residx, &ch) == 2 && ch == '_') { - TRACE("Loading %s...\n", fname.c_str()); + TRACE("Loading {}...", fname); al::span res{GetResource(residx)}; if(res.empty()) { - ERR("Could not get resource %u, %s\n", residx, name.c_str()); + ERR("Could not get resource {}, {}", residx, name); return nullptr; } - stream = std::make_unique(res.begin(), res.end()); + /* NOLINTNEXTLINE(*-const-cast) */ + stream = std::make_unique(al::span{const_cast(res.data()), res.size()}); } else { - TRACE("Loading %s...\n", fname.c_str()); - auto fstr = std::make_unique(fname.c_str(), std::ios::binary); + TRACE("Loading {}...", fname); + auto fstr = std::make_unique(fs::u8path(fname), + std::ios::binary); if(!fstr->is_open()) { - ERR("Could not open %s\n", fname.c_str()); + ERR("Could not open {}", fname); return nullptr; } stream = std::move(fstr); } - std::unique_ptr hrtf; - char magic[sizeof(magicMarker03)]; - stream->read(magic, sizeof(magic)); - if(stream->gcount() < static_cast(sizeof(magicMarker03))) - ERR("%s data is too short (%zu bytes)\n", name.c_str(), stream->gcount()); - else if(memcmp(magic, magicMarker03, sizeof(magicMarker03)) == 0) + auto hrtf = std::unique_ptr{}; + auto magic = std::array{}; + stream->read(magic.data(), magic.size()); + if(stream->gcount() < std::streamsize{magic.size()}) + ERR("{} data is too short ({} bytes)", name, stream->gcount()); + else if(GetMarker03Name() == std::string_view{magic.data(), magic.size()}) { - TRACE("Detected data set format v3\n"); - hrtf = LoadHrtf03(*stream, name.c_str()); + TRACE("Detected data set format v3"); + hrtf = LoadHrtf03(*stream); } - else if(memcmp(magic, magicMarker02, sizeof(magicMarker02)) == 0) + else if(GetMarker02Name() == std::string_view{magic.data(), magic.size()}) { - TRACE("Detected data set format v2\n"); - hrtf = LoadHrtf02(*stream, name.c_str()); + TRACE("Detected data set format v2"); + hrtf = LoadHrtf02(*stream); } - else if(memcmp(magic, magicMarker01, sizeof(magicMarker01)) == 0) + else if(GetMarker01Name() == std::string_view{magic.data(), magic.size()}) { - TRACE("Detected data set format v1\n"); - hrtf = LoadHrtf01(*stream, name.c_str()); + TRACE("Detected data set format v1"); + hrtf = LoadHrtf01(*stream); } - else if(memcmp(magic, magicMarker00, sizeof(magicMarker00)) == 0) + else if(GetMarker00Name() == std::string_view{magic.data(), magic.size()}) { - TRACE("Detected data set format v0\n"); - hrtf = LoadHrtf00(*stream, name.c_str()); + TRACE("Detected data set format v0"); + hrtf = LoadHrtf00(*stream); } else - ERR("Invalid header in %s: \"%.8s\"\n", name.c_str(), magic); + ERR("Invalid header in {}: \"{}\"", name, std::string_view{magic.data(), magic.size()}); stream.reset(); if(!hrtf) - { - ERR("Failed to load %s\n", name.c_str()); return nullptr; - } if(hrtf->mSampleRate != devrate) { - TRACE("Resampling HRTF %s (%uhz -> %uhz)\n", name.c_str(), hrtf->mSampleRate, devrate); + TRACE("Resampling HRTF {} ({}hz -> {}hz)", name, uint{hrtf->mSampleRate}, devrate); /* Calculate the last elevation's index and get the total IR count. */ const size_t lastEv{std::accumulate(hrtf->mFields.begin(), hrtf->mFields.end(), 0_uz, @@ -1375,17 +1357,18 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) const size_t irCount{size_t{hrtf->mElev[lastEv].irOffset} + hrtf->mElev[lastEv].azCount}; /* Resample all the IRs. */ - std::array,2> inout; + std::array,2> inout{}; PPhaseResampler rs; rs.init(hrtf->mSampleRate, devrate); for(size_t i{0};i < irCount;++i) { - HrirArray &coeffs = const_cast(hrtf->mCoeffs[i]); + /* NOLINTNEXTLINE(*-const-cast) */ + auto coeffs = al::span{const_cast(hrtf->mCoeffs[i])}; for(size_t j{0};j < 2;++j) { std::transform(coeffs.cbegin(), coeffs.cend(), inout[0].begin(), [j](const float2 &in) noexcept -> double { return in[j]; }); - rs.process(HrirLength, inout[0].data(), HrirLength, inout[1].data()); + rs.process(inout[0], inout[1]); for(size_t k{0};k < HrirLength;++k) coeffs[k][j] = static_cast(inout[1][k]); } @@ -1400,9 +1383,9 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) { for(size_t j{0};j < 2;++j) { - const float new_delay{std::round(hrtf->mDelays[i][j] * rate_scale) / + const float new_delay{std::round(float(hrtf->mDelays[i][j]) * rate_scale) / float{HrirDelayFracOne}}; - max_delay = maxf(max_delay, new_delay); + max_delay = std::max(max_delay, new_delay); new_delays[i][j] = new_delay; } } @@ -1414,54 +1397,60 @@ HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate) float delay_scale{HrirDelayFracOne}; if(max_delay > MaxHrirDelay) { - WARN("Resampled delay exceeds max (%.2f > %d)\n", max_delay, MaxHrirDelay); + WARN("Resampled delay exceeds max ({:.2f} > {})", max_delay, MaxHrirDelay); delay_scale *= float{MaxHrirDelay} / max_delay; } for(size_t i{0};i < irCount;++i) { - ubyte2 &delays = const_cast(hrtf->mDelays[i]); - for(size_t j{0};j < 2;++j) - delays[j] = static_cast(float2int(new_delays[i][j]*delay_scale + 0.5f)); + /* NOLINTNEXTLINE(*-const-cast) */ + auto delays = al::span{const_cast(hrtf->mDelays[i])}; + std::transform(new_delays[i].cbegin(), new_delays[i].cend(), delays.begin(), + [delay_scale](const float delay) + { return static_cast(float2int(delay*delay_scale + 0.5f)); }); } /* Scale the IR size for the new sample rate and update the stored * sample rate. */ const float newIrSize{std::round(static_cast(hrtf->mIrSize) * rate_scale)}; - hrtf->mIrSize = static_cast(minf(HrirLength, newIrSize)); + hrtf->mIrSize = static_cast(std::min(float{HrirLength}, newIrSize)); hrtf->mSampleRate = devrate & 0xff'ff'ff; } - TRACE("Loaded HRTF %s for sample rate %uhz, %u-sample filter\n", name.c_str(), - hrtf->mSampleRate, hrtf->mIrSize); - handle = LoadedHrtfs.emplace(handle, fname, std::move(hrtf)); + handle = LoadedHrtfs.emplace(handle, fname, devrate, std::move(hrtf)); + TRACE("Loaded HRTF {} for sample rate {}hz, {}-sample filter", name, + uint{handle->mEntry->mSampleRate}, uint{handle->mEntry->mIrSize}); return HrtfStorePtr{handle->mEntry.get()}; } +catch(std::exception& e) { + ERR("Failed to load {}: {}", name, e.what()); + return nullptr; +} void HrtfStore::add_ref() { auto ref = IncrementRef(mRef); - TRACE("HrtfStore %p increasing refcount to %u\n", decltype(std::declval()){this}, ref); + TRACE("HrtfStore {} increasing refcount to {}", decltype(std::declval()){this}, ref); } void HrtfStore::dec_ref() { auto ref = DecrementRef(mRef); - TRACE("HrtfStore %p decreasing refcount to %u\n", decltype(std::declval()){this}, ref); + TRACE("HrtfStore {} decreasing refcount to {}", decltype(std::declval()){this}, ref); if(ref == 0) { - std::lock_guard _{LoadedHrtfLock}; + std::lock_guard loadlock{LoadedHrtfLock}; /* Go through and remove all unused HRTFs. */ auto remove_unused = [](LoadedHrtf &hrtf) -> bool { HrtfStore *entry{hrtf.mEntry.get()}; - if(entry && ReadRef(entry->mRef) == 0) + if(entry && entry->mRef.load() == 0) { - TRACE("Unloading unused HRTF %s\n", hrtf.mFilename.data()); + TRACE("Unloading unused HRTF {}", hrtf.mFilename); hrtf.mEntry = nullptr; return true; } diff --git a/3rdparty/openal/core/hrtf.h b/3rdparty/openal/core/hrtf.h index 5e6e09a8c3bd..020e3077a11a 100644 --- a/3rdparty/openal/core/hrtf.h +++ b/3rdparty/openal/core/hrtf.h @@ -6,19 +6,20 @@ #include #include #include +#include #include #include "almalloc.h" #include "alspan.h" -#include "atomic.h" #include "ambidefs.h" #include "bufferline.h" -#include "mixer/hrtfdefs.h" +#include "flexarray.h" #include "intrusive_ptr.h" +#include "mixer/hrtfdefs.h" -struct HrtfStore { - RefCount mRef; +struct alignas(16) HrtfStore { + std::atomic mRef{}; uint mSampleRate : 24; uint mIrSize : 8; @@ -36,17 +37,24 @@ struct HrtfStore { ushort azCount; ushort irOffset; }; - Elevation *mElev; - const HrirArray *mCoeffs; - const ubyte2 *mDelays; + al::span mElev; + al::span mCoeffs; + al::span mDelays; - void getCoeffs(float elevation, float azimuth, float distance, float spread, HrirArray &coeffs, - const al::span delays); + void getCoeffs(float elevation, float azimuth, float distance, float spread, + const HrirSpan coeffs, const al::span delays) const; void add_ref(); void dec_ref(); - DEF_PLACE_NEWDEL() + void *operator new(size_t) = delete; + void *operator new[](size_t) = delete; + void operator delete[](void*) noexcept = delete; + + void operator delete(gsl::owner block, void*) noexcept + { ::operator delete[](block, std::align_val_t{alignof(HrtfStore)}); } + void operator delete(gsl::owner block) noexcept + { ::operator delete[](block, std::align_val_t{alignof(HrtfStore)}); } }; using HrtfStorePtr = al::intrusive_ptr; @@ -60,13 +68,13 @@ struct AngularPoint { struct DirectHrtfState { - std::array mTemp; + std::array mTemp{}; /* HRTF filter state for dry buffer content */ uint mIrSize{0}; al::FlexArray mChannels; - DirectHrtfState(size_t numchans) : mChannels{numchans} { } + explicit DirectHrtfState(size_t numchans) : mChannels{numchans} { } /** * Produces HRTF filter coefficients for decoding B-Format, given a set of * virtual speaker positions, a matching decoding matrix, and per-order @@ -74,7 +82,8 @@ struct DirectHrtfState { * are ordered and scaled according to the matrix input. */ void build(const HrtfStore *Hrtf, const uint irSize, const bool perHrirMin, - const al::span AmbiPoints, const float (*AmbiMatrix)[MaxAmbiChannels], + const al::span AmbiPoints, + const al::span> AmbiMatrix, const float XOverFreq, const al::span AmbiOrderHFGain); static std::unique_ptr Create(size_t num_chans); @@ -84,6 +93,6 @@ struct DirectHrtfState { std::vector EnumerateHrtf(std::optional pathopt); -HrtfStorePtr GetLoadedHrtf(const std::string &name, const uint devrate); +HrtfStorePtr GetLoadedHrtf(const std::string_view name, const uint devrate); #endif /* CORE_HRTF_H */ diff --git a/3rdparty/openal/core/logging.cpp b/3rdparty/openal/core/logging.cpp index 56ad0a0dba45..ba40b36865d0 100644 --- a/3rdparty/openal/core/logging.cpp +++ b/3rdparty/openal/core/logging.cpp @@ -10,9 +10,10 @@ #include #include #include -#include +#include +#include -#include "alspan.h" +#include "alstring.h" #include "strutils.h" @@ -34,6 +35,8 @@ LogLevel gLogLevel{LogLevel::Error}; namespace { +using namespace std::string_view_literals; + enum class LogState : uint8_t { FirstRun, Ready, @@ -46,7 +49,7 @@ LogState gLogState{LogState::FirstRun}; LogCallbackFunc gLogCallback{}; void *gLogCallbackPtr{}; -constexpr std::optional GetLevelCode(LogLevel level) +constexpr auto GetLevelCode(LogLevel level) noexcept -> std::optional { switch(level) { @@ -75,55 +78,23 @@ void al_set_log_callback(LogCallbackFunc callback, void *userptr) } } -void al_print(LogLevel level, const char *fmt, ...) +void al_print_impl(LogLevel level, const fmt::string_view fmt, fmt::format_args args) { - /* Kind of ugly since string literals are const char arrays with a size - * that includes the null terminator, which we want to exclude from the - * span. - */ - auto prefix = al::span{"[ALSOFT] (--) "}.first<14>(); + const auto msg = fmt::vformat(fmt, std::move(args)); + + auto prefix = "[ALSOFT] (--) "sv; switch(level) { case LogLevel::Disable: break; - case LogLevel::Error: prefix = al::span{"[ALSOFT] (EE) "}.first<14>(); break; - case LogLevel::Warning: prefix = al::span{"[ALSOFT] (WW) "}.first<14>(); break; - case LogLevel::Trace: prefix = al::span{"[ALSOFT] (II) "}.first<14>(); break; - } - - std::vector dynmsg; - std::array stcmsg{}; - - char *str{stcmsg.data()}; - auto prefend1 = std::copy_n(prefix.begin(), prefix.size(), stcmsg.begin()); - al::span msg{prefend1, stcmsg.end()}; - - std::va_list args, args2; - va_start(args, fmt); - va_copy(args2, args); - const int msglen{std::vsnprintf(msg.data(), msg.size(), fmt, args)}; - if(msglen >= 0) - { - if(static_cast(msglen) >= msg.size()) UNLIKELY - { - dynmsg.resize(static_cast(msglen)+prefix.size() + 1u); - - str = dynmsg.data(); - auto prefend2 = std::copy_n(prefix.begin(), prefix.size(), dynmsg.begin()); - msg = {prefend2, dynmsg.end()}; - - std::vsnprintf(msg.data(), msg.size(), fmt, args2); - } - msg = msg.first(static_cast(msglen)); + case LogLevel::Error: prefix = "[ALSOFT] (EE) "sv; break; + case LogLevel::Warning: prefix = "[ALSOFT] (WW) "sv; break; + case LogLevel::Trace: prefix = "[ALSOFT] (II) "sv; break; } - else - msg = {msg.data(), std::strlen(msg.data())}; - va_end(args2); - va_end(args); if(gLogLevel >= level) { auto logfile = gLogFile; - fputs(str, logfile); + fmt::println(logfile, "{}{}", prefix, msg); fflush(logfile); } #if defined(_WIN32) && !defined(NDEBUG) @@ -131,8 +102,7 @@ void al_print(LogLevel level, const char *fmt, ...) * informational, warning, or error debug messages. So only print them for * non-Release builds. */ - std::wstring wstr{utf8_to_wstr(str)}; - OutputDebugStringW(wstr.c_str()); + OutputDebugStringW(utf8_to_wstr(fmt::format("{}{}\n", prefix, msg)).c_str()); #elif defined(__ANDROID__) auto android_severity = [](LogLevel l) noexcept { @@ -147,21 +117,18 @@ void al_print(LogLevel level, const char *fmt, ...) } return ANDROID_LOG_ERROR; }; - __android_log_print(android_severity(level), "openal", "%s", str); + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ + __android_log_print(android_severity(level), "openal", "%.*s%s", al::sizei(prefix), + prefix.data(), msg.c_str()); #endif auto cblock = std::lock_guard{LogCallbackMutex}; if(gLogState != LogState::Disable) { - while(!msg.empty() && std::isspace(msg.back())) - { - msg.back() = '\0'; - msg = msg.first(msg.size()-1); - } - if(auto logcode = GetLevelCode(level); logcode && !msg.empty()) + if(auto logcode = GetLevelCode(level)) { if(gLogCallback) - gLogCallback(gLogCallbackPtr, *logcode, msg.data(), static_cast(msg.size())); + gLogCallback(gLogCallbackPtr, *logcode, msg.data(), al::sizei(msg)); else if(gLogState == LogState::FirstRun) gLogState = LogState::Disable; } diff --git a/3rdparty/openal/core/logging.h b/3rdparty/openal/core/logging.h index 06b7cddea316..f32fd43e8aac 100644 --- a/3rdparty/openal/core/logging.h +++ b/3rdparty/openal/core/logging.h @@ -1,8 +1,9 @@ #ifndef CORE_LOGGING_H #define CORE_LOGGING_H -#include +#include +#include "fmt/core.h" #include "opthelpers.h" @@ -12,9 +13,9 @@ enum class LogLevel { Warning, Trace }; -extern LogLevel gLogLevel; +DECL_HIDDEN extern LogLevel gLogLevel; -extern FILE *gLogFile; +DECL_HIDDEN extern FILE *gLogFile; using LogCallbackFunc = void(*)(void *userptr, char level, const char *message, int length) noexcept; @@ -22,12 +23,13 @@ using LogCallbackFunc = void(*)(void *userptr, char level, const char *message, void al_set_log_callback(LogCallbackFunc callback, void *userptr); -#ifdef __USE_MINGW_ANSI_STDIO -[[gnu::format(gnu_printf,2,3)]] -#else -[[gnu::format(printf,2,3)]] -#endif -void al_print(LogLevel level, const char *fmt, ...); +void al_print_impl(LogLevel level, const fmt::string_view fmt, fmt::format_args args); + +template +void al_print(LogLevel level, fmt::format_string fmt, Args&& ...args) noexcept +try { + al_print_impl(level, fmt, fmt::make_format_args(args...)); +} catch(...) { } #define TRACE(...) al_print(LogLevel::Trace, __VA_ARGS__) diff --git a/3rdparty/openal/core/mastering.cpp b/3rdparty/openal/core/mastering.cpp index 4445719b4216..4da708ab86cd 100644 --- a/3rdparty/openal/core/mastering.cpp +++ b/3rdparty/openal/core/mastering.cpp @@ -11,7 +11,6 @@ #include #include -#include "almalloc.h" #include "alnumeric.h" #include "alspan.h" #include "opthelpers.h" @@ -20,9 +19,9 @@ /* These structures assume BufferLineSize is a power of 2. */ static_assert((BufferLineSize & (BufferLineSize-1)) == 0, "BufferLineSize is not a power of 2"); -struct SlidingHold { - alignas(16) float mValues[BufferLineSize]; - uint mExpiries[BufferLineSize]; +struct SIMDALIGN SlidingHold { + alignas(16) FloatBufferLine mValues; + std::array mExpiries; uint mLowerIndex; uint mUpperIndex; uint mLength; @@ -31,7 +30,9 @@ struct SlidingHold { namespace { -using namespace std::placeholders; +template +constexpr auto assume_aligned_span(const al::span s) noexcept -> al::span +{ return al::span{al::assume_aligned(s.data()), s.size()}; } /* This sliding hold follows the input level with an instant attack and a * fixed duration hold before an instant release to the next highest level. @@ -44,8 +45,8 @@ float UpdateSlidingHold(SlidingHold *Hold, const uint i, const float in) { static constexpr uint mask{BufferLineSize - 1}; const uint length{Hold->mLength}; - float (&values)[BufferLineSize] = Hold->mValues; - uint (&expiries)[BufferLineSize] = Hold->mExpiries; + const al::span values{Hold->mValues}; + const al::span expiries{Hold->mExpiries}; uint lowerIndex{Hold->mLowerIndex}; uint upperIndex{Hold->mUpperIndex}; @@ -60,14 +61,16 @@ float UpdateSlidingHold(SlidingHold *Hold, const uint i, const float in) } else { - do { + auto findLowerIndex = [&lowerIndex,in,values]() noexcept -> bool + { do { if(!(in >= values[lowerIndex])) - goto found_place; + return true; } while(lowerIndex--); + return false; + }; + while(!findLowerIndex()) lowerIndex = mask; - } while(true); - found_place: lowerIndex = (lowerIndex + 1) & mask; values[lowerIndex] = in; @@ -82,38 +85,42 @@ float UpdateSlidingHold(SlidingHold *Hold, const uint i, const float in) void ShiftSlidingHold(SlidingHold *Hold, const uint n) { - auto exp_begin = std::begin(Hold->mExpiries) + Hold->mUpperIndex; - auto exp_last = std::begin(Hold->mExpiries) + Hold->mLowerIndex; - if(exp_last-exp_begin < 0) + auto exp_upper = Hold->mExpiries.begin() + Hold->mUpperIndex; + if(Hold->mLowerIndex < Hold->mUpperIndex) { - std::transform(exp_begin, std::end(Hold->mExpiries), exp_begin, - [n](uint e){ return e - n; }); - exp_begin = std::begin(Hold->mExpiries); + std::transform(exp_upper, Hold->mExpiries.end(), exp_upper, + [n](const uint e) noexcept { return e - n; }); + exp_upper = Hold->mExpiries.begin(); } - std::transform(exp_begin, exp_last+1, exp_begin, [n](uint e){ return e - n; }); + const auto exp_lower = Hold->mExpiries.begin() + Hold->mLowerIndex; + std::transform(exp_upper, exp_lower+1, exp_upper, + [n](const uint e) noexcept { return e - n; }); } +} // namespace /* Multichannel compression is linked via the absolute maximum of all * channels. */ -void LinkChannels(Compressor *Comp, const uint SamplesToDo, const FloatBufferLine *OutBuffer) +void Compressor::linkChannels(const uint SamplesToDo, + const al::span OutBuffer) { - const size_t numChans{Comp->mNumChans}; - ASSUME(SamplesToDo > 0); - ASSUME(numChans > 0); + ASSUME(SamplesToDo <= BufferLineSize); - auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead; - std::fill(side_begin, side_begin+SamplesToDo, 0.0f); + const auto sideChain = al::span{mSideChain}.subspan(mLookAhead, SamplesToDo); + std::fill_n(sideChain.begin(), sideChain.size(), 0.0f); - auto fill_max = [SamplesToDo,side_begin](const FloatBufferLine &input) -> void + auto fill_max = [sideChain](const FloatBufferLine &input) -> void { - const float *RESTRICT buffer{al::assume_aligned<16>(input.data())}; - auto max_abs = std::bind(maxf, _1, std::bind(static_cast(std::fabs), _2)); - std::transform(side_begin, side_begin+SamplesToDo, buffer, side_begin, max_abs); + const auto buffer = assume_aligned_span<16>(al::span{input}); + auto max_abs = [](const float s0, const float s1) noexcept -> float + { return std::max(s0, std::fabs(s1)); }; + std::transform(sideChain.begin(), sideChain.end(), buffer.begin(), sideChain.begin(), + max_abs); }; - std::for_each(OutBuffer, OutBuffer+numChans, fill_max); + for(const FloatBufferLine &input : OutBuffer) + fill_max(input); } /* This calculates the squared crest factor of the control signal for the @@ -121,60 +128,63 @@ void LinkChannels(Compressor *Comp, const uint SamplesToDo, const FloatBufferLin * it uses an instantaneous squared peak detector and a squared RMS detector * both with 200ms release times. */ -void CrestDetector(Compressor *Comp, const uint SamplesToDo) +void Compressor::crestDetector(const uint SamplesToDo) { - const float a_crest{Comp->mCrestCoeff}; - float y2_peak{Comp->mLastPeakSq}; - float y2_rms{Comp->mLastRmsSq}; + const float a_crest{mCrestCoeff}; + float y2_peak{mLastPeakSq}; + float y2_rms{mLastRmsSq}; ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); auto calc_crest = [&y2_rms,&y2_peak,a_crest](const float x_abs) noexcept -> float { - const float x2{clampf(x_abs * x_abs, 0.000001f, 1000000.0f)}; + const float x2{std::clamp(x_abs*x_abs, 0.000001f, 1000000.0f)}; - y2_peak = maxf(x2, lerpf(x2, y2_peak, a_crest)); + y2_peak = std::max(x2, lerpf(x2, y2_peak, a_crest)); y2_rms = lerpf(x2, y2_rms, a_crest); return y2_peak / y2_rms; }; - auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead; - std::transform(side_begin, side_begin+SamplesToDo, std::begin(Comp->mCrestFactor), calc_crest); + const auto sideChain = al::span{mSideChain}.subspan(mLookAhead, SamplesToDo); + std::transform(sideChain.cbegin(), sideChain.cend(), mCrestFactor.begin(), calc_crest); - Comp->mLastPeakSq = y2_peak; - Comp->mLastRmsSq = y2_rms; + mLastPeakSq = y2_peak; + mLastRmsSq = y2_rms; } /* The side-chain starts with a simple peak detector (based on the absolute * value of the incoming signal) and performs most of its operations in the * log domain. */ -void PeakDetector(Compressor *Comp, const uint SamplesToDo) +void Compressor::peakDetector(const uint SamplesToDo) { ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); - /* Clamp the minimum amplitude to near-zero and convert to logarithm. */ - auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead; - std::transform(side_begin, side_begin+SamplesToDo, side_begin, - [](float s) { return std::log(maxf(0.000001f, s)); }); + /* Clamp the minimum amplitude to near-zero and convert to logarithmic. */ + const auto sideChain = al::span{mSideChain}.subspan(mLookAhead, SamplesToDo); + std::transform(sideChain.cbegin(), sideChain.cend(), sideChain.begin(), + [](float s) { return std::log(std::max(0.000001f, s)); }); } /* An optional hold can be used to extend the peak detector so it can more * solidly detect fast transients. This is best used when operating as a * limiter. */ -void PeakHoldDetector(Compressor *Comp, const uint SamplesToDo) +void Compressor::peakHoldDetector(const uint SamplesToDo) { ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); - SlidingHold *hold{Comp->mHold}; + SlidingHold *hold{mHold.get()}; uint i{0}; auto detect_peak = [&i,hold](const float x_abs) -> float { - const float x_G{std::log(maxf(0.000001f, x_abs))}; + const float x_G{std::log(std::max(0.000001f, x_abs))}; return UpdateSlidingHold(hold, i++, x_G); }; - auto side_begin = std::begin(Comp->mSideChain) + Comp->mLookAhead; - std::transform(side_begin, side_begin+SamplesToDo, side_begin, detect_peak); + auto sideChain = al::span{mSideChain}.subspan(mLookAhead, SamplesToDo); + std::transform(sideChain.cbegin(), sideChain.cend(), sideChain.begin(), detect_peak); ShiftSlidingHold(hold, SamplesToDo); } @@ -184,46 +194,46 @@ void PeakHoldDetector(Compressor *Comp, const uint SamplesToDo) * to knee width, attack/release times, make-up/post gain, and clipping * reduction. */ -void GainCompressor(Compressor *Comp, const uint SamplesToDo) +void Compressor::gainCompressor(const uint SamplesToDo) { - const bool autoKnee{Comp->mAuto.Knee}; - const bool autoAttack{Comp->mAuto.Attack}; - const bool autoRelease{Comp->mAuto.Release}; - const bool autoPostGain{Comp->mAuto.PostGain}; - const bool autoDeclip{Comp->mAuto.Declip}; - const uint lookAhead{Comp->mLookAhead}; - const float threshold{Comp->mThreshold}; - const float slope{Comp->mSlope}; - const float attack{Comp->mAttack}; - const float release{Comp->mRelease}; - const float c_est{Comp->mGainEstimate}; - const float a_adp{Comp->mAdaptCoeff}; - const float *crestFactor{Comp->mCrestFactor}; - float postGain{Comp->mPostGain}; - float knee{Comp->mKnee}; + const bool autoKnee{mAuto.Knee}; + const bool autoAttack{mAuto.Attack}; + const bool autoRelease{mAuto.Release}; + const bool autoPostGain{mAuto.PostGain}; + const bool autoDeclip{mAuto.Declip}; + const float threshold{mThreshold}; + const float slope{mSlope}; + const float attack{mAttack}; + const float release{mRelease}; + const float c_est{mGainEstimate}; + const float a_adp{mAdaptCoeff}; + auto lookAhead = mSideChain.cbegin() + mLookAhead; + auto crestFactor = mCrestFactor.cbegin(); + float postGain{mPostGain}; + float knee{mKnee}; float t_att{attack}; float t_rel{release - attack}; float a_att{std::exp(-1.0f / t_att)}; float a_rel{std::exp(-1.0f / t_rel)}; - float y_1{Comp->mLastRelease}; - float y_L{Comp->mLastAttack}; - float c_dev{Comp->mLastGainDev}; + float y_1{mLastRelease}; + float y_L{mLastAttack}; + float c_dev{mLastGainDev}; ASSUME(SamplesToDo > 0); - for(float &sideChain : al::span{Comp->mSideChain, SamplesToDo}) + auto process = [&](const float input) -> float { if(autoKnee) - knee = maxf(0.0f, 2.5f * (c_dev + c_est)); + knee = std::max(0.0f, 2.5f * (c_dev + c_est)); const float knee_h{0.5f * knee}; /* This is the gain computer. It applies a static compression curve * to the control signal. */ - const float x_over{std::addressof(sideChain)[lookAhead] - threshold}; + const float x_over{*(lookAhead++) - threshold}; const float y_G{ (x_over <= -knee_h) ? 0.0f : - (std::fabs(x_over) < knee_h) ? (x_over + knee_h) * (x_over + knee_h) / (2.0f * knee) : + (std::fabs(x_over) < knee_h) ? (x_over+knee_h) * (x_over+knee_h) / (2.0f * knee) : x_over}; const float y2_crest{*(crestFactor++)}; @@ -243,7 +253,7 @@ void GainCompressor(Compressor *Comp, const uint SamplesToDo) * above to compensate for the chained operating mode. */ const float x_L{-slope * y_G}; - y_1 = maxf(x_L, lerpf(x_L, y_1, a_rel)); + y_1 = std::max(x_L, lerpf(x_L, y_1, a_rel)); y_L = lerpf(y_1, y_L, a_att); /* Knee width and make-up gain automation make use of a smoothed @@ -262,17 +272,19 @@ void GainCompressor(Compressor *Comp, const uint SamplesToDo) * same output level. */ if(autoDeclip) - c_dev = maxf(c_dev, sideChain - y_L - threshold - c_est); + c_dev = std::max(c_dev, input - y_L - threshold - c_est); postGain = -(c_dev + c_est); } - sideChain = std::exp(postGain - y_L); - } + return std::exp(postGain - y_L); + }; + auto sideChain = al::span{mSideChain}.first(SamplesToDo); + std::transform(sideChain.begin(), sideChain.end(), sideChain.begin(), process); - Comp->mLastRelease = y_1; - Comp->mLastAttack = y_L; - Comp->mLastGainDev = c_dev; + mLastRelease = y_1; + mLastAttack = y_L; + mLastGainDev = c_dev; } /* Combined with the hold time, a look-ahead delay can improve handling of @@ -280,75 +292,60 @@ void GainCompressor(Compressor *Comp, const uint SamplesToDo) * reaching the offending impulse. This is best used when operating as a * limiter. */ -void SignalDelay(Compressor *Comp, const uint SamplesToDo, FloatBufferLine *OutBuffer) +void Compressor::signalDelay(const uint SamplesToDo, const al::span OutBuffer) { - const size_t numChans{Comp->mNumChans}; - const uint lookAhead{Comp->mLookAhead}; + const auto lookAhead = mLookAhead; ASSUME(SamplesToDo > 0); - ASSUME(numChans > 0); + ASSUME(SamplesToDo <= BufferLineSize); ASSUME(lookAhead > 0); + ASSUME(lookAhead < BufferLineSize); - for(size_t c{0};c < numChans;c++) + auto delays = mDelay.begin(); + for(auto &buffer : OutBuffer) { - float *inout{al::assume_aligned<16>(OutBuffer[c].data())}; - float *delaybuf{al::assume_aligned<16>(Comp->mDelay[c].data())}; + const auto inout = al::span{buffer}.first(SamplesToDo); + const auto delaybuf = al::span{*(delays++)}.first(lookAhead); - auto inout_end = inout + SamplesToDo; - if(SamplesToDo >= lookAhead) LIKELY + if(SamplesToDo >= delaybuf.size()) LIKELY { - auto delay_end = std::rotate(inout, inout_end - lookAhead, inout_end); - std::swap_ranges(inout, delay_end, delaybuf); + const auto inout_start = inout.end() - ptrdiff_t(delaybuf.size()); + const auto delay_end = std::rotate(inout.begin(), inout_start, inout.end()); + std::swap_ranges(inout.begin(), delay_end, delaybuf.begin()); } else { - auto delay_start = std::swap_ranges(inout, inout_end, delaybuf); - std::rotate(delaybuf, delay_start, delaybuf + lookAhead); + auto delay_start = std::swap_ranges(inout.begin(), inout.end(), delaybuf.begin()); + std::rotate(delaybuf.begin(), delay_start, delaybuf.end()); } } } -} // namespace - std::unique_ptr Compressor::Create(const size_t NumChans, const float SampleRate, - const bool AutoKnee, const bool AutoAttack, const bool AutoRelease, const bool AutoPostGain, - const bool AutoDeclip, const float LookAheadTime, const float HoldTime, const float PreGainDb, - const float PostGainDb, const float ThresholdDb, const float Ratio, const float KneeDb, - const float AttackTime, const float ReleaseTime) + const FlagBits autoflags, const float LookAheadTime, const float HoldTime, + const float PreGainDb, const float PostGainDb, const float ThresholdDb, const float Ratio, + const float KneeDb, const float AttackTime, const float ReleaseTime) { - const auto lookAhead = static_cast( - clampf(std::round(LookAheadTime*SampleRate), 0.0f, BufferLineSize-1)); - const auto hold = static_cast( - clampf(std::round(HoldTime*SampleRate), 0.0f, BufferLineSize-1)); - - size_t size{sizeof(Compressor)}; - if(lookAhead > 0) - { - size += sizeof(*Compressor::mDelay) * NumChans; - /* The sliding hold implementation doesn't handle a length of 1. A 1- - * sample hold is useless anyway, it would only ever give back what was - * just given to it. - */ - if(hold > 1) - size += sizeof(*Compressor::mHold); - } - - auto Comp = CompressorPtr{al::construct_at(static_cast(al_calloc(16, size)))}; - Comp->mNumChans = NumChans; - Comp->mAuto.Knee = AutoKnee; - Comp->mAuto.Attack = AutoAttack; - Comp->mAuto.Release = AutoRelease; - Comp->mAuto.PostGain = AutoPostGain; - Comp->mAuto.Declip = AutoPostGain && AutoDeclip; + const auto lookAhead = static_cast(std::clamp(std::round(LookAheadTime*SampleRate), 0.0f, + BufferLineSize-1.0f)); + const auto hold = static_cast(std::clamp(std::round(HoldTime*SampleRate), 0.0f, + BufferLineSize-1.0f)); + + auto Comp = CompressorPtr{new Compressor{}}; + Comp->mAuto.Knee = autoflags.test(AutoKnee); + Comp->mAuto.Attack = autoflags.test(AutoAttack); + Comp->mAuto.Release = autoflags.test(AutoRelease); + Comp->mAuto.PostGain = autoflags.test(AutoPostGain); + Comp->mAuto.Declip = autoflags.test(AutoPostGain) && autoflags.test(AutoDeclip); Comp->mLookAhead = lookAhead; Comp->mPreGain = std::pow(10.0f, PreGainDb / 20.0f); - Comp->mPostGain = PostGainDb * std::log(10.0f) / 20.0f; - Comp->mThreshold = ThresholdDb * std::log(10.0f) / 20.0f; - Comp->mSlope = 1.0f / maxf(1.0f, Ratio) - 1.0f; - Comp->mKnee = maxf(0.0f, KneeDb * std::log(10.0f) / 20.0f); - Comp->mAttack = maxf(1.0f, AttackTime * SampleRate); - Comp->mRelease = maxf(1.0f, ReleaseTime * SampleRate); + Comp->mPostGain = std::log(10.0f)/20.0f * PostGainDb; + Comp->mThreshold = std::log(10.0f)/20.0f * ThresholdDb; + Comp->mSlope = 1.0f / std::max(1.0f, Ratio) - 1.0f; + Comp->mKnee = std::max(0.0f, std::log(10.0f)/20.0f * KneeDb); + Comp->mAttack = std::max(1.0f, AttackTime * SampleRate); + Comp->mRelease = std::max(1.0f, ReleaseTime * SampleRate); /* Knee width automation actually treats the compressor as a limiter. By * varying the knee width, it can effectively be seen as applying @@ -359,17 +356,18 @@ std::unique_ptr Compressor::Create(const size_t NumChans, const floa if(lookAhead > 0) { + /* The sliding hold implementation doesn't handle a length of 1. A 1- + * sample hold is useless anyway, it would only ever give back what was + * just given to it. + */ if(hold > 1) { - Comp->mHold = al::construct_at(reinterpret_cast(Comp.get() + 1)); + Comp->mHold = std::make_unique(); Comp->mHold->mValues[0] = -std::numeric_limits::infinity(); Comp->mHold->mExpiries[0] = hold; Comp->mHold->mLength = hold; - Comp->mDelay = reinterpret_cast(Comp->mHold + 1); } - else - Comp->mDelay = reinterpret_cast(Comp.get() + 1); - std::uninitialized_fill_n(Comp->mDelay, NumChans, FloatBufferLine{}); + Comp->mDelay.resize(NumChans, FloatBufferLine{}); } Comp->mCrestCoeff = std::exp(-1.0f / (0.200f * SampleRate)); // 200ms @@ -379,61 +377,51 @@ std::unique_ptr Compressor::Create(const size_t NumChans, const floa return Comp; } -Compressor::~Compressor() -{ - if(mHold) - std::destroy_at(mHold); - mHold = nullptr; - if(mDelay) - std::destroy_n(mDelay, mNumChans); - mDelay = nullptr; -} +Compressor::~Compressor() = default; -void Compressor::process(const uint SamplesToDo, FloatBufferLine *OutBuffer) +void Compressor::process(const uint SamplesToDo, const al::span InOut) { - const size_t numChans{mNumChans}; - ASSUME(SamplesToDo > 0); - ASSUME(numChans > 0); + ASSUME(SamplesToDo <= BufferLineSize); const float preGain{mPreGain}; if(preGain != 1.0f) { auto apply_gain = [SamplesToDo,preGain](FloatBufferLine &input) noexcept -> void { - float *buffer{al::assume_aligned<16>(input.data())}; - std::transform(buffer, buffer+SamplesToDo, buffer, - [preGain](float s) { return s * preGain; }); + const auto buffer = assume_aligned_span<16>(al::span{input}.first(SamplesToDo)); + std::transform(buffer.cbegin(), buffer.cend(), buffer.begin(), + [preGain](const float s) noexcept { return s * preGain; }); }; - std::for_each(OutBuffer, OutBuffer+numChans, apply_gain); + std::for_each(InOut.begin(), InOut.end(), apply_gain); } - LinkChannels(this, SamplesToDo, OutBuffer); + linkChannels(SamplesToDo, InOut); if(mAuto.Attack || mAuto.Release) - CrestDetector(this, SamplesToDo); + crestDetector(SamplesToDo); if(mHold) - PeakHoldDetector(this, SamplesToDo); + peakHoldDetector(SamplesToDo); else - PeakDetector(this, SamplesToDo); + peakDetector(SamplesToDo); - GainCompressor(this, SamplesToDo); + gainCompressor(SamplesToDo); - if(mDelay) - SignalDelay(this, SamplesToDo, OutBuffer); + if(!mDelay.empty()) + signalDelay(SamplesToDo, InOut); - const float (&sideChain)[BufferLineSize*2] = mSideChain; - auto apply_comp = [SamplesToDo,&sideChain](FloatBufferLine &input) noexcept -> void + const auto gains = assume_aligned_span<16>(al::span{mSideChain}.first(SamplesToDo)); + auto apply_comp = [gains](const FloatBufferSpan inout) noexcept -> void { - float *buffer{al::assume_aligned<16>(input.data())}; - const float *gains{al::assume_aligned<16>(&sideChain[0])}; - std::transform(gains, gains+SamplesToDo, buffer, buffer, - [](float g, float s) { return g * s; }); + const auto buffer = assume_aligned_span<16>(inout); + std::transform(gains.cbegin(), gains.cend(), buffer.cbegin(), buffer.begin(), + std::multiplies{}); }; - std::for_each(OutBuffer, OutBuffer+numChans, apply_comp); + for(const FloatBufferSpan inout : InOut) + apply_comp(inout); - auto side_begin = std::begin(mSideChain) + SamplesToDo; - std::copy(side_begin, side_begin+mLookAhead, std::begin(mSideChain)); + const auto delayedGains = al::span{mSideChain}.subspan(SamplesToDo, mLookAhead); + std::copy(delayedGains.begin(), delayedGains.end(), mSideChain.begin()); } diff --git a/3rdparty/openal/core/mastering.h b/3rdparty/openal/core/mastering.h index 1a36937ca484..32f581dbc486 100644 --- a/3rdparty/openal/core/mastering.h +++ b/3rdparty/openal/core/mastering.h @@ -1,10 +1,15 @@ #ifndef CORE_MASTERING_H #define CORE_MASTERING_H +#include +#include #include -#include "almalloc.h" +#include "alnumeric.h" +#include "alspan.h" #include "bufferline.h" +#include "opthelpers.h" +#include "vector.h" struct SlidingHold; @@ -21,16 +26,15 @@ using uint = unsigned int; * * http://c4dm.eecs.qmul.ac.uk/audioengineering/compressors/ */ -struct Compressor { - size_t mNumChans{0u}; - - struct { +class SIMDALIGN Compressor { + struct AutoFlags { bool Knee : 1; bool Attack : 1; bool Release : 1; bool PostGain : 1; bool Declip : 1; - } mAuto{}; + }; + AutoFlags mAuto{}; uint mLookAhead{0}; @@ -44,11 +48,11 @@ struct Compressor { float mAttack{0.0f}; float mRelease{0.0f}; - alignas(16) float mSideChain[2*BufferLineSize]{}; - alignas(16) float mCrestFactor[BufferLineSize]{}; + alignas(16) std::array mSideChain{}; + alignas(16) std::array mCrestFactor{}; - SlidingHold *mHold{nullptr}; - FloatBufferLine *mDelay{nullptr}; + std::unique_ptr mHold; + al::vector mDelay; float mCrestCoeff{0.0f}; float mGainEstimate{0.0f}; @@ -60,12 +64,24 @@ struct Compressor { float mLastAttack{0.0f}; float mLastGainDev{0.0f}; + Compressor() = default; - ~Compressor(); - void process(const uint SamplesToDo, FloatBufferLine *OutBuffer); - int getLookAhead() const noexcept { return static_cast(mLookAhead); } + void linkChannels(const uint SamplesToDo, const al::span OutBuffer); + void crestDetector(const uint SamplesToDo); + void peakDetector(const uint SamplesToDo); + void peakHoldDetector(const uint SamplesToDo); + void gainCompressor(const uint SamplesToDo); + void signalDelay(const uint SamplesToDo, const al::span OutBuffer); - DEF_PLACE_NEWDEL() +public: + enum { + AutoKnee, AutoAttack, AutoRelease, AutoPostGain, AutoDeclip, FlagsCount + }; + using FlagBits = std::bitset; + + ~Compressor(); + void process(const uint SamplesToDo, al::span InOut); + [[nodiscard]] auto getLookAhead() const noexcept -> uint { return mLookAhead; } /** * The compressor is initialized with the following settings: @@ -94,11 +110,9 @@ struct Compressor { * automating release time. */ static std::unique_ptr Create(const size_t NumChans, const float SampleRate, - const bool AutoKnee, const bool AutoAttack, const bool AutoRelease, - const bool AutoPostGain, const bool AutoDeclip, const float LookAheadTime, - const float HoldTime, const float PreGainDb, const float PostGainDb, - const float ThresholdDb, const float Ratio, const float KneeDb, const float AttackTime, - const float ReleaseTime); + const FlagBits autoflags, const float LookAheadTime, const float HoldTime, + const float PreGainDb, const float PostGainDb, const float ThresholdDb, const float Ratio, + const float KneeDb, const float AttackTime, const float ReleaseTime); }; using CompressorPtr = std::unique_ptr; diff --git a/3rdparty/openal/core/mixer.cpp b/3rdparty/openal/core/mixer.cpp index 066c57bd765e..bba7ae2061f9 100644 --- a/3rdparty/openal/core/mixer.cpp +++ b/3rdparty/openal/core/mixer.cpp @@ -3,10 +3,12 @@ #include "mixer.h" +#include #include +#include #include "alnumbers.h" -#include "devformat.h" +#include "core/ambidefs.h" #include "device.h" #include "mixer/defs.h" @@ -82,14 +84,13 @@ std::array CalcAmbiCoeffs(const float y, const float z, c return coeffs; } -void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain, - const al::span gains) +void ComputePanGains(const MixParams *mix, const al::span coeffs, + const float ingain, const al::span gains) { - auto ambimap = mix->AmbiMap.cbegin(); + auto ambimap = al::span{std::as_const(mix->AmbiMap)}.first(mix->Buffer.size()); - auto iter = std::transform(ambimap, ambimap+mix->Buffer.size(), gains.begin(), + auto iter = std::transform(ambimap.begin(), ambimap.end(), gains.begin(), [coeffs,ingain](const BFChannelConfig &chanmap) noexcept -> float - { return chanmap.Scale * coeffs[chanmap.Index] * ingain; } - ); + { return chanmap.Scale * coeffs[chanmap.Index] * ingain; }); std::fill(iter, gains.end(), 0.0f); } diff --git a/3rdparty/openal/core/mixer.h b/3rdparty/openal/core/mixer.h index a9c1f931ca9f..ec6c3271d578 100644 --- a/3rdparty/openal/core/mixer.h +++ b/3rdparty/openal/core/mixer.h @@ -3,34 +3,33 @@ #include #include -#include -#include +#include #include "alspan.h" #include "ambidefs.h" #include "bufferline.h" -#include "devformat.h" +#include "opthelpers.h" struct MixParams; /* Mixer functions that handle one input and multiple output channels. */ using MixerOutFunc = void(*)(const al::span InSamples, - const al::span OutBuffer, float *CurrentGains, const float *TargetGains, - const size_t Counter, const size_t OutPos); + const al::span OutBuffer, const al::span CurrentGains, + const al::span TargetGains, const std::size_t Counter, const std::size_t OutPos); -extern MixerOutFunc MixSamplesOut; +DECL_HIDDEN extern MixerOutFunc MixSamplesOut; inline void MixSamples(const al::span InSamples, - const al::span OutBuffer, float *CurrentGains, const float *TargetGains, - const size_t Counter, const size_t OutPos) + const al::span OutBuffer, const al::span CurrentGains, + const al::span TargetGains, const std::size_t Counter, const std::size_t OutPos) { MixSamplesOut(InSamples, OutBuffer, CurrentGains, TargetGains, Counter, OutPos); } /* Mixer functions that handle one input and one output channel. */ -using MixerOneFunc = void(*)(const al::span InSamples, float *OutBuffer, - float &CurrentGain, const float TargetGain, const size_t Counter); +using MixerOneFunc = void(*)(const al::span InSamples,const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const std::size_t Counter); -extern MixerOneFunc MixSamplesOne; -inline void MixSamples(const al::span InSamples, float *OutBuffer, float &CurrentGain, - const float TargetGain, const size_t Counter) +DECL_HIDDEN extern MixerOneFunc MixSamplesOne; +inline void MixSamples(const al::span InSamples, const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const std::size_t Counter) { MixSamplesOne(InSamples, OutBuffer, CurrentGain, TargetGain, Counter); } @@ -103,7 +102,7 @@ inline std::array CalcAngleCoeffs(const float azimuth, * coeffs are a 'slice' of a transform matrix for the input channel, used to * scale and orient the sound samples. */ -void ComputePanGains(const MixParams *mix, const float*RESTRICT coeffs, const float ingain, - const al::span gains); +void ComputePanGains(const MixParams *mix, const al::span coeffs, + const float ingain, const al::span gains); #endif /* CORE_MIXER_H */ diff --git a/3rdparty/openal/core/mixer/defs.h b/3rdparty/openal/core/mixer/defs.h index 48daca9b95c2..4506dde67ea0 100644 --- a/3rdparty/openal/core/mixer/defs.h +++ b/3rdparty/openal/core/mixer/defs.h @@ -2,13 +2,15 @@ #define CORE_MIXER_DEFS_H #include -#include +#include +#include +#include +#include #include "alspan.h" #include "core/bufferline.h" -#include "core/resampler_limits.h" +#include "core/cubic_defs.h" -struct CubicCoefficients; struct HrtfChannelState; struct HrtfFilter; struct MixHrtfFilter; @@ -17,24 +19,27 @@ using uint = unsigned int; using float2 = std::array; -constexpr int MixerFracBits{16}; -constexpr int MixerFracOne{1 << MixerFracBits}; -constexpr int MixerFracMask{MixerFracOne - 1}; -constexpr int MixerFracHalf{MixerFracOne >> 1}; +inline constexpr int MixerFracBits{16}; +inline constexpr int MixerFracOne{1 << MixerFracBits}; +inline constexpr int MixerFracMask{MixerFracOne - 1}; +inline constexpr int MixerFracHalf{MixerFracOne >> 1}; -constexpr float GainSilenceThreshold{0.00001f}; /* -100dB */ +inline constexpr float GainSilenceThreshold{0.00001f}; /* -100dB */ -enum class Resampler : uint8_t { +enum class Resampler : std::uint8_t { Point, Linear, - Cubic, + Spline, + Gaussian, FastBSinc12, BSinc12, FastBSinc24, BSinc24, + FastBSinc48, + BSinc48, - Max = BSinc24 + Max = BSinc48 }; /* Interpolator state. Kind of a misnomer since the interpolator itself is @@ -49,56 +54,59 @@ struct BsincState { * delta coefficients. Starting at phase index 0, each subsequent phase * index follows contiguously. */ - const float *filter; + al::span filter; }; struct CubicState { /* Filter coefficients, and coefficient deltas. Starting at phase index 0, * each subsequent phase index follows contiguously. */ - const CubicCoefficients *filter; + al::span filter; + explicit CubicState(al::span f) : filter{f} { } }; -union InterpState { - CubicState cubic; - BsincState bsinc; -}; +using InterpState = std::variant; -using ResamplerFunc = void(*)(const InterpState *state, const float *RESTRICT src, uint frac, +using ResamplerFunc = void(*)(const InterpState *state, const al::span src, uint frac, const uint increment, const al::span dst); ResamplerFunc PrepareResampler(Resampler resampler, uint increment, InterpState *state); template -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, +void Resample_(const InterpState *state, const al::span src, uint frac, const uint increment, const al::span dst); template void Mix_(const al::span InSamples, const al::span OutBuffer, - float *CurrentGains, const float *TargetGains, const size_t Counter, const size_t OutPos); + const al::span CurrentGains, const al::span TargetGains, + const size_t Counter, const size_t OutPos); template -void Mix_(const al::span InSamples, float *OutBuffer, float &CurrentGain, - const float TargetGain, const size_t Counter); +void Mix_(const al::span InSamples, const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const size_t Counter); template -void MixHrtf_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize); +void MixHrtf_(const al::span InSamples, const al::span AccumSamples, + const uint IrSize, const MixHrtfFilter *hrtfparams, const size_t SamplesToDo); template -void MixHrtfBlend_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const HrtfFilter *oldparams, const MixHrtfFilter *newparams, const size_t BufferSize); +void MixHrtfBlend_(const al::span InSamples, const al::span AccumSamples, + const uint IrSize, const HrtfFilter *oldparams, const MixHrtfFilter *newparams, + const size_t SamplesToDo); template void MixDirectHrtf_(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *AccumSamples, - float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize); + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChanState, + const size_t IrSize, const size_t SamplesToDo); /* Vectorized resampler helpers */ template -inline void InitPosArrays(uint frac, uint increment, uint (&frac_arr)[N], uint (&pos_arr)[N]) +constexpr void InitPosArrays(uint pos, uint frac, const uint increment, + const al::span frac_arr, const al::span pos_arr) { - pos_arr[0] = 0; + static_assert(pos_arr.size() == frac_arr.size()); + pos_arr[0] = pos; frac_arr[0] = frac; - for(size_t i{1};i < N;i++) + for(size_t i{1};i < pos_arr.size();++i) { const uint frac_tmp{frac_arr[i-1] + increment}; pos_arr[i] = pos_arr[i-1] + (frac_tmp>>MixerFracBits); diff --git a/3rdparty/openal/core/mixer/hrtfbase.h b/3rdparty/openal/core/mixer/hrtfbase.h index 36f88e4967ce..703bfab9d649 100644 --- a/3rdparty/openal/core/mixer/hrtfbase.h +++ b/3rdparty/openal/core/mixer/hrtfbase.h @@ -4,21 +4,23 @@ #include #include -#include "almalloc.h" +#include "defs.h" #include "hrtfdefs.h" #include "opthelpers.h" using uint = unsigned int; -using ApplyCoeffsT = void(&)(float2 *RESTRICT Values, const size_t irSize, +using ApplyCoeffsT = void(const al::span Values, const size_t irSize, const ConstHrirSpan Coeffs, const float left, const float right); template -inline void MixHrtfBase(const float *InSamples, float2 *RESTRICT AccumSamples, const size_t IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize) +inline void MixHrtfBase(const al::span InSamples, const al::span AccumSamples, + const size_t IrSize, const MixHrtfFilter *hrtfparams, const size_t SamplesToDo) { - ASSUME(BufferSize > 0); + ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); + ASSUME(IrSize <= HrirLength); const ConstHrirSpan Coeffs{hrtfparams->Coeffs}; const float gainstep{hrtfparams->GainStep}; @@ -27,26 +29,28 @@ inline void MixHrtfBase(const float *InSamples, float2 *RESTRICT AccumSamples, c size_t ldelay{HrtfHistoryLength - hrtfparams->Delay[0]}; size_t rdelay{HrtfHistoryLength - hrtfparams->Delay[1]}; float stepcount{0.0f}; - for(size_t i{0u};i < BufferSize;++i) + for(size_t i{0u};i < SamplesToDo;++i) { const float g{gain + gainstep*stepcount}; const float left{InSamples[ldelay++] * g}; const float right{InSamples[rdelay++] * g}; - ApplyCoeffs(AccumSamples+i, IrSize, Coeffs, left, right); + ApplyCoeffs(AccumSamples.subspan(i), IrSize, Coeffs, left, right); stepcount += 1.0f; } } template -inline void MixHrtfBlendBase(const float *InSamples, float2 *RESTRICT AccumSamples, - const size_t IrSize, const HrtfFilter *oldparams, const MixHrtfFilter *newparams, - const size_t BufferSize) +inline void MixHrtfBlendBase(const al::span InSamples, + const al::span AccumSamples, const size_t IrSize, const HrtfFilter *oldparams, + const MixHrtfFilter *newparams, const size_t SamplesToDo) { - ASSUME(BufferSize > 0); + ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); + ASSUME(IrSize <= HrirLength); const ConstHrirSpan OldCoeffs{oldparams->Coeffs}; - const float oldGainStep{oldparams->Gain / static_cast(BufferSize)}; + const float oldGainStep{oldparams->Gain / static_cast(SamplesToDo)}; const ConstHrirSpan NewCoeffs{newparams->Coeffs}; const float newGainStep{newparams->GainStep}; @@ -54,29 +58,29 @@ inline void MixHrtfBlendBase(const float *InSamples, float2 *RESTRICT AccumSampl { size_t ldelay{HrtfHistoryLength - oldparams->Delay[0]}; size_t rdelay{HrtfHistoryLength - oldparams->Delay[1]}; - auto stepcount = static_cast(BufferSize); - for(size_t i{0u};i < BufferSize;++i) + auto stepcount = static_cast(SamplesToDo); + for(size_t i{0u};i < SamplesToDo;++i) { const float g{oldGainStep*stepcount}; const float left{InSamples[ldelay++] * g}; const float right{InSamples[rdelay++] * g}; - ApplyCoeffs(AccumSamples+i, IrSize, OldCoeffs, left, right); + ApplyCoeffs(AccumSamples.subspan(i), IrSize, OldCoeffs, left, right); stepcount -= 1.0f; } } - if(newGainStep*static_cast(BufferSize) > GainSilenceThreshold) LIKELY + if(newGainStep*static_cast(SamplesToDo) > GainSilenceThreshold) LIKELY { size_t ldelay{HrtfHistoryLength+1 - newparams->Delay[0]}; size_t rdelay{HrtfHistoryLength+1 - newparams->Delay[1]}; float stepcount{1.0f}; - for(size_t i{1u};i < BufferSize;++i) + for(size_t i{1u};i < SamplesToDo;++i) { const float g{newGainStep*stepcount}; const float left{InSamples[ldelay++] * g}; const float right{InSamples[rdelay++] * g}; - ApplyCoeffs(AccumSamples+i, IrSize, NewCoeffs, left, right); + ApplyCoeffs(AccumSamples.subspan(i), IrSize, NewCoeffs, left, right); stepcount += 1.0f; } @@ -85,45 +89,52 @@ inline void MixHrtfBlendBase(const float *InSamples, float2 *RESTRICT AccumSampl template inline void MixDirectHrtfBase(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *RESTRICT AccumSamples, - float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize) + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChannelState, + const size_t IrSize, const size_t SamplesToDo) { - ASSUME(BufferSize > 0); + ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); + ASSUME(IrSize <= HrirLength); + assert(ChannelState.size() == InSamples.size()); + auto ChanState = ChannelState.begin(); for(const FloatBufferLine &input : InSamples) { /* For dual-band processing, the signal needs extra scaling applied to * the high frequency response. The band-splitter applies this scaling * with a consistent phase shift regardless of the scale amount. */ - ChanState->mSplitter.processHfScale({input.data(), BufferSize}, TempBuf, + ChanState->mSplitter.processHfScale(al::span{input}.first(SamplesToDo), TempBuf, ChanState->mHfScale); /* Now apply the HRIR coefficients to this channel. */ - const float *RESTRICT tempbuf{al::assume_aligned<16>(TempBuf)}; const ConstHrirSpan Coeffs{ChanState->mCoeffs}; - for(size_t i{0u};i < BufferSize;++i) + for(size_t i{0u};i < SamplesToDo;++i) { - const float insample{tempbuf[i]}; - ApplyCoeffs(AccumSamples+i, IrSize, Coeffs, insample, insample); + const float insample{TempBuf[i]}; + ApplyCoeffs(AccumSamples.subspan(i), IrSize, Coeffs, insample, insample); } ++ChanState; } /* Add the HRTF signal to the existing "direct" signal. */ - float *RESTRICT left{al::assume_aligned<16>(LeftOut.data())}; - float *RESTRICT right{al::assume_aligned<16>(RightOut.data())}; - for(size_t i{0u};i < BufferSize;++i) - left[i] += AccumSamples[i][0]; - for(size_t i{0u};i < BufferSize;++i) - right[i] += AccumSamples[i][1]; + const auto left = al::span{al::assume_aligned<16>(LeftOut.data()), SamplesToDo}; + std::transform(left.cbegin(), left.cend(), AccumSamples.cbegin(), left.begin(), + [](const float sample, const float2 &accum) noexcept -> float + { return sample + accum[0]; }); + const auto right = al::span{al::assume_aligned<16>(RightOut.data()), SamplesToDo}; + std::transform(right.cbegin(), right.cend(), AccumSamples.cbegin(), right.begin(), + [](const float sample, const float2 &accum) noexcept -> float + { return sample + accum[1]; }); /* Copy the new in-progress accumulation values to the front and clear the * following samples for the next mix. */ - auto accum_iter = std::copy_n(AccumSamples+BufferSize, HrirLength, AccumSamples); - std::fill_n(accum_iter, BufferSize, float2{}); + const auto accum_inprog = AccumSamples.subspan(SamplesToDo, HrirLength); + auto accum_iter = std::copy(accum_inprog.cbegin(), accum_inprog.cend(), AccumSamples.begin()); + std::fill_n(accum_iter, SamplesToDo, float2{}); } #endif /* CORE_MIXER_HRTFBASE_H */ diff --git a/3rdparty/openal/core/mixer/mixer_c.cpp b/3rdparty/openal/core/mixer/mixer_c.cpp index 28a92ef7e637..e14454d26d84 100644 --- a/3rdparty/openal/core/mixer/mixer_c.cpp +++ b/3rdparty/openal/core/mixer/mixer_c.cpp @@ -1,14 +1,21 @@ #include "config.h" -#include -#include +#include +#include +#include #include +#include #include "alnumeric.h" +#include "alspan.h" #include "core/bsinc_defs.h" +#include "core/bufferline.h" #include "core/cubic_defs.h" +#include "core/mixer/hrtfdefs.h" +#include "core/resampler_limits.h" #include "defs.h" #include "hrtfbase.h" +#include "opthelpers.h" struct CTag; struct PointTag; @@ -28,191 +35,246 @@ constexpr uint CubicPhaseDiffBits{MixerFracBits - CubicPhaseBits}; constexpr uint CubicPhaseDiffOne{1 << CubicPhaseDiffBits}; constexpr uint CubicPhaseDiffMask{CubicPhaseDiffOne - 1u}; -inline float do_point(const InterpState&, const float *RESTRICT vals, const uint) -{ return vals[0]; } -inline float do_lerp(const InterpState&, const float *RESTRICT vals, const uint frac) -{ return lerpf(vals[0], vals[1], static_cast(frac)*(1.0f/MixerFracOne)); } -inline float do_cubic(const InterpState &istate, const float *RESTRICT vals, const uint frac) +using SamplerNST = float(const al::span, const size_t, const uint) noexcept; + +template +using SamplerT = float(const T&,const al::span,const size_t,const uint) noexcept; + +[[nodiscard]] constexpr +auto do_point(const al::span vals, const size_t pos, const uint) noexcept -> float +{ return vals[pos]; } +[[nodiscard]] constexpr +auto do_lerp(const al::span vals, const size_t pos, const uint frac) noexcept -> float +{ return lerpf(vals[pos+0], vals[pos+1], static_cast(frac)*(1.0f/MixerFracOne)); } +[[nodiscard]] constexpr +auto do_cubic(const CubicState &istate, const al::span vals, const size_t pos, + const uint frac) noexcept -> float { /* Calculate the phase index and factor. */ - const uint pi{frac >> CubicPhaseDiffBits}; + const uint pi{frac >> CubicPhaseDiffBits}; ASSUME(pi < CubicPhaseCount); const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; - const float *RESTRICT fil{al::assume_aligned<16>(istate.cubic.filter[pi].mCoeffs)}; - const float *RESTRICT phd{al::assume_aligned<16>(istate.cubic.filter[pi].mDeltas)}; + const auto fil = al::span{istate.filter[pi].mCoeffs}; + const auto phd = al::span{istate.filter[pi].mDeltas}; /* Apply the phase interpolated filter. */ - return (fil[0] + pf*phd[0])*vals[0] + (fil[1] + pf*phd[1])*vals[1] - + (fil[2] + pf*phd[2])*vals[2] + (fil[3] + pf*phd[3])*vals[3]; + return (fil[0] + pf*phd[0])*vals[pos+0] + (fil[1] + pf*phd[1])*vals[pos+1] + + (fil[2] + pf*phd[2])*vals[pos+2] + (fil[3] + pf*phd[3])*vals[pos+3]; } -inline float do_bsinc(const InterpState &istate, const float *RESTRICT vals, const uint frac) +[[nodiscard]] constexpr +auto do_fastbsinc(const BsincState &bsinc, const al::span vals, const size_t pos, + const uint frac) noexcept -> float { - const size_t m{istate.bsinc.m}; + const size_t m{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); /* Calculate the phase index and factor. */ - const uint pi{frac >> BsincPhaseDiffBits}; + const uint pi{frac >> BsincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BsincPhaseDiffMask) * (1.0f/BsincPhaseDiffOne)}; - const float *RESTRICT fil{istate.bsinc.filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; - const float *RESTRICT scd{fil + BSincPhaseCount*2*m}; - const float *RESTRICT spd{scd + m}; + const auto fil = bsinc.filter.subspan(2_uz*pi*m); + const auto phd = fil.subspan(m); - /* Apply the scale and phase interpolated filter. */ + /* Apply the phase interpolated filter. */ float r{0.0f}; - for(size_t j_f{0};j_f < m;j_f++) - r += (fil[j_f] + istate.bsinc.sf*scd[j_f] + pf*(phd[j_f] + istate.bsinc.sf*spd[j_f])) * vals[j_f]; + for(size_t j_f{0};j_f < m;++j_f) + r += (fil[j_f] + pf*phd[j_f]) * vals[pos+j_f]; return r; } -inline float do_fastbsinc(const InterpState &istate, const float *RESTRICT vals, const uint frac) +[[nodiscard]] constexpr +auto do_bsinc(const BsincState &bsinc, const al::span vals, const size_t pos, + const uint frac) noexcept -> float { - const size_t m{istate.bsinc.m}; + const size_t m{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); /* Calculate the phase index and factor. */ - const uint pi{frac >> BsincPhaseDiffBits}; + const uint pi{frac >> BsincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BsincPhaseDiffMask) * (1.0f/BsincPhaseDiffOne)}; - const float *RESTRICT fil{istate.bsinc.filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; + const auto fil = bsinc.filter.subspan(2_uz*pi*m); + const auto phd = fil.subspan(m); + const auto scd = fil.subspan(BSincPhaseCount*2_uz*m); + const auto spd = scd.subspan(m); - /* Apply the phase interpolated filter. */ + /* Apply the scale and phase interpolated filter. */ float r{0.0f}; - for(size_t j_f{0};j_f < m;j_f++) - r += (fil[j_f] + pf*phd[j_f]) * vals[j_f]; + for(size_t j_f{0};j_f < m;++j_f) + r += (fil[j_f] + bsinc.sf*scd[j_f] + pf*(phd[j_f] + bsinc.sf*spd[j_f])) * vals[pos+j_f]; return r; } -using SamplerT = float(&)(const InterpState&, const float*RESTRICT, const uint); -template -void DoResample(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +template +void DoResample(const al::span src, uint frac, const uint increment, + const al::span dst) { - const InterpState istate{*state}; ASSUME(frac < MixerFracOne); - for(float &out : dst) + size_t pos{0}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment]() -> float { - out = Sampler(istate, src, frac); + const float output{Sampler(src, pos, frac)}; + frac += increment; + pos += frac>>MixerFracBits; + frac &= MixerFracMask; + return output; + }); +} +template Sampler> +void DoResample(const U istate, const al::span src, uint frac, const uint increment, + const al::span dst) +{ + ASSUME(frac < MixerFracOne); + size_t pos{0}; + std::generate(dst.begin(), dst.end(), [istate,src,&pos,&frac,increment]() -> float + { + const float output{Sampler(istate, src, pos, frac)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } -inline void ApplyCoeffs(float2 *RESTRICT Values, const size_t IrSize, const ConstHrirSpan Coeffs, - const float left, const float right) +inline void ApplyCoeffs(const al::span Values, const size_t IrSize, + const ConstHrirSpan Coeffs, const float left, const float right) noexcept { ASSUME(IrSize >= MinIrLength); - for(size_t c{0};c < IrSize;++c) - { - Values[c][0] += Coeffs[c][0] * left; - Values[c][1] += Coeffs[c][1] * right; - } + ASSUME(IrSize <= HrirLength); + + auto mix_impulse = [left,right](const float2 &value, const float2 &coeff) noexcept -> float2 + { return float2{{value[0] + coeff[0]*left, value[1] + coeff[1]*right}}; }; + std::transform(Values.cbegin(), Values.cbegin()+ptrdiff_t(IrSize), Coeffs.cbegin(), + Values.begin(), mix_impulse); } -force_inline void MixLine(const al::span InSamples, float *RESTRICT dst, - float &CurrentGain, const float TargetGain, const float delta, const size_t min_len, +force_inline void MixLine(al::span InSamples, const al::span dst, + float &CurrentGain, const float TargetGain, const float delta, const size_t fade_len, size_t Counter) { - float gain{CurrentGain}; - const float step{(TargetGain-gain) * delta}; + const float step{(TargetGain-CurrentGain) * delta}; - size_t pos{0}; - if(!(std::abs(step) > std::numeric_limits::epsilon())) - gain = TargetGain; - else + auto output = dst.begin(); + if(std::abs(step) > std::numeric_limits::epsilon()) { + auto input = InSamples.first(fade_len); + InSamples = InSamples.subspan(fade_len); + + const float gain{CurrentGain}; float step_count{0.0f}; - for(;pos != min_len;++pos) + output = std::transform(input.begin(), input.end(), output, output, + [gain,step,&step_count](const float in, float out) noexcept -> float + { + out += in * (gain + step*step_count); + step_count += 1.0f; + return out; + }); + + if(fade_len < Counter) { - dst[pos] += InSamples[pos] * (gain + step*step_count); - step_count += 1.0f; + CurrentGain = gain + step*step_count; + return; } - if(pos == Counter) - gain = TargetGain; - else - gain += step*step_count; } - CurrentGain = gain; + CurrentGain = TargetGain; - if(!(std::abs(gain) > GainSilenceThreshold)) + if(!(std::abs(TargetGain) > GainSilenceThreshold)) return; - for(;pos != InSamples.size();++pos) - dst[pos] += InSamples[pos] * gain; + + std::transform(InSamples.begin(), InSamples.end(), output, output, + [TargetGain](const float in, const float out) noexcept -> float + { return out + in*TargetGain; }); } } // namespace template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, +void Resample_(const InterpState*, const al::span src, uint frac, const uint increment, const al::span dst) -{ DoResample(state, src, frac, increment, dst); } +{ DoResample(src.subspan(MaxResamplerEdge), frac, increment, dst); } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, +void Resample_(const InterpState*, const al::span src, uint frac, const uint increment, const al::span dst) -{ DoResample(state, src, frac, increment, dst); } +{ DoResample(src.subspan(MaxResamplerEdge), frac, increment, dst); } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, +void Resample_(const InterpState *state, const al::span src, uint frac, const uint increment, const al::span dst) -{ DoResample(state, src-1, frac, increment, dst); } +{ + DoResample(std::get(*state), src.subspan(MaxResamplerEdge-1), + frac, increment, dst); +} template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) -{ DoResample(state, src-state->bsinc.l, frac, increment, dst); } +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) +{ + const auto istate = std::get(*state); + ASSUME(istate.l <= MaxResamplerEdge); + DoResample(istate, src.subspan(MaxResamplerEdge-istate.l), frac, + increment, dst); +} template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, +void Resample_(const InterpState *state, const al::span src, uint frac, const uint increment, const al::span dst) -{ DoResample(state, src-state->bsinc.l, frac, increment, dst); } +{ + const auto istate = std::get(*state); + ASSUME(istate.l <= MaxResamplerEdge); + DoResample(istate, src.subspan(MaxResamplerEdge-istate.l), frac, + increment, dst); +} template<> -void MixHrtf_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } +void MixHrtf_(const al::span InSamples, const al::span AccumSamples, + const uint IrSize, const MixHrtfFilter *hrtfparams, const size_t SamplesToDo) +{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, SamplesToDo); } template<> -void MixHrtfBlend_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const HrtfFilter *oldparams, const MixHrtfFilter *newparams, const size_t BufferSize) +void MixHrtfBlend_(const al::span InSamples,const al::span AccumSamples, + const uint IrSize, const HrtfFilter *oldparams, const MixHrtfFilter *newparams, + const size_t SamplesToDo) { MixHrtfBlendBase(InSamples, AccumSamples, IrSize, oldparams, newparams, - BufferSize); + SamplesToDo); } template<> void MixDirectHrtf_(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *AccumSamples, - float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize) + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChanState, + const size_t IrSize, const size_t SamplesToDo) { MixDirectHrtfBase(LeftOut, RightOut, InSamples, AccumSamples, TempBuf, ChanState, - IrSize, BufferSize); + IrSize, SamplesToDo); } template<> void Mix_(const al::span InSamples, const al::span OutBuffer, - float *CurrentGains, const float *TargetGains, const size_t Counter, const size_t OutPos) + const al::span CurrentGains, const al::span TargetGains, + const size_t Counter, const size_t OutPos) { const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); + const auto fade_len = std::min(Counter, InSamples.size()); + auto curgains = CurrentGains.begin(); + auto targetgains = TargetGains.cbegin(); for(FloatBufferLine &output : OutBuffer) - MixLine(InSamples, al::assume_aligned<16>(output.data()+OutPos), *CurrentGains++, - *TargetGains++, delta, min_len, Counter); + MixLine(InSamples, al::span{output}.subspan(OutPos), *curgains++, *targetgains++, delta, + fade_len, Counter); } template<> -void Mix_(const al::span InSamples, float *OutBuffer, float &CurrentGain, - const float TargetGain, const size_t Counter) +void Mix_(const al::span InSamples, const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const size_t Counter) { const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); + const auto fade_len = std::min(Counter, InSamples.size()); - MixLine(InSamples, al::assume_aligned<16>(OutBuffer), CurrentGain, - TargetGain, delta, min_len, Counter); + MixLine(InSamples, OutBuffer, CurrentGain, TargetGain, delta, fade_len, Counter); } diff --git a/3rdparty/openal/core/mixer/mixer_neon.cpp b/3rdparty/openal/core/mixer/mixer_neon.cpp index ead775af1ebf..600c014b7ab9 100644 --- a/3rdparty/openal/core/mixer/mixer_neon.cpp +++ b/3rdparty/openal/core/mixer/mixer_neon.cpp @@ -2,15 +2,24 @@ #include -#include +#include +#include +#include #include +#include #include "alnumeric.h" +#include "alspan.h" #include "core/bsinc_defs.h" +#include "core/bufferline.h" #include "core/cubic_defs.h" +#include "core/mixer/hrtfdefs.h" +#include "core/resampler_limits.h" #include "defs.h" #include "hrtfbase.h" +#include "opthelpers.h" +struct CTag; struct NEONTag; struct LerpTag; struct CubicTag; @@ -22,6 +31,8 @@ struct FastBSincTag; #pragma GCC target("fpu=neon") #endif +using uint = unsigned int; + namespace { constexpr uint BSincPhaseDiffBits{MixerFracBits - BSincPhaseBits}; @@ -32,6 +43,19 @@ constexpr uint CubicPhaseDiffBits{MixerFracBits - CubicPhaseBits}; constexpr uint CubicPhaseDiffOne{1 << CubicPhaseDiffBits}; constexpr uint CubicPhaseDiffMask{CubicPhaseDiffOne - 1u}; +force_inline +void vtranspose4(float32x4_t &x0, float32x4_t &x1, float32x4_t &x2, float32x4_t &x3) noexcept +{ + float32x4x2_t t0_{vzipq_f32(x0, x2)}; + float32x4x2_t t1_{vzipq_f32(x1, x3)}; + float32x4x2_t u0_{vzipq_f32(t0_.val[0], t1_.val[0])}; + float32x4x2_t u1_{vzipq_f32(t0_.val[1], t1_.val[1])}; + x0 = u0_.val[0]; + x1 = u0_.val[1]; + x2 = u1_.val[0]; + x3 = u1_.val[1]; +} + inline float32x4_t set_f4(float l0, float l1, float l2, float l3) { float32x4_t ret{vmovq_n_f32(l0)}; @@ -41,60 +65,62 @@ inline float32x4_t set_f4(float l0, float l1, float l2, float l3) return ret; } -inline void ApplyCoeffs(float2 *RESTRICT Values, const size_t IrSize, const ConstHrirSpan Coeffs, - const float left, const float right) +inline void ApplyCoeffs(const al::span Values, const size_t IrSize, + const ConstHrirSpan Coeffs, const float left, const float right) { - float32x4_t leftright4; - { - float32x2_t leftright2{vmov_n_f32(left)}; - leftright2 = vset_lane_f32(right, leftright2, 1); - leftright4 = vcombine_f32(leftright2, leftright2); - } - ASSUME(IrSize >= MinIrLength); + ASSUME(IrSize <= HrirLength); + + auto dup_samples = [left,right]() -> float32x4_t + { + float32x2_t leftright2{vset_lane_f32(right, vmov_n_f32(left), 1)}; + return vcombine_f32(leftright2, leftright2); + }; + const auto leftright4 = dup_samples(); + + /* Using a loop here instead of std::transform since some builds seem to + * have an issue with accessing an array/span of float32x4_t. + */ for(size_t c{0};c < IrSize;c += 2) { - float32x4_t vals = vld1q_f32(&Values[c][0]); - float32x4_t coefs = vld1q_f32(&Coeffs[c][0]); - - vals = vmlaq_f32(vals, coefs, leftright4); - + auto vals = vld1q_f32(&Values[c][0]); + vals = vmlaq_f32(vals, vld1q_f32(&Coeffs[c][0]), leftright4); vst1q_f32(&Values[c][0], vals); } } -force_inline void MixLine(const al::span InSamples, float *RESTRICT dst, - float &CurrentGain, const float TargetGain, const float delta, const size_t min_len, - const size_t aligned_len, size_t Counter) +force_inline void MixLine(const al::span InSamples, const al::span dst, + float &CurrentGain, const float TargetGain, const float delta, const size_t fade_len, + const size_t realign_len, size_t Counter) { - float gain{CurrentGain}; - const float step{(TargetGain-gain) * delta}; + const auto step = float{(TargetGain-CurrentGain) * delta}; - size_t pos{0}; - if(!(std::abs(step) > std::numeric_limits::epsilon())) - gain = TargetGain; - else + auto pos = size_t{0}; + if(std::abs(step) > std::numeric_limits::epsilon()) { - float step_count{0.0f}; + const auto gain = float{CurrentGain}; + auto step_count = float{0.0f}; /* Mix with applying gain steps in aligned multiples of 4. */ - if(size_t todo{min_len >> 2}) + if(const size_t todo{fade_len >> 2}) { - const float32x4_t four4{vdupq_n_f32(4.0f)}; - const float32x4_t step4{vdupq_n_f32(step)}; - const float32x4_t gain4{vdupq_n_f32(gain)}; - float32x4_t step_count4{vdupq_n_f32(0.0f)}; - step_count4 = vsetq_lane_f32(1.0f, step_count4, 1); - step_count4 = vsetq_lane_f32(2.0f, step_count4, 2); - step_count4 = vsetq_lane_f32(3.0f, step_count4, 3); + const auto four4 = vdupq_n_f32(4.0f); + const auto step4 = vdupq_n_f32(step); + const auto gain4 = vdupq_n_f32(gain); + auto step_count4 = set_f4(0.0f, 1.0f, 2.0f, 3.0f); + + const auto in4 = al::span{reinterpret_cast(InSamples.data()), + InSamples.size()/4}.first(todo); + const auto out4 = al::span{reinterpret_cast(dst.data()), dst.size()/4}; + std::transform(in4.begin(), in4.end(), out4.begin(), out4.begin(), + [gain4,step4,four4,&step_count4](const float32x4_t val4, float32x4_t dry4) + { + /* dry += val * (gain + step*step_count) */ + dry4 = vmlaq_f32(dry4, val4, vmlaq_f32(gain4, step4, step_count4)); + step_count4 = vaddq_f32(step_count4, four4); + return dry4; + }); + pos += in4.size()*4; - do { - const float32x4_t val4 = vld1q_f32(&InSamples[pos]); - float32x4_t dry4 = vld1q_f32(&dst[pos]); - dry4 = vmlaq_f32(dry4, val4, vmlaq_f32(gain4, step4, step_count4)); - step_count4 = vaddq_f32(step_count4, four4); - vst1q_f32(&dst[pos], dry4); - pos += 4; - } while(--todo); /* NOTE: step_count4 now represents the next four counts after the * last four mixed samples, so the lowest element represents the * next step count to apply. @@ -102,152 +128,242 @@ force_inline void MixLine(const al::span InSamples, float *RESTRICT step_count = vgetq_lane_f32(step_count4, 0); } /* Mix with applying left over gain steps that aren't aligned multiples of 4. */ - for(size_t leftover{min_len&3};leftover;++pos,--leftover) + if(const size_t leftover{fade_len&3}) + { + const auto in = InSamples.subspan(pos, leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [gain,step,&step_count](const float val, float dry) noexcept -> float + { + dry += val * (gain + step*step_count); + step_count += 1.0f; + return dry; + }); + pos += leftover; + } + if(pos < Counter) { - dst[pos] += InSamples[pos] * (gain + step*step_count); - step_count += 1.0f; + CurrentGain = gain + step*step_count; + return; } - if(pos == Counter) - gain = TargetGain; - else - gain += step*step_count; /* Mix until pos is aligned with 4 or the mix is done. */ - for(size_t leftover{aligned_len&3};leftover;++pos,--leftover) - dst[pos] += InSamples[pos] * gain; + if(const size_t leftover{realign_len&3}) + { + const auto in = InSamples.subspan(pos, leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [TargetGain](const float val, const float dry) noexcept -> float + { return dry + val*TargetGain; }); + pos += leftover; + } } - CurrentGain = gain; + CurrentGain = TargetGain; - if(!(std::abs(gain) > GainSilenceThreshold)) + if(!(std::abs(TargetGain) > GainSilenceThreshold)) return; - if(size_t todo{(InSamples.size()-pos) >> 2}) + if(const size_t todo{(InSamples.size()-pos) >> 2}) { - const float32x4_t gain4 = vdupq_n_f32(gain); - do { - const float32x4_t val4 = vld1q_f32(&InSamples[pos]); - float32x4_t dry4 = vld1q_f32(&dst[pos]); - dry4 = vmlaq_f32(dry4, val4, gain4); - vst1q_f32(&dst[pos], dry4); - pos += 4; - } while(--todo); + const auto in4 = al::span{reinterpret_cast(InSamples.data()), + InSamples.size()/4}.last(todo); + const auto out = dst.subspan(pos); + const auto out4 = al::span{reinterpret_cast(out.data()), out.size()/4}; + + const auto gain4 = vdupq_n_f32(TargetGain); + std::transform(in4.begin(), in4.end(), out4.begin(), out4.begin(), + [gain4](const float32x4_t val4, const float32x4_t dry4) -> float32x4_t + { return vmlaq_f32(dry4, val4, gain4); }); + pos += in4.size()*4; + } + if(const size_t leftover{(InSamples.size()-pos)&3}) + { + const auto in = InSamples.last(leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [TargetGain](const float val, const float dry) noexcept -> float + { return dry + val*TargetGain; }); } - for(size_t leftover{(InSamples.size()-pos)&3};leftover;++pos,--leftover) - dst[pos] += InSamples[pos] * gain; } } // namespace template<> -void Resample_(const InterpState*, const float *RESTRICT src, uint frac, +void Resample_(const InterpState*, const al::span src, uint frac, const uint increment, const al::span dst) { ASSUME(frac < MixerFracOne); - const int32x4_t increment4 = vdupq_n_s32(static_cast(increment*4)); + const uint32x4_t increment4 = vdupq_n_u32(increment*4u); const float32x4_t fracOne4 = vdupq_n_f32(1.0f/MixerFracOne); - const int32x4_t fracMask4 = vdupq_n_s32(MixerFracMask); - alignas(16) uint pos_[4], frac_[4]; - int32x4_t pos4, frac4; + const uint32x4_t fracMask4 = vdupq_n_u32(MixerFracMask); - InitPosArrays(frac, increment, frac_, pos_); - frac4 = vld1q_s32(reinterpret_cast(frac_)); - pos4 = vld1q_s32(reinterpret_cast(pos_)); + alignas(16) std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge, frac, increment, al::span{frac_}, al::span{pos_}); + uint32x4_t frac4 = vld1q_u32(frac_.data()); + uint32x4_t pos4 = vld1q_u32(pos_.data()); - auto dst_iter = dst.begin(); - for(size_t todo{dst.size()>>2};todo;--todo) + auto vecout = al::span{reinterpret_cast(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4]() -> float32x4_t { - const int pos0{vgetq_lane_s32(pos4, 0)}; - const int pos1{vgetq_lane_s32(pos4, 1)}; - const int pos2{vgetq_lane_s32(pos4, 2)}; - const int pos3{vgetq_lane_s32(pos4, 3)}; + const uint pos0{vgetq_lane_u32(pos4, 0)}; + const uint pos1{vgetq_lane_u32(pos4, 1)}; + const uint pos2{vgetq_lane_u32(pos4, 2)}; + const uint pos3{vgetq_lane_u32(pos4, 3)}; + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); const float32x4_t val1{set_f4(src[pos0], src[pos1], src[pos2], src[pos3])}; - const float32x4_t val2{set_f4(src[pos0+1], src[pos1+1], src[pos2+1], src[pos3+1])}; + const float32x4_t val2{set_f4(src[pos0+1_uz], src[pos1+1_uz], src[pos2+1_uz], src[pos3+1_uz])}; /* val1 + (val2-val1)*mu */ const float32x4_t r0{vsubq_f32(val2, val1)}; - const float32x4_t mu{vmulq_f32(vcvtq_f32_s32(frac4), fracOne4)}; + const float32x4_t mu{vmulq_f32(vcvtq_f32_u32(frac4), fracOne4)}; const float32x4_t out{vmlaq_f32(val1, mu, r0)}; - vst1q_f32(dst_iter, out); - dst_iter += 4; - - frac4 = vaddq_s32(frac4, increment4); - pos4 = vaddq_s32(pos4, vshrq_n_s32(frac4, MixerFracBits)); - frac4 = vandq_s32(frac4, fracMask4); - } + frac4 = vaddq_u32(frac4, increment4); + pos4 = vaddq_u32(pos4, vshrq_n_u32(frac4, MixerFracBits)); + frac4 = vandq_u32(frac4, fracMask4); + return out; + }); if(size_t todo{dst.size()&3}) { - src += static_cast(vgetq_lane_s32(pos4, 0)); - frac = static_cast(vgetq_lane_s32(frac4, 0)); + auto pos = size_t{vgetq_lane_u32(pos4, 0)}; + frac = vgetq_lane_u32(frac4, 0); - do { - *(dst_iter++) = lerpf(src[0], src[1], static_cast(frac) * (1.0f/MixerFracOne)); + const auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment] + { + const float output{lerpf(src[pos+0], src[pos+1], + static_cast(frac) * (1.0f/MixerFracOne))}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } while(--todo); + return output; + }); } } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { ASSUME(frac < MixerFracOne); - const CubicCoefficients *RESTRICT filter = al::assume_aligned<16>(state->cubic.filter); + const auto filter = std::get(*state).filter; - src -= 1; - for(float &out_sample : dst) + const uint32x4_t increment4{vdupq_n_u32(increment*4u)}; + const uint32x4_t fracMask4{vdupq_n_u32(MixerFracMask)}; + const float32x4_t fracDiffOne4{vdupq_n_f32(1.0f/CubicPhaseDiffOne)}; + const uint32x4_t fracDiffMask4{vdupq_n_u32(CubicPhaseDiffMask)}; + + alignas(16) std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge-1, frac, increment, al::span{frac_}, al::span{pos_}); + uint32x4_t frac4{vld1q_u32(frac_.data())}; + uint32x4_t pos4{vld1q_u32(pos_.data())}; + + auto vecout = al::span{reinterpret_cast(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4] + { + const uint pos0{vgetq_lane_u32(pos4, 0)}; + const uint pos1{vgetq_lane_u32(pos4, 1)}; + const uint pos2{vgetq_lane_u32(pos4, 2)}; + const uint pos3{vgetq_lane_u32(pos4, 3)}; + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); + const float32x4_t val0{vld1q_f32(&src[pos0])}; + const float32x4_t val1{vld1q_f32(&src[pos1])}; + const float32x4_t val2{vld1q_f32(&src[pos2])}; + const float32x4_t val3{vld1q_f32(&src[pos3])}; + + const uint32x4_t pi4{vshrq_n_u32(frac4, CubicPhaseDiffBits)}; + const uint pi0{vgetq_lane_u32(pi4, 0)}; ASSUME(pi0 < CubicPhaseCount); + const uint pi1{vgetq_lane_u32(pi4, 1)}; ASSUME(pi1 < CubicPhaseCount); + const uint pi2{vgetq_lane_u32(pi4, 2)}; ASSUME(pi2 < CubicPhaseCount); + const uint pi3{vgetq_lane_u32(pi4, 3)}; ASSUME(pi3 < CubicPhaseCount); + + const float32x4_t pf4{vmulq_f32(vcvtq_f32_u32(vandq_u32(frac4, fracDiffMask4)), + fracDiffOne4)}; + + float32x4_t r0{vmulq_f32(val0, + vmlaq_f32(vld1q_f32(filter[pi0].mCoeffs.data()), vdupq_lane_f32(vget_low_f32(pf4), 0), + vld1q_f32(filter[pi0].mDeltas.data())))}; + float32x4_t r1{vmulq_f32(val1, + vmlaq_f32(vld1q_f32(filter[pi1].mCoeffs.data()), vdupq_lane_f32(vget_low_f32(pf4), 1), + vld1q_f32(filter[pi1].mDeltas.data())))}; + float32x4_t r2{vmulq_f32(val2, + vmlaq_f32(vld1q_f32(filter[pi2].mCoeffs.data()), vdupq_lane_f32(vget_high_f32(pf4), 0), + vld1q_f32(filter[pi2].mDeltas.data())))}; + float32x4_t r3{vmulq_f32(val3, + vmlaq_f32(vld1q_f32(filter[pi3].mCoeffs.data()), vdupq_lane_f32(vget_high_f32(pf4), 1), + vld1q_f32(filter[pi3].mDeltas.data())))}; + + vtranspose4(r0, r1, r2, r3); + r0 = vaddq_f32(vaddq_f32(r0, r1), vaddq_f32(r2, r3)); + + frac4 = vaddq_u32(frac4, increment4); + pos4 = vaddq_u32(pos4, vshrq_n_u32(frac4, MixerFracBits)); + frac4 = vandq_u32(frac4, fracMask4); + return r0; + }); + + if(const size_t todo{dst.size()&3}) { - const uint pi{frac >> CubicPhaseDiffBits}; - const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; - const float32x4_t pf4{vdupq_n_f32(pf)}; + auto pos = size_t{vgetq_lane_u32(pos4, 0)}; + frac = vgetq_lane_u32(frac4, 0); - /* Apply the phase interpolated filter. */ + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment,filter] + { + const uint pi{frac >> CubicPhaseDiffBits}; ASSUME(pi < CubicPhaseCount); + const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; + const float32x4_t pf4{vdupq_n_f32(pf)}; - /* f = fil + pf*phd */ - const float32x4_t f4 = vmlaq_f32(vld1q_f32(filter[pi].mCoeffs), pf4, - vld1q_f32(filter[pi].mDeltas)); - /* r = f*src */ - float32x4_t r4{vmulq_f32(f4, vld1q_f32(src))}; + const float32x4_t f4{vmlaq_f32(vld1q_f32(filter[pi].mCoeffs.data()), pf4, + vld1q_f32(filter[pi].mDeltas.data()))}; + float32x4_t r4{vmulq_f32(f4, vld1q_f32(&src[pos]))}; - r4 = vaddq_f32(r4, vrev64q_f32(r4)); - out_sample = vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + r4 = vaddq_f32(r4, vrev64q_f32(r4)); + const float output{vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0)}; - frac += increment; - src += frac>>MixerFracBits; - frac &= MixerFracMask; + frac += increment; + pos += frac>>MixerFracBits; + frac &= MixerFracMask; + return output; + }); } } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { - const float *const filter{state->bsinc.filter}; - const float32x4_t sf4{vdupq_n_f32(state->bsinc.sf)}; - const size_t m{state->bsinc.m}; + const auto &bsinc = std::get(*state); + const auto sf4 = vdupq_n_f32(bsinc.sf); + const auto m = size_t{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); ASSUME(frac < MixerFracOne); - src -= state->bsinc.l; - for(float &out_sample : dst) + const auto filter = bsinc.filter.first(4_uz*BSincPhaseCount*m); + + ASSUME(bsinc.l <= MaxResamplerEdge); + auto pos = size_t{MaxResamplerEdge-bsinc.l}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment,sf4,m,filter]() -> float { // Calculate the phase index and factor. - const uint pi{frac >> BSincPhaseDiffBits}; + const uint pi{frac >> BSincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BSincPhaseDiffMask) * (1.0f/BSincPhaseDiffOne)}; // Apply the scale and phase interpolated filter. float32x4_t r4{vdupq_n_f32(0.0f)}; { const float32x4_t pf4{vdupq_n_f32(pf)}; - const float *RESTRICT fil{filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; - const float *RESTRICT scd{fil + BSincPhaseCount*2*m}; - const float *RESTRICT spd{scd + m}; + const auto fil = filter.subspan(2_uz*pi*m); + const auto phd = fil.subspan(m); + const auto scd = fil.subspan(2_uz*BSincPhaseCount*m); + const auto spd = scd.subspan(m); size_t td{m >> 2}; size_t j{0u}; @@ -257,41 +373,46 @@ void Resample_(const InterpState *state, const float *RESTRICT vmlaq_f32(vld1q_f32(&fil[j]), sf4, vld1q_f32(&scd[j])), pf4, vmlaq_f32(vld1q_f32(&phd[j]), sf4, vld1q_f32(&spd[j]))); /* r += f*src */ - r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[j])); + r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[pos+j])); j += 4; } while(--td); } r4 = vaddq_f32(r4, vrev64q_f32(r4)); - out_sample = vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + const float output{vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { - const float *const filter{state->bsinc.filter}; - const size_t m{state->bsinc.m}; + const auto &bsinc = std::get(*state); + const auto m = size_t{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); ASSUME(frac < MixerFracOne); - src -= state->bsinc.l; - for(float &out_sample : dst) + const auto filter = bsinc.filter.first(2_uz*BSincPhaseCount*m); + + ASSUME(bsinc.l <= MaxResamplerEdge); + auto pos = size_t{MaxResamplerEdge-bsinc.l}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment,m,filter]() -> float { // Calculate the phase index and factor. - const uint pi{frac >> BSincPhaseDiffBits}; + const uint pi{frac >> BSincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BSincPhaseDiffMask) * (1.0f/BSincPhaseDiffOne)}; // Apply the phase interpolated filter. float32x4_t r4{vdupq_n_f32(0.0f)}; { const float32x4_t pf4{vdupq_n_f32(pf)}; - const float *RESTRICT fil{filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; + const auto fil = filter.subspan(2_uz*pi*m); + const auto phd = fil.subspan(m); size_t td{m >> 2}; size_t j{0u}; @@ -299,64 +420,75 @@ void Resample_(const InterpState *state, const float *REST /* f = fil + pf*phd */ const float32x4_t f4 = vmlaq_f32(vld1q_f32(&fil[j]), pf4, vld1q_f32(&phd[j])); /* r += f*src */ - r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[j])); + r4 = vmlaq_f32(r4, f4, vld1q_f32(&src[pos+j])); j += 4; } while(--td); } r4 = vaddq_f32(r4, vrev64q_f32(r4)); - out_sample = vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0); + const float output{vget_lane_f32(vadd_f32(vget_low_f32(r4), vget_high_f32(r4)), 0)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } template<> -void MixHrtf_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } +void MixHrtf_(const al::span InSamples, const al::span AccumSamples, + const uint IrSize, const MixHrtfFilter *hrtfparams, const size_t SamplesToDo) +{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, SamplesToDo); } template<> -void MixHrtfBlend_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const HrtfFilter *oldparams, const MixHrtfFilter *newparams, const size_t BufferSize) +void MixHrtfBlend_(const al::span InSamples, + const al::span AccumSamples, const uint IrSize, const HrtfFilter *oldparams, + const MixHrtfFilter *newparams, const size_t SamplesToDo) { MixHrtfBlendBase(InSamples, AccumSamples, IrSize, oldparams, newparams, - BufferSize); + SamplesToDo); } template<> void MixDirectHrtf_(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *AccumSamples, - float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize) + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChanState, + const size_t IrSize, const size_t SamplesToDo) { MixDirectHrtfBase(LeftOut, RightOut, InSamples, AccumSamples, TempBuf, ChanState, - IrSize, BufferSize); + IrSize, SamplesToDo); } template<> -void Mix_(const al::span InSamples, const al::span OutBuffer, - float *CurrentGains, const float *TargetGains, const size_t Counter, const size_t OutPos) +void Mix_(const al::span InSamples,const al::span OutBuffer, + const al::span CurrentGains, const al::span TargetGains, + const size_t Counter, const size_t OutPos) { + if((OutPos&3) != 0) UNLIKELY + return Mix_(InSamples, OutBuffer, CurrentGains, TargetGains, Counter, OutPos); + const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; + const auto fade_len = std::min(Counter, InSamples.size()); + const auto realign_len = std::min((fade_len+3_uz) & ~3_uz, InSamples.size()) - fade_len; + auto curgains = CurrentGains.begin(); + auto targetgains = TargetGains.cbegin(); for(FloatBufferLine &output : OutBuffer) - MixLine(InSamples, al::assume_aligned<16>(output.data()+OutPos), *CurrentGains++, - *TargetGains++, delta, min_len, aligned_len, Counter); + MixLine(InSamples, al::span{output}.subspan(OutPos), *curgains++, *targetgains++, delta, + fade_len, realign_len, Counter); } template<> -void Mix_(const al::span InSamples, float *OutBuffer, float &CurrentGain, - const float TargetGain, const size_t Counter) +void Mix_(const al::span InSamples, const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const size_t Counter) { + if((reinterpret_cast(OutBuffer.data())&15) != 0) UNLIKELY + return Mix_(InSamples, OutBuffer, CurrentGain, TargetGain, Counter); + const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; + const auto fade_len = std::min(Counter, InSamples.size()); + const auto realign_len = std::min((fade_len+3_uz) & ~3_uz, InSamples.size()) - fade_len; - MixLine(InSamples, al::assume_aligned<16>(OutBuffer), CurrentGain, TargetGain, delta, min_len, - aligned_len, Counter); + MixLine(InSamples, OutBuffer, CurrentGain, TargetGain, delta, fade_len, realign_len, Counter); } diff --git a/3rdparty/openal/core/mixer/mixer_sse.cpp b/3rdparty/openal/core/mixer/mixer_sse.cpp index 70f77c14cf91..097cd9333087 100644 --- a/3rdparty/openal/core/mixer/mixer_sse.cpp +++ b/3rdparty/openal/core/mixer/mixer_sse.cpp @@ -1,16 +1,27 @@ #include "config.h" +#include #include -#include +#include +#include +#include +#include #include +#include #include "alnumeric.h" +#include "alspan.h" #include "core/bsinc_defs.h" +#include "core/bufferline.h" #include "core/cubic_defs.h" +#include "core/mixer/hrtfdefs.h" +#include "core/resampler_limits.h" #include "defs.h" #include "hrtfbase.h" +#include "opthelpers.h" +struct CTag; struct SSETag; struct CubicTag; struct BSincTag; @@ -31,42 +42,48 @@ constexpr uint CubicPhaseDiffBits{MixerFracBits - CubicPhaseBits}; constexpr uint CubicPhaseDiffOne{1 << CubicPhaseDiffBits}; constexpr uint CubicPhaseDiffMask{CubicPhaseDiffOne - 1u}; -#define MLA4(x, y, z) _mm_add_ps(x, _mm_mul_ps(y, z)) +force_inline __m128 vmadd(const __m128 x, const __m128 y, const __m128 z) noexcept +{ return _mm_add_ps(x, _mm_mul_ps(y, z)); } -inline void ApplyCoeffs(float2 *RESTRICT Values, const size_t IrSize, const ConstHrirSpan Coeffs, - const float left, const float right) +inline void ApplyCoeffs(const al::span Values, const size_t IrSize, + const ConstHrirSpan Coeffs, const float left, const float right) { - const __m128 lrlr{_mm_setr_ps(left, right, left, right)}; - ASSUME(IrSize >= MinIrLength); + ASSUME(IrSize <= HrirLength); + const auto lrlr = _mm_setr_ps(left, right, left, right); + /* Round up the IR size to a multiple of 2 for SIMD (2 IRs for 2 channels + * is 4 floats), to avoid cutting the last sample for odd IR counts. The + * underlying HRIR is a fixed-size multiple of 2, any extra samples are + * either 0 (silence) or more IR samples that get applied for "free". + */ + const auto count4 = size_t{(IrSize+1) >> 1}; + /* This isn't technically correct to test alignment, but it's true for * systems that support SSE, which is the only one that needs to know the * alignment of Values (which alternates between 8- and 16-byte aligned). */ - if(!(reinterpret_cast(Values)&15)) + if(!(reinterpret_cast(Values.data())&15)) { - for(size_t i{0};i < IrSize;i += 2) - { - const __m128 coeffs{_mm_load_ps(Coeffs[i].data())}; - __m128 vals{_mm_load_ps(Values[i].data())}; - vals = MLA4(vals, lrlr, coeffs); - _mm_store_ps(Values[i].data(), vals); - } + const auto vals4 = al::span{reinterpret_cast<__m128*>(Values[0].data()), count4}; + const auto coeffs4 = al::span{reinterpret_cast(Coeffs[0].data()), count4}; + + std::transform(vals4.cbegin(), vals4.cend(), coeffs4.cbegin(), vals4.begin(), + [lrlr](const __m128 &val, const __m128 &coeff) -> __m128 + { return vmadd(val, coeff, lrlr); }); } else { - __m128 imp0, imp1; - __m128 coeffs{_mm_load_ps(Coeffs[0].data())}; - __m128 vals{_mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64*>(Values[0].data()))}; - imp0 = _mm_mul_ps(lrlr, coeffs); + auto coeffs = _mm_load_ps(Coeffs[0].data()); + auto vals = _mm_loadl_pi(_mm_setzero_ps(), reinterpret_cast<__m64*>(Values[0].data())); + auto imp0 = _mm_mul_ps(lrlr, coeffs); vals = _mm_add_ps(imp0, vals); _mm_storel_pi(reinterpret_cast<__m64*>(Values[0].data()), vals); - size_t td{((IrSize+1)>>1) - 1}; + size_t td{count4 - 1}; size_t i{1}; do { coeffs = _mm_load_ps(Coeffs[i+1].data()); vals = _mm_load_ps(Values[i].data()); - imp1 = _mm_mul_ps(lrlr, coeffs); + const auto imp1 = _mm_mul_ps(lrlr, coeffs); imp0 = _mm_shuffle_ps(imp0, imp1, _MM_SHUFFLE(1, 0, 3, 2)); vals = _mm_add_ps(imp0, vals); _mm_store_ps(Values[i].data(), vals); @@ -80,37 +97,38 @@ inline void ApplyCoeffs(float2 *RESTRICT Values, const size_t IrSize, const Cons } } -force_inline void MixLine(const al::span InSamples, float *RESTRICT dst, - float &CurrentGain, const float TargetGain, const float delta, const size_t min_len, - const size_t aligned_len, size_t Counter) +force_inline void MixLine(const al::span InSamples, const al::span dst, + float &CurrentGain, const float TargetGain, const float delta, const size_t fade_len, + const size_t realign_len, size_t Counter) { - float gain{CurrentGain}; - const float step{(TargetGain-gain) * delta}; + const auto step = float{(TargetGain-CurrentGain) * delta}; size_t pos{0}; - if(!(std::abs(step) > std::numeric_limits::epsilon())) - gain = TargetGain; - else + if(std::abs(step) > std::numeric_limits::epsilon()) { - float step_count{0.0f}; + const auto gain = CurrentGain; + auto step_count = 0.0f; /* Mix with applying gain steps in aligned multiples of 4. */ - if(size_t todo{min_len >> 2}) + if(const size_t todo{fade_len >> 2}) { - const __m128 four4{_mm_set1_ps(4.0f)}; - const __m128 step4{_mm_set1_ps(step)}; - const __m128 gain4{_mm_set1_ps(gain)}; - __m128 step_count4{_mm_setr_ps(0.0f, 1.0f, 2.0f, 3.0f)}; - do { - const __m128 val4{_mm_load_ps(&InSamples[pos])}; - __m128 dry4{_mm_load_ps(&dst[pos])}; - - /* dry += val * (gain + step*step_count) */ - dry4 = MLA4(dry4, val4, MLA4(gain4, step4, step_count4)); + const auto four4 = _mm_set1_ps(4.0f); + const auto step4 = _mm_set1_ps(step); + const auto gain4 = _mm_set1_ps(gain); + auto step_count4 = _mm_setr_ps(0.0f, 1.0f, 2.0f, 3.0f); + + const auto in4 = al::span{reinterpret_cast(InSamples.data()), + InSamples.size()/4}.first(todo); + const auto out4 = al::span{reinterpret_cast<__m128*>(dst.data()), dst.size()/4}; + std::transform(in4.begin(), in4.end(), out4.begin(), out4.begin(), + [gain4,step4,four4,&step_count4](const __m128 val4, __m128 dry4) -> __m128 + { + /* dry += val * (gain + step*step_count) */ + dry4 = vmadd(dry4, val4, vmadd(gain4, step4, step_count4)); + step_count4 = _mm_add_ps(step_count4, four4); + return dry4; + }); + pos += in4.size()*4; - _mm_store_ps(&dst[pos], dry4); - step_count4 = _mm_add_ps(step_count4, four4); - pos += 4; - } while(--todo); /* NOTE: step_count4 now represents the next four counts after the * last four mixed samples, so the lowest element represents the * next step count to apply. @@ -118,210 +136,258 @@ force_inline void MixLine(const al::span InSamples, float *RESTRICT step_count = _mm_cvtss_f32(step_count4); } /* Mix with applying left over gain steps that aren't aligned multiples of 4. */ - for(size_t leftover{min_len&3};leftover;++pos,--leftover) + if(const size_t leftover{fade_len&3}) { - dst[pos] += InSamples[pos] * (gain + step*step_count); - step_count += 1.0f; + const auto in = InSamples.subspan(pos, leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [gain,step,&step_count](const float val, float dry) noexcept -> float + { + dry += val * (gain + step*step_count); + step_count += 1.0f; + return dry; + }); + pos += leftover; + } + if(pos < Counter) + { + CurrentGain = gain + step*step_count; + return; } - if(pos == Counter) - gain = TargetGain; - else - gain += step*step_count; /* Mix until pos is aligned with 4 or the mix is done. */ - for(size_t leftover{aligned_len&3};leftover;++pos,--leftover) - dst[pos] += InSamples[pos] * gain; + if(const size_t leftover{realign_len&3}) + { + const auto in = InSamples.subspan(pos, leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [TargetGain](const float val, const float dry) noexcept -> float + { return dry + val*TargetGain; }); + pos += leftover; + } } - CurrentGain = gain; + CurrentGain = TargetGain; - if(!(std::abs(gain) > GainSilenceThreshold)) + if(!(std::abs(TargetGain) > GainSilenceThreshold)) return; if(size_t todo{(InSamples.size()-pos) >> 2}) { - const __m128 gain4{_mm_set1_ps(gain)}; - do { - const __m128 val4{_mm_load_ps(&InSamples[pos])}; - __m128 dry4{_mm_load_ps(&dst[pos])}; - dry4 = _mm_add_ps(dry4, _mm_mul_ps(val4, gain4)); - _mm_store_ps(&dst[pos], dry4); - pos += 4; - } while(--todo); + const auto in4 = al::span{reinterpret_cast(InSamples.data()), + InSamples.size()/4}.last(todo); + const auto out = dst.subspan(pos); + const auto out4 = al::span{reinterpret_cast<__m128*>(out.data()), out.size()/4}; + + const auto gain4 = _mm_set1_ps(TargetGain); + std::transform(in4.begin(), in4.end(), out4.begin(), out4.begin(), + [gain4](const __m128 val4, const __m128 dry4) -> __m128 + { return vmadd(dry4, val4, gain4); }); + pos += in4.size()*4; + } + if(const size_t leftover{(InSamples.size()-pos)&3}) + { + const auto in = InSamples.last(leftover); + const auto out = dst.subspan(pos); + + std::transform(in.begin(), in.end(), out.begin(), out.begin(), + [TargetGain](const float val, const float dry) noexcept -> float + { return dry + val*TargetGain; }); } - for(size_t leftover{(InSamples.size()-pos)&3};leftover;++pos,--leftover) - dst[pos] += InSamples[pos] * gain; } } // namespace template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { ASSUME(frac < MixerFracOne); - const CubicCoefficients *RESTRICT filter = al::assume_aligned<16>(state->cubic.filter); + const auto filter = std::get(*state).filter; - src -= 1; - for(float &out_sample : dst) + size_t pos{MaxResamplerEdge-1}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment,filter]() -> float { - const uint pi{frac >> CubicPhaseDiffBits}; + const uint pi{frac >> CubicPhaseDiffBits}; ASSUME(pi < CubicPhaseCount); const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; const __m128 pf4{_mm_set1_ps(pf)}; /* Apply the phase interpolated filter. */ /* f = fil + pf*phd */ - const __m128 f4 = MLA4(_mm_load_ps(filter[pi].mCoeffs), pf4, - _mm_load_ps(filter[pi].mDeltas)); + const __m128 f4 = vmadd(_mm_load_ps(filter[pi].mCoeffs.data()), pf4, + _mm_load_ps(filter[pi].mDeltas.data())); /* r = f*src */ - __m128 r4{_mm_mul_ps(f4, _mm_loadu_ps(src))}; + __m128 r4{_mm_mul_ps(f4, _mm_loadu_ps(&src[pos]))}; r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); - out_sample = _mm_cvtss_f32(r4); + const float output{_mm_cvtss_f32(r4)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { - const float *const filter{state->bsinc.filter}; - const __m128 sf4{_mm_set1_ps(state->bsinc.sf)}; - const size_t m{state->bsinc.m}; + const auto &bsinc = std::get(*state); + const auto sf4 = _mm_set1_ps(bsinc.sf); + const auto m = size_t{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); ASSUME(frac < MixerFracOne); - src -= state->bsinc.l; - for(float &out_sample : dst) + const auto filter = bsinc.filter.first(4_uz*BSincPhaseCount*m); + + ASSUME(bsinc.l <= MaxResamplerEdge); + auto pos = size_t{MaxResamplerEdge-bsinc.l}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment,sf4,m,filter]() -> float { // Calculate the phase index and factor. - const uint pi{frac >> BSincPhaseDiffBits}; + const size_t pi{frac >> BSincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BSincPhaseDiffMask) * (1.0f/BSincPhaseDiffOne)}; // Apply the scale and phase interpolated filter. - __m128 r4{_mm_setzero_ps()}; + auto r4 = _mm_setzero_ps(); { - const __m128 pf4{_mm_set1_ps(pf)}; - const float *RESTRICT fil{filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; - const float *RESTRICT scd{fil + BSincPhaseCount*2*m}; - const float *RESTRICT spd{scd + m}; - size_t td{m >> 2}; - size_t j{0u}; + const auto pf4 = _mm_set1_ps(pf); + const auto fil = filter.subspan(2_uz*pi*m); + const auto phd = fil.subspan(m); + const auto scd = fil.subspan(2_uz*BSincPhaseCount*m); + const auto spd = scd.subspan(m); + auto td = size_t{m >> 2}; + auto j = size_t{0}; do { /* f = ((fil + sf*scd) + pf*(phd + sf*spd)) */ - const __m128 f4 = MLA4( - MLA4(_mm_load_ps(&fil[j]), sf4, _mm_load_ps(&scd[j])), - pf4, MLA4(_mm_load_ps(&phd[j]), sf4, _mm_load_ps(&spd[j]))); + const __m128 f4 = vmadd( + vmadd(_mm_load_ps(&fil[j]), sf4, _mm_load_ps(&scd[j])), + pf4, vmadd(_mm_load_ps(&phd[j]), sf4, _mm_load_ps(&spd[j]))); /* r += f*src */ - r4 = MLA4(r4, f4, _mm_loadu_ps(&src[j])); + r4 = vmadd(r4, f4, _mm_loadu_ps(&src[pos+j])); j += 4; } while(--td); } r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); - out_sample = _mm_cvtss_f32(r4); + const auto output = _mm_cvtss_f32(r4); frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } template<> -void Resample_(const InterpState *state, const float *RESTRICT src, uint frac, - const uint increment, const al::span dst) +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) { - const float *const filter{state->bsinc.filter}; - const size_t m{state->bsinc.m}; + const auto &bsinc = std::get(*state); + const auto m = size_t{bsinc.m}; ASSUME(m > 0); + ASSUME(m <= MaxResamplerPadding); ASSUME(frac < MixerFracOne); - src -= state->bsinc.l; - for(float &out_sample : dst) + const auto filter = bsinc.filter.first(2_uz*m*BSincPhaseCount); + + ASSUME(bsinc.l <= MaxResamplerEdge); + size_t pos{MaxResamplerEdge-bsinc.l}; + std::generate(dst.begin(), dst.end(), [&pos,&frac,src,increment,filter,m]() -> float { // Calculate the phase index and factor. - const uint pi{frac >> BSincPhaseDiffBits}; + const size_t pi{frac >> BSincPhaseDiffBits}; ASSUME(pi < BSincPhaseCount); const float pf{static_cast(frac&BSincPhaseDiffMask) * (1.0f/BSincPhaseDiffOne)}; // Apply the phase interpolated filter. - __m128 r4{_mm_setzero_ps()}; + auto r4 = _mm_setzero_ps(); { - const __m128 pf4{_mm_set1_ps(pf)}; - const float *RESTRICT fil{filter + m*pi*2}; - const float *RESTRICT phd{fil + m}; - size_t td{m >> 2}; - size_t j{0u}; + const auto pf4 = _mm_set1_ps(pf); + const auto fil = filter.subspan(2_uz*m*pi); + const auto phd = fil.subspan(m); + auto td = size_t{m >> 2}; + auto j = size_t{0}; do { /* f = fil + pf*phd */ - const __m128 f4 = MLA4(_mm_load_ps(&fil[j]), pf4, _mm_load_ps(&phd[j])); + const auto f4 = vmadd(_mm_load_ps(&fil[j]), pf4, _mm_load_ps(&phd[j])); /* r += f*src */ - r4 = MLA4(r4, f4, _mm_loadu_ps(&src[j])); + r4 = vmadd(r4, f4, _mm_loadu_ps(&src[pos+j])); j += 4; } while(--td); } r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); - out_sample = _mm_cvtss_f32(r4); + const auto output = _mm_cvtss_f32(r4); frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } + return output; + }); } template<> -void MixHrtf_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize) -{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, BufferSize); } +void MixHrtf_(const al::span InSamples, const al::span AccumSamples, + const uint IrSize, const MixHrtfFilter *hrtfparams, const size_t SamplesToDo) +{ MixHrtfBase(InSamples, AccumSamples, IrSize, hrtfparams, SamplesToDo); } template<> -void MixHrtfBlend_(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const HrtfFilter *oldparams, const MixHrtfFilter *newparams, const size_t BufferSize) +void MixHrtfBlend_(const al::span InSamples, + const al::span AccumSamples, const uint IrSize, const HrtfFilter *oldparams, + const MixHrtfFilter *newparams, const size_t SamplesToDo) { MixHrtfBlendBase(InSamples, AccumSamples, IrSize, oldparams, newparams, - BufferSize); + SamplesToDo); } template<> void MixDirectHrtf_(const FloatBufferSpan LeftOut, const FloatBufferSpan RightOut, - const al::span InSamples, float2 *AccumSamples, - float *TempBuf, HrtfChannelState *ChanState, const size_t IrSize, const size_t BufferSize) + const al::span InSamples, const al::span AccumSamples, + const al::span TempBuf, const al::span ChanState, + const size_t IrSize, const size_t SamplesToDo) { MixDirectHrtfBase(LeftOut, RightOut, InSamples, AccumSamples, TempBuf, ChanState, - IrSize, BufferSize); + IrSize, SamplesToDo); } template<> void Mix_(const al::span InSamples, const al::span OutBuffer, - float *CurrentGains, const float *TargetGains, const size_t Counter, const size_t OutPos) + const al::span CurrentGains, const al::span TargetGains, + const size_t Counter, const size_t OutPos) { + if((OutPos&3) != 0) UNLIKELY + return Mix_(InSamples, OutBuffer, CurrentGains, TargetGains, Counter, OutPos); + const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; + const auto fade_len = std::min(Counter, InSamples.size()); + const auto realign_len = std::min((fade_len+3_uz) & ~3_uz, InSamples.size()) - fade_len; + auto curgains = CurrentGains.begin(); + auto targetgains = TargetGains.cbegin(); for(FloatBufferLine &output : OutBuffer) - MixLine(InSamples, al::assume_aligned<16>(output.data()+OutPos), *CurrentGains++, - *TargetGains++, delta, min_len, aligned_len, Counter); + MixLine(InSamples, al::span{output}.subspan(OutPos), *curgains++, *targetgains++, delta, + fade_len, realign_len, Counter); } template<> -void Mix_(const al::span InSamples, float *OutBuffer, float &CurrentGain, - const float TargetGain, const size_t Counter) +void Mix_(const al::span InSamples, const al::span OutBuffer, + float &CurrentGain, const float TargetGain, const size_t Counter) { + if((reinterpret_cast(OutBuffer.data())&15) != 0) UNLIKELY + return Mix_(InSamples, OutBuffer, CurrentGain, TargetGain, Counter); + const float delta{(Counter > 0) ? 1.0f / static_cast(Counter) : 0.0f}; - const auto min_len = minz(Counter, InSamples.size()); - const auto aligned_len = minz((min_len+3) & ~3_uz, InSamples.size()) - min_len; + const auto fade_len = std::min(Counter, InSamples.size()); + const auto realign_len = std::min((fade_len+3_uz) & ~3_uz, InSamples.size()) - fade_len; - MixLine(InSamples, al::assume_aligned<16>(OutBuffer), CurrentGain, TargetGain, delta, min_len, - aligned_len, Counter); + MixLine(InSamples, OutBuffer, CurrentGain, TargetGain, delta, fade_len, realign_len, Counter); } diff --git a/3rdparty/openal/core/mixer/mixer_sse2.cpp b/3rdparty/openal/core/mixer/mixer_sse2.cpp index edaaf7a1a1fe..c79d50cabecf 100644 --- a/3rdparty/openal/core/mixer/mixer_sse2.cpp +++ b/3rdparty/openal/core/mixer/mixer_sse2.cpp @@ -23,19 +23,42 @@ #include #include +#include +#include +#include +#include + #include "alnumeric.h" +#include "alspan.h" +#include "core/cubic_defs.h" +#include "core/resampler_limits.h" #include "defs.h" +#include "opthelpers.h" struct SSE2Tag; struct LerpTag; +struct CubicTag; #if defined(__GNUC__) && !defined(__clang__) && !defined(__SSE2__) #pragma GCC target("sse2") #endif +using uint = unsigned int; + +namespace { + +constexpr uint CubicPhaseDiffBits{MixerFracBits - CubicPhaseBits}; +constexpr uint CubicPhaseDiffOne{1 << CubicPhaseDiffBits}; +constexpr uint CubicPhaseDiffMask{CubicPhaseDiffOne - 1u}; + +force_inline __m128 vmadd(const __m128 x, const __m128 y, const __m128 z) noexcept +{ return _mm_add_ps(x, _mm_mul_ps(y, z)); } + +} // namespace + template<> -void Resample_(const InterpState*, const float *RESTRICT src, uint frac, +void Resample_(const InterpState*, const al::span src, uint frac, const uint increment, const al::span dst) { ASSUME(frac < MixerFracOne); @@ -44,47 +67,148 @@ void Resample_(const InterpState*, const float *RESTRICT src, u const __m128 fracOne4{_mm_set1_ps(1.0f/MixerFracOne)}; const __m128i fracMask4{_mm_set1_epi32(MixerFracMask)}; - alignas(16) uint pos_[4], frac_[4]; - InitPosArrays(frac, increment, frac_, pos_); + std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge, frac, increment, al::span{frac_}, al::span{pos_}); __m128i frac4{_mm_setr_epi32(static_cast(frac_[0]), static_cast(frac_[1]), static_cast(frac_[2]), static_cast(frac_[3]))}; __m128i pos4{_mm_setr_epi32(static_cast(pos_[0]), static_cast(pos_[1]), static_cast(pos_[2]), static_cast(pos_[3]))}; - auto dst_iter = dst.begin(); - for(size_t todo{dst.size()>>2};todo;--todo) + auto vecout = al::span{reinterpret_cast<__m128*>(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4]() -> __m128 { - const int pos0{_mm_cvtsi128_si32(pos4)}; - const int pos1{_mm_cvtsi128_si32(_mm_srli_si128(pos4, 4))}; - const int pos2{_mm_cvtsi128_si32(_mm_srli_si128(pos4, 8))}; - const int pos3{_mm_cvtsi128_si32(_mm_srli_si128(pos4, 12))}; - const __m128 val1{_mm_setr_ps(src[pos0 ], src[pos1 ], src[pos2 ], src[pos3 ])}; - const __m128 val2{_mm_setr_ps(src[pos0+1], src[pos1+1], src[pos2+1], src[pos3+1])}; + const auto pos0 = static_cast(_mm_cvtsi128_si32(pos4)); + const auto pos1 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 4))); + const auto pos2 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 8))); + const auto pos3 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 12))); + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); + const __m128 val1{_mm_setr_ps(src[pos0], src[pos1], src[pos2], src[pos3])}; + const __m128 val2{_mm_setr_ps(src[pos0+1_uz], src[pos1+1_uz], src[pos2+1_uz], src[pos3+1_uz])}; /* val1 + (val2-val1)*mu */ const __m128 r0{_mm_sub_ps(val2, val1)}; const __m128 mu{_mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4)}; const __m128 out{_mm_add_ps(val1, _mm_mul_ps(mu, r0))}; - _mm_store_ps(dst_iter, out); - dst_iter += 4; - frac4 = _mm_add_epi32(frac4, increment4); pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, MixerFracBits)); frac4 = _mm_and_si128(frac4, fracMask4); - } + return out; + }); if(size_t todo{dst.size()&3}) { - src += static_cast(_mm_cvtsi128_si32(pos4)); + auto pos = size_t{static_cast(_mm_cvtsi128_si32(pos4))}; + frac = static_cast(_mm_cvtsi128_si32(frac4)); + + const auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment]() + { + const float smp{lerpf(src[pos+0], src[pos+1], + static_cast(frac) * (1.0f/MixerFracOne))}; + + frac += increment; + pos += frac>>MixerFracBits; + frac &= MixerFracMask; + return smp; + }); + } +} + +template<> +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) +{ + ASSUME(frac < MixerFracOne); + + const auto filter = std::get(*state).filter; + + const __m128i increment4{_mm_set1_epi32(static_cast(increment*4))}; + const __m128i fracMask4{_mm_set1_epi32(MixerFracMask)}; + const __m128 fracDiffOne4{_mm_set1_ps(1.0f/CubicPhaseDiffOne)}; + const __m128i fracDiffMask4{_mm_set1_epi32(CubicPhaseDiffMask)}; + + std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge-1, frac, increment, al::span{frac_}, al::span{pos_}); + __m128i frac4{_mm_setr_epi32(static_cast(frac_[0]), static_cast(frac_[1]), + static_cast(frac_[2]), static_cast(frac_[3]))}; + __m128i pos4{_mm_setr_epi32(static_cast(pos_[0]), static_cast(pos_[1]), + static_cast(pos_[2]), static_cast(pos_[3]))}; + + auto vecout = al::span{reinterpret_cast<__m128*>(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4] + { + const auto pos0 = static_cast(_mm_cvtsi128_si32(pos4)); + const auto pos1 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 4))); + const auto pos2 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 8))); + const auto pos3 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pos4, 12))); + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); + const __m128 val0{_mm_loadu_ps(&src[pos0])}; + const __m128 val1{_mm_loadu_ps(&src[pos1])}; + const __m128 val2{_mm_loadu_ps(&src[pos2])}; + const __m128 val3{_mm_loadu_ps(&src[pos3])}; + + const __m128i pi4{_mm_srli_epi32(frac4, CubicPhaseDiffBits)}; + const auto pi0 = static_cast(_mm_cvtsi128_si32(pi4)); + const auto pi1 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pi4, 4))); + const auto pi2 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pi4, 8))); + const auto pi3 = static_cast(_mm_cvtsi128_si32(_mm_srli_si128(pi4, 12))); + ASSUME(pi0 < CubicPhaseCount); ASSUME(pi1 < CubicPhaseCount); + ASSUME(pi2 < CubicPhaseCount); ASSUME(pi3 < CubicPhaseCount); + + const __m128 pf4{_mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(frac4, fracDiffMask4)), + fracDiffOne4)}; + + __m128 r0{_mm_mul_ps(val0, + vmadd(_mm_load_ps(filter[pi0].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_load_ps(filter[pi0].mDeltas.data())))}; + __m128 r1{_mm_mul_ps(val1, + vmadd(_mm_load_ps(filter[pi1].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(1, 1, 1, 1)), + _mm_load_ps(filter[pi1].mDeltas.data())))}; + __m128 r2{_mm_mul_ps(val2, + vmadd(_mm_load_ps(filter[pi2].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(2, 2, 2, 2)), + _mm_load_ps(filter[pi2].mDeltas.data())))}; + __m128 r3{_mm_mul_ps(val3, + vmadd(_mm_load_ps(filter[pi3].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(3, 3, 3, 3)), + _mm_load_ps(filter[pi3].mDeltas.data())))}; + + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + r0 = _mm_add_ps(_mm_add_ps(r0, r1), _mm_add_ps(r2, r3)); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, MixerFracBits)); + frac4 = _mm_and_si128(frac4, fracMask4); + return r0; + }); + + if(const size_t todo{dst.size()&3}) + { + auto pos = size_t{static_cast(_mm_cvtsi128_si32(pos4))}; frac = static_cast(_mm_cvtsi128_si32(frac4)); - do { - *(dst_iter++) = lerpf(src[0], src[1], static_cast(frac) * (1.0f/MixerFracOne)); + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment,filter] + { + const uint pi{frac >> CubicPhaseDiffBits}; ASSUME(pi < CubicPhaseCount); + const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; + const __m128 pf4{_mm_set1_ps(pf)}; + + const __m128 f4 = vmadd(_mm_load_ps(filter[pi].mCoeffs.data()), pf4, + _mm_load_ps(filter[pi].mDeltas.data())); + __m128 r4{_mm_mul_ps(f4, _mm_loadu_ps(&src[pos]))}; + + r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); + r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); + const float output{_mm_cvtss_f32(r4)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } while(--todo); + return output; + }); } } diff --git a/3rdparty/openal/core/mixer/mixer_sse41.cpp b/3rdparty/openal/core/mixer/mixer_sse41.cpp index 8ccd9fd3a862..345330454413 100644 --- a/3rdparty/openal/core/mixer/mixer_sse41.cpp +++ b/3rdparty/openal/core/mixer/mixer_sse41.cpp @@ -24,19 +24,42 @@ #include #include +#include +#include +#include +#include + #include "alnumeric.h" +#include "alspan.h" +#include "core/cubic_defs.h" +#include "core/resampler_limits.h" #include "defs.h" +#include "opthelpers.h" struct SSE4Tag; struct LerpTag; +struct CubicTag; #if defined(__GNUC__) && !defined(__clang__) && !defined(__SSE4_1__) #pragma GCC target("sse4.1") #endif +using uint = unsigned int; + +namespace { + +constexpr uint CubicPhaseDiffBits{MixerFracBits - CubicPhaseBits}; +constexpr uint CubicPhaseDiffOne{1 << CubicPhaseDiffBits}; +constexpr uint CubicPhaseDiffMask{CubicPhaseDiffOne - 1u}; + +force_inline __m128 vmadd(const __m128 x, const __m128 y, const __m128 z) noexcept +{ return _mm_add_ps(x, _mm_mul_ps(y, z)); } + +} // namespace + template<> -void Resample_(const InterpState*, const float *RESTRICT src, uint frac, +void Resample_(const InterpState*, const al::span src, uint frac, const uint increment, const al::span dst) { ASSUME(frac < MixerFracOne); @@ -45,35 +68,34 @@ void Resample_(const InterpState*, const float *RESTRICT src, u const __m128 fracOne4{_mm_set1_ps(1.0f/MixerFracOne)}; const __m128i fracMask4{_mm_set1_epi32(MixerFracMask)}; - alignas(16) uint pos_[4], frac_[4]; - InitPosArrays(frac, increment, frac_, pos_); + std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge, frac, increment, al::span{frac_}, al::span{pos_}); __m128i frac4{_mm_setr_epi32(static_cast(frac_[0]), static_cast(frac_[1]), static_cast(frac_[2]), static_cast(frac_[3]))}; __m128i pos4{_mm_setr_epi32(static_cast(pos_[0]), static_cast(pos_[1]), static_cast(pos_[2]), static_cast(pos_[3]))}; - auto dst_iter = dst.begin(); - for(size_t todo{dst.size()>>2};todo;--todo) + auto vecout = al::span{reinterpret_cast<__m128*>(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4] { - const int pos0{_mm_extract_epi32(pos4, 0)}; - const int pos1{_mm_extract_epi32(pos4, 1)}; - const int pos2{_mm_extract_epi32(pos4, 2)}; - const int pos3{_mm_extract_epi32(pos4, 3)}; - const __m128 val1{_mm_setr_ps(src[pos0 ], src[pos1 ], src[pos2 ], src[pos3 ])}; - const __m128 val2{_mm_setr_ps(src[pos0+1], src[pos1+1], src[pos2+1], src[pos3+1])}; + const auto pos0 = static_cast(_mm_extract_epi32(pos4, 0)); + const auto pos1 = static_cast(_mm_extract_epi32(pos4, 1)); + const auto pos2 = static_cast(_mm_extract_epi32(pos4, 2)); + const auto pos3 = static_cast(_mm_extract_epi32(pos4, 3)); + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); + const __m128 val1{_mm_setr_ps(src[pos0], src[pos1], src[pos2], src[pos3])}; + const __m128 val2{_mm_setr_ps(src[pos0+1_uz], src[pos1+1_uz], src[pos2+1_uz], src[pos3+1_uz])}; /* val1 + (val2-val1)*mu */ const __m128 r0{_mm_sub_ps(val2, val1)}; const __m128 mu{_mm_mul_ps(_mm_cvtepi32_ps(frac4), fracOne4)}; const __m128 out{_mm_add_ps(val1, _mm_mul_ps(mu, r0))}; - _mm_store_ps(dst_iter, out); - dst_iter += 4; - frac4 = _mm_add_epi32(frac4, increment4); pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, MixerFracBits)); frac4 = _mm_and_si128(frac4, fracMask4); - } + return out; + }); if(size_t todo{dst.size()&3}) { @@ -81,15 +103,117 @@ void Resample_(const InterpState*, const float *RESTRICT src, u * four samples, so the lowest element is the next position to * resample. */ - src += static_cast(_mm_cvtsi128_si32(pos4)); + auto pos = size_t{static_cast(_mm_cvtsi128_si32(pos4))}; + frac = static_cast(_mm_cvtsi128_si32(frac4)); + + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment] + { + const float smp{lerpf(src[pos+0], src[pos+1], + static_cast(frac) * (1.0f/MixerFracOne))}; + + frac += increment; + pos += frac>>MixerFracBits; + frac &= MixerFracMask; + return smp; + }); + } +} + +template<> +void Resample_(const InterpState *state, const al::span src, + uint frac, const uint increment, const al::span dst) +{ + ASSUME(frac < MixerFracOne); + + const auto filter = std::get(*state).filter; + + const __m128i increment4{_mm_set1_epi32(static_cast(increment*4))}; + const __m128i fracMask4{_mm_set1_epi32(MixerFracMask)}; + const __m128 fracDiffOne4{_mm_set1_ps(1.0f/CubicPhaseDiffOne)}; + const __m128i fracDiffMask4{_mm_set1_epi32(CubicPhaseDiffMask)}; + + std::array pos_{}, frac_{}; + InitPosArrays(MaxResamplerEdge-1, frac, increment, al::span{frac_}, al::span{pos_}); + __m128i frac4{_mm_setr_epi32(static_cast(frac_[0]), static_cast(frac_[1]), + static_cast(frac_[2]), static_cast(frac_[3]))}; + __m128i pos4{_mm_setr_epi32(static_cast(pos_[0]), static_cast(pos_[1]), + static_cast(pos_[2]), static_cast(pos_[3]))}; + + auto vecout = al::span{reinterpret_cast<__m128*>(dst.data()), dst.size()/4}; + std::generate(vecout.begin(), vecout.end(), [=,&pos4,&frac4] + { + const auto pos0 = static_cast(_mm_extract_epi32(pos4, 0)); + const auto pos1 = static_cast(_mm_extract_epi32(pos4, 1)); + const auto pos2 = static_cast(_mm_extract_epi32(pos4, 2)); + const auto pos3 = static_cast(_mm_extract_epi32(pos4, 3)); + ASSUME(pos0 <= pos1); ASSUME(pos1 <= pos2); ASSUME(pos2 <= pos3); + const __m128 val0{_mm_loadu_ps(&src[pos0])}; + const __m128 val1{_mm_loadu_ps(&src[pos1])}; + const __m128 val2{_mm_loadu_ps(&src[pos2])}; + const __m128 val3{_mm_loadu_ps(&src[pos3])}; + + const __m128i pi4{_mm_srli_epi32(frac4, CubicPhaseDiffBits)}; + const auto pi0 = static_cast(_mm_extract_epi32(pi4, 0)); + const auto pi1 = static_cast(_mm_extract_epi32(pi4, 1)); + const auto pi2 = static_cast(_mm_extract_epi32(pi4, 2)); + const auto pi3 = static_cast(_mm_extract_epi32(pi4, 3)); + ASSUME(pi0 < CubicPhaseCount); ASSUME(pi1 < CubicPhaseCount); + ASSUME(pi2 < CubicPhaseCount); ASSUME(pi3 < CubicPhaseCount); + + const __m128 pf4{_mm_mul_ps(_mm_cvtepi32_ps(_mm_and_si128(frac4, fracDiffMask4)), + fracDiffOne4)}; + + __m128 r0{_mm_mul_ps(val0, + vmadd(_mm_load_ps(filter[pi0].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(0, 0, 0, 0)), + _mm_load_ps(filter[pi0].mDeltas.data())))}; + __m128 r1{_mm_mul_ps(val1, + vmadd(_mm_load_ps(filter[pi1].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(1, 1, 1, 1)), + _mm_load_ps(filter[pi1].mDeltas.data())))}; + __m128 r2{_mm_mul_ps(val2, + vmadd(_mm_load_ps(filter[pi2].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(2, 2, 2, 2)), + _mm_load_ps(filter[pi2].mDeltas.data())))}; + __m128 r3{_mm_mul_ps(val3, + vmadd(_mm_load_ps(filter[pi3].mCoeffs.data()), + _mm_shuffle_ps(pf4, pf4, _MM_SHUFFLE(3, 3, 3, 3)), + _mm_load_ps(filter[pi3].mDeltas.data())))}; + + _MM_TRANSPOSE4_PS(r0, r1, r2, r3); + r0 = _mm_add_ps(_mm_add_ps(r0, r1), _mm_add_ps(r2, r3)); + + frac4 = _mm_add_epi32(frac4, increment4); + pos4 = _mm_add_epi32(pos4, _mm_srli_epi32(frac4, MixerFracBits)); + frac4 = _mm_and_si128(frac4, fracMask4); + return r0; + }); + + if(const size_t todo{dst.size()&3}) + { + auto pos = size_t{static_cast(_mm_cvtsi128_si32(pos4))}; frac = static_cast(_mm_cvtsi128_si32(frac4)); - do { - *(dst_iter++) = lerpf(src[0], src[1], static_cast(frac) * (1.0f/MixerFracOne)); + auto out = dst.last(todo); + std::generate(out.begin(), out.end(), [&pos,&frac,src,increment,filter] + { + const uint pi{frac >> CubicPhaseDiffBits}; ASSUME(pi < CubicPhaseCount); + const float pf{static_cast(frac&CubicPhaseDiffMask) * (1.0f/CubicPhaseDiffOne)}; + const __m128 pf4{_mm_set1_ps(pf)}; + + const __m128 f4 = vmadd(_mm_load_ps(filter[pi].mCoeffs.data()), pf4, + _mm_load_ps(filter[pi].mDeltas.data())); + __m128 r4{_mm_mul_ps(f4, _mm_loadu_ps(&src[pos]))}; + + r4 = _mm_add_ps(r4, _mm_shuffle_ps(r4, r4, _MM_SHUFFLE(0, 1, 2, 3))); + r4 = _mm_add_ps(r4, _mm_movehl_ps(r4, r4)); + const float output{_mm_cvtss_f32(r4)}; frac += increment; - src += frac>>MixerFracBits; + pos += frac>>MixerFracBits; frac &= MixerFracMask; - } while(--todo); + return output; + }); } } diff --git a/3rdparty/openal/core/resampler_limits.h b/3rdparty/openal/core/resampler_limits.h index 9d4cefdae251..a32807e8e0e1 100644 --- a/3rdparty/openal/core/resampler_limits.h +++ b/3rdparty/openal/core/resampler_limits.h @@ -5,8 +5,8 @@ * Note that the padding is symmetric (half at the beginning and half at the * end)! */ -constexpr int MaxResamplerPadding{48}; +constexpr unsigned int MaxResamplerPadding{48}; -constexpr int MaxResamplerEdge{MaxResamplerPadding >> 1}; +constexpr unsigned int MaxResamplerEdge{MaxResamplerPadding >> 1}; #endif /* CORE_RESAMPLER_LIMITS_H */ diff --git a/3rdparty/openal/core/rtkit.cpp b/3rdparty/openal/core/rtkit.cpp index ff944ebf2b4f..717059ab88af 100644 --- a/3rdparty/openal/core/rtkit.cpp +++ b/3rdparty/openal/core/rtkit.cpp @@ -30,14 +30,14 @@ #include "rtkit.h" -#include +#include #ifndef _GNU_SOURCE #define _GNU_SOURCE #endif #include -#include +#include #include #include #ifdef __linux__ @@ -69,6 +69,7 @@ namespace { inline pid_t _gettid() { #ifdef __linux__ + /* NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg) */ return static_cast(syscall(SYS_gettid)); #elif defined(__FreeBSD__) long pid{}; @@ -153,29 +154,29 @@ int rtkit_get_int_property(DBusConnection *connection, const char *propname, lon } // namespace -int rtkit_get_max_realtime_priority(DBusConnection *connection) +int rtkit_get_max_realtime_priority(DBusConnection *system_bus) { long long retval{}; - int err{rtkit_get_int_property(connection, "MaxRealtimePriority", &retval)}; + int err{rtkit_get_int_property(system_bus, "MaxRealtimePriority", &retval)}; return err < 0 ? err : static_cast(retval); } -int rtkit_get_min_nice_level(DBusConnection *connection, int *min_nice_level) +int rtkit_get_min_nice_level(DBusConnection *system_bus, int *min_nice_level) { long long retval{}; - int err{rtkit_get_int_property(connection, "MinNiceLevel", &retval)}; + int err{rtkit_get_int_property(system_bus, "MinNiceLevel", &retval)}; if(err >= 0) *min_nice_level = static_cast(retval); return err; } -long long rtkit_get_rttime_usec_max(DBusConnection *connection) +long long rtkit_get_rttime_usec_max(DBusConnection *system_bus) { long long retval{}; - int err{rtkit_get_int_property(connection, "RTTimeUSecMax", &retval)}; + int err{rtkit_get_int_property(system_bus, "RTTimeUSecMax", &retval)}; return err < 0 ? err : retval; } -int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) +int rtkit_make_realtime(DBusConnection *system_bus, pid_t thread, int priority) { if(thread == 0) thread = _gettid(); @@ -195,7 +196,7 @@ int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) if(!ready) return -ENOMEM; dbus::Error error; - dbus::MessagePtr r{dbus_connection_send_with_reply_and_block(connection, m.get(), -1, + dbus::MessagePtr r{dbus_connection_send_with_reply_and_block(system_bus, m.get(), -1, &error.get())}; if(!r) return translate_error(error->name); @@ -205,7 +206,7 @@ int rtkit_make_realtime(DBusConnection *connection, pid_t thread, int priority) return 0; } -int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_level) +int rtkit_make_high_priority(DBusConnection *system_bus, pid_t thread, int nice_level) { if(thread == 0) thread = _gettid(); @@ -225,7 +226,7 @@ int rtkit_make_high_priority(DBusConnection *connection, pid_t thread, int nice_ if(!ready) return -ENOMEM; dbus::Error error; - dbus::MessagePtr r{dbus_connection_send_with_reply_and_block(connection, m.get(), -1, + dbus::MessagePtr r{dbus_connection_send_with_reply_and_block(system_bus, m.get(), -1, &error.get())}; if(!r) return translate_error(error->name); diff --git a/3rdparty/openal/core/storage_formats.cpp b/3rdparty/openal/core/storage_formats.cpp new file mode 100644 index 000000000000..b62f91a0a4d8 --- /dev/null +++ b/3rdparty/openal/core/storage_formats.cpp @@ -0,0 +1,89 @@ + +#include "config.h" + +#include "storage_formats.h" + +#include +#include + +namespace { +using namespace std::string_view_literals; +} // namespace + +auto NameFromFormat(FmtType type) noexcept -> std::string_view +{ + switch(type) + { + case FmtUByte: return "UInt8"sv; + case FmtShort: return "Int16"sv; + case FmtInt: return "Int32"sv; + case FmtFloat: return "Float"sv; + case FmtDouble: return "Double"sv; + case FmtMulaw: return "muLaw"sv; + case FmtAlaw: return "aLaw"sv; + case FmtIMA4: return "IMA4 ADPCM"sv; + case FmtMSADPCM: return "MS ADPCM"sv; + } + return ""sv; +} + +auto NameFromFormat(FmtChannels channels) noexcept -> std::string_view +{ + switch(channels) + { + case FmtMono: return "Mono"sv; + case FmtStereo: return "Stereo"sv; + case FmtRear: return "Rear"sv; + case FmtQuad: return "Quadraphonic"sv; + case FmtX51: return "Surround 5.1"sv; + case FmtX61: return "Surround 6.1"sv; + case FmtX71: return "Surround 7.1"sv; + case FmtBFormat2D: return "B-Format 2D"sv; + case FmtBFormat3D: return "B-Format 3D"sv; + case FmtUHJ2: return "UHJ2"sv; + case FmtUHJ3: return "UHJ3"sv; + case FmtUHJ4: return "UHJ4"sv; + case FmtSuperStereo: return "Super Stereo"sv; + case FmtMonoDup: return "Mono (dup)"sv; + } + return ""sv; +} + +uint BytesFromFmt(FmtType type) noexcept +{ + switch(type) + { + case FmtUByte: return sizeof(std::uint8_t); + case FmtShort: return sizeof(std::int16_t); + case FmtInt: return sizeof(std::int32_t); + case FmtFloat: return sizeof(float); + case FmtDouble: return sizeof(double); + case FmtMulaw: return sizeof(std::uint8_t); + case FmtAlaw: return sizeof(std::uint8_t); + case FmtIMA4: break; + case FmtMSADPCM: break; + } + return 0; +} + +uint ChannelsFromFmt(FmtChannels chans, uint ambiorder) noexcept +{ + switch(chans) + { + case FmtMono: return 1; + case FmtStereo: return 2; + case FmtRear: return 2; + case FmtQuad: return 4; + case FmtX51: return 6; + case FmtX61: return 7; + case FmtX71: return 8; + case FmtBFormat2D: return (ambiorder*2) + 1; + case FmtBFormat3D: return (ambiorder+1) * (ambiorder+1); + case FmtUHJ2: return 2; + case FmtUHJ3: return 3; + case FmtUHJ4: return 4; + case FmtSuperStereo: return 2; + case FmtMonoDup: return 1; + } + return 0; +} diff --git a/3rdparty/openal/core/storage_formats.h b/3rdparty/openal/core/storage_formats.h new file mode 100644 index 000000000000..fab0a04ce28d --- /dev/null +++ b/3rdparty/openal/core/storage_formats.h @@ -0,0 +1,56 @@ +#ifndef CORE_STORAGE_FORMATS_H +#define CORE_STORAGE_FORMATS_H + +#include + +using uint = unsigned int; + +/* Storable formats */ +enum FmtType : unsigned char { + FmtUByte, + FmtShort, + FmtInt, + FmtFloat, + FmtDouble, + FmtMulaw, + FmtAlaw, + FmtIMA4, + FmtMSADPCM, +}; +enum FmtChannels : unsigned char { + FmtMono, + FmtStereo, + FmtRear, + FmtQuad, + FmtX51, /* (WFX order) */ + FmtX61, /* (WFX order) */ + FmtX71, /* (WFX order) */ + FmtBFormat2D, + FmtBFormat3D, + FmtUHJ2, /* 2-channel UHJ, aka "BHJ", stereo-compatible */ + FmtUHJ3, /* 3-channel UHJ, aka "THJ" */ + FmtUHJ4, /* 4-channel UHJ, aka "PHJ" */ + FmtSuperStereo, /* Stereo processed with Super Stereo. */ + FmtMonoDup, /* Mono duplicated for left/right separation */ +}; + +enum class AmbiLayout : unsigned char { + FuMa, + ACN, +}; +enum class AmbiScaling : unsigned char { + FuMa, + SN3D, + N3D, + UHJ, +}; + +auto NameFromFormat(FmtType type) noexcept -> std::string_view; +auto NameFromFormat(FmtChannels channels) noexcept -> std::string_view; + +uint BytesFromFmt(FmtType type) noexcept; +uint ChannelsFromFmt(FmtChannels chans, uint ambiorder) noexcept; +inline uint FrameSizeFromFmt(FmtChannels chans, FmtType type, uint ambiorder) noexcept +{ return ChannelsFromFmt(chans, ambiorder) * BytesFromFmt(type); } + +#endif /* CORE_STORAGE_FORMATS_H */ diff --git a/3rdparty/openal/core/uhjfilter.cpp b/3rdparty/openal/core/uhjfilter.cpp index 4e4e99a54800..c432acc4e765 100644 --- a/3rdparty/openal/core/uhjfilter.cpp +++ b/3rdparty/openal/core/uhjfilter.cpp @@ -4,29 +4,116 @@ #include "uhjfilter.h" #include -#include +#include +#include +#include +#include #include "alcomplex.h" -#include "alnumeric.h" +#include "almalloc.h" +#include "alnumbers.h" +#include "core/bufferline.h" #include "opthelpers.h" +#include "pffft.h" #include "phase_shifter.h" +#include "vector.h" -UhjQualityType UhjDecodeQuality{UhjQualityType::Default}; -UhjQualityType UhjEncodeQuality{UhjQualityType::Default}; +namespace { +template +constexpr auto assume_aligned_span(const al::span s) noexcept -> al::span +{ return al::span{al::assume_aligned(s.data()), s.size()}; } -namespace { +/* Convolution is implemented using a segmented overlap-add method. The filter + * response is broken up into multiple segments of 128 samples, and each + * segment has an FFT applied with a 256-sample buffer (the latter half left + * silent) to get its frequency-domain response. + * + * Input samples are similarly broken up into 128-sample segments, with a 256- + * sample FFT applied to each new incoming segment to get its frequency-domain + * response. A history of FFT'd input segments is maintained, equal to the + * number of filter response segments. + * + * To apply the convolution, each filter response segment is convolved with its + * paired input segment (using complex multiplies, far cheaper than time-domain + * FIRs), accumulating into an FFT buffer. The input history is then shifted to + * align with later filter response segments for the next input segment. + * + * An inverse FFT is then applied to the accumulated FFT buffer to get a 256- + * sample time-domain response for output, which is split in two halves. The + * first half is the 128-sample output, and the second half is a 128-sample + * (really, 127) delayed extension, which gets added to the output next time. + * Convolving two time-domain responses of length N results in a time-domain + * signal of length N*2 - 1, and this holds true regardless of the convolution + * being applied in the frequency domain, so these "overflow" samples need to + * be accounted for. + */ +template +struct SegmentedFilter { + static constexpr size_t sFftLength{256}; + static constexpr size_t sSampleLength{sFftLength / 2}; + static constexpr size_t sNumSegments{N/sSampleLength}; + static_assert(N >= sFftLength); + static_assert((N % sSampleLength) == 0); + + PFFFTSetup mFft; + alignas(16) std::array mFilterData; + + SegmentedFilter() : mFft{sFftLength, PFFFT_REAL} + { + static constexpr size_t fft_size{N}; + + /* To set up the filter, we first need to generate the desired + * response (not reversed). + */ + auto tmpBuffer = std::vector(fft_size, 0.0); + for(std::size_t i{0};i < fft_size/2;++i) + { + const auto k = int{fft_size/2} - static_cast(i*2 + 1); + + const auto w = 2.0*al::numbers::pi/double{fft_size} * static_cast(i*2 + 1); + const auto window = 0.3635819 - 0.4891775*std::cos(w) + 0.1365995*std::cos(2.0*w) + - 0.0106411*std::cos(3.0*w); + + const auto pk = al::numbers::pi * static_cast(k); + tmpBuffer[i*2 + 1] = window * (1.0-std::cos(pk)) / pk; + } + + /* The segments of the filter are converted back to the frequency + * domain, each on their own (0 stuffed). + */ + using complex_d = std::complex; + auto fftBuffer = std::vector(sFftLength); + auto fftTmp = al::vector(sFftLength); + auto filter = mFilterData.begin(); + for(size_t s{0};s < sNumSegments;++s) + { + const auto tmpspan = al::span{tmpBuffer}.subspan(sSampleLength*s, sSampleLength); + auto iter = std::copy_n(tmpspan.cbegin(), tmpspan.size(), fftBuffer.begin()); + std::fill(iter, fftBuffer.end(), complex_d{}); + forward_fft(fftBuffer); + + /* Convert to zdomain data for PFFFT, scaled by the FFT length so + * the iFFT result will be normalized. + */ + for(size_t i{0};i < sSampleLength;++i) + { + fftTmp[i*2 + 0] = static_cast(fftBuffer[i].real()) / float{sFftLength}; + fftTmp[i*2 + 1] = static_cast((i == 0) ? fftBuffer[sSampleLength].real() + : fftBuffer[i].imag()) / float{sFftLength}; + } + mFft.zreorder(fftTmp.data(), al::to_address(filter), PFFFT_BACKWARD); + filter += sFftLength; + } + } +}; -const PhaseShifterT PShiftLq{}; -const PhaseShifterT PShiftHq{}; +template +const SegmentedFilter gSegmentedFilter; template -struct GetPhaseShifter; -template<> -struct GetPhaseShifter { static auto& Get() noexcept { return PShiftLq; } }; -template<> -struct GetPhaseShifter { static auto& Get() noexcept { return PShiftHq; } }; +const PhaseShifterT PShifter; /* Filter coefficients for the 'base' all-pass IIR, which applies a frequency- @@ -43,12 +130,24 @@ constexpr std::array Filter2Coeff{{ 0.161758498368f, 0.733028932341f, 0.945349700329f, 0.990599156684f }}; -} // namespace -void UhjAllPassFilter::process(const al::span coeffs, - const al::span src, const bool updateState, float *RESTRICT dst) +void processOne(UhjAllPassFilter &self, const al::span coeffs, float x) +{ + auto state = self.mState; + for(size_t i{0};i < 4;++i) + { + const float y{x*coeffs[i] + state[i].z[0]}; + state[i].z[0] = state[i].z[1]; + state[i].z[1] = y*coeffs[i] - x; + x = y; + } + self.mState = state; +} + +void process(UhjAllPassFilter &self, const al::span coeffs, + const al::span src, const bool updateState, const al::span dst) { - auto state = mState; + auto state = self.mState; auto proc_sample = [&state,coeffs](float x) noexcept -> float { @@ -61,10 +160,11 @@ void UhjAllPassFilter::process(const al::span coeffs, } return x; }; - std::transform(src.begin(), src.end(), dst, proc_sample); - if(updateState) LIKELY mState = state; + std::transform(src.begin(), src.end(), dst.begin(), proc_sample); + if(updateState) LIKELY self.mState = state; } +} // namespace /* Encoding UHJ from B-Format is done as: * @@ -87,68 +187,140 @@ template void UhjEncoder::encode(float *LeftOut, float *RightOut, const al::span InSamples, const size_t SamplesToDo) { - const auto &PShift = GetPhaseShifter::Get(); + static constexpr auto &Filter = gSegmentedFilter; + static_assert(sFftLength == Filter.sFftLength); + static_assert(sSegmentSize == Filter.sSampleLength); + static_assert(sNumSegments == Filter.sNumSegments); ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); - const float *RESTRICT winput{al::assume_aligned<16>(InSamples[0])}; - const float *RESTRICT xinput{al::assume_aligned<16>(InSamples[1])}; - const float *RESTRICT yinput{al::assume_aligned<16>(InSamples[2])}; + const auto winput = al::span{al::assume_aligned<16>(InSamples[0]), SamplesToDo}; + const auto xinput = al::span{al::assume_aligned<16>(InSamples[1]), SamplesToDo}; + const auto yinput = al::span{al::assume_aligned<16>(InSamples[2]), SamplesToDo}; - std::copy_n(winput, SamplesToDo, mW.begin()+sFilterDelay); - std::copy_n(xinput, SamplesToDo, mX.begin()+sFilterDelay); - std::copy_n(yinput, SamplesToDo, mY.begin()+sFilterDelay); + std::copy_n(winput.begin(), SamplesToDo, mW.begin()+sFilterDelay); + std::copy_n(xinput.begin(), SamplesToDo, mX.begin()+sFilterDelay); + std::copy_n(yinput.begin(), SamplesToDo, mY.begin()+sFilterDelay); /* S = 0.9396926*W + 0.1855740*X */ - for(size_t i{0};i < SamplesToDo;++i) - mS[i] = 0.9396926f*mW[i] + 0.1855740f*mX[i]; + std::transform(mW.begin(), mW.begin()+SamplesToDo, mX.begin(), mS.begin(), + [](const float w, const float x) noexcept { return 0.9396926f*w + 0.1855740f*x; }); /* Precompute j(-0.3420201*W + 0.5098604*X) and store in mD. */ - std::transform(winput, winput+SamplesToDo, xinput, mWX.begin() + sWXInOffset, - [](const float w, const float x) noexcept -> float - { return -0.3420201f*w + 0.5098604f*x; }); - PShift.process({mD.data(), SamplesToDo}, mWX.data()); + auto dstore = mD.begin(); + size_t curseg{mCurrentSegment}; + for(size_t base{0};base < SamplesToDo;) + { + const size_t todo{std::min(sSegmentSize-mFifoPos, SamplesToDo-base)}; + auto wseg = winput.subspan(base, todo); + auto xseg = xinput.subspan(base, todo); + /* Some Clang versions don't like calling subspan on an rvalue here. */ + const auto wxio_ = al::span{mWXInOut}; + auto wxio = wxio_.subspan(mFifoPos, todo); + + /* Copy out the samples that were previously processed by the FFT. */ + dstore = std::copy_n(wxio.begin(), todo, dstore); + + /* Transform the non-delayed input and store in the front half of the + * filter input. + */ + std::transform(wseg.begin(), wseg.end(), xseg.begin(), wxio.begin(), + [](const float w, const float x) noexcept -> float + { return -0.3420201f*w + 0.5098604f*x; }); + + mFifoPos += todo; + base += todo; + + /* Check whether the input buffer is filled with new samples. */ + if(mFifoPos < sSegmentSize) break; + mFifoPos = 0; + + /* Copy the new input to the next history segment, clearing the back + * half of the segment, and convert to the frequency domain. + */ + auto input = mWXHistory.begin() + curseg*sFftLength; + std::copy_n(mWXInOut.begin(), sSegmentSize, input); + std::fill_n(input+sSegmentSize, sSegmentSize, 0.0f); + + Filter.mFft.transform(al::to_address(input), al::to_address(input), mWorkData.data(), + PFFFT_FORWARD); + + /* Convolve each input segment with its IR filter counterpart (aligned + * in time, from newest to oldest). + */ + mFftBuffer.fill(0.0f); + auto filter = Filter.mFilterData.begin(); + for(size_t s{curseg};s < sNumSegments;++s) + { + Filter.mFft.zconvolve_accumulate(al::to_address(input), al::to_address(filter), + mFftBuffer.data()); + input += sFftLength; + filter += sFftLength; + } + input = mWXHistory.begin(); + for(size_t s{0};s < curseg;++s) + { + Filter.mFft.zconvolve_accumulate(al::to_address(input), al::to_address(filter), + mFftBuffer.data()); + input += sFftLength; + filter += sFftLength; + } + + /* Convert back to samples, writing to the output and storing the extra + * for next time. + */ + Filter.mFft.transform(mFftBuffer.data(), mFftBuffer.data(), mWorkData.data(), + PFFFT_BACKWARD); + + std::transform(mFftBuffer.begin(), mFftBuffer.begin()+sSegmentSize, + mWXInOut.begin()+sSegmentSize, mWXInOut.begin(), std::plus{}); + std::copy_n(mFftBuffer.begin()+sSegmentSize, sSegmentSize, mWXInOut.begin()+sSegmentSize); + + /* Shift the input history. */ + curseg = curseg ? (curseg-1) : (sNumSegments-1); + } + mCurrentSegment = curseg; /* D = j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y */ - for(size_t i{0};i < SamplesToDo;++i) - mD[i] = mD[i] + 0.6554516f*mY[i]; + std::transform(mD.begin(), mD.begin()+SamplesToDo, mY.begin(), mD.begin(), + [](const float jwx, const float y) noexcept { return jwx + 0.6554516f*y; }); /* Copy the future samples to the front for next time. */ std::copy(mW.cbegin()+SamplesToDo, mW.cbegin()+SamplesToDo+sFilterDelay, mW.begin()); std::copy(mX.cbegin()+SamplesToDo, mX.cbegin()+SamplesToDo+sFilterDelay, mX.begin()); std::copy(mY.cbegin()+SamplesToDo, mY.cbegin()+SamplesToDo+sFilterDelay, mY.begin()); - std::copy(mWX.cbegin()+SamplesToDo, mWX.cbegin()+SamplesToDo+sWXInOffset, mWX.begin()); /* Apply a delay to the existing output to align with the input delay. */ - auto *delayBuffer = mDirectDelay.data(); + auto delayBuffer = mDirectDelay.begin(); for(float *buffer : {LeftOut, RightOut}) { - float *distbuf{al::assume_aligned<16>(delayBuffer->data())}; + const auto distbuf = assume_aligned_span<16>(al::span{*delayBuffer}); ++delayBuffer; - float *inout{al::assume_aligned<16>(buffer)}; - auto inout_end = inout + SamplesToDo; - if(SamplesToDo >= sFilterDelay) LIKELY + const auto inout = al::span{al::assume_aligned<16>(buffer), SamplesToDo}; + if(SamplesToDo >= sFilterDelay) { - auto delay_end = std::rotate(inout, inout_end - sFilterDelay, inout_end); - std::swap_ranges(inout, delay_end, distbuf); + auto delay_end = std::rotate(inout.begin(), inout.end() - sFilterDelay, inout.end()); + std::swap_ranges(inout.begin(), delay_end, distbuf.begin()); } else { - auto delay_start = std::swap_ranges(inout, inout_end, distbuf); - std::rotate(distbuf, delay_start, distbuf + sFilterDelay); + auto delay_start = std::swap_ranges(inout.begin(), inout.end(), distbuf.begin()); + std::rotate(distbuf.begin(), delay_start, distbuf.begin() + sFilterDelay); } } /* Combine the direct signal with the produced output. */ /* Left = (S + D)/2.0 */ - float *RESTRICT left{al::assume_aligned<16>(LeftOut)}; - for(size_t i{0};i < SamplesToDo;i++) + const auto left = al::span{al::assume_aligned<16>(LeftOut), SamplesToDo}; + for(size_t i{0};i < SamplesToDo;++i) left[i] += (mS[i] + mD[i]) * 0.5f; + /* Right = (S - D)/2.0 */ - float *RESTRICT right{al::assume_aligned<16>(RightOut)}; - for(size_t i{0};i < SamplesToDo;i++) + const auto right = al::span{al::assume_aligned<16>(RightOut), SamplesToDo}; + for(size_t i{0};i < SamplesToDo;++i) right[i] += (mS[i] - mD[i]) * 0.5f; } @@ -171,47 +343,49 @@ void UhjEncoderIIR::encode(float *LeftOut, float *RightOut, const al::span InSamples, const size_t SamplesToDo) { ASSUME(SamplesToDo > 0); + ASSUME(SamplesToDo <= BufferLineSize); - const float *RESTRICT winput{al::assume_aligned<16>(InSamples[0])}; - const float *RESTRICT xinput{al::assume_aligned<16>(InSamples[1])}; - const float *RESTRICT yinput{al::assume_aligned<16>(InSamples[2])}; + const auto winput = al::span{al::assume_aligned<16>(InSamples[0]), SamplesToDo}; + const auto xinput = al::span{al::assume_aligned<16>(InSamples[1]), SamplesToDo}; + const auto yinput = al::span{al::assume_aligned<16>(InSamples[2]), SamplesToDo}; /* S = 0.9396926*W + 0.1855740*X */ - std::transform(winput, winput+SamplesToDo, xinput, mTemp.begin(), + std::transform(winput.begin(), winput.end(), xinput.begin(), mTemp.begin(), [](const float w, const float x) noexcept { return 0.9396926f*w + 0.1855740f*x; }); - mFilter1WX.process(Filter1Coeff, {mTemp.data(), SamplesToDo}, true, mS.data()+1); + process(mFilter1WX, Filter1Coeff, al::span{mTemp}.first(SamplesToDo), true, + al::span{mS}.subspan(1)); mS[0] = mDelayWX; mDelayWX = mS[SamplesToDo]; /* Precompute j(-0.3420201*W + 0.5098604*X) and store in mWX. */ - std::transform(winput, winput+SamplesToDo, xinput, mTemp.begin(), + std::transform(winput.begin(), winput.end(), xinput.begin(), mTemp.begin(), [](const float w, const float x) noexcept { return -0.3420201f*w + 0.5098604f*x; }); - mFilter2WX.process(Filter2Coeff, {mTemp.data(), SamplesToDo}, true, mWX.data()); + process(mFilter2WX, Filter2Coeff, al::span{mTemp}.first(SamplesToDo), true, mWX); /* Apply filter1 to Y and store in mD. */ - mFilter1Y.process(Filter1Coeff, {yinput, SamplesToDo}, SamplesToDo, mD.data()+1); + process(mFilter1Y, Filter1Coeff, yinput, true, al::span{mD}.subspan(1)); mD[0] = mDelayY; mDelayY = mD[SamplesToDo]; /* D = j(-0.3420201*W + 0.5098604*X) + 0.6554516*Y */ - for(size_t i{0};i < SamplesToDo;++i) - mD[i] = mWX[i] + 0.6554516f*mD[i]; + std::transform(mWX.begin(), mWX.begin()+SamplesToDo, mD.begin(), mD.begin(), + [](const float jwx, const float y) noexcept { return jwx + 0.6554516f*y; }); /* Apply the base filter to the existing output to align with the processed * signal. */ - mFilter1Direct[0].process(Filter1Coeff, {LeftOut, SamplesToDo}, true, mTemp.data()+1); + const auto left = al::span{al::assume_aligned<16>(LeftOut), SamplesToDo}; + process(mFilter1Direct[0], Filter1Coeff, left, true, al::span{mTemp}.subspan(1)); mTemp[0] = mDirectDelay[0]; mDirectDelay[0] = mTemp[SamplesToDo]; /* Left = (S + D)/2.0 */ - float *RESTRICT left{al::assume_aligned<16>(LeftOut)}; - for(size_t i{0};i < SamplesToDo;i++) + for(size_t i{0};i < SamplesToDo;++i) left[i] = (mS[i] + mD[i])*0.5f + mTemp[i]; - mFilter1Direct[1].process(Filter1Coeff, {RightOut, SamplesToDo}, true, mTemp.data()+1); + const auto right = al::span{al::assume_aligned<16>(RightOut), SamplesToDo}; + process(mFilter1Direct[1], Filter1Coeff, right, true, al::span{mTemp}.subspan(1)); mTemp[0] = mDirectDelay[1]; mDirectDelay[1] = mTemp[SamplesToDo]; /* Right = (S - D)/2.0 */ - float *RESTRICT right{al::assume_aligned<16>(RightOut)}; - for(size_t i{0};i < SamplesToDo;i++) + for(size_t i{0};i < SamplesToDo;++i) right[i] = (mS[i] - mD[i])*0.5f + mTemp[i]; } @@ -235,31 +409,29 @@ void UhjDecoder::decode(const al::span samples, const size_t samplesT { static_assert(sInputPadding <= sMaxPadding, "Filter padding is too large"); - const auto &PShift = GetPhaseShifter::Get(); + constexpr auto &PShift = PShifter; ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); { - const float *RESTRICT left{al::assume_aligned<16>(samples[0])}; - const float *RESTRICT right{al::assume_aligned<16>(samples[1])}; - const float *RESTRICT t{al::assume_aligned<16>(samples[2])}; + const auto left = al::span{al::assume_aligned<16>(samples[0]), samplesToDo+sInputPadding}; + const auto right = al::span{al::assume_aligned<16>(samples[1]), samplesToDo+sInputPadding}; + const auto t = al::span{al::assume_aligned<16>(samples[2]), samplesToDo+sInputPadding}; /* S = Left + Right */ - for(size_t i{0};i < samplesToDo+sInputPadding;++i) - mS[i] = left[i] + right[i]; + std::transform(left.begin(), left.end(), right.begin(), mS.begin(), std::plus{}); /* D = Left - Right */ - for(size_t i{0};i < samplesToDo+sInputPadding;++i) - mD[i] = left[i] - right[i]; + std::transform(left.begin(), left.end(), right.begin(), mD.begin(), std::minus{}); /* T */ - for(size_t i{0};i < samplesToDo+sInputPadding;++i) - mT[i] = t[i]; + std::copy(t.begin(), t.end(), mT.begin()); } - float *RESTRICT woutput{al::assume_aligned<16>(samples[0])}; - float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])}; - float *RESTRICT youtput{al::assume_aligned<16>(samples[2])}; + const auto woutput = al::span{al::assume_aligned<16>(samples[0]), samplesToDo}; + const auto xoutput = al::span{al::assume_aligned<16>(samples[1]), samplesToDo}; + const auto youtput = al::span{al::assume_aligned<16>(samples[2]), samplesToDo}; /* Precompute j(0.828331*D + 0.767820*T) and store in xoutput. */ auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin()); @@ -267,21 +439,22 @@ void UhjDecoder::decode(const al::span samples, const size_t samplesT [](const float d, const float t) noexcept { return 0.828331f*d + 0.767820f*t; }); if(updateState) LIKELY std::copy_n(mTemp.cbegin()+samplesToDo, mDTHistory.size(), mDTHistory.begin()); - PShift.process({xoutput, samplesToDo}, mTemp.data()); + PShift.process(xoutput, mTemp); /* W = 0.981532*S + 0.197484*j(0.828331*D + 0.767820*T) */ - for(size_t i{0};i < samplesToDo;++i) - woutput[i] = 0.981532f*mS[i] + 0.197484f*xoutput[i]; + std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), woutput.begin(), + [](const float s, const float jdt) noexcept { return 0.981532f*s + 0.197484f*jdt; }); + /* X = 0.418496*S - j(0.828331*D + 0.767820*T) */ - for(size_t i{0};i < samplesToDo;++i) - xoutput[i] = 0.418496f*mS[i] - xoutput[i]; + std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), xoutput.begin(), + [](const float s, const float jdt) noexcept { return 0.418496f*s - jdt; }); /* Precompute j*S and store in youtput. */ tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin()); std::copy_n(mS.cbegin(), samplesToDo+sInputPadding, tmpiter); if(updateState) LIKELY std::copy_n(mTemp.cbegin()+samplesToDo, mSHistory.size(), mSHistory.begin()); - PShift.process({youtput, samplesToDo}, mTemp.data()); + PShift.process(youtput, mTemp); /* Y = 0.795968*D - 0.676392*T + j(0.186633*S) */ for(size_t i{0};i < samplesToDo;++i) @@ -289,10 +462,10 @@ void UhjDecoder::decode(const al::span samples, const size_t samplesT if(samples.size() > 3) { - float *RESTRICT zoutput{al::assume_aligned<16>(samples[3])}; + const auto zoutput = al::span{al::assume_aligned<16>(samples[3]), samplesToDo}; /* Z = 1.023332*Q */ - for(size_t i{0};i < samplesToDo;++i) - zoutput[i] = 1.023332f*zoutput[i]; + std::transform(zoutput.begin(), zoutput.end(), zoutput.begin(), + [](const float q) noexcept { return 1.023332f*q; }); } } @@ -302,70 +475,68 @@ void UhjDecoderIIR::decode(const al::span samples, const size_t samplesT static_assert(sInputPadding <= sMaxPadding, "Filter padding is too large"); ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); { - const float *RESTRICT left{al::assume_aligned<16>(samples[0])}; - const float *RESTRICT right{al::assume_aligned<16>(samples[1])}; + const auto left = al::span{al::assume_aligned<16>(samples[0]), samplesToDo+sInputPadding}; + const auto right = al::span{al::assume_aligned<16>(samples[1]), samplesToDo+sInputPadding}; /* S = Left + Right */ - for(size_t i{0};i < samplesToDo;++i) - mS[i] = left[i] + right[i]; + std::transform(left.begin(), left.end(), right.begin(), mS.begin(), std::plus{}); /* D = Left - Right */ - for(size_t i{0};i < samplesToDo;++i) - mD[i] = left[i] - right[i]; + std::transform(left.begin(), left.end(), right.begin(), mD.begin(), std::minus{}); } - float *RESTRICT woutput{al::assume_aligned<16>(samples[0])}; - float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])}; - float *RESTRICT youtput{al::assume_aligned<16>(samples[2])}; + const auto woutput = al::span{al::assume_aligned<16>(samples[0]), samplesToDo}; + const auto xoutput = al::span{al::assume_aligned<16>(samples[1]), samplesToDo}; + const auto youtput = al::span{al::assume_aligned<16>(samples[2]), samplesToDo+sInputPadding}; /* Precompute j(0.828331*D + 0.767820*T) and store in xoutput. */ - std::transform(mD.cbegin(), mD.cbegin()+samplesToDo, youtput, mTemp.begin(), + std::transform(mD.cbegin(), mD.cbegin()+sInputPadding+samplesToDo, youtput.begin(), + mTemp.begin(), [](const float d, const float t) noexcept { return 0.828331f*d + 0.767820f*t; }); - mFilter2DT.process(Filter2Coeff, {mTemp.data(), samplesToDo}, updateState, xoutput); + if(mFirstRun) processOne(mFilter2DT, Filter2Coeff, mTemp[0]); + process(mFilter2DT, Filter2Coeff, al::span{mTemp}.subspan(1, samplesToDo), updateState, + xoutput); /* Apply filter1 to S and store in mTemp. */ - mTemp[0] = mDelayS; - mFilter1S.process(Filter1Coeff, {mS.data(), samplesToDo}, updateState, mTemp.data()+1); - if(updateState) LIKELY mDelayS = mTemp[samplesToDo]; + process(mFilter1S, Filter1Coeff, al::span{mS}.first(samplesToDo), updateState, mTemp); /* W = 0.981532*S + 0.197484*j(0.828331*D + 0.767820*T) */ - for(size_t i{0};i < samplesToDo;++i) - woutput[i] = 0.981532f*mTemp[i] + 0.197484f*xoutput[i]; + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), woutput.begin(), + [](const float s, const float jdt) noexcept { return 0.981532f*s + 0.197484f*jdt; }); /* X = 0.418496*S - j(0.828331*D + 0.767820*T) */ - for(size_t i{0};i < samplesToDo;++i) - xoutput[i] = 0.418496f*mTemp[i] - xoutput[i]; + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), xoutput.begin(), + [](const float s, const float jdt) noexcept { return 0.418496f*s - jdt; }); /* Apply filter1 to (0.795968*D - 0.676392*T) and store in mTemp. */ - std::transform(mD.cbegin(), mD.cbegin()+samplesToDo, youtput, youtput, + std::transform(mD.cbegin(), mD.cbegin()+samplesToDo, youtput.begin(), youtput.begin(), [](const float d, const float t) noexcept { return 0.795968f*d - 0.676392f*t; }); - mTemp[0] = mDelayDT; - mFilter1DT.process(Filter1Coeff, {youtput, samplesToDo}, updateState, mTemp.data()+1); - if(updateState) LIKELY mDelayDT = mTemp[samplesToDo]; + process(mFilter1DT, Filter1Coeff, youtput.first(samplesToDo), updateState, mTemp); /* Precompute j*S and store in youtput. */ - mFilter2S.process(Filter2Coeff, {mS.data(), samplesToDo}, updateState, youtput); + if(mFirstRun) processOne(mFilter2S, Filter2Coeff, mS[0]); + process(mFilter2S, Filter2Coeff, al::span{mS}.subspan(1, samplesToDo), updateState, youtput); /* Y = 0.795968*D - 0.676392*T + j(0.186633*S) */ - for(size_t i{0};i < samplesToDo;++i) - youtput[i] = mTemp[i] + 0.186633f*youtput[i]; - + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, youtput.begin(), youtput.begin(), + [](const float dt, const float js) noexcept { return dt + 0.186633f*js; }); if(samples.size() > 3) { - float *RESTRICT zoutput{al::assume_aligned<16>(samples[3])}; + const auto zoutput = al::span{al::assume_aligned<16>(samples[3]), samplesToDo}; /* Apply filter1 to Q and store in mTemp. */ - mTemp[0] = mDelayQ; - mFilter1Q.process(Filter1Coeff, {zoutput, samplesToDo}, updateState, mTemp.data()+1); - if(updateState) LIKELY mDelayQ = mTemp[samplesToDo]; + process(mFilter1Q, Filter1Coeff, zoutput, updateState, mTemp); /* Z = 1.023332*Q */ - for(size_t i{0};i < samplesToDo;++i) - zoutput[i] = 1.023332f*mTemp[i]; + std::transform(mTemp.begin(), mTemp.end(), zoutput.begin(), + [](const float q) noexcept { return 1.023332f*q; }); } + + mFirstRun = false; } @@ -374,9 +545,9 @@ void UhjDecoderIIR::decode(const al::span samples, const size_t samplesT * S = Left + Right * D = Left - Right * - * W = 0.6098637*S - 0.6896511*j*w*D - * X = 0.8624776*S + 0.7626955*j*w*D - * Y = 1.6822415*w*D - 0.2156194*j*S + * W = 0.6098637*S + 0.6896511*j*w*D + * X = 0.8624776*S - 0.7626955*j*w*D + * Y = 1.6822415*w*D + 0.2156194*j*S * * where j is a +90 degree phase shift. w is a variable control for the * resulting stereo width, with the range 0 <= w <= 0.7. @@ -387,16 +558,16 @@ void UhjStereoDecoder::decode(const al::span samples, const size_t sa { static_assert(sInputPadding <= sMaxPadding, "Filter padding is too large"); - const auto &PShift = GetPhaseShifter::Get(); + constexpr auto &PShift = PShifter; ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); { - const float *RESTRICT left{al::assume_aligned<16>(samples[0])}; - const float *RESTRICT right{al::assume_aligned<16>(samples[1])}; + const auto left = al::span{al::assume_aligned<16>(samples[0]), samplesToDo+sInputPadding}; + const auto right = al::span{al::assume_aligned<16>(samples[1]), samplesToDo+sInputPadding}; - for(size_t i{0};i < samplesToDo+sInputPadding;++i) - mS[i] = left[i] + right[i]; + std::transform(left.begin(), left.end(), right.begin(), mS.begin(), std::plus{}); /* Pre-apply the width factor to the difference signal D. Smoothly * interpolate when it changes. @@ -405,53 +576,60 @@ void UhjStereoDecoder::decode(const al::span samples, const size_t sa const float wcurrent{(mCurrentWidth < 0.0f) ? wtarget : mCurrentWidth}; if(wtarget == wcurrent || !updateState) { - for(size_t i{0};i < samplesToDo+sInputPadding;++i) - mD[i] = (left[i] - right[i]) * wcurrent; + std::transform(left.begin(), left.end(), right.begin(), mD.begin(), + [wcurrent](const float l, const float r) noexcept { return (l-r) * wcurrent; }); mCurrentWidth = wcurrent; } else { const float wstep{(wtarget - wcurrent) / static_cast(samplesToDo)}; float fi{0.0f}; - for(size_t i{0};i < samplesToDo;++i) - { - mD[i] = (left[i] - right[i]) * (wcurrent + wstep*fi); - fi += 1.0f; - } - for(size_t i{samplesToDo};i < samplesToDo+sInputPadding;++i) - mD[i] = (left[i] - right[i]) * wtarget; + + const auto lfade = left.first(samplesToDo); + auto dstore = std::transform(lfade.begin(), lfade.begin(), right.begin(), mD.begin(), + [wcurrent,wstep,&fi](const float l, const float r) noexcept + { + const float ret{(l-r) * (wcurrent + wstep*fi)}; + fi += 1.0f; + return ret; + }); + + const auto lend = left.subspan(samplesToDo); + const auto rend = right.subspan(samplesToDo); + std::transform(lend.begin(), lend.end(), rend.begin(), dstore, + [wtarget](const float l, const float r) noexcept { return (l-r) * wtarget; }); mCurrentWidth = wtarget; } } - float *RESTRICT woutput{al::assume_aligned<16>(samples[0])}; - float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])}; - float *RESTRICT youtput{al::assume_aligned<16>(samples[2])}; + const auto woutput = al::span{al::assume_aligned<16>(samples[0]), samplesToDo}; + const auto xoutput = al::span{al::assume_aligned<16>(samples[1]), samplesToDo}; + const auto youtput = al::span{al::assume_aligned<16>(samples[2]), samplesToDo}; /* Precompute j*D and store in xoutput. */ auto tmpiter = std::copy(mDTHistory.cbegin(), mDTHistory.cend(), mTemp.begin()); std::copy_n(mD.cbegin(), samplesToDo+sInputPadding, tmpiter); if(updateState) LIKELY std::copy_n(mTemp.cbegin()+samplesToDo, mDTHistory.size(), mDTHistory.begin()); - PShift.process({xoutput, samplesToDo}, mTemp.data()); + PShift.process(xoutput, mTemp); - /* W = 0.6098637*S - 0.6896511*j*w*D */ - for(size_t i{0};i < samplesToDo;++i) - woutput[i] = 0.6098637f*mS[i] - 0.6896511f*xoutput[i]; - /* X = 0.8624776*S + 0.7626955*j*w*D */ - for(size_t i{0};i < samplesToDo;++i) - xoutput[i] = 0.8624776f*mS[i] + 0.7626955f*xoutput[i]; + /* W = 0.6098637*S + 0.6896511*j*w*D */ + std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), woutput.begin(), + [](const float s, const float jd) noexcept { return 0.6098637f*s + 0.6896511f*jd; }); + /* X = 0.8624776*S - 0.7626955*j*w*D */ + std::transform(mS.begin(), mS.begin()+samplesToDo, xoutput.begin(), xoutput.begin(), + [](const float s, const float jd) noexcept { return 0.8624776f*s - 0.7626955f*jd; }); /* Precompute j*S and store in youtput. */ tmpiter = std::copy(mSHistory.cbegin(), mSHistory.cend(), mTemp.begin()); std::copy_n(mS.cbegin(), samplesToDo+sInputPadding, tmpiter); if(updateState) LIKELY std::copy_n(mTemp.cbegin()+samplesToDo, mSHistory.size(), mSHistory.begin()); - PShift.process({youtput, samplesToDo}, mTemp.data()); + PShift.process(youtput, mTemp); - /* Y = 1.6822415*w*D - 0.2156194*j*S */ - for(size_t i{0};i < samplesToDo;++i) - youtput[i] = 1.6822415f*mD[i] - 0.2156194f*youtput[i]; + /* Y = 1.6822415*w*D + 0.2156194*j*S */ + std::transform(mD.begin(), mD.begin()+samplesToDo, youtput.begin(), youtput.begin(), + [](const float d, const float js) noexcept { return 1.6822415f*d + 0.2156194f*js; }); } void UhjStereoDecoderIIR::decode(const al::span samples, const size_t samplesToDo, @@ -460,13 +638,13 @@ void UhjStereoDecoderIIR::decode(const al::span samples, const size_t sa static_assert(sInputPadding <= sMaxPadding, "Filter padding is too large"); ASSUME(samplesToDo > 0); + ASSUME(samplesToDo <= BufferLineSize); { - const float *RESTRICT left{al::assume_aligned<16>(samples[0])}; - const float *RESTRICT right{al::assume_aligned<16>(samples[1])}; + const auto left = al::span{al::assume_aligned<16>(samples[0]), samplesToDo+sInputPadding}; + const auto right = al::span{al::assume_aligned<16>(samples[1]), samplesToDo+sInputPadding}; - for(size_t i{0};i < samplesToDo;++i) - mS[i] = left[i] + right[i]; + std::transform(left.begin(), left.end(), right.begin(), mS.begin(), std::plus{}); /* Pre-apply the width factor to the difference signal D. Smoothly * interpolate when it changes. @@ -475,53 +653,63 @@ void UhjStereoDecoderIIR::decode(const al::span samples, const size_t sa const float wcurrent{(mCurrentWidth < 0.0f) ? wtarget : mCurrentWidth}; if(wtarget == wcurrent || !updateState) { - for(size_t i{0};i < samplesToDo;++i) - mD[i] = (left[i] - right[i]) * wcurrent; + std::transform(left.begin(), left.end(), right.begin(), mD.begin(), + [wcurrent](const float l, const float r) noexcept + { return (l-r) * wcurrent; }); mCurrentWidth = wcurrent; } else { const float wstep{(wtarget - wcurrent) / static_cast(samplesToDo)}; float fi{0.0f}; - for(size_t i{0};i < samplesToDo;++i) - { - mD[i] = (left[i] - right[i]) * (wcurrent + wstep*fi); - fi += 1.0f; - } + + const auto lfade = left.first(samplesToDo); + auto dstore = std::transform(lfade.begin(), lfade.begin(), right.begin(), mD.begin(), + [wcurrent,wstep,&fi](const float l, const float r) noexcept + { + const float ret{(l-r) * (wcurrent + wstep*fi)}; + fi += 1.0f; + return ret; + }); + + const auto lend = left.subspan(samplesToDo); + const auto rend = right.subspan(samplesToDo); + std::transform(lend.begin(), lend.end(), rend.begin(), dstore, + [wtarget](const float l, const float r) noexcept { return (l-r) * wtarget; }); mCurrentWidth = wtarget; } } - float *RESTRICT woutput{al::assume_aligned<16>(samples[0])}; - float *RESTRICT xoutput{al::assume_aligned<16>(samples[1])}; - float *RESTRICT youtput{al::assume_aligned<16>(samples[2])}; + const auto woutput = al::span{al::assume_aligned<16>(samples[0]), samplesToDo}; + const auto xoutput = al::span{al::assume_aligned<16>(samples[1]), samplesToDo}; + const auto youtput = al::span{al::assume_aligned<16>(samples[2]), samplesToDo}; /* Apply filter1 to S and store in mTemp. */ - mTemp[0] = mDelayS; - mFilter1S.process(Filter1Coeff, {mS.data(), samplesToDo}, updateState, mTemp.data()+1); - if(updateState) LIKELY mDelayS = mTemp[samplesToDo]; + process(mFilter1S, Filter1Coeff, al::span{mS}.first(samplesToDo), updateState, mTemp); /* Precompute j*D and store in xoutput. */ - mFilter2D.process(Filter2Coeff, {mD.data(), samplesToDo}, updateState, xoutput); + if(mFirstRun) processOne(mFilter2D, Filter2Coeff, mD[0]); + process(mFilter2D, Filter2Coeff, al::span{mD}.subspan(1, samplesToDo), updateState, xoutput); - /* W = 0.6098637*S - 0.6896511*j*w*D */ - for(size_t i{0};i < samplesToDo;++i) - woutput[i] = 0.6098637f*mTemp[i] - 0.6896511f*xoutput[i]; - /* X = 0.8624776*S + 0.7626955*j*w*D */ - for(size_t i{0};i < samplesToDo;++i) - xoutput[i] = 0.8624776f*mTemp[i] + 0.7626955f*xoutput[i]; + /* W = 0.6098637*S + 0.6896511*j*w*D */ + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), woutput.begin(), + [](const float s, const float jd) noexcept { return 0.6098637f*s + 0.6896511f*jd; }); + /* X = 0.8624776*S - 0.7626955*j*w*D */ + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, xoutput.begin(), xoutput.begin(), + [](const float s, const float jd) noexcept { return 0.8624776f*s - 0.7626955f*jd; }); /* Precompute j*S and store in youtput. */ - mFilter2S.process(Filter2Coeff, {mS.data(), samplesToDo}, updateState, youtput); + if(mFirstRun) processOne(mFilter2S, Filter2Coeff, mS[0]); + process(mFilter2S, Filter2Coeff, al::span{mS}.subspan(1, samplesToDo), updateState, youtput); /* Apply filter1 to D and store in mTemp. */ - mTemp[0] = mDelayD; - mFilter1D.process(Filter1Coeff, {mD.data(), samplesToDo}, updateState, mTemp.data()+1); - if(updateState) LIKELY mDelayD = mTemp[samplesToDo]; + process(mFilter1D, Filter1Coeff, al::span{mD}.first(samplesToDo), updateState, mTemp); - /* Y = 1.6822415*w*D - 0.2156194*j*S */ - for(size_t i{0};i < samplesToDo;++i) - youtput[i] = 1.6822415f*mTemp[i] - 0.2156194f*youtput[i]; + /* Y = 1.6822415*w*D + 0.2156194*j*S */ + std::transform(mTemp.begin(), mTemp.begin()+samplesToDo, youtput.begin(), youtput.begin(), + [](const float d, const float js) noexcept { return 1.6822415f*d + 0.2156194f*js; }); + + mFirstRun = false; } diff --git a/3rdparty/openal/core/uhjfilter.h b/3rdparty/openal/core/uhjfilter.h index df30809444b7..34ea1dfa09c1 100644 --- a/3rdparty/openal/core/uhjfilter.h +++ b/3rdparty/openal/core/uhjfilter.h @@ -2,42 +2,47 @@ #define CORE_UHJFILTER_H #include +#include +#include -#include "almalloc.h" #include "alspan.h" #include "bufferline.h" +#include "opthelpers.h" -static constexpr size_t UhjLength256{256}; -static constexpr size_t UhjLength512{512}; +inline constexpr std::size_t UhjLength256{256}; +inline constexpr std::size_t UhjLength512{512}; -enum class UhjQualityType : uint8_t { +enum class UhjQualityType : std::uint8_t { IIR = 0, FIR256, FIR512, Default = IIR }; -extern UhjQualityType UhjDecodeQuality; -extern UhjQualityType UhjEncodeQuality; +inline UhjQualityType UhjDecodeQuality{UhjQualityType::Default}; +inline UhjQualityType UhjEncodeQuality{UhjQualityType::Default}; struct UhjAllPassFilter { struct AllPassState { /* Last two delayed components for direct form II. */ - float z[2]; + std::array z{}; }; std::array mState; - - void process(const al::span coeffs, const al::span src, - const bool update, float *RESTRICT dst); }; -struct UhjEncoderBase { +struct SIMDALIGN UhjEncoderBase { + UhjEncoderBase() = default; + UhjEncoderBase(const UhjEncoderBase&) = delete; + UhjEncoderBase(UhjEncoderBase&&) = delete; virtual ~UhjEncoderBase() = default; - virtual size_t getDelay() noexcept = 0; + void operator=(const UhjEncoderBase&) = delete; + void operator=(UhjEncoderBase&&) = delete; + + virtual std::size_t getDelay() noexcept = 0; /** * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input @@ -45,12 +50,15 @@ struct UhjEncoderBase { * with an additional +3dB boost). */ virtual void encode(float *LeftOut, float *RightOut, - const al::span InSamples, const size_t SamplesToDo) = 0; + const al::span InSamples, const std::size_t SamplesToDo) = 0; }; -template +template struct UhjEncoder final : public UhjEncoderBase { - static constexpr size_t sFilterDelay{N/2}; + static constexpr std::size_t sFftLength{256}; + static constexpr std::size_t sSegmentSize{sFftLength/2}; + static constexpr std::size_t sNumSegments{N/sSegmentSize}; + static constexpr std::size_t sFilterDelay{N/2 + sSegmentSize}; /* Delays and processing storage for the input signal. */ alignas(16) std::array mW{}; @@ -60,15 +68,16 @@ struct UhjEncoder final : public UhjEncoderBase { alignas(16) std::array mS{}; alignas(16) std::array mD{}; - /* History and temp storage for the FIR filter. New samples should be - * written to index sFilterDelay*2 - 1. - */ - static constexpr size_t sWXInOffset{sFilterDelay*2 - 1}; - alignas(16) std::array mWX{}; + /* History and temp storage for the convolution filter. */ + std::size_t mFifoPos{}, mCurrentSegment{}; + alignas(16) std::array mWXInOut{}; + alignas(16) std::array mFftBuffer{}; + alignas(16) std::array mWorkData{}; + alignas(16) std::array mWXHistory{}; alignas(16) std::array,2> mDirectDelay{}; - size_t getDelay() noexcept override { return sFilterDelay; } + std::size_t getDelay() noexcept override { return sFilterDelay; } /** * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input @@ -76,13 +85,11 @@ struct UhjEncoder final : public UhjEncoderBase { * with an additional +3dB boost). */ void encode(float *LeftOut, float *RightOut, const al::span InSamples, - const size_t SamplesToDo) override; - - DEF_NEWDEL(UhjEncoder) + const std::size_t SamplesToDo) final; }; struct UhjEncoderIIR final : public UhjEncoderBase { - static constexpr size_t sFilterDelay{1}; + static constexpr std::size_t sFilterDelay{1}; /* Processing storage for the input signal. */ alignas(16) std::array mS{}; @@ -98,7 +105,7 @@ struct UhjEncoderIIR final : public UhjEncoderBase { std::array mFilter1Direct; std::array mDirectDelay{}; - size_t getDelay() noexcept override { return sFilterDelay; } + std::size_t getDelay() noexcept override { return sFilterDelay; } /** * Encodes a 2-channel UHJ (stereo-compatible) signal from a B-Format input @@ -106,22 +113,26 @@ struct UhjEncoderIIR final : public UhjEncoderBase { * with an additional +3dB boost). */ void encode(float *LeftOut, float *RightOut, const al::span InSamples, - const size_t SamplesToDo) override; - - DEF_NEWDEL(UhjEncoderIIR) + const std::size_t SamplesToDo) final; }; -struct DecoderBase { - static constexpr size_t sMaxPadding{256}; +struct SIMDALIGN DecoderBase { + static constexpr std::size_t sMaxPadding{256}; /* For 2-channel UHJ, shelf filters should use these LF responses. */ static constexpr float sWLFScale{0.661f}; static constexpr float sXYLFScale{1.293f}; + DecoderBase() = default; + DecoderBase(const DecoderBase&) = delete; + DecoderBase(DecoderBase&&) = delete; virtual ~DecoderBase() = default; - virtual void decode(const al::span samples, const size_t samplesToDo, + void operator=(const DecoderBase&) = delete; + void operator=(DecoderBase&&) = delete; + + virtual void decode(const al::span samples, const std::size_t samplesToDo, const bool updateState) = 0; /** @@ -131,10 +142,10 @@ struct DecoderBase { float mWidthControl{0.593f}; }; -template +template struct UhjDecoder final : public DecoderBase { /* The number of extra sample frames needed for input. */ - static constexpr size_t sInputPadding{N/2}; + static constexpr std::size_t sInputPadding{N/2}; alignas(16) std::array mS{}; alignas(16) std::array mD{}; @@ -153,24 +164,23 @@ struct UhjDecoder final : public DecoderBase { * reconstructed from 2-channel UHJ should not be run through a normal * B-Format decoder, as it needs different shelf filters. */ - void decode(const al::span samples, const size_t samplesToDo, - const bool updateState) override; - - DEF_NEWDEL(UhjDecoder) + void decode(const al::span samples, const std::size_t samplesToDo, + const bool updateState) final; }; struct UhjDecoderIIR final : public DecoderBase { - /* FIXME: These IIR decoder filters actually have a 1-sample delay on the - * non-filtered components, which is not reflected in the source latency - * value. sInputPadding is 0, however, because it doesn't need any extra - * input samples. + /* These IIR decoder filters normally have a 1-sample delay on the non- + * filtered components. However, the filtered components are made to skip + * the first output sample and take one future sample, which puts it ahead + * by one sample. The first filtered output sample is cut to align it with + * the first non-filtered sample, similar to the FIR filters. */ - static constexpr size_t sInputPadding{0}; + static constexpr std::size_t sInputPadding{1}; - alignas(16) std::array mS{}; - alignas(16) std::array mD{}; - alignas(16) std::array mTemp{}; - float mDelayS{}, mDelayDT{}, mDelayQ{}; + bool mFirstRun{true}; + alignas(16) std::array mS{}; + alignas(16) std::array mD{}; + alignas(16) std::array mTemp{}; UhjAllPassFilter mFilter1S; UhjAllPassFilter mFilter2DT; @@ -178,15 +188,13 @@ struct UhjDecoderIIR final : public DecoderBase { UhjAllPassFilter mFilter2S; UhjAllPassFilter mFilter1Q; - void decode(const al::span samples, const size_t samplesToDo, - const bool updateState) override; - - DEF_NEWDEL(UhjDecoderIIR) + void decode(const al::span samples, const std::size_t samplesToDo, + const bool updateState) final; }; -template +template struct UhjStereoDecoder final : public DecoderBase { - static constexpr size_t sInputPadding{N/2}; + static constexpr std::size_t sInputPadding{N/2}; float mCurrentWidth{-1.0f}; @@ -204,31 +212,27 @@ struct UhjStereoDecoder final : public DecoderBase { * should contain 3 channels, the first two being the left and right stereo * channels, and the third left empty. */ - void decode(const al::span samples, const size_t samplesToDo, - const bool updateState) override; - - DEF_NEWDEL(UhjStereoDecoder) + void decode(const al::span samples, const std::size_t samplesToDo, + const bool updateState) final; }; struct UhjStereoDecoderIIR final : public DecoderBase { - static constexpr size_t sInputPadding{0}; + static constexpr std::size_t sInputPadding{1}; + bool mFirstRun{true}; float mCurrentWidth{-1.0f}; - alignas(16) std::array mS{}; - alignas(16) std::array mD{}; - alignas(16) std::array mTemp{}; - float mDelayS{}, mDelayD{}; + alignas(16) std::array mS{}; + alignas(16) std::array mD{}; + alignas(16) std::array mTemp{}; UhjAllPassFilter mFilter1S; UhjAllPassFilter mFilter2D; UhjAllPassFilter mFilter1D; UhjAllPassFilter mFilter2S; - void decode(const al::span samples, const size_t samplesToDo, - const bool updateState) override; - - DEF_NEWDEL(UhjStereoDecoderIIR) + void decode(const al::span samples, const std::size_t samplesToDo, + const bool updateState) final; }; #endif /* CORE_UHJFILTER_H */ diff --git a/3rdparty/openal/core/uiddefs.cpp b/3rdparty/openal/core/uiddefs.cpp index 9471bba5cfbe..e52a9ae33c88 100644 --- a/3rdparty/openal/core/uiddefs.cpp +++ b/3rdparty/openal/core/uiddefs.cpp @@ -1,17 +1,13 @@ #include "config.h" - +#include "config_backends.h" #ifndef AL_NO_UID_DEFS -#if defined(HAVE_GUIDDEF_H) || defined(HAVE_INITGUID_H) +#if defined(HAVE_GUIDDEF_H) #define INITGUID #include -#ifdef HAVE_GUIDDEF_H #include -#else -#include -#endif DEFINE_GUID(KSDATAFORMAT_SUBTYPE_PCM, 0x00000001, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); DEFINE_GUID(KSDATAFORMAT_SUBTYPE_IEEE_FLOAT, 0x00000003, 0x0000, 0x0010, 0x80,0x00, 0x00,0xaa,0x00,0x38,0x9b,0x71); @@ -20,7 +16,7 @@ DEFINE_GUID(IID_IDirectSoundNotify, 0xb0210783, 0x89cd, 0x11d0, 0xaf,0x08, 0x0 DEFINE_GUID(CLSID_MMDeviceEnumerator, 0xbcde0395, 0xe52f, 0x467c, 0x8e,0x3d, 0xc4,0x57,0x92,0x91,0x69,0x2e); -#if defined(HAVE_WASAPI) && !defined(ALSOFT_UWP) +#if HAVE_WASAPI && !ALSOFT_UWP #include #include #include diff --git a/3rdparty/openal/core/voice.cpp b/3rdparty/openal/core/voice.cpp index b8acc7a66ef8..31214f0e293c 100644 --- a/3rdparty/openal/core/voice.cpp +++ b/3rdparty/openal/core/voice.cpp @@ -1,5 +1,6 @@ #include "config.h" +#include "config_simd.h" #include "voice.h" @@ -9,11 +10,11 @@ #include #include #include +#include #include #include #include #include -#include #include #include @@ -42,45 +43,44 @@ #include "voice_change.h" struct CTag; -#ifdef HAVE_SSE +#if HAVE_SSE struct SSETag; #endif -#ifdef HAVE_NEON +#if HAVE_NEON struct NEONTag; #endif -static_assert(!(sizeof(DeviceBase::MixerBufferLine)&15), - "DeviceBase::MixerBufferLine must be a multiple of 16 bytes"); +static_assert(!(DeviceBase::MixerLineSize&3), "MixerLineSize must be a multiple of 4"); static_assert(!(MaxResamplerEdge&3), "MaxResamplerEdge is not a multiple of 4"); static_assert((BufferLineSize-1)/MaxPitch > 0, "MaxPitch is too large for BufferLineSize!"); static_assert((INT_MAX>>MixerFracBits)/MaxPitch > BufferLineSize, "MaxPitch and/or BufferLineSize are too large for MixerFracBits!"); -Resampler ResamplerDefault{Resampler::Cubic}; - namespace { using uint = unsigned int; using namespace std::chrono; +using namespace std::string_view_literals; -using HrtfMixerFunc = void(*)(const float *InSamples, float2 *AccumSamples, const uint IrSize, - const MixHrtfFilter *hrtfparams, const size_t BufferSize); -using HrtfMixerBlendFunc = void(*)(const float *InSamples, float2 *AccumSamples, - const uint IrSize, const HrtfFilter *oldparams, const MixHrtfFilter *newparams, - const size_t BufferSize); +using HrtfMixerFunc = void(*)(const al::span InSamples, + const al::span AccumSamples, const uint IrSize, const MixHrtfFilter *hrtfparams, + const size_t SamplesToDo); +using HrtfMixerBlendFunc = void(*)(const al::span InSamples, + const al::span AccumSamples, const uint IrSize, const HrtfFilter *oldparams, + const MixHrtfFilter *newparams, const size_t SamplesToDo); HrtfMixerFunc MixHrtfSamples{MixHrtf_}; HrtfMixerBlendFunc MixHrtfBlendSamples{MixHrtfBlend_}; inline MixerOutFunc SelectMixer() { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Mix_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return Mix_; #endif @@ -89,11 +89,11 @@ inline MixerOutFunc SelectMixer() inline MixerOneFunc SelectMixerOne() { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return Mix_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return Mix_; #endif @@ -102,11 +102,11 @@ inline MixerOneFunc SelectMixerOne() inline HrtfMixerFunc SelectHrtfMixer() { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return MixHrtf_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return MixHrtf_; #endif @@ -115,11 +115,11 @@ inline HrtfMixerFunc SelectHrtfMixer() inline HrtfMixerBlendFunc SelectHrtfBlendMixer() { -#ifdef HAVE_NEON +#if HAVE_NEON if((CPUCapFlags&CPU_CAP_NEON)) return MixHrtfBlend_; #endif -#ifdef HAVE_SSE +#if HAVE_SSE if((CPUCapFlags&CPU_CAP_SSE)) return MixHrtfBlend_; #endif @@ -128,42 +128,52 @@ inline HrtfMixerBlendFunc SelectHrtfBlendMixer() } // namespace -void Voice::InitMixer(std::optional resampler) +void Voice::InitMixer(std::optional resopt) { - if(resampler) + if(resopt) { struct ResamplerEntry { - const char name[16]; + const std::string_view name; const Resampler resampler; }; - constexpr ResamplerEntry ResamplerList[]{ - { "none", Resampler::Point }, - { "point", Resampler::Point }, - { "linear", Resampler::Linear }, - { "cubic", Resampler::Cubic }, - { "bsinc12", Resampler::BSinc12 }, - { "fast_bsinc12", Resampler::FastBSinc12 }, - { "bsinc24", Resampler::BSinc24 }, - { "fast_bsinc24", Resampler::FastBSinc24 }, + constexpr std::array ResamplerList{ + ResamplerEntry{"none"sv, Resampler::Point}, + ResamplerEntry{"point"sv, Resampler::Point}, + ResamplerEntry{"linear"sv, Resampler::Linear}, + ResamplerEntry{"spline"sv, Resampler::Spline}, + ResamplerEntry{"gaussian"sv, Resampler::Gaussian}, + ResamplerEntry{"bsinc12"sv, Resampler::BSinc12}, + ResamplerEntry{"fast_bsinc12"sv, Resampler::FastBSinc12}, + ResamplerEntry{"bsinc24"sv, Resampler::BSinc24}, + ResamplerEntry{"fast_bsinc24"sv, Resampler::FastBSinc24}, + ResamplerEntry{"bsinc48"sv, Resampler::BSinc48}, + ResamplerEntry{"fast_bsinc48"sv, Resampler::FastBSinc48}, }; - const char *str{resampler->c_str()}; - if(al::strcasecmp(str, "bsinc") == 0) + std::string_view resampler{*resopt}; + + if (al::case_compare(resampler, "cubic"sv) == 0) + { + WARN("Resampler option \"{}\" is deprecated, using spline", *resopt); + resampler = "spline"sv; + } + else if(al::case_compare(resampler, "sinc4"sv) == 0 + || al::case_compare(resampler, "sinc8"sv) == 0) { - WARN("Resampler option \"%s\" is deprecated, using bsinc12\n", str); - str = "bsinc12"; + WARN("Resampler option \"{}\" is deprecated, using gaussian", *resopt); + resampler = "gaussian"sv; } - else if(al::strcasecmp(str, "sinc4") == 0 || al::strcasecmp(str, "sinc8") == 0) + else if(al::case_compare(resampler, "bsinc"sv) == 0) { - WARN("Resampler option \"%s\" is deprecated, using cubic\n", str); - str = "cubic"; + WARN("Resampler option \"{}\" is deprecated, using bsinc12", *resopt); + resampler = "bsinc12"sv; } - auto iter = std::find_if(std::begin(ResamplerList), std::end(ResamplerList), - [str](const ResamplerEntry &entry) -> bool - { return al::strcasecmp(str, entry.name) == 0; }); - if(iter == std::end(ResamplerList)) - ERR("Invalid resampler: %s\n", str); + auto iter = std::find_if(ResamplerList.begin(), ResamplerList.end(), + [resampler](const ResamplerEntry &entry) -> bool + { return al::case_compare(resampler, entry.name) == 0; }); + if(iter == ResamplerList.end()) + ERR("Invalid resampler: {}", *resopt); else ResamplerDefault = iter->resampler; } @@ -178,7 +188,7 @@ void Voice::InitMixer(std::optional resampler) namespace { /* IMA ADPCM Stepsize table */ -constexpr int IMAStep_size[89] = { +constexpr std::array IMAStep_size{{ 7, 8, 9, 10, 11, 12, 13, 14, 16, 17, 19, 21, 23, 25, 28, 31, 34, 37, 41, 45, 50, 55, 60, 66, 73, 80, 88, 97, 107, 118, 130, 143, 157, @@ -188,35 +198,35 @@ constexpr int IMAStep_size[89] = { 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442, 11487,12635,13899,15289,16818,18500,20350,22358,24633,27086,29794, 32767 -}; +}}; /* IMA4 ADPCM Codeword decode table */ -constexpr int IMA4Codeword[16] = { +constexpr std::array IMA4Codeword{{ 1, 3, 5, 7, 9, 11, 13, 15, -1,-3,-5,-7,-9,-11,-13,-15, -}; +}}; /* IMA4 ADPCM Step index adjust decode table */ -constexpr int IMA4Index_adjust[16] = { +constexpr std::array IMA4Index_adjust{{ -1,-1,-1,-1, 2, 4, 6, 8, -1,-1,-1,-1, 2, 4, 6, 8 -}; +}}; /* MSADPCM Adaption table */ -constexpr int MSADPCMAdaption[16] = { +constexpr std::array MSADPCMAdaption{{ 230, 230, 230, 230, 307, 409, 512, 614, 768, 614, 512, 409, 307, 230, 230, 230 -}; +}}; /* MSADPCM Adaption Coefficient tables */ -constexpr int MSADPCMAdaptionCoeff[7][2] = { - { 256, 0 }, - { 512, -256 }, - { 0, 0 }, - { 192, 64 }, - { 240, 0 }, - { 460, -208 }, - { 392, -232 } +constexpr std::array MSADPCMAdaptionCoeff{ + std::array{256, 0}, + std::array{512, -256}, + std::array{ 0, 0}, + std::array{192, 64}, + std::array{240, 0}, + std::array{460, -208}, + std::array{392, -232} }; @@ -224,9 +234,9 @@ void SendSourceStoppedEvent(ContextBase *context, uint id) { RingBuffer *ring{context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); - if(evt_vec.first.len < 1) return; + if(evt_vec[0].len < 1) return; - auto &evt = InitAsyncEvent(evt_vec.first.buf); + auto &evt = InitAsyncEvent(evt_vec[0].buf); evt.mId = id; evt.mState = AsyncSrcState::Stop; @@ -234,8 +244,8 @@ void SendSourceStoppedEvent(ContextBase *context, uint id) } -const float *DoFilters(BiquadFilter &lpfilter, BiquadFilter &hpfilter, float *dst, - const al::span src, int type) +al::span DoFilters(BiquadFilter &lpfilter, BiquadFilter &hpfilter, + const al::span dst, const al::span src, int type) { switch(type) { @@ -247,149 +257,166 @@ const float *DoFilters(BiquadFilter &lpfilter, BiquadFilter &hpfilter, float *ds case AF_LowPass: lpfilter.process(src, dst); hpfilter.clear(); - return dst; + return dst.first(src.size()); case AF_HighPass: lpfilter.clear(); hpfilter.process(src, dst); - return dst; + return dst.first(src.size()); case AF_BandPass: DualBiquad{lpfilter, hpfilter}.process(src, dst); - return dst; + return dst.first(src.size()); } - return src.data(); + return src; } template -inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, const size_t srcChan, - const size_t srcOffset, const size_t srcStep, const size_t /*samplesPerBlock*/, - const size_t samplesToLoad) noexcept +inline void LoadSamples(const al::span dstSamples, const al::span srcData, + const size_t srcChan, const size_t srcOffset, const size_t srcStep, + const size_t samplesPerBlock [[maybe_unused]]) noexcept { - constexpr size_t sampleSize{sizeof(typename al::FmtTypeTraits::Type)}; - auto s = src + (srcOffset*srcStep + srcChan)*sampleSize; - - al::LoadSampleArray(dstSamples, s, srcStep, samplesToLoad); + using TypeTraits = al::FmtTypeTraits; + using SampleType = typename TypeTraits::Type; + assert(srcChan < srcStep); + auto converter = TypeTraits{}; + + al::span src{reinterpret_cast(srcData.data()), + srcData.size()/sizeof(SampleType)}; + auto ssrc = src.cbegin() + ptrdiff_t(srcOffset*srcStep + srcChan); + dstSamples.front() = converter(*ssrc); + std::generate(dstSamples.begin()+1, dstSamples.end(), [&ssrc,srcStep,converter] + { + ssrc += ptrdiff_t(srcStep); + return converter(*ssrc); + }); } template<> -inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, +inline void LoadSamples(al::span dstSamples, al::span src, const size_t srcChan, const size_t srcOffset, const size_t srcStep, - const size_t samplesPerBlock, const size_t samplesToLoad) noexcept + const size_t samplesPerBlock) noexcept { + static constexpr int MaxStepIndex{static_cast(IMAStep_size.size()) - 1}; + + assert(srcStep > 0 || srcStep <= 2); + assert(srcChan < srcStep); + assert(samplesPerBlock > 1); const size_t blockBytes{((samplesPerBlock-1)/2 + 4)*srcStep}; /* Skip to the ADPCM block containing the srcOffset sample. */ - src += srcOffset/samplesPerBlock*blockBytes; + src = src.subspan(srcOffset/samplesPerBlock*blockBytes); /* Calculate how many samples need to be skipped in the block. */ size_t skip{srcOffset % samplesPerBlock}; /* NOTE: This could probably be optimized better. */ - size_t wrote{0}; - do { - static constexpr int MaxStepIndex{static_cast(std::size(IMAStep_size)) - 1}; - /* Each IMA4 block starts with a signed 16-bit sample, and a signed + auto dst = dstSamples.begin(); + while(dst != dstSamples.end()) + { + /* Each IMA4 block starts with a signed 16-bit sample, and a signed(?) * 16-bit table index. The table index needs to be clamped. */ - int sample{int(src[srcChan*4]) | (int(src[srcChan*4 + 1]) << 8)}; - int index{int(src[srcChan*4 + 2]) | (int(src[srcChan*4 + 3]) << 8)}; + auto prevSample = int(src[srcChan*4 + 0]) | (int(src[srcChan*4 + 1]) << 8); + auto prevIndex = int(src[srcChan*4 + 2]) | (int(src[srcChan*4 + 3]) << 8); + const auto nibbleData = src.subspan((srcStep+srcChan)*4); + src = src.subspan(blockBytes); - sample = (sample^0x8000) - 32768; - index = clampi((index^0x8000) - 32768, 0, MaxStepIndex); + /* Sign-extend the 16-bit sample and index values. */ + prevSample = (prevSample^0x8000) - 32768; + prevIndex = std::clamp((prevIndex^0x8000) - 32768, 0, MaxStepIndex); if(skip == 0) { - dstSamples[wrote++] = static_cast(sample) / 32768.0f; - if(wrote == samplesToLoad) return; + *dst = static_cast(prevSample) / 32768.0f; + if(++dst == dstSamples.end()) return; } else --skip; - auto decode_sample = [&sample,&index](const uint nibble) + /* The rest of the block is arranged as a series of nibbles, contained + * in 4 *bytes* per channel interleaved. So every 8 nibbles we need to + * skip 4 bytes per channel to get the next nibbles for this channel. + */ + auto decode_nibble = [&prevSample,&prevIndex,srcStep,nibbleData](const size_t nibbleOffset) + noexcept -> int { - sample += IMA4Codeword[nibble] * IMAStep_size[index] / 8; - sample = clampi(sample, -32768, 32767); + static constexpr auto NibbleMask = std::byte{0xf}; + const auto byteShift = (nibbleOffset&1) * 4; + const auto wordOffset = (nibbleOffset>>1) & ~3_uz; + const auto byteOffset = wordOffset*srcStep + ((nibbleOffset>>1)&3); - index += IMA4Index_adjust[nibble]; - index = clampi(index, 0, MaxStepIndex); + const auto nibble = al::to_underlying((nibbleData[byteOffset]>>byteShift)&NibbleMask); - return sample; + prevSample += IMA4Codeword[nibble] * IMAStep_size[static_cast(prevIndex)] / 8; + prevSample = std::clamp(prevSample, -32768, 32767); + + prevIndex += IMA4Index_adjust[nibble]; + prevIndex = std::clamp(prevIndex, 0, MaxStepIndex); + + return prevSample; }; - /* The rest of the block is arranged as a series of nibbles, contained - * in 4 *bytes* per channel interleaved. So every 8 nibbles we need to - * skip 4 bytes per channel to get the next nibbles for this channel. - * - * First, decode the samples that we need to skip in the block (will + /* First, decode the samples that we need to skip in the block (will * always be less than the block size). They need to be decoded despite * being ignored for proper state on the remaining samples. */ - const std::byte *nibbleData{src + (srcStep+srcChan)*4}; size_t nibbleOffset{0}; const size_t startOffset{skip + 1}; for(;skip;--skip) { - const size_t byteShift{(nibbleOffset&1) * 4}; - const size_t wordOffset{(nibbleOffset>>1) & ~3_uz}; - const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; + std::ignore = decode_nibble(nibbleOffset); ++nibbleOffset; - - std::ignore = decode_sample(uint(nibbleData[byteOffset]>>byteShift) & 15u); } /* Second, decode the rest of the block and write to the output, until * the end of the block or the end of output. */ - const size_t todo{minz(samplesPerBlock-startOffset, samplesToLoad-wrote)}; - for(size_t i{0};i < todo;++i) + const auto todo = std::min(samplesPerBlock - startOffset, + size_t(std::distance(dst, dstSamples.end()))); + dst = std::generate_n(dst, todo, [&] { - const size_t byteShift{(nibbleOffset&1) * 4}; - const size_t wordOffset{(nibbleOffset>>1) & ~3_uz}; - const size_t byteOffset{wordOffset*srcStep + ((nibbleOffset>>1)&3u)}; + const auto sample = decode_nibble(nibbleOffset); ++nibbleOffset; - const int result{decode_sample(uint(nibbleData[byteOffset]>>byteShift) & 15u)}; - dstSamples[wrote++] = static_cast(result) / 32768.0f; - } - if(wrote == samplesToLoad) - return; - - src += blockBytes; - } while(true); + return static_cast(sample) / 32768.0f; + }); + } } template<> -inline void LoadSamples(float *RESTRICT dstSamples, const std::byte *src, +inline void LoadSamples(al::span dstSamples, al::span src, const size_t srcChan, const size_t srcOffset, const size_t srcStep, - const size_t samplesPerBlock, const size_t samplesToLoad) noexcept + const size_t samplesPerBlock) noexcept { + assert(srcStep > 0 || srcStep <= 2); + assert(srcChan < srcStep); + assert(samplesPerBlock > 2); const size_t blockBytes{((samplesPerBlock-2)/2 + 7)*srcStep}; - src += srcOffset/samplesPerBlock*blockBytes; + src = src.subspan(srcOffset/samplesPerBlock*blockBytes); size_t skip{srcOffset % samplesPerBlock}; - size_t wrote{0}; - do { + auto dst = dstSamples.begin(); + while(dst != dstSamples.end()) + { /* Each MS ADPCM block starts with an 8-bit block predictor, used to * dictate how the two sample history values are mixed with the decoded - * sample, and an initial signed 16-bit delta value which scales the + * sample, and an initial signed 16-bit scaling value which scales the * nibble sample value. This is followed by the two initial 16-bit * sample history values. */ - const std::byte *input{src}; - const uint8_t blockpred{std::min(uint8_t(input[srcChan]), uint8_t{6})}; - input += srcStep; - int delta{int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1]) << 8)}; - input += srcStep*2; - - int sampleHistory[2]{}; - sampleHistory[0] = int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1])<<8); - input += srcStep*2; - sampleHistory[1] = int(input[2*srcChan + 0]) | (int(input[2*srcChan + 1])<<8); - input += srcStep*2; - - const al::span coeffs{MSADPCMAdaptionCoeff[blockpred]}; - delta = (delta^0x8000) - 32768; + const auto blockpred = std::min(uint8_t(src[srcChan]), + uint8_t{MSADPCMAdaptionCoeff.size()-1}); + auto scale = int(src[srcStep + 2*srcChan + 0]) | (int(src[srcStep + 2*srcChan + 1]) << 8); + + auto sampleHistory = std::array{ + int(src[3*srcStep + 2*srcChan + 0]) | (int(src[3*srcStep + 2*srcChan + 1])<<8), + int(src[5*srcStep + 2*srcChan + 0]) | (int(src[5*srcStep + 2*srcChan + 1])<<8)}; + const auto nibbleData = src.subspan(7*srcStep); + src = src.subspan(blockBytes); + + const auto coeffs = al::span{MSADPCMAdaptionCoeff[blockpred]}; + scale = (scale^0x8000) - 32768; sampleHistory[0] = (sampleHistory[0]^0x8000) - 32768; sampleHistory[1] = (sampleHistory[1]^0x8000) - 32768; @@ -398,82 +425,83 @@ inline void LoadSamples(float *RESTRICT dstSamples, const std::byte */ if(skip == 0) { - dstSamples[wrote++] = static_cast(sampleHistory[1]) / 32768.0f; - if(wrote == samplesToLoad) return; - dstSamples[wrote++] = static_cast(sampleHistory[0]) / 32768.0f; - if(wrote == samplesToLoad) return; + *dst = static_cast(sampleHistory[1]) / 32768.0f; + if(++dst == dstSamples.end()) return; + *dst = static_cast(sampleHistory[0]) / 32768.0f; + if(++dst == dstSamples.end()) return; } else if(skip == 1) { --skip; - dstSamples[wrote++] = static_cast(sampleHistory[0]) / 32768.0f; - if(wrote == samplesToLoad) return; + *dst = static_cast(sampleHistory[0]) / 32768.0f; + if(++dst == dstSamples.end()) return; } else skip -= 2; - auto decode_sample = [&sampleHistory,&delta,coeffs](const int nibble) + /* The rest of the block is a series of nibbles, interleaved per- + * channel. + */ + auto decode_nibble = [&sampleHistory,&scale,coeffs,nibbleData](const size_t nibbleOffset) + noexcept -> int { - int pred{(sampleHistory[0]*coeffs[0] + sampleHistory[1]*coeffs[1]) / 256}; - pred += ((nibble^0x08) - 0x08) * delta; - pred = clampi(pred, -32768, 32767); + static constexpr auto NibbleMask = std::byte{0xf}; + const auto byteOffset = nibbleOffset>>1; + const auto byteShift = ((nibbleOffset&1)^1) * 4; + + const auto nibble = al::to_underlying((nibbleData[byteOffset]>>byteShift)&NibbleMask); + + const auto pred = ((nibble^0x08) - 0x08) * scale; + const auto diff = (sampleHistory[0]*coeffs[0] + sampleHistory[1]*coeffs[1]) / 256; + const auto sample = std::clamp(pred + diff, -32768, 32767); sampleHistory[1] = sampleHistory[0]; - sampleHistory[0] = pred; + sampleHistory[0] = sample; - delta = (MSADPCMAdaption[nibble] * delta) / 256; - delta = maxi(16, delta); + scale = MSADPCMAdaption[nibble] * scale / 256; + scale = std::max(16, scale); - return pred; + return sample; }; - /* The rest of the block is a series of nibbles, interleaved per- - * channel. First, skip samples. - */ + /* First, skip samples. */ const size_t startOffset{skip + 2}; size_t nibbleOffset{srcChan}; for(;skip;--skip) { - const size_t byteOffset{nibbleOffset>>1}; - const size_t byteShift{((nibbleOffset&1)^1) * 4}; + std::ignore = decode_nibble(nibbleOffset); nibbleOffset += srcStep; - - std::ignore = decode_sample(int(input[byteOffset]>>byteShift) & 15); } /* Now decode the rest of the block, until the end of the block or the * dst buffer is filled. */ - const size_t todo{minz(samplesPerBlock-startOffset, samplesToLoad-wrote)}; - for(size_t j{0};j < todo;++j) + const auto todo = std::min(samplesPerBlock - startOffset, + size_t(std::distance(dst, dstSamples.end()))); + dst = std::generate_n(dst, todo, [&] { - const size_t byteOffset{nibbleOffset>>1}; - const size_t byteShift{((nibbleOffset&1)^1) * 4}; + const auto sample = decode_nibble(nibbleOffset); nibbleOffset += srcStep; - const int sample{decode_sample(int(input[byteOffset]>>byteShift) & 15)}; - dstSamples[wrote++] = static_cast(sample) / 32768.0f; - } - if(wrote == samplesToLoad) - return; - - src += blockBytes; - } while(true); + return static_cast(sample) / 32768.0f; + }); + } } -void LoadSamples(float *dstSamples, const std::byte *src, const size_t srcChan, - const size_t srcOffset, const FmtType srcType, const size_t srcStep, - const size_t samplesPerBlock, const size_t samplesToLoad) noexcept +void LoadSamples(const al::span dstSamples, const al::span src, + const size_t srcChan, const size_t srcOffset, const FmtType srcType, const size_t srcStep, + const size_t samplesPerBlock) noexcept { #define HANDLE_FMT(T) case T: \ LoadSamples(dstSamples, src, srcChan, srcOffset, srcStep, \ - samplesPerBlock, samplesToLoad); \ + samplesPerBlock); \ break switch(srcType) { HANDLE_FMT(FmtUByte); HANDLE_FMT(FmtShort); + HANDLE_FMT(FmtInt); HANDLE_FMT(FmtFloat); HANDLE_FMT(FmtDouble); HANDLE_FMT(FmtMulaw); @@ -486,26 +514,24 @@ void LoadSamples(float *dstSamples, const std::byte *src, const size_t srcChan, void LoadBufferStatic(VoiceBufferItem *buffer, VoiceBufferItem *bufferLoopItem, const size_t dataPosInt, const FmtType sampleType, const size_t srcChannel, - const size_t srcStep, size_t samplesLoaded, const size_t samplesToLoad, - float *voiceSamples) + const size_t srcStep, al::span voiceSamples) { if(!bufferLoopItem) { + float lastSample{0.0f}; /* Load what's left to play from the buffer */ if(buffer->mSampleLen > dataPosInt) LIKELY { const size_t buffer_remaining{buffer->mSampleLen - dataPosInt}; - const size_t remaining{minz(samplesToLoad-samplesLoaded, buffer_remaining)}; - LoadSamples(voiceSamples+samplesLoaded, buffer->mSamples, srcChannel, dataPosInt, - sampleType, srcStep, buffer->mBlockAlign, remaining); - samplesLoaded += remaining; + const size_t remaining{std::min(voiceSamples.size(), buffer_remaining)}; + LoadSamples(voiceSamples.first(remaining), buffer->mSamples, srcChannel, dataPosInt, + sampleType, srcStep, buffer->mBlockAlign); + lastSample = voiceSamples[remaining-1]; + voiceSamples = voiceSamples.subspan(remaining); } - if(const size_t toFill{samplesToLoad - samplesLoaded}) - { - auto srcsamples = voiceSamples + samplesLoaded; - std::fill_n(srcsamples, toFill, *(srcsamples-1)); - } + if(const size_t toFill{voiceSamples.size()}) + std::fill_n(voiceSamples.begin(), toFill, lastSample); } else { @@ -517,49 +543,47 @@ void LoadBufferStatic(VoiceBufferItem *buffer, VoiceBufferItem *bufferLoopItem, : (((dataPosInt-loopStart)%(loopEnd-loopStart)) + loopStart)}; /* Load what's left of this loop iteration */ - const size_t remaining{minz(samplesToLoad-samplesLoaded, loopEnd-dataPosInt)}; - LoadSamples(voiceSamples+samplesLoaded, buffer->mSamples, srcChannel, intPos, sampleType, - srcStep, buffer->mBlockAlign, remaining); - samplesLoaded += remaining; + const size_t remaining{std::min(voiceSamples.size(), loopEnd-dataPosInt)}; + LoadSamples(voiceSamples.first(remaining), buffer->mSamples, srcChannel, intPos, + sampleType, srcStep, buffer->mBlockAlign); + voiceSamples = voiceSamples.subspan(remaining); /* Load repeats of the loop to fill the buffer. */ const size_t loopSize{loopEnd - loopStart}; - while(const size_t toFill{minz(samplesToLoad - samplesLoaded, loopSize)}) + while(const size_t toFill{std::min(voiceSamples.size(), loopSize)}) { - LoadSamples(voiceSamples+samplesLoaded, buffer->mSamples, srcChannel, loopStart, - sampleType, srcStep, buffer->mBlockAlign, toFill); - samplesLoaded += toFill; + LoadSamples(voiceSamples.first(toFill), buffer->mSamples, srcChannel, loopStart, + sampleType, srcStep, buffer->mBlockAlign); + voiceSamples = voiceSamples.subspan(toFill); } } } void LoadBufferCallback(VoiceBufferItem *buffer, const size_t dataPosInt, const size_t numCallbackSamples, const FmtType sampleType, const size_t srcChannel, - const size_t srcStep, size_t samplesLoaded, const size_t samplesToLoad, float *voiceSamples) + const size_t srcStep, al::span voiceSamples) { - /* Load what's left to play from the buffer */ + float lastSample{0.0f}; if(numCallbackSamples > dataPosInt) LIKELY { - const size_t remaining{minz(samplesToLoad-samplesLoaded, numCallbackSamples-dataPosInt)}; - LoadSamples(voiceSamples+samplesLoaded, buffer->mSamples, srcChannel, dataPosInt, - sampleType, srcStep, buffer->mBlockAlign, remaining); - samplesLoaded += remaining; + const size_t remaining{std::min(voiceSamples.size(), numCallbackSamples-dataPosInt)}; + LoadSamples(voiceSamples.first(remaining), buffer->mSamples, srcChannel, dataPosInt, + sampleType, srcStep, buffer->mBlockAlign); + lastSample = voiceSamples[remaining-1]; + voiceSamples = voiceSamples.subspan(remaining); } - if(const size_t toFill{samplesToLoad - samplesLoaded}) - { - auto srcsamples = voiceSamples + samplesLoaded; - std::fill_n(srcsamples, toFill, *(srcsamples-1)); - } + if(const size_t toFill{voiceSamples.size()}) + std::fill_n(voiceSamples.begin(), toFill, lastSample); } void LoadBufferQueue(VoiceBufferItem *buffer, VoiceBufferItem *bufferLoopItem, size_t dataPosInt, const FmtType sampleType, const size_t srcChannel, - const size_t srcStep, size_t samplesLoaded, const size_t samplesToLoad, - float *voiceSamples) + const size_t srcStep, al::span voiceSamples) { + float lastSample{0.0f}; /* Crawl the buffer queue to fill in the temp buffer */ - while(buffer && samplesLoaded != samplesToLoad) + while(buffer && !voiceSamples.empty()) { if(dataPosInt >= buffer->mSampleLen) { @@ -569,48 +593,47 @@ void LoadBufferQueue(VoiceBufferItem *buffer, VoiceBufferItem *bufferLoopItem, continue; } - const size_t remaining{minz(samplesToLoad-samplesLoaded, buffer->mSampleLen-dataPosInt)}; - LoadSamples(voiceSamples+samplesLoaded, buffer->mSamples, srcChannel, dataPosInt, - sampleType, srcStep, buffer->mBlockAlign, remaining); + const size_t remaining{std::min(voiceSamples.size(), buffer->mSampleLen-dataPosInt)}; + LoadSamples(voiceSamples.first(remaining), buffer->mSamples, srcChannel, dataPosInt, + sampleType, srcStep, buffer->mBlockAlign); - samplesLoaded += remaining; - if(samplesLoaded == samplesToLoad) + lastSample = voiceSamples[remaining-1]; + voiceSamples = voiceSamples.subspan(remaining); + if(voiceSamples.empty()) break; dataPosInt = 0; buffer = buffer->mNext.load(std::memory_order_acquire); if(!buffer) buffer = bufferLoopItem; } - if(const size_t toFill{samplesToLoad - samplesLoaded}) - { - auto srcsamples = voiceSamples + samplesLoaded; - std::fill_n(srcsamples, toFill, *(srcsamples-1)); - } + if(const size_t toFill{voiceSamples.size()}) + std::fill_n(voiceSamples.begin(), toFill, lastSample); } -void DoHrtfMix(const float *samples, const uint DstBufferSize, DirectParams &parms, - const float TargetGain, const uint Counter, uint OutPos, const bool IsPlaying, - DeviceBase *Device) +void DoHrtfMix(const al::span samples, DirectParams &parms, const float TargetGain, + const size_t Counter, size_t OutPos, const bool IsPlaying, DeviceBase *Device) { const uint IrSize{Device->mIrSize}; - auto &HrtfSamples = Device->HrtfSourceData; - auto &AccumSamples = Device->HrtfAccumData; + const auto HrtfSamples = al::span{Device->ExtraSampleData}; + const auto AccumSamples = al::span{Device->HrtfAccumData}; /* Copy the HRTF history and new input samples into a temp buffer. */ auto src_iter = std::copy(parms.Hrtf.History.begin(), parms.Hrtf.History.end(), - std::begin(HrtfSamples)); - std::copy_n(samples, DstBufferSize, src_iter); + HrtfSamples.begin()); + std::copy_n(samples.begin(), samples.size(), src_iter); /* Copy the last used samples back into the history buffer for later. */ if(IsPlaying) LIKELY - std::copy_n(std::begin(HrtfSamples) + DstBufferSize, parms.Hrtf.History.size(), - parms.Hrtf.History.begin()); + { + const auto endsamples = HrtfSamples.subspan(samples.size(), parms.Hrtf.History.size()); + std::copy_n(endsamples.cbegin(), endsamples.size(), parms.Hrtf.History.begin()); + } /* If fading and this is the first mixing pass, fade between the IRs. */ - uint fademix{0u}; + size_t fademix{0}; if(Counter && OutPos == 0) { - fademix = minu(DstBufferSize, Counter); + fademix = std::min(samples.size(), Counter); float gain{TargetGain}; @@ -629,8 +652,8 @@ void DoHrtfMix(const float *samples, const uint DstBufferSize, DirectParams &par parms.Hrtf.Target.Coeffs, parms.Hrtf.Target.Delay, 0.0f, gain / static_cast(fademix)}; - MixHrtfBlendSamples(HrtfSamples, AccumSamples+OutPos, IrSize, &parms.Hrtf.Old, &hrtfparams, - fademix); + MixHrtfBlendSamples(HrtfSamples, AccumSamples.subspan(OutPos), IrSize, &parms.Hrtf.Old, + &hrtfparams, fademix); /* Update the old parameters with the result. */ parms.Hrtf.Old = parms.Hrtf.Target; @@ -638,15 +661,15 @@ void DoHrtfMix(const float *samples, const uint DstBufferSize, DirectParams &par OutPos += fademix; } - if(fademix < DstBufferSize) + if(fademix < samples.size()) { - const uint todo{DstBufferSize - fademix}; + const size_t todo{samples.size() - fademix}; float gain{TargetGain}; /* Interpolate the target gain if the gain fading lasts longer than * this mix. */ - if(Counter > DstBufferSize) + if(Counter > samples.size()) { const float a{static_cast(todo) / static_cast(Counter-fademix)}; gain = lerpf(parms.Hrtf.Old.Gain, TargetGain, a); @@ -657,37 +680,40 @@ void DoHrtfMix(const float *samples, const uint DstBufferSize, DirectParams &par parms.Hrtf.Target.Delay, parms.Hrtf.Old.Gain, (gain - parms.Hrtf.Old.Gain) / static_cast(todo)}; - MixHrtfSamples(HrtfSamples+fademix, AccumSamples+OutPos, IrSize, &hrtfparams, todo); + MixHrtfSamples(HrtfSamples.subspan(fademix), AccumSamples.subspan(OutPos), IrSize, + &hrtfparams, todo); /* Store the now-current gain for next time. */ parms.Hrtf.Old.Gain = gain; } } -void DoNfcMix(const al::span samples, FloatBufferLine *OutBuffer, DirectParams &parms, - const float *TargetGains, const uint Counter, const uint OutPos, DeviceBase *Device) +void DoNfcMix(const al::span samples, al::span OutBuffer, + DirectParams &parms, const al::span OutGains, + const uint Counter, const uint OutPos, DeviceBase *Device) { - using FilterProc = void (NfcFilter::*)(const al::span, float*); - static constexpr FilterProc NfcProcess[MaxAmbiOrder+1]{ - nullptr, &NfcFilter::process1, &NfcFilter::process2, &NfcFilter::process3}; + using FilterProc = void (NfcFilter::*)(const al::span, const al::span); + static constexpr std::array NfcProcess{{ + nullptr, &NfcFilter::process1, &NfcFilter::process2, &NfcFilter::process3}}; - float *CurrentGains{parms.Gains.Current.data()}; - MixSamples(samples, {OutBuffer, 1u}, CurrentGains, TargetGains, Counter, OutPos); - ++OutBuffer; - ++CurrentGains; - ++TargetGains; + MixSamples(samples, al::span{OutBuffer[0]}.subspan(OutPos), parms.Gains.Current[0], + OutGains[0], Counter); + OutBuffer = OutBuffer.subspan(1); + auto CurrentGains = al::span{parms.Gains.Current}.subspan(1); + auto TargetGains = OutGains.subspan(1); - const al::span nfcsamples{Device->NfcSampleData, samples.size()}; + const auto nfcsamples = al::span{Device->ExtraSampleData}.first(samples.size()); size_t order{1}; while(const size_t chancount{Device->NumChannelsPerOrder[order]}) { - (parms.NFCtrlFilter.*NfcProcess[order])(samples, nfcsamples.data()); - MixSamples(nfcsamples, {OutBuffer, chancount}, CurrentGains, TargetGains, Counter, OutPos); - OutBuffer += chancount; - CurrentGains += chancount; - TargetGains += chancount; + (parms.NFCtrlFilter.*NfcProcess[order])(samples, nfcsamples); + MixSamples(nfcsamples, OutBuffer.first(chancount), CurrentGains, TargetGains, Counter, + OutPos); if(++order == MaxAmbiOrder+1) break; + OutBuffer = OutBuffer.subspan(chancount); + CurrentGains = CurrentGains.subspan(chancount); + TargetGains = TargetGains.subspan(chancount); } } @@ -696,7 +722,7 @@ void DoNfcMix(const al::span samples, FloatBufferLine *OutBuffer, D void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds deviceTime, const uint SamplesToDo) { - static constexpr std::array SilentTarget{}; + static constexpr std::array SilentTarget{}; ASSUME(SamplesToDo > 0); @@ -750,17 +776,9 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi /* Get the number of samples ahead of the current time that output * should start at. Skip this update if it's beyond the output sample * count. - * - * Round the start position to a multiple of 4, which some mixers want. - * This makes the start time accurate to 4 samples. This could be made - * sample-accurate by forcing non-SIMD functions on the first run. */ - seconds::rep sampleOffset{duration_cast(diff * Device->Frequency).count()}; - sampleOffset = (sampleOffset+2) & ~seconds::rep{3}; - if(sampleOffset >= SamplesToDo) - return; - - OutPos = static_cast(sampleOffset); + OutPos = static_cast(round(diff * Device->mSampleRate).count()); + if(OutPos >= SamplesToDo) return; } /* Calculate the number of samples to mix, and the number of (resampled) @@ -772,34 +790,34 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi /* Get a span of pointers to hold the floating point, deinterlaced, * resampled buffer data to be mixed. */ - std::array SamplePointers; - const al::span MixingSamples{SamplePointers.data(), mChans.size()}; - auto get_bufferline = [](DeviceBase::MixerBufferLine &bufline) noexcept -> float* - { return bufline.data(); }; - std::transform(Device->mSampleData.end() - mChans.size(), Device->mSampleData.end(), - MixingSamples.begin(), get_bufferline); - - /* If there's a matching sample step and no phase offset, use a simple copy - * for resampling. - */ - const ResamplerFunc Resample{(increment == MixerFracOne && DataPosFrac == 0) - ? ResamplerFunc{[](const InterpState*, const float *RESTRICT src, uint, const uint, - const al::span dst) { std::copy_n(src, dst.size(), dst.begin()); }} - : mResampler}; + auto SamplePointers = std::array{}; + const auto MixingSamples = al::span{SamplePointers}.first(mChans.size()); + { + const uint channelStep{(samplesToLoad+3u)&~3u}; + auto base = Device->mSampleData.end() - MixingSamples.size()*channelStep; + std::generate(MixingSamples.begin(), MixingSamples.end(), [&base,channelStep] + { + const auto ret = base; + base += channelStep; + return al::to_address(ret); + }); + } /* UHJ2 and SuperStereo only have 2 buffer channels, but 3 mixing channels - * (3rd channel is generated from decoding). + * (3rd channel is generated from decoding). MonoDup only has 1 buffer + * channel, but 2 mixing channels (2nd channel is just duplicated). */ - const size_t realChannels{(mFmtChannels == FmtUHJ2 || mFmtChannels == FmtSuperStereo) ? 2u + const size_t realChannels{(mFmtChannels == FmtMonoDup) ? 1u + : (mFmtChannels == FmtUHJ2 || mFmtChannels == FmtSuperStereo) ? 2u : MixingSamples.size()}; for(size_t chan{0};chan < realChannels;++chan) { - using ResBufType = decltype(DeviceBase::mResampleData); - static constexpr uint srcSizeMax{static_cast(ResBufType{}.size()-MaxResamplerEdge)}; + static constexpr uint ResBufSize{std::tuple_size_v}; + static constexpr uint srcSizeMax{ResBufSize - MaxResamplerEdge}; const al::span prevSamples{mPrevSamples[chan]}; - const auto resampleBuffer = std::copy(prevSamples.cbegin(), prevSamples.cend(), - Device->mResampleData.begin()) - MaxResamplerEdge; + std::copy(prevSamples.cbegin(), prevSamples.cend(), Device->mResampleData.begin()); + const auto resampleBuffer = al::span{Device->mResampleData}.subspan(); int intPos{DataPosInt}; uint fracPos{DataPosFrac}; @@ -831,7 +849,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi dataSize64 += ext + MaxResamplerEdge; if(dataSize64 <= srcSizeMax) - return std::make_pair(dstBufferSize, static_cast(dataSize64)); + return std::array{dstBufferSize, static_cast(dataSize64)}; /* If the source size got saturated, we can't fill the desired * dst size. Figure out how many dst samples we can fill. @@ -846,88 +864,103 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi */ dstBufferSize = static_cast(dataSize64) & ~3u; } - return std::make_pair(dstBufferSize, srcSizeMax); + return std::array{dstBufferSize, srcSizeMax}; }; - const auto bufferSizes = calc_buffer_sizes(samplesToLoad - samplesLoaded); - const auto dstBufferSize = bufferSizes.first; - const auto srcBufferSize = bufferSizes.second; + const auto [dstBufferSize, srcBufferSize] = calc_buffer_sizes( + samplesToLoad - samplesLoaded); + + size_t srcSampleDelay{0}; + if(intPos < 0) UNLIKELY + { + /* If the current position is negative, there's that many + * silent samples to load before using the buffer. + */ + srcSampleDelay = static_cast(-intPos); + if(srcSampleDelay >= srcBufferSize) + { + /* If the number of silent source samples exceeds the + * number to load, the output will be silent. + */ + std::fill_n(MixingSamples[chan]+samplesLoaded, dstBufferSize, 0.0f); + std::fill_n(resampleBuffer.begin(), srcBufferSize, 0.0f); + goto skip_resample; + } + + std::fill_n(resampleBuffer.begin(), srcSampleDelay, 0.0f); + } /* Load the necessary samples from the given buffer(s). */ - if(!BufferListItem) + if(!BufferListItem) UNLIKELY { - const uint avail{minu(srcBufferSize, MaxResamplerEdge)}; - const uint tofill{maxu(srcBufferSize, MaxResamplerEdge)}; + const uint avail{std::min(srcBufferSize, MaxResamplerEdge)}; + const uint tofill{std::max(srcBufferSize, MaxResamplerEdge)}; + const auto srcbuf = resampleBuffer.first(tofill); /* When loading from a voice that ended prematurely, only take * the samples that get closest to 0 amplitude. This helps * certain sounds fade out better. */ - auto abs_lt = [](const float lhs, const float rhs) noexcept -> bool - { return std::abs(lhs) < std::abs(rhs); }; - auto srciter = std::min_element(resampleBuffer, resampleBuffer+avail, abs_lt); + auto srciter = std::min_element(srcbuf.begin(), srcbuf.begin()+ptrdiff_t(avail), + [](const float l, const float r) { return std::abs(l) < std::abs(r); }); - std::fill(srciter+1, resampleBuffer+tofill, *srciter); + std::fill(srciter+1, srcbuf.end(), *srciter); } - else + else if(mFlags.test(VoiceIsStatic)) { - size_t srcSampleDelay{0}; - if(intPos < 0) UNLIKELY - { - /* If the current position is negative, there's that many - * silent samples to load before using the buffer. - */ - srcSampleDelay = static_cast(-intPos); - if(srcSampleDelay >= srcBufferSize) - { - /* If the number of silent source samples exceeds the - * number to load, the output will be silent. - */ - std::fill_n(MixingSamples[chan]+samplesLoaded, dstBufferSize, 0.0f); - std::fill_n(resampleBuffer, srcBufferSize, 0.0f); - goto skip_resample; - } - - std::fill_n(resampleBuffer, srcSampleDelay, 0.0f); - } - const uint uintPos{static_cast(maxi(intPos, 0))}; - - if(mFlags.test(VoiceIsStatic)) - LoadBufferStatic(BufferListItem, BufferLoopItem, uintPos, mFmtType, chan, - mFrameStep, srcSampleDelay, srcBufferSize, al::to_address(resampleBuffer)); - else if(mFlags.test(VoiceIsCallback)) + const auto uintPos = static_cast(std::max(intPos, 0)); + const auto bufferSamples = resampleBuffer.subspan(srcSampleDelay, + srcBufferSize-srcSampleDelay); + LoadBufferStatic(BufferListItem, BufferLoopItem, uintPos, mFmtType, chan, + mFrameStep, bufferSamples); + } + else if(mFlags.test(VoiceIsCallback)) + { + const auto uintPos = static_cast(std::max(intPos, 0)); + const uint callbackBase{mCallbackBlockBase * mSamplesPerBlock}; + const size_t bufferOffset{uintPos - callbackBase}; + const size_t needSamples{bufferOffset + srcBufferSize - srcSampleDelay}; + const size_t needBlocks{(needSamples + mSamplesPerBlock-1) / mSamplesPerBlock}; + if(!mFlags.test(VoiceCallbackStopped) && needBlocks > mNumCallbackBlocks) { - const uint callbackBase{mCallbackBlockBase * mSamplesPerBlock}; - const size_t bufferOffset{uintPos - callbackBase}; - const size_t needSamples{bufferOffset + srcBufferSize - srcSampleDelay}; - const size_t needBlocks{(needSamples + mSamplesPerBlock-1) / mSamplesPerBlock}; - if(!mFlags.test(VoiceCallbackStopped) && needBlocks > mNumCallbackBlocks) + const size_t byteOffset{mNumCallbackBlocks*size_t{mBytesPerBlock}}; + const size_t needBytes{(needBlocks-mNumCallbackBlocks)*size_t{mBytesPerBlock}}; + + const int gotBytes{BufferListItem->mCallback(BufferListItem->mUserData, + &BufferListItem->mSamples[byteOffset], static_cast(needBytes))}; + if(gotBytes < 0) + mFlags.set(VoiceCallbackStopped); + else if(static_cast(gotBytes) < needBytes) { - const size_t byteOffset{mNumCallbackBlocks*mBytesPerBlock}; - const size_t needBytes{(needBlocks-mNumCallbackBlocks)*mBytesPerBlock}; - - const int gotBytes{BufferListItem->mCallback(BufferListItem->mUserData, - &BufferListItem->mSamples[byteOffset], static_cast(needBytes))}; - if(gotBytes < 0) - mFlags.set(VoiceCallbackStopped); - else if(static_cast(gotBytes) < needBytes) - { - mFlags.set(VoiceCallbackStopped); - mNumCallbackBlocks += static_cast(gotBytes) / mBytesPerBlock; - } - else - mNumCallbackBlocks = static_cast(needBlocks); + mFlags.set(VoiceCallbackStopped); + mNumCallbackBlocks += static_cast(gotBytes) / mBytesPerBlock; } - const size_t numSamples{uint{mNumCallbackBlocks} * mSamplesPerBlock}; - LoadBufferCallback(BufferListItem, bufferOffset, numSamples, mFmtType, chan, - mFrameStep, srcSampleDelay, srcBufferSize, al::to_address(resampleBuffer)); + else + mNumCallbackBlocks = static_cast(needBlocks); } - else - LoadBufferQueue(BufferListItem, BufferLoopItem, uintPos, mFmtType, chan, - mFrameStep, srcSampleDelay, srcBufferSize, al::to_address(resampleBuffer)); + const size_t numSamples{size_t{mNumCallbackBlocks} * mSamplesPerBlock}; + const auto bufferSamples = resampleBuffer.subspan(srcSampleDelay, + srcBufferSize-srcSampleDelay); + LoadBufferCallback(BufferListItem, bufferOffset, numSamples, mFmtType, chan, + mFrameStep, bufferSamples); + } + else + { + const auto uintPos = static_cast(std::max(intPos, 0)); + const auto bufferSamples = resampleBuffer.subspan(srcSampleDelay, + srcBufferSize-srcSampleDelay); + LoadBufferQueue(BufferListItem, BufferLoopItem, uintPos, mFmtType, chan, + mFrameStep, bufferSamples); } - Resample(&mResampleState, al::to_address(resampleBuffer), fracPos, increment, - {MixingSamples[chan]+samplesLoaded, dstBufferSize}); + /* If there's a matching sample step and no phase offset, use a + * simple copy for resampling. + */ + if(increment == MixerFracOne && fracPos == 0) + std::copy_n(resampleBuffer.cbegin(), dstBufferSize, + MixingSamples[chan]+samplesLoaded); + else + mResampler(&mResampleState, Device->mResampleData, fracPos, increment, + {MixingSamples[chan]+samplesLoaded, dstBufferSize}); /* Store the last source samples used for next time. */ if(vstate == Playing) LIKELY @@ -940,7 +973,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi { const size_t dstOffset{samplesToMix - samplesLoaded}; const size_t srcOffset{(dstOffset*increment + fracPos) >> MixerFracBits}; - std::copy_n(resampleBuffer-MaxResamplerEdge+srcOffset, prevSamples.size(), + std::copy_n(Device->mResampleData.cbegin()+srcOffset, prevSamples.size(), prevSamples.begin()); } } @@ -952,18 +985,26 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi fracPos += dstBufferSize*increment; const uint srcOffset{fracPos >> MixerFracBits}; fracPos &= MixerFracMask; - intPos += srcOffset; + intPos += static_cast(srcOffset); /* If more samples need to be loaded, copy the back of the * resampleBuffer to the front to reuse it. prevSamples isn't * reliable since it's only updated for the end of the mix. */ - std::copy(resampleBuffer-MaxResamplerEdge+srcOffset, - resampleBuffer+MaxResamplerEdge+srcOffset, resampleBuffer-MaxResamplerEdge); + std::copy_n(Device->mResampleData.cbegin()+srcOffset, MaxResamplerPadding, + Device->mResampleData.begin()); } } } - for(auto &samples : MixingSamples.subspan(realChannels)) + if(mFmtChannels == FmtMonoDup) + { + /* NOTE: a mono source shouldn't have a decoder or the VoiceIsAmbisonic + * flag, so aliasing instead of copying to the second channel shouldn't + * be a problem. + */ + MixingSamples[1] = MixingSamples[0]; + } + else for(auto &samples : MixingSamples.subspan(realChannels)) std::fill_n(samples, samplesToLoad, 0.0f); if(mDecoder) @@ -980,7 +1021,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi } } - const uint Counter{mFlags.test(VoiceIsFading) ? minu(samplesToMix, 64u) : 0u}; + const uint Counter{mFlags.test(VoiceIsFading) ? std::min(samplesToMix, 64u) : 0u}; if(!Counter) { /* No fading, just overwrite the old/current params. */ @@ -1011,25 +1052,24 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi const al::span FilterBuf{Device->FilteredData}; { DirectParams &parms = chandata.mDryParams; - const float *samples{DoFilters(parms.LowPass, parms.HighPass, FilterBuf.data(), - {*voiceSamples, samplesToMix}, mDirect.FilterType)}; + const auto samples = DoFilters(parms.LowPass, parms.HighPass, FilterBuf, + {*voiceSamples, samplesToMix}, mDirect.FilterType); if(mFlags.test(VoiceHasHrtf)) { - const float TargetGain{parms.Hrtf.Target.Gain * (vstate == Playing)}; - DoHrtfMix(samples, samplesToMix, parms, TargetGain, Counter, OutPos, - (vstate == Playing), Device); + const float TargetGain{parms.Hrtf.Target.Gain * float(vstate == Playing)}; + DoHrtfMix(samples, parms, TargetGain, Counter, OutPos, (vstate == Playing), + Device); } else { - const float *TargetGains{(vstate == Playing) ? parms.Gains.Target.data() - : SilentTarget.data()}; + const auto TargetGains = (vstate == Playing) ? al::span{parms.Gains.Target} + : al::span{SilentTarget}; if(mFlags.test(VoiceHasNfc)) - DoNfcMix({samples, samplesToMix}, mDirect.Buffer.data(), parms, - TargetGains, Counter, OutPos, Device); + DoNfcMix(samples, mDirect.Buffer, parms, TargetGains, Counter, OutPos, Device); else - MixSamples({samples, samplesToMix}, mDirect.Buffer, - parms.Gains.Current.data(), TargetGains, Counter, OutPos); + MixSamples(samples, mDirect.Buffer, parms.Gains.Current, TargetGains, Counter, + OutPos); } } @@ -1039,13 +1079,13 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi continue; SendParams &parms = chandata.mWetParams[send]; - const float *samples{DoFilters(parms.LowPass, parms.HighPass, FilterBuf.data(), - {*voiceSamples, samplesToMix}, mSend[send].FilterType)}; + const auto samples = DoFilters(parms.LowPass, parms.HighPass, FilterBuf, + {*voiceSamples, samplesToMix}, mSend[send].FilterType); - const float *TargetGains{(vstate == Playing) ? parms.Gains.Target.data() - : SilentTarget.data()}; - MixSamples({samples, samplesToMix}, mSend[send].Buffer, - parms.Gains.Current.data(), TargetGains, Counter, OutPos); + const auto TargetGains = (vstate == Playing) ? al::span{parms.Gains.Target} + : al::span{SilentTarget}; + MixSamples(samples, mSend[send].Buffer, parms.Gains.Current, TargetGains, Counter, + OutPos); } ++voiceSamples; @@ -1062,12 +1102,11 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi /* Update voice positions and buffers as needed. */ DataPosFrac += increment*samplesToMix; - const uint SrcSamplesDone{DataPosFrac>>MixerFracBits}; - DataPosInt += SrcSamplesDone; + DataPosInt += static_cast(DataPosFrac>>MixerFracBits); DataPosFrac &= MixerFracMask; uint buffers_done{0u}; - if(BufferListItem && DataPosInt >= 0) LIKELY + if(BufferListItem && DataPosInt > 0) LIKELY { if(mFlags.test(VoiceIsStatic)) { @@ -1098,10 +1137,11 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi const uint blocksDone{currentBlock - mCallbackBlockBase}; if(blocksDone < mNumCallbackBlocks) { - const size_t byteOffset{blocksDone*mBytesPerBlock}; - const size_t byteEnd{mNumCallbackBlocks*mBytesPerBlock}; - std::byte *data{BufferListItem->mSamples}; - std::copy(data+byteOffset, data+byteEnd, data); + const size_t byteOffset{blocksDone*size_t{mBytesPerBlock}}; + const size_t byteEnd{mNumCallbackBlocks*size_t{mBytesPerBlock}}; + const al::span data{BufferListItem->mSamples}; + std::copy(data.cbegin()+ptrdiff_t(byteOffset), data.cbegin()+ptrdiff_t(byteEnd), + data.begin()); mNumCallbackBlocks -= blocksDone; mCallbackBlockBase += blocksDone; } @@ -1119,7 +1159,7 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi if(BufferListItem->mSampleLen > static_cast(DataPosInt)) break; - DataPosInt -= BufferListItem->mSampleLen; + DataPosInt -= static_cast(BufferListItem->mSampleLen); ++buffers_done; BufferListItem = BufferListItem->mNext.load(std::memory_order_relaxed); @@ -1148,9 +1188,9 @@ void Voice::mix(const State vstate, ContextBase *Context, const nanoseconds devi { RingBuffer *ring{Context->mAsyncEvents.get()}; auto evt_vec = ring->getWriteVector(); - if(evt_vec.first.len > 0) + if(evt_vec[0].len > 0) { - auto &evt = InitAsyncEvent(evt_vec.first.buf); + auto &evt = InitAsyncEvent(evt_vec[0].buf); evt.mId = SourceID; evt.mCount = buffers_done; ring->writeAdvance(1); @@ -1173,22 +1213,23 @@ void Voice::prepare(DeviceBase *device) /* Even if storing really high order ambisonics, we only mix channels for * orders up to the device order. The rest are simply dropped. */ - uint num_channels{(mFmtChannels == FmtUHJ2 || mFmtChannels == FmtSuperStereo) ? 3 : - ChannelsFromFmt(mFmtChannels, minu(mAmbiOrder, device->mAmbiOrder))}; - if(num_channels > device->mSampleData.size()) UNLIKELY + uint num_channels{(mFmtChannels == FmtMonoDup) ? 2 + : (mFmtChannels == FmtUHJ2 || mFmtChannels == FmtSuperStereo) ? 3 + : ChannelsFromFmt(mFmtChannels, std::min(mAmbiOrder, device->mAmbiOrder))}; + if(num_channels > device->MixerChannelsMax) UNLIKELY { - ERR("Unexpected channel count: %u (limit: %zu, %d:%d)\n", num_channels, - device->mSampleData.size(), mFmtChannels, mAmbiOrder); - num_channels = static_cast(device->mSampleData.size()); + ERR("Unexpected channel count: {} (limit: {}, {} : {})", num_channels, + device->MixerChannelsMax, NameFromFormat(mFmtChannels), mAmbiOrder); + num_channels = device->MixerChannelsMax; } if(mChans.capacity() > 2 && num_channels < mChans.capacity()) { decltype(mChans){}.swap(mChans); decltype(mPrevSamples){}.swap(mPrevSamples); } - mChans.reserve(maxu(2, num_channels)); + mChans.reserve(std::max(2u, num_channels)); mChans.resize(num_channels); - mPrevSamples.reserve(maxu(2, num_channels)); + mPrevSamples.reserve(std::max(2u, num_channels)); mPrevSamples.resize(num_channels); mDecoder = nullptr; @@ -1252,7 +1293,7 @@ void Voice::prepare(DeviceBase *device) * Note this isn't needed with UHJ output (UHJ2->B-Format->UHJ2 is * identity, so don't mess with it). */ - const BandSplitter splitter{device->mXOverFreq / static_cast(device->Frequency)}; + const BandSplitter splitter{device->mXOverFreq / static_cast(device->mSampleRate)}; for(auto &chandata : mChans) { chandata.mAmbiHFScale = 1.0f; @@ -1272,12 +1313,14 @@ void Voice::prepare(DeviceBase *device) */ else if(mAmbiOrder && device->mAmbiOrder > mAmbiOrder) { - const uint8_t *OrderFromChan{Is2DAmbisonic(mFmtChannels) ? - AmbiIndex::OrderFrom2DChannel.data() : AmbiIndex::OrderFromChannel.data()}; + auto OrdersSpan = Is2DAmbisonic(mFmtChannels) + ? al::span{AmbiIndex::OrderFrom2DChannel} + : al::span{AmbiIndex::OrderFromChannel}; + auto OrderFromChan = OrdersSpan.cbegin(); const auto scales = AmbiScale::GetHFOrderScales(mAmbiOrder, device->mAmbiOrder, device->m2DMixing); - const BandSplitter splitter{device->mXOverFreq / static_cast(device->Frequency)}; + const BandSplitter splitter{device->mXOverFreq / static_cast(device->mSampleRate)}; for(auto &chandata : mChans) { chandata.mAmbiHFScale = scales[*(OrderFromChan++)]; diff --git a/3rdparty/openal/core/voice.h b/3rdparty/openal/core/voice.h index a599eda8f8ec..bb7c6e249844 100644 --- a/3rdparty/openal/core/voice.h +++ b/3rdparty/openal/core/voice.h @@ -10,7 +10,6 @@ #include #include -#include "almalloc.h" #include "alspan.h" #include "bufferline.h" #include "buffer_storage.h" @@ -20,6 +19,7 @@ #include "filters/splitter.h" #include "mixer/defs.h" #include "mixer/hrtfdefs.h" +#include "opthelpers.h" #include "resampler_limits.h" #include "uhjfilter.h" #include "vector.h" @@ -32,7 +32,7 @@ enum class DistanceModel : unsigned char; using uint = unsigned int; -#define MAX_SENDS 6 +inline constexpr size_t MaxSendCount{6}; enum class SpatializeMode : unsigned char { @@ -48,7 +48,7 @@ enum class DirectMode : unsigned char { }; -constexpr uint MaxPitch{10}; +inline constexpr uint MaxPitch{10}; enum { @@ -65,26 +65,29 @@ struct DirectParams { NfcFilter NFCtrlFilter; - struct { - HrtfFilter Old; - HrtfFilter Target; - alignas(16) std::array History; - } Hrtf; + struct HrtfParams { + HrtfFilter Old{}; + HrtfFilter Target{}; + alignas(16) std::array History{}; + }; + HrtfParams Hrtf; - struct { - std::array Current; - std::array Target; - } Gains; + struct GainParams { + std::array Current{}; + std::array Target{}; + }; + GainParams Gains; }; struct SendParams { BiquadFilter LowPass; BiquadFilter HighPass; - struct { - std::array Current; - std::array Target; - } Gains; + struct GainParams { + std::array Current{}; + std::array Target{}; + }; + GainParams Gains; }; @@ -99,7 +102,10 @@ struct VoiceBufferItem { uint mLoopStart{0u}; uint mLoopEnd{0u}; - std::byte *mSamples{nullptr}; + al::span mSamples; + +protected: + ~VoiceBufferItem() = default; }; @@ -138,15 +144,18 @@ struct VoiceProps { float Radius; float EnhWidth; + float Panning; /** Direct filter and auxiliary send info. */ - struct { + struct DirectData { float Gain; float GainHF; float HFReference; float GainLF; float LFReference; - } Direct; + }; + DirectData Direct; + struct SendData { EffectSlot *Slot; float Gain; @@ -154,13 +163,12 @@ struct VoiceProps { float HFReference; float GainLF; float LFReference; - } Send[MAX_SENDS]; + }; + std::array Send; }; struct VoicePropsItem : public VoiceProps { std::atomic next{nullptr}; - - DEF_NEWDEL(VoicePropsItem) }; enum : uint { @@ -175,7 +183,7 @@ enum : uint { VoiceFlagCount }; -struct Voice { +struct SIMDALIGN Voice { enum State { Stopped, Playing, @@ -185,7 +193,7 @@ struct Voice { std::atomic mUpdate{nullptr}; - VoiceProps mProps; + VoiceProps mProps{}; std::atomic mSourceID{0u}; std::atomic mPlayState{Stopped}; @@ -195,30 +203,30 @@ struct Voice { * Source offset in samples, relative to the currently playing buffer, NOT * the whole queue. */ - std::atomic mPosition; + std::atomic mPosition{}; /** Fractional (fixed-point) offset to the next sample. */ - std::atomic mPositionFrac; + std::atomic mPositionFrac{}; /* Current buffer queue item being played. */ - std::atomic mCurrentBuffer; + std::atomic mCurrentBuffer{}; /* Buffer queue item to loop to at end of queue (will be NULL for non- * looping voices). */ - std::atomic mLoopBuffer; + std::atomic mLoopBuffer{}; std::chrono::nanoseconds mStartTime{}; /* Properties for the attached buffer(s). */ - FmtChannels mFmtChannels; - FmtType mFmtType; - uint mFrequency; - uint mFrameStep; /**< In steps of the sample type size. */ - uint mBytesPerBlock; /**< Or for PCM formats, BytesPerFrame. */ - uint mSamplesPerBlock; /**< Always 1 for PCM formats. */ - AmbiLayout mAmbiLayout; - AmbiScaling mAmbiScaling; - uint mAmbiOrder; + FmtChannels mFmtChannels{}; + FmtType mFmtType{}; + uint mFrequency{}; + uint mFrameStep{}; /**< In steps of the sample type size. */ + uint mBytesPerBlock{}; /**< Or for PCM formats, BytesPerFrame. */ + uint mSamplesPerBlock{}; /**< Always 1 for PCM formats. */ + AmbiLayout mAmbiLayout{}; + AmbiScaling mAmbiScaling{}; + uint mAmbiOrder{}; std::unique_ptr mDecoder; uint mDecoderPadding{}; @@ -226,20 +234,20 @@ struct Voice { /** Current target parameters used for mixing. */ uint mStep{0}; - ResamplerFunc mResampler; + ResamplerFunc mResampler{}; InterpState mResampleState; - std::bitset mFlags{}; + std::bitset mFlags; uint mNumCallbackBlocks{0}; uint mCallbackBlockBase{0}; struct TargetData { - int FilterType; + int FilterType{}; al::span Buffer; }; TargetData mDirect; - std::array mSend; + std::array mSend; /* The first MaxResamplerPadding/2 elements are the sample history from the * previous mix, with an additional MaxResamplerPadding/2 elements that are @@ -250,11 +258,11 @@ struct Voice { al::vector mPrevSamples{2}; struct ChannelData { - float mAmbiHFScale, mAmbiLFScale; + float mAmbiHFScale{}, mAmbiLFScale{}; BandSplitter mAmbiSplitter; DirectParams mDryParams; - std::array mWetParams; + std::array mWetParams; }; al::vector mChans{2}; @@ -269,11 +277,9 @@ struct Voice { void prepare(DeviceBase *device); - static void InitMixer(std::optional resampler); - - DEF_NEWDEL(Voice) + static void InitMixer(std::optional resopt); }; -extern Resampler ResamplerDefault; +inline Resampler ResamplerDefault{Resampler::Spline}; #endif /* CORE_VOICE_H */ diff --git a/3rdparty/openal/core/voice_change.h b/3rdparty/openal/core/voice_change.h index ddc6186f5da2..e97c48f33110 100644 --- a/3rdparty/openal/core/voice_change.h +++ b/3rdparty/openal/core/voice_change.h @@ -3,8 +3,6 @@ #include -#include "almalloc.h" - struct Voice; using uint = unsigned int; @@ -24,8 +22,6 @@ struct VoiceChange { VChangeState mState{}; std::atomic mNext{nullptr}; - - DEF_NEWDEL(VoiceChange) }; #endif /* VOICE_CHANGE_H */ diff --git a/3rdparty/openal/examples/common/alhelpers.c b/3rdparty/openal/examples/common/alhelpers.c deleted file mode 100644 index 6627f7042056..000000000000 --- a/3rdparty/openal/examples/common/alhelpers.c +++ /dev/null @@ -1,228 +0,0 @@ -/* - * OpenAL Helpers - * - * Copyright (c) 2011 by Chris Robinson - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - -/* This file contains routines to help with some menial OpenAL-related tasks, - * such as opening a device and setting up a context, closing the device and - * destroying its context, converting between frame counts and byte lengths, - * finding an appropriate buffer format, and getting readable strings for - * channel configs and sample types. */ - -#include "alhelpers.h" - -#include -#include -#include - -#include "AL/al.h" -#include "AL/alc.h" -#include "AL/alext.h" - - -/* InitAL opens a device and sets up a context using default attributes, making - * the program ready to call OpenAL functions. */ -int InitAL(char ***argv, int *argc) -{ - const ALCchar *name; - ALCdevice *device; - ALCcontext *ctx; - - /* Open and initialize a device */ - device = NULL; - if(argc && argv && *argc > 1 && strcmp((*argv)[0], "-device") == 0) - { - device = alcOpenDevice((*argv)[1]); - if(!device) - fprintf(stderr, "Failed to open \"%s\", trying default\n", (*argv)[1]); - (*argv) += 2; - (*argc) -= 2; - } - if(!device) - device = alcOpenDevice(NULL); - if(!device) - { - fprintf(stderr, "Could not open a device!\n"); - return 1; - } - - ctx = alcCreateContext(device, NULL); - if(ctx == NULL || alcMakeContextCurrent(ctx) == ALC_FALSE) - { - if(ctx != NULL) - alcDestroyContext(ctx); - alcCloseDevice(device); - fprintf(stderr, "Could not set a context!\n"); - return 1; - } - - name = NULL; - if(alcIsExtensionPresent(device, "ALC_ENUMERATE_ALL_EXT")) - name = alcGetString(device, ALC_ALL_DEVICES_SPECIFIER); - if(!name || alcGetError(device) != AL_NO_ERROR) - name = alcGetString(device, ALC_DEVICE_SPECIFIER); - printf("Opened \"%s\"\n", name); - - return 0; -} - -/* CloseAL closes the device belonging to the current context, and destroys the - * context. */ -void CloseAL(void) -{ - ALCdevice *device; - ALCcontext *ctx; - - ctx = alcGetCurrentContext(); - if(ctx == NULL) - return; - - device = alcGetContextsDevice(ctx); - - alcMakeContextCurrent(NULL); - alcDestroyContext(ctx); - alcCloseDevice(device); -} - - -const char *FormatName(ALenum format) -{ - switch(format) - { - case AL_FORMAT_MONO8: return "Mono, U8"; - case AL_FORMAT_MONO16: return "Mono, S16"; - case AL_FORMAT_MONO_FLOAT32: return "Mono, Float32"; - case AL_FORMAT_MONO_MULAW: return "Mono, muLaw"; - case AL_FORMAT_MONO_ALAW_EXT: return "Mono, aLaw"; - case AL_FORMAT_MONO_IMA4: return "Mono, IMA4 ADPCM"; - case AL_FORMAT_MONO_MSADPCM_SOFT: return "Mono, MS ADPCM"; - case AL_FORMAT_STEREO8: return "Stereo, U8"; - case AL_FORMAT_STEREO16: return "Stereo, S16"; - case AL_FORMAT_STEREO_FLOAT32: return "Stereo, Float32"; - case AL_FORMAT_STEREO_MULAW: return "Stereo, muLaw"; - case AL_FORMAT_STEREO_ALAW_EXT: return "Stereo, aLaw"; - case AL_FORMAT_STEREO_IMA4: return "Stereo, IMA4 ADPCM"; - case AL_FORMAT_STEREO_MSADPCM_SOFT: return "Stereo, MS ADPCM"; - case AL_FORMAT_QUAD8: return "Quadraphonic, U8"; - case AL_FORMAT_QUAD16: return "Quadraphonic, S16"; - case AL_FORMAT_QUAD32: return "Quadraphonic, Float32"; - case AL_FORMAT_QUAD_MULAW: return "Quadraphonic, muLaw"; - case AL_FORMAT_51CHN8: return "5.1 Surround, U8"; - case AL_FORMAT_51CHN16: return "5.1 Surround, S16"; - case AL_FORMAT_51CHN32: return "5.1 Surround, Float32"; - case AL_FORMAT_51CHN_MULAW: return "5.1 Surround, muLaw"; - case AL_FORMAT_61CHN8: return "6.1 Surround, U8"; - case AL_FORMAT_61CHN16: return "6.1 Surround, S16"; - case AL_FORMAT_61CHN32: return "6.1 Surround, Float32"; - case AL_FORMAT_61CHN_MULAW: return "6.1 Surround, muLaw"; - case AL_FORMAT_71CHN8: return "7.1 Surround, U8"; - case AL_FORMAT_71CHN16: return "7.1 Surround, S16"; - case AL_FORMAT_71CHN32: return "7.1 Surround, Float32"; - case AL_FORMAT_71CHN_MULAW: return "7.1 Surround, muLaw"; - case AL_FORMAT_BFORMAT2D_8: return "B-Format 2D, U8"; - case AL_FORMAT_BFORMAT2D_16: return "B-Format 2D, S16"; - case AL_FORMAT_BFORMAT2D_FLOAT32: return "B-Format 2D, Float32"; - case AL_FORMAT_BFORMAT2D_MULAW: return "B-Format 2D, muLaw"; - case AL_FORMAT_BFORMAT3D_8: return "B-Format 3D, U8"; - case AL_FORMAT_BFORMAT3D_16: return "B-Format 3D, S16"; - case AL_FORMAT_BFORMAT3D_FLOAT32: return "B-Format 3D, Float32"; - case AL_FORMAT_BFORMAT3D_MULAW: return "B-Format 3D, muLaw"; - case AL_FORMAT_UHJ2CHN8_SOFT: return "UHJ 2-channel, U8"; - case AL_FORMAT_UHJ2CHN16_SOFT: return "UHJ 2-channel, S16"; - case AL_FORMAT_UHJ2CHN_FLOAT32_SOFT: return "UHJ 2-channel, Float32"; - case AL_FORMAT_UHJ3CHN8_SOFT: return "UHJ 3-channel, U8"; - case AL_FORMAT_UHJ3CHN16_SOFT: return "UHJ 3-channel, S16"; - case AL_FORMAT_UHJ3CHN_FLOAT32_SOFT: return "UHJ 3-channel, Float32"; - case AL_FORMAT_UHJ4CHN8_SOFT: return "UHJ 4-channel, U8"; - case AL_FORMAT_UHJ4CHN16_SOFT: return "UHJ 4-channel, S16"; - case AL_FORMAT_UHJ4CHN_FLOAT32_SOFT: return "UHJ 4-channel, Float32"; - } - return "Unknown Format"; -} - - -#ifdef _WIN32 - -#define WIN32_LEAN_AND_MEAN -#include -#include - -int altime_get(void) -{ - static int start_time = 0; - int cur_time; - union { - FILETIME ftime; - ULARGE_INTEGER ulint; - } systime; - GetSystemTimeAsFileTime(&systime.ftime); - /* FILETIME is in 100-nanosecond units, or 1/10th of a microsecond. */ - cur_time = (int)(systime.ulint.QuadPart/10000); - - if(!start_time) - start_time = cur_time; - return cur_time - start_time; -} - -void al_nssleep(unsigned long nsec) -{ - Sleep(nsec / 1000000); -} - -#else - -#include -#include -#include - -int altime_get(void) -{ - static int start_time = 0u; - int cur_time; - -#if _POSIX_TIMERS > 0 - struct timespec ts; - int ret = clock_gettime(CLOCK_REALTIME, &ts); - if(ret != 0) return 0; - cur_time = (int)(ts.tv_sec*1000 + ts.tv_nsec/1000000); -#else /* _POSIX_TIMERS > 0 */ - struct timeval tv; - int ret = gettimeofday(&tv, NULL); - if(ret != 0) return 0; - cur_time = (int)(tv.tv_sec*1000 + tv.tv_usec/1000); -#endif - - if(!start_time) - start_time = cur_time; - return cur_time - start_time; -} - -void al_nssleep(unsigned long nsec) -{ - struct timespec ts, rem; - ts.tv_sec = (time_t)(nsec / 1000000000ul); - ts.tv_nsec = (long)(nsec % 1000000000ul); - while(nanosleep(&ts, &rem) == -1 && errno == EINTR) - ts = rem; -} - -#endif diff --git a/3rdparty/openal/examples/common/alhelpers.h b/3rdparty/openal/examples/common/alhelpers.h deleted file mode 100644 index 34f738647668..000000000000 --- a/3rdparty/openal/examples/common/alhelpers.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef ALHELPERS_H -#define ALHELPERS_H - -#include "AL/al.h" - -#ifdef __cplusplus -extern "C" { -#endif - -/* Some helper functions to get the name from the format enums. */ -const char *FormatName(ALenum type); - -/* Easy device init/deinit functions. InitAL returns 0 on success. */ -int InitAL(char ***argv, int *argc); -void CloseAL(void); - -/* Cross-platform timeget and sleep functions. */ -int altime_get(void); -void al_nssleep(unsigned long nsec); - -/* C doesn't allow casting between function and non-function pointer types, so - * with C99 we need to use a union to reinterpret the pointer type. Pre-C99 - * still needs to use a normal cast and live with the warning (C++ is fine with - * a regular reinterpret_cast). - */ -#if __STDC_VERSION__ >= 199901L -#define FUNCTION_CAST(T, ptr) (union{void *p; T f;}){ptr}.f -#elif defined(__cplusplus) -#define FUNCTION_CAST(T, ptr) reinterpret_cast(ptr) -#else -#define FUNCTION_CAST(T, ptr) (T)(ptr) -#endif - -#ifdef __cplusplus -} // extern "C" -#endif - -#endif /* ALHELPERS_H */ diff --git a/3rdparty/openal/include/AL/al.h b/3rdparty/openal/include/AL/al.h index 87274184b2db..a4e3ad5159f1 100644 --- a/3rdparty/openal/include/AL/al.h +++ b/3rdparty/openal/include/AL/al.h @@ -1,12 +1,23 @@ #ifndef AL_AL_H #define AL_AL_H +/* NOLINTBEGIN */ #ifdef __cplusplus extern "C" { +#ifdef _MSVC_LANG +#define AL_CPLUSPLUS _MSVC_LANG +#else +#define AL_CPLUSPLUS __cplusplus +#endif + #ifndef AL_DISABLE_NOEXCEPT +#if AL_CPLUSPLUS >= 201103L #define AL_API_NOEXCEPT noexcept -#if __cplusplus >= 201703L +#else +#define AL_API_NOEXCEPT +#endif +#if AL_CPLUSPLUS >= 201703L #define AL_API_NOEXCEPT17 noexcept #else #define AL_API_NOEXCEPT17 @@ -18,6 +29,8 @@ extern "C" { #define AL_API_NOEXCEPT17 #endif +#undef AL_CPLUSPLUS + #else /* __cplusplus */ #define AL_API_NOEXCEPT @@ -689,5 +702,6 @@ typedef void (AL_APIENTRY *LPALDISTANCEMODEL)(ALenum distanceModel) AL_ #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_AL_H */ diff --git a/3rdparty/openal/include/AL/alc.h b/3rdparty/openal/include/AL/alc.h index 73dcf08f043d..d048ca04dbd0 100644 --- a/3rdparty/openal/include/AL/alc.h +++ b/3rdparty/openal/include/AL/alc.h @@ -1,12 +1,23 @@ #ifndef AL_ALC_H #define AL_ALC_H +/* NOLINTBEGIN */ #ifdef __cplusplus extern "C" { +#ifdef _MSVC_LANG +#define ALC_CPLUSPLUS _MSVC_LANG +#else +#define ALC_CPLUSPLUS __cplusplus +#endif + #ifndef AL_DISABLE_NOEXCEPT +#if ALC_CPLUSPLUS >= 201103L #define ALC_API_NOEXCEPT noexcept -#if __cplusplus >= 201703L +#else +#define ALC_API_NOEXCEPT +#endif +#if ALC_CPLUSPLUS >= 201703L #define ALC_API_NOEXCEPT17 noexcept #else #define ALC_API_NOEXCEPT17 @@ -18,6 +29,8 @@ extern "C" { #define ALC_API_NOEXCEPT17 #endif +#undef ALC_CPLUSPLUS + #else /* __cplusplus */ #define ALC_API_NOEXCEPT @@ -289,5 +302,6 @@ typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)(ALCdevice *device, AL #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_ALC_H */ diff --git a/3rdparty/openal/include/AL/alext.h b/3rdparty/openal/include/AL/alext.h index b99d6aacb83b..3908e19404c7 100644 --- a/3rdparty/openal/include/AL/alext.h +++ b/3rdparty/openal/include/AL/alext.h @@ -1,6 +1,7 @@ #ifndef AL_ALEXT_H #define AL_ALEXT_H +/* NOLINTBEGIN */ #include /* Define int64 and uint64 types */ #if (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L) || \ @@ -25,6 +26,8 @@ typedef uint64_t _alsoft_uint64_t; extern "C" { #endif +struct _GUID; + #ifndef AL_LOKI_IMA_ADPCM_format #define AL_LOKI_IMA_ADPCM_format 1 #define AL_FORMAT_IMA_ADPCM_MONO16_EXT 0x10000 @@ -701,15 +704,19 @@ typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPEXT)(void) AL_API_NOEXCEPT17; typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGEXT)(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; typedef void (AL_APIENTRY*LPALGETOBJECTLABELEXT)(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTEREXT)(ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVEXT)(ALenum pname, void **values) AL_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES void AL_APIENTRY alDebugMessageCallbackEXT(ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; void AL_APIENTRY alDebugMessageInsertEXT(ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; -void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; -void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; -ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlEXT(ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupEXT(ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupEXT(void) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogEXT(ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; void AL_APIENTRY alObjectLabelEXT(ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerEXT(ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervEXT(ALenum pname, void **values) AL_API_NOEXCEPT; #endif #endif @@ -720,18 +727,366 @@ void AL_APIENTRY alGetObjectLabelEXT(ALenum identifier, ALuint name, ALsizei buf #define ALC_EVENT_TYPE_DEFAULT_DEVICE_CHANGED_SOFT 0x19D6 #define ALC_EVENT_TYPE_DEVICE_ADDED_SOFT 0x19D7 #define ALC_EVENT_TYPE_DEVICE_REMOVED_SOFT 0x19D8 +#define ALC_EVENT_SUPPORTED_SOFT 0x19D9 +#define ALC_EVENT_NOT_SUPPORTED_SOFT 0x19DA typedef void (ALC_APIENTRY*ALCEVENTPROCTYPESOFT)(ALCenum eventType, ALCenum deviceType, ALCdevice *device, ALCsizei length, const ALCchar *message, void *userParam) ALC_API_NOEXCEPT17; +typedef ALCenum (ALC_APIENTRY*LPALCEVENTISSUPPORTEDSOFT)(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT17; typedef ALCboolean (ALC_APIENTRY*LPALCEVENTCONTROLSOFT)(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT17; typedef void (ALC_APIENTRY*LPALCEVENTCALLBACKSOFT)(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT17; #ifdef AL_ALEXT_PROTOTYPES +ALCenum ALC_APIENTRY alcEventIsSupportedSOFT(ALCenum eventType, ALCenum deviceType) ALC_API_NOEXCEPT; ALCboolean ALC_APIENTRY alcEventControlSOFT(ALCsizei count, const ALCenum *events, ALCboolean enable) ALC_API_NOEXCEPT; void ALC_APIENTRY alcEventCallbackSOFT(ALCEVENTPROCTYPESOFT callback, void *userParam) ALC_API_NOEXCEPT; #endif #endif +#ifndef AL_EXT_direct_context +#define AL_EXT_direct_context +typedef ALCvoid* (ALC_APIENTRY *LPALCGETPROCADDRESS2)(ALCdevice *device, const ALCchar *funcname) AL_API_NOEXCEPT17; + +typedef void (AL_APIENTRY *LPALENABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISABLEDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISENABLEDDIRECT)(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDOPPLERFACTORDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSPEEDOFSOUNDDIRECT)(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDISTANCEMODELDIRECT)(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT17; +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBOOLEANVDIRECT)(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETINTEGERVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFLOATVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETDOUBLEVDIRECT)(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEANDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALint (AL_APIENTRY *LPALGETINTEGERDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALfloat (AL_APIENTRY *LPALGETFLOATDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLEDIRECT)(ALCcontext *context, ALenum param) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETERRORDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENTDIRECT)(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPROCADDRESSDIRECT)(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUEDIRECT)(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERFVDIRECT)(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALLISTENERIVDIRECT)(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFDIRECT)(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3FDIRECT)(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERFVDIRECT)(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIDIRECT)(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENER3IDIRECT)(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETLISTENERIVDIRECT)(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENSOURCESDIRECT)(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETESOURCESDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISSOURCEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3FDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEFVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3IDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEIVDIRECT)(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEDIRECT)(ALCcontext *context, ALuint source) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCESTOPVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEREWINDVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPAUSEVDIRECT)(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERSDIRECT)(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENBUFFERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEBUFFERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISBUFFERDIRECT)(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERDATADIRECT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3FDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERFVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3IDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERIVDIRECT)(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT17; +/* ALC_EXT_EFX */ +typedef void (AL_APIENTRY *LPALGENEFFECTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEEFFECTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISEFFECTDIRECT)(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTIVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETEFFECTFVDIRECT)(ALCcontext *context, ALuint effect, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENFILTERSDIRECT)(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEFILTERSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISFILTERDIRECT)(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERIVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETFILTERFVDIRECT)(ALCcontext *context, ALuint filter, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGENAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALDELETEAUXILIARYEFFECTSLOTSDIRECT)(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPALISAUXILIARYEFFECTSLOTDIRECT)(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTIVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALint *values) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETAUXILIARYEFFECTSLOTFVDIRECT)(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *values) AL_API_NOEXCEPT17; +/* AL_EXT_BUFFER_DATA_STATIC */ +typedef void (AL_APIENTRY *LPALBUFFERDATASTATICDIRECT)(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT17; +/* AL_EXT_debug */ +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECALLBACKDIRECTEXT)(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGEINSERTDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALDEBUGMESSAGECONTROLDIRECTEXT)(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPUSHDEBUGGROUPDIRECTEXT)(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALPOPDEBUGGROUPDIRECTEXT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef ALuint (AL_APIENTRY*LPALGETDEBUGMESSAGELOGDIRECTEXT)(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETOBJECTLABELDIRECTEXT)(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY*LPALGETPOINTERDIRECTEXT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY*LPALGETPOINTERVDIRECTEXT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_EXT_FOLDBACK */ +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTARTDIRECT)(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALREQUESTFOLDBACKSTOPDIRECT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_buffer_sub_data */ +typedef void (AL_APIENTRY *LPALBUFFERSUBDATADIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT17; +/* AL_SOFT_source_latency */ +typedef void (AL_APIENTRY *LPALSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble,ALdouble,ALdouble) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3DDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*,ALdouble*,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEDVDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALdouble*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT,ALint64SOFT,ALint64SOFT) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,const ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCE3I64DIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*,ALint64SOFT*,ALint64SOFT*) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETSOURCEI64VDIRECTSOFT)(ALCcontext*,ALuint,ALenum,ALint64SOFT*) AL_API_NOEXCEPT17; +/* AL_SOFT_deferred_updates */ +typedef void (AL_APIENTRY *LPALDEFERUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALPROCESSUPDATESDIRECTSOFT)(ALCcontext *context) AL_API_NOEXCEPT17; +/* AL_SOFT_source_resampler */ +typedef const ALchar* (AL_APIENTRY *LPALGETSTRINGIDIRECTSOFT)(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT17; +/* AL_SOFT_events */ +typedef void (AL_APIENTRY *LPALEVENTCONTROLDIRECTSOFT)(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALEVENTCALLBACKDIRECTSOFT)(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT17; +typedef void* (AL_APIENTRY *LPALGETPOINTERDIRECTSOFT)(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETPOINTERVDIRECTSOFT)(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT17; +/* AL_SOFT_callback_buffer */ +typedef void (AL_APIENTRY *LPALBUFFERCALLBACKDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFER3PTRDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **value1, ALvoid **value2, ALvoid **value3) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALGETBUFFERPTRVDIRECTSOFT)(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **values) AL_API_NOEXCEPT17; +/* AL_SOFT_source_start_delay */ +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEDIRECTSOFT)(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT17; +typedef void (AL_APIENTRY *LPALSOURCEPLAYATTIMEVDIRECTSOFT)(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT17; +/* EAX */ +typedef ALenum (AL_APIENTRY *LPEAXSETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETDIRECT)(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT17; +typedef ALboolean (AL_APIENTRY *LPEAXSETBUFFERMODEDIRECT)(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT17; +typedef ALenum (AL_APIENTRY *LPEAXGETBUFFERMODEDIRECT)(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT17; +#ifdef AL_ALEXT_PROTOTYPES +ALCvoid* ALC_APIENTRY alcGetProcAddress2(ALCdevice *device, const ALCchar *funcName) AL_API_NOEXCEPT; + +void AL_APIENTRY alEnableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +void AL_APIENTRY alDisableDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEnabledDirect(ALCcontext *context, ALenum capability) AL_API_NOEXCEPT; + +void AL_APIENTRY alDopplerFactorDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSpeedOfSoundDirect(ALCcontext *context, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alDistanceModelDirect(ALCcontext *context, ALenum distanceModel) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBooleanvDirect(ALCcontext *context, ALenum param, ALboolean *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetIntegervDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFloatvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetDoublevDirect(ALCcontext *context, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alGetBooleanDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALint AL_APIENTRY alGetIntegerDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALfloat AL_APIENTRY alGetFloatDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; +ALdouble AL_APIENTRY alGetDoubleDirect(ALCcontext *context, ALenum param) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY alGetErrorDirect(ALCcontext *context) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsExtensionPresentDirect(ALCcontext *context, const ALchar *extname) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetProcAddressDirect(ALCcontext *context, const ALchar *fname) AL_API_NOEXCEPT; +ALenum AL_APIENTRY alGetEnumValueDirect(ALCcontext *context, const ALchar *ename) AL_API_NOEXCEPT; + +void AL_APIENTRY alListenerfDirect(ALCcontext *context, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3fDirect(ALCcontext *context, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerfvDirect(ALCcontext *context, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alListeneriDirect(ALCcontext *context, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alListener3iDirect(ALCcontext *context, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alListenerivDirect(ALCcontext *context, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfDirect(ALCcontext *context, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3fDirect(ALCcontext *context, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerfvDirect(ALCcontext *context, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListeneriDirect(ALCcontext *context, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListener3iDirect(ALCcontext *context, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetListenerivDirect(ALCcontext *context, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenSourcesDirect(ALCcontext *context, ALsizei n, ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteSourcesDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsSourceDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceivDirect(ALCcontext *context, ALuint source, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3fDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcefvDirect(ALCcontext *context, ALuint source, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceiDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3iDirect(ALCcontext *context, ALuint source, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourceivDirect(ALCcontext *context, ALuint source, ALenum param, ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePauseDirect(ALCcontext *context, ALuint source) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceStopvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceRewindvDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePausevDirect(ALCcontext *context, ALsizei n, const ALuint *sources) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceQueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, const ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alSourceUnqueueBuffersDirect(ALCcontext *context, ALuint source, ALsizei nb, ALuint *buffers) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenBuffersDirect(ALCcontext *context, ALsizei n, ALuint *buffers) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteBuffersDirect(ALCcontext *context, ALsizei n, const ALuint *buffers) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsBufferDirect(ALCcontext *context, ALuint buffer) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferDataDirect(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei size, ALsizei samplerate) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value) AL_API_NOEXCEPT; +void AL_APIENTRY alBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint value1, ALint value2, ALint value3) AL_API_NOEXCEPT; +void AL_APIENTRY alBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, const ALint *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3fDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferfvDirect(ALCcontext *context, ALuint buffer, ALenum param, ALfloat *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferiDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3iDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *value1, ALint *value2, ALint *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferivDirect(ALCcontext *context, ALuint buffer, ALenum param, ALint *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenEffectsDirect(ALCcontext *context, ALsizei n, ALuint *effects) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteEffectsDirect(ALCcontext *context, ALsizei n, const ALuint *effects) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsEffectDirect(ALCcontext *context, ALuint effect) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectiDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectivDirect(ALCcontext *context, ALuint effect, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetEffectfvDirect(ALCcontext *context, ALuint effect, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenFiltersDirect(ALCcontext *context, ALsizei n, ALuint *filters) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteFiltersDirect(ALCcontext *context, ALsizei n, const ALuint *filters) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsFilterDirect(ALCcontext *context, ALuint filter) AL_API_NOEXCEPT; +void AL_APIENTRY alFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilteriDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterivDirect(ALCcontext *context, ALuint filter, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetFilterfvDirect(ALCcontext *context, ALuint filter, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alGenAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, ALuint *effectslots) AL_API_NOEXCEPT; +void AL_APIENTRY alDeleteAuxiliaryEffectSlotsDirect(ALCcontext *context, ALsizei n, const ALuint *effectslots) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY alIsAuxiliaryEffectSlotDirect(ALCcontext *context, ALuint effectslot) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint iValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat flValue) AL_API_NOEXCEPT; +void AL_APIENTRY alAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, const ALfloat *pflValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotiDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotivDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALint *piValues) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValue) AL_API_NOEXCEPT; +void AL_APIENTRY alGetAuxiliaryEffectSlotfvDirect(ALCcontext *context, ALuint effectslot, ALenum param, ALfloat *pflValues) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferDataStaticDirect(ALCcontext *context, ALuint buffer, ALenum format, ALvoid *data, ALsizei size, ALsizei freq) AL_API_NOEXCEPT; + +void AL_APIENTRY alDebugMessageCallbackDirectEXT(ALCcontext *context, ALDEBUGPROCEXT callback, void *userParam) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageInsertDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALuint id, ALenum severity, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alDebugMessageControlDirectEXT(ALCcontext *context, ALenum source, ALenum type, ALenum severity, ALsizei count, const ALuint *ids, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alPushDebugGroupDirectEXT(ALCcontext *context, ALenum source, ALuint id, ALsizei length, const ALchar *message) AL_API_NOEXCEPT; +void AL_APIENTRY alPopDebugGroupDirectEXT(ALCcontext *context) AL_API_NOEXCEPT; +ALuint AL_APIENTRY alGetDebugMessageLogDirectEXT(ALCcontext *context, ALuint count, ALsizei logBufSize, ALenum *sources, ALenum *types, ALuint *ids, ALenum *severities, ALsizei *lengths, ALchar *logBuf) AL_API_NOEXCEPT; +void AL_APIENTRY alObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei length, const ALchar *label) AL_API_NOEXCEPT; +void AL_APIENTRY alGetObjectLabelDirectEXT(ALCcontext *context, ALenum identifier, ALuint name, ALsizei bufSize, ALsizei *length, ALchar *label) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectEXT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectEXT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alRequestFoldbackStartDirect(ALCcontext *context, ALenum mode, ALsizei count, ALsizei length, ALfloat *mem, LPALFOLDBACKCALLBACK callback) AL_API_NOEXCEPT; +void AL_APIENTRY alRequestFoldbackStopDirect(ALCcontext *context) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferSubDataDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, const ALvoid *data, ALsizei offset, ALsizei length) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble value1, ALdouble value2, ALdouble value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3dDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *value1, ALdouble *value2, ALdouble *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcedvDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALdouble *values) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value) AL_API_NOEXCEPT; +void AL_APIENTRY alSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT value1, ALint64SOFT value2, ALint64SOFT value3) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, const ALint64SOFT *values) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSource3i64DirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *value1, ALint64SOFT *value2, ALint64SOFT *value3) AL_API_NOEXCEPT; +void AL_APIENTRY alGetSourcei64vDirectSOFT(ALCcontext *context, ALuint source, ALenum param, ALint64SOFT *values) AL_API_NOEXCEPT; + +void AL_APIENTRY alDeferUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; +void AL_APIENTRY alProcessUpdatesDirectSOFT(ALCcontext *context) AL_API_NOEXCEPT; + +const ALchar* AL_APIENTRY alGetStringiDirectSOFT(ALCcontext *context, ALenum pname, ALsizei index) AL_API_NOEXCEPT; + +void AL_APIENTRY alEventControlDirectSOFT(ALCcontext *context, ALsizei count, const ALenum *types, ALboolean enable) AL_API_NOEXCEPT; +void AL_APIENTRY alEventCallbackDirectSOFT(ALCcontext *context, ALEVENTPROCSOFT callback, void *userParam) AL_API_NOEXCEPT; +void* AL_APIENTRY alGetPointerDirectSOFT(ALCcontext *context, ALenum pname) AL_API_NOEXCEPT; +void AL_APIENTRY alGetPointervDirectSOFT(ALCcontext *context, ALenum pname, void **values) AL_API_NOEXCEPT; + +void AL_APIENTRY alBufferCallbackDirectSOFT(ALCcontext *context, ALuint buffer, ALenum format, ALsizei freq, ALBUFFERCALLBACKTYPESOFT callback, ALvoid *userptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBuffer3PtrDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr0, ALvoid **ptr1, ALvoid **ptr2) AL_API_NOEXCEPT; +void AL_APIENTRY alGetBufferPtrvDirectSOFT(ALCcontext *context, ALuint buffer, ALenum param, ALvoid **ptr) AL_API_NOEXCEPT; + +void AL_APIENTRY alSourcePlayAtTimeDirectSOFT(ALCcontext *context, ALuint source, ALint64SOFT start_time) AL_API_NOEXCEPT; +void AL_APIENTRY alSourcePlayAtTimevDirectSOFT(ALCcontext *context, ALsizei n, const ALuint *sources, ALint64SOFT start_time) AL_API_NOEXCEPT; + +ALenum AL_APIENTRY EAXSetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetDirect(ALCcontext *context, const struct _GUID *property_set_id, ALuint property_id, ALuint source_id, ALvoid *value, ALuint value_size) AL_API_NOEXCEPT; +ALboolean AL_APIENTRY EAXSetBufferModeDirect(ALCcontext *context, ALsizei n, const ALuint *buffers, ALint value) AL_API_NOEXCEPT; +ALenum AL_APIENTRY EAXGetBufferModeDirect(ALCcontext *context, ALuint buffer, ALint *pReserved) AL_API_NOEXCEPT; +#endif +#endif + +#ifndef AL_SOFT_bformat_hoa +#define AL_SOFT_bformat_hoa +#define AL_UNPACK_AMBISONIC_ORDER_SOFT 0x199D +#endif + #ifdef __cplusplus } #endif +/* NOLINTEND */ #endif diff --git a/3rdparty/openal/include/AL/efx-presets.h b/3rdparty/openal/include/AL/efx-presets.h index 8539fd51789f..acd5bf398522 100644 --- a/3rdparty/openal/include/AL/efx-presets.h +++ b/3rdparty/openal/include/AL/efx-presets.h @@ -2,6 +2,7 @@ #ifndef EFX_PRESETS_H #define EFX_PRESETS_H +/* NOLINTBEGIN */ #ifndef EFXEAXREVERBPROPERTIES_DEFINED #define EFXEAXREVERBPROPERTIES_DEFINED @@ -399,4 +400,5 @@ typedef struct { #define EFX_REVERB_PRESET_SMALLWATERROOM \ { 1.0000f, 0.7000f, 0.3162f, 0.4477f, 1.0000f, 1.5100f, 1.2500f, 1.1400f, 0.8913f, 0.0200f, { 0.0000f, 0.0000f, 0.0000f }, 1.4125f, 0.0300f, { 0.0000f, 0.0000f, 0.0000f }, 0.1790f, 0.1500f, 0.8950f, 0.1900f, 0.9920f, 5000.0000f, 250.0000f, 0.0000f, 0x0 } +/* NOLINTEND */ #endif /* EFX_PRESETS_H */ diff --git a/3rdparty/openal/include/AL/efx.h b/3rdparty/openal/include/AL/efx.h index f24222c353db..1e93bf2222b4 100644 --- a/3rdparty/openal/include/AL/efx.h +++ b/3rdparty/openal/include/AL/efx.h @@ -1,6 +1,7 @@ #ifndef AL_EFX_H #define AL_EFX_H +/* NOLINTBEGIN */ #include #include "alc.h" @@ -758,5 +759,6 @@ AL_API void AL_APIENTRY alGetAuxiliaryEffectSlotfv(ALuint effectslot, ALenum par #ifdef __cplusplus } /* extern "C" */ #endif +/* NOLINTEND */ #endif /* AL_EFX_H */ diff --git a/3rdparty/simdjson/simdjson.cpp b/3rdparty/simdjson/simdjson.cpp index d79fc703a815..819942e8289b 100644 --- a/3rdparty/simdjson/simdjson.cpp +++ b/3rdparty/simdjson/simdjson.cpp @@ -1,4 +1,4 @@ -/* auto-generated on 2024-08-26 09:37:03 -0400. Do not edit! */ +/* auto-generated on 2025-06-04 00:22:10 -0400. Do not edit! */ /* including simdjson.cpp: */ /* begin file simdjson.cpp */ #define SIMDJSON_SRC_SIMDJSON_CPP @@ -77,6 +77,30 @@ #endif #endif +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + +#if defined(__apple_build_version__) +#if __apple_build_version__ < 14000000 +#define SIMDJSON_CONCEPT_DISABLED 1 // apple-clang/13 doesn't support std::convertible_to +#endif +#endif + + +#if defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) +#if __cpp_concepts >= 201907L +#include +#define SIMDJSON_SUPPORTS_DESERIALIZATION 1 +#else +#define SIMDJSON_SUPPORTS_DESERIALIZATION 0 +#endif +#else // defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) +#define SIMDJSON_SUPPORTS_DESERIALIZATION 0 +#endif // defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) + #endif // SIMDJSON_COMPILER_CHECK_H /* end file simdjson/compiler_check.h */ /* including simdjson/portability.h: #include "simdjson/portability.h" */ @@ -89,11 +113,15 @@ #include #include #include +#include #ifndef _WIN32 // strcasecmp, strncasecmp #include #endif +static_assert(CHAR_BIT == 8, "simdjson requires 8-bit bytes"); + + // We are using size_t without namespace std:: throughout the project using std::size_t; @@ -127,6 +155,7 @@ using std::size_t; #elif defined(__loongarch_lp64) #define SIMDJSON_IS_LOONGARCH64 1 #elif defined(__PPC64__) || defined(_M_PPC64) +#define SIMDJSON_IS_PPC64 1 #if defined(__ALTIVEC__) #define SIMDJSON_IS_PPC64_VMX 1 #endif // defined(__ALTIVEC__) @@ -284,6 +313,45 @@ using std::size_t; #endif + + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(sun) || defined(__sun) +#include +#elif defined(__MVS__) +#include +#else +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#define SIMDJSON_IS_BIG_ENDIAN 1 +#endif +#endif + + #endif // SIMDJSON_PORTABILITY_H /* end file simdjson/portability.h */ @@ -305,7 +373,7 @@ double from_chars(const char *first, const char* end) noexcept; } #ifndef SIMDJSON_EXCEPTIONS -#if __cpp_exceptions +#if defined(__cpp_exceptions) || defined(_CPPUNWIND) #define SIMDJSON_EXCEPTIONS 1 #else #define SIMDJSON_EXCEPTIONS 0 @@ -508,12 +576,14 @@ double from_chars(const char *first, const char* end) noexcept; // even if we do not have C++17 support. #ifdef __cpp_lib_string_view #define SIMDJSON_HAS_STRING_VIEW +#include #endif // Some systems have string_view even if we do not have C++17 support, // and even if __cpp_lib_string_view is undefined, it is the case // with Apple clang version 11. // We must handle it. *This is important.* +#ifndef _MSC_VER #ifndef SIMDJSON_HAS_STRING_VIEW #if defined __has_include // do not combine the next #if with the previous one (unsafe) @@ -529,6 +599,7 @@ double from_chars(const char *first, const char* end) noexcept; #endif // __has_include () #endif // defined __has_include #endif // def SIMDJSON_HAS_STRING_VIEW +#endif // def _MSC_VER // end of complicated but important routine to try to detect string_view. // @@ -549,7 +620,6 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#pragma once #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED @@ -709,22 +779,22 @@ inline namespace literals { inline namespace string_view_literals { -constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1) +constexpr std::string_view operator ""_sv( const char* str, size_t len ) noexcept // (1) { return std::string_view{ str, len }; } -constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2) +constexpr std::u16string_view operator ""_sv( const char16_t* str, size_t len ) noexcept // (2) { return std::u16string_view{ str, len }; } -constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3) +constexpr std::u32string_view operator ""_sv( const char32_t* str, size_t len ) noexcept // (3) { return std::u32string_view{ str, len }; } -constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4) +constexpr std::wstring_view operator ""_sv( const wchar_t* str, size_t len ) noexcept // (4) { return std::wstring_view{ str, len }; } @@ -2055,22 +2125,22 @@ nssv_inline_ns namespace string_view_literals { #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS -nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1) +nssv_constexpr nonstd::sv_lite::string_view operator ""sv( const char* str, size_t len ) nssv_noexcept // (1) { return nonstd::sv_lite::string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +nssv_constexpr nonstd::sv_lite::u16string_view operator ""sv( const char16_t* str, size_t len ) nssv_noexcept // (2) { return nonstd::sv_lite::u16string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +nssv_constexpr nonstd::sv_lite::u32string_view operator ""sv( const char32_t* str, size_t len ) nssv_noexcept // (3) { return nonstd::sv_lite::u32string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +nssv_constexpr nonstd::sv_lite::wstring_view operator ""sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) { return nonstd::sv_lite::wstring_view{ str, len }; } @@ -2079,22 +2149,22 @@ nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, #if nssv_CONFIG_USR_SV_OPERATOR -nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1) +nssv_constexpr nonstd::sv_lite::string_view operator ""_sv( const char* str, size_t len ) nssv_noexcept // (1) { return nonstd::sv_lite::string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +nssv_constexpr nonstd::sv_lite::u16string_view operator ""_sv( const char16_t* str, size_t len ) nssv_noexcept // (2) { return nonstd::sv_lite::u16string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +nssv_constexpr nonstd::sv_lite::u32string_view operator ""_sv( const char32_t* str, size_t len ) nssv_noexcept // (3) { return nonstd::sv_lite::u32string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +nssv_constexpr nonstd::sv_lite::wstring_view operator ""_sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) { return nonstd::sv_lite::wstring_view{ str, len }; } @@ -2364,7 +2434,7 @@ enum error_code { SUCCESS = 0, ///< No error CAPACITY, ///< This parser can't support a document that big MEMALLOC, ///< Error allocating memory, most likely out of memory - TAPE_ERROR, ///< Something went wrong, this is a generic error + TAPE_ERROR, ///< Something went wrong, this is a generic error. Fatal/unrecoverable error. DEPTH_ERROR, ///< Your document exceeds the user-specified depth limitation STRING_ERROR, ///< Problem while parsing a string T_ATOM_ERROR, ///< Problem while parsing an atom starting with the letter 't' @@ -2389,13 +2459,21 @@ enum error_code { PARSER_IN_USE, ///< parser is already in use. OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1) INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it. - INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early. + INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early. Fatal/unrecoverable error. SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value. OUT_OF_BOUNDS, ///< Attempted to access location outside of document. TRAILING_CONTENT, ///< Unexpected trailing content in the JSON input NUM_ERROR_CODES }; +/** + * Some errors are fatal and invalidate the document. This function returns true if the + * error is fatal. It returns true for TAPE_ERROR and INCOMPLETE_ARRAY_OR_OBJECT. + * Once a fatal error is encountered, the on-demand document is no longer valid and + * processing should stop. + */ + inline bool is_fatal(error_code error) noexcept; + /** * It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether * we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code @@ -2430,7 +2508,7 @@ struct simdjson_error : public std::exception { */ simdjson_error(error_code error) noexcept : _error{error} { } /** The error message */ - const char *what() const noexcept { return error_message(error()); } + const char *what() const noexcept override { return error_message(error()); } /** The error code */ error_code error() const noexcept { return _error; } private: @@ -2532,6 +2610,7 @@ struct simdjson_result_base : protected std::pair { * @throw simdjson_error if there was an error. */ simdjson_inline operator T&&() && noexcept(false); + #endif // SIMDJSON_EXCEPTIONS /** @@ -2588,7 +2667,17 @@ struct simdjson_result : public internal::simdjson_result_base { * @param value The variable to assign the value to. May not be set if there is an error. */ simdjson_warn_unused simdjson_inline error_code get(T &value) && noexcept; - +// + /** + * Copy the value to a provided std::string, only enabled for std::string_view. + * + * @param value The variable to assign the value to. May not be set if there is an error. + */ + simdjson_warn_unused simdjson_inline error_code get(std::string &value) && noexcept +#if SIMDJSON_SUPPORTS_DESERIALIZATION + requires (!std::is_same_v) +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + ; /** * The error. */ @@ -2662,6 +2751,140 @@ inline const std::string error_message(int error) noexcept; #endif // SIMDJSON_ERROR_H /* end file simdjson/error.h */ /* skipped duplicate #include "simdjson/portability.h" */ +/* including simdjson/concepts.h: #include "simdjson/concepts.h" */ +/* begin file simdjson/concepts.h */ +#ifndef SIMDJSON_CONCEPTS_H +#define SIMDJSON_CONCEPTS_H +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#include +#include + +namespace simdjson { +namespace concepts { + +namespace details { +#define SIMDJSON_IMPL_CONCEPT(name, method) \ + template \ + concept supports_##name = !std::is_const_v && requires { \ + typename std::remove_cvref_t::value_type; \ + requires requires(typename std::remove_cvref_t::value_type &&val, \ + T obj) { \ + obj.method(std::move(val)); \ + requires !requires { obj = std::move(val); }; \ + }; \ + }; + +SIMDJSON_IMPL_CONCEPT(emplace_back, emplace_back) +SIMDJSON_IMPL_CONCEPT(emplace, emplace) +SIMDJSON_IMPL_CONCEPT(push_back, push_back) +SIMDJSON_IMPL_CONCEPT(add, add) +SIMDJSON_IMPL_CONCEPT(push, push) +SIMDJSON_IMPL_CONCEPT(append, append) +SIMDJSON_IMPL_CONCEPT(insert, insert) +SIMDJSON_IMPL_CONCEPT(op_append, operator+=) + +#undef SIMDJSON_IMPL_CONCEPT +} // namespace details + + +template +concept string_view_like = std::is_convertible_v && + !std::is_convertible_v; + +template +concept constructible_from_string_view = std::is_constructible_v + && !std::is_same_v + && std::is_default_constructible_v; + +template +concept string_view_keyed_map = string_view_like + && requires(std::remove_cvref_t& m, typename M::key_type sv, typename M::mapped_type v) { + { m.emplace(sv, v) } -> std::same_as>; +}; + +/// Check if T is a container that we can append to, including: +/// std::vector, std::deque, std::list, std::string, ... +template +concept appendable_containers = + (details::supports_emplace_back || details::supports_emplace || + details::supports_push_back || details::supports_push || + details::supports_add || details::supports_append || + details::supports_insert) && !string_view_keyed_map; + +/// Insert into the container however possible +template +constexpr decltype(auto) emplace_one(T &vec, Args &&...args) { + if constexpr (details::supports_emplace_back) { + return vec.emplace_back(std::forward(args)...); + } else if constexpr (details::supports_emplace) { + return vec.emplace(std::forward(args)...); + } else if constexpr (details::supports_push_back) { + return vec.push_back(std::forward(args)...); + } else if constexpr (details::supports_push) { + return vec.push(std::forward(args)...); + } else if constexpr (details::supports_add) { + return vec.add(std::forward(args)...); + } else if constexpr (details::supports_append) { + return vec.append(std::forward(args)...); + } else if constexpr (details::supports_insert) { + return vec.insert(std::forward(args)...); + } else if constexpr (details::supports_op_append && sizeof...(Args) == 1) { + return vec.operator+=(std::forward(args)...); + } else { + static_assert(!sizeof(T *), + "We don't know how to add things to this container"); + } +} + +/// This checks if the container will return a reference to the newly added +/// element after an insert which for example `std::vector::emplace_back` does +/// since C++17; this will allow some optimizations. +template +concept returns_reference = appendable_containers && requires { + typename std::remove_cvref_t::reference; + requires requires(typename std::remove_cvref_t::value_type &&val, T obj) { + { + emplace_one(obj, std::move(val)) + } -> std::same_as::reference>; + }; +}; + +template +concept smart_pointer = requires(std::remove_cvref_t ptr) { + // Check if T has a member type named element_type + typename std::remove_cvref_t::element_type; + + // Check if T has a get() member function + { + ptr.get() + } -> std::same_as::element_type *>; + + // Check if T can be dereferenced + { *ptr } -> std::same_as::element_type &>; +}; + +template +concept optional_type = requires(std::remove_cvref_t obj) { + typename std::remove_cvref_t::value_type; + { obj.value() } -> std::same_as::value_type&>; + requires requires(typename std::remove_cvref_t::value_type &&val) { + obj.emplace(std::move(val)); + obj = std::move(val); + { + obj.value_or(val) + } -> std::convertible_to::value_type>; + }; + { static_cast(obj) } -> std::same_as; // convertible to bool +}; + + + +} // namespace concepts +} // namespace simdjson +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +#endif // SIMDJSON_CONCEPTS_H +/* end file simdjson/concepts.h */ /** * @brief The top level simdjson namespace, containing everything the library provides. @@ -4328,6 +4551,11 @@ extern SIMDJSON_DLLIMPORTEXPORT const uint32_t digit_to_val32[886]; #include namespace simdjson { + +inline bool is_fatal(error_code error) noexcept { + return error == TAPE_ERROR || error == INCOMPLETE_ARRAY_OR_OBJECT; +} + namespace internal { // We store the error code so we can validate the error message is associated with the right code struct error_code_info { @@ -4449,6 +4677,23 @@ simdjson_warn_unused simdjson_inline error_code simdjson_result::get(T &value return std::forward>(*this).get(value); } +template +simdjson_warn_unused simdjson_inline error_code +simdjson_result::get(std::string &value) && noexcept +#if SIMDJSON_SUPPORTS_DESERIALIZATION +requires (!std::is_same_v) +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +{ + // SFINAE : n'active que pour T = std::string_view + static_assert(std::is_same::value, "simdjson_result::get(std::string&) n'est disponible que pour T = std::string_view"); + std::string_view v; + error_code error = std::forward>(*this).get(v); + if (!error) { + value.assign(v.data(), v.size()); + } + return error; +} + template simdjson_inline error_code simdjson_result::error() const noexcept { return internal::simdjson_result_base::error(); @@ -4513,7 +4758,7 @@ namespace internal { { SUCCESS, "SUCCESS: No error" }, { CAPACITY, "CAPACITY: This parser can't support a document that big" }, { MEMALLOC, "MEMALLOC: Error allocating memory, we're most likely out of memory" }, - { TAPE_ERROR, "TAPE_ERROR: The JSON document has an improper structure: missing or superfluous commas, braces, missing keys, etc." }, + { TAPE_ERROR, "TAPE_ERROR: The JSON document has an improper structure: missing or superfluous commas, braces, missing keys, etc. This is a fatal and unrecoverable error." }, { DEPTH_ERROR, "DEPTH_ERROR: The JSON document was too deep (too many nested objects and arrays)" }, { STRING_ERROR, "STRING_ERROR: Problem while parsing a string" }, { T_ATOM_ERROR, "T_ATOM_ERROR: Problem while parsing an atom starting with the letter 't'" }, @@ -4538,7 +4783,7 @@ namespace internal { { PARSER_IN_USE, "PARSER_IN_USE: Cannot parse a new document while a document is still in use." }, { OUT_OF_ORDER_ITERATION, "OUT_OF_ORDER_ITERATION: Objects and arrays can only be iterated when they are first encountered." }, { INSUFFICIENT_PADDING, "INSUFFICIENT_PADDING: simdjson requires the input JSON string to have at least SIMDJSON_PADDING extra bytes allocated, beyond the string's length. Consider using the simdjson::padded_string class if needed." }, - { INCOMPLETE_ARRAY_OR_OBJECT, "INCOMPLETE_ARRAY_OR_OBJECT: JSON document ended early in the middle of an object or array." }, + { INCOMPLETE_ARRAY_OR_OBJECT, "INCOMPLETE_ARRAY_OR_OBJECT: JSON document ended early in the middle of an object or array. This is a fatal and unrecoverable error." }, { SCALAR_DOCUMENT_AS_VALUE, "SCALAR_DOCUMENT_AS_VALUE: A JSON document made of a scalar (number, Boolean, null or string) is treated as a value. Use get_bool(), get_double(), etc. on the document instead. "}, { OUT_OF_BOUNDS, "OUT_OF_BOUNDS: Attempt to access location outside of document."}, { TRAILING_CONTENT, "TRAILING_CONTENT: Unexpected trailing content in the JSON input."} @@ -6447,7 +6692,6 @@ extern SIMDJSON_DLLIMPORTEXPORT const uint64_t thintable_epi8[256]; #endif // SIMDJSON_INTERNAL_SIMDPRUNE_TABLES_H /* end file simdjson/internal/simdprune_tables.h */ - #endif // SIMDJSON_GENERIC_DEPENDENCIES_H /* end file simdjson/generic/dependencies.h */ /* including generic/dependencies.h: #include */ @@ -6605,7 +6849,7 @@ class document { * The memory allocation is strict: you * can you use this function to increase * or lower the amount of allocated memory. - * Passsing zero clears the memory. + * Passing zero clears the memory. */ error_code allocate(size_t len) noexcept; /** @private Capacity in bytes, in terms @@ -7623,7 +7867,7 @@ SIMDJSON_NO_SANITIZE_UNDEFINED // See issue https://github.com/simdjson/simdjson/issues/1965 SIMDJSON_NO_SANITIZE_MEMORY simdjson_inline int trailing_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long ret; // Search the mask data from least significant bit (LSB) // to the most significant bit (MSB) for a set bit (1). @@ -7639,9 +7883,15 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { return input_num & (input_num-1); } +// We sometimes call leading_zeroes on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +// Applies only when SIMDJSON_PREFER_REVERSE_BITS is defined and true. +// (See below.) +SIMDJSON_NO_SANITIZE_UNDEFINED /* result might be undefined when input_num is zero */ simdjson_inline int leading_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long leading_zero = 0; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). @@ -7694,7 +7944,7 @@ simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) #endif simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO *result = value1 + value2; return *result < value1; #else @@ -7811,7 +8061,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace arm64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H /* end file simdjson/arm64/numberparsing_defs.h */ @@ -7831,7 +8087,7 @@ namespace arm64 { namespace { namespace simd { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO namespace { // Start of private section with Visual Studio workaround @@ -7940,7 +8196,7 @@ namespace { // We return uint32_t instead of uint16_t because that seems to be more efficient for most // purposes (cutting it down to uint16_t costs performance in some compilers). simdjson_inline uint32_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); #else @@ -7971,7 +8227,7 @@ namespace { // Splat constructor simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 @@ -8065,7 +8321,7 @@ namespace { uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]}; uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -8095,7 +8351,7 @@ namespace { uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]); uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -8147,7 +8403,7 @@ namespace { // Array constructor simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 @@ -8268,7 +8524,7 @@ namespace { } simdjson_inline uint64_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t( 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 @@ -8991,7 +9247,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -9428,7 +9684,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -9502,7 +9757,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -9963,6 +10227,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -10379,7 +10649,7 @@ SIMDJSON_NO_SANITIZE_UNDEFINED // See issue https://github.com/simdjson/simdjson/issues/1965 SIMDJSON_NO_SANITIZE_MEMORY simdjson_inline int trailing_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long ret; // Search the mask data from least significant bit (LSB) // to the most significant bit (MSB) for a set bit (1). @@ -10395,9 +10665,15 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { return input_num & (input_num-1); } +// We sometimes call leading_zeroes on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +// Applies only when SIMDJSON_PREFER_REVERSE_BITS is defined and true. +// (See below.) +SIMDJSON_NO_SANITIZE_UNDEFINED /* result might be undefined when input_num is zero */ simdjson_inline int leading_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long leading_zero = 0; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). @@ -10450,7 +10726,7 @@ simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) #endif simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO *result = value1 + value2; return *result < value1; #else @@ -10567,7 +10843,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace arm64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H /* end file simdjson/arm64/numberparsing_defs.h */ @@ -10587,7 +10869,7 @@ namespace arm64 { namespace { namespace simd { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO namespace { // Start of private section with Visual Studio workaround @@ -10696,7 +10978,7 @@ namespace { // We return uint32_t instead of uint16_t because that seems to be more efficient for most // purposes (cutting it down to uint16_t costs performance in some compilers). simdjson_inline uint32_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); #else @@ -10727,7 +11009,7 @@ namespace { // Splat constructor simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 @@ -10821,7 +11103,7 @@ namespace { uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]}; uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -10851,7 +11133,7 @@ namespace { uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]); uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -10903,7 +11185,7 @@ namespace { // Array constructor simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 @@ -11024,7 +11306,7 @@ namespace { } simdjson_inline uint64_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t( 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 @@ -13977,6 +14259,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept { return arm64::stringparsing::parse_string(src, dst, allow_replacement); } @@ -14115,8 +14398,14 @@ static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient paddi /* end file simdjson/haswell/intrinsics.h */ #if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL +// We enable bmi2 only if LLVM/clang is used, because GCC may not +// make good use of it. See https://github.com/simdjson/simdjson/pull/2243 +#if defined(__clang__) +SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt") +#else SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") #endif +#endif /* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */ /* begin file simdjson/haswell/bitmanipulation.h */ @@ -15333,7 +15622,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -15770,7 +16059,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -15844,7 +16132,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -16305,6 +16602,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -16748,8 +17051,14 @@ static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient paddi /* end file simdjson/haswell/intrinsics.h */ #if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL +// We enable bmi2 only if LLVM/clang is used, because GCC may not +// make good use of it. See https://github.com/simdjson/simdjson/pull/2243 +#if defined(__clang__) +SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt") +#else SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") #endif +#endif /* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */ /* begin file simdjson/haswell/bitmanipulation.h */ @@ -20193,6 +20502,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool replacement_char) const noexcept { return haswell::stringparsing::parse_string(src, dst, replacement_char); } @@ -20595,14 +20905,18 @@ namespace simd { // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset). // Passing a 0 value for mask would be equivalent to writing out every byte to output. - // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes + // Only the first 64 - count_ones(mask) bytes of the result are significant but 64 bytes // get written. // Design consideration: it seems like a function with the // signature simd8 compress(uint32_t mask) would be // sensible, but the AVX ISA makes this kind of approach difficult. template simdjson_inline void compress(uint64_t mask, L * output) const { - _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + // we deliberately avoid _mm512_mask_compressstoreu_epi8 for portability + // (AMD Zen4 has terrible performance with it, it is effectively broken) + // _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + __m512i compressed = _mm512_maskz_compress_epi8(~mask, *this); + _mm512_storeu_si512(output, compressed); // could use a mask } template @@ -21547,7 +21861,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -21984,7 +22298,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -22058,7 +22371,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -22519,6 +22841,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -23226,14 +23554,18 @@ namespace simd { // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset). // Passing a 0 value for mask would be equivalent to writing out every byte to output. - // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes + // Only the first 64 - count_ones(mask) bytes of the result are significant but 64 bytes // get written. // Design consideration: it seems like a function with the // signature simd8 compress(uint32_t mask) would be // sensible, but the AVX ISA makes this kind of approach difficult. template simdjson_inline void compress(uint64_t mask, L * output) const { - _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + // we deliberately avoid _mm512_mask_compressstoreu_epi8 for portability + // (AMD Zen4 has terrible performance with it, it is effectively broken) + // _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + __m512i compressed = _mm512_maskz_compress_epi8(~mask, *this); + _mm512_storeu_si512(output, compressed); // could use a mask } template @@ -26448,6 +26780,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool replacement_char) const noexcept { return icelake::stringparsing::parse_string(src, dst, replacement_char); } @@ -26750,7 +27083,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace ppc64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H /* end file simdjson/ppc64/numberparsing_defs.h */ @@ -27917,7 +28256,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -28354,7 +28693,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -28428,7 +28766,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -28889,6 +29236,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -29494,7 +29847,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace ppc64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H /* end file simdjson/ppc64/numberparsing_defs.h */ @@ -32861,6 +33220,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool replacement_char) const noexcept { return ppc64::stringparsing::parse_string(src, dst, replacement_char); } @@ -34653,7 +35013,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -35090,7 +35450,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -35164,7 +35523,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -35625,6 +35993,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -39950,6 +40324,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool replacement_char) const noexcept { return westmere::stringparsing::parse_string(src, dst, replacement_char); } @@ -40176,7 +40551,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lsx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LSX_NUMBERPARSING_DEFS_H /* end file simdjson/lsx/numberparsing_defs.h */ @@ -41213,7 +41594,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -41650,7 +42031,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -41724,7 +42104,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -42185,6 +42574,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -42705,7 +43100,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lsx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LSX_NUMBERPARSING_DEFS_H /* end file simdjson/lsx/numberparsing_defs.h */ @@ -45936,6 +46337,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept { return lsx::stringparsing::parse_string(src, dst, allow_replacement); } @@ -46159,7 +46561,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lasx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LASX_NUMBERPARSING_DEFS_H /* end file simdjson/lasx/numberparsing_defs.h */ @@ -47212,7 +47620,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -47649,7 +48057,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -47723,7 +48130,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -48184,6 +48600,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -48704,7 +49126,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lasx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LASX_NUMBERPARSING_DEFS_H /* end file simdjson/lasx/numberparsing_defs.h */ @@ -51947,6 +52375,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool allow_replacement) const noexcept { return lasx::stringparsing::parse_string(src, dst, allow_replacement); } @@ -52188,7 +52617,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace fallback } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H /* end file simdjson/fallback/numberparsing_defs.h */ @@ -52810,7 +53245,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -53247,7 +53682,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -53321,7 +53755,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -53782,6 +54225,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -54322,7 +54771,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace fallback } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H /* end file simdjson/fallback/numberparsing_defs.h */ @@ -55909,6 +56364,7 @@ simdjson_warn_unused error_code dom_parser_implementation::stage2_next(dom::docu return stage2::tape_builder::parse_document(*this, _doc); } +SIMDJSON_NO_SANITIZE_MEMORY simdjson_warn_unused uint8_t *dom_parser_implementation::parse_string(const uint8_t *src, uint8_t *dst, bool replacement_char) const noexcept { return fallback::stringparsing::parse_string(src, dst, replacement_char); } diff --git a/3rdparty/simdjson/simdjson.h b/3rdparty/simdjson/simdjson.h index f21cd9381eef..8f52a4331d59 100644 --- a/3rdparty/simdjson/simdjson.h +++ b/3rdparty/simdjson/simdjson.h @@ -1,4 +1,4 @@ -/* auto-generated on 2024-08-26 09:37:03 -0400. Do not edit! */ +/* auto-generated on 2025-06-04 00:22:10 -0400. Do not edit! */ /* including simdjson.h: */ /* begin file simdjson.h */ #ifndef SIMDJSON_H @@ -97,6 +97,30 @@ #endif #endif +#ifdef __has_include +#if __has_include() +#include +#endif +#endif + +#if defined(__apple_build_version__) +#if __apple_build_version__ < 14000000 +#define SIMDJSON_CONCEPT_DISABLED 1 // apple-clang/13 doesn't support std::convertible_to +#endif +#endif + + +#if defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) +#if __cpp_concepts >= 201907L +#include +#define SIMDJSON_SUPPORTS_DESERIALIZATION 1 +#else +#define SIMDJSON_SUPPORTS_DESERIALIZATION 0 +#endif +#else // defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) +#define SIMDJSON_SUPPORTS_DESERIALIZATION 0 +#endif // defined(__cpp_concepts) && !defined(SIMDJSON_CONCEPT_DISABLED) + #endif // SIMDJSON_COMPILER_CHECK_H /* end file simdjson/compiler_check.h */ /* including simdjson/portability.h: #include "simdjson/portability.h" */ @@ -109,11 +133,15 @@ #include #include #include +#include #ifndef _WIN32 // strcasecmp, strncasecmp #include #endif +static_assert(CHAR_BIT == 8, "simdjson requires 8-bit bytes"); + + // We are using size_t without namespace std:: throughout the project using std::size_t; @@ -147,6 +175,7 @@ using std::size_t; #elif defined(__loongarch_lp64) #define SIMDJSON_IS_LOONGARCH64 1 #elif defined(__PPC64__) || defined(_M_PPC64) +#define SIMDJSON_IS_PPC64 1 #if defined(__ALTIVEC__) #define SIMDJSON_IS_PPC64_VMX 1 #endif // defined(__ALTIVEC__) @@ -304,6 +333,45 @@ using std::size_t; #endif + + +#if defined __BYTE_ORDER__ && defined __ORDER_BIG_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN (__BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) +#elif defined _WIN32 +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#if defined(__APPLE__) || defined(__FreeBSD__) +#include +#elif defined(sun) || defined(__sun) +#include +#elif defined(__MVS__) +#include +#else +#ifdef __has_include +#if __has_include() +#include +#endif //__has_include() +#endif //__has_include +#endif +# +#ifndef __BYTE_ORDER__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#ifndef __ORDER_LITTLE_ENDIAN__ +// safe choice +#define SIMDJSON_IS_BIG_ENDIAN 0 +#endif +# +#if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +#define SIMDJSON_IS_BIG_ENDIAN 0 +#else +#define SIMDJSON_IS_BIG_ENDIAN 1 +#endif +#endif + + #endif // SIMDJSON_PORTABILITY_H /* end file simdjson/portability.h */ @@ -325,7 +393,7 @@ double from_chars(const char *first, const char* end) noexcept; } #ifndef SIMDJSON_EXCEPTIONS -#if __cpp_exceptions +#if defined(__cpp_exceptions) || defined(_CPPUNWIND) #define SIMDJSON_EXCEPTIONS 1 #else #define SIMDJSON_EXCEPTIONS 0 @@ -528,12 +596,14 @@ double from_chars(const char *first, const char* end) noexcept; // even if we do not have C++17 support. #ifdef __cpp_lib_string_view #define SIMDJSON_HAS_STRING_VIEW +#include #endif // Some systems have string_view even if we do not have C++17 support, // and even if __cpp_lib_string_view is undefined, it is the case // with Apple clang version 11. // We must handle it. *This is important.* +#ifndef _MSC_VER #ifndef SIMDJSON_HAS_STRING_VIEW #if defined __has_include // do not combine the next #if with the previous one (unsafe) @@ -549,6 +619,7 @@ double from_chars(const char *first, const char* end) noexcept; #endif // __has_include () #endif // defined __has_include #endif // def SIMDJSON_HAS_STRING_VIEW +#endif // def _MSC_VER // end of complicated but important routine to try to detect string_view. // @@ -569,7 +640,6 @@ SIMDJSON_PUSH_DISABLE_ALL_WARNINGS // Distributed under the Boost Software License, Version 1.0. // (See accompanying file LICENSE.txt or copy at http://www.boost.org/LICENSE_1_0.txt) -#pragma once #ifndef NONSTD_SV_LITE_H_INCLUDED #define NONSTD_SV_LITE_H_INCLUDED @@ -729,22 +799,22 @@ inline namespace literals { inline namespace string_view_literals { -constexpr std::string_view operator "" _sv( const char* str, size_t len ) noexcept // (1) +constexpr std::string_view operator ""_sv( const char* str, size_t len ) noexcept // (1) { return std::string_view{ str, len }; } -constexpr std::u16string_view operator "" _sv( const char16_t* str, size_t len ) noexcept // (2) +constexpr std::u16string_view operator ""_sv( const char16_t* str, size_t len ) noexcept // (2) { return std::u16string_view{ str, len }; } -constexpr std::u32string_view operator "" _sv( const char32_t* str, size_t len ) noexcept // (3) +constexpr std::u32string_view operator ""_sv( const char32_t* str, size_t len ) noexcept // (3) { return std::u32string_view{ str, len }; } -constexpr std::wstring_view operator "" _sv( const wchar_t* str, size_t len ) noexcept // (4) +constexpr std::wstring_view operator ""_sv( const wchar_t* str, size_t len ) noexcept // (4) { return std::wstring_view{ str, len }; } @@ -2075,22 +2145,22 @@ nssv_inline_ns namespace string_view_literals { #if nssv_CONFIG_STD_SV_OPERATOR && nssv_HAVE_STD_DEFINED_LITERALS -nssv_constexpr nonstd::sv_lite::string_view operator "" sv( const char* str, size_t len ) nssv_noexcept // (1) +nssv_constexpr nonstd::sv_lite::string_view operator ""sv( const char* str, size_t len ) nssv_noexcept // (1) { return nonstd::sv_lite::string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u16string_view operator "" sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +nssv_constexpr nonstd::sv_lite::u16string_view operator ""sv( const char16_t* str, size_t len ) nssv_noexcept // (2) { return nonstd::sv_lite::u16string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u32string_view operator "" sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +nssv_constexpr nonstd::sv_lite::u32string_view operator ""sv( const char32_t* str, size_t len ) nssv_noexcept // (3) { return nonstd::sv_lite::u32string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +nssv_constexpr nonstd::sv_lite::wstring_view operator ""sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) { return nonstd::sv_lite::wstring_view{ str, len }; } @@ -2099,22 +2169,22 @@ nssv_constexpr nonstd::sv_lite::wstring_view operator "" sv( const wchar_t* str, #if nssv_CONFIG_USR_SV_OPERATOR -nssv_constexpr nonstd::sv_lite::string_view operator "" _sv( const char* str, size_t len ) nssv_noexcept // (1) +nssv_constexpr nonstd::sv_lite::string_view operator ""_sv( const char* str, size_t len ) nssv_noexcept // (1) { return nonstd::sv_lite::string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u16string_view operator "" _sv( const char16_t* str, size_t len ) nssv_noexcept // (2) +nssv_constexpr nonstd::sv_lite::u16string_view operator ""_sv( const char16_t* str, size_t len ) nssv_noexcept // (2) { return nonstd::sv_lite::u16string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::u32string_view operator "" _sv( const char32_t* str, size_t len ) nssv_noexcept // (3) +nssv_constexpr nonstd::sv_lite::u32string_view operator ""_sv( const char32_t* str, size_t len ) nssv_noexcept // (3) { return nonstd::sv_lite::u32string_view{ str, len }; } -nssv_constexpr nonstd::sv_lite::wstring_view operator "" _sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) +nssv_constexpr nonstd::sv_lite::wstring_view operator ""_sv( const wchar_t* str, size_t len ) nssv_noexcept // (4) { return nonstd::sv_lite::wstring_view{ str, len }; } @@ -2370,7 +2440,7 @@ namespace std { #define SIMDJSON_SIMDJSON_VERSION_H /** The version of simdjson being used (major.minor.revision) */ -#define SIMDJSON_VERSION "3.10.1" +#define SIMDJSON_VERSION "3.13.0" namespace simdjson { enum { @@ -2381,11 +2451,11 @@ enum { /** * The minor version (major.MINOR.revision) of simdjson being used. */ - SIMDJSON_VERSION_MINOR = 10, + SIMDJSON_VERSION_MINOR = 13, /** * The revision (major.minor.REVISION) of simdjson being used. */ - SIMDJSON_VERSION_REVISION = 1 + SIMDJSON_VERSION_REVISION = 0 }; } // namespace simdjson @@ -2427,7 +2497,7 @@ enum error_code { SUCCESS = 0, ///< No error CAPACITY, ///< This parser can't support a document that big MEMALLOC, ///< Error allocating memory, most likely out of memory - TAPE_ERROR, ///< Something went wrong, this is a generic error + TAPE_ERROR, ///< Something went wrong, this is a generic error. Fatal/unrecoverable error. DEPTH_ERROR, ///< Your document exceeds the user-specified depth limitation STRING_ERROR, ///< Problem while parsing a string T_ATOM_ERROR, ///< Problem while parsing an atom starting with the letter 't' @@ -2452,13 +2522,21 @@ enum error_code { PARSER_IN_USE, ///< parser is already in use. OUT_OF_ORDER_ITERATION, ///< tried to iterate an array or object out of order (checked when SIMDJSON_DEVELOPMENT_CHECKS=1) INSUFFICIENT_PADDING, ///< The JSON doesn't have enough padding for simdjson to safely parse it. - INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early. + INCOMPLETE_ARRAY_OR_OBJECT, ///< The document ends early. Fatal/unrecoverable error. SCALAR_DOCUMENT_AS_VALUE, ///< A scalar document is treated as a value. OUT_OF_BOUNDS, ///< Attempted to access location outside of document. TRAILING_CONTENT, ///< Unexpected trailing content in the JSON input NUM_ERROR_CODES }; +/** + * Some errors are fatal and invalidate the document. This function returns true if the + * error is fatal. It returns true for TAPE_ERROR and INCOMPLETE_ARRAY_OR_OBJECT. + * Once a fatal error is encountered, the on-demand document is no longer valid and + * processing should stop. + */ + inline bool is_fatal(error_code error) noexcept; + /** * It is the convention throughout the code that the macro SIMDJSON_DEVELOPMENT_CHECKS determines whether * we check for OUT_OF_ORDER_ITERATION. The logic behind it is that these errors only occurs when the code @@ -2493,7 +2571,7 @@ struct simdjson_error : public std::exception { */ simdjson_error(error_code error) noexcept : _error{error} { } /** The error message */ - const char *what() const noexcept { return error_message(error()); } + const char *what() const noexcept override { return error_message(error()); } /** The error code */ error_code error() const noexcept { return _error; } private: @@ -2595,6 +2673,7 @@ struct simdjson_result_base : protected std::pair { * @throw simdjson_error if there was an error. */ simdjson_inline operator T&&() && noexcept(false); + #endif // SIMDJSON_EXCEPTIONS /** @@ -2651,7 +2730,17 @@ struct simdjson_result : public internal::simdjson_result_base { * @param value The variable to assign the value to. May not be set if there is an error. */ simdjson_warn_unused simdjson_inline error_code get(T &value) && noexcept; - +// + /** + * Copy the value to a provided std::string, only enabled for std::string_view. + * + * @param value The variable to assign the value to. May not be set if there is an error. + */ + simdjson_warn_unused simdjson_inline error_code get(std::string &value) && noexcept +#if SIMDJSON_SUPPORTS_DESERIALIZATION + requires (!std::is_same_v) +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + ; /** * The error. */ @@ -2725,6 +2814,140 @@ inline const std::string error_message(int error) noexcept; #endif // SIMDJSON_ERROR_H /* end file simdjson/error.h */ /* skipped duplicate #include "simdjson/portability.h" */ +/* including simdjson/concepts.h: #include "simdjson/concepts.h" */ +/* begin file simdjson/concepts.h */ +#ifndef SIMDJSON_CONCEPTS_H +#define SIMDJSON_CONCEPTS_H +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#include +#include + +namespace simdjson { +namespace concepts { + +namespace details { +#define SIMDJSON_IMPL_CONCEPT(name, method) \ + template \ + concept supports_##name = !std::is_const_v && requires { \ + typename std::remove_cvref_t::value_type; \ + requires requires(typename std::remove_cvref_t::value_type &&val, \ + T obj) { \ + obj.method(std::move(val)); \ + requires !requires { obj = std::move(val); }; \ + }; \ + }; + +SIMDJSON_IMPL_CONCEPT(emplace_back, emplace_back) +SIMDJSON_IMPL_CONCEPT(emplace, emplace) +SIMDJSON_IMPL_CONCEPT(push_back, push_back) +SIMDJSON_IMPL_CONCEPT(add, add) +SIMDJSON_IMPL_CONCEPT(push, push) +SIMDJSON_IMPL_CONCEPT(append, append) +SIMDJSON_IMPL_CONCEPT(insert, insert) +SIMDJSON_IMPL_CONCEPT(op_append, operator+=) + +#undef SIMDJSON_IMPL_CONCEPT +} // namespace details + + +template +concept string_view_like = std::is_convertible_v && + !std::is_convertible_v; + +template +concept constructible_from_string_view = std::is_constructible_v + && !std::is_same_v + && std::is_default_constructible_v; + +template +concept string_view_keyed_map = string_view_like + && requires(std::remove_cvref_t& m, typename M::key_type sv, typename M::mapped_type v) { + { m.emplace(sv, v) } -> std::same_as>; +}; + +/// Check if T is a container that we can append to, including: +/// std::vector, std::deque, std::list, std::string, ... +template +concept appendable_containers = + (details::supports_emplace_back || details::supports_emplace || + details::supports_push_back || details::supports_push || + details::supports_add || details::supports_append || + details::supports_insert) && !string_view_keyed_map; + +/// Insert into the container however possible +template +constexpr decltype(auto) emplace_one(T &vec, Args &&...args) { + if constexpr (details::supports_emplace_back) { + return vec.emplace_back(std::forward(args)...); + } else if constexpr (details::supports_emplace) { + return vec.emplace(std::forward(args)...); + } else if constexpr (details::supports_push_back) { + return vec.push_back(std::forward(args)...); + } else if constexpr (details::supports_push) { + return vec.push(std::forward(args)...); + } else if constexpr (details::supports_add) { + return vec.add(std::forward(args)...); + } else if constexpr (details::supports_append) { + return vec.append(std::forward(args)...); + } else if constexpr (details::supports_insert) { + return vec.insert(std::forward(args)...); + } else if constexpr (details::supports_op_append && sizeof...(Args) == 1) { + return vec.operator+=(std::forward(args)...); + } else { + static_assert(!sizeof(T *), + "We don't know how to add things to this container"); + } +} + +/// This checks if the container will return a reference to the newly added +/// element after an insert which for example `std::vector::emplace_back` does +/// since C++17; this will allow some optimizations. +template +concept returns_reference = appendable_containers && requires { + typename std::remove_cvref_t::reference; + requires requires(typename std::remove_cvref_t::value_type &&val, T obj) { + { + emplace_one(obj, std::move(val)) + } -> std::same_as::reference>; + }; +}; + +template +concept smart_pointer = requires(std::remove_cvref_t ptr) { + // Check if T has a member type named element_type + typename std::remove_cvref_t::element_type; + + // Check if T has a get() member function + { + ptr.get() + } -> std::same_as::element_type *>; + + // Check if T can be dereferenced + { *ptr } -> std::same_as::element_type &>; +}; + +template +concept optional_type = requires(std::remove_cvref_t obj) { + typename std::remove_cvref_t::value_type; + { obj.value() } -> std::same_as::value_type&>; + requires requires(typename std::remove_cvref_t::value_type &&val) { + obj.emplace(std::move(val)); + obj = std::move(val); + { + obj.value_or(val) + } -> std::convertible_to::value_type>; + }; + { static_cast(obj) } -> std::same_as; // convertible to bool +}; + + + +} // namespace concepts +} // namespace simdjson +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +#endif // SIMDJSON_CONCEPTS_H +/* end file simdjson/concepts.h */ /** * @brief The top level simdjson namespace, containing everything the library provides. @@ -2787,6 +3010,11 @@ enum class tape_type; #include namespace simdjson { + +inline bool is_fatal(error_code error) noexcept { + return error == TAPE_ERROR || error == INCOMPLETE_ARRAY_OR_OBJECT; +} + namespace internal { // We store the error code so we can validate the error message is associated with the right code struct error_code_info { @@ -2908,6 +3136,23 @@ simdjson_warn_unused simdjson_inline error_code simdjson_result::get(T &value return std::forward>(*this).get(value); } +template +simdjson_warn_unused simdjson_inline error_code +simdjson_result::get(std::string &value) && noexcept +#if SIMDJSON_SUPPORTS_DESERIALIZATION +requires (!std::is_same_v) +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +{ + // SFINAE : n'active que pour T = std::string_view + static_assert(std::is_same::value, "simdjson_result::get(std::string&) n'est disponible que pour T = std::string_view"); + std::string_view v; + error_code error = std::forward>(*this).get(v); + if (!error) { + value.assign(v.data(), v.size()); + } + return error; +} + template simdjson_inline error_code simdjson_result::error() const noexcept { return internal::simdjson_result_base::error(); @@ -3655,9 +3900,9 @@ inline std::ostream& operator<<(std::ostream& out, simdjson_result &s) noexcept(false); #endif +/** + * Create a padded_string_view from a string. The string will be padded with SIMDJSON_PADDING + * space characters. The resulting padded_string_view will have a length equal to the original + * string. + * + * @param s The string. + * @return The padded string. + */ +inline padded_string_view pad(std::string& s) noexcept; } // namespace simdjson #endif // SIMDJSON_PADDED_STRING_VIEW_H @@ -3859,6 +4113,11 @@ inline bool padded_string_view::remove_utf8_bom() noexcept { inline std::ostream& operator<<(std::ostream& out, simdjson_result &s) noexcept(false) { return out << s.value(); } #endif +inline padded_string_view pad(std::string& s) noexcept { + const auto len = s.size(); + s.append(SIMDJSON_PADDING, ' '); + return padded_string_view(s.data(), len, s.size()); +} } // namespace simdjson @@ -3911,6 +4170,9 @@ inline padded_string::padded_string(const char *data, size_t length) noexcept if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, data, length); } + if (data_ptr == nullptr) { + viable_size = 0; + } } #ifdef __cpp_char8_t inline padded_string::padded_string(const char8_t *data, size_t length) noexcept @@ -3918,12 +4180,17 @@ inline padded_string::padded_string(const char8_t *data, size_t length) noexcept if ((data != nullptr) && (data_ptr != nullptr)) { std::memcpy(data_ptr, reinterpret_cast(data), length); } + if (data_ptr == nullptr) { + viable_size = 0; + } } #endif // note: do not pass std::string arguments by value inline padded_string::padded_string(const std::string & str_ ) noexcept : viable_size(str_.size()), data_ptr(internal::allocate_padded_buffer(str_.size())) { - if (data_ptr != nullptr) { + if (data_ptr == nullptr) { + viable_size = 0; + } else { std::memcpy(data_ptr, str_.data(), str_.size()); } } @@ -4037,11 +4304,11 @@ inline simdjson_result padded_string::load(std::string_view filen } // namespace simdjson -inline simdjson::padded_string operator "" _padded(const char *str, size_t len) { +inline simdjson::padded_string operator ""_padded(const char *str, size_t len) { return simdjson::padded_string(str, len); } #ifdef __cpp_char8_t -inline simdjson::padded_string operator "" _padded(const char8_t *str, size_t len) { +inline simdjson::padded_string operator ""_padded(const char8_t *str, size_t len) { return simdjson::padded_string(reinterpret_cast(str), len); } #endif @@ -4275,6 +4542,21 @@ class array { */ inline simdjson_result at_pointer(std::string_view json_pointer) const noexcept; + /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result at_path(std::string_view json_path) const noexcept; + /** * Get the value at the given index. This function has linear-time complexity and * is equivalent to the following: @@ -4319,6 +4601,7 @@ struct simdjson_result : public internal::simdjson_result_base at_pointer(std::string_view json_pointer) const noexcept; + inline simdjson_result at_path(std::string_view json_path) const noexcept; inline simdjson_result at(size_t index) const noexcept; #if SIMDJSON_EXCEPTIONS @@ -4435,7 +4718,7 @@ class document { * The memory allocation is strict: you * can you use this function to increase * or lower the amount of allocated memory. - * Passsing zero clears the memory. + * Passing zero clears the memory. */ error_code allocate(size_t len) noexcept; /** @private Capacity in bytes, in terms @@ -4654,6 +4937,22 @@ class parser { * simdjson::dom::parser parser; * simdjson::dom::element element = parser.parse(padded_json_copy.get(), json_len, false); * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's parse function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * element doc = parser.parse(simdjson::pad(json)); + * * ### Parser Capacity * * If the parser's current capacity is less than len, it will allocate enough capacity @@ -4776,7 +5075,7 @@ class parser { * arrays or objects) MUST be separated with whitespace. * * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse. - * Setting batch_size to excessively large or excesively small values may impact negatively the + * Setting batch_size to excessively large or excessively small values may impact negatively the * performance. * * ### Error Handling @@ -4870,7 +5169,7 @@ class parser { * arrays or objects) MUST be separated with whitespace. * * The documents must not exceed batch_size bytes (by default 1MB) or they will fail to parse. - * Setting batch_size to excessively large or excesively small values may impact negatively the + * Setting batch_size to excessively large or excessively small values may impact negatively the * performance. * * ### Error Handling @@ -5001,9 +5300,14 @@ class parser { /** * The parser instance can use threads when they are available to speed up some * operations. It is enabled by default. Changing this attribute will change the - * behavior of the parser for future operations. + * behavior of the parser for future operations. Set to true by default. */ bool threaded{true}; +#else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif /** @private Use the new DOM API instead */ class Iterator; @@ -5796,6 +6100,8 @@ class element { * - INCORRECT_TYPE if this is not an object */ inline simdjson_result operator[](const char *key) const noexcept; + simdjson_result operator[](int) const noexcept = delete; + /** * Get the value associated with the given JSON pointer. We use the RFC 6901 @@ -5821,6 +6127,21 @@ class element { */ inline simdjson_result at_pointer(const std::string_view json_pointer) const noexcept; + /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result at_path(std::string_view json_path) const noexcept; + #ifndef SIMDJSON_DISABLE_DEPRECATED_API /** * @@ -5949,7 +6270,9 @@ struct simdjson_result : public internal::simdjson_result_base operator[](std::string_view key) const noexcept; simdjson_inline simdjson_result operator[](const char *key) const noexcept; + simdjson_result operator[](int) const noexcept = delete; simdjson_inline simdjson_result at_pointer(const std::string_view json_pointer) const noexcept; + simdjson_inline simdjson_result at_path(const std::string_view json_path) const noexcept; [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] simdjson_inline simdjson_result at(const std::string_view json_pointer) const noexcept; simdjson_inline simdjson_result at(size_t index) const noexcept; @@ -6124,6 +6447,7 @@ class object { * - INCORRECT_TYPE if this is not an object */ inline simdjson_result operator[](const char *key) const noexcept; + simdjson_result operator[](int) const noexcept = delete; /** * Get the value associated with the given JSON pointer. We use the RFC 6901 @@ -6150,6 +6474,21 @@ class object { */ inline simdjson_result at_pointer(std::string_view json_pointer) const noexcept; + /** + * Get the value associated with the given JSONPath expression. We only support + * JSONPath queries that trivially convertible to JSON Pointer queries: key + * names and array indices. + * + * https://datatracker.ietf.org/doc/html/draft-normington-jsonpath-00 + * + * @return The value associated with the given JSONPath expression, or: + * - INVALID_JSON_POINTER if the JSONPath to JSON Pointer conversion fails + * - NO_SUCH_FIELD if a field does not exist in an object + * - INDEX_OUT_OF_BOUNDS if an array index is larger than an array length + * - INCORRECT_TYPE if a non-integer is used to access an array + */ + inline simdjson_result at_path(std::string_view json_path) const noexcept; + /** * Get the value associated with the given key. * @@ -6222,7 +6561,9 @@ struct simdjson_result : public internal::simdjson_result_base operator[](std::string_view key) const noexcept; inline simdjson_result operator[](const char *key) const noexcept; + simdjson_result operator[](int) const noexcept = delete; inline simdjson_result at_pointer(std::string_view json_pointer) const noexcept; + inline simdjson_result at_path(std::string_view json_path) const noexcept; inline simdjson_result at_key(std::string_view key) const noexcept; inline simdjson_result at_key_case_insensitive(std::string_view key) const noexcept; @@ -6529,6 +6870,73 @@ std::string prettify(simdjson_result x) { /* skipped duplicate #include "simdjson/dom/array.h" */ /* skipped duplicate #include "simdjson/dom/element.h" */ /* skipped duplicate #include "simdjson/error-inl.h" */ +/* including simdjson/jsonpathutil.h: #include "simdjson/jsonpathutil.h" */ +/* begin file simdjson/jsonpathutil.h */ +#ifndef SIMDJSON_JSONPATHUTIL_H +#define SIMDJSON_JSONPATHUTIL_H + +#include +/* skipped duplicate #include "simdjson/common_defs.h" */ + +namespace simdjson { +/** + * Converts JSONPath to JSON Pointer. + * @param json_path The JSONPath string to be converted. + * @return A string containing the equivalent JSON Pointer. + */ +inline std::string json_path_to_pointer_conversion(std::string_view json_path) { + size_t i = 0; + + // if JSONPath starts with $, skip it + if (!json_path.empty() && json_path.front() == '$') { + i = 1; + } + if (json_path.empty() || (json_path[i] != '.' && + json_path[i] != '[')) { + return "-1"; // This is just a sentinel value, the caller should check for this and return an error. + } + + std::string result; + // Reserve space to reduce allocations, adjusting for potential increases due + // to escaping. + result.reserve(json_path.size() * 2); + + while (i < json_path.length()) { + if (json_path[i] == '.') { + result += '/'; + } else if (json_path[i] == '[') { + result += '/'; + ++i; // Move past the '[' + while (i < json_path.length() && json_path[i] != ']') { + if (json_path[i] == '~') { + result += "~0"; + } else if (json_path[i] == '/') { + result += "~1"; + } else { + result += json_path[i]; + } + ++i; + } + if (i == json_path.length() || json_path[i] != ']') { + return "-1"; // Using sentinel value that will be handled as an error by the caller. + } + } else { + if (json_path[i] == '~') { + result += "~0"; + } else if (json_path[i] == '/') { + result += "~1"; + } else { + result += json_path[i]; + } + } + ++i; + } + + return result; +} +} // namespace simdjson +#endif // SIMDJSON_JSONPATHUTIL_H +/* end file simdjson/jsonpathutil.h */ /* including simdjson/internal/tape_ref-inl.h: #include "simdjson/internal/tape_ref-inl.h" */ /* begin file simdjson/internal/tape_ref-inl.h */ #ifndef SIMDJSON_TAPE_REF_INL_H @@ -6716,6 +7124,13 @@ inline simdjson_result simdjson_result::at_pointer(std if (error()) { return error(); } return first.at_pointer(json_pointer); } + + inline simdjson_result simdjson_result::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); + } + inline simdjson_result simdjson_result::at(size_t index) const noexcept { if (error()) { return error(); } return first.at(index); @@ -6785,6 +7200,12 @@ inline simdjson_result array::at_pointer(std::string_view json_pointer) return child; } +inline simdjson_result array::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} + inline simdjson_result array::at(size_t index) const noexcept { SIMDJSON_DEVELOPMENT_ASSERT(tape.usable()); // https://github.com/simdjson/simdjson/issues/1914 size_t i=0; @@ -6861,6 +7282,7 @@ inline bool array::iterator::operator>(const array::iterator& other) const noexc /* skipped duplicate #include "simdjson/dom/element-inl.h" */ /* skipped duplicate #include "simdjson/error-inl.h" */ +/* skipped duplicate #include "simdjson/jsonpathutil.h" */ #include @@ -6888,6 +7310,11 @@ inline simdjson_result simdjson_result::at_pointer(st if (error()) { return error(); } return first.at_pointer(json_pointer); } +inline simdjson_result simdjson_result::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} inline simdjson_result simdjson_result::at_key(std::string_view key) const noexcept { if (error()) { return error(); } return first.at_key(key); @@ -6985,6 +7412,12 @@ inline simdjson_result object::at_pointer(std::string_view json_pointer return child; } +inline simdjson_result object::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} + inline simdjson_result object::at_key(std::string_view key) const noexcept { iterator end_field = end(); for (iterator field = begin(); field != end_field; ++field) { @@ -7117,6 +7550,7 @@ static_assert(std::ranges::sized_range #include @@ -7230,6 +7664,11 @@ simdjson_inline simdjson_result simdjson_result::at_ if (error()) { return error(); } return first.at_pointer(json_pointer); } +simdjson_inline simdjson_result simdjson_result::at_path(const std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} #ifndef SIMDJSON_DISABLE_DEPRECATED_API [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] simdjson_inline simdjson_result simdjson_result::at(const std::string_view json_pointer) const noexcept { @@ -7520,6 +7959,11 @@ inline simdjson_result element::at_pointer(std::string_view json_pointe } } } +inline simdjson_result element::at_path(std::string_view json_path) const noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { return INVALID_JSON_POINTER; } + return at_pointer(json_pointer); +} #ifndef SIMDJSON_DISABLE_DEPRECATED_API [[deprecated("For standard compliance, use at_pointer instead, and prefix your pointers with a slash '/', see RFC6901 ")]] inline simdjson_result element::at(std::string_view json_pointer) const noexcept { @@ -9424,7 +9868,6 @@ extern SIMDJSON_DLLIMPORTEXPORT const uint64_t thintable_epi8[256]; #endif // SIMDJSON_INTERNAL_SIMDPRUNE_TABLES_H /* end file simdjson/internal/simdprune_tables.h */ - #endif // SIMDJSON_GENERIC_DEPENDENCIES_H /* end file simdjson/generic/dependencies.h */ @@ -9838,7 +10281,7 @@ SIMDJSON_NO_SANITIZE_UNDEFINED // See issue https://github.com/simdjson/simdjson/issues/1965 SIMDJSON_NO_SANITIZE_MEMORY simdjson_inline int trailing_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long ret; // Search the mask data from least significant bit (LSB) // to the most significant bit (MSB) for a set bit (1). @@ -9854,9 +10297,15 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { return input_num & (input_num-1); } +// We sometimes call leading_zeroes on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +// Applies only when SIMDJSON_PREFER_REVERSE_BITS is defined and true. +// (See below.) +SIMDJSON_NO_SANITIZE_UNDEFINED /* result might be undefined when input_num is zero */ simdjson_inline int leading_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long leading_zero = 0; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). @@ -9909,7 +10358,7 @@ simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) #endif simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO *result = value1 + value2; return *result < value1; #else @@ -10026,7 +10475,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace arm64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H /* end file simdjson/arm64/numberparsing_defs.h */ @@ -10046,7 +10501,7 @@ namespace arm64 { namespace { namespace simd { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO namespace { // Start of private section with Visual Studio workaround @@ -10155,7 +10610,7 @@ namespace { // We return uint32_t instead of uint16_t because that seems to be more efficient for most // purposes (cutting it down to uint16_t costs performance in some compilers). simdjson_inline uint32_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); #else @@ -10186,7 +10641,7 @@ namespace { // Splat constructor simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 @@ -10280,7 +10735,7 @@ namespace { uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]}; uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -10310,7 +10765,7 @@ namespace { uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]); uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -10362,7 +10817,7 @@ namespace { // Array constructor simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 @@ -10483,7 +10938,7 @@ namespace { } simdjson_inline uint64_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t( 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 @@ -11206,7 +11661,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -11643,7 +12098,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -11717,7 +12171,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -12178,6 +12641,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -12687,7 +13156,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace fallback } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H /* end file simdjson/fallback/numberparsing_defs.h */ @@ -13309,7 +13784,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -13746,7 +14221,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -13820,7 +14294,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -14281,6 +14764,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -14686,8 +15175,14 @@ static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient paddi /* end file simdjson/haswell/intrinsics.h */ #if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL +// We enable bmi2 only if LLVM/clang is used, because GCC may not +// make good use of it. See https://github.com/simdjson/simdjson/pull/2243 +#if defined(__clang__) +SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt") +#else SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") #endif +#endif /* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */ /* begin file simdjson/haswell/bitmanipulation.h */ @@ -15904,7 +16399,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -16341,7 +16836,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -16415,7 +16909,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -16876,6 +17379,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -17546,14 +18055,18 @@ namespace simd { // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset). // Passing a 0 value for mask would be equivalent to writing out every byte to output. - // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes + // Only the first 64 - count_ones(mask) bytes of the result are significant but 64 bytes // get written. // Design consideration: it seems like a function with the // signature simd8 compress(uint32_t mask) would be // sensible, but the AVX ISA makes this kind of approach difficult. template simdjson_inline void compress(uint64_t mask, L * output) const { - _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + // we deliberately avoid _mm512_mask_compressstoreu_epi8 for portability + // (AMD Zen4 has terrible performance with it, it is effectively broken) + // _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + __m512i compressed = _mm512_maskz_compress_epi8(~mask, *this); + _mm512_storeu_si512(output, compressed); // could use a mask } template @@ -18498,7 +19011,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -18935,7 +19448,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -19009,7 +19521,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -19470,6 +19991,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -20040,7 +20567,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace ppc64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H /* end file simdjson/ppc64/numberparsing_defs.h */ @@ -21207,7 +21740,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -21644,7 +22177,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -21718,7 +22250,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -22179,6 +22720,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -24239,7 +24786,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -24676,7 +25223,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -24750,7 +25296,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -25211,6 +25766,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -25705,7 +26266,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lsx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LSX_NUMBERPARSING_DEFS_H /* end file simdjson/lsx/numberparsing_defs.h */ @@ -26742,7 +27309,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -27179,7 +27746,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -27253,7 +27819,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -27714,6 +28289,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -28205,7 +28786,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lasx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LASX_NUMBERPARSING_DEFS_H /* end file simdjson/lasx/numberparsing_defs.h */ @@ -29258,7 +29845,7 @@ simdjson_inline bool compute_float_64(int64_t power, uint64_t i, bool negative, // floor(log(5**power)/log(2)) // // Note that this is not magic: 152170/(1<<16) is - // approximatively equal to log(5)/log(2). + // approximately equal to log(5)/log(2). // The 1<<16 value is a power of two; we could use a // larger power of 2 if we wanted to. // @@ -29695,7 +30282,6 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con // Our objective is accurate parsing (ULP of 0) at high speed. template simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { - // // Check for minus sign // @@ -29769,7 +30355,16 @@ simdjson_inline error_code parse_number(const uint8_t *const src, W &writer) { if (i > uint64_t(INT64_MAX)) { WRITE_UNSIGNED(i, src, writer); } else { - WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(i == 0 && negative) { + // We have to write -0.0 instead of 0 + WRITE_DOUBLE(-0.0, src, writer); + } else { + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); + } +#else + WRITE_INTEGER(negative ? (~i+1) : i, src, writer); +#endif } if (jsoncharutils::is_not_structural_or_whitespace(*p)) { return INVALID_NUMBER(src); } return SUCCESS; @@ -30230,6 +30825,12 @@ simdjson_unused simdjson_inline simdjson_result get_number_type(con if (simdjson_unlikely(digit_count == 19 && memcmp(src, smaller_big_integer, 19) > 0)) { return number_type::big_integer; } +#if SIMDJSON_MINUS_ZERO_AS_FLOAT + if(digit_count == 1 && src[0] == '0') { + // We have to write -0.0 instead of 0 + return number_type::floating_point_number; + } +#endif return number_type::signed_integer; } // Let us check if we have a big integer (>=2**64). @@ -30566,6 +31167,7 @@ simdjson_inline implementation_simdjson_result_base::implementation_simdjson_ /* skipped duplicate #include "simdjson/padded_string.h" */ /* skipped duplicate #include "simdjson/padded_string_view.h" */ /* skipped duplicate #include "simdjson/internal/dom_parser_implementation.h" */ +/* skipped duplicate #include "simdjson/jsonpathutil.h" */ #endif // SIMDJSON_GENERIC_ONDEMAND_DEPENDENCIES_H /* end file simdjson/generic/ondemand/dependencies.h */ @@ -30652,7 +31254,7 @@ SIMDJSON_NO_SANITIZE_UNDEFINED // See issue https://github.com/simdjson/simdjson/issues/1965 SIMDJSON_NO_SANITIZE_MEMORY simdjson_inline int trailing_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long ret; // Search the mask data from least significant bit (LSB) // to the most significant bit (MSB) for a set bit (1). @@ -30668,9 +31270,15 @@ simdjson_inline uint64_t clear_lowest_bit(uint64_t input_num) { return input_num & (input_num-1); } +// We sometimes call leading_zeroes on inputs that are zero, +// but the algorithms do not end up using the returned value. +// Sadly, sanitizers are not smart enough to figure it out. +// Applies only when SIMDJSON_PREFER_REVERSE_BITS is defined and true. +// (See below.) +SIMDJSON_NO_SANITIZE_UNDEFINED /* result might be undefined when input_num is zero */ simdjson_inline int leading_zeroes(uint64_t input_num) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO unsigned long leading_zero = 0; // Search the mask data from most significant bit (MSB) // to least significant bit (LSB) for a set bit (1). @@ -30723,7 +31331,7 @@ simdjson_inline uint64_t zero_leading_bit(uint64_t rev_bits, int leading_zeroes) #endif simdjson_inline bool add_overflow(uint64_t value1, uint64_t value2, uint64_t *result) { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO *result = value1 + value2; return *result < value1; #else @@ -30840,7 +31448,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace arm64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_ARM64_NUMBERPARSING_DEFS_H /* end file simdjson/arm64/numberparsing_defs.h */ @@ -30860,7 +31474,7 @@ namespace arm64 { namespace { namespace simd { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO namespace { // Start of private section with Visual Studio workaround @@ -30969,7 +31583,7 @@ namespace { // We return uint32_t instead of uint16_t because that seems to be more efficient for most // purposes (cutting it down to uint16_t costs performance in some compilers). simdjson_inline uint32_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t(0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80); #else @@ -31000,7 +31614,7 @@ namespace { // Splat constructor simdjson_inline simd8(uint8_t _value) : simd8(splat(_value)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( uint8_t v0, uint8_t v1, uint8_t v2, uint8_t v3, uint8_t v4, uint8_t v5, uint8_t v6, uint8_t v7, uint8_t v8, uint8_t v9, uint8_t v10, uint8_t v11, uint8_t v12, uint8_t v13, uint8_t v14, uint8_t v15 @@ -31094,7 +31708,7 @@ namespace { uint64x2_t shufmask64 = {thintable_epi8[mask1], thintable_epi8[mask2]}; uint8x16_t shufmask = vreinterpretq_u8_u64(shufmask64); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x16_t inc = simdjson_make_uint8x16_t(0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x16_t inc = {0, 0, 0, 0, 0, 0, 0, 0, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -31124,7 +31738,7 @@ namespace { uint8x8_t compactmask1 = vcreate_u8(thintable_epi8[mask1]); uint8x8_t compactmask2 = vcreate_u8(thintable_epi8[mask2]); // we increment by 0x08 the second half of the mask -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO uint8x8_t inc = simdjson_make_uint8x8_t(0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08); #else uint8x8_t inc = {0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08}; @@ -31176,7 +31790,7 @@ namespace { // Array constructor simdjson_inline simd8(const int8_t* values) : simd8(load(values)) {} // Member-by-member initialization -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO simdjson_inline simd8( int8_t v0, int8_t v1, int8_t v2, int8_t v3, int8_t v4, int8_t v5, int8_t v6, int8_t v7, int8_t v8, int8_t v9, int8_t v10, int8_t v11, int8_t v12, int8_t v13, int8_t v14, int8_t v15 @@ -31297,7 +31911,7 @@ namespace { } simdjson_inline uint64_t to_bitmask() const { -#ifdef SIMDJSON_REGULAR_VISUAL_STUDIO +#if SIMDJSON_REGULAR_VISUAL_STUDIO const uint8x16_t bit_mask = simdjson_make_uint8x16_t( 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80, 0x01, 0x02, 0x4, 0x8, 0x10, 0x20, 0x40, 0x80 @@ -31460,6 +32074,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for arm64 */ +/* including simdjson/generic/ondemand/deserialize.h for arm64: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for arm64 */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = arm64::ondemand::value; + using document_type = arm64::ondemand::document; + using document_reference_type = arm64::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for arm64 */ /* including simdjson/generic/ondemand/value_iterator.h for arm64: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for arm64 */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -31589,7 +32329,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -31599,7 +32340,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -31721,7 +32463,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -31731,7 +32474,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -31964,12 +32708,15 @@ struct simdjson_result : public arm64::implemen /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace arm64 { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -31994,16 +32741,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -32013,7 +32765,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -32089,6 +32872,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -32340,6 +33134,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -32707,6 +33502,7 @@ struct simdjson_result : public arm64::implementation_si simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -33762,6 +34558,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -33956,8 +34768,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -34099,7 +34915,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -34377,8 +35194,11 @@ struct simdjson_result : public arm64::implemen /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace arm64 { namespace ondemand { @@ -34551,24 +35371,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -34582,7 +35417,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -34684,7 +35551,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -34796,6 +35664,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -35064,6 +35933,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -35089,7 +35963,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -35114,6 +36058,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -35192,6 +36137,7 @@ struct simdjson_result : public arm64::implementation simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -35241,8 +36187,14 @@ struct simdjson_result : public arm64::impl simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator arm64::ondemand::array() & noexcept(false); simdjson_inline operator arm64::ondemand::object() & noexcept(false); @@ -35263,6 +36215,7 @@ struct simdjson_result : public arm64::impl simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -36193,6 +37146,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + arm64::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + arm64::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for arm64 */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for arm64: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for arm64 */ @@ -36200,6 +37367,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -36561,313 +37682,276 @@ simdjson_inline simdjson_result &simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for arm64 */ -/* including simdjson/generic/ondemand/document-inl.h for arm64: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for arm64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for arm64: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for arm64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace arm64 { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; + } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -36877,15 +37961,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -36904,685 +37988,1324 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - arm64::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + arm64::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator arm64::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator arm64::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for arm64 */ +/* including simdjson/generic/ondemand/document-inl.h for arm64: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for arm64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace arm64 { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } -/** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. - */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } -template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } -#endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } - -} // namespace ondemand -} // namespace arm64 -} // namespace simdjson +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} +inline void document::rewind() noexcept { + iter.rewind(); +} -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(arm64::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); +inline int32_t document::current_depth() const noexcept { + return iter.depth(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); + +inline bool document::at_end() const noexcept { + return iter.at_end(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { - if (error()) { return error(); } - return first.at(index); + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - return {}; +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { - if (error()) { return error(); } - return first[key]; +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { - if (error()) { return error(); } - return first[key]; + +/** + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. + */ + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { - if (error()) { return error(); } - return first.find_field(key); +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { - if (error()) { return error(); } - return first.find_field(key); +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { - if (error()) { return error(); } - return first.get_array(); +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { - if (error()) { return error(); } - return first.get_object(); +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); +template +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); } -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + +#endif +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); +simdjson_inline simdjson_result document::end() & noexcept { + return {}; } -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; } -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; } -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; } -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} + +} // namespace ondemand +} // namespace arm64 +} // namespace simdjson + +namespace simdjson { + +simdjson_inline simdjson_result::simdjson_result( + arm64::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } + + #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::array() & noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::object() & noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator arm64::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator arm64::ondemand::value() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } return first.raw_json_token(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { if (error()) { return error(); } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { - return error(); - } +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } return first.at_path(json_path); } } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H -/* end file simdjson/generic/ondemand/document-inl.h for arm64 */ -/* including simdjson/generic/ondemand/document_stream-inl.h for arm64: #include "simdjson/generic/ondemand/document_stream-inl.h" */ -/* begin file simdjson/generic/ondemand/document_stream-inl.h for arm64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -#include -#include namespace simdjson { namespace arm64 { namespace ondemand { -#ifdef SIMDJSON_THREADS_ENABLED +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } -inline void stage1_worker::finish() { - // After calling "run" someone would call finish() to wait - // for the end of the processing. - // This function will wait until either the thread has done - // the processing or, else, the destructor has been called. - std::unique_lock lock(locking_mutex); - cond_var.wait(lock, [this]{return has_work == false;}); -} +} // namespace ondemand +} // namespace arm64 +} // namespace simdjson -inline stage1_worker::~stage1_worker() { - // The thread may never outlive the stage1_worker instance - // and will always be stopped/joined before the stage1_worker - // instance is gone. - stop_thread(); -} -inline void stage1_worker::start_thread() { - std::unique_lock lock(locking_mutex); - if(thread.joinable()) { - return; // This should never happen but we never want to create more than one thread. - } - thread = std::thread([this]{ - while(true) { - std::unique_lock thread_lock(locking_mutex); - // We wait for either "run" or "stop_thread" to be called. - cond_var.wait(thread_lock, [this]{return has_work || !can_work;}); - // If, for some reason, the stop_thread() method was called (i.e., the - // destructor of stage1_worker is called, then we want to immediately destroy - // the thread (and not do any more processing). - if(!can_work) { - break; - } - this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser, - this->_next_batch_start); - this->has_work = false; - // The condition variable call should be moved after thread_lock.unlock() for performance - // reasons but thread sanitizers may report it as a data race if we do. - // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock - cond_var.notify_one(); // will notify "finish" - thread_lock.unlock(); - } - } - ); -} +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(arm64::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} -inline void stage1_worker::stop_thread() { - std::unique_lock lock(locking_mutex); - // We have to make sure that all locks can be released. - can_work = false; - has_work = false; - cond_var.notify_all(); - lock.unlock(); - if(thread.joinable()) { - thread.join(); - } -} -inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) { - std::unique_lock lock(locking_mutex); - owner = ds; - _next_batch_start = next_batch_start; - stage1_thread_parser = stage1; - has_work = true; - // The condition variable call should be moved after thread_lock.unlock() for performance - // reasons but thread sanitizers may report it as a data race if we do. - // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock - cond_var.notify_one(); // will notify the thread lock that we have work - lock.unlock(); +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); } - -#endif // SIMDJSON_THREADS_ENABLED - -simdjson_inline document_stream::document_stream( - ondemand::parser &_parser, - const uint8_t *_buf, - size_t _len, - size_t _batch_size, - bool _allow_comma_separated -) noexcept - : parser{&_parser}, +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} +template <> +simdjson_inline error_code simdjson_result::get(arm64::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(arm64::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + if (error()) { throw simdjson_error(error()); } + return first.get(); +} +simdjson_inline simdjson_result::operator arm64::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator arm64::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator arm64::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { + return error(); + } + return first.at_path(json_path); +} + +} // namespace simdjson + +#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* end file simdjson/generic/ondemand/document-inl.h for arm64 */ +/* including simdjson/generic/ondemand/document_stream-inl.h for arm64: #include "simdjson/generic/ondemand/document_stream-inl.h" */ +/* begin file simdjson/generic/ondemand/document_stream-inl.h for arm64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +#include + +namespace simdjson { +namespace arm64 { +namespace ondemand { + +#ifdef SIMDJSON_THREADS_ENABLED + +inline void stage1_worker::finish() { + // After calling "run" someone would call finish() to wait + // for the end of the processing. + // This function will wait until either the thread has done + // the processing or, else, the destructor has been called. + std::unique_lock lock(locking_mutex); + cond_var.wait(lock, [this]{return has_work == false;}); +} + +inline stage1_worker::~stage1_worker() { + // The thread may never outlive the stage1_worker instance + // and will always be stopped/joined before the stage1_worker + // instance is gone. + stop_thread(); +} + +inline void stage1_worker::start_thread() { + std::unique_lock lock(locking_mutex); + if(thread.joinable()) { + return; // This should never happen but we never want to create more than one thread. + } + thread = std::thread([this]{ + while(true) { + std::unique_lock thread_lock(locking_mutex); + // We wait for either "run" or "stop_thread" to be called. + cond_var.wait(thread_lock, [this]{return has_work || !can_work;}); + // If, for some reason, the stop_thread() method was called (i.e., the + // destructor of stage1_worker is called, then we want to immediately destroy + // the thread (and not do any more processing). + if(!can_work) { + break; + } + this->owner->stage1_thread_error = this->owner->run_stage1(*this->stage1_thread_parser, + this->_next_batch_start); + this->has_work = false; + // The condition variable call should be moved after thread_lock.unlock() for performance + // reasons but thread sanitizers may report it as a data race if we do. + // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock + cond_var.notify_one(); // will notify "finish" + thread_lock.unlock(); + } + } + ); +} + + +inline void stage1_worker::stop_thread() { + std::unique_lock lock(locking_mutex); + // We have to make sure that all locks can be released. + can_work = false; + has_work = false; + cond_var.notify_all(); + lock.unlock(); + if(thread.joinable()) { + thread.join(); + } +} + +inline void stage1_worker::run(document_stream * ds, parser * stage1, size_t next_batch_start) { + std::unique_lock lock(locking_mutex); + owner = ds; + _next_batch_start = next_batch_start; + stage1_thread_parser = stage1; + has_work = true; + // The condition variable call should be moved after thread_lock.unlock() for performance + // reasons but thread sanitizers may report it as a data race if we do. + // See https://stackoverflow.com/questions/35775501/c-should-condition-variable-be-notified-under-lock + cond_var.notify_one(); // will notify the thread lock that we have work + lock.unlock(); +} + +#endif // SIMDJSON_THREADS_ENABLED + +simdjson_inline document_stream::document_stream( + ondemand::parser &_parser, + const uint8_t *_buf, + size_t _len, + size_t _batch_size, + bool _allow_comma_separated +) noexcept + : parser{&_parser}, buf{_buf}, len{_len}, batch_size{_batch_size <= MINIMAL_BATCH_SIZE ? MINIMAL_BATCH_SIZE : _batch_size}, @@ -37637,7 +39360,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -39496,36 +41218,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -39537,7 +41262,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -40011,775 +41736,230 @@ simdjson_inline simdjson_result::simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for arm64 */ -/* including simdjson/generic/ondemand/value-inl.h for arm64: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for arm64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for arm64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace arm64 { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace arm64 -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - arm64::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(arm64::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator arm64::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator arm64::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator arm64::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for arm64 */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for arm64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for arm64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace arm64 { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -41338,19 +42518,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -41359,6 +42543,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -41650,6 +42836,8 @@ simdjson_inline simdjson_result::simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for arm64 */ + + /* end file simdjson/generic/ondemand/amalgamated.h for arm64 */ /* including simdjson/arm64/end.h: #include "simdjson/arm64/end.h" */ /* begin file simdjson/arm64/end.h */ @@ -41865,7 +43053,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace fallback } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_FALLBACK_NUMBERPARSING_DEFS_H /* end file simdjson/fallback/numberparsing_defs.h */ @@ -41927,6 +43121,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for fallback */ +/* including simdjson/generic/ondemand/deserialize.h for fallback: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for fallback */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = fallback::ondemand::value; + using document_type = fallback::ondemand::document; + using document_reference_type = fallback::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for fallback */ /* including simdjson/generic/ondemand/value_iterator.h for fallback: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for fallback */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -42056,7 +43376,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -42066,7 +43387,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -42188,7 +43510,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -42198,7 +43521,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -42431,12 +43755,15 @@ struct simdjson_result : public fallback::im /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace fallback { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -42461,16 +43788,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -42480,7 +43812,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -42556,6 +43919,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -42807,6 +44181,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -43174,6 +44549,7 @@ struct simdjson_result : public fallback::implementat simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -44229,6 +45605,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -44423,8 +45815,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -44566,7 +45962,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -44844,8 +46241,11 @@ struct simdjson_result : public fallback::im /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace fallback { namespace ondemand { @@ -45018,24 +46418,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -45049,7 +46464,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -45151,7 +46598,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -45263,6 +46711,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -45531,6 +46980,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -45556,7 +47010,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -45581,6 +47105,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -45659,6 +47184,7 @@ struct simdjson_result : public fallback::implemen simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -45708,8 +47234,14 @@ struct simdjson_result : public fallback simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator fallback::ondemand::array() & noexcept(false); simdjson_inline operator fallback::ondemand::object() & noexcept(false); @@ -45730,6 +47262,7 @@ struct simdjson_result : public fallback simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -46660,6 +48193,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + fallback::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + fallback::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for fallback */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for fallback: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for fallback */ @@ -46667,6 +48414,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -47028,313 +48729,276 @@ simdjson_inline simdjson_result &simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for fallback */ -/* including simdjson/generic/ondemand/document-inl.h for fallback: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for fallback */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for fallback: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for fallback */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace fallback { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -47344,15 +49008,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -47371,417 +49035,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - fallback::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + fallback::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator fallback::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator fallback::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator fallback::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator fallback::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator fallback::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator fallback::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator fallback::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for fallback */ +/* including simdjson/generic/ondemand/document-inl.h for fallback: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for fallback */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace fallback { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace fallback } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(fallback::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + fallback::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator fallback::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator fallback::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator fallback::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator fallback::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace fallback { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace fallback +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(fallback::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -47850,6 +50119,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -47862,6 +50151,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(fallback::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(fallback::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -47879,10 +50180,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator fallback::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -48104,7 +50407,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -49963,36 +52265,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -50004,7 +52309,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -50478,775 +52783,230 @@ simdjson_inline simdjson_result::simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for fallback */ -/* including simdjson/generic/ondemand/value-inl.h for fallback: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for fallback */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for fallback */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace fallback { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace fallback -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - fallback::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(fallback::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator fallback::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator fallback::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator fallback::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for fallback */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for fallback: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for fallback */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace fallback { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -51805,19 +53565,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -51826,6 +53590,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -52117,6 +53883,8 @@ simdjson_inline simdjson_result::simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for fallback */ + + /* end file simdjson/generic/ondemand/amalgamated.h for fallback */ /* including simdjson/fallback/end.h: #include "simdjson/fallback/end.h" */ /* begin file simdjson/fallback/end.h */ @@ -52228,8 +53996,14 @@ static_assert(sizeof(__m256i) <= simdjson::SIMDJSON_PADDING, "insufficient paddi /* end file simdjson/haswell/intrinsics.h */ #if !SIMDJSON_CAN_ALWAYS_RUN_HASWELL +// We enable bmi2 only if LLVM/clang is used, because GCC may not +// make good use of it. See https://github.com/simdjson/simdjson/pull/2243 +#if defined(__clang__) +SIMDJSON_TARGET_REGION("avx2,bmi,bmi2,pclmul,lzcnt,popcnt") +#else SIMDJSON_TARGET_REGION("avx2,bmi,pclmul,lzcnt,popcnt") #endif +#endif /* including simdjson/haswell/bitmanipulation.h: #include "simdjson/haswell/bitmanipulation.h" */ /* begin file simdjson/haswell/bitmanipulation.h */ @@ -52886,6 +54660,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for haswell */ +/* including simdjson/generic/ondemand/deserialize.h for haswell: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for haswell */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = haswell::ondemand::value; + using document_type = haswell::ondemand::document; + using document_reference_type = haswell::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for haswell */ /* including simdjson/generic/ondemand/value_iterator.h for haswell: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for haswell */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -53015,7 +54915,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -53025,7 +54926,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -53147,7 +55049,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -53157,7 +55060,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -53390,12 +55294,15 @@ struct simdjson_result : public haswell::impl /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace haswell { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -53420,16 +55327,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -53439,7 +55351,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -53515,6 +55458,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -53766,6 +55720,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -54133,6 +56088,7 @@ struct simdjson_result : public haswell::implementatio simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -55188,6 +57144,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -55382,8 +57354,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -55525,7 +57501,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -55803,8 +57780,11 @@ struct simdjson_result : public haswell::impl /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace haswell { namespace ondemand { @@ -55977,24 +57957,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -56008,7 +58003,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -56110,7 +58137,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -56222,6 +58250,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -56490,6 +58519,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -56515,7 +58549,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -56540,6 +58644,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -56618,6 +58723,7 @@ struct simdjson_result : public haswell::implementa simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -56667,8 +58773,14 @@ struct simdjson_result : public haswell:: simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator haswell::ondemand::array() & noexcept(false); simdjson_inline operator haswell::ondemand::object() & noexcept(false); @@ -56689,6 +58801,7 @@ struct simdjson_result : public haswell:: simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -57619,6 +59732,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + haswell::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + haswell::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for haswell */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for haswell: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for haswell */ @@ -57626,6 +59953,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -57987,313 +60268,276 @@ simdjson_inline simdjson_result &simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for haswell */ -/* including simdjson/generic/ondemand/document-inl.h for haswell: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for haswell */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for haswell: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for haswell */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace haswell { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -58303,15 +60547,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -58330,417 +60574,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - haswell::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + haswell::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator haswell::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator haswell::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator haswell::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator haswell::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator haswell::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator haswell::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator haswell::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for haswell */ +/* including simdjson/generic/ondemand/document-inl.h for haswell: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for haswell */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace haswell { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace haswell } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(haswell::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + haswell::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator haswell::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator haswell::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator haswell::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator haswell::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace haswell { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace haswell +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(haswell::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -58809,6 +61658,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -58821,6 +61690,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(haswell::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(haswell::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -58838,10 +61719,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator haswell::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -59063,7 +61946,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -60922,36 +63804,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -60963,7 +63848,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -61437,775 +64322,230 @@ simdjson_inline simdjson_result::simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for haswell */ -/* including simdjson/generic/ondemand/value-inl.h for haswell: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for haswell */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for haswell */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace haswell { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace haswell -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - haswell::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(haswell::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator haswell::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator haswell::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator haswell::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for haswell */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for haswell: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for haswell */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace haswell { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -62764,19 +65104,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -62785,6 +65129,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -63076,6 +65422,8 @@ simdjson_inline simdjson_result::simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for haswell */ + + /* end file simdjson/generic/ondemand/amalgamated.h for haswell */ /* including simdjson/haswell/end.h: #include "simdjson/haswell/end.h" */ /* begin file simdjson/haswell/end.h */ @@ -63452,14 +65800,18 @@ namespace simd { // Copies to 'output" all bytes corresponding to a 0 in the mask (interpreted as a bitset). // Passing a 0 value for mask would be equivalent to writing out every byte to output. - // Only the first 32 - count_ones(mask) bytes of the result are significant but 32 bytes + // Only the first 64 - count_ones(mask) bytes of the result are significant but 64 bytes // get written. // Design consideration: it seems like a function with the // signature simd8 compress(uint32_t mask) would be // sensible, but the AVX ISA makes this kind of approach difficult. template simdjson_inline void compress(uint64_t mask, L * output) const { - _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + // we deliberately avoid _mm512_mask_compressstoreu_epi8 for portability + // (AMD Zen4 has terrible performance with it, it is effectively broken) + // _mm512_mask_compressstoreu_epi8 (output,~mask,*this); + __m512i compressed = _mm512_maskz_compress_epi8(~mask, *this); + _mm512_storeu_si512(output, compressed); // could use a mask } template @@ -63844,6 +66196,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for icelake */ +/* including simdjson/generic/ondemand/deserialize.h for icelake: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for icelake */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = icelake::ondemand::value; + using document_type = icelake::ondemand::document; + using document_reference_type = icelake::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for icelake */ /* including simdjson/generic/ondemand/value_iterator.h for icelake: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for icelake */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -63973,7 +66451,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -63983,7 +66462,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -64105,7 +66585,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -64115,7 +66596,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -64348,12 +66830,15 @@ struct simdjson_result : public icelake::impl /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace icelake { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -64378,16 +66863,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -64397,7 +66887,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -64473,6 +66994,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -64724,6 +67256,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -65091,6 +67624,7 @@ struct simdjson_result : public icelake::implementatio simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -66146,6 +68680,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -66340,8 +68890,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -66483,7 +69037,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -66761,8 +69316,11 @@ struct simdjson_result : public icelake::impl /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace icelake { namespace ondemand { @@ -66935,24 +69493,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -66966,7 +69539,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -67068,7 +69673,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -67180,6 +69786,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -67448,6 +70055,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -67473,7 +70085,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -67498,6 +70180,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -67576,6 +70259,7 @@ struct simdjson_result : public icelake::implementa simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -67625,8 +70309,14 @@ struct simdjson_result : public icelake:: simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator icelake::ondemand::array() & noexcept(false); simdjson_inline operator icelake::ondemand::object() & noexcept(false); @@ -67647,6 +70337,7 @@ struct simdjson_result : public icelake:: simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -68577,6 +71268,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + icelake::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + icelake::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for icelake */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for icelake: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for icelake */ @@ -68584,6 +71489,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -68945,313 +71804,276 @@ simdjson_inline simdjson_result &simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for icelake */ -/* including simdjson/generic/ondemand/document-inl.h for icelake: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for icelake */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for icelake: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for icelake */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace icelake { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -69261,15 +72083,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -69288,417 +72110,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - icelake::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + icelake::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator icelake::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator icelake::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator icelake::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator icelake::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator icelake::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator icelake::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator icelake::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for icelake */ +/* including simdjson/generic/ondemand/document-inl.h for icelake: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for icelake */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace icelake { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace icelake } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(icelake::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + icelake::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator icelake::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator icelake::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator icelake::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator icelake::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace icelake { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace icelake +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(icelake::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -69767,6 +73194,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -69779,6 +73226,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(icelake::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(icelake::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -69796,10 +73255,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator icelake::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -70021,7 +73482,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -71880,36 +75340,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -71921,7 +75384,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -72395,775 +75858,230 @@ simdjson_inline simdjson_result::simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for icelake */ -/* including simdjson/generic/ondemand/value-inl.h for icelake: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for icelake */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for icelake */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace icelake { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace icelake -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - icelake::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(icelake::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator icelake::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator icelake::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator icelake::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for icelake */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for icelake: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for icelake */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace icelake { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -73722,19 +76640,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -73743,6 +76665,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -74034,6 +76958,8 @@ simdjson_inline simdjson_result::simdjson_res #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for icelake */ + + /* end file simdjson/generic/ondemand/amalgamated.h for icelake */ /* including simdjson/icelake/end.h: #include "simdjson/icelake/end.h" */ /* begin file simdjson/icelake/end.h */ @@ -74310,7 +77236,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace ppc64 } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_PPC64_NUMBERPARSING_DEFS_H /* end file simdjson/ppc64/numberparsing_defs.h */ @@ -74917,6 +77849,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for ppc64 */ +/* including simdjson/generic/ondemand/deserialize.h for ppc64: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for ppc64 */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = ppc64::ondemand::value; + using document_type = ppc64::ondemand::document; + using document_reference_type = ppc64::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for ppc64 */ /* including simdjson/generic/ondemand/value_iterator.h for ppc64: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for ppc64 */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -75046,7 +78104,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -75056,7 +78115,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -75178,7 +78238,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -75188,7 +78249,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -75421,12 +78483,15 @@ struct simdjson_result : public ppc64::implemen /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace ppc64 { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -75451,16 +78516,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -75470,7 +78540,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -75546,6 +78647,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -75797,6 +78909,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -76164,6 +79277,7 @@ struct simdjson_result : public ppc64::implementation_si simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -77219,6 +80333,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -77413,8 +80543,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -77556,7 +80690,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -77834,8 +80969,11 @@ struct simdjson_result : public ppc64::implemen /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace ppc64 { namespace ondemand { @@ -78008,24 +81146,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -78039,7 +81192,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -78141,7 +81326,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -78253,6 +81439,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -78521,6 +81708,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -78546,7 +81738,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -78571,6 +81833,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -78649,6 +81912,7 @@ struct simdjson_result : public ppc64::implementation simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -78698,8 +81962,14 @@ struct simdjson_result : public ppc64::impl simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator ppc64::ondemand::array() & noexcept(false); simdjson_inline operator ppc64::ondemand::object() & noexcept(false); @@ -78720,6 +81990,7 @@ struct simdjson_result : public ppc64::impl simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -79650,6 +82921,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + ppc64::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + ppc64::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for ppc64 */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for ppc64: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for ppc64 */ @@ -79657,6 +83142,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -80018,313 +83457,276 @@ simdjson_inline simdjson_result &simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for ppc64 */ -/* including simdjson/generic/ondemand/document-inl.h for ppc64: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for ppc64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for ppc64: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for ppc64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace ppc64 { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -80334,15 +83736,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -80361,417 +83763,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - ppc64::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + ppc64::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator ppc64::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator ppc64::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator ppc64::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator ppc64::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator ppc64::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator ppc64::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator ppc64::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for ppc64 */ +/* including simdjson/generic/ondemand/document-inl.h for ppc64: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for ppc64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace ppc64 { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace ppc64 } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(ppc64::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + ppc64::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator ppc64::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator ppc64::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator ppc64::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator ppc64::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace ppc64 { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace ppc64 +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(ppc64::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -80840,6 +84847,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -80852,6 +84879,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(ppc64::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -80869,10 +84908,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator ppc64::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -81094,7 +85135,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -82953,36 +86993,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -82994,7 +87037,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -83468,775 +87511,230 @@ simdjson_inline simdjson_result::simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for ppc64 */ -/* including simdjson/generic/ondemand/value-inl.h for ppc64: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for ppc64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for ppc64 */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace ppc64 { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace ppc64 -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - ppc64::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(ppc64::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator ppc64::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator ppc64::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator ppc64::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for ppc64 */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for ppc64: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for ppc64 */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace ppc64 { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -84795,19 +88293,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -84816,6 +88318,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -85107,6 +88611,8 @@ simdjson_inline simdjson_result::simdjson_resul #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for ppc64 */ + + /* end file simdjson/generic/ondemand/amalgamated.h for ppc64 */ /* including simdjson/ppc64/end.h: #include "simdjson/ppc64/end.h" */ /* begin file simdjson/ppc64/end.h */ @@ -86313,6 +89819,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for westmere */ +/* including simdjson/generic/ondemand/deserialize.h for westmere: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for westmere */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = westmere::ondemand::value; + using document_type = westmere::ondemand::document; + using document_reference_type = westmere::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for westmere */ /* including simdjson/generic/ondemand/value_iterator.h for westmere: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for westmere */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -86442,7 +90074,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -86452,7 +90085,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -86574,7 +90208,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -86584,7 +90219,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -86817,12 +90453,15 @@ struct simdjson_result : public westmere::im /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace westmere { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -86847,16 +90486,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -86866,7 +90510,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -86942,6 +90617,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -87193,6 +90879,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -87560,6 +91247,7 @@ struct simdjson_result : public westmere::implementat simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -88615,6 +92303,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -88809,8 +92513,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -88952,7 +92660,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -89230,8 +92939,11 @@ struct simdjson_result : public westmere::im /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace westmere { namespace ondemand { @@ -89404,24 +93116,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -89435,7 +93162,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -89537,7 +93296,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -89649,6 +93409,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -89917,6 +93678,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -89942,7 +93708,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -89967,6 +93803,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -90045,6 +93882,7 @@ struct simdjson_result : public westmere::implemen simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -90094,8 +93932,14 @@ struct simdjson_result : public westmere simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator westmere::ondemand::array() & noexcept(false); simdjson_inline operator westmere::ondemand::object() & noexcept(false); @@ -90116,6 +93960,7 @@ struct simdjson_result : public westmere simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -91046,6 +94891,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + westmere::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + westmere::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for westmere */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for westmere: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for westmere */ @@ -91053,6 +95112,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -91414,313 +95427,276 @@ simdjson_inline simdjson_result &simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for westmere */ -/* including simdjson/generic/ondemand/document-inl.h for westmere: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for westmere */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for westmere: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for westmere */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace westmere { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -91730,15 +95706,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -91757,417 +95733,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - westmere::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + westmere::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator westmere::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator westmere::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator westmere::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator westmere::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator westmere::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator westmere::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator westmere::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for westmere */ +/* including simdjson/generic/ondemand/document-inl.h for westmere: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for westmere */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace westmere { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace westmere } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(westmere::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + westmere::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator westmere::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator westmere::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator westmere::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator westmere::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace westmere { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace westmere +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(westmere::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -92236,6 +96817,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -92248,6 +96849,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(westmere::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(westmere::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -92265,10 +96878,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator westmere::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -92490,7 +97105,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -94349,36 +98963,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -94390,7 +99007,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -94864,775 +99481,230 @@ simdjson_inline simdjson_result::simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for westmere */ -/* including simdjson/generic/ondemand/value-inl.h for westmere: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for westmere */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for westmere */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace westmere { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace westmere -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - westmere::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(westmere::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator westmere::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator westmere::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator westmere::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for westmere */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for westmere: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for westmere */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace westmere { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -96191,19 +100263,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -96212,6 +100288,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -96503,6 +100581,8 @@ simdjson_inline simdjson_result::simdjson_re #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for westmere */ + + /* end file simdjson/generic/ondemand/amalgamated.h for westmere */ /* including simdjson/westmere/end.h: #include "simdjson/westmere/end.h" */ /* begin file simdjson/westmere/end.h */ @@ -96703,7 +100783,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lsx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LSX_NUMBERPARSING_DEFS_H /* end file simdjson/lsx/numberparsing_defs.h */ @@ -97180,6 +101266,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for lsx */ +/* including simdjson/generic/ondemand/deserialize.h for lsx: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for lsx */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = lsx::ondemand::value; + using document_type = lsx::ondemand::document; + using document_reference_type = lsx::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for lsx */ /* including simdjson/generic/ondemand/value_iterator.h for lsx: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for lsx */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -97309,7 +101521,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -97319,7 +101532,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -97441,7 +101655,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -97451,7 +101666,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -97684,12 +101900,15 @@ struct simdjson_result : public lsx::implementati /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace lsx { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -97714,16 +101933,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -97733,7 +101957,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -97809,6 +102064,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -98060,6 +102326,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -98427,6 +102694,7 @@ struct simdjson_result : public lsx::implementation_simdjs simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -99482,6 +103750,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -99676,8 +103960,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -99819,7 +104107,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -100097,8 +104386,11 @@ struct simdjson_result : public lsx::implementati /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace lsx { namespace ondemand { @@ -100271,24 +104563,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -100302,7 +104609,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -100404,7 +104743,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -100516,6 +104856,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -100784,6 +105125,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -100809,7 +105155,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -100834,6 +105250,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -100912,6 +105329,7 @@ struct simdjson_result : public lsx::implementation_sim simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -100961,8 +105379,14 @@ struct simdjson_result : public lsx::implemen simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator lsx::ondemand::array() & noexcept(false); simdjson_inline operator lsx::ondemand::object() & noexcept(false); @@ -100983,6 +105407,7 @@ struct simdjson_result : public lsx::implemen simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -101913,6 +106338,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + lsx::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + lsx::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for lsx */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for lsx: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for lsx */ @@ -101920,6 +106559,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -102281,313 +106874,276 @@ simdjson_inline simdjson_result &simdjson_result< #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for lsx */ -/* including simdjson/generic/ondemand/document-inl.h for lsx: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for lsx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for lsx: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for lsx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lsx { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -102597,15 +107153,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -102624,417 +107180,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - lsx::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + lsx::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator lsx::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator lsx::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator lsx::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator lsx::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator lsx::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator lsx::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator lsx::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for lsx */ +/* including simdjson/generic/ondemand/document-inl.h for lsx: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for lsx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lsx { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace lsx } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(lsx::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + lsx::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lsx::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lsx::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lsx::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lsx::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace lsx { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace lsx +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(lsx::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -103103,6 +108264,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -103115,6 +108296,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(lsx::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(lsx::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -103132,10 +108325,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator lsx::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -103357,7 +108552,6 @@ simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bo } simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } return simdjson_result(stream->doc, stream->error); } @@ -105216,36 +110410,39 @@ simdjson_inline const char * raw_json_string::raw() const noexcept { return rein simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } } + pos++; } return true; } @@ -105257,7 +110454,7 @@ simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string } simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and + // Assumptions: does not contain unescaped quote characters("), and // the raw content is quote terminated within a valid JSON string. if(target.size() <= SIMDJSON_PADDING) { return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); @@ -105731,775 +110928,230 @@ simdjson_inline simdjson_result::simdjson_result( #endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H /* end file simdjson/generic/ondemand/token_iterator-inl.h for lsx */ -/* including simdjson/generic/ondemand/value-inl.h for lsx: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for lsx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* including simdjson/generic/ondemand/value_iterator-inl.h for lsx: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/value_iterator-inl.h for lsx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lsx { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} +simdjson_inline value_iterator::value_iterator( + json_iterator *json_iter, + depth_t depth, + token_position start_position +) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} { } -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { + SIMDJSON_TRY( start_container('{', "Not an object", "object") ); + return started_root_object(); } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { + assert_at_container_start(); +#if SIMDJSON_DEVELOPMENT_CHECKS + _json_iter->set_start_position(_depth, start_position()); #endif - -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); -} - -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} - -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} - -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; -} - -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); + if (*_json_iter->peek() == '}') { + logger::log_value(*_json_iter, "empty object"); + _json_iter->return_current_and_advance(); + end_container(); + return false; + } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); +simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { + // When in streaming mode, we cannot expect peek_last() to be the last structural element of the + // current document. It only works in the normal mode where we have indexed a single document. + // Note that adding a check for 'streaming' is not expensive since we only have at most + // one root element. + if ( ! _json_iter->streaming() ) { + // The following lines do not fully protect against garbage content within the + // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should + // call `at_end()` on the document instance at the end of the processing to + // ensure that the processing has finished at the end. + // + if (*_json_iter->peek_last() != '}') { + _json_iter->abandon(); + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); + } + // If the last character is } *and* the first gibberish character is also '}' + // then on-demand could accidentally go over. So we need additional checks. + // https://github.com/simdjson/simdjson/issues/1834 + // Checking that the document is balanced requires a full scan which is potentially + // expensive, but it only happens in edge cases where the first padding character is + // a closing bracket. + if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { + _json_iter->abandon(); + // The exact error would require more work. It will typically be an unclosed object. + return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); + } + } + return SUCCESS; } -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { + auto error = check_root_object(); if(error) { return error; } - return (this_type == json_type::string); -} - - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); + return started_object(); } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { +#if SIMDJSON_CHECK_EOF + if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } + // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + _json_iter->ascend_to(depth()-1); + return SUCCESS; } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { + assert_at_next(); -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } + // It's illegal to call this unless there are more tokens: anything that ends in } or ] is + // obligated to verify there are more tokens if they are not the top level. + switch (*_json_iter->return_current_and_advance()) { + case '}': + logger::log_end_value(*_json_iter, "object"); + SIMDJSON_TRY( end_container() ); + return false; + case ',': + return true; default: - return raw_json_token(); + return report_error(TAPE_ERROR, "Missing comma between object fields"); } } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); -} - -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { + error_code error; + bool has_value; + // + // Initially, the object can be in one of a few different places: + // + // 1. The start of the object, at the first field: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2, index 1) + // ``` + if (at_first_field()) { + has_value = true; -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + // + // 2. When a previous search did not yield a value or the object is empty: + // + // ``` + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 0) + // { } + // ^ (depth 0, index 2) + // ``` + // + } else if (!is_open()) { +#if SIMDJSON_DEVELOPMENT_CHECKS + // If we're past the end of the object, we're being iterated out of order. + // Note: this is not perfect detection. It's possible the user is inside some other object; if so, + // this object iterator will blithely scan that object for fields. + if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } +#endif return false; - } - return true; -} -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; + // 3. When a previous search found a field or an iterator yielded a value: + // + // ``` + // // When a field was not fully consumed (or not even touched at all) + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 2) + // // When a field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // // When the last field was fully consumed + // { "a": [ 1, 2 ], "b": [ 3, 4 ] } + // ^ (depth 1) + // ``` + // + } else { + if ((error = skip_child() )) { abandon(); return error; } + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } +#if SIMDJSON_DEVELOPMENT_CHECKS + if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } +#endif } -} + while (has_value) { + // Get the key and colon, stopping at the value. + raw_json_string actual_key; + // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes + // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. + // field_key() advances the pointer and checks that '"' is found (corresponding to a key). + // The depth is left unchanged by field_key(). + if ((error = field_key().get(actual_key) )) { abandon(); return error; }; + // field_value() will advance and check that we find a ':' separating the + // key and the value. It will also increment the depth by one. + if ((error = field_value() )) { abandon(); return error; } + // If it matches, stop and return + // We could do it this way if we wanted to allow arbitrary + // key content (including escaped quotes). + //if (actual_key.unsafe_is_equal(max_key_length, key)) { + // Instead we do the following which may trigger buffer overruns if the + // user provides an adversarial key (containing a well placed unescaped quote + // character and being longer than the number of bytes remaining in the JSON + // input). + if (actual_key.unsafe_is_equal(key)) { + logger::log_event(*this, "match", key, -2); + // If we return here, then we return while pointing at the ':' that we just checked. + return true; + } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; + // No match: skip the value and see if , or } is next + logger::log_event(*this, "no match", key, -2); + // The call to skip_child is meant to skip over the value corresponding to the key. + // After skip_child(), we are right before the next comma (',') or the final brace ('}'). + SIMDJSON_TRY( skip_child() ); // Skip the value entirely + // The has_next_field() advances the pointer and check that either ',' or '}' is found. + // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, + // then we are in error and we abort. + if ((error = has_next_field().get(has_value) )) { abandon(); return error; } } -} - -} // namespace ondemand -} // namespace lsx -} // namespace simdjson - -namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - lsx::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { - if (error()) { return error(); } - return first.count_elements(); -} -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { - if (error()) { return error(); } - return first.at(index); -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + // If the loop ended, we're out of fields to look at. + return false; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { + /** + * When find_field_unordered_raw is called, we can either be pointing at the + * first key, pointing outside (at the closing brace) or if a key was matched + * we can be either pointing right afterthe ':' right before the value (that we need skip), + * or we may have consumed the value and we might be at a comma or at the + * final brace (ready for a call to has_next_field()). + */ + error_code error; + bool has_value; -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} - -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; -} - -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); -} -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); -} -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); -} -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); -} -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); -} -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); -} -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); -} -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); -} -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); -} - -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); -} - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); -} -template<> simdjson_inline error_code simdjson_result::get(lsx::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; -} - -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); -} -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); -} -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); -} -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); -} -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); -} -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); -} -simdjson_inline simdjson_result::operator lsx::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator lsx::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator lsx::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); -} - -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} - -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} - -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for lsx */ -/* including simdjson/generic/ondemand/value_iterator-inl.h for lsx: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/value_iterator-inl.h for lsx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/atomparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/numberparsing.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace lsx { -namespace ondemand { - -simdjson_inline value_iterator::value_iterator( - json_iterator *json_iter, - depth_t depth, - token_position start_position -) noexcept : _json_iter{json_iter}, _depth{depth}, _start_position{start_position} -{ -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::start_root_object() noexcept { - SIMDJSON_TRY( start_container('{', "Not an object", "object") ); - return started_root_object(); -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_object() noexcept { - assert_at_container_start(); -#if SIMDJSON_DEVELOPMENT_CHECKS - _json_iter->set_start_position(_depth, start_position()); -#endif - if (*_json_iter->peek() == '}') { - logger::log_value(*_json_iter, "empty object"); - _json_iter->return_current_and_advance(); - end_container(); - return false; - } - return true; -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::check_root_object() noexcept { - // When in streaming mode, we cannot expect peek_last() to be the last structural element of the - // current document. It only works in the normal mode where we have indexed a single document. - // Note that adding a check for 'streaming' is not expensive since we only have at most - // one root element. - if ( ! _json_iter->streaming() ) { - // The following lines do not fully protect against garbage content within the - // object: e.g., `{"a":2} foo }`. Users concerned with garbage content should - // call `at_end()` on the document instance at the end of the processing to - // ensure that the processing has finished at the end. - // - if (*_json_iter->peek_last() != '}') { - _json_iter->abandon(); - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing } at end"); - } - // If the last character is } *and* the first gibberish character is also '}' - // then on-demand could accidentally go over. So we need additional checks. - // https://github.com/simdjson/simdjson/issues/1834 - // Checking that the document is balanced requires a full scan which is potentially - // expensive, but it only happens in edge cases where the first padding character is - // a closing bracket. - if ((*_json_iter->peek(_json_iter->end_position()) == '}') && (!_json_iter->balanced())) { - _json_iter->abandon(); - // The exact error would require more work. It will typically be an unclosed object. - return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "the document is unbalanced"); - } - } - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::started_root_object() noexcept { - auto error = check_root_object(); - if(error) { return error; } - return started_object(); -} - -simdjson_warn_unused simdjson_inline error_code value_iterator::end_container() noexcept { -#if SIMDJSON_CHECK_EOF - if (depth() > 1 && at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing parent ] or }"); } - // if (depth() <= 1 && !at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - _json_iter->ascend_to(depth()-1); - return SUCCESS; -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::has_next_field() noexcept { - assert_at_next(); - - // It's illegal to call this unless there are more tokens: anything that ends in } or ] is - // obligated to verify there are more tokens if they are not the top level. - switch (*_json_iter->return_current_and_advance()) { - case '}': - logger::log_end_value(*_json_iter, "object"); - SIMDJSON_TRY( end_container() ); - return false; - case ',': - return true; - default: - return report_error(TAPE_ERROR, "Missing comma between object fields"); - } -} - -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_raw(const std::string_view key) noexcept { - error_code error; - bool has_value; - // - // Initially, the object can be in one of a few different places: - // - // 1. The start of the object, at the first field: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2, index 1) - // ``` - if (at_first_field()) { - has_value = true; - - // - // 2. When a previous search did not yield a value or the object is empty: - // - // ``` - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 0) - // { } - // ^ (depth 0, index 2) - // ``` - // - } else if (!is_open()) { -#if SIMDJSON_DEVELOPMENT_CHECKS - // If we're past the end of the object, we're being iterated out of order. - // Note: this is not perfect detection. It's possible the user is inside some other object; if so, - // this object iterator will blithely scan that object for fields. - if (_json_iter->depth() < depth() - 1) { return OUT_OF_ORDER_ITERATION; } -#endif - return false; - - // 3. When a previous search found a field or an iterator yielded a value: - // - // ``` - // // When a field was not fully consumed (or not even touched at all) - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 2) - // // When a field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // // When the last field was fully consumed - // { "a": [ 1, 2 ], "b": [ 3, 4 ] } - // ^ (depth 1) - // ``` - // - } else { - if ((error = skip_child() )) { abandon(); return error; } - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } -#if SIMDJSON_DEVELOPMENT_CHECKS - if (_json_iter->start_position(_depth) != start_position()) { return OUT_OF_ORDER_ITERATION; } -#endif - } - while (has_value) { - // Get the key and colon, stopping at the value. - raw_json_string actual_key; - // size_t max_key_length = _json_iter->peek_length() - 2; // -2 for the two quotes - // Note: _json_iter->peek_length() - 2 might overflow if _json_iter->peek_length() < 2. - // field_key() advances the pointer and checks that '"' is found (corresponding to a key). - // The depth is left unchanged by field_key(). - if ((error = field_key().get(actual_key) )) { abandon(); return error; }; - // field_value() will advance and check that we find a ':' separating the - // key and the value. It will also increment the depth by one. - if ((error = field_value() )) { abandon(); return error; } - // If it matches, stop and return - // We could do it this way if we wanted to allow arbitrary - // key content (including escaped quotes). - //if (actual_key.unsafe_is_equal(max_key_length, key)) { - // Instead we do the following which may trigger buffer overruns if the - // user provides an adversarial key (containing a well placed unescaped quote - // character and being longer than the number of bytes remaining in the JSON - // input). - if (actual_key.unsafe_is_equal(key)) { - logger::log_event(*this, "match", key, -2); - // If we return here, then we return while pointing at the ':' that we just checked. - return true; - } - - // No match: skip the value and see if , or } is next - logger::log_event(*this, "no match", key, -2); - // The call to skip_child is meant to skip over the value corresponding to the key. - // After skip_child(), we are right before the next comma (',') or the final brace ('}'). - SIMDJSON_TRY( skip_child() ); // Skip the value entirely - // The has_next_field() advances the pointer and check that either ',' or '}' is found. - // It returns true if ',' is found, false otherwise. If anything other than ',' or '}' is found, - // then we are in error and we abort. - if ((error = has_next_field().get(has_value) )) { abandon(); return error; } - } - - // If the loop ended, we're out of fields to look at. - return false; -} - -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline simdjson_result value_iterator::find_field_unordered_raw(const std::string_view key) noexcept { - /** - * When find_field_unordered_raw is called, we can either be pointing at the - * first key, pointing outside (at the closing brace) or if a key was matched - * we can be either pointing right afterthe ':' right before the value (that we need skip), - * or we may have consumed the value and we might be at a comma or at the - * final brace (ready for a call to has_next_field()). - */ - error_code error; - bool has_value; - - // First, we scan from that point to the end. - // If we don't find a match, we may loop back around, and scan from the beginning to that point. - token_position search_start = _json_iter->position(); + // First, we scan from that point to the end. + // If we don't find a match, we may loop back around, and scan from the beginning to that point. + token_position search_start = _json_iter->position(); // We want to know whether we need to go back to the beginning. bool at_first = at_first_field(); @@ -107058,19 +111710,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -107079,6 +111735,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -107370,6 +112028,8 @@ simdjson_inline simdjson_result::simdjson_result( #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for lsx */ + + /* end file simdjson/generic/ondemand/amalgamated.h for lsx */ /* including simdjson/lsx/end.h: #include "simdjson/lsx/end.h" */ /* begin file simdjson/lsx/end.h */ @@ -107567,7 +112227,13 @@ simdjson_inline internal::value128 full_multiplication(uint64_t value1, uint64_t } // namespace lasx } // namespace simdjson +#ifndef SIMDJSON_SWAR_NUMBER_PARSING +#if SIMDJSON_IS_BIG_ENDIAN +#define SIMDJSON_SWAR_NUMBER_PARSING 0 +#else #define SIMDJSON_SWAR_NUMBER_PARSING 1 +#endif +#endif #endif // SIMDJSON_LASX_NUMBERPARSING_DEFS_H /* end file simdjson/lasx/numberparsing_defs.h */ @@ -108060,6 +112726,132 @@ class value_iterator; #endif // SIMDJSON_GENERIC_ONDEMAND_BASE_H /* end file simdjson/generic/ondemand/base.h for lasx */ +/* including simdjson/generic/ondemand/deserialize.h for lasx: #include "simdjson/generic/ondemand/deserialize.h" */ +/* begin file simdjson/generic/ondemand/deserialize.h for lasx */ +#if SIMDJSON_SUPPORTS_DESERIALIZATION + +#ifndef SIMDJSON_ONDEMAND_DESERIALIZE_H +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_ONDEMAND_DESERIALIZE_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +#include +namespace simdjson { + +namespace tag_invoke_fn_ns { +void tag_invoke(); + +struct tag_invoke_fn { + template + requires requires(Tag tag, Args &&...args) { + tag_invoke(std::forward(tag), std::forward(args)...); + } + constexpr auto operator()(Tag tag, Args &&...args) const + noexcept(noexcept(tag_invoke(std::forward(tag), + std::forward(args)...))) + -> decltype(tag_invoke(std::forward(tag), + std::forward(args)...)) { + return tag_invoke(std::forward(tag), std::forward(args)...); + } +}; +} // namespace tag_invoke_fn_ns + +inline namespace tag_invoke_ns { +inline constexpr tag_invoke_fn_ns::tag_invoke_fn tag_invoke = {}; +} // namespace tag_invoke_ns + +template +concept tag_invocable = requires(Tag tag, Args... args) { + tag_invoke(std::forward(tag), std::forward(args)...); +}; + +template +concept nothrow_tag_invocable = + tag_invocable && requires(Tag tag, Args... args) { + { + tag_invoke(std::forward(tag), std::forward(args)...) + } noexcept; + }; + +template +using tag_invoke_result = + std::invoke_result; + +template +using tag_invoke_result_t = + std::invoke_result_t; + +template using tag_t = std::decay_t; + + +struct deserialize_tag; + +/// These types are deserializable in a built-in way +template struct is_builtin_deserializable : std::false_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; +template <> struct is_builtin_deserializable : std::true_type {}; + +template +concept is_builtin_deserializable_v = is_builtin_deserializable::value; + +template +concept custom_deserializable = tag_invocable; + +template +concept deserializable = custom_deserializable || is_builtin_deserializable_v; + +template +concept nothrow_custom_deserializable = nothrow_tag_invocable; + +// built-in types are noexcept and if an error happens, the value simply gets ignored and the error is returned. +template +concept nothrow_deserializable = nothrow_custom_deserializable || is_builtin_deserializable_v; + +/// Deserialize Tag +inline constexpr struct deserialize_tag { + using value_type = lasx::ondemand::value; + using document_type = lasx::ondemand::document; + using document_reference_type = lasx::ondemand::document_reference; + + // Customization Point for value + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(value_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + // Customization Point for document reference + template + requires custom_deserializable + [[nodiscard]] constexpr /* error_code */ auto operator()(document_reference_type &object, T& output) const noexcept(nothrow_custom_deserializable) { + return tag_invoke(*this, object, output); + } + + +} deserialize{}; + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + +/* end file simdjson/generic/ondemand/deserialize.h for lasx */ /* including simdjson/generic/ondemand/value_iterator.h for lasx: #include "simdjson/generic/ondemand/value_iterator.h" */ /* begin file simdjson/generic/ondemand/value_iterator.h for lasx */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_H @@ -108189,7 +112981,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_object() noexcept; /** @@ -108199,7 +112992,8 @@ class value_iterator { * * @returns Whether the object had any fields (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_object() noexcept; @@ -108321,7 +113115,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_array() noexcept; /** @@ -108331,7 +113126,8 @@ class value_iterator { * * @returns Whether the array had any elements (returns false for empty). * @error INCOMPLETE_ARRAY_OR_OBJECT If there are no more tokens (implying the *parent* - * array or object is incomplete). + * array or object is incomplete). An INCOMPLETE_ARRAY_OR_OBJECT is an unrecoverable error that + * invalidates the document. */ simdjson_warn_unused simdjson_inline simdjson_result started_root_array() noexcept; @@ -108564,12 +113360,15 @@ struct simdjson_result : public lasx::implementa /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +#include + namespace simdjson { + namespace lasx { namespace ondemand { - /** * An ephemeral JSON value returned during iteration. It is only valid for as long as you do * not access more data in the JSON document. @@ -108594,16 +113393,21 @@ class value { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "The specified type is not default constructible."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } + /** * Get this value as the given type. * @@ -108613,7 +113417,38 @@ class value { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) noexcept; + template + simdjson_inline error_code get(T &out) +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + #if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif + } /** * Cast this JSON value to an array. @@ -108689,6 +113524,17 @@ class value { * Important: a value should be consumed once. Calling get_string() twice on the same value * is an error. * + * In some instances, you may want to allow replacement of invalid Unicode sequences. + * You may do so by passing the allow_replacement parameter as true. In the following + * example, the string "431924697b\udff0L\u0001Y" is not valid Unicode. By passing true + * to get_string, we allow the replacement of the invalid Unicode sequences with the Unicode + * replacement character (U+FFFD). + * + * simdjson::ondemand::parser parser; + * auto json = R"({"deviceId":"431924697b\udff0L\u0001Y"})"_padded; + * simdjson::ondemand::document doc = parser.iterate(json); + * auto view = doc["deviceId"].get_string(true); + * * @returns An UTF-8 string. The string is stored in the parser and will be invalidated the next * time it parses a document or when it is destroyed. * @returns INCORRECT_TYPE if the JSON value is not a string. @@ -108940,6 +113786,7 @@ class value { simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -109307,6 +114154,7 @@ struct simdjson_result : public lasx::implementation_simd simdjson_inline simdjson_result operator[](std::string_view key) noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) noexcept; */ simdjson_inline simdjson_result operator[](const char *key) noexcept; + simdjson_result operator[](int) noexcept = delete; /** * Get the type of this JSON value. @@ -110362,6 +115210,22 @@ class parser { * using a sanitizer that verifies that no uninitialized byte is read, then you should initialize the * SIMDJSON_PADDING bytes to avoid runtime warnings. * + * ### std::string references + * + * If you pass a mutable std::string reference (std::string&), the parser will seek to extend + * its capacity to SIMDJSON_PADDING bytes beyond the end of the string. + * + * Whenever you pass an std::string reference, the parser will access the bytes beyond the end of + * the string but before the end of the allocated memory (std::string::capacity()). + * If you are using a sanitizer that checks for reading uninitialized bytes or std::string's + * container-overflow checks, you may encounter sanitizer warnings. + * You can safely ignore these warnings. Or you can call simdjson::pad(std::string&) to pad the + * string with SIMDJSON_PADDING spaces: this function returns a simdjson::padding_string_view + * which can be be passed to the parser's iterate function: + * + * std::string json = R"({ "foo": 1 } { "foo": 2 } { "foo": 3 } )"; + * document doc = parser.iterate(simdjson::pad(json)); + * * @param json The JSON to parse. * @param len The length of the JSON. * @param capacity The number of bytes allocated in the JSON (must be at least len+SIMDJSON_PADDING). @@ -110556,8 +115420,12 @@ class parser { * behavior of the parser for future operations. */ bool threaded{true}; + #else + /** + * When SIMDJSON_THREADS_ENABLED is not defined, the parser instance cannot use threads. + */ + bool threaded{false}; #endif - /** * Unescape this JSON string, replacing \\ with \, \n with newline, etc. to a user-provided buffer. * The result must be valid UTF-8. @@ -110699,7 +115567,8 @@ class array { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. * * To check that an array is empty, it is more performant to use * the is_empty() method. @@ -110977,8 +115846,11 @@ struct simdjson_result : public lasx::implementa /* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + namespace simdjson { namespace lasx { namespace ondemand { @@ -111151,24 +116023,39 @@ class document { * @returns A value of the given type, parsed from the JSON. * @returns INCORRECT_TYPE If the JSON value is not the given type. */ - template simdjson_inline simdjson_result get() & noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; } - /** @overload template simdjson_result get() & noexcept */ - template simdjson_deprecated simdjson_inline simdjson_result get() && noexcept { - // Unless the simdjson library or the user provides an inline implementation, calling this method should - // immediately fail. - static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " - "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " - "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " - " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." - " You may also add support for custom types, see our documentation."); + /** + * @overload template simdjson_result get() & noexcept + * + * We disallow the use tag_invoke CPO on a moved document; it may create UB + * if user uses `ondemand::array` or `ondemand::object` in their custom type. + * + * The member function is still remains specialize-able for compatibility + * reasons, but we completely disallow its use when a tag_invoke customization + * is provided. + */ + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); } /** @@ -111182,7 +116069,39 @@ class document { * @returns INCORRECT_TYPE If the JSON value is not an object. * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. */ - template simdjson_inline error_code get(T &out) & noexcept; + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + /** @overload template error_code get(T &out) & noexcept */ template simdjson_deprecated simdjson_inline error_code get(T &out) && noexcept; @@ -111284,7 +116203,8 @@ class document { * calling this function, if successful, the array is 'rewinded' at its * beginning as if it had never been accessed. If the JSON is malformed (e.g., * there is a missing comma), then an error is returned and it is no longer - * safe to continue. + * safe to continue. Note that count_elements() does not validate the JSON values, + * only the structure of the array. */ simdjson_inline simdjson_result count_elements() & noexcept; /** @@ -111396,6 +116316,7 @@ class document { simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; /** @overload simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; */ simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; /** * Get the type of this JSON value. It does not validate or consume the value. @@ -111664,6 +116585,11 @@ class document { /** * A document_reference is a thin wrapper around a document reference instance. + * The document_reference instances are used primarily/solely for streams of JSON + * documents. They differ from document instances when parsing a scalar value + * (a document that is not an array or an object). In the case of a document, + * we expect the document to be fully consumed. In the case of a document_reference, + * we allow trailing content. */ class document_reference { public: @@ -111689,7 +116615,77 @@ class document_reference { simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; - template simdjson_inline simdjson_result get() & noexcept; + template + simdjson_inline simdjson_result get() & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(std::is_default_constructible::value, "Cannot initialize the specified type."); + T out{}; + SIMDJSON_TRY(get(out)); + return out; + } + template + simdjson_inline simdjson_result get() && +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { + static_assert(!std::is_same::value && !std::is_same::value, "You should never hold either an ondemand::array or ondemand::object without a corresponding ondemand::document_reference being alive; that would be Undefined Behaviour."); + return static_cast(*this).get(); + } + + /** + * Get this value as the given type. + * + * Supported types: object, array, raw_json_string, string_view, uint64_t, int64_t, double, bool, value + * + * Be mindful that the document instance must remain in scope while you are accessing object, array and value instances. + * + * @param out This is set to a value of the given type, parsed from the JSON. If there is an error, this may not be initialized. + * @returns INCORRECT_TYPE If the JSON value is not an object. + * @returns SUCCESS If the parse succeeded and the out parameter was set to the value. + */ + template + simdjson_inline error_code get(T &out) & +#if SIMDJSON_SUPPORTS_DESERIALIZATION + noexcept(custom_deserializable ? nothrow_custom_deserializable : true) +#else + noexcept +#endif + { +#if SIMDJSON_SUPPORTS_DESERIALIZATION + if constexpr (custom_deserializable) { + return deserialize(*this, out); + } else { + static_assert(!sizeof(T), "The get method with type T is not implemented by the simdjson library. " + "And you do not seem to have added support for it. Indeed, we have that " + "simdjson::custom_deserializable is false and the type T is not a default type " + "such as ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, or bool."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; + } +#else // SIMDJSON_SUPPORTS_DESERIALIZATION + // Unless the simdjson library or the user provides an inline implementation, calling this method should + // immediately fail. + static_assert(!sizeof(T), "The get method with given type is not implemented by the simdjson library. " + "The supported types are ondemand::object, ondemand::array, raw_json_string, std::string_view, uint64_t, " + "int64_t, double, and bool. We recommend you use get_double(), get_bool(), get_uint64(), get_int64(), " + " get_object(), get_array(), get_raw_json_string(), or get_string() instead of the get template." + " You may also add support for custom types, see our documentation."); + static_cast(out); // to get rid of unused errors + return UNINITIALIZED; +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION + } + + /** @overload template error_code get(T &out) & noexcept */ + template simdjson_inline error_code get(T &out) && noexcept; simdjson_inline simdjson_result raw_json() noexcept; simdjson_inline operator document&() const noexcept; #if SIMDJSON_EXCEPTIONS @@ -111714,6 +116710,7 @@ class document_reference { simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; @@ -111792,6 +116789,7 @@ struct simdjson_result : public lasx::implementation_s simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -111841,8 +116839,14 @@ struct simdjson_result : public lasx::implem simdjson_inline simdjson_result get_bool() noexcept; simdjson_inline simdjson_result get_value() noexcept; simdjson_inline simdjson_result is_null() noexcept; + + template simdjson_inline simdjson_result get() & noexcept; + template simdjson_inline simdjson_result get() && noexcept; + + template simdjson_inline error_code get(T &out) & noexcept; + template simdjson_inline error_code get(T &out) && noexcept; #if SIMDJSON_EXCEPTIONS - template ::value == false>::type> + template explicit simdjson_inline operator T() noexcept(false); simdjson_inline operator lasx::ondemand::array() & noexcept(false); simdjson_inline operator lasx::ondemand::object() & noexcept(false); @@ -111863,6 +116867,7 @@ struct simdjson_result : public lasx::implem simdjson_inline simdjson_result find_field(const char *key) & noexcept; simdjson_inline simdjson_result operator[](std::string_view key) & noexcept; simdjson_inline simdjson_result operator[](const char *key) & noexcept; + simdjson_result operator[](int) & noexcept = delete; simdjson_inline simdjson_result find_field_unordered(std::string_view key) & noexcept; simdjson_inline simdjson_result find_field_unordered(const char *key) & noexcept; simdjson_inline simdjson_result type() noexcept; @@ -112793,6 +117798,220 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result +#include + +namespace simdjson { +template +constexpr bool require_custom_serialization = false; + +////////////////////////////// +// Number deserialization +////////////////////////////// + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + uint64_t x; + SIMDJSON_TRY(val.get_uint64().get(x)); + if (x > (limits::max)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + double x; + SIMDJSON_TRY(val.get_double().get(x)); + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, auto &val, T &out) noexcept { + using limits = std::numeric_limits; + + int64_t x; + SIMDJSON_TRY(val.get_int64().get(x)); + if (x > (limits::max)() || x < (limits::min)()) { + return NUMBER_OUT_OF_RANGE; + } + out = static_cast(x); + return SUCCESS; +} + +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(std::is_nothrow_constructible_v) { + std::string_view str; + SIMDJSON_TRY(val.get_string().get(str)); + out = T{str}; + return SUCCESS; +} + + +/** + * STL containers have several constructors including one that takes a single + * size argument. Thus, some compilers (Visual Studio) will not be able to + * disambiguate between the size and container constructor. Users should + * explicitly specify the type of the container as needed: e.g., + * doc.get>(). + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::value_type; + static_assert( + deserializable, + "The specified type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the container must default constructible."); + + lasx::ondemand::array arr; + SIMDJSON_TRY(val.get_array().get(arr)); + for (auto v : arr) { + if constexpr (concepts::returns_reference) { + if (auto const err = v.get().get(concepts::emplace_one(out)); + err) { + // If an error occurs, the empty element that we just inserted gets + // removed. We're not using a temp variable because if T is a heavy + // type, we want the valid path to be the fast path and the slow path be + // the path that has errors in it. + if constexpr (requires { out.pop_back(); }) { + static_cast(out.pop_back()); + } + return err; + } + } else { + value_type temp; + if (auto const err = v.get().get(temp); err) { + return err; + } + concepts::emplace_one(out, std::move(temp)); + } + } + return SUCCESS; +} + + +/** + * We want to support std::map and std::unordered_map but only for + * string-keyed types. + */ + template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(false) { + using value_type = typename std::remove_cvref_t::mapped_type; + static_assert( + deserializable, + "The specified value type inside the container must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified value type inside the container must default constructible."); + lasx::ondemand::object obj; + SIMDJSON_TRY(val.get_object().get(obj)); + for (auto field : obj) { + std::string_view key; + SIMDJSON_TRY(field.unescaped_key().get(key)); + value_type this_value; + SIMDJSON_TRY(field.value().get().get(this_value)); + [[maybe_unused]] std::pair result = out.emplace(key, this_value); + // unclear what to do if the key already exists + // if (result.second == false) { + // // key already exists + // } + } + (void)out; + return SUCCESS; +} + + + + +/** + * This CPO (Customization Point Object) will help deserialize into + * smart pointers. + * + * If constructing T is nothrow, this conversion should be nothrow as well since + * we return MEMALLOC if we're not able to allocate memory instead of throwing + * the error message. + * + * @tparam T The type inside the smart pointer + * @tparam ValT document/value type + * @param val document/value + * @param out a reference to the smart pointer + * @return status of the conversion + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::element_type, ValT>) { + using element_type = typename std::remove_cvref_t::element_type; + + // For better error messages, don't use these as constraints on + // the tag_invoke CPO. + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + auto ptr = new (std::nothrow) element_type(); + if (ptr == nullptr) { + return MEMALLOC; + } + SIMDJSON_TRY(val.template get(*ptr)); + out.reset(ptr); + return SUCCESS; +} + +/** + * This CPO (Customization Point Object) will help deserialize into optional types. + */ +template + requires(!require_custom_serialization) +error_code tag_invoke(deserialize_tag, ValT &val, T &out) noexcept(nothrow_deserializable::value_type, ValT>) { + using value_type = typename std::remove_cvref_t::value_type; + + static_assert( + deserializable, + "The specified type inside the unique_ptr must itself be deserializable"); + static_assert( + std::is_default_constructible_v, + "The specified type inside the unique_ptr must default constructible."); + + if (!out) { + out.emplace(); + } + SIMDJSON_TRY(val.template get(out.value())); + return SUCCESS; +} + +} // namespace simdjson + +#endif // SIMDJSON_ONDEMAND_DESERIALIZE_H +#endif // SIMDJSON_SUPPORTS_DESERIALIZATION +/* end file simdjson/generic/ondemand/std_deserialize.h for lasx */ + // Inline definitions /* including simdjson/generic/ondemand/array-inl.h for lasx: #include "simdjson/generic/ondemand/array-inl.h" */ /* begin file simdjson/generic/ondemand/array-inl.h for lasx */ @@ -112800,6 +118019,7 @@ inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result array::at_pointer(std::string_view json_pointer) n return child; } -inline std::string json_path_to_pointer_conversion(std::string_view json_path) { - if (json_path.empty() || (json_path.front() != '.' && - json_path.front() != '[')) { - return "-1"; // This is just a sentinel value, the caller should check for this and return an error. - } - - std::string result; - // Reserve space to reduce allocations, adjusting for potential increases due - // to escaping. - result.reserve(json_path.size() * 2); - - size_t i = 0; - - while (i < json_path.length()) { - if (json_path[i] == '.') { - result += '/'; - } else if (json_path[i] == '[') { - result += '/'; - ++i; // Move past the '[' - while (i < json_path.length() && json_path[i] != ']') { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - ++i; - } - if (i == json_path.length() || json_path[i] != ']') { - return "-1"; // Using sentinel value that will be handled as an error by the caller. - } - } else { - if (json_path[i] == '~') { - result += "~0"; - } else if (json_path[i] == '/') { - result += "~1"; - } else { - result += json_path[i]; - } - } - ++i; - } - - return result; -} - inline simdjson_result array::at_path(std::string_view json_path) noexcept { auto json_pointer = json_path_to_pointer_conversion(json_path); if (json_pointer == "-1") { return INVALID_JSON_POINTER; } @@ -113161,313 +118334,276 @@ simdjson_inline simdjson_result &simdjson_result #endif // SIMDJSON_GENERIC_ONDEMAND_ARRAY_ITERATOR_INL_H /* end file simdjson/generic/ondemand/array_iterator-inl.h for lasx */ -/* including simdjson/generic/ondemand/document-inl.h for lasx: #include "simdjson/generic/ondemand/document-inl.h" */ -/* begin file simdjson/generic/ondemand/document-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H +/* including simdjson/generic/ondemand/value-inl.h for lasx: #include "simdjson/generic/ondemand/value-inl.h" */ +/* begin file simdjson/generic/ondemand/value-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lasx { namespace ondemand { -simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept - : iter{std::forward(_iter)} +simdjson_inline value::value(const value_iterator &_iter) noexcept + : iter{_iter} { - logger::log_start_value(iter, "document"); } - -simdjson_inline document document::start(json_iterator &&iter) noexcept { - return document(std::forward(iter)); +simdjson_inline value value::start(const value_iterator &iter) noexcept { + return iter; } - -inline void document::rewind() noexcept { - iter.rewind(); +simdjson_inline value value::resume(const value_iterator &iter) noexcept { + return iter; } -inline std::string document::to_debug_string() noexcept { - return iter.to_string(); +simdjson_inline simdjson_result value::get_array() noexcept { + return array::start(iter); } - -inline simdjson_result document::current_location() const noexcept { - return iter.current_location(); +simdjson_inline simdjson_result value::get_object() noexcept { + return object::start(iter); } - -inline int32_t document::current_depth() const noexcept { - return iter.depth(); +simdjson_inline simdjson_result value::start_or_resume_object() noexcept { + if (iter.at_start()) { + return get_object(); + } else { + return object::resume(iter); + } } -inline bool document::at_end() const noexcept { - return iter.at_end(); +simdjson_inline simdjson_result value::get_raw_json_string() noexcept { + return iter.get_raw_json_string(); } - - -inline bool document::is_alive() noexcept { - return iter.is_alive(); +simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { + return iter.get_string(allow_replacement); } -simdjson_inline value_iterator document::resume_value_iterator() noexcept { - return value_iterator(&iter, 1, iter.root_position()); +template +simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { + return iter.get_string(receiver, allow_replacement); } -simdjson_inline value_iterator document::get_root_value_iterator() noexcept { - return resume_value_iterator(); +simdjson_inline simdjson_result value::get_wobbly_string() noexcept { + return iter.get_wobbly_string(); } -simdjson_inline simdjson_result document::start_or_resume_object() noexcept { - if (iter.at_root()) { - return get_object(); - } else { - return object::resume(resume_value_iterator()); - } +simdjson_inline simdjson_result value::get_double() noexcept { + return iter.get_double(); } -simdjson_inline simdjson_result document::get_value() noexcept { - // Make sure we start any arrays or objects before returning, so that start_root_() - // gets called. - - // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether - // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. -#if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } -#endif - // assert_at_root() serves two purposes: in Debug mode, whether or not - // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of - // the document (this will typically be redundant). In release mode, it generates - // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. - iter.assert_at_root(); - switch (*iter.peek()) { - case '[': { - // The following lines check that the document ends with ]. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_array(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - case '{': { - // The following lines would check that the document ends with }. - auto value_iterator = get_root_value_iterator(); - auto error = value_iterator.check_root_object(); - if(error) { return error; } - return value(get_root_value_iterator()); - } - default: - // Unfortunately, scalar documents are a special case in simdjson and they cannot - // be safely converted to value instances. - return SCALAR_DOCUMENT_AS_VALUE; - } +simdjson_inline simdjson_result value::get_double_in_string() noexcept { + return iter.get_double_in_string(); } -simdjson_inline simdjson_result document::get_array() & noexcept { - auto value = get_root_value_iterator(); - return array::start_root(value); +simdjson_inline simdjson_result value::get_uint64() noexcept { + return iter.get_uint64(); } -simdjson_inline simdjson_result document::get_object() & noexcept { - auto value = get_root_value_iterator(); - return object::start_root(value); +simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { + return iter.get_uint64_in_string(); } - -/** - * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. We want to disallow trailing - * content. - * Thus, in several implementations below, we pass a 'true' parameter value to - * a get_root_value_iterator() method: this indicates that we disallow trailing content. - */ - -simdjson_inline simdjson_result document::get_uint64() noexcept { - return get_root_value_iterator().get_root_uint64(true); +simdjson_inline simdjson_result value::get_int64() noexcept { + return iter.get_int64(); } -simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { - return get_root_value_iterator().get_root_uint64_in_string(true); +simdjson_inline simdjson_result value::get_int64_in_string() noexcept { + return iter.get_int64_in_string(); } -simdjson_inline simdjson_result document::get_int64() noexcept { - return get_root_value_iterator().get_root_int64(true); +simdjson_inline simdjson_result value::get_bool() noexcept { + return iter.get_bool(); } -simdjson_inline simdjson_result document::get_int64_in_string() noexcept { - return get_root_value_iterator().get_root_int64_in_string(true); +simdjson_inline simdjson_result value::is_null() noexcept { + return iter.is_null(); } -simdjson_inline simdjson_result document::get_double() noexcept { - return get_root_value_iterator().get_root_double(true); + +template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } + + +template<> simdjson_inline error_code value::get(array& out) noexcept { return get_array().get(out); } +template<> simdjson_inline error_code value::get(object& out) noexcept { return get_object().get(out); } +template<> simdjson_inline error_code value::get(raw_json_string& out) noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code value::get(std::string_view& out) noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code value::get(number& out) noexcept { return get_number().get(out); } +template<> simdjson_inline error_code value::get(double& out) noexcept { return get_double().get(out); } +template<> simdjson_inline error_code value::get(uint64_t& out) noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code value::get(int64_t& out) noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code value::get(bool& out) noexcept { return get_bool().get(out); } + +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline value::operator T() noexcept(false) { + return get(); } -simdjson_inline simdjson_result document::get_double_in_string() noexcept { - return get_root_value_iterator().get_root_double_in_string(true); +simdjson_inline value::operator array() noexcept(false) { + return get_array(); } -simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(true, allow_replacement); +simdjson_inline value::operator object() noexcept(false) { + return get_object(); } -template -simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { - return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +simdjson_inline value::operator uint64_t() noexcept(false) { + return get_uint64(); } -simdjson_inline simdjson_result document::get_wobbly_string() noexcept { - return get_root_value_iterator().get_root_wobbly_string(true); +simdjson_inline value::operator int64_t() noexcept(false) { + return get_int64(); } -simdjson_inline simdjson_result document::get_raw_json_string() noexcept { - return get_root_value_iterator().get_root_raw_json_string(true); +simdjson_inline value::operator double() noexcept(false) { + return get_double(); } -simdjson_inline simdjson_result document::get_bool() noexcept { - return get_root_value_iterator().get_root_bool(true); +simdjson_inline value::operator std::string_view() noexcept(false) { + return get_string(false); } -simdjson_inline simdjson_result document::is_null() noexcept { - return get_root_value_iterator().is_root_null(true); +simdjson_inline value::operator raw_json_string() noexcept(false) { + return get_raw_json_string(); } +simdjson_inline value::operator bool() noexcept(false) { + return get_bool(); +} +#endif -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } - -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } -template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } - -template simdjson_inline error_code document::get(T &out) & noexcept { - return get().get(out); +simdjson_inline simdjson_result value::begin() & noexcept { + return get_array().begin(); } -template simdjson_deprecated simdjson_inline error_code document::get(T &out) && noexcept { - return std::forward(*this).get().get(out); +simdjson_inline simdjson_result value::end() & noexcept { + return {}; } - -#if SIMDJSON_EXCEPTIONS -template -simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } -template -simdjson_inline document::operator T() & noexcept(false) { return get(); } -simdjson_inline document::operator array() & noexcept(false) { return get_array(); } -simdjson_inline document::operator object() & noexcept(false) { return get_object(); } -simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document::operator double() noexcept(false) { return get_double(); } -simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } -simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document::operator value() noexcept(false) { return get_value(); } - -#endif -simdjson_inline simdjson_result document::count_elements() & noexcept { +simdjson_inline simdjson_result value::count_elements() & noexcept { + simdjson_result answer; auto a = get_array(); - simdjson_result answer = a.count_elements(); - /* If there was an array, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_elements(); + // count_elements leaves you pointing inside the array, at the first element. + // We need to move back so that the user can create a new array (which requires that + // we point at '['). + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::count_fields() & noexcept { +simdjson_inline simdjson_result value::count_fields() & noexcept { + simdjson_result answer; auto a = get_object(); - simdjson_result answer = a.count_fields(); - /* If there was an object, we are now left pointing at its first element. */ - if(answer.error() == SUCCESS) { rewind(); } + answer = a.count_fields(); + iter.move_at_start(); return answer; } -simdjson_inline simdjson_result document::at(size_t index) & noexcept { +simdjson_inline simdjson_result value::at(size_t index) noexcept { auto a = get_array(); return a.at(index); } -simdjson_inline simdjson_result document::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result document::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field(const char *key) noexcept { return start_or_resume_object().find_field(key); } -simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { return start_or_resume_object().find_field_unordered(key); } -simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result value::operator[](const char *key) noexcept { return start_or_resume_object()[key]; } -simdjson_inline error_code document::consume() noexcept { - auto error = iter.skip_child(0); - if(error) { iter.abandon(); } - return error; -} - -simdjson_inline simdjson_result document::raw_json() noexcept { - auto _iter = get_root_value_iterator(); - const uint8_t * starting_point{_iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - // After 'consume()', we could be left pointing just beyond the document, but that - // is ok because we are not going to dereference the final pointer position, we just - // use it to compute the length in bytes. - const uint8_t * final_point{iter.unsafe_pointer()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); -} - -simdjson_inline simdjson_result document::type() noexcept { - return get_root_value_iterator().type(); +simdjson_inline simdjson_result value::type() noexcept { + return iter.type(); } -simdjson_inline simdjson_result document::is_scalar() noexcept { +simdjson_inline simdjson_result value::is_scalar() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return ! ((this_type == json_type::array) || (this_type == json_type::object)); } -simdjson_inline simdjson_result document::is_string() noexcept { +simdjson_inline simdjson_result value::is_string() noexcept { json_type this_type; auto error = type().get(this_type); if(error) { return error; } return (this_type == json_type::string); } -simdjson_inline bool document::is_negative() noexcept { - return get_root_value_iterator().is_root_negative(); + +simdjson_inline bool value::is_negative() noexcept { + return iter.is_negative(); } -simdjson_inline simdjson_result document::is_integer() noexcept { - return get_root_value_iterator().is_root_integer(true); +simdjson_inline simdjson_result value::is_integer() noexcept { + return iter.is_integer(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { + return iter.get_number_type(); +} +simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { + return iter.get_number(); } -simdjson_inline simdjson_result document::get_number_type() noexcept { - return get_root_value_iterator().get_root_number_type(true); +simdjson_inline std::string_view value::raw_json_token() noexcept { + return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); } -simdjson_inline simdjson_result document::get_number() noexcept { - return get_root_value_iterator().get_root_number(true); +simdjson_inline simdjson_result value::raw_json() noexcept { + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: { + ondemand::array array; + SIMDJSON_TRY(get_array().get(array)); + return array.raw_json(); + } + case json_type::object: { + ondemand::object object; + SIMDJSON_TRY(get_object().get(object)); + return object.raw_json(); + } + default: + return raw_json_token(); + } } +simdjson_inline simdjson_result value::current_location() noexcept { + return iter.json_iter().current_location(); +} -simdjson_inline simdjson_result document::raw_json_token() noexcept { - auto _iter = get_root_value_iterator(); - return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +simdjson_inline int32_t value::current_depth() const noexcept{ + return iter.json_iter().depth(); } -simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_pointer.empty()) { - return this->get_value(); +inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { + if (simdjson_unlikely(json_pointer.empty())) { // can't be + return false; + } + if (simdjson_unlikely(json_pointer[0] != '/')) { + return false; + } + size_t escape = json_pointer.find('~'); + if (escape == std::string_view::npos) { + return true; + } + if (escape == json_pointer.size() - 1) { + return false; } + if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { + return false; + } + return true; +} + +simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) @@ -113477,15 +118613,15 @@ simdjson_inline simdjson_result document::at_pointer(std::string_view jso case json_type::object: return (*this).get_object().at_pointer(json_pointer); default: + // a non-empty string can be invalid, or accessing a primitive (issue 2154) + if (is_pointer_well_formed(json_pointer)) { + return NO_SUCH_FIELD; + } return INVALID_JSON_POINTER; } } -simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { - rewind(); // Rewind the document each time at_pointer is called - if (json_path.empty()) { - return this->get_value(); - } +simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { json_type t; SIMDJSON_TRY(type().get(t)); switch (t) { @@ -113504,417 +118640,1022 @@ simdjson_inline simdjson_result document::at_path(std::string_view json_p namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - lasx::ondemand::document &&value +simdjson_inline simdjson_result::simdjson_result( + lasx::ondemand::value &&value ) noexcept : - implementation_simdjson_result_base( - std::forward(value) + implementation_simdjson_result_base( + std::forward(value) ) { } -simdjson_inline simdjson_result::simdjson_result( +simdjson_inline simdjson_result::simdjson_result( error_code error ) noexcept : - implementation_simdjson_result_base( - error - ) + implementation_simdjson_result_base(error) { } -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { - if (error()) { return error(); } - first.rewind(); - return SUCCESS; -} -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + if (error()) { return error(); } return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { if (error()) { return error(); } - return first.find_field_unordered(key); + return first.find_field(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { if (error()) { return error(); } - return first[key]; + return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { if (error()) { return error(); } - return first.find_field(key); + return first[key]; } -simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + +simdjson_inline simdjson_result simdjson_result::get_array() noexcept { if (error()) { return error(); } return first.get_array(); } -simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { +simdjson_inline simdjson_result simdjson_result::get_object() noexcept { if (error()) { return error(); } return first.get_object(); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { if (error()) { return error(); } return first.get_uint64(); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { if (error()) { return error(); } return first.get_uint64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { if (error()) { return error(); } return first.get_int64(); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { if (error()) { return error(); } return first.get_int64_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { if (error()) { return error(); } return first.get_double(); } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { if (error()) { return error(); } return first.get_double_in_string(); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(allow_replacement); } template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { if (error()) { return error(); } return first.get_string(receiver, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { if (error()) { return error(); } return first.get_wobbly_string(); } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { if (error()) { return error(); } return first.get_raw_json_string(); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { if (error()) { return error(); } return first.get_bool(); } -simdjson_inline simdjson_result simdjson_result::get_value() noexcept { - if (error()) { return error(); } - return first.get_value(); -} -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { if (error()) { return error(); } return first.is_null(); } -template -simdjson_inline simdjson_result simdjson_result::get() & noexcept { +template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::value &out) noexcept { if (error()) { return error(); } - return first.get(); + out = first; + return SUCCESS; } -template -simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + +template simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - return std::forward(first).get(); + return first.get(); } -template -simdjson_inline error_code simdjson_result::get(T &out) & noexcept { +template simdjson_inline error_code simdjson_result::get(T &out) noexcept { if (error()) { return error(); } return first.get(out); } -template -simdjson_inline error_code simdjson_result::get(T &out) && noexcept { - if (error()) { return error(); } - return std::forward(first).get(out); -} -template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; -template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { - if (error()) { return error(); } - return std::forward(first); -} -template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::document &out) & noexcept = delete; -template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::document &out) && noexcept { +template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { if (error()) { return error(); } - out = std::forward(first); - return SUCCESS; + return std::move(first); } -simdjson_inline simdjson_result simdjson_result::type() noexcept { +simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); } - -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { if (error()) { return error(); } return first.is_scalar(); } - -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { if (error()) { return error(); } return first.is_string(); } - -simdjson_inline bool simdjson_result::is_negative() noexcept { +simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); } - -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { if (error()) { return error(); } return first.is_integer(); } - -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { if (error()) { return error(); } return first.get_number_type(); } - -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { if (error()) { return error(); } return first.get_number(); } - - #if SIMDJSON_EXCEPTIONS -template ::value == false>::type> -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; -} -simdjson_inline simdjson_result::operator lasx::ondemand::array() & noexcept(false) { +template +simdjson_inline simdjson_result::operator T() noexcept(false) { if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } -simdjson_inline simdjson_result::operator lasx::ondemand::object() & noexcept(false) { +simdjson_inline simdjson_result::operator lasx::ondemand::array() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { +simdjson_inline simdjson_result::operator lasx::ondemand::object() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator double() noexcept(false) { +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { +simdjson_inline simdjson_result::operator double() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator lasx::ondemand::raw_json_string() noexcept(false) { +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { +simdjson_inline simdjson_result::operator lasx::ondemand::raw_json_string() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } -simdjson_inline simdjson_result::operator lasx::ondemand::value() noexcept(false) { +simdjson_inline simdjson_result::operator bool() noexcept(false) { if (error()) { throw simdjson_error(error()); } return first; } #endif - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { if (error()) { return error(); } - return first.current_location(); + return first.raw_json_token(); } -simdjson_inline bool simdjson_result::at_end() const noexcept { +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.at_end(); + return first.raw_json(); } - -simdjson_inline int32_t simdjson_result::current_depth() const noexcept { +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { if (error()) { return error(); } - return first.current_depth(); + return first.current_location(); } -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { +simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { if (error()) { return error(); } - return first.raw_json_token(); + return first.current_depth(); } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_pointer( + std::string_view json_pointer) noexcept { + if (error()) { + return error(); + } return first.at_pointer(json_pointer); } -simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { - if (error()) { return error(); } +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); + } return first.at_path(json_path); } } // namespace simdjson +#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +/* end file simdjson/generic/ondemand/value-inl.h for lasx */ +/* including simdjson/generic/ondemand/document-inl.h for lasx: #include "simdjson/generic/ondemand/document-inl.h" */ +/* begin file simdjson/generic/ondemand/document-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/deserialize.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lasx { namespace ondemand { -simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} -simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} -simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } -simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } -simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +simdjson_inline document::document(ondemand::json_iterator &&_iter) noexcept + : iter{std::forward(_iter)} +{ + logger::log_start_value(iter, "document"); +} + +simdjson_inline document document::start(json_iterator &&iter) noexcept { + return document(std::forward(iter)); +} + +inline void document::rewind() noexcept { + iter.rewind(); +} + +inline std::string document::to_debug_string() noexcept { + return iter.to_string(); +} + +inline simdjson_result document::current_location() const noexcept { + return iter.current_location(); +} + +inline int32_t document::current_depth() const noexcept { + return iter.depth(); +} + +inline bool document::at_end() const noexcept { + return iter.at_end(); +} + + +inline bool document::is_alive() noexcept { + return iter.is_alive(); +} +simdjson_inline value_iterator document::resume_value_iterator() noexcept { + return value_iterator(&iter, 1, iter.root_position()); +} +simdjson_inline value_iterator document::get_root_value_iterator() noexcept { + return resume_value_iterator(); +} +simdjson_inline simdjson_result document::start_or_resume_object() noexcept { + if (iter.at_root()) { + return get_object(); + } else { + return object::resume(resume_value_iterator()); + } +} +simdjson_inline simdjson_result document::get_value() noexcept { + // Make sure we start any arrays or objects before returning, so that start_root_() + // gets called. + + // It is the convention throughout the code that the macro `SIMDJSON_DEVELOPMENT_CHECKS` determines whether + // we check for OUT_OF_ORDER_ITERATION. Proper on::demand code should never trigger this error. +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.at_root()) { return OUT_OF_ORDER_ITERATION; } +#endif + // assert_at_root() serves two purposes: in Debug mode, whether or not + // SIMDJSON_DEVELOPMENT_CHECKS is set or not, it checks that we are at the root of + // the document (this will typically be redundant). In release mode, it generates + // SIMDJSON_ASSUME statements to allow the compiler to make assumptions. + iter.assert_at_root(); + switch (*iter.peek()) { + case '[': { + // The following lines check that the document ends with ]. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_array(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + case '{': { + // The following lines would check that the document ends with }. + auto value_iterator = get_root_value_iterator(); + auto error = value_iterator.check_root_object(); + if(error) { return error; } + return value(get_root_value_iterator()); + } + default: + // Unfortunately, scalar documents are a special case in simdjson and they cannot + // be safely converted to value instances. + return SCALAR_DOCUMENT_AS_VALUE; + } +} +simdjson_inline simdjson_result document::get_array() & noexcept { + auto value = get_root_value_iterator(); + return array::start_root(value); +} +simdjson_inline simdjson_result document::get_object() & noexcept { + auto value = get_root_value_iterator(); + return object::start_root(value); +} + /** - * The document_reference instances are used primarily/solely for streams of JSON - * documents. * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should - * give an error, so we check for trailing content. - * - * However, for streams of JSON documents, we want to be able to start from - * "321" "321" "321" - * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() - * successfully each time. - * - * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: - * this indicates that we allow trailing content. + * give an error, so we check for trailing content. We want to disallow trailing + * content. + * Thus, in several implementations below, we pass a 'true' parameter value to + * a get_root_value_iterator() method: this indicates that we disallow trailing content. */ -simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } -simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } -simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } -simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } -simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } + +simdjson_inline simdjson_result document::get_uint64() noexcept { + return get_root_value_iterator().get_root_uint64(true); +} +simdjson_inline simdjson_result document::get_uint64_in_string() noexcept { + return get_root_value_iterator().get_root_uint64_in_string(true); +} +simdjson_inline simdjson_result document::get_int64() noexcept { + return get_root_value_iterator().get_root_int64(true); +} +simdjson_inline simdjson_result document::get_int64_in_string() noexcept { + return get_root_value_iterator().get_root_int64_in_string(true); +} +simdjson_inline simdjson_result document::get_double() noexcept { + return get_root_value_iterator().get_root_double(true); +} +simdjson_inline simdjson_result document::get_double_in_string() noexcept { + return get_root_value_iterator().get_root_double_in_string(true); +} +simdjson_inline simdjson_result document::get_string(bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(true, allow_replacement); +} template -simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } -simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } -simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } -simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } -simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } -simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } -template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +simdjson_inline error_code document::get_string(string_type& receiver, bool allow_replacement) noexcept { + return get_root_value_iterator().get_root_string(receiver, true, allow_replacement); +} +simdjson_inline simdjson_result document::get_wobbly_string() noexcept { + return get_root_value_iterator().get_root_wobbly_string(true); +} +simdjson_inline simdjson_result document::get_raw_json_string() noexcept { + return get_root_value_iterator().get_root_raw_json_string(true); +} +simdjson_inline simdjson_result document::get_bool() noexcept { + return get_root_value_iterator().get_root_bool(true); +} +simdjson_inline simdjson_result document::is_null() noexcept { + return get_root_value_iterator().is_root_null(true); +} + +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document::get() & noexcept { return get_value(); } + +template<> simdjson_inline error_code document::get(array& out) & noexcept { return get_array().get(out); } +template<> simdjson_inline error_code document::get(object& out) & noexcept { return get_object().get(out); } +template<> simdjson_inline error_code document::get(raw_json_string& out) & noexcept { return get_raw_json_string().get(out); } +template<> simdjson_inline error_code document::get(std::string_view& out) & noexcept { return get_string(false).get(out); } +template<> simdjson_inline error_code document::get(double& out) & noexcept { return get_double().get(out); } +template<> simdjson_inline error_code document::get(uint64_t& out) & noexcept { return get_uint64().get(out); } +template<> simdjson_inline error_code document::get(int64_t& out) & noexcept { return get_int64().get(out); } +template<> simdjson_inline error_code document::get(bool& out) & noexcept { return get_bool().get(out); } +template<> simdjson_inline error_code document::get(value& out) & noexcept { return get_value().get(out); } + +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_raw_json_string(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_string(false); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_double(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_uint64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_int64(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return std::forward(*this).get_bool(); } +template<> simdjson_deprecated simdjson_inline simdjson_result document::get() && noexcept { return get_value(); } + #if SIMDJSON_EXCEPTIONS template -simdjson_inline document_reference::operator T() noexcept(false) { return get(); } -simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } -simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } -simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } -simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } -simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } -simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } -simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } -simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } -simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +simdjson_deprecated simdjson_inline document::operator T() && noexcept(false) { return get(); } +template +simdjson_inline document::operator T() & noexcept(false) { return get(); } +simdjson_inline document::operator array() & noexcept(false) { return get_array(); } +simdjson_inline document::operator object() & noexcept(false) { return get_object(); } +simdjson_inline document::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document::operator double() noexcept(false) { return get_double(); } +simdjson_inline document::operator std::string_view() noexcept(false) { return get_string(false); } +simdjson_inline document::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document::operator value() noexcept(false) { return get_value(); } + #endif -simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } -simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } -simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } -simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } -simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } -simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } -simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } -simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } -simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } -simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } -simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } -simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } -simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } -simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } -simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } -simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } -simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } -simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } -simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } -simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } -simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} -simdjson_inline document_reference::operator document&() const noexcept { return *doc; } +simdjson_inline simdjson_result document::count_elements() & noexcept { + auto a = get_array(); + simdjson_result answer = a.count_elements(); + /* If there was an array, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::count_fields() & noexcept { + auto a = get_object(); + simdjson_result answer = a.count_fields(); + /* If there was an object, we are now left pointing at its first element. */ + if(answer.error() == SUCCESS) { rewind(); } + return answer; +} +simdjson_inline simdjson_result document::at(size_t index) & noexcept { + auto a = get_array(); + return a.at(index); +} +simdjson_inline simdjson_result document::begin() & noexcept { + return get_array().begin(); +} +simdjson_inline simdjson_result document::end() & noexcept { + return {}; +} + +simdjson_inline simdjson_result document::find_field(std::string_view key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field(const char *key) & noexcept { + return start_or_resume_object().find_field(key); +} +simdjson_inline simdjson_result document::find_field_unordered(std::string_view key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::find_field_unordered(const char *key) & noexcept { + return start_or_resume_object().find_field_unordered(key); +} +simdjson_inline simdjson_result document::operator[](std::string_view key) & noexcept { + return start_or_resume_object()[key]; +} +simdjson_inline simdjson_result document::operator[](const char *key) & noexcept { + return start_or_resume_object()[key]; +} + +simdjson_inline error_code document::consume() noexcept { + bool scalar = false; + auto error = is_scalar().get(scalar); + if(error) { return error; } + if(scalar) { + iter.return_current_and_advance(); + return SUCCESS; + } + error = iter.skip_child(0); + if(error) { iter.abandon(); } + return error; +} + +simdjson_inline simdjson_result document::raw_json() noexcept { + auto _iter = get_root_value_iterator(); + const uint8_t * starting_point{_iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + // After 'consume()', we could be left pointing just beyond the document, but that + // is ok because we are not going to dereference the final pointer position, we just + // use it to compute the length in bytes. + const uint8_t * final_point{iter.unsafe_pointer()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} + +simdjson_inline simdjson_result document::type() noexcept { + return get_root_value_iterator().type(); +} + +simdjson_inline simdjson_result document::is_scalar() noexcept { + // For more speed, we could do: + // return iter.is_single_token(); + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return ! ((this_type == json_type::array) || (this_type == json_type::object)); +} + +simdjson_inline simdjson_result document::is_string() noexcept { + json_type this_type; + auto error = type().get(this_type); + if(error) { return error; } + return (this_type == json_type::string); +} + +simdjson_inline bool document::is_negative() noexcept { + return get_root_value_iterator().is_root_negative(); +} + +simdjson_inline simdjson_result document::is_integer() noexcept { + return get_root_value_iterator().is_root_integer(true); +} + +simdjson_inline simdjson_result document::get_number_type() noexcept { + return get_root_value_iterator().get_root_number_type(true); +} + +simdjson_inline simdjson_result document::get_number() noexcept { + return get_root_value_iterator().get_root_number(true); +} + + +simdjson_inline simdjson_result document::raw_json_token() noexcept { + auto _iter = get_root_value_iterator(); + return std::string_view(reinterpret_cast(_iter.peek_start()), _iter.peek_root_length()); +} + +simdjson_inline simdjson_result document::at_pointer(std::string_view json_pointer) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_pointer.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) + { + case json_type::array: + return (*this).get_array().at_pointer(json_pointer); + case json_type::object: + return (*this).get_object().at_pointer(json_pointer); + default: + return INVALID_JSON_POINTER; + } +} + +simdjson_inline simdjson_result document::at_path(std::string_view json_path) noexcept { + rewind(); // Rewind the document each time at_pointer is called + if (json_path.empty()) { + return this->get_value(); + } + json_type t; + SIMDJSON_TRY(type().get(t)); + switch (t) { + case json_type::array: + return (*this).get_array().at_path(json_path); + case json_type::object: + return (*this).get_object().at_path(json_path); + default: + return INVALID_JSON_POINTER; + } +} } // namespace ondemand } // namespace lasx } // namespace simdjson - - namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::document_reference value, error_code error) - noexcept : implementation_simdjson_result_base(std::forward(value), error) {} - -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result( + lasx::ondemand::document &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base( + error + ) +{ +} +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { if (error()) { return error(); } return first.count_elements(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } return first.count_fields(); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { if (error()) { return error(); } return first.at(index); } -simdjson_inline error_code simdjson_result::rewind() noexcept { +simdjson_inline error_code simdjson_result::rewind() noexcept { if (error()) { return error(); } first.rewind(); return SUCCESS; } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { if (error()) { return error(); } return first.begin(); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { +simdjson_inline simdjson_result simdjson_result::end() & noexcept { return {}; } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { if (error()) { return error(); } return first.find_field_unordered(key); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { if (error()) { return error(); } return first[key]; } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::get_array() & noexcept { + if (error()) { return error(); } + return first.get_array(); +} +simdjson_inline simdjson_result simdjson_result::get_object() & noexcept { + if (error()) { return error(); } + return first.get_object(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { + if (error()) { return error(); } + return first.get_uint64(); +} +simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { + if (error()) { return error(); } + return first.get_uint64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { + if (error()) { return error(); } + return first.get_int64(); +} +simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { + if (error()) { return error(); } + return first.get_int64_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_double() noexcept { + if (error()) { return error(); } + return first.get_double(); +} +simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { + if (error()) { return error(); } + return first.get_double_in_string(); +} +simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(allow_replacement); +} +template +simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.get_string(receiver, allow_replacement); +} +simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { + if (error()) { return error(); } + return first.get_wobbly_string(); +} +simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { + if (error()) { return error(); } + return first.get_raw_json_string(); +} +simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { + if (error()) { return error(); } + return first.get_bool(); +} +simdjson_inline simdjson_result simdjson_result::get_value() noexcept { + if (error()) { return error(); } + return first.get_value(); +} +simdjson_inline simdjson_result simdjson_result::is_null() noexcept { + if (error()) { return error(); } + return first.is_null(); +} + +template +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} + +template<> simdjson_inline simdjson_result simdjson_result::get() & noexcept = delete; +template<> simdjson_deprecated simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first); +} +template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::document &out) & noexcept = delete; +template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::document &out) && noexcept { + if (error()) { return error(); } + out = std::forward(first); + return SUCCESS; +} + +simdjson_inline simdjson_result simdjson_result::type() noexcept { + if (error()) { return error(); } + return first.type(); +} + +simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { + if (error()) { return error(); } + return first.is_scalar(); +} + +simdjson_inline simdjson_result simdjson_result::is_string() noexcept { + if (error()) { return error(); } + return first.is_string(); +} + +simdjson_inline bool simdjson_result::is_negative() noexcept { + if (error()) { return error(); } + return first.is_negative(); +} + +simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { + if (error()) { return error(); } + return first.is_integer(); +} + +simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { + if (error()) { return error(); } + return first.get_number_type(); +} + +simdjson_inline simdjson_result simdjson_result::get_number() noexcept { + if (error()) { return error(); } + return first.get_number(); +} + + +#if SIMDJSON_EXCEPTIONS +template ::value == false>::type> +simdjson_inline simdjson_result::operator T() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lasx::ondemand::array() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lasx::ondemand::object() & noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator int64_t() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator double() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lasx::ondemand::raw_json_string() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator bool() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +simdjson_inline simdjson_result::operator lasx::ondemand::value() noexcept(false) { + if (error()) { throw simdjson_error(error()); } + return first; +} +#endif + + +simdjson_inline simdjson_result simdjson_result::current_location() noexcept { + if (error()) { return error(); } + return first.current_location(); +} + +simdjson_inline bool simdjson_result::at_end() const noexcept { + if (error()) { return error(); } + return first.at_end(); +} + + +simdjson_inline int32_t simdjson_result::current_depth() const noexcept { + if (error()) { return error(); } + return first.current_depth(); +} + +simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { + if (error()) { return error(); } + return first.raw_json_token(); +} + +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); +} + +simdjson_inline simdjson_result simdjson_result::at_path(std::string_view json_path) noexcept { + if (error()) { return error(); } + return first.at_path(json_path); +} + +} // namespace simdjson + + +namespace simdjson { +namespace lasx { +namespace ondemand { + +simdjson_inline document_reference::document_reference() noexcept : doc{nullptr} {} +simdjson_inline document_reference::document_reference(document &d) noexcept : doc(&d) {} +simdjson_inline void document_reference::rewind() noexcept { doc->rewind(); } +simdjson_inline simdjson_result document_reference::get_array() & noexcept { return doc->get_array(); } +simdjson_inline simdjson_result document_reference::get_object() & noexcept { return doc->get_object(); } +/** + * The document_reference instances are used primarily/solely for streams of JSON + * documents. + * We decided that calling 'get_double()' on the JSON document '1.233 blabla' should + * give an error, so we check for trailing content. + * + * However, for streams of JSON documents, we want to be able to start from + * "321" "321" "321" + * and parse it successfully as a stream of JSON documents, calling get_uint64_in_string() + * successfully each time. + * + * To achieve this result, we pass a 'false' to a get_root_value_iterator() method: + * this indicates that we allow trailing content. + */ +simdjson_inline simdjson_result document_reference::get_uint64() noexcept { return doc->get_root_value_iterator().get_root_uint64(false); } +simdjson_inline simdjson_result document_reference::get_uint64_in_string() noexcept { return doc->get_root_value_iterator().get_root_uint64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_int64() noexcept { return doc->get_root_value_iterator().get_root_int64(false); } +simdjson_inline simdjson_result document_reference::get_int64_in_string() noexcept { return doc->get_root_value_iterator().get_root_int64_in_string(false); } +simdjson_inline simdjson_result document_reference::get_double() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_double_in_string() noexcept { return doc->get_root_value_iterator().get_root_double(false); } +simdjson_inline simdjson_result document_reference::get_string(bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(false, allow_replacement); } +template +simdjson_inline error_code document_reference::get_string(string_type& receiver, bool allow_replacement) noexcept { return doc->get_root_value_iterator().get_root_string(receiver, false, allow_replacement); } +simdjson_inline simdjson_result document_reference::get_wobbly_string() noexcept { return doc->get_root_value_iterator().get_root_wobbly_string(false); } +simdjson_inline simdjson_result document_reference::get_raw_json_string() noexcept { return doc->get_root_value_iterator().get_root_raw_json_string(false); } +simdjson_inline simdjson_result document_reference::get_bool() noexcept { return doc->get_root_value_iterator().get_root_bool(false); } +simdjson_inline simdjson_result document_reference::get_value() noexcept { return doc->get_value(); } +simdjson_inline simdjson_result document_reference::is_null() noexcept { return doc->get_root_value_iterator().is_root_null(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_array(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_object(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_raw_json_string(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_string(false); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_double(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_uint64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_int64(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_bool(); } +template<> simdjson_inline simdjson_result document_reference::get() & noexcept { return get_value(); } +#if SIMDJSON_EXCEPTIONS +template +simdjson_inline document_reference::operator T() noexcept(false) { return get(); } +simdjson_inline document_reference::operator array() & noexcept(false) { return array(*doc); } +simdjson_inline document_reference::operator object() & noexcept(false) { return object(*doc); } +simdjson_inline document_reference::operator uint64_t() noexcept(false) { return get_uint64(); } +simdjson_inline document_reference::operator int64_t() noexcept(false) { return get_int64(); } +simdjson_inline document_reference::operator double() noexcept(false) { return get_double(); } +simdjson_inline document_reference::operator std::string_view() noexcept(false) { return std::string_view(*doc); } +simdjson_inline document_reference::operator raw_json_string() noexcept(false) { return get_raw_json_string(); } +simdjson_inline document_reference::operator bool() noexcept(false) { return get_bool(); } +simdjson_inline document_reference::operator value() noexcept(false) { return value(*doc); } +#endif +simdjson_inline simdjson_result document_reference::count_elements() & noexcept { return doc->count_elements(); } +simdjson_inline simdjson_result document_reference::count_fields() & noexcept { return doc->count_fields(); } +simdjson_inline simdjson_result document_reference::at(size_t index) & noexcept { return doc->at(index); } +simdjson_inline simdjson_result document_reference::begin() & noexcept { return doc->begin(); } +simdjson_inline simdjson_result document_reference::end() & noexcept { return doc->end(); } +simdjson_inline simdjson_result document_reference::find_field(std::string_view key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::find_field(const char *key) & noexcept { return doc->find_field(key); } +simdjson_inline simdjson_result document_reference::operator[](std::string_view key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::operator[](const char *key) & noexcept { return (*doc)[key]; } +simdjson_inline simdjson_result document_reference::find_field_unordered(std::string_view key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::find_field_unordered(const char *key) & noexcept { return doc->find_field_unordered(key); } +simdjson_inline simdjson_result document_reference::type() noexcept { return doc->type(); } +simdjson_inline simdjson_result document_reference::is_scalar() noexcept { return doc->is_scalar(); } +simdjson_inline simdjson_result document_reference::is_string() noexcept { return doc->is_string(); } +simdjson_inline simdjson_result document_reference::current_location() noexcept { return doc->current_location(); } +simdjson_inline int32_t document_reference::current_depth() const noexcept { return doc->current_depth(); } +simdjson_inline bool document_reference::is_negative() noexcept { return doc->is_negative(); } +simdjson_inline simdjson_result document_reference::is_integer() noexcept { return doc->get_root_value_iterator().is_root_integer(false); } +simdjson_inline simdjson_result document_reference::get_number_type() noexcept { return doc->get_root_value_iterator().get_root_number_type(false); } +simdjson_inline simdjson_result document_reference::get_number() noexcept { return doc->get_root_value_iterator().get_root_number(false); } +simdjson_inline simdjson_result document_reference::raw_json_token() noexcept { return doc->raw_json_token(); } +simdjson_inline simdjson_result document_reference::at_pointer(std::string_view json_pointer) noexcept { return doc->at_pointer(json_pointer); } +simdjson_inline simdjson_result document_reference::at_path(std::string_view json_path) noexcept { return doc->at_path(json_path); } +simdjson_inline simdjson_result document_reference::raw_json() noexcept { return doc->raw_json();} +simdjson_inline document_reference::operator document&() const noexcept { return *doc; } + +} // namespace ondemand +} // namespace lasx +} // namespace simdjson + + + +namespace simdjson { +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::document_reference value, error_code error) + noexcept : implementation_simdjson_result_base(std::forward(value), error) {} + + +simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { + if (error()) { return error(); } + return first.count_elements(); +} +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { + if (error()) { return error(); } + return first.count_fields(); +} +simdjson_inline simdjson_result simdjson_result::at(size_t index) & noexcept { + if (error()) { return error(); } + return first.at(index); +} +simdjson_inline error_code simdjson_result::rewind() noexcept { + if (error()) { return error(); } + first.rewind(); + return SUCCESS; +} +simdjson_inline simdjson_result simdjson_result::begin() & noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() & noexcept { + return {}; +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](const char *key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { if (error()) { return error(); } return first.find_field(key); } @@ -113983,6 +119724,26 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline simdjson_result simdjson_result::get() & noexcept { + if (error()) { return error(); } + return first.get(); +} +template +simdjson_inline simdjson_result simdjson_result::get() && noexcept { + if (error()) { return error(); } + return std::forward(first).get(); +} +template +simdjson_inline error_code simdjson_result::get(T &out) & noexcept { + if (error()) { return error(); } + return first.get(out); +} +template +simdjson_inline error_code simdjson_result::get(T &out) && noexcept { + if (error()) { return error(); } + return std::forward(first).get(out); +} simdjson_inline simdjson_result simdjson_result::type() noexcept { if (error()) { return error(); } return first.type(); @@ -113995,6 +119756,18 @@ simdjson_inline simdjson_result simdjson_result +simdjson_inline error_code simdjson_result::get(lasx::ondemand::document_reference &out) & noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} +template <> +simdjson_inline error_code simdjson_result::get(lasx::ondemand::document_reference &out) && noexcept { + if (error()) { return error(); } + out = first; + return SUCCESS; +} simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { if (error()) { return error(); } return first.is_negative(); @@ -114012,10 +119785,12 @@ simdjson_inline simdjson_result simdjson_result::value == false>::type> +template simdjson_inline simdjson_result::operator T() noexcept(false) { + static_assert(std::is_same::value == false, "You should not call get when T is a document"); + static_assert(std::is_same::value == false, "You should not call get when T is a document"); if (error()) { throw simdjson_error(error()); } - return first; + return first.get(); } simdjson_inline simdjson_result::operator lasx::ondemand::array() & noexcept(false) { if (error()) { throw simdjson_error(error()); } @@ -114212,2388 +119987,1848 @@ simdjson_inline document_stream::document_stream() noexcept { } -simdjson_inline document_stream::~document_stream() noexcept -{ - #ifdef SIMDJSON_THREADS_ENABLED - worker.reset(); - #endif -} - -inline size_t document_stream::size_in_bytes() const noexcept { - return len; -} - -inline size_t document_stream::truncated_bytes() const noexcept { - if(error == CAPACITY) { return len - batch_start; } - return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1]; -} - -simdjson_inline document_stream::iterator::iterator() noexcept - : stream{nullptr}, finished{true} { -} - -simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept - : stream{_stream}, finished{is_end} { -} - -simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { - //if(stream->error) { return stream->error; } - return simdjson_result(stream->doc, stream->error); -} - -simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept { - // If there is an error, then we want the iterator - // to be finished, no matter what. (E.g., we do not - // keep generating documents with errors, or go beyond - // a document with errors.) - // - // Users do not have to call "operator*()" when they use operator++, - // so we need to end the stream in the operator++ function. - // - // Note that setting finished = true is essential otherwise - // we would enter an infinite loop. - if (stream->error) { finished = true; } - // Note that stream->error() is guarded against error conditions - // (it will immediately return if stream->error casts to false). - // In effect, this next function does nothing when (stream->error) - // is true (hence the risk of an infinite loop). - stream->next(); - // If that was the last document, we're finished. - // It is the only type of error we do not want to appear - // in operator*. - if (stream->error == EMPTY) { finished = true; } - // If we had any other kind of error (not EMPTY) then we want - // to pass it along to the operator* and we cannot mark the result - // as "finished" just yet. - return *this; -} - -simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept { - return finished != other.finished; -} - -simdjson_inline document_stream::iterator document_stream::begin() noexcept { - start(); - // If there are no documents, we're finished. - return iterator(this, error == EMPTY); -} - -simdjson_inline document_stream::iterator document_stream::end() noexcept { - return iterator(this, true); -} - -inline void document_stream::start() noexcept { - if (error) { return; } - error = parser->allocate(batch_size); - if (error) { return; } - // Always run the first stage 1 parse immediately - batch_start = 0; - error = run_stage1(*parser, batch_start); - while(error == EMPTY) { - // In exceptional cases, we may start with an empty block - batch_start = next_batch_start(); - if (batch_start >= len) { return; } - error = run_stage1(*parser, batch_start); - } - if (error) { return; } - doc_index = batch_start; - doc = document(json_iterator(&buf[batch_start], parser)); - doc.iter._streaming = true; - - #ifdef SIMDJSON_THREADS_ENABLED - if (use_thread && next_batch_start() < len) { - // Kick off the first thread on next batch if needed - error = stage1_thread_parser.allocate(batch_size); - if (error) { return; } - worker->start_thread(); - start_stage1_thread(); - if (error) { return; } - } - #endif // SIMDJSON_THREADS_ENABLED -} - -inline void document_stream::next() noexcept { - // We always enter at once once in an error condition. - if (error) { return; } - next_document(); - if (error) { return; } - auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get(); - doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index]; - - // Check if at end of structural indexes (i.e. at end of batch) - if(cur_struct_index >= static_cast(parser->implementation->n_structural_indexes)) { - error = EMPTY; - // Load another batch (if available) - while (error == EMPTY) { - batch_start = next_batch_start(); - if (batch_start >= len) { break; } - #ifdef SIMDJSON_THREADS_ENABLED - if(use_thread) { - load_from_stage1_thread(); - } else { - error = run_stage1(*parser, batch_start); - } - #else - error = run_stage1(*parser, batch_start); - #endif - /** - * Whenever we move to another window, we need to update all pointers to make - * it appear as if the input buffer started at the beginning of the window. - * - * Take this input: - * - * {"z":5} {"1":1,"2":2,"4":4} [7, 10, 9] [15, 11, 12, 13] [154, 110, 112, 1311] - * - * Say you process the following window... - * - * '{"z":5} {"1":1,"2":2,"4":4} [7, 10, 9]' - * - * When you do so, the json_iterator has a pointer at the beginning of the memory region - * (pointing at the beginning of '{"z"...'. - * - * When you move to the window that starts at... - * - * '[7, 10, 9] [15, 11, 12, 13] ... - * - * then it is not sufficient to just run stage 1. You also need to re-anchor the - * json_iterator so that it believes we are starting at '[7, 10, 9]...'. - * - * Under the DOM front-end, this gets done automatically because the parser owns - * the pointer the data, and when you call stage1 and then stage2 on the same - * parser, then stage2 will run on the pointer acquired by stage1. - * - * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that - * we used. But json_iterator has no callback when stage1 is called on the parser. - * In fact, I think that the parser is unaware of json_iterator. - * - * - * So we need to re-anchor the json_iterator after each call to stage 1 so that - * all of the pointers are in sync. - */ - doc.iter = json_iterator(&buf[batch_start], parser); - doc.iter._streaming = true; - /** - * End of resync. - */ - - if (error) { continue; } // If the error was EMPTY, we may want to load another batch. - doc_index = batch_start; - } - } -} - -inline void document_stream::next_document() noexcept { - // Go to next place where depth=0 (document depth) - error = doc.iter.skip_child(0); - if (error) { return; } - // Always set depth=1 at the start of document - doc.iter._depth = 1; - // consume comma if comma separated is allowed - if (allow_comma_separated) { doc.iter.consume_character(','); } - // Resets the string buffer at the beginning, thus invalidating the strings. - doc.iter._string_buf_loc = parser->string_buf.get(); - doc.iter._root = doc.iter.position(); -} - -inline size_t document_stream::next_batch_start() const noexcept { - return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes]; -} - -inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept { - // This code only updates the structural index in the parser, it does not update any json_iterator - // instance. - size_t remaining = len - _batch_start; - if (remaining <= batch_size) { - return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final); - } else { - return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial); - } -} - -simdjson_inline size_t document_stream::iterator::current_index() const noexcept { - return stream->doc_index; -} - -simdjson_inline std::string_view document_stream::iterator::source() const noexcept { - auto depth = stream->doc.iter.depth(); - auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get(); - - // If at root, process the first token to determine if scalar value - if (stream->doc.iter.at_root()) { - switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) { - case '{': case '[': // Depth=1 already at start of document - break; - case '}': case ']': - depth--; - break; - default: // Scalar value document - // TODO: We could remove trailing whitespaces - // This returns a string spanning from start of value to the beginning of the next document (excluded) - { - auto next_index = stream->parser->implementation->structural_indexes[++cur_struct_index]; - // normally the length would be next_index - current_index() - 1, except for the last document - size_t svlen = next_index - current_index(); - const char *start = reinterpret_cast(stream->buf) + current_index(); - while(svlen > 1 && (std::isspace(start[svlen-1]) || start[svlen-1] == '\0')) { - svlen--; - } - return std::string_view(start, svlen); - } - } - cur_struct_index++; - } - - while (cur_struct_index <= static_cast(stream->parser->implementation->n_structural_indexes)) { - switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) { - case '{': case '[': - depth++; - break; - case '}': case ']': - depth--; - break; - } - if (depth == 0) { break; } - cur_struct_index++; - } - - return std::string_view(reinterpret_cast(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);; -} - -inline error_code document_stream::iterator::error() const noexcept { - return stream->error; -} - -#ifdef SIMDJSON_THREADS_ENABLED - -inline void document_stream::load_from_stage1_thread() noexcept { - worker->finish(); - // Swap to the parser that was loaded up in the thread. Make sure the parser has - // enough memory to swap to, as well. - std::swap(stage1_thread_parser,*parser); - error = stage1_thread_error; - if (error) { return; } - - // If there's anything left, start the stage 1 thread! - if (next_batch_start() < len) { - start_stage1_thread(); - } -} - -inline void document_stream::start_stage1_thread() noexcept { - // we call the thread on a lambda that will update - // this->stage1_thread_error - // there is only one thread that may write to this value - // TODO this is NOT exception-safe. - this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error - size_t _next_batch_start = this->next_batch_start(); - - worker->run(this, & this->stage1_thread_parser, _next_batch_start); -} - -#endif // SIMDJSON_THREADS_ENABLED - -} // namespace ondemand -} // namespace lasx -} // namespace simdjson - -namespace simdjson { - -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result::simdjson_result( - lasx::ondemand::document_stream &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} - -} - -#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H -/* end file simdjson/generic/ondemand/document_stream-inl.h for lasx */ -/* including simdjson/generic/ondemand/field-inl.h for lasx: #include "simdjson/generic/ondemand/field-inl.h" */ -/* begin file simdjson/generic/ondemand/field-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace lasx { -namespace ondemand { - -// clang 6 does not think the default constructor can be noexcept, so we make it explicit -simdjson_inline field::field() noexcept : std::pair() {} - -simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept - : std::pair(key, std::forward(value)) -{ -} - -simdjson_inline simdjson_result field::start(value_iterator &parent_iter) noexcept { - raw_json_string key; - SIMDJSON_TRY( parent_iter.field_key().get(key) ); - SIMDJSON_TRY( parent_iter.field_value() ); - return field::start(parent_iter, key); -} - -simdjson_inline simdjson_result field::start(const value_iterator &parent_iter, raw_json_string key) noexcept { - return field(key, parent_iter.child()); -} - -simdjson_inline simdjson_warn_unused simdjson_result field::unescaped_key(bool allow_replacement) noexcept { - SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us. - simdjson_result answer = first.unescape(second.iter.json_iter(), allow_replacement); - first.consume(); - return answer; -} - -template -simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { - std::string_view key; - SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); - receiver = key; - return SUCCESS; -} - -simdjson_inline raw_json_string field::key() const noexcept { - SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. - return first; -} - - -simdjson_inline std::string_view field::key_raw_json_token() const noexcept { - SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. - return std::string_view(reinterpret_cast(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1); -} - -simdjson_inline std::string_view field::escaped_key() const noexcept { - SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. - auto end_quote = second.iter._json_iter->token.peek(-1); - while(*end_quote != '"') end_quote--; - return std::string_view(reinterpret_cast(first.buf), end_quote - first.buf); -} - -simdjson_inline value &field::value() & noexcept { - return second; -} - -simdjson_inline value field::value() && noexcept { - return std::forward(*this).second; -} - -} // namespace ondemand -} // namespace lasx -} // namespace simdjson - -namespace simdjson { - -simdjson_inline simdjson_result::simdjson_result( - lasx::ondemand::field &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} - -simdjson_inline simdjson_result simdjson_result::key() noexcept { - if (error()) { return error(); } - return first.key(); -} - -simdjson_inline simdjson_result simdjson_result::key_raw_json_token() noexcept { - if (error()) { return error(); } - return first.key_raw_json_token(); -} - -simdjson_inline simdjson_result simdjson_result::escaped_key() noexcept { - if (error()) { return error(); } - return first.escaped_key(); -} - -simdjson_inline simdjson_result simdjson_result::unescaped_key(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.unescaped_key(allow_replacement); -} - -template -simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.unescaped_key(receiver, allow_replacement); -} - -simdjson_inline simdjson_result simdjson_result::value() noexcept { - if (error()) { return error(); } - return std::move(first.value()); -} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H -/* end file simdjson/generic/ondemand/field-inl.h for lasx */ -/* including simdjson/generic/ondemand/json_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/json_iterator-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H - -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ - -namespace simdjson { -namespace lasx { -namespace ondemand { - -simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept - : token(std::forward(other.token)), - parser{other.parser}, - _string_buf_loc{other._string_buf_loc}, - error{other.error}, - _depth{other._depth}, - _root{other._root}, - _streaming{other._streaming} -{ - other.parser = nullptr; -} -simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept { - token = other.token; - parser = other.parser; - _string_buf_loc = other._string_buf_loc; - error = other.error; - _depth = other._depth; - _root = other._root; - _streaming = other._streaming; - other.parser = nullptr; - return *this; -} - -simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept - : token(buf, &_parser->implementation->structural_indexes[0]), - parser{_parser}, - _string_buf_loc{parser->string_buf.get()}, - _depth{1}, - _root{parser->implementation->structural_indexes.get()}, - _streaming{false} - -{ - logger::log_headers(); -#if SIMDJSON_CHECK_EOF - assert_more_tokens(); -#endif -} - -#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON -simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser, bool streaming) noexcept - : token(buf, &_parser->implementation->structural_indexes[0]), - parser{_parser}, - _string_buf_loc{parser->string_buf.get()}, - _depth{1}, - _root{parser->implementation->structural_indexes.get()}, - _streaming{streaming} - -{ - logger::log_headers(); -#if SIMDJSON_CHECK_EOF - assert_more_tokens(); -#endif -} -#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON - -inline void json_iterator::rewind() noexcept { - token.set_position( root_position() ); - logger::log_headers(); // We start again - _string_buf_loc = parser->string_buf.get(); - _depth = 1; -} - -inline bool json_iterator::balanced() const noexcept { - token_iterator ti(token); - int32_t count{0}; - ti.set_position( root_position() ); - while(ti.peek() <= peek_last()) { - switch (*ti.return_current_and_advance()) - { - case '[': case '{': - count++; - break; - case ']': case '}': - count--; - break; - default: - break; - } - } - return count == 0; -} - - -// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller -// relating depth and parent_depth, which is a desired effect. The warning does not show up if the -// skip_child() function is not marked inline). -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept { - if (depth() <= parent_depth) { return SUCCESS; } - switch (*return_current_and_advance()) { - // TODO consider whether matching braces is a requirement: if non-matching braces indicates - // *missing* braces, then future lookups are not in the object/arrays they think they are, - // violating the rule "validate enough structure that the user can be confident they are - // looking at the right values." - // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth - - // For the first open array/object in a value, we've already incremented depth, so keep it the same - // We never stop at colon, but if we did, it wouldn't affect depth - case '[': case '{': case ':': - logger::log_start_value(*this, "skip"); - break; - // If there is a comma, we have just finished a value in an array/object, and need to get back in - case ',': - logger::log_value(*this, "skip"); - break; - // ] or } means we just finished a value and need to jump out of the array/object - case ']': case '}': - logger::log_end_value(*this, "skip"); - _depth--; - if (depth() <= parent_depth) { return SUCCESS; } -#if SIMDJSON_CHECK_EOF - // If there are no more tokens, the parent is incomplete. - if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); } -#endif // SIMDJSON_CHECK_EOF - break; - case '"': - if(*peek() == ':') { - // We are at a key!!! - // This might happen if you just started an object and you skip it immediately. - // Performance note: it would be nice to get rid of this check as it is somewhat - // expensive. - // https://github.com/simdjson/simdjson/issues/1742 - logger::log_value(*this, "key"); - return_current_and_advance(); // eat up the ':' - break; // important!!! - } - simdjson_fallthrough; - // Anything else must be a scalar value - default: - // For the first scalar, we will have incremented depth already, so we decrement it here. - logger::log_value(*this, "skip"); - _depth--; - if (depth() <= parent_depth) { return SUCCESS; } - break; - } - - // Now that we've considered the first value, we only increment/decrement for arrays/objects - while (position() < end_position()) { - switch (*return_current_and_advance()) { - case '[': case '{': - logger::log_start_value(*this, "skip"); - _depth++; - break; - // TODO consider whether matching braces is a requirement: if non-matching braces indicates - // *missing* braces, then future lookups are not in the object/arrays they think they are, - // violating the rule "validate enough structure that the user can be confident they are - // looking at the right values." - // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth - case ']': case '}': - logger::log_end_value(*this, "skip"); - _depth--; - if (depth() <= parent_depth) { return SUCCESS; } - break; - default: - logger::log_value(*this, "skip", ""); - break; - } - } - - return report_error(TAPE_ERROR, "not enough close braces"); -} - -SIMDJSON_POP_DISABLE_WARNINGS - -simdjson_inline bool json_iterator::at_root() const noexcept { - return position() == root_position(); -} - -simdjson_inline bool json_iterator::is_single_token() const noexcept { - return parser->implementation->n_structural_indexes == 1; -} - -simdjson_inline bool json_iterator::streaming() const noexcept { - return _streaming; -} - -simdjson_inline token_position json_iterator::root_position() const noexcept { - return _root; -} - -simdjson_inline void json_iterator::assert_at_document_depth() const noexcept { - SIMDJSON_ASSUME( _depth == 1 ); -} - -simdjson_inline void json_iterator::assert_at_root() const noexcept { - SIMDJSON_ASSUME( _depth == 1 ); -#ifndef SIMDJSON_CLANG_VISUAL_STUDIO - // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument - // has side effects that will be discarded. - SIMDJSON_ASSUME( token.position() == _root ); -#endif -} - -simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept { - assert_valid_position(token._position + required_tokens - 1); -} - -simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept { -#ifndef SIMDJSON_CLANG_VISUAL_STUDIO - SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] ); - SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] ); -#endif -} - -simdjson_inline bool json_iterator::at_end() const noexcept { - return position() == end_position(); -} -simdjson_inline token_position json_iterator::end_position() const noexcept { - uint32_t n_structural_indexes{parser->implementation->n_structural_indexes}; - return &parser->implementation->structural_indexes[n_structural_indexes]; -} - -inline std::string json_iterator::to_string() const noexcept { - if( !is_alive() ) { return "dead json_iterator instance"; } - const char * current_structural = reinterpret_cast(token.peek()); - return std::string("json_iterator [ depth : ") + std::to_string(_depth) - + std::string(", structural : '") + std::string(current_structural,1) - + std::string("', offset : ") + std::to_string(token.current_offset()) - + std::string("', error : ") + error_message(error) - + std::string(" ]"); -} - -inline simdjson_result json_iterator::current_location() const noexcept { - if (!is_alive()) { // Unrecoverable error - if (!at_root()) { - return reinterpret_cast(token.peek(-1)); - } else { - return reinterpret_cast(token.peek()); - } - } - if (at_end()) { - return OUT_OF_BOUNDS; - } - return reinterpret_cast(token.peek()); -} - -simdjson_inline bool json_iterator::is_alive() const noexcept { - return parser; -} - -simdjson_inline void json_iterator::abandon() noexcept { - parser = nullptr; - _depth = 0; +simdjson_inline document_stream::~document_stream() noexcept +{ + #ifdef SIMDJSON_THREADS_ENABLED + worker.reset(); + #endif } -simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept { -#if SIMDJSON_CHECK_EOF - assert_more_tokens(); -#endif // SIMDJSON_CHECK_EOF - return token.return_current_and_advance(); +inline size_t document_stream::size_in_bytes() const noexcept { + return len; } -simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept { - // deliberately done without safety guard: - return token.peek(); +inline size_t document_stream::truncated_bytes() const noexcept { + if(error == CAPACITY) { return len - batch_start; } + return parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] - parser->implementation->structural_indexes[parser->implementation->n_structural_indexes + 1]; } -simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept { -#if SIMDJSON_CHECK_EOF - assert_more_tokens(delta+1); -#endif // SIMDJSON_CHECK_EOF - return token.peek(delta); +simdjson_inline document_stream::iterator::iterator() noexcept + : stream{nullptr}, finished{true} { } -simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept { -#if SIMDJSON_CHECK_EOF - assert_more_tokens(delta+1); -#endif // #if SIMDJSON_CHECK_EOF - return token.peek_length(delta); +simdjson_inline document_stream::iterator::iterator(document_stream* _stream, bool is_end) noexcept + : stream{_stream}, finished{is_end} { } -simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept { - // todo: currently we require end-of-string buffering, but the following - // assert_valid_position should be turned on if/when we lift that condition. - // assert_valid_position(position); - // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF - // is ON by default, we have no choice but to disable it for real with a comment. - return token.peek(position); +simdjson_inline simdjson_result document_stream::iterator::operator*() noexcept { + return simdjson_result(stream->doc, stream->error); } -simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept { -#if SIMDJSON_CHECK_EOF - assert_valid_position(position); -#endif // SIMDJSON_CHECK_EOF - return token.peek_length(position); -} -simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept { -#if SIMDJSON_CHECK_EOF - assert_valid_position(position); -#endif // SIMDJSON_CHECK_EOF - return token.peek_root_length(position); +simdjson_inline document_stream::iterator& document_stream::iterator::operator++() noexcept { + // If there is an error, then we want the iterator + // to be finished, no matter what. (E.g., we do not + // keep generating documents with errors, or go beyond + // a document with errors.) + // + // Users do not have to call "operator*()" when they use operator++, + // so we need to end the stream in the operator++ function. + // + // Note that setting finished = true is essential otherwise + // we would enter an infinite loop. + if (stream->error) { finished = true; } + // Note that stream->error() is guarded against error conditions + // (it will immediately return if stream->error casts to false). + // In effect, this next function does nothing when (stream->error) + // is true (hence the risk of an infinite loop). + stream->next(); + // If that was the last document, we're finished. + // It is the only type of error we do not want to appear + // in operator*. + if (stream->error == EMPTY) { finished = true; } + // If we had any other kind of error (not EMPTY) then we want + // to pass it along to the operator* and we cannot mark the result + // as "finished" just yet. + return *this; } -simdjson_inline token_position json_iterator::last_position() const noexcept { - // The following line fails under some compilers... - // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0); - // since it has side-effects. - uint32_t n_structural_indexes{parser->implementation->n_structural_indexes}; - SIMDJSON_ASSUME(n_structural_indexes > 0); - return &parser->implementation->structural_indexes[n_structural_indexes - 1]; -} -simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept { - return token.peek(last_position()); +simdjson_inline bool document_stream::iterator::operator!=(const document_stream::iterator &other) const noexcept { + return finished != other.finished; } -simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept { - SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1); - SIMDJSON_ASSUME(_depth == parent_depth + 1); - _depth = parent_depth; +simdjson_inline document_stream::iterator document_stream::begin() noexcept { + start(); + // If there are no documents, we're finished. + return iterator(this, error == EMPTY); } -simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept { - SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX); - SIMDJSON_ASSUME(_depth == child_depth - 1); - _depth = child_depth; +simdjson_inline document_stream::iterator document_stream::end() noexcept { + return iterator(this, true); } -simdjson_inline depth_t json_iterator::depth() const noexcept { - return _depth; -} +inline void document_stream::start() noexcept { + if (error) { return; } + error = parser->allocate(batch_size); + if (error) { return; } + // Always run the first stage 1 parse immediately + batch_start = 0; + error = run_stage1(*parser, batch_start); + while(error == EMPTY) { + // In exceptional cases, we may start with an empty block + batch_start = next_batch_start(); + if (batch_start >= len) { return; } + error = run_stage1(*parser, batch_start); + } + if (error) { return; } + doc_index = batch_start; + doc = document(json_iterator(&buf[batch_start], parser)); + doc.iter._streaming = true; -simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept { - return _string_buf_loc; + #ifdef SIMDJSON_THREADS_ENABLED + if (use_thread && next_batch_start() < len) { + // Kick off the first thread on next batch if needed + error = stage1_thread_parser.allocate(batch_size); + if (error) { return; } + worker->start_thread(); + start_stage1_thread(); + if (error) { return; } + } + #endif // SIMDJSON_THREADS_ENABLED } -simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept { - SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD); - logger::log_error(*this, message); - error = _error; - return error; +inline void document_stream::next() noexcept { + // We always enter at once once in an error condition. + if (error) { return; } + next_document(); + if (error) { return; } + auto cur_struct_index = doc.iter._root - parser->implementation->structural_indexes.get(); + doc_index = batch_start + parser->implementation->structural_indexes[cur_struct_index]; + + // Check if at end of structural indexes (i.e. at end of batch) + if(cur_struct_index >= static_cast(parser->implementation->n_structural_indexes)) { + error = EMPTY; + // Load another batch (if available) + while (error == EMPTY) { + batch_start = next_batch_start(); + if (batch_start >= len) { break; } + #ifdef SIMDJSON_THREADS_ENABLED + if(use_thread) { + load_from_stage1_thread(); + } else { + error = run_stage1(*parser, batch_start); + } + #else + error = run_stage1(*parser, batch_start); + #endif + /** + * Whenever we move to another window, we need to update all pointers to make + * it appear as if the input buffer started at the beginning of the window. + * + * Take this input: + * + * {"z":5} {"1":1,"2":2,"4":4} [7, 10, 9] [15, 11, 12, 13] [154, 110, 112, 1311] + * + * Say you process the following window... + * + * '{"z":5} {"1":1,"2":2,"4":4} [7, 10, 9]' + * + * When you do so, the json_iterator has a pointer at the beginning of the memory region + * (pointing at the beginning of '{"z"...'. + * + * When you move to the window that starts at... + * + * '[7, 10, 9] [15, 11, 12, 13] ... + * + * then it is not sufficient to just run stage 1. You also need to re-anchor the + * json_iterator so that it believes we are starting at '[7, 10, 9]...'. + * + * Under the DOM front-end, this gets done automatically because the parser owns + * the pointer the data, and when you call stage1 and then stage2 on the same + * parser, then stage2 will run on the pointer acquired by stage1. + * + * That is, stage1 calls "this->buf = _buf" so the parser remembers the buffer that + * we used. But json_iterator has no callback when stage1 is called on the parser. + * In fact, I think that the parser is unaware of json_iterator. + * + * + * So we need to re-anchor the json_iterator after each call to stage 1 so that + * all of the pointers are in sync. + */ + doc.iter = json_iterator(&buf[batch_start], parser); + doc.iter._streaming = true; + /** + * End of resync. + */ + + if (error) { continue; } // If the error was EMPTY, we may want to load another batch. + doc_index = batch_start; + } + } } -simdjson_inline token_position json_iterator::position() const noexcept { - return token.position(); +inline void document_stream::next_document() noexcept { + // Go to next place where depth=0 (document depth) + error = doc.iter.skip_child(0); + if (error) { return; } + // Always set depth=1 at the start of document + doc.iter._depth = 1; + // consume comma if comma separated is allowed + if (allow_comma_separated) { doc.iter.consume_character(','); } + // Resets the string buffer at the beginning, thus invalidating the strings. + doc.iter._string_buf_loc = parser->string_buf.get(); + doc.iter._root = doc.iter.position(); } -simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { -#if SIMDJSON_DEVELOPMENT_CHECKS - auto result = parser->unescape(in, _string_buf_loc, allow_replacement); - SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); - return result; -#else - return parser->unescape(in, _string_buf_loc, allow_replacement); -#endif +inline size_t document_stream::next_batch_start() const noexcept { + return batch_start + parser->implementation->structural_indexes[parser->implementation->n_structural_indexes]; } -simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { -#if SIMDJSON_DEVELOPMENT_CHECKS - auto result = parser->unescape_wobbly(in, _string_buf_loc); - SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); - return result; -#else - return parser->unescape_wobbly(in, _string_buf_loc); -#endif +inline error_code document_stream::run_stage1(ondemand::parser &p, size_t _batch_start) noexcept { + // This code only updates the structural index in the parser, it does not update any json_iterator + // instance. + size_t remaining = len - _batch_start; + if (remaining <= batch_size) { + return p.implementation->stage1(&buf[_batch_start], remaining, stage1_mode::streaming_final); + } else { + return p.implementation->stage1(&buf[_batch_start], batch_size, stage1_mode::streaming_partial); + } } -simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { - SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX); - SIMDJSON_ASSUME(_depth == child_depth - 1); -#if SIMDJSON_DEVELOPMENT_CHECKS -#ifndef SIMDJSON_CLANG_VISUAL_STUDIO - SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth()); - SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]); -#endif -#endif - token.set_position(position); - _depth = child_depth; +simdjson_inline size_t document_stream::iterator::current_index() const noexcept { + return stream->doc_index; } -simdjson_inline error_code json_iterator::consume_character(char c) noexcept { - if (*peek() == c) { - return_current_and_advance(); - return SUCCESS; +simdjson_inline std::string_view document_stream::iterator::source() const noexcept { + auto depth = stream->doc.iter.depth(); + auto cur_struct_index = stream->doc.iter._root - stream->parser->implementation->structural_indexes.get(); + + // If at root, process the first token to determine if scalar value + if (stream->doc.iter.at_root()) { + switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) { + case '{': case '[': // Depth=1 already at start of document + break; + case '}': case ']': + depth--; + break; + default: // Scalar value document + // TODO: We could remove trailing whitespaces + // This returns a string spanning from start of value to the beginning of the next document (excluded) + { + auto next_index = stream->parser->implementation->structural_indexes[++cur_struct_index]; + // normally the length would be next_index - current_index() - 1, except for the last document + size_t svlen = next_index - current_index(); + const char *start = reinterpret_cast(stream->buf) + current_index(); + while(svlen > 1 && (std::isspace(start[svlen-1]) || start[svlen-1] == '\0')) { + svlen--; + } + return std::string_view(start, svlen); + } + } + cur_struct_index++; } - return TAPE_ERROR; -} -#if SIMDJSON_DEVELOPMENT_CHECKS + while (cur_struct_index <= static_cast(stream->parser->implementation->n_structural_indexes)) { + switch (stream->buf[stream->batch_start + stream->parser->implementation->structural_indexes[cur_struct_index]]) { + case '{': case '[': + depth++; + break; + case '}': case ']': + depth--; + break; + } + if (depth == 0) { break; } + cur_struct_index++; + } -simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept { - SIMDJSON_ASSUME(size_t(depth) < parser->max_depth()); - return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0; + return std::string_view(reinterpret_cast(stream->buf) + current_index(), stream->parser->implementation->structural_indexes[cur_struct_index] - current_index() + stream->batch_start + 1);; } -simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept { - SIMDJSON_ASSUME(size_t(depth) < parser->max_depth()); - if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; } +inline error_code document_stream::iterator::error() const noexcept { + return stream->error; } -#endif +#ifdef SIMDJSON_THREADS_ENABLED +inline void document_stream::load_from_stage1_thread() noexcept { + worker->finish(); + // Swap to the parser that was loaded up in the thread. Make sure the parser has + // enough memory to swap to, as well. + std::swap(stage1_thread_parser,*parser); + error = stage1_thread_error; + if (error) { return; } -simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept { - SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD); - logger::log_error(*this, message); - return _error; + // If there's anything left, start the stage 1 thread! + if (next_batch_start() < len) { + start_stage1_thread(); + } } +inline void document_stream::start_stage1_thread() noexcept { + // we call the thread on a lambda that will update + // this->stage1_thread_error + // there is only one thread that may write to this value + // TODO this is NOT exception-safe. + this->stage1_thread_error = UNINITIALIZED; // In case something goes wrong, make sure it's an error + size_t _next_batch_start = this->next_batch_start(); -simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept { - // This function is not expected to be called in performance-sensitive settings. - // Let us guard against silly cases: - if((N < max_len) || (N == 0)) { return false; } - // Copy to the buffer. - std::memcpy(tmpbuf, json, max_len); - if(N > max_len) { // We pad whatever remains with ' '. - std::memset(tmpbuf + max_len, ' ', N - max_len); - } - return true; + worker->run(this, & this->stage1_thread_parser, _next_batch_start); } +#endif // SIMDJSON_THREADS_ENABLED + } // namespace ondemand } // namespace lasx } // namespace simdjson namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::json_iterator &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base(error) +{ +} +simdjson_inline simdjson_result::simdjson_result( + lasx::ondemand::document_stream &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} -} // namespace simdjson +} -#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H -/* end file simdjson/generic/ondemand/json_iterator-inl.h for lasx */ -/* including simdjson/generic/ondemand/json_type-inl.h for lasx: #include "simdjson/generic/ondemand/json_type-inl.h" */ -/* begin file simdjson/generic/ondemand/json_type-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_DOCUMENT_STREAM_INL_H +/* end file simdjson/generic/ondemand/document_stream-inl.h for lasx */ +/* including simdjson/generic/ondemand/field-inl.h for lasx: #include "simdjson/generic/ondemand/field-inl.h" */ +/* begin file simdjson/generic/ondemand/field-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lasx { namespace ondemand { -inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept { - switch (type) { - case json_type::array: out << "array"; break; - case json_type::object: out << "object"; break; - case json_type::number: out << "number"; break; - case json_type::string: out << "string"; break; - case json_type::boolean: out << "boolean"; break; - case json_type::null: out << "null"; break; - default: SIMDJSON_UNREACHABLE(); - } - return out; -} +// clang 6 does not think the default constructor can be noexcept, so we make it explicit +simdjson_inline field::field() noexcept : std::pair() {} -#if SIMDJSON_EXCEPTIONS -inline std::ostream& operator<<(std::ostream& out, simdjson_result &type) noexcept(false) { - return out << type.value(); +simdjson_inline field::field(raw_json_string key, ondemand::value &&value) noexcept + : std::pair(key, std::forward(value)) +{ } -#endif - - -simdjson_inline number_type number::get_number_type() const noexcept { - return type; +simdjson_inline simdjson_result field::start(value_iterator &parent_iter) noexcept { + raw_json_string key; + SIMDJSON_TRY( parent_iter.field_key().get(key) ); + SIMDJSON_TRY( parent_iter.field_value() ); + return field::start(parent_iter, key); } -simdjson_inline bool number::is_uint64() const noexcept { - return get_number_type() == number_type::unsigned_integer; +simdjson_inline simdjson_result field::start(const value_iterator &parent_iter, raw_json_string key) noexcept { + return field(key, parent_iter.child()); } -simdjson_inline uint64_t number::get_uint64() const noexcept { - return payload.unsigned_integer; +simdjson_inline simdjson_warn_unused simdjson_result field::unescaped_key(bool allow_replacement) noexcept { + SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() but Visual Studio won't let us. + simdjson_result answer = first.unescape(second.iter.json_iter(), allow_replacement); + first.consume(); + return answer; } -simdjson_inline number::operator uint64_t() const noexcept { - return get_uint64(); +template +simdjson_inline simdjson_warn_unused error_code field::unescaped_key(string_type& receiver, bool allow_replacement) noexcept { + std::string_view key; + SIMDJSON_TRY( unescaped_key(allow_replacement).get(key) ); + receiver = key; + return SUCCESS; } -simdjson_inline bool number::is_int64() const noexcept { - return get_number_type() == number_type::signed_integer; +simdjson_inline raw_json_string field::key() const noexcept { + SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. + return first; } -simdjson_inline int64_t number::get_int64() const noexcept { - return payload.signed_integer; -} -simdjson_inline number::operator int64_t() const noexcept { - return get_int64(); +simdjson_inline std::string_view field::key_raw_json_token() const noexcept { + SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. + return std::string_view(reinterpret_cast(first.buf-1), second.iter._json_iter->token.peek(-1) - first.buf + 1); } -simdjson_inline bool number::is_double() const noexcept { - return get_number_type() == number_type::floating_point_number; +simdjson_inline std::string_view field::escaped_key() const noexcept { + SIMDJSON_ASSUME(first.buf != nullptr); // We would like to call .alive() by Visual Studio won't let us. + auto end_quote = second.iter._json_iter->token.peek(-1); + while(*end_quote != '"') end_quote--; + return std::string_view(reinterpret_cast(first.buf), end_quote - first.buf); } -simdjson_inline double number::get_double() const noexcept { - return payload.floating_point_number; +simdjson_inline value &field::value() & noexcept { + return second; } -simdjson_inline number::operator double() const noexcept { - return get_double(); +simdjson_inline value field::value() && noexcept { + return std::forward(*this).second; } -simdjson_inline double number::as_double() const noexcept { - if(is_double()) { - return payload.floating_point_number; - } - if(is_int64()) { - return double(payload.signed_integer); - } - return double(payload.unsigned_integer); -} +} // namespace ondemand +} // namespace lasx +} // namespace simdjson -simdjson_inline void number::append_s64(int64_t value) noexcept { - payload.signed_integer = value; - type = number_type::signed_integer; +namespace simdjson { + +simdjson_inline simdjson_result::simdjson_result( + lasx::ondemand::field &&value +) noexcept : + implementation_simdjson_result_base( + std::forward(value) + ) +{ +} +simdjson_inline simdjson_result::simdjson_result( + error_code error +) noexcept : + implementation_simdjson_result_base(error) +{ } -simdjson_inline void number::append_u64(uint64_t value) noexcept { - payload.unsigned_integer = value; - type = number_type::unsigned_integer; +simdjson_inline simdjson_result simdjson_result::key() noexcept { + if (error()) { return error(); } + return first.key(); } -simdjson_inline void number::append_double(double value) noexcept { - payload.floating_point_number = value; - type = number_type::floating_point_number; +simdjson_inline simdjson_result simdjson_result::key_raw_json_token() noexcept { + if (error()) { return error(); } + return first.key_raw_json_token(); } -simdjson_inline void number::skip_double() noexcept { - type = number_type::floating_point_number; +simdjson_inline simdjson_result simdjson_result::escaped_key() noexcept { + if (error()) { return error(); } + return first.escaped_key(); } -} // namespace ondemand -} // namespace lasx -} // namespace simdjson +simdjson_inline simdjson_result simdjson_result::unescaped_key(bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(allow_replacement); +} -namespace simdjson { +template +simdjson_inline error_code simdjson_result::unescaped_key(string_type &receiver, bool allow_replacement) noexcept { + if (error()) { return error(); } + return first.unescaped_key(receiver, allow_replacement); +} -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::json_type &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} +simdjson_inline simdjson_result simdjson_result::value() noexcept { + if (error()) { return error(); } + return std::move(first.value()); +} } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H -/* end file simdjson/generic/ondemand/json_type-inl.h for lasx */ -/* including simdjson/generic/ondemand/logger-inl.h for lasx: #include "simdjson/generic/ondemand/logger-inl.h" */ -/* begin file simdjson/generic/ondemand/logger-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_FIELD_INL_H +/* end file simdjson/generic/ondemand/field-inl.h for lasx */ +/* including simdjson/generic/ondemand/json_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/json_iterator-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ -#include -#include - namespace simdjson { namespace lasx { namespace ondemand { -namespace logger { - -static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"; -static constexpr const int LOG_EVENT_LEN = 20; -static constexpr const int LOG_BUFFER_LEN = 30; -static constexpr const int LOG_SMALL_BUFFER_LEN = 10; -static int log_depth = 0; // Not threadsafe. Log only. - -// Helper to turn unprintable or newline characters into spaces -static inline char printable_char(char c) { - if (c >= 0x20) { - return c; - } else { - return ' '; - } -} -template -static inline std::string string_format(const std::string& format, const Args&... args) +simdjson_inline json_iterator::json_iterator(json_iterator &&other) noexcept + : token(std::forward(other.token)), + parser{other.parser}, + _string_buf_loc{other._string_buf_loc}, + error{other.error}, + _depth{other._depth}, + _root{other._root}, + _streaming{other._streaming} { - SIMDJSON_PUSH_DISABLE_ALL_WARNINGS - int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; - auto size = static_cast(size_s); - if (size <= 0) return std::string(); - std::unique_ptr buf(new char[size]); - std::snprintf(buf.get(), size, format.c_str(), args...); - SIMDJSON_POP_DISABLE_WARNINGS - return std::string(buf.get(), buf.get() + size - 1); + other.parser = nullptr; } - -static inline log_level get_log_level_from_env() -{ - SIMDJSON_PUSH_DISABLE_WARNINGS - SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe - char *lvl = getenv("SIMDJSON_LOG_LEVEL"); - SIMDJSON_POP_DISABLE_WARNINGS - if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; } - return log_level::info; +simdjson_inline json_iterator &json_iterator::operator=(json_iterator &&other) noexcept { + token = other.token; + parser = other.parser; + _string_buf_loc = other._string_buf_loc; + error = other.error; + _depth = other._depth; + _root = other._root; + _streaming = other._streaming; + other.parser = nullptr; + return *this; } -static inline log_level log_threshold() +simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser) noexcept + : token(buf, &_parser->implementation->structural_indexes[0]), + parser{_parser}, + _string_buf_loc{parser->string_buf.get()}, + _depth{1}, + _root{parser->implementation->structural_indexes.get()}, + _streaming{false} + { - static log_level threshold = get_log_level_from_env(); - return threshold; + logger::log_headers(); +#if SIMDJSON_CHECK_EOF + assert_more_tokens(); +#endif } -static inline bool should_log(log_level level) +#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON +simdjson_inline json_iterator::json_iterator(const uint8_t *buf, ondemand::parser *_parser, bool streaming) noexcept + : token(buf, &_parser->implementation->structural_indexes[0]), + parser{_parser}, + _string_buf_loc{parser->string_buf.get()}, + _depth{1}, + _root{parser->implementation->structural_indexes.get()}, + _streaming{streaming} + { - return level >= log_threshold(); + logger::log_headers(); +#if SIMDJSON_CHECK_EOF + assert_more_tokens(); +#endif } +#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON -inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { - log_line(iter, "", type, detail, delta, depth_delta, log_level::info); +inline void json_iterator::rewind() noexcept { + token.set_position( root_position() ); + logger::log_headers(); // We start again + _string_buf_loc = parser->string_buf.get(); + _depth = 1; } -inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept { - log_line(iter, index, depth, "", type, detail, log_level::info); -} -inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { - log_line(iter, "", type, detail, delta, depth_delta, log_level::info); +inline bool json_iterator::balanced() const noexcept { + token_iterator ti(token); + int32_t count{0}; + ti.set_position( root_position() ); + while(ti.peek() <= peek_last()) { + switch (*ti.return_current_and_advance()) + { + case '[': case '{': + count++; + break; + case ']': case '}': + count--; + break; + default: + break; + } + } + return count == 0; } -inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept { - log_line(iter, index, depth, "+", type, detail, log_level::info); - if (LOG_ENABLED) { log_depth++; } -} -inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept { - log_line(iter, "+", type, "", delta, depth_delta, log_level::info); - if (LOG_ENABLED) { log_depth++; } -} -inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept { - if (LOG_ENABLED) { log_depth--; } - log_line(iter, "-", type, "", delta, depth_delta, log_level::info); +// GCC 7 warns when the first line of this function is inlined away into oblivion due to the caller +// relating depth and parent_depth, which is a desired effect. The warning does not show up if the +// skip_child() function is not marked inline). +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_warn_unused simdjson_inline error_code json_iterator::skip_child(depth_t parent_depth) noexcept { + if (depth() <= parent_depth) { return SUCCESS; } + switch (*return_current_and_advance()) { + // TODO consider whether matching braces is a requirement: if non-matching braces indicates + // *missing* braces, then future lookups are not in the object/arrays they think they are, + // violating the rule "validate enough structure that the user can be confident they are + // looking at the right values." + // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth + + // For the first open array/object in a value, we've already incremented depth, so keep it the same + // We never stop at colon, but if we did, it wouldn't affect depth + case '[': case '{': case ':': + logger::log_start_value(*this, "skip"); + break; + // If there is a comma, we have just finished a value in an array/object, and need to get back in + case ',': + logger::log_value(*this, "skip"); + break; + // ] or } means we just finished a value and need to jump out of the array/object + case ']': case '}': + logger::log_end_value(*this, "skip"); + _depth--; + if (depth() <= parent_depth) { return SUCCESS; } +#if SIMDJSON_CHECK_EOF + // If there are no more tokens, the parent is incomplete. + if (at_end()) { return report_error(INCOMPLETE_ARRAY_OR_OBJECT, "Missing [ or { at start"); } +#endif // SIMDJSON_CHECK_EOF + break; + case '"': + if(*peek() == ':') { + // We are at a key!!! + // This might happen if you just started an object and you skip it immediately. + // Performance note: it would be nice to get rid of this check as it is somewhat + // expensive. + // https://github.com/simdjson/simdjson/issues/1742 + logger::log_value(*this, "key"); + return_current_and_advance(); // eat up the ':' + break; // important!!! + } + simdjson_fallthrough; + // Anything else must be a scalar value + default: + // For the first scalar, we will have incremented depth already, so we decrement it here. + logger::log_value(*this, "skip"); + _depth--; + if (depth() <= parent_depth) { return SUCCESS; } + break; + } + + // Now that we've considered the first value, we only increment/decrement for arrays/objects + while (position() < end_position()) { + switch (*return_current_and_advance()) { + case '[': case '{': + logger::log_start_value(*this, "skip"); + _depth++; + break; + // TODO consider whether matching braces is a requirement: if non-matching braces indicates + // *missing* braces, then future lookups are not in the object/arrays they think they are, + // violating the rule "validate enough structure that the user can be confident they are + // looking at the right values." + // PERF TODO we can eliminate the switch here with a lookup of how much to add to depth + case ']': case '}': + logger::log_end_value(*this, "skip"); + _depth--; + if (depth() <= parent_depth) { return SUCCESS; } + break; + default: + logger::log_value(*this, "skip", ""); + break; + } + } + + return report_error(TAPE_ERROR, "not enough close braces"); } -inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept { - log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error); +SIMDJSON_POP_DISABLE_WARNINGS + +simdjson_inline bool json_iterator::at_root() const noexcept { + return position() == root_position(); } -inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept { - log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error); + +simdjson_inline bool json_iterator::is_single_token() const noexcept { + return parser->implementation->n_structural_indexes == 1; } -inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { - log_event(iter.json_iter(), type, detail, delta, depth_delta); +simdjson_inline bool json_iterator::streaming() const noexcept { + return _streaming; } -inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { - log_value(iter.json_iter(), type, detail, delta, depth_delta); +simdjson_inline token_position json_iterator::root_position() const noexcept { + return _root; } -inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept { - log_start_value(iter.json_iter(), type, delta, depth_delta); +simdjson_inline void json_iterator::assert_at_document_depth() const noexcept { + SIMDJSON_ASSUME( _depth == 1 ); } -inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept { - log_end_value(iter.json_iter(), type, delta, depth_delta); +simdjson_inline void json_iterator::assert_at_root() const noexcept { + SIMDJSON_ASSUME( _depth == 1 ); +#ifndef SIMDJSON_CLANG_VISUAL_STUDIO + // Under Visual Studio, the next SIMDJSON_ASSUME fails with: the argument + // has side effects that will be discarded. + SIMDJSON_ASSUME( token.position() == _root ); +#endif } -inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept { - log_error(iter.json_iter(), error, detail, delta, depth_delta); +simdjson_inline void json_iterator::assert_more_tokens(uint32_t required_tokens) const noexcept { + assert_valid_position(token._position + required_tokens - 1); } -inline void log_headers() noexcept { - if (LOG_ENABLED) { - if (simdjson_unlikely(should_log(log_level::info))) { - // Technically a static variable is not thread-safe, but if you are using threads and logging... well... - static bool displayed_hint{false}; - log_depth = 0; - printf("\n"); - if (!displayed_hint) { - // We only print this helpful header once. - printf("# Logging provides the depth and position of the iterator user-visible steps:\n"); - printf("# +array says 'this is where we were when we discovered the start array'\n"); - printf( - "# -array says 'this is where we were when we ended the array'\n"); - printf("# skip says 'this is a structural or value I am skipping'\n"); - printf("# +/-skip says 'this is a start/end array or object I am skipping'\n"); - printf("#\n"); - printf("# The indentation of the terms (array, string,...) indicates the depth,\n"); - printf("# in addition to the depth being displayed.\n"); - printf("#\n"); - printf("# Every token in the document has a single depth determined by the tokens before it,\n"); - printf("# and is not affected by what the token actually is.\n"); - printf("#\n"); - printf("# Not all structural elements are presented as tokens in the logs.\n"); - printf("#\n"); - printf("# We never give control to the user within an empty array or an empty object.\n"); - printf("#\n"); - printf("# Inside an array, having a depth greater than the array's depth means that\n"); - printf("# we are pointing inside a value.\n"); - printf("# Having a depth equal to the array means that we are pointing right before a value.\n"); - printf("# Having a depth smaller than the array means that we have moved beyond the array.\n"); - displayed_hint = true; - } - printf("\n"); - printf("| %-*s ", LOG_EVENT_LEN, "Event"); - printf("| %-*s ", LOG_BUFFER_LEN, "Buffer"); - printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next"); - // printf("| %-*s ", 5, "Next#"); - printf("| %-*s ", 5, "Depth"); - printf("| Detail "); - printf("|\n"); +simdjson_inline void json_iterator::assert_valid_position(token_position position) const noexcept { +#ifndef SIMDJSON_CLANG_VISUAL_STUDIO + SIMDJSON_ASSUME( position >= &parser->implementation->structural_indexes[0] ); + SIMDJSON_ASSUME( position < &parser->implementation->structural_indexes[parser->implementation->n_structural_indexes] ); +#endif +} - printf("|%.*s", LOG_EVENT_LEN + 2, DASHES); - printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES); - printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES); - // printf("|%.*s", 5+2, DASHES); - printf("|%.*s", 5 + 2, DASHES); - printf("|--------"); - printf("|\n"); - fflush(stdout); - } - } +simdjson_inline bool json_iterator::at_end() const noexcept { + return position() == end_position(); +} +simdjson_inline token_position json_iterator::end_position() const noexcept { + uint32_t n_structural_indexes{parser->implementation->n_structural_indexes}; + return &parser->implementation->structural_indexes[n_structural_indexes]; } -template -inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept { - log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward(args)...); +inline std::string json_iterator::to_string() const noexcept { + if( !is_alive() ) { return "dead json_iterator instance"; } + const char * current_structural = reinterpret_cast(token.peek()); + return std::string("json_iterator [ depth : ") + std::to_string(_depth) + + std::string(", structural : '") + std::string(current_structural,1) + + std::string("', offset : ") + std::to_string(token.current_offset()) + + std::string("', error : ") + error_message(error) + + std::string(" ]"); } -template -inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept { - if (LOG_ENABLED) { - if (simdjson_unlikely(should_log(level))) { - const int indent = depth * 2; - const auto buf = iter.token.buf; - auto msg = string_format(title, std::forward(args)...); - printf("| %*s%s%-*s ", indent, "", title_prefix, - LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str()); - { - // Print the current structural. - printf("| "); - // Before we begin, the index might point right before the document. - // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938 - if (index < iter._root) { - printf("%*s", LOG_BUFFER_LEN, ""); - } else { - auto current_structural = &buf[*index]; - for (int i = 0; i < LOG_BUFFER_LEN; i++) { - printf("%c", printable_char(current_structural[i])); - } - } - printf(" "); - } - { - // Print the next structural. - printf("| "); - auto next_structural = &buf[*(index + 1)]; - for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) { - printf("%c", printable_char(next_structural[i])); - } - printf(" "); - } - // printf("| %5u ", *(index+1)); - printf("| %5i ", depth); - printf("| %6.*s ", int(detail.size()), detail.data()); - printf("|\n"); - fflush(stdout); +inline simdjson_result json_iterator::current_location() const noexcept { + if (!is_alive()) { // Unrecoverable error + if (!at_root()) { + return reinterpret_cast(token.peek(-1)); + } else { + return reinterpret_cast(token.peek()); } } + if (at_end()) { + return OUT_OF_BOUNDS; + } + return reinterpret_cast(token.peek()); } -} // namespace logger -} // namespace ondemand -} // namespace lasx -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H -/* end file simdjson/generic/ondemand/logger-inl.h for lasx */ -/* including simdjson/generic/ondemand/object-inl.h for lasx: #include "simdjson/generic/ondemand/object-inl.h" */ -/* begin file simdjson/generic/ondemand/object-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H +simdjson_inline bool json_iterator::is_alive() const noexcept { + return parser; +} -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +simdjson_inline void json_iterator::abandon() noexcept { + parser = nullptr; + _depth = 0; +} -namespace simdjson { -namespace lasx { -namespace ondemand { +simdjson_inline const uint8_t *json_iterator::return_current_and_advance() noexcept { +#if SIMDJSON_CHECK_EOF + assert_more_tokens(); +#endif // SIMDJSON_CHECK_EOF + return token.return_current_and_advance(); +} -simdjson_inline simdjson_result object::find_field_unordered(const std::string_view key) & noexcept { - bool has_value; - SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) ); - if (!has_value) { - logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); - return NO_SUCH_FIELD; - } - return value(iter.child()); +simdjson_inline const uint8_t *json_iterator::unsafe_pointer() const noexcept { + // deliberately done without safety guard: + return token.peek(); } -simdjson_inline simdjson_result object::find_field_unordered(const std::string_view key) && noexcept { - bool has_value; - SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) ); - if (!has_value) { - logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); - return NO_SUCH_FIELD; - } - return value(iter.child()); + +simdjson_inline const uint8_t *json_iterator::peek(int32_t delta) const noexcept { +#if SIMDJSON_CHECK_EOF + assert_more_tokens(delta+1); +#endif // SIMDJSON_CHECK_EOF + return token.peek(delta); } -simdjson_inline simdjson_result object::operator[](const std::string_view key) & noexcept { - return find_field_unordered(key); + +simdjson_inline uint32_t json_iterator::peek_length(int32_t delta) const noexcept { +#if SIMDJSON_CHECK_EOF + assert_more_tokens(delta+1); +#endif // #if SIMDJSON_CHECK_EOF + return token.peek_length(delta); } -simdjson_inline simdjson_result object::operator[](const std::string_view key) && noexcept { - return std::forward(*this).find_field_unordered(key); + +simdjson_inline const uint8_t *json_iterator::peek(token_position position) const noexcept { + // todo: currently we require end-of-string buffering, but the following + // assert_valid_position should be turned on if/when we lift that condition. + // assert_valid_position(position); + // This is almost surely related to SIMDJSON_CHECK_EOF but given that SIMDJSON_CHECK_EOF + // is ON by default, we have no choice but to disable it for real with a comment. + return token.peek(position); } -simdjson_inline simdjson_result object::find_field(const std::string_view key) & noexcept { - bool has_value; - SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) ); - if (!has_value) { - logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); - return NO_SUCH_FIELD; - } - return value(iter.child()); + +simdjson_inline uint32_t json_iterator::peek_length(token_position position) const noexcept { +#if SIMDJSON_CHECK_EOF + assert_valid_position(position); +#endif // SIMDJSON_CHECK_EOF + return token.peek_length(position); } -simdjson_inline simdjson_result object::find_field(const std::string_view key) && noexcept { - bool has_value; - SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) ); - if (!has_value) { - logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); - return NO_SUCH_FIELD; - } - return value(iter.child()); +simdjson_inline uint32_t json_iterator::peek_root_length(token_position position) const noexcept { +#if SIMDJSON_CHECK_EOF + assert_valid_position(position); +#endif // SIMDJSON_CHECK_EOF + return token.peek_root_length(position); } -simdjson_inline simdjson_result object::start(value_iterator &iter) noexcept { - SIMDJSON_TRY( iter.start_object().error() ); - return object(iter); +simdjson_inline token_position json_iterator::last_position() const noexcept { + // The following line fails under some compilers... + // SIMDJSON_ASSUME(parser->implementation->n_structural_indexes > 0); + // since it has side-effects. + uint32_t n_structural_indexes{parser->implementation->n_structural_indexes}; + SIMDJSON_ASSUME(n_structural_indexes > 0); + return &parser->implementation->structural_indexes[n_structural_indexes - 1]; } -simdjson_inline simdjson_result object::start_root(value_iterator &iter) noexcept { - SIMDJSON_TRY( iter.start_root_object().error() ); - return object(iter); +simdjson_inline const uint8_t *json_iterator::peek_last() const noexcept { + return token.peek(last_position()); } -simdjson_inline error_code object::consume() noexcept { - if(iter.is_at_key()) { - /** - * whenever you are pointing at a key, calling skip_child() is - * unsafe because you will hit a string and you will assume that - * it is string value, and this mistake will lead you to make bad - * depth computation. - */ - /** - * We want to 'consume' the key. We could really - * just do _json_iter->return_current_and_advance(); at this - * point, but, for clarity, we will use the high-level API to - * eat the key. We assume that the compiler optimizes away - * most of the work. - */ - simdjson_unused raw_json_string actual_key; - auto error = iter.field_key().get(actual_key); - if (error) { iter.abandon(); return error; }; - // Let us move to the value while we are at it. - if ((error = iter.field_value())) { iter.abandon(); return error; } - } - auto error_skip = iter.json_iter().skip_child(iter.depth()-1); - if(error_skip) { iter.abandon(); } - return error_skip; + +simdjson_inline void json_iterator::ascend_to(depth_t parent_depth) noexcept { + SIMDJSON_ASSUME(parent_depth >= 0 && parent_depth < INT32_MAX - 1); + SIMDJSON_ASSUME(_depth == parent_depth + 1); + _depth = parent_depth; } -simdjson_inline simdjson_result object::raw_json() noexcept { - const uint8_t * starting_point{iter.peek_start()}; - auto error = consume(); - if(error) { return error; } - const uint8_t * final_point{iter._json_iter->peek()}; - return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +simdjson_inline void json_iterator::descend_to(depth_t child_depth) noexcept { + SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX); + SIMDJSON_ASSUME(_depth == child_depth - 1); + _depth = child_depth; } -simdjson_inline simdjson_result object::started(value_iterator &iter) noexcept { - SIMDJSON_TRY( iter.started_object().error() ); - return object(iter); +simdjson_inline depth_t json_iterator::depth() const noexcept { + return _depth; } -simdjson_inline object object::resume(const value_iterator &iter) noexcept { - return iter; +simdjson_inline uint8_t *&json_iterator::string_buf_loc() noexcept { + return _string_buf_loc; } -simdjson_inline object::object(const value_iterator &_iter) noexcept - : iter{_iter} -{ +simdjson_inline error_code json_iterator::report_error(error_code _error, const char *message) noexcept { + SIMDJSON_ASSUME(_error != SUCCESS && _error != UNINITIALIZED && _error != INCORRECT_TYPE && _error != NO_SUCH_FIELD); + logger::log_error(*this, message); + error = _error; + return error; } -simdjson_inline simdjson_result object::begin() noexcept { +simdjson_inline token_position json_iterator::position() const noexcept { + return token.position(); +} + +simdjson_inline simdjson_result json_iterator::unescape(raw_json_string in, bool allow_replacement) noexcept { #if SIMDJSON_DEVELOPMENT_CHECKS - if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; } + auto result = parser->unescape(in, _string_buf_loc, allow_replacement); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else + return parser->unescape(in, _string_buf_loc, allow_replacement); #endif - return object_iterator(iter); -} -simdjson_inline simdjson_result object::end() noexcept { - return object_iterator(iter); } -inline simdjson_result object::at_pointer(std::string_view json_pointer) noexcept { - if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; } - json_pointer = json_pointer.substr(1); - size_t slash = json_pointer.find('/'); - std::string_view key = json_pointer.substr(0, slash); - // Grab the child with the given key - simdjson_result child; +simdjson_inline simdjson_result json_iterator::unescape_wobbly(raw_json_string in) noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + auto result = parser->unescape_wobbly(in, _string_buf_loc); + SIMDJSON_ASSUME(!parser->string_buffer_overflow(_string_buf_loc)); + return result; +#else + return parser->unescape_wobbly(in, _string_buf_loc); +#endif +} - // If there is an escape character in the key, unescape it and then get the child. - size_t escape = key.find('~'); - if (escape != std::string_view::npos) { - // Unescape the key - std::string unescaped(key); - do { - switch (unescaped[escape+1]) { - case '0': - unescaped.replace(escape, 2, "~"); - break; - case '1': - unescaped.replace(escape, 2, "/"); - break; - default: - return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer"); - } - escape = unescaped.find('~', escape+1); - } while (escape != std::string::npos); - child = find_field(unescaped); // Take note find_field does not unescape keys when matching - } else { - child = find_field(key); - } - if(child.error()) { - return child; // we do not continue if there was an error - } - // If there is a /, we have to recurse and look up more of the path - if (slash != std::string_view::npos) { - child = child.at_pointer(json_pointer.substr(slash)); - } - return child; +simdjson_inline void json_iterator::reenter_child(token_position position, depth_t child_depth) noexcept { + SIMDJSON_ASSUME(child_depth >= 1 && child_depth < INT32_MAX); + SIMDJSON_ASSUME(_depth == child_depth - 1); +#if SIMDJSON_DEVELOPMENT_CHECKS +#ifndef SIMDJSON_CLANG_VISUAL_STUDIO + SIMDJSON_ASSUME(size_t(child_depth) < parser->max_depth()); + SIMDJSON_ASSUME(position >= parser->start_positions[child_depth]); +#endif +#endif + token.set_position(position); + _depth = child_depth; } -inline simdjson_result object::at_path(std::string_view json_path) noexcept { - auto json_pointer = json_path_to_pointer_conversion(json_path); - if (json_pointer == "-1") { - return INVALID_JSON_POINTER; +simdjson_inline error_code json_iterator::consume_character(char c) noexcept { + if (*peek() == c) { + return_current_and_advance(); + return SUCCESS; } - return at_pointer(json_pointer); + return TAPE_ERROR; } -simdjson_inline simdjson_result object::count_fields() & noexcept { - size_t count{0}; - // Important: we do not consume any of the values. - for(simdjson_unused auto v : *this) { count++; } - // The above loop will always succeed, but we want to report errors. - if(iter.error()) { return iter.error(); } - // We need to move back at the start because we expect users to iterate through - // the object after counting the number of elements. - iter.reset_object(); - return count; -} +#if SIMDJSON_DEVELOPMENT_CHECKS -simdjson_inline simdjson_result object::is_empty() & noexcept { - bool is_not_empty; - auto error = iter.reset_object().get(is_not_empty); - if(error) { return error; } - return !is_not_empty; +simdjson_inline token_position json_iterator::start_position(depth_t depth) const noexcept { + SIMDJSON_ASSUME(size_t(depth) < parser->max_depth()); + return size_t(depth) < parser->max_depth() ? parser->start_positions[depth] : 0; } -simdjson_inline simdjson_result object::reset() & noexcept { - return iter.reset_object(); +simdjson_inline void json_iterator::set_start_position(depth_t depth, token_position position) noexcept { + SIMDJSON_ASSUME(size_t(depth) < parser->max_depth()); + if(size_t(depth) < parser->max_depth()) { parser->start_positions[depth] = position; } } -} // namespace ondemand -} // namespace lasx -} // namespace simdjson - -namespace simdjson { +#endif -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::object &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} -simdjson_inline simdjson_result simdjson_result::begin() noexcept { - if (error()) { return error(); } - return first.begin(); -} -simdjson_inline simdjson_result simdjson_result::end() noexcept { - if (error()) { return error(); } - return first.end(); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) && noexcept { - if (error()) { return error(); } - return std::forward(first).find_field_unordered(key); -} -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { - if (error()) { return error(); } - return first[key]; -} -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) && noexcept { - if (error()) { return error(); } - return std::forward(first)[key]; -} -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { - if (error()) { return error(); } - return first.find_field(key); -} -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) && noexcept { - if (error()) { return error(); } - return std::forward(first).find_field(key); +simdjson_inline error_code json_iterator::optional_error(error_code _error, const char *message) noexcept { + SIMDJSON_ASSUME(_error == INCORRECT_TYPE || _error == NO_SUCH_FIELD); + logger::log_error(*this, message); + return _error; } -simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { - if (error()) { return error(); } - return first.at_pointer(json_pointer); -} -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); +simdjson_warn_unused simdjson_inline bool json_iterator::copy_to_buffer(const uint8_t *json, uint32_t max_len, uint8_t *tmpbuf, size_t N) noexcept { + // This function is not expected to be called in performance-sensitive settings. + // Let us guard against silly cases: + if((N < max_len) || (N == 0)) { return false; } + // Copy to the buffer. + std::memcpy(tmpbuf, json, max_len); + if(N > max_len) { // We pad whatever remains with ' '. + std::memset(tmpbuf + max_len, ' ', N - max_len); } - return first.at_path(json_path); + return true; } -inline simdjson_result simdjson_result::reset() noexcept { - if (error()) { return error(); } - return first.reset(); -} +} // namespace ondemand +} // namespace lasx +} // namespace simdjson -inline simdjson_result simdjson_result::is_empty() noexcept { - if (error()) { return error(); } - return first.is_empty(); -} +namespace simdjson { -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { - if (error()) { return error(); } - return first.count_fields(); -} +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::json_iterator &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); -} } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H -/* end file simdjson/generic/ondemand/object-inl.h for lasx */ -/* including simdjson/generic/ondemand/object_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/object_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/object_iterator-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_ITERATOR_INL_H +/* end file simdjson/generic/ondemand/json_iterator-inl.h for lasx */ +/* including simdjson/generic/ondemand/json_type-inl.h for lasx: #include "simdjson/generic/ondemand/json_type-inl.h" */ +/* begin file simdjson/generic/ondemand/json_type-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { namespace lasx { namespace ondemand { -// -// object_iterator -// - -simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept - : iter{_iter} -{} - -simdjson_inline simdjson_result object_iterator::operator*() noexcept { - error_code error = iter.error(); - if (error) { iter.abandon(); return error; } - auto result = field::start(iter); - // TODO this is a safety rail ... users should exit loops as soon as they receive an error. - // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free. - if (result.error()) { iter.abandon(); } - return result; -} -simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept { - return !(*this != other); +inline std::ostream& operator<<(std::ostream& out, json_type type) noexcept { + switch (type) { + case json_type::array: out << "array"; break; + case json_type::object: out << "object"; break; + case json_type::number: out << "number"; break; + case json_type::string: out << "string"; break; + case json_type::boolean: out << "boolean"; break; + case json_type::null: out << "null"; break; + default: SIMDJSON_UNREACHABLE(); + } + return out; } -simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept { - return iter.is_open(); + +#if SIMDJSON_EXCEPTIONS +inline std::ostream& operator<<(std::ostream& out, simdjson_result &type) noexcept(false) { + return out << type.value(); } +#endif -SIMDJSON_PUSH_DISABLE_WARNINGS -SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING -simdjson_inline object_iterator &object_iterator::operator++() noexcept { - // TODO this is a safety rail ... users should exit loops as soon as they receive an error. - // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free. - if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error - simdjson_unused error_code error; - if ((error = iter.skip_child() )) { return *this; } - simdjson_unused bool has_value; - if ((error = iter.has_next_field().get(has_value) )) { return *this; }; - return *this; +simdjson_inline number_type number::get_number_type() const noexcept { + return type; } -SIMDJSON_POP_DISABLE_WARNINGS -// -// ### Live States -// -// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is -// always SUCCESS: -// -// - Start: This is the state when the object is first found and the iterator is just past the {. -// In this state, at_start == true. -// - Next: After we hand a scalar value to the user, or an array/object which they then fully -// iterate over, the iterator is at the , or } before the next value. In this state, -// depth == iter.depth, at_start == false, and error == SUCCESS. -// - Unfinished Business: When we hand an array/object to the user which they do not fully -// iterate over, we need to finish that iteration by skipping child values until we reach the -// Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS. -// -// ## Error States -// -// In error states, we will yield exactly one more value before stopping. iter.depth == depth -// and at_start is always false. We decrement after yielding the error, moving to the Finished -// state. -// -// - Chained Error: When the object iterator is part of an error chain--for example, in -// `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an -// object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and -// iter.depth == depth, and at_start == false. We decrement depth when we yield the error. -// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields, -// we flag that as an error and treat it exactly the same as a Chained Error. In this state, -// error == TAPE_ERROR, iter.depth == depth, and at_start == false. -// -// Errors that occur while reading a field to give to the user (such as when the key is not a -// string or the field is missing a colon) are yielded immediately. Depth is then decremented, -// moving to the Finished state without transitioning through an Error state at all. -// -// ## Terminal State -// -// The terminal state has iter.depth < depth. at_start is always false. -// -// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth. -// In this state, iter.depth < depth, at_start == false, and error == SUCCESS. -// +simdjson_inline bool number::is_uint64() const noexcept { + return get_number_type() == number_type::unsigned_integer; +} -} // namespace ondemand -} // namespace lasx -} // namespace simdjson +simdjson_inline uint64_t number::get_uint64() const noexcept { + return payload.unsigned_integer; +} -namespace simdjson { +simdjson_inline number::operator uint64_t() const noexcept { + return get_uint64(); +} -simdjson_inline simdjson_result::simdjson_result( - lasx::ondemand::object_iterator &&value -) noexcept - : implementation_simdjson_result_base(std::forward(value)) -{ - first.iter.assert_is_valid(); +simdjson_inline bool number::is_int64() const noexcept { + return get_number_type() == number_type::signed_integer; } -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base({}, error) -{ + +simdjson_inline int64_t number::get_int64() const noexcept { + return payload.signed_integer; } -simdjson_inline simdjson_result simdjson_result::operator*() noexcept { - if (error()) { return error(); } - return *first; +simdjson_inline number::operator int64_t() const noexcept { + return get_int64(); } -// If we're iterating and there is an error, return the error once. -simdjson_inline bool simdjson_result::operator==(const simdjson_result &other) const noexcept { - if (!first.iter.is_valid()) { return !error(); } - return first == other.first; + +simdjson_inline bool number::is_double() const noexcept { + return get_number_type() == number_type::floating_point_number; } -// If we're iterating and there is an error, return the error once. -simdjson_inline bool simdjson_result::operator!=(const simdjson_result &other) const noexcept { - if (!first.iter.is_valid()) { return error(); } - return first != other.first; + +simdjson_inline double number::get_double() const noexcept { + return payload.floating_point_number; } -// Checks for ']' and ',' -simdjson_inline simdjson_result &simdjson_result::operator++() noexcept { - // Clear the error if there is one, so we don't yield it twice - if (error()) { second = SUCCESS; return *this; } - ++first; - return *this; + +simdjson_inline number::operator double() const noexcept { + return get_double(); } -} // namespace simdjson +simdjson_inline double number::as_double() const noexcept { + if(is_double()) { + return payload.floating_point_number; + } + if(is_int64()) { + return double(payload.signed_integer); + } + return double(payload.unsigned_integer); +} -#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H -/* end file simdjson/generic/ondemand/object_iterator-inl.h for lasx */ -/* including simdjson/generic/ondemand/parser-inl.h for lasx: #include "simdjson/generic/ondemand/parser-inl.h" */ -/* begin file simdjson/generic/ondemand/parser-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H +simdjson_inline void number::append_s64(int64_t value) noexcept { + payload.signed_integer = value; + type = number_type::signed_integer; +} -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ +simdjson_inline void number::append_u64(uint64_t value) noexcept { + payload.unsigned_integer = value; + type = number_type::unsigned_integer; +} -namespace simdjson { -namespace lasx { -namespace ondemand { +simdjson_inline void number::append_double(double value) noexcept { + payload.floating_point_number = value; + type = number_type::floating_point_number; +} -simdjson_inline parser::parser(size_t max_capacity) noexcept - : _max_capacity{max_capacity} { +simdjson_inline void number::skip_double() noexcept { + type = number_type::floating_point_number; } -simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept { - if (new_capacity > max_capacity()) { return CAPACITY; } - if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; } +} // namespace ondemand +} // namespace lasx +} // namespace simdjson - // string_capacity copied from document::allocate - _capacity = 0; - size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64); - string_buf.reset(new (std::nothrow) uint8_t[string_capacity]); -#if SIMDJSON_DEVELOPMENT_CHECKS - start_positions.reset(new (std::nothrow) token_position[new_max_depth]); -#endif - if (implementation) { - SIMDJSON_TRY( implementation->set_capacity(new_capacity) ); - SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) ); - } else { - SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) ); - } - _capacity = new_capacity; - _max_depth = new_max_depth; - return SUCCESS; -} -#if SIMDJSON_DEVELOPMENT_CHECKS -simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { - return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); -} -#endif +namespace simdjson { -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { - if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::json_type &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} - json.remove_utf8_bom(); +} // namespace simdjson - // Allocate if needed - if (capacity() < json.length() || !string_buf) { - SIMDJSON_TRY( allocate(json.length(), max_depth()) ); - } +#endif // SIMDJSON_GENERIC_ONDEMAND_JSON_TYPE_INL_H +/* end file simdjson/generic/ondemand/json_type-inl.h for lasx */ +/* including simdjson/generic/ondemand/logger-inl.h for lasx: #include "simdjson/generic/ondemand/logger-inl.h" */ +/* begin file simdjson/generic/ondemand/logger-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H - // Run stage 1. - SIMDJSON_TRY( implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular) ); - return document::start({ reinterpret_cast(json.data()), this }); -} +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/logger.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ -#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate_allow_incomplete_json(padded_string_view json) & noexcept { - if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } +#include +#include - json.remove_utf8_bom(); +namespace simdjson { +namespace lasx { +namespace ondemand { +namespace logger { - // Allocate if needed - if (capacity() < json.length() || !string_buf) { - SIMDJSON_TRY( allocate(json.length(), max_depth()) ); - } +static constexpr const char * DASHES = "----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------"; +static constexpr const int LOG_EVENT_LEN = 20; +static constexpr const int LOG_BUFFER_LEN = 30; +static constexpr const int LOG_SMALL_BUFFER_LEN = 10; +static int log_depth = 0; // Not threadsafe. Log only. - // Run stage 1. - const simdjson::error_code err = implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular); - if (err) { - if (err != UNCLOSED_STRING) - return err; +// Helper to turn unprintable or newline characters into spaces +static inline char printable_char(char c) { + if (c >= 0x20) { + return c; + } else { + return ' '; } - return document::start({ reinterpret_cast(json.data()), this, true }); } -#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const char *json, size_t len, size_t allocated) & noexcept { - return iterate(padded_string_view(json, len, allocated)); +template +static inline std::string string_format(const std::string& format, const Args&... args) +{ + SIMDJSON_PUSH_DISABLE_ALL_WARNINGS + int size_s = std::snprintf(nullptr, 0, format.c_str(), args...) + 1; + auto size = static_cast(size_s); + if (size <= 0) return std::string(); + std::unique_ptr buf(new char[size]); + std::snprintf(buf.get(), size, format.c_str(), args...); + SIMDJSON_POP_DISABLE_WARNINGS + return std::string(buf.get(), buf.get() + size - 1); } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept { - return iterate(padded_string_view(json, len, allocated)); +static inline log_level get_log_level_from_env() +{ + SIMDJSON_PUSH_DISABLE_WARNINGS + SIMDJSON_DISABLE_DEPRECATED_WARNING // Disable CRT_SECURE warning on MSVC: manually verified this is safe + char *lvl = getenv("SIMDJSON_LOG_LEVEL"); + SIMDJSON_POP_DISABLE_WARNINGS + if (lvl && simdjson_strcasecmp(lvl, "ERROR") == 0) { return log_level::error; } + return log_level::info; } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(std::string_view json, size_t allocated) & noexcept { - return iterate(padded_string_view(json, allocated)); +static inline log_level log_threshold() +{ + static log_level threshold = get_log_level_from_env(); + return threshold; } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(std::string &json) & noexcept { - if(json.capacity() - json.size() < SIMDJSON_PADDING) { - json.reserve(json.size() + SIMDJSON_PADDING); - } - return iterate(padded_string_view(json)); +static inline bool should_log(log_level level) +{ + return level >= log_threshold(); } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const std::string &json) & noexcept { - return iterate(padded_string_view(json)); +inline void log_event(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { + log_line(iter, "", type, detail, delta, depth_delta, log_level::info); } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const simdjson_result &result) & noexcept { - // We don't presently have a way to temporarily get a const T& from a simdjson_result without throwing an exception - SIMDJSON_TRY( result.error() ); - padded_string_view json = result.value_unsafe(); - return iterate(json); +inline void log_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept { + log_line(iter, index, depth, "", type, detail, log_level::info); } - -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const simdjson_result &result) & noexcept { - // We don't presently have a way to temporarily get a const T& from a simdjson_result without throwing an exception - SIMDJSON_TRY( result.error() ); - const padded_string &json = result.value_unsafe(); - return iterate(json); +inline void log_value(const json_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { + log_line(iter, "", type, detail, delta, depth_delta, log_level::info); } -simdjson_warn_unused simdjson_inline simdjson_result parser::iterate_raw(padded_string_view json) & noexcept { - if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } - - json.remove_utf8_bom(); - - // Allocate if needed - if (capacity() < json.length()) { - SIMDJSON_TRY( allocate(json.length(), max_depth()) ); - } +inline void log_start_value(const json_iterator &iter, token_position index, depth_t depth, const char *type, std::string_view detail) noexcept { + log_line(iter, index, depth, "+", type, detail, log_level::info); + if (LOG_ENABLED) { log_depth++; } +} +inline void log_start_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept { + log_line(iter, "+", type, "", delta, depth_delta, log_level::info); + if (LOG_ENABLED) { log_depth++; } +} - // Run stage 1. - SIMDJSON_TRY( implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular) ); - return json_iterator(reinterpret_cast(json.data()), this); +inline void log_end_value(const json_iterator &iter, const char *type, int delta, int depth_delta) noexcept { + if (LOG_ENABLED) { log_depth--; } + log_line(iter, "-", type, "", delta, depth_delta, log_level::info); } -inline simdjson_result parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept { - if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; } - if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) { - buf += 3; - len -= 3; - } - if(allow_comma_separated && batch_size < len) { batch_size = len; } - return document_stream(*this, buf, len, batch_size, allow_comma_separated); +inline void log_error(const json_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept { + log_line(iter, "ERROR: ", error, detail, delta, depth_delta, log_level::error); } -inline simdjson_result parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept { - return iterate_many(reinterpret_cast(buf), len, batch_size, allow_comma_separated); +inline void log_error(const json_iterator &iter, token_position index, depth_t depth, const char *error, const char *detail) noexcept { + log_line(iter, index, depth, "ERROR: ", error, detail, log_level::error); } -inline simdjson_result parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept { - return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated); + +inline void log_event(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { + log_event(iter.json_iter(), type, detail, delta, depth_delta); } -inline simdjson_result parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept { - return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated); + +inline void log_value(const value_iterator &iter, const char *type, std::string_view detail, int delta, int depth_delta) noexcept { + log_value(iter.json_iter(), type, detail, delta, depth_delta); } -simdjson_pure simdjson_inline size_t parser::capacity() const noexcept { - return _capacity; +inline void log_start_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept { + log_start_value(iter.json_iter(), type, delta, depth_delta); } -simdjson_pure simdjson_inline size_t parser::max_capacity() const noexcept { - return _max_capacity; + +inline void log_end_value(const value_iterator &iter, const char *type, int delta, int depth_delta) noexcept { + log_end_value(iter.json_iter(), type, delta, depth_delta); } -simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept { - return _max_depth; + +inline void log_error(const value_iterator &iter, const char *error, const char *detail, int delta, int depth_delta) noexcept { + log_error(iter.json_iter(), error, detail, delta, depth_delta); } -simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept { - if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) { - _max_capacity = max_capacity; - } else { - _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY; +inline void log_headers() noexcept { + if (LOG_ENABLED) { + if (simdjson_unlikely(should_log(log_level::info))) { + // Technically a static variable is not thread-safe, but if you are using threads and logging... well... + static bool displayed_hint{false}; + log_depth = 0; + printf("\n"); + if (!displayed_hint) { + // We only print this helpful header once. + printf("# Logging provides the depth and position of the iterator user-visible steps:\n"); + printf("# +array says 'this is where we were when we discovered the start array'\n"); + printf( + "# -array says 'this is where we were when we ended the array'\n"); + printf("# skip says 'this is a structural or value I am skipping'\n"); + printf("# +/-skip says 'this is a start/end array or object I am skipping'\n"); + printf("#\n"); + printf("# The indentation of the terms (array, string,...) indicates the depth,\n"); + printf("# in addition to the depth being displayed.\n"); + printf("#\n"); + printf("# Every token in the document has a single depth determined by the tokens before it,\n"); + printf("# and is not affected by what the token actually is.\n"); + printf("#\n"); + printf("# Not all structural elements are presented as tokens in the logs.\n"); + printf("#\n"); + printf("# We never give control to the user within an empty array or an empty object.\n"); + printf("#\n"); + printf("# Inside an array, having a depth greater than the array's depth means that\n"); + printf("# we are pointing inside a value.\n"); + printf("# Having a depth equal to the array means that we are pointing right before a value.\n"); + printf("# Having a depth smaller than the array means that we have moved beyond the array.\n"); + displayed_hint = true; + } + printf("\n"); + printf("| %-*s ", LOG_EVENT_LEN, "Event"); + printf("| %-*s ", LOG_BUFFER_LEN, "Buffer"); + printf("| %-*s ", LOG_SMALL_BUFFER_LEN, "Next"); + // printf("| %-*s ", 5, "Next#"); + printf("| %-*s ", 5, "Depth"); + printf("| Detail "); + printf("|\n"); + + printf("|%.*s", LOG_EVENT_LEN + 2, DASHES); + printf("|%.*s", LOG_BUFFER_LEN + 2, DASHES); + printf("|%.*s", LOG_SMALL_BUFFER_LEN + 2, DASHES); + // printf("|%.*s", 5+2, DASHES); + printf("|%.*s", 5 + 2, DASHES); + printf("|--------"); + printf("|\n"); + fflush(stdout); + } } } -simdjson_inline simdjson_warn_unused simdjson_result parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept { - uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement); - if (!end) { return STRING_ERROR; } - std::string_view result(reinterpret_cast(dst), end-dst); - dst = end; - return result; +template +inline void log_line(const json_iterator &iter, const char *title_prefix, const char *title, std::string_view detail, int delta, int depth_delta, log_level level, Args&&... args) noexcept { + log_line(iter, iter.position()+delta, depth_t(iter.depth()+depth_delta), title_prefix, title, detail, level, std::forward(args)...); } -simdjson_inline simdjson_warn_unused simdjson_result parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept { - uint8_t *end = implementation->parse_wobbly_string(in.buf, dst); - if (!end) { return STRING_ERROR; } - std::string_view result(reinterpret_cast(dst), end-dst); - dst = end; - return result; +template +inline void log_line(const json_iterator &iter, token_position index, depth_t depth, const char *title_prefix, const char *title, std::string_view detail, log_level level, Args&&... args) noexcept { + if (LOG_ENABLED) { + if (simdjson_unlikely(should_log(level))) { + const int indent = depth * 2; + const auto buf = iter.token.buf; + auto msg = string_format(title, std::forward(args)...); + printf("| %*s%s%-*s ", indent, "", title_prefix, + LOG_EVENT_LEN - indent - int(strlen(title_prefix)), msg.c_str()); + { + // Print the current structural. + printf("| "); + // Before we begin, the index might point right before the document. + // This could be unsafe, see https://github.com/simdjson/simdjson/discussions/1938 + if (index < iter._root) { + printf("%*s", LOG_BUFFER_LEN, ""); + } else { + auto current_structural = &buf[*index]; + for (int i = 0; i < LOG_BUFFER_LEN; i++) { + printf("%c", printable_char(current_structural[i])); + } + } + printf(" "); + } + { + // Print the next structural. + printf("| "); + auto next_structural = &buf[*(index + 1)]; + for (int i = 0; i < LOG_SMALL_BUFFER_LEN; i++) { + printf("%c", printable_char(next_structural[i])); + } + printf(" "); + } + // printf("| %5u ", *(index+1)); + printf("| %5i ", depth); + printf("| %6.*s ", int(detail.size()), detail.data()); + printf("|\n"); + fflush(stdout); + } + } } +} // namespace logger } // namespace ondemand } // namespace lasx } // namespace simdjson -namespace simdjson { - -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::parser &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} - -} // namespace simdjson - -#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H -/* end file simdjson/generic/ondemand/parser-inl.h for lasx */ -/* including simdjson/generic/ondemand/raw_json_string-inl.h for lasx: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ -/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_LOGGER_INL_H +/* end file simdjson/generic/ondemand/logger-inl.h for lasx */ +/* including simdjson/generic/ondemand/object-inl.h for lasx: #include "simdjson/generic/ondemand/object-inl.h" */ +/* begin file simdjson/generic/ondemand/object-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { - namespace lasx { namespace ondemand { -simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {} - -simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast(buf); } - - -simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { - size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;pos < target.size() && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;pos < target.size();pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; - } +simdjson_inline simdjson_result object::find_field_unordered(const std::string_view key) & noexcept { + bool has_value; + SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) ); + if (!has_value) { + logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); + return NO_SUCH_FIELD; } - return true; + return value(iter.child()); +} +simdjson_inline simdjson_result object::find_field_unordered(const std::string_view key) && noexcept { + bool has_value; + SIMDJSON_TRY( iter.find_field_unordered_raw(key).get(has_value) ); + if (!has_value) { + logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); + return NO_SUCH_FIELD; + } + return value(iter.child()); +} +simdjson_inline simdjson_result object::operator[](const std::string_view key) & noexcept { + return find_field_unordered(key); +} +simdjson_inline simdjson_result object::operator[](const std::string_view key) && noexcept { + return std::forward(*this).find_field_unordered(key); +} +simdjson_inline simdjson_result object::find_field(const std::string_view key) & noexcept { + bool has_value; + SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) ); + if (!has_value) { + logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); + return NO_SUCH_FIELD; + } + return value(iter.child()); +} +simdjson_inline simdjson_result object::find_field(const std::string_view key) && noexcept { + bool has_value; + SIMDJSON_TRY( iter.find_field_raw(key).get(has_value) ); + if (!has_value) { + logger::log_line(iter.json_iter(), "ERROR: ", "Cannot find key %.*s", "", -1, 0, logger::log_level::error, static_cast(key.size()), key.data()); + return NO_SUCH_FIELD; + } + return value(iter.child()); } -simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { - size_t pos{0}; - // if the content has no escape character, just scan through it quickly! - for(;target[pos] && target[pos] != '\\';pos++) {} - // slow path may begin. - bool escaping{false}; - for(;target[pos];pos++) { - if((target[pos] == '"') && !escaping) { - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; - } +simdjson_inline simdjson_result object::start(value_iterator &iter) noexcept { + SIMDJSON_TRY( iter.start_object().error() ); + return object(iter); +} +simdjson_inline simdjson_result object::start_root(value_iterator &iter) noexcept { + SIMDJSON_TRY( iter.start_root_object().error() ); + return object(iter); +} +simdjson_inline error_code object::consume() noexcept { + if(iter.is_at_key()) { + /** + * whenever you are pointing at a key, calling skip_child() is + * unsafe because you will hit a string and you will assume that + * it is string value, and this mistake will lead you to make bad + * depth computation. + */ + /** + * We want to 'consume' the key. We could really + * just do _json_iter->return_current_and_advance(); at this + * point, but, for clarity, we will use the high-level API to + * eat the key. We assume that the compiler optimizes away + * most of the work. + */ + simdjson_unused raw_json_string actual_key; + auto error = iter.field_key().get(actual_key); + if (error) { iter.abandon(); return error; }; + // Let us move to the value while we are at it. + if ((error = iter.field_value())) { iter.abandon(); return error; } } - return true; + auto error_skip = iter.json_iter().skip_child(iter.depth()-1); + if(error_skip) { iter.abandon(); } + return error_skip; } +simdjson_inline simdjson_result object::raw_json() noexcept { + const uint8_t * starting_point{iter.peek_start()}; + auto error = consume(); + if(error) { return error; } + const uint8_t * final_point{iter._json_iter->peek()}; + return std::string_view(reinterpret_cast(starting_point), size_t(final_point - starting_point)); +} -simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept { - // If we are going to call memcmp, then we must know something about the length of the raw_json_string. - return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); +simdjson_inline simdjson_result object::started(value_iterator &iter) noexcept { + SIMDJSON_TRY( iter.started_object().error() ); + return object(iter); } -simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and - // the raw content is quote terminated within a valid JSON string. - if(target.size() <= SIMDJSON_PADDING) { - return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); - } - const char * r{raw()}; - size_t pos{0}; - for(;pos < target.size();pos++) { - if(r[pos] != target[pos]) { return false; } - } - if(r[pos] != '"') { return false; } - return true; +simdjson_inline object object::resume(const value_iterator &iter) noexcept { + return iter; } -simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept { - const char * r{raw()}; - size_t pos{0}; - bool escaping{false}; - for(;pos < target.size();pos++) { - if(r[pos] != target[pos]) { return false; } - // if target is a compile-time constant and it is free from - // quotes, then the next part could get optimized away through - // inlining. - if((target[pos] == '"') && !escaping) { - // We have reached the end of the raw_json_string but - // the target is not done. - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; - } - } - if(r[pos] != '"') { return false; } - return true; +simdjson_inline object::object(const value_iterator &_iter) noexcept + : iter{_iter} +{ } +simdjson_inline simdjson_result object::begin() noexcept { +#if SIMDJSON_DEVELOPMENT_CHECKS + if (!iter.is_at_iterator_start()) { return OUT_OF_ORDER_ITERATION; } +#endif + return object_iterator(iter); +} +simdjson_inline simdjson_result object::end() noexcept { + return object_iterator(iter); +} -simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept { - // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and - // the raw content is quote terminated within a valid JSON string. - const char * r{raw()}; - size_t pos{0}; - for(;target[pos];pos++) { - if(r[pos] != target[pos]) { return false; } +inline simdjson_result object::at_pointer(std::string_view json_pointer) noexcept { + if (json_pointer[0] != '/') { return INVALID_JSON_POINTER; } + json_pointer = json_pointer.substr(1); + size_t slash = json_pointer.find('/'); + std::string_view key = json_pointer.substr(0, slash); + // Grab the child with the given key + simdjson_result child; + + // If there is an escape character in the key, unescape it and then get the child. + size_t escape = key.find('~'); + if (escape != std::string_view::npos) { + // Unescape the key + std::string unescaped(key); + do { + switch (unescaped[escape+1]) { + case '0': + unescaped.replace(escape, 2, "~"); + break; + case '1': + unescaped.replace(escape, 2, "/"); + break; + default: + return INVALID_JSON_POINTER; // "Unexpected ~ escape character in JSON pointer"); + } + escape = unescaped.find('~', escape+1); + } while (escape != std::string::npos); + child = find_field(unescaped); // Take note find_field does not unescape keys when matching + } else { + child = find_field(key); + } + if(child.error()) { + return child; // we do not continue if there was an error } - if(r[pos] != '"') { return false; } - return true; + // If there is a /, we have to recurse and look up more of the path + if (slash != std::string_view::npos) { + child = child.at_pointer(json_pointer.substr(slash)); + } + return child; } -simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept { - // Assumptions: does not contain unescaped quote characters, and - // the raw content is quote terminated within a valid JSON string. - const char * r{raw()}; - size_t pos{0}; - bool escaping{false}; - for(;target[pos];pos++) { - if(r[pos] != target[pos]) { return false; } - // if target is a compile-time constant and it is free from - // quotes, then the next part could get optimized away through - // inlining. - if((target[pos] == '"') && !escaping) { - // We have reached the end of the raw_json_string but - // the target is not done. - return false; - } else if(target[pos] == '\\') { - escaping = !escaping; - } else { - escaping = false; - } +inline simdjson_result object::at_path(std::string_view json_path) noexcept { + auto json_pointer = json_path_to_pointer_conversion(json_path); + if (json_pointer == "-1") { + return INVALID_JSON_POINTER; } - if(r[pos] != '"') { return false; } - return true; + return at_pointer(json_pointer); } -simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept { - return a.unsafe_is_equal(c); +simdjson_inline simdjson_result object::count_fields() & noexcept { + size_t count{0}; + // Important: we do not consume any of the values. + for(simdjson_unused auto v : *this) { count++; } + // The above loop will always succeed, but we want to report errors. + if(iter.error()) { return iter.error(); } + // We need to move back at the start because we expect users to iterate through + // the object after counting the number of elements. + iter.reset_object(); + return count; } -simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept { - return a == c; +simdjson_inline simdjson_result object::is_empty() & noexcept { + bool is_not_empty; + auto error = iter.reset_object().get(is_not_empty); + if(error) { return error; } + return !is_not_empty; } -simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept { - return !(a == c); +simdjson_inline simdjson_result object::reset() & noexcept { + return iter.reset_object(); } -simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept { - return !(a == c); -} +} // namespace ondemand +} // namespace lasx +} // namespace simdjson +namespace simdjson { -simdjson_inline simdjson_warn_unused simdjson_result raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept { - return iter.unescape(*this, allow_replacement); +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::object &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} + +simdjson_inline simdjson_result simdjson_result::begin() noexcept { + if (error()) { return error(); } + return first.begin(); +} +simdjson_inline simdjson_result simdjson_result::end() noexcept { + if (error()) { return error(); } + return first.end(); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) && noexcept { + if (error()) { return error(); } + return std::forward(first).find_field_unordered(key); +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) & noexcept { + if (error()) { return error(); } + return first[key]; +} +simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) && noexcept { + if (error()) { return error(); } + return std::forward(first)[key]; +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) & noexcept { + if (error()) { return error(); } + return first.find_field(key); +} +simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) && noexcept { + if (error()) { return error(); } + return std::forward(first).find_field(key); } -simdjson_inline simdjson_warn_unused simdjson_result raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept { - return iter.unescape_wobbly(*this); +simdjson_inline simdjson_result simdjson_result::at_pointer(std::string_view json_pointer) noexcept { + if (error()) { return error(); } + return first.at_pointer(json_pointer); } -simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept { - bool in_escape = false; - const char *s = str.raw(); - while (true) { - switch (*s) { - case '\\': in_escape = !in_escape; break; - case '"': if (in_escape) { in_escape = false; } else { return out; } break; - default: if (in_escape) { in_escape = false; } - } - out << *s; - s++; +simdjson_inline simdjson_result simdjson_result::at_path( + std::string_view json_path) noexcept { + if (error()) { + return error(); } + return first.at_path(json_path); } -} // namespace ondemand -} // namespace lasx -} // namespace simdjson - -namespace simdjson { - -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::raw_json_string &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} +inline simdjson_result simdjson_result::reset() noexcept { + if (error()) { return error(); } + return first.reset(); +} -simdjson_inline simdjson_result simdjson_result::raw() const noexcept { +inline simdjson_result simdjson_result::is_empty() noexcept { if (error()) { return error(); } - return first.raw(); + return first.is_empty(); } -simdjson_inline simdjson_warn_unused simdjson_result simdjson_result::unescape(lasx::ondemand::json_iterator &iter, bool allow_replacement) const noexcept { + +simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { if (error()) { return error(); } - return first.unescape(iter, allow_replacement); + return first.count_fields(); } -simdjson_inline simdjson_warn_unused simdjson_result simdjson_result::unescape_wobbly(lasx::ondemand::json_iterator &iter) const noexcept { + +simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { if (error()) { return error(); } - return first.unescape_wobbly(iter); + return first.raw_json(); } } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H -/* end file simdjson/generic/ondemand/raw_json_string-inl.h for lasx */ -/* including simdjson/generic/ondemand/serialization-inl.h for lasx: #include "simdjson/generic/ondemand/serialization-inl.h" */ -/* begin file simdjson/generic/ondemand/serialization-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_INL_H +/* end file simdjson/generic/ondemand/object-inl.h for lasx */ +/* including simdjson/generic/ondemand/object_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/object_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/object_iterator-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/field-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { +namespace lasx { +namespace ondemand { -inline std::string_view trim(const std::string_view str) noexcept { - // We can almost surely do better by rolling our own find_first_not_of function. - size_t first = str.find_first_not_of(" \t\n\r"); - // If we have the empty string (just white space), then no trimming is possible, and - // we return the empty string_view. - if (std::string_view::npos == first) { return std::string_view(); } - size_t last = str.find_last_not_of(" \t\n\r"); - return str.substr(first, (last - first + 1)); -} - - -inline simdjson_result to_json_string(lasx::ondemand::document& x) noexcept { - std::string_view v; - auto error = x.raw_json().get(v); - if(error) {return error; } - return trim(v); -} +// +// object_iterator +// -inline simdjson_result to_json_string(lasx::ondemand::document_reference& x) noexcept { - std::string_view v; - auto error = x.raw_json().get(v); - if(error) {return error; } - return trim(v); -} +simdjson_inline object_iterator::object_iterator(const value_iterator &_iter) noexcept + : iter{_iter} +{} -inline simdjson_result to_json_string(lasx::ondemand::value& x) noexcept { - /** - * If we somehow receive a value that has already been consumed, - * then the following code could be in trouble. E.g., we create - * an array as needed, but if an array was already created, then - * it could be bad. - */ - using namespace lasx::ondemand; - lasx::ondemand::json_type t; - auto error = x.type().get(t); - if(error != SUCCESS) { return error; } - switch (t) - { - case json_type::array: - { - lasx::ondemand::array array; - error = x.get_array().get(array); - if(error) { return error; } - return to_json_string(array); - } - case json_type::object: - { - lasx::ondemand::object object; - error = x.get_object().get(object); - if(error) { return error; } - return to_json_string(object); - } - default: - return trim(x.raw_json_token()); - } +simdjson_inline simdjson_result object_iterator::operator*() noexcept { + error_code error = iter.error(); + if (error) { iter.abandon(); return error; } + auto result = field::start(iter); + // TODO this is a safety rail ... users should exit loops as soon as they receive an error. + // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free. + if (result.error()) { iter.abandon(); } + return result; } - -inline simdjson_result to_json_string(lasx::ondemand::object& x) noexcept { - std::string_view v; - auto error = x.raw_json().get(v); - if(error) {return error; } - return trim(v); +simdjson_inline bool object_iterator::operator==(const object_iterator &other) const noexcept { + return !(*this != other); } - -inline simdjson_result to_json_string(lasx::ondemand::array& x) noexcept { - std::string_view v; - auto error = x.raw_json().get(v); - if(error) {return error; } - return trim(v); +simdjson_inline bool object_iterator::operator!=(const object_iterator &) const noexcept { + return iter.is_open(); } -inline simdjson_result to_json_string(simdjson_result x) { - if (x.error()) { return x.error(); } - return to_json_string(x.value_unsafe()); -} +SIMDJSON_PUSH_DISABLE_WARNINGS +SIMDJSON_DISABLE_STRICT_OVERFLOW_WARNING +simdjson_inline object_iterator &object_iterator::operator++() noexcept { + // TODO this is a safety rail ... users should exit loops as soon as they receive an error. + // Nonetheless, let's see if performance is OK with this if statement--the compiler may give it to us for free. + if (!iter.is_open()) { return *this; } // Iterator will be released if there is an error -inline simdjson_result to_json_string(simdjson_result x) { - if (x.error()) { return x.error(); } - return to_json_string(x.value_unsafe()); -} + simdjson_unused error_code error; + if ((error = iter.skip_child() )) { return *this; } -inline simdjson_result to_json_string(simdjson_result x) { - if (x.error()) { return x.error(); } - return to_json_string(x.value_unsafe()); + simdjson_unused bool has_value; + if ((error = iter.has_next_field().get(has_value) )) { return *this; }; + return *this; } +SIMDJSON_POP_DISABLE_WARNINGS -inline simdjson_result to_json_string(simdjson_result x) { - if (x.error()) { return x.error(); } - return to_json_string(x.value_unsafe()); -} +// +// ### Live States +// +// While iterating or looking up values, depth >= iter.depth. at_start may vary. Error is +// always SUCCESS: +// +// - Start: This is the state when the object is first found and the iterator is just past the {. +// In this state, at_start == true. +// - Next: After we hand a scalar value to the user, or an array/object which they then fully +// iterate over, the iterator is at the , or } before the next value. In this state, +// depth == iter.depth, at_start == false, and error == SUCCESS. +// - Unfinished Business: When we hand an array/object to the user which they do not fully +// iterate over, we need to finish that iteration by skipping child values until we reach the +// Next state. In this state, depth > iter.depth, at_start == false, and error == SUCCESS. +// +// ## Error States +// +// In error states, we will yield exactly one more value before stopping. iter.depth == depth +// and at_start is always false. We decrement after yielding the error, moving to the Finished +// state. +// +// - Chained Error: When the object iterator is part of an error chain--for example, in +// `for (auto tweet : doc["tweets"])`, where the tweet field may be missing or not be an +// object--we yield that error in the loop, exactly once. In this state, error != SUCCESS and +// iter.depth == depth, and at_start == false. We decrement depth when we yield the error. +// - Missing Comma Error: When the iterator ++ method discovers there is no comma between fields, +// we flag that as an error and treat it exactly the same as a Chained Error. In this state, +// error == TAPE_ERROR, iter.depth == depth, and at_start == false. +// +// Errors that occur while reading a field to give to the user (such as when the key is not a +// string or the field is missing a colon) are yielded immediately. Depth is then decremented, +// moving to the Finished state without transitioning through an Error state at all. +// +// ## Terminal State +// +// The terminal state has iter.depth < depth. at_start is always false. +// +// - Finished: When we have reached a }, we are finished. We signal this by decrementing depth. +// In this state, iter.depth < depth, at_start == false, and error == SUCCESS. +// -inline simdjson_result to_json_string(simdjson_result x) { - if (x.error()) { return x.error(); } - return to_json_string(x.value_unsafe()); -} +} // namespace ondemand +} // namespace lasx } // namespace simdjson -namespace simdjson { namespace lasx { namespace ondemand { +namespace simdjson { -#if SIMDJSON_EXCEPTIONS -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::value x) { - std::string_view v; - auto error = simdjson::to_json_string(x).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - throw simdjson::simdjson_error(error); - } -} -inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { - if (x.error()) { throw simdjson::simdjson_error(x.error()); } - return (out << x.value()); +simdjson_inline simdjson_result::simdjson_result( + lasx::ondemand::object_iterator &&value +) noexcept + : implementation_simdjson_result_base(std::forward(value)) +{ + first.iter.assert_is_valid(); } -#else -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::value x) { - std::string_view v; - auto error = simdjson::to_json_string(x).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - return (out << error); - } +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base({}, error) +{ } -#endif -#if SIMDJSON_EXCEPTIONS -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::array value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - throw simdjson::simdjson_error(error); - } +simdjson_inline simdjson_result simdjson_result::operator*() noexcept { + if (error()) { return error(); } + return *first; } -inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { - if (x.error()) { throw simdjson::simdjson_error(x.error()); } - return (out << x.value()); +// If we're iterating and there is an error, return the error once. +simdjson_inline bool simdjson_result::operator==(const simdjson_result &other) const noexcept { + if (!first.iter.is_valid()) { return !error(); } + return first == other.first; } -#else -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::array value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - return (out << error); - } +// If we're iterating and there is an error, return the error once. +simdjson_inline bool simdjson_result::operator!=(const simdjson_result &other) const noexcept { + if (!first.iter.is_valid()) { return error(); } + return first != other.first; +} +// Checks for ']' and ',' +simdjson_inline simdjson_result &simdjson_result::operator++() noexcept { + // Clear the error if there is one, so we don't yield it twice + if (error()) { second = SUCCESS; return *this; } + ++first; + return *this; } -#endif -#if SIMDJSON_EXCEPTIONS -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document& value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - throw simdjson::simdjson_error(error); - } +} // namespace simdjson + +#endif // SIMDJSON_GENERIC_ONDEMAND_OBJECT_ITERATOR_INL_H +/* end file simdjson/generic/ondemand/object_iterator-inl.h for lasx */ +/* including simdjson/generic/ondemand/parser-inl.h for lasx: #include "simdjson/generic/ondemand/parser-inl.h" */ +/* begin file simdjson/generic/ondemand/parser-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/padded_string.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/padded_string_view.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/implementation.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/internal/dom_parser_implementation.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/dom/base.h" // for MINIMAL_DOCUMENT_CAPACITY */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document_stream.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/parser.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +namespace simdjson { +namespace lasx { +namespace ondemand { + +simdjson_inline parser::parser(size_t max_capacity) noexcept + : _max_capacity{max_capacity} { } -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document_reference& value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); + +simdjson_warn_unused simdjson_inline error_code parser::allocate(size_t new_capacity, size_t new_max_depth) noexcept { + if (new_capacity > max_capacity()) { return CAPACITY; } + if (string_buf && new_capacity == capacity() && new_max_depth == max_depth()) { return SUCCESS; } + + // string_capacity copied from document::allocate + _capacity = 0; + size_t string_capacity = SIMDJSON_ROUNDUP_N(5 * new_capacity / 3 + SIMDJSON_PADDING, 64); + string_buf.reset(new (std::nothrow) uint8_t[string_capacity]); +#if SIMDJSON_DEVELOPMENT_CHECKS + start_positions.reset(new (std::nothrow) token_position[new_max_depth]); +#endif + if (implementation) { + SIMDJSON_TRY( implementation->set_capacity(new_capacity) ); + SIMDJSON_TRY( implementation->set_max_depth(new_max_depth) ); } else { - throw simdjson::simdjson_error(error); + SIMDJSON_TRY( simdjson::get_active_implementation()->create_dom_parser_implementation(new_capacity, new_max_depth, implementation) ); } + _capacity = new_capacity; + _max_depth = new_max_depth; + return SUCCESS; } -inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result&& x) { - if (x.error()) { throw simdjson::simdjson_error(x.error()); } - return (out << x.value()); -} -inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result&& x) { - if (x.error()) { throw simdjson::simdjson_error(x.error()); } - return (out << x.value()); -} -#else -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document& value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - return (out << error); - } +#if SIMDJSON_DEVELOPMENT_CHECKS +simdjson_inline simdjson_warn_unused bool parser::string_buffer_overflow(const uint8_t *string_buf_loc) const noexcept { + return (string_buf_loc < string_buf.get()) || (size_t(string_buf_loc - string_buf.get()) >= capacity()); } #endif -#if SIMDJSON_EXCEPTIONS -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::object value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - throw simdjson::simdjson_error(error); - } -} -inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { - if (x.error()) { throw simdjson::simdjson_error(x.error()); } - return (out << x.value()); -} -#else -inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::object value) { - std::string_view v; - auto error = simdjson::to_json_string(value).get(v); - if(error == simdjson::SUCCESS) { - return (out << v); - } else { - return (out << error); +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(padded_string_view json) & noexcept { + if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } + + json.remove_utf8_bom(); + + // Allocate if needed + if (capacity() < json.length() || !string_buf) { + SIMDJSON_TRY( allocate(json.length(), max_depth()) ); } + + // Run stage 1. + SIMDJSON_TRY( implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular) ); + return document::start({ reinterpret_cast(json.data()), this }); } -#endif -}}} // namespace simdjson::lasx::ondemand -#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H -/* end file simdjson/generic/ondemand/serialization-inl.h for lasx */ -/* including simdjson/generic/ondemand/token_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/token_iterator-inl.h" */ -/* begin file simdjson/generic/ondemand/token_iterator-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H +#ifdef SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate_allow_incomplete_json(padded_string_view json) & noexcept { + if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } -/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ -/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + json.remove_utf8_bom(); -namespace simdjson { -namespace lasx { -namespace ondemand { + // Allocate if needed + if (capacity() < json.length() || !string_buf) { + SIMDJSON_TRY( allocate(json.length(), max_depth()) ); + } -simdjson_inline token_iterator::token_iterator( - const uint8_t *_buf, - token_position position -) noexcept : buf{_buf}, _position{position} -{ + // Run stage 1. + const simdjson::error_code err = implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular); + if (err) { + if (err != UNCLOSED_STRING) + return err; + } + return document::start({ reinterpret_cast(json.data()), this, true }); } +#endif // SIMDJSON_EXPERIMENTAL_ALLOW_INCOMPLETE_JSON -simdjson_inline uint32_t token_iterator::current_offset() const noexcept { - return *(_position); +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const char *json, size_t len, size_t allocated) & noexcept { + return iterate(padded_string_view(json, len, allocated)); } +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const uint8_t *json, size_t len, size_t allocated) & noexcept { + return iterate(padded_string_view(json, len, allocated)); +} -simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept { - return &buf[*(_position++)]; +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(std::string_view json, size_t allocated) & noexcept { + return iterate(padded_string_view(json, allocated)); } -simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept { - return &buf[*position]; +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(std::string &json) & noexcept { + if(json.capacity() - json.size() < SIMDJSON_PADDING) { + json.reserve(json.size() + SIMDJSON_PADDING); + } + return iterate(padded_string_view(json)); } -simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept { - return *position; + +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const std::string &json) & noexcept { + return iterate(padded_string_view(json)); } -simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept { - return *(position+1) - *position; + +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const simdjson_result &result) & noexcept { + // We don't presently have a way to temporarily get a const T& from a simdjson_result without throwing an exception + SIMDJSON_TRY( result.error() ); + padded_string_view json = result.value_unsafe(); + return iterate(json); } -simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept { - return *(position+2) - *(position) > *(position+1) - *(position) ? - *(position+1) - *(position) - : *(position+2) - *(position); +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate(const simdjson_result &result) & noexcept { + // We don't presently have a way to temporarily get a const T& from a simdjson_result without throwing an exception + SIMDJSON_TRY( result.error() ); + const padded_string &json = result.value_unsafe(); + return iterate(json); } -simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept { - return &buf[*(_position+delta)]; + +simdjson_warn_unused simdjson_inline simdjson_result parser::iterate_raw(padded_string_view json) & noexcept { + if (json.padding() < SIMDJSON_PADDING) { return INSUFFICIENT_PADDING; } + + json.remove_utf8_bom(); + + // Allocate if needed + if (capacity() < json.length()) { + SIMDJSON_TRY( allocate(json.length(), max_depth()) ); + } + + // Run stage 1. + SIMDJSON_TRY( implementation->stage1(reinterpret_cast(json.data()), json.length(), stage1_mode::regular) ); + return json_iterator(reinterpret_cast(json.data()), this); } -simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept { - return *(_position+delta); + +inline simdjson_result parser::iterate_many(const uint8_t *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept { + if(batch_size < MINIMAL_BATCH_SIZE) { batch_size = MINIMAL_BATCH_SIZE; } + if((len >= 3) && (std::memcmp(buf, "\xEF\xBB\xBF", 3) == 0)) { + buf += 3; + len -= 3; + } + if(allow_comma_separated && batch_size < len) { batch_size = len; } + return document_stream(*this, buf, len, batch_size, allow_comma_separated); } -simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept { - return *(_position+delta+1) - *(_position+delta); +inline simdjson_result parser::iterate_many(const char *buf, size_t len, size_t batch_size, bool allow_comma_separated) noexcept { + return iterate_many(reinterpret_cast(buf), len, batch_size, allow_comma_separated); } - -simdjson_inline token_position token_iterator::position() const noexcept { - return _position; +inline simdjson_result parser::iterate_many(const std::string &s, size_t batch_size, bool allow_comma_separated) noexcept { + return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated); } -simdjson_inline void token_iterator::set_position(token_position target_position) noexcept { - _position = target_position; +inline simdjson_result parser::iterate_many(const padded_string &s, size_t batch_size, bool allow_comma_separated) noexcept { + return iterate_many(s.data(), s.length(), batch_size, allow_comma_separated); } -simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept { - return _position == other._position; +simdjson_pure simdjson_inline size_t parser::capacity() const noexcept { + return _capacity; } -simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept { - return _position != other._position; +simdjson_pure simdjson_inline size_t parser::max_capacity() const noexcept { + return _max_capacity; } -simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept { - return _position > other._position; +simdjson_pure simdjson_inline size_t parser::max_depth() const noexcept { + return _max_depth; } -simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept { - return _position >= other._position; + +simdjson_inline void parser::set_max_capacity(size_t max_capacity) noexcept { + if(max_capacity < dom::MINIMAL_DOCUMENT_CAPACITY) { + _max_capacity = max_capacity; + } else { + _max_capacity = dom::MINIMAL_DOCUMENT_CAPACITY; + } } -simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept { - return _position < other._position; + +simdjson_inline simdjson_warn_unused simdjson_result parser::unescape(raw_json_string in, uint8_t *&dst, bool allow_replacement) const noexcept { + uint8_t *end = implementation->parse_string(in.buf, dst, allow_replacement); + if (!end) { return STRING_ERROR; } + std::string_view result(reinterpret_cast(dst), end-dst); + dst = end; + return result; } -simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept { - return _position <= other._position; + +simdjson_inline simdjson_warn_unused simdjson_result parser::unescape_wobbly(raw_json_string in, uint8_t *&dst) const noexcept { + uint8_t *end = implementation->parse_wobbly_string(in.buf, dst); + if (!end) { return STRING_ERROR; } + std::string_view result(reinterpret_cast(dst), end-dst); + dst = end; + return result; } } // namespace ondemand @@ -116602,304 +121837,194 @@ simdjson_inline bool token_iterator::operator<=(const token_iterator &other) con namespace simdjson { -simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::token_iterator &&value) noexcept - : implementation_simdjson_result_base(std::forward(value)) {} -simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept - : implementation_simdjson_result_base(error) {} +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::parser &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H -/* end file simdjson/generic/ondemand/token_iterator-inl.h for lasx */ -/* including simdjson/generic/ondemand/value-inl.h for lasx: #include "simdjson/generic/ondemand/value-inl.h" */ -/* begin file simdjson/generic/ondemand/value-inl.h for lasx */ -#ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H +#endif // SIMDJSON_GENERIC_ONDEMAND_PARSER_INL_H +/* end file simdjson/generic/ondemand/parser-inl.h for lasx */ +/* including simdjson/generic/ondemand/raw_json_string-inl.h for lasx: #include "simdjson/generic/ondemand/raw_json_string-inl.h" */ +/* begin file simdjson/generic/ondemand/raw_json_string-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H /* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ -/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ /* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/raw_json_string.h" */ -/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_iterator-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ /* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ namespace simdjson { + namespace lasx { namespace ondemand { -simdjson_inline value::value(const value_iterator &_iter) noexcept - : iter{_iter} -{ -} -simdjson_inline value value::start(const value_iterator &iter) noexcept { - return iter; -} -simdjson_inline value value::resume(const value_iterator &iter) noexcept { - return iter; -} - -simdjson_inline simdjson_result value::get_array() noexcept { - return array::start(iter); -} -simdjson_inline simdjson_result value::get_object() noexcept { - return object::start(iter); -} -simdjson_inline simdjson_result value::start_or_resume_object() noexcept { - if (iter.at_start()) { - return get_object(); - } else { - return object::resume(iter); - } -} +simdjson_inline raw_json_string::raw_json_string(const uint8_t * _buf) noexcept : buf{_buf} {} -simdjson_inline simdjson_result value::get_raw_json_string() noexcept { - return iter.get_raw_json_string(); -} -simdjson_inline simdjson_result value::get_string(bool allow_replacement) noexcept { - return iter.get_string(allow_replacement); -} -template -simdjson_inline error_code value::get_string(string_type& receiver, bool allow_replacement) noexcept { - return iter.get_string(receiver, allow_replacement); -} -simdjson_inline simdjson_result value::get_wobbly_string() noexcept { - return iter.get_wobbly_string(); -} -simdjson_inline simdjson_result value::get_double() noexcept { - return iter.get_double(); -} -simdjson_inline simdjson_result value::get_double_in_string() noexcept { - return iter.get_double_in_string(); -} -simdjson_inline simdjson_result value::get_uint64() noexcept { - return iter.get_uint64(); -} -simdjson_inline simdjson_result value::get_uint64_in_string() noexcept { - return iter.get_uint64_in_string(); -} -simdjson_inline simdjson_result value::get_int64() noexcept { - return iter.get_int64(); -} -simdjson_inline simdjson_result value::get_int64_in_string() noexcept { - return iter.get_int64_in_string(); -} -simdjson_inline simdjson_result value::get_bool() noexcept { - return iter.get_bool(); -} -simdjson_inline simdjson_result value::is_null() noexcept { - return iter.is_null(); -} -template<> simdjson_inline simdjson_result value::get() noexcept { return get_array(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_object(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_raw_json_string(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_string(false); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_number(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_double(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_uint64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_int64(); } -template<> simdjson_inline simdjson_result value::get() noexcept { return get_bool(); } +simdjson_inline const char * raw_json_string::raw() const noexcept { return reinterpret_cast(buf); } -template simdjson_inline error_code value::get(T &out) noexcept { - return get().get(out); -} -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline value::operator T() noexcept(false) { - return get(); -} -simdjson_inline value::operator array() noexcept(false) { - return get_array(); -} -simdjson_inline value::operator object() noexcept(false) { - return get_object(); -} -simdjson_inline value::operator uint64_t() noexcept(false) { - return get_uint64(); -} -simdjson_inline value::operator int64_t() noexcept(false) { - return get_int64(); -} -simdjson_inline value::operator double() noexcept(false) { - return get_double(); -} -simdjson_inline value::operator std::string_view() noexcept(false) { - return get_string(false); -} -simdjson_inline value::operator raw_json_string() noexcept(false) { - return get_raw_json_string(); -} -simdjson_inline value::operator bool() noexcept(false) { - return get_bool(); +simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(std::string_view target) noexcept { + size_t pos{0}; + while(pos < target.size()) { + pos = target.find('"', pos); + if(pos == std::string_view::npos) { return true; } + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } + } + pos++; + } + return true; } -#endif -simdjson_inline simdjson_result value::begin() & noexcept { - return get_array().begin(); -} -simdjson_inline simdjson_result value::end() & noexcept { - return {}; -} -simdjson_inline simdjson_result value::count_elements() & noexcept { - simdjson_result answer; - auto a = get_array(); - answer = a.count_elements(); - // count_elements leaves you pointing inside the array, at the first element. - // We need to move back so that the user can create a new array (which requires that - // we point at '['). - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::count_fields() & noexcept { - simdjson_result answer; - auto a = get_object(); - answer = a.count_fields(); - iter.move_at_start(); - return answer; -} -simdjson_inline simdjson_result value::at(size_t index) noexcept { - auto a = get_array(); - return a.at(index); +simdjson_inline bool raw_json_string::is_free_from_unescaped_quote(const char* target) noexcept { + size_t pos{0}; + while(target[pos]) { + const char * result = strchr(target+pos, '"'); + if(result == nullptr) { return true; } + pos = result - target; + if(pos != 0 && target[pos-1] != '\\') { return false; } + if(pos > 1 && target[pos-2] == '\\') { + size_t backslash_count{2}; + for(size_t i = 3; i <= pos; i++) { + if(target[pos-i] == '\\') { backslash_count++; } + else { break; } + } + if(backslash_count % 2 == 0) { return false; } + } + pos++; + } + return true; } -simdjson_inline simdjson_result value::find_field(std::string_view key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field(const char *key) noexcept { - return start_or_resume_object().find_field(key); -} -simdjson_inline simdjson_result value::find_field_unordered(std::string_view key) noexcept { - return start_or_resume_object().find_field_unordered(key); -} -simdjson_inline simdjson_result value::find_field_unordered(const char *key) noexcept { - return start_or_resume_object().find_field_unordered(key); +simdjson_inline bool raw_json_string::unsafe_is_equal(size_t length, std::string_view target) const noexcept { + // If we are going to call memcmp, then we must know something about the length of the raw_json_string. + return (length >= target.size()) && (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); } -simdjson_inline simdjson_result value::operator[](std::string_view key) noexcept { - return start_or_resume_object()[key]; -} -simdjson_inline simdjson_result value::operator[](const char *key) noexcept { - return start_or_resume_object()[key]; +simdjson_inline bool raw_json_string::unsafe_is_equal(std::string_view target) const noexcept { + // Assumptions: does not contain unescaped quote characters("), and + // the raw content is quote terminated within a valid JSON string. + if(target.size() <= SIMDJSON_PADDING) { + return (raw()[target.size()] == '"') && !memcmp(raw(), target.data(), target.size()); + } + const char * r{raw()}; + size_t pos{0}; + for(;pos < target.size();pos++) { + if(r[pos] != target[pos]) { return false; } + } + if(r[pos] != '"') { return false; } + return true; } -simdjson_inline simdjson_result value::type() noexcept { - return iter.type(); +simdjson_inline bool raw_json_string::is_equal(std::string_view target) const noexcept { + const char * r{raw()}; + size_t pos{0}; + bool escaping{false}; + for(;pos < target.size();pos++) { + if(r[pos] != target[pos]) { return false; } + // if target is a compile-time constant and it is free from + // quotes, then the next part could get optimized away through + // inlining. + if((target[pos] == '"') && !escaping) { + // We have reached the end of the raw_json_string but + // the target is not done. + return false; + } else if(target[pos] == '\\') { + escaping = !escaping; + } else { + escaping = false; + } + } + if(r[pos] != '"') { return false; } + return true; } -simdjson_inline simdjson_result value::is_scalar() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return ! ((this_type == json_type::array) || (this_type == json_type::object)); -} -simdjson_inline simdjson_result value::is_string() noexcept { - json_type this_type; - auto error = type().get(this_type); - if(error) { return error; } - return (this_type == json_type::string); +simdjson_inline bool raw_json_string::unsafe_is_equal(const char * target) const noexcept { + // Assumptions: 'target' does not contain unescaped quote characters, is null terminated and + // the raw content is quote terminated within a valid JSON string. + const char * r{raw()}; + size_t pos{0}; + for(;target[pos];pos++) { + if(r[pos] != target[pos]) { return false; } + } + if(r[pos] != '"') { return false; } + return true; } - -simdjson_inline bool value::is_negative() noexcept { - return iter.is_negative(); +simdjson_inline bool raw_json_string::is_equal(const char* target) const noexcept { + // Assumptions: does not contain unescaped quote characters, and + // the raw content is quote terminated within a valid JSON string. + const char * r{raw()}; + size_t pos{0}; + bool escaping{false}; + for(;target[pos];pos++) { + if(r[pos] != target[pos]) { return false; } + // if target is a compile-time constant and it is free from + // quotes, then the next part could get optimized away through + // inlining. + if((target[pos] == '"') && !escaping) { + // We have reached the end of the raw_json_string but + // the target is not done. + return false; + } else if(target[pos] == '\\') { + escaping = !escaping; + } else { + escaping = false; + } + } + if(r[pos] != '"') { return false; } + return true; } -simdjson_inline simdjson_result value::is_integer() noexcept { - return iter.is_integer(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number_type() noexcept { - return iter.get_number_type(); -} -simdjson_warn_unused simdjson_inline simdjson_result value::get_number() noexcept { - return iter.get_number(); +simdjson_unused simdjson_inline bool operator==(const raw_json_string &a, std::string_view c) noexcept { + return a.unsafe_is_equal(c); } -simdjson_inline std::string_view value::raw_json_token() noexcept { - return std::string_view(reinterpret_cast(iter.peek_start()), iter.peek_start_length()); +simdjson_unused simdjson_inline bool operator==(std::string_view c, const raw_json_string &a) noexcept { + return a == c; } -simdjson_inline simdjson_result value::raw_json() noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: { - ondemand::array array; - SIMDJSON_TRY(get_array().get(array)); - return array.raw_json(); - } - case json_type::object: { - ondemand::object object; - SIMDJSON_TRY(get_object().get(object)); - return object.raw_json(); - } - default: - return raw_json_token(); - } +simdjson_unused simdjson_inline bool operator!=(const raw_json_string &a, std::string_view c) noexcept { + return !(a == c); } -simdjson_inline simdjson_result value::current_location() noexcept { - return iter.json_iter().current_location(); +simdjson_unused simdjson_inline bool operator!=(std::string_view c, const raw_json_string &a) noexcept { + return !(a == c); } -simdjson_inline int32_t value::current_depth() const noexcept{ - return iter.json_iter().depth(); -} -inline bool is_pointer_well_formed(std::string_view json_pointer) noexcept { - if (simdjson_unlikely(json_pointer.empty())) { // can't be - return false; - } - if (simdjson_unlikely(json_pointer[0] != '/')) { - return false; - } - size_t escape = json_pointer.find('~'); - if (escape == std::string_view::npos) { - return true; - } - if (escape == json_pointer.size() - 1) { - return false; - } - if (json_pointer[escape + 1] != '0' && json_pointer[escape + 1] != '1') { - return false; - } - return true; +simdjson_inline simdjson_warn_unused simdjson_result raw_json_string::unescape(json_iterator &iter, bool allow_replacement) const noexcept { + return iter.unescape(*this, allow_replacement); } - -simdjson_inline simdjson_result value::at_pointer(std::string_view json_pointer) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) - { - case json_type::array: - return (*this).get_array().at_pointer(json_pointer); - case json_type::object: - return (*this).get_object().at_pointer(json_pointer); - default: - // a non-empty string can be invalid, or accessing a primitive (issue 2154) - if (is_pointer_well_formed(json_pointer)) { - return NO_SUCH_FIELD; - } - return INVALID_JSON_POINTER; - } + +simdjson_inline simdjson_warn_unused simdjson_result raw_json_string::unescape_wobbly(json_iterator &iter) const noexcept { + return iter.unescape_wobbly(*this); } -simdjson_inline simdjson_result value::at_path(std::string_view json_path) noexcept { - json_type t; - SIMDJSON_TRY(type().get(t)); - switch (t) { - case json_type::array: - return (*this).get_array().at_path(json_path); - case json_type::object: - return (*this).get_object().at_path(json_path); - default: - return INVALID_JSON_POINTER; +simdjson_unused simdjson_inline std::ostream &operator<<(std::ostream &out, const raw_json_string &str) noexcept { + bool in_escape = false; + const char *s = str.raw(); + while (true) { + switch (*s) { + case '\\': in_escape = !in_escape; break; + case '"': if (in_escape) { in_escape = false; } else { return out; } break; + default: if (in_escape) { in_escape = false; } + } + out << *s; + s++; } } @@ -116909,253 +122034,360 @@ simdjson_inline simdjson_result value::at_path(std::string_view json_path namespace simdjson { -simdjson_inline simdjson_result::simdjson_result( - lasx::ondemand::value &&value -) noexcept : - implementation_simdjson_result_base( - std::forward(value) - ) -{ -} -simdjson_inline simdjson_result::simdjson_result( - error_code error -) noexcept : - implementation_simdjson_result_base(error) -{ -} -simdjson_inline simdjson_result simdjson_result::count_elements() & noexcept { +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::raw_json_string &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} + +simdjson_inline simdjson_result simdjson_result::raw() const noexcept { if (error()) { return error(); } - return first.count_elements(); + return first.raw(); } -simdjson_inline simdjson_result simdjson_result::count_fields() & noexcept { +simdjson_inline simdjson_warn_unused simdjson_result simdjson_result::unescape(lasx::ondemand::json_iterator &iter, bool allow_replacement) const noexcept { if (error()) { return error(); } - return first.count_fields(); + return first.unescape(iter, allow_replacement); } -simdjson_inline simdjson_result simdjson_result::at(size_t index) noexcept { +simdjson_inline simdjson_warn_unused simdjson_result simdjson_result::unescape_wobbly(lasx::ondemand::json_iterator &iter) const noexcept { if (error()) { return error(); } - return first.at(index); + return first.unescape_wobbly(iter); } -simdjson_inline simdjson_result simdjson_result::begin() & noexcept { - if (error()) { return error(); } - return first.begin(); +} // namespace simdjson + +#endif // SIMDJSON_GENERIC_ONDEMAND_RAW_JSON_STRING_INL_H +/* end file simdjson/generic/ondemand/raw_json_string-inl.h for lasx */ +/* including simdjson/generic/ondemand/serialization-inl.h for lasx: #include "simdjson/generic/ondemand/serialization-inl.h" */ +/* begin file simdjson/generic/ondemand/serialization-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/array.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/document-inl.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/json_type.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/object.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/serialization.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/value.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +namespace simdjson { + +inline std::string_view trim(const std::string_view str) noexcept { + // We can almost surely do better by rolling our own find_first_not_of function. + size_t first = str.find_first_not_of(" \t\n\r"); + // If we have the empty string (just white space), then no trimming is possible, and + // we return the empty string_view. + if (std::string_view::npos == first) { return std::string_view(); } + size_t last = str.find_last_not_of(" \t\n\r"); + return str.substr(first, (last - first + 1)); } -simdjson_inline simdjson_result simdjson_result::end() & noexcept { - if (error()) { return error(); } - return {}; + + +inline simdjson_result to_json_string(lasx::ondemand::document& x) noexcept { + std::string_view v; + auto error = x.raw_json().get(v); + if(error) {return error; } + return trim(v); } -simdjson_inline simdjson_result simdjson_result::find_field(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field(key); +inline simdjson_result to_json_string(lasx::ondemand::document_reference& x) noexcept { + std::string_view v; + auto error = x.raw_json().get(v); + if(error) {return error; } + return trim(v); } -simdjson_inline simdjson_result simdjson_result::find_field(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field(key); + +inline simdjson_result to_json_string(lasx::ondemand::value& x) noexcept { + /** + * If we somehow receive a value that has already been consumed, + * then the following code could be in trouble. E.g., we create + * an array as needed, but if an array was already created, then + * it could be bad. + */ + using namespace lasx::ondemand; + lasx::ondemand::json_type t; + auto error = x.type().get(t); + if(error != SUCCESS) { return error; } + switch (t) + { + case json_type::array: + { + lasx::ondemand::array array; + error = x.get_array().get(array); + if(error) { return error; } + return to_json_string(array); + } + case json_type::object: + { + lasx::ondemand::object object; + error = x.get_object().get(object); + if(error) { return error; } + return to_json_string(object); + } + default: + return trim(x.raw_json_token()); + } } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(std::string_view key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); +inline simdjson_result to_json_string(lasx::ondemand::object& x) noexcept { + std::string_view v; + auto error = x.raw_json().get(v); + if(error) {return error; } + return trim(v); } -simdjson_inline simdjson_result simdjson_result::find_field_unordered(const char *key) noexcept { - if (error()) { return error(); } - return first.find_field_unordered(key); + +inline simdjson_result to_json_string(lasx::ondemand::array& x) noexcept { + std::string_view v; + auto error = x.raw_json().get(v); + if(error) {return error; } + return trim(v); } -simdjson_inline simdjson_result simdjson_result::operator[](std::string_view key) noexcept { - if (error()) { return error(); } - return first[key]; +inline simdjson_result to_json_string(simdjson_result x) { + if (x.error()) { return x.error(); } + return to_json_string(x.value_unsafe()); } -simdjson_inline simdjson_result simdjson_result::operator[](const char *key) noexcept { - if (error()) { return error(); } - return first[key]; + +inline simdjson_result to_json_string(simdjson_result x) { + if (x.error()) { return x.error(); } + return to_json_string(x.value_unsafe()); } -simdjson_inline simdjson_result simdjson_result::get_array() noexcept { - if (error()) { return error(); } - return first.get_array(); +inline simdjson_result to_json_string(simdjson_result x) { + if (x.error()) { return x.error(); } + return to_json_string(x.value_unsafe()); } -simdjson_inline simdjson_result simdjson_result::get_object() noexcept { - if (error()) { return error(); } - return first.get_object(); + +inline simdjson_result to_json_string(simdjson_result x) { + if (x.error()) { return x.error(); } + return to_json_string(x.value_unsafe()); } -simdjson_inline simdjson_result simdjson_result::get_uint64() noexcept { - if (error()) { return error(); } - return first.get_uint64(); + +inline simdjson_result to_json_string(simdjson_result x) { + if (x.error()) { return x.error(); } + return to_json_string(x.value_unsafe()); } -simdjson_inline simdjson_result simdjson_result::get_uint64_in_string() noexcept { - if (error()) { return error(); } - return first.get_uint64_in_string(); +} // namespace simdjson + +namespace simdjson { namespace lasx { namespace ondemand { + +#if SIMDJSON_EXCEPTIONS +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::value x) { + std::string_view v; + auto error = simdjson::to_json_string(x).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + throw simdjson::simdjson_error(error); + } } -simdjson_inline simdjson_result simdjson_result::get_int64() noexcept { - if (error()) { return error(); } - return first.get_int64(); +inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { + if (x.error()) { throw simdjson::simdjson_error(x.error()); } + return (out << x.value()); } -simdjson_inline simdjson_result simdjson_result::get_int64_in_string() noexcept { - if (error()) { return error(); } - return first.get_int64_in_string(); +#else +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::value x) { + std::string_view v; + auto error = simdjson::to_json_string(x).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + return (out << error); + } } -simdjson_inline simdjson_result simdjson_result::get_double() noexcept { - if (error()) { return error(); } - return first.get_double(); +#endif + +#if SIMDJSON_EXCEPTIONS +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::array value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + throw simdjson::simdjson_error(error); + } } -simdjson_inline simdjson_result simdjson_result::get_double_in_string() noexcept { - if (error()) { return error(); } - return first.get_double_in_string(); +inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { + if (x.error()) { throw simdjson::simdjson_error(x.error()); } + return (out << x.value()); } -simdjson_inline simdjson_result simdjson_result::get_string(bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(allow_replacement); +#else +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::array value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + return (out << error); + } } -template -simdjson_inline error_code simdjson_result::get_string(string_type& receiver, bool allow_replacement) noexcept { - if (error()) { return error(); } - return first.get_string(receiver, allow_replacement); +#endif + +#if SIMDJSON_EXCEPTIONS +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document& value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + throw simdjson::simdjson_error(error); + } } -simdjson_inline simdjson_result simdjson_result::get_wobbly_string() noexcept { - if (error()) { return error(); } - return first.get_wobbly_string(); +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document_reference& value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + throw simdjson::simdjson_error(error); + } } -simdjson_inline simdjson_result simdjson_result::get_raw_json_string() noexcept { - if (error()) { return error(); } - return first.get_raw_json_string(); +inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result&& x) { + if (x.error()) { throw simdjson::simdjson_error(x.error()); } + return (out << x.value()); } -simdjson_inline simdjson_result simdjson_result::get_bool() noexcept { - if (error()) { return error(); } - return first.get_bool(); +inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result&& x) { + if (x.error()) { throw simdjson::simdjson_error(x.error()); } + return (out << x.value()); } -simdjson_inline simdjson_result simdjson_result::is_null() noexcept { - if (error()) { return error(); } - return first.is_null(); +#else +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::document& value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + return (out << error); + } } +#endif -template simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return first.get(); -} -template simdjson_inline error_code simdjson_result::get(T &out) noexcept { - if (error()) { return error(); } - return first.get(out); +#if SIMDJSON_EXCEPTIONS +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::object value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + throw simdjson::simdjson_error(error); + } } - -template<> simdjson_inline simdjson_result simdjson_result::get() noexcept { - if (error()) { return error(); } - return std::move(first); +inline std::ostream& operator<<(std::ostream& out, simdjson::simdjson_result x) { + if (x.error()) { throw simdjson::simdjson_error(x.error()); } + return (out << x.value()); } -template<> simdjson_inline error_code simdjson_result::get(lasx::ondemand::value &out) noexcept { - if (error()) { return error(); } - out = first; - return SUCCESS; +#else +inline std::ostream& operator<<(std::ostream& out, simdjson::lasx::ondemand::object value) { + std::string_view v; + auto error = simdjson::to_json_string(value).get(v); + if(error == simdjson::SUCCESS) { + return (out << v); + } else { + return (out << error); + } } +#endif +}}} // namespace simdjson::lasx::ondemand -simdjson_inline simdjson_result simdjson_result::type() noexcept { - if (error()) { return error(); } - return first.type(); -} -simdjson_inline simdjson_result simdjson_result::is_scalar() noexcept { - if (error()) { return error(); } - return first.is_scalar(); +#endif // SIMDJSON_GENERIC_ONDEMAND_SERIALIZATION_INL_H +/* end file simdjson/generic/ondemand/serialization-inl.h for lasx */ +/* including simdjson/generic/ondemand/token_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/token_iterator-inl.h" */ +/* begin file simdjson/generic/ondemand/token_iterator-inl.h for lasx */ +#ifndef SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H + +/* amalgamation skipped (editor-only): #ifndef SIMDJSON_CONDITIONAL_INCLUDE */ +/* amalgamation skipped (editor-only): #define SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/base.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/ondemand/token_iterator.h" */ +/* amalgamation skipped (editor-only): #include "simdjson/generic/implementation_simdjson_result_base-inl.h" */ +/* amalgamation skipped (editor-only): #endif // SIMDJSON_CONDITIONAL_INCLUDE */ + +namespace simdjson { +namespace lasx { +namespace ondemand { + +simdjson_inline token_iterator::token_iterator( + const uint8_t *_buf, + token_position position +) noexcept : buf{_buf}, _position{position} +{ } -simdjson_inline simdjson_result simdjson_result::is_string() noexcept { - if (error()) { return error(); } - return first.is_string(); + +simdjson_inline uint32_t token_iterator::current_offset() const noexcept { + return *(_position); } -simdjson_inline simdjson_result simdjson_result::is_negative() noexcept { - if (error()) { return error(); } - return first.is_negative(); + + +simdjson_inline const uint8_t *token_iterator::return_current_and_advance() noexcept { + return &buf[*(_position++)]; } -simdjson_inline simdjson_result simdjson_result::is_integer() noexcept { - if (error()) { return error(); } - return first.is_integer(); + +simdjson_inline const uint8_t *token_iterator::peek(token_position position) const noexcept { + return &buf[*position]; } -simdjson_inline simdjson_result simdjson_result::get_number_type() noexcept { - if (error()) { return error(); } - return first.get_number_type(); +simdjson_inline uint32_t token_iterator::peek_index(token_position position) const noexcept { + return *position; } -simdjson_inline simdjson_result simdjson_result::get_number() noexcept { - if (error()) { return error(); } - return first.get_number(); +simdjson_inline uint32_t token_iterator::peek_length(token_position position) const noexcept { + return *(position+1) - *position; } -#if SIMDJSON_EXCEPTIONS -template -simdjson_inline simdjson_result::operator T() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return static_cast(first); + +simdjson_inline uint32_t token_iterator::peek_root_length(token_position position) const noexcept { + return *(position+2) - *(position) > *(position+1) - *(position) ? + *(position+1) - *(position) + : *(position+2) - *(position); } -simdjson_inline simdjson_result::operator lasx::ondemand::array() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline const uint8_t *token_iterator::peek(int32_t delta) const noexcept { + return &buf[*(_position+delta)]; } -simdjson_inline simdjson_result::operator lasx::ondemand::object() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline uint32_t token_iterator::peek_index(int32_t delta) const noexcept { + return *(_position+delta); } -simdjson_inline simdjson_result::operator uint64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline uint32_t token_iterator::peek_length(int32_t delta) const noexcept { + return *(_position+delta+1) - *(_position+delta); } -simdjson_inline simdjson_result::operator int64_t() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; + +simdjson_inline token_position token_iterator::position() const noexcept { + return _position; } -simdjson_inline simdjson_result::operator double() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline void token_iterator::set_position(token_position target_position) noexcept { + _position = target_position; } -simdjson_inline simdjson_result::operator std::string_view() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; + +simdjson_inline bool token_iterator::operator==(const token_iterator &other) const noexcept { + return _position == other._position; } -simdjson_inline simdjson_result::operator lasx::ondemand::raw_json_string() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline bool token_iterator::operator!=(const token_iterator &other) const noexcept { + return _position != other._position; } -simdjson_inline simdjson_result::operator bool() noexcept(false) { - if (error()) { throw simdjson_error(error()); } - return first; +simdjson_inline bool token_iterator::operator>(const token_iterator &other) const noexcept { + return _position > other._position; } -#endif - -simdjson_inline simdjson_result simdjson_result::raw_json_token() noexcept { - if (error()) { return error(); } - return first.raw_json_token(); +simdjson_inline bool token_iterator::operator>=(const token_iterator &other) const noexcept { + return _position >= other._position; } - -simdjson_inline simdjson_result simdjson_result::raw_json() noexcept { - if (error()) { return error(); } - return first.raw_json(); +simdjson_inline bool token_iterator::operator<(const token_iterator &other) const noexcept { + return _position < other._position; } - -simdjson_inline simdjson_result simdjson_result::current_location() noexcept { - if (error()) { return error(); } - return first.current_location(); +simdjson_inline bool token_iterator::operator<=(const token_iterator &other) const noexcept { + return _position <= other._position; } -simdjson_inline simdjson_result simdjson_result::current_depth() const noexcept { - if (error()) { return error(); } - return first.current_depth(); -} +} // namespace ondemand +} // namespace lasx +} // namespace simdjson -simdjson_inline simdjson_result simdjson_result::at_pointer( - std::string_view json_pointer) noexcept { - if (error()) { - return error(); - } - return first.at_pointer(json_pointer); -} +namespace simdjson { -simdjson_inline simdjson_result simdjson_result::at_path( - std::string_view json_path) noexcept { - if (error()) { - return error(); - } - return first.at_path(json_path); -} +simdjson_inline simdjson_result::simdjson_result(lasx::ondemand::token_iterator &&value) noexcept + : implementation_simdjson_result_base(std::forward(value)) {} +simdjson_inline simdjson_result::simdjson_result(error_code error) noexcept + : implementation_simdjson_result_base(error) {} } // namespace simdjson -#endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_INL_H -/* end file simdjson/generic/ondemand/value-inl.h for lasx */ +#endif // SIMDJSON_GENERIC_ONDEMAND_TOKEN_ITERATOR_INL_H +/* end file simdjson/generic/ondemand/token_iterator-inl.h for lasx */ /* including simdjson/generic/ondemand/value_iterator-inl.h for lasx: #include "simdjson/generic/ondemand/value_iterator-inl.h" */ /* begin file simdjson/generic/ondemand/value_iterator-inl.h for lasx */ #ifndef SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H @@ -117938,19 +123170,23 @@ simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get } return result; } + simdjson_warn_unused simdjson_inline simdjson_result value_iterator::get_root_bool(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("bool"); - uint8_t tmpbuf[5+1+1]; // +1 for null termination - tmpbuf[5+1] = '\0'; // make sure that buffer is always null terminated. - if (!_json_iter->copy_to_buffer(json, max_len, tmpbuf, 5+1)) { return incorrect_type_error("Not a boolean"); } - auto result = parse_bool(tmpbuf); - if(result.error() == SUCCESS) { - if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } - advance_root_scalar("bool"); - } - return result; + // We have a boolean if we have either "true" or "false" and the next character is either + // a structural character or whitespace. We also check that the length is correct: + // "true" and "false" are 4 and 5 characters long, respectively. + bool value_true = (max_len >= 4 && !atomparsing::str4ncmp(json, "true") && + (max_len == 4 || jsoncharutils::is_structural_or_whitespace(json[4]))); + bool value_false = (max_len >= 5 && !atomparsing::str4ncmp(json, "false") && + (max_len == 5 || jsoncharutils::is_structural_or_whitespace(json[5]))); + if(value_true == false && value_false == false) { return incorrect_type_error("Not a boolean"); } + if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } + advance_root_scalar("bool"); + return value_true; } + simdjson_inline simdjson_result value_iterator::is_root_null(bool check_trailing) noexcept { auto max_len = peek_root_length(); auto json = peek_root_scalar("null"); @@ -117959,6 +123195,8 @@ simdjson_inline simdjson_result value_iterator::is_root_null(bool check_tr if(result) { // we have something that looks like a null. if (check_trailing && !_json_iter->is_single_token()) { return TRAILING_CONTENT; } advance_root_scalar("null"); + } else if (json[0] == 'n') { + return incorrect_type_error("Not a null but starts with n"); } return result; } @@ -118250,6 +123488,8 @@ simdjson_inline simdjson_result::simdjson_result #endif // SIMDJSON_GENERIC_ONDEMAND_VALUE_ITERATOR_INL_H /* end file simdjson/generic/ondemand/value_iterator-inl.h for lasx */ + + /* end file simdjson/generic/ondemand/amalgamated.h for lasx */ /* including simdjson/lasx/end.h: #include "simdjson/lasx/end.h" */ /* begin file simdjson/lasx/end.h */ @@ -118290,6 +123530,5 @@ namespace simdjson { #endif // SIMDJSON_ONDEMAND_H /* end file simdjson/ondemand.h */ - #endif // SIMDJSON_H /* end file simdjson.h */ diff --git a/3rdparty/yasio/yasio/bindings/yasio_axlua.cpp b/3rdparty/yasio/yasio/bindings/yasio_axlua.cpp index ccd455283ca7..208f2b4ad653 100644 --- a/3rdparty/yasio/yasio/bindings/yasio_axlua.cpp +++ b/3rdparty/yasio/yasio/bindings/yasio_axlua.cpp @@ -37,8 +37,11 @@ SOFTWARE. # if !__has_attribute(format) # undef __has_attribute # endif -#include "cocos2d.h" -using namespace cocos2d; + +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" + +using namespace ax; namespace lyasio { @@ -72,7 +75,7 @@ static TIMER_ID loop(unsigned int n, float interval, vcallback_t callback) auto timerId = reinterpret_cast(++TimerObject::s_timerId); - std::string key = StringUtils::format("LSTMR#%p", timerId); + std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId)); Director::getInstance()->getScheduler()->schedule( [timerObj]( @@ -93,7 +96,7 @@ static TIMER_ID delay(float delay, vcallback_t callback) yasio::ref_ptr timerObj(new TimerObject(std::move(callback))); auto timerId = reinterpret_cast(++TimerObject::s_timerId); - std::string key = StringUtils::format("LSTMR#%p", timerId); + std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId)); Director::getInstance()->getScheduler()->schedule( [timerObj]( float /*dt*/) { // lambda expression hold the reference of timerObj automatically. @@ -108,7 +111,7 @@ static TIMER_ID delay(float delay, vcallback_t callback) static void kill(TIMER_ID timerId) { - std::string key = StringUtils::format("LSTMR#%p", timerId); + std::string key = fmt::format("LSTMR#{}", fmt::ptr(timerId)); Director::getInstance()->getScheduler()->unschedule(key, STIMER_TARGET_VALUE); } YASIO_LUA_API void clear() diff --git a/CMakeLists.txt b/CMakeLists.txt index 99360c0aee07..b02827bc79fb 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -47,9 +47,9 @@ include(AXBuildSet) option(AX_BUILD_TESTS "Build cpp & lua tests" ON) -add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) +add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) -# prevent tests project to build "axmol/core" again +# prevent tests project to build axmol engine again set(BUILD_ENGINE_DONE ON) if(AX_BUILD_TESTS) diff --git a/CMakeOptions.md b/CMakeOptions.md index 164e2bb4d2f5..1149b269d6f4 100644 --- a/CMakeOptions.md +++ b/CMakeOptions.md @@ -37,10 +37,8 @@ - AX_ENABLE_EXT_JSONDEFAULT: the UserDefault based on json, default: `FALSE` - AX_ENABLE_EXT_LUA: the lua extension, default: `TRUE` - AX_WITH_XXX: usually user don't need care it -- AX_USE_COMPAT_GL: whether use compat gl as renderer backend, default: win32: `TRUE`, others: `FALSE` - - win32: whether use ANGLE GLES backend - - osx: whether use OpenGL instead Metal backend - - ios/tvos: whether use GLES instead Metal backend +- AX_RENDER_API: specify render api: gl, mtl, d3d, default: `auto` +- AX_USE_ANGLE: whether use angle as win32 gl backend, default: `TRUE` - AX_CORE_PROFILE: whether strip all deprecated features, default `FALSE`, it's useful to pre-upgrade your game project to adapte future axmol versions - AX_ISA_LEVEL: specifiy SIMD Instructions Acceleration Level: 0~4, 0: disabled, 1: SSE2, 2: SSE4.1/NEON, 3: SSE4.2, 4: AVX2, default: 2 - AX_GLES_PROFILE: specify GLES profile version for GLES backend, valid value `200`, `300` diff --git a/core/2d/Action.cpp b/axmol/2d/Action.cpp similarity index 97% rename from core/2d/Action.cpp rename to axmol/2d/Action.cpp index d19d5af1c2b8..eb23ace4ef7b 100644 --- a/core/2d/Action.cpp +++ b/axmol/2d/Action.cpp @@ -27,11 +27,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Action.h" -#include "2d/ActionInterval.h" -#include "2d/Node.h" -#include "base/Director.h" -#include "base/UTF8.h" +#include "axmol/2d/Action.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" namespace ax { diff --git a/core/2d/Action.h b/axmol/2d/Action.h similarity index 95% rename from core/2d/Action.h rename to axmol/2d/Action.h index 0e57a29c2bb9..29bec3883c88 100644 --- a/core/2d/Action.h +++ b/axmol/2d/Action.h @@ -28,9 +28,9 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" -#include "math/Math.h" -#include "base/ScriptSupport.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/base/ScriptSupport.h" namespace ax { @@ -206,12 +206,12 @@ class AX_DLL FiniteTimeAction : public Action // // Overrides // - virtual FiniteTimeAction* reverse() const override + FiniteTimeAction* reverse() const override { AX_ASSERT(0); return nullptr; } - virtual FiniteTimeAction* clone() const override + FiniteTimeAction* clone() const override { AX_ASSERT(0); return nullptr; @@ -271,19 +271,19 @@ class AX_DLL Speed : public Action // // Override // - virtual Speed* clone() const override; - virtual Speed* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + Speed* clone() const override; + Speed* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param dt in seconds. */ - virtual void step(float dt) override; + void step(float dt) override; /** Return true if the action has finished. * * @return Is true if the action has finished. */ - virtual bool isDone() const override; + bool isDone() const override; Speed(); virtual ~Speed(); @@ -352,14 +352,14 @@ class AX_DLL Follow : public Action // // Override // - virtual Follow* clone() const override; - virtual Follow* reverse() const override; + Follow* clone() const override; + Follow* reverse() const override; /** * @param dt in seconds. */ - virtual void step(float dt) override; - virtual bool isDone() const override; - virtual void stop() override; + void step(float dt) override; + bool isDone() const override; + void stop() override; /** */ diff --git a/core/2d/ActionCamera.cpp b/axmol/2d/ActionCamera.cpp similarity index 98% rename from core/2d/ActionCamera.cpp rename to axmol/2d/ActionCamera.cpp index 2c51709a12f6..d5914f54ea2c 100644 --- a/core/2d/ActionCamera.cpp +++ b/axmol/2d/ActionCamera.cpp @@ -26,9 +26,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionCamera.h" -#include "2d/Node.h" -#include "platform/StdC.h" +#include "axmol/2d/ActionCamera.h" +#include "axmol/2d/Node.h" +#include "axmol/platform/StdC.h" namespace ax { diff --git a/core/2d/ActionCamera.h b/axmol/2d/ActionCamera.h similarity index 93% rename from core/2d/ActionCamera.h rename to axmol/2d/ActionCamera.h index 47743bf06c8e..d99c5150534b 100644 --- a/core/2d/ActionCamera.h +++ b/axmol/2d/ActionCamera.h @@ -28,8 +28,8 @@ THE SOFTWARE. #pragma once -#include "2d/ActionInterval.h" -#include "math/Math.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/math/Math.h" namespace ax { @@ -58,9 +58,9 @@ class AX_DLL ActionCamera : public ActionInterval virtual ~ActionCamera(){}; // Overrides - virtual void startWithTarget(Node* target) override; - virtual ActionCamera* reverse() const override; - virtual ActionCamera* clone() const override; + void startWithTarget(Node* target) override; + ActionCamera* reverse() const override; + ActionCamera* clone() const override; /* Sets the Eye value of the Camera. * @@ -136,8 +136,8 @@ class AX_DLL OrbitCamera : public ActionCamera // Overrides OrbitCamera* clone() const override; - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; + void startWithTarget(Node* target) override; + void update(float time) override; /** */ diff --git a/core/2d/ActionCatmullRom.cpp b/axmol/2d/ActionCatmullRom.cpp similarity index 99% rename from core/2d/ActionCatmullRom.cpp rename to axmol/2d/ActionCatmullRom.cpp index a53f6fc54ddf..359ceeb519aa 100644 --- a/core/2d/ActionCatmullRom.cpp +++ b/axmol/2d/ActionCatmullRom.cpp @@ -32,9 +32,9 @@ * * Adapted from cocos2d-x to cocos2d-iphone by Ricardo Quesada */ -#include "base/Macros.h" -#include "2d/ActionCatmullRom.h" -#include "2d/Node.h" +#include "axmol/base/Macros.h" +#include "axmol/2d/ActionCatmullRom.h" +#include "axmol/2d/Node.h" #include diff --git a/core/2d/ActionCatmullRom.h b/axmol/2d/ActionCatmullRom.h similarity index 92% rename from core/2d/ActionCatmullRom.h rename to axmol/2d/ActionCatmullRom.h index d95fc49f1306..5b9db1f3d2fc 100644 --- a/core/2d/ActionCatmullRom.h +++ b/axmol/2d/ActionCatmullRom.h @@ -38,8 +38,8 @@ #include -#include "2d/ActionInterval.h" -#include "math/Math.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/math/Math.h" namespace ax { @@ -200,14 +200,14 @@ class AX_DLL CardinalSplineTo : public ActionInterval } // Overrides - virtual CardinalSplineTo* clone() const override; - virtual CardinalSplineTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + CardinalSplineTo* clone() const override; + CardinalSplineTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; protected: /** Array of control points */ @@ -241,10 +241,10 @@ class AX_DLL CardinalSplineBy : public CardinalSplineTo CardinalSplineBy(); // Overrides - virtual void startWithTarget(Node* target) override; - virtual void updatePosition(const Vec2& newPos) override; - virtual CardinalSplineBy* clone() const override; - virtual CardinalSplineBy* reverse() const override; + void startWithTarget(Node* target) override; + void updatePosition(const Vec2& newPos) override; + CardinalSplineBy* clone() const override; + CardinalSplineBy* reverse() const override; protected: Vec2 _startPosition; @@ -279,8 +279,8 @@ class AX_DLL CatmullRomTo : public CardinalSplineTo bool initWithDuration(float dt, PointArray* points); // Override - virtual CatmullRomTo* clone() const override; - virtual CatmullRomTo* reverse() const override; + CatmullRomTo* clone() const override; + CatmullRomTo* reverse() const override; }; /** @class CatmullRomBy @@ -311,8 +311,8 @@ class AX_DLL CatmullRomBy : public CardinalSplineBy bool initWithDuration(float dt, PointArray* points); // Override - virtual CatmullRomBy* clone() const override; - virtual CatmullRomBy* reverse() const override; + CatmullRomBy* clone() const override; + CatmullRomBy* reverse() const override; }; /** Returns the Cardinal Spline position for a given set of control points, tension and time */ diff --git a/core/2d/ActionCoroutine.cpp b/axmol/2d/ActionCoroutine.cpp similarity index 98% rename from core/2d/ActionCoroutine.cpp rename to axmol/2d/ActionCoroutine.cpp index 1f55bc46957a..8be6f73d081b 100644 --- a/core/2d/ActionCoroutine.cpp +++ b/axmol/2d/ActionCoroutine.cpp @@ -27,7 +27,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ActionCoroutine.h" +#include "axmol/2d/ActionCoroutine.h" namespace ax { diff --git a/core/2d/ActionCoroutine.h b/axmol/2d/ActionCoroutine.h similarity index 97% rename from core/2d/ActionCoroutine.h rename to axmol/2d/ActionCoroutine.h index e4c80ac7784b..0a47d8e8e3e2 100644 --- a/core/2d/ActionCoroutine.h +++ b/axmol/2d/ActionCoroutine.h @@ -29,7 +29,7 @@ THE SOFTWARE. #pragma once -#include "2d/Action.h" +#include "axmol/2d/Action.h" #if __has_include() # include @@ -133,8 +133,8 @@ class AX_DLL ActionCoroutine : public Action // // Overrides // - virtual bool isDone() const override; - virtual void step(float dt) override; + bool isDone() const override; + void step(float dt) override; public: ActionCoroutine() = default; diff --git a/core/2d/ActionEase.cpp b/axmol/2d/ActionEase.cpp similarity index 99% rename from core/2d/ActionEase.cpp rename to axmol/2d/ActionEase.cpp index 587b22b16f10..49e018ca5a39 100644 --- a/core/2d/ActionEase.cpp +++ b/axmol/2d/ActionEase.cpp @@ -33,8 +33,8 @@ THE SOFTWARE. * by http://github.com/NikhilK */ -#include "2d/ActionEase.h" -#include "2d/TweenFunction.h" +#include "axmol/2d/ActionEase.h" +#include "axmol/2d/TweenFunction.h" namespace ax { diff --git a/core/2d/ActionEase.h b/axmol/2d/ActionEase.h similarity index 93% rename from core/2d/ActionEase.h rename to axmol/2d/ActionEase.h index 4890344ed217..504923fe290b 100644 --- a/core/2d/ActionEase.h +++ b/axmol/2d/ActionEase.h @@ -28,8 +28,8 @@ THE SOFTWARE. #pragma once -#include "2d/ActionInterval.h" -#include "2d/TweenFunction.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/TweenFunction.h" namespace ax { @@ -58,9 +58,9 @@ class AX_DLL ActionEase : public ActionInterval // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual void stop() override; - virtual void update(float time) override; + void startWithTarget(Node* target) override; + void stop() override; + void update(float time) override; ActionEase() : _inner(nullptr) {} @@ -130,9 +130,9 @@ class AX_DLL EaseRateAction : public ActionEase \ public: \ static CLASSNAME* create(ActionInterval* action); \ - virtual CLASSNAME* clone() const override; \ - virtual void update(float time) override; \ - virtual ActionEase* reverse() const override; \ + CLASSNAME* clone() const override; \ + void update(float time) override; \ + ActionEase* reverse() const override; \ \ private: \ AX_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \ @@ -381,9 +381,9 @@ EASE_TEMPLATE_DECL_CLASS(EaseCubicActionInOut); CLASSNAME() {} \ \ static CLASSNAME* create(ActionInterval* action, float rate); \ - virtual CLASSNAME* clone() const override; \ - virtual void update(float time) override; \ - virtual EaseRateAction* reverse() const override; \ + CLASSNAME* clone() const override; \ + void update(float time) override; \ + EaseRateAction* reverse() const override; \ \ private: \ AX_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \ @@ -467,9 +467,9 @@ class AX_DLL EaseElastic : public ActionEase CLASSNAME() {} \ \ static CLASSNAME* create(ActionInterval* action, float rate = 0.3f); \ - virtual CLASSNAME* clone() const override; \ - virtual void update(float time) override; \ - virtual EaseElastic* reverse() const override; \ + CLASSNAME* clone() const override; \ + void update(float time) override; \ + EaseElastic* reverse() const override; \ \ private: \ AX_DISALLOW_COPY_AND_ASSIGN(CLASSNAME); \ @@ -527,9 +527,9 @@ class AX_DLL EaseBezierAction : public ax::ActionEase */ static EaseBezierAction* create(ax::ActionInterval* action); - virtual void update(float time) override; - virtual EaseBezierAction* clone() const override; - virtual EaseBezierAction* reverse() const override; + void update(float time) override; + EaseBezierAction* clone() const override; + EaseBezierAction* reverse() const override; /** @brief Set the bezier parameters. diff --git a/core/2d/ActionGrid.cpp b/axmol/2d/ActionGrid.cpp similarity index 98% rename from core/2d/ActionGrid.cpp rename to axmol/2d/ActionGrid.cpp index 6700653b522a..6ce6200e1821 100644 --- a/core/2d/ActionGrid.cpp +++ b/axmol/2d/ActionGrid.cpp @@ -25,11 +25,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionGrid.h" +#include "axmol/2d/ActionGrid.h" -#include "2d/Grid.h" -#include "2d/NodeGrid.h" -#include "base/Director.h" +#include "axmol/2d/Grid.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/2d/ActionGrid.h b/axmol/2d/ActionGrid.h similarity index 88% rename from core/2d/ActionGrid.h rename to axmol/2d/ActionGrid.h index 976314ab8f46..ba6144af4426 100644 --- a/core/2d/ActionGrid.h +++ b/axmol/2d/ActionGrid.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionInterval.h" -#include "2d/ActionInstant.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/ActionInstant.h" namespace ax { @@ -55,13 +55,13 @@ class AX_DLL GridAction : public ActionInterval virtual GridBase* getGrid(); // overrides - virtual GridAction* clone() const override + GridAction* clone() const override { AX_ASSERT(0); return nullptr; } - virtual GridAction* reverse() const override; - virtual void startWithTarget(Node* target) override; + GridAction* reverse() const override; + void startWithTarget(Node* target) override; GridAction() {} virtual ~GridAction() {} @@ -91,7 +91,7 @@ class AX_DLL GridAction : public ActionInterval class AX_DLL Grid3DAction : public GridAction { public: - virtual GridBase* getGrid() override; + GridBase* getGrid() override; /** * @brief Get the vertex that belongs to certain position in the grid. * @param position The position of the grid. @@ -117,7 +117,7 @@ class AX_DLL Grid3DAction : public GridAction void setVertex(const Vec2& position, const Vec3& vertex); // Overrides - virtual Grid3DAction* clone() const override + Grid3DAction* clone() const override { AX_ASSERT(0); return nullptr; @@ -170,10 +170,10 @@ class AX_DLL TiledGrid3DAction : public GridAction void setTile(const Vec2& position, const Quad3& coords); /** returns the grid */ - virtual GridBase* getGrid() override; + GridBase* getGrid() override; // Override - virtual TiledGrid3DAction* clone() const override + TiledGrid3DAction* clone() const override { AX_ASSERT(0); return nullptr; @@ -206,10 +206,10 @@ class AX_DLL AccelDeccelAmplitude : public ActionInterval void setRate(float rate) { _rate = rate; } // Overrides - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; - virtual AccelDeccelAmplitude* clone() const override; - virtual AccelDeccelAmplitude* reverse() const override; + void startWithTarget(Node* target) override; + void update(float time) override; + AccelDeccelAmplitude* clone() const override; + AccelDeccelAmplitude* reverse() const override; AccelDeccelAmplitude() {} virtual ~AccelDeccelAmplitude(); @@ -256,10 +256,10 @@ class AX_DLL AccelAmplitude : public ActionInterval void setRate(float rate) { _rate = rate; } // Overrides - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; - virtual AccelAmplitude* clone() const override; - virtual AccelAmplitude* reverse() const override; + void startWithTarget(Node* target) override; + void update(float time) override; + AccelAmplitude* clone() const override; + AccelAmplitude* reverse() const override; AccelAmplitude() {} virtual ~AccelAmplitude(); @@ -300,10 +300,10 @@ class AX_DLL DeccelAmplitude : public ActionInterval void setRate(float rate) { _rate = rate; } // overrides - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; - virtual DeccelAmplitude* clone() const override; - virtual DeccelAmplitude* reverse() const override; + void startWithTarget(Node* target) override; + void update(float time) override; + DeccelAmplitude* clone() const override; + DeccelAmplitude* reverse() const override; DeccelAmplitude() {} virtual ~DeccelAmplitude(); @@ -342,9 +342,9 @@ class AX_DLL StopGrid : public ActionInstant static StopGrid* create(); // Overrides - virtual void startWithTarget(Node* target) override; - virtual StopGrid* clone() const override; - virtual StopGrid* reverse() const override; + void startWithTarget(Node* target) override; + StopGrid* clone() const override; + StopGrid* reverse() const override; StopGrid() {} virtual ~StopGrid() {} @@ -372,9 +372,9 @@ class AX_DLL ReuseGrid : public ActionInstant static ReuseGrid* create(int times); // Override - virtual void startWithTarget(Node* target) override; - virtual ReuseGrid* clone() const override; - virtual ReuseGrid* reverse() const override; + void startWithTarget(Node* target) override; + ReuseGrid* clone() const override; + ReuseGrid* reverse() const override; ReuseGrid() {} virtual ~ReuseGrid() {} diff --git a/core/2d/ActionGrid3D.cpp b/axmol/2d/ActionGrid3D.cpp similarity index 99% rename from core/2d/ActionGrid3D.cpp rename to axmol/2d/ActionGrid3D.cpp index e086224d6f80..99ec6228c065 100644 --- a/core/2d/ActionGrid3D.cpp +++ b/axmol/2d/ActionGrid3D.cpp @@ -25,8 +25,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionGrid3D.h" -#include "base/Director.h" +#include "axmol/2d/ActionGrid3D.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/2d/ActionGrid3D.h b/axmol/2d/ActionGrid3D.h similarity index 96% rename from core/2d/ActionGrid3D.h rename to axmol/2d/ActionGrid3D.h index a083c51e56c9..9146442c25c7 100644 --- a/core/2d/ActionGrid3D.h +++ b/axmol/2d/ActionGrid3D.h @@ -27,7 +27,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionGrid.h" +#include "axmol/2d/ActionGrid.h" namespace ax { @@ -79,8 +79,8 @@ class AX_DLL Waves3D : public Grid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Overrides - virtual Waves3D* clone() const override; - virtual void update(float time) override; + Waves3D* clone() const override; + void update(float time) override; Waves3D() {} virtual ~Waves3D() {} @@ -119,8 +119,8 @@ class AX_DLL FlipX3D : public Grid3DAction static FlipX3D* create(float duration); // Override - virtual FlipX3D* clone() const override; - virtual void update(float time) override; + FlipX3D* clone() const override; + void update(float time) override; FlipX3D() {} virtual ~FlipX3D() {} @@ -159,8 +159,8 @@ class AX_DLL FlipY3D : public FlipX3D static FlipY3D* create(float duration); // Overrides - virtual void update(float time) override; - virtual FlipY3D* clone() const override; + void update(float time) override; + FlipY3D* clone() const override; FlipY3D() {} virtual ~FlipY3D() {} @@ -220,8 +220,8 @@ class AX_DLL Lens3D : public Grid3DAction void setPosition(const Vec2& position); // Overrides - virtual Lens3D* clone() const override; - virtual void update(float time) override; + Lens3D* clone() const override; + void update(float time) override; Lens3D() {} virtual ~Lens3D() {} @@ -312,8 +312,8 @@ class AX_DLL Ripple3D : public Grid3DAction void setAmplitudeRate(float fAmplitudeRate) { _amplitudeRate = fAmplitudeRate; } // Override - virtual Ripple3D* clone() const override; - virtual void update(float time) override; + Ripple3D* clone() const override; + void update(float time) override; Ripple3D() {} virtual ~Ripple3D() {} @@ -367,8 +367,8 @@ class AX_DLL Shaky3D : public Grid3DAction static Shaky3D* create(float initWithDuration, const Vec2& gridSize, int range, bool shakeZ); // Overrides - virtual Shaky3D* clone() const override; - virtual void update(float time) override; + Shaky3D* clone() const override; + void update(float time) override; Shaky3D() {} virtual ~Shaky3D() {} @@ -433,8 +433,8 @@ class AX_DLL Liquid : public Grid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Overrides - virtual Liquid* clone() const override; - virtual void update(float time) override; + Liquid* clone() const override; + void update(float time) override; Liquid() {} virtual ~Liquid() {} @@ -508,8 +508,8 @@ class AX_DLL Waves : public Grid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Overrides - virtual Waves* clone() const override; - virtual void update(float time) override; + Waves* clone() const override; + void update(float time) override; Waves() {} virtual ~Waves() {} @@ -600,8 +600,8 @@ class AX_DLL Twirl : public Grid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Overrides - virtual Twirl* clone() const override; - virtual void update(float time) override; + Twirl* clone() const override; + void update(float time) override; Twirl() {} virtual ~Twirl() {} diff --git a/core/2d/ActionInstant.cpp b/axmol/2d/ActionInstant.cpp similarity index 98% rename from core/2d/ActionInstant.cpp rename to axmol/2d/ActionInstant.cpp index d4d92db1362f..3b51f87445b6 100644 --- a/core/2d/ActionInstant.cpp +++ b/axmol/2d/ActionInstant.cpp @@ -26,9 +26,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionInstant.h" -#include "2d/Node.h" -#include "2d/Sprite.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Sprite.h" namespace ax { diff --git a/core/2d/ActionInstant.h b/axmol/2d/ActionInstant.h similarity index 83% rename from core/2d/ActionInstant.h rename to axmol/2d/ActionInstant.h index dec6d2634d67..59e695cfdc58 100644 --- a/core/2d/ActionInstant.h +++ b/axmol/2d/ActionInstant.h @@ -29,7 +29,7 @@ THE SOFTWARE. #pragma once #include -#include "2d/Action.h" +#include "axmol/2d/Action.h" namespace ax { @@ -48,29 +48,29 @@ class AX_DLL ActionInstant : public FiniteTimeAction // // Overrides // - virtual ActionInstant* clone() const override + ActionInstant* clone() const override { AX_ASSERT(0); return nullptr; } - virtual ActionInstant* reverse() const override + ActionInstant* reverse() const override { AX_ASSERT(0); return nullptr; } - virtual void startWithTarget(Node* target) override; + void startWithTarget(Node* target) override; - virtual bool isDone() const override; + bool isDone() const override; /** * @param dt In seconds. */ - virtual void step(float dt) override; + void step(float dt) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; private: bool _done; @@ -94,9 +94,9 @@ class AX_DLL Show : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual ActionInstant* reverse() const override; - virtual Show* clone() const override; + void update(float time) override; + ActionInstant* reverse() const override; + Show* clone() const override; Show() {} virtual ~Show() {} @@ -123,9 +123,9 @@ class AX_DLL Hide : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual ActionInstant* reverse() const override; - virtual Hide* clone() const override; + void update(float time) override; + ActionInstant* reverse() const override; + Hide* clone() const override; Hide() {} virtual ~Hide() {} @@ -152,9 +152,9 @@ class AX_DLL ToggleVisibility : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual ToggleVisibility* reverse() const override; - virtual ToggleVisibility* clone() const override; + void update(float time) override; + ToggleVisibility* reverse() const override; + ToggleVisibility* clone() const override; ToggleVisibility() {} virtual ~ToggleVisibility() {} @@ -182,9 +182,9 @@ class AX_DLL RemoveSelf : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual RemoveSelf* clone() const override; - virtual RemoveSelf* reverse() const override; + void update(float time) override; + RemoveSelf* clone() const override; + RemoveSelf* reverse() const override; RemoveSelf() : _isNeedCleanUp(true) {} virtual ~RemoveSelf() {} @@ -219,9 +219,9 @@ class AX_DLL FlipX : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual FlipX* reverse() const override; - virtual FlipX* clone() const override; + void update(float time) override; + FlipX* reverse() const override; + FlipX* clone() const override; FlipX() : _flipX(false) {} virtual ~FlipX() {} @@ -256,9 +256,9 @@ class AX_DLL FlipY : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual FlipY* reverse() const override; - virtual FlipY* clone() const override; + void update(float time) override; + FlipY* reverse() const override; + FlipY* clone() const override; FlipY() : _flipY(false) {} virtual ~FlipY() {} @@ -292,9 +292,9 @@ class AX_DLL Place : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual Place* reverse() const override; - virtual Place* clone() const override; + void update(float time) override; + Place* reverse() const override; + Place* clone() const override; Place() {} virtual ~Place() {} @@ -337,9 +337,9 @@ class AX_DLL CallFunc : public ActionInstant /** * @param time In seconds. */ - virtual void update(float time) override; - virtual CallFunc* reverse() const override; - virtual CallFunc* clone() const override; + void update(float time) override; + CallFunc* reverse() const override; + CallFunc* clone() const override; CallFunc() = default; virtual ~CallFunc() = default; @@ -374,8 +374,8 @@ class AX_DLL CallFuncN : public CallFunc // // Overrides // - virtual CallFuncN* clone() const override; - virtual void execute() override; + CallFuncN* clone() const override; + void execute() override; CallFuncN() : _functionN(nullptr) {} virtual ~CallFuncN() {} diff --git a/core/2d/ActionInterval.cpp b/axmol/2d/ActionInterval.cpp similarity index 98% rename from core/2d/ActionInterval.cpp rename to axmol/2d/ActionInterval.cpp index 333794473dd1..3ee0c1db3c7f 100644 --- a/core/2d/ActionInterval.cpp +++ b/axmol/2d/ActionInterval.cpp @@ -27,19 +27,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionInterval.h" +#include "axmol/2d/ActionInterval.h" #include -#include "2d/Sprite.h" -#include "2d/Node.h" -#include "2d/SpriteFrame.h" -#include "2d/ActionInstant.h" -#include "base/Director.h" -#include "base/EventCustom.h" -#include "base/EventDispatcher.h" -#include "platform/StdC.h" -#include "base/ScriptSupport.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/platform/StdC.h" +#include "axmol/base/ScriptSupport.h" namespace ax { @@ -2208,10 +2208,10 @@ void FadeTo::update(float time) // // TintTo // -TintTo* TintTo::create(float duration, uint8_t red, uint8_t green, uint8_t blue) +TintTo* TintTo::create(float duration, const Color32& color) { TintTo* tintTo = new TintTo(); - if (tintTo->initWithDuration(duration, red, green, blue)) + if (tintTo->initWithDuration(duration, color)) { tintTo->autorelease(); return tintTo; @@ -2221,16 +2221,11 @@ TintTo* TintTo::create(float duration, uint8_t red, uint8_t green, uint8_t blue) return nullptr; } -TintTo* TintTo::create(float duration, const Color3B& color) -{ - return create(duration, color.r, color.g, color.b); -} - -bool TintTo::initWithDuration(float duration, uint8_t red, uint8_t green, uint8_t blue) +bool TintTo::initWithDuration(float duration, const Color32& color) { if (ActionInterval::initWithDuration(duration)) { - _to = Color3B(red, green, blue); + _to = color; return true; } @@ -2240,7 +2235,7 @@ bool TintTo::initWithDuration(float duration, uint8_t red, uint8_t green, uint8_ TintTo* TintTo::clone() const { // no copy constructor - return TintTo::create(_duration, _to.r, _to.g, _to.b); + return TintTo::create(_duration, _to); } TintTo* TintTo::reverse() const @@ -2262,9 +2257,11 @@ void TintTo::update(float time) { if (_target) { - _target->setColor(Color3B(uint8_t(_from.r + (_to.r - _from.r) * time), + // FIXME: should we need introduce opacity tint support in axmol-v3? + auto opacity = _target->getColor().a; + _target->setColor(Color32{uint8_t(_from.r + (_to.r - _from.r) * time), (uint8_t)(_from.g + (_to.g - _from.g) * time), - (uint8_t)(_from.b + (_to.b - _from.b) * time))); + (uint8_t)(_from.b + (_to.b - _from.b) * time), opacity}); } } @@ -2311,7 +2308,7 @@ void TintBy::startWithTarget(Node* target) if (target) { - Color3B color = target->getColor(); + auto color = target->getColor(); _fromR = color.r; _fromG = color.g; _fromB = color.b; @@ -2322,8 +2319,10 @@ void TintBy::update(float time) { if (_target) { - _target->setColor(Color3B((uint8_t)(_fromR + _deltaR * time), (uint8_t)(_fromG + _deltaG * time), - (uint8_t)(_fromB + _deltaB * time))); + // FIXME: do we should introduce opacity tint support in axmol-v3? + auto opacity = _target->getColor().a; + _target->setColor(Color32((uint8_t)(_fromR + _deltaR * time), (uint8_t)(_fromG + _deltaG * time), + (uint8_t)(_fromB + _deltaB * time), opacity)); } } diff --git a/core/2d/ActionInterval.h b/axmol/2d/ActionInterval.h similarity index 85% rename from core/2d/ActionInterval.h rename to axmol/2d/ActionInterval.h index 135622ba3e23..894dc910820e 100644 --- a/core/2d/ActionInterval.h +++ b/axmol/2d/ActionInterval.h @@ -31,10 +31,10 @@ THE SOFTWARE. #include -#include "2d/Action.h" -#include "2d/Animation.h" -#include "base/Protocols.h" -#include "base/Vector.h" +#include "axmol/2d/Action.h" +#include "axmol/2d/Animation.h" +#include "axmol/base/Protocols.h" +#include "axmol/base/Vector.h" namespace ax { @@ -92,19 +92,19 @@ class AX_DLL ActionInterval : public FiniteTimeAction // // Overrides // - virtual bool isDone() const override; + bool isDone() const override; /** * @param dt in seconds */ - virtual void step(float dt) override; - virtual void startWithTarget(Node* target) override; - virtual ActionInterval* reverse() const override + void step(float dt) override; + void startWithTarget(Node* target) override; + ActionInterval* reverse() const override { AX_ASSERT(0); return nullptr; } - virtual ActionInterval* clone() const override + ActionInterval* clone() const override { AX_ASSERT(0); return nullptr; @@ -164,15 +164,15 @@ class AX_DLL Sequence : public ActionInterval // // Overrides // - virtual Sequence* clone() const override; - virtual Sequence* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; - virtual bool isDone() const override; + Sequence* clone() const override; + Sequence* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; + bool isDone() const override; /** * @param t In seconds. */ - virtual void update(float t) override; + void update(float t) override; Sequence(); virtual ~Sequence(); @@ -228,15 +228,15 @@ class AX_DLL Repeat : public ActionInterval // // Overrides // - virtual Repeat* clone() const override; - virtual Repeat* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + Repeat* clone() const override; + Repeat* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param dt In seconds. */ - virtual void update(float dt) override; - virtual bool isDone() const override; + void update(float dt) override; + bool isDone() const override; Repeat() {} virtual ~Repeat(); @@ -294,14 +294,14 @@ class AX_DLL RepeatForever : public ActionInterval // // Overrides // - virtual RepeatForever* clone() const override; - virtual RepeatForever* reverse() const override; - virtual void startWithTarget(Node* target) override; + RepeatForever* clone() const override; + RepeatForever* reverse() const override; + void startWithTarget(Node* target) override; /** * @param dt In seconds. */ - virtual void step(float dt) override; - virtual bool isDone() const override; + void step(float dt) override; + bool isDone() const override; RepeatForever() : _innerAction(nullptr) {} virtual ~RepeatForever(); @@ -360,14 +360,14 @@ class AX_DLL Spawn : public ActionInterval // // Overrides // - virtual Spawn* clone() const override; - virtual Spawn* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + Spawn* clone() const override; + Spawn* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; Spawn(); virtual ~Spawn(); @@ -421,13 +421,13 @@ class AX_DLL RotateTo : public ActionInterval // // Overrides // - virtual RotateTo* clone() const override; - virtual RotateTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + RotateTo* clone() const override; + RotateTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; RotateTo(); virtual ~RotateTo() {} @@ -496,13 +496,13 @@ class AX_DLL RotateBy : public ActionInterval // // Override // - virtual RotateBy* clone() const override; - virtual RotateBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + RotateBy* clone() const override; + RotateBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; RotateBy(); virtual ~RotateBy() {} @@ -556,13 +556,13 @@ class AX_DLL MoveBy : public ActionInterval // // Overrides // - virtual MoveBy* clone() const override; - virtual MoveBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + MoveBy* clone() const override; + MoveBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time in seconds */ - virtual void update(float time) override; + void update(float time) override; MoveBy() : _is3D(false) {} virtual ~MoveBy() {} @@ -608,9 +608,9 @@ class AX_DLL MoveTo : public MoveBy // // Overrides // - virtual MoveTo* clone() const override; - virtual MoveTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + MoveTo* clone() const override; + MoveTo* reverse() const override; + void startWithTarget(Node* target) override; MoveTo() {} virtual ~MoveTo() {} @@ -652,13 +652,13 @@ class AX_DLL SkewTo : public ActionInterval // // Overrides // - virtual SkewTo* clone() const override; - virtual SkewTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + SkewTo* clone() const override; + SkewTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; SkewTo(); virtual ~SkewTo() {} @@ -700,9 +700,9 @@ class AX_DLL SkewBy : public SkewTo // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual SkewBy* clone() const override; - virtual SkewBy* reverse() const override; + void startWithTarget(Node* target) override; + SkewBy* clone() const override; + SkewBy* reverse() const override; SkewBy() {} virtual ~SkewBy() {} @@ -734,7 +734,7 @@ class AX_DLL ResizeTo : public ActionInterval // // Overrides // - virtual ResizeTo* clone() const override; + ResizeTo* clone() const override; void startWithTarget(ax::Node* target) override; void update(float time) override; @@ -776,13 +776,13 @@ class AX_DLL ResizeBy : public ActionInterval // // Overrides // - virtual ResizeBy* clone() const override; - virtual ResizeBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + ResizeBy* clone() const override; + ResizeBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time in seconds */ - virtual void update(float time) override; + void update(float time) override; ResizeBy() {} virtual ~ResizeBy() {} @@ -818,13 +818,13 @@ class AX_DLL JumpBy : public ActionInterval // // Overrides // - virtual JumpBy* clone() const override; - virtual JumpBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + JumpBy* clone() const override; + JumpBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; JumpBy() {} virtual ~JumpBy() {} @@ -865,9 +865,9 @@ class AX_DLL JumpTo : public JumpBy // // Override // - virtual void startWithTarget(Node* target) override; - virtual JumpTo* clone() const override; - virtual JumpTo* reverse() const override; + void startWithTarget(Node* target) override; + JumpTo* clone() const override; + JumpTo* reverse() const override; JumpTo() {} virtual ~JumpTo() {} @@ -920,13 +920,13 @@ class AX_DLL BezierBy : public ActionInterval // // Overrides // - virtual BezierBy* clone() const override; - virtual BezierBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + BezierBy* clone() const override; + BezierBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; BezierBy() {} virtual ~BezierBy() {} @@ -968,9 +968,9 @@ class AX_DLL BezierTo : public BezierBy // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual BezierTo* clone() const override; - virtual BezierTo* reverse() const override; + void startWithTarget(Node* target) override; + BezierTo* clone() const override; + BezierTo* reverse() const override; BezierTo() {} virtual ~BezierTo() {} @@ -1024,13 +1024,13 @@ class AX_DLL ScaleTo : public ActionInterval // // Overrides // - virtual ScaleTo* clone() const override; - virtual ScaleTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + ScaleTo* clone() const override; + ScaleTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; ScaleTo() {} virtual ~ScaleTo() {} @@ -1106,9 +1106,9 @@ class AX_DLL ScaleBy : public ScaleTo // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual ScaleBy* clone() const override; - virtual ScaleBy* reverse() const override; + void startWithTarget(Node* target) override; + ScaleBy* clone() const override; + ScaleBy* reverse() const override; ScaleBy() {} virtual ~ScaleBy() {} @@ -1134,14 +1134,14 @@ class AX_DLL Blink : public ActionInterval // // Overrides // - virtual Blink* clone() const override; - virtual Blink* reverse() const override; + Blink* clone() const override; + Blink* reverse() const override; /** * @param time In seconds. */ - virtual void update(float time) override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + void update(float time) override; + void startWithTarget(Node* target) override; + void stop() override; Blink() {} virtual ~Blink() {} @@ -1179,13 +1179,13 @@ class AX_DLL FadeTo : public ActionInterval // // Overrides // - virtual FadeTo* clone() const override; - virtual FadeTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + FadeTo* clone() const override; + FadeTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; FadeTo() {} virtual ~FadeTo() {} @@ -1223,9 +1223,9 @@ class AX_DLL FadeIn : public FadeTo // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual FadeIn* clone() const override; - virtual FadeTo* reverse() const override; + void startWithTarget(Node* target) override; + FadeIn* clone() const override; + FadeTo* reverse() const override; /** */ @@ -1255,9 +1255,9 @@ class AX_DLL FadeOut : public FadeTo // // Overrides // - virtual void startWithTarget(Node* target) override; - virtual FadeOut* clone() const override; - virtual FadeTo* reverse() const override; + void startWithTarget(Node* target) override; + FadeOut* clone() const override; + FadeTo* reverse() const override; /** */ @@ -1282,40 +1282,35 @@ class AX_DLL TintTo : public ActionInterval /** * Creates an action with duration and color. * @param duration Duration time, in seconds. - * @param red Red Color, from 0 to 255. - * @param green Green Color, from 0 to 255. - * @param blue Blue Color, from 0 to 255. - * @return An autoreleased TintTo object. - */ - static TintTo* create(float duration, uint8_t red, uint8_t green, uint8_t blue); - /** - * Creates an action with duration and color. - * @param duration Duration time, in seconds. - * @param color It's a Color3B type. + * @param color It's a Color32 type. * @return An autoreleased TintTo object. */ - static TintTo* create(float duration, const Color3B& color); + static TintTo* create(float duration, uint8_t r, uint8_t g, uint8_t b) + { + return TintTo::create(duration, Color32{r, g, b}); + } + static TintTo* create(float duration, const Color32& color); // // Overrides // - virtual TintTo* clone() const override; - virtual TintTo* reverse() const override; - virtual void startWithTarget(Node* target) override; + TintTo* clone() const override; + TintTo* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; TintTo() {} virtual ~TintTo() {} /** initializes the action with duration and color */ - bool initWithDuration(float duration, uint8_t red, uint8_t green, uint8_t blue); + bool initWithDuration(float duration, const Color32& color); protected: - Color3B _to; - Color3B _from; + Color32 _to; + Color32 _from; private: AX_DISALLOW_COPY_AND_ASSIGN(TintTo); @@ -1341,13 +1336,13 @@ class AX_DLL TintBy : public ActionInterval // // Overrides // - virtual TintBy* clone() const override; - virtual TintBy* reverse() const override; - virtual void startWithTarget(Node* target) override; + TintBy* clone() const override; + TintBy* reverse() const override; + void startWithTarget(Node* target) override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; TintBy() {} virtual ~TintBy() {} @@ -1387,9 +1382,9 @@ class AX_DLL DelayTime : public ActionInterval /** * @param time In seconds. */ - virtual void update(float time) override; - virtual DelayTime* reverse() const override; - virtual DelayTime* clone() const override; + void update(float time) override; + DelayTime* reverse() const override; + DelayTime* clone() const override; DelayTime() {} virtual ~DelayTime() {} @@ -1419,14 +1414,14 @@ class AX_DLL ReverseTime : public ActionInterval // // Overrides // - virtual ReverseTime* reverse() const override; - virtual ReverseTime* clone() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + ReverseTime* reverse() const override; + ReverseTime* clone() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; ReverseTime(); virtual ~ReverseTime(); @@ -1475,14 +1470,14 @@ class AX_DLL Animate : public ActionInterval // // Overrides // - virtual Animate* clone() const override; - virtual Animate* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + Animate* clone() const override; + Animate* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param t In seconds. */ - virtual void update(float t) override; + void update(float t) override; Animate(); virtual ~Animate(); @@ -1535,14 +1530,14 @@ class AX_DLL TargetedAction : public ActionInterval // // Overrides // - virtual TargetedAction* clone() const override; - virtual TargetedAction* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void stop() override; + TargetedAction* clone() const override; + TargetedAction* reverse() const override; + void startWithTarget(Node* target) override; + void stop() override; /** * @param time In seconds. */ - virtual void update(float time) override; + void update(float time) override; TargetedAction(); virtual ~TargetedAction(); diff --git a/core/2d/ActionManager.cpp b/axmol/2d/ActionManager.cpp similarity index 98% rename from core/2d/ActionManager.cpp rename to axmol/2d/ActionManager.cpp index 18476167daad..4621cb5af8d0 100644 --- a/core/2d/ActionManager.cpp +++ b/axmol/2d/ActionManager.cpp @@ -28,11 +28,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionManager.h" -#include "2d/Node.h" -#include "2d/Action.h" -#include "base/Scheduler.h" -#include "base/Macros.h" +#include "axmol/2d/ActionManager.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Action.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/2d/ActionManager.h b/axmol/2d/ActionManager.h similarity index 98% rename from core/2d/ActionManager.h rename to axmol/2d/ActionManager.h index 6e5519de13d3..c2619a247789 100644 --- a/core/2d/ActionManager.h +++ b/axmol/2d/ActionManager.h @@ -30,9 +30,9 @@ THE SOFTWARE. #pragma once -#include "2d/Action.h" -#include "base/Vector.h" -#include "base/Object.h" +#include "axmol/2d/Action.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Object.h" namespace ax { diff --git a/core/2d/ActionPageTurn3D.cpp b/axmol/2d/ActionPageTurn3D.cpp similarity index 97% rename from core/2d/ActionPageTurn3D.cpp rename to axmol/2d/ActionPageTurn3D.cpp index fca74f9b491e..4595adb6ccae 100644 --- a/core/2d/ActionPageTurn3D.cpp +++ b/axmol/2d/ActionPageTurn3D.cpp @@ -24,9 +24,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionPageTurn3D.h" -#include "2d/Grid.h" -#include "2d/NodeGrid.h" +#include "axmol/2d/ActionPageTurn3D.h" +#include "axmol/2d/Grid.h" +#include "axmol/2d/NodeGrid.h" namespace ax { diff --git a/core/2d/ActionPageTurn3D.h b/axmol/2d/ActionPageTurn3D.h similarity index 93% rename from core/2d/ActionPageTurn3D.h rename to axmol/2d/ActionPageTurn3D.h index a0054d7ef6aa..859c1a674d3c 100644 --- a/core/2d/ActionPageTurn3D.h +++ b/axmol/2d/ActionPageTurn3D.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionGrid3D.h" +#include "axmol/2d/ActionGrid3D.h" namespace ax { @@ -50,7 +50,7 @@ class AX_DLL PageTurn3D : public Grid3DAction public: /** */ - virtual GridBase* getGrid() override; + GridBase* getGrid() override; /** @brief Create an action with duration, grid size. @@ -61,8 +61,8 @@ class AX_DLL PageTurn3D : public Grid3DAction static PageTurn3D* create(float duration, const Vec2& gridSize); // Overrides - virtual PageTurn3D* clone() const override; - virtual void update(float time) override; + PageTurn3D* clone() const override; + void update(float time) override; }; // end of actions group diff --git a/core/2d/ActionProgressTimer.cpp b/axmol/2d/ActionProgressTimer.cpp similarity index 97% rename from core/2d/ActionProgressTimer.cpp rename to axmol/2d/ActionProgressTimer.cpp index fa8bf2beb899..9a3210955c66 100644 --- a/core/2d/ActionProgressTimer.cpp +++ b/axmol/2d/ActionProgressTimer.cpp @@ -24,8 +24,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionProgressTimer.h" -#include "2d/ProgressTimer.h" +#include "axmol/2d/ActionProgressTimer.h" +#include "axmol/2d/ProgressTimer.h" namespace ax { diff --git a/core/2d/ActionProgressTimer.h b/axmol/2d/ActionProgressTimer.h similarity index 90% rename from core/2d/ActionProgressTimer.h rename to axmol/2d/ActionProgressTimer.h index f66da5d00abc..4c4e4475c8c9 100644 --- a/core/2d/ActionProgressTimer.h +++ b/axmol/2d/ActionProgressTimer.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionInterval.h" +#include "axmol/2d/ActionInterval.h" namespace ax { @@ -56,10 +56,10 @@ class AX_DLL ProgressTo : public ActionInterval // // Overrides // - virtual ProgressTo* clone() const override; - virtual ProgressTo* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; + ProgressTo* clone() const override; + ProgressTo* reverse() const override; + void startWithTarget(Node* target) override; + void update(float time) override; ProgressTo() {} virtual ~ProgressTo() {} @@ -99,10 +99,10 @@ class AX_DLL ProgressFromTo : public ActionInterval // // Overrides // - virtual ProgressFromTo* clone() const override; - virtual ProgressFromTo* reverse() const override; - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; + ProgressFromTo* clone() const override; + ProgressFromTo* reverse() const override; + void startWithTarget(Node* target) override; + void update(float time) override; ProgressFromTo() {} virtual ~ProgressFromTo() {} diff --git a/core/2d/ActionTiledGrid.cpp b/axmol/2d/ActionTiledGrid.cpp similarity index 99% rename from core/2d/ActionTiledGrid.cpp rename to axmol/2d/ActionTiledGrid.cpp index 9e6e76e68d03..b5a96eb503d6 100644 --- a/core/2d/ActionTiledGrid.cpp +++ b/axmol/2d/ActionTiledGrid.cpp @@ -24,11 +24,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionTiledGrid.h" -#include "2d/Grid.h" -#include "2d/NodeGrid.h" -#include "base/Director.h" -#include "base/Macros.h" +#include "axmol/2d/ActionTiledGrid.h" +#include "axmol/2d/Grid.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/base/Director.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/2d/ActionTiledGrid.h b/axmol/2d/ActionTiledGrid.h similarity index 92% rename from core/2d/ActionTiledGrid.h rename to axmol/2d/ActionTiledGrid.h index fff0fc745c14..70c1a272d0b0 100644 --- a/core/2d/ActionTiledGrid.h +++ b/axmol/2d/ActionTiledGrid.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionGrid.h" +#include "axmol/2d/ActionGrid.h" namespace ax { @@ -56,8 +56,8 @@ class AX_DLL ShakyTiles3D : public TiledGrid3DAction static ShakyTiles3D* create(float duration, const Vec2& gridSize, int range, bool shakeZ); // Override - virtual ShakyTiles3D* clone() const override; - virtual void update(float time) override; + ShakyTiles3D* clone() const override; + void update(float time) override; ShakyTiles3D() {} virtual ~ShakyTiles3D() {} @@ -100,8 +100,8 @@ class AX_DLL ShatteredTiles3D : public TiledGrid3DAction static ShatteredTiles3D* create(float duration, const Vec2& gridSize, int range, bool shatterZ); // Override - virtual ShatteredTiles3D* clone() const override; - virtual void update(float time) override; + ShatteredTiles3D* clone() const override; + void update(float time) override; ShatteredTiles3D() {} virtual ~ShatteredTiles3D() {} @@ -149,9 +149,9 @@ class AX_DLL ShuffleTiles : public TiledGrid3DAction void placeTile(const Vec2& pos, Tile* t); // Overrides - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; - virtual ShuffleTiles* clone() const override; + void startWithTarget(Node* target) override; + void update(float time) override; + ShuffleTiles* clone() const override; ShuffleTiles() {} virtual ~ShuffleTiles(); @@ -218,8 +218,8 @@ class AX_DLL FadeOutTRTiles : public TiledGrid3DAction virtual void transformTile(const Vec2& pos, float distance); // Overrides - virtual void update(float time) override; - virtual FadeOutTRTiles* clone() const override; + void update(float time) override; + FadeOutTRTiles* clone() const override; FadeOutTRTiles() {} virtual ~FadeOutTRTiles() {} @@ -244,8 +244,8 @@ class AX_DLL FadeOutBLTiles : public FadeOutTRTiles static FadeOutBLTiles* create(float duration, const Vec2& gridSize); // Overrides - virtual float testFunc(const Vec2& pos, float time) override; - virtual FadeOutBLTiles* clone() const override; + float testFunc(const Vec2& pos, float time) override; + FadeOutBLTiles* clone() const override; FadeOutBLTiles() {} virtual ~FadeOutBLTiles() {} @@ -269,11 +269,11 @@ class AX_DLL FadeOutUpTiles : public FadeOutTRTiles */ static FadeOutUpTiles* create(float duration, const Vec2& gridSize); - virtual void transformTile(const Vec2& pos, float distance) override; + void transformTile(const Vec2& pos, float distance) override; // Overrides - virtual FadeOutUpTiles* clone() const override; - virtual float testFunc(const Vec2& pos, float time) override; + FadeOutUpTiles* clone() const override; + float testFunc(const Vec2& pos, float time) override; FadeOutUpTiles() {} virtual ~FadeOutUpTiles() {} @@ -298,8 +298,8 @@ class AX_DLL FadeOutDownTiles : public FadeOutUpTiles static FadeOutDownTiles* create(float duration, const Vec2& gridSize); // Overrides - virtual FadeOutDownTiles* clone() const override; - virtual float testFunc(const Vec2& pos, float time) override; + FadeOutDownTiles* clone() const override; + float testFunc(const Vec2& pos, float time) override; FadeOutDownTiles() {} virtual ~FadeOutDownTiles() {} @@ -351,9 +351,9 @@ class AX_DLL TurnOffTiles : public TiledGrid3DAction void turnOffTile(const Vec2& pos); // Overrides - virtual TurnOffTiles* clone() const override; - virtual void startWithTarget(Node* target) override; - virtual void update(float time) override; + TurnOffTiles* clone() const override; + void startWithTarget(Node* target) override; + void update(float time) override; TurnOffTiles() {} virtual ~TurnOffTiles(); @@ -416,8 +416,8 @@ class AX_DLL WavesTiles3D : public TiledGrid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Override - virtual WavesTiles3D* clone() const override; - virtual void update(float time) override; + WavesTiles3D* clone() const override; + void update(float time) override; WavesTiles3D() {} virtual ~WavesTiles3D() {} @@ -481,8 +481,8 @@ class AX_DLL JumpTiles3D : public TiledGrid3DAction void setAmplitudeRate(float amplitudeRate) { _amplitudeRate = amplitudeRate; } // Override - virtual JumpTiles3D* clone() const override; - virtual void update(float time) override; + JumpTiles3D* clone() const override; + void update(float time) override; JumpTiles3D() {} virtual ~JumpTiles3D() {} @@ -523,9 +523,9 @@ class AX_DLL SplitRows : public TiledGrid3DAction static SplitRows* create(float duration, unsigned int rows); // Overrides - virtual SplitRows* clone() const override; - virtual void update(float time) override; - virtual void startWithTarget(Node* target) override; + SplitRows* clone() const override; + void update(float time) override; + void startWithTarget(Node* target) override; SplitRows() {} virtual ~SplitRows() {} @@ -563,12 +563,12 @@ class AX_DLL SplitCols : public TiledGrid3DAction static SplitCols* create(float duration, unsigned int cols); // Overrides - virtual SplitCols* clone() const override; + SplitCols* clone() const override; /** * @param time in seconds */ - virtual void update(float time) override; - virtual void startWithTarget(Node* target) override; + void update(float time) override; + void startWithTarget(Node* target) override; SplitCols() {} virtual ~SplitCols() {} diff --git a/core/2d/ActionTween.cpp b/axmol/2d/ActionTween.cpp similarity index 98% rename from core/2d/ActionTween.cpp rename to axmol/2d/ActionTween.cpp index b3040918fe84..ee2ea21222e5 100644 --- a/core/2d/ActionTween.cpp +++ b/axmol/2d/ActionTween.cpp @@ -25,7 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ActionTween.h" +#include "axmol/2d/ActionTween.h" namespace ax { diff --git a/core/2d/ActionTween.h b/axmol/2d/ActionTween.h similarity index 99% rename from core/2d/ActionTween.h rename to axmol/2d/ActionTween.h index b92aa3bf0cef..efc981ab59a2 100644 --- a/core/2d/ActionTween.h +++ b/axmol/2d/ActionTween.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ActionInterval.h" +#include "axmol/2d/ActionInterval.h" namespace ax { diff --git a/core/2d/AnchoredSprite.cpp b/axmol/2d/AnchoredSprite.cpp similarity index 92% rename from core/2d/AnchoredSprite.cpp rename to axmol/2d/AnchoredSprite.cpp index f0d2efcdf2bd..7800684ee89c 100644 --- a/core/2d/AnchoredSprite.cpp +++ b/axmol/2d/AnchoredSprite.cpp @@ -26,9 +26,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/AnchoredSprite.h" -#include "renderer/backend/DriverBase.h" -#include "base/format.h" +#include "axmol/2d/AnchoredSprite.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/base/format.h" namespace ax { @@ -72,7 +72,7 @@ AnchoredSprite* AnchoredSprite::createWithTexture(Texture2D* texture, const Rect AnchoredSprite* AnchoredSprite::create(std::string_view filename) { - return AnchoredSprite::create(filename, Texture2D::getDefaultAlphaPixelFormat()); + return AnchoredSprite::create(filename, PixelFormat::NONE); } AnchoredSprite* AnchoredSprite::create(std::string_view filename, PixelFormat format) @@ -127,7 +127,7 @@ AnchoredSprite* AnchoredSprite::createWithSpriteFrameName(std::string_view sprit { SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName); -#if _AX_DEBUG > 0 +#if defined(_AX_DEBUG) && _AX_DEBUG > 0 char msg[256]; fmt::format_to_z(msg, "Invalid spriteFrameName: {}", spriteFrameName); AXASSERT(frame != nullptr, msg); @@ -148,7 +148,7 @@ AnchoredSprite* AnchoredSprite::create() return nullptr; } -void AnchoredSprite::setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad) +void AnchoredSprite::setVertexCoords(const Rect& rect, V3F_T2F_C4B_Quad* outQuad) { float relativeOffsetX = _unflippedOffsetPositionFromCenter.x - getContentSize().x * _spriteVertexAnchor.x; float relativeOffsetY = _unflippedOffsetPositionFromCenter.y - getContentSize().y * _spriteVertexAnchor.y; @@ -187,10 +187,10 @@ void AnchoredSprite::setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad const float y2 = y1 + rect.size.height; // Don't update Z. - outQuad->bl.vertices.set(x1, y1, 0.0f); - outQuad->br.vertices.set(x2, y1, 0.0f); - outQuad->tl.vertices.set(x1, y2, 0.0f); - outQuad->tr.vertices.set(x2, y2, 0.0f); + outQuad->bl.position.set(x1, y1, 0.0f); + outQuad->br.position.set(x2, y1, 0.0f); + outQuad->tl.position.set(x1, y2, 0.0f); + outQuad->tr.position.set(x2, y2, 0.0f); } } diff --git a/core/2d/AnchoredSprite.h b/axmol/2d/AnchoredSprite.h similarity index 96% rename from core/2d/AnchoredSprite.h rename to axmol/2d/AnchoredSprite.h index f749fe489942..47869fa62227 100644 --- a/core/2d/AnchoredSprite.h +++ b/axmol/2d/AnchoredSprite.h @@ -29,7 +29,7 @@ THE SOFTWARE. #pragma once #include -#include "2d/Sprite.h" +#include "axmol/2d/Sprite.h" namespace ax { @@ -138,12 +138,12 @@ class AX_DLL AnchoredSprite : public Sprite static AnchoredSprite* createWithSpriteFrameName(std::string_view spriteFrameName); /* This function will reposition the sprite's vertices itself instead of the node */ - virtual void setAnchorPoint(const Vec2& anchor) override; + void setAnchorPoint(const Vec2& anchor) override; /* Gets the hit area of the anchored sprite, this requires special calculations for shifted vertices and should be used with touch event listeners */ virtual Rect getTouchRect(); protected: - virtual void setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad) override; + void setVertexCoords(const Rect& rect, V3F_T2F_C4B_Quad* outQuad) override; Vec2 _spriteVertexAnchor = Vec2::ANCHOR_MIDDLE; }; diff --git a/core/2d/Animation.cpp b/axmol/2d/Animation.cpp similarity index 97% rename from core/2d/Animation.cpp rename to axmol/2d/Animation.cpp index 238d86907f4f..9fa0de30f60d 100644 --- a/core/2d/Animation.cpp +++ b/axmol/2d/Animation.cpp @@ -26,10 +26,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Animation.h" -#include "renderer/TextureCache.h" -#include "renderer/Texture2D.h" -#include "base/Director.h" +#include "axmol/2d/Animation.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/2d/Animation.h b/axmol/2d/Animation.h similarity index 97% rename from core/2d/Animation.h rename to axmol/2d/Animation.h index 4cd8a9ae5eac..0213f955d872 100644 --- a/core/2d/Animation.h +++ b/axmol/2d/Animation.h @@ -28,11 +28,11 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" -#include "base/Object.h" -#include "base/Value.h" -#include "base/Vector.h" -#include "2d/SpriteFrame.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/base/Object.h" +#include "axmol/base/Value.h" +#include "axmol/base/Vector.h" +#include "axmol/2d/SpriteFrame.h" #include @@ -120,7 +120,7 @@ class AX_DLL AnimationFrame : public Object, public Clonable void setUserInfo(const ValueMap& userInfo) { _userInfo = userInfo; } // Overrides - virtual AnimationFrame* clone() const override; + AnimationFrame* clone() const override; /** */ @@ -270,7 +270,7 @@ class AX_DLL Animation : public Object, public Clonable void setLoops(unsigned int loops) { _loops = loops; }; // overrides - virtual Animation* clone() const override; + Animation* clone() const override; Animation(); virtual ~Animation(); diff --git a/core/2d/AnimationCache.cpp b/axmol/2d/AnimationCache.cpp similarity index 98% rename from core/2d/AnimationCache.cpp rename to axmol/2d/AnimationCache.cpp index f131e8ddda4a..04e0be707982 100644 --- a/core/2d/AnimationCache.cpp +++ b/axmol/2d/AnimationCache.cpp @@ -26,9 +26,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/AnimationCache.h" -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" +#include "axmol/2d/AnimationCache.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" using namespace std; diff --git a/core/2d/AnimationCache.h b/axmol/2d/AnimationCache.h similarity index 96% rename from core/2d/AnimationCache.h rename to axmol/2d/AnimationCache.h index 96120a2d13f7..cce72c3b1270 100644 --- a/core/2d/AnimationCache.h +++ b/axmol/2d/AnimationCache.h @@ -28,10 +28,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Object.h" -#include "base/Map.h" -#include "base/Value.h" -#include "2d/Animation.h" +#include "axmol/base/Object.h" +#include "axmol/base/Map.h" +#include "axmol/base/Value.h" +#include "axmol/2d/Animation.h" #include diff --git a/core/2d/AtlasNode.cpp b/axmol/2d/AtlasNode.cpp similarity index 85% rename from core/2d/AtlasNode.cpp rename to axmol/2d/AtlasNode.cpp index ca44f778df03..7b3d0a96983e 100644 --- a/core/2d/AtlasNode.cpp +++ b/axmol/2d/AtlasNode.cpp @@ -4,6 +4,7 @@ Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2011 Zynga Inc. Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,16 +26,16 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/AtlasNode.h" +#include "axmol/2d/AtlasNode.h" #include // offsetof -#include "base/Types.h" -#include "renderer/TextureAtlas.h" -#include "base/Director.h" -#include "renderer/TextureCache.h" -#include "base/Utils.h" -#include "renderer/Shaders.h" -#include "renderer/Renderer.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -72,7 +73,7 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh _itemWidth = tileWidth; _itemHeight = tileHeight; - _colorUnmodified = Color3B::WHITE; + _colorUnmodified = Color32::WHITE; _isOpacityModifyRGB = true; _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; @@ -81,7 +82,7 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh _textureAtlas->initWithTexture(texture, itemsToRender); - setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, texture); + setProgramStateWithRegistry(rhi::ProgramType::POSITION_TEXTURE_COLOR, texture); this->updateBlendFunc(); this->updateOpacityModifyRGB(); @@ -93,12 +94,12 @@ bool AtlasNode::initWithTexture(Texture2D* texture, int tileWidth, int tileHeigh return true; } -bool AtlasNode::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) +bool AtlasNode::setProgramState(rhi::ProgramState* programState, bool ownPS /*= false*/) { if (Node::setProgramState(programState, ownPS)) { - auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _quadCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; _mvpMatrixLocation = _programState->getUniformLocation("u_MVPMatrix"); updateProgramStateTexture(_textureAtlas->getTexture()); @@ -133,7 +134,7 @@ void AtlasNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) if (_textureAtlas->getTotalQuads() == 0) return; - auto programState = _quadCommand.getPipelineDescriptor().programState; + auto programState = _quadCommand.getPipelineDesc().programState; const auto& projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m)); @@ -145,7 +146,7 @@ void AtlasNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) // AtlasNode - RGBA protocol -const Color3B& AtlasNode::getColor() const +const Color32& AtlasNode::getColor() const { if (_isOpacityModifyRGB) { @@ -154,16 +155,15 @@ const Color3B& AtlasNode::getColor() const return Node::getColor(); } -void AtlasNode::setColor(const Color3B& color3) +void AtlasNode::setColor(const Color32& color) { - Color3B tmp = color3; - _colorUnmodified = color3; - + Color32 tmp = color; + _colorUnmodified = color; if (_isOpacityModifyRGB) { - tmp.r = tmp.r * _displayedOpacity / 255; - tmp.g = tmp.g * _displayedOpacity / 255; - tmp.b = tmp.b * _displayedOpacity / 255; + tmp.r = tmp.r * _displayedColor.a / 255; + tmp.g = tmp.g * _displayedColor.a / 255; + tmp.b = tmp.b * _displayedColor.a / 255; } Node::setColor(tmp); } @@ -179,7 +179,7 @@ void AtlasNode::setOpacity(uint8_t opacity) void AtlasNode::setOpacityModifyRGB(bool value) { - Color3B oldColor = this->getColor(); + Color32 oldColor = this->getColor(); _isOpacityModifyRGB = value; this->setColor(oldColor); } diff --git a/core/2d/AtlasNode.h b/axmol/2d/AtlasNode.h similarity index 83% rename from core/2d/AtlasNode.h rename to axmol/2d/AtlasNode.h index eb0da4ab0d44..fdf07d125ff7 100644 --- a/core/2d/AtlasNode.h +++ b/axmol/2d/AtlasNode.h @@ -4,6 +4,7 @@ Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2011 Zynga Inc. Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -27,10 +28,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "base/Protocols.h" -#include "base/Types.h" -#include "renderer/QuadCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Protocols.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/QuadCommand.h" namespace ax { @@ -66,14 +67,14 @@ class AX_DLL AtlasNode : public Node, public TextureProtocol virtual void updateAtlasValues(); // Overrides - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; - virtual bool isOpacityModifyRGB() const override; - virtual void setOpacityModifyRGB(bool isOpacityModifyRGB) override; - virtual const Color3B& getColor() const override; - virtual void setColor(const Color3B& color) override; - virtual void setOpacity(uint8_t opacity) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; + bool isOpacityModifyRGB() const override; + void setOpacityModifyRGB(bool isOpacityModifyRGB) override; + const Color32& getColor() const override; + void setColor(const Color32& color) override; + void setOpacity(uint8_t opacity) override; /** * @code @@ -82,11 +83,11 @@ class AX_DLL AtlasNode : public Node, public TextureProtocol * @endcode * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; /** Set an buffer manager of the texture vertex. */ void setTextureAtlas(TextureAtlas* textureAtlas); @@ -100,7 +101,7 @@ class AX_DLL AtlasNode : public Node, public TextureProtocol void setQuadsToDraw(ssize_t quadsToDraw); size_t getQuadsToDraw() const; - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; AtlasNode() = default; virtual ~AtlasNode(); @@ -131,7 +132,7 @@ class AX_DLL AtlasNode : public Node, public TextureProtocol /** Height of each char. */ int _itemHeight = 0; - Color3B _colorUnmodified; + Color32 _colorUnmodified; TextureAtlas* _textureAtlas = nullptr; /** Protocol variables. */ @@ -145,7 +146,7 @@ class AX_DLL AtlasNode : public Node, public TextureProtocol bool _ignoreContentScaleFactor = false; QuadCommand _quadCommand; - backend::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _mvpMatrixLocation; private: AX_DISALLOW_COPY_AND_ASSIGN(AtlasNode); diff --git a/core/2d/AutoPolygon.cpp b/axmol/2d/AutoPolygon.cpp similarity index 94% rename from core/2d/AutoPolygon.cpp rename to axmol/2d/AutoPolygon.cpp index a77ae4a20ca3..2b41ce35f2a1 100644 --- a/core/2d/AutoPolygon.cpp +++ b/axmol/2d/AutoPolygon.cpp @@ -27,11 +27,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/AutoPolygon.h" +#include "axmol/2d/AutoPolygon.h" #include "poly2tri/poly2tri.h" -#include "base/Director.h" -#include "base/axstd.h" -#include "renderer/TextureCache.h" +#include "axmol/base/Director.h" +#include "axmol/base/axstd.h" +#include "axmol/renderer/TextureCache.h" #include "clipper2/clipper.h" #include #include @@ -63,7 +63,7 @@ PolygonInfo::PolygonInfo(const PolygonInfo& other) : triangles(), _isVertsOwner( _filename = other._filename; _isVertsOwner = true; _rect = other._rect; - triangles.verts = new V3F_C4B_T2F[other.triangles.vertCount]; + triangles.verts = new V3F_T2F_C4B[other.triangles.vertCount]; triangles.indices = new unsigned short[other.triangles.indexCount]; AXASSERT(triangles.verts && triangles.indices, "not enough memory"); triangles.vertCount = other.triangles.vertCount; @@ -80,7 +80,7 @@ PolygonInfo& PolygonInfo::operator=(const PolygonInfo& other) _filename = other._filename; _isVertsOwner = true; _rect = other._rect; - triangles.verts = new V3F_C4B_T2F[other.triangles.vertCount]; + triangles.verts = new V3F_T2F_C4B[other.triangles.vertCount]; triangles.indices = new unsigned short[other.triangles.indexCount]; AXASSERT(triangles.verts && triangles.indices, "not enough memory"); triangles.vertCount = other.triangles.vertCount; @@ -97,17 +97,17 @@ PolygonInfo::~PolygonInfo() releaseVertsAndIndices(); } -void PolygonInfo::setQuad(V3F_C4B_T2F_Quad* quad) +void PolygonInfo::setQuad(V3F_T2F_C4B_Quad* quad) { releaseVertsAndIndices(); _isVertsOwner = false; triangles.indices = quadIndices9; triangles.vertCount = 4; triangles.indexCount = 6; - triangles.verts = (V3F_C4B_T2F*)quad; + triangles.verts = (V3F_T2F_C4B*)quad; } -void PolygonInfo::setQuads(V3F_C4B_T2F_Quad* quad, int numberOfQuads) +void PolygonInfo::setQuads(V3F_T2F_C4B_Quad* quad, int numberOfQuads) { AXASSERT(numberOfQuads >= 1 && numberOfQuads <= 9, "Invalid number of Quads"); @@ -116,7 +116,7 @@ void PolygonInfo::setQuads(V3F_C4B_T2F_Quad* quad, int numberOfQuads) triangles.indices = quadIndices9; triangles.vertCount = 4 * numberOfQuads; triangles.indexCount = 6 * numberOfQuads; - triangles.verts = (V3F_C4B_T2F*)quad; + triangles.verts = (V3F_T2F_C4B*)quad; } void PolygonInfo::setTriangles(const TrianglesCommand::Triangles& other) @@ -159,13 +159,13 @@ unsigned int PolygonInfo::getTrianglesCount() const float PolygonInfo::getArea() const { float area = 0; - V3F_C4B_T2F* verts = triangles.verts; + V3F_T2F_C4B* verts = triangles.verts; unsigned short* indices = triangles.indices; for (unsigned int i = 0; i < triangles.indexCount; i += 3) { - auto A = verts[indices[i]].vertices; - auto B = verts[indices[i + 1]].vertices; - auto C = verts[indices[i + 2]].vertices; + auto A = verts[indices[i]].position; + auto B = verts[indices[i + 1]].position; + auto C = verts[indices[i + 2]].position; area += (A.x * (B.y - C.y) + B.x * (C.y - A.y) + C.x * (A.y - B.y)) / 2; } return area; @@ -177,7 +177,7 @@ AutoPolygon::AutoPolygon(std::string_view filename) _filename = filename; _image = new Image(); _image->initWithImageFile(filename); - AXASSERT(_image->getPixelFormat() == backend::PixelFormat::RGBA8, + AXASSERT(_image->getPixelFormat() == rhi::PixelFormat::RGBA8, "unsupported format, currently only supports rgba8888"); _data = _image->getData(); _width = _image->getWidth(); @@ -610,7 +610,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po std::vector tris = cdt.GetTriangles(); axstd::pod_vector indices(tris.size() * 3); - axstd::pod_vector verts; + axstd::pod_vector verts; verts.reserve(indices.size() / 2); // we won't know the size of verts until we process all of the triangles! unsigned short idx = 0; @@ -627,7 +627,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po auto length = vdx; for (j = 0; j < length; j++) { - if (verts[j].vertices == v3) + if (verts[j].position == v3) { found = true; break; @@ -640,10 +640,8 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po } else { - // vert does not exist yet, so we need to create a new one, - auto c4b = Color4B::WHITE; - auto t2f = Tex2F(0, 0); // don't worry about tex coords now, we calculate that later - verts.push_back(V3F_C4B_T2F{v3, c4b, t2f}); + // vert does not exist yet, so we need to create a new one + verts.emplace_back(v3, Vec2::ZERO, Color32::WHITE); indices[idx++] = vdx++;; } } @@ -656,7 +654,7 @@ TrianglesCommand::Triangles AutoPolygon::triangulate(const std::vector& po return triangles; } -void AutoPolygon::calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count) +void AutoPolygon::calculateUV(const Rect& rect, V3F_T2F_C4B* verts, ssize_t count) { /* whole texture UV coordination @@ -683,10 +681,10 @@ void AutoPolygon::calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t coun for (auto i = verts; i != end; ++i) { // for every point, offset with the center point - float u = (i->vertices.x * _scaleFactor + rect.origin.x) / texWidth; - float v = (rect.origin.y + rect.size.height - i->vertices.y * _scaleFactor) / texHeight; - i->texCoords.u = u; - i->texCoords.v = v; + float u = (i->position.x * _scaleFactor + rect.origin.x) / texWidth; + float v = (rect.origin.y + rect.size.height - i->position.y * _scaleFactor) / texHeight; + i->texCoord.u = u; + i->texCoord.v = v; } } diff --git a/core/2d/AutoPolygon.h b/axmol/2d/AutoPolygon.h similarity index 96% rename from core/2d/AutoPolygon.h rename to axmol/2d/AutoPolygon.h index bae39824afa2..69470ab5586a 100644 --- a/core/2d/AutoPolygon.h +++ b/axmol/2d/AutoPolygon.h @@ -32,8 +32,8 @@ THE SOFTWARE. #include #include -#include "platform/Image.h" -#include "renderer/TrianglesCommand.h" +#include "axmol/platform/Image.h" +#include "axmol/renderer/TrianglesCommand.h" namespace ax { @@ -79,17 +79,17 @@ class AX_DLL PolygonInfo * set the data to be a pointer to a quad * the member verts will not be released when this PolygonInfo destructs * as the verts memory are managed by other objects - * @param quad a pointer to the V3F_C4B_T2F_Quad object + * @param quad a pointer to the V3F_T2F_C4B_Quad object */ - void setQuad(V3F_C4B_T2F_Quad* quad); + void setQuad(V3F_T2F_C4B_Quad* quad); /** * set the data to be a pointer to a number of Quads * the member verts will not be released when this PolygonInfo destructs * as the verts memory are managed by other objects - * @param quad a pointer to the V3F_C4B_T2F_Quad quads + * @param quad a pointer to the V3F_T2F_C4B_Quad quads */ - void setQuads(V3F_C4B_T2F_Quad* quads, int numberOfQuads); + void setQuads(V3F_T2F_C4B_Quad* quads, int numberOfQuads); /** * set the data to be a pointer to a triangles @@ -224,7 +224,7 @@ class AX_DLL AutoPolygon * ap.calculateUV(rect, myPolygons.verts, 20); * @endcode */ - void calculateUV(const Rect& rect, V3F_C4B_T2F* verts, ssize_t count); + void calculateUV(const Rect& rect, V3F_T2F_C4B* verts, ssize_t count); /** * a helper function, packing trace, reduce, expand, triangulate and calculate uv in one function diff --git a/core/2d/CMakeLists.txt b/axmol/2d/CMakeLists.txt similarity index 100% rename from core/2d/CMakeLists.txt rename to axmol/2d/CMakeLists.txt diff --git a/core/2d/Camera.cpp b/axmol/2d/Camera.cpp similarity index 98% rename from core/2d/Camera.cpp rename to axmol/2d/Camera.cpp index 8f6b58113c33..d359ea516ef7 100644 --- a/core/2d/Camera.cpp +++ b/axmol/2d/Camera.cpp @@ -26,12 +26,12 @@ Code based GamePlay3D's Camera: http://gameplay3d.org ****************************************************************************/ -#include "2d/Camera.h" -#include "2d/CameraBackgroundBrush.h" -#include "platform/RenderView.h" -#include "2d/Scene.h" -#include "renderer/Renderer.h" -#include "renderer/QuadCommand.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/CameraBackgroundBrush.h" +#include "axmol/platform/RenderView.h" +#include "axmol/2d/Scene.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/QuadCommand.h" namespace ax { diff --git a/core/2d/Camera.h b/axmol/2d/Camera.h similarity index 97% rename from core/2d/Camera.h rename to axmol/2d/Camera.h index 14c2b214cf92..f8a1ab944f02 100644 --- a/core/2d/Camera.h +++ b/axmol/2d/Camera.h @@ -28,13 +28,13 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" +#include "axmol/2d/Node.h" #if defined(AX_ENABLE_3D) -#include "3d/Frustum.h" +#include "axmol/3d/Frustum.h" #endif -#include "renderer/QuadCommand.h" -#include "renderer/CustomCommand.h" -#include "base/Director.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/base/Director.h" namespace ax { @@ -286,8 +286,8 @@ class AX_DLL Camera : public Node void applyZoom(); // override - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** Before rendering the scene with this camera, the background needs to be cleared. @@ -317,7 +317,7 @@ class AX_DLL Camera : public Node */ CameraBackgroundBrush* getBackgroundBrush() const { return _clearBrush; } - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; bool isBrushValid(); diff --git a/core/2d/CameraBackgroundBrush.cpp b/axmol/2d/CameraBackgroundBrush.cpp similarity index 82% rename from core/2d/CameraBackgroundBrush.cpp rename to axmol/2d/CameraBackgroundBrush.cpp index f69e652ed240..45a8a24a9cf8 100644 --- a/core/2d/CameraBackgroundBrush.cpp +++ b/axmol/2d/CameraBackgroundBrush.cpp @@ -23,24 +23,24 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/CameraBackgroundBrush.h" +#include "axmol/2d/CameraBackgroundBrush.h" #include // offsetof -#include "base/Types.h" -#include "2d/Camera.h" -#include "base/Macros.h" -#include "base/Utils.h" -#include "base/Configuration.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "renderer/RenderState.h" -#include "renderer/TextureCube.h" -#include "renderer/Shaders.h" +#include "axmol/base/Types.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Utils.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/TextureCube.h" +#include "axmol/renderer/Shaders.h" #if AX_ENABLE_CACHE_TEXTURE_DATA -# include "base/EventCustom.h" -# include "base/EventListenerCustom.h" -# include "base/EventType.h" -# include "base/EventDispatcher.h" +# include "axmol/base/EventCustom.h" +# include "axmol/base/EventListenerCustom.h" +# include "axmol/base/EventType.h" +# include "axmol/base/EventDispatcher.h" #endif namespace ax @@ -62,7 +62,7 @@ CameraBackgroundBrush* CameraBackgroundBrush::createNoneBrush() return ret; } -CameraBackgroundColorBrush* CameraBackgroundBrush::createColorBrush(const Color4F& color, float depth) +CameraBackgroundColorBrush* CameraBackgroundBrush::createColorBrush(const Color& color, float depth) { return CameraBackgroundColorBrush::create(color, depth); } @@ -124,26 +124,26 @@ CameraBackgroundDepthBrush* CameraBackgroundDepthBrush::create(float depth) bool CameraBackgroundDepthBrush::init() { AX_SAFE_RELEASE_NULL(_programState); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::CAMERA_CLEAR); - _programState = new backend::ProgramState(program); + auto* program = ProgramManager::getInstance()->getBuiltinProgram(rhi::ProgramType::CAMERA_CLEAR); + _programState = new rhi::ProgramState(program); _locDepth = _programState->getUniformLocation("dpeth"); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; _vertices.resize(4); - _vertices[0].vertices = Vec3(-1, -1, 0); - _vertices[1].vertices = Vec3(1, -1, 0); - _vertices[2].vertices = Vec3(1, 1, 0); - _vertices[3].vertices = Vec3(-1, 1, 0); + _vertices[0].position = Vec3(-1, -1, 0); + _vertices[1].position = Vec3(1, -1, 0); + _vertices[2].position = Vec3(1, 1, 0); + _vertices[3].position = Vec3(-1, 1, 0); - _vertices[0].colors = _vertices[1].colors = _vertices[2].colors = _vertices[3].colors = Color4B(0, 0, 0, 1); + _vertices[0].color = _vertices[1].color = _vertices[2].color = _vertices[3].color = Color32::BLACK; - _vertices[0].texCoords = Tex2F(0, 0); - _vertices[1].texCoords = Tex2F(1, 0); - _vertices[2].texCoords = Tex2F(1, 1); - _vertices[3].texCoords = Tex2F(0, 1); + _vertices[0].texCoord = Tex2F(0, 0); + _vertices[1].texCoord = Tex2F(1, 0); + _vertices[2].texCoord = Tex2F(1, 1); + _vertices[3].texCoord = Tex2F(0, 1); _customCommand.setBeforeCallback(AX_CALLBACK_0(CameraBackgroundDepthBrush::onBeforeDraw, this)); _customCommand.setAfterCallback(AX_CALLBACK_0(CameraBackgroundDepthBrush::onAfterDraw, this)); @@ -174,9 +174,9 @@ void CameraBackgroundDepthBrush::drawBackground(Camera* /*camera*/) renderer->addCommand(groupCommand); renderer->pushGroup(groupCommand->getRenderQueueID()); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - auto& blend = pipelineDescriptor.blendDescriptor; - blend.writeMask = _clearColor ? backend::ColorWriteMask::ALL : backend::ColorWriteMask::NONE; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + auto& blend = pipelineDesc.blendDesc; + blend.writeMask = _clearColor ? rhi::ColorWriteMask::ALL : rhi::ColorWriteMask::NONE; // draw _programState->setUniform(_locDepth, &_depth, sizeof(_depth)); @@ -191,11 +191,11 @@ void CameraBackgroundDepthBrush::onBeforeDraw() auto* renderer = Director::getInstance()->getRenderer(); _stateBlock.stencilWriteMask = renderer->getStencilWriteMask(); _stateBlock.depthTest = renderer->getDepthTest(); - _stateBlock.compareFunc = renderer->getDepthCompareFunction(); + _stateBlock.compareFunc = renderer->getDepthCompareFunc(); renderer->setStencilWriteMask(0); renderer->setDepthTest(true); - renderer->setDepthCompareFunction(backend::CompareFunction::ALWAYS); + renderer->setDepthCompareFunc(rhi::CompareFunc::ALWAYS); } void CameraBackgroundDepthBrush::onAfterDraw() @@ -203,7 +203,7 @@ void CameraBackgroundDepthBrush::onAfterDraw() auto* renderer = Director::getInstance()->getRenderer(); renderer->setStencilWriteMask(_stateBlock.stencilWriteMask); renderer->setDepthTest(_stateBlock.depthTest); - renderer->setDepthCompareFunction(_stateBlock.compareFunc); + renderer->setDepthCompareFunc(_stateBlock.compareFunc); } ////////////////////////////////////////////////////////////////////////////////////////// @@ -223,7 +223,7 @@ void CameraBackgroundColorBrush::drawBackground(Camera* camera) { BlendFunc op = {BlendFunc::ALPHA_NON_PREMULTIPLIED.src, BlendFunc::ALPHA_NON_PREMULTIPLIED.dst}; - auto& blend = _customCommand.getPipelineDescriptor().blendDescriptor; + auto& blend = _customCommand.getPipelineDesc().blendDesc; blend.sourceRGBBlendFactor = blend.sourceAlphaBlendFactor = op.src; blend.destinationRGBBlendFactor = blend.destinationAlphaBlendFactor = op.dst; blend.blendEnabled = true; @@ -231,16 +231,17 @@ void CameraBackgroundColorBrush::drawBackground(Camera* camera) CameraBackgroundDepthBrush::drawBackground(camera); } -void CameraBackgroundColorBrush::setColor(const Color4F& color) +void CameraBackgroundColorBrush::setColor(const Color& color) { + ax::Color32 tmp{color}; for (auto&& vert : _vertices) { - vert.colors = Color4B(color); + vert.color.value = tmp.value; } _customCommand.updateVertexBuffer(_vertices.data(), sizeof(_vertices[0]) * _vertices.size()); } -CameraBackgroundColorBrush* CameraBackgroundColorBrush::create(const Color4F& color, float depth) +CameraBackgroundColorBrush* CameraBackgroundColorBrush::create(const Color& color, float depth) { auto ret = new CameraBackgroundColorBrush(); @@ -296,11 +297,7 @@ CameraBackgroundSkyBoxBrush* CameraBackgroundSkyBoxBrush::create(std::string_vie if (texture != nullptr) { - Texture2D::TexParams tRepeatParams; - tRepeatParams.magFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.minFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - tRepeatParams.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + Texture2D::TexParams tRepeatParams{}; texture->setTexParameters(tRepeatParams); ret = new CameraBackgroundSkyBoxBrush; @@ -349,8 +346,8 @@ void CameraBackgroundSkyBoxBrush::drawBackground(Camera* camera) Mat4 cameraModelMat = camera->getNodeToWorldTransform(); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - pipelineDescriptor.blendDescriptor.blendEnabled = false; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + pipelineDesc.blendDesc.blendEnabled = false; Vec4 color(1.f, 1.f, 1.f, 1.f); cameraModelMat.m[12] = cameraModelMat.m[13] = cameraModelMat.m[14] = 0; @@ -376,16 +373,16 @@ bool CameraBackgroundSkyBoxBrush::init() _customCommand.setAfterCallback(AX_CALLBACK_0(CameraBackgroundSkyBoxBrush::onAfterDraw, this)); AX_SAFE_RELEASE_NULL(_programState); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::SKYBOX_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::SKYBOX_3D); + _programState = new rhi::ProgramState(program); _uniformColorLoc = _programState->getUniformLocation("u_color"); _uniformCameraRotLoc = _programState->getUniformLocation("u_cameraRot"); _uniformEnvLoc = _programState->getUniformLocation("u_Env"); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; // disable blend - pipelineDescriptor.blendDescriptor.blendEnabled = false; + pipelineDesc.blendDesc.blendEnabled = false; initBuffer(); @@ -448,7 +445,7 @@ void CameraBackgroundSkyBoxBrush::onBeforeDraw() auto* renderer = Director::getInstance()->getRenderer(); _stateBlock.depthTest = renderer->getDepthTest(); _stateBlock.depthWrite = renderer->getDepthWrite(); - _stateBlock.depthFunc = renderer->getDepthCompareFunction(); + _stateBlock.depthFunc = renderer->getDepthCompareFunc(); _stateBlock.cullMode = renderer->getCullMode(); } @@ -457,7 +454,7 @@ void CameraBackgroundSkyBoxBrush::onAfterDraw() auto* renderer = Director::getInstance()->getRenderer(); renderer->setDepthTest(_stateBlock.depthTest); renderer->setDepthWrite(_stateBlock.depthWrite); - renderer->setDepthCompareFunction(_stateBlock.depthFunc); + renderer->setDepthCompareFunc(_stateBlock.depthFunc); renderer->setCullMode(_stateBlock.cullMode); } diff --git a/core/2d/CameraBackgroundBrush.h b/axmol/2d/CameraBackgroundBrush.h similarity index 84% rename from core/2d/CameraBackgroundBrush.h rename to axmol/2d/CameraBackgroundBrush.h index 3e5c4bd462f5..cda6e1edbbbf 100644 --- a/core/2d/CameraBackgroundBrush.h +++ b/axmol/2d/CameraBackgroundBrush.h @@ -1,6 +1,7 @@ /**************************************************************************** Copyright (c) 2015-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,14 +26,14 @@ ****************************************************************************/ #pragma once -#include "base/Types.h" -#include "base/Object.h" -#include "base/EventListenerCustom.h" -#include "3d/Frustum.h" -#include "renderer/QuadCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/backend/Types.h" +#include "axmol/base/Types.h" +#include "axmol/base/Object.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/3d/Frustum.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/GroupCommand.h" + #include namespace ax @@ -43,11 +44,11 @@ class CameraBackgroundDepthBrush; class CameraBackgroundSkyBoxBrush; class Camera; -namespace backend +namespace rhi { class ProgramState; class Buffer; -} // namespace backend +} // namespace rhi /** * Defines a brush to clear the background of camera. @@ -95,7 +96,7 @@ class AX_DLL CameraBackgroundBrush : public Object * @param depth Depth used to clear depth buffer * @return Created brush */ - static CameraBackgroundColorBrush* createColorBrush(const Color4F& color, float depth); + static CameraBackgroundColorBrush* createColorBrush(const Color& color, float depth); /** Creates a Skybox brush with 6 textures. @param positive_x texture for the right side of the texture cube face. @@ -125,7 +126,7 @@ class AX_DLL CameraBackgroundBrush : public Object virtual bool init() { return true; } protected: - backend::ProgramState* _programState = nullptr; + rhi::ProgramState* _programState = nullptr; }; /** @@ -145,12 +146,12 @@ class AX_DLL CameraBackgroundDepthBrush : public CameraBackgroundBrush * Get brush type. Should be BrushType::DEPTH * @return brush type */ - virtual BrushType getBrushType() const override { return BrushType::DEPTH; } + BrushType getBrushType() const override { return BrushType::DEPTH; } /** * Draw background */ - virtual void drawBackground(Camera* camera) override; + void drawBackground(Camera* camera) override; /** * Set depth @@ -161,7 +162,7 @@ class AX_DLL CameraBackgroundDepthBrush : public CameraBackgroundBrush CameraBackgroundDepthBrush(); virtual ~CameraBackgroundDepthBrush(); - virtual bool init() override; + bool init() override; private: void onBeforeDraw(); @@ -175,16 +176,16 @@ class AX_DLL CameraBackgroundDepthBrush : public CameraBackgroundBrush protected: float _depth; - backend::UniformLocation _locDepth; + rhi::UniformLocation _locDepth; CustomCommand _customCommand; bool _clearColor; - std::vector _vertices; + std::vector _vertices; struct { uint32_t stencilWriteMask = 0; bool depthTest = true; - backend::CompareFunction compareFunc = backend::CompareFunction::ALWAYS; + rhi::CompareFunc compareFunc = rhi::CompareFunc::ALWAYS; } _stateBlock; }; @@ -198,7 +199,7 @@ class AX_DLL CameraBackgroundColorBrush : public CameraBackgroundDepthBrush * Get brush type. Should be BrushType::COLOR * @return brush type */ - virtual BrushType getBrushType() const override { return BrushType::COLOR; } + BrushType getBrushType() const override { return BrushType::COLOR; } /** * Create a color brush @@ -206,26 +207,26 @@ class AX_DLL CameraBackgroundColorBrush : public CameraBackgroundDepthBrush * @param depth Depth used to clear the depth buffer * @return Created brush */ - static CameraBackgroundColorBrush* create(const Color4F& color, float depth); + static CameraBackgroundColorBrush* create(const Color& color, float depth); /** * Draw background */ - virtual void drawBackground(Camera* camera) override; + void drawBackground(Camera* camera) override; /** * Set clear color * @param color Color used to clear the color buffer */ - void setColor(const Color4F& color); + void setColor(const Color& color); CameraBackgroundColorBrush(); virtual ~CameraBackgroundColorBrush(); - virtual bool init() override; + bool init() override; protected: - Color4F _color; + Color _color; }; class TextureCube; @@ -242,7 +243,7 @@ class AX_DLL CameraBackgroundSkyBoxBrush : public CameraBackgroundBrush * Get brush type. Should be BrushType::SKYBOX * @return brush type */ - virtual BrushType getBrushType() const override { return BrushType::SKYBOX; } + BrushType getBrushType() const override { return BrushType::SKYBOX; } /** Creates a Skybox brush with 6 textures. @param positive_x texture for the right side of the texture cube face. @@ -274,12 +275,12 @@ class AX_DLL CameraBackgroundSkyBoxBrush : public CameraBackgroundBrush /** * Draw background */ - virtual void drawBackground(Camera* camera) override; + void drawBackground(Camera* camera) override; bool isActived() const; void setActived(bool actived); virtual void setTextureValid(bool valid); - virtual bool isValid() override; + bool isValid() override; CameraBackgroundSkyBoxBrush(); virtual ~CameraBackgroundSkyBoxBrush(); @@ -287,7 +288,7 @@ class AX_DLL CameraBackgroundSkyBoxBrush : public CameraBackgroundBrush /** * init Skybox. */ - virtual bool init() override; + bool init() override; private: void onBeforeDraw(); @@ -308,16 +309,16 @@ class AX_DLL CameraBackgroundSkyBoxBrush : public CameraBackgroundBrush CustomCommand _customCommand; - backend::UniformLocation _uniformColorLoc; - backend::UniformLocation _uniformCameraRotLoc; - backend::UniformLocation _uniformEnvLoc; + rhi::UniformLocation _uniformColorLoc; + rhi::UniformLocation _uniformCameraRotLoc; + rhi::UniformLocation _uniformEnvLoc; struct { bool depthTest = true; bool depthWrite = true; - backend::CompareFunction depthFunc = backend::CompareFunction::ALWAYS; - backend::CullMode cullMode = backend::CullMode::BACK; + rhi::CompareFunc depthFunc = rhi::CompareFunc::ALWAYS; + rhi::CullMode cullMode = rhi::CullMode::BACK; } _stateBlock; }; diff --git a/core/2d/ClippingNode.cpp b/axmol/2d/ClippingNode.cpp similarity index 95% rename from core/2d/ClippingNode.cpp rename to axmol/2d/ClippingNode.cpp index 86fab916105b..22870e071c82 100644 --- a/core/2d/ClippingNode.cpp +++ b/axmol/2d/ClippingNode.cpp @@ -26,12 +26,12 @@ * THE SOFTWARE. * */ -#include "2d/ClippingNode.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "base/Director.h" -#include "base/StencilStateManager.h" +#include "axmol/2d/ClippingNode.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/base/Director.h" +#include "axmol/base/StencilStateManager.h" namespace ax { @@ -166,8 +166,8 @@ void ClippingNode::visit(Renderer* renderer, const Mat4& parentTransform, uint32 auto alphaThreshold = this->getAlphaThreshold(); if (alphaThreshold < 1) { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); - auto programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); + auto programState = new rhi::ProgramState(program); auto alphaLocation = programState->getUniformLocation("u_alpha_value"); programState->setUniform(alphaLocation, &alphaThreshold, sizeof(alphaThreshold)); setProgramStateRecursively(_stencil, programState); @@ -349,7 +349,7 @@ void ClippingNode::setInverted(bool inverted) _stencilStateManager->setInverted(inverted); } -void ClippingNode::setProgramStateRecursively(Node* node, backend::ProgramState* programState) +void ClippingNode::setProgramStateRecursively(Node* node, rhi::ProgramState* programState) { if (_originalStencilProgramState.find(node) == _originalStencilProgramState.end()) { diff --git a/core/2d/ClippingNode.h b/axmol/2d/ClippingNode.h similarity index 87% rename from core/2d/ClippingNode.h rename to axmol/2d/ClippingNode.h index b59df48eb72b..d219c810db75 100644 --- a/core/2d/ClippingNode.h +++ b/axmol/2d/ClippingNode.h @@ -28,10 +28,10 @@ */ #pragma once -#include "2d/Node.h" -#include "renderer/GroupCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" #include namespace ax { @@ -122,24 +122,24 @@ class AX_DLL ClippingNode : public Node /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onEnterTransitionDidFinish() override; + void onEnterTransitionDidFinish() override; /** * @lua NA */ - virtual void onExitTransitionDidStart() override; + void onExitTransitionDidStart() override; /** * @lua NA */ - virtual void onExit() override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void onExit() override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void setGlobalZOrder(float globalZOrder) override; + void setGlobalZOrder(float globalZOrder) override; - virtual void setCameraMask(unsigned short mask, bool applyChildren = true) override; + void setCameraMask(unsigned short mask, bool applyChildren = true) override; ClippingNode(); @@ -150,7 +150,7 @@ class AX_DLL ClippingNode : public Node /** Initializes a clipping node without a stencil. */ - virtual bool init() override; + bool init() override; /** Initializes a clipping node with an other node as its stencil. The stencil node will be retained, and its parent will be set to this clipping node. @@ -158,7 +158,7 @@ class AX_DLL ClippingNode : public Node virtual bool init(Node* stencil); protected: - void setProgramStateRecursively(Node* node, backend::ProgramState* programState); + void setProgramStateRecursively(Node* node, rhi::ProgramState* programState); void restoreAllProgramStates(); bool _uniqueChildStencils = false; @@ -167,7 +167,7 @@ class AX_DLL ClippingNode : public Node //CallbackCommand _afterDrawStencilCmd; //CallbackCommand _afterVisitCmd; - std::unordered_map _originalStencilProgramState; + std::unordered_map _originalStencilProgramState; private: AX_DISALLOW_COPY_AND_ASSIGN(ClippingNode); diff --git a/core/2d/ClippingRectangleNode.cpp b/axmol/2d/ClippingRectangleNode.cpp similarity index 95% rename from core/2d/ClippingRectangleNode.cpp rename to axmol/2d/ClippingRectangleNode.cpp index a259d5de545c..5b0b3f285d23 100644 --- a/core/2d/ClippingRectangleNode.cpp +++ b/axmol/2d/ClippingRectangleNode.cpp @@ -21,11 +21,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ClippingRectangleNode.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "math/Vec2.h" -#include "platform/RenderView.h" +#include "axmol/2d/ClippingRectangleNode.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/math/Vec2.h" +#include "axmol/platform/RenderView.h" namespace ax { diff --git a/core/2d/ClippingRectangleNode.h b/axmol/2d/ClippingRectangleNode.h similarity index 95% rename from core/2d/ClippingRectangleNode.h rename to axmol/2d/ClippingRectangleNode.h index 945bb163f1cd..2384abc7a156 100644 --- a/core/2d/ClippingRectangleNode.h +++ b/axmol/2d/ClippingRectangleNode.h @@ -27,8 +27,8 @@ */ #pragma once -#include "2d/Node.h" -#include "renderer/CallbackCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/CallbackCommand.h" namespace ax { @@ -82,7 +82,7 @@ class AX_DLL ClippingRectangleNode : public Node void setClippingEnabled(bool enabled) { _clippingEnabled = enabled; } // virtual void draw(Renderer* renderer, const Mat4 &transform, uint32_t flags) override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; protected: ClippingRectangleNode() = default; diff --git a/core/2d/Component.cpp b/axmol/2d/Component.cpp similarity index 98% rename from core/2d/Component.cpp rename to axmol/2d/Component.cpp index ac0819938728..9e10a93083f1 100644 --- a/core/2d/Component.cpp +++ b/axmol/2d/Component.cpp @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Component.h" +#include "axmol/2d/Component.h" namespace ax { diff --git a/core/2d/Component.h b/axmol/2d/Component.h similarity index 97% rename from core/2d/Component.h rename to axmol/2d/Component.h index bc6e3c997f47..2604aa10f65f 100644 --- a/core/2d/Component.h +++ b/axmol/2d/Component.h @@ -27,8 +27,8 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW #include -#include "base/Object.h" -#include "base/ScriptSupport.h" +#include "axmol/base/Object.h" +#include "axmol/base/ScriptSupport.h" namespace ax { diff --git a/core/2d/ComponentContainer.cpp b/axmol/2d/ComponentContainer.cpp similarity index 97% rename from core/2d/ComponentContainer.cpp rename to axmol/2d/ComponentContainer.cpp index e6587a91d9bb..1b963827554b 100644 --- a/core/2d/ComponentContainer.cpp +++ b/axmol/2d/ComponentContainer.cpp @@ -23,9 +23,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ComponentContainer.h" -#include "2d/Component.h" -#include "2d/Node.h" +#include "axmol/2d/ComponentContainer.h" +#include "axmol/2d/Component.h" +#include "axmol/2d/Node.h" namespace ax { diff --git a/core/2d/ComponentContainer.h b/axmol/2d/ComponentContainer.h similarity index 98% rename from core/2d/ComponentContainer.h rename to axmol/2d/ComponentContainer.h index e4387cf501a9..0009d679174d 100644 --- a/core/2d/ComponentContainer.h +++ b/axmol/2d/ComponentContainer.h @@ -27,7 +27,7 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "base/Map.h" +#include "axmol/base/Map.h" #include namespace ax diff --git a/core/2d/DrawNode.cpp b/axmol/2d/DrawNode.cpp similarity index 80% rename from core/2d/DrawNode.cpp rename to axmol/2d/DrawNode.cpp index 36c1a78101a5..356b22d7db12 100644 --- a/core/2d/DrawNode.cpp +++ b/axmol/2d/DrawNode.cpp @@ -23,19 +23,19 @@ * SOFTWARE. */ -#include "2d/DrawNode.h" +#include "axmol/2d/DrawNode.h" #include -#include "base/Types.h" -#include "base/EventType.h" -#include "base/Configuration.h" -#include "renderer/Renderer.h" -#include "base/Director.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "2d/ActionCatmullRom.h" -#include "base/Utils.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Configuration.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/2d/ActionCatmullRom.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" #include "poly2tri/poly2tri.h" namespace ax @@ -72,7 +72,7 @@ static bool isConvex(const Vec2* verts, int count) return true; // is convex } -static V2F_C4B_T2F* expandBufferAndGetPointer(axstd::pod_vector& buffer, size_t count) +static V2F_T2F_C4F* expandBufferAndGetPointer(axstd::pod_vector& buffer, size_t count) { size_t oldSize = buffer.size(); buffer.expand(count); @@ -133,13 +133,13 @@ bool DrawNode::init() void DrawNode::updateShader() { - updateShaderInternal(_customCommandTriangle, backend::ProgramType::POSITION_COLOR_LENGTH_TEXTURE, + updateShaderInternal(_customCommandTriangle, rhi::ProgramType::POSITION_COLOR_LENGTH_TEXTURE, CustomCommand::DrawType::ARRAY, CustomCommand::PrimitiveType::TRIANGLE); - updateShaderInternal(_customCommandPoint, backend::ProgramType::POSITION_COLOR_TEXTURE_AS_POINTSIZE, + updateShaderInternal(_customCommandPoint, rhi::ProgramType::POSITION_COLOR_TEXTURE_AS_POINTSIZE, CustomCommand::DrawType::ARRAY, CustomCommand::PrimitiveType::POINT); - updateShaderInternal(_customCommandLine, backend::ProgramType::POSITION_COLOR_LENGTH_TEXTURE, + updateShaderInternal(_customCommandLine, rhi::ProgramType::POSITION_COLOR_LENGTH_TEXTURE, CustomCommand::DrawType::ARRAY, CustomCommand::PrimitiveType::LINE); } @@ -148,11 +148,11 @@ void DrawNode::updateShaderInternal(CustomCommand& cmd, CustomCommand::DrawType drawType, CustomCommand::PrimitiveType primitiveType) { - auto& pipelinePS = cmd.getPipelineDescriptor().programState; + auto& pipelinePS = cmd.getPipelineDesc().programState; AX_SAFE_RELEASE(pipelinePS); - auto program = backend::Program::getBuiltinProgram(programType); - pipelinePS = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(programType); + pipelinePS = new rhi::ProgramState(program); setVertexLayout(cmd); cmd.setPrimitiveType(primitiveType); cmd.setDrawType(drawType); @@ -160,49 +160,50 @@ void DrawNode::updateShaderInternal(CustomCommand& cmd, void DrawNode::setVertexLayout(CustomCommand& cmd) { - auto* programState = cmd.getPipelineDescriptor().programState; - programState->validateSharedVertexLayout(backend::VertexLayoutType::DrawNode); + auto* programState = cmd.getPipelineDesc().programState; + programState->validateSharedVertexLayout(rhi::VertexLayoutType::DrawNode); } void DrawNode::freeShaderInternal(CustomCommand& cmd) { - auto& pipelinePS = cmd.getPipelineDescriptor().programState; + auto& pipelinePS = cmd.getPipelineDesc().programState; AX_SAFE_RELEASE_NULL(pipelinePS); } void DrawNode::updateBlendState(CustomCommand& cmd) { - backend::BlendDescriptor& blendDescriptor = cmd.getPipelineDescriptor().blendDescriptor; - blendDescriptor.blendEnabled = true; + rhi::BlendDesc& blendDesc = cmd.getPipelineDesc().blendDesc; + blendDesc.blendEnabled = true; if (_blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED) { - blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceRGBBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDesc.destinationRGBBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceAlphaBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDesc.destinationAlphaBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; setOpacityModifyRGB(false); } else { - blendDescriptor.sourceRGBBlendFactor = _blendFunc.src; - blendDescriptor.destinationRGBBlendFactor = _blendFunc.dst; - blendDescriptor.sourceAlphaBlendFactor = _blendFunc.src; - blendDescriptor.destinationAlphaBlendFactor = _blendFunc.dst; + blendDesc.sourceRGBBlendFactor = _blendFunc.src; + blendDesc.destinationRGBBlendFactor = _blendFunc.dst; + blendDesc.sourceAlphaBlendFactor = _blendFunc.src; + blendDesc.destinationAlphaBlendFactor = _blendFunc.dst; setOpacityModifyRGB(true); } } void DrawNode::updateUniforms(const Mat4& transform, CustomCommand& cmd) { - auto& pipelineDescriptor = cmd.getPipelineDescriptor(); + auto& pipelineDesc = cmd.getPipelineDesc(); const auto& matrixP = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); Mat4 matrixMVP = matrixP * transform; - auto mvpLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); - pipelineDescriptor.programState->setUniform(mvpLocation, matrixMVP.m, sizeof(matrixMVP.m)); + auto mvpLocation = pipelineDesc.programState->getUniformLocation("u_MVPMatrix"); + pipelineDesc.programState->setUniform(mvpLocation, matrixMVP.m, sizeof(matrixMVP.m)); - float alpha = _displayedOpacity / 255.0f; - auto alphaUniformLocation = pipelineDescriptor.programState->getUniformLocation("u_alpha"); - pipelineDescriptor.programState->setUniform(alphaUniformLocation, &alpha, sizeof(alpha)); + // FIXME: consider whether 'u_alpha' is a redundant uniform in shaders? + float alpha = _displayedColor.a / 255.0f; + auto alphaUniformLocation = pipelineDesc.programState->getUniformLocation("u_alpha"); + pipelineDesc.programState->setUniform(alphaUniformLocation, &alpha, sizeof(alpha)); } void DrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) @@ -235,7 +236,7 @@ void DrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) } } -static void udpateCommand(CustomCommand& cmd, const axstd::pod_vector& buffer) +static void udpateCommand(CustomCommand& cmd, const axstd::pod_vector& buffer) { if (buffer.empty()) { @@ -243,8 +244,9 @@ static void udpateCommand(CustomCommand& cmd, const axstd::pod_vector triangleList; + axstd::pod_vector triangleList; int vertex_count = 0; @@ -877,10 +879,10 @@ void DrawNode::_drawPolygon(const Vec2* verts, p2t::Point* vec2 = t->GetPoint(1); p2t::Point* vec3 = t->GetPoint(2); - V2F_C4B_T2F_Triangle triangle = { - {Vec2(vec1->x, vec1->y), fillColor, Vec2::ZERO}, - {Vec2(vec2->x, vec2->y), fillColor, Vec2::ZERO}, - {Vec2(vec3->x, vec3->y), fillColor, Vec2::ZERO}, + V2F_T2F_C4F_Triangle triangle = { + {Vec2(vec1->x, vec1->y), Vec2::ZERO, fillColor}, + {Vec2(vec2->x, vec2->y), Vec2::ZERO, fillColor}, + {Vec2(vec3->x, vec3->y), Vec2::ZERO, fillColor}, }; triangleList.emplace_back(triangle); // use it for drawing later } @@ -904,7 +906,7 @@ void DrawNode::_drawPolygon(const Vec2* verts, vertex_count *= 3; - auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); + auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); _trianglesDirty = true; // start drawing... @@ -921,9 +923,9 @@ void DrawNode::_drawPolygon(const Vec2* verts, for (unsigned int i = 0; i < count - 2; i++) { triangles[ii++] = { - {_vertices[0], fillColor, Vec2::ZERO}, - {_vertices[i + 1], fillColor, Vec2::ZERO}, - {_vertices[i + 2], fillColor, Vec2::ZERO}, + {_vertices[0], Vec2::ZERO, fillColor}, + {_vertices[i + 1], Vec2::ZERO, fillColor}, + {_vertices[i + 2], Vec2::ZERO, fillColor}, }; } } @@ -951,38 +953,38 @@ void DrawNode::_drawPolygon(const Vec2* verts, { triangles[ii++] = { - {v0, borderColor, -(n + t)}, - {v1, borderColor, n - t}, - {v2, borderColor, -n}, + {v0, -(n + t), borderColor}, + {v1, n - t, borderColor}, + {v2, -n, borderColor}, }; triangles[ii++] = { - {v3, borderColor, n}, - {v1, borderColor, n - t}, - {v2, borderColor, -n}, + {v3, n, borderColor}, + {v1, n - t, borderColor}, + {v2, -n, borderColor}, }; } triangles[ii++] = { - {v3, borderColor, n}, - {v4, borderColor, -n}, - {v2, borderColor, -n}, + {v3, n, borderColor}, + {v4, -n, borderColor}, + {v2, -n, borderColor}, }; triangles[ii++] = { - {v3, borderColor, n}, - {v4, borderColor, -n}, - {v5, borderColor, n}, + {v3, n, borderColor}, + {v4, -n, borderColor}, + {v5, n, borderColor}, }; { triangles[ii++] = { - {v6, borderColor, t - n}, - {v4, borderColor, -n}, - {v5, borderColor, n}, + {v6, t - n, borderColor}, + {v4, -n, borderColor}, + {v5, n, borderColor}, }; triangles[ii++] = { - {v6, borderColor, t - n}, - {v7, borderColor, t + n}, - {v5, borderColor, n}, + {v6, t - n, borderColor}, + {v7, t + n, borderColor}, + {v5, n, borderColor}, }; } } @@ -1025,9 +1027,9 @@ void DrawNode::_drawPolygon(const Vec2* verts, Vec2 outer0 = v0 + offset0 * width; Vec2 outer1 = v1 + offset1 * width; - triangles[ii++] = {{inner0, borderColor, -n0}, {inner1, borderColor, -n0}, {outer1, borderColor, n0}}; + triangles[ii++] = {{inner0, -n0, borderColor}, {inner1, -n0, borderColor}, {outer1, n0, borderColor}}; - triangles[ii++] = {{inner0, borderColor, -n0}, {outer0, borderColor, n0}, {outer1, borderColor, n0}}; + triangles[ii++] = {{inner0, -n0, borderColor}, {outer0, n0, borderColor}, {outer1, n0, borderColor}}; } } } @@ -1036,7 +1038,7 @@ void DrawNode::_drawPolygon(const Vec2* verts, void DrawNode::_drawPoly(const Vec2* verts, unsigned int count, bool closedPolygon, - const Color4B& color, + const Color& color, float thickness, bool isconvex) { @@ -1052,24 +1054,24 @@ void DrawNode::_drawPoly(const Vec2* verts, int ii = 0; for (unsigned int i = 0; i < count - 1; i++) { - line[ii++] = {_vertices[i], color, Vec2::ZERO}; - line[ii++] = {_vertices[i + 1], color, Vec2::ZERO}; + line[ii++] = {_vertices[i], Vec2::ZERO, color}; + line[ii++] = {_vertices[i + 1], Vec2::ZERO, color}; } if (closedPolygon) { - line[ii++] = {_vertices[count - 1], color, Vec2::ZERO}; + line[ii++] = {_vertices[count - 1], Vec2::ZERO, color}; line[ii++] = line[0]; } } else { - _drawPolygon(verts, count, Color4B::TRANSPARENT, color, closedPolygon, thickness, isconvex); + _drawPolygon(verts, count, Color::TRANSPARENT, color, closedPolygon, thickness, isconvex); } } void DrawNode::_drawSegment(const Vec2& from, const Vec2& to, - const Color4B& color, + const Color& color, float thickness, DrawNode::EndType etStart, DrawNode::EndType etEnd) @@ -1105,7 +1107,7 @@ void DrawNode::_drawSegment(const Vec2& from, unsigned int vertex_count = 3 * ((etStart != DrawNode::EndType::Butt) ? 2 : 0) + 3 * 2 + 3 * ((etEnd != DrawNode::EndType::Butt) ? 2 : 0); - auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); + auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); _trianglesDirty = true; int ii = 0; @@ -1116,29 +1118,29 @@ void DrawNode::_drawSegment(const Vec2& from, case DrawNode::EndType::Square: triangles[ii++] = { - {v0, color, Vec2::ZERO}, - {v1, color, -n}, - {v2, color, n}, + {v0, Vec2::ZERO, color}, + {v1, -n, color}, + {v2, n, color}, }; triangles[ii++] = { - {v3, color, n}, - {v1, color, Vec2::ZERO}, - {v2, color, -n}, + {v3, n, color}, + {v1, Vec2::ZERO, color}, + {v2, -n, color}, }; break; case DrawNode::EndType::Round: triangles[ii++] = { - {v0, color, -(n + t)}, - {v1, color, n - t}, - {v2, color, -n}, + {v0, -(n + t), color}, + {v1, n - t, color}, + {v2, -n, color}, }; triangles[ii++] = { - {v3, color, n}, - {v1, color, n - t}, - {v2, color, -n}, + {v3, n, color}, + {v1, n - t, color}, + {v2, -n, color}, }; break; @@ -1148,15 +1150,15 @@ void DrawNode::_drawSegment(const Vec2& from, // BODY triangles[ii++] = { - {v3, color, n}, - {v4, color, -n}, - {v2, color, -n}, + {v3, n, color}, + {v4, -n, color}, + {v2, -n, color}, }; triangles[ii++] = { - {v3, color, n}, - {v4, color, -n}, - {v5, color, n}, + {v3, n, color}, + {v4, -n, color}, + {v5, n, color}, }; switch (etStart) @@ -1166,29 +1168,29 @@ void DrawNode::_drawSegment(const Vec2& from, case DrawNode::EndType::Square: triangles[ii++] = { - {v6, color, Vec2::ZERO}, - {v4, color, -n}, - {v5, color, n}, + {v6, Vec2::ZERO, color}, + {v4, -n, color}, + {v5, n, color}, }; triangles[ii++] = { - {v6, color, -n}, - {v7, color, Vec2::ZERO}, - {v5, color, n}, + {v6, -n, color}, + {v7, Vec2::ZERO, color}, + {v5, n, color}, }; break; case DrawNode::EndType::Round: triangles[ii++] = { - {v6, color, t - n}, - {v4, color, -n}, - {v5, color, n}, + {v6, t - n, color}, + {v4, -n, color}, + {v5, n, color}, }; triangles[ii++] = { - {v6, color, t - n}, - {v7, color, t + n}, - {v5, color, n}, + {v6, t - n, color}, + {v7, t + n, color}, + {v5, n, color}, }; break; @@ -1198,29 +1200,28 @@ void DrawNode::_drawSegment(const Vec2& from, } } // Internal function _drawLine => thickness is always 1 (fastes way to draw a line) -void DrawNode::_drawLine(const Vec2& from, const Vec2& to, const Color4B& color) +void DrawNode::_drawLine(const Vec2& from, const Vec2& to, const Color& color) { Vec2 vertices[2] = {from, to}; applyTransform(vertices, vertices, 2); - - auto line = expandBufferAndGetPointer(_lines, 2); + auto line = expandBufferAndGetPointer(_lines, 2); _linesDirty = true; - line[0] = {vertices[0], color, Vec2::ZERO}; - line[1] = {vertices[1], color, Vec2::ZERO}; + line[0] = {vertices[0], Vec2::ZERO, color}; + line[1] = {vertices[1], Vec2::ZERO, color}; } -void DrawNode::_drawDot(const Vec2& pos, float radius, const Color4B& color) +void DrawNode::_drawDot(const Vec2& pos, float radius, const Color& color) { unsigned int vertex_count = 2 * 3; - auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); + auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); _trianglesDirty = true; - V2F_C4B_T2F a = {Vec2(pos.x - radius, pos.y - radius), color, Vec2(-1.0f, -1.0f)}; - V2F_C4B_T2F b = {Vec2(pos.x - radius, pos.y + radius), color, Vec2(-1.0f, 1.0f)}; - V2F_C4B_T2F c = {Vec2(pos.x + radius, pos.y + radius), color, Vec2(1.0f, 1.0f)}; - V2F_C4B_T2F d = {Vec2(pos.x + radius, pos.y - radius), color, Vec2(1.0f, -1.0f)}; + V2F_T2F_C4F a = {Vec2(pos.x - radius, pos.y - radius), Vec2(-1.0f, -1.0f), color}; + V2F_T2F_C4F b = {Vec2(pos.x - radius, pos.y + radius), Vec2(-1.0f, 1.0f), color}; + V2F_T2F_C4F c = {Vec2(pos.x + radius, pos.y + radius), Vec2(1.0f, 1.0f), color}; + V2F_T2F_C4F d = {Vec2(pos.x + radius, pos.y - radius), Vec2(1.0f, -1.0f), color}; triangles[0] = {a, b, c}; triangles[1] = {a, c, d}; @@ -1233,8 +1234,8 @@ void DrawNode::_drawCircle(const Vec2& center, bool drawLineToCenter, float scaleX, float scaleY, - const Color4B& borderColor, - const Color4B& fillColor, + const Color& borderColor, + const Color& fillColor, bool solid, float thickness) { @@ -1265,24 +1266,23 @@ void DrawNode::_drawCircle(const Vec2& center, } void DrawNode::_drawColoredTriangle(Vec2* vertices3, - const Color4B* color3) + const Color* color3) { unsigned int vertex_count = 3; applyTransform(vertices3, vertices3, vertex_count); - auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); + auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); _trianglesDirty = true; - triangles[0] = {{vertices3[0], color3[0], Vec2::ZERO}, - {vertices3[1], color3[1], Vec2::ZERO}, - {vertices3[2], color3[2], Vec2::ZERO}}; + triangles[0] = {{vertices3[0], Vec2::ZERO, color3[0]}, + {vertices3[1], Vec2::ZERO, color3[1]}, + {vertices3[2], Vec2::ZERO, color3[2]}}; } - void DrawNode::_drawTriangle(Vec2* vertices3, - const Color4B& borderColor, - const Color4B& fillColor, + const Color& borderColor, + const Color& fillColor, bool solid, float thickness) { @@ -1296,12 +1296,12 @@ void DrawNode::_drawTriangle(Vec2* vertices3, { applyTransform(vertices3, vertices3, vertex_count); - auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); + auto triangles = reinterpret_cast(expandBufferAndGetPointer(_triangles, vertex_count)); _trianglesDirty = true; - triangles[0] = {{vertices3[0], fillColor, Vec2::ZERO}, - {vertices3[1], fillColor, Vec2::ZERO}, - {vertices3[2], fillColor, Vec2::ZERO}}; + triangles[0] = {{vertices3[0], Vec2::ZERO, fillColor}, + {vertices3[1], Vec2::ZERO, fillColor}, + {vertices3[2], Vec2::ZERO, fillColor}}; } } @@ -1309,8 +1309,8 @@ void DrawNode::_drawAStar(const Vec2& center, float radiusI, // inner float radiusO, // outer unsigned int segments, - const Color4B& color, - const Color4B& filledColor, + const Color& color, + const Color& filledColor, float thickness, bool solid) { @@ -1341,7 +1341,7 @@ void DrawNode::_drawAStar(const Vec2& center, void DrawNode::_drawPoints(const Vec2* position, unsigned int numberOfPoints, const float pointSize, - const Color4B& color, + const Color& color, const DrawNode::PointType pointType) { if (properties.drawOrder == true) @@ -1354,7 +1354,7 @@ void DrawNode::_drawPoints(const Vec2* position, { case PointType::Circle: { - _drawCircle(position[i], pointSize4, 90, 32, false, 1.0f, 1.0f, Color4B(), color, true); + _drawCircle(position[i], pointSize4, 90, 32, false, 1.0f, 1.0f, Color(), color, true); break; } case PointType::Rect: @@ -1378,13 +1378,13 @@ void DrawNode::_drawPoints(const Vec2* position, for (unsigned int i = 0; i < numberOfPoints; i++) { - *(point + i) = {position[i], color, Vec2(pointSize, 0.0f)}; + *(point + i) = {position[i], Vec2(pointSize, 0.0f), color}; } } void DrawNode::_drawPoint(const Vec2& position, const float pointSize, - const Color4B& color, + const Color& color, const DrawNode::PointType pointType) { if (properties.drawOrder == true) @@ -1396,7 +1396,7 @@ void DrawNode::_drawPoint(const Vec2& position, { case PointType::Circle: { - _drawCircle(position, pointSize4, 90, 32, false, 1.0f, 1.0f, Color4B(), color, true); + _drawCircle(position, pointSize4, 90, 32, false, 1.0f, 1.0f, Color(), color, true); break; } case PointType::Rect: @@ -1428,7 +1428,7 @@ void DrawNode::_drawPoint(const Vec2& position, auto point = expandBufferAndGetPointer(_points, 1); _pointsDirty = true; - *point = {position, color, Vec2(pointSize, 0.0f)}; + *point = {position, Vec2(pointSize, 0.0f), color}; } } @@ -1439,8 +1439,8 @@ void DrawNode::_drawPie(const Vec2& center, int endAngle, float scaleX, float scaleY, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, DrawMode drawMode, float thickness) { @@ -1459,11 +1459,11 @@ void DrawNode::_drawPie(const Vec2& center, _drawCircle(center, radius, 0.0f, 360, false, scaleX, scaleY, borderColor, fillColor, true, thickness); break; case DrawMode::Outline: - _drawCircle(center, radius, 0.0f, 360, false, scaleX, scaleY, borderColor, Color4B::TRANSPARENT, true, + _drawCircle(center, radius, 0.0f, 360, false, scaleX, scaleY, borderColor, Color::TRANSPARENT, true, thickness); break; case DrawMode::Line: - _drawCircle(center, radius, 0.0f, 360, false, scaleX, scaleY, borderColor, Color4B::TRANSPARENT, true, + _drawCircle(center, radius, 0.0f, 360, false, scaleX, scaleY, borderColor, Color::TRANSPARENT, true, thickness); break; case DrawMode::Semi: @@ -1508,7 +1508,7 @@ void DrawNode::_drawPie(const Vec2& center, case DrawMode::Fill: _vertices[n++] = center; _vertices[n++] = _vertices[0]; - _drawPolygon(_vertices.data(), n, fillColor, Color4B::TRANSPARENT, true, 0, false); + _drawPolygon(_vertices.data(), n, fillColor, Color::TRANSPARENT, true, 0, false); _drawPoly(_vertices.data(), n, false, borderColor, thickness, true); break; case DrawMode::Outline: @@ -1520,7 +1520,7 @@ void DrawNode::_drawPie(const Vec2& center, _drawPoly(_vertices.data(), n, false, borderColor, thickness, true); break; case DrawMode::Semi: - if (fillColor != Color4B::TRANSPARENT) + if (fillColor != Color::TRANSPARENT) _drawPolygon(_vertices.data(), n, fillColor, borderColor, true, 0, false); _drawPoly(_vertices.data(), n, true, borderColor, thickness, true); break; @@ -1609,7 +1609,7 @@ void DrawNode::Properties::setDefaultValues() { auto fac = Director::getInstance()->getContentScaleFactor(); factor = fac; - + scale = Vec2(1.0f, 1.0f); center = Vec2(0.0f, 0.0f); rotation = 0.0f; diff --git a/core/2d/DrawNode.h b/axmol/2d/DrawNode.h similarity index 87% rename from core/2d/DrawNode.h rename to axmol/2d/DrawNode.h index 6dd5062712fc..f68513d0af1b 100644 --- a/core/2d/DrawNode.h +++ b/axmol/2d/DrawNode.h @@ -32,11 +32,11 @@ #pragma once -#include "2d/Node.h" -#include "base/axstd.h" -#include "base/Types.h" -#include "renderer/CustomCommand.h" -#include "math/Math.h" +#include "axmol/2d/Node.h" +#include "axmol/base/axstd.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/math/Math.h" namespace ax { @@ -99,7 +99,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawPoint(const Vec2& point, const float pointSize, - const Color4B& color, + const Color& color, DrawNode::PointType pointType = DrawNode::PointType::Rect); /** Draw a group point. @@ -110,7 +110,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawPoints(const Vec2* position, unsigned int numberOfPoints, - const Color4B& color, + const Color& color, DrawNode::PointType pointType = DrawNode::PointType::Rect); /** Draw a group point. @@ -123,7 +123,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void drawPoints(const Vec2* position, unsigned int numberOfPoints, const float pointSize, - const Color4B& color, + const Color& color, DrawNode::PointType pointType = DrawNode::PointType::Rect); /** Draw an line from origin to destination with color. @@ -134,7 +134,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawLine(const Vec2& origin, const Vec2& destination, - const Color4B& color, + const Color& color, float thickness = 1.0f, DrawNode::EndType etStart = DrawNode::EndType::Round, DrawNode::EndType etEnd = DrawNode::EndType::Round); @@ -146,7 +146,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol * @param destination The rectangle destination. * @param color The rectangle color. */ - void drawRect(const Vec2& origin, const Vec2& destination, const Color4B& color, float thickness = 1.0f); + void drawRect(const Vec2& origin, const Vec2& destination, const Color& color, float thickness = 1.0f); /** Draws a polygon given a pointer to point coordinates and the number of vertices measured in points. * The polygon can be closed or open. @@ -159,7 +159,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void drawPoly(const Vec2* poli, unsigned int numberOfPoints, bool closedPolygon, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a circle given the center, radius and number of segments. @@ -181,7 +181,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol bool drawLineToCenter, float scaleX, float scaleY, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a circle given the center, radius and number of segments. @@ -199,7 +199,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol float angle, unsigned int segments, bool drawLineToCenter, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a star given the center, radiusI, radiusO and number of segments. @@ -215,7 +215,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol float radiusI, float radiusO, unsigned int segments, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a solid star given the center, radiusI, radiusO and number of segments. @@ -231,8 +231,8 @@ class AX_DLL DrawNode : public Node, public BlendProtocol float radiusI, float radiusO, unsigned int segments, - const Color4B& color, - const Color4B& filledColor, + const Color& color, + const Color& filledColor, float thickness = 1.0f); /** Draws a quad bezier path. @@ -247,7 +247,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol const Vec2& control, const Vec2& destination, unsigned int segments, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draw a cubic bezier curve with color and number of segments @@ -264,7 +264,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol const Vec2& control2, const Vec2& destination, unsigned int segments, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a Cardinal Spline path. @@ -277,7 +277,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void drawCardinalSpline(const PointArray* configIn, float tension, unsigned int segments, - const Color4B& color, + const Color& color, float thickness = 1.0f, bool closed = false); @@ -289,7 +289,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawCatmullRom(const PointArray* pointsIn, unsigned int segments, - const Color4B& color, + const Color& color, float thickness = 1.0f, bool closed = false); @@ -299,7 +299,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol * @param radius The dot radius. * @param color The dot color. */ - void drawDot(const Vec2& pos, float radius, const Color4B& color); + void drawDot(const Vec2& pos, float radius, const Color& color); /** Draws a rectangle with 4 points. * @@ -313,7 +313,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol const Vec2& p2, const Vec2& p3, const Vec2& p4, - const Color4B& color, + const Color& color, float thickness = 1.0f); /** Draws a solid rectangle given the origin and destination point measured in points. @@ -325,9 +325,9 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawSolidRect(const Vec2& origin, const Vec2& destination, - const Color4B& color, + const Color& color, float thickness = 0, - const Color4B& borderColor = Color4B(0, 0, 0, 0)); + const Color& borderColor = Color(0, 0, 0, 0)); /** Draws a solid polygon given a pointer to CGPoint coordinates, the number of vertices measured in points, and a * color. @@ -338,9 +338,9 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawSolidPoly(const Vec2* poli, unsigned int numberOfPoints, - const Color4B& color, + const Color& color, float thickness = 0, - const Color4B& borderColor = Color4B(0, 0, 0, 0), + const Color& borderColor = Color(0, 0, 0, 0), bool isconvex = false); /** Draws a solid circle given the center, radius and number of segments. @@ -361,9 +361,9 @@ class AX_DLL DrawNode : public Node, public BlendProtocol unsigned int segments, float scaleX, float scaleY, - const Color4B& fillColor, + const Color& fillColor, float thickness, - const Color4B& borderColor, + const Color& borderColor, bool drawLineToCenter = false); /** Draws a solid circle given the center, radius and number of segments. @@ -381,7 +381,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol unsigned int segments, float scaleX, float scaleY, - const Color4B& color); + const Color& color); /** Draws a solid circle given the center, radius and number of segments. * @param center The circle center point. @@ -390,7 +390,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol * @param segments The number of segments. * @param color The solid circle color. */ - void drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, const Color4B& color); + void drawSolidCircle(const Vec2& center, float radius, float angle, unsigned int segments, const Color& color); /** Draws a pie given the center, radius, angle, start angle, end angle and number of segments. * @param center The circle center point. @@ -411,8 +411,8 @@ class AX_DLL DrawNode : public Node, public BlendProtocol int endAngle, float scaleX, float scaleY, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, DrawMode drawMode = DrawMode::Outline, float thickness = 1.0f); @@ -435,14 +435,9 @@ class AX_DLL DrawNode : public Node, public BlendProtocol int endAngle, float scaleX, float scaleY, - const Color4B& color, + const Color& color, DrawMode drawMode = DrawMode::Outline); - void setIsConvex(bool isConvex) - { - AXLOGW("'setIsConvex()' No longer supported. Use the new drawPolygon API."); - }; - /** draw a segment with a radius and color. * @@ -454,7 +449,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void drawSegment(const Vec2& from, const Vec2& to, float radius, - const Color4B& color, + const Color& color, DrawNode::EndType etStart = DrawNode::EndType::Round, DrawNode::EndType etEnd = DrawNode::EndType::Round); @@ -472,18 +467,18 @@ class AX_DLL DrawNode : public Node, public BlendProtocol */ void drawPolygon(const Vec2* verts, int count, - const Color4B& fillColor, + const Color& fillColor, float thickness, - const Color4B& borderColor, + const Color& borderColor, bool isconvex = false); - void drawPolygon(const Vec2* verts, int count, float thickness, const Color4B& borderColor, bool isconvex = false); + void drawPolygon(const Vec2* verts, int count, float thickness, const Color& borderColor, bool isconvex = false); void drawSolidPolygon(const Vec2* verts, int count, - const Color4B& fillColor, + const Color& fillColor, float thickness, - const Color4B& borderColor, + const Color& borderColor, bool isconvex = false); /** draw a triangle with color. @@ -494,25 +489,25 @@ class AX_DLL DrawNode : public Node, public BlendProtocol * @param color The triangle color. */ - void drawColoredTriangle(const Vec2* vertices3, const Color4B* color3); - void drawTriangle(const Vec2* vertices3, const Color4B& color); + void drawColoredTriangle(const Vec2* vertices3, const Color* color3); + void drawTriangle(const Vec2* vertices3, const Color& color); - void drawTriangle(const Vec2& p1, const Vec2& p2, const Vec2& p3, const Color4B& color); + void drawTriangle(const Vec2& p1, const Vec2& p2, const Vec2& p3, const Color& color); void drawSolidTriangle(const Vec2* vertices3, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, float thickness = 1.0f); void drawSolidTriangle(const Vec2& p1, const Vec2& p2, const Vec2& p3, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, float thickness = 1.0f); /** Clear the geometry in the node's buffer. */ - void clear(); + virtual void clear(); /** Get the color mixed mode. * @lua NA */ @@ -527,9 +522,9 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void setBlendFunc(const BlendFunc& blendFunc) override; // Overrides - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** * When isolated is set, the position of the node is no longer affected by parent nodes. @@ -541,7 +536,7 @@ class AX_DLL DrawNode : public Node, public BlendProtocol DrawNode(); virtual ~DrawNode(); - virtual bool init() override; + bool init() override; protected: void updateBuffers(); @@ -569,46 +564,46 @@ class AX_DLL DrawNode : public Node, public BlendProtocol CustomCommand _customCommandPoint; CustomCommand _customCommandLine; - axstd::pod_vector _triangles; - axstd::pod_vector _points; - axstd::pod_vector _lines; + axstd::pod_vector _triangles; + axstd::pod_vector _points; + axstd::pod_vector _lines; private: // Internal function _drawPoint void _drawPoint(const Vec2& position, const float pointSize, - const Color4B& color, + const Color& color, const DrawNode::PointType pointType); // Internal function _drawPoints void _drawPoints(const Vec2* position, unsigned int numberOfPoints, const float pointSize, - const Color4B& color, + const Color& color, const DrawNode::PointType pointType); // Internal function _drawDot - void _drawDot(const Vec2& pos, float radius, const Color4B& color); + void _drawDot(const Vec2& pos, float radius, const Color& color); // Internal function _drawTriangle // Note: modifies supplied vertex array void _drawTriangle(Vec2* vertices3, - const Color4B& borderColor, - const Color4B& fillColor, + const Color& borderColor, + const Color& fillColor, bool solid = true, float thickness = 0.0f); void _drawColoredTriangle(Vec2* vertices3, - const Color4B* color3); + const Color* color3); // Internal function _drawAStar void _drawAStar(const Vec2& center, float radiusI, float radiusO, unsigned int segments, - const Color4B& color, - const Color4B& filledColor, + const Color& color, + const Color& filledColor, float thickness = 1.0f, bool solid = false); @@ -616,26 +611,26 @@ class AX_DLL DrawNode : public Node, public BlendProtocol void _drawPoly(const Vec2* poli, unsigned int numberOfPoints, bool closedPolygon, - const Color4B& color, + const Color& color, float thickness = 1.0f, bool isconvex = true); // Internal function _drawPolygon void _drawPolygon(const Vec2* verts, unsigned int count, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, bool closedPolygon = true, float thickness = 1.0f, bool isconvex = true); // Internal function _drawLine - void _drawLine(const Vec2& from, const Vec2& to, const Color4B& color); + void _drawLine(const Vec2& from, const Vec2& to, const Color& color); // Internal function _drawSegment void _drawSegment(const Vec2& origin, const Vec2& destination, - const Color4B& color, + const Color& color, float thickness = 1.0f, DrawNode::EndType etStart = DrawNode::EndType::Square, DrawNode::EndType etEnd = DrawNode::EndType::Square); @@ -648,8 +643,8 @@ class AX_DLL DrawNode : public Node, public BlendProtocol bool drawLineToCenter, float scaleX, float scaleY, - const Color4B& borderColor, - const Color4B& fillColor, + const Color& borderColor, + const Color& fillColor, bool solid, float thickness = 1.0f); @@ -661,8 +656,8 @@ class AX_DLL DrawNode : public Node, public BlendProtocol int endAngle, float scaleX, float scaleY, - const Color4B& fillColor, - const Color4B& borderColor, + const Color& fillColor, + const Color& borderColor, DrawMode drawMode, float thickness = 1.0f); diff --git a/core/2d/FastTMXLayer.cpp b/axmol/2d/FastTMXLayer.cpp similarity index 88% rename from core/2d/FastTMXLayer.cpp rename to axmol/2d/FastTMXLayer.cpp index f62e1d1694a7..666af442ae39 100644 --- a/core/2d/FastTMXLayer.cpp +++ b/axmol/2d/FastTMXLayer.cpp @@ -36,20 +36,20 @@ THE SOFTWARE. It was rewritten again, and only a small part of the original HK ideas/code remains in this implementation */ -#include "2d/FastTMXLayer.h" +#include "axmol/2d/FastTMXLayer.h" #include // offsetof -#include "base/Types.h" -#include "2d/FastTMXTiledMap.h" -#include "2d/Sprite.h" -#include "2d/Camera.h" -#include "renderer/TextureCache.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Buffer.h" -#include "base/Director.h" -#include "base/UTF8.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -125,7 +125,7 @@ FastTMXLayer::~FastTMXLayer() for (auto&& e : _customCommands) { - AX_SAFE_RELEASE(e.second->getPipelineDescriptor().programState); + AX_SAFE_RELEASE(e.second->getPipelineDesc().programState); delete e.second; } } @@ -163,8 +163,8 @@ void FastTMXLayer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag { if (e.second->getIndexDrawCount() > 0) { - auto mvpmatrixLocation = e.second->getPipelineDescriptor().programState->getUniformLocation("u_MVPMatrix"); - e.second->getPipelineDescriptor().programState->setUniform(mvpmatrixLocation, finalMat.m, + auto mvpmatrixLocation = e.second->getPipelineDesc().programState->getUniformLocation("u_MVPMatrix"); + e.second->getPipelineDesc().programState->setUniform(mvpmatrixLocation, finalMat.m, sizeof(finalMat.m)); renderer->addCommand(e.second); } @@ -271,10 +271,10 @@ void FastTMXLayer::updateTiles(const Rect& culledRect) void FastTMXLayer::updateVertexBuffer() { - unsigned int vertexBufferSize = (unsigned int)(sizeof(V3F_C4B_T2F) * _totalQuads.size() * 4); + unsigned int vertexBufferSize = (unsigned int)(sizeof(V3F_T2F_C4B) * _totalQuads.size() * 4); if (!_vertexBuffer) { - _vertexBuffer = backend::DriverBase::getInstance()->newBuffer(vertexBufferSize, backend::BufferType::VERTEX, backend::BufferUsage::STATIC); + _vertexBuffer = rhi::DriverBase::getInstance()->createBuffer(vertexBufferSize, rhi::BufferType::VERTEX, rhi::BufferUsage::STATIC); } _vertexBuffer->updateData(&_totalQuads[0], vertexBufferSize); } @@ -284,7 +284,7 @@ void FastTMXLayer::updateIndexBuffer() auto indexBufferSize = (sizeof(decltype(_indices)::value_type) * _indices.size()); if (!_indexBuffer) { - _indexBuffer = backend::DriverBase::getInstance()->newBuffer(indexBufferSize, backend::BufferType::INDEX, backend::BufferUsage::DYNAMIC); + _indexBuffer = rhi::DriverBase::getInstance()->createBuffer(indexBufferSize, rhi::BufferType::INDEX, rhi::BufferUsage::DYNAMIC); } _indexBuffer->updateData(&_indices[0], indexBufferSize); } @@ -446,30 +446,30 @@ void FastTMXLayer::updatePrimitives() command->setIndexDrawInfo(start * 6, iter.second * 6); - auto& pipelineDescriptor = command->getPipelineDescriptor(); + auto& pipelineDesc = command->getPipelineDesc(); if (_useAutomaticVertexZ) { - AX_SAFE_RELEASE(pipelineDescriptor.programState); + AX_SAFE_RELEASE(pipelineDesc.programState); auto* program = - backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); - auto programState = new backend::ProgramState(program); - pipelineDescriptor.programState = programState; - _alphaValueLocation = pipelineDescriptor.programState->getUniformLocation("u_alpha_value"); - pipelineDescriptor.programState->setUniform(_alphaValueLocation, &_alphaFuncValue, + axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); + auto programState = new rhi::ProgramState(program); + pipelineDesc.programState = programState; + _alphaValueLocation = pipelineDesc.programState->getUniformLocation("u_alpha_value"); + pipelineDesc.programState->setUniform(_alphaValueLocation, &_alphaFuncValue, sizeof(_alphaFuncValue)); } else { - AX_SAFE_RELEASE(pipelineDescriptor.programState); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - auto programState = new backend::ProgramState(program); - pipelineDescriptor.programState = programState; + AX_SAFE_RELEASE(pipelineDesc.programState); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR); + auto programState = new rhi::ProgramState(program); + pipelineDesc.programState = programState; } - _mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); - _textureLocation = pipelineDescriptor.programState->getUniformLocation("u_tex0"); - pipelineDescriptor.programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); + _mvpMatrixLocaiton = pipelineDesc.programState->getUniformLocation("u_MVPMatrix"); + _textureLocation = pipelineDesc.programState->getUniformLocation("u_tex0"); + pipelineDesc.programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); command->init(_globalZOrder, blendfunc); _customCommands[iter.first] = command; @@ -499,7 +499,7 @@ void FastTMXLayer::updateTotalQuads() _tileToQuadIndex.resize(int(_layerSize.width * _layerSize.height), -1); _indicesVertexZOffsets.clear(); - auto color = Color4B::WHITE; + auto color = Color32::WHITE; color.a = getDisplayedOpacity(); if (_texture->hasPremultipliedAlpha()) @@ -565,33 +565,33 @@ void FastTMXLayer::updateTotalQuads() if (tileGID & kTMXTileDiagonalFlag) { // FIXME: not working correctly - quad.bl.vertices.x = left; - quad.bl.vertices.y = bottom; - quad.bl.vertices.z = z; - quad.br.vertices.x = left; - quad.br.vertices.y = top; - quad.br.vertices.z = z; - quad.tl.vertices.x = right; - quad.tl.vertices.y = bottom; - quad.tl.vertices.z = z; - quad.tr.vertices.x = right; - quad.tr.vertices.y = top; - quad.tr.vertices.z = z; + quad.bl.position.x = left; + quad.bl.position.y = bottom; + quad.bl.position.z = z; + quad.br.position.x = left; + quad.br.position.y = top; + quad.br.position.z = z; + quad.tl.position.x = right; + quad.tl.position.y = bottom; + quad.tl.position.z = z; + quad.tr.position.x = right; + quad.tr.position.y = top; + quad.tr.position.z = z; } else { - quad.bl.vertices.x = left; - quad.bl.vertices.y = bottom; - quad.bl.vertices.z = z; - quad.br.vertices.x = right; - quad.br.vertices.y = bottom; - quad.br.vertices.z = z; - quad.tl.vertices.x = left; - quad.tl.vertices.y = top; - quad.tl.vertices.z = z; - quad.tr.vertices.x = right; - quad.tr.vertices.y = top; - quad.tr.vertices.z = z; + quad.bl.position.x = left; + quad.bl.position.y = bottom; + quad.bl.position.z = z; + quad.br.position.x = right; + quad.br.position.y = bottom; + quad.br.position.z = z; + quad.tl.position.x = left; + quad.tl.position.y = top; + quad.tl.position.z = z; + quad.tr.position.x = right; + quad.tr.position.y = top; + quad.tr.position.z = z; } // texcoords @@ -605,19 +605,19 @@ void FastTMXLayer::updateTotalQuads() float ptx = 1.0 / (_tileSet->_imageSize.x * tileSize.x); float pty = 1.0 / (_tileSet->_imageSize.y * tileSize.y); - quad.bl.texCoords.u = left + ptx; - quad.bl.texCoords.v = bottom + pty; - quad.br.texCoords.u = right - ptx; - quad.br.texCoords.v = bottom + pty; - quad.tl.texCoords.u = left + ptx; - quad.tl.texCoords.v = top - pty; - quad.tr.texCoords.u = right - ptx; - quad.tr.texCoords.v = top - pty; - - quad.bl.colors = color; - quad.br.colors = color; - quad.tl.colors = color; - quad.tr.colors = color; + quad.bl.texCoord.u = left + ptx; + quad.bl.texCoord.v = bottom + pty; + quad.br.texCoord.u = right - ptx; + quad.br.texCoord.v = bottom + pty; + quad.tl.texCoord.u = left + ptx; + quad.tl.texCoord.v = top - pty; + quad.tr.texCoord.u = right - ptx; + quad.tr.texCoord.v = top - pty; + + quad.bl.color = color; + quad.br.color = color; + quad.tl.color = color; + quad.tr.color = color; ++quadIndex; } diff --git a/core/2d/FastTMXLayer.h b/axmol/2d/FastTMXLayer.h similarity index 96% rename from core/2d/FastTMXLayer.h rename to axmol/2d/FastTMXLayer.h index c15e2be6355b..fa40d1cc1d19 100644 --- a/core/2d/FastTMXLayer.h +++ b/axmol/2d/FastTMXLayer.h @@ -29,9 +29,9 @@ THE SOFTWARE. #pragma once #include -#include "2d/Node.h" -#include "2d/TMXXMLParser.h" -#include "renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/TMXXMLParser.h" +#include "axmol/renderer/CustomCommand.h" namespace ax { @@ -43,7 +43,7 @@ class TMXTileAnimManager; class Texture2D; class Sprite; -namespace backend +namespace rhi { class Buffer; } @@ -280,8 +280,8 @@ class AX_DLL FastTMXLayer : public Node // // Override // - virtual std::string getDescription() const override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + std::string getDescription() const override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; void removeChild(Node* child, bool cleanup = true) override; /** Map from gid of animated tile to its instance. @@ -299,7 +299,7 @@ class AX_DLL FastTMXLayer : public Node TMXMapInfo* mapInfo); protected: - virtual void setOpacity(uint8_t opacity) override; + void setOpacity(uint8_t opacity) override; void updateTiles(const Rect& culledRect); Vec2 calculateLayerOffset(const Vec2& offset); @@ -367,7 +367,7 @@ class AX_DLL FastTMXLayer : public Node float _cameraZoomDirty; std::vector _tileToQuadIndex; - std::vector _totalQuads; + std::vector _totalQuads; #ifdef AX_FAST_TILEMAP_32_BIT_INDICES std::vector _indices; #else @@ -377,15 +377,15 @@ class AX_DLL FastTMXLayer : public Node std::unordered_map _indicesVertexZNumber; bool _dirty = true; - backend::Buffer* _vertexBuffer = nullptr; - backend::Buffer* _indexBuffer = nullptr; + rhi::Buffer* _vertexBuffer = nullptr; + rhi::Buffer* _indexBuffer = nullptr; float _alphaFuncValue = 0.f; std::unordered_map _customCommands; - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _textureLocation; - backend::UniformLocation _alphaValueLocation; + rhi::UniformLocation _mvpMatrixLocaiton; + rhi::UniformLocation _textureLocation; + rhi::UniformLocation _alphaValueLocation; }; /** @brief TMXTileAnimTask represents the frame-tick task of an animated tile. diff --git a/core/2d/FastTMXTiledMap.cpp b/axmol/2d/FastTMXTiledMap.cpp similarity index 98% rename from core/2d/FastTMXTiledMap.cpp rename to axmol/2d/FastTMXTiledMap.cpp index 08b891ad4236..341b9625abc1 100644 --- a/core/2d/FastTMXTiledMap.cpp +++ b/axmol/2d/FastTMXTiledMap.cpp @@ -26,9 +26,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/FastTMXTiledMap.h" -#include "2d/FastTMXLayer.h" -#include "base/UTF8.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/2d/FastTMXLayer.h" +#include "axmol/base/text_utils.h" namespace ax { diff --git a/core/2d/FastTMXTiledMap.h b/axmol/2d/FastTMXTiledMap.h similarity index 97% rename from core/2d/FastTMXTiledMap.h rename to axmol/2d/FastTMXTiledMap.h index 87a3e36563d5..c79ac7623c0e 100644 --- a/core/2d/FastTMXTiledMap.h +++ b/axmol/2d/FastTMXTiledMap.h @@ -28,8 +28,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "2d/TMXObjectGroup.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/TMXObjectGroup.h" namespace ax { @@ -200,15 +200,13 @@ class AX_DLL FastTMXTiledMap : public Node */ void setProperties(const ValueMap& properties) { _properties = properties; } - virtual std::string getDescription() const override; + std::string getDescription() const override; /** Set all tile animations enabled or not. * animations are not enabled by default */ void setTileAnimEnabled(bool enabled); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) int getLayerNum() const { return getLayerCount(); } -#endif + int getLayerCount() const { return _layerCount; } std::string_view getResourceFile() const { return _tmxFile; } @@ -225,7 +223,7 @@ class AX_DLL FastTMXTiledMap : public Node /** * @lua NA */ - virtual ~FastTMXTiledMap() override; + ~FastTMXTiledMap() override; /** initializes a TMX Tiled Map with a TMX file */ bool initWithTMXFile(std::string_view tmxFile, bool allowInvisibleLayers = false); diff --git a/core/2d/Font.cpp b/axmol/2d/Font.cpp similarity index 100% rename from core/2d/Font.cpp rename to axmol/2d/Font.cpp diff --git a/core/2d/Font.h b/axmol/2d/Font.h similarity index 96% rename from core/2d/Font.h rename to axmol/2d/Font.h index 68e0d502e9d7..1775e45c1bc0 100644 --- a/core/2d/Font.h +++ b/axmol/2d/Font.h @@ -30,8 +30,8 @@ /// @cond DO_NOT_SHOW #include -#include "base/Types.h" -#include "base/UTF8.h" +#include "axmol/base/Types.h" +#include "axmol/base/text_utils.h" namespace ax { diff --git a/core/2d/FontAtlas.cpp b/axmol/2d/FontAtlas.cpp similarity index 96% rename from core/2d/FontAtlas.cpp rename to axmol/2d/FontAtlas.cpp index 41914d6652bd..28d815fad91c 100644 --- a/core/2d/FontAtlas.cpp +++ b/axmol/2d/FontAtlas.cpp @@ -25,28 +25,27 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/FontAtlas.h" +#include "axmol/2d/FontAtlas.h" #if AX_TARGET_PLATFORM != AX_PLATFORM_WIN32 && AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID #elif AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID -# include "platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" +# include "axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" #endif #include -#include "2d/FontFreeType.h" -#include "base/UTF8.h" -#include "base/Director.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" #include "simdjson/simdjson.h" #include "zlib.h" -#include "base/ZipUtils.h" +#include "axmol/base/ZipUtils.h" -#include "base/PaddedString.h" +#include "axmol/base/json.h" namespace ax { - const int FontAtlas::CacheTextureWidth = 512; const int FontAtlas::CacheTextureHeight = 512; const char* FontAtlas::CMD_PURGE_FONTATLAS = "__ax_PURGE_FONTATLAS"; @@ -54,11 +53,12 @@ const char* FontAtlas::CMD_RESET_FONTATLAS = "__ax_RESET_FONTATLAS"; void FontAtlas::loadFontAtlas(std::string_view fontatlasFile, hlookup::string_map& outAtlasMap) { - using namespace simdjson; + using namespace ::simdjson; try { - auto strJson = PaddedString::load(fontatlasFile); + simdjson::PaddedString strJson; + FileUtils::getInstance()->getContents(fontatlasFile, &strJson); ondemand::parser parser; ondemand::document settings = parser.iterate(strJson); std::string_view type = settings["type"]; @@ -144,7 +144,7 @@ FontAtlas::FontAtlas(Font* theFont, int atlasWidth, int atlasHeight, float scale if (outlineSize > 0) { _strideShift = 1; - _pixelFormat = backend::PixelFormat::RG8; + _pixelFormat = rhi::PixelFormat::RG8; _currentPageDataSize = _width * _height << _strideShift; _lineHeight += 2 * outlineSize; @@ -152,7 +152,7 @@ FontAtlas::FontAtlas(Font* theFont, int atlasWidth, int atlasHeight, float scale else { _strideShift = 0; - _pixelFormat = backend::PixelFormat::R8; + _pixelFormat = rhi::PixelFormat::R8; _currentPageDataSize = _width * _height; } @@ -460,7 +460,7 @@ bool FontAtlas::prepareLetterDefinitions(const std::u32string& utf32Text) return true; } -void FontAtlas::updateTextureContent(backend::PixelFormat format, int startY) +void FontAtlas::updateTextureContent(rhi::PixelFormat format, int startY) { auto data = _currentPageData + (_width * (int)startY << _strideShift); _atlasTextures[_currentPage]->updateWithSubData(data, 0, startY, _width, diff --git a/core/2d/FontAtlas.h b/axmol/2d/FontAtlas.h similarity index 94% rename from core/2d/FontAtlas.h rename to axmol/2d/FontAtlas.h index a6e5f52e76c7..96ee58a25ebc 100644 --- a/core/2d/FontAtlas.h +++ b/axmol/2d/FontAtlas.h @@ -32,13 +32,13 @@ #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "platform/StdC.h" // ssize_t on windows -#include "renderer/Texture2D.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/platform/StdC.h" // ssize_t on windows +#include "axmol/renderer/Texture2D.h" -#include "base/Map.h" -#include "2d/FontFreeType.h" +#include "axmol/base/Map.h" +#include "axmol/2d/FontFreeType.h" namespace ax { @@ -142,7 +142,7 @@ class AX_DLL FontAtlas : public Object */ void scaleFontLetterDefinition(float scaleFactor); - void updateTextureContent(backend::PixelFormat format, int startY); + void updateTextureContent(rhi::PixelFormat format, int startY); std::unordered_map _atlasTextures; std::unordered_map _letterDefinitions; @@ -161,7 +161,7 @@ class AX_DLL FontAtlas : public Object // Dynamic GlyphCollection related stuff int _currentPage = -1; - backend::PixelFormat _pixelFormat = backend::PixelFormat::NONE; + rhi::PixelFormat _pixelFormat = rhi::PixelFormat::NONE; int _strideShift = 0; uint8_t* _currentPageData = nullptr; int _currentPageDataSize = 0; diff --git a/core/2d/FontAtlasCache.cpp b/axmol/2d/FontAtlasCache.cpp similarity index 92% rename from core/2d/FontAtlasCache.cpp rename to axmol/2d/FontAtlasCache.cpp index 807da7358a9d..2e32285479f3 100644 --- a/core/2d/FontAtlasCache.cpp +++ b/axmol/2d/FontAtlasCache.cpp @@ -24,16 +24,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/FontAtlasCache.h" +#include "axmol/2d/FontAtlasCache.h" -#include "base/Director.h" -#include "2d/FontFNT.h" -#include "2d/FontFreeType.h" -#include "2d/FontAtlas.h" -#include "2d/FontCharMap.h" -#include "2d/Label.h" -#include "platform/FileUtils.h" -#include "base/format.h" +#include "axmol/base/Director.h" +#include "axmol/2d/FontFNT.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/2d/FontCharMap.h" +#include "axmol/2d/Label.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/format.h" namespace ax { @@ -141,12 +141,7 @@ FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, const return nullptr; } -#ifndef AX_CORE_PROFILE -FontAtlas* FontAtlasCache::getFontAtlasFNT(std::string_view fontFileName, const Vec2& imageOffset) -{ - return getFontAtlasFNT(fontFileName, Rect(imageOffset.x, imageOffset.y, 0, 0), false); -} -#endif + FontAtlas* FontAtlasCache::getFontAtlasCharMap(std::string_view plistFile) { std::string_view atlasName = plistFile; @@ -257,12 +252,6 @@ void FontAtlasCache::reloadFontAtlasFNT(std::string_view fontFileName, const Rec _atlasMap.emplace(std::move(atlasName), tempAtlas); } } -#ifndef AX_CORE_PROFILE -void FontAtlasCache::reloadFontAtlasFNT(std::string_view fontFileName, const Vec2& imageOffset) -{ - reloadFontAtlasFNT(fontFileName, Rect(imageOffset.x, imageOffset.y, 0, 0), false); -} -#endif void FontAtlasCache::unloadFontAtlasTTF(std::string_view fontFileName) { diff --git a/core/2d/FontAtlasCache.h b/axmol/2d/FontAtlasCache.h similarity index 89% rename from core/2d/FontAtlasCache.h rename to axmol/2d/FontAtlasCache.h index 097b99ebb8af..c17996589645 100644 --- a/core/2d/FontAtlasCache.h +++ b/axmol/2d/FontAtlasCache.h @@ -29,7 +29,7 @@ /// @cond DO_NOT_SHOW #include -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -51,9 +51,7 @@ class AX_DLL FontAtlasCache static FontAtlas* getFontAtlasFNT(std::string_view fontFileName); static FontAtlas* getFontAtlasFNT(std::string_view fontFileName, std::string_view subTextureKey); static FontAtlas* getFontAtlasFNT(std::string_view fontFileName, const Rect& imageRect, bool imageRotated); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) static FontAtlas* getFontAtlasFNT(std::string_view fontFileName, const Vec2& imageOffset); -#endif + static FontAtlas* getFontAtlasCharMap(std::string_view charMapFile, int itemWidth, int itemHeight, @@ -73,10 +71,7 @@ class AX_DLL FontAtlasCache otherwise, it will cause program crash! */ static void reloadFontAtlasFNT(std::string_view fontFileName, const Rect& imageRect, bool imageRotated); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) static void reloadFontAtlasFNT(std::string_view fontFileName, - const Vec2& imageOffset = Vec2::ZERO); -#endif + /** Unload all texture atlas texture create by special file name. CAUTION : All component use this font texture should be reset font name, though the file name is same! otherwise, it will cause program crash! diff --git a/core/2d/FontCharMap.cpp b/axmol/2d/FontCharMap.cpp similarity index 96% rename from core/2d/FontCharMap.cpp rename to axmol/2d/FontCharMap.cpp index 73b390b5e609..1386942f730f 100644 --- a/core/2d/FontCharMap.cpp +++ b/axmol/2d/FontCharMap.cpp @@ -25,11 +25,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/FontCharMap.h" -#include "2d/FontAtlas.h" -#include "platform/FileUtils.h" -#include "base/Director.h" -#include "renderer/TextureCache.h" +#include "axmol/2d/FontCharMap.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/TextureCache.h" namespace ax { diff --git a/core/2d/FontCharMap.h b/axmol/2d/FontCharMap.h similarity index 92% rename from core/2d/FontCharMap.h rename to axmol/2d/FontCharMap.h index 7c3af94f21f4..1fc2a650d1bb 100644 --- a/core/2d/FontCharMap.h +++ b/axmol/2d/FontCharMap.h @@ -29,7 +29,7 @@ /// @cond DO_NOT_SHOW -#include "2d/Font.h" +#include "axmol/2d/Font.h" namespace ax { @@ -42,8 +42,8 @@ class FontCharMap : public Font static FontCharMap* create(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); static FontCharMap* create(std::string_view plistFile); - virtual int* getHorizontalKerningForTextUTF32(const std::u32string& text, int& outNumLetters) const override; - virtual FontAtlas* newFontAtlas() override; + int* getHorizontalKerningForTextUTF32(const std::u32string& text, int& outNumLetters) const override; + FontAtlas* newFontAtlas() override; protected: FontCharMap(Texture2D* texture, int itemWidth, int itemHeight, int startCharMap) diff --git a/core/2d/FontFNT.cpp b/axmol/2d/FontFNT.cpp similarity index 98% rename from core/2d/FontFNT.cpp rename to axmol/2d/FontFNT.cpp index 1160e6702be0..d10565772707 100644 --- a/core/2d/FontFNT.cpp +++ b/axmol/2d/FontFNT.cpp @@ -25,15 +25,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/FontFNT.h" -#include "2d/FontAtlas.h" -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" -#include "base/Configuration.h" -#include "base/Director.h" -#include "base/Map.h" -#include "base/UTF8.h" -#include "renderer/TextureCache.h" +#include "axmol/2d/FontFNT.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/base/Map.h" +#include "axmol/base/text_utils.h" +#include "axmol/renderer/TextureCache.h" #include @@ -444,7 +444,7 @@ void BMFontConfiguration::parseCommonArguments(const char* line) auto tmp = strstr(line, "lineHeight=") + 11; sscanf(tmp, "%d", &_commonHeight); -#if _AX_DEBUG > 0 +#if defined(_AX_DEBUG) && _AX_DEBUG > 0 // scaleW. sanity check int value; tmp = strstr(tmp, "scaleW=") + 7; @@ -590,12 +590,7 @@ FontFNT* FontFNT::create(std::string_view fntFilePath) tempFont->autorelease(); return tempFont; } -#ifndef AX_CORE_PROFILE -FontFNT* FontFNT::create(std::string_view fntFilePath, const Vec2& imageOffset) -{ - return create(fntFilePath, Rect(imageOffset.x, imageOffset.y, 0, 0), false); -} -#endif + FontFNT::FontFNT(BMFontConfiguration* theContfig, const Rect& imageRect, bool imageRotated) : _configuration(theContfig), _imageRectInPoints(AX_RECT_PIXELS_TO_POINTS(imageRect)), _imageRotated(imageRotated) { diff --git a/core/2d/FontFNT.h b/axmol/2d/FontFNT.h similarity index 94% rename from core/2d/FontFNT.h rename to axmol/2d/FontFNT.h index 996e956f2df6..8f3de72e3614 100644 --- a/core/2d/FontFNT.h +++ b/axmol/2d/FontFNT.h @@ -29,7 +29,7 @@ /// @cond DO_NOT_SHOW -#include "2d/Font.h" +#include "axmol/2d/Font.h" #include #include @@ -145,15 +145,13 @@ class AX_DLL FontFNT : public Font static FontFNT* create(std::string_view fntFilePath, const Rect& imageRect, bool imageRotated); static FontFNT* create(std::string_view fntFilePath, std::string_view subTextureKey); static FontFNT* create(std::string_view fntFilePath); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) static FontFNT* create(std::string_view fntFilePath, const Vec2& imageOffset = Vec2::ZERO); -#endif + /** Purges the cached data. Removes from memory the cached configurations and the atlas name dictionary. */ static void purgeCachedData(); - virtual int* getHorizontalKerningForTextUTF32(const std::u32string& text, int& outNumLetters) const override; - virtual FontAtlas* newFontAtlas() override; + int* getHorizontalKerningForTextUTF32(const std::u32string& text, int& outNumLetters) const override; + FontAtlas* newFontAtlas() override; void setFontSize(float fontSize); float getFontSize() const { return _fontSize; } diff --git a/core/2d/FontFreeType.cpp b/axmol/2d/FontFreeType.cpp similarity index 98% rename from core/2d/FontFreeType.cpp rename to axmol/2d/FontFreeType.cpp index 33a47c21ad43..c6c4ed405f49 100644 --- a/core/2d/FontFreeType.cpp +++ b/axmol/2d/FontFreeType.cpp @@ -25,15 +25,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/FontFreeType.h" -#include "2d/FontAtlas.h" -#include "base/Director.h" -#include "base/UTF8.h" -#include "base/filesystem.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/filesystem.h" #include "freetype/ftmodapi.h" -#include "platform/FileUtils.h" -#include "platform/FileStream.h" -#include "platform/Application.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/FileStream.h" +#include "axmol/platform/Application.h" #include "ft2build.h" #include FT_FREETYPE_H @@ -351,7 +351,7 @@ FontAtlas* FontFreeType::newFontAtlas() if (_usedGlyphs != GlyphCollection::DYNAMIC) { std::u32string utf32; - if (StringUtils::UTF8ToUTF32(getGlyphCollection(), utf32)) + if (text_utils::UTF8ToUTF32(getGlyphCollection(), utf32)) { fontAtlas->prepareLetterDefinitions(utf32); } @@ -436,7 +436,7 @@ unsigned char* FontFreeType::getGlyphBitmap(char32_t charCode, char32_t ntcs[2] = {charCode, (char32_t)0}; std::u32string_view charUTF32(ntcs, 1); std::string charUTF8; - ax::StringUtils::UTF32ToUTF8(charUTF32, charUTF8); + ax::text_utils::UTF32ToUTF8(charUTF32, charUTF8); if (charUTF8 == "\n") charUTF8 = "\\n"; diff --git a/core/2d/FontFreeType.h b/axmol/2d/FontFreeType.h similarity index 97% rename from core/2d/FontFreeType.h rename to axmol/2d/FontFreeType.h index af7b04df72c4..c5bb97b4daae 100644 --- a/core/2d/FontFreeType.h +++ b/axmol/2d/FontFreeType.h @@ -26,8 +26,8 @@ ****************************************************************************/ #pragma once -#include "2d/Font.h" -#include "2d/IFontEngine.h" +#include "axmol/2d/Font.h" +#include "axmol/2d/IFontEngine.h" #include namespace ax @@ -135,8 +135,8 @@ class AX_DLL FontFreeType : public Font const char* getFontFamily() const; std::string_view getFontName() const { return _fontName; } - virtual FontAtlas* newFontAtlas() override; - virtual int getFontMaxHeight() const override { return _lineHeight; } + FontAtlas* newFontAtlas() override; + int getFontMaxHeight() const override { return _lineHeight; } std::string_view getGlyphCollection() const; diff --git a/core/2d/Grid.cpp b/axmol/2d/Grid.cpp similarity index 92% rename from core/2d/Grid.cpp rename to axmol/2d/Grid.cpp index a3873fa8f2ba..849afe77ab13 100644 --- a/core/2d/Grid.cpp +++ b/axmol/2d/Grid.cpp @@ -25,18 +25,18 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Grid.h" - -#include "base/Macros.h" -#include "base/Utils.h" -#include "2d/Node.h" -#include "renderer/Renderer.h" -#include "renderer/Texture2D.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/RenderTarget.h" -#include "2d/Camera.h" +#include "axmol/2d/Grid.h" + +#include "axmol/base/Macros.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/RenderTarget.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -57,12 +57,12 @@ bool GridBase::initWithSize(const Vec2& gridSize, const ax::Rect& rect) Texture2D* texture = new Texture2D(); - backend::TextureDescriptor descriptor; + rhi::TextureDesc descriptor; descriptor.width = POTWide; descriptor.height = POTHigh; - descriptor.textureUsage = backend::TextureUsage::RENDER_TARGET; - descriptor.textureFormat = backend::PixelFormat::RGBA8; - texture->updateTextureDescriptor(descriptor); + descriptor.textureUsage = rhi::TextureUsage::RENDER_TARGET; + descriptor.textureFormat = rhi::PixelFormat::RGBA8; + texture->updateTextureDesc(descriptor); initWithSize(gridSize, texture, false, rect); @@ -88,7 +88,7 @@ bool GridBase::initWithSize(const Vec2& gridSize, Texture2D* texture, bool flipp AX_SAFE_RETAIN(_texture); _isTextureFlipped = flipped; -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _isTextureFlipped = !flipped; #endif @@ -104,30 +104,30 @@ bool GridBase::initWithSize(const Vec2& gridSize, Texture2D* texture, bool flipp _step.x = _gridRect.size.width / _gridSize.width; _step.y = _gridRect.size.height / _gridSize.height; - auto& pipelineDescriptor = _drawCommand.getPipelineDescriptor(); + auto& pipelineDesc = _drawCommand.getPipelineDesc(); AX_SAFE_RELEASE(_programState); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE); - _programState = new backend::ProgramState(program); - pipelineDescriptor.programState = _programState; - _mvpMatrixLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); - _textureLocation = pipelineDescriptor.programState->getUniformLocation("u_tex0"); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE); + _programState = new rhi::ProgramState(program); + pipelineDesc.programState = _programState; + _mvpMatrixLocation = pipelineDesc.programState->getUniformLocation("u_MVPMatrix"); + _textureLocation = pipelineDesc.programState->getUniformLocation("u_tex0"); #define VERTEX_POSITION_SIZE 3 #define VERTEX_TEXCOORD_SIZE 2 uint32_t texcoordOffset = (VERTEX_POSITION_SIZE) * sizeof(float); uint32_t totalSize = (VERTEX_POSITION_SIZE + VERTEX_TEXCOORD_SIZE) * sizeof(float); - const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); - auto iter = attributeInfo.find("a_position"); + const auto& vertexInputs = _programState->getProgram()->getActiveVertexInputs(); + auto iter = vertexInputs.find("a_position"); auto layout = _programState->getMutableVertexLayout(); - if (iter != attributeInfo.end()) + if (iter != vertexInputs.end()) { - layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT3, 0, false); + layout->setAttrib("a_position", &iter->second, rhi::VertexFormat::FLOAT3, 0, false); } - iter = attributeInfo.find("a_texCoord"); - if (iter != attributeInfo.end()) + iter = vertexInputs.find("a_texCoord"); + if (iter != vertexInputs.end()) { - layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, texcoordOffset, + layout->setAttrib("a_texCoord", &iter->second, rhi::VertexFormat::FLOAT2, texcoordOffset, false); } layout->setStride(totalSize); @@ -220,7 +220,7 @@ void GridBase::beforeDraw() _oldRenderTarget = renderer->getRenderTarget(); AX_SAFE_RELEASE(_renderTarget); _renderTarget = - backend::DriverBase::getInstance()->newRenderTarget(_texture->getBackendTexture()); + rhi::DriverBase::getInstance()->createRenderTarget(_texture->getBackendTexture()); renderer->setRenderTarget(_renderTarget); }; renderer->addCallbackCommand(beforeDrawCommandFunc); @@ -383,7 +383,7 @@ void Grid3D::blit() _drawCommand.init(0, _blendFunc); Director::getInstance()->getRenderer()->addCommand(&_drawCommand); ax::Mat4 projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = _drawCommand.getPipelineDescriptor().programState; + auto programState = _drawCommand.getPipelineDesc().programState; programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m)); programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); } @@ -633,7 +633,7 @@ void TiledGrid3D::blit() updateVertexBuffer(); Director::getInstance()->getRenderer()->addCommand(&_drawCommand); ax::Mat4 projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = _drawCommand.getPipelineDescriptor().programState; + auto programState = _drawCommand.getPipelineDesc().programState; programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m)); programState->setTexture(_textureLocation, 0, _texture->getBackendTexture()); } diff --git a/core/2d/Grid.h b/axmol/2d/Grid.h similarity index 90% rename from core/2d/Grid.h rename to axmol/2d/Grid.h index 886c497e4db9..143dca2f04e8 100644 --- a/core/2d/Grid.h +++ b/axmol/2d/Grid.h @@ -27,12 +27,12 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Object.h" -#include "base/Types.h" -#include "base/Director.h" -#include "renderer/GroupCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" namespace ax { @@ -42,7 +42,7 @@ class Texture2D; // class GLProgram; class Node; -namespace backend +namespace rhi { class RenderTarget; } @@ -150,7 +150,7 @@ class AX_DLL GridBase : public Object Director::Projection _directorProjection = Director::Projection::_2D; Rect _gridRect; - Color4F _clearColor = {0, 0, 0, 0}; + Color _clearColor = {0, 0, 0, 0}; CustomCommand _drawCommand; //CallbackCommand _beforeDrawCommand; @@ -159,12 +159,12 @@ class AX_DLL GridBase : public Object //CallbackCommand _afterBlitCommand; // New - backend::RenderTarget* _oldRenderTarget = nullptr; - backend::RenderTarget* _renderTarget = nullptr; + rhi::RenderTarget* _oldRenderTarget = nullptr; + rhi::RenderTarget* _renderTarget = nullptr; - backend::UniformLocation _mvpMatrixLocation; - backend::UniformLocation _textureLocation; - backend::ProgramState* _programState = nullptr; + rhi::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _textureLocation; + rhi::ProgramState* _programState = nullptr; BlendFunc _blendFunc; }; @@ -210,11 +210,11 @@ class AX_DLL Grid3D : public GridBase /**@{ Implementations for interfaces in base class. */ - virtual void beforeBlit() override; - virtual void afterBlit() override; - virtual void blit() override; - virtual void reuse() override; - virtual void calculateVertexPoints() override; + void beforeBlit() override; + void afterBlit() override; + void blit() override; + void reuse() override; + void calculateVertexPoints() override; /**@}*/ /**@{ @@ -256,9 +256,9 @@ class AX_DLL TiledGrid3D : public GridBase /**@{ Implementations for interfaces in base class. */ - virtual void blit() override; - virtual void reuse() override; - virtual void calculateVertexPoints() override; + void blit() override; + void reuse() override; + void calculateVertexPoints() override; /**@}*/ /** Returns the tile at the given position. diff --git a/core/2d/IFontEngine.h b/axmol/2d/IFontEngine.h similarity index 98% rename from core/2d/IFontEngine.h rename to axmol/2d/IFontEngine.h index 9cb7d500adf1..3cbb742a8db8 100644 --- a/core/2d/IFontEngine.h +++ b/axmol/2d/IFontEngine.h @@ -24,7 +24,7 @@ #pragma once #include -#include "base/Config.h" +#include "axmol/base/Config.h" /* freetype fwd decls */ diff --git a/core/2d/Label.cpp b/axmol/2d/Label.cpp similarity index 86% rename from core/2d/Label.cpp rename to axmol/2d/Label.cpp index 870519bacec6..45c580d385fb 100644 --- a/core/2d/Label.cpp +++ b/axmol/2d/Label.cpp @@ -25,53 +25,53 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/Label.h" +#include "axmol/2d/Label.h" #include #include // offsetof -#include "base/Types.h" -#include "2d/Font.h" -#include "2d/FontAtlasCache.h" -#include "2d/FontAtlas.h" -#include "2d/Sprite.h" -#include "2d/SpriteBatchNode.h" -#include "2d/DrawNode.h" -#include "2d/Camera.h" -#include "base/UTF8.h" -#include "base/Macros.h" -#include "platform/FileUtils.h" -#include "renderer/Renderer.h" -#include "renderer/RenderCommand.h" -#include "base/Director.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventCustom.h" -#include "base/Utils.h" -#include "2d/FontFNT.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/ProgramStateRegistry.h" +#include "axmol/base/Types.h" +#include "axmol/2d/Font.h" +#include "axmol/2d/FontAtlasCache.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/SpriteBatchNode.h" +#include "axmol/2d/DrawNode.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/FontFNT.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/ProgramStateRegistry.h" namespace ax { namespace { -void updateBlend(backend::BlendDescriptor& blendDescriptor, BlendFunc blendFunc) +void updateBlend(rhi::BlendDesc& blendDesc, BlendFunc blendFunc) { - blendDescriptor.blendEnabled = true; + blendDesc.blendEnabled = true; if (blendFunc == BlendFunc::ALPHA_NON_PREMULTIPLIED) { - blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::SRC_ALPHA; - blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceRGBBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDesc.destinationRGBBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceAlphaBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDesc.destinationAlphaBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } else { - blendDescriptor.sourceRGBBlendFactor = backend::BlendFactor::ONE; - blendDescriptor.destinationRGBBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor.sourceAlphaBlendFactor = backend::BlendFactor::ONE; - blendDescriptor.destinationAlphaBlendFactor = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceRGBBlendFactor = rhi::BlendFactor::ONE; + blendDesc.destinationRGBBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDesc.sourceAlphaBlendFactor = rhi::BlendFactor::ONE; + blendDesc.destinationAlphaBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } } } // namespace @@ -103,7 +103,7 @@ class LabelLetter : public Sprite CREATE_FUNC(LabelLetter); - virtual void updateTransform() override + void updateTransform() override { if (isDirty()) { @@ -136,10 +136,10 @@ class LabelLetter : public Sprite float dx = x1 * cr - y2 * sr2 + x; float dy = x1 * sr + y2 * cr2 + y; - _quad.bl.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(ax), SPRITE_RENDER_IN_SUBPIXEL(ay), _positionZ); - _quad.br.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(bx), SPRITE_RENDER_IN_SUBPIXEL(by), _positionZ); - _quad.tl.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(dx), SPRITE_RENDER_IN_SUBPIXEL(dy), _positionZ); - _quad.tr.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(cx), SPRITE_RENDER_IN_SUBPIXEL(cy), _positionZ); + _quad.bl.position.set(SPRITE_RENDER_IN_SUBPIXEL(ax), SPRITE_RENDER_IN_SUBPIXEL(ay), _positionZ); + _quad.br.position.set(SPRITE_RENDER_IN_SUBPIXEL(bx), SPRITE_RENDER_IN_SUBPIXEL(by), _positionZ); + _quad.tl.position.set(SPRITE_RENDER_IN_SUBPIXEL(dx), SPRITE_RENDER_IN_SUBPIXEL(dy), _positionZ); + _quad.tr.position.set(SPRITE_RENDER_IN_SUBPIXEL(cx), SPRITE_RENDER_IN_SUBPIXEL(cy), _positionZ); if (_textureAtlas) { @@ -153,30 +153,26 @@ class LabelLetter : public Sprite Node::updateTransform(); } - virtual void updateColor() override + void updateColor() override { if (_textureAtlas == nullptr) { return; } - auto displayedOpacity = _displayedOpacity; + Color color(_displayedColor); if (!_letterVisible) - { - displayedOpacity = 0.0f; - } - Color4B color4(_displayedColor.r, _displayedColor.g, _displayedColor.b, displayedOpacity); + color.a = 0.0f; + // special opacity for premultiplied textures if (_opacityModifyRGB) - { - color4.r *= displayedOpacity / 255.0f; - color4.g *= displayedOpacity / 255.0f; - color4.b *= displayedOpacity / 255.0f; - } - _quad.bl.colors = color4; - _quad.br.colors = color4; - _quad.tl.colors = color4; - _quad.tr.colors = color4; + color.premultiplyAlpha(); + + Color32 color32{color}; + _quad.bl.color = color32; + _quad.br.color = color32; + _quad.tl.color = color32; + _quad.tr.color = color32; _textureAtlas->updateQuad(_quad, _atlasIndex); } @@ -208,24 +204,24 @@ Label::BatchCommand::BatchCommand() Label::BatchCommand::~BatchCommand() { - AX_SAFE_RELEASE(textCommand.getPipelineDescriptor().programState); - AX_SAFE_RELEASE(shadowCommand.getPipelineDescriptor().programState); - AX_SAFE_RELEASE(outLineCommand.getPipelineDescriptor().programState); + AX_SAFE_RELEASE(textCommand.getPipelineDesc().programState); + AX_SAFE_RELEASE(shadowCommand.getPipelineDesc().programState); + AX_SAFE_RELEASE(outLineCommand.getPipelineDesc().programState); } -void Label::BatchCommand::setProgramState(backend::ProgramState* programState) +void Label::BatchCommand::setProgramState(rhi::ProgramState* programState) { assert(programState); - auto& programStateText = textCommand.getPipelineDescriptor().programState; + auto& programStateText = textCommand.getPipelineDesc().programState; AX_SAFE_RELEASE(programStateText); programStateText = programState->clone(); - auto& programStateShadow = shadowCommand.getPipelineDescriptor().programState; + auto& programStateShadow = shadowCommand.getPipelineDesc().programState; AX_SAFE_RELEASE(programStateShadow); programStateShadow = programState->clone(); - auto& programStateOutline = outLineCommand.getPipelineDescriptor().programState; + auto& programStateOutline = outLineCommand.getPipelineDesc().programState; AX_SAFE_RELEASE(programStateOutline); programStateOutline = programState->clone(); } @@ -360,17 +356,6 @@ Label* Label::createWithBMFont(std::string_view bmfontPath, return nullptr; } -#ifndef AX_CORE_PROFILE -Label* Label::createWithBMFont(std::string_view bmfontPath, - std::string_view text, - const TextHAlignment& hAlignment, - int maxLineWidth, - const Vec2& imageOffset) -{ - return createWithBMFont(bmfontPath, text, hAlignment, maxLineWidth, Rect(imageOffset.x, imageOffset.y, 0, 0), - false); -} -#endif Label* Label::createWithCharMap(std::string_view plistFile) { auto ret = new Label(); @@ -631,10 +616,11 @@ void Label::reset() _hAlignment = TextHAlignment::LEFT; _vAlignment = TextVAlignment::TOP; - _effectColorF = Color4F::BLACK; - _textColor = Color4B::WHITE; - _textColorF = Color4F::WHITE; - setColor(Color3B::WHITE); + _effectColor = Color::BLACK; + _textColor = Color::WHITE; + _textColor32 = Color32::WHITE; + + setColor(Color32::WHITE); _shadowDirty = false; _shadowEnabled = false; @@ -685,10 +671,10 @@ static Texture2D* _getTexture(Label* label) void Label::setVertexLayout() { - _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); + _programState->validateSharedVertexLayout(rhi::VertexLayoutType::Sprite); } -bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) +bool Label::setProgramState(rhi::ProgramState* programState, bool ownPS /*= false*/) { if (Node::setProgramState(programState, ownPS)) { @@ -700,7 +686,7 @@ bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= setVertexLayout(); - auto& quadPipeline = _quadCommand.getPipelineDescriptor(); + auto& quadPipeline = _quadCommand.getPipelineDesc(); quadPipeline.programState = _programState; return true; @@ -710,14 +696,14 @@ bool Label::setProgramState(backend::ProgramState* programState, bool ownPS /*= void Label::updateShaderProgram() { - uint32_t programType = backend::ProgramType::POSITION_TEXTURE_COLOR; + uint32_t programType = rhi::ProgramType::POSITION_TEXTURE_COLOR; if (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP) { auto texture = _getTexture(this); if (texture) { programType = - backend::ProgramStateRegistry::getInstance()->getProgramType(programType, texture->getSamplerFlags()); + ProgramStateRegistry::getInstance()->getProgramType(programType, texture->getSamplerFlags()); } } else @@ -726,26 +712,26 @@ void Label::updateShaderProgram() { case ax::LabelEffect::NORMAL: if (_useDistanceField) - programType = backend::ProgramType::LABEL_DISTANCE_NORMAL; + programType = rhi::ProgramType::LABEL_DISTANCE_NORMAL; else if (_useA8Shader) - programType = backend::ProgramType::LABEL_NORMAL; + programType = rhi::ProgramType::LABEL_NORMAL; else { auto texture = _getTexture(this); if (texture) { - programType = backend::ProgramStateRegistry::getInstance()->getProgramType( + programType = ProgramStateRegistry::getInstance()->getProgramType( programType, texture->getSamplerFlags()); } } break; case ax::LabelEffect::OUTLINE: programType = - _useDistanceField ? backend::ProgramType::LABEL_DISTANCE_OUTLINE : backend::ProgramType::LABLE_OUTLINE; + _useDistanceField ? rhi::ProgramType::LABEL_DISTANCE_OUTLINE : rhi::ProgramType::LABLE_OUTLINE; break; case ax::LabelEffect::GLOW: if (_useDistanceField) - programType = backend::ProgramType::LABLE_DISTANCE_GLOW; + programType = rhi::ProgramType::LABLE_DISTANCE_GLOW; break; default: return; @@ -759,7 +745,7 @@ void Label::updateShaderProgram() for (auto&& batch : _batchCommands) updateBatchCommand(batch); - auto& quadPipeline = _quadCommand.getPipelineDescriptor(); + auto& quadPipeline = _quadCommand.getPipelineDesc(); quadPipeline.programState = _programState; } @@ -771,11 +757,11 @@ void Label::updateBatchCommand(Label::BatchCommand& batch) void Label::updateUniformLocations() { - _mvpMatrixLocation = _programState->getUniformLocation(backend::Uniform::MVP_MATRIX); - _textureLocation = _programState->getUniformLocation(backend::Uniform::TEXTURE); - _textColorLocation = _programState->getUniformLocation(backend::Uniform::TEXT_COLOR); - _effectColorLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_COLOR); - _effectTypeLocation = _programState->getUniformLocation(backend::Uniform::EFFECT_TYPE); + _mvpMatrixLocation = _programState->getUniformLocation(rhi::Uniform::MVP_MATRIX); + _textureLocation = _programState->getUniformLocation(rhi::Uniform::TEXTURE); + _textColorLocation = _programState->getUniformLocation(rhi::Uniform::TEXT_COLOR); + _effectColorLocation = _programState->getUniformLocation(rhi::Uniform::EFFECT_COLOR); + _effectTypeLocation = _programState->getUniformLocation(rhi::Uniform::EFFECT_TYPE); } bool Label::setFontAtlas(FontAtlas* atlas, bool distanceFieldEnabled /* = false */, bool useA8Shader /* = false */) @@ -932,12 +918,7 @@ bool Label::setBMFontFilePath(std::string_view bmfontFilePath, std::string_view return true; } -#ifndef AX_CORE_PROFILE -bool Label::setBMFontFilePath(std::string_view bmfontFilePath, const Vec2& imageOffset, float fontSize) -{ - return setBMFontFilePath(bmfontFilePath, Rect(imageOffset.x, imageOffset.y, 0, 0), false); -} -#endif + void Label::setString(std::string_view text) { if (text.compare(_utf8Text)) @@ -946,7 +927,7 @@ void Label::setString(std::string_view text) _contentDirty = true; std::u32string utf32String; - if (StringUtils::UTF8ToUTF32(_utf8Text, utf32String)) + if (text_utils::UTF8ToUTF32(_utf8Text, utf32String)) { _utf32Text = utf32String; } @@ -1073,7 +1054,7 @@ void Label::updateLabelLetters() letterInfo.positionX + _fontScale * uvRect.size.width / 2 + _linesOffsetX[letterInfo.lineIndex]; auto py = letterInfo.positionY - _fontScale * uvRect.size.height / 2 + _letterOffsetY; letterSprite->setPosition(px, py); - letterSprite->setOpacity(_realOpacity); + letterSprite->setOpacity(_realColor.a); } else { @@ -1324,7 +1305,7 @@ bool Label::updateTTFConfigInternal(unsigned int mods) updateShaderProgram(); } } - + if (_fontConfig.italics) this->enableItalics(); if (_fontConfig.bold) @@ -1382,7 +1363,7 @@ void Label::scaleFontSize(float fontSize) } } -void Label::enableGlow(const Color4B& glowColor) +void Label::enableGlow(const Color32& glowColor) { if (_currentLabelType == LabelType::TTF) { @@ -1406,15 +1387,15 @@ void Label::enableGlow(const Color4B& glowColor) updateShaderProgram(); } _currLabelEffect = LabelEffect::GLOW; - _effectColorF.r = glowColor.r / 255.0f; - _effectColorF.g = glowColor.g / 255.0f; - _effectColorF.b = glowColor.b / 255.0f; - _effectColorF.a = glowColor.a / 255.0f; + _effectColor.r = glowColor.r / 255.0f; + _effectColor.g = glowColor.g / 255.0f; + _effectColor.b = glowColor.b / 255.0f; + _effectColor.a = glowColor.a / 255.0f; updateShaderProgram(); } } -void Label::enableOutline(const Color4B& outlineColor, int outlineSize /* = -1 */) +void Label::enableOutline(const Color32& outlineColor, int outlineSize /* = -1 */) { AXASSERT(_currentLabelType == LabelType::STRING_TEXTURE || _currentLabelType == LabelType::TTF, "Only supported system font and TTF!"); @@ -1423,14 +1404,14 @@ void Label::enableOutline(const Color4B& outlineColor, int outlineSize /* = -1 * { if (_currentLabelType == LabelType::TTF) { - _effectColorF.r = outlineColor.r / 255.0f; - _effectColorF.g = outlineColor.g / 255.0f; - _effectColorF.b = outlineColor.b / 255.0f; - _effectColorF.a = outlineColor.a / 255.0f; + _effectColor.r = outlineColor.r / 255.0f; + _effectColor.g = outlineColor.g / 255.0f; + _effectColor.b = outlineColor.b / 255.0f; + _effectColor.a = outlineColor.a / 255.0f; if (outlineSize > 0 && _fontConfig.outlineSize != outlineSize) { - + _fontConfig.outlineSize = outlineSize; setTTFConfig(_fontConfig); } @@ -1440,12 +1421,12 @@ void Label::enableOutline(const Color4B& outlineColor, int outlineSize /* = -1 * updateShaderProgram(); } } - else if (_effectColorF != outlineColor || _outlineSize != outlineSize) + else if (_effectColor != outlineColor || _outlineSize != outlineSize) { - _effectColorF.r = outlineColor.r / 255.f; - _effectColorF.g = outlineColor.g / 255.f; - _effectColorF.b = outlineColor.b / 255.f; - _effectColorF.a = outlineColor.a / 255.f; + _effectColor.r = outlineColor.r / 255.f; + _effectColor.g = outlineColor.g / 255.f; + _effectColor.b = outlineColor.b / 255.f; + _effectColor.a = outlineColor.a / 255.f; _currLabelEffect = LabelEffect::OUTLINE; _contentDirty = true; } @@ -1453,7 +1434,7 @@ void Label::enableOutline(const Color4B& outlineColor, int outlineSize /* = -1 * } } -void Label::enableShadow(const Color4B& shadowColor /* = Color4B::BLACK */, +void Label::enableShadow(const Color32& shadowColor /* = Color32::BLACK */, const Vec2& offset /* = Vec2(2 ,-2)*/, int /* blurRadius = 0 */) { @@ -1464,17 +1445,14 @@ void Label::enableShadow(const Color4B& shadowColor /* = Color4B::BLACK */, _shadowOffset.height = offset.height; // TODO: support blur for shadow - _shadowColor3B.r = shadowColor.r; - _shadowColor3B.g = shadowColor.g; - _shadowColor3B.b = shadowColor.b; - _shadowOpacity = shadowColor.a; + _shadowColor32 = shadowColor; if (!_systemFontDirty && !_contentDirty && _textSprite) { auto fontDef = _getFontDefinition(); if (_shadowNode) { - if (shadowColor != _shadowColor4F) + if (shadowColor != _shadowColor) { _shadowNode->release(); _shadowNode = nullptr; @@ -1491,10 +1469,10 @@ void Label::enableShadow(const Color4B& shadowColor /* = Color4B::BLACK */, } } - _shadowColor4F.r = shadowColor.r / 255.0f; - _shadowColor4F.g = shadowColor.g / 255.0f; - _shadowColor4F.b = shadowColor.b / 255.0f; - _shadowColor4F.a = shadowColor.a / 255.0f; + _shadowColor.r = shadowColor.r / 255.0f; + _shadowColor.g = shadowColor.g / 255.0f; + _shadowColor.b = shadowColor.b / 255.0f; + _shadowColor.a = shadowColor.a / 255.0f; if (_currentLabelType == LabelType::BMFONT || _currentLabelType == LabelType::CHARMAP) { @@ -1512,7 +1490,7 @@ void Label::enableBold() if (!_boldEnabled) { // bold is implemented with outline - enableShadow(Color4B::WHITE, Vec2(0.9f, 0), 0); + enableShadow(Color32::WHITE, Vec2(0.9f, 0), 0); // add one to kerning setAdditionalKerning(_additionalKerning + 1); _boldEnabled = true; @@ -1531,7 +1509,7 @@ void Label::enableUnderline() { _lineDrawNode = DrawNode::create(); _lineDrawNode->setGlobalZOrder(getGlobalZOrder()); - _lineDrawNode->setOpacity(_displayedOpacity); + _lineDrawNode->setOpacity(_displayedColor.a); _lineDrawNode->properties.setFactor(_lineDrawNode->properties.getFactor() * 2.0f); // 2.0f: Makes the line smaller addChild(_lineDrawNode, 100000); @@ -1550,7 +1528,7 @@ void Label::enableStrikethrough() { _lineDrawNode = DrawNode::create(); _lineDrawNode->setGlobalZOrder(getGlobalZOrder()); - _lineDrawNode->setOpacity(_displayedOpacity); + _lineDrawNode->setOpacity(_displayedColor.a); _lineDrawNode->properties.setFactor(_lineDrawNode->properties.getFactor() * 2.0f); // 2.0f: Makes the line smaller addChild(_lineDrawNode, 100000); @@ -1674,28 +1652,22 @@ void Label::createSpriteForSystemFont(const FontDefinition& fontDef) _textSprite->retain(); _textSprite->updateDisplayedColor(_displayedColor); - _textSprite->updateDisplayedOpacity(_displayedOpacity); } void Label::createShadowSpriteForSystemFont(const FontDefinition& fontDef) { - if (!fontDef._stroke._strokeEnabled && fontDef._fontFillColor == _shadowColor3B && - (fontDef._fontAlpha == _shadowOpacity)) + if (!fontDef._stroke._strokeEnabled && fontDef._fontFillColor == _shadowColor32) { _shadowNode = Sprite::createWithTexture(_textSprite->getTexture()); } else { - FontDefinition shadowFontDefinition = fontDef; - shadowFontDefinition._fontFillColor.r = _shadowColor3B.r; - shadowFontDefinition._fontFillColor.g = _shadowColor3B.g; - shadowFontDefinition._fontFillColor.b = _shadowColor3B.b; - shadowFontDefinition._fontAlpha = _shadowOpacity; + FontDefinition shadowFontDefinition = fontDef; + shadowFontDefinition._fontFillColor = _shadowColor32; shadowFontDefinition._stroke._strokeColor = shadowFontDefinition._fontFillColor; - shadowFontDefinition._stroke._strokeAlpha = shadowFontDefinition._fontAlpha; - auto texture = new Texture2D; + auto texture = new Texture2D(); texture->initWithString(_utf8Text, shadowFontDefinition); _shadowNode = Sprite::createWithTexture(texture); texture->release(); @@ -1714,7 +1686,6 @@ void Label::createShadowSpriteForSystemFont(const FontDefinition& fontDef) _shadowNode->retain(); _shadowNode->updateDisplayedColor(_displayedColor); - _shadowNode->updateDisplayedOpacity(_displayedOpacity); } } @@ -1754,7 +1725,7 @@ void Label::clearTextures() if (_fontAtlas) { std::u32string utf32String; - if (StringUtils::UTF8ToUTF32(_utf8Text, utf32String)) + if (text_utils::UTF8ToUTF32(_utf8Text, utf32String)) { _utf32Text = utf32String; } @@ -1784,9 +1755,9 @@ void Label::updateContent() if (_lineDrawNode) { - Color4B lineColor = Color4B(_displayedColor); - if (_textColor != Color4B::WHITE && _textColor != lineColor) - lineColor = _textColor; + Color32 lineColor = Color32(_displayedColor); + if (_textColor32 != Color32::WHITE && _textColor32 != lineColor) + lineColor = _textColor32; _lineDrawNode->clear(); @@ -1826,13 +1797,14 @@ void Label::updateContent() if (_strikethroughEnabled) { auto y = nextY - lineHeight / 2; - _lineDrawNode->drawLine(Vec2(startOffset, y), Vec2(endOffset, y), Color4F(lineColor), thickness); + _lineDrawNode->drawLine(Vec2(_linesOffsetX[i], y), Vec2(_linesWidth[i] + _linesOffsetX[i], y), + Color(lineColor), thickness); } if (_underlineEnabled) { auto y = nextY - lineHeight; - _lineDrawNode->drawLine(Vec2(startOffset, y), Vec2(endOffset, y), Color4F(lineColor), thickness); + _lineDrawNode->drawLine(Vec2(startOffset, y), Vec2(endOffset, y), Color(lineColor), thickness); } nextY -= lineHeight + lineSpacing; } @@ -1854,7 +1826,7 @@ void Label::updateContent() for (int i = 0; i < _numberOfLines; ++i) { float y = baseY + lineSize * i; - _lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color4F(lineColor), thickness); + _lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color(lineColor), thickness); } } @@ -1865,7 +1837,7 @@ void Label::updateContent() for (int i = 0; i < _numberOfLines; ++i) { float y = baseY + lineSize * i; - _lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color4F(lineColor), thickness); + _lineDrawNode->drawLine(Vec2(0.0f, y), Vec2(spriteSize.width, y), Color(lineColor), thickness); } } } @@ -1880,7 +1852,7 @@ void Label::updateContent() _debugDrawNode->clear(); Vec2 vertices[4] = {Vec2::ZERO, Vec2(_contentSize.width, 0.0f), Vec2(_contentSize.width, _contentSize.height), Vec2(0.0f, _contentSize.height)}; - _debugDrawNode->drawPoly(vertices, 4, true, Color4B::WHITE); + _debugDrawNode->drawPoly(vertices, 4, true, Color::WHITE); #endif } @@ -1913,7 +1885,7 @@ void Label::updateBuffer(TextureAtlas* textureAtlas, CustomCommand& customComman { if (textureAtlas->getTotalQuads() > customCommand.getVertexCapacity()) { - customCommand.createVertexBuffer((unsigned int)sizeof(V3F_C4B_T2F_Quad), + customCommand.createVertexBuffer((unsigned int)sizeof(V3F_T2F_C4B_Quad), (unsigned int)textureAtlas->getTotalQuads(), CustomCommand::BufferUsage::DYNAMIC); customCommand.createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, @@ -1921,7 +1893,7 @@ void Label::updateBuffer(TextureAtlas* textureAtlas, CustomCommand& customComman CustomCommand::BufferUsage::DYNAMIC); } customCommand.updateVertexBuffer(textureAtlas->getQuads(), - (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad))); + (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_T2F_C4B_Quad))); customCommand.updateIndexBuffer(textureAtlas->getIndices(), (unsigned int)(textureAtlas->getTotalQuads() * 6 * sizeof(unsigned short))); customCommand.setIndexDrawInfo(0, (unsigned int)(textureAtlas->getTotalQuads() * 6)); @@ -1940,7 +1912,7 @@ void Label::updateEffectUniforms(BatchCommand& batch, { updateBuffer(textureAtlas, batch.shadowCommand); auto shadowMatrix = matrixProjection * _shadowTransform; - batch.shadowCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, shadowMatrix.m, + batch.shadowCommand.getPipelineDesc().programState->setUniform(_mvpMatrixLocation, shadowMatrix.m, sizeof(shadowMatrix.m)); } @@ -1951,14 +1923,13 @@ void Label::updateEffectUniforms(BatchCommand& batch, case LabelEffect::OUTLINE: { int effectType = 0; - Vec4 effectColor(_effectColorF.r, _effectColorF.g, _effectColorF.b, _effectColorF.a); + Vec4 effectColor(_effectColor.r, _effectColor.g, _effectColor.b, _effectColor.a); // draw shadow if (_shadowEnabled) { effectType = 2; - Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - auto* programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; - programStateShadow->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); + auto* programStateShadow = batch.shadowCommand.getPipelineDesc().programState; + programStateShadow->setUniform(_effectColorLocation, &_shadowColor, sizeof(ax::Color)); programStateShadow->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); batch.shadowCommand.init(_globalZOrder); renderer->addCommand(&batch.shadowCommand); @@ -1967,8 +1938,8 @@ void Label::updateEffectUniforms(BatchCommand& batch, if (_useDistanceField) { // distance outline effectColor.w = _outlineSize > 0 ? _outlineSize : _fontConfig.outlineSize; - batch.textCommand.getPipelineDescriptor().programState->setUniform(_effectColorLocation, &effectColor, - sizeof(Vec4)); + batch.textCommand.getPipelineDesc().programState->setUniform(_effectColorLocation, &effectColor, + sizeof(ax::Color)); } else { @@ -1976,7 +1947,7 @@ void Label::updateEffectUniforms(BatchCommand& batch, { effectType = 1; updateBuffer(textureAtlas, batch.outLineCommand); - auto* programStateOutline = batch.outLineCommand.getPipelineDescriptor().programState; + auto* programStateOutline = batch.outLineCommand.getPipelineDesc().programState; programStateOutline->setUniform(_effectColorLocation, &effectColor, sizeof(Vec4)); programStateOutline->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); batch.outLineCommand.init(_globalZOrder); @@ -1986,7 +1957,7 @@ void Label::updateEffectUniforms(BatchCommand& batch, // draw text { effectType = 0; - auto* programStateText = batch.textCommand.getPipelineDescriptor().programState; + auto* programStateText = batch.textCommand.getPipelineDesc().programState; programStateText->setUniform(_effectColorLocation, &effectColor, sizeof(effectColor)); programStateText->setUniform(_effectTypeLocation, &effectType, sizeof(effectType)); @@ -1998,9 +1969,8 @@ void Label::updateEffectUniforms(BatchCommand& batch, { if (_shadowEnabled) { - Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - auto* programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; - programStateShadow->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); + auto* programStateShadow = batch.shadowCommand.getPipelineDesc().programState; + programStateShadow->setUniform(_textColorLocation, &_shadowColor, sizeof(Vec4)); batch.shadowCommand.init(_globalZOrder); renderer->addCommand(&batch.shadowCommand); } @@ -2011,16 +1981,14 @@ void Label::updateEffectUniforms(BatchCommand& batch, // draw shadow if (_shadowEnabled) { - Vec4 shadowColor = Vec4(_shadowColor4F.r, _shadowColor4F.g, _shadowColor4F.b, _shadowColor4F.a); - auto* programStateShadow = batch.shadowCommand.getPipelineDescriptor().programState; - programStateShadow->setUniform(_textColorLocation, &shadowColor, sizeof(Vec4)); - programStateShadow->setUniform(_effectColorLocation, &shadowColor, sizeof(Vec4)); + auto* programStateShadow = batch.shadowCommand.getPipelineDesc().programState; + programStateShadow->setUniform(_textColorLocation, &_shadowColor, sizeof(Vec4)); + programStateShadow->setUniform(_effectColorLocation, &_shadowColor, sizeof(Vec4)); batch.shadowCommand.init(_globalZOrder); renderer->addCommand(&batch.shadowCommand); } - Vec4 effectColor(_effectColorF.r, _effectColorF.g, _effectColorF.b, _effectColorF.a); - batch.textCommand.getPipelineDescriptor().programState->setUniform(_effectColorLocation, &effectColor, + batch.textCommand.getPipelineDesc().programState->setUniform(_effectColorLocation, &_effectColor, sizeof(Vec4)); } break; @@ -2032,16 +2000,16 @@ void Label::updateEffectUniforms(BatchCommand& batch, { if (_shadowEnabled) { - Color3B oldColor = _realColor; - uint8_t oldOPacity = _displayedOpacity; - _displayedOpacity = _shadowColor4F.a * (oldOPacity / 255.0f) * 255; - setColor(Color3B(_shadowColor4F)); + Color32 oldColor = _realColor; + uint8_t oldOPacity = _displayedColor.a; + _displayedColor.a = _shadowColor.a * (oldOPacity / 255.0f) * 255; + setColor(Color32{_shadowColor}); batch.shadowCommand.updateVertexBuffer( - textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_C4B_T2F_Quad))); + textureAtlas->getQuads(), (unsigned int)(textureAtlas->getTotalQuads() * sizeof(V3F_T2F_C4B_Quad))); batch.shadowCommand.init(_globalZOrder); renderer->addCommand(&batch.shadowCommand); - _displayedOpacity = oldOPacity; + _displayedColor.a = oldOPacity; setColor(oldColor); } } @@ -2089,7 +2057,7 @@ void Label::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) return; auto texture = textureAtlas->getTexture(); - auto& pipelineQuad = _quadCommand.getPipelineDescriptor(); + auto& pipelineQuad = _quadCommand.getPipelineDesc(); pipelineQuad.programState->setUniform(_mvpMatrixLocation, matrixProjection.m, sizeof(matrixProjection.m)); pipelineQuad.programState->setTexture(texture->getBackendTexture()); _quadCommand.init(_globalZOrder, texture, _blendFunc, textureAtlas->getQuads(), @@ -2123,14 +2091,13 @@ void Label::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) auto& batch = _batchCommands[i++]; for (auto&& command : batch.getCommandArray()) { - auto* programState = command->getPipelineDescriptor().programState; - Vec4 textColor(_textColorF.r, _textColorF.g, _textColorF.b, _textColorF.a); - programState->setUniform(_textColorLocation, &textColor, sizeof(Vec4)); + auto* programState = command->getPipelineDesc().programState; + programState->setUniform(_textColorLocation, &_textColor, sizeof(_textColor)); programState->setTexture(textureAtlas->getTexture()->getBackendTexture()); } - batch.textCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, + batch.textCommand.getPipelineDesc().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); - batch.outLineCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, + batch.outLineCommand.getPipelineDesc().programState->setUniform(_mvpMatrixLocation, matrixMVP.m, sizeof(matrixMVP.m)); updateEffectUniforms(batch, textureAtlas, renderer, transform); } @@ -2145,11 +2112,11 @@ void Label::updateBlendState() { for (auto&& command : batch.getCommandArray()) { - auto& blendDescriptor = command->getPipelineDescriptor().blendDescriptor; - updateBlend(blendDescriptor, _blendFunc); + auto& blendDesc = command->getPipelineDesc().blendDesc; + updateBlend(blendDesc, _blendFunc); } } - updateBlend(_quadCommand.getPipelineDescriptor().blendDescriptor, _blendFunc); + updateBlend(_quadCommand.getPipelineDesc().blendDesc, _blendFunc); } void Label::visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) @@ -2324,7 +2291,7 @@ Sprite* Label::getLetter(int letterIndex) letterInfo.positionX + _fontScale * uvRect.size.width / 2 + _linesOffsetX[letterInfo.lineIndex]; auto py = letterInfo.positionY - _fontScale * uvRect.size.height / 2 + _letterOffsetY; letter->setPosition(px, py); - letter->setOpacity(_realOpacity); + letter->setOpacity(_realColor.a); this->updateLetterSpriteScale(letter); } @@ -2404,7 +2371,7 @@ void Label::computeStringNumLines() size_t stringLen = _utf32Text.length(); for (size_t i = 0; i < stringLen - 1; ++i) { - if (_utf32Text[i] == StringUtils::UnicodeCharacters::NewLine) + if (_utf32Text[i] == text_utils::UnicodeCharacters::NewLine) { quantityOfLines++; } @@ -2444,7 +2411,7 @@ void Label::setOpacityModifyRGB(bool isOpacityModifyRGB) } } -void Label::updateDisplayedColor(const Color3B& parentColor) +void Label::updateDisplayedColor(const Color32& parentColor) { Node::updateDisplayedColor(parentColor); @@ -2480,21 +2447,21 @@ void Label::updateDisplayedOpacity(uint8_t parentOpacity) if (_textSprite) { - _textSprite->updateDisplayedOpacity(_displayedOpacity); + _textSprite->updateDisplayedOpacity(_displayedColor.a); if (_shadowNode) { - _shadowNode->updateDisplayedOpacity(_displayedOpacity); + _shadowNode->updateDisplayedOpacity(_displayedColor.a); } } for (auto&& it : _letters) { - it.second->updateDisplayedOpacity(_displayedOpacity); + it.second->updateDisplayedOpacity(_displayedColor.a); } if (_lineDrawNode) { - _lineDrawNode->setOpacity(_displayedOpacity); + _lineDrawNode->setOpacity(_displayedColor.a); _contentDirty = true; } } @@ -2502,9 +2469,9 @@ void Label::updateDisplayedOpacity(uint8_t parentOpacity) // FIXME: it is not clear what is the difference between setTextColor() and setColor() // if setTextColor() only changes the text and nothing but the text (no glow, no outline, not underline) // that's fine but it should be documented -void Label::setTextColor(const Color4B& color) +void Label::setTextColor(const Color32& color) { - if (_textColor != color) + if (_textColor32 != color) { switch (_currentLabelType) { @@ -2514,16 +2481,14 @@ void Label::setTextColor(const Color4B& color) _contentDirty = true; break; } + + _textColor = color; + _textColor32 = color; } - _textColor = color; - _textColorF.r = _textColor.r / 255.0f; - _textColorF.g = _textColor.g / 255.0f; - _textColorF.b = _textColor.b / 255.0f; - _textColorF.a = _textColor.a / 255.0f; // System font and TTF using setColor for Outline/Glow!"); if (_currentLabelType != LabelType::TTF && _currentLabelType != LabelType::STRING_TEXTURE) - setColor(Color3B(color)); + setColor(color); } void Label::updateColor() @@ -2533,30 +2498,26 @@ void Label::updateColor() return; } - Color4B color4(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity); + Color color(_displayedColor); // special opacity for premultiplied textures if (_isOpacityModifyRGB) - { - color4.r *= _displayedOpacity / 255.0f; - color4.g *= _displayedOpacity / 255.0f; - color4.b *= _displayedOpacity / 255.0f; - } + color.premultiplyAlpha(); + + Color32 color32{color}; - ax::TextureAtlas* textureAtlas; - V3F_C4B_T2F_Quad* quads; for (auto&& batchNode : _batchNodes) { - textureAtlas = batchNode->getTextureAtlas(); - quads = textureAtlas->getQuads(); - auto count = textureAtlas->getTotalQuads(); + auto textureAtlas = batchNode->getTextureAtlas(); + auto quads = textureAtlas->getQuads(); + auto count = textureAtlas->getTotalQuads(); for (int index = 0; index < count; ++index) { - quads[index].bl.colors = color4; - quads[index].br.colors = color4; - quads[index].tl.colors = color4; - quads[index].tr.colors = color4; + quads[index].bl.color = color32; + quads[index].br.color = color32; + quads[index].tl.color = color32; + quads[index].tr.color = color32; textureAtlas->updateQuad(quads[index], index); } } @@ -2633,10 +2594,7 @@ FontDefinition Label::_getFontDefinition() const systemFontDef._vertAlignment = _vAlignment; systemFontDef._dimensions.width = _labelWidth == 0.f ? _maxLineWidth : _labelWidth; systemFontDef._dimensions.height = _labelHeight; - systemFontDef._fontFillColor.r = _textColor.r; - systemFontDef._fontFillColor.g = _textColor.g; - systemFontDef._fontFillColor.b = _textColor.b; - systemFontDef._fontAlpha = _textColor.a; + systemFontDef._fontFillColor = _textColor32; systemFontDef._shadow._shadowEnabled = false; systemFontDef._enableWrap = _enableWrap; systemFontDef._overflow = (int)_overflow; @@ -2645,10 +2603,7 @@ FontDefinition Label::_getFontDefinition() const { systemFontDef._stroke._strokeEnabled = true; systemFontDef._stroke._strokeSize = _outlineSize; - systemFontDef._stroke._strokeColor.r = _effectColorF.r * 255; - systemFontDef._stroke._strokeColor.g = _effectColorF.g * 255; - systemFontDef._stroke._strokeColor.b = _effectColorF.b * 255; - systemFontDef._stroke._strokeAlpha = _effectColorF.a * 255; + systemFontDef._stroke._strokeColor = Color32{_effectColor}; } else { @@ -2834,9 +2789,9 @@ int Label::getFirstWordLen(const std::u32string& utf32Text, int startIndex, int { char32_t character = utf32Text[index]; - if (character == StringUtils::UnicodeCharacters::NewLine || - (!StringUtils::isUnicodeNonBreaking(character) && - (StringUtils::isUnicodeSpace(character) || StringUtils::isCJKUnicode(character)))) + if (character == text_utils::UnicodeCharacters::NewLine || + (!text_utils::isUnicodeNonBreaking(character) && + (text_utils::isUnicodeSpace(character) || text_utils::isCJKUnicode(character)))) { break; } @@ -2867,13 +2822,13 @@ int Label::getFirstWordLen(const std::u32string& utf32Text, int startIndex, int bool Label::getFontLetterDef(char32_t character, FontLetterDefinition& letterDef) const { - if (character == StringUtils::UnicodeCharacters::NoBreakSpace) + if (character == text_utils::UnicodeCharacters::NoBreakSpace) { // change no-break space to regular space // reason: some fonts have issue with no-break space: // * no letter definition // * not normal big width - character = StringUtils::UnicodeCharacters::Space; + character = text_utils::UnicodeCharacters::Space; } return _fontAtlas->getLetterDefinitionForChar(character, letterDef); @@ -2928,7 +2883,7 @@ bool Label::multilineTextWrap(bool breakOnChar, bool ignoreOverflow) for (int index = 0; index < textLen;) { char32_t character = _utf32Text[index]; - if (character == StringUtils::UnicodeCharacters::NewLine) + if (character == text_utils::UnicodeCharacters::NewLine) { _linesWidth.emplace_back(letterRight); letterRight = 0.f; @@ -2952,11 +2907,11 @@ bool Label::multilineTextWrap(bool breakOnChar, bool ignoreOverflow) (index + tokenLen) < textLen) { auto tokenLastChar = _utf32Text[index + tokenLen - 1]; - if (!StringUtils::isCJKUnicode(tokenLastChar) && !StringUtils::isUnicodeSpace(tokenLastChar)) + if (!text_utils::isCJKUnicode(tokenLastChar) && !text_utils::isUnicodeSpace(tokenLastChar)) { // Work out if this token is valid based on the desired output auto nextChar = _utf32Text[index + tokenLen]; - if (!StringUtils::isUnicodeSpace(nextChar) && !StringUtils::isCJKUnicode(nextChar)) + if (!text_utils::isUnicodeSpace(nextChar) && !text_utils::isCJKUnicode(nextChar)) { // No point continuing here return false; @@ -2975,14 +2930,14 @@ bool Label::multilineTextWrap(bool breakOnChar, bool ignoreOverflow) { int letterIndex = index + tmp; character = _utf32Text[letterIndex]; - if (character == StringUtils::UnicodeCharacters::CarriageReturn) + if (character == text_utils::UnicodeCharacters::CarriageReturn) { recordPlaceholderInfo(letterIndex, character); continue; } // \b - Next char not change x position - if (character == StringUtils::UnicodeCharacters::NextCharNoChangeX) + if (character == text_utils::UnicodeCharacters::NextCharNoChangeX) { nextChangeSize = false; recordPlaceholderInfo(letterIndex, character); @@ -2999,7 +2954,7 @@ bool Label::multilineTextWrap(bool breakOnChar, bool ignoreOverflow) auto letterX = (nextLetterX + letterDef.offsetX * _fontScale) / contentScaleFactor; if (_enableWrap && _maxLineWidth > 0.f && nextTokenX > 0.f && - letterX + letterDef.width * _fontScale > _maxLineWidth && !StringUtils::isUnicodeSpace(character) && + letterX + letterDef.width * _fontScale > _maxLineWidth && !text_utils::isUnicodeSpace(character) && nextChangeSize) { _linesWidth.emplace_back(letterRight - whitespaceWidth); @@ -3028,7 +2983,7 @@ bool Label::multilineTextWrap(bool breakOnChar, bool ignoreOverflow) nextLetterX += newLetterWidth; tokenRight = nextLetterX / contentScaleFactor; - if (StringUtils::isUnicodeSpace(character)) + if (text_utils::isUnicodeSpace(character)) { nextWhitespaceWidth += newLetterWidth / contentScaleFactor; } diff --git a/core/2d/Label.h b/axmol/2d/Label.h similarity index 87% rename from core/2d/Label.h rename to axmol/2d/Label.h index fa766fe7be9c..3e2cf7575ef0 100644 --- a/core/2d/Label.h +++ b/axmol/2d/Label.h @@ -27,12 +27,12 @@ #pragma once -#include "2d/Node.h" -#include "renderer/CustomCommand.h" -#include "renderer/QuadCommand.h" -#include "2d/FontAtlas.h" -#include "2d/FontFreeType.h" -#include "base/Types.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/2d/FontAtlas.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/base/Types.h" namespace ax { @@ -259,25 +259,6 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol int maxLineWidth, std::string_view subTextureKey); - /** - * Allocates and initializes a Label, with a bitmap font file. - * - * @param bmfontPath A bitmap font file, it's a FNT format. - * @param text The initial text. - * @param hAlignment Text horizontal alignment. - * @param maxLineWidth The max line width. - * @param imageOffset Offset into larger texture - * - * @return An automatically released Label object. - * @see setBMFontFilePath setMaxLineWidth - */ -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) static Label* createWithBMFont(std::string_view bmfontPath, - std::string_view text, - const TextHAlignment& hAlignment, - int maxLineWidth, - const Vec2& imageOffset); -#endif /** * Allocates and initializes a Label, with char map configuration. * @@ -340,12 +321,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol /** Sets a new bitmap font to Label */ virtual bool setBMFontFilePath(std::string_view bmfontFilePath, std::string_view subTextureKey, float fontSize = 0); -#ifndef AX_CORE_PROFILE - /** Sets a new bitmap font to Label */ - AX_DEPRECATED(2.1) virtual bool setBMFontFilePath(std::string_view bmfontFilePath, - const Vec2& imageOffset, - float fontSize = 0); -#endif + /** Returns the bitmap font used by the Label.*/ std::string_view getBMFontFilePath() const { return _bmFontPath; } @@ -396,10 +372,10 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol /// @} /** Sets the text that this Label is to display.*/ - virtual void setString(std::string_view text) override; + void setString(std::string_view text) override; /** Return the text the Label is currently displaying.*/ - virtual std::string_view getString() const override { return _utf8Text; } + std::string_view getString() const override { return _utf8Text; } /** * Return the number of lines of text. @@ -418,17 +394,17 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol * * @warning Limiting use to only when the Label created with true type font or system font. */ - virtual void setTextColor(const Color4B& color); + virtual void setTextColor(const Color32& color); /** Returns the text color of the Label.*/ - const Color4B& getTextColor() const { return _textColor; } + const Color32& getTextColor() const { return _textColor32; } /** * Enable shadow effect to Label. * * @todo Support blur for shadow effect. */ - virtual void enableShadow(const Color4B& shadowColor = Color4B::BLACK, + virtual void enableShadow(const Color32& shadowColor = Color32::BLACK, const Vec2& offset = Vec2(2, -2), int blurRadius = 0); @@ -436,13 +412,13 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol * Enable outline effect to Label. * @warning Limiting use to only when the Label created with true type font or system font. */ - virtual void enableOutline(const Color4B& outlineColor, int outlineSize = -1); + virtual void enableOutline(const Color32& outlineColor, int outlineSize = -1); /** * Enable glow effect to Label. * @warning Limiting use to only when the Label created with true type font. */ - virtual void enableGlow(const Color4B& glowColor); + virtual void enableGlow(const Color32& glowColor); /** * Enable italics rendering @@ -496,7 +472,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol /** * Return the shadow effect color value. */ - Color4F getShadowColor() const { return _shadowColor4F; } + Color getShadowColor() const { return _shadowColor; } /** * Return the outline effect size value. @@ -511,7 +487,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol /** * Return current effect color value. */ - Color4F getEffectColor() const { return _effectColorF; } + Color getEffectColor() const { return _effectColor; } /** Sets the Label's text horizontal alignment.*/ void setAlignment(TextHAlignment hAlignment) { setAlignment(hAlignment, _vAlignment); } @@ -682,31 +658,31 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol */ float getAdditionalKerning() const; - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; FontAtlas* getFontAtlas() { return _fontAtlas; } - virtual const BlendFunc& getBlendFunc() const override { return _blendFunc; } - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + const BlendFunc& getBlendFunc() const override { return _blendFunc; } + void setBlendFunc(const BlendFunc& blendFunc) override; - virtual bool isOpacityModifyRGB() const override { return _isOpacityModifyRGB; } - virtual void setOpacityModifyRGB(bool isOpacityModifyRGB) override; - virtual void updateDisplayedColor(const Color3B& parentColor) override; - virtual void updateDisplayedOpacity(uint8_t parentOpacity) override; + bool isOpacityModifyRGB() const override { return _isOpacityModifyRGB; } + void setOpacityModifyRGB(bool isOpacityModifyRGB) override; + void updateDisplayedColor(const Color32& parentColor) override; + void updateDisplayedOpacity(uint8_t parentOpacity) override; - virtual std::string getDescription() const override; + std::string getDescription() const override; - virtual const Vec2& getContentSize() const override; - virtual Rect getBoundingBox() const override; + const Vec2& getContentSize() const override; + Rect getBoundingBox() const override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void setCameraMask(unsigned short mask, bool applyChildren = true) override; + void setCameraMask(unsigned short mask, bool applyChildren = true) override; - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - virtual void removeChild(Node* child, bool cleanup = true) override; - virtual void setGlobalZOrder(float globalZOrder) override; + void removeAllChildrenWithCleanup(bool cleanup) override; + void removeChild(Node* child, bool cleanup = true) override; + void setGlobalZOrder(float globalZOrder) override; /** * Constructor of Label. @@ -754,7 +730,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol BatchCommand& operator=(const BatchCommand& rhs) = delete; BatchCommand& operator=(BatchCommand&& rhs) = default; - void setProgramState(backend::ProgramState* state); + void setProgramState(rhi::ProgramState* state); std::array getCommandArray(); @@ -799,10 +775,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol virtual void updateShaderProgram(); virtual void updateFontScale(); -#ifndef AX_CORE_PROFILE - /* DEPRECATED: use updateFontScale instead */ - AX_DEPRECATED(2.1) virtual void updateBMFontScale() { updateFontScale(); } -#endif + void scaleFontSize(float fontSize); bool setTTFConfigInternal(const TTFConfig& ttfConfig); bool updateTTFConfigInternal(unsigned int mods = 0); @@ -817,7 +790,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol FontDefinition _getFontDefinition() const; - virtual void updateColor() override; + void updateColor() override; void updateUniformLocations(); void setVertexLayout(); @@ -850,9 +823,8 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol bool _strikethroughEnabled; bool _underlineEnabled; bool _lineBreakWithoutSpaces; - uint8_t _shadowOpacity; - Color3B _shadowColor3B; + Color32 _shadowColor32; LabelType _currentLabelType; int _numberOfLines; @@ -887,7 +859,7 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol Overflow _overflow; float _originalFontSize; - Color4B _textColor; + Color32 _textColor32; BlendFunc _blendFunc; @@ -906,9 +878,9 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol Rect _bmRect; Rect _reusedRect; - Color4F _effectColorF; - Color4F _textColorF; - Color4F _shadowColor4F; + Color _effectColor; + Color _textColor; + Color _shadowColor; Mat4 _shadowTransform; std::u32string _utf32Text; @@ -939,11 +911,11 @@ class AX_DLL Label : public Node, public LabelProtocol, public BlendProtocol DrawNode* _debugDrawNode; #endif - backend::UniformLocation _mvpMatrixLocation; - backend::UniformLocation _textureLocation; - backend::UniformLocation _textColorLocation; - backend::UniformLocation _effectColorLocation; - backend::UniformLocation _effectTypeLocation; + rhi::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _textureLocation; + rhi::UniformLocation _textColorLocation; + rhi::UniformLocation _effectColorLocation; + rhi::UniformLocation _effectTypeLocation; private: AX_DISALLOW_COPY_AND_ASSIGN(Label); diff --git a/core/2d/LabelAtlas.cpp b/axmol/2d/LabelAtlas.cpp similarity index 80% rename from core/2d/LabelAtlas.cpp rename to axmol/2d/LabelAtlas.cpp index 611526016625..de37233d204e 100644 --- a/core/2d/LabelAtlas.cpp +++ b/axmol/2d/LabelAtlas.cpp @@ -25,14 +25,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/LabelAtlas.h" -#include "renderer/TextureAtlas.h" -#include "platform/FileUtils.h" -#include "base/Director.h" -#include "renderer/TextureCache.h" +#include "axmol/2d/LabelAtlas.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/TextureCache.h" #if AX_LABELATLAS_DEBUG_DRAW -# include "renderer/Renderer.h" +# include "axmol/renderer/Renderer.h" #endif namespace ax @@ -161,7 +161,7 @@ void LabelAtlas::updateAtlasValues() } AXASSERT(n <= _textureAtlas->getCapacity(), "updateAtlasValues: Invalid String length"); - V3F_C4B_T2F_Quad* quads = _textureAtlas->getQuads(); + auto quads = _textureAtlas->getQuads(); for (ssize_t i = 0; i < n; i++) { @@ -182,32 +182,32 @@ void LabelAtlas::updateAtlasValues() float bottom = top + itemHeightInPixels / textureHigh; #endif // ! AX_FIX_ARTIFACTS_BY_STRECHING_TEXEL - quads[i].tl.texCoords.u = left; - quads[i].tl.texCoords.v = top; - quads[i].tr.texCoords.u = right; - quads[i].tr.texCoords.v = top; - quads[i].bl.texCoords.u = left; - quads[i].bl.texCoords.v = bottom; - quads[i].br.texCoords.u = right; - quads[i].br.texCoords.v = bottom; - - quads[i].bl.vertices.x = (float)(i * _itemWidth); - quads[i].bl.vertices.y = 0; - quads[i].bl.vertices.z = 0.0f; - quads[i].br.vertices.x = (float)(i * _itemWidth + _itemWidth); - quads[i].br.vertices.y = 0; - quads[i].br.vertices.z = 0.0f; - quads[i].tl.vertices.x = (float)(i * _itemWidth); - quads[i].tl.vertices.y = (float)(_itemHeight); - quads[i].tl.vertices.z = 0.0f; - quads[i].tr.vertices.x = (float)(i * _itemWidth + _itemWidth); - quads[i].tr.vertices.y = (float)(_itemHeight); - quads[i].tr.vertices.z = 0.0f; - Color4B c(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity); - quads[i].tl.colors = c; - quads[i].tr.colors = c; - quads[i].bl.colors = c; - quads[i].br.colors = c; + quads[i].tl.texCoord.u = left; + quads[i].tl.texCoord.v = top; + quads[i].tr.texCoord.u = right; + quads[i].tr.texCoord.v = top; + quads[i].bl.texCoord.u = left; + quads[i].bl.texCoord.v = bottom; + quads[i].br.texCoord.u = right; + quads[i].br.texCoord.v = bottom; + + quads[i].bl.position.x = (float)(i * _itemWidth); + quads[i].bl.position.y = 0; + quads[i].bl.position.z = 0.0f; + quads[i].br.position.x = (float)(i * _itemWidth + _itemWidth); + quads[i].br.position.y = 0; + quads[i].br.position.z = 0.0f; + quads[i].tl.position.x = (float)(i * _itemWidth); + quads[i].tl.position.y = (float)(_itemHeight); + quads[i].tl.position.z = 0.0f; + quads[i].tr.position.x = (float)(i * _itemWidth + _itemWidth); + quads[i].tr.position.y = (float)(_itemHeight); + quads[i].tr.position.z = 0.0f; + const Color32& c = _displayedColor; + quads[i].tl.color = c; + quads[i].tr.color = c; + quads[i].bl.color = c; + quads[i].br.color = c; } if (n > 0) { @@ -248,21 +248,18 @@ void LabelAtlas::updateColor() { if (_textureAtlas) { - Color4B color4(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity); + Color color(_displayedColor); if (_isOpacityModifyRGB) - { - color4.r *= _displayedOpacity / 255.0f; - color4.g *= _displayedOpacity / 255.0f; - color4.b *= _displayedOpacity / 255.0f; - } + color.premultiplyAlpha(); + Color32 color32{color}; auto quads = _textureAtlas->getQuads(); ssize_t length = _string.length(); for (int index = 0; index < length; index++) { - quads[index].bl.colors = color4; - quads[index].br.colors = color4; - quads[index].tl.colors = color4; - quads[index].tr.colors = color4; + quads[index].bl.color = color32; + quads[index].br.color = color32; + quads[index].tl.color = color32; + quads[index].tr.color = color32; _textureAtlas->updateQuad(quads[index], index); } } @@ -277,7 +274,7 @@ void LabelAtlas::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) _debugDrawNode->clear(); auto size = getContentSize(); Vec2 vertices[4] = {Vec2::ZERO, Vec2(size.width, 0), Vec2(size.width, size.height), Vec2(0.0f, size.height)}; - _debugDrawNode->drawPoly(vertices, 4, true, Color4B::WHITE); + _debugDrawNode->drawPoly(vertices, 4, true, Color32::WHITE); } #endif diff --git a/core/2d/LabelAtlas.h b/axmol/2d/LabelAtlas.h similarity index 90% rename from core/2d/LabelAtlas.h rename to axmol/2d/LabelAtlas.h index 452ca1ece9ed..1fb661bc2ad3 100644 --- a/core/2d/LabelAtlas.h +++ b/axmol/2d/LabelAtlas.h @@ -27,10 +27,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/AtlasNode.h" +#include "axmol/2d/AtlasNode.h" #if AX_LABELATLAS_DEBUG_DRAW -# include "renderer/CustomCommand.h" -# include "2d/DrawNode.h" +# include "axmol/renderer/CustomCommand.h" +# include "axmol/2d/DrawNode.h" #endif namespace ax { @@ -98,16 +98,16 @@ class AX_DLL LabelAtlas : public AtlasNode, public LabelProtocol * starting char of the atlas */ bool initWithString(std::string_view string, Texture2D* texture, int itemWidth, int itemHeight, int startCharMap); - virtual void setString(std::string_view label) override; - virtual std::string_view getString() const override; + void setString(std::string_view label) override; + std::string_view getString() const override; - virtual void updateAtlasValues() override; + void updateAtlasValues() override; /** */ - virtual std::string getDescription() const override; + std::string getDescription() const override; #if AX_LABELATLAS_DEBUG_DRAW - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; #endif LabelAtlas() @@ -121,7 +121,7 @@ class AX_DLL LabelAtlas : public AtlasNode, public LabelProtocol virtual ~LabelAtlas() { _string.clear(); } protected: - virtual void updateColor() override; + void updateColor() override; #if AX_LABELATLAS_DEBUG_DRAW DrawNode* _debugDrawNode; diff --git a/core/2d/Layer.cpp b/axmol/2d/Layer.cpp similarity index 73% rename from core/2d/Layer.cpp rename to axmol/2d/Layer.cpp index 87da0ec1607f..0555bdfe78b5 100644 --- a/core/2d/Layer.cpp +++ b/axmol/2d/Layer.cpp @@ -28,23 +28,23 @@ THE SOFTWARE. ****************************************************************************/ #include -#include "2d/Layer.h" -#include "base/ScriptSupport.h" -#include "base/Utils.h" -#include "platform/Device.h" -#include "renderer/Renderer.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerTouch.h" -#include "base/EventTouch.h" -#include "base/EventKeyboard.h" -#include "base/EventListenerKeyboard.h" -#include "base/EventAcceleration.h" -#include "base/EventListenerAcceleration.h" -#include "base/UTF8.h" -#include "renderer/backend/Buffer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/2d/Layer.h" +#include "axmol/base/ScriptSupport.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/Device.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventTouch.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/EventAcceleration.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/text_utils.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -74,7 +74,7 @@ LayerColor* LayerColor::create() return ret; } -LayerColor* LayerColor::create(const Color4B& color, float width, float height) +LayerColor* LayerColor::create(const Color32& color, float width, float height) { LayerColor* layer = new LayerColor(); if (layer->initWithColor(color, width, height)) @@ -86,7 +86,7 @@ LayerColor* LayerColor::create(const Color4B& color, float width, float height) return nullptr; } -LayerColor* LayerColor::create(const Color4B& color) +LayerColor* LayerColor::create(const Color32& color) { LayerColor* layer = new LayerColor(); if (layer->initWithColor(color)) @@ -101,10 +101,10 @@ LayerColor* LayerColor::create(const Color4B& color) bool LayerColor::init() { Size s = _director->getWinSize(); - return initWithColor(Color4B(0, 0, 0, 0), s.width, s.height); + return initWithColor(Color32(0, 0, 0, 0), s.width, s.height); } -bool LayerColor::initWithColor(const Color4B& color, float w, float h) +bool LayerColor::initWithColor(const Color32& color, float w, float h) { if (Sprite::init()) { @@ -115,15 +115,14 @@ bool LayerColor::initWithColor(const Color4B& color, float w, float h) const Rect defaultRect{0.f, 0.f, 2.f, 2.f}; setTextureRect(defaultRect, false, defaultRect.size); setContentSize(Size(w, h)); - setColor(Color3B{color}); - setOpacity(color.a); + setColor(color); return true; } return false; } -bool LayerColor::initWithColor(const Color4B& color) +bool LayerColor::initWithColor(const Color32& color) { Size s = _director->getWinSize(); return initWithColor(color, s.width, s.height); @@ -151,7 +150,7 @@ LayerGradient::LayerGradient() {} LayerGradient::~LayerGradient() {} -LayerGradient* LayerGradient::create(const Color4B& start, const Color4B& end) +LayerGradient* LayerGradient::create(const Color32& start, const Color32& end) { LayerGradient* layer = new LayerGradient(); if (layer->initWithColor(start, end)) @@ -163,7 +162,7 @@ LayerGradient* LayerGradient::create(const Color4B& start, const Color4B& end) return nullptr; } -LayerGradient* LayerGradient::create(const Color4B& start, const Color4B& end, const Vec2& v) +LayerGradient* LayerGradient::create(const Color32& start, const Color32& end, const Vec2& v) { LayerGradient* layer = new LayerGradient(); if (layer->initWithColor(start, end, v)) @@ -191,27 +190,22 @@ LayerGradient* LayerGradient::create() bool LayerGradient::init() { - return initWithColor(Color4B(0, 0, 0, 255), Color4B(0, 0, 0, 255)); + return initWithColor(Color32(0, 0, 0, 255), Color32(0, 0, 0, 255)); } -bool LayerGradient::initWithColor(const Color4B& start, const Color4B& end) +bool LayerGradient::initWithColor(const Color32& start, const Color32& end) { return initWithColor(start, end, Vec2(0, -1)); } -bool LayerGradient::initWithColor(const Color4B& start, const Color4B& end, const Vec2& v) +bool LayerGradient::initWithColor(const Color32& start, const Color32& end, const Vec2& v) { - _endColor.r = end.r; - _endColor.g = end.g; - _endColor.b = end.b; - - _endOpacity = end.a; - _startOpacity = start.a; + _endColor = end; _alongVector = v; _compressedInterpolation = true; - return LayerColor::initWithColor(Color4B(start.r, start.g, start.b, 255)); + return LayerColor::initWithColor(start); } void LayerGradient::updateColor() @@ -230,33 +224,33 @@ void LayerGradient::updateColor() u = u * (h2 * (float)c); } - float opacityf = (float)_displayedOpacity / 255.0f; + float opacityf = (float)_displayedColor.a / 255.0f; - Color4F S(_displayedColor.r / 255.0f, _displayedColor.g / 255.0f, _displayedColor.b / 255.0f, - _startOpacity * opacityf / 255.0f); + Color S(_displayedColor.r / 255.f, _displayedColor.g / 255.f, _displayedColor.b / 255.f, + _startColor.a / 255.0f * opacityf); - Color4F E(_endColor.r / 255.0f, _endColor.g / 255.0f, _endColor.b / 255.0f, _endOpacity * opacityf / 255.0f); + Color E(_endColor.r / 255.f, _endColor.g / 255.f, _endColor.b / 255.f, _endColor.a / 255.0f * opacityf); // (-1, -1) - _quad.bl.colors.r = (E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c))) * 255; - _quad.bl.colors.g = (E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c))) * 255; - _quad.bl.colors.b = (E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c))) * 255; - _quad.bl.colors.a = (E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c))) * 255; + _quad.bl.color.r = (E.r + (S.r - E.r) * ((c + u.x + u.y) / (2.0f * c))) * 255; + _quad.bl.color.g = (E.g + (S.g - E.g) * ((c + u.x + u.y) / (2.0f * c))) * 255; + _quad.bl.color.b = (E.b + (S.b - E.b) * ((c + u.x + u.y) / (2.0f * c))) * 255; + _quad.bl.color.a = (E.a + (S.a - E.a) * ((c + u.x + u.y) / (2.0f * c))) * 255; // (1, -1) - _quad.br.colors.r = (E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c))) * 255; - _quad.br.colors.g = (E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c))) * 255; - _quad.br.colors.b = (E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c))) * 255; - _quad.br.colors.a = (E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c))) * 255; + _quad.br.color.r = (E.r + (S.r - E.r) * ((c - u.x + u.y) / (2.0f * c))) * 255; + _quad.br.color.g = (E.g + (S.g - E.g) * ((c - u.x + u.y) / (2.0f * c))) * 255; + _quad.br.color.b = (E.b + (S.b - E.b) * ((c - u.x + u.y) / (2.0f * c))) * 255; + _quad.br.color.a = (E.a + (S.a - E.a) * ((c - u.x + u.y) / (2.0f * c))) * 255; // (-1, 1) - _quad.tl.colors.r = (E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c))) * 255; - _quad.tl.colors.g = (E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c))) * 255; - _quad.tl.colors.b = (E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c))) * 255; - _quad.tl.colors.a = (E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c))) * 255; + _quad.tl.color.r = (E.r + (S.r - E.r) * ((c + u.x - u.y) / (2.0f * c))) * 255; + _quad.tl.color.g = (E.g + (S.g - E.g) * ((c + u.x - u.y) / (2.0f * c))) * 255; + _quad.tl.color.b = (E.b + (S.b - E.b) * ((c + u.x - u.y) / (2.0f * c))) * 255; + _quad.tl.color.a = (E.a + (S.a - E.a) * ((c + u.x - u.y) / (2.0f * c))) * 255; // (1, 1) - _quad.tr.colors.r = (E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c))) * 255; - _quad.tr.colors.g = (E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c))) * 255; - _quad.tr.colors.b = (E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c))) * 255; - _quad.tr.colors.a = (E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c))) * 255; + _quad.tr.color.r = (E.r + (S.r - E.r) * ((c - u.x - u.y) / (2.0f * c))) * 255; + _quad.tr.color.g = (E.g + (S.g - E.g) * ((c - u.x - u.y) / (2.0f * c))) * 255; + _quad.tr.color.b = (E.b + (S.b - E.b) * ((c - u.x - u.y) / (2.0f * c))) * 255; + _quad.tr.color.a = (E.a + (S.a - E.a) * ((c - u.x - u.y) / (2.0f * c))) * 255; // renders using batch node if (_renderMode == RenderMode::QUAD_BATCHNODE) @@ -270,47 +264,47 @@ void LayerGradient::updateColor() } } -const Color3B& LayerGradient::getStartColor() const +const Color32& LayerGradient::getStartColor() const { return _realColor; } -void LayerGradient::setStartColor(const Color3B& color) +void LayerGradient::setStartColor(const Color32& color) { setColor(color); } -void LayerGradient::setEndColor(const Color3B& color) +void LayerGradient::setEndColor(const Color32& color) { _endColor = color; updateColor(); } -const Color3B& LayerGradient::getEndColor() const +const Color32& LayerGradient::getEndColor() const { return _endColor; } void LayerGradient::setStartOpacity(uint8_t o) { - _startOpacity = o; + _startColor.a = o; updateColor(); } uint8_t LayerGradient::getStartOpacity() const { - return _startOpacity; + return _startColor.a; } void LayerGradient::setEndOpacity(uint8_t o) { - _endOpacity = o; + _endColor.a = o; updateColor(); } uint8_t LayerGradient::getEndOpacity() const { - return _endOpacity; + return _endColor.a; } void LayerGradient::setVector(const Vec2& var) @@ -343,8 +337,8 @@ std::string LayerGradient::getDescription() const /** * LayerRadialGradient */ -LayerRadialGradient* LayerRadialGradient::create(const Color4B& startColor, - const Color4B& endColor, +LayerRadialGradient* LayerRadialGradient::create(const Color32& startColor, + const Color32& endColor, float radius, const Vec2& center, float expand) @@ -363,7 +357,7 @@ LayerRadialGradient* LayerRadialGradient::create(const Color4B& startColor, LayerRadialGradient* LayerRadialGradient::create() { auto layerGradient = new LayerRadialGradient(); - if (layerGradient && layerGradient->initWithColor(Color4B::BLACK, Color4B::BLACK, 0, Vec2(0, 0), 0)) + if (layerGradient && layerGradient->initWithColor(Color32::BLACK, Color32::BLACK, 0, Vec2(0, 0), 0)) { layerGradient->autorelease(); return layerGradient; @@ -375,10 +369,10 @@ LayerRadialGradient* LayerRadialGradient::create() LayerRadialGradient::LayerRadialGradient() { - auto& pipelinePS = _customCommand.getPipelineDescriptor().programState; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::LAYER_RADIA_GRADIENT); + auto& pipelinePS = _customCommand.getPipelineDesc().programState; + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::LAYER_RADIA_GRADIENT); //!!! LayerRadialGradient private programState don't want affect by Node::_programState, so store at _customCommand - pipelinePS = new backend::ProgramState(program); + pipelinePS = new rhi::ProgramState(program); _mvpMatrixLocation = pipelinePS->getUniformLocation("u_MVPMatrix"); _startColorLocation = pipelinePS->getUniformLocation("u_startColor"); _endColorLocation = pipelinePS->getUniformLocation("u_endColor"); @@ -394,11 +388,11 @@ LayerRadialGradient::LayerRadialGradient() LayerRadialGradient::~LayerRadialGradient() { - AX_SAFE_RELEASE_NULL(_customCommand.getPipelineDescriptor().programState); + AX_SAFE_RELEASE_NULL(_customCommand.getPipelineDesc().programState); } -bool LayerRadialGradient::initWithColor(const ax::Color4B& startColor, - const ax::Color4B& endColor, +bool LayerRadialGradient::initWithColor(const ax::Color32& startColor, + const ax::Color32& endColor, float radius, const Vec2& center, float expand) @@ -409,10 +403,10 @@ bool LayerRadialGradient::initWithColor(const ax::Color4B& startColor, if (Node::initLayer()) { - convertColor4B24F(_startColorRend, startColor); + _startColorRend = static_cast(startColor); _startColor = startColor; - convertColor4B24F(_endColorRend, endColor); + _endColorRend = static_cast(endColor); _endColor = endColor; _expand = expand; @@ -432,7 +426,7 @@ void LayerRadialGradient::draw(Renderer* renderer, const Mat4& transform, uint32 renderer->addCommand(&_customCommand); const auto& projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = _customCommand.getPipelineDescriptor().programState; + auto programState = _customCommand.getPipelineDesc().programState; Mat4 finalMat = projectionMat * transform; programState->setUniform(_mvpMatrixLocation, finalMat.m, sizeof(finalMat.m)); @@ -506,48 +500,28 @@ float LayerRadialGradient::getExpand() const return _expand; } -void LayerRadialGradient::setStartColor(const Color3B& color) -{ - setStartColor(Color4B(color)); -} - -void LayerRadialGradient::setStartColor(const ax::Color4B& color) +void LayerRadialGradient::setStartColor(const ax::Color32& color) { _startColor = color; - convertColor4B24F(_startColorRend, _startColor); + _startColorRend = static_cast(color); } -Color4B LayerRadialGradient::getStartColor() const +Color32 LayerRadialGradient::getStartColor() const { return _startColor; } -Color3B LayerRadialGradient::getStartColor3B() const -{ - return Color3B(_startColor); -} - -void LayerRadialGradient::setEndColor(const Color3B& color) -{ - setEndColor(Color4B(color)); -} - -void LayerRadialGradient::setEndColor(const ax::Color4B& color) +void LayerRadialGradient::setEndColor(const ax::Color32& color) { _endColor = color; - convertColor4B24F(_endColorRend, _endColor); + _endColorRend = static_cast(color); } -Color4B LayerRadialGradient::getEndColor() const +Color32 LayerRadialGradient::getEndColor() const { return _endColor; } -Color3B LayerRadialGradient::getEndColor3B() const -{ - return Color3B(_endColor); -} - void LayerRadialGradient::setBlendFunc(const BlendFunc& blendFunc) { _blendFunc = blendFunc; @@ -558,14 +532,6 @@ const BlendFunc& LayerRadialGradient::getBlendFunc() const return _blendFunc; } -void LayerRadialGradient::convertColor4B24F(Color4F& outColor, const Color4B& inColor) -{ - outColor.r = inColor.r / 255.0f; - outColor.g = inColor.g / 255.0f; - outColor.b = inColor.b / 255.0f; - outColor.a = inColor.a / 255.0f; -} - /// MultiplexLayer LayerMultiplex::LayerMultiplex() : _enabledLayer(0) {} diff --git a/core/2d/Layer.h b/axmol/2d/Layer.h similarity index 82% rename from core/2d/Layer.h rename to axmol/2d/Layer.h index 4bb4dd689710..281bfe26a8ad 100644 --- a/core/2d/Layer.h +++ b/axmol/2d/Layer.h @@ -26,10 +26,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "2d/Sprite.h" -#include "base/Protocols.h" -#include "renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/Protocols.h" +#include "axmol/renderer/CustomCommand.h" #include @@ -73,13 +73,13 @@ class AX_DLL LayerColor : public Sprite * @param height The height of layer. * @return An autoreleased LayerColor object. */ - static LayerColor * create(const Color4B& color, float width, float height); + static LayerColor * create(const Color32& color, float width, float height); /** Creates a Layer with color. Width and height are the window size. * * @param color The color of layer. * @return An autoreleased LayerColor object. */ - static LayerColor * create(const Color4B& color); + static LayerColor * create(const Color32& color); /** Change width in Points. * @@ -100,8 +100,8 @@ class AX_DLL LayerColor : public Sprite void changeWidthAndHeight(float w, float h); LayerColor(); bool init() override; - bool initWithColor(const Color4B& color, float width, float height); - bool initWithColor(const Color4B& color); + bool initWithColor(const Color32& color, float width, float height); + bool initWithColor(const Color32& color); private: AX_DISALLOW_COPY_AND_ASSIGN(LayerColor); @@ -146,7 +146,7 @@ class AX_DLL LayerGradient : public LayerColor * @param end The end color. * @return An autoreleased LayerGradient object. */ - static LayerGradient* create(const Color4B& start, const Color4B& end); + static LayerGradient* create(const Color32& start, const Color32& end); /** Creates a full-screen Layer with a gradient between start and end in the direction of v. * @@ -155,7 +155,7 @@ class AX_DLL LayerGradient : public LayerColor * @param v The direction of gradient color. * @return An autoreleased LayerGradient object. */ - static LayerGradient* create(const Color4B& start, const Color4B& end, const Vec2& v); + static LayerGradient* create(const Color32& start, const Color32& end, const Vec2& v); /** Whether or not the interpolation will be compressed in order to display all the colors of the gradient both in canonical and non canonical vectors. Default: true. @@ -173,23 +173,23 @@ class AX_DLL LayerGradient : public LayerColor * * @param startColor The start color. */ - void setStartColor(const Color3B& startColor); + void setStartColor(const Color32& startColor); /** Returns the start color of the gradient. * * @return The start color. */ - const Color3B& getStartColor() const; + const Color32& getStartColor() const; /** Sets the end color of the gradient. * * @param endColor The end color. */ - void setEndColor(const Color3B& endColor); + void setEndColor(const Color32& endColor); /** Returns the end color of the gradient. * * @return The end color. */ - const Color3B& getEndColor() const; + const Color32& getEndColor() const; /** Returns the start opacity of the gradient. * @@ -225,29 +225,27 @@ class AX_DLL LayerGradient : public LayerColor */ const Vec2& getVector() const; - virtual std::string getDescription() const override; + std::string getDescription() const override; LayerGradient(); virtual ~LayerGradient(); - virtual bool init() override; + bool init() override; /** Initializes the Layer with a gradient between start and end. * @lua init */ - bool initWithColor(const Color4B& start, const Color4B& end); + bool initWithColor(const Color32& start, const Color32& end); /** Initializes the Layer with a gradient between start and end in the direction of v. * @lua init */ - bool initWithColor(const Color4B& start, const Color4B& end, const Vec2& v); + bool initWithColor(const Color32& start, const Color32& end, const Vec2& v); protected: - virtual void updateColor() override; + void updateColor() override; - Color3B _startColor = Color3B::BLACK; - Color3B _endColor = Color3B::BLACK; - uint8_t _startOpacity = 255; - uint8_t _endOpacity = 255; + Color32 _startColor = Color32::BLACK; + Color32 _endColor = Color32::BLACK; Vec2 _alongVector = {0.0f, -1.0f}; bool _compressedInterpolation = true; }; @@ -267,8 +265,8 @@ class AX_DLL LayerRadialGradient : public Node, BlendProtocol * @param expand an alpha value(0.f-1.f) that specifies how much of that radius in only inner color(the gradient starts outside of that amount) */ - static LayerRadialGradient* create(const Color4B& startColor, - const Color4B& endColor, + static LayerRadialGradient* create(const Color32& startColor, + const Color32& endColor, float radius, const Vec2& center, float expand); @@ -277,8 +275,8 @@ class AX_DLL LayerRadialGradient : public Node, BlendProtocol // // overrides // - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void setContentSize(const Vec2& size) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void setContentSize(const Vec2& size) override; void setStartOpacity(uint8_t opacity); uint8_t getStartOpacity() const; @@ -295,15 +293,11 @@ class AX_DLL LayerRadialGradient : public Node, BlendProtocol void setExpand(float expand); float getExpand() const; - void setStartColor(const Color3B& color); - void setStartColor(const Color4B& color); - Color4B getStartColor() const; - Color3B getStartColor3B() const; + void setStartColor(const Color32& color); + Color32 getStartColor() const; - void setEndColor(const Color3B& color); - void setEndColor(const Color4B& color); - Color4B getEndColor() const; - Color3B getEndColor3B() const; + void setEndColor(const Color32& color); + Color32 getEndColor() const; void setBlendFunc(const BlendFunc& blendFunc) override; const BlendFunc& getBlendFunc() const override; @@ -311,20 +305,18 @@ class AX_DLL LayerRadialGradient : public Node, BlendProtocol LayerRadialGradient(); virtual ~LayerRadialGradient(); - bool initWithColor(const Color4B& startColor, - const Color4B& endColor, + bool initWithColor(const Color32& startColor, + const Color32& endColor, float radius, const Vec2& center, float expand); private: - void convertColor4B24F(Color4F& outColor, const Color4B& inColor); - - Color4B _startColor = Color4B::BLACK; - Color4F _startColorRend = Color4F::BLACK; // start color used in shader + Color32 _startColor = Color32::BLACK; + Color _startColorRend = Color::BLACK; // start color used in shader - Color4B _endColor = Color4B::BLACK; - Color4F _endColorRend = Color4F::BLACK; // end color used in shader + Color32 _endColor = Color32::BLACK; + Color _endColorRend = Color::BLACK; // end color used in shader Vec2 _vertices[4]; Vec2 _center; @@ -334,12 +326,12 @@ class AX_DLL LayerRadialGradient : public Node, BlendProtocol BlendFunc _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; - backend::UniformLocation _mvpMatrixLocation; - backend::UniformLocation _startColorLocation; - backend::UniformLocation _endColorLocation; - backend::UniformLocation _centerLocation; - backend::UniformLocation _radiusLocation; - backend::UniformLocation _expandLocation; + rhi::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _startColorLocation; + rhi::UniformLocation _endColorLocation; + rhi::UniformLocation _centerLocation; + rhi::UniformLocation _radiusLocation; + rhi::UniformLocation _expandLocation; }; /** @class LayerMultiplex @@ -407,7 +399,7 @@ class AX_DLL LayerMultiplex : public Node */ void switchToAndReleaseMe(int n); - virtual std::string getDescription() const override; + std::string getDescription() const override; /** */ @@ -417,7 +409,7 @@ class AX_DLL LayerMultiplex : public Node */ virtual ~LayerMultiplex(); - virtual bool init() override; + bool init() override; /** initializes a MultiplexLayer with one or more layers using a variable argument list. * @lua NA */ diff --git a/core/2d/Light.cpp b/axmol/2d/Light.cpp similarity index 94% rename from core/2d/Light.cpp rename to axmol/2d/Light.cpp index eb84265b89a9..f56137a59147 100644 --- a/core/2d/Light.cpp +++ b/axmol/2d/Light.cpp @@ -1,5 +1,6 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -22,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/Light.h" -#include "2d/Scene.h" +#include "axmol/2d/Light.h" +#include "axmol/2d/Scene.h" namespace ax { @@ -71,7 +72,7 @@ BaseLight::BaseLight() : _intensity(1.0f), _lightFlag(LightFlag::LIGHT0), _enabl BaseLight::~BaseLight() {} //////////////////////////////////////////////////////////////////// -DirectionLight* DirectionLight::create(const Vec3& direction, const Color3B& color) +DirectionLight* DirectionLight::create(const Vec3& direction, const Color32& color) { auto light = new DirectionLight(); light->setRotationFromDirection(direction); @@ -98,7 +99,7 @@ DirectionLight::DirectionLight() {} DirectionLight::~DirectionLight() {} ////////////////////////////////////////////////////////////////// -PointLight* PointLight::create(const Vec3& position, const Color3B& color, float range) +PointLight* PointLight::create(const Vec3& position, const Color32& color, float range) { auto light = new PointLight(); light->setPosition3D(position); @@ -114,7 +115,7 @@ PointLight::~PointLight() {} ////////////////////////////////////////////////////////////// SpotLight* SpotLight::create(const Vec3& direction, const Vec3& position, - const Color3B& color, + const Color32& color, float innerAngle, float outerAngle, float range) @@ -165,7 +166,7 @@ SpotLight::~SpotLight() {} ///////////////////////////////////////////////////////////// -AmbientLight* AmbientLight::create(const Color3B& color) +AmbientLight* AmbientLight::create(const Color32& color) { auto light = new AmbientLight(); light->setColor(color); @@ -177,4 +178,4 @@ AmbientLight::AmbientLight() {} AmbientLight::~AmbientLight() {} -} \ No newline at end of file +} diff --git a/core/2d/Light.h b/axmol/2d/Light.h similarity index 91% rename from core/2d/Light.h rename to axmol/2d/Light.h index 7e60655a05e6..14bf4cb6c4c0 100644 --- a/core/2d/Light.h +++ b/axmol/2d/Light.h @@ -1,6 +1,7 @@ /**************************************************************************** Copyright (c) 2014-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,7 +26,7 @@ #pragma once -#include "2d/Node.h" +#include "axmol/2d/Node.h" namespace ax { @@ -84,8 +85,8 @@ class AX_DLL BaseLight : public Node bool isEnabled() const { return _enabled; } // override - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; BaseLight(); virtual ~BaseLight(); @@ -111,10 +112,10 @@ class AX_DLL DirectionLight : public BaseLight * * @return The new direction light. */ - static DirectionLight* create(const Vec3& direction, const Color3B& color); + static DirectionLight* create(const Vec3& direction, const Color32& color); // get light type - virtual LightType getLightType() const override { return LightType::DIRECTIONAL; } + LightType getLightType() const override { return LightType::DIRECTIONAL; } /** * Sets the Direction in parent. @@ -150,10 +151,10 @@ class AX_DLL PointLight : public BaseLight * * @return The new point light. */ - static PointLight* create(const Vec3& position, const Color3B& color, float range); + static PointLight* create(const Vec3& position, const Color32& color, float range); // get light type - virtual LightType getLightType() const override { return LightType::POINT; } + LightType getLightType() const override { return LightType::POINT; } /** get or set range */ float getRange() const { return _range; } @@ -184,13 +185,13 @@ class AX_DLL SpotLight : public BaseLight */ static SpotLight* create(const Vec3& direction, const Vec3& position, - const Color3B& color, + const Color32& color, float innerAngle, float outerAngle, float range); // get light type - virtual LightType getLightType() const override { return LightType::SPOT; } + LightType getLightType() const override { return LightType::SPOT; } /** * Sets the Direction in parent. @@ -274,10 +275,10 @@ class AX_DLL AmbientLight : public BaseLight * * @return The new ambient light. */ - static AmbientLight* create(const Color3B& color); + static AmbientLight* create(const Color32& color); // get light type - virtual LightType getLightType() const override { return LightType::AMBIENT; } + LightType getLightType() const override { return LightType::AMBIENT; } AmbientLight(); virtual ~AmbientLight(); diff --git a/core/2d/Menu.cpp b/axmol/2d/Menu.cpp similarity index 98% rename from core/2d/Menu.cpp rename to axmol/2d/Menu.cpp index 0eb4e1d03bbe..315f0e8d1d7c 100644 --- a/core/2d/Menu.cpp +++ b/axmol/2d/Menu.cpp @@ -25,14 +25,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Menu.h" -#include "2d/Camera.h" -#include "base/Director.h" -#include "base/Touch.h" -#include "base/EventListenerTouch.h" -#include "base/EventDispatcher.h" -#include "base/UTF8.h" -#include "platform/StdC.h" +#include "axmol/2d/Menu.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/Director.h" +#include "axmol/base/Touch.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/text_utils.h" +#include "axmol/platform/StdC.h" #include diff --git a/core/2d/Menu.h b/axmol/2d/Menu.h similarity index 88% rename from core/2d/Menu.h rename to axmol/2d/Menu.h index 82fae7f57a50..c7a1be6516d7 100644 --- a/core/2d/Menu.h +++ b/axmol/2d/Menu.h @@ -27,9 +27,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/MenuItem.h" -#include "2d/Layer.h" -#include "base/Value.h" +#include "axmol/2d/MenuItem.h" +#include "axmol/2d/Layer.h" +#include "axmol/base/Value.h" namespace ax { @@ -139,19 +139,19 @@ class AX_DLL Menu : public Node virtual void onTouchMoved(Touch* touch, Event* event); // overrides - virtual void removeChild(Node* child, bool cleanup) override; + void removeChild(Node* child, bool cleanup) override; - virtual void addChild(Node* child) override; - virtual void addChild(Node* child, int zOrder) override; - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; + void addChild(Node* child) override; + void addChild(Node* child, int zOrder) override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void onEnter() override; - virtual void onExit() override; - virtual void setOpacityModifyRGB(bool value) override; - virtual bool isOpacityModifyRGB() const override; + void onEnter() override; + void onExit() override; + void setOpacityModifyRGB(bool value) override; + bool isOpacityModifyRGB() const override; - virtual std::string getDescription() const override; + std::string getDescription() const override; /** */ diff --git a/core/2d/MenuItem.cpp b/axmol/2d/MenuItem.cpp similarity index 98% rename from core/2d/MenuItem.cpp rename to axmol/2d/MenuItem.cpp index fdb4be393c50..8cdd831b9f94 100644 --- a/core/2d/MenuItem.cpp +++ b/axmol/2d/MenuItem.cpp @@ -27,12 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/MenuItem.h" -#include "2d/ActionInterval.h" -#include "2d/Sprite.h" -#include "2d/LabelAtlas.h" -#include "2d/Label.h" -#include "base/UTF8.h" +#include "axmol/2d/MenuItem.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/LabelAtlas.h" +#include "axmol/2d/Label.h" +#include "axmol/base/text_utils.h" #include namespace ax @@ -184,8 +184,8 @@ bool MenuItemLabel::initWithLabel(Node* label, const ccMenuCallback& callback) { MenuItem::initWithCallback(callback); _originalScale = 1.0f; - _colorBackup = Color3B::WHITE; - setDisabledColor(Color3B(126, 126, 126)); + _colorBackup = Color32::WHITE; + setDisabledColor(Color32(126, 126, 126, 255)); this->setLabel(label); setCascadeColorEnabled(true); diff --git a/core/2d/MenuItem.h b/axmol/2d/MenuItem.h similarity index 96% rename from core/2d/MenuItem.h rename to axmol/2d/MenuItem.h index 7ca2729d58a9..4da93e0ba2cd 100644 --- a/core/2d/MenuItem.h +++ b/axmol/2d/MenuItem.h @@ -33,8 +33,8 @@ THE SOFTWARE. #include // axmol includes -#include "2d/Node.h" -#include "base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Protocols.h" namespace ax { @@ -95,7 +95,7 @@ class AX_DLL MenuItem : public Node /** */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** */ @@ -148,10 +148,10 @@ class AX_DLL MenuItemLabel : public MenuItem std::string_view getString() const; /** Gets the color that will be used when the item is disabled. */ - const Color3B& getDisabledColor() const { return _disabledColor; } + const Color32& getDisabledColor() const { return _disabledColor; } /** Sets the color that will be used when the item is disabled. */ - void setDisabledColor(const Color3B& color) { _disabledColor = color; } + void setDisabledColor(const Color32& color) { _disabledColor = color; } /** Gets the label that is rendered. */ Node* getLabel() const { return _label; } @@ -160,10 +160,10 @@ class AX_DLL MenuItemLabel : public MenuItem void setLabel(Node* node); // Overrides - virtual void activate() override; - virtual void selected() override; - virtual void unselected() override; - virtual void setEnabled(bool enabled) override; + void activate() override; + void selected() override; + void unselected() override; + void setEnabled(bool enabled) override; /** */ @@ -177,11 +177,11 @@ class AX_DLL MenuItemLabel : public MenuItem bool initWithLabel(Node* label, const ccMenuCallback& callback); protected: - Color3B _colorBackup; + Color32 _colorBackup; float _originalScale; /** The color that will be used to disable the item. */ - Color3B _disabledColor; + Color32 _disabledColor; /** Label that is rendered. It can be any Node that implements the LabelProtocol. */ Node* _label; @@ -463,11 +463,11 @@ class AX_DLL MenuItemToggle : public MenuItem void setSubItems(const Vector& items) { _subItems = items; } // Overrides - virtual void activate() override; - virtual void selected() override; - virtual void unselected() override; - virtual void setEnabled(bool var) override; - virtual void cleanup() override; + void activate() override; + void selected() override; + void unselected() override; + void setEnabled(bool var) override; + void cleanup() override; /** */ diff --git a/core/2d/MotionStreak.cpp b/axmol/2d/MotionStreak.cpp similarity index 64% rename from core/2d/MotionStreak.cpp rename to axmol/2d/MotionStreak.cpp index 9f4187ec323a..387301aed040 100644 --- a/core/2d/MotionStreak.cpp +++ b/axmol/2d/MotionStreak.cpp @@ -3,6 +3,7 @@ Copyright (c) 2011 ForzeField Studios S.L. Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -24,15 +25,15 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/MotionStreak.h" -#include "math/Vertex.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "renderer/TextureCache.h" -#include "renderer/Texture2D.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/2d/MotionStreak.h" +#include "axmol/math/Vertex.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -48,12 +49,9 @@ MotionStreak::~MotionStreak() AX_SAFE_RELEASE(_texture); AX_SAFE_FREE(_pointState); AX_SAFE_FREE(_pointVertexes); - AX_SAFE_FREE(_vertices); - AX_SAFE_FREE(_colorPointer); - AX_SAFE_FREE(_texCoords); } -MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path) +MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const Color32& color, std::string_view path) { MotionStreak* ret = new MotionStreak(); if (ret->initWithFade(fade, minSeg, stroke, color, path)) @@ -66,7 +64,7 @@ MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const return nullptr; } -MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture) +MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture) { MotionStreak* ret = new MotionStreak(); if (ret->initWithFade(fade, minSeg, stroke, color, texture)) @@ -79,7 +77,7 @@ MotionStreak* MotionStreak::create(float fade, float minSeg, float stroke, const return nullptr; } -bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path) +bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Color32& color, std::string_view path) { AXASSERT(!path.empty(), "Invalid filename"); @@ -87,7 +85,7 @@ bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Co return initWithFade(fade, minSeg, stroke, color, texture); } -bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture) +bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture) { Node::setPosition(Vec2::ZERO); setAnchorPoint(Vec2::ZERO); @@ -113,16 +111,14 @@ bool MotionStreak::initWithFade(float fade, float minSeg, float stroke, const Co _pointState = (float*)malloc(sizeof(float) * _maxPoints); _pointVertexes = (Vec2*)malloc(sizeof(Vec2) * _maxPoints); - const size_t VERTEX_SIZE = sizeof(Vec2) + sizeof(Tex2F) + sizeof(uint8_t) * 4; + constexpr size_t vertexSize = sizeof(_vertices[0]); - _vertexCount = _maxPoints * 2; - _vertices = (Vec2*)malloc(sizeof(Vec2) * _vertexCount); - _texCoords = (Tex2F*)malloc(sizeof(Tex2F) * _vertexCount); - _colorPointer = (uint8_t*)malloc(sizeof(uint8_t) * 4 * _vertexCount); - _customCommand.createVertexBuffer(VERTEX_SIZE, _vertexCount, CustomCommand::BufferUsage::DYNAMIC); + auto vertexCount = _maxPoints * 2; + _vertices.resize(vertexCount); + memset(_vertices.data(), 0, sizeof(_vertices[0]) * vertexCount); + _customCommand.createVertexBuffer(vertexSize, vertexCount, CustomCommand::BufferUsage::DYNAMIC); - auto zeros = std::make_unique(VERTEX_SIZE * _vertexCount); - _customCommand.updateVertexBuffer(zeros.get(), VERTEX_SIZE * _vertexCount); + _customCommand.updateVertexBuffer(_vertices.data(), vertexSize * vertexCount); setTexture(texture); setColor(color); @@ -194,14 +190,14 @@ void MotionStreak::setPositionY(float y) _positionR.y = y; } -void MotionStreak::tintWithColor(const Color3B& colors) +void MotionStreak::tintWithColor(const Color32& color) { - setColor(colors); + setColor(color); // Fast assignation - for (unsigned int i = 0; i < _nuPoints * 2; i++) + for (unsigned int i = 0; i < _nuPoints * 2; ++i) { - *((Color3B*)(_colorPointer + i * 4)) = colors; + _vertices[i].color = color; } } @@ -212,48 +208,52 @@ Texture2D* MotionStreak::getTexture() const void MotionStreak::setTexture(Texture2D* texture) { + if (texture == nullptr) + texture = _director->getTextureCache()->getWhiteTexture(); + if (_texture != texture) { AX_SAFE_RETAIN(texture); AX_SAFE_RELEASE(_texture); _texture = texture; - setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, _texture); + setProgramStateWithRegistry(rhi::ProgramType::TRAIL_2D, _texture); } } -bool MotionStreak::setProgramState(backend::ProgramState* programState, bool ownPS /*= false*/) +bool MotionStreak::setProgramState(rhi::ProgramState* programState, bool ownPS /*= false*/) { if (Node::setProgramState(programState, ownPS)) { AXASSERT(programState, "argument should not be nullptr"); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; _mvpMatrixLocaiton = _programState->getUniformLocation("u_MVPMatrix"); - _textureLocation = _programState->getUniformLocation("u_tex0"); + #if 0 // setup custom vertex layout for V2F_T2F_C4B - const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); - auto iter = attributeInfo.find("a_position"); + const auto& vertexInputs = _programState->getProgram()->getActiveVertexInputs(); + auto iter = vertexInputs.find("a_position"); auto layout = _programState->getMutableVertexLayout(); - if (iter != attributeInfo.end()) + if (iter != vertexInputs.end()) { - layout->setAttrib("a_position", iter->second.location, backend::VertexFormat::FLOAT2, 0, false); + layout->setAttrib("a_position", &iter->second, rhi::VertexFormat::FLOAT2, 0, false); } - iter = attributeInfo.find("a_texCoord"); - if (iter != attributeInfo.end()) + iter = vertexInputs.find("a_texCoord"); + if (iter != vertexInputs.end()) { - layout->setAttrib("a_texCoord", iter->second.location, backend::VertexFormat::FLOAT2, - 2 * sizeof(float), false); + layout->setAttrib("a_texCoord", &iter->second, rhi::VertexFormat::FLOAT2, sizeof(Vec2), false); } - iter = attributeInfo.find("a_color"); - if (iter != attributeInfo.end()) + iter = vertexInputs.find("a_color"); + if (iter != vertexInputs.end()) { - layout->setAttrib("a_color", iter->second.location, backend::VertexFormat::UBYTE4, - 4 * sizeof(float), true); + layout->setAttrib("a_color", &iter->second, rhi::VertexFormat::UBYTE4, sizeof(Vec2) * 2, true); } - layout->setStride(4 * sizeof(float) + 4 * sizeof(uint8_t)); + + constexpr size_t vertexSize = sizeof(_vertices[0]); + layout->setStride(vertexSize); + #endif updateProgramStateTexture(_texture); return true; @@ -318,28 +318,22 @@ void MotionStreak::update(float delta) // Move point _pointVertexes[newIdx] = _pointVertexes[i]; - // Move vertices + // Move pos i2 = i * 2; newIdx2 = newIdx * 2; - _vertices[newIdx2] = _vertices[i2]; - _vertices[newIdx2 + 1] = _vertices[i2 + 1]; + _vertices[newIdx2].position = _vertices[i2].position; + _vertices[newIdx2 + 1].position = _vertices[i2 + 1].position; // Move color - i2 *= 4; - newIdx2 *= 4; - _colorPointer[newIdx2 + 0] = _colorPointer[i2 + 0]; - _colorPointer[newIdx2 + 1] = _colorPointer[i2 + 1]; - _colorPointer[newIdx2 + 2] = _colorPointer[i2 + 2]; - _colorPointer[newIdx2 + 4] = _colorPointer[i2 + 4]; - _colorPointer[newIdx2 + 5] = _colorPointer[i2 + 5]; - _colorPointer[newIdx2 + 6] = _colorPointer[i2 + 6]; + _vertices[newIdx2].color = _vertices[i2].color; + _vertices[newIdx2 + 1].color = _vertices[i2 + 1].color; } else - newIdx2 = newIdx * 8; + newIdx2 = newIdx * 2; - const uint8_t op = (uint8_t)(_pointState[newIdx] * 255.0f); - _colorPointer[newIdx2 + 3] = op; - _colorPointer[newIdx2 + 7] = op; + const uint8_t alpha = (uint8_t)(_pointState[newIdx] * 255.0f); + _vertices[newIdx2].color.a = alpha; + _vertices[newIdx2].color.a = alpha; } } _nuPoints -= mov; @@ -363,41 +357,39 @@ void MotionStreak::update(float delta) _pointState[_nuPoints] = 1.0f; // Color assignment - const unsigned int offset = _nuPoints * 8; - *((Color3B*)(_colorPointer + offset)) = _displayedColor; - *((Color3B*)(_colorPointer + offset + 4)) = _displayedColor; - - // Opacity - _colorPointer[offset + 3] = 255; - _colorPointer[offset + 7] = 255; + const auto offset = _nuPoints * 2; + auto tmpColor = _displayedColor; + tmpColor.a = 255; + _vertices[offset].color = tmpColor; + _vertices[offset + 1].color = tmpColor; // Generate polygon if (_nuPoints > 0 && _fastMode) { if (_nuPoints > 1) { - vertexLineToPolygon(_pointVertexes, _stroke, _vertices, _nuPoints, 1); + vertexLineToPolygon(_pointVertexes, _stroke, _vertices.data(), _nuPoints, 1); } else { - vertexLineToPolygon(_pointVertexes, _stroke, _vertices, 0, 2); + vertexLineToPolygon(_pointVertexes, _stroke, _vertices.data(), 0, 2); } } - _nuPoints++; + ++_nuPoints; } if (!_fastMode) - vertexLineToPolygon(_pointVertexes, _stroke, _vertices, 0, _nuPoints); + vertexLineToPolygon(_pointVertexes, _stroke, _vertices.data(), 0, _nuPoints); // Updated Tex Coords only if they are different than previous step if (_nuPoints && _previousNuPoints != _nuPoints) { float texDelta = 1.0f / _nuPoints; - for (i = 0; i < _nuPoints; i++) + for (i = 0; i < _nuPoints; ++i) { - _texCoords[i * 2] = Tex2F(0, texDelta * i); - _texCoords[i * 2 + 1] = Tex2F(1, texDelta * i); + _vertices[i * 2].texCoord = Tex2F(0, texDelta * i); + _vertices[i * 2 + 1].texCoord = Tex2F(1, texDelta * i); } _previousNuPoints = _nuPoints; @@ -420,22 +412,13 @@ void MotionStreak::draw(Renderer* renderer, const Mat4& transform, uint32_t flag _customCommand.setVertexDrawInfo(0, drawCount); renderer->addCommand(&_customCommand); - auto programState = _customCommand.getPipelineDescriptor().programState; + auto programState = _customCommand.getPipelineDesc().programState; const auto& projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); Mat4 finalMat = projectionMat * transform; programState->setUniform(_mvpMatrixLocaiton, finalMat.m, sizeof(Mat4)); - unsigned int offset = 0; - unsigned int vertexSize = sizeof(Vec2) + sizeof(Vec2) + sizeof(uint8_t) * 4; - for (unsigned int i = 0; i < drawCount; ++i) - { - offset = i * vertexSize; - _customCommand.updateVertexBuffer(&_vertices[i], offset, sizeof(_vertices[0])); - _customCommand.updateVertexBuffer(&_texCoords[i], offset + sizeof(_vertices[0]), sizeof(_texCoords[0])); - _customCommand.updateVertexBuffer(&_colorPointer[i * 4], offset + sizeof(_vertices[0]) + sizeof(_texCoords[0]), - 4 * sizeof(uint8_t)); - } + _customCommand.updateVertexBuffer(_vertices.data(), sizeof(_vertices[0]) * drawCount); } } diff --git a/core/2d/MotionStreak.h b/axmol/2d/MotionStreak.h similarity index 75% rename from core/2d/MotionStreak.h rename to axmol/2d/MotionStreak.h index c310210e4068..b01828e886fa 100644 --- a/core/2d/MotionStreak.h +++ b/axmol/2d/MotionStreak.h @@ -3,6 +3,7 @@ Copyright (c) 2011 ForzeField Studios S.L. Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -26,9 +27,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Protocols.h" -#include "2d/Node.h" -#include "renderer/CustomCommand.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/base/axstd.h" namespace ax { @@ -59,7 +61,7 @@ class AX_DLL MotionStreak : public Node, public TextureProtocol static MotionStreak* create(float timeToFade, float minSeg, float strokeWidth, - const Color3B& strokeColor, + const Color32& strokeColor, std::string_view imagePath); /** Creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture. * @@ -73,47 +75,47 @@ class AX_DLL MotionStreak : public Node, public TextureProtocol static MotionStreak* create(float timeToFade, float minSeg, float strokeWidth, - const Color3B& strokeColor, + const Color32& strokeColor, Texture2D* texture); // Overrides - virtual void setPosition(const Vec2& position) override; - virtual void setPosition(float x, float y) override; - virtual const Vec2& getPosition() const override; - virtual void getPosition(float* x, float* y) const override; - virtual void setPositionX(float x) override; - virtual void setPositionY(float y) override; - virtual float getPositionX() const override; - virtual float getPositionY() const override; - virtual Vec3 getPosition3D() const override; + void setPosition(const Vec2& position) override; + void setPosition(float x, float y) override; + const Vec2& getPosition() const override; + void getPosition(float* x, float* y) const override; + void setPositionX(float x) override; + void setPositionY(float y) override; + float getPositionX() const override; + float getPositionY() const override; + Vec3 getPosition3D() const override; /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * @lua NA */ - virtual void update(float delta) override; - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; + void update(float delta) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; /** * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; - virtual uint8_t getOpacity() const override; - virtual void setOpacity(uint8_t opacity) override; - virtual void setOpacityModifyRGB(bool value) override; - virtual bool isOpacityModifyRGB() const override; + const BlendFunc& getBlendFunc() const override; + uint8_t getOpacity() const override; + void setOpacity(uint8_t opacity) override; + void setOpacityModifyRGB(bool value) override; + bool isOpacityModifyRGB() const override; /** Color used for the tint. * * @param colors The color used for the tint. */ - void tintWithColor(const Color3B& colors); + void tintWithColor(const Color32& colors); /** Remove all living segments of the ribbon. */ @@ -154,17 +156,17 @@ class AX_DLL MotionStreak : public Node, public TextureProtocol _startingPositionInitialized = bStartingPositionInitialized; } - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; MotionStreak(); virtual ~MotionStreak(); /** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture filename */ - bool initWithFade(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path); + bool initWithFade(float fade, float minSeg, float stroke, const Color32& color, std::string_view path); /** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture */ - bool initWithFade(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture); + bool initWithFade(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture); protected: bool _fastMode = false; @@ -187,15 +189,11 @@ class AX_DLL MotionStreak : public Node, public TextureProtocol Vec2* _pointVertexes = nullptr; float* _pointState = nullptr; - Vec2* _vertices = nullptr; - uint8_t* _colorPointer = nullptr; - Tex2F* _texCoords = nullptr; - unsigned int _vertexCount = 0; + axstd::pod_vector _vertices; CustomCommand _customCommand; - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _textureLocation; + rhi::UniformLocation _mvpMatrixLocaiton; private: AX_DISALLOW_COPY_AND_ASSIGN(MotionStreak); diff --git a/core/2d/Node.cpp b/axmol/2d/Node.cpp similarity index 97% rename from core/2d/Node.cpp rename to axmol/2d/Node.cpp index 674bcfa09e72..7af754a244e2 100644 --- a/core/2d/Node.cpp +++ b/axmol/2d/Node.cpp @@ -28,25 +28,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Node.h" +#include "axmol/2d/Node.h" #include #include #include #include "xxhash.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include "base/EventDispatcher.h" -#include "base/UTF8.h" -#include "2d/Camera.h" -#include "2d/ActionManager.h" -#include "2d/Scene.h" -#include "2d/Component.h" -#include "renderer/Material.h" -#include "math/TransformUtils.h" -#include "renderer/backend/ProgramManager.h" -#include "renderer/backend/ProgramStateRegistry.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/text_utils.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/ActionManager.h" +#include "axmol/2d/Scene.h" +#include "axmol/2d/Component.h" +#include "axmol/renderer/Material.h" +#include "axmol/math/TransformUtils.h" +#include "axmol/renderer/ProgramManager.h" +#include "axmol/renderer/ProgramStateRegistry.h" #if AX_NODE_RENDER_SUBPIXEL # define RENDER_IN_SUBPIXEL @@ -113,10 +113,8 @@ Node::Node() , _updateScriptHandler(0) #endif , _componentContainer(nullptr) - , _displayedOpacity(255) - , _realOpacity(255) - , _displayedColor(Color3B::WHITE) - , _realColor(Color3B::WHITE) + , _displayedColor(Color32::WHITE) + , _realColor(Color32::WHITE) , _cascadeColorEnabled(false) , _cascadeOpacityEnabled(false) , _childFollowCameraMask(false) @@ -2009,31 +2007,31 @@ void Node::removeAllComponents() uint8_t Node::getOpacity() const { - return _realOpacity; + return _realColor.a; } uint8_t Node::getDisplayedOpacity() const { - return _displayedOpacity; + return _displayedColor.a; } void Node::setOpacity(uint8_t opacity) { - _displayedOpacity = _realOpacity = opacity; + _displayedColor.a = _realColor.a = opacity; updateCascadeOpacity(); } void Node::updateDisplayedOpacity(uint8_t parentOpacity) { - _displayedOpacity = _realOpacity * parentOpacity / 255.0; + _displayedColor.a = _realColor.a * parentOpacity / 255.0; updateColor(); if (_cascadeOpacityEnabled) { for (const auto& child : _children) { - child->updateDisplayedOpacity(_displayedOpacity); + child->updateDisplayedOpacity(_displayedColor.a); } } } @@ -2076,7 +2074,7 @@ void Node::updateCascadeOpacity() void Node::disableCascadeOpacity() { - _displayedOpacity = _realOpacity; + _displayedColor.a = _realColor.a; for (const auto& child : _children) { @@ -2091,28 +2089,30 @@ bool Node::isOpacityModifyRGB() const return false; } -const Color3B& Node::getColor() const +const Color32& Node::getColor() const { return _realColor; } -const Color3B& Node::getDisplayedColor() const +const Color32& Node::getDisplayedColor() const { return _displayedColor; } -void Node::setColor(const Color3B& color) +void Node::setColor(const Color32& color) { _displayedColor = _realColor = color; updateCascadeColor(); } -void Node::updateDisplayedColor(const Color3B& parentColor) +void Node::updateDisplayedColor(const Color32& parentColor) { - _displayedColor.r = _realColor.r * parentColor.r / 255.0; - _displayedColor.g = _realColor.g * parentColor.g / 255.0; - _displayedColor.b = _realColor.b * parentColor.b / 255.0; + _displayedColor.r = _realColor.r * parentColor.r / 255.0f; + _displayedColor.g = _realColor.g * parentColor.g / 255.0f; + _displayedColor.b = _realColor.b * parentColor.b / 255.0f; + if (_cascadeOpacityEnabled) + _displayedColor.a = _realColor.a * parentColor.a / 255.0f; updateColor(); if (_cascadeColorEnabled) @@ -2150,7 +2150,7 @@ void Node::setCascadeColorEnabled(bool cascadeColorEnabled) void Node::updateCascadeColor() { - Color3B parentColor = Color3B::WHITE; + Color32 parentColor = Color32::WHITE; if (_parent && _parent->isCascadeColorEnabled()) { parentColor = _parent->getDisplayedColor(); @@ -2163,7 +2163,7 @@ void Node::disableCascadeColor() { for (const auto& child : _children) { - child->updateDisplayedColor(Color3B::WHITE); + child->updateDisplayedColor(Color32::WHITE); } } @@ -2241,11 +2241,11 @@ int Node::getAttachedNodeCount() void Node::setProgramStateWithRegistry(uint32_t programType, Texture2D* texture) { auto samplerFlags = texture ? texture->getSamplerFlags() : 0; - auto programState = backend::ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags); + auto programState = ProgramStateRegistry::getInstance()->newProgramState(programType, samplerFlags); setProgramState(programState, true); } -bool Node::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) +bool Node::setProgramState(rhi::ProgramState* programState, bool ownPS/* = false*/) { if (_programState != programState) { @@ -2258,7 +2258,7 @@ bool Node::setProgramState(backend::ProgramState* programState, bool ownPS/* = f return false; } -backend::ProgramState* Node::setProgramStateByProgramId(uint64_t programId) +rhi::ProgramState* Node::setProgramStateByProgramId(uint64_t programId) { auto prog = ProgramManager::getInstance()->loadProgram(programId); if (prog) @@ -2277,7 +2277,7 @@ void Node::updateProgramStateTexture(Texture2D* texture) _programState->setTexture(texture->getBackendTexture()); } -backend::ProgramState* Node::getProgramState() const +rhi::ProgramState* Node::getProgramState() const { return _programState; } diff --git a/core/2d/Node.h b/axmol/2d/Node.h similarity index 98% rename from core/2d/Node.h rename to axmol/2d/Node.h index 8043f07932e4..f1261eaee288 100644 --- a/core/2d/Node.h +++ b/axmol/2d/Node.h @@ -31,17 +31,17 @@ #pragma once #include -#include "base/Macros.h" -#include "base/Vector.h" -#include "base/Protocols.h" -#include "base/ScriptSupport.h" -#include "math/AffineTransform.h" -#include "math/Math.h" -#include "2d/ComponentContainer.h" -#include "2d/Component.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Protocols.h" +#include "axmol/base/ScriptSupport.h" +#include "axmol/math/AffineTransform.h" +#include "axmol/math/Math.h" +#include "axmol/2d/ComponentContainer.h" +#include "axmol/2d/Component.h" #if defined(AX_ENABLE_PHYSICS) -# include "physics/PhysicsBody.h" +# include "axmol/physics/PhysicsBody.h" #endif namespace ax @@ -63,7 +63,7 @@ class Material; class Camera; class PhysicsBody; -namespace backend +namespace rhi { class ProgramState; } @@ -1695,24 +1695,24 @@ class AX_DLL Node : public Object /** * Query node's color value. - * @return A Color3B color value. + * @return A Color32 color value. */ - virtual const Color3B& getColor() const; + virtual const Color32& getColor() const; /** * Query node's displayed color. - * @return A Color3B color value. + * @return A Color32 color value. */ - virtual const Color3B& getDisplayedColor() const; + virtual const Color32& getDisplayedColor() const; /** * Change the color of node. - * @param color A Color3B color value. + * @param color A Color32 color value. */ - virtual void setColor(const Color3B& color); + virtual void setColor(const Color32& color); /** * Update node's displayed color with its parent color. - * @param parentColor A Color3B color value. + * @param parentColor A Color32 color value. */ - virtual void updateDisplayedColor(const Color3B& parentColor); + virtual void updateDisplayedColor(const Color32& parentColor); /** * Query whether cascadeColor is enabled or not. * @return Whether cascadeColor is enabled or not. @@ -1816,16 +1816,16 @@ class AX_DLL Node : public Object * Sets ProgramState with retain * @param programState */ - virtual bool setProgramState(backend::ProgramState* programState, bool ownPS = false); + virtual bool setProgramState(rhi::ProgramState* programState, bool ownPS = false); /** * Sets ProgramState by programId * @param progId the program id or programType used to create programState * @return ProgramState* (nullable) */ - backend::ProgramState* setProgramStateByProgramId(uint64_t progId); + rhi::ProgramState* setProgramStateByProgramId(uint64_t progId); - backend::ProgramState* getProgramState() const; + rhi::ProgramState* getProgramState() const; void updateProgramStateTexture(Texture2D* texture); @@ -1993,17 +1993,15 @@ class AX_DLL Node : public Object ComponentContainer* _componentContainer; ///< Dictionary of components // opacity controls - Color3B _displayedColor; - uint8_t _displayedOpacity; - Color3B _realColor; - uint8_t _realOpacity; + Color32 _displayedColor; + Color32 _realColor; std::function _onEnterCallback; std::function _onExitCallback; std::function _onEnterTransitionDidFinishCallback; std::function _onExitTransitionDidStartCallback; - backend::ProgramState* _programState = nullptr; + rhi::ProgramState* _programState = nullptr; // Physics:remaining backwardly compatible #if defined(AX_ENABLE_PHYSICS) diff --git a/core/2d/NodeGrid.cpp b/axmol/2d/NodeGrid.cpp similarity index 98% rename from core/2d/NodeGrid.cpp rename to axmol/2d/NodeGrid.cpp index e6bc74d576bd..28ca48e03f19 100644 --- a/core/2d/NodeGrid.cpp +++ b/axmol/2d/NodeGrid.cpp @@ -22,9 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/NodeGrid.h" -#include "2d/Grid.h" -#include "renderer/Renderer.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/2d/Grid.h" +#include "axmol/renderer/Renderer.h" namespace ax { diff --git a/core/2d/NodeGrid.h b/axmol/2d/NodeGrid.h similarity index 93% rename from core/2d/NodeGrid.h rename to axmol/2d/NodeGrid.h index 7178f899e579..be28737c9b30 100644 --- a/core/2d/NodeGrid.h +++ b/axmol/2d/NodeGrid.h @@ -24,9 +24,9 @@ ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "renderer/GroupCommand.h" -#include "renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CustomCommand.h" namespace ax { @@ -86,7 +86,7 @@ class AX_DLL NodeGrid : public Node const Rect& getGridRect() const { return _gridRect; } // overrides - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; NodeGrid(); virtual ~NodeGrid(); diff --git a/core/2d/ParallaxNode.cpp b/axmol/2d/ParallaxNode.cpp similarity index 99% rename from core/2d/ParallaxNode.cpp rename to axmol/2d/ParallaxNode.cpp index 5074c4f9deef..768aff09a4c1 100644 --- a/core/2d/ParallaxNode.cpp +++ b/axmol/2d/ParallaxNode.cpp @@ -25,7 +25,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ParallaxNode.h" +#include "axmol/2d/ParallaxNode.h" namespace ax { diff --git a/core/2d/ParallaxNode.h b/axmol/2d/ParallaxNode.h similarity index 88% rename from core/2d/ParallaxNode.h rename to axmol/2d/ParallaxNode.h index 4fe9d835cdd0..980ade34a65a 100644 --- a/core/2d/ParallaxNode.h +++ b/axmol/2d/ParallaxNode.h @@ -27,8 +27,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "base/Vector.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Vector.h" namespace ax { @@ -80,11 +80,11 @@ class AX_DLL ParallaxNode : public Node // // Overrides // - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void removeChild(Node* child, bool cleanup) override; - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; + void removeChild(Node* child, bool cleanup) override; + void removeAllChildrenWithCleanup(bool cleanup) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** Adds a child to the container with a z-order, a parallax ratio and a position offset It returns self, so you can chain several addChilds. diff --git a/core/2d/ParticleBatchNode.cpp b/axmol/2d/ParticleBatchNode.cpp similarity index 94% rename from core/2d/ParticleBatchNode.cpp rename to axmol/2d/ParticleBatchNode.cpp index f5afe8eaa0bc..e26fd3fe30b0 100644 --- a/core/2d/ParticleBatchNode.cpp +++ b/axmol/2d/ParticleBatchNode.cpp @@ -29,31 +29,31 @@ * THE SOFTWARE. * */ -#include "2d/ParticleBatchNode.h" +#include "axmol/2d/ParticleBatchNode.h" #include // offsetof -#include "base/Types.h" -#include "2d/Grid.h" -#include "2d/ParticleSystem.h" -#include "renderer/TextureCache.h" -#include "renderer/QuadCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureAtlas.h" -#include "base/Profiling.h" -#include "base/UTF8.h" -#include "base/Utils.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/2d/Grid.h" +#include "axmol/2d/ParticleSystem.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/base/Profiling.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" namespace ax { ParticleBatchNode::ParticleBatchNode() { - auto& pipelinePS = _customCommand.getPipelineDescriptor().programState; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); + auto& pipelinePS = _customCommand.getPipelineDesc().programState; + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR); //!!! ParticleBatchNode private programState don't want affect by Node::_programState, so store at _customCommand //!!! support etc1 with alpha? - pipelinePS = new backend::ProgramState(program); + pipelinePS = new rhi::ProgramState(program); _mvpMatrixLocaiton = pipelinePS->getUniformLocation("u_MVPMatrix"); _textureLocation = pipelinePS->getUniformLocation("u_tex0"); @@ -65,7 +65,7 @@ ParticleBatchNode::ParticleBatchNode() ParticleBatchNode::~ParticleBatchNode() { AX_SAFE_RELEASE(_textureAtlas); - AX_SAFE_RELEASE(_customCommand.getPipelineDescriptor().programState); + AX_SAFE_RELEASE(_customCommand.getPipelineDesc().programState); } /* * creation with Texture2D @@ -436,7 +436,7 @@ void ParticleBatchNode::draw(Renderer* renderer, const Mat4& transform, uint32_t // Texture is set in TextureAtlas. const ax::Mat4& projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); Mat4 finalMat = projectionMat * transform; - auto programState = _customCommand.getPipelineDescriptor().programState; + auto programState = _customCommand.getPipelineDesc().programState; programState->setUniform(_mvpMatrixLocaiton, finalMat.m, sizeof(finalMat.m)); if (_textureAtlas->isDirty()) { @@ -474,9 +474,9 @@ void ParticleBatchNode::increaseAtlasCapacityTo(ssize_t quantity) // sets a 0'd quad into the quads array void ParticleBatchNode::disableParticle(int particleIndex) { - V3F_C4B_T2F_Quad* quad = &((_textureAtlas->getQuads())[particleIndex]); - quad->br.vertices.x = quad->br.vertices.y = quad->tr.vertices.x = quad->tr.vertices.y = quad->tl.vertices.x = - quad->tl.vertices.y = quad->bl.vertices.x = quad->bl.vertices.y = 0.0f; + auto quad = &((_textureAtlas->getQuads())[particleIndex]); + quad->br.position.x = quad->br.position.y = quad->tr.position.x = quad->tr.position.y = quad->tl.position.x = + quad->tl.position.y = quad->bl.position.x = quad->bl.position.y = 0.0f; } // ParticleBatchNode - add / remove / reorder helper methods @@ -540,7 +540,7 @@ void ParticleBatchNode::updateProgramStateTexture() auto texture = _textureAtlas->getTexture(); if (!texture) return; - auto programState = _customCommand.getPipelineDescriptor().programState; + auto programState = _customCommand.getPipelineDesc().programState; programState->setTexture(texture->getBackendTexture()); // If the new texture has No premultiplied alpha, AND the blendFunc hasn't been changed, then update it if (!texture->hasPremultipliedAlpha() && (_blendFunc.src == AX_BLEND_SRC && _blendFunc.dst == AX_BLEND_DST)) diff --git a/core/2d/ParticleBatchNode.h b/axmol/2d/ParticleBatchNode.h similarity index 87% rename from core/2d/ParticleBatchNode.h rename to axmol/2d/ParticleBatchNode.h index 1036babfa8c7..5d9a0c6ea1ba 100644 --- a/core/2d/ParticleBatchNode.h +++ b/axmol/2d/ParticleBatchNode.h @@ -31,9 +31,9 @@ */ #pragma once -#include "2d/Node.h" -#include "base/Protocols.h" -#include "renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Protocols.h" +#include "axmol/renderer/CustomCommand.h" namespace ax { @@ -124,16 +124,16 @@ class AX_DLL ParticleBatchNode : public Node, public TextureProtocol void setTextureAtlas(TextureAtlas* atlas) { _textureAtlas = atlas; } // Overrides - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; using Node::addChild; - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void removeChild(Node* child, bool cleanup) override; - virtual void reorderChild(Node* child, int zOrder) override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; + void removeChild(Node* child, bool cleanup) override; + void reorderChild(Node* child, int zOrder) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; /** * @code * When this function bound into js or lua,the parameter will be changed @@ -141,11 +141,11 @@ class AX_DLL ParticleBatchNode : public Node, public TextureProtocol * @endcode * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; /** */ @@ -181,8 +181,8 @@ class AX_DLL ParticleBatchNode : public Node, public TextureProtocol CustomCommand _customCommand; - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _textureLocation; + rhi::UniformLocation _mvpMatrixLocaiton; + rhi::UniformLocation _textureLocation; }; // end of _2d group diff --git a/core/2d/ParticleExamples.cpp b/axmol/2d/ParticleExamples.cpp similarity index 99% rename from core/2d/ParticleExamples.cpp rename to axmol/2d/ParticleExamples.cpp index 14e4b7559b21..a9319ea9f5dd 100644 --- a/core/2d/ParticleExamples.cpp +++ b/axmol/2d/ParticleExamples.cpp @@ -26,10 +26,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ParticleExamples.h" -#include "base/Director.h" -#include "base/firePngData.h" -#include "renderer/TextureCache.h" +#include "axmol/2d/ParticleExamples.h" +#include "axmol/base/Director.h" +#include "axmol/base/firePngData.h" +#include "axmol/renderer/TextureCache.h" namespace ax { diff --git a/core/2d/ParticleExamples.h b/axmol/2d/ParticleExamples.h similarity index 99% rename from core/2d/ParticleExamples.h rename to axmol/2d/ParticleExamples.h index d82e0af4d545..a786d4d58685 100644 --- a/core/2d/ParticleExamples.h +++ b/axmol/2d/ParticleExamples.h @@ -27,7 +27,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ParticleSystemQuad.h" +#include "axmol/2d/ParticleSystemQuad.h" namespace ax { @@ -64,7 +64,7 @@ class AX_DLL ParticleFire : public ParticleSystemQuad virtual ~ParticleFire() {} bool init() override { return initWithTotalParticles(250); } - virtual bool initWithTotalParticles(int numberOfParticles) override; + bool initWithTotalParticles(int numberOfParticles) override; private: AX_DISALLOW_COPY_AND_ASSIGN(ParticleFire); diff --git a/core/2d/ParticleSystem.cpp b/axmol/2d/ParticleSystem.cpp similarity index 98% rename from core/2d/ParticleSystem.cpp rename to axmol/2d/ParticleSystem.cpp index 98d684ab6c3b..464d87319501 100644 --- a/core/2d/ParticleSystem.cpp +++ b/axmol/2d/ParticleSystem.cpp @@ -44,19 +44,19 @@ THE SOFTWARE. // axmol uses a another approach, but the results are almost identical. // -#include "2d/ParticleSystem.h" +#include "axmol/2d/ParticleSystem.h" #include -#include "2d/ParticleBatchNode.h" -#include "renderer/TextureAtlas.h" -#include "base/ZipUtils.h" -#include "base/Director.h" -#include "base/Profiling.h" -#include "base/UTF8.h" -#include "base/Utils.h" -#include "renderer/TextureCache.h" -#include "platform/FileUtils.h" +#include "axmol/2d/ParticleBatchNode.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/base/ZipUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Profiling.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/platform/FileUtils.h" using namespace std; @@ -1108,15 +1108,15 @@ void ParticleSystem::addParticles(int count, int animationIndex, int animationCe } } -void ParticleSystem::setAnimationDescriptor(unsigned short indexOfDescriptor, +void ParticleSystem::setAnimationDesc(unsigned short indexOfDesc, float time, float timeVariance, const std::vector& indices, bool reverse) { - auto iter = _animations.find(indexOfDescriptor); + auto iter = _animations.find(indexOfDesc); if (iter == _animations.end()) - iter = _animations.emplace(indexOfDescriptor, ParticleAnimationDescriptor{}).first; + iter = _animations.emplace(indexOfDesc, ParticleAnimationDesc{}).first; auto& desc = iter->second; desc.animationSpeed = time; @@ -1470,7 +1470,7 @@ bool ParticleSystem::addAnimationIndex(unsigned short index, ax::Rect rect, bool auto iter = _animationIndices.find(index); if (iter == _animationIndices.end()) { - iter = _animationIndices.emplace(index, ParticleFrameDescriptor{}).first; + iter = _animationIndices.emplace(index, ParticleFrameDesc{}).first; _animIndexCount++; } @@ -1912,7 +1912,7 @@ void ParticleSystem::setBlendAdditive(bool additive) bool ParticleSystem::isBlendAdditive() const { - return (_blendFunc.src == backend::BlendFactor::SRC_ALPHA && _blendFunc.dst == backend::BlendFactor::ONE); + return (_blendFunc.src == rhi::BlendFactor::SRC_ALPHA && _blendFunc.dst == rhi::BlendFactor::ONE); } // ParticleSystem - Properties of Gravity Mode @@ -2325,9 +2325,9 @@ void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskId, auto iter = this->masks.find(fourccId); if (iter == this->masks.end()) - iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first; + iter = this->masks.emplace(fourccId, ParticleEmissionMaskDesc{}).first; - ParticleEmissionMaskDescriptor desc; + ParticleEmissionMaskDesc desc; desc.size = {float(w), float(h)}; desc.points = std::move(points); @@ -2337,12 +2337,12 @@ void ParticleEmissionMaskCache::bakeEmissionMask(std::string_view maskId, (unsigned int)htonl(fourccId), w, h, desc.points.size(), desc.points.size() * 8 / 1e+6); } -const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask(uint32_t fourccId) +const ParticleEmissionMaskDesc& ParticleEmissionMaskCache::getEmissionMask(uint32_t fourccId) { auto iter = this->masks.find(fourccId); if (iter == this->masks.end()) { - iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first; + iter = this->masks.emplace(fourccId, ParticleEmissionMaskDesc{}).first; iter->second.size = {float(1), float(1)}; iter->second.points = {{0, 0}}; return iter->second; @@ -2350,14 +2350,14 @@ const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask return iter->second; } -const ParticleEmissionMaskDescriptor& ParticleEmissionMaskCache::getEmissionMask(std::string_view maskId) +const ParticleEmissionMaskDesc& ParticleEmissionMaskCache::getEmissionMask(std::string_view maskId) { auto fourccId = utils::fourccValue(maskId); auto iter = this->masks.find(fourccId); if (iter == this->masks.end()) { - iter = this->masks.emplace(fourccId, ParticleEmissionMaskDescriptor{}).first; + iter = this->masks.emplace(fourccId, ParticleEmissionMaskDesc{}).first; iter->second.size = {float(1), float(1)}; iter->second.points = {{0, 0}}; return iter->second; diff --git a/core/2d/ParticleSystem.h b/axmol/2d/ParticleSystem.h similarity index 96% rename from core/2d/ParticleSystem.h rename to axmol/2d/ParticleSystem.h index a16eac88a557..427a90bccb2b 100644 --- a/core/2d/ParticleSystem.h +++ b/axmol/2d/ParticleSystem.h @@ -28,12 +28,12 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Protocols.h" -#include "2d/Node.h" -#include "base/Value.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" -#include "math/FastRNG.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Value.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/math/FastRNG.h" namespace ax { @@ -77,16 +77,16 @@ struct EmissionShape * Particle emission mask descriptor. * @since axmol-1.0.0b8 */ -struct ParticleEmissionMaskDescriptor +struct ParticleEmissionMaskDesc { Vec2 size; std::vector points; }; -/** @struct ParticleAnimationDescriptor +/** @struct ParticleAnimationDesc Structure that contains animation description */ -struct ParticleAnimationDescriptor +struct ParticleAnimationDesc { float animationSpeed; float animationSpeedVariance; @@ -94,10 +94,10 @@ struct ParticleAnimationDescriptor bool reverseIndices; }; -/** @struct ParticleFrameDescriptor +/** @struct ParticleFrameDesc Structure that contains frame description */ -struct ParticleFrameDescriptor +struct ParticleFrameDesc { ax::Rect rect; bool isRotated; @@ -284,13 +284,13 @@ class AX_DLL ParticleEmissionMaskCache * * @param fourccId The unsigned integer id of the mask. */ - const ParticleEmissionMaskDescriptor& getEmissionMask(uint32_t fourccId); + const ParticleEmissionMaskDesc& getEmissionMask(uint32_t fourccId); /** Returns a baked mask with the specified name if it exists. otherwise, it will return a dummy mask. * * @param maskId The id of the mask, FOURCC starts with '#', such as "#abcd" */ - const ParticleEmissionMaskDescriptor& getEmissionMask(std::string_view maskId); + const ParticleEmissionMaskDesc& getEmissionMask(std::string_view maskId); /** Removes a baked mask and releases the data from memory with the specified name if it exists. * @@ -302,7 +302,7 @@ class AX_DLL ParticleEmissionMaskCache void removeAllMasks(); private: - std::unordered_map masks; + std::unordered_map masks; }; @@ -627,10 +627,10 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab */ virtual void setRotatePerSecondVar(float degrees); - virtual void setScale(float s) override; - virtual void setRotation(float newRotation) override; - virtual void setScaleX(float newScaleX) override; - virtual void setScaleY(float newScaleY) override; + void setScale(float s) override; + void setRotation(float newRotation) override; + void setScaleX(float newScaleX) override; + void setScaleY(float newScaleY) override; /** Whether or not the particle system is active. * @@ -814,45 +814,45 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab * * @return The start color of each particle. */ - const Color4F& getStartColor() const { return _startColor; } + const Color& getStartColor() const { return _startColor; } /** Sets the start color of each particle. * * @param color The start color of each particle. */ - void setStartColor(const Color4F& color) { _startColor = color; } + void setStartColor(const Color& color) { _startColor = color; } /** Gets the start color variance of each particle. * * @return The start color variance of each particle. */ - const Color4F& getStartColorVar() const { return _startColorVar; } + const Color& getStartColorVar() const { return _startColorVar; } /** Sets the start color variance of each particle. * * @param color The start color variance of each particle. */ - void setStartColorVar(const Color4F& color) { _startColorVar = color; } + void setStartColorVar(const Color& color) { _startColorVar = color; } /** Gets the end color and end color variation of each particle. * * @return The end color and end color variation of each particle. */ - const Color4F& getEndColor() const { return _endColor; } + const Color& getEndColor() const { return _endColor; } /** Sets the end color and end color variation of each particle. * * @param color The end color and end color variation of each particle. */ - void setEndColor(const Color4F& color) { _endColor = color; } + void setEndColor(const Color& color) { _endColor = color; } /** Gets the end color variance of each particle. * * @return The end color variance of each particle. */ - const Color4F& getEndColorVar() const { return _endColorVar; } + const Color& getEndColorVar() const { return _endColorVar; } /** Sets the end color variance of each particle. * * @param color The end color variance of each particle. */ - void setEndColorVar(const Color4F& color) { _endColorVar = color; } + void setEndColorVar(const Color& color) { _endColorVar = color; } /** Sets wether to use HSV color system. * WARNING: becareful when using HSV with too many particles because it's expensive. @@ -1172,14 +1172,14 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab /** Add a particle animation descriptor with an index. * - * @param indexOfDescriptor Index of the animation to be added, adding to the same index will just override the + * @param indexOfDesc Index of the animation to be added, adding to the same index will just override the * pervious animation descriptor * @param time length of the animation in seconds * @param timeVariance Time randomly selected for each different particle added on the animation length * @param indices An array of the indicies * @param reverse Should the animation indicies be played backwards? (default: false) */ - void setAnimationDescriptor(unsigned short indexOfDescriptor, + void setAnimationDesc(unsigned short indexOfDesc, float time, float timeVariance, const std::vector& indices, @@ -1190,9 +1190,9 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab * @param indices An array of the indicies * @param reverse Should the animation indicies be played backwards? (default: false) */ - void setAnimationDescriptor(const std::vector& indices, bool reverse = false) + void setAnimationDesc(const std::vector& indices, bool reverse = false) { - setAnimationDescriptor(0, 0, 0, indices, reverse); + setAnimationDesc(0, 0, 0, indices, reverse); }; /** Sets wether the animation descriptors should follow the time scale of the system or not. @@ -1353,11 +1353,11 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab float frameRate = SIMULATION_USE_GAME_ANIMATION_INTERVAL); // Overrides - virtual void onEnter() override; - virtual void onExit() override; - virtual void update(float dt) override; - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; + void onEnter() override; + void onExit() override; + void update(float dt) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; /** *@code *When this function bound into js or lua,the parameter will be changed @@ -1365,18 +1365,18 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab *In lua: local setBlendFunc(local src, local dst) *@endcode */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; std::string_view getResourceFile() const { return _plistFile; } /// @{ /// @name implement Playable Protocol - virtual void start() override; - virtual void stop() override; + void start() override; + void stop() override; /// @} end of PlayableProtocol void setSourcePositionCompatible(bool sourcePositionCompatible) @@ -1581,13 +1581,13 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab /** end size variance in pixels of each particle */ float _endSizeVar; /** start color of each particle */ - Color4F _startColor; + Color _startColor; /** start color variance of each particle */ - Color4F _startColorVar; + Color _startColorVar; /** end color and end color variation of each particle */ - Color4F _endColor; + Color _endColor; /** end color variance of each particle */ - Color4F _endColorVar; + Color _endColorVar; /** hsv color of each particle */ HSV _hsv; /** hsv color variance of each particle */ @@ -1633,9 +1633,9 @@ class AX_DLL ParticleSystem : public Node, public TextureProtocol, public Playab /** wether to start from first or last when using life animation */ bool _isAnimationReversed; /** A map that stores particle animation index coords */ - std::unordered_map _animationIndices; + std::unordered_map _animationIndices; /** A map that stores particle animation descriptors */ - std::unordered_map _animations; + std::unordered_map _animations; /** A vector that stores ids of animation descriptors that are choosen at random */ std::vector _randomAnimations; /** Wether the animation goes with the time scale of the system or is independent. */ diff --git a/core/2d/ParticleSystemQuad.cpp b/axmol/2d/ParticleSystemQuad.cpp similarity index 76% rename from core/2d/ParticleSystemQuad.cpp rename to axmol/2d/ParticleSystemQuad.cpp index 5aae06c1e28c..b0fddd62cd7f 100644 --- a/core/2d/ParticleSystemQuad.cpp +++ b/axmol/2d/ParticleSystemQuad.cpp @@ -28,37 +28,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ParticleSystemQuad.h" +#include "axmol/2d/ParticleSystemQuad.h" #include #include // offsetof -#include "base/Types.h" -#include "2d/SpriteFrame.h" -#include "2d/ParticleBatchNode.h" -#include "renderer/TextureAtlas.h" -#include "renderer/Renderer.h" -#include "base/Director.h" -#include "base/EventType.h" -#include "base/Configuration.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/UTF8.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "2d/TweenFunction.h" +#include "axmol/base/Types.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/ParticleBatchNode.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/text_utils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/2d/TweenFunction.h" namespace ax { ParticleSystemQuad::ParticleSystemQuad() { - auto& pipelinePS = _quadCommand.getPipelineDescriptor().programState; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - - //!!! support etc1 with alpha? - pipelinePS = (new backend::ProgramState(program)); - - _mvpMatrixLocaiton = pipelinePS->getUniformLocation("u_MVPMatrix"); - _textureLocation = pipelinePS->getUniformLocation("u_tex0"); } ParticleSystemQuad::~ParticleSystemQuad() @@ -68,8 +60,6 @@ ParticleSystemQuad::~ParticleSystemQuad() AX_SAFE_FREE(_quads); AX_SAFE_FREE(_indices); } - - AX_SAFE_RELEASE_NULL(_quadCommand.getPipelineDescriptor().programState); } // implementation ParticleSystemQuad @@ -176,7 +166,7 @@ void ParticleSystemQuad::initTexCoordsWithRect(const Rect& pointRect) // Important. Texture in axmol are inverted, so the Y component should be inverted std::swap(top, bottom); - V3F_C4B_T2F_Quad* quads = nullptr; + V3F_T2F_C4B_Quad* quads = nullptr; unsigned int start = 0, end = 0; if (_batchNode) { @@ -194,17 +184,17 @@ void ParticleSystemQuad::initTexCoordsWithRect(const Rect& pointRect) for (unsigned int i = start; i < end; i++) { // bottom-left vertex: - quads[i].bl.texCoords.u = left; - quads[i].bl.texCoords.v = bottom; + quads[i].bl.texCoord.u = left; + quads[i].bl.texCoord.v = bottom; // bottom-right vertex: - quads[i].br.texCoords.u = right; - quads[i].br.texCoords.v = bottom; + quads[i].br.texCoord.u = right; + quads[i].br.texCoord.v = bottom; // top-left vertex: - quads[i].tl.texCoords.u = left; - quads[i].tl.texCoords.v = top; + quads[i].tl.texCoord.u = left; + quads[i].tl.texCoord.v = top; // top-right vertex: - quads[i].tr.texCoords.u = right; - quads[i].tr.texCoords.v = top; + quads[i].tr.texCoord.u = right; + quads[i].tr.texCoord.v = top; } } @@ -219,13 +209,25 @@ void ParticleSystemQuad::updateTexCoords() void ParticleSystemQuad::setTextureWithRect(Texture2D* texture, const Rect& rect) { + bool needsUpdatePS = + ((!_programState || _programState->getProgram()->getProgramType() < rhi::ProgramType::CUSTOM_PROGRAM) && + (_texture == nullptr || _texture->getSamplerFlags() != texture->getSamplerFlags() || + _texture->getPixelFormat() != texture->getPixelFormat())); + + if (needsUpdatePS) { + auto programType = ax::ProgramManager::chooseSpriteProgramType(texture->getPixelFormat()); + setProgramState(programType); + _quadCommand.getPipelineDesc().programState = _programState; + + _mvpMatrixLocaiton = _programState->getUniformLocation("u_MVPMatrix"); + } + // Only update the texture if is different from the current one if (!_texture || texture->getBackendTexture() != _texture->getBackendTexture()) { ParticleSystem::setTexture(texture); - auto programState = _quadCommand.getPipelineDescriptor().programState; - programState->setTexture(_texture->getBackendTexture()); + _programState->setTexture(_texture->getBackendTexture()); } this->initTexCoordsWithRect(rect); @@ -260,7 +262,7 @@ void ParticleSystemQuad::initIndices() } } -inline void updatePosWithParticle(V3F_C4B_T2F_Quad* quad, +static void updatePosWithParticle(V3F_T2F_C4B_Quad* quad, const Vec2& newPosition, float size, float scaleInSize, @@ -290,20 +292,20 @@ inline void updatePosWithParticle(V3F_C4B_T2F_Quad* quad, float dy = x1 * sr + y2 * cr + y; // bottom-left - quad->bl.vertices.x = ax; - quad->bl.vertices.y = ay; + quad->bl.position.x = ax; + quad->bl.position.y = ay; // bottom-right vertex: - quad->br.vertices.x = bx; - quad->br.vertices.y = by; + quad->br.position.x = bx; + quad->br.position.y = by; // top-left vertex: - quad->tl.vertices.x = dx; - quad->tl.vertices.y = dy; + quad->tl.position.x = dx; + quad->tl.position.y = dy; // top-right vertex: - quad->tr.vertices.x = cx; - quad->tr.vertices.y = cy; + quad->tr.position.x = cx; + quad->tr.position.y = cy; } void ParticleSystemQuad::updateParticleQuads() @@ -323,11 +325,11 @@ void ParticleSystemQuad::updateParticleQuads() currentPosition = _position; } - V3F_C4B_T2F_Quad* startQuad; + V3F_T2F_C4B_Quad* startQuad; Vec2 pos = Vec2::ZERO; if (_batchNode) { - V3F_C4B_T2F_Quad* batchQuads = _batchNode->getTextureAtlas()->getQuads(); + V3F_T2F_C4B_Quad* batchQuads = _batchNode->getTextureAtlas()->getQuads(); startQuad = &(batchQuads[_atlasIndex]); pos = _position; } @@ -352,7 +354,7 @@ void ParticleSystemQuad::updateParticleQuads() float* sr = _particleData.staticRotation; float* sid = _particleData.scaleInDelta; float* sil = _particleData.scaleInLength; - V3F_C4B_T2F_Quad* quadStart = startQuad; + V3F_T2F_C4B_Quad* quadStart = startQuad; if (_isScaleInAllocated) { for (int i = 0; i < _particleCount; @@ -393,7 +395,7 @@ void ParticleSystemQuad::updateParticleQuads() float* sr = _particleData.staticRotation; float* sid = _particleData.scaleInDelta; float* sil = _particleData.scaleInLength; - V3F_C4B_T2F_Quad* quadStart = startQuad; + V3F_T2F_C4B_Quad* quadStart = startQuad; if (_isScaleInAllocated) { for (int i = 0; i < _particleCount; @@ -430,7 +432,7 @@ void ParticleSystemQuad::updateParticleQuads() float* sr = _particleData.staticRotation; float* sid = _particleData.scaleInDelta; float* sil = _particleData.scaleInLength; - V3F_C4B_T2F_Quad* quadStart = startQuad; + V3F_T2F_C4B_Quad* quadStart = startQuad; if (_isScaleInAllocated) { for (int i = 0; i < _particleCount; @@ -450,7 +452,7 @@ void ParticleSystemQuad::updateParticleQuads() } } - V3F_C4B_T2F_Quad* quad = startQuad; + auto quad = startQuad; float* r = _particleData.colorR; float* g = _particleData.colorG; float* b = _particleData.colorB; @@ -478,15 +480,12 @@ void ParticleSystemQuad::updateParticleQuads() hsv.h += *hue; hsv.s = abs(*sat); hsv.v = abs(*val); - auto colF = hsv.toColor4F(); - quad->bl.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->br.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->tl.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->tr.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); + auto colF = hsv.toRgba(); + Color32 col{colF.premultiplyAlpha()}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } else @@ -499,11 +498,11 @@ void ParticleSystemQuad::updateParticleQuads() hsv.h += *hue; hsv.s = abs(*sat); hsv.v = abs(*val); - auto col = hsv.toColor4B(); - quad->bl.colors.set(col.r, col.g, col.b, col.a); - quad->br.colors.set(col.r, col.g, col.b, col.a); - quad->tl.colors.set(col.r, col.g, col.b, col.a); - quad->tr.colors.set(col.r, col.g, col.b, col.a); + auto col = hsv.toColor32(); + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } } @@ -514,28 +513,22 @@ void ParticleSystemQuad::updateParticleQuads() { for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a, ++fadeDt, ++fadeLn) { - uint8_t colorR = *r * *a * 255; - uint8_t colorG = *g * *a * 255; - uint8_t colorB = *b * *a * 255; - uint8_t colorA = *a * (*fadeDt / *fadeLn) * 255; - quad->bl.colors.set(colorR, colorG, colorB, colorA); - quad->br.colors.set(colorR, colorG, colorB, colorA); - quad->tl.colors.set(colorR, colorG, colorB, colorA); - quad->tr.colors.set(colorR, colorG, colorB, colorA); + Color32 col{Color{*r * *a, *g * *a, *b * *a, *a * (*fadeDt / *fadeLn)}}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } else { for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a, ++fadeDt, ++fadeLn) { - uint8_t colorR = *r * 255; - uint8_t colorG = *g * 255; - uint8_t colorB = *b * 255; - uint8_t colorA = *a * (*fadeDt / *fadeLn) * 255; - quad->bl.colors.set(colorR, colorG, colorB, colorA); - quad->br.colors.set(colorR, colorG, colorB, colorA); - quad->tl.colors.set(colorR, colorG, colorB, colorA); - quad->tr.colors.set(colorR, colorG, colorB, colorA); + Color32 col{Color{*r, *g, *b, *a * (*fadeDt / *fadeLn)}}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } } @@ -558,15 +551,13 @@ void ParticleSystemQuad::updateParticleQuads() hsv.h += *hue; hsv.s = abs(*sat); hsv.v = abs(*val); - auto colF = hsv.toColor4F(); - quad->bl.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->br.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->tl.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); - quad->tr.colors.set(colF.r * colF.a * 255.0F, colF.g * colF.a * 255.0F, colF.b * colF.a * 255.0F, - colF.a * 255.0F); + auto colF = hsv.toRgba(); + Color32 col{colF.premultiplyAlpha()}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; + } } else @@ -578,11 +569,11 @@ void ParticleSystemQuad::updateParticleQuads() hsv.h += *hue; hsv.s = abs(*sat); hsv.v = abs(*val); - auto col = hsv.toColor4B(); - quad->bl.colors.set(col.r, col.g, col.b, col.a); - quad->br.colors.set(col.r, col.g, col.b, col.a); - quad->tl.colors.set(col.r, col.g, col.b, col.a); - quad->tr.colors.set(col.r, col.g, col.b, col.a); + auto col = hsv.toColor32(); + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } } @@ -593,28 +584,22 @@ void ParticleSystemQuad::updateParticleQuads() { for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a) { - uint8_t colorR = *r * *a * 255; - uint8_t colorG = *g * *a * 255; - uint8_t colorB = *b * *a * 255; - uint8_t colorA = *a * 255; - quad->bl.colors.set(colorR, colorG, colorB, colorA); - quad->br.colors.set(colorR, colorG, colorB, colorA); - quad->tl.colors.set(colorR, colorG, colorB, colorA); - quad->tr.colors.set(colorR, colorG, colorB, colorA); + Color32 col{Color{*r * *a, *g * *a, *b * *a, *a}}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } else { for (int i = 0; i < _particleCount; ++i, ++quad, ++r, ++g, ++b, ++a) { - uint8_t colorR = *r * 255; - uint8_t colorG = *g * 255; - uint8_t colorB = *b * 255; - uint8_t colorA = *a * 255; - quad->bl.colors.set(colorR, colorG, colorB, colorA); - quad->br.colors.set(colorR, colorG, colorB, colorA); - quad->tl.colors.set(colorR, colorG, colorB, colorA); - quad->tr.colors.set(colorR, colorG, colorB, colorA); + Color32 col{Color{*r, *g, *b, *a}}; + quad->bl.color = col; + quad->br.color = col; + quad->tl.color = col; + quad->tr.color = col; } } } @@ -628,10 +613,10 @@ void ParticleSystemQuad::updateParticleQuads() // It was proved to be effective especially for low-end devices. if ((_isLifeAnimated || _isEmitterAnimated || _isLoopAnimated) && _isAnimAllocated) { - V3F_C4B_T2F_Quad* quad = startQuad; + V3F_T2F_C4B_Quad* quad = startQuad; unsigned short* cellIndex = _particleData.animCellIndex; - ParticleFrameDescriptor index; + ParticleFrameDesc index; for (int i = 0; i < _particleCount; ++i, ++quad, ++cellIndex) { float left = 0.0F, bottom = 0.0F, top = 1.0F, right = 1.0F; @@ -653,17 +638,17 @@ void ParticleSystemQuad::updateParticleQuads() top = index.rect.origin.y / texHeight; bottom = (index.rect.origin.y + index.rect.size.y) / texHeight; - quad->bl.texCoords.u = left; - quad->bl.texCoords.v = bottom; + quad->bl.texCoord.u = left; + quad->bl.texCoord.v = bottom; - quad->br.texCoords.u = right; - quad->br.texCoords.v = bottom; + quad->br.texCoord.u = right; + quad->br.texCoord.v = bottom; - quad->tl.texCoords.u = left; - quad->tl.texCoords.v = top; + quad->tl.texCoord.u = left; + quad->tl.texCoord.v = top; - quad->tr.texCoords.u = right; - quad->tr.texCoords.v = top; + quad->tr.texCoord.u = right; + quad->tr.texCoord.v = top; } } } @@ -674,7 +659,7 @@ void ParticleSystemQuad::draw(Renderer* renderer, const Mat4& transform, uint32_ // quad command if (_particleCount > 0) { - auto programState = _quadCommand.getPipelineDescriptor().programState; + auto programState = _quadCommand.getPipelineDesc().programState; ax::Mat4 projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); programState->setUniform(_mvpMatrixLocaiton, projectionMat.m, sizeof(projectionMat.m)); @@ -700,7 +685,7 @@ void ParticleSystemQuad::setTotalParticles(int tp) AXLOGW("Particle system: not enough memory"); return; } - V3F_C4B_T2F_Quad* quadsNew = (V3F_C4B_T2F_Quad*)realloc(_quads, quadsSize); + auto quadsNew = (V3F_T2F_C4B_Quad*)realloc(_quads, quadsSize); unsigned short* indicesNew = (unsigned short*)realloc(_indices, indicesSize); if (quadsNew && indicesNew) @@ -780,7 +765,7 @@ bool ParticleSystemQuad::allocMemory() AX_SAFE_FREE(_quads); AX_SAFE_FREE(_indices); - _quads = (V3F_C4B_T2F_Quad*)malloc(_totalParticles * sizeof(V3F_C4B_T2F_Quad)); + _quads = (V3F_T2F_C4B_Quad*)malloc(_totalParticles * sizeof(V3F_T2F_C4B_Quad)); _indices = (unsigned short*)malloc(_totalParticles * 6 * sizeof(unsigned short)); if (!_quads || !_indices) @@ -792,7 +777,7 @@ bool ParticleSystemQuad::allocMemory() return false; } - memset(_quads, 0, _totalParticles * sizeof(V3F_C4B_T2F_Quad)); + memset(_quads, 0, _totalParticles * sizeof(V3F_T2F_C4B_Quad)); memset(_indices, 0, _totalParticles * 6 * sizeof(unsigned short)); return true; @@ -818,8 +803,8 @@ void ParticleSystemQuad::setBatchNode(ParticleBatchNode* batchNode) else if (!oldBatch) { // copy current state to batch - V3F_C4B_T2F_Quad* batchQuads = _batchNode->getTextureAtlas()->getQuads(); - V3F_C4B_T2F_Quad* quad = &(batchQuads[_atlasIndex]); + auto batchQuads = _batchNode->getTextureAtlas()->getQuads(); + auto quad = &(batchQuads[_atlasIndex]); memcpy(quad, _quads, _totalParticles * sizeof(_quads[0])); AX_SAFE_FREE(_quads); diff --git a/core/2d/ParticleSystemQuad.h b/axmol/2d/ParticleSystemQuad.h similarity index 87% rename from core/2d/ParticleSystemQuad.h rename to axmol/2d/ParticleSystemQuad.h index 70a7c8df0171..cf2e182835fc 100644 --- a/core/2d/ParticleSystemQuad.h +++ b/axmol/2d/ParticleSystemQuad.h @@ -29,8 +29,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/ParticleSystem.h" -#include "renderer/QuadCommand.h" +#include "axmol/2d/ParticleSystem.h" +#include "axmol/renderer/QuadCommand.h" namespace ax { @@ -111,26 +111,26 @@ class AX_DLL ParticleSystemQuad : public ParticleSystem /** * @lua NA */ - virtual void setTexture(Texture2D* texture) override; + void setTexture(Texture2D* texture) override; /** * @lua NA */ - virtual void updateParticleQuads() override; + void updateParticleQuads() override; /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * @lua NA */ - virtual void setBatchNode(ParticleBatchNode* batchNode) override; + void setBatchNode(ParticleBatchNode* batchNode) override; /** * @lua NA */ - virtual void setTotalParticles(int tp) override; + void setTotalParticles(int tp) override; - virtual std::string getDescription() const override; + std::string getDescription() const override; /** */ @@ -144,7 +144,7 @@ class AX_DLL ParticleSystemQuad : public ParticleSystem /** * @lua NA */ - virtual bool initWithTotalParticles(int numberOfParticles) override; + bool initWithTotalParticles(int numberOfParticles) override; protected: /** initializes the indices for the vertices*/ @@ -158,13 +158,12 @@ class AX_DLL ParticleSystemQuad : public ParticleSystem bool allocMemory(); - V3F_C4B_T2F_Quad* _quads = nullptr; // quads to be rendered + V3F_T2F_C4B_Quad* _quads = nullptr; // quads to be rendered unsigned short* _indices = nullptr; // indices QuadCommand _quadCommand; // quad command - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _textureLocation; + rhi::UniformLocation _mvpMatrixLocaiton; private: AX_DISALLOW_COPY_AND_ASSIGN(ParticleSystemQuad); diff --git a/core/2d/PlistSpriteSheetLoader.cpp b/axmol/2d/PlistSpriteSheetLoader.cpp similarity index 94% rename from core/2d/PlistSpriteSheetLoader.cpp rename to axmol/2d/PlistSpriteSheetLoader.cpp index f86edf854007..07024e88aba4 100644 --- a/core/2d/PlistSpriteSheetLoader.cpp +++ b/axmol/2d/PlistSpriteSheetLoader.cpp @@ -22,19 +22,19 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/PlistSpriteSheetLoader.h" - -#include "platform/FileUtils.h" -#include "2d/AutoPolygon.h" -#include "2d/SpriteFrameCache.h" -#include "base/NinePatchImageParser.h" -#include "base/NS.h" -#include "base/Macros.h" -#include "base/UTF8.h" -#include "base/Utils.h" -#include "base/Director.h" -#include "renderer/Texture2D.h" -#include "renderer/TextureCache.h" +#include "axmol/2d/PlistSpriteSheetLoader.h" + +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/AutoPolygon.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/base/NinePatchImageParser.h" +#include "axmol/base/NS.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Utils.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/TextureCache.h" #include @@ -361,21 +361,21 @@ void PlistSpriteSheetLoader::addSpriteFramesWithDictionary(ValueMap& dict, } Texture2D* texture = nullptr; - static std::unordered_map pixelFormats = { - {"RGBA8888", backend::PixelFormat::RGBA8}, - {"RGBA4444", backend::PixelFormat::RGBA4}, - {"RGB5A1", backend::PixelFormat::RGB5A1}, - {"RGBA5551", backend::PixelFormat::RGB5A1}, - {"RGB565", backend::PixelFormat::RGB565}, - {"R8", backend::PixelFormat::R8}, - {"RG8", backend::PixelFormat::RG8}, - //{"BGRA8888", backend::PixelFormat::BGRA8888}, no Image conversion RGBA -> BGRA - {"RGB888", backend::PixelFormat::RGB8}}; + static std::unordered_map pixelFormats = { + {"RGBA8888", rhi::PixelFormat::RGBA8}, + {"RGBA4444", rhi::PixelFormat::RGBA4}, + {"RGB5A1", rhi::PixelFormat::RGB5A1}, + {"RGBA5551", rhi::PixelFormat::RGB5A1}, + {"RGB565", rhi::PixelFormat::RGB565}, + {"R8", rhi::PixelFormat::R8}, + {"RG8", rhi::PixelFormat::RG8}, + //{"BGRA8888", rhi::PixelFormat::BGRA8888}, no Image conversion RGBA -> BGRA + {"RGB888", rhi::PixelFormat::RGB8}}; const auto pixelFormatIt = pixelFormats.find(pixelFormatName); if (pixelFormatIt != pixelFormats.end()) { - const backend::PixelFormat pixelFormat = (*pixelFormatIt).second; + const rhi::PixelFormat pixelFormat = (*pixelFormatIt).second; texture = Director::getInstance()->getTextureCache()->addImage(texturePath, pixelFormat); } else diff --git a/core/2d/PlistSpriteSheetLoader.h b/axmol/2d/PlistSpriteSheetLoader.h similarity index 96% rename from core/2d/PlistSpriteSheetLoader.h rename to axmol/2d/PlistSpriteSheetLoader.h index 57706c2cffd3..4f8e08e225ed 100644 --- a/core/2d/PlistSpriteSheetLoader.h +++ b/axmol/2d/PlistSpriteSheetLoader.h @@ -26,9 +26,9 @@ #include -#include "2d/SpriteSheetLoader.h" -#include "base/Value.h" -#include "base/Data.h" +#include "axmol/2d/SpriteSheetLoader.h" +#include "axmol/base/Value.h" +#include "axmol/base/Data.h" namespace ax { diff --git a/core/2d/ProgressTimer.cpp b/axmol/2d/ProgressTimer.cpp similarity index 77% rename from core/2d/ProgressTimer.cpp rename to axmol/2d/ProgressTimer.cpp index a4d9df0810e7..05ec7aa24a5f 100644 --- a/core/2d/ProgressTimer.cpp +++ b/axmol/2d/ProgressTimer.cpp @@ -25,17 +25,17 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/ProgressTimer.h" +#include "axmol/2d/ProgressTimer.h" #include #include // offsetof -#include "base/Types.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "2d/Sprite.h" -#include "renderer/Renderer.h" -#include "base/Utils.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Sprite.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -46,28 +46,28 @@ const char kProgressTextureCoords = 0x4b; namespace { -backend::ProgramState* initPipelineDescriptor(ax::CustomCommand& command, +rhi::ProgramState* initPipelineDesc(ax::CustomCommand& command, bool ridal, - backend::UniformLocation& locMVP, - backend::UniformLocation& locTexture) + rhi::UniformLocation& locMVP, + rhi::UniformLocation& locTexture) { - auto& pipelieDescriptor = command.getPipelineDescriptor(); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - auto programState = new backend::ProgramState(program); - AX_SAFE_RELEASE(pipelieDescriptor.programState); - pipelieDescriptor.programState = programState; + auto& pipelieDesc = command.getPipelineDesc(); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR); + auto programState = new rhi::ProgramState(program); + AX_SAFE_RELEASE(pipelieDesc.programState); + pipelieDesc.programState = programState; - // set custom vertexLayout according to V2F_C4B_T2F structure + // set custom vertexLayout according to V2F_T2F_C4F structure auto vertexLayout = programState->getMutableVertexLayout(); - vertexLayout->setAttrib("a_position", program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - vertexLayout->setAttrib("a_texCoord", program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, - offsetof(V2F_C4B_T2F, texCoords), false); - vertexLayout->setAttrib("a_color", program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, - offsetof(V2F_C4B_T2F, colors), true); - vertexLayout->setStride(sizeof(V2F_C4B_T2F)); + vertexLayout->setAttrib("a_position", program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT2, 0, false); + vertexLayout->setAttrib("a_texCoord", program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, + offsetof(V2F_T2F_C4F, texCoord), false); + vertexLayout->setAttrib("a_color", program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, + offsetof(V2F_T2F_C4F, color), false); + vertexLayout->setStride(sizeof(V2F_T2F_C4F)); if (ridal) { @@ -109,8 +109,8 @@ bool ProgressTimer::initWithSprite(Sprite* sp) // TODO: Use ProgramState Vector to Node AX_SAFE_RELEASE(_programState2); - setProgramState(initPipelineDescriptor(_customCommand, true, _locMVP1, _locTex1), true); - _programState2 = initPipelineDescriptor(_customCommand2, false, _locMVP2, _locTex2); + setProgramState(initPipelineDesc(_customCommand, true, _locMVP1, _locTex1), true); + _programState2 = initPipelineDesc(_customCommand2, false, _locMVP2, _locTex2); return true; } @@ -202,9 +202,9 @@ Tex2F ProgressTimer::textureCoordFromAlphaPoint(Vec2 alpha) { return ret; } - V3F_C4B_T2F_Quad quad = _sprite->getQuad(); - Vec2 min(quad.bl.texCoords.u, quad.bl.texCoords.v); - Vec2 max(quad.tr.texCoords.u, quad.tr.texCoords.v); + auto& quad = _sprite->getQuad(); + Vec2 min(quad.bl.texCoord.u, quad.bl.texCoord.v); + Vec2 max(quad.tr.texCoord.u, quad.tr.texCoord.v); // Fix bug #1303 so that progress timer handles sprite frame texture rotation if (_sprite->isTextureRectRotated()) { @@ -220,9 +220,9 @@ Vec2 ProgressTimer::vertexFromAlphaPoint(Vec2 alpha) { return ret; } - V3F_C4B_T2F_Quad quad = _sprite->getQuad(); - Vec2 min(quad.bl.vertices.x, quad.bl.vertices.y); - Vec2 max(quad.tr.vertices.x, quad.tr.vertices.y); + auto& quad = _sprite->getQuad(); + Vec2 min(quad.bl.position.x, quad.bl.position.y); + Vec2 max(quad.tr.position.x, quad.tr.position.y); ret.x = min.x * (1.f - alpha.x) + max.x * alpha.x; ret.y = min.y * (1.f - alpha.y) + max.y * alpha.y; return ret; @@ -232,19 +232,19 @@ void ProgressTimer::updateDisplayedOpacity(uint8_t parentOpacity) { Node::updateDisplayedOpacity(parentOpacity); - _displayedOpacity = _realOpacity * parentOpacity / 0xFF; + _displayedColor.a = _realColor.a * parentOpacity / 0xFF; - _sprite->setOpacity(_displayedOpacity); + _sprite->setOpacity(_displayedColor.a); updateColor(); updateProgress(); if (_cascadeOpacityEnabled) { - _sprite->updateDisplayedOpacity(_displayedOpacity); + _sprite->updateDisplayedOpacity(_displayedColor.a); for(const auto& child : _children) { - child->updateDisplayedOpacity(_displayedOpacity); + child->updateDisplayedOpacity(_displayedColor.a); } } } @@ -256,14 +256,14 @@ void ProgressTimer::updateColor() if (!_vertexData.empty()) { - auto sc = _sprite->getQuad().tl.colors; + auto sc = _sprite->getQuad().tl.color; sc.r = sc.r * _sprite->getOpacity() / 255.0f; sc.g = sc.g * _sprite->getOpacity() / 255.0f; sc.b = sc.b * _sprite->getOpacity() / 255.0f; sc.a = sc.a * _sprite->getOpacity() / 255.0f; for (auto& d : _vertexData) { - d.colors = sc; + d.color = ax::Color{sc}; } } } @@ -293,22 +293,22 @@ Vec2 ProgressTimer::getMidpoint() const return _midpoint; } -void ProgressTimer::setColor(const Color3B& color) +void ProgressTimer::setColor(const Color32& color) { _sprite->setColor(color); updateColor(); } -const Color3B& ProgressTimer::getColor() const +const Color32& ProgressTimer::getColor() const { return _sprite->getColor(); } void ProgressTimer::setOpacity(uint8_t opacity) { - _displayedOpacity = _realOpacity = opacity; + _displayedColor.a = _realColor.a = opacity; - _sprite->setOpacity(_displayedOpacity); + _sprite->setOpacity(opacity); updateColor(); updateCascadeOpacity(); @@ -454,17 +454,17 @@ void ProgressTimer::updateRadial() { // First we populate the array with the _midpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint - _vertexData[0].texCoords = textureCoordFromAlphaPoint(_midpoint); - _vertexData[0].vertices = vertexFromAlphaPoint(_midpoint); + _vertexData[0].texCoord = textureCoordFromAlphaPoint(_midpoint); + _vertexData[0].position = vertexFromAlphaPoint(_midpoint); - _vertexData[1].texCoords = textureCoordFromAlphaPoint(topMid); - _vertexData[1].vertices = vertexFromAlphaPoint(topMid); + _vertexData[1].texCoord = textureCoordFromAlphaPoint(topMid); + _vertexData[1].position = vertexFromAlphaPoint(topMid); for (int i = 0; i < index; ++i) { Vec2 alphaPoint = boundaryTexCoord(i); - _vertexData[i + 2].texCoords = textureCoordFromAlphaPoint(alphaPoint); - _vertexData[i + 2].vertices = vertexFromAlphaPoint(alphaPoint); + _vertexData[i + 2].texCoord = textureCoordFromAlphaPoint(alphaPoint); + _vertexData[i + 2].position = vertexFromAlphaPoint(alphaPoint); } for (int i = 0; i < index + 1; i++) @@ -478,8 +478,8 @@ void ProgressTimer::updateRadial() } // hitpoint will go last - _vertexData[_vertexData.size() - 1].texCoords = textureCoordFromAlphaPoint(hit); - _vertexData[_vertexData.size() - 1].vertices = vertexFromAlphaPoint(hit); + _vertexData[_vertexData.size() - 1].texCoord = textureCoordFromAlphaPoint(hit); + _vertexData[_vertexData.size() - 1].position = vertexFromAlphaPoint(hit); updateColor(); _customCommand.updateVertexBuffer(_vertexData.data(), (unsigned int)(sizeof(_vertexData[0]) * _vertexData.size())); @@ -541,20 +541,20 @@ void ProgressTimer::updateBar() } // TOPLEFT - _vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); - _vertexData[0].vertices = vertexFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[0].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[0].position = vertexFromAlphaPoint(Vec2(min.x, max.y)); // BOTLEFT - _vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); - _vertexData[1].vertices = vertexFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[1].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[1].position = vertexFromAlphaPoint(Vec2(min.x, min.y)); // TOPRIGHT - _vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); - _vertexData[2].vertices = vertexFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[2].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[2].position = vertexFromAlphaPoint(Vec2(max.x, max.y)); // BOTRIGHT - _vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); - _vertexData[3].vertices = vertexFromAlphaPoint(Vec2(max.x, min.y)); + _vertexData[3].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); + _vertexData[3].position = vertexFromAlphaPoint(Vec2(max.x, min.y)); updateColor(); @@ -571,37 +571,37 @@ void ProgressTimer::updateBar() _customCommand2.createVertexBuffer(sizeof(_vertexData[0]), (unsigned int)(_vertexData.size() / 2), CustomCommand::BufferUsage::DYNAMIC); // TOPLEFT 1 - _vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(0, 1)); - _vertexData[0].vertices = vertexFromAlphaPoint(Vec2(0, 1)); + _vertexData[0].texCoord = textureCoordFromAlphaPoint(Vec2(0, 1)); + _vertexData[0].position = vertexFromAlphaPoint(Vec2(0, 1)); // BOTLEFT 1 - _vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(0, 0)); - _vertexData[1].vertices = vertexFromAlphaPoint(Vec2(0, 0)); + _vertexData[1].texCoord = textureCoordFromAlphaPoint(Vec2(0, 0)); + _vertexData[1].position = vertexFromAlphaPoint(Vec2(0, 0)); // TOPRIGHT 2 - _vertexData[6].texCoords = textureCoordFromAlphaPoint(Vec2(1, 1)); - _vertexData[6].vertices = vertexFromAlphaPoint(Vec2(1, 1)); + _vertexData[6].texCoord = textureCoordFromAlphaPoint(Vec2(1, 1)); + _vertexData[6].position = vertexFromAlphaPoint(Vec2(1, 1)); // BOTRIGHT 2 - _vertexData[7].texCoords = textureCoordFromAlphaPoint(Vec2(1, 0)); - _vertexData[7].vertices = vertexFromAlphaPoint(Vec2(1, 0)); + _vertexData[7].texCoord = textureCoordFromAlphaPoint(Vec2(1, 0)); + _vertexData[7].position = vertexFromAlphaPoint(Vec2(1, 0)); } // TOPRIGHT 1 - _vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); - _vertexData[2].vertices = vertexFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[2].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[2].position = vertexFromAlphaPoint(Vec2(min.x, max.y)); // BOTRIGHT 1 - _vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); - _vertexData[3].vertices = vertexFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[3].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[3].position = vertexFromAlphaPoint(Vec2(min.x, min.y)); // TOPLEFT 2 - _vertexData[4].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); - _vertexData[4].vertices = vertexFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[4].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[4].position = vertexFromAlphaPoint(Vec2(max.x, max.y)); // BOTLEFT 2 - _vertexData[5].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); - _vertexData[5].vertices = vertexFromAlphaPoint(Vec2(max.x, min.y)); + _vertexData[5].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); + _vertexData[5].position = vertexFromAlphaPoint(Vec2(max.x, min.y)); updateColor(); diff --git a/core/2d/ProgressTimer.h b/axmol/2d/ProgressTimer.h similarity index 87% rename from core/2d/ProgressTimer.h rename to axmol/2d/ProgressTimer.h index b25192d2c1b2..fabd30acfc7c 100644 --- a/core/2d/ProgressTimer.h +++ b/axmol/2d/ProgressTimer.h @@ -27,11 +27,11 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "renderer/CustomCommand.h" -#include "2d/Node.h" -#include "renderer/PipelineDescriptor.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/PipelineDesc.h" -#include +#include "axmol/base/axstd.h" namespace ax { @@ -151,13 +151,13 @@ class AX_DLL ProgressTimer : public Node Vec2 getBarChangeRate() const { return _barChangeRate; } // Overrides - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void setAnchorPoint(const Vec2& anchorPoint) override; - virtual void setColor(const Color3B& color) override; - virtual const Color3B& getColor() const override; - virtual void setOpacity(uint8_t opacity) override; - virtual uint8_t getOpacity() const override; - virtual uint8_t getDisplayedOpacity() const override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void setAnchorPoint(const Vec2& anchorPoint) override; + void setColor(const Color32& color) override; + const Color32& getColor() const override; + void setOpacity(uint8_t opacity) override; + uint8_t getOpacity() const override; + uint8_t getDisplayedOpacity() const override; /** */ @@ -185,20 +185,20 @@ class AX_DLL ProgressTimer : public Node Vec2 _barChangeRate; float _percentage = 0.0f; Sprite* _sprite = nullptr; - std::vector _vertexData; - std::vector _indexData; + axstd::pod_vector _vertexData; + axstd::pod_vector _indexData; bool _reverseDirection = false; CustomCommand _customCommand; CustomCommand _customCommand2; - backend::ProgramState* _programState2 = nullptr; + rhi::ProgramState* _programState2 = nullptr; - backend::UniformLocation _locMVP1; - backend::UniformLocation _locTex1; + rhi::UniformLocation _locMVP1; + rhi::UniformLocation _locTex1; - backend::UniformLocation _locMVP2; - backend::UniformLocation _locTex2; + rhi::UniformLocation _locMVP2; + rhi::UniformLocation _locTex2; private: AX_DISALLOW_COPY_AND_ASSIGN(ProgressTimer); diff --git a/core/2d/ProtectedNode.cpp b/axmol/2d/ProtectedNode.cpp similarity index 93% rename from core/2d/ProtectedNode.cpp rename to axmol/2d/ProtectedNode.cpp index b7414a296835..7b16cb4c687b 100644 --- a/core/2d/ProtectedNode.cpp +++ b/axmol/2d/ProtectedNode.cpp @@ -28,10 +28,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/ProtectedNode.h" +#include "axmol/2d/ProtectedNode.h" -#include "base/Director.h" -#include "2d/Scene.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Scene.h" namespace ax { @@ -369,28 +369,31 @@ void ProtectedNode::onExit() void ProtectedNode::updateDisplayedOpacity(uint8_t parentOpacity) { - _displayedOpacity = _realOpacity * parentOpacity / 255.0; + _displayedColor.a = _realColor.a * parentOpacity / 255.0; updateColor(); if (_cascadeOpacityEnabled) { for (auto&& child : _children) { - child->updateDisplayedOpacity(_displayedOpacity); + child->updateDisplayedOpacity(_displayedColor.a); } } for (auto&& child : _protectedChildren) { - child->updateDisplayedOpacity(_displayedOpacity); + child->updateDisplayedOpacity(_displayedColor.a); } } -void ProtectedNode::updateDisplayedColor(const Color3B& parentColor) +void ProtectedNode::updateDisplayedColor(const Color32& parentColor) { - _displayedColor.r = _realColor.r * parentColor.r / 255.0; - _displayedColor.g = _realColor.g * parentColor.g / 255.0; - _displayedColor.b = _realColor.b * parentColor.b / 255.0; + _displayedColor.r = _realColor.r * parentColor.r / 255.0f; + _displayedColor.g = _realColor.g * parentColor.g / 255.0f; + _displayedColor.b = _realColor.b * parentColor.b / 255.0f; + if (_cascadeOpacityEnabled) + _displayedColor.a = _realColor.a * parentColor.a / 255.0f; + updateColor(); if (_cascadeColorEnabled) @@ -410,17 +413,17 @@ void ProtectedNode::disableCascadeColor() { for (auto&& child : _children) { - child->updateDisplayedColor(Color3B::WHITE); + child->updateDisplayedColor(Color32::WHITE); } for (auto&& child : _protectedChildren) { - child->updateDisplayedColor(Color3B::WHITE); + child->updateDisplayedColor(Color32::WHITE); } } void ProtectedNode::disableCascadeOpacity() { - _displayedOpacity = _realOpacity; + _displayedColor.a = _realColor.a; for (auto&& child : _children) { diff --git a/core/2d/ProtectedNode.h b/axmol/2d/ProtectedNode.h similarity index 90% rename from core/2d/ProtectedNode.h rename to axmol/2d/ProtectedNode.h index 8dac74425377..c5573d6f0e18 100644 --- a/core/2d/ProtectedNode.h +++ b/axmol/2d/ProtectedNode.h @@ -30,7 +30,7 @@ #pragma once -#include "2d/Node.h" +#include "axmol/2d/Node.h" namespace ax { @@ -159,11 +159,11 @@ class AX_DLL ProtectedNode : public Node /** */ - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void cleanup() override; + void cleanup() override; - virtual void onEnter() override; + void onEnter() override; /** Event callback that is invoked when the Node enters in the 'stage'. * If the Node enters the 'stage' with a transition, this event is called when the transition finishes. @@ -171,7 +171,7 @@ class AX_DLL ProtectedNode : public Node * Node::onEnterTransitionDidFinish() * @lua NA */ - virtual void onEnterTransitionDidFinish() override; + void onEnterTransitionDidFinish() override; /** * Event callback that is invoked every time the Node leaves the 'stage'. @@ -180,21 +180,21 @@ class AX_DLL ProtectedNode : public Node * If you override onExit, you shall call its parent's one, e.g., Node::onExit(). * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * Event callback that is called every time the Node leaves the 'stage'. * If the Node leaves the 'stage' with a transition, this callback is called when the transition starts. * @lua NA */ - virtual void onExitTransitionDidStart() override; + void onExitTransitionDidStart() override; - virtual void updateDisplayedOpacity(uint8_t parentOpacity) override; - virtual void updateDisplayedColor(const Color3B& parentColor) override; - virtual void disableCascadeColor() override; - virtual void disableCascadeOpacity() override; - virtual void setCameraMask(unsigned short mask, bool applyChildren = true) override; - virtual void setGlobalZOrder(float globalZOrder) override; + void updateDisplayedOpacity(uint8_t parentOpacity) override; + void updateDisplayedColor(const Color32& parentColor) override; + void disableCascadeColor() override; + void disableCascadeOpacity() override; + void setCameraMask(unsigned short mask, bool applyChildren = true) override; + void setGlobalZOrder(float globalZOrder) override; ProtectedNode(); virtual ~ProtectedNode(); diff --git a/core/2d/RenderTexture.cpp b/axmol/2d/RenderTexture.cpp similarity index 91% rename from core/2d/RenderTexture.cpp rename to axmol/2d/RenderTexture.cpp index 0d348e736830..454b88a97dac 100644 --- a/core/2d/RenderTexture.cpp +++ b/axmol/2d/RenderTexture.cpp @@ -25,23 +25,23 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/RenderTexture.h" - -#include "base/Utils.h" -#include "platform/FileUtils.h" -#include "base/EventType.h" -#include "base/Configuration.h" -#include "base/Director.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "renderer/Renderer.h" -#include "2d/Camera.h" -#include "renderer/TextureCache.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/RenderTarget.h" -#if defined(AX_USE_GL) -# include "renderer/backend/opengl/CommandBufferGL.h" +#include "axmol/2d/RenderTexture.h" + +#include "axmol/base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/RenderTarget.h" +#if AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/rhi/opengl/CommandBufferGL.h" #endif namespace ax @@ -85,7 +85,7 @@ void RenderTexture::listenToBackground(EventCustom* /*event*/) _UITextureImage = uiTextureImage; const Vec2& s = _texture2D->getContentSizeInPixels(); VolatileTextureMgr::addDataTexture(_texture2D, uiTextureImage->getData(), s.width * s.height * 4, - backend::PixelFormat::RGBA8, s); + rhi::PixelFormat::RGBA8, s); } else { @@ -104,7 +104,7 @@ void RenderTexture::listenToForeground(EventCustom* /*event*/) #endif } -RenderTexture* RenderTexture::create(int w, int h, backend::PixelFormat eFormat, bool sharedRenderTarget) +RenderTexture* RenderTexture::create(int w, int h, rhi::PixelFormat eFormat, bool sharedRenderTarget) { RenderTexture* ret = new RenderTexture(); @@ -119,7 +119,7 @@ RenderTexture* RenderTexture::create(int w, int h, backend::PixelFormat eFormat, RenderTexture* RenderTexture::create(int w, int h, - backend::PixelFormat eFormat, + rhi::PixelFormat eFormat, PixelFormat uDepthStencilFormat, bool sharedRenderTarget) { @@ -138,7 +138,7 @@ RenderTexture* RenderTexture::create(int w, int h, bool sharedRenderTarget) { RenderTexture* ret = new RenderTexture(); - if (ret->initWithWidthAndHeight(w, h, backend::PixelFormat::RGBA8, PixelFormat::NONE, sharedRenderTarget)) + if (ret->initWithWidthAndHeight(w, h, rhi::PixelFormat::RGBA8, PixelFormat::NONE, sharedRenderTarget)) { ret->autorelease(); return ret; @@ -147,18 +147,18 @@ RenderTexture* RenderTexture::create(int w, int h, bool sharedRenderTarget) return nullptr; } -bool RenderTexture::initWithWidthAndHeight(int w, int h, backend::PixelFormat eFormat, bool sharedRenderTarget) +bool RenderTexture::initWithWidthAndHeight(int w, int h, rhi::PixelFormat eFormat, bool sharedRenderTarget) { return initWithWidthAndHeight(w, h, eFormat, PixelFormat::NONE, sharedRenderTarget); } bool RenderTexture::initWithWidthAndHeight(int w, int h, - backend::PixelFormat format, + rhi::PixelFormat format, PixelFormat depthStencilFormat, bool sharedRenderTarget) { - AXASSERT(format == backend::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4, + AXASSERT(format == rhi::PixelFormat::RGBA8 || format == PixelFormat::RGB8 || format == PixelFormat::RGBA4, "only RGB and RGBA formats are valid for a render texture"); bool ret = false; @@ -186,13 +186,13 @@ bool RenderTexture::initWithWidthAndHeight(int w, powH = utils::nextPOT(h); } - backend::TextureDescriptor descriptor; + rhi::TextureDesc descriptor; descriptor.width = powW; descriptor.height = powH; descriptor.textureUsage = TextureUsage::RENDER_TARGET; descriptor.textureFormat = PixelFormat::RGBA8; _texture2D = new Texture2D(); - _texture2D->updateTextureDescriptor(descriptor, !!AX_ENABLE_PREMULTIPLIED_ALPHA); + _texture2D->updateTextureDesc(descriptor, !!AX_ENABLE_PREMULTIPLIED_ALPHA); if (PixelFormat::D24S8 == depthStencilFormat || sharedRenderTarget) { @@ -201,7 +201,7 @@ bool RenderTexture::initWithWidthAndHeight(int w, AX_SAFE_RELEASE(_depthStencilTexture); _depthStencilTexture = new Texture2D(); - _depthStencilTexture->updateTextureDescriptor(descriptor); + _depthStencilTexture->updateTextureDesc(descriptor); } AX_SAFE_RELEASE(_renderTarget); @@ -213,17 +213,15 @@ bool RenderTexture::initWithWidthAndHeight(int w, } else { - _renderTarget = backend::DriverBase::getInstance()->newRenderTarget( + _renderTarget = rhi::DriverBase::getInstance()->createRenderTarget( _texture2D ? _texture2D->getBackendTexture() : nullptr, - _depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr, _depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr); } _renderTarget->setColorAttachment(_texture2D ? _texture2D->getBackendTexture() : nullptr); auto depthStencilTexture = _depthStencilTexture ? _depthStencilTexture->getBackendTexture() : nullptr; - _renderTarget->setDepthAttachment(depthStencilTexture); - _renderTarget->setStencilAttachment(depthStencilTexture); + _renderTarget->setDepthStencilAttachment(depthStencilTexture); clearColorAttachment(); @@ -235,7 +233,7 @@ bool RenderTexture::initWithWidthAndHeight(int w, _sprite->setAnchorPoint(Vec2::ANCHOR_MIDDLE); _sprite->setPosition(Vec2(w, h) / 2); -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL _sprite->setFlippedY(true); #endif @@ -339,7 +337,7 @@ void RenderTexture::beginWithClear(float r, int stencilValue, ClearFlag flags) { - setClearColor(Color4F(r, g, b, a)); + setClearColor(Color(r, g, b, a)); setClearDepth(depthValue); setClearStencil(stencilValue); setClearFlags(flags); @@ -527,7 +525,7 @@ void RenderTexture::onSaveToFile(std::string filename, bool isRGBA, bool forceNo /* get buffer as Image */ void RenderTexture::newImage(std::function)> imageCallback, bool eglCacheHint) { - AXASSERT(_pixelFormat == backend::PixelFormat::RGBA8, "only RGBA8888 can be saved as image"); + AXASSERT(_pixelFormat == rhi::PixelFormat::RGBA8, "only RGBA8888 can be saved as image"); if ((nullptr == _texture2D)) { @@ -543,7 +541,7 @@ void RenderTexture::newImage(std::function)> imageCallback, b int savedBufferHeight = (int)s.height; bool hasPremultipliedAlpha = _texture2D->hasPremultipliedAlpha(); - auto callback = [hasPremultipliedAlpha, imageCallback](const backend::PixelBufferDescriptor& pbd) { + auto callback = [hasPremultipliedAlpha, imageCallback](const rhi::PixelBufferDesc& pbd) { if (pbd) { auto image = utils::makeInstance(&Image::initWithRawData, pbd._data.getBytes(), pbd._data.getSize(), @@ -553,14 +551,14 @@ void RenderTexture::newImage(std::function)> imageCallback, b else imageCallback(nullptr); }; -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL if (eglCacheHint) { auto colorAttachment = _renderTarget->_color[0].texture; if (colorAttachment) { - backend::PixelBufferDescriptor pbd; - static_cast(_director->getRenderer()->getCommandBuffer()) + rhi::PixelBufferDesc pbd; + static_cast(_director->getRenderer()->getCommandBuffer()) ->readPixels(_renderTarget, 0, 0, colorAttachment->getWidth(), colorAttachment->getHeight(), colorAttachment->getWidth() * 4, true, pbd); callback(pbd); @@ -725,7 +723,7 @@ void RenderTexture::clearColorAttachment() }; renderer->addCommand(beforeClearAttachmentCommand); - Color4F color(0.f, 0.f, 0.f, 0.f); + Color color(0.f, 0.f, 0.f, 0.f); renderer->clear(ClearFlag::COLOR, color, 1, 0, _globalZOrder); // auto renderer = _director->getRenderer(); diff --git a/core/2d/RenderTexture.h b/axmol/2d/RenderTexture.h similarity index 92% rename from core/2d/RenderTexture.h rename to axmol/2d/RenderTexture.h index d10f98ff720f..15fe76bd5a07 100644 --- a/core/2d/RenderTexture.h +++ b/axmol/2d/RenderTexture.h @@ -27,22 +27,21 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" -#include "2d/Sprite.h" -#include "platform/Image.h" -#include "renderer/GroupCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" -#include "renderer/backend/Types.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Sprite.h" +#include "axmol/platform/Image.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" namespace ax { -namespace backend +namespace rhi { -class TextureBackend; +class Texture; class RenderTarget; -} // namespace backend +} // namespace rhi class EventCustom; @@ -75,8 +74,8 @@ class AX_DLL RenderTexture : public Node */ static RenderTexture* create(int w, int h, - backend::PixelFormat format, - backend::PixelFormat depthStencilFormat, + rhi::PixelFormat format, + rhi::PixelFormat depthStencilFormat, bool sharedRenderTarget = false); /** Creates a RenderTexture object with width and height in Points and a pixel format, only RGB and RGBA formats are @@ -87,7 +86,7 @@ class AX_DLL RenderTexture : public Node * @param format In Points and a pixel format( only RGB and RGBA formats are valid ). * @param sharedRenderTarget Select whether to use a new or shared render target. */ - static RenderTexture* create(int w, int h, backend::PixelFormat format, bool sharedRenderTarget = false); + static RenderTexture* create(int w, int h, rhi::PixelFormat format, bool sharedRenderTarget = false); /** Creates a RenderTexture object with width and height in Points, pixel format is RGBA8888. * @@ -98,9 +97,9 @@ class AX_DLL RenderTexture : public Node static RenderTexture* create(int w, int h, bool sharedRenderTarget = false); // Overrides - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** Starts grabbing. */ virtual void begin(); @@ -260,13 +259,13 @@ class AX_DLL RenderTexture : public Node * * @return Color value. */ - inline const Color4F& getClearColor() const { return _clearColor; } + inline const Color& getClearColor() const { return _clearColor; } /** Set color value. * * @param clearColor Color value. */ - inline void setClearColor(const Color4F& clearColor) { _clearColor = clearColor; } + inline void setClearColor(const Color& clearColor) { _clearColor = clearColor; } /** Value for clearDepth. Valid only when "autoDraw" is true. * @@ -311,7 +310,7 @@ class AX_DLL RenderTexture : public Node */ inline Sprite* getSprite() const { return _sprite; } - inline backend::RenderTarget* getRenderTarget() const { return _renderTarget; } + inline rhi::RenderTarget* getRenderTarget() const { return _renderTarget; } /** Flag: Use stack matrix computed from scene hierarchy or generate new modelView and projection matrix. * @@ -352,7 +351,7 @@ class AX_DLL RenderTexture : public Node * @param sharedRenderTarget Select whether to use a new or shared render target. * @return If succeed, it will return true. */ - bool initWithWidthAndHeight(int w, int h, backend::PixelFormat format, bool sharedRenderTarget = true); + bool initWithWidthAndHeight(int w, int h, rhi::PixelFormat format, bool sharedRenderTarget = true); /** Initializes a RenderTexture object with width and height in Points and a pixel format( only RGB and RGBA formats * are valid ) and depthStencil format. * @@ -365,8 +364,8 @@ class AX_DLL RenderTexture : public Node */ bool initWithWidthAndHeight(int w, int h, - backend::PixelFormat format, - backend::PixelFormat depthStencilFormat, + rhi::PixelFormat format, + rhi::PixelFormat depthStencilFormat, bool sharedRenderTarget = true); /** @@ -415,13 +414,13 @@ class AX_DLL RenderTexture : public Node Texture2D* _texture2D = nullptr; Texture2D* _depthStencilTexture = nullptr; - backend::RenderTarget* _renderTarget = nullptr; - backend::RenderTarget* _oldRenderTarget = nullptr; + rhi::RenderTarget* _renderTarget = nullptr; + rhi::RenderTarget* _oldRenderTarget = nullptr; RefPtr _UITextureImage = nullptr; - backend::PixelFormat _pixelFormat = backend::PixelFormat::RGBA8; + rhi::PixelFormat _pixelFormat = rhi::PixelFormat::RGBA8; - Color4F _clearColor; + Color _clearColor; float _clearDepth = 1.f; int _clearStencil = 0; bool _autoDraw = false; diff --git a/core/2d/Scene.cpp b/axmol/2d/Scene.cpp similarity index 96% rename from core/2d/Scene.cpp rename to axmol/2d/Scene.cpp index dd7266190e28..19d5593a74d5 100644 --- a/core/2d/Scene.cpp +++ b/axmol/2d/Scene.cpp @@ -27,25 +27,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Scene.h" -#include "base/Director.h" -#include "2d/Camera.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerCustom.h" -#include "base/UTF8.h" -#include "renderer/Renderer.h" +#include "axmol/2d/Scene.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/text_utils.h" +#include "axmol/renderer/Renderer.h" #if defined(AX_ENABLE_PHYSICS) -# include "physics/PhysicsWorld.h" +# include "axmol/physics/PhysicsWorld.h" #endif #if defined(AX_ENABLE_3D_PHYSICS) -# include "physics3d/Physics3DWorld.h" -# include "physics3d/Physics3DComponent.h" +# include "axmol/physics3d/Physics3DWorld.h" +# include "axmol/physics3d/Physics3DComponent.h" #endif #if defined(AX_ENABLE_NAVMESH) -# include "navmesh/NavMesh.h" +# include "axmol/navmesh/NavMesh.h" #endif namespace ax diff --git a/core/2d/Scene.h b/axmol/2d/Scene.h similarity index 98% rename from core/2d/Scene.h rename to axmol/2d/Scene.h index 7fae818a145f..367ad3ea3155 100644 --- a/core/2d/Scene.h +++ b/axmol/2d/Scene.h @@ -30,7 +30,7 @@ THE SOFTWARE. #pragma once #include -#include "2d/Node.h" +#include "axmol/2d/Node.h" namespace ax { @@ -85,7 +85,7 @@ class AX_DLL Scene : public Node static Scene* createWithSize(const Vec2& size); using Node::addChild; - virtual std::string getDescription() const override; + std::string getDescription() const override; /** Get all cameras. * @@ -114,7 +114,7 @@ class AX_DLL Scene : public Node void visit() override; /** override function */ - virtual void removeAllChildren() override; + void removeAllChildren() override; Scene(); virtual ~Scene(); diff --git a/core/2d/Sprite.cpp b/axmol/2d/Sprite.cpp similarity index 90% rename from core/2d/Sprite.cpp rename to axmol/2d/Sprite.cpp index aaea078e19f8..aad6a6c1ec3f 100644 --- a/core/2d/Sprite.cpp +++ b/axmol/2d/Sprite.cpp @@ -26,24 +26,24 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Sprite.h" +#include "axmol/2d/Sprite.h" #include #include // offsetof -#include "base/Types.h" -#include "2d/SpriteBatchNode.h" -#include "2d/AnimationCache.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" -#include "renderer/TextureCache.h" -#include "renderer/Texture2D.h" -#include "renderer/Renderer.h" -#include "base/Director.h" -#include "base/UTF8.h" -#include "2d/Camera.h" -#include "platform/FileUtils.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/base/Types.h" +#include "axmol/2d/SpriteBatchNode.h" +#include "axmol/2d/AnimationCache.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/2d/Camera.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/DriverBase.h" namespace ax { @@ -75,7 +75,7 @@ Sprite* Sprite::createWithTexture(Texture2D* texture, const Rect& rect, bool rot Sprite* Sprite::create(std::string_view filename) { - return Sprite::create(filename, Texture2D::getDefaultAlphaPixelFormat()); + return Sprite::create(filename, PixelFormat::NONE); } Sprite* Sprite::create(std::string_view filename, PixelFormat format) @@ -142,7 +142,7 @@ Sprite* Sprite::createWithSpriteFrameName(std::string_view spriteFrameName) { SpriteFrame* frame = SpriteFrameCache::getInstance()->getSpriteFrameByName(spriteFrameName); -#if _AX_DEBUG > 0 +#if defined(_AX_DEBUG) && _AX_DEBUG > 0 char msg[256]; fmt::format_to_z(msg, "Invalid spriteFrameName: {}", spriteFrameName); AXASSERT(frame != nullptr, msg); @@ -187,7 +187,7 @@ bool Sprite::initWithTexture(Texture2D* texture, const Rect& rect) bool Sprite::initWithFile(std::string_view filename) { - return initWithFile(filename, Texture2D::getDefaultAlphaPixelFormat()); + return initWithFile(filename, PixelFormat::NONE); } bool Sprite::initWithFile(std::string_view filename, PixelFormat format) @@ -296,10 +296,10 @@ bool Sprite::initWithTexture(Texture2D* texture, const Rect& rect, bool rotated) memset(&_quad, 0, sizeof(_quad)); // Atlas: Color - _quad.bl.colors = Color4B::WHITE; - _quad.br.colors = Color4B::WHITE; - _quad.tl.colors = Color4B::WHITE; - _quad.tr.colors = Color4B::WHITE; + _quad.bl.color = Color32::WHITE; + _quad.br.color = Color32::WHITE; + _quad.tl.color = Color32::WHITE; + _quad.tr.color = Color32::WHITE; // update texture (calls updateBlendFunc) setTexture(texture); @@ -378,7 +378,7 @@ void Sprite::setTexture(std::string_view filename) void Sprite::setVertexLayout() { AXASSERT(_programState, "programState should not be nullptr"); - _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); + _programState->validateSharedVertexLayout(rhi::VertexLayoutType::Sprite); } void Sprite::setProgramState(uint32_t type) @@ -386,15 +386,15 @@ void Sprite::setProgramState(uint32_t type) setProgramStateWithRegistry(type, _texture); } -bool Sprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) +bool Sprite::setProgramState(rhi::ProgramState* programState, bool ownPS/* = false*/) { AXASSERT(programState, "argument should not be nullptr"); if (Node::setProgramState(programState, ownPS)) { - auto& pipelineDescriptor = _trianglesCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _trianglesCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; - _mvpMatrixLocation = _programState->getUniformLocation(backend::Uniform::MVP_MATRIX); + _mvpMatrixLocation = _programState->getUniformLocation(rhi::Uniform::MVP_MATRIX); setVertexLayout(); updateProgramStateTexture(_texture); @@ -407,10 +407,7 @@ bool Sprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = void Sprite::setTexture(Texture2D* texture) { AXASSERT(!_batchNode || (texture && texture == _batchNode->getTexture()), - "CCSprite: Batched sprites should use the same texture as the batchnode"); - // accept texture==nil as argument - AXASSERT(!texture || dynamic_cast(texture), "setTexture expects a Texture2D. Invalid argument"); - + "Sprite: Batched sprites should use the same texture as the batchnode"); if (texture == nullptr) { // Gets the texture by key firstly. @@ -419,8 +416,9 @@ void Sprite::setTexture(Texture2D* texture) bool needsUpdatePS = _autoUpdatePS && - ((!_programState || _programState->getProgram()->getProgramType() < backend::ProgramType::CUSTOM_PROGRAM) && - (_texture == nullptr || _texture->getSamplerFlags() != texture->getSamplerFlags())); + ((!_programState || _programState->getProgram()->getProgramType() < rhi::ProgramType::CUSTOM_PROGRAM) && + (_texture == nullptr || _texture->getSamplerFlags() != texture->getSamplerFlags() || + _texture->getPixelFormat() != texture->getPixelFormat())); if (_renderMode != RenderMode::QUAD_BATCHNODE) { @@ -434,7 +432,10 @@ void Sprite::setTexture(Texture2D* texture) } if (needsUpdatePS) - setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + { + auto programType = ProgramManager::chooseSpriteProgramType(_texture->getPixelFormat()); + setProgramState(programType); + } else updateProgramStateTexture(_texture); } @@ -683,7 +684,7 @@ void Sprite::updatePoly() }; // needed in order to get color from "_quad" - V3F_C4B_T2F_Quad tmpQuad = _quad; + V3F_T2F_C4B_Quad tmpQuad = _quad; for (int i = 0; i < 9; ++i) { @@ -736,7 +737,7 @@ void Sprite::setCenterRectNormalized(const ax::Rect& rectTopLeft) { _renderMode = RenderMode::SLICE9; // 9 quads + 7 exterior points = 16 - _trianglesVertex = (V3F_C4B_T2F*)malloc(sizeof(*_trianglesVertex) * (9 + 3 + 4)); + _trianglesVertex = (V3F_T2F_C4B*)malloc(sizeof(*_trianglesVertex) * (9 + 3 + 4)); // 9 quads, each needs 6 vertices = 54 _trianglesIndex = (unsigned short*)malloc(sizeof(*_trianglesIndex) * 6 * 9); @@ -808,7 +809,7 @@ void Sprite::setTextureCoords(const Rect& rectInPoints) setTextureCoords(rectInPoints, &_quad); } -void Sprite::setTextureCoords(const Rect& rectInPoints, V3F_C4B_T2F_Quad* outQuad) +void Sprite::setTextureCoords(const Rect& rectInPoints, V3F_T2F_C4B_Quad* outQuad) { Texture2D* tex = (_renderMode == RenderMode::QUAD_BATCHNODE) ? _textureAtlas->getTexture() : _texture; @@ -856,29 +857,29 @@ void Sprite::setTextureCoords(const Rect& rectInPoints, V3F_C4B_T2F_Quad* outQua if (_rectRotated) { - outQuad->bl.texCoords.u = left; - outQuad->bl.texCoords.v = top; - outQuad->br.texCoords.u = left; - outQuad->br.texCoords.v = bottom; - outQuad->tl.texCoords.u = right; - outQuad->tl.texCoords.v = top; - outQuad->tr.texCoords.u = right; - outQuad->tr.texCoords.v = bottom; + outQuad->bl.texCoord.u = left; + outQuad->bl.texCoord.v = top; + outQuad->br.texCoord.u = left; + outQuad->br.texCoord.v = bottom; + outQuad->tl.texCoord.u = right; + outQuad->tl.texCoord.v = top; + outQuad->tr.texCoord.u = right; + outQuad->tr.texCoord.v = bottom; } else { - outQuad->bl.texCoords.u = left; - outQuad->bl.texCoords.v = bottom; - outQuad->br.texCoords.u = right; - outQuad->br.texCoords.v = bottom; - outQuad->tl.texCoords.u = left; - outQuad->tl.texCoords.v = top; - outQuad->tr.texCoords.u = right; - outQuad->tr.texCoords.v = top; + outQuad->bl.texCoord.u = left; + outQuad->bl.texCoord.v = bottom; + outQuad->br.texCoord.u = right; + outQuad->br.texCoord.v = bottom; + outQuad->tl.texCoord.u = left; + outQuad->tl.texCoord.v = top; + outQuad->tr.texCoord.u = right; + outQuad->tr.texCoord.v = top; } } -void Sprite::setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad) +void Sprite::setVertexCoords(const Rect& rect, V3F_T2F_C4B_Quad* outQuad) { float relativeOffsetX = _unflippedOffsetPositionFromCenter.x; float relativeOffsetY = _unflippedOffsetPositionFromCenter.y; @@ -917,14 +918,14 @@ void Sprite::setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad) const float y2 = y1 + rect.size.height; // Don't update Z. - outQuad->bl.vertices.set(x1, y1, 0.0f); - outQuad->br.vertices.set(x2, y1, 0.0f); - outQuad->tl.vertices.set(x1, y2, 0.0f); - outQuad->tr.vertices.set(x2, y2, 0.0f); + outQuad->bl.position.set(x1, y1, 0.0f); + outQuad->br.position.set(x2, y1, 0.0f); + outQuad->tl.position.set(x1, y2, 0.0f); + outQuad->tr.position.set(x2, y2, 0.0f); } } -void Sprite::populateTriangle(int quadIndex, const V3F_C4B_T2F_Quad& quad) +void Sprite::populateTriangle(int quadIndex, const V3F_T2F_C4B_Quad& quad) { AXASSERT(quadIndex < 9, "Invalid quadIndex"); // convert Quad intro Triangle since it takes less memory @@ -993,10 +994,10 @@ void Sprite::updateTransform() // If it is not visible, or one of its ancestors is not visible, then do nothing: if (!_visible || (_parent && _parent != _batchNode && static_cast(_parent)->_shouldBeHidden)) { - _quad.br.vertices.setZero(); - _quad.tl.vertices.setZero(); - _quad.tr.vertices.setZero(); - _quad.bl.vertices.setZero(); + _quad.br.position.setZero(); + _quad.tl.position.setZero(); + _quad.tr.position.setZero(); + _quad.bl.position.setZero(); _shouldBeHidden = true; } else @@ -1044,10 +1045,10 @@ void Sprite::updateTransform() float dx = x1 * cr - y2 * sr2 + x; float dy = x1 * sr + y2 * cr2 + y; - _quad.bl.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(ax), SPRITE_RENDER_IN_SUBPIXEL(ay), _positionZ); - _quad.br.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(bx), SPRITE_RENDER_IN_SUBPIXEL(by), _positionZ); - _quad.tl.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(dx), SPRITE_RENDER_IN_SUBPIXEL(dy), _positionZ); - _quad.tr.vertices.set(SPRITE_RENDER_IN_SUBPIXEL(cx), SPRITE_RENDER_IN_SUBPIXEL(cy), _positionZ); + _quad.bl.position.set(SPRITE_RENDER_IN_SUBPIXEL(ax), SPRITE_RENDER_IN_SUBPIXEL(ay), _positionZ); + _quad.br.position.set(SPRITE_RENDER_IN_SUBPIXEL(bx), SPRITE_RENDER_IN_SUBPIXEL(by), _positionZ); + _quad.tl.position.set(SPRITE_RENDER_IN_SUBPIXEL(dx), SPRITE_RENDER_IN_SUBPIXEL(dy), _positionZ); + _quad.tr.position.set(SPRITE_RENDER_IN_SUBPIXEL(cx), SPRITE_RENDER_IN_SUBPIXEL(cy), _positionZ); setTextureCoords(_rect); } @@ -1099,17 +1100,17 @@ void Sprite::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) for (unsigned int i = 0; i < count; i++) { // draw 3 lines - Vec3 from = verts[indices[i * 3]].vertices; - Vec3 to = verts[indices[i * 3 + 1]].vertices; - _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4B::WHITE); + Vec3 from = verts[indices[i * 3]].position; + Vec3 to = verts[indices[i * 3 + 1]].position; + _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color32::WHITE); - from = verts[indices[i * 3 + 1]].vertices; - to = verts[indices[i * 3 + 2]].vertices; - _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4B::WHITE); + from = verts[indices[i * 3 + 1]].position; + to = verts[indices[i * 3 + 2]].position; + _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color32::WHITE); - from = verts[indices[i * 3 + 2]].vertices; - to = verts[indices[i * 3]].vertices; - _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4B::WHITE); + from = verts[indices[i * 3 + 2]].position; + to = verts[indices[i * 3]].position; + _debugDrawNode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color32::WHITE); } #endif // AX_SPRITE_DEBUG_DRAW } @@ -1126,7 +1127,7 @@ void Sprite::addChild(Node* child, int zOrder, int tag) if (_renderMode == RenderMode::QUAD_BATCHNODE) { Sprite* childSprite = dynamic_cast(child); - AXASSERT(childSprite, "CCSprite only supports Sprites as children when using SpriteBatchNode"); + AXASSERT(childSprite, "Sprite only supports Sprites as children when using SpriteBatchNode"); AXASSERT(childSprite->getTexture() == _textureAtlas->getTexture(), "childSprite's texture name should be equal to _textureAtlas's texture name!"); // put it in descendants array of batch node @@ -1150,7 +1151,7 @@ void Sprite::addChild(Node* child, int zOrder, std::string_view name) if (_renderMode == RenderMode::QUAD_BATCHNODE) { Sprite* childSprite = dynamic_cast(child); - AXASSERT(childSprite, "CCSprite only supports Sprites as children when using SpriteBatchNode"); + AXASSERT(childSprite, "Sprite only supports Sprites as children when using SpriteBatchNode"); AXASSERT(childSprite->getTexture() == _textureAtlas->getTexture(), "childSprite's texture name should be equal to _textureAtlas's texture name."); // put it in descendants array of batch node @@ -1314,7 +1315,7 @@ void Sprite::setScaleX(float scaleX) void Sprite::setScaleY(float scaleY) { -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL if (_texture &&_texture->isRenderTarget()) scaleY = std::abs(scaleY); #endif @@ -1443,7 +1444,7 @@ bool Sprite::isFlippedX() const void Sprite::setFlippedY(bool flippedY) { -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL if (_texture && _texture->isRenderTarget()) flippedY = !flippedY; #endif @@ -1467,7 +1468,7 @@ void Sprite::flipX() { for (unsigned int i = 0; i < _polyInfo.triangles.vertCount; i++) { - auto& v = _polyInfo.triangles.verts[i].vertices; + auto& v = _polyInfo.triangles.verts[i].position; v.x = _contentSize.width - v.x; } } @@ -1484,7 +1485,7 @@ void Sprite::flipY() { for (unsigned int i = 0; i < _polyInfo.triangles.vertCount; i++) { - auto& v = _polyInfo.triangles.verts[i].vertices; + auto& v = _polyInfo.triangles.verts[i].position; v.y = _contentSize.height - v.y; } } @@ -1499,23 +1500,21 @@ void Sprite::flipY() void Sprite::updateColor() { - Color4B color4(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity); + Color color(_displayedColor); // special opacity for premultiplied textures if (_opacityModifyRGB) - { - color4.r *= _displayedOpacity / 255.0f; - color4.g *= _displayedOpacity / 255.0f; - color4.b *= _displayedOpacity / 255.0f; - } + color.premultiplyAlpha(); + + Color32 color32{color}; for (unsigned int i = 0; i < _polyInfo.triangles.vertCount; i++) - _polyInfo.triangles.verts[i].colors = color4; + _polyInfo.triangles.verts[i].color = color32; // related to issue #17116 // when switching from Quad to Slice9, the color will be obtained from _quad // so it is important to update _quad colors as well. - _quad.bl.colors = _quad.tl.colors = _quad.br.colors = _quad.tr.colors = color4; + _quad.bl.color = _quad.tl.color = _quad.br.color = _quad.tr.color = color32; // renders using batch node if (_renderMode == RenderMode::QUAD_BATCHNODE) @@ -1601,17 +1600,17 @@ void Sprite::setSpriteFrame(SpriteFrame* spriteFrame) void Sprite::setDisplayFrameWithAnimationName(std::string_view animationName, unsigned int frameIndex) { - AXASSERT(!animationName.empty(), "CCSprite#setDisplayFrameWithAnimationName. animationName must not be nullptr"); + AXASSERT(!animationName.empty(), "Sprite#setDisplayFrameWithAnimationName. animationName must not be nullptr"); if (animationName.empty()) return; Animation* a = AnimationCache::getInstance()->getAnimation(animationName); - AXASSERT(a, "CCSprite#setDisplayFrameWithAnimationName: Frame not found"); + AXASSERT(a, "Sprite#setDisplayFrameWithAnimationName: Frame not found"); AnimationFrame* frame = a->getFrames().at(frameIndex); - AXASSERT(frame, "CCSprite#setDisplayFrame. Invalid frame"); + AXASSERT(frame, "Sprite#setDisplayFrame. Invalid frame"); setSpriteFrame(frame->getSpriteFrame()); } @@ -1658,10 +1657,10 @@ void Sprite::setBatchNode(SpriteBatchNode* spriteBatchNode) float y1 = _offsetPosition.y; float x2 = x1 + _rect.size.width; float y2 = y1 + _rect.size.height; - _quad.bl.vertices.set(x1, y1, 0); - _quad.br.vertices.set(x2, y1, 0); - _quad.tl.vertices.set(x1, y2, 0); - _quad.tr.vertices.set(x2, y2, 0); + _quad.bl.position.set(x1, y1, 0); + _quad.br.position.set(x2, y1, 0); + _quad.tl.position.set(x1, y2, 0); + _quad.tr.position.set(x2, y2, 0); } else { @@ -1676,11 +1675,11 @@ void Sprite::setBatchNode(SpriteBatchNode* spriteBatchNode) void Sprite::updateBlendFunc() { AXASSERT(_renderMode != RenderMode::QUAD_BATCHNODE, - "CCSprite: updateBlendFunc doesn't work when the sprite is rendered using a SpriteBatchNode"); + "Sprite: updateBlendFunc doesn't work when the sprite is rendered using a SpriteBatchNode"); // it is possible to have an untextured sprite - backend::BlendDescriptor& blendDescriptor = _trianglesCommand.getPipelineDescriptor().blendDescriptor; - blendDescriptor.blendEnabled = true; + rhi::BlendDesc& blendDesc = _trianglesCommand.getPipelineDesc().blendDesc; + blendDesc.blendEnabled = true; if (!_texture || !_texture->hasPremultipliedAlpha()) { @@ -1722,7 +1721,7 @@ void Sprite::setPolygonInfo(const PolygonInfo& info) void Sprite::setMVPMatrixUniform() { const auto& projectionMat = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = _trianglesCommand.getPipelineDescriptor().programState; + auto programState = _trianglesCommand.getPipelineDesc().programState; if (programState && _mvpMatrixLocation) programState->setUniform(_mvpMatrixLocation, projectionMat.m, sizeof(projectionMat.m)); } diff --git a/core/2d/Sprite.h b/axmol/2d/Sprite.h similarity index 90% rename from core/2d/Sprite.h rename to axmol/2d/Sprite.h index 35e5d5610257..d432f10a2b65 100644 --- a/core/2d/Sprite.h +++ b/axmol/2d/Sprite.h @@ -29,13 +29,13 @@ THE SOFTWARE. #pragma once #include -#include "2d/Node.h" -#include "2d/DrawNode.h" -#include "base/Protocols.h" -#include "renderer/TextureAtlas.h" -#include "renderer/TrianglesCommand.h" -#include "renderer/CustomCommand.h" -#include "2d/AutoPolygon.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/DrawNode.h" +#include "axmol/base/Protocols.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/renderer/TrianglesCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/2d/AutoPolygon.h" namespace ax { @@ -214,7 +214,7 @@ class AX_DLL Sprite : public Node, public TextureProtocol /** * Updates the quad according the rotation, position, scale values. */ - virtual void updateTransform() override; + void updateTransform() override; /** * Returns the batch node object if this sprite is rendered by SpriteBatchNode. @@ -251,10 +251,10 @@ class AX_DLL Sprite : public Node, public TextureProtocol * * The Texture's rect is not changed. */ - virtual void setTexture(Texture2D* texture) override; + void setTexture(Texture2D* texture) override; /** Returns the Texture2D object used by the sprite. */ - virtual Texture2D* getTexture() const override; + Texture2D* getTexture() const override; /** * Updates the texture rect of the Sprite in points. @@ -358,48 +358,48 @@ class AX_DLL Sprite : public Node, public TextureProtocol /** */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /// @{ /// @name Functions inherited from Node. - virtual void setScaleX(float scaleX) override; - virtual void setScaleY(float scaleY) override; - virtual void setScale(float scaleX, float scaleY) override; + void setScaleX(float scaleX) override; + void setScaleY(float scaleY) override; + void setScale(float scaleX, float scaleY) override; /** * @lua NA */ - virtual void setPosition(const Vec2& pos) override; - virtual void setPosition(float x, float y) override; - virtual void setRotation(float rotation) override; - virtual void setRotationSkewX(float rotationX) override; - virtual void setRotationSkewY(float rotationY) override; - virtual void setSkewX(float sx) override; - virtual void setSkewY(float sy) override; - virtual void removeChild(Node* child, bool cleanup = true) override; - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - virtual void reorderChild(Node* child, int zOrder) override; + void setPosition(const Vec2& pos) override; + void setPosition(float x, float y) override; + void setRotation(float rotation) override; + void setRotationSkewX(float rotationX) override; + void setRotationSkewY(float rotationY) override; + void setSkewX(float sx) override; + void setSkewY(float sy) override; + void removeChild(Node* child, bool cleanup = true) override; + void removeAllChildrenWithCleanup(bool cleanup) override; + void reorderChild(Node* child, int zOrder) override; using Node::addChild; - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void sortAllChildren() override; - virtual void setScale(float scale) override; - virtual void setPositionZ(float positionZ) override; - virtual void setAnchorPoint(const Vec2& anchor) override; - virtual void setContentSize(const Vec2& size) override; - - virtual void setIgnoreAnchorPointForPosition(bool value) override; - - virtual void setVisible(bool bVisible) override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void setOpacityModifyRGB(bool modify) override; - virtual bool isOpacityModifyRGB() const override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; + void sortAllChildren() override; + void setScale(float scale) override; + void setPositionZ(float positionZ) override; + void setAnchorPoint(const Vec2& anchor) override; + void setContentSize(const Vec2& size) override; + + void setIgnoreAnchorPointForPosition(bool value) override; + + void setVisible(bool bVisible) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void setOpacityModifyRGB(bool modify) override; + bool isOpacityModifyRGB() const override; /// @} /** * Returns the quad (tex coords, vertex coords and color) information. * @lua NA */ - const V3F_C4B_T2F_Quad& getQuad() const { return _quad; } + const V3F_T2F_C4B_Quad& getQuad() const { return _quad; } /** * Returns whether or not the texture rectangle is rotated. @@ -431,7 +431,7 @@ class AX_DLL Sprite : public Node, public TextureProtocol /** * Set or Attach new ProgramState */ - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; /** * Sets the weak reference of the TextureAtlas when the sprite is rendered using via SpriteBatchNode. @@ -529,7 +529,7 @@ class AX_DLL Sprite : public Node, public TextureProtocol virtual ~Sprite(); /* Initializes an empty sprite with no parameters. */ - virtual bool init() override; + bool init() override; /** * Initializes a sprite with a texture. @@ -653,10 +653,10 @@ class AX_DLL Sprite : public Node, public TextureProtocol void setAutoSize(bool enabled) { _autoSizeEnabled = enabled; } protected: - virtual void updateColor() override; + void updateColor() override; virtual void setTextureCoords(const Rect& rect); - virtual void setTextureCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad); - virtual void setVertexCoords(const Rect& rect, V3F_C4B_T2F_Quad* outQuad); + virtual void setTextureCoords(const Rect& rect, V3F_T2F_C4B_Quad* outQuad); + virtual void setVertexCoords(const Rect& rect, V3F_T2F_C4B_Quad* outQuad); virtual void updateBlendFunc(); virtual void setReorderChildDirtyRecursively(); virtual void setDirtyRecursively(bool value); @@ -665,7 +665,7 @@ class AX_DLL Sprite : public Node, public TextureProtocol void updatePoly(); void updateStretchFactor(); - void populateTriangle(int quadIndex, const V3F_C4B_T2F_Quad& quad); + void populateTriangle(int quadIndex, const V3F_T2F_C4B_Quad& quad); void setMVPMatrixUniform(); // // Data used when the sprite is rendered using a SpriteSheet @@ -687,7 +687,7 @@ class AX_DLL Sprite : public Node, public TextureProtocol SpriteFrame* _spriteFrame = nullptr; TrianglesCommand _trianglesCommand; - backend::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _mvpMatrixLocation; #if AX_SPRITE_DEBUG_DRAW DrawNode* _debugDrawNode = nullptr; #endif // AX_SPRITE_DEBUG_DRAW @@ -710,8 +710,8 @@ class AX_DLL Sprite : public Node, public TextureProtocol Vec2 _unflippedOffsetPositionFromCenter; // vertex coords, texture coords and color info - V3F_C4B_T2F_Quad _quad; - V3F_C4B_T2F* _trianglesVertex = nullptr; + V3F_T2F_C4B_Quad _quad; + V3F_T2F_C4B* _trianglesVertex = nullptr; unsigned short* _trianglesIndex = nullptr; PolygonInfo _polyInfo; diff --git a/core/2d/SpriteBatchNode.cpp b/axmol/2d/SpriteBatchNode.cpp similarity index 95% rename from core/2d/SpriteBatchNode.cpp rename to axmol/2d/SpriteBatchNode.cpp index a05657e83466..e9443cc688a2 100644 --- a/core/2d/SpriteBatchNode.cpp +++ b/axmol/2d/SpriteBatchNode.cpp @@ -27,19 +27,19 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/SpriteBatchNode.h" +#include "axmol/2d/SpriteBatchNode.h" #include // offsetof -#include "base/Types.h" -#include "2d/Sprite.h" -#include "base/Director.h" -#include "base/Profiling.h" -#include "base/UTF8.h" -#include "renderer/TextureCache.h" -#include "renderer/Renderer.h" -#include "renderer/QuadCommand.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/base/Types.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/Director.h" +#include "axmol/base/Profiling.h" +#include "axmol/base/text_utils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/DriverBase.h" namespace ax { @@ -104,7 +104,7 @@ bool SpriteBatchNode::initWithTexture(Texture2D* tex, ssize_t capacity /* = DEFA _textureAtlas->initWithTexture(tex, capacity); - setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, tex); + setProgramStateWithRegistry(rhi::ProgramType::POSITION_TEXTURE_COLOR, tex); updateBlendFunc(); @@ -119,22 +119,21 @@ void SpriteBatchNode::setUniformLocation() { AXASSERT(_programState, "programState should not be nullptr"); _mvpMatrixLocaiton = _programState->getUniformLocation("u_MVPMatrix"); - _textureLocation = _programState->getUniformLocation("u_tex0"); } void SpriteBatchNode::setVertexLayout() { AXASSERT(_programState, "programState should not be nullptr"); - _programState->validateSharedVertexLayout(backend::VertexLayoutType::Sprite); + _programState->validateSharedVertexLayout(rhi::VertexLayoutType::Sprite); } -bool SpriteBatchNode::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) +bool SpriteBatchNode::setProgramState(rhi::ProgramState* programState, bool ownPS/* = false*/) { AXASSERT(programState, "programState should not be nullptr"); if (Node::setProgramState(programState, ownPS)) { - auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _quadCommand.getPipelineDesc(); + pipelineDesc.programState = _programState; setVertexLayout(); updateProgramStateTexture(_textureAtlas->getTexture()); @@ -397,7 +396,7 @@ void SpriteBatchNode::swap(ssize_t oldIndex, ssize_t newIndex) oldIndex >= 0 && oldIndex < (int)_descendants.size() && newIndex >= 0 && newIndex < (int)_descendants.size(), "Invalid index"); - V3F_C4B_T2F_Quad* quads = _textureAtlas->getQuads(); + auto quads = _textureAtlas->getQuads(); std::swap(quads[oldIndex], quads[newIndex]); // update the index of other swapped item @@ -430,7 +429,7 @@ void SpriteBatchNode::draw(Renderer* renderer, const Mat4& transform, uint32_t f } const auto& matrixProjection = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); - auto programState = _quadCommand.getPipelineDescriptor().programState; + auto programState = _quadCommand.getPipelineDesc().programState; programState->setUniform(_mvpMatrixLocaiton, matrixProjection.m, sizeof(matrixProjection.m)); _quadCommand.init(_globalZOrder, _textureAtlas->getTexture(), _blendFunc, _textureAtlas->getQuads(), _textureAtlas->getTotalQuads(), transform, flags); @@ -701,7 +700,7 @@ Texture2D* SpriteBatchNode::getTexture() const void SpriteBatchNode::setTexture(Texture2D* texture) { _textureAtlas->setTexture(texture); - setProgramStateWithRegistry(backend::ProgramType::POSITION_TEXTURE_COLOR, texture); + setProgramStateWithRegistry(rhi::ProgramType::POSITION_TEXTURE_COLOR, texture); updateBlendFunc(); } diff --git a/core/2d/SpriteBatchNode.h b/axmol/2d/SpriteBatchNode.h similarity index 88% rename from core/2d/SpriteBatchNode.h rename to axmol/2d/SpriteBatchNode.h index 64a0e95014b5..add860a9144f 100644 --- a/core/2d/SpriteBatchNode.h +++ b/axmol/2d/SpriteBatchNode.h @@ -31,10 +31,10 @@ THE SOFTWARE. #include -#include "2d/Node.h" -#include "base/Protocols.h" -#include "renderer/TextureAtlas.h" -#include "renderer/QuadCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Protocols.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/renderer/QuadCommand.h" namespace ax { @@ -175,8 +175,8 @@ class AX_DLL SpriteBatchNode : public Node, public TextureProtocol // Overrides // // TextureProtocol - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; /** *@code * When this function bound into js or lua,the parameter will be changed. @@ -184,34 +184,34 @@ class AX_DLL SpriteBatchNode : public Node, public TextureProtocol * @endcode * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; /** */ - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; using Node::addChild; - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void reorderChild(Node* child, int zOrder) override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; + void reorderChild(Node* child, int zOrder) override; - virtual void removeChild(Node* child, bool cleanup) override; + void removeChild(Node* child, bool cleanup) override; /** */ - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - virtual void sortAllChildren() override; + void removeAllChildrenWithCleanup(bool cleanup) override; + void sortAllChildren() override; /** */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** */ - virtual std::string getDescription() const override; + std::string getDescription() const override; - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; /** Inserts a quad at a certain index into the texture atlas. The Sprite won't be added into the children array. * This method should be called only when you are dealing with very big AtlasSprite and when most of the Sprite @@ -265,8 +265,7 @@ class AX_DLL SpriteBatchNode : public Node, public TextureProtocol BlendFunc _blendFunc; QuadCommand _quadCommand; - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _textureLocation; + rhi::UniformLocation _mvpMatrixLocaiton; // all descendants: children, grand children, etc... // There is not need to retain/release these objects, since they are already retained by _children diff --git a/core/2d/SpriteFrame.cpp b/axmol/2d/SpriteFrame.cpp similarity index 98% rename from core/2d/SpriteFrame.cpp rename to axmol/2d/SpriteFrame.cpp index 47a5ed0a10cc..87f2b3a52ba2 100644 --- a/core/2d/SpriteFrame.cpp +++ b/axmol/2d/SpriteFrame.cpp @@ -27,10 +27,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/TextureCache.h" -#include "2d/SpriteFrame.h" -#include "base/Director.h" -#include "platform/FileUtils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/core/2d/SpriteFrame.h b/axmol/2d/SpriteFrame.h similarity index 98% rename from core/2d/SpriteFrame.h rename to axmol/2d/SpriteFrame.h index 0f2016cc180a..1927bd50ec96 100644 --- a/core/2d/SpriteFrame.h +++ b/axmol/2d/SpriteFrame.h @@ -29,10 +29,10 @@ THE SOFTWARE. #pragma once -#include "2d/Node.h" -#include "2d/AutoPolygon.h" -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/AutoPolygon.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" namespace ax { @@ -243,7 +243,7 @@ class AX_DLL SpriteFrame : public Object, public Clonable bool hasAnchorPoint() const; // Overrides - virtual SpriteFrame* clone() const override; + SpriteFrame* clone() const override; /** Set the polygon info for polygon mesh sprites * diff --git a/core/2d/SpriteFrameCache.cpp b/axmol/2d/SpriteFrameCache.cpp similarity index 97% rename from core/2d/SpriteFrameCache.cpp rename to axmol/2d/SpriteFrameCache.cpp index 62e9778210ef..ce9958ddb6c4 100644 --- a/core/2d/SpriteFrameCache.cpp +++ b/axmol/2d/SpriteFrameCache.cpp @@ -29,18 +29,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/SpriteFrameCache.h" +#include "axmol/2d/SpriteFrameCache.h" #include -#include "2d/Sprite.h" -#include "2d/AutoPolygon.h" -#include "2d/PlistSpriteSheetLoader.h" -#include "platform/FileUtils.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "renderer/Texture2D.h" -#include "base/NinePatchImageParser.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/AutoPolygon.h" +#include "axmol/2d/PlistSpriteSheetLoader.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/NinePatchImageParser.h" #include "xxhash.h" using namespace std; diff --git a/core/2d/SpriteFrameCache.h b/axmol/2d/SpriteFrameCache.h similarity index 98% rename from core/2d/SpriteFrameCache.h rename to axmol/2d/SpriteFrameCache.h index 9e5091b97d46..0d3934ca5c45 100644 --- a/core/2d/SpriteFrameCache.h +++ b/axmol/2d/SpriteFrameCache.h @@ -34,12 +34,12 @@ THE SOFTWARE. #include #include #include -#include "2d/SpriteFrame.h" -#include "2d/SpriteSheetLoader.h" -#include "base/Object.h" -#include "base/Value.h" -#include "base/Map.h" -#include "base/Data.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteSheetLoader.h" +#include "axmol/base/Object.h" +#include "axmol/base/Value.h" +#include "axmol/base/Map.h" +#include "axmol/base/Data.h" namespace ax { diff --git a/core/2d/SpriteSheetLoader.cpp b/axmol/2d/SpriteSheetLoader.cpp similarity index 85% rename from core/2d/SpriteSheetLoader.cpp rename to axmol/2d/SpriteSheetLoader.cpp index a1bbba484333..1c9e011980d0 100644 --- a/core/2d/SpriteSheetLoader.cpp +++ b/axmol/2d/SpriteSheetLoader.cpp @@ -1,5 +1,5 @@ -#include "2d/SpriteSheetLoader.h" -#include "base/Director.h" +#include "axmol/2d/SpriteSheetLoader.h" +#include "axmol/base/Director.h" #include using namespace std; @@ -19,13 +19,13 @@ void SpriteSheetLoader::initializePolygonInfo(const Vec2& textureSize, const auto scaleFactor = AX_CONTENT_SCALE_FACTOR(); - auto* vertexData = new V3F_C4B_T2F[vertexCount]; + auto* vertexData = new V3F_T2F_C4B[vertexCount]; for (size_t i = 0; i < vertexCount / 2; i++) { - vertexData[i].colors = Color4B::WHITE; - vertexData[i].vertices = + vertexData[i].color = Color32::WHITE; + vertexData[i].position = Vec3(vertices[i * 2] / scaleFactor, (spriteSize.height - vertices[i * 2 + 1]) / scaleFactor, 0); - vertexData[i].texCoords = + vertexData[i].texCoord = Tex2F(verticesUV[i * 2] / textureSize.width, verticesUV[i * 2 + 1] / textureSize.height); } diff --git a/core/2d/SpriteSheetLoader.h b/axmol/2d/SpriteSheetLoader.h similarity index 96% rename from core/2d/SpriteSheetLoader.h rename to axmol/2d/SpriteSheetLoader.h index c4ae18ea02e2..a9fc7dcd54ae 100644 --- a/core/2d/SpriteSheetLoader.h +++ b/axmol/2d/SpriteSheetLoader.h @@ -33,11 +33,11 @@ THE SOFTWARE. #include #include #include -#include "2d/SpriteFrame.h" -#include "base/Object.h" -#include "base/Value.h" -#include "base/Map.h" -#include "base/Data.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/base/Object.h" +#include "axmol/base/Value.h" +#include "axmol/base/Map.h" +#include "axmol/base/Data.h" namespace ax { diff --git a/core/2d/TMXObjectGroup.cpp b/axmol/2d/TMXObjectGroup.cpp similarity index 97% rename from core/2d/TMXObjectGroup.cpp rename to axmol/2d/TMXObjectGroup.cpp index 0cb365f7f9ce..31ea08c5ee81 100644 --- a/core/2d/TMXObjectGroup.cpp +++ b/axmol/2d/TMXObjectGroup.cpp @@ -27,8 +27,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TMXObjectGroup.h" -#include "base/Macros.h" +#include "axmol/2d/TMXObjectGroup.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/2d/TMXObjectGroup.h b/axmol/2d/TMXObjectGroup.h similarity index 97% rename from core/2d/TMXObjectGroup.h rename to axmol/2d/TMXObjectGroup.h index 017b6c339fe1..a47f05fa2c29 100644 --- a/core/2d/TMXObjectGroup.h +++ b/axmol/2d/TMXObjectGroup.h @@ -29,9 +29,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "math/Math.h" -#include "base/Value.h" -#include "base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/base/Value.h" +#include "axmol/base/Object.h" namespace ax { diff --git a/core/2d/TMXXMLParser.cpp b/axmol/2d/TMXXMLParser.cpp similarity index 88% rename from core/2d/TMXXMLParser.cpp rename to axmol/2d/TMXXMLParser.cpp index 3d7d5c903245..3944f4500ab2 100644 --- a/core/2d/TMXXMLParser.cpp +++ b/axmol/2d/TMXXMLParser.cpp @@ -28,17 +28,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TMXXMLParser.h" +#include "axmol/2d/TMXXMLParser.h" #include #include #include -// #include "2d/TMXTiledMap.h" -#include "base/ZipUtils.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "platform/FileUtils.h" -// using namespace std; +#include "axmol/base/ZipUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include +#include namespace ax { @@ -452,10 +452,9 @@ void TMXMapInfo::startElement(void* /*ctx*/, const char* name, const char** atts TMXLayerInfo* layer = tmxMapInfo->getLayers().back(); Vec2 layerSize = layer->_layerSize; - auto tilesAmount = static_cast(layerSize.width * layerSize.height); + auto tilesAmount = static_cast(layerSize.width * layerSize.height); - layer->_tiles = - (uint32_t*)axstd::pod_vector(tilesAmount, 0U).release_pointer(); + layer->_tiles = (uint32_t*)axstd::pod_vector(tilesAmount, 0U).release_pointer(); } else if (encoding == "base64") { @@ -534,7 +533,7 @@ void TMXMapInfo::startElement(void* /*ctx*/, const char* name, const char** atts if (tmxMapInfo->getParentElement() == TMXPropertyNone) { AXLOGD("TMX tile map: Parent element is unsupported. Cannot add property named '{}' with value '{}'", - attributeDict["name"].asString(), attributeDict["value"].asString()); + attributeDict["name"].asString(), attributeDict["value"].asString()); tmxMapInfo->setStoringCharacters(false); } else if (tmxMapInfo->getParentElement() == TMXPropertyMap) @@ -596,36 +595,36 @@ void TMXMapInfo::startElement(void* /*ctx*/, const char* name, const char** atts ValueVector pointsArray; pointsArray.reserve(10); - // parse points string into a space-separated set of points - std::stringstream pointsStream(value); - std::string pointPair; - while (std::getline(pointsStream, pointPair, ' ')) + const auto offsetX = static_cast(objectGroup->getPositionOffset().x); + const auto offsetY = static_cast(objectGroup->getPositionOffset().y); + // std::views::split 2~3x faster than std::getline + for (auto pt : std::views::split(value, ' ')) { - // parse each point combo into a comma-separated x,y point - std::stringstream pointStream(pointPair); - std::string xStr, yStr; - + std::string_view citem{pt.data(), pt.size()}; + int idx = 0; ValueMap pointDict; - - // set x - if (std::getline(pointStream, xStr, ',')) - { - int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x; - pointDict["x"] = Value(x); - } - - // set y - if (std::getline(pointStream, yStr, ',')) + for (auto subrgn : std::views::split(pt, ',')) { - int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y; - pointDict["y"] = Value(y); + int axisVal = 0; + std::string_view word(subrgn.data()); + std::from_chars(word.data(), word.data() + word.length(), axisVal, 10); + switch (idx++) + { + case 0: + pointDict["x"] = Value(axisVal + offsetX); + break; + case 1: + pointDict["y"] = Value(axisVal + offsetY); + break; + } + if (idx == 2) + break; } - // add to points array - pointsArray.emplace_back(Value(pointDict)); + pointsArray.emplace_back(Value(std::move(pointDict))); } - dict["points"] = Value(pointsArray); + dict["points"] = Value(std::move(pointsArray)); } } else if (elementName == "polyline") @@ -641,36 +640,32 @@ void TMXMapInfo::startElement(void* /*ctx*/, const char* name, const char** atts ValueVector pointsArray; pointsArray.reserve(10); - // parse points string into a space-separated set of points - std::stringstream pointsStream(value); - std::string pointPair; - while (std::getline(pointsStream, pointPair, ' ')) + const auto offsetX = static_cast(objectGroup->getPositionOffset().x); + const auto offsetY = static_cast(objectGroup->getPositionOffset().y); + for (auto pt : std::views::split(value, ' ')) { - // parse each point combo into a comma-separated x,y point - std::stringstream pointStream(pointPair); - std::string xStr, yStr; - + int idx = 0; ValueMap pointDict; - - // set x - if (std::getline(pointStream, xStr, ',')) - { - int x = atoi(xStr.c_str()) + (int)objectGroup->getPositionOffset().x; - pointDict["x"] = Value(x); - } - - // set y - if (std::getline(pointStream, yStr, ',')) + for (auto pt_axis : std::views::split(pt, ',')) { - int y = atoi(yStr.c_str()) + (int)objectGroup->getPositionOffset().y; - pointDict["y"] = Value(y); + int axisVal = 0; + std::from_chars(pt_axis.data(), pt_axis.data() + pt_axis.size(), axisVal, 10); + switch (idx++) + { + case 0: + pointDict["x"] = Value(axisVal + offsetX); + break; + case 1: + pointDict["y"] = Value(axisVal + offsetY); + break; + } + if (idx == 2) + break; } - // add to points array - pointsArray.emplace_back(Value(pointDict)); + pointsArray.emplace_back(Value(std::move(pointDict))); } - - dict["polylinePoints"] = Value(pointsArray); + dict["polylinePoints"] = Value(std::move(pointsArray)); } } else if (elementName == "animation") @@ -701,7 +696,7 @@ void TMXMapInfo::endElement(void* /*ctx*/, const char* name) tmxMapInfo->setStoringCharacters(false); TMXLayerInfo* layer = tmxMapInfo->getLayers().back(); - auto currentString = tmxMapInfo->getCurrentString(); + auto currentString = tmxMapInfo->getCurrentString(); auto buffer = utils::base64Decode(currentString); if (buffer.empty()) @@ -712,7 +707,7 @@ void TMXMapInfo::endElement(void* /*ctx*/, const char* name) if (tmxMapInfo->getLayerAttribs() & (TMXLayerAttribGzip | TMXLayerAttribZlib)) { - Vec2 s = layer->_layerSize; + Vec2 s = layer->_layerSize; // int sizeHint = s.width * s.height * sizeof(uint32_t); ssize_t sizeHint = s.width * s.height * sizeof(unsigned int); @@ -741,31 +736,17 @@ void TMXMapInfo::endElement(void* /*ctx*/, const char* name) tmxMapInfo->setStoringCharacters(false); auto currentString = tmxMapInfo->getCurrentString(); - std::vector gidTokens; - std::stringstream filestr; - filestr << currentString; - std::string sRow; - while (std::getline(filestr, sRow, '\n')) - { - std::string sGID; - std::istringstream rowstr(sRow); - while (std::getline(rowstr, sGID, ',')) - { - gidTokens.emplace_back(sGID); - } - } + axstd::pod_vector tileGids; + axstd::split_cb(currentString, '\n', [&tileGids](const char* first, const char* last) { + axstd::split_cb(std::string_view{first, static_cast(last - first)}, ',', + [&tileGids](const char* _first, const char* _last) { + unsigned int gid{0}; + std::from_chars(_first, _last, gid); + tileGids.push_back(gid); + }); + }); - // 32-bits per gid - axstd::pod_vector buffer(gidTokens.size()); - uint32_t* bufferPtr = buffer.data(); - for (const auto& gidToken : gidTokens) - { - auto tileGid = (uint32_t)strtoul(gidToken.c_str(), nullptr, 10); - *bufferPtr = tileGid; - bufferPtr++; - } - - layer->_tiles = buffer.release_pointer(); + layer->_tiles = tileGids.release_pointer(); tmxMapInfo->setCurrentString(""); } @@ -884,4 +865,4 @@ TMXTileAnimInfo* TMXTileAnimInfo::create(uint32_t tileID) return ret; } -} +} // namespace ax diff --git a/core/2d/TMXXMLParser.h b/axmol/2d/TMXXMLParser.h similarity index 98% rename from core/2d/TMXXMLParser.h rename to axmol/2d/TMXXMLParser.h index a14c94d5d033..012a3d7004d0 100644 --- a/core/2d/TMXXMLParser.h +++ b/axmol/2d/TMXXMLParser.h @@ -31,12 +31,12 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "math/Math.h" -#include "platform/SAXParser.h" -#include "base/Vector.h" -#include "base/Map.h" -#include "base/Value.h" -#include "2d/TMXObjectGroup.h" // needed for Vector for binding +#include "axmol/math/Math.h" +#include "axmol/platform/SAXParser.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Map.h" +#include "axmol/base/Value.h" +#include "axmol/2d/TMXObjectGroup.h" // needed for Vector for binding #include diff --git a/core/2d/TextFieldTTF.cpp b/axmol/2d/TextFieldTTF.cpp similarity index 94% rename from core/2d/TextFieldTTF.cpp rename to axmol/2d/TextFieldTTF.cpp index b142d569c9fa..35abec1d2126 100644 --- a/core/2d/TextFieldTTF.cpp +++ b/axmol/2d/TextFieldTTF.cpp @@ -2,6 +2,7 @@ Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -26,12 +27,12 @@ THE SOFTWARE. #include -#include "2d/TextFieldTTF.h" +#include "axmol/2d/TextFieldTTF.h" -#include "base/Director.h" -#include "platform/FileUtils.h" -#include "base/UTF8.h" -#include "2d/Sprite.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/text_utils.h" +#include "axmol/2d/Sprite.h" namespace ax { @@ -93,7 +94,7 @@ TextFieldTTF::TextFieldTTF() , _charCount(0) , _inputText("") , _placeHolder("") // prevent Label initWithString assertion - , _colorText(Color4B::WHITE) + , _colorText(Color32::WHITE) , _secureTextEntry(false) , _passwordStyleText(PASSWORD_STYLE_TEXT_DEFAULT) , _cursorEnabled(false) @@ -256,7 +257,7 @@ void TextFieldTTF::insertText(const char* text, size_t len) std::string insert(text, len); // insert \n means input end - int pos = static_cast(insert.find(StringUtils::AsciiCharacters::NewLine)); + int pos = static_cast(insert.find(text_utils::AsciiCharacters::NewLine)); if ((int)insert.npos != pos) { len = pos; @@ -271,7 +272,7 @@ void TextFieldTTF::insertText(const char* text, size_t len) return; } - std::size_t countInsertChar = StringUtils::countUTF8Chars(insert); + std::size_t countInsertChar = text_utils::countUTF8Chars(insert); _charCount += countInsertChar; if (_cursorEnabled) @@ -279,7 +280,7 @@ void TextFieldTTF::insertText(const char* text, size_t len) std::string sText; sText.reserve(_inputText.length() + insert.length()); sText += _inputText; - auto pos = StringUtils::getUTF8ByteOffset(sText, _cursorPosition); + auto pos = text_utils::getUTF8ByteOffset(sText, _cursorPosition); if (pos != std::string::npos) sText.insert(pos, insert); else @@ -364,7 +365,7 @@ void TextFieldTTF::deleteBackward(size_t numChars) setCursorPosition(_cursorPosition - 1); std::string sText(_inputText); - auto nb = StringUtils::eraseUTF8CharAt(sText, _cursorPosition); + auto nb = text_utils::eraseUTF8CharAt(sText, _cursorPosition); if (nb) --_charCount; @@ -448,18 +449,18 @@ void TextFieldTTF::setAttachWithIME(bool isAttachWithIME) } } -void TextFieldTTF::setTextColorInternally(const Color4B& color) +void TextFieldTTF::setTextColorInternally(const Color32& color) { if (_currentLabelType == LabelType::BMFONT) { - Label::setColor(Color3B(color)); + Label::setColor(color); return; } Label::setTextColor(color); } -void TextFieldTTF::setTextColor(const Color4B& color) +void TextFieldTTF::setTextColor(const Color32& color) { _colorText = color; if (!_inputText.empty()) @@ -508,17 +509,12 @@ void TextFieldTTF::update(float delta) } } -const Color4B& TextFieldTTF::getColorSpaceHolder() +const Color32& TextFieldTTF::getColorSpaceHolder() { return _colorSpaceHolder; } -void TextFieldTTF::setColorSpaceHolder(const Color3B& color) -{ - setColorSpaceHolder(Color4B(color)); -} - -void TextFieldTTF::setColorSpaceHolder(const Color4B& color) +void TextFieldTTF::setColorSpaceHolder(const Color32& color) { _colorSpaceHolder = color; if (_inputText.empty()) @@ -598,22 +594,22 @@ void TextFieldTTF::makeStringSupportCursor(std::string& displayText) { // \b - Next char not change x position if (_currentLabelType == LabelType::TTF || _currentLabelType == LabelType::BMFONT) - displayText.push_back(StringUtils::AsciiCharacters::NextCharNoChangeX); + displayText.push_back(text_utils::AsciiCharacters::NextCharNoChangeX); displayText.push_back(_cursorChar); } else { - auto numChars = StringUtils::countUTF8Chars(displayText); + auto numChars = text_utils::countUTF8Chars(displayText); if (_cursorPosition > numChars) _cursorPosition = numChars; std::string cursorChar; // \b - Next char not change x position if (_currentLabelType == LabelType::TTF || _currentLabelType == LabelType::BMFONT) - cursorChar.push_back(StringUtils::AsciiCharacters::NextCharNoChangeX); + cursorChar.push_back(text_utils::AsciiCharacters::NextCharNoChangeX); cursorChar.push_back(_cursorChar); - auto offset = StringUtils::getUTF8ByteOffset(displayText, _cursorPosition); + auto offset = text_utils::getUTF8ByteOffset(displayText, _cursorPosition); if (offset != std::string::npos) displayText.insert(offset, cursorChar); else @@ -657,7 +653,7 @@ void TextFieldTTF::controlKey(EventKeyboard::KeyCode keyCode) if (_cursorPosition < (std::size_t)_charCount) { std::string sText(_inputText); - auto nb = StringUtils::eraseUTF8CharAt(sText, _cursorPosition); + auto nb = text_utils::eraseUTF8CharAt(sText, _cursorPosition); if (nb) --_charCount; setCursorPosition(_cursorPosition); diff --git a/core/2d/TextFieldTTF.h b/axmol/2d/TextFieldTTF.h similarity index 85% rename from core/2d/TextFieldTTF.h rename to axmol/2d/TextFieldTTF.h index e39448d70d50..9b45847be76a 100644 --- a/core/2d/TextFieldTTF.h +++ b/axmol/2d/TextFieldTTF.h @@ -2,6 +2,7 @@ Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -26,8 +27,8 @@ THE SOFTWARE. #pragma once -#include "2d/Label.h" -#include "base/IMEDelegate.h" +#include "axmol/2d/Label.h" +#include "axmol/base/IMEDelegate.h" /** * @addtogroup ui @@ -124,12 +125,12 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate /** *@brief Open keyboard and receive input text. */ - virtual bool attachWithIME() override; + bool attachWithIME() override; /** *@brief End text input and close keyboard. */ - virtual bool detachWithIME() override; + bool detachWithIME() override; ////////////////////////////////////////////////////////////////////////// // properties @@ -153,31 +154,25 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate * Query the color of place holder. *@return The place holder color. */ - virtual const Color4B& getColorSpaceHolder(); - - /** - *@brief Change input placeholder color. - *@param color A color value in `Color3B`. - */ - virtual void setColorSpaceHolder(const Color3B& color); + virtual const Color32& getColorSpaceHolder(); /** * Change the placeholder color. - *@param color The placeholder color in Color4B. + *@param color The placeholder color in Color32. */ - virtual void setColorSpaceHolder(const Color4B& color); + virtual void setColorSpaceHolder(const Color32& color); /** * Change the color of input text. - *@param textColor The text color in Color4B. + *@param textColor The text color in Color32. */ - virtual void setTextColor(const Color4B& textColor) override; + void setTextColor(const Color32& textColor) override; /** * Change input text of TextField. *@param text The input text of TextField. */ - virtual void setString(std::string_view text) override; + void setString(std::string_view text) override; /** * Append to input text of TextField. @@ -189,7 +184,7 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate * Query the input text of TextField. *@return Get the input text of TextField. */ - virtual std::string_view getString() const override; + std::string_view getString() const override; /** * Change placeholder text. @@ -219,9 +214,9 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate */ virtual bool isSecureTextEntry() const; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void update(float delta) override; + void update(float delta) override; /** * Set enable cursor use. @@ -248,14 +243,14 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate // IMEDelegate interface ////////////////////////////////////////////////////////////////////////// - virtual bool canAttachWithIME() override; - virtual bool canDetachWithIME() override; - virtual void didAttachWithIME() override; - virtual void didDetachWithIME() override; - virtual void insertText(const char* text, size_t len) override; - virtual void deleteBackward(size_t numChars) override; - virtual std::string_view getContentText() override; - virtual void controlKey(EventKeyboard::KeyCode keyCode) override; + bool canAttachWithIME() override; + bool canDetachWithIME() override; + void didAttachWithIME() override; + void didDetachWithIME() override; + void insertText(const char* text, size_t len) override; + void deleteBackward(size_t numChars) override; + std::string_view getContentText() override; + void controlKey(EventKeyboard::KeyCode keyCode) override; TextFieldDelegate* _delegate; std::size_t _charCount; @@ -263,8 +258,8 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate std::string _inputText; std::string _placeHolder; - Color4B _colorSpaceHolder; - Color4B _colorText; + Color32 _colorSpaceHolder; + Color32 _colorText; bool _secureTextEntry; std::string _passwordStyleText; @@ -283,7 +278,7 @@ class AX_DLL TextFieldTTF : public Label, public IMEDelegate void makeStringSupportCursor(std::string& displayText); void updateCursorDisplayText(); void setAttachWithIME(bool isAttachWithIME); - void setTextColorInternally(const Color4B& color); + void setTextColorInternally(const Color32& color); private: class LengthStack; diff --git a/core/2d/TileMapAtlas.cpp b/axmol/2d/TileMapAtlas.cpp similarity index 68% rename from core/2d/TileMapAtlas.cpp rename to axmol/2d/TileMapAtlas.cpp index d4b9ce6abbaf..715f845234be 100644 --- a/core/2d/TileMapAtlas.cpp +++ b/axmol/2d/TileMapAtlas.cpp @@ -26,12 +26,12 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TileMapAtlas.h" -#include "platform/FileUtils.h" -#include "renderer/TextureAtlas.h" -#include "base/TGAlib.h" -#include "base/Director.h" -#include "base/UTF8.h" +#include "axmol/2d/TileMapAtlas.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/base/TGAlib.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" namespace ax { @@ -92,12 +92,9 @@ void TileMapAtlas::calculateItemsToRender() { for (int y = 0; y < _TGAInfo->height; y++) { - Color3B* ptr = (Color3B*)_TGAInfo->imageData; - Color3B value = ptr[x + y * _TGAInfo->width]; - if (value.r) - { + uint8_t* color24 = (uint8_t*)_TGAInfo->imageData + (x + y * _TGAInfo->width) * 3; + if (color24[0]) ++_itemsToRender; - } } } } @@ -121,54 +118,52 @@ void TileMapAtlas::loadTGAfile(std::string_view file) } // TileMapAtlas - Atlas generation / updates -void TileMapAtlas::setTile(const Color3B& tile, const Vec2& position) +void TileMapAtlas::setTile(const Color32& tile, const Vec2& position) { AXASSERT(_TGAInfo != nullptr, "tgaInfo must not be nil"); AXASSERT(position.x < _TGAInfo->width, "Invalid position.x"); AXASSERT(position.y < _TGAInfo->height, "Invalid position.x"); AXASSERT(tile.r != 0, "R component must be non 0"); - Color3B* ptr = (Color3B*)_TGAInfo->imageData; - Color3B value = ptr[(unsigned int)(position.x + position.y * _TGAInfo->width)]; - if (value.r == 0) - { - AXLOGD("Value.r must be non 0."); - } - else + auto color24 = (uint8_t*)_TGAInfo->imageData + static_cast(position.x + position.y * _TGAInfo->width) * 3; + if (color24[0]) { - ptr[(unsigned int)(position.x + position.y * _TGAInfo->width)] = tile; + color24[0] = tile.r; + color24[1] = tile.g; + color24[2] = tile.b; - // FIXME:: this method consumes a lot of memory // FIXME:: a tree of something like that shall be implemented - std::string key = StringUtils::toString(position.x) + "," + StringUtils::toString(position.y); + std::string key = fmt::format("{},{}", position.x, position.y); int num = _posToAtlasIndex[key].asInt(); - this->updateAtlasValueAt(position, tile, num); + this->updateAtlasValueAt(position, &tile.r, num); } + else + AXLOGD("Value.r must be non 0."); } -Color3B TileMapAtlas::getTileAt(const Vec2& position) const +Color32 TileMapAtlas::getTileAt(const Vec2& position) const { AXASSERT(_TGAInfo != nullptr, "tgaInfo must not be nil"); AXASSERT(position.x < _TGAInfo->width, "Invalid position.x"); AXASSERT(position.y < _TGAInfo->height, "Invalid position.y"); - Color3B* ptr = (Color3B*)_TGAInfo->imageData; - Color3B value = ptr[(unsigned int)(position.x + position.y * _TGAInfo->width)]; - - return value; + auto color24 = (uint8_t*)_TGAInfo->imageData + static_cast(position.x + position.y * _TGAInfo->width) * 3; + return Color32{color24[0], color24[1], color24[2]}; } -void TileMapAtlas::updateAtlasValueAt(const Vec2& pos, const Color3B& value, int index) +void TileMapAtlas::updateAtlasValueAt(const Vec2& pos, const uint8_t* color24, int index) { AXASSERT(index >= 0 && index < _textureAtlas->getCapacity(), "updateAtlasValueAt: Invalid index"); - V3F_C4B_T2F_Quad* quad = &((_textureAtlas->getQuads())[index]); + auto quad = &((_textureAtlas->getQuads())[index]); int x = pos.x; int y = pos.y; - float row = (float)(value.r % _itemsPerRow); - float col = (float)(value.r / _itemsPerRow); + + const auto red = color24[0]; + float row = (float)(red % _itemsPerRow); + float col = (float)(red / _itemsPerRow); float textureWide = (float)(_textureAtlas->getTexture()->getPixelsWide()); float textureHigh = (float)(_textureAtlas->getTexture()->getPixelsHigh()); @@ -188,33 +183,33 @@ void TileMapAtlas::updateAtlasValueAt(const Vec2& pos, const Color3B& value, int float bottom = top + itemHeightInPixels / textureHigh; #endif - quad->tl.texCoords.u = left; - quad->tl.texCoords.v = top; - quad->tr.texCoords.u = right; - quad->tr.texCoords.v = top; - quad->bl.texCoords.u = left; - quad->bl.texCoords.v = bottom; - quad->br.texCoords.u = right; - quad->br.texCoords.v = bottom; - - quad->bl.vertices.x = (float)(x * _itemWidth); - quad->bl.vertices.y = (float)(y * _itemHeight); - quad->bl.vertices.z = 0.0f; - quad->br.vertices.x = (float)(x * _itemWidth + _itemWidth); - quad->br.vertices.y = (float)(y * _itemHeight); - quad->br.vertices.z = 0.0f; - quad->tl.vertices.x = (float)(x * _itemWidth); - quad->tl.vertices.y = (float)(y * _itemHeight + _itemHeight); - quad->tl.vertices.z = 0.0f; - quad->tr.vertices.x = (float)(x * _itemWidth + _itemWidth); - quad->tr.vertices.y = (float)(y * _itemHeight + _itemHeight); - quad->tr.vertices.z = 0.0f; - - Color4B color(_displayedColor.r, _displayedColor.g, _displayedColor.b, _displayedOpacity); - quad->tr.colors = color; - quad->tl.colors = color; - quad->br.colors = color; - quad->bl.colors = color; + quad->tl.texCoord.u = left; + quad->tl.texCoord.v = top; + quad->tr.texCoord.u = right; + quad->tr.texCoord.v = top; + quad->bl.texCoord.u = left; + quad->bl.texCoord.v = bottom; + quad->br.texCoord.u = right; + quad->br.texCoord.v = bottom; + + quad->bl.position.x = (float)(x * _itemWidth); + quad->bl.position.y = (float)(y * _itemHeight); + quad->bl.position.z = 0.0f; + quad->br.position.x = (float)(x * _itemWidth + _itemWidth); + quad->br.position.y = (float)(y * _itemHeight); + quad->br.position.z = 0.0f; + quad->tl.position.x = (float)(x * _itemWidth); + quad->tl.position.y = (float)(y * _itemHeight + _itemHeight); + quad->tl.position.z = 0.0f; + quad->tr.position.x = (float)(x * _itemWidth + _itemWidth); + quad->tr.position.y = (float)(y * _itemHeight + _itemHeight); + quad->tr.position.z = 0.0f; + + const Color32& color = _displayedColor; + quad->tr.color = color; + quad->tl.color = color; + quad->br.color = color; + quad->bl.color = color; _textureAtlas->setDirty(true); ssize_t totalQuads = _textureAtlas->getTotalQuads(); @@ -236,14 +231,12 @@ void TileMapAtlas::updateAtlasValues() { if (total < _itemsToRender) { - Color3B* ptr = (Color3B*)_TGAInfo->imageData; - Color3B value = ptr[x + y * _TGAInfo->width]; - - if (value.r != 0) + auto color24 = (uint8_t*)_TGAInfo->imageData + (x + y * _TGAInfo->width) * 3; + if (color24[0]) { - this->updateAtlasValueAt(Vec2(x, y), value, total); + this->updateAtlasValueAt(Vec2(x, y), color24, total); - std::string key = StringUtils::toString(x) + "," + StringUtils::toString(y); + std::string key = fmt::format("{},{}", x, y); _posToAtlasIndex[key] = total; total++; diff --git a/core/2d/TileMapAtlas.h b/axmol/2d/TileMapAtlas.h similarity index 93% rename from core/2d/TileMapAtlas.h rename to axmol/2d/TileMapAtlas.h index 5010dc896831..552d05d48b28 100644 --- a/core/2d/TileMapAtlas.h +++ b/axmol/2d/TileMapAtlas.h @@ -28,8 +28,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/AtlasNode.h" -#include "base/Value.h" +#include "axmol/2d/AtlasNode.h" +#include "axmol/base/Value.h" namespace ax { @@ -76,12 +76,12 @@ class AX_DLL TileMapAtlas : public AtlasNode * Returns a tile from position x,y. *For the moment only channel R is used */ - Color3B getTileAt(const Vec2& position) const; + Color32 getTileAt(const Vec2& position) const; /** sets a tile at position x,y. For the moment only channel R is used */ - void setTile(const Color3B& tile, const Vec2& position); + void setTile(const Color32& tile, const Vec2& position); /** dealloc the map from memory */ void releaseMap(); @@ -100,7 +100,7 @@ class AX_DLL TileMapAtlas : public AtlasNode protected: void loadTGAfile(std::string_view file); void calculateItemsToRender(); - void updateAtlasValueAt(const Vec2& pos, const Color3B& value, int index); + void updateAtlasValueAt(const Vec2& pos, const uint8_t* color24, int index); void updateAtlasValues(); //! x,y to atlas dictionary diff --git a/core/2d/Transition.cpp b/axmol/2d/Transition.cpp similarity index 98% rename from core/2d/Transition.cpp rename to axmol/2d/Transition.cpp index 6df70fbd40e2..71aea2776a4d 100644 --- a/core/2d/Transition.cpp +++ b/axmol/2d/Transition.cpp @@ -27,18 +27,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/Transition.h" -#include "2d/ActionInterval.h" -#include "2d/ActionInstant.h" -#include "2d/ActionEase.h" -#include "2d/ActionCamera.h" -#include "2d/ActionTiledGrid.h" -#include "2d/ActionGrid.h" -#include "2d/Layer.h" -#include "2d/RenderTexture.h" -#include "2d/NodeGrid.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" +#include "axmol/2d/Transition.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/2d/ActionEase.h" +#include "axmol/2d/ActionCamera.h" +#include "axmol/2d/ActionTiledGrid.h" +#include "axmol/2d/ActionGrid.h" +#include "axmol/2d/Layer.h" +#include "axmol/2d/RenderTexture.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" namespace ax { @@ -1032,7 +1032,7 @@ TransitionZoomFlipAngular* TransitionZoomFlipAngular::create(float t, Scene* s) TransitionFade::TransitionFade() {} TransitionFade::~TransitionFade() {} -TransitionFade* TransitionFade::create(float duration, Scene* scene, const Color3B& color) +TransitionFade* TransitionFade::create(float duration, Scene* scene, const Color32& color) { TransitionFade* transition = new TransitionFade(); transition->initWithDuration(duration, scene, color); @@ -1042,10 +1042,10 @@ TransitionFade* TransitionFade::create(float duration, Scene* scene, const Color TransitionFade* TransitionFade::create(float duration, Scene* scene) { - return TransitionFade::create(duration, scene, Color3B::BLACK); + return TransitionFade::create(duration, scene, Color32::BLACK); } -bool TransitionFade::initWithDuration(float duration, Scene* scene, const Color3B& color) +bool TransitionFade::initWithDuration(float duration, Scene* scene, const Color32& color) { if (TransitionScene::initWithDuration(duration, scene)) { @@ -1059,7 +1059,7 @@ bool TransitionFade::initWithDuration(float duration, Scene* scene, const Color3 bool TransitionFade::initWithDuration(float t, Scene* scene) { - this->initWithDuration(t, scene, Color3B::BLACK); + this->initWithDuration(t, scene, Color32::BLACK); return true; } @@ -1116,13 +1116,13 @@ void TransitionCrossFade::onEnter() // create a transparent color layer // in which we are going to add our rendertextures - Color4B color(0, 0, 0, 0); + Color32 color(0, 0, 0, 0); Vec2 size = _director->getWinSize(); LayerColor* layer = LayerColor::create(color); // create the first render texture for inScene RenderTexture* inTexture = - RenderTexture::create((int)size.width, (int)size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8, false); + RenderTexture::create((int)size.width, (int)size.height, rhi::PixelFormat::RGBA8, PixelFormat::D24S8, false); if (nullptr == inTexture) { @@ -1139,7 +1139,7 @@ void TransitionCrossFade::onEnter() // create the second render texture for outScene RenderTexture* outTexture = - RenderTexture::create((int)size.width, (int)size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8, false); + RenderTexture::create((int)size.width, (int)size.height, rhi::PixelFormat::RGBA8, PixelFormat::D24S8, false); outTexture->setPosition(size.width / 2, size.height / 2); outTexture->setAnchorPoint(Vec2(0.5f, 0.5f)); diff --git a/core/2d/Transition.h b/axmol/2d/Transition.h similarity index 90% rename from core/2d/Transition.h rename to axmol/2d/Transition.h index 391cd9ac2367..c970758e349c 100644 --- a/core/2d/Transition.h +++ b/axmol/2d/Transition.h @@ -4,6 +4,7 @@ Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2011 Zynga Inc. Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -28,7 +29,7 @@ THE SOFTWARE. #pragma once -#include "2d/Scene.h" +#include "axmol/2d/Scene.h" namespace ax { @@ -107,10 +108,10 @@ class AX_DLL TransitionScene : public Scene // // Overrides // - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void onEnter() override; - virtual void onExit() override; - virtual void cleanup() override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void onEnter() override; + void onExit() override; + void cleanup() override; TransitionScene(); virtual ~TransitionScene(); @@ -186,7 +187,7 @@ class AX_DLL TransitionRotoZoom : public TransitionScene // // Overrides // - virtual void onEnter() override; + void onEnter() override; TransitionRotoZoom(); virtual ~TransitionRotoZoom(); @@ -213,7 +214,7 @@ class AX_DLL TransitionJumpZoom : public TransitionScene // // Overrides // - virtual void onEnter() override; + void onEnter() override; TransitionJumpZoom(); virtual ~TransitionJumpZoom(); @@ -243,12 +244,12 @@ class AX_DLL TransitionMoveInL : public TransitionScene, public TransitionEaseSc */ virtual ActionInterval* action(); - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; // // Overrides // - virtual void onEnter() override; + void onEnter() override; TransitionMoveInL(); virtual ~TransitionMoveInL(); @@ -351,7 +352,7 @@ class AX_DLL TransitionSlideInL : public TransitionScene, public TransitionEaseS */ static TransitionSlideInL* create(float t, Scene* scene); - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; /** Returns the action that will be performed by the incoming and outgoing scene. * @@ -362,7 +363,7 @@ class AX_DLL TransitionSlideInL : public TransitionScene, public TransitionEaseS // // Overrides // - virtual void onEnter() override; + void onEnter() override; TransitionSlideInL(); virtual ~TransitionSlideInL(); @@ -371,7 +372,7 @@ class AX_DLL TransitionSlideInL : public TransitionScene, public TransitionEaseS /** initializes the scenes */ virtual void initScenes(); - virtual void sceneOrder() override; + void sceneOrder() override; private: AX_DISALLOW_COPY_AND_ASSIGN(TransitionSlideInL); @@ -393,16 +394,16 @@ class AX_DLL TransitionSlideInR : public TransitionSlideInL static TransitionSlideInR* create(float t, Scene* scene); /** Returns the action that will be performed by the incoming and outgoing scene. */ - virtual ActionInterval* action() override; + ActionInterval* action() override; TransitionSlideInR(); virtual ~TransitionSlideInR(); protected: /** initializes the scenes */ - virtual void initScenes() override; + void initScenes() override; - virtual void sceneOrder() override; + void sceneOrder() override; private: AX_DISALLOW_COPY_AND_ASSIGN(TransitionSlideInR); @@ -424,16 +425,16 @@ class AX_DLL TransitionSlideInB : public TransitionSlideInL static TransitionSlideInB* create(float t, Scene* scene); /** returns the action that will be performed by the incoming and outgoing scene */ - virtual ActionInterval* action() override; + ActionInterval* action() override; TransitionSlideInB(); virtual ~TransitionSlideInB(); protected: /** initializes the scenes */ - virtual void initScenes() override; + void initScenes() override; - virtual void sceneOrder() override; + void sceneOrder() override; private: AX_DISALLOW_COPY_AND_ASSIGN(TransitionSlideInB); @@ -455,16 +456,16 @@ class AX_DLL TransitionSlideInT : public TransitionSlideInL static TransitionSlideInT* create(float t, Scene* scene); /** returns the action that will be performed by the incoming and outgoing scene */ - virtual ActionInterval* action() override; + ActionInterval* action() override; TransitionSlideInT(); virtual ~TransitionSlideInT(); protected: /** initializes the scenes */ - virtual void initScenes() override; + void initScenes() override; - virtual void sceneOrder() override; + void sceneOrder() override; private: AX_DISALLOW_COPY_AND_ASSIGN(TransitionSlideInT); @@ -490,8 +491,8 @@ class AX_DLL TransitionShrinkGrow : public TransitionScene, public TransitionEas /** * @lua NA */ - virtual void onEnter() override; - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; + void onEnter() override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; TransitionShrinkGrow(); virtual ~TransitionShrinkGrow(); @@ -530,7 +531,7 @@ class AX_DLL TransitionFlipX : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionFlipX(); virtual ~TransitionFlipX(); @@ -569,7 +570,7 @@ class AX_DLL TransitionFlipY : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionFlipY(); virtual ~TransitionFlipY(); @@ -608,7 +609,7 @@ class AX_DLL TransitionFlipAngular : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionFlipAngular(); virtual ~TransitionFlipAngular(); @@ -647,7 +648,7 @@ class AX_DLL TransitionZoomFlipX : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionZoomFlipX(); virtual ~TransitionZoomFlipX(); @@ -686,7 +687,7 @@ class AX_DLL TransitionZoomFlipY : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionZoomFlipY(); virtual ~TransitionZoomFlipY(); @@ -725,7 +726,7 @@ class AX_DLL TransitionZoomFlipAngular : public TransitionSceneOriented /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; TransitionZoomFlipAngular(); virtual ~TransitionZoomFlipAngular(); @@ -742,14 +743,14 @@ class AX_DLL TransitionFade : public TransitionScene { public: /** Creates the transition with a duration and with an RGB color - * Example: FadeTransition::create(2, scene, Color3B(255,0,0); // red color + * Example: FadeTransition::create(2, scene, Color32(255,0,0,255); // red color * * @param duration Duration time, in seconds. * @param scene A given scene. * @param color A given transition color. * @return A autoreleased TransitionFade object. */ - static TransitionFade* create(float duration, Scene* scene, const Color3B& color); + static TransitionFade* create(float duration, Scene* scene, const Color32& color); /** Creates the transition with a duration. * * @param duration Duration time, in seconds. @@ -761,21 +762,21 @@ class AX_DLL TransitionFade : public TransitionScene /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; TransitionFade(); virtual ~TransitionFade(); - /** initializes the transition with a duration and with an RGB color */ - bool initWithDuration(float t, Scene* scene, const Color3B& color); + /** initializes the transition with a duration and with an RGBA color */ + bool initWithDuration(float t, Scene* scene, const Color32& color); bool initWithDuration(float t, Scene* scene); protected: - Color4B _color; + Color32 _color; private: AX_DISALLOW_COPY_AND_ASSIGN(TransitionFade); @@ -803,15 +804,15 @@ class AX_DLL TransitionCrossFade : public TransitionScene /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; TransitionCrossFade(); virtual ~TransitionCrossFade(); @@ -841,20 +842,20 @@ class AX_DLL TransitionTurnOffTiles : public TransitionScene, public TransitionE /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** */ - virtual void onExit() override; - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; + void onExit() override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; /** */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; TransitionTurnOffTiles(); virtual ~TransitionTurnOffTiles(); protected: - virtual void sceneOrder() override; + void sceneOrder() override; NodeGrid* _outSceneProxy; private: @@ -888,10 +889,10 @@ class AX_DLL TransitionSplitCols : public TransitionScene, public TransitionEase /** * @lua NA */ - virtual void onEnter() override; - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; - virtual void onExit() override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void onEnter() override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; + void onExit() override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; TransitionSplitCols(); virtual ~TransitionSplitCols(); @@ -922,7 +923,7 @@ class AX_DLL TransitionSplitRows : public TransitionSplitCols // // Overrides // - virtual ActionInterval* action() override; + ActionInterval* action() override; TransitionSplitRows(); virtual ~TransitionSplitRows(); @@ -959,16 +960,16 @@ class AX_DLL TransitionFadeTR : public TransitionScene, public TransitionEaseSce /** * @lua NA */ - virtual void onEnter() override; - virtual ActionInterval* easeActionWithAction(ActionInterval* action) override; - virtual void onExit() override; - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void onEnter() override; + ActionInterval* easeActionWithAction(ActionInterval* action) override; + void onExit() override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; TransitionFadeTR(); virtual ~TransitionFadeTR(); protected: - virtual void sceneOrder() override; + void sceneOrder() override; NodeGrid* _outSceneProxy; @@ -994,7 +995,7 @@ class AX_DLL TransitionFadeBL : public TransitionFadeTR // // Overrides // - virtual ActionInterval* actionWithSize(const Vec2& size) override; + ActionInterval* actionWithSize(const Vec2& size) override; TransitionFadeBL(); virtual ~TransitionFadeBL(); @@ -1021,7 +1022,7 @@ class AX_DLL TransitionFadeUp : public TransitionFadeTR // // Overrides // - virtual ActionInterval* actionWithSize(const Vec2& size) override; + ActionInterval* actionWithSize(const Vec2& size) override; TransitionFadeUp(); virtual ~TransitionFadeUp(); @@ -1048,7 +1049,7 @@ class AX_DLL TransitionFadeDown : public TransitionFadeTR // // Overrides // - virtual ActionInterval* actionWithSize(const Vec2& size) override; + ActionInterval* actionWithSize(const Vec2& size) override; TransitionFadeDown(); virtual ~TransitionFadeDown(); diff --git a/core/2d/TransitionPageTurn.cpp b/axmol/2d/TransitionPageTurn.cpp similarity index 96% rename from core/2d/TransitionPageTurn.cpp rename to axmol/2d/TransitionPageTurn.cpp index 9dcf619283e2..6c6c8f6739a6 100644 --- a/core/2d/TransitionPageTurn.cpp +++ b/axmol/2d/TransitionPageTurn.cpp @@ -25,11 +25,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TransitionPageTurn.h" -#include "base/Director.h" -#include "2d/ActionPageTurn3D.h" -#include "2d/NodeGrid.h" -#include "renderer/Renderer.h" +#include "axmol/2d/TransitionPageTurn.h" +#include "axmol/base/Director.h" +#include "axmol/2d/ActionPageTurn3D.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/renderer/Renderer.h" namespace ax { diff --git a/core/2d/TransitionPageTurn.h b/axmol/2d/TransitionPageTurn.h similarity index 93% rename from core/2d/TransitionPageTurn.h rename to axmol/2d/TransitionPageTurn.h index 79a803ae7616..e6afd2c38250 100644 --- a/core/2d/TransitionPageTurn.h +++ b/axmol/2d/TransitionPageTurn.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once -#include "2d/Transition.h" -#include "renderer/CustomCommand.h" +#include "axmol/2d/Transition.h" +#include "axmol/renderer/CustomCommand.h" namespace ax { @@ -70,7 +70,7 @@ class AX_DLL TransitionPageTurn : public TransitionScene // // Overrides // - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * Creates a base transition with duration and incoming scene. @@ -95,8 +95,8 @@ class AX_DLL TransitionPageTurn : public TransitionScene // // Overrides // - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** */ @@ -107,7 +107,7 @@ class AX_DLL TransitionPageTurn : public TransitionScene virtual ~TransitionPageTurn(); protected: - virtual void sceneOrder() override; + void sceneOrder() override; protected: NodeGrid* _inSceneProxy; diff --git a/core/2d/TransitionProgress.cpp b/axmol/2d/TransitionProgress.cpp similarity index 96% rename from core/2d/TransitionProgress.cpp rename to axmol/2d/TransitionProgress.cpp index 1b8b91943003..93b424f53584 100644 --- a/core/2d/TransitionProgress.cpp +++ b/axmol/2d/TransitionProgress.cpp @@ -26,12 +26,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TransitionProgress.h" -#include "base/Director.h" -#include "2d/RenderTexture.h" -#include "2d/ProgressTimer.h" -#include "2d/ActionInstant.h" -#include "2d/ActionProgressTimer.h" +#include "axmol/2d/TransitionProgress.h" +#include "axmol/base/Director.h" +#include "axmol/2d/RenderTexture.h" +#include "axmol/2d/ProgressTimer.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/2d/ActionProgressTimer.h" namespace ax { @@ -67,8 +67,8 @@ void TransitionProgress::onEnter() auto& size = _director->getWinSize(); // create the second render texture for outScene - RenderTexture* texture = RenderTexture::create((int)size.width, (int)size.height, backend::PixelFormat::RGBA8, - backend::PixelFormat::D24S8); + RenderTexture* texture = RenderTexture::create((int)size.width, (int)size.height, rhi::PixelFormat::RGBA8, + rhi::PixelFormat::D24S8); texture->getSprite()->setAnchorPoint(Vec2(0.5f, 0.5f)); texture->setPosition(size.width / 2, size.height / 2); texture->setAnchorPoint(Vec2(0.5f, 0.5f)); diff --git a/core/2d/TransitionProgress.h b/axmol/2d/TransitionProgress.h similarity index 88% rename from core/2d/TransitionProgress.h rename to axmol/2d/TransitionProgress.h index 53bf9cbb7f9a..50c0b482b965 100644 --- a/core/2d/TransitionProgress.h +++ b/axmol/2d/TransitionProgress.h @@ -28,7 +28,7 @@ THE SOFTWARE. #pragma once -#include "2d/Transition.h" +#include "axmol/2d/Transition.h" namespace ax { @@ -57,14 +57,14 @@ class AX_DLL TransitionProgress : public TransitionScene // // Overrides // - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; TransitionProgress(); virtual ~TransitionProgress() {} protected: - virtual void sceneOrder() override; + void sceneOrder() override; protected: virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture); @@ -100,7 +100,7 @@ class AX_DLL TransitionProgressRadialCCW : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; }; /** @class TransitionProgressRadialCW @@ -127,7 +127,7 @@ class AX_DLL TransitionProgressRadialCW : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; }; /** @class TransitionProgressHorizontal @@ -154,7 +154,7 @@ class AX_DLL TransitionProgressHorizontal : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; }; /** @class TransitionProgressVertical @@ -180,7 +180,7 @@ class AX_DLL TransitionProgressVertical : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; }; /** @class TransitionProgressInOut @@ -206,9 +206,9 @@ class AX_DLL TransitionProgressInOut : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; - virtual void sceneOrder() override; - virtual void setupTransition() override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + void sceneOrder() override; + void setupTransition() override; }; /** @class TransitionProgressOutIn @@ -234,7 +234,7 @@ class AX_DLL TransitionProgressOutIn : public TransitionProgress // // Overrides // - virtual ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; + ProgressTimer* progressTimerNodeWithRenderTexture(RenderTexture* texture) override; }; // end of _2d group diff --git a/core/2d/TweenFunction.cpp b/axmol/2d/TweenFunction.cpp similarity index 99% rename from core/2d/TweenFunction.cpp rename to axmol/2d/TweenFunction.cpp index eb19c39d42f5..b0c14a5e6d87 100644 --- a/core/2d/TweenFunction.cpp +++ b/axmol/2d/TweenFunction.cpp @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/TweenFunction.h" +#include "axmol/2d/TweenFunction.h" #define _USE_MATH_DEFINES // needed for M_PI and M_PI2 #include // M_PI diff --git a/core/2d/TweenFunction.h b/axmol/2d/TweenFunction.h similarity index 99% rename from core/2d/TweenFunction.h rename to axmol/2d/TweenFunction.h index 9667630d9d56..8cb722e72ff3 100644 --- a/core/2d/TweenFunction.h +++ b/axmol/2d/TweenFunction.h @@ -27,7 +27,7 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/3d/AABB.cpp b/axmol/3d/AABB.cpp similarity index 99% rename from core/3d/AABB.cpp rename to axmol/3d/AABB.cpp index 8bedc8e2d8f6..c8ea17138d7f 100644 --- a/core/3d/AABB.cpp +++ b/axmol/3d/AABB.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/AABB.h" +#include "axmol/3d/AABB.h" namespace ax { diff --git a/core/3d/AABB.h b/axmol/3d/AABB.h similarity index 98% rename from core/3d/AABB.h rename to axmol/3d/AABB.h index c846e0ef4b7a..8a6ac0515c70 100644 --- a/core/3d/AABB.h +++ b/axmol/3d/AABB.h @@ -25,8 +25,8 @@ #pragma once -#include "base/Macros.h" -#include "math/Math.h" +#include "axmol/base/Macros.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/core/3d/Animate3D.cpp b/axmol/3d/Animate3D.cpp similarity index 98% rename from core/3d/Animate3D.cpp rename to axmol/3d/Animate3D.cpp index dd9108ed0d8e..11a9264110cd 100644 --- a/core/3d/Animate3D.cpp +++ b/axmol/3d/Animate3D.cpp @@ -24,14 +24,14 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Animate3D.h" -#include "3d/MeshRenderer.h" -#include "3d/Skeleton3D.h" -#include "platform/FileUtils.h" -#include "base/Configuration.h" -#include "base/EventCustom.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" +#include "axmol/3d/Animate3D.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Skeleton3D.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" namespace ax { diff --git a/core/3d/Animate3D.h b/axmol/3d/Animate3D.h similarity index 93% rename from core/3d/Animate3D.h rename to axmol/3d/Animate3D.h index 292dc0819f81..f8a6a25889cf 100644 --- a/core/3d/Animate3D.h +++ b/axmol/3d/Animate3D.h @@ -29,10 +29,10 @@ #include #include -#include "3d/Animation3D.h" -#include "base/Macros.h" -#include "base/Object.h" -#include "2d/ActionInterval.h" +#include "axmol/3d/Animation3D.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Object.h" +#include "axmol/2d/ActionInterval.h" namespace ax { @@ -85,13 +85,13 @@ class AX_DLL Animate3D : public ActionInterval // // Overrides // - virtual void stop() override; - virtual void step(float dt) override; - virtual void startWithTarget(Node* target) override; - virtual Animate3D* reverse() const override; - virtual Animate3D* clone() const override; + void stop() override; + void step(float dt) override; + void startWithTarget(Node* target) override; + Animate3D* reverse() const override; + Animate3D* clone() const override; - virtual void update(float t) override; + void update(float t) override; /**get & set speed, negative speed means playing reverse */ float getSpeed() const; diff --git a/core/3d/Animation3D.cpp b/axmol/3d/Animation3D.cpp similarity index 98% rename from core/3d/Animation3D.cpp rename to axmol/3d/Animation3D.cpp index e34fd3cbd54c..d7ebbb0dd32d 100644 --- a/core/3d/Animation3D.cpp +++ b/axmol/3d/Animation3D.cpp @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Animation3D.h" -#include "3d/Bundle3D.h" -#include "platform/FileUtils.h" -#include "base/axstd.h" +#include "axmol/3d/Animation3D.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/axstd.h" namespace ax { diff --git a/core/3d/Animation3D.h b/axmol/3d/Animation3D.h similarity index 96% rename from core/3d/Animation3D.h rename to axmol/3d/Animation3D.h index 947018e49446..14c3cd35ab6c 100644 --- a/core/3d/Animation3D.h +++ b/axmol/3d/Animation3D.h @@ -27,11 +27,11 @@ #include -#include "3d/AnimationCurve.h" +#include "axmol/3d/AnimationCurve.h" -#include "base/Macros.h" -#include "base/Object.h" -#include "3d/Bundle3DData.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Object.h" +#include "axmol/3d/Bundle3DData.h" namespace ax { diff --git a/core/3d/AnimationCurve.h b/axmol/3d/AnimationCurve.h similarity index 95% rename from core/3d/AnimationCurve.h rename to axmol/3d/AnimationCurve.h index f0095ef738ce..2c5ef6f80cf6 100644 --- a/core/3d/AnimationCurve.h +++ b/axmol/3d/AnimationCurve.h @@ -27,9 +27,9 @@ #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" namespace ax { @@ -101,4 +101,4 @@ class AnimationCurve : public Object } -#include "3d/AnimationCurve.inl" +#include "axmol/3d/AnimationCurve.inl" diff --git a/core/3d/AnimationCurve.inl b/axmol/3d/AnimationCurve.inl similarity index 100% rename from core/3d/AnimationCurve.inl rename to axmol/3d/AnimationCurve.inl diff --git a/core/3d/AttachNode.cpp b/axmol/3d/AttachNode.cpp similarity index 97% rename from core/3d/AttachNode.cpp rename to axmol/3d/AttachNode.cpp index 4b748856cd59..dd29a310e68f 100644 --- a/core/3d/AttachNode.cpp +++ b/axmol/3d/AttachNode.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/AttachNode.h" -#include "3d/Skeleton3D.h" +#include "axmol/3d/AttachNode.h" +#include "axmol/3d/Skeleton3D.h" namespace ax { diff --git a/core/3d/AttachNode.h b/axmol/3d/AttachNode.h similarity index 86% rename from core/3d/AttachNode.h rename to axmol/3d/AttachNode.h index a4695e464785..21f7025132cf 100644 --- a/core/3d/AttachNode.h +++ b/axmol/3d/AttachNode.h @@ -25,8 +25,8 @@ #pragma once -#include "math/Math.h" -#include "2d/Node.h" +#include "axmol/math/Math.h" +#include "axmol/2d/Node.h" namespace ax { @@ -54,10 +54,10 @@ class AX_DLL AttachNode : public Node static AttachNode* create(Bone3D* attachBone); // override - virtual Mat4 getWorldToNodeTransform() const override; - virtual Mat4 getNodeToWorldTransform() const override; - virtual const Mat4& getNodeToParentTransform() const override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + Mat4 getWorldToNodeTransform() const override; + Mat4 getNodeToWorldTransform() const override; + const Mat4& getNodeToParentTransform() const override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; AttachNode(); virtual ~AttachNode(); diff --git a/core/3d/BillBoard.cpp b/axmol/3d/BillBoard.cpp similarity index 97% rename from core/3d/BillBoard.cpp rename to axmol/3d/BillBoard.cpp index 4625efd897bd..3733e9ec269e 100644 --- a/core/3d/BillBoard.cpp +++ b/axmol/3d/BillBoard.cpp @@ -23,11 +23,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/BillBoard.h" -#include "2d/SpriteFrameCache.h" -#include "base/Director.h" -#include "2d/Camera.h" -#include "renderer/Renderer.h" +#include "axmol/3d/BillBoard.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/Renderer.h" namespace ax { diff --git a/core/3d/BillBoard.h b/axmol/3d/BillBoard.h similarity index 94% rename from core/3d/BillBoard.h rename to axmol/3d/BillBoard.h index 0f0aa8a019ad..eaa89d64241b 100644 --- a/core/3d/BillBoard.h +++ b/axmol/3d/BillBoard.h @@ -25,7 +25,7 @@ #pragma once -#include "2d/Sprite.h" +#include "axmol/2d/Sprite.h" namespace ax { @@ -94,14 +94,14 @@ class AX_DLL BillBoard : public Sprite // override /** update billboard's transform and turn it towards camera */ - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** * draw BillBoard object. * * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; BillBoard(); virtual ~BillBoard(); diff --git a/axmol/3d/Bundle3D.cpp b/axmol/3d/Bundle3D.cpp new file mode 100644 index 000000000000..a1e7e99ef08a --- /dev/null +++ b/axmol/3d/Bundle3D.cpp @@ -0,0 +1,2354 @@ +/**************************************************************************** +Copyright (c) 2014-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "axmol/3d/Bundle3D.h" +#include "axmol/3d/ObjLoader.h" + +#include "axmol/base/Macros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Data.h" + +#define BUNDLE_TYPE_SCENE 1 +#define BUNDLE_TYPE_NODE 2 +#define BUNDLE_TYPE_ANIMATIONS 3 +#define BUNDLE_TYPE_ANIMATION 4 +#define BUNDLE_TYPE_ANIMATION_CHANNEL 5 +#define BUNDLE_TYPE_MODEL 10 +#define BUNDLE_TYPE_MATERIAL 16 +#define BUNDLE_TYPE_EFFECT 18 +#define BUNDLE_TYPE_CAMERA 32 +#define BUNDLE_TYPE_LIGHT 33 +#define BUNDLE_TYPE_MESH 34 +#define BUNDLE_TYPE_MESHPART 35 +#define BUNDLE_TYPE_MESHSKIN 36 + +static const char* VERSION = "version"; +static const char* ID = "id"; +static const char* DEFAULTPART = "body"; +static const char* VERTEXSIZE = "vertexsize"; +static const char* VERTEX = "vertex"; +static const char* VERTICES = "vertices"; +static const char* INDEXNUM = "indexnum"; +static const char* INDICES = "indices"; +static const char* SUBMESH = "submesh"; +static const char* ATTRIBUTES = "attributes"; +static const char* ATTRIBUTESIZE = "size"; +static const char* TYPE = "type"; +static const char* ATTRIBUTE = "attribute"; +static const char* SKIN = "skin"; +static const char* BINDSHAPE = "bindshape"; +static const char* MESH = "mesh"; +static const char* MESHES = "meshes"; +static const char* MESHPARTID = "meshpartid"; +static const char* MATERIALID = "materialid"; +static const char* NODE = "node"; +static const char* NODES = "nodes"; +static const char* CHILDREN = "children"; +static const char* PARTS = "parts"; +static const char* BONES = "bones"; +static const char* SKELETON = "skeleton"; +static const char* MATERIALS = "materials"; +static const char* ANIMATIONS = "animations"; +static const char* TRANSFORM = "transform"; +static const char* OLDTRANSFORM = "tansform"; +static const char* ANIMATION = "animation"; +static const char* MATERIAL = "material"; +static const char* BASE = "base"; +static const char* FILENAME = "filename"; +static const char* TEXTURES = "textures"; +static const char* LENGTH = "length"; +static const char* BONEID = "boneId"; +static const char* KEYFRAMES = "keyframes"; +static const char* TRANSLATION = "translation"; +static const char* ROTATION = "rotation"; +static const char* SCALE = "scale"; +static const char* KEYTIME = "keytime"; +static const char* AABBS = "aabb"; + +namespace ax +{ +using namespace simdjson; +void getChildMap(std::map>& map, + SkinData* skinData, + simdjson::simdjson_result& val) +{ + if (!skinData) + return; + + // get transform matrix + Mat4 transform; + auto parent_transform = val.get_object()[OLDTRANSFORM]; + int j = 0; + for (auto vv : val) + { + transform.m[j++] = static_cast(vv); + } + + // set origin matrices + std::string_view parent_name = val[ID]; + int parent_name_index = skinData->getSkinBoneNameIndex(parent_name); + if (parent_name_index < 0) + { + skinData->addNodeBoneNames(parent_name); + skinData->nodeBoneOriginMatrices.emplace_back(transform); + parent_name_index = skinData->getBoneNameIndex(parent_name); + } + else if (parent_name_index < static_cast(skinData->skinBoneNames.size())) + { + skinData->skinBoneOriginMatrices[parent_name_index] = transform; + } + + // set root bone index + if (skinData->rootBoneIndex < 0) + skinData->rootBoneIndex = parent_name_index; + + auto children = val[CHILDREN]; + if (children.is_null()) + return; + for (auto child : children) + { + std::string_view child_name = child[ID]; + int child_name_index = skinData->getSkinBoneNameIndex(child_name); + if (child_name_index < 0) + { + skinData->addNodeBoneNames(child_name); + child_name_index = skinData->getBoneNameIndex(child_name); + } + + map[parent_name_index].emplace_back(child_name_index); + + getChildMap(map, skinData, child); + } +} + +Bundle3D* Bundle3D::createBundle() +{ + auto bundle = new Bundle3D(); + return bundle; +} + +void Bundle3D::destroyBundle(Bundle3D* bundle) +{ + delete bundle; +} + +void Bundle3D::clear() +{ + if (_isBinary) + { + _binaryBuffer.clear(); + AX_SAFE_DELETE_ARRAY(_references); + } + else + { + _jsonBuffer.clear(); + } +} + +bool Bundle3D::load(std::string_view path) +{ + if (path.empty()) + return false; + + if (_path == path) + return true; + + getModelRelativePath(path); + + bool ret = false; + std::string ext = FileUtils::getPathExtension(path); + if (ext == ".c3t") + { + _isBinary = false; + ret = loadJson(path); + } + else if (ext == ".c3b") + { + _isBinary = true; + ret = loadBinary(path); + } + else + { + AXLOGW("warning: {} is invalid file format", path.data()); + } + + ret ? (_path = path) : (_path = ""); + + return ret; +} + +bool Bundle3D::loadObj(MeshDatas& meshdatas, + MaterialDatas& materialdatas, + NodeDatas& nodedatas, + std::string_view fullPath, + const char* mtl_basepath) +{ + meshdatas.resetData(); + materialdatas.resetData(); + nodedatas.resetData(); + + std::string mtlPath = ""; + if (mtl_basepath) + mtlPath = mtl_basepath; + else + mtlPath = fullPath.substr(0, fullPath.find_last_of("\\/") + 1); + + std::vector shapes; + std::vector materials; + auto ret = tinyobj::LoadObj(shapes, materials, fullPath.data(), mtlPath.c_str()); + if (ret.empty()) + { + // fill data + // convert material + int i = 0; + char buf[20]; + std::string dir; + auto last = fullPath.rfind('/'); + if (last != std::string::npos) + dir = fullPath.substr(0, last + 1); + for (auto&& material : materials) + { + NMaterialData materialdata; + + NTextureData tex; + tex.filename = material.diffuse_texname.empty() ? material.diffuse_texname : dir + material.diffuse_texname; + tex.type = NTextureData::Usage::Diffuse; + tex.wrapS = rhi::SamplerAddressMode::CLAMP_TO_EDGE; + tex.wrapT = rhi::SamplerAddressMode::CLAMP_TO_EDGE; + + auto dataId = fmt::format_to_z(buf, "{}", ++i); + materialdata.textures.emplace_back(tex); + materialdata.id = dataId; + material.name = dataId; + materialdatas.materials.emplace_back(materialdata); + } + + // convert mesh + i = 0; + for (auto&& shape : shapes) + { + auto mesh = shape.mesh; + MeshData* meshdata = new MeshData(); + MeshVertexAttrib attrib; + attrib.type = parseGLDataType("GL_FLOAT", 3); + + if (mesh.positions.size()) + { + attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; + meshdata->attribs.emplace_back(attrib); + } + bool hasnormal = false, hastex = false; + if (mesh.normals.size()) + { + hasnormal = true; + attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; + meshdata->attribs.emplace_back(attrib); + } + if (mesh.texcoords.size()) + { + hastex = true; + attrib.type = parseGLDataType("GL_FLOAT", 2); + attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; + meshdata->attribs.emplace_back(attrib); + } + + auto vertexNum = mesh.positions.size() / 3; + for (unsigned int k = 0; k < vertexNum; ++k) + { + meshdata->vertex.emplace_back(mesh.positions[k * 3]); + meshdata->vertex.emplace_back(mesh.positions[k * 3 + 1]); + meshdata->vertex.emplace_back(mesh.positions[k * 3 + 2]); + + if (hasnormal) + { + meshdata->vertex.emplace_back(mesh.normals[k * 3]); + meshdata->vertex.emplace_back(mesh.normals[k * 3 + 1]); + meshdata->vertex.emplace_back(mesh.normals[k * 3 + 2]); + } + + if (hastex) + { + meshdata->vertex.emplace_back(mesh.texcoords[k * 2]); + meshdata->vertex.emplace_back(mesh.texcoords[k * 2 + 1]); + } + } + + // split into submesh according to material + std::map subMeshMap; + for (size_t k = 0, size = mesh.material_ids.size(); k < size; ++k) + { + int id = mesh.material_ids[k]; + size_t idx = k * 3; + subMeshMap[id].emplace_back(mesh.indices[idx]); + subMeshMap[id].emplace_back(mesh.indices[idx + 1]); + subMeshMap[id].emplace_back(mesh.indices[idx + 2]); + } + + auto node = new NodeData(); + node->id = shape.name; + for (auto&& submesh : subMeshMap) + { + auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(submesh.second)); + meshdata->subMeshAABB.emplace_back( + calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); + auto meshId = fmt::format_to_z(buf, "{}", ++i); + meshdata->subMeshIds.emplace_back(meshId); + + auto modelnode = new ModelData(); + modelnode->materialId = submesh.first == -1 ? "" : materials[submesh.first].name; + modelnode->subMeshId = meshId; + node->modelNodeDatas.emplace_back(modelnode); + } + nodedatas.nodes.emplace_back(node); + meshdatas.meshDatas.emplace_back(meshdata); + } + + return true; + } + AXLOGW("warning: load {} file error: {}", fullPath, ret); + return false; +} + +bool Bundle3D::loadSkinData(std::string_view /*id*/, SkinData* skindata) +{ + skindata->resetData(); + + if (_isBinary) + { + return loadSkinDataBinary(skindata); + } + else + { + return loadSkinDataJson(skindata); + } +} + +bool Bundle3D::loadAnimationData(std::string_view id, Animation3DData* animationdata) +{ + animationdata->resetData(); + + if (_isBinary) + { + return loadAnimationDataBinary(id, animationdata); + } + else + { + return loadAnimationDataJson(id, animationdata); + } +} + +// since 3.3, to support reskin +bool Bundle3D::loadMeshDatas(MeshDatas& meshdatas) +{ + meshdatas.resetData(); + if (_isBinary) + { + if (_version == "0.1" || _version == "0.2") + { + return loadMeshDatasBinary_0_1(meshdatas); + } + else + { + return loadMeshDatasBinary(meshdatas); + } + } + else + { + if (_version == "1.2" || _version == "0.2") + { + return loadMeshDataJson_0_1(meshdatas); + } + else + { + return loadMeshDatasJson(meshdatas); + } + } + return true; +} +bool Bundle3D::loadMeshDatasBinary(MeshDatas& meshdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MESH)) + return false; + MeshData* meshData = nullptr; + try + { + unsigned int meshSize = _binaryReader.read(); + for (unsigned int i = 0; i < meshSize; ++i) + { + unsigned int attribSize = _binaryReader.read(); + + // read mesh data + if (attribSize < 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + goto FAILED; + } + meshData = new MeshData(); + meshData->attribCount = attribSize; + meshData->attribs.resize(meshData->attribCount); + for (ssize_t j = 0; j < meshData->attribCount; ++j) + { + unsigned int vSize = _binaryReader.read(); + std::string_view type = _binaryReader.read_v32(); + std::string_view attribute = _binaryReader.read_v32(); + meshData->attribs[j].type = parseGLDataType(type, vSize); + meshData->attribs[j].vertexAttrib = parseGLProgramAttribute(attribute); + } + unsigned int vertexSizeInFloat = _binaryReader.read(); + // Read vertex data + if (vertexSizeInFloat == 0) + { + AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); + goto FAILED; + } + + meshData->vertex.resize(vertexSizeInFloat); + + _binaryReader.read_blob(&meshData->vertex[0], 4, vertexSizeInFloat); + + // Read index data + unsigned int meshPartCount = _binaryReader.read(); + for (unsigned int k = 0; k < meshPartCount; ++k) + { + IndexArray indexArray{}; + std::string_view meshPartid = _binaryReader.read_v32(); + meshData->subMeshIds.emplace_back(meshPartid); + unsigned int nIndexCount = _binaryReader.read(); + indexArray.resize(nIndexCount); + _binaryReader.read_blob(indexArray.data(), 2, nIndexCount); + auto& storedIndices = meshData->subMeshIndices.emplace_back(std::move(indexArray)); + meshData->numIndex = (int)meshData->subMeshIndices.size(); + // meshData->subMeshAABB.emplace_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), + // indexArray)); + if (_version != "0.3" && _version != "0.4" && _version != "0.5") + { + // read mesh aabb + Vec3 aabb[2]; + _binaryReader.read_blob(aabb); + meshData->subMeshAABB.emplace_back(AABB(aabb[0], aabb[1])); + } + else + { + meshData->subMeshAABB.emplace_back( + calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); + } + } + meshdatas.meshDatas.emplace_back(meshData); + } + + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } +FAILED: +{ + AX_SAFE_DELETE(meshData); + for (auto&& meshdata : meshdatas.meshDatas) + { + delete meshdata; + } + meshdatas.meshDatas.clear(); + return false; +} +} +bool Bundle3D::loadMeshDatasBinary_0_1(MeshDatas& meshdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MESH)) + return false; + + meshdatas.resetData(); + + MeshData* meshdata = new MeshData(); + + try + { + // read mesh data + unsigned int attribSize = _binaryReader.read(); + if (attribSize < 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + enum + { + VERTEX_ATTRIB_POSITION, + VERTEX_ATTRIB_COLOR, + VERTEX_ATTRIB_TEX_COORD, + VERTEX_ATTRIB_NORMAL, + VERTEX_ATTRIB_BLEND_WEIGHT, + VERTEX_ATTRIB_BLEND_INDEX, + + VERTEX_ATTRIB_MAX, + + // backward compatibility + VERTEX_ATTRIB_TEX_COORDS = VERTEX_ATTRIB_TEX_COORD, + }; + for (unsigned int i = 0; i < attribSize; ++i) + { + auto vUsage = _binaryReader.read(); + auto vSize = _binaryReader.read(); + shaderinfos::VertexKey usage; + + MeshVertexAttrib meshVertexAttribute; + meshVertexAttribute.type = parseGLDataType("GL_FLOAT", vSize); + if (vUsage == VERTEX_ATTRIB_NORMAL) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; + } + else if (vUsage == VERTEX_ATTRIB_BLEND_WEIGHT) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; + } + else if (vUsage == VERTEX_ATTRIB_BLEND_INDEX) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; + } + else if (vUsage == VERTEX_ATTRIB_POSITION) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; + } + else if (vUsage == VERTEX_ATTRIB_TEX_COORD) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; + } + else + { + AXASSERT(false, "invalidate usage value"); + } + meshVertexAttribute.vertexAttrib = usage; + + meshdata->attribs.emplace_back(meshVertexAttribute); + } + + // Read vertex data + meshdata->vertexSizeInFloat = _binaryReader.read(); + if (meshdata->vertexSizeInFloat == 0) + { + AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + meshdata->vertex.resize(meshdata->vertexSizeInFloat); + _binaryReader.read_blob(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat); + + // Read index data + unsigned int meshPartCount = 1; + for (unsigned int i = 0; i < meshPartCount; ++i) + { + unsigned int nIndexCount = _binaryReader.read(); + + IndexArray indices{}; + indices.resize(nIndexCount); + _binaryReader.read_blob(indices.data(), 2, nIndexCount); + + auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); + meshdata->subMeshAABB.emplace_back( + calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); + } + + meshdatas.meshDatas.emplace_back(meshdata); + + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} + +bool Bundle3D::loadMeshDatasBinary_0_2(MeshDatas& meshdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MESH)) + return false; + + meshdatas.resetData(); + + MeshData* meshdata = new MeshData(); + + try + { + // read mesh data + unsigned int attribSize = 0; + if (_binaryReader.read_blob(attribSize) != 1 || attribSize < 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + enum + { + VERTEX_ATTRIB_POSITION, + VERTEX_ATTRIB_COLOR, + VERTEX_ATTRIB_TEX_COORD, + VERTEX_ATTRIB_NORMAL, + VERTEX_ATTRIB_BLEND_WEIGHT, + VERTEX_ATTRIB_BLEND_INDEX, + + VERTEX_ATTRIB_MAX, + + // backward compatibility + VERTEX_ATTRIB_TEX_COORDS = VERTEX_ATTRIB_TEX_COORD, + }; + for (unsigned int i = 0; i < attribSize; ++i) + { + unsigned int vUsage, vSize; + shaderinfos::VertexKey usage = shaderinfos::VertexKey::VERTEX_ATTRIB_ERROR; + if (_binaryReader.read_blob(vUsage) != 1 || _binaryReader.read_blob(vSize) != 1) + { + AXLOGW("warning: Failed to read meshdata: usage or size '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + MeshVertexAttrib meshVertexAttribute; + meshVertexAttribute.type = parseGLDataType("GL_FLOAT", vSize); + if (vUsage == VERTEX_ATTRIB_NORMAL) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; + } + else if (vUsage == VERTEX_ATTRIB_BLEND_WEIGHT) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; + } + else if (vUsage == VERTEX_ATTRIB_BLEND_INDEX) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; + } + else if (vUsage == VERTEX_ATTRIB_POSITION) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; + } + else if (vUsage == VERTEX_ATTRIB_TEX_COORD) + { + usage = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; + } + meshVertexAttribute.vertexAttrib = usage; + + meshdata->attribs.emplace_back(meshVertexAttribute); + } + + // Read vertex data + if (_binaryReader.read_blob(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0) + { + AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + meshdata->vertex.resize(meshdata->vertexSizeInFloat); + if (_binaryReader.read_blob(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat) + { + AXLOGW("warning: Failed to read meshdata: vertex element '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + // read submesh + unsigned int submeshCount; + if (_binaryReader.read_blob(submeshCount) != 1) + { + AXLOGW("warning: Failed to read meshdata: submeshCount '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + for (unsigned int i = 0; i < submeshCount; ++i) + { + unsigned int nIndexCount; + if (_binaryReader.read_blob(nIndexCount) != 1) + { + AXLOGW("warning: Failed to read meshdata: nIndexCount '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + IndexArray indices{}; /* TODO: _version == 1.3 use U_INT?*/ + indices.resize(nIndexCount); + if (_binaryReader.read_blob(indices.data(), 2, nIndexCount) != nIndexCount) + { + AXLOGW("warning: Failed to read meshdata: indices '{}'.", _path); + AX_SAFE_DELETE(meshdata); + return false; + } + + auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); + meshdata->subMeshAABB.emplace_back( + calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); + } + + meshdatas.meshDatas.emplace_back(meshdata); + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + + return false; +} +bool Bundle3D::loadMeshDatasJson(MeshDatas& meshdatas) +{ + auto mesh_data_array = _jsonReader[MESHES]; + for (auto&& mesh_data : mesh_data_array) + { + MeshData* meshData = new MeshData(); + // mesh_vertex_attribute + auto&& mesh_vertex_attribute = mesh_data[ATTRIBUTES].get_array(); + + meshData->attribCount = mesh_vertex_attribute.count_elements(); + meshData->attribs.reserve(meshData->attribCount); + for (auto&& mesh_vertex_attribute_val : mesh_vertex_attribute) + { + int size = static_cast(mesh_vertex_attribute_val[ATTRIBUTESIZE]); + std::string_view type = mesh_vertex_attribute_val[TYPE]; + std::string_view attribute = mesh_vertex_attribute_val[ATTRIBUTE]; + + meshData->attribs.emplace_back(parseGLDataType(type, size), parseGLProgramAttribute(attribute)); + } + // mesh vertices + //////////////////////////////////////////////////////////////////////////////////////////////// + auto&& mesh_data_vertex_array = mesh_data[VERTICES].get_array(); + for (auto&& vertex_val : mesh_data_vertex_array) + { + meshData->vertex.emplace_back(static_cast(vertex_val)); + } + meshData->vertexSizeInFloat = meshData->vertex.size(); + // mesh part + //////////////////////////////////////////////////////////////////////////////////////////////// + auto&& mesh_part_array = mesh_data[PARTS].get_array(); + for (auto&& mesh_part : mesh_part_array) + { + IndexArray indexArray{}; + meshData->subMeshIds.emplace_back(static_cast(mesh_part[ID])); + // index_number + auto&& indices_val_array = mesh_part[INDICES]; + for (auto&& indices_val : indices_val_array) + indexArray.emplace_back(static_cast(indices_val)); + + auto& storedIndices = meshData->subMeshIndices.emplace_back(std::move(indexArray)); + meshData->numIndex = (int)meshData->subMeshIndices.size(); + + auto&& mesh_part_aabb = mesh_part[AABBS]; + if (!mesh_part_aabb.error()) + { + if (mesh_part_aabb.count_elements() == 6) + { + Vec3 aabb_vals[2]; + int aabb_idx = 0; + for (auto aabb_val : mesh_part_aabb) + { + aabb_vals->comps[aabb_idx++] = static_cast(aabb_val); + if (aabb_idx >= 6) + break; + } + meshData->subMeshAABB.emplace_back(AABB(aabb_vals[0], aabb_vals[1])); + } + else + { + meshData->subMeshAABB.emplace_back( + calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); + } + } + else + { + meshData->subMeshAABB.emplace_back( + calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); + } + } + meshdatas.meshDatas.emplace_back(meshData); + } + return true; +} +bool Bundle3D::loadNodes(NodeDatas& nodedatas) +{ + if (_version == "0.1" || _version == "1.2" || _version == "0.2") + { + SkinData skinData; + if (!loadSkinData("", &skinData)) + { + auto node = new NodeData(); + auto modelnode = new ModelData(); + modelnode->materialId = ""; + modelnode->subMeshId = ""; + node->modelNodeDatas.emplace_back(modelnode); + nodedatas.nodes.emplace_back(node); + return true; + } + + auto nodeDatas = new NodeData*[skinData.skinBoneNames.size() + skinData.nodeBoneNames.size()]; + int index = 0; + size_t i; + auto skinBoneSize = skinData.skinBoneNames.size(); + auto nodeBoneSize = skinData.nodeBoneNames.size(); + for (i = 0; i < skinBoneSize; ++i) + { + nodeDatas[index] = new NodeData(); + nodeDatas[index]->id = skinData.skinBoneNames[i]; + nodeDatas[index]->transform = skinData.skinBoneOriginMatrices[i]; + ++index; + } + for (i = 0; i < nodeBoneSize; ++i) + { + nodeDatas[index] = new NodeData(); + nodeDatas[index]->id = skinData.nodeBoneNames[i]; + nodeDatas[index]->transform = skinData.nodeBoneOriginMatrices[i]; + ++index; + } + for (const auto& it : skinData.boneChild) + { + const auto& children = it.second; + auto parent = nodeDatas[it.first]; + for (const auto& child : children) + { + parent->children.emplace_back(nodeDatas[child]); + } + } + nodedatas.skeleton.emplace_back(nodeDatas[skinData.rootBoneIndex]); + auto node = new NodeData(); + auto modelnode = new ModelData(); + modelnode->materialId = ""; + modelnode->subMeshId = ""; + modelnode->bones = skinData.skinBoneNames; + modelnode->invBindPose = skinData.inverseBindPoseMatrices; + node->modelNodeDatas.emplace_back(modelnode); + nodedatas.nodes.emplace_back(node); + delete[] nodeDatas; + } + else + { + if (_isBinary) + { + loadNodesBinary(nodedatas); + } + else + { + loadNodesJson(nodedatas); + } + } + return true; +} +bool Bundle3D::loadMaterials(MaterialDatas& materialdatas) +{ + materialdatas.resetData(); + if (_isBinary) + { + if (_version == "0.1") + { + return loadMaterialsBinary_0_1(materialdatas); + } + else if (_version == "0.2") + { + return loadMaterialsBinary_0_2(materialdatas); + } + else + { + return loadMaterialsBinary(materialdatas); + } + } + else + { + if (_version == "1.2") + { + return loadMaterialDataJson_0_1(materialdatas); + } + else if (_version == "0.2") + { + return loadMaterialDataJson_0_2(materialdatas); + } + else + { + return loadMaterialsJson(materialdatas); + } + } + return true; +} +bool Bundle3D::loadMaterialsBinary(MaterialDatas& materialdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) + return false; + + try + { + unsigned int materialnum = 1; + _binaryReader.read_blob(materialnum); + for (unsigned int i = 0; i < materialnum; ++i) + { + NMaterialData materialData; + materialData.id = _binaryReader.read_v32(); + + // skip: diffuse(3), ambient(3), emissive(3), opacity(1), specular(3), shininess(1) + float data[14]; + _binaryReader.read_blob(data); + + unsigned int textureNum = 1; + _binaryReader.read_blob(textureNum); + for (unsigned int j = 0; j < textureNum; ++j) + { + NTextureData textureData; + textureData.id = _binaryReader.read_v32(); + if (textureData.id.empty()) + { + AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", textureData.id); + return false; + } + std::string_view texturePath = _binaryReader.read_v32(); + if (texturePath.empty()) + { + AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); + return false; + } + (textureData.filename = _modelPath) += texturePath; + float uvdata[4]; + _binaryReader.read_blob(uvdata); + textureData.type = parseGLTextureType(_binaryReader.read_v32()); + textureData.wrapS = parseSamplerAddressMode(_binaryReader.read_v32()); + textureData.wrapT = parseSamplerAddressMode(_binaryReader.read_v32()); + materialData.textures.emplace_back(textureData); + } + materialdatas.materials.emplace_back(materialData); + } + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} +bool Bundle3D::loadMaterialsBinary_0_1(MaterialDatas& materialdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) + return false; + + NMaterialData materialData; + + std::string_view texturePath = _binaryReader.read_v32(); + if (texturePath.empty()) + { + AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); + return false; + } + + NTextureData textureData; + (textureData.filename = _modelPath) += texturePath; + textureData.type = NTextureData::Usage::Diffuse; + textureData.id = ""; + materialData.textures.emplace_back(textureData); + materialdatas.materials.emplace_back(materialData); + return true; +} + +bool Bundle3D::loadMaterialsBinary_0_2(MaterialDatas& materialdatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) + return false; + + try + { + unsigned int materialnum = 1; + _binaryReader.read_blob(materialnum); + + for (unsigned int i = 0; i < materialnum; ++i) + { + NMaterialData materialData; + + std::string_view texturePath = _binaryReader.read_v32(); + if (texturePath.empty()) + { + AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); + return true; + } + + NTextureData textureData; + (textureData.filename = _modelPath) += texturePath; + textureData.type = NTextureData::Usage::Diffuse; + textureData.id = ""; + materialData.textures.emplace_back(textureData); + materialdatas.materials.emplace_back(materialData); + } + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} + +bool loadMeshDataJson(MeshData* /*meshdata*/) +{ + return true; +} + +bool loadMeshDataJson_0_1(MeshData* /*meshdata*/) +{ + return true; +} + +bool loadMeshDataJson_0_2(MeshData* /*meshdata*/) +{ + return true; +} + +bool Bundle3D::loadMaterialsJson(MaterialDatas& materialdatas) +{ + auto material_array = _jsonReader[MATERIALS].get_array(); + if (material_array.error()) + return false; + for (auto&& material_val : material_array) + { + NMaterialData materialData; + materialData.id = static_cast(material_val[ID]); + auto&& texture_array = material_val[TEXTURES]; + if (!texture_array.error()) + { + for (auto&& texture_val : texture_array.get_array()) + { + NTextureData textureData; + std::string_view filename = texture_val[FILENAME]; + if (!filename.empty()) + (textureData.filename = _modelPath) += filename; + textureData.type = parseGLTextureType(texture_val["type"]); + textureData.wrapS = parseSamplerAddressMode(texture_val["wrapModeU"]); + textureData.wrapT = parseSamplerAddressMode(texture_val["wrapModeV"]); + materialData.textures.emplace_back(textureData); + } + } + materialdatas.materials.emplace_back(materialData); + } + return true; +} +bool Bundle3D::loadJson(std::string_view path) +{ + clear(); + + FileUtils::getInstance()->getContents(path, &_jsonBuffer); + + _jsonReader = _jsonParser.iterate(_jsonBuffer); + if (_jsonReader.is_null()) + { + clear(); + AXLOGW("Parse json failed in Bundle3D::loadJson function"); + return false; + } + + auto mash_data_array = _jsonReader[VERSION]; + if (mash_data_array.type() == ondemand::json_type::array) // Compatible with the old version + _version = "1.2"; + else + _version = static_cast(mash_data_array); + + return true; +} + +bool Bundle3D::loadBinary(std::string_view path) +{ + clear(); + + // get file data + _binaryBuffer.clear(); + _binaryBuffer = FileUtils::getInstance()->getDataFromFile(path); + if (_binaryBuffer.isNull()) + { + clear(); + AXLOGW("warning: Failed to read file: {}", path); + return false; + } + + // Initialise bundle reader + _binaryReader.reset((char*)_binaryBuffer.getBytes(), _binaryBuffer.getSize()); + + try + { + // Read identifier info + char identifier[] = {'C', '3', 'B', '\0'}; + char sig[4]; + if (_binaryReader.read_blob(sig) != 4 || memcmp(sig, identifier, 4) != 0) + { + clear(); + AXLOGW("warning: Invalid identifier: {}", path); + return false; + } + + // Read version + unsigned char ver[2]; + if (_binaryReader.read_blob(ver) != 2) + { + AXLOGW("warning: Failed to read version:"); + return false; + } + + char buf[20]; + _version = fmt::format_to_z(buf, "{}.{}", ver[0], ver[1]); + + // Read ref table size + if (_binaryReader.read_blob(_referenceCount) != 1) + { + clear(); + AXLOGW("warning: Failed to read ref table size '{}'.", path); + return false; + } + + // Read all refs + AX_SAFE_DELETE_ARRAY(_references); + _references = new Reference[_referenceCount]; + for (unsigned int i = 0; i < _referenceCount; ++i) + { + if ((_references[i].id = _binaryReader.read_v32()).empty() || + _binaryReader.read_blob(_references[i].type) != 1 || _binaryReader.read_blob(_references[i].offset) != 1) + { + clear(); + AXLOGW("warning: Failed to read ref number {} for bundle '{}'.", i, path); + AX_SAFE_DELETE_ARRAY(_references); + return false; + } + } + + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} + +bool Bundle3D::loadMeshDataJson_0_1(MeshDatas& meshdatas) +{ + auto&& mesh_data_array = _jsonReader[MESH]; + MeshData* meshdata = new MeshData(); + auto&& mesh_data_val = mesh_data_array.at(0); + + auto&& mesh_data_body_array = mesh_data_val[DEFAULTPART]; + + auto&& mesh_data_body_array_0 = mesh_data_body_array.at(0); + + // mesh_vertex_attribute + auto&& mesh_vertex_attribute = mesh_data_val[ATTRIBUTES].get_array(); + meshdata->attribCount = mesh_vertex_attribute.count_elements(); + meshdata->attribs.reserve(meshdata->attribCount); + for (auto&& mesh_vertex_attribute_val : mesh_vertex_attribute) + { + int size = mesh_vertex_attribute_val[ATTRIBUTESIZE]; + meshdata->attribs.emplace_back(parseGLDataType(mesh_vertex_attribute_val[TYPE], size), + parseGLProgramAttribute(mesh_vertex_attribute_val[ATTRIBUTE])); + /*meshdata->attribs[i].type = parseGLDataType(mesh_vertex_attribute_val[TYPE], size); + meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[ATTRIBUTE]);*/ + } + // meshdata->attribCount = meshdata->attribs.size(); + + // vertices + meshdata->vertexSizeInFloat = mesh_data_body_array_0[VERTEXSIZE]; + meshdata->vertex.resize(meshdata->vertexSizeInFloat); + + auto mesh_data_body_vertices = mesh_data_body_array_0[VERTICES]; + int i = 0; + for (auto&& vertex_val : mesh_data_body_vertices) + meshdata->vertex[i++] = static_cast(vertex_val); + + // index_number + int indexnum = mesh_data_body_array_0[INDEXNUM]; + + // indices + IndexArray indices{}; + indices.resize(indexnum); + + auto&& indices_val_array = mesh_data_body_array_0[INDICES]; + i = 0; + for (auto&& index_val : indices_val_array.get_array()) + indices.at(i++) = static_cast(indices_val_array); + + auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); + meshdata->subMeshAABB.emplace_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); + meshdatas.meshDatas.emplace_back(meshdata); + return true; +} + +bool Bundle3D::loadMeshDataJson_0_2(MeshDatas& meshdatas) +{ + MeshData* meshdata = new MeshData(); + auto&& mesh_array = _jsonReader[MESH]; + auto&& mesh_array_0 = mesh_array.at(0); + + // mesh_vertex_attribute + auto&& mesh_vertex_attribute = mesh_array_0[ATTRIBUTES]; + meshdata->attribCount = mesh_vertex_attribute.count_elements(); + meshdata->attribs.resize(meshdata->attribCount); + int i = 0; + for (auto&& mesh_vertex_attribute_val : mesh_vertex_attribute.get_array()) + { + auto size = static_cast(mesh_vertex_attribute_val[ATTRIBUTESIZE]); + meshdata->attribs[i].type = parseGLDataType(mesh_vertex_attribute_val[TYPE], size); + meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[ATTRIBUTE]); + } + + // vertices + auto&& mesh_data_vertex = mesh_array_0[VERTEX]; + auto&& mesh_data_vertex_0 = mesh_data_vertex.at(0); + + meshdata->vertexSizeInFloat = static_cast(mesh_data_vertex_0[VERTEXSIZE]); + meshdata->vertex.resize(meshdata->vertexSizeInFloat); + + auto&& mesh_data_body_vertices = mesh_data_vertex_0[VERTICES]; + i = 0; + for (auto&& vertex_val : mesh_data_body_vertices) + meshdata->vertex[i++] = static_cast(vertex_val); + + // submesh + auto&& mesh_submesh_array = mesh_array_0[SUBMESH]; + for (auto&& mesh_submesh_val : mesh_submesh_array.get_array()) + { + // std::string id = mesh_submesh_val[ID].GetString(); + + // index_number + auto indexnum = static_cast(mesh_submesh_val[INDEXNUM]); + + // indices + IndexArray indices{}; + indices.resize(indexnum); + + auto indices_val_array = mesh_submesh_val[INDICES]; + int j = 0; + for (auto&& index_val : indices_val_array) + indices.at(j) = static_cast(indices_val_array); + + auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); + meshdata->subMeshAABB.emplace_back( + calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); + } + meshdatas.meshDatas.emplace_back(meshdata); + return true; +} + +bool Bundle3D::loadSkinDataJson(SkinData* skindata) +{ + auto&& skin_data_array = _jsonReader[SKIN].get_array(); + if (skin_data_array.error()) + return false; + + // AXASSERT(skin_data_array.(), "skin data is not an array"); + auto&& skin_data_array_val_0 = skin_data_array.at(0); + + auto&& skin_data_bones = skin_data_array_val_0[BONES].get_array(); + if (skin_data_bones.error()) + return false; + for (auto&& skin_data_bone : skin_data_bones) + { + std::string_view name = skin_data_bone[NODE]; + skindata->addSkinBoneNames(name); + + Mat4 mat_bind_pos; + auto&& bind_pos_array = skin_data_bone[BINDSHAPE]; + int j = 0; + for (auto&& pos : bind_pos_array.get_array()) + { + mat_bind_pos.m[j++] = static_cast(pos); + } + skindata->inverseBindPoseMatrices.emplace_back(mat_bind_pos); + } + + // set root bone information + auto&& skin_data_1 = skin_data_array.at(1); + + // parent and child relationship map + skindata->skinBoneOriginMatrices.resize(skindata->skinBoneNames.size()); + getChildMap(skindata->boneChild, skindata, skin_data_1); + return true; +} + +bool Bundle3D::loadSkinDataBinary(SkinData* skindata) +{ + if (!seekToFirstType(BUNDLE_TYPE_MESHSKIN)) + return false; + + try + { + std::string_view boneName = _binaryReader.read_v32(); + + // transform + float bindShape[16]; + if (!_binaryReader.read_blob(bindShape)) + { + AXLOGW("warning: Failed to read SkinData: bindShape matrix '{}'.", _path); + return false; + } + + // bone count + unsigned int boneNum; + if (!_binaryReader.read_blob(boneNum)) + { + AXLOGW("warning: Failed to read SkinData: boneNum '{}'.", _path); + return false; + } + + // Fix bug: check if the bone number is 0. + if (boneNum == 0) + return false; + + // bone names and bind pos + float bindpos[16]; + for (unsigned int i = 0; i < boneNum; ++i) + { + std::string_view skinBoneName = _binaryReader.read_v32(); + skindata->skinBoneNames.emplace_back(skinBoneName); + if (!_binaryReader.read_blob(bindpos)) + { + AXLOGW("warning: Failed to load SkinData: bindpos '{}'.", _path); + return false; + } + skindata->inverseBindPoseMatrices.emplace_back(bindpos); + } + + skindata->skinBoneOriginMatrices.resize(boneNum); + + boneName = _binaryReader.read_v32(); + + // bind shape + _binaryReader.read_blob(bindShape); + int rootIndex = skindata->getSkinBoneNameIndex(boneName); + if (rootIndex < 0) + { + skindata->addNodeBoneNames(boneName); + rootIndex = skindata->getBoneNameIndex(boneName); + skindata->nodeBoneOriginMatrices.emplace_back(bindShape); + } + else + { + skindata->skinBoneOriginMatrices[rootIndex] = bindShape; + } + + // set root bone index + skindata->rootBoneIndex = rootIndex; + + // read parent and child relationship map + float transform[16]; + unsigned int linkNum; + _binaryReader.read_blob(linkNum); + for (unsigned int i = 0; i < linkNum; ++i) + { + std::string_view id = _binaryReader.read_v32(); + int index = skindata->getSkinBoneNameIndex(id); + + std::string_view parentid = _binaryReader.read_v32(); + if (!_binaryReader.read_blob(transform)) + { + AXLOGW("warning: Failed to load SkinData: transform '{}'.", _path); + return false; + } + + if (index < 0) + { + skindata->addNodeBoneNames(id); + index = skindata->getBoneNameIndex(id); + skindata->nodeBoneOriginMatrices.emplace_back(transform); + } + else + { + skindata->skinBoneOriginMatrices[index] = transform; + } + + int parentIndex = skindata->getSkinBoneNameIndex(parentid); + if (parentIndex < 0) + { + skindata->addNodeBoneNames(parentid); + parentIndex = skindata->getBoneNameIndex(parentid); + } + + skindata->boneChild[parentIndex].emplace_back(index); + } + + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} + +bool Bundle3D::loadMaterialDataJson_0_1(MaterialDatas& materialdatas) +{ + NMaterialData materialData; + auto&& material_data_array = _jsonReader[MATERIAL].get_array(); + if (material_data_array.error()) + return false; + + auto&& material_data_array_0 = material_data_array.at(0); + + auto&& material_data_base_array = material_data_array_0[BASE].get_array(); + if (!material_data_base_array.error()) + { + auto&& material_data_base_array_0 = material_data_base_array.at(0); + NTextureData textureData; + // set texture + std::string_view filename = material_data_base_array_0[FILENAME]; + if (!filename.empty()) + (textureData.filename = _modelPath) += filename; + textureData.type = NTextureData::Usage::Diffuse; + materialData.textures.emplace_back(textureData); + materialdatas.materials.emplace_back(materialData); + } + + return true; +} + +bool Bundle3D::loadMaterialDataJson_0_2(MaterialDatas& materialdatas) +{ + NMaterialData materialData; + auto&& material_array = _jsonReader[MATERIAL]; + if (material_array.error()) + return false; + + for (auto&& material_val : material_array.get_array()) + { + NTextureData textureData; + + // set texture + std::string_view filename = material_val[TEXTURES]; + if (!filename.empty()) + (textureData.filename = _modelPath) += filename; + textureData.type = NTextureData::Usage::Diffuse; + materialData.textures.emplace_back(textureData); + } + materialdatas.materials.emplace_back(materialData); + return true; +} + +bool loadMaterialDataJson(MaterialData* /*materialdata*/) +{ + return true; +} + +bool loadMaterialDataJson_0_1(MaterialData* /*materialdata*/) +{ + return true; +} + +bool loadMaterialDataJson_0_2(MaterialData* /*materialdata*/) +{ + return true; +} + +bool Bundle3D::loadAnimationDataJson(std::string_view id, Animation3DData* animationdata) +{ + std::string anim = ""; + if (_version == "1.2" || _version == "0.2") + anim = ANIMATION; + else + anim = ANIMATIONS; + + int the_index = -1; + auto&& animation_data_array = _jsonReader[anim]; + if (animation_data_array.error()) + return false; + + if (!id.empty()) + { + int i = 0; + for (auto&& animation_data : animation_data_array.get_array()) + { + std::string_view keyid = animation_data[ID]; + if (keyid == id) + { + the_index = static_cast(i); + } + ++i; + } + if (the_index < 0) + return false; + } + else + { + the_index = 0; + } + + auto&& animation_data_array_val_0 = animation_data_array.at(the_index); + + animationdata->_totalTime = static_cast(animation_data_array_val_0[LENGTH]); + + auto&& bones = animation_data_array_val_0[BONES]; + for (auto&& bone : bones.get_array()) + { + std::string_view bone_name = bone[BONEID]; + auto&& bone_keyframes = bone[KEYFRAMES]; + if (bone_keyframes.error()) + continue; + size_t keyframe_size = bone_keyframes.count_elements(); + animationdata->_rotationKeys[bone_name].reserve(keyframe_size); + animationdata->_scaleKeys[bone_name].reserve(keyframe_size); + animationdata->_translationKeys[bone_name].reserve(keyframe_size); + + for (auto&& bone_keyframe : bone_keyframes) + { + float keytime = static_cast(bone_keyframe[KEYTIME]); + auto&& bone_keyframe_translation = bone_keyframe[TRANSLATION]; + if (!bone_keyframe_translation.error()) + { + Vec3 val; + int i = 0; + for (auto&& axis_val : bone_keyframe_translation) + { + val.comps[i++] = static_cast(axis_val); + if (i >= 3) + break; + } + animationdata->_translationKeys[bone_name].emplace_back(Animation3DData::Vec3Key(keytime, Vec3{val})); + } + auto&& bone_keyframe_rotation = bone_keyframe[ROTATION]; + if (!bone_keyframe_rotation.error()) + { + Quaternion val; + int i = 0; + for (auto&& axis_val : bone_keyframe_rotation) + { + val.comps[i++] = static_cast(axis_val); + if (i >= 4) + break; + } + animationdata->_rotationKeys[bone_name].emplace_back(Animation3DData::QuatKey(keytime, val)); + } + auto&& bone_keyframe_scale = bone_keyframe[SCALE]; + if (!bone_keyframe_scale.error()) + { + Vec3 val; + int i = 0; + for (auto&& axis_val : bone_keyframe_scale) + { + val.comps[i++] = static_cast(axis_val); + if (i >= 3) + break; + } + animationdata->_scaleKeys[bone_name].emplace_back(Animation3DData::Vec3Key(keytime, val)); + } + } + } + + return true; +} + +bool Bundle3D::loadAnimationDataBinary(std::string_view id, Animation3DData* animationdata) +{ + + if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4") + { + if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS)) + return false; + } + else + { + // if id is not a null string, we need to add a suffix of "animation" for seeding. + std::string id_{id}; + if (!id.empty()) + id_.append("animation"); + + if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS, id_)) + return false; + } + + try + { + unsigned int animNum = 1; + if (_version == "0.3" || _version == "0.4") + { + if (!_binaryReader.read_blob(animNum)) + { + AXLOGW("warning: Failed to read AnimationData: animNum '{}'.", _path); + return false; + } + } + + bool has_found = false; + for (unsigned int k = 0; k < animNum; ++k) + { + animationdata->resetData(); + std::string_view animId = _binaryReader.read_v32(); + + if (!_binaryReader.read_blob(animationdata->_totalTime)) + { + AXLOGW("warning: Failed to read AnimationData: totalTime '{}'.", _path); + return false; + } + + unsigned int nodeAnimationNum; + if (!_binaryReader.read_blob(nodeAnimationNum)) + { + AXLOGW("warning: Failed to read AnimationData: animNum '{}'.", _path); + return false; + } + for (unsigned int i = 0; i < nodeAnimationNum; ++i) + { + std::string_view boneName = _binaryReader.read_v32(); + unsigned int keyframeNum; + if (!_binaryReader.read_blob(keyframeNum)) + { + AXLOGW("warning: Failed to read AnimationData: keyframeNum '{}'.", _path); + return false; + } + + animationdata->_rotationKeys[boneName].reserve(keyframeNum); + animationdata->_scaleKeys[boneName].reserve(keyframeNum); + animationdata->_translationKeys[boneName].reserve(keyframeNum); + + for (unsigned int j = 0; j < keyframeNum; ++j) + { + float keytime; + if (!_binaryReader.read_blob(keytime)) + { + AXLOGW("warning: Failed to read AnimationData: keytime '{}'.", _path); + return false; + } + + // transform flag + unsigned char transformFlag(0); + if (_version != "0.1" && _version != "0.2" && _version != "0.3") + { + if (!_binaryReader.read_blob(transformFlag)) + { + AXLOGW("warning: Failed to read AnimationData: transformFlag '{}'.", _path); + return false; + } + } + + // rotation + bool hasRotate = true; + if (_version != "0.1" && _version != "0.2" && _version != "0.3") + hasRotate = transformFlag & 0x01; + + if (hasRotate) + { + Quaternion rotate; + if (_binaryReader.read_blob(rotate.comps) != 4) + { + AXLOGW("warning: Failed to read AnimationData: rotate '{}'.", _path); + return false; + } + animationdata->_rotationKeys[boneName].emplace_back(Animation3DData::QuatKey(keytime, rotate)); + } + + // scale + bool hasScale = true; + if (_version != "0.1" && _version != "0.2" && _version != "0.3") + hasScale = (transformFlag >> 1) & 0x01; + + if (hasScale) + { + Vec3 scale; + if (_binaryReader.read_blob(scale.comps) != 3) + { + AXLOGW("warning: Failed to read AnimationData: scale '{}'.", _path); + return false; + } + animationdata->_scaleKeys[boneName].emplace_back(Animation3DData::Vec3Key(keytime, scale)); + } + + // translation + bool hasTranslation = true; + if (_version != "0.1" && _version != "0.2" && _version != "0.3") + hasTranslation = (transformFlag >> 2) & 0x01; + + if (hasTranslation) + { + Vec3 position; + if (_binaryReader.read_blob(position.comps) != 3) + { + AXLOGW("warning: Failed to read AnimationData: position '{}'.", _path); + return false; + } + animationdata->_translationKeys[boneName].emplace_back( + Animation3DData::Vec3Key(keytime, position)); + } + } + } + if (id == animId || id.empty()) + { + has_found = true; + break; + } + } + if (!has_found) + { + animationdata->resetData(); + return false; + } + return true; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return false; +} + +bool Bundle3D::loadNodesJson(NodeDatas& nodedatas) +{ + auto&& nodes = _jsonReader[NODES]; + if (nodes.error()) + return false; + + // traverse the nodes again + int node_count = nodes.count_elements(); + for (auto&& jnode : nodes.get_array()) + { + + NodeData* nodedata = parseNodesRecursivelyJson(jnode, node_count == 1); + + bool isSkeleton = jnode[SKELETON]; + if (isSkeleton) + nodedatas.skeleton.emplace_back(nodedata); + else + nodedatas.nodes.emplace_back(nodedata); + } + return true; +} +NodeData* Bundle3D::parseNodesRecursivelyJson(simdjson::simdjson_result jvalue, + bool singleSprite) +{ + NodeData* nodedata = new NodeData(); + // id + nodedata->id = static_cast(jvalue[ID]); + + // transform + Mat4 transform; + auto&& jtransform = jvalue[TRANSFORM]; + int j = 0; + for (auto&& val : jtransform.get_array()) + { + transform.m[j++] = static_cast(val); + } + + nodedata->transform = transform; + + bool isSkin = false; + + // parts + auto&& parts = jvalue[PARTS]; + if (!parts.error()) + { + for (auto&& part : parts.get_array()) + { + auto modelnodedata = new ModelData(); + modelnodedata->subMeshId = static_cast(part[MESHPARTID]); + modelnodedata->materialId = static_cast(part[MATERIALID]); + + if (modelnodedata->subMeshId == "" || modelnodedata->materialId == "") + { + AXLOGW("warning: Node {} part is missing meshPartId or materialId", nodedata->id); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + auto&& bones = part[BONES]; + if (!bones.error()) + { + unsigned int bones_count = 0; + for (auto&& bone : bones.get_array()) + { + // node + auto&& node_name = bone[NODE]; + if (node_name.error()) + { + AXLOGW("warning: Bone node ID missing"); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + + ++bones_count; + modelnodedata->bones.emplace_back(static_cast(node_name)); + + Mat4 invbindpos; + auto&& jinvbindpos = bone[TRANSFORM]; + int k = 0; + for (auto&& val : jinvbindpos) + { + invbindpos.m[k] = static_cast(val); + } + + // invbindpos.inverse(); + modelnodedata->invBindPose.emplace_back(invbindpos); + } + + if (bones_count) + isSkin = true; + } + nodedata->modelNodeDatas.emplace_back(modelnodedata); + } + } + + // set transform + if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || + _version == "0.6") + { + if (isSkin || singleSprite) + { + nodedata->transform = Mat4::IDENTITY; + } + else + { + nodedata->transform = transform; + } + } + else + { + nodedata->transform = transform; + } + + auto&& children = jvalue[CHILDREN].get_array(); + if (!children.error()) + { + for (auto&& child : children) + { + NodeData* tempdata = parseNodesRecursivelyJson(child, singleSprite); + nodedata->children.emplace_back(tempdata); + } + } + return nodedata; +} + +bool Bundle3D::loadNodesBinary(NodeDatas& nodedatas) +{ + if (!seekToFirstType(BUNDLE_TYPE_NODE)) + return false; + + unsigned int nodeSize = 0; + if (_binaryReader.read_blob(nodeSize) != 1) + { + AXLOGW("warning: Failed to read nodes"); + return false; + } + + // traverse the nodes again + for (unsigned int i = 0; i < nodeSize; ++i) + { + bool skeleton = false; + NodeData* nodedata = parseNodesRecursivelyBinary(skeleton, nodeSize == 1); + + if (skeleton) + nodedatas.skeleton.emplace_back(nodedata); + else + nodedatas.nodes.emplace_back(nodedata); + } + return true; +} +NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton, bool singleSprite) +{ + try + { + // id + std::string_view id = _binaryReader.read_v32(); + // is skeleton + bool skeleton_; + if (_binaryReader.read_blob(skeleton_) != 1) + { + AXLOGW("warning: Failed to read is skeleton"); + return nullptr; + } + if (skeleton_) + skeleton = true; + + // transform + Mat4 transform; + if (!_binaryReader.read_blob(transform.m)) + { + AXLOGW("warning: Failed to read transform matrix"); + return nullptr; + } + // parts + unsigned int partsSize = 0; + if (_binaryReader.read_blob(partsSize) != 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + return nullptr; + } + + NodeData* nodedata = new NodeData(); + nodedata->id = id; + + bool isSkin = false; + + if (partsSize > 0) + { + for (unsigned int i = 0; i < partsSize; ++i) + { + auto modelnodedata = new ModelData(); + modelnodedata->subMeshId = _binaryReader.read_v32(); + modelnodedata->materialId = _binaryReader.read_v32(); + + if (modelnodedata->subMeshId.empty() || modelnodedata->materialId.empty()) + { + AXLOGW("Node {} part is missing meshPartId or materialId", nodedata->id); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + + // read bone + unsigned int bonesSize = 0; + if (_binaryReader.read_blob(bonesSize) != 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + + if (bonesSize > 0) + { + for (unsigned int j = 0; j < bonesSize; ++j) + { + std::string_view name = _binaryReader.read_v32(); + modelnodedata->bones.emplace_back(name); + + Mat4 invbindpos; + if (!_binaryReader.read_blob(invbindpos.m)) + { + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + + modelnodedata->invBindPose.emplace_back(invbindpos); + } + isSkin = true; + } + unsigned int uvMapping = 0; + if (_binaryReader.read_blob(uvMapping) != 1) + { + AXLOGW("warning: Failed to read nodedata: uvMapping '{}'.", _path); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + for (unsigned int j = 0; j < uvMapping; ++j) + { + unsigned int textureIndexSize = 0; + if (_binaryReader.read_blob(textureIndexSize) != 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + for (unsigned int k = 0; k < textureIndexSize; ++k) + { + unsigned int index = 0; + if (_binaryReader.read_blob(index) != 1) + { + AX_SAFE_DELETE(modelnodedata); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + } + } + nodedata->modelNodeDatas.emplace_back(modelnodedata); + } + } + + // set transform + if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || + _version == "0.6") + { + if (isSkin || singleSprite) + { + nodedata->transform = Mat4::IDENTITY; + } + else + { + nodedata->transform = transform; + } + } + else + { + nodedata->transform = transform; + } + + unsigned int childrenSize = 0; + if (_binaryReader.read_blob(childrenSize) != 1) + { + AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); + AX_SAFE_DELETE(nodedata); + return nullptr; + } + if (childrenSize > 0) + { + for (unsigned int i = 0; i < childrenSize; ++i) + { + NodeData* tempdata = parseNodesRecursivelyBinary(skeleton, singleSprite); + nodedata->children.emplace_back(tempdata); + } + } + return nodedata; + } + catch (const std::exception& ex) + { + AXLOGW("exception occurred: {}", ex.what()); + } + return nullptr; +} + +rhi::VertexFormat Bundle3D::parseGLDataType(std::string_view str, int size) +{ + rhi::VertexFormat ret = rhi::VertexFormat::INT; + if (str == "GL_BYTE") + { + switch (size) + { + case 4: + return rhi::VertexFormat::UBYTE4; + default: + AXLOGE("parseVertexType GL_BYTE x {} error", size); + } + } + else if (str == "GL_UNSIGNED_BYTE") + { + switch (size) + { + case 4: + return rhi::VertexFormat::UBYTE4; + default: + AXLOGE("parseVertexType GL_UNSIGNED_BYTE x {} error", size); + } + } + else if (str == "GL_SHORT") + { + switch (size) + { + case 2: + return rhi::VertexFormat::USHORT2; + case 4: + return rhi::VertexFormat::USHORT4; + default: + AXLOGE("parseVertexType GL_SHORT x {} error", size); + } + } + else if (str == "GL_UNSIGNED_SHORT") + { + switch (size) + { + case 2: + return rhi::VertexFormat::USHORT2; + case 4: + return rhi::VertexFormat::USHORT4; + default: + AXLOGE("parseVertexType GL_UNSIGNED_SHORT x {} error", size); + } + } + else if (str == "GL_INT") + { + switch (size) + { + case 1: + return rhi::VertexFormat::INT; + case 2: + return rhi::VertexFormat::INT2; + case 3: + return rhi::VertexFormat::INT3; + case 4: + return rhi::VertexFormat::INT4; + default: + AXLOGE("parseVertexType GL_INT x {} error", size); + } + } + else if (str == "GL_UNSIGNED_INT") + { + switch (size) + { + case 1: + return rhi::VertexFormat::INT; + case 2: + return rhi::VertexFormat::INT2; + case 3: + return rhi::VertexFormat::INT3; + case 4: + return rhi::VertexFormat::INT4; + default: + AXLOGE("parseVertexType GL_UNSIGNED_INT x {} error", size); + } + } + else if (str == "GL_FLOAT") + { + switch (size) + { + case 1: + return rhi::VertexFormat::FLOAT; + case 2: + return rhi::VertexFormat::FLOAT2; + case 3: + return rhi::VertexFormat::FLOAT3; + case 4: + return rhi::VertexFormat::FLOAT4; + default: + AXLOGE("parseVertexType GL_UNSIGNED_INT x {} error", size); + } + } + AXASSERT(false, "parseVertexType failed!"); + return ret; +} + +rhi::SamplerAddressMode Bundle3D::parseSamplerAddressMode(std::string_view str) +{ + + if (str == "REPEAT") + { + return rhi::SamplerAddressMode::REPEAT; + } + else if (str == "CLAMP") + { + return rhi::SamplerAddressMode::CLAMP_TO_EDGE; + } + else + { + AXASSERT(false, "Invalid GL type"); + return rhi::SamplerAddressMode::REPEAT; + } +} + +NTextureData::Usage Bundle3D::parseGLTextureType(std::string_view str) +{ + if (str == "AMBIENT") + { + return NTextureData::Usage::Ambient; + } + else if (str == "BUMP") + { + return NTextureData::Usage::Bump; + } + else if (str == "DIFFUSE") + { + return NTextureData::Usage::Diffuse; + } + else if (str == "EMISSIVE") + { + return NTextureData::Usage::Emissive; + } + else if (str == "NONE") + { + return NTextureData::Usage::None; + } + else if (str == "NORMAL") + { + return NTextureData::Usage::Normal; + } + else if (str == "REFLECTION") + { + return NTextureData::Usage::Reflection; + } + else if (str == "SHININESS") + { + return NTextureData::Usage::Shininess; + } + else if (str == "SPECULAR") + { + return NTextureData::Usage::Specular; + } + else if (str == "TRANSPARENCY") + { + return NTextureData::Usage::Transparency; + } + else + { + AXASSERT(false, "Wrong Texture type"); + return NTextureData::Usage::Unknown; + } +} +shaderinfos::VertexKey Bundle3D::parseGLProgramAttribute(std::string_view str) +{ + if (str == "VERTEX_ATTRIB_POSITION") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; + } + else if (str == "VERTEX_ATTRIB_COLOR") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_COLOR; + } + else if (str == "VERTEX_ATTRIB_TEX_COORD") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; + } + else if (str == "VERTEX_ATTRIB_TEX_COORD1") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD1; + } + else if (str == "VERTEX_ATTRIB_TEX_COORD2") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD2; + } + else if (str == "VERTEX_ATTRIB_TEX_COORD3") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD3; + } + // comment out them + // else if (str == "VERTEX_ATTRIB_TEX_COORD4") + // { + // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD4; + // } + // else if (str == "VERTEX_ATTRIB_TEX_COORD5") + // { + // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD5; + // } + // else if (str == "VERTEX_ATTRIB_TEX_COORD6") + // { + // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD6; + // } + // else if (str == "VERTEX_ATTRIB_TEX_COORD7") + // { + // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD7; + // } + else if (str == "VERTEX_ATTRIB_NORMAL") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; + } + else if (str == "VERTEX_ATTRIB_BLEND_WEIGHT") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; + } + else if (str == "VERTEX_ATTRIB_BLEND_INDEX") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; + } + else if (str == "VERTEX_ATTRIB_TANGENT") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_TANGENT; + } + else if (str == "VERTEX_ATTRIB_BINORMAL") + { + return shaderinfos::VertexKey::VERTEX_ATTRIB_BINORMAL; + } + else + { + AXASSERT(false, "Wrong Attribute type"); + return shaderinfos::VertexKey::VERTEX_ATTRIB_ERROR; + } +} + +void Bundle3D::getModelRelativePath(std::string_view path) +{ + ssize_t index = path.find_last_of('/'); + std::string fullModelPath; + _modelPath = path.substr(0, index + 1); +} + +Reference* Bundle3D::seekToFirstType(unsigned int type, std::string_view id) +{ + // for each Reference + for (unsigned int i = 0; i < _referenceCount; ++i) + { + Reference* ref = &_references[i]; + if (ref->type == type) + { + // if id is not a null string, we also need to check the Reference's id. + if (id != "" && id != ref->id) + { + continue; + } + + // Found a match + if (_binaryReader.seek(ref->offset, SEEK_SET) != ref->offset) + { + AXLOGW("warning: Failed to seek to object '{}' in bundle '{}'.", ref->id, _path); + return nullptr; + } + return ref; + } + } + return nullptr; +} + +std::vector Bundle3D::getTrianglesList(std::string_view path) +{ + std::vector trianglesList; + + if (path.length() <= 4) + return trianglesList; + + auto bundle = Bundle3D::createBundle(); + std::string ext = FileUtils::getPathExtension(path); + MeshDatas meshs; + if (ext == ".obj") + { + MaterialDatas materials; + NodeDatas nodes; + if (!Bundle3D::loadObj(meshs, materials, nodes, path)) + { + Bundle3D::destroyBundle(bundle); + return trianglesList; + } + } + else + { + if (!bundle->load(path)) + { + Bundle3D::destroyBundle(bundle); + return trianglesList; + } + + bundle->loadMeshDatas(meshs); + } + + Bundle3D::destroyBundle(bundle); + for (auto&& iter : meshs.meshDatas) + { + int preVertexSize = iter->getPerVertexSize() / sizeof(float); + for (const auto& indices : iter->subMeshIndices) + { + indices.for_each([&](unsigned int ind) { + trianglesList.emplace_back(Vec3(iter->vertex[ind * preVertexSize], + iter->vertex[ind * preVertexSize + 1], + iter->vertex[ind * preVertexSize + 2])); + }); + } + } + + return trianglesList; +} + +Bundle3D::Bundle3D() + : _modelPath(""), _path(""), _version(""), _referenceCount(0), _references(nullptr), _isBinary(false) +{} +Bundle3D::~Bundle3D() +{ + clear(); +} + +ax::AABB Bundle3D::calculateAABB(const std::vector& vertex, int stride, const IndexArray& indices) +{ + AABB aabb; + stride /= 4; + + indices.for_each([&](uint32_t i) { + Vec3 point(vertex[i * stride], vertex[i * stride + 1], vertex[i * stride + 2]); + aabb.updateMinMax(&point, 1); + }); + + return aabb; +} + +} // namespace ax diff --git a/core/3d/Bundle3D.h b/axmol/3d/Bundle3D.h similarity index 91% rename from core/3d/Bundle3D.h rename to axmol/3d/Bundle3D.h index 1f0084b99e47..93263906dc6d 100644 --- a/core/3d/Bundle3D.h +++ b/axmol/3d/Bundle3D.h @@ -26,12 +26,10 @@ #pragma once -#include "base/Data.h" -#include "3d/Bundle3DData.h" -#include "3d/BundleReader.h" -#include "rapidjson/rapidjson.h" -#include "rapidjson/document.h" - +#include "axmol/base/Data.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/base/json.h" +#include "yasio/ibstream.hpp" namespace ax { @@ -66,13 +64,13 @@ class AX_DLL Bundle3D * get define data type * @param str The type in string */ - static backend::VertexFormat parseGLDataType(std::string_view str, int size); + static rhi::VertexFormat parseGLDataType(std::string_view str, int size); /** * get define data type * @param str The type in string */ - static backend::SamplerAddressMode parseSamplerAddressMode(std::string_view str); + static rhi::SamplerAddressMode parseSamplerAddressMode(std::string_view str); /** * load a file. You must load a file first, then call loadMeshData, loadSkinData, and so on @@ -149,7 +147,7 @@ class AX_DLL Bundle3D * load nodes of json */ bool loadNodesJson(NodeDatas& nodedatas); - NodeData* parseNodesRecursivelyJson(const rapidjson::Value& jvalue, bool singleSprite); + NodeData* parseNodesRecursivelyJson(simdjson::simdjson_result jvalue, bool singleSprite); /** * load nodes of binary @@ -188,12 +186,13 @@ class AX_DLL Bundle3D std::string _version; // the c3b or c3t version // for json reading - std::string _jsonBuffer; - rapidjson::Document _jsonReader; + simdjson::PaddedString _jsonBuffer; + simdjson::ondemand::parser _jsonParser; + simdjson::ondemand::document _jsonReader; // for binary reading Data _binaryBuffer; - BundleReader _binaryReader; + yasio::fast_ibstream_view _binaryReader; unsigned int _referenceCount; Reference* _references; bool _isBinary; diff --git a/axmol/3d/Bundle3DData.cpp b/axmol/3d/Bundle3DData.cpp new file mode 100644 index 000000000000..082386bea34c --- /dev/null +++ b/axmol/3d/Bundle3DData.cpp @@ -0,0 +1,32 @@ +#include "axmol/3d/Bundle3DData.h" + +namespace ax +{ + +int MeshVertexAttrib::getAttribSizeBytes() const +{ + int ret = 0; + switch (type) + { + case rhi::VertexFormat::FLOAT4: + case rhi::VertexFormat::INT4: + return 16; + case rhi::VertexFormat::FLOAT3: + case rhi::VertexFormat::INT3: + return 12; + case rhi::VertexFormat::FLOAT2: + case rhi::VertexFormat::INT2: + case rhi::VertexFormat::USHORT4: + return 8; + case rhi::VertexFormat::FLOAT: + case rhi::VertexFormat::INT: + case rhi::VertexFormat::UBYTE4: + case rhi::VertexFormat::USHORT2: + return 4; + default: + AXASSERT(false, "VertexFormat convert to size error"); + } + return ret; +} + +} diff --git a/core/3d/Bundle3DData.h b/axmol/3d/Bundle3DData.h similarity index 93% rename from core/3d/Bundle3DData.h rename to axmol/3d/Bundle3DData.h index d4151c62a725..421b45d6bfe1 100644 --- a/core/3d/Bundle3DData.h +++ b/axmol/3d/Bundle3DData.h @@ -26,20 +26,17 @@ #pragma once -#include "base/Object.h" -#include "base/Types.h" -#include "math/Math.h" -#include "3d/AABB.h" - -#include "renderer/backend/Types.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/math/Math.h" +#include "axmol/3d/AABB.h" #include #include #include -#include "3d/3DProgramInfo.h" - -#include "yasio/byte_buffer.hpp" +#include "axmol/3d/shaderinfos.h" +#include "axmol/base/axstd.h" namespace ax { @@ -55,14 +52,14 @@ inline constexpr bool is_index_format_type_v = class IndexArray { public: - static constexpr unsigned int formatToStride(backend::IndexFormat format) { return 1 << (int)format; } - static constexpr backend::IndexFormat strideToFormat(unsigned int stride) + static constexpr unsigned int formatToStride(rhi::IndexFormat format) { return 1 << (int)format; } + static constexpr rhi::IndexFormat strideToFormat(unsigned int stride) { - return (backend::IndexFormat)(stride >> 1); + return (rhi::IndexFormat)(stride >> 1); } - IndexArray() : _stride(formatToStride(backend::IndexFormat::U_SHORT)) {} - IndexArray(backend::IndexFormat indexFormat) : _stride(formatToStride(indexFormat)) {} + IndexArray() : _stride(formatToStride(rhi::IndexFormat::U_SHORT)) {} + IndexArray(rhi::IndexFormat indexFormat) : _stride(formatToStride(indexFormat)) {} template , int> = 0> IndexArray(std::initializer_list<_Ty> rhs) : _stride(sizeof(_Ty)) @@ -94,13 +91,13 @@ class IndexArray } /** Returns the format of the index array. */ - backend::IndexFormat format() const { return strideToFormat(_stride); } + rhi::IndexFormat format() const { return strideToFormat(_stride); } /** Clears the internal byte buffer. */ void clear() { _buffer.clear(); } /** Clears the internal byte buffer and sets the format specified. */ - void clear(backend::IndexFormat format) + void clear(rhi::IndexFormat format) { clear(); _stride = formatToStride(format); @@ -223,7 +220,7 @@ class IndexArray */ struct AX_DLL MeshVertexAttrib { - backend::VertexFormat type; + rhi::VertexFormat type; shaderinfos::VertexKey vertexAttrib; int getAttribSizeBytes() const; }; @@ -313,7 +310,7 @@ struct MeshData std::vector subMeshIds; // subMesh Names (since 3.3) std::vector subMeshAABB; int numIndex; - std::vector attribs; + axstd::pod_vector attribs; int attribCount; public: @@ -466,8 +463,8 @@ struct NTextureData std::string id; std::string filename; Usage type; - backend::SamplerAddressMode wrapS; - backend::SamplerAddressMode wrapT; + rhi::SamplerAddressMode wrapS; + rhi::SamplerAddressMode wrapT; }; struct NMaterialData { @@ -527,9 +524,9 @@ struct Animation3DData }; public: - std::map> _translationKeys; - std::map> _rotationKeys; - std::map> _scaleKeys; + hlookup::string_map> _translationKeys; + hlookup::string_map> _rotationKeys; + hlookup::string_map> _scaleKeys; float _totalTime; diff --git a/core/3d/CMakeLists.txt b/axmol/3d/CMakeLists.txt similarity index 83% rename from core/3d/CMakeLists.txt rename to axmol/3d/CMakeLists.txt index 60e2a500de15..c402e534131c 100644 --- a/core/3d/CMakeLists.txt +++ b/axmol/3d/CMakeLists.txt @@ -1,4 +1,5 @@ set(_AX_3D_HEADER + 3d/BillBoard.h 3d/Frustum.h 3d/MeshVertexIndexData.h @@ -15,16 +16,14 @@ set(_AX_3D_HEADER 3d/MotionStreak3D.h 3d/Skybox.h 3d/MeshSkin.h - 3d/cocos3d.h 3d/AABB.h 3d/Bundle3D.h 3d/ObjLoader.h 3d/Bundle3DData.h 3d/Skeleton3D.h - 3d/BundleReader.h 3d/AttachNode.h - 3d/VertexAttribBinding.h - 3d/3DProgramInfo.h + 3d/VertexInputBinding.h + 3d/shaderinfos.h ) set(_AX_3D_SRC @@ -36,7 +35,6 @@ set(_AX_3D_SRC 3d/BillBoard.cpp 3d/Bundle3D.cpp 3d/Bundle3DData.cpp - 3d/BundleReader.cpp 3d/Frustum.cpp 3d/Mesh.cpp 3d/MeshSkin.cpp @@ -51,6 +49,6 @@ set(_AX_3D_SRC 3d/MeshRenderer.cpp 3d/MeshMaterial.cpp 3d/Terrain.cpp - 3d/VertexAttribBinding.cpp - 3d/3DProgramInfo.cpp + 3d/VertexInputBinding.cpp + 3d/shaderinfos.cpp ) diff --git a/core/3d/Frustum.cpp b/axmol/3d/Frustum.cpp similarity index 98% rename from core/3d/Frustum.cpp rename to axmol/3d/Frustum.cpp index 084d80480e38..9ac05c30ef6b 100644 --- a/core/3d/Frustum.cpp +++ b/axmol/3d/Frustum.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Frustum.h" -#include "2d/Camera.h" +#include "axmol/3d/Frustum.h" +#include "axmol/2d/Camera.h" namespace ax { diff --git a/core/3d/Frustum.h b/axmol/3d/Frustum.h similarity index 94% rename from core/3d/Frustum.h rename to axmol/3d/Frustum.h index 3db096a319a7..4aa20ffc59be 100644 --- a/core/3d/Frustum.h +++ b/axmol/3d/Frustum.h @@ -25,11 +25,11 @@ #pragma once -#include "base/Macros.h" -#include "math/Math.h" -#include "3d/AABB.h" -#include "3d/OBB.h" -#include "3d/Plane.h" +#include "axmol/base/Macros.h" +#include "axmol/math/Math.h" +#include "axmol/3d/AABB.h" +#include "axmol/3d/OBB.h" +#include "axmol/3d/Plane.h" namespace ax { diff --git a/core/3d/Mesh.cpp b/axmol/3d/Mesh.cpp similarity index 93% rename from core/3d/Mesh.cpp rename to axmol/3d/Mesh.cpp index e4c3b8440321..9509567dc81f 100644 --- a/core/3d/Mesh.cpp +++ b/axmol/3d/Mesh.cpp @@ -24,25 +24,25 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Mesh.h" -#include "3d/MeshSkin.h" -#include "3d/Skeleton3D.h" -#include "3d/MeshVertexIndexData.h" -#include "3d/VertexAttribBinding.h" -#include "2d/Light.h" -#include "2d/Scene.h" -#include "base/EventDispatcher.h" -#include "base/Director.h" -#include "base/Configuration.h" -#include "renderer/TextureCache.h" -#include "renderer/Material.h" -#include "renderer/Technique.h" -#include "renderer/Pass.h" -#include "renderer/Renderer.h" -#include "renderer/backend/Buffer.h" -#include "renderer/backend/Program.h" -#include "renderer/RenderConsts.h" -#include "math/Mat4.h" +#include "axmol/3d/Mesh.h" +#include "axmol/3d/MeshSkin.h" +#include "axmol/3d/Skeleton3D.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/VertexInputBinding.h" +#include "axmol/2d/Light.h" +#include "axmol/2d/Scene.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/base/Configuration.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Pass.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/Program.h" +#include "axmol/renderer/RenderConsts.h" +#include "axmol/math/Mat4.h" using namespace std; @@ -167,7 +167,7 @@ void Mesh::setDynamicInstancing(bool dynamic) _dynamicInstancing = dynamic; } -backend::Buffer* Mesh::getVertexBuffer() const +rhi::Buffer* Mesh::getVertexBuffer() const { return _meshIndexData->getVertexBuffer(); } @@ -199,10 +199,10 @@ Mesh* Mesh::create(const std::vector& positions, { int perVertexSizeInFloat = 0; std::vector vertices; - std::vector attribs; + axstd::pod_vector attribs; MeshVertexAttrib att; - att.type = backend::VertexFormat::FLOAT3; + att.type = rhi::VertexFormat::FLOAT3; attribs.reserve(3); @@ -224,7 +224,7 @@ Mesh* Mesh::create(const std::vector& positions, if (!texs.empty()) { perVertexSizeInFloat += 2; - att.type = backend::VertexFormat::FLOAT2; + att.type = rhi::VertexFormat::FLOAT2; att.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; attribs.emplace_back(att); hasTexCoord = 1; @@ -258,7 +258,7 @@ Mesh* Mesh::create(const std::vector& positions, Mesh* Mesh::create(const std::vector& vertices, int /*perVertexSizeInFloat*/, const IndexArray& indices, - const std::vector& attribs) + const axstd::pod_vector& attribs) { MeshData meshdata; meshdata.attribs = attribs; @@ -396,15 +396,15 @@ void Mesh::setMaterial(Material* material) if (_material->getTechnique()->getName().compare(technique->getName()) == 0) { auto program = pass->getProgramState()->getProgram(); - auto& attributes = program->getActiveAttributes(); + auto& vertexInputs = program->getActiveVertexInputs(); auto meshVertexData = _meshIndexData->getMeshVertexData(); auto attributeCount = meshVertexData->getMeshVertexAttribCount(); - //AXASSERT(attributes.size() <= attributeCount, "missing attribute data"); + //AXASSERT(vertexInputs.size() <= attributeCount, "missing attribute data"); } #endif // TODO - auto vertexAttribBinding = VertexAttribBinding::create(_meshIndexData, pass, &list[i]); - pass->setVertexAttribBinding(vertexAttribBinding); + auto vertexInputBinding = VertexInputBinding::create(_meshIndexData, pass, &list[i]); + pass->setVertexInputBinding(vertexInputBinding); i += 1; } } @@ -450,8 +450,8 @@ void Mesh::draw(Renderer* renderer, AX_SAFE_RELEASE(_instanceTransformBuffer); AX_SAFE_DELETE_ARRAY(_instanceMatrixCache); - _instanceTransformBuffer = backend::DriverBase::getInstance()->newBuffer( - _instanceCount * 64, backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + _instanceTransformBuffer = rhi::DriverBase::getInstance()->createBuffer( + _instanceCount * 64, rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); _instanceMatrixCache = new float[_instanceCount * 16]; for (int i = 0; i < _instanceCount; i++) @@ -537,7 +537,7 @@ void Mesh::draw(Renderer* renderer, command.setWireframe(wireframe); if (_instancing && _instances.size() > 0) { - command.setDrawType(CustomCommand::DrawType::ELEMENT_INSTANCE); + command.setDrawType(CustomCommand::DrawType::ELEMENT_INSTANCED); command.setInstanceBuffer(_instanceTransformBuffer, static_cast(_instances.size())); } else if (_instancing) @@ -572,7 +572,7 @@ void Mesh::setMeshIndexData(MeshIndexData* subMesh) } } -void Mesh::setProgramState(backend::ProgramState* programState) +void Mesh::setProgramState(rhi::ProgramState* programState) { auto material = Material::createWithProgramState(programState); if (_material) @@ -582,7 +582,7 @@ void Mesh::setProgramState(backend::ProgramState* programState) setMaterial(material); } -backend::ProgramState* Mesh::getProgramState() const +rhi::ProgramState* Mesh::getProgramState() const { return _material ? _material->_currentTechnique->_passes.at(0)->getProgramState() : nullptr; } @@ -633,7 +633,7 @@ void Mesh::bindMeshCommand() auto& stateBlock = _material->getStateBlock(); stateBlock.setCullFace(true); stateBlock.setDepthTest(true); - if (_blend.src != backend::BlendFactor::ONE && _blend.dst != backend::BlendFactor::ONE) + if (_blend.src != rhi::BlendFactor::ONE && _blend.dst != rhi::BlendFactor::ONE) stateBlock.setBlend(true); } } @@ -674,7 +674,7 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne auto dirLight = static_cast(light); Vec3 dir = dirLight->getDirectionInWorld(); dir.normalize(); - const Color3B& col = dirLight->getDisplayedColor(); + const Color32& col = dirLight->getDisplayedColor(); _dirLightUniformColorValues[enabledDirLightNum].set( col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity); _dirLightUniformDirValues[enabledDirLightNum] = dir; @@ -688,7 +688,7 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne { auto pointLight = static_cast(light); Mat4 mat = pointLight->getNodeToWorldTransform(); - const Color3B& col = pointLight->getDisplayedColor(); + const Color32& col = pointLight->getDisplayedColor(); _pointLightUniformColorValues[enabledPointLightNum].set( col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity); _pointLightUniformPositionValues[enabledPointLightNum].set(mat.m[12], mat.m[13], mat.m[14]); @@ -705,7 +705,7 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne Vec3 dir = spotLight->getDirectionInWorld(); dir.normalize(); Mat4 mat = light->getNodeToWorldTransform(); - const Color3B& col = spotLight->getDisplayedColor(); + const Color32& col = spotLight->getDisplayedColor(); _spotLightUniformColorValues[enabledSpotLightNum].set( col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity); _spotLightUniformPositionValues[enabledSpotLightNum].set(mat.m[12], mat.m[13], mat.m[14]); @@ -720,7 +720,7 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne case LightType::AMBIENT: { auto ambLight = static_cast(light); - const Color3B& col = ambLight->getDisplayedColor(); + const Color32& col = ambLight->getDisplayedColor(); ambientColor.add(col.r / 255.0f * intensity, col.g / 255.0f * intensity, col.b / 255.0f * intensity); } @@ -787,7 +787,7 @@ void Mesh::setLightUniforms(Pass* pass, Scene* scene, const Vec4& color, unsigne if (useLight) { hasAmbient = true; - const Color3B& col = light->getDisplayedColor(); + const Color32& col = light->getDisplayedColor(); ambient.x += col.r * light->getIntensity(); ambient.y += col.g * light->getIntensity(); ambient.z += col.b * light->getIntensity(); @@ -851,7 +851,7 @@ void Mesh::setIndexFormat(CustomCommand::IndexFormat indexFormat) meshIndexFormat = indexFormat; } -backend::Buffer* Mesh::getIndexBuffer() const +rhi::Buffer* Mesh::getIndexBuffer() const { return _meshIndexData->getIndexBuffer(); } diff --git a/core/3d/Mesh.h b/axmol/3d/Mesh.h similarity index 94% rename from core/3d/Mesh.h rename to axmol/3d/Mesh.h index 58d7f303a396..e914ae16d1b2 100644 --- a/core/3d/Mesh.h +++ b/axmol/3d/Mesh.h @@ -28,15 +28,15 @@ #include #include -#include "3d/Bundle3DData.h" -#include "3d/AABB.h" -#include "3d/3DProgramInfo.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/3d/AABB.h" +#include "axmol/3d/shaderinfos.h" -#include "base/Object.h" -#include "math/Math.h" -#include "renderer/MeshCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/backend/Backend.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/rhi/axmol-rhi.h" namespace ax { @@ -54,7 +54,7 @@ class Renderer; class Scene; class Pass; -namespace backend +namespace rhi { class Buffer; } @@ -80,7 +80,7 @@ class AX_DLL Mesh : public Object static Mesh* create(const std::vector& vertices, int perVertexSizeInFloat, const IndexArray& indices, - const std::vector& attribs); + const axstd::pod_vector& attribs); /** * create mesh @@ -93,7 +93,7 @@ class AX_DLL Mesh : public Object * * @lua NA */ - backend::Buffer* getVertexBuffer() const; + rhi::Buffer* getVertexBuffer() const; /** * has vertex attribute? * @@ -168,7 +168,7 @@ class AX_DLL Mesh : public Object * * @lua NA */ - backend::ProgramState* getProgramState() const; + rhi::ProgramState* getProgramState() const; /**name getter */ std::string_view getName() const { return _name; } @@ -205,7 +205,7 @@ class AX_DLL Mesh : public Object * * @lua NA */ - backend::Buffer* getIndexBuffer() const; + rhi::Buffer* getIndexBuffer() const; /**get AABB*/ const AABB& getAABB() const { return _aabb; } @@ -213,7 +213,7 @@ class AX_DLL Mesh : public Object /** Sets a new ProgramState for the Mesh * A new Material will be created for it */ - void setProgramState(backend::ProgramState* programState); + void setProgramState(rhi::ProgramState* programState); /** Sets a new Material to the Mesh */ void setMaterial(Material* material); @@ -288,7 +288,7 @@ class AX_DLL Mesh : public Object bool _visible; // is the submesh visible bool _instancing; - backend::Buffer* _instanceTransformBuffer; + rhi::Buffer* _instanceTransformBuffer; bool _instanceTransformDirty; bool _instanceTransformBufferDirty; int _instanceCount; diff --git a/core/3d/MeshMaterial.cpp b/axmol/3d/MeshMaterial.cpp similarity index 77% rename from core/3d/MeshMaterial.cpp rename to axmol/3d/MeshMaterial.cpp index 9b3b0f6ecdb1..97afbd8a9800 100644 --- a/core/3d/MeshMaterial.cpp +++ b/axmol/3d/MeshMaterial.cpp @@ -24,16 +24,16 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/MeshMaterial.h" -#include "3d/Mesh.h" -#include "platform/FileUtils.h" -#include "renderer/Texture2D.h" -#include "base/Director.h" -#include "base/EventType.h" -#include "base/Configuration.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/Shaders.h" -#include "renderer/Pass.h" +#include "axmol/3d/MeshMaterial.h" +#include "axmol/3d/Mesh.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Configuration.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/renderer/Pass.h" namespace ax { @@ -57,90 +57,90 @@ MeshMaterial* MeshMaterial::_bumpedDiffuseMaterialSkin = nullptr; MeshMaterial* MeshMaterial::_quadTextureMaterial = nullptr; MeshMaterial* MeshMaterial::_quadColorMaterial = nullptr; -backend::ProgramState* MeshMaterial::_unLitMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_unLitInstanceMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_unLitNoTexMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_vertexLitMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_diffuseMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_diffuseNoTexMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_bumpedDiffuseMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_unLitMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_unLitInstanceMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_unLitNoTexMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_vertexLitMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_diffuseMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_diffuseNoTexMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_bumpedDiffuseMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_unLitMaterialSkinProgState = nullptr; -backend::ProgramState* MeshMaterial::_vertexLitMaterialSkinProgState = nullptr; -backend::ProgramState* MeshMaterial::_diffuseMaterialSkinProgState = nullptr; -backend::ProgramState* MeshMaterial::_bumpedDiffuseMaterialSkinProgState = nullptr; +rhi::ProgramState* MeshMaterial::_unLitMaterialSkinProgState = nullptr; +rhi::ProgramState* MeshMaterial::_vertexLitMaterialSkinProgState = nullptr; +rhi::ProgramState* MeshMaterial::_diffuseMaterialSkinProgState = nullptr; +rhi::ProgramState* MeshMaterial::_bumpedDiffuseMaterialSkinProgState = nullptr; -backend::ProgramState* MeshMaterial::_quadTextureMaterialProgState = nullptr; -backend::ProgramState* MeshMaterial::_quadColorMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_quadTextureMaterialProgState = nullptr; +rhi::ProgramState* MeshMaterial::_quadColorMaterialProgState = nullptr; void MeshMaterial::createBuiltInMaterial() { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::SKINPOSITION_TEXTURE_3D); - _unLitMaterialSkinProgState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::SKINPOSITION_TEXTURE_3D); + _unLitMaterialSkinProgState = new rhi::ProgramState(program); _unLitMaterialSkin = new MeshMaterial(); if (_unLitMaterialSkin && _unLitMaterialSkin->initWithProgramState(_unLitMaterialSkinProgState)) { _unLitMaterialSkin->_type = MeshMaterial::MaterialType::UNLIT; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::SKINPOSITION_NORMAL_TEXTURE_3D); - _diffuseMaterialSkinProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::SKINPOSITION_NORMAL_TEXTURE_3D); + _diffuseMaterialSkinProgState = new rhi::ProgramState(program); _diffuseMaterialSkin = new MeshMaterial(); if (_diffuseMaterialSkin && _diffuseMaterialSkin->initWithProgramState(_diffuseMaterialSkinProgState)) { _diffuseMaterialSkin->_type = MeshMaterial::MaterialType::DIFFUSE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_NORMAL_TEXTURE_3D); - _diffuseMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_NORMAL_TEXTURE_3D); + _diffuseMaterialProgState = new rhi::ProgramState(program); _diffuseMaterial = new MeshMaterial(); if (_diffuseMaterial && _diffuseMaterial->initWithProgramState(_diffuseMaterialProgState)) { _diffuseMaterial->_type = MeshMaterial::MaterialType::DIFFUSE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_3D); - _unLitMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::UNLIT); + _unLitMaterialProgState = new rhi::ProgramState(program); _unLitMaterial = new MeshMaterial(); if (_unLitMaterial && _unLitMaterial->initWithProgramState(_unLitMaterialProgState)) { _unLitMaterial->_type = MeshMaterial::MaterialType::UNLIT; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_3D_INSTANCE); - _unLitInstanceMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::UNLIT_INSTANCE); + _unLitInstanceMaterialProgState = new rhi::ProgramState(program); _unLitInstanceMaterial = new MeshMaterial(); if (_unLitInstanceMaterial && _unLitInstanceMaterial->initWithProgramState(_unLitInstanceMaterialProgState)) { _unLitInstanceMaterial->_type = MeshMaterial::MaterialType::UNLIT_INSTANCE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_3D); - _unLitNoTexMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_3D); + _unLitNoTexMaterialProgState = new rhi::ProgramState(program); _unLitNoTexMaterial = new MeshMaterial(); if (_unLitNoTexMaterial && _unLitNoTexMaterial->initWithProgramState(_unLitNoTexMaterialProgState)) { _unLitNoTexMaterial->_type = MeshMaterial::MaterialType::UNLIT_NOTEX; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_NORMAL_3D); - _diffuseNoTexMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_NORMAL_3D); + _diffuseNoTexMaterialProgState = new rhi::ProgramState(program); _diffuseNoTexMaterial = new MeshMaterial(); if (_diffuseNoTexMaterial && _diffuseNoTexMaterial->initWithProgramState(_diffuseNoTexMaterialProgState)) { _diffuseNoTexMaterial->_type = MeshMaterial::MaterialType::DIFFUSE_NOTEX; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_BUMPEDNORMAL_TEXTURE_3D); - _bumpedDiffuseMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_BUMPEDNORMAL_TEXTURE_3D); + _bumpedDiffuseMaterialProgState = new rhi::ProgramState(program); _bumpedDiffuseMaterial = new MeshMaterial(); if (_bumpedDiffuseMaterial && _bumpedDiffuseMaterial->initWithProgramState(_bumpedDiffuseMaterialProgState)) { _bumpedDiffuseMaterial->_type = MeshMaterial::MaterialType::BUMPED_DIFFUSE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D); - _bumpedDiffuseMaterialSkinProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D); + _bumpedDiffuseMaterialSkinProgState = new rhi::ProgramState(program); _bumpedDiffuseMaterialSkin = new MeshMaterial(); if (_bumpedDiffuseMaterialSkin && _bumpedDiffuseMaterialSkin->initWithProgramState(_bumpedDiffuseMaterialSkinProgState)) @@ -148,16 +148,16 @@ void MeshMaterial::createBuiltInMaterial() _bumpedDiffuseMaterialSkin->_type = MeshMaterial::MaterialType::BUMPED_DIFFUSE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::QUAD_TEXTURE_2D); - _quadTextureMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::QUAD_TEXTURE_2D); + _quadTextureMaterialProgState = new rhi::ProgramState(program); _quadTextureMaterial = new MeshMaterial(); if (_quadTextureMaterial && _quadTextureMaterial->initWithProgramState(_quadTextureMaterialProgState)) { _quadTextureMaterial->_type = MeshMaterial::MaterialType::QUAD_TEXTURE; } - program = backend::Program::getBuiltinProgram(backend::ProgramType::QUAD_COLOR_2D); - _quadColorMaterialProgState = new backend::ProgramState(program); + program = axpm->getBuiltinProgram(rhi::ProgramType::QUAD_COLOR_2D); + _quadColorMaterialProgState = new rhi::ProgramState(program); _quadColorMaterial = new MeshMaterial(); if (_quadColorMaterial && _quadColorMaterial->initWithProgramState(_quadColorMaterialProgState)) { @@ -305,7 +305,7 @@ MeshMaterial* MeshMaterial::createWithFilename(std::string_view path) return nullptr; } -MeshMaterial* MeshMaterial::createWithProgramState(backend::ProgramState* programState) +MeshMaterial* MeshMaterial::createWithProgramState(rhi::ProgramState* programState) { AXASSERT(programState, "Invalid program state."); diff --git a/core/3d/MeshMaterial.h b/axmol/3d/MeshMaterial.h similarity index 83% rename from core/3d/MeshMaterial.h rename to axmol/3d/MeshMaterial.h index cf4aba92e7dd..ce2072131707 100644 --- a/core/3d/MeshMaterial.h +++ b/axmol/3d/MeshMaterial.h @@ -27,10 +27,9 @@ #include #include -#include "base/Types.h" -#include "renderer/Material.h" -#include "3d/Bundle3DData.h" -#include "renderer/backend/Types.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/Material.h" +#include "axmol/3d/Bundle3DData.h" namespace ax { @@ -42,7 +41,7 @@ namespace ax class Texture2D; -namespace backend +namespace rhi { class ProgramState; } @@ -111,7 +110,7 @@ class AX_DLL MeshMaterial : public Material * @param programState GLProgramState instance * @return An autorelease material object */ - static MeshMaterial* createWithProgramState(backend::ProgramState* programState); + static MeshMaterial* createWithProgramState(rhi::ProgramState* programState); void setTexture(Texture2D* tex, NTextureData::Usage usage); @@ -133,7 +132,7 @@ class AX_DLL MeshMaterial : public Material /** * Clone this material. */ - virtual Material* clone() const override; + Material* clone() const override; protected: MaterialType _type; @@ -154,21 +153,21 @@ class AX_DLL MeshMaterial : public Material static MeshMaterial* _quadTextureMaterial; static MeshMaterial* _quadColorMaterial; - static backend::ProgramState* _unLitMaterialProgState; - static backend::ProgramState* _unLitInstanceMaterialProgState; - static backend::ProgramState* _unLitNoTexMaterialProgState; - static backend::ProgramState* _vertexLitMaterialProgState; - static backend::ProgramState* _diffuseMaterialProgState; - static backend::ProgramState* _diffuseNoTexMaterialProgState; - static backend::ProgramState* _bumpedDiffuseMaterialProgState; - - static backend::ProgramState* _unLitMaterialSkinProgState; - static backend::ProgramState* _vertexLitMaterialSkinProgState; - static backend::ProgramState* _diffuseMaterialSkinProgState; - static backend::ProgramState* _bumpedDiffuseMaterialSkinProgState; - - static backend::ProgramState* _quadTextureMaterialProgState; - static backend::ProgramState* _quadColorMaterialProgState; + static rhi::ProgramState* _unLitMaterialProgState; + static rhi::ProgramState* _unLitInstanceMaterialProgState; + static rhi::ProgramState* _unLitNoTexMaterialProgState; + static rhi::ProgramState* _vertexLitMaterialProgState; + static rhi::ProgramState* _diffuseMaterialProgState; + static rhi::ProgramState* _diffuseNoTexMaterialProgState; + static rhi::ProgramState* _bumpedDiffuseMaterialProgState; + + static rhi::ProgramState* _unLitMaterialSkinProgState; + static rhi::ProgramState* _vertexLitMaterialSkinProgState; + static rhi::ProgramState* _diffuseMaterialSkinProgState; + static rhi::ProgramState* _bumpedDiffuseMaterialSkinProgState; + + static rhi::ProgramState* _quadTextureMaterialProgState; + static rhi::ProgramState* _quadColorMaterialProgState; }; /** diff --git a/core/3d/MeshRenderer.cpp b/axmol/3d/MeshRenderer.cpp similarity index 95% rename from core/3d/MeshRenderer.cpp rename to axmol/3d/MeshRenderer.cpp index badafaf50c4e..bb76ee8bfd88 100644 --- a/core/3d/MeshRenderer.cpp +++ b/axmol/3d/MeshRenderer.cpp @@ -24,27 +24,27 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/MeshRenderer.h" -#include "3d/ObjLoader.h" -#include "3d/MeshSkin.h" -#include "3d/Bundle3D.h" -#include "3d/MeshMaterial.h" -#include "3d/AttachNode.h" -#include "3d/Mesh.h" - -#include "base/Director.h" -#include "base/UTF8.h" -#include "base/Utils.h" -#include "2d/Light.h" -#include "2d/Camera.h" -#include "base/Macros.h" -#include "platform/PlatformMacros.h" -#include "platform/FileUtils.h" -#include "renderer/TextureCache.h" -#include "renderer/Renderer.h" -#include "renderer/Material.h" -#include "renderer/Technique.h" -#include "renderer/Pass.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/ObjLoader.h" +#include "axmol/3d/MeshSkin.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/3d/MeshMaterial.h" +#include "axmol/3d/AttachNode.h" +#include "axmol/3d/Mesh.h" + +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/Light.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Pass.h" namespace ax { @@ -402,9 +402,7 @@ MeshRenderer* MeshRenderer::createMeshRendererNode(NodeData* nodedata, auto tex = mesh->getTexture(); if (tex) { - Texture2D::TexParams texParams; - texParams.minFilter = backend::SamplerFilter::LINEAR; - texParams.magFilter = backend::SamplerFilter::LINEAR; + Texture2D::TexParams texParams{}; texParams.sAddressMode = textureData->wrapS; texParams.tAddressMode = textureData->wrapT; tex->setTexParameters(texParams); @@ -418,9 +416,7 @@ MeshRenderer* MeshRenderer::createMeshRendererNode(NodeData* nodedata, auto tex = setMeshTexture(mesh, textureData->filename, NTextureData::Usage::Normal); if (tex) { - Texture2D::TexParams texParams; - texParams.minFilter = backend::SamplerFilter::LINEAR; - texParams.magFilter = backend::SamplerFilter::LINEAR; + Texture2D::TexParams texParams{}; texParams.sAddressMode = textureData->wrapS; texParams.tAddressMode = textureData->wrapT; tex->setTexParameters(texParams); @@ -569,9 +565,7 @@ void MeshRenderer::createNode(NodeData* nodedata, Node* root, const MaterialData auto tex = mesh->getTexture(); if (tex) { - Texture2D::TexParams texParams; - texParams.minFilter = backend::SamplerFilter::LINEAR; - texParams.magFilter = backend::SamplerFilter::LINEAR; + Texture2D::TexParams texParams{}; texParams.sAddressMode = textureData->wrapS; texParams.tAddressMode = textureData->wrapT; tex->setTexParameters(texParams); @@ -585,9 +579,7 @@ void MeshRenderer::createNode(NodeData* nodedata, Node* root, const MaterialData auto tex = setMeshTexture(mesh, textureData->filename, NTextureData::Usage::Normal); if (tex) { - Texture2D::TexParams texParams; - texParams.minFilter = backend::SamplerFilter::LINEAR; - texParams.magFilter = backend::SamplerFilter::LINEAR; + Texture2D::TexParams texParams{}; texParams.sAddressMode = textureData->wrapS; texParams.tAddressMode = textureData->wrapT; tex->setTexParameters(texParams); @@ -869,7 +861,7 @@ void MeshRenderer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag if (_skeleton) _skeleton->updateBoneMatrix(); - Color4F color(getDisplayedColor()); + Color color(getDisplayedColor()); color.a = getDisplayedOpacity() / 255.0f; // check light and determine the shader used @@ -899,7 +891,7 @@ void MeshRenderer::draw(Renderer* renderer, const Mat4& transform, uint32_t flag } } -bool MeshRenderer::setProgramState(backend::ProgramState* programState, bool ownPS /* = false*/) +bool MeshRenderer::setProgramState(rhi::ProgramState* programState, bool ownPS /* = false*/) { if (Node::setProgramState(programState, ownPS)) { diff --git a/core/3d/MeshRenderer.h b/axmol/3d/MeshRenderer.h similarity index 94% rename from core/3d/MeshRenderer.h rename to axmol/3d/MeshRenderer.h index b33989a5282b..907658ceee8b 100644 --- a/core/3d/MeshRenderer.h +++ b/axmol/3d/MeshRenderer.h @@ -28,16 +28,16 @@ #include -#include "base/Vector.h" -#include "base/Types.h" -#include "base/Protocols.h" -#include "2d/Node.h" -#include "renderer/MeshCommand.h" -#include "3d/Skeleton3D.h" // needs to be included for lua-bindings -#include "3d/AABB.h" -#include "3d/Bundle3DData.h" -#include "3d/MeshVertexIndexData.h" -#include "3d/MeshMaterial.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Types.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/3d/Skeleton3D.h" // needs to be included for lua-bindings +#include "axmol/3d/AABB.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/MeshMaterial.h" namespace ax { @@ -125,12 +125,12 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol void removeAllAttachNode(); // overrides - virtual void setBlendFunc(const BlendFunc& blendFunc) override; - virtual const BlendFunc& getBlendFunc() const override; + void setBlendFunc(const BlendFunc& blendFunc) override; + const BlendFunc& getBlendFunc() const override; // overrides /** Sets ProgramState, attributes should be bound by the user */ - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; /* * Get AABB @@ -156,7 +156,7 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol * * @return a pointer to Action */ - virtual Action* runAction(Action* action) override; + Action* runAction(Action* action) override; /** * Force depth buffer writing, this is useful if you want to achieve effects like fading. @@ -168,7 +168,7 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol * Returns a 2d bounding-box * Note: the bounding-box is taken from the mesh's AABB with Z-axis ignored. */ - virtual Rect getBoundingBox() const override; + Rect getBoundingBox() const override; // set face culling side, CullFaceSide::BACK, CullFaceSide::FRONT and CullFaceSide::NONE. virtual void setCullFace(CullFaceSide side); @@ -186,7 +186,7 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol bool isWireframe() const { return _wireframe; } /** render all meshes within this mesh renderer */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** Adds a new material to this mesh renderer. The Material will be applied to all the meshes that belong to the mesh renderer. @@ -213,7 +213,7 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol MeshRenderer(); virtual ~MeshRenderer(); - virtual bool init() override; + bool init() override; bool initWithFile(std::string_view path); @@ -231,7 +231,7 @@ class AX_DLL MeshRenderer : public Node, public BlendProtocol * Note: all children will be rendered in 3D space with depth, this behaviour can be changed using * setForce2DQueue() */ - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** generate default material. */ void genMaterial(bool useLight = false); @@ -352,7 +352,7 @@ class AX_DLL MeshRendererCache struct MeshRenderData { Vector meshVertexDatas; - Vector programStates; + Vector programStates; NodeDatas* nodedatas; MaterialDatas* materialdatas; ~MeshRenderData() diff --git a/core/3d/MeshSkin.cpp b/axmol/3d/MeshSkin.cpp similarity index 97% rename from core/3d/MeshSkin.cpp rename to axmol/3d/MeshSkin.cpp index 32ab607d7fed..fdf1f38788bf 100644 --- a/core/3d/MeshSkin.cpp +++ b/axmol/3d/MeshSkin.cpp @@ -23,9 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/MeshSkin.h" -#include "3d/Bundle3D.h" -#include "3d/Skeleton3D.h" +#include "axmol/3d/MeshSkin.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/3d/Skeleton3D.h" namespace ax { diff --git a/core/3d/MeshSkin.h b/axmol/3d/MeshSkin.h similarity index 96% rename from core/3d/MeshSkin.h rename to axmol/3d/MeshSkin.h index 5f7c148efbce..a4ed7b3c0160 100644 --- a/core/3d/MeshSkin.h +++ b/axmol/3d/MeshSkin.h @@ -25,10 +25,10 @@ #pragma once -#include "3d/Bundle3DData.h" -#include "base/Object.h" -#include "base/Vector.h" -#include "math/Math.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/math/Math.h" #include namespace ax diff --git a/core/3d/MeshVertexIndexData.cpp b/axmol/3d/MeshVertexIndexData.cpp similarity index 86% rename from core/3d/MeshVertexIndexData.cpp rename to axmol/3d/MeshVertexIndexData.cpp index 4ec11c9b19b0..3fd42233f4bf 100644 --- a/core/3d/MeshVertexIndexData.cpp +++ b/axmol/3d/MeshVertexIndexData.cpp @@ -28,21 +28,21 @@ #include #include -#include "3d/MeshVertexIndexData.h" -#include "3d/ObjLoader.h" -#include "3d/MeshMaterial.h" -#include "3d/Mesh.h" -#include "3d/Bundle3D.h" - -#include "base/Macros.h" -#include "base/EventCustom.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "base/Director.h" - -#include "renderer/backend/Buffer.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/ObjLoader.h" +#include "axmol/3d/MeshMaterial.h" +#include "axmol/3d/Mesh.h" +#include "axmol/3d/Bundle3D.h" + +#include "axmol/base/Macros.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Director.h" + +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/DriverBase.h" using namespace std; @@ -52,7 +52,7 @@ namespace ax ///////////////////////////////////////////////////////////////////////////////////////////////////////////// MeshIndexData* MeshIndexData::create(std::string_view id, MeshVertexData* vertexData, - backend::Buffer* indexbuffer, + rhi::Buffer* indexbuffer, const AABB& aabb) { auto meshindex = new MeshIndexData(); @@ -67,7 +67,7 @@ MeshIndexData* MeshIndexData::create(std::string_view id, return meshindex; } -backend::Buffer* MeshIndexData::getVertexBuffer() const +rhi::Buffer* MeshIndexData::getVertexBuffer() const { return _vertexData->getVertexBuffer(); } @@ -112,8 +112,8 @@ void MeshVertexData::setVertexData(const std::vector& vertexData) MeshVertexData* MeshVertexData::create(const MeshData& meshdata, CustomCommand::IndexFormat format) { auto vertexdata = new MeshVertexData(); - vertexdata->_vertexBuffer = backend::DriverBase::getInstance()->newBuffer( - meshdata.vertex.size() * sizeof(meshdata.vertex[0]), backend::BufferType::VERTEX, backend::BufferUsage::STATIC); + vertexdata->_vertexBuffer = rhi::DriverBase::getInstance()->createBuffer( + meshdata.vertex.size() * sizeof(meshdata.vertex[0]), rhi::BufferType::VERTEX, rhi::BufferUsage::STATIC); // AX_SAFE_RETAIN(vertexdata->_vertexBuffer); vertexdata->_sizePerVertex = meshdata.getPerVertexSize(); @@ -134,8 +134,8 @@ MeshVertexData* MeshVertexData::create(const MeshData& meshdata, CustomCommand:: for (size_t i = 0, size = meshdata.subMeshIndices.size(); i < size; ++i) { auto& indices = meshdata.subMeshIndices[i]; - auto indexBuffer = backend::DriverBase::getInstance()->newBuffer( - indices.bsize(), backend::BufferType::INDEX, backend::BufferUsage::STATIC); + auto indexBuffer = rhi::DriverBase::getInstance()->createBuffer( + indices.bsize(), rhi::BufferType::INDEX, rhi::BufferUsage::STATIC); indexBuffer->autorelease(); #if AX_ENABLE_CACHE_TEXTURE_DATA indexBuffer->usingDefaultStoredData(false); diff --git a/core/3d/MeshVertexIndexData.h b/axmol/3d/MeshVertexIndexData.h similarity index 87% rename from core/3d/MeshVertexIndexData.h rename to axmol/3d/MeshVertexIndexData.h index c59530dbe469..3645094bac60 100644 --- a/core/3d/MeshVertexIndexData.h +++ b/axmol/3d/MeshVertexIndexData.h @@ -27,14 +27,14 @@ #include #include -#include "3d/Bundle3DData.h" -#include "3d/AABB.h" -#include "3d/3DProgramInfo.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/3d/AABB.h" +#include "axmol/3d/shaderinfos.h" -#include "base/Object.h" -#include "base/Vector.h" -#include "math/Math.h" -#include "renderer/MeshCommand.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/math/Math.h" +#include "axmol/renderer/MeshCommand.h" namespace ax { @@ -57,14 +57,14 @@ class AX_DLL MeshIndexData : public Object /** create */ static MeshIndexData* create(std::string_view id, MeshVertexData* vertexData, - backend::Buffer* indexbuffer, + rhi::Buffer* indexbuffer, const AABB& aabb); /**get index buffer*/ - backend::Buffer* getIndexBuffer() const { return _indexBuffer; } + rhi::Buffer* getIndexBuffer() const { return _indexBuffer; } /**get vertex buffer*/ - backend::Buffer* getVertexBuffer() const; + rhi::Buffer* getVertexBuffer() const; /**get vertex data*/ const MeshVertexData* getMeshVertexData() const { return _vertexData; } @@ -87,7 +87,7 @@ class AX_DLL MeshIndexData : public Object virtual ~MeshIndexData(); protected: - backend::Buffer* _indexBuffer = nullptr; // index buffer + rhi::Buffer* _indexBuffer = nullptr; // index buffer MeshVertexData* _vertexData = nullptr; // vertex buffer, weak ref AABB _aabb; // original aabb of the submesh std::string _id; // id @@ -115,7 +115,7 @@ class AX_DLL MeshVertexData : public Object static MeshVertexData* create(const MeshData& meshdata, CustomCommand::IndexFormat format = CustomCommand::IndexFormat::U_SHORT); /** get vertexbuffer */ - backend::Buffer* getVertexBuffer() const { return _vertexBuffer; } + rhi::Buffer* getVertexBuffer() const { return _vertexBuffer; } /** get attributes count */ ssize_t getMeshVertexAttribCount() const { return _attribs.size(); } @@ -142,10 +142,10 @@ class AX_DLL MeshVertexData : public Object virtual ~MeshVertexData(); protected: - backend::Buffer* _vertexBuffer = nullptr; // vertex buffer + rhi::Buffer* _vertexBuffer = nullptr; // vertex buffer ssize_t _sizePerVertex = -1; Vector _indices; // index data - std::vector _attribs; // vertex attributes + axstd::pod_vector _attribs; // vertex attributes int _vertexCount = 0; // vertex count std::vector _vertexData; diff --git a/core/3d/MotionStreak3D.cpp b/axmol/3d/MotionStreak3D.cpp similarity index 80% rename from core/3d/MotionStreak3D.cpp rename to axmol/3d/MotionStreak3D.cpp index 5e79a8e2cfe8..dfed96309401 100644 --- a/core/3d/MotionStreak3D.cpp +++ b/axmol/3d/MotionStreak3D.cpp @@ -3,6 +3,7 @@ Copyright (c) 2011 ForzeField Studios S.L. Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -24,17 +25,17 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "3d/MotionStreak3D.h" +#include "axmol/3d/MotionStreak3D.h" #include // offsetof -#include "base/Types.h" -#include "math/Vertex.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "renderer/TextureCache.h" -#include "renderer/Texture2D.h" -#include "renderer/Renderer.h" -#include "renderer/RenderState.h" -#include "renderer/Shaders.h" +#include "axmol/base/Types.h" +#include "axmol/math/Vertex.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/Shaders.h" namespace ax { @@ -61,7 +62,7 @@ MotionStreak3D::~MotionStreak3D() MotionStreak3D* MotionStreak3D::create(float fade, float minSeg, float stroke, - const Color3B& color, + const Color32& color, std::string_view path) { MotionStreak3D* ret = new MotionStreak3D(); @@ -75,7 +76,7 @@ MotionStreak3D* MotionStreak3D::create(float fade, return nullptr; } -MotionStreak3D* MotionStreak3D::create(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture) +MotionStreak3D* MotionStreak3D::create(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture) { MotionStreak3D* ret = new MotionStreak3D(); if (ret && ret->initWithFade(fade, minSeg, stroke, color, texture)) @@ -88,7 +89,7 @@ MotionStreak3D* MotionStreak3D::create(float fade, float minSeg, float stroke, c return nullptr; } -bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path) +bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const Color32& color, std::string_view path) { AXASSERT(!path.empty(), "Invalid filename"); @@ -96,7 +97,7 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const return initWithFade(fade, minSeg, stroke, color, texture); } -bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture) +bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture) { Node::setPosition(Vec2::ZERO); setAnchorPoint(Vec2::ZERO); @@ -116,7 +117,7 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const _pointState.resize(_maxPoints); _pointVertexes.resize(_maxPoints); - _vertexData.resize(_maxPoints * 2); + _vertices.resize(_maxPoints * 2); // Set blend mode _blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; @@ -124,7 +125,7 @@ bool MotionStreak3D::initWithFade(float fade, float minSeg, float stroke, const // shader state this->setProgramStateByProgramId(ProgramType::POSITION_TEXTURE_COLOR); - _customCommand.getPipelineDescriptor().programState = _programState; + _customCommand.getPipelineDesc().programState = _programState; initCustomCommand(); @@ -140,9 +141,9 @@ void MotionStreak3D::initCustomCommand() _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE_STRIP); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + auto& pipelineDesc = _customCommand.getPipelineDesc(); - auto& blend = pipelineDescriptor.blendDescriptor; + auto& blend = pipelineDesc.blendDesc; blend.blendEnabled = true; blend.sourceAlphaBlendFactor = blend.sourceRGBBlendFactor = _blendFunc.src; blend.destinationAlphaBlendFactor = blend.destinationRGBBlendFactor = _blendFunc.dst; @@ -150,7 +151,7 @@ void MotionStreak3D::initCustomCommand() _locMVP = _programState->getUniformLocation("u_MVPMatrix"); _locTexture = _programState->getUniformLocation("u_tex0"); - _customCommand.createVertexBuffer(sizeof(VertexData), _vertexData.size(), CustomCommand::BufferUsage::DYNAMIC); + _customCommand.createVertexBuffer(sizeof(_vertices[0]), _vertices.size(), CustomCommand::BufferUsage::DYNAMIC); } void MotionStreak3D::setPosition(const Vec2& position) @@ -231,15 +232,14 @@ void MotionStreak3D::setPositionY(float y) _positionR.y = y; } -void MotionStreak3D::tintWithColor(const Color3B& colors) +void MotionStreak3D::tintWithColor(const Color32& color) { - setColor(colors); + setColor(color); // Fast assignation for (unsigned int i = 0; i < _nuPoints * 2; i++) { - auto& color = _vertexData[i].color; - color.set(colors.r, colors.g, colors.b, color.a); + _vertices[i].color = color; } } @@ -250,6 +250,9 @@ Texture2D* MotionStreak3D::getTexture() const void MotionStreak3D::setTexture(Texture2D* texture) { + if (texture == nullptr) + texture = _director->getTextureCache()->getWhiteTexture(); + if (_texture != texture) { AX_SAFE_RETAIN(texture); @@ -318,22 +321,22 @@ void MotionStreak3D::update(float delta) // Move point _pointVertexes[newIdx] = _pointVertexes[i]; - // Move vertices + // Move pos i2 = i * 2; newIdx2 = newIdx * 2; - _vertexData[newIdx2].pos = _vertexData[i2].pos; - _vertexData[newIdx2 + 1].pos = _vertexData[i2 + 1].pos; + _vertices[newIdx2].position = _vertices[i2].position; + _vertices[newIdx2 + 1].position = _vertices[i2 + 1].position; // Move color - _vertexData[newIdx2].color = _vertexData[i2].color; - _vertexData[newIdx2 + 1].color = _vertexData[i2 + 1].color; + _vertices[newIdx2].color = _vertices[i2].color; + _vertices[newIdx2 + 1].color = _vertices[i2 + 1].color; } else newIdx2 = newIdx * 2; - const uint8_t op = (uint8_t)(_pointState[newIdx] * 255.0f); - _vertexData[newIdx2].color.a = op; - _vertexData[newIdx2 + 1].color.a = op; + const uint8_t alpha = (uint8_t)(_pointState[newIdx] * 255.0f); + _vertices[newIdx2].color.a = alpha; + _vertices[newIdx2 + 1].color.a = alpha; } } _nuPoints -= mov; @@ -362,14 +365,16 @@ void MotionStreak3D::update(float delta) _pointState[_nuPoints] = 1.0f; // Color assignment - _vertexData[_nuPoints * 2].color = Color4B(_displayedColor, 255); - _vertexData[_nuPoints * 2 + 1].color = Color4B(_displayedColor, 255); + auto tmpColor = _displayedColor; + tmpColor.a = 255; + _vertices[_nuPoints * 2].color = tmpColor; + _vertices[_nuPoints * 2 + 1].color = tmpColor; // Generate polygon { - float stroke = _stroke * 0.5f; - _vertexData[_nuPoints * 2].pos = _pointVertexes[_nuPoints] + (_sweepAxis * stroke); - _vertexData[_nuPoints * 2 + 1].pos = _pointVertexes[_nuPoints] - (_sweepAxis * stroke); + float stroke = _stroke * 0.5f; + _vertices[_nuPoints * 2].position = _pointVertexes[_nuPoints] + (_sweepAxis * stroke); + _vertices[_nuPoints * 2 + 1].position = _pointVertexes[_nuPoints] - (_sweepAxis * stroke); } _nuPoints++; @@ -381,8 +386,8 @@ void MotionStreak3D::update(float delta) float texDelta = 1.0f / _nuPoints; for (i = 0; i < _nuPoints; i++) { - _vertexData[i * 2].texPos = Tex2F(0, texDelta * i); - _vertexData[i * 2 + 1].texPos = Tex2F(1, texDelta * i); + _vertices[i * 2].texCoord = Tex2F(0, texDelta * i); + _vertices[i * 2 + 1].texCoord = Tex2F(1, texDelta * i); } _previousNuPoints = _nuPoints; @@ -413,7 +418,7 @@ void MotionStreak3D::draw(Renderer* renderer, const Mat4& transform, uint32_t fl beforeCommand->func = AX_CALLBACK_0(MotionStreak3D::onBeforeDraw, this); afterCommand->func = AX_CALLBACK_0(MotionStreak3D::onAfterDraw, this); - _customCommand.updateVertexBuffer(_vertexData.data(), sizeof(_vertexData[0]) * _nuPoints * 2); + _customCommand.updateVertexBuffer(_vertices.data(), sizeof(_vertices[0]) * _nuPoints * 2); _customCommand.setVertexDrawInfo(0, _nuPoints * 2); diff --git a/core/3d/MotionStreak3D.h b/axmol/3d/MotionStreak3D.h similarity index 73% rename from core/3d/MotionStreak3D.h rename to axmol/3d/MotionStreak3D.h index 7a68db292bea..670f49c907e8 100644 --- a/core/3d/MotionStreak3D.h +++ b/axmol/3d/MotionStreak3D.h @@ -1,6 +1,7 @@ /**************************************************************************** Copyright (c) 2015-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -24,10 +25,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Protocols.h" -#include "2d/Node.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" #include @@ -57,7 +58,7 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol * @param path The texture file name of stoke. * @return An autoreleased MotionStreak3D object. */ - static MotionStreak3D* create(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path); + static MotionStreak3D* create(float fade, float minSeg, float stroke, const Color32& color, std::string_view path); /** Creates and initializes a motion streak with fade in seconds, minimum segments, stroke's width, color, texture. * * @param fade The fade time, in seconds. @@ -67,13 +68,13 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol * @param texture The texture name of stoke. * @return An autoreleased MotionStreak3D object. */ - static MotionStreak3D* create(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture); + static MotionStreak3D* create(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture); /** Color used for the tint. * * @param colors The color used for the tint. */ - void tintWithColor(const Color3B& colors); + void tintWithColor(const Color32& colors); /** Remove all living segments of the ribbon. */ @@ -105,41 +106,41 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol } // Overrides - virtual void setPosition(const Vec2& position) override; - virtual void setPosition(float x, float y) override; - virtual void setPosition3D(const Vec3& position) override; - virtual void setRotation3D(const Vec3& rotation) override; - virtual void setRotationQuat(const Quaternion& quat) override; - - virtual const Vec2& getPosition() const override; - virtual void getPosition(float* x, float* y) const override; - virtual void setPositionX(float x) override; - virtual void setPositionY(float y) override; - virtual float getPositionX() const override; - virtual float getPositionY() const override; - virtual Vec3 getPosition3D() const override; + void setPosition(const Vec2& position) override; + void setPosition(float x, float y) override; + void setPosition3D(const Vec3& position) override; + void setRotation3D(const Vec3& rotation) override; + void setRotationQuat(const Quaternion& quat) override; + + const Vec2& getPosition() const override; + void getPosition(float* x, float* y) const override; + void setPositionX(float x) override; + void setPositionY(float y) override; + float getPositionX() const override; + float getPositionY() const override; + Vec3 getPosition3D() const override; /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * @lua NA */ - virtual void update(float delta) override; - virtual Texture2D* getTexture() const override; - virtual void setTexture(Texture2D* texture) override; + void update(float delta) override; + Texture2D* getTexture() const override; + void setTexture(Texture2D* texture) override; /** * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; - virtual uint8_t getOpacity() const override; - virtual void setOpacity(uint8_t opacity) override; - virtual void setOpacityModifyRGB(bool value) override; - virtual bool isOpacityModifyRGB() const override; + const BlendFunc& getBlendFunc() const override; + uint8_t getOpacity() const override; + void setOpacity(uint8_t opacity) override; + void setOpacityModifyRGB(bool value) override; + bool isOpacityModifyRGB() const override; /** * Set the direction of sweeping line segment. @@ -157,23 +158,16 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol /** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture filename */ - bool initWithFade(float fade, float minSeg, float stroke, const Color3B& color, std::string_view path); + bool initWithFade(float fade, float minSeg, float stroke, const Color32& color, std::string_view path); /** initializes a motion streak with fade in seconds, minimum segments, stroke's width, color and texture */ - bool initWithFade(float fade, float minSeg, float stroke, const Color3B& color, Texture2D* texture); + bool initWithFade(float fade, float minSeg, float stroke, const Color32& color, Texture2D* texture); protected: // renderer callback void initCustomCommand(); - struct VertexData - { - Vec3 pos; - Color4B color; - Tex2F texPos; - }; - bool _startingPositionInitialized; /** texture used for the motion streak */ @@ -195,7 +189,7 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol std::vector _pointVertexes; std::vector _pointState; - std::vector _vertexData; + std::vector _vertices; CustomCommand _customCommand; @@ -204,13 +198,13 @@ class AX_DLL MotionStreak3D : public Node, public TextureProtocol //CallbackCommand _beforeCommand; //CallbackCommand _afterCommand; - backend::UniformLocation _locMVP; - backend::UniformLocation _locTexture; + rhi::UniformLocation _locMVP; + rhi::UniformLocation _locTexture; void onBeforeDraw(); void onAfterDraw(); - backend::CullMode _rendererCullface; + rhi::CullMode _rendererCullface; bool _rendererDepthTest; }; diff --git a/core/3d/OBB.cpp b/axmol/3d/OBB.cpp similarity index 99% rename from core/3d/OBB.cpp rename to axmol/3d/OBB.cpp index 8183ef5ed38e..47da44b900cc 100644 --- a/core/3d/OBB.cpp +++ b/axmol/3d/OBB.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/OBB.h" +#include "axmol/3d/OBB.h" namespace ax { diff --git a/core/3d/OBB.h b/axmol/3d/OBB.h similarity index 99% rename from core/3d/OBB.h rename to axmol/3d/OBB.h index f62278d44a3b..575f6c412841 100644 --- a/core/3d/OBB.h +++ b/axmol/3d/OBB.h @@ -25,7 +25,7 @@ #pragma once -#include "3d/AABB.h" +#include "axmol/3d/AABB.h" namespace ax { diff --git a/core/3d/ObjLoader.cpp b/axmol/3d/ObjLoader.cpp similarity index 99% rename from core/3d/ObjLoader.cpp rename to axmol/3d/ObjLoader.cpp index 471b522499b4..0a5b930d92e0 100644 --- a/core/3d/ObjLoader.cpp +++ b/axmol/3d/ObjLoader.cpp @@ -33,10 +33,10 @@ #include #include #include -#include "platform/FileUtils.h" -#include "base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Utils.h" -#include "3d/ObjLoader.h" +#include "axmol/3d/ObjLoader.h" namespace tinyobj { diff --git a/core/3d/ObjLoader.h b/axmol/3d/ObjLoader.h similarity index 99% rename from core/3d/ObjLoader.h rename to axmol/3d/ObjLoader.h index e07c5ec10cf9..29456ee6e6d3 100644 --- a/core/3d/ObjLoader.h +++ b/axmol/3d/ObjLoader.h @@ -27,7 +27,7 @@ #include #include #include -#include "base/hlookup.h" +#include "axmol/base/hlookup.h" namespace tinyobj { diff --git a/core/3d/Plane.cpp b/axmol/3d/Plane.cpp similarity index 98% rename from core/3d/Plane.cpp rename to axmol/3d/Plane.cpp index 36a12a76fa3d..262f1e462802 100644 --- a/core/3d/Plane.cpp +++ b/axmol/3d/Plane.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Plane.h" +#include "axmol/3d/Plane.h" namespace ax { diff --git a/core/3d/Plane.h b/axmol/3d/Plane.h similarity index 97% rename from core/3d/Plane.h rename to axmol/3d/Plane.h index 22983f839459..f1bf96402052 100644 --- a/core/3d/Plane.h +++ b/axmol/3d/Plane.h @@ -25,8 +25,8 @@ #pragma once -#include "base/Macros.h" -#include "math/Math.h" +#include "axmol/base/Macros.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/core/3d/Ray.cpp b/axmol/3d/Ray.cpp similarity index 99% rename from core/3d/Ray.cpp rename to axmol/3d/Ray.cpp index 591f24838ee9..0dc2b4420852 100644 --- a/core/3d/Ray.cpp +++ b/axmol/3d/Ray.cpp @@ -21,7 +21,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "3d/Ray.h" +#include "axmol/3d/Ray.h" namespace ax { diff --git a/core/3d/Ray.h b/axmol/3d/Ray.h similarity index 96% rename from core/3d/Ray.h rename to axmol/3d/Ray.h index ac5709b0f1d0..d5309e2dda42 100644 --- a/core/3d/Ray.h +++ b/axmol/3d/Ray.h @@ -25,10 +25,10 @@ #pragma once -#include "math/Math.h" -#include "3d/AABB.h" -#include "3d/OBB.h" -#include "3d/Plane.h" +#include "axmol/math/Math.h" +#include "axmol/3d/AABB.h" +#include "axmol/3d/OBB.h" +#include "axmol/3d/Plane.h" namespace ax { diff --git a/core/3d/Skeleton3D.cpp b/axmol/3d/Skeleton3D.cpp similarity index 99% rename from core/3d/Skeleton3D.cpp rename to axmol/3d/Skeleton3D.cpp index 2d143c9c87c6..98fd881e24b8 100644 --- a/core/3d/Skeleton3D.cpp +++ b/axmol/3d/Skeleton3D.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "3d/Skeleton3D.h" +#include "axmol/3d/Skeleton3D.h" namespace ax { diff --git a/core/3d/Skeleton3D.h b/axmol/3d/Skeleton3D.h similarity index 98% rename from core/3d/Skeleton3D.h rename to axmol/3d/Skeleton3D.h index 9030e56999dd..bc1e4a378fe0 100644 --- a/core/3d/Skeleton3D.h +++ b/axmol/3d/Skeleton3D.h @@ -25,9 +25,9 @@ #pragma once -#include "3d/Bundle3DData.h" -#include "base/Object.h" -#include "base/Vector.h" +#include "axmol/3d/Bundle3DData.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" namespace ax { diff --git a/core/3d/Skybox.cpp b/axmol/3d/Skybox.cpp similarity index 88% rename from core/3d/Skybox.cpp rename to axmol/3d/Skybox.cpp index bc155b41c7d4..03a156049842 100644 --- a/core/3d/Skybox.cpp +++ b/axmol/3d/Skybox.cpp @@ -22,15 +22,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "3d/Skybox.h" -#include "base/Macros.h" -#include "base/Configuration.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "renderer/RenderState.h" -#include "renderer/TextureCube.h" -#include "renderer/Shaders.h" -#include "2d/Camera.h" +#include "axmol/3d/Skybox.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/TextureCube.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -65,13 +65,13 @@ bool Skybox::init() _customCommand.setAfterCallback(AX_CALLBACK_0(Skybox::onAfterDraw, this)); // create and set our custom shader - setProgramStateByProgramId(backend::ProgramType::SKYBOX_3D); + setProgramStateByProgramId(rhi::ProgramType::SKYBOX_3D); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + auto& pipelineDesc = _customCommand.getPipelineDesc(); - pipelineDescriptor.programState = _programState; + pipelineDesc.programState = _programState; // disable blend - pipelineDescriptor.blendDescriptor.blendEnabled = false; + pipelineDesc.blendDesc.blendEnabled = false; _uniformColorLoc = _programState->getUniformLocation("u_color"); _uniformCameraRotLoc = _programState->getUniformLocation("u_cameraRot"); @@ -149,7 +149,8 @@ void Skybox::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) // prescale the matrix to account for the camera fov cameraModelMat.scale(1 / projectionMat.m[0], 1 / projectionMat.m[5], 1.0); - Vec4 color(_displayedColor.r / 255.f, _displayedColor.g / 255.f, _displayedColor.b / 255.f, 1.f); + Color color(_displayedColor); + color.a = 1.0f; // FIXME: should we ignore opacity for compatibile with previous versions _programState->setUniform(_uniformColorLoc, &color, sizeof(color)); _programState->setUniform(_uniformCameraRotLoc, cameraModelMat.m, sizeof(cameraModelMat.m)); @@ -175,11 +176,11 @@ void Skybox::onBeforeDraw() auto* renderer = _director->getRenderer(); _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); renderer->setDepthTest(true); - renderer->setDepthCompareFunction(backend::CompareFunction::LESS_EQUAL); + renderer->setDepthCompareFunc(rhi::CompareFunc::LESS_EQUAL); renderer->setCullMode(CullMode::BACK); } @@ -187,7 +188,7 @@ void Skybox::onAfterDraw() { auto* renderer = _director->getRenderer(); renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); } diff --git a/core/3d/Skybox.h b/axmol/3d/Skybox.h similarity index 86% rename from core/3d/Skybox.h rename to axmol/3d/Skybox.h index 85e0b5cb6b97..80d90ebf7920 100644 --- a/core/3d/Skybox.h +++ b/axmol/3d/Skybox.h @@ -25,11 +25,11 @@ #pragma once -#include "base/Types.h" -#include "platform/PlatformMacros.h" -#include "renderer/CustomCommand.h" -#include "2d/Node.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Types.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/2d/Node.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -69,7 +69,7 @@ class AX_DLL Skybox : public Node void setTexture(TextureCube*); /** draw Skybox object */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** reload sky box after GLESContext reconstructed.*/ void reload(); @@ -87,7 +87,7 @@ class AX_DLL Skybox : public Node /** * init Skybox. */ - virtual bool init() override; + bool init() override; /** * initialize with texture path @@ -111,16 +111,16 @@ class AX_DLL Skybox : public Node private: AX_DISALLOW_COPY_AND_ASSIGN(Skybox); - backend::UniformLocation _uniformColorLoc; - backend::UniformLocation _uniformCameraRotLoc; - backend::UniformLocation _uniformEnvLoc; + rhi::UniformLocation _uniformColorLoc; + rhi::UniformLocation _uniformCameraRotLoc; + rhi::UniformLocation _uniformEnvLoc; void onBeforeDraw(); void onAfterDraw(); bool _rendererDepthTestEnabled; - backend::CompareFunction _rendererDepthCmpFunc; - backend::CullMode _rendererCullMode; + rhi::CompareFunc _rendererDepthCmpFunc; + rhi::CullMode _rendererCullMode; }; // end of 3d group diff --git a/core/3d/Terrain.cpp b/axmol/3d/Terrain.cpp similarity index 95% rename from core/3d/Terrain.cpp rename to axmol/3d/Terrain.cpp index 5cfeef236d16..bf82e1c32532 100644 --- a/core/3d/Terrain.cpp +++ b/axmol/3d/Terrain.cpp @@ -24,26 +24,26 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "3d/Terrain.h" +#include "axmol/3d/Terrain.h" using namespace ax; #include #include #include #include // offsetof -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Program.h" -#include "renderer/backend/Buffer.h" -#include "base/Director.h" -#include "base/Types.h" -#include "base/axstd.h" -#include "base/EventType.h" -#include "2d/Camera.h" -#include "platform/Image.h" -#include "3d/3DProgramInfo.h" -#include "base/Utils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/base/Director.h" +#include "axmol/base/Types.h" +#include "axmol/base/axstd.h" +#include "axmol/base/EventType.h" +#include "axmol/2d/Camera.h" +#include "axmol/platform/Image.h" +#include "axmol/3d/shaderinfos.h" +#include "axmol/base/Utils.h" namespace ax { @@ -94,10 +94,9 @@ void ax::Terrain::setLightMap(std::string_view fileName) _lightMap = new Texture2D(); _lightMap->initWithImage(image); - Texture2D::TexParams tRepeatParams; // set texture parameters - tRepeatParams.magFilter = tRepeatParams.minFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.sAddressMode = backend::SamplerAddressMode::REPEAT; - tRepeatParams.tAddressMode = backend::SamplerAddressMode::REPEAT; + Texture2D::TexParams tRepeatParams{}; + tRepeatParams.sAddressMode = rhi::SamplerAddressMode::REPEAT; + tRepeatParams.tAddressMode = rhi::SamplerAddressMode::REPEAT; _lightMap->setTexParameters(tRepeatParams); } @@ -112,7 +111,7 @@ bool Terrain::initProperties() _stateBlock.depthWrite = true; _stateBlock.depthTest = true; - _stateBlock.cullFace = backend::CullMode::FRONT; + _stateBlock.cullFace = rhi::CullMode::FRONT; setDrawWire(false); setIsEnableFrustumCull(true); @@ -164,7 +163,7 @@ void Terrain::draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t f { int hasLightMap = 0; _programState->setUniform(_lightMapCheckLocation, &hasLightMap, sizeof(hasLightMap)); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D _programState->setTexture(_lightMapLocation, 5, _dummyTexture->getBackendTexture()); #endif } @@ -266,7 +265,7 @@ Terrain::Terrain() EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { reload(); }); _director->getEventDispatcher()->addEventListenerWithFixedPriority(_backToForegroundListener, 1); #endif -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D auto image = new Image(); bool AX_UNUSED isOK = image->initWithRawData(ax_2x2_white_image, sizeof(ax_2x2_white_image), 2, 2, 8); AXASSERT(isOK, "The 2x2 empty texture was created unsuccessfully."); @@ -365,13 +364,13 @@ float Terrain::getImageHeight(int pixel_x, int pixel_y) const int byte_stride = 1; switch (_heightMapImage->getPixelFormat()) { - case backend::PixelFormat::BGRA8: + case rhi::PixelFormat::BGRA8: byte_stride = 4; break; - case backend::PixelFormat::RGB8: + case rhi::PixelFormat::RGB8: byte_stride = 3; break; - case backend::PixelFormat::R8: + case rhi::PixelFormat::R8: byte_stride = 1; break; default: @@ -736,8 +735,8 @@ Terrain::ChunkIndices Terrain::insertIndicesLOD(int neighborLod[4], int selfLod, lodIndices._relativeLod[4] = selfLod; lodIndices._chunkIndices._size = size; - auto buffer = backend::DriverBase::getInstance()->newBuffer(sizeof(uint16_t) * size, backend::BufferType::INDEX, - backend::BufferUsage::STATIC); + auto buffer = rhi::DriverBase::getInstance()->createBuffer(sizeof(uint16_t) * size, rhi::BufferType::INDEX, + rhi::BufferUsage::STATIC); buffer->updateData(indices, sizeof(uint16_t) * size); AX_SAFE_RELEASE_NULL(lodIndices._chunkIndices._indexBuffer); @@ -774,8 +773,8 @@ Terrain::ChunkIndices Terrain::insertIndicesLODSkirt(int selfLod, uint16_t* indi skirtIndices._selfLod = selfLod; skirtIndices._chunkIndices._size = size; - auto buffer = backend::DriverBase::getInstance()->newBuffer(sizeof(uint16_t) * size, backend::BufferType::INDEX, - backend::BufferUsage::STATIC); + auto buffer = rhi::DriverBase::getInstance()->createBuffer(sizeof(uint16_t) * size, rhi::BufferType::INDEX, + rhi::BufferUsage::STATIC); buffer->updateData(indices, sizeof(uint16_t) * size); AX_SAFE_RELEASE_NULL(skirtIndices._chunkIndices._indexBuffer); @@ -837,19 +836,18 @@ bool Terrain::initTextures() _detailMapTextures[i] = nullptr; } - Texture2D::TexParams texParam; - texParam.sAddressMode = backend::SamplerAddressMode::REPEAT; - texParam.tAddressMode = backend::SamplerAddressMode::REPEAT; + Texture2D::TexParams texParam{}; + if (_terrainData._alphaMapSrc.empty()) { + texParam.sAddressMode = rhi::SamplerAddressMode::REPEAT; + texParam.tAddressMode = rhi::SamplerAddressMode::REPEAT; auto textImage = new Image(); textImage->initWithImageFile(_terrainData._detailMaps[0]._detailMapSrc); auto texture = new Texture2D(); texture->initWithImage(textImage); texture->generateMipmap(); _detailMapTextures[0] = texture; - texParam.minFilter = backend::SamplerFilter::LINEAR; - texParam.magFilter = backend::SamplerFilter::LINEAR; texture->setTexParameters(texParam); delete textImage; } @@ -860,13 +858,13 @@ bool Terrain::initTextures() image->initWithImageFile(_terrainData._alphaMapSrc); _alphaMap = new Texture2D(); _alphaMap->initWithImage(image); - texParam.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - texParam.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - texParam.minFilter = backend::SamplerFilter::LINEAR; - texParam.magFilter = backend::SamplerFilter::LINEAR; + texParam.sAddressMode = rhi::SamplerAddressMode::CLAMP; + texParam.tAddressMode = rhi::SamplerAddressMode::CLAMP; _alphaMap->setTexParameters(texParam); delete image; + texParam.sAddressMode = rhi::SamplerAddressMode::REPEAT; + texParam.tAddressMode = rhi::SamplerAddressMode::REPEAT; for (int i = 0; i < _terrainData._detailMapAmount; ++i) { auto textImage = new Image(); @@ -877,10 +875,6 @@ bool Terrain::initTextures() texture->generateMipmap(); _detailMapTextures[i] = texture; - texParam.sAddressMode = backend::SamplerAddressMode::REPEAT; - texParam.tAddressMode = backend::SamplerAddressMode::REPEAT; - texParam.minFilter = backend::SamplerFilter::LINEAR; - texParam.magFilter = backend::SamplerFilter::LINEAR; texture->setTexParameters(texParam); } } @@ -913,8 +907,8 @@ void Terrain::Chunk::finish() // frequently AX_SAFE_RELEASE_NULL(_buffer); - _buffer = backend::DriverBase::getInstance()->newBuffer(sizeof(TerrainVertexData) * _originalVertices.size(), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + _buffer = rhi::DriverBase::getInstance()->createBuffer(sizeof(TerrainVertexData) * _originalVertices.size(), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); _buffer->updateData(&_originalVertices[0], sizeof(TerrainVertexData) * _originalVertices.size()); @@ -953,9 +947,9 @@ void Terrain::Chunk::bindAndDraw() auto* renderer = Director::getInstance()->getRenderer(); AXASSERT(_buffer && _chunkIndices._indexBuffer, "buffer should not be nullptr"); - _command.setIndexBuffer(_chunkIndices._indexBuffer, backend::IndexFormat::U_SHORT); + _command.setIndexBuffer(_chunkIndices._indexBuffer, rhi::IndexFormat::U_SHORT); _command.setVertexBuffer(_buffer); - _command.getPipelineDescriptor().programState = _terrain->_programState; + _command.getPipelineDesc().programState = _terrain->_programState; _command.setIndexDrawInfo(0, _chunkIndices._size); renderer->addCommand(&_command); AX_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _chunkIndices._size); @@ -1083,8 +1077,8 @@ Terrain::Chunk::Chunk(Terrain* terrain) _command.setBeforeCallback(AX_CALLBACK_0(Terrain::onBeforeDraw, terrain)); _command.setAfterCallback(AX_CALLBACK_0(Terrain::onAfterDraw, terrain)); - auto& pipelineDescriptor = _command.getPipelineDescriptor(); - pipelineDescriptor.blendDescriptor.blendEnabled = false; + auto& pipelineDesc = _command.getPipelineDesc(); + pipelineDesc.blendDesc.blendEnabled = false; } void Terrain::Chunk::updateIndicesLOD() diff --git a/core/3d/Terrain.h b/axmol/3d/Terrain.h similarity index 93% rename from core/3d/Terrain.h rename to axmol/3d/Terrain.h index 0ef0f117ca16..61c240c75a0d 100644 --- a/core/3d/Terrain.h +++ b/axmol/3d/Terrain.h @@ -27,19 +27,18 @@ THE SOFTWARE. #include -#include "2d/Node.h" -#include "2d/Camera.h" -#include "renderer/Texture2D.h" -#include "renderer/MeshCommand.h" -#include "renderer/CallbackCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/RenderState.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/ProgramState.h" -#include "3d/AABB.h" -#include "3d/Ray.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/3d/AABB.h" +#include "axmol/3d/Ray.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" namespace ax { @@ -189,7 +188,7 @@ class AX_DLL Terrain : public Node ChunkIndices(const ChunkIndices&); ChunkIndices& operator=(const ChunkIndices& o); ~ChunkIndices(); - backend::Buffer* _indexBuffer = nullptr; + rhi::Buffer* _indexBuffer = nullptr; unsigned short _size = 0; }; @@ -292,7 +291,7 @@ class AX_DLL Terrain : public Node std::vector _trianglesList; - backend::Buffer* _buffer = nullptr; + rhi::Buffer* _buffer = nullptr; MeshCommand _command; }; @@ -403,7 +402,7 @@ class AX_DLL Terrain : public Node void setDetailMap(unsigned int index, DetailMap detailMap); // Overrides, internal use only - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; /** * Ray-Terrain intersection. * @return the intersection point @@ -492,7 +491,7 @@ class AX_DLL Terrain : public Node void calculateNormal(); // override - virtual void onEnter() override; + void onEnter() override; /** * cache all uniform locations in GLSL. @@ -551,8 +550,8 @@ class AX_DLL Terrain : public Node // bool blend; bool depthWrite = true; bool depthTest = true; - backend::CullMode cullFace = backend::CullMode::FRONT; - backend::Winding winding = backend::Winding::CLOCK_WISE; + rhi::CullMode cullFace = rhi::CullMode::FRONT; + rhi::Winding winding = rhi::Winding::CLOCK_WISE; void apply(); void save(); }; @@ -562,15 +561,15 @@ class AX_DLL Terrain : public Node private: // uniform locations - backend::UniformLocation _detailMapLocation[4]; - backend::UniformLocation _alphaMapLocation; - backend::UniformLocation _alphaIsHasAlphaMapLocation; - backend::UniformLocation _lightMapCheckLocation; - backend::UniformLocation _lightMapLocation; - backend::UniformLocation _detailMapSizeLocation; - backend::UniformLocation _lightDirLocation; - - backend::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _detailMapLocation[4]; + rhi::UniformLocation _alphaMapLocation; + rhi::UniformLocation _alphaIsHasAlphaMapLocation; + rhi::UniformLocation _lightMapCheckLocation; + rhi::UniformLocation _lightMapLocation; + rhi::UniformLocation _detailMapSizeLocation; + rhi::UniformLocation _lightDirLocation; + + rhi::UniformLocation _mvpMatrixLocation; #if AX_ENABLE_CACHE_TEXTURE_DATA EventListenerCustom* _backToForegroundListener; #endif diff --git a/core/3d/VertexAttribBinding.cpp b/axmol/3d/VertexInputBinding.cpp similarity index 59% rename from core/3d/VertexAttribBinding.cpp rename to axmol/3d/VertexInputBinding.cpp index 3f950e45e803..1dfe9fe9f68a 100644 --- a/core/3d/VertexAttribBinding.cpp +++ b/axmol/3d/VertexInputBinding.cpp @@ -21,43 +21,43 @@ This file was modified to fit the cocos2d-x project */ -#include "renderer/backend/Program.h" -#include "renderer/Pass.h" -#include "base/Configuration.h" -#include "3d/MeshVertexIndexData.h" -#include "3d/3DProgramInfo.h" -#include "3d/VertexAttribBinding.h" +#include "axmol/rhi/Program.h" +#include "axmol/renderer/Pass.h" +#include "axmol/base/Configuration.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/shaderinfos.h" +#include "axmol/3d/VertexInputBinding.h" namespace ax { -static std::vector __vertexAttribBindingCache; +static std::vector __vertexInputBindingCache; -VertexAttribBinding::VertexAttribBinding() : _meshIndexData(nullptr), _programState(nullptr) {} +VertexInputBinding::VertexInputBinding() : _meshIndexData(nullptr), _programState(nullptr) {} -VertexAttribBinding::~VertexAttribBinding() +VertexInputBinding::~VertexInputBinding() { // Delete from the vertex attribute binding cache. - std::vector::iterator itr = - std::find(__vertexAttribBindingCache.begin(), __vertexAttribBindingCache.end(), this); - if (itr != __vertexAttribBindingCache.end()) + std::vector::iterator itr = + std::find(__vertexInputBindingCache.begin(), __vertexInputBindingCache.end(), this); + if (itr != __vertexInputBindingCache.end()) { - __vertexAttribBindingCache.erase(itr); + __vertexInputBindingCache.erase(itr); } AX_SAFE_RELEASE(_meshIndexData); AX_SAFE_RELEASE(_programState); } -VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, Pass* pass, MeshCommand* command) +VertexInputBinding* VertexInputBinding::create(MeshIndexData* meshIndexData, Pass* pass, MeshCommand* command) { AXASSERT(meshIndexData && pass && pass->getProgramState(), "Invalid MeshIndexData and/or programState"); // Search for an existing vertex attribute binding that can be used. - VertexAttribBinding* b; - for (size_t i = 0, count = __vertexAttribBindingCache.size(); i < count; ++i) + VertexInputBinding* b; + for (size_t i = 0, count = __vertexInputBindingCache.size(); i < count; ++i) { - b = __vertexAttribBindingCache[i]; + b = __vertexInputBindingCache[i]; AX_ASSERT(b); if (b->_meshIndexData == meshIndexData && b->_programState == pass->getProgramState()) { @@ -66,17 +66,17 @@ VertexAttribBinding* VertexAttribBinding::create(MeshIndexData* meshIndexData, P } } - b = new VertexAttribBinding(); + b = new VertexInputBinding(); if (b->init(meshIndexData, pass, command)) { b->autorelease(); - __vertexAttribBindingCache.emplace_back(b); + __vertexInputBindingCache.emplace_back(b); } return b; } -bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand* command) +bool VertexInputBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand* command) { AXASSERT(meshIndexData && pass && pass->getProgramState(), "Invalid arguments"); @@ -96,7 +96,7 @@ bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCom for (auto k = 0; k < attributeCount; k++) { auto meshattribute = meshVertexData->getMeshVertexAttrib(k); - setVertexAttribPointer(vertexLayout, shaderinfos::getAttributeName(meshattribute.vertexAttrib), + setVertexInputPointer(vertexLayout, shaderinfos::getAttributeName(meshattribute.vertexAttrib), meshattribute.type, false, offset, 1 << k); offset += meshattribute.getAttribSizeBytes(); @@ -109,46 +109,42 @@ bool VertexAttribBinding::init(MeshIndexData* meshIndexData, Pass* pass, MeshCom return true; } -uint32_t VertexAttribBinding::getVertexAttribsFlags() const +uint32_t VertexInputBinding::getVertexAttribsFlags() const { return _vertexAttribsFlags; } -void VertexAttribBinding::parseAttributes() +void VertexInputBinding::parseAttributes() { AXASSERT(_programState, "invalid glprogram"); _vertexAttribsFlags = 0; } -bool VertexAttribBinding::hasAttribute(const shaderinfos::VertexKey& key) const +bool VertexInputBinding::hasAttribute(const shaderinfos::VertexKey& key) const { auto& name = shaderinfos::getAttributeName(key); - auto& attributes = _programState->getProgram()->getActiveAttributes(); - return attributes.find(name) != attributes.end(); + auto& vertexInputs = _programState->getProgram()->getActiveVertexInputs(); + return vertexInputs.find(name) != vertexInputs.end(); } -const backend::AttributeBindInfo* VertexAttribBinding::getVertexAttribValue(std::string_view name) +const rhi::VertexInputDesc* VertexInputBinding::getVertexInputDesc(std::string_view name) { - auto& attributes = _programState->getProgram()->getActiveAttributes(); - const auto itr = attributes.find(name); - if (itr != attributes.end()) - return &itr->second; - return nullptr; + return _programState->getProgram()->getVertexInputDesc(name); } -void VertexAttribBinding::setVertexAttribPointer(VertexLayout* vertexLayout, +void VertexInputBinding::setVertexInputPointer(VertexLayout* vertexLayout, std::string_view name, - backend::VertexFormat type, + rhi::VertexFormat type, bool normalized, int offset, int flag) { - auto v = getVertexAttribValue(name); + auto v = getVertexInputDesc(name); if (v) { // AXLOGD("set attribute '{}' location: {}, offset: {}", name, v->location, offset); - vertexLayout->setAttrib(name, v->location, type, offset, normalized); + vertexLayout->setAttrib(name, v, type, offset, normalized); _vertexAttribsFlags |= flag; } else diff --git a/core/3d/VertexAttribBinding.h b/axmol/3d/VertexInputBinding.h similarity index 71% rename from core/3d/VertexAttribBinding.h rename to axmol/3d/VertexInputBinding.h index ba3c0319d529..dd1f73ac4dba 100644 --- a/core/3d/VertexAttribBinding.h +++ b/axmol/3d/VertexInputBinding.h @@ -25,11 +25,10 @@ #include -#include "base/Object.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Types.h" -#include "renderer/Pass.h" -#include "3d/3DProgramInfo.h" +#include "axmol/base/Object.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/Pass.h" +#include "axmol/3d/shaderinfos.h" namespace ax { @@ -54,31 +53,31 @@ class VertexAttribValue; * and an Effect, however this binding is actually a client-side binding and * should only be used when writing custom code that use client-side vertex * arrays, since it is slower than the server-side VAOs used by OpenGL - * (when creating a VertexAttribBinding between a Mesh and Effect). + * (when creating a VertexInputBinding between a Mesh and Effect). */ -class AX_DLL VertexAttribBinding : public Object +class AX_DLL VertexInputBinding : public Object { public: /** - * Creates a new VertexAttribBinding between the given MeshVertexData and GLProgramState. + * Creates a new VertexInputBinding between the given MeshVertexData and GLProgramState. * - * If a VertexAttribBinding matching the specified MeshVertexData and GLProgramState already - * exists, it will be returned. Otherwise, a new VertexAttribBinding will + * If a VertexInputBinding matching the specified MeshVertexData and GLProgramState already + * exists, it will be returned. Otherwise, a new VertexInputBinding will * be returned. If OpenGL VAOs are enabled, the a new VAO will be created and - * stored in the returned VertexAttribBinding, otherwise a client-side + * stored in the returned VertexInputBinding, otherwise a client-side * array of vertex attribute bindings will be stored. * * @param mesh The mesh. * @param effect The effect. * - * @return A VertexAttribBinding for the requested parameters. + * @return A VertexInputBinding for the requested parameters. */ - static VertexAttribBinding* create(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*); + static VertexInputBinding* create(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*); /** * Binds this vertex array object. */ - // void bind(backend::VertexLayout &layout); + // void bind(rhi::VertexLayout &layout); /** * Unbinds this vertex array object. @@ -96,29 +95,29 @@ class AX_DLL VertexAttribBinding : public Object /** * Constructor. */ - VertexAttribBinding(); + VertexInputBinding(); /** * Destructor. */ - ~VertexAttribBinding(); + ~VertexInputBinding(); /** * Hidden copy assignment operator. */ - VertexAttribBinding& operator=(const VertexAttribBinding&); + VertexInputBinding& operator=(const VertexInputBinding&); bool init(MeshIndexData* meshIndexData, Pass* pass, MeshCommand*); - void setVertexAttribPointer(VertexLayout* vertexLayout, std::string_view name, - backend::VertexFormat type, + void setVertexInputPointer(VertexLayout* vertexLayout, std::string_view name, + rhi::VertexFormat type, bool normalized, int offset, int flag); - const backend::AttributeBindInfo* getVertexAttribValue(std::string_view name); + const rhi::VertexInputDesc* getVertexInputDesc(std::string_view name); void parseAttributes(); MeshIndexData* _meshIndexData; - backend::ProgramState* _programState; + rhi::ProgramState* _programState; uint32_t _vertexAttribsFlags; }; diff --git a/core/3d/3DProgramInfo.cpp b/axmol/3d/shaderinfos.cpp similarity index 70% rename from core/3d/3DProgramInfo.cpp rename to axmol/3d/shaderinfos.cpp index 2c333d293476..db254f7e23f5 100644 --- a/core/3d/3DProgramInfo.cpp +++ b/axmol/3d/shaderinfos.cpp @@ -1,4 +1,4 @@ -#include "3DProgramInfo.h" +#include "axmol/3d/shaderinfos.h" namespace ax { @@ -74,27 +74,27 @@ const char* UNIFORM_NAME_ALPHA_TEST_VALUE = "AX_alpha_value"; namespace attribute { // Attribute names -const char* ATTRIBUTE_NAME_COLOR = "a_color"; -const char* ATTRIBUTE_NAME_POSITION = "a_position"; -const char* ATTRIBUTE_NAME_TEX_COORD = "a_texCoord"; -const char* ATTRIBUTE_NAME_TEX_COORD1 = "a_texCoord1"; -const char* ATTRIBUTE_NAME_TEX_COORD2 = "a_texCoord2"; -const char* ATTRIBUTE_NAME_TEX_COORD3 = "a_texCoord3"; -const char* ATTRIBUTE_NAME_NORMAL = "a_normal"; -const char* ATTRIBUTE_NAME_BLEND_WEIGHT = "a_blendWeight"; -const char* ATTRIBUTE_NAME_BLEND_INDEX = "a_blendIndex"; -const char* ATTRIBUTE_NAME_TANGENT = "a_tangent"; -const char* ATTRIBUTE_NAME_BINORMAL = "a_binormal"; +const char* VERTEX_INPUT_NAME_COLOR = "a_color"; +const char* VERTEX_INPUT_NAME_POSITION = "a_position"; +const char* VERTEX_INPUT_NAME_TEX_COORD = "a_texCoord"; +const char* VERTEX_INPUT_NAME_TEX_COORD1 = "a_texCoord1"; +const char* VERTEX_INPUT_NAME_TEX_COORD2 = "a_texCoord2"; +const char* VERTEX_INPUT_NAME_TEX_COORD3 = "a_texCoord3"; +const char* VERTEX_INPUT_NAME_NORMAL = "a_normal"; +const char* VERTEX_INPUT_NAME_BLEND_WEIGHT = "a_blendWeight"; +const char* VERTEX_INPUT_NAME_BLEND_INDEX = "a_blendIndex"; +const char* VERTEX_INPUT_NAME_TANGENT = "a_tangent"; +const char* VERTEX_INPUT_NAME_BINORMAL = "a_binormal"; } // namespace attribute static std::vector> locations = { - {attribute::ATTRIBUTE_NAME_POSITION, VertexKey::VERTEX_ATTRIB_POSITION}, - {attribute::ATTRIBUTE_NAME_COLOR, VertexKey::VERTEX_ATTRIB_COLOR}, - {attribute::ATTRIBUTE_NAME_TEX_COORD, VertexKey::VERTEX_ATTRIB_TEX_COORD}, - {attribute::ATTRIBUTE_NAME_TEX_COORD1, VertexKey::VERTEX_ATTRIB_TEX_COORD1}, - {attribute::ATTRIBUTE_NAME_TEX_COORD2, VertexKey::VERTEX_ATTRIB_TEX_COORD2}, - {attribute::ATTRIBUTE_NAME_TEX_COORD3, VertexKey::VERTEX_ATTRIB_TEX_COORD3}, - {attribute::ATTRIBUTE_NAME_NORMAL, VertexKey::VERTEX_ATTRIB_NORMAL}, + {attribute::VERTEX_INPUT_NAME_POSITION, VertexKey::VERTEX_ATTRIB_POSITION}, + {attribute::VERTEX_INPUT_NAME_COLOR, VertexKey::VERTEX_ATTRIB_COLOR}, + {attribute::VERTEX_INPUT_NAME_TEX_COORD, VertexKey::VERTEX_ATTRIB_TEX_COORD}, + {attribute::VERTEX_INPUT_NAME_TEX_COORD1, VertexKey::VERTEX_ATTRIB_TEX_COORD1}, + {attribute::VERTEX_INPUT_NAME_TEX_COORD2, VertexKey::VERTEX_ATTRIB_TEX_COORD2}, + {attribute::VERTEX_INPUT_NAME_TEX_COORD3, VertexKey::VERTEX_ATTRIB_TEX_COORD3}, + {attribute::VERTEX_INPUT_NAME_NORMAL, VertexKey::VERTEX_ATTRIB_NORMAL}, }; const std::vector>& getPredefinedAttributes() @@ -102,15 +102,15 @@ const std::vector>& getPredefinedAttributes() return locations; } -const std::string getAttributeName(const VertexKey& key) +const std::string_view getAttributeName(const VertexKey& key) { - static std::string s_attributeNames[] = { - shaderinfos::attribute::ATTRIBUTE_NAME_POSITION, shaderinfos::attribute::ATTRIBUTE_NAME_COLOR, - shaderinfos::attribute::ATTRIBUTE_NAME_TEX_COORD, shaderinfos::attribute::ATTRIBUTE_NAME_TEX_COORD1, - shaderinfos::attribute::ATTRIBUTE_NAME_TEX_COORD2, shaderinfos::attribute::ATTRIBUTE_NAME_TEX_COORD3, - shaderinfos::attribute::ATTRIBUTE_NAME_NORMAL, shaderinfos::attribute::ATTRIBUTE_NAME_BLEND_WEIGHT, - shaderinfos::attribute::ATTRIBUTE_NAME_BLEND_INDEX, shaderinfos::attribute::ATTRIBUTE_NAME_TANGENT, - shaderinfos::attribute::ATTRIBUTE_NAME_BINORMAL}; + static std::string_view s_attributeNames[] = { + shaderinfos::attribute::VERTEX_INPUT_NAME_POSITION, shaderinfos::attribute::VERTEX_INPUT_NAME_COLOR, + shaderinfos::attribute::VERTEX_INPUT_NAME_TEX_COORD, shaderinfos::attribute::VERTEX_INPUT_NAME_TEX_COORD1, + shaderinfos::attribute::VERTEX_INPUT_NAME_TEX_COORD2, shaderinfos::attribute::VERTEX_INPUT_NAME_TEX_COORD3, + shaderinfos::attribute::VERTEX_INPUT_NAME_NORMAL, shaderinfos::attribute::VERTEX_INPUT_NAME_BLEND_WEIGHT, + shaderinfos::attribute::VERTEX_INPUT_NAME_BLEND_INDEX, shaderinfos::attribute::VERTEX_INPUT_NAME_TANGENT, + shaderinfos::attribute::VERTEX_INPUT_NAME_BINORMAL}; static int max = sizeof(s_attributeNames) / sizeof(s_attributeNames[0]); auto idx = static_cast(key); @@ -119,4 +119,4 @@ const std::string getAttributeName(const VertexKey& key) } }; // namespace shaderinfos -} \ No newline at end of file +} diff --git a/core/3d/3DProgramInfo.h b/axmol/3d/shaderinfos.h similarity index 92% rename from core/3d/3DProgramInfo.h rename to axmol/3d/shaderinfos.h index 98322a9c1b4c..4231e5cf72dc 100644 --- a/core/3d/3DProgramInfo.h +++ b/axmol/3d/shaderinfos.h @@ -1,8 +1,8 @@ #pragma once -#include "base/Macros.h" -#include "math/Math.h" +#include "axmol/base/Macros.h" +#include "axmol/math/Math.h" #include #include @@ -78,7 +78,7 @@ enum class Uniformkey UNIFORM_SAMPLER2, UNIFORM_SAMPLER3, /**@}*/ - UNIFORM_MAX, + UNIFORM_COUNT, }; namespace shader @@ -250,25 +250,25 @@ namespace attribute @{ */ /**Attribute color.*/ -extern const char* ATTRIBUTE_NAME_COLOR; +extern const char* VERTEX_INPUT_NAME_COLOR; /**Attribute position.*/ -extern const char* ATTRIBUTE_NAME_POSITION; +extern const char* VERTEX_INPUT_NAME_POSITION; /**@{ Attribute Texcoord 0-3.*/ -extern const char* ATTRIBUTE_NAME_TEX_COORD; -extern const char* ATTRIBUTE_NAME_TEX_COORD1; -extern const char* ATTRIBUTE_NAME_TEX_COORD2; -extern const char* ATTRIBUTE_NAME_TEX_COORD3; +extern const char* VERTEX_INPUT_NAME_TEX_COORD; +extern const char* VERTEX_INPUT_NAME_TEX_COORD1; +extern const char* VERTEX_INPUT_NAME_TEX_COORD2; +extern const char* VERTEX_INPUT_NAME_TEX_COORD3; /**@}*/ /**Attribute normal.*/ -extern const char* ATTRIBUTE_NAME_NORMAL; +extern const char* VERTEX_INPUT_NAME_NORMAL; /**Attribute blend weight.*/ -extern const char* ATTRIBUTE_NAME_BLEND_WEIGHT; +extern const char* VERTEX_INPUT_NAME_BLEND_WEIGHT; /**Attribute blend index.*/ -extern const char* ATTRIBUTE_NAME_BLEND_INDEX; +extern const char* VERTEX_INPUT_NAME_BLEND_INDEX; /**Attribute blend tangent.*/ -extern const char* ATTRIBUTE_NAME_TANGENT; +extern const char* VERTEX_INPUT_NAME_TANGENT; /**Attribute blend binormal.*/ -extern const char* ATTRIBUTE_NAME_BINORMAL; +extern const char* VERTEX_INPUT_NAME_BINORMAL; /** end of Built Attribute names @} @@ -276,7 +276,7 @@ end of Built Attribute names } // namespace attribute const std::vector>& getPredefinedAttributes(); -const std::string getAttributeName(const VertexKey& key); +const std::string_view getAttributeName(const VertexKey& key); }; // namespace shaderinfos -} \ No newline at end of file +} diff --git a/core/CMakeLists.txt b/axmol/CMakeLists.txt similarity index 90% rename from core/CMakeLists.txt rename to axmol/CMakeLists.txt index a3cbaeb69919..eb475e575ed5 100644 --- a/core/CMakeLists.txt +++ b/axmol/CMakeLists.txt @@ -35,7 +35,7 @@ set(_AX_VERSION 2.7) if(NOT DEFINED _AX_CORE_LIB) - set(_AX_CORE_LIB axmol CACHE INTERNAL "The axmol core lib name") + set(_AX_CORE_LIB axmol CACHE INTERNAL "The axmol engine lib name") endif() cmake_policy(SET CMP0127 NEW) @@ -51,26 +51,40 @@ endif() include(CMakeDependentOption) # by default: use angle on win32 -cmake_dependent_option(AX_USE_COMPAT_GL "Whether use compatibility GL as render backend" ${WIN32} "WIN32 OR APPLE" OFF) +cmake_dependent_option(AX_USE_ANGLE "Whether use angle as gles API provider" ${WIN32} "WIN32 OR APPLE" OFF) -# choosing render backend for all target platforms: win32, winuwp, ios, tvos, android, linux, osx -if(APPLE AND(NOT AX_USE_COMPAT_GL)) - set(AX_USE_METAL ON CACHE BOOL "" FORCE) - set(AX_USE_GL OFF CACHE BOOL "" FORCE) -else() # win32, winuwp, android, linux: OpenGL - set(AX_USE_GL ON CACHE BOOL "" FORCE) - set(AX_USE_METAL OFF CACHE BOOL "" FORCE) +# set(AX_RENDER_API_GL 1 CACHE INTERNAL "" FORCE) +# set(AX_RENDER_API_MTL 2 CACHE INTERNAL "" FORCE) +# set(AX_RENDER_API_D3D 3 CACHE INTERNAL "" FORCE) +set(AX_RENDER_API "auto" CACHE STRING "Specify axmol graphics render API") + +if(AX_RENDER_API STREQUAL "auto") + if(APPLE) + set(AX_RENDER_API "mtl" CACHE INTERNAL "" FORCE) + else() + set(AX_RENDER_API "gl" CACHE INTERNAL "" FORCE) + endif() +else() + if(AX_RENDER_API STREQUAL "mtl") + if(NOT APPLE) # non-apple platforms, invalid api specified, fallback to gl + set(AX_RENDER_API "gl" CACHE INTERNAL "" FORCE) + endif() + elseif(AX_RENDER_API STREQUAL "d3d") + if(NOT WIN32) + if(APPLE) + set(AX_RENDER_API "mtl" CACHE INTERNAL "" FORCE) + else() + set(AX_RENDER_API "gl" CACHE INTERNAL "" FORCE) + endif() + endif() + endif() endif() -# macos, linux or (win32, ios, tvos and NOT AX_USE_COMPAT_GL) not use GLES profile +# macos, linux or (win32, ios, tvos) not use GLES profile set(_GLES_PROFILE 0) # _GLES_PROFILE is the default GLES profile -if(ANDROID) # android force use GLES profile - set(_GLES_PROFILE 200) -elseif(WINRT OR WASM) # winuwp/wasm fore use GLES profile - set(_GLES_PROFILE 300) -elseif((NOT MACOSX) AND(NOT LINUX)) # win32, ios, tvos - if(AX_USE_COMPAT_GL) +if(AX_RENDER_API STREQUAL "gl") + if(ANDROID OR WINRT OR WASM OR (WINDOWS AND AX_USE_ANGLE) OR IOS OR TVOS) set(_GLES_PROFILE 300) endif() endif() @@ -78,15 +92,16 @@ endif() if(_GLES_PROFILE) set(AX_GLES_PROFILE ${_GLES_PROFILE} CACHE STRING "") - if(NOT(AX_GLES_PROFILE EQUAL 200 OR AX_GLES_PROFILE EQUAL 300)) - message(FATAL_ERROR "${MACOSX} Invalid GLES profile ${AX_GLES_PROFILE}, must be 200 or 300, default ${_GLES_PROFILE}") + if(AX_GLES_PROFILE LESS 300) + set(AX_GLES_PROFILE ${_GLES_PROFILE} CACHE STRING "" FORCE) + message(AUTHOR_WARNING "Forcing GLES profile to ${_GLES_PROFILE} for OpenGL ES") endif() else() # force disable GLES profile set(AX_GLES_PROFILE 0 CACHE STRING "" FORCE) endif() # print renderer backend profile -message(AUTHOR_WARNING "AX_USE_GL=${AX_USE_GL}, AX_USE_METAL=${AX_USE_METAL}, AX_GLES_PROFILE=${AX_GLES_PROFILE}") +message(AUTHOR_WARNING "AX_RENDER_API=${AX_RENDER_API}, AX_GLES_PROFILE=${AX_GLES_PROFILE}") if(LINUX) include(CheckIncludeFile) @@ -212,6 +227,7 @@ if(AX_ENABLE_NAVMESH) include(navmesh/CMakeLists.txt) endif() +include(rhi/CMakeLists.txt) include(renderer/CMakeLists.txt) include(base/CMakeLists.txt) include(ui/CMakeLists.txt) @@ -235,6 +251,7 @@ set(_AX_HEADER axmol.h ${_AX_2D_HEADER} ${_AX_PLATFORM_HEADER} ${_AX_MATH_HEADER} + ${_AX_RHI_HEADER} ${_AX_RENDERER_HEADER} ${_AX_BASE_HEADER} ${_AX_UI_HEADER} @@ -245,6 +262,7 @@ set(_AX_SRC axmol.cpp ${_AX_2D_SRC} ${_AX_PLATFORM_SRC} ${_AX_MATH_SRC} + ${_AX_RHI_SRC} ${_AX_RENDERER_SRC} ${_AX_BASE_SRC} ${_AX_UI_SRC} @@ -305,7 +323,7 @@ elseif(AX_ENABLE_MFMEDIA AND NOT WINRT) endif() endif() -ax_find_shaders(${_AX_ROOT}/core/renderer/shaders BUILTIN_SHADER_SOURCES) +ax_find_shaders(${_AX_ROOT}/axmol/renderer/shaders BUILTIN_SHADER_SOURCES) set(ax_builtin_shaders ${BUILTIN_SHADER_SOURCES} CACHE STATIC "" FORCE) # configure engine builtin light num @@ -331,17 +349,17 @@ configure_file( # POSITION_BUMPEDNORMAL_TEXTURE_3D: positionNormalTexture.vert, colorNormalTexture.frag, lightNormMapDef # SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D: skinPositionNormalTexture_vert, colorNormalTexture.frag, lightNormMapDef set_source_files_properties( - ${_AX_ROOT}/core/renderer/shaders/colorNormal.frag - ${_AX_ROOT}/core/renderer/shaders/colorNormalTexture.frag - ${_AX_ROOT}/core/renderer/shaders/positionNormalTexture.vert - ${_AX_ROOT}/core/renderer/shaders/skinPositionNormalTexture.vert + ${_AX_ROOT}/axmol/renderer/shaders/colorNormal.frag + ${_AX_ROOT}/axmol/renderer/shaders/colorNormalTexture.frag + ${_AX_ROOT}/axmol/renderer/shaders/positionNormalTexture.vert + ${_AX_ROOT}/axmol/renderer/shaders/skinPositionNormalTexture.vert PROPERTIES AXSLCC_DEFINES "MAX_DIRECTIONAL_LIGHT_NUM=${AX_MAX_DIRECTIONAL_LIGHT},MAX_POINT_LIGHT_NUM=${AX_MAX_POINT_LIGHT},MAX_SPOT_LIGHT_NUM=${AX_MAX_SPOT_LIGHT}" ) set_source_files_properties( - ${_AX_ROOT}/core/renderer/shaders/colorNormalTexture.frag - ${_AX_ROOT}/core/renderer/shaders/positionNormalTexture.vert - ${_AX_ROOT}/core/renderer/shaders/skinPositionNormalTexture.vert + ${_AX_ROOT}/axmol/renderer/shaders/colorNormalTexture.frag + ${_AX_ROOT}/axmol/renderer/shaders/positionNormalTexture.vert + ${_AX_ROOT}/axmol/renderer/shaders/skinPositionNormalTexture.vert PROPERTIES AXSLCC_OUTPUT1 "USE_NORMAL_MAPPING=1" ) ax_target_compile_shaders(${_AX_CORE_LIB} FILES ${BUILTIN_SHADER_SOURCES}) @@ -367,15 +385,6 @@ use_ax_depend(${_AX_CORE_LIB}) target_include_directories(${_AX_CORE_LIB} PUBLIC ${_AX_ROOT} PUBLIC ${_AX_ROOT}/3rdparty - PUBLIC ${_AX_ROOT}/extensions/scripting - PUBLIC ${_AX_ROOT}/core - PUBLIC ${_AX_ROOT}/core/platform - - INTERFACE ${_AX_ROOT}/3rdparty - INTERFACE ${_AX_ROOT}/extensions/scripting - INTERFACE ${_AX_ROOT}/core/base - INTERFACE ${_AX_ROOT}/core/audio - INTERFACE ${_AX_ROOT}/core/platform/${PLATFORM_NAME} ) set_target_properties(${_AX_CORE_LIB} @@ -393,7 +402,7 @@ endif() message(STATUS "CMake precompile headers for ${_AX_CORE_LIB}") target_precompile_headers(${_AX_CORE_LIB} PRIVATE - "$<$:axmol.h>" + "$<$:axmol/axmol.h>" ) if(WINDOWS) @@ -610,7 +619,7 @@ if(MSVC) endif() if(ANDROID) - add_subdirectory(${_AX_ROOT}/core/platform/android ${ENGINE_BINARY_PATH}/core/cpp-android) + add_subdirectory(${_AX_ROOT}/axmol/platform/android ${ENGINE_BINARY_PATH}/axmol/cpp-android) if(BUILD_SHARED_LIBS) # whole archive for jni diff --git a/core/audio/AudioCache.cpp b/axmol/audio/AudioCache.cpp similarity index 98% rename from core/audio/AudioCache.cpp rename to axmol/audio/AudioCache.cpp index 435666056590..9f00517d85b7 100644 --- a/core/audio/AudioCache.cpp +++ b/axmol/audio/AudioCache.cpp @@ -24,15 +24,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" -#include "audio/AudioCache.h" +#include "axmol/audio/AudioCache.h" #include -#include "base/Director.h" -#include "base/Scheduler.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" -#include "audio/AudioDecoderManager.h" -#include "audio/AudioDecoder.h" +#include "axmol/audio/AudioDecoderManager.h" +#include "axmol/audio/AudioDecoder.h" namespace { diff --git a/core/audio/AudioCache.h b/axmol/audio/AudioCache.h similarity index 95% rename from core/audio/AudioCache.h rename to axmol/audio/AudioCache.h index 19ebb37574d5..e040bf2fb227 100644 --- a/core/audio/AudioCache.h +++ b/axmol/audio/AudioCache.h @@ -26,16 +26,16 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include #include #include #include -#include "platform/PlatformMacros.h" -#include "audio/AudioMacros.h" -#include "audio/alconfig.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/audio/alconfig.h" namespace ax { diff --git a/core/audio/AudioDecoder.cpp b/axmol/audio/AudioDecoder.cpp similarity index 96% rename from core/audio/AudioDecoder.cpp rename to axmol/audio/AudioDecoder.cpp index 8ce0036407fb..226fbfcac523 100644 --- a/core/audio/AudioDecoder.cpp +++ b/axmol/audio/AudioDecoder.cpp @@ -24,9 +24,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "audio/AudioDecoder.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" +#include "axmol/audio/AudioDecoder.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/core/audio/AudioDecoder.h b/axmol/audio/AudioDecoder.h similarity index 99% rename from core/audio/AudioDecoder.h rename to axmol/audio/AudioDecoder.h index 91441f6c4293..807437a61144 100644 --- a/core/audio/AudioDecoder.h +++ b/axmol/audio/AudioDecoder.h @@ -28,7 +28,7 @@ #include #include -#include "platform/IFileStream.h" +#include "axmol/platform/IFileStream.h" namespace ax { diff --git a/core/audio/AudioDecoderEXT.h b/axmol/audio/AudioDecoderEXT.h similarity index 98% rename from core/audio/AudioDecoderEXT.h rename to axmol/audio/AudioDecoderEXT.h index 9491af65dec3..b1025b416efe 100644 --- a/core/audio/AudioDecoderEXT.h +++ b/axmol/audio/AudioDecoderEXT.h @@ -28,8 +28,8 @@ #include #import -#include "audio/AudioDecoder.h" -#include "platform/IFileStream.h" +#include "axmol/audio/AudioDecoder.h" +#include "axmol/platform/IFileStream.h" namespace ax { diff --git a/core/audio/AudioDecoderEXT.mm b/axmol/audio/AudioDecoderEXT.mm similarity index 98% rename from core/audio/AudioDecoderEXT.mm rename to axmol/audio/AudioDecoderEXT.mm index 22ea783fc003..fa1474e4bcb3 100644 --- a/core/audio/AudioDecoderEXT.mm +++ b/axmol/audio/AudioDecoderEXT.mm @@ -24,9 +24,9 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "audio/AudioDecoderEXT.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" +#include "axmol/audio/AudioDecoderEXT.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" #import diff --git a/core/audio/AudioDecoderManager.cpp b/axmol/audio/AudioDecoderManager.cpp similarity index 90% rename from core/audio/AudioDecoderManager.cpp rename to axmol/audio/AudioDecoderManager.cpp index 80ca61553f3c..46c384493a82 100644 --- a/core/audio/AudioDecoderManager.cpp +++ b/axmol/audio/AudioDecoderManager.cpp @@ -24,18 +24,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "audio/AudioDecoderManager.h" -#include "audio/AudioDecoderVorbis.h" -#include "audio/AudioDecoderOpus.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" -#include "base/Logging.h" +#include "axmol/audio/AudioDecoderManager.h" +#include "axmol/audio/AudioDecoderVorbis.h" +#include "axmol/audio/AudioDecoderOpus.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Logging.h" #if !defined(__APPLE__) -# include "audio/AudioDecoderMp3.h" -# include "audio/AudioDecoderWav.h" +# include "axmol/audio/AudioDecoderMp3.h" +# include "axmol/audio/AudioDecoderWav.h" #else -# include "audio/AudioDecoderEXT.h" +# include "axmol/audio/AudioDecoderEXT.h" #endif #include "yasio/string_view.hpp" diff --git a/core/audio/AudioDecoderManager.h b/axmol/audio/AudioDecoderManager.h similarity index 97% rename from core/audio/AudioDecoderManager.h rename to axmol/audio/AudioDecoderManager.h index 6c38967458c3..25f54e8972a7 100644 --- a/core/audio/AudioDecoderManager.h +++ b/axmol/audio/AudioDecoderManager.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/audio/AudioDecoderMp3.cpp b/axmol/audio/AudioDecoderMp3.cpp similarity index 98% rename from core/audio/AudioDecoderMp3.cpp rename to axmol/audio/AudioDecoderMp3.cpp index 8786656d60ae..dec4aa2f86ea 100644 --- a/core/audio/AudioDecoderMp3.cpp +++ b/axmol/audio/AudioDecoderMp3.cpp @@ -24,11 +24,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "audio/AudioDecoderMp3.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" +#include "axmol/audio/AudioDecoderMp3.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" -#include "base/Logging.h" +#include "axmol/base/Logging.h" #if !AX_USE_MPG123 # define MINIMP3_IMPLEMENTATION diff --git a/core/audio/AudioDecoderMp3.h b/axmol/audio/AudioDecoderMp3.h similarity index 98% rename from core/audio/AudioDecoderMp3.h rename to axmol/audio/AudioDecoderMp3.h index 3c607edc4ed4..71da29d12d5f 100644 --- a/core/audio/AudioDecoderMp3.h +++ b/axmol/audio/AudioDecoderMp3.h @@ -26,7 +26,7 @@ #pragma once -#include "audio/AudioDecoder.h" +#include "axmol/audio/AudioDecoder.h" #include #if !defined(AX_USE_MPG123) diff --git a/core/audio/AudioDecoderOpus.cpp b/axmol/audio/AudioDecoderOpus.cpp similarity index 96% rename from core/audio/AudioDecoderOpus.cpp rename to axmol/audio/AudioDecoderOpus.cpp index ae4b92b131db..af57a97337c2 100644 --- a/core/audio/AudioDecoderOpus.cpp +++ b/axmol/audio/AudioDecoderOpus.cpp @@ -30,9 +30,9 @@ #if defined(AX_ENABLE_OPUS) -# include "audio/AudioDecoderOpus.h" -# include "audio/AudioMacros.h" -# include "platform/FileUtils.h" +# include "axmol/audio/AudioDecoderOpus.h" +# include "axmol/audio/AudioMacros.h" +# include "axmol/platform/FileUtils.h" # include "opus/opusfile.h" diff --git a/core/audio/AudioDecoderOpus.h b/axmol/audio/AudioDecoderOpus.h similarity index 98% rename from core/audio/AudioDecoderOpus.h rename to axmol/audio/AudioDecoderOpus.h index 75ff1eb2f821..d2c4c5cf5b2b 100644 --- a/core/audio/AudioDecoderOpus.h +++ b/axmol/audio/AudioDecoderOpus.h @@ -25,7 +25,7 @@ #pragma once #if defined(AX_ENABLE_OPUS) -# include "audio/AudioDecoder.h" +# include "axmol/audio/AudioDecoder.h" # include diff --git a/core/audio/AudioDecoderVorbis.cpp b/axmol/audio/AudioDecoderVorbis.cpp similarity index 96% rename from core/audio/AudioDecoderVorbis.cpp rename to axmol/audio/AudioDecoderVorbis.cpp index c6bf20a2669b..e0f6424bdf5e 100644 --- a/core/audio/AudioDecoderVorbis.cpp +++ b/axmol/audio/AudioDecoderVorbis.cpp @@ -24,9 +24,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "audio/AudioDecoderVorbis.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" +#include "axmol/audio/AudioDecoderVorbis.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID # include diff --git a/core/audio/AudioDecoderVorbis.h b/axmol/audio/AudioDecoderVorbis.h similarity index 98% rename from core/audio/AudioDecoderVorbis.h rename to axmol/audio/AudioDecoderVorbis.h index 5fe7b2c14cc2..293f3865b552 100644 --- a/core/audio/AudioDecoderVorbis.h +++ b/axmol/audio/AudioDecoderVorbis.h @@ -26,7 +26,7 @@ #pragma once -#include "audio/AudioDecoder.h" +#include "axmol/audio/AudioDecoder.h" #include "vorbis/vorbisfile.h" #include diff --git a/core/audio/AudioDecoderWav.cpp b/axmol/audio/AudioDecoderWav.cpp similarity index 97% rename from core/audio/AudioDecoderWav.cpp rename to axmol/audio/AudioDecoderWav.cpp index 83852d99c699..9a85d867f705 100644 --- a/core/audio/AudioDecoderWav.cpp +++ b/axmol/audio/AudioDecoderWav.cpp @@ -25,9 +25,9 @@ #include #include -#include "audio/AudioDecoderWav.h" -#include "audio/AudioMacros.h" -#include "platform/FileUtils.h" +#include "axmol/audio/AudioDecoderWav.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/FileUtils.h" namespace ax { @@ -184,7 +184,7 @@ static int wav_close(WAV_FILE* wavf) AudioDecoderWav::AudioDecoderWav() { - memset(&_wavf, 0, offsetof(WAV_FILE, Stream)); + memset((void*)&_wavf, 0, offsetof(WAV_FILE, Stream)); } AudioDecoderWav::~AudioDecoderWav() diff --git a/core/audio/AudioDecoderWav.h b/axmol/audio/AudioDecoderWav.h similarity index 99% rename from core/audio/AudioDecoderWav.h rename to axmol/audio/AudioDecoderWav.h index fcb20ffeee3d..aba176c5b3d4 100644 --- a/core/audio/AudioDecoderWav.h +++ b/axmol/audio/AudioDecoderWav.h @@ -24,7 +24,7 @@ #pragma once -#include "audio/AudioDecoder.h" +#include "axmol/audio/AudioDecoder.h" #include #if !defined(MAKE_FOURCC) diff --git a/core/audio/AudioEngine.cpp b/axmol/audio/AudioEngine.cpp similarity index 98% rename from core/audio/AudioEngine.cpp rename to axmol/audio/AudioEngine.cpp index 156e12d89347..e002de13070a 100644 --- a/core/audio/AudioEngine.cpp +++ b/axmol/audio/AudioEngine.cpp @@ -24,15 +24,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" -#include "audio/AudioEngine.h" +#include "axmol/audio/AudioEngine.h" #include #include -#include "platform/FileUtils.h" -#include "base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Utils.h" -#include "audio/AudioEngineImpl.h" +#include "axmol/audio/AudioEngineImpl.h" #define TIME_DELAY_PRECISION 0.0001 diff --git a/core/audio/AudioEngine.h b/axmol/audio/AudioEngine.h similarity index 98% rename from core/audio/AudioEngine.h rename to axmol/audio/AudioEngine.h index 0e23acc05f0f..1597362e15b9 100644 --- a/core/audio/AudioEngine.h +++ b/axmol/audio/AudioEngine.h @@ -26,9 +26,9 @@ #pragma once -#include "platform/PlatformConfig.h" -#include "platform/PlatformMacros.h" -#include "audio/AudioMacros.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/audio/AudioMacros.h" #include #include #include diff --git a/core/audio/AudioEngineImpl.cpp b/axmol/audio/AudioEngineImpl.cpp similarity index 99% rename from core/audio/AudioEngineImpl.cpp rename to axmol/audio/AudioEngineImpl.cpp index 962b291108ff..b345857a15b8 100644 --- a/core/audio/AudioEngineImpl.cpp +++ b/axmol/audio/AudioEngineImpl.cpp @@ -23,20 +23,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" -#include "audio/AudioEngineImpl.h" -#include "audio/AudioDecoderManager.h" +#include "axmol/audio/AudioEngineImpl.h" +#include "axmol/audio/AudioDecoderManager.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC # import #endif -#include "audio/AudioEngine.h" -#include "platform/FileUtils.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include "base/Utils.h" +#include "axmol/audio/AudioEngine.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Utils.h" #if AX_USE_ALSOFT # include "alc/inprogext.h" diff --git a/core/audio/AudioEngineImpl.h b/axmol/audio/AudioEngineImpl.h similarity index 94% rename from core/audio/AudioEngineImpl.h rename to axmol/audio/AudioEngineImpl.h index 3da8ed90e0f5..b2bf0071ed0b 100644 --- a/core/audio/AudioEngineImpl.h +++ b/axmol/audio/AudioEngineImpl.h @@ -27,15 +27,15 @@ #ifndef __AUDIO_ENGINE_IMPL_H_ # define __AUDIO_ENGINE_IMPL_H_ -# include "platform/PlatformConfig.h" +# include "axmol/platform/PlatformConfig.h" # include # include -# include "base/Object.h" -# include "audio/AudioMacros.h" -# include "audio/AudioCache.h" -# include "audio/AudioPlayer.h" +# include "axmol/base/Object.h" +# include "axmol/audio/AudioMacros.h" +# include "axmol/audio/AudioCache.h" +# include "axmol/audio/AudioPlayer.h" namespace ax { diff --git a/core/audio/AudioMacros.h b/axmol/audio/AudioMacros.h similarity index 98% rename from core/audio/AudioMacros.h rename to axmol/audio/AudioMacros.h index 3950d12ede7a..b54a3ba33ad6 100644 --- a/core/audio/AudioMacros.h +++ b/axmol/audio/AudioMacros.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Logging.h" +#include "axmol/base/Logging.h" #include diff --git a/core/audio/AudioPlayer.cpp b/axmol/audio/AudioPlayer.cpp similarity index 98% rename from core/audio/AudioPlayer.cpp rename to axmol/audio/AudioPlayer.cpp index 33fec68cdaed..2a3f2531d5a5 100644 --- a/core/audio/AudioPlayer.cpp +++ b/axmol/audio/AudioPlayer.cpp @@ -24,12 +24,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" -#include "audio/AudioPlayer.h" -#include "audio/AudioCache.h" -#include "platform/FileUtils.h" -#include "audio/AudioDecoder.h" -#include "audio/AudioDecoderManager.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/audio/AudioPlayer.h" +#include "axmol/audio/AudioCache.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/audio/AudioDecoder.h" +#include "axmol/audio/AudioDecoderManager.h" #include "yasio/thread_name.hpp" diff --git a/core/audio/AudioPlayer.h b/axmol/audio/AudioPlayer.h similarity index 94% rename from core/audio/AudioPlayer.h rename to axmol/audio/AudioPlayer.h index 27d15be5ff9e..b669191aa429 100644 --- a/core/audio/AudioPlayer.h +++ b/axmol/audio/AudioPlayer.h @@ -26,7 +26,7 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include #include @@ -34,9 +34,9 @@ #include #include -#include "audio/AudioMacros.h" -#include "platform/PlatformMacros.h" -#include "audio/alconfig.h" +#include "axmol/audio/AudioMacros.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/audio/alconfig.h" namespace ax { diff --git a/core/audio/CMakeLists.txt b/axmol/audio/CMakeLists.txt similarity index 100% rename from core/audio/CMakeLists.txt rename to axmol/audio/CMakeLists.txt diff --git a/core/audio/alconfig.h b/axmol/audio/alconfig.h similarity index 100% rename from core/audio/alconfig.h rename to axmol/audio/alconfig.h diff --git a/core/axmol.cpp b/axmol/axmol.cpp similarity index 90% rename from core/axmol.cpp rename to axmol/axmol.cpp index 207555e63c6d..d973f8b1dfeb 100644 --- a/core/axmol.cpp +++ b/axmol/axmol.cpp @@ -27,21 +27,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" -#include "axmolver.h" +#include "axmol/axmolver.h" namespace ax { AX_DLL const char* axmolVersion() { - return "axmol-" AX_VERSION_STR_FULL; -} - -AX_DLL const char* cocos2dVersion() -{ - return axmolVersion(); + return AX_VERSION_STR_FULL; } } diff --git a/axmol/axmol.h b/axmol/axmol.h new file mode 100644 index 000000000000..238af2d18f6a --- /dev/null +++ b/axmol/axmol.h @@ -0,0 +1,287 @@ +/**************************************************************************** +Copyright (c) 2008-2010 Ricardo Quesada +Copyright (c) 2010-2012 cocos2d-x.org +Copyright (c) 2011 Zynga Inc. +Copyright (c) 2013-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + +https://axmol.dev/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#pragma once + +#include "axmol/axmolver.h" + +// +// all axmol include files +// +#include "axmol/base/Config.h" + +// base +#include "axmol/base/AutoreleasePool.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Logging.h" +#include "axmol/base/Data.h" +#include "axmol/base/Director.h" +#include "axmol/base/IMEDelegate.h" +#include "axmol/base/IMEDispatcher.h" +#include "axmol/base/Map.h" +#include "axmol/base/NS.h" +#include "axmol/base/Profiling.h" +#include "axmol/base/Properties.h" +#include "axmol/base/Object.h" +#include "axmol/base/RefPtr.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/UserDefault.h" +#include "axmol/base/Value.h" +#include "axmol/base/Vector.h" +#include "axmol/base/ZipUtils.h" +#include "axmol/base/base64.h" +#include "axmol/base/Config.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Types.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Utils.h" + +// EventDispatcher +#include "axmol/base/EventAcceleration.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventFocus.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventListenerFocus.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/EventListenerMouse.h" +#include "axmol/base/EventListenerController.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventMouse.h" +#include "axmol/base/EventController.h" +#include "axmol/base/Controller.h" +#include "axmol/base/EventTouch.h" +#include "axmol/base/EventType.h" + +// math +#include "axmol/math/AffineTransform.h" +#include "axmol/math/Math.h" +#include "axmol/math/Vertex.h" +#include "axmol/math/Mat4.h" +#include "axmol/math/MathUtil.h" +#include "axmol/math/Quaternion.h" +#include "axmol/math/Vec2.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Vec4.h" + +// actions +#include "axmol/2d/Action.h" +#include "axmol/2d/ActionCamera.h" +#include "axmol/2d/ActionCatmullRom.h" +#include "axmol/2d/ActionEase.h" +#include "axmol/2d/ActionGrid.h" +#include "axmol/2d/ActionGrid3D.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/ActionManager.h" +#include "axmol/2d/ActionPageTurn3D.h" +#include "axmol/2d/ActionProgressTimer.h" +#include "axmol/2d/ActionTiledGrid.h" +#include "axmol/2d/ActionTween.h" +#include "axmol/2d/TweenFunction.h" +#include "axmol/2d/ActionCoroutine.h" + +// 2d nodes +#include "axmol/2d/AtlasNode.h" +#include "axmol/2d/ClippingNode.h" +#include "axmol/2d/ClippingRectangleNode.h" +#include "axmol/2d/DrawNode.h" +#include "axmol/2d/FontFNT.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/LabelAtlas.h" +#include "axmol/2d/Layer.h" +#include "axmol/2d/Menu.h" +#include "axmol/2d/MenuItem.h" +#include "axmol/2d/MotionStreak.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/NodeGrid.h" +#include "axmol/2d/ParticleBatchNode.h" +#include "axmol/2d/ParticleExamples.h" +#include "axmol/2d/ParticleSystem.h" +#include "axmol/2d/ParticleSystemQuad.h" +#include "axmol/2d/ProgressTimer.h" +#include "axmol/2d/ProtectedNode.h" +#include "axmol/2d/RenderTexture.h" +#include "axmol/2d/Scene.h" +#include "axmol/2d/Transition.h" +#include "axmol/2d/TransitionPageTurn.h" +#include "axmol/2d/TransitionProgress.h" + +// 2d utils +#include "axmol/2d/Camera.h" +#include "axmol/2d/CameraBackgroundBrush.h" +#include "axmol/2d/Grid.h" +#include "axmol/2d/Light.h" + +// include +#include "axmol/base/Protocols.h" + +// renderer +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Pass.h" +#include "axmol/renderer/QuadCommand.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/renderer/RenderCommandPool.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/TextureCube.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/TrianglesCommand.h" +#include "axmol/renderer/Shaders.h" + +// physics + #include "axmol/physics/PhysicsBody.h" + #include "axmol/physics/PhysicsContact.h" + #include "axmol/physics/PhysicsJoint.h" + #include "axmol/physics/PhysicsCollider.h" + #include "axmol/physics/PhysicsWorld.h" + +// platform +#include "axmol/platform/Common.h" +#include "axmol/platform/Device.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/FileStream.h" +#include "axmol/platform/Image.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/SAXParser.h" + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) +# include "axmol/platform/ios/Application-ios.h" +# include "axmol/platform/ios/RenderViewImpl-ios.h" +# include "axmol/platform/ios/StdC-ios.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_IOS + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) +# include "axmol/platform/android/Application-android.h" +# include "axmol/platform/android/RenderViewImpl-android.h" +# include "axmol/platform/android/GL-android.h" +# include "axmol/platform/android/StdC-android.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) +# include "axmol/platform/win32/Application-win32.h" +# include "axmol/platform/RenderViewImpl.h" +# include "axmol/platform/win32/GL-win32.h" +# include "axmol/platform/win32/StdC-win32.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) +# include "axmol/platform/winrt/Application-winrt.h" +# include "axmol/platform/winrt/RenderViewImpl-winrt.h" +# include "axmol/platform/winrt/GL-winrt.h" +# include "axmol/platform/winrt/StdC-winrt.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WINRT + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) +# include "axmol/platform/RenderViewImpl.h" +# include "axmol/platform/mac/Application-mac.h" +# include "axmol/platform/mac/StdC-mac.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_MAC + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) +# include "axmol/platform/linux/Application-linux.h" +# include "axmol/platform/RenderViewImpl.h" +# include "axmol/platform/linux/GL-linux.h" +# include "axmol/platform/linux/StdC-linux.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_LINUX + +#if (AX_TARGET_PLATFORM == AX_PLATFORM_WASM) + #include "axmol/platform/wasm/Application-wasm.h" + #include "axmol/platform/RenderViewImpl.h" + #include "axmol/platform/wasm/GL-wasm.h" + #include "axmol/platform/wasm/StdC-wasm.h" +#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WASM + +// script_support +#include "axmol/base/ScriptSupport.h" + +// sprite_nodes +#include "axmol/2d/Animation.h" +#include "axmol/2d/AnimationCache.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/AnchoredSprite.h" +#include "axmol/2d/AutoPolygon.h" +#include "axmol/2d/SpriteBatchNode.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" + +// text_input_node +#include "axmol/2d/TextFieldTTF.h" + +// textures +#include "axmol/renderer/TextureAtlas.h" + +// tilemap_parallax_nodes +#include "axmol/2d/ParallaxNode.h" +#include "axmol/2d/TMXObjectGroup.h" +#include "axmol/2d/TMXXMLParser.h" +#include "axmol/2d/TileMapAtlas.h" +#include "axmol/2d/FastTMXLayer.h" +#include "axmol/2d/FastTMXTiledMap.h" + +// component +#include "axmol/2d/Component.h" +#include "axmol/2d/ComponentContainer.h" + +// 3d +#include "axmol/3d/AABB.h" +#include "axmol/3d/Animate3D.h" +#include "axmol/3d/Animation3D.h" +#include "axmol/3d/AttachNode.h" +#include "axmol/3d/BillBoard.h" +#include "axmol/3d/Frustum.h" +#include "axmol/3d/Mesh.h" +#include "axmol/3d/MeshSkin.h" +#include "axmol/3d/MotionStreak3D.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/OBB.h" +#include "axmol/3d/Plane.h" +#include "axmol/3d/Ray.h" +#include "axmol/3d/Skeleton3D.h" +#include "axmol/3d/Skybox.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/MeshMaterial.h" +#include "axmol/3d/Terrain.h" +#include "axmol/3d/VertexInputBinding.h" + +namespace ax +{ + +AX_DLL const char* axmolVersion(); + +} diff --git a/core/axmol.natvis b/axmol/axmol.natvis similarity index 100% rename from core/axmol.natvis rename to axmol/axmol.natvis diff --git a/core/axmolver.h.in b/axmol/axmolver.h.in similarity index 95% rename from core/axmolver.h.in rename to axmol/axmolver.h.in index 2990585c1be4..4edc597b45af 100644 --- a/core/axmolver.h.in +++ b/axmol/axmolver.h.in @@ -3,8 +3,8 @@ /* Define the axmol version */ // 0x00 HI ME LO // 00 03 08 00 -#define AX_VERSION_MAJOR 2 -#define AX_VERSION_MINOR 8 +#define AX_VERSION_MAJOR 3 +#define AX_VERSION_MINOR 0 #define AX_VERSION_PATCH 0 /* Define axmol version helper macros */ diff --git a/core/base/AutoreleasePool.cpp b/axmol/base/AutoreleasePool.cpp similarity index 98% rename from core/base/AutoreleasePool.cpp rename to axmol/base/AutoreleasePool.cpp index 4d4168af8e0d..b52d0607c176 100644 --- a/core/base/AutoreleasePool.cpp +++ b/axmol/base/AutoreleasePool.cpp @@ -24,8 +24,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/AutoreleasePool.h" -#include "base/Macros.h" +#include "axmol/base/AutoreleasePool.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/base/AutoreleasePool.h b/axmol/base/AutoreleasePool.h similarity index 99% rename from core/base/AutoreleasePool.h rename to axmol/base/AutoreleasePool.h index 575af1ff04b1..769b1f27b2b9 100644 --- a/core/base/AutoreleasePool.h +++ b/axmol/base/AutoreleasePool.h @@ -28,7 +28,7 @@ THE SOFTWARE. #include #include -#include "base/Object.h" +#include "axmol/base/Object.h" /** * @addtogroup base diff --git a/core/base/CMakeLists.txt b/axmol/base/CMakeLists.txt similarity index 92% rename from core/base/CMakeLists.txt rename to axmol/base/CMakeLists.txt index 00de19a12759..5f8f8c5b35aa 100644 --- a/core/base/CMakeLists.txt +++ b/axmol/base/CMakeLists.txt @@ -38,7 +38,6 @@ set(_AX_BASE_HEADER base/Constants.h base/Event.h base/Types.h - base/Enums.h base/Random.h base/Object.h base/Profiling.h @@ -60,7 +59,7 @@ set(_AX_BASE_HEADER base/FPSImages.h base/ZipUtils.h base/Map.h - base/UTF8.h + base/text_utils.h base/ScriptSupport.h base/EventFocus.h base/Configuration.h @@ -78,7 +77,6 @@ set(_AX_BASE_HEADER base/Scheduler.h base/EventType.h base/IMEDispatcher.h - base/PaddedString.h base/JsonWriter.h base/JobSystem.h ) @@ -128,7 +126,7 @@ set(_AX_BASE_SRC base/FPSImages.cpp base/Random.cpp base/Types.cpp - base/UTF8.cpp + base/text_utils.cpp base/Utils.cpp base/SimpleTimer.cpp base/etc1.cpp @@ -139,11 +137,6 @@ set(_AX_BASE_SRC ${_AX_BASE_SPECIFIC_SRC} ) -if(NOT AX_CORE_PROFILE) - set(_AX_BASE_HEADER ${_AX_BASE_HEADER} base/AsyncTaskPool.h) - set(_AX_BASE_SRC ${_AX_BASE_SRC} base/AsyncTaskPool.cpp) -endif() - if(AX_ENABLE_CONSOLE) set(_AX_BASE_HEADER ${_AX_BASE_HEADER} base/Console.h) set(_AX_BASE_SRC ${_AX_BASE_SRC} base/Console.cpp) diff --git a/core/base/ConcurrentDeque.h b/axmol/base/ConcurrentDeque.h similarity index 100% rename from core/base/ConcurrentDeque.h rename to axmol/base/ConcurrentDeque.h diff --git a/core/base/Config.h b/axmol/base/Config.h similarity index 95% rename from core/base/Config.h rename to axmol/base/Config.h index f0755b246ac8..a32c7ed1a17e 100644 --- a/core/base/Config.h +++ b/axmol/base/Config.h @@ -28,7 +28,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" /** * @file @@ -252,20 +252,6 @@ THE SOFTWARE. # define AX_LUA_ENGINE_DEBUG 0 #endif -/** Use physics integration API. */ -// It works with: -// Chipmunk2D or Box2D -#if defined(AX_ENABLE_PHYSICS) -/** Use Chipmunk2D physics 2d engine on physics integration API. */ -# ifndef AX_ENABLE_CHIPMUNK_INTEGRATION -# define AX_ENABLE_CHIPMUNK_INTEGRATION 0 -# endif -/** or use Box2D physics 2d engine on physics integration API. */ -# ifndef AX_ENABLE_BOX2D_INTEGRATION -# define AX_ENABLE_BOX2D_INTEGRATION 1 -# endif -#endif // defined(AX_ENABLE_PHYSICS) - /** Use culling or not. */ #ifndef AX_USE_CULLING # define AX_USE_CULLING 1 diff --git a/core/base/Configuration.cpp b/axmol/base/Configuration.cpp similarity index 91% rename from core/base/Configuration.cpp rename to axmol/base/Configuration.cpp index b6a661bcb6b1..92c6a4dbf0da 100644 --- a/core/base/Configuration.cpp +++ b/axmol/base/Configuration.cpp @@ -26,12 +26,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Configuration.h" -#include "platform/FileUtils.h" -#include "base/EventCustom.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/base/Configuration.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/rhi/DriverBase.h" namespace ax { @@ -81,7 +81,7 @@ bool Configuration::init() _valueDict["axmol.compiled_with_gl_state_cache"] = Value(true); #endif -#if _AX_DEBUG +#if defined(_AX_DEBUG) && _AX_DEBUG _valueDict["axmol.build_type"] = Value("DEBUG"); #else _valueDict["axmol.build_type"] = Value("RELEASE"); @@ -127,12 +127,12 @@ std::string Configuration::getInfo() const void Configuration::gatherGPUInfo() { - auto driver = backend::DriverBase::getInstance(); + auto driver = rhi::DriverBase::getInstance(); _valueDict["vendor"] = Value(driver->getVendor()); _valueDict["renderer"] = Value(driver->getRenderer()); _valueDict["version"] = Value(driver->getVersion()); - _valueDict["glsl"] = Value(driver->getShaderVersion()); + _valueDict["shader"] = Value(driver->getShaderVersion()); _valueDict["max_texture_size"] = Value(driver->getMaxTextureSize()); _valueDict["max_vertex_attributes"] = Value(driver->getMaxAttributes()); @@ -142,40 +142,40 @@ void Configuration::gatherGPUInfo() _supportsNPOT = true; _valueDict["supports_NPOT"] = Value(_supportsNPOT); - _supportsETC1 = driver->checkForFeatureSupported(backend::FeatureType::ETC1); + _supportsETC1 = driver->checkForFeatureSupported(rhi::FeatureType::ETC1); _valueDict["supports_ETC1"] = Value(_supportsETC1); - _supportsETC2 = driver->checkForFeatureSupported(backend::FeatureType::ETC2); + _supportsETC2 = driver->checkForFeatureSupported(rhi::FeatureType::ETC2); _valueDict["supports_ETC2"] = Value(_supportsETC2); - _supportsS3TC = driver->checkForFeatureSupported(backend::FeatureType::S3TC); + _supportsS3TC = driver->checkForFeatureSupported(rhi::FeatureType::S3TC); _valueDict["supports_S3TC"] = Value(_supportsS3TC); - _supportsATITC = driver->checkForFeatureSupported(backend::FeatureType::AMD_COMPRESSED_ATC); + _supportsATITC = driver->checkForFeatureSupported(rhi::FeatureType::AMD_COMPRESSED_ATC); _valueDict["supports_ATITC"] = Value(_supportsATITC); - _supportsASTC = driver->checkForFeatureSupported(backend::FeatureType::ASTC); + _supportsASTC = driver->checkForFeatureSupported(rhi::FeatureType::ASTC); _valueDict["supports_ASTC"] = Value(_supportsASTC); - _supportsPVRTC = driver->checkForFeatureSupported(backend::FeatureType::PVRTC); + _supportsPVRTC = driver->checkForFeatureSupported(rhi::FeatureType::PVRTC); _valueDict["supports_PVRTC"] = Value(_supportsPVRTC); - _supportsBGRA8888 = driver->checkForFeatureSupported(backend::FeatureType::IMG_FORMAT_BGRA8888); + _supportsBGRA8888 = driver->checkForFeatureSupported(rhi::FeatureType::IMG_FORMAT_BGRA8888); _valueDict["supports_BGRA8888"] = Value(_supportsBGRA8888); - _supportsDiscardFramebuffer = driver->checkForFeatureSupported(backend::FeatureType::DISCARD_FRAMEBUFFER); + _supportsDiscardFramebuffer = driver->checkForFeatureSupported(rhi::FeatureType::DISCARD_FRAMEBUFFER); _valueDict["supports_discard_framebuffer"] = Value(_supportsDiscardFramebuffer); - _supportsOESPackedDepthStencil = driver->checkForFeatureSupported(backend::FeatureType::PACKED_DEPTH_STENCIL); + _supportsOESPackedDepthStencil = driver->checkForFeatureSupported(rhi::FeatureType::PACKED_DEPTH_STENCIL); _valueDict["supports_OES_packed_depth_stencil"] = Value(_supportsOESPackedDepthStencil); - _supportsShareableVAO = driver->checkForFeatureSupported(backend::FeatureType::VAO); + _supportsShareableVAO = driver->checkForFeatureSupported(rhi::FeatureType::VAO); _valueDict["supports_vertex_array_object"] = Value(_supportsShareableVAO); - _supportsOESMapBuffer = driver->checkForFeatureSupported(backend::FeatureType::MAPBUFFER); + _supportsOESMapBuffer = driver->checkForFeatureSupported(rhi::FeatureType::MAPBUFFER); _valueDict["supports_OES_map_buffer"] = Value(_supportsOESMapBuffer); - _supportsOESDepth24 = driver->checkForFeatureSupported(backend::FeatureType::DEPTH24); + _supportsOESDepth24 = driver->checkForFeatureSupported(rhi::FeatureType::DEPTH24); _valueDict["supports_OES_depth24"] = Value(_supportsOESDepth24); } @@ -201,7 +201,7 @@ void Configuration::destroyInstance() // int Configuration::getMaxTextureSize() const { - return backend::DriverBase::getInstance()->getMaxTextureSize(); + return rhi::DriverBase::getInstance()->getMaxTextureSize(); } int Configuration::getMaxModelviewStackDepth() const @@ -211,7 +211,7 @@ int Configuration::getMaxModelviewStackDepth() const int Configuration::getMaxTextureUnits() const { - return backend::DriverBase::getInstance()->getMaxTextureUnits(); + return rhi::DriverBase::getInstance()->getMaxTextureUnits(); } bool Configuration::supportsNPOT() const @@ -414,7 +414,7 @@ void Configuration::loadConfigFile(std::string_view filename) int Configuration::getMaxAttributes() const { - return backend::DriverBase::getInstance()->getMaxAttributes(); + return rhi::DriverBase::getInstance()->getMaxAttributes(); } } diff --git a/core/base/Configuration.h b/axmol/base/Configuration.h similarity index 98% rename from core/base/Configuration.h rename to axmol/base/Configuration.h index 169859f709ed..ac8a08e14bec 100644 --- a/core/base/Configuration.h +++ b/axmol/base/Configuration.h @@ -30,9 +30,9 @@ THE SOFTWARE. #include -#include "base/Object.h" -#include "base/Value.h" -#include "3d/Animate3D.h" +#include "axmol/base/Object.h" +#include "axmol/base/Value.h" +#include "axmol/3d/Animate3D.h" /** * @addtogroup base diff --git a/core/base/Console.cpp b/axmol/base/Console.cpp similarity index 92% rename from core/base/Console.cpp rename to axmol/base/Console.cpp index 71a87b47df13..590972feef4d 100644 --- a/core/base/Console.cpp +++ b/axmol/base/Console.cpp @@ -24,7 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Console.h" +#include "axmol/base/Console.h" +#include "axmol/base/charconv.h" #include #include @@ -37,21 +38,23 @@ #include #include #include +#include + #if defined(_MSC_VER) || defined(__MINGW32__) # include # define bzero(a, b) memset(a, 0, b) #endif -#include "base/Director.h" -#include "base/Scheduler.h" -#include "platform/PlatformConfig.h" -#include "base/Configuration.h" -#include "2d/Scene.h" -#include "platform/FileUtils.h" -#include "renderer/TextureCache.h" -#include "base/Utils.h" -#include "base/UTF8.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/base/Configuration.h" +#include "axmol/2d/Scene.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/base/Utils.h" +#include "axmol/base/text_utils.h" #include "yasio/xxsocket.hpp" @@ -71,51 +74,6 @@ static const size_t SEND_BUFSIZ = 512; std::string Console::Utility::_prompt(PROMPT); -// TODO: these general utils should be in a separate class -// -// Trimming functions were taken from: http://stackoverflow.com/a/217605 -// Since c++17, some parts of the standard library were removed, include "ptr_fun". - -// trim from start - -std::string& Console::Utility::ltrim(std::string& s) -{ - s.erase(s.begin(), std::find_if(s.begin(), s.end(), [](int ch) { return !std::isspace(ch); })); - return s; -} - -// trim from end -std::string& Console::Utility::rtrim(std::string& s) -{ - s.erase(std::find_if(s.rbegin(), s.rend(), [](int ch) { return !std::isspace(ch); }).base(), s.end()); - return s; -} - -// trim from both ends -std::string& Console::Utility::trim(std::string& s) -{ - return Console::Utility::ltrim(Console::Utility::rtrim(s)); -} - -std::vector& Console::Utility::split(std::string_view s, char delim, std::vector& elems) -{ - std::stringstream ss; - ss << s; - std::string item; - while (std::getline(ss, item, delim)) - { - elems.emplace_back(item); - } - return elems; -} - -std::vector Console::Utility::split(std::string_view s, char delim) -{ - std::vector elems; - Console::Utility::split(s, delim, elems); - return elems; -} - // isFloat taken from http://stackoverflow.com/questions/447206/c-isfloat-function bool Console::Utility::isFloat(std::string_view myString) { @@ -409,13 +367,13 @@ bool Console::listenOnTCP(int port) else if (ep.af() == AF_INET6) AXLOGI("Console: IPV6 server is listening on {}", ep.to_string()); - return listenOnFileDescriptor(sock.release_handle()); + return listenOnFileDesc(sock.release_handle()); #else return false; #endif } -bool Console::listenOnFileDescriptor(int fd) +bool Console::listenOnFileDesc(int fd) { if (_running) { @@ -756,14 +714,13 @@ bool Console::parseCommand(socket_native_type fd) return false; } } - std::string cmdLine; - cmdLine = std::string(buf); - auto commands = Console::Utility::split(cmdLine, _commandSeparator); try { - for (auto&& command : commands) + std::string_view cmdLine(buf); + for (auto rgn : std::views::split(cmdLine, _commandSeparator)) { - performCommand(fd, Console::Utility::trim(command)); + std::string_view command{&*rgn.begin(), static_cast(std::ranges::distance(rgn))}; + performCommand(fd, command); } } catch (const std::runtime_error& e) @@ -778,30 +735,39 @@ bool Console::parseCommand(socket_native_type fd) void Console::performCommand(socket_native_type fd, std::string_view command) { - std::vector args = Console::Utility::split(command, ' '); - if (args.empty()) + if (command.empty()) { - throw std::runtime_error("Unknown command. Type 'help' for options\n"); + return; } - auto it = _commands.find(Console::Utility::trim(args[0])); - if (it != _commands.end()) + int index = 0; + hlookup::string_map::iterator it; + std::string cmd_args; + for (auto rgn : std::views::split(command, ' ')) { - std::string args2; - for (size_t i = 1; i < args.size(); ++i) + std::string_view cmd_arg{&*rgn.begin(), static_cast(std::ranges::distance(rgn))}; + if (index == 0) { - if (i > 1) + it = _commands.find(text_utils::trim(cmd_arg)); + if (it == _commands.end()) { - args2 += ' '; + AXLOGW("Unknown command {} . Type 'help' for options", command); + break; } - args2 += Console::Utility::trim(args[i]); } - auto cmd = it->second; - cmd->commandGeneric(fd, args2); + else + { + if (index > 1) + cmd_args += ' '; + cmd_args += cmd_arg; + } + ++index; } - else + + if (it != _commands.end()) { - throw std::runtime_error(std::string{"Unknown command "}.append(command).append(". Type 'help' for options\n")); + auto cmd = it->second; + cmd->commandGeneric(fd, cmd_args); } } @@ -1162,14 +1128,28 @@ void Console::commandTexturesSubCommandFlush(socket_native_type /*fd*/, std::str void Console::commandTouchSubCommandTap(socket_native_type fd, std::string_view args) { - auto argv = Console::Utility::split(args, ' '); - - if ((argv.size() == 3) && (Console::Utility::isFloat(argv[1]) && Console::Utility::isFloat(argv[2]))) + int argi = 0; + float x, y; + for (auto rgn : std::views::split(args, ' ')) { + std::string_view argv{&*rgn.begin(), static_cast(std::ranges::distance(rgn))}; + switch (argi++) + { + case 1: + axstd::from_chars(argv.data(), argv.data() + argv.length(), x); + break; + case 2: + axstd::from_chars(argv.data(), argv.data() + argv.length(), x); + break; + } + if (argi == 3) + { + break; + } + } - float x = (float)utils::atof(argv[1].c_str()); - float y = (float)utils::atof(argv[2].c_str()); - + if (argi == 3) + { std::srand((unsigned)time(nullptr)); _touchId = rand(); Scheduler* sched = Director::getInstance()->getScheduler(); @@ -1187,16 +1167,34 @@ void Console::commandTouchSubCommandTap(socket_native_type fd, std::string_view void Console::commandTouchSubCommandSwipe(socket_native_type fd, std::string_view args) { - auto argv = Console::Utility::split(args, ' '); + std::vector argv; + for (auto rgn : std::views::split(args, ' ')) + { + argv.emplace_back(&*rgn.begin(), static_cast(std::ranges::distance(rgn))); + } if ((argv.size() == 5) && (Console::Utility::isFloat(argv[1])) && (Console::Utility::isFloat(argv[2])) && (Console::Utility::isFloat(argv[3])) && (Console::Utility::isFloat(argv[4]))) { + float points[4]; + + for (int i = 0; i < 4; ++i) + { + const auto& val = argv[i + 1]; + // const auto [_, ec] = std::from_chars(val.data(), val.data() + val.size(), points[i]); + // if (!!(int)ec) + // { + // AXLOGW("invalid float number: {}", val); + // return; + // } + char* endptr = nullptr; + points[i] = std::strtod(val.data(), &endptr); + } - float x1 = (float)utils::atof(argv[1].c_str()); - float y1 = (float)utils::atof(argv[2].c_str()); - float x2 = (float)utils::atof(argv[3].c_str()); - float y2 = (float)utils::atof(argv[4].c_str()); + float& x1 = points[0]; + float& y1 = points[1]; + float& x2 = points[2]; + float& y2 = points[3]; std::srand((unsigned)time(nullptr)); _touchId = rand(); @@ -1429,4 +1427,4 @@ void Console::sendHelp(socket_native_type fd, const hlookup::string_map #include "yasio/io_watcher.hpp" -#include "base/Object.h" -#include "base/Macros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Macros.h" namespace ax { @@ -69,15 +69,6 @@ class AX_DLL Console : public Object class Utility { public: - // Trimming functions - static std::string& ltrim(std::string& s); - static std::string& rtrim(std::string& s); - static std::string& trim(std::string& s); - - // split - static std::vector& split(std::string_view s, char delim, std::vector& elems); - static std::vector split(std::string_view s, char delim); - /** Checks myString is a floating-point type. */ static bool isFloat(std::string_view myString); @@ -167,7 +158,7 @@ class AX_DLL Console : public Object bool listenOnTCP(int port); /** starts listening to specified file descriptor */ - bool listenOnFileDescriptor(int fd); + bool listenOnFileDesc(int fd); /** stops the Console. 'stop' will be called at destruction time as well */ void stop(); diff --git a/core/base/Constants.h b/axmol/base/Constants.h similarity index 99% rename from core/base/Constants.h rename to axmol/base/Constants.h index 7619e79100ae..39d57bc235d8 100644 --- a/core/base/Constants.h +++ b/axmol/base/Constants.h @@ -23,7 +23,7 @@ #pragma once -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { @@ -64,4 +64,4 @@ const int CLAMP_TO_EDGE = 0x812F; // GL_CLAMP_TO_EDGE const int MIRROR_REPEAT = 0x8370; // GL_MIRRORED_REPEAT } // namespace GLTexParamConst -} \ No newline at end of file +} diff --git a/core/base/Controller-android.cpp b/axmol/base/Controller-android.cpp similarity index 97% rename from core/base/Controller-android.cpp rename to axmol/base/Controller-android.cpp index de07de3b9cdf..776f1512e001 100644 --- a/core/base/Controller-android.cpp +++ b/axmol/base/Controller-android.cpp @@ -25,14 +25,14 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Controller.h" +#include "axmol/base/Controller.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) # include -# include "base/Macros.h" -# include "base/Director.h" -# include "platform/android/jni/JniHelper.h" -# include "base/EventController.h" +# include "axmol/base/Macros.h" +# include "axmol/base/Director.h" +# include "axmol/platform/android/jni/JniHelper.h" +# include "axmol/base/EventController.h" namespace ax { diff --git a/core/base/Controller-apple.mm b/axmol/base/Controller-apple.mm similarity index 97% rename from core/base/Controller-apple.mm rename to axmol/base/Controller-apple.mm index aaa2bde1147c..cdcbf1dcc8bb 100644 --- a/core/base/Controller-apple.mm +++ b/axmol/base/Controller-apple.mm @@ -25,16 +25,16 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "base/Controller.h" -#include "platform/PlatformConfig.h" +#include "axmol/base/Controller.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC) -# include "base/Macros.h" -# include "base/EventDispatcher.h" -# include "base/EventController.h" -# include "base/EventListenerController.h" -# include "base/Director.h" -# include "2d/Label.h" +# include "axmol/base/Macros.h" +# include "axmol/base/EventDispatcher.h" +# include "axmol/base/EventController.h" +# include "axmol/base/EventListenerController.h" +# include "axmol/base/Director.h" +# include "axmol/2d/Label.h" # import diff --git a/core/base/Controller-linux-win32.cpp b/axmol/base/Controller-linux-win32.cpp similarity index 99% rename from core/base/Controller-linux-win32.cpp rename to axmol/base/Controller-linux-win32.cpp index 1db259cdc7d0..3642953dcd8b 100644 --- a/core/base/Controller-linux-win32.cpp +++ b/axmol/base/Controller-linux-win32.cpp @@ -26,14 +26,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Controller.h" +#include "axmol/base/Controller.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) # include -# include "base/Macros.h" -# include "base/Director.h" -# include "base/Scheduler.h" -# include "base/EventController.h" +# include "axmol/base/Macros.h" +# include "axmol/base/Director.h" +# include "axmol/base/Scheduler.h" +# include "axmol/base/EventController.h" # include "glfw3.h" namespace ax diff --git a/core/base/Controller.cpp b/axmol/base/Controller.cpp similarity index 96% rename from core/base/Controller.cpp rename to axmol/base/Controller.cpp index 76f47ee5bda2..6a7f24f8de16 100644 --- a/core/base/Controller.cpp +++ b/axmol/base/Controller.cpp @@ -24,15 +24,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Controller.h" +#include "axmol/base/Controller.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || \ AX_TARGET_PLATFORM == AX_PLATFORM_MAC || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || \ defined(_WIN32) || AX_TARGET_PLATFORM == AX_PLATFORM_WASM) -# include "base/EventDispatcher.h" -# include "base/EventController.h" -# include "base/Director.h" +# include "axmol/base/EventDispatcher.h" +# include "axmol/base/EventController.h" +# include "axmol/base/Director.h" namespace ax { diff --git a/core/base/Controller.h b/axmol/base/Controller.h similarity index 99% rename from core/base/Controller.h rename to axmol/base/Controller.h index bf2bd83ff31f..7a247c4f2b2f 100644 --- a/core/base/Controller.h +++ b/axmol/base/Controller.h @@ -30,7 +30,7 @@ defined(_WIN32) /* win32 & winuwp */ || \ AX_TARGET_PLATFORM == AX_PLATFORM_WASM) -# include "platform/PlatformMacros.h" +# include "axmol/platform/PlatformMacros.h" # include # include # include diff --git a/core/base/Data.cpp b/axmol/base/Data.cpp similarity index 98% rename from core/base/Data.cpp rename to axmol/base/Data.cpp index c84565c1f913..d812b6dcf594 100644 --- a/core/base/Data.cpp +++ b/axmol/base/Data.cpp @@ -25,8 +25,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Data.h" -#include "base/Logging.h" +#include "axmol/base/Data.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/base/Data.h b/axmol/base/Data.h similarity index 97% rename from core/base/Data.h rename to axmol/base/Data.h index 5fe19b4102df..3d34dd0910df 100644 --- a/core/base/Data.h +++ b/axmol/base/Data.h @@ -27,11 +27,11 @@ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include // for ssize_t on android #include // for ssize_t on linux -#include "platform/StdC.h" // for ssize_t on window -#include "base/axstd.h" +#include "axmol/platform/StdC.h" // for ssize_t on window +#include "axmol/base/axstd.h" /** * @addtogroup base diff --git a/core/base/Director.cpp b/axmol/base/Director.cpp similarity index 95% rename from core/base/Director.cpp rename to axmol/base/Director.cpp index b53f22dab54b..810db297affe 100644 --- a/core/base/Director.cpp +++ b/axmol/base/Director.cpp @@ -28,49 +28,46 @@ THE SOFTWARE. ****************************************************************************/ // axmol includes -#include "base/Director.h" +#include "axmol/base/Director.h" // standard includes #include -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" - -#include "2d/ActionManager.h" -#include "2d/FontFNT.h" -#include "2d/FontAtlasCache.h" -#include "2d/AnimationCache.h" -#include "2d/Transition.h" -#include "2d/FontFreeType.h" -#include "2d/LabelAtlas.h" -#include "renderer/TextureCache.h" -#include "renderer/Renderer.h" -#include "renderer/RenderState.h" -#include "2d/Camera.h" -#include "base/UserDefault.h" -#include "base/Utils.h" -#include "base/FPSImages.h" -#include "base/Scheduler.h" -#include "base/Macros.h" -#include "base/EventDispatcher.h" -#include "base/EventCustom.h" -#include "base/Logging.h" -#include "base/AutoreleasePool.h" -#include "base/Configuration.h" -#ifndef AX_CORE_PROFILE -# include "base/AsyncTaskPool.h" -#endif -#include "base/ObjectFactory.h" -#include "platform/Application.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" + +#include "axmol/2d/ActionManager.h" +#include "axmol/2d/FontFNT.h" +#include "axmol/2d/FontAtlasCache.h" +#include "axmol/2d/AnimationCache.h" +#include "axmol/2d/Transition.h" +#include "axmol/2d/FontFreeType.h" +#include "axmol/2d/LabelAtlas.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/2d/Camera.h" +#include "axmol/base/UserDefault.h" +#include "axmol/base/Utils.h" +#include "axmol/base/FPSImages.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Macros.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/Logging.h" +#include "axmol/base/AutoreleasePool.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/platform/Application.h" #if defined(AX_ENABLE_AUDIO) -# include "audio/AudioEngine.h" +# include "axmol/audio/AudioEngine.h" #endif #if AX_ENABLE_SCRIPT_BINDING -# include "base/ScriptSupport.h" +# include "axmol/base/ScriptSupport.h" #endif -using namespace std; +#include "axmol/rhi/SamplerCache.h" namespace ax { @@ -232,15 +229,6 @@ void Director::setDefaultValues() else AXASSERT(false, "Invalid projection value"); - // Default pixel format for PNG images with alpha - std::string pixel_format = conf->getValue("axmol.texture.pixel_format_for_png", Value("rgba8888")).asString(); - if (pixel_format == "rgba8888") - Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat::RGBA8); - else if (pixel_format == "rgba4444") - Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat::RGBA4); - else if (pixel_format == "rgba5551") - Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat::RGB5A1); - /* !!!Notes ** All compressed image should do PMA at texture convert tools(such as astcenc-2.2+ with -pp-premultiply) ** or GPU fragment shader @@ -267,7 +255,7 @@ void Director::setGLDefaultValues() AXASSERT(_renderView, "opengl view should not be null"); _renderer->setDepthTest(false); - _renderer->setDepthCompareFunction(backend::CompareFunction::LESS_EQUAL); + _renderer->setDepthCompareFunc(rhi::CompareFunc::LESS_EQUAL); setProjection(_projection); } @@ -382,7 +370,7 @@ void Director::calculateDeltaTime() _deltaTime = MAX(0, _deltaTime); } -#if _AX_DEBUG +#if defined(_AX_DEBUG) && _AX_DEBUG // If we are debugging our code, prevent big delta time if (_deltaTime > 0.2f) { @@ -693,7 +681,7 @@ float Director::getZEye() const return (_winSizeInPoints.height / 1.154700538379252f); //(2 * tanf(M_PI/6)) } -void Director::setClearColor(const Color4F& clearColor) +void Director::setClearColor(const Color& clearColor) { _clearColor = clearColor; } @@ -1059,17 +1047,17 @@ void Director::reset() AnimationCache::destroyInstance(); SpriteFrameCache::destroyInstance(); FileUtils::destroyInstance(); -#ifndef AX_CORE_PROFILE - AsyncTaskPool::destroyInstance(); -#endif - backend::ProgramStateRegistry::destroyInstance(); - backend::ProgramManager::destroyInstance(); + + ProgramStateRegistry::destroyInstance(); + ProgramManager::destroyInstance(); // axmol specific data structures UserDefault::destroyInstance(); resetMatrixStack(); destroyTextureCache(); + + rhi::SamplerCache::destroyInstance(); } void Director::cleanupDirector() @@ -1079,7 +1067,8 @@ void Director::cleanupDirector() // If any graphics resources not cleanup or leaked, will crash on linux when destroy graphics context, // so we should cleanup any graphics resources. AX_SAFE_DELETE(_renderer); - backend::DriverBase::destroyInstance(); + ProgramManager::destroyInstance(); + rhi::DriverBase::destroyInstance(); // OpenGL view if (_renderView) @@ -1254,14 +1243,14 @@ void Director::showStats() auto currentVerts = (uint32_t)_renderer->getDrawnVertices(); if (currentCalls != prevCalls) { - auto msg = fmt::format_to_z(buffer, "GL calls:{:6d}", currentCalls); + auto msg = fmt::format_to_z(buffer, "Draw calls:{:6d}", currentCalls); _drawnBatchesLabel->setString(msg); prevCalls = currentCalls; } if (currentVerts != prevVerts) { - auto msg = fmt::format_to_z(buffer, "GL verts:{:6d}", currentVerts); + auto msg = fmt::format_to_z(buffer, "Vertices: {:6d}", currentVerts); _drawnVerticesLabel->setString(msg); prevVerts = currentVerts; } @@ -1323,7 +1312,7 @@ void Director::createStatsLabel() return; } - texture = _textureCache->addImage(image, "/ax_fps_images", PixelFormat::RGBA4); + texture = _textureCache->addImage(image, "/ax_fps_images"); AX_SAFE_RELEASE(image); /* diff --git a/core/base/Director.h b/axmol/base/Director.h similarity index 97% rename from core/base/Director.h rename to axmol/base/Director.h index a6d9a892ea98..500f92abee52 100644 --- a/core/base/Director.h +++ b/axmol/base/Director.h @@ -32,20 +32,20 @@ THE SOFTWARE. #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "base/Vector.h" -#include "2d/Scene.h" -#include "math/Math.h" -#include "platform/RenderView.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/2d/Scene.h" +#include "axmol/math/Math.h" +#include "axmol/platform/RenderView.h" #if defined(AX_PLATFORM_PC) # include "concurrentqueue/concurrentqueue.h" #endif #ifdef AX_ENABLE_CONSOLE -#include "base/Console.h" +#include "axmol/base/Console.h" #endif -#include "base/JobSystem.h" +#include "axmol/base/JobSystem.h" namespace ax { @@ -175,11 +175,6 @@ class AX_DLL Director */ void setRenderView(RenderView* renderView); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) RenderView* getGLView() { return getRenderView(); } - AX_DEPRECATED(2.8) void setGLView(RenderView* renderView) { setRenderView(renderView); } -#endif - /* * Gets singleton of TextureCache. */ @@ -375,7 +370,7 @@ class AX_DLL Director /** Sets clear values for the color buffers, * value range of each element is [0.0, 1.0]. */ - void setClearColor(const Color4F& clearColor); + void setClearColor(const Color& clearColor); void mainLoop(); /** Invoke main loop with delta time. Then `calculateDeltaTime` can just use the delta time directly. @@ -647,7 +642,7 @@ class AX_DLL Director /* Renderer for the Director */ Renderer* _renderer = nullptr; - Color4F _clearColor = {0, 0, 0, 1}; + Color _clearColor = {0, 0, 0, 1}; #ifdef AX_ENABLE_CONSOLE /* Console for the director */ Console* _console = nullptr; diff --git a/core/base/Event.cpp b/axmol/base/Event.cpp similarity index 98% rename from core/base/Event.cpp rename to axmol/base/Event.cpp index b76a706f9b8e..9943d3d8174f 100644 --- a/core/base/Event.cpp +++ b/axmol/base/Event.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Event.h" +#include "axmol/base/Event.h" namespace ax { diff --git a/core/base/Event.h b/axmol/base/Event.h similarity index 97% rename from core/base/Event.h rename to axmol/base/Event.h index 58cfb8124538..ee92fbecd363 100644 --- a/core/base/Event.h +++ b/axmol/base/Event.h @@ -25,8 +25,8 @@ #pragma once -#include "base/Object.h" -#include "platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/platform/PlatformMacros.h" /** * @addtogroup base diff --git a/core/base/EventAcceleration.cpp b/axmol/base/EventAcceleration.cpp similarity index 97% rename from core/base/EventAcceleration.cpp rename to axmol/base/EventAcceleration.cpp index 9dff922cbaa9..eb9729c4eac1 100644 --- a/core/base/EventAcceleration.cpp +++ b/axmol/base/EventAcceleration.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventAcceleration.h" +#include "axmol/base/EventAcceleration.h" namespace ax { diff --git a/core/base/EventAcceleration.h b/axmol/base/EventAcceleration.h similarity index 96% rename from core/base/EventAcceleration.h rename to axmol/base/EventAcceleration.h index 4d666e3a6c65..2e654b2088c1 100644 --- a/core/base/EventAcceleration.h +++ b/axmol/base/EventAcceleration.h @@ -25,8 +25,8 @@ #pragma once -#include "base/Event.h" -#include "base/Types.h" +#include "axmol/base/Event.h" +#include "axmol/base/Types.h" /** * @addtogroup base diff --git a/core/base/EventController.cpp b/axmol/base/EventController.cpp similarity index 97% rename from core/base/EventController.cpp rename to axmol/base/EventController.cpp index f4ecbb9613c1..9a150caadde4 100644 --- a/core/base/EventController.cpp +++ b/axmol/base/EventController.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventController.h" +#include "axmol/base/EventController.h" namespace ax { diff --git a/core/base/EventController.h b/axmol/base/EventController.h similarity index 98% rename from core/base/EventController.h rename to axmol/base/EventController.h index b159d2f61f0e..381dc7e279ae 100644 --- a/core/base/EventController.h +++ b/axmol/base/EventController.h @@ -26,8 +26,8 @@ #pragma once -#include "platform/PlatformMacros.h" -#include "base/Event.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Event.h" /** * @addtogroup base diff --git a/core/base/EventCustom.cpp b/axmol/base/EventCustom.cpp similarity index 95% rename from core/base/EventCustom.cpp rename to axmol/base/EventCustom.cpp index 4d5ae09f4bc8..e431e2499df1 100644 --- a/core/base/EventCustom.cpp +++ b/axmol/base/EventCustom.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventCustom.h" -#include "base/Event.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/Event.h" namespace ax { diff --git a/core/base/EventCustom.h b/axmol/base/EventCustom.h similarity index 98% rename from core/base/EventCustom.h rename to axmol/base/EventCustom.h index da828263d670..0d199a6f5b4f 100644 --- a/core/base/EventCustom.h +++ b/axmol/base/EventCustom.h @@ -26,7 +26,7 @@ #pragma once #include -#include "base/Event.h" +#include "axmol/base/Event.h" /** * @addtogroup base diff --git a/core/base/EventDispatcher.cpp b/axmol/base/EventDispatcher.cpp similarity index 98% rename from core/base/EventDispatcher.cpp rename to axmol/base/EventDispatcher.cpp index c6f823b77fa2..3b3afd632a33 100644 --- a/core/base/EventDispatcher.cpp +++ b/axmol/base/EventDispatcher.cpp @@ -23,26 +23,26 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/EventDispatcher.h" +#include "axmol/base/EventDispatcher.h" #include -#include "base/EventCustom.h" -#include "base/EventListenerTouch.h" -#include "base/EventListenerAcceleration.h" -#include "base/EventListenerMouse.h" -#include "base/EventListenerKeyboard.h" -#include "base/EventListenerCustom.h" -#include "base/EventListenerFocus.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/EventListenerMouse.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventListenerFocus.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || \ AX_TARGET_PLATFORM == AX_PLATFORM_MAC || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || \ AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "base/EventListenerController.h" +# include "axmol/base/EventListenerController.h" #endif -#include "2d/Scene.h" -#include "base/Director.h" -#include "base/EventType.h" -#include "2d/Camera.h" -#include "2d/ProtectedNode.h" +#include "axmol/2d/Scene.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventType.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/ProtectedNode.h" #define DUMP_LISTENER_ITEM_PRIORITY_INFO 0 diff --git a/core/base/EventDispatcher.h b/axmol/base/EventDispatcher.h similarity index 98% rename from core/base/EventDispatcher.h rename to axmol/base/EventDispatcher.h index 0251f1254e07..2877bf009467 100644 --- a/core/base/EventDispatcher.h +++ b/axmol/base/EventDispatcher.h @@ -32,10 +32,10 @@ #include #include -#include "platform/PlatformMacros.h" -#include "base/EventListener.h" -#include "base/Event.h" -#include "platform/StdC.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/Event.h" +#include "axmol/platform/StdC.h" /** * @addtogroup base diff --git a/core/base/EventFocus.cpp b/axmol/base/EventFocus.cpp similarity index 97% rename from core/base/EventFocus.cpp rename to axmol/base/EventFocus.cpp index 8eaf61e25075..15436c475e6f 100644 --- a/core/base/EventFocus.cpp +++ b/axmol/base/EventFocus.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventFocus.h" +#include "axmol/base/EventFocus.h" namespace ax { diff --git a/core/base/EventFocus.h b/axmol/base/EventFocus.h similarity index 98% rename from core/base/EventFocus.h rename to axmol/base/EventFocus.h index 942e9374f6d8..ec1b25e344be 100644 --- a/core/base/EventFocus.h +++ b/axmol/base/EventFocus.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Event.h" +#include "axmol/base/Event.h" /** * @addtogroup base diff --git a/core/base/EventKeyboard.cpp b/axmol/base/EventKeyboard.cpp similarity index 97% rename from core/base/EventKeyboard.cpp rename to axmol/base/EventKeyboard.cpp index e0517b471d8f..ec687298982a 100644 --- a/core/base/EventKeyboard.cpp +++ b/axmol/base/EventKeyboard.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ -#include "base/EventKeyboard.h" +#include "axmol/base/EventKeyboard.h" namespace ax { diff --git a/core/base/EventKeyboard.h b/axmol/base/EventKeyboard.h similarity index 99% rename from core/base/EventKeyboard.h rename to axmol/base/EventKeyboard.h index ff90ad4c0da7..c744807fca38 100644 --- a/core/base/EventKeyboard.h +++ b/axmol/base/EventKeyboard.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Event.h" +#include "axmol/base/Event.h" /** * @addtogroup base diff --git a/core/base/EventListener.cpp b/axmol/base/EventListener.cpp similarity index 96% rename from core/base/EventListener.cpp rename to axmol/base/EventListener.cpp index 159c8c92012a..dea6704e07aa 100644 --- a/core/base/EventListener.cpp +++ b/axmol/base/EventListener.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListener.h" -#include "base/Logging.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/base/EventListener.h b/axmol/base/EventListener.h similarity index 98% rename from core/base/EventListener.h rename to axmol/base/EventListener.h index 6cfafb99f1f8..4c48b34ad059 100644 --- a/core/base/EventListener.h +++ b/axmol/base/EventListener.h @@ -29,8 +29,8 @@ #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" /** * @addtogroup base diff --git a/core/base/EventListenerAcceleration.cpp b/axmol/base/EventListenerAcceleration.cpp similarity index 95% rename from core/base/EventListenerAcceleration.cpp rename to axmol/base/EventListenerAcceleration.cpp index bc3211e5be68..7c57c898fa5a 100644 --- a/core/base/EventListenerAcceleration.cpp +++ b/axmol/base/EventListenerAcceleration.cpp @@ -24,9 +24,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListenerAcceleration.h" -#include "base/EventAcceleration.h" -#include "base/Logging.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/EventAcceleration.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/base/EventListenerAcceleration.h b/axmol/base/EventListenerAcceleration.h similarity index 93% rename from core/base/EventListenerAcceleration.h rename to axmol/base/EventListenerAcceleration.h index ec97bcae157d..34d0d0a48043 100644 --- a/core/base/EventListenerAcceleration.h +++ b/axmol/base/EventListenerAcceleration.h @@ -26,8 +26,8 @@ #pragma once -#include "base/EventListener.h" -#include "base/Types.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/Types.h" /** * @addtogroup base @@ -57,8 +57,8 @@ class AX_DLL EventListenerAcceleration : public EventListener virtual ~EventListenerAcceleration(); /// Overrides - virtual EventListenerAcceleration* clone() override; - virtual bool checkAvailable() override; + EventListenerAcceleration* clone() override; + bool checkAvailable() override; EventListenerAcceleration(); diff --git a/core/base/EventListenerController.cpp b/axmol/base/EventListenerController.cpp similarity index 96% rename from core/base/EventListenerController.cpp rename to axmol/base/EventListenerController.cpp index 32f8b37ddd9c..0b82cd0e41ed 100644 --- a/core/base/EventListenerController.cpp +++ b/axmol/base/EventListenerController.cpp @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListenerController.h" -#include "base/EventController.h" -#include "base/Macros.h" -#include "base/Controller.h" +#include "axmol/base/EventListenerController.h" +#include "axmol/base/EventController.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Controller.h" namespace ax { @@ -116,4 +116,4 @@ EventListenerController* EventListenerController::clone() return nullptr; } -} \ No newline at end of file +} diff --git a/core/base/EventListenerController.h b/axmol/base/EventListenerController.h similarity index 93% rename from core/base/EventListenerController.h rename to axmol/base/EventListenerController.h index 3d2839494051..f858fe276466 100644 --- a/core/base/EventListenerController.h +++ b/axmol/base/EventListenerController.h @@ -26,8 +26,8 @@ #pragma once -#include "platform/PlatformMacros.h" -#include "base/EventListener.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/EventListener.h" /** * @addtogroup base @@ -55,8 +55,8 @@ class AX_DLL EventListenerController : public EventListener static EventListenerController* create(); /// Overrides - virtual bool checkAvailable() override; - virtual EventListenerController* clone() override; + bool checkAvailable() override; + EventListenerController* clone() override; std::function onConnected; std::function onDisconnected; diff --git a/core/base/EventListenerCustom.cpp b/axmol/base/EventListenerCustom.cpp similarity index 97% rename from core/base/EventListenerCustom.cpp rename to axmol/base/EventListenerCustom.cpp index a65ed38ee94b..1ca390bf99b8 100644 --- a/core/base/EventListenerCustom.cpp +++ b/axmol/base/EventListenerCustom.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListenerCustom.h" -#include "base/EventCustom.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventCustom.h" namespace ax { diff --git a/core/base/EventListenerCustom.h b/axmol/base/EventListenerCustom.h similarity index 95% rename from core/base/EventListenerCustom.h rename to axmol/base/EventListenerCustom.h index 7821935cc882..b59785e54a56 100644 --- a/core/base/EventListenerCustom.h +++ b/axmol/base/EventListenerCustom.h @@ -25,7 +25,7 @@ #pragma once -#include "base/EventListener.h" +#include "axmol/base/EventListener.h" /** * @addtogroup base @@ -68,8 +68,8 @@ class AX_DLL EventListenerCustom : public EventListener static EventListenerCustom* create(std::string_view eventName, const std::function& callback); /// Overrides - virtual bool checkAvailable() override; - virtual EventListenerCustom* clone() override; + bool checkAvailable() override; + EventListenerCustom* clone() override; /** Constructor */ EventListenerCustom(); diff --git a/core/base/EventListenerFocus.cpp b/axmol/base/EventListenerFocus.cpp similarity index 96% rename from core/base/EventListenerFocus.cpp rename to axmol/base/EventListenerFocus.cpp index 27d8d705530c..a8de0e83545d 100644 --- a/core/base/EventListenerFocus.cpp +++ b/axmol/base/EventListenerFocus.cpp @@ -25,9 +25,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListenerFocus.h" -#include "base/EventFocus.h" -#include "base/Macros.h" +#include "axmol/base/EventListenerFocus.h" +#include "axmol/base/EventFocus.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/base/EventListenerFocus.h b/axmol/base/EventListenerFocus.h similarity index 94% rename from core/base/EventListenerFocus.h rename to axmol/base/EventListenerFocus.h index 5c1e3b474372..5aadf6182b77 100644 --- a/core/base/EventListenerFocus.h +++ b/axmol/base/EventListenerFocus.h @@ -27,7 +27,7 @@ #pragma once -#include "base/EventListener.h" +#include "axmol/base/EventListener.h" /** * @addtogroup base @@ -61,8 +61,8 @@ class AX_DLL EventListenerFocus : public EventListener virtual ~EventListenerFocus(); /// Overrides - virtual EventListenerFocus* clone() override; - virtual bool checkAvailable() override; + EventListenerFocus* clone() override; + bool checkAvailable() override; // public: diff --git a/core/base/EventListenerKeyboard.cpp b/axmol/base/EventListenerKeyboard.cpp similarity index 97% rename from core/base/EventListenerKeyboard.cpp rename to axmol/base/EventListenerKeyboard.cpp index 03a5d7f74a86..b3a95ec12372 100644 --- a/core/base/EventListenerKeyboard.cpp +++ b/axmol/base/EventListenerKeyboard.cpp @@ -24,8 +24,8 @@ ****************************************************************************/ -#include "base/EventListenerKeyboard.h" -#include "base/Macros.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/base/EventListenerKeyboard.h b/axmol/base/EventListenerKeyboard.h similarity index 92% rename from core/base/EventListenerKeyboard.h rename to axmol/base/EventListenerKeyboard.h index 7944ec107036..1f459e9ec5bf 100644 --- a/core/base/EventListenerKeyboard.h +++ b/axmol/base/EventListenerKeyboard.h @@ -26,8 +26,8 @@ #pragma once -#include "base/EventListener.h" -#include "base/EventKeyboard.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/EventKeyboard.h" /** * @addtogroup base @@ -54,8 +54,8 @@ class AX_DLL EventListenerKeyboard : public EventListener static EventListenerKeyboard* create(); /// Overrides - virtual EventListenerKeyboard* clone() override; - virtual bool checkAvailable() override; + EventListenerKeyboard* clone() override; + bool checkAvailable() override; std::function onKeyPressed; std::function onKeyReleased; diff --git a/core/base/EventListenerMouse.cpp b/axmol/base/EventListenerMouse.cpp similarity index 98% rename from core/base/EventListenerMouse.cpp rename to axmol/base/EventListenerMouse.cpp index 0e67c03daf04..fa76aabe8961 100644 --- a/core/base/EventListenerMouse.cpp +++ b/axmol/base/EventListenerMouse.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ -#include "base/EventListenerMouse.h" +#include "axmol/base/EventListenerMouse.h" namespace ax { diff --git a/core/base/EventListenerMouse.h b/axmol/base/EventListenerMouse.h similarity index 93% rename from core/base/EventListenerMouse.h rename to axmol/base/EventListenerMouse.h index 77fd0b88482b..d7b9a262e847 100644 --- a/core/base/EventListenerMouse.h +++ b/axmol/base/EventListenerMouse.h @@ -26,8 +26,8 @@ #pragma once -#include "base/EventListener.h" -#include "base/EventMouse.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/EventMouse.h" /** * @addtogroup base @@ -65,8 +65,8 @@ class AX_DLL EventListenerMouse : public EventListener bool isSwallowMouse(); /// Overrides - virtual EventListenerMouse* clone() override; - virtual bool checkAvailable() override; + EventListenerMouse* clone() override; + bool checkAvailable() override; std::function onMouseDown; std::function onMouseUp; diff --git a/core/base/EventListenerTouch.cpp b/axmol/base/EventListenerTouch.cpp similarity index 97% rename from core/base/EventListenerTouch.cpp rename to axmol/base/EventListenerTouch.cpp index ac07fee96ad8..7ee457440ffc 100644 --- a/core/base/EventListenerTouch.cpp +++ b/axmol/base/EventListenerTouch.cpp @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventListenerTouch.h" -#include "base/EventDispatcher.h" -#include "base/EventTouch.h" -#include "base/Touch.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventTouch.h" +#include "axmol/base/Touch.h" #include diff --git a/core/base/EventListenerTouch.h b/axmol/base/EventListenerTouch.h similarity index 93% rename from core/base/EventListenerTouch.h rename to axmol/base/EventListenerTouch.h index f2df746d8abd..00478ef0e93c 100644 --- a/core/base/EventListenerTouch.h +++ b/axmol/base/EventListenerTouch.h @@ -27,7 +27,7 @@ #pragma once -#include "base/EventListener.h" +#include "axmol/base/EventListener.h" #include /** @@ -69,8 +69,8 @@ class AX_DLL EventListenerTouchOneByOne : public EventListener bool isSwallowTouches(); /// Overrides - virtual EventListenerTouchOneByOne* clone() override; - virtual bool checkAvailable() override; + EventListenerTouchOneByOne* clone() override; + bool checkAvailable() override; // public: @@ -110,8 +110,8 @@ class AX_DLL EventListenerTouchAllAtOnce : public EventListener virtual ~EventListenerTouchAllAtOnce(); /// Overrides - virtual EventListenerTouchAllAtOnce* clone() override; - virtual bool checkAvailable() override; + EventListenerTouchAllAtOnce* clone() override; + bool checkAvailable() override; // public: typedef std::function&, Event*)> ccTouchesCallback; diff --git a/core/base/EventMouse.cpp b/axmol/base/EventMouse.cpp similarity index 97% rename from core/base/EventMouse.cpp rename to axmol/base/EventMouse.cpp index 679e7c17288f..9a7403691777 100644 --- a/core/base/EventMouse.cpp +++ b/axmol/base/EventMouse.cpp @@ -24,8 +24,8 @@ ****************************************************************************/ -#include "base/EventMouse.h" -#include "base/Director.h" +#include "axmol/base/EventMouse.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/base/EventMouse.h b/axmol/base/EventMouse.h similarity index 98% rename from core/base/EventMouse.h rename to axmol/base/EventMouse.h index 1c8939b08d43..da602bfa7c4b 100644 --- a/core/base/EventMouse.h +++ b/axmol/base/EventMouse.h @@ -26,8 +26,8 @@ ****************************************************************************/ #pragma once -#include "base/Event.h" -#include "math/Math.h" +#include "axmol/base/Event.h" +#include "axmol/math/Math.h" /** * @addtogroup base diff --git a/core/base/EventTouch.cpp b/axmol/base/EventTouch.cpp similarity index 95% rename from core/base/EventTouch.cpp rename to axmol/base/EventTouch.cpp index 31c93fed0a64..e2bc31d158f4 100644 --- a/core/base/EventTouch.cpp +++ b/axmol/base/EventTouch.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/EventTouch.h" -#include "base/Touch.h" +#include "axmol/base/EventTouch.h" +#include "axmol/base/Touch.h" namespace ax { diff --git a/core/base/EventTouch.h b/axmol/base/EventTouch.h similarity index 98% rename from core/base/EventTouch.h rename to axmol/base/EventTouch.h index 9ab70d5351a7..f7de89172117 100644 --- a/core/base/EventTouch.h +++ b/axmol/base/EventTouch.h @@ -25,7 +25,7 @@ #pragma once -#include "base/Event.h" +#include "axmol/base/Event.h" #include /** diff --git a/core/base/EventType.h b/axmol/base/EventType.h similarity index 86% rename from core/base/EventType.h rename to axmol/base/EventType.h index 52422660d8ee..a8ad9dc9c6c7 100644 --- a/core/base/EventType.h +++ b/axmol/base/EventType.h @@ -32,27 +32,27 @@ */ // The application will come to foreground. -// This message is posted in core/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp. +// This message is posted in axmol/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp. #define EVENT_COME_TO_FOREGROUND "event_come_to_foreground" // The renderer[android:GLSurfaceView.Renderer WP8:Cocos2dRenderer] was recreated. // This message is used for reloading resources before renderer is recreated on Android/WP8. -// This message is posted in core/platform/android/javaactivity.cpp and +// This message is posted in axmol/platform/android/javaactivity.cpp and // cocos\platform\wp8-xaml\cpp\Cocos2dRenderer.cpp. #define EVENT_RENDERER_RECREATED "event_renderer_recreated" // The application will come to background. // This message is used for doing something before coming to background, such as save RenderTexture. -// This message is posted in core/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp and +// This message is posted in axmol/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp and // cocos\platform\wp8-xaml\cpp\Cocos2dRenderer.cpp. #define EVENT_COME_TO_BACKGROUND "event_come_to_background" // The application will be restarted. // This message is used for notifying application code of a pending application restart. -// This message is posted in core/platform/android/javaactivity.cpp +// This message is posted in axmol/platform/android/javaactivity.cpp #define EVENT_APP_RESTARTING "event_app_restarting" // The application has made a warm start, creating a new Activity, Surface View and Renderer // This message is used for notifying application code of a warm start. -// This message is posted in core/platform/android/javaactivity.cpp +// This message is posted in axmol/platform/android/javaactivity.cpp #define EVENT_APP_WARM_START "event_app_warm_start" diff --git a/core/base/FPSImages.cpp b/axmol/base/FPSImages.cpp similarity index 99% rename from core/base/FPSImages.cpp rename to axmol/base/FPSImages.cpp index 277412a5d519..4a2ac18a0340 100644 --- a/core/base/FPSImages.cpp +++ b/axmol/base/FPSImages.cpp @@ -25,7 +25,7 @@ * THE SOFTWARE. */ -#include "base/FPSImages.h" +#include "axmol/base/FPSImages.h" #if !AX_STRIP_FPS diff --git a/core/base/FPSImages.h b/axmol/base/FPSImages.h similarity index 97% rename from core/base/FPSImages.h rename to axmol/base/FPSImages.h index c28d57cf772c..fe9d52fb9f60 100644 --- a/core/base/FPSImages.h +++ b/axmol/base/FPSImages.h @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" /// @cond DO_NOT_SHOW diff --git a/core/base/GameController.h b/axmol/base/GameController.h similarity index 91% rename from core/base/GameController.h rename to axmol/base/GameController.h index 8e182f04f4b4..214fc97d578c 100644 --- a/core/base/GameController.h +++ b/axmol/base/GameController.h @@ -27,6 +27,6 @@ /// @cond DO_NOT_SHOW -#include "base/Controller.h" -#include "base/EventController.h" -#include "base/EventListenerController.h" +#include "axmol/base/Controller.h" +#include "axmol/base/EventController.h" +#include "axmol/base/EventListenerController.h" diff --git a/core/base/IMEDelegate.h b/axmol/base/IMEDelegate.h similarity index 98% rename from core/base/IMEDelegate.h rename to axmol/base/IMEDelegate.h index 013b50ece31a..16c514a9ed27 100644 --- a/core/base/IMEDelegate.h +++ b/axmol/base/IMEDelegate.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once #include -#include "math/Math.h" -#include "base/EventKeyboard.h" +#include "axmol/math/Math.h" +#include "axmol/base/EventKeyboard.h" /** * @addtogroup base diff --git a/core/base/IMEDispatcher.cpp b/axmol/base/IMEDispatcher.cpp similarity index 99% rename from core/base/IMEDispatcher.cpp rename to axmol/base/IMEDispatcher.cpp index c9090cb1fae5..68ed1c3b3336 100644 --- a/core/base/IMEDispatcher.cpp +++ b/axmol/base/IMEDispatcher.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/IMEDispatcher.h" +#include "axmol/base/IMEDispatcher.h" #include diff --git a/core/base/IMEDispatcher.h b/axmol/base/IMEDispatcher.h similarity index 99% rename from core/base/IMEDispatcher.h rename to axmol/base/IMEDispatcher.h index 43725206084b..1ff552e419b9 100644 --- a/core/base/IMEDispatcher.h +++ b/axmol/base/IMEDispatcher.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "base/IMEDelegate.h" +#include "axmol/base/IMEDelegate.h" /** * @addtogroup base diff --git a/core/base/JobSystem.cpp b/axmol/base/JobSystem.cpp similarity index 99% rename from core/base/JobSystem.cpp rename to axmol/base/JobSystem.cpp index f55f87d30862..162092ac00d0 100644 --- a/core/base/JobSystem.cpp +++ b/axmol/base/JobSystem.cpp @@ -23,8 +23,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/JobSystem.h" -#include "base/Director.h" +#include "axmol/base/JobSystem.h" +#include "axmol/base/Director.h" #include "yasio/thread_name.hpp" #include diff --git a/core/base/JobSystem.h b/axmol/base/JobSystem.h similarity index 97% rename from core/base/JobSystem.h rename to axmol/base/JobSystem.h index 30d3ce90a4ff..fa68ec2d974f 100644 --- a/core/base/JobSystem.h +++ b/axmol/base/JobSystem.h @@ -39,8 +39,8 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). #include #include #include -#include "base/Config.h" -#include "platform/PlatformDefine.h" +#include "axmol/base/Config.h" +#include "axmol/platform/PlatformDefine.h" namespace ax { diff --git a/core/base/JsonWriter.h b/axmol/base/JsonWriter.h similarity index 50% rename from core/base/JsonWriter.h rename to axmol/base/JsonWriter.h index 3fbf020fd0ed..901f68624a29 100644 --- a/core/base/JsonWriter.h +++ b/axmol/base/JsonWriter.h @@ -22,7 +22,7 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - A simple wrapper dotnet Utf8JsonWriter like API style of rapidjson + A simple JsonWriter implementation like dotnet Utf8JsonWriter API. ****************************************************************************/ @@ -30,73 +30,46 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). #include -#include "rapidjson/writer.h" -#include "rapidjson/prettywriter.h" +#include "yasio/byte_buffer.hpp" +#include "axmol/base/format.h" namespace ax { struct JsonWriterOptions { - char indentChar = ' '; - int indentCharCount = 2; - rapidjson::PrettyFormatOptions formatOptions = rapidjson::kFormatDefault; -}; - -template -struct JsonWriterImpl -{ - using type = rapidjson::PrettyWriter; -}; - -template <> -struct JsonWriterImpl -{ - using type = rapidjson::Writer; + char indentChar = ' '; + int indentCharCount = 2; + int initialBufferSize = 128; }; template class JsonWriter { - using writer_type = typename JsonWriterImpl<_Pretty>::type; - public: JsonWriter() { - new (static_cast(_writerHold)) writer_type(_buffer); setOptions(JsonWriterOptions{}); + _buffer.reserve(_options.initialBufferSize); } - ~JsonWriter() { writer().~writer_type(); } + ~JsonWriter() {} explicit JsonWriter(const JsonWriterOptions& options) { setOptions(options); } - void setOptions(const JsonWriterOptions& options) - { - if constexpr (_Pretty) - { - prettyWriter().SetIndent(options.indentChar, options.indentCharCount); - prettyWriter().SetFormatOptions(options.formatOptions); - } - } + void setOptions(const JsonWriterOptions& options) { _options = options; } - void writePropertyName(std::string_view propertyName) - { - writer().Key(propertyName.data(), static_cast(propertyName.length()), false); - } + explicit operator std::string_view() const { return std::string_view{_buffer.data(), _buffer.size()}; } #pragma region write values - void writeBoolValue(bool value) { writer().Bool(value); } - void writeNumberValue(int value) { writer().Int(value); } - void writeNumberValue(long long value) { writer().Int64(value); } - void writeNumberValue(double value) { writer().Double(value); } - void writeStringValue(std::string_view value) - { - writer().String(value.data(), static_cast(value.length())); - } + void writeBoolValue(bool value) { writeUnquoteValue(value); } + void writeNumberValue(int value) { writeUnquoteValue(value); } + void writeNumberValue(long long value) { writeUnquoteValue(value); } + void writeNumberValue(double value) { writeUnquoteValue(value); } + void writeNullValue() { writeUnquoteValue("null"sv); } - void writeNullValue() { writer().Null(); } + void writeStringValue(std::string_view value) { writeQuoteValue(value); } - template - void writeNumberValues(Intty (&values)[_N]) + template + void writeNumberValues(_Nty (&values)[_N]) { for (auto v : values) writeNumberValue(v); @@ -154,21 +127,108 @@ class JsonWriter writePropertyName(propertyName); writeStartObject(); } - void writeStartArray() { writer().StartArray(); } - void writeEndArray() { writer().EndArray(); } - void writeStartObject() { writer().StartObject(); } - void writeEndObject() { writer().EndObject(); } + void writeStartArray() { writeStartCollection('['); } + void writeEndArray() { writeEndCollection(']'); } + + void writeStartObject() { writeStartCollection('{'); } + void writeEndObject() { writeEndCollection('}'); } #pragma endregion - explicit operator std::string_view() { return std::string_view{_buffer.GetString(), _buffer.GetLength()}; } + void writePropertyName(std::string_view propertyName) + { + if constexpr (_Pretty) + { + fillIndentChars(); + _pendingValue = true; + } + _buffer += '"'; + _buffer += propertyName; + _buffer += "\":"sv; + if constexpr (_Pretty) + _buffer += _options.indentChar; + } protected: - inline writer_type& writer() { return *reinterpret_cast(&_writerHold[0]); } - inline JsonWriterImpl::type& prettyWriter() + void writeQuoteValue(const std::string_view& value) { - return *reinterpret_cast::type*>(&_writerHold[0]); + if constexpr (_Pretty) + if (!_pendingValue) + fillIndentChars(); + + _buffer += '"'; + _buffer += value; + _buffer += "\","sv; + if constexpr (_Pretty) + _buffer += '\n'; + + _pendingValue = false; } - rapidjson::StringBuffer _buffer; - uint8_t _writerHold[sizeof(writer_type)]; + template + void writeUnquoteValue(const _Ty& value) + { + if constexpr (_Pretty) + if (!_pendingValue) + fillIndentChars(); + + fmt::vformat_to(std::back_inserter(_buffer), "{},", fmt::make_format_args(value)); + if constexpr (_Pretty) + _buffer += '\n'; + + _pendingValue = false; + } + + void writeStartCollection(const char startChar) + { + if constexpr (_Pretty) + if (!_pendingValue) + fillIndentChars(); + + ++_level; + + _buffer += startChar; + if constexpr (_Pretty) + _buffer += '\n'; + + _pendingValue = false; + } + + void writeEndCollection(const char termChar) + { + if (_buffer.empty()) + return; + + --_level; + + if constexpr (_Pretty) + { + if (_buffer.back() == '\n') + _buffer.pop_back(); // pop '\n' + } + if (_buffer.back() == ',') + _buffer.pop_back(); + if constexpr (_Pretty) + { + _buffer += '\n'; + fillIndentChars(); + } + _buffer += termChar; + + if (_level != 0) + _buffer += ','; + if constexpr (_Pretty) + _buffer += '\n'; + } + + void fillIndentChars() + { + if constexpr (_Pretty) + if (_level) + _buffer.expand(_level * _options.indentCharCount, _options.indentChar); + } + + yasio::sbyte_buffer _buffer; + uint16_t _level{0}; + bool _pendingValue{false}; + JsonWriterOptions _options; }; } // namespace ax diff --git a/core/base/Logging.cpp b/axmol/base/Logging.cpp similarity index 94% rename from core/base/Logging.cpp rename to axmol/base/Logging.cpp index 0c1e3a4ab91f..80cdbda29a0c 100644 --- a/core/base/Logging.cpp +++ b/axmol/base/Logging.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Logging.h" +#include "axmol/base/Logging.h" #include "yasio/utils.hpp" #include "fmt/color.h" @@ -231,18 +231,4 @@ AX_DLL void writeLog(LogItem& item, const char* tag) # endif #endif } -#ifndef AX_CORE_PROFILE -AX_API void print(const char* format, ...) -{ - va_list args; - - va_start(args, format); - auto message = StringUtils::vformat(format, args); - va_end(args); - - if (!message.empty()) - outputLog(LogItem::vformat(FMT_COMPILE("{}{}\n"), preprocessLog(LogItem{LogLevel::Silent}), message), - "axmol debug info"); } -#endif -} // namespace ax diff --git a/core/base/Logging.h b/axmol/base/Logging.h similarity index 94% rename from core/base/Logging.h rename to axmol/base/Logging.h index 1eeb00df213f..7c6d410b2af1 100644 --- a/core/base/Logging.h +++ b/axmol/base/Logging.h @@ -24,8 +24,8 @@ #pragma once -#include "base/bitmask.h" -#include "platform/PlatformMacros.h" +#include "axmol/base/bitmask.h" +#include "axmol/platform/PlatformMacros.h" #include "fmt/compile.h" @@ -160,12 +160,5 @@ inline void printLogT(_FmtType&& fmt, LogItem&& item, _Types&&... args) #define AXLOGW(fmtOrMsg, ...) AXLOG_WITH_LEVEL(ax::LogLevel::Warn, fmtOrMsg, ##__VA_ARGS__) #define AXLOGE(fmtOrMsg, ...) AXLOG_WITH_LEVEL(ax::LogLevel::Error, fmtOrMsg, ##__VA_ARGS__) -#define AXLOGT AXLOGV - -#ifndef AX_CORE_PROFILE -/** - @brief Output Debug message. - */ -/* AX_DEPRECATED(2.1)*/ AX_API void print(const char* format, ...) AX_FORMAT_PRINTF(1, 2); // use AXLOGD instead -#endif -} // namespace ax +#define AXLOGT AXLOGV +} diff --git a/core/base/Macros.h b/axmol/base/Macros.h similarity index 98% rename from core/base/Macros.h rename to axmol/base/Macros.h index cd51a15ff08c..262152423145 100644 --- a/core/base/Macros.h +++ b/axmol/base/Macros.h @@ -33,11 +33,11 @@ THE SOFTWARE. # define _USE_MATH_DEFINES #endif -#include "base/Logging.h" -#include "platform/StdC.h" +#include "axmol/base/Logging.h" +#include "axmol/platform/StdC.h" #ifndef AXASSERT -# if _AX_DEBUG > 0 +# if defined(_AX_DEBUG) && _AX_DEBUG > 0 # if AX_ENABLE_SCRIPT_BINDING extern bool AX_DLL ax_assert_script_compatible(const char* msg); # define AXASSERT(cond, msg) \ @@ -62,9 +62,9 @@ extern bool AX_DLL ax_assert_script_compatible(const char* msg); # define CCAssert AXASSERT #endif // AXASSERT -#include "base/Config.h" +#include "axmol/base/Config.h" -#include "base/Random.h" +#include "axmol/base/Random.h" #define AX_HALF_PI (M_PI * 0.5f) @@ -96,8 +96,8 @@ extern bool AX_DLL ax_assert_script_compatible(const char* msg); /** @def AX_BLEND_SRC default gl blend src function. Compatible with premultiplied alpha images. */ -#define AX_BLEND_SRC ax::backend::BlendFactor::ONE -#define AX_BLEND_DST ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA +#define AX_BLEND_SRC ax::rhi::BlendFactor::ONE +#define AX_BLEND_DST ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA /** @def AX_NODE_DRAW_SETUP [DEPRECATED] Helpful macro that setups the GL server state, the correct GL program and sets the Model View Projection matrix diff --git a/core/base/Map.h b/axmol/base/Map.h similarity index 99% rename from core/base/Map.h rename to axmol/base/Map.h index bc3b191ab82b..b5026018f973 100644 --- a/core/base/Map.h +++ b/axmol/base/Map.h @@ -28,8 +28,8 @@ #define USE_STD_UNORDERED_MAP 1 #define USE_ROBIN_MAP 1 -#include "base/Macros.h" -#include "base/Object.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Object.h" #include #if USE_STD_UNORDERED_MAP diff --git a/core/base/NS.cpp b/axmol/base/NS.cpp similarity index 90% rename from core/base/NS.cpp rename to axmol/base/NS.cpp index 1e09bd01f495..f20c2b90e407 100644 --- a/core/base/NS.cpp +++ b/axmol/base/NS.cpp @@ -23,13 +23,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/NS.h" +#include "axmol/base/NS.h" #include #include #include #include -#include "base/Utils.h" +#include "axmol/base/Utils.h" using namespace std; @@ -137,10 +137,10 @@ Rect RectFromString(std::string_view str) strArray sizeInfo; AX_BREAK_IF(!splitWithForm(sizeStr, sizeInfo)); - float x = (float)utils::atof(pointInfo[0].c_str()); - float y = (float)utils::atof(pointInfo[1].c_str()); - float width = (float)utils::atof(sizeInfo[0].c_str()); - float height = (float)utils::atof(sizeInfo[1].c_str()); + float x = (float)utils::atof(pointInfo[0]); + float y = (float)utils::atof(pointInfo[1]); + float width = (float)utils::atof(sizeInfo[0]); + float height = (float)utils::atof(sizeInfo[1]); result = Rect(x, y, width, height); } while (0); @@ -157,8 +157,8 @@ Vec2 PointFromString(std::string_view str) strArray strs; AX_BREAK_IF(!splitWithForm(str, strs)); - float x = (float)utils::atof(strs[0].c_str()); - float y = (float)utils::atof(strs[1].c_str()); + float x = (float)utils::atof(strs[0]); + float y = (float)utils::atof(strs[1]); ret.set(x, y); } while (0); @@ -175,8 +175,8 @@ Vec2 SizeFromString(std::string_view pszContent) strArray strs; AX_BREAK_IF(!splitWithForm(pszContent, strs)); - float width = (float)utils::atof(strs[0].c_str()); - float height = (float)utils::atof(strs[1].c_str()); + float width = (float)utils::atof(strs[0]); + float height = (float)utils::atof(strs[1]); ret = Vec2(width, height); } while (0); diff --git a/core/base/NS.h b/axmol/base/NS.h similarity index 99% rename from core/base/NS.h rename to axmol/base/NS.h index 57c2a63b7ca9..bd7f9449b246 100644 --- a/core/base/NS.h +++ b/axmol/base/NS.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "math/Math.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/core/base/NinePatchImageParser.cpp b/axmol/base/NinePatchImageParser.cpp similarity index 95% rename from core/base/NinePatchImageParser.cpp rename to axmol/base/NinePatchImageParser.cpp index ea09fa3d4c5f..d1009afec261 100644 --- a/core/base/NinePatchImageParser.cpp +++ b/axmol/base/NinePatchImageParser.cpp @@ -22,9 +22,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/NinePatchImageParser.h" -#include "platform/Image.h" -#include "base/Director.h" +#include "axmol/base/NinePatchImageParser.h" +#include "axmol/platform/Image.h" +#include "axmol/base/Director.h" namespace ax { @@ -36,14 +36,14 @@ NinePatchImageParser::NinePatchImageParser() : _image(nullptr), _imageFrame(Rect NinePatchImageParser::NinePatchImageParser(Image* image) : _image(image), _imageFrame(Rect::ZERO), _isRotated(false) { this->_imageFrame = Rect(0, 0, image->getWidth(), image->getHeight()); - AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8, + AXASSERT(image->getPixelFormat() == rhi::PixelFormat::RGBA8, "unsupported format, currently only supports rgba8888"); } NinePatchImageParser::NinePatchImageParser(Image* image, const Rect& frame, bool rotated) : _image(image), _imageFrame(frame), _isRotated(rotated) { - AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8, + AXASSERT(image->getPixelFormat() == rhi::PixelFormat::RGBA8, "unsupported format, currently only supports rgba8888"); } @@ -174,7 +174,7 @@ Rect NinePatchImageParser::parseCapInset() const void NinePatchImageParser::setSpriteFrameInfo(Image* image, const ax::Rect& frameRect, bool rotated) { this->_image = image; - AXASSERT(image->getPixelFormat() == backend::PixelFormat::RGBA8, + AXASSERT(image->getPixelFormat() == rhi::PixelFormat::RGBA8, "unsupported format, currently only supports rgba8888"); this->_imageFrame = frameRect; this->_isRotated = rotated; diff --git a/core/base/NinePatchImageParser.h b/axmol/base/NinePatchImageParser.h similarity index 98% rename from core/base/NinePatchImageParser.h rename to axmol/base/NinePatchImageParser.h index 40bc32e68c61..a76e24777ec6 100644 --- a/core/base/NinePatchImageParser.h +++ b/axmol/base/NinePatchImageParser.h @@ -24,8 +24,8 @@ ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" -#include "math/Math.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/core/base/Object.cpp b/axmol/base/Object.cpp similarity index 97% rename from core/base/Object.cpp rename to axmol/base/Object.cpp index e95cd1fc83d4..98c305617394 100644 --- a/core/base/Object.cpp +++ b/axmol/base/Object.cpp @@ -25,10 +25,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Object.h" -#include "base/AutoreleasePool.h" -#include "base/Macros.h" -#include "base/ScriptSupport.h" +#include "axmol/base/Object.h" +#include "axmol/base/AutoreleasePool.h" +#include "axmol/base/Macros.h" +#include "axmol/base/ScriptSupport.h" #if AX_OBJECT_LEAK_DETECTION # include // std::find diff --git a/core/base/Object.h b/axmol/base/Object.h similarity index 98% rename from core/base/Object.h rename to axmol/base/Object.h index 842cd7f9ac15..dfc4c3812f1d 100644 --- a/core/base/Object.h +++ b/axmol/base/Object.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" -#include "base/Config.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Config.h" #define AX_OBJECT_LEAK_DETECTION 0 diff --git a/core/base/ObjectFactory.cpp b/axmol/base/ObjectFactory.cpp similarity index 98% rename from core/base/ObjectFactory.cpp rename to axmol/base/ObjectFactory.cpp index 3a1dcd4882ab..e403b658a09c 100644 --- a/core/base/ObjectFactory.cpp +++ b/axmol/base/ObjectFactory.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ #include -#include "base/ObjectFactory.h" +#include "axmol/base/ObjectFactory.h" namespace ax { diff --git a/core/base/ObjectFactory.h b/axmol/base/ObjectFactory.h similarity index 96% rename from core/base/ObjectFactory.h rename to axmol/base/ObjectFactory.h index 021a9fd7f8ad..aa990adb6b3c 100644 --- a/core/base/ObjectFactory.h +++ b/axmol/base/ObjectFactory.h @@ -28,8 +28,8 @@ THE SOFTWARE. #include #include #include -#include "base/Object.h" -#include "platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/base/Profiling.cpp b/axmol/base/Profiling.cpp similarity index 99% rename from core/base/Profiling.cpp rename to axmol/base/Profiling.cpp index fb6f4e87afd2..32afc455828c 100644 --- a/core/base/Profiling.cpp +++ b/axmol/base/Profiling.cpp @@ -25,7 +25,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Profiling.h" +#include "axmol/base/Profiling.h" using namespace std; diff --git a/core/base/Profiling.h b/axmol/base/Profiling.h similarity index 97% rename from core/base/Profiling.h rename to axmol/base/Profiling.h index 62112ac64136..764f27c2a99b 100644 --- a/core/base/Profiling.h +++ b/axmol/base/Profiling.h @@ -32,9 +32,9 @@ THE SOFTWARE. #include #include -#include "base/Config.h" -#include "base/Object.h" -#include "base/Map.h" +#include "axmol/base/Config.h" +#include "axmol/base/Object.h" +#include "axmol/base/Map.h" namespace ax { diff --git a/core/base/Properties.cpp b/axmol/base/Properties.cpp similarity index 96% rename from core/base/Properties.cpp rename to axmol/base/Properties.cpp index d10081b1e064..d453b0914db7 100644 --- a/core/base/Properties.cpp +++ b/axmol/base/Properties.cpp @@ -21,19 +21,19 @@ This file was modified to fit the cocos2d-x project */ -#include "base/Properties.h" +#include "axmol/base/Properties.h" #include -#include "platform/PlatformMacros.h" -#include "platform/FileUtils.h" -#include "math/Vec2.h" -#include "math/Vec3.h" -#include "math/Vec4.h" -#include "math/Mat4.h" -#include "math/Quaternion.h" -#include "base/UTF8.h" -#include "base/Data.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/math/Vec2.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Vec4.h" +#include "axmol/math/Mat4.h" +#include "axmol/math/Quaternion.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Data.h" using namespace ax; @@ -955,12 +955,7 @@ bool Properties::getQuaternionFromAxisAngle(const char* name, Quaternion* out) c return parseAxisAngle(getString(name), out); } -bool Properties::getColor(const char* name, Vec3* out) const -{ - return parseColor(getString(name), out); -} - -bool Properties::getColor(const char* name, Vec4* out) const +bool Properties::getColor(const char* name, Color* out) const { return parseColor(getString(name), out); } @@ -1261,39 +1256,7 @@ bool Properties::parseAxisAngle(const char* str, Quaternion* out) return false; } -bool Properties::parseColor(const char* str, Vec3* out) -{ - if (str) - { - if (strlen(str) == 7 && str[0] == '#') - { - // Read the string into an int as hex. - unsigned int color; - if (sscanf(str + 1, "%x", &color) == 1) - { - if (out) - out->set(Vec3::fromColor(color)); - return true; - } - else - { - // Invalid format - AXLOGW("Error attempting to parse property as an RGB color: {}", str); - } - } - else - { - // Not a color string. - AXLOGW("Error attempting to parse property as an RGB color (not specified as a color string): {}", str); - } - } - - if (out) - out->set(0.0f, 0.0f, 0.0f); - return false; -} - -bool Properties::parseColor(const char* str, Vec4* out) +bool Properties::parseColor(const char* str, Color* out) { if (str) { @@ -1304,7 +1267,7 @@ bool Properties::parseColor(const char* str, Vec4* out) if (sscanf(str + 1, "%x", &color) == 1) { if (out) - out->set(Vec4::fromColor(color)); + out->set(Color::fromHex(color)); return true; } else diff --git a/core/base/Properties.h b/axmol/base/Properties.h similarity index 93% rename from core/base/Properties.h rename to axmol/base/Properties.h index e01c74965eb1..2d184b1d2535 100644 --- a/core/base/Properties.h +++ b/axmol/base/Properties.h @@ -28,11 +28,11 @@ #include #include -#include "renderer/Texture2D.h" -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "base/Types.h" -#include "base/Vector.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Vector.h" namespace ax { @@ -391,20 +391,6 @@ class AX_DLL Properties */ bool getQuaternionFromAxisAngle(const char* name, Quaternion* out) const; - /** - * Interpret the value of the given property as an RGB color in hex and write this color to a Vector3. - * E.g. 0xff0000 represents red and sets the vector to (1, 0, 0). - * If the property does not exist, out will be set to Vector3(0.0f, 0.0f, 0.0f). - * If the property exists but could not be scanned, an error will be logged and out will be set - * to Vector3(0.0f, 0.0f, 0.0f). - * - * @param name The name of the property to interpret, or NULL to return the current property's value. - * @param out The vector to set to this property's interpreted value. - * - * @return True on success, false if the property does not exist or could not be scanned. - */ - bool getColor(const char* name, Vec3* out) const; - /** * Interpret the value of the given property as an RGBA color in hex and write this color to a Vector4. * E.g. 0xff0000ff represents opaque red and sets the vector to (1, 0, 0, 1). @@ -417,7 +403,7 @@ class AX_DLL Properties * * @return True on success, false if the property does not exist or could not be scanned. */ - bool getColor(const char* name, Vec4* out) const; + bool getColor(const char* name, Color* out) const; /** * Gets the file path for the given property if the file exists. @@ -506,16 +492,6 @@ class AX_DLL Properties */ static bool parseAxisAngle(const char* str, Quaternion* out); - /** - * Attempts to parse the specified string as an RGB color value. - * - * @param str The string to parse. - * @param out The value to populate if successful. - * - * @return True if a valid RGB color was parsed, false otherwise. - */ - static bool parseColor(const char* str, Vec3* out); - /** * Attempts to parse the specified string as an RGBA color value. * @@ -524,7 +500,7 @@ class AX_DLL Properties * * @return True if a valid RGBA color was parsed, false otherwise. */ - static bool parseColor(const char* str, Vec4* out); + static bool parseColor(const char* str, Color* out); private: /** diff --git a/core/base/Protocols.h b/axmol/base/Protocols.h similarity index 93% rename from core/base/Protocols.h rename to axmol/base/Protocols.h index 2581bdde8d17..e5a751e4e2b5 100644 --- a/core/base/Protocols.h +++ b/axmol/base/Protocols.h @@ -31,8 +31,8 @@ THE SOFTWARE. #include -#include "base/Types.h" -#include "renderer/Texture2D.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/Texture2D.h" namespace ax { @@ -48,26 +48,26 @@ class AX_DLL __RGBAProtocol /** * Changes the color with R,G,B bytes * - * @param color Example: Color3B(255,100,0) means R=255, G=100, B=0 + * @param color Example: Color32(255,100,0) means R=255, G=100, B=0 * @lua NA */ - virtual void setColor(const Color3B& color) = 0; + virtual void setColor(const Color32& color) = 0; /** * Returns color that is currently used. * - * @return The Color3B contains R,G,B bytes. + * @return The Color32 contains R,G,B bytes. * @lua NA */ - virtual const Color3B& getColor() const = 0; + virtual const Color32& getColor() const = 0; /** * Returns the displayed color. * - * @return The Color3B contains R,G,B bytes. + * @return The Color32 contains R,G,B bytes. * @lua NA */ - virtual const Color3B& getDisplayedColor() const = 0; + virtual const Color32& getDisplayedColor() const = 0; /** * Returns the displayed opacity. @@ -131,7 +131,7 @@ class AX_DLL __RGBAProtocol * recursive method that updates display color * @lua NA */ - virtual void updateDisplayedColor(const Color3B& color) = 0; + virtual void updateDisplayedColor(const Color32& color) = 0; /** * whether or not opacity should be propagated to its children. diff --git a/core/base/Random.cpp b/axmol/base/Random.cpp similarity index 98% rename from core/base/Random.cpp rename to axmol/base/Random.cpp index 3eb4f417699f..9fb1ac155cf8 100644 --- a/core/base/Random.cpp +++ b/axmol/base/Random.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Random.h" +#include "axmol/base/Random.h" #ifdef EMSCRIPTEN # include diff --git a/core/base/Random.h b/axmol/base/Random.h similarity index 98% rename from core/base/Random.h rename to axmol/base/Random.h index b1d63c4a2803..3a10a9c656f1 100644 --- a/core/base/Random.h +++ b/axmol/base/Random.h @@ -29,7 +29,7 @@ THE SOFTWARE. #include #include -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" /** * @addtogroup base diff --git a/core/base/RefPtr.h b/axmol/base/RefPtr.h similarity index 99% rename from core/base/RefPtr.h rename to axmol/base/RefPtr.h index 2c1470956b91..c3364c7da961 100644 --- a/core/base/RefPtr.h +++ b/axmol/base/RefPtr.h @@ -28,8 +28,8 @@ #pragma once /// @cond DO_NOT_SHOW -#include "base/Object.h" -#include "base/Macros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Macros.h" #include #include diff --git a/core/base/Scheduler.cpp b/axmol/base/Scheduler.cpp similarity index 99% rename from core/base/Scheduler.cpp rename to axmol/base/Scheduler.cpp index db1e8916e8d0..45066eedf3cd 100644 --- a/core/base/Scheduler.cpp +++ b/axmol/base/Scheduler.cpp @@ -27,10 +27,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Scheduler.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "base/ScriptSupport.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/base/ScriptSupport.h" namespace ax { diff --git a/core/base/Scheduler.h b/axmol/base/Scheduler.h similarity index 96% rename from core/base/Scheduler.h rename to axmol/base/Scheduler.h index 73a239815c73..5151bb7d2e4f 100644 --- a/core/base/Scheduler.h +++ b/axmol/base/Scheduler.h @@ -32,9 +32,9 @@ THE SOFTWARE. #include #include #include -#include "base/axstd.h" -#include "base/Object.h" -#include "base/Vector.h" +#include "axmol/base/axstd.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" namespace ax { @@ -91,8 +91,8 @@ class AX_DLL TimerTargetSelector : public Timer SEL_SCHEDULE getSelector() const { return _selector; } - virtual void trigger(float dt) override; - virtual void cancel() override; + void trigger(float dt) override; + void cancel() override; protected: Object* _target; @@ -117,8 +117,8 @@ class AX_DLL TimerTargetCallback : public Timer const ccSchedulerFunc& getCallback() const { return _callback; } std::string_view getKey() const { return _key; } - virtual void trigger(float dt) override; - virtual void cancel() override; + void trigger(float dt) override; + void cancel() override; protected: void* _target; @@ -134,8 +134,8 @@ class AX_DLL TimerScriptHandler : public Timer bool initWithScriptHandler(int handler, float seconds); int getScriptHandler() const { return _scriptHandler; } - virtual void trigger(float dt) override; - virtual void cancel() override; + void trigger(float dt) override; + void cancel() override; private: int _scriptHandler; @@ -464,12 +464,7 @@ class AX_DLL Scheduler : public Object @since axmol */ void runOnAxmolThread(std::function action); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) void performFunctionInCocosThread(std::function action) - { - runOnAxmolThread(std::move(action)); - } -#endif + /** * Remove all pending functions queued to be performed with Scheduler::runOnAxmolThread * Functions unscheduled in this manner will not be executed @@ -477,9 +472,6 @@ class AX_DLL Scheduler : public Object * @since v3.14 */ void removeAllPendingActions(); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) void removeAllFunctionsToBePerformedInCocosThread() { removeAllPendingActions(); } -#endif protected: /** Schedules the 'callback' function for a given target with a given priority. The 'callback' selector will be called every frame. diff --git a/core/base/ScriptSupport.cpp b/axmol/base/ScriptSupport.cpp similarity index 97% rename from core/base/ScriptSupport.cpp rename to axmol/base/ScriptSupport.cpp index 2782e8870fec..3940ae0f6842 100644 --- a/core/base/ScriptSupport.cpp +++ b/axmol/base/ScriptSupport.cpp @@ -24,12 +24,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/ScriptSupport.h" +#include "axmol/base/ScriptSupport.h" #if AX_ENABLE_SCRIPT_BINDING -# include "base/Scheduler.h" -# include "2d/Node.h" +# include "axmol/base/Scheduler.h" +# include "axmol/2d/Node.h" bool AX_DLL ax_assert_script_compatible(const char* msg) { diff --git a/core/base/ScriptSupport.h b/axmol/base/ScriptSupport.h similarity index 99% rename from core/base/ScriptSupport.h rename to axmol/base/ScriptSupport.h index 86d26962dd46..afdfce52fcda 100644 --- a/core/base/ScriptSupport.h +++ b/axmol/base/ScriptSupport.h @@ -26,11 +26,11 @@ #pragma once -#include "base/Config.h" -#include "platform/Common.h" -#include "base/Touch.h" -#include "base/EventTouch.h" -#include "base/EventKeyboard.h" +#include "axmol/base/Config.h" +#include "axmol/platform/Common.h" +#include "axmol/base/Touch.h" +#include "axmol/base/EventTouch.h" +#include "axmol/base/EventKeyboard.h" #include #include #include diff --git a/core/base/SimpleTimer.cpp b/axmol/base/SimpleTimer.cpp similarity index 69% rename from core/base/SimpleTimer.cpp rename to axmol/base/SimpleTimer.cpp index f03062ad067b..63fe45437690 100644 --- a/core/base/SimpleTimer.cpp +++ b/axmol/base/SimpleTimer.cpp @@ -1,7 +1,32 @@ -#include "SimpleTimer.h" +/**************************************************************************** +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + +https://axmol.dev/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN false EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "axmol/base/SimpleTimer.h" #include "yasio/object_pool.hpp" #include "yasio/ref_ptr.hpp" -#include "axmol.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" #define STIMER_DEFINE_REFERENCE_CLASS \ private: \ diff --git a/core/base/SimpleTimer.h b/axmol/base/SimpleTimer.h similarity index 94% rename from core/base/SimpleTimer.h rename to axmol/base/SimpleTimer.h index 1b087d4f277e..acaf31e00696 100644 --- a/core/base/SimpleTimer.h +++ b/axmol/base/SimpleTimer.h @@ -3,7 +3,7 @@ // #pragma once -#include "base/Macros.h" +#include "axmol/base/Macros.h" #include namespace ax diff --git a/core/base/StencilStateManager.cpp b/axmol/base/StencilStateManager.cpp similarity index 77% rename from core/base/StencilStateManager.cpp rename to axmol/base/StencilStateManager.cpp index 542663725aa7..fb301c56c726 100644 --- a/core/base/StencilStateManager.cpp +++ b/axmol/base/StencilStateManager.cpp @@ -23,11 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/StencilStateManager.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/StencilStateManager.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" namespace ax { @@ -36,13 +36,13 @@ int StencilStateManager::s_layer = -1; StencilStateManager::StencilStateManager() { - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_UCOLOR); - _programState = new backend::ProgramState(program); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = _customCommand.getPipelineDesc(); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_UCOLOR); + _programState = new rhi::ProgramState(program); + pipelineDesc.programState = _programState; - _mvpMatrixLocaiton = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); - _colorUniformLocation = pipelineDescriptor.programState->getUniformLocation("u_color"); + _mvpMatrixLocaiton = pipelineDesc.programState->getUniformLocation("u_MVPMatrix"); + _colorUniformLocation = pipelineDesc.programState->getUniformLocation("u_color"); Vec2 vertices[4] = {Vec2(-1.0f, -1.0f), Vec2(1.0f, -1.0f), Vec2(1.0f, 1.0f), Vec2(-1.0f, 1.0f)}; _customCommand.createVertexBuffer(sizeof(Vec2), 4, CustomCommand::BufferUsage::STATIC); @@ -52,8 +52,8 @@ StencilStateManager::StencilStateManager() _customCommand.createIndexBuffer(CustomCommand::IndexFormat::U_SHORT, 6, CustomCommand::BufferUsage::STATIC); _customCommand.updateIndexBuffer(indices, sizeof(indices)); - Color4F color(1, 1, 1, 1); - pipelineDescriptor.programState->setUniform(_colorUniformLocation, &color, sizeof(color)); + Color color(1, 1, 1, 1); + pipelineDesc.programState->setUniform(_colorUniformLocation, &color, sizeof(color)); } StencilStateManager::~StencilStateManager() @@ -117,12 +117,12 @@ void StencilStateManager::onBeforeDrawQuadCmd() // manually save the stencil state _currentStencilEnabled = renderer->getStencilTest(); _currentStencilWriteMask = renderer->getStencilWriteMask(); - _currentStencilFunc = renderer->getStencilCompareFunction(); + _currentStencilFunc = renderer->getStencilCompareFunc(); _currentStencilRef = renderer->getStencilReferenceValue(); _currentStencilReadMask = renderer->getStencilReadMask(); - _currentStencilFail = renderer->getStencilFailureOperation(); - _currentStencilPassDepthFail = renderer->getStencilPassDepthFailureOperation(); - _currentStencilPassDepthPass = renderer->getStencilDepthPassOperation(); + _currentStencilFail = renderer->getStencilFailureOp(); + _currentStencilPassDepthFail = renderer->getStencilPassDepthFailureOp(); + _currentStencilPassDepthPass = renderer->getStencilDepthPassOp(); // enable stencil use renderer->setStencilTest(true); @@ -150,18 +150,18 @@ void StencilStateManager::onBeforeDrawQuadCmd() // never draw it into the frame buffer // if not in inverted mode: set the current layer value to 0 in the stencil buffer // if in inverted mode: set the current layer value to 1 in the stencil buffer - renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, _currentLayerMask, _currentLayerMask); - renderer->setStencilOperation(!_inverted ? backend::StencilOperation::ZERO : backend::StencilOperation::REPLACE, - backend::StencilOperation::KEEP, backend::StencilOperation::KEEP); + renderer->setStencilCompareFunc(rhi::CompareFunc::NEVER, _currentLayerMask, _currentLayerMask); + renderer->setStencilOp(!_inverted ? rhi::StencilOp::ZERO : rhi::StencilOp::REPLACE, + rhi::StencilOp::KEEP, rhi::StencilOp::KEEP); } void StencilStateManager::onAfterDrawQuadCmd() { auto renderer = Director::getInstance()->getRenderer(); - renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, _currentLayerMask, _currentLayerMask); + renderer->setStencilCompareFunc(rhi::CompareFunc::NEVER, _currentLayerMask, _currentLayerMask); - renderer->setStencilOperation(!_inverted ? backend::StencilOperation::REPLACE : backend::StencilOperation::ZERO, - backend::StencilOperation::KEEP, backend::StencilOperation::KEEP); + renderer->setStencilOp(!_inverted ? rhi::StencilOp::REPLACE : rhi::StencilOp::ZERO, + rhi::StencilOp::KEEP, rhi::StencilOp::KEEP); } void StencilStateManager::onAfterDrawStencil() @@ -183,10 +183,10 @@ void StencilStateManager::onAfterDrawStencil() // draw the pixel and keep the current layer in the stencil buffer // else // do not draw the pixel but keep the current layer in the stencil buffer - renderer->setStencilCompareFunction(backend::CompareFunction::EQUAL, _mask_layer_le, _mask_layer_le); + renderer->setStencilCompareFunc(rhi::CompareFunc::EQUAL, _mask_layer_le, _mask_layer_le); - renderer->setStencilOperation(backend::StencilOperation::KEEP, backend::StencilOperation::KEEP, - backend::StencilOperation::KEEP); + renderer->setStencilOp(rhi::StencilOp::KEEP, rhi::StencilOp::KEEP, + rhi::StencilOp::KEEP); // draw (according to the stencil test function) this node and its children } @@ -198,9 +198,9 @@ void StencilStateManager::onAfterVisit() // manually restore the stencil state auto renderer = Director::getInstance()->getRenderer(); - renderer->setStencilCompareFunction(_currentStencilFunc, _currentStencilRef, _currentStencilReadMask); + renderer->setStencilCompareFunc(_currentStencilFunc, _currentStencilRef, _currentStencilReadMask); - renderer->setStencilOperation(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass); + renderer->setStencilOp(_currentStencilFail, _currentStencilPassDepthFail, _currentStencilPassDepthPass); renderer->setStencilWriteMask(_currentStencilWriteMask); if (!_currentStencilEnabled) diff --git a/core/base/StencilStateManager.h b/axmol/base/StencilStateManager.h similarity index 80% rename from core/base/StencilStateManager.h rename to axmol/base/StencilStateManager.h index 51463abcb93f..797bd44fc8f1 100644 --- a/core/base/StencilStateManager.h +++ b/axmol/base/StencilStateManager.h @@ -25,10 +25,10 @@ ****************************************************************************/ #pragma once -#include "base/Config.h" -#include "platform/PlatformMacros.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/base/Config.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" /** * @addtogroup base @@ -66,12 +66,12 @@ class AX_DLL StencilStateManager bool _currentStencilEnabled = false; unsigned int _currentStencilWriteMask = ~0; - backend::CompareFunction _currentStencilFunc = backend::CompareFunction::ALWAYS; + rhi::CompareFunc _currentStencilFunc = rhi::CompareFunc::ALWAYS; unsigned int _currentStencilRef = 0; unsigned int _currentStencilReadMask = ~0; - backend::StencilOperation _currentStencilFail = backend::StencilOperation::KEEP; - backend::StencilOperation _currentStencilPassDepthFail = backend::StencilOperation::KEEP; - backend::StencilOperation _currentStencilPassDepthPass = backend::StencilOperation::KEEP; + rhi::StencilOp _currentStencilFail = rhi::StencilOp::KEEP; + rhi::StencilOp _currentStencilPassDepthFail = rhi::StencilOp::KEEP; + rhi::StencilOp _currentStencilPassDepthPass = rhi::StencilOp::KEEP; bool _currentDepthWriteMask = true; unsigned int _mask_layer_le = 0; @@ -81,9 +81,9 @@ class AX_DLL StencilStateManager //CallbackCommand _afterDrawStencilCmd; //CallbackCommand _afterVisitCmd; - backend::UniformLocation _mvpMatrixLocaiton; - backend::UniformLocation _colorUniformLocation; - backend::ProgramState* _programState = nullptr; + rhi::UniformLocation _mvpMatrixLocaiton; + rhi::UniformLocation _colorUniformLocation; + rhi::ProgramState* _programState = nullptr; }; } diff --git a/core/base/TGAlib.cpp b/axmol/base/TGAlib.cpp similarity index 99% rename from core/base/TGAlib.cpp rename to axmol/base/TGAlib.cpp index 4e4825dd6b7d..9aca430c8980 100644 --- a/core/base/TGAlib.cpp +++ b/axmol/base/TGAlib.cpp @@ -27,9 +27,9 @@ THE SOFTWARE. #include #include -#include "base/TGAlib.h" -#include "base/Data.h" -#include "platform/FileUtils.h" +#include "axmol/base/TGAlib.h" +#include "axmol/base/Data.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/core/base/TGAlib.h b/axmol/base/TGAlib.h similarity index 98% rename from core/base/TGAlib.h rename to axmol/base/TGAlib.h index b08e2045662a..d8bfebfa7377 100644 --- a/core/base/TGAlib.h +++ b/axmol/base/TGAlib.h @@ -28,7 +28,7 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW #include "stdint.h" -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/base/Touch.cpp b/axmol/base/Touch.cpp similarity index 97% rename from core/base/Touch.cpp rename to axmol/base/Touch.cpp index 69518bf10418..f36359a57f98 100644 --- a/core/base/Touch.cpp +++ b/axmol/base/Touch.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Touch.h" -#include "base/Director.h" +#include "axmol/base/Touch.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/base/Touch.h b/axmol/base/Touch.h similarity index 98% rename from core/base/Touch.h rename to axmol/base/Touch.h index c834845afbe1..e19cac15f119 100644 --- a/core/base/Touch.h +++ b/axmol/base/Touch.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/core/base/Types.cpp b/axmol/base/Types.cpp similarity index 72% rename from core/base/Types.cpp rename to axmol/base/Types.cpp index 0db6286abcdf..8807bd5f03e6 100644 --- a/core/base/Types.cpp +++ b/axmol/base/Types.cpp @@ -26,8 +26,7 @@ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. THE SOFTWARE. ****************************************************************************/ -#include "base/Types.h" -#include "renderer/backend/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -35,11 +34,11 @@ namespace ax const std::string STD_STRING_EMPTY{}; const ssize_t AX_INVALID_INDEX = -1; -const BlendFunc BlendFunc::DISABLE = {backend::BlendFactor::ONE, backend::BlendFactor::ZERO}; -const BlendFunc BlendFunc::ALPHA_PREMULTIPLIED = {backend::BlendFactor::ONE, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}; -const BlendFunc BlendFunc::ALPHA_NON_PREMULTIPLIED = {backend::BlendFactor::SRC_ALPHA, - backend::BlendFactor::ONE_MINUS_SRC_ALPHA}; -const BlendFunc BlendFunc::ADDITIVE = {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE}; +const BlendFunc BlendFunc::DISABLE = {rhi::BlendFactor::ONE, rhi::BlendFactor::ZERO}; +const BlendFunc BlendFunc::ALPHA_PREMULTIPLIED = {rhi::BlendFactor::ONE, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}; +const BlendFunc BlendFunc::ALPHA_NON_PREMULTIPLIED = {rhi::BlendFactor::SRC_ALPHA, + rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}; +const BlendFunc BlendFunc::ADDITIVE = {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE}; } diff --git a/core/base/Types.h b/axmol/base/Types.h similarity index 67% rename from core/base/Types.h rename to axmol/base/Types.h index 6f9b88607cbe..ceb040727f3d 100644 --- a/core/base/Types.h +++ b/axmol/base/Types.h @@ -30,11 +30,9 @@ THE SOFTWARE. #include -#include "math/Math.h" -#include "base/Object.h" -#include "renderer/backend/Types.h" - -#include "Enums.h" +#include "axmol/math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/rhi/RHITypes.h" /** * @addtogroup base @@ -44,26 +42,123 @@ THE SOFTWARE. namespace ax { -/** @struct Tex2F - * A TEXCOORD composed of 2 floats: u, v - * @since v3.0 +/** + * @brief Effects used by `Label` */ -typedef Vec2 Tex2F; +enum class LabelEffect +{ + // FIXME: Covert them to bitwise. More than one effect should be supported + NORMAL, + OUTLINE, + SHADOW, + GLOW, + ITALICS, + BOLD, + UNDERLINE, + STRIKETHROUGH, + ALL +}; + +/** + * @brief Interval change reason. + */ +enum class SetIntervalReason : char +{ + BY_GAME = 0, + BY_ENGINE, + BY_SYSTEM, + BY_SCENE_CHANGE, + BY_DIRECTOR_PAUSE +}; + +/** + * @brief Texture flags. + */ +struct TextureFlag +{ + enum + { + NONE = 0, + ANTIALIAS_ENABLED = 1 << 1, + PREMULTIPLIEDALPHA = 1 << 2, + RENDERTARGET = 1 << 3, + }; +}; + +/** + * @brief Texture sampler flags. + */ +struct TextureSamplerFlag +{ + enum + { + DEFAULT = 0, + DUAL_SAMPLER = 1 << 1, + }; +}; -/** @struct PointSprite - * Vec2 Sprite component. +/** + * @brief Matrix stack type. */ -struct AX_DLL PointSprite +enum class MATRIX_STACK_TYPE { - Vec2 pos; // 8 bytes - Color4B color; // 4 bytes - float size = 0.f; // 4 bytes + /// Model view matrix stack + MATRIX_STACK_MODELVIEW, + + /// projection matrix stack + MATRIX_STACK_PROJECTION, + + /// texture matrix stack + MATRIX_STACK_TEXTURE }; +/** + * @brief Anchor presets used to position nodes in corners + */ +enum class AnchorPreset +{ + BOTTOM_LEFT = 0, + BOTTOM_CENTER = 1, + BOTTOM_RIGHT = 2, + CENTER_LEFT = 3, + CENTER = 4, + CENTER_RIGHT = 5, + TOP_LEFT = 6, + TOP_CENTER = 7, + TOP_RIGHT = 8 +}; + +/** + * Particle emission shapes. + * Supported shapes are Point, Rectangle, RectangularTorus, Circle, Torus, Cone, Cone Torus, Texture alpha emission mask + * @since axmol-1.0.0b8 + */ +enum class EmissionShapeType +{ + // Emission shape of type point + POINT, + // Emission shape of type rectangle + RECT, + // Emission shape of type rectangular torus + RECTTORUS, + // Emission shape of type circle or cone + CIRCLE, + // Emission shape of type torus or cone torus + TORUS, + // Emission shape of type texture alpha mask + TEXTURE_ALPHA_MASK +}; + +/** @struct Tex2F + * A TEXCOORD composed of 2 floats: u, v + * @since v3.0 + */ +typedef Vec2 Tex2F; + /** @struct Quad2 * A 2D Quad. 4 * 2 floats. */ -struct AX_DLL Quad2 +struct Quad2 { Vec2 tl; Vec2 tr; @@ -74,7 +169,7 @@ struct AX_DLL Quad2 /** @struct Quad3 * A 3D Quad. 4 * 3 floats. */ -struct AX_DLL Quad3 +struct Quad3 { Vec3 bl; Vec3 br; @@ -82,93 +177,83 @@ struct AX_DLL Quad3 Vec3 tr; }; -/** @struct V2F_C4B_T2F - * A Vec2 with a vertex point, a tex coord point and a color 4B. +/* @struct V2F_T2F + * A Vec2 with a vertex point and a tex coord point. + * MotionStreak */ -struct V2F_C4B_T2F +struct V2F_T2F_C4B { - /// vertices (2F) - Vec2 vertices; - /// colors (4B) - Color4B colors; + /// position (2F) + Vec2 position; /// tex coords (2F) - Tex2F texCoords; + Tex2F texCoord; + /// color (4F) + Color32 color; }; -/** @struct V2F_C4B_PF - * - */ -struct V2F_C4B_PF -{ - /// vertices (2F) - Vec2 vertices; - /// colors (4B) - Color4B colors; - /// pointsize - float pointSize = 0.f; -}; - -/** @struct V2F_C4F_T2F +/** @struct V2F_T2F_C4F * A Vec2 with a vertex point, a tex coord point and a color 4F. */ -struct AX_DLL V2F_C4F_T2F +struct V2F_T2F_C4F { - /// vertices (2F) - Vec2 vertices; - /// colors (4F) - Color4F colors; + /// position (2F) + Vec2 position; /// tex coords (2F) - Tex2F texCoords; + Tex2F texCoord; + /// color (4F) + Color color; }; -/** @struct V3F_C4B_T2F +/** @struct V3F_T2F_C4B * A Vec2 with a vertex point, a tex coord point and a color 4B. */ -struct AX_DLL V3F_C4B_T2F +struct V3F_T2F_C4B { - /// vertices (3F) - Vec3 vertices; // 12 bytes + /// position (3F) + Vec3 position; // 12 bytes - /// colors (4B) - Color4B colors; // 4 bytes + // tex coords (2F) + Tex2F texCoord; // 8 bytes + + /// color (4B) + Color32 color; // 4 bytes +}; + +/** @struct V3F_T2F_C4F + * A Vec2 with a vertex point, a tex coord point and a color 4F. + */ +struct V3F_T2F_C4F +{ + /// position (3F) + Vec3 position; // 12 bytes // tex coords (2F) - Tex2F texCoords; // 8 bytes + Tex2F texCoord; // 8 bytes + + /// color (4F) + Color color; // 16 bytes }; /** @struct V3F_T2F * A Vec2 with a vertex point, a tex coord point. */ -struct AX_DLL V3F_T2F +struct V3F_T2F { - /// vertices (2F) - Vec3 vertices; + /// position (2F) + Vec3 position; /// tex coords (2F) - Tex2F texCoords; + Tex2F texCoord; }; /** @struct V3F_C4F * A Vec3 with a vertex point, a color. */ -struct AX_DLL V3F_C4F -{ - /// vertices (3F) - Vec3 vertices; - /// vertices (4F) - Color4F colors; -}; - -struct V3F_C4B -{ - Vec3 vertices; - Color4B colors; -}; - -struct V3F_T2F_C4F +struct V3F_C4F { + /// position (3F) Vec3 position; - Vec2 uv; - Vec4 color; + /// color (4F) + Color color; }; struct V3F_T2F_N3F @@ -178,65 +263,47 @@ struct V3F_T2F_N3F Vec3 normal; }; -/** @struct V2F_C4B_T2F_Triangle - * A Triangle of V2F_C4B_T2F. - */ -struct AX_DLL V2F_C4B_T2F_Triangle +struct V2F_T2F_C4F_Triangle { - V2F_C4B_T2F a; - V2F_C4B_T2F b; - V2F_C4B_T2F c; + V2F_T2F_C4F a; + V2F_T2F_C4F b; + V2F_T2F_C4F c; }; -/** @struct V2F_C4B_T2F_Quad - * A Quad of V2F_C4B_T2F. +/** @struct V3F_T2F_C4F_Quad + * 4 Vertex3FTex2FColor32. */ -struct AX_DLL V2F_C4B_T2F_Quad +struct V3F_T2F_C4B_Quad { - /// bottom left - V2F_C4B_T2F bl; - /// bottom right - V2F_C4B_T2F br; /// top left - V2F_C4B_T2F tl; - /// top right - V2F_C4B_T2F tr; -}; - -/** @struct V3F_C4B_T2F_Quad - * 4 Vertex3FTex2FColor4B. - */ -struct AX_DLL V3F_C4B_T2F_Quad -{ - /// top left - V3F_C4B_T2F tl; + V3F_T2F_C4B tl; /// bottom left - V3F_C4B_T2F bl; + V3F_T2F_C4B bl; /// top right - V3F_C4B_T2F tr; + V3F_T2F_C4B tr; /// bottom right - V3F_C4B_T2F br; + V3F_T2F_C4B br; }; -/** @struct V2F_C4F_T2F_Quad - * 4 Vertex2FTex2FColor4F Quad. +/** @struct V3F_T2F_C4F_Quad + * 4 Vertex3FTex2FColor4F. */ -struct AX_DLL V2F_C4F_T2F_Quad +struct V3F_T2F_C4F_Quad { - /// bottom left - V2F_C4F_T2F bl; - /// bottom right - V2F_C4F_T2F br; /// top left - V2F_C4F_T2F tl; + V3F_T2F_C4F tl; + /// bottom left + V3F_T2F_C4F bl; /// top right - V2F_C4F_T2F tr; + V3F_T2F_C4F tr; + /// bottom right + V3F_T2F_C4F br; }; /** @struct V3F_T2F_Quad * */ -struct AX_DLL V3F_T2F_Quad +struct V3F_T2F_Quad { /// bottom left V3F_T2F bl; @@ -248,20 +315,15 @@ struct AX_DLL V3F_T2F_Quad V3F_T2F tr; }; -namespace backend -{ -enum class BlendFactor : uint32_t; -} - /** @struct BlendFunc * Blend Function used for textures. */ struct AX_DLL BlendFunc { /** source blend function */ - backend::BlendFactor src; + rhi::BlendFactor src; /** destination blend function */ - backend::BlendFactor dst; + rhi::BlendFactor dst; /** Blending disabled. Uses {BlendFactor::ONE, BlendFactor::ZERO} */ static const BlendFunc DISABLE; @@ -371,13 +433,11 @@ struct AX_DLL FontShadow struct AX_DLL FontStroke { /// stroke color - Color3B _strokeColor = Color3B::BLACK; + Color32 _strokeColor = Color32::BLACK; /// stroke size float _strokeSize = 0.f; /// true if stroke enabled bool _strokeEnabled = false; - /// stroke alpha - uint8_t _strokeAlpha = 255; }; /** @struct FontDefinition @@ -396,9 +456,7 @@ struct AX_DLL FontDefinition /// rendering box Vec2 _dimensions = Vec2::ZERO; /// font color - Color3B _fontFillColor = Color3B::WHITE; - /// font alpha - uint8_t _fontAlpha = 255; + Color32 _fontFillColor = Color32::WHITE; /// font shadow FontShadow _shadow; /// font stroke @@ -465,12 +523,12 @@ struct RectI using Viewport = RectI; using ScissorRect = RectI; // both GL & Metal is integer type, GL: int, Metal: NSUInteger -using TextureUsage = backend::TextureUsage; -using PixelFormat = backend::PixelFormat; +using TextureUsage = rhi::TextureUsage; +using PixelFormat = rhi::PixelFormat; -using TargetBufferFlags = backend::TargetBufferFlags; -using DepthStencilFlags = backend::DepthStencilFlags; -using ClearFlag = backend::ClearFlag; +using TargetBufferFlags = rhi::TargetBufferFlags; +using DepthStencilFlags = rhi::DepthStencilFlags; +using ClearFlag = rhi::ClearFlag; typedef void (*AsyncOperation)(void* param); diff --git a/core/3d/cocos3d.h b/axmol/base/UTF8.h similarity index 87% rename from core/3d/cocos3d.h rename to axmol/base/UTF8.h index 93e9c707fd65..fa8e0c3cd9f5 100644 --- a/core/3d/cocos3d.h +++ b/axmol/base/UTF8.h @@ -1,6 +1,8 @@ /**************************************************************************** + Copyright (c) 2014 cocos2d-x.org Copyright (c) 2014-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,6 +27,9 @@ #pragma once -// DON'T ADD FILES HERE -// ADD THEM IN THE COCOS2D.H HEADER FILE +#include "axmol/base/text_utils.h" +namespace ax +{ +namespace StringUtils = text_utils; +} diff --git a/core/base/UserDefault.cpp b/axmol/base/UserDefault.cpp similarity index 98% rename from core/base/UserDefault.cpp rename to axmol/base/UserDefault.cpp index b9da9d2e550d..426be15efdf6 100644 --- a/core/base/UserDefault.cpp +++ b/axmol/base/UserDefault.cpp @@ -45,13 +45,13 @@ THE SOFTWARE. #include "yasio/obstream.hpp" #include "yasio/sz.hpp" -#include "base/UserDefault.h" -#include "platform/Common.h" -#include "platform/FileUtils.h" +#include "axmol/base/UserDefault.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/FileUtils.h" #include "pugixml/pugixml.hpp" -#include "base/Utils.h" +#include "axmol/base/Utils.h" -#include "base/format.h" +#include "axmol/base/format.h" #define USER_DEFAULT_PLAIN_MODE 0 @@ -201,7 +201,7 @@ double UserDefault::getDoubleForKey(const char* pKey, double defaultValue) { auto pValue = getValueForKey(pKey); if (pValue) - return utils::atof(pValue->c_str()); + return utils::atof(*pValue); return defaultValue; } diff --git a/core/base/UserDefault.h b/axmol/base/UserDefault.h similarity index 99% rename from core/base/UserDefault.h rename to axmol/base/UserDefault.h index 12e80512ae5a..9c6ea2b38641 100644 --- a/core/base/UserDefault.h +++ b/axmol/base/UserDefault.h @@ -26,13 +26,13 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include #include "mio/mio.hpp" #include "yasio/string_view.hpp" -#include "platform/FileStream.h" +#include "axmol/platform/FileStream.h" /** * @addtogroup base diff --git a/core/base/Utils.cpp b/axmol/base/Utils.cpp similarity index 86% rename from core/base/Utils.cpp rename to axmol/base/Utils.cpp index 0658d0b05b0e..acb6af7d8952 100755 --- a/core/base/Utils.cpp +++ b/axmol/base/Utils.cpp @@ -25,7 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Utils.h" +#include "axmol/base/Utils.h" #include #include @@ -38,24 +38,24 @@ THE SOFTWARE. #include "openssl/evp.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/Constants.h" -#include "base/UTF8.h" -#include "renderer/CustomCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/RenderState.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/PixelBufferDescriptor.h" - -#include "platform/Image.h" -#include "platform/FileUtils.h" -#include "2d/Sprite.h" -#include "2d/RenderTexture.h" - -#include "base/base64.h" -#include "base/axstd.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/Constants.h" +#include "axmol/base/text_utils.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/rhi/PixelBufferDesc.h" + +#include "axmol/platform/Image.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/RenderTexture.h" + +#include "axmol/base/base64.h" +#include "axmol/base/axstd.h" +#include "axmol/base/charconv.h" #include "yasio/string_view.hpp" using namespace std::string_view_literals; @@ -105,7 +105,7 @@ void captureScreen(std::function)> imageCallback) auto eventDispatcher = director->getEventDispatcher(); // !!!Metal: needs setFrameBufferOnly before draw -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL s_captureScreenListener = eventDispatcher->addCustomEventListener(Director::EVENT_BEFORE_DRAW, [=](EventCustom* /*event*/) { #else @@ -115,7 +115,7 @@ void captureScreen(std::function)> imageCallback) eventDispatcher->removeEventListener(s_captureScreenListener); s_captureScreenListener = nullptr; // !!!GL: AFTER_DRAW and BEFORE_END_FRAME - renderer->readPixels(renderer->getDefaultRenderTarget(), [=](const backend::PixelBufferDescriptor& pbd) { + renderer->readPixels(renderer->getDefaultRenderTarget(), [=](const rhi::PixelBufferDesc& pbd) { if (pbd) { auto image = utils::makeInstance(&Image::initWithRawData, pbd._data.getBytes(), @@ -149,7 +149,7 @@ void captureNode(Node* startNode, std::function)> imageCallba RenderTexture* finalRtx = nullptr; auto rtx = - RenderTexture::create(size.width, size.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8, false); + RenderTexture::create(size.width, size.height, rhi::PixelFormat::RGBA8, PixelFormat::D24S8, false); // rtx->setKeepMatrix(true); Point savedPos = startNode->getPosition(); Point anchor; @@ -172,7 +172,7 @@ void captureNode(Node* startNode, std::function)> imageCallba Sprite* sprite = Sprite::createWithTexture(rtx->getSprite()->getTexture(), finalRect); sprite->setAnchorPoint(Point(0, 0)); sprite->setFlippedY(true); - finalRtx = RenderTexture::create(size.width * scale, size.height * scale, backend::PixelFormat::RGBA8, + finalRtx = RenderTexture::create(size.width * scale, size.height * scale, rhi::PixelFormat::RGBA8, PixelFormat::D24S8, false); sprite->setScale(scale); // or use finalRtx->setKeepMatrix(true); @@ -224,24 +224,14 @@ std::vector findChildren(const Node& node, std::string_view name) } #define MAX_ITOA_BUFFER_SIZE 256 -double atof(const char* str) +double atof(std::string_view str) { - if (str == nullptr) - { + if (str.empty()) return 0.0; - } - - char buf[MAX_ITOA_BUFFER_SIZE]; - strncpy(buf, str, MAX_ITOA_BUFFER_SIZE); - - // strip string, only remain 7 numbers after '.' - char* dot = strchr(buf, '.'); - if (dot != nullptr && dot - buf + 8 < MAX_ITOA_BUFFER_SIZE) - { - dot[8] = '\0'; - } - return ::atof(buf); + double ret{0.0}; + axstd::from_chars(str.data(), str.data() + str.size(), ret); + return ret; } double gettime() @@ -504,7 +494,7 @@ std::string computeFileDigest(std::string_view filename, LanguageType getLanguageTypeByISO2(const char* code) { // this function is used by all platforms to get system language - // except windows: core/platform/win32/CCApplication-win32.cpp + // except windows: axmol/platform/win32/CCApplication-win32.cpp LanguageType ret = LanguageType::ENGLISH; if (strncmp(code, "zh", 2) == 0) @@ -586,84 +576,84 @@ LanguageType getLanguageTypeByISO2(const char* code) return ret; } -backend::BlendFactor toBackendBlendFactor(int factor) +rhi::BlendFactor toBackendBlendFactor(int factor) { switch (factor) { case GLBlendConst::ONE: - return backend::BlendFactor::ONE; + return rhi::BlendFactor::ONE; case GLBlendConst::ZERO: - return backend::BlendFactor::ZERO; + return rhi::BlendFactor::ZERO; case GLBlendConst::SRC_COLOR: - return backend::BlendFactor::SRC_COLOR; + return rhi::BlendFactor::SRC_COLOR; case GLBlendConst::ONE_MINUS_SRC_COLOR: - return backend::BlendFactor::ONE_MINUS_SRC_COLOR; + return rhi::BlendFactor::ONE_MINUS_SRC_COLOR; case GLBlendConst::SRC_ALPHA: - return backend::BlendFactor::SRC_ALPHA; + return rhi::BlendFactor::SRC_ALPHA; case GLBlendConst::ONE_MINUS_SRC_ALPHA: - return backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + return rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; case GLBlendConst::DST_COLOR: - return backend::BlendFactor::DST_COLOR; + return rhi::BlendFactor::DST_COLOR; case GLBlendConst::ONE_MINUS_DST_COLOR: - return backend::BlendFactor::ONE_MINUS_DST_COLOR; + return rhi::BlendFactor::ONE_MINUS_DST_COLOR; case GLBlendConst::DST_ALPHA: - return backend::BlendFactor::DST_ALPHA; + return rhi::BlendFactor::DST_ALPHA; case GLBlendConst::ONE_MINUS_DST_ALPHA: - return backend::BlendFactor::ONE_MINUS_DST_ALPHA; + return rhi::BlendFactor::ONE_MINUS_DST_ALPHA; case GLBlendConst::SRC_ALPHA_SATURATE: - return backend::BlendFactor::SRC_ALPHA_SATURATE; + return rhi::BlendFactor::SRC_ALPHA_SATURATE; case GLBlendConst::BLEND_COLOR: - return backend::BlendFactor::BLEND_COLOR; + return rhi::BlendFactor::BLEND_COLOR; case GLBlendConst::CONSTANT_ALPHA: - return backend::BlendFactor::CONSTANT_ALPHA; + return rhi::BlendFactor::CONSTANT_ALPHA; case GLBlendConst::ONE_MINUS_CONSTANT_ALPHA: - return backend::BlendFactor::ONE_MINUS_CONSTANT_ALPHA; + return rhi::BlendFactor::ONE_MINUS_CONSTANT_ALPHA; default: assert(false); break; } - return backend::BlendFactor::ONE; + return rhi::BlendFactor::ONE; } -int toGLBlendFactor(backend::BlendFactor blendFactor) +int toGLBlendFactor(rhi::BlendFactor blendFactor) { int ret = GLBlendConst::ONE; switch (blendFactor) { - case backend::BlendFactor::ZERO: + case rhi::BlendFactor::ZERO: ret = GLBlendConst::ZERO; break; - case backend::BlendFactor::ONE: + case rhi::BlendFactor::ONE: ret = GLBlendConst::ONE; break; - case backend::BlendFactor::SRC_COLOR: + case rhi::BlendFactor::SRC_COLOR: ret = GLBlendConst::SRC_COLOR; break; - case backend::BlendFactor::ONE_MINUS_SRC_COLOR: + case rhi::BlendFactor::ONE_MINUS_SRC_COLOR: ret = GLBlendConst::ONE_MINUS_SRC_COLOR; break; - case backend::BlendFactor::SRC_ALPHA: + case rhi::BlendFactor::SRC_ALPHA: ret = GLBlendConst::SRC_ALPHA; break; - case backend::BlendFactor::ONE_MINUS_SRC_ALPHA: + case rhi::BlendFactor::ONE_MINUS_SRC_ALPHA: ret = GLBlendConst::ONE_MINUS_SRC_ALPHA; break; - case backend::BlendFactor::DST_COLOR: + case rhi::BlendFactor::DST_COLOR: ret = GLBlendConst::DST_COLOR; break; - case backend::BlendFactor::ONE_MINUS_DST_COLOR: + case rhi::BlendFactor::ONE_MINUS_DST_COLOR: ret = GLBlendConst::ONE_MINUS_DST_COLOR; break; - case backend::BlendFactor::DST_ALPHA: + case rhi::BlendFactor::DST_ALPHA: ret = GLBlendConst::DST_ALPHA; break; - case backend::BlendFactor::ONE_MINUS_DST_ALPHA: + case rhi::BlendFactor::ONE_MINUS_DST_ALPHA: ret = GLBlendConst::ONE_MINUS_DST_ALPHA; break; - case backend::BlendFactor::SRC_ALPHA_SATURATE: + case rhi::BlendFactor::SRC_ALPHA_SATURATE: ret = GLBlendConst::SRC_ALPHA_SATURATE; break; - case backend::BlendFactor::BLEND_COLOR: + case rhi::BlendFactor::BLEND_COLOR: ret = GLBlendConst::BLEND_COLOR; break; default: @@ -672,41 +662,6 @@ int toGLBlendFactor(backend::BlendFactor blendFactor) return ret; } -backend::SamplerFilter toBackendSamplerFilter(int mode) -{ - switch (mode) - { - case GLTexParamConst::LINEAR: - case GLTexParamConst::LINEAR_MIPMAP_LINEAR: - case GLTexParamConst::LINEAR_MIPMAP_NEAREST: - case GLTexParamConst::NEAREST_MIPMAP_LINEAR: - return backend::SamplerFilter::LINEAR; - case GLTexParamConst::NEAREST: - case GLTexParamConst::NEAREST_MIPMAP_NEAREST: - return backend::SamplerFilter::NEAREST; - default: - AXASSERT(false, "invalid GL sampler filter!"); - return backend::SamplerFilter::LINEAR; - } -} - -backend::SamplerAddressMode toBackendAddressMode(int mode) -{ - switch (mode) - { - case GLTexParamConst::REPEAT: - return backend::SamplerAddressMode::REPEAT; - case GLTexParamConst::CLAMP: - case GLTexParamConst::CLAMP_TO_EDGE: - return backend::SamplerAddressMode::CLAMP_TO_EDGE; - case GLTexParamConst::MIRROR_REPEAT: - return backend::SamplerAddressMode::MIRROR_REPEAT; - default: - AXASSERT(false, "invalid GL address mode"); - return backend::SamplerAddressMode::REPEAT; - } -} - const Mat4& getAdjustMatrix() { static ax::Mat4 adjustMatrix = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0.5, 0.5, 0, 0, 0, 1}; diff --git a/core/base/Utils.h b/axmol/base/Utils.h similarity index 96% rename from core/base/Utils.h rename to axmol/base/Utils.h index 6e6f67657a64..d831b6bf8a3d 100755 --- a/core/base/Utils.h +++ b/axmol/base/Utils.h @@ -28,14 +28,14 @@ THE SOFTWARE. #include #include -#include "2d/Node.h" -#include "base/Macros.h" -#include "base/RefPtr.h" -#include "base/Data.h" -#include "renderer/backend/Types.h" -#include "math/Mat4.h" -#include "math/Mat3.h" -#include "base/axstd.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Macros.h" +#include "axmol/base/RefPtr.h" +#include "axmol/base/Data.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/math/Mat4.h" +#include "axmol/math/Mat3.h" +#include "axmol/base/axstd.h" /** @file ccUtils.h Misc free functions @@ -116,7 +116,7 @@ AX_DLL std::vector findChildren(const Node& node, std::string_view name); * @param str The string be to converted to double. * @return Returns converted value of a string. */ -AX_DLL double atof(const char* str); +AX_DLL double atof(std::string_view str); /** Get current exact time, accurate to nanoseconds. * @return Returns the time in seconds since the Epoch. @@ -238,13 +238,9 @@ AX_DLL std::string computeFileDigest(std::string_view filename, */ AX_DLL LanguageType getLanguageTypeByISO2(const char* code); -AX_DLL backend::BlendFactor toBackendBlendFactor(int factor); +AX_DLL rhi::BlendFactor toBackendBlendFactor(int factor); -AX_DLL int toGLBlendFactor(backend::BlendFactor blendFactor); - -AX_DLL backend::SamplerFilter toBackendSamplerFilter(int mode); - -AX_DLL backend::SamplerAddressMode toBackendAddressMode(int mode); +AX_DLL int toGLBlendFactor(rhi::BlendFactor blendFactor); // Adjust matrix for metal. AX_DLL const Mat4& getAdjustMatrix(); diff --git a/core/base/Value.cpp b/axmol/base/Value.cpp similarity index 99% rename from core/base/Value.cpp rename to axmol/base/Value.cpp index 6293881d2bf1..a2addd355164 100644 --- a/core/base/Value.cpp +++ b/axmol/base/Value.cpp @@ -24,11 +24,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Value.h" +#include "axmol/base/Value.h" #include #include #include -#include "base/Utils.h" +#include "axmol/base/Utils.h" namespace ax { @@ -631,7 +631,7 @@ float Value::asFloat(float defaultValue) const return _field.floatVal; case Type::STRING: - return static_cast(utils::atof(_field.strVal->c_str())); + return static_cast(utils::atof(*_field.strVal)); case Type::INT_I32: return static_cast(_field.intVal); @@ -663,7 +663,7 @@ double Value::asDouble(double defaultValue) const return _field.doubleVal; case Type::STRING: - return static_cast(utils::atof(_field.strVal->c_str())); + return static_cast(utils::atof(*_field.strVal)); case Type::INT_I32: return static_cast(_field.intVal); diff --git a/core/base/Value.h b/axmol/base/Value.h similarity index 99% rename from core/base/Value.h rename to axmol/base/Value.h index 154fbbd2c387..02fcc1d06aa0 100644 --- a/core/base/Value.h +++ b/axmol/base/Value.h @@ -26,8 +26,8 @@ #pragma once -#include "platform/PlatformMacros.h" -#include "base/Macros.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Macros.h" #include #include #include diff --git a/core/base/Vector.h b/axmol/base/Vector.h similarity index 99% rename from core/base/Vector.h rename to axmol/base/Vector.h index 56e77b6aa1e6..ad490896fd9b 100644 --- a/core/base/Vector.h +++ b/axmol/base/Vector.h @@ -27,8 +27,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Macros.h" -#include "base/Object.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Object.h" #include #include #include // for std::find diff --git a/core/base/ZipUtils.cpp b/axmol/base/ZipUtils.cpp similarity index 99% rename from core/base/ZipUtils.cpp rename to axmol/base/ZipUtils.cpp index cf3fc6e792e9..b4f8880cd1a8 100644 --- a/core/base/ZipUtils.cpp +++ b/axmol/base/ZipUtils.cpp @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/ZipUtils.h" +#include "axmol/base/ZipUtils.h" #ifdef MINIZIP_FROM_SYSTEM # include @@ -42,9 +42,9 @@ #include #include -#include "base/Data.h" -#include "base/Macros.h" -#include "platform/FileUtils.h" +#include "axmol/base/Data.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/FileUtils.h" #include #include @@ -442,7 +442,7 @@ int ZipUtils::inflateCCZBuffer(const unsigned char* buffer, ssize_t bufferLen, u decodeEncodedPvr(ints, enclen); -#if _AX_DEBUG > 0 +#if defined(_AX_DEBUG) && _AX_DEBUG > 0 // verify checksum in debug mode unsigned int calculated = checksumPvr(ints, enclen); unsigned int required = AX_SWAP_INT32_BIG_TO_HOST(header->reserved); diff --git a/core/base/ZipUtils.h b/axmol/base/ZipUtils.h similarity index 98% rename from core/base/ZipUtils.h rename to axmol/base/ZipUtils.h index cea952f82da2..f410ae87cd9a 100644 --- a/core/base/ZipUtils.h +++ b/axmol/base/ZipUtils.h @@ -28,15 +28,15 @@ THE SOFTWARE. #pragma once /// @cond DO_NOT_SHOW -#include "platform/PlatformMacros.h" -#include "platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/FileUtils.h" #include #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "platform/android/FileUtils-android.h" +# include "axmol/platform/android/FileUtils-android.h" #elif (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) // for import ssize_t on win32 platform -# include "platform/StdC.h" +# include "axmol/platform/StdC.h" #endif #include "yasio/byte_buffer.hpp" diff --git a/core/base/astc.cpp b/axmol/base/astc.cpp similarity index 99% rename from core/base/astc.cpp rename to axmol/base/astc.cpp index 379014a40931..badc08fe2905 100644 --- a/core/base/astc.cpp +++ b/axmol/base/astc.cpp @@ -11,7 +11,7 @@ ******************************************************************************/ -#include "base/astc.h" +#include "axmol/base/astc.h" #include #include @@ -22,7 +22,7 @@ #include "astcenc/astcenc_internal_entry.h" #include "yasio/utils.hpp" -#include "base/Director.h" +#include "axmol/base/Director.h" #if !defined(__EMSCRIPTEN__) || defined(__EMSCRIPTEN_PTHREADS__) diff --git a/core/base/astc.h b/axmol/base/astc.h similarity index 100% rename from core/base/astc.h rename to axmol/base/astc.h diff --git a/core/base/atitc.cpp b/axmol/base/atitc.cpp similarity index 99% rename from core/base/atitc.cpp rename to axmol/base/atitc.cpp index d0b8f44e623b..5f9d60bbaeb5 100644 --- a/core/base/atitc.cpp +++ b/axmol/base/atitc.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/atitc.h" +#include "axmol/base/atitc.h" // Decode ATITC encode block to 4x4 RGB32 pixels static void atitc_decode_block(uint8_t** blockData, diff --git a/core/base/atitc.h b/axmol/base/atitc.h similarity index 97% rename from core/base/atitc.h rename to axmol/base/atitc.h index 8159577c0572..4b7645f1822c 100644 --- a/core/base/atitc.h +++ b/axmol/base/atitc.h @@ -27,7 +27,7 @@ /// @cond DO_NOT_SHOW -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" enum class ATITCDecodeFlag { @@ -42,4 +42,4 @@ void atitc_decode(uint8_t* encode_data, const int pixelsWidth, const int pixelsHeight, ATITCDecodeFlag decodeFlag); -/// @endcond \ No newline at end of file +/// @endcond diff --git a/core/base/axstd.h b/axmol/base/axstd.h similarity index 100% rename from core/base/axstd.h rename to axmol/base/axstd.h diff --git a/core/base/base64.cpp b/axmol/base/base64.cpp similarity index 99% rename from core/base/base64.cpp rename to axmol/base/base64.cpp index a835e546a161..2080c39bf1a6 100644 --- a/core/base/base64.cpp +++ b/axmol/base/base64.cpp @@ -7,7 +7,7 @@ // Official repository: https://github.com/boostorg/beast // -#include "base64.h" +#include "axmol/base/base64.h" namespace ax { diff --git a/core/base/base64.h b/axmol/base/base64.h similarity index 97% rename from core/base/base64.h rename to axmol/base/base64.h index b39fac5a6c72..260ebb091720 100644 --- a/core/base/base64.h +++ b/axmol/base/base64.h @@ -10,7 +10,7 @@ #pragma once #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/base/bitmask.h b/axmol/base/bitmask.h similarity index 100% rename from core/base/bitmask.h rename to axmol/base/bitmask.h diff --git a/axmol/base/charconv.h b/axmol/base/charconv.h new file mode 100644 index 000000000000..7cb028ce91c7 --- /dev/null +++ b/axmol/base/charconv.h @@ -0,0 +1,18 @@ +#pragma once + +// llvm clang and Apple clang std::from_chars not support floating-point +// use fast_float instead: https://github.com/fastfloat/fast_float +#if !defined(_WIN32) && defined(__clang__) +#include "fast_float/fast_float.h" +namespace axstd { + using fast_float::from_chars; + using from_chars_result = fast_float::from_chars_result; +} + +#else +#include +namespace axstd { + using std::from_chars; + using std::from_chars_result; +} +#endif diff --git a/core/base/etc1.cpp b/axmol/base/etc1.cpp similarity index 99% rename from core/base/etc1.cpp rename to axmol/base/etc1.cpp index 56c18f5166a4..e743bcff3792 100644 --- a/core/base/etc1.cpp +++ b/axmol/base/etc1.cpp @@ -12,7 +12,7 @@ // See the License for the specific language governing permissions and // limitations under the License. -#include "base/etc1.h" +#include "axmol/base/etc1.h" #include diff --git a/core/base/etc1.h b/axmol/base/etc1.h similarity index 100% rename from core/base/etc1.h rename to axmol/base/etc1.h diff --git a/core/base/etc2.cpp b/axmol/base/etc2.cpp similarity index 99% rename from core/base/etc2.cpp rename to axmol/base/etc2.cpp index a8cc3d365d6c..9574fb4d3881 100644 --- a/core/base/etc2.cpp +++ b/axmol/base/etc2.cpp @@ -31,7 +31,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/etc2.h" +#include "axmol/base/etc2.h" #include #include #include diff --git a/core/base/etc2.h b/axmol/base/etc2.h similarity index 100% rename from core/base/etc2.h rename to axmol/base/etc2.h diff --git a/core/base/filesystem.h b/axmol/base/filesystem.h similarity index 100% rename from core/base/filesystem.h rename to axmol/base/filesystem.h diff --git a/core/base/firePngData.h b/axmol/base/firePngData.h similarity index 100% rename from core/base/firePngData.h rename to axmol/base/firePngData.h diff --git a/core/base/format.h b/axmol/base/format.h similarity index 100% rename from core/base/format.h rename to axmol/base/format.h diff --git a/core/base/hlookup.h b/axmol/base/hlookup.h similarity index 100% rename from core/base/hlookup.h rename to axmol/base/hlookup.h diff --git a/axmol/base/json.h b/axmol/base/json.h new file mode 100644 index 000000000000..51457f19eb47 --- /dev/null +++ b/axmol/base/json.h @@ -0,0 +1,76 @@ +#pragma once + +#include "simdjson/simdjson.h" + +namespace simdjson +{ + +/** + * @addtogroup base + * @{ + */ +/** + @brief A dedicated class for easy load padded string for simdjson parser. + + The only legal use case is: + + PaddedString strJson; + FileUtils::getInstance()->getContents(filePath, &strJson); + ondemand::parser parser; + ondemand::document settings = parser.iterate(strJson); + */ +class PaddedString final +{ +public: + PaddedString() = default; + ~PaddedString() { delete[] data_ptr; } + + PaddedString(PaddedString&& o) noexcept : viable_size(o.viable_size), data_ptr(o.data_ptr) + { + o.data_ptr = nullptr; // we take ownership + } + PaddedString& operator=(PaddedString&& o) noexcept + { + swap(o); + return *this; + } + void swap(PaddedString& o) noexcept + { + std::swap(viable_size, o.viable_size); + std::swap(data_ptr, o.data_ptr); + } + + using value_type = char; + size_t size() const { return viable_size; } + void resize(size_t size) + { + assert(!data_ptr || size <= capacity); // not allow enlarge + if (!data_ptr && size > 0) + { + capacity = size; + data_ptr = internal::allocate_padded_buffer(size); + } + viable_size = size; + } + + char* data() { return data_ptr; } + const char* data() const { return data_ptr; } + + void clear() { resize(0); } + + operator padded_string_view() const noexcept + { + return padded_string_view(data(), size(), size() + SIMDJSON_PADDING); + } + +private: + PaddedString(const PaddedString&) = delete; + size_t viable_size{0}; + size_t capacity{0}; + char* data_ptr{nullptr}; +}; + +// end of base group +/** @} */ + +} // namespace ax::simdjson diff --git a/core/base/ktxspec_v1.h b/axmol/base/ktxspec_v1.h similarity index 100% rename from core/base/ktxspec_v1.h rename to axmol/base/ktxspec_v1.h diff --git a/core/base/pvr.cpp b/axmol/base/pvr.cpp similarity index 99% rename from core/base/pvr.cpp rename to axmol/base/pvr.cpp index 671a8cba97c0..b4f48577462e 100644 --- a/core/base/pvr.cpp +++ b/axmol/base/pvr.cpp @@ -18,7 +18,7 @@ #include #include #include -#include "base/pvr.h" +#include "axmol/base/pvr.h" #define PVRT_MIN(a, b) (((a) < (b)) ? (a) : (b)) #define PVRT_MAX(a, b) (((a) > (b)) ? (a) : (b)) @@ -691,4 +691,4 @@ static void PVRDecompress(AMTC_BLOCK_STRUCT* pCompressedData, /***************************************************************************** End of file (pvr.cpp) - *****************************************************************************/ \ No newline at end of file + *****************************************************************************/ diff --git a/core/base/pvr.h b/axmol/base/pvr.h similarity index 100% rename from core/base/pvr.h rename to axmol/base/pvr.h diff --git a/core/base/s3tc.cpp b/axmol/base/s3tc.cpp similarity index 99% rename from core/base/s3tc.cpp rename to axmol/base/s3tc.cpp index e3765a7c4a9b..81099f34c3c3 100644 --- a/core/base/s3tc.cpp +++ b/axmol/base/s3tc.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/s3tc.h" +#include "axmol/base/s3tc.h" // Decode S3TC encode block to 4x4 RGB32 pixels static void s3tc_decode_block(uint8_t** blockData, diff --git a/core/base/s3tc.h b/axmol/base/s3tc.h similarity index 98% rename from core/base/s3tc.h rename to axmol/base/s3tc.h index a4267707527c..6b30e5911716 100644 --- a/core/base/s3tc.h +++ b/axmol/base/s3tc.h @@ -27,7 +27,7 @@ /// @cond DO_NOT_SHOW -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" enum class S3TCDecodeFlag { diff --git a/core/base/UTF8.cpp b/axmol/base/text_utils.cpp similarity index 75% rename from core/base/UTF8.cpp rename to axmol/base/text_utils.cpp index ce05d149cce9..ce1098d01427 100644 --- a/core/base/UTF8.cpp +++ b/axmol/base/text_utils.cpp @@ -25,9 +25,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/UTF8.h" -#include "platform/Common.h" -#include "base/Logging.h" +#include "axmol/base/text_utils.h" +#include "axmol/platform/Common.h" +#include "axmol/base/Logging.h" #include "ConvertUTF.h" #include @@ -36,87 +36,40 @@ using namespace llvm; namespace ax { -namespace StringUtils +namespace text_utils { -//#ifndef AX_CORE_PROFILE -std::string AX_DLL format(const char* format, ...) -{ - va_list args; - va_start(args, format); - auto ret = vformat(format, args); - va_end(args); - return ret; -} -/*--- This a C++ universal sprintf in the future. -** @pitfall: The behavior of vsnprintf between VS2013 and VS2015/2017 is different -** VS2013 or Unix-Like System will return -1 when buffer not enough, but VS2015/2017 will return the actural needed -*length for buffer at this station -** The _vsnprintf behavior is compatible API which always return -1 when buffer isn't enough at VS2013/2015/2017 -** Yes, The vsnprintf is more efficient implemented by MSVC 19.0 or later, AND it's also standard-compliant, see -*reference: http://www.cplusplus.com/reference/cstdio/vsnprintf/ -*/ -std::string vformat(const char* format, va_list ap) -{ -#define AX_VSNPRINTF_BUFFER_LENGTH 512 - std::string buf(AX_VSNPRINTF_BUFFER_LENGTH, '\0'); - - va_list args; - va_copy(args, ap); - int nret = vsnprintf(&buf.front(), buf.length() + 1, format, args); - va_end(args); - if (nret >= 0) +std::string_view ltrim(std::string_view s) +{ + if (!s.empty()) { - if ((unsigned int)nret < buf.length()) + auto first = s.data(); + auto last = first + s.length(); + while (first < last && std::isspace(*first)) { - buf.resize(nret); - } - else if ((unsigned int)nret > buf.length()) - { // handle return required length when buffer insufficient - buf.resize(nret); - - va_copy(args, ap); - nret = vsnprintf(&buf.front(), buf.length() + 1, format, args); - va_end(args); + ++first; } - // else equals, do nothing. + return std::string_view{first, static_cast(last - first)}; } - else - { // handle return -1 when buffer insufficient - /* - vs2013/older & glibc <= 2.0.6, they would return -1 when the output was truncated. - see: http://man7.org/linux/man-pages/man3/vsnprintf.3.html - */ -#if (defined(__linux__) && ((__GLIBC__ < 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ < 1)))) || \ - (defined(_MSC_VER) && _MSC_VER < 1900) - enum : size_t - { - enlarge_limits = (1 << 20), // limits the buffer cost memory less than 2MB - }; - do - { - buf.resize(buf.length() << 1); - - va_copy(args, ap); - nret = vsnprintf(&buf.front(), buf.length() + 1, format, args); - va_end(args); + return s; +} - } while (nret < 0 && buf.size() <= enlarge_limits); - if (nret > 0) - buf.resize(nret); - else - buf = "strfmt: an error is encountered!"; -#else - /* other standard implementation - see: http://www.cplusplus.com/reference/cstdio/vsnprintf/ - */ - buf = "strfmt: an error is encountered!"; -#endif +std::string_view rtrim(std::string_view s) +{ + if (!s.empty()) + { + auto first = s.data(); + auto last = first + s.length(); + auto rfirst = last - 1; + while (rfirst > first && std::isspace(*rfirst)) + { + --rfirst; + } + return std::string_view{first, static_cast(rfirst + 1 - first)}; } - - return buf; + return s; } -//#endif + /* * @str: the string to search through. * @c: the character to not look for. @@ -379,7 +332,7 @@ std::string getStringUTFCharsJNI(JNIEnv* env, jstring srcjStr, bool* ret) jstring newStringUTFJNI(JNIEnv* env, std::string_view utf8Str, bool* ret) { std::u16string utf16Str; - bool flag = ax::StringUtils::UTF8ToUTF16(utf8Str, utf16Str); + bool flag = ax::text_utils::UTF8ToUTF16(utf8Str, utf16Str); if (ret) { @@ -514,23 +467,15 @@ bool isLegalUTF8String(const char* str, size_t len) return ::isLegalUTF8String((const UTF8**)&str, (const UTF8*)str + len); } -StringUTF8::StringUTF8() {} - -StringUTF8::StringUTF8(std::string_view newStr) +u8char_span::u8char_span(std::string_view newStr) { - replace(newStr); + reset(newStr); } -StringUTF8::~StringUTF8() {} - -std::size_t StringUTF8::length() const -{ - return _str.size(); -} - -void StringUTF8::replace(std::string_view newStr) +void u8char_span::reset(std::string_view newStr) { _str.clear(); + _size_bytes = 0; if (!newStr.empty()) { UTF8* sequenceUtf8 = (UTF8*)newStr.data(); @@ -548,76 +493,47 @@ void StringUTF8::replace(std::string_view newStr) std::size_t lengthChar = getNumBytesForUTF8(*sequenceUtf8); CharUTF8 charUTF8; - charUTF8._char.append((char*)sequenceUtf8, lengthChar); + charUTF8._char = std::string_view((char*)sequenceUtf8, lengthChar); sequenceUtf8 += lengthChar; _str.emplace_back(charUTF8); } + + _size_bytes = newStr.length(); } } -std::string StringUTF8::getAsCharSequence() const +std::string_view u8char_span::view() const { - return getAsCharSequence(0, std::numeric_limits::max()); + return this->subview(0, std::numeric_limits::max()); } -std::string StringUTF8::getAsCharSequence(std::size_t pos) const +std::string_view u8char_span::subview(std::size_t pos) const { - return getAsCharSequence(pos, std::numeric_limits::max()); + return this->subview(pos, std::numeric_limits::max()); } -std::string StringUTF8::getAsCharSequence(std::size_t pos, std::size_t len) const +std::string_view u8char_span::subview(std::size_t pos, std::size_t len) const { - std::string charSequence; - std::size_t maxLen = _str.size() - pos; - if (len > maxLen) - { - len = maxLen; - } - - std::size_t endPos = len + pos; - while (pos < endPos) + if (!_str.empty()) { - charSequence.append(_str[pos++]._char); - } - - return charSequence; -} + const auto last_pos = std::clamp(pos + len - 1, pos, _str.size() - 1); + if (pos <= last_pos) + { + auto first_char = _str[pos]; + auto last_char = _str[last_pos]; -bool StringUTF8::deleteChar(std::size_t pos) -{ - if (pos < _str.size()) - { - _str.erase(_str.begin() + pos); - return true; - } - else - { - return false; + return std::string_view{first_char._char.data(), last_char._char.data() + last_char._char.length()}; + } } + return std::string_view{""}; } -bool StringUTF8::insert(std::size_t pos, std::string_view insertStr) +void u8char_span::remove_prefix(size_t n) { - StringUTF8 utf8(insertStr); - - return insert(pos, utf8); + _str.erase(_str.begin(), _str.begin() + n); } -bool StringUTF8::insert(std::size_t pos, const StringUTF8& insertStr) -{ - if (pos <= _str.size()) - { - _str.insert(_str.begin() + pos, insertStr._str.begin(), insertStr._str.end()); +} // namespace text_utils - return true; - } - else - { - return false; - } -} - -} // namespace StringUtils - -} +} // namespace ax diff --git a/core/base/UTF8.h b/axmol/base/text_utils.h similarity index 78% rename from core/base/UTF8.h rename to axmol/base/text_utils.h index d64c5184ac87..6f2ff40a2ce7 100644 --- a/core/base/UTF8.h +++ b/axmol/base/text_utils.h @@ -25,10 +25,11 @@ THE SOFTWARE. ****************************************************************************/ -#pragma once +#ifndef AXMOL__TEXT_UTILS_H +#define AXMOL__TEXT_UTILS_H -#include "platform/PlatformMacros.h" -#include "base/format.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/format.h" #include #include #include @@ -40,24 +41,24 @@ namespace ax { -namespace StringUtils +namespace text_utils { namespace UnicodeCharacters { -const char32_t NewLine = 0x000A; // 10 -const char32_t CarriageReturn = 0x000D; // 13 -const char32_t NextCharNoChangeX = 0x0008; // 8 -const char32_t Space = 0x0020; // 32 -const char32_t NoBreakSpace = 0x00A0; // 160 +inline constexpr char32_t NewLine = 0x000A; // 10 +inline constexpr char32_t CarriageReturn = 0x000D; // 13 +inline constexpr char32_t NextCharNoChangeX = 0x0008; // 8 +inline constexpr char32_t Space = 0x0020; // 32 +inline constexpr char32_t NoBreakSpace = 0x00A0; // 160 } // namespace UnicodeCharacters namespace AsciiCharacters { -const char NewLine = '\n'; -const char CarriageReturn = '\r'; -const char NextCharNoChangeX = '\b'; -const char Space = ' '; +inline constexpr char NewLine = '\n'; +inline constexpr char CarriageReturn = '\r'; +inline constexpr char NextCharNoChangeX = '\b'; +inline constexpr char Space = ' '; } // namespace AsciiCharacters template @@ -65,11 +66,13 @@ inline std::string toString(T arg) { return fmt::to_string(arg); } -//#ifndef AX_CORE_PROFILE -// DEPRECATED since axmol-2.1.4, use fmt::format instead -std::string AX_DLL format(const char* format, ...) AX_FORMAT_PRINTF(1, 2); -std::string AX_DLL vformat(const char* format, va_list ap); -//#endif + +AX_DLL std::string_view ltrim(std::string_view s); +AX_DLL std::string_view rtrim(std::string_view s); +inline std::string_view trim(std::string_view s) +{ + return ltrim(rtrim(s)); +} /** * @brief Converts from UTF8 string to UTF16 string. @@ -85,7 +88,7 @@ std::string AX_DLL vformat(const char* format, va_list ap); * e.g. * @code * std::u16string utf16; - * bool ret = StringUtils::UTF8ToUTF16("你好hello", utf16); + * bool ret = text_utils::UTF8ToUTF16("你好hello", utf16); * if (ret) { * do_some_thing_with_utf16(utf16); * } @@ -220,10 +223,6 @@ AX_DLL size_t getUTF8ByteOffset(std::string_view utf8, size_t utf8CharOffset); */ AX_DLL size_t eraseUTF8CharAt(std::string& str, size_t utf8CharOffset); -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) AX_DLL size_t getCharacterCountInUTF8String(std::string_view utf8); -#endif - /** * @brief Gets the index of the last character that is not equal to the character given. * @param str The string to be searched. @@ -253,42 +252,51 @@ AX_DLL bool detectNonAsciiUTF8(const char* str, size_t len, bool restrictUTF8, b AX_DLL bool isLegalUTF8String(const char* str, size_t len); /** - * Utf8 sequence - * Store all utf8 chars as std::string - * Build from std::string + * Utf8 readonly sequence + * Store all utf8 chars as std::string_view + * Build from std::string_view */ -class AX_DLL StringUTF8 +class AX_DLL u8char_span { public: - struct CharUTF8 + typedef struct CharUTF8 { - std::string _char; + std::string_view _char; bool isASCII() const { return _char.size() == 1; } - }; - typedef std::vector CharUTF8Store; + } value_type; - StringUTF8(); - StringUTF8(std::string_view newStr); - ~StringUTF8(); + u8char_span() = default; + u8char_span(std::string_view newStr); + ~u8char_span() = default; - std::size_t length() const; - void replace(std::string_view newStr); + void reset(std::string_view newStr); - std::string getAsCharSequence() const; - std::string getAsCharSequence(std::size_t pos) const; - std::string getAsCharSequence(std::size_t pos, std::size_t len) const; + std::size_t size() const { return _str.size(); } + std::size_t size_bytes() const { return _size_bytes; } - bool deleteChar(std::size_t pos); - bool insert(std::size_t pos, std::string_view insertStr); - bool insert(std::size_t pos, const StringUTF8& insertStr); + bool empty() const { return _str.empty(); } + + const value_type& at(size_t pos) const { return _str.at(pos); } - CharUTF8Store& getString() { return _str; } - const CharUTF8Store& getString() const { return _str; } + std::string_view view() const; + std::string_view subview(std::size_t pos) const; + std::string_view subview(std::size_t pos, std::size_t len) const; + + std::vector::const_reverse_iterator rbegin() const { return _str.rbegin(); } + std::vector::const_reverse_iterator rend() const { return _str.rend(); } + + std::vector::const_iterator begin() const { return _str.begin(); } + std::vector::const_iterator end() const { return _str.end(); } + + void remove_prefix(size_t n); private: - CharUTF8Store _str; + std::vector _str; + size_t _size_bytes{0}; }; -} // namespace StringUtils +} // namespace text_utils -} +} // namespace ax + +#endif /** defined(AXMOL__TEXT_UTILS_H) */ diff --git a/core/cocos2d.h b/axmol/cocos2d.h similarity index 93% rename from core/cocos2d.h rename to axmol/cocos2d.h index 0999b8703b5a..33538590e557 100644 --- a/core/cocos2d.h +++ b/axmol/cocos2d.h @@ -33,15 +33,12 @@ extensions use it, i.g fairygui, live2d ... #pragma once -#include "axmol.h" +#include "axmol/axmol.h" #define COCOS2D_VERSION 0x00040000 namespace ax { - -AX_DLL const char* cocos2dVersion(); - /** Backward compatibility with old axmol projects */ using Sprite3D = MeshRenderer; @@ -62,12 +59,6 @@ namespace cocos2d = ax; #define CCASSERT AXASSERT #define CC_ASSERT AX_ASSERT #define CC_CONSTRUCTOR_ACCESS public -#ifndef AX_CORE_PROFILE -# define CCLOG AXLOG -# define CCLOGINFO AXLOGINFO -# define CCLOGWARN AXLOGWARN -# define CCLOGERROR AXLOGERROR -#endif #define CC_SAFE_RETAIN AX_SAFE_RETAIN diff --git a/core/math/AffineTransform.cpp b/axmol/math/AffineTransform.cpp similarity index 99% rename from core/math/AffineTransform.cpp rename to axmol/math/AffineTransform.cpp index e2c0816576a6..63c4177cf022 100644 --- a/core/math/AffineTransform.cpp +++ b/axmol/math/AffineTransform.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "math/AffineTransform.h" +#include "axmol/math/AffineTransform.h" #include #include diff --git a/core/math/AffineTransform.h b/axmol/math/AffineTransform.h similarity index 98% rename from core/math/AffineTransform.h rename to axmol/math/AffineTransform.h index 9eafb8332a63..c9973616f9a4 100644 --- a/core/math/AffineTransform.h +++ b/axmol/math/AffineTransform.h @@ -26,9 +26,9 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" -#include "math/Math.h" +#include "axmol/math/Math.h" /** * @addtogroup base diff --git a/core/math/CMakeLists.txt b/axmol/math/CMakeLists.txt similarity index 100% rename from core/math/CMakeLists.txt rename to axmol/math/CMakeLists.txt diff --git a/core/math/Color.cpp b/axmol/math/Color.cpp similarity index 55% rename from core/math/Color.cpp rename to axmol/math/Color.cpp index c337b6ea5cba..3346217b22f9 100644 --- a/core/math/Color.cpp +++ b/axmol/math/Color.cpp @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "math/Color.h" +#include "axmol/math/Color.h" #if defined(_WIN32) # pragma push_macro("TRANSPARENT") @@ -33,153 +33,80 @@ THE SOFTWARE. NS_AX_MATH_BEGIN /** - * Color3B + * Color32 */ -bool Color3B::operator==(const Color3B& right) const +bool Color32::operator==(const Color32& right) const { - return (r == right.r && g == right.g && b == right.b); + return right.value == this->value; } -bool Color3B::operator==(const Color4B& right) const +bool Color32::operator==(const Color& right) const { - return (r == right.r && g == right.g && b == right.b && 255 == right.a); + return (*this == Color32(right)); } -bool Color3B::operator==(const Color4F& right) const -{ - return (right.a == 1.0f && Color4F(*this) == right); -} - -bool Color3B::operator!=(const Color3B& right) const -{ - return !(*this == right); -} - -bool Color3B::operator!=(const Color4B& right) const -{ - return !(*this == right); -} - -bool Color3B::operator!=(const Color4F& right) const -{ - return !(*this == right); -} - -/** - * Color4B - */ - -bool Color4B::operator==(const Color4B& right) const -{ - return (r == right.r && g == right.g && b == right.b && a == right.a); -} - -bool Color4B::operator==(const Color3B& right) const -{ - return (r == right.r && g == right.g && b == right.b && a == 255); -} - -bool Color4B::operator==(const Color4F& right) const -{ - return (*this == Color4B(right)); -} - -bool Color4B::operator!=(const Color4B& right) const -{ - return !(*this == right); -} - -bool Color4B::operator!=(const Color3B& right) const +bool Color32::operator!=(const Color32& right) const { return !(*this == right); } -bool Color4B::operator!=(const Color4F& right) const +bool Color32::operator!=(const Color& right) const { return !(*this == right); } /** - * Color4F + * Color */ -bool Color4F::operator==(const Color3B& right) const -{ - return (a == 1.0f && Color3B(*this) == right); -} - -bool Color4F::operator==(const Color4B& right) const +bool Color::operator==(const Color32& right) const { - return (*this == Color4F(right)); + return (*this == Color(right)); } -bool Color4F::operator!=(const Color3B& right) const +bool Color::operator!=(const Color32& right) const { return !(*this == right); } -bool Color4F::operator!=(const Color4B& right) const -{ - return !(*this == right); -} - -/** - * Color constants - */ - -const Color3B Color3B::WHITE(255, 255, 255); -const Color3B Color3B::YELLOW(255, 255, 0); -const Color3B Color3B::GREEN(0, 255, 0); -const Color3B Color3B::BLUE(0, 0, 255); -const Color3B Color3B::RED(255, 0, 0); -const Color3B Color3B::MAGENTA(255, 0, 255); -const Color3B Color3B::BLACK(0, 0, 0); -const Color3B Color3B::ORANGE(255, 127, 0); -const Color3B Color3B::GRAY(166, 166, 166); - -const Color4B Color4B::WHITE(255, 255, 255, 255); -const Color4B Color4B::YELLOW(255, 255, 0, 255); -const Color4B Color4B::GREEN(0, 255, 0, 255); -const Color4B Color4B::BLUE(0, 0, 255, 255); -const Color4B Color4B::RED(255, 0, 0, 255); -const Color4B Color4B::MAGENTA(255, 0, 255, 255); -const Color4B Color4B::BLACK(0, 0, 0, 255); -const Color4B Color4B::ORANGE(255, 127, 0, 255); -const Color4B Color4B::GRAY(166, 166, 166, 255); -const Color4B Color4B::TRANSPARENT(0, 0, 0, 0); - -const Color4F Color4F::WHITE(1, 1, 1, 1); -const Color4F Color4F::YELLOW(1, 1, 0, 1); -const Color4F Color4F::GREEN(0, 1, 0, 1); -const Color4F Color4F::BLUE(0, 0, 1, 1); -const Color4F Color4F::RED(1, 0, 0, 1); -const Color4F Color4F::MAGENTA(1, 0, 1, 1); -const Color4F Color4F::BLACK(0, 0, 0, 1); -const Color4F Color4F::ORANGE(1, 0.5f, 0, 1); -const Color4F Color4F::GRAY(0.65f, 0.65f, 0.65f, 1); -const Color4F Color4F::TRANSPARENT(0, 0, 0, 0); +const Color32 Color32::WHITE(255, 255, 255, 255); +const Color32 Color32::YELLOW(255, 255, 0, 255); +const Color32 Color32::GREEN(0, 255, 0, 255); +const Color32 Color32::BLUE(0, 0, 255, 255); +const Color32 Color32::RED(255, 0, 0, 255); +const Color32 Color32::MAGENTA(255, 0, 255, 255); +const Color32 Color32::BLACK(0, 0, 0, 255); +const Color32 Color32::ORANGE(255, 127, 0, 255); +const Color32 Color32::GRAY(166, 166, 166, 255); +const Color32 Color32::TRANSPARENT(0, 0, 0, 0); + +const Color Color::WHITE(1, 1, 1, 1); +const Color Color::YELLOW(1, 1, 0, 1); +const Color Color::GREEN(0, 1, 0, 1); +const Color Color::BLUE(0, 0, 1, 1); +const Color Color::RED(1, 0, 0, 1); +const Color Color::MAGENTA(1, 0, 1, 1); +const Color Color::BLACK(0, 0, 0, 1); +const Color Color::ORANGE(1, 0.5f, 0, 1); +const Color Color::GRAY(0.65f, 0.65f, 0.65f, 1); +const Color Color::TRANSPARENT(0, 0, 0, 0); HSV::HSV() {} -HSV::HSV(float _h, float _s, float _v, float _a) : Vec4Base(_h, _s, _v, _a) {} +HSV::HSV(float _h, float _s, float _v, float _a) : Vec4Adapter(_h, _s, _v, _a) {} -HSV::HSV(const Color3B& c) +HSV::HSV(const Color32& c) { - fromRgba(Color4F(c)); -}; - -HSV::HSV(const Color4B& c) -{ - fromRgba(Color4F(c)); + fromRgba(Color(c)); } -HSV::HSV(const Color4F& c) +HSV::HSV(const Color& c) { fromRgba(c); } -void HSV::fromRgba(const Color4F& rgba) +void HSV::fromRgba(const Color& rgba) { float fcmax = MAX(MAX(rgba.r, rgba.g), rgba.b); float fcmin = MIN(MIN(rgba.r, rgba.g), rgba.b); @@ -226,9 +153,9 @@ void HSV::fromRgba(const Color4F& rgba) this->a = rgba.a; } -Color4F HSV::toRgba() const +Color HSV::toRgba() const { - auto rgba = Color4F(0, 0, 0, a); + auto rgba = Color(0, 0, 0, a); float hue = remainder(std::fabs(h), 360); hue += 360; @@ -288,40 +215,25 @@ Color4F HSV::toRgba() const return rgba; } -Color3B HSV::toColor3B() const +Color32 HSV::toColor32() const { - return Color3B(toRgba()); -} - -Color4B HSV::toColor4B() const -{ - return Color4B(toRgba()); -} - -Color4F HSV::toColor4F() const -{ - return toRgba(); + return Color32(toRgba()); } HSL::HSL() {} -HSL::HSL(float _h, float _s, float _l, float _a) : Vec4Base(_h, _s, _l, _a) {} - -HSL::HSL(const Color3B& c) -{ - fromRgba(Color4F(c)); -} +HSL::HSL(float _h, float _s, float _l, float _a) : Vec4Adapter(_h, _s, _l, _a) {} -HSL::HSL(const Color4B& c) +HSL::HSL(const Color32& c) { - fromRgba(Color4F(c)); + fromRgba(Color(c)); } -HSL::HSL(const Color4F& c) +HSL::HSL(const Color& c) { fromRgba(c); } -void HSL::fromRgba(const Color4F& rgba) +void HSL::fromRgba(const Color& rgba) { float max = MAX(MAX(rgba.r, rgba.g), rgba.b); float min = MIN(MIN(rgba.r, rgba.g), rgba.b); @@ -372,9 +284,9 @@ float HSL::hue2rgb(float p, float q, float t) return p; } -Color4F HSL::toRgba() const +Color HSL::toRgba() const { - auto rgba = Color4F(0, 0, 0, a); + auto rgba = Color(0, 0, 0, a); float hue = remainder(std::fabs(h), 360); hue += 360; @@ -396,19 +308,9 @@ Color4F HSL::toRgba() const return rgba; } -Color3B HSL::toColor3B() const -{ - return Color3B(toRgba()); -} - -Color4B HSL::toColor4B() const -{ - return Color4B(toRgba()); -} - -Color4F HSL::toColor4F() const +Color32 HSL::toColor32() const { - return Color4F(toRgba()); + return Color32(toRgba()); } NS_AX_MATH_END diff --git a/axmol/math/Color.h b/axmol/math/Color.h new file mode 100644 index 000000000000..ccf419f3d580 --- /dev/null +++ b/axmol/math/Color.h @@ -0,0 +1,228 @@ +/**************************************************************************** + +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + +https://axmol.dev/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#pragma once + +#include "axmol/math/Vec4.h" + +#if defined(_WIN32) +# pragma push_macro("TRANSPARENT") +# undef TRANSPARENT +#endif + +NS_AX_MATH_BEGIN + +struct Color32; +struct Color; +struct HSV; + +/** + * RGBA color composed of 4 bytes. + * @since v3.0 + */ +struct AX_DLL Color32 +{ + Color32() : value(0) {} + Color32(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {} + + Color32(uint8_t _r, uint8_t _g, uint8_t _b) : r(_r), g(_g), b(_b), a(255) {} + + template && + std::is_same_v && + std::is_same_v && + std::is_same_v>, + typename = void> + explicit Color32(const _Other& other) noexcept : r(other.r), g(other.g), b(other.b), a(other.a) + {} + + template && + std::is_same_v && + std::is_same_v && + std::is_same_v>> + explicit Color32(const _Other& other) noexcept + : r(static_cast(other.r * 255.f + 0.5f)) + , g(static_cast(other.g * 255.f + 0.5f)) + , b(static_cast(other.b * 255.f + 0.5f)) + , a(static_cast(other.a * 255.f + 0.5f)) + {} + + // from normalized color, comment to refactor all low performance assign code + template && + std::is_same_v && + std::is_same_v && + std::is_same_v>> + Color32& operator=(const _Other& other) noexcept + { + set(static_cast(other.r * 255.f + 0.5f), static_cast(other.g * 255.f + 0.5f), + static_cast(other.b * 255.f + 0.5f), static_cast(other.a * 255.f + 0.5f)); + return *this; + } + + operator Color() const; + + void set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) + { + r = _r; + g = _g; + b = _b; + a = _a; + } + + bool operator==(const Color32& right) const; + bool operator==(const Color& right) const; + bool operator!=(const Color32& right) const; + bool operator!=(const Color& right) const; + + union + { + struct + { + uint8_t r; + uint8_t g; + uint8_t b; + uint8_t a; + }; + uint32_t value; + }; + + static const Color32 WHITE; + static const Color32 YELLOW; + static const Color32 BLUE; + static const Color32 GREEN; + static const Color32 RED; + static const Color32 MAGENTA; + static const Color32 BLACK; + static const Color32 ORANGE; + static const Color32 GRAY; + static const Color32 TRANSPARENT; // TRANSPARENT is defined on wingdi.h /*Background Modes*/ +}; + +/** + * RGBA color composed of 4 floats. + * @since v3.0, renamed from Color4F + */ +struct AX_DLL Color : public Vec4Adapter +{ + Color() {} + Color(float _r, float _g, float _b, float _a) : Vec4Adapter(_r, _g, _b, _a) {} + Color(float _r, float _g, float _b) : Vec4Adapter(_r, _g, _b, 1.0f) {} + explicit Color(const Color32& color) + : Vec4Adapter(color.r / 255.f, color.g / 255.f, color.b / 255.f, color.a / 255.f) + {} + template + explicit Color(const _Other& color) : Vec4Adapter(color.r, color.g, color.b, color.a) + {} + + static Color fromHex(unsigned int v) + { + auto r = (v >> 24) & 0xff; + auto g = (v >> 16) & 0xff; + auto b = (v >> 8) & 0xff; + auto a = v & 0xff; + return Color{r / 255.f, g / 255.f, b / 255.f, a / 255.f}; + } + + inline Color& premultiplyAlpha() + { + r *= a; + g *= a; + b *= a; + return *this; + } + + bool operator==(const Color32& rhs) const; + bool operator!=(const Color32& rhs) const; + + bool equals(const Color& other) const { return (*this == other); } + + static const Color WHITE; + static const Color YELLOW; + static const Color BLUE; + static const Color GREEN; + static const Color RED; + static const Color MAGENTA; + static const Color BLACK; + static const Color ORANGE; + static const Color GRAY; + static const Color TRANSPARENT; // TRANSPARENT is defined on wingdi.h /*Background Modes*/ +}; + +/** + * Hue Saturation Value color space composed of 4 floats. + * @since axmol-1.0.0b7 + * + * Implementation source: https://gist.github.com/fairlight1337/4935ae72bcbcc1ba5c72 + */ +struct AX_DLL HSV : public Vec4Adapter +{ + HSV(); + HSV(float _h, float _s, float _v, float _a = 1.0F); + explicit HSV(const Color32& c); + explicit HSV(const Color& c); + + bool equals(const HSV& other) const { return (*this == other); } + + void fromRgba(const Color& rgba); + Color toRgba() const; + Color32 toColor32() const; +}; + +/** + * Hue Saturation Luminance color space composed of 4 floats. + * @since axmol-1.0.0b7 + * + * Implementation source: https://gist.github.com/ciembor/1494530 + */ +struct AX_DLL HSL : public Vec4Adapter +{ + HSL(); + HSL(float _h, float _s, float _l, float _a = 1.0F); + + explicit HSL(const Color32& c); + explicit HSL(const Color& c); + + bool equals(const HSL& other) const { return (*this == other); } + + void fromRgba(const Color& rgba); + Color toRgba() const; + + static float hue2rgb(float p, float q, float t); + + Color32 toColor32() const; +}; + +inline Color32::operator Color() const +{ + return Color{r / 255.f, g / 255.f, b / 255.f, a / 255.f}; +} + +NS_AX_MATH_END + +#if defined(_WIN32) +# pragma pop_macro("TRANSPARENT") +#endif diff --git a/core/math/FastRNG.h b/axmol/math/FastRNG.h similarity index 98% rename from core/math/FastRNG.h rename to axmol/math/FastRNG.h index 7298dcbb8139..49f7de965eea 100644 --- a/core/math/FastRNG.h +++ b/axmol/math/FastRNG.h @@ -24,8 +24,8 @@ #pragma once -#include "base/Macros.h" -#include "math/MathBase.h" +#include "axmol/base/Macros.h" +#include "axmol/math/MathBase.h" #include #include diff --git a/core/math/Mat3.h b/axmol/math/Mat3.h similarity index 69% rename from core/math/Mat3.h rename to axmol/math/Mat3.h index 4090a5e3d178..12400fe4f9ff 100644 --- a/core/math/Mat3.h +++ b/axmol/math/Mat3.h @@ -1,14 +1,13 @@ #pragma once -#include "math/MathBase.h" +#include "axmol/math/MathBase.h" NS_AX_MATH_BEGIN -// both metal and GLSL3/ESSL3 mat3 is identical to mat3x4, +// both metal, d3d11, gl-3.3, gles-3.0 mat3 in shader is identical to mat3x4, // so provide this helper struct to construct mat3 match with GPU struct Mat3 { -#if AX_GLES_PROFILE != 200 enum Index { _M00 = 0, @@ -21,20 +20,7 @@ struct Mat3 _M21 = 9, _M22 = 10 }; -#else - enum Index - { - _M00 = 0, - _M01 = 1, - _M02 = 2, - _M10 = 3, - _M11 = 4, - _M12 = 5, - _M20 = 6, - _M21 = 7, - _M22 = 8 - }; -#endif + Mat3() = default; Mat3(float m00, float m01, float m02, float m10, float m11, float m12, float m20, float m21, float m22) { @@ -57,19 +43,11 @@ struct Mat3 } float* operator[](size_t rowIndex) { -#if AX_GLES_PROFILE != 200 assert(rowIndex < 3); return &m[rowIndex * 4]; -#else - assert(rowIndex < 2); - return &m[rowIndex * 3]; -#endif } -#if AX_GLES_PROFILE != 200 + float m[12] = {}; -#else - float m[9] = {}; -#endif }; NS_AX_MATH_END diff --git a/core/math/Mat4.cpp b/axmol/math/Mat4.cpp similarity index 99% rename from core/math/Mat4.cpp rename to axmol/math/Mat4.cpp index 72ab74acc1eb..8d167233eafb 100644 --- a/core/math/Mat4.cpp +++ b/axmol/math/Mat4.cpp @@ -20,12 +20,12 @@ This file was modified to fit the axmol project */ -#include "math/Mat4.h" +#include "axmol/math/Mat4.h" #include -#include "math/Quaternion.h" -#include "math/MathUtil.h" -#include "base/Macros.h" +#include "axmol/math/Quaternion.h" +#include "axmol/math/MathUtil.h" +#include "axmol/base/Macros.h" NS_AX_MATH_BEGIN @@ -121,7 +121,7 @@ void Mat4::createPerspective(float fieldOfView, float aspectRatio, float zNearPl dst->m[14] = -2.0f * zFarPlane * zNearPlane * f_n; // https://metashapes.com/blog/opengl-metal-projection-matrix-problem/ -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL dst->m[10] = -(zFarPlane)*f_n; dst->m[14] = -(zFarPlane * zNearPlane) * f_n; #endif @@ -158,7 +158,7 @@ void Mat4::createOrthographicOffCenter(float left, dst->m[15] = 1; //// https://metashapes.com/blog/opengl-metal-projection-matrix-problem/ -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL dst->m[10] = 1 / (zNearPlane - zFarPlane); dst->m[14] = zNearPlane / (zNearPlane - zFarPlane); #endif diff --git a/core/math/Mat4.h b/axmol/math/Mat4.h similarity index 99% rename from core/math/Mat4.h rename to axmol/math/Mat4.h index 554eabdb923a..0fcaf7b50c14 100644 --- a/core/math/Mat4.h +++ b/axmol/math/Mat4.h @@ -23,10 +23,10 @@ #pragma once -#include "base/Macros.h" +#include "axmol/base/Macros.h" -#include "math/Vec3.h" -#include "math/Vec4.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Vec4.h" /** * @addtogroup base diff --git a/core/math/Math.h b/axmol/math/Math.h similarity index 85% rename from core/math/Math.h rename to axmol/math/Math.h index 815d0a4e14f2..ec30d1b62f3e 100644 --- a/core/math/Math.h +++ b/axmol/math/Math.h @@ -24,11 +24,11 @@ #pragma once -#include "math/Vec2.h" -#include "math/Vec3.h" -#include "math/Vec4.h" -#include "math/Mat4.h" -#include "math/Rect.h" -#include "math/Quaternion.h" -#include "math/Color.h" +#include "axmol/math/Vec2.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Vec4.h" +#include "axmol/math/Mat4.h" +#include "axmol/math/Rect.h" +#include "axmol/math/Quaternion.h" +#include "axmol/math/Color.h" diff --git a/core/math/MathBase.h b/axmol/math/MathBase.h similarity index 98% rename from core/math/MathBase.h rename to axmol/math/MathBase.h index 1953cb9958ac..d900cf5b3f0c 100644 --- a/core/math/MathBase.h +++ b/axmol/math/MathBase.h @@ -27,7 +27,7 @@ #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" /** * @addtogroup base diff --git a/core/math/MathUtil.cpp b/axmol/math/MathUtil.cpp similarity index 95% rename from core/math/MathUtil.cpp rename to axmol/math/MathUtil.cpp index f2ca2ce8dd1d..6fb7855ca7c6 100644 --- a/core/math/MathUtil.cpp +++ b/axmol/math/MathUtil.cpp @@ -20,21 +20,21 @@ Original file from GamePlay3D: http://gameplay3d.org This file was modified to fit the axmol project */ -#include "math/MathUtil.h" -#include "math/Mat4.h" -#include "base/Macros.h" +#include "axmol/math/MathUtil.h" +#include "axmol/math/Mat4.h" +#include "axmol/base/Macros.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) # include #endif #if defined(AX_SSE_INTRINSICS) -# include "math/MathUtilSSE.inl" +# include "axmol/math/MathUtilSSE.inl" #elif defined(AX_NEON_INTRINSICS) -# include "math/MathUtilNeon.inl" +# include "axmol/math/MathUtilNeon.inl" #endif -#include "math/MathUtil.inl" +#include "axmol/math/MathUtil.inl" NS_AX_MATH_BEGIN @@ -283,13 +283,13 @@ void MathUtil::crossVec3(const float* v1, const float* v2, float* dst) #endif } -void MathUtil::transformVertices(V3F_C4B_T2F* dst, const V3F_C4B_T2F* src, size_t count, const Mat4& transform) +void MathUtil::transformVertices(V3F_T2F_C4B* dst, const V3F_T2F_C4B* src, size_t count, const Mat4& transform) { // Check some assumptions made by optimizations - static_assert(sizeof(V3F_C4B_T2F) == 24); - static_assert(offsetof(V3F_C4B_T2F, vertices) == 0); - static_assert(offsetof(V3F_C4B_T2F, colors) == 12); - static_assert(offsetof(V3F_C4B_T2F, texCoords) == 16); + static_assert(sizeof(V3F_T2F_C4B) == 24); + static_assert(offsetof(V3F_T2F_C4B, position) == 0); + static_assert(offsetof(V3F_T2F_C4B, texCoord) == 12); + static_assert(offsetof(V3F_T2F_C4B, color) == 20); #if defined(AX_SSE_INTRINSICS) MathUtilSSE::transformVertices(dst, src, count, transform); #elif defined(AX_NEON_INTRINSICS) diff --git a/core/math/MathUtil.h b/axmol/math/MathUtil.h similarity index 95% rename from core/math/MathUtil.h rename to axmol/math/MathUtil.h index d09af16c85d3..f6b49d4fa005 100644 --- a/core/math/MathUtil.h +++ b/axmol/math/MathUtil.h @@ -23,12 +23,12 @@ #pragma once -#include "math/MathBase.h" +#include "axmol/math/MathBase.h" namespace ax { - struct V3F_C4B_T2F; + struct V3F_T2F_C4B; } /** @@ -118,7 +118,7 @@ class AX_DLL MathUtil static void crossVec3(const float* v1, const float* v2, float* dst); - static void transformVertices(V3F_C4B_T2F* dst, const V3F_C4B_T2F* src, size_t count, const Mat4& transform); + static void transformVertices(V3F_T2F_C4B* dst, const V3F_T2F_C4B* src, size_t count, const Mat4& transform); static void transformIndices(uint16_t* dst, const uint16_t* src, size_t count, uint16_t offset); }; diff --git a/core/math/MathUtil.inl b/axmol/math/MathUtil.inl similarity index 94% rename from core/math/MathUtil.inl rename to axmol/math/MathUtil.inl index 649cb0426786..d1971cbd11e1 100644 --- a/core/math/MathUtil.inl +++ b/axmol/math/MathUtil.inl @@ -191,7 +191,7 @@ public: dst[2] = z; } - inline static void transformVertices(V3F_C4B_T2F* dst, const V3F_C4B_T2F* src, size_t count, const Mat4& transform) + inline static void transformVertices(V3F_T2F_C4B* dst, const V3F_T2F_C4B* src, size_t count, const Mat4& transform) { auto end = dst + count; auto& t = transform; // Make copy for better aliasing inference @@ -199,11 +199,12 @@ public: while (dst < end) { - auto pos = src->vertices; - dst->vertices.x = pos.x * m[0] + pos.y * m[4] + pos.z * m[8] + m[12]; - dst->vertices.y = pos.x * m[1] + pos.y * m[5] + pos.z * m[9] + m[13]; - dst->vertices.z = pos.x * m[2] + pos.y * m[6] + pos.z * m[10] + m[14]; - memcpy(&dst->colors, &src->colors, sizeof(V3F_C4B_T2F::colors) + sizeof(V3F_C4B_T2F::texCoords)); + auto pos = src->position; + dst->position.x = pos.x * m[0] + pos.y * m[4] + pos.z * m[8] + m[12]; + dst->position.y = pos.x * m[1] + pos.y * m[5] + pos.z * m[9] + m[13]; + dst->position.z = pos.x * m[2] + pos.y * m[6] + pos.z * m[10] + m[14]; + dst->texCoord = src->texCoord; + dst->color = src->color; ++dst; ++src; } diff --git a/core/math/MathUtilNeon.inl b/axmol/math/MathUtilNeon.inl similarity index 76% rename from core/math/MathUtilNeon.inl rename to axmol/math/MathUtilNeon.inl index d85324ddc541..1db8ea891bd9 100644 --- a/core/math/MathUtilNeon.inl +++ b/axmol/math/MathUtilNeon.inl @@ -147,7 +147,7 @@ struct MathUtilNeon } #if AX_64BITS - inline static void transformVertices(V3F_C4B_T2F* dst, const V3F_C4B_T2F* src, size_t count, const Mat4& transform) + inline static void transformVertices(V3F_T2F_C4B* dst, const V3F_T2F_C4B* src, size_t count, const Mat4& transform) { auto end = dst + count; @@ -159,26 +159,26 @@ struct MathUtilNeon while (dst < end4) { // Do this for each vertex - // dst->vertices.x = pos.x * m[0] + pos.y * m[4] + pos.z * m[8] + m[12]; - // dst->vertices.y = pos.x * m[1] + pos.y * m[5] + pos.z * m[9] + m[13]; - // dst->vertices.z = pos.x * m[2] + pos.y * m[6] + pos.z * m[10] + m[14]; + // dst->position.x = pos.x * m[0] + pos.y * m[4] + pos.z * m[8] + m[12]; + // dst->position.y = pos.x * m[1] + pos.y * m[5] + pos.z * m[9] + m[13]; + // dst->position.z = pos.x * m[2] + pos.y * m[6] + pos.z * m[10] + m[14]; // First, load each vertex, multiply x by column 0 and add to column 3 - // Note: since we're reading 4 floats it will load color bytes into v.w - float32x4_t v0 = vld1q_f32(&src[0].vertices.x); + // Note: since we're reading 4 floats it will load uv.u into v.w + float32x4_t v0 = vld1q_f32(&src[0].position.x); float32x4_t r0 = vmlaq_laneq_f32(m.val[3], m.val[0], v0, 0); - float32x4_t v1 = vld1q_f32(&src[1].vertices.x); + float32x4_t v1 = vld1q_f32(&src[1].position.x); float32x4_t r1 = vmlaq_laneq_f32(m.val[3], m.val[0], v1, 0); - float32x4_t v2 = vld1q_f32(&src[2].vertices.x); + float32x4_t v2 = vld1q_f32(&src[2].position.x); float32x4_t r2 = vmlaq_laneq_f32(m.val[3], m.val[0], v2, 0); - float32x4_t v3 = vld1q_f32(&src[3].vertices.x); + float32x4_t v3 = vld1q_f32(&src[3].position.x); float32x4_t r3 = vmlaq_laneq_f32(m.val[3], m.val[0], v3, 0); - // Load texCoords - float32x2_t uv0 = vld1_f32(&src[0].texCoords.u); - float32x2_t uv1 = vld1_f32(&src[1].texCoords.u); - float32x2_t uv2 = vld1_f32(&src[2].texCoords.u); - float32x2_t uv3 = vld1_f32(&src[3].texCoords.u); + // Load texCoord.v and color32 + float32x2_t vc0 = vld1_f32(&src[0].texCoord.v); + float32x2_t vc1 = vld1_f32(&src[1].texCoord.v); + float32x2_t vc2 = vld1_f32(&src[2].texCoord.v); + float32x2_t vc3 = vld1_f32(&src[3].texCoord.v); // Multiply y by column 1 and add to result r0 = vmlaq_laneq_f32(r0, m.val[1], v0, 1); @@ -192,21 +192,21 @@ struct MathUtilNeon r2 = vmlaq_laneq_f32(r2, m.val[2], v2, 2); r3 = vmlaq_laneq_f32(r3, m.val[2], v3, 2); - // Set w to loaded color + // Set w to loaded uv.u r0 = vsetq_lane_f32(vgetq_lane_f32(v0, 3), r0, 3); r1 = vsetq_lane_f32(vgetq_lane_f32(v1, 3), r1, 3); r2 = vsetq_lane_f32(vgetq_lane_f32(v2, 3), r2, 3); r3 = vsetq_lane_f32(vgetq_lane_f32(v3, 3), r3, 3); // Store result - vst1q_f32(&dst[0].vertices.x, r0); - vst1_f32(&dst[0].texCoords.u, uv0); - vst1q_f32(&dst[1].vertices.x, r1); - vst1_f32(&dst[1].texCoords.u, uv1); - vst1q_f32(&dst[2].vertices.x, r2); - vst1_f32(&dst[2].texCoords.u, uv2); - vst1q_f32(&dst[3].vertices.x, r3); - vst1_f32(&dst[3].texCoords.u, uv3); + vst1q_f32(&dst[0].position.x, r0); + vst1_f32(&dst[0].texCoord.v, vc0); + vst1q_f32(&dst[1].position.x, r1); + vst1_f32(&dst[1].texCoord.v, vc1); + vst1q_f32(&dst[2].position.x, r2); + vst1_f32(&dst[2].texCoord.v, vc2); + vst1q_f32(&dst[3].position.x, r3); + vst1_f32(&dst[3].texCoord.v, vc3); dst += 4; src += 4; @@ -215,14 +215,14 @@ struct MathUtilNeon // Process remaining vertices one by one while (dst < end) { - float32x4_t v = vld1q_f32(&src->vertices.x); + float32x4_t v = vld1q_f32(&src->position.x); float32x4_t r = vmlaq_laneq_f32(m.val[3], m.val[0], v, 0); r = vmlaq_laneq_f32(r, m.val[1], v, 1); r = vmlaq_laneq_f32(r, m.val[2], v, 2); r = vsetq_lane_f32(vgetq_lane_f32(v, 3), r, 3); - float32x2_t uv = vld1_f32(&src->texCoords.u); - vst1q_f32(&dst->vertices.x, r); - vst1_f32(&dst->texCoords.u, uv); + float32x2_t vc = vld1_f32(&src->texCoord.v); + vst1q_f32(&dst->position.x, r); + vst1_f32(&dst->texCoord.v, vc); ++dst; ++src; @@ -280,8 +280,8 @@ struct MathUtilNeon } } #else - inline static void transformVertices(ax::V3F_C4B_T2F* dst, - const ax::V3F_C4B_T2F* src, + inline static void transformVertices(ax::V3F_T2F_C4B* dst, + const ax::V3F_T2F_C4B* src, size_t count, const ax::Mat4& transform) { @@ -297,19 +297,19 @@ struct MathUtilNeon auto end4 = dst + count / 4 * 4; while (dst < end4) { - // Load 4 vertices. Note that color will also get loaded into w - float32x2_t xy0 = vld1_f32(&src[0].vertices.x); - float32x2_t zw0 = vld1_f32(&src[0].vertices.z); - float32x2_t uv0 = vld1_f32(&src[0].texCoords.u); - float32x2_t xy1 = vld1_f32(&src[1].vertices.x); - float32x2_t zw1 = vld1_f32(&src[1].vertices.z); - float32x2_t uv1 = vld1_f32(&src[1].texCoords.u); - float32x2_t xy2 = vld1_f32(&src[2].vertices.x); - float32x2_t zw2 = vld1_f32(&src[2].vertices.z); - float32x2_t uv2 = vld1_f32(&src[2].texCoords.u); - float32x2_t xy3 = vld1_f32(&src[3].vertices.x); - float32x2_t zw3 = vld1_f32(&src[3].vertices.z); - float32x2_t uv3 = vld1_f32(&src[3].texCoords.u); + // Load 4 vertices. Note that texCoord.u will also get loaded into w + float32x2_t xy0 = vld1_f32(&src[0].position.x); + float32x2_t zw0 = vld1_f32(&src[0].position.z); + //float32x2_t uv0 = vld1_f32(&src[0].texCoord.u); + float32x2_t xy1 = vld1_f32(&src[1].position.x); + float32x2_t zw1 = vld1_f32(&src[1].position.z); + //float32x2_t uv1 = vld1_f32(&src[1].texCoord.u); + float32x2_t xy2 = vld1_f32(&src[2].position.x); + float32x2_t zw2 = vld1_f32(&src[2].position.z); + //float32x2_t uv2 = vld1_f32(&src[2].texCoord.u); + float32x2_t xy3 = vld1_f32(&src[3].position.x); + float32x2_t zw3 = vld1_f32(&src[3].position.z); + //float32x2_t uv3 = vld1_f32(&src[3].texCoord.u); // Multiply x by column 0 float32x4_t r0 = vmulq_lane_f32(mc0, xy0, 0); @@ -335,21 +335,27 @@ struct MathUtilNeon r2 = vaddq_f32(r2, mc3); r3 = vaddq_f32(r3, mc3); - // Set color + // Set uv.u r0 = vsetq_lane_f32(vget_lane_f32(zw0, 1), r0, 3); r1 = vsetq_lane_f32(vget_lane_f32(zw1, 1), r1, 3); r2 = vsetq_lane_f32(vget_lane_f32(zw2, 1), r2, 3); r3 = vsetq_lane_f32(vget_lane_f32(zw3, 1), r3, 3); + // Load texCoords.v and color32 + float32x2_t vc0 = vld1_f32(&src[0].texCoord.v); + float32x2_t vc1 = vld1_f32(&src[1].texCoord.v); + float32x2_t vc2 = vld1_f32(&src[2].texCoord.v); + float32x2_t vc3 = vld1_f32(&src[3].texCoord.v); + // Store result - vst1q_f32(&dst[0].vertices.x, r0); - vst1_f32(&dst[0].texCoords.u, uv0); - vst1q_f32(&dst[1].vertices.x, r1); - vst1_f32(&dst[1].texCoords.u, uv1); - vst1q_f32(&dst[2].vertices.x, r2); - vst1_f32(&dst[2].texCoords.u, uv2); - vst1q_f32(&dst[3].vertices.x, r3); - vst1_f32(&dst[3].texCoords.u, uv3); + vst1q_f32(&dst[0].position.x, r0); + vst1_f32(&dst[0].texCoord.v, vc0); + vst1q_f32(&dst[1].position.x, r1); + vst1_f32(&dst[1].texCoord.v, vc1); + vst1q_f32(&dst[2].position.x, r2); + vst1_f32(&dst[2].texCoord.v, vc2); + vst1q_f32(&dst[3].position.x, r3); + vst1_f32(&dst[3].texCoord.v, vc3); dst += 4; src += 4; @@ -359,9 +365,9 @@ struct MathUtilNeon while (dst < end) { // Load vertex - float32x2_t xy = vld1_f32(&src->vertices.x); - float32x2_t zw = vld1_f32(&src->vertices.z); - float32x2_t uv = vld1_f32(&src->texCoords.u); + float32x2_t xy = vld1_f32(&src->position.x); + float32x2_t zw = vld1_f32(&src->position.z); + float32x2_t vc = vld1_f32(&src->texCoord.v); // Multiply x by column 0 float32x4_t r = vmulq_lane_f32(mc0, xy, 0); @@ -376,8 +382,8 @@ struct MathUtilNeon r = vsetq_lane_f32(vget_lane_f32(zw, 1), r, 3); // Store result - vst1q_f32(&dst->vertices.x, r); - vst1_f32(&dst->texCoords.u, uv); + vst1q_f32(&dst->position.x, r); + vst1_f32(&dst->texCoord.v, vc); ++dst; ++src; diff --git a/core/math/MathUtilSSE.inl b/axmol/math/MathUtilSSE.inl similarity index 93% rename from core/math/MathUtilSSE.inl rename to axmol/math/MathUtilSSE.inl index 4869fe98b1de..26dc9d5cf051 100644 --- a/core/math/MathUtilSSE.inl +++ b/axmol/math/MathUtilSSE.inl @@ -230,23 +230,27 @@ struct MathUtilSSE # endif } - static void transformVertices(V3F_C4B_T2F* dst, const V3F_C4B_T2F* src, size_t count, const Mat4& transform) + static void transformVertices(V3F_T2F_C4B* dst, const V3F_T2F_C4B* src, size_t count, const Mat4& transform) { auto& m = transform.col; for (size_t i = 0; i < count; ++i) { - auto& vert = src[i].vertices; + auto& vert = src[i].position; __m128 v = _mm_set_ps(1.0f, vert.z, vert.y, vert.x); v = _mm_add_ps( _mm_add_ps(_mm_mul_ps(m[0], _mm_shuffle_ps(v, v, 0)), _mm_mul_ps(m[1], _mm_shuffle_ps(v, v, 0x55))), _mm_add_ps(_mm_mul_ps(m[2], _mm_shuffle_ps(v, v, 0xaa)), _mm_mul_ps(m[3], _mm_shuffle_ps(v, v, 0xff)))); - _mm_storeu_ps((float*)&dst[i].vertices, v); - - // Copy tex coords and colors - // dst[i].texCoords = src[i].texCoords; - // dst[i].colors = src[i].colors; - memcpy(&dst[i].colors, &src[i].colors, sizeof(V3F_C4B_T2F::colors) + sizeof(V3F_C4B_T2F::texCoords)); + _mm_storeu_ps((float*)&dst[i].position, v); + + // Copy tex coord and color (12 bytes) + // memcpy(&dst[i].texCoord, &src[i].texCoord, sizeof(V3F_T2F_C4B::color) + sizeof(V3F_T2F_C4B::texCoord)); + dst[i].texCoord.u = src[i].texCoord.u; + dst[i].texCoord.v = src[i].texCoord.v; + dst[i].color.r = src[i].color.r; + dst[i].color.g = src[i].color.g; + dst[i].color.b = src[i].color.b; + dst[i].color.a = src[i].color.a; } } diff --git a/core/math/Quaternion.cpp b/axmol/math/Quaternion.cpp similarity index 99% rename from core/math/Quaternion.cpp rename to axmol/math/Quaternion.cpp index bf8bef48a666..bd5c425cf4b0 100644 --- a/core/math/Quaternion.cpp +++ b/axmol/math/Quaternion.cpp @@ -19,10 +19,10 @@ This file was modified to fit the cocos2d-x project */ -#include "math/Quaternion.h" +#include "axmol/math/Quaternion.h" #include -#include "base/Macros.h" +#include "axmol/base/Macros.h" NS_AX_MATH_BEGIN diff --git a/core/math/Quaternion.h b/axmol/math/Quaternion.h similarity index 97% rename from core/math/Quaternion.h rename to axmol/math/Quaternion.h index ea81e95436d5..a5a9a4dbfc26 100644 --- a/core/math/Quaternion.h +++ b/axmol/math/Quaternion.h @@ -22,9 +22,9 @@ #pragma once -#include "base/Macros.h" -#include "math/Vec3.h" -#include "math/Mat4.h" +#include "axmol/base/Macros.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Mat4.h" //#include "Plane.h" /** @@ -77,22 +77,14 @@ class AX_DLL Quaternion friend class Transform; public: - /** - * The x-value of the quaternion's vector component. - */ - float x; - /** - * The y-value of the quaternion's vector component. - */ - float y; - /** - * The z-value of the quaternion's vector component. - */ - float z; - /** - * The scalar component of the quaternion. - */ - float w; + union + { + struct + { + float x, y, z, w; + }; + float comps[4]; + }; /** * Constructs a quaternion initialized to (0, 0, 0, 1). diff --git a/core/math/Rect.cpp b/axmol/math/Rect.cpp similarity index 98% rename from core/math/Rect.cpp rename to axmol/math/Rect.cpp index 05fb79adbe90..e74a5804af03 100644 --- a/core/math/Rect.cpp +++ b/axmol/math/Rect.cpp @@ -24,11 +24,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "math/Rect.h" +#include "axmol/math/Rect.h" #include #include -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/core/math/Rect.h b/axmol/math/Rect.h similarity index 99% rename from core/math/Rect.h rename to axmol/math/Rect.h index b25ac031a338..7dbe87caa213 100644 --- a/core/math/Rect.h +++ b/axmol/math/Rect.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once -#include "math/Vec2.h" +#include "axmol/math/Vec2.h" /** * @addtogroup base diff --git a/core/math/TransformUtils.cpp b/axmol/math/TransformUtils.cpp similarity index 96% rename from core/math/TransformUtils.cpp rename to axmol/math/TransformUtils.cpp index 907a02e17870..b3b01c3d8f37 100644 --- a/core/math/TransformUtils.cpp +++ b/axmol/math/TransformUtils.cpp @@ -25,8 +25,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "math/TransformUtils.h" -#include "math/AffineTransform.h" +#include "axmol/math/TransformUtils.h" +#include "axmol/math/AffineTransform.h" namespace ax { diff --git a/core/math/TransformUtils.h b/axmol/math/TransformUtils.h similarity index 98% rename from core/math/TransformUtils.h rename to axmol/math/TransformUtils.h index c7e60cf04252..27a37fb1d0d6 100644 --- a/core/math/TransformUtils.h +++ b/axmol/math/TransformUtils.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once -#include "base/Macros.h" +#include "axmol/base/Macros.h" /** * @addtogroup base diff --git a/core/math/Vec2.cpp b/axmol/math/Vec2.cpp similarity index 98% rename from core/math/Vec2.cpp rename to axmol/math/Vec2.cpp index 3d451fe45352..327a72e7ca1e 100644 --- a/core/math/Vec2.cpp +++ b/axmol/math/Vec2.cpp @@ -19,9 +19,9 @@ This file was modified to fit the cocos2d-x project */ -#include "math/Vec2.h" -#include "math/MathUtil.h" -#include "base/Macros.h" +#include "axmol/math/Vec2.h" +#include "axmol/math/MathUtil.h" +#include "axmol/base/Macros.h" NS_AX_MATH_BEGIN diff --git a/core/math/Vec2.h b/axmol/math/Vec2.h similarity index 99% rename from core/math/Vec2.h rename to axmol/math/Vec2.h index 5812f2d79166..2cd77f0dc7a6 100644 --- a/core/math/Vec2.h +++ b/axmol/math/Vec2.h @@ -29,8 +29,8 @@ #include #include -#include "base/Macros.h" -#include "math/MathBase.h" +#include "axmol/base/Macros.h" +#include "axmol/math/MathBase.h" /** * @addtogroup base diff --git a/core/math/Vec3.cpp b/axmol/math/Vec3.cpp similarity index 90% rename from core/math/Vec3.cpp rename to axmol/math/Vec3.cpp index 60c9235eda99..c71429c1a90c 100644 --- a/core/math/Vec3.cpp +++ b/axmol/math/Vec3.cpp @@ -1,6 +1,7 @@ /** Copyright 2013 BlackBerry Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. @@ -16,12 +17,12 @@ Original file from GamePlay3D: http://gameplay3d.org - This file was modified to fit the cocos2d-x project + This file was modified to fit the axmol project */ -#include "math/Vec3.h" -#include "math/MathUtil.h" -#include "base/Macros.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/MathUtil.h" +#include "axmol/base/Macros.h" NS_AX_MATH_BEGIN @@ -33,22 +34,6 @@ NS_AX_MATH_BEGIN const Vec3 Vec3::UNIT_Z(0.0f, 0.0f, 1.0f); #endif - -Vec3 Vec3::fromColor(unsigned int color) -{ - float components[3]; - int componentIndex = 0; - for (int i = 2; i >= 0; --i) - { - int component = (color >> i * 8) & 0x0000ff; - - components[componentIndex++] = static_cast(component) / 255.0f; - } - - Vec3 value(components); - return value; -} - float Vec3::angle(const Vec3& v1, const Vec3& v2) { float dx = v1.y * v2.z - v1.z * v2.y; diff --git a/core/math/Vec3.h b/axmol/math/Vec3.h similarity index 96% rename from core/math/Vec3.h rename to axmol/math/Vec3.h index 6a562ada8ab8..ed39977e80a1 100644 --- a/core/math/Vec3.h +++ b/axmol/math/Vec3.h @@ -23,8 +23,8 @@ #pragma once #include -#include "base/Macros.h" -#include "math/MathBase.h" +#include "axmol/base/Macros.h" +#include "axmol/math/MathBase.h" /** * @addtogroup base @@ -48,20 +48,18 @@ class Quaternion; class AX_DLL Vec3 { public: - /** - * The x-coordinate. - */ - float x; + union + { + float comps[3]; - /** - * The y-coordinate. - */ - float y; - - /** - * The z-coordinate. - */ - float z; + // The coord alias + struct + { + float x; + float y; + float z; + }; + }; /** * Constructs a new vector initialized to all zeros. @@ -92,16 +90,6 @@ class AX_DLL Vec3 */ constexpr Vec3(const Vec3& p1, const Vec3& p2) { set(p1, p2); } - /** - * Creates a new vector from an integer interpreted as an RGB value. - * E.g. 0xff0000 represents red or the vector (1, 0, 0). - * - * @param color The integer to interpret as an RGB value. - * - * @return A vector corresponding to the interpreted RGB color. - */ - static Vec3 fromColor(unsigned int color); - /** * Indicates whether this vector contains all zeros. * diff --git a/core/math/Vec4.cpp b/axmol/math/Vec4.cpp similarity index 88% rename from core/math/Vec4.cpp rename to axmol/math/Vec4.cpp index 3d26db646e3c..2b09da4132e8 100644 --- a/core/math/Vec4.cpp +++ b/axmol/math/Vec4.cpp @@ -17,14 +17,14 @@ Original file from GamePlay3D: http://gameplay3d.org - This file was modified to fit the cocos2d-x project + This file was modified to fit the axmol project */ -#include "math/Vec4.h" +#include "axmol/math/Vec4.h" #include -#include "math/MathUtil.h" -#include "base/Macros.h" +#include "axmol/math/MathUtil.h" +#include "axmol/base/Macros.h" NS_AX_MATH_BEGIN @@ -37,52 +37,8 @@ NS_AX_MATH_BEGIN const Vec4 Vec4::UNIT_W = Vec4(0.0f, 0.0f, 0.0f, 1.0f); #endif - -Vec4 Vec4::fromColor(unsigned int color) -{ - float components[4]; - int componentIndex = 0; - for (int i = 3; i >= 0; --i) - { - int component = (color >> i * 8) & 0x000000ff; - - components[componentIndex++] = static_cast(component) / 255.0f; - } - - Vec4 value(components); - return value; -} - -bool Vec4::isZero() const -{ - return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f; -} - -bool Vec4::isOne() const -{ - return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f; -} - -float Vec4::angle(const Vec4& v1, const Vec4& v2) -{ - float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y; - float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z; - float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x; - - return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2)); -} - -void Vec4::add(const Vec4& v1, const Vec4& v2, Vec4* dst) -{ - AX_ASSERT(dst); - - dst->x = v1.x + v2.x; - dst->y = v1.y + v2.y; - dst->z = v1.z + v2.z; - dst->w = v1.w + v2.w; -} - -void Vec4::clamp(const Vec4& min, const Vec4& max) + +void Vec4Base::clamp(const Vec4Base& min, const Vec4Base& max) { AX_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w)); @@ -111,7 +67,7 @@ void Vec4::clamp(const Vec4& min, const Vec4& max) w = max.w; } -void Vec4::clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst) +void Vec4Base::clamp(const Vec4Base& v, const Vec4Base& min, const Vec4Base& max, Vec4Base* dst) { AX_ASSERT(dst); AX_ASSERT(!(min.x > max.x || min.y > max.y || min.z > max.z || min.w > max.w)); @@ -145,6 +101,35 @@ void Vec4::clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst) dst->w = max.w; } +bool Vec4::isZero() const +{ + return x == 0.0f && y == 0.0f && z == 0.0f && w == 0.0f; +} + +bool Vec4::isOne() const +{ + return x == 1.0f && y == 1.0f && z == 1.0f && w == 1.0f; +} + +float Vec4::angle(const Vec4& v1, const Vec4& v2) +{ + float dx = v1.w * v2.x - v1.x * v2.w - v1.y * v2.z + v1.z * v2.y; + float dy = v1.w * v2.y - v1.y * v2.w - v1.z * v2.x + v1.x * v2.z; + float dz = v1.w * v2.z - v1.z * v2.w - v1.x * v2.y + v1.y * v2.x; + + return std::atan2(std::sqrt(dx * dx + dy * dy + dz * dz) + MATH_FLOAT_SMALL, dot(v1, v2)); +} + +void Vec4::add(const Vec4& v1, const Vec4& v2, Vec4* dst) +{ + AX_ASSERT(dst); + + dst->x = v1.x + v2.x; + dst->y = v1.y + v2.y; + dst->z = v1.z + v2.z; + dst->w = v1.w + v2.w; +} + float Vec4::distance(const Vec4& v) const { float dx = v.x - x; diff --git a/core/math/Vec4.h b/axmol/math/Vec4.h similarity index 90% rename from core/math/Vec4.h rename to axmol/math/Vec4.h index 974510326fd2..60867fcc1785 100644 --- a/core/math/Vec4.h +++ b/axmol/math/Vec4.h @@ -23,8 +23,8 @@ #pragma once -#include "base/Macros.h" -#include "math/MathBase.h" +#include "axmol/base/Macros.h" +#include "axmol/math/MathBase.h" /** * @addtogroup base @@ -35,18 +35,73 @@ NS_AX_MATH_BEGIN class Mat4; -/* - * @brief A 4-floats class template with base math operators - */ -template -class Vec4Base +struct AX_DLL Vec4Base { -public: - using impl_type = _ImplType; - constexpr Vec4Base() : x(0.0f), y(0.0f), z(0.0f), w(0.0f) {} constexpr Vec4Base(float xx, float yy, float zz, float ww) : x(xx), y(yy), z(zz), w(ww) {} - constexpr explicit Vec4Base(const float* src) { this->set(src); } + explicit Vec4Base(const float* src) { this->set(src); } + + /** + * Sets the elements of this vector to those in the specified vector. + * + * @param v The vector to copy. + */ + void set(const Vec4Base& v) + { + this->x = v.x; + this->y = v.y; + this->z = v.z; + this->w = v.w; + } + + /** + * Sets the elements of this vector to the specified values. + * + * @param xx The new x coordinate. + * @param yy The new y coordinate. + * @param zz The new z coordinate. + * @param ww The new w coordinate. + */ + constexpr void set(float xx, float yy, float zz, float ww) + { + this->x = xx; + this->y = yy; + this->z = zz; + this->w = ww; + } + + /** + * Sets the elements of this vector from the values in the specified array. + * + * @param array An array containing the elements of the vector in the order x, y, z, w. + */ + void set(const float* array) + { + AX_ASSERT(array); + + this->x = array[0]; + this->y = array[1]; + this->z = array[2]; + this->w = array[3]; + } + + /** + * Clamps this vector within the specified range. + * + * @param min The minimum value. + * @param max The maximum value. + */ + void clamp(const Vec4Base& min, const Vec4Base& max); + + /** + * Clamps the specified vector within the specified range and returns it in dst. + * + * @param v The vector to clamp. + * @param min The minimum value. + * @param max The maximum value. + * @param dst A vector to store the result in. + */ + static void clamp(const Vec4Base& v, const Vec4Base& min, const Vec4Base& max, Vec4Base* dst); union { @@ -68,6 +123,20 @@ class Vec4Base }; float comps[4]; }; +}; + +/* + * @brief A 4-floats class template with base math operators + */ +template +struct Vec4Adapter : public Vec4Base +{ +public: + using impl_type = _ImplType; + + constexpr Vec4Adapter() = default; + constexpr Vec4Adapter(float xx, float yy, float zz, float ww) : Vec4Base(xx, yy, zz, ww) {} + constexpr explicit Vec4Adapter(const float* src) : Vec4Base(src) {} impl_type& negate() { @@ -111,50 +180,6 @@ class Vec4Base return *static_cast(this); } - /** - * Sets the elements of this vector to the specified values. - * - * @param xx The new x coordinate. - * @param yy The new y coordinate. - * @param zz The new z coordinate. - * @param ww The new w coordinate. - */ - constexpr void set(float xx, float yy, float zz, float ww) - { - this->x = xx; - this->y = yy; - this->z = zz; - this->w = ww; - } - - /** - * Sets the elements of this vector from the values in the specified array. - * - * @param array An array containing the elements of the vector in the order x, y, z, w. - */ - void set(const float* array) - { - AX_ASSERT(array); - - this->x = array[0]; - this->y = array[1]; - this->z = array[2]; - this->w = array[3]; - } - - /** - * Sets the elements of this vector to those in the specified vector. - * - * @param v The vector to copy. - */ - void set(const impl_type& v) - { - this->x = v.x; - this->y = v.y; - this->z = v.z; - this->w = v.w; - } - inline impl_type& operator-() { return impl_type{*static_cast(this)}.negate(); } /** @@ -268,9 +293,9 @@ class Vec4Base /** * Defines 4-element floating point vector. */ -class AX_DLL Vec4 : public Vec4Base +class AX_DLL Vec4 : public Vec4Adapter { - using Vec4Base = Vec4Base; + using MyBase = Vec4Adapter; public: /** @@ -286,14 +311,14 @@ class AX_DLL Vec4 : public Vec4Base * @param zz The z coordinate. * @param ww The w coordinate. */ - constexpr Vec4(float xx, float yy, float zz, float ww) : Vec4Base(xx, yy, zz, ww) {} + constexpr Vec4(float xx, float yy, float zz, float ww) : MyBase(xx, yy, zz, ww) {} /** * Constructs a new vector from the values in the specified array. * * @param array An array containing the elements of the vector in the order x, y, z, w. */ - constexpr explicit Vec4(const float* array) : Vec4Base(array) {} + constexpr explicit Vec4(const float* array) : MyBase(array) {} /** * Constructs a vector that describes the direction between the specified points. @@ -303,16 +328,6 @@ class AX_DLL Vec4 : public Vec4Base */ constexpr Vec4(const Vec4& p1, const Vec4& p2) { setDirection(p1, p2); } - /** - * Creates a new vector from an integer interpreted as an RGBA value. - * E.g. 0xff0000ff represents opaque red or the vector (1, 0, 0, 1). - * - * @param color The integer to interpret as an RGBA value. - * - * @return A vector corresponding to the interpreted RGBA color. - */ - static Vec4 fromColor(unsigned int color); - /** * Indicates whether this vector contains all zeros. * @@ -346,24 +361,6 @@ class AX_DLL Vec4 : public Vec4Base */ static void add(const Vec4& v1, const Vec4& v2, Vec4* dst); - /** - * Clamps this vector within the specified range. - * - * @param min The minimum value. - * @param max The maximum value. - */ - void clamp(const Vec4& min, const Vec4& max); - - /** - * Clamps the specified vector within the specified range and returns it in dst. - * - * @param v The vector to clamp. - * @param min The minimum value. - * @param max The maximum value. - * @param dst A vector to store the result in. - */ - static void clamp(const Vec4& v, const Vec4& min, const Vec4& max, Vec4* dst); - /** * Returns the distance between this vector and v. * @@ -490,12 +487,12 @@ class AX_DLL Vec4 : public Vec4Base }; #if !(defined(AX_DLLEXPORT) || defined(AX_DLLIMPORT)) - inline constexpr Vec4 Vec4::ZERO = Vec4(0.0f, 0.0f, 0.0f, 0.0f); - inline constexpr Vec4 Vec4::ONE = Vec4(1.0f, 1.0f, 1.0f, 1.0f); - inline constexpr Vec4 Vec4::UNIT_X = Vec4(1.0f, 0.0f, 0.0f, 0.0f); - inline constexpr Vec4 Vec4::UNIT_Y = Vec4(0.0f, 1.0f, 0.0f, 0.0f); - inline constexpr Vec4 Vec4::UNIT_Z = Vec4(0.0f, 0.0f, 1.0f, 0.0f); - inline constexpr Vec4 Vec4::UNIT_W = Vec4(0.0f, 0.0f, 0.0f, 1.0f); +inline constexpr Vec4 Vec4::ZERO = Vec4(0.0f, 0.0f, 0.0f, 0.0f); +inline constexpr Vec4 Vec4::ONE = Vec4(1.0f, 1.0f, 1.0f, 1.0f); +inline constexpr Vec4 Vec4::UNIT_X = Vec4(1.0f, 0.0f, 0.0f, 0.0f); +inline constexpr Vec4 Vec4::UNIT_Y = Vec4(0.0f, 1.0f, 0.0f, 0.0f); +inline constexpr Vec4 Vec4::UNIT_Z = Vec4(0.0f, 0.0f, 1.0f, 0.0f); +inline constexpr Vec4 Vec4::UNIT_W = Vec4(0.0f, 0.0f, 0.0f, 1.0f); #endif NS_AX_MATH_END diff --git a/core/math/Vertex.cpp b/axmol/math/Vertex.cpp similarity index 85% rename from core/math/Vertex.cpp rename to axmol/math/Vertex.cpp index edb313a5a6be..0aa59aaadc17 100644 --- a/core/math/Vertex.cpp +++ b/axmol/math/Vertex.cpp @@ -25,14 +25,17 @@ THE SOFTWARE. ****************************************************************************/ -#include "math/Vertex.h" -#include "base/Macros.h" +#include "axmol/math/Vertex.h" +#include "axmol/base/Macros.h" namespace ax { -void vertexLineToPolygon(Vec2* points, float stroke, Vec2* vertices, unsigned int offset, unsigned int nuPoints) +void vertexLineToPolygon(Vec2* points, float stroke, V2F_T2F_C4B* vertices, unsigned int offset, unsigned int nuPoints) { + assert(points != nullptr); + assert(vertices != nullptr); + nuPoints += offset; if (nuPoints <= 1) return; @@ -72,8 +75,8 @@ void vertexLineToPolygon(Vec2* points, float stroke, Vec2* vertices, unsigned in } perpVector = perpVector * stroke; - vertices[idx].set(p1.x + perpVector.x, p1.y + perpVector.y); - vertices[idx + 1].set(p1.x - perpVector.x, p1.y - perpVector.y); + vertices[idx].position.set(p1.x + perpVector.x, p1.y + perpVector.y); + vertices[idx + 1].position.set(p1.x - perpVector.x, p1.y - perpVector.y); } // Validate vertexes @@ -83,10 +86,10 @@ void vertexLineToPolygon(Vec2* points, float stroke, Vec2* vertices, unsigned in idx = i * 2; const unsigned int idx1 = idx + 2; - Vec2 p1 = vertices[idx]; - Vec2 p2 = vertices[idx + 1]; - Vec2 p3 = vertices[idx1]; - Vec2 p4 = vertices[idx1 + 1]; + const auto& p1 = vertices[idx].position; + const auto& p2 = vertices[idx + 1].position; + const auto& p3 = vertices[idx1].position; + const auto& p4 = vertices[idx1 + 1].position; float s; // BOOL fixVertex = !ccpLineIntersect(Vec2(p1.x, p1.y), Vec2(p4.x, p4.y), Vec2(p2.x, p2.y), Vec2(p3.x, p3.y), @@ -98,8 +101,8 @@ void vertexLineToPolygon(Vec2* points, float stroke, Vec2* vertices, unsigned in if (fixVertex) { - vertices[idx1] = p4; - vertices[idx1 + 1] = p3; + vertices[idx1].position = p4; + vertices[idx1 + 1].position = p3; } } } diff --git a/core/math/Vertex.h b/axmol/math/Vertex.h similarity index 91% rename from core/math/Vertex.h rename to axmol/math/Vertex.h index 05d9a19c2cca..61844b7fe89f 100644 --- a/core/math/Vertex.h +++ b/axmol/math/Vertex.h @@ -26,7 +26,7 @@ ****************************************************************************/ #pragma once -#include "base/Types.h" +#include "axmol/base/Types.h" /** * @addtogroup base @@ -36,11 +36,11 @@ namespace ax { -/** @file CCVertex.h */ +/** @file Vertex.h */ /** converts a line to a polygon */ void AX_DLL -vertexLineToPolygon(Vec2* points, float stroke, Vec2* vertices, unsigned int offset, unsigned int nuPoints); +vertexLineToPolygon(Vec2* points, float stroke, V2F_T2F_C4B* vertices, unsigned int offset, unsigned int nuPoints); /** returns whether or not the line intersects */ bool AX_DLL diff --git a/core/media/AndroidMediaEngine.cpp b/axmol/media/AndroidMediaEngine.cpp similarity index 98% rename from core/media/AndroidMediaEngine.cpp rename to axmol/media/AndroidMediaEngine.cpp index c6b319053483..51add1bf7be7 100644 --- a/core/media/AndroidMediaEngine.cpp +++ b/axmol/media/AndroidMediaEngine.cpp @@ -23,8 +23,8 @@ ****************************************************************************/ #if defined(__ANDROID__) -# include "AndroidMediaEngine.h" -# include "platform/android/jni/JniHelper.h" +# include "axmol/media/AndroidMediaEngine.h" +# include "axmol/platform/android/jni/JniHelper.h" extern "C" { JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolMediaEngine_nativeFireEvent(JNIEnv* env, jclass, jlong pME, int arg1) diff --git a/core/media/AndroidMediaEngine.h b/axmol/media/AndroidMediaEngine.h similarity index 98% rename from core/media/AndroidMediaEngine.h rename to axmol/media/AndroidMediaEngine.h index 3e58e40af892..879fb1f6c0b3 100644 --- a/core/media/AndroidMediaEngine.h +++ b/axmol/media/AndroidMediaEngine.h @@ -24,7 +24,7 @@ #pragma once #if defined(__ANDROID__) -# include "MediaEngine.h" +# include "axmol/media/MediaEngine.h" namespace ax { diff --git a/core/media/AvfMediaEngine.h b/axmol/media/AvfMediaEngine.h similarity index 98% rename from core/media/AvfMediaEngine.h rename to axmol/media/AvfMediaEngine.h index 755be0696d49..71e78a0d5ddb 100644 --- a/core/media/AvfMediaEngine.h +++ b/axmol/media/AvfMediaEngine.h @@ -23,7 +23,7 @@ ****************************************************************************/ #pragma once -#include "MediaEngine.h" +#include "axmol/media/MediaEngine.h" #if defined(__APPLE__) diff --git a/core/media/AvfMediaEngine.mm b/axmol/media/AvfMediaEngine.mm similarity index 99% rename from core/media/AvfMediaEngine.mm rename to axmol/media/AvfMediaEngine.mm index ec4de35f9ab8..5fc3d09466b9 100644 --- a/core/media/AvfMediaEngine.mm +++ b/axmol/media/AvfMediaEngine.mm @@ -22,7 +22,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "AvfMediaEngine.h" +#include "axmol/media/AvfMediaEngine.h" #if defined(__APPLE__) diff --git a/core/media/MFUtils.cpp b/axmol/media/MFUtils.cpp similarity index 99% rename from core/media/MFUtils.cpp rename to axmol/media/MFUtils.cpp index 5cf9618d4690..dd5ee9f53187 100644 --- a/core/media/MFUtils.cpp +++ b/axmol/media/MFUtils.cpp @@ -1,6 +1,6 @@ #if defined(_WIN32) -#include "MFUtils.h" +#include "axmol/media/MFUtils.h" #include #include diff --git a/core/media/MFUtils.h b/axmol/media/MFUtils.h similarity index 100% rename from core/media/MFUtils.h rename to axmol/media/MFUtils.h diff --git a/core/media/MediaEngine.cpp b/axmol/media/MediaEngine.cpp similarity index 91% rename from core/media/MediaEngine.cpp rename to axmol/media/MediaEngine.cpp index ba4d6e13e4e6..6ce9e7fc46ac 100644 --- a/core/media/MediaEngine.cpp +++ b/axmol/media/MediaEngine.cpp @@ -22,22 +22,22 @@ THE SOFTWARE. ****************************************************************************/ -#include "MediaEngine.h" +#include "axmol/media/MediaEngine.h" #if defined(WINAPI_FAMILY) # if WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP && !defined(AXME_USE_IMFME) -# include "media/WmfMediaEngine.h" +# include "axmol/media/WmfMediaEngine.h" # else -# include "media/MfMediaEngine.h" +# include "axmol/media/MfMediaEngine.h" # endif #elif defined(__APPLE__) -# include "media/AvfMediaEngine.h" +# include "axmol/media/AvfMediaEngine.h" #elif defined(__ANDROID__) -# include "media/AndroidMediaEngine.h" +# include "axmol/media/AndroidMediaEngine.h" #endif #if defined(AX_ENABLE_VLC_MEDIA) -# include "media/VlcMediaEngine.h" +# include "axmol/media/VlcMediaEngine.h" #endif namespace axstd diff --git a/core/media/MediaEngine.h b/axmol/media/MediaEngine.h similarity index 98% rename from core/media/MediaEngine.h rename to axmol/media/MediaEngine.h index 91881da10347..35e3a5bfb9df 100644 --- a/core/media/MediaEngine.h +++ b/axmol/media/MediaEngine.h @@ -25,8 +25,8 @@ #pragma once #if !defined(AXME_NO_AXMOL) -# include "base/Logging.h" -# include "platform/PlatformMacros.h" +# include "axmol/base/Logging.h" +# include "axmol/platform/PlatformMacros.h" # define AXME_TRACE AXLOGD #else # define AXME_TRACE printf diff --git a/core/media/MfMediaEngine.cpp b/axmol/media/MfMediaEngine.cpp similarity index 98% rename from core/media/MfMediaEngine.cpp rename to axmol/media/MfMediaEngine.cpp index e50a2e9a8096..8097cbff2d53 100644 --- a/core/media/MfMediaEngine.cpp +++ b/axmol/media/MfMediaEngine.cpp @@ -8,15 +8,15 @@ // https://axmol.dev/ //------------------------------------------------------------------------------------- -#include "media/MfMediaEngine.h" +#include "axmol/media/MfMediaEngine.h" #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP || defined(AXME_USE_IMFME)) # include "ntcvt/ntcvt.hpp" -# include "MFUtils.h" +# include "axmol/media/MFUtils.h" # include "yasio/string_view.hpp" -# include "base/format.h" +# include "axmol/base/format.h" namespace ax { diff --git a/core/media/MfMediaEngine.h b/axmol/media/MfMediaEngine.h similarity index 98% rename from core/media/MfMediaEngine.h rename to axmol/media/MfMediaEngine.h index 83377cac1bd5..9f4d92e0f796 100644 --- a/core/media/MfMediaEngine.h +++ b/axmol/media/MfMediaEngine.h @@ -14,7 +14,7 @@ #if defined(_WIN32) #include -#include "media/MediaEngine.h" +#include "axmol/media/MediaEngine.h" # if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP || defined(AXME_USE_IMFME)) @@ -25,7 +25,7 @@ #include #include -#include "media/MFUtils.h" +#include "axmol/media/MFUtils.h" namespace ax { diff --git a/core/media/VlcMediaEngine.cpp b/axmol/media/VlcMediaEngine.cpp similarity index 99% rename from core/media/VlcMediaEngine.cpp rename to axmol/media/VlcMediaEngine.cpp index 75ca30c0dc17..5b205d10633d 100644 --- a/core/media/VlcMediaEngine.cpp +++ b/axmol/media/VlcMediaEngine.cpp @@ -30,9 +30,9 @@ sudo apt install ubuntu-restricted-extras ****************************************************************************/ #if defined(AX_ENABLE_VLC_MEDIA) -# include "VlcMediaEngine.h" +# include "axmol/media/VlcMediaEngine.h" -# include "VlcMediaEngine.h" +# include "axmol/media/VlcMediaEngine.h" namespace ax { diff --git a/core/media/VlcMediaEngine.h b/axmol/media/VlcMediaEngine.h similarity index 98% rename from core/media/VlcMediaEngine.h rename to axmol/media/VlcMediaEngine.h index 7081b62003cb..e22fb03e51ab 100644 --- a/core/media/VlcMediaEngine.h +++ b/axmol/media/VlcMediaEngine.h @@ -4,7 +4,7 @@ #pragma once -# include "MediaEngine.h" +# include "axmol/media/MediaEngine.h" #if defined(AX_ENABLE_VLC_MEDIA) diff --git a/core/media/WmfMediaEngine.cpp b/axmol/media/WmfMediaEngine.cpp similarity index 99% rename from core/media/WmfMediaEngine.cpp rename to axmol/media/WmfMediaEngine.cpp index 77152f492b33..17f258b66cb4 100644 --- a/core/media/WmfMediaEngine.cpp +++ b/axmol/media/WmfMediaEngine.cpp @@ -14,12 +14,12 @@ // https://axmol.dev/ ////////////////////////////////////////////////////////////////////////// -#include "WmfMediaEngine.h" +#include "axmol/media/WmfMediaEngine.h" #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_DESKTOP_APP) # include -# include "MFUtils.h" +# include "axmol/media/MFUtils.h" # include "ntcvt/ntcvt.hpp" # include "yasio/sz.hpp" diff --git a/core/media/WmfMediaEngine.h b/axmol/media/WmfMediaEngine.h similarity index 99% rename from core/media/WmfMediaEngine.h rename to axmol/media/WmfMediaEngine.h index 8c9bc8fec806..a7b1044115f9 100644 --- a/core/media/WmfMediaEngine.h +++ b/axmol/media/WmfMediaEngine.h @@ -44,12 +44,12 @@ // Safe string functions # include -# include "MFUtils.h" +# include "axmol/media/MFUtils.h" # include # include -# include "MediaEngine.h" +# include "axmol/media/MediaEngine.h" # include # include diff --git a/core/navmesh/CMakeLists.txt b/axmol/navmesh/CMakeLists.txt similarity index 100% rename from core/navmesh/CMakeLists.txt rename to axmol/navmesh/CMakeLists.txt diff --git a/core/navmesh/NavMesh.cpp b/axmol/navmesh/NavMesh.cpp similarity index 99% rename from core/navmesh/NavMesh.cpp rename to axmol/navmesh/NavMesh.cpp index 6b655d6b1582..fcf64f751465 100644 --- a/core/navmesh/NavMesh.cpp +++ b/axmol/navmesh/NavMesh.cpp @@ -23,11 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "navmesh/NavMesh.h" +#include "axmol/navmesh/NavMesh.h" #if defined(AX_ENABLE_NAVMESH) -# include "platform/FileUtils.h" -# include "renderer/Renderer.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/renderer/Renderer.h" # include "recast/DetourCommon.h" # include "recast/DetourDebugDraw.h" # include diff --git a/core/navmesh/NavMesh.h b/axmol/navmesh/NavMesh.h similarity index 93% rename from core/navmesh/NavMesh.h rename to axmol/navmesh/NavMesh.h index 314403b1c07d..6d9d26ca9003 100644 --- a/core/navmesh/NavMesh.h +++ b/axmol/navmesh/NavMesh.h @@ -26,11 +26,11 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) -# include "base/Object.h" -# include "math/Vec3.h" +# include "axmol/base/Object.h" +# include "axmol/math/Vec3.h" # include "recast/DetourNavMesh.h" # include "recast/DetourNavMeshQuery.h" # include "recast/DetourCrowd.h" @@ -38,10 +38,10 @@ # include # include -# include "navmesh/NavMeshAgent.h" -# include "navmesh/NavMeshDebugDraw.h" -# include "navmesh/NavMeshObstacle.h" -# include "navmesh/NavMeshUtils.h" +# include "axmol/navmesh/NavMeshAgent.h" +# include "axmol/navmesh/NavMeshDebugDraw.h" +# include "axmol/navmesh/NavMeshObstacle.h" +# include "axmol/navmesh/NavMeshUtils.h" namespace ax { diff --git a/core/navmesh/NavMeshAgent.cpp b/axmol/navmesh/NavMeshAgent.cpp similarity index 98% rename from core/navmesh/NavMeshAgent.cpp rename to axmol/navmesh/NavMeshAgent.cpp index 643495337afe..68d15b2e31f3 100644 --- a/core/navmesh/NavMeshAgent.cpp +++ b/axmol/navmesh/NavMeshAgent.cpp @@ -24,13 +24,13 @@ THE SOFTWARE. ****************************************************************************/ -#include "navmesh/NavMeshAgent.h" +#include "axmol/navmesh/NavMeshAgent.h" #if defined(AX_ENABLE_NAVMESH) -# include "navmesh/NavMesh.h" +# include "axmol/navmesh/NavMesh.h" # include "recast/DetourCrowd.h" -# include "2d/Node.h" -# include "2d/Scene.h" +# include "axmol/2d/Node.h" +# include "axmol/2d/Scene.h" # include namespace ax diff --git a/core/navmesh/NavMeshAgent.h b/axmol/navmesh/NavMeshAgent.h similarity index 97% rename from core/navmesh/NavMeshAgent.h rename to axmol/navmesh/NavMeshAgent.h index b9427f7f5f77..c680c21fbca2 100644 --- a/core/navmesh/NavMeshAgent.h +++ b/axmol/navmesh/NavMeshAgent.h @@ -26,12 +26,12 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) -# include "2d/Component.h" +# include "axmol/2d/Component.h" -# include "base/Object.h" -# include "math/Vec3.h" +# include "axmol/base/Object.h" +# include "axmol/math/Vec3.h" # include "recast/DetourCrowd.h" class dtNavMeshQuery; @@ -100,8 +100,8 @@ class AX_DLL NavMeshAgent : public Component static NavMeshAgent* create(const NavMeshAgentParam& param); static std::string_view getNavMeshAgentComponentName(); - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** set agent radius */ void setRadius(float radius); diff --git a/core/navmesh/NavMeshDebugDraw.cpp b/axmol/navmesh/NavMeshDebugDraw.cpp similarity index 80% rename from core/navmesh/NavMeshDebugDraw.cpp rename to axmol/navmesh/NavMeshDebugDraw.cpp index b863eb9178f9..db0a903ba3f5 100644 --- a/core/navmesh/NavMeshDebugDraw.cpp +++ b/axmol/navmesh/NavMeshDebugDraw.cpp @@ -23,37 +23,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "navmesh/NavMeshDebugDraw.h" +#include "axmol/navmesh/NavMeshDebugDraw.h" #if defined(AX_ENABLE_NAVMESH) # include // offsetof -# include "base/Types.h" -# include "renderer/backend/ProgramState.h" -# include "renderer/backend/DriverBase.h" -# include "renderer/Renderer.h" -# include "renderer/RenderState.h" -# include "renderer/Shaders.h" -# include "base/Director.h" -# include "base/Macros.h" +# include "axmol/base/Types.h" +# include "axmol/rhi/ProgramState.h" +# include "axmol/rhi/DriverBase.h" +# include "axmol/renderer/Renderer.h" +# include "axmol/renderer/RenderState.h" +# include "axmol/renderer/Shaders.h" +# include "axmol/base/Director.h" +# include "axmol/base/Macros.h" namespace ax { NavMeshDebugDraw::NavMeshDebugDraw() { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_COLOR); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_COLOR); + _programState = new rhi::ProgramState(program); _locMVP = _programState->getUniformLocation("u_MVPMatrix"); - // the POSITION_COLOR default vertex layout is: V3F_C4B, so we need modify it + // the POSITION_COLOR default vertex layout is: V3F_C4F, so we need modify it auto vertexLayout = _programState->getMutableVertexLayout(); - vertexLayout->setAttrib("a_position", - _programState->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, + vertexLayout->setAttrib("a_position", _programState->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, offsetof(V3F_C4F, position), false); - vertexLayout->setAttrib("a_color", - _programState->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::FLOAT4, + vertexLayout->setAttrib("a_color", _programState->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, offsetof(V3F_C4F, color), false); vertexLayout->setStride(sizeof(V3F_C4F)); @@ -65,10 +63,10 @@ void NavMeshDebugDraw::initCustomCommand(CustomCommand& command) command.setTransparent(true); command.init(0, Mat4::IDENTITY, Node::FLAGS_RENDER_AS_3D); command.setDrawType(CustomCommand::DrawType::ARRAY); - auto& pipelineDescriptor = command.getPipelineDescriptor(); - pipelineDescriptor.programState = _programState; + auto& pipelineDesc = command.getPipelineDesc(); + pipelineDesc.programState = _programState; - auto& blend = pipelineDescriptor.blendDescriptor; + auto& blend = pipelineDesc.blendDesc; blend.blendEnabled = true; blend.sourceRGBBlendFactor = blend.sourceAlphaBlendFactor = BlendFunc::ALPHA_NON_PREMULTIPLIED.src; blend.destinationRGBBlendFactor = blend.destinationAlphaBlendFactor = BlendFunc::ALPHA_NON_PREMULTIPLIED.dst; @@ -147,18 +145,18 @@ Vec4 NavMeshDebugDraw::getColor(unsigned int col) return Vec4(r, g, b, a) * factor; } -backend::PrimitiveType NavMeshDebugDraw::getPrimitiveType(duDebugDrawPrimitives prim) +rhi::PrimitiveType NavMeshDebugDraw::getPrimitiveType(duDebugDrawPrimitives prim) { switch (prim) { case DU_DRAW_POINTS: - return backend::PrimitiveType::POINT; + return rhi::PrimitiveType::POINT; case DU_DRAW_LINES: - return backend::PrimitiveType::LINE; + return rhi::PrimitiveType::LINE; case DU_DRAW_TRIS: - return backend::PrimitiveType::TRIANGLE; + return rhi::PrimitiveType::TRIANGLE; default: - return backend::PrimitiveType::POINT; + return rhi::PrimitiveType::POINT; } } @@ -185,8 +183,8 @@ void NavMeshDebugDraw::draw(Renderer* renderer) if (!_vertexBuffer || _vertexBuffer->getSize() < _vertices.size() * sizeof(_vertices[0])) { - _vertexBuffer = backend::DriverBase::getInstance()->newBuffer( - _vertices.size() * sizeof(_vertices[0]), backend::BufferType::VERTEX, backend::BufferUsage::STATIC); + _vertexBuffer = rhi::DriverBase::getInstance()->createBuffer( + _vertices.size() * sizeof(_vertices[0]), rhi::BufferType::VERTEX, rhi::BufferUsage::STATIC); _dirtyBuffer = true; } @@ -202,7 +200,7 @@ void NavMeshDebugDraw::draw(Renderer* renderer) } for (auto&& iter : _primitiveList) { - if (iter->type == backend::PrimitiveType::POINT) + if (iter->type == rhi::PrimitiveType::POINT) continue; if (iter->end - iter->start <= 0) continue; @@ -230,13 +228,13 @@ void NavMeshDebugDraw::onBeforeVisitCmd() auto* renderer = Director::getInstance()->getRenderer(); _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); _rendererDepthWrite = renderer->getDepthWrite(); _rendererWinding = renderer->getWinding(); - renderer->setCullMode(backend::CullMode::NONE); + renderer->setCullMode(rhi::CullMode::NONE); renderer->setDepthTest(true); } @@ -244,7 +242,7 @@ void NavMeshDebugDraw::onAfterVisitCmd() { auto* renderer = Director::getInstance()->getRenderer(); renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); renderer->setDepthWrite(_rendererDepthWrite); renderer->setWinding(_rendererWinding); diff --git a/core/navmesh/NavMeshDebugDraw.h b/axmol/navmesh/NavMeshDebugDraw.h similarity index 69% rename from core/navmesh/NavMeshDebugDraw.h rename to axmol/navmesh/NavMeshDebugDraw.h index 8887d6c145a1..db2eb6613fb9 100644 --- a/core/navmesh/NavMeshDebugDraw.h +++ b/axmol/navmesh/NavMeshDebugDraw.h @@ -26,18 +26,17 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) -# include "renderer/RenderState.h" -# include "renderer/backend/ProgramState.h" -# include "renderer/backend/Types.h" -# include "renderer/backend/Buffer.h" -# include "math/Vec3.h" +# include "axmol/renderer/RenderState.h" +# include "axmol/rhi/ProgramState.h" +# include "axmol/rhi/Buffer.h" +# include "axmol/math/Vec3.h" # include "recast/DebugDraw.h" -# include "renderer/GroupCommand.h" -# include "renderer/CallbackCommand.h" -# include "renderer/CustomCommand.h" +# include "axmol/renderer/GroupCommand.h" +# include "axmol/renderer/CallbackCommand.h" +# include "axmol/renderer/CustomCommand.h" # include # include @@ -55,18 +54,18 @@ class NavMeshDebugDraw : public duDebugDraw NavMeshDebugDraw(); virtual ~NavMeshDebugDraw(); - virtual void depthMask(bool state) override; - virtual void texture(bool /*state*/) override{}; - virtual void begin(duDebugDrawPrimitives prim, float size = 1.0f) override; + void depthMask(bool state) override; + void texture(bool /*state*/) override{}; + void begin(duDebugDrawPrimitives prim, float size = 1.0f) override; - virtual void vertex(const float* pos, unsigned int color) override; - virtual void vertex(const float x, const float y, const float z, unsigned int color) override; + void vertex(const float* pos, unsigned int color) override; + void vertex(const float x, const float y, const float z, unsigned int color) override; - virtual void vertex(const float* pos, unsigned int color, const float* uv) override; + void vertex(const float* pos, unsigned int color, const float* uv) override; virtual void vertex(const float x, const float y, const float z, unsigned int color, const float u, const float v) override; - virtual void end() override; + void end() override; void draw(Renderer* renderer); @@ -74,7 +73,7 @@ class NavMeshDebugDraw : public duDebugDraw private: void initCustomCommand(CustomCommand& command); - backend::PrimitiveType getPrimitiveType(duDebugDrawPrimitives prim); + rhi::PrimitiveType getPrimitiveType(duDebugDrawPrimitives prim); static Vec4 getColor(unsigned int col); void onBeforeVisitCmd(); @@ -90,7 +89,7 @@ class NavMeshDebugDraw : public duDebugDraw struct Primitive { - backend::PrimitiveType type = backend::PrimitiveType::LINE; + rhi::PrimitiveType type = rhi::PrimitiveType::LINE; bool depthMask = false; unsigned short start = 0; unsigned short end = 0; @@ -98,15 +97,15 @@ class NavMeshDebugDraw : public duDebugDraw }; Primitive* _currentPrimitive = nullptr; - backend::ProgramState* _programState = nullptr; + rhi::ProgramState* _programState = nullptr; bool _currentDepthMask = true; bool _dirtyBuffer = true; - backend::Buffer* _vertexBuffer = nullptr; + rhi::Buffer* _vertexBuffer = nullptr; // RenderState::StateBlock _stateBlock; std::vector _vertices; std::vector _primitiveList; - backend::UniformLocation _locMVP; + rhi::UniformLocation _locMVP; std::vector _commands; //CallbackCommand _beforeCommand; @@ -114,9 +113,9 @@ class NavMeshDebugDraw : public duDebugDraw // renderer state cache variables bool _rendererDepthTestEnabled = true; - backend::CompareFunction _rendererDepthCmpFunc = backend::CompareFunction::LESS; - backend::CullMode _rendererCullMode = backend::CullMode::BACK; - backend::Winding _rendererWinding = backend::Winding::COUNTER_CLOCK_WISE; + rhi::CompareFunc _rendererDepthCmpFunc = rhi::CompareFunc::LESS; + rhi::CullMode _rendererCullMode = rhi::CullMode::BACK; + rhi::Winding _rendererWinding = rhi::Winding::COUNTER_CLOCK_WISE; bool _rendererDepthWrite = false; }; diff --git a/core/navmesh/NavMeshObstacle.cpp b/axmol/navmesh/NavMeshObstacle.cpp similarity index 97% rename from core/navmesh/NavMeshObstacle.cpp rename to axmol/navmesh/NavMeshObstacle.cpp index fd5aaed0107b..817e2a9a92a8 100644 --- a/core/navmesh/NavMeshObstacle.cpp +++ b/axmol/navmesh/NavMeshObstacle.cpp @@ -24,12 +24,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "navmesh/NavMeshObstacle.h" +#include "axmol/navmesh/NavMeshObstacle.h" #if defined(AX_ENABLE_NAVMESH) -# include "navmesh/NavMesh.h" -# include "2d/Node.h" -# include "2d/Scene.h" +# include "axmol/navmesh/NavMesh.h" +# include "axmol/2d/Node.h" +# include "axmol/2d/Scene.h" # include "recast/DetourTileCache.h" namespace ax diff --git a/core/navmesh/NavMeshObstacle.h b/axmol/navmesh/NavMeshObstacle.h similarity index 94% rename from core/navmesh/NavMeshObstacle.h rename to axmol/navmesh/NavMeshObstacle.h index a3f43cccde73..be6deff379b5 100644 --- a/core/navmesh/NavMeshObstacle.h +++ b/axmol/navmesh/NavMeshObstacle.h @@ -26,13 +26,13 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) -# include "2d/Component.h" +# include "axmol/2d/Component.h" -# include "base/Object.h" -# include "math/Vec3.h" +# include "axmol/base/Object.h" +# include "axmol/math/Vec3.h" # include "recast/DetourNavMesh.h" # include "recast/DetourTileCache.h" @@ -67,8 +67,8 @@ class AX_DLL NavMeshObstacle : public Component static NavMeshObstacle* create(float radius, float height); static std::string_view getNavMeshObstacleComponentName(); - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** Set radius of obstacle */ void setRadius(float radius); diff --git a/core/navmesh/NavMeshUtils.cpp b/axmol/navmesh/NavMeshUtils.cpp similarity index 99% rename from core/navmesh/NavMeshUtils.cpp rename to axmol/navmesh/NavMeshUtils.cpp index ff9604912c83..c8b93d5319c4 100644 --- a/core/navmesh/NavMeshUtils.cpp +++ b/axmol/navmesh/NavMeshUtils.cpp @@ -23,7 +23,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "navmesh/NavMeshUtils.h" +#include "axmol/navmesh/NavMeshUtils.h" #if defined(AX_ENABLE_NAVMESH) # include "recast/DetourCommon.h" diff --git a/core/navmesh/NavMeshUtils.h b/axmol/navmesh/NavMeshUtils.h similarity index 97% rename from core/navmesh/NavMeshUtils.h rename to axmol/navmesh/NavMeshUtils.h index 56485fa4ecc6..f813176705fc 100644 --- a/core/navmesh/NavMeshUtils.h +++ b/axmol/navmesh/NavMeshUtils.h @@ -26,11 +26,11 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) -# include "platform/PlatformMacros.h" -# include "math/Math.h" +# include "axmol/platform/PlatformMacros.h" +# include "axmol/math/Math.h" # include "recast/DetourCommon.h" # include "recast/DetourNavMesh.h" diff --git a/core/network/CMakeLists.txt b/axmol/network/CMakeLists.txt similarity index 100% rename from core/network/CMakeLists.txt rename to axmol/network/CMakeLists.txt diff --git a/core/network/ConcurrentRefCountedBase.h b/axmol/network/ConcurrentRefCountedBase.h similarity index 100% rename from core/network/ConcurrentRefCountedBase.h rename to axmol/network/ConcurrentRefCountedBase.h diff --git a/core/network/Downloader-curl.cpp b/axmol/network/Downloader-curl.cpp similarity index 99% rename from core/network/Downloader-curl.cpp rename to axmol/network/Downloader-curl.cpp index 866e58ff59bd..720c11d0ed8d 100644 --- a/core/network/Downloader-curl.cpp +++ b/axmol/network/Downloader-curl.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #if !defined(__EMSCRIPTEN__) -# include "network/Downloader-curl.h" +# include "axmol/network/Downloader-curl.h" # include # include @@ -33,13 +33,13 @@ # include # include # include -# include "base/Utils.h" -# include "base/UTF8.h" -# include "base/Director.h" -# include "base/Scheduler.h" -# include "platform/FileUtils.h" -# include "network/Downloader.h" -# include "platform/FileStream.h" +# include "axmol/base/Utils.h" +# include "axmol/base/text_utils.h" +# include "axmol/base/Director.h" +# include "axmol/base/Scheduler.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/network/Downloader.h" +# include "axmol/platform/FileStream.h" # include "openssl/md5.h" # include "yasio/xxsocket.hpp" # include "yasio/thread_name.hpp" diff --git a/core/network/Downloader-curl.h b/axmol/network/Downloader-curl.h similarity index 95% rename from core/network/Downloader-curl.h rename to axmol/network/Downloader-curl.h index 456d49bd58aa..dadfe620666b 100644 --- a/core/network/Downloader-curl.h +++ b/axmol/network/Downloader-curl.h @@ -27,7 +27,7 @@ #pragma once #include -#include "network/IDownloaderImpl.h" +#include "axmol/network/IDownloaderImpl.h" namespace ax { @@ -46,7 +46,7 @@ class DownloaderCURL : public IDownloaderImpl DownloaderCURL(const DownloaderHints& hints); virtual ~DownloaderCURL(); - virtual void startTask(std::shared_ptr& task) override; + void startTask(std::shared_ptr& task) override; protected: class Impl; diff --git a/core/network/Downloader-wasm.cpp b/axmol/network/Downloader-wasm.cpp similarity index 99% rename from core/network/Downloader-wasm.cpp rename to axmol/network/Downloader-wasm.cpp index c9026082f04e..40ccaed69306 100644 --- a/core/network/Downloader-wasm.cpp +++ b/axmol/network/Downloader-wasm.cpp @@ -23,8 +23,8 @@ ****************************************************************************/ -#include "platform/FileUtils.h" -#include "network/Downloader-wasm.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/network/Downloader-wasm.h" #include using namespace std; diff --git a/core/network/Downloader-wasm.h b/axmol/network/Downloader-wasm.h similarity index 93% rename from core/network/Downloader-wasm.h rename to axmol/network/Downloader-wasm.h index bac17a0869d0..2685958d4153 100644 --- a/core/network/Downloader-wasm.h +++ b/axmol/network/Downloader-wasm.h @@ -25,8 +25,8 @@ #pragma once -#include "network/IDownloaderImpl.h" -#include "network/Downloader.h" +#include "axmol/network/IDownloaderImpl.h" +#include "axmol/network/Downloader.h" #include namespace ax { @@ -43,7 +43,7 @@ namespace ax { namespace network DownloaderEmscripten(const DownloaderHints& hints); virtual ~DownloaderEmscripten(); - virtual void startTask(std::shared_ptr& task) override; + void startTask(std::shared_ptr& task) override; protected: int _id; diff --git a/core/network/Downloader.cpp b/axmol/network/Downloader.cpp similarity index 97% rename from core/network/Downloader.cpp rename to axmol/network/Downloader.cpp index 61725f29debf..f48f99459605 100644 --- a/core/network/Downloader.cpp +++ b/axmol/network/Downloader.cpp @@ -24,13 +24,13 @@ THE SOFTWARE. ****************************************************************************/ -#include "network/Downloader.h" +#include "axmol/network/Downloader.h" #if EMSCRIPTEN -# include "network/Downloader-wasm.h" +# include "axmol/network/Downloader-wasm.h" # define DownloaderImpl DownloaderEmscripten #else -# include "network/Downloader-curl.h" +# include "axmol/network/Downloader-curl.h" # define DownloaderImpl DownloaderCURL #endif diff --git a/core/network/Downloader.h b/axmol/network/Downloader.h similarity index 99% rename from core/network/Downloader.h rename to axmol/network/Downloader.h index e49c118204e3..53f57b35150c 100644 --- a/core/network/Downloader.h +++ b/axmol/network/Downloader.h @@ -31,7 +31,7 @@ #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/network/HttpClient-wasm.cpp b/axmol/network/HttpClient-wasm.cpp similarity index 98% rename from core/network/HttpClient-wasm.cpp rename to axmol/network/HttpClient-wasm.cpp index b37bc5134a6e..7370692491cb 100644 --- a/core/network/HttpClient-wasm.cpp +++ b/axmol/network/HttpClient-wasm.cpp @@ -26,10 +26,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "network/HttpClient-wasm.h" +#include "axmol/network/HttpClient-wasm.h" #include -#include "base/Director.h" -#include "platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" #include "yasio/string_view.hpp" #if EMSCRIPTEN diff --git a/core/network/HttpClient-wasm.h b/axmol/network/HttpClient-wasm.h similarity index 97% rename from core/network/HttpClient-wasm.h rename to axmol/network/HttpClient-wasm.h index eee0ff5bd0bc..48badbba900e 100644 --- a/core/network/HttpClient-wasm.h +++ b/axmol/network/HttpClient-wasm.h @@ -24,10 +24,10 @@ #pragma once -#include "base/Vector.h" -#include "network/HttpRequest.h" -#include "network/HttpResponse.h" -#include "network/HttpCookie.h" +#include "axmol/base/Vector.h" +#include "axmol/network/HttpRequest.h" +#include "axmol/network/HttpResponse.h" +#include "axmol/network/HttpCookie.h" struct emscripten_fetch_t; diff --git a/core/network/HttpClient.cpp b/axmol/network/HttpClient.cpp similarity index 99% rename from core/network/HttpClient.cpp rename to axmol/network/HttpClient.cpp index f34c2190a3a7..818faf5bad48 100644 --- a/core/network/HttpClient.cpp +++ b/axmol/network/HttpClient.cpp @@ -28,11 +28,11 @@ #if !defined(__EMSCRIPTEN__) -#include "network/HttpClient.h" +#include "axmol/network/HttpClient.h" #include -#include "base/Utils.h" -#include "base/Director.h" -#include "platform/FileUtils.h" +#include "axmol/base/Utils.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" #include "yasio/yasio.hpp" using namespace yasio; diff --git a/core/network/HttpClient.h b/axmol/network/HttpClient.h similarity index 96% rename from core/network/HttpClient.h rename to axmol/network/HttpClient.h index 7aab2366f21d..d7121c728be7 100644 --- a/core/network/HttpClient.h +++ b/axmol/network/HttpClient.h @@ -33,13 +33,13 @@ #include #include -#include "base/Scheduler.h" -#include "network/HttpRequest.h" -#include "network/HttpResponse.h" -#include "network/HttpCookie.h" -#include "network/Uri.h" +#include "axmol/base/Scheduler.h" +#include "axmol/network/HttpRequest.h" +#include "axmol/network/HttpResponse.h" +#include "axmol/network/HttpCookie.h" +#include "axmol/network/Uri.h" #include "yasio/yasio_fwd.hpp" -#include "base/ConcurrentDeque.h" +#include "axmol/base/ConcurrentDeque.h" /** * @addtogroup network @@ -255,6 +255,6 @@ class AX_DLL HttpClient #else -#include "network/HttpClient-wasm.h" +#include "axmol/network/HttpClient-wasm.h" #endif diff --git a/core/network/HttpCookie.cpp b/axmol/network/HttpCookie.cpp similarity index 98% rename from core/network/HttpCookie.cpp rename to axmol/network/HttpCookie.cpp index 048e37c26e17..6623ed17c5af 100644 --- a/core/network/HttpCookie.cpp +++ b/axmol/network/HttpCookie.cpp @@ -24,9 +24,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "network/HttpCookie.h" -#include "network/Uri.h" -#include "platform/FileUtils.h" +#include "axmol/network/HttpCookie.h" +#include "axmol/network/Uri.h" +#include "axmol/platform/FileUtils.h" #include "yasio/utils.hpp" #include "yasio/string_view.hpp" @@ -36,7 +36,7 @@ #include #include -#include "base/axstd.h" +#include "axmol/base/axstd.h" #include "fmt/compile.h" namespace ax diff --git a/core/network/HttpCookie.h b/axmol/network/HttpCookie.h similarity index 98% rename from core/network/HttpCookie.h rename to axmol/network/HttpCookie.h index 6f95a2f82fdd..547e6e548a9b 100644 --- a/core/network/HttpCookie.h +++ b/axmol/network/HttpCookie.h @@ -27,7 +27,7 @@ #pragma once /// @cond DO_NOT_SHOW -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include diff --git a/core/network/HttpRequest.h b/axmol/network/HttpRequest.h similarity index 98% rename from core/network/HttpRequest.h rename to axmol/network/HttpRequest.h index daa5731f4128..f85b0f1b03f9 100644 --- a/core/network/HttpRequest.h +++ b/axmol/network/HttpRequest.h @@ -32,12 +32,12 @@ #include #include #include -#include "base/Object.h" -#include "base/Macros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Macros.h" #include "yasio/byte_buffer.hpp" -#include "ConcurrentRefCountedBase.h" +#include "axmol/network/ConcurrentRefCountedBase.h" /** * @addtogroup network diff --git a/core/network/HttpResponse.h b/axmol/network/HttpResponse.h similarity index 99% rename from core/network/HttpResponse.h rename to axmol/network/HttpResponse.h index b67132d8359c..87df8a11e316 100644 --- a/core/network/HttpResponse.h +++ b/axmol/network/HttpResponse.h @@ -29,8 +29,8 @@ #include #include #include -#include "network/HttpRequest.h" -#include "network/Uri.h" +#include "axmol/network/HttpRequest.h" +#include "axmol/network/Uri.h" #include "llhttp.h" /** diff --git a/core/network/IDownloaderImpl.h b/axmol/network/IDownloaderImpl.h similarity index 98% rename from core/network/IDownloaderImpl.h rename to axmol/network/IDownloaderImpl.h index 2f7e8b4fbc52..b19be75d278f 100644 --- a/core/network/IDownloaderImpl.h +++ b/axmol/network/IDownloaderImpl.h @@ -30,7 +30,7 @@ #include #include -#include "base/Logging.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/network/Uri.cpp b/axmol/network/Uri.cpp similarity index 99% rename from core/network/Uri.cpp rename to axmol/network/Uri.cpp index 5564f8d0e9f0..6d1d1a04bdd5 100644 --- a/core/network/Uri.cpp +++ b/axmol/network/Uri.cpp @@ -18,8 +18,8 @@ * Uri class is based on the original file here https://github.com/facebook/folly/blob/master/folly/Uri.cpp */ -#include "network/Uri.h" -#include "base/Logging.h" +#include "axmol/network/Uri.h" +#include "axmol/base/Logging.h" #include #include diff --git a/core/network/Uri.h b/axmol/network/Uri.h similarity index 99% rename from core/network/Uri.h rename to axmol/network/Uri.h index 7df586f10fd2..ff7bdd9c3891 100644 --- a/core/network/Uri.h +++ b/axmol/network/Uri.h @@ -20,7 +20,7 @@ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include diff --git a/core/network/WebSocket-wasm.cpp b/axmol/network/WebSocket-wasm.cpp similarity index 97% rename from core/network/WebSocket-wasm.cpp rename to axmol/network/WebSocket-wasm.cpp index 433a5092b7e4..f40e6fe5a5b4 100644 --- a/core/network/WebSocket-wasm.cpp +++ b/axmol/network/WebSocket-wasm.cpp @@ -22,8 +22,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "network/WebSocket-wasm.h" -#include "base/Logging.h" +#include "axmol/network/WebSocket-wasm.h" +#include "axmol/base/Logging.h" namespace ax { @@ -107,7 +107,7 @@ bool WebSocket::open(Delegate* delegate, std::string_view url, std::string_view // chrome/edge can't connect // firefox works with "Sec-Fetch-Site: cross-site" in request header - // refer: https://github.com/emscripten-core/emscripten/issues/19100 + // refer: https://github.com/emscripten-axmol/emscripten/issues/19100 // wasm websocket callback thread same with axmol render thread emscripten_websocket_set_onopen_callback(_wsfd, this, em_ws_onopen); emscripten_websocket_set_onerror_callback(_wsfd, this, em_ws_onerror); diff --git a/core/network/WebSocket-wasm.h b/axmol/network/WebSocket-wasm.h similarity index 99% rename from core/network/WebSocket-wasm.h rename to axmol/network/WebSocket-wasm.h index c5e6005ec014..4357e1a308f7 100644 --- a/core/network/WebSocket-wasm.h +++ b/axmol/network/WebSocket-wasm.h @@ -24,9 +24,9 @@ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include -#include "base/Object.h" +#include "axmol/base/Object.h" #include "yasio/byte_buffer.hpp" #include diff --git a/core/network/WebSocket.cpp b/axmol/network/WebSocket.cpp similarity index 99% rename from core/network/WebSocket.cpp rename to axmol/network/WebSocket.cpp index b6b89904f64b..1205afd0049d 100644 --- a/core/network/WebSocket.cpp +++ b/axmol/network/WebSocket.cpp @@ -25,9 +25,9 @@ #include "yasio/yasio.hpp" -#include "network/WebSocket.h" +#include "axmol/network/WebSocket.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace yasio; diff --git a/core/network/WebSocket.h b/axmol/network/WebSocket.h similarity index 98% rename from core/network/WebSocket.h rename to axmol/network/WebSocket.h index 59627d95b55e..d7fe57074423 100644 --- a/core/network/WebSocket.h +++ b/axmol/network/WebSocket.h @@ -45,13 +45,13 @@ # include # include -# include "platform/PlatformMacros.h" -# include "platform/StdC.h" -# include "base/Scheduler.h" -# include "base/ConcurrentDeque.h" +# include "axmol/platform/PlatformMacros.h" +# include "axmol/platform/StdC.h" +# include "axmol/base/Scheduler.h" +# include "axmol/base/ConcurrentDeque.h" # include "yasio/yasio_fwd.hpp" # include "yasio/byte_buffer.hpp" -# include "network/Uri.h" +# include "axmol/network/Uri.h" # include "llhttp.h" # include "websocket_parser.h" @@ -442,5 +442,5 @@ class AX_DLL WebSocket } #else -# include "network/WebSocket-wasm.h" +# include "axmol/network/WebSocket-wasm.h" #endif diff --git a/axmol/physics/CMakeLists.txt b/axmol/physics/CMakeLists.txt new file mode 100644 index 000000000000..d6096e989d75 --- /dev/null +++ b/axmol/physics/CMakeLists.txt @@ -0,0 +1,16 @@ +set(_AX_PHYSICS_HEADER + physics/PhysicsContact.h + physics/PhysicsWorld.h + physics/PhysicsBody.h + physics/PhysicsCollider.h + physics/PhysicsHelper.h + physics/PhysicsJoint.h + ) + +set(_AX_PHYSICS_SRC + physics/PhysicsBody.cpp + physics/PhysicsContact.cpp + physics/PhysicsJoint.cpp + physics/PhysicsCollider.cpp + physics/PhysicsWorld.cpp + ) diff --git a/core/physics/PhysicsBody.cpp b/axmol/physics/PhysicsBody.cpp similarity index 59% rename from core/physics/PhysicsBody.cpp rename to axmol/physics/PhysicsBody.cpp index bf0f21d7aca8..de62104b22bc 100644 --- a/core/physics/PhysicsBody.cpp +++ b/axmol/physics/PhysicsBody.cpp @@ -22,31 +22,29 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + + remark: box2d rigibody + + TODO: + + Check whether applyForce need invoke phlppixelsToMeters + ****************************************************************************/ -#include "physics/PhysicsBody.h" +#include "axmol/physics/PhysicsBody.h" #if defined(AX_ENABLE_PHYSICS) # include # include # include -# include "chipmunk/chipmunk_private.h" - -# include "2d/Scene.h" -# include "physics/PhysicsShape.h" -# include "physics/PhysicsJoint.h" -# include "physics/PhysicsWorld.h" -# include "physics/PhysicsHelper.h" +# include "axmol/2d/Scene.h" +# include "axmol/physics/PhysicsCollider.h" +# include "axmol/physics/PhysicsJoint.h" +# include "axmol/physics/PhysicsWorld.h" +# include "axmol/physics/PhysicsHelper.h" -static void internalBodySetMass(cpBody* body, cpFloat mass) -{ - cpBodyActivate(body); - body->m = mass; - body->m_inv = 1.0f / mass; - // cpAssertSaneBody(body); -} - -static void internalBodyUpdateVelocity(cpBody* body, cpVect gravity, cpFloat damping, cpFloat dt) +# if 0 +static void internalBodyUpdateVelocity(cpBody* body, b2Vec2 gravity, float damping, float dt) { cpBodyUpdateVelocity(body, cpvzero, damping, dt); // Skip kinematic bodies. @@ -73,6 +71,61 @@ static void internalBodyUpdateVelocity(cpBody* body, cpVect gravity, cpFloat dam // to check body sanity cpBodySetTorque(body, 0.0f); } +# endif + +// TODO: check whther really require custom update velocity, then should call in world b2World_Step manually +static void internalBodyUpdateVelocity(b2BodyId& bodyId, const b2Vec2& gravity, float damping, float dt) +{ + // Skip kinematic bodies. + if (b2Body_GetType(bodyId) == b2_kinematicBody) + return; + + // Ensure the body's mass and inertia are positive + auto mass = b2Body_GetMass(bodyId); + assert(mass > 0.0f && b2Body_GetRotationalInertia(bodyId) > 0.0f); + + // Get the user data and cast it to your custom PhysicsBody class + ax::PhysicsBody* physicsBody = static_cast(b2Body_GetUserData(bodyId)); + + // Update linear velocity + b2Vec2 velocity = b2Body_GetLinearVelocity(bodyId); + if (physicsBody->isGravityEnabled()) + { + velocity += dt * gravity; + } + velocity *= damping; + float velocityLimit = physicsBody->getVelocityLimit(); + velocity.x = std::clamp(velocity.x, -velocityLimit, velocityLimit); + velocity.y = std::clamp(velocity.y, -velocityLimit, velocityLimit); + b2Body_SetLinearVelocity(bodyId, velocity); + + // Update angular velocity + float angularVelocity = b2Body_GetAngularVelocity(bodyId); + angularVelocity *= damping; + float angularVelocityLimit = physicsBody->getAngularVelocityLimit(); + angularVelocity = std::clamp(angularVelocity, -angularVelocityLimit, angularVelocityLimit); + b2Body_SetAngularVelocity(bodyId, angularVelocity); + + // Reset forces and torque (Box2D does not accumulate forces, but we set them to zero for clarity) + b2Body_SetLinearDamping(bodyId, 0.0f); + b2Body_SetAngularDamping(bodyId, 0.0f); +} + +static void internalApplyDamping(b2BodyId& body, float delta, float linearDamping, float angularDamping) +{ + // Apply linear damping + b2Vec2 velocity = b2Body_GetLinearVelocity(body); + float linearDampFactor = std::clamp(1.0f - delta * linearDamping, 0.0f, 1.0f); + velocity.x *= linearDampFactor; + velocity.y *= linearDampFactor; + b2Body_SetLinearVelocity(body, velocity); + + // Apply angular damping + float angularVelocity = b2Body_GetAngularVelocity(body); + float angularDampFactor = std::clamp(1.0f - delta * angularDamping, 0.0f, 1.0f); + angularVelocity *= angularDampFactor; + b2Body_SetAngularVelocity(body, angularVelocity); +} namespace ax { @@ -88,13 +141,10 @@ static const float MOMENT_DEFAULT = 200; PhysicsBody::PhysicsBody() : _world(nullptr) - , _cpBody(nullptr) + , _b2Body(b2_nullBodyId) , _dynamic(true) , _rotationEnabled(true) , _gravityEnabled(true) - , _massDefault(true) - , _momentDefault(true) - , _mass(MASS_DEFAULT) , _area(0.0f) , _density(0.0f) , _moment(MOMENT_DEFAULT) @@ -104,13 +154,13 @@ PhysicsBody::PhysicsBody() , _linearDamping(0.0f) , _angularDamping(0.0f) , _tag(0) - , _massSetByUser(false) - , _momentSetByUser(false) , _rotationOffset(0) , _recordedRotation(0.0f) , _recordedAngle(0.0) , _recordScaleX(1.f) , _recordScaleY(1.f) + , _recordPosX(0.0f) + , _recordPosY(0.0f) , _fixedUpdate(false) { _name = COMPONENT_NAME; @@ -118,16 +168,25 @@ PhysicsBody::PhysicsBody() PhysicsBody::~PhysicsBody() { + deatchFromWOrld(); +} + +void PhysicsBody::deatchFromWOrld() +{ + removeAllColliders(); + for (auto&& joint : _joints) { PhysicsBody* other = joint->getBodyA() == this ? joint->getBodyB() : joint->getBodyA(); other->removeJoint(joint); delete joint; } + _joints.clear(); - if (_cpBody) + if (b2Body_IsValid(_b2Body)) { - cpBodyFree(_cpBody); + b2DestroyBody(_b2Body); + _b2Body = b2_nullBodyId; } } @@ -144,50 +203,12 @@ PhysicsBody* PhysicsBody::create() return nullptr; } -PhysicsBody* PhysicsBody::create(float mass) -{ - PhysicsBody* body = new PhysicsBody(); - if (body) - { - body->_mass = mass; - body->_massDefault = false; - if (body->init()) - { - body->autorelease(); - return body; - } - } - - AX_SAFE_DELETE(body); - return nullptr; -} - -PhysicsBody* PhysicsBody::create(float mass, float moment) -{ - PhysicsBody* body = new PhysicsBody(); - if (body) - { - body->_mass = mass; - body->_massDefault = false; - body->_moment = moment; - body->_momentDefault = false; - if (body->init()) - { - body->autorelease(); - return body; - } - } - - AX_SAFE_DELETE(body); - return nullptr; -} - PhysicsBody* PhysicsBody::createCircle(float radius, const PhysicsMaterial& material, const Vec2& offset) { PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeCircle::create(radius, material, offset)); + body->addCollider(PhysicsColliderCircle::create(body, radius, material, offset)); body->autorelease(); return body; } @@ -201,7 +222,7 @@ PhysicsBody* PhysicsBody::createBox(const Vec2& size, const PhysicsMaterial& mat PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeBox::create(size, material, offset)); + body->addCollider(PhysicsColliderBox::create(body, size, material, offset)); body->autorelease(); return body; } @@ -218,7 +239,7 @@ PhysicsBody* PhysicsBody::createPolygon(const Vec2* points, PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapePolygon::create(points, count, material, offset)); + body->addCollider(PhysicsColliderPolygon::create(body, points, count, material, offset)); body->autorelease(); return body; } @@ -235,8 +256,9 @@ PhysicsBody* PhysicsBody::createEdgeSegment(const Vec2& a, PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeEdgeSegment::create(a, b, material, border)); + body->addCollider(PhysicsColliderEdgeSegment::create(body, a, b, material, border)); body->setDynamic(false); + body->autorelease(); return body; } @@ -253,7 +275,7 @@ PhysicsBody* PhysicsBody::createEdgeBox(const Vec2& size, PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeEdgeBox::create(size, material, border, offset)); + body->addCollider(PhysicsColliderEdgeBox::create(body, size, material, border, offset)); body->setDynamic(false); body->autorelease(); return body; @@ -272,7 +294,7 @@ PhysicsBody* PhysicsBody::createEdgePolygon(const Vec2* points, PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeEdgePolygon::create(points, count, material, border)); + body->addCollider(PhysicsColliderEdgePolygon::create(body, points, count, material, border)); body->setDynamic(false); body->autorelease(); return body; @@ -291,7 +313,7 @@ PhysicsBody* PhysicsBody::createEdgeChain(const Vec2* points, PhysicsBody* body = new PhysicsBody(); if (body->init()) { - body->addShape(PhysicsShapeEdgeChain::create(points, count, material, border)); + body->addCollider(PhysicsColliderEdgeChain::create(body, points, count, material, border)); body->setDynamic(false); body->autorelease(); return body; @@ -306,12 +328,21 @@ bool PhysicsBody::init() { do { - _cpBody = cpBodyNew(_mass, _moment); - internalBodySetMass(_cpBody, _mass); - cpBodySetUserData(_cpBody, this); - cpBodySetVelocityUpdateFunc(_cpBody, internalBodyUpdateVelocity); + _world = Director::getInstance()->getRunningScene()->getPhysicsWorld(); + b2WorldId worldId = _world->_b2World; + AX_BREAK_IF(!b2World_IsValid(worldId)); + + b2BodyDef def = b2DefaultBodyDef(); + def.type = b2_dynamicBody; + def.position = b2Vec2{0.0f, 0.0f}; + + _b2Body = b2CreateBody(worldId, &def); + AX_BREAK_IF(!b2Body_IsValid(_b2Body)); + + b2Body_SetUserData(_b2Body, this); - AX_BREAK_IF(_cpBody == nullptr); + // TODO: + // cpBodySetVelocityUpdateFunc(_cpBody, internalBodyUpdateVelocity); return true; } while (false); @@ -325,33 +356,48 @@ void PhysicsBody::removeJoint(PhysicsJoint* joint) if (it != _joints.end()) { + (*it)->deatchFromBody(); _joints.erase(it); } } void PhysicsBody::setDynamic(bool dynamic) { +# if 1 if (dynamic != _dynamic) { _dynamic = dynamic; if (dynamic) { - cpBodySetType(_cpBody, CP_BODY_TYPE_DYNAMIC); - internalBodySetMass(_cpBody, _mass); - cpBodySetMoment(_cpBody, _moment); + b2Body_SetType(_b2Body, b2_dynamicBody); + b2Body_ApplyMassFromShapes(_b2Body); } else { - cpBodySetType(_cpBody, CP_BODY_TYPE_KINEMATIC); + b2Body_SetType(_b2Body, b2_kinematicBody); } } +# endif +} + +float PhysicsBody::getMass() const +{ + return b2Body_GetMass(_b2Body); +} + +float PhysicsBody::getMoment() const +{ + return b2Body_GetRotationalInertia(_b2Body); } void PhysicsBody::setRotationEnable(bool enable) { if (_rotationEnabled != enable) { - cpBodySetMoment(_cpBody, enable ? _moment : PHYSICS_INFINITY); + // cpBodySetMoment(_cpBody, enable ? _moment : PHYSICS_INFINITY); + auto massData = b2Body_GetMassData(_b2Body); + massData.rotationalInertia = enable ? _moment : PHYSICS_INFINITY; + b2Body_SetMassData(_b2Body, massData); _rotationEnabled = enable; } } @@ -364,44 +410,34 @@ void PhysicsBody::setGravityEnable(bool enable) void PhysicsBody::setRotation(float rotation) { _recordedRotation = rotation; - _recordedAngle = -(rotation + _rotationOffset) * (M_PI / 180.0); - cpBodySetAngle(_cpBody, _recordedAngle); + _recordedAngle = -(rotation + _rotationOffset) * (M_PI / 180.0f); + b2Body_SetTransform(_b2Body, b2Body_GetPosition(_b2Body), b2MakeRot(_recordedAngle)); } void PhysicsBody::setScale(float scaleX, float scaleY) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - _area -= shape->getArea(); - if (!_massSetByUser) - addMass(-shape->getMass()); - if (!_momentSetByUser) - addMoment(-shape->getMoment()); - - shape->setScale(scaleX, scaleY); - - _area += shape->getArea(); - if (!_massSetByUser) - addMass(shape->getMass()); - if (!_momentSetByUser) - addMoment(shape->getMoment()); + collider->setScale(scaleX, scaleY); } + + b2Body_ApplyMassFromShapes(_b2Body); } void PhysicsBody::setPosition(float positionX, float positionY) { - cpVect tt; + Vec2 tt; - tt.x = positionX + _positionOffset.x; - tt.y = positionY + _positionOffset.y; + tt.x = (positionX + _positionOffset.x); + tt.y = (positionY + _positionOffset.y); - cpBodySetPosition(_cpBody, tt); + b2Body_SetTransform(_b2Body, phlp::tob2Vec2(tt), b2Body_GetRotation(_b2Body)); } Vec2 PhysicsBody::getPosition() const { - cpVect tt = cpBodyGetPosition(_cpBody); - return Vec2(tt.x - _positionOffset.x, tt.y - _positionOffset.y); + auto tt = b2Body_GetPosition(_b2Body); + return phlp::toVec2(tt) - _positionOffset; } void PhysicsBody::setPositionOffset(const Vec2& position) @@ -416,230 +452,123 @@ void PhysicsBody::setPositionOffset(const Vec2& position) float PhysicsBody::getRotation() { - if (_recordedAngle != cpBodyGetAngle(_cpBody)) + auto angle = b2Rot_GetAngle(b2Body_GetRotation(_b2Body)); + if (_recordedAngle != angle) { - _recordedAngle = cpBodyGetAngle(_cpBody); + _recordedAngle = angle; _recordedRotation = -_recordedAngle * 180.0 / M_PI - _rotationOffset; } return _recordedRotation; } -PhysicsShape* PhysicsBody::addShape(PhysicsShape* shape, bool addMassAndMoment /* = true*/) +PhysicsCollider* PhysicsBody::addCollider(PhysicsCollider* collider, bool addMassAndMoment /* = true*/) { - if (shape == nullptr) + if (collider == nullptr) return nullptr; - // add shape to body - if (_shapes.getIndex(shape) == -1) + // add collider to body + if (_colliders.getIndex(collider) == -1) { - shape->setBody(this); - // calculate the area, mass, and density // area must update before mass, because the density changes depend on it. if (addMassAndMoment) { - _area += shape->getArea(); - addMass(shape->getMass()); - addMoment(shape->getMoment()); - } - - if (_world && cpBodyGetSpace(_cpBody)) - { - _world->addShape(shape); + _area += collider->getArea(); } - _shapes.pushBack(shape); + _colliders.pushBack(collider); } - return shape; + return collider; } void PhysicsBody::applyForce(const Vec2& force, const Vec2& offset) { - if (_dynamic && _mass != PHYSICS_INFINITY) + if (_dynamic && getMass() != PHYSICS_INFINITY) { - cpBodyApplyForceAtLocalPoint(_cpBody, PhysicsHelper::vec22cpv(force), PhysicsHelper::vec22cpv(offset)); + b2Vec2 worldPoint = b2Body_GetWorldPoint(_b2Body, phlp::tob2Vec2(offset)); + + // Apply the force at the world point + b2Body_ApplyForce(_b2Body, phlp::tob2Vec2(force), worldPoint, true); } } void PhysicsBody::resetForces() { - cpBodySetForce(_cpBody, PhysicsHelper::vec22cpv(Vec2(0, 0))); -} - -void PhysicsBody::applyImpulse(const Vec2& impulse, const Vec2& offset) -{ - cpBodyApplyImpulseAtLocalPoint(_cpBody, PhysicsHelper::vec22cpv(impulse), PhysicsHelper::vec22cpv(offset)); -} - -void PhysicsBody::applyTorque(float torque) -{ - cpBodySetTorque(_cpBody, torque); -} - -void PhysicsBody::setMass(float mass) -{ - if (mass <= 0) - { - return; - } - _mass = mass; - _massDefault = false; - _massSetByUser = true; - - // update density - if (_mass == PHYSICS_INFINITY) - { - _density = PHYSICS_INFINITY; - } - else - { - if (_area > 0) - { - _density = _mass / _area; - } - else - { - _density = 0; - } - } + // Reset the body's forces (Box2D accumulates forces over time) + b2Body_SetLinearVelocity(_b2Body, b2Vec2_zero); - // the static body's mass and moment is always infinity - if (_dynamic) - { - internalBodySetMass(_cpBody, _mass); - } + // Apply the force to the center of the body + b2Body_ApplyForceToCenter(_b2Body, b2Vec2_zero, true); } -void PhysicsBody::addMass(float mass) +void PhysicsBody::applyImpulse(const Vec2& impulse, const Vec2& offset) { - if (mass == PHYSICS_INFINITY) - { - _mass = PHYSICS_INFINITY; - _massDefault = false; - _density = PHYSICS_INFINITY; - } - else if (mass == -PHYSICS_INFINITY) - { - return; - } - else - { - if (_massDefault) - { - _mass = 0; - _massDefault = false; - } - - if (_mass + mass > 0) - { - _mass += mass; - } - else - { - _mass = MASS_DEFAULT; - _massDefault = true; - } + b2Vec2 worldPoint = b2Body_GetWorldPoint(_b2Body, phlp::tob2Vec2(offset)); - if (_area > 0) - { - _density = _mass / _area; - } - else - { - _density = 0; - } - } - - // the static body's mass and moment is always infinity - if (_dynamic) - { - internalBodySetMass(_cpBody, _mass); - } + // Apply the impulse at the world point + b2Body_ApplyLinearImpulse(_b2Body, phlp::tob2Vec2(impulse), worldPoint, true); } -void PhysicsBody::addMoment(float moment) +void PhysicsBody::applyTorque(float torque) { - if (moment == PHYSICS_INFINITY) - { - // if moment is PHYSICS_INFINITY, the moment of the body will become PHYSICS_INFINITY - _moment = PHYSICS_INFINITY; - _momentDefault = false; - } - else if (moment == -PHYSICS_INFINITY) - { - return; - } - else - { - // if moment of the body is PHYSICS_INFINITY is has no effect - if (_moment != PHYSICS_INFINITY) - { - if (_momentDefault) - { - _moment = 0; - _momentDefault = false; - } - - if (_moment + moment > 0) - { - _moment += moment; - } - else - { - _moment = MOMENT_DEFAULT; - _momentDefault = true; - } - } - } - - // the static body's mass and moment is always infinity - if (_rotationEnabled && _dynamic) - { - cpBodySetMoment(_cpBody, _moment); - } + b2Body_ApplyTorque(_b2Body, torque, true); } void PhysicsBody::setVelocity(const Vec2& velocity) { - if (cpBodyGetType(_cpBody) == CP_BODY_TYPE_STATIC) + if (b2Body_GetType(_b2Body) == b2_staticBody) { AXLOGD("physics warning: you can't set velocity for a static body."); return; } - cpBodySetVelocity(_cpBody, PhysicsHelper::vec22cpv(velocity)); + b2Body_SetLinearVelocity(_b2Body, PhysicsHelper::tob2Vec2(velocity)); } Vec2 PhysicsBody::getVelocity() { - return PhysicsHelper::cpv2vec2(cpBodyGetVelocity(_cpBody)); + return PhysicsHelper::toVec2(b2Body_GetLinearVelocity(_b2Body)); } Vec2 PhysicsBody::getVelocityAtLocalPoint(const Vec2& point) { - return PhysicsHelper::cpv2vec2(cpBodyGetVelocityAtLocalPoint(_cpBody, PhysicsHelper::vec22cpv(point))); + // return PhysicsHelper::cpv2vec2(cpBodyGetVelocityAtLocalPoint(_cpBody, PhysicsHelper::vec22cpv(point))); + + b2Vec2 worldPoint = b2Body_GetWorldPoint(_b2Body, PhysicsHelper::tob2Vec2(point)); + + auto r = b2Sub(worldPoint, b2Body_GetPosition(_b2Body)); + auto av = b2Body_GetAngularVelocity(_b2Body); + b2Vec2 velocity = b2Add(b2Body_GetLinearVelocity(_b2Body), b2Vec2{-r.y * av, r.x * av}); + + return PhysicsHelper::toVec2(velocity); } Vec2 PhysicsBody::getVelocityAtWorldPoint(const Vec2& point) { - return PhysicsHelper::cpv2vec2(cpBodyGetVelocityAtWorldPoint(_cpBody, PhysicsHelper::vec22cpv(point))); + // return PhysicsHelper::cpv2vec2(cpBodyGetVelocityAtWorldPoint(_cpBody, PhysicsHelper::vec22cpv(point))); + b2Vec2 r = b2Sub(PhysicsHelper::tob2Vec2(point), b2Body_GetPosition(_b2Body)); + auto av = b2Body_GetAngularVelocity(_b2Body); + b2Vec2 velocity = b2Add(b2Body_GetLinearVelocity(_b2Body), b2Vec2{-r.y * av, r.x * av}); + return PhysicsHelper::toVec2(velocity); } void PhysicsBody::setAngularVelocity(float velocity) { - if (cpBodyGetType(_cpBody) == CP_BODY_TYPE_STATIC) + if (b2Body_GetType(_b2Body) == b2_staticBody) { AXLOGD("physics warning: you can't set angular velocity for a static body."); return; } - cpBodySetAngularVelocity(_cpBody, velocity); + // cpBodySetAngularVelocity(_cpBody, velocity); + b2Body_SetAngularVelocity(_b2Body, velocity); } float PhysicsBody::getAngularVelocity() { - return PhysicsHelper::cpfloat2float(cpBodyGetAngularVelocity(_cpBody)); + // return PhysicsHelper::cpfloat2float(cpBodyGetAngularVelocity(_cpBody)); + return b2Body_GetAngularVelocity(_b2Body); } void PhysicsBody::setVelocityLimit(float limit) @@ -662,96 +591,62 @@ float PhysicsBody::getAngularVelocityLimit() return _angularVelocityLimit; } -void PhysicsBody::setMoment(float moment) -{ - _moment = moment; - _momentDefault = false; - _momentSetByUser = true; - - // the static body's mass and moment is always infinity - if (_rotationEnabled && _dynamic) - { - cpBodySetMoment(_cpBody, _moment); - } -} - -PhysicsShape* PhysicsBody::getShape(int tag) const +PhysicsCollider* PhysicsBody::getCollider(int tag) const { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - if (shape->getTag() == tag) + if (collider->getTag() == tag) { - return shape; + return collider; } } return nullptr; } -void PhysicsBody::removeShape(int tag, bool reduceMassAndMoment /* = true*/) +void PhysicsBody::removeCollider(int tag, bool reduceMassAndMoment /* = true*/) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - if (shape->getTag() == tag) + if (collider->getTag() == tag) { - removeShape(shape, reduceMassAndMoment); + removeCollider(collider, reduceMassAndMoment); return; } } } -void PhysicsBody::removeShape(PhysicsShape* shape, bool reduceMassAndMoment /* = true*/) +void PhysicsBody::removeCollider(PhysicsCollider* collider, bool reduceMassAndMoment /* = true*/) { - if (_shapes.getIndex(shape) != -1) + if (_colliders.getIndex(collider) != -1) { // deduce the area, mass and moment // area must update before mass, because the density changes depend on it. if (reduceMassAndMoment) { - _area -= shape->getArea(); - addMass(-shape->getMass()); - addMoment(-shape->getMoment()); + _area -= collider->getArea(); } - // remove - if (_world) - { - _world->removeShape(shape); - } - - // set shape->_body = nullptr make the shape->setBody will not trigger the _body->removeShape function call. - shape->_body = nullptr; - shape->setBody(nullptr); - _shapes.eraseObject(shape); + collider->deatchFromBody(); + _colliders.eraseObject(collider); } } -void PhysicsBody::removeAllShapes(bool reduceMassAndMoment /* = true*/) +void PhysicsBody::removeAllColliders(bool reduceMassAndMoment /* = true*/) { - for (auto&& child : _shapes) + for (auto&& collider : _colliders) { - PhysicsShape* shape = dynamic_cast(child); - // deduce the area, mass and moment // area must update before mass, because the density changes depend on it. if (reduceMassAndMoment) { - _area -= shape->getArea(); - addMass(-shape->getMass()); - addMoment(-shape->getMoment()); + _area -= collider->getArea(); } - if (_world) - { - _world->removeShape(shape); - } - - // set shape->_body = nullptr make the shape->setBody will not trigger the _body->removeShape function call. - shape->_body = nullptr; - shape->setBody(nullptr); + collider->deatchFromBody(); } - _shapes.clear(); + _colliders.clear(); } void PhysicsBody::removeFromWorld() @@ -781,18 +676,18 @@ void PhysicsBody::setEnabled(bool enable) bool PhysicsBody::isResting() const { - return cpBodyIsSleeping(_cpBody) != cpFalse; + return !b2Body_IsAwake(_b2Body); } void PhysicsBody::setResting(bool rest) const { if (rest && !isResting()) { - cpBodySleep(_cpBody); + b2Body_SetAwake(_b2Body, false); } else if (!rest && isResting()) { - cpBodyActivate(_cpBody); + b2Body_SetAwake(_b2Body, true); } } @@ -801,9 +696,7 @@ void PhysicsBody::update(float delta) // damping compute if (!_fixedUpdate && _isDamping && _dynamic && !isResting()) { - _cpBody->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); - _cpBody->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); - _cpBody->w *= cpfclamp(1.0f - delta * _angularDamping, 0.0f, 1.0f); + internalApplyDamping(_b2Body, delta, _linearDamping, _angularDamping); } } @@ -811,25 +704,23 @@ void PhysicsBody::fixedUpdate(float delta) { if (_fixedUpdate && _isDamping && _dynamic && !isResting()) { - _cpBody->v.x *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); - _cpBody->v.y *= cpfclamp(1.0f - delta * _linearDamping, 0.0f, 1.0f); - _cpBody->w *= cpfclamp(1.0f - delta * _angularDamping, 0.0f, 1.0f); + internalApplyDamping(_b2Body, delta, _linearDamping, _angularDamping); } } void PhysicsBody::setCategoryBitmask(int bitmask) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - shape->setCategoryBitmask(bitmask); + collider->setCategoryBitmask(bitmask); } } int PhysicsBody::getCategoryBitmask() const { - if (!_shapes.empty()) + if (!_colliders.empty()) { - return _shapes.front()->getCategoryBitmask(); + return _colliders.front()->getCategoryBitmask(); } else { @@ -839,17 +730,17 @@ int PhysicsBody::getCategoryBitmask() const void PhysicsBody::setContactTestBitmask(int bitmask) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - shape->setContactTestBitmask(bitmask); + collider->setContactTestBitmask(bitmask); } } int PhysicsBody::getContactTestBitmask() const { - if (!_shapes.empty()) + if (!_colliders.empty()) { - return _shapes.front()->getContactTestBitmask(); + return _colliders.front()->getContactTestBitmask(); } else { @@ -859,17 +750,17 @@ int PhysicsBody::getContactTestBitmask() const void PhysicsBody::setCollisionBitmask(int bitmask) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - shape->setCollisionBitmask(bitmask); + collider->setCollisionBitmask(bitmask); } } int PhysicsBody::getCollisionBitmask() const { - if (!_shapes.empty()) + if (!_colliders.empty()) { - return _shapes.front()->getCollisionBitmask(); + return _colliders.front()->getCollisionBitmask(); } else { @@ -879,17 +770,17 @@ int PhysicsBody::getCollisionBitmask() const void PhysicsBody::setGroup(int group) { - for (auto&& shape : _shapes) + for (auto&& collider : _colliders) { - shape->setGroup(group); + collider->setGroup(group); } } int PhysicsBody::getGroup() const { - if (!_shapes.empty()) + if (!_colliders.empty()) { - return _shapes.front()->getGroup(); + return _colliders.front()->getGroup(); } else { @@ -909,12 +800,12 @@ void PhysicsBody::setRotationOffset(float rotation) Vec2 PhysicsBody::world2Local(const Vec2& point) { - return PhysicsHelper::cpv2vec2(cpBodyWorldToLocal(_cpBody, PhysicsHelper::vec22cpv(point))); + return phlp::toVec2(b2Body_GetLocalPoint(_b2Body, phlp::tob2Vec2(point))); } Vec2 PhysicsBody::local2World(const Vec2& point) { - return PhysicsHelper::cpv2vec2(cpBodyLocalToWorld(_cpBody, PhysicsHelper::vec22cpv(point))); + return phlp::toVec2(b2Body_GetWorldPoint(_b2Body, phlp::tob2Vec2(point))); } void PhysicsBody::beforeSimulation(const Mat4& parentToWorldTransform, @@ -1022,6 +913,6 @@ void PhysicsBody::removeFromPhysicsWorld() } } -} +} // namespace ax #endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/PhysicsBody.h b/axmol/physics/PhysicsBody.h similarity index 76% rename from core/physics/PhysicsBody.h rename to axmol/physics/PhysicsBody.h index 3c9e1ec082c5..d936e2713290 100644 --- a/core/physics/PhysicsBody.h +++ b/axmol/physics/PhysicsBody.h @@ -26,15 +26,13 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_PHYSICS) -# include "2d/Component.h" -# include "math/Math.h" -# include "physics/PhysicsShape.h" -# include "base/Vector.h" - -struct cpBody; +# include "axmol/2d/Component.h" +# include "axmol/math/Math.h" +# include "axmol/physics/PhysicsCollider.h" +# include "axmol/base/Vector.h" namespace ax { @@ -55,12 +53,13 @@ const PhysicsMaterial PHYSICSBODY_MATERIAL_DEFAULT(0.1f, 0.5f, 0.5f); /** * A body affect by physics. * - * It can attach one or more shapes. + * It can attach one or more colliders. * If you create body with createXXX, it will automatically compute mass and moment with density your specified(which is * PHYSICSBODY_MATERIAL_DEFAULT by default, and the density value is 0.1f), and it based on the formula: mass = density * * area. If you create body with createEdgeXXX, the mass and moment will be PHYSICS_INFINITY by default. And it's a - * static body. You can change mass and moment with setMass() and setMoment(). And you can change the body to be dynamic + * static body. * or static by use function setDynamic(). + * Note: box2d not allow change mass and moment dynamic */ class AX_DLL PhysicsBody : public Component { @@ -68,31 +67,13 @@ class AX_DLL PhysicsBody : public Component const static std::string COMPONENT_NAME; /** - * Create a body with default mass and moment. + * Create a rigibody. * - * This default mass value is 1.0. - * This default moment value is 200. + * The mass and moment automaticall computed by box2d internal * @return An autoreleased PhysicsBody object pointer. */ static PhysicsBody* create(); - /** - * Create a body with mass and default moment. - * - * @param mass This body's mass. - * @return An autoreleased PhysicsBody object pointer. - */ - static PhysicsBody* create(float mass); - - /** - * Create a body with mass and moment. - * - * @param mass This body's mass. - * @param moment This body's moment. - * @return An autoreleased PhysicsBody object pointer. - */ - static PhysicsBody* create(float mass, float moment); - /** * Create a body contains a circle. * @@ -105,7 +86,7 @@ class AX_DLL PhysicsBody : public Component const PhysicsMaterial& material = PHYSICSBODY_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO); /** - * Create a body contains a box shape. + * Create a body contains a box collider. * * @param size Size contains this box's width and height. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. @@ -117,7 +98,7 @@ class AX_DLL PhysicsBody : public Component const Vec2& offset = Vec2::ZERO); /** - * @brief Create a body contains a polygon shape. + * @brief Create a body contains a polygon collider. * * @param points Points is an array of Vec2 structs defining a convex hull with a clockwise winding. * @param count An integer number, contains the count of the points array. @@ -131,7 +112,7 @@ class AX_DLL PhysicsBody : public Component const Vec2& offset = Vec2::ZERO); /** - * Create a body contains a EdgeSegment shape. + * Create a body contains a EdgeSegment collider. * * @param a It's the edge's begin position. * @param b It's the edge's end position. @@ -145,7 +126,7 @@ class AX_DLL PhysicsBody : public Component float border = 1); /** - * Create a body contains a EdgeBox shape. + * Create a body contains a EdgeBox collider. * @param size The size contains this box's width and height. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param border It's a edge's border width. @@ -158,7 +139,7 @@ class AX_DLL PhysicsBody : public Component const Vec2& offset = Vec2::ZERO); /** - * Create a body contains a EdgePolygon shape. + * Create a body contains a EdgePolygon collider. * * @param points Points is an array of Vec2 structs defining a convex hull with a clockwise winding. * @param count An integer number, contains the count of the points array. @@ -172,7 +153,7 @@ class AX_DLL PhysicsBody : public Component float border = 1); /** - * Create a body contains a EdgeChain shape. + * Create a body contains a EdgeChain collider. * * @param points A Vec2 object pointer, it contains an array of points. * @param count An integer number, contains the count of the points array. @@ -186,58 +167,58 @@ class AX_DLL PhysicsBody : public Component float border = 1); /** - * @brief Add a shape to body. - * @param shape The shape to be added. - * @param addMassAndMoment If this is true, the shape's mass and moment will be added to body. The default is true. - * @return This shape's pointer if added success or nullptr if failed. + * @brief Add a collider to body. + * @param collider The collider to be added. + * @param addMassAndMoment If this is true, the collider's mass and moment will be added to body. The default is true. + * @return This collider's pointer if added success or nullptr if failed. */ - virtual PhysicsShape* addShape(PhysicsShape* shape, bool addMassAndMoment = true); + virtual PhysicsCollider* addCollider(PhysicsCollider* collider, bool addMassAndMoment = true); /** - * @brief Remove a shape from body. - * @param shape Shape the shape to be removed. - * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by shape. The default is + * @brief Remove a collider from body. + * @param collider the collider to be removed. + * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by collider. The default is * true. */ - void removeShape(PhysicsShape* shape, bool reduceMassAndMoment = true); + void removeCollider(PhysicsCollider* collider, bool reduceMassAndMoment = true); /** - * @brief Remove a shape from body. - * @param tag The tag of the shape to be removed. - * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by shape. The default is + * @brief Remove a collider from body. + * @param tag The tag of the collider to be removed. + * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by collider. The default is * true. */ - void removeShape(int tag, bool reduceMassAndMoment = true); + void removeCollider(int tag, bool reduceMassAndMoment = true); /** - * Remove all shapes. + * Remove all colliders. * - * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by shape. The default is + * @param reduceMassAndMoment If this is true, the body mass and moment will be reduced by collider. The default is * true. */ - void removeAllShapes(bool reduceMassAndMoment = true); + void removeAllColliders(bool reduceMassAndMoment = true); /** - * Get the body shapes. + * Get the body colliders. * - * @return A Vector object contains PhysicsShape pointer. + * @return A Vector object contains PhysicsCollider pointer. */ - const Vector& getShapes() const { return _shapes; } + const Vector& getColliders() const { return _colliders; } /** - * Get the first shape of the body shapes. + * Get the first collider of the body colliders. * - * @return The first shape in this body. + * @return The first collider in this body. */ - PhysicsShape* getFirstShape() const { return _shapes.size() >= 1 ? _shapes.at(0) : nullptr; } + PhysicsCollider* getFirstCollider() const { return _colliders.size() >= 1 ? _colliders.at(0) : nullptr; } /** - * get the shape of the body. + * get the collider of the body. * - * @param tag An integer number that identifies a PhysicsShape object. - * @return A PhysicsShape object pointer or nullptr if no shapes were found. + * @param tag An integer number that identifies a PhysicsCollider object. + * @return A PhysicsCollider object pointer or nullptr if no colliders were found. */ - PhysicsShape* getShape(int tag) const; + PhysicsCollider* getCollider(int tag) const; /** * Applies a continuous force to body. @@ -352,23 +333,23 @@ class AX_DLL PhysicsBody : public Component void setCollisionBitmask(int bitmask); /** - * Return bitmask of first shape. + * Return bitmask of first collider. * - * @return If there is no shape in body, return default value.(0xFFFFFFFF) + * @return If there is no collider in body, return default value.(0xFFFFFFFF) */ int getCategoryBitmask() const; /** - * Return bitmask of first shape. + * Return bitmask of first collider. * - * @return If there is no shape in body, return default value.(0x00000000) + * @return If there is no collider in body, return default value.(0x00000000) */ int getContactTestBitmask() const; /** - * Return bitmask of first shape. + * Return bitmask of first collider. * - * @return If there is no shape in body, return default value.(0xFFFFFFFF) + * @return If there is no collider in body, return default value.(0xFFFFFFFF) */ int getCollisionBitmask() const; @@ -381,9 +362,9 @@ class AX_DLL PhysicsBody : public Component void setGroup(int group); /** - * Return group of first shape. + * Return group of first collider. * - * @return If there is no shape in body, return default value.(0) + * @return If there is no collider in body, return default value.(0) */ int getGroup() const; @@ -418,49 +399,11 @@ class AX_DLL PhysicsBody : public Component */ void setDynamic(bool dynamic); - /** - * @brief Set the body mass. - * - * @attention If you need add/subtract mass to body, don't use setMass(getMass() +/- mass), because the mass of body - * may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMass() instead. - */ - void setMass(float mass); - /** Get the body mass. */ - float getMass() const { return _mass; } - - /** - * @brief Add mass to body. - * - * @param mass If _mass(mass of the body) == PHYSICS_INFINITY, it remains. - * if mass == PHYSICS_INFINITY, _mass will be PHYSICS_INFINITY. - * if mass == -PHYSICS_INFINITY, _mass will not change. - * if mass + _mass <= 0, _mass will equal to MASS_DEFAULT(1.0) - * other wise, mass = mass + _mass; - */ - void addMass(float mass); - - /** - * @brief Set the body moment of inertia. - * - * @note If you need add/subtract moment to body, don't use setMoment(getMoment() +/- moment), because the moment of - * body may be equal to PHYSICS_INFINITY, it will cause some unexpected result, please use addMoment() instead. - */ - void setMoment(float moment); + float getMass() const; /** Get the body moment of inertia. */ - float getMoment() const { return _moment; } - - /** - * @brief Add moment of inertia to body. - * - * @param moment If _moment(moment of the body) == PHYSICS_INFINITY, it remains. - * if moment == PHYSICS_INFINITY, _moment will be PHYSICS_INFINITY. - * if moment == -PHYSICS_INFINITY, _moment will not change. - * if moment + _moment <= 0, _moment will equal to MASS_DEFAULT(1.0) - * other wise, moment = moment + _moment; - */ - void addMoment(float moment); + float getMoment() const; /** get linear damping. */ float getLinearDamping() const { return _linearDamping; } @@ -503,7 +446,7 @@ class AX_DLL PhysicsBody : public Component * * If the body it isn't enabled, it will not has simulation by world. */ - virtual void setEnabled(bool enable) override; + void setEnabled(bool enable) override; /** Whether the body can rotation. */ bool isRotationEnabled() const { return _rotationEnabled; } @@ -530,21 +473,21 @@ class AX_DLL PhysicsBody : public Component Vec2 local2World(const Vec2& point); /** Get the rigid body of chipmunk. */ - cpBody* getCPBody() const { return _cpBody; } + b2BodyId getB2Body() const { return _b2Body; } /** Set fixed update state */ void setFixedUpdate(bool fixedUpdate) { _fixedUpdate = fixedUpdate; } - virtual void onEnter() override; - virtual void onExit() override; - virtual void onAdd() override; - virtual void onRemove() override; + void onEnter() override; + void onExit() override; + void onAdd() override; + void onRemove() override; protected: PhysicsBody(); virtual ~PhysicsBody(); - virtual bool init() override; + bool init() override; virtual void setPosition(float positionX, float positionY); @@ -570,17 +513,17 @@ class AX_DLL PhysicsBody : public Component void afterSimulation(const Mat4& parentToWorldTransform, float parentRotation); protected: + + void deatchFromWOrld(); + std::vector _joints; - Vector _shapes; + Vector _colliders; PhysicsWorld* _world; - cpBody* _cpBody; + b2BodyId _b2Body; bool _dynamic; bool _rotationEnabled; bool _gravityEnabled; - bool _massDefault; - bool _momentDefault; - float _mass; float _area; float _density; float _moment; @@ -592,15 +535,10 @@ class AX_DLL PhysicsBody : public Component int _tag; - // when setMass() is invoked, it means body's mass is not calculated by shapes - bool _massSetByUser; - // when setMoment() is invoked, it means body's moment is not calculated by shapes - bool _momentSetByUser; - Vec2 _positionOffset; float _rotationOffset; float _recordedRotation; - double _recordedAngle; + float _recordedAngle; // offset between owner's center point and down left point Vec3 _ownerCenterOffset; @@ -616,7 +554,7 @@ class AX_DLL PhysicsBody : public Component bool _fixedUpdate; friend class PhysicsWorld; - friend class PhysicsShape; + friend class PhysicsCollider; friend class PhysicsJoint; }; diff --git a/axmol/physics/PhysicsCollider.cpp b/axmol/physics/PhysicsCollider.cpp new file mode 100644 index 000000000000..0fcdb7555c3d --- /dev/null +++ b/axmol/physics/PhysicsCollider.cpp @@ -0,0 +1,875 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "axmol/physics/PhysicsCollider.h" +#if defined(AX_ENABLE_PHYSICS) + +# include +# include +# include + +# include "axmol/physics/PhysicsBody.h" +# include "axmol/physics/PhysicsWorld.h" +# include "axmol/physics/PhysicsHelper.h" + +namespace ax +{ +extern const float PHYSICS_INFINITY; + +static b2Vec2 b2CentroidForPoly(const b2Vec2* verts, const int count) +{ + float sum = 0.0f; + b2Vec2 vsum{0.0f, 0.0f}; + + for (int i = 0; i < count; i++) + { + b2Vec2 v1 = verts[i]; + b2Vec2 v2 = verts[(i + 1) % count]; + float cross = b2Cross(v1, v2); // v1.x * v2.y - v1.y * v2.x; + + sum += cross; + vsum += (v1 + v2) * cross; + } + + return vsum * (1.0f / (3.0f * sum)); +} + +PhysicsCollider::PhysicsCollider(PhysicsBody* body) + : _body(body) + , _type(Type::UNKNOWN) + , _area(0.0f) + , _sensor(false) + , _scaleX(1.0f) + , _scaleY(1.0f) + , _newScaleX(1.0f) + , _newScaleY(1.0f) + , _tag(0) + , _categoryBitmask(UINT_MAX) + , _collisionBitmask(UINT_MAX) + , _contactTestBitmask(0) + , _group(0) +{} + +PhysicsCollider::~PhysicsCollider() +{ + deatchFromBody(); +} + +void PhysicsCollider::deatchFromBody() +{ + for (auto&& shape : _b2Shapes) + { + if (b2Shape_IsValid(shape)) + b2DestroyShape(shape, true); + } + _b2Shapes.clear(); + _body = nullptr; +} + +bool PhysicsCollider::isDeatched() const +{ + return _body != nullptr; +} + +void PhysicsCollider::setMaterial(const PhysicsMaterial& material) +{ + setDensity(material.density, false); + setRestitution(material.restitution, false); + setFriction(material.friction, false); + + for (auto shape : _b2Shapes) + { + b2Shape_SetDensity(shape, material.density, false); + b2Shape_SetRestitution(shape, material.restitution); + b2Shape_SetFriction(shape, material.friction); + } + + b2Body_ApplyMassFromShapes(_body->getB2Body()); +} + +void PhysicsCollider::setScale(float scaleX, float scaleY) +{ + if (std::abs(_scaleX - scaleX) > FLT_EPSILON || std::abs(_scaleY - scaleY) > FLT_EPSILON) + { + if (_type == Type::CIRCLE && scaleX != scaleY) + { + AXLOGD("PhysicsColliderCircle WARNING: CANNOT support setScale with different x and y"); + return; + } + _newScaleX = scaleX; + _newScaleY = scaleY; + + updateScale(); + + // re-calculate area + _area = calculateArea(); + } +} + +void PhysicsCollider::updateScale() +{ + _scaleX = _newScaleX; + _scaleY = _newScaleY; +} + +void PhysicsCollider::addShape(b2ShapeId shape) +{ + if (b2Shape_IsValid(shape)) + { + b2Shape_SetUserData(shape, this); + b2Shape_SetFilter(shape, b2Filter{(uint64_t)CollisionBits::All, (uint64_t)CollisionBits::All, _group}); + _b2Shapes.emplace_back(shape); + } +} + +PhysicsColliderCircle::~PhysicsColliderCircle() {} + +PhysicsColliderBox::~PhysicsColliderBox() {} + +PhysicsColliderPolygon::~PhysicsColliderPolygon() {} + +PhysicsColliderEdgeBox::~PhysicsColliderEdgeBox() {} + +PhysicsColliderEdgeChain::~PhysicsColliderEdgeChain() {} + +PhysicsColliderEdgePolygon::~PhysicsColliderEdgePolygon() {} + +PhysicsColliderEdgeSegment::~PhysicsColliderEdgeSegment() {} + +void PhysicsCollider::setDensity(float density, bool apply) +{ + if (density < 0) + { + return; + } + + _material.density = density; + if (apply) + { + for (auto& shape : _b2Shapes) + b2Shape_SetDensity(shape, density, false); + + b2Body_ApplyMassFromShapes(_body->getB2Body()); + } +} + +void PhysicsCollider::setRestitution(float restitution, bool apply) +{ + _material.restitution = restitution; + if (apply) + { + for (auto& shape : _b2Shapes) + b2Shape_SetDensity(shape, restitution, false); + + b2Body_ApplyMassFromShapes(_body->getB2Body()); + } +} + +void PhysicsCollider::setFriction(float friction, bool apply) +{ + _material.friction = friction; + + if (apply) + { + for (auto shape : _b2Shapes) + b2Shape_SetFriction(shape, friction); + b2Body_ApplyMassFromShapes(_body->getB2Body()); + } +} + +void PhysicsCollider::setSensor(bool sensor) +{ // FIXME: NOT SUPPORT + if (sensor != _sensor) + { + _sensor = sensor; + } +} + +void PhysicsCollider::recenterPoints(Vec2* points, int count, const Vec2& center) +{ + auto centroid = b2CentroidForPoly(reinterpret_cast(points), count); + for (int i = 0; i < count; i++) + { + points[i].x -= centroid.x; + points[i].y -= centroid.y; + } + + if (center != Vec2::ZERO) + { + for (int i = 0; i < count; ++i) + { + points[i] += center; + } + } +} + +Vec2 PhysicsCollider::getPolygonCenter(const Vec2* points, int count) +{ + auto centroid = b2CentroidForPoly(reinterpret_cast(points), count); + + return PhysicsHelper::toVec2(centroid); +} + +// PhysicsColliderCircle +PhysicsColliderCircle* PhysicsColliderCircle::create(PhysicsBody* body, + float radius, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /* = Vec2(0, 0)*/) +{ + PhysicsColliderCircle* collider = new PhysicsColliderCircle(body); + if (collider->init(radius, material, offset)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderCircle::init(float radius, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /*= Vec2(0, 0)*/) +{ + do + { + _type = Type::CIRCLE; + + auto circleShapeDef = b2DefaultShapeDef(); + b2Circle circle{PhysicsHelper::tob2Vec2(offset), radius}; + auto shape = b2CreateCircleShape(_body->getB2Body(), &circleShapeDef, &circle); + + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + + _area = calculateArea(); + + setMaterial(material); + return true; + } while (false); + + return false; +} + +float PhysicsColliderCircle::calculateArea(float radius) +{ + return B2_PI * radius * radius; +} + +float PhysicsColliderCircle::calculateArea() +{ + auto circle = b2Shape_GetCircle(_b2Shapes[0]); + return calculateArea(circle.radius); +} + +float PhysicsColliderCircle::getRadius() const +{ + return b2Shape_GetCircle(_b2Shapes[0]).radius; +} + +Vec2 PhysicsColliderCircle::getOffset() +{ + return PhysicsHelper::toVec2(b2Shape_GetCircle(_b2Shapes[0]).center); +} + +void PhysicsColliderCircle::updateScale() +{ + auto factor = std::abs(_newScaleX / _scaleX); + + auto circle = b2Shape_GetCircle(_b2Shapes[0]); + circle.center *= factor; + circle.radius *= factor; + + b2Shape_SetCircle(_b2Shapes[0], &circle); + + PhysicsCollider::updateScale(); +} + +// PhysicsColliderEdgeSegment +PhysicsColliderEdgeSegment* PhysicsColliderEdgeSegment::create(PhysicsBody* body, + const Vec2& a, + const Vec2& b, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + PhysicsColliderEdgeSegment* collider = new PhysicsColliderEdgeSegment(body); + if (collider->init(a, b, material, border)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderEdgeSegment::init(const Vec2& a, + const Vec2& b, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + do + { + _type = Type::EDGESEGMENT; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment{PhysicsHelper::tob2Vec2(a), PhysicsHelper::tob2Vec2(b)}; + auto shape = b2CreateSegmentShape(_body->getB2Body(), &shapeDef, &segment); + + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsColliderEdgeSegment::getPointA() const +{ + auto detail = b2Shape_GetSegment(_b2Shapes[0]); + return PhysicsHelper::toVec2(detail.point1); +} + +Vec2 PhysicsColliderEdgeSegment::getPointB() const +{ + auto detail = b2Shape_GetSegment(_b2Shapes[0]); + return PhysicsHelper::toVec2(detail.point2); +} + +Vec2 PhysicsColliderEdgeSegment::getCenter() +{ + auto detail = b2Shape_GetSegment(_b2Shapes[0]); + return PhysicsHelper::toVec2((detail.point1 + detail.point2) * 0.5f); +} + +void PhysicsColliderEdgeSegment::updateScale() +{ + auto factorX = _newScaleX / _scaleX; + auto factorY = _newScaleY / _scaleY; + + auto shape = _b2Shapes[0]; + auto detail = b2Shape_GetSegment(shape); + detail.point1.x *= factorX; + detail.point1.y *= factorY; + detail.point2.x *= factorX; + detail.point2.y *= factorY; + b2Shape_SetSegment(shape, &detail); + + PhysicsCollider::updateScale(); +} + +// PhysicsColliderBox +PhysicsColliderBox* PhysicsColliderBox::create(PhysicsBody* body, + const Vec2& size, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /* = Vec2(0, 0)*/, + float radius /* = 0.0f*/) +{ + PhysicsColliderBox* collider = new PhysicsColliderBox(body); + if (collider->init(size, material, offset, radius)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderBox::init(const Vec2& size, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /*= Vec2(0, 0)*/, + float radius /* = 0.0f*/) +{ + do + { + _type = Type::BOX; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + // !!!remark: should div 2 with b2MakeOffsetBox, otherwise, size will be double + auto polygon = b2MakeOffsetBox(size.x / 2, size.y / 2, phlp::tob2Vec2(offset), b2MakeRot(radius)); + auto shape = b2CreatePolygonShape(_body->getB2Body(), &shapeDef, &polygon); + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + + _area = calculateArea(); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsColliderBox::getSize() const +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + auto x = b2Distance(polygon.vertices[1], polygon.vertices[2]); + auto y = b2Distance(polygon.vertices[0], polygon.vertices[1]); + return phlp::toVec2(b2Vec2{x, y}); +} + +// PhysicsColliderPolygon +PhysicsColliderPolygon* PhysicsColliderPolygon::create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /* = Vec2(0, 0)*/, + float radius /* = 0.0f*/) +{ + PhysicsColliderPolygon* collider = new PhysicsColliderPolygon(body); + if (collider->init(points, count, material, offset, radius)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderPolygon::init(const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + const Vec2& offset /* = Vec2(0, 0)*/, + float radius /* = 0.0f*/) +{ + do + { + _type = Type::POLYGON; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + auto hull = b2ComputeHull(reinterpret_cast(points), count); + auto polygon = b2MakeOffsetPolygon(&hull, PhysicsHelper::tob2Vec2(offset), b2MakeRot(radius)); + auto shape = b2CreatePolygonShape(_body->getB2Body(), &shapeDef, &polygon); + + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + + _area = calculateArea(); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +float PhysicsColliderPolygon::calculateArea(const Vec2* points, int count) +{ + float area = 0.0f; + for (int i = 0; i < count; ++i) + { + const auto& current = points[i]; + const auto& next = points[(i + 1) % count]; + area += current.x * next.y - next.x * current.y; + } + + return 0.5f * fabs(area); +} + +float PhysicsColliderPolygon::calculateArea() +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + auto area = calculateArea(reinterpret_cast(polygon.vertices), polygon.count); + return area; +} + +Vec2 PhysicsColliderPolygon::getPoint(int i) const +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + return i < polygon.count ? PhysicsHelper::toVec2(polygon.vertices[i]) : Vec2::ZERO; +} + +void PhysicsColliderPolygon::getPoints(Vec2* outPoints) const +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + memcpy(outPoints, polygon.vertices, sizeof(Vec2) * polygon.count); +} + +int PhysicsColliderPolygon::getPointsCount() const +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + return polygon.count; +} + +Vec2 PhysicsColliderPolygon::getCenter() +{ + auto polygon = b2Shape_GetPolygon(_b2Shapes[0]); + + return PhysicsHelper::toVec2(polygon.centroid); +} + +void PhysicsColliderPolygon::updateScale() +{ + auto factorX = _newScaleX / _scaleX; + auto factorY = _newScaleY / _scaleY; + + auto shape = _b2Shapes[0]; + auto polygon = b2Shape_GetPolygon(shape); + auto count = polygon.count; + auto& verts = polygon.vertices; + for (int i = 0; i < count; ++i) + { + verts[i].x *= factorX; + verts[i].y *= factorY; + } + + // convert hole to clockwise + if (factorX * factorY < 0) + { + for (int i = 0; i < count / 2; ++i) + { + auto v = polygon.vertices[i]; + verts[i] = polygon.vertices[count - i - 1]; + verts[count - i - 1] = v; + } + } + + // FIXME: apply radius and offset + auto transform = b2Transform_identity; + auto hull = b2ComputeHull(reinterpret_cast(polygon.vertices), count); + auto polygon1 = b2MakePolygon(&hull, 0); + + b2Shape_SetPolygon(shape, &polygon1); + + PhysicsCollider::updateScale(); +} + +// PhysicsColliderEdgeBox +PhysicsColliderEdgeBox* PhysicsColliderEdgeBox::create(PhysicsBody* body, + const Vec2& size, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/, + const Vec2& offset /* = Vec2(0, 0)*/) +{ + PhysicsColliderEdgeBox* collider = new PhysicsColliderEdgeBox(body); + if (collider->init(size, material, border, offset)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderEdgeBox::init(const Vec2& size, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/, + const Vec2& offset /*= Vec2(0, 0)*/) +{ + do + { + _type = Type::EDGEBOX; + + // NOTE: box2d doesn't support border + + b2Vec2 vec[4] = {}; + vec[0] = phlp::tob2Vec2(Vec2(-size.width / 2 + offset.x, -size.height / 2 + offset.y)); + vec[1] = phlp::tob2Vec2(Vec2(+size.width / 2 + offset.x, -size.height / 2 + offset.y)); + vec[2] = phlp::tob2Vec2(Vec2(+size.width / 2 + offset.x, +size.height / 2 + offset.y)); + vec[3] = phlp::tob2Vec2(Vec2(-size.width / 2 + offset.x, +size.height / 2 + offset.y)); + + int i = 0; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + for (; i < 4; ++i) + { + b2Segment segment{vec[i], vec[(i + 1) % 4]}; + auto shape = b2CreateSegmentShape(_body->getB2Body(), &shapeDef, &segment); + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + } + AX_BREAK_IF(i < 4); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +// PhysicsColliderEdgeBox +PhysicsColliderEdgePolygon* PhysicsColliderEdgePolygon::create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + PhysicsColliderEdgePolygon* collider = new PhysicsColliderEdgePolygon(body); + if (collider->init(points, count, material, border)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +bool PhysicsColliderEdgePolygon::init(const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + do + { + _type = Type::EDGEPOLYGON; + + auto def = b2DefaultShapeDef(); + + int i = 0; + for (; i < count; ++i) + { + b2Segment segment{PhysicsHelper::tob2Vec2(points[i]), PhysicsHelper::tob2Vec2(points[(i + 1) % count])}; + auto shape = b2CreateSegmentShape(_body->getB2Body(), &def, &segment); + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + } + + AX_BREAK_IF(i < count); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsColliderEdgePolygon::getCenter() +{ + // REMARK: check the logic whether identical to + // collect points then invoke b2CentroidForPoly + b2Vec2 centroid{0.0f, 0.0f}; + float signedArea = 0.0f; + int count = static_cast(_b2Shapes.size()); + + for (int i = 0; i < count; ++i) + { + auto curSegment = b2Shape_GetSegment(_b2Shapes[i]); + auto nextSegment = b2Shape_GetSegment(_b2Shapes[(i + 1) % count]); + const b2Vec2& current = curSegment.point1; + const b2Vec2& next = nextSegment.point1; + float crossProduct = b2Cross(current, next); + float triangleArea = 0.5f * crossProduct; + signedArea += triangleArea; + centroid += triangleArea * (current + next) * (1 / 3.0f); + } + + centroid *= (1 / signedArea); + return PhysicsHelper::toVec2(centroid); +} + +void PhysicsColliderEdgePolygon::getPoints(ax::Vec2* outPoints) const +{ + int i = 0; + for (auto&& shape : _b2Shapes) + { + auto& outPoint = outPoints[i++]; + auto segment = b2Shape_GetSegment(shape); + auto& inPoint = segment.point1; + outPoint.x = inPoint.x; + outPoint.y = inPoint.y; + } +} + +int PhysicsColliderEdgePolygon::getPointsCount() const +{ + return static_cast(_b2Shapes.size()); +} + +// PhysicsColliderEdgeChain +PhysicsColliderEdgeChain* PhysicsColliderEdgeChain::create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + PhysicsColliderEdgeChain* collider = new PhysicsColliderEdgeChain(body); + if (collider->init(points, count, material, border)) + { + collider->autorelease(); + return collider; + } + + AX_SAFE_DELETE(collider); + return nullptr; +} + +void PhysicsColliderEdgePolygon::updateScale() +{ + auto factorX = _newScaleX / _scaleX; + auto factorY = _newScaleY / _scaleY; + + for (auto&& shape : _b2Shapes) + { + auto segment = b2Shape_GetSegment(shape); + auto& a = segment.point1; + a.x *= factorX; + a.y *= factorY; + auto& b = segment.point2; + b.x *= factorX; + b.y *= factorY; + b2Shape_SetSegment(shape, &segment); + } + + PhysicsCollider::updateScale(); +} + +bool PhysicsColliderEdgeChain::init(const Vec2* points, + int count, + const PhysicsMaterial& material /* = MaterialDefault*/, + float border /* = 1*/) +{ + do + { + _type = Type::EDGECHAIN; + + auto def = b2DefaultShapeDef(); + int i = 0; + for (; i < count - 1; ++i) + { + b2Segment segment{PhysicsHelper::tob2Vec2(points[i]), PhysicsHelper::tob2Vec2(points[i + 1])}; + auto shape = b2CreateSegmentShape(_body->getB2Body(), &def, &segment); + AX_BREAK_IF(!b2Shape_IsValid(shape)); + + addShape(shape); + } + + AX_BREAK_IF(i < count - 1); + + setMaterial(material); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsColliderEdgeChain::getCenter() +{ + // REMARK: check the logic whether identical to + // collect points then invoke b2CentroidForPoly + b2Vec2 centroid{0.0f, 0.0f}; + float signedArea = 0.0f; + int count = static_cast(_b2Shapes.size()); + + for (int i = 0; i < count; ++i) + { + auto curSegment = b2Shape_GetSegment(_b2Shapes[i]); + auto nextSegment = b2Shape_GetSegment(_b2Shapes[(i + 1) % count]); + const b2Vec2& current = curSegment.point1; + const b2Vec2& next = i != (count - 1) ? nextSegment.point1 : nextSegment.point2; + float crossProduct = b2Cross(current, next); + float triangleArea = 0.5f * crossProduct; + signedArea += triangleArea; + centroid += triangleArea * (current + next) * (1 / 3.0f); + } + + centroid *= (1 / signedArea); + return PhysicsHelper::toVec2(centroid); +} + +void PhysicsColliderEdgeChain::getPoints(Vec2* outPoints) const +{ + int i = 0; + for (auto&& shape : _b2Shapes) + { + outPoints[i++] = PhysicsHelper::toVec2(b2Shape_GetSegment(shape).point1); + } + + outPoints[i++] = PhysicsHelper::toVec2(b2Shape_GetSegment(_b2Shapes.back()).point2); +} + +int PhysicsColliderEdgeChain::getPointsCount() const +{ + return static_cast(_b2Shapes.size() + 1); +} + +void PhysicsColliderEdgeChain::updateScale() +{ + auto factorX = _newScaleX / _scaleX; + auto factorY = _newScaleY / _scaleY; + + for (auto&& shape : _b2Shapes) + { + auto segment = b2Shape_GetSegment(shape); + auto& a = segment.point1; + a.x *= factorX; + a.y *= factorY; + auto& b = segment.point2; + b.x *= factorX; + b.y *= factorY; + b2Shape_SetSegment(shape, &segment); + } + + PhysicsCollider::updateScale(); +} + +void PhysicsCollider::setGroup(int group) +{ + if (group < 0) + { + const b2Filter filter{static_cast(CollisionBits::All), static_cast(CollisionBits::All), + group}; + for (auto&& shape : _b2Shapes) + { + + b2Shape_SetFilter(shape, filter); + } + } + + _group = group; +} + +bool PhysicsCollider::containsPoint(const Vec2& point) const +{ + auto b2pt = PhysicsHelper::tob2Vec2(point); + for (auto&& shape : _b2Shapes) + { + if (b2Shape_TestPoint(shape, b2pt)) + return true; + } + + return false; +} + +} // namespace ax + +#endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/PhysicsShape.h b/axmol/physics/PhysicsCollider.h similarity index 71% rename from core/physics/PhysicsShape.h rename to axmol/physics/PhysicsCollider.h index f6f68fbaa1d5..abb8c6af22e7 100644 --- a/core/physics/PhysicsShape.h +++ b/axmol/physics/PhysicsCollider.h @@ -26,13 +26,14 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_PHYSICS) -# include "base/Object.h" -# include "math/Math.h" +# include "axmol/base/Object.h" +# include "axmol/math/Math.h" +# include "box2d/box2d.h" -struct cpShape; +# include "axmol/base/axstd.h" namespace ax { @@ -66,7 +67,7 @@ const PhysicsMaterial PHYSICSSHAPE_MATERIAL_DEFAULT; * @brief A shape for body. You do not create PhysicsWorld objects directly, instead, you can view PhysicsBody to see * how to create it. */ -class AX_DLL PhysicsShape : public Object +class AX_DLL PhysicsCollider : public Object { public: enum class Type @@ -87,6 +88,16 @@ class AX_DLL PhysicsShape : public Object EDGEPOLYGEN = EDGEPOLYGON, }; + enum CollisionBits + { + Static = 0x00000001, + Dynamic = 0x00000002, + Debris = 0x00000004, + Player = 0x00000008, + + All = (~0u) + }; + public: /** * Get the body that this shape attaches. @@ -109,22 +120,6 @@ class AX_DLL PhysicsShape : public Object */ float getArea() const { return _area; } - /** - * Get this shape's moment. - * - * @return A float number. - */ - float getMoment() const { return _moment; } - - /** - * Set this shape's moment. - * - * It will change the body's moment this shape attaches. - * - * @param moment A float number. - */ - void setMoment(float moment); - /** * Set this shape's tag. * @@ -139,21 +134,6 @@ class AX_DLL PhysicsShape : public Object */ int getTag() const { return _tag; } - /** - * Get the mass of this shape. - * - * @return A float number. - */ - float getMass() const { return _mass; } - - /** - * Set this shape's mass. - * - * It will change the body's mass this shape attaches. - * - * @param mass A float number. - */ - void setMass(float mass); /** * Get this shape's density. @@ -169,7 +149,7 @@ class AX_DLL PhysicsShape : public Object * * @param density A float number. */ - void setDensity(float density); + void setDensity(float density, bool apply = true); /** * Get this shape's restitution. @@ -185,7 +165,7 @@ class AX_DLL PhysicsShape : public Object * * @param restitution A float number. */ - void setRestitution(float restitution); + void setRestitution(float restitution, bool apply = true); /** * Get this shape's friction. @@ -201,7 +181,7 @@ class AX_DLL PhysicsShape : public Object * * @param friction A float number. */ - void setFriction(float friction); + void setFriction(float friction, bool apply = true); /** * Get this shape's PhysicsMaterial object. @@ -219,15 +199,11 @@ class AX_DLL PhysicsShape : public Object */ void setMaterial(const PhysicsMaterial& material); bool isSensor() const { return _sensor; } - void setSensor(bool sensor); /** - * Calculate the default moment value. - * - * This function should be overridden in inherit classes. - * @return A float number, equals 0.0. + * box2d v3 doesn't support modify sensor for shapes runtime once the shape is created */ - virtual float calculateDefaultMoment() { return 0.0f; } + void setSensor(bool sensor); /** * Get this shape's position offset. @@ -342,28 +318,30 @@ class AX_DLL PhysicsShape : public Object */ int getGroup() { return _group; } -protected: - void setBody(PhysicsBody* body); + void deatchFromBody(); + + // A deatched collider can't be re-attach to rigibody again + bool isDeatched() const; +protected: /** calculate the area of this shape */ virtual float calculateArea() { return 0.0f; } virtual void setScale(float scaleX, float scaleY); virtual void updateScale(); - void addShape(cpShape* shape); + void addShape(b2ShapeId shape); protected: - PhysicsShape(); - virtual ~PhysicsShape() = 0; + PhysicsCollider(PhysicsBody* body); + virtual ~PhysicsCollider() = 0; protected: PhysicsBody* _body; - std::vector _cpShapes; + + axstd::pod_vector _b2Shapes; Type _type; float _area; - float _mass; - float _moment; bool _sensor; float _scaleX; float _scaleY; @@ -383,20 +361,21 @@ class AX_DLL PhysicsShape : public Object }; /** A circle shape. */ -class AX_DLL PhysicsShapeCircle : public PhysicsShape +class AX_DLL PhysicsColliderCircle : public PhysicsCollider { public: /** - * Creates a PhysicsShapeCircle with specified value. + * Creates a PhysicsColliderCircle with specified value. * * @param radius A float number, it is the circle's radius. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return An autoreleased PhysicsShapeCircle object pointer. + * @return An autoreleased PhysicsColliderCircle object pointer. */ - static PhysicsShapeCircle* create(float radius, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - const Vec2& offset = Vec2(0.0f, 0.0f)); + static PhysicsColliderCircle* create(PhysicsBody* body, + float radius, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + const Vec2& offset = Vec2(0.0f, 0.0f)); /** * Calculate the area of a circle with specified radius. @@ -406,23 +385,6 @@ class AX_DLL PhysicsShapeCircle : public PhysicsShape */ static float calculateArea(float radius); - /** - * Calculate the moment of a circle with specified value. - * - * @param mass A float number - * @param radius A float number - * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return A float number - */ - static float calculateMoment(float mass, float radius, const Vec2& offset = Vec2::ZERO); - - /** - * Calculate the moment for a circle. - * - * @return A float number. - */ - virtual float calculateDefaultMoment() override; - /** * Get the circle's radius. * @@ -435,38 +397,39 @@ class AX_DLL PhysicsShapeCircle : public PhysicsShape * * @return A Vec2 object. */ - virtual Vec2 getOffset() override; + Vec2 getOffset() override; protected: bool init(float radius, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, const Vec2& offset = Vec2::ZERO); - virtual float calculateArea() override; - virtual void updateScale() override; + float calculateArea() override; + void updateScale() override; protected: - PhysicsShapeCircle(); - virtual ~PhysicsShapeCircle(); + PhysicsColliderCircle(PhysicsBody* body) : PhysicsCollider(body) {} + virtual ~PhysicsColliderCircle(); }; /** A polygon shape. */ -class AX_DLL PhysicsShapePolygon : public PhysicsShape +class AX_DLL PhysicsColliderPolygon : public PhysicsCollider { public: /** - * Creates a PhysicsShapePolygon with specified value. + * Creates a PhysicsColliderPolygon with specified value. * * @param points A Vec2 object pointer, it is an array of Vec2. * @param count An integer number, contains the count of the points array. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return An autoreleased PhysicsShapePolygon object pointer. + * @return An autoreleased PhysicsColliderPolygon object pointer. */ - static PhysicsShapePolygon* create(const Vec2* points, - int count, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - const Vec2& offset = Vec2::ZERO, - float radius = 0.0f); + static PhysicsColliderPolygon* create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + const Vec2& offset = Vec2::ZERO, + float radius = 0.0f); /** * Calculate the area of a polygon with specified value. @@ -477,28 +440,6 @@ class AX_DLL PhysicsShapePolygon : public PhysicsShape */ static float calculateArea(const Vec2* points, int count); - /** - * Calculate the moment of a polygon with specified value. - * - * @param mass A float number - * @param points A Vec2 object pointer, it is an array of Vec2. - * @param count An integer number, contains the count of the points array. - * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return A float number - */ - static float calculateMoment(float mass, - const Vec2* points, - int count, - const Vec2& offset = Vec2::ZERO, - float radius = 0.0f); - - /** - * Calculate the moment for a polygon. - * - * @return A float number. - */ - float calculateDefaultMoment() override; - /** * Get a point of this polygon's points array. * @@ -526,7 +467,7 @@ class AX_DLL PhysicsShapePolygon : public PhysicsShape * * @return A Vec2 object. */ - virtual Vec2 getCenter() override; + Vec2 getCenter() override; protected: bool init(const Vec2* points, @@ -535,29 +476,30 @@ class AX_DLL PhysicsShapePolygon : public PhysicsShape const Vec2& offset = Vec2::ZERO, float radius = 0.0f); float calculateArea() override; - virtual void updateScale() override; + void updateScale() override; protected: - PhysicsShapePolygon(); - virtual ~PhysicsShapePolygon(); + PhysicsColliderPolygon(PhysicsBody* body) : PhysicsCollider(body) {} + virtual ~PhysicsColliderPolygon(); }; /** A box shape. */ -class AX_DLL PhysicsShapeBox : public PhysicsShapePolygon +class AX_DLL PhysicsColliderBox : public PhysicsColliderPolygon { public: /** - * Creates a PhysicsShapeBox with specified value. + * Creates a PhysicsColliderBox with specified value. * * @param size The size contains this box's width and height. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return An autoreleased PhysicsShapeBox object pointer. + * @return An autoreleased PhysicsColliderBox object pointer. */ - static PhysicsShapeBox* create(const Vec2& size, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - const Vec2& offset = Vec2::ZERO, - float radius = 0.0f); + static PhysicsColliderBox* create(PhysicsBody* body, + const Vec2& size, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + const Vec2& offset = Vec2::ZERO, + float radius = 0.0f); /** * Get this box's width and height. @@ -571,7 +513,7 @@ class AX_DLL PhysicsShapeBox : public PhysicsShapePolygon * * @return A Vec2 object. */ - virtual Vec2 getOffset() override { return getCenter(); } + Vec2 getOffset() override { return getCenter(); } protected: bool init(const Vec2& size, @@ -580,27 +522,28 @@ class AX_DLL PhysicsShapeBox : public PhysicsShapePolygon float radius = 0.0f); protected: - PhysicsShapeBox(); - virtual ~PhysicsShapeBox(); + PhysicsColliderBox(PhysicsBody* body) : PhysicsColliderPolygon(body) {} + virtual ~PhysicsColliderBox(); }; /** A segment shape. */ -class AX_DLL PhysicsShapeEdgeSegment : public PhysicsShape +class AX_DLL PhysicsColliderEdgeSegment : public PhysicsCollider { public: /** - * Creates a PhysicsShapeEdgeSegment with specified value. + * Creates a PhysicsColliderEdgeSegment with specified value. * * @param a It's the edge's begin position. * @param b It's the edge's end position. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param border It's a edge's border width. - * @return An autoreleased PhysicsShapeEdgeSegment object pointer. + * @return An autoreleased PhysicsColliderEdgeSegment object pointer. */ - static PhysicsShapeEdgeSegment* create(const Vec2& a, - const Vec2& b, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - float border = 1); + static PhysicsColliderEdgeSegment* create(PhysicsBody* body, + const Vec2& a, + const Vec2& b, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + float border = 1); /** * Get this edge's begin position. @@ -621,46 +564,47 @@ class AX_DLL PhysicsShapeEdgeSegment : public PhysicsShape * * @return A Vec2 object. */ - virtual Vec2 getCenter() override; + Vec2 getCenter() override; protected: bool init(const Vec2& a, const Vec2& b, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); - virtual void updateScale() override; + void updateScale() override; protected: - PhysicsShapeEdgeSegment(); - virtual ~PhysicsShapeEdgeSegment(); + PhysicsColliderEdgeSegment(PhysicsBody* body) : PhysicsCollider(body) {} + virtual ~PhysicsColliderEdgeSegment(); friend class PhysicsBody; }; /** An edge polygon shape. */ -class AX_DLL PhysicsShapeEdgePolygon : public PhysicsShape +class AX_DLL PhysicsColliderEdgePolygon : public PhysicsCollider { public: /** - * Creates a PhysicsShapeEdgePolygon with specified value. + * Creates a PhysicsColliderEdgePolygon with specified value. * * @param points A Vec2 object pointer, it contains an array of points. * @param count An integer number, contains the count of the points array. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param border It's a edge's border width. - * @return An autoreleased PhysicsShapeEdgePolygon object pointer. + * @return An autoreleased PhysicsColliderEdgePolygon object pointer. */ - static PhysicsShapeEdgePolygon* create(const Vec2* points, - int count, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - float border = 1); + static PhysicsColliderEdgePolygon* create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + float border = 1); /** * Get this polygon's center position. * * @return A Vec2 object. */ - virtual Vec2 getCenter() override; + Vec2 getCenter() override; /** * Get this polygon's points array. @@ -681,39 +625,40 @@ class AX_DLL PhysicsShapeEdgePolygon : public PhysicsShape int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); - virtual void updateScale() override; + void updateScale() override; protected: - PhysicsShapeEdgePolygon(); - virtual ~PhysicsShapeEdgePolygon(); + PhysicsColliderEdgePolygon(PhysicsBody* body) : PhysicsCollider(body) {} + virtual ~PhysicsColliderEdgePolygon(); friend class PhysicsBody; }; /** An edge box shape. */ -class AX_DLL PhysicsShapeEdgeBox : public PhysicsShapeEdgePolygon +class AX_DLL PhysicsColliderEdgeBox : public PhysicsColliderEdgePolygon { public: /** - * Creates a PhysicsShapeEdgeBox with specified value. + * Creates a PhysicsColliderEdgeBox with specified value. * * @param size The size contains this box's width and height. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param border It's a edge's border width. * @param offset A Vec2 object, it is the offset from the body's center of gravity in body local coordinates. - * @return An autoreleased PhysicsShapeEdgeBox object pointer. + * @return An autoreleased PhysicsColliderEdgeBox object pointer. */ - static PhysicsShapeEdgeBox* create(const Vec2& size, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - float border = 0, - const Vec2& offset = Vec2::ZERO); + static PhysicsColliderEdgeBox* create(PhysicsBody* body, + const Vec2& size, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + float border = 0, + const Vec2& offset = Vec2::ZERO); /** * Get this box's position offset. * * @return A Vec2 object. */ - virtual Vec2 getOffset() override { return getCenter(); } + Vec2 getOffset() override { return getCenter(); } protected: bool init(const Vec2& size, @@ -722,36 +667,37 @@ class AX_DLL PhysicsShapeEdgeBox : public PhysicsShapeEdgePolygon const Vec2& offset = Vec2::ZERO); protected: - PhysicsShapeEdgeBox(); - virtual ~PhysicsShapeEdgeBox(); + PhysicsColliderEdgeBox(PhysicsBody* body) : PhysicsColliderEdgePolygon(body) {} + virtual ~PhysicsColliderEdgeBox(); friend class PhysicsBody; }; /** A chain shape. */ -class AX_DLL PhysicsShapeEdgeChain : public PhysicsShape +class AX_DLL PhysicsColliderEdgeChain : public PhysicsCollider { public: /** - * Creates a PhysicsShapeEdgeChain with specified value. + * Creates a PhysicsColliderEdgeChain with specified value. * * @param points A Vec2 object pointer, it contains an array of points. * @param count An integer number, contains the count of the points array. * @param material A PhysicsMaterial object, the default value is PHYSICSSHAPE_MATERIAL_DEFAULT. * @param border It's a edge's border width. - * @return An autoreleased PhysicsShapeEdgeChain object pointer. + * @return An autoreleased PhysicsColliderEdgeChain object pointer. */ - static PhysicsShapeEdgeChain* create(const Vec2* points, - int count, - const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, - float border = 1); + static PhysicsColliderEdgeChain* create(PhysicsBody* body, + const Vec2* points, + int count, + const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, + float border = 1); /** * Get this chain's center position. * * @return A Vec2 object. */ - virtual Vec2 getCenter() override; + Vec2 getCenter() override; /** * Get this chain's points array. @@ -772,11 +718,11 @@ class AX_DLL PhysicsShapeEdgeChain : public PhysicsShape int count, const PhysicsMaterial& material = PHYSICSSHAPE_MATERIAL_DEFAULT, float border = 1); - virtual void updateScale() override; + void updateScale() override; protected: - PhysicsShapeEdgeChain(); - virtual ~PhysicsShapeEdgeChain(); + PhysicsColliderEdgeChain(PhysicsBody* body) : PhysicsCollider(body) {} + virtual ~PhysicsColliderEdgeChain(); friend class PhysicsBody; }; @@ -784,6 +730,6 @@ class AX_DLL PhysicsShapeEdgeChain : public PhysicsShape /** @} */ /** @} */ -} +} // namespace ax #endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/PhysicsContact.cpp b/axmol/physics/PhysicsContact.cpp similarity index 82% rename from core/physics/PhysicsContact.cpp rename to axmol/physics/PhysicsContact.cpp index 267ff043be21..4b42b1270234 100644 --- a/core/physics/PhysicsContact.cpp +++ b/axmol/physics/PhysicsContact.cpp @@ -23,13 +23,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "physics/PhysicsContact.h" +#include "axmol/physics/PhysicsContact.h" #if defined(AX_ENABLE_PHYSICS) -# include "chipmunk/chipmunk.h" -# include "physics/PhysicsBody.h" -# include "physics/PhysicsHelper.h" -# include "base/EventCustom.h" +# include "axmol/physics/PhysicsBody.h" +# include "axmol/physics/PhysicsHelper.h" +# include "axmol/base/EventCustom.h" namespace ax { @@ -56,7 +55,7 @@ PhysicsContact::~PhysicsContact() AX_SAFE_DELETE(_preContactData); } -PhysicsContact* PhysicsContact::construct(PhysicsShape* a, PhysicsShape* b) +PhysicsContact* PhysicsContact::construct(PhysicsCollider* a, PhysicsCollider* b) { PhysicsContact* contact = new PhysicsContact(); if (contact->init(a, b)) @@ -68,7 +67,7 @@ PhysicsContact* PhysicsContact::construct(PhysicsShape* a, PhysicsShape* b) return nullptr; } -bool PhysicsContact::init(PhysicsShape* a, PhysicsShape* b) +bool PhysicsContact::init(PhysicsCollider* a, PhysicsCollider* b) { do { @@ -90,17 +89,18 @@ void PhysicsContact::generateContactData() return; } - cpArbiter* arb = static_cast(_contactInfo); + auto count = b2Body_GetContactCapacity(b2_nullBodyId); // FIXME + b2ContactData* arb = static_cast(_contactInfo); AX_SAFE_DELETE(_preContactData); _preContactData = _contactData; _contactData = new PhysicsContactData(); - _contactData->count = cpArbiterGetCount(arb); + _contactData->count = count; for (int i = 0; i < _contactData->count && i < PhysicsContactData::POINT_MAX; ++i) { - _contactData->points[i] = PhysicsHelper::cpv2vec2(cpArbiterGetPointA(arb, i)); + _contactData->points[i] = PhysicsHelper::toVec2(arb->manifold.points[i].point); } - _contactData->normal = _contactData->count > 0 ? PhysicsHelper::cpv2vec2(cpArbiterGetNormal(arb)) : Vec2::ZERO; + _contactData->normal = _contactData->count > 0 ? PhysicsHelper::toVec2(arb->manifold.normal) : Vec2::ZERO; } // PhysicsContactPreSolve implementation @@ -110,37 +110,45 @@ PhysicsContactPreSolve::~PhysicsContactPreSolve() {} float PhysicsContactPreSolve::getRestitution() const { - return cpArbiterGetRestitution(static_cast(_contactInfo)); + //return cpArbiterGetRestitution(static_cast(_contactInfo)); + + return 0; // FIXME } float PhysicsContactPreSolve::getFriction() const { - return cpArbiterGetFriction(static_cast(_contactInfo)); + //return cpArbiterGetFriction(static_cast(_contactInfo)); + return 0; // FIXME } Vec2 PhysicsContactPreSolve::getSurfaceVelocity() const { - return PhysicsHelper::cpv2vec2(cpArbiterGetSurfaceVelocity(static_cast(_contactInfo))); + //return PhysicsHelper::cpv2vec2(cpArbiterGetSurfaceVelocity(static_cast(_contactInfo))); + return 0; // FIXME } void PhysicsContactPreSolve::setRestitution(float restitution) { - cpArbiterSetRestitution(static_cast(_contactInfo), restitution); + // FIXME + //cpArbiterSetRestitution(static_cast(_contactInfo), restitution); } void PhysicsContactPreSolve::setFriction(float friction) { - cpArbiterSetFriction(static_cast(_contactInfo), friction); + // FIXME + //cpArbiterSetFriction(static_cast(_contactInfo), friction); } void PhysicsContactPreSolve::setSurfaceVelocity(const Vec2& velocity) { - cpArbiterSetSurfaceVelocity(static_cast(_contactInfo), PhysicsHelper::vec22cpv(velocity)); + // FIXME + //cpArbiterSetSurfaceVelocity(static_cast(_contactInfo), PhysicsHelper::vec22cpv(velocity)); } void PhysicsContactPreSolve::ignore() { - cpArbiterIgnore(static_cast(_contactInfo)); + // FIXME + //cpArbiterIgnore(static_cast(_contactInfo)); } // PhysicsContactPostSolve implementation @@ -150,17 +158,23 @@ PhysicsContactPostSolve::~PhysicsContactPostSolve() {} float PhysicsContactPostSolve::getRestitution() const { - return cpArbiterGetRestitution(static_cast(_contactInfo)); + // FIXME + //return cpArbiterGetRestitution(static_cast(_contactInfo)); + return 0; } float PhysicsContactPostSolve::getFriction() const { - return cpArbiterGetFriction(static_cast(_contactInfo)); + // FIXME + //return cpArbiterGetFriction(static_cast(_contactInfo)); + return 0; } Vec2 PhysicsContactPostSolve::getSurfaceVelocity() const { - return PhysicsHelper::cpv2vec2(cpArbiterGetSurfaceVelocity(static_cast(_contactInfo))); + // FIXME + //return PhysicsHelper::cpv2vec2(cpArbiterGetSurfaceVelocity(static_cast(_contactInfo))); + return Vec2::ZERO; } EventListenerPhysicsContact::EventListenerPhysicsContact() @@ -251,7 +265,7 @@ EventListenerPhysicsContact* EventListenerPhysicsContact::create() return nullptr; } -bool EventListenerPhysicsContact::hitTest(PhysicsShape* /*shapeA*/, PhysicsShape* /*shapeB*/) +bool EventListenerPhysicsContact::hitTest(PhysicsCollider* /*shapeA*/, PhysicsCollider* /*shapeB*/) { return true; } @@ -307,7 +321,7 @@ EventListenerPhysicsContactWithBodies::EventListenerPhysicsContactWithBodies() : EventListenerPhysicsContactWithBodies::~EventListenerPhysicsContactWithBodies() {} -bool EventListenerPhysicsContactWithBodies::hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) +bool EventListenerPhysicsContactWithBodies::hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) { if ((shapeA->getBody() == _a && shapeB->getBody() == _b) || (shapeA->getBody() == _b && shapeB->getBody() == _a)) { @@ -339,8 +353,8 @@ EventListenerPhysicsContactWithShapes::EventListenerPhysicsContactWithShapes() : EventListenerPhysicsContactWithShapes::~EventListenerPhysicsContactWithShapes() {} -EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::create(PhysicsShape* shapeA, - PhysicsShape* shapeB) +EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::create(PhysicsCollider* shapeA, + PhysicsCollider* shapeB) { EventListenerPhysicsContactWithShapes* obj = new EventListenerPhysicsContactWithShapes(); @@ -356,7 +370,7 @@ EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::cr return nullptr; } -bool EventListenerPhysicsContactWithShapes::hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) +bool EventListenerPhysicsContactWithShapes::hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) { if ((shapeA == _a && shapeB == _b) || (shapeA == _b && shapeB == _a)) { @@ -384,7 +398,7 @@ EventListenerPhysicsContactWithShapes* EventListenerPhysicsContactWithShapes::cl return nullptr; } -EventListenerPhysicsContactWithGroup::EventListenerPhysicsContactWithGroup() : _group(CP_NO_GROUP) {} +EventListenerPhysicsContactWithGroup::EventListenerPhysicsContactWithGroup() : _group(0) {} EventListenerPhysicsContactWithGroup::~EventListenerPhysicsContactWithGroup() {} @@ -403,7 +417,7 @@ EventListenerPhysicsContactWithGroup* EventListenerPhysicsContactWithGroup::crea return nullptr; } -bool EventListenerPhysicsContactWithGroup::hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) +bool EventListenerPhysicsContactWithGroup::hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) { if (shapeA->getGroup() == _group || shapeB->getGroup() == _group) { diff --git a/core/physics/PhysicsContact.h b/axmol/physics/PhysicsContact.h similarity index 87% rename from core/physics/PhysicsContact.h rename to axmol/physics/PhysicsContact.h index 97502036c258..532071f886c7 100644 --- a/core/physics/PhysicsContact.h +++ b/axmol/physics/PhysicsContact.h @@ -26,19 +26,19 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_PHYSICS) -# include "base/Object.h" -# include "math/Math.h" -# include "base/EventListenerCustom.h" -# include "base/Event.h" -# include "base/EventCustom.h" +# include "axmol/base/Object.h" +# include "axmol/math/Math.h" +# include "axmol/base/EventListenerCustom.h" +# include "axmol/base/Event.h" +# include "axmol/base/EventCustom.h" namespace ax { -class PhysicsShape; +class PhysicsCollider; class PhysicsBody; class PhysicsWorld; @@ -78,10 +78,10 @@ class AX_DLL PhysicsContact : public EventCustom }; /** Get contact shape A. */ - PhysicsShape* getShapeA() const { return _shapeA; } + PhysicsCollider* getShapeA() const { return _shapeA; } /** Get contact shape B. */ - PhysicsShape* getShapeB() const { return _shapeB; } + PhysicsCollider* getShapeB() const { return _shapeB; } /** Get contact data. */ const PhysicsContactData* getContactData() const { return _contactData; } @@ -109,8 +109,8 @@ class AX_DLL PhysicsContact : public EventCustom EventCode getEventCode() const { return _eventCode; }; private: - static PhysicsContact* construct(PhysicsShape* a, PhysicsShape* b); - bool init(PhysicsShape* a, PhysicsShape* b); + static PhysicsContact* construct(PhysicsCollider* a, PhysicsCollider* b); + bool init(PhysicsCollider* a, PhysicsCollider* b); void setEventCode(EventCode eventCode) { _eventCode = eventCode; }; bool isNotificationEnabled() const { return _notificationEnable; } @@ -133,8 +133,8 @@ class AX_DLL PhysicsContact : public EventCustom private: PhysicsWorld* _world; - PhysicsShape* _shapeA; - PhysicsShape* _shapeB; + PhysicsCollider* _shapeA; + PhysicsCollider* _shapeB; EventCode _eventCode; bool _notificationEnable; bool _result; @@ -214,17 +214,17 @@ class AX_DLL EventListenerPhysicsContact : public EventListenerCustom * @return True if there's one available callback function at least, false if there's no one. */ - virtual bool checkAvailable() override; + bool checkAvailable() override; /** Clone an object from this listener.*/ - virtual EventListenerPhysicsContact* clone() override; + EventListenerPhysicsContact* clone() override; protected: /** * It will be call when two body have contact. * if return false, it will not invoke callbacks. */ - virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB); + virtual bool hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB); public: /** @@ -267,9 +267,9 @@ class AX_DLL EventListenerPhysicsContactWithBodies : public EventListenerPhysics /** Create the listener. */ static EventListenerPhysicsContactWithBodies* create(PhysicsBody* bodyA, PhysicsBody* bodyB); - virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override; + bool hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) override; - virtual EventListenerPhysicsContactWithBodies* clone() override; + EventListenerPhysicsContactWithBodies* clone() override; protected: PhysicsBody* _a; @@ -285,14 +285,14 @@ class AX_DLL EventListenerPhysicsContactWithShapes : public EventListenerPhysics { public: /** Create the listener. */ - static EventListenerPhysicsContactWithShapes* create(PhysicsShape* shapeA, PhysicsShape* shapeB); + static EventListenerPhysicsContactWithShapes* create(PhysicsCollider* shapeA, PhysicsCollider* shapeB); - virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override; - virtual EventListenerPhysicsContactWithShapes* clone() override; + bool hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) override; + EventListenerPhysicsContactWithShapes* clone() override; protected: - PhysicsShape* _a; - PhysicsShape* _b; + PhysicsCollider* _a; + PhysicsCollider* _b; protected: EventListenerPhysicsContactWithShapes(); @@ -306,8 +306,8 @@ class AX_DLL EventListenerPhysicsContactWithGroup : public EventListenerPhysicsC /** Create the listener. */ static EventListenerPhysicsContactWithGroup* create(int group); - virtual bool hitTest(PhysicsShape* shapeA, PhysicsShape* shapeB) override; - virtual EventListenerPhysicsContactWithGroup* clone() override; + bool hitTest(PhysicsCollider* shapeA, PhysicsCollider* shapeB) override; + EventListenerPhysicsContactWithGroup* clone() override; protected: int _group; diff --git a/axmol/physics/PhysicsHelper.h b/axmol/physics/PhysicsHelper.h new file mode 100644 index 000000000000..bc756eb81082 --- /dev/null +++ b/axmol/physics/PhysicsHelper.h @@ -0,0 +1,37 @@ +#pragma once + +#include "axmol/math/Math.h" +#include "box2d/box2d.h" + +namespace ax +{ +struct PhysicsHelper +{ + static Vec2 toVec2(const b2Vec2& v) { return Vec2{v.x, v.y}; } + + static b2Vec2 tob2Vec2(const Vec2& v) { return b2Vec2{v.x, v.y}; } + + static b2AABB tob2AABB(const Rect& v) + { + return b2AABB{b2Vec2{v.getMinX(), v.getMinY()}, b2Vec2{v.getMaxX(), v.getMaxY()}}; + } + + static Color toColor(b2HexColor color) + { + unsigned int r = ((unsigned int)color >> 16) & 0xff; + unsigned int g = ((unsigned int)color >> 8) & 0xff; + unsigned int b = ((unsigned int)color) & 0xff; + return ax::Color{r / 255.f, g / 255.f, b / 255.f, 1.0f}; + } + + static b2HexColor tob2HexColor(Color color) + { + Color32 ret{color}; + return (b2HexColor)(static_cast(ret.r) << 16 | static_cast(ret.g) << 8 | + static_cast(ret.b)); + } +}; + +using phlp = PhysicsHelper; + +} // namespace ax diff --git a/axmol/physics/PhysicsJoint.cpp b/axmol/physics/PhysicsJoint.cpp new file mode 100644 index 000000000000..7c4bcb02184f --- /dev/null +++ b/axmol/physics/PhysicsJoint.cpp @@ -0,0 +1,1147 @@ +/**************************************************************************** + Copyright (c) 2013-2016 Chukong Technologies Inc. + Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "axmol/physics/PhysicsJoint.h" +#if defined(AX_ENABLE_PHYSICS) + +# include "axmol/physics/PhysicsBody.h" +# include "axmol/physics/PhysicsWorld.h" +# include "axmol/physics/PhysicsHelper.h" +# include "axmol/2d/Node.h" + +# include + +namespace ax +{ + +template +class Optional +{ + +public: + Optional() {} + explicit Optional(T d) : _isSet(true), _data(d) {} + Optional(const Optional& t) : _isSet(t._isSet), _data(t._data) {} + + // bool isNull() const { return !_isSet; } + // bool isDefineded() const { return _isSet; } + // bool isEmpty() const { return !_isSet; } + + T get() const + { + AXASSERT(_isSet, "data should be set!"); + return _data; + } + void set(T d) + { + _isSet = true; + _data = d; + } + +private: + bool _isSet = false; + T _data; +}; + +class WriteCache +{ +public: + Optional _grooveA; + Optional _grooveB; + Optional _anchr1; + Optional _anchr2; + Optional _min; + Optional _max; + Optional _distance; + Optional _restLength; + Optional _restAngle; + Optional _stiffness; + Optional _damping; + Optional _angle; + Optional _phase; + Optional _ratchet; + Optional _ratio; + Optional _rate; +}; + +# if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__) +# define LIKELY(x) (__builtin_expect((x), 1)) +# define UNLIKELY(x) (__builtin_expect((x), 0)) +# else +# define LIKELY(x) (x) +# define UNLIKELY(x) (x) +# endif + +# define AX_PJOINT_CACHE_READ(field) \ + do \ + { \ + if (UNLIKELY(_initDirty)) \ + { \ + return _writeCache->field.get(); \ + } \ + } while (0) + +# define AX_PJOINT_CACHE_WRITE2(field, method, arg, convertedArg) \ + do \ + { \ + if (UNLIKELY(_initDirty)) \ + { \ + _writeCache->field.set(arg); \ + delay([this, arg]() { method(_b2Joints.front(), convertedArg); }); \ + } \ + else \ + { \ + method(_b2Joints.front(), convertedArg); \ + } \ + } while (0) + +# define AX_PJOINT_CACHE_WRITE(field, method, arg) AX_PJOINT_CACHE_WRITE2(field, method, arg, arg) + +static void b2JointSetMaxForce(b2JointId joint, float force) +{ + if (!b2Joint_IsValid(joint)) + { + AXLOGE("b2JointSetMaxForce: joint is invalid"); + return; + } + auto jointType = b2Joint_GetType(joint); + switch (jointType) + { + case b2_distanceJoint: + b2DistanceJoint_SetMaxMotorForce(joint, force); + break; + case b2_filterJoint: + break; + case b2_motorJoint: + b2MotorJoint_SetMaxForce(joint, force); + break; + case b2_mouseJoint: + b2MouseJoint_SetMaxForce(joint, force); + break; + case b2_prismaticJoint: + b2PrismaticJoint_SetMaxMotorForce(joint, force); + break; + case b2_revoluteJoint: + break; + case b2_weldJoint: + break; + case b2_wheelJoint: + break; + } +} + +static float b2Body_GetAngle(const b2BodyId& bodyId) +{ + b2Rot rot = b2Body_GetRotation(bodyId); + float angle = b2Rot_GetAngle(rot); + return angle; +} + +PhysicsJoint::PhysicsJoint() + : _bodyA(nullptr) + , _bodyB(nullptr) + , _world(nullptr) + , _enable(false) + , _collisionEnable(true) + , _destroyMark(false) + , _tag(0) + , _maxForce(PHYSICS_INFINITY) + , _initDirty(true) +{ + _writeCache = new WriteCache(); +} + +PhysicsJoint::~PhysicsJoint() +{ + deatchFromBody(); +} + +void PhysicsJoint::deatchFromBody() +{ + for (auto& joint : _b2Joints) + { + if(b2Joint_IsValid(joint)) + b2DestroyJoint(joint); + } + _b2Joints.clear(); + + AX_SAFE_DELETE(_writeCache); +} + +bool PhysicsJoint::init(ax::PhysicsBody* a, ax::PhysicsBody* b) +{ + do + { + AXASSERT(a != nullptr && b != nullptr, "the body passed in is nil"); + AXASSERT(a != b, "the two bodies are equal"); + + _bodyA = a; + _bodyB = b; + _bodyA->_joints.emplace_back(this); + _bodyB->_joints.emplace_back(this); + + return true; + } while (false); + + return false; +} + +bool PhysicsJoint::initJoint() +{ + if (_initDirty) + { + auto ret = buildConstraints(); + if (ret) { + for (auto&& joint : _b2Joints) + b2JointSetMaxForce(joint, _maxForce); + } + _initDirty = false; + return ret; + } + return false; +} + +void PhysicsJoint::flushDelayTasks() +{ + for (const auto& tsk : _delayTasks) + { + tsk(); + } + _delayTasks.clear(); +} + +void PhysicsJoint::setEnable(bool enable) +{ + if (_enable != enable) + { + _enable = enable; + + if (_world) + { + if (enable) + { + _world->addJoint(this); + } + else + { + _world->removeJoint(this, false); + } + } + } +} + +void PhysicsJoint::setCollisionEnable(bool enable) +{ + if (_collisionEnable != enable) + { + _collisionEnable = enable; + } +} + +void PhysicsJoint::removeFormWorld() +{ + if (_world) + { + _world->removeJoint(this, false); + } +} + +void PhysicsJoint::setMaxForce(float force) +{ + if (_initDirty) + { + delay([this, force]() { + _maxForce = force; + for (auto&& joint : _b2Joints) + b2JointSetMaxForce(joint, force); + }); + } + else + { + _maxForce = force; + for (auto&& joint : _b2Joints) + b2JointSetMaxForce(joint, force); + } +} + +PhysicsJointFixed* PhysicsJointFixed::instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr) +{ + auto joint = new PhysicsJointFixed(); + + if (joint->init(a, b)) + { + joint->_anchr = anchr; + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointFixed::buildConstraints() +{ + do + { + _bodyA->getNode()->setPosition(_anchr); + _bodyB->getNode()->setPosition(_anchr); + + //// add a pivot joint to fixed two body together + // auto joint = cpPivotJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), phlp::vec22cpv(_anchr)); + // AX_BREAK_IF(!b2Joint_IsValid(joint)); + //_b2Joints.emplace_back(joint); + + //// add a gear joint to make two body have the same rotation. + // joint = cpGearJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), 0, 1); + // AX_BREAK_IF(!b2Joint_IsValid(joint)); + //_b2Joints.emplace_back(joint); + + // FIXME: not 100% identical to cpPivotJointNew and cpGearJointNew + b2Vec2 a = phlp::tob2Vec2(_anchr); + b2WeldJointDef wd = b2DefaultWeldJointDef(); + wd.bodyIdA = _bodyA->getB2Body(); + wd.bodyIdB = _bodyB->getB2Body(); + wd.localAnchorA = b2Body_GetLocalPoint(wd.bodyIdA, a); + wd.localAnchorB = b2Body_GetLocalPoint(wd.bodyIdB, a); + wd.referenceAngle = b2Body_GetAngle(wd.bodyIdB) - b2Body_GetAngle(wd.bodyIdA); + wd.collideConnected = false; + auto weld = b2CreateWeldJoint(_bodyA->getWorld()->getB2World(), &wd); + AX_BREAK_IF(!b2Joint_IsValid(weld)); + _b2Joints.emplace_back(weld); + + _collisionEnable = false; + + return true; + } while (false); + + return false; +} + +PhysicsJointPin* PhysicsJointPin::instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot) +{ + auto joint = new PhysicsJointPin(); + + if (joint->init(a, b)) + { + joint->_anchr1 = pivot; + joint->_useSpecificAnchr = false; + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +PhysicsJointPin* PhysicsJointPin::instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2) +{ + auto joint = new PhysicsJointPin(); + + if (joint->init(a, b)) + { + joint->_anchr1 = anchr1; + joint->_anchr2 = anchr2; + joint->_useSpecificAnchr = true; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointPin::buildConstraints() +{ + do + { + b2RevoluteJointDef pivotJointDef = b2DefaultRevoluteJointDef(); + pivotJointDef.bodyIdA = _bodyA->getB2Body(); + pivotJointDef.bodyIdB = _bodyB->getB2Body(); + pivotJointDef.collideConnected = false; + pivotJointDef.localAnchorA = b2Body_GetLocalPoint(_bodyA->getB2Body(), phlp::tob2Vec2(_anchr1)); + if (_useSpecificAnchr) + { + pivotJointDef.localAnchorB = b2Body_GetLocalPoint(_bodyB->getB2Body(), phlp::tob2Vec2(_anchr2)); + } + else + { + pivotJointDef.localAnchorB = b2Body_GetLocalPoint(_bodyB->getB2Body(), phlp::tob2Vec2(_anchr1)); + } + + auto joint = b2CreateRevoluteJoint(_bodyA->getWorld()->getB2World(), &pivotJointDef); + + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +PhysicsJointLimit* PhysicsJointLimit::instantiate(PhysicsBody* a, + PhysicsBody* b, + const Vec2& anchr1, + const Vec2& anchr2, + float min, + float max) +{ + auto joint = new PhysicsJointLimit(); + + if (joint->init(a, b)) + { + joint->_anchr1 = anchr1; + joint->_anchr2 = anchr2; + joint->_min = min; + joint->_max = max; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +PhysicsJointLimit* PhysicsJointLimit::instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2) +{ + return instantiate(a, b, anchr1, anchr2, 0, b->local2World(anchr1).getDistance(a->local2World(anchr2))); +} + +bool PhysicsJointLimit::buildConstraints() +{ + do + { + // alternative implementation using b2PrismaticJointDef + // b2PrismaticJointDef def = b2DefaultPrismaticJointDef(); + // def.bodyIdA = _bodyA->getB2Body(); + // def.bodyIdB = _bodyB->getB2Body(); + // def.localAnchorA = phlp::tob2Vec2(_anchr1); + // def.localAnchorB = phlp::tob2Vec2(_anchr2); + // def.localAxisA = b2Vec2{1.0f, 0.0f}; // Axis along which the bodies can slide + // def.enableLimit = true; + // def.lowerTranslation = _min; + // def.upperTranslation = _max; + // + // auto joint = b2CreatePrismaticJoint(_bodyA->getWorld()->getB2World(), &def); + + b2DistanceJointDef jd = b2DefaultDistanceJointDef(); + + jd.bodyIdA = _bodyA->getB2Body(); + jd.bodyIdB = _bodyB->getB2Body(); + + jd.localAnchorA = phlp::tob2Vec2(_anchr1); + jd.localAnchorB = phlp::tob2Vec2(_anchr2); + + // !IMPORTANT: calculate the length based on the world position of the anchors + jd.length = _bodyB->local2World(_anchr1).getDistance(_bodyA->local2World(_anchr2)); + + jd.minLength = _min; + jd.maxLength = _max; + + b2JointId joint = b2CreateDistanceJoint(_bodyA->getWorld()->getB2World(), &jd); + + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointLimit::getMin() const +{ + return _min; +} + +void PhysicsJointLimit::setMin(float min) +{ + _min = min; + b2PrismaticJoint_SetLimits(_b2Joints[0], min, _max); +} + +float PhysicsJointLimit::getMax() const +{ + return _max; +} + +void PhysicsJointLimit::setMax(float max) +{ + _max = max; + + b2PrismaticJoint_SetLimits(_b2Joints[0], _min, max); +} + +Vec2 PhysicsJointLimit::getAnchr1() const +{ + return _anchr1; +} + +void PhysicsJointLimit::setAnchr1(const Vec2& anchr) +{ + // NOTE: NOT SUPPORT +} + +Vec2 PhysicsJointLimit::getAnchr2() const +{ + return _anchr2; +} + +void PhysicsJointLimit::setAnchr2(const Vec2& anchr) +{ + // NOTE: NOT SUPPORT +} + +PhysicsJointDistance* PhysicsJointDistance::instantiate(PhysicsBody* a, + PhysicsBody* b, + const Vec2& anchr1, + const Vec2& anchr2) +{ + auto joint = new PhysicsJointDistance(); + + if (joint->init(a, b)) + { + joint->_anchr1 = anchr1; + joint->_anchr2 = anchr2; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointDistance::buildConstraints() +{ + do + { + b2DistanceJointDef def = b2DefaultDistanceJointDef(); + + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + + def.localAnchorA = phlp::tob2Vec2(_anchr1); + def.localAnchorB = phlp::tob2Vec2(_anchr2); + + // !IMPORTANT + def.length = _bodyB->local2World(_anchr1).getDistance(_bodyA->local2World(_anchr2)); + + // Set both min and max to the same value for a fixed distance joint + def.minLength = def.length; + def.maxLength = def.length; + + b2JointId joint = b2CreateDistanceJoint(_bodyA->getWorld()->getB2World(), &def); + + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointDistance::getDistance() const +{ + AX_PJOINT_CACHE_READ(_distance); + return b2DistanceJoint_GetLength(_b2Joints[0]); +} + +void PhysicsJointDistance::setDistance(float distance) +{ + AX_PJOINT_CACHE_WRITE(_distance, b2DistanceJoint_SetLength, distance); +} + +PhysicsJointSpring* PhysicsJointSpring::instantiate(PhysicsBody* a, + PhysicsBody* b, + const Vec2& anchr1, + const Vec2& anchr2, + float stiffness, + float damping) +{ + auto joint = new PhysicsJointSpring(); + + if (joint->init(a, b)) + { + joint->_anchr1 = anchr1; + joint->_anchr2 = anchr2; + joint->_stiffness = stiffness; + joint->_damping = damping; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointSpring::buildConstraints() +{ + do + { + b2DistanceJointDef def = b2DefaultDistanceJointDef(); + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + def.localAnchorA = phlp::tob2Vec2(_anchr1); + def.localAnchorB = phlp::tob2Vec2(_anchr2); + def.length = _bodyB->local2World(_anchr1).getDistance(_bodyA->local2World(_anchr2)); + def.enableSpring = true; + + // calculate effective mass + float m1 = _bodyA->getMass(); + float m2 = _bodyB->getMass(); + float mass = (m1 * m2) / (m1 + m2); + + // calculate hertz + def.hertz = sqrtf(_stiffness / mass) / (2.0f * std::numbers::pi_v); + + // calculate damping ratio + def.dampingRatio = _damping / (2.0f * sqrtf(_stiffness * mass)); + + auto joint = b2CreateDistanceJoint(_bodyA->getWorld()->getB2World(), &def); + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsJointSpring::getAnchr1() const +{ + AX_PJOINT_CACHE_READ(_anchr1); + return phlp::toVec2(b2Joint_GetLocalAnchorA(_b2Joints[0])); +} + +void PhysicsJointSpring::setAnchr1(const Vec2& anchr) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE2(_anchr1, cpDampedSpringSetAnchorA, anchr, phlp::vec22cpv(anchr)); +} + +Vec2 PhysicsJointSpring::getAnchr2() const +{ + AX_PJOINT_CACHE_READ(_anchr2); + return phlp::toVec2(b2Joint_GetLocalAnchorB(_b2Joints[0])); +} + +void PhysicsJointSpring::setAnchr2(const Vec2& anchr) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE2(_anchr2, cpDampedSpringSetAnchorB, anchr, phlp::vec22cpv(anchr)); +} + +float PhysicsJointSpring::getRestLength() const +{ + AX_PJOINT_CACHE_READ(_restLength); + return b2DistanceJoint_GetLength(_b2Joints[0]); +} + +void PhysicsJointSpring::setRestLength(float restLength) +{ + // FIXME: + AX_PJOINT_CACHE_WRITE(_restLength, b2DistanceJoint_SetLength, restLength); +} + +float PhysicsJointSpring::getStiffness() const +{ + AX_PJOINT_CACHE_READ(_stiffness); + return b2DistanceJoint_GetSpringHertz(_b2Joints[0]); +} + +void PhysicsJointSpring::setStiffness(float stiffness) +{ + AX_PJOINT_CACHE_WRITE(_stiffness, b2DistanceJoint_SetSpringHertz, stiffness); +} + +float PhysicsJointSpring::getDamping() const +{ + AX_PJOINT_CACHE_READ(_damping); + return b2DistanceJoint_GetSpringDampingRatio(_b2Joints[0]); +} + +void PhysicsJointSpring::setDamping(float damping) +{ + AX_PJOINT_CACHE_WRITE(_damping, b2DistanceJoint_SetSpringDampingRatio, damping); +} + +PhysicsJointGroove* PhysicsJointGroove::instantiate(PhysicsBody* a, + PhysicsBody* b, + const Vec2& grooveA, + const Vec2& grooveB, + const Vec2& anchr2) +{ + auto joint = new PhysicsJointGroove(); + + if (joint->init(a, b)) + { + joint->_grooveA = grooveA; + joint->_grooveB = grooveB; + joint->_anchr2 = anchr2; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointGroove::buildConstraints() +{ + do + { + auto world = _bodyA->getWorld()->getB2World(); + + b2PrismaticJointDef def = b2DefaultPrismaticJointDef(); + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + def.localAnchorA = phlp::tob2Vec2(_grooveA); + def.localAnchorB = phlp::tob2Vec2(_anchr2); + def.localAxisA = phlp::tob2Vec2(_grooveB) - phlp::tob2Vec2(_grooveA); + def.lowerTranslation = 0.0f; + def.upperTranslation = b2Distance(phlp::tob2Vec2(_grooveA), phlp::tob2Vec2(_grooveB)); + def.enableLimit = true; + + b2JointId joint = b2CreatePrismaticJoint(world, &def); + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +Vec2 PhysicsJointGroove::getGrooveA() const +{ + AX_PJOINT_CACHE_READ(_grooveA); + return phlp::toVec2(b2Joint_GetLocalAnchorA(_b2Joints.front())); +} + +void PhysicsJointGroove::setGrooveA(const Vec2& grooveA) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE2(_grooveA, cpGrooveJointSetGrooveA, grooveA, phlp::vec22cpv(grooveA)); +} + +Vec2 PhysicsJointGroove::getGrooveB() const +{ + AX_PJOINT_CACHE_READ(_grooveB); + + return _grooveB; + // return phlp::cpv2vec2(cpGrooveJointGetGrooveB(_b2Joints.front())); +} + +void PhysicsJointGroove::setGrooveB(const Vec2& grooveB) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE2(_grooveB, cpGrooveJointSetGrooveB, grooveB, phlp::vec22cpv(grooveB)); +} + +Vec2 PhysicsJointGroove::getAnchr2() const +{ + AX_PJOINT_CACHE_READ(_anchr2); + return phlp::toVec2(b2Joint_GetLocalAnchorB(_b2Joints.front())); +} + +void PhysicsJointGroove::setAnchr2(const Vec2& anchr2) +{ + // AX_PJOINT_CACHE_WRITE2(_anchr2, cpGrooveJointSetAnchorB, anchr2, phlp::vec22cpv(anchr2)); +} + +PhysicsJointRotarySpring* PhysicsJointRotarySpring::instantiate(PhysicsBody* a, + PhysicsBody* b, + float stiffness, + float damping) +{ + auto joint = new PhysicsJointRotarySpring(); + + if (joint->init(a, b)) + { + joint->_stiffness = stiffness; + joint->_damping = damping; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointRotarySpring::buildConstraints() +{ + do + { + auto world = _bodyA->getWorld()->getB2World(); + // Note: not 100% indentical to cpDampedRotarySpringNew + // auto joint = cpDampedRotarySpringNew(_bodyA->getCPBody(), _bodyB->getCPBody(), + // _bodyB->getRotation() - _bodyA->getRotation(), _stiffness, _damping); + b2MotorJointDef motorDef = b2DefaultMotorJointDef(); + motorDef.bodyIdA = _bodyA->getB2Body(); + motorDef.bodyIdB = _bodyB->getB2Body(); + motorDef.angularOffset = AX_DEGREES_TO_RADIANS(_bodyB->getRotation()) - + AX_DEGREES_TO_RADIANS(_bodyA->getRotation()); + motorDef.maxTorque = 10000.0f; + motorDef.correctionFactor = 1.0f; + auto offset = _bodyA->getPosition() - _bodyB->getPosition(); + motorDef.linearOffset = phlp::tob2Vec2(offset); + auto joint = b2CreateMotorJoint(world, &motorDef); + + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointRotarySpring::getRestAngle() const +{ + AX_PJOINT_CACHE_READ(_restAngle); + return b2RevoluteJoint_GetAngle(_b2Joints.front()); +} + +void PhysicsJointRotarySpring::setRestAngle(float restAngle) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE(_restAngle, b2RevoluteJoint_SetAngle, restAngle); +} + +float PhysicsJointRotarySpring::getStiffness() const +{ + AX_PJOINT_CACHE_READ(_stiffness); + return b2RevoluteJoint_GetSpringHertz(_b2Joints.front()); +} + +void PhysicsJointRotarySpring::setStiffness(float stiffness) +{ + AX_PJOINT_CACHE_WRITE(_stiffness, b2RevoluteJoint_SetSpringHertz, stiffness); +} + +float PhysicsJointRotarySpring::getDamping() const +{ + AX_PJOINT_CACHE_READ(_damping); + return b2RevoluteJoint_GetSpringDampingRatio(_b2Joints.front()); +} + +void PhysicsJointRotarySpring::setDamping(float damping) +{ + AX_PJOINT_CACHE_WRITE(_damping, b2RevoluteJoint_SetSpringDampingRatio, damping); +} + +PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::instantiate(PhysicsBody* a, PhysicsBody* b, float min, float max) +{ + auto joint = new PhysicsJointRotaryLimit(); + + if (joint->init(a, b)) + { + joint->_min = min; + joint->_max = max; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::instantiate(PhysicsBody* a, PhysicsBody* b) +{ + return instantiate(a, b, 0.0f, 0.0f); +} + +bool PhysicsJointRotaryLimit::buildConstraints() +{ + do + { + /*auto joint = cpRotaryLimitJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _min, _max);*/ + + // Note: Not 100% indentical to cpRotaryLimitJointNew + b2RevoluteJointDef def = b2DefaultRevoluteJointDef(); + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + + def.enableLimit = true; + def.lowerAngle = _min; // Set the lower angle limit + def.upperAngle = _max; // Set the upper angle limit + + auto joint = b2CreateRevoluteJoint(_bodyA->getWorld()->getB2World(), &def); // FIXME: + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointRotaryLimit::getMin() const +{ + AX_PJOINT_CACHE_READ(_min); + return b2RevoluteJoint_GetLowerLimit(_b2Joints.front()); +} + +void PhysicsJointRotaryLimit::setMin(float min) +{ + // AX_PJOINT_CACHE_WRITE(_min, cpRotaryLimitJointSetMin, min); + + _min = min; + b2RevoluteJoint_SetLimits(_b2Joints[0], min, _max); +} + +float PhysicsJointRotaryLimit::getMax() const +{ + AX_PJOINT_CACHE_READ(_max); + return b2RevoluteJoint_GetUpperLimit(_b2Joints.front()); +} + +void PhysicsJointRotaryLimit::setMax(float max) +{ + // AX_PJOINT_CACHE_WRITE(_max, cpRotaryLimitJointSetMax, max); + _max = max; + b2RevoluteJoint_SetLimits(_b2Joints[0], _min, max); +} + +PhysicsJointRatchet* PhysicsJointRatchet::instantiate(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet) +{ + auto joint = new PhysicsJointRatchet(); + + if (joint->init(a, b)) + { + joint->_phase = phase; + joint->_ratchet = ratchet; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointRatchet::buildConstraints() +{ + do + { + /*auto joint = + cpRatchetJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _phase, + phlp::cpfloat2float(_ratchet));*/ + + b2RevoluteJointDef def = b2DefaultRevoluteJointDef(); + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + def.referenceAngle = _phase; // Set the initial phase + def.enableLimit = true; + def.lowerAngle = 0.0f; // Set the lower angle limit (the ratchet step) + def.upperAngle = _ratchet; // Set the upper angle limit (the ratchet step) + def.enableMotor = true; + def.motorSpeed = 0.0f; // Initial motor speed + def.maxMotorTorque = 10.0f; // Set a high torque to simulate the ratchet + + auto joint = b2CreateRevoluteJoint(_bodyA->getWorld()->getB2World(), &def); // FIXME: + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointRatchet::getAngle() const +{ + AX_PJOINT_CACHE_READ(_angle); + return b2RevoluteJoint_GetAngle(_b2Joints.front()); +} + +void PhysicsJointRatchet::setAngle(float angle) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE(_angle, b2RevoluteJoint_SetAngle, angle); +} + +float PhysicsJointRatchet::getPhase() const +{ + AX_PJOINT_CACHE_READ(_phase); + // return phlp::cpfloat2float(cpRatchetJointGetPhase(_b2Joints.front())); + return _phase; +} + +void PhysicsJointRatchet::setPhase(float phase) +{ + // NOTE: NOT SUPPORT + // AX_PJOINT_CACHE_WRITE(_phase, cpRatchetJointSetPhase, phase); +} + +float PhysicsJointRatchet::getRatchet() const +{ + AX_PJOINT_CACHE_READ(_ratchet); + return b2RevoluteJoint_GetUpperLimit(_b2Joints.front()); +} + +void PhysicsJointRatchet::setRatchet(float ratchet) +{ + // AX_PJOINT_CACHE_WRITE(_ratchet, cpRatchetJointSetRatchet, ratchet); + b2RevoluteJoint_SetLimits(_b2Joints[0], 0, ratchet); +} + +PhysicsJointGear* PhysicsJointGear::instantiate(PhysicsBody* a, PhysicsBody* b, float phase, float ratio) +{ + auto joint = new PhysicsJointGear(); + + if (joint->init(a, b)) + { + joint->_phase = phase; + joint->_ratio = ratio; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointGear::buildConstraints() +{ + do + { + // auto joint = cpGearJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _phase, _ratio); + // gear and pulley joint removed (temporarily) in box2d-3.x, see https://box2d.org/documentation/md_migration.html + auto world = _bodyA->getWorld()->getB2World(); + auto bodyA = _bodyA->getB2Body(); + auto bodyB = _bodyB->getB2Body(); + + // bodyA, bodyB, phase, ratio + b2MotorJointDef motorDef = b2DefaultMotorJointDef(); + motorDef.bodyIdA = bodyA; + motorDef.bodyIdB = bodyB; + + b2Vec2 posA = b2Body_GetWorldCenterOfMass(bodyA); + b2Vec2 posB = b2Body_GetWorldCenterOfMass(bodyB); + motorDef.linearOffset = posB - posA; + + float angleA = b2Body_GetAngle(bodyA); + float angleB = b2Body_GetAngle(bodyB); + motorDef.angularOffset = _phase - (angleA + _ratio * angleB); + + motorDef.maxForce = 0.0f; + motorDef.maxTorque = 10000.0f; + motorDef.correctionFactor = 1.0f; + + b2JointId joint = b2CreateMotorJoint(world, &motorDef); + + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointGear::getPhase() const +{ + AX_PJOINT_CACHE_READ(_phase); + // return phlp::cpfloat2float(cpGearJointGetPhase(_b2Joints.front())); + return _phase; +} + +void PhysicsJointGear::setPhase(float phase) +{ + // AX_PJOINT_CACHE_WRITE(_phase, cpGearJointSetPhase, phase); +} + +float PhysicsJointGear::getRatio() const +{ + AX_PJOINT_CACHE_READ(_ratio); + // return phlp::cpfloat2float(cpGearJointGetRatio(_b2Joints.front())); + return _ratio; +} + +void PhysicsJointGear::setRatio(float ratio) +{ + // AX_PJOINT_CACHE_WRITE(_ratio, cpGearJointSetRatio, ratio); +} + +PhysicsJointMotor* PhysicsJointMotor::instantiate(PhysicsBody* a, PhysicsBody* b, float rate) +{ + auto joint = new PhysicsJointMotor(); + + if (joint->init(a, b)) + { + joint->_rate = rate; + + return joint; + } + + AX_SAFE_DELETE(joint); + return nullptr; +} + +bool PhysicsJointMotor::buildConstraints() +{ + do + { + /*auto joint = cpSimpleMotorNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _rate);*/ + + // Define the motor joint (simple motor equivalent in Box2D) + b2RevoluteJointDef def = b2DefaultRevoluteJointDef(); + def.bodyIdA = _bodyA->getB2Body(); + def.bodyIdB = _bodyB->getB2Body(); + + def.localAnchorA = b2Vec2_zero; // Set the local anchor points as required + def.localAnchorB = b2Vec2_zero; // Set the local anchor points as required + + def.referenceAngle = 0.0f; // Set the reference angle + def.enableMotor = true; + def.motorSpeed = _rate; // Set the motor speed (rate) + def.maxMotorTorque = 10000.0f; // Set the maximum torque the motor can apply + + auto joint = b2CreateRevoluteJoint(_bodyA->getWorld()->getB2World(), &def); // FIXME: + setRate(_rate); + AX_BREAK_IF(!b2Joint_IsValid(joint)); + _b2Joints.emplace_back(joint); + + return true; + } while (false); + + return false; +} + +float PhysicsJointMotor::getRate() const +{ + AX_PJOINT_CACHE_READ(_rate); + // return phlp::cpfloat2float(cpSimpleMotorGetRate(_b2Joints.front())); + return _rate; +} + +void PhysicsJointMotor::setRate(float rate) +{ + AX_PJOINT_CACHE_WRITE(_rate, b2RevoluteJoint_SetMotorSpeed, rate); + // b2RevoluteJoint_SetMotorSpeed(_b2Joints[0], _rate); +} + +} // namespace ax +#endif // AX_ENABLE_PHYSICS diff --git a/core/physics/PhysicsJoint.h b/axmol/physics/PhysicsJoint.h similarity index 83% rename from core/physics/PhysicsJoint.h rename to axmol/physics/PhysicsJoint.h index a31a29f63f19..7ff999480b0b 100644 --- a/core/physics/PhysicsJoint.h +++ b/axmol/physics/PhysicsJoint.h @@ -28,13 +28,13 @@ #include -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_PHYSICS) -# include "base/Object.h" -# include "math/Math.h" +# include "axmol/base/Object.h" +# include "axmol/math/Math.h" -struct cpConstraint; +# include "box2d/box2d.h" namespace ax { @@ -118,10 +118,12 @@ class AX_DLL PhysicsJoint void flushDelayTasks(); - /** Create constraints for this type joint */ - virtual bool createConstraints() { return false; } + void deatchFromBody(); - std::vector _cpConstraints; + /** Build constraints for this type joint */ + virtual bool buildConstraints() { return false; } + + std::vector _b2Joints; std::vector _delayTasks; PhysicsBody* _bodyA; PhysicsBody* _bodyB; @@ -156,13 +158,10 @@ class AX_DLL PhysicsJointFixed : public PhysicsJoint @param anchr It's the pivot position. @return A object pointer. */ - static PhysicsJointFixed* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr); - - virtual bool createConstraints() override; + static PhysicsJointFixed* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr); protected: - PhysicsJointFixed() {} - virtual ~PhysicsJointFixed() {} + bool buildConstraints() override; Vec2 _anchr; }; @@ -181,7 +180,7 @@ class AX_DLL PhysicsJointLimit : public PhysicsJoint @param anchr2 Anchr2 is the anchor point on body b. @return A object pointer. */ - static PhysicsJointLimit* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); + static PhysicsJointLimit* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); /** Create a limit joint. @@ -193,7 +192,7 @@ class AX_DLL PhysicsJointLimit : public PhysicsJoint @param max Define the allowed max distance of the anchor points. @return A object pointer. */ - static PhysicsJointLimit* construct(PhysicsBody* a, + static PhysicsJointLimit* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, @@ -222,11 +221,8 @@ class AX_DLL PhysicsJointLimit : public PhysicsJoint /** Set the max distance of the anchor points.*/ void setMax(float max); - virtual bool createConstraints() override; - protected: - PhysicsJointLimit() {} - virtual ~PhysicsJointLimit() {} + bool buildConstraints() override; Vec2 _anchr1; Vec2 _anchr2; @@ -247,7 +243,7 @@ class AX_DLL PhysicsJointPin : public PhysicsJoint @param pivot It's the pivot position. @return A object pointer. */ - static PhysicsJointPin* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot); + static PhysicsJointPin* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot); /** Create a pin joint. @@ -257,13 +253,10 @@ class AX_DLL PhysicsJointPin : public PhysicsJoint @param anchr2 Anchr2 is the anchor point on body b. @return A object pointer. */ - static PhysicsJointPin* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); - - virtual bool createConstraints() override; + static PhysicsJointPin* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); protected: - PhysicsJointPin() {} - virtual ~PhysicsJointPin() {} + bool buildConstraints() override; bool _useSpecificAnchr; Vec2 _anchr1; @@ -282,17 +275,15 @@ class AX_DLL PhysicsJointDistance : public PhysicsJoint @param anchr2 Anchr2 is the anchor point on body b. @return A object pointer. */ - static PhysicsJointDistance* construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); + static PhysicsJointDistance* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2); /** Get the distance of the anchor points.*/ float getDistance() const; /** Set the distance of the anchor points.*/ void setDistance(float distance); - virtual bool createConstraints() override; protected: - PhysicsJointDistance() {} - virtual ~PhysicsJointDistance() {} + bool buildConstraints() override; Vec2 _anchr1; Vec2 _anchr2; @@ -302,7 +293,7 @@ class AX_DLL PhysicsJointDistance : public PhysicsJoint class AX_DLL PhysicsJointSpring : public PhysicsJoint { public: - /** Create a fixed distance joint. + /** Create a Spring joint. @param a A is the body to connect. @param b B is the body to connect. @@ -312,7 +303,7 @@ class AX_DLL PhysicsJointSpring : public PhysicsJoint @param damping It's how soft to make the damping of the spring. @return A object pointer. */ - static PhysicsJointSpring* construct(PhysicsBody* a, + static PhysicsJointSpring* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2, @@ -349,11 +340,8 @@ class AX_DLL PhysicsJointSpring : public PhysicsJoint /** Set the spring soft constant.*/ void setDamping(float damping); - virtual bool createConstraints() override; - protected: - PhysicsJointSpring() {} - virtual ~PhysicsJointSpring() {} + bool buildConstraints() override; Vec2 _anchr1; Vec2 _anchr2; @@ -374,7 +362,7 @@ class AX_DLL PhysicsJointGroove : public PhysicsJoint @param anchr2 Anchr2 is the anchor point on body b. @return A object pointer. */ - static PhysicsJointGroove* construct(PhysicsBody* a, + static PhysicsJointGroove* instantiate(PhysicsBody* a, PhysicsBody* b, const Vec2& grooveA, const Vec2& grooveB, @@ -398,11 +386,8 @@ class AX_DLL PhysicsJointGroove : public PhysicsJoint /** Set the anchor point on body b.*/ void setAnchr2(const Vec2& anchr2); - virtual bool createConstraints() override; - protected: - PhysicsJointGroove() {} - virtual ~PhysicsJointGroove() {} + bool buildConstraints() override; Vec2 _grooveA; Vec2 _grooveB; @@ -421,7 +406,7 @@ class AX_DLL PhysicsJointRotarySpring : public PhysicsJoint @param damping It's how soft to make the damping of the spring. @return A object pointer. */ - static PhysicsJointRotarySpring* construct(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping); + static PhysicsJointRotarySpring* instantiate(PhysicsBody* a, PhysicsBody* b, float stiffness, float damping); /** Get the relative angle in radians from the body a to b.*/ float getRestAngle() const; @@ -441,11 +426,8 @@ class AX_DLL PhysicsJointRotarySpring : public PhysicsJoint /** Set the spring soft constant.*/ void setDamping(float damping); - virtual bool createConstraints() override; - protected: - PhysicsJointRotarySpring() {} - virtual ~PhysicsJointRotarySpring() {} + bool buildConstraints() override; float _stiffness; float _damping; @@ -463,7 +445,7 @@ class AX_DLL PhysicsJointRotaryLimit : public PhysicsJoint @param max It's max rotation limit in radians. @return A object pointer. */ - static PhysicsJointRotaryLimit* construct(PhysicsBody* a, PhysicsBody* b, float min, float max); + static PhysicsJointRotaryLimit* instantiate(PhysicsBody* a, PhysicsBody* b, float min, float max); /** Create a limit rotary joint. @@ -471,7 +453,7 @@ class AX_DLL PhysicsJointRotaryLimit : public PhysicsJoint @param b B is the body to connect. @return A object pointer. */ - static PhysicsJointRotaryLimit* construct(PhysicsBody* a, PhysicsBody* b); + static PhysicsJointRotaryLimit* instantiate(PhysicsBody* a, PhysicsBody* b); /** Get the min rotation limit.*/ float getMin() const; @@ -485,11 +467,8 @@ class AX_DLL PhysicsJointRotaryLimit : public PhysicsJoint /** Set the max rotation limit.*/ void setMax(float max); - virtual bool createConstraints() override; - protected: - PhysicsJointRotaryLimit() {} - virtual ~PhysicsJointRotaryLimit() {} + bool buildConstraints() override; float _min; float _max; @@ -507,7 +486,7 @@ class AX_DLL PhysicsJointRatchet : public PhysicsJoint @param ratchet Ratchet is the distance between "clicks". @return A object pointer. */ - static PhysicsJointRatchet* construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet); + static PhysicsJointRatchet* instantiate(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet); /** Get the ratchet angle.*/ float getAngle() const; @@ -526,11 +505,9 @@ class AX_DLL PhysicsJointRatchet : public PhysicsJoint /** Set the distance between "clicks".*/ void setRatchet(float ratchet); - virtual bool createConstraints() override; protected: - PhysicsJointRatchet() {} - virtual ~PhysicsJointRatchet() {} + bool buildConstraints() override; float _phase; float _ratchet; @@ -548,7 +525,7 @@ class AX_DLL PhysicsJointGear : public PhysicsJoint @param ratio Ratio is always measured in absolute terms. @return A object pointer. */ - static PhysicsJointGear* construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratio); + static PhysicsJointGear* instantiate(PhysicsBody* a, PhysicsBody* b, float phase, float ratio); /** Get the angular offset of the two bodies.*/ float getPhase() const; @@ -562,11 +539,8 @@ class AX_DLL PhysicsJointGear : public PhysicsJoint /** Set the ratio.*/ void setRatio(float ratchet); - virtual bool createConstraints() override; - protected: - PhysicsJointGear() {} - virtual ~PhysicsJointGear() {} + bool buildConstraints() override; float _phase; float _ratio; @@ -583,18 +557,16 @@ class AX_DLL PhysicsJointMotor : public PhysicsJoint @param rate Rate is the desired relative angular velocity. @return A object pointer. */ - static PhysicsJointMotor* construct(PhysicsBody* a, PhysicsBody* b, float rate); + static PhysicsJointMotor* instantiate(PhysicsBody* a, PhysicsBody* b, float rate); /** Get the relative angular velocity.*/ float getRate() const; /** Set the relative angular velocity.*/ void setRate(float rate); - virtual bool createConstraints() override; protected: - PhysicsJointMotor() {} - virtual ~PhysicsJointMotor() {} + bool buildConstraints() override; float _rate; }; @@ -602,6 +574,6 @@ class AX_DLL PhysicsJointMotor : public PhysicsJoint /** @} */ /** @} */ -} +} // namespace ax #endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/PhysicsWorld.cpp b/axmol/physics/PhysicsWorld.cpp similarity index 52% rename from core/physics/PhysicsWorld.cpp rename to axmol/physics/PhysicsWorld.cpp index 85389f1ad7e9..b7c529dde72b 100644 --- a/core/physics/PhysicsWorld.cpp +++ b/axmol/physics/PhysicsWorld.cpp @@ -24,27 +24,27 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics/PhysicsWorld.h" +#include "axmol/physics/PhysicsWorld.h" #if defined(AX_ENABLE_PHYSICS) # include # include -# include "chipmunk/chipmunk_private.h" -# include "physics/PhysicsBody.h" -# include "physics/PhysicsShape.h" -# include "physics/PhysicsContact.h" -# include "physics/PhysicsJoint.h" -# include "physics/PhysicsHelper.h" +# include "axmol/physics/PhysicsBody.h" +# include "axmol/physics/PhysicsCollider.h" +# include "axmol/physics/PhysicsContact.h" +# include "axmol/physics/PhysicsJoint.h" +# include "axmol/physics/PhysicsHelper.h" -# include "2d/DrawNode.h" -# include "2d/Scene.h" -# include "base/Director.h" -# include "base/EventDispatcher.h" -# include "base/EventCustom.h" +# include "axmol/2d/DrawNode.h" +# include "axmol/2d/Scene.h" +# include "axmol/base/Director.h" +# include "axmol/base/EventDispatcher.h" +# include "axmol/base/EventCustom.h" namespace ax { -const float PHYSICS_INFINITY = FLT_MAX; +// box2d not support FLT_MAX as infinity, oterwise will trigger NAN in world step, so we use a large value instead +const float PHYSICS_INFINITY = 10e6; extern const char* PHYSICSCONTACT_EVENT_NAME; const int PhysicsWorld::DEBUGDRAW_NONE = 0x00; @@ -57,307 +57,176 @@ const float _debugDrawThickness = 0.5f; // thickness of the DebugDraw lines, ci namespace { -typedef struct RayCastCallbackInfo +struct RayCastCallbackInfo { PhysicsWorld* world; PhysicsRayCastCallbackFunc func; Vec2 p1; Vec2 p2; void* data; -} RayCastCallbackInfo; +}; -typedef struct RectQueryCallbackInfo +struct RectQueryCallbackInfo { PhysicsWorld* world; PhysicsQueryRectCallbackFunc func; void* data; -} RectQueryCallbackInfo; +}; -typedef struct PointQueryCallbackInfo +struct PointQueryCallbackInfo { PhysicsWorld* world; PhysicsQueryPointCallbackFunc func; + b2Vec2 p; void* data; -} PointQueryCallbackInfo; -} // namespace - -class PhysicsWorldCallback -{ -public: - static cpBool collisionBeginCallbackFunc(cpArbiter* arb, struct cpSpace* space, PhysicsWorld* world); - static cpBool collisionPreSolveCallbackFunc(cpArbiter* arb, cpSpace* space, PhysicsWorld* world); - static void collisionPostSolveCallbackFunc(cpArbiter* arb, cpSpace* space, PhysicsWorld* world); - static void collisionSeparateCallbackFunc(cpArbiter* arb, cpSpace* space, PhysicsWorld* world); - static void rayCastCallbackFunc(cpShape* shape, - cpVect point, - cpVect normal, - cpFloat alpha, - RayCastCallbackInfo* info); - static void queryRectCallbackFunc(cpShape* shape, RectQueryCallbackInfo* info); - static void queryPointFunc(cpShape* shape, - cpVect point, - cpFloat distance, - cpVect gradient, - PointQueryCallbackInfo* info); - static void getShapesAtPointFunc(cpShape* shape, - cpVect point, - cpFloat distance, - cpVect gradient, - Vector* arr); - -public: - static bool continues; }; -bool PhysicsWorldCallback::continues = true; - -cpBool PhysicsWorldCallback::collisionBeginCallbackFunc(cpArbiter* arb, struct cpSpace* /*space*/, PhysicsWorld* world) -{ - CP_ARBITER_GET_SHAPES(arb, a, b); - - PhysicsShape* shapeA = static_cast(cpShapeGetUserData(a)); - PhysicsShape* shapeB = static_cast(cpShapeGetUserData(b)); - AX_ASSERT(shapeA != nullptr && shapeB != nullptr); - - auto contact = PhysicsContact::construct(shapeA, shapeB); - cpArbiterSetUserData(arb, contact); - contact->_contactInfo = arb; - - return world->collisionBeginCallback(*contact); -} - -cpBool PhysicsWorldCallback::collisionPreSolveCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) +struct ShapeQueryCallbackInfo { - return world->collisionPreSolveCallback(*static_cast(cpArbiterGetUserData(arb))); -} + Vector& colliders; + b2Vec2 p; +}; +} // namespace -void PhysicsWorldCallback::collisionPostSolveCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) +struct PhysicsWorldCallback { - world->collisionPostSolveCallback(*static_cast(cpArbiterGetUserData(arb))); -} +# if 0 + static cpBool collisionBeginCallbackFunc(cpArbiter* arb, + struct cpSpace* /*space*/, + PhysicsWorld* world) + { + CP_ARBITER_GET_SHAPES(arb, a, b); -void PhysicsWorldCallback::collisionSeparateCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) -{ - PhysicsContact* contact = static_cast(cpArbiterGetUserData(arb)); + PhysicsCollider* shapeA = static_cast(cpShapeGetUserData(a)); + PhysicsCollider* shapeB = static_cast(cpShapeGetUserData(b)); + AX_ASSERT(shapeA != nullptr && shapeB != nullptr); - world->collisionSeparateCallback(*contact); + auto contact = PhysicsContact::construct(shapeA, shapeB); + cpArbiterSetUserData(arb, contact); + contact->_contactInfo = arb; - delete contact; -} + return world->collisionBeginCallback(*contact); + } -void PhysicsWorldCallback::rayCastCallbackFunc(cpShape* shape, - cpVect point, - cpVect normal, - cpFloat alpha, - RayCastCallbackInfo* info) -{ - if (!PhysicsWorldCallback::continues) + static cpBool collisionPreSolveCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) { - return; + return world->collisionPreSolveCallback(*static_cast(cpArbiterGetUserData(arb))); } - PhysicsShape* physicsShape = static_cast(cpShapeGetUserData(shape)); - AX_ASSERT(physicsShape != nullptr); - - PhysicsRayCastInfo callbackInfo = { - physicsShape, - info->p1, - info->p2, - PhysicsHelper::cpv2vec2(point), - PhysicsHelper::cpv2vec2(normal), - static_cast(alpha), - }; - - PhysicsWorldCallback::continues = info->func(*info->world, callbackInfo, info->data); -} - -void PhysicsWorldCallback::queryRectCallbackFunc(cpShape* shape, RectQueryCallbackInfo* info) -{ - PhysicsShape* physicsShape = static_cast(cpShapeGetUserData(shape)); - AX_ASSERT(physicsShape != nullptr); - - if (!PhysicsWorldCallback::continues) + static void collisionPostSolveCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) { - return; + world->collisionPostSolveCallback(*static_cast(cpArbiterGetUserData(arb))); } - PhysicsWorldCallback::continues = info->func(*info->world, *physicsShape, info->data); -} - -void PhysicsWorldCallback::getShapesAtPointFunc(cpShape* shape, - cpVect /*point*/, - cpFloat /*distance*/, - cpVect /*gradient*/, - Vector* arr) -{ - PhysicsShape* physicsShape = static_cast(cpShapeGetUserData(shape)); - AX_ASSERT(physicsShape != nullptr); - arr->pushBack(physicsShape); -} - -void PhysicsWorldCallback::queryPointFunc(cpShape* shape, - cpVect /*point*/, - cpFloat /*distance*/, - cpVect /*gradient*/, - PointQueryCallbackInfo* info) -{ - PhysicsShape* physicsShape = static_cast(cpShapeGetUserData(shape)); - AX_ASSERT(physicsShape != nullptr); - PhysicsWorldCallback::continues = info->func(*info->world, *physicsShape, info->data); -} - -static inline cpSpaceDebugColor RGBAColor(float r, float g, float b, float a) -{ - cpSpaceDebugColor color = {r, g, b, a}; - return color; -} - -static inline cpSpaceDebugColor LAColor(float l, float a) -{ - cpSpaceDebugColor color = {l, l, l, a}; - return color; -} - -static void DrawCircle(cpVect p, - cpFloat /*a*/, - cpFloat r, - cpSpaceDebugColor outline, - cpSpaceDebugColor fill, - cpDataPointer data) -{ - const Color4F fillColor(fill.r, fill.g, fill.b, fill.a); - const Color4F outlineColor(outline.r, outline.g, outline.b, outline.a); - DrawNode* drawNode = static_cast(data); - float radius = PhysicsHelper::cpfloat2float(r); - Vec2 centre = PhysicsHelper::cpv2vec2(p); + static void collisionSeparateCallbackFunc(cpArbiter* arb, cpSpace* /*space*/, PhysicsWorld* world) + { + PhysicsContact* contact = static_cast(cpArbiterGetUserData(arb)); - static const int CIRCLE_SEG_NUM = 12; - Vec2 seg[CIRCLE_SEG_NUM] = {}; + world->collisionSeparateCallback(*contact); - for (int i = 0; i < CIRCLE_SEG_NUM; ++i) - { - float angle = (float)i * M_PI / (float)CIRCLE_SEG_NUM * 2.0f; - Vec2 d(radius * cosf(angle), radius * sinf(angle)); - seg[i] = centre + d; + delete contact; } - drawNode->drawPolygon(seg, CIRCLE_SEG_NUM, fillColor, _debugDrawThickness, outlineColor); -} +# endif -static void DrawFatSegment(cpVect a, - cpVect b, - cpFloat r, - cpSpaceDebugColor outline, - cpSpaceDebugColor /*fill*/, - cpDataPointer data) -{ - const Color4F outlineColor(outline.r, outline.g, outline.b, outline.a); - DrawNode* drawNode = static_cast(data); - drawNode->drawSegment(PhysicsHelper::cpv2vec2(a), PhysicsHelper::cpv2vec2(b), - PhysicsHelper::cpfloat2float(r == 0 ? _debugDrawThickness : r), outlineColor); -} + /// Called for each shape found in the query. You control how the ray cast + /// proceeds by returning a float: + /// return -1: ignore this shape and continue + /// return 0: terminate the ray cast + /// return fraction: clip the ray to this point + /// return 1: don't clip the ray and continue + /// @param shapeId the shape hit by the ray + /// @param point the point of initial intersection + /// @param normal the normal vector at the point of intersection + /// @param fraction the fraction along the ray at the point of intersection + /// @param context the user context + /// @return -1 to filter, 0 to terminate, fraction to clip the ray for closest hit, 1 to continue + static float rayCastCallbackFunc(b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context) + { + if (!continues) + return fraction; -static void DrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color, cpDataPointer data) -{ - DrawFatSegment(a, b, 0.0, color, color, data); -} + auto info = static_cast(context); -static void DrawPolygon(int count, - const cpVect* verts, - cpFloat /*r*/, - cpSpaceDebugColor outline, - cpSpaceDebugColor fill, - cpDataPointer data) -{ - const Color4F fillColor(fill.r, fill.g, fill.b, fill.a); - const Color4F outlineColor(outline.r, outline.g, outline.b, outline.a); - DrawNode* drawNode = static_cast(data); - int num = count; - Vec2* seg = new Vec2[num]; - for (int i = 0; i < num; ++i) - seg[i] = PhysicsHelper::cpv2vec2(verts[i]); + PhysicsCollider* collider = static_cast(b2Shape_GetUserData(shapeId)); + AX_ASSERT(collider != nullptr); - drawNode->drawPolygon(seg, num, fillColor, _debugDrawThickness, outlineColor); + PhysicsRayCastInfo callbackInfo = {collider, info->p1, info->p2, phlp::toVec2(point), phlp::toVec2(normal), + fraction}; - delete[] seg; -} + continues = info->func(*info->world, callbackInfo, info->data); -static void DrawDot(cpFloat /*size*/, cpVect pos, cpSpaceDebugColor color, cpDataPointer data) -{ - const Color4F dotColor(color.r, color.g, color.b, color.a); - DrawNode* drawNode = static_cast(data); - drawNode->drawDot(PhysicsHelper::cpv2vec2(pos), _debugDrawThickness, dotColor); -} + return fraction; + } -static cpSpaceDebugColor ColorForShape(cpShape* shape, cpDataPointer /*data*/) -{ - if (cpShapeGetSensor(shape)) + static bool queryRectCallbackFunc(b2ShapeId shape, void* context) { - return LAColor(1.0f, 0.3f); + PhysicsCollider* collider = static_cast(b2Shape_GetUserData(shape)); + AX_ASSERT(collider != nullptr); + + auto info = static_cast(context); + return info->func(*info->world, *collider, info->data); } - else + + static bool queryPointCallbackFunc(b2ShapeId shape, void* context) { - cpBody* body = cpShapeGetBody(shape); + PhysicsCollider* collider = static_cast(b2Shape_GetUserData(shape)); + AX_ASSERT(collider != nullptr); - if (cpBodyIsSleeping(body)) - { - return LAColor(0.2f, 0.3f); - } - else if (body->sleeping.idleTime > shape->space->sleepTimeThreshold) - { - return LAColor(0.66f, 0.3f); - } - else - { + bool continues = true; - float intensity = (cpBodyGetType(body) == CP_BODY_TYPE_STATIC ? 0.15f : 0.75f); - return RGBAColor(intensity, 0.0f, 0.0f, 0.3f); + auto info = static_cast(context); + if (b2Shape_TestPoint(shape, info->p)) + { + b2Vec2 position = b2Body_GetPosition(collider->getBody()->getB2Body()); + if (b2Distance(info->p, position) <= 1e-6) + { + continues = info->func(*info->world, *collider, info->data); + } } + return continues; } -} -void PhysicsWorld::debugDraw() -{ - if (!_debugDraw) + static bool queryShapeCallbackFunc(b2ShapeId shape, void* context) { - return; - } + PhysicsCollider* collider = static_cast(b2Shape_GetUserData(shape)); + AX_ASSERT(collider != nullptr); - if (!_debugDraw->getParent()) - { - Director::getInstance()->getRunningScene()->addChild(_debugDraw); + auto info = static_cast(context); + if (b2Shape_TestPoint(shape, info->p)) + { + info->colliders.pushBack(collider); + } + return true; } - cpSpaceDebugDrawOptions drawOptions = { - DrawCircle, - DrawSegment, - DrawFatSegment, - DrawPolygon, - DrawDot, - - (cpSpaceDebugDrawFlags)(_debugDrawMask), - - {1.0f, 0.0f, 0.0f, 1.0f}, - ColorForShape, - {0.0f, 0.75f, 0.0f, 1.0f}, - {0.0f, 0.0f, 1.0f, 1.0f}, - _debugDraw, - }; - if (_debugDraw) +# if 0 + static void getShapesAtPointFunc(cpShape* shape, + cpVect /*point*/, + cpFloat /*distance*/, + cpVect /*gradient*/, + Vector* arr) { - _debugDraw->clear(); - cpSpaceDebugDraw(_cpSpace, &drawOptions); + PhysicsCollider* physicsShape = static_cast(cpShapeGetUserData(shape)); + AX_ASSERT(physicsShape != nullptr); + arr->pushBack(physicsShape); } -} + +# endif + + static bool continues; +}; + +bool PhysicsWorldCallback::continues = true; bool PhysicsWorld::collisionBeginCallback(PhysicsContact& contact) { bool ret = true; - PhysicsShape* shapeA = contact.getShapeA(); - PhysicsShape* shapeB = contact.getShapeB(); - PhysicsBody* bodyA = shapeA->getBody(); - PhysicsBody* bodyB = shapeB->getBody(); - auto&& jointsA = bodyA->getJoints(); + PhysicsCollider* shapeA = contact.getShapeA(); + PhysicsCollider* shapeB = contact.getShapeB(); + PhysicsBody* bodyA = shapeA->getBody(); + PhysicsBody* bodyB = shapeB->getBody(); + auto&& jointsA = bodyA->getJoints(); // check the joint is collision enable or not for (PhysicsJoint* joint : jointsA) @@ -459,10 +328,21 @@ void PhysicsWorld::rayCast(PhysicsRayCastCallbackFunc func, const Vec2& point1, } RayCastCallbackInfo info = {this, func, point1, point2, data}; + auto translation = point2 - point1; PhysicsWorldCallback::continues = true; - cpSpaceSegmentQuery(_cpSpace, PhysicsHelper::vec22cpv(point1), PhysicsHelper::vec22cpv(point2), 0.0f, - CP_SHAPE_FILTER_ALL, (cpSpaceSegmentQueryFunc)PhysicsWorldCallback::rayCastCallbackFunc, - &info); + b2World_CastRay(_b2World, phlp::tob2Vec2(point1), phlp::tob2Vec2(translation), b2DefaultQueryFilter(), + PhysicsWorldCallback::rayCastCallbackFunc, &info); + + #if 0 + auto result = b2World_CastRayClosest(_b2World, phlp::tob2Vec2(point1), phlp::tob2Vec2(translation), b2DefaultQueryFilter()); + if (b2Shape_IsValid(result.shapeId)) + { + auto collider = static_cast(b2Shape_GetUserData(result.shapeId)); + PhysicsRayCastInfo rayCastInfo{collider, info.p1, info.p2, phlp::toVec2(result.point), phlp::toVec2(result.normal), + result.fraction}; + func(*this, rayCastInfo, data); + } + #endif } } @@ -478,9 +358,9 @@ void PhysicsWorld::queryRect(PhysicsQueryRectCallbackFunc func, const Rect& rect } RectQueryCallbackInfo info = {this, func, data}; - PhysicsWorldCallback::continues = true; - cpSpaceBBQuery(_cpSpace, PhysicsHelper::rect2cpbb(rect), CP_SHAPE_FILTER_ALL, - (cpSpaceBBQueryFunc)PhysicsWorldCallback::queryRectCallbackFunc, &info); + auto filter = b2DefaultQueryFilter(); + b2World_OverlapAABB(_b2World, phlp::tob2AABB(rect), b2DefaultQueryFilter(), + PhysicsWorldCallback::queryRectCallbackFunc, &info); } } @@ -494,50 +374,81 @@ void PhysicsWorld::queryPoint(PhysicsQueryPointCallbackFunc func, const Vec2& po { updateBodies(); } - PointQueryCallbackInfo info = {this, func, data}; - PhysicsWorldCallback::continues = true; - cpSpacePointQuery(_cpSpace, PhysicsHelper::vec22cpv(point), 0, CP_SHAPE_FILTER_ALL, - (cpSpacePointQueryFunc)PhysicsWorldCallback::queryPointFunc, &info); + PointQueryCallbackInfo info = {this, func, phlp::tob2Vec2(point), data}; + + b2AABB aabb; + aabb.lowerBound = info.p; + aabb.upperBound = info.p; + + auto filter = b2DefaultQueryFilter(); + b2World_OverlapAABB(_b2World, aabb, b2DefaultQueryFilter(), PhysicsWorldCallback::queryRectCallbackFunc, &info); } } -Vector PhysicsWorld::getShapes(const Vec2& point) const +Vector PhysicsWorld::getShapes(const Vec2& point) const { - Vector arr; - cpSpacePointQuery(_cpSpace, PhysicsHelper::vec22cpv(point), 0, CP_SHAPE_FILTER_ALL, - (cpSpacePointQueryFunc)PhysicsWorldCallback::getShapesAtPointFunc, &arr); + Vector arr; + + ShapeQueryCallbackInfo info = {arr, phlp::tob2Vec2(point)}; + + b2AABB aabb; + aabb.lowerBound = info.p; + aabb.upperBound = info.p; + + b2World_OverlapAABB(_b2World, aabb, b2DefaultQueryFilter(), PhysicsWorldCallback::queryShapeCallbackFunc, &info); return arr; } -PhysicsShape* PhysicsWorld::getShape(const Vec2& point) const +PhysicsCollider* PhysicsWorld::getShape(const Vec2& point) const { - cpShape* shape = - cpSpacePointQueryNearest(_cpSpace, PhysicsHelper::vec22cpv(point), 0, CP_SHAPE_FILTER_ALL, nullptr); - return shape == nullptr ? nullptr : static_cast(cpShapeGetUserData(shape)); + // TODO: use b2World_OverlapCircle + // cpShape* shape = + // cpSpacePointQueryNearest(_cpSpace, phlpvec22cpv(point), 0, CP_SHAPE_FILTER_ALL, nullptr); + // return shape == nullptr ? nullptr : static_cast(cpShapeGetUserData(shape)); + return nullptr; } bool PhysicsWorld::init() { do { -# if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - _cpSpace = cpSpaceNew(); -# else - _cpSpace = cpHastySpaceNew(); - cpHastySpaceSetThreads(_cpSpace, 0); -# endif - AX_BREAK_IF(_cpSpace == nullptr); + /* create the physics world + @see: https://box2d.org/documentation/md_faq.html#autotoc_md135 + How do I convert pixels to meters? + Suppose you have a sprite for a character that is 100x100 pixels. You decide to use a scaling factor that is + 0.01. This will make the character physics box 1m x 1m. So go make a physics box that is 1x1. Now suppose the + character starts out at pixel coordinate (345,679). So position the physics box at (3.45,6.79). Now simulate + the physics world. Suppose the character physics box moves to (2.31,4.98), so move your character sprite to + pixel coordinates (231,498). + + Now the only tricky part is choosing a scaling factor. This really depends on your game. You should try to + get your moving objects in the range 0.1 - 10 meters, with 1 meter being the sweet spot. + + This https://github.com/erincatto/box2d-raylib/blob/main/main.c shows how to convert meters to pixels. + */ + b2SetLengthUnitsPerMeter(_PTMRatio); - cpSpaceSetGravity(_cpSpace, PhysicsHelper::vec22cpv(_gravity)); + auto def = b2DefaultWorldDef(); + // Realistic gravity is achieved by multiplying gravity by the length unit. + def.gravity = phlp::tob2Vec2(_gravity * _PTMRatio); - cpCollisionHandler* handler = cpSpaceAddDefaultCollisionHandler(_cpSpace); - handler->userData = this; - handler->beginFunc = (cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc; - handler->preSolveFunc = (cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc; - handler->postSolveFunc = (cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc; - handler->separateFunc = (cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc; + _b2World = b2CreateWorld(&def); + + AX_BREAK_IF(!b2World_IsValid(_b2World)); + + // Do we want to let bodies sleep? + b2World_EnableSleeping(_b2World, true); + b2World_EnableContinuous(_b2World, true); + + // TODO: + // cpCollisionHandler* handler = cpSpaceAddDefaultCollisionHandler(_cpSpace); + // handler->userData = this; + // handler->beginFunc = (cpCollisionBeginFunc)PhysicsWorldCallback::collisionBeginCallbackFunc; + // handler->preSolveFunc = (cpCollisionPreSolveFunc)PhysicsWorldCallback::collisionPreSolveCallbackFunc; + // handler->postSolveFunc = (cpCollisionPostSolveFunc)PhysicsWorldCallback::collisionPostSolveCallbackFunc; + // handler->separateFunc = (cpCollisionSeparateFunc)PhysicsWorldCallback::collisionSeparateCallbackFunc; return true; } while (false); @@ -549,40 +460,12 @@ void PhysicsWorld::addBody(PhysicsBody* body) { AXASSERT(body != nullptr, "the body can not be nullptr"); - if (body->getWorld() == this) - { - return; - } - - if (body->getWorld() != nullptr) - { - body->removeFromWorld(); - } - addBodyOrDelay(body); _bodies.pushBack(body); body->_world = this; body->setFixedUpdate(_fixedRate > 0); } -void PhysicsWorld::doAddBody(PhysicsBody* body) -{ - if (body->isEnabled()) - { - // add body to space - if (!cpSpaceContainsBody(_cpSpace, body->_cpBody)) - { - cpSpaceAddBody(_cpSpace, body->_cpBody); - } - - // add shapes to space - for (auto&& shape : body->getShapes()) - { - addShape(dynamic_cast(shape)); - } - } -} - void PhysicsWorld::addBodyOrDelay(PhysicsBody* body) { auto removeBodyIter = _delayRemoveBodies.find(body); @@ -600,7 +483,7 @@ void PhysicsWorld::addBodyOrDelay(PhysicsBody* body) void PhysicsWorld::updateBodies() { - if (cpSpaceIsLocked(_cpSpace)) + if (_isWorldLocked) { return; } @@ -611,7 +494,7 @@ void PhysicsWorld::updateBodies() _delayAddBodies.clear(); for (auto&& body : addCopy) { - doAddBody(body); + // doAddBody(body); } auto removeCopy = _delayRemoveBodies; @@ -663,7 +546,7 @@ void PhysicsWorld::removeBodyOrDelay(PhysicsBody* body) return; } - if (cpSpaceIsLocked(_cpSpace)) + if (_isWorldLocked) { if (_delayRemoveBodies.getIndex(body) == AX_INVALID_INDEX) { @@ -698,7 +581,7 @@ void PhysicsWorld::removeJoint(PhysicsJoint* joint, bool destroy) removedFromDelayAdd = true; } - if (cpSpaceIsLocked(_cpSpace)) + if (_isWorldLocked) { if (removedFromDelayAdd) return; @@ -716,7 +599,7 @@ void PhysicsWorld::removeJoint(PhysicsJoint* joint, bool destroy) void PhysicsWorld::updateJoints() { - if (cpSpaceIsLocked(_cpSpace)) + if (_isWorldLocked) { return; } @@ -747,20 +630,6 @@ void PhysicsWorld::updateJoints() } } -void PhysicsWorld::removeShape(PhysicsShape* shape) -{ - if (shape) - { - for (auto&& cps : shape->_cpShapes) - { - if (cpSpaceContainsShape(_cpSpace, cps)) - { - cpSpaceRemoveShape(_cpSpace, cps); - } - } - } -} - void PhysicsWorld::addJoint(PhysicsJoint* joint) { if (joint) @@ -791,39 +660,33 @@ void PhysicsWorld::removeAllJoints(bool destroy) } } -void PhysicsWorld::addShape(PhysicsShape* physicsShape) -{ - if (physicsShape) - { - for (auto&& shape : physicsShape->_cpShapes) - { - cpSpaceAddShape(_cpSpace, shape); - } - } -} - void PhysicsWorld::doRemoveBody(PhysicsBody* body) { AXASSERT(body != nullptr, "the body can not be nullptr"); // remove shapes - for (auto&& shape : body->getShapes()) - { - removeShape(shape); - } + // for (auto&& shape : body->getShapes()) + //{ + // removeShape(shape); + //} + + // TODO: body->removeSelf // remove body - if (cpSpaceContainsBody(_cpSpace, body->_cpBody)) - { - cpSpaceRemoveBody(_cpSpace, body->_cpBody); - } + // if (cpSpaceContainsBody(_cpSpace, body->_cpBody)) + // { + // cpSpaceRemoveBody(_cpSpace, body->_cpBody); + // } + + body->deatchFromWOrld(); } void PhysicsWorld::doRemoveJoint(PhysicsJoint* joint) { - for (auto&& constraint : joint->_cpConstraints) + // TODO: joint->removeSelf + for (auto&& constraint : joint->_b2Joints) { - cpSpaceRemoveConstraint(_cpSpace, constraint); + // cpSpaceRemoveConstraint(_cpSpace, constraint); } _joints.remove(joint); joint->_world = nullptr; @@ -855,26 +718,6 @@ void PhysicsWorld::removeAllBodies() _bodies.clear(); } -void PhysicsWorld::setDebugDrawMask(int mask) -{ - if (mask == DEBUGDRAW_NONE) - { - if (_debugDraw) - { - _debugDraw->removeFromParent(); - AX_SAFE_RELEASE_NULL(_debugDraw); - } - } - else if (!_debugDraw) - { - _debugDraw = DrawNode::create(); - _debugDraw->setIsolated(true); - _debugDraw->retain(); - } - - _debugDrawMask = mask; -} - const Vector& PhysicsWorld::getAllBodies() const { return _bodies; @@ -896,13 +739,14 @@ PhysicsBody* PhysicsWorld::getBody(int tag) const void PhysicsWorld::setGravity(const Vec2& gravity) { _gravity = gravity; - cpSpaceSetGravity(_cpSpace, PhysicsHelper::vec22cpv(gravity)); + b2World_SetGravity(_b2World, phlp::tob2Vec2(_gravity * _PTMRatio)); } void PhysicsWorld::setSlopBias(float slop, float bias) { - cpSpaceSetCollisionSlop(_cpSpace, slop); - cpSpaceSetCollisionBias(_cpSpace, bias); + // NOTE: NOT SUPPORT + // cpSpaceSetCollisionSlop(_cpSpace, slop); + // cpSpaceSetCollisionBias(_cpSpace, bias); } void PhysicsWorld::setSubsteps(int steps) @@ -959,11 +803,7 @@ void PhysicsWorld::update(float delta, bool userCall /* = false*/) if (userCall) { -# if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceStep(_cpSpace, delta); -# else - cpHastySpaceStep(_cpSpace, delta); -# endif + b2World_Step(_b2World, delta, 4); } else { @@ -981,11 +821,7 @@ void PhysicsWorld::update(float delta, bool userCall /* = false*/) } _scene->fixedUpdate(dt); -# if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceStep(_cpSpace, dt); -# else - cpHastySpaceStep(_cpSpace, dt); -# endif + b2World_Step(_b2World, dt, 1); } } else @@ -993,23 +829,14 @@ void PhysicsWorld::update(float delta, bool userCall /* = false*/) if (++_updateRateCount >= _updateRate) { const float dt = _updateTime * _speed / _substeps; - for (int i = 0; i < _substeps; ++i) - { -# if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceStep(_cpSpace, dt); -# else - cpHastySpaceStep(_cpSpace, dt); -# endif - } + b2World_Step(_b2World, 1 / 60.f, _substeps); _updateRateCount = 0; _updateTime = 0.0f; } - } - } - if (_debugDrawMask != DEBUGDRAW_NONE) - { - debugDraw(); + _updateRateCount = 0; + _updateTime = 0.0f; + } } // Update physics position, should loop as the same sequence as node tree. @@ -1035,19 +862,18 @@ PhysicsWorld* PhysicsWorld::construct(Scene* scene) } PhysicsWorld::PhysicsWorld() - : _gravity(Vec2(0.0f, -98.0f)) + : _gravity(Vec2(0.0f, -9.8f)) + , _PTMRatio(10.0f) , _speed(1.0f) , _updateRate(1) , _updateRateCount(0) , _updateTime(0.0f) , _substeps(1) , _fixedRate(0) - , _cpSpace(nullptr) + , _b2World(b2_nullWorldId) , _updateBodyTransform(false) , _scene(nullptr) , _autoStep(true) - , _debugDraw(nullptr) - , _debugDrawMask(DEBUGDRAW_NONE) , _eventDispatcher(nullptr) {} @@ -1055,15 +881,10 @@ PhysicsWorld::~PhysicsWorld() { removeAllJoints(true); removeAllBodies(); - if (_cpSpace) + if (b2World_IsValid(_b2World)) { -# if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceFree(_cpSpace); -# else - cpHastySpaceFree(_cpSpace); -# endif + b2DestroyWorld(_b2World); } - AX_SAFE_RELEASE_NULL(_debugDraw); } void PhysicsWorld::beforeSimulation(Node* node, @@ -1113,6 +934,6 @@ void PhysicsWorld::setPreUpdateCallback(const std::function& callback) _preUpdateCallback = callback; } -} +} // namespace ax #endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/PhysicsWorld.h b/axmol/physics/PhysicsWorld.h similarity index 88% rename from core/physics/PhysicsWorld.h rename to axmol/physics/PhysicsWorld.h index 2018141ae84a..7cf16270c359 100644 --- a/core/physics/PhysicsWorld.h +++ b/axmol/physics/PhysicsWorld.h @@ -26,13 +26,13 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_PHYSICS) # include -# include "base/Vector.h" -# include "math/Math.h" -# include "physics/PhysicsBody.h" +# include "axmol/base/Vector.h" +# include "axmol/math/Math.h" +# include "axmol/physics/PhysicsBody.h" struct cpSpace; @@ -41,7 +41,7 @@ namespace ax class PhysicsBody; class PhysicsJoint; -class PhysicsShape; +class PhysicsCollider; class PhysicsContact; class Director; @@ -56,7 +56,7 @@ class PhysicsWorld; typedef struct PhysicsRayCastInfo { - PhysicsShape* shape; + PhysicsCollider* shape; Vec2 start; Vec2 end; ///< in lua, it's name is "ended" Vec2 contact; @@ -65,7 +65,7 @@ typedef struct PhysicsRayCastInfo // FIXME: correct thing to do is use `cpFloat` instead of float. // but in order to do so, we should include "chipmunk_types.h" // in Chipmunk v7.0, chipmunk_types includes all the mac types that - // conflicts with axmol Vec2, Point,... etc types. And all the CocosStudio + // conflicts with cocos2d Vec2, Point,... etc types. And all the CocosStudio // lib will need to use the `ax::` namespace prefix. And it is easier to do this // than change all the cocosstudio library (and also users code) float fraction; @@ -83,7 +83,7 @@ typedef struct PhysicsRayCastInfo * @return true to continue, false to terminate */ typedef std::function PhysicsRayCastCallbackFunc; -typedef std::function PhysicsQueryRectCallbackFunc; +typedef std::function PhysicsQueryRectCallbackFunc; typedef PhysicsQueryRectCallbackFunc PhysicsQueryPointCallbackFunc; /** @@ -108,6 +108,8 @@ class AX_DLL PhysicsWorld static const int DEBUGDRAW_ALL; ///< draw all public: + b2WorldId getB2World() const { return _b2World; } + /** * Adds a joint to this physics world. * @@ -195,21 +197,21 @@ class AX_DLL PhysicsWorld /** * Get physics shapes that contains the point. * - * All shapes contains the point will be pushed in a Vector object. + * All shapes contains the point will be pushed in a Vector object. * @attention The point must lie inside a shape. * @param point A Vec2 object contains the position of the point. - * @return A Vector object contains all found PhysicsShape pointer. + * @return A Vector object contains all found PhysicsCollider pointer. */ - Vector getShapes(const Vec2& point) const; + Vector getShapes(const Vec2& point) const; /** * Get the nearest physics shape that contains the point. * * Query this physics world at point and return the closest shape. * @param point A Vec2 object contains the position of the point. - * @return A PhysicsShape object pointer or nullptr if no shapes were found + * @return A PhysicsCollider object pointer or nullptr if no shapes were found */ - PhysicsShape* getShape(const Vec2& point) const; + PhysicsCollider* getShape(const Vec2& point) const; /** * Get all the bodies that in this physics world. @@ -251,8 +253,11 @@ class AX_DLL PhysicsWorld /** * set the slop and bias value of this physics world. * - * @param slop Amount of encouraged penetration between colliding shapes. Used to reduce oscillating contacts and keep the collision cache warm. - * @param bias Determines how fast overlapping shapes are pushed apart. Expressed as a fraction of the error remaining after each second. Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each frame at 60Hz. + * @param slop Amount of encouraged penetration between colliding shapes. Used to reduce oscillating contacts and + * keep the collision cache warm. + * @param bias Determines how fast overlapping shapes are pushed apart. Expressed as a fraction of the error + * remaining after each second. Defaults to pow(1.0 - 0.1, 60.0) meaning that Chipmunk fixes 10% of overlap each + * frame at 60Hz. */ void setSlopBias(float slop, float bias); @@ -341,14 +346,6 @@ class AX_DLL PhysicsWorld /** get the number of substeps */ int getFixedUpdateRate() const { return _fixedRate; } - /** - * Set the debug draw mask of this physics world. - * - * This physics world will draw shapes and joints by DrawNode according to mask. - * @param mask Mask has four value:DEBUGDRAW_NONE, DEBUGDRAW_SHAPE, DEBUGDRAW_JOINT, DEBUGDRAW_CONTACT and - * DEBUGDRAW_ALL, default is DEBUGDRAW_NONE - */ - void setDebugDrawMask(int mask); /** * set the callback which invoked before update of each object in physics world. @@ -360,20 +357,6 @@ class AX_DLL PhysicsWorld */ void setPostUpdateCallback(const std::function& callback); - /** - * Get the debug draw mask. - * - * @return An integer number. - */ - int getDebugDrawMask() const { return _debugDrawMask; } - - /** - * Get the debug draw node - * - * @return Pointer to draw node, which may be nullptr - */ - DrawNode* getDebugDraw() const { return _debugDraw; } - /** * To control the step of physics. * @@ -406,18 +389,14 @@ class AX_DLL PhysicsWorld bool init(); virtual void addBody(PhysicsBody* body); - virtual void addShape(PhysicsShape* shape); - virtual void removeShape(PhysicsShape* shape); - virtual void update(float delta, bool userCall = false); - virtual void debugDraw(); + virtual void update(float delta, bool userCall = false); virtual bool collisionBeginCallback(PhysicsContact& contact); virtual bool collisionPreSolveCallback(PhysicsContact& contact); virtual void collisionPostSolveCallback(PhysicsContact& contact); virtual void collisionSeparateCallback(PhysicsContact& contact); - virtual void doAddBody(PhysicsBody* body); virtual void doRemoveBody(PhysicsBody* body); virtual void doRemoveJoint(PhysicsJoint* joint); virtual void addBodyOrDelay(PhysicsBody* body); @@ -427,13 +406,15 @@ class AX_DLL PhysicsWorld protected: Vec2 _gravity; + float _PTMRatio; float _speed; int _updateRate; int _updateRateCount; float _updateTime; int _substeps; int _fixedRate; - cpSpace* _cpSpace; + b2WorldId _b2World; + bool _isWorldLocked = false; bool _updateBodyTransform; Vector _bodies; @@ -441,8 +422,6 @@ class AX_DLL PhysicsWorld Scene* _scene; bool _autoStep; - DrawNode* _debugDraw; - int _debugDrawMask; EventDispatcher* _eventDispatcher; @@ -470,7 +449,7 @@ class AX_DLL PhysicsWorld friend class Scene; friend class Director; friend class PhysicsBody; - friend class PhysicsShape; + friend class PhysicsCollider; friend class PhysicsJoint; friend class PhysicsWorldCallback; friend class PhysicsDebugDraw; @@ -481,6 +460,6 @@ extern const float AX_DLL PHYSICS_INFINITY; /** @} */ /** @} */ -} +} // namespace ax #endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics3d/CMakeLists.txt b/axmol/physics3d/CMakeLists.txt similarity index 100% rename from core/physics3d/CMakeLists.txt rename to axmol/physics3d/CMakeLists.txt diff --git a/core/physics3d/Physics3D.cpp b/axmol/physics3d/Physics3D.cpp similarity index 98% rename from core/physics3d/Physics3D.cpp rename to axmol/physics3d/Physics3D.cpp index 871a6a78eb7e..206b71e29fbb 100644 --- a/core/physics3d/Physics3D.cpp +++ b/axmol/physics3d/Physics3D.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3D.h b/axmol/physics3d/Physics3D.h similarity index 84% rename from core/physics3d/Physics3D.h rename to axmol/physics3d/Physics3D.h index 61c37c485022..41f69100f17c 100644 --- a/core/physics3d/Physics3D.h +++ b/axmol/physics3d/Physics3D.h @@ -25,18 +25,18 @@ #pragma once -#include "base/Config.h" -#include "math/Math.h" +#include "axmol/base/Config.h" +#include "axmol/math/Math.h" #if defined(AX_ENABLE_3D_PHYSICS) -# include "physics3d/Physics3DShape.h" -# include "physics3d/PhysicsMeshRenderer.h" -# include "physics3d/Physics3DWorld.h" -# include "physics3d/Physics3DDebugDrawer.h" -# include "physics3d/Physics3DObject.h" -# include "physics3d/Physics3DComponent.h" -# include "physics3d/Physics3DConstraint.h" +# include "axmol/physics3d/Physics3DShape.h" +# include "axmol/physics3d/PhysicsMeshRenderer.h" +# include "axmol/physics3d/Physics3DWorld.h" +# include "axmol/physics3d/Physics3DDebugDrawer.h" +# include "axmol/physics3d/Physics3DObject.h" +# include "axmol/physics3d/Physics3DComponent.h" +# include "axmol/physics3d/Physics3DConstraint.h" namespace ax { diff --git a/core/physics3d/Physics3DComponent.cpp b/axmol/physics3d/Physics3DComponent.cpp similarity index 98% rename from core/physics3d/Physics3DComponent.cpp rename to axmol/physics3d/Physics3DComponent.cpp index eec30b50b786..668b3996709f 100644 --- a/core/physics3d/Physics3DComponent.cpp +++ b/axmol/physics3d/Physics3DComponent.cpp @@ -24,9 +24,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" -#include "2d/Node.h" -#include "2d/Scene.h" +#include "axmol/physics3d/Physics3D.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Scene.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DComponent.h b/axmol/physics3d/Physics3DComponent.h similarity index 95% rename from core/physics3d/Physics3DComponent.h rename to axmol/physics3d/Physics3DComponent.h index 42f1396779e7..863b8bd09d3b 100644 --- a/core/physics3d/Physics3DComponent.h +++ b/axmol/physics3d/Physics3DComponent.h @@ -26,10 +26,10 @@ #pragma once -#include "base/Config.h" -#include "math/Math.h" +#include "axmol/base/Config.h" +#include "axmol/math/Math.h" -#include "2d/Component.h" +#include "axmol/2d/Component.h" #if defined(AX_ENABLE_3D_PHYSICS) @@ -63,7 +63,7 @@ class AX_DLL Physics3DComponent : public ax::Component CREATE_FUNC(Physics3DComponent); virtual ~Physics3DComponent(); - virtual bool init() override; + bool init() override; /** * create Physics3DComponent @@ -94,10 +94,10 @@ class AX_DLL Physics3DComponent : public ax::Component /** * set it enable or not */ - virtual void setEnabled(bool b) override; + void setEnabled(bool b) override; - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** * add this component to physics world, called by scene diff --git a/core/physics3d/Physics3DConstraint.cpp b/axmol/physics3d/Physics3DConstraint.cpp similarity index 99% rename from core/physics3d/Physics3DConstraint.cpp rename to axmol/physics3d/Physics3DConstraint.cpp index 31886b0c9163..550e20115af4 100644 --- a/core/physics3d/Physics3DConstraint.cpp +++ b/axmol/physics3d/Physics3DConstraint.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DConstraint.h b/axmol/physics3d/Physics3DConstraint.h similarity index 99% rename from core/physics3d/Physics3DConstraint.h rename to axmol/physics3d/Physics3DConstraint.h index 8c46d85562e1..54fcd775ee0d 100644 --- a/core/physics3d/Physics3DConstraint.h +++ b/axmol/physics3d/Physics3DConstraint.h @@ -26,9 +26,9 @@ #pragma once -#include "math/Math.h" -#include "base/Object.h" -#include "base/Config.h" +#include "axmol/math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DDebugDrawer.cpp b/axmol/physics3d/Physics3DDebugDrawer.cpp similarity index 86% rename from core/physics3d/Physics3DDebugDrawer.cpp rename to axmol/physics3d/Physics3DDebugDrawer.cpp index ef3551354035..6c6f46abc11f 100644 --- a/core/physics3d/Physics3DDebugDrawer.cpp +++ b/axmol/physics3d/Physics3DDebugDrawer.cpp @@ -23,17 +23,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #include // offsetof -#include "base/Types.h" -#include "base/Configuration.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "renderer/Renderer.h" -#include "renderer/RenderState.h" -#include "renderer/Shaders.h" -#include "renderer/backend/Buffer.h" +#include "axmol/base/Types.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/Buffer.h" #if defined(AX_ENABLE_3D_PHYSICS) @@ -45,10 +45,10 @@ void Physics3DDebugDrawer::drawLine(const btVector3& from, const btVector3& to, Vec3 col = convertbtVector3ToVec3(color); V3F_C4F a, b; - a.vertices = convertbtVector3ToVec3(from); - a.colors = Color4F(col.x, col.y, col.z, 1.0f); - b.vertices = convertbtVector3ToVec3(to); - b.colors = Color4F(col.x, col.y, col.z, 1.0f); + a.position = convertbtVector3ToVec3(from); + a.color = Color(col.x, col.y, col.z, 1.0f); + b.position = convertbtVector3ToVec3(to); + b.color = Color(col.x, col.y, col.z, 1.0f); _buffer.emplace_back(a); _buffer.emplace_back(b); @@ -90,7 +90,7 @@ void Physics3DDebugDrawer::draw(Renderer* renderer) _programState->setUniform(_locMVP, transform.m, sizeof(transform.m)); _customCommand.init(0, Mat4::IDENTITY, 0); - auto& blend = _customCommand.getPipelineDescriptor().blendDescriptor; + auto& blend = _customCommand.getPipelineDesc().blendDesc; blend.blendEnabled = true; blend.sourceAlphaBlendFactor = blend.sourceRGBBlendFactor = _blendFunc.src; blend.destinationAlphaBlendFactor = blend.destinationRGBBlendFactor = _blendFunc.dst; @@ -128,13 +128,13 @@ Physics3DDebugDrawer::~Physics3DDebugDrawer() void Physics3DDebugDrawer::init() { AX_SAFE_RELEASE_NULL(_programState); - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_COLOR); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_COLOR); + _programState = new rhi::ProgramState(program); _locMVP = _programState->getUniformLocation("u_MVPMatrix"); _buffer.reserve(512); - _customCommand.getPipelineDescriptor().programState = _programState; + _customCommand.getPipelineDesc().programState = _programState; _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::LINE); _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setBeforeCallback(AX_CALLBACK_0(Physics3DDebugDrawer::onBeforeDraw, this)); diff --git a/core/physics3d/Physics3DDebugDrawer.h b/axmol/physics3d/Physics3DDebugDrawer.h similarity index 79% rename from core/physics3d/Physics3DDebugDrawer.h rename to axmol/physics3d/Physics3DDebugDrawer.h index 9fad48aa94d6..d34107eb824f 100644 --- a/core/physics3d/Physics3DDebugDrawer.h +++ b/axmol/physics3d/Physics3DDebugDrawer.h @@ -26,13 +26,12 @@ #pragma once -#include "math/Math.h" -#include "base/Object.h" -#include "base/Types.h" -#include "base/Config.h" -#include "renderer/CustomCommand.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Types.h" +#include "axmol/math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Config.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/rhi/ProgramState.h" #if defined(AX_ENABLE_3D_PHYSICS) @@ -58,16 +57,16 @@ class Physics3DDebugDrawer : public btIDebugDraw void draw(ax::Renderer* renderer); // override function - virtual void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override; + void drawLine(const btVector3& from, const btVector3& to, const btVector3& color) override; virtual void drawContactPoint(const btVector3& PointOnB, const btVector3& normalOnB, btScalar distance, int lifeTime, const btVector3& color) override; - virtual void reportErrorWarning(const char* warningString) override; - virtual void draw3dText(const btVector3& location, const char* textString) override; - virtual void setDebugMode(int debugMode) override; - virtual int getDebugMode() const override; + void reportErrorWarning(const char* warningString) override; + void draw3dText(const btVector3& location, const char* textString) override; + void setDebugMode(int debugMode) override; + int getDebugMode() const override; void clear(); @@ -78,11 +77,11 @@ class Physics3DDebugDrawer : public btIDebugDraw protected: std::vector _buffer; - ax::backend::UniformLocation _locMVP; + ax::rhi::UniformLocation _locMVP; ax::BlendFunc _blendFunc = BlendFunc::DISABLE; ax::CustomCommand _customCommand; - ax::backend::ProgramState* _programState = nullptr; + ax::rhi::ProgramState* _programState = nullptr; bool _dirty = true; int _debugMode = DBG_DrawWireframe | DBG_DrawConstraints | DBG_DrawConstraintLimits; diff --git a/core/physics3d/Physics3DObject.cpp b/axmol/physics3d/Physics3DObject.cpp similarity index 99% rename from core/physics3d/Physics3DObject.cpp rename to axmol/physics3d/Physics3DObject.cpp index 195529d80d3b..182be5a300b8 100644 --- a/core/physics3d/Physics3DObject.cpp +++ b/axmol/physics3d/Physics3DObject.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" -#include "base/UTF8.h" +#include "axmol/physics3d/Physics3D.h" +#include "axmol/base/text_utils.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DObject.h b/axmol/physics3d/Physics3DObject.h similarity index 98% rename from core/physics3d/Physics3DObject.h rename to axmol/physics3d/Physics3DObject.h index cac3a2c2ec74..83eacc559f18 100644 --- a/core/physics3d/Physics3DObject.h +++ b/axmol/physics3d/Physics3DObject.h @@ -26,9 +26,9 @@ #pragma once -#include "math/Math.h" -#include "base/Object.h" -#include "base/Config.h" +#include "axmol/math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/base/Config.h" #include @@ -319,7 +319,7 @@ class AX_DLL Physics3DRigidBody : public Physics3DObject bool isKinematic() const; /** override. */ - virtual ax::Mat4 getWorldTransform() const override; + ax::Mat4 getWorldTransform() const override; /** Get constraint by index. */ Physics3DConstraint* getConstraint(unsigned int idx) const; diff --git a/core/physics3d/Physics3DShape.cpp b/axmol/physics3d/Physics3DShape.cpp similarity index 99% rename from core/physics3d/Physics3DShape.cpp rename to axmol/physics3d/Physics3DShape.cpp index 595b3dee3e69..9938fe3d6849 100644 --- a/core/physics3d/Physics3DShape.cpp +++ b/axmol/physics3d/Physics3DShape.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DShape.h b/axmol/physics3d/Physics3DShape.h similarity index 98% rename from core/physics3d/Physics3DShape.h rename to axmol/physics3d/Physics3DShape.h index d38577466016..807fd91dbaba 100644 --- a/core/physics3d/Physics3DShape.h +++ b/axmol/physics3d/Physics3DShape.h @@ -26,9 +26,9 @@ #pragma once -#include "base/Object.h" -#include "base/Config.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/base/Config.h" +#include "axmol/math/Math.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DWorld.cpp b/axmol/physics3d/Physics3DWorld.cpp similarity index 99% rename from core/physics3d/Physics3DWorld.cpp rename to axmol/physics3d/Physics3DWorld.cpp index 6a1a3240d9e9..0296f89f81bb 100644 --- a/core/physics3d/Physics3DWorld.cpp +++ b/axmol/physics3d/Physics3DWorld.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" -#include "renderer/Renderer.h" +#include "axmol/physics3d/Physics3D.h" +#include "axmol/renderer/Renderer.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/Physics3DWorld.h b/axmol/physics3d/Physics3DWorld.h similarity index 98% rename from core/physics3d/Physics3DWorld.h rename to axmol/physics3d/Physics3DWorld.h index ff8c66db0dfa..cdaf9e142cbe 100644 --- a/core/physics3d/Physics3DWorld.h +++ b/axmol/physics3d/Physics3DWorld.h @@ -26,9 +26,9 @@ #pragma once -#include "math/Math.h" -#include "base/Object.h" -#include "base/Config.h" +#include "axmol/math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/PhysicsMeshRenderer.cpp b/axmol/physics3d/PhysicsMeshRenderer.cpp similarity index 99% rename from core/physics3d/PhysicsMeshRenderer.cpp rename to axmol/physics3d/PhysicsMeshRenderer.cpp index 664eeef11bc4..356867dd036d 100644 --- a/core/physics3d/PhysicsMeshRenderer.cpp +++ b/axmol/physics3d/PhysicsMeshRenderer.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/physics3d/PhysicsMeshRenderer.h b/axmol/physics3d/PhysicsMeshRenderer.h similarity index 95% rename from core/physics3d/PhysicsMeshRenderer.h rename to axmol/physics3d/PhysicsMeshRenderer.h index 24835d8d3725..43524d58e3f9 100644 --- a/core/physics3d/PhysicsMeshRenderer.h +++ b/axmol/physics3d/PhysicsMeshRenderer.h @@ -26,10 +26,10 @@ #pragma once -#include "base/Config.h" -#include "3d/MeshRenderer.h" -#include "physics3d/Physics3DObject.h" -#include "physics3d/Physics3DComponent.h" +#include "axmol/base/Config.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/physics3d/Physics3DObject.h" +#include "axmol/physics3d/Physics3DComponent.h" #if defined(AX_ENABLE_3D_PHYSICS) diff --git a/core/platform/Application.h b/axmol/platform/Application.h similarity index 79% rename from core/platform/Application.h rename to axmol/platform/Application.h index d937db0e150a..407529f57bb0 100644 --- a/core/platform/Application.h +++ b/axmol/platform/Application.h @@ -28,20 +28,20 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_MAC -# include "platform/mac/Application-mac.h" +# include "axmol/platform/mac/Application-mac.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_IOS -# include "platform/ios/Application-ios.h" +# include "axmol/platform/ios/Application-ios.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID -# include "platform/android/Application-android.h" +# include "axmol/platform/android/Application-android.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 -# include "platform/win32/Application-win32.h" +# include "axmol/platform/win32/Application-win32.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WINRT -# include "platform/winrt/Application-winrt.h" +# include "axmol/platform/winrt/Application-winrt.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_LINUX -# include "platform/linux/Application-linux.h" +# include "axmol/platform/linux/Application-linux.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "platform/wasm/Application-wasm.h" +# include "axmol/platform/wasm/Application-wasm.h" #endif diff --git a/core/platform/ApplicationBase.cpp b/axmol/platform/ApplicationBase.cpp similarity index 95% rename from core/platform/ApplicationBase.cpp rename to axmol/platform/ApplicationBase.cpp index 378b98ab124c..090444c41b54 100644 --- a/core/platform/ApplicationBase.cpp +++ b/axmol/platform/ApplicationBase.cpp @@ -25,8 +25,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ApplicationBase.h" -#include "base/Director.h" +#include "axmol/platform/ApplicationBase.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/platform/ApplicationBase.h b/axmol/platform/ApplicationBase.h similarity index 93% rename from core/platform/ApplicationBase.h rename to axmol/platform/ApplicationBase.h index 48161a42d610..98f003d05118 100644 --- a/core/platform/ApplicationBase.h +++ b/axmol/platform/ApplicationBase.h @@ -27,9 +27,9 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" -#include "base/AutoreleasePool.h" -#include "base/Types.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/AutoreleasePool.h" +#include "axmol/base/Types.h" namespace ax { @@ -102,15 +102,7 @@ class AX_DLL ApplicationBase * RenderView::setGfxContextAttrs(gfxContextAttrs); * } */ -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) virtual void initGLContextAttrs() {} -#endif - virtual void initGfxContextAttrs() - { -#ifndef AX_CORE_PROFILE - initGLContextAttrs(); -#endif - } + virtual void initGfxContextAttrs() {} /** @brief Get current language config. diff --git a/core/platform/CMakeLists.txt b/axmol/platform/CMakeLists.txt similarity index 97% rename from core/platform/CMakeLists.txt rename to axmol/platform/CMakeLists.txt index 1b5be5139796..ff86fa1b56a2 100644 --- a/core/platform/CMakeLists.txt +++ b/axmol/platform/CMakeLists.txt @@ -23,7 +23,7 @@ # ****************************************************************************/ if(ANDROID) - # refer to target: core/platform/android/CMakeLists.txt + # refer to target: axmol/platform/android/CMakeLists.txt set(_AX_PLATFORM_SPECIFIC_SRC platform/android/Application-android.cpp platform/android/Common-android.cpp @@ -99,7 +99,7 @@ elseif(APPLE) platform/ios/InputView-ios.mm ) - if(AX_USE_GL) + if(AX_RENDER_API STREQUAL "gl") set(_AX_PLATFORM_SPECIFIC_HEADER ${_AX_PLATFORM_SPECIFIC_HEADER} platform/ios/ES3Renderer-ios.h @@ -140,7 +140,7 @@ elseif(LINUX) elseif(EMSCRIPTEN) include_directories( PUBLIC "${_AX_ROOT}/3rdparty/angle/_x/include" - PUBLIC "${_AX_ROOT}/core" + PUBLIC "${_AX_ROOT}/axmol" ) set(_AX_PLATFORM_SPECIFIC_HEADER platform/wasm/Application-wasm.h diff --git a/core/platform/Common.h b/axmol/platform/Common.h similarity index 97% rename from core/platform/Common.h rename to axmol/platform/Common.h index 4582979ad984..a67ea4cebeee 100644 --- a/core/platform/Common.h +++ b/axmol/platform/Common.h @@ -27,7 +27,7 @@ THE SOFTWARE. #pragma once /// @cond DO_NOT_SHOW -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/platform/Device.h b/axmol/platform/Device.h similarity index 98% rename from core/platform/Device.h rename to axmol/platform/Device.h index 0a7a150f217c..bffb2410fb4d 100644 --- a/core/platform/Device.h +++ b/axmol/platform/Device.h @@ -27,9 +27,9 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" -#include "base/Macros.h" -#include "base/Data.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Data.h" namespace ax { diff --git a/core/platform/FileStream.cpp b/axmol/platform/FileStream.cpp similarity index 98% rename from core/platform/FileStream.cpp rename to axmol/platform/FileStream.cpp index a81c72e85b34..91917f4d0526 100644 --- a/core/platform/FileStream.cpp +++ b/axmol/platform/FileStream.cpp @@ -1,9 +1,9 @@ // Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md) -#include "platform/FileStream.h" +#include "axmol/platform/FileStream.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID -# include "platform/android/FileUtils-android.h" -# include "base/ZipUtils.h" +# include "axmol/platform/android/FileUtils-android.h" +# include "axmol/base/ZipUtils.h" #endif #include diff --git a/core/platform/FileStream.h b/axmol/platform/FileStream.h similarity index 93% rename from core/platform/FileStream.h rename to axmol/platform/FileStream.h index 32f3f164d76d..38bda8e96367 100644 --- a/core/platform/FileStream.h +++ b/axmol/platform/FileStream.h @@ -1,12 +1,12 @@ // Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md) #pragma once -#include "platform/IFileStream.h" -#include "platform/PlatformConfig.h" +#include "axmol/platform/IFileStream.h" +#include "axmol/platform/PlatformConfig.h" #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID # include diff --git a/core/platform/FileUtils.cpp b/axmol/platform/FileUtils.cpp similarity index 82% rename from core/platform/FileUtils.cpp rename to axmol/platform/FileUtils.cpp index 83c61f0bd47e..c46abe572db5 100644 --- a/core/platform/FileUtils.cpp +++ b/axmol/platform/FileUtils.cpp @@ -25,17 +25,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include #include #include -#include "base/Data.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "platform/SAXParser.h" -#include "platform/FileStream.h" +#include "axmol/base/Data.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/platform/SAXParser.h" +#include "axmol/platform/FileStream.h" #ifdef MINIZIP_FROM_SYSTEM # include @@ -51,7 +51,7 @@ THE SOFTWARE. #include "pugixml/pugixml.hpp" -#include "base/filesystem.h" +#include "axmol/base/filesystem.h" #if defined(_WIN32) inline stdfs::path toFspath(const std::string_view& pathSV) @@ -487,32 +487,12 @@ bool FileUtils::writeStringToFile(std::string_view dataStr, std::string_view ful { return FileUtils::writeBinaryToFile(dataStr.data(), dataStr.size(), fullPath); } -#ifndef AX_CORE_PROFILE -void FileUtils::writeStringToFile(std::string dataStr, - std::string_view fullPath, - std::function callback) const -{ - performOperationOffthread( - [path = std::string{fullPath}](std::string_view dataStrIn) -> bool { - return FileUtils::getInstance()->writeStringToFile(dataStrIn, path); - }, - std::move(callback), std::move(dataStr)); -} -#endif + bool FileUtils::writeDataToFile(const Data& data, std::string_view fullPath) const { return FileUtils::writeBinaryToFile(data.getBytes(), data.getSize(), fullPath); } -#ifndef AX_CORE_PROFILE -void FileUtils::writeDataToFile(Data data, std::string_view fullPath, std::function callback) const -{ - performOperationOffthread( - [path = std::string{fullPath}](const Data& dataIn) -> bool { - return FileUtils::getInstance()->writeDataToFile(dataIn, path); - }, - std::move(callback), std::move(data)); -} -#endif + bool FileUtils::writeBinaryToFile(const void* data, size_t dataSize, std::string_view fullPath) { AXASSERT(!fullPath.empty() && dataSize > 0, "Invalid parameters."); @@ -549,32 +529,14 @@ std::string FileUtils::getStringFromFile(std::string_view filename) const getContents(filename, &s); return s; } -#ifndef AX_CORE_PROFILE -void FileUtils::getStringFromFile(std::string_view path, std::function callback) const -{ - // Get the full path on the main thread, to avoid the issue that FileUtil's is not - // thread safe, and accessing the fullPath cache and searching the search paths is not thread safe - auto fullPath = fullPathForFilename(path); - performOperationOffthread( - [path = std::string{fullPath}]() -> std::string { return FileUtils::getInstance()->getStringFromFile(path); }, - std::move(callback)); -} -#endif + Data FileUtils::getDataFromFile(std::string_view filename) const { Data d; getContents(filename, &d); return d; } -#ifndef AX_CORE_PROFILE -void FileUtils::getDataFromFile(std::string_view filename, std::function callback) const -{ - auto fullPath = fullPathForFilename(filename); - performOperationOffthread( - [path = std::string{fullPath}]() -> Data { return FileUtils::getInstance()->getDataFromFile(path); }, - std::move(callback)); -} -#endif + FileUtils::Status FileUtils::getContents(std::string_view filename, ResizableBuffer* buffer) const { if (filename.empty()) @@ -610,28 +572,7 @@ FileUtils::Status FileUtils::getContents(std::string_view filename, ResizableBuf return Status::OK; } -#ifndef AX_CORE_PROFILE -void FileUtils::writeValueMapToFile(ValueMap dict, std::string_view fullPath, std::function callback) const -{ - - performOperationOffthread( - [path = std::string{fullPath}](const ValueMap& dictIn) -> bool { - return FileUtils::getInstance()->writeValueMapToFile(dictIn, path); - }, - std::move(callback), std::move(dict)); -} -void FileUtils::writeValueVectorToFile(ValueVector vecData, - std::string_view fullPath, - std::function callback) const -{ - performOperationOffthread( - [path = std::string{fullPath}](const ValueVector& vecDataIn) -> bool { - return FileUtils::getInstance()->writeValueVectorToFile(vecDataIn, path); - }, - std::move(callback), std::move(vecData)); -} -#endif std::string FileUtils::getPathForFilename(std::string_view filename, std::string_view searchPath) const { auto file = filename; @@ -907,15 +848,7 @@ bool FileUtils::isFileExist(std::string_view filename) const return !fullpath.empty(); } } -#ifndef AX_CORE_PROFILE -void FileUtils::isFileExist(std::string_view filename, std::function callback) const -{ - auto fullPath = fullPathForFilename(filename); - performOperationOffthread( - [path = std::string{fullPath}]() -> bool { return FileUtils::getInstance()->isFileExist(path); }, - std::move(callback)); -} -#endif + bool FileUtils::isAbsolutePath(std::string_view path) const { return isAbsolutePathInternal(path); @@ -952,89 +885,6 @@ bool FileUtils::isDirectoryExist(std::string_view dirPath) const } } -#ifndef AX_CORE_PROFILE - -void FileUtils::isDirectoryExist(std::string_view fullPath, std::function callback) const -{ - AXASSERT(isAbsolutePath(fullPath), "Async isDirectoryExist only accepts absolute file paths"); - performOperationOffthread( - [path = std::string{fullPath}]() -> bool { return FileUtils::getInstance()->isDirectoryExist(path); }, - std::move(callback)); -} - -void FileUtils::createDirectory(std::string_view dirPath, std::function callback) const -{ - performOperationOffthread( - [path = std::string{dirPath}]() -> bool { return FileUtils::getInstance()->createDirectories(path); }, - std::move(callback)); -} - -void FileUtils::removeDirectory(std::string_view dirPath, std::function callback) const -{ - performOperationOffthread( - [path = std::string{dirPath}]() -> bool { return FileUtils::getInstance()->removeDirectory(path); }, - std::move(callback)); -} - -void FileUtils::removeFile(std::string_view filepath, std::function callback) const -{ - auto fullPath = fullPathForFilename(filepath); - performOperationOffthread( - [path = std::string{fullPath}]() -> bool { return FileUtils::getInstance()->removeFile(path); }, - std::move(callback)); -} - -void FileUtils::renameFile(std::string_view path, - std::string_view oldname, - std::string_view name, - std::function callback) const -{ - performOperationOffthread( - [path = std::string{path}, oldname = std::string{oldname}, name = std::string{name}]() -> bool { - return FileUtils::getInstance()->renameFile(path, oldname, name); - }, - std::move(callback)); -} - -void FileUtils::renameFile(std::string_view oldfullpath, - std::string_view newfullpath, - std::function callback) const -{ - performOperationOffthread( - [oldpath = std::string{oldfullpath}, newpath = std::string{newfullpath}]() { - return FileUtils::getInstance()->renameFile(oldpath, newpath); - }, - std::move(callback)); -} - -void FileUtils::getFileSize(std::string_view filepath, std::function callback) const -{ - auto fullPath = fullPathForFilename(filepath); - performOperationOffthread([path = std::string{fullPath}]() { return FileUtils::getInstance()->getFileSize(path); }, - std::move(callback)); -} - -void FileUtils::listFilesAsync(std::string_view dirPath, std::function)> callback) const -{ - auto fullPath = fullPathForDirectory(dirPath); - performOperationOffthread([path = std::string{fullPath}]() { return FileUtils::getInstance()->listFiles(path); }, - std::move(callback)); -} - -void FileUtils::listFilesRecursivelyAsync(std::string_view dirPath, - std::function)> callback) const -{ - auto fullPath = fullPathForDirectory(dirPath); - performOperationOffthread( - [path = std::string{fullPath}]() { - std::vector retval; - FileUtils::getInstance()->listFilesRecursively(path, &retval); - return retval; - }, - std::move(callback)); -} -#endif - std::unique_ptr FileUtils::openFileStream(std::string_view filePath, IFileStream::Mode mode) const { FileStream fs; @@ -1219,26 +1069,13 @@ int unlink_cb(const char* fpath, const struct stat* sb, int typeflag, struct FTW bool FileUtils::removeDirectory(std::string_view path) const { -# if !defined(AX_TARGET_OS_TVOS) - -# if (AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID) - if (nftw(path.data(), unlink_cb, 64, FTW_DEPTH | FTW_PHYS) == -1) - return false; - else - return true; -# else - std::string command = "rm -r \""s; - // Path may include space. - command.append(path).append("\"", 1); - if (system(command.c_str()) >= 0) - return true; - else - return false; -# endif // (AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID) - +# if (AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID) && !defined(AX_TARGET_OS_TVOS) + return nftw(path.data(), unlink_cb, 64, FTW_DEPTH | FTW_PHYS) != -1; # else - return false; -# endif // !defined(AX_TARGET_OS_TVOS) + std::error_code ec; + auto n = stdfs::remove_all(path, ec); + return !ec && n > 0; +# endif } bool FileUtils::removeFile(std::string_view path) const diff --git a/core/platform/FileUtils.h b/axmol/platform/FileUtils.h similarity index 72% rename from core/platform/FileUtils.h rename to axmol/platform/FileUtils.h index 5e08a052e9ce..6a5a1372be6a 100644 --- a/core/platform/FileUtils.h +++ b/axmol/platform/FileUtils.h @@ -33,13 +33,13 @@ THE SOFTWARE. #include #include -#include "platform/IFileStream.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" -#include "base/Value.h" -#include "base/Data.h" -#include "base/Scheduler.h" -#include "base/Director.h" +#include "axmol/platform/IFileStream.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" +#include "axmol/base/Value.h" +#include "axmol/base/Data.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Director.h" #define AX_CONTENT_DIR "Content/" #define AX_CONTENT_DIR_LEN (sizeof("Content/") - 1) @@ -89,12 +89,12 @@ class ResizableBufferAdapter : public ResizableBuffer public: explicit ResizableBufferAdapter(T* buffer) : _buffer(buffer) {} - virtual void resize(size_t size) override + void resize(size_t size) override { _buffer->resize((size + sizeof(typename T::value_type) - 1) / sizeof(typename T::value_type)); } - virtual void* buffer() const override { return _buffer->data(); } - virtual size_t size() const override { return _buffer->size() * sizeof(typename T::value_type); } + void* buffer() const override { return _buffer->data(); } + size_t size() const override { return _buffer->size() * sizeof(typename T::value_type); } }; /** Helper class to handle file operations. */ @@ -570,198 +570,6 @@ class AX_DLL FileUtils */ virtual void listFilesRecursively(std::string_view dirPath, std::vector* files) const; - -#ifndef AX_CORE_PROFILE - /** - * Gets string from a file, async off the main cocos thread - * - * @param path filepath for the string to be read. Can be relative or absolute path - * @param callback Function that will be called when file is read. Will be called - * on the main cocos thread. - */ - AX_DEPRECATED(2.1) virtual void getStringFromFile(std::string_view path, std::function callback) const; - /** - * Gets a binary data object from a file, async off the main cocos thread. - * - * @param filename filepath for the data to be read. Can be relative or absolute path - * @param callback Function that will be called when file is read. Will be called - * on the main cocos thread. - */ - AX_DEPRECATED(2.1) virtual void getDataFromFile(std::string_view filename, std::function callback) const; - /** - * Write a string to a file, done async off the main cocos thread - * Use this function if you need file access without blocking the main thread. - * - * This function takes a std::string by value on purpose, to leverage move sematics. - * If you want to avoid a copy of your datastr, use std::move/std::forward if appropriate - * - * @param dataStr the string want to save - * @param fullPath The full path to the file you want to save a string - * @param callback The function called once the string has been written to a file. This - * function will be executed on the main cocos thread. It will have on boolean argument - * signifying if the write was successful. - */ - AX_DEPRECATED(2.1) virtual void writeStringToFile(std::string dataStr, - std::string_view fullPath, - std::function callback) const; - /** - * Write Data into a file, done async off the main cocos thread. - * - * Use this function if you need to write Data while not blocking the main cocos thread. - * - * This function takes Data by value on purpose, to leverage move sematics. - * If you want to avoid a copy of your data, use std::move/std::forward if appropriate - * - *@param data The data that will be written to disk - *@param fullPath The absolute file path that the data will be written to - *@param callback The function that will be called when data is written to disk. This - * function will be executed on the main cocos thread. It will have on boolean argument - * signifying if the write was successful. - */ - AX_DEPRECATED(2.1) virtual void writeDataToFile(Data data, std::string_view fullPath, std::function callback) const; - /** - * Write a ValueMap into a file, done async off the main cocos thread. - * - * Use this function if you need to write a ValueMap while not blocking the main cocos thread. - * - * This function takes ValueMap by value on purpose, to leverage move sematics. - * If you want to avoid a copy of your dict, use std::move/std::forward if appropriate - * - *@param dict The ValueMap that will be written to disk - *@param fullPath The absolute file path that the data will be written to - *@param callback The function that will be called when dict is written to disk. This - * function will be executed on the main cocos thread. It will have on boolean argument - * signifying if the write was successful. - */ - AX_DEPRECATED(2.1) virtual void writeValueMapToFile(ValueMap dict, - std::string_view fullPath, - std::function callback) const; - /** - * Write a ValueVector into a file, done async off the main cocos thread. - * - * Use this function if you need to write a ValueVector while not blocking the main cocos thread. - * - * This function takes ValueVector by value on purpose, to leverage move sematics. - * If you want to avoid a copy of your dict, use std::move/std::forward if appropriate - * - *@param vecData The ValueVector that will be written to disk - *@param fullPath The absolute file path that the data will be written to - *@param callback The function that will be called when vecData is written to disk. This - * function will be executed on the main cocos thread. It will have on boolean argument - * signifying if the write was successful. - */ - AX_DEPRECATED(2.1) virtual void writeValueVectorToFile(ValueVector vecData, - std::string_view fullPath, - std::function callback) const; - /** - * Checks if a file exists, done async off the main cocos thread. - * - * Use this function if you need to check if a file exists while not blocking the main cocos thread. - * - * @note If a relative path was passed in, it will be inserted a default root path at the beginning. - * @param filename The path of the file, it could be a relative or absolute path. - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the file exists, false otherwise. - */ - AX_DEPRECATED(2.1) virtual void isFileExist(std::string_view filename, std::function callback) const; - - AX_DEPRECATED(2.1) static std::string getFileExtension(std::string_view filePath) { return getPathExtension(filePath); } - AX_DEPRECATED(2.1) static std::string getFileShortName(std::string_view filePath) { return getPathBaseName(filePath); } - /** - * Checks whether the absoulate path is a directory, async off of the main cocos thread. - * - * @param dirPath The path of the directory, it must be an absolute path - * @param callback that will accept a boolean, true if the file exists, false otherwise. - * Callback will happen on the main cocos thread. - */ - AX_DEPRECATED(2.1) virtual void isDirectoryExist(std::string_view fullPath, std::function callback) const; - - AX_DEPRECATED(2.1) bool createDirectory(std::string_view dirPath) const { return createDirectories(dirPath); } - - /** - * Create a directory, async off the main cocos thread. - * - * @param dirPath the path of the directory, it must be an absolute path - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the directory was successfully, false otherwise. - */ - AX_DEPRECATED(2.1) void createDirectory(std::string_view dirPath, std::function callback) const; - - /** - * Removes a directory, async off the main cocos thread. - * - * @param dirPath the path of the directory, it must be an absolute path - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the directory was successfully removed, false otherwise. - */ - AX_DEPRECATED(2.1) void removeDirectory(std::string_view dirPath, std::function callback) const; - - /** - * Removes a file, async off the main cocos thread. - * - * @param filepath the path of the file to remove, it must be an absolute path - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the file was successfully removed, false otherwise. - */ - AX_DEPRECATED(2.1) virtual void removeFile(std::string_view filepath, std::function callback) const; - - /** - * Renames a file under the given directory, async off the main cocos thread. - * - * @param path The parent directory path of the file, it must be an absolute path. - * @param oldname The current name of the file. - * @param name The new name of the file. - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the file was successfully renamed, false otherwise. - */ - AX_DEPRECATED(2.1) virtual void renameFile(std::string_view path, - std::string_view oldname, - std::string_view name, - std::function callback) const; - - /** - * Renames a file under the given directory, async off the main cocos thread. - * - * @param oldfullpath The current fullpath of the file. Includes path and name. - * @param newfullpath The new fullpath of the file. Includes path and name. - * @param callback The function that will be called when the operation is complete. Will have one boolean - * argument, true if the file was successfully renamed, false otherwise. - */ - AX_DEPRECATED(2.1) void renameFile(std::string_view oldfullpath, - std::string_view newfullpath, - std::function callback) const; - - /** - * Retrieve the file size, async off the main cocos thread. - * - * @note If a relative path was passed in, it will be inserted a default root path at the beginning. - * @param filepath The path of the file, it could be a relative or absolute path. - * @param callback The function that will be called when the operation is complete. Will have one long - * argument, the file size. - */ - AX_DEPRECATED(2.1) void getFileSize(std::string_view filepath, std::function callback) const; - - /** - * List all files in a directory async, off of the main cocos thread. - * - * @param dirPath The path of the directory, it could be a relative or an absolute path. - * @param callback The callback to be called once the list operation is complete. Will be called on the main cocos - * thread. - * @lua NA - */ - AX_DEPRECATED(2.1) void listFilesAsync(std::string_view dirPath, std::function)> callback) const; - - /** - * List all files recursively in a directory, async off the main cocos thread. - * - * @param dirPath The path of the directory, it could be a relative or an absolute path. - * @param callback The callback to be called once the list operation is complete. - * Will be called on the main cocos thread. - * @lua NA - */ - AX_DEPRECATED(2.1) void listFilesRecursivelyAsync(std::string_view dirPath, - std::function)> callback) const; -#endif /** Returns the full path cache. */ const hlookup::string_map getFullPathCache() const { return _fullPathCache; } diff --git a/core/platform/GL.h b/axmol/platform/GL.h similarity index 82% rename from core/platform/GL.h rename to axmol/platform/GL.h index dcc14ee9600c..4727ed368ec7 100644 --- a/core/platform/GL.h +++ b/axmol/platform/GL.h @@ -29,29 +29,31 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID -# include "platform/android/GL-android.h" +# include "axmol/platform/android/GL-android.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 -# include "platform/win32/GL-win32.h" +# if AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/platform/win32/GL-win32.h" +# endif #elif AX_TARGET_PLATFORM == AX_PLATFORM_WINRT -# include "platform/winrt/GL-winrt.h" +# include "axmol/platform/winrt/GL-winrt.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_LINUX -# include "platform/linux/GL-linux.h" +# include "axmol/platform/linux/GL-linux.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "platform/wasm/GL-wasm.h" +# include "axmol/platform/wasm/GL-wasm.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_IOS -# if defined(AX_USE_GL) -# include "platform/ios/GL-ios.h" +# if AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/platform/ios/GL-ios.h" # endif #elif AX_TARGET_PLATFORM == AX_PLATFORM_MAC -# if defined(AX_USE_GL) -# include "platform/mac/GL-mac.h" +# if AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/platform/mac/GL-mac.h" # endif #endif -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL # if !defined(GL_BGRA) # define GL_BGRA 0x80E1 # endif diff --git a/core/platform/IFileStream.h b/axmol/platform/IFileStream.h similarity index 96% rename from core/platform/IFileStream.h rename to axmol/platform/IFileStream.h index be4ecc656af9..e45f14064049 100644 --- a/core/platform/IFileStream.h +++ b/axmol/platform/IFileStream.h @@ -3,8 +3,8 @@ #include -#include "platform/PlatformConfig.h" -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/platform/Image.cpp b/axmol/platform/Image.cpp similarity index 92% rename from core/platform/Image.cpp rename to axmol/platform/Image.cpp index 86c68c5ca8f1..aab9ddab5798 100644 --- a/core/platform/Image.cpp +++ b/axmol/platform/Image.cpp @@ -25,14 +25,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Image.h" -#include "renderer/backend/PixelFormatUtils.h" +#include "axmol/platform/Image.h" +#include "axmol/rhi/PixelFormatUtils.h" #include #include -#include "base/axstd.h" -#include "base/Config.h" // AX_USE_JPEG, AX_USE_WEBP +#include "axmol/base/axstd.h" +#include "axmol/base/Config.h" // AX_USE_JPEG, AX_USE_WEBP #define STBI_NO_JPEG #define STBI_NO_PNG @@ -103,36 +103,36 @@ struct dirent* readdir$INODE64(DIR* dir) #endif // AX_USE_JPEG } /* extern "C" */ -#include "base/ktxspec_v1.h" +#include "axmol/base/ktxspec_v1.h" -#include "base/s3tc.h" -#include "base/atitc.h" -#include "base/pvr.h" -#include "base/TGAlib.h" +#include "axmol/base/s3tc.h" +#include "axmol/base/atitc.h" +#include "axmol/base/pvr.h" +#include "axmol/base/TGAlib.h" -#include "base/etc1.h" -#include "base/etc2.h" +#include "axmol/base/etc1.h" +#include "axmol/base/etc2.h" -#include "base/astc.h" +#include "axmol/base/astc.h" #if AX_USE_WEBP # include "decode.h" #endif // AX_USE_WEBP -#include "base/Macros.h" -#include "platform/Common.h" -#include "platform/StdC.h" -#include "platform/FileUtils.h" -#include "base/Configuration.h" -#include "base/Utils.h" -#include "base/ZipUtils.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/StdC.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Utils.h" +#include "axmol/base/ZipUtils.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "platform/android/FileUtils-android.h" -# include "platform/GL.h" +# include "axmol/platform/android/FileUtils-android.h" +# include "axmol/platform/GL.h" #endif #if AX_USE_WIC -# include "platform/winrt/WICImageLoader-winrt.h" +# include "axmol/platform/winrt/WICImageLoader-winrt.h" #endif namespace ax @@ -231,21 +231,21 @@ enum class PVR3TexturePixelFormat : uint64_t }; // v2 -typedef const std::map _pixel2_formathash; +typedef const std::map _pixel2_formathash; static const _pixel2_formathash::value_type v2_pixel_formathash_value[] = { - _pixel2_formathash::value_type(PVR2TexturePixelFormat::BGRA8888, backend::PixelFormat::BGRA8), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA8888, backend::PixelFormat::RGBA8), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA4444, backend::PixelFormat::RGBA4), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA5551, backend::PixelFormat::RGB5A1), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGB565, backend::PixelFormat::RGB565), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGB888, backend::PixelFormat::RGB8), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::A8, backend::PixelFormat::R8), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::I8, backend::PixelFormat::R8), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::AI88, backend::PixelFormat::RG8), - - _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC2BPP_RGBA, backend::PixelFormat::PVRTC2A), - _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC4BPP_RGBA, backend::PixelFormat::PVRTC4A), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::BGRA8888, rhi::PixelFormat::BGRA8), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA8888, rhi::PixelFormat::RGBA8), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA4444, rhi::PixelFormat::RGBA4), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGBA5551, rhi::PixelFormat::RGB5A1), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGB565, rhi::PixelFormat::RGB565), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::RGB888, rhi::PixelFormat::RGB8), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::A8, rhi::PixelFormat::R8), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::I8, rhi::PixelFormat::R8), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::AI88, rhi::PixelFormat::RG8), + + _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC2BPP_RGBA, rhi::PixelFormat::PVRTC2A), + _pixel2_formathash::value_type(PVR2TexturePixelFormat::PVRTC4BPP_RGBA, rhi::PixelFormat::PVRTC4A), }; static const int PVR2_MAX_TABLE_ELEMENTS = sizeof(v2_pixel_formathash_value) / sizeof(v2_pixel_formathash_value[0]); @@ -253,26 +253,26 @@ static const _pixel2_formathash v2_pixel_formathash(v2_pixel_formathash_value, v2_pixel_formathash_value + PVR2_MAX_TABLE_ELEMENTS); // v3 -typedef const std::map _pixel3_formathash; +typedef const std::map _pixel3_formathash; static _pixel3_formathash::value_type v3_pixel_formathash_value[] = { - _pixel3_formathash::value_type(PVR3TexturePixelFormat::BGRA8888, backend::PixelFormat::BGRA8), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA8888, backend::PixelFormat::RGBA8), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA4444, backend::PixelFormat::RGBA4), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA5551, backend::PixelFormat::RGB5A1), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGB565, backend::PixelFormat::RGB565), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGB888, backend::PixelFormat::RGB8), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::A8, backend::PixelFormat::R8), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::L8, backend::PixelFormat::R8), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::LA88, backend::PixelFormat::RG8), - - _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGB, backend::PixelFormat::PVRTC2), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGBA, backend::PixelFormat::PVRTC2A), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGB, backend::PixelFormat::PVRTC4), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGBA, backend::PixelFormat::PVRTC4A), - - _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC1, backend::PixelFormat::ETC1), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC2_RGB, backend::PixelFormat::ETC2_RGB), - _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC2_RGBA, backend::PixelFormat::ETC2_RGBA), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::BGRA8888, rhi::PixelFormat::BGRA8), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA8888, rhi::PixelFormat::RGBA8), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA4444, rhi::PixelFormat::RGBA4), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGBA5551, rhi::PixelFormat::RGB5A1), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGB565, rhi::PixelFormat::RGB565), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::RGB888, rhi::PixelFormat::RGB8), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::A8, rhi::PixelFormat::R8), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::L8, rhi::PixelFormat::R8), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::LA88, rhi::PixelFormat::RG8), + + _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGB, rhi::PixelFormat::PVRTC2), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC2BPP_RGBA, rhi::PixelFormat::PVRTC2A), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGB, rhi::PixelFormat::PVRTC4), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::PVRTC4BPP_RGBA, rhi::PixelFormat::PVRTC4A), + + _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC1, rhi::PixelFormat::ETC1), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC2_RGB, rhi::PixelFormat::ETC2_RGB), + _pixel3_formathash::value_type(PVR3TexturePixelFormat::ETC2_RGBA, rhi::PixelFormat::ETC2_RGBA), }; static const int PVR3_MAX_TABLE_ELEMENTS = sizeof(v3_pixel_formathash_value) / sizeof(v3_pixel_formathash_value[0]); @@ -463,25 +463,25 @@ static void pngReadCallback(png_structp png_ptr, png_bytep data, png_size_t leng * Notes: PVR file Specification have many pixel formats, cocos2d-x-v2~v4 and axmol only support pvrtc and etc1 * see: https://cdn.imgtec.com/sdk-documentation/PVR+File+Format.Specification.pdf */ -static backend::PixelFormat getDevicePVRPixelFormat(backend::PixelFormat format) +static rhi::PixelFormat getDevicePVRPixelFormat(rhi::PixelFormat format) { switch (format) { - case backend::PixelFormat::PVRTC4: - case backend::PixelFormat::PVRTC4A: - case backend::PixelFormat::PVRTC2: - case backend::PixelFormat::PVRTC2A: + case rhi::PixelFormat::PVRTC4: + case rhi::PixelFormat::PVRTC4A: + case rhi::PixelFormat::PVRTC2: + case rhi::PixelFormat::PVRTC2A: if (Configuration::getInstance()->supportsPVRTC()) return format; else - return backend::PixelFormat::RGBA8; - case backend::PixelFormat::ETC1: + return rhi::PixelFormat::RGBA8; + case rhi::PixelFormat::ETC1: if (Configuration::getInstance()->supportsETC1()) return format; else if (Configuration::getInstance()->supportsETC2()) - return backend::PixelFormat::ETC2_RGB; + return rhi::PixelFormat::ETC2_RGB; else - return backend::PixelFormat::RGBA8; + return rhi::PixelFormat::RGBA8; default: return format; } @@ -567,7 +567,7 @@ Image::Image() , _height(0) , _unpack(false) , _fileType(Format::UNKNOWN) - , _pixelFormat(backend::PixelFormat::NONE) + , _pixelFormat(rhi::PixelFormat::NONE) , _numberOfMipmaps(0) , _hasPremultipliedAlpha(false) {} @@ -733,7 +733,7 @@ bool Image::initWithRawData(const uint8_t* data, _height = height; _width = width; _hasPremultipliedAlpha = preMulti; - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; // only RGBA8888 supported int bytesPerComponent = 4; @@ -750,8 +750,8 @@ bool Image::initWithRawData(const uint8_t* data, void Image::flipRawData() { - AXASSERT(_pixelFormat == backend::PixelFormat::RGBA8, "only RGBA8888 can be flipped"); - if (_pixelFormat != backend::PixelFormat::RGBA8) + AXASSERT(_pixelFormat == rhi::PixelFormat::RGBA8, "only RGBA8888 can be flipped"); + if (_pixelFormat != rhi::PixelFormat::RGBA8) { AXLOGE("Cannot flip image. Unsupported pixel format."); return; @@ -924,17 +924,17 @@ Image::Format Image::detectFormat(const uint8_t* data, ssize_t dataLen) int Image::getBitPerPixel() { - return backend::PixelFormatUtils::getFormatDescriptor(_pixelFormat).bpp; + return rhi::PixelFormatUtils::getFormatDesc(_pixelFormat).bpp; } bool Image::hasAlpha() { - return backend::PixelFormatUtils::getFormatDescriptor(_pixelFormat).alpha; + return rhi::PixelFormatUtils::getFormatDesc(_pixelFormat).alpha; } bool Image::isCompressed() { - return backend::PixelFormatUtils::isCompressed(_pixelFormat); + return rhi::PixelFormatUtils::isCompressed(_pixelFormat); } #if AX_USE_WIC @@ -952,27 +952,27 @@ bool Image::decodeWithWIC(const unsigned char* data, ssize_t dataLen) if (memcmp(&format, &GUID_WICPixelFormat8bppGray, sizeof(WICPixelFormatGUID)) == 0) { - _pixelFormat = backend::PixelFormat::R8; + _pixelFormat = rhi::PixelFormat::R8; } if (memcmp(&format, &GUID_WICPixelFormat8bppAlpha, sizeof(WICPixelFormatGUID)) == 0) { - _pixelFormat = backend::PixelFormat::RG8; + _pixelFormat = rhi::PixelFormat::RG8; } if (memcmp(&format, &GUID_WICPixelFormat24bppRGB, sizeof(WICPixelFormatGUID)) == 0) { - _pixelFormat = backend::PixelFormat::RGB8; + _pixelFormat = rhi::PixelFormat::RGB8; } if (memcmp(&format, &GUID_WICPixelFormat32bppRGBA, sizeof(WICPixelFormatGUID)) == 0) { - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; } if (memcmp(&format, &GUID_WICPixelFormat32bppBGRA, sizeof(WICPixelFormatGUID)) == 0) { - _pixelFormat = backend::PixelFormat::BGRA8; + _pixelFormat = rhi::PixelFormat::BGRA8; } _dataLen = img.getImageDataSize(); @@ -982,7 +982,7 @@ bool Image::decodeWithWIC(const unsigned char* data, ssize_t dataLen) _data = new (std::nothrow) unsigned char[_dataLen]; bRet = (img.getImageData(_data, _dataLen) > 0); - if (_pixelFormat == backend::PixelFormat::RGBA8) + if (_pixelFormat == rhi::PixelFormat::RGBA8) { premultiplyAlpha(); } @@ -999,7 +999,7 @@ bool Image::encodeWithWIC(std::string_view filePath, bool isToRGB, GUID containe int saveLen = _dataLen; int bpp = 4; - if (targetFormat == GUID_WICPixelFormat24bppBGR && _pixelFormat == backend::PixelFormat::RGBA8) + if (targetFormat == GUID_WICPixelFormat24bppBGR && _pixelFormat == rhi::PixelFormat::RGBA8) { bpp = 3; saveLen = _width * _height * bpp; @@ -1142,12 +1142,12 @@ bool Image::initWithJpgData(uint8_t* data, ssize_t dataLen) // we only support RGB or grayscale if (cinfo.jpeg_color_space == JCS_GRAYSCALE) { - _pixelFormat = backend::PixelFormat::R8; + _pixelFormat = rhi::PixelFormat::R8; } else { cinfo.out_color_space = JCS_RGB; - _pixelFormat = backend::PixelFormat::RGB8; + _pixelFormat = rhi::PixelFormat::RGB8; } /* Start decompression jpeg here */ @@ -1273,16 +1273,16 @@ bool Image::initWithPngData(uint8_t* data, ssize_t dataLen) switch (color_type) { case PNG_COLOR_TYPE_GRAY: - _pixelFormat = backend::PixelFormat::R8; + _pixelFormat = rhi::PixelFormat::R8; break; case PNG_COLOR_TYPE_GRAY_ALPHA: - _pixelFormat = backend::PixelFormat::RG8; + _pixelFormat = rhi::PixelFormat::RG8; break; case PNG_COLOR_TYPE_RGB: - _pixelFormat = backend::PixelFormat::RGB8; + _pixelFormat = rhi::PixelFormat::RGB8; break; case PNG_COLOR_TYPE_RGB_ALPHA: - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; break; default: break; @@ -1314,7 +1314,8 @@ bool Image::initWithPngData(uint8_t* data, ssize_t dataLen) png_read_end(png_ptr, nullptr); // premultiplied alpha for RGBA8888 - if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA) || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) + if ((color_type == PNG_COLOR_TYPE_RGB_ALPHA) + || (color_type == PNG_COLOR_TYPE_GRAY_ALPHA)) { if (PNG_PREMULTIPLIED_ALPHA_ENABLED) { @@ -1355,7 +1356,7 @@ bool Image::initWithBmpData(uint8_t* data, ssize_t dataLen) { _dataLen = _width * _height * nrChannels; _fileType = Format::BMP; - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; return true; } return false; @@ -1377,7 +1378,7 @@ bool Image::initWithWebpData(uint8_t* data, ssize_t dataLen) break; config.output.colorspace = config.input.has_alpha ? MODE_rgbA : MODE_RGB; - _pixelFormat = config.input.has_alpha ? backend::PixelFormat::RGBA8 : backend::PixelFormat::RGB8; + _pixelFormat = config.input.has_alpha ? rhi::PixelFormat::RGBA8 : rhi::PixelFormat::RGB8; _width = config.input.width; _height = config.input.height; @@ -1423,15 +1424,15 @@ bool Image::initWithTGAData(tImageTGA* tgaData) // unsupported RGB555 if (tgaData->pixelDepth == 16) { - _pixelFormat = backend::PixelFormat::RGB5A1; + _pixelFormat = rhi::PixelFormat::RGB5A1; } else if (tgaData->pixelDepth == 24) { - _pixelFormat = backend::PixelFormat::RGB8; + _pixelFormat = rhi::PixelFormat::RGB8; } else if (tgaData->pixelDepth == 32) { - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; } else { @@ -1444,7 +1445,7 @@ bool Image::initWithTGAData(tImageTGA* tgaData) // gray if (8 == tgaData->pixelDepth) { - _pixelFormat = backend::PixelFormat::R8; + _pixelFormat = rhi::PixelFormat::R8; } else { @@ -1534,7 +1535,7 @@ bool Image::initWithPVRv2Data(uint8_t* data, ssize_t dataLen, bool ownData) } auto pixelFormat = getDevicePVRPixelFormat(v2_pixel_formathash.at(formatFlags)); - auto& info = backend::PixelFormatUtils::getFormatDescriptor(pixelFormat); + auto& info = rhi::PixelFormatUtils::getFormatDesc(pixelFormat); int bpp = info.bpp; if (!bpp) { @@ -1686,7 +1687,7 @@ bool Image::initWithPVRv3Data(uint8_t* data, ssize_t dataLen, bool ownData) } auto finalPixelFormat = getDevicePVRPixelFormat(v3_pixel_formathash.at(pixelFormat)); - auto& info = backend::PixelFormatUtils::getFormatDescriptor(finalPixelFormat); + auto& info = rhi::PixelFormatUtils::getFormatDesc(finalPixelFormat); int bpp = info.bpp; if (!info.bpp) { @@ -1857,15 +1858,15 @@ bool Image::initWithETCData(uint8_t* data, ssize_t dataLen, bool ownData) // GL_ETC1_RGB8_OES is not available in any desktop GL extension but the compression // format is forwards compatible so just use the ETC2 format. - backend::PixelFormat compressedFormat; + rhi::PixelFormat compressedFormat; if (Configuration::getInstance()->supportsETC1()) - compressedFormat = backend::PixelFormat::ETC1; + compressedFormat = rhi::PixelFormat::ETC1; else if (Configuration::getInstance()->supportsETC2()) - compressedFormat = backend::PixelFormat::ETC2_RGB; + compressedFormat = rhi::PixelFormat::ETC2_RGB; else - compressedFormat = backend::PixelFormat::NONE; + compressedFormat = rhi::PixelFormat::NONE; - if (compressedFormat != backend::PixelFormat::NONE) + if (compressedFormat != rhi::PixelFormat::NONE) { _pixelFormat = compressedFormat; forwardPixels(data, dataLen, pixelOffset, ownData); @@ -1881,7 +1882,7 @@ bool Image::initWithETCData(uint8_t* data, ssize_t dataLen, bool ownData) static_cast(_data), _width, _height) == 0) { // if it is not gles or device do not support ETC1, decode texture by software // directly decode ETC1_RGB to RGBA8888 - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; return true; } @@ -1932,7 +1933,7 @@ bool Image::initWithETC2Data(uint8_t* data, ssize_t dataLen, bool ownData) if (Configuration::getInstance()->supportsETC2()) { _pixelFormat = - format == ETC2_RGBA_NO_MIPMAPS ? backend::PixelFormat::ETC2_RGBA : backend::PixelFormat::ETC2_RGB; + format == ETC2_RGBA_NO_MIPMAPS ? rhi::PixelFormat::ETC2_RGBA : rhi::PixelFormat::ETC2_RGB; forwardPixels(data, dataLen, pixelOffset, ownData); } @@ -1952,7 +1953,7 @@ bool Image::initWithETC2Data(uint8_t* data, ssize_t dataLen, bool ownData) _dataLen = 0; break; } - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; } _hasPremultipliedAlpha = isCompressedImageHavePMA(CompressedImagePMAFlag::ETC2); @@ -1994,31 +1995,31 @@ bool Image::initWithASTCData(uint8_t* data, ssize_t dataLen, bool ownData) { if (block_x == 4 && block_y == 4) { - _pixelFormat = backend::PixelFormat::ASTC4x4; + _pixelFormat = rhi::PixelFormat::ASTC4x4; } else if (block_x == 5 && block_y == 5) { - _pixelFormat = backend::PixelFormat::ASTC5x5; + _pixelFormat = rhi::PixelFormat::ASTC5x5; } else if (block_x == 6 && block_y == 6) { - _pixelFormat = backend::PixelFormat::ASTC6x6; + _pixelFormat = rhi::PixelFormat::ASTC6x6; } else if (block_x == 8 && block_y == 5) { - _pixelFormat = backend::PixelFormat::ASTC8x5; + _pixelFormat = rhi::PixelFormat::ASTC8x5; } else if (block_x == 8 && block_y == 6) { - _pixelFormat = backend::PixelFormat::ASTC8x6; + _pixelFormat = rhi::PixelFormat::ASTC8x6; } else if (block_x == 8 && block_y == 8) { - _pixelFormat = backend::PixelFormat::ASTC8x8; + _pixelFormat = rhi::PixelFormat::ASTC8x8; } else if (block_x == 10 && block_y == 5) { - _pixelFormat = backend::PixelFormat::ASTC10x5; + _pixelFormat = rhi::PixelFormat::ASTC10x5; } forwardPixels(data, dataLen, ASTC_HEAD_SIZE, ownData); @@ -2038,7 +2039,7 @@ bool Image::initWithASTCData(uint8_t* data, ssize_t dataLen, bool ownData) break; } - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; } _hasPremultipliedAlpha = isCompressedImageHavePMA(CompressedImagePMAFlag::ASTC); @@ -2082,20 +2083,20 @@ bool Image::initWithS3TCData(uint8_t* data, ssize_t dataLen, bool ownData) if (FOURCC_DXT1 == header->ddsd.DUMMYUNIONNAMEN4.ddpfPixelFormat.fourCC) { - _pixelFormat = backend::PixelFormat::S3TC_DXT1; + _pixelFormat = rhi::PixelFormat::S3TC_DXT1; } else if (FOURCC_DXT3 == header->ddsd.DUMMYUNIONNAMEN4.ddpfPixelFormat.fourCC) { - _pixelFormat = backend::PixelFormat::S3TC_DXT3; + _pixelFormat = rhi::PixelFormat::S3TC_DXT3; } else if (FOURCC_DXT5 == header->ddsd.DUMMYUNIONNAMEN4.ddpfPixelFormat.fourCC) { - _pixelFormat = backend::PixelFormat::S3TC_DXT5; + _pixelFormat = rhi::PixelFormat::S3TC_DXT5; } } else { // will software decode - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; // prepare data for software decompress for (int i = 0; i < _numberOfMipmaps && (width || height); ++i) @@ -2216,13 +2217,13 @@ bool Image::initWithATITCData(uint8_t* data, ssize_t dataLen, bool ownData) switch (header->glInternalFormat) { case KTXv1Header::InternalFormat::ATC_RGB_AMD: - _pixelFormat = backend::PixelFormat::ATC_RGB; + _pixelFormat = rhi::PixelFormat::ATC_RGB; break; case KTXv1Header::InternalFormat::ATC_RGBA_EXPLICIT_ALPHA_AMD: - _pixelFormat = backend::PixelFormat::ATC_EXPLICIT_ALPHA; + _pixelFormat = rhi::PixelFormat::ATC_EXPLICIT_ALPHA; break; case KTXv1Header::InternalFormat::ATC_RGBA_INTERPOLATED_ALPHA_AMD: - _pixelFormat = backend::PixelFormat::ATC_INTERPOLATED_ALPHA; + _pixelFormat = rhi::PixelFormat::ATC_INTERPOLATED_ALPHA; break; default: break; @@ -2233,7 +2234,7 @@ bool Image::initWithATITCData(uint8_t* data, ssize_t dataLen, bool ownData) AXLOGW("Hardware ATITC decoder not present. Using software decoder"); - _pixelFormat = backend::PixelFormat::RGBA8; + _pixelFormat = rhi::PixelFormat::RGBA8; for (int i = 0; i < _numberOfMipmaps && (width || height); ++i) { @@ -2338,11 +2339,11 @@ void Image::forwardPixels(uint8_t* data, ssize_t dataLen, int offset, bool ownDa #if (AX_TARGET_PLATFORM != AX_PLATFORM_IOS) bool Image::saveToFile(std::string_view filename, bool isToRGB) { - // only support for backend::PixelFormat::RGB8 or backend::PixelFormat::RGBA8 uncompressed data - if (isCompressed() || (_pixelFormat != backend::PixelFormat::RGB8 && _pixelFormat != backend::PixelFormat::RGBA8)) + // only support for rhi::PixelFormat::RGB8 or rhi::PixelFormat::RGBA8 uncompressed data + if (isCompressed() || (_pixelFormat != rhi::PixelFormat::RGB8 && _pixelFormat != rhi::PixelFormat::RGBA8)) { AXLOGW( - "Image: saveToFile is only support for backend::PixelFormat::RGB8 or backend::PixelFormat::RGBA8 " + "Image: saveToFile is only support for rhi::PixelFormat::RGB8 or rhi::PixelFormat::RGBA8 " "uncompressed data for now"); return false; } @@ -2617,11 +2618,11 @@ bool Image::saveImageToJPG(std::string_view filePath) void Image::premultiplyAlpha() { #if AX_ENABLE_PREMULTIPLIED_ALPHA - AXASSERT((_pixelFormat == backend::PixelFormat::RGBA8) - || (_pixelFormat == backend::PixelFormat::RG8), + AXASSERT((_pixelFormat == rhi::PixelFormat::RGBA8) + || (_pixelFormat == rhi::PixelFormat::RG8), "The pixel format should be RGBA8888 or RG88."); - if (_pixelFormat == backend::PixelFormat::RGBA8) { + if (_pixelFormat == rhi::PixelFormat::RGBA8) { unsigned int* fourBytes = (unsigned int*)_data; for (int i = 0; i < _width * _height; i++) { @@ -2635,7 +2636,7 @@ void Image::premultiplyAlpha() for (int i = 0; i < _width * _height; i++) { uint8_t* p = _data + i * 2; - twoBytes[i] = ((p[0] * p[1] + 1) >> 8) | (p[1] << 8); + twoBytes[i] = ((p[0] * (p[1] + 1)) >> 8) | (p[1] << 8); } } @@ -2652,7 +2653,7 @@ static inline uint8_t clamp(int x) void Image::reversePremultipliedAlpha() { - AXASSERT(_pixelFormat == backend::PixelFormat::RGBA8, "The pixel format should be RGBA8888!"); + AXASSERT(_pixelFormat == rhi::PixelFormat::RGBA8, "The pixel format should be RGBA8888!"); unsigned int* fourBytes = (unsigned int*)_data; for (int i = 0; i < _width * _height; i++) diff --git a/core/platform/Image.h b/axmol/platform/Image.h similarity index 97% rename from core/platform/Image.h rename to axmol/platform/Image.h index 8956278523f4..49d7eb2e99a5 100644 --- a/core/platform/Image.h +++ b/axmol/platform/Image.h @@ -27,9 +27,9 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" -#include "renderer/Texture2D.h" -#include "base/Data.h" +#include "axmol/base/Object.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Data.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WINRT # define AX_USE_WIC 1 @@ -165,12 +165,12 @@ class AX_DLL Image : public Object // only RGBA8888 supported void flipRawData(); - + // Getters uint8_t* getData() { return _data + _offset; } ssize_t getDataLen() { return _dataLen - _offset; } Format getFileType() { return _fileType; } - backend::PixelFormat getPixelFormat() { return _pixelFormat; } + rhi::PixelFormat getPixelFormat() { return _pixelFormat; } int getWidth() { return _width; } int getHeight() { return _height; } int getNumberOfMipmaps() { return _numberOfMipmaps; } @@ -239,7 +239,7 @@ class AX_DLL Image : public Object int _height; bool _unpack; Format _fileType; - backend::PixelFormat _pixelFormat; + rhi::PixelFormat _pixelFormat; MipmapInfo _mipmaps[MIPMAP_MAX]; // pointer to mipmap images int _numberOfMipmaps; // false if we can't auto detect the image is premultiplied or not. diff --git a/core/platform/PlatformConfig.h b/axmol/platform/PlatformConfig.h similarity index 90% rename from core/platform/PlatformConfig.h rename to axmol/platform/PlatformConfig.h index 3ed46f79fd7d..3ea8b9f134dc 100644 --- a/core/platform/PlatformConfig.h +++ b/axmol/platform/PlatformConfig.h @@ -122,6 +122,22 @@ THE SOFTWARE. # endif #endif // AX_PLATFORM_WIN32 +////////////////////////////////////////////////////////////////////////// +// render configure +////////////////////////////////////////////////////////////////////////// + +#define AX_RENDER_API_GL 1 +#define AX_RENDER_API_MTL 2 +#define AX_RENDER_API_D3D 3 + +#ifndef AX_RENDER_API +# if defined(__APPLE__) +# define AX_RENDER_API AX_RENDER_API_MTL +# else +# define AX_RENDER_API AX_RENDER_API_GL +# endif +#endif + /* The google/angle is library which translate native graphics API to GLES3+ APIs repo: https://github.com/google/angle @@ -134,9 +150,9 @@ Linux: Desktop GL/Vulkan // mac/iOS/android use system builtin GL/GLES, not ANGLE // Windows: use ANGLE GLES #ifndef AX_GLES_PROFILE -# if defined(__ANDROID__) -# define AX_GLES_PROFILE 200 -# elif (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) +# if defined(__ANDROID__) || defined(_WIN32) || \ + (AX_RENDER_API == AX_RENDER_API_GL && \ + (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_TVOS)) # define AX_GLES_PROFILE 300 # else # define AX_GLES_PROFILE 0 @@ -152,16 +168,6 @@ Linux: Desktop GL/Vulkan # define AX_PLATFORM_PC #endif -#if defined(__APPLE__) -# if !defined(AX_USE_GL) -# define AX_USE_METAL 1 -# endif -#else // win32,linux,winuwp,android -# if !defined(AX_USE_GL) -# define AX_USE_GL 1 -# endif -#endif - // ## SIMD detections #if !defined(AX_NEON_INTRINSICS) # if (AX_TARGET_PLATFORM != AX_PLATFORM_WASM) diff --git a/core/platform/PlatformDefine.h b/axmol/platform/PlatformDefine.h similarity index 98% rename from core/platform/PlatformDefine.h rename to axmol/platform/PlatformDefine.h index 37590acf0b9b..8c5937828779 100644 --- a/core/platform/PlatformDefine.h +++ b/axmol/platform/PlatformDefine.h @@ -28,7 +28,7 @@ THE SOFTWARE. #pragma once /// @cond DO_NOT_SHOW -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include #include diff --git a/core/platform/PlatformMacros.h b/axmol/platform/PlatformMacros.h similarity index 90% rename from core/platform/PlatformMacros.h rename to axmol/platform/PlatformMacros.h index 6b3f5f283fcb..4692e58bb719 100644 --- a/core/platform/PlatformMacros.h +++ b/axmol/platform/PlatformMacros.h @@ -30,10 +30,10 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). /** * Define some platform specific macros. */ -#include "base/Config.h" -#include "base/hlookup.h" -#include "platform/PlatformConfig.h" -#include "platform/PlatformDefine.h" +#include "axmol/base/Config.h" +#include "axmol/base/hlookup.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/PlatformDefine.h" /** @def CREATE_FUNC(__TYPE__) * Define a create function for a specific type, such as Layer. @@ -312,52 +312,6 @@ public: \ #define AX_BREAK_IF(cond) \ if (cond) \ break -#ifndef AX_CORE_PROFILE -# define __AXLOGWITHFUNCTION(s, ...) \ - ax::print("%s : %s", __FUNCTION__, ax::StringUtils::format(s, ##__VA_ARGS__).c_str()) -/// @name legacy log macros, deprecated since axmol 2.1.4, use AXLOGD, AXLOGI, AXLOGW, ... instead -/// @{ -# if !defined(_AX_DEBUG) || _AX_DEBUG == 0 -# define AXLOG(...) \ - do \ - { \ - } while (0) -# define AXLOGINFO(...) \ - do \ - { \ - } while (0) -# define AXLOGERROR(...) \ - do \ - { \ - } while (0) -# define AXLOGWARN(...) \ - do \ - { \ - } while (0) - -# elif _AX_DEBUG == 1 -# define AXLOG(format, ...) ax::print(format, ##__VA_ARGS__) -# define AXLOGERROR(format, ...) ax::print(format, ##__VA_ARGS__) -# define AXLOGINFO(format, ...) \ - do \ - { \ - } while (0) -# define AXLOGWARN(...) __AXLOGWITHFUNCTION(__VA_ARGS__) - -# elif _AX_DEBUG > 1 -# define AXLOG(format, ...) ax::print(format, ##__VA_ARGS__) -# define AXLOGERROR(format, ...) ax::print(format, ##__VA_ARGS__) -# define AXLOGINFO(format, ...) ax::print(format, ##__VA_ARGS__) -# define AXLOGWARN(...) __AXLOGWITHFUNCTION(__VA_ARGS__) -# endif // _AX_DEBUG - -/** Lua engine debug */ -# if !defined(_AX_DEBUG) || _AX_DEBUG == 0 || AX_LUA_ENGINE_DEBUG == 0 -# define LUALOG(...) -# else -# define LUALOG(format, ...) ax::print(format, ##__VA_ARGS__) -# endif // Lua engine debug -#endif // end of debug group /// @} diff --git a/core/platform/RenderView.cpp b/axmol/platform/RenderView.cpp similarity index 98% rename from core/platform/RenderView.cpp rename to axmol/platform/RenderView.cpp index 316714650db2..83e72e1077c8 100644 --- a/core/platform/RenderView.cpp +++ b/axmol/platform/RenderView.cpp @@ -25,14 +25,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/RenderView.h" - -#include "base/Touch.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "2d/Camera.h" -#include "2d/Scene.h" -#include "renderer/Renderer.h" +#include "axmol/platform/RenderView.h" + +#include "axmol/base/Touch.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Scene.h" +#include "axmol/renderer/Renderer.h" namespace ax { diff --git a/core/platform/RenderView.h b/axmol/platform/RenderView.h similarity index 96% rename from core/platform/RenderView.h rename to axmol/platform/RenderView.h index 6aa06226eaab..23af0d5c6d35 100644 --- a/core/platform/RenderView.h +++ b/axmol/platform/RenderView.h @@ -27,8 +27,8 @@ THE SOFTWARE. #pragma once -#include "base/Types.h" -#include "base/EventTouch.h" +#include "axmol/base/Types.h" +#include "axmol/base/EventTouch.h" #include #include @@ -93,10 +93,6 @@ struct GfxContextAttrs #endif }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef GfxContextAttrs GLContextAttrs; -#endif - namespace ax { @@ -131,9 +127,6 @@ class AX_DLL RenderView : public Object virtual void end() = 0; /** Get whether graphics context is ready, subclass must implement this method. */ -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) bool isOpenGLReady() { return isGfxContextReady(); } -#endif virtual bool isGfxContextReady() = 0; /** Exchanges the front and back buffers, subclass must implement this method. */ @@ -156,12 +149,6 @@ class AX_DLL RenderView : public Object * * @param gfxContextAttrs The OpenGL context attrs. */ -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) static void setGLContextAttrs(GfxContextAttrs& gfxContextAttrs) - { - setGfxContextAttrs(gfxContextAttrs); - } -#endif static void setGfxContextAttrs(GfxContextAttrs& gfxContextAttrs); /** Return the OpenGL context attrs. @@ -486,10 +473,6 @@ class AX_DLL RenderView : public Object bool _interactive; }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef RenderView GLView; -#endif - // end of platform group /// @} diff --git a/core/platform/RenderViewImpl.cpp b/axmol/platform/RenderViewImpl.cpp similarity index 95% rename from core/platform/RenderViewImpl.cpp rename to axmol/platform/RenderViewImpl.cpp index 467a233d27ba..cc7181bf6f8a 100644 --- a/core/platform/RenderViewImpl.cpp +++ b/axmol/platform/RenderViewImpl.cpp @@ -25,35 +25,35 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/RenderViewImpl.h" +#include "axmol/platform/RenderViewImpl.h" #include #include -#include "platform/Application.h" -#include "base/Director.h" -#include "base/Touch.h" -#include "base/EventDispatcher.h" -#include "base/EventKeyboard.h" -#include "base/EventMouse.h" -#include "base/IMEDispatcher.h" -#include "base/Utils.h" -#include "base/UTF8.h" -#include "2d/Camera.h" +#include "axmol/platform/Application.h" +#include "axmol/base/Director.h" +#include "axmol/base/Touch.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventMouse.h" +#include "axmol/base/IMEDispatcher.h" +#include "axmol/base/Utils.h" +#include "axmol/base/text_utils.h" +#include "axmol/2d/Camera.h" #if AX_ICON_SET_SUPPORT -# include "platform/Image.h" +# include "axmol/platform/Image.h" #endif /* AX_ICON_SET_SUPPORT */ -#include "renderer/Renderer.h" +#include "axmol/renderer/Renderer.h" -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL # include -# include "renderer/backend/metal/DriverMTL.h" -# include "renderer/backend/metal/UtilsMTL.h" -#else -# include "renderer/backend/opengl/DriverGL.h" -# include "renderer/backend/opengl/MacrosGL.h" -# include "renderer/backend/opengl/OpenGLState.h" +# include "axmol/rhi/metal/DriverMTL.h" +# include "axmol/rhi/metal/UtilsMTL.h" +#elif AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/rhi/opengl/DriverGL.h" +# include "axmol/rhi/opengl/MacrosGL.h" +# include "axmol/rhi/opengl/OpenGLState.h" #endif // #if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) /** glfw3native.h */ @@ -499,15 +499,19 @@ bool RenderViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rec Vec2 windowSize = rect.size * frameZoomFactor; -#if AX_GLES_PROFILE +#if AX_RENDER_API == AX_RENDER_API_GL +# if AX_GLES_PROFILE glfwWindowHint(GLFW_CLIENT_API, GLFW_OPENGL_ES_API); glfwWindowHint(GLFW_CONTEXT_CREATION_API, GLFW_EGL_CONTEXT_API); glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, AX_GLES_PROFILE / AX_GLES_PROFILE_DEN); glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 0); -#elif defined(AX_USE_GL) +# else glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3); // We want OpenGL 3.3 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 3); glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE); // We don't want the old OpenGL +# endif +#else // Other Graphics driver, don't create gl context. + glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); #endif glfwWindowHint(GLFW_RESIZABLE, resizable ? GL_TRUE : GL_FALSE); @@ -523,11 +527,6 @@ bool RenderViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rec glfwWindowHint(GLFW_VISIBLE, _gfxContextAttrs.visible); glfwWindowHint(GLFW_DECORATED, _gfxContextAttrs.decorated); -#if defined(AX_USE_METAL) - // Don't create gl context. - glfwWindowHint(GLFW_CLIENT_API, GLFW_NO_API); -#endif - #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) glfwWindowHintPointer(GLFW_WIN32_HWND_PARENT, _gfxContextAttrs.viewParent); #endif @@ -566,7 +565,7 @@ bool RenderViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rec if (static_cast(windowSize.height) != actualHeight) windowSize.y = static_cast(actualHeight); -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL int fbWidth, fbHeight; glfwGetFramebufferSize(_mainWindow, &fbWidth, &fbHeight); @@ -590,14 +589,14 @@ bool RenderViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rec [layer setDrawableSize:size]; layer.displaySyncEnabled = _gfxContextAttrs.vsync; [contentView setLayer:layer]; - backend::DriverMTL::setCAMetalLayer(layer); + rhi::mtl::DriverImpl::setCAMetalLayer(layer); #endif -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL glfwMakeContextCurrent(_mainWindow); - glfwSetWindowUserPointer(_mainWindow, backend::__gl); + glfwSetWindowUserPointer(_mainWindow, rhi::gl::__state); #endif - + #if !defined(__APPLE__) handleWindowSize(static_cast(windowSize.width), static_cast(windowSize.height)); #else @@ -641,13 +640,15 @@ bool RenderViewImpl::initWithRect(std::string_view viewName, const ax::Rect& rec glfwSetWindowCloseCallback(_mainWindow, GLFWEventHandler::onGLFWWindowCloseCallback); #if (AX_TARGET_PLATFORM != AX_PLATFORM_MAC) +#if AX_RENDER_API == AX_RENDER_API_GL loadGL(); +#endif // Init driver after load GL - backend::DriverBase::getInstance(); + rhi::DriverBase::getInstance(); #endif -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL # if !defined(__EMSCRIPTEN__) glfwSwapInterval(_gfxContextAttrs.vsync ? 1 : 0); # endif @@ -726,7 +727,7 @@ void RenderViewImpl::end() void RenderViewImpl::swapBuffers() { -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL if (_mainWindow) glfwSwapBuffers(_mainWindow); #endif @@ -1268,12 +1269,32 @@ void RenderViewImpl::onGLFWKeyCallback(GLFWwindow* /*window*/, int key, int /*sc break; } } +#if defined(AX_PLATFORM_PC) && defined(_DEBUG) + else + { + auto director = Director::getInstance(); + switch (g_keyCodeMap[key]) + { + case EventKeyboard::KeyCode::KEY_SPACE: + if (director->isPaused()) + director->resume(); + else + director->pause(); + break; + case EventKeyboard::KeyCode::KEY_RIGHT_ARROW: + director->resume(); + director->getScheduler()->schedule([director](float) { director->pause(); + }, director, 0, 0, 0, false, "step"); + break; + } + } +#endif } void RenderViewImpl::onGLFWCharCallback(GLFWwindow* /*window*/, unsigned int charCode) { std::string utf8String; - StringUtils::UTF32ToUTF8(std::u32string_view{(char32_t*)&charCode, (size_t)1}, utf8String); + text_utils::UTF32ToUTF8(std::u32string_view{(char32_t*)&charCode, (size_t)1}, utf8String); static std::unordered_set controlUnicode = { "\xEF\x9C\x80", // up "\xEF\x9C\x81", // down @@ -1307,11 +1328,15 @@ void RenderViewImpl::onGLFWWindowSizeCallback(GLFWwindow* /*window*/, int w, int { handleWindowSize(w, h); -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL // update metal attachment texture size. int fbWidth, fbHeight; glfwGetFramebufferSize(_mainWindow, &fbWidth, &fbHeight); - backend::UtilsMTL::resizeDefaultAttachmentTexture(fbWidth, fbHeight); + rhi::mtl::UtilsMTL::resizeDefaultAttachmentTexture(fbWidth, fbHeight); +#elif AX_RENDER_API == AX_RENDER_API_D3D + int fbWidth, fbHeight; + glfwGetFramebufferSize(_mainWindow, &fbWidth, &fbHeight); + Director::getInstance()->getRenderer()->resizeSwapChain(fbWidth, fbHeight); #endif Size size(w, h); @@ -1353,13 +1378,13 @@ void RenderViewImpl::onGLFWWindowCloseCallback(GLFWwindow* window) } } -#if (AX_TARGET_PLATFORM != AX_PLATFORM_MAC) +#if AX_TARGET_PLATFORM != AX_PLATFORM_MAC && AX_RENDER_API == AX_RENDER_API_GL static bool loadFboExtensions() { // If the current opengl driver doesn't have framebuffers methods, check if an extension exists if (glGenFramebuffers == nullptr) { - auto driver = backend::DriverGL::getInstance(); + auto driver = rhi::DriverBase::getInstance(); AXLOGW("OpenGL: glGenFramebuffers is nullptr, try to detect an extension"); if (driver->hasExtension("ARB_framebuffer_object"sv)) { diff --git a/core/platform/RenderViewImpl.h b/axmol/platform/RenderViewImpl.h similarity index 97% rename from core/platform/RenderViewImpl.h rename to axmol/platform/RenderViewImpl.h index 997651a2edd1..32bfde498fcc 100644 --- a/core/platform/RenderViewImpl.h +++ b/axmol/platform/RenderViewImpl.h @@ -26,13 +26,13 @@ THE SOFTWARE. ****************************************************************************/ // Implement RenderView based on GLFW for targets: win32,osx,web(wasm) #pragma once -#include "platform/GL.h" -#include "base/Object.h" -#include "platform/Common.h" -#include "platform/RenderView.h" +#include "axmol/platform/GL.h" +#include "axmol/base/Object.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/RenderView.h" #include "GLFW/glfw3.h" #if defined(__EMSCRIPTEN__) -# include "base/axstd.h" +# include "axmol/base/axstd.h" struct EmscriptenMouseEvent; struct EmscriptenTouchEvent; #endif @@ -221,8 +221,4 @@ class AX_DLL RenderViewImpl : public RenderView AX_DISALLOW_COPY_AND_ASSIGN(RenderViewImpl); }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef RenderViewImpl GLViewImpl; -#endif - } // end of namespace ax diff --git a/core/platform/SAXParser.cpp b/axmol/platform/SAXParser.cpp similarity index 98% rename from core/platform/SAXParser.cpp rename to axmol/platform/SAXParser.cpp index 16252aff6109..b757bd7ccd81 100644 --- a/core/platform/SAXParser.cpp +++ b/axmol/platform/SAXParser.cpp @@ -27,11 +27,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/SAXParser.h" +#include "axmol/platform/SAXParser.h" #include // because its based on windows 8 build :P -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include "xsxml/xsxml.hpp" namespace ax diff --git a/core/platform/SAXParser.h b/axmol/platform/SAXParser.h similarity index 97% rename from core/platform/SAXParser.h rename to axmol/platform/SAXParser.h index e691abffc859..f7e2d5836049 100644 --- a/core/platform/SAXParser.h +++ b/axmol/platform/SAXParser.h @@ -26,8 +26,8 @@ /// @cond DO_NOT_SHOW -#include "platform/PlatformConfig.h" -#include "platform/Common.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/Common.h" #include namespace ax diff --git a/core/platform/StdC.h b/axmol/platform/StdC.h similarity index 83% rename from core/platform/StdC.h rename to axmol/platform/StdC.h index 8a47aff22b4d..a5c7661a17ef 100644 --- a/core/platform/StdC.h +++ b/axmol/platform/StdC.h @@ -26,18 +26,18 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_MAC -# include "platform/mac/StdC-mac.h" +# include "axmol/platform/mac/StdC-mac.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_IOS -# include "platform/ios/StdC-ios.h" +# include "axmol/platform/ios/StdC-ios.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID -# include "platform/android/StdC-android.h" +# include "axmol/platform/android/StdC-android.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 -# include "platform/win32/StdC-win32.h" +# include "axmol/platform/win32/StdC-win32.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_WINRT -# include "platform/winrt/StdC-winrt.h" +# include "axmol/platform/winrt/StdC-winrt.h" #elif AX_TARGET_PLATFORM == AX_PLATFORM_LINUX -# include "platform/linux/StdC-linux.h" +# include "axmol/platform/linux/StdC-linux.h" #endif diff --git a/core/platform/android/Application-android.cpp b/axmol/platform/android/Application-android.cpp similarity index 92% rename from core/platform/android/Application-android.cpp rename to axmol/platform/android/Application-android.cpp index 266b2109951f..cb646fcf7963 100644 --- a/core/platform/android/Application-android.cpp +++ b/axmol/platform/android/Application-android.cpp @@ -23,10 +23,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/jni/JniHelper.h" -#include "platform/Application.h" -#include "base/Director.h" -#include "base/Utils.h" +#include "axmol/platform/android/jni/JniHelper.h" +#include "axmol/platform/Application.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" #include #include #include @@ -79,12 +79,6 @@ Application* Application::getInstance() return sm_pSharedApplication; } -// @deprecated Use getInstance() instead -Application* Application::sharedApplication() -{ - return Application::getInstance(); -} - const char* Application::getCurrentLanguageCode() { static char code[3] = {0}; diff --git a/core/platform/android/Application-android.h b/axmol/platform/android/Application-android.h similarity index 83% rename from core/platform/android/Application-android.h rename to axmol/platform/android/Application-android.h index aa83d5f5c974..ea3285f7043d 100644 --- a/core/platform/android/Application-android.h +++ b/axmol/platform/android/Application-android.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" namespace ax { @@ -47,7 +47,7 @@ class AX_DLL Application : public ApplicationBase @brief Callback by Director to limit FPS. @param interval The time, expressed in seconds, between current frame and next. */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; /** @brief Run the message loop. @@ -59,38 +59,35 @@ class AX_DLL Application : public ApplicationBase @return Current application instance pointer. */ static Application* getInstance(); -#ifndef AX_CORE_PROFILE - /** @deprecated Use getInstance() instead */ - AX_DEPRECATED(2.1) static Application* sharedApplication(); -#endif + /** @brief Get current language config @return Current language config */ - virtual LanguageType getCurrentLanguage() override; + LanguageType getCurrentLanguage() override; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code */ - virtual const char* getCurrentLanguageCode() override; + const char* getCurrentLanguageCode() override; /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; /** @brief Get application version. */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser @param String with url to open. @return true if the resource located by the URL was successfully opened; otherwise false. */ - virtual bool openURL(std::string_view url) override; + bool openURL(std::string_view url) override; /** @brief This function will be called when the application screen size is changed. diff --git a/core/platform/android/CMakeLists.txt b/axmol/platform/android/CMakeLists.txt similarity index 100% rename from core/platform/android/CMakeLists.txt rename to axmol/platform/android/CMakeLists.txt diff --git a/core/platform/android/Common-android.cpp b/axmol/platform/android/Common-android.cpp similarity index 95% rename from core/platform/android/Common-android.cpp rename to axmol/platform/android/Common-android.cpp index e1380c15de5e..b535eb02c00e 100644 --- a/core/platform/android/Common-android.cpp +++ b/axmol/platform/android/Common-android.cpp @@ -23,8 +23,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" -#include "platform/android/jni/JniHelper.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/android/jni/JniHelper.h" #include #include #include diff --git a/core/platform/android/ControllerManualAdapter/AndroidManifest.xml b/axmol/platform/android/ControllerManualAdapter/AndroidManifest.xml similarity index 100% rename from core/platform/android/ControllerManualAdapter/AndroidManifest.xml rename to axmol/platform/android/ControllerManualAdapter/AndroidManifest.xml diff --git a/core/platform/android/ControllerManualAdapter/build.xml b/axmol/platform/android/ControllerManualAdapter/build.xml similarity index 100% rename from core/platform/android/ControllerManualAdapter/build.xml rename to axmol/platform/android/ControllerManualAdapter/build.xml diff --git a/core/platform/android/ControllerManualAdapter/libs/com.bda.controller.jar b/axmol/platform/android/ControllerManualAdapter/libs/com.bda.controller.jar similarity index 100% rename from core/platform/android/ControllerManualAdapter/libs/com.bda.controller.jar rename to axmol/platform/android/ControllerManualAdapter/libs/com.bda.controller.jar diff --git a/core/platform/android/ControllerManualAdapter/libs/nibiru_lib.jar b/axmol/platform/android/ControllerManualAdapter/libs/nibiru_lib.jar similarity index 100% rename from core/platform/android/ControllerManualAdapter/libs/nibiru_lib.jar rename to axmol/platform/android/ControllerManualAdapter/libs/nibiru_lib.jar diff --git a/core/platform/android/ControllerManualAdapter/libs/ouya-sdk.jar b/axmol/platform/android/ControllerManualAdapter/libs/ouya-sdk.jar similarity index 100% rename from core/platform/android/ControllerManualAdapter/libs/ouya-sdk.jar rename to axmol/platform/android/ControllerManualAdapter/libs/ouya-sdk.jar diff --git a/core/platform/android/ControllerManualAdapter/lint.xml b/axmol/platform/android/ControllerManualAdapter/lint.xml similarity index 100% rename from core/platform/android/ControllerManualAdapter/lint.xml rename to axmol/platform/android/ControllerManualAdapter/lint.xml diff --git a/core/platform/android/ControllerManualAdapter/proguard-project.txt b/axmol/platform/android/ControllerManualAdapter/proguard-project.txt similarity index 100% rename from core/platform/android/ControllerManualAdapter/proguard-project.txt rename to axmol/platform/android/ControllerManualAdapter/proguard-project.txt diff --git a/core/platform/android/ControllerManualAdapter/res/.gitignore b/axmol/platform/android/ControllerManualAdapter/res/.gitignore similarity index 100% rename from core/platform/android/ControllerManualAdapter/res/.gitignore rename to axmol/platform/android/ControllerManualAdapter/res/.gitignore diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerActivity.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerActivity.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerActivity.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerActivity.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerHelper.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerHelper.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerHelper.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerHelper.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerMoga.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerMoga.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerMoga.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerMoga.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerNibiru.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerNibiru.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerNibiru.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerNibiru.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerOuya.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerOuya.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerOuya.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/GameControllerOuya.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerCompat.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerCompat.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerCompat.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerCompat.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV16.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV16.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV16.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV16.java diff --git a/core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV9.java b/axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV9.java similarity index 100% rename from core/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV9.java rename to axmol/platform/android/ControllerManualAdapter/src/dev/axmol/lib/inputmanagercompat/InputManagerV9.java diff --git a/core/platform/android/Device-android.cpp b/axmol/platform/android/Device-android.cpp similarity index 95% rename from core/platform/android/Device-android.cpp rename to axmol/platform/android/Device-android.cpp index 49bd6f787a30..a7b82e3a02cf 100644 --- a/core/platform/android/Device-android.cpp +++ b/axmol/platform/android/Device-android.cpp @@ -24,13 +24,13 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Device.h" +#include "axmol/platform/Device.h" #include #include #include -#include "base/Types.h" -#include "platform/android/jni/JniHelper.h" -#include "platform/FileUtils.h" +#include "axmol/base/Types.h" +#include "axmol/platform/android/jni/JniHelper.h" +#include "axmol/platform/FileUtils.h" #include "yasio/string_view.hpp" static const char* deviceHelperClassName = "dev.axmol.lib.AxmolEngine"; @@ -124,12 +124,12 @@ class BitmapDC if (!methodInfo.env->CallStaticBooleanMethod( methodInfo.classID, methodInfo.methodID, strArray, jstrFont, textDefinition._fontSize, textDefinition._fontFillColor.r, textDefinition._fontFillColor.g, textDefinition._fontFillColor.b, - textDefinition._fontAlpha, eAlignMask, nWidth, nHeight, textDefinition._shadow._shadowEnabled, + textDefinition._fontFillColor.a, eAlignMask, nWidth, nHeight, textDefinition._shadow._shadowEnabled, textDefinition._shadow._shadowOffset.width, -textDefinition._shadow._shadowOffset.height, textDefinition._shadow._shadowBlur, textDefinition._shadow._shadowOpacity, textDefinition._stroke._strokeEnabled, textDefinition._stroke._strokeColor.r, textDefinition._stroke._strokeColor.g, textDefinition._stroke._strokeColor.b, - textDefinition._stroke._strokeAlpha, textDefinition._stroke._strokeSize, textDefinition._enableWrap, + textDefinition._stroke._strokeColor.a, textDefinition._stroke._strokeSize, textDefinition._enableWrap, textDefinition._overflow)) { return false; diff --git a/core/platform/android/FileUtils-android.cpp b/axmol/platform/android/FileUtils-android.cpp similarity index 97% rename from core/platform/android/FileUtils-android.cpp rename to axmol/platform/android/FileUtils-android.cpp index 76b6e3cc75aa..d8d669ba0d5d 100644 --- a/core/platform/android/FileUtils-android.cpp +++ b/axmol/platform/android/FileUtils-android.cpp @@ -24,11 +24,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/FileUtils-android.h" -#include "platform/Common.h" -#include "platform/android/jni/JniHelper.h" -#include "platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" -#include "base/ZipUtils.h" +#include "axmol/platform/android/FileUtils-android.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/android/jni/JniHelper.h" +#include "axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" +#include "axmol/base/ZipUtils.h" #include #include diff --git a/core/platform/android/FileUtils-android.h b/axmol/platform/android/FileUtils-android.h similarity index 80% rename from core/platform/android/FileUtils-android.h rename to axmol/platform/android/FileUtils-android.h index 660f3e908787..53b9a1168844 100644 --- a/core/platform/android/FileUtils-android.h +++ b/axmol/platform/android/FileUtils-android.h @@ -25,9 +25,9 @@ Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. ****************************************************************************/ #pragma once -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" #include #include #include @@ -63,16 +63,16 @@ class AX_DLL FileUtilsAndroid : public FileUtils /* override functions */ bool init() override; - virtual std::string getWritablePath() const override; + std::string getWritablePath() const override; std::string getNativeWritableAbsolutePath() const override; - virtual bool isAbsolutePath(std::string_view strPath) const override; + bool isAbsolutePath(std::string_view strPath) const override; - virtual int64_t getFileSize(std::string_view filepath) const override; - virtual std::vector listFiles(std::string_view dirPath) const override; + int64_t getFileSize(std::string_view filepath) const override; + std::vector listFiles(std::string_view dirPath) const override; private: - virtual bool isFileExistInternal(std::string_view strFilePath) const override; - virtual bool isDirectoryExistInternal(std::string_view dirPath) const override; + bool isFileExistInternal(std::string_view strFilePath) const override; + bool isDirectoryExistInternal(std::string_view dirPath) const override; static AAssetManager* assetmanager; static ZipFile* obbfile; diff --git a/core/platform/android/GL-android.h b/axmol/platform/android/GL-android.h similarity index 98% rename from core/platform/android/GL-android.h rename to axmol/platform/android/GL-android.h index d184d9ac4364..a49e0567a91b 100644 --- a/core/platform/android/GL-android.h +++ b/axmol/platform/android/GL-android.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "glad/gl.h" diff --git a/core/platform/android/RenderViewImpl-android.cpp b/axmol/platform/android/RenderViewImpl-android.cpp similarity index 97% rename from core/platform/android/RenderViewImpl-android.cpp rename to axmol/platform/android/RenderViewImpl-android.cpp index 01b654466caf..5b0b1aad1b20 100644 --- a/core/platform/android/RenderViewImpl-android.cpp +++ b/axmol/platform/android/RenderViewImpl-android.cpp @@ -24,11 +24,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/RenderViewImpl-android.h" -#include "base/Director.h" -#include "base/Macros.h" -#include "platform/android/jni/JniHelper.h" -#include "platform/GL.h" +#include "axmol/platform/android/RenderViewImpl-android.h" +#include "axmol/base/Director.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/android/jni/JniHelper.h" +#include "axmol/platform/GL.h" #include #include diff --git a/core/platform/android/RenderViewImpl-android.h b/axmol/platform/android/RenderViewImpl-android.h similarity index 91% rename from core/platform/android/RenderViewImpl-android.h rename to axmol/platform/android/RenderViewImpl-android.h index d59b8e024406..a2a97943bbfb 100644 --- a/core/platform/android/RenderViewImpl-android.h +++ b/axmol/platform/android/RenderViewImpl-android.h @@ -26,9 +26,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "base/Object.h" -#include "math/Math.h" -#include "platform/RenderView.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/platform/RenderView.h" namespace ax { @@ -46,7 +46,7 @@ class AX_DLL RenderViewImpl : public RenderView void end() override; void swapBuffers() override; void setIMEKeyboardState(bool bOpen) override; - virtual Rect getSafeAreaRect() const override; + Rect getSafeAreaRect() const override; void queueOperation(void (*op)(void*), void* param) override; @@ -58,8 +58,4 @@ class AX_DLL RenderViewImpl : public RenderView bool initWithFullScreen(std::string_view viewName); }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef RenderViewImpl GLViewImpl; -#endif - } diff --git a/core/platform/android/StdC-android.h b/axmol/platform/android/StdC-android.h similarity index 97% rename from core/platform/android/StdC-android.h rename to axmol/platform/android/StdC-android.h index 59e16321c8da..a57c9960efba 100644 --- a/core/platform/android/StdC-android.h +++ b/axmol/platform/android/StdC-android.h @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include #include diff --git a/core/platform/android/dsl/axmol.gradle b/axmol/platform/android/dsl/axmol.gradle similarity index 100% rename from core/platform/android/dsl/axmol.gradle rename to axmol/platform/android/dsl/axmol.gradle diff --git a/core/platform/android/java/AndroidManifest.xml b/axmol/platform/android/java/AndroidManifest.xml similarity index 100% rename from core/platform/android/java/AndroidManifest.xml rename to axmol/platform/android/java/AndroidManifest.xml diff --git a/core/platform/android/java/build.xml b/axmol/platform/android/java/build.xml similarity index 100% rename from core/platform/android/java/build.xml rename to axmol/platform/android/java/build.xml diff --git a/core/platform/android/java/libs/com.android.vending.expansion.zipfile.jar b/axmol/platform/android/java/libs/com.android.vending.expansion.zipfile.jar similarity index 100% rename from core/platform/android/java/libs/com.android.vending.expansion.zipfile.jar rename to axmol/platform/android/java/libs/com.android.vending.expansion.zipfile.jar diff --git a/core/platform/android/java/lint.xml b/axmol/platform/android/java/lint.xml similarity index 100% rename from core/platform/android/java/lint.xml rename to axmol/platform/android/java/lint.xml diff --git a/core/platform/android/java/proguard-project.txt b/axmol/platform/android/java/proguard-project.txt similarity index 100% rename from core/platform/android/java/proguard-project.txt rename to axmol/platform/android/java/proguard-project.txt diff --git a/core/platform/android/java/res/.gitignore b/axmol/platform/android/java/res/.gitignore similarity index 100% rename from core/platform/android/java/res/.gitignore rename to axmol/platform/android/java/res/.gitignore diff --git a/core/platform/android/java/src/com/enhance/gameservice/IGameTuningService.aidl b/axmol/platform/android/java/src/com/enhance/gameservice/IGameTuningService.aidl similarity index 100% rename from core/platform/android/java/src/com/enhance/gameservice/IGameTuningService.aidl rename to axmol/platform/android/java/src/com/enhance/gameservice/IGameTuningService.aidl diff --git a/core/platform/android/java/src/com/jakewharton/processphoenix/ProcessPhoenix.java b/axmol/platform/android/java/src/com/jakewharton/processphoenix/ProcessPhoenix.java similarity index 100% rename from core/platform/android/java/src/com/jakewharton/processphoenix/ProcessPhoenix.java rename to axmol/platform/android/java/src/com/jakewharton/processphoenix/ProcessPhoenix.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolAccelerometer.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolAccelerometer.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolAccelerometer.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolAccelerometer.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolActivity.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolActivity.java similarity index 98% rename from core/platform/android/java/src/dev/axmol/lib/AxmolActivity.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolActivity.java index db26b6944e34..e378ea2f565e 100644 --- a/core/platform/android/java/src/dev/axmol/lib/AxmolActivity.java +++ b/axmol/platform/android/java/src/dev/axmol/lib/AxmolActivity.java @@ -25,13 +25,11 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ package dev.axmol.lib; -import android.app.Activity; import android.app.KeyguardManager; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; -import android.graphics.PixelFormat; import android.media.AudioManager; import android.opengl.GLSurfaceView; import android.os.Build; @@ -46,14 +44,15 @@ of this software and associated documentation files (the "Software"), to deal import android.view.Window; import android.view.WindowManager; +import androidx.appcompat.app.AppCompatActivity; + import dev.axmol.lib.AxmolEngine.AxmolEngineListener; import javax.microedition.khronos.egl.EGL10; import javax.microedition.khronos.egl.EGLConfig; import javax.microedition.khronos.egl.EGLDisplay; -import javax.microedition.khronos.egl.EGLContext; -public abstract class AxmolActivity extends Activity implements AxmolEngineListener { +public abstract class AxmolActivity extends AppCompatActivity implements AxmolEngineListener { // =========================================================== // Constants // =========================================================== diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolEditBox.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolEditBox.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolEditBox.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolEditBox.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolEngine.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolEngine.java similarity index 99% rename from core/platform/android/java/src/dev/axmol/lib/AxmolEngine.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolEngine.java index 3a47213ca26b..2bad71c9f9cb 100644 --- a/core/platform/android/java/src/dev/axmol/lib/AxmolEngine.java +++ b/axmol/platform/android/java/src/dev/axmol/lib/AxmolEngine.java @@ -30,7 +30,6 @@ of this software and associated documentation files (the "Software"), to deal import android.content.pm.PackageManager; import android.graphics.Rect; import android.media.AudioManager; -import android.app.Activity; import android.content.ComponentName; import android.content.Context; import android.content.Intent; @@ -59,6 +58,8 @@ of this software and associated documentation files (the "Software"), to deal import android.view.WindowInsets; import android.view.WindowManager; +import androidx.appcompat.app.AppCompatActivity; + import com.android.vending.expansion.zipfile.APKExpansionSupport; import com.android.vending.expansion.zipfile.ZipResourceFile; @@ -95,7 +96,7 @@ public class AxmolEngine { private static boolean sCompassEnabled; private static boolean sActivityVisible; private static String sPackageName; - private static Activity sActivity = null; + private static AppCompatActivity sActivity = null; private static AxmolEngineListener sAxmolEngineListener; private static Set onActivityResultListeners = new LinkedHashSet(); private static Vibrator sVibrateService = null; @@ -128,7 +129,7 @@ public void run() { } private static boolean sInited = false; - public static void init(final Activity activity) { + public static void init(final AppCompatActivity activity) { sActivity = activity; AxmolEngine.sAxmolEngineListener = (AxmolEngineListener)activity; if (!sInited) { @@ -202,7 +203,7 @@ public static ZipResourceFile getObbFile() { return sOBBFile; } - public static Activity getActivity() { + public static AppCompatActivity getActivity() { return sActivity; } diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolGLSurfaceView.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolGLSurfaceView.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolGLSurfaceView.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolGLSurfaceView.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolHandler.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolHandler.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolHandler.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolHandler.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java similarity index 99% rename from core/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java index 58018a14c7eb..d4318a3dd9df 100644 --- a/core/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java +++ b/axmol/platform/android/java/src/dev/axmol/lib/AxmolMediaEngine.java @@ -23,7 +23,6 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ package dev.axmol.lib; -import android.app.Activity; import android.content.Context; import android.media.MediaCodecInfo; import android.media.MediaFormat; @@ -32,6 +31,7 @@ of this software and associated documentation files (the "Software"), to deal import android.util.Log; import androidx.annotation.Nullable; +import androidx.appcompat.app.AppCompatActivity; import androidx.media3.common.Format; import androidx.media3.common.MediaItem; import androidx.media3.common.PlaybackException; @@ -127,7 +127,7 @@ public class AxmolMediaEngine extends DefaultRenderersFactory implements Player. public static native void nativeStoreCurrentTime(long nativeObj, double currentTime); - public static void setContext(Activity activity) { + public static void setContext(AppCompatActivity activity) { sContext = activity.getApplicationContext(); } diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolRenderer.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolRenderer.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolRenderer.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolRenderer.java diff --git a/core/platform/android/java/src/dev/axmol/lib/AxmolWebView.java b/axmol/platform/android/java/src/dev/axmol/lib/AxmolWebView.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/AxmolWebView.java rename to axmol/platform/android/java/src/dev/axmol/lib/AxmolWebView.java diff --git a/core/platform/android/java/src/dev/axmol/lib/BitmapHelper.java b/axmol/platform/android/java/src/dev/axmol/lib/BitmapHelper.java similarity index 99% rename from core/platform/android/java/src/dev/axmol/lib/BitmapHelper.java rename to axmol/platform/android/java/src/dev/axmol/lib/BitmapHelper.java index a096383bb9ca..a54b7a74c1b3 100644 --- a/core/platform/android/java/src/dev/axmol/lib/BitmapHelper.java +++ b/axmol/platform/android/java/src/dev/axmol/lib/BitmapHelper.java @@ -47,7 +47,7 @@ public final class BitmapHelper { // Constants // =========================================================== - /* The values are the same as core/platform/Image.h. */ + /* The values are the same as axmol/platform/Image.h. */ private static final int HORIZONTAL_ALIGN_LEFT = 1; private static final int HORIZONTAL_ALIGN_RIGHT = 2; private static final int HORIZONTAL_ALIGN_CENTER = 3; diff --git a/core/platform/android/java/src/dev/axmol/lib/EditBoxHelper.java b/axmol/platform/android/java/src/dev/axmol/lib/EditBoxHelper.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/EditBoxHelper.java rename to axmol/platform/android/java/src/dev/axmol/lib/EditBoxHelper.java diff --git a/core/platform/android/java/src/dev/axmol/lib/GameControllerAdapter.java b/axmol/platform/android/java/src/dev/axmol/lib/GameControllerAdapter.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/GameControllerAdapter.java rename to axmol/platform/android/java/src/dev/axmol/lib/GameControllerAdapter.java diff --git a/core/platform/android/java/src/dev/axmol/lib/GameControllerDelegate.java b/axmol/platform/android/java/src/dev/axmol/lib/GameControllerDelegate.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/GameControllerDelegate.java rename to axmol/platform/android/java/src/dev/axmol/lib/GameControllerDelegate.java diff --git a/core/platform/android/java/src/dev/axmol/lib/GameControllerUtils.java b/axmol/platform/android/java/src/dev/axmol/lib/GameControllerUtils.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/GameControllerUtils.java rename to axmol/platform/android/java/src/dev/axmol/lib/GameControllerUtils.java diff --git a/core/platform/android/java/src/dev/axmol/lib/LuaBridge.java b/axmol/platform/android/java/src/dev/axmol/lib/LuaBridge.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/LuaBridge.java rename to axmol/platform/android/java/src/dev/axmol/lib/LuaBridge.java diff --git a/core/platform/android/java/src/dev/axmol/lib/MediaCodecVideoRenderer.java b/axmol/platform/android/java/src/dev/axmol/lib/MediaCodecVideoRenderer.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/MediaCodecVideoRenderer.java rename to axmol/platform/android/java/src/dev/axmol/lib/MediaCodecVideoRenderer.java diff --git a/core/platform/android/java/src/dev/axmol/lib/ReflectionHelper.java b/axmol/platform/android/java/src/dev/axmol/lib/ReflectionHelper.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/ReflectionHelper.java rename to axmol/platform/android/java/src/dev/axmol/lib/ReflectionHelper.java diff --git a/core/platform/android/java/src/dev/axmol/lib/ResizeLayout.java b/axmol/platform/android/java/src/dev/axmol/lib/ResizeLayout.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/ResizeLayout.java rename to axmol/platform/android/java/src/dev/axmol/lib/ResizeLayout.java diff --git a/core/platform/android/java/src/dev/axmol/lib/TextInputWrapper.java b/axmol/platform/android/java/src/dev/axmol/lib/TextInputWrapper.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/TextInputWrapper.java rename to axmol/platform/android/java/src/dev/axmol/lib/TextInputWrapper.java diff --git a/core/platform/android/java/src/dev/axmol/lib/TypefaceHelper.java b/axmol/platform/android/java/src/dev/axmol/lib/TypefaceHelper.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/TypefaceHelper.java rename to axmol/platform/android/java/src/dev/axmol/lib/TypefaceHelper.java diff --git a/core/platform/android/java/src/dev/axmol/lib/WebViewHelper.java b/axmol/platform/android/java/src/dev/axmol/lib/WebViewHelper.java similarity index 100% rename from core/platform/android/java/src/dev/axmol/lib/WebViewHelper.java rename to axmol/platform/android/java/src/dev/axmol/lib/WebViewHelper.java diff --git a/core/platform/android/javaactivity-android.cpp b/axmol/platform/android/javaactivity-android.cpp similarity index 92% rename from core/platform/android/javaactivity-android.cpp rename to axmol/platform/android/javaactivity-android.cpp index b9e490e94622..090cc5e7b321 100644 --- a/core/platform/android/javaactivity-android.cpp +++ b/axmol/platform/android/javaactivity-android.cpp @@ -23,15 +23,15 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/Application-android.h" -#include "platform/android/RenderViewImpl-android.h" -#include "base/Director.h" -#include "base/EventCustom.h" -#include "base/EventType.h" -#include "base/EventDispatcher.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/TextureCache.h" -#include "platform/android/jni/JniHelper.h" +#include "axmol/platform/android/Application-android.h" +#include "axmol/platform/android/RenderViewImpl-android.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventType.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/platform/android/jni/JniHelper.h" #include #include @@ -96,7 +96,7 @@ JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeInit(JNIEnv*, jcla } else { - backend::DriverBase::getInstance()->resetState(); + rhi::DriverBase::getInstance()->resetState(); director->resetMatrixStack(); ax::EventCustom recreatedEvent(EVENT_RENDERER_RECREATED); director->getEventDispatcher()->dispatchEvent(&recreatedEvent, true); diff --git a/core/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp similarity index 95% rename from core/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp rename to axmol/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp index 2de645030fcd..09b960c20aed 100644 --- a/core/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp +++ b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolAccelerometer.cpp @@ -24,9 +24,9 @@ ****************************************************************************/ #include -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/EventAcceleration.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventAcceleration.h" #define TG3_GRAVITY_EARTH (9.80665f) diff --git a/core/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp similarity index 97% rename from core/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp rename to axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp index 60e7ffd31ce2..4d0d67450a55 100644 --- a/core/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp +++ b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.cpp @@ -27,11 +27,11 @@ THE SOFTWARE. #include #include #include -#include "platform/android/jni/JniHelper.h" -#include "platform/android/FileUtils-android.h" -#include "platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" +#include "axmol/platform/android/jni/JniHelper.h" +#include "axmol/platform/android/FileUtils-android.h" +#include "axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h" -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" #define LOG_TAG "Java_dev_axmol_lib_AxmolEngine.cpp" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) diff --git a/core/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h similarity index 100% rename from core/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h rename to axmol/platform/android/jni/Java_dev_axmol_lib_AxmolEngine.h diff --git a/core/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp similarity index 87% rename from core/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp rename to axmol/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp index d316d1ce749b..6008df436651 100644 --- a/core/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp +++ b/axmol/platform/android/jni/Java_dev_axmol_lib_AxmolRenderer.cpp @@ -23,16 +23,16 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/IMEDispatcher.h" -#include "base/Director.h" -#include "base/EventType.h" -#include "base/EventCustom.h" -#include "base/EventDispatcher.h" -#include "platform/Application.h" -#include "platform/FileUtils.h" +#include "axmol/base/IMEDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventType.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/platform/Application.h" +#include "axmol/platform/FileUtils.h" #include -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" using namespace ax; @@ -65,7 +65,7 @@ JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeOnResume(JNIEnv*, JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeInsertText(JNIEnv* env, jclass, jstring text) { - std::string strValue = ax::StringUtils::getStringUTFCharsJNI(env, text); + std::string strValue = ax::text_utils::getStringUTFCharsJNI(env, text); const char* pszText = strValue.c_str(); ax::IMEDispatcher::sharedDispatcher()->dispatchInsertText(pszText, strlen(pszText)); } @@ -78,6 +78,6 @@ JNIEXPORT void JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeDeleteBackward(JNI JNIEXPORT jstring JNICALL Java_dev_axmol_lib_AxmolRenderer_nativeGetContentText(JNIEnv* env, jclass) { auto pszText = ax::IMEDispatcher::sharedDispatcher()->getContentText(); - return ax::StringUtils::newStringUTFJNI(env, pszText); + return ax::text_utils::newStringUTFJNI(env, pszText); } } diff --git a/core/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp b/axmol/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp similarity index 90% rename from core/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp rename to axmol/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp index 674cd11bcd3c..4994d9b3dc5c 100644 --- a/core/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp +++ b/axmol/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.cpp @@ -24,12 +24,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/jni/JniHelper.h" +#include "axmol/platform/android/jni/JniHelper.h" #include -#include "base/Director.h" -#include "platform/Application.h" -#include "platform/FileUtils.h" -#include "base/UTF8.h" +#include "axmol/base/Director.h" +#include "axmol/platform/Application.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/text_utils.h" static const char* className = "dev.axmol.lib.BitmapHelper"; diff --git a/core/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.h b/axmol/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.h similarity index 100% rename from core/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.h rename to axmol/platform/android/jni/Java_dev_axmol_lib_BitmapHelper.h diff --git a/core/platform/android/jni/JniHelper.cpp b/axmol/platform/android/jni/JniHelper.cpp similarity index 97% rename from core/platform/android/jni/JniHelper.cpp rename to axmol/platform/android/jni/JniHelper.cpp index f99b7731ab3c..c81f4a00ce7c 100644 --- a/core/platform/android/jni/JniHelper.cpp +++ b/axmol/platform/android/jni/JniHelper.cpp @@ -24,12 +24,12 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/android/jni/JniHelper.h" +#include "axmol/platform/android/jni/JniHelper.h" #include #include #include -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" #define LOG_TAG "JniHelper" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) @@ -307,14 +307,14 @@ std::string JniHelper::jstring2string(jstring jstr) return ""; } - std::string strValue = ax::StringUtils::getStringUTFCharsJNI(env, jstr); + std::string strValue = ax::text_utils::getStringUTFCharsJNI(env, jstr); return strValue; } jstring JniHelper::convert(LocalRefMapType& localRefs, ax::JniMethodInfo& t, const char* x) { - jstring ret = ax::StringUtils::newStringUTFJNI(t.env, x ? x : ""); + jstring ret = ax::text_utils::newStringUTFJNI(t.env, x ? x : ""); localRefs[t.env].emplace_back(ret); return ret; } diff --git a/core/platform/android/jni/JniHelper.h b/axmol/platform/android/jni/JniHelper.h similarity index 99% rename from core/platform/android/jni/JniHelper.h rename to axmol/platform/android/jni/JniHelper.h index a0b3f7da28ca..a49557e0f917 100644 --- a/core/platform/android/jni/JniHelper.h +++ b/axmol/platform/android/jni/JniHelper.h @@ -32,10 +32,10 @@ THE SOFTWARE. #include #include #include -#include "platform/PlatformMacros.h" -#include "math/Vec3.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/math/Vec3.h" #include "jni/jni.hpp" -#include "base/axstd.h" +#include "axmol/base/axstd.h" namespace jni { diff --git a/core/platform/android/jni/TouchesJni.cpp b/axmol/platform/android/jni/TouchesJni.cpp similarity index 96% rename from core/platform/android/jni/TouchesJni.cpp rename to axmol/platform/android/jni/TouchesJni.cpp index 28505fbdbfc7..7223d5437615 100644 --- a/core/platform/android/jni/TouchesJni.cpp +++ b/axmol/platform/android/jni/TouchesJni.cpp @@ -22,10 +22,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Director.h" -#include "base/EventKeyboard.h" -#include "base/EventDispatcher.h" -#include "platform/android/RenderViewImpl-android.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/platform/android/RenderViewImpl-android.h" #include #include diff --git a/core/platform/android/libaxmol-with-controller/.gitignore b/axmol/platform/android/libaxmol-with-controller/.gitignore similarity index 100% rename from core/platform/android/libaxmol-with-controller/.gitignore rename to axmol/platform/android/libaxmol-with-controller/.gitignore diff --git a/core/platform/android/libaxmol-with-controller/AndroidManifest.xml b/axmol/platform/android/libaxmol-with-controller/AndroidManifest.xml similarity index 100% rename from core/platform/android/libaxmol-with-controller/AndroidManifest.xml rename to axmol/platform/android/libaxmol-with-controller/AndroidManifest.xml diff --git a/core/platform/android/libaxmol-with-controller/build.gradle b/axmol/platform/android/libaxmol-with-controller/build.gradle similarity index 100% rename from core/platform/android/libaxmol-with-controller/build.gradle rename to axmol/platform/android/libaxmol-with-controller/build.gradle diff --git a/core/platform/android/libaxmol-with-controller/proguard-rules.pro b/axmol/platform/android/libaxmol-with-controller/proguard-rules.pro similarity index 100% rename from core/platform/android/libaxmol-with-controller/proguard-rules.pro rename to axmol/platform/android/libaxmol-with-controller/proguard-rules.pro diff --git a/core/platform/android/libaxmol/.gitignore b/axmol/platform/android/libaxmol/.gitignore similarity index 100% rename from core/platform/android/libaxmol/.gitignore rename to axmol/platform/android/libaxmol/.gitignore diff --git a/core/platform/android/libaxmol/AndroidManifest.xml b/axmol/platform/android/libaxmol/AndroidManifest.xml similarity index 100% rename from core/platform/android/libaxmol/AndroidManifest.xml rename to axmol/platform/android/libaxmol/AndroidManifest.xml diff --git a/core/platform/android/libaxmol/build.gradle b/axmol/platform/android/libaxmol/build.gradle similarity index 97% rename from core/platform/android/libaxmol/build.gradle rename to axmol/platform/android/libaxmol/build.gradle index 60cbcbf6f9e0..7a874dffa98c 100644 --- a/core/platform/android/libaxmol/build.gradle +++ b/axmol/platform/android/libaxmol/build.gradle @@ -55,6 +55,7 @@ dependencies { //api "androidx.media3:media3-exoplayer-ima:$media3_version" implementation "androidx.annotation:annotation:$annotation_ver" + implementation "androidx.appcompat:appcompat:$appcompat_ver" api ("com.google.guava:guava:$guava_ver-android") { // Exclude dependencies that are only used by Guava at compile time diff --git a/core/platform/android/libaxmol/proguard-rules.pro b/axmol/platform/android/libaxmol/proguard-rules.pro similarity index 100% rename from core/platform/android/libaxmol/proguard-rules.pro rename to axmol/platform/android/libaxmol/proguard-rules.pro diff --git a/core/platform/apple/Device-apple.h b/axmol/platform/apple/Device-apple.h similarity index 97% rename from core/platform/apple/Device-apple.h rename to axmol/platform/apple/Device-apple.h index 8193436fae2f..b166124e02dc 100644 --- a/core/platform/apple/Device-apple.h +++ b/axmol/platform/apple/Device-apple.h @@ -26,7 +26,7 @@ #pragma once -#include "platform/Device.h" +#include "axmol/platform/Device.h" namespace FontUtils { diff --git a/core/platform/apple/Device-apple.mm b/axmol/platform/apple/Device-apple.mm similarity index 94% rename from core/platform/apple/Device-apple.mm rename to axmol/platform/apple/Device-apple.mm index 9b654b94c948..3501477c61dc 100644 --- a/core/platform/apple/Device-apple.mm +++ b/axmol/platform/apple/Device-apple.mm @@ -24,8 +24,8 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" -#include "platform/Device.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/Device.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_MAC @@ -39,8 +39,8 @@ of this software and associated documentation files (the "Software"), to deal #endif -#include "base/Types.h" -#include "platform/apple/Device-apple.h" +#include "axmol/base/Types.h" +#include "axmol/platform/apple/Device-apple.h" namespace FontUtils { diff --git a/core/platform/apple/FileUtils-apple.h b/axmol/platform/apple/FileUtils-apple.h similarity index 82% rename from core/platform/apple/FileUtils-apple.h rename to axmol/platform/apple/FileUtils-apple.h index b247f58f752e..6fa47775af06 100644 --- a/core/platform/apple/FileUtils-apple.h +++ b/axmol/platform/apple/FileUtils-apple.h @@ -30,9 +30,9 @@ #include #include -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" namespace ax { @@ -49,10 +49,10 @@ class AX_DLL FileUtilsApple : public FileUtils FileUtilsApple(); virtual ~FileUtilsApple(); - virtual bool init() override; + bool init() override; - virtual std::string getWritablePath() const override; - virtual std::string getNativeWritableAbsolutePath() const override; + std::string getWritablePath() const override; + std::string getNativeWritableAbsolutePath() const override; virtual std::string getFullPathForFilenameWithinDirectory(std::string_view directory, std::string_view filename) const override; @@ -60,13 +60,13 @@ class AX_DLL FileUtilsApple : public FileUtils void setBundle(NSBundle* bundle); #endif - virtual bool createDirectories(std::string_view path) const override; + bool createDirectories(std::string_view path) const override; virtual std::string getPathForDirectory(std::string_view dir, std::string_view searchPath) const override; private: - virtual bool isFileExistInternal(std::string_view filePath) const override; - virtual bool removeDirectory(std::string_view dirPath) const override; + bool isFileExistInternal(std::string_view filePath) const override; + bool removeDirectory(std::string_view dirPath) const override; struct IMPL; std::unique_ptr pimpl_; diff --git a/core/platform/apple/FileUtils-apple.mm b/axmol/platform/apple/FileUtils-apple.mm similarity index 98% rename from core/platform/apple/FileUtils-apple.mm rename to axmol/platform/apple/FileUtils-apple.mm index 450a0a5d871f..2a2e47cfe2c2 100644 --- a/core/platform/apple/FileUtils-apple.mm +++ b/axmol/platform/apple/FileUtils-apple.mm @@ -27,15 +27,15 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import -#include "platform/apple/FileUtils-apple.h" +#include "axmol/platform/apple/FileUtils-apple.h" #include #include #include -#include "base/Director.h" -#include "platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/core/platform/ios/Application-ios.h b/axmol/platform/ios/Application-ios.h similarity index 87% rename from core/platform/ios/Application-ios.h rename to axmol/platform/ios/Application-ios.h index 636e2229ac4b..b3e1279a2a3e 100644 --- a/core/platform/ios/Application-ios.h +++ b/axmol/platform/ios/Application-ios.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" namespace ax { @@ -58,36 +58,36 @@ class AX_DLL Application : public ApplicationBase @brief Callback by Director for limit FPS. @param interval The time, expressed in seconds, between current frame and next. */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; /** @brief Get current language config @return Current language config */ - virtual LanguageType getCurrentLanguage() override; + LanguageType getCurrentLanguage() override; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code */ - virtual const char* getCurrentLanguageCode() override; + const char* getCurrentLanguageCode() override; /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; /** @brief Get application version. */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser @param String with url to open. @return true if the resource located by the URL was successfully opened; otherwise false. */ - virtual bool openURL(std::string_view url) override; + bool openURL(std::string_view url) override; /** @brief This function will be called when the application screen size is changed. diff --git a/core/platform/ios/Application-ios.mm b/axmol/platform/ios/Application-ios.mm similarity index 96% rename from core/platform/ios/Application-ios.mm rename to axmol/platform/ios/Application-ios.mm index 44ce7cdd4cfd..9f25e7cc311e 100644 --- a/core/platform/ios/Application-ios.mm +++ b/axmol/platform/ios/Application-ios.mm @@ -23,13 +23,13 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#import "Application.h" +#import "axmol/platform/Application.h" #import -#import "math/Math.h" -#import "platform/ios/DirectorCaller-ios.h" -#import "base/Utils.h" +#import "axmol/math/Math.h" +#import "axmol/platform/ios/DirectorCaller-ios.h" +#import "axmol/base/Utils.h" namespace ax { diff --git a/core/platform/ios/Common-ios.mm b/axmol/platform/ios/Common-ios.mm similarity index 96% rename from core/platform/ios/Common-ios.mm rename to axmol/platform/ios/Common-ios.mm index e7ea39ec2952..6cdeb5cda7b0 100644 --- a/core/platform/ios/Common-ios.mm +++ b/axmol/platform/ios/Common-ios.mm @@ -23,15 +23,15 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" +#include "axmol/platform/Common.h" #include #include #import #import -#include "base/Director.h" -#include "base/Logging.h" +#include "axmol/base/Director.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/platform/ios/Device-ios.mm b/axmol/platform/ios/Device-ios.mm similarity index 98% rename from core/platform/ios/Device-ios.mm rename to axmol/platform/ios/Device-ios.mm index 7c4494242851..2c60ac7b7751 100644 --- a/core/platform/ios/Device-ios.mm +++ b/axmol/platform/ios/Device-ios.mm @@ -26,12 +26,12 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import -#include "platform/Device.h" -#include "base/Types.h" -#include "base/EventDispatcher.h" -#include "base/EventAcceleration.h" -#include "base/Director.h" -#include "platform/apple/Device-apple.h" +#include "axmol/platform/Device.h" +#include "axmol/base/Types.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventAcceleration.h" +#include "axmol/base/Director.h" +#include "axmol/platform/apple/Device-apple.h" // Accelerometer #if !defined(AX_TARGET_OS_TVOS) @@ -627,12 +627,12 @@ static bool _initWithString(std::string_view text, info.strokeColorR = textDefinition._stroke._strokeColor.r / 255.0f; info.strokeColorG = textDefinition._stroke._strokeColor.g / 255.0f; info.strokeColorB = textDefinition._stroke._strokeColor.b / 255.0f; - info.strokeColorA = textDefinition._stroke._strokeAlpha / 255.0f; + info.strokeColorA = textDefinition._stroke._strokeColor.a / 255.0f; info.strokeSize = textDefinition._stroke._strokeSize; info.tintColorR = textDefinition._fontFillColor.r / 255.0f; info.tintColorG = textDefinition._fontFillColor.g / 255.0f; info.tintColorB = textDefinition._fontFillColor.b / 255.0f; - info.tintColorA = textDefinition._fontAlpha / 255.0f; + info.tintColorA = textDefinition._fontFillColor.a / 255.0f; if (!_initWithString(text, align, textDefinition._fontName.c_str(), textDefinition._fontSize, &info, textDefinition._enableWrap, textDefinition._overflow)) diff --git a/core/platform/ios/DirectorCaller-ios.h b/axmol/platform/ios/DirectorCaller-ios.h similarity index 100% rename from core/platform/ios/DirectorCaller-ios.h rename to axmol/platform/ios/DirectorCaller-ios.h diff --git a/core/platform/ios/DirectorCaller-ios.mm b/axmol/platform/ios/DirectorCaller-ios.mm similarity index 97% rename from core/platform/ios/DirectorCaller-ios.mm rename to axmol/platform/ios/DirectorCaller-ios.mm index e62622de0b3b..d84f5ceff6ef 100644 --- a/core/platform/ios/DirectorCaller-ios.mm +++ b/axmol/platform/ios/DirectorCaller-ios.mm @@ -25,13 +25,13 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #include -#import "platform/ios/DirectorCaller-ios.h" +#import "axmol/platform/ios/DirectorCaller-ios.h" #import #import -#import "base/Director.h" -#import "platform/ios/EARenderView-ios.h" +#import "axmol/base/Director.h" +#import "axmol/platform/ios/EARenderView-ios.h" static id s_sharedDirectorCaller; diff --git a/core/platform/ios/EARenderView-ios.h b/axmol/platform/ios/EARenderView-ios.h similarity index 98% rename from core/platform/ios/EARenderView-ios.h rename to axmol/platform/ios/EARenderView-ios.h index c24aab251081..63d586b70d2d 100644 --- a/core/platform/ios/EARenderView-ios.h +++ b/axmol/platform/ios/EARenderView-ios.h @@ -66,13 +66,13 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #import -#import "platform/PlatformConfig.h" +#import "axmol/platform/PlatformConfig.h" #if AX_GLES_PROFILE # import # import # import # import -# import "platform/ios/ESRenderer-ios.h" +# import "axmol/platform/ios/ESRenderer-ios.h" #endif // CLASS INTERFACE: diff --git a/core/platform/ios/EARenderView-ios.mm b/axmol/platform/ios/EARenderView-ios.mm similarity index 96% rename from core/platform/ios/EARenderView-ios.mm rename to axmol/platform/ios/EARenderView-ios.mm index 18480ad8dff2..9e47ef89e95d 100644 --- a/core/platform/ios/EARenderView-ios.mm +++ b/axmol/platform/ios/EARenderView-ios.mm @@ -60,23 +60,23 @@ CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE Copyright (C) 2008 Apple Inc. All Rights Reserved. */ -#import "platform/ios/EARenderView-ios.h" +#import "axmol/platform/ios/EARenderView-ios.h" #import -#import "base/Director.h" -#import "base/Touch.h" -#import "base/IMEDispatcher.h" -#import "platform/ios/InputView-ios.h" +#import "axmol/base/Director.h" +#import "axmol/base/Touch.h" +#import "axmol/base/IMEDispatcher.h" +#import "axmol/platform/ios/InputView-ios.h" -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL # import -# import "renderer/backend/metal/DriverMTL.h" -# import "renderer/backend/metal/UtilsMTL.h" +# import "axmol/rhi/metal/DriverMTL.h" +# import "axmol/rhi/metal/UtilsMTL.h" #else -# import "platform/ios/RenderViewImpl-ios.h" -# import "platform/ios/ES3Renderer-ios.h" -# import "platform/ios/OpenGL_Internal-ios.h" +# import "axmol/platform/ios/RenderViewImpl-ios.h" +# import "axmol/platform/ios/ES3Renderer-ios.h" +# import "axmol/platform/ios/OpenGL_Internal-ios.h" #endif // CLASS IMPLEMENTATIONS: @@ -94,7 +94,7 @@ @implementation EARenderView @synthesize surfaceSize = size_; @synthesize pixelFormat = pixelformat_, depthFormat = depthFormat_; -#if !defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_GL @synthesize context = context_; #endif @synthesize multiSampling = multiSampling_; @@ -104,7 +104,7 @@ @implementation EARenderView + (Class)layerClass { -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL return [CAMetalLayer class]; #else return [CAEAGLLayer class]; @@ -191,7 +191,7 @@ - (id)initWithFrame:(CGRect)frame self.contentScaleFactor = [[UIScreen mainScreen] scale]; } -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL AX_UNUSED_PARAM(format); AX_UNUSED_PARAM(depth); AX_UNUSED_PARAM(sharegroup); @@ -205,7 +205,7 @@ - (id)initWithFrame:(CGRect)frame metalLayer.device = device; metalLayer.pixelFormat = MTLPixelFormatBGRA8Unorm; metalLayer.framebufferOnly = YES; - ax::backend::DriverMTL::setCAMetalLayer(metalLayer); + ax::rhi::mtl::DriverImpl::setCAMetalLayer(metalLayer); #else pixelformat_ = format; depthFormat_ = depth; @@ -228,7 +228,7 @@ - (id)initWithCoder:(NSCoder*)aDecoder if ((self = [super initWithCoder:aDecoder])) { self.textInputView = [[TextInputView alloc] initWithCoder:aDecoder]; -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL size_ = [self bounds].size; #else CAEAGLLayer* eaglLayer = (CAEAGLLayer*)[self layer]; @@ -262,11 +262,11 @@ - (int)getHeight return (int)bound.height * self.contentScaleFactor; } -#if !defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_GL - (BOOL)setupSurfaceWithSharegroup:(void*)sharegroup { CAEAGLLayer* eaglLayer = (CAEAGLLayer*)self.layer; - + NSString* platformPF = pixelformat_ == (int)ax::PixelFormat::RGB565 ? kEAGLColorFormatRGB565 : kEAGLColorFormatRGBA8; eaglLayer.opaque = YES; @@ -304,7 +304,7 @@ - (BOOL)setupSurfaceWithSharegroup:(void*)sharegroup - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; // remove keyboard notification -#if !defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_GL [renderer_ release]; #endif [self.textInputView release]; @@ -316,11 +316,11 @@ - (void)layoutSubviews if (!ax::Director::getInstance()->isValid()) return; -#if defined(AX_USE_METAL) +#if AX_RENDER_API == AX_RENDER_API_MTL size_ = [self bounds].size; size_.width *= self.contentScaleFactor; size_.height *= self.contentScaleFactor; - ax::backend::UtilsMTL::resizeDefaultAttachmentTexture(size_.width, size_.height); + ax::rhi::mtl::UtilsMTL::resizeDefaultAttachmentTexture(size_.width, size_.height); #else [renderer_ resizeFromLayer:(CAEAGLLayer*)self.layer]; size_ = [renderer_ backingSize]; @@ -341,12 +341,9 @@ - (void)layoutSubviews } } -#if defined(AX_USE_METAL) -- (void)swapBuffers -{} -#else - (void)swapBuffers { +#if AX_RENDER_API == AX_RENDER_API_GL // IMPORTANT: // - preconditions // -> context_ MUST be the OpenGL context @@ -357,7 +354,7 @@ - (void)swapBuffers if (multiSampling_) { /* Resolve from msaaFramebuffer to resolveFramebuffer */ - // __gl.disableStencilTest(); + // __state.disableStencilTest(); glBindFramebuffer(GL_READ_FRAMEBUFFER_APPLE, [renderer_ msaaFrameBuffer]); glBindFramebuffer(GL_DRAW_FRAMEBUFFER_APPLE, [renderer_ defaultFrameBuffer]); glResolveMultisampleFramebufferAPPLE(); @@ -404,13 +401,8 @@ - (void)swapBuffers // 1st instruction of the new main loop if (multiSampling_) glBindFramebuffer(GL_FRAMEBUFFER, [renderer_ msaaFrameBuffer]); -} - -- (unsigned int)convertPixelFormat:(int)pixelFormat -{ - return pixelFormat == (int)ax::PixelFormat::RGB565 ? GL_RGB565 : GL_RGBA8_OES; -} #endif +} #pragma mark EARenderView - Point conversion diff --git a/core/platform/ios/ES3Renderer-ios.h b/axmol/platform/ios/ES3Renderer-ios.h similarity index 96% rename from core/platform/ios/ES3Renderer-ios.h rename to axmol/platform/ios/ES3Renderer-ios.h index cb2e426aeb45..42075c488220 100644 --- a/core/platform/ios/ES3Renderer-ios.h +++ b/axmol/platform/ios/ES3Renderer-ios.h @@ -31,10 +31,10 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS -# import "platform/ios/ESRenderer-ios.h" +# import "axmol/platform/ios/ESRenderer-ios.h" # import # import diff --git a/core/platform/ios/ES3Renderer-ios.m b/axmol/platform/ios/ES3Renderer-ios.m similarity index 98% rename from core/platform/ios/ES3Renderer-ios.m rename to axmol/platform/ios/ES3Renderer-ios.m index 52279d615245..754d93f074b4 100644 --- a/core/platform/ios/ES3Renderer-ios.m +++ b/axmol/platform/ios/ES3Renderer-ios.m @@ -28,13 +28,13 @@ of this software and associated documentation files (the "Software"), to deal // Only compile this code on iOS. These files should NOT be included on your Mac project. // But in case they are included, it won't be compiled. -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS -#import "platform/ios/ES3Renderer-ios.h" +#import "axmol/platform/ios/ES3Renderer-ios.h" // #import "platform/PlatformMacros.h" -#import "platform/ios/OpenGL_Internal-ios.h" +#import "axmol/platform/ios/OpenGL_Internal-ios.h" #if !defined(_AX_DEBUG) || _AX_DEBUG == 0 #define NSLog(...) do {} while (0) diff --git a/core/platform/ios/ESRenderer-ios.h b/axmol/platform/ios/ESRenderer-ios.h similarity index 98% rename from core/platform/ios/ESRenderer-ios.h rename to axmol/platform/ios/ESRenderer-ios.h index cf8792396706..52a48e68a438 100644 --- a/core/platform/ios/ESRenderer-ios.h +++ b/axmol/platform/ios/ESRenderer-ios.h @@ -31,7 +31,7 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS // # include "platform/PlatformMacros.h" diff --git a/core/platform/ios/GL-ios.h b/axmol/platform/ios/GL-ios.h similarity index 99% rename from core/platform/ios/GL-ios.h rename to axmol/platform/ios/GL-ios.h index a7523d262d62..16cef6ac77dc 100644 --- a/core/platform/ios/GL-ios.h +++ b/axmol/platform/ios/GL-ios.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS # define glClearDepth glClearDepthf diff --git a/core/platform/ios/Image-ios.mm b/axmol/platform/ios/Image-ios.mm similarity index 89% rename from core/platform/ios/Image-ios.mm rename to axmol/platform/ios/Image-ios.mm index bbea21909846..d108745158a9 100644 --- a/core/platform/ios/Image-ios.mm +++ b/axmol/platform/ios/Image-ios.mm @@ -23,9 +23,9 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#import "platform/Image.h" -#import "platform/Common.h" -#import "platform/FileUtils.h" +#import "axmol/platform/Image.h" +#import "axmol/platform/Common.h" +#import "axmol/platform/FileUtils.h" #import #import @@ -38,11 +38,11 @@ of this software and associated documentation files (the "Software"), to deal bool ax::Image::saveToFile(std::string_view filename, bool isToRGB) { - // only support for backend::PixelFormat::RGB8 or backend::PixelFormat::RGBA8 uncompressed data - if (isCompressed() || (_pixelFormat != backend::PixelFormat::RGB8 && _pixelFormat != backend::PixelFormat::RGBA8)) + // only support for rhi::PixelFormat::RGB8 or rhi::PixelFormat::RGBA8 uncompressed data + if (isCompressed() || (_pixelFormat != rhi::PixelFormat::RGB8 && _pixelFormat != rhi::PixelFormat::RGBA8)) { - AXLOGW("Image: saveToFile is only support for backend::PixelFormat::RGB8 or " - "backend::PixelFormat::RGBA8 uncompressed data for now"); + AXLOGW("Image: saveToFile is only support for rhi::PixelFormat::RGB8 or " + "rhi::PixelFormat::RGBA8 uncompressed data for now"); return false; } bool saveToPNG = false; diff --git a/core/platform/ios/InputView-ios.h b/axmol/platform/ios/InputView-ios.h similarity index 100% rename from core/platform/ios/InputView-ios.h rename to axmol/platform/ios/InputView-ios.h diff --git a/core/platform/ios/InputView-ios.mm b/axmol/platform/ios/InputView-ios.mm similarity index 98% rename from core/platform/ios/InputView-ios.mm rename to axmol/platform/ios/InputView-ios.mm index 9f60e34bda9e..3ffd437b7988 100644 --- a/core/platform/ios/InputView-ios.mm +++ b/axmol/platform/ios/InputView-ios.mm @@ -21,9 +21,9 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#import "platform/ios/InputView-ios.h" -#import "base/IMEDispatcher.h" -#import "base/Director.h" +#import "axmol/platform/ios/InputView-ios.h" +#import "axmol/base/IMEDispatcher.h" +#import "axmol/base/Director.h" @interface TextInputView () diff --git a/core/platform/ios/OpenGL_Internal-ios.h b/axmol/platform/ios/OpenGL_Internal-ios.h similarity index 99% rename from core/platform/ios/OpenGL_Internal-ios.h rename to axmol/platform/ios/OpenGL_Internal-ios.h index a33d552ba762..6142a98a8f48 100644 --- a/core/platform/ios/OpenGL_Internal-ios.h +++ b/axmol/platform/ios/OpenGL_Internal-ios.h @@ -63,7 +63,7 @@ Copyright (C) 2008 Apple Inc. All Rights Reserved. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_IOS /* Generic error reporting */ diff --git a/core/platform/ios/RenderViewImpl-ios.h b/axmol/platform/ios/RenderViewImpl-ios.h similarity index 86% rename from core/platform/ios/RenderViewImpl-ios.h rename to axmol/platform/ios/RenderViewImpl-ios.h index c93682e9072a..a67d1294e398 100644 --- a/core/platform/ios/RenderViewImpl-ios.h +++ b/axmol/platform/ios/RenderViewImpl-ios.h @@ -25,9 +25,9 @@ ****************************************************************************/ #pragma once -#include "base/Object.h" -#include "platform/Common.h" -#include "platform/RenderView.h" +#include "axmol/base/Object.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/RenderView.h" namespace ax { @@ -38,11 +38,6 @@ class AX_DLL RenderViewImpl : public RenderView { public: -#ifndef AX_CORE_PROFILE - /** DEPRECATED creates a RenderViewImpl with a objective-c EARenderViewImpl instance */ - AX_DEPRECATED(2.8) static RenderViewImpl* createWithEARenderView(void* viewHandle); -#endif - /** creates a RenderViewImpl with a title name in fullscreen mode */ static RenderViewImpl* create(std::string_view viewName); @@ -54,17 +49,15 @@ class AX_DLL RenderViewImpl : public RenderView /** creates a RenderViewImpl with a name in fullscreen mode */ static RenderViewImpl* createWithFullScreen(std::string_view viewName); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) static void convertAttrs() { choosePixelFormats(); } -#endif + static void choosePixelFormats(); static PixelFormat _pixelFormat; static PixelFormat _depthFormat; static int _multisamplingCount; - + /** @since axmol-2.8.0, sets multi touch enabled */ void setMultipleTouchEnabled(bool enabled); - + void showWindow(void* viewController); /** sets the content scale factor */ @@ -95,9 +88,6 @@ class AX_DLL RenderViewImpl : public RenderView protected: RenderViewImpl(); ~RenderViewImpl() override; -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.8) bool initWithEARenderView(void* viewHandle); -#endif bool initWithRect(std::string_view viewName, const Rect& rect, float frameZoomFactor, bool resizable = false); bool initWithFullScreen(std::string_view viewName); @@ -106,8 +96,4 @@ class AX_DLL RenderViewImpl : public RenderView void* _eaWindowHandle; }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef RenderViewImpl GLViewImpl; -#endif - } diff --git a/core/platform/ios/RenderViewImpl-ios.mm b/axmol/platform/ios/RenderViewImpl-ios.mm similarity index 91% rename from core/platform/ios/RenderViewImpl-ios.mm rename to axmol/platform/ios/RenderViewImpl-ios.mm index 8217aa0871ce..a43210cac9fd 100644 --- a/core/platform/ios/RenderViewImpl-ios.mm +++ b/axmol/platform/ios/RenderViewImpl-ios.mm @@ -26,11 +26,11 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import -#include "platform/ios/EARenderView-ios.h" -#include "platform/ios/DirectorCaller-ios.h" -#include "platform/ios/RenderViewImpl-ios.h" -#include "base/Touch.h" -#include "base/Director.h" +#include "axmol/platform/ios/EARenderView-ios.h" +#include "axmol/platform/ios/DirectorCaller-ios.h" +#include "axmol/platform/ios/RenderViewImpl-ios.h" +#include "axmol/base/Touch.h" +#include "axmol/base/Director.h" namespace ax { @@ -39,20 +39,6 @@ of this software and associated documentation files (the "Software"), to deal PixelFormat RenderViewImpl::_depthFormat = PixelFormat::D24S8; int RenderViewImpl::_multisamplingCount = 0; -#ifndef AX_CORE_PROFILE -RenderViewImpl* RenderViewImpl::createWithEARenderView(void* viewHandle) -{ - auto ret = new RenderViewImpl; - if (ret->initWithEARenderView(viewHandle)) - { - ret->autorelease(); - return ret; - } - AX_SAFE_DELETE(ret); - return nullptr; -} -#endif - RenderViewImpl* RenderViewImpl::create(std::string_view viewName) { auto ret = new RenderViewImpl; @@ -133,20 +119,6 @@ of this software and associated documentation files (the "Software"), to deal //[eaView release]; } -#ifndef AX_CORE_PROFILE -bool RenderViewImpl::initWithEARenderView(void* viewHandle) -{ - _eaViewHandle = viewHandle; - EARenderView* eaView = (__bridge EARenderView*)_eaViewHandle; - - _screenSize.width = _designResolutionSize.width = [eaView getWidth]; - _screenSize.height = _designResolutionSize.height = [eaView getHeight]; - // _scaleX = _scaleY = [eaView contentScaleFactor]; - - return true; -} -#endif - bool RenderViewImpl::initWithRect(std::string_view /*viewName*/, const Rect& rect, float frameZoomFactor, bool /*resizable*/) { CGRect r = CGRectMake(rect.origin.x, rect.origin.y, rect.size.width, rect.size.height); diff --git a/core/platform/ios/StdC-ios.h b/axmol/platform/ios/StdC-ios.h similarity index 97% rename from core/platform/ios/StdC-ios.h rename to axmol/platform/ios/StdC-ios.h index ba57b99b03ac..5514a37aca7e 100644 --- a/core/platform/ios/StdC-ios.h +++ b/axmol/platform/ios/StdC-ios.h @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include #include diff --git a/core/platform/linux/Application-linux.cpp b/axmol/platform/linux/Application-linux.cpp similarity index 94% rename from core/platform/linux/Application-linux.cpp rename to axmol/platform/linux/Application-linux.cpp index ca5277dd268b..517be026131b 100644 --- a/core/platform/linux/Application-linux.cpp +++ b/axmol/platform/linux/Application-linux.cpp @@ -23,14 +23,14 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/linux/Application-linux.h" +#include "axmol/platform/linux/Application-linux.h" #include #include #include #include -#include "base/Director.h" -#include "base/Utils.h" -#include "platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/FileUtils.h" namespace ax { @@ -132,12 +132,6 @@ Application* Application::getInstance() return sm_pSharedApplication; } -// @deprecated Use getInstance() instead -Application* Application::sharedApplication() -{ - return Application::getInstance(); -} - const char* Application::getCurrentLanguageCode() { static char code[3] = {0}; diff --git a/core/platform/linux/Application-linux.h b/axmol/platform/linux/Application-linux.h similarity index 82% rename from core/platform/linux/Application-linux.h rename to axmol/platform/linux/Application-linux.h index 0216ad88c10a..0e1bc30c659a 100644 --- a/core/platform/linux/Application-linux.h +++ b/axmol/platform/linux/Application-linux.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" #include #include @@ -50,7 +50,7 @@ class Application : public ApplicationBase @brief Callback by Director for limit FPS. @param interval The time, which expressed in second in second, between current frame and next. */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; /** @brief Run the message loop. @@ -62,35 +62,32 @@ class Application : public ApplicationBase @return Current application instance pointer. */ static Application* getInstance(); -#ifndef AX_CORE_PROFILE - /** @deprecated Use getInstance() instead */ - AX_DEPRECATED(2.1) static Application* sharedApplication(); -#endif + /* override functions */ - virtual LanguageType getCurrentLanguage() override; + LanguageType getCurrentLanguage() override; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code */ - virtual const char* getCurrentLanguageCode() override; + const char* getCurrentLanguageCode() override; /** @brief Get application version */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser @param String with url to open. @return true if the resource located by the URL was successfully opened; otherwise false. */ - virtual bool openURL(std::string_view url) override; + bool openURL(std::string_view url) override; /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; protected: std::chrono::nanoseconds _animationInterval; // nano seconds diff --git a/core/platform/linux/Common-linux.cpp b/axmol/platform/linux/Common-linux.cpp similarity index 93% rename from core/platform/linux/Common-linux.cpp rename to axmol/platform/linux/Common-linux.cpp index 3ed0e16341ad..ef6d245f4bfb 100644 --- a/core/platform/linux/Common-linux.cpp +++ b/axmol/platform/linux/Common-linux.cpp @@ -24,9 +24,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" -#include "platform/linux/StdC-linux.h" -#include "base/Logging.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/linux/StdC-linux.h" +#include "axmol/base/Logging.h" namespace ax { diff --git a/core/platform/linux/Device-linux.cpp b/axmol/platform/linux/Device-linux.cpp similarity index 99% rename from core/platform/linux/Device-linux.cpp rename to axmol/platform/linux/Device-linux.cpp index ecf691130f3b..8a232b661204 100644 --- a/core/platform/linux/Device-linux.cpp +++ b/axmol/platform/linux/Device-linux.cpp @@ -24,8 +24,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Device.h" -#include "platform/FileUtils.h" +#include "axmol/platform/Device.h" +#include "axmol/platform/FileUtils.h" #include #include @@ -481,7 +481,7 @@ class BitmapDC int lineCount = textLines.size(); - auto&& textColor = Color4B(textDefinition._fontFillColor, textDefinition._fontAlpha); + auto&& textColor = textDefinition._fontFillColor; for (int line = 0; line < lineCount; line++) { int iCurXCursor = computeLineStart(face, eAlignMask, line); diff --git a/core/platform/linux/FileUtils-linux.cpp b/axmol/platform/linux/FileUtils-linux.cpp similarity index 95% rename from core/platform/linux/FileUtils-linux.cpp rename to axmol/platform/linux/FileUtils-linux.cpp index b58e4488ff76..f55aac004ba7 100644 --- a/core/platform/linux/FileUtils-linux.cpp +++ b/axmol/platform/linux/FileUtils-linux.cpp @@ -24,11 +24,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/linux/FileUtils-linux.h" -#include "platform/linux/Application-linux.h" -#include "platform/Common.h" -#include "base/Macros.h" -#include "base/UTF8.h" +#include "axmol/platform/linux/FileUtils-linux.h" +#include "axmol/platform/linux/Application-linux.h" +#include "axmol/platform/Common.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" #include #include #include diff --git a/core/platform/linux/FileUtils-linux.h b/axmol/platform/linux/FileUtils-linux.h similarity index 88% rename from core/platform/linux/FileUtils-linux.h rename to axmol/platform/linux/FileUtils-linux.h index bbe0ba2f4724..6c2e75219d81 100644 --- a/core/platform/linux/FileUtils-linux.h +++ b/axmol/platform/linux/FileUtils-linux.h @@ -25,9 +25,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" #include #include @@ -53,11 +53,11 @@ class AX_DLL FileUtilsLinux : public FileUtils public: /* override functions */ bool init() override; - virtual std::string getWritablePath() const override; + std::string getWritablePath() const override; std::string getNativeWritableAbsolutePath() const override; private: - virtual bool isFileExistInternal(std::string_view strFilePath) const override; + bool isFileExistInternal(std::string_view strFilePath) const override; static std::string s_exeName; }; diff --git a/core/platform/linux/GL-linux.h b/axmol/platform/linux/GL-linux.h similarity index 100% rename from core/platform/linux/GL-linux.h rename to axmol/platform/linux/GL-linux.h diff --git a/core/platform/linux/StdC-linux.h b/axmol/platform/linux/StdC-linux.h similarity index 97% rename from core/platform/linux/StdC-linux.h rename to axmol/platform/linux/StdC-linux.h index aa50cd654c2a..298fd7d629e1 100644 --- a/core/platform/linux/StdC-linux.h +++ b/axmol/platform/linux/StdC-linux.h @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include diff --git a/core/platform/mac/Application-mac.h b/axmol/platform/mac/Application-mac.h similarity index 87% rename from core/platform/mac/Application-mac.h rename to axmol/platform/mac/Application-mac.h index 70dcc45f17b0..0b5d07d1d172 100644 --- a/core/platform/mac/Application-mac.h +++ b/axmol/platform/mac/Application-mac.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" #include #include @@ -49,7 +49,7 @@ class AX_DLL Application : public ApplicationBase @brief Callback by Director for limit FPS. @param interval The time, which expressed in second in second, between current frame and next. */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; /** @brief Run the message loop. @@ -67,30 +67,30 @@ class AX_DLL Application : public ApplicationBase @brief Get current language config @return Current language config */ - virtual LanguageType getCurrentLanguage() override; + LanguageType getCurrentLanguage() override; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code */ - virtual const char* getCurrentLanguageCode() override; + const char* getCurrentLanguageCode() override; /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; /** @brief Get application version. */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser @param String with url to open. @return true if the resource located by the URL was successfully opened; otherwise false. */ - virtual bool openURL(std::string_view url) override; + bool openURL(std::string_view url) override; void setStartupScriptFilename(std::string_view startupScriptFile); diff --git a/core/platform/mac/Application-mac.mm b/axmol/platform/mac/Application-mac.mm similarity index 96% rename from core/platform/mac/Application-mac.mm rename to axmol/platform/mac/Application-mac.mm index 2cca9afa10c9..d9e414373f70 100644 --- a/core/platform/mac/Application-mac.mm +++ b/axmol/platform/mac/Application-mac.mm @@ -28,12 +28,12 @@ of this software and associated documentation files (the "Software"), to deal #include #include -#include "platform/Application.h" -#include "platform/FileUtils.h" -#include "math/Math.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "renderer/backend/metal/DriverMTL.h" +#include "axmol/platform/Application.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/math/Math.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/rhi/metal/DriverMTL.h" namespace ax { diff --git a/core/platform/mac/Common-mac.mm b/axmol/platform/mac/Common-mac.mm similarity index 96% rename from core/platform/mac/Common-mac.mm rename to axmol/platform/mac/Common-mac.mm index ee1e89bcb460..0485749a2407 100644 --- a/core/platform/mac/Common-mac.mm +++ b/axmol/platform/mac/Common-mac.mm @@ -23,9 +23,9 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" +#include "axmol/platform/Common.h" -#include "base/Director.h" +#include "axmol/base/Director.h" #include #include diff --git a/core/platform/mac/Device-mac.mm b/axmol/platform/mac/Device-mac.mm similarity index 97% rename from core/platform/mac/Device-mac.mm rename to axmol/platform/mac/Device-mac.mm index a20042f12e90..fce93a09bcc3 100644 --- a/core/platform/mac/Device-mac.mm +++ b/axmol/platform/mac/Device-mac.mm @@ -24,12 +24,12 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Device.h" +#include "axmol/platform/Device.h" #include #include #include -#include "base/Types.h" -#include "platform/apple/Device-apple.h" +#include "axmol/base/Types.h" +#include "axmol/platform/apple/Device-apple.h" namespace ax { @@ -283,8 +283,7 @@ static bool _initWithString(std::string_view text, const char* fontName, int size, tImageInfo* info, - const Color3B* fontColor, - int fontAlpha, + const Color32* fontColor, bool enableWrap, int overflow, const FontStroke& stroke) @@ -306,10 +305,10 @@ static bool _initWithString(std::string_view text, NSColor* foregroundColor; if (fontColor) { - foregroundColor = [NSColor colorWithDeviceRed:fontColor->r / 255.0 - green:fontColor->g / 255.0 - blue:fontColor->b / 255.0 - alpha:fontAlpha / 255.0]; + foregroundColor = [NSColor colorWithDeviceRed:fontColor->r / 255.0f + green:fontColor->g / 255.0f + blue:fontColor->b / 255.0f + alpha:fontColor->a / 255.0f]; } else { @@ -376,7 +375,7 @@ static bool _initWithString(std::string_view text, NSColor* strokeColor = [NSColor colorWithDeviceRed:stroke._strokeColor.r / 255.0 green:stroke._strokeColor.g / 255.0 blue:stroke._strokeColor.b / 255.0 - alpha:stroke._strokeAlpha / 255.0]; + alpha:stroke._strokeColor.a / 255.0]; NSNumber* strokeSize = [NSNumber numberWithFloat:stroke._strokeSize / size * 100.0]; NSDictionary* tokenAttributesDict2 = [NSDictionary dictionaryWithObjectsAndKeys:foregroundColor, NSForegroundColorAttributeName, font, NSFontAttributeName, @@ -424,7 +423,7 @@ static bool _initWithString(std::string_view text, info.height = textDefinition._dimensions.height; if (!_initWithString(text, align, textDefinition._fontName.c_str(), textDefinition._fontSize, &info, - &textDefinition._fontFillColor, textDefinition._fontAlpha, textDefinition._enableWrap, + &textDefinition._fontFillColor, textDefinition._enableWrap, textDefinition._overflow, textDefinition._stroke)) { break; diff --git a/core/platform/mac/GL-mac.h b/axmol/platform/mac/GL-mac.h similarity index 99% rename from core/platform/mac/GL-mac.h rename to axmol/platform/mac/GL-mac.h index 3f0824bfdd96..67606468318e 100644 --- a/core/platform/mac/GL-mac.h +++ b/axmol/platform/mac/GL-mac.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_MAC # import diff --git a/core/platform/mac/StdC-mac.h b/axmol/platform/mac/StdC-mac.h similarity index 97% rename from core/platform/mac/StdC-mac.h rename to axmol/platform/mac/StdC-mac.h index ba57b99b03ac..5514a37aca7e 100644 --- a/core/platform/mac/StdC-mac.h +++ b/axmol/platform/mac/StdC-mac.h @@ -25,7 +25,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include #include #include diff --git a/core/platform/wasm/Application-wasm.cpp b/axmol/platform/wasm/Application-wasm.cpp similarity index 88% rename from core/platform/wasm/Application-wasm.cpp rename to axmol/platform/wasm/Application-wasm.cpp index 42b759360328..3b3e4bd6ef44 100644 --- a/core/platform/wasm/Application-wasm.cpp +++ b/axmol/platform/wasm/Application-wasm.cpp @@ -25,17 +25,17 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "platform/wasm/Application-wasm.h" -# include "platform/wasm/devtools-wasm.h" +# include "axmol/platform/wasm/Application-wasm.h" +# include "axmol/platform/wasm/devtools-wasm.h" # include # include # include -# include "base/Director.h" -# include "base/Utils.h" -# include "platform/FileUtils.h" +# include "axmol/base/Director.h" +# include "axmol/base/Utils.h" +# include "axmol/platform/FileUtils.h" # include "yasio/utils.hpp" # include @@ -61,7 +61,7 @@ void axmol_webglcontextrestored() AXLOGI("receive event: webglcontextrestored"); auto director = ax::Director::getInstance(); - ax::backend::DriverBase::getInstance()->resetState(); + ax::rhi::DriverBase::getInstance()->resetState(); director->resetMatrixStack(); ax::EventCustom recreatedEvent(EVENT_RENDERER_RECREATED); director->getEventDispatcher()->dispatchEvent(&recreatedEvent, true); @@ -211,24 +211,6 @@ void Application::setAnimationInterval(float interval) s_animationInterval = static_cast(interval * NANOSECONDSPERSECOND); } -void Application::setResourceRootPath(const std::string& rootResDir) -{ - _resourceRootPath = rootResDir; - if (_resourceRootPath[_resourceRootPath.length() - 1] != '/') - { - _resourceRootPath += '/'; - } - FileUtils* pFileUtils = FileUtils::getInstance(); - std::vector searchPaths = pFileUtils->getSearchPaths(); - searchPaths.insert(searchPaths.begin(), _resourceRootPath); - pFileUtils->setSearchPaths(searchPaths); -} - -const std::string& Application::getResourceRootPath() -{ - return _resourceRootPath; -} - Application::Platform Application::getTargetPlatform() { return Platform::Wasm; @@ -255,12 +237,6 @@ Application* Application::getInstance() return sm_pSharedApplication; } -// @deprecated Use getInstance() instead -Application* Application::sharedApplication() -{ - return Application::getInstance(); -} - const char* Application::getCurrentLanguageCode() { static char code[3] = {0}; diff --git a/core/platform/wasm/Application-wasm.h b/axmol/platform/wasm/Application-wasm.h similarity index 72% rename from core/platform/wasm/Application-wasm.h rename to axmol/platform/wasm/Application-wasm.h index b76c75ef23c6..efbb1feb3c10 100644 --- a/core/platform/wasm/Application-wasm.h +++ b/axmol/platform/wasm/Application-wasm.h @@ -28,11 +28,11 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" #include namespace ax @@ -54,7 +54,7 @@ class Application : public ApplicationBase @brief Callback by Director for limit FPS. @param interval The time, which expressed in second in second, between current frame and next. */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; /** @brief Run the message loop. @@ -66,48 +66,32 @@ class Application : public ApplicationBase @return Current application instance pointer. */ static Application* getInstance(); -#ifndef AX_CORE_PROFILE - /** @deprecated Use getInstance() instead */ - AX_DEPRECATED(2.1) static Application* sharedApplication(); -#endif + /* override functions */ - virtual LanguageType getCurrentLanguage() override; + LanguageType getCurrentLanguage() override; /** @brief Get current language iso 639-1 code @return Current language iso 639-1 code */ - virtual const char * getCurrentLanguageCode() override; + const char * getCurrentLanguageCode() override; /** @brief Get application version */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser @param String with url to open. @return true if the resource located by the URL was successfully opened; otherwise false. */ - virtual bool openURL(std::string_view url) override; - -#ifndef AX_CORE_PROFILE - /** - * Sets the Resource root path. - * @deprecated Please use FileUtils::getInstance()->setSearchPaths() instead. - */ - AX_DEPRECATED(2.1) void setResourceRootPath(const std::string& rootResDir); + bool openURL(std::string_view url) override; - /** - * Gets the Resource root path. - * @deprecated Please use FileUtils::getInstance()->getSearchPaths() instead. - */ - AX_DEPRECATED(2.1) const std::string& getResourceRootPath(); -#endif /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; protected: std::string _resourceRootPath; diff --git a/core/platform/wasm/Common-wasm.cpp b/axmol/platform/wasm/Common-wasm.cpp similarity index 91% rename from core/platform/wasm/Common-wasm.cpp rename to axmol/platform/wasm/Common-wasm.cpp index f0314e2c5fa8..74cabd587fd8 100644 --- a/core/platform/wasm/Common-wasm.cpp +++ b/axmol/platform/wasm/Common-wasm.cpp @@ -25,12 +25,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "platform/Common.h" -#include "platform/wasm/StdC-wasm.h" -#include "base/Logging.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/wasm/StdC-wasm.h" +#include "axmol/base/Logging.h" #include namespace ax diff --git a/core/platform/wasm/Device-wasm.cpp b/axmol/platform/wasm/Device-wasm.cpp similarity index 98% rename from core/platform/wasm/Device-wasm.cpp rename to axmol/platform/wasm/Device-wasm.cpp index 7c6b07ab47ed..bad08cbf35ea 100644 --- a/core/platform/wasm/Device-wasm.cpp +++ b/axmol/platform/wasm/Device-wasm.cpp @@ -25,11 +25,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "platform/Device.h" -# include "platform/FileUtils.h" +# include "axmol/platform/Device.h" +# include "axmol/platform/FileUtils.h" # include # include @@ -66,7 +66,7 @@ Data Device::getTextureDataForText(std::string_view text, { char color[10]; fmt::format_to_z(color, "#{:02x}{:02x}{:02x}{:02x}", textDefinition._fontFillColor.r, textDefinition._fontFillColor.g, - textDefinition._fontFillColor.b, textDefinition._fontAlpha); + textDefinition._fontFillColor.b, textDefinition._fontFillColor.a); // clang-format off unsigned char* ptr = (unsigned char*)EM_ASM_PTR({ var lines = UTF8ToString($0).split("\n"); diff --git a/core/platform/wasm/FileUtils-wasm.cpp b/axmol/platform/wasm/FileUtils-wasm.cpp similarity index 92% rename from core/platform/wasm/FileUtils-wasm.cpp rename to axmol/platform/wasm/FileUtils-wasm.cpp index 78e6506e3efc..8c1ee96ea4a9 100644 --- a/core/platform/wasm/FileUtils-wasm.cpp +++ b/axmol/platform/wasm/FileUtils-wasm.cpp @@ -25,14 +25,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "platform/wasm/FileUtils-wasm.h" -#include "platform/wasm/Application-wasm.h" -#include "platform/Common.h" -#include "base/Macros.h" -#include "base/UTF8.h" +#include "axmol/platform/wasm/FileUtils-wasm.h" +#include "axmol/platform/wasm/Application-wasm.h" +#include "axmol/platform/Common.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" #include #include "yasio/string_view.hpp" diff --git a/core/platform/wasm/FileUtils-wasm.h b/axmol/platform/wasm/FileUtils-wasm.h similarity index 87% rename from core/platform/wasm/FileUtils-wasm.h rename to axmol/platform/wasm/FileUtils-wasm.h index 3a5ae738460f..cc06c0355ee7 100644 --- a/core/platform/wasm/FileUtils-wasm.h +++ b/axmol/platform/wasm/FileUtils-wasm.h @@ -26,12 +26,12 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" #include #include @@ -52,10 +52,10 @@ class AX_DLL FileUtilsEmscripten : public FileUtils public: /* override functions */ bool init() override; - virtual std::string getWritablePath() const override; + std::string getWritablePath() const override; std::string getNativeWritableAbsolutePath() const override; private: - virtual bool isFileExistInternal(std::string_view path) const override; + bool isFileExistInternal(std::string_view path) const override; }; // end of platform group diff --git a/core/platform/wasm/GL-wasm.h b/axmol/platform/wasm/GL-wasm.h similarity index 98% rename from core/platform/wasm/GL-wasm.h rename to axmol/platform/wasm/GL-wasm.h index d184d9ac4364..a49e0567a91b 100644 --- a/core/platform/wasm/GL-wasm.h +++ b/axmol/platform/wasm/GL-wasm.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "glad/gl.h" diff --git a/core/platform/wasm/StdC-wasm.h b/axmol/platform/wasm/StdC-wasm.h similarity index 95% rename from core/platform/wasm/StdC-wasm.h rename to axmol/platform/wasm/StdC-wasm.h index 0180916051d1..f634059ff5c5 100644 --- a/core/platform/wasm/StdC-wasm.h +++ b/axmol/platform/wasm/StdC-wasm.h @@ -25,8 +25,8 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/PlatformMacros.h" #include #include #include diff --git a/core/platform/wasm/devtools-wasm.cpp b/axmol/platform/wasm/devtools-wasm.cpp similarity index 94% rename from core/platform/wasm/devtools-wasm.cpp rename to axmol/platform/wasm/devtools-wasm.cpp index d476d80d388d..7fea1d64a1e0 100644 --- a/core/platform/wasm/devtools-wasm.cpp +++ b/axmol/platform/wasm/devtools-wasm.cpp @@ -25,12 +25,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "platform/wasm/devtools-wasm.h" +#include "axmol/platform/wasm/devtools-wasm.h" #include -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" namespace ax { diff --git a/core/platform/wasm/devtools-wasm.h b/axmol/platform/wasm/devtools-wasm.h similarity index 78% rename from core/platform/wasm/devtools-wasm.h rename to axmol/platform/wasm/devtools-wasm.h index a76ea320f357..416c4bae91e2 100644 --- a/core/platform/wasm/devtools-wasm.h +++ b/axmol/platform/wasm/devtools-wasm.h @@ -1,10 +1,10 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -#include "base/Scheduler.h" -#include "base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/platform/wasm/shell_minimal.html b/axmol/platform/wasm/shell_minimal.html similarity index 100% rename from core/platform/wasm/shell_minimal.html rename to axmol/platform/wasm/shell_minimal.html diff --git a/core/platform/wasm/shell_production.html b/axmol/platform/wasm/shell_production.html similarity index 100% rename from core/platform/wasm/shell_production.html rename to axmol/platform/wasm/shell_production.html diff --git a/core/platform/win32/Application-win32.cpp b/axmol/platform/win32/Application-win32.cpp similarity index 98% rename from core/platform/win32/Application-win32.cpp rename to axmol/platform/win32/Application-win32.cpp index c26ca8b1fbf0..816b3fb12d31 100644 --- a/core/platform/win32/Application-win32.cpp +++ b/axmol/platform/win32/Application-win32.cpp @@ -24,10 +24,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Application.h" -#include "base/Director.h" +#include "axmol/platform/Application.h" +#include "axmol/base/Director.h" #include -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include #include #include @@ -85,8 +85,8 @@ int Application::run() return 1; } - auto director = Director::getInstance(); - auto renderView = director->getRenderView(); + auto director = Director::getInstance(); + auto renderView = director->getRenderView(); // Retain renderView to avoid renderView being released in the while loop renderView->retain(); @@ -129,7 +129,6 @@ int Application::run() } renderView->release(); - return 0; } diff --git a/core/platform/win32/Application-win32.h b/axmol/platform/win32/Application-win32.h similarity index 92% rename from core/platform/win32/Application-win32.h rename to axmol/platform/win32/Application-win32.h index 2baa097d09aa..e6093edff734 100644 --- a/core/platform/win32/Application-win32.h +++ b/axmol/platform/win32/Application-win32.h @@ -26,9 +26,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/StdC.h" -#include "platform/Common.h" -#include "platform/ApplicationBase.h" +#include "axmol/platform/StdC.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/ApplicationBase.h" #include namespace ax @@ -57,7 +57,7 @@ class AX_DLL Application : public ApplicationBase static Application* getInstance(); /* override functions */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; virtual LanguageType getCurrentLanguage(); @@ -71,7 +71,7 @@ class AX_DLL Application : public ApplicationBase /** @brief Get application version */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser diff --git a/core/platform/win32/Common-win32.cpp b/axmol/platform/win32/Common-win32.cpp similarity index 96% rename from core/platform/win32/Common-win32.cpp rename to axmol/platform/win32/Common-win32.cpp index 4b5892599fb9..1ae3630f8c75 100644 --- a/core/platform/win32/Common-win32.cpp +++ b/axmol/platform/win32/Common-win32.cpp @@ -24,8 +24,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" -#include "platform/StdC.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/StdC.h" #include "ntcvt/ntcvt.hpp" namespace ax diff --git a/core/platform/win32/Device-win32.cpp b/axmol/platform/win32/Device-win32.cpp similarity index 98% rename from core/platform/win32/Device-win32.cpp rename to axmol/platform/win32/Device-win32.cpp index 630d6f7ce9d3..a727d2f76091 100644 --- a/core/platform/win32/Device-win32.cpp +++ b/axmol/platform/win32/Device-win32.cpp @@ -24,9 +24,9 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Device.h" -#include "platform/FileUtils.h" -#include "platform/StdC.h" +#include "axmol/platform/Device.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/StdC.h" #include "ntcvt/ntcvt.hpp" @@ -460,7 +460,7 @@ Data Device::getTextureDataForText(std::string_view text, COLORREF textColor = (textDefinition._fontFillColor.b << 16 | textDefinition._fontFillColor.g << 8 | textDefinition._fontFillColor.r) & 0x00ffffff; - float alpha = textDefinition._fontAlpha / 255.0f; + float alpha = textDefinition._fontFillColor.a / 255.0f; COLORREF* pPixel = nullptr; for (int y = 0; y < height; ++y) { diff --git a/core/platform/win32/EmbedConsole.h b/axmol/platform/win32/EmbedConsole.h similarity index 100% rename from core/platform/win32/EmbedConsole.h rename to axmol/platform/win32/EmbedConsole.h diff --git a/core/platform/win32/FileUtils-win32.cpp b/axmol/platform/win32/FileUtils-win32.cpp similarity index 99% rename from core/platform/win32/FileUtils-win32.cpp rename to axmol/platform/win32/FileUtils-win32.cpp index ff8bb4f4d8ff..d08b666cb43a 100644 --- a/core/platform/win32/FileUtils-win32.cpp +++ b/axmol/platform/win32/FileUtils-win32.cpp @@ -24,8 +24,8 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/win32/FileUtils-win32.h" -#include "platform/Common.h" +#include "axmol/platform/win32/FileUtils-win32.h" +#include "axmol/platform/Common.h" #include #include #include diff --git a/core/platform/win32/FileUtils-win32.h b/axmol/platform/win32/FileUtils-win32.h similarity index 83% rename from core/platform/win32/FileUtils-win32.h rename to axmol/platform/win32/FileUtils-win32.h index c885971a1191..7cf07c1ffcf8 100644 --- a/core/platform/win32/FileUtils-win32.h +++ b/axmol/platform/win32/FileUtils-win32.h @@ -26,9 +26,9 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" #include #include @@ -51,11 +51,11 @@ class AX_DLL FileUtilsWin32 : public FileUtils public: /* override functions */ bool init() override; - virtual std::string getWritablePath() const override; - virtual std::string getNativeWritableAbsolutePath() const override; + std::string getWritablePath() const override; + std::string getNativeWritableAbsolutePath() const override; protected: - virtual bool isFileExistInternal(std::string_view strFilePath) const override; + bool isFileExistInternal(std::string_view strFilePath) const override; /** * Renames a file under the given directory. @@ -65,7 +65,7 @@ class AX_DLL FileUtilsWin32 : public FileUtils * @param name The new name of the file. * @return True if the file have been renamed successfully, false if not. */ - virtual bool renameFile(std::string_view path, std::string_view oldname, std::string_view name) const override; + bool renameFile(std::string_view path, std::string_view oldname, std::string_view name) const override; /** * Renames a file under the given directory. @@ -74,14 +74,14 @@ class AX_DLL FileUtilsWin32 : public FileUtils * @param newfullpath The new path + name of the file. * @return True if the file have been renamed successfully, false if not. */ - virtual bool renameFile(std::string_view oldfullpath, std::string_view newfullpath) const override; + bool renameFile(std::string_view oldfullpath, std::string_view newfullpath) const override; /** * Checks whether a directory exists without considering search paths and resolution orders. * @param dirPath The directory (with absolute path) to look up for * @return Returns true if the directory found at the given absolute path, otherwise returns false */ - virtual bool isDirectoryExistInternal(std::string_view dirPath) const override; + bool isDirectoryExistInternal(std::string_view dirPath) const override; /** * Removes a file. @@ -89,7 +89,7 @@ class AX_DLL FileUtilsWin32 : public FileUtils * @param filepath The full path of the file, it must be an absolute path. * @return True if the file have been removed successfully, false if not. */ - virtual bool removeFile(std::string_view filepath) const override; + bool removeFile(std::string_view filepath) const override; /** * Creates a directory. @@ -97,7 +97,7 @@ class AX_DLL FileUtilsWin32 : public FileUtils * @param dirPath The path of the directory, it must be an absolute path. * @return True if the directory have been created successfully, false if not. */ - virtual bool createDirectories(std::string_view dirPath) const override; + bool createDirectories(std::string_view dirPath) const override; /** * Removes a directory. @@ -105,9 +105,9 @@ class AX_DLL FileUtilsWin32 : public FileUtils * @param dirPath The full path of the directory, it must be an absolute path. * @return True if the directory have been removed successfully, false if not. */ - virtual bool removeDirectory(std::string_view dirPath) const override; + bool removeDirectory(std::string_view dirPath) const override; - virtual int64_t getFileSize(std::string_view filepath) const override; + int64_t getFileSize(std::string_view filepath) const override; /** * Gets full path for filename, resolution directory and search path. diff --git a/core/platform/win32/GL-win32.h b/axmol/platform/win32/GL-win32.h similarity index 96% rename from core/platform/win32/GL-win32.h rename to axmol/platform/win32/GL-win32.h index 80c8ee3d5728..d4e554a82a9b 100644 --- a/core/platform/win32/GL-win32.h +++ b/axmol/platform/win32/GL-win32.h @@ -26,8 +26,8 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" -#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 +#include "axmol/platform/PlatformConfig.h" +#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 && AX_RENDER_API == AX_RENDER_API_GL # include "glad/gl.h" diff --git a/core/platform/win32/StdC-win32.cpp b/axmol/platform/win32/StdC-win32.cpp similarity index 98% rename from core/platform/win32/StdC-win32.cpp rename to axmol/platform/win32/StdC-win32.cpp index 6295be0941a5..9c16cf301af5 100644 --- a/core/platform/win32/StdC-win32.cpp +++ b/axmol/platform/win32/StdC-win32.cpp @@ -23,7 +23,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" #ifndef __MINGW32__ diff --git a/core/platform/win32/StdC-win32.h b/axmol/platform/win32/StdC-win32.h similarity index 98% rename from core/platform/win32/StdC-win32.h rename to axmol/platform/win32/StdC-win32.h index 0d0aff37b86b..3d8bc4f0a9c4 100644 --- a/core/platform/win32/StdC-win32.h +++ b/axmol/platform/win32/StdC-win32.h @@ -32,7 +32,7 @@ THE SOFTWARE. typedef SSIZE_T ssize_t; #endif // __SSIZE_T -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include // for math.h on win32 platform diff --git a/core/platform/winrt/Application-winrt.cpp b/axmol/platform/winrt/Application-winrt.cpp similarity index 95% rename from core/platform/winrt/Application-winrt.cpp rename to axmol/platform/winrt/Application-winrt.cpp index afd82df9539b..82d61f716fb8 100644 --- a/core/platform/winrt/Application-winrt.cpp +++ b/axmol/platform/winrt/Application-winrt.cpp @@ -24,16 +24,16 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "base/Director.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/base/Director.h" #include -#include "platform/FileUtils.h" -#include "platform/winrt/WinRTUtils.h" -#include "platform/Application.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/platform/Application.h" #include "pugixml/pugixml.hpp" -#include "base/format.h" +#include "axmol/base/format.h" #include #include diff --git a/core/platform/winrt/Application-winrt.h b/axmol/platform/winrt/Application-winrt.h similarity index 87% rename from core/platform/winrt/Application-winrt.h rename to axmol/platform/winrt/Application-winrt.h index 4edce1252144..35ca0d176093 100644 --- a/core/platform/winrt/Application-winrt.h +++ b/axmol/platform/winrt/Application-winrt.h @@ -26,13 +26,13 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) -# include "platform/StdC.h" -# include "platform/Common.h" -# include "platform/ApplicationBase.h" -# include "platform/winrt/InputEvent.h" +# include "axmol/platform/StdC.h" +# include "axmol/platform/Common.h" +# include "axmol/platform/ApplicationBase.h" +# include "axmol/platform/winrt/InputEvent.h" # include # include @@ -62,21 +62,21 @@ class AX_DLL Application : public ApplicationBase static Application* getInstance(); /* override functions */ - virtual void setAnimationInterval(float interval) override; + void setAnimationInterval(float interval) override; // virtual void setAnimationInterval(float interval, SetIntervalReason reason) override; - virtual LanguageType getCurrentLanguage() override; - virtual const char* getCurrentLanguageCode() override; + LanguageType getCurrentLanguage() override; + const char* getCurrentLanguageCode() override; /** @brief Get target platform */ - virtual Platform getTargetPlatform() override; + Platform getTargetPlatform() override; /** @brief Get application version */ - virtual std::string getVersion() override; + std::string getVersion() override; /** @brief Open url in default browser diff --git a/core/platform/winrt/Common-winrt.cpp b/axmol/platform/winrt/Common-winrt.cpp similarity index 91% rename from core/platform/winrt/Common-winrt.cpp rename to axmol/platform/winrt/Common-winrt.cpp index bdb09562ae62..b1347d1f0e59 100644 --- a/core/platform/winrt/Common-winrt.cpp +++ b/axmol/platform/winrt/Common-winrt.cpp @@ -23,10 +23,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/Common.h" -#include "platform/StdC.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "platform/winrt/WinRTUtils.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/StdC.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/platform/winrt/WinRTUtils.h" #if defined(VLD_DEBUG_MEMORY) #include diff --git a/core/platform/winrt/Device-winrt.cpp b/axmol/platform/winrt/Device-winrt.cpp similarity index 98% rename from core/platform/winrt/Device-winrt.cpp rename to axmol/platform/winrt/Device-winrt.cpp index 1d8317d8cd54..ae260174f0bf 100644 --- a/core/platform/winrt/Device-winrt.cpp +++ b/axmol/platform/winrt/Device-winrt.cpp @@ -25,7 +25,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) # include @@ -34,11 +34,11 @@ THE SOFTWARE. # include # include # include "ntcvt/ntcvt.hpp" -# include "platform/Device.h" -# include "platform/FileUtils.h" -# include "platform/winrt/WinRTUtils.h" -# include "platform/StdC.h" -# include "platform/winrt/RenderViewImpl-winrt.h" +# include "axmol/platform/Device.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/platform/winrt/WinRTUtils.h" +# include "axmol/platform/StdC.h" +# include "axmol/platform/winrt/RenderViewImpl-winrt.h" # include diff --git a/core/platform/winrt/FileUtilsWinRT.cpp b/axmol/platform/winrt/FileUtilsWinRT.cpp similarity index 98% rename from core/platform/winrt/FileUtilsWinRT.cpp rename to axmol/platform/winrt/FileUtilsWinRT.cpp index 3ea6fb4ffd38..62cb8f93bff7 100644 --- a/core/platform/winrt/FileUtilsWinRT.cpp +++ b/axmol/platform/winrt/FileUtilsWinRT.cpp @@ -24,10 +24,10 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/winrt/FileUtilsWinRT.h" +#include "axmol/platform/winrt/FileUtilsWinRT.h" #include -#include "platform/winrt/WinRTUtils.h" -#include "platform/Common.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/platform/Common.h" #include "ntcvt/ntcvt.hpp" #include diff --git a/core/platform/winrt/FileUtilsWinRT.h b/axmol/platform/winrt/FileUtilsWinRT.h similarity index 85% rename from core/platform/winrt/FileUtilsWinRT.h rename to axmol/platform/winrt/FileUtilsWinRT.h index a2c034660d71..d56c9210004e 100644 --- a/core/platform/winrt/FileUtilsWinRT.h +++ b/axmol/platform/winrt/FileUtilsWinRT.h @@ -29,9 +29,9 @@ #include #include -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "base/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" namespace ax { @@ -53,19 +53,19 @@ class AX_DLL FileUtilsWinRT : public FileUtils /* override functions */ bool init(); virtual std::string getWritablePath() const; - virtual bool isAbsolutePath(std::string_view strPath) const override; + bool isAbsolutePath(std::string_view strPath) const override; virtual std::string getPathForFilename(std::string_view filename, std::string_view resolutionDirectory) const override; virtual std::string getFullPathForFilenameWithinDirectory(std::string_view strDirectory, std::string_view strFilename) const override; //virtual std::string getSuitableFOpen(const std::string_view& filenameUtf8) const override; - virtual int64_t getFileSize(std::string_view filepath) const override; + int64_t getFileSize(std::string_view filepath) const override; static std::string getAppPath(); std::string getNativeWritableAbsolutePath() const override; private: - virtual bool isFileExistInternal(std::string_view strFilePath) const override; + bool isFileExistInternal(std::string_view strFilePath) const override; /** * Renames a file under the given directory. @@ -85,14 +85,14 @@ class AX_DLL FileUtilsWinRT : public FileUtils * @param newfullpath The new name of the file, including path and name * @return True if the file have been renamed successfully, false if not. */ - virtual bool renameFile(std::string_view oldfullpath, std::string_view newfullpath) const override; + bool renameFile(std::string_view oldfullpath, std::string_view newfullpath) const override; /** * Checks whether a directory exists without considering search paths and resolution orders. * @param dirPath The directory (with absolute path) to look up for * @return Returns true if the directory found at the given absolute path, otherwise returns false */ - virtual bool isDirectoryExistInternal(std::string_view dirPath) const override; + bool isDirectoryExistInternal(std::string_view dirPath) const override; /** * Removes a file. @@ -100,7 +100,7 @@ class AX_DLL FileUtilsWinRT : public FileUtils * @param filepath The full path of the file, it must be an absolute path. * @return True if the file have been removed successfully, false if not. */ - virtual bool removeFile(std::string_view filepath) const override; + bool removeFile(std::string_view filepath) const override; /** * Creates a directory. @@ -108,7 +108,7 @@ class AX_DLL FileUtilsWinRT : public FileUtils * @param dirPath The path of the directory, it must be an absolute path. * @return True if the directory have been created successfully, false if not. */ - virtual bool createDirectories(std::string_view dirPath) const override; + bool createDirectories(std::string_view dirPath) const override; /** * Removes a directory. @@ -116,7 +116,7 @@ class AX_DLL FileUtilsWinRT : public FileUtils * @param dirPath The full path of the directory, it must be an absolute path. * @return True if the directory have been removed successfully, false if not. */ - virtual bool removeDirectory(std::string_view dirPath) const override; + bool removeDirectory(std::string_view dirPath) const override; }; // end of platform group diff --git a/core/platform/winrt/GL-winrt.h b/axmol/platform/winrt/GL-winrt.h similarity index 100% rename from core/platform/winrt/GL-winrt.h rename to axmol/platform/winrt/GL-winrt.h diff --git a/core/platform/winrt/InputEvent.cpp b/axmol/platform/winrt/InputEvent.cpp similarity index 94% rename from core/platform/winrt/InputEvent.cpp rename to axmol/platform/winrt/InputEvent.cpp index a1e6228def28..b3aa066040a0 100644 --- a/core/platform/winrt/InputEvent.cpp +++ b/axmol/platform/winrt/InputEvent.cpp @@ -24,13 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/winrt/InputEvent.h" -#include "platform/winrt/WinRTUtils.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "base/EventAcceleration.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/IMEDispatcher.h" +#include "axmol/platform/winrt/InputEvent.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/base/EventAcceleration.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/IMEDispatcher.h" namespace ax { diff --git a/core/platform/winrt/InputEvent.h b/axmol/platform/winrt/InputEvent.h similarity index 97% rename from core/platform/winrt/InputEvent.h rename to axmol/platform/winrt/InputEvent.h index 8dfb9e59a516..b463afcf461e 100644 --- a/core/platform/winrt/InputEvent.h +++ b/axmol/platform/winrt/InputEvent.h @@ -26,9 +26,9 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" -#include "platform/winrt/InputEventTypes.h" -#include "base/Types.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/winrt/InputEventTypes.h" +#include "axmol/base/Types.h" #include #include diff --git a/core/platform/winrt/InputEventTypes.h b/axmol/platform/winrt/InputEventTypes.h similarity index 100% rename from core/platform/winrt/InputEventTypes.h rename to axmol/platform/winrt/InputEventTypes.h diff --git a/core/platform/winrt/Keyboard-winrt.cpp b/axmol/platform/winrt/Keyboard-winrt.cpp similarity index 98% rename from core/platform/winrt/Keyboard-winrt.cpp rename to axmol/platform/winrt/Keyboard-winrt.cpp index 352af6de4791..05b077a7a212 100644 --- a/core/platform/winrt/Keyboard-winrt.cpp +++ b/axmol/platform/winrt/Keyboard-winrt.cpp @@ -27,12 +27,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/winrt/Keyboard-winrt.h" -#include "base/EventKeyboard.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "base/IMEDispatcher.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" +#include "axmol/platform/winrt/Keyboard-winrt.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/base/IMEDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" #include #include diff --git a/core/platform/winrt/Keyboard-winrt.h b/axmol/platform/winrt/Keyboard-winrt.h similarity index 98% rename from core/platform/winrt/Keyboard-winrt.h rename to axmol/platform/winrt/Keyboard-winrt.h index 94d938dadc09..593c1aab0455 100644 --- a/core/platform/winrt/Keyboard-winrt.h +++ b/axmol/platform/winrt/Keyboard-winrt.h @@ -30,7 +30,7 @@ THE SOFTWARE. #pragma once #include -#include "platform/winrt/InputEvent.h" +#include "axmol/platform/winrt/InputEvent.h" namespace ax { diff --git a/core/platform/winrt/RenderViewImpl-winrt.cpp b/axmol/platform/winrt/RenderViewImpl-winrt.cpp similarity index 97% rename from core/platform/winrt/RenderViewImpl-winrt.cpp rename to axmol/platform/winrt/RenderViewImpl-winrt.cpp index 6f1395ecbbf7..f3202f18969f 100644 --- a/core/platform/winrt/RenderViewImpl-winrt.cpp +++ b/axmol/platform/winrt/RenderViewImpl-winrt.cpp @@ -25,16 +25,16 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "base/Macros.h" -#include "base/Director.h" -#include "base/Touch.h" -#include "base/IMEDispatcher.h" -#include "base/EventListenerKeyboard.h" -#include "platform/winrt/Application-winrt.h" -#include "platform/winrt/WinRTUtils.h" -#include "base/EventDispatcher.h" -#include "base/EventMouse.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Director.h" +#include "axmol/base/Touch.h" +#include "axmol/base/IMEDispatcher.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/platform/winrt/Application-winrt.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventMouse.h" #include #include diff --git a/core/platform/winrt/RenderViewImpl-winrt.h b/axmol/platform/winrt/RenderViewImpl-winrt.h similarity index 95% rename from core/platform/winrt/RenderViewImpl-winrt.h rename to axmol/platform/winrt/RenderViewImpl-winrt.h index 94bb329f45f2..7f67ac5b3852 100644 --- a/core/platform/winrt/RenderViewImpl-winrt.h +++ b/axmol/platform/winrt/RenderViewImpl-winrt.h @@ -27,12 +27,12 @@ THE SOFTWARE. #pragma once -#include "platform/winrt/StdC-winrt.h" -#include "platform/Common.h" -#include "platform/winrt/Keyboard-winrt.h" -#include "platform/RenderView.h" -#include "base/EventKeyboard.h" -#include "base/EventMouse.h" +#include "axmol/platform/winrt/StdC-winrt.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/winrt/Keyboard-winrt.h" +#include "axmol/platform/RenderView.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventMouse.h" #include #include @@ -71,7 +71,7 @@ class AX_DLL RenderViewImpl : public RenderView * * @param isVisible Hide or Show the mouse cursor if there is one. */ - virtual void setCursorVisible(bool isVisible) override; + void setCursorVisible(bool isVisible) override; bool isCursorVisible() { return _isCursorVisible; } @@ -200,9 +200,5 @@ class AX_DLL RenderViewImpl : public RenderView ax::EventListenerKeyboard* m_backButtonListener; }; -#ifndef AX_CORE_PROFILE -AX_DEPRECATED(2.8) typedef RenderViewImpl GLViewImpl; -#endif - } diff --git a/core/platform/winrt/StdC-winrt.cpp b/axmol/platform/winrt/StdC-winrt.cpp similarity index 98% rename from core/platform/winrt/StdC-winrt.cpp rename to axmol/platform/winrt/StdC-winrt.cpp index 75a58586811d..76afcd349044 100644 --- a/core/platform/winrt/StdC-winrt.cpp +++ b/axmol/platform/winrt/StdC-winrt.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" namespace ax { diff --git a/core/platform/winrt/StdC-winrt.h b/axmol/platform/winrt/StdC-winrt.h similarity index 98% rename from core/platform/winrt/StdC-winrt.h rename to axmol/platform/winrt/StdC-winrt.h index 91364c2d75e5..be567451f64c 100644 --- a/core/platform/winrt/StdC-winrt.h +++ b/axmol/platform/winrt/StdC-winrt.h @@ -31,7 +31,7 @@ THE SOFTWARE. typedef SSIZE_T ssize_t; #endif // __SSIZE_T -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include // for math.h on win32 platform diff --git a/core/platform/winrt/WICImageLoader-winrt.cpp b/axmol/platform/winrt/WICImageLoader-winrt.cpp similarity index 99% rename from core/platform/winrt/WICImageLoader-winrt.cpp rename to axmol/platform/winrt/WICImageLoader-winrt.cpp index cebf5b441646..d71d4c33314b 100644 --- a/core/platform/winrt/WICImageLoader-winrt.cpp +++ b/axmol/platform/winrt/WICImageLoader-winrt.cpp @@ -25,8 +25,8 @@ THE SOFTWARE. Based upon code from the DirectX Tool Kit by Microsoft Corporation, obtained from https://directxtk.codeplex.com ****************************************************************************/ -#include "platform/winrt/WICImageLoader-winrt.h" -#include "platform/winrt/WinRTUtils.h" +#include "axmol/platform/winrt/WICImageLoader-winrt.h" +#include "axmol/platform/winrt/WinRTUtils.h" #include "ntcvt/ntcvt.hpp" namespace ax diff --git a/core/platform/winrt/WICImageLoader-winrt.h b/axmol/platform/winrt/WICImageLoader-winrt.h similarity index 97% rename from core/platform/winrt/WICImageLoader-winrt.h rename to axmol/platform/winrt/WICImageLoader-winrt.h index 985aff61fc28..a76fb82f5859 100644 --- a/core/platform/winrt/WICImageLoader-winrt.h +++ b/axmol/platform/winrt/WICImageLoader-winrt.h @@ -27,7 +27,7 @@ obtained from https://directxtk.codeplex.com #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #if AX_USE_WIC @@ -37,7 +37,7 @@ obtained from https://directxtk.codeplex.com #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/platform/winrt/WinRTUtils.cpp b/axmol/platform/winrt/WinRTUtils.cpp similarity index 97% rename from core/platform/winrt/WinRTUtils.cpp rename to axmol/platform/winrt/WinRTUtils.cpp index 34f892f297cf..d1ddc995101c 100644 --- a/core/platform/winrt/WinRTUtils.cpp +++ b/axmol/platform/winrt/WinRTUtils.cpp @@ -24,11 +24,11 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/winrt/WinRTUtils.h" -#include "base/Macros.h" -#include "platform/PlatformMacros.h" -#include "platform/FileUtils.h" -#include "base/UserDefault.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/UserDefault.h" #include "ntcvt/ntcvt.hpp" #include diff --git a/core/platform/winrt/WinRTUtils.h b/axmol/platform/winrt/WinRTUtils.h similarity index 98% rename from core/platform/winrt/WinRTUtils.h rename to axmol/platform/winrt/WinRTUtils.h index 326ff6afbd8d..fa98c327dbcb 100644 --- a/core/platform/winrt/WinRTUtils.h +++ b/axmol/platform/winrt/WinRTUtils.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include diff --git a/core/platform/winrt/xaml/AxmolRenderer.cpp b/axmol/platform/winrt/xaml/AxmolRenderer.cpp similarity index 95% rename from core/platform/winrt/xaml/AxmolRenderer.cpp rename to axmol/platform/winrt/xaml/AxmolRenderer.cpp index 99aa49a4843d..9b51dca318f9 100644 --- a/core/platform/winrt/xaml/AxmolRenderer.cpp +++ b/axmol/platform/winrt/xaml/AxmolRenderer.cpp @@ -17,11 +17,11 @@ * specific language governing permissions and limitations under the License. */ -#include "AxmolRenderer.h" +#include "axmol/platform/winrt/xaml/AxmolRenderer.h" #include "AppDelegate.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "platform/Application.h" -#include "renderer/TextureCache.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/platform/Application.h" +#include "axmol/renderer/TextureCache.h" // These are used by the shader compilation methods. #include @@ -97,7 +97,7 @@ void AxmolRenderer::DeviceLost() auto director = ax::Director::getInstance(); if (director->getRenderView()) { - backend::DriverBase::getInstance()->resetState(); + rhi::DriverBase::getInstance()->resetState(); ax::Director::getInstance()->resetMatrixStack(); ax::EventCustom recreatedEvent(EVENT_RENDERER_RECREATED); director->getEventDispatcher()->dispatchEvent(&recreatedEvent, true); diff --git a/core/platform/winrt/xaml/AxmolRenderer.h b/axmol/platform/winrt/xaml/AxmolRenderer.h similarity index 96% rename from core/platform/winrt/xaml/AxmolRenderer.h rename to axmol/platform/winrt/xaml/AxmolRenderer.h index ad46fe4d9bb9..179bcd580b15 100644 --- a/core/platform/winrt/xaml/AxmolRenderer.h +++ b/axmol/platform/winrt/xaml/AxmolRenderer.h @@ -18,8 +18,8 @@ */ #pragma once -#include "platform/winrt/InputEvent.h" -#include "base/Types.h" +#include "axmol/platform/winrt/InputEvent.h" +#include "axmol/base/Types.h" #include #include diff --git a/core/platform/winrt/xaml/OpenGLES.cpp b/axmol/platform/winrt/xaml/OpenGLES.cpp similarity index 99% rename from core/platform/winrt/xaml/OpenGLES.cpp rename to axmol/platform/winrt/xaml/OpenGLES.cpp index 2cc19dec52a1..43d480846bea 100644 --- a/core/platform/winrt/xaml/OpenGLES.cpp +++ b/axmol/platform/winrt/xaml/OpenGLES.cpp @@ -17,7 +17,7 @@ * See the License for the specific language governing permissions and limitations under the License. */ -#include "OpenGLES.h" +#include "axmol/platform/winrt/xaml/OpenGLES.h" #include diff --git a/core/platform/winrt/xaml/OpenGLES.h b/axmol/platform/winrt/xaml/OpenGLES.h similarity index 100% rename from core/platform/winrt/xaml/OpenGLES.h rename to axmol/platform/winrt/xaml/OpenGLES.h diff --git a/core/platform/winrt/xaml/OpenGLESPage.cpp b/axmol/platform/winrt/xaml/OpenGLESPage.cpp similarity index 99% rename from core/platform/winrt/xaml/OpenGLESPage.cpp rename to axmol/platform/winrt/xaml/OpenGLESPage.cpp index 2e40216d45b0..3579906b5492 100644 --- a/core/platform/winrt/xaml/OpenGLESPage.cpp +++ b/axmol/platform/winrt/xaml/OpenGLESPage.cpp @@ -17,11 +17,11 @@ * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * specific language governing permissions and limitations under the License. */ -#include "OpenGLESPage.h" +#include "axmol/platform/winrt/xaml/OpenGLESPage.h" #include "OpenGLESPage.g.cpp" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "platform/Application.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/platform/Application.h" #include "yasio/wtimer_hres.hpp" diff --git a/core/platform/winrt/xaml/OpenGLESPage.h b/axmol/platform/winrt/xaml/OpenGLESPage.h similarity index 97% rename from core/platform/winrt/xaml/OpenGLESPage.h rename to axmol/platform/winrt/xaml/OpenGLESPage.h index a6a4387c73b6..9e92e1e502d4 100644 --- a/core/platform/winrt/xaml/OpenGLESPage.h +++ b/axmol/platform/winrt/xaml/OpenGLESPage.h @@ -21,14 +21,14 @@ #include "OpenGLESPage.g.h" -#include "OpenGLES.h" +#include "axmol/platform/winrt/xaml/OpenGLES.h" #include #include #include #include #include -#include "AxmolRenderer.h" +#include "axmol/platform/winrt/xaml/AxmolRenderer.h" #include #include diff --git a/core/platform/winrt/xaml/OpenGLESPage.idl b/axmol/platform/winrt/xaml/OpenGLESPage.idl similarity index 100% rename from core/platform/winrt/xaml/OpenGLESPage.idl rename to axmol/platform/winrt/xaml/OpenGLESPage.idl diff --git a/core/platform/winrt/xaml/OpenGLESPage.xaml b/axmol/platform/winrt/xaml/OpenGLESPage.xaml similarity index 100% rename from core/platform/winrt/xaml/OpenGLESPage.xaml rename to axmol/platform/winrt/xaml/OpenGLESPage.xaml diff --git a/axmol/renderer/CMakeLists.txt b/axmol/renderer/CMakeLists.txt new file mode 100644 index 000000000000..c39e4ce2e17b --- /dev/null +++ b/axmol/renderer/CMakeLists.txt @@ -0,0 +1,45 @@ +set(_AX_RENDERER_HEADER + renderer/CallbackCommand.h + renderer/CustomCommand.h + renderer/GroupCommand.h + renderer/Material.h + renderer/MeshCommand.h + renderer/Pass.h + renderer/PipelineDesc.h + renderer/QuadCommand.h + renderer/RenderCommand.h + renderer/RenderCommandPool.h + renderer/Renderer.h + renderer/RenderState.h + renderer/Technique.h + renderer/Texture2D.h + renderer/TextureAtlas.h + renderer/TextureCache.h + renderer/TextureCube.h + renderer/TrianglesCommand.h + renderer/ProgramManager.h + renderer/ProgramStateRegistry.h + renderer/Shaders.h +) + +set(_AX_RENDERER_SRC + renderer/CallbackCommand.cpp + renderer/CustomCommand.cpp + renderer/GroupCommand.cpp + renderer/Material.cpp + renderer/MeshCommand.cpp + renderer/Pass.cpp + renderer/QuadCommand.cpp + renderer/RenderCommand.cpp + renderer/RenderState.cpp + renderer/Renderer.cpp + renderer/Technique.cpp + renderer/Texture2D.cpp + renderer/TextureAtlas.cpp + renderer/TextureCache.cpp + renderer/TextureCube.cpp + renderer/TrianglesCommand.cpp + renderer/ProgramManager.cpp + renderer/ProgramStateRegistry.cpp + renderer/Shaders.cpp +) diff --git a/core/renderer/CallbackCommand.cpp b/axmol/renderer/CallbackCommand.cpp similarity index 96% rename from core/renderer/CallbackCommand.cpp rename to axmol/renderer/CallbackCommand.cpp index 0d98203c140f..1819259e4cdd 100644 --- a/core/renderer/CallbackCommand.cpp +++ b/axmol/renderer/CallbackCommand.cpp @@ -22,8 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/CallbackCommand.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/rhi/DriverBase.h" namespace ax { diff --git a/core/renderer/CallbackCommand.h b/axmol/renderer/CallbackCommand.h similarity index 93% rename from core/renderer/CallbackCommand.h rename to axmol/renderer/CallbackCommand.h index 41dd196ed6a9..9272f093296c 100644 --- a/core/renderer/CallbackCommand.h +++ b/axmol/renderer/CallbackCommand.h @@ -24,9 +24,9 @@ ****************************************************************************/ #pragma once -#include "renderer/backend/PixelBufferDescriptor.h" -#include "renderer/RenderCommand.h" -#include "base/RefPtr.h" +#include "axmol/rhi/PixelBufferDesc.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/base/RefPtr.h" /** * @addtogroup renderer @@ -36,9 +36,9 @@ namespace ax { -namespace backend +namespace rhi { -class TextureBackend; +class Texture; } /** diff --git a/core/renderer/CustomCommand.cpp b/axmol/renderer/CustomCommand.cpp similarity index 74% rename from core/renderer/CustomCommand.cpp rename to axmol/renderer/CustomCommand.cpp index 0fc957218446..bd017f5dfb72 100644 --- a/core/renderer/CustomCommand.cpp +++ b/axmol/renderer/CustomCommand.cpp @@ -22,11 +22,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/CustomCommand.h" -#include "renderer/TextureAtlas.h" -#include "renderer/backend/Buffer.h" -#include "renderer/backend/DriverBase.h" -#include "base/Utils.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/base/Utils.h" #include namespace ax @@ -40,6 +40,7 @@ CustomCommand::CustomCommand() CustomCommand::~CustomCommand() { AX_SAFE_RELEASE(_vertexBuffer); + AX_SAFE_RELEASE(_instanceBuffer); AX_SAFE_RELEASE(_indexBuffer); } @@ -106,7 +107,7 @@ void CustomCommand::assign(CustomCommand&& rhs) _afterCallback = std::move(rhs._afterCallback); rhs._vertexBuffer = rhs._indexBuffer = nullptr; - rhs._pipelineDescriptor.programState = nullptr; + rhs._pipelineDesc.programState = nullptr; } } #if defined(__INTEL_COMPILER) @@ -129,10 +130,10 @@ void CustomCommand::init(float globalZOrder, const BlendFunc& blendFunc) { _globalOrder = globalZOrder; - auto& blendDescriptor = _pipelineDescriptor.blendDescriptor; - blendDescriptor.blendEnabled = true; - blendDescriptor.sourceRGBBlendFactor = blendDescriptor.sourceAlphaBlendFactor = blendFunc.src; - blendDescriptor.destinationRGBBlendFactor = blendDescriptor.destinationAlphaBlendFactor = blendFunc.dst; + auto& blendDesc = _pipelineDesc.blendDesc; + blendDesc.blendEnabled = true; + blendDesc.sourceRGBBlendFactor = blendDesc.sourceAlphaBlendFactor = blendFunc.src; + blendDesc.destinationRGBBlendFactor = blendDesc.destinationAlphaBlendFactor = blendFunc.dst; } void CustomCommand::createVertexBuffer(std::size_t vertexSize, std::size_t capacity, BufferUsage usage) @@ -142,7 +143,29 @@ void CustomCommand::createVertexBuffer(std::size_t vertexSize, std::size_t capac _vertexCapacity = capacity; _vertexDrawCount = capacity; - _vertexBuffer = backend::DriverBase::getInstance()->newBuffer(vertexSize * capacity, backend::BufferType::VERTEX, usage); + _vertexBuffer = + rhi::DriverBase::getInstance()->createBuffer(vertexSize * capacity, rhi::BufferType::VERTEX, usage); +} + +void CustomCommand::createInstanceBuffer(std::size_t vertexSize, int capacity, BufferUsage usage) +{ + AX_SAFE_RELEASE(_instanceBuffer); + _instanceBuffer = + rhi::DriverBase::getInstance()->createBuffer(vertexSize * capacity, rhi::BufferType::VERTEX, usage); + _instanceCapacity = capacity; + _instanceCount = capacity; +} + +void CustomCommand::setInstanceBuffer(rhi::Buffer* instanceBuffer, int count) +{ + if (_instanceBuffer != instanceBuffer) + { + AX_SAFE_RELEASE(_instanceBuffer); + _instanceBuffer = instanceBuffer; + _instanceCount = count; + _instanceCapacity = count; + AX_SAFE_RETAIN(_instanceBuffer); + } } void CustomCommand::createIndexBuffer(IndexFormat format, std::size_t capacity, BufferUsage usage) @@ -154,7 +177,8 @@ void CustomCommand::createIndexBuffer(IndexFormat format, std::size_t capacity, _indexCapacity = capacity; _indexDrawCount = capacity; - _indexBuffer = backend::DriverBase::getInstance()->newBuffer(_indexSize * capacity, backend::BufferType::INDEX, usage); + _indexBuffer = + rhi::DriverBase::getInstance()->createBuffer(_indexSize * capacity, rhi::BufferType::INDEX, usage); } void CustomCommand::updateVertexBuffer(const void* data, std::size_t offset, std::size_t length) @@ -169,7 +193,7 @@ void CustomCommand::updateIndexBuffer(const void* data, std::size_t offset, std: _indexBuffer->updateSubData(data, offset, length); } -void CustomCommand::setVertexBuffer(backend::Buffer* vertexBuffer) +void CustomCommand::setVertexBuffer(rhi::Buffer* vertexBuffer) { if (_vertexBuffer == vertexBuffer) return; @@ -177,9 +201,12 @@ void CustomCommand::setVertexBuffer(backend::Buffer* vertexBuffer) AX_SAFE_RELEASE(_vertexBuffer); _vertexBuffer = vertexBuffer; AX_SAFE_RETAIN(_vertexBuffer); + + if (!_vertexBuffer) + _vertexCapacity = _vertexDrawCount = 0; } -void CustomCommand::setIndexBuffer(backend::Buffer* indexBuffer, IndexFormat format) +void CustomCommand::setIndexBuffer(rhi::Buffer* indexBuffer, IndexFormat format) { if (_indexBuffer == indexBuffer && _indexFormat == format) return; @@ -190,6 +217,9 @@ void CustomCommand::setIndexBuffer(backend::Buffer* indexBuffer, IndexFormat for _indexFormat = format; _indexSize = computeIndexSize(); + + if(!_indexBuffer) + _indexCapacity = _indexDrawCount = 0; } void CustomCommand::updateVertexBuffer(const void* data, std::size_t length) @@ -204,6 +234,12 @@ void CustomCommand::updateIndexBuffer(const void* data, std::size_t length) _indexBuffer->updateData(data, length); } +void CustomCommand::updateInstanceBuffer(const void* data, std::size_t length) +{ + assert(_instanceBuffer); + _instanceBuffer->updateData(data, length); +} + std::size_t CustomCommand::computeIndexSize() const { if (IndexFormat::U_SHORT == _indexFormat) @@ -212,4 +248,4 @@ std::size_t CustomCommand::computeIndexSize() const return sizeof(unsigned int); } -} +} // namespace ax diff --git a/core/renderer/CustomCommand.h b/axmol/renderer/CustomCommand.h similarity index 88% rename from core/renderer/CustomCommand.h rename to axmol/renderer/CustomCommand.h index 81233ce9f28b..619ccb0ccfd9 100644 --- a/core/renderer/CustomCommand.h +++ b/axmol/renderer/CustomCommand.h @@ -1,6 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -24,7 +25,7 @@ ****************************************************************************/ #pragma once -#include "renderer/RenderCommand.h" +#include "axmol/renderer/RenderCommand.h" /** * @addtogroup renderer @@ -34,7 +35,7 @@ namespace ax { -namespace backend +namespace rhi { class Buffer; } @@ -49,22 +50,23 @@ class AX_DLL CustomCommand : public RenderCommand enum class DrawType { ARRAY, + ARRAY_INSTANCED, ELEMENT, - ELEMENT_INSTANCE + ELEMENT_INSTANCED }; - using PrimitiveType = backend::PrimitiveType; + using PrimitiveType = rhi::PrimitiveType; /** Buffer usage of vertex/index buffer. If the contents are not updated every frame, then STATIC should be used. Otherwise, DYNAMIC should be used. This flag is not improtant because most GPU drivers ignore it, so it's best left to STATIC. */ - using BufferUsage = backend::BufferUsage; + using BufferUsage = rhi::BufferUsage; /** The index format that determines the size of index data. U_SHORT (65535 vertices) is enough for most cases, But support for U_INT (4294967295 vertices) has been added. */ - using IndexFormat = backend::IndexFormat; + using IndexFormat = rhi::IndexFormat; typedef std::function CallBackFunc; @@ -112,6 +114,8 @@ TODO: should remove it. every frame, otherwise use DYNAMIC. */ void createVertexBuffer(std::size_t vertexSize, std::size_t capacity, BufferUsage usage); + void createInstanceBuffer(std::size_t vertexSize, int capacity, BufferUsage usage); + /** Create an index buffer of the custom command. The buffer size is (indexSize * capacity). Index size is determined by format. If the buffer already exists, then it will delete the @@ -136,6 +140,9 @@ TODO: should remove it. @param length Specifies the size in bytes of the data store region being replaced. */ void updateIndexBuffer(const void* data, std::size_t length); + + void updateInstanceBuffer(const void* data, std::size_t length); + /** Update some or all contents of vertex buffer. @param data Specifies a pointer to the new data that will be copied into the data store. @@ -162,6 +169,8 @@ TODO: should remove it. */ inline std::size_t getIndexCapacity() const { return _indexCapacity; } + int getInstanceCapacity() const { return _instanceCapacity; } + inline void setDrawType(DrawType drawType) { _drawType = drawType; } inline DrawType getDrawType() const { return _drawType; } @@ -171,14 +180,14 @@ TODO: should remove it. /** Set the vertex buffer. The existing vertex buffer will be replaced if exist. */ - void setVertexBuffer(backend::Buffer* vertexBuffer); - inline backend::Buffer* getVertexBuffer() const { return _vertexBuffer; } + void setVertexBuffer(rhi::Buffer* vertexBuffer); + inline rhi::Buffer* getVertexBuffer() const { return _vertexBuffer; } /** Set the index buffer. The existing index buffer will be replaced if exist. */ - void setIndexBuffer(backend::Buffer* indexBuffer, IndexFormat indexFormat); - inline backend::Buffer* getIndexBuffer() const { return _indexBuffer; } + void setIndexBuffer(rhi::Buffer* indexBuffer, IndexFormat indexFormat); + inline rhi::Buffer* getIndexBuffer() const { return _indexBuffer; } /** Set the drawing information if the drawing type is ARRAY. @@ -204,6 +213,8 @@ TODO: should remove it. _indexDrawCount = count; } + void setInstanceDrawInfo(int count) { _instanceCount = count; } + inline std::size_t getIndexDrawOffset() const { return _indexDrawOffset; } inline std::size_t getIndexDrawCount() const { return _indexDrawCount; } @@ -221,11 +232,8 @@ TODO: should remove it. */ void setAfterCallback(const CallBackFunc& after) { _afterCallback = after; } - void setInstanceBuffer(backend::Buffer* transformBuffer, int count) - { - _InstanceTransformBuffer = transformBuffer, _instanceCount = count; - } - backend::Buffer* getInstanceBuffer() const { return _InstanceTransformBuffer; } + void setInstanceBuffer(rhi::Buffer* instanceBuffer, int count); + rhi::Buffer* getInstanceBuffer() const { return _instanceBuffer; } int getInstanceCount() const { return _instanceCount; } const CallBackFunc& getBeforeCallback() { return _beforeCallback; } @@ -235,11 +243,12 @@ TODO: should remove it. protected: std::size_t computeIndexSize() const; - backend::Buffer* _vertexBuffer = nullptr; - backend::Buffer* _indexBuffer = nullptr; + rhi::Buffer* _vertexBuffer = nullptr; + rhi::Buffer* _indexBuffer = nullptr; - backend::Buffer* _InstanceTransformBuffer = nullptr; - int _instanceCount = 0; + rhi::Buffer* _instanceBuffer = nullptr; + int _instanceCount = 0; + int _instanceCapacity = 0; std::size_t _vertexDrawStart = 0; std::size_t _vertexDrawCount = 0; @@ -262,7 +271,7 @@ TODO: should remove it. CallBackFunc _afterCallback = nullptr; }; -} +} // namespace ax /** end of support group @} diff --git a/core/renderer/GroupCommand.cpp b/axmol/renderer/GroupCommand.cpp similarity index 96% rename from core/renderer/GroupCommand.cpp rename to axmol/renderer/GroupCommand.cpp index d126a88734c1..c154830a0a45 100644 --- a/core/renderer/GroupCommand.cpp +++ b/axmol/renderer/GroupCommand.cpp @@ -23,9 +23,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "renderer/GroupCommand.h" -#include "renderer/Renderer.h" -#include "base/Director.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" namespace ax { diff --git a/core/renderer/GroupCommand.h b/axmol/renderer/GroupCommand.h similarity index 97% rename from core/renderer/GroupCommand.h rename to axmol/renderer/GroupCommand.h index ccae254c3b24..4c515ad2b019 100644 --- a/core/renderer/GroupCommand.h +++ b/axmol/renderer/GroupCommand.h @@ -28,8 +28,8 @@ #include #include -#include "base/Object.h" -#include "renderer/RenderCommand.h" +#include "axmol/base/Object.h" +#include "axmol/renderer/RenderCommand.h" /** * @addtogroup renderer diff --git a/core/renderer/Material.cpp b/axmol/renderer/Material.cpp similarity index 88% rename from core/renderer/Material.cpp rename to axmol/renderer/Material.cpp index 96bdcc5c2380..0d553659d6d5 100644 --- a/core/renderer/Material.cpp +++ b/axmol/renderer/Material.cpp @@ -28,16 +28,16 @@ - OGRE3D: http://www.ogre3d.org/ - Qt3D: http://qt-project.org/ ****************************************************************************/ -#include "renderer/Material.h" -#include "renderer/Technique.h" -#include "renderer/Pass.h" -#include "renderer/TextureCache.h" -#include "renderer/Texture2D.h" -#include "renderer/backend/DriverBase.h" -#include "base/Properties.h" -#include "base/Director.h" -#include "platform/FileUtils.h" -#include "base/Logging.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Pass.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/base/Properties.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Logging.h" #include @@ -98,7 +98,7 @@ Material* Material::createWithProperties(Properties* materialProperties) return nullptr; } -Material* Material::createWithProgramState(backend::ProgramState* programState) +Material* Material::createWithProgramState(rhi::ProgramState* programState) { AXASSERT(programState, "Invalid Program State"); @@ -112,7 +112,7 @@ Material* Material::createWithProgramState(backend::ProgramState* programState) return nullptr; } -bool Material::initWithProgramState(backend::ProgramState* state) +bool Material::initWithProgramState(rhi::ProgramState* state) { auto technique = Technique::createWithProgramState(this, state); if (technique) @@ -146,8 +146,8 @@ bool Material::initWithProperties(Properties* materialProperties) void Material::draw(MeshCommand* meshCommands, float globalZOrder, - backend::Buffer* vertexBuffer, - backend::Buffer* indexBuffer, + rhi::Buffer* vertexBuffer, + rhi::Buffer* indexBuffer, CustomCommand::PrimitiveType primitive, CustomCommand::IndexFormat indexFormat, unsigned int indexCount, @@ -257,7 +257,7 @@ bool Material::parsePass(Technique* technique, Properties* passProperties) } // axmol doesn't support Samplers yet. -bool Material::parseSampler(backend::ProgramState* programState, Properties* samplerProperties) +bool Material::parseSampler(rhi::ProgramState* programState, Properties* samplerProperties) { AXASSERT(!samplerProperties->getId().empty(), "Sampler must have an id. The id is the uniform name"); @@ -287,18 +287,18 @@ bool Material::parseSampler(backend::ProgramState* programState, Properties* sam // valid options: REPEAT, CLAMP const char* wrapS = getOptionalString(samplerProperties, "wrapS", "CLAMP_TO_EDGE"); if (strcasecmp(wrapS, "REPEAT") == 0) - texParams.sAddressMode = backend::SamplerAddressMode::REPEAT; + texParams.sAddressMode = rhi::SamplerAddressMode::REPEAT; else if (strcasecmp(wrapS, "CLAMP_TO_EDGE") == 0) - texParams.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + texParams.sAddressMode = rhi::SamplerAddressMode::CLAMP; else AXLOGW("Invalid wrapS: {}", wrapS); // valid options: REPEAT, CLAMP const char* wrapT = getOptionalString(samplerProperties, "wrapT", "CLAMP_TO_EDGE"); if (strcasecmp(wrapT, "REPEAT") == 0) - texParams.tAddressMode = backend::SamplerAddressMode::REPEAT; + texParams.tAddressMode = rhi::SamplerAddressMode::REPEAT; else if (strcasecmp(wrapT, "CLAMP_TO_EDGE") == 0) - texParams.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + texParams.tAddressMode = rhi::SamplerAddressMode::CLAMP; else AXLOGW("Invalid wrapT: {}", wrapT); @@ -307,26 +307,34 @@ bool Material::parseSampler(backend::ProgramState* programState, Properties* sam const char* minFilter = getOptionalString(samplerProperties, "minFilter", usemipmap ? "LINEAR_MIPMAP_NEAREST" : "LINEAR"); if (strcasecmp(minFilter, "NEAREST") == 0) - texParams.minFilter = backend::SamplerFilter::NEAREST; + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; else if (strcasecmp(minFilter, "LINEAR") == 0) - texParams.minFilter = backend::SamplerFilter::LINEAR; - else if (strcasecmp(minFilter, "NEAREST_MIPMAP_NEAREST") == 0) - texParams.minFilter = backend::SamplerFilter::NEAREST; - else if (strcasecmp(minFilter, "LINEAR_MIPMAP_NEAREST") == 0) - texParams.minFilter = backend::SamplerFilter::LINEAR; - else if (strcasecmp(minFilter, "NEAREST_MIPMAP_LINEAR") == 0) - texParams.minFilter = backend::SamplerFilter::LINEAR; - else if (strcasecmp(minFilter, "LINEAR_MIPMAP_LINEAR") == 0) - texParams.minFilter = backend::SamplerFilter::LINEAR; + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + else if (strcasecmp(minFilter, "NEAREST_MIPMAP_NEAREST") == 0) { + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; + texParams.mipFilter = rhi::SamplerFilter::MIP_NEAREST; + } + else if (strcasecmp(minFilter, "LINEAR_MIPMAP_NEAREST") == 0) { + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + texParams.mipFilter = rhi::SamplerFilter::MIP_NEAREST; + } + else if (strcasecmp(minFilter, "NEAREST_MIPMAP_LINEAR") == 0) { + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; + texParams.mipFilter = rhi::SamplerFilter::MIP_LINEAR; + } + else if (strcasecmp(minFilter, "LINEAR_MIPMAP_LINEAR") == 0) { + texParams.minFilter = rhi::SamplerFilter::LINEAR; + texParams.mipFilter = rhi::SamplerFilter::MIP_LINEAR; + } else AXLOGW("Invalid minFilter: {}", minFilter); // valid options: NEAREST, LINEAR const char* magFilter = getOptionalString(samplerProperties, "magFilter", "LINEAR"); if (strcasecmp(magFilter, "NEAREST") == 0) - texParams.magFilter = backend::SamplerFilter::NEAREST; + texParams.magFilter = rhi::SamplerFilter::NEAREST; else if (strcasecmp(magFilter, "LINEAR") == 0) - texParams.magFilter = backend::SamplerFilter::LINEAR; + texParams.magFilter = rhi::SamplerFilter::LINEAR; else AXLOGW("Invalid magFilter: {}", magFilter); @@ -369,7 +377,7 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties) if (vertShader && fragShader) { auto program = ProgramManager::getInstance()->loadProgram(vertShader, fragShader); - auto programState = new backend::ProgramState(program); + auto programState = new rhi::ProgramState(program); pass->setProgramState(programState); // Parse uniforms only if the GLProgramState was created @@ -400,13 +408,13 @@ bool Material::parseShader(Pass* pass, Properties* shaderProperties) return true; } -bool Material::parseUniform(backend::ProgramState* programState, Properties* properties, const char* uniformName) +bool Material::parseUniform(rhi::ProgramState* programState, Properties* properties, const char* uniformName) { bool ret = true; auto type = properties->getType(uniformName); - backend::UniformLocation location; + rhi::UniformLocation location; location = programState->getUniformLocation(uniformName); switch (type) diff --git a/core/renderer/Material.h b/axmol/renderer/Material.h similarity index 85% rename from core/renderer/Material.h rename to axmol/renderer/Material.h index 10c450195511..3a26b781e039 100644 --- a/core/renderer/Material.h +++ b/axmol/renderer/Material.h @@ -33,16 +33,16 @@ #include #include -#include "renderer/RenderState.h" -#include "renderer/Technique.h" -#include "renderer/CustomCommand.h" -#include "base/Object.h" -#include "base/Vector.h" -#include "math/Vec2.h" -#include "math/Vec3.h" -#include "math/Vec4.h" -#include "math/Mat4.h" -#include "platform/PlatformMacros.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/math/Vec2.h" +#include "axmol/math/Vec3.h" +#include "axmol/math/Vec4.h" +#include "axmol/math/Mat4.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { @@ -54,7 +54,7 @@ class Node; class Properties; class RenderState; -namespace backend +namespace rhi { class ProgramState; } @@ -86,7 +86,7 @@ class AX_DLL Material : public Object It will only contain one Technique and one Pass. Added in order to support legacy code. */ - static Material* createWithProgramState(backend::ProgramState* programState); + static Material* createWithProgramState(rhi::ProgramState* programState); /** * Creates a material from the specified properties object. @@ -99,8 +99,8 @@ class AX_DLL Material : public Object void draw(MeshCommand* meshCommand, float globalZOrder, - backend::Buffer* vertexBuffer, - backend::Buffer* indexBuffer, + rhi::Buffer* vertexBuffer, + rhi::Buffer* indexBuffer, CustomCommand::PrimitiveType primitive, CustomCommand::IndexFormat indexFormat, unsigned int indexCount, @@ -149,13 +149,13 @@ class AX_DLL Material : public Object * Set material primitive draw type * @param primitive Primitive draw type */ - void setPrimitiveType(ax::backend::PrimitiveType primitive) { _drawPrimitive = primitive; } + void setPrimitiveType(ax::rhi::PrimitiveType primitive) { _drawPrimitive = primitive; } /** * Get material primitive draw type * @return Primitive draw type */ - ax::backend::PrimitiveType getPrimitiveType() const { return _drawPrimitive; } + ax::rhi::PrimitiveType getPrimitiveType() const { return _drawPrimitive; } /** * Enable material transparent rendering. @@ -181,7 +181,7 @@ class AX_DLL Material : public Object protected: Material(); ~Material(); - bool initWithProgramState(backend::ProgramState* state); + bool initWithProgramState(rhi::ProgramState* state); bool initWithFile(std::string_view file); bool initWithProperties(Properties* materialProperties); @@ -191,8 +191,8 @@ class AX_DLL Material : public Object bool parseTechnique(Properties* properties); bool parsePass(Technique* technique, Properties* properties); bool parseShader(Pass* pass, Properties* properties); - bool parseSampler(backend::ProgramState* programState, Properties* properties); - bool parseUniform(backend::ProgramState* programState, Properties* properties, const char* uniformName); + bool parseSampler(rhi::ProgramState* programState, Properties* properties); + bool parseUniform(rhi::ProgramState* programState, Properties* properties, const char* uniformName); bool parseRenderState(RenderState::StateBlock* state, Properties* properties); // material name @@ -215,8 +215,8 @@ class AX_DLL Material : public Object bool _isTransparent = false; // is this mesh transparent. bool _force2DQueue = false; // render meshes using this material in 2D render queue. - ax::backend::PrimitiveType _drawPrimitive = - ax::backend::PrimitiveType::TRIANGLE; // primitive draw type for meshes + ax::rhi::PrimitiveType _drawPrimitive = + ax::rhi::PrimitiveType::TRIANGLE; // primitive draw type for meshes }; } diff --git a/core/renderer/MeshCommand.cpp b/axmol/renderer/MeshCommand.cpp similarity index 81% rename from core/renderer/MeshCommand.cpp rename to axmol/renderer/MeshCommand.cpp index f357b2b2f964..e175eb11d0df 100644 --- a/core/renderer/MeshCommand.cpp +++ b/axmol/renderer/MeshCommand.cpp @@ -23,22 +23,22 @@ THE SOFTWARE. ****************************************************************************/ -#include "renderer/MeshCommand.h" -#include "base/Macros.h" -#include "base/Configuration.h" -#include "base/Director.h" -#include "base/EventCustom.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "2d/Light.h" -#include "2d/Camera.h" -#include "renderer/Renderer.h" -#include "renderer/TextureAtlas.h" -#include "renderer/Texture2D.h" -#include "renderer/Technique.h" -#include "renderer/Material.h" -#include "renderer/Pass.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventCustom.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/2d/Light.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureAtlas.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Pass.h" #include "xxhash.h" namespace ax diff --git a/core/renderer/MeshCommand.h b/axmol/renderer/MeshCommand.h similarity index 86% rename from core/renderer/MeshCommand.h rename to axmol/renderer/MeshCommand.h index 9beaf0e1a6c1..582edf84f2a8 100644 --- a/core/renderer/MeshCommand.h +++ b/axmol/renderer/MeshCommand.h @@ -1,6 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -26,12 +27,11 @@ #pragma once #include -#include "renderer/RenderCommand.h" -#include "renderer/RenderState.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Types.h" -#include "renderer/CustomCommand.h" -#include "math/Math.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/math/Math.h" namespace ax { @@ -45,17 +45,17 @@ class Material; class AX_DLL MeshCommand : public CustomCommand { public: - // using PrimitiveType = backend::PrimitiveType; + // using PrimitiveType = rhi::PrimitiveType; /** Buffer usage of vertex/index buffer. If the contents is not updated every frame, then use STATIC, other use DYNAMIC. */ - using BufferUsage = backend::BufferUsage; + using BufferUsage = rhi::BufferUsage; /** The index format determine the size for index data. U_SHORT is enough for most cases. */ - using IndexFormat = backend::IndexFormat; + using IndexFormat = rhi::IndexFormat; MeshCommand(); virtual ~MeshCommand(); diff --git a/core/renderer/Pass.cpp b/axmol/renderer/Pass.cpp similarity index 86% rename from core/renderer/Pass.cpp rename to axmol/renderer/Pass.cpp index 8c6c320b0d09..0bb4c3d27059 100644 --- a/core/renderer/Pass.cpp +++ b/axmol/renderer/Pass.cpp @@ -27,20 +27,20 @@ - OGRE3D: http://www.ogre3d.org/ - Qt3D: http://qt-project.org/ ****************************************************************************/ -#include "renderer/Pass.h" +#include "axmol/renderer/Pass.h" #include -#include "renderer/Texture2D.h" -#include "renderer/Technique.h" -#include "renderer/Material.h" -#include "renderer/backend/ProgramState.h" -#include "3d/MeshVertexIndexData.h" -#include "3d/VertexAttribBinding.h" -#include "base/Director.h" -#include "renderer/Renderer.h" - -#include "base/Types.h" -#include "base/Utils.h" -#include "2d/Node.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Material.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/3d/MeshVertexIndexData.h" +#include "axmol/3d/VertexInputBinding.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" + +#include "axmol/base/Types.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/Node.h" namespace ax { @@ -75,7 +75,7 @@ Pass* Pass::create(Technique* technique) return nullptr; } -Pass* Pass::createWithProgramState(Technique* technique, backend::ProgramState* programState) +Pass* Pass::createWithProgramState(Technique* technique, rhi::ProgramState* programState) { auto pass = new Pass(); if (pass->initWithProgramState(technique, programState)) @@ -93,7 +93,7 @@ bool Pass::init(Technique* technique) return true; } -bool Pass::initWithProgramState(Technique* technique, backend::ProgramState* programState) +bool Pass::initWithProgramState(Technique* technique, rhi::ProgramState* programState) { _technique = technique; setProgramState(programState); @@ -104,7 +104,7 @@ Pass::Pass() {} Pass::~Pass() { - AX_SAFE_RELEASE(_vertexAttribBinding); + AX_SAFE_RELEASE(_vertexInputBinding); AX_SAFE_RELEASE(_programState); } @@ -115,8 +115,8 @@ Pass* Pass::clone() const pass->setProgramState(_programState->clone()); - pass->_vertexAttribBinding = _vertexAttribBinding; - AX_SAFE_RETAIN(pass->_vertexAttribBinding); + pass->_vertexInputBinding = _vertexInputBinding; + AX_SAFE_RETAIN(pass->_vertexInputBinding); pass->setTechnique(_technique); @@ -125,12 +125,12 @@ Pass* Pass::clone() const return pass; } -backend::ProgramState* Pass::getProgramState() const +rhi::ProgramState* Pass::getProgramState() const { return _programState; } -void Pass::setProgramState(backend::ProgramState* programState) +void Pass::setProgramState(rhi::ProgramState* programState) { if (_programState != programState) { @@ -176,8 +176,8 @@ void Pass::initUniformLocations() void Pass::draw(MeshCommand* meshCommand, float globalZOrder, - backend::Buffer* vertexBuffer, - backend::Buffer* indexBuffer, + rhi::Buffer* vertexBuffer, + rhi::Buffer* indexBuffer, MeshCommand::PrimitiveType primitive, MeshCommand::IndexFormat indexFormat, unsigned int indexCount, @@ -191,7 +191,7 @@ void Pass::draw(MeshCommand* meshCommand, meshCommand->setIndexBuffer(indexBuffer, indexFormat); meshCommand->setVertexBuffer(vertexBuffer); meshCommand->setIndexDrawInfo(0, indexCount); - meshCommand->getPipelineDescriptor().programState = _programState; + meshCommand->getPipelineDesc().programState = _programState; auto* renderer = Director::getInstance()->getRenderer(); @@ -226,7 +226,7 @@ void Pass::onBeforeVisitCmd(MeshCommand* command) // save renderer states _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); _rendererDepthWrite = renderer->getDepthWrite(); _rendererWinding = renderer->getWinding(); @@ -241,7 +241,7 @@ void Pass::onAfterVisitCmd(MeshCommand* command) auto* renderer = Director::getInstance()->getRenderer(); // restore renderer states renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); renderer->setDepthWrite(_rendererDepthWrite); renderer->setWinding(_rendererWinding); @@ -260,27 +260,27 @@ void Pass::setTechnique(Technique* technique) _technique = technique; // weak reference } -void Pass::setVertexAttribBinding(VertexAttribBinding* binding) +void Pass::setVertexInputBinding(VertexInputBinding* binding) { - if (_vertexAttribBinding != binding) + if (_vertexInputBinding != binding) { - AX_SAFE_RELEASE(_vertexAttribBinding); - _vertexAttribBinding = binding; - AX_SAFE_RETAIN(_vertexAttribBinding); + AX_SAFE_RELEASE(_vertexInputBinding); + _vertexInputBinding = binding; + AX_SAFE_RETAIN(_vertexInputBinding); } } -VertexAttribBinding* Pass::getVertexAttributeBinding() const +VertexInputBinding* Pass::getVertexAttributeBinding() const { - return _vertexAttribBinding; + return _vertexInputBinding; } -void Pass::setUniformTexture(uint32_t slot, backend::TextureBackend* tex) +void Pass::setUniformTexture(uint32_t slot, rhi::Texture* tex) { _programState->setTexture(_locTexture, slot, tex); } -void Pass::setUniformNormTexture(uint32_t slot, backend::TextureBackend* tex) +void Pass::setUniformNormTexture(uint32_t slot, rhi::Texture* tex) { _programState->setTexture(_locNormalTexture, slot, tex); } diff --git a/core/renderer/Pass.h b/axmol/renderer/Pass.h similarity index 62% rename from core/renderer/Pass.h rename to axmol/renderer/Pass.h index 9142f82e1f97..e1c5c4c6cf91 100644 --- a/core/renderer/Pass.h +++ b/axmol/renderer/Pass.h @@ -31,48 +31,48 @@ #include -#include "platform/PlatformMacros.h" -#include "renderer/RenderState.h" -#include "renderer/MeshCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CallbackCommand.h" namespace ax { class Technique; class Node; -class VertexAttribBinding; +class VertexInputBinding; class MeshIndexData; class RenderState; -namespace backend +namespace rhi { class ProgramState; class Buffer; -} // namespace backend +} // namespace rhi class AX_DLL Pass : public Object { friend class Material; friend class Technique; friend class RenderState; - friend class VertexAttribBinding; + friend class VertexInputBinding; public: /** Creates a Pass with a GLProgramState. */ - static Pass* createWithProgramState(Technique* parent, backend::ProgramState* programState); + static Pass* createWithProgramState(Technique* parent, rhi::ProgramState* programState); static Pass* create(Technique* parent); /** Returns the ProgramState */ - backend::ProgramState* getProgramState() const; + rhi::ProgramState* getProgramState() const; void draw(MeshCommand* meshCommand, float globalZOrder, - backend::Buffer* vertexBuffer, - backend::Buffer* indexBuffer, + rhi::Buffer* vertexBuffer, + rhi::Buffer* indexBuffer, MeshCommand::PrimitiveType primitive, MeshCommand::IndexFormat indexFormat, unsigned int indexCount, @@ -81,19 +81,19 @@ class AX_DLL Pass : public Object /** * Sets a vertex attribute binding for this pass. * - * When a mesh binding is set, the VertexAttribBinding will be automatically + * When a mesh binding is set, the VertexInputBinding will be automatically * bound when the bind() method is called for the pass. * - * @param binding The VertexAttribBinding to set (or NULL to remove an existing binding). + * @param binding The VertexInputBinding to set (or NULL to remove an existing binding). */ - void setVertexAttribBinding(VertexAttribBinding* binding); + void setVertexInputBinding(VertexInputBinding* binding); /** * Returns the vertex attribute binding for this pass. * * @return The vertex attribute binding for this pass. */ - VertexAttribBinding* getVertexAttributeBinding() const; + VertexInputBinding* getVertexAttributeBinding() const; void setName(std::string_view name) { _name = name; } std::string_view getName() const { return _name; } @@ -108,8 +108,8 @@ class AX_DLL Pass : public Object void updateMVPUniform(const Mat4& modelView); - void setUniformTexture(uint32_t slot, backend::TextureBackend*); // u_tex0 - void setUniformNormTexture(uint32_t slot, backend::TextureBackend*); // u_normalTex + void setUniformTexture(uint32_t slot, rhi::Texture*); // u_tex0 + void setUniformNormTexture(uint32_t slot, rhi::Texture*); // u_normalTex void setUniformColor(const void*, size_t); // ucolor void setUniformMatrixPalette(const void*, size_t); // u_matrixPalette @@ -134,13 +134,13 @@ class AX_DLL Pass : public Object Pass(); ~Pass(); bool init(Technique* parent); - bool initWithProgramState(Technique* parent, backend::ProgramState* glProgramState); + bool initWithProgramState(Technique* parent, rhi::ProgramState* glProgramState); - void setProgramState(backend::ProgramState* programState); + void setProgramState(rhi::ProgramState* programState); Node* getTarget() const; - VertexAttribBinding* _vertexAttribBinding = nullptr; - backend::ProgramState* _programState = nullptr; + VertexInputBinding* _vertexInputBinding = nullptr; + rhi::ProgramState* _programState = nullptr; Technique* _technique = nullptr; bool _hashDirty = true; RenderState _renderState; @@ -151,38 +151,38 @@ class AX_DLL Pass : public Object void onBeforeVisitCmd(MeshCommand*); void onAfterVisitCmd(MeshCommand*); - backend::UniformLocation _locMVPMatrix; - backend::UniformLocation _locMVMatrix; - backend::UniformLocation _locPMatrix; - backend::UniformLocation _locNormalMatrix; + rhi::UniformLocation _locMVPMatrix; + rhi::UniformLocation _locMVMatrix; + rhi::UniformLocation _locPMatrix; + rhi::UniformLocation _locNormalMatrix; - backend::UniformLocation _locTexture; // u_tex0 - backend::UniformLocation _locNormalTexture; // u_normalTex + rhi::UniformLocation _locTexture; // u_tex0 + rhi::UniformLocation _locNormalTexture; // u_normalTex - backend::UniformLocation _locColor; // ucolor - backend::UniformLocation _locMatrixPalette; // u_matrixPalette + rhi::UniformLocation _locColor; // ucolor + rhi::UniformLocation _locMatrixPalette; // u_matrixPalette - backend::UniformLocation _locDirLightColor; - backend::UniformLocation _locDirLightDir; + rhi::UniformLocation _locDirLightColor; + rhi::UniformLocation _locDirLightDir; - backend::UniformLocation _locPointLightColor; - backend::UniformLocation _locPointLightPosition; - backend::UniformLocation _locPointLightRangeInverse; + rhi::UniformLocation _locPointLightColor; + rhi::UniformLocation _locPointLightPosition; + rhi::UniformLocation _locPointLightRangeInverse; - backend::UniformLocation _locSpotLightColor; - backend::UniformLocation _locSpotLightPosition; - backend::UniformLocation _locSpotLightDir; - backend::UniformLocation _locSpotLightInnerAngleCos; - backend::UniformLocation _locSpotLightOuterAngleCos; - backend::UniformLocation _locSpotLightRangeInverse; + rhi::UniformLocation _locSpotLightColor; + rhi::UniformLocation _locSpotLightPosition; + rhi::UniformLocation _locSpotLightDir; + rhi::UniformLocation _locSpotLightInnerAngleCos; + rhi::UniformLocation _locSpotLightOuterAngleCos; + rhi::UniformLocation _locSpotLightRangeInverse; - backend::UniformLocation _locAmbientLigthColor; + rhi::UniformLocation _locAmbientLigthColor; // renderer state cache variables bool _rendererDepthTestEnabled = true; - backend::CompareFunction _rendererDepthCmpFunc = backend::CompareFunction::LESS; - backend::CullMode _rendererCullMode = backend::CullMode::BACK; - backend::Winding _rendererWinding = backend::Winding::COUNTER_CLOCK_WISE; + rhi::CompareFunc _rendererDepthCmpFunc = rhi::CompareFunc::LESS; + rhi::CullMode _rendererCullMode = rhi::CullMode::BACK; + rhi::Winding _rendererWinding = rhi::Winding::COUNTER_CLOCK_WISE; bool _rendererDepthWrite = false; }; diff --git a/core/renderer/PipelineDescriptor.h b/axmol/renderer/PipelineDesc.h similarity index 78% rename from core/renderer/PipelineDescriptor.h rename to axmol/renderer/PipelineDesc.h index 358d96edef14..1ce6395bdabe 100644 --- a/core/renderer/PipelineDescriptor.h +++ b/axmol/renderer/PipelineDesc.h @@ -1,5 +1,6 @@ /**************************************************************************** Copyright (c) 2019 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -23,12 +24,12 @@ ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" -#include "renderer/backend/DepthStencilState.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/VertexLayout.h" -#include "renderer/backend/RenderPassDescriptor.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/rhi/DepthStencilState.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/VertexLayout.h" +#include "axmol/rhi/RenderPassDesc.h" +#include "axmol/rhi/ProgramState.h" #include @@ -39,10 +40,10 @@ namespace ax { -struct AX_DLL PipelineDescriptor +struct PipelineDesc { - backend::ProgramState* programState = nullptr; - backend::BlendDescriptor blendDescriptor; + rhi::ProgramState* programState{nullptr}; + rhi::BlendDesc blendDesc; }; // end of renderer group diff --git a/core/renderer/backend/ProgramManager.cpp b/axmol/renderer/ProgramManager.cpp similarity index 86% rename from core/renderer/backend/ProgramManager.cpp rename to axmol/renderer/ProgramManager.cpp index a7abce33cf10..bcf790c07fb3 100644 --- a/core/renderer/backend/ProgramManager.cpp +++ b/axmol/renderer/ProgramManager.cpp @@ -23,36 +23,48 @@ THE SOFTWARE. ****************************************************************************/ -#include "ProgramManager.h" -#include "DriverBase.h" -#include "ShaderModule.h" -#include "renderer/Shaders.h" -#include "base/Macros.h" -#include "base/Configuration.h" +#include "axmol/renderer/ProgramManager.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/ShaderModule.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/base/Macros.h" +#include "axmol/base/Configuration.h" #include "xxhash.h" -#include -NS_AX_BACKEND_BEGIN +namespace ax { -ProgramManager* ProgramManager::_sharedProgramManager = nullptr; +ProgramManager* ProgramManager::_instance = nullptr; ProgramManager* ProgramManager::getInstance() { - if (!_sharedProgramManager) + if (!_instance) { - _sharedProgramManager = new ProgramManager(); - if (!_sharedProgramManager->init()) - { - AX_SAFE_DELETE(_sharedProgramManager); - } + _instance = new ProgramManager(); + _instance->init(); } - return _sharedProgramManager; + return _instance; } void ProgramManager::destroyInstance() { - AX_SAFE_DELETE(_sharedProgramManager); + AX_SAFE_DELETE(_instance); +} + +int ProgramManager::chooseSpriteProgramType(rhi::PixelFormat pixelFormat) +{ + switch (pixelFormat) + { + case PixelFormat::R8: + return rhi::ProgramType::POSITION_TEXTURE_GRAY; + case PixelFormat::RG8: + return rhi::ProgramType::POSITION_TEXTURE_GRAY_ALPHA; + case PixelFormat::RGBA8: + return rhi::ProgramType::POSITION_TEXTURE_COLOR; + default: + AXLOGW("Warning: chooseSpriteProgramType() unhandled pixel format {}", (int)pixelFormat); + return rhi::ProgramType::POSITION_TEXTURE_COLOR; + } } ProgramManager::ProgramManager() @@ -69,7 +81,7 @@ ProgramManager::~ProgramManager() AX_SAFE_RELEASE(program.second); } AXLOGD("deallocing ProgramManager: {}", fmt::ptr(this)); - backend::ShaderCache::destroyInstance(); + rhi::ShaderCache::destroyInstance(); } // ### end of vertex layout setup functions @@ -82,7 +94,7 @@ static std::string joinPath(std::string_view path, std::string_view childPath) return ret; } -bool ProgramManager::init() +void ProgramManager::init() { auto fileUtils = FileUtils::getInstance(); #if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX @@ -115,6 +127,10 @@ bool ProgramManager::init() VertexLayoutType::Texture); registerProgram(ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST, positionTextureColor_vert, positionTextureColorAlphaTest_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::POSITION_TEXTURE_GRAY_ALPHA, positionTextureColor_vert, + positionTextureGrayAlpha_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::POSITION_TEXTURE_GRAY, positionTextureColor_vert, + positionTextureGray_frag, VertexLayoutType::Sprite); registerProgram(ProgramType::POSITION_UCOLOR, positionUColor_vert, positionColor_frag, VertexLayoutType::Pos); registerProgram(ProgramType::DUAL_SAMPLER_GRAY, positionTextureColor_vert, dualSampler_gray_frag, VertexLayoutType::Sprite); @@ -128,10 +144,10 @@ bool ProgramManager::init() colorNormalTexture_frag, VertexLayoutType::Unspec); registerProgram(ProgramType::POSITION_NORMAL_TEXTURE_3D, positionNormalTexture_vert, colorNormalTexture_frag, VertexLayoutType::Unspec); - registerProgram(ProgramType::POSITION_TEXTURE_3D, positionTexture3D_vert, colorTexture_frag, - VertexLayoutType::Unspec); - registerProgram(ProgramType::POSITION_TEXTURE_3D_INSTANCE, positionTextureInstance_vert, colorTexture_frag, + registerProgram(ProgramType::UNLIT, unlit_vert, colorTexture_frag, VertexLayoutType::Unspec); + registerProgram(ProgramType::UNLIT_INSTANCE, unlit_instance_vert, colorTexture_frag, + VertexLayoutType::Instanced); registerProgram(ProgramType::POSITION_3D, position_vert, color_frag, VertexLayoutType::Unspec); registerProgram(ProgramType::POSITION_NORMAL_3D, positionNormalTexture_vert, colorNormal_frag, VertexLayoutType::Unspec); @@ -140,8 +156,9 @@ bool ProgramManager::init() registerProgram(ProgramType::SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D, skinPositionNormalTexture_vert_1, colorNormalTexture_frag_1, VertexLayoutType::Unspec); registerProgram(ProgramType::TERRAIN_3D, terrain_vert, terrain_frag, VertexLayoutType::Terrain3D); - registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, VertexLayoutType::PU3D); - registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutType::PU3D); + registerProgram(ProgramType::PARTICLE_TEXTURE_3D, particle_vert, particleTexture_frag, + VertexLayoutType::PosUvColor); + registerProgram(ProgramType::PARTICLE_COLOR_3D, particle_vert, particleColor_frag, VertexLayoutType::PosUvColor); registerProgram(ProgramType::QUAD_COLOR_2D, quadColor_vert, quadColor_frag, VertexLayoutType::Unspec); registerProgram(ProgramType::QUAD_TEXTURE_2D, quadTexture_vert, quadTexture_frag, VertexLayoutType::Unspec); registerProgram(ProgramType::HSV, positionTextureColor_vert, hsv_frag, VertexLayoutType::Sprite); @@ -155,6 +172,8 @@ bool ProgramManager::init() registerProgram(ProgramType::VIDEO_TEXTURE_I420, positionTextureColor_vert, videoTextureI420_frag, VertexLayoutType::Sprite); + registerProgram(ProgramType::TRAIL_2D, trail_2d_vert, positionTextureColor_frag, VertexLayoutType::Sprite2D); + // The builtin dual sampler shader registry ProgramStateRegistry::getInstance()->registerProgram(ProgramType::POSITION_TEXTURE_COLOR, TextureSamplerFlag::DUAL_SAMPLER, ProgramType::DUAL_SAMPLER); @@ -164,7 +183,6 @@ bool ProgramManager::init() ProgramStateRegistry::getInstance()->registerProgram(ProgramType::HSV, TextureSamplerFlag::DUAL_SAMPLER, ProgramType::HSV_DUAL_SAMPLER); - return true; } Program* ProgramManager::getBuiltinProgram(uint32_t type) @@ -210,13 +228,13 @@ Program* ProgramManager::loadProgram(std::string_view vsName, auto fragFile = fileUtils->fullPathForFilename(fsName); auto vertSource = fileUtils->getStringFromFile(vertFile); auto fragSource = fileUtils->getStringFromFile(fragFile); - auto program = backend::DriverBase::getInstance()->newProgram(vertSource, fragSource); + auto program = rhi::DriverBase::getInstance()->createProgram(vertSource, fragSource); if (program) { program->setProgramIds(progType, progId); if (vlt < VertexLayoutType::Count) - program->setupVertexLayout(vlt); + program->defineVertexLayout(vlt); _cachedPrograms.emplace(progId, program); } return program; @@ -286,7 +304,6 @@ void ProgramManager::unloadUnusedPrograms() auto program = iter->second; if (program->getReferenceCount() == 1) { - // AXLOGD("TextureCache: removing unused program"); program->release(); iter = _cachedPrograms.erase(iter); } @@ -307,4 +324,4 @@ void ProgramManager::unloadAllPrograms() _cachedPrograms.clear(); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ProgramManager.h b/axmol/renderer/ProgramManager.h similarity index 77% rename from core/renderer/backend/ProgramManager.h rename to axmol/renderer/ProgramManager.h index e40a4273fa0f..ad4537aab83c 100644 --- a/core/renderer/backend/ProgramManager.h +++ b/axmol/renderer/ProgramManager.h @@ -25,24 +25,30 @@ #pragma once -#include "Macros.h" -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "Program.h" - +#include "axmol/platform/PlatformMacros.h" #include #include #include -#include "ProgramStateRegistry.h" +#include "axmol/rhi/Program.h" +#include "axmol/renderer/ProgramStateRegistry.h" struct XXH64_state_s; -NS_AX_BACKEND_BEGIN +namespace ax { /** - * @addtogroup _backend + * @addtogroup _renderer * @{ */ +/** + * @alias some feq use types to namespace ax + */ +using ProgramType = ::ax::rhi::ProgramType; +using ProgramState = ::ax::rhi::ProgramState; +using Program = ::ax::rhi::Program; +using VertexLayout = ::ax::rhi::VertexLayout; +using VertexLayoutType = ::ax::rhi::VertexLayoutType; + /** * Cache and reuse program object. */ @@ -55,6 +61,8 @@ class AX_DLL ProgramManager /** purges the cache. It releases the retained instance. */ static void destroyInstance(); + static int chooseSpriteProgramType(rhi::PixelFormat pixelFormat); + /// get built-in program Program* getBuiltinProgram(uint32_t type); @@ -103,23 +111,6 @@ class AX_DLL ProgramManager * Unload all program objects from cache. */ void unloadAllPrograms(); -#ifndef AX_CORE_PROFILE - /** - * Remove a program object from cache. - * @param program Specifies the program object to move. - */ - AX_DEPRECATED(2.1) void removeProgram(Program* prog) { unloadProgram(prog); } - - /** - * Remove all unused program objects from cache. - */ - AX_DEPRECATED(2.1) void removeUnusedProgram() { unloadUnusedPrograms(); } - - /** - * Remove all program objects from cache. - */ - AX_DEPRECATED(2.1) void removeAllPrograms() { unloadAllPrograms(); } -#endif protected: ProgramManager(); virtual ~ProgramManager(); @@ -127,7 +118,7 @@ class AX_DLL ProgramManager /** * Pre-load programs into cache. */ - bool init(); + void init(); /** * register a program @@ -156,35 +147,18 @@ class AX_DLL ProgramManager VertexLayoutType vlt; }; - BuiltinRegInfo _builtinRegistry[(int)backend::ProgramType::BUILTIN_COUNT]; + BuiltinRegInfo _builtinRegistry[(int)rhi::ProgramType::BUILTIN_COUNT]; std::unordered_map _customRegistry; std::unordered_map _cachedPrograms; ///< The cached program object. XXH64_state_s* _programIdGen; - static ProgramManager* _sharedProgramManager; ///< A shared instance of the program cache. + static ProgramManager* _instance; ///< A shared instance of the program cache. }; -using ProgramCache = ProgramManager; // for compatible +#define axpm ax::ProgramManager::getInstance() -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END - -/** - * @alias some feq use types to namespace ax - */ - -namespace ax -{ - -using ProgramType = ::ax::backend::ProgramType; -using ProgramState = ::ax::backend::ProgramState; -using Program = ::ax::backend::Program; -using VertexLayout = ::ax::backend::VertexLayout; -using VertexLayoutType = ::ax::backend::VertexLayoutType; -using ProgramManager = ::ax::backend::ProgramManager; -using ProgramRegistry = ::ax::backend::ProgramStateRegistry; - } diff --git a/core/renderer/backend/ProgramStateRegistry.cpp b/axmol/renderer/ProgramStateRegistry.cpp similarity index 76% rename from core/renderer/backend/ProgramStateRegistry.cpp rename to axmol/renderer/ProgramStateRegistry.cpp index 809137f1bc76..aa48e5c863c6 100644 --- a/core/renderer/backend/ProgramStateRegistry.cpp +++ b/axmol/renderer/ProgramStateRegistry.cpp @@ -1,6 +1,6 @@ -#include "ProgramStateRegistry.h" +#include "axmol/renderer/ProgramStateRegistry.h" -NS_AX_BACKEND_BEGIN +namespace ax { static ProgramStateRegistry* _sharedStateRegistry = nullptr; /** returns the shared instance */ @@ -10,11 +10,6 @@ ProgramStateRegistry* ProgramStateRegistry::getInstance() return _sharedStateRegistry; _sharedStateRegistry = new ProgramStateRegistry(); - if (!_sharedStateRegistry->init()) - { - AX_SAFE_DELETE(_sharedStateRegistry); - } - return _sharedStateRegistry; } @@ -24,11 +19,6 @@ void ProgramStateRegistry::destroyInstance() AX_SAFE_DELETE(_sharedStateRegistry); } -bool ProgramStateRegistry::init() -{ - return true; -} - void ProgramStateRegistry::registerProgram(uint32_t programType, int textureSamplerFlags, uint32_t builtinProgramType) { uint32_t key = (static_cast(programType) << 16) | textureSamplerFlags; @@ -44,7 +34,7 @@ void ProgramStateRegistry::clearPrograms() this->_registry.clear(); } -ProgramState* ProgramStateRegistry::newProgramState(uint32_t programType, int textureSamplerFlags) +rhi::ProgramState* ProgramStateRegistry::newProgramState(uint32_t programType, int textureSamplerFlags) { uint32_t key = ((programType) << 16) | textureSamplerFlags; auto it = this->_registry.find(key); @@ -52,10 +42,10 @@ ProgramState* ProgramStateRegistry::newProgramState(uint32_t programType, int te { auto fallback = it->second; if (fallback) - return new ProgramState(Program::getBuiltinProgram(fallback)); + return new rhi::ProgramState(axpm->getBuiltinProgram(fallback)); } - return new ProgramState(Program::getBuiltinProgram(programType)); + return new rhi::ProgramState(axpm->getBuiltinProgram(programType)); } uint32_t ProgramStateRegistry::getProgramType(uint32_t programType, int textureSamplerFlags) @@ -70,6 +60,6 @@ uint32_t ProgramStateRegistry::getProgramType(uint32_t programType, int textureS } return programType; } -// end of _backend group +// end of _renderer group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ProgramStateRegistry.h b/axmol/renderer/ProgramStateRegistry.h similarity index 66% rename from core/renderer/backend/ProgramStateRegistry.h rename to axmol/renderer/ProgramStateRegistry.h index 7c2805753c11..784224facc8f 100644 --- a/core/renderer/backend/ProgramStateRegistry.h +++ b/axmol/renderer/ProgramStateRegistry.h @@ -1,17 +1,16 @@ #pragma once -#include "Macros.h" -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "Program.h" -#include "ProgramState.h" + +#include "axmol/platform/PlatformMacros.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/ProgramState.h" #include #include -NS_AX_BACKEND_BEGIN +namespace ax { /** - * @addtogroup _backend + * @addtogroup _renderer * @{ * #todo: Rename to ProgramStateRegistry */ @@ -24,18 +23,17 @@ class AX_DLL ProgramStateRegistry /** purges the cache. It releases the retained instance. */ static void destroyInstance(); - bool init(); void clearPrograms(); void registerProgram(uint32_t programType, int textureSamplerFlags, uint32_t builtinProgramType); - ProgramState* newProgramState(uint32_t programType, int textureSamplerFlags); + rhi::ProgramState* newProgramState(uint32_t programType, int textureSamplerFlags); uint32_t getProgramType(uint32_t programType, int textureSamplerFlags); protected: std::unordered_map _registry; }; -// end of _backend group +// end of _renderer group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/QuadCommand.cpp b/axmol/renderer/QuadCommand.cpp similarity index 92% rename from core/renderer/QuadCommand.cpp rename to axmol/renderer/QuadCommand.cpp index a60af606eccc..9f216697399a 100644 --- a/core/renderer/QuadCommand.cpp +++ b/axmol/renderer/QuadCommand.cpp @@ -24,14 +24,14 @@ THE SOFTWARE. ****************************************************************************/ -#include "renderer/QuadCommand.h" +#include "axmol/renderer/QuadCommand.h" -#include "renderer/Material.h" -#include "renderer/Technique.h" -#include "renderer/Renderer.h" -#include "renderer/Pass.h" -#include "renderer/Texture2D.h" -#include "base/Utils.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Pass.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Utils.h" namespace ax { @@ -92,7 +92,7 @@ void QuadCommand::reIndex(int indicesCount) void QuadCommand::init(float globalOrder, Texture2D* texture, const BlendFunc& blendType, - V3F_C4B_T2F_Quad* quads, + V3F_T2F_C4B_Quad* quads, ssize_t quadCount, const Mat4& mv, uint32_t flags) diff --git a/core/renderer/QuadCommand.h b/axmol/renderer/QuadCommand.h similarity index 97% rename from core/renderer/QuadCommand.h rename to axmol/renderer/QuadCommand.h index ebb079769105..9c875271a17f 100644 --- a/core/renderer/QuadCommand.h +++ b/axmol/renderer/QuadCommand.h @@ -28,7 +28,7 @@ #include -#include "renderer/TrianglesCommand.h" +#include "axmol/renderer/TrianglesCommand.h" /** * @addtogroup renderer @@ -63,7 +63,7 @@ class AX_DLL QuadCommand : public TrianglesCommand void init(float globalOrder, Texture2D* texture, const BlendFunc& blendType, - V3F_C4B_T2F_Quad* quads, + V3F_T2F_C4B_Quad* quads, ssize_t quadCount, const Mat4& mv, uint32_t flags); diff --git a/core/renderer/RenderCommand.cpp b/axmol/renderer/RenderCommand.cpp similarity index 95% rename from core/renderer/RenderCommand.cpp rename to axmol/renderer/RenderCommand.cpp index 676eb2657153..a2a06f021932 100644 --- a/core/renderer/RenderCommand.cpp +++ b/axmol/renderer/RenderCommand.cpp @@ -23,9 +23,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/RenderCommand.h" -#include "2d/Camera.h" -#include "2d/Node.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Node.h" namespace ax { diff --git a/core/renderer/RenderCommand.h b/axmol/renderer/RenderCommand.h similarity index 95% rename from core/renderer/RenderCommand.h rename to axmol/renderer/RenderCommand.h index 4f896ae9378d..6e75af37662f 100644 --- a/core/renderer/RenderCommand.h +++ b/axmol/renderer/RenderCommand.h @@ -25,9 +25,9 @@ ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" -#include "base/Types.h" -#include "renderer/PipelineDescriptor.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/PipelineDesc.h" /** * @addtogroup renderer @@ -99,7 +99,7 @@ class AX_DLL RenderCommand /**Set wireframe render mode for this command.*/ void setWireframe(bool value) { _isWireframe = value; } /// Can use the result to change the descriptor content. - inline PipelineDescriptor& getPipelineDescriptor() { return _pipelineDescriptor; } + inline PipelineDesc& getPipelineDesc() { return _pipelineDesc; } const Mat4& getMV() const { return _mv; } @@ -137,7 +137,7 @@ class AX_DLL RenderCommand Mat4 _mv; - PipelineDescriptor _pipelineDescriptor; + PipelineDesc _pipelineDesc; }; } diff --git a/core/renderer/RenderCommandPool.h b/axmol/renderer/RenderCommandPool.h similarity index 98% rename from core/renderer/RenderCommandPool.h rename to axmol/renderer/RenderCommandPool.h index 45323f553bbe..8ae8821feb51 100644 --- a/core/renderer/RenderCommandPool.h +++ b/axmol/renderer/RenderCommandPool.h @@ -28,7 +28,7 @@ #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/renderer/RenderConsts.h.in b/axmol/renderer/RenderConsts.h.in similarity index 100% rename from core/renderer/RenderConsts.h.in rename to axmol/renderer/RenderConsts.h.in diff --git a/core/renderer/RenderState.cpp b/axmol/renderer/RenderState.cpp similarity index 79% rename from core/renderer/RenderState.cpp rename to axmol/renderer/RenderState.cpp index 7ecbb801377f..d3f63be652e4 100644 --- a/core/renderer/RenderState.cpp +++ b/axmol/renderer/RenderState.cpp @@ -26,17 +26,17 @@ ****************************************************************************/ -#include "renderer/RenderState.h" +#include "axmol/renderer/RenderState.h" #include #include -#include "renderer/Texture2D.h" -#include "renderer/Pass.h" -#include "base/Utils.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "renderer/Material.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/Pass.h" +#include "axmol/base/Utils.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Material.h" namespace ax { @@ -52,10 +52,10 @@ void RenderState::bindPass(Pass* pass, MeshCommand* command) assert(pass->_technique && pass->_technique->_material); auto* technique = pass->_technique; auto* material = technique->_material; - auto& pipelineDescriptor = command->getPipelineDescriptor(); + auto& pipelineDesc = command->getPipelineDesc(); // need reset all state - // pipelineDescriptor.blendDescriptor.blendEnabled = true; + // pipelineDesc.blendDesc.blendEnabled = true; // Get the combined modified state bits for our RenderState hierarchy. int32_t overrideBits = _state._modifiedBits; @@ -63,11 +63,11 @@ void RenderState::bindPass(Pass* pass, MeshCommand* command) overrideBits |= material->getStateBlock()._modifiedBits; // Restore renderer state to its default, except for explicitly specified states - RenderState::StateBlock::restoreUnmodifiedStates(overrideBits, &pipelineDescriptor); + RenderState::StateBlock::restoreUnmodifiedStates(overrideBits, &pipelineDesc); - material->getStateBlock().apply(&pipelineDescriptor); - technique->getStateBlock().apply(&pipelineDescriptor); - _state.apply(&pipelineDescriptor); + material->getStateBlock().apply(&pipelineDesc); + technique->getStateBlock().apply(&pipelineDesc); + _state.apply(&pipelineDesc); } RenderState::StateBlock& RenderState::getStateBlock() const @@ -75,24 +75,24 @@ RenderState::StateBlock& RenderState::getStateBlock() const return _state; } -void RenderState::StateBlock::bind(PipelineDescriptor* pipelineDescriptor) +void RenderState::StateBlock::bind(PipelineDesc* pipelineDesc) { // When the public bind() is called with no RenderState object passed in, // we assume we are being called to bind the state of a single StateBlock, // irrespective of whether it belongs to a hierarchy of RenderStates. // Therefore, we call restore() here with only this StateBlock's override // bits to restore state before applying the new state. - StateBlock::restoreUnmodifiedStates(_modifiedBits, pipelineDescriptor); + StateBlock::restoreUnmodifiedStates(_modifiedBits, pipelineDesc); - apply(pipelineDescriptor); + apply(pipelineDesc); } -void RenderState::StateBlock::apply(PipelineDescriptor* pipelineDescriptor) +void RenderState::StateBlock::apply(PipelineDesc* pipelineDesc) { // AX_ASSERT(_globalState); auto renderer = Director::getInstance()->getRenderer(); - auto& blend = pipelineDescriptor->blendDescriptor; + auto& blend = pipelineDesc->blendDesc; // Update any state that differs from _globalState and flip _globalState bits if ((_modifiedBits & RS_BLEND)) @@ -133,14 +133,14 @@ void RenderState::StateBlock::apply(PipelineDescriptor* pipelineDescriptor) if ((_modifiedBits & RS_DEPTH_FUNC)) { - renderer->setDepthCompareFunction(_depthFunction); + renderer->setDepthCompareFunc(_depthFunction); } } -void RenderState::StateBlock::restoreUnmodifiedStates(int32_t overrideBits, PipelineDescriptor* programState) +void RenderState::StateBlock::restoreUnmodifiedStates(int32_t overrideBits, PipelineDesc* programState) { auto renderer = Director::getInstance()->getRenderer(); - auto& blend = programState->blendDescriptor; + auto& blend = programState->blendDesc; // Update any state that differs from _globalState and flip _globalState bits if (!(overrideBits & RS_BLEND)) @@ -150,8 +150,8 @@ void RenderState::StateBlock::restoreUnmodifiedStates(int32_t overrideBits, Pipe if (!(overrideBits & RS_BLEND_FUNC)) { - blend.sourceAlphaBlendFactor = blend.sourceRGBBlendFactor = backend::BlendFactor::ONE; - blend.destinationAlphaBlendFactor = blend.destinationRGBBlendFactor = backend::BlendFactor::ZERO; + blend.sourceAlphaBlendFactor = blend.sourceRGBBlendFactor = rhi::BlendFactor::ONE; + blend.destinationAlphaBlendFactor = blend.destinationRGBBlendFactor = rhi::BlendFactor::ZERO; } if (!(overrideBits & RS_CULL_FACE)) @@ -181,7 +181,7 @@ void RenderState::StateBlock::restoreUnmodifiedStates(int32_t overrideBits, Pipe if (!(overrideBits & RS_DEPTH_FUNC)) { - renderer->setDepthCompareFunction(DepthFunction::LESS); + renderer->setDepthCompareFunc(DepthFunc::LESS); } } @@ -190,71 +190,71 @@ static bool parseBoolean(std::string_view value) return (value.compare("true") == 0); } -static backend::BlendFactor parseBlend(std::string_view value) +static rhi::BlendFactor parseBlend(std::string_view value) { // Convert the string to uppercase for comparison. std::string upper(value); std::transform(upper.begin(), upper.end(), upper.begin(), (int (*)(int))toupper); if (upper == "ZERO") - return backend::BlendFactor::ZERO; + return rhi::BlendFactor::ZERO; else if (upper == "ONE") - return backend::BlendFactor::ONE; + return rhi::BlendFactor::ONE; else if (upper == "SRC_COLOR") - return backend::BlendFactor::SRC_COLOR; + return rhi::BlendFactor::SRC_COLOR; else if (upper == "ONE_MINUS_SRC_COLOR") - return backend::BlendFactor::ONE_MINUS_SRC_COLOR; + return rhi::BlendFactor::ONE_MINUS_SRC_COLOR; else if (upper == "DST_COLOR") - return backend::BlendFactor::DST_COLOR; + return rhi::BlendFactor::DST_COLOR; else if (upper == "ONE_MINUS_DST_COLOR") - return backend::BlendFactor::ONE_MINUS_DST_COLOR; + return rhi::BlendFactor::ONE_MINUS_DST_COLOR; else if (upper == "SRC_ALPHA") - return backend::BlendFactor::SRC_ALPHA; + return rhi::BlendFactor::SRC_ALPHA; else if (upper == "ONE_MINUS_SRC_ALPHA") - return backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + return rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; else if (upper == "DST_ALPHA") - return backend::BlendFactor::DST_ALPHA; + return rhi::BlendFactor::DST_ALPHA; else if (upper == "ONE_MINUS_DST_ALPHA") - return backend::BlendFactor::ONE_MINUS_DST_ALPHA; + return rhi::BlendFactor::ONE_MINUS_DST_ALPHA; else if (upper == "CONSTANT_ALPHA") - return backend::BlendFactor::CONSTANT_ALPHA; + return rhi::BlendFactor::CONSTANT_ALPHA; else if (upper == "ONE_MINUS_CONSTANT_ALPHA") - return backend::BlendFactor::ONE_MINUS_CONSTANT_ALPHA; + return rhi::BlendFactor::ONE_MINUS_CONSTANT_ALPHA; else if (upper == "SRC_ALPHA_SATURATE") - return backend::BlendFactor::SRC_ALPHA_SATURATE; + return rhi::BlendFactor::SRC_ALPHA_SATURATE; else { AXLOGW("Unsupported blend value ({}). (Will default to BLEND_ONE if errors are treated as warnings)", value); - return backend::BlendFactor::ONE; + return rhi::BlendFactor::ONE; } } -static DepthFunction parseDepthFunc(std::string_view value) +static DepthFunc parseDepthFunc(std::string_view value) { // Convert string to uppercase for comparison std::string upper(value); std::transform(upper.begin(), upper.end(), upper.begin(), (int (*)(int))toupper); if (upper == "NEVER") - return DepthFunction::NEVER; + return DepthFunc::NEVER; else if (upper == "LESS") - return DepthFunction::LESS; + return DepthFunc::LESS; else if (upper == "EQUAL") - return DepthFunction::EQUAL; + return DepthFunc::EQUAL; else if (upper == "LEQUAL") - return DepthFunction::LESS_EQUAL; + return DepthFunc::LESS_EQUAL; else if (upper == "GREATER") - return DepthFunction::GREATER; + return DepthFunc::GREATER; else if (upper == "NOTEQUAL") - return DepthFunction::NOT_EQUAL; + return DepthFunc::NOT_EQUAL; else if (upper == "GEQUAL") - return DepthFunction::GREATER_EQUAL; + return DepthFunc::GREATER_EQUAL; else if (upper == "ALWAYS") - return DepthFunction::ALWAYS; + return DepthFunc::ALWAYS; else { AXLOGW("Unsupported depth function value ({}). Will default to DEPTH_LESS if errors are treated as warnings)", value); - return DepthFunction::LESS; + return DepthFunc::LESS; } } @@ -331,7 +331,7 @@ void RenderState::StateBlock::setState(std::string_view name, std::string_view v } else if (name.compare("depthFunc") == 0) { - setDepthFunction(parseDepthFunc(value)); + setDepthFunc(parseDepthFunc(value)); } else { @@ -363,13 +363,13 @@ void RenderState::StateBlock::setBlendFunc(const BlendFunc& blendFunc) setBlendDst(blendFunc.dst); } -void RenderState::StateBlock::setBlendSrc(backend::BlendFactor blend) +void RenderState::StateBlock::setBlendSrc(rhi::BlendFactor blend) { _blendSrc = blend; _modifiedBits |= RS_BLEND_FUNC; } -void RenderState::StateBlock::setBlendDst(backend::BlendFactor blend) +void RenderState::StateBlock::setBlendDst(rhi::BlendFactor blend) { _blendDst = blend; _modifiedBits |= RS_BLEND_FUNC; @@ -405,7 +405,7 @@ void RenderState::StateBlock::setDepthWrite(bool enabled) _modifiedBits |= RS_DEPTH_WRITE; } -void RenderState::StateBlock::setDepthFunction(DepthFunction func) +void RenderState::StateBlock::setDepthFunc(DepthFunc func) { _depthFunction = func; _modifiedBits |= RS_DEPTH_FUNC; diff --git a/core/renderer/RenderState.h b/axmol/renderer/RenderState.h similarity index 89% rename from core/renderer/RenderState.h rename to axmol/renderer/RenderState.h index eca31746b491..4ea532801af9 100644 --- a/core/renderer/RenderState.h +++ b/axmol/renderer/RenderState.h @@ -31,14 +31,13 @@ #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "base/Types.h" -#include "base/Vector.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Vector.h" -#include "renderer/PipelineDescriptor.h" -#include "renderer/backend/Types.h" -#include "renderer/MeshCommand.h" +#include "axmol/renderer/PipelineDesc.h" +#include "axmol/renderer/MeshCommand.h" namespace ax { @@ -47,9 +46,9 @@ class Texture2D; class Pass; class MeshCommand; -using CullFaceSide = backend::CullMode; -using FrontFace = backend::Winding; -using DepthFunction = backend::CompareFunction; +using CullFaceSide = rhi::CullMode; +using FrontFace = rhi::Winding; +using DepthFunc = rhi::CompareFunc; /** * Defines the rendering state of the graphics device. @@ -99,7 +98,7 @@ class AX_DLL RenderState : public Object * This method handles both setting and restoring of render states to ensure that * only the state explicitly defined by this StateBlock is applied to the renderer. */ - void bind(PipelineDescriptor* programState); + void bind(PipelineDesc* programState); /** * Explicitly sets the source and destination used in the blend function for this render state. @@ -124,7 +123,7 @@ class AX_DLL RenderState : public Object * * @param blend Specifies how the source blending factors are computed. */ - void setBlendSrc(backend::BlendFactor blend); + void setBlendSrc(rhi::BlendFactor blend); /** * Explicitly sets the source used in the blend function for this render state. @@ -133,7 +132,7 @@ class AX_DLL RenderState : public Object * * @param blend Specifies how the destination blending factors are computed. */ - void setBlendDst(backend::BlendFactor blend); + void setBlendDst(rhi::BlendFactor blend); /** * Explicitly enables or disables backface culling. @@ -184,7 +183,7 @@ class AX_DLL RenderState : public Object * * @param func The depth function. */ - void setDepthFunction(DepthFunction func); + void setDepthFunc(DepthFunc func); /** * Sets a render state from the given name and value strings. @@ -224,17 +223,17 @@ class AX_DLL RenderState : public Object /** * update internal states of ProgramState */ - void apply(PipelineDescriptor* pipelineDescriptor); + void apply(PipelineDesc* pipelineDesc); - static void restoreUnmodifiedStates(int32_t flags, PipelineDescriptor* pipelineDescriptor); + static void restoreUnmodifiedStates(int32_t flags, PipelineDesc* pipelineDesc); bool _cullFaceEnabled = false; bool _depthTestEnabled = true; bool _depthWriteEnabled = false; - DepthFunction _depthFunction = DepthFunction::LESS; + DepthFunc _depthFunction = DepthFunc::LESS; bool _blendEnabled = true; - backend::BlendFactor _blendSrc = backend::BlendFactor::ONE; - backend::BlendFactor _blendDst = backend::BlendFactor::ZERO; + rhi::BlendFactor _blendSrc = rhi::BlendFactor::ONE; + rhi::BlendFactor _blendDst = rhi::BlendFactor::ZERO; CullFaceSide _cullFaceSide = CullFaceSide::BACK; FrontFace _frontFace = FrontFace::COUNTER_CLOCK_WISE; int32_t _modifiedBits = 0L; diff --git a/core/renderer/Renderer.cpp b/axmol/renderer/Renderer.cpp similarity index 82% rename from core/renderer/Renderer.cpp rename to axmol/renderer/Renderer.cpp index d5c53214d61e..1c74bc8d69ae 100644 --- a/core/renderer/Renderer.cpp +++ b/axmol/renderer/Renderer.cpp @@ -23,31 +23,31 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/Renderer.h" +#include "axmol/renderer/Renderer.h" #include -#include "renderer/TrianglesCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/CallbackCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/MeshCommand.h" -#include "renderer/Material.h" -#include "renderer/Technique.h" -#include "renderer/Pass.h" -#include "renderer/Texture2D.h" - -#include "base/Configuration.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerCustom.h" -#include "base/EventType.h" -#include "2d/Camera.h" -#include "2d/Scene.h" +#include "axmol/renderer/TrianglesCommand.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Pass.h" +#include "axmol/renderer/Texture2D.h" + +#include "axmol/base/Configuration.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventType.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Scene.h" #include "xxhash.h" -#include "renderer/backend/Backend.h" -#include "renderer/backend/RenderTarget.h" +#include "axmol/rhi/axmol-rhi.h" +#include "axmol/rhi/RenderTarget.h" namespace ax { @@ -203,22 +203,27 @@ void Renderer::init() _vertexBuffer = _triangleCommandBufferManager.getVertexBuffer(); _indexBuffer = _triangleCommandBufferManager.getIndexBuffer(); - auto driver = backend::DriverBase::getInstance(); - _commandBuffer = driver->newCommandBuffer(); + auto driver = rhi::DriverBase::getInstance(); +#if AX_RENDER_API == AX_RENDER_API_D3D + auto mainWindowHandle = Director::getInstance()->getRenderView()->getWin32Window(); + _commandBuffer = driver->createCommandBuffer(mainWindowHandle); +#else + _commandBuffer = driver->createCommandBuffer(nullptr); +#endif _dsDesc.flags = DepthStencilFlags::ALL; - _defaultRT = driver->newDefaultRenderTarget(); + _currentRT = _defaultRT = driver->createDefaultRenderTarget(); + _commandBuffer->setScreenRenderTarget(_defaultRT); - _currentRT = _defaultRT; - _renderPipeline = driver->newRenderPipeline(); + _renderPipeline = driver->createRenderPipeline(); _commandBuffer->setRenderPipeline(_renderPipeline); - _depthStencilState = driver->newDepthStencilState(); + _depthStencilState = driver->createDepthStencilState(); _commandBuffer->setDepthStencilState(_depthStencilState); } -backend::RenderTarget* Renderer::getOffscreenRenderTarget() { +rhi::RenderTarget* Renderer::getOffscreenRenderTarget() { if (_offscreenRT != nullptr) return _offscreenRT; - return (_offscreenRT = backend::DriverBase::getInstance()->newRenderTarget()); + return (_offscreenRT = rhi::DriverBase::getInstance()->createRenderTarget()); } void Renderer::addCallbackCommand(std::function func, float globalZOrder) @@ -309,7 +314,7 @@ void Renderer::processRenderCommand(RenderCommand* command) drawBatchedTriangles(); _queuedTotalIndexCount = _queuedTotalVertexCount = 0; -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _queuedIndexCount = _queuedVertexCount = 0; _triangleCommandBufferManager.prepareNextBuffer(); _vertexBuffer = _triangleCommandBufferManager.getVertexBuffer(); @@ -319,7 +324,7 @@ void Renderer::processRenderCommand(RenderCommand* command) // queue it _queuedTriangleCommands.emplace_back(cmd); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _queuedIndexCount += cmd->getIndexCount(); _queuedVertexCount += cmd->getVertexCount(); #endif @@ -357,7 +362,7 @@ void Renderer::visitRenderQueue(RenderQueue& queue) // Apply default state for all render queues setDepthTest(false); setDepthWrite(false); - setCullMode(backend::CullMode::NONE); + setCullMode(rhi::CullMode::NONE); // // Process Global-Z < 0 Objects @@ -370,7 +375,7 @@ void Renderer::visitRenderQueue(RenderQueue& queue) pushStateBlock(); setDepthTest(true); // enable depth test in 3D queue by default setDepthWrite(true); - setCullMode(backend::CullMode::BACK); + setCullMode(rhi::CullMode::BACK); doVisitRenderQueue(queue.getSubQueue(RenderQueue::QUEUE_GROUP::OPAQUE_3D)); // @@ -428,7 +433,7 @@ void Renderer::endFrame() { _commandBuffer->endFrame(); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _triangleCommandBufferManager.putbackAllBuffers(); _vertexBuffer = _triangleCommandBufferManager.getVertexBuffer(); _indexBuffer = _triangleCommandBufferManager.getIndexBuffer(); @@ -478,14 +483,14 @@ void Renderer::setDepthWrite(bool value) _dsDesc.removeFlag(DepthStencilFlags::DEPTH_WRITE); } -void Renderer::setDepthCompareFunction(backend::CompareFunction func) +void Renderer::setDepthCompareFunc(rhi::CompareFunc func) { - _dsDesc.depthCompareFunction = func; + _dsDesc.depthCompareFunc = func; } -backend::CompareFunction Renderer::getDepthCompareFunction() const +rhi::CompareFunc Renderer::getDepthCompareFunc() const { - return _dsDesc.depthCompareFunction; + return _dsDesc.depthCompareFunc; } bool Renderer::Renderer::getDepthTest() const @@ -503,10 +508,10 @@ bool Renderer::getDepthWrite() const return bitmask::any(_dsDesc.flags, DepthStencilFlags::DEPTH_WRITE); } -void Renderer::setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask) +void Renderer::setStencilCompareFunc(rhi::CompareFunc func, unsigned int ref, unsigned int readMask) { - _dsDesc.frontFaceStencil.stencilCompareFunction = func; - _dsDesc.backFaceStencil.stencilCompareFunction = func; + _dsDesc.frontFaceStencil.stencilCompareFunc = func; + _dsDesc.backFaceStencil.stencilCompareFunc = func; _dsDesc.frontFaceStencil.readMask = readMask; _dsDesc.backFaceStencil.readMask = readMask; @@ -514,18 +519,18 @@ void Renderer::setStencilCompareFunction(backend::CompareFunction func, unsigned _stencilRef = ref; } -void Renderer::setStencilOperation(backend::StencilOperation stencilFailureOp, - backend::StencilOperation depthFailureOp, - backend::StencilOperation stencilDepthPassOp) +void Renderer::setStencilOp(rhi::StencilOp stencilFailureOp, + rhi::StencilOp depthFailureOp, + rhi::StencilOp stencilDepthPassOp) { - _dsDesc.frontFaceStencil.stencilFailureOperation = stencilFailureOp; - _dsDesc.backFaceStencil.stencilFailureOperation = stencilFailureOp; + _dsDesc.frontFaceStencil.stencilFailureOp = stencilFailureOp; + _dsDesc.backFaceStencil.stencilFailureOp = stencilFailureOp; - _dsDesc.frontFaceStencil.depthFailureOperation = depthFailureOp; - _dsDesc.backFaceStencil.depthFailureOperation = depthFailureOp; + _dsDesc.frontFaceStencil.depthFailureOp = depthFailureOp; + _dsDesc.backFaceStencil.depthFailureOp = depthFailureOp; - _dsDesc.frontFaceStencil.depthStencilPassOperation = stencilDepthPassOp; - _dsDesc.backFaceStencil.depthStencilPassOperation = stencilDepthPassOp; + _dsDesc.frontFaceStencil.depthStencilPassOp = stencilDepthPassOp; + _dsDesc.backFaceStencil.depthStencilPassOp = stencilDepthPassOp; } void Renderer::setStencilWriteMask(unsigned int mask) @@ -534,24 +539,24 @@ void Renderer::setStencilWriteMask(unsigned int mask) _dsDesc.backFaceStencil.writeMask = mask; } -backend::StencilOperation Renderer::getStencilFailureOperation() const +rhi::StencilOp Renderer::getStencilFailureOp() const { - return _dsDesc.frontFaceStencil.stencilFailureOperation; + return _dsDesc.frontFaceStencil.stencilFailureOp; } -backend::StencilOperation Renderer::getStencilPassDepthFailureOperation() const +rhi::StencilOp Renderer::getStencilPassDepthFailureOp() const { - return _dsDesc.frontFaceStencil.depthFailureOperation; + return _dsDesc.frontFaceStencil.depthFailureOp; } -backend::StencilOperation Renderer::getStencilDepthPassOperation() const +rhi::StencilOp Renderer::getStencilDepthPassOp() const { - return _dsDesc.frontFaceStencil.depthStencilPassOperation; + return _dsDesc.frontFaceStencil.depthStencilPassOp; } -backend::CompareFunction Renderer::getStencilCompareFunction() const +rhi::CompareFunc Renderer::getStencilCompareFunc() const { - return _dsDesc.depthCompareFunction; + return _dsDesc.depthCompareFunc; } unsigned int Renderer::getStencilReadMask() const @@ -569,12 +574,12 @@ unsigned int Renderer::getStencilReferenceValue() const return _stencilRef; } -void Renderer::setDepthStencilDesc(const backend::DepthStencilDescriptor& dsDesc) +void Renderer::setDepthStencilDesc(const rhi::DepthStencilDesc& dsDesc) { _dsDesc = dsDesc; } -const backend::DepthStencilDescriptor& Renderer::getDepthStencilDesc() const +const rhi::DepthStencilDesc& Renderer::getDepthStencilDesc() const { return _dsDesc; } @@ -611,7 +616,7 @@ void Renderer::drawBatchedTriangles() return; /************** 1: Setup up vertices/indices *************/ -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL unsigned int vertexBufferFillOffset = _queuedTotalVertexCount - _queuedVertexCount; unsigned int indexBufferFillOffset = _queuedTotalIndexCount - _queuedIndexCount; #else @@ -675,7 +680,7 @@ void Renderer::drawBatchedTriangles() firstCommand = false; } batchesTotal++; -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _vertexBuffer->updateSubData(_verts, vertexBufferFillOffset * sizeof(_verts[0]), _filledVertex * sizeof(_verts[0])); _indexBuffer->updateSubData(_indices, indexBufferFillOffset * sizeof(_indices[0]), _filledIndex * sizeof(_indices[0])); @@ -693,10 +698,10 @@ void Renderer::drawBatchedTriangles() for (int i = 0; i < batchesTotal; ++i) { auto& drawInfo = _triBatchesToDraw[i]; - _commandBuffer->updatePipelineState(_currentRT, drawInfo.cmd->getPipelineDescriptor()); - auto& pipelineDescriptor = drawInfo.cmd->getPipelineDescriptor(); - _commandBuffer->setProgramState(pipelineDescriptor.programState); - _commandBuffer->drawElements(backend::PrimitiveType::TRIANGLE, backend::IndexFormat::U_SHORT, + _commandBuffer->updatePipelineState(_currentRT, drawInfo.cmd->getPipelineDesc()); + auto& pipelineDesc = drawInfo.cmd->getPipelineDesc(); + _commandBuffer->setProgramState(pipelineDesc.programState); + _commandBuffer->drawElements(rhi::PrimitiveType::TRIANGLE, rhi::IndexFormat::U_SHORT, drawInfo.indicesToDraw, drawInfo.offset * sizeof(_indices[0])); _drawnBatches++; @@ -708,7 +713,7 @@ void Renderer::drawBatchedTriangles() /************** 3: Cleanup *************/ _queuedTriangleCommands.clear(); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL _queuedIndexCount = 0; _queuedVertexCount = 0; #endif @@ -724,30 +729,38 @@ void Renderer::drawCustomCommand(RenderCommand* command) beginRenderPass(); _commandBuffer->setVertexBuffer(cmd->getVertexBuffer()); - _commandBuffer->updatePipelineState(_currentRT, cmd->getPipelineDescriptor()); - _commandBuffer->setProgramState(cmd->getPipelineDescriptor().programState); + _commandBuffer->updatePipelineState(_currentRT, cmd->getPipelineDesc()); + _commandBuffer->setProgramState(cmd->getPipelineDesc().programState); auto drawType = cmd->getDrawType(); - if (CustomCommand::DrawType::ELEMENT == drawType) + switch (drawType) { + case CustomCommand::DrawType::ELEMENT: _commandBuffer->setIndexBuffer(cmd->getIndexBuffer()); _commandBuffer->drawElements(cmd->getPrimitiveType(), cmd->getIndexFormat(), cmd->getIndexDrawCount(), cmd->getIndexDrawOffset(), cmd->isWireframe()); _drawnVertices += cmd->getIndexDrawCount(); - } - else if (CustomCommand::DrawType::ELEMENT_INSTANCE == drawType) - { + break; + case CustomCommand::DrawType::ELEMENT_INSTANCED: _commandBuffer->setIndexBuffer(cmd->getIndexBuffer()); _commandBuffer->setInstanceBuffer(cmd->getInstanceBuffer()); _commandBuffer->drawElementsInstanced(cmd->getPrimitiveType(), cmd->getIndexFormat(), cmd->getIndexDrawCount(), cmd->getIndexDrawOffset(), cmd->getInstanceCount(), cmd->isWireframe()); _drawnVertices += cmd->getIndexDrawCount() * cmd->getInstanceCount(); - } - else - { + break; + case CustomCommand::DrawType::ARRAY: _commandBuffer->drawArrays(cmd->getPrimitiveType(), cmd->getVertexDrawStart(), cmd->getVertexDrawCount(), cmd->isWireframe()); _drawnVertices += cmd->getVertexDrawCount(); + break; + case CustomCommand::DrawType::ARRAY_INSTANCED: + _commandBuffer->setInstanceBuffer(cmd->getInstanceBuffer()); + _commandBuffer->drawArraysInstanced(cmd->getPrimitiveType(), cmd->getVertexDrawStart(), + cmd->getVertexDrawCount(), cmd->getInstanceCount(), + cmd->isWireframe()); + _drawnVertices += cmd->getVertexDrawCount() * cmd->getInstanceCount(); + break; + default:; } _drawnBatches++; endRenderPass(); @@ -819,17 +832,23 @@ bool Renderer::checkVisibility(const Mat4& transform, const Vec2& size) return ret; } -void Renderer::readPixels(backend::RenderTarget* rt, - std::function callback) +void Renderer::readPixels(rhi::RenderTarget* rt, + std::function callback) { assert(!!rt); if (rt == _defaultRT) // read pixels from screen, metal renderer backend: screen texture must not be a framebufferOnly - backend::DriverBase::getInstance()->setFrameBufferOnly(false); + rhi::DriverBase::getInstance()->setFrameBufferOnly(false); _commandBuffer->readPixels(rt, std::move(callback)); } +void Renderer::resizeSwapChain(uint32_t width, uint32_t height) +{ + if (_commandBuffer) + _commandBuffer->resizeSwapChain(width, height); +} + void Renderer::beginRenderPass() { _commandBuffer->beginRenderPass(_currentRT, _renderPassDesc); @@ -838,10 +857,9 @@ void Renderer::beginRenderPass() auto depthStencil = _dsDesc; if (!_currentRT->isDefaultRenderTarget()) { - if (!_currentRT->_depth) - depthStencil.removeFlag(DepthStencilFlags::DEPTH_TEST | DepthStencilFlags::DEPTH_WRITE); - if (!_currentRT->_stencil) - depthStencil.removeFlag(DepthStencilFlags::STENCIL_TEST); + if (!_currentRT->_depthStencil) + depthStencil.removeFlag(DepthStencilFlags::DEPTH_TEST | DepthStencilFlags::DEPTH_WRITE | + DepthStencilFlags::STENCIL_TEST); } _commandBuffer->updateDepthStencilState(depthStencil); @@ -859,7 +877,7 @@ void Renderer::endRenderPass() _commandBuffer->endRenderPass(); } -void Renderer::clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder) +void Renderer::clear(ClearFlag flags, const Color& color, float depth, unsigned int stencil, float globalOrder) { _clearFlag = flags; @@ -867,7 +885,7 @@ void Renderer::clear(ClearFlag flags, const Color4F& color, float depth, unsigne command->init(globalOrder); command->func = [this, flags, color, depth, stencil]() -> void { - backend::RenderPassDescriptor descriptor; + rhi::RenderPassDesc descriptor; descriptor.flags.clear = flags; if (bitmask::any(flags, ClearFlag::COLOR)) @@ -904,7 +922,7 @@ CallbackCommand* Renderer::nextCallbackCommand() return cmd; } -const Color4F& Renderer::getClearColor() const +const Color& Renderer::getClearColor() const { return _clearColor; } @@ -979,31 +997,31 @@ void Renderer::TriangleCommandBufferManager::prepareNextBuffer() ++_currentBufferIndex; } -backend::Buffer* Renderer::TriangleCommandBufferManager::getVertexBuffer() const +rhi::Buffer* Renderer::TriangleCommandBufferManager::getVertexBuffer() const { return _vertexBufferPool[_currentBufferIndex]; } -backend::Buffer* Renderer::TriangleCommandBufferManager::getIndexBuffer() const +rhi::Buffer* Renderer::TriangleCommandBufferManager::getIndexBuffer() const { return _indexBufferPool[_currentBufferIndex]; } void Renderer::TriangleCommandBufferManager::createBuffer() { - auto driver = backend::DriverBase::getInstance(); + auto driver = rhi::DriverBase::getInstance(); // Not initializing the buffer before passing it to updateData for Android/OpenGL ES. // This change does fix the Android/OpenGL ES performance problem // If for some reason we get reports of performance issues on OpenGL implementations, // then we can just add pre-processor checks for OpenGL and have the updateData() allocate the full size after buffer creation. - auto vertexBuffer = driver->newBuffer(Renderer::VBO_SIZE * sizeof(_verts[0]), backend::BufferType::VERTEX, - backend::BufferUsage::DYNAMIC); + auto vertexBuffer = driver->createBuffer(Renderer::VBO_SIZE * sizeof(_verts[0]), rhi::BufferType::VERTEX, + rhi::BufferUsage::DYNAMIC); if (!vertexBuffer) return; - auto indexBuffer = driver->newBuffer(Renderer::INDEX_VBO_SIZE * sizeof(_indices[0]), backend::BufferType::INDEX, - backend::BufferUsage::DYNAMIC); + auto indexBuffer = driver->createBuffer(Renderer::INDEX_VBO_SIZE * sizeof(_indices[0]), rhi::BufferType::INDEX, + rhi::BufferUsage::DYNAMIC); if (!indexBuffer) { vertexBuffer->release(); diff --git a/core/renderer/Renderer.h b/axmol/renderer/Renderer.h similarity index 84% rename from core/renderer/Renderer.h rename to axmol/renderer/Renderer.h index 0ffdd2194290..d8b2ce7c4213 100644 --- a/core/renderer/Renderer.h +++ b/axmol/renderer/Renderer.h @@ -31,10 +31,9 @@ #include #include -#include "platform/PlatformMacros.h" -#include "renderer/RenderCommand.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/ProgramManager.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/renderer/ProgramManager.h" /** * @addtogroup renderer @@ -44,26 +43,26 @@ namespace ax { -using CullMode = backend::CullMode; -using Winding = backend::Winding; +using CullMode = rhi::CullMode; +using Winding = rhi::Winding; -namespace backend +namespace rhi { class Buffer; class CommandBuffer; class RenderPipeline; class RenderPass; -class TextureBackend; +class Texture; class RenderTarget; -struct PixelBufferDescriptor; -} // namespace backend +struct PixelBufferDesc; +} // namespace rhi class EventListenerCustom; class TrianglesCommand; class MeshCommand; class GroupCommand; class CallbackCommand; -struct PipelineDescriptor; +struct PipelineDesc; class Texture2D; /** Class that knows how to sort `RenderCommand` objects. @@ -194,13 +193,13 @@ class AX_DLL Renderer @stencilAttachment The value to replace stencil attachment. Depth attachment and stencil attachment can be the same value. */ - backend::RenderTarget* getRenderTarget() const { return _currentRT; } - void setRenderTarget(backend::RenderTarget* rt) { _currentRT = rt; }; + rhi::RenderTarget* getRenderTarget() const { return _currentRT; } + void setRenderTarget(rhi::RenderTarget* rt) { _currentRT = rt; }; - backend::RenderTarget* getDefaultRenderTarget() const { return _defaultRT; } + rhi::RenderTarget* getDefaultRenderTarget() const { return _defaultRT; } /* The offscreen render target for RenderTexture to share it */ - backend::RenderTarget* getOffscreenRenderTarget(); + rhi::RenderTarget* getOffscreenRenderTarget(); /** Set clear values for each attachment. @@ -209,13 +208,13 @@ class AX_DLL Renderer @depth The clear depth value. @stencil The clear stencil value. */ - void clear(ClearFlag flags, const Color4F& color, float depth, unsigned int stencil, float globalOrder); + void clear(ClearFlag flags, const Color& color, float depth, unsigned int stencil, float globalOrder); /** * Get color clear value. * @return Color clear value. */ - const Color4F& getClearColor() const; + const Color& getClearColor() const; /** * Get depth clear value. @@ -253,7 +252,7 @@ class AX_DLL Renderer * Set depth compare function. * @param func Specifies the value used for depth buffer comparisons. */ - void setDepthCompareFunction(backend::CompareFunction func); + void setDepthCompareFunc(rhi::CompareFunc func); /** * Get whether depth test state is enabled or disabled. @@ -271,7 +270,7 @@ class AX_DLL Renderer * Get depth compare function. * @return Depth compare function. */ - backend::CompareFunction getDepthCompareFunction() const; + rhi::CompareFunc getDepthCompareFunc() const; /** * Enable/disable stencil test. @@ -286,7 +285,7 @@ class AX_DLL Renderer * @readMask Specifies a mask that is ANDed with both the reference value and the stored stencil value when the test * is done. */ - void setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask); + void setStencilCompareFunc(rhi::CompareFunc func, unsigned int ref, unsigned int readMask); /** * Set front and back stencil test actions. @@ -295,9 +294,9 @@ class AX_DLL Renderer * @param stencilDepthPassOp Specifies the stencil action when both the stencil test and the depth test pass, or * when the stencil test passes and either there is no depth buffer or depth testing is not enabled. */ - void setStencilOperation(backend::StencilOperation stencilFailureOp, - backend::StencilOperation depthFailureOp, - backend::StencilOperation stencilDepthPassOp); + void setStencilOp(rhi::StencilOp stencilFailureOp, + rhi::StencilOp depthFailureOp, + rhi::StencilOp stencilDepthPassOp); /** * Control the front and back writing of individual bits in the stencil planes. @@ -312,22 +311,22 @@ class AX_DLL Renderer bool getStencilTest() const; /// Get the action to take when the stencil test fails. - backend::StencilOperation getStencilFailureOperation() const; + rhi::StencilOp getStencilFailureOp() const; /// Get the stencil action when the stencil test passes, but the depth test fails. - backend::StencilOperation getStencilPassDepthFailureOperation() const; + rhi::StencilOp getStencilPassDepthFailureOp() const; /// Get the stencil action when both the stencil test and the depth test pass, or when the stencil test passes and /// either there is no depth buffer or depth testing is not enabled. - backend::StencilOperation getStencilDepthPassOperation() const; + rhi::StencilOp getStencilDepthPassOp() const; /// Get the stencil test function. - backend::CompareFunction getStencilCompareFunction() const; + rhi::CompareFunc getStencilCompareFunc() const; /** * Get the stencil readMask. * @return Stencil read mask. - * @see `setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask)` + * @see `setStencilCompareFunc(rhi::CompareFunc func, unsigned int ref, unsigned int readMask)` */ unsigned int getStencilReadMask() const; @@ -339,21 +338,21 @@ class AX_DLL Renderer unsigned int getStencilWriteMask() const; /** - * Get stencil reference value set by `setStencilCompareFunction`. + * Get stencil reference value set by `setStencilCompareFunc`. * @return Stencil reference value. - * @see `setStencilCompareFunction(backend::CompareFunction func, unsigned int ref, unsigned int readMask)` + * @see `setStencilCompareFunc(rhi::CompareFunc func, unsigned int ref, unsigned int readMask)` */ unsigned int getStencilReferenceValue() const; /** * Sets depth stencil descriptor */ - void setDepthStencilDesc(const backend::DepthStencilDescriptor& dsDesc); + void setDepthStencilDesc(const rhi::DepthStencilDesc& dsDesc); /** * Gets depth stencil descriptor */ - const backend::DepthStencilDescriptor& getDepthStencilDesc() const; + const rhi::DepthStencilDesc& getDepthStencilDesc() const; /** * Fixed-function state @@ -407,19 +406,21 @@ class AX_DLL Renderer bool getScissorTest() const; ///< Get whether scissor test is enabled or not. const ScissorRect& getScissorRect() const; ///< Get scissor rectangle. - backend::CommandBuffer* getCommandBuffer() const { return _commandBuffer ; } + rhi::CommandBuffer* getCommandBuffer() const { return _commandBuffer ; } /** returns whether or not a rectangle is visible or not */ bool checkVisibility(const Mat4& transform, const Vec2& size); /** read pixels from RenderTarget or screen framebuffer */ - void readPixels(backend::RenderTarget* rt, std::function callback); + void readPixels(rhi::RenderTarget* rt, std::function callback); void beginRenderPass(); /// Begin a render pass. void endRenderPass(); CallbackCommand* nextCallbackCommand(); + void resizeSwapChain(uint32_t width, uint32_t height); + protected: friend class Director; friend class GroupCommand; @@ -452,15 +453,15 @@ class AX_DLL Renderer */ void prepareNextBuffer(); - backend::Buffer* getVertexBuffer() const; ///< Get the vertex buffer. - backend::Buffer* getIndexBuffer() const; ///< Get the index buffer. + rhi::Buffer* getVertexBuffer() const; ///< Get the vertex buffer. + rhi::Buffer* getIndexBuffer() const; ///< Get the index buffer. private: void createBuffer(); int _currentBufferIndex = 0; - std::vector _vertexBufferPool; - std::vector _indexBufferPool; + std::vector _vertexBufferPool; + std::vector _indexBufferPool; }; inline GroupCommandManager* getGroupCommandManager() const { return _groupCommandManager; } @@ -491,7 +492,7 @@ class AX_DLL Renderer void popStateBlock(); - backend::RenderPipeline* _renderPipeline = nullptr; + rhi::RenderPipeline* _renderPipeline = nullptr; Viewport _viewport; CullMode _cullMode = CullMode::NONE; @@ -509,17 +510,17 @@ class AX_DLL Renderer std::vector _groupCommandPool; // for TrianglesCommand - V3F_C4B_T2F _verts[VBO_SIZE]; + V3F_T2F_C4B _verts[VBO_SIZE]; unsigned short _indices[INDEX_VBO_SIZE]; - backend::Buffer* _vertexBuffer = nullptr; - backend::Buffer* _indexBuffer = nullptr; + rhi::Buffer* _vertexBuffer = nullptr; + rhi::Buffer* _indexBuffer = nullptr; TriangleCommandBufferManager _triangleCommandBufferManager; - backend::CommandBuffer* _commandBuffer = nullptr; - backend::RenderPassDescriptor _renderPassDesc; + rhi::CommandBuffer* _commandBuffer = nullptr; + rhi::RenderPassDesc _renderPassDesc; - backend::DepthStencilState* _depthStencilState = nullptr; - backend::DepthStencilDescriptor _dsDesc; + rhi::DepthStencilState* _depthStencilState = nullptr; + rhi::DepthStencilDesc _dsDesc; // Internal structure that has the information for the batches struct TriBatchToDraw @@ -551,12 +552,12 @@ class AX_DLL Renderer unsigned int _stencilRef = 0; - backend::RenderTarget* _defaultRT = nullptr; - backend::RenderTarget* _currentRT = nullptr; // weak ref + rhi::RenderTarget* _defaultRT = nullptr; + rhi::RenderTarget* _currentRT = nullptr; // weak ref - backend::RenderTarget* _offscreenRT = nullptr; + rhi::RenderTarget* _offscreenRT = nullptr; - Color4F _clearColor = Color4F::BLACK; + Color _clearColor = Color::BLACK; ClearFlag _clearFlag; struct ScissorState @@ -570,7 +571,7 @@ class AX_DLL Renderer { bool depthTest = false; bool depthWrite = false; - backend::CullMode cullMode = backend::CullMode::NONE; + rhi::CullMode cullMode = rhi::CullMode::NONE; }; std::deque _stateBlockStack; diff --git a/core/renderer/Shaders.cpp b/axmol/renderer/Shaders.cpp similarity index 92% rename from core/renderer/Shaders.cpp rename to axmol/renderer/Shaders.cpp index ed097d29d920..6a27b82dc8ca 100644 --- a/core/renderer/Shaders.cpp +++ b/axmol/renderer/Shaders.cpp @@ -25,7 +25,7 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/Shaders.h" +#include "axmol/renderer/Shaders.h" namespace ax { @@ -39,6 +39,8 @@ AX_DLL const std::string_view positionTexture_frag = "positionTe AX_DLL const std::string_view positionTextureColor_vert = "positionTextureColor_vs"sv; AX_DLL const std::string_view positionTextureColor_frag = "positionTextureColor_fs"sv; AX_DLL const std::string_view positionTextureColorAlphaTest_frag = "positionTextureColorAlphaTest_fs"sv; +AX_DLL const std::string_view positionTextureGray_frag = "positionTextureGray_fs"sv; +AX_DLL const std::string_view positionTextureGrayAlpha_frag = "positionTextureGrayAlpha_fs"sv; AX_DLL const std::string_view label_normal_frag = "label_normal_fs"sv; AX_DLL const std::string_view label_outline_frag = "label_outline_fs"sv; AX_DLL const std::string_view label_distanceNormal_frag = "label_distanceNormal_fs"sv; @@ -64,6 +66,7 @@ AX_DLL const std::string_view dualSampler_hsv_frag = "dualSample AX_DLL const std::string_view videoTextureYUY2_frag = "videoTextureYUY2_fs"sv; AX_DLL const std::string_view videoTextureNV12_frag = "videoTextureNV12_fs"sv; AX_DLL const std::string_view videoTextureI420_frag = "videoTextureI420_fs"sv; +AX_DLL const std::string_view trail_2d_vert = "trail_2d_vs"sv; AX_DLL const std::string_view lineColor_frag = "lineColor_fs"sv; AX_DLL const std::string_view lineColor_vert = "lineColor_vs"sv; AX_DLL const std::string_view color_frag = "color_fs"sv; @@ -75,8 +78,8 @@ AX_DLL const std::string_view particleColor_frag = "particleCo AX_DLL const std::string_view particle_vert = "particle_vs"sv; AX_DLL const std::string_view positionNormalTexture_vert = "positionNormalTexture_vs"sv; AX_DLL const std::string_view skinPositionNormalTexture_vert = "skinPositionNormalTexture_vs"sv; -AX_DLL const std::string_view positionTexture3D_vert = "positionTexture3D_vs"sv; -AX_DLL const std::string_view positionTextureInstance_vert = "positionTextureInstance_vs"sv; +AX_DLL const std::string_view unlit_vert = "unlit_vs"sv; +AX_DLL const std::string_view unlit_instance_vert = "unlit_instance_vs"sv; AX_DLL const std::string_view skinPositionTexture_vert = "skinPositionTexture_vs"sv; AX_DLL const std::string_view skybox_frag = "skybox_fs"sv; AX_DLL const std::string_view skybox_vert = "skybox_vs"sv; diff --git a/core/renderer/Shaders.h b/axmol/renderer/Shaders.h similarity index 93% rename from core/renderer/Shaders.h rename to axmol/renderer/Shaders.h index cb99f492a636..a18904634676 100644 --- a/core/renderer/Shaders.h +++ b/axmol/renderer/Shaders.h @@ -28,7 +28,7 @@ THE SOFTWARE. /// @cond DO_NOT_SHOW -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include @@ -47,6 +47,8 @@ extern AX_DLL const std::string_view positionTexture_frag; extern AX_DLL const std::string_view positionTextureColor_vert; extern AX_DLL const std::string_view positionTextureColor_frag; extern AX_DLL const std::string_view positionTextureColorAlphaTest_frag; +extern AX_DLL const std::string_view positionTextureGray_frag; +extern AX_DLL const std::string_view positionTextureGrayAlpha_frag; extern AX_DLL const std::string_view label_normal_frag; extern AX_DLL const std::string_view label_outline_frag; extern AX_DLL const std::string_view label_distanceNormal_frag; @@ -76,6 +78,8 @@ extern AX_DLL const std::string_view videoTextureYUY2_frag; extern AX_DLL const std::string_view videoTextureNV12_frag; extern AX_DLL const std::string_view videoTextureI420_frag; +extern AX_DLL const std::string_view trail_2d_vert; + /* below is 3d shaders */ extern AX_DLL const std::string_view lineColor_frag; extern AX_DLL const std::string_view lineColor_vert; @@ -89,8 +93,8 @@ extern AX_DLL const std::string_view particleColor_frag; extern AX_DLL const std::string_view particle_vert; extern AX_DLL const std::string_view positionNormalTexture_vert; extern AX_DLL const std::string_view skinPositionNormalTexture_vert; -extern AX_DLL const std::string_view positionTexture3D_vert; -extern AX_DLL const std::string_view positionTextureInstance_vert; +extern AX_DLL const std::string_view unlit_vert; +extern AX_DLL const std::string_view unlit_instance_vert; extern AX_DLL const std::string_view skinPositionTexture_vert; extern AX_DLL const std::string_view skybox_frag; extern AX_DLL const std::string_view skybox_vert; diff --git a/core/renderer/Technique.cpp b/axmol/renderer/Technique.cpp similarity index 93% rename from core/renderer/Technique.cpp rename to axmol/renderer/Technique.cpp index ff0b3c94c142..f6c97962c000 100644 --- a/core/renderer/Technique.cpp +++ b/axmol/renderer/Technique.cpp @@ -28,14 +28,14 @@ - Qt3D: http://qt-project.org/ ****************************************************************************/ -#include "renderer/Technique.h" -#include "renderer/Material.h" -#include "renderer/Pass.h" +#include "axmol/renderer/Technique.h" +#include "axmol/renderer/Material.h" +#include "axmol/renderer/Pass.h" namespace ax { -Technique* Technique::createWithProgramState(Material* parent, backend::ProgramState* state) +Technique* Technique::createWithProgramState(Material* parent, rhi::ProgramState* state) { auto technique = new Technique(); if (technique->init(parent)) diff --git a/core/renderer/Technique.h b/axmol/renderer/Technique.h similarity index 92% rename from core/renderer/Technique.h rename to axmol/renderer/Technique.h index 35a5a1b92c1f..90300de822cc 100644 --- a/core/renderer/Technique.h +++ b/axmol/renderer/Technique.h @@ -30,10 +30,10 @@ #pragma once #include -#include "renderer/RenderState.h" -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "base/Vector.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/base/Object.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Vector.h" namespace ax { @@ -41,7 +41,7 @@ namespace ax class Pass; class Material; -namespace backend +namespace rhi { class ProgramState; } @@ -60,7 +60,7 @@ class AX_DLL Technique : public Object /** Creates a new Technique with a GLProgramState. Method added to support legacy code */ - static Technique* createWithProgramState(Material* parent, backend::ProgramState* state); + static Technique* createWithProgramState(Material* parent, rhi::ProgramState* state); static Technique* create(Material* parent); /** Adds a new pass to the Technique. diff --git a/core/renderer/Texture2D.cpp b/axmol/renderer/Texture2D.cpp similarity index 73% rename from core/renderer/Texture2D.cpp rename to axmol/renderer/Texture2D.cpp index 99c46e9f21ba..1d9132eb0241 100644 --- a/core/renderer/Texture2D.cpp +++ b/axmol/renderer/Texture2D.cpp @@ -31,39 +31,45 @@ THE SOFTWARE. * https://devforums.apple.com/message/37855#37855 by a1studmuffin */ -#include "renderer/Texture2D.h" -#include "platform/Image.h" -#include "platform/GL.h" -#include "base/Utils.h" -#include "platform/Device.h" -#include "base/Config.h" -#include "base/Macros.h" -#include "base/UTF8.h" -#include "base/Configuration.h" -#include "platform/PlatformMacros.h" -#include "base/Director.h" -#include "base/NinePatchImageParser.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/Shaders.h" -#include "renderer/backend/PixelFormatUtils.h" -#include "renderer/Renderer.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/platform/Image.h" +#include "axmol/platform/GL.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/Device.h" +#include "axmol/base/Config.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Configuration.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Director.h" +#include "axmol/base/NinePatchImageParser.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/PixelFormatUtils.h" +#include "axmol/renderer/Renderer.h" #if AX_ENABLE_CACHE_TEXTURE_DATA -# include "renderer/TextureCache.h" +# include "axmol/renderer/TextureCache.h" #endif namespace ax { -// CLASS IMPLEMENTATIONS: - -// If the image has alpha, you can create RGBA8 (32-bit) or RGBA4 (16-bit) or RGB5A1 (16-bit) -// Default is: RGBA8888 (32-bit textures) -static backend::PixelFormat g_defaultAlphaPixelFormat = backend::PixelFormat::RGBA8; +rhi::SamplerDesc Texture2D::chooseSamplerDesc(bool antialiasEnabled, bool mipEnabled) +{ + return antialiasEnabled ? rhi::SamplerDesc{.minFilter = rhi::SamplerFilter::MIN_LINEAR, + .magFilter = rhi::SamplerFilter::MAG_LINEAR, + .mipFilter = mipEnabled ? rhi::SamplerFilter::MIP_LINEAR + : rhi::SamplerFilter::MIP_NONE} + : rhi::SamplerDesc{.minFilter = rhi::SamplerFilter::MIN_NEAREST, + .magFilter = rhi::SamplerFilter::MAG_NEAREST, + .mipFilter = mipEnabled ? rhi::SamplerFilter::MIP_NEAREST + : rhi::SamplerFilter::MIP_NONE}; +} Texture2D::Texture2D() - : _pixelFormat(backend::PixelFormat::NONE) + : _pixelFormat(rhi::PixelFormat::NONE) , _pixelsWide(0) , _pixelsHigh(0) , _maxS(0.0) @@ -73,9 +79,10 @@ Texture2D::Texture2D() , _ninePatchInfo(nullptr) , _valid(true) { - backend::TextureDescriptor textureDescriptor; - textureDescriptor.textureFormat = PixelFormat::NONE; - _texture = static_cast(backend::DriverBase::getInstance()->newTexture(textureDescriptor)); + rhi::TextureDesc textureDesc; + textureDesc.textureFormat = PixelFormat::NONE; + _texture = + static_cast(rhi::DriverBase::getInstance()->createTexture(textureDesc)); } Texture2D::~Texture2D() @@ -90,7 +97,7 @@ Texture2D::~Texture2D() AX_SAFE_RELEASE(_programState); } -backend::PixelFormat Texture2D::getPixelFormat() const +rhi::PixelFormat Texture2D::getPixelFormat() const { return _pixelFormat; } @@ -105,7 +112,7 @@ int Texture2D::getPixelsHigh() const return _pixelsHigh; } -backend::TextureBackend* Texture2D::getBackendTexture() const +rhi::Texture* Texture2D::getBackendTexture() const { return _texture; } @@ -159,8 +166,8 @@ void Texture2D::setPremultipliedAlpha(bool premultipliedAlpha) bool Texture2D::initWithData(const void* data, ssize_t dataLen, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha) @@ -176,8 +183,8 @@ bool Texture2D::initWithData(const void* data, bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha) @@ -188,7 +195,12 @@ bool Texture2D::initWithMipmaps(MipmapInfo* mipmaps, return true; } -bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int index) +bool Texture2D::updateWithImage(Image* image, int index) +{ + return updateWithImage(image, image->getPixelFormat(), index); +} + +bool Texture2D::updateWithImage(Image* image, rhi::PixelFormat format, int index) { if (image == nullptr) { @@ -214,11 +226,11 @@ bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int i unsigned char* tempData = image->getData(); // Vec2 imageSize = Vec2((float)imageWidth, (float)imageHeight); - backend::PixelFormat renderFormat = (PixelFormat::NONE == format) ? image->getPixelFormat() : format; - backend::PixelFormat imagePixelFormat = image->getPixelFormat(); + rhi::PixelFormat renderFormat = (PixelFormat::NONE == format) ? image->getPixelFormat() : format; + rhi::PixelFormat imagePixelFormat = image->getPixelFormat(); size_t tempDataLen = image->getDataLen(); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL //! override renderFormat, since some render format is not supported by metal switch (renderFormat) { @@ -237,34 +249,35 @@ bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int i default: break; } -#elif !AX_GLES_PROFILE - // Non-GLES doesn't support follow render formats, needs convert PixelFormat::RGBA8 - // Note: axmol-1.1 deprecated A8, L8, LA8 as renderFormat, preferred R8, RG8 +#elif AX_RENDER_API == AX_RENDER_API_D3D + //! override renderFormat, since some render format is not supported by d3d switch (renderFormat) { - case PixelFormat::R8: - case PixelFormat::RG8: + case PixelFormat::RGB8: // Note: conversion to RGBA8 will happends renderFormat = PixelFormat::RGBA8; + break; + default: + break; } #endif if (image->getNumberOfMipmaps() > 1) { - if (renderFormat != image->getPixelFormat()) + if (renderFormat != imagePixelFormat) { AXLOGW("WARNING: This image has more than 1 mipmaps and we will not convert the data format"); } // pixel format of data is not converted, renderFormat can be different from pixelFormat // it will be done later - updateWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), image->getPixelFormat(), renderFormat, imageHeight, imageWidth, image->hasPremultipliedAlpha(), index); + updateWithMipmaps(image->getMipmaps(), image->getNumberOfMipmaps(), imagePixelFormat, renderFormat, imageHeight, imageWidth, image->hasPremultipliedAlpha(), index); } else if (image->isCompressed()) { // !Only hardware support texture will be compression PixelFormat, otherwise, will convert to RGBA8 duraing image // load renderFormat = imagePixelFormat; - updateWithData(tempData, tempDataLen, image->getPixelFormat(), image->getPixelFormat(), imageWidth, imageHeight, image->hasPremultipliedAlpha(), index); + updateWithData(tempData, tempDataLen, imagePixelFormat, image->getPixelFormat(), imageWidth, imageHeight, image->hasPremultipliedAlpha(), index); } else { @@ -278,8 +291,8 @@ bool Texture2D::updateWithImage(Image* image, backend::PixelFormat format, int i bool Texture2D::updateWithData(const void* data, ssize_t dataLen, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha, @@ -296,8 +309,8 @@ bool Texture2D::updateWithData(const void* data, bool Texture2D::updateWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha, @@ -313,17 +326,17 @@ bool Texture2D::updateWithMipmaps(MipmapInfo* mipmaps, return false; } - auto& pfd = backend::PixelFormatUtils::getFormatDescriptor(pixelFormat); + auto& pfd = rhi::PixelFormatUtils::getFormatDesc(pixelFormat); if (!pfd.bpp) { AXLOGW("WARNING: unsupported pixelformat: {:x}", (uint32_t)pixelFormat); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL AXASSERT(false, "pixeformat not found in _pixelFormatInfoTables, register required!"); #endif return false; } - bool compressed = backend::PixelFormatUtils::isCompressed(pixelFormat); + bool compressed = rhi::PixelFormatUtils::isCompressed(pixelFormat); if (compressed && !Configuration::getInstance()->supportsPVRTC() && !Configuration::getInstance()->supportsETC1() && !Configuration::getInstance()->supportsETC2() && !Configuration::getInstance()->supportsS3TC() && @@ -337,28 +350,15 @@ bool Texture2D::updateWithMipmaps(MipmapInfo* mipmaps, VolatileTextureMgr::getOrAddVolatileTexture(this); #endif - backend::TextureDescriptor textureDescriptor; - textureDescriptor.width = pixelsWide; - textureDescriptor.height = pixelsHigh; + rhi::TextureDesc textureDesc; + textureDesc.width = pixelsWide; + textureDesc.height = pixelsHigh; - textureDescriptor.samplerDescriptor.magFilter = - (_flags & TextureFlag::ANTIALIAS_ENABLED) ? backend::SamplerFilter::LINEAR : backend::SamplerFilter::NEAREST; - if (mipmapsNum == 1) - { - textureDescriptor.samplerDescriptor.minFilter = (_flags & TextureFlag::ANTIALIAS_ENABLED) - ? backend::SamplerFilter::LINEAR - : backend::SamplerFilter::NEAREST; - } - else - { - textureDescriptor.samplerDescriptor.minFilter = (_flags & TextureFlag::ANTIALIAS_ENABLED) - ? backend::SamplerFilter::LINEAR_MIPMAP_NEAREST - : backend::SamplerFilter::NEAREST_MIPMAP_NEAREST; - } + textureDesc.samplerDesc = chooseSamplerDesc(_flags & TextureFlag::ANTIALIAS_ENABLED, mipmapsNum > 1); int width = pixelsWide; int height = pixelsHigh; - backend::PixelFormat oriPixelFormat = pixelFormat; + rhi::PixelFormat oriPixelFormat = pixelFormat; for (int i = 0; i < mipmapsNum; ++i) { unsigned char* data = mipmaps[i].address; @@ -368,20 +368,20 @@ bool Texture2D::updateWithMipmaps(MipmapInfo* mipmaps, if (renderFormat != oriPixelFormat && !compressed) // need conversion { - auto convertedFormat = backend::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, + auto convertedFormat = rhi::PixelFormatUtils::convertDataToFormat(data, dataLen, oriPixelFormat, renderFormat, &outData, &outDataLen); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL AXASSERT(convertedFormat == renderFormat, "PixelFormat convert failed!"); #endif if (convertedFormat == renderFormat) pixelFormat = renderFormat; } - textureDescriptor.textureFormat = pixelFormat; - AXASSERT(textureDescriptor.textureFormat != backend::PixelFormat::NONE, "PixelFormat should not be NONE"); + textureDesc.textureFormat = pixelFormat; + AXASSERT(textureDesc.textureFormat != rhi::PixelFormat::NONE, "PixelFormat should not be NONE"); - if (_texture->getTextureFormat() != textureDescriptor.textureFormat) - _texture->updateTextureDescriptor(textureDescriptor, index); + if (_texture->getTextureFormat() != textureDesc.textureFormat) + _texture->updateTextureDesc(textureDesc, index); if (compressed) { @@ -448,10 +448,16 @@ bool Texture2D::updateWithSubData(void* data, int offsetX, int offsetY, int widt // implementation Texture2D (Image) bool Texture2D::initWithImage(Image* image) { - return initWithImage(image, g_defaultAlphaPixelFormat); + if (image == nullptr) + { + AXLOGW("Texture2D. Can't create Texture. UIImage is nil"); + return false; + } + + return initWithImage(image, image->getPixelFormat()); } -bool Texture2D::initWithImage(Image* image, backend::PixelFormat format) +bool Texture2D::initWithImage(Image* image, rhi::PixelFormat format) { if (image == nullptr) { @@ -484,7 +490,7 @@ bool Texture2D::initWithString(std::string_view text, tempDef._dimensions = dimensions; tempDef._alignment = hAlignment; tempDef._vertAlignment = vAlignment; - tempDef._fontFillColor = Color3B::WHITE; + tempDef._fontFillColor = Color32::WHITE; tempDef._enableWrap = enableWrap; tempDef._overflow = overflow; @@ -532,10 +538,6 @@ bool Texture2D::initWithString(std::string_view text, const FontDefinition& text AXASSERT(textDefinition._stroke._strokeEnabled == false, "Currently stroke only supported on iOS and Android!"); #endif - PixelFormat pixelFormat = g_defaultAlphaPixelFormat; - unsigned char* outTempData = nullptr; - size_t outTempDataLen = 0; - int imageWidth; int imageHeight; auto textDef = textDefinition; @@ -551,7 +553,7 @@ bool Texture2D::initWithString(std::string_view text, const FontDefinition& text if (outData.isNull()) return false; - const auto maxTextureSize = backend::DriverBase::getInstance()->getMaxTextureSize(); + const auto maxTextureSize = rhi::DriverBase::getInstance()->getMaxTextureSize(); if (imageWidth > maxTextureSize || imageHeight > maxTextureSize) { AXLOGW("Texture2D::initWithString fail, the texture size:{}x{} too large, max texture size:{}", imageWidth, @@ -560,26 +562,20 @@ bool Texture2D::initWithString(std::string_view text, const FontDefinition& text } Vec2 imageSize = Vec2((float)imageWidth, (float)imageHeight); - pixelFormat = - backend::PixelFormatUtils::convertDataToFormat(outData.getBytes(), imageWidth * imageHeight * 4, - PixelFormat::RGBA8, pixelFormat, &outTempData, &outTempDataLen); + const PixelFormat pixelFormat = PixelFormat::RGBA8; - ret = initWithData(outTempData, outTempDataLen, pixelFormat, imageWidth, imageHeight); + ret = initWithData(outData.getBytes(), imageWidth * imageHeight * 4, pixelFormat, imageWidth, imageHeight); - if (outTempData != nullptr && outTempData != outData.getBytes()) - { - free(outTempData); - } setPremultipliedAlpha(hasPremultipliedAlpha); return ret; } -bool Texture2D::updateTextureDescriptor(const backend::TextureDescriptor& descriptor, bool preMultipliedAlpha) +bool Texture2D::updateTextureDesc(const rhi::TextureDesc& descriptor, bool preMultipliedAlpha) { AX_ASSERT(_texture); - _texture->updateTextureDescriptor(descriptor); + _texture->updateTextureDesc(descriptor); _pixelsWide = _contentSize.width = _texture->getWidth(); _pixelsHigh = _contentSize.height = _texture->getHeight(); setPremultipliedAlpha(preMultipliedAlpha); @@ -615,13 +611,8 @@ void Texture2D::setAliasTexParameters() _flags &= ~TextureFlag::ANTIALIAS_ENABLED; - backend::SamplerDescriptor descriptor(backend::SamplerFilter::NEAREST, // magFilter - (_texture->hasMipmaps()) ? backend::SamplerFilter::NEAREST_MIPMAP_NEAREST - : backend::SamplerFilter::NEAREST, // minFilter - backend::SamplerAddressMode::DONT_CARE, // sAddressMode - backend::SamplerAddressMode::DONT_CARE // tAddressMode - ); - _texture->updateSamplerDescriptor(descriptor); + const auto desc = chooseSamplerDesc(false, _texture->hasMipmaps()); + _texture->updateSamplerDesc(desc); } void Texture2D::setAntiAliasTexParameters() @@ -633,38 +624,18 @@ void Texture2D::setAntiAliasTexParameters() } _flags |= TextureFlag::ANTIALIAS_ENABLED; - backend::SamplerDescriptor descriptor(backend::SamplerFilter::LINEAR, // magFilter - (_texture->hasMipmaps()) ? backend::SamplerFilter::LINEAR_MIPMAP_NEAREST - : backend::SamplerFilter::LINEAR, // minFilter - backend::SamplerAddressMode::DONT_CARE, // sAddressMode - backend::SamplerAddressMode::DONT_CARE // tAddressMode - ); - _texture->updateSamplerDescriptor(descriptor); + const auto desc = chooseSamplerDesc(true, _texture->hasMipmaps()); + _texture->updateSamplerDesc(desc); } const char* Texture2D::getStringForFormat() const { - return backend::PixelFormatUtils::getFormatDescriptor(_pixelFormat).name; -} - -// -// Texture options for images that contains alpha -// -// implementation Texture2D (PixelFormat) - -void Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat format) -{ - g_defaultAlphaPixelFormat = format; -} - -backend::PixelFormat Texture2D::getDefaultAlphaPixelFormat() -{ - return g_defaultAlphaPixelFormat; + return rhi::PixelFormatUtils::getFormatDesc(_pixelFormat).name; } -unsigned int Texture2D::getBitsPerPixelForFormat(backend::PixelFormat format) const +unsigned int Texture2D::getBitsPerPixelForFormat(rhi::PixelFormat format) const { - return backend::PixelFormatUtils::getFormatDescriptor(format).bpp; + return rhi::PixelFormatUtils::getFormatDesc(format).bpp; } unsigned int Texture2D::getBitsPerPixelForFormat() const @@ -729,7 +700,7 @@ void Texture2D::removeSpriteFrameCapInset(SpriteFrame* spriteFrame) void Texture2D::setTexParameters(const Texture2D::TexParams& desc) { - _texture->updateSamplerDescriptor(desc); + _texture->updateSamplerDesc(desc); } void Texture2D::generateMipmap() @@ -745,14 +716,14 @@ void Texture2D::initProgram() if (_programState != nullptr) return; - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + auto& pipelineDesc = _customCommand.getPipelineDesc(); // create program state - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE); - _programState = new ax::backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE); + _programState = new ax::rhi::ProgramState(program); _mvpMatrixLocation = _programState->getUniformLocation("u_MVPMatrix"); _textureLocation = _programState->getUniformLocation("u_tex0"); - pipelineDescriptor.programState = _programState; + pipelineDesc.programState = _programState; // create vertex buffer _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); @@ -770,10 +741,10 @@ void Texture2D::initProgram() blendFunc = BlendFunc::ALPHA_NON_PREMULTIPLIED; } - auto& blendDescriptor = pipelineDescriptor.blendDescriptor; - blendDescriptor.blendEnabled = true; - blendDescriptor.sourceRGBBlendFactor = blendDescriptor.sourceAlphaBlendFactor = blendFunc.src; - blendDescriptor.destinationRGBBlendFactor = blendDescriptor.destinationAlphaBlendFactor = blendFunc.dst; + auto& blendDesc = pipelineDesc.blendDesc; + blendDesc.blendEnabled = true; + blendDesc.sourceRGBBlendFactor = blendDesc.sourceAlphaBlendFactor = blendFunc.src; + blendDesc.destinationRGBBlendFactor = blendDesc.destinationAlphaBlendFactor = blendFunc.dst; _programState->setTexture(_textureLocation, 0, _texture); } diff --git a/core/renderer/Texture2D.h b/axmol/renderer/Texture2D.h similarity index 79% rename from core/renderer/Texture2D.h rename to axmol/renderer/Texture2D.h index f651334c5947..48aa3c95dd30 100644 --- a/core/renderer/Texture2D.h +++ b/axmol/renderer/Texture2D.h @@ -3,6 +3,7 @@ Copyright (c) 2008 Apple Inc. All Rights Reserved. Copyright (c) 2010-2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -31,10 +32,10 @@ THE SOFTWARE. #include #include -#include "base/Object.h" -#include "math/Math.h" -#include "base/Types.h" -#include "renderer/CustomCommand.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/base/Types.h" +#include "axmol/renderer/CustomCommand.h" namespace ax { @@ -49,12 +50,12 @@ namespace ui class Scale9Sprite; } -namespace backend +namespace rhi { -class Texture2DBackend; -class TextureBackend; +class Texture; +class Texture; class ProgramState; -} // namespace backend +} // namespace rhi /** * @addtogroup _2d @@ -89,39 +90,12 @@ class AX_DLL Texture2D : public Object /** * Extension to set the Min / Mag filter */ - using TexParams = backend::SamplerDescriptor; + using TexParams = rhi::SamplerDesc; public: - /** sets the default pixel format for UIImagescontains alpha channel. - - @param format - If the UIImage contains alpha channel, then the options are: - - generate 32-bit textures: backend::PixelFormat::RGBA8 (default one) - - generate 24-bit textures: backend::PixelFormat::RGB8 - - generate 16-bit textures: backend::PixelFormat::RGBA4 - - generate 16-bit textures: backend::PixelFormat::RGB5A1 - - generate 16-bit textures: backend::PixelFormat::RGB565 - - generate 8-bit textures: backend::PixelFormat::R8 (only use it if you use just 1 color) - - generate 16-bit textures: backend::PixelFormat::RG8 (only use it if you use just 2 color) - - How does it work ? - - If the image is an RGBA (with Alpha) then the default pixel format will be used (it can be a 8-bit, 16-bit or - 32-bit texture) - - If the image is an RGB (without Alpha) then: If the default pixel format is RGBA8888 then a RGBA8888 (32-bit) - will be used. Otherwise a RGB565 (16-bit texture) will be used. - - This parameter is not valid for PVR / PVR.CCZ images. - @since v0.8 - */ - static void setDefaultAlphaPixelFormat(backend::PixelFormat format); - - /** Returns the alpha pixel format. - @since v0.8 - */ - static backend::PixelFormat getDefaultAlphaPixelFormat(); + static rhi::SamplerDesc chooseSamplerDesc(bool antialiasEnabled, bool mipEnabled); -public: /** */ Texture2D(); @@ -143,7 +117,7 @@ class AX_DLL Texture2D : public Object */ bool initWithData(const void* data, ssize_t dataLen, - backend::PixelFormat pixelFormat, + rhi::PixelFormat pixelFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false) @@ -166,8 +140,8 @@ class AX_DLL Texture2D : public Object */ bool initWithData(const void* data, ssize_t dataLen, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false); @@ -183,8 +157,8 @@ class AX_DLL Texture2D : public Object */ bool initWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false); @@ -197,19 +171,20 @@ class AX_DLL Texture2D : public Object @param width Specifies the width of the texture subimage. @param height Specifies the height of the texture subimage. */ - bool updateWithImage(Image* image, backend::PixelFormat format, int index = 0); + bool updateWithImage(Image* image, int index = 0); + bool updateWithImage(Image* image, rhi::PixelFormat format, int index = 0); bool updateWithData(const void* data, ssize_t dataLen, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha, int index = 0); bool updateWithMipmaps(MipmapInfo* mipmaps, int mipmapsNum, - backend::PixelFormat pixelFormat, - backend::PixelFormat renderFormat, + rhi::PixelFormat pixelFormat, + rhi::PixelFormat renderFormat, int pixelsWide, int pixelsHigh, bool preMultipliedAlpha = false, @@ -240,21 +215,19 @@ class AX_DLL Texture2D : public Object /** Initializes a texture from a UIImage object. - We will use the format you specified with setDefaultAlphaPixelFormat to convert the image for texture. + We will use the pixel format of the image. NOTE: It will not convert the pvr image file. @param image An UIImage object. */ bool initWithImage(Image* image); /** - Initializes a texture from a UIImage object. + Initializes a texture from an Image object and convert it to the given + format if necessary. - We will use the format you passed to the function to convert the image format to the texture format. - If you pass PixelFormat::NONE, we will auto detect the image render type and use that type for texture to render. - @param image An UIImage object. - @param format Texture pixel formats. - **/ - bool initWithImage(Image* image, backend::PixelFormat format); + NOTE: It will not convert the pvr image file. + */ + bool initWithImage(Image* image, PixelFormat format); /** Initializes a texture from a string with dimensions, alignment, font name and font size. @@ -284,7 +257,7 @@ class AX_DLL Texture2D : public Object bool initWithString(std::string_view text, const FontDefinition& textDefinition); //!!Used for render buffer, such depth stencil attachment - bool updateTextureDescriptor(const backend::TextureDescriptor& descriptor, bool preMultipliedAlpha = false); + bool updateTextureDesc(const rhi::TextureDesc& descriptor, bool preMultipliedAlpha = false); void setRenderTarget(bool renderTarget); inline bool isRenderTarget() const { return _flags & TextureFlag::RENDERTARGET; } @@ -330,7 +303,7 @@ class AX_DLL Texture2D : public Object /** Helper functions that returns bits per pixels for a given format. @since v2.0 */ - unsigned int getBitsPerPixelForFormat(backend::PixelFormat format) const; + unsigned int getBitsPerPixelForFormat(rhi::PixelFormat format) const; /** Get content size. */ const Vec2& getContentSizeInPixels(); @@ -343,7 +316,7 @@ class AX_DLL Texture2D : public Object bool hasMipmaps() const; /** Gets the pixel format of the texture. */ - backend::PixelFormat getPixelFormat() const; + rhi::PixelFormat getPixelFormat() const; int getSamplerFlags() const { return _samplerFlags; } @@ -353,7 +326,7 @@ class AX_DLL Texture2D : public Object /** Gets the height of the texture in pixels. */ int getPixelsHigh() const; - backend::TextureBackend* getBackendTexture() const; + rhi::Texture* getBackendTexture() const; /** Gets max S. */ float getMaxS() const; @@ -418,7 +391,7 @@ class AX_DLL Texture2D : public Object protected: /** pixel format of the texture */ - backend::PixelFormat _pixelFormat; + rhi::PixelFormat _pixelFormat; /** width in pixels */ int _pixelsWide; @@ -427,7 +400,7 @@ class AX_DLL Texture2D : public Object int _pixelsHigh; /** texture name */ - backend::Texture2DBackend* _texture; + rhi::Texture* _texture; /** texture max S */ float _maxS; @@ -449,9 +422,9 @@ class AX_DLL Texture2D : public Object bool _valid; std::string _filePath; - backend::ProgramState* _programState = nullptr; - backend::UniformLocation _mvpMatrixLocation; - backend::UniformLocation _textureLocation; + rhi::ProgramState* _programState = nullptr; + rhi::UniformLocation _mvpMatrixLocation; + rhi::UniformLocation _textureLocation; CustomCommand _customCommand; }; diff --git a/core/renderer/TextureAtlas.cpp b/axmol/renderer/TextureAtlas.cpp similarity index 90% rename from core/renderer/TextureAtlas.cpp rename to axmol/renderer/TextureAtlas.cpp index 074566e44c1a..7595d64bfc8d 100644 --- a/core/renderer/TextureAtlas.cpp +++ b/axmol/renderer/TextureAtlas.cpp @@ -27,20 +27,20 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/TextureAtlas.h" +#include "axmol/renderer/TextureAtlas.h" #include -#include "base/Macros.h" -#include "base/UTF8.h" -#include "base/EventType.h" -#include "base/Director.h" -#include "base/Configuration.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerCustom.h" -#include "renderer/TextureCache.h" -#include "renderer/Renderer.h" -#include "renderer/Texture2D.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Director.h" +#include "axmol/base/Configuration.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Texture2D.h" // According to some tests GL_TRIANGLE_STRIP is slower, MUCH slower. Probably I'm doing something very wrong @@ -87,14 +87,14 @@ void TextureAtlas::setTexture(Texture2D* var) _texture = var; } -V3F_C4B_T2F_Quad* TextureAtlas::getQuads() +V3F_T2F_C4B_Quad* TextureAtlas::getQuads() { // if someone accesses the quads directly, presume that changes will be made _dirty = true; return _quads; } -void TextureAtlas::setQuads(V3F_C4B_T2F_Quad* quads) +void TextureAtlas::setQuads(V3F_T2F_C4B_Quad* quads) { _quads = quads; } @@ -156,7 +156,7 @@ bool TextureAtlas::initWithTexture(Texture2D* texture, ssize_t capacity) // Re-initialization is not allowed AXASSERT(_quads == nullptr && _indices == nullptr, "_quads and _indices should be nullptr."); - _quads = (V3F_C4B_T2F_Quad*)malloc(_capacity * sizeof(V3F_C4B_T2F_Quad)); + _quads = (V3F_T2F_C4B_Quad*)malloc(_capacity * sizeof(V3F_T2F_C4B_Quad)); _indices = (uint16_t*)malloc(_capacity * 6 * sizeof(uint16_t)); if (!(_quads && _indices) && _capacity > 0) @@ -171,7 +171,7 @@ bool TextureAtlas::initWithTexture(Texture2D* texture, ssize_t capacity) return false; } - memset(_quads, 0, _capacity * sizeof(V3F_C4B_T2F_Quad)); + memset(_quads, 0, _capacity * sizeof(V3F_T2F_C4B_Quad)); memset(_indices, 0, _capacity * 6 * sizeof(uint16_t)); this->setupIndices(); @@ -206,7 +206,7 @@ void TextureAtlas::setupIndices() // TextureAtlas - Update, Insert, Move & Remove -void TextureAtlas::updateQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index) +void TextureAtlas::updateQuad(const V3F_T2F_C4B_Quad& quad, ssize_t index) { AXASSERT(index >= 0 && index < _capacity, "updateQuadWithTexture: Invalid index"); @@ -217,7 +217,7 @@ void TextureAtlas::updateQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index) _dirty = true; } -void TextureAtlas::insertQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index) +void TextureAtlas::insertQuad(const V3F_T2F_C4B_Quad& quad, ssize_t index) { AXASSERT(index >= 0 && index < _capacity, "insertQuadWithTexture: Invalid index"); @@ -239,7 +239,7 @@ void TextureAtlas::insertQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index) _dirty = true; } -void TextureAtlas::insertQuads(V3F_C4B_T2F_Quad* quads, ssize_t index, ssize_t amount) +void TextureAtlas::insertQuads(V3F_T2F_C4B_Quad* quads, ssize_t index, ssize_t amount) { AXASSERT(index >= 0 && amount >= 0 && index + amount <= _capacity, "insertQuadWithTexture: Invalid index + amount"); @@ -290,7 +290,7 @@ void TextureAtlas::insertQuadFromIndex(ssize_t oldIndex, ssize_t newIndex) } // texture coordinates - V3F_C4B_T2F_Quad quadsBackup = _quads[oldIndex]; + V3F_T2F_C4B_Quad quadsBackup = _quads[oldIndex]; memmove(&_quads[dst], &_quads[src], sizeof(_quads[0]) * howMany); _quads[newIndex] = quadsBackup; @@ -351,7 +351,7 @@ bool TextureAtlas::resizeCapacity(ssize_t newCapacity) _totalQuads = MIN(_totalQuads, newCapacity); _capacity = newCapacity; - V3F_C4B_T2F_Quad* tmpQuads = nullptr; + V3F_T2F_C4B_Quad* tmpQuads = nullptr; uint16_t* tmpIndices = nullptr; // when calling initWithTexture(fileName, 0) on bada device, calloc(0, 1) will fail and return nullptr, @@ -361,7 +361,7 @@ bool TextureAtlas::resizeCapacity(ssize_t newCapacity) ssize_t new_quads_size = _capacity * _quads_size; if (_quads == nullptr) { - tmpQuads = (V3F_C4B_T2F_Quad*)malloc(new_quads_size); + tmpQuads = (V3F_T2F_C4B_Quad*)malloc(new_quads_size); if (tmpQuads != nullptr) { memset(tmpQuads, 0, new_quads_size); @@ -369,7 +369,7 @@ bool TextureAtlas::resizeCapacity(ssize_t newCapacity) } else { - tmpQuads = (V3F_C4B_T2F_Quad*)realloc(_quads, new_quads_size); + tmpQuads = (V3F_T2F_C4B_Quad*)realloc(_quads, new_quads_size); if (tmpQuads != nullptr && _capacity > oldCapacity) { memset(tmpQuads + oldCapacity, 0, (_capacity - oldCapacity) * _quads_size); @@ -436,8 +436,8 @@ void TextureAtlas::moveQuadsFromIndex(ssize_t oldIndex, ssize_t amount, ssize_t return; } // create buffer - size_t quadSize = sizeof(V3F_C4B_T2F_Quad); - V3F_C4B_T2F_Quad* tempQuads = (V3F_C4B_T2F_Quad*)malloc(quadSize * amount); + size_t quadSize = sizeof(V3F_T2F_C4B_Quad); + V3F_T2F_C4B_Quad* tempQuads = (V3F_T2F_C4B_Quad*)malloc(quadSize * amount); memcpy(tempQuads, &_quads[oldIndex], quadSize * amount); if (newIndex < oldIndex) @@ -468,7 +468,7 @@ void TextureAtlas::moveQuadsFromIndex(ssize_t index, ssize_t newIndex) void TextureAtlas::fillWithEmptyQuadsFromIndex(ssize_t index, ssize_t amount) { AXASSERT(index >= 0 && amount >= 0, "values must be >= 0"); - V3F_C4B_T2F_Quad quad; + V3F_T2F_C4B_Quad quad; memset(&quad, 0, sizeof(quad)); auto to = index + amount; diff --git a/core/renderer/TextureAtlas.h b/axmol/renderer/TextureAtlas.h similarity index 95% rename from core/renderer/TextureAtlas.h rename to axmol/renderer/TextureAtlas.h index d9175b12db07..6bbbfe914bf2 100644 --- a/core/renderer/TextureAtlas.h +++ b/axmol/renderer/TextureAtlas.h @@ -30,9 +30,9 @@ THE SOFTWARE. #include -#include "base/Types.h" -#include "base/Object.h" -#include "base/Config.h" +#include "axmol/base/Types.h" +#include "axmol/base/Object.h" +#include "axmol/base/Config.h" namespace ax { @@ -111,14 +111,14 @@ class AX_DLL TextureAtlas : public Object @param index Index must be between 0 and the atlas capacity - 1. @since v0.8 */ - void updateQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index); + void updateQuad(const V3F_T2F_C4B_Quad& quad, ssize_t index); /** Inserts a Quad (texture, vertex and color) at a certain index. @param quad Quad that are going to be rendered. @param index Index must be between 0 and the atlas capacity - 1. @since v0.8 */ - void insertQuad(const V3F_C4B_T2F_Quad& quad, ssize_t index); + void insertQuad(const V3F_T2F_C4B_Quad& quad, ssize_t index); /** Inserts a c array of quads at a given index. @param quads Quad that are going to be rendered. @@ -127,7 +127,7 @@ class AX_DLL TextureAtlas : public Object @attention This method doesn't enlarge the array when amount + index > totalQuads. @since v1.1 */ - void insertQuads(V3F_C4B_T2F_Quad* quads, ssize_t index, ssize_t amount); + void insertQuads(V3F_T2F_C4B_Quad* quads, ssize_t index, ssize_t amount); /** Removes the quad that is located at a certain index and inserts it at a new index. This operation is faster than removing and inserting in a quad in 2 different steps. @@ -211,10 +211,10 @@ class AX_DLL TextureAtlas : public Object void setTexture(Texture2D* texture); /** Gets the quads that are going to be rendered. */ - V3F_C4B_T2F_Quad* getQuads(); + V3F_T2F_C4B_Quad* getQuads(); /** Sets the quads that are going to be rendered. */ - void setQuads(V3F_C4B_T2F_Quad* quads); + void setQuads(V3F_T2F_C4B_Quad* quads); inline unsigned short* getIndices() { return _indices; } @@ -236,7 +236,7 @@ class AX_DLL TextureAtlas : public Object /** Texture of the texture atlas */ Texture2D* _texture = nullptr; /** Quads that are going to be rendered */ - V3F_C4B_T2F_Quad* _quads = nullptr; + V3F_T2F_C4B_Quad* _quads = nullptr; #if AX_ENABLE_CACHE_TEXTURE_DATA EventListenerCustom* _rendererRecreatedListener = nullptr; diff --git a/core/renderer/TextureCache.cpp b/axmol/renderer/TextureCache.cpp similarity index 97% rename from core/renderer/TextureCache.cpp rename to axmol/renderer/TextureCache.cpp index 1c1baac5abd4..4cd5112e9b75 100644 --- a/core/renderer/TextureCache.cpp +++ b/axmol/renderer/TextureCache.cpp @@ -27,22 +27,22 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/TextureCache.h" +#include "axmol/renderer/TextureCache.h" #include #include #include #include -#include "renderer/Texture2D.h" -#include "base/Macros.h" -#include "base/UTF8.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include "platform/FileUtils.h" -#include "base/Utils.h" -#include "base/NinePatchImageParser.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Macros.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Utils.h" +#include "axmol/base/NinePatchImageParser.h" +#include "axmol/rhi/DriverBase.h" using namespace std; @@ -87,7 +87,7 @@ struct TextureCache::AsyncStruct : filename(fn) , callback(f) , callbackKey(key) - , pixelFormat(Texture2D::getDefaultAlphaPixelFormat()) + , pixelFormat(PixelFormat::NONE) , loadSuccess(false) {} @@ -96,7 +96,7 @@ struct TextureCache::AsyncStruct std::string callbackKey; Image image; Image imageAlpha; - backend::PixelFormat pixelFormat; + rhi::PixelFormat pixelFormat; bool loadSuccess; }; @@ -433,7 +433,7 @@ Texture2D* TextureCache::getDummyTexture() Texture2D* TextureCache::addImage(std::string_view path) { - return addImage(path, Texture2D::getDefaultAlphaPixelFormat()); + return addImage(path, PixelFormat::NONE); } Texture2D* TextureCache::addImage(std::string_view path, PixelFormat format) @@ -516,7 +516,7 @@ void TextureCache::parseNinePatchImage(ax::Image* image, ax::Texture2D* texture, Texture2D* TextureCache::addImage(Image* image, std::string_view key) { - return addImage(image, key, Texture2D::getDefaultAlphaPixelFormat()); + return addImage(image, key, PixelFormat::NONE); } Texture2D* TextureCache::addImage(Image* image, std::string_view key, PixelFormat format) @@ -819,7 +819,7 @@ VolatileTexture::VolatileTexture(Texture2D* t) , _uiImage(nullptr) , _cashedImageType(kInvalid) , _textureData(nullptr) - , _pixelFormat(backend::PixelFormat::RGBA8) + , _pixelFormat(rhi::PixelFormat::RGBA8) , _fileName("") , _text("") {} @@ -884,7 +884,7 @@ VolatileTexture* VolatileTextureMgr::getOrAddVolatileTexture(Texture2D* tt) void VolatileTextureMgr::addDataTexture(Texture2D* tt, void* data, int dataLen, - backend::PixelFormat pixelFormat, + rhi::PixelFormat pixelFormat, const Vec2& contentSize) { if (_isReloading) @@ -976,7 +976,7 @@ void VolatileTextureMgr::reloadAllTextures() _isReloading = false; } -void VolatileTextureMgr::reloadTexture(Texture2D* texture, std::string_view filename, backend::PixelFormat pixelFormat) +void VolatileTextureMgr::reloadTexture(Texture2D* texture, std::string_view filename, rhi::PixelFormat pixelFormat) { if (!texture) return; diff --git a/core/renderer/TextureCache.h b/axmol/renderer/TextureCache.h similarity index 96% rename from core/renderer/TextureCache.h rename to axmol/renderer/TextureCache.h index 6f0be3d0d0c8..6ffa4e2c1b66 100644 --- a/core/renderer/TextureCache.h +++ b/axmol/renderer/TextureCache.h @@ -37,9 +37,9 @@ THE SOFTWARE. #include #include -#include "base/Object.h" -#include "renderer/Texture2D.h" -#include "platform/Image.h" +#include "axmol/base/Object.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/platform/Image.h" #if AX_ENABLE_CACHE_TEXTURE_DATA # include @@ -111,8 +111,6 @@ class AX_DLL TextureCache : public Object @param filepath The file path. @param callback A callback function would be invoked after the image is loaded. @since v0.8 - - @remark Please don't invoke Texture2D::setDefaultAlphaPixelFormat in main GL thread before invoke this API. */ virtual void addImageAsync(std::string_view filepath, const std::function& callback); @@ -280,7 +278,7 @@ class VolatileTexture void* _textureData; int _dataLen; Vec2 _textureSize; - backend::PixelFormat _pixelFormat; + rhi::PixelFormat _pixelFormat; std::string _fileName; @@ -296,7 +294,7 @@ class AX_DLL VolatileTextureMgr static void addDataTexture(Texture2D* tt, void* data, int dataLen, - backend::PixelFormat pixelFormat, + rhi::PixelFormat pixelFormat, const Vec2& contentSize); static void addImage(Texture2D* tt, Image* image); static void removeTexture(Texture2D* t); @@ -312,7 +310,7 @@ class AX_DLL VolatileTextureMgr static VolatileTexture* getOrAddVolatileTexture(Texture2D* tt); private: - static void reloadTexture(Texture2D* texture, std::string_view filename, backend::PixelFormat pixelFormat); + static void reloadTexture(Texture2D* texture, std::string_view filename, rhi::PixelFormat pixelFormat); }; #endif diff --git a/core/renderer/TextureCube.cpp b/axmol/renderer/TextureCube.cpp similarity index 81% rename from core/renderer/TextureCube.cpp rename to axmol/renderer/TextureCube.cpp index ff281d9cbabf..37bc1bbcfc53 100644 --- a/core/renderer/TextureCube.cpp +++ b/axmol/renderer/TextureCube.cpp @@ -24,17 +24,17 @@ THE SOFTWARE. ****************************************************************************/ -#include "renderer/TextureCube.h" -#include "platform/Image.h" -#include "platform/FileUtils.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/PixelFormatUtils.h" +#include "axmol/renderer/TextureCube.h" +#include "axmol/platform/Image.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/PixelFormatUtils.h" namespace ax { -unsigned char* getImageData(Image* img, backend::PixelFormat& ePixFmt) +unsigned char* getImageData(Image* img, rhi::PixelFormat& ePixFmt) { unsigned char* pTmpData = img->getData(); unsigned int* inPixel32 = nullptr; @@ -49,24 +49,24 @@ unsigned char* getImageData(Image* img, backend::PixelFormat& ePixFmt) // compute pixel format if (bHasAlpha) { - ePixFmt = backend::PixelFormat::RGBA8; + ePixFmt = rhi::PixelFormat::RGBA8; } else { if (uBPP >= 8) { - ePixFmt = backend::PixelFormat::RGB8; + ePixFmt = rhi::PixelFormat::RGB8; } else { - ePixFmt = backend::PixelFormat::RGB565; + ePixFmt = rhi::PixelFormat::RGB565; } } // Repack the pixel data into the right format unsigned int uLen = nWidth * nHeight; - if (ePixFmt == backend::PixelFormat::RGB565) + if (ePixFmt == rhi::PixelFormat::RGB565) { if (bHasAlpha) { @@ -102,7 +102,7 @@ unsigned char* getImageData(Image* img, backend::PixelFormat& ePixFmt) } } - if (bHasAlpha && ePixFmt == backend::PixelFormat::RGB8) + if (bHasAlpha && ePixFmt == rhi::PixelFormat::RGB8) { // Convert "RRRRRRRRRGGGGGGGGBBBBBBBBAAAAAAAA" to "RRRRRRRRGGGGGGGGBBBBBBBB" inPixel32 = (unsigned int*)img->getData(); @@ -208,32 +208,28 @@ bool TextureCube::init(std::string_view positive_x, } } - backend::TextureDescriptor textureDescriptor; - textureDescriptor.width = textureDescriptor.height = imageSize; - textureDescriptor.textureType = backend::TextureType::TEXTURE_CUBE; - textureDescriptor.samplerDescriptor.minFilter = backend::SamplerFilter::LINEAR; - textureDescriptor.samplerDescriptor.magFilter = backend::SamplerFilter::LINEAR; - textureDescriptor.samplerDescriptor.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - textureDescriptor.samplerDescriptor.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + rhi::TextureDesc textureDesc{}; + textureDesc.width = textureDesc.height = imageSize; + textureDesc.textureType = rhi::TextureType::TEXTURE_CUBE; _texture = - static_cast(backend::DriverBase::getInstance()->newTexture(textureDescriptor)); + static_cast(rhi::DriverBase::getInstance()->createTexture(textureDesc)); AXASSERT(_texture != nullptr, "TextureCubemap: texture can not be nullptr"); for (int i = 0; i < 6; i++) { Image* img = images[i]; - backend::PixelFormat ePixelFmt; + rhi::PixelFormat ePixelFmt; unsigned char* pData = getImageData(img, ePixelFmt); uint8_t* cData = nullptr; uint8_t* useData = pData; // convert pixel format to RGBA - if (ePixelFmt != backend::PixelFormat::RGBA8) + if (ePixelFmt != rhi::PixelFormat::RGBA8) { size_t len = 0; - backend::PixelFormatUtils::convertDataToFormat(pData, img->getDataLen(), ePixelFmt, - backend::PixelFormat::RGBA8, &cData, &len); + rhi::PixelFormatUtils::convertDataToFormat(pData, img->getDataLen(), ePixelFmt, + rhi::PixelFormat::RGBA8, &cData, &len); if (cData != pData) // convert error { useData = cData; @@ -245,7 +241,7 @@ bool TextureCube::init(std::string_view positive_x, } } - _texture->updateFaceData(static_cast(i), useData); + _texture->updateFaceData(static_cast(i), useData); if (cData != pData) free(cData); @@ -264,7 +260,7 @@ bool TextureCube::init(std::string_view positive_x, void TextureCube::setTexParameters(const Texture2D::TexParams& texParams) { - _texture->updateSamplerDescriptor(texParams); + _texture->updateSamplerDesc(texParams); } bool TextureCube::reloadTexture() diff --git a/core/renderer/TextureCube.h b/axmol/renderer/TextureCube.h similarity index 93% rename from core/renderer/TextureCube.h rename to axmol/renderer/TextureCube.h index 052fffe1f23e..8a4e46a54f69 100644 --- a/core/renderer/TextureCube.h +++ b/axmol/renderer/TextureCube.h @@ -25,12 +25,12 @@ #pragma once -#include "renderer/Texture2D.h" -#include "renderer/backend/Texture.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/rhi/Texture.h" #include #include -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -68,7 +68,7 @@ class AX_DLL TextureCube : public Object */ void setTexParameters(const Texture2D::TexParams&); - backend::TextureBackend* getBackendTexture() { return _texture; } + rhi::Texture* getBackendTexture() { return _texture; } const std::vector& getImagePaths() const { return _imgPath; } @@ -95,7 +95,7 @@ class AX_DLL TextureCube : public Object private: std::vector _imgPath; - backend::TextureCubemapBackend* _texture = nullptr; + rhi::Texture* _texture = nullptr; }; // end of 3d group diff --git a/core/renderer/TrianglesCommand.cpp b/axmol/renderer/TrianglesCommand.cpp similarity index 83% rename from core/renderer/TrianglesCommand.cpp rename to axmol/renderer/TrianglesCommand.cpp index 53e6259c90d0..66c7a0077aa4 100644 --- a/core/renderer/TrianglesCommand.cpp +++ b/axmol/renderer/TrianglesCommand.cpp @@ -23,11 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "renderer/TrianglesCommand.h" +#include "axmol/renderer/TrianglesCommand.h" #include "xxhash.h" -#include "renderer/Renderer.h" -#include "renderer/Texture2D.h" -#include "base//Utils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/base/Utils.h" namespace ax { @@ -55,7 +55,7 @@ void TrianglesCommand::init(float globalOrder, } _mv = mv; - auto batchId = _pipelineDescriptor.programState->getBatchId(); + auto batchId = _pipelineDesc.programState->getBatchId(); if (_batchId != batchId || _texture != texture->getBackendTexture() || _blendType != blendType) { _batchId = batchId; @@ -63,12 +63,12 @@ void TrianglesCommand::init(float globalOrder, _blendType = blendType; // TODO: minggo set it in Node? - auto& blendDescriptor = _pipelineDescriptor.blendDescriptor; - blendDescriptor.blendEnabled = true; - blendDescriptor.sourceRGBBlendFactor = blendDescriptor.sourceAlphaBlendFactor = blendType.src; - blendDescriptor.destinationRGBBlendFactor = blendDescriptor.destinationAlphaBlendFactor = blendType.dst; + auto& blendDesc = _pipelineDesc.blendDesc; + blendDesc.blendEnabled = true; + blendDesc.sourceRGBBlendFactor = blendDesc.sourceAlphaBlendFactor = blendType.src; + blendDesc.destinationRGBBlendFactor = blendDesc.destinationAlphaBlendFactor = blendType.dst; - if (!_pipelineDescriptor.programState->isBatchable()) + if (!_pipelineDesc.programState->isBatchable()) setSkipBatching(true); if (!isSkipBatching()) @@ -90,8 +90,8 @@ void TrianglesCommand::generateMaterialID() { void* texture; uint64_t batchId; - backend::BlendFactor src; - backend::BlendFactor dst; + rhi::BlendFactor src; + rhi::BlendFactor dst; } hashMe; // NOTE: Initialize hashMe struct to make the value of padding bytes be filled with zero. diff --git a/core/renderer/TrianglesCommand.h b/axmol/renderer/TrianglesCommand.h similarity index 92% rename from core/renderer/TrianglesCommand.h rename to axmol/renderer/TrianglesCommand.h index 7f297b2e95ad..df1f54e984f9 100644 --- a/core/renderer/TrianglesCommand.h +++ b/axmol/renderer/TrianglesCommand.h @@ -25,8 +25,8 @@ ****************************************************************************/ #pragma once -#include "renderer/RenderCommand.h" -#include "renderer/PipelineDescriptor.h" +#include "axmol/renderer/RenderCommand.h" +#include "axmol/renderer/PipelineDesc.h" /** * @addtogroup renderer @@ -40,11 +40,11 @@ namespace ax Every TrianglesCommand will have generate material ID by give textureID, glProgramState, Blend function if the material id is the same, these TrianglesCommands could be batched to save draw call. */ -namespace backend +namespace rhi { -class TextureBackend; +class Texture; class Program; -} // namespace backend +} // namespace rhi class Texture2D; @@ -54,14 +54,14 @@ class AX_DLL TrianglesCommand : public RenderCommand /**The structure of Triangles. */ struct Triangles { - Triangles(V3F_C4B_T2F* _verts, unsigned short* _indices, unsigned int _vertCount, unsigned int _indexCount) + Triangles(V3F_T2F_C4B* _verts, unsigned short* _indices, unsigned int _vertCount, unsigned int _indexCount) : verts(_verts), indices(_indices), vertCount(_vertCount), indexCount(_indexCount) {} Triangles() {} /**Vertex data pointer.*/ - V3F_C4B_T2F* verts = nullptr; + V3F_T2F_C4B* verts = nullptr; /**Index data pointer.*/ unsigned short* indices = nullptr; /**The number of vertices.*/ @@ -98,7 +98,7 @@ class AX_DLL TrianglesCommand : public RenderCommand /**Get the index count of the triangles.*/ size_t getIndexCount() const { return _triangles.indexCount; } /**Get the vertex data pointer.*/ - const V3F_C4B_T2F* getVertices() const { return _triangles.verts; } + const V3F_T2F_C4B* getVertices() const { return _triangles.verts; } /**Get the index data pointer.*/ const unsigned short* getIndices() const { return _triangles.indices; } /**Get the model view matrix.*/ @@ -120,7 +120,7 @@ class AX_DLL TrianglesCommand : public RenderCommand // Cached value to determine to generate material id or not. BlendFunc _blendType = BlendFunc::DISABLE; uint64_t _batchId = 0; - backend::TextureBackend* _texture = nullptr; + rhi::Texture* _texture = nullptr; }; } diff --git a/core/renderer/shaders/base.glsl b/axmol/renderer/shaders/base.glsl similarity index 69% rename from core/renderer/shaders/base.glsl rename to axmol/renderer/shaders/base.glsl index c8c06a985550..ac6f6161615c 100644 --- a/core/renderer/shaders/base.glsl +++ b/axmol/renderer/shaders/base.glsl @@ -20,8 +20,6 @@ #define BLENDINDICES COLOR1 #define BLENDWEIGHT COLOR2 -#if !defined(GLES2) - # define vfloat_def(x, y) vec4 x[(y + 3) / 4] # define vfloat_at(x, y) x[y / 4][y % 4] @@ -36,22 +34,3 @@ # define RG8_CHANNEL xy # define FWIDTH(dist) 0.4 - -#else - -# define vfloat_def(x, y) float x[y] -# define vfloat_at(x, y) x[y] - -# define vvec2_def(x, y) vec2 x[y] -# define vvec2_at1(x, y, z) x[y][z] -# define vvec2_at(x, y) x[y] - -# define vvec3_def(x, y) vec3 x[y] -# define vvec3_at1(x, y, z) x[y][z] -# define vvec3_at(x, y) x[y] - -# define RG8_CHANNEL xw // emulate RG8 with LA8 - -# define FWIDTH(dist) fwidth(dist) - -#endif diff --git a/core/renderer/shaders/cameraClear.frag b/axmol/renderer/shaders/cameraClear.frag similarity index 100% rename from core/renderer/shaders/cameraClear.frag rename to axmol/renderer/shaders/cameraClear.frag diff --git a/core/renderer/shaders/cameraClear.vert b/axmol/renderer/shaders/cameraClear.vert similarity index 100% rename from core/renderer/shaders/cameraClear.vert rename to axmol/renderer/shaders/cameraClear.vert diff --git a/core/renderer/shaders/color.frag b/axmol/renderer/shaders/color.frag similarity index 100% rename from core/renderer/shaders/color.frag rename to axmol/renderer/shaders/color.frag diff --git a/core/renderer/shaders/colorNormal.frag b/axmol/renderer/shaders/colorNormal.frag similarity index 100% rename from core/renderer/shaders/colorNormal.frag rename to axmol/renderer/shaders/colorNormal.frag diff --git a/core/renderer/shaders/colorNormalTexture.frag b/axmol/renderer/shaders/colorNormalTexture.frag similarity index 100% rename from core/renderer/shaders/colorNormalTexture.frag rename to axmol/renderer/shaders/colorNormalTexture.frag diff --git a/core/renderer/shaders/colorTexture.frag b/axmol/renderer/shaders/colorTexture.frag similarity index 100% rename from core/renderer/shaders/colorTexture.frag rename to axmol/renderer/shaders/colorTexture.frag diff --git a/core/renderer/shaders/colorUtils.glsl b/axmol/renderer/shaders/colorUtils.glsl similarity index 100% rename from core/renderer/shaders/colorUtils.glsl rename to axmol/renderer/shaders/colorUtils.glsl diff --git a/core/renderer/shaders/dualSampler.frag b/axmol/renderer/shaders/dualSampler.frag similarity index 100% rename from core/renderer/shaders/dualSampler.frag rename to axmol/renderer/shaders/dualSampler.frag diff --git a/core/renderer/shaders/dualSampler_gray.frag b/axmol/renderer/shaders/dualSampler_gray.frag similarity index 100% rename from core/renderer/shaders/dualSampler_gray.frag rename to axmol/renderer/shaders/dualSampler_gray.frag diff --git a/core/renderer/shaders/dualSampler_hsv.frag b/axmol/renderer/shaders/dualSampler_hsv.frag similarity index 100% rename from core/renderer/shaders/dualSampler_hsv.frag rename to axmol/renderer/shaders/dualSampler_hsv.frag diff --git a/core/renderer/shaders/grayScale.frag b/axmol/renderer/shaders/grayScale.frag similarity index 100% rename from core/renderer/shaders/grayScale.frag rename to axmol/renderer/shaders/grayScale.frag diff --git a/core/renderer/shaders/hsv.frag b/axmol/renderer/shaders/hsv.frag similarity index 100% rename from core/renderer/shaders/hsv.frag rename to axmol/renderer/shaders/hsv.frag diff --git a/core/renderer/shaders/label_distanceGlow.frag b/axmol/renderer/shaders/label_distanceGlow.frag similarity index 100% rename from core/renderer/shaders/label_distanceGlow.frag rename to axmol/renderer/shaders/label_distanceGlow.frag diff --git a/core/renderer/shaders/label_distanceNormal.frag b/axmol/renderer/shaders/label_distanceNormal.frag similarity index 100% rename from core/renderer/shaders/label_distanceNormal.frag rename to axmol/renderer/shaders/label_distanceNormal.frag diff --git a/core/renderer/shaders/label_distanceOutline.frag b/axmol/renderer/shaders/label_distanceOutline.frag similarity index 100% rename from core/renderer/shaders/label_distanceOutline.frag rename to axmol/renderer/shaders/label_distanceOutline.frag diff --git a/core/renderer/shaders/label_normal.frag b/axmol/renderer/shaders/label_normal.frag similarity index 100% rename from core/renderer/shaders/label_normal.frag rename to axmol/renderer/shaders/label_normal.frag diff --git a/core/renderer/shaders/label_outline.frag b/axmol/renderer/shaders/label_outline.frag similarity index 95% rename from core/renderer/shaders/label_outline.frag rename to axmol/renderer/shaders/label_outline.frag index c20b96af163a..b652cdf3335c 100644 --- a/core/renderer/shaders/label_outline.frag +++ b/axmol/renderer/shaders/label_outline.frag @@ -21,11 +21,7 @@ void main() // fontAlpha == 1 means the area of solid text (without edge) // fontAlpha == 0 means the area outside text, including outline area // fontAlpha == (0, 1) means the edge of text -#ifndef GLES2 float fontAlpha = texColor.y; -#else - float fontAlpha = texColor.w; -#endif // outlineAlpha == 1 means the area of 'solid text' and 'solid outline' // outlineAlpha == 0 means the transparent area outside text and outline diff --git a/core/renderer/shaders/layer_radialGradient.frag b/axmol/renderer/shaders/layer_radialGradient.frag similarity index 100% rename from core/renderer/shaders/layer_radialGradient.frag rename to axmol/renderer/shaders/layer_radialGradient.frag diff --git a/core/renderer/shaders/lineColor.frag b/axmol/renderer/shaders/lineColor.frag similarity index 100% rename from core/renderer/shaders/lineColor.frag rename to axmol/renderer/shaders/lineColor.frag diff --git a/core/renderer/shaders/lineColor.vert b/axmol/renderer/shaders/lineColor.vert similarity index 100% rename from core/renderer/shaders/lineColor.vert rename to axmol/renderer/shaders/lineColor.vert diff --git a/core/renderer/shaders/particle.vert b/axmol/renderer/shaders/particle.vert similarity index 100% rename from core/renderer/shaders/particle.vert rename to axmol/renderer/shaders/particle.vert diff --git a/core/renderer/shaders/particleColor.frag b/axmol/renderer/shaders/particleColor.frag similarity index 100% rename from core/renderer/shaders/particleColor.frag rename to axmol/renderer/shaders/particleColor.frag diff --git a/core/renderer/shaders/particleTexture.frag b/axmol/renderer/shaders/particleTexture.frag similarity index 100% rename from core/renderer/shaders/particleTexture.frag rename to axmol/renderer/shaders/particleTexture.frag diff --git a/core/renderer/shaders/position.vert b/axmol/renderer/shaders/position.vert similarity index 71% rename from core/renderer/shaders/position.vert rename to axmol/renderer/shaders/position.vert index e4ec88513ee5..8cafb640c63c 100644 --- a/core/renderer/shaders/position.vert +++ b/axmol/renderer/shaders/position.vert @@ -3,9 +3,6 @@ layout(location = POSITION) in vec4 a_position; -layout(location = 0) out vec4 v_position; - - layout(std140) uniform vs_ub { mat4 u_MVPMatrix; }; @@ -13,5 +10,4 @@ layout(std140) uniform vs_ub { void main() { gl_Position = u_MVPMatrix * a_position; - v_position = a_position; } diff --git a/core/renderer/shaders/positionColor.frag b/axmol/renderer/shaders/positionColor.frag similarity index 100% rename from core/renderer/shaders/positionColor.frag rename to axmol/renderer/shaders/positionColor.frag diff --git a/core/renderer/shaders/positionColor.vert b/axmol/renderer/shaders/positionColor.vert similarity index 100% rename from core/renderer/shaders/positionColor.vert rename to axmol/renderer/shaders/positionColor.vert diff --git a/core/renderer/shaders/positionColorLengthTexture.frag b/axmol/renderer/shaders/positionColorLengthTexture.frag similarity index 100% rename from core/renderer/shaders/positionColorLengthTexture.frag rename to axmol/renderer/shaders/positionColorLengthTexture.frag diff --git a/core/renderer/shaders/positionColorLengthTexture.vert b/axmol/renderer/shaders/positionColorLengthTexture.vert similarity index 100% rename from core/renderer/shaders/positionColorLengthTexture.vert rename to axmol/renderer/shaders/positionColorLengthTexture.vert diff --git a/core/renderer/shaders/positionColorTextureAsPointsize.vert b/axmol/renderer/shaders/positionColorTextureAsPointsize.vert similarity index 100% rename from core/renderer/shaders/positionColorTextureAsPointsize.vert rename to axmol/renderer/shaders/positionColorTextureAsPointsize.vert diff --git a/core/renderer/shaders/positionNormalTexture.vert b/axmol/renderer/shaders/positionNormalTexture.vert similarity index 100% rename from core/renderer/shaders/positionNormalTexture.vert rename to axmol/renderer/shaders/positionNormalTexture.vert diff --git a/core/renderer/shaders/positionTexture.frag b/axmol/renderer/shaders/positionTexture.frag similarity index 100% rename from core/renderer/shaders/positionTexture.frag rename to axmol/renderer/shaders/positionTexture.frag diff --git a/core/renderer/shaders/positionTexture.vert b/axmol/renderer/shaders/positionTexture.vert similarity index 100% rename from core/renderer/shaders/positionTexture.vert rename to axmol/renderer/shaders/positionTexture.vert diff --git a/core/renderer/shaders/positionTextureColor.frag b/axmol/renderer/shaders/positionTextureColor.frag similarity index 100% rename from core/renderer/shaders/positionTextureColor.frag rename to axmol/renderer/shaders/positionTextureColor.frag diff --git a/core/renderer/shaders/positionTextureColor.vert b/axmol/renderer/shaders/positionTextureColor.vert similarity index 100% rename from core/renderer/shaders/positionTextureColor.vert rename to axmol/renderer/shaders/positionTextureColor.vert diff --git a/core/renderer/shaders/positionTextureColorAlphaTest.frag b/axmol/renderer/shaders/positionTextureColorAlphaTest.frag similarity index 100% rename from core/renderer/shaders/positionTextureColorAlphaTest.frag rename to axmol/renderer/shaders/positionTextureColorAlphaTest.frag diff --git a/axmol/renderer/shaders/positionTextureGray.frag b/axmol/renderer/shaders/positionTextureGray.frag new file mode 100644 index 000000000000..d01133dde380 --- /dev/null +++ b/axmol/renderer/shaders/positionTextureGray.frag @@ -0,0 +1,16 @@ +#version 310 es +precision highp float; +precision highp int; + +layout(location = COLOR0) in vec4 v_color; +layout(location = TEXCOORD0) in vec2 v_texCoord; + +layout(binding = 0) uniform sampler2D u_tex0; + +layout(location = SV_Target0) out vec4 FragColor; + +void main() +{ + vec4 c = texture(u_tex0, v_texCoord); + FragColor = v_color * vec4(c.r, c.r, c.r, 1); +} diff --git a/axmol/renderer/shaders/positionTextureGrayAlpha.frag b/axmol/renderer/shaders/positionTextureGrayAlpha.frag new file mode 100644 index 000000000000..9abd1fc8aebc --- /dev/null +++ b/axmol/renderer/shaders/positionTextureGrayAlpha.frag @@ -0,0 +1,16 @@ +#version 310 es +precision highp float; +precision highp int; + +layout(location = COLOR0) in vec4 v_color; +layout(location = TEXCOORD0) in vec2 v_texCoord; + +layout(binding = 0) uniform sampler2D u_tex0; + +layout(location = SV_Target0) out vec4 FragColor; + +void main() +{ + vec4 c = texture(u_tex0, v_texCoord); + FragColor = v_color * vec4(c.r, c.r, c.r, c.g); +} diff --git a/core/renderer/shaders/positionUColor.vert b/axmol/renderer/shaders/positionUColor.vert similarity index 100% rename from core/renderer/shaders/positionUColor.vert rename to axmol/renderer/shaders/positionUColor.vert diff --git a/core/renderer/shaders/quadColor.frag b/axmol/renderer/shaders/quadColor.frag similarity index 100% rename from core/renderer/shaders/quadColor.frag rename to axmol/renderer/shaders/quadColor.frag diff --git a/core/renderer/shaders/quadColor.vert b/axmol/renderer/shaders/quadColor.vert similarity index 100% rename from core/renderer/shaders/quadColor.vert rename to axmol/renderer/shaders/quadColor.vert diff --git a/core/renderer/shaders/quadTexture.frag b/axmol/renderer/shaders/quadTexture.frag similarity index 100% rename from core/renderer/shaders/quadTexture.frag rename to axmol/renderer/shaders/quadTexture.frag diff --git a/core/renderer/shaders/quadTexture.vert b/axmol/renderer/shaders/quadTexture.vert similarity index 100% rename from core/renderer/shaders/quadTexture.vert rename to axmol/renderer/shaders/quadTexture.vert diff --git a/core/renderer/shaders/skinPositionNormalTexture.vert b/axmol/renderer/shaders/skinPositionNormalTexture.vert similarity index 100% rename from core/renderer/shaders/skinPositionNormalTexture.vert rename to axmol/renderer/shaders/skinPositionNormalTexture.vert diff --git a/core/renderer/shaders/skinPositionTexture.vert b/axmol/renderer/shaders/skinPositionTexture.vert similarity index 100% rename from core/renderer/shaders/skinPositionTexture.vert rename to axmol/renderer/shaders/skinPositionTexture.vert diff --git a/core/renderer/shaders/skybox.frag b/axmol/renderer/shaders/skybox.frag similarity index 100% rename from core/renderer/shaders/skybox.frag rename to axmol/renderer/shaders/skybox.frag diff --git a/core/renderer/shaders/skybox.vert b/axmol/renderer/shaders/skybox.vert similarity index 100% rename from core/renderer/shaders/skybox.vert rename to axmol/renderer/shaders/skybox.vert diff --git a/core/renderer/shaders/terrain.frag b/axmol/renderer/shaders/terrain.frag similarity index 100% rename from core/renderer/shaders/terrain.frag rename to axmol/renderer/shaders/terrain.frag diff --git a/core/renderer/shaders/terrain.vert b/axmol/renderer/shaders/terrain.vert similarity index 100% rename from core/renderer/shaders/terrain.vert rename to axmol/renderer/shaders/terrain.vert diff --git a/axmol/renderer/shaders/trail_2d.vert b/axmol/renderer/shaders/trail_2d.vert new file mode 100644 index 000000000000..a56698626a14 --- /dev/null +++ b/axmol/renderer/shaders/trail_2d.vert @@ -0,0 +1,19 @@ +#version 310 es + +layout(location = POSITION) in vec2 a_position; +layout(location = TEXCOORD0) in vec2 a_texCoord; +layout(location = COLOR0) in vec4 a_color; + +layout(location = COLOR0) out vec4 v_color; +layout(location = TEXCOORD0) out vec2 v_texCoord; + +layout(std140) uniform vs_ub { + mat4 u_MVPMatrix; +}; + +void main() +{ + gl_Position = u_MVPMatrix * vec4(a_position, 1.0, 1.0); + v_color = a_color; + v_texCoord = a_texCoord; +} diff --git a/core/renderer/shaders/positionTexture3D.vert b/axmol/renderer/shaders/unlit.vert similarity index 100% rename from core/renderer/shaders/positionTexture3D.vert rename to axmol/renderer/shaders/unlit.vert diff --git a/core/renderer/shaders/positionTextureInstance.vert b/axmol/renderer/shaders/unlit_instance.vert similarity index 79% rename from core/renderer/shaders/positionTextureInstance.vert rename to axmol/renderer/shaders/unlit_instance.vert index 480942902978..e5415d283ffa 100644 --- a/core/renderer/shaders/positionTextureInstance.vert +++ b/axmol/renderer/shaders/unlit_instance.vert @@ -2,7 +2,7 @@ layout (location = POSITION) in vec4 a_position; layout (location = TEXCOORD0) in vec2 a_texCoord; -#if !defined(METAL) +#if !defined(AXSLC_TARGET_MSL) layout (location = TEXCOORD1) in mat4 a_instance; #endif layout (location = TEXCOORD0) out vec2 v_texCoord; @@ -11,15 +11,15 @@ layout(std140, binding = 0) uniform vs_ub { mat4 u_MVPMatrix; }; -#if defined(METAL) -layout(std140, binding = 1) buffer vs_inst { +#if defined(AXSLC_TARGET_MSL) +layout(std140, binding = 1) readonly buffer vs_inst { mat4 u_instance[]; }; #endif void main(void) { -#if defined(METAL) +#if defined(AXSLC_TARGET_MSL) gl_Position = u_MVPMatrix * u_instance[gl_InstanceIndex] * a_position; #else gl_Position = u_MVPMatrix * a_instance * a_position; diff --git a/core/renderer/shaders/videoTextureBGRA.frag b/axmol/renderer/shaders/videoTextureBGRA.frag similarity index 100% rename from core/renderer/shaders/videoTextureBGRA.frag rename to axmol/renderer/shaders/videoTextureBGRA.frag diff --git a/core/renderer/shaders/videoTextureI420.frag b/axmol/renderer/shaders/videoTextureI420.frag similarity index 100% rename from core/renderer/shaders/videoTextureI420.frag rename to axmol/renderer/shaders/videoTextureI420.frag diff --git a/core/renderer/shaders/videoTextureNV12.frag b/axmol/renderer/shaders/videoTextureNV12.frag similarity index 100% rename from core/renderer/shaders/videoTextureNV12.frag rename to axmol/renderer/shaders/videoTextureNV12.frag diff --git a/core/renderer/shaders/videoTextureYUY2.frag b/axmol/renderer/shaders/videoTextureYUY2.frag similarity index 100% rename from core/renderer/shaders/videoTextureYUY2.frag rename to axmol/renderer/shaders/videoTextureYUY2.frag diff --git a/core/renderer/backend/Buffer.h b/axmol/rhi/Buffer.h similarity index 96% rename from core/renderer/backend/Buffer.h rename to axmol/rhi/Buffer.h index 616e1bc745c6..0bc5ef215234 100644 --- a/core/renderer/backend/Buffer.h +++ b/axmol/rhi/Buffer.h @@ -24,9 +24,8 @@ #pragma once -#include "Macros.h" -#include "Types.h" -#include "base/Object.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" namespace ax { @@ -35,10 +34,10 @@ class MeshVertexData; class MeshIndexData; } // namespace ax -NS_AX_BACKEND_BEGIN +namespace ax::rhi { /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -97,6 +96,6 @@ class Buffer : public ax::Object std::size_t _size = 0; ///< buffer size in bytes. }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/axmol/rhi/CMakeLists.txt b/axmol/rhi/CMakeLists.txt new file mode 100644 index 000000000000..25656aa1058e --- /dev/null +++ b/axmol/rhi/CMakeLists.txt @@ -0,0 +1,123 @@ +set(_AX_RHI_HEADER + rhi/axslc-spec.h + rhi/axmol-rhi.h + rhi/RHITypes.h + rhi/Buffer.h + rhi/CommandBuffer.h + rhi/DepthStencilState.h + rhi/DriverBase.h + rhi/PixelBufferDesc.h + rhi/PixelFormatUtils.h + rhi/Program.h + rhi/ProgramState.h + rhi/RenderPassDesc.h + rhi/RenderPipeline.h + rhi/RenderTarget.h + rhi/ShaderCache.h + rhi/ShaderModule.h + rhi/Texture.h + rhi/VertexLayout.h + rhi/SamplerCache.h +) + +set(_AX_RHI_SRC + rhi/CommandBuffer.cpp + rhi/DepthStencilState.cpp + rhi/DriverBase.cpp + rhi/ShaderModule.cpp + rhi/Texture.cpp + rhi/PixelFormatUtils.cpp + rhi/VertexLayout.cpp + rhi/Program.cpp + rhi/ProgramState.cpp + rhi/ShaderCache.cpp + rhi/RenderPassDesc.cpp + rhi/SamplerCache.cpp +) + +if(AX_RENDER_API STREQUAL "gl") + list(APPEND _AX_RHI_HEADER + rhi/opengl/OpenGLState.h + rhi/opengl/BufferGL.h + rhi/opengl/CommandBufferGL.h + rhi/opengl/DepthStencilStateGL.h + rhi/opengl/DriverGL.h + rhi/opengl/MacrosGL.h + rhi/opengl/ProgramGL.h + rhi/opengl/RenderPipelineGL.h + rhi/opengl/RenderTargetGL.h + rhi/opengl/ShaderModuleGL.h + rhi/opengl/TextureGL.h + rhi/opengl/UtilsGL.h + ) + + list(APPEND _AX_RHI_SRC + rhi/opengl/OpenGLState.cpp + rhi/opengl/BufferGL.cpp + rhi/opengl/CommandBufferGL.cpp + rhi/opengl/DepthStencilStateGL.cpp + rhi/opengl/DriverGL.cpp + rhi/opengl/ProgramGL.cpp + rhi/opengl/RenderPipelineGL.cpp + rhi/opengl/ShaderModuleGL.cpp + rhi/opengl/TextureGL.cpp + rhi/opengl/UtilsGL.cpp + rhi/opengl/RenderTargetGL.cpp + ) +elseif(AX_RENDER_API STREQUAL "mtl") + list(APPEND _AX_RHI_HEADER + rhi/metal/BufferMTL.h + rhi/metal/BufferManager.h + rhi/metal/CommandBufferMTL.h + rhi/metal/RenderTargetMTL.h + rhi/metal/DepthStencilStateMTL.h + rhi/metal/DriverMTL.h + rhi/metal/RenderPipelineMTL.h + rhi/metal/ShaderModuleMTL.h + rhi/metal/TextureMTL.h + rhi/metal/UtilsMTL.h + rhi/metal/ProgramMTL.h + ) + + list(APPEND _AX_RHI_SRC + rhi/metal/BufferMTL.mm + rhi/metal/BufferManager.mm + rhi/metal/CommandBufferMTL.mm + rhi/metal/RenderTargetMTL.mm + rhi/metal/DepthStencilStateMTL.mm + rhi/metal/DriverMTL.mm + rhi/metal/RenderPipelineMTL.mm + rhi/metal/ShaderModuleMTL.mm + rhi/metal/TextureMTL.mm + rhi/metal/UtilsMTL.mm + rhi/metal/ProgramMTL.mm + ) +elseif(AX_RENDER_API STREQUAL "d3d") + list(APPEND _AX_RHI_HEADER + rhi/d3d/BufferD3D.h + rhi/d3d/CommandBufferD3D.h + rhi/d3d/RenderTargetD3D.h + rhi/d3d/DepthStencilStateD3D.h + rhi/d3d/DriverD3D.h + rhi/d3d/RenderPipelineD3D.h + rhi/d3d/ShaderModuleD3D.h + rhi/d3d/TextureD3D.h + rhi/d3d/UtilsD3D.h + rhi/d3d/ProgramD3D.h + rhi/d3d/VertexLayoutD3D.h + ) + + list(APPEND _AX_RHI_SRC + rhi/d3d/BufferD3D.cpp + rhi/d3d/CommandBufferD3D.cpp + rhi/d3d/RenderTargetD3D.cpp + rhi/d3d/DepthStencilStateD3D.cpp + rhi/d3d/DriverD3D.cpp + rhi/d3d/RenderPipelineD3D.cpp + rhi/d3d/ShaderModuleD3D.cpp + rhi/d3d/TextureD3D.cpp + rhi/d3d/UtilsD3D.cpp + rhi/d3d/ProgramD3D.cpp + rhi/d3d/VertexLayoutD3D.cpp + ) +endif() diff --git a/core/renderer/backend/CommandBuffer.cpp b/axmol/rhi/CommandBuffer.cpp similarity index 81% rename from core/renderer/backend/CommandBuffer.cpp rename to axmol/rhi/CommandBuffer.cpp index 6cc429b2b704..20b3a819dc87 100644 --- a/core/renderer/backend/CommandBuffer.cpp +++ b/axmol/rhi/CommandBuffer.cpp @@ -22,19 +22,19 @@ THE SOFTWARE. ****************************************************************************/ -#include "CommandBuffer.h" +#include "axmol/rhi/CommandBuffer.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi +{ void CommandBuffer::setStencilReferenceValue(uint32_t value) { - _stencilReferenceValueBack = _stencilReferenceValueFront = value; + _stencilReferenceValue = value; } -void CommandBuffer::setStencilReferenceValue(unsigned int frontRef, unsigned int backRef) +bool CommandBuffer::resizeSwapChain(uint32_t /*width*/, uint32_t /*height*/) { - _stencilReferenceValueFront = frontRef; - _stencilReferenceValueBack = backRef; + return true; } -NS_AX_BACKEND_END +} // namespace ax::rhi diff --git a/core/renderer/backend/CommandBuffer.h b/axmol/rhi/CommandBuffer.h similarity index 86% rename from core/renderer/backend/CommandBuffer.h rename to axmol/rhi/CommandBuffer.h index 166a4d533176..ed938ff4d50b 100644 --- a/core/renderer/backend/CommandBuffer.h +++ b/axmol/rhi/CommandBuffer.h @@ -26,37 +26,36 @@ #include -#include "base/Object.h" -#include "base/Data.h" +#include "axmol/base/Object.h" +#include "axmol/base/Data.h" -#include "Macros.h" -#include "Types.h" -#include "RenderPassDescriptor.h" -#include "PixelBufferDescriptor.h" -#include "platform/StdC.h" -#include "ProgramState.h" -#include "VertexLayout.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/RenderPassDesc.h" +#include "axmol/rhi/PixelBufferDesc.h" +#include "axmol/platform/StdC.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/VertexLayout.h" #include #include namespace ax { -struct PipelineDescriptor; +struct PipelineDesc; } -NS_AX_BACKEND_BEGIN +namespace ax::rhi { class RenderPass; class RenderPipeline; class Buffer; class DepthStencilState; -class TextureBackend; +class Texture; class RenderTarget; -struct DepthStencilDescriptor; +struct DepthStencilDesc; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -67,6 +66,8 @@ struct DepthStencilDescriptor; class CommandBuffer : public ax::Object { public: + void setScreenRenderTarget(RenderTarget* rt) { _screenRT = rt; } + /** * Set depthStencil status once * @param depthStencilState Specifies the depth and stencil status @@ -90,22 +91,22 @@ class CommandBuffer : public ax::Object * Begin a render pass, initial color, depth and stencil attachment. * @param descriptor Specifies a group of render targets that hold the results of a render pass. */ - virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassDescriptor& descriptor) = 0; + virtual void beginRenderPass(const RenderTarget* renderTarget, const RenderPassDesc& descriptor) = 0; /** * Update depthStencil status, improvment: for metal backend cache it * @param depthStencilState Specifies the depth and stencil status */ - virtual void updateDepthStencilState(const DepthStencilDescriptor& descriptor) = 0; + virtual void updateDepthStencilState(const DepthStencilDesc& descriptor) = 0; /** * Update render pipeline status * Building a programmable pipeline involves an expensive evaluation of GPU state. * So a new render pipeline object will be created only if it hasn't been created before. * @param rt Specifies the render target. - * @param pipelineDescriptor Specifies the pipeline descriptor. + * @param pipelineDesc Specifies the pipeline descriptor. */ - virtual void updatePipelineState(const RenderTarget* rt, const PipelineDescriptor& descriptor) = 0; + virtual void updatePipelineState(const RenderTarget* rt, const PipelineDesc& descriptor) = 0; /** * Fixed-function state @@ -165,6 +166,12 @@ class CommandBuffer : public ax::Object std::size_t count, bool wireframe = false) = 0; + virtual void drawArraysInstanced(PrimitiveType primitiveType, + std::size_t start, + std::size_t count, + int instanceCount, + bool wireframe = false) = 0; + /** * Draw primitives with an index list. * @param primitiveType The type of primitives that elements are assembled into. @@ -219,7 +226,7 @@ class CommandBuffer : public ax::Object * Get a screen snapshot * @param callback A callback to deal with screen snapshot image. */ - virtual void readPixels(RenderTarget* rt, std::function callback) = 0; + virtual void readPixels(RenderTarget* rt, std::function callback) = 0; /** * Update both front and back stencil reference value. @@ -227,20 +234,16 @@ class CommandBuffer : public ax::Object */ void setStencilReferenceValue(unsigned int value); - /** - * Update stencil reference value. - * @param frontRef Specifies front stencil reference value. - * @param backRef Specifies back stencil reference value. - */ - void setStencilReferenceValue(unsigned int frontRef, unsigned int backRef); + virtual bool resizeSwapChain(uint32_t width, uint32_t height); protected: virtual ~CommandBuffer() = default; - unsigned int _stencilReferenceValueFront = 0; ///< front stencil reference value. - unsigned int _stencilReferenceValueBack = 0; ///< back stencil reference value. + const RenderTarget* _screenRT{nullptr}; // weak ref (managed by Renderer) + const RenderTarget* _currentRT{nullptr}; // weak ref (managed by Renderer) + unsigned int _stencilReferenceValue = 0; ///< front stencil reference value }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/DepthStencilState.cpp b/axmol/rhi/DepthStencilState.cpp similarity index 70% rename from core/renderer/backend/DepthStencilState.cpp rename to axmol/rhi/DepthStencilState.cpp index 2f702ca26c56..89cf712c4db8 100644 --- a/core/renderer/backend/DepthStencilState.cpp +++ b/axmol/rhi/DepthStencilState.cpp @@ -22,25 +22,25 @@ THE SOFTWARE. ****************************************************************************/ -#include "DepthStencilState.h" -#include "RenderTarget.h" +#include "axmol/rhi/DepthStencilState.h" +#include "axmol/rhi/RenderTarget.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { -bool StencilDescriptor::operator==(const StencilDescriptor& rhs) const +bool StencilDesc::operator==(const StencilDesc& rhs) const { return ( - stencilFailureOperation == rhs.stencilFailureOperation && depthFailureOperation == rhs.depthFailureOperation && - depthStencilPassOperation == rhs.depthStencilPassOperation && - stencilCompareFunction == rhs.stencilCompareFunction && readMask == rhs.readMask && writeMask == rhs.writeMask); + stencilFailureOp == rhs.stencilFailureOp && depthFailureOp == rhs.depthFailureOp && + depthStencilPassOp == rhs.depthStencilPassOp && + stencilCompareFunc == rhs.stencilCompareFunc && readMask == rhs.readMask && writeMask == rhs.writeMask); } DepthStencilState::~DepthStencilState() {} -void DepthStencilState::update(const DepthStencilDescriptor& dsDesc) +void DepthStencilState::update(const DepthStencilDesc& dsDesc) { - _depthStencilInfo = dsDesc; + _dsDesc = dsDesc; _isBackFrontStencilEqual = dsDesc.backFaceStencil == dsDesc.frontFaceStencil; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/DepthStencilState.h b/axmol/rhi/DepthStencilState.h similarity index 63% rename from core/renderer/backend/DepthStencilState.h rename to axmol/rhi/DepthStencilState.h index bc8be7cbff28..b4b9c01de40f 100644 --- a/core/renderer/backend/DepthStencilState.h +++ b/axmol/rhi/DepthStencilState.h @@ -24,42 +24,41 @@ #pragma once -#include "Macros.h" -#include "Types.h" +#include "axmol/rhi/RHITypes.h" -#include "base/Object.h" +#include "axmol/base/Object.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { class RenderTarget; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ /** * Stencil descriptor. */ -struct StencilDescriptor +struct StencilDesc { - bool operator==(const StencilDescriptor& rhs) const; - - StencilOperation stencilFailureOperation = StencilOperation::KEEP; - StencilOperation depthFailureOperation = StencilOperation::KEEP; - StencilOperation depthStencilPassOperation = StencilOperation::KEEP; - CompareFunction stencilCompareFunction = CompareFunction::ALWAYS; - unsigned int readMask = 0; - unsigned int writeMask = 0; + bool operator==(const StencilDesc& rhs) const; + + StencilOp stencilFailureOp = StencilOp::KEEP; + StencilOp depthFailureOp = StencilOp::KEEP; + StencilOp depthStencilPassOp = StencilOp::KEEP; + CompareFunc stencilCompareFunc = CompareFunc::ALWAYS; + unsigned int readMask = 0; + unsigned int writeMask = 0; }; /** * Depth and stencil descriptor. */ -struct DepthStencilDescriptor +struct DepthStencilDesc { - CompareFunction depthCompareFunction = CompareFunction::LESS; - StencilDescriptor backFaceStencil; - StencilDescriptor frontFaceStencil; + CompareFunc depthCompareFunc = CompareFunc::LESS; + StencilDesc backFaceStencil; + StencilDesc frontFaceStencil; void addFlag(DepthStencilFlags flag) { this->flags |= flag; } void removeFlag(DepthStencilFlags flag) { this->flags &= ~flag; } DepthStencilFlags flags = DepthStencilFlags::ALL; @@ -71,9 +70,9 @@ struct DepthStencilDescriptor class DepthStencilState : public ax::Object { public: - virtual void update(const DepthStencilDescriptor& desc); - const DepthStencilDescriptor& getDepthStencilInfo() const { return _depthStencilInfo; } - bool isEnabled() const { return bitmask::any(_depthStencilInfo.flags, DepthStencilFlags::DEPTH_STENCIL_TEST); } + virtual void update(const DepthStencilDesc& desc); + const DepthStencilDesc& getDepthStencilDesc() const { return _dsDesc; } + bool isEnabled() const { return bitmask::any(_dsDesc.flags, DepthStencilFlags::DEPTH_STENCIL_TEST); } protected: /** @@ -82,10 +81,10 @@ class DepthStencilState : public ax::Object DepthStencilState() = default; virtual ~DepthStencilState(); - DepthStencilDescriptor _depthStencilInfo{}; ///< depth and stencil descriptor. + DepthStencilDesc _dsDesc{}; ///< depth and stencil descriptor. bool _isBackFrontStencilEqual = false; ///< Does front stencil status equals to back stencil's. }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/DriverBase.cpp b/axmol/rhi/DriverBase.cpp similarity index 87% rename from core/renderer/backend/DriverBase.cpp rename to axmol/rhi/DriverBase.cpp index 5c6f4aa92f9b..8f6397e096cd 100644 --- a/core/renderer/backend/DriverBase.cpp +++ b/axmol/rhi/DriverBase.cpp @@ -23,10 +23,18 @@ THE SOFTWARE. ****************************************************************************/ -#include "DriverBase.h" +#include "axmol/rhi/DriverBase.h" -NS_AX_BACKEND_BEGIN +#include "axmol/rhi/VertexLayout.h" + +namespace ax::rhi +{ DriverBase* DriverBase::_instance = nullptr; -NS_AX_BACKEND_END +VertexLayout* DriverBase::createVertexLayout() +{ + return new VertexLayout(); +} + +} // namespace ax::rhi diff --git a/core/renderer/backend/DriverBase.h b/axmol/rhi/DriverBase.h similarity index 77% rename from core/renderer/backend/DriverBase.h rename to axmol/rhi/DriverBase.h index 89fe8e410bc9..231333abcf9f 100644 --- a/core/renderer/backend/DriverBase.h +++ b/axmol/rhi/DriverBase.h @@ -25,18 +25,17 @@ #pragma once -#include "Macros.h" -#include "Types.h" -#include "RenderPassDescriptor.h" -#include "Texture.h" -#include "DepthStencilState.h" -#include "ShaderCache.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/RenderPassDesc.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/DepthStencilState.h" +#include "axmol/rhi/ShaderCache.h" -#include "base/Object.h" +#include "axmol/base/Object.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { class CommandBuffer; class Buffer; @@ -45,8 +44,10 @@ class RenderPipeline; class RenderPass; class RenderTarget; -class ProgramManager; class Program; +class VertexLayout; + +class SamplerCache; enum class FeatureType : uint32_t { @@ -65,7 +66,7 @@ enum class FeatureType : uint32_t }; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -75,8 +76,8 @@ enum class FeatureType : uint32_t class AX_DLL DriverBase { public: - friend class ProgramManager; friend class ShaderCache; + friend class SamplerCache; /** * Returns a shared instance of the DriverBase. @@ -88,9 +89,10 @@ class AX_DLL DriverBase /** * New a CommandBuffer object, not auto released. + * @param windowHandle, current is win32 HWND * @return A CommandBuffer object. */ - virtual CommandBuffer* newCommandBuffer() = 0; + virtual CommandBuffer* createCommandBuffer(void* windowHandle) = 0; /** * New a Buffer object, not auto released. @@ -101,29 +103,28 @@ class AX_DLL DriverBase * BufferUsage::STATIC, BufferUsage::DYNAMIC. * @return A Buffer object. */ - virtual Buffer* newBuffer(size_t size, BufferType type, BufferUsage usage) = 0; + virtual Buffer* createBuffer(size_t size, BufferType type, BufferUsage usage) = 0; /** - * New a TextureBackend object, not auto released. + * New a Texture object, not auto released. * @param descriptor Specifies texture description. - * @return A TextureBackend object. + * @return A Texture object. */ - virtual TextureBackend* newTexture(const TextureDescriptor& descriptor) = 0; + virtual Texture* createTexture(const TextureDesc& descriptor) = 0; - virtual RenderTarget* newDefaultRenderTarget() = 0; + virtual RenderTarget* createDefaultRenderTarget() = 0; - virtual RenderTarget* newRenderTarget(TextureBackend* colorAttachment = nullptr, - TextureBackend* depthAttachment = nullptr, - TextureBackend* stencilAttachhment = nullptr) = 0; + virtual RenderTarget* createRenderTarget(Texture* colorAttachment = nullptr, + Texture* depthStencilAttachment = nullptr) = 0; - virtual DepthStencilState* newDepthStencilState() = 0; + virtual DepthStencilState* createDepthStencilState() = 0; /** * New a RenderPipeline object, not auto released. * @param descriptor Specifies render pipeline description. * @return A RenderPipeline object. */ - virtual RenderPipeline* newRenderPipeline() = 0; + virtual RenderPipeline* createRenderPipeline() = 0; /** * This property controls whether or not the drawables' @@ -143,7 +144,9 @@ class AX_DLL DriverBase * @param fragmentShader Specifes this is a fragment shader source. * @return A Program instance. */ - virtual Program* newProgram(std::string_view vertexShader, std::string_view fragmentShader) = 0; + virtual Program* createProgram(std::string_view vsSource, std::string_view fsSource) = 0; + + virtual VertexLayout* createVertexLayout(); virtual void resetState() {}; @@ -152,21 +155,21 @@ class AX_DLL DriverBase * Get vendor device name. * @return Vendor device name. */ - virtual const char* getVendor() const = 0; + virtual std::string getVendor() const = 0; /** * Get the full name of the vendor device. * @return The full name of the vendor device. */ - virtual const char* getRenderer() const = 0; + virtual std::string getRenderer() const = 0; /** * Get version name. * @return Version name. */ - virtual const char* getVersion() const = 0; + virtual std::string getVersion() const = 0; - virtual const char* getShaderVersion() const { return ""; } + virtual std::string getShaderVersion() const { return {}; } /** * Check does device has extension. @@ -216,8 +219,12 @@ class AX_DLL DriverBase * @param source Specifies shader source. * @return A ShaderModule object. */ - virtual ShaderModule* newShaderModule(ShaderStage stage, std::string_view source) = 0; + virtual ShaderModule* createShaderModule(ShaderStage stage, std::string_view source) = 0; + + virtual SamplerHandle createSampler(const SamplerDesc& desc) = 0; + virtual void destroySampler(SamplerHandle&) = 0; + // TODO: driverCaps int _maxAttributes = 0; ///< Maximum attribute count. int _maxTextureSize = 0; ///< Maximum texture size. int _maxTextureUnits = 0; ///< Maximum texture unit. @@ -227,6 +234,6 @@ class AX_DLL DriverBase static DriverBase* _instance; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/axmol/rhi/PixelBufferDesc.h b/axmol/rhi/PixelBufferDesc.h new file mode 100644 index 000000000000..b40221104dec --- /dev/null +++ b/axmol/rhi/PixelBufferDesc.h @@ -0,0 +1,23 @@ +#pragma once +#include "axmol/base/Data.h" + +#include "axmol/rhi/RHITypes.h" + +namespace ax::rhi { + +struct PixelBufferDesc +{ + PixelBufferDesc() = default; + PixelBufferDesc(const PixelBufferDesc&) = default; + PixelBufferDesc(PixelBufferDesc&& rhs) noexcept + : _data(std::move(rhs._data)), _width(rhs._width), _height(rhs._height) + {} + + explicit operator bool() const { return !_data.isNull(); } + + Data _data; + int _width = 0; + int _height = 0; +}; + +} diff --git a/core/renderer/backend/PixelFormatUtils.cpp b/axmol/rhi/PixelFormatUtils.cpp similarity index 91% rename from core/renderer/backend/PixelFormatUtils.cpp rename to axmol/rhi/PixelFormatUtils.cpp index 2113197b64f5..9d17e9fde611 100644 --- a/core/renderer/backend/PixelFormatUtils.cpp +++ b/axmol/rhi/PixelFormatUtils.cpp @@ -23,18 +23,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "PixelFormatUtils.h" -#include "Macros.h" +#include "axmol/rhi/PixelFormatUtils.h" -namespace ax +namespace ax::rhi { -namespace backend -{ namespace PixelFormatUtils { -static const PixelFormatDescriptor s_pixelFormatDescriptors[] = { +static const PixelFormatDesc s_pixelFormatDescriptors[] = { // +--------------------------------------------- bpp // | +----------------------------------------- block width // | | +-------------------------------------- block height @@ -74,7 +71,7 @@ static const PixelFormatDescriptor s_pixelFormatDescriptors[] = { //{8, 1, 1, 1, 1, 1, true, "A8"}, // A8 //{8, 1, 1, 1, 1, 1, false, "L8"}, // L8 //{16, 1, 1, 2, 1, 1, true, "LA8"}, // LA8 - {128, 1, 1, 4, 1, 1, true, "RGBA32F"}, // RGBA32F + {128, 1, 1, 4, 1, 1, true, "RGBA32F"}, // RGBA32F #if (AX_TARGET_PLATFORM != AX_PLATFORM_IOS) {32, 1, 1, 4, 1, 1, false, "D24S8"}, // D24S8 #else @@ -87,13 +84,13 @@ static_assert(AX_ARRAYSIZE(s_pixelFormatDescriptors) == (int)PixelFormat::COUNT, ////////////////////////////////////////////////////////////////////////// // pixel format helper functions -const PixelFormatDescriptor& getFormatDescriptor(PixelFormat format) +const PixelFormatDesc& getFormatDesc(PixelFormat format) { if (AX_LIKELY(format < PixelFormat::COUNT)) return s_pixelFormatDescriptors[(uint32_t)format]; - static const PixelFormatDescriptor s_invalidDescriptor = {}; - return s_invalidDescriptor; + static const PixelFormatDesc s_invalidDesc = {}; + return s_invalidDesc; } uint32_t computeRowPitch(PixelFormat format, uint32_t width) @@ -133,9 +130,9 @@ static void convertRG8ToRGB8(const unsigned char* data, size_t dataLen, unsigned { for (ssize_t i = 0, l = dataLen - 1; i < l; i += 2) { - *outData++ = data[i]; // R + *outData++ = data[i]; // R *outData++ = data[i + 1]; // G - *outData++ = data[i]; // B + *outData++ = data[i]; // B } } @@ -145,7 +142,7 @@ static void convertRG8ToRGBA8(const unsigned char* data, size_t dataLen, unsigne for (ssize_t i = 0, l = dataLen - 1; i < l; i += 2) { *outData++ = data[i]; // R - *outData++ = data[i + 1]; // G + *outData++ = data[i + 1]; // G *outData++ = data[i]; // B *outData++ = data[i + 1]; // A } @@ -169,9 +166,9 @@ static void convertRG8ToRGB565(const unsigned char* data, size_t dataLen, unsign unsigned short* out16 = (unsigned short*)outData; for (ssize_t i = 0, l = dataLen - 1; i < l; i += 2) { - *out16++ = (data[i] & 0x00F8) << 8 // R - | (data[i + 1] & 0x00FC) << 3 // G - | (data[i] & 0x00F8) >> 3; // B + *out16++ = (data[i] & 0x00F8) << 8 // R + | (data[i + 1] & 0x00FC) << 3 // G + | (data[i] & 0x00F8) >> 3; // B } } @@ -455,11 +452,11 @@ static void convertBGRA8ToRGBA8(const unsigned char* data, size_t dataLen, unsig // converter function end ////////////////////////////////////////////////////////////////////////// -static ax::backend::PixelFormat convertR8ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertR8ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -515,11 +512,11 @@ static ax::backend::PixelFormat convertR8ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRG8ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRG8ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -571,11 +568,11 @@ static ax::backend::PixelFormat convertRG8ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRGB8ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRGB8ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -626,11 +623,11 @@ static ax::backend::PixelFormat convertRGB8ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRGBA8ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRGBA8ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) @@ -683,11 +680,11 @@ static ax::backend::PixelFormat convertRGBA8ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRGB5A1ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRGB5A1ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -717,11 +714,11 @@ static ax::backend::PixelFormat convertRGB5A1ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRGB565ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRGB565ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -751,11 +748,11 @@ static ax::backend::PixelFormat convertRGB565ToFormat(const unsigned char* data, return format; } -static ax::backend::PixelFormat convertRGBA4ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +static ax::rhi::PixelFormat convertRGBA4ToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -786,10 +783,10 @@ static ax::backend::PixelFormat convertRGBA4ToFormat(const unsigned char* data, } static PixelFormat convertBGRA8ToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) + size_t dataLen, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { switch (format) { @@ -821,12 +818,12 @@ static PixelFormat convertBGRA8ToFormat(const unsigned char* data, rgba(1) -> 12345678 */ -ax::backend::PixelFormat convertDataToFormat(const unsigned char* data, - size_t dataLen, - PixelFormat originFormat, - PixelFormat format, - unsigned char** outData, - size_t* outDataLen) +ax::rhi::PixelFormat convertDataToFormat(const unsigned char* data, + size_t dataLen, + PixelFormat originFormat, + PixelFormat format, + unsigned char** outData, + size_t* outDataLen) { // don't need to convert if (format == originFormat) @@ -856,13 +853,12 @@ ax::backend::PixelFormat convertDataToFormat(const unsigned char* data, return convertBGRA8ToFormat(data, dataLen, format, outData, outDataLen); default: AXLOGW("unsupported conversion from format {} to format {}", static_cast(originFormat), - static_cast(format)); + static_cast(format)); *outData = (unsigned char*)data; *outDataLen = dataLen; return originFormat; } } } // namespace PixelFormatUtils -} // namespace backend -} +} // namespace ax::rhi diff --git a/core/renderer/backend/PixelFormatUtils.h b/axmol/rhi/PixelFormatUtils.h similarity index 89% rename from core/renderer/backend/PixelFormatUtils.h rename to axmol/rhi/PixelFormatUtils.h index c23d8c3cff6c..a8b68ba67c80 100644 --- a/core/renderer/backend/PixelFormatUtils.h +++ b/axmol/rhi/PixelFormatUtils.h @@ -25,19 +25,14 @@ #pragma once -#include "PlatformMacros.h" -#include "renderer/Texture2D.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/renderer/Texture2D.h" -namespace ax -{ - -namespace backend +namespace ax::rhi { namespace PixelFormatUtils { -typedef ax::backend::PixelFormat PixelFormat; - -struct PixelFormatDescriptor +struct PixelFormatDesc { uint8_t bpp; // bitsPerPixel: !!!regard bpp=0 as invalid pixel format uint8_t blockWidth; @@ -49,11 +44,11 @@ struct PixelFormatDescriptor const char* name; }; -const PixelFormatDescriptor& getFormatDescriptor(PixelFormat format); +const PixelFormatDesc& getFormatDesc(PixelFormat format); uint32_t computeRowPitch(PixelFormat format, uint32_t width); inline uint8_t getBitsPerPixel(PixelFormat format) { - return getFormatDescriptor(format).bpp; + return getFormatDesc(format).bpp; } inline bool isCompressed(PixelFormat format) { @@ -74,5 +69,4 @@ PixelFormat convertDataToFormat(const unsigned char* data, unsigned char** outData, size_t* outDataLen); }; // namespace PixelFormatUtils -} // namespace backend -} +} // namespace ax::rhi diff --git a/axmol/rhi/Program.cpp b/axmol/rhi/Program.cpp new file mode 100644 index 000000000000..afe48fea6025 --- /dev/null +++ b/axmol/rhi/Program.cpp @@ -0,0 +1,229 @@ +/**************************************************************************** + Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "axmol/rhi/Program.h" +#include "axmol/rhi/VertexLayout.h" + +namespace ax::rhi +{ + +/* + * shader vertex layout define functions + */ +struct VertexLayoutHelper +{ + static void defineDummy(Program*) {} + static void defineTexture(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT2, 0, false); + /// a_texCoord + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, 2 * sizeof(float), false); + + vertexLayout->setStride(4 * sizeof(float)); + } + + static void definePosUvColor(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + /// a_texCoord + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, texCoord), false); + + /// a_color + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false); + vertexLayout->setStride(sizeof(V3F_T2F_C4F)); + } + + static void defineSprite(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + /// a_texCoord + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4B, texCoord), false); + + /// a_color + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::UBYTE4, offsetof(V3F_T2F_C4B, color), true); + vertexLayout->setStride(sizeof(V3F_T2F_C4B)); + } + + static void defineSprite2D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + /// a_position + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT2, 0, false); + /// a_texCoord + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, offsetof(V2F_T2F_C4B, texCoord), false); + + /// a_color + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::UBYTE4, offsetof(V2F_T2F_C4B, color), true); + vertexLayout->setStride(sizeof(V2F_T2F_C4B)); + } + + static void defineDrawNode(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT2, 0, false); + + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, offsetof(V2F_T2F_C4F, texCoord), false); + + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, offsetof(V2F_T2F_C4F, color), true); + + vertexLayout->setStride(sizeof(V2F_T2F_C4F)); + } + + static void defineDrawNode3D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, offsetof(V3F_C4F, color), true); + + vertexLayout->setStride(sizeof(V3F_C4F)); + } + + static void defineSkyBox(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + auto attrNameLoc = program->getVertexInputDesc(rhi::VERTEX_INPUT_NAME_POSITION); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, attrNameLoc, rhi::VertexFormat::FLOAT3, 0, false); + vertexLayout->setStride(sizeof(Vec3)); + } + + static void definePos(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + vertexLayout->setStride(sizeof(Vec3)); + } + + static void definePosColor(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_COLOR, + program->getVertexInputDesc(rhi::VertexInputKind::COLOR), + rhi::VertexFormat::FLOAT4, offsetof(V3F_C4F, color), false); + vertexLayout->setStride(sizeof(V3F_C4F)); + } + + static void defineTerrain3D(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_POSITION, + program->getVertexInputDesc(rhi::VertexInputKind::POSITION), + rhi::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_TEXCOORD, + program->getVertexInputDesc(rhi::VertexInputKind::TEXCOORD), + rhi::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_NORMAL, + program->getVertexInputDesc(rhi::VertexInputKind::NORMAL), + rhi::VertexFormat::FLOAT3, offsetof(V3F_T2F_N3F, normal), false); + vertexLayout->setStride(sizeof(V3F_T2F_N3F)); + } + + static void defineInstanced(Program* program) + { + auto vertexLayout = program->getVertexLayout(); + vertexLayout->setAttrib(rhi::VERTEX_INPUT_NAME_INSTANCE, + program->getVertexInputDesc(rhi::VertexInputKind::INSTANCE), + rhi::VertexFormat::MAT4, 0, false, 1); + vertexLayout->setInstanceStride(sizeof(Mat4)); + } +}; +std::function Program::s_vertexLayoutDefineList[static_cast(VertexLayoutType::Count)] = { + VertexLayoutHelper::defineDummy, VertexLayoutHelper::definePos, VertexLayoutHelper::defineTexture, + VertexLayoutHelper::definePosUvColor, VertexLayoutHelper::defineSprite, VertexLayoutHelper::defineSprite2D, + VertexLayoutHelper::defineDrawNode, VertexLayoutHelper::defineDrawNode3D, VertexLayoutHelper::defineSkyBox, + VertexLayoutHelper::definePosColor, VertexLayoutHelper::defineTerrain3D, VertexLayoutHelper::defineInstanced}; + +Program::Program(std::string_view vs, std::string_view fs) : _vsSource(vs), _fsSource(fs) +{ + auto driver = DriverBase::getInstance(); + _vertexLayout = driver->createVertexLayout(); +} + +Program::~Program() +{ + delete _vertexLayout; +} + +void Program::defineVertexLayout(VertexLayoutType vlt) +{ + if (vlt < VertexLayoutType::Count) + s_vertexLayoutDefineList[static_cast(vlt)](this); +} + +void Program::setProgramIds(uint32_t progType, uint64_t progId) +{ + _programType = progType; + _programId = progId; +} +} // namespace ax::rhi diff --git a/core/renderer/backend/Program.h b/axmol/rhi/Program.h similarity index 77% rename from core/renderer/backend/Program.h rename to axmol/rhi/Program.h index 8a75abcbe833..ffeae1255cb8 100644 --- a/core/renderer/backend/Program.h +++ b/axmol/rhi/Program.h @@ -1,5 +1,6 @@ /**************************************************************************** Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -24,25 +25,27 @@ #pragma once -#include "Macros.h" -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "Types.h" -#include "ShaderCache.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/rhi/ShaderCache.h" #include #include #include #include -NS_AX_BACKEND_BEGIN +namespace ax +{ +class ProgramManager; + +namespace rhi { class ShaderModule; class VertexLayout; -class ProgramManager; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -51,18 +54,20 @@ enum class VertexLayoutType Unspec, // needs binding after program load Pos, // V2F Texture, // T2F - Sprite, // V3F_C4B_T2F posTexColor - DrawNode, // V2F_C4B_T2F - DrawNode3D, // V3F_C4B + PosUvColor, // V3F_T2F_C4F + Sprite, // V3F_T2F_C4B + Sprite2D, // V2F_T2F_C4B + DrawNode, // V2F_T2F_C4F + DrawNode3D, // V3F_C4F SkyBox, // V3F - PU3D, // V3F_C4B_T2F // same with sprite, TODO: reuse spriete - posColor, // V3F_C4B + posColor, // V3F_C4F Terrain3D, // V3F_T2F_V3F + Instanced, // builtin instanced vertex format for 3D transform Count }; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -71,13 +76,9 @@ enum class VertexLayoutType */ class AX_DLL Program : public Object { + friend class ::ax::ProgramManager; public: ~Program(); - /** - * Get engine built-in program. - * @param type Specifies the built-in program type. - */ - static Program* getBuiltinProgram(uint32_t type); /** * Get uniform location by name. @@ -91,21 +92,21 @@ class AX_DLL Program : public Object * @param name Specifies the engine built-in uniform enum name. * @return The uniform location. */ - virtual UniformLocation getUniformLocation(backend::Uniform name) const = 0; + virtual UniformLocation getUniformLocation(rhi::Uniform name) const = 0; /** * Get attribute location by attribute name. * @param name Specifies the attribute name. * @return The attribute location. */ - virtual int getAttributeLocation(std::string_view name) const = 0; + virtual const VertexInputDesc* getVertexInputDesc(std::string_view name) const = 0; /** * Get attribute location by engine built-in attribute enum name. * @param name Specifies the engine built-in attribute enum name. * @return The attribute location. */ - virtual int getAttributeLocation(backend::Attribute name) const = 0; + virtual const VertexInputDesc* getVertexInputDesc(rhi::VertexInputKind name) const = 0; /** * Get maximum vertex location. @@ -123,24 +124,24 @@ class AX_DLL Program : public Object * Get active vertex attributes. * @return Active vertex attributes. key is active attribute name, Value is corresponding attribute info. */ - virtual const hlookup::string_map& getActiveAttributes() const = 0; + virtual const hlookup::string_map& getActiveVertexInputs() const = 0; /** * Get vertex shader. * @return Vertex shader. */ - std::string_view getVertexShader() const { return _vertexShader; } + std::string_view getVertexShaderSource() const { return _vsSource; } /** * Get fragment shader. * @ Fragment shader. */ - std::string_view getFragmentShader() const { return _fragmentShader; } + std::string_view getFragmentShaderSource() const { return _fsSource; } /** - * Sets the program shared vertex layout type, see: VertexLayoutType + * Define the program shared vertex layout type, see: VertexLayoutType */ - void setupVertexLayout(VertexLayoutType vlt); + void defineVertexLayout(VertexLayoutType vlt); /** * Get engine built-in program type. @@ -165,7 +166,7 @@ class AX_DLL Program : public Object * Get all uniformInfos. * @return The uniformInfos. */ - virtual const hlookup::string_map& getAllActiveUniformInfo(ShaderStage stage) const = 0; + virtual const hlookup::string_map& getActiveUniformInfos(ShaderStage stage) const = 0; inline VertexLayout* getVertexLayout() const { return _vertexLayout; } @@ -207,19 +208,19 @@ class AX_DLL Program : public Object virtual const std::unordered_map getAllUniformsLocation() const = 0; friend class ProgramState; #endif - friend class ProgramManager; - std::string _vertexShader; ///< Vertex shader. - std::string _fragmentShader; ///< Fragment shader. - VertexLayout* _vertexLayout = nullptr; + std::string _vsSource; ///< Vertex shader. + std::string _fsSource; ///< Fragment shader. + VertexLayout* _vertexLayout{nullptr}; uint32_t _programType = ProgramType::CUSTOM_PROGRAM; ///< built-in program type, initial value is CUSTOM_PROGRAM. uint64_t _programId = 0; using VERTEX_LAYOUT_SETUP_FUNC = std::function; - static std::function s_vertexLayoutSetupList[static_cast(VertexLayoutType::Count)]; + static std::function s_vertexLayoutDefineList[static_cast(VertexLayoutType::Count)]; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} +} diff --git a/core/renderer/backend/ProgramState.cpp b/axmol/rhi/ProgramState.cpp similarity index 78% rename from core/renderer/backend/ProgramState.cpp rename to axmol/rhi/ProgramState.cpp index 0d740547bbac..b8d1aaccf0a7 100644 --- a/core/renderer/backend/ProgramState.cpp +++ b/axmol/rhi/ProgramState.cpp @@ -23,30 +23,27 @@ THE SOFTWARE. ****************************************************************************/ -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Program.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/Types.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "base/Director.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/Texture.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Director.h" #include #include "xxhash/xxhash.h" -#include "axslcc/sgs-spec.h" - -NS_AX_BACKEND_BEGIN +namespace ax::rhi { // static field std::vector ProgramState::_customAutoBindingResolvers; -TextureInfo::TextureInfo(std::vector&& _slots, std::vector&& _textures) +TextureInfo::TextureInfo(std::vector&& _slots, std::vector&& _textures) : TextureInfo(std::move(_slots), std::vector(_slots.size(), 0), std::move(_textures)) {} TextureInfo::TextureInfo(std::vector&& _slots, std::vector&& _indexs, - std::vector&& _textures) + std::vector&& _textures) : slots(std::move(_slots)), indexs(std::move(_indexs)), textures(std::move(_textures)) { retainTextures(); @@ -127,7 +124,7 @@ void TextureInfo::assign(TextureInfo&& other) } } -void TextureInfo::assign(int slot, int index, backend::TextureBackend* texture) +void TextureInfo::assign(int slot, int index, rhi::Texture* texture) { if (textures.size() != 1 or textures[0] != texture or slots[0] != slot or indexs[0] != index) { @@ -157,11 +154,11 @@ bool ProgramState::init(Program* program) AX_SAFE_RETAIN(program); _program = program; - _vertexLayout = program->getVertexLayout(); - _ownVertexLayout = false; - _vertexUniformBufferSize = _program->getUniformBufferSize(ShaderStage::VERTEX); + _vertexLayout = program->getVertexLayout(); + _ownVertexLayout = false; + _vertexUniformBufferSize = _program->getUniformBufferSize(ShaderStage::VERTEX); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D _fragmentUniformBufferSize = _program->getUniformBufferSize(ShaderStage::FRAGMENT); #endif @@ -230,33 +227,33 @@ ProgramState* ProgramState::clone() const cp->_uniformBuffers = _uniformBuffers; cp->_ownVertexLayout = _ownVertexLayout; - cp->_vertexLayout = !_ownVertexLayout ? _vertexLayout : new VertexLayout(*_vertexLayout); + cp->_vertexLayout = !_ownVertexLayout ? _vertexLayout : _vertexLayout->clone(); // OPTIMIZE ME: make VertexLayout inherit from ax::Object, and just retain cp->_batchId = this->_batchId; cp->_isBatchable = this->_isBatchable; return cp; } -backend::UniformLocation ProgramState::getUniformLocation(backend::Uniform name) const +rhi::UniformLocation ProgramState::getUniformLocation(rhi::Uniform name) const { return _program->getUniformLocation(name); } -backend::UniformLocation ProgramState::getUniformLocation(std::string_view uniform) const +rhi::UniformLocation ProgramState::getUniformLocation(std::string_view uniform) const { return _program->getUniformLocation(uniform); } -void ProgramState::setCallbackUniform(const backend::UniformLocation& uniformLocation, const UniformCallback& callback) +void ProgramState::setCallbackUniform(const rhi::UniformLocation& uniformLocation, const UniformCallback& callback) { _callbackUniforms[uniformLocation] = callback; } -void ProgramState::setUniform(const backend::UniformLocation& uniformLocation, const void* data, std::size_t size) +void ProgramState::setUniform(const rhi::UniformLocation& uniformLocation, const void* data, std::size_t size) { if (uniformLocation.vertStage) setVertexUniform(uniformLocation.vertStage.location, data, size, uniformLocation.vertStage.offset); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D if (uniformLocation.fragStage) setFragmentUniform(uniformLocation.fragStage.location, data, size, uniformLocation.fragStage.offset); #endif @@ -267,16 +264,11 @@ void ProgramState::setVertexUniform(int location, const void* data, std::size_t if (location < 0 || offset < 0) return; -#if AX_GLES_PROFILE != 200 assert(location + offset + size <= _vertexUniformBufferSize); memcpy(_uniformBuffers.data() + location + offset, data, size); -#else - assert(offset + size <= _vertexUniformBufferSize); - memcpy(_uniformBuffers.data() + offset, data, size); -#endif } -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D void ProgramState::setFragmentUniform(int location, const void* data, std::size_t size, int offset) { if (location < 0 || offset < 0) @@ -286,46 +278,35 @@ void ProgramState::setFragmentUniform(int location, const void* data, std::size_ } #endif -#ifndef AX_CORE_PROFILE -void ProgramState::setVertexAttrib(std::string_view name, - std::size_t index, - VertexFormat format, - std::size_t offset, - bool needToBeNormallized) -{ - ensureVertexLayoutMutable(); - - _vertexLayout->setAttrib(name, index, format, offset, needToBeNormallized); -} - -void ProgramState::setVertexStride(uint32_t stride) -{ - ensureVertexLayoutMutable(); - _vertexLayout->setStride(stride); -} -#endif void ProgramState::validateSharedVertexLayout(VertexLayoutType vlt) { if (!_ownVertexLayout && !_vertexLayout->isValid()) - _program->setupVertexLayout(vlt); + _program->defineVertexLayout(vlt); } void ProgramState::ensureVertexLayoutMutable() { if (!_ownVertexLayout) { - _vertexLayout = new VertexLayout(); + if(_vertexLayout) + _vertexLayout = _vertexLayout->clone(); + else + _vertexLayout = DriverBase::getInstance()->createVertexLayout(); _ownVertexLayout = true; } } VertexLayout* ProgramState::getMutableVertexLayout() { + auto driver = DriverBase::getInstance(); + if (_ownVertexLayout || !_vertexLayout->isValid()) return _vertexLayout; + assert(_vertexLayout); + _vertexLayout = _vertexLayout->clone(); _ownVertexLayout = true; - return _vertexLayout = new VertexLayout(); + return _vertexLayout; } void ProgramState::setSharedVertexLayout(VertexLayout* vertexLayout) @@ -336,51 +317,52 @@ void ProgramState::setSharedVertexLayout(VertexLayout* vertexLayout) _vertexLayout = vertexLayout; } -void ProgramState::setTexture(backend::TextureBackend* texture) +void ProgramState::setTexture(rhi::Texture* texture) { for (int slot = 0; slot < texture->getCount() && slot < AX_META_TEXTURES; ++slot) { - auto location = getUniformLocation((backend::Uniform)(backend::Uniform::TEXTURE + slot)); + auto location = getUniformLocation((rhi::Uniform)(rhi::Uniform::TEXTURE + slot)); setTexture(location, slot, slot, texture); } } -void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, +void ProgramState::setTexture(const rhi::UniformLocation& uniformLocation, int slot, - backend::TextureBackend* texture) + rhi::Texture* texture) { setTexture(uniformLocation, slot, 0, texture); } -void ProgramState::setTexture(const backend::UniformLocation& uniformLocation, +void ProgramState::setTexture(const rhi::UniformLocation& uniformLocation, int slot, int index, - backend::TextureBackend* texture) + rhi::Texture* texture) { if (uniformLocation.vertStage) setTexture(uniformLocation.vertStage.location, slot, index, texture, _vertexTextureInfos); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D if (uniformLocation.fragStage) setTexture(uniformLocation.fragStage.location, slot, index, texture, _fragmentTextureInfos); #endif } -void ProgramState::setTextureArray(const backend::UniformLocation& uniformLocation, +void ProgramState::setTextureArray(const rhi::UniformLocation& uniformLocation, std::vector slots, - std::vector textures) + std::vector textures) { if (uniformLocation.vertStage) setTextureArray(uniformLocation.vertStage.location, std::move(slots), std::move(textures), _vertexTextureInfos); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D if (uniformLocation.fragStage) - setTextureArray(uniformLocation.fragStage.location, std::move(slots), std::move(textures), _fragmentTextureInfos); + setTextureArray(uniformLocation.fragStage.location, std::move(slots), std::move(textures), + _fragmentTextureInfos); #endif } void ProgramState::setTexture(int location, int slot, int index, - backend::TextureBackend* texture, + rhi::Texture* texture, std::unordered_map& textureInfo) { if (location < 0) @@ -396,7 +378,7 @@ void ProgramState::setTexture(int location, void ProgramState::setTextureArray(int location, std::vector slots, - std::vector textures, + std::vector textures, std::unordered_map& textureInfo) { assert(slots.size() == textures.size()); @@ -447,4 +429,4 @@ const char* ProgramState::getFragmentUniformBuffer(std::size_t& size) const return _uniformBuffers.data() + _vertexUniformBufferSize; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ProgramState.h b/axmol/rhi/ProgramState.h similarity index 82% rename from core/renderer/backend/ProgramState.h rename to axmol/rhi/ProgramState.h index 03e14f1ae314..ac01be4cc2fd 100644 --- a/core/renderer/backend/ProgramState.h +++ b/axmol/rhi/ProgramState.h @@ -30,21 +30,21 @@ #include #include #include -#include "platform/PlatformMacros.h" -#include "base/Object.h" -#include "base/EventListenerCustom.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/Program.h" -#include "renderer/backend/VertexLayout.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Object.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/VertexLayout.h" #include "yasio/byte_buffer.hpp" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { -class TextureBackend; +class Texture; class VertexLayout; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -53,10 +53,8 @@ class VertexLayout; */ struct AX_DLL TextureInfo { - TextureInfo(std::vector&& _slots, std::vector&& _textures); - TextureInfo(std::vector&& _slots, - std::vector&& _indexs, - std::vector&& _textures); + TextureInfo(std::vector&& _slots, std::vector&& _textures); + TextureInfo(std::vector&& _slots, std::vector&& _indexs, std::vector&& _textures); TextureInfo() = default; TextureInfo(const TextureInfo&); TextureInfo(TextureInfo&& rhs); @@ -68,14 +66,14 @@ struct AX_DLL TextureInfo void assign(const TextureInfo& other); void assign(TextureInfo&& other); - void assign(int slot, int index, backend::TextureBackend* texture); + void assign(int slot, int index, rhi::Texture* texture); void retainTextures(); void releaseTextures(); std::vector slots; std::vector indexs; - std::vector textures; + std::vector textures; #if AX_ENABLE_CACHE_TEXTURE_DATA int location = -1; #endif @@ -106,7 +104,7 @@ class AX_DLL ProgramState : public Object /** * Get the program object. */ - backend::Program* getProgram() const { return _program; } + rhi::Program* getProgram() const { return _program; } /** * Specify the value of a uniform variable for the current program state object. @@ -114,23 +112,23 @@ class AX_DLL ProgramState : public Object * @param data Specifies the new values to be used for the specified uniform variable. * @param size Specifies the uniform data size. */ - void setUniform(const backend::UniformLocation& uniformLocation, const void* data, std::size_t size); + void setUniform(const rhi::UniformLocation& uniformLocation, const void* data, std::size_t size); /** * Get uniform location in given uniform name. * @param uniform Specifies the uniform name. * @return Uniform location. - * @see `backend::UniformLocation getUniformLocation(backend::Uniform name) const` + * @see `rhi::UniformLocation getUniformLocation(rhi::Uniform name) const` */ - backend::UniformLocation getUniformLocation(std::string_view uniform) const; + rhi::UniformLocation getUniformLocation(std::string_view uniform) const; /** * Get uniform location in a more efficient way by the given built-in uniform name. * @param uniform Specifies the engin built-in uniform name. * @return Uniform location. - * @see `backend::UniformLocation getUniformLocation(backend::Uniform name) const` + * @see `rhi::UniformLocation getUniformLocation(rhi::Uniform name) const` */ - backend::UniformLocation getUniformLocation(backend::Uniform name) const; + rhi::UniformLocation getUniformLocation(rhi::Uniform name) const; /** * Get an attribute location by the actual attribute name. @@ -138,7 +136,7 @@ class AX_DLL ProgramState : public Object * @return Attribute location. * @see `int getAttributeLocation(std::string_view name) const` */ - inline int getAttributeLocation(std::string_view name) const { return _program->getAttributeLocation(name); } + inline const VertexInputDesc* getVertexInputDesc(std::string_view name) const { return _program->getVertexInputDesc(name); } /** * Get an attribute location by the engine built-in attribute name. @@ -146,14 +144,17 @@ class AX_DLL ProgramState : public Object * @return Attribute location. * @see `int getAttributeLocation(std::string_view name) const` */ - inline int getAttributeLocation(Attribute name) const { return _program->getAttributeLocation(name); } + inline const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const + { + return _program->getVertexInputDesc(name); + } /** * A callback to update unifrom. * @param uniformLocation Specifies the uniform location. * @param unifromCallback Specifies a callback function to update the uniform. */ - void setCallbackUniform(const backend::UniformLocation&, const UniformCallback&); + void setCallbackUniform(const rhi::UniformLocation&, const UniformCallback&); /** * Get the uniform callback function. @@ -169,7 +170,7 @@ class AX_DLL ProgramState : public Object * @param uniformLocation Specifies texture location. * @param texture Specifies a pointer to backend texture. */ - void setTexture(backend::TextureBackend* texture); + void setTexture(rhi::Texture* texture); /** * Set texture. @@ -177,7 +178,7 @@ class AX_DLL ProgramState : public Object * @param slot Specifies texture slot selector. * @param texture Specifies a pointer to backend texture. */ - void setTexture(const backend::UniformLocation& uniformLocation, int slot, backend::TextureBackend* texture); + void setTexture(const rhi::UniformLocation& uniformLocation, int slot, rhi::Texture* texture); /** * Set texture. @@ -186,10 +187,10 @@ class AX_DLL ProgramState : public Object * @param index Specifies texture index selector * @param texture Specifies a pointer to backend texture. */ - void setTexture(const backend::UniformLocation& uniformLocation, + void setTexture(const rhi::UniformLocation& uniformLocation, int slot, int index, - backend::TextureBackend* texture); + rhi::Texture* texture); /** * Set textures in array. @@ -197,9 +198,9 @@ class AX_DLL ProgramState : public Object * @param slots Specifies texture slot selector. * @param textures Specifies a vector of backend texture object. */ - void setTextureArray(const backend::UniformLocation& uniformLocation, + void setTextureArray(const rhi::UniformLocation& uniformLocation, std::vector slots, - std::vector textures); + std::vector textures); /** * Get vertex texture informations @@ -290,15 +291,18 @@ class AX_DLL ProgramState : public Object */ void setParameterAutoBinding(std::string_view uniformName, std::string_view autoBinding); - inline const VertexLayout* getVertexLayout() const { return _vertexLayout; } + inline const VertexLayout* getVertexLayout() const + { + return _vertexLayout; + } VertexLayout* getMutableVertexLayout(); void setSharedVertexLayout(VertexLayout* vertexLayout); /* - * Gets batch id of current program state, part of batch draw materialID - */ + * Gets batch id of current program state, part of batch draw materialID + */ uint64_t getBatchId() const { return _batchId; }; /* @@ -311,17 +315,7 @@ class AX_DLL ProgramState : public Object * so batch ID was set to -1 indicate batch was disabled */ void updateBatchId(); -#ifndef AX_CORE_PROFILE - /* - * Follow API is deprecated, use getMutableVertexLayout instead - */ - AX_DEPRECATED(2.1) void setVertexAttrib(std::string_view name, - std::size_t index, - VertexFormat format, - std::size_t offset, - bool needToBeNormallized); - AX_DEPRECATED(2.1) void setVertexStride(uint32_t stride); -#endif + /** Custom shader program's vertex layout maybe not setup * so engine specific render node(such as Sprite) should invoke this API when ProgramState changed */ @@ -338,7 +332,7 @@ class AX_DLL ProgramState : public Object */ void setVertexUniform(int location, const void* data, std::size_t size, int offset); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL || AX_RENDER_API == AX_RENDER_API_D3D /** * Set the fargment uniform data. * @param location Specifies the uniform location. @@ -358,7 +352,7 @@ class AX_DLL ProgramState : public Object void setTexture(int location, int slot, int index, - backend::TextureBackend* texture, + rhi::Texture* texture, std::unordered_map& textureInfo); /** @@ -370,7 +364,7 @@ class AX_DLL ProgramState : public Object */ void setTextureArray(int location, std::vector slots, - std::vector textures, + std::vector textures, std::unordered_map& textureInfo); /** @@ -389,7 +383,7 @@ class AX_DLL ProgramState : public Object */ void applyAutoBinding(std::string_view, std::string_view); - backend::Program* _program = nullptr; + rhi::Program* _program = nullptr; std::unordered_map _callbackUniforms; yasio::sbyte_buffer _uniformBuffers; std::size_t _vertexUniformBufferSize = 0; @@ -401,8 +395,8 @@ class AX_DLL ProgramState : public Object std::unordered_map _autoBindings; static std::vector _customAutoBindingResolvers; - VertexLayout* _vertexLayout = nullptr; - bool _ownVertexLayout = false; + VertexLayout* _vertexLayout = nullptr; + bool _ownVertexLayout = false; uint64_t _batchId = -1; bool _isBatchable = false; @@ -412,6 +406,6 @@ class AX_DLL ProgramState : public Object #endif }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/Enums.h b/axmol/rhi/RHITypes.h similarity index 66% rename from core/renderer/backend/Enums.h rename to axmol/rhi/RHITypes.h index 7cfea6b09483..41cc52b140b5 100644 --- a/core/renderer/backend/Enums.h +++ b/axmol/rhi/RHITypes.h @@ -25,19 +25,26 @@ #pragma once -#include "Macros.h" - +#include #include -#include #include -#include "base/bitmask.h" +#include "axmol/base/bitmask.h" + +#define MAX_COLOR_ATTCHMENT 4 -NS_AX_BACKEND_BEGIN +#define MAX_INFLIGHT_BUFFER 3 + +#define AX_ARRAYSIZE(A) (sizeof(A) / sizeof((A)[0])) + +namespace ax::rhi +{ +using namespace std::string_view_literals; enum class BufferUsage : uint32_t { STATIC, - DYNAMIC + DYNAMIC, + IMMUTABLE, // d3d only }; enum class BufferType : uint32_t @@ -71,9 +78,10 @@ enum class VertexFormat : uint32_t INT, USHORT4, USHORT2, - UBYTE4 + UBYTE4, + MAT4, }; -/** @typedef backend::PixelFormat +/** @typedef rhi::PixelFormat Possible texture pixel formats refer to: https://docs.gl/es3/glTexImage2D @@ -188,32 +196,7 @@ enum class PrimitiveType : uint32_t TRIANGLE_STRIP }; -enum class TextureType : uint32_t -{ - TEXTURE_2D, - TEXTURE_CUBE -}; - -enum class SamplerAddressMode : uint32_t -{ - REPEAT, - MIRROR_REPEAT, - CLAMP_TO_EDGE, - DONT_CARE, -}; - -enum class SamplerFilter : uint32_t -{ - NEAREST, - NEAREST_MIPMAP_NEAREST, - NEAREST_MIPMAP_LINEAR, - LINEAR, - LINEAR_MIPMAP_LINEAR, - LINEAR_MIPMAP_NEAREST, - DONT_CARE, -}; - -enum class StencilOperation : uint32_t +enum class StencilOp : uint32_t { KEEP, ZERO, @@ -223,19 +206,7 @@ enum class StencilOperation : uint32_t DECREMENT_WRAP }; -enum class CompareFunction : uint32_t -{ - NEVER, - LESS, - LESS_EQUAL, - GREATER, - GREATER_EQUAL, - EQUAL, - NOT_EQUAL, - ALWAYS -}; - -enum class BlendOperation : uint32_t +enum class BlendOp : uint32_t { ADD, SUBTRACT, @@ -295,6 +266,14 @@ enum class TargetBufferFlags : uint8_t }; AX_ENABLE_BITMASK_OPS(TargetBufferFlags) +inline TargetBufferFlags getMRTColorFlag(size_t index) noexcept +{ + assert(index < 4); + return TargetBufferFlags(1u << index); +} + +typedef TargetBufferFlags ClearFlag; + enum class DepthStencilFlags : unsigned int { NONE = 0, @@ -320,6 +299,55 @@ enum class Winding : uint32_t COUNTER_CLOCK_WISE }; +enum class TextureType : uint32_t +{ + TEXTURE_2D, + TEXTURE_CUBE +}; + +enum class SamplerAddressMode : uint32_t +{ + REPEAT = 0, + MIRROR, + CLAMP, + BORDER, + // alias + CLAMP_TO_EDGE = CLAMP, +}; + +enum class SamplerFilter : uint32_t +{ + // min filter + MIN_NEAREST = 0, + MIN_LINEAR, + MIN_ANISOTROPIC, + + // mag filter + MAG_NEAREST = 0, + MAG_LINEAR, + + // mip filter + MIP_NONE = 0, + MIP_NEAREST, + MIP_LINEAR, + + // alias + NEAREST = 0, + LINEAR +}; + +enum class CompareFunc : uint32_t +{ + NEVER, + LESS, + EQUAL, + LESS_EQUAL, + GREATER, + NOT_EQUAL, + GREATER_EQUAL, + ALWAYS +}; + enum class TextureCubeFace : uint32_t { POSITIVE_X = 0, @@ -330,6 +358,127 @@ enum class TextureCubeFace : uint32_t NEGATIVE_Z = 5 }; +/// @remark sizeof(SamplerDesc) == 4 as key for caching sampler fast +struct SamplerDesc +{ + SamplerFilter minFilter : 2 = SamplerFilter::MIN_LINEAR; + SamplerFilter magFilter : 1 = SamplerFilter::MAG_LINEAR; + SamplerFilter mipFilter : 2 = SamplerFilter::MIP_NONE; + SamplerAddressMode sAddressMode : 2 = SamplerAddressMode::CLAMP; + SamplerAddressMode tAddressMode : 2 = SamplerAddressMode::CLAMP; + SamplerAddressMode wAddressMode : 2 = SamplerAddressMode::CLAMP; + CompareFunc compareFunc : 4 = CompareFunc::NEVER; + uint32_t anisotropy : 4 = 1; +}; + +using SamplerHandle = void*; + +/** + * Store texture description. + */ +struct TextureDesc +{ + TextureType textureType = TextureType::TEXTURE_2D; + PixelFormat textureFormat = PixelFormat::RGBA8; + TextureUsage textureUsage = TextureUsage::READ; + uint32_t width = 1; + uint32_t height = 1; + uint32_t depth = 1; + SamplerDesc samplerDesc{}; +}; + +/** + * @brief a structor to store blend descriptor + */ +struct BlendDesc +{ + ColorWriteMask writeMask = ColorWriteMask::ALL; + + bool blendEnabled = false; + + BlendOp rgbBlendOp = BlendOp::ADD; + BlendOp alphaBlendOp = BlendOp::ADD; + + BlendFactor sourceRGBBlendFactor = BlendFactor::ONE; + BlendFactor destinationRGBBlendFactor = BlendFactor::ZERO; + BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE; + BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO; +}; + +struct UniformInfo +{ + int count = 0; // element count + int location = -1; + + // in opengl, type means uniform data type, i.e. GL_FLOAT_VEC2, while in metal type means data basic type, i.e. + // float + unsigned int type = 0; + unsigned int size = 0; // element size + unsigned int bufferOffset = 0; +}; + +struct StageUniformLocation +{ + int location = -1; + int offset = -1; + + operator bool() const { return location != -1; } + bool operator==(const StageUniformLocation& other) const + { + return location == other.location && offset == other.offset; + } +}; + +struct UniformLocation +{ + StageUniformLocation vertStage; + StageUniformLocation fragStage; + + operator bool() const { return vertStage || fragStage; } + void reset() + { + vertStage = {}; + fragStage = {}; + } + bool operator==(const UniformLocation& other) const + { + return vertStage == other.vertStage && fragStage == other.fragStage; + } + std::size_t operator()(const UniformLocation&) const // used as a hash function + { + return size_t(vertStage.location) ^ size_t(fragStage.location << 16); + } +}; + +// vertex input descriptor in vertex shader +struct VertexInputDesc +{ + std::string semantic; + int location = -1; // gl: location, d3d: semantic_index, metal: index + int count = 0; + int format = 0; +}; + +/// built-in uniform name +static constexpr auto UNIFORM_NAME_MVP_MATRIX = "u_MVPMatrix"sv; +static constexpr auto UNIFORM_NAME_TEXTURE = "u_tex0"sv; +static constexpr auto UNIFORM_NAME_TEXTURE1 = "u_tex1"sv; +static constexpr auto UNIFORM_NAME_TEXTURE2 = "u_tex2"sv; +static constexpr auto UNIFORM_NAME_TEXTURE3 = "u_tex3"sv; +static constexpr auto UNIFORM_NAME_TEXT_COLOR = "u_textColor"sv; +static constexpr auto UNIFORM_NAME_EFFECT_COLOR = "u_effectColor"sv; +static constexpr auto UNIFORM_NAME_EFFECT_TYPE = "u_effectType"sv; + +/// built-in attribute name +static constexpr auto VERTEX_INPUT_NAME_POSITION = "a_position"sv; +static constexpr auto VERTEX_INPUT_NAME_COLOR = "a_color"sv; +static constexpr auto VERTEX_INPUT_NAME_TEXCOORD = "a_texCoord"sv; +static constexpr auto VERTEX_INPUT_NAME_TEXCOORD1 = "a_texCoord1"sv; +static constexpr auto VERTEX_INPUT_NAME_TEXCOORD2 = "a_texCoord2"sv; +static constexpr auto VERTEX_INPUT_NAME_TEXCOORD3 = "a_texCoord3"sv; +static constexpr auto VERTEX_INPUT_NAME_NORMAL = "a_normal"sv; +static constexpr auto VERTEX_INPUT_NAME_INSTANCE = "a_instance"sv; + // clang-format off struct ProgramType { @@ -342,6 +491,8 @@ struct ProgramType POSITION_TEXTURE, // positionTexture_vert, positionTexture_frag POSITION_TEXTURE_COLOR, // positionTextureColor_vert, positionTextureColor_frag POSITION_TEXTURE_COLOR_ALPHA_TEST, // positionTextureColor_vert, positionTextureColorAlphaTest_frag + POSITION_TEXTURE_GRAY_ALPHA, // positionTextureColor_vert, positionTextureGrayAlpha_frag + POSITION_TEXTURE_GRAY, // positionTextureColor_vert, positionTextureGray_frag LABEL_NORMAL, // positionTextureColor_vert, label_normal_frag LABLE_OUTLINE, // positionTextureColor_vert, labelOutline_frag LABEL_DISTANCE_NORMAL, // positionTextureColor_vert, label_distanceNormal_frag @@ -364,8 +515,8 @@ struct ProgramType SKINPOSITION_NORMAL_TEXTURE_3D, // skinPositionNormalTexture_vert, colorNormalTexture_frag POSITION_NORMAL_TEXTURE_3D, // positionNormalTexture_vert, colorNormalTexture_frag POSITION_NORMAL_3D, // positionNormalTexture_vert, colorNormal_frag - POSITION_TEXTURE_3D, // positionTexture3D_vert, colorTexture_frag - POSITION_TEXTURE_3D_INSTANCE, // positionTextureInstance_vert, colorTexture_frag + UNLIT, // unlit_vert, colorTexture_frag + UNLIT_INSTANCE, // unlitInstance_vert, colorTexture_frag POSITION_3D, // positionTexture_vert, color_frag POSITION_BUMPEDNORMAL_TEXTURE_3D, // positionNormalTexture_vert, colorNormalTexture_frag SKINPOSITION_BUMPEDNORMAL_TEXTURE_3D, // skinPositionNormalTexture_vert, colorNormalTexture_frag @@ -384,6 +535,8 @@ struct ProgramType VIDEO_TEXTURE_I420, // For some android 11 and older devices VIDEO_TEXTURE_BGR32, + TRAIL_2D, + BUILTIN_COUNT, VIDEO_TEXTURE_RGB32 = POSITION_TEXTURE_COLOR, @@ -392,4 +545,23 @@ struct ProgramType }; // clang-format on -NS_AX_BACKEND_END +template +inline void SafeRelease(T (&resourceBlock)[N]) +{ + for (unsigned int i = 0; i < N; i++) + { + SafeRelease(resourceBlock[i]); + } +} + +template +inline void SafeRelease(T& resource) +{ + if (resource) + { + resource->Release(); + resource = nullptr; + } +} + +} // namespace ax::rhi diff --git a/core/renderer/backend/RenderPassDescriptor.cpp b/axmol/rhi/RenderPassDesc.cpp similarity index 92% rename from core/renderer/backend/RenderPassDescriptor.cpp rename to axmol/rhi/RenderPassDesc.cpp index 257fa044db6d..9e032ebad8f9 100644 --- a/core/renderer/backend/RenderPassDescriptor.cpp +++ b/axmol/rhi/RenderPassDesc.cpp @@ -22,11 +22,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "RenderPassDescriptor.h" +#include "axmol/rhi/RenderPassDesc.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { -bool RenderPassDescriptor::operator==(const RenderPassDescriptor& descriptor) const +bool RenderPassDesc::operator==(const RenderPassDesc& descriptor) const { return (clearDepthValue == descriptor.clearDepthValue && clearStencilValue == descriptor.clearStencilValue && clearColorValue == descriptor.clearColorValue && @@ -37,4 +37,4 @@ bool RenderPassDescriptor::operator==(const RenderPassDescriptor& descriptor) co flags.discardEnd == descriptor.flags.discardEnd); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/RenderPassDescriptor.h b/axmol/rhi/RenderPassDesc.h similarity index 87% rename from core/renderer/backend/RenderPassDescriptor.h rename to axmol/rhi/RenderPassDesc.h index 6c13e9005f19..6d573b2a31e3 100644 --- a/core/renderer/backend/RenderPassDescriptor.h +++ b/axmol/rhi/RenderPassDesc.h @@ -27,14 +27,13 @@ #include #include -#include "Macros.h" -#include "Types.h" +#include "axmol/rhi/RHITypes.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { -class TextureBackend; +class Texture; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -62,10 +61,10 @@ struct RenderPassFlags /** * Store values about color, depth and stencil attachment. */ -struct RenderPassDescriptor +struct RenderPassDesc { - RenderPassDescriptor& operator=(const RenderPassDescriptor& descriptor) = default; - bool operator==(const RenderPassDescriptor& descriptor) const; + RenderPassDesc& operator=(const RenderPassDesc& descriptor) = default; + bool operator==(const RenderPassDesc& descriptor) const; float clearDepthValue = 0.f; float clearStencilValue = 0.f; @@ -74,6 +73,6 @@ struct RenderPassDescriptor // Now, only clear flag used RenderPassFlags flags{}; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/RenderPipeline.h b/axmol/rhi/RenderPipeline.h similarity index 81% rename from core/renderer/backend/RenderPipeline.h rename to axmol/rhi/RenderPipeline.h index e3d3ca13623c..02c10970980a 100644 --- a/core/renderer/backend/RenderPipeline.h +++ b/axmol/rhi/RenderPipeline.h @@ -24,15 +24,14 @@ #pragma once -#include "Macros.h" -#include "Types.h" -#include "base/Object.h" -#include "renderer/PipelineDescriptor.h" -#include "renderer/backend/RenderPassDescriptor.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" +#include "axmol/renderer/PipelineDesc.h" +#include "axmol/rhi/RenderPassDesc.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ class RenderTarget; @@ -43,11 +42,11 @@ class RenderTarget; class RenderPipeline : public ax::Object { public: - virtual void update(const RenderTarget*, const PipelineDescriptor& pipelineDescriptor) = 0; + virtual void update(const RenderTarget*, const PipelineDesc& desc) = 0; protected: virtual ~RenderPipeline() = default; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/RenderTarget.h b/axmol/rhi/RenderTarget.h similarity index 74% rename from core/renderer/backend/RenderTarget.h rename to axmol/rhi/RenderTarget.h index 6578788e3576..96199784729e 100644 --- a/core/renderer/backend/RenderTarget.h +++ b/axmol/rhi/RenderTarget.h @@ -25,18 +25,18 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" -#include "Texture.h" +#include "axmol/base/Object.h" +#include "axmol/rhi/Texture.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { class RenderTarget : public ax::Object { public: struct RenderBuffer { - TextureBackend* texture = nullptr; + Texture* texture = nullptr; uint8_t level = 0; // level when attached to a texture explicit operator bool() const { return texture != nullptr; } }; @@ -47,8 +47,7 @@ class RenderTarget : public ax::Object { for (auto colorItem : _color) AX_SAFE_RELEASE(colorItem.texture); - AX_SAFE_RELEASE(_depth.texture); - AX_SAFE_RELEASE(_stencil.texture); + AX_SAFE_RELEASE(_depthStencil.texture); } bool isDefaultRenderTarget() const { return _defaultRenderTarget; } @@ -67,7 +66,7 @@ class RenderTarget : public ax::Object AX_SAFE_RETAIN(colorItem.texture); }; - void setColorAttachment(TextureBackend* attachment, int level = 0, int index = 0) + void setColorAttachment(Texture* attachment, int level = 0, int index = 0) { if (_color[index].texture != attachment || _color[index].level != level) { @@ -79,38 +78,26 @@ class RenderTarget : public ax::Object } } - void setDepthAttachment(TextureBackend* attachment, int level = 0) + void setDepthStencilAttachment(Texture* attachment, int level = 0) { - if (_depth.texture != attachment || _depth.level != level) + if (_depthStencil.texture != attachment || _depthStencil.level != level) { _dirtyFlags |= TargetBufferFlags::DEPTH; - AX_SAFE_RELEASE(_depth.texture); - _depth.texture = attachment; - _depth.level = level; - AX_SAFE_RETAIN(_depth.texture); + AX_SAFE_RELEASE(_depthStencil.texture); + _depthStencil.texture = attachment; + _depthStencil.level = level; + AX_SAFE_RETAIN(_depthStencil.texture); } - }; - void setStencilAttachment(TextureBackend* attachment, int level = 0) - { - if (_stencil.texture != attachment || _depth.level != level) - { - _dirtyFlags |= TargetBufferFlags::STENCIL; - AX_SAFE_RELEASE(_stencil.texture); - _stencil.texture = attachment; - _stencil.level = level; - AX_SAFE_RETAIN(_stencil.texture); - } - }; + } bool isDirty() const { return !!_dirtyFlags; } ColorAttachment _color{}; - RenderBuffer _depth{}; - RenderBuffer _stencil{}; + RenderBuffer _depthStencil{}; protected: bool _defaultRenderTarget = false; mutable TargetBufferFlags _dirtyFlags{}; }; -NS_AX_BACKEND_END +} diff --git a/axmol/rhi/SamplerCache.cpp b/axmol/rhi/SamplerCache.cpp new file mode 100644 index 000000000000..33ce6cf0bff9 --- /dev/null +++ b/axmol/rhi/SamplerCache.cpp @@ -0,0 +1,68 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/SamplerCache.h" +#include "axmol/rhi/DriverBase.h" +#include "yasio/singleton.hpp" + +namespace ax::rhi +{ +SamplerCache* SamplerCache::getInstance() +{ + return yasio::singleton::instance(); +} +void SamplerCache::destroyInstance() +{ + yasio::singleton::destroy(); +} + +SamplerCache::~SamplerCache() +{ + removeAllSamplers(); +} + +void SamplerCache::removeAllSamplers() +{ + auto driver = DriverBase::getInstance(); + for (auto& [_, sampler] : _samplers) + { + driver->destroySampler(sampler); + } + _samplers.clear(); +} + +SamplerHandle SamplerCache::getSampler(const SamplerDesc& desc) +{ + auto key = *reinterpret_cast(&desc); + auto it = _samplers.find(key); + if (it != _samplers.end()) + return it->second; + + auto sampler = DriverBase::getInstance()->createSampler(desc); + + _samplers.emplace(key, sampler); + + return sampler; +} + +} // namespace ax::rhi diff --git a/core/renderer/backend/Backend.h b/axmol/rhi/SamplerCache.h similarity index 74% rename from core/renderer/backend/Backend.h rename to axmol/rhi/SamplerCache.h index 12e18c267886..122b4777a697 100644 --- a/core/renderer/backend/Backend.h +++ b/axmol/rhi/SamplerCache.h @@ -1,5 +1,4 @@ /**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,12 +24,25 @@ #pragma once -#include "renderer/backend/RenderPassDescriptor.h" -#include "renderer/backend/RenderPipeline.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/CommandBuffer.h" -#include "renderer/backend/Buffer.h" -#include "renderer/backend/VertexLayout.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/DepthStencilState.h" +#include "axmol/base/hlookup.h" +#include "RHITypes.h" + +namespace ax::rhi +{ +class SamplerCache +{ +public: + + static SamplerCache* getInstance(); + static void destroyInstance(); + + ~SamplerCache(); + + void removeAllSamplers(); + + SamplerHandle getSampler(const SamplerDesc& desc); + +private: + tsl::robin_map _samplers; +}; +} // namespace ax::rhi diff --git a/core/renderer/backend/ShaderCache.cpp b/axmol/rhi/ShaderCache.cpp similarity index 77% rename from core/renderer/backend/ShaderCache.cpp rename to axmol/rhi/ShaderCache.cpp index 0d9abbaa6b88..688c2222b304 100644 --- a/core/renderer/backend/ShaderCache.cpp +++ b/axmol/rhi/ShaderCache.cpp @@ -23,10 +23,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "ShaderCache.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/rhi/ShaderCache.h" +#include "axmol/rhi/DriverBase.h" -NS_AX_BACKEND_BEGIN +#include "xxhash.h" + +namespace ax::rhi { static ShaderCache* s_instance; @@ -56,29 +58,34 @@ void ShaderCache::purge() AXLOGV("purging ShaderCache"); } -backend::ShaderModule* ShaderCache::newVertexShaderModule(std::string_view shaderSource) +rhi::ShaderModule* ShaderCache::acquireVertexShaderModule(std::string_view shaderSource) { - return newShaderModule(backend::ShaderStage::VERTEX, shaderSource); + return acquireShaderModule(rhi::ShaderStage::VERTEX, shaderSource); } -backend::ShaderModule* ShaderCache::newFragmentShaderModule(std::string_view shaderSource) +rhi::ShaderModule* ShaderCache::acquireFragmentShaderModule(std::string_view shaderSource) { - return newShaderModule(backend::ShaderStage::FRAGMENT, shaderSource); + return acquireShaderModule(rhi::ShaderStage::FRAGMENT, shaderSource); } -backend::ShaderModule* ShaderCache::newShaderModule(backend::ShaderStage stage, std::string_view shaderSource) +rhi::ShaderModule* ShaderCache::acquireShaderModule(rhi::ShaderStage stage, std::string_view shaderSource) { - const std::size_t key = std::hash{}(shaderSource); + const auto key = XXH64(shaderSource.data(), shaderSource.size(), 0); const auto iter = _cachedShaders.find(key); if (_cachedShaders.end() != iter) + { + AX_SAFE_RETAIN(iter->second); return iter->second; + } - ShaderModule* const shader = backend::DriverBase::getInstance()->newShaderModule(stage, shaderSource); + ShaderModule* const shader = rhi::DriverBase::getInstance()->createShaderModule(stage, shaderSource); shader->setHashValue(key); _cachedShaders.emplace(key, shader); + AX_SAFE_RETAIN(shader); + return shader; } @@ -100,4 +107,4 @@ void ShaderCache::removeUnusedShader() } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ShaderCache.h b/axmol/rhi/ShaderCache.h similarity index 83% rename from core/renderer/backend/ShaderCache.h rename to axmol/rhi/ShaderCache.h index e603c80a075c..fd38ee79ab69 100644 --- a/core/renderer/backend/ShaderCache.h +++ b/axmol/rhi/ShaderCache.h @@ -24,17 +24,17 @@ ****************************************************************************/ #pragma once -#include "Macros.h" -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "renderer/backend/ShaderModule.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/rhi/ShaderModule.h" #include #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -57,14 +57,14 @@ class AX_DLL ShaderCache * If it is created before, then just return the cached shader module. * @param shaderSource The source code of the shader. */ - backend::ShaderModule* newVertexShaderModule(std::string_view shaderSource); + rhi::ShaderModule* acquireVertexShaderModule(std::string_view shaderSource); /** * Create a fragment shader module. * If it is created before, then just return the cached shader module. * @param shaderSource The source code of the shader. */ - backend::ShaderModule* newFragmentShaderModule(std::string_view shaderSource); + rhi::ShaderModule* acquireFragmentShaderModule(std::string_view shaderSource); /** * Remove all unused shaders. @@ -80,11 +80,11 @@ class AX_DLL ShaderCache * @param source Specifies shader source. * @return A ShaderModule object. */ - backend::ShaderModule* newShaderModule(backend::ShaderStage stage, std::string_view shaderSource); + rhi::ShaderModule* acquireShaderModule(rhi::ShaderStage stage, std::string_view shaderSource); - std::unordered_map _cachedShaders; + std::unordered_map _cachedShaders; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ShaderModule.cpp b/axmol/rhi/ShaderModule.cpp similarity index 95% rename from core/renderer/backend/ShaderModule.cpp rename to axmol/rhi/ShaderModule.cpp index 3d1cc25d44a4..2a54a20aceaa 100644 --- a/core/renderer/backend/ShaderModule.cpp +++ b/axmol/rhi/ShaderModule.cpp @@ -22,9 +22,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "ShaderModule.h" +#include "axmol/rhi/ShaderModule.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi { ShaderStage ShaderModule::getShaderStage() const { @@ -35,4 +35,4 @@ ShaderModule::ShaderModule(ShaderStage stage) : _stage(stage) {} ShaderModule::~ShaderModule() {} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/ShaderModule.h b/axmol/rhi/ShaderModule.h similarity index 83% rename from core/renderer/backend/ShaderModule.h rename to axmol/rhi/ShaderModule.h index e886ab0a10f5..04e8f0d1b256 100644 --- a/core/renderer/backend/ShaderModule.h +++ b/axmol/rhi/ShaderModule.h @@ -24,18 +24,17 @@ #pragma once -#include "Macros.h" -#include "Types.h" -#include "base/Object.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { // #define AX_USE_UNIFORM_FULL_NAME /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -49,10 +48,10 @@ enum Uniform : uint32_t TEXT_COLOR, EFFECT_TYPE, EFFECT_COLOR, - UNIFORM_MAX // Maximum uniforms + UNIFORM_COUNT // Maximum uniforms }; -enum Attribute : uint32_t +enum VertexInputKind : uint32_t { POSITION, COLOR, @@ -62,7 +61,7 @@ enum Attribute : uint32_t TEXCOORD3, NORMAL, INSTANCE, - ATTRIBUTE_MAX // Maximum attributes + VIK_COUNT // }; /** * Create shader. @@ -76,18 +75,18 @@ class AX_DLL ShaderModule : public ax::Object */ ShaderStage getShaderStage() const; - std::size_t getHashValue() const { return _hash; } + uint64_t getHashValue() const { return _hash; } protected: ShaderModule(ShaderStage stage); virtual ~ShaderModule(); - void setHashValue(std::size_t hash) { _hash = hash; } + void setHashValue(uint64_t hash) { _hash = hash; } friend class ShaderCache; ShaderStage _stage = ShaderStage::VERTEX; - std::size_t _hash = 0; + uint64_t _hash = 0; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/Texture.cpp b/axmol/rhi/Texture.cpp similarity index 82% rename from core/renderer/backend/Texture.cpp rename to axmol/rhi/Texture.cpp index 6fd726e609df..16810aa0d16c 100644 --- a/core/renderer/backend/Texture.cpp +++ b/axmol/rhi/Texture.cpp @@ -23,21 +23,22 @@ THE SOFTWARE. ****************************************************************************/ -#include "Texture.h" -#include "PixelFormatUtils.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/PixelFormatUtils.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi +{ -TextureBackend::~TextureBackend() {} +Texture::~Texture() {} -void TextureBackend::updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int /*index*/) +void Texture::updateTextureDesc(const TextureDesc& descriptor, int /*index*/) { _bitsPerPixel = PixelFormatUtils::getBitsPerPixel(descriptor.textureFormat); _textureType = descriptor.textureType; _textureFormat = descriptor.textureFormat; _textureUsage = descriptor.textureUsage; - _width = (std::max)(descriptor.width, (uint32_t)1); - _height = (std::max)(descriptor.height, (uint32_t)1); + _width = (std::max)(descriptor.width, (uint32_t)1); + _height = (std::max)(descriptor.height, (uint32_t)1); if (_bitsPerPixel == 0) { @@ -45,4 +46,4 @@ void TextureBackend::updateTextureDescriptor(const ax::backend::TextureDescripto } } -NS_AX_BACKEND_END +} // namespace ax::rhi diff --git a/core/renderer/backend/Texture.h b/axmol/rhi/Texture.h similarity index 83% rename from core/renderer/backend/Texture.h rename to axmol/rhi/Texture.h index efd382c72b92..caf462ac9775 100644 --- a/core/renderer/backend/Texture.h +++ b/axmol/rhi/Texture.h @@ -25,43 +25,29 @@ #pragma once -#include "Types.h" -#include "base/Object.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" #include #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ -/** - * Store texture description. - */ -struct TextureDescriptor -{ - TextureType textureType = TextureType::TEXTURE_2D; - PixelFormat textureFormat = PixelFormat::RGBA8; - TextureUsage textureUsage = TextureUsage::READ; - uint32_t width = 0; - uint32_t height = 0; - uint32_t depth = 0; - SamplerDescriptor samplerDescriptor; -}; - /** * A base texture */ -class TextureBackend : public Object +class Texture : public Object { public: /** * Update sampler * @param sampler Specifies the sampler descriptor. */ - virtual void updateSamplerDescriptor(const SamplerDescriptor& sampler) = 0; + virtual void updateSamplerDesc(const SamplerDesc& sampler) = 0; /// Generate mipmaps. virtual void generateMipmaps() = 0; @@ -70,7 +56,7 @@ class TextureBackend : public Object * Update texture description. * @param descriptor Specifies texture and sampler descriptor. */ - virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0); + virtual void updateTextureDesc(const TextureDesc& descriptor, int index = 0); /** * Get texture format. @@ -98,36 +84,9 @@ class TextureBackend : public Object virtual int getCount() const { return 1; }; - virtual uintptr_t getHandler(int index = 0) const { return 0; } - int getWidth() const { return _width; } int getHeight() const { return _height; } -protected: - /** - * @param descriptor Specifies the texture descriptor. - */ - TextureBackend() {} - virtual ~TextureBackend(); - - /// The bytes of all components. - uint8_t _bitsPerPixel = 0; - bool _hasMipmaps = false; - bool _isCompressed = false; - uint32_t _width = 0; - uint32_t _height = 0; - - TextureType _textureType = TextureType::TEXTURE_2D; - PixelFormat _textureFormat = PixelFormat::RGBA8; - TextureUsage _textureUsage = TextureUsage::READ; -}; - -/** - * A 2D texture. - */ -class Texture2DBackend : public TextureBackend -{ -public: /** * Update a two-dimensional texture image * @param data Specifies a pointer to the image data in memory. @@ -192,33 +151,31 @@ class Texture2DBackend : public TextureBackend uint8_t* data, int index = 0) = 0; - /** - * Get texture width. - * @return Texture width. - */ - inline std::size_t getWidth() const { return _width; } - - /** - * Get texture height. - * @return Texture height. - */ - inline std::size_t getHeight() const { return _height; } -}; - -/** - * A cubemap texture. - */ -class TextureCubemapBackend : public TextureBackend -{ -public: /** * Update texutre cube data in give slice side. * @param side Specifies which slice texture of cube to be update. * @param data Specifies a pointer to the image data in memory. */ virtual void updateFaceData(TextureCubeFace side, void* data, int index = 0) = 0; + +protected: + /** + * @param descriptor Specifies the texture descriptor. + */ + Texture() {} + virtual ~Texture(); + + /// The bytes of all components. + uint8_t _bitsPerPixel = 0; + bool _hasMipmaps = false; + uint32_t _width = 0; + uint32_t _height = 0; + + TextureType _textureType = TextureType::TEXTURE_2D; + PixelFormat _textureFormat = PixelFormat::RGBA8; + TextureUsage _textureUsage = TextureUsage::READ; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/VertexLayout.cpp b/axmol/rhi/VertexLayout.cpp similarity index 61% rename from core/renderer/backend/VertexLayout.cpp rename to axmol/rhi/VertexLayout.cpp index 9bbb6187c855..6a7fa726fb8a 100644 --- a/core/renderer/backend/VertexLayout.cpp +++ b/axmol/rhi/VertexLayout.cpp @@ -23,34 +23,34 @@ THE SOFTWARE. ****************************************************************************/ -#include "VertexLayout.h" -#include "base/Macros.h" +#include "axmol/rhi/VertexLayout.h" +#include "axmol/base/Macros.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi +{ void VertexLayout::setAttrib(std::string_view name, - std::size_t index, - VertexFormat format, - std::size_t offset, - bool needToBeNormallized) + const VertexInputDesc* desc, + VertexFormat format, + std::size_t offset, + bool needToBeNormallized, + uint8_t instanceStepRate) { - if (index == -1) + if (!desc) { - AXLOGW("The vertex attribute '{}' vfmt={} not exist, unused/optimized?", name, static_cast(format)); + AXLOGW("The vertex input '{}' vfmt={} not exist, unused/optimized?", name, static_cast(format)); return; } - // FIXME 2021/12/25 TODO: store name key is enough - hlookup::set_item( - _attributes, name, - Attribute{name, index, format, offset, - needToBeNormallized}); // _attributes[name] = {name, index, format, offset, needToBeNormallized}; -} - -void VertexLayout::setStride(std::size_t stride) -{ - _stride = stride; + if (!instanceStepRate) + hlookup::set_item( + _bindings, name, + InputBindingDesc{desc->semantic, desc->location, format, offset, needToBeNormallized, instanceStepRate}); + else + hlookup::set_item( + _instanceBindings, name, + InputBindingDesc{desc->semantic, desc->location, format, offset, needToBeNormallized, instanceStepRate}); } -NS_AX_BACKEND_END +} // namespace ax::rhi diff --git a/core/renderer/backend/VertexLayout.h b/axmol/rhi/VertexLayout.h similarity index 58% rename from core/renderer/backend/VertexLayout.h rename to axmol/rhi/VertexLayout.h index ff2ed5658e62..052faff3ba7a 100644 --- a/core/renderer/backend/VertexLayout.h +++ b/axmol/rhi/VertexLayout.h @@ -25,18 +25,19 @@ #pragma once -#include "Macros.h" -#include "Types.h" -#include "base/Object.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" #include #include #include #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi +{ +class Program; /** - * @addtogroup _backend + * @addtogroup _rhi * @{ */ @@ -45,27 +46,39 @@ NS_AX_BACKEND_BEGIN */ class AX_DLL VertexLayout { + friend class DriverBase; + +protected: + VertexLayout() = default; + VertexLayout(const VertexLayout& rhs) = default; + public: - struct Attribute + struct InputBindingDesc { - Attribute() = default; - Attribute(std::string_view _name, - std::size_t _index, - VertexFormat _format, - std::size_t _offset, - bool needToBeNormallized) - : name(_name), format(_format), offset(_offset), index(_index), needToBeNormallized(needToBeNormallized) + InputBindingDesc() = default; + InputBindingDesc(std::string_view _name, + int _index, + VertexFormat _format, + std::size_t _offset, + bool needToBeNormallized, + uint8_t instanceStepRate) + : name(_name) + , format(_format) + , offset(_offset) + , index(_index) + , needToBeNormallized(needToBeNormallized) + , instanceStepRate(instanceStepRate) {} std::string name; ///< name is used in opengl VertexFormat format = VertexFormat::INT3; - std::size_t offset = 0; - std::size_t index = 0; ///< index is used in metal + unsigned int offset = 0; + int index = 0; ///< index is used in metal bool needToBeNormallized = false; + uint8_t instanceStepRate = 0; }; - VertexLayout() = default; - VertexLayout(const VertexLayout&) = default; + virtual ~VertexLayout() = default; /** * Set attribute values to name. @@ -77,56 +90,64 @@ class AX_DLL VertexLayout * directly as fixed-point values (false) when they are accessed. */ void setAttrib(std::string_view name, - std::size_t index, + const VertexInputDesc* desc, VertexFormat format, std::size_t offset, - bool needNormalized); -#ifndef AX_CORE_PROFILE - AX_DEPRECATED(2.1) void setAttribute(std::string_view name, - std::size_t index, - VertexFormat format, - std::size_t offset, - bool needNormalized) - { - setAttrib(name, index, format, offset, needNormalized); - } -#endif + bool needNormalized, + uint8_t instanceStepRate = 0); /** * Set stride of vertices. * @param stride Specifies the distance between the data of two vertices, in bytes. */ - void setStride(std::size_t stride); + inline void setStride(std::size_t stride) { _strides[0] = stride; } /** * Get the distance between the data of two vertices, in bytes. * @return The distance between the data of two vertices, in bytes. */ - inline std::size_t getStride() const { return _stride; } + inline std::size_t getStride() const { return _strides[0]; } /** - * Get vertex step function. Default value is VERTEX. - * @return Vertex step function. - * @note Used in metal. + * Set stride of vertices. + * @param stride Specifies the distance between the data of two vertices, in bytes. */ - inline VertexStepMode getVertexStepMode() const { return _stepMode; } + inline void setInstanceStride(std::size_t stride) { _strides[1] = stride; } + + /** + * Get the distance between the data of two vertices, in bytes. + * @return The distance between the data of two vertices, in bytes. + */ + inline std::size_t getInstanceStride() const { return _strides[1]; } /** * Get attribute informations * @return Atrribute informations. */ - inline const hlookup::string_map& getAttributes() const { return _attributes; } + inline const hlookup::string_map& getBindings() const { return _bindings; } + + inline const hlookup::string_map& getInstanceBindings() const { return _instanceBindings; } + + /** + * Get vertex step function. Default value is VERTEX. + * @return Vertex step function. + * @note Used in metal. + */ + inline VertexStepMode getVertexStepMode() const { return _stepMode; } /** * Check if vertex layout has been set. */ - inline bool isValid() const { return _stride != 0; } + inline bool isValid() const { return _strides[0] != 0; } + + virtual VertexLayout* clone() { return new VertexLayout(*this); } -private: - hlookup::string_map _attributes; - std::size_t _stride = 0; +protected: + hlookup::string_map _bindings; + hlookup::string_map _instanceBindings; + uint32_t _strides[2] = {}; // 0: normal verts, 1: instance verts VertexStepMode _stepMode = VertexStepMode::VERTEX; }; -// end of _backend group +// end of _rhi group /// @} -NS_AX_BACKEND_END +} // namespace ax::rhi diff --git a/core/renderer/backend/Macros.h b/axmol/rhi/axmol-rhi.h similarity index 81% rename from core/renderer/backend/Macros.h rename to axmol/rhi/axmol-rhi.h index 5f565f085169..2b83a9f814a4 100644 --- a/core/renderer/backend/Macros.h +++ b/axmol/rhi/axmol-rhi.h @@ -25,17 +25,12 @@ #pragma once -#define NS_AX_BACKEND_BEGIN \ - namespace ax \ - { \ - namespace backend \ - { -#define NS_AX_BACKEND_END \ - } \ - } - -#define MAX_COLOR_ATTCHMENT 4 - -#define MAX_INFLIGHT_BUFFER 3 - -#define AX_ARRAYSIZE(A) (sizeof(A) / sizeof((A)[0])) +#include "axmol/rhi/RenderPassDesc.h" +#include "axmol/rhi/RenderPipeline.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/CommandBuffer.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/VertexLayout.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/DepthStencilState.h" diff --git a/axmol/rhi/axslc-spec.h b/axmol/rhi/axslc-spec.h new file mode 100644 index 000000000000..f3f54177bc26 --- /dev/null +++ b/axmol/rhi/axslc-spec.h @@ -0,0 +1,114 @@ +// The Axmol Shader Compiler spec, define macros and structs, can be include anywhere +// match with axslcc-1.9.0+ + +#pragma once + +#include + +namespace axslc { + +#define sc_makefourcc(_a, _b, _c, _d) \ + (((uint32_t)(_a) | ((uint32_t)(_b) << 8) | ((uint32_t)(_c) << 16) | ((uint32_t)(_d) << 24))) + +#pragma pack(push, 1) + +#define SC_CHUNK sc_makefourcc('S', 'G', 'S', ' ') +#define SC_CHUNK_STAG sc_makefourcc('S', 'T', 'A', 'G') +#define SC_CHUNK_REFL sc_makefourcc('R', 'E', 'F', 'L') +#define SC_CHUNK_CODE sc_makefourcc('C', 'O', 'D', 'E') +#define SC_CHUNK_DATA sc_makefourcc('D', 'A', 'T', 'A') + +#define SC_LANG_GLES sc_makefourcc('G', 'L', 'E', 'S') +#define SC_LANG_HLSL sc_makefourcc('H', 'L', 'S', 'L') +#define SC_LANG_GLSL sc_makefourcc('G', 'L', 'S', 'L') +#define SC_LANG_MSL sc_makefourcc('M', 'S', 'L', ' ') +#define SC_LANG_SPIRV sc_makefourcc('S', 'P', 'I', 'R') + +#define SC_VERTEXFORMAT_FLOAT sc_makefourcc('F', 'L', 'T', '1') +#define SC_VERTEXFORMAT_FLOAT2 sc_makefourcc('F', 'L', 'T', '2') +#define SC_VERTEXFORMAT_FLOAT3 sc_makefourcc('F', 'L', 'T', '3') +#define SC_VERTEXFORMAT_FLOAT4 sc_makefourcc('F', 'L', 'T', '4') +#define SC_VERTEXFORMAT_INT sc_makefourcc('I', 'N', 'T', '1') +#define SC_VERTEXFORMAT_INT2 sc_makefourcc('I', 'N', 'T', '2') +#define SC_VERTEXFORMAT_INT3 sc_makefourcc('I', 'N', 'T', '3') +#define SC_VERTEXFORMAT_INT4 sc_makefourcc('I', 'N', 'T', '4') +#define SC_VERTEXFORMAT_MAT3 sc_makefourcc('M', 'A', 'T', '3') +#define SC_VERTEXFORMAT_MAT4 sc_makefourcc('M', 'A', 'T', '4') + +#define SC_STAGE_VERTEX sc_makefourcc('V', 'E', 'R', 'T') +#define SC_STAGE_FRAGMENT sc_makefourcc('F', 'R', 'A', 'G') +#define SC_STAGE_COMPUTE sc_makefourcc('C', 'O', 'M', 'P') + +#define SC_IMAGEDIM_1D sc_makefourcc('1', 'D', ' ', ' ') +#define SC_IMAGEDIM_2D sc_makefourcc('2', 'D', ' ', ' ') +#define SC_IMAGEDIM_3D sc_makefourcc('3', 'D', ' ', ' ') +#define SC_IMAGEDIM_CUBE sc_makefourcc('C', 'U', 'B', 'E') +#define SC_IMAGEDIM_RECT sc_makefourcc('R', 'E', 'C', 'T') +#define SC_IMAGEDIM_BUFFER sc_makefourcc('B', 'U', 'F', 'F') +#define SC_IMAGEDIM_SUBPASS sc_makefourcc('S', 'U', 'B', 'P') + +// SGS chunk +struct sc_chunk { + uint32_t lang; // sc_shader_lang + uint32_t profile_ver; +}; + +// REFL +struct sc_chunk_refl { + char name[32]; + uint32_t num_inputs; + uint32_t num_textures; + uint32_t num_uniform_buffers; + uint32_t num_storage_images; + uint32_t num_storage_buffers; + uint16_t flatten_ubos; + uint16_t debug_info; + + // inputs: sc_refl_input[num_inputs] + // uniform-buffers: sc_refl_uniformbuffer[num_uniform_buffers] + // textures: sc_refl_texture[num_textures] + // storage_images: sc_refl_texture[num_storage_images] + // storage_buffers: sc_refl_buffer[num_storage_buffers] +}; + +struct sc_refl_input { + char name[32]; + int32_t loc; + char semantic[32]; + uint32_t semantic_index; + uint32_t format; +}; + +struct sc_refl_texture { + char name[32]; + int32_t binding; + uint32_t image_dim; + uint8_t multisample; + uint8_t is_array; +}; + +struct sc_refl_buffer { + char name[32]; + int32_t binding; + uint32_t size_bytes; + uint32_t array_stride; +}; + +typedef struct sc_refl_uniformbuffer { + char name[32]; + int32_t binding; + uint32_t size_bytes; + uint16_t array_size; + uint16_t num_members; +} sc_refl_ub; + +typedef struct sc_refl_uniformbuffer_member { + char name[32]; + int32_t offset; + uint32_t format; + uint32_t size_bytes; + uint16_t array_size; +} sc_refl_ub_member; +#pragma pack(pop) + +} diff --git a/axmol/rhi/d3d/BufferD3D.cpp b/axmol/rhi/d3d/BufferD3D.cpp new file mode 100644 index 000000000000..7d96d4c93ae7 --- /dev/null +++ b/axmol/rhi/d3d/BufferD3D.cpp @@ -0,0 +1,200 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/BufferD3D.h" + +namespace ax::rhi::d3d +{ + +// BufferUsage -> D3D11_USAGE / CPU flags +// https://learn.microsoft.com/en-us/windows/win32/api/d3d11/ne-d3d11-d3d11_usage +static void translateUsage(BufferUsage in, D3D11_USAGE& outUsage, UINT& outCpu) +{ + switch (in) + { + + case BufferUsage::DYNAMIC: // GPU read, CPU write + outUsage = D3D11_USAGE_DYNAMIC; + outCpu = D3D11_CPU_ACCESS_WRITE; + break; + case BufferUsage::STATIC: // GPU read/write, can use d3d API: UpdateSubresource to update data + outUsage = D3D11_USAGE_DEFAULT; + outCpu = 0; + break; + case BufferUsage::IMMUTABLE: // GPU read, must provide inital data, axmol do delay create when first updateData called + outUsage = D3D11_USAGE_IMMUTABLE; + outCpu = 0; + break; + } +} + +// BufferType -> BindFlag +static D3D11_BIND_FLAG translateBindFlag(BufferType t) +{ + switch (t) + { + case BufferType::VERTEX: + return D3D11_BIND_VERTEX_BUFFER; + + case BufferType::INDEX: + return D3D11_BIND_INDEX_BUFFER; + + case BufferType::UNIFORM: + return D3D11_BIND_CONSTANT_BUFFER; + + case BufferType::PIXEL_PACK_BUFFER: + // read backbuffer,map as staging or copy target + return D3D11_BIND_SHADER_RESOURCE; // FIXME: + + default: + AXLOGW("Unknown BufferType: {}", static_cast(t)); + return static_cast(0); + } +} + +static inline std::size_t alignTo(std::size_t value, std::size_t alignment) +{ + return (value + alignment - 1) & ~(alignment - 1); +} + +/* -------------------------------------------------- ctor */ +BufferImpl::BufferImpl(ID3D11Device* device, + ID3D11DeviceContext* context, + std::size_t size, + BufferType type, + BufferUsage usage, + const void* initial) + : Buffer(size, type, usage), _device(device), _context(context) +{ + translateUsage(usage, _nativeUsage, _cpuAccess); + _bindFlag = translateBindFlag(type); + + _capacity = _bindFlag == D3D11_BIND_CONSTANT_BUFFER ? alignTo(size, 16) : size; + + + if (initial && size) + _defaultData.assign(static_cast(initial), static_cast(initial) + size); + + if (usage != BufferUsage::IMMUTABLE || initial) + createNativeBuffer(initial); +} + +/* -------------------------------------------------- createNativeBuffer */ +void BufferImpl::createNativeBuffer(const void* initial) +{ + D3D11_BUFFER_DESC desc{}; + desc.ByteWidth = static_cast(_capacity); + desc.Usage = _nativeUsage; + desc.BindFlags = _bindFlag; + desc.CPUAccessFlags = _cpuAccess; + desc.MiscFlags = 0; + + D3D11_SUBRESOURCE_DATA initData{}; + initData.pSysMem = initial; + + HRESULT hr = _device->CreateBuffer(&desc, initial ? &initData : nullptr, &_buffer); + + if (FAILED(hr)) + { + AXLOGE("Failed to create ID3D11Buffer, size={}, alignedSize={}, hr=0x{:08X}", _size, _capacity, + static_cast(hr)); + assert(false && "Failed to create ID3D11Buffer"); + } +} + +/* -------------------------------------------------- updateData */ +void BufferImpl::updateData(const void* data, std::size_t size) +{ + assert(size <= _size); + assert(data); + + if (_nativeUsage == D3D11_USAGE_DYNAMIC) + { + D3D11_MAPPED_SUBRESOURCE mapped{}; + _context->Map(_buffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped); + std::memcpy(mapped.pData, data, size); + _context->Unmap(_buffer.Get(), 0); + } + else if (_nativeUsage == D3D11_USAGE_IMMUTABLE) { + if (!_buffer && size == _capacity) + createNativeBuffer(data); + else + AXLOGE("immutable buffer must update whole data one-time"); + } + else { + _context->UpdateSubresource(_buffer.Get(), 0, nullptr, data, 0, 0); + } + + if (_needDefaultStoredData) + _defaultData.assign(static_cast(data), static_cast(data) + size); +} + +/* -------------------------------------------------- updateSubData */ +void BufferImpl::updateSubData(const void* data, std::size_t offset, std::size_t size) +{ + assert(data && (offset + size <= _size)); + + if (_nativeUsage == D3D11_USAGE_DYNAMIC) + { + D3D11_MAPPED_SUBRESOURCE mapped{}; + _context->Map(_buffer.Get(), 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mapped); + std::memcpy(static_cast(mapped.pData) + offset, data, size); + _context->Unmap(_buffer.Get(), 0); + } + else if (_nativeUsage == D3D11_USAGE_IMMUTABLE) + { + if (!_buffer && size == _capacity && offset == 0) + createNativeBuffer(data); + else + AXLOGE("immutable buffer must update whole data one-time"); + } + else + { + D3D11_BOX box{}; + box.left = static_cast(offset); + box.right = static_cast(offset + size); + box.top = 0; + box.bottom = 1; + box.front = 0; + box.back = 1; + + _context->UpdateSubresource(_buffer.Get(), 0, &box, data, 0, 0); + } + + if (_needDefaultStoredData) + std::memcpy(_defaultData.data() + offset, data, size); +} + +/* -------------------------------------------------- usingDefaultStoredData */ +void BufferImpl::usingDefaultStoredData(bool needDefaultStoredData) +{ + _needDefaultStoredData = needDefaultStoredData; + + if (needDefaultStoredData && !_defaultData.empty()) + { + // restore to default, write to GPU immidately + updateData(_defaultData.data(), _defaultData.size()); + } +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/BufferD3D.h b/axmol/rhi/d3d/BufferD3D.h new file mode 100644 index 000000000000..c683465bb149 --- /dev/null +++ b/axmol/rhi/d3d/BufferD3D.h @@ -0,0 +1,78 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include +#include +#include +#include + +#include "axmol/rhi/Buffer.h" + +namespace ax::rhi::d3d +{ + +class BufferImpl final : public Buffer +{ +public: + /** + * @param device created device from driver impl + * @param context the context related to device + * @param size request size of buffer + * @param type BufferType::VERTEX or BufferType::INDEX + * @param usage BufferUsage::STATIC / DYNAMIC / STREAM + * @param initial initial data + */ + BufferImpl(ID3D11Device* device, + ID3D11DeviceContext* context, + std::size_t size, + BufferType type, + BufferUsage usage, + const void* initial = nullptr); + + void updateData(const void* data, std::size_t size) override; + void updateSubData(const void* data, std::size_t offset, std::size_t size) override; + void usingDefaultStoredData(bool needDefaultStoredData) override; + + ID3D11Buffer* internalHandle() const noexcept { return _buffer.Get(); } + D3D11_BIND_FLAG getBindFlag() const noexcept { return _bindFlag; } + +private: + void createNativeBuffer(const void* initial); + + size_t _capacity{0}; + + std::vector _defaultData; + bool _needDefaultStoredData = true; + + ID3D11Device* _device; // weak ref + ID3D11DeviceContext* _context; // weak ref + Microsoft::WRL::ComPtr _buffer; + + D3D11_USAGE _nativeUsage = D3D11_USAGE_DYNAMIC; + UINT _cpuAccess = D3D11_CPU_ACCESS_WRITE; + D3D11_BIND_FLAG _bindFlag = D3D11_BIND_VERTEX_BUFFER; +}; + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/CommandBufferD3D.cpp b/axmol/rhi/d3d/CommandBufferD3D.cpp new file mode 100644 index 000000000000..8a8b4412950e --- /dev/null +++ b/axmol/rhi/d3d/CommandBufferD3D.cpp @@ -0,0 +1,623 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/CommandBufferD3D.h" +#include "axmol/rhi/d3d/RenderTargetD3D.h" +#include "axmol/rhi/d3d/RenderPipelineD3D.h" +#include "axmol/rhi/d3d/DepthStencilStateD3D.h" +#include "axmol/rhi/d3d/BufferD3D.h" +#include "axmol/rhi/d3d/UtilsD3D.h" +#include "axmol/rhi/d3d/ProgramD3D.h" +#include "axmol/rhi/d3d/VertexLayoutD3D.h" +#include +#include +#include "axmol/base/Logging.h" + +namespace ax::rhi::d3d +{ +static D3D11_PRIMITIVE_TOPOLOGY toD3DPrimitiveTopology(PrimitiveType type, bool wireframe) +{ + switch (type) + { + case PrimitiveType::POINT: + return D3D11_PRIMITIVE_TOPOLOGY_POINTLIST; + case PrimitiveType::LINE: + return D3D11_PRIMITIVE_TOPOLOGY_LINELIST; + case PrimitiveType::LINE_LOOP: + return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; // FIXME: LINE_LOOP + case PrimitiveType::LINE_STRIP: + return D3D11_PRIMITIVE_TOPOLOGY_LINESTRIP; + case PrimitiveType::TRIANGLE: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST; + case PrimitiveType::TRIANGLE_STRIP: + return D3D11_PRIMITIVE_TOPOLOGY_TRIANGLESTRIP; + default: + return D3D11_PRIMITIVE_TOPOLOGY_UNDEFINED; + } +} + +static DXGI_FORMAT toDXGIFormat(IndexFormat format) +{ + switch (format) + { + case IndexFormat::U_SHORT: + return DXGI_FORMAT_R16_UINT; + case IndexFormat::U_INT: + return DXGI_FORMAT_R32_UINT; + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +typedef LONG(WINAPI* PFN_RtlVerifyVersionInfo)(OSVERSIONINFOEXW*, ULONG, ULONGLONG); + +static BOOL _axmolIsWindows10BuildOrGreaterWin32(WORD build) +{ + OSVERSIONINFOEXW osvi = {sizeof(osvi), 10, 0, build}; + DWORD mask = VER_MAJORVERSION | VER_MINORVERSION | VER_BUILDNUMBER; + ULONGLONG cond = VerSetConditionMask(0, VER_MAJORVERSION, VER_GREATER_EQUAL); + cond = VerSetConditionMask(cond, VER_MINORVERSION, VER_GREATER_EQUAL); + cond = VerSetConditionMask(cond, VER_BUILDNUMBER, VER_GREATER_EQUAL); + // HACK: Use RtlVerifyVersionInfo instead of VerifyVersionInfoW as the + // latter lies unless the user knew to embed a non-default manifest + // announcing support for Windows 10 via supportedOS GUID + + static PFN_RtlVerifyVersionInfo RtlVerifyVersionInfo = + (PFN_RtlVerifyVersionInfo)GetProcAddress(GetModuleHandleW(L"ntdll"), "RtlVerifyVersionInfo"); + return RtlVerifyVersionInfo(&osvi, mask, cond) == 0; +} + +static constexpr DXGI_FORMAT _AX_SWAPCHAIN_FORMAT = DXGI_FORMAT_R8G8B8A8_UNORM; + +CommandBufferImpl::CommandBufferImpl(DriverImpl* driver, HWND hwnd) +{ + _driverImpl = driver; + // TODO: listen window size changed, to call swapChain->ResizeBuffers ? + // auto hwnd = Director::getInstance()->getRenderView()->getWin32Window(); + + RECT clientRect; + GetClientRect(hwnd, &clientRect); + _screenWidth = clientRect.right - clientRect.left; + _screenHeight = clientRect.bottom - clientRect.top; + + auto context = driver->getContext(); + ID3D11Device* device = driver->getDevice(); + + ComPtr dxgiDevice; + device->QueryInterface(__uuidof(IDXGIDevice), (void**)dxgiDevice.GetAddressOf()); + + ComPtr dxgiAdapter; + dxgiDevice->GetAdapter(dxgiAdapter.GetAddressOf()); + + ComPtr factory; + dxgiAdapter->GetParent(__uuidof(IDXGIFactory), (void**)factory.GetAddressOf()); + + // create swapchain + ComPtr swapChain; + ComPtr factory2; + + DXGI_SWAP_EFFECT swapEffect = DXGI_SWAP_EFFECT_DISCARD; // Default is blt mode + + if (SUCCEEDED(factory->QueryInterface(IID_PPV_ARGS(&factory2)))) + { + // DXGI 1.2+ support Flip mode + DXGI_SWAP_CHAIN_DESC1 desc1 = {}; + desc1.Width = _screenWidth; + desc1.Height = _screenHeight; + desc1.Format = _AX_SWAPCHAIN_FORMAT; + desc1.SampleDesc.Count = 1; // Flip not support MSAA + desc1.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + desc1.BufferCount = 2; + + // choolse swapchain by OS version + if (_axmolIsWindows10BuildOrGreaterWin32(0)) + { // Win10+ + desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD; + } + else + { // Win8 / Win7+PlatformUpdate + desc1.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL; + } + + DXGI_SWAP_CHAIN_FULLSCREEN_DESC fsDesc = {}; + fsDesc.Windowed = TRUE; + + ComPtr swapChain1; + HRESULT hr = factory2->CreateSwapChainForHwnd(device, hwnd, &desc1, &fsDesc, nullptr, &swapChain1); + + if (SUCCEEDED(hr)) + { + factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER); + swapChain1.As(&swapChain); + } + } + + // Fallback to blt mode if flip mode fail + if (!swapChain) + { + DXGI_SWAP_CHAIN_DESC scDesc = {}; + scDesc.BufferCount = 1; + scDesc.BufferDesc.Width = _screenWidth; + scDesc.BufferDesc.Height = _screenHeight; + scDesc.BufferDesc.Format = _AX_SWAPCHAIN_FORMAT; + scDesc.BufferDesc.RefreshRate.Numerator = 60; + scDesc.BufferDesc.RefreshRate.Denominator = 1; + scDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + scDesc.OutputWindow = hwnd; + scDesc.SampleDesc.Count = 1; + scDesc.SampleDesc.Quality = 0; + scDesc.Windowed = TRUE; + scDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD; + + factory->CreateSwapChain(device, &scDesc, &swapChain); + } + + _swapChain = swapChain.Detach(); + + UtilsD3D::updateDefaultRenderTargetAttachments(_driverImpl, _swapChain); + + _nullSRVs.reserve(8); +} + +CommandBufferImpl::~CommandBufferImpl() +{ + // cleanup GPU resources + UtilsD3D::updateDefaultRenderTargetAttachments(nullptr, nullptr); + _driverImpl->getContext()->OMSetRenderTargets(0, nullptr, nullptr); + + SafeRelease(_swapChain); + + if (_rasterState) + _rasterState.Reset(); +} + +bool CommandBufferImpl::resizeSwapChain(uint32_t width, uint32_t height) +{ + if (!_swapChain || !_driverImpl || !_screenRT) + return false; + + // Since the window size can be zero when minimized, delay rebuilding until it returns to normal state + if (width == 0 || height == 0) + { + return true; + } + + if (width == _screenWidth && height == _screenHeight) + return true; + + // 2) Resize swapchain buffers + UINT flags = 0; + // if (_allowTearing) + // flags |= DXGI_SWAP_CHAIN_FLAG_ALLOW_TEARING; + + auto impl = static_cast(const_cast(_screenRT)); + impl->invalidate(); + + HRESULT hr = _swapChain->ResizeBuffers(0, width, height, _AX_SWAPCHAIN_FORMAT, flags); + + UtilsD3D::updateDefaultRenderTargetAttachments(_driverImpl, _swapChain); + + if (FAILED(hr)) + return false; + + _screenWidth = width; + _screenHeight = height; + + return true; +} + +void CommandBufferImpl::setDepthStencilState(DepthStencilState* depthStencilState) +{ + _depthStencilState = static_cast(depthStencilState); +} + +void CommandBufferImpl::setRenderPipeline(RenderPipeline* renderPipeline) +{ + _renderPipeline = static_cast(renderPipeline); +} + +bool CommandBufferImpl::beginFrame() +{ + return true; +} + +void CommandBufferImpl::beginRenderPass(const RenderTarget* renderTarget, const RenderPassDesc& renderPassDesc) +{ + auto context = _driverImpl->getContext(); + + auto activeRT = static_cast(renderTarget); + if (_renderPassDesc == renderPassDesc && _currentRT == activeRT && !activeRT->isDirty()) + { + ; + } + else + { + + _currentRT = activeRT; + _renderPassDesc = renderPassDesc; + } + + activeRT->update(context); + activeRT->apply(context); + + auto colorAttachment = activeRT->getColorAttachment(0); + _renderTargetWidth = colorAttachment.desc.width; + _renderTargetHeight = colorAttachment.desc.height; + + auto clearFlags = renderPassDesc.flags.clear; + + // clear color + if (bitmask::any(clearFlags, TargetBufferFlags::COLOR)) + context->ClearRenderTargetView(activeRT->getRTV(0), renderPassDesc.clearColorValue.data()); + + // clear depth & stencil + if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH_AND_STENCIL) && activeRT->getDSV()) + context->ClearDepthStencilView(activeRT->getDSV(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, + renderPassDesc.clearDepthValue, + static_cast(renderPassDesc.clearStencilValue)); +} + +void CommandBufferImpl::updateDepthStencilState(const DepthStencilDesc& desc) +{ + _depthStencilState->update(desc); +} + +void CommandBufferImpl::updatePipelineState(const RenderTarget* rt, const PipelineDesc& desc) +{ + _renderPipeline->update(rt, desc); +} + +void CommandBufferImpl::setViewport(int x, int y, unsigned int w, unsigned int h) +{ + D3D11_VIEWPORT viewport = {}; + viewport.TopLeftX = x; + viewport.TopLeftY = (int)(_renderTargetHeight - y - h); + viewport.Width = static_cast(w); + viewport.Height = static_cast(h); + viewport.MinDepth = 0.0f; + viewport.MaxDepth = 1.0f; + + _driverImpl->getContext()->RSSetViewports(1, &viewport); +} + +void CommandBufferImpl::setCullMode(CullMode mode) +{ + if (_rasterDesc.cullMode != mode) + { + _rasterDesc.cullMode = mode; + _rasterDesc.dirtyFlags |= RF_CULL_MODE; + } +} + +void CommandBufferImpl::setWinding(Winding winding) +{ + if (_rasterDesc.winding != winding) + { + _rasterDesc.winding = winding; + _rasterDesc.dirtyFlags |= RF_WINDING; + } +} + +void CommandBufferImpl::setScissorRect(bool isEnabled, float x, float y, float width, float height) +{ + const int rtW = static_cast(_renderTargetWidth); + const int rtH = static_cast(_renderTargetHeight); + + D3D11_RECT rect{}; + + if (isEnabled) + { + y = _renderTargetHeight - height - y; + + const int minX = std::clamp(static_cast(x), 0, rtW); + const int minY = std::clamp(static_cast(y), 0, rtH); + const int maxX = std::clamp(static_cast(x + width), 0, rtW); + const int maxY = std::clamp(static_cast(y + height), 0, rtH); + + rect.left = minX; + rect.top = minY; + rect.right = maxX; + rect.bottom = maxY; + + if (rect.right < rect.left) + rect.right = rect.left; + if (rect.bottom < rect.top) + rect.bottom = rect.top; + } + else + { + rect.left = 0; + rect.top = 0; + rect.right = rtW; + rect.bottom = rtH; + } + + if (_rasterDesc.scissorEnable != isEnabled) + { + _rasterDesc.scissorEnable = isEnabled; + _rasterDesc.dirtyFlags |= RF_SCISSOR; + } + + _driverImpl->getContext()->RSSetScissorRects(1, &rect); +} + +void CommandBufferImpl::updateRasterizerState() +{ + if (!_rasterDesc.dirtyFlags && _rasterState) + return; + D3D11_RASTERIZER_DESC desc = {}; + desc.FillMode = D3D11_FILL_SOLID; + + switch (_rasterDesc.cullMode) + { + case CullMode::NONE: + desc.CullMode = D3D11_CULL_NONE; + break; + case CullMode::BACK: + desc.CullMode = D3D11_CULL_BACK; + break; + case CullMode::FRONT: + desc.CullMode = D3D11_CULL_FRONT; + break; + } + + desc.FrontCounterClockwise = (_rasterDesc.winding == Winding::COUNTER_CLOCK_WISE); + + desc.DepthClipEnable = TRUE; + desc.ScissorEnable = _rasterDesc.scissorEnable ? TRUE : FALSE; + + ID3D11RasterizerState* rasterizerState = nullptr; + HRESULT hr = _driverImpl->getDevice()->CreateRasterizerState(&desc, &rasterizerState); + if (SUCCEEDED(hr)) + { + _driverImpl->getContext()->RSSetState(rasterizerState); + _rasterState = rasterizerState; + } + + _rasterDesc.dirtyFlags = 0; +} + +void CommandBufferImpl::setProgramState(ProgramState* programState) +{ + AX_SAFE_RETAIN(programState); + AX_SAFE_RELEASE(_programState); + _programState = programState; +} + +void CommandBufferImpl::setVertexBuffer(Buffer* buffer) +{ + assert(buffer != nullptr); + if (buffer == nullptr || _vertexBuffer == buffer) + return; + + buffer->retain(); + AX_SAFE_RELEASE(_vertexBuffer); + _vertexBuffer = static_cast(buffer); +} + +void CommandBufferImpl::setIndexBuffer(Buffer* buffer) +{ + assert(buffer != nullptr); + if (buffer == nullptr || _indexBuffer == buffer) + return; + + buffer->retain(); + AX_SAFE_RELEASE(_indexBuffer); + _indexBuffer = static_cast(buffer); +} + +void CommandBufferImpl::setInstanceBuffer(Buffer* buffer) +{ + assert(buffer != nullptr); + if (buffer == nullptr || _instanceBuffer == buffer) + return; + + buffer->retain(); + AX_SAFE_RELEASE(_instanceBuffer); + _instanceBuffer = static_cast(buffer); +} + +void CommandBufferImpl::drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe) +{ + prepareDrawing(); + auto context = _driverImpl->getContext(); + context->IASetPrimitiveTopology(toD3DPrimitiveTopology(primitiveType, wireframe)); + context->Draw(static_cast(count), static_cast(start)); +} + +void CommandBufferImpl::drawArraysInstanced(PrimitiveType primitiveType, + std::size_t start, + std::size_t count, + int instanceCount, + bool wireframe) +{ + prepareDrawing(); + auto context = _driverImpl->getContext(); + context->IASetPrimitiveTopology(toD3DPrimitiveTopology(primitiveType, wireframe)); + context->DrawInstanced(static_cast(count), static_cast(instanceCount), static_cast(start), 0); +} + +void CommandBufferImpl::drawElements(PrimitiveType primitiveType, + IndexFormat indexType, + std::size_t count, + std::size_t offset, + bool wireframe) +{ + prepareDrawing(); + + const DXGI_FORMAT dxgiFmt = (indexType == IndexFormat::U_SHORT) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + const UINT indexSize = (indexType == IndexFormat::U_SHORT) ? 2u : 4u; + + assert((offset % indexSize) == 0); + + const UINT startIndex = static_cast(offset / indexSize); + const UINT indexCount = static_cast(count); + + auto context = _driverImpl->getContext(); + + context->IASetIndexBuffer(_indexBuffer->internalHandle(), dxgiFmt, 0); + + context->IASetPrimitiveTopology(toD3DPrimitiveTopology(primitiveType, wireframe)); + + context->DrawIndexed(indexCount, startIndex, 0); +} + +void CommandBufferImpl::drawElementsInstanced(PrimitiveType primitiveType, + IndexFormat indexType, + std::size_t count, + std::size_t offset, + int instanceCount, + bool wireframe) +{ + prepareDrawing(); + + const DXGI_FORMAT dxgiFmt = (indexType == IndexFormat::U_SHORT) ? DXGI_FORMAT_R16_UINT : DXGI_FORMAT_R32_UINT; + const UINT indexSize = (indexType == IndexFormat::U_SHORT) ? 2u : 4u; + + assert((offset % indexSize) == 0); + + const UINT startIndex = static_cast(offset / indexSize); + const UINT indexCount = static_cast(count); + + auto context = _driverImpl->getContext(); + context->IASetIndexBuffer(_indexBuffer->internalHandle(), dxgiFmt, 0); + + context->IASetPrimitiveTopology(toD3DPrimitiveTopology(primitiveType, wireframe)); + context->DrawIndexedInstanced(static_cast(count), static_cast(instanceCount), startIndex, 0, 0); +} + +void CommandBufferImpl::endRenderPass() +{ + AX_SAFE_RELEASE_NULL(_programState); + AX_SAFE_RELEASE_NULL(_indexBuffer); + AX_SAFE_RELEASE_NULL(_vertexBuffer); + AX_SAFE_RELEASE_NULL(_instanceBuffer); + + // clean bound SRVs to resolve: D3D11 WARNING: ID3D11DeviceContext::OMSetRenderTargets: Resource being set to OM RenderTarget slot 0 is still bound on input! + if (_textureBounds) { + _nullSRVs.resize(_textureBounds, nullptr); + _driverImpl->getContext()->PSSetShaderResources(0, _textureBounds, _nullSRVs.data()); + _textureBounds = 0; + } +} + +void CommandBufferImpl::prepareDrawing() +{ + assert(_programState); + updateRasterizerState(); + + auto context = _driverImpl->getContext(); + + auto& callbackUniforms = _programState->getCallbackUniforms(); + for (auto& cb : callbackUniforms) + cb.second(_programState, cb.first); + + // bind shader + auto program = static_cast(_programState->getProgram()); + context->VSSetShader(static_cast(program->getVertexShader()->internalHandle()), nullptr, 0); + context->PSSetShader(static_cast(program->getFragmentShader()->internalHandle()), nullptr, 0); + + // bind vertex layout + auto vertexLayout = static_cast(_programState->getVertexLayout()); + vertexLayout->apply(context, program); + + // bind vertexBuffer + if (!_instanceBuffer) + { + ID3D11Buffer* vbs[] = {_vertexBuffer->internalHandle()}; + UINT strides[] = {static_cast(vertexLayout->getStride())}; + UINT offsets[] = {0}; + context->IASetVertexBuffers(0, 1, vbs, strides, offsets); + } + else + { + ID3D11Buffer* vbs[] = {_vertexBuffer->internalHandle(), _instanceBuffer->internalHandle()}; + UINT strides[] = {static_cast(vertexLayout->getStride()), + static_cast(vertexLayout->getInstanceStride())}; + UINT offsets[] = {0, 0}; + context->IASetVertexBuffers(0, 2, vbs, strides, offsets); + } + + // bind uniform buffer: glsl-optimizer is bound to index 1, axslcc: bound to 0 + constexpr int bindingIndex = DriverImpl::VBO_BINDING_INDEX_START; + std::size_t bufferSize = 0; + auto uniformBuffer = _programState->getVertexUniformBuffer(bufferSize); + if (bufferSize) + { + program->bindVertexUniformBuffer(context, uniformBuffer, bufferSize, bindingIndex); + } + + // bind fragmentBuffer + auto fragmentBuffer = _programState->getFragmentUniformBuffer(bufferSize); + if (bufferSize) + { + program->bindFragmentUniformBuffer(context, fragmentBuffer, bufferSize, bindingIndex); + } + + // bind texture + _textureBounds = 0; + const auto& textureInfo = _programState->getFragmentTextureInfos(); + for (const auto& texBinding : textureInfo) + { + auto texture = texBinding.second; + auto& slots = texBinding.second.slots; + + int i = 0; + for (const auto& texture : texture.textures) + { + auto textureImpl = static_cast(texture); + // static_cast(texture)->apply(slots[i], indexs[i]); + auto& textureHandle = textureImpl->internalHandle(i); + context->PSSetShaderResources(slots[i], 1, &textureHandle.srv); + auto samplerState = textureImpl->getSamplerState(); + context->PSSetSamplers(slots[i], 1, &samplerState); + ++i; + ++_textureBounds; + } + } + + // depth stencil + if (_depthStencilState->isEnabled()) + _depthStencilState->apply(context, _stencilReferenceValue); + else + _depthStencilState->reset(context); +} + +void CommandBufferImpl::endFrame() +{ + HRESULT hr = _swapChain->Present(1, 0 /*DXGI_PRESENT_DO_NOT_WAIT*/); + + if (FAILED(hr)) + { + if (hr == DXGI_ERROR_DEVICE_REMOVED) + { + auto device = static_cast(DriverBase::getInstance())->getDevice(); + HRESULT reason = device->GetDeviceRemovedReason(); + // AXLOGD("D3D11 Device remove reason: {}", reason); + } + } +} + +void CommandBufferImpl::readPixels(RenderTarget* rt, std::function callback) {} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/CommandBufferD3D.h b/axmol/rhi/d3d/CommandBufferD3D.h new file mode 100644 index 000000000000..e3435dfb6af4 --- /dev/null +++ b/axmol/rhi/d3d/CommandBufferD3D.h @@ -0,0 +1,253 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include "axmol/rhi/CommandBuffer.h" +#include "axmol/rhi/d3d/DriverD3D.h" +#include + +namespace ax::rhi::d3d +{ +using namespace Microsoft::WRL; +class BufferImpl; +class DepthStencilStateImpl; +class RenderPipelineImpl; +class RenderTargetImpl; + +enum RasterFlag +{ + RF_CULL_MODE = 1, + RF_WINDING = 1 << 1, + RF_SCISSOR = 1 << 2 +}; + +struct RasterStateDesc +{ + CullMode cullMode{CullMode::BACK}; + Winding winding{Winding::CLOCK_WISE}; + bool scissorEnable{FALSE}; + unsigned int dirtyFlags{0}; +}; + +/** + * @addtogroup _d3d + * @{ + */ + +/** + * @brief Store encoded commands for the GPU to execute. + * A command buffer stores encoded commands until the buffer is committed for execution by the GPU + */ +class CommandBufferImpl : public CommandBuffer +{ +public: + /// @name Constructor, Destructor and Initializers + /** + * @param driver The device for which MTLCommandQueue object was created. + */ + CommandBufferImpl(DriverImpl* driver, HWND hwnd); + ~CommandBufferImpl() override; + + bool resizeSwapChain(uint32_t width, uint32_t height) override; + + /** + * Set depthStencil status + * @param depthStencilState Specifies the depth and stencil status + */ + void setDepthStencilState(DepthStencilState* depthStencilState) override; + + /** + * Sets the current render pipeline state object once + * @param renderPipeline An object that contains the graphics functions and configuration state used in a render + * pass. + */ + void setRenderPipeline(RenderPipeline* renderPipeline) override; + + /// @name Setters & Getters + /** + * @brief Indicate the begining of a frame + * Wait until the inflight command buffer has completed its work. + * Then create MTLCommandBuffer and enqueue it to MTLCommandQueue. + * Then start schedule available MTLBuffer + */ + bool beginFrame() override; + + /** + * Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDesc. + * MTLRenderCommandEncoder is cached if current RenderPassDesc is identical to previous one. + * @param descriptor Specifies a group of render targets that hold the results of a render pass. + */ + void beginRenderPass(const RenderTarget* renderTarget, const RenderPassDesc& descriptor) override; + + /** + * Update depthStencil status, improvment: for metal backend cache it + * @param depthStencilState Specifies the depth and stencil status + */ + void updateDepthStencilState(const DepthStencilDesc& descriptor) override; + + /** + * Update render pipeline status + * Building a programmable pipeline involves an expensive evaluation of GPU state. + * So a new render pipeline object will be created only if it hasn't been created before. + * @param rt Specifies the render target. + * @param pipelineDesc Specifies the pipeline descriptor. + */ + void updatePipelineState(const RenderTarget* rt, const PipelineDesc& descriptor) override; + + /** + * Fixed-function state + * @param x The x coordinate of the upper-left corner of the viewport. + * @param y The y coordinate of the upper-left corner of the viewport. + * @param w The width of the viewport, in pixels. + * @param h The height of the viewport, in pixels. + */ + void setViewport(int x, int y, unsigned int w, unsigned int h) override; + + /** + * Fixed-function state + * @param mode Controls if primitives are culled when front facing, back facing, or not culled at all. + */ + void setCullMode(CullMode mode) override; + + /** + * Fixed-function state + * @param winding The winding order of front-facing primitives. + */ + void setWinding(Winding winding) override; + + /** + * Set a global buffer for all vertex shaders at the given bind point index 0. + * @param buffer The buffer to set in the buffer argument table. + */ + void setVertexBuffer(Buffer* buffer) override; + + /** + * Set the uniform data at a given vertex and fragment buffer binding point 1 + * Set a global texture for all vertex and fragment shaders at the given bind location. + * @param programState A programState object that hold the uniform and texture data. + */ + void setProgramState(ProgramState* programState) override; + + /** + * Set indexes when drawing primitives with index list + * @ buffer A buffer object that the device will read indexes from. + * @ see `drawElements(PrimitiveType primitiveType, IndexFormat indexType, unsigned int count, unsigned int offset)` + */ + void setIndexBuffer(Buffer* buffer) override; + + void setInstanceBuffer(Buffer* buffer) override; + + /** + * Draw primitives without an index list. + * @param primitiveType The type of primitives that elements are assembled into. + * @param start For each instance, the first index to draw + * @param count For each instance, the number of indexes to draw + * @see `drawElements(PrimitiveType primitiveType, IndexFormat indexType, unsigned int count, unsigned int offset)` + * + * TODO: Implement a wireframe mode for METAL devices. Refer to: https://forums.ogre3d.org/viewtopic.php?t=95089 + */ + void drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe) override; + void drawArraysInstanced(PrimitiveType primitiveType, + std::size_t start, + std::size_t count, + int instanceCount, + bool wireframe = false) override; + + /** + * Draw primitives with an index list. + * @param primitiveType The type of primitives that elements are assembled into. + * @param indexType The type if indexes, either 16 bit integer or 32 bit integer. + * @param count The number of indexes to read from the index buffer for each instance. + * @param offset Byte offset within indexBuffer to start reading indexes from. + * @see `setIndexBuffer(Buffer* buffer)` + * @see `drawArrays(PrimitiveType primitiveType, unsigned int start, unsigned int count)` + * + * TODO: Implement a wireframe mode for METAL devices. Refer to: https://forums.ogre3d.org/viewtopic.php?t=95089 + */ + void drawElements(PrimitiveType primitiveType, + IndexFormat indexType, + std::size_t count, + std::size_t offset, + bool wireframe) override; + + void drawElementsInstanced(PrimitiveType primitiveType, + IndexFormat indexType, + std::size_t count, + std::size_t offset, + int instanceCount, + bool wireframe = false) override; + + /** + * Do some resources release. + */ + void endRenderPass() override; + + /** + * Present a drawable and commit a command buffer so it can be executed as soon as possible. + */ + void endFrame() override; + + /** + * Fixed-function state + * @param x, y Specifies the lower left corner of the scissor box + * @param wdith Specifies the width of the scissor box + * @param height Specifies the height of the scissor box + */ + void setScissorRect(bool isEnabled, float x, float y, float width, float height) override; + + /** + * Read pixels from RenderTarget + * @param callback A callback to deal with pixel data read. + */ + void readPixels(RenderTarget* rt, std::function callback) override; + +protected: + void updateRasterizerState(); + + void prepareDrawing(); + + DriverImpl* _driverImpl{nullptr}; + IDXGISwapChain* _swapChain{nullptr}; + ID3D11Texture2D* _depthStencilTexture {nullptr}; + ComPtr _rasterState{nullptr}; + RasterStateDesc _rasterDesc{}; + ProgramState* _programState{nullptr}; + BufferImpl* _vertexBuffer{nullptr}; + BufferImpl* _indexBuffer{nullptr}; + BufferImpl* _instanceBuffer{nullptr}; + DepthStencilStateImpl* _depthStencilState{nullptr}; + RenderPipelineImpl* _renderPipeline{nullptr}; + UINT _renderTargetWidth{0}; + UINT _renderTargetHeight{0}; + UINT _screenWidth{0}; + UINT _screenHeight{0}; + RenderPassDesc _renderPassDesc{}; + + axstd::pod_vector _nullSRVs; + UINT _textureBounds{0}; +}; + +// end of _metal group +/// @} +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/DepthStencilStateD3D.cpp b/axmol/rhi/d3d/DepthStencilStateD3D.cpp new file mode 100644 index 000000000000..5b1f3bd59a4a --- /dev/null +++ b/axmol/rhi/d3d/DepthStencilStateD3D.cpp @@ -0,0 +1,147 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/DepthStencilStateD3D.h" +#include +#include + +namespace ax::rhi::d3d +{ +namespace +{ +static D3D11_COMPARISON_FUNC to_d3d(CompareFunc func) +{ + switch (func) + { + case CompareFunc::NEVER: + return D3D11_COMPARISON_NEVER; + case CompareFunc::LESS: + return D3D11_COMPARISON_LESS; + case CompareFunc::LESS_EQUAL: + return D3D11_COMPARISON_LESS_EQUAL; + case CompareFunc::GREATER: + return D3D11_COMPARISON_GREATER; + case CompareFunc::GREATER_EQUAL: + return D3D11_COMPARISON_GREATER_EQUAL; + case CompareFunc::EQUAL: + return D3D11_COMPARISON_EQUAL; + case CompareFunc::NOT_EQUAL: + return D3D11_COMPARISON_NOT_EQUAL; + case CompareFunc::ALWAYS: + return D3D11_COMPARISON_ALWAYS; + default: + return D3D11_COMPARISON_LESS_EQUAL; + } +} + +static D3D11_STENCIL_OP to_d3d(StencilOp op) +{ + switch (op) + { + case StencilOp::KEEP: + return D3D11_STENCIL_OP_KEEP; + case StencilOp::ZERO: + return D3D11_STENCIL_OP_ZERO; + case StencilOp::REPLACE: + return D3D11_STENCIL_OP_REPLACE; + case StencilOp::INVERT: + return D3D11_STENCIL_OP_INVERT; + case StencilOp::INCREMENT_WRAP: + return D3D11_STENCIL_OP_INCR; + case StencilOp::DECREMENT_WRAP: + return D3D11_STENCIL_OP_DECR; + default: + return D3D11_STENCIL_OP_KEEP; + } +} + +static D3D11_DEPTH_STENCILOP_DESC make_op_desc(const StencilDesc& s) +{ + D3D11_DEPTH_STENCILOP_DESC d{}; + d.StencilFailOp = to_d3d(s.stencilFailureOp); + d.StencilDepthFailOp = to_d3d(s.depthFailureOp); + d.StencilPassOp = to_d3d(s.depthStencilPassOp); + d.StencilFunc = to_d3d(s.stencilCompareFunc); + return d; +} +} // namespace + +void DepthStencilStateImpl::update(const DepthStencilDesc& desc) +{ + if (_state && memcmp(&desc, &_dsDesc, sizeof(desc)) == 0) + { + return; + } + + DepthStencilState::update(desc); + + D3D11_DEPTH_STENCIL_DESC d{}; + + d.DepthEnable = bitmask::any(desc.flags, DepthStencilFlags::DEPTH_TEST) ? TRUE : FALSE; + d.DepthWriteMask = bitmask::any(desc.flags, DepthStencilFlags::DEPTH_WRITE) ? D3D11_DEPTH_WRITE_MASK_ALL + : D3D11_DEPTH_WRITE_MASK_ZERO; + d.DepthFunc = to_d3d(desc.depthCompareFunc); + + d.StencilEnable = bitmask::any(desc.flags, DepthStencilFlags::STENCIL_TEST) ? TRUE : FALSE; + d.StencilReadMask = desc.frontFaceStencil.readMask; + d.StencilWriteMask = desc.frontFaceStencil.writeMask; + d.FrontFace = make_op_desc(desc.frontFaceStencil); + d.BackFace = make_op_desc(desc.backFaceStencil); + + Microsoft::WRL::ComPtr newState; + HRESULT hr = _device->CreateDepthStencilState(&d, newState.GetAddressOf()); + if (FAILED(hr)) + { + throw std::runtime_error("CreateDepthStencilState failed"); + } + + _state = std::move(newState); + _dsDesc = desc; + _isBackFrontStencilEqual = + (std::memcmp(&desc.frontFaceStencil, &desc.backFaceStencil, sizeof(StencilDesc)) == 0); +} + +void DepthStencilStateImpl::apply(ID3D11DeviceContext* ctx, UINT stencilRef) const +{ + if (ctx && _state) + ctx->OMSetDepthStencilState(_state.Get(), stencilRef); +} + +void DepthStencilStateImpl::reset(ID3D11DeviceContext* ctx) +{ + if (!_disableState) + { + D3D11_DEPTH_STENCIL_DESC dsDesc = {}; + dsDesc.DepthEnable = FALSE; + dsDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ZERO; + dsDesc.DepthFunc = D3D11_COMPARISON_ALWAYS; + + dsDesc.StencilEnable = FALSE; + + _device->CreateDepthStencilState(&dsDesc, _disableState.GetAddressOf()); + } + + if (_disableState) + ctx->OMSetDepthStencilState(_disableState.Get(), 0); +} +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/DepthStencilStateD3D.h b/axmol/rhi/d3d/DepthStencilStateD3D.h new file mode 100644 index 000000000000..4f69c82801b9 --- /dev/null +++ b/axmol/rhi/d3d/DepthStencilStateD3D.h @@ -0,0 +1,51 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once +#include +#include +#include "axmol/rhi/DepthStencilState.h" + +namespace ax::rhi::d3d +{ +using namespace Microsoft::WRL; +class DepthStencilStateImpl : public DepthStencilState +{ +public: + explicit DepthStencilStateImpl(ID3D11Device* device) : _device(device) {} + + void update(const DepthStencilDesc& desc) override; + + void apply(ID3D11DeviceContext* ctx, UINT stencilRef = 0) const; + + void reset(ID3D11DeviceContext* ctx); + + ID3D11DepthStencilState* internalHandle() const { return _state.Get(); } + +private: + ID3D11Device* _device = nullptr; // weak ref + ComPtr _state; + + ComPtr _disableState; +}; +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/DriverD3D.cpp b/axmol/rhi/d3d/DriverD3D.cpp new file mode 100644 index 000000000000..2ae8aed46d5e --- /dev/null +++ b/axmol/rhi/d3d/DriverD3D.cpp @@ -0,0 +1,487 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/DriverD3D.h" +#include "axmol/rhi/d3d/CommandBufferD3D.h" +#include "axmol/rhi/d3d/BufferD3D.h" +#include "axmol/rhi/d3d/TextureD3D.h" +#include "axmol/rhi/d3d/ProgramD3D.h" +#include "axmol/rhi/d3d/ShaderModuleD3D.h" +#include "axmol/rhi/d3d/RenderTargetD3D.h" +#include "axmol/rhi/d3d/RenderPipelineD3D.h" +#include "axmol/rhi/d3d/DepthStencilStateD3D.h" +#include "axmol/rhi/d3d/VertexLayoutD3D.h" +#include "axmol/base/Logging.h" +#include "ntcvt/ntcvt.hpp" + +#include + +#pragma comment(lib, "D3D11.lib") + +namespace ax::rhi +{ +enum VendorID : uint32_t +{ + VENDOR_ID_UNKNOWN = 0x0, + VENDOR_ID_AMD = 0x1002, + VENDOR_ID_APPLE = 0x106B, + VENDOR_ID_ARM = 0x13B5, + // Broadcom devices won't use PCI, but this is their Vulkan vendor id. + VENDOR_ID_BROADCOM = 0x14E4, + VENDOR_ID_GOOGLE = 0x1AE0, + VENDOR_ID_INTEL = 0x8086, + VENDOR_ID_MESA = 0x10005, + VENDOR_ID_MICROSOFT = 0x1414, + VENDOR_ID_NVIDIA = 0x10DE, + VENDOR_ID_POWERVR = 0x1010, + // This is Qualcomm PCI Vendor ID. + // Android doesn't have a PCI bus, but all we need is a unique id. + VENDOR_ID_QUALCOMM = 0x5143, + VENDOR_ID_SAMSUNG = 0x144D, + VENDOR_ID_VIVANTE = 0x9999, + VENDOR_ID_VMWARE = 0x15AD, + VENDOR_ID_VIRTIO = 0x1AF4, +}; + +std::string_view GetVendorString(uint32_t vendorId) +{ + switch (vendorId) + { + case VENDOR_ID_AMD: + return "AMD"sv; + case VENDOR_ID_ARM: + return "ARM"sv; + case VENDOR_ID_APPLE: + return "Apple"sv; + case VENDOR_ID_BROADCOM: + return "Broadcom"sv; + case VENDOR_ID_GOOGLE: + return "Google"sv; + case VENDOR_ID_INTEL: + return "Intel"sv; + case VENDOR_ID_MESA: + return "Mesa"sv; + case VENDOR_ID_MICROSOFT: + return "Microsoft"sv; + case VENDOR_ID_NVIDIA: + return "NVIDIA"sv; + case VENDOR_ID_POWERVR: + return "Imagination Technologies"sv; + case VENDOR_ID_QUALCOMM: + return "Qualcomm"sv; + case VENDOR_ID_SAMSUNG: + return "Samsung Electronics Co., Ltd."sv; + case VENDOR_ID_VIVANTE: + return "Vivante"sv; + case VENDOR_ID_VMWARE: + return "VMware"sv; + case VENDOR_ID_VIRTIO: + return "VirtIO"sv; + case 0: + return "NULL"sv; + default: + // TODO(jmadill): More vendor IDs. + // UNIMPLEMENTED(); + return "Unknown"; + } +} + +DriverBase* DriverBase::getInstance() +{ + if (!_instance) + _instance = new d3d::DriverImpl(); + + return _instance; +} + +void DriverBase::destroyInstance() +{ + AX_SAFE_DELETE(_instance); +} +} // namespace ax::rhi + +namespace ax::rhi::d3d +{ +namespace +{ + +static int32_t EstimateMaxTexSize(D3D_FEATURE_LEVEL fl) +{ + switch (fl) + { + case D3D_FEATURE_LEVEL_12_1: + case D3D_FEATURE_LEVEL_12_0: + case D3D_FEATURE_LEVEL_11_1: + case D3D_FEATURE_LEVEL_11_0: + return 16384; // guaranteed + case D3D_FEATURE_LEVEL_10_1: + case D3D_FEATURE_LEVEL_10_0: + return 8192; + case D3D_FEATURE_LEVEL_9_3: + return 4096; + default: + return 2048; // Oldest device + } +} + +// iterating 1,2,4,8,16,32,64 to find max samples +static uint32_t FindMaxMsaaSamples(ID3D11Device* device, DXGI_FORMAT format) +{ + uint32_t best = 1; + for (uint32_t s = 2; s <= D3D11_MAX_MULTISAMPLE_SAMPLE_COUNT; s <<= 1) + { + UINT quality = 0; + if (SUCCEEDED(device->CheckMultisampleQualityLevels(format, s, &quality)) && quality > 0) + { + best = s; + } + } + return best; +} +} // namespace + +DriverImpl::DriverImpl() +{ +#if 0 // TODO: enum adapter + Microsoft::WRL::ComPtr factory; + CreateDXGIFactory(__uuidof(IDXGIFactory), (void**)&factory); + + UINT i = 0; + Microsoft::WRL::ComPtr adapter; + while (factory->EnumAdapters(i, adapter.ReleaseAndGetAddressOf()) != DXGI_ERROR_NOT_FOUND) + { + DXGI_ADAPTER_DESC desc; + adapter->GetDesc(&desc); + + // std::wcout << L"Adapter " << i << L": " << desc.Description << std::endl; + + // select best adapter + ++i; + } +#endif + + UINT createDeviceFlags = 0; + +#if defined(_DEBUG) + createDeviceFlags |= D3D11_CREATE_DEVICE_DEBUG; +#endif + + D3D_FEATURE_LEVEL featureLevels[] = { + D3D_FEATURE_LEVEL_11_1, + D3D_FEATURE_LEVEL_11_0, + }; + + auto requestDriverType = D3D_DRIVER_TYPE_HARDWARE; + HRESULT hr = D3D11CreateDevice(nullptr, // Adapter + requestDriverType, // Driver Type + nullptr, // Software + createDeviceFlags, // Flags + featureLevels, // Feature Levels + ARRAYSIZE(featureLevels), // Num Feature Levels + D3D11_SDK_VERSION, // SDK Version + &_device, // Device + &_featureLevel, // Feature Level + &_context); + if (hr == DXGI_ERROR_UNSUPPORTED) + { + // Try again with software driver type + requestDriverType = D3D_DRIVER_TYPE_WARP; + hr = D3D11CreateDevice(nullptr, // Adapter + requestDriverType, // Driver Type + nullptr, // Software + createDeviceFlags, // Flags + featureLevels, // Feature Levels + ARRAYSIZE(featureLevels), // Num Feature Levels + D3D11_SDK_VERSION, // SDK Version + &_device, // Device + &_featureLevel, // Feature Level + &_context); + } + if (FAILED(hr)) + { + AXLOGE("Failed to create D3D11 device."); + } + + Microsoft::WRL::ComPtr dxgiDevice; + _device->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast(dxgiDevice.GetAddressOf())); + + Microsoft::WRL::ComPtr dxgiAdapter; + dxgiDevice->GetAdapter(&dxgiAdapter); + + dxgiAdapter->GetDesc(&_adapterDesc); + + LARGE_INTEGER version; + hr = dxgiAdapter->CheckInterfaceSupport(__uuidof(IDXGIDevice), &version); + if (FAILED(hr)) + { + _driverVersion.reset(); + AXLOGE("Error querying driver version from DXGI Adapter."); + } + else + { + _driverVersion = version; + } + // _maxAttributes = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; + // _maxTextureSize = 16384; + // _maxTextureUnits = D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; + // _maxSamplesAllowed = 1; + + _maxAttributes = D3D11_IA_VERTEX_INPUT_RESOURCE_SLOT_COUNT; // 16 + + _maxTextureUnits = D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT; // 128 + + _maxTextureSize = EstimateMaxTexSize(_device->GetFeatureLevel()); + + _maxSamplesAllowed = static_cast(FindMaxMsaaSamples(_device, DXGI_FORMAT_R8G8B8A8_UNORM)); +} + +DriverImpl::~DriverImpl() +{ + SafeRelease(_context); + SafeRelease(_device); +} + +CommandBuffer* DriverImpl::createCommandBuffer(void* hwnd) +{ + return new CommandBufferImpl(this, (HWND)hwnd); +} + +Buffer* DriverImpl::createBuffer(std::size_t size, BufferType type, BufferUsage usage) +{ + return new BufferImpl(_device, _context, size, type, usage); +} + +/** + * New a Texture object. + * @param descriptor Specifies texture description. + * @return A Texture object. + */ +Texture* DriverImpl::createTexture(const TextureDesc& descriptor) +{ + return new TextureImpl(_device, descriptor); +} + +RenderTarget* DriverImpl::createDefaultRenderTarget() +{ + return new RenderTargetImpl(_device, true); +} + +RenderTarget* DriverImpl::createRenderTarget(Texture* colorAttachment, Texture* depthAttachment) +{ + auto renderTarget = new RenderTargetImpl(_device, false); + RenderTarget::ColorAttachment colors{{colorAttachment, 0}}; + renderTarget->setColorAttachment(colors); + renderTarget->setDepthStencilAttachment(depthAttachment); + return renderTarget; +} + +/** + * New a DepthStencilState object. + */ +DepthStencilState* DriverImpl::createDepthStencilState() +{ + return new DepthStencilStateImpl(_device); +} + +/** + * New a RenderPipeline object. + * @param descriptor Specifies render pipeline description. + * @return A RenderPipeline object. + */ +RenderPipeline* DriverImpl::createRenderPipeline() +{ + return new RenderPipelineImpl(_device, _context); +} + +/** + * This property controls whether or not the drawables' + * MTLTextures may only be used for framebuffer attachments (YES) or + * whether they may also be used for texture sampling and pixel + * read/write operations (NO). + * @param frameBufferOnly A value of YES allows CAMetalLayer to allocate the MTLTexture objects in ways that are + * optimized for display purposes that makes them unsuitable for sampling. The recommended value for most + * applications is YES. + */ +void DriverImpl::setFrameBufferOnly(bool frameBufferOnly) {} + +Program* DriverImpl::createProgram(std::string_view vertexShader, std::string_view fragmentShader) +{ + return new ProgramImpl(vertexShader, fragmentShader); +} + +ShaderModule* DriverImpl::createShaderModule(ShaderStage stage, std::string_view source) +{ + return new ShaderModuleImpl(_device, stage, source); +} + +SamplerHandle DriverImpl::createSampler(const SamplerDesc& desc) +{ + D3D11_SAMPLER_DESC sd = {}; + + // --- Filter --- + if (desc.minFilter == SamplerFilter::MIN_ANISOTROPIC) + { + sd.Filter = D3D11_FILTER_ANISOTROPIC; + sd.MaxAnisotropy = desc.anisotropy ? desc.anisotropy : 1; + } + else + { + const int minL = static_cast(desc.minFilter) & 1; + const int magL = static_cast(desc.magFilter) & 1; + const int mipL = static_cast(desc.mipFilter) & 1; + + if (!minL && !magL && !mipL) + sd.Filter = D3D11_FILTER_MIN_MAG_MIP_POINT; + else if (!minL && !magL && mipL) + sd.Filter = D3D11_FILTER_MIN_MAG_POINT_MIP_LINEAR; + else if (!minL && magL && !mipL) + sd.Filter = D3D11_FILTER_MIN_POINT_MAG_LINEAR_MIP_POINT; + else if (!minL && magL && mipL) + sd.Filter = D3D11_FILTER_MIN_POINT_MAG_MIP_LINEAR; + else if (minL && !magL && !mipL) + sd.Filter = D3D11_FILTER_MIN_LINEAR_MAG_MIP_POINT; + else if (minL && !magL && mipL) + sd.Filter = D3D11_FILTER_MIN_LINEAR_MAG_POINT_MIP_LINEAR; + else if (minL && magL && !mipL) + sd.Filter = D3D11_FILTER_MIN_MAG_LINEAR_MIP_POINT; + else + sd.Filter = D3D11_FILTER_MIN_MAG_MIP_LINEAR; + + sd.MaxAnisotropy = 1; + } + + // --- Wrap --- + static const D3D11_TEXTURE_ADDRESS_MODE wrapTbl[4] = { + D3D11_TEXTURE_ADDRESS_WRAP, // REPEAT + D3D11_TEXTURE_ADDRESS_MIRROR, // MIRROR + D3D11_TEXTURE_ADDRESS_CLAMP, // CLAMP + D3D11_TEXTURE_ADDRESS_BORDER // BORDER + }; + sd.AddressU = wrapTbl[static_cast(desc.sAddressMode)]; + sd.AddressV = wrapTbl[static_cast(desc.tAddressMode)]; + sd.AddressW = wrapTbl[static_cast(desc.wAddressMode)]; + + // --- Compare --- + sd.ComparisonFunc = static_cast(D3D11_COMPARISON_NEVER + static_cast(desc.compareFunc)); + + sd.MinLOD = 0; + sd.MaxLOD = D3D11_FLOAT32_MAX; + + ID3D11SamplerState* sampler{nullptr}; + _device->CreateSamplerState(&sd, &sampler); + return sampler; +} + +void DriverImpl::destroySampler(SamplerHandle& h) { + + SafeRelease(reinterpret_cast(h)); +} + +VertexLayout* DriverImpl::createVertexLayout() +{ + return new VertexLayoutImpl(); +} + +/// below is driver info + +/// @name Setters & Getters +/** + * Get vendor device name. + * @return Vendor device name. + */ +std::string DriverImpl::getVendor() const +{ + return std::string{GetVendorString(_adapterDesc.VendorId)}; +} + +/** + * Get the full name of the vendor device. + * @return The full name of the vendor device. + */ +std::string DriverImpl::getRenderer() const +{ + auto desc = ntcvt::from_chars(_adapterDesc.Description); + return fmt::format("{} D3D11 vs_5_0 ps_5_0", desc); +} + +/** + * Get featureSet name. + * @return FeatureSet name. + */ +std::string DriverImpl::getVersion() const +{ + if (_driverVersion.has_value()) + { + uint64_t intVersion = static_cast(_driverVersion->QuadPart); + constexpr uint64_t kMask16 = std::numeric_limits::max(); + + return fmt::format("D3D11-{}.{}.{}.{}", (intVersion >> 48) & kMask16, (intVersion >> 32) & kMask16, + (intVersion >> 16) & kMask16, intVersion & kMask16); + } + else + { + return "D3D11"s; + } +} + +std::string DriverImpl::getShaderVersion() const +{ + return "D3D11 HLSL vs_5_0 ps_5_0"s; +} + +/** + * Check if feature supported by Metal. + * @param feature Specify feature to be query. + * @return true if the feature is supported, false otherwise. + */ +bool DriverImpl::checkForFeatureSupported(FeatureType feature) +{ + // enum class FeatureType : uint32_t + // { + // ETC1, + // ETC2, + // S3TC, + // AMD_COMPRESSED_ATC, + // PVRTC, + // IMG_FORMAT_BGRA8888, + // DISCARD_FRAMEBUFFER, + // PACKED_DEPTH_STENCIL, + // VAO, + // MAPBUFFER, + // DEPTH24, + // ASTC + // }; + + switch (feature) + { + case FeatureType::DEPTH24: + case FeatureType::VAO: + case FeatureType::PACKED_DEPTH_STENCIL: + case FeatureType::IMG_FORMAT_BGRA8888: + case FeatureType::S3TC: + return true; + } + return false; +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/DriverD3D.h b/axmol/rhi/d3d/DriverD3D.h new file mode 100644 index 000000000000..bfb20b4aaaa9 --- /dev/null +++ b/axmol/rhi/d3d/DriverD3D.h @@ -0,0 +1,190 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include "axmol/rhi/DriverBase.h" +#include +#include + +namespace ax::rhi::d3d { + +/** + * @addtogroup _d3d + * @{ + */ + +/** + * Create resources from MTLDevice. + */ +class DriverImpl : public DriverBase +{ +public: + /* The max vertex attribs, it's not how many device supports which may be lower. */ + static constexpr uint32_t MAX_VERTEX_ATTRIBS = 16; + + /* The vertex data buffers binding index start, the axslcc(SPIRV-Cross), default UBO binding index is 0, + scope is per stage in MSL + */ + static constexpr uint32_t VBO_BINDING_INDEX_START = 0; + + /* The vertex instancing buffer binding index */ + static constexpr uint32_t VBO_INSTANCING_BINDING_INDEX = VBO_BINDING_INDEX_START + 1; + + /* The default attribs binding index */ + static constexpr uint32_t DEFAULT_ATTRIBS_BINDING_INDEX = VBO_BINDING_INDEX_START + MAX_VERTEX_ATTRIBS; + + /// @name Constructor, Destructor and Initializers + DriverImpl(); + ~DriverImpl(); + + /// @name Setters & Getters + /** + * Create a CommandBuffer object. + * @return A CommandBuffer object. + */ + CommandBuffer* createCommandBuffer(void*) override; + + /** + * Create a Buffer object. + * @param size Specifies the size in bytes of the buffer object's new data store. + * @param type Specifies the target buffer object. The symbolic constant must be BufferType::VERTEX or + * BufferType::INDEX. + * @param usage Specifies the expected usage pattern of the data store. The symbolic constant must be + * BufferUsage::STATIC, BufferUsage::DYNAMIC. + * @return A Buffer object. + */ + Buffer* createBuffer(std::size_t size, BufferType type, BufferUsage usage) override; + + /** + * Create a Texture object. + * @param descriptor Specifies texture description. + * @return A Texture object. + */ + Texture* createTexture(const TextureDesc& descriptor) override; + + RenderTarget* createDefaultRenderTarget() override; + RenderTarget* createRenderTarget(Texture* colorAttachment, + Texture* depthStencilAttachment) override; + + /** + * Create a DepthStencilState object. + */ + DepthStencilState* createDepthStencilState() override; + + /** + * Create a RenderPipeline object. + * @param descriptor Specifies render pipeline description. + * @return A RenderPipeline object. + */ + RenderPipeline* createRenderPipeline() override; + + /** + * This property controls whether or not the drawables' + * MTLTextures may only be used for framebuffer attachments (YES) or + * whether they may also be used for texture sampling and pixel + * read/write operations (NO). + * @param frameBufferOnly A value of YES allows CAMetalLayer to allocate the MTLTexture objects in ways that are + * optimized for display purposes that makes them unsuitable for sampling. The recommended value for most + * applications is YES. + */ + void setFrameBufferOnly(bool frameBufferOnly) override; + + /** + * Create a Program, not auto release. + * @param vertexShader Specifes this is a vertex shader source. + * @param fragmentShader Specifes this is a fragment shader source. + * @return A Program instance. + */ + Program* createProgram(std::string_view vertexShader, std::string_view fragmentShader) override; + + VertexLayout* createVertexLayout() override; + + /// below is driver info +\ + /// @name Setters & Getters + /** + * Get vendor device name. + * @return Vendor device name. + */ + std::string getVendor() const override; + + /** + * Get the full name of the vendor device. + * @return The full name of the vendor device. + */ + std::string getRenderer() const override; + + /** + * Get featureSet name. + * @return FeatureSet name. + */ + std::string getVersion() const override; + + std::string getShaderVersion() const override; + + D3D_FEATURE_LEVEL getFeatureLevel() const { return _featureLevel; } + + /** + * Check if feature supported by Metal. + * @param feature Specify feature to be query. + * @return true if the feature is supported, false otherwise. + */ + bool checkForFeatureSupported(FeatureType feature) override; + + + inline ID3D11Device* getDevice() const { return _device; } + + inline ID3D11DeviceContext* getContext() const { return _context; } + + static bool supportD24S8() { return _isDepth24Stencil8PixelFormatSupported; } + +protected: + /** + * Create a shaderModule. + * @param stage Specifies whether is vertex shader or fragment shader. + * @param source Specifies shader source. + * @return A ShaderModule object. + */ + ShaderModule* createShaderModule(ShaderStage stage, std::string_view source) override; + SamplerHandle createSampler(const SamplerDesc& desc) override; + void destroySampler(SamplerHandle& h) override; + +private: + + ID3D11Device* _device = nullptr; + ID3D11DeviceContext* _context = nullptr; + + DXGI_ADAPTER_DESC _adapterDesc; + + //FeatureSet _featureSet = FeatureSet::Unknown; + static bool _isDepth24Stencil8PixelFormatSupported; + + std::optional _driverVersion; + + D3D_FEATURE_LEVEL _featureLevel{}; +}; + +// end of _metal group +/// @} +} diff --git a/axmol/rhi/d3d/ProgramD3D.cpp b/axmol/rhi/d3d/ProgramD3D.cpp new file mode 100644 index 000000000000..7bbd1f8d8b56 --- /dev/null +++ b/axmol/rhi/d3d/ProgramD3D.cpp @@ -0,0 +1,146 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/ProgramD3D.h" +#include "axmol/rhi/d3d/BufferD3D.h" +#include "axmol/rhi/ShaderCache.h" + +namespace ax::rhi::d3d +{ +ProgramImpl::ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader) + : Program(vertexShader, fragmentShader) +{ + _vertexShader = static_cast(ShaderCache::getInstance()->acquireVertexShaderModule(_vsSource)); + _fragmentShader = + static_cast(ShaderCache::getInstance()->acquireFragmentShaderModule(_fsSource)); +} +ProgramImpl ::~ProgramImpl() +{ + AX_SAFE_RELEASE(_vertexShader); + AX_SAFE_RELEASE(_fragmentShader); + + AX_SAFE_RELEASE(_vsUniformBuffer); + AX_SAFE_RELEASE(_fsUniformBuffer); +} + +const VertexInputDesc* ProgramImpl::getVertexInputDesc(VertexInputKind name) const +{ + return _vertexShader->getVertexInputDesc(name); +} + +const VertexInputDesc* ProgramImpl::getVertexInputDesc(std::string_view name) const +{ + return _vertexShader->getVertexInputDesc(name); +} + +const hlookup::string_map& ProgramImpl::getActiveVertexInputs() const +{ + return _vertexShader->getActiveVertexInputs(); +} + +UniformLocation ProgramImpl::getUniformLocation(rhi::Uniform name) const +{ + auto& vert = _vertexShader->getUniformInfo(name); + auto& frag = _fragmentShader->getUniformInfo(name); + + return UniformLocation{{vert.location, vert.location == -1 ? -1 : static_cast(vert.bufferOffset)}, + {frag.location, frag.location == -1 ? -1 : static_cast(frag.bufferOffset)}}; +} + +UniformLocation ProgramImpl::getUniformLocation(std::string_view uniform) const +{ + auto& vert = _vertexShader->getUniformInfo(uniform); + auto& frag = _fragmentShader->getUniformInfo(uniform); + + if (vert.location != -1 && frag.location != -1) + AXASSERT(vert.type == frag.type && vert.count == frag.count && vert.size == frag.size, + "Same vertex and fragment uniform must much in type and size"); + + return UniformLocation{{vert.location, vert.location == -1 ? -1 : static_cast(vert.bufferOffset)}, + {frag.location, frag.location == -1 ? -1 : static_cast(frag.bufferOffset)}}; +} + +int ProgramImpl::getMaxVertexLocation() const +{ + return _vertexShader->getMaxLocation(); +} + +int ProgramImpl::getMaxFragmentLocation() const +{ + return _fragmentShader->getMaxLocation(); +} + +std::size_t ProgramImpl::getUniformBufferSize(ShaderStage stage) const +{ + switch (stage) + { + case ShaderStage::VERTEX: + return _vertexShader->getUniformBufferSize(); + case ShaderStage::FRAGMENT: + return _fragmentShader->getUniformBufferSize(); + default: + AXASSERT(false, "Invalid shader stage."); + break; + } + return 0; +} + +const hlookup::string_map& ProgramImpl::getActiveUniformInfos(ShaderStage stage) const +{ + return stage == ShaderStage::VERTEX ? _vertexShader->getActiveUniformInfos() + : _fragmentShader->getActiveUniformInfos(); +} + +ID3DBlob* ProgramImpl::getVSBlob() const +{ + return _vertexShader->getShaderBlob(); +} + +void ProgramImpl::bindVertexUniformBuffer(ID3D11DeviceContext* context, + const char* data, + size_t size, + UINT bindingIndex) +{ + if (!_vsUniformBuffer) + _vsUniformBuffer = static_cast( + DriverBase::getInstance()->createBuffer(size, BufferType::UNIFORM, BufferUsage::DYNAMIC)); + _vsUniformBuffer->updateData(data, size); + + ID3D11Buffer* vsUniformBuffer = static_cast(_vsUniformBuffer->internalHandle()); + context->VSSetConstantBuffers(bindingIndex, 1, &vsUniformBuffer); +} + +void ProgramImpl::bindFragmentUniformBuffer(ID3D11DeviceContext* context, + const char* data, + size_t size, + UINT bindingIndex) +{ + if (!_fsUniformBuffer) + _fsUniformBuffer = static_cast( + DriverBase::getInstance()->createBuffer(size, BufferType::UNIFORM, BufferUsage::DYNAMIC)); + _fsUniformBuffer->updateData(data, size); + + ID3D11Buffer* psUniformBuffer = static_cast(_fsUniformBuffer->internalHandle()); + context->PSSetConstantBuffers(bindingIndex, 1, &psUniformBuffer); +} +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/ProgramD3D.h b/axmol/rhi/d3d/ProgramD3D.h new file mode 100644 index 000000000000..d5dc04b0b8e4 --- /dev/null +++ b/axmol/rhi/d3d/ProgramD3D.h @@ -0,0 +1,127 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include "axmol/rhi/Program.h" + +#include "axmol/rhi/d3d/ShaderModuleD3D.h" + +namespace ax::rhi::d3d +{ +class BufferImpl; +class ProgramImpl : public Program +{ +public: + /// @name Constructor, Destructor and Initializers + /** + * @param vertexShader Specifes the vertex shader source. + * @param fragmentShader Specifes the fragment shader source. + */ + ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader); + ~ProgramImpl() override; + + /** + * Get uniform location by name. + * @param uniform Specifies the uniform name. + * @return The uniform location. + */ + UniformLocation getUniformLocation(std::string_view uniform) const override; + + /** + * Get uniform location by engine built-in uniform enum name. + * @param name Specifies the engine built-in uniform enum name. + * @return The uniform location. + */ + UniformLocation getUniformLocation(rhi::Uniform name) const override; + + /** + * Get attribute location by attribute name. + * @param name Specifies the attribute name. + * @return The attribute location. + */ + const VertexInputDesc* getVertexInputDesc(std::string_view name) const override; + + /** + * Get attribute location by engine built-in attribute enum name. + * @param name Specifies the engine built-in attribute enum name. + * @return The attribute location. + */ + const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const override; + + /** + * Get active vertex attributes. + * @return Active vertex attributes. key is active attribute name, Value is corresponding attribute info. + */ + const hlookup::string_map& getActiveVertexInputs() const override; + + /** + * Get vertex shader module. + * @return Vertex shader module. + */ + ShaderModuleImpl* getVertexShader() const { return _vertexShader; } + + /** + * Get fragment shader module. + * @ Fragment shader module. + */ + ShaderModuleImpl* getFragmentShader() const { return _fragmentShader; } + + /** + * Get maximum vertex location. + * @return Maximum vertex locaiton. + */ + int getMaxVertexLocation() const override; + + /** + * Get maximum fragment location. + * @return Maximum fragment location. + */ + int getMaxFragmentLocation() const override; + + /** + * Get uniform buffer size in bytes that can hold all the uniforms. + * @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT. + * @return The uniform buffer size in bytes. + */ + std::size_t getUniformBufferSize(ShaderStage stage) const override; + + /** + * Get all uniformInfos. + * @return The uniformInfos. + */ + const hlookup::string_map& getActiveUniformInfos(ShaderStage stage) const override; + + ID3DBlob* getVSBlob() const; + + void bindVertexUniformBuffer(ID3D11DeviceContext*, const char* data, size_t size, UINT bindingIndex); + void bindFragmentUniformBuffer(ID3D11DeviceContext*, const char* data, size_t size, UINT bindingIndex); + +private: + ShaderModuleImpl* _vertexShader = nullptr; + ShaderModuleImpl* _fragmentShader = nullptr; + + BufferImpl* _vsUniformBuffer{nullptr}; + BufferImpl* _fsUniformBuffer{nullptr}; +}; +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/RenderPipelineD3D.cpp b/axmol/rhi/d3d/RenderPipelineD3D.cpp new file mode 100644 index 000000000000..baf8d87d0e4b --- /dev/null +++ b/axmol/rhi/d3d/RenderPipelineD3D.cpp @@ -0,0 +1,266 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/RenderPipelineD3D.h" +#include "axmol/rhi/d3d/ProgramD3D.h" +#include "xxhash.h" + +namespace ax::rhi::d3d +{ +static D3D11_BLEND_OP toD3DBlendOp(BlendOp op) +{ + switch (op) + { + case BlendOp::ADD: + return D3D11_BLEND_OP_ADD; + case BlendOp::SUBTRACT: + return D3D11_BLEND_OP_SUBTRACT; + case BlendOp::REVERSE_SUBTRACT: + return D3D11_BLEND_OP_REV_SUBTRACT; + default: + return D3D11_BLEND_OP_ADD; + } +} + +static D3D11_BLEND toD3DBlendRGB(BlendFactor f) +{ + switch (f) + { + case BlendFactor::ZERO: + return D3D11_BLEND_ZERO; + case BlendFactor::ONE: + return D3D11_BLEND_ONE; + case BlendFactor::SRC_COLOR: + return D3D11_BLEND_SRC_COLOR; + case BlendFactor::ONE_MINUS_SRC_COLOR: + return D3D11_BLEND_INV_SRC_COLOR; + case BlendFactor::SRC_ALPHA: + return D3D11_BLEND_SRC_ALPHA; + case BlendFactor::ONE_MINUS_SRC_ALPHA: + return D3D11_BLEND_INV_SRC_ALPHA; + case BlendFactor::DST_COLOR: + return D3D11_BLEND_DEST_COLOR; + case BlendFactor::ONE_MINUS_DST_COLOR: + return D3D11_BLEND_INV_DEST_COLOR; + case BlendFactor::DST_ALPHA: + return D3D11_BLEND_DEST_ALPHA; + case BlendFactor::ONE_MINUS_DST_ALPHA: + return D3D11_BLEND_INV_DEST_ALPHA; + case BlendFactor::CONSTANT_ALPHA: + return D3D11_BLEND_BLEND_FACTOR; // same wiht BLEND_COLOR + case BlendFactor::SRC_ALPHA_SATURATE: + return D3D11_BLEND_SRC_ALPHA_SAT; + case BlendFactor::ONE_MINUS_CONSTANT_ALPHA: + return D3D11_BLEND_INV_BLEND_FACTOR; + case BlendFactor::BLEND_COLOR: + return D3D11_BLEND_BLEND_FACTOR; // blendColor.xyz + default: + return D3D11_BLEND_ONE; + } +} + +static D3D11_BLEND toD3DBlendAlpha(BlendFactor f) +{ + switch (f) + { + case BlendFactor::ZERO: + return D3D11_BLEND_ZERO; + case BlendFactor::ONE: + return D3D11_BLEND_ONE; + case BlendFactor::SRC_COLOR: + return D3D11_BLEND_SRC_ALPHA; + case BlendFactor::ONE_MINUS_SRC_COLOR: + return D3D11_BLEND_INV_SRC_ALPHA; + case BlendFactor::DST_COLOR: + return D3D11_BLEND_DEST_ALPHA; + case BlendFactor::ONE_MINUS_DST_COLOR: + return D3D11_BLEND_INV_DEST_ALPHA; + case BlendFactor::SRC_ALPHA: + return D3D11_BLEND_SRC_ALPHA; + case BlendFactor::ONE_MINUS_SRC_ALPHA: + return D3D11_BLEND_INV_SRC_ALPHA; + case BlendFactor::DST_ALPHA: + return D3D11_BLEND_DEST_ALPHA; + case BlendFactor::ONE_MINUS_DST_ALPHA: + return D3D11_BLEND_INV_DEST_ALPHA; + case BlendFactor::CONSTANT_ALPHA: + return D3D11_BLEND_BLEND_FACTOR; // blendColor.w + case BlendFactor::SRC_ALPHA_SATURATE: + return D3D11_BLEND_ONE; // alpha factor is one + case BlendFactor::ONE_MINUS_CONSTANT_ALPHA: + return D3D11_BLEND_INV_BLEND_FACTOR; // 1 - blendColor.w + case BlendFactor::BLEND_COLOR: + return D3D11_BLEND_BLEND_FACTOR; // Alpha = blendColor.w + default: + return D3D11_BLEND_ONE; + } +} + +static D3D11_BLEND toD3DBlend(BlendFactor factor) +{ + switch (factor) + { + case BlendFactor::ZERO: + return D3D11_BLEND_ZERO; + case BlendFactor::ONE: + return D3D11_BLEND_ONE; + case BlendFactor::SRC_COLOR: + return D3D11_BLEND_SRC_COLOR; + case BlendFactor::ONE_MINUS_SRC_COLOR: + return D3D11_BLEND_INV_SRC_COLOR; + case BlendFactor::SRC_ALPHA: + return D3D11_BLEND_SRC_ALPHA; + case BlendFactor::ONE_MINUS_SRC_ALPHA: + return D3D11_BLEND_INV_SRC_ALPHA; + case BlendFactor::DST_COLOR: + return D3D11_BLEND_DEST_COLOR; + case BlendFactor::ONE_MINUS_DST_COLOR: + return D3D11_BLEND_INV_DEST_COLOR; + case BlendFactor::DST_ALPHA: + return D3D11_BLEND_DEST_ALPHA; + case BlendFactor::ONE_MINUS_DST_ALPHA: + return D3D11_BLEND_INV_DEST_ALPHA; + case BlendFactor::CONSTANT_ALPHA: + return D3D11_BLEND_BLEND_FACTOR; + case BlendFactor::SRC_ALPHA_SATURATE: + return D3D11_BLEND_SRC_ALPHA_SAT; + case BlendFactor::ONE_MINUS_CONSTANT_ALPHA: + return D3D11_BLEND_INV_BLEND_FACTOR; + case BlendFactor::BLEND_COLOR: + return D3D11_BLEND_BLEND_FACTOR; + default: + return D3D11_BLEND_ONE; + } +} + +static UINT toD3DColorWriteMask(ColorWriteMask mask) +{ + UINT result = 0; + if (static_cast(mask) & static_cast(ColorWriteMask::RED)) + result |= D3D11_COLOR_WRITE_ENABLE_RED; + if (static_cast(mask) & static_cast(ColorWriteMask::GREEN)) + result |= D3D11_COLOR_WRITE_ENABLE_GREEN; + if (static_cast(mask) & static_cast(ColorWriteMask::BLUE)) + result |= D3D11_COLOR_WRITE_ENABLE_BLUE; + if (static_cast(mask) & static_cast(ColorWriteMask::ALPHA)) + result |= D3D11_COLOR_WRITE_ENABLE_ALPHA; + return result; +} + +static uint32_t hashBlendDesc(const BlendDesc& bd) +{ + struct PODBlend + { + uint32_t writeMask; + uint8_t blendEnabled; + uint8_t rgbBlendOp; + uint8_t alphaBlendOp; + uint8_t pad0; + uint8_t sourceRGBBlendFactor; + uint8_t destinationRGBBlendFactor; + uint8_t sourceAlphaBlendFactor; + uint8_t destinationAlphaBlendFactor; + uint32_t pad1; + } pod{static_cast(bd.writeMask), + static_cast(bd.blendEnabled), + static_cast(bd.rgbBlendOp), + static_cast(bd.alphaBlendOp), + 0, + static_cast(bd.sourceRGBBlendFactor), + static_cast(bd.destinationRGBBlendFactor), + static_cast(bd.sourceAlphaBlendFactor), + static_cast(bd.destinationAlphaBlendFactor), + 0}; + + return XXH32(&pod, sizeof(pod), 0); +} + +void RenderPipelineImpl::update(const RenderTarget*, const PipelineDesc& desc) +{ + ComPtr blendState; + + auto key = hashBlendDesc(desc.blendDesc); + auto it = _blendCache.find(key); + + if (it != _blendCache.end()) + { + blendState = it->second; + } + else + { + D3D11_BLEND_DESC bd{}; + + auto& bd0 = bd.RenderTarget[0]; + bd0.RenderTargetWriteMask = toD3DColorWriteMask(desc.blendDesc.writeMask); + + if (desc.blendDesc.blendEnabled) + { + bd0.BlendEnable = TRUE; + + bd0.SrcBlend = toD3DBlendRGB(desc.blendDesc.sourceRGBBlendFactor); + bd0.DestBlend = toD3DBlendRGB(desc.blendDesc.destinationRGBBlendFactor); + + bd0.SrcBlendAlpha = toD3DBlendAlpha(desc.blendDesc.sourceAlphaBlendFactor); + bd0.DestBlendAlpha = toD3DBlendAlpha(desc.blendDesc.destinationAlphaBlendFactor); + + bd0.BlendOp = toD3DBlendOp(desc.blendDesc.rgbBlendOp); + bd0.BlendOpAlpha = toD3DBlendOp(desc.blendDesc.alphaBlendOp); + } + else + { + bd0.BlendEnable = FALSE; + bd0.SrcBlend = D3D11_BLEND_ONE; + bd0.DestBlend = D3D11_BLEND_ZERO; + bd0.BlendOp = D3D11_BLEND_OP_ADD; + bd0.SrcBlendAlpha = D3D11_BLEND_ONE; + bd0.DestBlendAlpha = D3D11_BLEND_ZERO; + bd0.BlendOpAlpha = D3D11_BLEND_OP_ADD; + } + + if (SUCCEEDED(_device->CreateBlendState(&bd, &blendState))) + { + _blendCache.emplace(key, blendState); + } + else + { + AXLOGW("create blend state fail"); + } + } + + if (!blendState) + return; + + constexpr UINT sampleMask = 0xFFFFFFFF; + + if (desc.blendDesc.blendEnabled) + { + // axmol don't call glBlendColor, so the default blendFactor shoud be transparent + const FLOAT blendColor[4] = {0.0f, 0.0f, 0.0f, 0.0f}; + _context->OMSetBlendState(blendState.Get(), blendColor, sampleMask); + } + else + { + _context->OMSetBlendState(nullptr, nullptr, sampleMask); + } +} +} // namespace ax::rhi::d3d diff --git a/core/renderer/backend/Types.cpp b/axmol/rhi/d3d/RenderPipelineD3D.h similarity index 68% rename from core/renderer/backend/Types.cpp rename to axmol/rhi/d3d/RenderPipelineD3D.h index d13e554552b0..a0c3573d0e4f 100644 --- a/core/renderer/backend/Types.cpp +++ b/axmol/rhi/d3d/RenderPipelineD3D.h @@ -1,5 +1,4 @@ /**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -22,24 +21,25 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#pragma once -#include "Types.h" +#include "axmol/rhi/RenderPipeline.h" +#include +#include +using Microsoft::WRL::ComPtr; -NS_AX_BACKEND_BEGIN - -bool StageUniformLocation::operator==(const StageUniformLocation& other) const +namespace ax::rhi::d3d { - return location == other.location && offset == other.offset; -} - -bool UniformLocation::operator==(const UniformLocation& other) const +class RenderPipelineImpl : public RenderPipeline { - return vertStage == other.vertStage && fragStage == other.fragStage; -} +public: + RenderPipelineImpl(ID3D11Device* device, ID3D11DeviceContext* context) : _device(device), _context(context) {} + void update(const RenderTarget*, const PipelineDesc& desc) override; -std::size_t UniformLocation::operator()(const UniformLocation& uniform) const -{ - return size_t(vertStage.location) ^ size_t(fragStage.location << 16); -} + private: + ID3D11Device* _device = nullptr; + ID3D11DeviceContext* _context = nullptr; -NS_AX_BACKEND_END + tsl::robin_map> _blendCache; +}; +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/RenderTargetD3D.cpp b/axmol/rhi/d3d/RenderTargetD3D.cpp new file mode 100644 index 000000000000..ce202679c453 --- /dev/null +++ b/axmol/rhi/d3d/RenderTargetD3D.cpp @@ -0,0 +1,135 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/RenderTargetD3D.h" +#include "axmol/rhi/d3d/TextureD3D.h" +#include "axmol/rhi/d3d/UtilsD3D.h" + +namespace ax::rhi::d3d +{ +RenderTargetImpl::RenderTargetImpl(ID3D11Device* device, bool defaultRenderTarget) + : _device(device), RenderTarget(defaultRenderTarget) +{ + if (_defaultRenderTarget) + _dirtyFlags = TargetBufferFlags::ALL; +} + +RenderTargetImpl::~RenderTargetImpl() +{ + invalidate(); +} + +void RenderTargetImpl::invalidate() +{ + for (auto& rtv : _rtvs) + SafeRelease(rtv); + + SafeRelease(_dsv); + + if (_defaultRenderTarget) // release default render target attachments + UtilsD3D::updateDefaultRenderTargetAttachments(nullptr, nullptr); + + _dirtyFlags = TargetBufferFlags::ALL; +} + +void RenderTargetImpl::update(ID3D11DeviceContext* context) const +{ + if (!_dirtyFlags) + return; + + if (_defaultRenderTarget) + { + context->OMGetRenderTargets(1, &_rtvs[0], &_dsv); + } + else + { + if (bitmask::any(_dirtyFlags, TargetBufferFlags::COLOR_ALL)) + { // color attachments + for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; ++i) + { + auto textureInfo = _color[i]; + if (bitmask::any(_dirtyFlags, getMRTColorFlag(i))) + { + if (textureInfo.texture) + { + _device->CreateRenderTargetView( + static_cast(textureInfo.texture)->internalHandle().tex2d, nullptr, &_rtvs[i]); + } + else if (_rtvs[i]) + { + SafeRelease(_rtvs[i]); + } + } + } + } + + if (bitmask::any(_dirtyFlags, TargetBufferFlags::DEPTH_AND_STENCIL)) + { + if (_depthStencil) + { + auto fmtInfo = UtilsD3D::toDxgiFormatInfo(_depthStencil.texture->getTextureFormat()); + D3D11_DEPTH_STENCIL_VIEW_DESC desc{}; + desc.Format = fmtInfo->fmtDsv; + desc.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; + // desc.Flags = 0; + // desc.Texture2D.MipSlice = 0; + + _device->CreateDepthStencilView( + static_cast(_depthStencil.texture)->internalHandle().tex2d, &desc, &_dsv); + } + else if (_dsv) + SafeRelease(_dsv); + } + } + + _dirtyFlags = TargetBufferFlags::NONE; +} + +RenderTargetImpl::Attachment RenderTargetImpl::getColorAttachment(int index) const +{ + + auto textureImpl = + _defaultRenderTarget ? UtilsD3D::getDefaultColorAttachment() : static_cast(_color[index].texture); + return textureImpl + ? RenderTargetImpl::Attachment{static_cast(textureImpl->internalHandle().tex2d), + textureImpl->getDesc()} + : RenderTargetImpl::Attachment{}; +} + +RenderTargetImpl::Attachment RenderTargetImpl::getDepthStencilAttachment(int index) const +{ + auto textureImpl = + _defaultRenderTarget ? UtilsD3D::getDefaultColorAttachment() : static_cast(_depthStencil.texture); + + return textureImpl + ? RenderTargetImpl::Attachment{static_cast(textureImpl->internalHandle().tex2d), + textureImpl->getDesc()} + : RenderTargetImpl::Attachment{}; +} + +void RenderTargetImpl::apply(ID3D11DeviceContext* context) const +{ + context->OMSetRenderTargets(_rtvs.size(), _rtvs.data(), _dsv); +} + +} // namespace ax::rhi::d3d diff --git a/core/renderer/backend/opengl/CommandBufferGLES2.h b/axmol/rhi/d3d/RenderTargetD3D.h similarity index 59% rename from core/renderer/backend/opengl/CommandBufferGLES2.h rename to axmol/rhi/d3d/RenderTargetD3D.h index 0afcb3243d5f..9bedd71025cb 100644 --- a/core/renderer/backend/opengl/CommandBufferGLES2.h +++ b/axmol/rhi/d3d/RenderTargetD3D.h @@ -1,5 +1,4 @@ /**************************************************************************** - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -22,41 +21,40 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ +#pragma once - #pragma once - -#include "CommandBufferGL.h" +#include "axmol/rhi/RenderTarget.h" +#include +#include -#if !defined(__APPLE__) && AX_TARGET_PLATFORM != AX_PLATFORM_WINRT +namespace ax::rhi::d3d +{ -NS_AX_BACKEND_BEGIN +class RenderTargetImpl : public RenderTarget { +public: + struct Attachment + { + ID3D11Texture2D* texure; + TextureDesc desc; + }; + RenderTargetImpl(ID3D11Device* device, bool defaultRenderTarget); + ~RenderTargetImpl(); -/** - * @addtogroup _opengl - * @{ - */ + void invalidate(); -/** - * @brief Store encoded commands for the GPU to execute. - * A command buffer stores encoded commands until the buffer is committed for execution by the GPU - */ -class CommandBufferGLES2 : public CommandBufferGL -{ -public: - CommandBufferGLES2(); - void drawElementsInstanced(PrimitiveType primitiveType, - IndexFormat indexType, - std::size_t count, - std::size_t offset, - int instanceCount, - bool wireframe = false) override; + void update(ID3D11DeviceContext*) const; - void bindInstanceBuffer(ProgramGL* program, uint32_t& usedBits) const override; + void apply(ID3D11DeviceContext*) const; -}; + ID3D11RenderTargetView* getRTV(size_t idx) const { return _rtvs[idx]; } + ID3D11DepthStencilView* getDSV() const { return _dsv; } -// end of _opengl group -/// @} -NS_AX_BACKEND_END + Attachment getColorAttachment(int index) const; + Attachment getDepthStencilAttachment(int index) const; -#endif +private: + ID3D11Device* _device = nullptr; + mutable std::array _rtvs{}; + mutable ID3D11DepthStencilView* _dsv = nullptr; +}; +} diff --git a/axmol/rhi/d3d/ShaderModuleD3D.cpp b/axmol/rhi/d3d/ShaderModuleD3D.cpp new file mode 100644 index 000000000000..8072692a849e --- /dev/null +++ b/axmol/rhi/d3d/ShaderModuleD3D.cpp @@ -0,0 +1,369 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +// refer: https://learn.microsoft.com/en-us/windows/win32/direct3dhlsl/dx-graphics-hlsl-semantics +#include "axmol/rhi/d3d/ShaderModuleD3D.h" +#include +#include "axmol/base/Logging.h" +#include "yasio/ibstream.hpp" +#include "axmol/rhi/axslc-spec.h" + +#pragma comment(lib, "d3dcompiler.lib") +// #pragma comment(lib, "dxguid.lib") + +namespace ax::rhi::d3d +{ + +using namespace ::axslc; + +namespace +{ +// ShaderStage -> profile +inline const char* stageToProfile(ShaderStage s) +{ + switch (s) + { + case ShaderStage::VERTEX: + return "vs_5_0"; + case ShaderStage::FRAGMENT: + return "ps_5_0"; + default: + return "vs_5_0"; + } +} + +static inline std::string_view _sc_read_name(yasio::fast_ibstream_view* ibs) +{ + // view bytes without copy + std::string_view name = ibs->read_bytes(sizeof(sc_refl_input::name)); + auto len = name.find_last_not_of('\0'); + assert(len != std::string::npos); // name must not empty + name.remove_suffix(name.length() - len - 1); + return name; +} + +} // namespace + +struct SLCReflectContext +{ + sc_chunk_refl* refl; + yasio::fast_ibstream_view* ibs; +}; + +ShaderModuleImpl::ShaderModuleImpl(ID3D11Device* device, ShaderStage stage, std::string_view source) + : ShaderModule(stage) +{ + compileShader(device, stage, source); +} + +ShaderModuleImpl::~ShaderModuleImpl() +{ + releaseShader(); +} + +void ShaderModuleImpl::releaseShader() +{ + SafeRelease(_shader); + SafeRelease(_blob); +} + +void ShaderModuleImpl::compileShader(ID3D11Device* device, ShaderStage stage, std::string_view source) +{ + std::fill(std::begin(_builtinVertexInputs), std::end(_builtinVertexInputs), nullptr); + + _maxLocation = -1; + _uniformBufferSize = 0; + for (int i = 0; i < UNIFORM_COUNT; ++i) + _builtinUniforms[i] = {}; + + yasio::fast_ibstream_view ibs(source.data(), source.length()); + uint32_t fourccId = ibs.read(); + if (fourccId != SC_CHUNK) + { + assert(false); + return; + } + auto sc_size = ibs.read(); // always 0, doesn't matter + struct sc_chunk chunk; + ibs.read_bytes(&chunk, static_cast(sizeof(chunk))); + + std::string_view shaderSource; + + do + { + fourccId = ibs.read(); + if (fourccId != SC_CHUNK_STAG) + { + assert(false); + return; // error + } + auto stage_size = ibs.read(); // stage_size + auto stage_id = ibs.read(); // stage_id + ShaderStage ref_stage = (ShaderStage)-1; + if (stage_id == SC_STAGE_VERTEX) + ref_stage = ShaderStage::VERTEX; + else if (stage_id == SC_STAGE_FRAGMENT) + ref_stage = ShaderStage::FRAGMENT; + + assert(ref_stage == stage); + + fourccId = ibs.read(); + if (fourccId == SC_CHUNK_CODE) + { + shaderSource = ibs.read_bytes(ibs.read()); + } + else if (fourccId == SC_CHUNK_DATA) + { + shaderSource = ibs.read_bytes(ibs.read()); + } + else + { + // no text or binary code chunk + assert(false); + } + + if (!ibs.eof()) + { // try read reflect info + fourccId = ibs.read(); + if (fourccId == SC_CHUNK_REFL) + { + /* + REFL: Reflection data for the shader stage + struct sc_chunk_refl: reflection data header + struct sc_refl_input[]: array of vertex-shader input attributes (see sc_chunk_refl for number of + inputs) struct sc_refl_uniformbuffer[]: array of uniform buffer objects (see sc_chunk_refl for number + of uniform buffers) struct sc_refl_texture[]: array of texture objects (see sc_chunk_refl for number + of textures) struct sc_refl_texture[]: array of storage image objects (see sc_chunk_refl for number + of storage images) struct sc_refl_buffer[]: array of storage buffer objects (see sc_chunk_refl for + number of storage buffers) + */ + const auto refl_size = ibs.read(); + const auto refl_data_offset = ibs.tell(); + sc_chunk_refl refl; + ibs.advance(sizeof(refl.name)); + refl.num_inputs = ibs.read(); + refl.num_textures = ibs.read(); + refl.num_uniform_buffers = ibs.read(); + refl.num_storage_images = ibs.read(); + refl.num_storage_buffers = ibs.read(); + + // skip infos we don't need + ibs.advance(sizeof(sc_chunk_refl) - offsetof(sc_chunk_refl, flatten_ubos)); + + SLCReflectContext context{&refl, &ibs}; + + // refl_inputs + reflectVertexInputs(&context); + + // refl_uniformbuffers + reflectUniforms(&context); + + // refl_textures + reflectSamplers(&context); + + // refl_storage_images: ignore + ibs.advance(refl.num_storage_images * sizeof(sc_refl_texture)); + + // refl_storage_buffers: ignore + ibs.advance(refl.num_storage_buffers * sizeof(sc_refl_buffer)); + + assert(ibs.tell() - refl_data_offset == refl_size); + } + else + { + assert(false); + return; + } + } + + assert(ibs.eof()); + } while (false); // iterator stages, current only 1 stage + + Microsoft::WRL::ComPtr errorBlob; + UINT flags = D3DCOMPILE_ENABLE_STRICTNESS; +#if defined(_DEBUG) + flags |= D3DCOMPILE_DEBUG | D3DCOMPILE_SKIP_OPTIMIZATION; +#endif + HRESULT hr = D3DCompile(shaderSource.data(), shaderSource.size(), nullptr, nullptr, nullptr, "main", stageToProfile(stage), + flags, 0, &_blob, &errorBlob); + if (FAILED(hr)) + { + std::string_view errorDetail = + errorBlob ? std::string_view((const char*)errorBlob->GetBufferPointer(), errorBlob->GetBufferSize()) + : "Unknown compile error"sv; + AXLOGE("axmol:ERROR: Failed to compile shader, hr:{},{}", hr, errorDetail); + AXASSERT(false, "Shader compile failed!"); + return; + } + + if (stage == ShaderStage::VERTEX) + device->CreateVertexShader(_blob->GetBufferPointer(), _blob->GetBufferSize(), nullptr, + (ID3D11VertexShader**)&_shader); + else + device->CreatePixelShader(_blob->GetBufferPointer(), _blob->GetBufferSize(), nullptr, + (ID3D11PixelShader**)&_shader); + + setBuiltinLocations(); +} + +const UniformInfo& ShaderModuleImpl::getUniformInfo(Uniform name) const +{ + return _builtinUniforms[name]; +} + +const UniformInfo& ShaderModuleImpl::getUniformInfo(std::string_view name) const +{ + static UniformInfo none; + auto iter = _activeUniformInfos.find(name); + if (iter != _activeUniformInfos.end()) + return iter->second; + return none; +} + +const VertexInputDesc* ShaderModuleImpl::getVertexInputDesc(VertexInputKind name) const +{ + return _builtinVertexInputs[name]; +} + +const VertexInputDesc* ShaderModuleImpl::getVertexInputDesc(std::string_view name) const +{ + auto it = _activeVertexInputs.find(name); + if (it != _activeVertexInputs.end()) + return &it->second; + else + return nullptr; +} +void ShaderModuleImpl::reflectVertexInputs(SLCReflectContext* context) +{ + auto ibs = context->ibs; + + for (int i = 0; i < context->refl->num_inputs; ++i) + { + std::string_view name = _sc_read_name(ibs); + auto loc = ibs->read(); + std::string_view semantic = _sc_read_name(ibs); + auto semantic_index = ibs->read(); + auto format = ibs->read(); + + VertexInputDesc desc; + desc.semantic = semantic; + desc.location = semantic_index; + desc.format = format; + _activeVertexInputs.emplace(name, desc); + } +} + +void ShaderModuleImpl::reflectUniforms(SLCReflectContext* context) +{ + _uniformBufferSize = 0; + auto ibs = context->ibs; + for (int i = 0; i < context->refl->num_uniform_buffers; ++i) + { + ibs->advance(sizeof(sc_refl_ub::name)); + auto ub_binding = ibs->read(); + auto ub_size_bytes = ibs->read(); + ibs->advance(sizeof(sc_refl_ub::array_size)); + auto ub_num_members = ibs->read(); + + for (int k = 0; k < ub_num_members; ++k) + { + UniformInfo uniform; + auto name = _sc_read_name(ibs); + auto offset = ibs->read(); + auto format = ibs->read(); + auto size_bytes = ibs->read(); + auto array_size = ibs->read(); + + uniform.count = array_size; + uniform.location = ub_binding; + uniform.size = size_bytes; + uniform.bufferOffset = offset; + uniform.type = format; + _activeUniformInfos[name] = uniform; + + if (_maxLocation < i) + _maxLocation = (i + 1); + } + _uniformBufferSize = ub_size_bytes; + // current: only support 1 uniform block for d3d11 + break; + } +} + +void ShaderModuleImpl::reflectSamplers(SLCReflectContext* context) +{ + auto ibs = context->ibs; + for (int i = 0; i < context->refl->num_textures; ++i) + { + std::string_view name = _sc_read_name(ibs); + auto binding = ibs->read(); + + ibs->advance(sizeof(sc_refl_texture) - offsetof(sc_refl_texture, image_dim)); + + UniformInfo uniform; + uniform.location = binding; + uniform.bufferOffset = -1; + _activeUniformInfos[name] = uniform; + } +} + +void ShaderModuleImpl::setBuiltinLocations() +{ + /*--- Builtin Attribs ---*/ + + /// a_position + _builtinVertexInputs[VertexInputKind::POSITION] = getVertexInputDesc(VERTEX_INPUT_NAME_POSITION); + + /// a_color + _builtinVertexInputs[VertexInputKind::COLOR] = getVertexInputDesc(VERTEX_INPUT_NAME_COLOR); + + /// a_texCoord + _builtinVertexInputs[VertexInputKind::TEXCOORD] = getVertexInputDesc(VERTEX_INPUT_NAME_TEXCOORD); + + // a_normal + _builtinVertexInputs[VertexInputKind::NORMAL] = getVertexInputDesc(VERTEX_INPUT_NAME_NORMAL); + + // a_instance + _builtinVertexInputs[VertexInputKind::INSTANCE] = getVertexInputDesc(VERTEX_INPUT_NAME_INSTANCE); + + /*--- Builtin Uniforms ---*/ + + /// u_MVPMatrix + _builtinUniforms[Uniform::MVP_MATRIX] = getUniformInfo(UNIFORM_NAME_MVP_MATRIX); + + /// u_tex0 + _builtinUniforms[Uniform::TEXTURE] = getUniformInfo(UNIFORM_NAME_TEXTURE); + + /// u_tex1 + _builtinUniforms[Uniform::TEXTURE1] = getUniformInfo(UNIFORM_NAME_TEXTURE1); + + /// u_textColor + _builtinUniforms[Uniform::TEXT_COLOR] = getUniformInfo(UNIFORM_NAME_TEXT_COLOR); + + /// u_effectColor + _builtinUniforms[Uniform::EFFECT_COLOR] = getUniformInfo(UNIFORM_NAME_EFFECT_COLOR); + + /// u_effectType + _builtinUniforms[Uniform::EFFECT_TYPE] = getUniformInfo(UNIFORM_NAME_EFFECT_TYPE); +} +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/ShaderModuleD3D.h b/axmol/rhi/d3d/ShaderModuleD3D.h new file mode 100644 index 000000000000..ae6d64e2d255 --- /dev/null +++ b/axmol/rhi/d3d/ShaderModuleD3D.h @@ -0,0 +1,119 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once +#include "axmol/rhi/ShaderModule.h" +#include +#include + +namespace ax::rhi::d3d +{ +struct SLCReflectContext; + +class ShaderModuleImpl : public ShaderModule +{ +public: + ShaderModuleImpl(ID3D11Device* device, ShaderStage stage, std::string_view source); + ~ShaderModuleImpl(); + + IUnknown* internalHandle() const { return _shader; } + ID3DBlob* getShaderBlob() const { return _blob; } + + /** + * Get uniform info by engine built-in uniform enum name. + * @param name Specifies the engine built-in uniform enum name. + * @return The uniform location. + */ + const UniformInfo& getUniformInfo(Uniform name) const; + + /** + * Get uniform info by name. + * @param uniform Specifies the uniform name. + * @return The uniform location. + */ + const UniformInfo& getUniformInfo(std::string_view name) const; + + /** + * Get attribute location by engine built-in attribute enum name. + * @param name Specifies the engine built-in attribute enum name. + * @return The attribute location. + */ + const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const; + + /** + * Get attribute location by attribute name. + * @param name Specifies the attribute name. + * @return The attribute location. + */ + const VertexInputDesc* getVertexInputDesc(std::string_view name) const; + + /** + * Get active attribute informations. + * @return Active attribute informations. key is attribute name and Value is corresponding attribute info. + */ + inline const hlookup::string_map& getActiveVertexInputs() const { return _activeVertexInputs; } + + + /** + * Get all uniformInfos. + * @return The uniformInfos. + */ + inline const hlookup::string_map& getActiveUniformInfos() const { return _activeUniformInfos; } + + /** + * Get maximum uniform location. + * @return Maximum uniform location. + */ + inline const int getMaxLocation() const { return _maxLocation; } + + /** + * Get uniform buffer size in bytes that holds all the uniforms. + * @return The uniform buffer size. + */ + inline std::size_t getUniformBufferSize() const { return _uniformBufferSize; } + +private: + void compileShader(ID3D11Device* device, ShaderStage stage, std::string_view source); + void releaseShader(); + + void reflectVertexInputs(SLCReflectContext* context); + void reflectUniforms(SLCReflectContext* context); + void reflectSamplers(SLCReflectContext* context); + + void setBuiltinLocations(); + + IUnknown* _shader = nullptr; + ID3DBlob* _blob = nullptr; + + hlookup::string_map _activeVertexInputs; + hlookup::string_map _activeUniformInfos; + + const VertexInputDesc* _builtinVertexInputs[VIK_COUNT]; + + int _maxLocation = -1; + UniformInfo _builtinUniforms[UNIFORM_COUNT]; + + std::size_t _uniformBufferSize = 0; +}; + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/TextureD3D.cpp b/axmol/rhi/d3d/TextureD3D.cpp new file mode 100644 index 000000000000..b78380a5ea2f --- /dev/null +++ b/axmol/rhi/d3d/TextureD3D.cpp @@ -0,0 +1,394 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/TextureD3D.h" +#include "axmol/rhi/d3d/DriverD3D.h" +#include "axmol/rhi/d3d/UtilsD3D.h" +#include "axmol/rhi/PixelFormatUtils.h" +#include "axmol/rhi/SamplerCache.h" + +namespace ax::rhi::d3d +{ + +static void translateUsage(TextureUsage usage, D3D11_TEXTURE2D_DESC& outDesc) +{ + outDesc.BindFlags = D3D11_BIND_SHADER_RESOURCE; + + switch (usage) + { + case TextureUsage::READ: + case TextureUsage::RENDER_TARGET: + outDesc.Usage = D3D11_USAGE_DEFAULT; + outDesc.CPUAccessFlags = 0; + break; + case TextureUsage::WRITE: + outDesc.Usage = D3D11_USAGE_DYNAMIC; + outDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE; + outDesc.BindFlags |= (UINT)D3D11_BIND_UNORDERED_ACCESS; + break; + } +} + +static void translateTexDesc(const TextureDesc& desc, D3D11_TEXTURE2D_DESC& outDesc) +{ + outDesc.Width = desc.width; + outDesc.Height = desc.height; + outDesc.SampleDesc.Count = 1; + outDesc.SampleDesc.Quality = 0; + translateUsage(desc.textureUsage, outDesc); + + switch (desc.textureType) + { + case TextureType::TEXTURE_2D: + outDesc.ArraySize = 1; + break; + case TextureType::TEXTURE_CUBE: + outDesc.ArraySize = 6; + outDesc.MiscFlags |= D3D11_RESOURCE_MISC_TEXTURECUBE; + break; + } + + // depth-stencil + switch (desc.textureFormat) + { + case PixelFormat::D24S8: + outDesc.BindFlags |= D3D11_BIND_DEPTH_STENCIL; + break; + default: + if (desc.textureUsage == TextureUsage::RENDER_TARGET) + outDesc.BindFlags |= D3D11_BIND_RENDER_TARGET; + break; + } +} + +static void fromD3DTexDesc(TextureDesc& td, const D3D11_TEXTURE2D_DESC& desc) +{ + td.textureType = TextureType::TEXTURE_2D; + + td.width = desc.Width; + td.height = desc.Height; + + td.depth = 1; // desc.ArraySize + + switch (desc.Format) + { + case DXGI_FORMAT_R8G8B8A8_UNORM: + td.textureFormat = PixelFormat::RGBA8; + break; + case DXGI_FORMAT_R8_UNORM: + td.textureFormat = PixelFormat::R8; + break; + case DXGI_FORMAT_D24_UNORM_S8_UINT: + td.textureFormat = PixelFormat::D24S8; + break; + default: + td.textureFormat = PixelFormat::NONE; + break; + } + + if (desc.BindFlags & D3D11_BIND_RENDER_TARGET) + td.textureUsage = TextureUsage::RENDER_TARGET; + else if (desc.BindFlags & D3D11_BIND_SHADER_RESOURCE) + td.textureUsage = TextureUsage::READ; +} + +TextureHandle TextureResource::createTexture(UINT mipLevels) +{ + D3D11_TEXTURE2D_DESC texDesc{}; + translateTexDesc(_desc, texDesc); + + texDesc.MipLevels = mipLevels; + + if (mipLevels == 0) + { + texDesc.MiscFlags |= D3D11_RESOURCE_MISC_GENERATE_MIPS; + texDesc.BindFlags |= D3D11_BIND_RENDER_TARGET; + } + + auto fmtInfo = UtilsD3D::toDxgiFormatInfo(_desc.textureFormat); + assert(fmtInfo); + if (fmtInfo->format == DXGI_FORMAT_UNKNOWN) + { + AXLOGE("axmol: D3D not support pixel format: {}", (int)_desc.textureFormat); + return TextureHandle{}; + } + + texDesc.Format = fmtInfo->format; + + ComPtr texture; + HRESULT hr = _device->CreateTexture2D(&texDesc, nullptr, texture.GetAddressOf()); + if (FAILED(hr) || !texture) + { + return TextureHandle{}; + } + + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; + srvDesc.Format = fmtInfo->fmtSrv; + switch (_desc.textureType) + { + case TextureType::TEXTURE_CUBE: + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURECUBE; + srvDesc.TextureCube.MipLevels = -1; + srvDesc.TextureCube.MostDetailedMip = 0; + break; + default: + srvDesc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D; + srvDesc.Texture2D.MipLevels = -1; + srvDesc.Texture2D.MostDetailedMip = 0; + } + + ComPtr srv; + hr = _device->CreateShaderResourceView(texture.Get(), &srvDesc, srv.GetAddressOf()); + + if (FAILED(hr) || !srv) + { + return TextureHandle{}; + } + + return TextureHandle{texture.Detach(), srv.Detach()}; +} + +TextureHandle TextureResource::ensure(int index) +{ + if (index < 0 || index >= _textures.size()) + return TextureHandle{}; + + if (_textures[index]) + return _textures[index]; + + _textures[index] = createTexture(1); + _maxIdx = (std::max)(_maxIdx, index + 1); + + return _textures[index]; +} + +// ------------------------------------------------------------ +// ctor / dtor +// ------------------------------------------------------------ +TextureImpl::TextureImpl(ID3D11Device* device, const TextureDesc& descriptor) : _textureRes(device) +{ + updateTextureDesc(descriptor); + // TODO: + // _rendererRecreatedListener = EventDispatcher::addListener( + // EventType::RENDERER_RECREATED, [this](auto&&) { updateTextureDesc(this->_textureDesc); }); +} + +TextureImpl::TextureImpl(ID3D11Device* device, ID3D11Texture2D* texture) : _textureRes(device) +{ + texture->AddRef(); + _textureRes._textures[0].tex2d = texture; + _textureRes._maxIdx = 0; + + D3D11_TEXTURE2D_DESC desc; + texture->GetDesc(&desc); + fromD3DTexDesc(_textureRes._desc, desc); + + Texture::updateTextureDesc(_textureRes._desc); +} + +TextureImpl::~TextureImpl() +{ + // TODO: + // EventDispatcher::removeListener(_rendererRecreatedListener); + _textureRes.destroy(); +} + +// ------------------------------------------------------------ +// updateSamplerDesc +// ------------------------------------------------------------ +void TextureImpl::updateSamplerDesc(const SamplerDesc& desc) +{ + _textureRes._samplerState = static_cast(SamplerCache::getInstance()->getSampler(desc)); +} + +// ------------------------------------------------------------ +// updateTextureDesc +// ------------------------------------------------------------ +void TextureImpl::updateTextureDesc(const TextureDesc& descriptor, int index /*=0*/) +{ + + _textureRes._desc = descriptor; + + Texture::updateTextureDesc(descriptor); + + updateSamplerDesc(descriptor.samplerDesc); + + if (descriptor.textureFormat != PixelFormat::NONE) + _textureRes.ensure(index); +} + +// ------------------------------------------------------------ +// generateMipmaps +// ------------------------------------------------------------ +void TextureImpl::generateMipmaps() +{ + if (TextureUsage::RENDER_TARGET == _textureUsage) + return; + + if (!_hasMipmaps) + { + _hasMipmaps = true; + auto context = static_cast(DriverBase::getInstance())->getContext(); + + // FIXME: consider add a member mipLevels to TextureDesc to avoid recreate texture + // + _textureRes.foreachTextures([context, this](TextureHandle& h, int) { + if (h && h.srv) + { + // recreate texture with mip + auto tmp = _textureRes.createTexture(0); + if (tmp) + { + context->CopySubresourceRegion(tmp.tex2d, 0, 0, 0, 0, h.tex2d, 0, nullptr); + context->GenerateMips(tmp.srv); + h.Release(); + h = tmp; + } + } + }); + + auto mainTexture = _textureRes._textures[0]; + if (mainTexture.srv) + { + D3D11_SHADER_RESOURCE_VIEW_DESC srvDesc{}; + mainTexture.srv->GetDesc(&srvDesc); + _textureRes._mipLevels = srvDesc.Texture2D.MipLevels; + } + } +} + +void TextureImpl::updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index /*=0*/) +{ + assert(_textureType == TextureType::TEXTURE_2D); + _textureRes.ensure(index); + AX_ASSERT(index <= _textureRes._maxIdx); + + auto rowPitch = PixelFormatUtils::computeRowPitch(_textureFormat, static_cast(width)); + + UINT slicePitch = rowPitch * static_cast(height); + + auto context = static_cast(DriverBase::getInstance())->getContext(); + context->UpdateSubresource(_textureRes._textures[index].tex2d, static_cast(level), nullptr, data, rowPitch, + slicePitch); +} + +void TextureImpl::updateCompressedData(uint8_t* data, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + int index /*=0*/) +{ + assert(_textureType == TextureType::TEXTURE_2D); + _textureRes.ensure(index); + AX_ASSERT(index <= _textureRes._maxIdx); + + auto context = static_cast(DriverBase::getInstance())->getContext(); + context->UpdateSubresource(_textureRes._textures[index].tex2d, static_cast(level), nullptr, data, 0, 0); +} + +void TextureImpl::updateSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t level, + uint8_t* data, + int index /*=0*/) +{ + assert(_textureType == TextureType::TEXTURE_2D); + _textureRes.ensure(index); + AX_ASSERT(index <= _textureRes._maxIdx); + + D3D11_BOX box{}; + box.left = static_cast(xoffset); + box.top = static_cast(yoffset); + box.front = 0; + box.right = static_cast(xoffset + width); + box.bottom = static_cast(yoffset + height); + box.back = 1; + + auto rowPitch = PixelFormatUtils::computeRowPitch(_textureFormat, static_cast(width)); + UINT slicePitch = rowPitch * static_cast(height); + + auto context = static_cast(DriverBase::getInstance())->getContext(); + context->UpdateSubresource(_textureRes._textures[index].tex2d, static_cast(level), &box, data, rowPitch, + slicePitch); +} + +void TextureImpl::updateCompressedSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + uint8_t* data, + int index /*=0*/) +{ + assert(_textureType == TextureType::TEXTURE_2D); + _textureRes.ensure(index); + AX_ASSERT(index <= _textureRes._maxIdx); + + D3D11_BOX box{}; + box.left = static_cast(xoffset); + box.top = static_cast(yoffset); + box.front = 0; + box.right = static_cast(xoffset + width); + box.bottom = static_cast(yoffset + height); + box.back = 1; + + auto context = static_cast(DriverBase::getInstance())->getContext(); + context->UpdateSubresource(_textureRes._textures[index].tex2d, static_cast(level), &box, data, 0, 0); +} + +void TextureImpl::updateFaceData(TextureCubeFace side, void* data, int index) +{ + assert(_textureType == TextureType::TEXTURE_CUBE); + _textureRes.ensure(index); + assert(index <= _textureRes._maxIdx); + + auto context = static_cast(DriverBase::getInstance())->getContext(); + + auto& texHandle = _textureRes.getTexture(index); + + //------------------------------------------------------------------- + // 1. compute SubResource: = 6 * (mip-levels) + //------------------------------------------------------------------- + const uint32_t mipLevels = 1; // texHandle.tex2d->getMipLevels(); + const uint32_t mipLevel = 0; + const uint32_t arraySlice = static_cast(side) + index * 6; + const uint32_t subresource = ::D3D11CalcSubresource(mipLevel, arraySlice, mipLevels); + + //------------------------------------------------------------------- + // 2. compute RowPitch / SlicePitch + //------------------------------------------------------------------- + const uint32_t rowPitch = + PixelFormatUtils::computeRowPitch(_textureFormat, static_cast(_textureRes._desc.width)); + const uint32_t slicePitch = _textureRes._desc.height * rowPitch; + + //------------------------------------------------------------------- + // 3. update + //------------------------------------------------------------------- + context->UpdateSubresource(_textureRes._textures[index].tex2d, subresource, nullptr, data, rowPitch, slicePitch); +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/TextureD3D.h b/axmol/rhi/d3d/TextureD3D.h new file mode 100644 index 000000000000..3778e68ff6e2 --- /dev/null +++ b/axmol/rhi/d3d/TextureD3D.h @@ -0,0 +1,226 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include +#include "axmol/rhi/Texture.h" +#include "axmol/base/EventListenerCustom.h" + +#include +#include +#include +#include // std::array + +namespace ax::rhi::d3d +{ +using namespace Microsoft::WRL; + +struct TextureHandle +{ + explicit operator bool() const { return tex2d != nullptr; } + + void Release() + { + SafeRelease(srv); + SafeRelease(tex2d); + } + + ID3D11Texture2D* tex2d{}; + ID3D11ShaderResourceView* srv{}; // Note: default color attachment not create srv yet. +}; + +/** + * Store texture resource. + */ +struct TextureResource +{ + TextureResource(ID3D11Device* d3d11device) + { + _device = d3d11device; + _textures.fill(TextureHandle{}); + } + ~TextureResource() { destroy(); } + + template + void foreachTextures(const _Fty& cb) + { + int idx = 0; + while (_textures[idx]) + { + auto& h = _textures[idx]; + cb(h, idx++); + } + } + + TextureHandle createTexture(UINT mipLevels); + + TextureHandle ensure(int index); + + void destroy() + { + foreachTextures([this](TextureHandle& tex, int) { + if (tex) + tex.Release(); + }); + _textures.fill(TextureHandle{}); + } + + const TextureHandle& getTexture(int index) const { return _textures[index]; } + + ID3D11Device* _device; + + TextureDesc _desc; + + std::array _textures; + ID3D11SamplerState* _samplerState = nullptr; + int _maxIdx = 0; + UINT _mipLevels = -1; // means only 1 layer +}; + +/** + * @addtogroup _d3d + * @{ + */ + +/** + * TextureImpl + */ +class TextureImpl : public rhi::Texture +{ +public: + /** + * @param descriptor Specifies the texture description. + */ + TextureImpl(ID3D11Device* device, const TextureDesc& descriptor); + TextureImpl(ID3D11Device* device, ID3D11Texture2D* texture); + ~TextureImpl(); + + /** + * Update a two-dimensional texture image + * @param data Specifies a pointer to the image data in memory. + * @param width Specifies the width of the texture image. + * @param height Specifies the height of the texture image. + * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap + * reduction image. + */ + void updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index = 0) override; + + /** + * Update a two-dimensional texture image in a compressed format + * @param data Specifies a pointer to the compressed image data in memory. + * @param width Specifies the width of the texture image. + * @param height Specifies the height of the texture image. + * @param dataLen Specifies the totoal size of compressed image in bytes. + * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap + * reduction image. + */ + void updateCompressedData(uint8_t* data, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + int index = 0) override; + + /** + * Update a two-dimensional texture subimage + * @param xoffset Specifies a texel offset in the x direction within the texture array. + * @param yoffset Specifies a texel offset in the y direction within the texture array. + * @param width Specifies the width of the texture subimage. + * @param height Specifies the height of the texture subimage. + * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap + * reduction image. + * @param data Specifies a pointer to the image data in memory. + */ + void updateSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t level, + uint8_t* data, + int index = 0) override; + + /** + * Update a two-dimensional texture subimage in a compressed format + * @param xoffset Specifies a texel offset in the x direction within the texture array. + * @param yoffset Specifies a texel offset in the y direction within the texture array. + * @param width Specifies the width of the texture subimage. + * @param height Specifies the height of the texture subimage. + * @param dataLen Specifies the totoal size of compressed subimage in bytes. + * @param level Specifies the level-of-detail number. Level 0 is the base image level. Level n is the nth mipmap + * reduction image. + * @param data Specifies a pointer to the compressed image data in memory. + */ + void updateCompressedSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + uint8_t* data, + int index = 0) override; + + /** + * Update texutre cube data in give slice side. + * @param side Specifies which slice texture of cube to be update. + * @param data Specifies a pointer to the image data in memory. + */ + void updateFaceData(TextureCubeFace side, void* data, int index) override; + + /** + * Update sampler + * @param sampler Specifies the sampler descriptor. + */ + void updateSamplerDesc(const SamplerDesc& sampler) override; + + /** + * Generate mipmaps. + */ + void generateMipmaps() override; + + /** + * Update texture description. + * @param descriptor Specifies texture and sampler descriptor. + */ + void updateTextureDesc(const TextureDesc& descriptor, int index = 0) override; + + /** + * Get texture object. + * @return Texture object. + */ + const TextureHandle& internalHandle(int index = 0) const { return _textureRes._textures[index]; } + + ID3D11SamplerState* getSamplerState() const { return _textureRes._samplerState; } + + const TextureDesc& getDesc() const { return _textureRes._desc; } + + int getCount() const override { return _textureRes._maxIdx + 1; } + +private: + TextureResource _textureRes; + EventListener* _rendererRecreatedListener = nullptr; +}; + +// end of d3d group +/// @} +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/UtilsD3D.cpp b/axmol/rhi/d3d/UtilsD3D.cpp new file mode 100644 index 000000000000..8651280befb2 --- /dev/null +++ b/axmol/rhi/d3d/UtilsD3D.cpp @@ -0,0 +1,212 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +// Direct3D / DXGI equivalent of the OpenGL `s_textureFormats` table. +// For compressed formats that D3D11/D3D12 do **not** natively support (PVRTC, ETC*, ATC, ASTC, …), +// we fall back to the closest broadly-available format so the rest of the engine can still +// create a valid texture object and sample from it. +// • Lossy RGB‐only schemes → BC1 (a.k.a. DXT1) or R8G8B8A8_UNORM as a generic 32-bit placeholder +// • Lossy RGBA schemes → BC3 (DXT5) or R8G8B8A8_UNORM +// • High-quality ASTC → BC7 (best quality on PC GPUs) +// +// The **`type`** column has no real DXGI equivalent; it is kept for structural parity and +// set to `DXGI_FORMAT_UNKNOWN`. +// + +#include "axmol/rhi/d3d/UtilsD3D.h" +#include "axmol/rhi/d3d/DriverD3D.h" +#include +#include + +#include "axmol/base/Logging.h" + +#include "axmol/rhi/PixelFormatUtils.h" + +using namespace Microsoft::WRL; + +namespace ax::rhi::d3d +{ + +#define DXGI_FORMAT_ASTC_4X4_TYPELESS DXGI_FORMAT(133) +#define DXGI_FORMAT_ASTC_4X4_UNORM DXGI_FORMAT(134) +#define DXGI_FORMAT_ASTC_4X4_UNORM_SRGB DXGI_FORMAT(135) +#define DXGI_FORMAT_ASTC_5X4_TYPELESS DXGI_FORMAT(137) +#define DXGI_FORMAT_ASTC_5X4_UNORM DXGI_FORMAT(138) +#define DXGI_FORMAT_ASTC_5X4_UNORM_SRGB DXGI_FORMAT(139) +#define DXGI_FORMAT_ASTC_5X5_TYPELESS DXGI_FORMAT(141) +#define DXGI_FORMAT_ASTC_5X5_UNORM DXGI_FORMAT(142) +#define DXGI_FORMAT_ASTC_5X5_UNORM_SRGB DXGI_FORMAT(143) +#define DXGI_FORMAT_ASTC_6X5_TYPELESS DXGI_FORMAT(145) +#define DXGI_FORMAT_ASTC_6X5_UNORM DXGI_FORMAT(146) +#define DXGI_FORMAT_ASTC_6X5_UNORM_SRGB DXGI_FORMAT(147) +#define DXGI_FORMAT_ASTC_6X6_TYPELESS DXGI_FORMAT(149) +#define DXGI_FORMAT_ASTC_6X6_UNORM DXGI_FORMAT(150) +#define DXGI_FORMAT_ASTC_6X6_UNORM_SRGB DXGI_FORMAT(151) +#define DXGI_FORMAT_ASTC_8X5_TYPELESS DXGI_FORMAT(153) +#define DXGI_FORMAT_ASTC_8X5_UNORM DXGI_FORMAT(154) +#define DXGI_FORMAT_ASTC_8X5_UNORM_SRGB DXGI_FORMAT(155) +#define DXGI_FORMAT_ASTC_8X6_TYPELESS DXGI_FORMAT(157) +#define DXGI_FORMAT_ASTC_8X6_UNORM DXGI_FORMAT(158) +#define DXGI_FORMAT_ASTC_8X6_UNORM_SRGB DXGI_FORMAT(159) +#define DXGI_FORMAT_ASTC_8X8_TYPELESS DXGI_FORMAT(161) +#define DXGI_FORMAT_ASTC_8X8_UNORM DXGI_FORMAT(162) +#define DXGI_FORMAT_ASTC_8X8_UNORM_SRGB DXGI_FORMAT(163) +#define DXGI_FORMAT_ASTC_10X5_TYPELESS DXGI_FORMAT(165) +#define DXGI_FORMAT_ASTC_10X5_UNORM DXGI_FORMAT(166) +#define DXGI_FORMAT_ASTC_10X5_UNORM_SRGB DXGI_FORMAT(167) +#define DXGI_FORMAT_ASTC_10X6_TYPELESS DXGI_FORMAT(169) +#define DXGI_FORMAT_ASTC_10X6_UNORM DXGI_FORMAT(170) +#define DXGI_FORMAT_ASTC_10X6_UNORM_SRGB DXGI_FORMAT(171) +#define DXGI_FORMAT_ASTC_10X8_TYPELESS DXGI_FORMAT(173) +#define DXGI_FORMAT_ASTC_10X8_UNORM DXGI_FORMAT(174) +#define DXGI_FORMAT_ASTC_10X8_UNORM_SRGB DXGI_FORMAT(175) +#define DXGI_FORMAT_ASTC_10X10_TYPELESS DXGI_FORMAT(177) +#define DXGI_FORMAT_ASTC_10X10_UNORM DXGI_FORMAT(178) +#define DXGI_FORMAT_ASTC_10X10_UNORM_SRGB DXGI_FORMAT(179) +#define DXGI_FORMAT_ASTC_12X10_TYPELESS DXGI_FORMAT(181) +#define DXGI_FORMAT_ASTC_12X10_UNORM DXGI_FORMAT(182) +#define DXGI_FORMAT_ASTC_12X10_UNORM_SRGB DXGI_FORMAT(183) +#define DXGI_FORMAT_ASTC_12X12_TYPELESS DXGI_FORMAT(185) +#define DXGI_FORMAT_ASTC_12X12_UNORM DXGI_FORMAT(186) +#define DXGI_FORMAT_ASTC_12X12_UNORM_SRGB DXGI_FORMAT(187) + +// clang-format off +static PixelFormatInfo s_pixelFormatInfos[] = +{ + /* ---- format ----------------------- fmtSvr -----------------------fmtDsv --------------------- fmtSrgb -------------------*/ + /* pvrtc v1 ------------------------------------------------------------ */ + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PVRTC4 (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PVRTC4A (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PVRTC2 (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // PVRTC2A (NA) + + /* etc ----------------------------------------------------------------- */ + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC1 (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC2 (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ETC2A (NA) + + /* s3tc / bc ----------------------------------------------------------- */ + { DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_BC1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC1_UNORM_SRGB }, // S3TC_DXT1 + { DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_BC2_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC2_UNORM_SRGB }, // S3TC_DXT3 + { DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_BC3_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_BC3_UNORM_SRGB }, // S3TC_DXT5 + + /* atc ----------------------------------------------------------------- */ + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ATC (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ATCE (NA) + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // ATCI (NA) + + /* astc ---------------------------------------------------------------- */ + { DXGI_FORMAT_ASTC_4X4_UNORM, DXGI_FORMAT_ASTC_4X4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_4X4_UNORM_SRGB }, // ASTC4×4 + { DXGI_FORMAT_ASTC_5X5_UNORM, DXGI_FORMAT_ASTC_5X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_5X5_UNORM_SRGB }, // ASTC5×5 + { DXGI_FORMAT_ASTC_6X6_UNORM, DXGI_FORMAT_ASTC_6X6_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_6X6_UNORM_SRGB }, // ASTC6×6 + { DXGI_FORMAT_ASTC_8X5_UNORM, DXGI_FORMAT_ASTC_8X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X5_UNORM_SRGB }, // ASTC8×5 + { DXGI_FORMAT_ASTC_8X6_UNORM, DXGI_FORMAT_ASTC_8X6_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X6_UNORM_SRGB }, // ASTC8×6 + { DXGI_FORMAT_ASTC_8X8_UNORM, DXGI_FORMAT_ASTC_8X8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_8X8_UNORM_SRGB }, // ASTC8×8 + { DXGI_FORMAT_ASTC_10X5_UNORM, DXGI_FORMAT_ASTC_10X5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_ASTC_10X5_UNORM_SRGB }, // ASTC10×5 + + /* uncompressed -------------------------------------------------------- */ + { DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_R8G8B8A8_UNORM_SRGB }, // RGBA8 + { DXGI_FORMAT_B8G8R8A8_UNORM, DXGI_FORMAT_R8G8B8A8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_B8G8R8A8_UNORM_SRGB }, // BGRA8 + { DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGB8 (NA) + { DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_B5G6R5_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGB565 + { DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_B4G4R4A4_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGBA4 + { DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_B5G5R5A1_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGB5A1 + + { DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_R8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, }, // R8 + { DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_R8G8_UNORM, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN, }, // RG8 + { DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_R32G32B32A32_FLOAT, DXGI_FORMAT_UNKNOWN, DXGI_FORMAT_UNKNOWN }, // RGBA32F + + /* depth-stencil ------------------------------------------------------- */ + { DXGI_FORMAT_R24G8_TYPELESS, DXGI_FORMAT_R24_UNORM_X8_TYPELESS, DXGI_FORMAT_D24_UNORM_S8_UINT, DXGI_FORMAT_UNKNOWN }, // D24S8 +}; +// clang-format on + +static_assert(AX_ARRAYSIZE(s_pixelFormatInfos) == static_cast(PixelFormat::COUNT), + "The Direct3D GPU texture format info table is incomplete!"); + +static TextureImpl* s_defaultColorAttachment; +static TextureImpl* s_defaultDepthStencilAttachment; + +const PixelFormatInfo* UtilsD3D::toDxgiFormatInfo(PixelFormat pf) +{ + if (pf < PixelFormat::COUNT) [[likely]] + return &s_pixelFormatInfos[(int)pf]; + return nullptr; +} + +void UtilsD3D::updateDefaultRenderTargetAttachments(DriverImpl* driverImpl, IDXGISwapChain* swapChain) +{ + AX_SAFE_RELEASE_NULL(s_defaultColorAttachment); + AX_SAFE_RELEASE_NULL(s_defaultDepthStencilAttachment); + + if (swapChain) + { + auto device = driverImpl->getDevice(); + auto context = driverImpl->getContext(); + + // swap chain only contains color attachment + ComPtr rtv; + ComPtr backBuffer; + HRESULT hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), (void**)backBuffer.GetAddressOf()); + hr = device->CreateRenderTargetView(backBuffer.Get(), nullptr, rtv.GetAddressOf()); + s_defaultColorAttachment = new TextureImpl(device, backBuffer.Get()); + + UINT fmtSupport = 0; + device->CheckFormatSupport(DXGI_FORMAT_D24_UNORM_S8_UINT, &fmtSupport); + assert(fmtSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL); + + // create depth-stencil attachment + D3D11_TEXTURE2D_DESC depthDesc = {}; + depthDesc.Width = s_defaultColorAttachment->getWidth(); + depthDesc.Height = s_defaultColorAttachment->getHeight(); + depthDesc.MipLevels = 1; + depthDesc.ArraySize = 1; + depthDesc.Format = DXGI_FORMAT_D24_UNORM_S8_UINT; // 24-bit depth, 8-bit stencil + depthDesc.Usage = D3D11_USAGE_DEFAULT; + depthDesc.BindFlags = D3D11_BIND_DEPTH_STENCIL; + depthDesc.SampleDesc.Count = 1; + depthDesc.SampleDesc.Quality = 0; + + ComPtr depthStencilTexture; + hr = device->CreateTexture2D(&depthDesc, nullptr, depthStencilTexture.GetAddressOf()); + + ComPtr depthStencilView = nullptr; + hr = device->CreateDepthStencilView(depthStencilTexture.Get(), nullptr, depthStencilView.GetAddressOf()); + + context->OMSetRenderTargets(1, rtv.GetAddressOf(), depthStencilView.Get()); + + s_defaultDepthStencilAttachment = new TextureImpl(device, depthStencilTexture.Get()); + } +} + +TextureImpl* UtilsD3D::getDefaultColorAttachment() +{ + return s_defaultColorAttachment; +} +TextureImpl* UtilsD3D::getDefaultDepthStencilAttachment() +{ + return s_defaultDepthStencilAttachment; +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/UtilsD3D.h b/axmol/rhi/d3d/UtilsD3D.h new file mode 100644 index 000000000000..5c3f877c43e8 --- /dev/null +++ b/axmol/rhi/d3d/UtilsD3D.h @@ -0,0 +1,72 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/PixelBufferDesc.h" +#include "axmol/rhi/d3d/TextureD3D.h" +#include + +namespace ax::rhi::d3d +{ +class DriverImpl; + +struct PixelFormatInfo +{ + DXGI_FORMAT format; + DXGI_FORMAT fmtSrv; // View format for SRV/UAV + DXGI_FORMAT fmtDsv; // View format for DSV + DXGI_FORMAT fmtSrgb; // fmtSrgb +}; + +struct UtilsD3D +{ + static const PixelFormatInfo* toDxgiFormatInfo(PixelFormat pf); + + static void updateDefaultRenderTargetAttachments(DriverImpl*, IDXGISwapChain*); + + static TextureImpl* getDefaultColorAttachment(); + static TextureImpl* getDefaultDepthStencilAttachment(); +}; + +template +inline void SafeRelease(T (&resourceBlock)[N]) +{ + for (unsigned int i = 0; i < N; i++) + { + SafeRelease(resourceBlock[i]); + } +} + +template +inline void SafeRelease(T& resource) +{ + if (resource) + { + resource->Release(); + resource = nullptr; + } +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/VertexLayoutD3D.cpp b/axmol/rhi/d3d/VertexLayoutD3D.cpp new file mode 100644 index 000000000000..5b273e15da5d --- /dev/null +++ b/axmol/rhi/d3d/VertexLayoutD3D.cpp @@ -0,0 +1,149 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#include "axmol/rhi/d3d/VertexLayoutD3D.h" +#include "axmol/rhi/d3d/ProgramD3D.h" +#include "axmol/rhi/d3d/DriverD3D.h" + +namespace ax::rhi::d3d +{ + +static DXGI_FORMAT toDXGIFormat(VertexFormat format, bool unorm) +{ + switch (format) + { + case VertexFormat::FLOAT4: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + case VertexFormat::FLOAT3: + return DXGI_FORMAT_R32G32B32_FLOAT; + case VertexFormat::FLOAT2: + return DXGI_FORMAT_R32G32_FLOAT; + case VertexFormat::FLOAT: + return DXGI_FORMAT_R32_FLOAT; + + case VertexFormat::INT4: + return DXGI_FORMAT_R32G32B32A32_SINT; + case VertexFormat::INT3: + return DXGI_FORMAT_R32G32B32_SINT; + case VertexFormat::INT2: + return DXGI_FORMAT_R32G32_SINT; + case VertexFormat::INT: + return DXGI_FORMAT_R32_SINT; + + case VertexFormat::USHORT4: + return unorm ? DXGI_FORMAT_R16G16B16A16_UNORM : DXGI_FORMAT_R16G16B16A16_UINT; + case VertexFormat::USHORT2: + return unorm ? DXGI_FORMAT_R16G16_UNORM : DXGI_FORMAT_R16G16_UINT; + + case VertexFormat::UBYTE4: + return unorm ? DXGI_FORMAT_R8G8B8A8_UNORM : DXGI_FORMAT_R8G8B8A8_UINT; + + case VertexFormat::MAT4: + return DXGI_FORMAT_R32G32B32A32_FLOAT; + + default: + return DXGI_FORMAT_UNKNOWN; + } +} + +VertexLayoutImpl::~VertexLayoutImpl() +{ + SafeRelease(_d3dVL); +} + +void VertexLayoutImpl::apply(ID3D11DeviceContext* context, Program* program) const +{ + if (!_d3dVL) + { + auto progImpl = static_cast(program); + auto device = static_cast(DriverBase::getInstance())->getDevice(); + + axstd::pod_vector inputElements; + inputElements.reserve(_bindings.size() + _instanceBindings.size()); + + auto appendElement = [&inputElements](const InputBindingDesc& inputDesc) { + const auto inputSlot = inputDesc.instanceStepRate ? 1 : 0; + const auto inputSlotClass = + inputDesc.instanceStepRate ? D3D11_INPUT_PER_INSTANCE_DATA : D3D11_INPUT_PER_VERTEX_DATA; + if (inputDesc.format != VertexFormat::MAT4) + { + D3D11_INPUT_ELEMENT_DESC desc{}; + + desc.SemanticName = inputDesc.name.c_str(); + desc.SemanticIndex = inputDesc.index; + desc.Format = toDXGIFormat(inputDesc.format, inputDesc.needToBeNormallized); + desc.InputSlot = inputSlot; + desc.AlignedByteOffset = inputDesc.offset; + desc.InputSlotClass = inputSlotClass; + desc.InstanceDataStepRate = inputDesc.instanceStepRate; + + inputElements.push_back(desc); + } + else + { + for (UINT i = 0; i < 4; ++i) + { + D3D11_INPUT_ELEMENT_DESC desc{}; + desc.SemanticName = inputDesc.name.c_str(); + desc.SemanticIndex = inputDesc.index + i; + desc.Format = DXGI_FORMAT_R32G32B32A32_FLOAT; + desc.InputSlot = inputSlot; + desc.AlignedByteOffset = inputDesc.offset + sizeof(float) * 4 * i; + desc.InputSlotClass = inputSlotClass; + desc.InstanceDataStepRate = inputDesc.instanceStepRate; + + inputElements.push_back(desc); + } + } + }; + + for (auto& [_, inputDesc] : _bindings) + appendElement(inputDesc); + + for (auto& [_, inputDesc] : _instanceBindings) + appendElement(inputDesc); + + ID3DBlob* vsBlob = progImpl->getVSBlob(); + HRESULT hr = device->CreateInputLayout(inputElements.data(), static_cast(inputElements.size()), + vsBlob->GetBufferPointer(), vsBlob->GetBufferSize(), &_d3dVL); + } + + if (_d3dVL) + { + context->IASetInputLayout(_d3dVL); + } + else + { + AXLOGE("Create input layout fail"); + } +} + +VertexLayoutImpl* VertexLayoutImpl::clone() +{ + auto vl = new VertexLayoutImpl(*this); + if (vl->_d3dVL) + vl->_d3dVL->AddRef(); + return vl; +} + +} // namespace ax::rhi::d3d diff --git a/axmol/rhi/d3d/VertexLayoutD3D.h b/axmol/rhi/d3d/VertexLayoutD3D.h new file mode 100644 index 000000000000..1d4f95fa738f --- /dev/null +++ b/axmol/rhi/d3d/VertexLayoutD3D.h @@ -0,0 +1,44 @@ +/**************************************************************************** + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ +#pragma once + +#include "axmol/rhi/VertexLayout.h" +#include "axmol/rhi/RHITypes.h" +#include + +namespace ax::rhi::d3d +{ +class VertexLayoutImpl : public VertexLayout +{ +public: + ~VertexLayoutImpl() override; + + void apply(ID3D11DeviceContext* context, Program* program) const; + VertexLayoutImpl* clone() override; + +private: + + mutable ID3D11InputLayout* _d3dVL{nullptr}; +}; +} // namespace ax::rhi::d3d diff --git a/core/renderer/backend/metal/BufferMTL.h b/axmol/rhi/metal/BufferMTL.h similarity index 87% rename from core/renderer/backend/metal/BufferMTL.h rename to axmol/rhi/metal/BufferMTL.h index d90a661417d4..af3adbbe05fb 100644 --- a/core/renderer/backend/metal/BufferMTL.h +++ b/axmol/rhi/metal/BufferMTL.h @@ -24,10 +24,10 @@ #pragma once -#include "../Buffer.h" +#include "axmol/rhi/Buffer.h" #import -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { /** * @addtogroup _metal @@ -40,12 +40,12 @@ NS_AX_BACKEND_BEGIN * To avoid creating new buffers per frame and to minimize processor idle time between frames, implement a triple * buffering model to update dynamic buffer. */ -class BufferMTL : public Buffer +class BufferImpl : public Buffer { public: /// @name Constructor, Destructor and Initializers /** - * @brief BufferMTL constructor + * @brief BufferImpl constructor * @param mtlDevice The device for which MTLBuffer object was created. * @param size Specifies the size in bytes of the buffer object's new data store. * @param type Specifies the target buffer object. The symbolic constant must be BufferType::VERTEX or @@ -53,8 +53,8 @@ class BufferMTL : public Buffer * @param usage Specifies the expected usage pattern of the data store. The symbolic constant must be * BufferUsage::STATIC, BufferUsage::DYNAMIC. */ - BufferMTL(id mtlDevice, std::size_t size, BufferType type, BufferUsage usage); - ~BufferMTL(); + BufferImpl(id mtlDevice, std::size_t size, BufferType type, BufferUsage usage); + ~BufferImpl(); /// @name Update Buffer /** @@ -63,7 +63,7 @@ class BufferMTL : public Buffer * @param size Specifies the size in bytes of the data store region being replaced. * @see `updateSubData(void* data, unsigned int offset, unsigned int size)` */ - virtual void updateData(const void* data, std::size_t size) override; + void updateData(const void* data, std::size_t size) override; /** * @brief Update buffer sub-region data @@ -73,12 +73,12 @@ class BufferMTL : public Buffer * @param size Specifies the size in bytes of the data store region being replaced. * @see `updateData(void* data, unsigned int size)` */ - virtual void updateSubData(const void* data, std::size_t offset, std::size_t size) override; + void updateSubData(const void* data, std::size_t offset, std::size_t size) override; /** * Emply implementation. Mainly used in EGL context lost. */ - virtual void usingDefaultStoredData(bool needDefaultStoredData) override{}; + void usingDefaultStoredData(bool needDefaultStoredData) override{}; /// @name Setters & Getters id getMTLBuffer() const; @@ -100,4 +100,4 @@ class BufferMTL : public Buffer // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/BufferMTL.mm b/axmol/rhi/metal/BufferMTL.mm similarity index 84% rename from core/renderer/backend/metal/BufferMTL.mm rename to axmol/rhi/metal/BufferMTL.mm index c22c4a89e43c..f30bbe5c0f46 100644 --- a/core/renderer/backend/metal/BufferMTL.mm +++ b/axmol/rhi/metal/BufferMTL.mm @@ -22,13 +22,13 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "BufferMTL.h" -#include "../Macros.h" -#include "BufferManager.h" +#include "axmol/rhi/metal/BufferMTL.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/metal/BufferManager.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { -BufferMTL::BufferMTL(id mtlDevice, std::size_t size, BufferType type, BufferUsage usage) +BufferImpl::BufferImpl(id mtlDevice, std::size_t size, BufferType type, BufferUsage usage) : Buffer(size, type, usage) { if (BufferUsage::DYNAMIC == usage) @@ -51,7 +51,7 @@ of this software and associated documentation files (the "Software"), to deal } } -BufferMTL::~BufferMTL() +BufferImpl::~BufferImpl() { if (BufferUsage::DYNAMIC == _usage) { @@ -68,31 +68,31 @@ of this software and associated documentation files (the "Software"), to deal } } -void BufferMTL::updateData(const void* data, std::size_t size) +void BufferImpl::updateData(const void* data, std::size_t size) { assert(size <= _size); updateIndex(); memcpy((uint8_t*)_mtlBuffer.contents, data, size); } -void BufferMTL::updateSubData(const void* data, std::size_t offset, std::size_t size) +void BufferImpl::updateSubData(const void* data, std::size_t offset, std::size_t size) { assert(offset + size <= _size); updateIndex(); memcpy((uint8_t*)_mtlBuffer.contents + offset, data, size); } -id BufferMTL::getMTLBuffer() const +id BufferImpl::getMTLBuffer() const { return _mtlBuffer; } -void BufferMTL::beginFrame() +void BufferImpl::beginFrame() { _indexUpdated = false; } -void BufferMTL::updateIndex() +void BufferImpl::updateIndex() { if (BufferUsage::DYNAMIC == _usage && !_indexUpdated) { @@ -102,4 +102,4 @@ of this software and associated documentation files (the "Software"), to deal } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/BufferManager.h b/axmol/rhi/metal/BufferManager.h similarity index 89% rename from core/renderer/backend/metal/BufferManager.h rename to axmol/rhi/metal/BufferManager.h index 2edae7ae999a..117a86e40359 100644 --- a/core/renderer/backend/metal/BufferManager.h +++ b/axmol/rhi/metal/BufferManager.h @@ -25,11 +25,11 @@ #pragma once #include -#include "../Macros.h" +#include "axmol/rhi/RHITypes.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { -class BufferMTL; +class BufferImpl; /** * @addtogroup _metal @@ -47,13 +47,13 @@ class BufferManager * Add a buffer object into container. * @param buffer Specifies the buffer to be added. */ - static void addBuffer(BufferMTL* buffer); + static void addBuffer(BufferImpl* buffer); /** * Remove a buffer object from container. * @param buffer Specifies the buffer to be removed. */ - static void removeBuffer(BufferMTL* buffer); + static void removeBuffer(BufferImpl* buffer); /** * Schedule next available buffer at the beginning of frame for the following render passes. @@ -61,9 +61,9 @@ class BufferManager static void beginFrame(); private: - static std::vector _buffers; + static std::vector _buffers; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/BufferManager.mm b/axmol/rhi/metal/BufferManager.mm similarity index 85% rename from core/renderer/backend/metal/BufferManager.mm rename to axmol/rhi/metal/BufferManager.mm index 1a0ac0237469..5d57d7c24bd3 100644 --- a/core/renderer/backend/metal/BufferManager.mm +++ b/axmol/rhi/metal/BufferManager.mm @@ -22,19 +22,19 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "BufferManager.h" -#include "BufferMTL.h" +#include "axmol/rhi/metal/BufferManager.h" +#include "axmol/rhi/metal/BufferMTL.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { -std::vector BufferManager::_buffers; +std::vector BufferManager::_buffers; -void BufferManager::addBuffer(BufferMTL* buffer) +void BufferManager::addBuffer(BufferImpl* buffer) { _buffers.push_back(buffer); } -void BufferManager::removeBuffer(BufferMTL* buffer) +void BufferManager::removeBuffer(BufferImpl* buffer) { auto iter = std::find(_buffers.begin(), _buffers.end(), buffer); if (_buffers.end() != iter) @@ -47,4 +47,4 @@ of this software and associated documentation files (the "Software"), to deal buffer->beginFrame(); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/CommandBufferMTL.h b/axmol/rhi/metal/CommandBufferMTL.h similarity index 87% rename from core/renderer/backend/metal/CommandBufferMTL.h rename to axmol/rhi/metal/CommandBufferMTL.h index 242c0aee9252..e8a9b37d554b 100644 --- a/core/renderer/backend/metal/CommandBufferMTL.h +++ b/axmol/rhi/metal/CommandBufferMTL.h @@ -25,14 +25,14 @@ #pragma once -#include "../CommandBuffer.h" -#include "DriverMTL.h" +#include "axmol/rhi/CommandBuffer.h" +#include "axmol/rhi/metal/DriverMTL.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { -class RenderPipelineMTL; -class DepthStencilStateMTL; +class RenderPipelineImpl; +class DepthStencilStateImpl; /** * @addtogroup _metal @@ -43,15 +43,15 @@ class DepthStencilStateMTL; * @brief Store encoded commands for the GPU to execute. * A command buffer stores encoded commands until the buffer is committed for execution by the GPU */ -class CommandBufferMTL : public CommandBuffer +class CommandBufferImpl : public CommandBuffer { public: /// @name Constructor, Destructor and Initializers /** * @param driver The device for which MTLCommandQueue object was created. */ - CommandBufferMTL(DriverMTL* driver); - ~CommandBufferMTL(); + CommandBufferImpl(DriverImpl* driver); + ~CommandBufferImpl(); /** * Set depthStencil status @@ -76,26 +76,26 @@ class CommandBufferMTL : public CommandBuffer bool beginFrame() override; /** - * Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDescriptor. - * MTLRenderCommandEncoder is cached if current RenderPassDescriptor is identical to previous one. + * Create a MTLRenderCommandEncoder object for graphics rendering to an attachment in a RenderPassDesc. + * MTLRenderCommandEncoder is cached if current RenderPassDesc is identical to previous one. * @param descriptor Specifies a group of render targets that hold the results of a render pass. */ - void beginRenderPass(const RenderTarget* renderTarget, const RenderPassDescriptor& descriptor) override; + void beginRenderPass(const RenderTarget* renderTarget, const RenderPassDesc& descriptor) override; /** * Update depthStencil status, improvment: for metal backend cache it * @param depthStencilState Specifies the depth and stencil status */ - void updateDepthStencilState(const DepthStencilDescriptor& descriptor) override; + void updateDepthStencilState(const DepthStencilDesc& descriptor) override; /** * Update render pipeline status * Building a programmable pipeline involves an expensive evaluation of GPU state. * So a new render pipeline object will be created only if it hasn't been created before. * @param rt Specifies the render target. - * @param pipelineDescriptor Specifies the pipeline descriptor. + * @param desc Specifies the pipeline descriptor. */ - void updatePipelineState(const RenderTarget* rt, const PipelineDescriptor& descriptor) override; + void updatePipelineState(const RenderTarget* rt, const PipelineDesc& desc) override; /** * Fixed-function state @@ -150,6 +150,11 @@ class CommandBufferMTL : public CommandBuffer * TODO: Implement a wireframe mode for METAL devices. Refer to: https://forums.ogre3d.org/viewtopic.php?t=95089 */ void drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe) override; + void drawArraysInstanced(PrimitiveType primitiveType, + std::size_t start, + std::size_t count, + int instanceCount, + bool wireframe = false) override; /** * Draw primitives with an index list. @@ -199,7 +204,7 @@ class CommandBufferMTL : public CommandBuffer * Read pixels from RenderTarget * @param callback A callback to deal with pixel data read. */ - void readPixels(RenderTarget* rt, std::function callback) override; + void readPixels(RenderTarget* rt, std::function callback) override; id getRenderCommandEncoder() const { return _mtlRenderEncoder; } @@ -216,18 +221,18 @@ class CommandBufferMTL : public CommandBuffer * @param pbd, the output buffer for fill texels data * @remark: !!!this function only can call after endFrame, then it's could be works well. */ - static void readPixels(TextureBackend* texture, + static void readPixels(Texture* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, - PixelBufferDescriptor& pbd); + PixelBufferDesc& pbd); static void readPixels(id texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, - PixelBufferDescriptor& pbd); + PixelBufferDesc& pbd); private: void prepareDrawing() const; @@ -237,7 +242,7 @@ class CommandBufferMTL : public CommandBuffer void afterDraw(); void flush(); void flushCaptureCommands(); - void updateRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassDescriptor& renderPassParams); + void updateRenderCommandEncoder(const RenderTarget* renderTarget, const RenderPassDesc& renderPassParams); id _mtlCommandBuffer = nil; id _mtlCommandQueue = nil; @@ -245,21 +250,21 @@ class CommandBufferMTL : public CommandBuffer id _mtlIndexBuffer = nil; id _drawableTexture = nil; - DepthStencilStateMTL* _depthStencilStateMTL = nullptr; - RenderPipelineMTL* _renderPipelineMTL = nullptr; - ProgramState* _programState = nullptr; + DepthStencilStateImpl* _depthStencilStateImpl = nullptr; + RenderPipelineImpl* _renderPipelineImpl = nullptr; + ProgramState* _programState = nullptr; unsigned int _renderTargetWidth = 0; unsigned int _renderTargetHeight = 0; dispatch_semaphore_t _frameBoundarySemaphore; const RenderTarget* _currentRenderTarget = nil; // weak ref - RenderPassDescriptor _currentRenderPassDesc; + RenderPassDesc _currentRenderPassDesc; NSAutoreleasePool* _autoReleasePool = nil; - std::vector>> _captureCallbacks; + std::vector>> _captureCallbacks; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/CommandBufferMTL.mm b/axmol/rhi/metal/CommandBufferMTL.mm similarity index 71% rename from core/renderer/backend/metal/CommandBufferMTL.mm rename to axmol/rhi/metal/CommandBufferMTL.mm index 0520cbb32e5d..03eb6dca67a3 100644 --- a/core/renderer/backend/metal/CommandBufferMTL.mm +++ b/axmol/rhi/metal/CommandBufferMTL.mm @@ -23,18 +23,17 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "CommandBufferMTL.h" -#include "BufferMTL.h" -#include "DriverMTL.h" -#include "RenderPipelineMTL.h" -#include "TextureMTL.h" -#include "UtilsMTL.h" -#include "../Macros.h" -#include "BufferManager.h" -#include "DepthStencilStateMTL.h" -#include "RenderTargetMTL.h" - -NS_AX_BACKEND_BEGIN +#include "axmol/rhi/metal/CommandBufferMTL.h" +#include "axmol/rhi/metal/BufferMTL.h" +#include "axmol/rhi/metal/DriverMTL.h" +#include "axmol/rhi/metal/RenderPipelineMTL.h" +#include "axmol/rhi/metal/TextureMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/rhi/metal/BufferManager.h" +#include "axmol/rhi/metal/DepthStencilStateMTL.h" +#include "axmol/rhi/metal/RenderTargetMTL.h" + +namespace ax::rhi::mtl { namespace { @@ -126,32 +125,23 @@ static MTLCullMode toMTLCullMode(CullMode mode) } } -static MTLRenderPassDescriptor* toMTLRenderPassDescriptor(const RenderTarget* rt, const RenderPassDescriptor& desc) +static MTLRenderPassDescriptor* toMTLRenderPassDesc(const RenderTarget* rt, const RenderPassDesc& desc) { - MTLRenderPassDescriptor* mtlDescritpor = [MTLRenderPassDescriptor renderPassDescriptor]; + MTLRenderPassDescriptor* mtlDesc = [MTLRenderPassDescriptor renderPassDescriptor]; - auto rtMTL = static_cast(rt); - rtMTL->applyRenderPassAttachments(desc, mtlDescritpor); - return mtlDescritpor; + auto rtMTL = static_cast(rt); + rtMTL->applyRenderPassAttachments(desc, mtlDesc); + return mtlDesc; } -static id getMTLTexture(TextureBackend* texture, int index) +static id getMTLTexture(Texture* texture, int index) { - return reinterpret_cast>(texture->getHandler(index)); + return static_cast(texture)->internalHandle(index); } -static id getMTLSamplerState(TextureBackend* texture) +static id getMTLSamplerState(Texture* texture) { - switch (texture->getTextureType()) - { - case TextureType::TEXTURE_2D: - return static_cast(texture)->getMTLSamplerState(); - case TextureType::TEXTURE_CUBE: - return static_cast(texture)->getMTLSamplerState(); - default: - assert(false); - return nil; - } + return static_cast(texture)->internalSampler(); } inline int clamp(int value, int min, int max) @@ -160,12 +150,12 @@ inline int clamp(int value, int min, int max) } } -CommandBufferMTL::CommandBufferMTL(DriverMTL* driver) +CommandBufferImpl::CommandBufferImpl(DriverImpl* driver) : _mtlCommandQueue(driver->getMTLCommandQueue()) , _frameBoundarySemaphore(dispatch_semaphore_create(MAX_INFLIGHT_BUFFER)) {} -CommandBufferMTL::~CommandBufferMTL() +CommandBufferImpl::~CommandBufferImpl() { // Wait for all frames to finish by submitting and waiting on a dummy command buffer. flush(); @@ -176,17 +166,17 @@ inline int clamp(int value, int min, int max) dispatch_semaphore_signal(_frameBoundarySemaphore); } -void CommandBufferMTL::setDepthStencilState(DepthStencilState* depthStencilState) +void CommandBufferImpl::setDepthStencilState(DepthStencilState* depthStencilState) { - _depthStencilStateMTL = static_cast(depthStencilState); + _depthStencilStateImpl = static_cast(depthStencilState); } -void CommandBufferMTL::setRenderPipeline(RenderPipeline* renderPipeline) +void CommandBufferImpl::setRenderPipeline(RenderPipeline* renderPipeline) { - _renderPipelineMTL = static_cast(renderPipeline); + _renderPipelineImpl = static_cast(renderPipeline); } -bool CommandBufferMTL::beginFrame() +bool CommandBufferImpl::beginFrame() { _autoReleasePool = [[NSAutoreleasePool alloc] init]; dispatch_semaphore_wait(_frameBoundarySemaphore, DISPATCH_TIME_FOREVER); @@ -200,8 +190,8 @@ inline int clamp(int value, int min, int max) return true; } -void CommandBufferMTL::updateRenderCommandEncoder(const RenderTarget* renderTarget, - const RenderPassDescriptor& renderPassDesc) +void CommandBufferImpl::updateRenderCommandEncoder(const RenderTarget* renderTarget, + const RenderPassDesc& renderPassDesc) { if (_mtlRenderEncoder != nil && _currentRenderPassDesc == renderPassDesc && _currentRenderTarget == renderTarget && !renderTarget->isDirty()) @@ -219,31 +209,31 @@ inline int clamp(int value, int min, int max) _mtlRenderEncoder = nil; } - auto mtlDescriptor = toMTLRenderPassDescriptor(renderTarget, renderPassDesc); - _renderTargetWidth = (unsigned int)mtlDescriptor.colorAttachments[0].texture.width; - _renderTargetHeight = (unsigned int)mtlDescriptor.colorAttachments[0].texture.height; - _mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDescriptor]; + auto mtlDesc = toMTLRenderPassDesc(renderTarget, renderPassDesc); + _renderTargetWidth = (unsigned int)mtlDesc.colorAttachments[0].texture.width; + _renderTargetHeight = (unsigned int)mtlDesc.colorAttachments[0].texture.height; + _mtlRenderEncoder = [_mtlCommandBuffer renderCommandEncoderWithDescriptor:mtlDesc]; [_mtlRenderEncoder retain]; } -void CommandBufferMTL::beginRenderPass(const RenderTarget* renderTarget, const RenderPassDescriptor& renderPassDesc) +void CommandBufferImpl::beginRenderPass(const RenderTarget* renderTarget, const RenderPassDesc& renderPassDesc) { updateRenderCommandEncoder(renderTarget, renderPassDesc); // [_mtlRenderEncoder setFrontFacingWinding:MTLWindingCounterClockwise]; } -void CommandBufferMTL::updateDepthStencilState(const DepthStencilDescriptor& descriptor) +void CommandBufferImpl::updateDepthStencilState(const DepthStencilDesc& descriptor) { - _depthStencilStateMTL->update(descriptor); + _depthStencilStateImpl->update(descriptor); } -void CommandBufferMTL::updatePipelineState(const RenderTarget* rt, const PipelineDescriptor& descriptor) +void CommandBufferImpl::updatePipelineState(const RenderTarget* rt, const PipelineDesc& descriptor) { - _renderPipelineMTL->update(rt, descriptor); - [_mtlRenderEncoder setRenderPipelineState:_renderPipelineMTL->getMTLRenderPipelineState()]; + _renderPipelineImpl->update(rt, descriptor); + [_mtlRenderEncoder setRenderPipelineState:_renderPipelineImpl->getMTLRenderPipelineState()]; } -void CommandBufferMTL::setViewport(int x, int y, unsigned int w, unsigned int h) +void CommandBufferImpl::setViewport(int x, int y, unsigned int w, unsigned int h) { MTLViewport viewport; viewport.originX = x; @@ -255,52 +245,58 @@ inline int clamp(int value, int min, int max) [_mtlRenderEncoder setViewport:viewport]; } -void CommandBufferMTL::setCullMode(CullMode mode) +void CommandBufferImpl::setCullMode(CullMode mode) { [_mtlRenderEncoder setCullMode:toMTLCullMode(mode)]; } -void CommandBufferMTL::setWinding(Winding winding) +void CommandBufferImpl::setWinding(Winding winding) { [_mtlRenderEncoder setFrontFacingWinding:toMTLWinding(winding)]; } -void CommandBufferMTL::setVertexBuffer(Buffer* buffer) +void CommandBufferImpl::setVertexBuffer(Buffer* buffer) { // Vertex buffer is bound in index DEFAULT_ATTRIBS_BINDING_INDEX. - [_mtlRenderEncoder setVertexBuffer:static_cast(buffer)->getMTLBuffer() offset:0 atIndex:DriverMTL::DEFAULT_ATTRIBS_BINDING_INDEX]; + [_mtlRenderEncoder setVertexBuffer:static_cast(buffer)->getMTLBuffer() offset:0 atIndex:DriverImpl::DEFAULT_ATTRIBS_BINDING_INDEX]; } -void CommandBufferMTL::setInstanceBuffer(Buffer* buffer) { +void CommandBufferImpl::setInstanceBuffer(Buffer* buffer) { // Vertex instancing transform buffer is bound in index VBO_INSTANCING_BINDING_INDEX. // TODO: sync device binding macros to AXSLCC - [_mtlRenderEncoder setVertexBuffer:static_cast(buffer)->getMTLBuffer() offset:0 atIndex:DriverMTL::VBO_INSTANCING_BINDING_INDEX]; + [_mtlRenderEncoder setVertexBuffer:static_cast(buffer)->getMTLBuffer() offset:0 atIndex:DriverImpl::VBO_INSTANCING_BINDING_INDEX]; } -void CommandBufferMTL::setProgramState(ProgramState* programState) +void CommandBufferImpl::setProgramState(ProgramState* programState) { AX_SAFE_RETAIN(programState); AX_SAFE_RELEASE(_programState); _programState = programState; } -void CommandBufferMTL::setIndexBuffer(Buffer* buffer) +void CommandBufferImpl::setIndexBuffer(Buffer* buffer) { assert(buffer != nullptr); if (!buffer) return; - _mtlIndexBuffer = static_cast(buffer)->getMTLBuffer(); + _mtlIndexBuffer = static_cast(buffer)->getMTLBuffer(); [_mtlIndexBuffer retain]; } -void CommandBufferMTL::drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe /* unused */) +void CommandBufferImpl::drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe /* unused */) { prepareDrawing(); [_mtlRenderEncoder drawPrimitives:toMTLPrimitive(primitiveType) vertexStart:start vertexCount:count]; } -void CommandBufferMTL::drawElements(PrimitiveType primitiveType, +void CommandBufferImpl::drawArraysInstanced(PrimitiveType primitiveType, std::size_t start, std::size_t count, int instanceCount, bool wireframe /* unused */) +{ + prepareDrawing(); + [_mtlRenderEncoder drawPrimitives:toMTLPrimitive(primitiveType) vertexStart:start vertexCount:count instanceCount:instanceCount]; +} + +void CommandBufferImpl::drawElements(PrimitiveType primitiveType, IndexFormat indexType, std::size_t count, std::size_t offset, @@ -308,13 +304,13 @@ inline int clamp(int value, int min, int max) { prepareDrawing(); [_mtlRenderEncoder drawIndexedPrimitives:toMTLPrimitive(primitiveType) - indexCount:count - indexType:toMTLIndexType(indexType) - indexBuffer:_mtlIndexBuffer - indexBufferOffset:offset]; + indexCount:count + indexType:toMTLIndexType(indexType) + indexBuffer:_mtlIndexBuffer + indexBufferOffset:offset]; } -void CommandBufferMTL::drawElementsInstanced(PrimitiveType primitiveType, +void CommandBufferImpl::drawElementsInstanced(PrimitiveType primitiveType, IndexFormat indexType, std::size_t count, std::size_t offset, @@ -323,21 +319,21 @@ inline int clamp(int value, int min, int max) { prepareDrawing(); [_mtlRenderEncoder drawIndexedPrimitives:toMTLPrimitive(primitiveType) - indexCount:count - indexType:toMTLIndexType(indexType) - indexBuffer:_mtlIndexBuffer - indexBufferOffset:offset - instanceCount:instanceCount]; + indexCount:count + indexType:toMTLIndexType(indexType) + indexBuffer:_mtlIndexBuffer + indexBufferOffset:offset + instanceCount:instanceCount]; } -void CommandBufferMTL::endRenderPass() +void CommandBufferImpl::endRenderPass() { afterDraw(); } -void CommandBufferMTL::readPixels(RenderTarget* rt, std::function callback) +void CommandBufferImpl::readPixels(RenderTarget* rt, std::function callback) { - auto rtMTL = static_cast(rt); + auto rtMTL = static_cast(rt); // we only read form color attachment 0 // if it's nullptr, will regard as screen to perform capture @@ -346,13 +342,13 @@ inline int clamp(int value, int min, int max) _captureCallbacks.emplace_back(texture, std::move(callback)); } -void CommandBufferMTL::endFrame() +void CommandBufferImpl::endFrame() { [_mtlRenderEncoder endEncoding]; [_mtlRenderEncoder release]; _mtlRenderEncoder = nil; - auto currentDrawable = DriverMTL::getCurrentDrawable(); + auto currentDrawable = DriverImpl::getCurrentDrawable(); [_mtlCommandBuffer presentDrawable:currentDrawable]; _drawableTexture = currentDrawable.texture; [_mtlCommandBuffer addCompletedHandler:^(id commandBuffer) { @@ -363,11 +359,11 @@ inline int clamp(int value, int min, int max) flush(); - DriverMTL::resetCurrentDrawable(); + DriverImpl::resetCurrentDrawable(); [_autoReleasePool drain]; } -void CommandBufferMTL::endEncoding() +void CommandBufferImpl::endEncoding() { if (_mtlRenderEncoder) { [_mtlRenderEncoder endEncoding]; @@ -376,7 +372,7 @@ inline int clamp(int value, int min, int max) _mtlRenderEncoder = nil; } -void CommandBufferMTL::flush() +void CommandBufferImpl::flush() { if (_mtlCommandBuffer) { @@ -390,7 +386,7 @@ inline int clamp(int value, int min, int max) } } -void CommandBufferMTL::flushCaptureCommands() +void CommandBufferImpl::flushCaptureCommands() { if (!_captureCallbacks.empty()) { @@ -400,26 +396,26 @@ inline int clamp(int value, int min, int max) // !!!Notes, MTL is mutli-threading, all GPU handler is dispatch at GPU threads [_mtlCommandBuffer waitUntilCompleted]; - PixelBufferDescriptor screenPixelData; + PixelBufferDesc screenPixelData; for (auto& cb : _captureCallbacks) { if (cb.first == nil) { // screen capture if (!screenPixelData) { - CommandBufferMTL::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], + CommandBufferImpl::readPixels(_drawableTexture, 0, 0, [_drawableTexture width], [_drawableTexture height], screenPixelData); // screen framebuffer copied, restore screen framebuffer only to true - backend::DriverBase::getInstance()->setFrameBufferOnly(true); + rhi::DriverBase::getInstance()->setFrameBufferOnly(true); } cb.second(screenPixelData); } else { - PixelBufferDescriptor pixelData; + PixelBufferDesc pixelData; auto texture = cb.first; assert(texture != nullptr); - CommandBufferMTL::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData); + CommandBufferImpl::readPixels(texture, 0, 0, texture->getWidth(), texture->getHeight(), pixelData); AX_SAFE_RELEASE(texture); cb.second(pixelData); } @@ -428,7 +424,7 @@ inline int clamp(int value, int min, int max) } } -void CommandBufferMTL::afterDraw() +void CommandBufferImpl::afterDraw() { if (_mtlIndexBuffer) { @@ -439,21 +435,21 @@ inline int clamp(int value, int min, int max) AX_SAFE_RELEASE_NULL(_programState); } -void CommandBufferMTL::prepareDrawing() const +void CommandBufferImpl::prepareDrawing() const { setUniformBuffer(); setTextures(); - auto mtlDepthStencilState = _depthStencilStateMTL->getMTLDepthStencilState(); + auto mtlDepthStencilState = _depthStencilStateImpl->getMTLDepthStencilState(); if (mtlDepthStencilState) { [_mtlRenderEncoder setDepthStencilState:mtlDepthStencilState]; - [_mtlRenderEncoder setStencilFrontReferenceValue:_stencilReferenceValueFront - backReferenceValue:_stencilReferenceValueBack]; + [_mtlRenderEncoder setStencilFrontReferenceValue:_stencilReferenceValue + backReferenceValue:_stencilReferenceValue]; } } -void CommandBufferMTL::setTextures() const +void CommandBufferImpl::setTextures() const { if (_programState) { @@ -462,7 +458,7 @@ inline int clamp(int value, int min, int max) } } -void CommandBufferMTL::doSetTextures(bool isVertex) const +void CommandBufferImpl::doSetTextures(bool isVertex) const { const auto& bindTextureInfos = (isVertex) ? _programState->getVertexTextureInfos() : _programState->getFragmentTextureInfos(); @@ -495,7 +491,7 @@ inline int clamp(int value, int min, int max) } } -void CommandBufferMTL::setUniformBuffer() const +void CommandBufferImpl::setUniformBuffer() const { if (_programState) { @@ -504,7 +500,7 @@ inline int clamp(int value, int min, int max) cb.second(_programState, cb.first); // Uniform buffer: glsl-optimizer is bound to index 1, axslcc: bound to 0 - constexpr int bindingIndex = DriverMTL::VBO_BINDING_INDEX_START; + constexpr int bindingIndex = DriverImpl::VBO_BINDING_INDEX_START; std::size_t bufferSize = 0; auto vertexBuffer = _programState->getVertexUniformBuffer(bufferSize); if (bufferSize) @@ -520,7 +516,7 @@ inline int clamp(int value, int min, int max) } } -void CommandBufferMTL::setScissorRect(bool isEnabled, float x, float y, float width, float height) +void CommandBufferImpl::setScissorRect(bool isEnabled, float x, float y, float width, float height) { MTLScissorRect scissorRect; if (isEnabled) @@ -550,38 +546,38 @@ inline int clamp(int value, int min, int max) [_mtlRenderEncoder setScissorRect:scissorRect]; } -void CommandBufferMTL::readPixels(TextureBackend* texture, +void CommandBufferImpl::readPixels(Texture* texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, - PixelBufferDescriptor& pbd) + PixelBufferDesc& pbd) { - CommandBufferMTL::readPixels(reinterpret_cast>(texture->getHandler()), origX, origY, rectWidth, + CommandBufferImpl::readPixels(static_cast(texture)->internalHandle(), origX, origY, rectWidth, rectHeight, pbd); } -void CommandBufferMTL::readPixels(id texture, +void CommandBufferImpl::readPixels(id texture, std::size_t origX, std::size_t origY, std::size_t rectWidth, std::size_t rectHeight, - PixelBufferDescriptor& pbd) + PixelBufferDesc& pbd) { NSUInteger texWidth = texture.width; NSUInteger texHeight = texture.height; MTLRegion region = MTLRegionMake2D(0, 0, texWidth, texHeight); MTLRegion imageRegion = MTLRegionMake2D(origX, origY, rectWidth, rectHeight); - MTLTextureDescriptor* textureDescriptor = + MTLTextureDescriptor* textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:[texture pixelFormat] width:texWidth height:texHeight mipmapped:NO]; - id device = static_cast(DriverMTL::getInstance())->getMTLDevice(); - id readPixelsTexture = [device newTextureWithDescriptor:textureDescriptor]; + id device = static_cast(DriverBase::getInstance())->getMTLDevice(); + id readPixelsTexture = [device newTextureWithDescriptor:textureDesc]; - id commandQueue = static_cast(DriverMTL::getInstance())->getMTLCommandQueue(); + id commandQueue = static_cast(DriverBase::getInstance())->getMTLCommandQueue(); auto commandBuffer = [commandQueue commandBuffer]; // [commandBuffer enqueue]; @@ -617,4 +613,4 @@ inline int clamp(int value, int min, int max) [commandBuffer waitUntilCompleted]; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/DepthStencilStateMTL.h b/axmol/rhi/metal/DepthStencilStateMTL.h similarity index 89% rename from core/renderer/backend/metal/DepthStencilStateMTL.h rename to axmol/rhi/metal/DepthStencilStateMTL.h index fcc889b81aab..c5581d43932f 100644 --- a/core/renderer/backend/metal/DepthStencilStateMTL.h +++ b/axmol/rhi/metal/DepthStencilStateMTL.h @@ -25,12 +25,12 @@ #pragma once -#include "../DepthStencilState.h" +#include "axmol/rhi/DepthStencilState.h" #import #include "tsl/robin_map.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { /** * @addtogroup _metal @@ -40,17 +40,17 @@ NS_AX_BACKEND_BEGIN /** * A class represent a depth/stencil test status. */ -class DepthStencilStateMTL : public DepthStencilState +class DepthStencilStateImpl : public DepthStencilState { public: /// @name Constructor, Destructor and Initializers /** * @param mtlDevice The device for which MTLDepthStencilState object was created. */ - DepthStencilStateMTL(id mtlDevice); - ~DepthStencilStateMTL(); + DepthStencilStateImpl(id mtlDevice); + ~DepthStencilStateImpl(); - void update(const DepthStencilDescriptor& dsDesc) override; + void update(const DepthStencilDesc& dsDesc) override; /// @name Setters & Getters /** @@ -71,4 +71,4 @@ class DepthStencilStateMTL : public DepthStencilState // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/DepthStencilStateMTL.mm b/axmol/rhi/metal/DepthStencilStateMTL.mm similarity index 56% rename from core/renderer/backend/metal/DepthStencilStateMTL.mm rename to axmol/rhi/metal/DepthStencilStateMTL.mm index ceac2a6e4ea7..afdba5287523 100644 --- a/core/renderer/backend/metal/DepthStencilStateMTL.mm +++ b/axmol/rhi/metal/DepthStencilStateMTL.mm @@ -23,41 +23,41 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "DepthStencilStateMTL.h" -#include "../RenderTarget.h" +#include "axmol/rhi/metal/DepthStencilStateMTL.h" +#include "axmol/rhi/RenderTarget.h" #include "xxhash.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { namespace { -MTLCompareFunction toMTLCompareFunction(CompareFunction compareFunction) +static MTLCompareFunction toMTLCompareFunc(CompareFunc func) { MTLCompareFunction ret = MTLCompareFunctionNever; - switch (compareFunction) + switch (func) { - case CompareFunction::NEVER: + case CompareFunc::NEVER: ret = MTLCompareFunctionNever; break; - case CompareFunction::LESS: + case CompareFunc::LESS: ret = MTLCompareFunctionLess; break; - case CompareFunction::LESS_EQUAL: + case CompareFunc::LESS_EQUAL: ret = MTLCompareFunctionLessEqual; break; - case CompareFunction::GREATER: + case CompareFunc::GREATER: ret = MTLCompareFunctionGreater; break; - case CompareFunction::GREATER_EQUAL: + case CompareFunc::GREATER_EQUAL: ret = MTLCompareFunctionGreaterEqual; break; - case CompareFunction::EQUAL: + case CompareFunc::EQUAL: ret = MTLCompareFunctionEqual; break; - case CompareFunction::NOT_EQUAL: + case CompareFunc::NOT_EQUAL: ret = MTLCompareFunctionNotEqual; break; - case CompareFunction::ALWAYS: + case CompareFunc::ALWAYS: ret = MTLCompareFunctionAlways; break; default: @@ -67,27 +67,27 @@ MTLCompareFunction toMTLCompareFunction(CompareFunction compareFunction) return ret; } -MTLStencilOperation toMTLStencilOperation(StencilOperation operation) +static MTLStencilOperation toMTLStencilOp(StencilOp op) { MTLStencilOperation ret = MTLStencilOperationKeep; - switch (operation) + switch (op) { - case StencilOperation::KEEP: + case StencilOp::KEEP: ret = MTLStencilOperationKeep; break; - case StencilOperation::ZERO: + case StencilOp::ZERO: ret = MTLStencilOperationZero; break; - case StencilOperation::REPLACE: + case StencilOp::REPLACE: ret = MTLStencilOperationReplace; break; - case StencilOperation::INVERT: + case StencilOp::INVERT: ret = MTLStencilOperationInvert; break; - case StencilOperation::INCREMENT_WRAP: + case StencilOp::INCREMENT_WRAP: ret = MTLStencilOperationIncrementWrap; break; - case StencilOperation::DECREMENT_WRAP: + case StencilOp::DECREMENT_WRAP: ret = MTLStencilOperationDecrementWrap; break; default: @@ -97,26 +97,26 @@ MTLStencilOperation toMTLStencilOperation(StencilOperation operation) return ret; } -void setMTLStencilDescriptor(MTLStencilDescriptor* stencilDescriptor, const StencilDescriptor& descriptor) +static void setMTLStencilDesc(MTLStencilDescriptor* stencilDesc, const StencilDesc& desc) { - stencilDescriptor.stencilFailureOperation = toMTLStencilOperation(descriptor.stencilFailureOperation); - stencilDescriptor.depthFailureOperation = toMTLStencilOperation(descriptor.depthFailureOperation); - stencilDescriptor.depthStencilPassOperation = toMTLStencilOperation(descriptor.depthStencilPassOperation); - stencilDescriptor.stencilCompareFunction = toMTLCompareFunction(descriptor.stencilCompareFunction); - stencilDescriptor.readMask = descriptor.readMask; - stencilDescriptor.writeMask = descriptor.writeMask; + stencilDesc.stencilFailureOperation = toMTLStencilOp(desc.stencilFailureOp); + stencilDesc.depthFailureOperation = toMTLStencilOp(desc.depthFailureOp); + stencilDesc.depthStencilPassOperation = toMTLStencilOp(desc.depthStencilPassOp); + stencilDesc.stencilCompareFunction = toMTLCompareFunc(desc.stencilCompareFunc); + stencilDesc.readMask = desc.readMask; + stencilDesc.writeMask = desc.writeMask; } } -DepthStencilStateMTL::DepthStencilStateMTL(id mtlDevice) : _mtlDevice(mtlDevice) +DepthStencilStateImpl::DepthStencilStateImpl(id mtlDevice) : _mtlDevice(mtlDevice) { // By default MTLDepthStencilDescriptor disables depth and stencil access - MTLDepthStencilDescriptor* mtlDescriptor = [MTLDepthStencilDescriptor new]; - _mtlDepthStencilDisabledState = [mtlDevice newDepthStencilStateWithDescriptor:mtlDescriptor]; - [mtlDescriptor release]; + MTLDepthStencilDescriptor* mtlDesc = [MTLDepthStencilDescriptor new]; + _mtlDepthStencilDisabledState = [mtlDevice newDepthStencilStateWithDescriptor:mtlDesc]; + [mtlDesc release]; } -void DepthStencilStateMTL::update(const DepthStencilDescriptor& dsDesc) +void DepthStencilStateImpl::update(const DepthStencilDesc& dsDesc) { DepthStencilState::update(dsDesc); @@ -126,12 +126,12 @@ void setMTLStencilDescriptor(MTLStencilDescriptor* stencilDescriptor, const Sten return; } - DepthStencilDescriptor hashMe; + DepthStencilDesc hashMe; memset(&hashMe, 0, sizeof(hashMe)); - hashMe.depthCompareFunction = dsDesc.depthCompareFunction; - hashMe.backFaceStencil = dsDesc.backFaceStencil; - hashMe.frontFaceStencil = dsDesc.frontFaceStencil; - hashMe.flags = dsDesc.flags; + hashMe.depthCompareFunc = dsDesc.depthCompareFunc; + hashMe.backFaceStencil = dsDesc.backFaceStencil; + hashMe.frontFaceStencil = dsDesc.frontFaceStencil; + hashMe.flags = dsDesc.flags; auto key = XXH32((const void*)&hashMe, sizeof(hashMe), 0); auto it = _mtlStateCache.find(key); @@ -141,29 +141,29 @@ void setMTLStencilDescriptor(MTLStencilDescriptor* stencilDescriptor, const Sten return; } - MTLDepthStencilDescriptor* mtlDescriptor = [[MTLDepthStencilDescriptor alloc] init]; + MTLDepthStencilDescriptor* mtlDesc = [[MTLDepthStencilDescriptor alloc] init]; if (bitmask::any(dsDesc.flags, DepthStencilFlags::DEPTH_TEST)) - mtlDescriptor.depthCompareFunction = toMTLCompareFunction(_depthStencilInfo.depthCompareFunction); + mtlDesc.depthCompareFunction = toMTLCompareFunc(_dsDesc.depthCompareFunc); else - mtlDescriptor.depthCompareFunction = MTLCompareFunctionAlways; + mtlDesc.depthCompareFunction = MTLCompareFunctionAlways; - mtlDescriptor.depthWriteEnabled = bitmask::any(dsDesc.flags, DepthStencilFlags::DEPTH_WRITE); + mtlDesc.depthWriteEnabled = bitmask::any(dsDesc.flags, DepthStencilFlags::DEPTH_WRITE); if (bitmask::any(dsDesc.flags, DepthStencilFlags::STENCIL_TEST)) { - setMTLStencilDescriptor(mtlDescriptor.frontFaceStencil, _depthStencilInfo.frontFaceStencil); - setMTLStencilDescriptor(mtlDescriptor.backFaceStencil, _depthStencilInfo.backFaceStencil); + setMTLStencilDesc(mtlDesc.frontFaceStencil, _dsDesc.frontFaceStencil); + setMTLStencilDesc(mtlDesc.backFaceStencil, _dsDesc.backFaceStencil); } - _mtlDepthStencilState = [_mtlDevice newDepthStencilStateWithDescriptor:mtlDescriptor]; - [mtlDescriptor release]; + _mtlDepthStencilState = [_mtlDevice newDepthStencilStateWithDescriptor:mtlDesc]; + [mtlDesc release]; // emplace to state cache _mtlStateCache.emplace(key, _mtlDepthStencilState); } -DepthStencilStateMTL::~DepthStencilStateMTL() +DepthStencilStateImpl::~DepthStencilStateImpl() { _mtlDepthStencilState = nullptr; [_mtlDepthStencilDisabledState release]; @@ -172,4 +172,4 @@ void setMTLStencilDescriptor(MTLStencilDescriptor* stencilDescriptor, const Sten _mtlStateCache.clear(); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/DriverMTL.h b/axmol/rhi/metal/DriverMTL.h similarity index 84% rename from core/renderer/backend/metal/DriverMTL.h rename to axmol/rhi/metal/DriverMTL.h index 04512d36afb3..ae390ab21861 100644 --- a/core/renderer/backend/metal/DriverMTL.h +++ b/axmol/rhi/metal/DriverMTL.h @@ -25,11 +25,11 @@ #pragma once -#include "../DriverBase.h" +#include "axmol/rhi/DriverBase.h" #import #import -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { enum class FeatureSet : int32_t { @@ -75,7 +75,7 @@ enum class FeatureSet : int32_t /** * Create resources from MTLDevice. */ -class DriverMTL : public DriverBase +class DriverImpl : public DriverBase { public: /* The max vertex attribs, it's not how many device supports which may be lower. */ @@ -107,7 +107,7 @@ class DriverMTL : public DriverBase * Get a CAMetalLayer. * @return A CAMetalLayer object. */ - static CAMetalLayer* getCAMetalLayer() { return DriverMTL::_metalLayer; } + static CAMetalLayer* getCAMetalLayer() { return DriverImpl::_metalLayer; } /** * Get available Drawable. @@ -121,15 +121,15 @@ class DriverMTL : public DriverBase static void resetCurrentDrawable(); /// @name Constructor, Destructor and Initializers - DriverMTL(); - ~DriverMTL(); + DriverImpl(); + ~DriverImpl(); /// @name Setters & Getters /** * New a CommandBuffer object. * @return A CommandBuffer object. */ - CommandBuffer* newCommandBuffer() override; + CommandBuffer* createCommandBuffer(void*) override; /** * New a Buffer object. @@ -140,31 +140,30 @@ class DriverMTL : public DriverBase * BufferUsage::STATIC, BufferUsage::DYNAMIC. * @return A Buffer object. */ - Buffer* newBuffer(std::size_t size, BufferType type, BufferUsage usage) override; + Buffer* createBuffer(std::size_t size, BufferType type, BufferUsage usage) override; /** - * New a TextureBackend object. + * New a Texture object. * @param descriptor Specifies texture description. - * @return A TextureBackend object. + * @return A Texture object. */ - TextureBackend* newTexture(const TextureDescriptor& descriptor) override; + Texture* createTexture(const TextureDesc& descriptor) override; - RenderTarget* newDefaultRenderTarget() override; - RenderTarget* newRenderTarget(TextureBackend* colorAttachment, - TextureBackend* depthAttachment, - TextureBackend* stencilAttachhment) override; + RenderTarget* createDefaultRenderTarget() override; + RenderTarget* createRenderTarget(Texture* colorAttachment, + Texture* depthStencilAttachment) override; /** * New a DepthStencilState object. */ - DepthStencilState* newDepthStencilState() override; + DepthStencilState* createDepthStencilState() override; /** * New a RenderPipeline object. * @param descriptor Specifies render pipeline description. * @return A RenderPipeline object. */ - RenderPipeline* newRenderPipeline() override; + RenderPipeline* createRenderPipeline() override; /** * This property controls whether or not the drawables' @@ -183,7 +182,7 @@ class DriverMTL : public DriverBase * @param fragmentShader Specifes this is a fragment shader source. * @return A Program instance. */ - Program* newProgram(std::string_view vertexShader, std::string_view fragmentShader) override; + Program* createProgram(std::string_view vertexShader, std::string_view fragmentShader) override; /** * Get a MTLDevice object. @@ -204,19 +203,19 @@ class DriverMTL : public DriverBase * Get vendor device name. * @return Vendor device name. */ - const char* getVendor() const override; + std::string getVendor() const override; /** * Get the full name of the vendor device. * @return The full name of the vendor device. */ - const char* getRenderer() const override; + std::string getRenderer() const override; /** * Get featureSet name. * @return FeatureSet name. */ - const char* getVersion() const override; + std::string getVersion() const override; /** * Check if feature supported by Metal. @@ -234,7 +233,10 @@ class DriverMTL : public DriverBase * @param source Specifies shader source. * @return A ShaderModule object. */ - ShaderModule* newShaderModule(ShaderStage stage, std::string_view source) override; + ShaderModule* createShaderModule(ShaderStage stage, std::string_view source) override; + + SamplerHandle createSampler(const SamplerDesc& desc) override; + void destroySampler(SamplerHandle& sampler) override; private: static CAMetalLayer* _metalLayer; @@ -250,4 +252,4 @@ class DriverMTL : public DriverBase // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/DriverMTL.mm b/axmol/rhi/metal/DriverMTL.mm similarity index 68% rename from core/renderer/backend/metal/DriverMTL.mm rename to axmol/rhi/metal/DriverMTL.mm index 9e7b5e576c35..709d801f0258 100644 --- a/core/renderer/backend/metal/DriverMTL.mm +++ b/axmol/rhi/metal/DriverMTL.mm @@ -23,21 +23,34 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "DriverMTL.h" -#include "CommandBufferMTL.h" -#include "BufferMTL.h" -#include "RenderPipelineMTL.h" -#include "ShaderModuleMTL.h" -#include "DepthStencilStateMTL.h" -#include "TextureMTL.h" -#include "ProgramMTL.h" -#include "RenderTargetMTL.h" -#include "UtilsMTL.h" -#include "base/Macros.h" - -#include "renderer/backend/ProgramManager.h" - -NS_AX_BACKEND_BEGIN +#include "axmol/rhi/metal/DriverMTL.h" +#include "axmol/rhi/metal/CommandBufferMTL.h" +#include "axmol/rhi/metal/BufferMTL.h" +#include "axmol/rhi/metal/RenderPipelineMTL.h" +#include "axmol/rhi/metal/ShaderModuleMTL.h" +#include "axmol/rhi/metal/DepthStencilStateMTL.h" +#include "axmol/rhi/metal/TextureMTL.h" +#include "axmol/rhi/metal/ProgramMTL.h" +#include "axmol/rhi/metal/RenderTargetMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/base/Macros.h" + +namespace ax::rhi { +DriverBase* DriverBase::getInstance() +{ + if (!_instance) + _instance = new mtl::DriverImpl(); + + return _instance; +} + +void DriverBase::destroyInstance() +{ + if(_instance) delete _instance; +} +} + +namespace ax::rhi::mtl { inline FeatureSet operator--(FeatureSet& x) { @@ -192,58 +205,58 @@ int getMaxTextureWidthHeight(FeatureSet featureSet) return maxTextureSize; } -const char* featureSetToString(FeatureSet featureSet) +std::string_view featureSetToString(FeatureSet featureSet) { switch (featureSet) { case FeatureSet::FeatureSet_iOS_GPUFamily1_v1: - return "iOS_GPUFamily1_v1"; + return "iOS_GPUFamily1_v1"sv; case FeatureSet::FeatureSet_iOS_GPUFamily2_v1: - return "iOS_GPUFamily2_v1"; + return "iOS_GPUFamily2_v1"sv; case FeatureSet::FeatureSet_iOS_GPUFamily1_v2: - return "iOS_GPUFamily1_v2"; + return "iOS_GPUFamily1_v2"sv; case FeatureSet::FeatureSet_iOS_GPUFamily2_v2: - return "iOS_GPUFamily2_v2"; + return "iOS_GPUFamily2_v2"sv; case FeatureSet::FeatureSet_iOS_GPUFamily1_v3: - return "iOS_GPUFamily1_v3"; + return "iOS_GPUFamily1_v3"sv; case FeatureSet::FeatureSet_iOS_GPUFamily2_v3: - return "iOS_GPUFamily2_v3"; + return "iOS_GPUFamily2_v3"sv; case FeatureSet::FeatureSet_iOS_GPUFamily1_v4: - return "iOS_GPUFamily1_v4"; + return "iOS_GPUFamily1_v4"sv; case FeatureSet::FeatureSet_iOS_GPUFamily2_v4: - return "iOS_GPUFamily2_v4"; + return "iOS_GPUFamily2_v4"sv; case FeatureSet::FeatureSet_iOS_GPUFamily1_v5: - return "iOS_GPUFamily1_v5"; + return "iOS_GPUFamily1_v5"sv; case FeatureSet::FeatureSet_iOS_GPUFamily2_v5: - return "iOS_GPUFamily2_v5"; + return "iOS_GPUFamily2_v5"sv; case FeatureSet::FeatureSet_iOS_GPUFamily3_v1: - return "iOS_GPUFamily3_v1"; + return "iOS_GPUFamily3_v1"sv; case FeatureSet::FeatureSet_iOS_GPUFamily3_v2: - return "iOS_GPUFamily3_v2"; + return "iOS_GPUFamily3_v2"sv; case FeatureSet::FeatureSet_iOS_GPUFamily3_v3: - return "iOS_GPUFamily3_v3"; + return "iOS_GPUFamily3_v3"sv; case FeatureSet::FeatureSet_iOS_GPUFamily4_v1: - return "iOS_GPUFamily4_v1"; + return "iOS_GPUFamily4_v1"sv; case FeatureSet::FeatureSet_iOS_GPUFamily3_v4: - return "iOS_GPUFamily3_v4"; + return "iOS_GPUFamily3_v4"sv; case FeatureSet::FeatureSet_iOS_GPUFamily4_v2: - return "iOS_GPUFamily4_v2"; + return "iOS_GPUFamily4_v2"sv; case FeatureSet::FeatureSet_macOS_GPUFamily1_v1: - return "macOS_GPUFamily1_v1"; + return "macOS_GPUFamily1_v1"sv; case FeatureSet::FeatureSet_macOS_GPUFamily1_v2: - return "macOS_GPUFamily1_v2"; + return "macOS_GPUFamily1_v2"sv; case FeatureSet::FeatureSet_macOS_ReadWriteTextureTier2: - return "macOS_ReadWriteTextureTier2"; + return "macOS_ReadWriteTextureTier2"sv; case FeatureSet::FeatureSet_macOS_GPUFamily1_v3: - return "macOS_GPUFamily1_v3"; + return "macOS_GPUFamily1_v3"sv; case FeatureSet::FeatureSet_macOS_GPUFamily1_v4: - return "macOS_GPUFamily1_v4"; + return "macOS_GPUFamily1_v4"sv; case FeatureSet::FeatureSet_macOS_GPUFamily2_v1: - return "macOS_GPUFamily2_v1"; + return "macOS_GPUFamily2_v1"sv; default: break; } - return ""; + return ""sv; } bool supportPVRTC(FeatureSet featureSet) @@ -384,45 +397,32 @@ bool supportS3TC(FeatureSet featureSet) } } -bool DriverMTL::_isDepth24Stencil8PixelFormatSupported = false; - -CAMetalLayer* DriverMTL::_metalLayer = nil; -id DriverMTL::_currentDrawable = nil; - -DriverBase* DriverBase::getInstance() -{ - if (!_instance) - _instance = new DriverMTL(); - - return _instance; -} +bool DriverImpl::_isDepth24Stencil8PixelFormatSupported = false; -void DriverBase::destroyInstance() -{ - AX_SAFE_DELETE(_instance); -} +CAMetalLayer* DriverImpl::_metalLayer = nil; +id DriverImpl::_currentDrawable = nil; -void DriverMTL::setCAMetalLayer(CAMetalLayer* metalLayer) +void DriverImpl::setCAMetalLayer(CAMetalLayer* metalLayer) { - DriverMTL::_metalLayer = metalLayer; + DriverImpl::_metalLayer = metalLayer; } -id DriverMTL::getCurrentDrawable() +id DriverImpl::getCurrentDrawable() { - if (!DriverMTL::_currentDrawable) - DriverMTL::_currentDrawable = [DriverMTL::_metalLayer nextDrawable]; + if (!DriverImpl::_currentDrawable) + DriverImpl::_currentDrawable = [DriverImpl::_metalLayer nextDrawable]; - return DriverMTL::_currentDrawable; + return DriverImpl::_currentDrawable; } -void DriverMTL::resetCurrentDrawable() +void DriverImpl::resetCurrentDrawable() { - DriverMTL::_currentDrawable = nil; + DriverImpl::_currentDrawable = nil; } -DriverMTL::DriverMTL() +DriverImpl::DriverImpl() { - _mtlDevice = DriverMTL::_metalLayer.device; + _mtlDevice = DriverImpl::_metalLayer.device; _mtlCommandQueue = [_mtlDevice newCommandQueue]; _deviceName = [_mtlDevice.name UTF8String]; @@ -453,94 +453,175 @@ bool supportS3TC(FeatureSet featureSet) _maxTextureSize = getMaxTextureWidthHeight(_featureSet); } -DriverMTL::~DriverMTL() +DriverImpl::~DriverImpl() { - ProgramManager::destroyInstance(); } -CommandBuffer* DriverMTL::newCommandBuffer() +CommandBuffer* DriverImpl::createCommandBuffer(void*) { - return new CommandBufferMTL(this); + return new CommandBufferImpl(this); } -Buffer* DriverMTL::newBuffer(std::size_t size, BufferType type, BufferUsage usage) +Buffer* DriverImpl::createBuffer(std::size_t size, BufferType type, BufferUsage usage) { - return new BufferMTL(_mtlDevice, size, type, usage); + return new BufferImpl(_mtlDevice, size, type, usage); } -TextureBackend* DriverMTL::newTexture(const TextureDescriptor& descriptor) +Texture* DriverImpl::createTexture(const TextureDesc& descriptor) { - switch (descriptor.textureType) - { - case TextureType::TEXTURE_2D: - return new TextureMTL(_mtlDevice, descriptor); - case TextureType::TEXTURE_CUBE: - return new TextureCubeMTL(_mtlDevice, descriptor); - default: - AXASSERT(false, "invalidate texture type"); - return nullptr; - } + return new TextureImpl(_mtlDevice, descriptor); } -RenderTarget* DriverMTL::newDefaultRenderTarget() +RenderTarget* DriverImpl::createDefaultRenderTarget() { - auto rtGL = new RenderTargetMTL(true); - return rtGL; + return new RenderTargetImpl(true); } -RenderTarget* DriverMTL::newRenderTarget(TextureBackend* colorAttachment, - TextureBackend* depthAttachment, - TextureBackend* stencilAttachhment) +RenderTarget* DriverImpl::createRenderTarget(Texture* colorAttachment, + Texture* depthStencilAttachment) { - auto rtMTL = new RenderTargetMTL(false); + auto rtMTL = new RenderTargetImpl(false); RenderTarget::ColorAttachment colors{{colorAttachment, 0}}; rtMTL->setColorAttachment(colors); - rtMTL->setDepthAttachment(depthAttachment); - rtMTL->setStencilAttachment(stencilAttachhment); + rtMTL->setDepthStencilAttachment(depthStencilAttachment); return rtMTL; } -ShaderModule* DriverMTL::newShaderModule(ShaderStage stage, std::string_view source) +DepthStencilState* DriverImpl::createDepthStencilState() { - return new ShaderModuleMTL(_mtlDevice, stage, source); + return new DepthStencilStateImpl(_mtlDevice); } -DepthStencilState* DriverMTL::newDepthStencilState() +RenderPipeline* DriverImpl::createRenderPipeline() { - return new DepthStencilStateMTL(_mtlDevice); + return new RenderPipelineImpl(_mtlDevice); } -RenderPipeline* DriverMTL::newRenderPipeline() +Program* DriverImpl::createProgram(std::string_view vertexShader, std::string_view fragmentShader) { - return new RenderPipelineMTL(_mtlDevice); + return new ProgramImpl(vertexShader, fragmentShader); } -Program* DriverMTL::newProgram(std::string_view vertexShader, std::string_view fragmentShader) +ShaderModule* DriverImpl::createShaderModule(ShaderStage stage, std::string_view source) { - return new ProgramMTL(vertexShader, fragmentShader); + return new ShaderModuleImpl(_mtlDevice, stage, source); } -void DriverMTL::setFrameBufferOnly(bool frameBufferOnly) +SamplerHandle DriverImpl::createSampler(const SamplerDesc& desc) { - [DriverMTL::_metalLayer setFramebufferOnly:frameBufferOnly]; + MTLSamplerDescriptor* samplerDesc = [[MTLSamplerDescriptor alloc] init]; + + // --- Min & Mag Filter --- + switch (desc.minFilter) + { + case SamplerFilter::MIN_NEAREST: + samplerDesc.minFilter = MTLSamplerMinMagFilterNearest; + break; + case SamplerFilter::MIN_LINEAR: + case SamplerFilter::MIN_ANISOTROPIC: + samplerDesc.minFilter = MTLSamplerMinMagFilterLinear; + break; + } + + samplerDesc.magFilter = (desc.magFilter == SamplerFilter::MAG_NEAREST) + ? MTLSamplerMinMagFilterNearest + : MTLSamplerMinMagFilterLinear; + + // --- Mip Filter --- + switch (desc.mipFilter) + { + case SamplerFilter::MIP_NONE: + samplerDesc.mipFilter = MTLSamplerMipFilterNotMipmapped; + break; + case SamplerFilter::MIP_NEAREST: + samplerDesc.mipFilter = MTLSamplerMipFilterNearest; + break; + case SamplerFilter::MIP_LINEAR: + samplerDesc.mipFilter = MTLSamplerMipFilterLinear; + break; + } + + // --- Address Modes --- + auto toMTLAddressMode = [](SamplerAddressMode mode) -> MTLSamplerAddressMode { + switch (mode) + { + case SamplerAddressMode::REPEAT: return MTLSamplerAddressModeRepeat; + case SamplerAddressMode::MIRROR: return MTLSamplerAddressModeMirrorRepeat; + case SamplerAddressMode::CLAMP: return MTLSamplerAddressModeClampToEdge; + case SamplerAddressMode::BORDER: return MTLSamplerAddressModeClampToBorderColor; + } + return MTLSamplerAddressModeRepeat; + }; + + samplerDesc.sAddressMode = toMTLAddressMode(desc.sAddressMode); + samplerDesc.tAddressMode = toMTLAddressMode(desc.tAddressMode); + samplerDesc.rAddressMode = toMTLAddressMode(desc.wAddressMode); + + // --- Border Color --- + if (desc.sAddressMode == SamplerAddressMode::BORDER || + desc.tAddressMode == SamplerAddressMode::BORDER || + desc.wAddressMode == SamplerAddressMode::BORDER) + { + samplerDesc.borderColor = MTLSamplerBorderColorTransparentBlack; + } + + // --- Compare Function --- + auto toMTLCompareFunc = [](CompareFunc func) ->MTLCompareFunction { + if(func == CompareFunc::NEVER) + return MTLCompareFunctionNever; + switch (func) + { + case CompareFunc::LESS: return MTLCompareFunctionLess; + case CompareFunc::EQUAL: return MTLCompareFunctionEqual; + case CompareFunc::LESS_EQUAL: return MTLCompareFunctionLessEqual; + case CompareFunc::GREATER: return MTLCompareFunctionGreater; + case CompareFunc::NOT_EQUAL: return MTLCompareFunctionNotEqual; + case CompareFunc::GREATER_EQUAL: return MTLCompareFunctionGreaterEqual; + case CompareFunc::ALWAYS: return MTLCompareFunctionAlways; + default: return MTLCompareFunctionNever; + } + }; + samplerDesc.compareFunction = toMTLCompareFunc(desc.compareFunc); + + // --- Anisotropy --- + samplerDesc.maxAnisotropy = desc.anisotropy; + + // --- Create Sampler --- + id sampler = [_mtlDevice newSamplerStateWithDescriptor:samplerDesc]; + [samplerDesc release]; + + return (__bridge SamplerHandle)sampler; +} + +void DriverImpl::destroySampler(SamplerHandle& sampler) +{ + if(sampler) { + [reinterpret_cast>(sampler) release]; + sampler = nullptr; + } } -const char* DriverMTL::getVendor() const +void DriverImpl::setFrameBufferOnly(bool frameBufferOnly) { - return ""; + [DriverImpl::_metalLayer setFramebufferOnly:frameBufferOnly]; } -const char* DriverMTL::getRenderer() const +std::string DriverImpl::getVendor() const +{ + return "Apple Inc."; +} + +std::string DriverImpl::getRenderer() const { return _deviceName.c_str(); } -const char* DriverMTL::getVersion() const +std::string DriverImpl::getVersion() const { - return featureSetToString(_featureSet); + return std::string{featureSetToString(_featureSet)}; } -bool DriverMTL::checkForFeatureSupported(FeatureType feature) +bool DriverImpl::checkForFeatureSupported(FeatureType feature) { bool featureSupported = false; switch (feature) @@ -570,4 +651,4 @@ bool supportS3TC(FeatureSet featureSet) return featureSupported; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/ProgramMTL.h b/axmol/rhi/metal/ProgramMTL.h similarity index 72% rename from core/renderer/backend/metal/ProgramMTL.h rename to axmol/rhi/metal/ProgramMTL.h index a9e86ed72d0f..1947418e6801 100644 --- a/core/renderer/backend/metal/ProgramMTL.h +++ b/axmol/rhi/metal/ProgramMTL.h @@ -24,12 +24,12 @@ #pragma once -#include "../Program.h" +#include "axmol/rhi/Program.h" #import -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { -class ShaderModuleMTL; +class ShaderModuleImpl; /** * @addtogroup _metal @@ -39,7 +39,7 @@ class ShaderModuleMTL; /** * A metal Program */ -class ProgramMTL : public Program +class ProgramImpl : public Program { public: /// @name Constructor, Destructor and Initializers @@ -47,85 +47,85 @@ class ProgramMTL : public Program * @param vertexShader Specifes the vertex shader source. * @param fragmentShader Specifes the fragment shader source. */ - ProgramMTL(std::string_view vertexShader, std::string_view fragmentShader); - virtual ~ProgramMTL(); + ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader); + virtual ~ProgramImpl(); /** * Get uniform location by name. * @param uniform Specifies the uniform name. * @return The uniform location. */ - virtual UniformLocation getUniformLocation(std::string_view uniform) const override; + UniformLocation getUniformLocation(std::string_view uniform) const override; /** * Get uniform location by engine built-in uniform enum name. * @param name Specifies the engine built-in uniform enum name. * @return The uniform location. */ - virtual UniformLocation getUniformLocation(backend::Uniform name) const override; + UniformLocation getUniformLocation(rhi::Uniform name) const override; /** * Get attribute location by attribute name. * @param name Specifies the attribute name. * @return The attribute location. */ - virtual int getAttributeLocation(std::string_view name) const override; + const VertexInputDesc* getVertexInputDesc(std::string_view name) const override; /** * Get attribute location by engine built-in attribute enum name. * @param name Specifies the engine built-in attribute enum name. * @return The attribute location. */ - virtual int getAttributeLocation(Attribute name) const override; + const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const override; + + /** + * Get active vertex attributes. + * @return Active vertex attributes. key is active attribute name, Value is corresponding attribute info. + */ + const hlookup::string_map& getActiveVertexInputs() const override; /** * Get vertex shader module. * @return Vertex shader module. */ - virtual ShaderModuleMTL* getVertexShader() const { return _vertexShader; } + ShaderModuleImpl* getVertexShader() const { return _vertexShader; } /** * Get fragment shader module. * @ Fragment shader module. */ - virtual ShaderModuleMTL* getFragmentShader() const { return _fragmentShader; } - - /** - * Get active vertex attributes. - * @return Active vertex attributes. key is active attribute name, Value is corresponding attribute info. - */ - const hlookup::string_map& getActiveAttributes() const override; + ShaderModuleImpl* getFragmentShader() const { return _fragmentShader; } /** * Get maximum vertex location. * @return Maximum vertex locaiton. */ - virtual int getMaxVertexLocation() const override; + int getMaxVertexLocation() const override; /** * Get maximum fragment location. * @return Maximum fragment location. */ - virtual int getMaxFragmentLocation() const override; + int getMaxFragmentLocation() const override; /** * Get uniform buffer size in bytes that can hold all the uniforms. * @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT. * @return The uniform buffer size in bytes. */ - virtual std::size_t getUniformBufferSize(ShaderStage stage) const override; + std::size_t getUniformBufferSize(ShaderStage stage) const override; /** * Get all uniformInfos. * @return The uniformInfos. */ - virtual const hlookup::string_map& getAllActiveUniformInfo(ShaderStage stage) const override; + const hlookup::string_map& getActiveUniformInfos(ShaderStage stage) const override; private: - ShaderModuleMTL* _vertexShader = nullptr; - ShaderModuleMTL* _fragmentShader = nullptr; + ShaderModuleImpl* _vertexShader = nullptr; + ShaderModuleImpl* _fragmentShader = nullptr; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/ProgramMTL.mm b/axmol/rhi/metal/ProgramMTL.mm similarity index 67% rename from core/renderer/backend/metal/ProgramMTL.mm rename to axmol/rhi/metal/ProgramMTL.mm index 35367f55b459..a869dba48b08 100644 --- a/core/renderer/backend/metal/ProgramMTL.mm +++ b/axmol/rhi/metal/ProgramMTL.mm @@ -23,44 +23,41 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "ProgramMTL.h" -#include "ShaderModuleMTL.h" -#include "base/Macros.h" -#include "DriverMTL.h" +#include "axmol/rhi/metal/ProgramMTL.h" +#include "axmol/rhi/metal/ShaderModuleMTL.h" +#include "axmol/base/Macros.h" +#include "axmol/rhi/metal/DriverMTL.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { namespace { // constexpr std::string_view metalSpecificDefine = "#define METAL\n"sv; } -ProgramMTL::ProgramMTL(std::string_view vertexShader, std::string_view fragmentShader) +ProgramImpl::ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader) : Program(vertexShader, fragmentShader) { - _vertexShader = static_cast(ShaderCache::getInstance()->newVertexShaderModule(vertexShader)); - _fragmentShader = static_cast(ShaderCache::getInstance()->newFragmentShaderModule(fragmentShader)); - - AX_SAFE_RETAIN(_vertexShader); - AX_SAFE_RETAIN(_fragmentShader); + _vertexShader = static_cast(ShaderCache::getInstance()->acquireVertexShaderModule(_vsSource)); + _fragmentShader = static_cast(ShaderCache::getInstance()->acquireFragmentShaderModule(_fsSource)); } -ProgramMTL::~ProgramMTL() +ProgramImpl::~ProgramImpl() { AX_SAFE_RELEASE(_vertexShader); AX_SAFE_RELEASE(_fragmentShader); } -int ProgramMTL::getAttributeLocation(Attribute name) const +const VertexInputDesc* ProgramImpl::getVertexInputDesc(VertexInputKind name) const { - return _vertexShader->getAttributeLocation(name); + return _vertexShader->getVertexInputDesc(name); } -int ProgramMTL::getAttributeLocation(std::string_view name) const +const VertexInputDesc* ProgramImpl::getVertexInputDesc(std::string_view name) const { - return _vertexShader->getAttributeLocation(name); + return _vertexShader->getVertexInputDesc(name); } -UniformLocation ProgramMTL::getUniformLocation(backend::Uniform name) const +UniformLocation ProgramImpl::getUniformLocation(rhi::Uniform name) const { auto& vert = _vertexShader->getUniformInfo(name); auto& frag = _fragmentShader->getUniformInfo(name); @@ -71,7 +68,7 @@ of this software and associated documentation files (the "Software"), to deal }; } -UniformLocation ProgramMTL::getUniformLocation(std::string_view uniform) const +UniformLocation ProgramImpl::getUniformLocation(std::string_view uniform) const { auto& vert = _vertexShader->getUniformInfo(uniform); auto& frag = _fragmentShader->getUniformInfo(uniform); @@ -86,22 +83,22 @@ of this software and associated documentation files (the "Software"), to deal }; } -int ProgramMTL::getMaxVertexLocation() const +int ProgramImpl::getMaxVertexLocation() const { return _vertexShader->getMaxLocation(); } -int ProgramMTL::getMaxFragmentLocation() const +int ProgramImpl::getMaxFragmentLocation() const { return _fragmentShader->getMaxLocation(); } -const hlookup::string_map& ProgramMTL::getActiveAttributes() const +const hlookup::string_map& ProgramImpl::getActiveVertexInputs() const { - return _vertexShader->getAttributeInfo(); + return _vertexShader->getActiveVertexInputs(); } -std::size_t ProgramMTL::getUniformBufferSize(ShaderStage stage) const +std::size_t ProgramImpl::getUniformBufferSize(ShaderStage stage) const { switch (stage) { @@ -116,17 +113,17 @@ of this software and associated documentation files (the "Software"), to deal return 0; } -const hlookup::string_map& ProgramMTL::getAllActiveUniformInfo(ShaderStage stage) const +const hlookup::string_map& ProgramImpl::getActiveUniformInfos(ShaderStage stage) const { switch (stage) { case ShaderStage::VERTEX: - return _vertexShader->getAllActiveUniformInfo(); + return _vertexShader->getActiveUniformInfos(); case ShaderStage::FRAGMENT: - return _fragmentShader->getAllActiveUniformInfo(); + return _fragmentShader->getActiveUniformInfos(); default: AXASSERT(false, "Invalid shader stage."); } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/RenderPipelineMTL.h b/axmol/rhi/metal/RenderPipelineMTL.h similarity index 78% rename from core/renderer/backend/metal/RenderPipelineMTL.h rename to axmol/rhi/metal/RenderPipelineMTL.h index eab1b6796d5a..3c0137ff26ef 100644 --- a/core/renderer/backend/metal/RenderPipelineMTL.h +++ b/axmol/rhi/metal/RenderPipelineMTL.h @@ -25,14 +25,14 @@ #pragma once -#include "../RenderPipeline.h" +#include "axmol/rhi/RenderPipeline.h" #include #include #include #include "tsl/robin_map.h" #import -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { /** * @addtogroup _metal * @{ @@ -41,16 +41,16 @@ NS_AX_BACKEND_BEGIN /** * Create and compile a new MTLRenderPipelineState object synchronously. */ -class RenderPipelineMTL : public RenderPipeline +class RenderPipelineImpl : public RenderPipeline { public: /** * @param mtlDevice The device for which MTLRenderPipelineState object was created. * @param descriptor Specify the render pipeline description. */ - RenderPipelineMTL(id mtlDevice); - ~RenderPipelineMTL(); - virtual void update(const RenderTarget* renderTarget, const PipelineDescriptor&) override; + RenderPipelineImpl(id mtlDevice); + ~RenderPipelineImpl(); + void update(const RenderTarget* renderTarget, const PipelineDesc&) override; /** * Get a MTLRenderPipelineState object. @@ -59,26 +59,24 @@ class RenderPipelineMTL : public RenderPipeline inline id getMTLRenderPipelineState() const { return _mtlRenderPipelineState; } private: - void setVertexLayout(MTLRenderPipelineDescriptor*, const PipelineDescriptor&); - void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*, const BlendDescriptor&); - void setShaderModules(const PipelineDescriptor&); - void setBlendStateAndFormat(const BlendDescriptor&); + void setVertexLayout(MTLRenderPipelineDescriptor*, const PipelineDesc&); + void setBlendState(MTLRenderPipelineColorAttachmentDescriptor*, const BlendDesc&); + void setShaderModules(const PipelineDesc&); + void setBlendStateAndFormat(const BlendDesc&); void chooseAttachmentFormat(const RenderTarget* renderTarget, PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT], - PixelFormat&, PixelFormat&); id _mtlRenderPipelineState = nil; id _mtlDevice = nil; - MTLRenderPipelineDescriptor* _mtlRenderPipelineDescriptor = nil; + MTLRenderPipelineDescriptor* _mtlRenderPipelineDesc = nil; PixelFormat _colorAttachmentsFormat[MAX_COLOR_ATTCHMENT] = {PixelFormat::NONE}; - PixelFormat _depthAttachmentFormat = PixelFormat::NONE; - PixelFormat _stencilAttachmentFormat = PixelFormat::NONE; + PixelFormat _depthStencilPF = PixelFormat::NONE; tsl::robin_map> _mtlStateCache; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/RenderPipelineMTL.mm b/axmol/rhi/metal/RenderPipelineMTL.mm similarity index 54% rename from core/renderer/backend/metal/RenderPipelineMTL.mm rename to axmol/rhi/metal/RenderPipelineMTL.mm index aae4f832a8e8..01164f03b52b 100644 --- a/core/renderer/backend/metal/RenderPipelineMTL.mm +++ b/axmol/rhi/metal/RenderPipelineMTL.mm @@ -23,20 +23,20 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "RenderPipelineMTL.h" -#include "DriverMTL.h" -#include "RenderTargetMTL.h" -#include "ShaderModuleMTL.h" -#include "DepthStencilStateMTL.h" -#include "UtilsMTL.h" -#include "ProgramMTL.h" +#include "axmol/rhi/metal/RenderPipelineMTL.h" +#include "axmol/rhi/metal/DriverMTL.h" +#include "axmol/rhi/metal/RenderTargetMTL.h" +#include "axmol/rhi/metal/ShaderModuleMTL.h" +#include "axmol/rhi/metal/DepthStencilStateMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/rhi/metal/ProgramMTL.h" #include "xxhash.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { namespace { -MTLVertexStepFunction toMTLVertexStepFunction(VertexStepMode vertexStepMode) +static MTLVertexStepFunction toMTLVertexStepFunc(VertexStepMode vertexStepMode) { if (VertexStepMode::VERTEX == vertexStepMode) return MTLVertexStepFunctionPerVertex; @@ -44,7 +44,7 @@ MTLVertexStepFunction toMTLVertexStepFunction(VertexStepMode vertexStepMode) return MTLVertexStepFunctionPerInstance; } -MTLVertexFormat toMTLVertexFormat(VertexFormat vertexFormat, bool needNormalize) +static MTLVertexFormat toMTLVertexFormat(VertexFormat vertexFormat, bool needNormalize) { MTLVertexFormat ret = MTLVertexFormatFloat4; switch (vertexFormat) @@ -92,7 +92,7 @@ MTLVertexFormat toMTLVertexFormat(VertexFormat vertexFormat, bool needNormalize) return ret; } -MTLColorWriteMask toMTLColorWriteMask(ColorWriteMask mask) +static MTLColorWriteMask toMTLColorWriteMask(ColorWriteMask mask) { switch (mask) { @@ -111,7 +111,7 @@ MTLColorWriteMask toMTLColorWriteMask(ColorWriteMask mask) } } -MTLBlendFactor toMTLBlendFactor(BlendFactor factor) +static MTLBlendFactor toMTLBlendFactor(BlendFactor factor) { switch (factor) { @@ -144,15 +144,15 @@ MTLBlendFactor toMTLBlendFactor(BlendFactor factor) } } -MTLBlendOperation toMTLBlendOperation(BlendOperation operation) +static MTLBlendOperation toMTLBlendOp(BlendOp operation) { switch (operation) { - case BlendOperation::ADD: + case BlendOp::ADD: return MTLBlendOperationAdd; - case BlendOperation::SUBTRACT: + case BlendOp::SUBTRACT: return MTLBlendOperationSubtract; - case BlendOperation::REVERSE_SUBTRACT: + case BlendOp::REVERSE_SUBTRACT: return MTLBlendOperationReverseSubtract; default: return MTLBlendOperationAdd; @@ -160,22 +160,21 @@ MTLBlendOperation toMTLBlendOperation(BlendOperation operation) } } -RenderPipelineMTL::RenderPipelineMTL(id mtlDevice) : _mtlDevice(mtlDevice) {} +RenderPipelineImpl::RenderPipelineImpl(id mtlDevice) : _mtlDevice(mtlDevice) {} -void RenderPipelineMTL::update(const RenderTarget* renderTarget, const PipelineDescriptor& pipelineDescriptor) +void RenderPipelineImpl::update(const RenderTarget* renderTarget, const PipelineDesc& pipelineDesc) { struct { size_t vertexShaderHash; size_t fragmentShaderHash; unsigned int vertexLayoutInfo[32]; - backend::PixelFormat colorAttachment[MAX_COLOR_ATTCHMENT]; - backend::PixelFormat depthAttachment; - backend::PixelFormat stencilAttachment; + rhi::PixelFormat colorAttachment[MAX_COLOR_ATTCHMENT]; + rhi::PixelFormat depthStencilPF; bool blendEnabled; unsigned int writeMask; - unsigned int rgbBlendOperation; - unsigned int alphaBlendOperation; + unsigned int rgbBlendOp; + unsigned int alphaBlendOp; unsigned int sourceRGBBlendFactor; unsigned int destinationRGBBlendFactor; unsigned int sourceAlphaBlendFactor; @@ -183,36 +182,33 @@ MTLBlendOperation toMTLBlendOperation(BlendOperation operation) } hashMe; memset(&hashMe, 0, sizeof(hashMe)); - const auto& blendDescriptor = pipelineDescriptor.blendDescriptor; - chooseAttachmentFormat(renderTarget, _colorAttachmentsFormat, _depthAttachmentFormat, _stencilAttachmentFormat); - auto program = static_cast(pipelineDescriptor.programState->getProgram()); + const auto& blendDesc = pipelineDesc.blendDesc; + chooseAttachmentFormat(renderTarget, _colorAttachmentsFormat, _depthStencilPF); + auto program = static_cast(pipelineDesc.programState->getProgram()); hashMe.vertexShaderHash = program->getVertexShader()->getHashValue(); hashMe.fragmentShaderHash = program->getFragmentShader()->getHashValue(); memcpy(&hashMe.colorAttachment, &_colorAttachmentsFormat, sizeof(_colorAttachmentsFormat)); - hashMe.depthAttachment = _depthAttachmentFormat; - hashMe.stencilAttachment = _stencilAttachmentFormat; - hashMe.blendEnabled = blendDescriptor.blendEnabled; - hashMe.writeMask = (unsigned int)blendDescriptor.writeMask; - hashMe.rgbBlendOperation = (unsigned int)blendDescriptor.rgbBlendOperation; - hashMe.alphaBlendOperation = (unsigned int)blendDescriptor.alphaBlendOperation; - hashMe.sourceRGBBlendFactor = (unsigned int)blendDescriptor.sourceRGBBlendFactor; - hashMe.destinationRGBBlendFactor = (unsigned int)blendDescriptor.destinationRGBBlendFactor; - hashMe.sourceAlphaBlendFactor = (unsigned int)blendDescriptor.sourceAlphaBlendFactor; - hashMe.destinationAlphaBlendFactor = (unsigned int)blendDescriptor.destinationAlphaBlendFactor; + hashMe.depthStencilPF = _depthStencilPF; + hashMe.blendEnabled = blendDesc.blendEnabled; + hashMe.writeMask = (unsigned int)blendDesc.writeMask; + hashMe.rgbBlendOp = (unsigned int)blendDesc.rgbBlendOp; + hashMe.alphaBlendOp = (unsigned int)blendDesc.alphaBlendOp; + hashMe.sourceRGBBlendFactor = (unsigned int)blendDesc.sourceRGBBlendFactor; + hashMe.destinationRGBBlendFactor = (unsigned int)blendDesc.destinationRGBBlendFactor; + hashMe.sourceAlphaBlendFactor = (unsigned int)blendDesc.sourceAlphaBlendFactor; + hashMe.destinationAlphaBlendFactor = (unsigned int)blendDesc.destinationAlphaBlendFactor; int index = 0; - auto vertexLayout = pipelineDescriptor.programState->getVertexLayout(); - const auto& attributes = vertexLayout->getAttributes(); - for (const auto& it : attributes) + auto vertexLayout = pipelineDesc.programState->getVertexLayout(); + for (const auto& [_, bindingDesc] : vertexLayout->getBindings()) { - auto& attribute = it.second; /* stepFunction:1 stride:15 offest:10 format:5 needNormalized:1 bit31 bit30 ~ bit16 bit15 ~ bit6 bit5 ~ bit1 bit0 */ hashMe.vertexLayoutInfo[index++] = ((unsigned int)vertexLayout->getVertexStepMode() & 0x1) << 31 | - ((unsigned int)(vertexLayout->getStride() & 0x7FFF)) << 16 | ((unsigned int)attribute.offset & 0x3FF) << 6 | - ((unsigned int)attribute.format & 0x1F) << 1 | ((unsigned int)attribute.needToBeNormallized & 0x1); + ((unsigned int)(vertexLayout->getStride() & 0x7FFF)) << 16 | ((unsigned int)bindingDesc.offset & 0x3FF) << 6 | + ((unsigned int)bindingDesc.format & 0x1F) << 1 | ((unsigned int)bindingDesc.needToBeNormallized & 0x1); } unsigned int hash = XXH32((const void*)&hashMe, sizeof(hashMe), 0); @@ -223,114 +219,109 @@ MTLBlendOperation toMTLBlendOperation(BlendOperation operation) return; } - _mtlRenderPipelineDescriptor = [[MTLRenderPipelineDescriptor alloc] init]; + _mtlRenderPipelineDesc = [[MTLRenderPipelineDescriptor alloc] init]; - setShaderModules(pipelineDescriptor); - setVertexLayout(_mtlRenderPipelineDescriptor, pipelineDescriptor); + setShaderModules(pipelineDesc); + setVertexLayout(_mtlRenderPipelineDesc, pipelineDesc); - setBlendStateAndFormat(pipelineDescriptor.blendDescriptor); + setBlendStateAndFormat(pipelineDesc.blendDesc); NSError* error = nil; - _mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDescriptor + _mtlRenderPipelineState = [_mtlDevice newRenderPipelineStateWithDescriptor:_mtlRenderPipelineDesc error:&error]; if (error) NSLog(@"Can not create renderpipeline state: %@", error); - [_mtlRenderPipelineDescriptor release]; + [_mtlRenderPipelineDesc release]; _mtlStateCache.emplace(hash, _mtlRenderPipelineState); } -RenderPipelineMTL::~RenderPipelineMTL() +RenderPipelineImpl::~RenderPipelineImpl() { for (auto& item : _mtlStateCache) [item.second release]; } -void RenderPipelineMTL::setVertexLayout(MTLRenderPipelineDescriptor* mtlDescriptor, - const PipelineDescriptor& descriptor) +void RenderPipelineImpl::setVertexLayout(MTLRenderPipelineDescriptor* mtlDesc, + const PipelineDesc& desc) { - auto vertexLayout = descriptor.programState->getVertexLayout(); + auto vertexLayout = desc.programState->getVertexLayout(); if (!vertexLayout->isValid()) return; int stride = static_cast(vertexLayout->getStride()); - auto vertexDesc = mtlDescriptor.vertexDescriptor; - vertexDesc.layouts[DriverMTL::DEFAULT_ATTRIBS_BINDING_INDEX].stride = stride; - vertexDesc.layouts[DriverMTL::DEFAULT_ATTRIBS_BINDING_INDEX].stepFunction = - toMTLVertexStepFunction(vertexLayout->getVertexStepMode()); + auto vertexDesc = mtlDesc.vertexDescriptor; + vertexDesc.layouts[DriverImpl::DEFAULT_ATTRIBS_BINDING_INDEX].stride = stride; + vertexDesc.layouts[DriverImpl::DEFAULT_ATTRIBS_BINDING_INDEX].stepFunction = + toMTLVertexStepFunc(vertexLayout->getVertexStepMode()); - const auto& attributes = vertexLayout->getAttributes(); - - - for (const auto& it : attributes) + for (const auto& [_, bindingDesc] : vertexLayout->getBindings()) { - auto attribute = it.second; - - vertexDesc.attributes[attribute.index].format = - toMTLVertexFormat(attribute.format, attribute.needToBeNormallized); - vertexDesc.attributes[attribute.index].offset = attribute.offset; + vertexDesc.attributes[bindingDesc.index].format = + toMTLVertexFormat(bindingDesc.format, bindingDesc.needToBeNormallized); + vertexDesc.attributes[bindingDesc.index].offset = bindingDesc.offset; // Buffer index will always be 0; - vertexDesc.attributes[attribute.index].bufferIndex = DriverMTL::DEFAULT_ATTRIBS_BINDING_INDEX; + vertexDesc.attributes[bindingDesc.index].bufferIndex = DriverImpl::DEFAULT_ATTRIBS_BINDING_INDEX; } } -void RenderPipelineMTL::setBlendState(MTLRenderPipelineColorAttachmentDescriptor* colorAttachmentDescriptor, - const BlendDescriptor& blendDescriptor) +void RenderPipelineImpl::setBlendState(MTLRenderPipelineColorAttachmentDescriptor* colorAttachmentDesc, + const BlendDesc& blendDesc) { - colorAttachmentDescriptor.blendingEnabled = blendDescriptor.blendEnabled; - colorAttachmentDescriptor.writeMask = toMTLColorWriteMask(blendDescriptor.writeMask); + colorAttachmentDesc.blendingEnabled = blendDesc.blendEnabled; + colorAttachmentDesc.writeMask = toMTLColorWriteMask(blendDesc.writeMask); - colorAttachmentDescriptor.rgbBlendOperation = toMTLBlendOperation(blendDescriptor.rgbBlendOperation); - colorAttachmentDescriptor.alphaBlendOperation = toMTLBlendOperation(blendDescriptor.alphaBlendOperation); + colorAttachmentDesc.rgbBlendOperation = toMTLBlendOp(blendDesc.rgbBlendOp); + colorAttachmentDesc.alphaBlendOperation = toMTLBlendOp(blendDesc.alphaBlendOp); - colorAttachmentDescriptor.sourceRGBBlendFactor = toMTLBlendFactor(blendDescriptor.sourceRGBBlendFactor); - colorAttachmentDescriptor.destinationRGBBlendFactor = toMTLBlendFactor(blendDescriptor.destinationRGBBlendFactor); - colorAttachmentDescriptor.sourceAlphaBlendFactor = toMTLBlendFactor(blendDescriptor.sourceAlphaBlendFactor); - colorAttachmentDescriptor.destinationAlphaBlendFactor = - toMTLBlendFactor(blendDescriptor.destinationAlphaBlendFactor); + colorAttachmentDesc.sourceRGBBlendFactor = toMTLBlendFactor(blendDesc.sourceRGBBlendFactor); + colorAttachmentDesc.destinationRGBBlendFactor = toMTLBlendFactor(blendDesc.destinationRGBBlendFactor); + colorAttachmentDesc.sourceAlphaBlendFactor = toMTLBlendFactor(blendDesc.sourceAlphaBlendFactor); + colorAttachmentDesc.destinationAlphaBlendFactor = + toMTLBlendFactor(blendDesc.destinationAlphaBlendFactor); } -void RenderPipelineMTL::setShaderModules(const PipelineDescriptor& descriptor) +void RenderPipelineImpl::setShaderModules(const PipelineDesc& descriptor) { - auto vertexShaderModule = static_cast(descriptor.programState->getProgram())->getVertexShader(); - _mtlRenderPipelineDescriptor.vertexFunction = vertexShaderModule->getMTLFunction(); + auto vertexShaderModule = static_cast(descriptor.programState->getProgram())->getVertexShader(); + _mtlRenderPipelineDesc.vertexFunction = vertexShaderModule->getMTLFunction(); - auto fragShaderModule = static_cast(descriptor.programState->getProgram())->getFragmentShader(); - _mtlRenderPipelineDescriptor.fragmentFunction = fragShaderModule->getMTLFunction(); + auto fragShaderModule = static_cast(descriptor.programState->getProgram())->getFragmentShader(); + _mtlRenderPipelineDesc.fragmentFunction = fragShaderModule->getMTLFunction(); } -void RenderPipelineMTL::chooseAttachmentFormat(const RenderTarget* renderTarget, +void RenderPipelineImpl::chooseAttachmentFormat(const RenderTarget* renderTarget, PixelFormat colorAttachmentsFormat[MAX_COLOR_ATTCHMENT], - PixelFormat& depthFormat, - PixelFormat& stencilFormat) + PixelFormat& depthStencilFormat) { // Choose color attachment format - auto rtMTL = static_cast(renderTarget); + auto rtMTL = static_cast(renderTarget); for (auto i = 0; i < MAX_COLOR_ATTCHMENT; ++i) colorAttachmentsFormat[i] = rtMTL->getColorAttachmentPixelFormat(i); - depthFormat = rtMTL->getDepthAttachmentPixelFormat(); - stencilFormat = rtMTL->getStencilAttachmentPixelFormat(); + depthStencilFormat = rtMTL->getDepthStencilAttachmentPixelFormat(); } -void RenderPipelineMTL::setBlendStateAndFormat(const BlendDescriptor& blendDescriptor) +void RenderPipelineImpl::setBlendStateAndFormat(const BlendDesc& blendDesc) { for (int i = 0; i < MAX_COLOR_ATTCHMENT; ++i) { if (PixelFormat::NONE == _colorAttachmentsFormat[i]) { - _mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = MTLPixelFormat::MTLPixelFormatInvalid; + _mtlRenderPipelineDesc.colorAttachments[i].pixelFormat = MTLPixelFormat::MTLPixelFormatInvalid; continue; } - _mtlRenderPipelineDescriptor.colorAttachments[i].pixelFormat = + _mtlRenderPipelineDesc.colorAttachments[i].pixelFormat = UtilsMTL::toMTLPixelFormat(_colorAttachmentsFormat[i]); - setBlendState(_mtlRenderPipelineDescriptor.colorAttachments[i], blendDescriptor); + setBlendState(_mtlRenderPipelineDesc.colorAttachments[i], blendDesc); } - _mtlRenderPipelineDescriptor.depthAttachmentPixelFormat = UtilsMTL::toMTLPixelFormat(_depthAttachmentFormat); - _mtlRenderPipelineDescriptor.stencilAttachmentPixelFormat = UtilsMTL::toMTLPixelFormat(_stencilAttachmentFormat); + + auto nativePF = UtilsMTL::toMTLPixelFormat(_depthStencilPF); + _mtlRenderPipelineDesc.depthAttachmentPixelFormat = nativePF; + _mtlRenderPipelineDesc.stencilAttachmentPixelFormat = nativePF; } -NS_AX_BACKEND_END +} diff --git a/axmol/rhi/metal/RenderTargetMTL.h b/axmol/rhi/metal/RenderTargetMTL.h new file mode 100644 index 000000000000..4bbfdb9b16d2 --- /dev/null +++ b/axmol/rhi/metal/RenderTargetMTL.h @@ -0,0 +1,32 @@ +#pragma once +#include "axmol/rhi/RenderTarget.h" +#include "axmol/rhi/metal/CommandBufferMTL.h" + +namespace ax::rhi::mtl { + +class RenderTargetImpl : public RenderTarget +{ +public: + struct Attachment + { + id texture = nil; + int level = 0; + explicit operator bool() const { return texture != nullptr; } + }; + + /* + * generateFBO, false, use for screen framebuffer + */ + RenderTargetImpl(bool defaultRenderTarget); + ~RenderTargetImpl(); + + void applyRenderPassAttachments(const RenderPassDesc&, MTLRenderPassDescriptor*) const; + + Attachment getColorAttachment(int index) const; + Attachment getDepthStencilAttachment() const; + + PixelFormat getColorAttachmentPixelFormat(int index) const; + PixelFormat getDepthStencilAttachmentPixelFormat() const; +}; + +} diff --git a/axmol/rhi/metal/RenderTargetMTL.mm b/axmol/rhi/metal/RenderTargetMTL.mm new file mode 100644 index 000000000000..362fb4d4f468 --- /dev/null +++ b/axmol/rhi/metal/RenderTargetMTL.mm @@ -0,0 +1,126 @@ +#include "axmol/rhi/metal/RenderTargetMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/rhi/metal/TextureMTL.h" + +namespace ax::rhi::mtl { + +static MTLLoadAction getLoadAction(const RenderPassDesc& params, TargetBufferFlags buffer) +{ + const auto clearFlags = (TargetBufferFlags)params.flags.clear; + const auto discardStartFlags = params.flags.discardStart; + if (bitmask::any(clearFlags, buffer)) + { + return MTLLoadActionClear; + } + else if (bitmask::any(discardStartFlags, buffer)) + { + return MTLLoadActionDontCare; + } + return MTLLoadActionLoad; +} + +static MTLStoreAction getStoreAction(const RenderPassDesc& params, TargetBufferFlags buffer) +{ + const auto discardEndFlags = params.flags.discardEnd; + if (bitmask::any(discardEndFlags, buffer)) + { + return MTLStoreActionDontCare; + } + return MTLStoreActionStore; +} + +RenderTargetImpl::RenderTargetImpl(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget) {} +RenderTargetImpl::~RenderTargetImpl() {} + +void RenderTargetImpl::applyRenderPassAttachments(const RenderPassDesc& params, + MTLRenderPassDescriptor* desc) const +{ + // const auto discardFlags = params.flags.discardEnd; + auto clearFlags = params.flags.clear; + + for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; i++) + { + auto attachment = getColorAttachment(static_cast(i)); + if (!attachment) + { + continue; + } + + const auto MRTColorFlag = getMRTColorFlag(i); + + desc.colorAttachments[i].texture = attachment.texture; + desc.colorAttachments[i].level = attachment.level; + // desc.colorAttachments[i].slice = attachment.layer; + desc.colorAttachments[i].loadAction = getLoadAction(params, MRTColorFlag); + desc.colorAttachments[i].storeAction = getStoreAction(params, MRTColorFlag); + if (bitmask::any(clearFlags, MRTColorFlag)) + desc.colorAttachments[i].clearColor = + MTLClearColorMake(params.clearColorValue[0], params.clearColorValue[1], params.clearColorValue[2], + params.clearColorValue[3]); + } + + // Sets descriptor depth and stencil params, should match RenderTargetImpl::chooseAttachmentFormat + { + auto depthStencilAttachment = getDepthStencilAttachment(); + if (depthStencilAttachment) + { + // depth + desc.depthAttachment.texture = depthStencilAttachment.texture; + desc.depthAttachment.level = depthStencilAttachment.level; + // desc.depthAttachment.slice = depthAttachment.layer; + desc.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH); + desc.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH); + if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH)) + desc.depthAttachment.clearDepth = params.clearDepthValue; + + // depth + desc.stencilAttachment.texture = depthStencilAttachment.texture; + desc.stencilAttachment.level = depthStencilAttachment.level; + // desc.stencilAttachment.slice = depthAttachment.layer; + desc.stencilAttachment.loadAction = getLoadAction(params, TargetBufferFlags::STENCIL); + desc.stencilAttachment.storeAction = getStoreAction(params, TargetBufferFlags::STENCIL); + if (bitmask::any(clearFlags, TargetBufferFlags::STENCIL)) + desc.stencilAttachment.clearStencil = params.clearStencilValue; + } + } + + _dirtyFlags = TargetBufferFlags::NONE; +} + +RenderTargetImpl::Attachment RenderTargetImpl::getColorAttachment(int index) const +{ + if (isDefaultRenderTarget() && index == 0) + return {DriverImpl::getCurrentDrawable().texture, 0}; + auto& rb = this->_color[index]; + return RenderTargetImpl::Attachment{static_cast(rb) ? static_cast(rb.texture)->internalHandle() : nil, + rb.level}; +} + +RenderTargetImpl::Attachment RenderTargetImpl::getDepthStencilAttachment() const +{ + if (isDefaultRenderTarget()) + return {UtilsMTL::getDefaultDepthStencilTexture(), 0}; + auto& rb = this->_depthStencil; + return RenderTargetImpl::Attachment{!!rb ? static_cast(rb.texture)->internalHandle() : nil, rb.level}; +} + +PixelFormat RenderTargetImpl::getColorAttachmentPixelFormat(int index) const +{ + // !!!important + // the default framebuffer pixel format is: MTLPixelFormatBGRA8Unorm + if (isDefaultRenderTarget() && index == 0) + return PixelFormat::BGRA8; + auto& rb = this->_color[index]; + return rb ? rb.texture->getTextureFormat() : PixelFormat::NONE; +} + +PixelFormat RenderTargetImpl::getDepthStencilAttachmentPixelFormat() const +{ // FIXME: axmol only support D24S8 + if (isDefaultRenderTarget()) + return PixelFormat::D24S8; + if (_depthStencil) + return _depthStencil.texture->getTextureFormat(); + return PixelFormat::NONE; +} + +} diff --git a/core/renderer/backend/metal/ShaderModuleMTL.h b/axmol/rhi/metal/ShaderModuleMTL.h similarity index 79% rename from core/renderer/backend/metal/ShaderModuleMTL.h rename to axmol/rhi/metal/ShaderModuleMTL.h index 92dbdd6b9244..1adab77e92ff 100644 --- a/core/renderer/backend/metal/ShaderModuleMTL.h +++ b/axmol/rhi/metal/ShaderModuleMTL.h @@ -25,8 +25,7 @@ #pragma once -#include "../ShaderModule.h" -#include "../Types.h" +#include "axmol/rhi/ShaderModule.h" #include #include #include @@ -34,7 +33,7 @@ #include #import -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { /** * @addtogroup _metal * @{ @@ -45,7 +44,7 @@ struct SLCReflectContext; /** * To Create a vertex or fragment shader. */ -class ShaderModuleMTL : public ShaderModule +class ShaderModuleImpl : public ShaderModule { public: /** @@ -53,8 +52,8 @@ class ShaderModuleMTL : public ShaderModule * @param stage Specify what kinds of shader to be created. * @param source Specify the shader source. */ - ShaderModuleMTL(id mtlDevice, ShaderStage stage, std::string_view source); - ~ShaderModuleMTL(); + ShaderModuleImpl(id mtlDevice, ShaderStage stage, std::string_view source); + ~ShaderModuleImpl(); /** * Get MTLFunction object. @@ -62,24 +61,6 @@ class ShaderModuleMTL : public ShaderModule */ inline id getMTLFunction() const { return _mtlFunction; } - /** - * Get all uniformInfos. - * @return The uniformInfos. - */ - inline const hlookup::string_map& getAllActiveUniformInfo() const { return _activeUniformInfos; } - - /** - * Get maximum uniform location. - * @return Maximum uniform location. - */ - inline const int getMaxLocation() const { return _maxLocation; } - - /** - * Get active attribute informations. - * @return Active attribute informations. key is attribute name and Value is corresponding attribute info. - */ - inline const hlookup::string_map& getAttributeInfo() const { return _attributeInfo; } - /** * Get uniform info by engine built-in uniform enum name. * @param name Specifies the engine built-in uniform enum name. @@ -99,14 +80,33 @@ class ShaderModuleMTL : public ShaderModule * @param name Specifies the engine built-in attribute enum name. * @return The attribute location. */ - int getAttributeLocation(Attribute name) const; + const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const; /** * Get attribute location by attribute name. * @param name Specifies the attribute name. * @return The attribute location. */ - int getAttributeLocation(std::string_view name); + const VertexInputDesc* getVertexInputDesc(std::string_view name) const; + + /** + * Get active attribute informations. + * @return Active attribute informations. key is attribute name and Value is corresponding attribute info. + */ + inline const hlookup::string_map& getActiveVertexInputs() const { return _activeVertexInputs; } + + + /** + * Get all uniformInfos. + * @return The uniformInfos. + */ + inline const hlookup::string_map& getActiveUniformInfos() const { return _activeUniformInfos; } + + /** + * Get maximum uniform location. + * @return Maximum uniform location. + */ + inline const int getMaxLocation() const { return _maxLocation; } /** * Get uniform buffer size in bytes that holds all the uniforms. @@ -115,24 +115,25 @@ class ShaderModuleMTL : public ShaderModule inline std::size_t getUniformBufferSize() const { return _uniformBufferSize; } private: - void parseAttibute(SLCReflectContext* context); - void parseUniform(SLCReflectContext* context); - void parseTexture(SLCReflectContext* context); + void reflectVertexInputs(SLCReflectContext* context); + void reflectUniforms(SLCReflectContext* context); + void reflectSamplers(SLCReflectContext* context); + void setBuiltinLocations(); id _mtlFunction = nil; + hlookup::string_map _activeVertexInputs; hlookup::string_map _activeUniformInfos; - hlookup::string_map _attributeInfo; - int _attributeLocation[ATTRIBUTE_MAX]; + const VertexInputDesc* _builtinVertexInputs[VIK_COUNT]; int _maxLocation = -1; - UniformInfo _builtinUniforms[UNIFORM_MAX]; + UniformInfo _builtinUniforms[UNIFORM_COUNT]; std::size_t _uniformBufferSize = 0; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/ShaderModuleMTL.mm b/axmol/rhi/metal/ShaderModuleMTL.mm similarity index 57% rename from core/renderer/backend/metal/ShaderModuleMTL.mm rename to axmol/rhi/metal/ShaderModuleMTL.mm index 2148db725a62..23f6b9cf9e79 100644 --- a/core/renderer/backend/metal/ShaderModuleMTL.mm +++ b/axmol/rhi/metal/ShaderModuleMTL.mm @@ -23,51 +23,53 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "ShaderModuleMTL.h" -#include "DriverMTL.h" +#include "axmol/rhi/metal/ShaderModuleMTL.h" +#include "axmol/rhi/metal/DriverMTL.h" #include "yasio/ibstream.hpp" #include "yasio/sz.hpp" -#include "axslcc/sgs-spec.h" +#include "axmol/rhi/axslc-spec.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { + +using namespace ::axslc; struct SLCReflectContext { - sgs_chunk_refl* refl; + sc_chunk_refl* refl; yasio::fast_ibstream_view* ibs; }; -static inline std::string_view _sgs_read_name(yasio::fast_ibstream_view* ibs) { +static inline std::string_view _sc_read_name(yasio::fast_ibstream_view* ibs) { // view bytes without copy - std::string_view name = ibs->read_bytes(sizeof(sgs_refl_input::name)); + std::string_view name = ibs->read_bytes(sizeof(sc_refl_input::name)); auto len = name.find_last_not_of('\0'); assert(len != std::string::npos); // name must not empty name.remove_suffix(name.length() - len - 1); return name; } -ShaderModuleMTL::ShaderModuleMTL(id mtlDevice, ShaderStage stage, std::string_view source) +ShaderModuleImpl::ShaderModuleImpl(id mtlDevice, ShaderStage stage, std::string_view source) : ShaderModule(stage) { yasio::fast_ibstream_view ibs(source.data(), source.length()); uint32_t fourccId = ibs.read(); - if (fourccId != SGS_CHUNK) + if (fourccId != SC_CHUNK) { assert(false); return; } - auto sgs_size = ibs.read(); // always 0, doesn't matter - struct sgs_chunk chunk; + auto sc_size = ibs.read(); // always 0, doesn't matter + struct sc_chunk chunk; ibs.read_bytes(&chunk, static_cast(sizeof(chunk))); - std::string_view mslCode; + std::string_view shaderSource; do { fourccId = ibs.read(); - if (fourccId != SGS_CHUNK_STAG) + if (fourccId != SC_CHUNK_STAG) { assert(false); return; // error @@ -75,24 +77,21 @@ of this software and associated documentation files (the "Software"), to deal auto stage_size = ibs.read(); // stage_size auto stage_id = ibs.read(); // stage_id ShaderStage ref_stage = (ShaderStage)-1; - if (stage_id == SGS_STAGE_VERTEX) + if (stage_id == SC_STAGE_VERTEX) ref_stage = ShaderStage::VERTEX; - else if (stage_id == SGS_STAGE_FRAGMENT) + else if (stage_id == SC_STAGE_FRAGMENT) ref_stage = ShaderStage::FRAGMENT; assert(ref_stage == stage); - int code_size = 0; - fourccId = ibs.read(); - if (fourccId == SGS_CHUNK_CODE) + fourccId = ibs.read(); + if (fourccId == SC_CHUNK_CODE) { - code_size = ibs.read(); - mslCode = ibs.read_bytes(code_size); + shaderSource = ibs.read_bytes(ibs.read()); } - else if (fourccId == SGS_CHUNK_DATA) + else if (fourccId == SC_CHUNK_DATA) { - code_size = ibs.read(); - mslCode = ibs.read_bytes(code_size); + shaderSource = ibs.read_bytes(ibs.read()); } else { @@ -100,51 +99,50 @@ of this software and associated documentation files (the "Software"), to deal assert(false); } - size_t refl_size = 0; if (!ibs.eof()) { // try read reflect info fourccId = ibs.read(); - if (fourccId == SGS_CHUNK_REFL) + if (fourccId == SC_CHUNK_REFL) { /* REFL: Reflection data for the shader stage - struct sgs_chunk_refl: reflection data header - struct sgs_refl_input[]: array of vertex-shader input attributes (see sgs_chunk_refl for number of - inputs) struct sgs_refl_uniformbuffer[]: array of uniform buffer objects (see sgs_chunk_refl for number - of uniform buffers) struct sgs_refl_texture[]: array of texture objects (see sgs_chunk_refl for number - of textures) struct sgs_refl_texture[]: array of storage image objects (see sgs_chunk_refl for number - of storage images) struct sgs_refl_buffer[]: array of storage buffer objects (see sgs_chunk_refl for + struct sc_chunk_refl: reflection data header + struct sc_refl_input[]: array of vertex-shader input attributes (see sc_chunk_refl for number of + inputs) struct sc_refl_uniformbuffer[]: array of uniform buffer objects (see sc_chunk_refl for number + of uniform buffers) struct sc_refl_texture[]: array of texture objects (see sc_chunk_refl for number + of textures) struct sc_refl_texture[]: array of storage image objects (see sc_chunk_refl for number + of storage images) struct sc_refl_buffer[]: array of storage buffer objects (see sc_chunk_refl for number of storage buffers) */ - const auto refl_size = ibs.read(); + const auto refl_size = ibs.read(); const auto refl_data_offset = ibs.tell(); - sgs_chunk_refl refl; + sc_chunk_refl refl; ibs.advance(sizeof(refl.name)); - refl.num_inputs = ibs.read(); - refl.num_textures = ibs.read(); + refl.num_inputs = ibs.read(); + refl.num_textures = ibs.read(); refl.num_uniform_buffers = ibs.read(); - refl.num_storage_images = ibs.read(); + refl.num_storage_images = ibs.read(); refl.num_storage_buffers = ibs.read(); // skip infos we don't need - ibs.advance(sizeof(sgs_chunk_refl) - offsetof(sgs_chunk_refl, flatten_ubos)); + ibs.advance(sizeof(sc_chunk_refl) - offsetof(sc_chunk_refl, flatten_ubos)); SLCReflectContext context{&refl, &ibs}; // refl_inputs - parseAttibute(&context); + reflectVertexInputs(&context); // refl_uniformbuffers - parseUniform(&context); + reflectUniforms(&context); // refl_textures - parseTexture(&context); + reflectSamplers(&context); // refl_storage_images: ignore - ibs.advance(refl.num_storage_images * sizeof(sgs_refl_texture)); + ibs.advance(refl.num_storage_images * sizeof(sc_refl_texture)); // refl_storage_buffers: ignore - ibs.advance(refl.num_storage_buffers * sizeof(sgs_refl_buffer)); + ibs.advance(refl.num_storage_buffers * sizeof(sc_refl_buffer)); assert(ibs.tell() - refl_data_offset == refl_size); } @@ -158,7 +156,7 @@ of this software and associated documentation files (the "Software"), to deal assert(ibs.eof()); } while (false); // iterator stages, current only 1 stage - auto metalShader = mslCode.data(); + auto metalShader = shaderSource.data(); NSString* shader = [NSString stringWithUTF8String:metalShader]; NSError* error; id library = [mtlDevice newLibraryWithSource:shader options:nil error:&error]; @@ -184,55 +182,55 @@ of this software and associated documentation files (the "Software"), to deal [library release]; } -ShaderModuleMTL::~ShaderModuleMTL() +ShaderModuleImpl::~ShaderModuleImpl() { [_mtlFunction release]; } -void ShaderModuleMTL::parseAttibute(SLCReflectContext* context) +void ShaderModuleImpl::reflectVertexInputs(SLCReflectContext* context) { auto ibs = context->ibs; for (int i = 0; i < context->refl->num_inputs; ++i) { - std::string_view name = _sgs_read_name(ibs); + std::string_view name = _sc_read_name(ibs); auto loc = ibs->read(); - ibs->advance(sizeof(sgs_refl_input) - offsetof(sgs_refl_input, semantic)); + ibs->advance(sizeof(sc_refl_input) - offsetof(sc_refl_input, semantic)); - AttributeBindInfo attributeInfo; - attributeInfo.location = loc; - _attributeInfo[name] = attributeInfo; + VertexInputDesc desc; + desc.location = loc; + _activeVertexInputs[name] = desc; } } -void ShaderModuleMTL::parseUniform(SLCReflectContext* context) +void ShaderModuleImpl::reflectUniforms(SLCReflectContext* context) { _uniformBufferSize = 0; - auto ibs = context->ibs; + auto ibs = context->ibs; for (int i = 0; i < context->refl->num_uniform_buffers; ++i) { - ibs->advance(sizeof(sgs_refl_ub::name)); - auto ub_binding = ibs->read(); + ibs->advance(sizeof(sc_refl_ub::name)); + auto ub_binding = ibs->read(); auto ub_size_bytes = ibs->read(); - ibs->advance(sizeof(sgs_refl_ub::array_size)); + ibs->advance(sizeof(sc_refl_ub::array_size)); auto ub_num_members = ibs->read(); for (int k = 0; k < ub_num_members; ++k) { UniformInfo uniform; - auto name = _sgs_read_name(ibs); + auto name = _sc_read_name(ibs); auto offset = ibs->read(); auto format = ibs->read(); auto size_bytes = ibs->read(); auto array_size = ibs->read(); - uniform.count = array_size; - uniform.location = ub_binding; - uniform.size = size_bytes; - uniform.bufferOffset = offset; - uniform.type = format; - _activeUniformInfos[name] = uniform; + uniform.count = array_size; + uniform.location = ub_binding; + uniform.size = size_bytes; + uniform.bufferOffset = offset; + uniform.type = format; + _activeUniformInfos[name] = uniform; if (_maxLocation < i) _maxLocation = (i + 1); @@ -243,15 +241,15 @@ of this software and associated documentation files (the "Software"), to deal } } -void ShaderModuleMTL::parseTexture(SLCReflectContext* context) +void ShaderModuleImpl::reflectSamplers(SLCReflectContext* context) { auto ibs = context->ibs; for (int i = 0; i < context->refl->num_textures; ++i) { - std::string_view name = _sgs_read_name(ibs); - auto binding = ibs->read(); + std::string_view name = _sc_read_name(ibs); + auto binding = ibs->read(); - ibs->advance(sizeof(sgs_refl_texture) - offsetof(sgs_refl_texture, image_dim)); + ibs->advance(sizeof(sc_refl_texture) - offsetof(sc_refl_texture, image_dim)); UniformInfo uniform; uniform.location = binding; @@ -260,12 +258,12 @@ of this software and associated documentation files (the "Software"), to deal } } -const UniformInfo& ShaderModuleMTL::getUniformInfo(Uniform name) const +const UniformInfo& ShaderModuleImpl::getUniformInfo(Uniform name) const { return _builtinUniforms[name]; } -const UniformInfo& ShaderModuleMTL::getUniformInfo(std::string_view name) const +const UniformInfo& ShaderModuleImpl::getUniformInfo(std::string_view name) const { static UniformInfo none; auto iter = _activeUniformInfos.find(name); @@ -274,21 +272,38 @@ of this software and associated documentation files (the "Software"), to deal return none; } -void ShaderModuleMTL::setBuiltinLocations() +const VertexInputDesc* ShaderModuleImpl::getVertexInputDesc(VertexInputKind name) const +{ + return _builtinVertexInputs[name]; +} + +const VertexInputDesc* ShaderModuleImpl::getVertexInputDesc(std::string_view name) const +{ + auto it = _activeVertexInputs.find(name); + if (it != _activeVertexInputs.end()) + return &it->second; + else + return nullptr; +} + +void ShaderModuleImpl::setBuiltinLocations() { /*--- Builtin Attribs ---*/ /// a_position - _attributeLocation[Attribute::POSITION] = getAttributeLocation(ATTRIBUTE_NAME_POSITION); + _builtinVertexInputs[VertexInputKind::POSITION] = getVertexInputDesc(VERTEX_INPUT_NAME_POSITION); /// a_color - _attributeLocation[Attribute::COLOR] = getAttributeLocation(ATTRIBUTE_NAME_COLOR); + _builtinVertexInputs[VertexInputKind::COLOR] = getVertexInputDesc(VERTEX_INPUT_NAME_COLOR); /// a_texCoord - _attributeLocation[Attribute::TEXCOORD] = getAttributeLocation(ATTRIBUTE_NAME_TEXCOORD); + _builtinVertexInputs[VertexInputKind::TEXCOORD] = getVertexInputDesc(VERTEX_INPUT_NAME_TEXCOORD); // a_normal - _attributeLocation[Attribute::NORMAL] = getAttributeLocation(ATTRIBUTE_NAME_NORMAL); + _builtinVertexInputs[VertexInputKind::NORMAL] = getVertexInputDesc(VERTEX_INPUT_NAME_NORMAL); + + // a_instance, metal use SSUBO(Shader Storage Uniform Buffer) + // _builtinVertexInputs[VertexInputKind::INSTANCE] = getVertexInputDesc(VERTEX_INPUT_NAME_INSTANCE); /*--- Builtin Uniforms ---*/ @@ -311,18 +326,4 @@ of this software and associated documentation files (the "Software"), to deal _builtinUniforms[Uniform::EFFECT_TYPE] = getUniformInfo(UNIFORM_NAME_EFFECT_TYPE); } -int ShaderModuleMTL::getAttributeLocation(Attribute name) const -{ - return _attributeLocation[name]; -} - -int ShaderModuleMTL::getAttributeLocation(std::string_view name) -{ - auto iter = _attributeInfo.find(name); - if (iter != _attributeInfo.end()) - return _attributeInfo[name].location; - else - return -1; } - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/metal/TextureMTL.h b/axmol/rhi/metal/TextureMTL.h similarity index 72% rename from core/renderer/backend/metal/TextureMTL.h rename to axmol/rhi/metal/TextureMTL.h index 25b20cfdbff7..4cee22116bb0 100644 --- a/core/renderer/backend/metal/TextureMTL.h +++ b/axmol/rhi/metal/TextureMTL.h @@ -25,23 +25,17 @@ #pragma once -#include "../Texture.h" -#include "DriverMTL.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/metal/DriverMTL.h" #import #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { /** * @addtogroup _metal * @{ */ -enum -{ - MTL_TEXTURE_2D = 1, - MTL_TEXTURE_CUBE, -}; - struct TextureInfoMTL { TextureInfoMTL(id mtlDevice) @@ -51,11 +45,11 @@ struct TextureInfoMTL } ~TextureInfoMTL() { destroy(); } - id ensure(int index, int target); + id ensure(int index); void destroy(); - id createTexture(id mtlDevice, const TextureDescriptor& descriptor, int target); - void recreateSampler(const SamplerDescriptor& descriptor); + id createTexture(id mtlDevice, const TextureDesc& descriptor); + void recreateSampler(const SamplerDesc& descriptor); MTLSamplerAddressMode _sAddressMode; MTLSamplerAddressMode _tAddressMode; @@ -63,28 +57,28 @@ struct TextureInfoMTL MTLSamplerMinMagFilter _magFilter; MTLSamplerMipFilter _mipFilter; - TextureDescriptor _descriptor; - id _mtlDevice; std::array, AX_META_TEXTURES + 1> _mtlTextures; int _maxIdx = -1; + TextureDesc _desc; + id _mtlSamplerState = nil; unsigned int _bytesPerRow = 0; }; /** - * A 2D texture + * TextureImpl */ -class TextureMTL : public backend::Texture2DBackend +class TextureImpl : public rhi::Texture { public: /** * @param mtlDevice The device for which MTLTexture and MTLSamplerState object was created. * @param descriptor Specify texture and sampler description. */ - TextureMTL(id mtlDevice, const TextureDescriptor& descriptor); - ~TextureMTL(); + TextureImpl(id mtlDevice, const TextureDesc& descriptor); + ~TextureImpl(); /** * Update a two-dimensional texture image @@ -156,99 +150,51 @@ class TextureMTL : public backend::Texture2DBackend /** * Update sampler - * @param sampler Specifies the sampler descriptor. + * @param desc Specifies the sampler descriptor. */ - virtual void updateSamplerDescriptor(const SamplerDescriptor& sampler) override; + void updateSamplerDesc(const SamplerDesc& desc) override; /** * Generate mipmaps. */ - virtual void generateMipmaps() override; + void generateMipmaps() override; /** * Update texture description. - * @param descriptor Specifies texture and sampler descriptor. - */ - virtual void updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index = 0) override; - - int getCount() const override { return _textureInfo._maxIdx + 1; } - - /** - * Get MTLTexture object. reinterpret_cast>(handler); - * @return A MTLTexture object. - */ - uintptr_t getHandler(int index = 0) const override - { - return reinterpret_cast((void*)_textureInfo._mtlTextures[index]); - } - - /** - * Get MTLSamplerState object - * @return A MTLSamplerState object. - */ - inline id getMTLSamplerState() const { return _textureInfo._mtlSamplerState; } - -private: - TextureInfoMTL _textureInfo; -}; - -/** - * A texture cube - */ -class TextureCubeMTL : public backend::TextureCubemapBackend -{ -public: - /** - * @param mtlDevice The device for which MTLTexture and MTLSamplerState object was created. - * @param descriptor Specify texture and sampler description. + * @param desc Specifies texture and sampler descriptor. */ - TextureCubeMTL(id mtlDevice, const TextureDescriptor& descriptor); - ~TextureCubeMTL(); - - /** - * Update sampler - * @param sampler Specifies the sampler descriptor. - */ - virtual void updateSamplerDescriptor(const SamplerDescriptor& sampler) override; + void updateTextureDesc(const TextureDesc& desc, int index = 0) override; /** * Update texutre cube data in give slice side. * @param side Specifies which slice texture of cube to be update. * @param data Specifies a pointer to the image data in memory. */ - virtual void updateFaceData(TextureCubeFace side, void* data, int index = 0) override; + void updateFaceData(TextureCubeFace side, void* data, int index = 0) override; - /** - * Generate mipmaps. - */ - virtual void generateMipmaps() override; + int getCount() const override { return _textureInfo._maxIdx + 1; } /** - * Update texture description. - * @param descriptor Specifies texture and sampler descriptor. + * Get MTLTexture object. reinterpret_cast>(handler); + * @return A MTLTexture object. */ - virtual void updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index = 0) override; - - int getCount() const override { return _textureInfo._maxIdx + 1; } - - uintptr_t getHandler(int index = 0) const override + id internalHandle(int index = 0) const { - return reinterpret_cast((void*)_textureInfo._mtlTextures[index]); + return _textureInfo._mtlTextures[index]; } /** * Get MTLSamplerState object * @return A MTLSamplerState object. */ - inline id getMTLSamplerState() const { return _textureInfo._mtlSamplerState; } + inline id internalSampler() const { return _textureInfo._mtlSamplerState; } private: TextureInfoMTL _textureInfo; MTLRegion _region; - std::size_t _bytesPerImage = 0; }; // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/axmol/rhi/metal/TextureMTL.mm b/axmol/rhi/metal/TextureMTL.mm new file mode 100644 index 000000000000..e4c1e3579b12 --- /dev/null +++ b/axmol/rhi/metal/TextureMTL.mm @@ -0,0 +1,232 @@ +/**************************************************************************** + Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "axmol/rhi/metal/TextureMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/base/Macros.h" +#include "axmol/rhi/PixelFormatUtils.h" +#include "axmol/rhi/SamplerCache.h" + +namespace ax::rhi::mtl { + +namespace +{ + +static bool isColorRenderable(PixelFormat textureFormat) +{ + switch (textureFormat) + { + case PixelFormat::RGBA8: + case PixelFormat::RGBA4: + case PixelFormat::RGB565: + case PixelFormat::RGB5A1: + return true; + default: + return false; + } +} +} + +/// CLASS TextureInfoMTL +id TextureInfoMTL::ensure(int index) +{ + if (index < AX_META_TEXTURES) + { + id& mtlTexture = _mtlTextures[index]; + if (mtlTexture) + return mtlTexture; + mtlTexture = createTexture(_mtlDevice, _desc); + if (_maxIdx < index) + _maxIdx = index; + return mtlTexture; + } + return nil; +} + +void TextureInfoMTL::destroy() +{ + if (_maxIdx == -1) + return; + + id texture; + int i = 0; + while ((texture = _mtlTextures[i++])) + [texture release]; + + _mtlSamplerState = nil; + + _maxIdx = -1; +} + +id TextureInfoMTL::createTexture(id mtlDevice, const TextureDesc& descriptor) +{ + MTLPixelFormat pixelFormat = UtilsMTL::toMTLPixelFormat(descriptor.textureFormat); + if (pixelFormat == MTLPixelFormatInvalid) + return nil; + + MTLTextureDescriptor* textureDesc = nil; + switch (descriptor.textureType) + { + case TextureType::TEXTURE_2D: + textureDesc = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat + width:descriptor.width + height:descriptor.height + mipmapped:YES]; + break; + case TextureType::TEXTURE_CUBE: + textureDesc = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:pixelFormat + size:descriptor.width + mipmapped:YES]; + break; + default: + return nil; + } + + if (TextureUsage::RENDER_TARGET == descriptor.textureUsage) + { + // DepthStencil, and Multisample textures must be allocated with the MTLResourceStorageModePrivate resource + // option + if (PixelFormat::D24S8 == descriptor.textureFormat && descriptor.textureType == TextureType::TEXTURE_2D) + textureDesc.resourceOptions = MTLResourceStorageModePrivate; + textureDesc.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; + } + + return [mtlDevice newTextureWithDescriptor:textureDesc]; +} + +void TextureInfoMTL::recreateSampler(const SamplerDesc& desc) +{ + _mtlSamplerState = (id)SamplerCache::getInstance()->getSampler(desc); +} + +/// CLASS TextureImpl +TextureImpl::TextureImpl(id mtlDevice, const TextureDesc& descriptor) : _textureInfo(mtlDevice) +{ + updateTextureDesc(descriptor); +} + +TextureImpl::~TextureImpl() {} + +void TextureImpl::updateSamplerDesc(const SamplerDesc& sampler) +{ + _textureInfo.recreateSampler(sampler); +} + +void TextureImpl::updateTextureDesc(const TextureDesc& desc, int index) +{ + Texture::updateTextureDesc(desc, index); + + _textureInfo._desc = desc; + _textureInfo.ensure(index); + updateSamplerDesc(desc.samplerDesc); + + _textureInfo._bytesPerRow = PixelFormatUtils::computeRowPitch(desc.textureFormat, desc.width); + + if (desc.textureType == TextureType::TEXTURE_CUBE) { + _region = MTLRegionMake2D(0, 0, desc.width, desc.height); + } +} + +void TextureImpl::updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index) +{ + updateSubData(0, 0, width, height, level, data, index); +} + +void TextureImpl::updateSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t level, + uint8_t* data, + int index) +{ + auto mtlTexture = _textureInfo.ensure(index); + if (!mtlTexture) + return; + + MTLRegion region = { + {xoffset, yoffset, 0}, // MTLOrigin + {width, height, 1} // MTLSize + }; + + auto bytesPerRow = PixelFormatUtils::computeRowPitch(_textureFormat, static_cast(width)); + + [mtlTexture replaceRegion:region mipmapLevel:level withBytes:data bytesPerRow:bytesPerRow]; + + if (!_hasMipmaps && level > 0) + _hasMipmaps = true; +} + +void TextureImpl::updateCompressedData(uint8_t* data, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + int index) +{ + updateCompressedSubData(0, 0, width, height, dataLen, level, data, index); +} + +void TextureImpl::updateCompressedSubData(std::size_t xoffset, + std::size_t yoffset, + std::size_t width, + std::size_t height, + std::size_t dataLen, + std::size_t level, + uint8_t* data, + int index) +{ + updateSubData(xoffset, yoffset, width, height, level, data, index); +} + +void TextureImpl::generateMipmaps() +{ + if (TextureUsage::RENDER_TARGET == _textureUsage || !isColorRenderable(_textureFormat)) + return; + + if (!_hasMipmaps) + { + _hasMipmaps = true; + UtilsMTL::generateMipmaps(internalHandle()); + } +} + +void TextureImpl::updateFaceData(TextureCubeFace side, void* data, int index) +{ + NSUInteger slice = static_cast(side); + auto mtlTexture = _textureInfo.ensure(index); + if (!mtlTexture) + return; + + auto slicePitch = _textureInfo._bytesPerRow * _textureInfo._desc.height; + [mtlTexture replaceRegion:_region + mipmapLevel:0 + slice:slice + withBytes:data + bytesPerRow:_textureInfo._bytesPerRow + bytesPerImage:slicePitch]; +} + +} diff --git a/core/renderer/backend/metal/UtilsMTL.h b/axmol/rhi/metal/UtilsMTL.h similarity index 94% rename from core/renderer/backend/metal/UtilsMTL.h rename to axmol/rhi/metal/UtilsMTL.h index d8ea59dcaf5c..1b303f5b0ba4 100644 --- a/core/renderer/backend/metal/UtilsMTL.h +++ b/axmol/rhi/metal/UtilsMTL.h @@ -25,15 +25,15 @@ #pragma once -#include "../Macros.h" -#include "../Types.h" -#include "../PixelBufferDescriptor.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/PixelBufferDesc.h" #import #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi { +class Texture; -class TextureBackend; +namespace mtl { /** * @addtogroup _metal @@ -70,7 +70,7 @@ struct UtilsMTL static id getDefaultDepthStencilTexture(); /** - * Convert backend::PixelFormat to MTLPixelFormat. + * Convert rhi::PixelFormat to MTLPixelFormat. * @param textureFormat Specifies a pixel format to be converted. * @return A MTLPixelFormat. */ @@ -98,6 +98,8 @@ struct UtilsMTL static id _defaultDepthStencilAttachmentTexture; }; +} + // end of _metal group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/metal/UtilsMTL.mm b/axmol/rhi/metal/UtilsMTL.mm similarity index 87% rename from core/renderer/backend/metal/UtilsMTL.mm rename to axmol/rhi/metal/UtilsMTL.mm index fca8fec252bb..bccd0f654a84 100644 --- a/core/renderer/backend/metal/UtilsMTL.mm +++ b/axmol/rhi/metal/UtilsMTL.mm @@ -23,13 +23,13 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "UtilsMTL.h" -#include "DriverMTL.h" -#include "TextureMTL.h" -#include "../PixelFormatUtils.h" -#include "base/Configuration.h" +#include "axmol/rhi/metal/UtilsMTL.h" +#include "axmol/rhi/metal/DriverMTL.h" +#include "axmol/rhi/metal/TextureMTL.h" +#include "axmol/rhi/PixelFormatUtils.h" +#include "axmol/base/Configuration.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::mtl { id UtilsMTL::_defaultColorAttachmentTexture = nil; id UtilsMTL::_defaultDepthStencilAttachmentTexture = nil; @@ -40,7 +40,7 @@ MTLPixelFormat getSupportedDepthStencilFormat() { MTLPixelFormat pixelFormat = MTLPixelFormatDepth32Float_Stencil8; #if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) - bool isDepth24Stencil8PixelFormatSupported = DriverMTL::supportD24S8(); + bool isDepth24Stencil8PixelFormatSupported = DriverImpl::supportD24S8(); if (isDepth24Stencil8PixelFormatSupported) pixelFormat = MTLPixelFormatDepth24Unorm_Stencil8; #endif @@ -153,29 +153,29 @@ MTLPixelFormat getSupportedDepthStencilFormat() void UtilsMTL::resizeDefaultAttachmentTexture(std::size_t width, std::size_t height) { - [backend::DriverMTL::getCAMetalLayer() setDrawableSize:CGSizeMake(width, height)]; + [DriverImpl::getCAMetalLayer() setDrawableSize:CGSizeMake(width, height)]; [_defaultDepthStencilAttachmentTexture release]; _defaultDepthStencilAttachmentTexture = UtilsMTL::createDepthStencilAttachmentTexture(); } id UtilsMTL::createDepthStencilAttachmentTexture() { - auto CAMetalLayer = DriverMTL::getCAMetalLayer(); - MTLTextureDescriptor* textureDescriptor = [[MTLTextureDescriptor alloc] init]; - textureDescriptor.width = CAMetalLayer.drawableSize.width; - textureDescriptor.height = CAMetalLayer.drawableSize.height; - textureDescriptor.pixelFormat = s_textureFormats[(int)PixelFormat::D24S8].fmt; - textureDescriptor.resourceOptions = MTLResourceStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget; - auto ret = [CAMetalLayer.device newTextureWithDescriptor:textureDescriptor]; - [textureDescriptor release]; + auto CAMetalLayer = DriverImpl::getCAMetalLayer(); + MTLTextureDescriptor* textureDesc = [[MTLTextureDescriptor alloc] init]; + textureDesc.width = CAMetalLayer.drawableSize.width; + textureDesc.height = CAMetalLayer.drawableSize.height; + textureDesc.pixelFormat = s_textureFormats[(int)PixelFormat::D24S8].fmt; + textureDesc.resourceOptions = MTLResourceStorageModePrivate; + textureDesc.usage = MTLTextureUsageRenderTarget; + auto ret = [CAMetalLayer.device newTextureWithDescriptor:textureDesc]; + [textureDesc release]; return ret; } void UtilsMTL::generateMipmaps(id texture) { - auto commandQueue = static_cast(DriverMTL::getInstance())->getMTLCommandQueue(); + auto commandQueue = static_cast(DriverBase::getInstance())->getMTLCommandQueue(); auto commandBuffer = [commandQueue commandBuffer]; id commandEncoder = [commandBuffer blitCommandEncoder]; [commandEncoder generateMipmapsForTexture:texture]; @@ -206,4 +206,4 @@ MTLPixelFormat getSupportedDepthStencilFormat() } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/BufferGL.cpp b/axmol/rhi/opengl/BufferGL.cpp similarity index 77% rename from core/renderer/backend/opengl/BufferGL.cpp rename to axmol/rhi/opengl/BufferGL.cpp index 5c717940bbbb..886787076688 100644 --- a/core/renderer/backend/opengl/BufferGL.cpp +++ b/axmol/rhi/opengl/BufferGL.cpp @@ -22,15 +22,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "BufferGL.h" +#include "axmol/rhi/opengl/BufferGL.h" #include -#include "base/Director.h" -#include "base/EventType.h" -#include "base/EventDispatcher.h" -#include "renderer/backend/opengl/MacrosGL.h" -#include "OpenGLState.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventType.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/OpenGLState.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { namespace { @@ -48,7 +48,7 @@ GLenum toGLUsage(const BufferUsage& usage) } } // namespace -BufferGL::BufferGL(std::size_t size, BufferType type, BufferUsage usage) : Buffer(size, type, usage) +BufferImpl::BufferImpl(std::size_t size, BufferType type, BufferUsage usage) : Buffer(size, type, usage) { glGenBuffers(1, &_buffer); @@ -59,17 +59,17 @@ BufferGL::BufferGL(std::size_t size, BufferType type, BufferUsage usage) : Buffe #endif } -BufferGL::~BufferGL() +BufferImpl::~BufferImpl() { if (_buffer) - __gl->deleteBuffer(_type, _buffer); + __state->deleteBuffer(_type, _buffer); #if AX_ENABLE_CACHE_TEXTURE_DATA AX_SAFE_DELETE_ARRAY(_data); Director::getInstance()->getEventDispatcher()->removeEventListener(_backToForegroundListener); #endif } -void BufferGL::usingDefaultStoredData(bool needDefaultStoredData) +void BufferImpl::usingDefaultStoredData(bool needDefaultStoredData) { #if AX_ENABLE_CACHE_TEXTURE_DATA _needDefaultStoredData = needDefaultStoredData; @@ -77,7 +77,7 @@ void BufferGL::usingDefaultStoredData(bool needDefaultStoredData) } #if AX_ENABLE_CACHE_TEXTURE_DATA -void BufferGL::reloadBuffer() +void BufferImpl::reloadBuffer() { glGenBuffers(1, &_buffer); @@ -88,7 +88,7 @@ void BufferGL::reloadBuffer() updateData(_data, _bufferAllocated); } -void BufferGL::fillBuffer(const void* data, std::size_t offset, std::size_t size) +void BufferImpl::fillBuffer(const void* data, std::size_t offset, std::size_t size) { if (_bufferAlreadyFilled || !_needDefaultStoredData || BufferUsage::STATIC != _usage) return; @@ -102,13 +102,13 @@ void BufferGL::fillBuffer(const void* data, std::size_t offset, std::size_t size } #endif -void BufferGL::updateData(const void* data, std::size_t size) +void BufferImpl::updateData(const void* data, std::size_t size) { assert(size && size <= _size); if (_buffer) { - glBufferData(__gl->bindBuffer(_type, _buffer), size, data, toGLUsage(_usage)); + glBufferData(__state->bindBuffer(_type, _buffer), size, data, toGLUsage(_usage)); CHECK_GL_ERROR_DEBUG(); _bufferAllocated = size; @@ -119,7 +119,7 @@ void BufferGL::updateData(const void* data, std::size_t size) } } -void BufferGL::updateSubData(const void* data, std::size_t offset, std::size_t size) +void BufferImpl::updateSubData(const void* data, std::size_t offset, std::size_t size) { AXASSERT(_bufferAllocated != 0, "updateData should be invoke before updateSubData"); @@ -129,7 +129,7 @@ void BufferGL::updateSubData(const void* data, std::size_t offset, std::size_t s { CHECK_GL_ERROR_DEBUG(); - glBufferSubData(__gl->bindBuffer(_type, _buffer), offset, size, data); + glBufferSubData(__state->bindBuffer(_type, _buffer), offset, size, data); #if AX_ENABLE_CACHE_TEXTURE_DATA fillBuffer(data, offset, size); @@ -138,4 +138,4 @@ void BufferGL::updateSubData(const void* data, std::size_t offset, std::size_t s } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/BufferGL.h b/axmol/rhi/opengl/BufferGL.h similarity index 87% rename from core/renderer/backend/opengl/BufferGL.h rename to axmol/rhi/opengl/BufferGL.h index 6cd3a51d2d9a..aa0e40bbe3c7 100644 --- a/core/renderer/backend/opengl/BufferGL.h +++ b/axmol/rhi/opengl/BufferGL.h @@ -24,13 +24,13 @@ #pragma once -#include "../Buffer.h" -#include "platform/GL.h" -#include "base/EventListenerCustom.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/platform/GL.h" +#include "axmol/base/EventListenerCustom.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { /** * @addtogroup _opengl * @{ @@ -39,7 +39,7 @@ NS_AX_BACKEND_BEGIN /** * Store vertex and index data. */ -class BufferGL : public Buffer +class BufferImpl : public Buffer { public: /** @@ -49,8 +49,8 @@ class BufferGL : public Buffer * @param usage Specifies the expected usage pattern of the data store. The symbolic constant must be * BufferUsage::STATIC, BufferUsage::DYNAMIC. */ - BufferGL(std::size_t size, BufferType type, BufferUsage usage); - ~BufferGL(); + BufferImpl(std::size_t size, BufferType type, BufferUsage usage); + ~BufferImpl(); /** * @brief Update buffer data @@ -58,7 +58,7 @@ class BufferGL : public Buffer * @param size Specifies the size in bytes of the data store region being replaced. * @see `updateSubData(void* data, unsigned int offset, unsigned int size)` */ - virtual void updateData(const void* data, std::size_t size) override; + void updateData(const void* data, std::size_t size) override; /** * @brief Update buffer sub-region data @@ -68,7 +68,7 @@ class BufferGL : public Buffer * @param size Specifies the size in bytes of the data store region being replaced. * @see `updateData(void* data, unsigned int size)` */ - virtual void updateSubData(const void* data, std::size_t offset, std::size_t size) override; + void updateSubData(const void* data, std::size_t offset, std::size_t size) override; /** * Static buffer data will automatically stored when it comes to foreground. @@ -76,7 +76,7 @@ class BufferGL : public Buffer * using the default stored data(true). * @param needDefaultStoredData Specifies whether to use the default stored data. */ - virtual void usingDefaultStoredData(bool needDefaultStoredData) override; + void usingDefaultStoredData(bool needDefaultStoredData) override; /** * Get buffer object. @@ -99,4 +99,4 @@ class BufferGL : public Buffer }; // end of _opengl group ///> @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/CommandBufferGL.cpp b/axmol/rhi/opengl/CommandBufferGL.cpp similarity index 59% rename from core/renderer/backend/opengl/CommandBufferGL.cpp rename to axmol/rhi/opengl/CommandBufferGL.cpp index e040692abf0f..5afefb6290ab 100644 --- a/core/renderer/backend/opengl/CommandBufferGL.cpp +++ b/axmol/rhi/opengl/CommandBufferGL.cpp @@ -23,63 +23,45 @@ THE SOFTWARE. ****************************************************************************/ -#include "CommandBufferGL.h" -#include "BufferGL.h" -#include "RenderPipelineGL.h" -#include "TextureGL.h" -#include "DepthStencilStateGL.h" -#include "ProgramGL.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "base/Director.h" -#include "MacrosGL.h" -#include "UtilsGL.h" -#include "RenderTargetGL.h" -#include "DriverGL.h" +#include "axmol/rhi/opengl/CommandBufferGL.h" +#include "axmol/rhi/opengl/BufferGL.h" +#include "axmol/rhi/opengl/RenderPipelineGL.h" +#include "axmol/rhi/opengl/TextureGL.h" +#include "axmol/rhi/opengl/DepthStencilStateGL.h" +#include "axmol/rhi/opengl/ProgramGL.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Director.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/opengl/RenderTargetGL.h" +#include "axmol/rhi/opengl/DriverGL.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -#if AX_GLES_PROFILE != 200 && AX_TARGET_PLATFORM != AX_PLATFORM_WASM +// !!Note: WebGL 2.0 on (Open GELS 3.0) not support map buffer range +#if AX_TARGET_PLATFORM != AX_PLATFORM_WASM # define AX_HAVE_MAP_BUFFER_RANGE 1 #else # define AX_HAVE_MAP_BUFFER_RANGE 0 #endif -namespace -{ -void applyTexture(TextureBackend* texture, int slot, int index) -{ - switch (texture->getTextureType()) - { - case TextureType::TEXTURE_2D: - static_cast(texture)->apply(slot, index); - break; - case TextureType::TEXTURE_CUBE: - static_cast(texture)->apply(slot, index); - break; - default: - assert(false); - return; - } -} -} // namespace - -CommandBufferGL::CommandBufferGL() {} +CommandBufferImpl::CommandBufferImpl() {} -CommandBufferGL::~CommandBufferGL() +CommandBufferImpl::~CommandBufferImpl() { cleanResources(); } -bool CommandBufferGL::beginFrame() +bool CommandBufferImpl::beginFrame() { return true; } -void CommandBufferGL::beginRenderPass(const RenderTarget* rt, const RenderPassDescriptor& descriptor) +void CommandBufferImpl::beginRenderPass(const RenderTarget* rt, const RenderPassDesc& descriptor) { - auto rtGL = static_cast(rt); + auto rtGL = static_cast(rt); rtGL->bindFrameBuffer(); rtGL->update(); @@ -110,10 +92,10 @@ void CommandBufferGL::beginRenderPass(const RenderTarget* rt, const RenderPassDe mask |= GL_DEPTH_BUFFER_BIT; glClearDepth(descriptor.clearDepthValue); - __gl->enableDepthTest(); + __state->enableDepthTest(); - __gl->depthMask(GL_TRUE); - __gl->depthFunc(GL_ALWAYS); + __state->depthMask(GL_TRUE); + __state->depthFunc(GL_ALWAYS); } CHECK_GL_ERROR_DEBUG(); @@ -133,100 +115,118 @@ void CommandBufferGL::beginRenderPass(const RenderTarget* rt, const RenderPassDe if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH)) { if (!oldDepthTest) - __gl->disableDepthTest(); + __state->disableDepthTest(); - __gl->depthMask(oldDepthWrite); - __gl->depthFunc(oldDepthFunc); + __state->depthMask(oldDepthWrite); + __state->depthFunc(oldDepthFunc); glClearDepth(oldDepthClearValue); } CHECK_GL_ERROR_DEBUG(); } -void CommandBufferGL::setDepthStencilState(DepthStencilState* depthStencilState) +void CommandBufferImpl::setDepthStencilState(DepthStencilState* depthStencilState) { - _depthStencilStateGL = static_cast(depthStencilState); + _depthStencilStateImpl = static_cast(depthStencilState); } -void CommandBufferGL::setRenderPipeline(RenderPipeline* renderPipeline) +void CommandBufferImpl::setRenderPipeline(RenderPipeline* renderPipeline) { - _renderPipeline = static_cast(renderPipeline); + _renderPipeline = static_cast(renderPipeline); } /** * Update depthStencil status, improvment: for metal backend cache it * @param depthStencilState Specifies the depth and stencil status */ -void CommandBufferGL::updateDepthStencilState(const DepthStencilDescriptor& descriptor) +void CommandBufferImpl::updateDepthStencilState(const DepthStencilDesc& descriptor) { - _depthStencilStateGL->update(descriptor); + _depthStencilStateImpl->update(descriptor); } /** * Update render pipeline status * @param depthStencilState Specifies the depth and stencil status */ -void CommandBufferGL::updatePipelineState(const RenderTarget* rt, const PipelineDescriptor& descriptor) +void CommandBufferImpl::updatePipelineState(const RenderTarget* rt, const PipelineDesc& descriptor) { _renderPipeline->update(rt, descriptor); } -void CommandBufferGL::setViewport(int x, int y, unsigned int w, unsigned int h) +void CommandBufferImpl::setViewport(int x, int y, unsigned int w, unsigned int h) { - __gl->viewport(_viewPort.set(x, y, w, h)); + __state->viewport(_viewPort.set(x, y, w, h)); } -void CommandBufferGL::setCullMode(CullMode mode) +void CommandBufferImpl::setCullMode(CullMode mode) { _cullMode = mode; } -void CommandBufferGL::setWinding(Winding winding) +void CommandBufferImpl::setWinding(Winding winding) { - __gl->winding(winding); + __state->winding(winding); } -void CommandBufferGL::setIndexBuffer(Buffer* buffer) +void CommandBufferImpl::setProgramState(ProgramState* programState) +{ + AX_SAFE_RETAIN(programState); + AX_SAFE_RELEASE(_programState); + _programState = programState; +} + +void CommandBufferImpl::setVertexBuffer(Buffer* buffer) { assert(buffer != nullptr); - if (buffer == nullptr || _indexBuffer == buffer) + if (buffer == nullptr || _vertexBuffer == buffer) return; buffer->retain(); - AX_SAFE_RELEASE(_indexBuffer); - _indexBuffer = static_cast(buffer); + AX_SAFE_RELEASE(_vertexBuffer); + _vertexBuffer = static_cast(buffer); } -void CommandBufferGL::setInstanceBuffer(Buffer* buffer) +void CommandBufferImpl::setIndexBuffer(Buffer* buffer) { assert(buffer != nullptr); - if (buffer == nullptr || _instanceTransformBuffer == buffer) + if (buffer == nullptr || _indexBuffer == buffer) return; buffer->retain(); - AX_SAFE_RELEASE(_instanceTransformBuffer); - _instanceTransformBuffer = static_cast(buffer); + AX_SAFE_RELEASE(_indexBuffer); + _indexBuffer = static_cast(buffer); } -void CommandBufferGL::setVertexBuffer(Buffer* buffer) +void CommandBufferImpl::setInstanceBuffer(Buffer* buffer) { assert(buffer != nullptr); - if (buffer == nullptr || _vertexBuffer == buffer) + if (buffer == nullptr || _instanceBuffer == buffer) return; buffer->retain(); - AX_SAFE_RELEASE(_vertexBuffer); - _vertexBuffer = static_cast(buffer); + AX_SAFE_RELEASE(_instanceBuffer); + _instanceBuffer = static_cast(buffer); } -void CommandBufferGL::setProgramState(ProgramState* programState) +void CommandBufferImpl::drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe) { - AX_SAFE_RETAIN(programState); - AX_SAFE_RELEASE(_programState); - _programState = programState; + prepareDrawing(); +#if !AX_GLES_PROFILE // glPolygonMode is only supported in Desktop OpenGL + if (wireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); +#else + if (wireframe) + primitiveType = PrimitiveType::LINE; +#endif + glDrawArrays(UtilsGL::toGLPrimitiveType(primitiveType), start, count); +#if !AX_GLES_PROFILE // glPolygonMode is only supported in Desktop OpenGL + if (wireframe) + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); +#endif + cleanResources(); } -void CommandBufferGL::drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe) +void CommandBufferImpl::drawArraysInstanced(PrimitiveType primitiveType, std::size_t start, std::size_t count, int instanceCount, bool wireframe) { prepareDrawing(); #if !AX_GLES_PROFILE // glPolygonMode is only supported in Desktop OpenGL @@ -236,7 +236,7 @@ void CommandBufferGL::drawArrays(PrimitiveType primitiveType, std::size_t start, if (wireframe) primitiveType = PrimitiveType::LINE; #endif - glDrawArrays(UtilsGL::toGLPrimitiveType(primitiveType), start, count); + glDrawArraysInstanced(UtilsGL::toGLPrimitiveType(primitiveType), start, count, instanceCount); #if !AX_GLES_PROFILE // glPolygonMode is only supported in Desktop OpenGL if (wireframe) glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); @@ -244,7 +244,7 @@ void CommandBufferGL::drawArrays(PrimitiveType primitiveType, std::size_t start, cleanResources(); } -void CommandBufferGL::drawElements(PrimitiveType primitiveType, +void CommandBufferImpl::drawElements(PrimitiveType primitiveType, IndexFormat indexType, std::size_t count, std::size_t offset, @@ -258,7 +258,7 @@ void CommandBufferGL::drawElements(PrimitiveType primitiveType, if (wireframe) primitiveType = PrimitiveType::LINE; #endif - __gl->bindBuffer(BufferType::ELEMENT_ARRAY_BUFFER, _indexBuffer->getHandler()); + __state->bindBuffer(BufferType::ELEMENT_ARRAY_BUFFER, _indexBuffer->getHandler()); glDrawElements(UtilsGL::toGLPrimitiveType(primitiveType), count, UtilsGL::toGLIndexType(indexType), (GLvoid*)offset); CHECK_GL_ERROR_DEBUG(); @@ -269,7 +269,7 @@ void CommandBufferGL::drawElements(PrimitiveType primitiveType, cleanResources(); } -void CommandBufferGL::drawElementsInstanced(PrimitiveType primitiveType, +void CommandBufferImpl::drawElementsInstanced(PrimitiveType primitiveType, IndexFormat indexType, std::size_t count, std::size_t offset, @@ -284,7 +284,7 @@ void CommandBufferGL::drawElementsInstanced(PrimitiveType primitiveType, if (wireframe) primitiveType = PrimitiveType::LINE; #endif - __gl->bindBuffer(BufferType::ELEMENT_ARRAY_BUFFER, _indexBuffer->getHandler()); + __state->bindBuffer(BufferType::ELEMENT_ARRAY_BUFFER, _indexBuffer->getHandler()); glDrawElementsInstanced(UtilsGL::toGLPrimitiveType(primitiveType), count, UtilsGL::toGLIndexType(indexType), (GLvoid*)offset, instanceCount); CHECK_GL_ERROR_DEBUG(); @@ -295,91 +295,104 @@ void CommandBufferGL::drawElementsInstanced(PrimitiveType primitiveType, cleanResources(); } -void CommandBufferGL::endRenderPass() +void CommandBufferImpl::endRenderPass() { AX_SAFE_RELEASE_NULL(_indexBuffer); AX_SAFE_RELEASE_NULL(_vertexBuffer); - AX_SAFE_RELEASE_NULL(_instanceTransformBuffer); + AX_SAFE_RELEASE_NULL(_instanceBuffer); } -void CommandBufferGL::endFrame() {} +void CommandBufferImpl::endFrame() +{ +} -void CommandBufferGL::prepareDrawing() const +void CommandBufferImpl::prepareDrawing() const { const auto& program = _renderPipeline->getProgram(); - __gl->useProgram(program->getHandler()); + __state->useProgram(program->getHandler()); uint32_t usedBits{0}; bindVertexBuffer(usedBits); - bindInstanceBuffer(program, usedBits); - __gl->disableUnusedVertexAttribs(usedBits); + __state->disableUnusedVertexAttribs(usedBits); bindUniforms(program); // Set depth/stencil state. - if (_depthStencilStateGL->isEnabled()) - _depthStencilStateGL->apply(_stencilReferenceValueFront, _stencilReferenceValueBack); + if (_depthStencilStateImpl->isEnabled()) + _depthStencilStateImpl->apply(_stencilReferenceValue); else - DepthStencilStateGL::reset(); + DepthStencilStateImpl::reset(); // Set cull mode. if (_cullMode != CullMode::NONE) - __gl->enableCullFace(UtilsGL::toGLCullMode(_cullMode)); + __state->enableCullFace(UtilsGL::toGLCullMode(_cullMode)); else - __gl->disableCullFace(); + __state->disableCullFace(); } -void CommandBufferGL::bindVertexBuffer(uint32_t& usedBits) const +void CommandBufferImpl::bindVertexBuffer(uint32_t& usedBits) const { - // Bind vertex buffers and set the attributes. auto vertexLayout = _programState->getVertexLayout(); - const auto& attributes = vertexLayout->getAttributes(); if (!vertexLayout->isValid()) return; - // Bind VAO, engine share 1 VAO for all vertexLayouts aka vfmts - // optimize proposal: create VAO per vertexLayout, just need bind VAO - __gl->bindBuffer(BufferType::ARRAY_BUFFER, _vertexBuffer->getHandler()); - - for (const auto& attributeInfo : attributes) + // Bind vertex buffers and set the attributes. { - const auto& attribute = attributeInfo.second; - __gl->enableVertexAttribArray(attribute.index); - glVertexAttribPointer(attribute.index, UtilsGL::getGLAttributeSize(attribute.format), - UtilsGL::toGLAttributeType(attribute.format), attribute.needToBeNormallized, - vertexLayout->getStride(), (GLvoid*)attribute.offset); - // non-instance attrib not use divisor, so clear to 0 - __gl->clearVertexAttribDivisor(attribute.index); - usedBits |= (1 << attribute.index); + // Bind VAO, engine share 1 VAO for all vertexLayouts aka vfmts + // optimize proposal: create VAO per vertexLayout, just need bind VAO + __state->bindBuffer(BufferType::ARRAY_BUFFER, _vertexBuffer->getHandler()); + + const auto& attributes = vertexLayout->getBindings(); + for (const auto& attributeInfo : attributes) + { + const auto& attribute = attributeInfo.second; + __state->enableVertexAttribArray(attribute.index); + glVertexAttribPointer(attribute.index, UtilsGL::getGLAttributeSize(attribute.format), + UtilsGL::toGLAttributeType(attribute.format), attribute.needToBeNormallized, + vertexLayout->getStride(), (GLvoid*)static_cast(attribute.offset)); + // non-instance attrib not use divisor, so clear to 0 + __state->clearVertexAttribDivisor(attribute.index); + usedBits |= (1 << attribute.index); + } } -} -void CommandBufferGL::bindInstanceBuffer(ProgramGL* program, uint32_t& usedBits) const -{ - // if we have an instance transform buffer pointer then we must be rendering in instance mode. - if (_instanceTransformBuffer) + // Bind vertex instance buffer and set attributes + if (_instanceBuffer) { - auto instanceLoc = program->getAttributeLocation(Attribute::INSTANCE); - if (instanceLoc != -1) + __state->bindBuffer(BufferType::ARRAY_BUFFER, _instanceBuffer->getHandler()); + const auto instanceStride = vertexLayout->getInstanceStride(); + const auto& attributes = vertexLayout->getInstanceBindings(); + for (const auto& attributeInfo : attributes) { - __gl->bindBuffer(BufferType::ARRAY_BUFFER, _instanceTransformBuffer->getHandler()); - - for (auto i = 0; i < 4; ++i) + const auto& attribute = attributeInfo.second; + switch (attribute.format) { - auto elementLoc = instanceLoc + i; - __gl->enableVertexAttribArray(elementLoc); - glVertexAttribPointer(elementLoc, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 16, - (void*)(sizeof(float) * 4 * i)); - __gl->setVertexAttribDivisor(elementLoc); - usedBits |= (1 << elementLoc); + case VertexFormat::MAT4: + for (auto i = 0; i < 4; ++i) + { + auto elementLoc = attribute.index + i; + __state->enableVertexAttribArray(elementLoc); + glVertexAttribPointer(elementLoc, 4, GL_FLOAT, GL_FALSE, sizeof(float) * 16, + (void*)(sizeof(float) * 4 * i)); + __state->setVertexAttribDivisor(elementLoc); + usedBits |= (1 << elementLoc); + } + break; + default: + __state->enableVertexAttribArray(attribute.index); + glVertexAttribPointer(attribute.index, UtilsGL::getGLAttributeSize(attribute.format), + UtilsGL::toGLAttributeType(attribute.format), attribute.needToBeNormallized, + instanceStride, (GLvoid*)static_cast(attribute.offset)); + __state->setVertexAttribDivisor(attribute.index); + usedBits |= (1 << attribute.index); } } } } -void CommandBufferGL::bindUniforms(ProgramGL* program) const +void CommandBufferImpl::bindUniforms(ProgramImpl* program) const { if (_programState) { @@ -389,7 +402,7 @@ void CommandBufferGL::bindUniforms(ProgramGL* program) const for (auto&& cb : callbacks) cb.second(_programState, cb.first); - auto& uniformInfos = program->getAllActiveUniformInfo(ShaderStage::VERTEX); + auto& uniformInfos = program->getActiveUniformInfos(ShaderStage::VERTEX); std::size_t bufferSize = 0; auto buffer = _programState->getVertexUniformBuffer(bufferSize); @@ -414,7 +427,7 @@ void CommandBufferGL::bindUniforms(ProgramGL* program) const int i = 0; for (const auto& texture : textures) { - applyTexture(texture, slots[i], indexs[i]); + static_cast(texture)->apply(slots[i], indexs[i]); ++i; } @@ -427,22 +440,22 @@ void CommandBufferGL::bindUniforms(ProgramGL* program) const } } -void CommandBufferGL::cleanResources() +void CommandBufferImpl::cleanResources() { AX_SAFE_RELEASE_NULL(_programState); } -void CommandBufferGL::setScissorRect(bool isEnabled, float x, float y, float width, float height) +void CommandBufferImpl::setScissorRect(bool isEnabled, float x, float y, float width, float height) { if (isEnabled) - __gl->enableScissor(x, y, width, height); + __state->enableScissor(x, y, width, height); else - __gl->disableScissor(); + __state->disableScissor(); } -void CommandBufferGL::readPixels(RenderTarget* rt, std::function callback) +void CommandBufferImpl::readPixels(RenderTarget* rt, std::function callback) { - PixelBufferDescriptor pbd; + PixelBufferDesc pbd; if (rt->isDefaultRenderTarget()) { // read pixels from screen readPixels(rt, _viewPort.x, _viewPort.y, _viewPort.width, _viewPort.height, _viewPort.width * 4, false, pbd); @@ -460,16 +473,16 @@ void CommandBufferGL::readPixels(RenderTarget* rt, std::function(rt); + auto rtGL = static_cast(rt); rtGL->bindFrameBuffer(); glPixelStorei(GL_PACK_ALIGNMENT, 1); @@ -478,7 +491,7 @@ void CommandBufferGL::readPixels(RenderTarget* rt, #if AX_HAVE_MAP_BUFFER_RANGE GLuint pbo; glGenBuffers(1, &pbo); - __gl->bindBuffer(BufferType::PIXEL_PACK_BUFFER, pbo); + __state->bindBuffer(BufferType::PIXEL_PACK_BUFFER, pbo); glBufferData(GL_PIXEL_PACK_BUFFER, bufferSize, nullptr, GL_STATIC_DRAW); glReadPixels(x, y, width, height, GL_RGBA, GL_UNSIGNED_BYTE, nullptr); auto buffer_ptr = (uint8_t*)glMapBufferRange(GL_PIXEL_PACK_BUFFER, 0, bufferSize, GL_MAP_READ_BIT); @@ -522,7 +535,7 @@ void CommandBufferGL::readPixels(RenderTarget* rt, } #if AX_HAVE_MAP_BUFFER_RANGE glUnmapBuffer(GL_PIXEL_PACK_BUFFER); - __gl->bindBuffer(BufferType::PIXEL_PACK_BUFFER, 0); + __state->bindBuffer(BufferType::PIXEL_PACK_BUFFER, 0); glDeleteBuffers(1, &pbo); #endif @@ -530,4 +543,4 @@ void CommandBufferGL::readPixels(RenderTarget* rt, rtGL->unbindFrameBuffer(); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/CommandBufferGL.h b/axmol/rhi/opengl/CommandBufferGL.h similarity index 79% rename from core/renderer/backend/opengl/CommandBufferGL.h rename to axmol/rhi/opengl/CommandBufferGL.h index 6e4773727fb5..28c560f641f9 100644 --- a/core/renderer/backend/opengl/CommandBufferGL.h +++ b/axmol/rhi/opengl/CommandBufferGL.h @@ -25,21 +25,22 @@ #pragma once -#include "../Macros.h" -#include "../CommandBuffer.h" -#include "base/EventListenerCustom.h" -#include "platform/GL.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/CommandBuffer.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/platform/GL.h" -#include "StdC.h" +#include "axmol/platform/StdC.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl +{ -class BufferGL; -class RenderPipelineGL; -class ProgramGL; -class DepthStencilStateGL; +class BufferImpl; +class RenderPipelineImpl; +class ProgramImpl; +class DepthStencilStateImpl; /** * @addtogroup _opengl @@ -50,11 +51,11 @@ class DepthStencilStateGL; * @brief Store encoded commands for the GPU to execute. * A command buffer stores encoded commands until the buffer is committed for execution by the GPU */ -class CommandBufferGL : public CommandBuffer +class CommandBufferImpl : public CommandBuffer { public: - CommandBufferGL(); - ~CommandBufferGL(); + CommandBufferImpl(); + ~CommandBufferImpl(); /** * Set depthStencil status once * @param depthStencilState Specifies the depth and stencil status @@ -78,19 +79,19 @@ class CommandBufferGL : public CommandBuffer * Begin a render pass, initial color, depth and stencil attachment. * @param descriptor Specifies a group of render targets that hold the results of a render pass. */ - void beginRenderPass(const RenderTarget* rt, const RenderPassDescriptor& descriptor) override; + void beginRenderPass(const RenderTarget* rt, const RenderPassDesc& descriptor) override; /** * Update depthStencil status, improvment: for metal backend cache it * @param depthStencilState Specifies the depth and stencil status */ - void updateDepthStencilState(const DepthStencilDescriptor& descriptor) override; + void updateDepthStencilState(const DepthStencilDesc& descriptor) override; /** * Update render pipeline status * @param depthStencilState Specifies the depth and stencil status */ - void updatePipelineState(const RenderTarget* rt, const PipelineDescriptor& descriptor) override; + void updatePipelineState(const RenderTarget* rt, const PipelineDesc& descriptor) override; /** * Fixed-function state @@ -147,6 +148,12 @@ class CommandBufferGL : public CommandBuffer */ void drawArrays(PrimitiveType primitiveType, std::size_t start, std::size_t count, bool wireframe = false) override; + void drawArraysInstanced(PrimitiveType primitiveType, + std::size_t start, + std::size_t count, + int instanceCount, + bool wireframe = false) override; + /** * Draw primitives with an index list. * @param primitiveType The type of primitives that elements are assembled into. @@ -157,10 +164,10 @@ class CommandBufferGL : public CommandBuffer * @see `drawArrays(PrimitiveType primitiveType, unsigned int start, unsigned int count)` */ void drawElements(PrimitiveType primitiveType, - IndexFormat indexType, - std::size_t count, - std::size_t offset, - bool wireframe = false) override; + IndexFormat indexType, + std::size_t count, + std::size_t offset, + bool wireframe = false) override; /** * Draw primitives with an index list instanced. @@ -174,11 +181,11 @@ class CommandBufferGL : public CommandBuffer * @see `drawArrays(PrimitiveType primitiveType, unsigned int start, unsigned int count)` */ void drawElementsInstanced(PrimitiveType primitiveType, - IndexFormat indexType, - std::size_t count, - std::size_t offset, - int instanceCount, - bool wireframe = false) override; + IndexFormat indexType, + std::size_t count, + std::size_t offset, + int instanceCount, + bool wireframe = false) override; /** * Do some resources release. @@ -202,12 +209,11 @@ class CommandBufferGL : public CommandBuffer * Get a screen snapshot * @param callback A callback to deal with screen snapshot image. */ - void readPixels(RenderTarget* rt, std::function callback) override; - + void readPixels(RenderTarget* rt, std::function callback) override; /** - * For internal use only - */ + * For internal use only + */ void readPixels(RenderTarget* rt, int x, int y, @@ -215,25 +221,23 @@ class CommandBufferGL : public CommandBuffer uint32_t height, uint32_t bytesPerRow, bool eglCacheHint, - PixelBufferDescriptor& pbd); + PixelBufferDesc& pbd); protected: - void prepareDrawing() const; void bindVertexBuffer(uint32_t& usedBits) const; - virtual void bindInstanceBuffer(ProgramGL* program, uint32_t& usedBits) const; - void bindUniforms(ProgramGL* program) const; + void bindUniforms(ProgramImpl* program) const; void cleanResources(); - BufferGL* _vertexBuffer = nullptr; - ProgramState* _programState = nullptr; - BufferGL* _indexBuffer = nullptr; - BufferGL* _instanceTransformBuffer = nullptr; - RenderPipelineGL* _renderPipeline = nullptr; - CullMode _cullMode = CullMode::NONE; - DepthStencilStateGL* _depthStencilStateGL = nullptr; + BufferImpl* _vertexBuffer = nullptr; + ProgramState* _programState = nullptr; + BufferImpl* _indexBuffer = nullptr; + BufferImpl* _instanceBuffer = nullptr; + RenderPipelineImpl* _renderPipeline = nullptr; + CullMode _cullMode = CullMode::NONE; + DepthStencilStateImpl* _depthStencilStateImpl = nullptr; Viewport _viewPort; - GLboolean _alphaTestEnabled = false; + GLboolean _alphaTestEnabled = false; #if AX_ENABLE_CACHE_TEXTURE_DATA EventListenerCustom* _backToForegroundListener = nullptr; @@ -242,4 +246,4 @@ class CommandBufferGL : public CommandBuffer // end of _opengl group /// @} -NS_AX_BACKEND_END +} // namespace ax::rhi::gl diff --git a/axmol/rhi/opengl/DepthStencilStateGL.cpp b/axmol/rhi/opengl/DepthStencilStateGL.cpp new file mode 100644 index 000000000000..41c6a1489463 --- /dev/null +++ b/axmol/rhi/opengl/DepthStencilStateGL.cpp @@ -0,0 +1,94 @@ +/**************************************************************************** + Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. + + https://axmol.dev/ + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + ****************************************************************************/ + +#include "axmol/rhi/opengl/DepthStencilStateGL.h" +#include "axmol/platform/GL.h" + +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/opengl/OpenGLState.h" + +namespace ax::rhi::gl { + +void DepthStencilStateImpl::reset() +{ + __state->disableDepthTest(); + __state->disableStencilTest(); +} + +void DepthStencilStateImpl::apply(unsigned int stencilReferenceValue) const +{ + const auto dsFlags = _dsDesc.flags; + // depth test + if (bitmask::any(dsFlags, DepthStencilFlags::DEPTH_TEST)) + __state->enableDepthTest(); + else + __state->disableDepthTest(); + + __state->depthMask(bitmask::any(dsFlags, DepthStencilFlags::DEPTH_WRITE)); + __state->depthFunc(UtilsGL::toGLCompareFunc(_dsDesc.depthCompareFunc)); + + // stencil test + if (bitmask::any(dsFlags, DepthStencilFlags::STENCIL_TEST)) + { + __state->enableStencilTest(); + + if (_isBackFrontStencilEqual) + { + __state->stencilFunc(UtilsGL::toGLCompareFunc(_dsDesc.frontFaceStencil.stencilCompareFunc), + (GLint)stencilReferenceValue, _dsDesc.frontFaceStencil.readMask); + + __state->stencilOp(UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.stencilFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.depthFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.depthStencilPassOp)); + + __state->stencilMask(_dsDesc.frontFaceStencil.writeMask); + } + else + { + __state->stencilFuncFront(UtilsGL::toGLCompareFunc(_dsDesc.backFaceStencil.stencilCompareFunc), + (GLint)stencilReferenceValue, _dsDesc.backFaceStencil.readMask); + __state->stencilFuncBack(UtilsGL::toGLCompareFunc(_dsDesc.frontFaceStencil.stencilCompareFunc), + (GLint)stencilReferenceValue, _dsDesc.frontFaceStencil.readMask); + + __state->stencilOpFront( + UtilsGL::toGLStencilOp(_dsDesc.backFaceStencil.stencilFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.backFaceStencil.depthFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.backFaceStencil.depthStencilPassOp)); + __state->stencilOpBack( + UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.stencilFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.depthFailureOp), + UtilsGL::toGLStencilOp(_dsDesc.frontFaceStencil.depthStencilPassOp)); + + __state->stencilMaskBack(_dsDesc.backFaceStencil.writeMask); + __state->stencilMaskFront(_dsDesc.frontFaceStencil.writeMask); + } + } + else + __state->disableStencilTest(); + + CHECK_GL_ERROR_DEBUG(); +} + +} diff --git a/core/renderer/backend/opengl/DepthStencilStateGL.h b/axmol/rhi/opengl/DepthStencilStateGL.h similarity index 87% rename from core/renderer/backend/opengl/DepthStencilStateGL.h rename to axmol/rhi/opengl/DepthStencilStateGL.h index b895556bac07..3e452d4d6bec 100644 --- a/core/renderer/backend/opengl/DepthStencilStateGL.h +++ b/axmol/rhi/opengl/DepthStencilStateGL.h @@ -24,9 +24,9 @@ #pragma once -#include "../DepthStencilState.h" +#include "axmol/rhi/DepthStencilState.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { /** * @addtogroup _opengl * @{ @@ -35,7 +35,7 @@ NS_AX_BACKEND_BEGIN /** * Set depth and stencil status to pipeline. */ -class DepthStencilStateGL : public DepthStencilState +class DepthStencilStateImpl : public DepthStencilState { public: /// Reset to default state. @@ -44,15 +44,15 @@ class DepthStencilStateGL : public DepthStencilState /** * @param descriptor Specifies the depth and stencil status. */ - DepthStencilStateGL() = default; + DepthStencilStateImpl() = default; /** * Set depth and stencil status to pipeline. * @param stencilReferenceValueFront Specifies front stencil reference value. * @param stencilReferenceValueBack Specifies back stencil reference value. */ - void apply(unsigned int stencilReferenceValueFront, unsigned int stencilReferenceValueBack) const; + void apply(unsigned int stencilReferenceValue) const; }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/DriverGL.cpp b/axmol/rhi/opengl/DriverGL.cpp similarity index 68% rename from core/renderer/backend/opengl/DriverGL.cpp rename to axmol/rhi/opengl/DriverGL.cpp index 5d6ef3d46d0e..0f55200b63ca 100644 --- a/core/renderer/backend/opengl/DriverGL.cpp +++ b/axmol/rhi/opengl/DriverGL.cpp @@ -23,24 +23,19 @@ THE SOFTWARE. ****************************************************************************/ -#include "DriverGL.h" -#include "RenderPipelineGL.h" -#include "BufferGL.h" -#include "ShaderModuleGL.h" -#include "CommandBufferGL.h" -#include "TextureGL.h" -#include "DepthStencilStateGL.h" -#include "ProgramGL.h" -#include "DriverGL.h" -#include "RenderTargetGL.h" -#include "MacrosGL.h" -#include "renderer/backend/ProgramManager.h" -#if !defined(__APPLE__) && AX_TARGET_PLATFORM != AX_PLATFORM_WINRT -# include "CommandBufferGLES2.h" -#endif - -#include "base/axstd.h" -#include "base/format.h" +#include "axmol/rhi/opengl/DriverGL.h" +#include "axmol/rhi/opengl/RenderPipelineGL.h" +#include "axmol/rhi/opengl/BufferGL.h" +#include "axmol/rhi/opengl/ShaderModuleGL.h" +#include "axmol/rhi/opengl/CommandBufferGL.h" +#include "axmol/rhi/opengl/TextureGL.h" +#include "axmol/rhi/opengl/DepthStencilStateGL.h" +#include "axmol/rhi/opengl/ProgramGL.h" +#include "axmol/rhi/opengl/RenderTargetGL.h" +#include "axmol/rhi/opengl/MacrosGL.h" + +#include "axmol/base/axstd.h" +#include "axmol/base/format.h" #include "xxhash/xxhash.h" #if !defined(GL_COMPRESSED_RGBA8_ETC2_EAC) @@ -51,7 +46,24 @@ # define GL_COMPRESSED_RGBA_ASTC_4x4 0x93B0 #endif -NS_AX_BACKEND_BEGIN +namespace ax::rhi +{ +DriverBase* DriverBase::getInstance() +{ + if (!_instance) + _instance = new gl::DriverImpl(); + + return _instance; +} + +void DriverBase::destroyInstance() +{ + AX_SAFE_DELETE(_instance); +} +} // namespace ax::rhi + +namespace ax::rhi::gl +{ static inline uint32_t hashString(std::string_view str) { @@ -61,7 +73,6 @@ static inline uint32_t hashString(std::string_view str) template static void GL_EnumAllExtensions(_Fty&& func) { -#if AX_GLES_PROFILE != 200 // NOT GLES2.0 GLint NumberOfExtensions{0}; glGetIntegerv(GL_NUM_EXTENSIONS, &NumberOfExtensions); for (GLint i = 0; i < NumberOfExtensions; ++i) @@ -70,43 +81,15 @@ static void GL_EnumAllExtensions(_Fty&& func) if (extName) func(std::string_view{extName}); } -#else - auto extensions = (const char*)glGetString(GL_EXTENSIONS); - if (extensions) - { - axstd::split_of_cb(extensions, " \f\n\r\t\v", [&func](const char* start, const char* end, char /*delim*/) { - if (start != end) - func(std::string_view{start, static_cast(end - start)}); - }); - } -#endif } -DriverBase* DriverBase::getInstance() -{ - if (!_instance) - _instance = new DriverGL(); - - return _instance; -} - -void DriverBase::destroyInstance() -{ - AX_SAFE_DELETE(_instance); -} - -DriverGL::DriverGL() +DriverImpl::DriverImpl() { /// driver info - // These queries work with all GL/GLES versions! - _vendor = (char const*)glGetString(GL_VENDOR); - _renderer = (char const*)glGetString(GL_RENDERER); - _version = (char const*)glGetString(GL_VERSION); - _shaderVer = (char const*)glGetString(GL_SHADING_LANGUAGE_VERSION); - - if (_version) + auto pszVersion = (char const*)glGetString(GL_VERSION); + if (pszVersion) { - auto hint = strstr(_version, "OpenGL ES"); + auto hint = strstr(pszVersion, "OpenGL ES"); _verInfo.es = !!hint; if (_verInfo.es) { @@ -115,9 +98,11 @@ DriverGL::DriverGL() } else { - _verInfo.major = (_version[0] - '0'); - _verInfo.minor = (_version[2] - '0'); + _verInfo.major = (pszVersion[0] - '0'); + _verInfo.minor = (pszVersion[2] - '0'); } + + _version = pszVersion; } // check OpenGL version at first @@ -127,12 +112,11 @@ DriverGL::DriverGL() { #if AX_GLES_PROFILE == 0 auto msg = fmt::format( - "OpeGL 3.3+ is required (your version is {}). Please upgrade the driver of your video card.", - _version); + "OpeGL 3.3+ is required (your version is {}). Please upgrade the driver of your video card.", pszVersion); #else auto msg = fmt::format( "OpeGL ES {}.{}+ is required (your version is {}). Please upgrade the driver of your video card.", - REQUIRED_GLES_MAJOR, AX_GLES_PROFILE % AX_GLES_PROFILE, _version); + REQUIRED_GLES_MAJOR, AX_GLES_PROFILE % AX_GLES_PROFILE, pszVersion); #endif messageBox(msg.c_str(), "OpenGL version too old"); utils::killCurrentProcess(); // kill current process, don't cause crash when driver issue. @@ -170,90 +154,210 @@ DriverGL::DriverGL() glGetIntegerv(GL_FRAMEBUFFER_BINDING, &_defaultFBO); -#if AX_GLES_PROFILE != 200 - glGenVertexArrays(1, &_defaultVAO); - glBindVertexArray(_defaultVAO); + resetState(); + CHECK_GL_ERROR_DEBUG(); -#endif } -DriverGL::~DriverGL() -{ - ProgramManager::destroyInstance(); -} +DriverImpl::~DriverImpl() {} -GLint DriverGL::getDefaultFBO() const +GLint DriverImpl::getDefaultFBO() const { return _defaultFBO; } -CommandBuffer* DriverGL::newCommandBuffer() +CommandBuffer* DriverImpl::createCommandBuffer(void*) { -#if !defined(__APPLE__) && AX_TARGET_PLATFORM != AX_PLATFORM_WINRT - return !isGLES2Only() ? new CommandBufferGL() : new CommandBufferGLES2(); -#else - return new CommandBufferGL(); -#endif + return new CommandBufferImpl(); } -Buffer* DriverGL::newBuffer(std::size_t size, BufferType type, BufferUsage usage) +Buffer* DriverImpl::createBuffer(std::size_t size, BufferType type, BufferUsage usage) { - return new BufferGL(size, type, usage); + return new BufferImpl(size, type, usage); } -TextureBackend* DriverGL::newTexture(const TextureDescriptor& descriptor) +Texture* DriverImpl::createTexture(const TextureDesc& descriptor) { - switch (descriptor.textureType) - { - case TextureType::TEXTURE_2D: - return new Texture2DGL(descriptor); - case TextureType::TEXTURE_CUBE: - return new TextureCubeGL(descriptor); - default: - return nullptr; - } + return new TextureImpl(descriptor); } -RenderTarget* DriverGL::newDefaultRenderTarget() +RenderTarget* DriverImpl::createDefaultRenderTarget() { - auto rtGL = new RenderTargetGL(true, this); - return rtGL; + return new RenderTargetImpl(true, this); } -RenderTarget* DriverGL::newRenderTarget(TextureBackend* colorAttachment, - TextureBackend* depthAttachment, - TextureBackend* stencilAttachhment) +RenderTarget* DriverImpl::createRenderTarget(Texture* colorAttachment, Texture* depthStencilAttachment) { - auto rtGL = new RenderTargetGL(false, this); + auto rtGL = new RenderTargetImpl(false, this); rtGL->bindFrameBuffer(); RenderTarget::ColorAttachment colors{{colorAttachment, 0}}; rtGL->setColorAttachment(colors); - rtGL->setDepthAttachment(depthAttachment); - rtGL->setStencilAttachment(stencilAttachhment); + rtGL->setDepthStencilAttachment(depthStencilAttachment); return rtGL; } -ShaderModule* DriverGL::newShaderModule(ShaderStage stage, std::string_view source) +ShaderModule* DriverImpl::createShaderModule(ShaderStage stage, std::string_view source) +{ + return new ShaderModuleImpl(stage, source); +} + + +SamplerHandle DriverImpl::createSampler(const SamplerDesc& desc) { - return new ShaderModuleGL(stage, source); + GLuint sampler = 0; + glGenSamplers(1, &sampler); + + // --- Minification filter (min + mip) --- + GLenum minFilterGL{GL_LINEAR}; + if (desc.minFilter != SamplerFilter::MIN_NEAREST) + { + switch (desc.mipFilter) + { + case SamplerFilter::MIP_NEAREST: + minFilterGL = GL_LINEAR_MIPMAP_NEAREST; + break; + case SamplerFilter::MIP_LINEAR: + minFilterGL = GL_LINEAR_MIPMAP_LINEAR; + break; + } + } + else + { + switch (desc.mipFilter) + { + case SamplerFilter::MIP_NEAREST: + minFilterGL = GL_NEAREST_MIPMAP_NEAREST; + break; + case SamplerFilter::MIP_LINEAR: + minFilterGL = GL_NEAREST_MIPMAP_LINEAR; + break; + default: // MIP_NONE + minFilterGL = GL_NEAREST; + } + } + + // --- Magnification filter --- + GLenum magFilterGL = (desc.magFilter == SamplerFilter::MAG_LINEAR) ? GL_LINEAR : GL_NEAREST; + + glSamplerParameteri(sampler, GL_TEXTURE_MIN_FILTER, minFilterGL); + glSamplerParameteri(sampler, GL_TEXTURE_MAG_FILTER, magFilterGL); + + // --- Address modes --- + auto toGLWrap = [](SamplerAddressMode mode) -> GLint { + switch (mode) + { + case SamplerAddressMode::REPEAT: + return GL_REPEAT; + case SamplerAddressMode::MIRROR: + return GL_MIRRORED_REPEAT; + case SamplerAddressMode::CLAMP: + return GL_CLAMP_TO_EDGE; +#if defined(GL_CLAMP_TO_BORDER_EXT) + case SamplerAddressMode::BORDER: + return GL_CLAMP_TO_BORDER_EXT; +#endif + } + return GL_REPEAT; + }; + + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_S, toGLWrap(desc.sAddressMode)); + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_T, toGLWrap(desc.tAddressMode)); + glSamplerParameteri(sampler, GL_TEXTURE_WRAP_R, toGLWrap(desc.wAddressMode)); + +#if defined(GL_TEXTURE_BORDER_COLOR_EXT) + // --- Border color --- + if (desc.sAddressMode == SamplerAddressMode::BORDER || desc.tAddressMode == SamplerAddressMode::BORDER || + desc.wAddressMode == SamplerAddressMode::BORDER) + { + GLfloat borderColor[4] = {0.f, 0.f, 0.f, 0.f}; + glSamplerParameterfv(sampler, GL_TEXTURE_BORDER_COLOR_EXT, borderColor); + } +#endif + + // --- Comparison mode (shadow samplers) --- + if (desc.compareFunc != CompareFunc::NEVER) + { + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); + + GLenum funcGL = GL_LEQUAL; + switch (desc.compareFunc) + { + case CompareFunc::LESS: + funcGL = GL_LESS; + break; + case CompareFunc::EQUAL: + funcGL = GL_EQUAL; + break; + case CompareFunc::LESS_EQUAL: + funcGL = GL_LEQUAL; + break; + case CompareFunc::GREATER: + funcGL = GL_GREATER; + break; + case CompareFunc::NOT_EQUAL: + funcGL = GL_NOTEQUAL; + break; + case CompareFunc::GREATER_EQUAL: + funcGL = GL_GEQUAL; + break; + case CompareFunc::ALWAYS: + funcGL = GL_ALWAYS; + break; + default: + funcGL = GL_NEVER; + break; + } + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_FUNC, funcGL); + } + else + { + glSamplerParameteri(sampler, GL_TEXTURE_COMPARE_MODE, GL_NONE); + } + + // --- Anisotropy --- +#ifdef GL_TEXTURE_MAX_ANISOTROPY_EXT + if (desc.anisotropy > 1) + { + GLfloat aniso = static_cast(desc.anisotropy); + GLfloat maxAniso = 0.0f; + glGetFloatv(GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &maxAniso); + if (maxAniso > 0.0f) + { + if (aniso > maxAniso) + aniso = maxAniso; + glSamplerParameterf(sampler, GL_TEXTURE_MAX_ANISOTROPY_EXT, aniso); + } + } +#endif + + return reinterpret_cast(static_cast(sampler)); +} + +void DriverImpl::destroySampler(SamplerHandle& h) +{ + if (h) + { + GLuint sampler = reinterpret_cast(h); + __state->deleteSampler(sampler); + } } -DepthStencilState* DriverGL::newDepthStencilState() +DepthStencilState* DriverImpl::createDepthStencilState() { - return new DepthStencilStateGL(); + return new DepthStencilStateImpl(); } -RenderPipeline* DriverGL::newRenderPipeline() +RenderPipeline* DriverImpl::createRenderPipeline() { - return new RenderPipelineGL(); + return new RenderPipelineImpl(); } -Program* DriverGL::newProgram(std::string_view vertexShader, std::string_view fragmentShader) +Program* DriverImpl::createProgram(std::string_view vertexShader, std::string_view fragmentShader) { - return new ProgramGL(vertexShader, fragmentShader); + return new ProgramImpl(vertexShader, fragmentShader); } -void DriverGL::resetState() +void DriverImpl::resetState() { OpenGLState::reset(); } @@ -469,31 +573,31 @@ void main() return supported; } -bool DriverGL::isGLES2Only() const +bool DriverImpl::isGLES2Only() const { return _verInfo.es && _verInfo.major == 2; } -const char* DriverGL::getVendor() const +std::string DriverImpl::getVendor() const { - return _vendor; + return (char const*)glGetString(GL_VENDOR); } -const char* DriverGL::getRenderer() const +std::string DriverImpl::getRenderer() const { - return _renderer; + return (char const*)glGetString(GL_RENDERER); } -const char* DriverGL::getVersion() const +std::string DriverImpl::getVersion() const { return _version; } -const char* DriverGL::getShaderVersion() const +std::string DriverImpl::getShaderVersion() const { - return _shaderVer; + return (char const*)glGetString(GL_SHADING_LANGUAGE_VERSION); } -bool DriverGL::checkForFeatureSupported(FeatureType feature) +bool DriverImpl::checkForFeatureSupported(FeatureType feature) { bool featureSupported = false; switch (feature) @@ -555,13 +659,13 @@ bool DriverGL::checkForFeatureSupported(FeatureType feature) return featureSupported; } -bool DriverGL::hasExtension(std::string_view searchName) const +bool DriverImpl::hasExtension(std::string_view searchName) const { const auto key = hashString(searchName); return _glExtensions.find(key) != _glExtensions.end(); } -std::string DriverGL::dumpExtensions() const +std::string DriverImpl::dumpExtensions() const { std::string strExts; @@ -573,4 +677,4 @@ std::string DriverGL::dumpExtensions() const return strExts; } -NS_AX_BACKEND_END +} // namespace ax::rhi::gl diff --git a/core/renderer/backend/opengl/DriverGL.h b/axmol/rhi/opengl/DriverGL.h similarity index 72% rename from core/renderer/backend/opengl/DriverGL.h rename to axmol/rhi/opengl/DriverGL.h index 7a0d8b9bbba9..c55e36aa68b9 100644 --- a/core/renderer/backend/opengl/DriverGL.h +++ b/axmol/rhi/opengl/DriverGL.h @@ -24,12 +24,12 @@ ****************************************************************************/ #pragma once -#include "../DriverBase.h" -#include "platform/GL.h" -#include "OpenGLState.h" -#include "base/hlookup.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/platform/GL.h" +#include "axmol/rhi/opengl/OpenGLState.h" +#include "axmol/base/hlookup.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { /** * @addtogroup _opengl * @{ @@ -38,19 +38,19 @@ NS_AX_BACKEND_BEGIN /** * Use to create resoureces. */ -class DriverGL : public DriverBase +class DriverImpl : public DriverBase { public: - DriverGL(); - ~DriverGL(); + DriverImpl(); + ~DriverImpl(); GLint getDefaultFBO() const; /** - * New a CommandBuffer object, not auto released. + * Create a CommandBuffer object, not auto released. * @return A CommandBuffer object. */ - CommandBuffer* newCommandBuffer() override; + CommandBuffer* createCommandBuffer(void*) override; /** * New a Buffer object, not auto released. @@ -61,28 +61,27 @@ class DriverGL : public DriverBase * BufferUsage::STATIC, BufferUsage::DYNAMIC. * @return A Buffer object. */ - Buffer* newBuffer(std::size_t size, BufferType type, BufferUsage usage) override; + Buffer* createBuffer(std::size_t size, BufferType type, BufferUsage usage) override; /** - * New a TextureBackend object, not auto released. + * New a Texture object, not auto released. * @param descriptor Specifies texture description. - * @return A TextureBackend object. + * @return A Texture object. */ - TextureBackend* newTexture(const TextureDescriptor& descriptor) override; + Texture* createTexture(const TextureDesc& descriptor) override; - RenderTarget* newDefaultRenderTarget() override; - RenderTarget* newRenderTarget(TextureBackend* colorAttachment, - TextureBackend* depthAttachment, - TextureBackend* stencilAttachhment) override; + RenderTarget* createDefaultRenderTarget() override; + RenderTarget* createRenderTarget(Texture* colorAttachment, + Texture* depthStencilAttachment) override; - DepthStencilState* newDepthStencilState() override; + DepthStencilState* createDepthStencilState() override; /** * New a RenderPipeline object, not auto released. * @param descriptor Specifies render pipeline description. * @return A RenderPipeline object. */ - RenderPipeline* newRenderPipeline() override; + RenderPipeline* createRenderPipeline() override; /** * Design for metal. @@ -95,7 +94,7 @@ class DriverGL : public DriverBase * @param fragmentShader Specifes this is a fragment shader source. * @return A Program instance. */ - Program* newProgram(std::string_view vertexShader, std::string_view fragmentShader) override; + Program* createProgram(std::string_view vertexShader, std::string_view fragmentShader) override; void resetState() override; @@ -105,21 +104,21 @@ class DriverGL : public DriverBase * Get vendor device name. * @return Vendor device name. */ - const char* getVendor() const override; + std::string getVendor() const override; /** * Get the full name of the vendor device. * @return The full name of the vendor device. */ - const char* getRenderer() const override; + std::string getRenderer() const override; /** * Get version name. * @return Version name. */ - const char* getVersion() const override; + std::string getVersion() const override; - const char* getShaderVersion() const override; + std::string getShaderVersion() const override; /** * Check does device has extension. @@ -150,19 +149,16 @@ class DriverGL : public DriverBase * @param source Specifies shader source. * @return A ShaderModule object. */ - ShaderModule* newShaderModule(ShaderStage stage, std::string_view source) override; + ShaderModule* createShaderModule(ShaderStage stage, std::string_view source) override; + + SamplerHandle createSampler(const SamplerDesc& desc) override; + void destroySampler(SamplerHandle&) override; GLint _defaultFBO = 0; // The value gets from glGetIntegerv, so need to use GLint - GLuint _defaultVAO = 0; private: std::set _glExtensions; - const char* _vendor{nullptr}; - const char* _renderer{nullptr}; - const char* _version{nullptr}; - const char* _shaderVer{nullptr}; - struct VersionInfo { bool es{false}; // is GLES? @@ -170,9 +166,11 @@ class DriverGL : public DriverBase uint16_t minor{0}; // minor version } _verInfo; - bool _textureCompressionAstc = false; - bool _textureCompressionEtc2 = false; + const char* _version{nullptr}; + + bool _textureCompressionAstc{false}; + bool _textureCompressionEtc2{false}; }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/MacrosGL.h b/axmol/rhi/opengl/MacrosGL.h similarity index 95% rename from core/renderer/backend/opengl/MacrosGL.h rename to axmol/rhi/opengl/MacrosGL.h index d1919e362267..c77f561d6993 100644 --- a/core/renderer/backend/opengl/MacrosGL.h +++ b/axmol/rhi/opengl/MacrosGL.h @@ -24,7 +24,7 @@ #pragma once -#include "base/Macros.h" +#include "axmol/base/Macros.h" #if !defined(_AX_DEBUG) || _AX_DEBUG == 0 # define CHECK_GL_ERROR_DEBUG() @@ -65,7 +65,7 @@ do \ { \ gl_code; \ - __gl_error_code = glGetError(); \ - AX_ASSERT(__gl_error_code == GL_NO_ERROR, "Error"); \ + __state_error_code = glGetError(); \ + AX_ASSERT(__state_error_code == GL_NO_ERROR, "Error"); \ } while (0) #endif diff --git a/axmol/rhi/opengl/OpenGLState.cpp b/axmol/rhi/opengl/OpenGLState.cpp new file mode 100644 index 000000000000..874b83db3b24 --- /dev/null +++ b/axmol/rhi/opengl/OpenGLState.cpp @@ -0,0 +1,25 @@ +#include "axmol/rhi/opengl/OpenGLState.h" + +namespace ax::rhi::gl { + +namespace +{ +std::unique_ptr g_defaultOpenGLState; +} + +AX_DLL OpenGLState* __state{nullptr}; + +OpenGLState::OpenGLState() +{ + // NOT GLES2.0, need generate VAO clearly + glGenVertexArrays(1, &_defaultVAO); + glBindVertexArray(_defaultVAO); +} + +void OpenGLState::reset() +{ + g_defaultOpenGLState = std::make_unique(); + __state = g_defaultOpenGLState.get(); +} + +} diff --git a/core/renderer/backend/opengl/OpenGLState.h b/axmol/rhi/opengl/OpenGLState.h similarity index 85% rename from core/renderer/backend/opengl/OpenGLState.h rename to axmol/rhi/opengl/OpenGLState.h index f2b75b5b3f09..0e271982a2dd 100644 --- a/core/renderer/backend/opengl/OpenGLState.h +++ b/axmol/rhi/opengl/OpenGLState.h @@ -2,26 +2,26 @@ #include -#include "base/Types.h" -#include "platform/GL.h" -#include "UtilsGL.h" -#include "renderer/backend/Enums.h" +#include "axmol/base/Types.h" +#include "axmol/platform/GL.h" +#include "axmol/rhi/opengl/UtilsGL.h" #define AX_ENABLE_STATE_GUARD 1 // Inline opengl state set calls -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl +{ struct BlendEquationSeparateState { - BlendEquationSeparateState(GLenum rgb, GLenum alpha) : rgbBlendOperation(rgb), alphaBlendOperation(alpha) {} + BlendEquationSeparateState(GLenum rgb, GLenum alpha) : rgbBlendOp(rgb), alphaBlendOp(alpha) {} bool equals(GLenum rgb, GLenum alpha) const { - return this->rgbBlendOperation == rgb && this->alphaBlendOperation == alpha; + return this->rgbBlendOp == rgb && this->alphaBlendOp == alpha; } - GLenum rgbBlendOperation; - GLenum alphaBlendOperation; + GLenum rgbBlendOp; + GLenum alphaBlendOp; }; struct BlendFuncSeparateState @@ -63,14 +63,14 @@ struct ColorMaskState struct StencilFuncState { StencilFuncState(GLenum func, GLint ref, GLuint mask) - : stencilCompareFunction(func), stencilReferenceValueFront(ref), readMask(mask) + : stencilCompareFunc(func), stencilReferenceValueFront(ref), readMask(mask) {} inline bool equals(GLenum func, GLint ref, GLuint mask) const { - return this->stencilCompareFunction == func && this->stencilReferenceValueFront == ref && + return this->stencilCompareFunc == func && this->stencilReferenceValueFront == ref && this->readMask == mask; } - unsigned int stencilCompareFunction; + unsigned int stencilCompareFunc; int stencilReferenceValueFront; unsigned int readMask; }; @@ -78,26 +78,34 @@ struct StencilFuncState struct StencilOperationState { StencilOperationState(GLenum fail, GLenum zfail, GLenum zpass) - : stencilFailureOperation(fail), depthFailureOperation(zfail), depthStencilPassOperation(zpass) + : stencilFailureOp(fail), depthFailureOp(zfail), depthStencilPassOp(zpass) {} inline bool equals(GLenum fail, GLenum zfail, GLenum zpass) const { - return this->stencilFailureOperation == fail && this->depthFailureOperation == zfail && - this->depthStencilPassOperation == zpass; + return this->stencilFailureOp == fail && this->depthFailureOp == zfail && + this->depthStencilPassOp == zpass; } - unsigned int stencilFailureOperation; - unsigned int depthFailureOperation; - unsigned int depthStencilPassOperation; + unsigned int stencilFailureOp; + unsigned int depthFailureOp; + unsigned int depthStencilPassOp; }; -struct CommonBindState +struct TextureBindState { - CommonBindState(GLenum t, GLuint h) : target(t), handle(h) {} + TextureBindState(GLenum t, GLuint h) : target(t), handle(h) {} inline bool equals(GLenum t, GLuint h) const { return this->target == t && this->handle == h; } GLenum target; GLuint handle; }; +struct SamplerBindState +{ + SamplerBindState(GLuint s, GLuint h) : slot(s), handle(h) {} + inline bool equals(GLuint s, GLuint h) const { return this->slot == s && this->handle == h; } + GLuint slot; + GLuint handle; +}; + struct UniformBufferBaseBindState { UniformBufferBaseBindState(GLenum i, GLuint h) : index(i), handle(h) {} @@ -107,7 +115,7 @@ struct UniformBufferBaseBindState GLuint handle; }; -struct OpenGLState +struct AX_DLL OpenGLState { constexpr static GLenum BufferTargets[] = { GL_ARRAY_BUFFER, // VERTEX of VAO @@ -191,12 +199,10 @@ struct OpenGLState func(upvalue, args...); } - using CullMode = backend::CullMode; - using Winding = backend::Winding; - using UtilsGL = backend::UtilsGL; - static void reset(); + OpenGLState(); + void viewport(const Viewport& v) { try_callf(glViewport, _viewPort, v, v.x, v.y, v.width, v.height); } void winding(Winding v) { try_callf(glFrontFace, _winding, v, UtilsGL::toGLFrontFace(v)); } void enableDepthTest() { try_enable(GL_DEPTH_TEST, _depthTest); } @@ -260,12 +266,13 @@ struct OpenGLState void stencilMaskFront(GLuint v) { try_callu(glStencilMaskSeparate, GL_FRONT, _stencilMaskFront, v); } void stencilMaskBack(GLuint v) { try_callu(glStencilMaskSeparate, GL_BACK, _stencilMaskBack, v); } void activeTexture(GLenum v) { try_call(glActiveTexture, _activeTexture, v); } - void bindTexture(GLenum target, GLuint handle) { + void bindTexture(GLenum target, GLuint handle) + { auto activeLayer = _activeTexture.has_value() ? _activeTexture.value() - GL_TEXTURE0 : 0; - if(activeLayer < MAX_TEXTURE_UNITS) + if (activeLayer < MAX_TEXTURE_UNITS) try_callx(glBindTexture, _textureBindings[activeLayer], target, handle); } - void deleteTexture(GLenum target, GLuint handle) + void deleteTexture(GLuint handle) { glDeleteTextures(1, &handle); @@ -275,6 +282,22 @@ struct OpenGLState textureBinding.reset(); } } + void bindSampler(GLuint slot, GLuint handle) + { + auto activeLayer = _activeTexture.has_value() ? _activeTexture.value() - GL_TEXTURE0 : 0; + if (activeLayer == slot && slot < MAX_TEXTURE_UNITS) + try_callx(glBindSampler, _samplerBindings[slot], slot, handle); + } + void deleteSampler(GLuint handle) + { + glDeleteSamplers(1, &handle); + + for (auto& samplerBinding : _samplerBindings) + { + if (samplerBinding.has_value() && samplerBinding->handle == handle) + samplerBinding.reset(); + } + } GLenum bindBuffer(BufferType type, GLuint buffer) { auto target = BufferTargets[static_cast(type)]; @@ -368,12 +391,7 @@ struct OpenGLState const auto mask = 1 << index; if (!(_divisorBits & mask)) { -#if defined(__ANDROID__) && AX_GLES_PROFILE == 200 - if (glVertexAttribDivisor) - glVertexAttribDivisor(index, 1); -#else glVertexAttribDivisor(index, 1); -#endif _divisorBits |= mask; } } @@ -383,21 +401,18 @@ struct OpenGLState const auto mask = 1 << index; if (_divisorBits & mask) { -#if defined(__ANDROID__) && AX_GLES_PROFILE == 200 - if (glVertexAttribDivisor) - glVertexAttribDivisor(index, 0); -#else glVertexAttribDivisor(index, 0); -#endif _divisorBits &= ~mask; } } private: - uint32_t _attribBits{0}; // vertexAttribArray bitset - uint32_t _divisorBits{0}; // divisor bitset + GLuint _defaultVAO{0}; + uint32_t _attribBits{0}; // vertexAttribArray bitset + uint32_t _divisorBits{0}; // divisor bitset std::optional _bufferBindings[(int)BufferType::COUNT]; - std::optional _textureBindings[MAX_TEXTURE_UNITS]; + std::optional _textureBindings[MAX_TEXTURE_UNITS]; + std::optional _samplerBindings[MAX_TEXTURE_UNITS]; std::optional _viewPort; std::optional _winding; @@ -429,6 +444,6 @@ struct OpenGLState std::optional _uniformBufferState; }; -AX_DLL extern OpenGLState* __gl; +AX_DLL extern OpenGLState* __state; -NS_AX_BACKEND_END +} // namespace ax::rhi::gl diff --git a/core/renderer/backend/opengl/ProgramGL.cpp b/axmol/rhi/opengl/ProgramGL.cpp similarity index 59% rename from core/renderer/backend/opengl/ProgramGL.cpp rename to axmol/rhi/opengl/ProgramGL.cpp index f8ac8140a90a..8691c18703cb 100644 --- a/core/renderer/backend/opengl/ProgramGL.cpp +++ b/axmol/rhi/opengl/ProgramGL.cpp @@ -23,111 +23,64 @@ THE SOFTWARE. ****************************************************************************/ -#include "ProgramGL.h" -#include "ShaderModuleGL.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/opengl/MacrosGL.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "base/axstd.h" +#include "axmol/rhi/opengl/ProgramGL.h" +#include "axmol/rhi/opengl/ShaderModuleGL.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/base/axstd.h" #include "yasio/byte_buffer.hpp" -#include "renderer/backend/opengl/UtilsGL.h" -#include "OpenGLState.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/opengl/OpenGLState.h" -NS_AX_BACKEND_BEGIN - -#if AX_GLES_PROFILE == 200 -# define DEF_TO_INT(pointer, index) (*((GLint*)(pointer) + index)) -# define DEF_TO_FLOAT(pointer, index) (*((GLfloat*)(pointer) + index)) -static void setUniform(bool isArray, GLuint location, unsigned int size, GLenum uniformType, void* data) +namespace ax::rhi::gl +{ +inline static std::string_view mapLocationEnumToUBO(rhi::Uniform name) { - GLsizei count = size; - switch (uniformType) + switch (name) { - case GL_INT: - case GL_BOOL: - case GL_SAMPLER_2D: - case GL_SAMPLER_CUBE: - if (isArray) - glUniform1iv(location, count, (GLint*)data); - else - glUniform1i(location, DEF_TO_INT(data, 0)); - break; - case GL_INT_VEC2: - case GL_BOOL_VEC2: - if (isArray) - glUniform2iv(location, count, (GLint*)data); - else - glUniform2i(location, DEF_TO_INT(data, 0), DEF_TO_INT(data, 1)); - break; - case GL_INT_VEC3: - case GL_BOOL_VEC3: - if (isArray) - glUniform3iv(location, count, (GLint*)data); - else - glUniform3i(location, DEF_TO_INT(data, 0), DEF_TO_INT(data, 1), DEF_TO_INT(data, 2)); - break; - case GL_INT_VEC4: - case GL_BOOL_VEC4: - if (isArray) - glUniform4iv(location, count, (GLint*)data); - else - glUniform4i(location, DEF_TO_INT(data, 0), DEF_TO_INT(data, 1), DEF_TO_INT(data, 2), DEF_TO_INT(data, 4)); - break; - case GL_FLOAT: - if (isArray) - glUniform1fv(location, count, (GLfloat*)data); - else - glUniform1f(location, DEF_TO_FLOAT(data, 0)); - break; - case GL_FLOAT_VEC2: - if (isArray) - glUniform2fv(location, count, (GLfloat*)data); - else - glUniform2f(location, DEF_TO_FLOAT(data, 0), DEF_TO_FLOAT(data, 1)); + case Uniform::MVP_MATRIX: + return UNIFORM_NAME_MVP_MATRIX; break; - case GL_FLOAT_VEC3: - if (isArray) - glUniform3fv(location, count, (GLfloat*)data); - else - glUniform3f(location, DEF_TO_FLOAT(data, 0), DEF_TO_FLOAT(data, 1), DEF_TO_FLOAT(data, 2)); + case Uniform::TEXTURE: + return UNIFORM_NAME_TEXTURE; break; - case GL_FLOAT_VEC4: - if (isArray) - glUniform4fv(location, count, (GLfloat*)data); - else - glUniform4f(location, DEF_TO_FLOAT(data, 0), DEF_TO_FLOAT(data, 1), DEF_TO_FLOAT(data, 2), - DEF_TO_FLOAT(data, 3)); + case Uniform::TEXTURE1: + return UNIFORM_NAME_TEXTURE1; break; - case GL_FLOAT_MAT2: - glUniformMatrix2fv(location, count, GL_FALSE, (GLfloat*)data); + case Uniform::TEXTURE2: + return UNIFORM_NAME_TEXTURE2; break; - case GL_FLOAT_MAT3: - glUniformMatrix3fv(location, count, GL_FALSE, (GLfloat*)data); + case Uniform::TEXTURE3: + return UNIFORM_NAME_TEXTURE3; break; - case GL_FLOAT_MAT4: - glUniformMatrix4fv(location, count, GL_FALSE, (GLfloat*)data); + case Uniform::TEXT_COLOR: + return UNIFORM_NAME_TEXT_COLOR; break; + case Uniform::EFFECT_COLOR: + return UNIFORM_NAME_EFFECT_COLOR; break; - - default: - AXASSERT(false, "invalidate Uniform data type"); + case Uniform::EFFECT_TYPE: + return UNIFORM_NAME_EFFECT_TYPE; break; + default:; } + return ""sv; } -#endif -ProgramGL::ProgramGL(std::string_view vertexShader, std::string_view fragmentShader) +ProgramImpl::ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader) : Program(vertexShader, fragmentShader) { - _vertexShaderModule = static_cast(ShaderCache::getInstance()->newVertexShaderModule(_vertexShader)); - _fragmentShaderModule = static_cast(ShaderCache::getInstance()->newFragmentShaderModule(_fragmentShader)); + _vertexShaderModule = + static_cast(ShaderCache::getInstance()->acquireVertexShaderModule(_vsSource)); + _fragmentShaderModule = + static_cast(ShaderCache::getInstance()->acquireFragmentShaderModule(_fsSource)); - AX_SAFE_RETAIN(_vertexShaderModule); - AX_SAFE_RETAIN(_fragmentShaderModule); compileProgram(); - computeUniformInfos(); + + reflectVertexInputs(); + reflectUniformInfos(); #if AX_ENABLE_CACHE_TEXTURE_DATA for (const auto& uniform : _activeUniformInfos) { @@ -145,7 +98,7 @@ ProgramGL::ProgramGL(std::string_view vertexShader, std::string_view fragmentSha setBuiltinLocations(); } -ProgramGL::~ProgramGL() +ProgramImpl::~ProgramImpl() { clearUniformBuffers(); @@ -160,15 +113,15 @@ ProgramGL::~ProgramGL() } #if AX_ENABLE_CACHE_TEXTURE_DATA -void ProgramGL::reloadProgram() +void ProgramImpl::reloadProgram() { _activeUniformInfos.clear(); _mapToCurrentActiveLocation.clear(); _mapToOriginalLocation.clear(); - static_cast(_vertexShaderModule)->compileShader(backend::ShaderStage::VERTEX, _vertexShader); - static_cast(_fragmentShaderModule)->compileShader(backend::ShaderStage::FRAGMENT, _fragmentShader); + static_cast(_vertexShaderModule)->compileShader(rhi::ShaderStage::VERTEX, _vsSource); + static_cast(_fragmentShaderModule)->compileShader(rhi::ShaderStage::FRAGMENT, _fsSource); compileProgram(); - computeUniformInfos(); + reflectUniformInfos(); for (const auto& uniform : _activeUniformInfos) { @@ -179,7 +132,7 @@ void ProgramGL::reloadProgram() } #endif -void ProgramGL::compileProgram() +void ProgramImpl::compileProgram() { if (_vertexShaderModule == nullptr || _fragmentShaderModule == nullptr) return; @@ -219,26 +172,26 @@ void ProgramGL::compileProgram() } } -void ProgramGL::setBuiltinLocations() +void ProgramImpl::setBuiltinLocations() { /*--- Builtin Attribs ---*/ - std::fill(_builtinAttributeLocation, _builtinAttributeLocation + Attribute::ATTRIBUTE_MAX, -1); + std::fill(_builtinVertxInputs, _builtinVertxInputs + VertexInputKind::VIK_COUNT, nullptr); /// a_position - _builtinAttributeLocation[Attribute::POSITION] = getAttributeLocation(ATTRIBUTE_NAME_POSITION); + _builtinVertxInputs[VertexInputKind::POSITION] = getVertexInputDesc(VERTEX_INPUT_NAME_POSITION); /// a_color - _builtinAttributeLocation[Attribute::COLOR] = getAttributeLocation(ATTRIBUTE_NAME_COLOR); + _builtinVertxInputs[VertexInputKind::COLOR] = getVertexInputDesc(VERTEX_INPUT_NAME_COLOR); /// a_texCoord - _builtinAttributeLocation[Attribute::TEXCOORD] = getAttributeLocation(ATTRIBUTE_NAME_TEXCOORD); + _builtinVertxInputs[VertexInputKind::TEXCOORD] = getVertexInputDesc(VERTEX_INPUT_NAME_TEXCOORD); // a_normal - _builtinAttributeLocation[Attribute::NORMAL] = getAttributeLocation(ATTRIBUTE_NAME_NORMAL); + _builtinVertxInputs[VertexInputKind::NORMAL] = getVertexInputDesc(VERTEX_INPUT_NAME_NORMAL); // a_instance - _builtinAttributeLocation[Attribute::INSTANCE] = getAttributeLocation(ATTRIBUTE_NAME_INSTANCE); + _builtinVertxInputs[VertexInputKind::INSTANCE] = getVertexInputDesc(VERTEX_INPUT_NAME_INSTANCE); /*--- Builtin Uniforms ---*/ @@ -261,43 +214,43 @@ void ProgramGL::setBuiltinLocations() _builtinUniformLocation[Uniform::EFFECT_TYPE] = getUniformLocation(UNIFORM_NAME_EFFECT_TYPE); } -const hlookup::string_map& ProgramGL::getActiveAttributes() const +void ProgramImpl::reflectVertexInputs() { - if (!_program || !_activeAttribs.empty()) - return _activeAttribs; + if (!_program) + return; - GLint numOfActiveAttributes = 0; - glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTES, &numOfActiveAttributes); + GLint numOfActiveInputs = 0; + glGetProgramiv(_program, GL_ACTIVE_ATTRIBUTES, &numOfActiveInputs); - if (numOfActiveAttributes <= 0) - return _activeAttribs; + if (numOfActiveInputs <= 0) + return; - _activeAttribs.reserve(numOfActiveAttributes); + _activeVertexInputs.reserve(numOfActiveInputs); - int MAX_ATTRIBUTE_NAME_LENGTH = 255; - auto attrName = axstd::make_unique_for_overwrite(MAX_ATTRIBUTE_NAME_LENGTH + 1); + constexpr int MAX_VERTEX_INPUT_NAME_LENGTH = 255; + auto attrName = axstd::make_unique_for_overwrite(MAX_VERTEX_INPUT_NAME_LENGTH + 1); GLint attrNameLen = 0; GLenum attrType; GLint attrSize; - backend::AttributeBindInfo info; - for (int i = 0; i < numOfActiveAttributes; i++) + for (int i = 0; i < numOfActiveInputs; i++) { - glGetActiveAttrib(_program, i, MAX_ATTRIBUTE_NAME_LENGTH, &attrNameLen, &attrSize, &attrType, attrName.get()); + glGetActiveAttrib(_program, i, MAX_VERTEX_INPUT_NAME_LENGTH, &attrNameLen, &attrSize, &attrType, + attrName.get()); CHECK_GL_ERROR_DEBUG(); std::string_view name{attrName.get(), static_cast(attrNameLen)}; + + rhi::VertexInputDesc info; info.location = glGetAttribLocation(_program, name.data()); - info.type = attrType; - info.size = UtilsGL::getGLDataTypeSize(attrType) * attrSize; + info.format = attrType; + info.count = UtilsGL::getGLDataTypeSize(attrType) * attrSize; CHECK_GL_ERROR_DEBUG(); - _activeAttribs[name] = info; + _activeVertexInputs.emplace(name, std::move(info)); } - - return _activeAttribs; } -void ProgramGL::computeUniformInfos() +void ProgramImpl::reflectUniformInfos() { if (!_program) return; @@ -314,7 +267,6 @@ void ProgramGL::computeUniformInfos() /* Query uniform blocks */ clearUniformBuffers(); -#if AX_GLES_PROFILE != 200 GLint numblocks{0}; glGetProgramiv(_program, GL_ACTIVE_UNIFORM_BLOCKS, &numblocks); @@ -336,7 +288,7 @@ void ProgramGL::computeUniformInfos() // create uniform buffer object auto& desc = _uniformBuffers.emplace_back( - static_cast(driver->newBuffer(blockSize, BufferType::UNIFORM, BufferUsage::DYNAMIC)), + static_cast(driver->createBuffer(blockSize, BufferType::UNIFORM, BufferUsage::DYNAMIC)), static_cast(_totalBufferSize), blockSize); desc._ubo->updateData(nullptr, blockSize); // ubo data can be nullptr @@ -345,7 +297,6 @@ void ProgramGL::computeUniformInfos() // increase _totalBufferSize _totalBufferSize += blockSize; } -#endif /* * construct _activeUniformInfos: uniformName-->UniformInfo @@ -376,7 +327,6 @@ void ProgramGL::computeUniformInfos() if (dot != std::string::npos) uniformName.remove_prefix(dot + 1); // trim uniformName -#if AX_GLES_PROFILE != 200 GLint blockIndex{-1}; glGetActiveUniformsiv(_program, 1, reinterpret_cast(&i), GL_UNIFORM_BLOCK_INDEX, &blockIndex); if (blockIndex != -1) @@ -393,19 +343,6 @@ void ProgramGL::computeUniformInfos() uniform.location = glGetUniformLocation(_program, uniformName.data()); uniform.bufferOffset = -1; } -#else - if (uniform.type == GL_SAMPLER_2D || uniform.type == GL_SAMPLER_CUBE) - { - uniform.location = glGetUniformLocation(_program, uniformName.data()); - uniform.bufferOffset = -1; - } - else - { // GLES2.0: GLSL100 - uniform.location = glGetUniformLocation(_program, uniformFullName.data()); - uniform.bufferOffset = (uniform.size == 0) ? 0 : _totalBufferSize; - _totalBufferSize += uniform.size * uniform.count; - } -#endif _activeUniformInfos[uniformName] = uniform; @@ -413,32 +350,19 @@ void ProgramGL::computeUniformInfos() } } -void ProgramGL::bindUniformBuffers(const char* buffer, size_t bufferSize) +void ProgramImpl::bindUniformBuffers(const char* buffer, size_t bufferSize) { -#if AX_GLES_PROFILE != 200 for (GLuint blockIdx = 0; blockIdx < static_cast(_uniformBuffers.size()); ++blockIdx) { auto& desc = _uniformBuffers[blockIdx]; desc._ubo->updateData(buffer + desc._location, desc._size); - __gl->bindUniformBufferBase(blockIdx, desc._ubo->getHandler()); + __state->bindUniformBufferBase(blockIdx, desc._ubo->getHandler()); } -#else - for (auto&& iter : _activeUniformInfos) - { - auto& uniformInfo = iter.second; - if (uniformInfo.size <= 0) - continue; - - int elementCount = uniformInfo.count; - setUniform(uniformInfo.count > 1, uniformInfo.location, elementCount, uniformInfo.type, - (void*)(buffer + uniformInfo.bufferOffset)); - } -#endif CHECK_GL_ERROR_DEBUG(); } -void ProgramGL::clearUniformBuffers() +void ProgramImpl::clearUniformBuffers() { if (_uniformBuffers.empty()) return; @@ -447,54 +371,24 @@ void ProgramGL::clearUniformBuffers() _uniformBuffers.clear(); } -int ProgramGL::getAttributeLocation(Attribute name) const -{ - return _builtinAttributeLocation[name]; -} - -int ProgramGL::getAttributeLocation(std::string_view name) const +const VertexInputDesc* ProgramImpl::getVertexInputDesc(VertexInputKind name) const { - return glGetAttribLocation(_program, name.data()); + return _builtinVertxInputs[name]; } -inline std::string_view mapLocationEnumToUBO(backend::Uniform name) +const VertexInputDesc* ProgramImpl::getVertexInputDesc(std::string_view name) const { - switch (name) - { - case Uniform::MVP_MATRIX: - return UNIFORM_NAME_MVP_MATRIX; - break; - case Uniform::TEXTURE: - return UNIFORM_NAME_TEXTURE; - break; - case Uniform::TEXTURE1: - return UNIFORM_NAME_TEXTURE1; - break; - case Uniform::TEXTURE2: - return UNIFORM_NAME_TEXTURE2; - break; - case Uniform::TEXTURE3: - return UNIFORM_NAME_TEXTURE3; - break; - case Uniform::TEXT_COLOR: - return UNIFORM_NAME_TEXT_COLOR; - break; - case Uniform::EFFECT_COLOR: - return UNIFORM_NAME_EFFECT_COLOR; - break; - case Uniform::EFFECT_TYPE: - return UNIFORM_NAME_EFFECT_TYPE; - break; - } - return ""sv; + // return glGetAttribLocation(_program, name.data()); + auto it = _activeVertexInputs.find(name); + return it != _activeVertexInputs.end() ? &it->second : nullptr; } -UniformLocation ProgramGL::getUniformLocation(backend::Uniform name) const +UniformLocation ProgramImpl::getUniformLocation(rhi::Uniform name) const { return _builtinUniformLocation[name]; } -UniformLocation ProgramGL::getUniformLocation(std::string_view uniform) const +UniformLocation ProgramImpl::getUniformLocation(std::string_view uniform) const { UniformLocation uniformLocation; auto iter = _activeUniformInfos.find(uniform); @@ -512,17 +406,17 @@ UniformLocation ProgramGL::getUniformLocation(std::string_view uniform) const return uniformLocation; } -int ProgramGL::getMaxVertexLocation() const +int ProgramImpl::getMaxVertexLocation() const { return _maxLocation; } -int ProgramGL::getMaxFragmentLocation() const +int ProgramImpl::getMaxFragmentLocation() const { return _maxLocation; } #if AX_ENABLE_CACHE_TEXTURE_DATA -int ProgramGL::getMappedLocation(int location) const +int ProgramImpl::getMappedLocation(int location) const { if (_mapToCurrentActiveLocation.find(location) != _mapToCurrentActiveLocation.end()) return _mapToCurrentActiveLocation.at(location); @@ -530,7 +424,7 @@ int ProgramGL::getMappedLocation(int location) const return -1; } -int ProgramGL::getOriginalLocation(int location) const +int ProgramImpl::getOriginalLocation(int location) const { if (_mapToOriginalLocation.find(location) != _mapToOriginalLocation.end()) return _mapToOriginalLocation.at(location); @@ -539,14 +433,19 @@ int ProgramGL::getOriginalLocation(int location) const } #endif -const hlookup::string_map& ProgramGL::getAllActiveUniformInfo(ShaderStage stage) const +const hlookup::string_map& ProgramImpl::getActiveVertexInputs() const +{ + return _activeVertexInputs; +} + +const hlookup::string_map& ProgramImpl::getActiveUniformInfos(ShaderStage stage) const { return _activeUniformInfos; } -std::size_t ProgramGL::getUniformBufferSize(ShaderStage stage) const +std::size_t ProgramImpl::getUniformBufferSize(ShaderStage stage) const { return _totalBufferSize; } -NS_AX_BACKEND_END +} // namespace ax::rhi::gl diff --git a/core/renderer/backend/opengl/ProgramGL.h b/axmol/rhi/opengl/ProgramGL.h similarity index 71% rename from core/renderer/backend/opengl/ProgramGL.h rename to axmol/rhi/opengl/ProgramGL.h index 78e11298e762..91902c33e3b1 100644 --- a/core/renderer/backend/opengl/ProgramGL.h +++ b/axmol/rhi/opengl/ProgramGL.h @@ -25,24 +25,23 @@ #pragma once -#include "../Macros.h" -#include "../Types.h" -#include "base/Object.h" -#include "base/EventListenerCustom.h" -#include "platform/GL.h" -#include "../Program.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/opengl/BufferGL.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/base/Object.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/platform/GL.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/opengl/BufferGL.h" #include #include #include -#include "base/axstd.h" +#include "axmol/base/axstd.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -class ShaderModuleGL; +class ShaderModuleImpl; /** * Store attribute information. @@ -65,10 +64,10 @@ struct AttributeInfo #define MAX_UNIFORM_NAME_LENGTH 256 -struct UniformBlockDescriptor +struct UniformBlockDesc { - UniformBlockDescriptor(BufferGL* ubo, int loc, int size) : _ubo(ubo), _location(loc), _size(size) {} - BufferGL* _ubo; + UniformBlockDesc(BufferImpl* ubo, int loc, int size) : _ubo(ubo), _location(loc), _size(size) {} + BufferImpl* _ubo; int _location; int _size; #if !AX_64BITS @@ -79,16 +78,16 @@ struct UniformBlockDescriptor /** * An OpenGL program. */ -class ProgramGL : public Program +class ProgramImpl : public Program { public: /** * @param vertexShader Specifes the vertex shader source. * @param fragmentShader Specifes the fragment shader source. */ - ProgramGL(std::string_view vertexShader, std::string_view fragmentShader); + ProgramImpl(std::string_view vertexShader, std::string_view fragmentShader); - ~ProgramGL(); + ~ProgramImpl(); /** * Get attribute informations. @@ -107,88 +106,93 @@ class ProgramGL : public Program * @param uniform Specifies the uniform name. * @return The uniform location. */ - virtual UniformLocation getUniformLocation(std::string_view uniform) const override; + UniformLocation getUniformLocation(std::string_view uniform) const override; /** * Get uniform location by engine built-in uniform enum name. * @param name Specifies the engine built-in uniform enum name. * @return The uniform location. */ - virtual UniformLocation getUniformLocation(backend::Uniform name) const override; + UniformLocation getUniformLocation(rhi::Uniform name) const override; /** * Get attribute location by attribute name. * @param name Specifies the attribute name. * @return The attribute location. */ - virtual int getAttributeLocation(std::string_view name) const override; + const VertexInputDesc* getVertexInputDesc (std::string_view name) const override; /** * Get attribute location by engine built-in attribute enum name. * @param name Specifies the engine built-in attribute enum name. * @return The attribute location. */ - virtual int getAttributeLocation(Attribute name) const override; + const VertexInputDesc* getVertexInputDesc(VertexInputKind name) const override; /** * Get maximum vertex location. * @return Maximum vertex locaiton. */ - virtual int getMaxVertexLocation() const override; + int getMaxVertexLocation() const override; /** * Get maximum fragment location. * @return Maximum fragment location. */ - virtual int getMaxFragmentLocation() const override; + int getMaxFragmentLocation() const override; /** * Get active vertex attributes. * @return Active vertex attributes. key is active attribute name, Value is corresponding attribute info. */ - virtual const hlookup::string_map& getActiveAttributes() const override; + const hlookup::string_map& getActiveVertexInputs() const override; /** * Get uniform buffer size in bytes that can hold all the uniforms. * @param stage Specifies the shader stage. The symbolic constant can be either VERTEX or FRAGMENT. * @return The uniform buffer size in bytes. */ - virtual std::size_t getUniformBufferSize(ShaderStage stage) const override; + std::size_t getUniformBufferSize(ShaderStage stage) const override; /** * Get all uniformInfos. * @return The uniformInfos. */ - virtual const hlookup::string_map& getAllActiveUniformInfo(ShaderStage stage) const override; + const hlookup::string_map& getActiveUniformInfos(ShaderStage stage) const override; void bindUniformBuffers(const char* buffer, size_t bufferSize); private: void compileProgram(); - void computeUniformInfos(); + + void reflectVertexInputs(); + void reflectUniformInfos(); + void setBuiltinLocations(); void clearUniformBuffers(); #if AX_ENABLE_CACHE_TEXTURE_DATA virtual void reloadProgram(); - virtual int getMappedLocation(int location) const override; - virtual int getOriginalLocation(int location) const override; - virtual const std::unordered_map getAllUniformsLocation() const override + int getMappedLocation(int location) const override; + int getOriginalLocation(int location) const override; + const std::unordered_map getAllUniformsLocation() const override { return _originalUniformLocations; } #endif GLuint _program = 0; - ShaderModuleGL* _vertexShaderModule = nullptr; - ShaderModuleGL* _fragmentShaderModule = nullptr; + ShaderModuleImpl* _vertexShaderModule = nullptr; + ShaderModuleImpl* _fragmentShaderModule = nullptr; - axstd::pod_vector _uniformBuffers; + axstd::pod_vector _uniformBuffers; std::vector _attributeInfos; + + hlookup::string_map _activeVertexInputs; hlookup::string_map _activeUniformInfos; - mutable hlookup::string_map _activeAttribs; + #if AX_ENABLE_CACHE_TEXTURE_DATA std::unordered_map _originalUniformLocations; ///< record the uniform location when shader was first created. @@ -200,9 +204,10 @@ class ProgramGL : public Program std::size_t _totalBufferSize = 0; // total uniform buffer size (all blocks) int _maxLocation = -1; - UniformLocation _builtinUniformLocation[UNIFORM_MAX]; - int _builtinAttributeLocation[Attribute::ATTRIBUTE_MAX]; + + const VertexInputDesc* _builtinVertxInputs[VertexInputKind::VIK_COUNT]; + UniformLocation _builtinUniformLocation[UNIFORM_COUNT]; }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/RenderPipelineGL.cpp b/axmol/rhi/opengl/RenderPipelineGL.cpp similarity index 64% rename from core/renderer/backend/opengl/RenderPipelineGL.cpp rename to axmol/rhi/opengl/RenderPipelineGL.cpp index 5e02b8157faa..05e19ccccbfa 100644 --- a/core/renderer/backend/opengl/RenderPipelineGL.cpp +++ b/axmol/rhi/opengl/RenderPipelineGL.cpp @@ -23,35 +23,35 @@ Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). THE SOFTWARE. ****************************************************************************/ -#include "RenderPipelineGL.h" -#include "ShaderModuleGL.h" -#include "DepthStencilStateGL.h" -#include "ProgramGL.h" -#include "UtilsGL.h" -#include "MacrosGL.h" -#include "OpenGLState.h" +#include "axmol/rhi/opengl/RenderPipelineGL.h" +#include "axmol/rhi/opengl/ShaderModuleGL.h" +#include "axmol/rhi/opengl/DepthStencilStateGL.h" +#include "axmol/rhi/opengl/ProgramGL.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/OpenGLState.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -void RenderPipelineGL::update(const RenderTarget*, const PipelineDescriptor& pipelineDescriptor) +void RenderPipelineImpl::update(const RenderTarget*, const PipelineDesc& pipelineDesc) { - if (_programGL != pipelineDescriptor.programState->getProgram()) + if (_programImpl != pipelineDesc.programState->getProgram()) { - AX_SAFE_RELEASE(_programGL); - _programGL = static_cast(pipelineDescriptor.programState->getProgram()); - AX_SAFE_RETAIN(_programGL); + AX_SAFE_RELEASE(_programImpl); + _programImpl = static_cast(pipelineDesc.programState->getProgram()); + AX_SAFE_RETAIN(_programImpl); } - updateBlendState(pipelineDescriptor.blendDescriptor); + updateBlendState(pipelineDesc.blendDesc); } -void RenderPipelineGL::updateBlendState(const BlendDescriptor& descriptor) +void RenderPipelineImpl::updateBlendState(const BlendDesc& descriptor) { auto blendEnabled = descriptor.blendEnabled; - auto rgbBlendOperation = UtilsGL::toGLBlendOperation(descriptor.rgbBlendOperation); - auto alphaBlendOperation = UtilsGL::toGLBlendOperation(descriptor.alphaBlendOperation); + auto rgbBlendOp = UtilsGL::toGLBlendOp(descriptor.rgbBlendOp); + auto alphaBlendOp = UtilsGL::toGLBlendOp(descriptor.alphaBlendOp); auto sourceRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceRGBBlendFactor); auto destinationRGBBlendFactor = UtilsGL::toGLBlendFactor(descriptor.destinationRGBBlendFactor); auto sourceAlphaBlendFactor = UtilsGL::toGLBlendFactor(descriptor.sourceAlphaBlendFactor); @@ -63,21 +63,21 @@ void RenderPipelineGL::updateBlendState(const BlendDescriptor& descriptor) if (blendEnabled) { - __gl->enableBlend(); + __state->enableBlend(); - __gl->blendEquationSeparate(rgbBlendOperation, alphaBlendOperation); - __gl->blendFuncSeparate(sourceRGBBlendFactor, destinationRGBBlendFactor, sourceAlphaBlendFactor, + __state->blendEquationSeparate(rgbBlendOp, alphaBlendOp); + __state->blendFuncSeparate(sourceRGBBlendFactor, destinationRGBBlendFactor, sourceAlphaBlendFactor, destinationAlphaBlendFactor); } else - __gl->disableBlend(); + __state->disableBlend(); - __gl->colorMask(writeMaskRed, writeMaskGreen, writeMaskBlue, writeMaskAlpha); + __state->colorMask(writeMaskRed, writeMaskGreen, writeMaskBlue, writeMaskAlpha); } -RenderPipelineGL::~RenderPipelineGL() +RenderPipelineImpl::~RenderPipelineImpl() { - AX_SAFE_RELEASE(_programGL); + AX_SAFE_RELEASE(_programImpl); } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/RenderPipelineGL.h b/axmol/rhi/opengl/RenderPipelineGL.h similarity index 76% rename from core/renderer/backend/opengl/RenderPipelineGL.h rename to axmol/rhi/opengl/RenderPipelineGL.h index 2e85fbe62ee0..95ebf261a282 100644 --- a/core/renderer/backend/opengl/RenderPipelineGL.h +++ b/axmol/rhi/opengl/RenderPipelineGL.h @@ -24,15 +24,15 @@ #pragma once -#include "../RenderPipeline.h" +#include "axmol/rhi/RenderPipeline.h" -#include "platform/GL.h" +#include "axmol/platform/GL.h" #include -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -class ProgramGL; +class ProgramImpl; /** * @addtogroup _opengl * @{ @@ -41,27 +41,27 @@ class ProgramGL; /** * Set program and blend state. */ -class RenderPipelineGL : public RenderPipeline +class RenderPipelineImpl : public RenderPipeline { public: /** * @param descriptor Specifies render pipeline descriptor. */ - RenderPipelineGL() = default; - ~RenderPipelineGL(); + RenderPipelineImpl() = default; + ~RenderPipelineImpl(); - virtual void update(const RenderTarget*, const PipelineDescriptor& pipelineDescriptor) override; + void update(const RenderTarget*, const PipelineDesc& pipelineDesc) override; /** * Get program instance. * @return Program instance. */ - inline ProgramGL* getProgram() const { return _programGL; } + inline ProgramImpl* getProgram() const { return _programImpl; } private: - void updateBlendState(const BlendDescriptor& descriptor); + void updateBlendState(const BlendDesc& descriptor); - ProgramGL* _programGL = nullptr; + ProgramImpl* _programImpl = nullptr; }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/RenderTargetGL.cpp b/axmol/rhi/opengl/RenderTargetGL.cpp similarity index 73% rename from core/renderer/backend/opengl/RenderTargetGL.cpp rename to axmol/rhi/opengl/RenderTargetGL.cpp index e288a5119f0a..a65a99968599 100644 --- a/core/renderer/backend/opengl/RenderTargetGL.cpp +++ b/axmol/rhi/opengl/RenderTargetGL.cpp @@ -23,13 +23,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "RenderTargetGL.h" -#include "DriverGL.h" -#include "renderer/backend/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/RenderTargetGL.h" +#include "axmol/rhi/opengl/DriverGL.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/TextureGL.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -RenderTargetGL::RenderTargetGL(bool defaultRenderTarget, DriverGL* driver) : RenderTarget(defaultRenderTarget) +RenderTargetImpl::RenderTargetImpl(bool defaultRenderTarget, DriverImpl* driver) : RenderTarget(defaultRenderTarget) { if (!defaultRenderTarget) { @@ -48,7 +49,7 @@ RenderTargetGL::RenderTargetGL(bool defaultRenderTarget, DriverGL* driver) : Ren _FBO = driver->getDefaultFBO(); } } -RenderTargetGL::~RenderTargetGL() +RenderTargetImpl::~RenderTargetImpl() { if (!_defaultRenderTarget) { @@ -70,17 +71,17 @@ RenderTargetGL::~RenderTargetGL() } } -void RenderTargetGL::bindFrameBuffer() const +void RenderTargetImpl::bindFrameBuffer() const { - __gl->bindFrameBuffer(_FBO); + __state->bindFrameBuffer(_FBO); } -void RenderTargetGL::unbindFrameBuffer() const +void RenderTargetImpl::unbindFrameBuffer() const { - __gl->bindFrameBuffer(0); + __state->bindFrameBuffer(0); } -void RenderTargetGL::update() const +void RenderTargetImpl::update() const { if (!_dirtyFlags) return; @@ -97,28 +98,23 @@ void RenderTargetGL::update() const if (bitmask::any(_dirtyFlags, getMRTColorFlag(i))) glFramebufferTexture2D( GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + i, GL_TEXTURE_2D, - static_cast(textureInfo.texture ? textureInfo.texture->getHandler() : 0), + textureInfo.texture ? static_cast(textureInfo.texture)->internalHandle() : 0, textureInfo.level); } -#if AX_GLES_PROFILE != 200 + glDrawBuffers(MAX_COLOR_ATTCHMENT, bufs); -#endif - CHECK_GL_ERROR_DEBUG(); - } - if (bitmask::any(_dirtyFlags, TargetBufferFlags::DEPTH)) - { - // depth attacmhemt - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, - _depth.texture != nullptr ? _depth.texture->getHandler() : 0, _depth.level); CHECK_GL_ERROR_DEBUG(); } - if (bitmask::any(_dirtyFlags, TargetBufferFlags::STENCIL)) + if (bitmask::any(_dirtyFlags, TargetBufferFlags::DEPTH_AND_STENCIL)) { - // stencil attachment - glFramebufferTexture2D(GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT, GL_TEXTURE_2D, - _stencil.texture != nullptr ? _stencil.texture->getHandler() : 0, _stencil.level); + // depth stencil attachment + glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT, GL_TEXTURE_2D, + _depthStencil.texture != nullptr + ? static_cast(_depthStencil.texture)->internalHandle() + : 0, + _depthStencil.level); CHECK_GL_ERROR_DEBUG(); } } @@ -126,4 +122,4 @@ void RenderTargetGL::update() const _dirtyFlags = TargetBufferFlags::NONE; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/RenderTargetGL.h b/axmol/rhi/opengl/RenderTargetGL.h similarity index 52% rename from core/renderer/backend/opengl/RenderTargetGL.h rename to axmol/rhi/opengl/RenderTargetGL.h index eaa4773dd4da..92f2942d5e47 100644 --- a/core/renderer/backend/opengl/RenderTargetGL.h +++ b/axmol/rhi/opengl/RenderTargetGL.h @@ -1,20 +1,20 @@ #pragma once -#include "../RenderTarget.h" -#include "platform/GL.h" -#include "OpenGLState.h" +#include "axmol/rhi/RenderTarget.h" +#include "axmol/platform/GL.h" +#include "axmol/rhi/opengl/OpenGLState.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -class DriverGL; +class DriverImpl; -class RenderTargetGL : public RenderTarget +class RenderTargetImpl : public RenderTarget { public: /* * generateFBO, false, use for screen framebuffer */ - RenderTargetGL(bool defaultRenderTarget, DriverGL* driver); - ~RenderTargetGL(); + RenderTargetImpl(bool defaultRenderTarget, DriverImpl* driver); + ~RenderTargetImpl(); void bindFrameBuffer() const; void unbindFrameBuffer() const; @@ -28,4 +28,4 @@ class RenderTargetGL : public RenderTarget #endif }; -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/ShaderModuleGL.cpp b/axmol/rhi/opengl/ShaderModuleGL.cpp similarity index 85% rename from core/renderer/backend/opengl/ShaderModuleGL.cpp rename to axmol/rhi/opengl/ShaderModuleGL.cpp index d9c962e5b2da..0fa84c4fca1a 100644 --- a/core/renderer/backend/opengl/ShaderModuleGL.cpp +++ b/axmol/rhi/opengl/ShaderModuleGL.cpp @@ -23,25 +23,25 @@ THE SOFTWARE. ****************************************************************************/ -#include "ShaderModuleGL.h" +#include "axmol/rhi/opengl/ShaderModuleGL.h" -#include "platform/PlatformMacros.h" -#include "base/Macros.h" -#include "base/axstd.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Macros.h" +#include "axmol/base/axstd.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { -ShaderModuleGL::ShaderModuleGL(ShaderStage stage, std::string_view source) : ShaderModule(stage) +ShaderModuleImpl::ShaderModuleImpl(ShaderStage stage, std::string_view source) : ShaderModule(stage) { compileShader(stage, source); } -ShaderModuleGL::~ShaderModuleGL() +ShaderModuleImpl::~ShaderModuleImpl() { deleteShader(); } -void ShaderModuleGL::compileShader(ShaderStage stage, std::string_view source) +void ShaderModuleImpl::compileShader(ShaderStage stage, std::string_view source) { GLenum shaderType = stage == ShaderStage::VERTEX ? GL_VERTEX_SHADER : GL_FRAGMENT_SHADER; const GLchar* sourcePtr = reinterpret_cast(source.data()); @@ -76,7 +76,7 @@ void ShaderModuleGL::compileShader(ShaderStage stage, std::string_view source) } } -void ShaderModuleGL::deleteShader() +void ShaderModuleImpl::deleteShader() { if (_shader) { @@ -85,4 +85,4 @@ void ShaderModuleGL::deleteShader() } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/ShaderModuleGL.h b/axmol/rhi/opengl/ShaderModuleGL.h similarity index 87% rename from core/renderer/backend/opengl/ShaderModuleGL.h rename to axmol/rhi/opengl/ShaderModuleGL.h index f3fbe201dc79..150e10458854 100644 --- a/core/renderer/backend/opengl/ShaderModuleGL.h +++ b/axmol/rhi/opengl/ShaderModuleGL.h @@ -24,11 +24,11 @@ #pragma once -#include "../ShaderModule.h" +#include "axmol/rhi/ShaderModule.h" -#include "platform/GL.h" +#include "axmol/platform/GL.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { /** * @addtogroup _opengl * @{ @@ -37,15 +37,15 @@ NS_AX_BACKEND_BEGIN /** * Create and compile shader. */ -class ShaderModuleGL : public ShaderModule +class ShaderModuleImpl : public ShaderModule { public: /** * @param stage Specifies whether is vertex shader or fragment shader. * @param source Specifies shader source. */ - ShaderModuleGL(ShaderStage stage, std::string_view source); - ~ShaderModuleGL(); + ShaderModuleImpl(ShaderStage stage, std::string_view source); + ~ShaderModuleImpl(); /** * Get shader object. @@ -58,8 +58,8 @@ class ShaderModuleGL : public ShaderModule void deleteShader(); GLuint _shader = 0; - friend class ProgramGL; + friend class ProgramImpl; }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/TextureGL.cpp b/axmol/rhi/opengl/TextureGL.cpp similarity index 56% rename from core/renderer/backend/opengl/TextureGL.cpp rename to axmol/rhi/opengl/TextureGL.cpp index 9b4edad89bdd..f10f9850e321 100644 --- a/core/renderer/backend/opengl/TextureGL.cpp +++ b/axmol/rhi/opengl/TextureGL.cpp @@ -23,16 +23,17 @@ THE SOFTWARE. ****************************************************************************/ -#include "TextureGL.h" -#include "base/EventListenerCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventType.h" -#include "base/Director.h" -#include "platform/PlatformConfig.h" -#include "renderer/backend/opengl/MacrosGL.h" -#include "renderer/backend/opengl/UtilsGL.h" - -NS_AX_BACKEND_BEGIN +#include "axmol/rhi/opengl/TextureGL.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventType.h" +#include "axmol/base/Director.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/rhi/opengl/MacrosGL.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/SamplerCache.h" + +namespace ax::rhi::gl { #define ISPOW2(n) (((n) & (n - 1)) == 0) @@ -55,50 +56,19 @@ bool isMipmapEnabled(GLint filter) } // namespace /// CLASS TextureInfoGL -void TextureInfoGL::applySampler(const SamplerDescriptor& descriptor, bool isPow2, bool hasMipmaps, GLenum target) -{ - if (descriptor.magFilter != SamplerFilter::DONT_CARE) - { - magFilterGL = UtilsGL::toGLMagFilter(descriptor.magFilter); - } - - if (descriptor.minFilter != SamplerFilter::DONT_CARE) - { - minFilterGL = UtilsGL::toGLMinFilter(descriptor.minFilter, hasMipmaps, isPow2); - } - - if (descriptor.sAddressMode != SamplerAddressMode::DONT_CARE) - { - sAddressModeGL = UtilsGL::toGLAddressMode(descriptor.sAddressMode, isPow2); - } - - if (descriptor.tAddressMode != SamplerAddressMode::DONT_CARE) - { - tAddressModeGL = UtilsGL::toGLAddressMode(descriptor.tAddressMode, isPow2); - } - - // apply sampler for all internal textures - foreachTextures([this, target](GLuint texID, int index) { - __gl->bindTexture(target, textures[index]); - setCurrentTexParameters(target); - }); -} - -void TextureInfoGL::setCurrentTexParameters(GLenum target) +void TextureInfoGL::applySampler(const SamplerDesc& desc, bool isPow2, bool hasMipmaps) { - glTexParameteri(target, GL_TEXTURE_MIN_FILTER, minFilterGL); - glTexParameteri(target, GL_TEXTURE_MAG_FILTER, magFilterGL); - glTexParameteri(target, GL_TEXTURE_WRAP_S, sAddressModeGL); - glTexParameteri(target, GL_TEXTURE_WRAP_T, tAddressModeGL); + this->sampler = static_cast(reinterpret_cast(SamplerCache::getInstance()->getSampler(desc))); } -void TextureInfoGL::apply(int slot, int index, GLenum target) const +void TextureInfoGL::apply(int slot, int index) const { - __gl->activeTexture(GL_TEXTURE0 + slot); - __gl->bindTexture(target, index < AX_META_TEXTURES ? textures[index] : textures[0]); + __state->activeTexture(GL_TEXTURE0 + slot); + __state->bindTexture(this->target, index < AX_META_TEXTURES ? textures[index] : textures[0]); + __state->bindSampler(slot, this->sampler); } -GLuint TextureInfoGL::ensure(int index, GLenum target) +GLuint TextureInfoGL::ensure(int index) { if (index >= AX_META_TEXTURES) return 0; @@ -106,9 +76,7 @@ GLuint TextureInfoGL::ensure(int index, GLenum target) auto& texID = this->textures[index]; if (!texID) glGenTextures(1, &texID); - __gl->bindTexture(target, texID); - - setCurrentTexParameters(target); // set once + __state->bindTexture(this->target, texID); if (this->maxIdx < index) this->maxIdx = index; @@ -116,7 +84,7 @@ GLuint TextureInfoGL::ensure(int index, GLenum target) return texID; } -void TextureInfoGL::onRendererRecreated(GLenum target) +void TextureInfoGL::onRendererRecreated() { int idx = 0; for (auto&& texID : textures) @@ -126,21 +94,22 @@ void TextureInfoGL::onRendererRecreated(GLenum target) // NOTE: glDeleteTextures() doesn't need to be called here, because the textures were // destroyed when the GL context was lost. texID = 0; - ensure(idx, target); + ensure(idx); } ++idx; } } -/// CLASS Texture2DGL -Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor) +/// CLASS TextureImpl +TextureImpl::TextureImpl(const TextureDesc& descriptor) { - updateTextureDescriptor(descriptor); + _textureType = descriptor.textureType; + updateTextureDesc(descriptor); #if AX_ENABLE_CACHE_TEXTURE_DATA // Listen this event to restored texture id after coming to foreground on GLES. _rendererRecreatedListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { - _textureInfo.onRendererRecreated(GL_TEXTURE_2D); + _textureInfo.onRendererRecreated(); if (_usedForRT) this->ensureTexStorageForRT(); }); @@ -148,14 +117,17 @@ Texture2DGL::Texture2DGL(const TextureDescriptor& descriptor) #endif } -void Texture2DGL::updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index) +void TextureImpl::updateTextureDesc(const TextureDesc& descriptor, int index) { - TextureBackend::updateTextureDescriptor(descriptor, index); + _textureInfo.target = _textureType == rhi::TextureType::TEXTURE_2D ? GL_TEXTURE_2D : GL_TEXTURE_CUBE_MAP; + + assert(descriptor.textureType == rhi::TextureType::TEXTURE_2D || _width == _height); - UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, - _isCompressed); + Texture::updateTextureDesc(descriptor, index); - updateSamplerDescriptor(descriptor.samplerDescriptor); + UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type); + + updateSamplerDesc(descriptor.samplerDesc); const bool useForRT = descriptor.textureUsage == TextureUsage::RENDER_TARGET; #if AX_ENABLE_CACHE_TEXTURE_DATA @@ -166,7 +138,7 @@ void Texture2DGL::updateTextureDescriptor(const ax::backend::TextureDescriptor& } } -void Texture2DGL::ensureTexStorageForRT() +void TextureImpl::ensureTexStorageForRT() { auto size = _width * _height * _bitsPerPixel / 8; assert(size > 0); @@ -177,27 +149,28 @@ void Texture2DGL::ensureTexStorageForRT() free(data); } -Texture2DGL::~Texture2DGL() +TextureImpl::~TextureImpl() { #if AX_ENABLE_CACHE_TEXTURE_DATA Director::getInstance()->getEventDispatcher()->removeEventListener(_rendererRecreatedListener); #endif - _textureInfo.destroy(GL_TEXTURE_2D); + _textureInfo.destroy(); } -void Texture2DGL::updateSamplerDescriptor(const SamplerDescriptor& sampler) +void TextureImpl::updateSamplerDesc(const SamplerDesc& sampler) { bool isPow2 = ISPOW2(_width) && ISPOW2(_height); - _textureInfo.applySampler(sampler, isPow2, _hasMipmaps, GL_TEXTURE_2D); + _textureInfo.applySampler(sampler, isPow2, _hasMipmaps); } -void Texture2DGL::updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index) +void TextureImpl::updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index) { - if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) + assert(_textureInfo.target == GL_TEXTURE_2D); + if (!_textureInfo.ensure(index)) return; // Set the row align only when mipmapsNum == 1 and the data is uncompressed - auto mipmapEnabled = isMipmapEnabled(_textureInfo.minFilterGL) || isMipmapEnabled(_textureInfo.magFilterGL); + auto mipmapEnabled = _hasMipmaps; // TODO: mipLevels if (!mipmapEnabled) { unsigned int bytesPerRow = width * _bitsPerPixel / 8; @@ -242,14 +215,15 @@ void Texture2DGL::updateData(uint8_t* data, std::size_t width, std::size_t heigh _hasMipmaps = true; } -void Texture2DGL::updateCompressedData(uint8_t* data, +void TextureImpl::updateCompressedData(uint8_t* data, std::size_t width, std::size_t height, std::size_t dataLen, std::size_t level, int index) { - if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) + assert(_textureInfo.target == GL_TEXTURE_2D); + if (!_textureInfo.ensure(index)) return; glPixelStorei(GL_UNPACK_ALIGNMENT, 1); @@ -263,7 +237,7 @@ void Texture2DGL::updateCompressedData(uint8_t* data, _hasMipmaps = true; } -void Texture2DGL::updateSubData(std::size_t xoffset, +void TextureImpl::updateSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, @@ -271,7 +245,8 @@ void Texture2DGL::updateSubData(std::size_t xoffset, uint8_t* data, int index) { - if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) + assert(_textureInfo.target == GL_TEXTURE_2D); + if (!_textureInfo.ensure(index)) return; // !IMPORTANT: Set the unpack alignment to 1 byte to avoid issues with width or height no align with 4. @@ -285,7 +260,7 @@ void Texture2DGL::updateSubData(std::size_t xoffset, _hasMipmaps = true; } -void Texture2DGL::updateCompressedSubData(std::size_t xoffset, +void TextureImpl::updateCompressedSubData(std::size_t xoffset, std::size_t yoffset, std::size_t width, std::size_t height, @@ -294,7 +269,8 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, uint8_t* data, int index) { - if (!_textureInfo.ensure(index, GL_TEXTURE_2D)) + assert(_textureInfo.target == GL_TEXTURE_2D); + if (!_textureInfo.ensure(index)) return; glCompressedTexSubImage2D(GL_TEXTURE_2D, level, xoffset, yoffset, width, height, _textureInfo.internalFormat, @@ -305,64 +281,10 @@ void Texture2DGL::updateCompressedSubData(std::size_t xoffset, _hasMipmaps = true; } -void Texture2DGL::generateMipmaps() +void TextureImpl::updateFaceData(TextureCubeFace side, void* data, int index) { - if (TextureUsage::RENDER_TARGET == _textureUsage) - return; - - if (!_hasMipmaps) - { -#if AX_ENABLE_CACHE_TEXTURE_DATA - _generateMipmaps = true; -#endif - _hasMipmaps = true; - __gl->bindTexture(GL_TEXTURE_2D, (GLuint)this->getHandler()); - glGenerateMipmap(GL_TEXTURE_2D); - } -} - -/// CLASS TextureCubeGL -TextureCubeGL::TextureCubeGL(const TextureDescriptor& descriptor) -{ - assert(_width == _height); - _textureType = TextureType::TEXTURE_CUBE; - updateTextureDescriptor(descriptor); - -#if AX_ENABLE_CACHE_TEXTURE_DATA - // Listen this event to restored texture id after coming to foreground on Android. - _rendererRecreatedListener = EventListenerCustom::create( - EVENT_RENDERER_RECREATED, [this](EventCustom*) { _textureInfo.onRendererRecreated(GL_TEXTURE_CUBE_MAP); }); - Director::getInstance()->getEventDispatcher()->addEventListenerWithFixedPriority(_rendererRecreatedListener, -1); -#endif - CHECK_GL_ERROR_DEBUG(); -} - -void TextureCubeGL::updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index) -{ - backend::TextureCubemapBackend::updateTextureDescriptor(descriptor, index); - - UtilsGL::toGLTypes(descriptor.textureFormat, _textureInfo.internalFormat, _textureInfo.format, _textureInfo.type, - _isCompressed); - - updateSamplerDescriptor(descriptor.samplerDescriptor); -} - -TextureCubeGL::~TextureCubeGL() -{ -#if AX_ENABLE_CACHE_TEXTURE_DATA - Director::getInstance()->getEventDispatcher()->removeEventListener(_rendererRecreatedListener); -#endif - _textureInfo.destroy(GL_TEXTURE_CUBE_MAP); -} - -void TextureCubeGL::updateSamplerDescriptor(const SamplerDescriptor& sampler) -{ - _textureInfo.applySampler(sampler, true, _hasMipmaps, GL_TEXTURE_CUBE_MAP); -} - -void TextureCubeGL::updateFaceData(TextureCubeFace side, void* data, int index) -{ - if (!_textureInfo.ensure(index, GL_TEXTURE_CUBE_MAP)) + assert(_textureInfo.target == GL_TEXTURE_CUBE_MAP); + if (!_textureInfo.ensure(index)) return; CHECK_GL_ERROR_DEBUG(); @@ -374,20 +296,23 @@ void TextureCubeGL::updateFaceData(TextureCubeFace side, void* data, int index) _textureInfo.format, _textureInfo.type, data); CHECK_GL_ERROR_DEBUG(); - __gl->bindTexture(GL_TEXTURE_CUBE_MAP, 0); + __state->bindTexture(GL_TEXTURE_CUBE_MAP, 0); } -void TextureCubeGL::generateMipmaps() +void TextureImpl::generateMipmaps() { if (TextureUsage::RENDER_TARGET == _textureUsage) return; if (!_hasMipmaps) { +#if AX_ENABLE_CACHE_TEXTURE_DATA + _generateMipmaps = true; +#endif _hasMipmaps = true; - __gl->bindTexture(GL_TEXTURE_CUBE_MAP, (GLuint)this->getHandler()); - glGenerateMipmap(GL_TEXTURE_CUBE_MAP); + __state->bindTexture(_textureInfo.target, (GLuint)this->internalHandle()); + glGenerateMipmap(_textureInfo.target); } } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/TextureGL.h b/axmol/rhi/opengl/TextureGL.h similarity index 68% rename from core/renderer/backend/opengl/TextureGL.h rename to axmol/rhi/opengl/TextureGL.h index 1d1492ff60a1..9a9bda510359 100644 --- a/core/renderer/backend/opengl/TextureGL.h +++ b/axmol/rhi/opengl/TextureGL.h @@ -26,40 +26,45 @@ #pragma once #include -#include "../Texture.h" -#include "platform/GL.h" -#include "base/EventListenerCustom.h" +#include "axmol/rhi/Texture.h" +#include "axmol/platform/GL.h" +#include "axmol/base/EventListenerCustom.h" -#include "OpenGLState.h" +#include "axmol/rhi/opengl/OpenGLState.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl +{ /** * Store texture information. */ struct TextureInfoGL { - void applySampler(const SamplerDescriptor& desc, bool isPow2, bool hasMipmaps, GLenum target); - void setCurrentTexParameters(GLenum target); + void applySampler(const SamplerDesc& desc, bool isPow2, bool hasMipmaps); TextureInfoGL() { textures.fill(0); } ~TextureInfoGL() {} template - void foreachTextures(const _Fty& cb) const + void foreachTextures(const _Fty& cb) { - GLuint texID; int idx = 0; - while ((texID = textures[idx])) - cb(texID, idx++); + while (textures[idx]) + { + auto& h = textures[idx]; + cb(h, idx++); + } } - GLuint ensure(int index, GLenum target); - void onRendererRecreated(GLenum target); + GLuint ensure(int index); + void onRendererRecreated(); - void destroy(GLenum target) + void destroy() { - foreachTextures([=](GLuint texID, int) { __gl->deleteTexture(target, texID); }); + foreachTextures([this](GLuint& texID, int) { + __state->deleteTexture(texID); + texID = 0; + }); textures.fill(0); } @@ -69,19 +74,17 @@ struct TextureInfoGL /// the slot in shader /// the index in meta textrues /// the target GL_TEXTURE_2D,GL_TEXTURE_CUBE_MAP - void apply(int slot, int index, GLenum target) const; - GLuint getName(int index) const { return textures[0]; } + void apply(int slot, int index) const; - GLint magFilterGL = GL_LINEAR; - GLint minFilterGL = GL_LINEAR; - GLint sAddressModeGL = GL_REPEAT; - GLint tAddressModeGL = GL_REPEAT; + GLuint sampler{0}; // Used in glTexImage2D(). GLint internalFormat = GL_RGBA; GLenum format = GL_RGBA; GLenum type = GL_UNSIGNED_BYTE; + GLenum target = GL_TEXTURE_2D; + std::array textures; int maxIdx = 0; }; @@ -94,14 +97,14 @@ struct TextureInfoGL /** * A 2D texture */ -class Texture2DGL : public backend::Texture2DBackend +class TextureImpl : public rhi::Texture { public: /** * @param descriptor Specifies the texture description. */ - Texture2DGL(const TextureDescriptor& descriptor); - ~Texture2DGL(); + TextureImpl(const TextureDesc& descriptor); + ~TextureImpl(); /** * Update a two-dimensional texture image @@ -171,34 +174,37 @@ class Texture2DGL : public backend::Texture2DBackend uint8_t* data, int index = 0) override; + void updateFaceData(TextureCubeFace side, void* data, int index = 0) override; + /** * Update sampler * @param sampler Specifies the sampler descriptor. */ - virtual void updateSamplerDescriptor(const SamplerDescriptor& sampler) override; + void updateSamplerDesc(const SamplerDesc& sampler) override; /** * Generate mipmaps. */ - virtual void generateMipmaps() override; + void generateMipmaps() override; /** * Update texture description. * @param descriptor Specifies texture and sampler descriptor. */ - virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0) override; + void updateTextureDesc(const TextureDesc& descriptor, int index = 0) override; /** - * Get texture object. + * Get internal texture object handle. * @return Texture object. */ - uintptr_t getHandler(int index = 0) const override { return _textureInfo.textures[index]; } + GLuint internalHandle(int index = 0) const { return _textureInfo.textures[index]; } /** * Set texture to pipeline * @param index Specifies the texture image unit selector. + * @param target GL_TEXTURE_2D or GL_TEXTURE_CUBE_MAP */ - void apply(int slot, int index) const { _textureInfo.apply(slot, index, GL_TEXTURE_2D); } + void apply(int slot, int index) const { _textureInfo.apply(slot, index); } int getCount() const override { return _textureInfo.maxIdx + 1; } @@ -210,63 +216,10 @@ class Texture2DGL : public backend::Texture2DBackend #if AX_ENABLE_CACHE_TEXTURE_DATA bool _generateMipmaps = false; - bool _usedForRT = false; + bool _usedForRT = false; #endif }; -/** - * Texture cube. - */ -class TextureCubeGL : public backend::TextureCubemapBackend -{ -public: - /** - * @param descriptor Specifies the texture description. - */ - TextureCubeGL(const TextureDescriptor& descriptor); - ~TextureCubeGL(); - - /** - * Update sampler - * @param sampler Specifies the sampler descriptor. - */ - virtual void updateSamplerDescriptor(const SamplerDescriptor& sampler) override; - - /** - * Update texutre cube data in give slice side. - * @param side Specifies which slice texture of cube to be update. - * @param data Specifies a pointer to the image data in memory. - */ - virtual void updateFaceData(TextureCubeFace side, void* data, int index = 0) override; - - /// Generate mipmaps. - virtual void generateMipmaps() override; - - /** - * Update texture description. - * @param descriptor Specifies texture and sampler descriptor. - */ - virtual void updateTextureDescriptor(const TextureDescriptor& descriptor, int index = 0) override; - - /** - * Get texture object. - * @return Texture object. - */ - uintptr_t getHandler(int index = 0) const override { return _textureInfo.textures[index]; } - - /** - * Set texture to pipeline - * @param index Specifies the texture image unit selector. - */ - void apply(int slot, int index) const { _textureInfo.apply(slot, index, GL_TEXTURE_CUBE_MAP); } - - int getCount() const override { return _textureInfo.maxIdx + 1; } - -private: - TextureInfoGL _textureInfo; - EventListener* _rendererRecreatedListener = nullptr; -}; - // end of _opengl group /// @} -NS_AX_BACKEND_END +} // namespace ax::rhi::gl diff --git a/core/renderer/backend/opengl/UtilsGL.cpp b/axmol/rhi/opengl/UtilsGL.cpp similarity index 79% rename from core/renderer/backend/opengl/UtilsGL.cpp rename to axmol/rhi/opengl/UtilsGL.cpp index 678f274ab4fd..95c68bbb587c 100644 --- a/core/renderer/backend/opengl/UtilsGL.cpp +++ b/axmol/rhi/opengl/UtilsGL.cpp @@ -23,14 +23,13 @@ THE SOFTWARE. ****************************************************************************/ -#include "UtilsGL.h" -#include "ProgramGL.h" -#include "TextureGL.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/PixelFormatUtils.h" -#include "platform/GL.h" +#include "axmol/rhi/opengl/UtilsGL.h" +#include "axmol/rhi/opengl/ProgramGL.h" +#include "axmol/rhi/opengl/TextureGL.h" +#include "axmol/rhi/PixelFormatUtils.h" +#include "axmol/platform/GL.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { struct GPUTextureFormatInfo { @@ -84,13 +83,8 @@ static GPUTextureFormatInfo s_textureFormats[] = { GL_RGB, GL_SRGB, GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5}, // RGB565 === MTLPixelFormatB5G6R5Unorm { GL_RGBA, GL_SRGB_ALPHA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_4_4_4_4}, // RGBA4 === MTLPixelFormatABGR4Unorm { GL_RGBA, GL_SRGB_ALPHA, GL_RGBA, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1}, // RGB5A1 === MTLPixelFormatA1BGR5Unorm -#if AX_GLES_PROFILE != 200 { GL_R8, GL_R8, GL_RED, GL_RED, GL_UNSIGNED_BYTE, }, // R8 In Shader: (R,0,0,0) GL3/GLES3 preferred { GL_RG8, GL_RG, GL_RG, GL_RG, GL_UNSIGNED_BYTE, }, // RG8 In Shader: (R,G,0,0) GL3/GLES3 preferred -#else - { GL_LUMINANCE, GL_SLUMINANCE, GL_LUMINANCE, GL_LUMINANCE, GL_UNSIGNED_BYTE, }, // L8 In Shader: (L,L,L,1) GLES2/GLES3 ONLY deprecated - { GL_LUMINANCE_ALPHA, GL_SLUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, }, // LA8 In Shader: (L,L,L,A) GLES2/GLES3 ONLY deprecated -#endif { GL_RGBA32F_EXT, GL_ZERO, GL_RGBA, GL_ZERO, GL_FLOAT, }, // RGBA32F /* depth stencil internalFormat | internalFormatSrgb | format | formatSrgb | type */ @@ -209,126 +203,47 @@ GLsizei UtilsGL::getGLDataTypeSize(GLenum size) return ret; } -GLint UtilsGL::toGLMagFilter(SamplerFilter magFilter) -{ - GLint ret = GL_LINEAR; - switch (magFilter) - { - case SamplerFilter::LINEAR: - ret = GL_LINEAR; - break; - case SamplerFilter::NEAREST: - ret = GL_NEAREST; - break; - default: - break; - } - return ret; -} - -GLint UtilsGL::toGLMinFilter(SamplerFilter minFilter, bool hasMipmaps, bool isPow2) -{ - if (hasMipmaps && !isPow2) - { - AXLOGD("Change minification filter to either NEAREST or LINEAR since non-power-of-two texture occur in {} {} {}", - __FILE__, __FUNCTION__, __LINE__); - if (SamplerFilter::LINEAR == minFilter) - return GL_LINEAR; - else - return GL_NEAREST; - } - - switch (minFilter) - { - case SamplerFilter::LINEAR: - return GL_LINEAR; - case SamplerFilter::LINEAR_MIPMAP_LINEAR: - return GL_LINEAR_MIPMAP_LINEAR; - case SamplerFilter::LINEAR_MIPMAP_NEAREST: - return GL_LINEAR_MIPMAP_NEAREST; - case SamplerFilter::NEAREST: - return GL_NEAREST; - case SamplerFilter::NEAREST_MIPMAP_NEAREST: - return GL_NEAREST_MIPMAP_NEAREST; - case SamplerFilter::NEAREST_MIPMAP_LINEAR: - return GL_NEAREST_MIPMAP_LINEAR; - default: - break; - } - - return GL_NEAREST; -} - -GLint UtilsGL::toGLAddressMode(SamplerAddressMode addressMode, bool isPow2) -{ - GLint ret = GL_REPEAT; - if (!isPow2 && (addressMode != SamplerAddressMode::CLAMP_TO_EDGE)) - { - AXLOGD("Change texture wrap mode to CLAMP_TO_EDGE since non-power-of-two texture occur in {} {} {}", __FILE__, - __FUNCTION__, __LINE__); - return GL_CLAMP_TO_EDGE; - } - - switch (addressMode) - { - case SamplerAddressMode::REPEAT: - ret = GL_REPEAT; - break; - case SamplerAddressMode::MIRROR_REPEAT: - ret = GL_MIRRORED_REPEAT; - break; - case SamplerAddressMode::CLAMP_TO_EDGE: - ret = GL_CLAMP_TO_EDGE; - break; - default: - break; - } - return ret; -} - void UtilsGL::toGLTypes(PixelFormat textureFormat, GLint& internalFormat, GLuint& format, - GLenum& type, - bool& isCompressed) + GLenum& type) { - if (AX_LIKELY(textureFormat < PixelFormat::COUNT)) + if (textureFormat < PixelFormat::COUNT) [[likely]] { auto& info = s_textureFormats[(int)textureFormat]; internalFormat = info.internalFmt; format = info.fmt; type = info.type; - isCompressed = PixelFormatUtils::isCompressed(textureFormat); } } -GLenum UtilsGL::toGLComareFunction(CompareFunction compareFunction) +GLenum UtilsGL::toGLCompareFunc(CompareFunc compareFunction) { GLenum ret = GL_ALWAYS; switch (compareFunction) { - case CompareFunction::NEVER: + case CompareFunc::NEVER: ret = GL_NEVER; break; - case CompareFunction::LESS: + case CompareFunc::LESS: ret = GL_LESS; break; - case CompareFunction::LESS_EQUAL: + case CompareFunc::LESS_EQUAL: ret = GL_LEQUAL; break; - case CompareFunction::GREATER: + case CompareFunc::GREATER: ret = GL_GREATER; break; - case CompareFunction::GREATER_EQUAL: + case CompareFunc::GREATER_EQUAL: ret = GL_GEQUAL; break; - case CompareFunction::NOT_EQUAL: + case CompareFunc::NOT_EQUAL: ret = GL_NOTEQUAL; break; - case CompareFunction::EQUAL: + case CompareFunc::EQUAL: ret = GL_EQUAL; break; - case CompareFunction::ALWAYS: + case CompareFunc::ALWAYS: ret = GL_ALWAYS; break; default: @@ -337,27 +252,27 @@ GLenum UtilsGL::toGLComareFunction(CompareFunction compareFunction) return ret; } -GLenum UtilsGL::toGLStencilOperation(StencilOperation stencilOperation) +GLenum UtilsGL::toGLStencilOp(StencilOp stencilOp) { GLenum ret = GL_KEEP; - switch (stencilOperation) + switch (stencilOp) { - case StencilOperation::KEEP: + case StencilOp::KEEP: ret = GL_KEEP; break; - case StencilOperation::ZERO: + case StencilOp::ZERO: ret = GL_ZERO; break; - case StencilOperation::REPLACE: + case StencilOp::REPLACE: ret = GL_REPLACE; break; - case StencilOperation::INVERT: + case StencilOp::INVERT: ret = GL_INVERT; break; - case StencilOperation::INCREMENT_WRAP: + case StencilOp::INCREMENT_WRAP: ret = GL_INCR_WRAP; break; - case StencilOperation::DECREMENT_WRAP: + case StencilOp::DECREMENT_WRAP: ret = GL_DECR_WRAP; break; default: @@ -366,18 +281,18 @@ GLenum UtilsGL::toGLStencilOperation(StencilOperation stencilOperation) return ret; } -GLenum UtilsGL::toGLBlendOperation(BlendOperation blendOperation) +GLenum UtilsGL::toGLBlendOp(BlendOp blendOp) { GLenum ret = GL_FUNC_ADD; - switch (blendOperation) + switch (blendOp) { - case BlendOperation::ADD: + case BlendOp::ADD: ret = GL_FUNC_ADD; break; - case BlendOperation::SUBTRACT: + case BlendOp::SUBTRACT: ret = GL_FUNC_SUBTRACT; break; - case BlendOperation::REVERSE_SUBTRACT: + case BlendOp::REVERSE_SUBTRACT: ret = GL_FUNC_REVERSE_SUBTRACT; break; default: @@ -495,4 +410,4 @@ GLenum UtilsGL::toGLCullMode(CullMode mode) return GL_FRONT; } -NS_AX_BACKEND_END +} diff --git a/core/renderer/backend/opengl/UtilsGL.h b/axmol/rhi/opengl/UtilsGL.h similarity index 68% rename from core/renderer/backend/opengl/UtilsGL.h rename to axmol/rhi/opengl/UtilsGL.h index ed45a1192303..c43082e497f0 100644 --- a/core/renderer/backend/opengl/UtilsGL.h +++ b/axmol/rhi/opengl/UtilsGL.h @@ -24,12 +24,12 @@ #pragma once -#include "base/Macros.h" -#include "platform/GL.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/PixelBufferDescriptor.h" +#include "axmol/base/Macros.h" +#include "axmol/platform/GL.h" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/PixelBufferDesc.h" -NS_AX_BACKEND_BEGIN +namespace ax::rhi::gl { /** * @addtogroup _opengl * @{ @@ -60,33 +60,6 @@ struct UtilsGL */ static GLsizei getGLDataTypeSize(GLenum size); - /** - * Convert magnification filter to GLint. i.e. convert SamplerFilter::LINEAR to GL_LINEAR. - * @param magFilter Specifies the magnification filter to convert. - * @return Magnification filter. - */ - static GLint toGLMagFilter(SamplerFilter magFilter); - - /** - * Convert minifying filter to GLint. i.e. convert SamplerFilter::LINEAR to GL_LINEAR. - * If mipmaps is enabled and texture width and height are not power of two, then if minFilter is - * SamplerFilter::LINEAR, GL_LINEAR is returned, otherwise return GL_NEAREST. - * @param minFilter Specifies minifying filter. - * @param hasMipmaps Specifies whether mipmap is enabled. - * @param isPow2 Specifies if texture width and height are power of two. - * @return Minifying filter - */ - static GLint toGLMinFilter(SamplerFilter minFilter, bool hasMipmaps, bool isPow2); - - /** - * Convert wrap parameter for texture coordinate to GLint. i.e. convert SamplerAddressMode::REPEAT to GL_REPEAT. - * If texture width and height are not power of 2, then GL_CLAMP_TO_EDGE is returned. - * @param addressMode Specifies wrapping mode. - * @param isPow2 Specifies if texture width and height are power of two. - * @return Wrap mode. - */ - static GLint toGLAddressMode(SamplerAddressMode addressMode, bool isPow2); - /** * Get textrue parameters from texture pixle format. * @param in textureFormat Specifies texture pixel format. @@ -98,29 +71,28 @@ struct UtilsGL static void toGLTypes(PixelFormat textureFormat, GLint& internalFormat, GLuint& format, - GLenum& type, - bool& isCompressed); + GLenum& type); /** - * Convert compare function to GLenum. i.e. convert CompareFunction::NEVER to GL_NEVER. + * Convert compare function to GLenum. i.e. convert CompareFunc::NEVER to GL_NEVER. * @param compareFunction Specifies the compare function to convert. * @return Compare function. */ - static GLenum toGLComareFunction(CompareFunction compareFunction); + static GLenum toGLCompareFunc(CompareFunc compareFunc); /** - * Convert stencil operation to GLenum. i.e. convert StencilOperation::KEEP to GL_KEEP. - * @param stencilOperation Specifies stencil operation. + * Convert stencil operation to GLenum. i.e. convert StencilOp::KEEP to GL_KEEP. + * @param b([a-z_][A-Za-z0-9_]*)Opb Specifies stencil operation. * @return Stencil operation. */ - static GLenum toGLStencilOperation(StencilOperation stencilOperation); + static GLenum toGLStencilOp(StencilOp stencilOp); /** - * Convert blend operation to GLenum. i.e. convert BlendOperation::ADD to GL_FUNC_ADD. - * @param blendOperation Specifies blend function to convert. + * Convert blend operation to GLenum. i.e. convert BlendOp::ADD to GL_FUNC_ADD. + * @param blendOp Specifies blend function to convert. * @return Blend operation. */ - static GLenum toGLBlendOperation(BlendOperation blendOperation); + static GLenum toGLBlendOp(BlendOp blendOp); /** * Convert blend factor to GLenum. i.e. convert BlendFactor::ZERO to GL_ZERO. @@ -159,4 +131,4 @@ struct UtilsGL }; // end of _opengl group /// @} -NS_AX_BACKEND_END +} diff --git a/core/ui/CMakeLists.txt b/axmol/ui/CMakeLists.txt similarity index 99% rename from core/ui/CMakeLists.txt rename to axmol/ui/CMakeLists.txt index c270c15ed4e8..869b1fafefc6 100644 --- a/core/ui/CMakeLists.txt +++ b/axmol/ui/CMakeLists.txt @@ -124,7 +124,6 @@ set(_AX_UI_HEADER ui/UIAbstractCheckButton.h ui/UIButton.h ui/UICheckBox.h - ui/LayoutHelper.h ui/UIHBox.h ui/UIHelper.h ui/UIImageView.h @@ -160,7 +159,6 @@ set(_AX_UI_SRC ui/UIAbstractCheckButton.cpp ui/UICheckBox.cpp ui/UIRadioButton.cpp - ui/LayoutHelper.cpp ui/UIHBox.cpp ui/UIHelper.cpp ui/UIImageView.cpp diff --git a/core/ui/CocosGUI.h b/axmol/ui/CocosGUI.h similarity index 64% rename from core/ui/CocosGUI.h rename to axmol/ui/CocosGUI.h index 497c8da6190f..abd2ec8a0337 100644 --- a/core/ui/CocosGUI.h +++ b/axmol/ui/CocosGUI.h @@ -1,5 +1,5 @@ #pragma once -#include "axmol-ui.h" +#include "axmol/ui/axmol-ui.h" AX_GUI_DLL const char* CocosGUIVersion(); diff --git a/core/ui/GUIDefine.h b/axmol/ui/GUIDefine.h similarity index 98% rename from core/ui/GUIDefine.h rename to axmol/ui/GUIDefine.h index 86cf88e327bc..78510394e628 100644 --- a/core/ui/GUIDefine.h +++ b/axmol/ui/GUIDefine.h @@ -27,7 +27,7 @@ #pragma once #include -#include "base/ObjectFactory.h" +#include "axmol/base/ObjectFactory.h" ///@cond DO_NOT_SHOW // diff --git a/core/ui/GUIExport.h b/axmol/ui/GUIExport.h similarity index 96% rename from core/ui/GUIExport.h rename to axmol/ui/GUIExport.h index 814baf5f3aff..d648e78c8ded 100644 --- a/core/ui/GUIExport.h +++ b/axmol/ui/GUIExport.h @@ -25,7 +25,7 @@ #pragma once -#include "platform/PlatformDefine.h" +#include "axmol/platform/PlatformDefine.h" #define AX_GUI_DLL AX_API diff --git a/core/ui/UIAbstractCheckButton.cpp b/axmol/ui/UIAbstractCheckButton.cpp similarity index 96% rename from core/ui/UIAbstractCheckButton.cpp rename to axmol/ui/UIAbstractCheckButton.cpp index af18d523647d..cca065c2557f 100644 --- a/core/ui/UIAbstractCheckButton.cpp +++ b/axmol/ui/UIAbstractCheckButton.cpp @@ -24,10 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIAbstractCheckButton.h" -#include "2d/Sprite.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramStateRegistry.h" +#include "axmol/ui/UIAbstractCheckButton.h" +#include "axmol/2d/Sprite.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/renderer/ProgramStateRegistry.h" namespace ax { @@ -312,8 +312,8 @@ void AbstractCheckButton::onPressStateChangedToNormal() _backGroundBoxDisabledRenderer->setVisible(false); _frontCrossDisabledRenderer->setVisible(false); - _backGroundBoxRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); - _frontCrossRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + _backGroundBoxRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); + _frontCrossRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); _backGroundBoxRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY); _frontCrossRenderer->setScale(_backgroundTextureScaleX, _backgroundTextureScaleY); @@ -327,8 +327,8 @@ void AbstractCheckButton::onPressStateChangedToNormal() void AbstractCheckButton::onPressStateChangedToPressed() { - _backGroundBoxRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); - _frontCrossRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + _backGroundBoxRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); + _frontCrossRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); if (!_isBackgroundSelectedTextureLoaded) { @@ -348,9 +348,9 @@ void AbstractCheckButton::onPressStateChangedToDisabled() { if (!_isBackgroundDisabledTextureLoaded || !_isFrontCrossDisabledTextureLoaded) { - _backGroundBoxRenderer->setProgramState(backend::ProgramType::GRAY_SCALE); + _backGroundBoxRenderer->setProgramState(rhi::ProgramType::GRAY_SCALE); - _frontCrossRenderer->setProgramState(backend::ProgramType::GRAY_SCALE); + _frontCrossRenderer->setProgramState(rhi::ProgramType::GRAY_SCALE); } else { diff --git a/core/ui/UIAbstractCheckButton.h b/axmol/ui/UIAbstractCheckButton.h similarity index 94% rename from core/ui/UIAbstractCheckButton.h rename to axmol/ui/UIAbstractCheckButton.h index 5895b7b8df17..033d2dcf7327 100644 --- a/core/ui/UIAbstractCheckButton.h +++ b/axmol/ui/UIAbstractCheckButton.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -123,8 +123,8 @@ class AX_GUI_DLL AbstractCheckButton : public Widget void setSelected(bool selected); // override functions - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; /** When user pressed the CheckBox, the button will zoom to a scale. * The final scale of the CheckBox equals (CheckBox original scale + _zoomScale) @@ -174,7 +174,7 @@ class AX_GUI_DLL AbstractCheckButton : public Widget ResourceData getCrossNormalFile(); ResourceData getCrossDisabledFile(); - virtual bool init() override; + bool init() override; virtual bool init(std::string_view backGround, std::string_view backGroundSelected, std::string_view cross, @@ -195,10 +195,10 @@ class AX_GUI_DLL AbstractCheckButton : public Widget */ virtual ~AbstractCheckButton(); - virtual void initRenderer() override; - virtual void onPressStateChangedToNormal() override; - virtual void onPressStateChangedToPressed() override; - virtual void onPressStateChangedToDisabled() override; + void initRenderer() override; + void onPressStateChangedToNormal() override; + void onPressStateChangedToPressed() override; + void onPressStateChangedToDisabled() override; void setupBackgroundTexture(); void loadTextureBackGround(SpriteFrame* spriteFrame); @@ -213,7 +213,7 @@ class AX_GUI_DLL AbstractCheckButton : public Widget virtual void dispatchSelectChangedEvent(bool selected) = 0; - virtual void onSizeChanged() override; + void onSizeChanged() override; void backGroundTextureScaleChangedWithSize(); void backGroundSelectedTextureScaleChangedWithSize(); @@ -221,8 +221,8 @@ class AX_GUI_DLL AbstractCheckButton : public Widget void backGroundDisabledTextureScaleChangedWithSize(); void frontCrossDisabledTextureScaleChangedWithSize(); - virtual void copySpecialProperties(Widget* model) override; - virtual void adaptRenderers() override; + void copySpecialProperties(Widget* model) override; + void adaptRenderers() override; protected: Sprite* _backGroundBoxRenderer; diff --git a/core/ui/UIButton.cpp b/axmol/ui/UIButton.cpp similarity index 98% rename from core/ui/UIButton.cpp rename to axmol/ui/UIButton.cpp index 2c21c2f1d2a0..c71953ef087f 100644 --- a/core/ui/UIButton.cpp +++ b/axmol/ui/UIButton.cpp @@ -24,13 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIButton.h" -#include "ui/UIScale9Sprite.h" -#include "2d/Label.h" -#include "2d/Sprite.h" -#include "2d/ActionInterval.h" -#include "platform/FileUtils.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIButton.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/ui/UIHelper.h" #include namespace ax @@ -751,19 +751,19 @@ std::string_view Button::getTitleText() const return _titleRenderer->getString(); } -void Button::setTitleColor(const Color3B& color) +void Button::setTitleColor(const Color32& color) { createTitleRendererIfNull(); - _titleRenderer->setTextColor(Color4B(color)); + _titleRenderer->setTextColor(color); } -Color3B Button::getTitleColor() const +const Color32& Button::getTitleColor() const { if (nullptr == _titleRenderer) { - return Color3B::WHITE; + return Color32::WHITE; } - return Color3B(_titleRenderer->getTextColor()); + return _titleRenderer->getTextColor(); } void Button::setTitleFontSize(float size) diff --git a/core/ui/UIButton.h b/axmol/ui/UIButton.h similarity index 92% rename from core/ui/UIButton.h rename to axmol/ui/UIButton.h index 7d660cf31c83..bbcf3a51caf2 100644 --- a/core/ui/UIButton.h +++ b/axmol/ui/UIButton.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -190,10 +190,10 @@ class AX_GUI_DLL Button : public Widget void setPressedActionEnabled(bool enabled); // override methods - virtual void ignoreContentAdaptWithSize(bool ignore) override; - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; - virtual std::string getDescription() const override; + void ignoreContentAdaptWithSize(bool ignore) override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; + std::string getDescription() const override; /** * Return the inner title renderer of Button. @@ -216,15 +216,15 @@ class AX_GUI_DLL Button : public Widget /** * Change the color of button's title. - *@param color The title color in Color3B. + *@param color The title color in Color32. */ - void setTitleColor(const Color3B& color); + void setTitleColor(const Color32& color); /** * Query the button title color. - *@return Color3B of button title. + *@return Color32 of button title. */ - Color3B getTitleColor() const; + const Color32& getTitleColor() const; /** * Change the font size of button's title @@ -313,7 +313,7 @@ class AX_GUI_DLL Button : public Widget ResourceData getPressedFile(); ResourceData getDisabledFile(); - virtual bool init() override; + bool init() override; virtual bool init(std::string_view normalImage, std::string_view selectedImage = "", std::string_view disableImage = "", @@ -322,11 +322,11 @@ class AX_GUI_DLL Button : public Widget virtual Vec2 getNormalTextureSize() const; protected: - virtual void initRenderer() override; - virtual void onPressStateChangedToNormal() override; - virtual void onPressStateChangedToPressed() override; - virtual void onPressStateChangedToDisabled() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onPressStateChangedToNormal() override; + void onPressStateChangedToPressed() override; + void onPressStateChangedToDisabled() override; + void onSizeChanged() override; void loadTextureNormal(SpriteFrame* normalSpriteFrame); void setupNormalTexture(bool textureLoaded); @@ -339,14 +339,14 @@ class AX_GUI_DLL Button : public Widget void pressedTextureScaleChangedWithSize(); void disabledTextureScaleChangedWithSize(); - virtual void adaptRenderers() override; + void adaptRenderers() override; virtual void updateTitleLocation(); void updateContentSize(); virtual void createTitleRenderer(); bool createTitleRendererIfNull(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; virtual Vec2 getNormalSize() const; diff --git a/core/ui/UICheckBox.cpp b/axmol/ui/UICheckBox.cpp similarity index 99% rename from core/ui/UICheckBox.cpp rename to axmol/ui/UICheckBox.cpp index 454928935853..429d001b37ea 100644 --- a/core/ui/UICheckBox.cpp +++ b/axmol/ui/UICheckBox.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UICheckBox.h" +#include "axmol/ui/UICheckBox.h" namespace ax { diff --git a/core/ui/UICheckBox.h b/axmol/ui/UICheckBox.h similarity index 91% rename from core/ui/UICheckBox.h rename to axmol/ui/UICheckBox.h index c074f532f6d6..54ba22961222 100644 --- a/core/ui/UICheckBox.h +++ b/axmol/ui/UICheckBox.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIAbstractCheckButton.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIAbstractCheckButton.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -120,15 +120,15 @@ class AX_GUI_DLL CheckBox : public AbstractCheckButton void addEventListener(const ccCheckBoxCallback& callback); // override functions - virtual std::string getDescription() const override; + std::string getDescription() const override; - virtual void onTouchEnded(Touch* touch, Event* unusedEvent) override; + void onTouchEnded(Touch* touch, Event* unusedEvent) override; protected: - virtual void dispatchSelectChangedEvent(bool selected) override; + void dispatchSelectChangedEvent(bool selected) override; - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; protected: // if you use the old event callback, it will retain the _checkBoxEventListener diff --git a/core/ui/UIEditBox/Mac/UIEditBoxMac.h b/axmol/ui/UIEditBox/Mac/UIEditBoxMac.h similarity index 96% rename from core/ui/UIEditBox/Mac/UIEditBoxMac.h rename to axmol/ui/UIEditBox/Mac/UIEditBoxMac.h index 7d907b4293f2..3d01988aefc4 100644 --- a/core/ui/UIEditBox/Mac/UIEditBoxMac.h +++ b/axmol/ui/UIEditBox/Mac/UIEditBoxMac.h @@ -27,8 +27,8 @@ #import #import -#include "ui/UIEditBox/UIEditBoxImpl-mac.h" -#include "ui/UIEditBox/Mac/UITextInput.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-mac.h" +#include "axmol/ui/UIEditBox/Mac/UITextInput.h" #pragma mark - UIEditBox mac implementation diff --git a/core/ui/UIEditBox/Mac/UIEditBoxMac.mm b/axmol/ui/UIEditBox/Mac/UIEditBoxMac.mm similarity index 97% rename from core/ui/UIEditBox/Mac/UIEditBoxMac.mm rename to axmol/ui/UIEditBox/Mac/UIEditBoxMac.mm index b2af6244a738..245c050b7987 100644 --- a/core/ui/UIEditBox/Mac/UIEditBoxMac.mm +++ b/axmol/ui/UIEditBox/Mac/UIEditBoxMac.mm @@ -24,11 +24,11 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/Mac/UIEditBoxMac.h" -#include "base/Director.h" -#include "ui/UIEditBox/Mac/UISingleLineTextField.h" -#include "ui/UIEditBox/Mac/UIPasswordTextField.h" -#include "ui/UIEditBox/Mac/UIMultilineTextField.h" +#import "axmol/ui/UIEditBox/Mac/UIEditBoxMac.h" +#include "axmol/base/Director.h" +#include "axmol/ui/UIEditBox/Mac/UISingleLineTextField.h" +#include "axmol/ui/UIEditBox/Mac/UIPasswordTextField.h" +#include "axmol/ui/UIEditBox/Mac/UIMultilineTextField.h" #define getEditBoxImplMac() ((ax::ui::EditBoxImplMac*)_editBox) diff --git a/core/ui/UIEditBox/Mac/UIMultilineTextField.h b/axmol/ui/UIEditBox/Mac/UIMultilineTextField.h similarity index 96% rename from core/ui/UIEditBox/Mac/UIMultilineTextField.h rename to axmol/ui/UIEditBox/Mac/UIMultilineTextField.h index e105277b7328..02ae18afe325 100644 --- a/core/ui/UIEditBox/Mac/UIMultilineTextField.h +++ b/axmol/ui/UIEditBox/Mac/UIMultilineTextField.h @@ -26,7 +26,7 @@ #pragma once #import -#include "ui/UIEditBox/Mac/UITextInput.h" +#include "axmol/ui/UIEditBox/Mac/UITextInput.h" @interface CCUIMultilineTextField : NSTextView { NSString* _placeHolder; diff --git a/core/ui/UIEditBox/Mac/UIMultilineTextField.m b/axmol/ui/UIEditBox/Mac/UIMultilineTextField.m similarity index 98% rename from core/ui/UIEditBox/Mac/UIMultilineTextField.m rename to axmol/ui/UIEditBox/Mac/UIMultilineTextField.m index a0c749446c82..035a85ccbb8f 100644 --- a/core/ui/UIEditBox/Mac/UIMultilineTextField.m +++ b/axmol/ui/UIEditBox/Mac/UIMultilineTextField.m @@ -23,7 +23,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/Mac/UIMultilineTextField.h" +#import "axmol/ui/UIEditBox/Mac/UIMultilineTextField.h" @interface CCUIMultilineTextField() @property(nonatomic, copy)NSString* placeHolder; diff --git a/core/ui/UIEditBox/Mac/UIPasswordTextField.h b/axmol/ui/UIEditBox/Mac/UIPasswordTextField.h similarity index 96% rename from core/ui/UIEditBox/Mac/UIPasswordTextField.h rename to axmol/ui/UIEditBox/Mac/UIPasswordTextField.h index 66c3a44faaee..c24aa53c3257 100644 --- a/core/ui/UIEditBox/Mac/UIPasswordTextField.h +++ b/axmol/ui/UIEditBox/Mac/UIPasswordTextField.h @@ -26,7 +26,7 @@ #pragma once #import -#include "ui/UIEditBox/Mac/UITextInput.h" +#include "axmol/ui/UIEditBox/Mac/UITextInput.h" @interface CCUIPasswordTextField : NSSecureTextField { } diff --git a/core/ui/UIEditBox/Mac/UIPasswordTextField.m b/axmol/ui/UIEditBox/Mac/UIPasswordTextField.m similarity index 97% rename from core/ui/UIEditBox/Mac/UIPasswordTextField.m rename to axmol/ui/UIEditBox/Mac/UIPasswordTextField.m index faf3554c9415..c7887a8de0f3 100644 --- a/core/ui/UIEditBox/Mac/UIPasswordTextField.m +++ b/axmol/ui/UIEditBox/Mac/UIPasswordTextField.m @@ -23,8 +23,8 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/Mac/UIPasswordTextField.h" -#include "ui/UIEditBox/Mac/UITextFieldFormatter.h" +#import "axmol/ui/UIEditBox/Mac/UIPasswordTextField.h" +#include "axmol/ui/UIEditBox/Mac/UITextFieldFormatter.h" @interface RSVerticallyCenteredSecureTextFieldCell : NSSecureTextFieldCell { diff --git a/core/ui/UIEditBox/Mac/UISingleLineTextField.h b/axmol/ui/UIEditBox/Mac/UISingleLineTextField.h similarity index 96% rename from core/ui/UIEditBox/Mac/UISingleLineTextField.h rename to axmol/ui/UIEditBox/Mac/UISingleLineTextField.h index 1a7e6e5b15f5..e1602fc27c83 100644 --- a/core/ui/UIEditBox/Mac/UISingleLineTextField.h +++ b/axmol/ui/UIEditBox/Mac/UISingleLineTextField.h @@ -26,7 +26,7 @@ #pragma once #import -#include "ui/UIEditBox/Mac/UITextInput.h" +#include "axmol/ui/UIEditBox/Mac/UITextInput.h" @interface CCUISingleLineTextField : NSTextField { } diff --git a/core/ui/UIEditBox/Mac/UISingleLineTextField.m b/axmol/ui/UIEditBox/Mac/UISingleLineTextField.m similarity index 97% rename from core/ui/UIEditBox/Mac/UISingleLineTextField.m rename to axmol/ui/UIEditBox/Mac/UISingleLineTextField.m index 6ea6750f743d..abacfc1e3f7d 100644 --- a/core/ui/UIEditBox/Mac/UISingleLineTextField.m +++ b/axmol/ui/UIEditBox/Mac/UISingleLineTextField.m @@ -23,8 +23,8 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/Mac/UISingleLineTextField.h" -#include "ui/UIEditBox/Mac/UITextFieldFormatter.h" +#import "axmol/ui/UIEditBox/Mac/UISingleLineTextField.h" +#include "axmol/ui/UIEditBox/Mac/UITextFieldFormatter.h" @interface RSVerticallyCenteredTextFieldCell : NSTextFieldCell { diff --git a/core/ui/UIEditBox/Mac/UITextFieldFormatter.h b/axmol/ui/UIEditBox/Mac/UITextFieldFormatter.h similarity index 100% rename from core/ui/UIEditBox/Mac/UITextFieldFormatter.h rename to axmol/ui/UIEditBox/Mac/UITextFieldFormatter.h diff --git a/core/ui/UIEditBox/Mac/UITextFieldFormatter.m b/axmol/ui/UIEditBox/Mac/UITextFieldFormatter.m similarity index 97% rename from core/ui/UIEditBox/Mac/UITextFieldFormatter.m rename to axmol/ui/UIEditBox/Mac/UITextFieldFormatter.m index b36bce7d8681..350273544e36 100644 --- a/core/ui/UIEditBox/Mac/UITextFieldFormatter.m +++ b/axmol/ui/UIEditBox/Mac/UITextFieldFormatter.m @@ -23,7 +23,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/Mac/UITextFieldFormatter.h" +#import "axmol/ui/UIEditBox/Mac/UITextFieldFormatter.h" @implementation CCUITextFieldFormatter { diff --git a/core/ui/UIEditBox/Mac/UITextInput.h b/axmol/ui/UIEditBox/Mac/UITextInput.h similarity index 100% rename from core/ui/UIEditBox/Mac/UITextInput.h rename to axmol/ui/UIEditBox/Mac/UITextInput.h diff --git a/core/ui/UIEditBox/UIEditBox.cpp b/axmol/ui/UIEditBox/UIEditBox.cpp similarity index 97% rename from core/ui/UIEditBox/UIEditBox.cpp rename to axmol/ui/UIEditBox/UIEditBox.cpp index 56ad3e0704d7..133d3d191da1 100644 --- a/core/ui/UIEditBox/UIEditBox.cpp +++ b/axmol/ui/UIEditBox/UIEditBox.cpp @@ -25,9 +25,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBox.h" -#include "ui/UIEditBox/UIEditBoxImpl.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl.h" +#include "axmol/ui/UIHelper.h" namespace ax { @@ -503,12 +503,8 @@ int EditBox::getFontSize() const } return -1; } -void EditBox::setFontColor(const Color3B& color) -{ - setFontColor(Color4B(color)); -} -void EditBox::setFontColor(const Color4B& color) +void EditBox::setFontColor(const Color32& color) { if (_editBoxImpl != nullptr) { @@ -516,13 +512,13 @@ void EditBox::setFontColor(const Color4B& color) } } -const Color4B& EditBox::getFontColor() const +const Color32& EditBox::getFontColor() const { if (_editBoxImpl != nullptr) { return _editBoxImpl->getFontColor(); } - return Color4B::WHITE; + return Color32::WHITE; } void EditBox::setPlaceholderFont(const char* pFontName, int fontSize) @@ -572,12 +568,7 @@ int EditBox::getPlaceholderFontSize() const return -1; } -void EditBox::setPlaceholderFontColor(const Color3B& color) -{ - setPlaceholderFontColor(Color4B(color)); -} - -void EditBox::setPlaceholderFontColor(const Color4B& color) +void EditBox::setPlaceholderFontColor(const Color32& color) { if (_editBoxImpl != nullptr) { @@ -585,13 +576,13 @@ void EditBox::setPlaceholderFontColor(const Color4B& color) } } -const Color4B& EditBox::getPlaceholderFontColor() const +const Color32& EditBox::getPlaceholderFontColor() const { if (_editBoxImpl != nullptr) { return _editBoxImpl->getPlaceholderFontColor(); } - return Color4B::GRAY; + return Color32::GRAY; } void EditBox::setPlaceHolder(const char* pText) diff --git a/core/ui/UIEditBox/UIEditBox.h b/axmol/ui/UIEditBox/UIEditBox.h similarity index 92% rename from core/ui/UIEditBox/UIEditBox.h rename to axmol/ui/UIEditBox/UIEditBox.h index fa023ae3d831..9118f6766c7c 100644 --- a/core/ui/UIEditBox/UIEditBox.h +++ b/axmol/ui/UIEditBox/UIEditBox.h @@ -27,10 +27,10 @@ #pragma once -#include "base/IMEDelegate.h" -#include "ui/GUIDefine.h" -#include "ui/UIWidget.h" -#include "ui/UIScale9Sprite.h" +#include "axmol/base/IMEDelegate.h" +#include "axmol/ui/GUIDefine.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/UIScale9Sprite.h" namespace ax { @@ -465,13 +465,12 @@ class AX_GUI_DLL EditBox : public Widget, public IMEDelegate /** * Set the font color of the widget's text. */ - void setFontColor(const Color3B& color); - void setFontColor(const Color4B& color); + void setFontColor(const Color32& color); /** * Get the font color of the widget's text. */ - const Color4B& getFontColor() const; + const Color32& getFontColor() const; /** * Set the placeholder's font. Only system font is allowed. @@ -507,17 +506,12 @@ class AX_GUI_DLL EditBox : public Widget, public IMEDelegate /** * Set the font color of the placeholder text when the edit box is empty. */ - void setPlaceholderFontColor(const Color3B& color); - - /** - * Set the font color of the placeholder text when the edit box is empty. - */ - void setPlaceholderFontColor(const Color4B& color); + void setPlaceholderFontColor(const Color32& color); /** * Get the font color of the placeholder text when the edit box is empty. */ - const Color4B& getPlaceholderFontColor() const; + const Color32& getPlaceholderFontColor() const; /** * Set a text in the edit box that acts as a placeholder when an @@ -595,44 +589,44 @@ class AX_GUI_DLL EditBox : public Widget, public IMEDelegate TextHAlignment getTextHorizontalAlignment() const; /* override functions */ - virtual void setPosition(const Vec2& pos) override; - virtual void setVisible(bool visible) override; - virtual void setContentSize(const Size& size) override; - virtual void setAnchorPoint(const Vec2& anchorPoint) override; + void setPosition(const Vec2& pos) override; + void setVisible(bool visible) override; + void setContentSize(const Size& size) override; + void setAnchorPoint(const Vec2& anchorPoint) override; /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void draw(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * @lua NA */ - virtual void keyboardWillShow(IMEKeyboardNotificationInfo& info) override; + void keyboardWillShow(IMEKeyboardNotificationInfo& info) override; /** * @lua NA */ - virtual void keyboardDidShow(IMEKeyboardNotificationInfo& info) override; + void keyboardDidShow(IMEKeyboardNotificationInfo& info) override; /** * @lua NA */ - virtual void keyboardWillHide(IMEKeyboardNotificationInfo& info) override; + void keyboardWillHide(IMEKeyboardNotificationInfo& info) override; /** * @lua NA */ - virtual void keyboardDidHide(IMEKeyboardNotificationInfo& info) override; + void keyboardDidHide(IMEKeyboardNotificationInfo& info) override; void setGlobalZOrder(float globalZOrder) override; @@ -640,13 +634,13 @@ class AX_GUI_DLL EditBox : public Widget, public IMEDelegate void closeKeyboard() const; protected: - virtual void releaseUpEvent() override; + void releaseUpEvent() override; - virtual void initRenderer() override; - virtual void onPressStateChangedToNormal() override; - virtual void onPressStateChangedToPressed() override; - virtual void onPressStateChangedToDisabled() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onPressStateChangedToNormal() override; + void onPressStateChangedToPressed() override; + void onPressStateChangedToDisabled() override; + void onSizeChanged() override; void loadTextureNormal(SpriteFrame* normalSpriteFrame); void setupNormalTexture(bool textureLoaded); @@ -659,7 +653,7 @@ class AX_GUI_DLL EditBox : public Widget, public IMEDelegate void pressedTextureScaleChangedWithSize(); void disabledTextureScaleChangedWithSize(); - virtual void adaptRenderers() override; + void adaptRenderers() override; protected: void updatePosition(float dt); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-android.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-android.cpp similarity index 93% rename from core/ui/UIEditBox/UIEditBoxImpl-android.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-android.cpp index b4961b06a3f4..8abc16781f3b 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-android.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-android.cpp @@ -26,19 +26,19 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-android.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-android.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "ui/UIEditBox/UIEditBox.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" # include -# include "platform/android/jni/JniHelper.h" -# include "2d/Label.h" -# include "base/UTF8.h" -# include "math/Vec2.h" -# include "ui/UIHelper.h" -# include "base/Director.h" -# include "platform/FileUtils.h" +# include "axmol/platform/android/jni/JniHelper.h" +# include "axmol/2d/Label.h" +# include "axmol/base/text_utils.h" +# include "axmol/math/Vec2.h" +# include "axmol/ui/UIHelper.h" +# include "axmol/base/Director.h" +# include "axmol/platform/FileUtils.h" # include "yasio/string_view.hpp" namespace ax @@ -64,7 +64,7 @@ JNIEXPORT void JNICALL Java_dev_axmol_lib_EditBoxHelper_editBoxEditingChanged(JN jint index, jstring text) { - std::string textString = StringUtils::getStringUTFCharsJNI(env, text); + std::string textString = text_utils::getStringUTFCharsJNI(env, text); editBoxEditingDidChanged(index, textString); } @@ -74,7 +74,7 @@ JNIEXPORT void JNICALL Java_dev_axmol_lib_EditBoxHelper_editBoxEditingDidEnd(JNI jstring text, jint action) { - std::string textString = StringUtils::getStringUTFCharsJNI(env, text); + std::string textString = text_utils::getStringUTFCharsJNI(env, text); editBoxEditingDidEnd(index, textString, action); } } @@ -135,7 +135,7 @@ void EditBoxImplAndroid::setNativeFont(const char* pFontName, int fontSize) (float)fontSize * renderView->getScaleX()); } -void EditBoxImplAndroid::setNativeFontColor(const Color4B& color) +void EditBoxImplAndroid::setNativeFontColor(const Color32& color) { JniHelper::callStaticVoidMethod(editBoxClassName, "setFontColor", _editBoxIndex, (int)color.r, (int)color.g, (int)color.b, (int)color.a); @@ -146,7 +146,7 @@ void EditBoxImplAndroid::setNativePlaceholderFont(const char* pFontName, int fon AXLOGD("Warning! You can't change Android Hint fontName and fontSize"); } -void EditBoxImplAndroid::setNativePlaceholderFontColor(const Color4B& color) +void EditBoxImplAndroid::setNativePlaceholderFontColor(const Color32& color) { JniHelper::callStaticVoidMethod(editBoxClassName, "setPlaceHolderTextColor", _editBoxIndex, (int)color.r, (int)color.g, (int)color.b, (int)color.a); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-android.h b/axmol/ui/UIEditBox/UIEditBoxImpl-android.h similarity index 58% rename from core/ui/UIEditBox/UIEditBoxImpl-android.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-android.h index a89647cd0517..db913f7ff233 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-android.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-android.h @@ -27,11 +27,11 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" namespace ax { @@ -54,24 +54,24 @@ class EditBoxImplAndroid : public EditBoxImplCommon */ virtual ~EditBoxImplAndroid(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override; - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setNativePlaceholderFontColor(const Color4B& color) override; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override; - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; - virtual const char* getNativeDefaultFontName() override; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override; - virtual void setNativeMaxLength(int maxLength) override; + bool isEditing() override; + void createNativeControl(const Rect& frame) override; + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override; + void setNativePlaceholderFontColor(const Color32& color) override; + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; + void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override; + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; + const char* getNativeDefaultFontName() override; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override; + void setNativeMaxLength(int maxLength) override; private: int _editBoxIndex; diff --git a/core/ui/UIEditBox/UIEditBoxImpl-common.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-common.cpp similarity index 96% rename from core/ui/UIEditBox/UIEditBoxImpl-common.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-common.cpp index 488468147d91..8a2d9b3e50d8 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-common.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-common.cpp @@ -25,14 +25,14 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-common.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" #define kLabelZOrder 9999 -#include "ui/UIEditBox/UIEditBox.h" -#include "base/Director.h" -#include "2d/Label.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Label.h" +#include "axmol/ui/UIHelper.h" static const int AX_EDIT_BOX_PADDING = 5; @@ -63,8 +63,8 @@ EditBoxImplCommon::EditBoxImplCommon(EditBox* pEditText) , _alignment(TextHAlignment::LEFT) , _fontSize(-1) , _placeholderFontSize(-1) - , _colText(Color3B::WHITE) - , _colPlaceHolder(Color3B::GRAY) + , _colText(Color32::WHITE) + , _colPlaceHolder(Color32::GRAY) , _maxLength(-1) , _editingMode(false) {} @@ -101,7 +101,7 @@ void EditBoxImplCommon::initInactiveLabels(const Vec2& size) _labelPlaceHolder = Label::create(); _labelPlaceHolder->setAnchorPoint(Vec2(0.0f, 1.0f)); - _labelPlaceHolder->setTextColor(Color4B::GRAY); + _labelPlaceHolder->setTextColor(Color32::GRAY); _labelPlaceHolder->enableWrap(false); _labelPlaceHolder->setGlobalZOrder(_editBox->getGlobalZOrder()); _editBox->addChild(_labelPlaceHolder, kLabelZOrder); @@ -182,7 +182,7 @@ void EditBoxImplCommon::setFont(const char* pFontName, int fontSize) } } -void EditBoxImplCommon::setFontColor(const Color4B& color) +void EditBoxImplCommon::setFontColor(const Color32& color) { _colText = color; this->setNativeFontColor(color); @@ -213,7 +213,7 @@ void EditBoxImplCommon::setPlaceholderFont(const char* pFontName, int fontSize) } } -void EditBoxImplCommon::setPlaceholderFontColor(const Color4B& color) +void EditBoxImplCommon::setPlaceholderFontColor(const Color32& color) { _colPlaceHolder = color; this->setNativePlaceholderFontColor(color); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-common.h b/axmol/ui/UIEditBox/UIEditBoxImpl-common.h similarity index 59% rename from core/ui/UIEditBox/UIEditBoxImpl-common.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-common.h index 0ba6ef754c18..6ea1e135f860 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-common.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-common.h @@ -28,10 +28,10 @@ #pragma once -#include "platform/PlatformConfig.h" -#include "2d/Label.h" -#include "ui/UIEditBox/UIEditBoxImpl-common.h" -#include "ui/UIEditBox/UIEditBoxImpl.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/2d/Label.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl.h" namespace ax { @@ -52,57 +52,57 @@ class AX_GUI_DLL EditBoxImplCommon : public EditBoxImpl */ virtual ~EditBoxImplCommon(); - virtual bool initWithSize(const Size& size) override; + bool initWithSize(const Size& size) override; - virtual void setFont(const char* pFontName, int fontSize) override; - virtual void setFontColor(const Color4B& color) override; - virtual void setPlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setPlaceholderFontColor(const Color4B& color) override; - virtual void setInputMode(EditBox::InputMode inputMode) override; - virtual void setInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setText(const char* pText) override; - virtual void setPlaceHolder(const char* pText) override; - virtual void setVisible(bool visible) override; + void setFont(const char* pFontName, int fontSize) override; + void setFontColor(const Color32& color) override; + void setPlaceholderFont(const char* pFontName, int fontSize) override; + void setPlaceholderFontColor(const Color32& color) override; + void setInputMode(EditBox::InputMode inputMode) override; + void setInputFlag(EditBox::InputFlag inputFlag) override; + void setReturnType(EditBox::KeyboardReturnType returnType) override; + void setText(const char* pText) override; + void setPlaceHolder(const char* pText) override; + void setVisible(bool visible) override; - virtual void setMaxLength(int maxLength) override; - virtual void setTextHorizontalAlignment(TextHAlignment alignment) override; + void setMaxLength(int maxLength) override; + void setTextHorizontalAlignment(TextHAlignment alignment) override; - virtual int getMaxLength() override { return _maxLength; } - virtual const char* getText() override { return _text.c_str(); } - virtual const char* getPlaceHolder() override { return _placeHolder.c_str(); } + int getMaxLength() override { return _maxLength; } + const char* getText() override { return _text.c_str(); } + const char* getPlaceHolder() override { return _placeHolder.c_str(); } - virtual const char* getFontName() override { return _fontName.c_str(); } - virtual int getFontSize() override { return _fontSize; } - virtual const Color4B& getFontColor() override { return _colText; } + const char* getFontName() override { return _fontName.c_str(); } + int getFontSize() override { return _fontSize; } + const Color32& getFontColor() override { return _colText; } - virtual const char* getPlaceholderFontName() override { return _placeholderFontName.c_str(); } - virtual int getPlaceholderFontSize() override { return _placeholderFontSize; } - virtual const Color4B& getPlaceholderFontColor() override { return _colPlaceHolder; } + const char* getPlaceholderFontName() override { return _placeholderFontName.c_str(); } + int getPlaceholderFontSize() override { return _placeholderFontSize; } + const Color32& getPlaceholderFontColor() override { return _colPlaceHolder; } - virtual EditBox::InputMode getInputMode() override { return _editBoxInputMode; } - virtual EditBox::InputFlag getInputFlag() override { return _editBoxInputFlag; } - virtual EditBox::KeyboardReturnType getReturnType() override { return _keyboardReturnType; } - virtual TextHAlignment getTextHorizontalAlignment() override { return _alignment; } + EditBox::InputMode getInputMode() override { return _editBoxInputMode; } + EditBox::InputFlag getInputFlag() override { return _editBoxInputFlag; } + EditBox::KeyboardReturnType getReturnType() override { return _keyboardReturnType; } + TextHAlignment getTextHorizontalAlignment() override { return _alignment; } virtual void refreshInactiveText(); - virtual void setContentSize(const Size& size) override; + void setContentSize(const Size& size) override; - virtual void setAnchorPoint(const Vec2& anchorPoint) override {} - virtual void setPosition(const Vec2& pos) override {} - virtual void setGlobalZOrder(float globalZOrder) override; + void setAnchorPoint(const Vec2& anchorPoint) override {} + void setPosition(const Vec2& pos) override {} + void setGlobalZOrder(float globalZOrder) override; /** * @lua NA */ - virtual void draw(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void draw(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** * @lua NA */ - virtual void onEnter() override; - virtual void openKeyboard() override; - virtual void closeKeyboard() override; + void onEnter() override; + void openKeyboard() override; + void closeKeyboard() override; virtual void onEndEditing(std::string_view text); @@ -111,12 +111,12 @@ class AX_GUI_DLL EditBoxImplCommon : public EditBoxImpl void editBoxEditingDidEnd(std::string_view text, EditBoxDelegate::EditBoxEndAction action = EditBoxDelegate::EditBoxEndAction::UNKNOWN); - virtual bool isEditing() override = 0; + bool isEditing() override = 0; virtual void createNativeControl(const Rect& frame) = 0; virtual void setNativeFont(const char* pFontName, int fontSize) = 0; - virtual void setNativeFontColor(const Color4B& color) = 0; + virtual void setNativeFontColor(const Color32& color) = 0; virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) = 0; - virtual void setNativePlaceholderFontColor(const Color4B& color) = 0; + virtual void setNativePlaceholderFontColor(const Color32& color) = 0; virtual void setNativeInputMode(EditBox::InputMode inputMode) = 0; virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) = 0; virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) = 0; @@ -135,7 +135,7 @@ class AX_GUI_DLL EditBoxImplCommon : public EditBoxImpl void setInactiveText(const char* pText); void refreshLabelAlignment(); void placeInactiveLabels(const Size& size); - virtual void doAnimationWhenKeyboardMove(float duration, float distance) override{}; + void doAnimationWhenKeyboardMove(float duration, float distance) override{}; Label* _label; Label* _labelPlaceHolder; @@ -153,8 +153,8 @@ class AX_GUI_DLL EditBoxImplCommon : public EditBoxImpl int _fontSize; int _placeholderFontSize; - Color4B _colText; - Color4B _colPlaceHolder; + Color32 _colText; + Color32 _colPlaceHolder; int _maxLength; Size _contentSize; diff --git a/core/ui/UIEditBox/UIEditBoxImpl-ios.h b/axmol/ui/UIEditBox/UIEditBoxImpl-ios.h similarity index 59% rename from core/ui/UIEditBox/UIEditBoxImpl-ios.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-ios.h index 1df5143820e3..caf9f2395712 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-ios.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-ios.h @@ -29,7 +29,7 @@ #if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" @class UIEditBoxImplIOS_objc; @class UIFont; @@ -53,28 +53,28 @@ class EditBoxImplIOS : public EditBoxImplCommon */ virtual ~EditBoxImplIOS(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override; - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setNativePlaceholderFontColor(const Color4B& color) override; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override; - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; - virtual const char* getNativeDefaultFontName() override; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override; + bool isEditing() override; + void createNativeControl(const Rect& frame) override; + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override; + void setNativePlaceholderFontColor(const Color32& color) override; + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; + void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override; + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; + const char* getNativeDefaultFontName() override; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override; // need to remove siri text - virtual const char* getText() override; + const char* getText() override; - virtual void doAnimationWhenKeyboardMove(float duration, float distance) override; + void doAnimationWhenKeyboardMove(float duration, float distance) override; private: UIFont* constructFont(const char* fontName, int fontSize); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-ios.mm b/axmol/ui/UIEditBox/UIEditBoxImpl-ios.mm similarity index 94% rename from core/ui/UIEditBox/UIEditBoxImpl-ios.mm rename to axmol/ui/UIEditBox/UIEditBoxImpl-ios.mm index ce41a8dfbb02..c7b7199eea1b 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-ios.mm +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-ios.mm @@ -25,21 +25,21 @@ of this software and associated documentation files (the "Software"), to deal OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-ios.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-ios.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) # define kLabelZOrder 9999 -# include "ui/UIEditBox/UIEditBox.h" -# include "base/Director.h" -# include "2d/Label.h" -# import "platform/ios/EARenderView-ios.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" +# include "axmol/base/Director.h" +# include "axmol/2d/Label.h" +# import "axmol/platform/ios/EARenderView-ios.h" # import # import -# import "ui/UIEditBox/iOS/UIEditBoxIOS.h" +# import "axmol/ui/UIEditBox/iOS/UIEditBoxIOS.h" # define getEditBoxImplIOS() ((ax::ui::EditBoxImplIOS*)_editBox) @@ -100,7 +100,7 @@ of this software and associated documentation files (the "Software"), to deal } } -void EditBoxImplIOS::setNativeFontColor(const Color4B& color) +void EditBoxImplIOS::setNativeFontColor(const Color32& color) { _systemControl.textColor = [UIColor colorWithRed:color.r / 255.0f green:color.g / 255.0f @@ -117,7 +117,7 @@ of this software and associated documentation files (the "Software"), to deal } } -void EditBoxImplIOS::setNativePlaceholderFontColor(const Color4B& color) +void EditBoxImplIOS::setNativePlaceholderFontColor(const Color32& color) { [_systemControl setPlaceholderTextColor:[UIColor colorWithRed:color.r / 255.0f green:color.g / 255.0f diff --git a/core/ui/UIEditBox/UIEditBoxImpl-linux.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-linux.cpp similarity index 98% rename from core/ui/UIEditBox/UIEditBoxImpl-linux.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-linux.cpp index 43e6e4d17338..abb681c9b49e 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-linux.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-linux.cpp @@ -25,13 +25,13 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-linux.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-linux.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) -# include "ui/UIEditBox/UIEditBox.h" -# include "2d/Label.h" -# include "base/UTF8.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" +# include "axmol/2d/Label.h" +# include "axmol/base/text_utils.h" #include diff --git a/core/ui/UIEditBox/UIEditBoxImpl-linux.h b/axmol/ui/UIEditBox/UIEditBoxImpl-linux.h similarity index 58% rename from core/ui/UIEditBox/UIEditBoxImpl-linux.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-linux.h index 3cc29bd13443..286fac2c0c50 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-linux.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-linux.h @@ -27,11 +27,11 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" namespace ax { @@ -54,27 +54,27 @@ class EditBoxImplLinux : public EditBoxImplCommon */ virtual ~EditBoxImplLinux(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override{}; - virtual void setNativeFont(const char* pFontName, int fontSize) override{}; - virtual void setNativeFontColor(const Color4B& color) override{}; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override{}; - virtual void setNativePlaceholderFontColor(const Color4B& color) override{}; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override{}; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override{}; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override{}; + bool isEditing() override; + void createNativeControl(const Rect& frame) override{}; + void setNativeFont(const char* pFontName, int fontSize) override{}; + void setNativeFontColor(const Color32& color) override{}; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override{}; + void setNativePlaceholderFontColor(const Color32& color) override{}; + void setNativeInputMode(EditBox::InputMode inputMode) override{}; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override{}; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override{}; virtual void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment){}; - virtual void setNativeText(const char* pText) override{}; - virtual void setNativePlaceHolder(const char* pText) override{}; - virtual void setNativeVisible(bool visible) override{}; - virtual void updateNativeFrame(const Rect& rect) override{}; - virtual const char* getNativeDefaultFontName() override{ return ""; }; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override{}; - virtual void setNativeMaxLength(int maxLength) override{}; + void setNativeText(const char* pText) override{}; + void setNativePlaceHolder(const char* pText) override{}; + void setNativeVisible(bool visible) override{}; + void updateNativeFrame(const Rect& rect) override{}; + const char* getNativeDefaultFontName() override{ return ""; }; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override{}; + void setNativeMaxLength(int maxLength) override{}; private: - virtual void doAnimationWhenKeyboardMove(float duration, float distance) override {} + void doAnimationWhenKeyboardMove(float duration, float distance) override {} }; } // namespace ui diff --git a/core/ui/UIEditBox/UIEditBoxImpl-mac.h b/axmol/ui/UIEditBox/UIEditBoxImpl-mac.h similarity index 59% rename from core/ui/UIEditBox/UIEditBoxImpl-mac.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-mac.h index 8f76fb71ff05..2fd09941cbac 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-mac.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-mac.h @@ -27,11 +27,11 @@ #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" @class UIEditBoxImplMac; @class NSFont; @@ -55,24 +55,24 @@ class EditBoxImplMac : public EditBoxImplCommon */ virtual ~EditBoxImplMac(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override; - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setNativePlaceholderFontColor(const Color4B& color) override; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override; - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; - virtual const char* getNativeDefaultFontName() override; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override; - virtual void setNativeMaxLength(int maxLength) override; + bool isEditing() override; + void createNativeControl(const Rect& frame) override; + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override; + void setNativePlaceholderFontColor(const Color32& color) override; + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; + void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment) override; + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override; + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; + const char* getNativeDefaultFontName() override; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override; + void setNativeMaxLength(int maxLength) override; private: NSFont* constructFont(const char* fontName, int fontSize); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-mac.mm b/axmol/ui/UIEditBox/UIEditBoxImpl-mac.mm similarity index 95% rename from core/ui/UIEditBox/UIEditBoxImpl-mac.mm rename to axmol/ui/UIEditBox/UIEditBoxImpl-mac.mm index 26eb680caed8..bfb9f6719ea2 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-mac.mm +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-mac.mm @@ -25,14 +25,14 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) -# include "ui/UIEditBox/UIEditBoxImpl-mac.h" -# include "base/Director.h" -# include "base/UTF8.h" -# include "ui/UIEditBox/UIEditBox.h" -# include "ui/UIEditBox/Mac/UIEditBoxMac.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-mac.h" +# include "axmol/base/Director.h" +# include "axmol/base/text_utils.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" +# include "axmol/ui/UIEditBox/Mac/UIEditBoxMac.h" namespace ax { @@ -125,7 +125,7 @@ of this software and associated documentation files (the "Software"), to deal [_sysEdit setPlaceholderFont:textFont]; } -void EditBoxImplMac::setNativeFontColor(const ax::Color4B& color) +void EditBoxImplMac::setNativeFontColor(const ax::Color32& color) { NSColor* newColor = [NSColor colorWithCalibratedRed:color.r / 255.0f green:color.g / 255.0f @@ -135,7 +135,7 @@ of this software and associated documentation files (the "Software"), to deal [_sysEdit setTextColor:newColor]; } -void EditBoxImplMac::setNativePlaceholderFontColor(const ax::Color4B& color) +void EditBoxImplMac::setNativePlaceholderFontColor(const ax::Color32& color) { NSColor* newColor = [NSColor colorWithCalibratedRed:color.r / 255.f green:color.g / 255.f diff --git a/core/ui/UIEditBox/UIEditBoxImpl-stub.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-stub.cpp similarity index 97% rename from core/ui/UIEditBox/UIEditBoxImpl-stub.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-stub.cpp index 240e01f4e4a0..69e8481e2e5b 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-stub.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-stub.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" #if (AX_TARGET_PLATFORM != AX_PLATFORM_ANDROID) && (AX_TARGET_PLATFORM != AX_PLATFORM_IOS) && \ (AX_TARGET_PLATFORM != AX_PLATFORM_WIN32) && (AX_TARGET_PLATFORM != AX_PLATFORM_MAC) diff --git a/core/ui/UIEditBox/UIEditBoxImpl-wasm.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-wasm.cpp similarity index 94% rename from core/ui/UIEditBox/UIEditBoxImpl-wasm.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-wasm.cpp index b86b5eeff47f..6afc414f73fa 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-wasm.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-wasm.cpp @@ -27,10 +27,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-wasm.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-wasm.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "ui/UIHelper.h" +# include "axmol/ui/UIHelper.h" # include namespace ax { @@ -42,11 +42,12 @@ extern "C" { EMSCRIPTEN_KEEPALIVE void getInputOver(char* dataPtr, int dataLength) { - AXLOGD("text {} ", dataPtr); + std::string_view text{ dataPtr, static_cast(dataLength) }; + AXLOGD("text {} ", text); if (_activeEditBox) { if (_activeEditBox->isEditingMode()) - _activeEditBox->editBoxEditingDidEnd(std::string_view{(char*)dataPtr}, + _activeEditBox->editBoxEditingDidEnd(text, EditBoxDelegate::EditBoxEndAction::RETURN); _activeEditBox = nullptr; } @@ -57,10 +58,11 @@ EMSCRIPTEN_KEEPALIVE void getInputChange(char* dataPtr, int dataLength) { - AXLOGD("text {} ", dataPtr); + std::string_view text{ dataPtr, static_cast(dataLength) }; + AXLOGD("text {} ", text); if (_activeEditBox && _activeEditBox->isEditingMode()) { - _activeEditBox->editBoxEditingChanged(std::string_view{(char*)dataPtr}); + _activeEditBox->editBoxEditingChanged(text); } free(dataPtr); } @@ -109,7 +111,7 @@ void EditBoxImplWasm::setNativeFont(const char* pFontName, int fontSize) fontSize); } -void EditBoxImplWasm::setNativeFontColor(const Color4B& color) +void EditBoxImplWasm::setNativeFontColor(const Color32& color) { // not implemented yet } @@ -119,7 +121,7 @@ void EditBoxImplWasm::setNativePlaceholderFont(const char* pFontName, int fontSi // not implemented yet } -void EditBoxImplWasm::setNativePlaceholderFontColor(const Color4B& color) +void EditBoxImplWasm::setNativePlaceholderFontColor(const Color32& color) { // not implemented yet } diff --git a/core/ui/UIEditBox/UIEditBoxImpl-wasm.h b/axmol/ui/UIEditBox/UIEditBoxImpl-wasm.h similarity index 59% rename from core/ui/UIEditBox/UIEditBoxImpl-wasm.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-wasm.h index 6d411a1cd04b..5eb708f2589e 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-wasm.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-wasm.h @@ -25,10 +25,10 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WASM -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" namespace ax { @@ -44,24 +44,24 @@ class AX_API EditBoxImplWasm : public EditBoxImplCommon EditBoxImplWasm(EditBox* pEditText); virtual ~EditBoxImplWasm(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override; - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setNativePlaceholderFontColor(const Color4B& color) override; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setNativeTextHorizontalAlignment(TextHAlignment alignment) override; - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override; - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; - virtual const char* getNativeDefaultFontName() override; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override; - virtual void setNativeMaxLength(int maxLength) override; + bool isEditing() override; + void createNativeControl(const Rect& frame) override; + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override; + void setNativePlaceholderFontColor(const Color32& color) override; + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; + void setNativeTextHorizontalAlignment(TextHAlignment alignment) override; + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override; + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; + const char* getNativeDefaultFontName() override; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override; + void setNativeMaxLength(int maxLength) override; //EditBoxDelegate::EditBoxEndAction _endAction; bool isEditingMode() const { return _editingMode; } private: diff --git a/core/ui/UIEditBox/UIEditBoxImpl-win32.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-win32.cpp similarity index 96% rename from core/ui/UIEditBox/UIEditBoxImpl-win32.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-win32.cpp index fc0b0e3b1d14..1954a95ed1d7 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-win32.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-win32.cpp @@ -25,20 +25,20 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIEditBox/UIEditBoxImpl-win32.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-win32.h" -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "ui/UIEditBox/UIEditBox.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" # include # include -# include "2d/Label.h" -# include "base/Director.h" -# include "base/UTF8.h" +# include "axmol/2d/Label.h" +# include "axmol/base/Director.h" +# include "axmol/base/text_utils.h" # include # include -# include "ui/UIHelper.h" +# include "axmol/ui/UIHelper.h" namespace ax { @@ -154,7 +154,7 @@ void EditBoxImplWin::setNativeFont(const char* pFontName, int fontSize) ); } -void EditBoxImplWin::setNativeFontColor(const Color4B& color) +void EditBoxImplWin::setNativeFontColor(const Color32& color) { // not implemented yet } @@ -164,7 +164,7 @@ void EditBoxImplWin::setNativePlaceholderFont(const char* pFontName, int fontSiz // not implemented yet } -void EditBoxImplWin::setNativePlaceholderFontColor(const Color4B& color) +void EditBoxImplWin::setNativePlaceholderFontColor(const Color32& color) { // not implemented yet } @@ -241,7 +241,7 @@ void EditBoxImplWin::setNativeText(const char* pText) { std::u16string utf16Result; std::string text(pText); - ax::StringUtils::UTF8ToUTF16(text, utf16Result); + ax::text_utils::UTF8ToUTF16(text, utf16Result); this->_changedTextManually = true; ::SetWindowTextW(_hwndEdit, (LPCWSTR)utf16Result.c_str()); int textLen = text.size(); @@ -401,7 +401,7 @@ std::string EditBoxImplWin::getText() const wstrResult.resize(inputLength); ::GetWindowTextW(_hwndEdit, (LPWSTR)&wstrResult[0], inputLength + 1); - bool conversionResult = ax::StringUtils::UTF16ToUTF8(wstrResult, utf8Result); + bool conversionResult = ax::text_utils::UTF16ToUTF8(wstrResult, utf8Result); if (!conversionResult) { AXLOGW("warning, editbox input text conversion error."); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-win32.h b/axmol/ui/UIEditBox/UIEditBoxImpl-win32.h similarity index 65% rename from core/ui/UIEditBox/UIEditBoxImpl-win32.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-win32.h index 5a46c06281b2..3daf99c4779b 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-win32.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-win32.h @@ -27,10 +27,10 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "ui/UIEditBox/UIEditBoxImpl-common.h" +# include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" namespace ax { @@ -46,24 +46,24 @@ class AX_GUI_DLL EditBoxImplWin : public EditBoxImplCommon EditBoxImplWin(EditBox* pEditText); virtual ~EditBoxImplWin(); - virtual bool isEditing() override; - virtual void createNativeControl(const Rect& frame) override; - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override; - virtual void setNativePlaceholderFontColor(const Color4B& color) override; - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; - virtual void setNativeTextHorizontalAlignment(TextHAlignment alignment) override; - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override; - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; - virtual const char* getNativeDefaultFontName() override; - virtual void nativeOpenKeyboard() override; - virtual void nativeCloseKeyboard() override; - virtual void setNativeMaxLength(int maxLength) override; + bool isEditing() override; + void createNativeControl(const Rect& frame) override; + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override; + void setNativePlaceholderFontColor(const Color32& color) override; + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override; + void setNativeTextHorizontalAlignment(TextHAlignment alignment) override; + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override; + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; + const char* getNativeDefaultFontName() override; + void nativeOpenKeyboard() override; + void nativeCloseKeyboard() override; + void setNativeMaxLength(int maxLength) override; private: void createEditCtrl(bool singleLine); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-winrt.cpp b/axmol/ui/UIEditBox/UIEditBoxImpl-winrt.cpp similarity index 98% rename from core/ui/UIEditBox/UIEditBoxImpl-winrt.cpp rename to axmol/ui/UIEditBox/UIEditBoxImpl-winrt.cpp index 0d4b3fa8e87f..215a3edb8a87 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-winrt.cpp +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-winrt.cpp @@ -27,12 +27,12 @@ //THE SOFTWARE. //****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) -#include "ui/UIEditBox/UIEditBoxImpl-winrt.h" -#include "platform/winrt/WinRTUtils.h" -#include "platform/winrt/RenderViewImpl-winrt.h" -#include "2d/FontFreeType.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-winrt.h" +#include "axmol/platform/winrt/WinRTUtils.h" +#include "axmol/platform/winrt/RenderViewImpl-winrt.h" +#include "axmol/2d/FontFreeType.h" #include #include @@ -470,7 +470,7 @@ void UIEditBoxImplWinrt::setNativeFont(const char* pFontName, int fontSize) } } -void UIEditBoxImplWinrt::setNativeFontColor(const Color4B& color) +void UIEditBoxImplWinrt::setNativeFontColor(const Color32& color) { Windows::UI::Color win_color = {0xFF, color.r, color.g, color.b}; _system_control->setFontColor(win_color); diff --git a/core/ui/UIEditBox/UIEditBoxImpl-winrt.h b/axmol/ui/UIEditBox/UIEditBoxImpl-winrt.h similarity index 77% rename from core/ui/UIEditBox/UIEditBoxImpl-winrt.h rename to axmol/ui/UIEditBox/UIEditBoxImpl-winrt.h index adf2e72886a2..59b2050012a1 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl-winrt.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl-winrt.h @@ -26,9 +26,9 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_WINRT -#include "ui/UIEditBox/UIEditBoxImpl-common.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-common.h" #include #include @@ -127,28 +127,28 @@ namespace ui { */ virtual ~UIEditBoxImplWinrt() { }; - virtual bool isEditing() override { return _system_control.get()->isEditing(); } - virtual void createNativeControl(const Rect& frame) override { } - virtual void setNativeFont(const char* pFontName, int fontSize) override; - virtual void setNativeFontColor(const Color4B& color) override; - virtual void setNativePlaceholderFont(const char* pFontName, int fontSize) override { AXLOGD("Warning! You can't change WinRT placeholder font"); } - virtual void setNativePlaceholderFontColor(const Color4B& color) override { AXLOGD("Warning! You can't change WinRT placeholder font color"); } - virtual void setNativeInputMode(EditBox::InputMode inputMode) override; - virtual void setNativeInputFlag(EditBox::InputFlag inputFlag) override; - virtual void setNativeReturnType(EditBox::KeyboardReturnType returnType) override { AXLOGD("Warning! You can't change WinRT return type"); } + bool isEditing() override { return _system_control.get()->isEditing(); } + void createNativeControl(const Rect& frame) override { } + void setNativeFont(const char* pFontName, int fontSize) override; + void setNativeFontColor(const Color32& color) override; + void setNativePlaceholderFont(const char* pFontName, int fontSize) override { AXLOGD("Warning! You can't change WinRT placeholder font"); } + void setNativePlaceholderFontColor(const Color32& color) override { AXLOGD("Warning! You can't change WinRT placeholder font color"); } + void setNativeInputMode(EditBox::InputMode inputMode) override; + void setNativeInputFlag(EditBox::InputFlag inputFlag) override; + void setNativeReturnType(EditBox::KeyboardReturnType returnType) override { AXLOGD("Warning! You can't change WinRT return type"); } virtual void setNativeTextHorizontalAlignment(ax::TextHAlignment alignment); - virtual void setNativeText(const char* pText) override; - virtual void setNativePlaceHolder(const char* pText) override { AXLOGD("Warning! You can't change WinRT placeholder text"); } - virtual void setNativeVisible(bool visible) override; - virtual void updateNativeFrame(const Rect& rect) override; // TODO - virtual const char* getNativeDefaultFontName() override { return "Segoe UI"; } + void setNativeText(const char* pText) override; + void setNativePlaceHolder(const char* pText) override { AXLOGD("Warning! You can't change WinRT placeholder text"); } + void setNativeVisible(bool visible) override; + void updateNativeFrame(const Rect& rect) override; // TODO + const char* getNativeDefaultFontName() override { return "Segoe UI"; } virtual void nativeOpenKeyboard(); - virtual void nativeCloseKeyboard() override; - virtual void setNativeMaxLength(int maxLength) override; + void nativeCloseKeyboard() override; + void setNativeMaxLength(int maxLength) override; private: ax::Vec2 convertDesignCoordToXamlCoord(const ax::Vec2& designCoord); - virtual void doAnimationWhenKeyboardMove(float duration, float distance) override { AXLOGD("Warning! doAnimationWhenKeyboardMove not supported on WinRT"); } + void doAnimationWhenKeyboardMove(float duration, float distance) override { AXLOGD("Warning! doAnimationWhenKeyboardMove not supported on WinRT"); } winrt::agile_ref _system_control_agile; winrt::com_ptr _system_control{}; diff --git a/core/ui/UIEditBox/UIEditBoxImpl.h b/axmol/ui/UIEditBox/UIEditBoxImpl.h similarity index 94% rename from core/ui/UIEditBox/UIEditBoxImpl.h rename to axmol/ui/UIEditBox/UIEditBoxImpl.h index 07adbe30de43..1e83687b5750 100644 --- a/core/ui/UIEditBox/UIEditBoxImpl.h +++ b/axmol/ui/UIEditBox/UIEditBoxImpl.h @@ -27,7 +27,7 @@ #pragma once -#include "ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" namespace ax { @@ -48,9 +48,9 @@ class AX_GUI_DLL EditBoxImpl virtual bool initWithSize(const Size& size) = 0; virtual void setFont(const char* pFontName, int fontSize) = 0; - virtual void setFontColor(const Color4B& color) = 0; + virtual void setFontColor(const Color32& color) = 0; virtual void setPlaceholderFont(const char* pFontName, int fontSize) = 0; - virtual void setPlaceholderFontColor(const Color4B& color) = 0; + virtual void setPlaceholderFontColor(const Color32& color) = 0; virtual void setInputMode(EditBox::InputMode inputMode) = 0; virtual void setInputFlag(EditBox::InputFlag inputFlag) = 0; virtual void setMaxLength(int maxLength) = 0; @@ -66,11 +66,11 @@ class AX_GUI_DLL EditBoxImpl virtual const char* getFontName() = 0; virtual int getFontSize() = 0; - virtual const Color4B& getFontColor() = 0; + virtual const Color32& getFontColor() = 0; virtual const char* getPlaceholderFontName() = 0; virtual int getPlaceholderFontSize() = 0; - virtual const Color4B& getPlaceholderFontColor() = 0; + virtual const Color32& getPlaceholderFontColor() = 0; virtual EditBox::InputMode getInputMode() = 0; virtual EditBox::InputFlag getInputFlag() = 0; diff --git a/core/ui/UIEditBox/iOS/UIEditBoxIOS.h b/axmol/ui/UIEditBox/iOS/UIEditBoxIOS.h similarity index 96% rename from core/ui/UIEditBox/iOS/UIEditBoxIOS.h rename to axmol/ui/UIEditBox/iOS/UIEditBoxIOS.h index 7f5be2a5133b..2160c139b008 100644 --- a/core/ui/UIEditBox/iOS/UIEditBoxIOS.h +++ b/axmol/ui/UIEditBox/iOS/UIEditBoxIOS.h @@ -28,8 +28,8 @@ #pragma once #import -#import "ui/UIEditBox/iOS/UITextInput.h" -#include "ui/UIEditBox/UIEditBoxImpl-ios.h" +#import "axmol/ui/UIEditBox/iOS/UITextInput.h" +#include "axmol/ui/UIEditBox/UIEditBoxImpl-ios.h" @interface UIEditBoxImplIOS_objc : NSObject diff --git a/core/ui/UIEditBox/iOS/UIEditBoxIOS.mm b/axmol/ui/UIEditBox/iOS/UIEditBoxIOS.mm similarity index 98% rename from core/ui/UIEditBox/iOS/UIEditBoxIOS.mm rename to axmol/ui/UIEditBox/iOS/UIEditBoxIOS.mm index 4eab0b143a2a..6a22047eee04 100644 --- a/core/ui/UIEditBox/iOS/UIEditBoxIOS.mm +++ b/axmol/ui/UIEditBox/iOS/UIEditBoxIOS.mm @@ -26,12 +26,12 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/iOS/UIEditBoxIOS.h" -#import "ui/UIEditBox/iOS/UISingleLineTextField.h" -#import "ui/UIEditBox/iOS/UIMultilineTextField.h" +#import "axmol/ui/UIEditBox/iOS/UIEditBoxIOS.h" +#import "axmol/ui/UIEditBox/iOS/UISingleLineTextField.h" +#import "axmol/ui/UIEditBox/iOS/UIMultilineTextField.h" -#import "platform/ios/EARenderView-ios.h" -#include "base/Director.h" +#import "axmol/platform/ios/EARenderView-ios.h" +#include "axmol/base/Director.h" #define getEditBoxImplIOS() ((ax::ui::EditBoxImplIOS*)_editBox) diff --git a/core/ui/UIEditBox/iOS/UIMultilineTextField.h b/axmol/ui/UIEditBox/iOS/UIMultilineTextField.h similarity index 96% rename from core/ui/UIEditBox/iOS/UIMultilineTextField.h rename to axmol/ui/UIEditBox/iOS/UIMultilineTextField.h index eb52db426ee2..4bf84115b17e 100644 --- a/core/ui/UIEditBox/iOS/UIMultilineTextField.h +++ b/axmol/ui/UIEditBox/iOS/UIMultilineTextField.h @@ -27,7 +27,7 @@ #pragma once #import -#import "ui/UIEditBox/iOS/UITextView+UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextView+UITextInput.h" #pragma mark - UIMultilineTextField implementation diff --git a/core/ui/UIEditBox/iOS/UIMultilineTextField.mm b/axmol/ui/UIEditBox/iOS/UIMultilineTextField.mm similarity index 98% rename from core/ui/UIEditBox/iOS/UIMultilineTextField.mm rename to axmol/ui/UIEditBox/iOS/UIMultilineTextField.mm index 1f5661cdb43c..61bcc84123bd 100644 --- a/core/ui/UIEditBox/iOS/UIMultilineTextField.mm +++ b/axmol/ui/UIEditBox/iOS/UIMultilineTextField.mm @@ -25,9 +25,9 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/iOS/UIMultilineTextField.h" +#import "axmol/ui/UIEditBox/iOS/UIMultilineTextField.h" -#include "base/Director.h" +#include "axmol/base/Director.h" /** * http://stackoverflow.com/questions/1328638/placeholder-in-uitextview diff --git a/core/ui/UIEditBox/iOS/UISingleLineTextField.h b/axmol/ui/UIEditBox/iOS/UISingleLineTextField.h similarity index 96% rename from core/ui/UIEditBox/iOS/UISingleLineTextField.h rename to axmol/ui/UIEditBox/iOS/UISingleLineTextField.h index 0a9bfe4b855b..ef5443f1249c 100644 --- a/core/ui/UIEditBox/iOS/UISingleLineTextField.h +++ b/axmol/ui/UIEditBox/iOS/UISingleLineTextField.h @@ -27,7 +27,7 @@ #pragma once #import -#import "ui/UIEditBox/iOS/UITextField+UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextField+UITextInput.h" #pragma mark - UISingleLineTextField implementation diff --git a/core/ui/UIEditBox/iOS/UISingleLineTextField.mm b/axmol/ui/UIEditBox/iOS/UISingleLineTextField.mm similarity index 95% rename from core/ui/UIEditBox/iOS/UISingleLineTextField.mm rename to axmol/ui/UIEditBox/iOS/UISingleLineTextField.mm index d96be74640ec..565332c7e8da 100644 --- a/core/ui/UIEditBox/iOS/UISingleLineTextField.mm +++ b/axmol/ui/UIEditBox/iOS/UISingleLineTextField.mm @@ -25,10 +25,10 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/iOS/UISingleLineTextField.h" -#import "ui/UIEditBox/iOS/UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UISingleLineTextField.h" +#import "axmol/ui/UIEditBox/iOS/UITextInput.h" -#include "base/Director.h" +#include "axmol/base/Director.h" /** * http://stackoverflow.com/questions/18244790/changing-uitextfield-placeholder-font diff --git a/core/ui/UIEditBox/iOS/UITextField+UITextInput.h b/axmol/ui/UIEditBox/iOS/UITextField+UITextInput.h similarity index 97% rename from core/ui/UIEditBox/iOS/UITextField+UITextInput.h rename to axmol/ui/UIEditBox/iOS/UITextField+UITextInput.h index 3deac2f2ac89..4d7afd4ad85f 100644 --- a/core/ui/UIEditBox/iOS/UITextField+UITextInput.h +++ b/axmol/ui/UIEditBox/iOS/UITextField+UITextInput.h @@ -25,7 +25,7 @@ #pragma once #import -#import "ui/UIEditBox/iOS/UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextInput.h" @interface UITextField (AXUITextInput) @end diff --git a/core/ui/UIEditBox/iOS/UITextField+UITextInput.mm b/axmol/ui/UIEditBox/iOS/UITextField+UITextInput.mm similarity index 98% rename from core/ui/UIEditBox/iOS/UITextField+UITextInput.mm rename to axmol/ui/UIEditBox/iOS/UITextField+UITextInput.mm index ef51c6776078..17a69a37b4ef 100644 --- a/core/ui/UIEditBox/iOS/UITextField+UITextInput.mm +++ b/axmol/ui/UIEditBox/iOS/UITextField+UITextInput.mm @@ -23,7 +23,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/iOS/UITextField+UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextField+UITextInput.h" @implementation UITextField (AXUITextInput) diff --git a/core/ui/UIEditBox/iOS/UITextInput.h b/axmol/ui/UIEditBox/iOS/UITextInput.h similarity index 100% rename from core/ui/UIEditBox/iOS/UITextInput.h rename to axmol/ui/UIEditBox/iOS/UITextInput.h diff --git a/core/ui/UIEditBox/iOS/UITextView+UITextInput.h b/axmol/ui/UIEditBox/iOS/UITextView+UITextInput.h similarity index 97% rename from core/ui/UIEditBox/iOS/UITextView+UITextInput.h rename to axmol/ui/UIEditBox/iOS/UITextView+UITextInput.h index d0e6241bebb5..69c761cb8fde 100644 --- a/core/ui/UIEditBox/iOS/UITextView+UITextInput.h +++ b/axmol/ui/UIEditBox/iOS/UITextView+UITextInput.h @@ -25,7 +25,7 @@ #pragma once #import -#import "ui/UIEditBox/iOS/UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextInput.h" @interface UITextView (AXUITextInput) @end diff --git a/core/ui/UIEditBox/iOS/UITextView+UITextInput.mm b/axmol/ui/UIEditBox/iOS/UITextView+UITextInput.mm similarity index 98% rename from core/ui/UIEditBox/iOS/UITextView+UITextInput.mm rename to axmol/ui/UIEditBox/iOS/UITextView+UITextInput.mm index aeb192df6a4c..3bae4adf1d64 100644 --- a/core/ui/UIEditBox/iOS/UITextView+UITextInput.mm +++ b/axmol/ui/UIEditBox/iOS/UITextView+UITextInput.mm @@ -23,7 +23,7 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#import "ui/UIEditBox/iOS/UITextView+UITextInput.h" +#import "axmol/ui/UIEditBox/iOS/UITextView+UITextInput.h" @implementation UITextView (AXUITextInput) diff --git a/core/ui/UIHBox.cpp b/axmol/ui/UIHBox.cpp similarity index 98% rename from core/ui/UIHBox.cpp rename to axmol/ui/UIHBox.cpp index 6467f102cb4c..74bab14244db 100644 --- a/core/ui/UIHBox.cpp +++ b/axmol/ui/UIHBox.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIHBox.h" +#include "axmol/ui/UIHBox.h" namespace ax { diff --git a/core/ui/UIHBox.h b/axmol/ui/UIHBox.h similarity index 96% rename from core/ui/UIHBox.h rename to axmol/ui/UIHBox.h index fa8c6892452c..62758520ae17 100644 --- a/core/ui/UIHBox.h +++ b/axmol/ui/UIHBox.h @@ -26,8 +26,8 @@ #pragma once -#include "ui/UILayout.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -72,7 +72,7 @@ class AX_GUI_DLL HBox : public Layout static HBox* create(const Vec2& size); // initializes state of widget. - virtual bool init() override; + bool init() override; virtual bool initWithSize(const Vec2& size); }; diff --git a/core/ui/LayoutHelper.cpp b/axmol/ui/UIHelper.cpp similarity index 54% rename from core/ui/LayoutHelper.cpp rename to axmol/ui/UIHelper.cpp index 8108d078fd48..3df7ec47a6e9 100644 --- a/core/ui/LayoutHelper.cpp +++ b/axmol/ui/UIHelper.cpp @@ -1,21 +1,223 @@ -// -// Copyright (c) 2014-2020 Simdsoft Limited - All Rights Reserved -// Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). -// -#include "ui/LayoutHelper.h" +/**************************************************************************** +Copyright (c) 2013-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2014-2020 Simdsoft Limited - All Rights Reserved +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). -using namespace ax; +https://axmol.dev/ -Vec2 LayoutHelper::s_designSize; -float LayoutHelper::s_adjustedScale = 1.0f; +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: -void LayoutHelper::setDesignSizeFixedEdge(const Vec2& designSize) +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ + +#include "axmol/ui/UIHelper.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/UILayoutComponent.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" + +namespace ax +{ + +namespace ui { - LayoutHelper::s_designSize = designSize; - // Set the design resolution//分辨率的大小 - RenderView* pERenderView = Director::getInstance()->getRenderView(); - const Vec2& frameSize = pERenderView->getFrameSize(); +static bool _activeLayout = true; + +Widget* Helper::seekWidgetByTag(Widget* root, int tag) +{ + if (!root) + { + return nullptr; + } + if (root->getTag() == tag) + { + return root; + } + const auto& arrayRootChildren = root->getChildren(); + ssize_t length = arrayRootChildren.size(); + for (ssize_t i = 0; i < length; i++) + { + Widget* child = dynamic_cast(arrayRootChildren.at(i)); + if (child) + { + Widget* res = seekWidgetByTag(child, tag); + if (res != nullptr) + { + return res; + } + } + } + return nullptr; +} + +Widget* Helper::seekWidgetByName(Widget* root, std::string_view name) +{ + if (!root) + { + return nullptr; + } + if (root->getName() == name) + { + return root; + } + const auto& arrayRootChildren = root->getChildren(); + for (auto&& subWidget : arrayRootChildren) + { + Widget* child = dynamic_cast(subWidget); + if (child) + { + Widget* res = seekWidgetByName(child, name); + if (res != nullptr) + { + return res; + } + } + } + return nullptr; +} + +/*temp action*/ +Widget* Helper::seekActionWidgetByActionTag(Widget* root, int tag) +{ + if (!root) + { + return nullptr; + } + if (root->getActionTag() == tag) + { + return root; + } + const auto& arrayRootChildren = root->getChildren(); + for (auto&& subWidget : arrayRootChildren) + { + Widget* child = dynamic_cast(subWidget); + if (child) + { + Widget* res = seekActionWidgetByActionTag(child, tag); + if (res != nullptr) + { + return res; + } + } + } + return nullptr; +} + +std::string Helper::getSubStringOfUTF8String(std::string_view str, + std::string::size_type start, + std::string::size_type length) +{ + std::u32string utf32; + if (!text_utils::UTF8ToUTF32(str, utf32)) + { + AXLOGE("Can't convert string to UTF-32: {}", str); + return ""; + } + if (utf32.size() < start) + { + AXLOGE("'start' is out of range: {}, {}", static_cast(start), str); + return ""; + } + std::string result; + if (!text_utils::UTF32ToUTF8(utf32.substr(start, length), result)) + { + AXLOGE("Can't convert internal UTF-32 string to UTF-8: {}", str); + return ""; + } + return result; +} + +void Helper::changeLayoutSystemActiveState(bool bActive) +{ + _activeLayout = bActive; +} +void Helper::doLayout(ax::Node* rootNode) +{ + if (!_activeLayout) + { + return; + } + + for (auto&& node : rootNode->getChildren()) + { + auto com = node->getComponent(__LAYOUT_COMPONENT_NAME); + Node* parent = node->getParent(); + if (nullptr != com && nullptr != parent) + { + LayoutComponent* layoutComponent = (LayoutComponent*)com; + + layoutComponent->refreshLayout(); + } + } +} + +Rect Helper::restrictCapInsetRect(const ax::Rect& capInsets, const Vec2& textureSize) +{ + float x = capInsets.origin.x; + float y = capInsets.origin.y; + float width = capInsets.size.width; + float height = capInsets.size.height; + + if (textureSize.width < width) + { + x = textureSize.width / 2.0f; + width = textureSize.width > 0 ? 1.0f : 0.0f; + } + if (textureSize.height < height) + { + y = textureSize.height / 2.0f; + height = textureSize.height > 0 ? 1.0f : 0.0f; + } + return Rect(x, y, width, height); +} + +Rect Helper::convertBoundingBoxToScreen(Node* node) +{ + auto director = Director::getInstance(); + auto renderView = director->getRenderView(); + auto frameSize = renderView->getFrameSize(); + + auto winSize = director->getWinSize(); + auto leftBottom = node->convertToWorldSpace(Point::ZERO); + + auto contentSize = node->getContentSize(); + auto rightTop = node->convertToWorldSpace(Point(contentSize.width, contentSize.height)); + + auto uiLeft = frameSize.width / 2 + (leftBottom.x - winSize.width / 2) * renderView->getScaleX(); + auto uiTop = frameSize.height / 2 - (rightTop.y - winSize.height / 2) * renderView->getScaleY(); + auto uiWidth = (rightTop.x - leftBottom.x) * renderView->getScaleX(); + auto uiHeight = (rightTop.y - leftBottom.y) * renderView->getScaleY(); + + return Rect(uiLeft, uiTop, uiWidth, uiHeight); +} + +#pragma region Layout helper +Vec2 Helper::s_designSize; +float Helper::s_adjustedScale = 1.0f; + +void Helper::setDesignSizeFixedEdge(const Vec2& designSize) +{ + Helper::s_designSize = designSize; + + // Set the design resolution + RenderView* pERenderView = Director::getInstance()->getRenderView(); + const Vec2& frameSize = pERenderView->getFrameSize(); // Vec2 lsSize = lsaSize; @@ -33,50 +235,51 @@ void LayoutHelper::setDesignSizeFixedEdge(const Vec2& designSize) } } -void LayoutHelper::setDesignSizeNoBorder(const Vec2& designSize) +void Helper::setDesignSizeNoBorder(const Vec2& designSize) { // save smart size - LayoutHelper::s_designSize = designSize; + Helper::s_designSize = designSize; - // Set the design resolution//分辨率的大小 - RenderView* pERenderView = Director::getInstance()->getRenderView(); - const Vec2& frameSize = pERenderView->getFrameSize(); + // Set the design resolution + RenderView* pERenderView = Director::getInstance()->getRenderView(); + const Vec2& frameSize = pERenderView->getFrameSize(); // Vec2 lsSize = lsaSize; - float scaleX = (float)frameSize.width / LayoutHelper::s_designSize.width; - float scaleY = (float)frameSize.height / LayoutHelper::s_designSize.height; + float scaleX = (float)frameSize.width / Helper::s_designSize.width; + float scaleY = (float)frameSize.height / Helper::s_designSize.height; - LayoutHelper::s_adjustedScale = 0.0f; // MAX(scaleX, scaleY); + Helper::s_adjustedScale = 0.0f; // MAX(scaleX, scaleY); if (scaleX > scaleY) { - LayoutHelper::s_adjustedScale = scaleX / (frameSize.height / LayoutHelper::s_designSize.height); + Helper::s_adjustedScale = scaleX / (frameSize.height / Helper::s_designSize.height); } else { - LayoutHelper::s_adjustedScale = scaleY / (frameSize.width / LayoutHelper::s_designSize.width); + Helper::s_adjustedScale = scaleY / (frameSize.width / Helper::s_designSize.width); } AXLOGD("x: {}; y: {}; scale: {}", scaleX, scaleY, s_adjustedScale); - pERenderView->setDesignResolutionSize(LayoutHelper::s_designSize.width * s_adjustedScale, - LayoutHelper::s_designSize.height * s_adjustedScale, ResolutionPolicy::NO_BORDER); + pERenderView->setDesignResolutionSize(Helper::s_designSize.width * s_adjustedScale, + Helper::s_designSize.height * s_adjustedScale, + ResolutionPolicy::NO_BORDER); } -ax::Vec2 LayoutHelper::getVisibleOrigin(void) +ax::Vec2 Helper::getVisibleOrigin(void) { const auto& adjustedDesignSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - return ax::Vec2((adjustedDesignSize.width - LayoutHelper::s_designSize.width) * .5f, - (adjustedDesignSize.height - LayoutHelper::s_designSize.height) * .5f); + return ax::Vec2((adjustedDesignSize.width - Helper::s_designSize.width) * .5f, + (adjustedDesignSize.height - Helper::s_designSize.height) * .5f); } -Vec2 LayoutHelper::getVisibleSize(void) +Vec2 Helper::getVisibleSize(void) { - return LayoutHelper::s_designSize; + return Helper::s_designSize; } /// Get node group size -Vec2 LayoutHelper::getNodeGroupSize(const std::vector& nodes) +Vec2 Helper::getNodeGroupSize(const std::vector& nodes) { if (nodes.empty()) { @@ -88,12 +291,12 @@ Vec2 LayoutHelper::getNodeGroupSize(const std::vector& nodes) maxX = getNodeLeft(nodes[0]) + nodes[0]->getContentSize().width /* * nodes[0]->getScaleX()*/; float minY = getNodeTop(nodes[0]), maxY = getNodeTop(nodes[0]) + nodes[0]->getContentSize().height /* * nodes[0]->getScaleY()*/; - float x = 0.0f, y = 0.0f; - // float width = 0.0f, height = 0.f; + for (size_t index = 1; index < nodes.size(); ++index) { Node* child = nodes[index]; - if (minX > (x = getNodeLeft(child))) + auto x = getNodeLeft(child); + if (minX > x) { minX = x; } @@ -102,7 +305,8 @@ Vec2 LayoutHelper::getNodeGroupSize(const std::vector& nodes) maxX = x + child->getContentSize().width /* * child->getScaleX()*/; } - if (minY > (y = getNodeTop(child))) + auto y = getNodeTop(child); + if (minY > y) { minY = y; } @@ -119,7 +323,7 @@ Vec2 LayoutHelper::getNodeGroupSize(const std::vector& nodes) } /// Set nodes group size -void LayoutHelper::setNodeGroupSize(const std::vector& nodes, const Vec2& newSize) +void Helper::setNodeGroupSize(const std::vector& nodes, const Vec2& newSize) { Vec2 groupSize = getNodeGroupScaledSize(nodes); if (groupSize.height == 0 || groupSize.width == 0 || newSize.width == 0 || newSize.height == 0) @@ -149,7 +353,7 @@ void LayoutHelper::setNodeGroupSize(const std::vector& nodes, const Vec2& } } -Vec2 LayoutHelper::getNodeGroupScaledSize(const std::vector& nodes) +Vec2 Helper::getNodeGroupScaledSize(const std::vector& nodes) { if (nodes.empty()) { @@ -159,19 +363,19 @@ Vec2 LayoutHelper::getNodeGroupScaledSize(const std::vector& nodes) auto scale = getScale2D(nodes[0]); // group nodes locators - float minX = LayoutHelper::getNodeLeft(nodes[0]), - maxX = LayoutHelper::getNodeLeft(nodes[0]) + nodes[0]->getContentSize().width * scale.x; - float minY = LayoutHelper::getNodeTop(nodes[0]), - maxY = LayoutHelper::getNodeTop(nodes[0]) + nodes[0]->getContentSize().height * scale.y; - float x = 0.0f, y = 0.0f; - // float width = 0.0f, height = 0.f; + float minX = Helper::getNodeLeft(nodes[0]), + maxX = Helper::getNodeLeft(nodes[0]) + nodes[0]->getContentSize().width * scale.x; + float minY = Helper::getNodeTop(nodes[0]), + maxY = Helper::getNodeTop(nodes[0]) + nodes[0]->getContentSize().height * scale.y; + for (size_t index = 1; index < nodes.size(); ++index) { Node* child = nodes[index]; scale = getScale2D(child); - if (minX > (x = LayoutHelper::getNodeLeft(child))) + auto x = Helper::getNodeLeft(child); + if (minX > x) { minX = x; } @@ -180,7 +384,8 @@ Vec2 LayoutHelper::getNodeGroupScaledSize(const std::vector& nodes) maxX = x + child->getContentSize().width * scale.x; } - if (minY > (y = LayoutHelper::getNodeTop(child))) + auto y = Helper::getNodeTop(child); + if (minY > y) { minY = y; } @@ -197,7 +402,7 @@ Vec2 LayoutHelper::getNodeGroupScaledSize(const std::vector& nodes) } /// Get Node group left -float LayoutHelper::getNodeGroupLeft(const std::vector& nodes) +float Helper::getNodeGroupLeft(const std::vector& nodes) { size_t index = 0; float minLeft = getNodeLeft(nodes[index]); @@ -212,7 +417,7 @@ float LayoutHelper::getNodeGroupLeft(const std::vector& nodes) } /// Get node group top -float LayoutHelper::getNodeGroupTop(const std::vector& nodes) +float Helper::getNodeGroupTop(const std::vector& nodes) { size_t index = 0; float minTop = getNodeTop(nodes[index]); @@ -227,7 +432,7 @@ float LayoutHelper::getNodeGroupTop(const std::vector& nodes) } /// Get node group right -float LayoutHelper::getNodeGroupRight(const std::vector& nodes) +float Helper::getNodeGroupRight(const std::vector& nodes) { size_t index = 0; float minRight = getNodeRight(nodes[index]); @@ -242,7 +447,7 @@ float LayoutHelper::getNodeGroupRight(const std::vector& nodes) } /// Get node group bottom -float LayoutHelper::getNodeGroupBottom(const std::vector& nodes) +float Helper::getNodeGroupBottom(const std::vector& nodes) { size_t index = 0; float minBottom = getNodeBottom(nodes[index]); @@ -260,7 +465,7 @@ float LayoutHelper::getNodeGroupBottom(const std::vector& nodes) ** setNodeGroupLeft ** */ -void LayoutHelper::setNodeGroupLeft(const std::vector& nodes, float left) +void Helper::setNodeGroupLeft(const std::vector& nodes, float left) { float delta = left - getNodeGroupLeft(nodes); @@ -274,7 +479,7 @@ void LayoutHelper::setNodeGroupLeft(const std::vector& nodes, float left) ** setNodeGroupLeft ** */ -void LayoutHelper::setNodeGroupTop(const std::vector& nodes, float top) +void Helper::setNodeGroupTop(const std::vector& nodes, float top) { float delta = top - getNodeGroupTop(nodes); @@ -284,7 +489,7 @@ void LayoutHelper::setNodeGroupTop(const std::vector& nodes, float top) } } -void LayoutHelper::setNodeGroupLT(const std::vector& nodes, const ax::Vec2& p) +void Helper::setNodeGroupLT(const std::vector& nodes, const ax::Vec2& p) { float deltaL = p.x - getNodeGroupLeft(nodes); float deltaT = p.y - getNodeGroupTop(nodes); @@ -299,7 +504,7 @@ void LayoutHelper::setNodeGroupLT(const std::vector& nodes, const ax::Vec ** setNodeGroupRight ** */ -void LayoutHelper::setNodeGroupRight(const std::vector& nodes, float right) +void Helper::setNodeGroupRight(const std::vector& nodes, float right) { float delta = right - getNodeGroupRight(nodes); @@ -313,7 +518,7 @@ void LayoutHelper::setNodeGroupRight(const std::vector& nodes, float righ ** setNodeGroupRight ** */ -void LayoutHelper::setNodeGroupBottom(const std::vector& nodes, float bottom) +void Helper::setNodeGroupBottom(const std::vector& nodes, float bottom) { float delta = bottom - getNodeGroupBottom(nodes); @@ -323,7 +528,7 @@ void LayoutHelper::setNodeGroupBottom(const std::vector& nodes, float bot } } -void LayoutHelper::moveNodeGroupHorizontally(const std::vector& nodes, float delta) +void Helper::moveNodeGroupHorizontally(const std::vector& nodes, float delta) { for (auto&& node : nodes) { @@ -331,7 +536,7 @@ void LayoutHelper::moveNodeGroupHorizontally(const std::vector& nodes, fl } } -void LayoutHelper::moveNodeGroupVertically(const std::vector& nodes, float delta) +void Helper::moveNodeGroupVertically(const std::vector& nodes, float delta) { for (auto&& node : nodes) { @@ -346,7 +551,7 @@ void LayoutHelper::moveNodeGroupVertically(const std::vector& nodes, floa /// 水平居中 /// /// -void LayoutHelper::centerHorizontally(const std::vector& nodes) +void Helper::centerHorizontally(const std::vector& nodes) { if (nodes.empty()) { @@ -360,24 +565,12 @@ void LayoutHelper::centerHorizontally(const std::vector& nodes) // group nodes locators float minX = getNodeLeft(nodes[0]), maxX = getNodeLeft(nodes[0]) + nodes[0]->getContentSize().width; - float x = 0.0f; - float width = 0.0f; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) - std::for_each(nodes.begin() + 1, nodes.end(), [&](Node* child) -> void { - if (minX > (x = getNodeLeft(child))) - { - minX = x; - } - if (maxX < x + child->getContentSize().width) - { - maxX = x + child->getContentSize().width; - } - }); -#else + for (size_t index = 1; index < nodes.size(); ++index) { Node* child = nodes[index]; - if (minX > (x = getNodeLeft(child))) + auto x = getNodeLeft(child); + if (minX > x) { minX = x; } @@ -386,26 +579,21 @@ void LayoutHelper::centerHorizontally(const std::vector& nodes) maxX = x + child->getContentSize().width; } } -#endif float groupWidth = maxX - minX; float dist = ((nodes[0]->getParent()->getContentSize().width - groupWidth) / 2.0f) - minX; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) - std::for_each(nodes.begin(), nodes.end(), - [dist](Node* child) -> void { setNodeLeft(child, getNodeLeft(child) + dist); }); -#else + for (size_t index = 0; index < nodes.size(); ++index) { Node* child = nodes[index]; setNodeLeft(child, getNodeLeft(child) + dist, 0); } -#endif } /// /// 垂直居中 /// /// -void LayoutHelper::centerVertically(const std::vector& nodes) +void Helper::centerVertically(const std::vector& nodes) { if (nodes.empty()) { @@ -420,8 +608,7 @@ void LayoutHelper::centerVertically(const std::vector& nodes) // group nodes locators float minY = getNodeTop(nodes[0]), maxY = getNodeTop(nodes[0]) + nodes[0]->getContentSize().height; float y = 0.0f; - float height = 0.0f; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) + std::for_each(nodes.begin() + 1, nodes.end(), [&](Node* child) -> void { if (minY > (y = getNodeTop(child))) { @@ -432,23 +619,18 @@ void LayoutHelper::centerVertically(const std::vector& nodes) maxY = y + child->getContentSize().height; } }); -#else -#endif float groupHeight = maxY - minY; float dist = ((nodes[0]->getParent()->getContentSize().height - groupHeight) / 2.0f) - minY; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) std::for_each(nodes.begin(), nodes.end(), [dist](Node* child) -> void { setNodeTop(child, getNodeTop(child) + dist); }); -#else -#endif } /// /// 居中 /// /// -void LayoutHelper::centerToParent(const std::vector& nodes) +void Helper::centerToParent(const std::vector& nodes) { if (nodes.empty()) { @@ -456,21 +638,17 @@ void LayoutHelper::centerToParent(const std::vector& nodes) } else if (nodes.size() == 1) { - LayoutHelper::centerNode(nodes[0]); + Helper::centerNode(nodes[0]); return; } // group nodes locators float minX = getNodeLeft(nodes[0]), maxX = getNodeLeft(nodes[0]) + nodes[0]->getContentSize().width; - float x = 0.0f; - float width = 0.0f; - float minY = getNodeTop(nodes[0]), maxY = getNodeTop(nodes[0]) + nodes[0]->getContentSize().height; - float y = 0.0f; - float height = 0.0f; std::for_each(nodes.begin() + 1, nodes.end(), [&](Node* child) -> void { - if (minX > (x = getNodeLeft(child))) + auto x = getNodeLeft(child); + if (minX > x) { minX = x; } @@ -478,7 +656,9 @@ void LayoutHelper::centerToParent(const std::vector& nodes) { maxX = x + child->getContentSize().width; } - if (minY > (y = getNodeTop(child))) + + auto y = getNodeTop(child); + if (minY > y) { minY = y; } @@ -503,7 +683,7 @@ void LayoutHelper::centerToParent(const std::vector& nodes) /// 左对齐 /// /// -void LayoutHelper::alignLefts(const std::vector& nodes) +void Helper::alignLefts(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -517,17 +697,14 @@ void LayoutHelper::alignLefts(const std::vector& nodes) minLeft = getNodeLeft(nodes[index]); } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) std::for_each(nodes.begin(), nodes.end(), [minLeft](Node* child) -> void { setNodeLeft(child, minLeft); }); -#else -#endif } /// /// 右对齐 /// /// -void LayoutHelper::alignRights(const std::vector& nodes) +void Helper::alignRights(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -542,18 +719,15 @@ void LayoutHelper::alignRights(const std::vector& nodes) } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) std::for_each(nodes.begin(), nodes.end(), [maxRight](Node* child) -> void { setNodeLeft(child, maxRight - child->getContentSize().width); }); -#else -#endif } /// /// 顶端对齐 /// /// -void LayoutHelper::alignTops(const std::vector& nodes) +void Helper::alignTops(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -567,17 +741,14 @@ void LayoutHelper::alignTops(const std::vector& nodes) minTop = getNodeTop(nodes[index]); } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) std::for_each(nodes.begin(), nodes.end(), [minTop](Node* child) -> void { setNodeTop(child, minTop); }); -#else -#endif } /// /// 底端对齐 /// /// -void LayoutHelper::alignBottoms(const std::vector& nodes) +void Helper::alignBottoms(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -591,31 +762,30 @@ void LayoutHelper::alignBottoms(const std::vector& nodes) maxBottom = getNodeTop(nodes[index]) + nodes[index]->getContentSize().height; } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) + std::for_each(nodes.begin(), nodes.end(), [maxBottom](Node* child) -> void { setNodeTop(child, maxBottom - child->getContentSize().height); }); -#else -#endif + } /// /// 水平对齐 /// /// -void LayoutHelper::alignHorizontals(const std::vector& nodes) +void Helper::alignHorizontals(const std::vector& nodes) { if (nodes.size() < 2) return; size_t index = 0; - float minCenterY, maxCenterY, centerY; + float minCenterY, maxCenterY; Node* child = nodes[index]; minCenterY = maxCenterY = getNodeBottom(child, 0.5f); // child.GetX(0.5f); for (index = 1; index < nodes.size(); ++index) { child = nodes[index]; - centerY = getNodeBottom(child, 0.5f); // child.GetX(0.5f); + auto centerY = getNodeBottom(child, 0.5f); // child.GetX(0.5f); if (minCenterY > centerY) { minCenterY = centerY; @@ -636,20 +806,20 @@ void LayoutHelper::alignHorizontals(const std::vector& nodes) /// 垂直对齐 /// /// -void LayoutHelper::alignVerticals(const std::vector& nodes) +void Helper::alignVerticals(const std::vector& nodes) { if (nodes.size() < 2) return; size_t index = 0; - float minCenterX, maxCenterX, centerX; + float minCenterX, maxCenterX; Node* child = nodes[index]; minCenterX = maxCenterX = getNodeLeft(child, 0.5f); // child.GetX(0.5f); for (index = 1; index < nodes.size(); ++index) { child = nodes[index]; - centerX = getNodeLeft(child, 0.5f); // child.GetX(0.5f); + auto centerX = getNodeLeft(child, 0.5f); // child.GetX(0.5f); if (minCenterX > centerX) { minCenterX = centerX; @@ -670,7 +840,7 @@ void LayoutHelper::alignVerticals(const std::vector& nodes) /// 中心原点对齐 /// /// -void LayoutHelper::alignCenters(const std::vector& nodes) +void Helper::alignCenters(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -683,7 +853,7 @@ void LayoutHelper::alignCenters(const std::vector& nodes) /// 使宽度相等 /// /// -void LayoutHelper::makeSameWidth(const std::vector& nodes) +void Helper::makeSameWidth(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -697,19 +867,17 @@ void LayoutHelper::makeSameWidth(const std::vector& nodes) maxWidth = nodes[index]->getContentSize().width; } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) + std::for_each(nodes.begin(), nodes.end(), [maxWidth](Node* child) -> void { child->setContentSize(Vec2(maxWidth, child->getContentSize().height)); }); -#else -#endif } /// /// 使高度相等 /// /// -void LayoutHelper::makeSameHeight(const std::vector& nodes) +void Helper::makeSameHeight(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -723,19 +891,17 @@ void LayoutHelper::makeSameHeight(const std::vector& nodes) minHeight = nodes[index]->getContentSize().height; } } -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) + std::for_each(nodes.begin(), nodes.end(), [minHeight](Node* child) -> void { child->setContentSize(Vec2(child->getContentSize().width, minHeight)); }); -#else -#endif } /// /// 使得大小相等 /// /// -void LayoutHelper::makeSameSize(const std::vector& nodes) +void Helper::makeSameSize(const std::vector& nodes) { if (nodes.size() < 2) return; @@ -748,26 +914,20 @@ void LayoutHelper::makeSameSize(const std::vector& nodes) /// 使水平间距相等 /// /// -void LayoutHelper::makeHorizontalSpacingEqual(std::vector& nodes) +void Helper::makeHorizontalSpacingEqual(std::vector& nodes) { if (nodes.size() < 3) return; - float avgHSpacing = 0; - Node *child, *childNext; - if (nodes.size() < 3) - return; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) // sort by x firstly std::sort(nodes.begin(), nodes.end(), [](Node* const left, Node* const right) { return getNodeLeft(left) < getNodeLeft(right); }); -#else -#endif + float avgHSpacing = 0; for (size_t index = 0; index < nodes.size() - 1; ++index) { - child = nodes[index]; - childNext = nodes[index + 1]; + auto child = nodes[index]; + auto childNext = nodes[index + 1]; avgHSpacing += (getNodeLeft(childNext) - getNodeLeft(child) - child->getContentSize().width); } @@ -776,20 +936,19 @@ void LayoutHelper::makeHorizontalSpacingEqual(std::vector& nodes) if (avgHSpacing < 0.0f) avgHSpacing = 0.0f; - LayoutHelper::makeHorizontalSpacingEqual(nodes, avgHSpacing); + Helper::makeHorizontalSpacingEqual(nodes, avgHSpacing); } /// /// 使水平间距相等 /// /// -void LayoutHelper::makeHorizontalSpacingEqual(const std::vector& nodes, float theSpacing) +void Helper::makeHorizontalSpacingEqual(const std::vector& nodes, float theSpacing) { - Node *child, *childNext; for (size_t index = 0; index < nodes.size() - 1; ++index) { - child = nodes[index]; - childNext = nodes[index + 1]; + auto child = nodes[index]; + auto childNext = nodes[index + 1]; setNodeLeft(childNext, theSpacing + getNodeLeft(child) + child->getContentSize().width); } } @@ -798,25 +957,21 @@ void LayoutHelper::makeHorizontalSpacingEqual(const std::vector& nodes, f /// 使垂直间距相等 /// /// -void LayoutHelper::makeVerticalSpacingEqual(std::vector& nodes) +void Helper::makeVerticalSpacingEqual(std::vector& nodes) { if (nodes.size() < 3) return; float avgVSpacing = 0; - Node *child, *childNext; - if (nodes.size() < 3) - return; -#if (defined(_WIN32) && _MSC_VER >= 1700) || !defined(_WIN32) + // sort by y firstly std::sort(nodes.begin(), nodes.end(), [](Node* const left, Node* const right) -> bool { return getNodeTop(left) < getNodeTop(right); }); -#else -#endif +# for (size_t index = 0; index < nodes.size() - 1; ++index) { - child = nodes[index]; - childNext = nodes[index + 1]; + auto child = nodes[index]; + auto childNext = nodes[index + 1]; avgVSpacing += (getNodeTop(childNext) - getNodeTop(child) - child->getContentSize().height); } @@ -825,10 +980,10 @@ void LayoutHelper::makeVerticalSpacingEqual(std::vector& nodes) if (avgVSpacing < 0.0f) avgVSpacing = 0.0f; - LayoutHelper::makeVerticalSpacingEqual(nodes, avgVSpacing); + Helper::makeVerticalSpacingEqual(nodes, avgVSpacing); } -void LayoutHelper::increaseHorizontalSpacing(std::vector& nodes, float theSpacing) +void Helper::increaseHorizontalSpacing(std::vector& nodes, float theSpacing) { if (nodes.size() < 2) return; @@ -842,7 +997,7 @@ void LayoutHelper::increaseHorizontalSpacing(std::vector& nodes, float th } } -void LayoutHelper::increaseVerticalSpacing(std::vector& nodes, float theSpacing) +void Helper::increaseVerticalSpacing(std::vector& nodes, float theSpacing) { if (nodes.size() < 2) return; @@ -856,59 +1011,58 @@ void LayoutHelper::increaseVerticalSpacing(std::vector& nodes, float theS } } -void LayoutHelper::decreaseHorizontalSpacing(std::vector& nodes, float theSpacing) +void Helper::decreaseHorizontalSpacing(std::vector& nodes, float theSpacing) { increaseHorizontalSpacing(nodes, -theSpacing); } -void LayoutHelper::decreaseVerticalSpacing(std::vector& nodes, float theSpacing) +void Helper::decreaseVerticalSpacing(std::vector& nodes, float theSpacing) { increaseVerticalSpacing(nodes, -theSpacing); } -void LayoutHelper::removeHorizontalSpacing(const std::vector& nodes) +void Helper::removeHorizontalSpacing(const std::vector& nodes) { - LayoutHelper::makeHorizontalSpacingEqual(nodes, 0); + Helper::makeHorizontalSpacingEqual(nodes, 0); } -void LayoutHelper::removeVerticalSpacing(const std::vector& nodes) +void Helper::removeVerticalSpacing(const std::vector& nodes) { - LayoutHelper::makeVerticalSpacingEqual(nodes, 0); + Helper::makeVerticalSpacingEqual(nodes, 0); } /// /// 使垂直间距相等 /// /// -void LayoutHelper::makeVerticalSpacingEqual(const std::vector& nodes, float theSpacing) +void Helper::makeVerticalSpacingEqual(const std::vector& nodes, float theSpacing) { - Node *child, *childNext; for (size_t index = 0; index < nodes.size() - 1; ++index) { - child = nodes[index]; - childNext = nodes[index + 1]; + auto child = nodes[index]; + auto childNext = nodes[index + 1]; setNodeTop(childNext, theSpacing + getNodeTop(child) + child->getContentSize().height); } } -// ----------------- LayoutHelper::VisibleRect -------------------------- +// ----------------- Helper::VisibleRect -------------------------- -ax::Rect LayoutHelper::VisibleRect::s_ScreenVisibleRect; +ax::Rect Helper::VisibleRect::s_ScreenVisibleRect; /// x-studio: when design resolution changed, should call this func. -void LayoutHelper::VisibleRect::refresh(void) +void Helper::VisibleRect::refresh(void) { auto director = Director::getInstance(); s_ScreenVisibleRect.origin = Director::getInstance()->getVisibleOrigin(); s_ScreenVisibleRect.size = Director::getInstance()->getVisibleSize(); } -void LayoutHelper::VisibleRect::lazyInit() +void Helper::VisibleRect::lazyInit() { if (s_ScreenVisibleRect.size.width == 0.0f && s_ScreenVisibleRect.size.height == 0.0f) { - auto director = Director::getInstance(); - auto renderView = director->getRenderView(); + auto director = Director::getInstance(); + auto renderView = director->getRenderView(); if (renderView->getResolutionPolicy() == ResolutionPolicy::NO_BORDER) { @@ -917,379 +1071,381 @@ void LayoutHelper::VisibleRect::lazyInit() } else { - s_ScreenVisibleRect.origin = LayoutHelper::getVisibleOrigin(); - s_ScreenVisibleRect.size = LayoutHelper::getVisibleSize(); + s_ScreenVisibleRect.origin = Helper::getVisibleOrigin(); + s_ScreenVisibleRect.size = Helper::getVisibleSize(); } } } -ax::Rect LayoutHelper::VisibleRect::getScreenVisibleRect() +ax::Rect Helper::VisibleRect::getScreenVisibleRect() { lazyInit(); return ax::Rect(s_ScreenVisibleRect.origin.x, s_ScreenVisibleRect.origin.y, s_ScreenVisibleRect.size.width, - s_ScreenVisibleRect.size.height); + s_ScreenVisibleRect.size.height); } -Vec2 LayoutHelper::VisibleRect::size() +Vec2 Helper::VisibleRect::size() { lazyInit(); return s_ScreenVisibleRect.size; } -Point LayoutHelper::VisibleRect::left() +Point Helper::VisibleRect::left() { lazyInit(); - return ax::Point(s_ScreenVisibleRect.origin.x, - s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); + return ax::Point(s_ScreenVisibleRect.origin.x, s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); } -Point LayoutHelper::VisibleRect::right() +Point Helper::VisibleRect::right() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width, - s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); + s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); } -Point LayoutHelper::VisibleRect::top() +Point Helper::VisibleRect::top() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width / 2, - s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height); + s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height); } -Point LayoutHelper::VisibleRect::bottom() +Point Helper::VisibleRect::bottom() { lazyInit(); - return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width / 2, - s_ScreenVisibleRect.origin.y); + return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width / 2, s_ScreenVisibleRect.origin.y); } -Point LayoutHelper::VisibleRect::center() +Point Helper::VisibleRect::center() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width / 2, - s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); + s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height / 2); } -Point LayoutHelper::VisibleRect::leftTop() +Point Helper::VisibleRect::leftTop() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x, s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height); } -Point LayoutHelper::VisibleRect::rightTop() +Point Helper::VisibleRect::rightTop() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width, - s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height); + s_ScreenVisibleRect.origin.y + s_ScreenVisibleRect.size.height); } -Point LayoutHelper::VisibleRect::leftBottom() +Point Helper::VisibleRect::leftBottom() { lazyInit(); return s_ScreenVisibleRect.origin; } -Point LayoutHelper::VisibleRect::rightBottom() +Point Helper::VisibleRect::rightBottom() { lazyInit(); return ax::Point(s_ScreenVisibleRect.origin.x + s_ScreenVisibleRect.size.width, s_ScreenVisibleRect.origin.y); } /// visual screen -float LayoutHelper::VisibleRect::getNodeLeft(Node* pNode) +float Helper::VisibleRect::getNodeLeft(Node* pNode) { - ax::Point ptLocal(LayoutHelper::getNodeLeft(pNode), 0); + ax::Point ptLocal(Helper::getNodeLeft(pNode), 0); auto ptWorld = pNode->getParent()->convertToWorldSpace(ptLocal); return ptWorld.x; } -float LayoutHelper::VisibleRect::getNodeBottom(Node* pNode) +float Helper::VisibleRect::getNodeBottom(Node* pNode) { - ax::Point ptLocal(0, LayoutHelper::getNodeBottom(pNode)); + ax::Point ptLocal(0, Helper::getNodeBottom(pNode)); auto ptWorld = pNode->getParent()->convertToWorldSpace(ptLocal); return ptWorld.y; } -float LayoutHelper::VisibleRect::getNodeRight(Node* pNode) +float Helper::VisibleRect::getNodeRight(Node* pNode) { - ax::Point ptLocal(LayoutHelper::getNodeLeft(pNode) + pNode->getContentSize().width /* * pNode->getScaleX()*/, - 0); + ax::Point ptLocal(Helper::getNodeLeft(pNode) + pNode->getContentSize().width /* * pNode->getScaleX()*/, 0); auto ptWorld = pNode->getParent()->convertToWorldSpace(ptLocal); - auto visibleRect = LayoutHelper::VisibleRect::getScreenVisibleRect(); + auto visibleRect = Helper::VisibleRect::getScreenVisibleRect(); return visibleRect.size.width - ptWorld.x; } -float LayoutHelper::VisibleRect::getNodeTop(Node* pNode) +float Helper::VisibleRect::getNodeTop(Node* pNode) { - ax::Point ptLocal( - 0, LayoutHelper::getNodeBottom(pNode) + pNode->getContentSize().height /* * pNode->getScaleY()*/); + ax::Point ptLocal(0, Helper::getNodeBottom(pNode) + pNode->getContentSize().height /* * pNode->getScaleY()*/); auto ptWorld = pNode->getParent()->convertToWorldSpace(ptLocal); - auto visibleRect = LayoutHelper::VisibleRect::getScreenVisibleRect(); + auto visibleRect = Helper::VisibleRect::getScreenVisibleRect(); return visibleRect.size.height - ptWorld.y; } -void LayoutHelper::VisibleRect::setNodeLeft(Node* pNode, float left) +void Helper::VisibleRect::setNodeLeft(Node* pNode, float left) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, scrSize.height) - LayoutHelper::VisibleRect::leftTop(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, scrSize.height) - Helper::VisibleRect::leftTop(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord(size.width, achorPoint.x, left) /* - delta.x*/, 0); + ax::Point ptWorld(adjustCoordByAnchor(size.width, achorPoint.x, left) /* - delta.x*/, 0); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionX(ptLocal.x); } -void LayoutHelper::VisibleRect::setNodeTop(Node* pNode, float top) +void Helper::VisibleRect::setNodeTop(Node* pNode, float top) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, scrSize.height) - LayoutHelper::VisibleRect::leftTop(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, scrSize.height) - Helper::VisibleRect::leftTop(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(0, adjust_coord_neg(scrSize.height, size.height, achorPoint.y, top) - delta.y); + ax::Point ptWorld(0, adjustCoordNegative(scrSize.height, size.height, achorPoint.y, top) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionY(ptLocal.y); } -void LayoutHelper::VisibleRect::setNodeRight(Node* pNode, float right) +void Helper::VisibleRect::setNodeRight(Node* pNode, float right) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, 0) - LayoutHelper::VisibleRect::rightBottom(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, 0) - Helper::VisibleRect::rightBottom(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord_neg(scrSize.width, size.width, achorPoint.x, right) /* - delta.x*/, 0); + ax::Point ptWorld(adjustCoordNegative(scrSize.width, size.width, achorPoint.x, right) /* - delta.x*/, 0); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionX(ptLocal.x); } -void LayoutHelper::VisibleRect::setNodeBottom(Node* pNode, float bottom) +void Helper::VisibleRect::setNodeBottom(Node* pNode, float bottom) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, 0) - LayoutHelper::VisibleRect::rightBottom(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, 0) - Helper::VisibleRect::rightBottom(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(0, adjust_coord(size.height, achorPoint.y, bottom) - delta.y); + ax::Point ptWorld(0, adjustCoordByAnchor(size.height, achorPoint.y, bottom) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionY(ptLocal.y); } -void LayoutHelper::VisibleRect::setNodeLT(Node* pNode, const ax::Point& p) +void Helper::VisibleRect::setNodeLT(Node* pNode, const ax::Point& p) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, scrSize.height) - LayoutHelper::VisibleRect::leftTop(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, scrSize.height) - Helper::VisibleRect::leftTop(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord(size.width, achorPoint.x, p.x), - adjust_coord_neg(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordByAnchor(size.width, achorPoint.x, p.x), + adjustCoordNegative(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeRT(Node* pNode, const ax::Point& p) +void Helper::VisibleRect::setNodeRT(Node* pNode, const ax::Point& p) { // right top AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - LayoutHelper::VisibleRect::rightTop(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - Helper::VisibleRect::rightTop(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord_neg(scrSize.width, size.width, achorPoint.x, p.x) /* - delta.x*/, - adjust_coord_neg(scrSize.height, size.height, achorPoint.y, p.y) /* - delta.y*/); + ax::Point ptWorld(adjustCoordNegative(scrSize.width, size.width, achorPoint.x, p.x) /* - delta.x*/, + adjustCoordNegative(scrSize.height, size.height, achorPoint.y, p.y) /* - delta.y*/); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeLB(Node* pNode, const ax::Point& p) +void Helper::VisibleRect::setNodeLB(Node* pNode, const ax::Point& p) { // left bottom AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, 0) - LayoutHelper::VisibleRect::leftBottom(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, 0) - Helper::VisibleRect::leftBottom(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord(size.width, achorPoint.x, p.x) - delta.x, - adjust_coord(size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordByAnchor(size.width, achorPoint.x, p.x) - delta.x, + adjustCoordByAnchor(size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeRB(Node* pNode, const ax::Point& p) +void Helper::VisibleRect::setNodeRB(Node* pNode, const ax::Point& p) { // right bottom AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, 0) - LayoutHelper::VisibleRect::rightBottom(); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, 0) - Helper::VisibleRect::rightBottom(); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord_neg(scrSize.width, size.width, achorPoint.x, p.x) /* - delta.x*/, - adjust_coord(size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordNegative(scrSize.width, size.width, achorPoint.x, p.x) /* - delta.x*/, + adjustCoordByAnchor(size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } /// ratio position -void LayoutHelper::VisibleRect::setNodeNormalizedLT(Node* pNode, const ax::Point& ratio) +void Helper::VisibleRect::setNodeNormalizedLT(Node* pNode, const ax::Point& ratio) { AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, scrSize.height) - LayoutHelper::VisibleRect::leftTop(); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, scrSize.height) - Helper::VisibleRect::leftTop(); - Vec2 vscrSize = LayoutHelper::VisibleRect::size(); - ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); + Vec2 vscrSize = Helper::VisibleRect::size(); + ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord(size.width, achorPoint.x, p.x) - delta.x, - adjust_coord_neg(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordByAnchor(size.width, achorPoint.x, p.x) - delta.x, + adjustCoordNegative(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeNormalizedRT(Node* pNode, const ax::Point& ratio) +void Helper::VisibleRect::setNodeNormalizedRT(Node* pNode, const ax::Point& ratio) { // right top AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - LayoutHelper::VisibleRect::rightTop(); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - Helper::VisibleRect::rightTop(); - Vec2 vscrSize = LayoutHelper::VisibleRect::size(); - ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); + Vec2 vscrSize = Helper::VisibleRect::size(); + ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord_neg(scrSize.width, size.width, achorPoint.x, p.x) - delta.x, - adjust_coord_neg(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordNegative(scrSize.width, size.width, achorPoint.x, p.x) - delta.x, + adjustCoordNegative(scrSize.height, size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeNormalizedLB(Node* pNode, const ax::Point& ratio) +void Helper::VisibleRect::setNodeNormalizedLB(Node* pNode, const ax::Point& ratio) { // left bottom AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(0, 0) - LayoutHelper::VisibleRect::leftBottom(); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(0, 0) - Helper::VisibleRect::leftBottom(); - Vec2 vscrSize = LayoutHelper::VisibleRect::size(); - ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); + Vec2 vscrSize = Helper::VisibleRect::size(); + ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord(size.width, achorPoint.x, p.x) - delta.x, - adjust_coord(size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordByAnchor(size.width, achorPoint.x, p.x) - delta.x, + adjustCoordByAnchor(size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeNormalizedRB(Node* pNode, const ax::Point& ratio) +void Helper::VisibleRect::setNodeNormalizedRB(Node* pNode, const ax::Point& ratio) { // right bottom AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, 0) - LayoutHelper::VisibleRect::rightBottom(); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, 0) - Helper::VisibleRect::rightBottom(); - Vec2 vscrSize = LayoutHelper::VisibleRect::size(); - ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); + Vec2 vscrSize = Helper::VisibleRect::size(); + ax::Point p = ax::Vec2(vscrSize.width * ratio.x, vscrSize.height * ratio.y); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(adjust_coord_neg(scrSize.width, size.width, achorPoint.x, p.x) - delta.x, - adjust_coord(size.height, achorPoint.y, p.y) - delta.y); + ax::Point ptWorld(adjustCoordNegative(scrSize.width, size.width, achorPoint.x, p.x) - delta.x, + adjustCoordByAnchor(size.height, achorPoint.y, p.y) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } -void LayoutHelper::VisibleRect::setNodeNormalizedTop(Node* pNode, const float ratioTop) +void Helper::VisibleRect::setNodeNormalizedTop(Node* pNode, const float ratioTop) { // right top AX_ASSERT(pNode); - Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); - ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - LayoutHelper::VisibleRect::rightTop(); + Vec2 scrSize = Director::getInstance()->getRenderView()->getDesignResolutionSize(); + ax::Point delta = ax::Vec2(scrSize.width, scrSize.height) - Helper::VisibleRect::rightTop(); - Vec2 vscrSize = LayoutHelper::VisibleRect::size(); + Vec2 vscrSize = Helper::VisibleRect::size(); float top = vscrSize.width * ratioTop; - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - ax::Point ptWorld(0, adjust_coord_neg(scrSize.height, size.height, achorPoint.y, top) - delta.y); + ax::Point ptWorld(0, adjustCoordNegative(scrSize.height, size.height, achorPoint.y, top) - delta.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionY(ptWorld.y); } -void LayoutHelper::VisibleRect::setNodeNormalizedPositionX(ax::Node* pNode, float ratio) +void Helper::VisibleRect::setNodeNormalizedPositionX(ax::Node* pNode, float ratio) { AX_ASSERT(pNode); - ax::Rect visibleRect = LayoutHelper::LayoutHelper::VisibleRect::getScreenVisibleRect(); + ax::Rect visibleRect = Helper::Helper::VisibleRect::getScreenVisibleRect(); ax::Point ptWorld(visibleRect.size.width * ratio + visibleRect.origin.x, 0); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionX(ptLocal.x); } -void LayoutHelper::VisibleRect::setNodeNormalizedPositionY(ax::Node* pNode, float ratio) +void Helper::VisibleRect::setNodeNormalizedPositionY(ax::Node* pNode, float ratio) { AX_ASSERT(pNode); - ax::Rect visibleRect = LayoutHelper::LayoutHelper::VisibleRect::getScreenVisibleRect(); + ax::Rect visibleRect = Helper::Helper::VisibleRect::getScreenVisibleRect(); ax::Point ptWorld(0, visibleRect.size.height * ratio + visibleRect.origin.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPositionY(ptLocal.y); } -void LayoutHelper::VisibleRect::setNodeNormalizedPosition(Node* pNode, const ax::Point& ratio) +void Helper::VisibleRect::setNodeNormalizedPosition(Node* pNode, const ax::Point& ratio) { AX_ASSERT(pNode); pNode->setIgnoreAnchorPointForPosition(false); pNode->setAnchorPoint(ax::Vec2(.5f, .5f)); - ax::Rect visibleRect = LayoutHelper::LayoutHelper::VisibleRect::getScreenVisibleRect(); + ax::Rect visibleRect = Helper::Helper::VisibleRect::getScreenVisibleRect(); ax::Point ptWorld(visibleRect.size.width * ratio.x + visibleRect.origin.x, - visibleRect.size.height * ratio.y + visibleRect.origin.y); + visibleRect.size.height * ratio.y + visibleRect.origin.y); auto ptLocal = pNode->getParent()->convertToNodeSpace(ptWorld); pNode->setPosition(ptLocal); } + +#pragma endregion + +} // namespace ui + +} diff --git a/core/ui/LayoutHelper.h b/axmol/ui/UIHelper.h similarity index 72% rename from core/ui/LayoutHelper.h rename to axmol/ui/UIHelper.h index 4b6d64b1eceb..d86bd3563558 100644 --- a/core/ui/LayoutHelper.h +++ b/axmol/ui/UIHelper.h @@ -1,47 +1,140 @@ -// -// Copyright (c) 2014-2020 Simdsoft Limited - All Rights Reserved -// Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - -// This module is used by x-studio UI Editor to layout UI elements -// It's very useful for programer to operate UI elements in runtime, -// so, we publish it to here. -// usage: -// #include "ui/LayoutHelper.h" -// LayoutHelper::centerNode(node); // the node should be already have parent. -// LayoutHelper::makeVerticalSpacingEqual(nodes); // all the nodes shoud be in the same parent. -// -#pragma once -#ifndef _LAYOUTHELPER_H_ -# define _LAYOUTHELPER_H_ - -# include "axmol.h" -# include "base/Macros.h" - -// f(x) = s * a + x -# define adjust_coord(__sz__, __achor__, __coord__) ((__sz__) * (__achor__) + (__coord__)) +/**************************************************************************** +Copyright (c) 2013-2016 Chukong Technologies Inc. +Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +Copyright (c) 2014-2020 Simdsoft Limited - All Rights Reserved +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). + +https://axmol.dev/ + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. +****************************************************************************/ -// f(y) = y - s * a -# define adjust_coord_r(__sz__, __achor__, __coord__) ((__coord__) - (__sz__) * (__achor__)) - -// f(x) = S - (s - s * a + x) -# define adjust_coord_neg(__SZ__, __sz__, __achor__, __coord__) \ - ((__SZ__) - ((__sz__) - (__sz__) * (__achor__) + (__coord__))) +#pragma once -// f(y) = S - (s - s * a + y) -# define adjust_coord_neg_r adjust_coord_neg +#include +#include "axmol/platform/PlatformMacros.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/2d/Node.h" -# define center_coord(__SZ__, __sz__, __achor__) (((__SZ__) - (__sz__) + 2 * (__sz__) * (__achor__)) * 0.5f) +namespace ax +{ -using namespace ax; +/** + * @addtogroup ui + * @{ + */ +namespace ui +{ -// inline Vec2 operator*(const Vec2& left, const ax::Vec2& right) -//{ -// return Vec2(left.width * right.x, left.height * right.y); -// } +class Widget; -struct AX_DLL LayoutHelper +/** + * Helper class for traversing children in widget tree. + * It also provides some helper functions for layout. + */ +class AX_GUI_DLL Helper { +public: + /** + * Find a widget with a specific tag from root widget. + * This search will be recursive through all child widgets. + * @param root The be searched root widget. + * @param tag The widget tag. + * @return Widget instance pointer. + */ + static Widget* seekWidgetByTag(Widget* root, int tag); + + /** + * Find a widget with a specific name from root widget. + * This search will be recursive through all child widgets. + * + * @param root The be searched root widget. + * @param name The widget name. + * @return Widget instance pointer. + */ + static Widget* seekWidgetByName(Widget* root, std::string_view name); + + /** + * Find a widget with a specific action tag from root widget + * This search will be recursive through all child widgets. + *@param root The be searched root widget. + *@param tag The widget action's tag. + *@return Widget instance pointer. + */ + static Widget* seekActionWidgetByActionTag(Widget* root, int tag); + + /** + * @brief Get a UTF8 substring from a std::string with a given start position and length + * Sample: std::string str = "中国中国中国"; substr = getSubStringOfUTF8String(str,0,2) will = "中国" + * + * @param str The source string. + * @param start The start position of the substring. + * @param length The length of the substring in UTF8 count + * @return a UTF8 substring + */ + static std::string getSubStringOfUTF8String(std::string_view str, + std::string::size_type start, + std::string::size_type length); + + /** + * Refresh object and it's children layout state + * + *@param rootNode A Node* or Node* descendant instance pointer. + * + */ + static void doLayout(Node* rootNode); + + /** + * Change the active property of Layout's @see `LayoutComponent` + *@param active A boolean value. + */ + static void changeLayoutSystemActiveState(bool active); + + /** + *@brief restrict capInsetSize, when the capInsets's width is larger than the textureSize, it will restrict to 0, + * the height goes the same way as width. + *@param capInsets A user defined capInsets. + *@param textureSize The size of a scale9enabled texture + *@return a restricted capInset. + */ + static Rect restrictCapInsetRect(const Rect& capInsets, const Vec2& textureSize); + + /** + *@brief Convert a node's boundingBox rect into screen coordinates. + * + * @param node Any node pointer. + * + * @return A Rect in screen coordinates. + */ + static Rect convertBoundingBoxToScreen(Node* node); + +#ifndef _AX_GEN_SCRIPT_BINDINGS +# pragma region x-studio spec + + // Follow APIs used by x-studio UI Editor to layout UI elements + // It's very useful for programer to operate UI elements in runtime, + // so, we publish it to here. + // usage: + // #include "ui/UIHelper.h" + // ui::Helper::centerNode(node); // the node should be already have parent. + // ui::Helper::makeVerticalSpacingEqual(nodes); // all the nodes shoud be in the same parent. + // static Vec2 s_designSize; static float s_adjustedScale; @@ -85,15 +178,34 @@ struct AX_DLL LayoutHelper ALIGN_RB = ALIGN_RIGHT | ALIGN_BOTTOM, // right bottom }; -# define isIgnoreX(align) (align != ALIGN_LEFT) && (align != ALIGN_RIGHT) -# define isIgnoreY(align) (align != ALIGN_TOP) && (align != ALIGN_BOTTOM) -# define isIgnoreXY(align) (align == ALIGN_CENTER) + // f(x) = s * a + x + inline static float adjustCoordByAnchor(float size, float anchor, float coord) { return size * anchor + coord; } + + // f(y) = y - s * a + inline static float reverseAdjustCoordByAnchor(float size, float anchor, float coord) + { + return coord - size * anchor; + } + + // f(x) = S - (s - s * a + x) + inline static float adjustCoordNegative(float containerSize, float size, float anchor, float coord) + { + return containerSize - (size - size * anchor + coord); + } + + // f(y) = S - (s - s * a + y) + inline static float reverseAdjustCoordNegative(float containerSize, float size, float anchor, float coord) + { + return adjustCoordNegative(containerSize, size, anchor, coord); + } - static ax::Vec2 getScale2D(ax::Node* pNode) + inline static float computeCenterCoord(float containerSize, float size, float anchor) { - return ax::Vec2(pNode->getScaleX(), pNode->getScaleY()); + return (containerSize - size + 2 * size * anchor) * 0.5f; } + static ax::Vec2 getScale2D(ax::Node* pNode) { return ax::Vec2(pNode->getScaleX(), pNode->getScaleY()); } + static float getNodeLeftX(ax::Node* pNode) { return pNode->getPositionX() - pNode->getAnchorPoint().x * pNode->getContentSize().width * pNode->getScaleX(); @@ -171,11 +283,7 @@ struct AX_DLL LayoutHelper ** y: specify coord y. ** */ - static void setNodePosition(ax::Node* pNode, - const ax::Point& anchorPoint, - const int align, - float x, - float y) + static void setNodePosition(ax::Node* pNode, const ax::Point& anchorPoint, const int align, float x, float y) { pNode->setAnchorPoint(anchorPoint); setNodePosition(pNode, align, x, y); @@ -186,10 +294,7 @@ struct AX_DLL LayoutHelper setNodePosition(pNode, align, value, value); } - static void setNodePosition(ax::Node* pNode, - const ax::Point& anchorPoint, - const int align, - float value = 0.0f) + static void setNodePosition(ax::Node* pNode, const ax::Point& anchorPoint, const int align, float value = 0.0f) { // ignore x or y setNodePosition(pNode, anchorPoint, align, value, value); } @@ -233,7 +338,7 @@ struct AX_DLL LayoutHelper { achorX = pNode->getAnchorPoint().x; } - pNode->setPositionX(center_coord(parentSize.width, size.width, achorX) /*parentSize.width * 0.5f*/); + pNode->setPositionX(computeCenterCoord(parentSize.width, size.width, achorX) /*parentSize.width * 0.5f*/); } static void centerNodeY(ax::Node* pNode, const Vec2& parentSize) @@ -246,21 +351,21 @@ struct AX_DLL LayoutHelper { achorY = pNode->getAnchorPoint().y; } - pNode->setPositionY(center_coord(parentSize.height, size.height, achorY)); + pNode->setPositionY(computeCenterCoord(parentSize.height, size.height, achorY)); } static void centerNode(ax::Node* pNode, const Vec2& parentSize) { AX_ASSERT(pNode); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achor = ax::Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achor = pNode->getAnchorPoint(); } - pNode->setPosition(ax::Vec2(center_coord(parentSize.width, size.width, achor.x), - center_coord(parentSize.height, size.height, achor.y))); + pNode->setPosition(ax::Vec2(computeCenterCoord(parentSize.width, size.width, achor.x), + computeCenterCoord(parentSize.height, size.height, achor.y))); } // @version 1 @@ -386,7 +491,7 @@ struct AX_DLL LayoutHelper { achorX = pNode->getAnchorPoint().x; } - pNode->setPositionX(adjust_coord(size.width, achorX, left) - size.width * anchor); + pNode->setPositionX(adjustCoordByAnchor(size.width, achorX, left) - size.width * anchor); } static float getNodeLeft(ax::Node* pNode, const Vec2& parentSize, float anchor = 0.0f) { @@ -398,7 +503,7 @@ struct AX_DLL LayoutHelper { achorX = pNode->getAnchorPoint().x; } - return adjust_coord_r(size.width, achorX, pNode->getPositionX()) + anchor * size.width; + return reverseAdjustCoordByAnchor(size.width, achorX, pNode->getPositionX()) + anchor * size.width; } static void setNodeTop(ax::Node* pNode, const Vec2& parentSize, float top, float anchor = 0.0f) @@ -411,7 +516,7 @@ struct AX_DLL LayoutHelper { achorY = pNode->getAnchorPoint().y; } - pNode->setPositionY(adjust_coord_neg(parentSize.height, size.height, achorY, top) - size.height * anchor); + pNode->setPositionY(adjustCoordNegative(parentSize.height, size.height, achorY, top) - size.height * anchor); } static float getNodeTop(ax::Node* pNode, const Vec2& parentSize, float anchor = 0.0f) { @@ -423,7 +528,8 @@ struct AX_DLL LayoutHelper { achorY = pNode->getAnchorPoint().y; } - return adjust_coord_neg_r(parentSize.height, size.height, achorY, pNode->getPositionY()) + size.height * anchor; + return reverseAdjustCoordNegative(parentSize.height, size.height, achorY, pNode->getPositionY()) + + size.height * anchor; } static void setNodeRight(ax::Node* pNode, const Vec2& parentSize, float right) @@ -436,7 +542,7 @@ struct AX_DLL LayoutHelper { achorX = pNode->getAnchorPoint().x; } - pNode->setPositionX(adjust_coord_neg(parentSize.width, size.width, achorX, right)); + pNode->setPositionX(adjustCoordNegative(parentSize.width, size.width, achorX, right)); } static float getNodeRight(ax::Node* pNode, const Vec2& parentSize, float anchor = 0.0f) @@ -449,7 +555,8 @@ struct AX_DLL LayoutHelper { achorX = pNode->getAnchorPoint().x; } - return adjust_coord_neg_r(parentSize.width, size.width, achorX, pNode->getPositionX()) + anchor * size.width; + return reverseAdjustCoordNegative(parentSize.width, size.width, achorX, pNode->getPositionX()) + + anchor * size.width; } static void setNodeBottom(ax::Node* pNode, const Vec2& parentSize, float bottom, float anchor = 0.0f) @@ -462,7 +569,7 @@ struct AX_DLL LayoutHelper { achorY = pNode->getAnchorPoint().y; } - pNode->setPositionY(adjust_coord(size.height, achorY, bottom) - anchor * size.height); + pNode->setPositionY(adjustCoordByAnchor(size.height, achorY, bottom) - anchor * size.height); } static float getNodeBottom(ax::Node* pNode, const Vec2& parentSize, float anchor = 0.f) @@ -475,63 +582,63 @@ struct AX_DLL LayoutHelper { achorY = pNode->getAnchorPoint().y; } - return adjust_coord_r(size.height, achorY, pNode->getPositionY()) + size.height * anchor; + return reverseAdjustCoordByAnchor(size.height, achorY, pNode->getPositionY()) + size.height * anchor; } static void setNodeLB(ax::Node* pNode, const Vec2& parentSize, const ax::Point& p) { // left bottom AX_ASSERT(pNode); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = ax::Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - pNode->setPosition( - ax::Vec2(adjust_coord(size.width, achorPoint.x, p.x), adjust_coord(size.height, achorPoint.y, p.y))); + pNode->setPosition(ax::Vec2(adjustCoordByAnchor(size.width, achorPoint.x, p.x), + adjustCoordByAnchor(size.height, achorPoint.y, p.y))); } static void setNodeRB(ax::Node* pNode, const Vec2& parentSize, const ax::Point& p) { // right bottom AX_ASSERT(pNode); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = ax::Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - pNode->setPosition(ax::Vec2(adjust_coord_neg(parentSize.width, size.width, achorPoint.x, p.x), - adjust_coord(size.height, achorPoint.y, p.y))); + pNode->setPosition(ax::Vec2(adjustCoordNegative(parentSize.width, size.width, achorPoint.x, p.x), + adjustCoordByAnchor(size.height, achorPoint.y, p.y))); } static void setNodeLT(ax::Node* pNode, const Vec2& parentSize, const ax::Point& p) { // left top AX_ASSERT(pNode); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = ax::Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - pNode->setPosition(ax::Vec2(adjust_coord(size.width, achorPoint.x, p.x), - adjust_coord_neg(parentSize.height, size.height, achorPoint.y, p.y))); + pNode->setPosition(ax::Vec2(adjustCoordByAnchor(size.width, achorPoint.x, p.x), + adjustCoordNegative(parentSize.height, size.height, achorPoint.y, p.y))); } static void setNodeRT(ax::Node* pNode, const Vec2& parentSize, const ax::Point& p) { // right top AX_ASSERT(pNode); - Vec2 size = pNode->getContentSize() * getScale2D(pNode); + Vec2 size = pNode->getContentSize() * getScale2D(pNode); ax::Point achorPoint = ax::Vec2::ZERO; if (!pNode->isIgnoreAnchorPointForPosition()) { achorPoint = pNode->getAnchorPoint(); } - pNode->setPosition(ax::Vec2(adjust_coord_neg(parentSize.width, size.width, achorPoint.x, p.x), - adjust_coord_neg(parentSize.height, size.height, achorPoint.y, p.y))); + pNode->setPosition(ax::Vec2(adjustCoordNegative(parentSize.width, size.width, achorPoint.x, p.x), + adjustCoordNegative(parentSize.height, size.height, achorPoint.y, p.y))); } /* set node position as normalized: @version 1 */ @@ -797,7 +904,7 @@ struct AX_DLL LayoutHelper static void setNodePosition(ax::Node* pNode, const ax::Point& p) { setNodeNormalizedPosition(pNode, ax::Vec2(p.x / s_designSize.width * s_adjustedScale, - p.y / s_designSize.height * s_adjustedScale)); + p.y / s_designSize.height * s_adjustedScale)); } static void centerNode(ax::Node* pNode) { setNodeNormalizedPosition(pNode, ax::Vec2(.5f, .5f)); } static void centerNodeX(ax::Node* pNode) { setNodeNormalizedPositionX(pNode, .5f); } @@ -835,6 +942,11 @@ struct AX_DLL LayoutHelper static void lazyInit(); static ax::Rect s_ScreenVisibleRect; }; +# pragma endregion +#endif }; +} // namespace ui -#endif +// end of ui group +/// @} +} // namespace ax diff --git a/core/ui/UIImageView.cpp b/axmol/ui/UIImageView.cpp similarity index 98% rename from core/ui/UIImageView.cpp rename to axmol/ui/UIImageView.cpp index 2e4d72e02bce..36d42338f7f0 100644 --- a/core/ui/UIImageView.cpp +++ b/axmol/ui/UIImageView.cpp @@ -24,10 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIImageView.h" -#include "ui/UIScale9Sprite.h" -#include "ui/UIHelper.h" -#include "2d/Sprite.h" +#include "axmol/ui/UIImageView.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/2d/Sprite.h" namespace ax { diff --git a/core/ui/UIImageView.h b/axmol/ui/UIImageView.h similarity index 87% rename from core/ui/UIImageView.h rename to axmol/ui/UIImageView.h index 52d635737cc5..6b28236ebef6 100644 --- a/core/ui/UIImageView.h +++ b/axmol/ui/UIImageView.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -125,7 +125,7 @@ class AX_GUI_DLL ImageView : public Widget, public ax::BlendProtocol * {BlendFactor::ONE, BlendFactor::ONE}, {BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA}. * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * Returns the blending function that is currently being used. @@ -133,31 +133,31 @@ class AX_GUI_DLL ImageView : public Widget, public ax::BlendProtocol * @return A BlendFunc structure with source and destination factor which specified pixel arithmetic. * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; // override methods. - virtual void ignoreContentAdaptWithSize(bool ignore) override; - virtual std::string getDescription() const override; - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; + void ignoreContentAdaptWithSize(bool ignore) override; + std::string getDescription() const override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; ResourceData getRenderFile(); // initializes state of widget. - virtual bool init() override; + bool init() override; virtual bool init(std::string_view imageFileName, TextureResType texType = TextureResType::LOCAL); protected: - virtual void initRenderer() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onSizeChanged() override; - virtual void adaptRenderers() override; + void adaptRenderers() override; void loadTexture(SpriteFrame* spriteframe); void setupTexture(); void imageTextureScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; protected: bool _scale9Enabled; diff --git a/core/ui/UILayout.cpp b/axmol/ui/UILayout.cpp similarity index 97% rename from core/ui/UILayout.cpp rename to axmol/ui/UILayout.cpp index 7204930a0ab6..c3d689335fd1 100644 --- a/core/ui/UILayout.cpp +++ b/axmol/ui/UILayout.cpp @@ -24,18 +24,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UILayout.h" -#include "ui/UIHelper.h" -#include "ui/UIScale9Sprite.h" -#include "renderer/RenderState.h" -#include "base/Director.h" -#include "renderer/Renderer.h" -#include "ui/UILayoutManager.h" -#include "2d/DrawNode.h" -#include "2d/Layer.h" -#include "2d/Sprite.h" -#include "base/EventFocus.h" -#include "base/StencilStateManager.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/ui/UILayoutManager.h" +#include "axmol/2d/DrawNode.h" +#include "axmol/2d/Layer.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/EventFocus.h" +#include "axmol/base/StencilStateManager.h" #include namespace ax @@ -57,15 +57,13 @@ Layout::Layout() , _colorType(BackGroundColorType::NONE) , _bgImageTexType(TextureResType::LOCAL) , _backGroundImageTextureSize(Vec2::ZERO) - , _backGroundImageColor(Color3B::WHITE) - , _backGroundImageOpacity(255) + , _backGroundImageColor(Color32::WHITE) , _colorRender(nullptr) , _gradientRender(nullptr) - , _cColor(Color3B::WHITE) - , _gStartColor(Color3B::WHITE) - , _gEndColor(Color3B::WHITE) + , _cColor(Color32::WHITE) + , _gStartColor(Color32::WHITE) + , _gEndColor(Color32::WHITE) , _alongVector(Vec2(0.0f, -1.0f)) - , _cOpacity(255) , _clippingEnabled(false) , _layoutType(Type::ABSOLUTE) , _clippingType(ClippingType::STENCIL) @@ -449,7 +447,7 @@ void Layout::setStencilClippingSize(const Vec2& /*size*/) if (_clippingEnabled && _clippingType == ClippingType::STENCIL) { _clippingStencil->clear(); - _clippingStencil->drawSolidRect(Vec2::ZERO, _contentSize, Color4B::GREEN); // Fix issue #1546 + _clippingStencil->drawSolidRect(Vec2::ZERO, _contentSize, Color::GREEN); // Fix issue #1546 } } @@ -729,14 +727,13 @@ void Layout::setBackGroundColorType(BackGroundColorType type) case BackGroundColorType::SOLID: _colorRender = LayerColor::create(); _colorRender->setContentSize(_contentSize); - _colorRender->setOpacity(_cOpacity); _colorRender->setColor(_cColor); addProtectedChild(_colorRender, BCAKGROUNDCOLORRENDERER_Z, -1); break; case BackGroundColorType::GRADIENT: _gradientRender = LayerGradient::create(); _gradientRender->setContentSize(_contentSize); - _gradientRender->setOpacity(_cOpacity); + _gradientRender->setOpacity(_cColor.a); _gradientRender->setStartColor(_gStartColor); _gradientRender->setEndColor(_gEndColor); _gradientRender->setVector(_alongVector); @@ -752,7 +749,7 @@ Layout::BackGroundColorType Layout::getBackGroundColorType() const return _colorType; } -void Layout::setBackGroundColor(const Color3B& color) +void Layout::setBackGroundColor(const Color32& color) { _cColor = color; if (_colorRender) @@ -761,12 +758,12 @@ void Layout::setBackGroundColor(const Color3B& color) } } -const Color3B& Layout::getBackGroundColor() const +const Color32& Layout::getBackGroundColor() const { return _cColor; } -void Layout::setBackGroundColor(const Color3B& startColor, const Color3B& endColor) +void Layout::setBackGroundColor(const Color32& startColor, const Color32& endColor) { _gStartColor = startColor; if (_gradientRender) @@ -780,19 +777,19 @@ void Layout::setBackGroundColor(const Color3B& startColor, const Color3B& endCol } } -const Color3B& Layout::getBackGroundStartColor() const +const Color32& Layout::getBackGroundStartColor() const { return _gStartColor; } -const Color3B& Layout::getBackGroundEndColor() const +const Color32& Layout::getBackGroundEndColor() const { return _gEndColor; } void Layout::setBackGroundColorOpacity(uint8_t opacity) { - _cOpacity = opacity; + _cColor.a = opacity; switch (_colorType) { case BackGroundColorType::NONE: @@ -810,7 +807,7 @@ void Layout::setBackGroundColorOpacity(uint8_t opacity) uint8_t Layout::getBackGroundColorOpacity() const { - return _cOpacity; + return _cColor.a; } void Layout::setBackGroundColorVector(const Vec2& vector) @@ -827,7 +824,7 @@ const Vec2& Layout::getBackGroundColorVector() const return _alongVector; } -void Layout::setBackGroundImageColor(const Color3B& color) +void Layout::setBackGroundImageColor(const Color32& color) { _backGroundImageColor = color; updateBackGroundImageColor(); @@ -835,18 +832,18 @@ void Layout::setBackGroundImageColor(const Color3B& color) void Layout::setBackGroundImageOpacity(uint8_t opacity) { - _backGroundImageOpacity = opacity; + _backGroundImageColor.a = opacity; updateBackGroundImageOpacity(); } -const Color3B& Layout::getBackGroundImageColor() const +const Color32& Layout::getBackGroundImageColor() const { return _backGroundImageColor; } uint8_t Layout::getBackGroundImageOpacity() const { - return _backGroundImageOpacity; + return _backGroundImageColor.a; } void Layout::updateBackGroundImageColor() @@ -861,7 +858,7 @@ void Layout::updateBackGroundImageOpacity() { if (_backGroundImage) { - _backGroundImage->setOpacity(_backGroundImageOpacity); + _backGroundImage->setOpacity(_backGroundImageColor.a); } } @@ -870,7 +867,6 @@ void Layout::updateBackGroundImageRGBA() if (_backGroundImage) { _backGroundImage->setColor(_backGroundImageColor); - _backGroundImage->setOpacity(_backGroundImageOpacity); } } @@ -992,7 +988,6 @@ void Layout::copySpecialProperties(Widget* widget) setBackGroundColorType(layout->_colorType); setBackGroundColor(layout->_cColor); setBackGroundColor(layout->_gStartColor, layout->_gEndColor); - setBackGroundColorOpacity(layout->_cOpacity); setBackGroundColorVector(layout->_alongVector); setLayoutType(layout->_layoutType); setClippingEnabled(layout->_clippingEnabled); diff --git a/core/ui/UILayout.h b/axmol/ui/UILayout.h similarity index 88% rename from core/ui/UILayout.h rename to axmol/ui/UILayout.h index cadae8af70bd..1485768cab02 100644 --- a/core/ui/UILayout.h +++ b/axmol/ui/UILayout.h @@ -26,11 +26,11 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" -#include "renderer/CustomCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/CallbackCommand.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/renderer/CallbackCommand.h" /** * @addtogroup ui @@ -215,36 +215,36 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol * Set background color for layout * The color only applies to layout when it's color type is BackGroundColorType::SOLIDE * - * @param color Color in Color3B. + * @param color Color in Color32. */ - void setBackGroundColor(const Color3B& color); + void setBackGroundColor(const Color32& color); /** * Query the layout's background color. - *@return Background color in Color3B. + *@return Background color in Color32. */ - const Color3B& getBackGroundColor() const; + const Color32& getBackGroundColor() const; /** * Set start and end background color for layout. * This setting only take effect when the layout's color type is BackGroundColorType::GRADIENT * - * @param startColor Color value in Color3B. - * @param endColor Color value in Color3B. + * @param startColor Color value in Color32. + * @param endColor Color value in Color32. */ - void setBackGroundColor(const Color3B& startColor, const Color3B& endColor); + void setBackGroundColor(const Color32& startColor, const Color32& endColor); /** * Get the gradient background start color. *@return Gradient background start color value. */ - const Color3B& getBackGroundStartColor() const; + const Color32& getBackGroundStartColor() const; /** * Get the gradient background end color. * @return Gradient background end color value. */ - const Color3B& getBackGroundEndColor() const; + const Color32& getBackGroundEndColor() const; /** * Sets background color opacity of layout. @@ -275,9 +275,9 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol /** * Set layout's background image color. - *@param color Background color value in `Color3B`. + *@param color Background color value in `Color32`. */ - void setBackGroundImageColor(const Color3B& color); + void setBackGroundImageColor(const Color32& color); /** * Set opacity of background image. @@ -289,7 +289,7 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol * Get color of layout's background image. *@return Layout's background image color. */ - const Color3B& getBackGroundImageColor() const; + const Color32& getBackGroundImageColor() const; /** * Get the opacity of layout's background image. @@ -342,7 +342,7 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * Change the layout type. @@ -356,8 +356,8 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol */ virtual Type getLayoutType() const; - virtual void addChild(Node* child) override; - virtual void addChild(Node* child, int localZOrder) override; + void addChild(Node* child) override; + void addChild(Node* child, int localZOrder) override; /** * Adds a child to the container with z order and tag * @@ -368,19 +368,19 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol * @param localZOrder Z order for drawing priority. Please refer to setLocalZOrder(int) * @param tag A integer to identify the node easily. Please refer to setTag(int) */ - virtual void addChild(Node* child, int localZOrder, int tag) override; - virtual void addChild(Node* child, int localZOrder, std::string_view name) override; + void addChild(Node* child, int localZOrder, int tag) override; + void addChild(Node* child, int localZOrder, std::string_view name) override; - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; - virtual void removeChild(Node* child, bool cleanup = true) override; + void removeChild(Node* child, bool cleanup = true) override; /** * Removes all children from the container with a cleanup. * * @see `removeAllChildrenWithCleanup(bool)` */ - virtual void removeAllChildren() override; + void removeAllChildren() override; /** * Removes all children from the container, and do a cleanup to all running actions depending on the cleanup * parameter. @@ -388,7 +388,7 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol * @param cleanup true if all running actions on all children nodes should be cleanup, false otherwise. * @lua removeAllChildren */ - virtual void removeAllChildrenWithCleanup(bool cleanup) override; + void removeAllChildrenWithCleanup(bool cleanup) override; /** * force refresh widget layout @@ -403,14 +403,14 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; - virtual void setGlobalZOrder(float globalZOrder) override; + void setGlobalZOrder(float globalZOrder) override; /** * If a layout is loop focused which means that the focus movement will be inside the layout @@ -441,7 +441,7 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol *@param current the current focused widget *@return the next focused widget in a layout */ - virtual Widget* findNextFocusedWidget(FocusDirection direction, Widget* current) override; + Widget* findNextFocusedWidget(FocusDirection direction, Widget* current) override; /** * To specify a user-defined functor to decide which child widget of the layout should get focused @@ -457,24 +457,24 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol * @param mask Mask being set * @param applyChildren If true call this function recursively from this node to its children. */ - virtual void setCameraMask(unsigned short mask, bool applyChildren = true) override; + void setCameraMask(unsigned short mask, bool applyChildren = true) override; ResourceData getRenderFile(); // override "init" method of widget. - virtual bool init() override; + bool init() override; protected: // override "onSizeChanged" method of widget. - virtual void onSizeChanged() override; + void onSizeChanged() override; // init background image renderer. void addBackGroundImage(); void supplyTheLayoutParameterLackToChild(Widget* child); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; - virtual void copyClonedWidgetChildren(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; + void copyClonedWidgetChildren(Widget* model) override; void stencilClippingVisit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags); void scissorClippingVisit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags); @@ -482,10 +482,10 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol void setStencilClippingSize(const Vec2& size); const Rect& getClippingRect(); - virtual void doLayout() override; - virtual LayoutManager* createLayoutManager() override; - virtual Vec2 getLayoutContentSize() const override; - virtual const Vector& getLayoutElements() const override; + void doLayout() override; + LayoutManager* createLayoutManager() override; + Vec2 getLayoutContentSize() const override; + const Vector& getLayoutElements() const override; // clipping @@ -611,16 +611,14 @@ class AX_GUI_DLL Layout : public Widget, public LayoutProtocol BackGroundColorType _colorType; TextureResType _bgImageTexType; Vec2 _backGroundImageTextureSize; - Color3B _backGroundImageColor; - uint8_t _backGroundImageOpacity; + Color32 _backGroundImageColor; LayerColor* _colorRender; LayerGradient* _gradientRender; - Color3B _cColor; - Color3B _gStartColor; - Color3B _gEndColor; + Color32 _cColor; + Color32 _gStartColor; + Color32 _gEndColor; Vec2 _alongVector; - uint8_t _cOpacity; // clipping bool _clippingEnabled; diff --git a/core/ui/UILayoutComponent.cpp b/axmol/ui/UILayoutComponent.cpp similarity index 99% rename from core/ui/UILayoutComponent.cpp rename to axmol/ui/UILayoutComponent.cpp index 223ca7cecff7..2e133e82c86c 100644 --- a/core/ui/UILayoutComponent.cpp +++ b/axmol/ui/UILayoutComponent.cpp @@ -23,11 +23,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIPageView.h" -#include "ui/UILayoutComponent.h" -#include "2d/Node.h" -#include "ui/GUIDefine.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/ui/UILayoutComponent.h" +#include "axmol/2d/Node.h" +#include "axmol/ui/GUIDefine.h" +#include "axmol/ui/UIHelper.h" namespace ax { @@ -672,4 +672,4 @@ void LayoutComponent::setPercentOnlyEnabled(bool enable) } } // namespace ui -} \ No newline at end of file +} diff --git a/core/ui/UILayoutComponent.h b/axmol/ui/UILayoutComponent.h similarity index 99% rename from core/ui/UILayoutComponent.h rename to axmol/ui/UILayoutComponent.h index 63afc1fc204b..afb627663812 100644 --- a/core/ui/UILayoutComponent.h +++ b/axmol/ui/UILayoutComponent.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "2d/Component.h" -#include "ui/GUIExport.h" +#include "axmol/2d/Component.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -59,7 +59,7 @@ class AX_GUI_DLL LayoutComponent : public Component */ ~LayoutComponent(); - virtual bool init() override; + bool init() override; /** * Create a LayoutComponent instance with default settings. diff --git a/core/ui/UILayoutManager.cpp b/axmol/ui/UILayoutManager.cpp similarity index 99% rename from core/ui/UILayoutManager.cpp rename to axmol/ui/UILayoutManager.cpp index ddfd3a7823d6..54edb533cfe4 100644 --- a/core/ui/UILayoutManager.cpp +++ b/axmol/ui/UILayoutManager.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UILayoutManager.h" -#include "ui/UILayout.h" +#include "axmol/ui/UILayoutManager.h" +#include "axmol/ui/UILayout.h" namespace ax { diff --git a/core/ui/UILayoutManager.h b/axmol/ui/UILayoutManager.h similarity index 92% rename from core/ui/UILayoutManager.h rename to axmol/ui/UILayoutManager.h index d257e468b1b7..d20e943ba7a7 100644 --- a/core/ui/UILayoutManager.h +++ b/axmol/ui/UILayoutManager.h @@ -26,9 +26,9 @@ #pragma once -#include "base/Object.h" -#include "base/Vector.h" -#include "ui/GUIExport.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -73,7 +73,7 @@ class AX_GUI_DLL LinearVerticalLayoutManager : public LayoutManager LinearVerticalLayoutManager(){} virtual ~LinearVerticalLayoutManager(){} static LinearVerticalLayoutManager* create(); - virtual void doLayout(LayoutProtocol* layout) override; + void doLayout(LayoutProtocol* layout) override; friend class Layout; }; @@ -89,7 +89,7 @@ class AX_GUI_DLL LinearHorizontalLayoutManager : public LayoutManager LinearHorizontalLayoutManager(){} virtual ~LinearHorizontalLayoutManager(){} static LinearHorizontalLayoutManager* create(); - virtual void doLayout(LayoutProtocol* layout) override; + void doLayout(LayoutProtocol* layout) override; friend class Layout; }; @@ -105,7 +105,7 @@ class AX_GUI_DLL LinearCenterVerticalLayoutManager : public LayoutManager LinearCenterVerticalLayoutManager(){} virtual ~LinearCenterVerticalLayoutManager(){} static LinearCenterVerticalLayoutManager* create(); - virtual void doLayout(LayoutProtocol* layout) override; + void doLayout(LayoutProtocol* layout) override; friend class Layout; }; @@ -121,7 +121,7 @@ class AX_GUI_DLL LinearCenterHorizontalLayoutManager : public LayoutManager LinearCenterHorizontalLayoutManager(){} virtual ~LinearCenterHorizontalLayoutManager(){} static LinearCenterHorizontalLayoutManager* create(); - virtual void doLayout(LayoutProtocol* layout) override; + void doLayout(LayoutProtocol* layout) override; friend class Layout; }; @@ -144,7 +144,7 @@ class AX_GUI_DLL RelativeLayoutManager : public LayoutManager {} virtual ~RelativeLayoutManager(){} static RelativeLayoutManager* create(); - virtual void doLayout(LayoutProtocol* layout) override; + void doLayout(LayoutProtocol* layout) override; Vector getAllWidgets(LayoutProtocol* layout); Widget* getRelativeWidget(Widget* widget); diff --git a/core/ui/UILayoutParameter.cpp b/axmol/ui/UILayoutParameter.cpp similarity index 98% rename from core/ui/UILayoutParameter.cpp rename to axmol/ui/UILayoutParameter.cpp index 3a523bf77606..b59151596343 100644 --- a/core/ui/UILayoutParameter.cpp +++ b/axmol/ui/UILayoutParameter.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UILayoutParameter.h" -#include "ui/UILayout.h" +#include "axmol/ui/UILayoutParameter.h" +#include "axmol/ui/UILayout.h" namespace ax { diff --git a/core/ui/UILayoutParameter.h b/axmol/ui/UILayoutParameter.h similarity index 96% rename from core/ui/UILayoutParameter.h rename to axmol/ui/UILayoutParameter.h index 502e01a15441..74b463f1d05f 100644 --- a/core/ui/UILayoutParameter.h +++ b/axmol/ui/UILayoutParameter.h @@ -27,8 +27,8 @@ #pragma once #include -#include "base/Object.h" -#include "ui/GUIExport.h" +#include "axmol/base/Object.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -272,8 +272,8 @@ class AX_GUI_DLL LinearLayoutParameter : public LayoutParameter LinearGravity getGravity() const; // override functions. - virtual LayoutParameter* createCloneInstance() override; - virtual void copyProperties(LayoutParameter* model) override; + LayoutParameter* createCloneInstance() override; + void copyProperties(LayoutParameter* model) override; protected: LinearGravity _linearGravity; @@ -387,8 +387,8 @@ class AX_GUI_DLL RelativeLayoutParameter : public LayoutParameter std::string_view getRelativeName() const; // override functions. - virtual LayoutParameter* createCloneInstance() override; - virtual void copyProperties(LayoutParameter* model) override; + LayoutParameter* createCloneInstance() override; + void copyProperties(LayoutParameter* model) override; protected: RelativeAlign _relativeAlign; diff --git a/core/ui/UIListView.cpp b/axmol/ui/UIListView.cpp similarity index 99% rename from core/ui/UIListView.cpp rename to axmol/ui/UIListView.cpp index d3ecf6dc3657..107601c34e7b 100644 --- a/core/ui/UIListView.cpp +++ b/axmol/ui/UIListView.cpp @@ -24,8 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIListView.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIListView.h" +#include "axmol/ui/UIHelper.h" namespace ax { diff --git a/core/ui/UIListView.h b/axmol/ui/UIListView.h similarity index 99% rename from core/ui/UIListView.h rename to axmol/ui/UIListView.h index 34820b7e7a04..55510941a8f7 100644 --- a/core/ui/UIListView.h +++ b/axmol/ui/UIListView.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIScrollView.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIScrollView.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui diff --git a/core/ui/UILoadingBar.cpp b/axmol/ui/UILoadingBar.cpp similarity index 98% rename from core/ui/UILoadingBar.cpp rename to axmol/ui/UILoadingBar.cpp index 74fddf5d6a87..c3f3ac796a6a 100644 --- a/core/ui/UILoadingBar.cpp +++ b/axmol/ui/UILoadingBar.cpp @@ -24,10 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UILoadingBar.h" -#include "ui/UIHelper.h" -#include "ui/UIScale9Sprite.h" -#include "2d/Sprite.h" +#include "axmol/ui/UILoadingBar.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/2d/Sprite.h" namespace ax { diff --git a/core/ui/UILoadingBar.h b/axmol/ui/UILoadingBar.h similarity index 91% rename from core/ui/UILoadingBar.h rename to axmol/ui/UILoadingBar.h index 0769ef02cbbc..036671931bbe 100644 --- a/core/ui/UILoadingBar.h +++ b/axmol/ui/UILoadingBar.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -164,16 +164,16 @@ class AX_GUI_DLL LoadingBar : public Widget const Rect& getCapInsets() const; // override methods. - virtual void ignoreContentAdaptWithSize(bool ignore) override; - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; - virtual std::string getDescription() const override; + void ignoreContentAdaptWithSize(bool ignore) override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; + std::string getDescription() const override; ResourceData getRenderFile(); protected: - virtual void initRenderer() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onSizeChanged() override; void setScale9Scale(); void updateProgressBar(); @@ -183,10 +183,10 @@ class AX_GUI_DLL LoadingBar : public Widget void handleSpriteFlipX(); void loadTexture(SpriteFrame* spriteframe); - virtual void adaptRenderers() override; + void adaptRenderers() override; - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; protected: Direction _direction; diff --git a/core/ui/UIMediaPlayer.cpp b/axmol/ui/UIMediaPlayer.cpp similarity index 93% rename from core/ui/UIMediaPlayer.cpp rename to axmol/ui/UIMediaPlayer.cpp index be7f8fe6da4c..1ccaffc4f8e6 100644 --- a/core/ui/UIMediaPlayer.cpp +++ b/axmol/ui/UIMediaPlayer.cpp @@ -24,21 +24,20 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIMediaPlayer.h" +#include "axmol/ui/UIMediaPlayer.h" // Now, common implementation based on redesigned MediaEngine is enable for windows and macOS #if defined(AX_ENABLE_MEDIA) # include # include # include -# include "base/Director.h" -# include "base/EventListenerKeyboard.h" -# include "platform/FileUtils.h" -# include "ui/UIHelper.h" -# include "media/MediaEngine.h" -# include "ui/LayoutHelper.h" -# include "UIButton.h" -# include "UILayout.h" +# include "axmol/base/Director.h" +# include "axmol/base/EventListenerKeyboard.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/ui/UIHelper.h" +# include "axmol/media/MediaEngine.h" +# include "axmol/ui/UIButton.h" +# include "axmol/ui/UILayout.h" # include "yasio/byte_buffer.hpp" //----------------------------------------------------------------------------------------------------------- @@ -65,7 +64,7 @@ using namespace ax::ui; namespace { -struct PrivateVideoDescriptor +struct PrivateVideoDesc { MediaEngine* _engine = nullptr; Texture2D* _vtexture = nullptr; @@ -149,7 +148,7 @@ struct PrivateVideoDescriptor } } - LayoutHelper::centerNode(_vrender); + ui::Helper::centerNode(_vrender); _vrender->setVisible(true); } @@ -160,7 +159,7 @@ struct PrivateVideoDescriptor _scaleDirty = false; } - static void updateColorTransform(backend::ProgramState* ps, bool bFullColorRange) + static void updateColorTransform(rhi::ProgramState* ps, bool bFullColorRange) { // clang-format off // 1.16438356 ~= 255/219.0 @@ -220,7 +219,7 @@ void createMediaControlTexture() auto DrawStop = [&](const Vec2& middle) -> void { auto s = Vec2(middle.x - iconW / 2.f, middle.y + iconH / 2.f); - drawNode->drawSolidRect(s, s + Vec2(iconW, -iconH), Color4B::WHITE); + drawNode->drawSolidRect(s, s + Vec2(iconW, -iconH), Color::WHITE); }; auto DrawPlay = [&](const Vec2& middle) -> void { @@ -228,15 +227,15 @@ void createMediaControlTexture() auto p2 = Vec2(middle.x + iconW / 2.f, middle.y); auto p3 = Vec2(middle.x - iconW / 2.f, middle.y - iconH / 2.f); - drawNode->drawTriangle(p1, p2, p3, Color4B::WHITE); + drawNode->drawTriangle(p1, p2, p3, Color::WHITE); }; auto DrawPause = [&](const Vec2& middle) -> void { auto start = Vec2(middle.x - 3, middle.y + iconH / 2.f); - drawNode->drawSolidRect(start, start + Vec2(-6, -iconH), Color4B::WHITE); + drawNode->drawSolidRect(start, start + Vec2(-6, -iconH), Color::WHITE); start = Vec2(middle.x + 3, middle.y + iconH / 2.f); - drawNode->drawSolidRect(start, start + Vec2(6, -iconH), Color4B::WHITE); + drawNode->drawSolidRect(start, start + Vec2(6, -iconH), Color::WHITE); }; auto DrawEnterFullscreen = [&](const Vec2& middle) -> void { @@ -246,20 +245,20 @@ void createMediaControlTexture() auto bottomRight = Vec2(middle.x + panelW / 2.f - 6, middle.y - panelH / 2.f + 6); // Top left - drawNode->drawSolidRect(topLeft, topLeft + Vec2(20, -6), Color4B::WHITE); - drawNode->drawSolidRect(topLeft, topLeft + Vec2(6, -20), Color4B::WHITE); + drawNode->drawSolidRect(topLeft, topLeft + Vec2(20, -6), Color::WHITE); + drawNode->drawSolidRect(topLeft, topLeft + Vec2(6, -20), Color::WHITE); // Top right - drawNode->drawSolidRect(topRight, topRight + Vec2(-20, -6), Color4B::WHITE); - drawNode->drawSolidRect(topRight, topRight + Vec2(-6, -20), Color4B::WHITE); + drawNode->drawSolidRect(topRight, topRight + Vec2(-20, -6), Color::WHITE); + drawNode->drawSolidRect(topRight, topRight + Vec2(-6, -20), Color::WHITE); // Bottom left - drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(20, 6), Color4B::WHITE); - drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(6, 20), Color4B::WHITE); + drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(20, 6), Color::WHITE); + drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(6, 20), Color::WHITE); // Bottom right - drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(-20, 6), Color4B::WHITE); - drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(-6, 20), Color4B::WHITE); + drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(-20, 6), Color::WHITE); + drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(-6, 20), Color::WHITE); }; auto DrawExitFullScreen = [&](const Vec2& middle) -> void { @@ -269,24 +268,24 @@ void createMediaControlTexture() auto bottomRight = Vec2(middle.x + 4, middle.y - 4); // Top left - drawNode->drawSolidRect(topLeft, topLeft + Vec2(-20, 6), Color4B::WHITE); - drawNode->drawSolidRect(topLeft, topLeft + Vec2(-6, 20), Color4B::WHITE); + drawNode->drawSolidRect(topLeft, topLeft + Vec2(-20, 6), Color::WHITE); + drawNode->drawSolidRect(topLeft, topLeft + Vec2(-6, 20), Color::WHITE); // Top right - drawNode->drawSolidRect(topRight, topRight + Vec2(20, 6), Color4B::WHITE); - drawNode->drawSolidRect(topRight, topRight + Vec2(6, 20), Color4B::WHITE); + drawNode->drawSolidRect(topRight, topRight + Vec2(20, 6), Color::WHITE); + drawNode->drawSolidRect(topRight, topRight + Vec2(6, 20), Color::WHITE); // Bottom left - drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(-20, -6), Color4B::WHITE); - drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(-6, -20), Color4B::WHITE); + drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(-20, -6), Color::WHITE); + drawNode->drawSolidRect(bottomLeft, bottomLeft + Vec2(-6, -20), Color::WHITE); // Bottom right - drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(20, -6), Color4B::WHITE); - drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(6, -20), Color4B::WHITE); + drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(20, -6), Color::WHITE); + drawNode->drawSolidRect(bottomRight, bottomRight + Vec2(6, -20), Color::WHITE); }; auto DrawSliderControlButton = [&](const Vec2& middle) -> void { - drawNode->drawSolidCircle(middle, panelW / 2, 0, 180, Color4B::WHITE); + drawNode->drawSolidCircle(middle, panelW / 2, 0, 180, Color::WHITE); }; std::map> items = { @@ -320,7 +319,7 @@ void createMediaControlTexture() Vec2(border + (i * panelW) + (i * gap) + (panelW / 2.f), imageSize.height - border - (panelH / 2.f)); item.second(midPoint); -# if defined(AX_USE_GL) +# if AX_RENDER_API == AX_RENDER_API_GL g_mediaControlTextureRegions[item.first] = Rect(border + (panelW * i) + (gap * i), imageSize.height - border - panelH, panelW, panelH); # else // For Metal renderer @@ -653,7 +652,7 @@ void BasicMediaController::createControls() auto scale = Director::getInstance()->getRenderView()->getScaleY(); _mediaOverlay = Layout::create(); - _mediaOverlay->setBackGroundColor(Color3B::BLACK); + _mediaOverlay->setBackGroundColor(Color32::BLACK); _mediaOverlay->setBackGroundColorType(Layout::BackGroundColorType::SOLID); _mediaOverlay->setAnchorPoint(Vec2::ANCHOR_MIDDLE); _mediaOverlay->setPositionNormalized(Vec2(0.5f, 0.5f)); @@ -760,7 +759,7 @@ void BasicMediaController::createControls() _timelineTotal->setAnchorPoint(Vec2::ANCHOR_MIDDLE_BOTTOM); _timelineTotal->setStretchEnabled(true); _timelineTotal->setPositionNormalized(Vec2(0.5f, 0.1f)); - _timelineTotal->setColor(Color3B::GRAY); + _timelineTotal->setColor(Color32::GRAY); _timelineTotal->setVisible(false); _timelineTotal->setCascadeOpacityEnabled(true); _timelineTotal->setContentSize(Size(contentSize.width - 40, _timelineBarHeight / scale)); @@ -770,7 +769,7 @@ void BasicMediaController::createControls() _timelinePlayed->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); _timelinePlayed->setStretchEnabled(true); _timelinePlayed->setPositionNormalized(Vec2(0.0f, 0.5f)); - _timelinePlayed->setColor(Color3B::WHITE); + _timelinePlayed->setColor(Color32::WHITE); _timelinePlayed->setCascadeOpacityEnabled(true); _timelineTotal->addChild(_timelinePlayed, 5); @@ -869,7 +868,7 @@ void BasicMediaController::updateControlsForContentSize(const Vec2& contentSize) MediaPlayer::MediaPlayer() { - auto pvd = new PrivateVideoDescriptor{}; + auto pvd = new PrivateVideoDesc{}; _videoContext = pvd; # if AX_VIDEOPLAYER_DEBUG_DRAW _debugDrawNode = DrawNode::create(); @@ -949,16 +948,16 @@ MediaPlayer::MediaPlayer() switch (pixelFormat) { case MEVideoPixelFormat::YUY2: - pvd->_vrender->setProgramState(backend::ProgramType::VIDEO_TEXTURE_YUY2); + pvd->_vrender->setProgramState(rhi::ProgramType::VIDEO_TEXTURE_YUY2); break; case MEVideoPixelFormat::NV12: - pvd->_vrender->setProgramState(backend::ProgramType::VIDEO_TEXTURE_NV12); + pvd->_vrender->setProgramState(rhi::ProgramType::VIDEO_TEXTURE_NV12); break; case MEVideoPixelFormat::I420: - pvd->_vrender->setProgramState(backend::ProgramType::VIDEO_TEXTURE_I420); + pvd->_vrender->setProgramState(rhi::ProgramType::VIDEO_TEXTURE_I420); break; default: - pvd->_vrender->setProgramState(backend::ProgramType::VIDEO_TEXTURE_RGB32); + pvd->_vrender->setProgramState(rhi::ProgramType::VIDEO_TEXTURE_RGB32); } } @@ -1016,7 +1015,7 @@ MediaPlayer::MediaPlayer() if (pixelFormat >= MEVideoPixelFormat::YUY2) { auto ps = pvd->_vrender->getProgramState(); - PrivateVideoDescriptor::updateColorTransform(ps, frame._vpd._fullRange); + PrivateVideoDesc::updateColorTransform(ps, frame._vpd._fullRange); ps->setTexture(ps->getUniformLocation("u_tex1"), 1, pvd->_vchromaTexture->getBackendTexture()); @@ -1036,7 +1035,7 @@ MediaPlayer::MediaPlayer() MediaPlayer::~MediaPlayer() { - auto pvd = reinterpret_cast(_videoContext); + auto pvd = reinterpret_cast(_videoContext); removeAllProtectedChildren(); @@ -1078,7 +1077,7 @@ void MediaPlayer::setFileName(std::string_view fileName) auto fullPath = FileUtils::getInstance()->fullPathForFilename(fileName); if (ax::utils::filePathToUrl(std::forward(fullPath)) != _videoURL) { - reinterpret_cast(_videoContext)->closePlayer(); + reinterpret_cast(_videoContext)->closePlayer(); _videoURL = std::move(fullPath); } _videoSource = MediaPlayer::Source::FILENAME; @@ -1088,7 +1087,7 @@ void MediaPlayer::setURL(std::string_view videoUrl) { if (_videoURL != videoUrl) { - reinterpret_cast(_videoContext)->closePlayer(); + reinterpret_cast(_videoContext)->closePlayer(); _videoURL = videoUrl; } _videoSource = MediaPlayer::Source::URL; @@ -1098,7 +1097,7 @@ void MediaPlayer::setLooping(bool looping) { _isLooping = looping; - auto pvd = reinterpret_cast(_videoContext); + auto pvd = reinterpret_cast(_videoContext); if (pvd->_engine) pvd->_engine->setLoop(looping); } @@ -1123,7 +1122,7 @@ void MediaPlayer::setStyle(StyleType style) Node* MediaPlayer::getVirtualRenderer() { - auto pvd = reinterpret_cast(_videoContext); + auto pvd = reinterpret_cast(_videoContext); return pvd->_vrender; } @@ -1131,7 +1130,7 @@ void MediaPlayer::draw(Renderer* renderer, const Mat4& transform, uint32_t flags { ax::ui::Widget::draw(renderer, transform, flags); - auto pvd = reinterpret_cast(_videoContext); + auto pvd = reinterpret_cast(_videoContext); auto vrender = pvd->_vrender; auto engine = pvd->_engine; if (!vrender || !engine) @@ -1148,14 +1147,14 @@ void MediaPlayer::draw(Renderer* renderer, const Mat4& transform, uint32_t flags _debugDrawNode->clear(); auto size = getContentSize(); Point vertices[4] = {Point::ZERO, Point(size.width, 0), Point(size.width, size.height), Point(0, size.height)}; - _debugDrawNode->drawPoly(vertices, 4, true, Color4B::WHITE); + _debugDrawNode->drawPoly(vertices, 4, true, Color32::WHITE); # endif } void MediaPlayer::setContentSize(const Size& contentSize) { Widget::setContentSize(contentSize); - auto videoContext = reinterpret_cast(_videoContext); + auto videoContext = reinterpret_cast(_videoContext); videoContext->_originalViewSize = contentSize; if (_mediaController) { @@ -1168,7 +1167,7 @@ MediaPlayer::MediaState MediaPlayer::getState() const if (_videoURL.empty()) return MediaState::CLOSED; - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { switch (engine->getState()) @@ -1215,7 +1214,7 @@ void MediaPlayer::setFullScreenEnabled(bool enabled) { _fullScreenEnabled = enabled; - auto pvd = reinterpret_cast(_videoContext); + auto pvd = reinterpret_cast(_videoContext); const auto contentSize = enabled ? _director->getRenderView()->getDesignResolutionSize() : pvd->_originalViewSize; Widget::setContentSize(contentSize); @@ -1233,7 +1232,7 @@ void MediaPlayer::setKeepAspectRatioEnabled(bool enable) if (_keepAspectRatioEnabled != enable) { _keepAspectRatioEnabled = enable; - reinterpret_cast(_videoContext)->_scaleDirty = true; + reinterpret_cast(_videoContext)->_scaleDirty = true; } } @@ -1241,7 +1240,7 @@ void MediaPlayer::setPlayRate(float fRate) { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) engine->setRate(fRate); } @@ -1251,7 +1250,7 @@ void MediaPlayer::play() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { switch (engine->getState()) @@ -1284,7 +1283,7 @@ void MediaPlayer::pausePlayback() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { engine->pause(); @@ -1297,7 +1296,7 @@ void MediaPlayer::resumePlayback() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { switch (engine->getState()) @@ -1316,7 +1315,7 @@ void MediaPlayer::stop() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { engine->stop(); @@ -1329,7 +1328,7 @@ void MediaPlayer::seekTo(float sec) { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { engine->setCurrentTime(sec); @@ -1342,7 +1341,7 @@ float MediaPlayer::getCurrentTime() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { return static_cast(engine->getCurrentTime()); @@ -1356,7 +1355,7 @@ float MediaPlayer::getDuration() { if (!_videoURL.empty()) { - auto engine = reinterpret_cast(_videoContext)->_engine; + auto engine = reinterpret_cast(_videoContext)->_engine; if (engine) { return static_cast(engine->getDuration()); diff --git a/core/ui/UIMediaPlayer.h b/axmol/ui/UIMediaPlayer.h similarity index 98% rename from core/ui/UIMediaPlayer.h rename to axmol/ui/UIMediaPlayer.h index 2004fb926770..6d503a0f8272 100644 --- a/core/ui/UIMediaPlayer.h +++ b/axmol/ui/UIMediaPlayer.h @@ -27,15 +27,15 @@ #if defined(AX_ENABLE_MEDIA) -# include "UIButton.h" -# include "ui/UIWidget.h" -# include "ui/UILayout.h" -# include "2d/Sprite.h" +# include "axmol/ui/UIButton.h" +# include "axmol/ui/UIWidget.h" +# include "axmol/ui/UILayout.h" +# include "axmol/2d/Sprite.h" # include # if AX_VIDEOPLAYER_DEBUG_DRAW -# include "2d/DrawNode.h" +# include "axmol/2d/DrawNode.h" # endif # undef ERROR diff --git a/core/ui/UIPageView.cpp b/axmol/ui/UIPageView.cpp similarity index 96% rename from core/ui/UIPageView.cpp rename to axmol/ui/UIPageView.cpp index 9d67a61adf4b..f871c8da4236 100644 --- a/core/ui/UIPageView.cpp +++ b/axmol/ui/UIPageView.cpp @@ -24,8 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIPageView.h" -#include "ui/UIPageViewIndicator.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/ui/UIPageViewIndicator.h" namespace ax { @@ -350,7 +350,7 @@ void PageView::setIndicatorEnabled(bool enabled) _indicator = PageViewIndicator::create(); _indicator->setDirection(getDirection()); addProtectedChild(_indicator, 10000); - setIndicatorSelectedIndexColor(Color3B(100, 100, 255)); + setIndicatorSelectedIndexColor(Color32(100, 100, 255, 255)); refreshIndicatorPosition(); } } @@ -396,7 +396,7 @@ float PageView::getIndicatorSpaceBetweenIndexNodes() const return _indicator->getSpaceBetweenIndexNodes(); } -void PageView::setIndicatorSelectedIndexColor(const Color3B& color) +void PageView::setIndicatorSelectedIndexColor(const Color32& color) { if (_indicator != nullptr) { @@ -404,13 +404,13 @@ void PageView::setIndicatorSelectedIndexColor(const Color3B& color) } } -const Color3B& PageView::getIndicatorSelectedIndexColor() const +const Color32& PageView::getIndicatorSelectedIndexColor() const { AXASSERT(_indicator != nullptr, ""); return _indicator->getSelectedIndexColor(); } -void PageView::setIndicatorIndexNodesColor(const Color3B& color) +void PageView::setIndicatorIndexNodesColor(const Color32& color) { if (_indicator != nullptr) { @@ -418,7 +418,7 @@ void PageView::setIndicatorIndexNodesColor(const Color3B& color) } } -const Color3B& PageView::getIndicatorIndexNodesColor() const +const Color32& PageView::getIndicatorIndexNodesColor() const { AXASSERT(_indicator != nullptr, ""); return _indicator->getIndexNodesColor(); diff --git a/core/ui/UIPageView.h b/axmol/ui/UIPageView.h similarity index 89% rename from core/ui/UIPageView.h rename to axmol/ui/UIPageView.h index c1ec8b6ee620..689958e1cc31 100644 --- a/core/ui/UIPageView.h +++ b/axmol/ui/UIPageView.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIListView.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIListView.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -98,7 +98,7 @@ class AX_GUI_DLL PageView : public ListView * Direction Direction::VERTICAL means vertical scroll, Direction::HORIZONTAL means horizontal scroll. * @param direction Set the page view's scroll direction. */ - virtual void setDirection(Direction direction) override; + void setDirection(Direction direction) override; /** * Insert a page into the end of PageView. @@ -186,7 +186,7 @@ class AX_GUI_DLL PageView : public ListView void addEventListener(const ccPageViewCallback& callback); using ScrollView::addEventListener; // override methods - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * @brief Toggle page indicator enabled. @@ -249,28 +249,28 @@ class AX_GUI_DLL PageView : public ListView * * @param color New color for selected (current) index. */ - void setIndicatorSelectedIndexColor(const Color3B& color); + void setIndicatorSelectedIndexColor(const Color32& color); /** * @brief Get the color of page indicator's selected index. * * @return color */ - const Color3B& getIndicatorSelectedIndexColor() const; + const Color32& getIndicatorSelectedIndexColor() const; /** * @brief Set color of page indicator's index nodes. * * @param color New indicator node color. */ - void setIndicatorIndexNodesColor(const Color3B& color); + void setIndicatorIndexNodesColor(const Color32& color); /** * @brief Get the color of page indicator's index nodes. * * @return color */ - const Color3B& getIndicatorIndexNodesColor() const; + const Color32& getIndicatorIndexNodesColor() const; /** * @brief Set opacity of page indicator's selected index. @@ -325,24 +325,24 @@ class AX_GUI_DLL PageView : public ListView void setAutoScrollStopEpsilon(float epsilon); - virtual bool init() override; + bool init() override; // override methods - virtual void doLayout() override; + void doLayout() override; protected: void pageTurningEvent(); - virtual float getAutoScrollStopEpsilon() const override; + float getAutoScrollStopEpsilon() const override; - virtual void remedyLayoutParameter(Widget* item) override; - virtual void moveInnerContainer(const Vec2& deltaMove, bool canStartBounceBack) override; - virtual void onItemListChanged() override; - virtual void onSizeChanged() override; - virtual void handleReleaseLogic(Touch* touch) override; - virtual void handlePressLogic(Touch* touch) override; + void remedyLayoutParameter(Widget* item) override; + void moveInnerContainer(const Vec2& deltaMove, bool canStartBounceBack) override; + void onItemListChanged() override; + void onSizeChanged() override; + void handleReleaseLogic(Touch* touch) override; + void handlePressLogic(Touch* touch) override; - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; void refreshIndicatorPosition(); diff --git a/core/ui/UIPageViewIndicator.cpp b/axmol/ui/UIPageViewIndicator.cpp similarity index 96% rename from core/ui/UIPageViewIndicator.cpp rename to axmol/ui/UIPageViewIndicator.cpp index 0aa66e9ce1de..179e8e5cb022 100644 --- a/core/ui/UIPageViewIndicator.cpp +++ b/axmol/ui/UIPageViewIndicator.cpp @@ -24,9 +24,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIPageViewIndicator.h" -#include "2d/Sprite.h" -#include "base/Utils.h" +#include "axmol/ui/UIPageViewIndicator.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/Utils.h" static const char* CIRCLE_IMAGE = "iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAQAAADZc7J/AAAA8ElEQVRIx62VyRGCQBBF+6gWRCEmYDIQkhiBCgHhSclC8YqWzOV5oVzKAYZp3r1/" @@ -66,8 +66,7 @@ PageViewIndicator::PageViewIndicator() , _currentOverlappingIndexNode(nullptr) , _spaceBetweenIndexNodes(SPACE_BETWEEN_INDEX_NODES_DEFAULT) , _indexNodesScale(1.0f) - , _indexNodesColor(Color3B::WHITE) - , _indexNodesOpacity(INDEX_NODES_OPACITY_DEFAULT) + , _indexNodesColor(Color32{255, 255, 255, INDEX_NODES_OPACITY_DEFAULT}) , _useDefaultTexture(true) , _indexNodesTextureFile("") , _indexNodesTexType(Widget::TextureResType::LOCAL) @@ -163,7 +162,7 @@ void PageViewIndicator::setSpaceBetweenIndexNodes(float spaceBetweenIndexNodes) rearrange(); } -void PageViewIndicator::setIndexNodesColor(const Color3B& indexNodesColor) +void PageViewIndicator::setIndexNodesColor(const Color32& indexNodesColor) { _indexNodesColor = indexNodesColor; @@ -175,7 +174,7 @@ void PageViewIndicator::setIndexNodesColor(const Color3B& indexNodesColor) void PageViewIndicator::setIndexNodesOpacity(uint8_t opacity) { - _indexNodesOpacity = opacity; + _indexNodesColor.a = opacity; for (auto&& indexNode : _indexNodes) indexNode->setOpacity(opacity); } @@ -256,7 +255,6 @@ void PageViewIndicator::increaseNumberOfPages() indexNode->setColor(_indexNodesColor); indexNode->setScale(_indexNodesScale); - indexNode->setOpacity(_indexNodesOpacity); addProtectedChild(indexNode); _indexNodes.pushBack(indexNode); } diff --git a/core/ui/UIPageViewIndicator.h b/axmol/ui/UIPageViewIndicator.h similarity index 88% rename from core/ui/UIPageViewIndicator.h rename to axmol/ui/UIPageViewIndicator.h index 69d83dcd2978..cb5831820154 100644 --- a/core/ui/UIPageViewIndicator.h +++ b/axmol/ui/UIPageViewIndicator.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIPageView.h" -#include "2d/Sprite.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/2d/Sprite.h" namespace ax { @@ -58,16 +58,16 @@ class PageViewIndicator : public ProtectedNode void clear(); void setSpaceBetweenIndexNodes(float spaceBetweenIndexNodes); float getSpaceBetweenIndexNodes() const { return _spaceBetweenIndexNodes; } - void setSelectedIndexColor(const Color3B& color) { _currentIndexNode->setColor(color); } - const Color3B& getSelectedIndexColor() const { return _currentIndexNode->getColor(); } - void setIndexNodesColor(const Color3B& indexNodesColor); - const Color3B& getIndexNodesColor() const { return _indexNodesColor; } + void setSelectedIndexColor(const Color32& color) { _currentIndexNode->setColor(color); } + const Color32& getSelectedIndexColor() const { return _currentIndexNode->getColor(); } + void setIndexNodesColor(const Color32& indexNodesColor); + const Color32& getIndexNodesColor() const { return _indexNodesColor; } void setIndexNodesScale(float indexNodesScale); float getIndexNodesScale() const { return _indexNodesScale; } void setSelectedIndexOpacity(uint8_t opacity) { _currentIndexNode->setOpacity(opacity); } uint8_t getSelectedIndexOpacity() const { return _currentIndexNode->getOpacity(); } void setIndexNodesOpacity(uint8_t opacity); - uint8_t getIndexNodesOpacity() const { return _indexNodesOpacity; } + uint8_t getIndexNodesOpacity() const { return _indexNodesColor.a; } /** * Sets texture for index nodes. @@ -89,8 +89,7 @@ class PageViewIndicator : public ProtectedNode Sprite* _currentOverlappingIndexNode; float _spaceBetweenIndexNodes; float _indexNodesScale; - Color3B _indexNodesColor; - uint8_t _indexNodesOpacity; + Color32 _indexNodesColor; bool _useDefaultTexture; std::string _indexNodesTextureFile; diff --git a/core/ui/UIRadioButton.cpp b/axmol/ui/UIRadioButton.cpp similarity index 99% rename from core/ui/UIRadioButton.cpp rename to axmol/ui/UIRadioButton.cpp index 5b3c4f6b519d..9d5041ed8468 100644 --- a/core/ui/UIRadioButton.cpp +++ b/axmol/ui/UIRadioButton.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIRadioButton.h" +#include "axmol/ui/UIRadioButton.h" namespace ax { diff --git a/core/ui/UIRadioButton.h b/axmol/ui/UIRadioButton.h similarity index 93% rename from core/ui/UIRadioButton.h rename to axmol/ui/UIRadioButton.h index a0cdacbb9599..fe3cccf75ddb 100644 --- a/core/ui/UIRadioButton.h +++ b/axmol/ui/UIRadioButton.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIAbstractCheckButton.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIAbstractCheckButton.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -124,15 +124,15 @@ class AX_GUI_DLL RadioButton : public AbstractCheckButton */ void addEventListener(const ccRadioButtonCallback& callback); - virtual std::string getDescription() const override; + std::string getDescription() const override; protected: - virtual void releaseUpEvent() override; + void releaseUpEvent() override; - virtual void dispatchSelectChangedEvent(bool selected) override; + void dispatchSelectChangedEvent(bool selected) override; - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; ccRadioButtonCallback _radioButtonEventCallback; RadioButtonGroup* _group; @@ -272,11 +272,11 @@ class AX_GUI_DLL RadioButtonGroup : public Widget */ bool isAllowedNoSelection() const; - virtual std::string getDescription() const override; + std::string getDescription() const override; protected: - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; void onChangedRadioButtonSelect(RadioButton* radioButton); void deselect(); diff --git a/core/ui/UIRelativeBox.cpp b/axmol/ui/UIRelativeBox.cpp similarity index 98% rename from core/ui/UIRelativeBox.cpp rename to axmol/ui/UIRelativeBox.cpp index 89076b23bf65..006e68cf2799 100644 --- a/core/ui/UIRelativeBox.cpp +++ b/axmol/ui/UIRelativeBox.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIRelativeBox.h" +#include "axmol/ui/UIRelativeBox.h" namespace ax { diff --git a/core/ui/UIRelativeBox.h b/axmol/ui/UIRelativeBox.h similarity index 96% rename from core/ui/UIRelativeBox.h rename to axmol/ui/UIRelativeBox.h index 8ac85a311ed7..979ed35db998 100644 --- a/core/ui/UIRelativeBox.h +++ b/axmol/ui/UIRelativeBox.h @@ -26,8 +26,8 @@ #pragma once -#include "ui/UILayout.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -74,7 +74,7 @@ class AX_GUI_DLL RelativeBox : public Layout static RelativeBox* create(const Vec2& size); // initializes state of widget. - virtual bool init() override; + bool init() override; virtual bool initWithSize(const Vec2& size); }; diff --git a/core/ui/UIRichText.cpp b/axmol/ui/UIRichText.cpp similarity index 88% rename from core/ui/UIRichText.cpp rename to axmol/ui/UIRichText.cpp index 9c119bdd7dad..cb1d6b8ebf5d 100644 --- a/core/ui/UIRichText.cpp +++ b/axmol/ui/UIRichText.cpp @@ -24,27 +24,28 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIRichText.h" +#include "axmol/ui/UIRichText.h" #include #include #include #include #include - -#include "platform/FileUtils.h" -#include "platform/Application.h" -#include "base/EventListenerTouch.h" -#include "base/EventDispatcher.h" -#include "base/Director.h" -#include "2d/Label.h" -#include "2d/Sprite.h" -#include "base/UTF8.h" -#include "ui/UIHelper.h" - -#include "fmt/compile.h" - -#include "platform/SAXParser.h" +#include + +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/Application.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/charconv.h" +#include "axmol/ui/UIHelper.h" + +#include "axmol/base/format.h" +#include "axmol/platform/SAXParser.h" using namespace ax; using namespace ax::ui; @@ -121,11 +122,10 @@ class UrlTouchListenerComponent : public Component }; const std::string UrlTouchListenerComponent::COMPONENT_NAME("ax_ui_UIRichText_UrlTouchListenerComponent"); -bool RichElement::init(int tag, const Color3B& color, uint8_t opacity) +bool RichElement::init(int tag, const Color32& color) { _tag = tag; _color = color; - _opacity = opacity; return true; } @@ -134,29 +134,28 @@ bool RichElement::equalType(Type type) return (_type == type); } -void RichElement::setColor(const Color3B& color) +void RichElement::setColor(const Color32& color) { _color = color; } RichElementText* RichElementText::create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view text, std::string_view fontName, float fontSize, uint32_t flags, std::string_view url, - const Color3B& outlineColor, + const Color32& outlineColor, int outlineSize, - const Color3B& shadowColor, + const Color32& shadowColor, const Vec2& shadowOffset, int shadowBlurRadius, - const Color3B& glowColor, + const Color32& glowColor, std::string_view id) { RichElementText* element = new RichElementText(); - if (element->init(tag, color, opacity, text, fontName, fontSize, flags, url, outlineColor, outlineSize, shadowColor, + if (element->init(tag, color, text, fontName, fontSize, flags, url, outlineColor, outlineSize, shadowColor, shadowOffset, shadowBlurRadius, glowColor, id)) { element->autorelease(); @@ -167,22 +166,21 @@ RichElementText* RichElementText::create(int tag, } bool RichElementText::init(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view text, std::string_view fontName, float fontSize, uint32_t flags, std::string_view url, - const Color3B& outlineColor, + const Color32& outlineColor, int outlineSize, - const Color3B& shadowColor, + const Color32& shadowColor, const Vec2& shadowOffset, int shadowBlurRadius, - const Color3B& glowColor, + const Color32& glowColor, std::string_view id) { - if (RichElement::init(tag, color, opacity)) + if (RichElement::init(tag, color)) { _text = text; _fontName = fontName; @@ -202,15 +200,14 @@ bool RichElementText::init(int tag, } RichElementImage* RichElementImage::create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view filePath, std::string_view url, Widget::TextureResType texType, std::string_view id) { RichElementImage* element = new RichElementImage(); - if (element->init(tag, color, opacity, filePath, url, texType, id)) + if (element->init(tag, color, filePath, url, texType, id)) { element->autorelease(); return element; @@ -220,14 +217,13 @@ RichElementImage* RichElementImage::create(int tag, } bool RichElementImage::init(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view filePath, std::string_view url, Widget::TextureResType texType, std::string_view id) { - if (RichElement::init(tag, color, opacity)) + if (RichElement::init(tag, color)) { _filePath = filePath; _width = -1; @@ -263,13 +259,12 @@ void RichElementImage::setId(std::string_view id) } RichElementCustomNode* RichElementCustomNode::create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, ax::Node* customNode, std::string_view id) { RichElementCustomNode* element = new RichElementCustomNode(); - if (element->init(tag, color, opacity, customNode, id)) + if (element->init(tag, color, customNode, id)) { element->autorelease(); return element; @@ -279,12 +274,11 @@ RichElementCustomNode* RichElementCustomNode::create(int tag, } bool RichElementCustomNode::init(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, ax::Node* customNode, std::string_view id) { - if (RichElement::init(tag, color, opacity)) + if (RichElement::init(tag, color)) { _customNode = customNode; _id = id; @@ -294,10 +288,10 @@ bool RichElementCustomNode::init(int tag, return false; } -RichElementNewLine* RichElementNewLine::create(int tag, const Color3B& color, uint8_t opacity) +RichElementNewLine* RichElementNewLine::create(int tag, const Color32& color) { RichElementNewLine* element = new RichElementNewLine(); - if (element->init(tag, color, opacity)) + if (element->init(tag, color)) { element->autorelease(); return element; @@ -306,10 +300,10 @@ RichElementNewLine* RichElementNewLine::create(int tag, const Color3B& color, ui return nullptr; } -RichElementNewLine* RichElementNewLine::create(int tag, int quantity, const Color3B& color, uint8_t opacity) +RichElementNewLine* RichElementNewLine::create(int tag, int quantity, const Color32& color) { RichElementNewLine* element = new RichElementNewLine(quantity); - if (element->init(tag, color, opacity)) + if (element->init(tag, color)) { element->autorelease(); return element; @@ -345,21 +339,21 @@ class MyXMLVisitor : public SAXDelegator std::string face; /*!< font name */ std::string url; /*!< url is a attribute of a anchor tag */ float fontSize; /*!< font size */ - Color3B color; /*!< font color */ + Color32 color; /*!< font color */ bool hasColor; /*!< or color is specified? */ bool bold; /*!< bold text */ bool italics; /*!< italic text */ StyleLine line; /*!< underline or strikethrough */ StyleEffect effect; /*!< outline, shadow or glow */ - Color3B outlineColor; /*!< the color of the outline */ + Color32 outlineColor; /*!< the color of the outline */ int outlineSize; /*!< the outline effect size value */ - Color3B shadowColor; /*!< the shadow effect color value */ + Color32 shadowColor; /*!< the shadow effect color value */ Vec2 shadowOffset; /*!< shadow effect offset value */ int shadowBlurRadius; /*!< the shadow effect blur radius */ - Color3B glowColor; /*!< the glow effect color value */ + Color32 glowColor; /*!< the glow effect color value */ std::string name; /*!< the name of this element */ - void setColor(const Color3B& acolor) + void setColor(const Color32& acolor) { color = acolor; hasColor = true; @@ -395,7 +389,7 @@ class MyXMLVisitor : public SAXDelegator explicit MyXMLVisitor(RichText* richText); ~MyXMLVisitor() override; - Color3B getColor() const; + Color32 getColor() const; float getFontSize() const; @@ -411,11 +405,11 @@ class MyXMLVisitor : public SAXDelegator bool getStrikethrough() const; - std::tuple getOutline() const; + std::tuple getOutline() const; - std::tuple getShadow() const; + std::tuple getShadow() const; - std::tuple getGlow() const; + std::tuple getGlow() const; std::string getName() const; @@ -582,7 +576,7 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri RichElementImage* elementImg = nullptr; if (!src.empty()) { - elementImg = RichElementImage::create(0, Color3B::WHITE, 255, src, "", resType); + elementImg = RichElementImage::create(0, Color32::WHITE, src, "", resType); if (height >= 0) elementImg->setHeight(height); if (width >= 0) @@ -617,7 +611,7 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri }); MyXMLVisitor::setTagDescription("br", false, [](const ValueMap& /*tagAttrValueMap*/) { - RichElementNewLine* richElement = RichElementNewLine::create(0, Color3B::WHITE, 255); + RichElementNewLine* richElement = RichElementNewLine::create(0, Color32::WHITE); return make_pair(ValueMap(), richElement); }); @@ -647,7 +641,7 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri return make_pair(attrValueMap, nullptr); }, - [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); constexpr auto headerTagEnterHandler = [](const ValueMap& tagAttrValueMap, std::string_view defaultFontSize) -> std::pair { @@ -683,27 +677,27 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri MyXMLVisitor::setTagDescription("h1", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "2em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("h2", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "1.75em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("h3", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "1.5em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("h4", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "1.25em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("h5", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "1.125em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("h6", true, [headerTagEnterHandler](const ValueMap& tagAttrValueMap) { return headerTagEnterHandler(tagAttrValueMap, "1em"); - }, [] { return RichElementNewLine::create(0, 2, Color3B::WHITE, 255); }); + }, [] { return RichElementNewLine::create(0, 2, Color32::WHITE); }); MyXMLVisitor::setTagDescription("outline", true, [](const ValueMap& tagAttrValueMap) { // supported attributes: @@ -763,14 +757,14 @@ MyXMLVisitor::MyXMLVisitor(RichText* richText) : _fontElements(20), _richText(ri MyXMLVisitor::~MyXMLVisitor() {} -Color3B MyXMLVisitor::getColor() const +Color32 MyXMLVisitor::getColor() const { for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i) { if (i->hasColor) return i->color; } - return Color3B::WHITE; + return Color32::WHITE; } float MyXMLVisitor::getFontSize() const @@ -843,34 +837,34 @@ bool MyXMLVisitor::getStrikethrough() const return false; } -std::tuple MyXMLVisitor::getOutline() const +std::tuple MyXMLVisitor::getOutline() const { for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i) { if (i->effect == StyleEffect::OUTLINE) return std::make_tuple(true, i->outlineColor, i->outlineSize); } - return std::make_tuple(false, Color3B::WHITE, -1); + return std::make_tuple(false, Color32::WHITE, -1); } -std::tuple MyXMLVisitor::getShadow() const +std::tuple MyXMLVisitor::getShadow() const { for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i) { if (i->effect == StyleEffect::SHADOW) return std::make_tuple(true, i->shadowColor, i->shadowOffset, i->shadowBlurRadius); } - return std::make_tuple(false, Color3B::BLACK, Vec2(2.0, -2.0), 0); + return std::make_tuple(false, Color32::BLACK, Vec2(2.0, -2.0), 0); } -std::tuple MyXMLVisitor::getGlow() const +std::tuple MyXMLVisitor::getGlow() const { for (auto i = _fontElements.rbegin(), iRend = _fontElements.rend(); i != iRend; ++i) { if (i->effect == StyleEffect::GLOW) return std::make_tuple(true, i->glowColor); } - return std::make_tuple(false, Color3B::WHITE); + return std::make_tuple(false, Color32::WHITE); } std::string MyXMLVisitor::getName() const @@ -907,7 +901,7 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch if (std::regex_match(sizeString, match, fontSizePattern) && match.size() == 3 && !match[1].str().empty()) { - auto scale = static_cast(utils::atof(match[1].str().c_str())); + auto scale = static_cast(utils::atof(match[1].str())); if (match[2].str() == "%") { attributes.fontSize = getFontSize() * scale / 100.f; @@ -932,7 +926,7 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch } if (auto&& itr = attrValueMap.find(RichText::KEY_FONT_COLOR_STRING); itr != attrValueMap.end()) { - attributes.setColor(_richText->color3BWithString(itr->second.asString())); + attributes.setColor(_richText->RichText::parseColor32(itr->second.asString())); } if (auto&& itr = attrValueMap.find(RichText::KEY_FONT_FACE); itr != attrValueMap.end()) { @@ -961,7 +955,7 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch if (auto&& itr = attrValueMap.find(RichText::KEY_URL); itr != attrValueMap.end()) { attributes.url = itr->second.asString(); - attributes.setColor(_richText->getAnchorFontColor3B()); + attributes.setColor(_richText->getAnchorFontColor32()); if (_richText->isAnchorTextBoldEnabled()) { attributes.bold = true; @@ -981,20 +975,20 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch if (_richText->isAnchorTextOutlineEnabled()) { attributes.effect = StyleEffect::OUTLINE; - attributes.outlineColor = _richText->getAnchorTextOutlineColor3B(); + attributes.outlineColor = _richText->getAnchorTextOutlineColor32(); attributes.outlineSize = _richText->getAnchorTextOutlineSize(); } if (_richText->isAnchorTextShadowEnabled()) { attributes.effect = StyleEffect::SHADOW; - attributes.shadowColor = _richText->getAnchorTextShadowColor3B(); + attributes.shadowColor = _richText->getAnchorTextShadowColor32(); attributes.shadowOffset = _richText->getAnchorTextShadowOffset(); attributes.shadowBlurRadius = _richText->getAnchorTextShadowBlurRadius(); } if (_richText->isAnchorTextGlowEnabled()) { attributes.effect = StyleEffect::GLOW; - attributes.glowColor = _richText->getAnchorTextGlowColor3B(); + attributes.glowColor = _richText->getAnchorTextGlowColor32(); } } if (auto&& itr = attrValueMap.find(RichText::KEY_TEXT_STYLE); itr != attrValueMap.end()) @@ -1006,7 +1000,7 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch if (auto&& styleItr = attrValueMap.find(RichText::KEY_TEXT_OUTLINE_COLOR); styleItr != attrValueMap.end()) { - attributes.outlineColor = _richText->color3BWithString(styleItr->second.asString()); + attributes.outlineColor = _richText->RichText::parseColor32(styleItr->second.asString()); } if (auto&& styleItr = attrValueMap.find(RichText::KEY_TEXT_OUTLINE_SIZE); styleItr != attrValueMap.end()) { @@ -1018,7 +1012,7 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch attributes.effect = StyleEffect::SHADOW; if (auto&& styleItr = attrValueMap.find(RichText::KEY_TEXT_SHADOW_COLOR); styleItr != attrValueMap.end()) { - attributes.shadowColor = _richText->color3BWithString(styleItr->second.asString()); + attributes.shadowColor = RichText::parseColor32(styleItr->second.asString()); } auto&& shadowOffsetWidthItr = attrValueMap.find(RichText::KEY_TEXT_SHADOW_OFFSET_WIDTH); @@ -1040,14 +1034,14 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch attributes.effect = StyleEffect::GLOW; if (auto&& styleItr = attrValueMap.find(RichText::KEY_TEXT_GLOW_COLOR); styleItr != attrValueMap.end()) { - attributes.glowColor = _richText->color3BWithString(styleItr->second.asString()); + attributes.glowColor = RichText::parseColor32(styleItr->second.asString()); } } } if (auto&& itr = attrValueMap.find(RichText::KEY_URL); itr != attrValueMap.end()) { attributes.url = itr->second.asString(); - attributes.setColor(_richText->getAnchorFontColor3B()); + attributes.setColor(_richText->getAnchorFontColor32()); if (_richText->isAnchorTextBoldEnabled()) { attributes.bold = true; @@ -1067,20 +1061,20 @@ void MyXMLVisitor::startElement(void* /*ctx*/, const char* elementName, const ch if (_richText->isAnchorTextOutlineEnabled()) { attributes.effect = StyleEffect::OUTLINE; - attributes.outlineColor = _richText->getAnchorTextOutlineColor3B(); + attributes.outlineColor = _richText->getAnchorTextOutlineColor32(); attributes.outlineSize = _richText->getAnchorTextOutlineSize(); } if (_richText->isAnchorTextShadowEnabled()) { attributes.effect = StyleEffect::SHADOW; - attributes.shadowColor = _richText->getAnchorTextShadowColor3B(); + attributes.shadowColor = _richText->getAnchorTextShadowColor32(); attributes.shadowOffset = _richText->getAnchorTextShadowOffset(); attributes.shadowBlurRadius = _richText->getAnchorTextShadowBlurRadius(); } if (_richText->isAnchorTextGlowEnabled()) { attributes.effect = StyleEffect::GLOW; - attributes.glowColor = _richText->getAnchorTextGlowColor3B(); + attributes.glowColor = _richText->getAnchorTextGlowColor32(); } } if (auto&& itr = attrValueMap.find(RichText::KEY_ID); itr != attrValueMap.end()) @@ -1163,7 +1157,7 @@ void MyXMLVisitor::textHandler(void* /*ctx*/, const char* str, size_t len) if (std::get<0>(glow)) flags |= RichElementText::GLOW_FLAG; - auto element = RichElementText::create(0, color, 255, text, face, fontSize, flags, url, std::get<1>(outline), + auto element = RichElementText::create(0, color, text, face, fontSize, flags, url, std::get<1>(outline), std::get<2>(outline), std::get<1>(shadow), std::get<2>(shadow), std::get<3>(shadow), std::get<1>(glow), name); _richText->pushBackElement(element); @@ -1422,9 +1416,9 @@ std::string RichText::getFontColor() return _defaults.at(KEY_FONT_COLOR_STRING).asString(); } -ax::Color3B RichText::getFontColor3B() +ax::Color32 RichText::getFontColor32() { - return color3BWithString(getFontColor()); + return parseColor32(getFontColor()); } void RichText::setFontSize(float size) @@ -1457,9 +1451,9 @@ std::string RichText::getAnchorFontColor() return _defaults.at(KEY_ANCHOR_FONT_COLOR_STRING).asString(); } -ax::Color3B RichText::getAnchorFontColor3B() +ax::Color32 RichText::getAnchorFontColor32() { - return color3BWithString(getAnchorFontColor()); + return parseColor32(getAnchorFontColor()); } void RichText::setAnchorTextBold(bool enable) @@ -1508,13 +1502,13 @@ bool RichText::isAnchorTextUnderlineEnabled() return (_defaults[KEY_ANCHOR_TEXT_LINE].asString() == VALUE_TEXT_LINE_UNDER); } -void RichText::setAnchorTextOutline(bool enable, const Color3B& outlineColor, int outlineSize) +void RichText::setAnchorTextOutline(bool enable, const Color32& outlineColor, int outlineSize) { if (enable) _defaults[KEY_ANCHOR_TEXT_STYLE] = VALUE_TEXT_STYLE_OUTLINE; else if (_defaults[KEY_ANCHOR_TEXT_STYLE].asString() == VALUE_TEXT_STYLE_OUTLINE) _defaults[KEY_ANCHOR_TEXT_STYLE] = VALUE_TEXT_STYLE_NONE; - _defaults[KEY_ANCHOR_TEXT_OUTLINE_COLOR] = stringWithColor3B(outlineColor); + _defaults[KEY_ANCHOR_TEXT_OUTLINE_COLOR] = formatColor32(outlineColor); _defaults[KEY_ANCHOR_TEXT_OUTLINE_SIZE] = outlineSize; } @@ -1523,11 +1517,11 @@ bool RichText::isAnchorTextOutlineEnabled() return (_defaults[KEY_ANCHOR_TEXT_STYLE].asString() == VALUE_TEXT_STYLE_OUTLINE); } -Color3B RichText::getAnchorTextOutlineColor3B() +Color32 RichText::getAnchorTextOutlineColor32() { if (auto&& itr = _defaults.find(KEY_ANCHOR_TEXT_OUTLINE_COLOR); itr != _defaults.end()) { - return color3BWithString(itr->second.asString()); + return parseColor32(itr->second.asString()); } return {}; } @@ -1541,13 +1535,13 @@ int RichText::getAnchorTextOutlineSize() return -1; } -void RichText::setAnchorTextShadow(bool enable, const Color3B& shadowColor, const Vec2& offset, int blurRadius) +void RichText::setAnchorTextShadow(bool enable, const Color32& shadowColor, const Vec2& offset, int blurRadius) { if (enable) _defaults[KEY_ANCHOR_TEXT_STYLE] = VALUE_TEXT_STYLE_SHADOW; else if (_defaults[KEY_ANCHOR_TEXT_STYLE].asString() == VALUE_TEXT_STYLE_SHADOW) _defaults[KEY_ANCHOR_TEXT_STYLE] = VALUE_TEXT_STYLE_NONE; - _defaults[KEY_ANCHOR_TEXT_SHADOW_COLOR] = stringWithColor3B(shadowColor); + _defaults[KEY_ANCHOR_TEXT_SHADOW_COLOR] = formatColor32(shadowColor); _defaults[KEY_ANCHOR_TEXT_SHADOW_OFFSET_WIDTH] = offset.width; _defaults[KEY_ANCHOR_TEXT_SHADOW_OFFSET_HEIGHT] = offset.height; _defaults[KEY_ANCHOR_TEXT_SHADOW_BLUR_RADIUS] = blurRadius; @@ -1558,11 +1552,11 @@ bool RichText::isAnchorTextShadowEnabled() return (_defaults[KEY_ANCHOR_TEXT_STYLE].asString() == VALUE_TEXT_STYLE_SHADOW); } -Color3B RichText::getAnchorTextShadowColor3B() +Color32 RichText::getAnchorTextShadowColor32() { if (auto&& itr = _defaults.find(KEY_ANCHOR_TEXT_SHADOW_COLOR); itr != _defaults.end()) { - return color3BWithString(itr->second.asString()); + return parseColor32(itr->second.asString()); } return {}; } @@ -1591,7 +1585,7 @@ int RichText::getAnchorTextShadowBlurRadius() return 0; } -void RichText::setAnchorTextGlow(bool enable, const Color3B& glowColor) +void RichText::setAnchorTextGlow(bool enable, const Color32& glowColor) { if (enable) { @@ -1602,7 +1596,7 @@ void RichText::setAnchorTextGlow(bool enable, const Color3B& glowColor) { itr->second = VALUE_TEXT_STYLE_NONE; } - _defaults[KEY_ANCHOR_TEXT_GLOW_COLOR] = stringWithColor3B(glowColor); + _defaults[KEY_ANCHOR_TEXT_GLOW_COLOR] = formatColor32(glowColor); } bool RichText::isAnchorTextGlowEnabled() @@ -1610,11 +1604,11 @@ bool RichText::isAnchorTextGlowEnabled() return (_defaults[KEY_ANCHOR_TEXT_STYLE].asString() == VALUE_TEXT_STYLE_GLOW); } -Color3B RichText::getAnchorTextGlowColor3B() +Color32 RichText::getAnchorTextGlowColor32() { if (auto&& itr = _defaults.find(KEY_ANCHOR_TEXT_GLOW_COLOR); itr != _defaults.end()) { - return color3BWithString(itr->second.asString()); + return parseColor32(itr->second.asString()); } return {}; } @@ -1673,40 +1667,59 @@ ValueMap RichText::getDefaults() const return defaults; } -ax::Color3B RichText::color3BWithString(std::string_view color) +static inline bool parseHexDigit(uint8_t& out, const char* p, int n) { - if (color.length() == 4) - { - unsigned int r, g, b; - sscanf(color.data(), "%*c%1x%1x%1x", &r, &g, &b); - r += r * 16; - g += g * 16; - b += b * 16; - return Color3B(r, g, b); - } - else if (color.length() == 7) - { - unsigned int r, g, b; - sscanf(color.data(), "%*c%2x%2x%2x", &r, &g, &b); - return Color3B(r, g, b); - } - else if (color.length() == 9) - { - unsigned int r, g, b, a; - sscanf(color.data(), "%*c%2x%2x%2x%2x", &r, &g, &b, &a); - return Color3B(r, g, b); - } - return Color3B::WHITE; + auto ret = axstd::from_chars(p, p + n, out, 16); + return ret.ec == std::errc{}; } -std::string RichText::stringWithColor3B(const ax::Color3B& color3b) +Color32 RichText::parseColor32(std::string_view color) { - return fmt::format("#{:02x}{:02x}{:02x}", color3b.r, color3b.g, color3b.b); + Color32 ret = Color32::WHITE; + + if (!color.empty() && color[0] == '#') [[likely]] + { + auto ptr = color.data(); + switch (color.length()) + { + case 4: + if (parseHexDigit(ret.r, ptr + 1, 1)) + ret.r += ret.r * 16; + if (parseHexDigit(ret.g, ptr + 2, 1)) + ret.g += ret.g * 16; + if (parseHexDigit(ret.b, ptr + 3, 1)) + ret.b += ret.b * 16; + break; + case 5: + if (parseHexDigit(ret.r, ptr + 1, 1)) + ret.r += ret.r * 16; + if (parseHexDigit(ret.g, ptr + 2, 1)) + ret.g += ret.g * 16; + if (parseHexDigit(ret.b, ptr + 3, 1)) + ret.b += ret.b * 16; + if (parseHexDigit(ret.a, ptr + 4, 1)) + ret.a += ret.a * 16; + break; + case 7: + parseHexDigit(ret.r, ptr + 1, 2); + parseHexDigit(ret.g, ptr + 3, 2); + parseHexDigit(ret.b, ptr + 5, 2); + break; + case 9: + parseHexDigit(ret.r, ptr + 1, 2); + parseHexDigit(ret.g, ptr + 3, 2); + parseHexDigit(ret.b, ptr + 5, 2); + parseHexDigit(ret.a, ptr + 7, 2); + break; + } + } + + return ret; // default color if parsing fails } -std::string RichText::stringWithColor4B(const ax::Color4B& color4b) +std::string RichText::formatColor32(const ax::Color32& color) { - return fmt::format("#{:02x}{:02x}{:02x}{:02x}", color4b.r, color4b.g, color4b.b, color4b.a); + return fmt::format("#{:02x}{:02x}{:02x}{:02x}", color.r, color.g, color.b, color.a); } void RichText::setTagDescription(std::string_view tag, @@ -1780,18 +1793,18 @@ void RichText::formatText(bool force) label, elmtText->_url, [this](std::string_view url) { openUrl(url); })); if (elmtText->_flags & RichElementText::OUTLINE_FLAG) { - label->enableOutline(Color4B(elmtText->_outlineColor), elmtText->_outlineSize); + label->enableOutline(Color32(elmtText->_outlineColor), elmtText->_outlineSize); } if (elmtText->_flags & RichElementText::SHADOW_FLAG) { - label->enableShadow(Color4B(elmtText->_shadowColor), elmtText->_shadowOffset, + label->enableShadow(Color32(elmtText->_shadowColor), elmtText->_shadowOffset, elmtText->_shadowBlurRadius); } if (elmtText->_flags & RichElementText::GLOW_FLAG) { - label->enableGlow(Color4B(elmtText->_glowColor)); + label->enableGlow(Color32(elmtText->_glowColor)); } - label->setTextColor(Color4B(elmtText->_color)); + label->setTextColor(Color32(elmtText->_color)); label->setName(elmtText->_id); @@ -1849,7 +1862,8 @@ void RichText::formatText(bool force) if (elementRenderer) { - elementRenderer->setOpacity(element->_opacity); + // not needed ?? + // elementRenderer->setOpacity(element->_color.a); pushToContainer(elementRenderer); } } @@ -1866,7 +1880,7 @@ void RichText::formatText(bool force) { RichElementText* elmtText = static_cast(element); handleTextRenderer(elmtText->_text, elmtText->_fontName, elmtText->_fontSize, elmtText->_color, - elmtText->_opacity, elmtText->_flags, elmtText->_url, elmtText->_outlineColor, + elmtText->_flags, elmtText->_url, elmtText->_outlineColor, elmtText->_outlineSize, elmtText->_shadowColor, elmtText->_shadowOffset, elmtText->_shadowBlurRadius, elmtText->_glowColor, elmtText->_id); break; @@ -1875,7 +1889,7 @@ void RichText::formatText(bool force) { RichElementImage* elmtImage = static_cast(element); handleImageRenderer(elmtImage->_filePath, elmtImage->_textureType, elmtImage->_color, - elmtImage->_opacity, elmtImage->_width, elmtImage->_height, elmtImage->_url, + elmtImage->_width, elmtImage->_height, elmtImage->_url, elmtImage->_scaleX, elmtImage->_scaleY, elmtImage->_id); break; } @@ -1904,53 +1918,50 @@ void RichText::formatText(bool force) namespace { -inline bool isUTF8CharWrappable(const StringUtils::StringUTF8::CharUTF8& ch) +inline bool isUTF8CharWrappable(const text_utils::u8char_span::value_type& ch) { return (!ch.isASCII() || !std::isgraph(ch._char[0], std::locale())); } -int getPrevWordPos(const StringUtils::StringUTF8& text, int idx) +int getPrevWordPos(const text_utils::u8char_span& text, int idx) { if (idx <= 0) return -1; // start from idx-1 - const StringUtils::StringUTF8::CharUTF8Store& str = text.getString(); - const auto it = std::find_if(str.rbegin() + (str.size() - idx + 1), str.rend(), isUTF8CharWrappable); - if (it == str.rend()) + const auto it = std::find_if(text.rbegin() + (text.size() - idx + 1), text.rend(), isUTF8CharWrappable); + if (it == text.rend()) return -1; - return static_cast(it.base() - str.begin()); + return static_cast(it.base() - text.begin()); } -int getNextWordPos(const StringUtils::StringUTF8& text, int idx) +int getNextWordPos(const text_utils::u8char_span& text, int idx) { - const StringUtils::StringUTF8::CharUTF8Store& str = text.getString(); - if (idx + 1 >= static_cast(str.size())) - return static_cast(str.size()); + if (idx + 1 >= static_cast(text.size())) + return static_cast(text.size()); - const auto it = std::find_if(str.begin() + idx + 1, str.end(), isUTF8CharWrappable); - return static_cast(it - str.begin()); + const auto it = std::find_if(text.begin() + idx + 1, text.end(), isUTF8CharWrappable); + return static_cast(it - text.begin()); } -bool isWrappable(const StringUtils::StringUTF8& text) +bool isWrappable(const text_utils::u8char_span& text) { - const StringUtils::StringUTF8::CharUTF8Store& str = text.getString(); - return std::any_of(str.begin(), str.end(), isUTF8CharWrappable); + return std::any_of(text.begin(), text.end(), isUTF8CharWrappable); } int findSplitPositionForWord(Label* label, - const StringUtils::StringUTF8& text, + const text_utils::u8char_span& text, int estimatedIdx, float originalLeftSpaceWidth, float newLineWidth) { const bool startingNewLine = (newLineWidth == originalLeftSpaceWidth); if (!isWrappable(text)) - return (startingNewLine ? static_cast(text.length()) : 0); + return (startingNewLine ? static_cast(text.size()) : 0); // The adjustment of the new line position - int idx = getNextWordPos(text, estimatedIdx); - std::string leftStr = text.getAsCharSequence(0, idx); + int idx = getNextWordPos(text, estimatedIdx); + auto leftStr = text.subview(0, idx); label->setString(leftStr); float textRendererWidth = label->getContentSize().width; if (originalLeftSpaceWidth < textRendererWidth) // Have protruding @@ -1961,7 +1972,7 @@ int findSplitPositionForWord(Label* label, int newidx = getPrevWordPos(text, idx); if (newidx >= 0) { - leftStr = text.getAsCharSequence(0, newidx); + leftStr = text.subview(0, newidx); label->setString(leftStr); textRendererWidth = label->getContentSize().width; if (textRendererWidth <= originalLeftSpaceWidth) // is fitted @@ -1979,13 +1990,13 @@ int findSplitPositionForWord(Label* label, { // try to append a word int newidx = getNextWordPos(text, idx); - leftStr = text.getAsCharSequence(0, newidx); + leftStr = text.subview(0, newidx); label->setString(leftStr); textRendererWidth = label->getContentSize().width; if (textRendererWidth < originalLeftSpaceWidth) { // the whole string is tested - if (newidx == static_cast(text.length())) + if (newidx == static_cast(text.size())) return newidx; idx = newidx; continue; @@ -1999,42 +2010,52 @@ int findSplitPositionForWord(Label* label, } int findSplitPositionForChar(Label* label, - const StringUtils::StringUTF8& text, + const text_utils::u8char_span& text, int estimatedIdx, float originalLeftSpaceWidth, float newLineWidth) { bool startingNewLine = (newLineWidth == originalLeftSpaceWidth); - int stringLength = static_cast(text.length()); + int stringLength = static_cast(text.size()); int leftLength = estimatedIdx; // The adjustment of the new line position - std::string leftStr = text.getAsCharSequence(0, leftLength); + std::string_view leftStr = text.subview(0, leftLength); label->setString(leftStr); float textRendererWidth = label->getContentSize().width; if (originalLeftSpaceWidth < textRendererWidth) // Have protruding { while (leftLength-- > 0) { - // try to erase a char - auto& ch = text.getString().at(leftLength); - leftStr.erase(leftStr.end() - ch._char.length(), leftStr.end()); + auto& ch = text.at(leftLength); + size_t trimLength = ch._char.length(); + + if (trimLength > leftStr.size()) [[unlikely]] + break; + + leftStr.remove_suffix(trimLength); + label->setString(leftStr); textRendererWidth = label->getContentSize().width; - if (textRendererWidth <= originalLeftSpaceWidth) // is fitted + if (textRendererWidth <= originalLeftSpaceWidth) break; } } else if (textRendererWidth < originalLeftSpaceWidth) // A wide margin { + auto first = leftStr.data(); + auto last = leftStr.data() + leftStr.length(); + while (leftLength < stringLength) { // try to append a char - auto& ch = text.getString().at(leftLength); + auto& ch = text.at(leftLength); ++leftLength; - leftStr.append(ch._char); - label->setString(leftStr); + last += ch._char.size(); + if (last - first > text.size_bytes()) [[unlikely]] + break; + label->setString(std::string_view{first, last}); textRendererWidth = label->getContentSize().width; if (originalLeftSpaceWidth < textRendererWidth) // protruded, undo add { @@ -2057,28 +2078,27 @@ int findSplitPositionForChar(Label* label, void RichText::handleTextRenderer(std::string_view text, std::string_view fontName, float fontSize, - const Color3B& color, - uint8_t opacity, + const Color32& color, uint32_t flags, std::string_view url, - const Color3B& outlineColor, + const Color32& outlineColor, int outlineSize, - const Color3B& shadowColor, + const Color32& shadowColor, const Vec2& shadowOffset, int shadowBlurRadius, - const Color3B& glowColor, + const Color32& glowColor, std::string_view id) { bool fileExist = FileUtils::getInstance()->isFileExist(fontName); RichText::WrapMode wrapMode = static_cast(_defaults.at(KEY_WRAP_MODE).asInt()); // split text by \n - std::stringstream ss; - ss << text; - std::string currentText; size_t realLines = 0; auto isFirstLabel = true; - while (std::getline(ss, currentText, '\n')) + + text_utils::u8char_span textSpan; + + for (auto&& subrgn : std::views::split(text, '\n')) { if (realLines > 0) { @@ -2088,8 +2108,9 @@ void RichText::handleTextRenderer(std::string_view text, ++realLines; size_t splitParts = 0; - StringUtils::StringUTF8 utf8Text(currentText); - while (!currentText.empty()) + std::string_view lineText{subrgn}; + textSpan.reset(lineText); + while (!textSpan.empty()) { if (splitParts > 0) { @@ -2098,8 +2119,9 @@ void RichText::handleTextRenderer(std::string_view text, } ++splitParts; - Label* textRenderer = fileExist ? Label::createWithTTF(currentText, fontName, fontSize) - : Label::createWithSystemFont(currentText, fontName, fontSize); + auto utf8Text = textSpan.view(); + Label* textRenderer = fileExist ? Label::createWithTTF(utf8Text, fontName, fontSize) + : Label::createWithSystemFont(utf8Text, fontName, fontSize); if (flags & RichElementText::ITALICS_FLAG) textRenderer->enableItalics(); @@ -2113,14 +2135,13 @@ void RichText::handleTextRenderer(std::string_view text, textRenderer->addComponent(UrlTouchListenerComponent::create( textRenderer, url, [this](std::string_view url) { openUrl(url); })); if (flags & RichElementText::OUTLINE_FLAG) - textRenderer->enableOutline(Color4B(outlineColor), outlineSize); + textRenderer->enableOutline(Color32(outlineColor), outlineSize); if (flags & RichElementText::SHADOW_FLAG) - textRenderer->enableShadow(Color4B(shadowColor), shadowOffset, shadowBlurRadius); + textRenderer->enableShadow(Color32(shadowColor), shadowOffset, shadowBlurRadius); if (flags & RichElementText::GLOW_FLAG) - textRenderer->enableGlow(Color4B(glowColor)); + textRenderer->enableGlow(Color32(glowColor)); - textRenderer->setTextColor(Color4B(color)); - textRenderer->setOpacity(opacity); + textRenderer->setTextColor(color); if (isFirstLabel && !id.empty()) { @@ -2145,37 +2166,33 @@ void RichText::handleTextRenderer(std::string_view text, // (_leftSpaceWidth / fontSize) means how many chars can be aligned in leftSpaceWidth. int estimatedIdx = 0; if (textRendererWidth > 0.0f) - estimatedIdx = static_cast(_leftSpaceWidth / textRendererWidth * utf8Text.length()); + estimatedIdx = static_cast(_leftSpaceWidth / textRendererWidth * textSpan.size()); else estimatedIdx = static_cast(_leftSpaceWidth / fontSize); int leftLength = 0; if (wrapMode == WRAP_PER_WORD) leftLength = - findSplitPositionForWord(textRenderer, utf8Text, estimatedIdx, _leftSpaceWidth, _customSize.width); + findSplitPositionForWord(textRenderer, textSpan, estimatedIdx, _leftSpaceWidth, _customSize.width); else leftLength = - findSplitPositionForChar(textRenderer, utf8Text, estimatedIdx, _leftSpaceWidth, _customSize.width); + findSplitPositionForChar(textRenderer, textSpan, estimatedIdx, _leftSpaceWidth, _customSize.width); // split string if (leftLength > 0) { - textRenderer->setString(utf8Text.getAsCharSequence(0, leftLength)); + textRenderer->setString(textSpan.subview(0, leftLength)); pushToContainer(textRenderer); } - StringUtils::StringUTF8::CharUTF8Store& str = utf8Text.getString(); - // after the first line, skip any spaces to the left - const auto startOfWordItr = std::find_if( - str.begin() + leftLength, str.end(), - [](const StringUtils::StringUTF8::CharUTF8& ch) { return !std::isspace(ch._char[0], std::locale()); }); - if (startOfWordItr != str.end()) - leftLength = static_cast(startOfWordItr - str.begin()); + const auto startOfWordItr = std::find_if(textSpan.begin() + leftLength, textSpan.end(), + [](const text_utils::u8char_span::value_type& ch) { return !std::isspace(ch._char[0], std::locale()); }); + if (startOfWordItr != textSpan.end()) + leftLength = static_cast(startOfWordItr - textSpan.begin()); // erase the chars which are processed - str.erase(str.begin(), str.begin() + leftLength); - currentText = utf8Text.getAsCharSequence(); + textSpan.remove_prefix(leftLength); } } @@ -2190,8 +2207,7 @@ void RichText::handleTextRenderer(std::string_view text, void RichText::handleImageRenderer(std::string_view filePath, Widget::TextureResType textureType, - const Color3B& /*color*/, - uint8_t /*opacity*/, + const Color32& /*color*/, int width, int height, std::string_view url, diff --git a/core/ui/UIRichText.h b/axmol/ui/UIRichText.h similarity index 86% rename from core/ui/UIRichText.h rename to axmol/ui/UIRichText.h index c994862f494f..0dbc1415c456 100644 --- a/core/ui/UIRichText.h +++ b/axmol/ui/UIRichText.h @@ -25,9 +25,9 @@ ****************************************************************************/ #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" -#include "base/Value.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/base/Value.h" namespace ax { @@ -63,20 +63,18 @@ class AX_GUI_DLL RichElement : public Object * @brief Initialize a rich element with different arguments. * * @param tag A integer tag value. - * @param color A color in @see `Color3B`. - * @param opacity A opacity value in `GLubyte`. + * @param color A color in @see `Color32`. * @return True if initialize success, false otherwise. */ - bool init(int tag, const Color3B& color, uint8_t opacity); + bool init(int tag, const Color32& color); bool equalType(Type type); - void setColor(const Color3B& color); + void setColor(const Color32& color); protected: Type _type{}; /*!< Rich element type. */ int _tag{}; /*!< A integer tag value. */ - Color3B _color{}; /*!< A color in `Color3B`. */ - uint8_t _opacity{}; /*!< A opacity value in `GLubyte`. */ + Color32 _color{}; /*!< A color in `Color32`. */ friend class RichText; }; @@ -108,8 +106,7 @@ class AX_GUI_DLL RichElementText : public RichElement * @brief Initialize a RichElementText with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param text Content string. * @param fontName Content font name. * @param fontSize Content font size. @@ -125,27 +122,25 @@ class AX_GUI_DLL RichElementText : public RichElement * @return True if initialize success, false otherwise. */ bool init(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view text, std::string_view fontName, float fontSize, uint32_t flags, std::string_view url, - const Color3B& outlineColor = Color3B::WHITE, + const Color32& outlineColor = Color32::WHITE, int outlineSize = -1, - const Color3B& shadowColor = Color3B::BLACK, + const Color32& shadowColor = Color32::BLACK, const Vec2& shadowOffset = Vec2(2.0, -2.0), int shadowBlurRadius = 0, - const Color3B& glowColor = Color3B::WHITE, + const Color32& glowColor = Color32::WHITE, std::string_view id = ""sv); /** * @brief Create a RichElementText with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param text Content string. * @param fontName Content font name. * @param fontSize Content font size. @@ -161,19 +156,18 @@ class AX_GUI_DLL RichElementText : public RichElement * @return RichElementText instance. */ static RichElementText* create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view text, std::string_view fontName, float fontSize, uint32_t flags = 0, std::string_view url = "", - const Color3B& outlineColor = Color3B::WHITE, + const Color32& outlineColor = Color32::WHITE, int outlineSize = -1, - const Color3B& shadowColor = Color3B::BLACK, + const Color32& shadowColor = Color32::BLACK, const Vec2& shadowOffset = Vec2(2.0, -2.0), int shadowBlurRadius = 0, - const Color3B& glowColor = Color3B::WHITE, + const Color32& glowColor = Color32::WHITE, std::string_view id = ""sv); protected: @@ -182,12 +176,12 @@ class AX_GUI_DLL RichElementText : public RichElement float _fontSize; uint32_t _flags; std::string _url; - Color3B _outlineColor; /*!< the color of the outline */ + Color32 _outlineColor; /*!< the color of the outline */ int _outlineSize; /*!< the outline effect size value */ - Color3B _shadowColor; /*!< the shadow effect color value */ + Color32 _shadowColor; /*!< the shadow effect color value */ Vec2 _shadowOffset; /*!< shadow effect offset value */ int _shadowBlurRadius; /*!< the shadow effect blur radius */ - Color3B _glowColor; /*!< attributes of glow tag */ + Color32 _glowColor; /*!< attributes of glow tag */ std::string _id; /*!< ID of this text field */ friend class RichText; }; @@ -209,8 +203,7 @@ class AX_GUI_DLL RichElementImage : public RichElement * @brief Initialize a RichElementImage with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param filePath A image file name. * @param url uniform resource locator * @param texType texture type, may be a valid file path, or a sprite frame name @@ -218,8 +211,7 @@ class AX_GUI_DLL RichElementImage : public RichElement * @return True if initialize success, false otherwise. */ bool init(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view filePath, std::string_view url = "", Widget::TextureResType texType = Widget::TextureResType::LOCAL, @@ -229,8 +221,7 @@ class AX_GUI_DLL RichElementImage : public RichElement * @brief Create a RichElementImage with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param filePath A image file name. * @param url uniform resource locator * @param texType texture type, may be a valid file path, or a sprite frame name @@ -238,8 +229,7 @@ class AX_GUI_DLL RichElementImage : public RichElement * @return A RichElementImage instance. */ static RichElementImage* create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, std::string_view filePath, std::string_view url = "", Widget::TextureResType texType = Widget::TextureResType::LOCAL, @@ -288,27 +278,24 @@ class AX_GUI_DLL RichElementCustomNode : public RichElement * @brief Initialize a RichElementCustomNode with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param customNode A custom node pointer. * @param id ID of element * @return True if initialize success, false otherwise. */ - bool init(int tag, const Color3B& color, uint8_t opacity, Node* customNode, std::string_view id = ""sv); + bool init(int tag, const Color32& color, Node* customNode, std::string_view id = ""sv); /** * @brief Create a RichElementCustomNode with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @param customNode A custom node pointer. * @param id ID of element * @return A RichElementCustomNode instance. */ static RichElementCustomNode* create(int tag, - const Color3B& color, - uint8_t opacity, + const Color32& color, Node* customNode, std::string_view id = ""sv); @@ -342,22 +329,20 @@ class AX_GUI_DLL RichElementNewLine : public RichElement * @brief Create a RichElementNewLine with various arguments. * * @param tag A integer tag value. - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @return A RichElementNewLine instance. */ - static RichElementNewLine* create(int tag, const Color3B& color, uint8_t opacity); + static RichElementNewLine* create(int tag, const Color32& color); /** * @brief Create a RichElementNewLine with various arguments. * * @param tag A integer tag value. * @param quantity Number of new lines to add - * @param color A color in Color3B. - * @param opacity A opacity in GLubyte. + * @param color A color in Color32. * @return A RichElementNewLine instance. */ - static RichElementNewLine* create(int tag, int quantity, const Color3B& color, uint8_t opacity); + static RichElementNewLine* create(int tag, int quantity, const Color32& color); protected: friend class RichText; @@ -532,14 +517,14 @@ class AX_GUI_DLL RichText : public Widget void setFontColor( std::string_view color); /*!< Set the font color. @param color the #RRGGBB hexadecimal notation. */ std::string getFontColor(); /*!< return the current font color */ - Color3B getFontColor3B(); /*!< return the current font color */ + Color32 getFontColor32(); /*!< return the current font Color32 */ void setFontSize(float size); /*!< Set the font size. @param size the font size. */ float getFontSize(); /*!< return the current font size */ void setFontFace(std::string_view face); /*!< Set the font face. @param face the font face. */ std::string getFontFace(); /*!< return the current font face */ void setAnchorFontColor(std::string_view color); /*!< Set the font color of a-tag. @param color the font color. */ std::string getAnchorFontColor(); /*!< return the current font color of a-tag */ - ax::Color3B getAnchorFontColor3B(); /*!< return the current font color of a-tag */ + ax::Color32 getAnchorFontColor32(); /*!< return the current font color of a-tag */ void setAnchorTextBold(bool enable); /*!< enable bold text of a-tag */ bool isAnchorTextBoldEnabled(); /*!< valid style is bold text of a-tag? */ void setAnchorTextItalic(bool enable); /*!< enable italic text of a-tag */ @@ -549,28 +534,27 @@ class AX_GUI_DLL RichText : public Widget void setAnchorTextUnderline(bool enable); /*!< enable the underline of a-tag */ bool isAnchorTextUnderlineEnabled(); /*!< valid underline of a-tag? */ /** @brief enable the outline of a-tag */ - void setAnchorTextOutline(bool enable, const Color3B& outlineColor = Color3B::WHITE, int outlineSize = -1); + void setAnchorTextOutline(bool enable, const Color32& outlineColor = Color32::WHITE, int outlineSize = -1); bool isAnchorTextOutlineEnabled(); /*!< valid outline of a-tag? */ - Color3B getAnchorTextOutlineColor3B(); /*!< return the current text outline color of a-tag */ + Color32 getAnchorTextOutlineColor32(); /*!< return the current text outline color of a-tag */ int getAnchorTextOutlineSize(); /*!< return the current text outline size of a-tag */ /** @brief enable the shadow of a-tag */ void setAnchorTextShadow(bool enable, - const Color3B& shadowColor = Color3B::BLACK, + const Color32& shadowColor = Color32::BLACK, const Vec2& offset = Vec2(2.0, -2.0), int blurRadius = 0); bool isAnchorTextShadowEnabled(); /*!< valid shadow of a-tag? */ - Color3B getAnchorTextShadowColor3B(); /*!< return the current text shadow color of a-tag */ + Color32 getAnchorTextShadowColor32(); /*!< return the current text shadow color of a-tag */ Vec2 getAnchorTextShadowOffset(); /*!< return the current text shadow offset of a-tag */ int getAnchorTextShadowBlurRadius(); /*!< return the current text shadow blur radius of a-tag */ - void setAnchorTextGlow(bool enable, const Color3B& glowColor = Color3B::WHITE); /*!< enable the glow of a-tag */ + void setAnchorTextGlow(bool enable, const Color32& glowColor = Color32::WHITE); /*!< enable the glow of a-tag */ bool isAnchorTextGlowEnabled(); /*!< valid glow of a-tag? */ - Color3B getAnchorTextGlowColor3B(); /*!< return the current text glow color of a-tag */ + Color32 getAnchorTextGlowColor32(); /*!< return the current text glow color of a-tag */ void setDefaults(const ValueMap& defaults); /*!< set the default values */ ValueMap getDefaults() const; /*!< returns the default values */ - ax::Color3B color3BWithString(std::string_view color); /*!< convert a color string into a Color3B. */ - std::string stringWithColor3B(const ax::Color3B& color3b); /*!< convert a Color3B into a color string. */ - std::string stringWithColor4B(const ax::Color4B& color4b); /*!< convert a Color4B into a color string. */ + static ax::Color32 parseColor32(std::string_view color); /*!< convert a color string into a Color32. */ + static std::string formatColor32(const ax::Color32& Color32); /*!< convert a Color32 into a color string. */ /** * @brief add a callback to own tag. @@ -615,21 +599,19 @@ class AX_GUI_DLL RichText : public Widget void handleTextRenderer(std::string_view text, std::string_view fontName, float fontSize, - const Color3B& color, - uint8_t opacity, + const Color32& color, uint32_t flags, std::string_view url = "", - const Color3B& outlineColor = Color3B::WHITE, + const Color32& outlineColor = Color32::WHITE, int outlineSize = -1, - const Color3B& shadowColor = Color3B::BLACK, + const Color32& shadowColor = Color32::BLACK, const Vec2& shadowOffset = Vec2(2.0, -2.0), int shadowBlurRadius = 0, - const Color3B& glowColor = Color3B::WHITE, + const Color32& glowColor = Color32::WHITE, std::string_view id = ""sv); void handleImageRenderer(std::string_view filePath, Widget::TextureResType textureType, - const Color3B& color, - uint8_t opacity, + const Color32& color, int width, int height, std::string_view url, diff --git a/core/ui/UIScale9Sprite.cpp b/axmol/ui/UIScale9Sprite.cpp similarity index 98% rename from core/ui/UIScale9Sprite.cpp rename to axmol/ui/UIScale9Sprite.cpp index 2c3c36605c85..ef30ead52bf2 100644 --- a/core/ui/UIScale9Sprite.cpp +++ b/axmol/ui/UIScale9Sprite.cpp @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIScale9Sprite.h" -#include "2d/Sprite.h" -#include "base/Vector.h" -#include "base/Director.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Director.h" using namespace ax::ui; @@ -295,10 +295,10 @@ void Scale9Sprite::setState(Scale9Sprite::State state) switch (state) { case State::NORMAL: - Sprite::setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + Sprite::setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); break; case State::GRAY: - Sprite::setProgramState(backend::ProgramType::GRAY_SCALE); + Sprite::setProgramState(rhi::ProgramType::GRAY_SCALE); default: break; } diff --git a/core/ui/UIScale9Sprite.h b/axmol/ui/UIScale9Sprite.h similarity index 98% rename from core/ui/UIScale9Sprite.h rename to axmol/ui/UIScale9Sprite.h index 2fc8994f4fc0..c3c08f62575a 100644 --- a/core/ui/UIScale9Sprite.h +++ b/axmol/ui/UIScale9Sprite.h @@ -26,9 +26,9 @@ #pragma once -#include "2d/Sprite.h" -#include "2d/SpriteFrame.h" -#include "ui/GUIExport.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -263,7 +263,7 @@ class AX_GUI_DLL Scale9Sprite : public Sprite * texture's full rect. * @return True if initializes success, false otherwise. */ - virtual bool initWithFile(std::string_view file, const Rect& rect) override; + bool initWithFile(std::string_view file, const Rect& rect) override; /** * Initializes a 9-slice sprite with a texture file. The whole texture will be @@ -275,7 +275,7 @@ class AX_GUI_DLL Scale9Sprite : public Sprite * @param file The name of the texture file. * @return True if initializes success, false otherwise. */ - virtual bool initWithFile(std::string_view file) override; + bool initWithFile(std::string_view file) override; /** * Initializes a 9-slice sprite with an sprite frame name. @@ -286,9 +286,9 @@ class AX_GUI_DLL Scale9Sprite : public Sprite * @param spriteFrameName The sprite frame name. * @return True if initializes success, false otherwise. */ - virtual bool initWithSpriteFrameName(std::string_view spriteFrameName) override; + bool initWithSpriteFrameName(std::string_view spriteFrameName) override; - virtual bool init() override; + bool init() override; /** * @brief Initializes a 9-slice sprite with an sprite instance. diff --git a/core/ui/UIScrollView.cpp b/axmol/ui/UIScrollView.cpp similarity index 99% rename from core/ui/UIScrollView.cpp rename to axmol/ui/UIScrollView.cpp index 5e64329ed6f9..255b433cc17b 100644 --- a/core/ui/UIScrollView.cpp +++ b/axmol/ui/UIScrollView.cpp @@ -24,13 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIScrollView.h" -#include "base/Director.h" -#include "base/Utils.h" -#include "platform/Device.h" -#include "ui/UIScrollViewBar.h" -#include "2d/TweenFunction.h" -#include "2d/Camera.h" +#include "axmol/ui/UIScrollView.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/Device.h" +#include "axmol/ui/UIScrollViewBar.h" +#include "axmol/2d/TweenFunction.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -142,8 +142,7 @@ void ScrollView::initRenderer() { Layout::initRenderer(); _innerContainer = Layout::create(); - _innerContainer->setColor(Color3B(255, 255, 255)); - _innerContainer->setOpacity(255); + _innerContainer->setColor(Color32::WHITE); _innerContainer->setCascadeColorEnabled(true); _innerContainer->setCascadeOpacityEnabled(true); addProtectedChild(_innerContainer, 1, 1); @@ -1376,7 +1375,7 @@ float ScrollView::getScrollBarWidth() const return 0; } -void ScrollView::setScrollBarColor(const Color3B& color) +void ScrollView::setScrollBarColor(const Color32& color) { AXASSERT(_scrollBarEnabled, "Scroll bar should be enabled!"); if (_verticalScrollBar != nullptr) @@ -1389,7 +1388,7 @@ void ScrollView::setScrollBarColor(const Color3B& color) } } -const Color3B& ScrollView::getScrollBarColor() const +const Color32& ScrollView::getScrollBarColor() const { AXASSERT(_scrollBarEnabled, "Scroll bar should be enabled!"); if (_verticalScrollBar != nullptr) @@ -1400,7 +1399,7 @@ const Color3B& ScrollView::getScrollBarColor() const { return _horizontalScrollBar->getColor(); } - return Color3B::WHITE; + return Color32::WHITE; } void ScrollView::setScrollBarOpacity(uint8_t opacity) diff --git a/core/ui/UIScrollView.h b/axmol/ui/UIScrollView.h similarity index 99% rename from core/ui/UIScrollView.h rename to axmol/ui/UIScrollView.h index 6bd50cb531c8..b97cf9b281da 100644 --- a/core/ui/UIScrollView.h +++ b/axmol/ui/UIScrollView.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UILayout.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/GUIExport.h" #include namespace ax @@ -455,14 +455,14 @@ class AX_GUI_DLL ScrollView : public Layout * * @param color the scroll bar's color */ - void setScrollBarColor(const Color3B& color); + void setScrollBarColor(const Color32& color); /** * @brief Get the scroll bar's color * * @return the scroll bar's color */ - const Color3B& getScrollBarColor() const; + const Color32& getScrollBarColor() const; /** * @brief Set the scroll bar's opacity diff --git a/core/ui/UIScrollViewBar.cpp b/axmol/ui/UIScrollViewBar.cpp similarity index 98% rename from core/ui/UIScrollViewBar.cpp rename to axmol/ui/UIScrollViewBar.cpp index 32bed9fb9ba4..f2d4d042316b 100644 --- a/core/ui/UIScrollViewBar.cpp +++ b/axmol/ui/UIScrollViewBar.cpp @@ -24,10 +24,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIScrollViewBar.h" -#include "platform/Image.h" -#include "2d/Sprite.h" -#include "base/Utils.h" +#include "axmol/ui/UIScrollViewBar.h" +#include "axmol/platform/Image.h" +#include "axmol/2d/Sprite.h" +#include "axmol/base/Utils.h" namespace ax { @@ -45,7 +45,7 @@ static const char* BODY_IMAGE_1_PIXEL_HEIGHT = static const char* HALF_CIRCLE_IMAGE_KEY = "/__halfCircleImage"; static const char* BODY_IMAGE_1_PIXEL_HEIGHT_KEY = "/__bodyImage"; -static const Color3B DEFAULT_COLOR(52, 65, 87); +static const Color32 DEFAULT_COLOR(52, 65, 87, 255); static const float DEFAULT_MARGIN = 20; static const float DEFAULT_AUTO_HIDE_TIME = 0.2f; static const float DEFAULT_SCROLLBAR_OPACITY = 0.4f; diff --git a/core/ui/UIScrollViewBar.h b/axmol/ui/UIScrollViewBar.h similarity index 94% rename from core/ui/UIScrollViewBar.h rename to axmol/ui/UIScrollViewBar.h index 78185f62df3b..305d234ded4a 100644 --- a/core/ui/UIScrollViewBar.h +++ b/axmol/ui/UIScrollViewBar.h @@ -26,7 +26,7 @@ THE SOFTWARE. #pragma once -#include "ui/UIScrollView.h" +#include "axmol/ui/UIScrollView.h" namespace ax { @@ -131,10 +131,10 @@ class AX_GUI_DLL ScrollViewBar : public ProtectedNode /** * @lua NA */ - virtual void setOpacity(uint8_t opacity) override { _opacity = opacity; } - virtual uint8_t getOpacity() const override { return _opacity; } - virtual void onEnter() override; - virtual void update(float deltaTime) override; + void setOpacity(uint8_t opacity) override { _opacity = opacity; } + uint8_t getOpacity() const override { return _opacity; } + void onEnter() override; + void update(float deltaTime) override; /** * @brief This is called by parent ScrollView when a touch is began. Don't call this directly. @@ -146,7 +146,7 @@ class AX_GUI_DLL ScrollViewBar : public ProtectedNode */ void onTouchEnded(); - virtual bool init() override; + bool init() override; private: float calculateLength(float innerContainerMeasure, float scrollViewMeasure, float outOfBoundaryValue); diff --git a/core/ui/UISlider.cpp b/axmol/ui/UISlider.cpp similarity index 98% rename from core/ui/UISlider.cpp rename to axmol/ui/UISlider.cpp index feb4b11e3288..27b9d49838ba 100644 --- a/core/ui/UISlider.cpp +++ b/axmol/ui/UISlider.cpp @@ -24,12 +24,12 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UISlider.h" -#include "ui/UIScale9Sprite.h" -#include "ui/UIHelper.h" -#include "2d/Sprite.h" -#include "2d/Camera.h" -#include "renderer/Shaders.h" +#include "axmol/ui/UISlider.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/Camera.h" +#include "axmol/renderer/Shaders.h" namespace ax { @@ -682,13 +682,13 @@ void Slider::onPressStateChangedToNormal() _slidBallPressedRenderer->setVisible(false); _slidBallDisabledRenderer->setVisible(false); - _slidBallNormalRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + _slidBallNormalRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); _slidBallNormalRenderer->setScale(_sliderBallNormalTextureScaleX, _sliderBallNormalTextureScaleY); } void Slider::onPressStateChangedToPressed() { - _slidBallNormalRenderer->setProgramState(backend::ProgramType::POSITION_TEXTURE_COLOR); + _slidBallNormalRenderer->setProgramState(rhi::ProgramType::POSITION_TEXTURE_COLOR); if (!_isSliderBallPressedTextureLoaded) { @@ -707,7 +707,7 @@ void Slider::onPressStateChangedToDisabled() { if (!_isSliderBallDisabledTexturedLoaded) { - _slidBallNormalRenderer->setProgramState(backend::ProgramType::GRAY_SCALE); + _slidBallNormalRenderer->setProgramState(rhi::ProgramType::GRAY_SCALE); _slidBallNormalRenderer->setVisible(true); } else diff --git a/core/ui/UISlider.h b/axmol/ui/UISlider.h similarity index 89% rename from core/ui/UISlider.h rename to axmol/ui/UISlider.h index 1a52912e78a3..d8ddccb536ed 100644 --- a/core/ui/UISlider.h +++ b/axmol/ui/UISlider.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -235,26 +235,26 @@ class AX_GUI_DLL Slider : public Widget */ void addEventListener(const ccSliderCallback& callback); - virtual bool onTouchBegan(Touch* touch, Event* unusedEvent) override; - virtual void onTouchMoved(Touch* touch, Event* unusedEvent) override; - virtual void onTouchEnded(Touch* touch, Event* unusedEvent) override; - virtual void onTouchCancelled(Touch* touch, Event* unusedEvent) override; + bool onTouchBegan(Touch* touch, Event* unusedEvent) override; + void onTouchMoved(Touch* touch, Event* unusedEvent) override; + void onTouchEnded(Touch* touch, Event* unusedEvent) override; + void onTouchCancelled(Touch* touch, Event* unusedEvent) override; // override "getVirtualRendererSize" method of widget. - virtual Vec2 getVirtualRendererSize() const override; + Vec2 getVirtualRendererSize() const override; // override "getVirtualRenderer" method of widget. - virtual Node* getVirtualRenderer() override; + Node* getVirtualRenderer() override; // override "ignoreContentAdaptWithSize" method of widget. - virtual void ignoreContentAdaptWithSize(bool ignore) override; + void ignoreContentAdaptWithSize(bool ignore) override; // override the widget's hitTest function to perform its own - virtual bool hitTest(const Vec2& pt, const Camera* camera, Vec3* p) const override; + bool hitTest(const Vec2& pt, const Camera* camera, Vec3* p) const override; /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** When user pressed the button, the button will zoom to a scale. * The final scale of the button equals (button original scale + _zoomScale) @@ -278,16 +278,16 @@ class AX_GUI_DLL Slider : public Widget ResourceData getBallPressedFile(); ResourceData getBallDisabledFile(); - virtual bool init() override; + bool init() override; protected: - virtual void initRenderer() override; + void initRenderer() override; float getPercentWithBallPos(const Vec2& pt) const; void percentChangedEvent(EventType event); - virtual void onPressStateChangedToNormal() override; - virtual void onPressStateChangedToPressed() override; - virtual void onPressStateChangedToDisabled() override; - virtual void onSizeChanged() override; + void onPressStateChangedToNormal() override; + void onPressStateChangedToPressed() override; + void onPressStateChangedToDisabled() override; + void onSizeChanged() override; void setupBarTexture(); void loadBarTexture(SpriteFrame* spriteframe); @@ -299,9 +299,9 @@ class AX_GUI_DLL Slider : public Widget void barRendererScaleChangedWithSize(); void progressBarRendererScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; - virtual void adaptRenderers() override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; + void adaptRenderers() override; protected: Scale9Sprite* _barRenderer; diff --git a/core/ui/UITabControl.cpp b/axmol/ui/UITabControl.cpp similarity index 98% rename from core/ui/UITabControl.cpp rename to axmol/ui/UITabControl.cpp index ed59739a0e90..8af053d509d9 100644 --- a/core/ui/UITabControl.cpp +++ b/axmol/ui/UITabControl.cpp @@ -24,11 +24,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/FileUtils.h" -#include "2d/Sprite.h" -#include "2d/Label.h" -#include "ui/UILayout.h" -#include "ui/UITabControl.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/Label.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/UITabControl.h" namespace ax { @@ -566,16 +566,16 @@ std::string_view TabHeader::getTitleText() const return _tabLabelRender->getString(); } -void TabHeader::setTitleColor(const Color4B& color) +void TabHeader::setTitleColor(const Color32& color) { _tabLabelRender->setTextColor(color); } -const Color4B& TabHeader::getTitleColor() const +const Color32& TabHeader::getTitleColor() const { if (nullptr == _tabLabelRender) { - return Color4B::WHITE; + return Color32::WHITE; } return _tabLabelRender->getTextColor(); } @@ -723,4 +723,4 @@ void TabHeader::copySpecialProperties(Widget* model) } } // namespace ui -} \ No newline at end of file +} diff --git a/core/ui/UITabControl.h b/axmol/ui/UITabControl.h similarity index 95% rename from core/ui/UITabControl.h rename to axmol/ui/UITabControl.h index b68533893eb6..2d98bcb81f0c 100644 --- a/core/ui/UITabControl.h +++ b/axmol/ui/UITabControl.h @@ -26,8 +26,8 @@ #pragma once -#include "ui/UIAbstractCheckButton.h" -#include "ui/UIWidget.h" +#include "axmol/ui/UIAbstractCheckButton.h" +#include "axmol/ui/UIWidget.h" /** * @addtogroup ui @@ -115,15 +115,15 @@ class AX_GUI_DLL TabHeader : public AbstractCheckButton /** * Change the color of he TabHeader text - *@param color The he TabHeader text's color in Color4B. + *@param color The he TabHeader text's color in Color32. */ - void setTitleColor(const Color4B& color); + void setTitleColor(const Color32& color); /** * get the TabHeader text color. - *@return Color4B of TabHeader text. + *@return Color32 of TabHeader text. */ - const Color4B& getTitleColor() const; + const Color32& getTitleColor() const; /** * Change the font size of TabHeader text @@ -159,15 +159,15 @@ class AX_GUI_DLL TabHeader : public AbstractCheckButton TabHeader(); ~TabHeader(); - virtual void initRenderer() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onSizeChanged() override; void updateContentSize(); - virtual void releaseUpEvent() override; + void releaseUpEvent() override; void dispatchSelectChangedEvent(bool select) override; - virtual void copySpecialProperties(Widget* model) override; + void copySpecialProperties(Widget* model) override; private: Label* _tabLabelRender; @@ -342,7 +342,7 @@ class AX_GUI_DLL TabControl : public Widget void onSizeChanged() override; void initTabHeadersPos(int startIndex); void initContainers(); - virtual void copySpecialProperties(Widget* model) override; + void copySpecialProperties(Widget* model) override; ccTabControlCallback _tabChangedCallback; // dispatch selected changed diff --git a/core/ui/UIText.cpp b/axmol/ui/UIText.cpp similarity index 94% rename from core/ui/UIText.cpp rename to axmol/ui/UIText.cpp index 03c7ad8d2f1b..84768e7c99ae 100644 --- a/core/ui/UIText.cpp +++ b/axmol/ui/UIText.cpp @@ -24,9 +24,9 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIText.h" -#include "2d/Label.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UIText.h" +#include "axmol/2d/Label.h" +#include "axmol/platform/FileUtils.h" namespace ax { @@ -221,12 +221,12 @@ TextVAlignment Text::getTextVerticalAlignment() const return _labelRenderer->getVerticalAlignment(); } -void Text::setTextColor(const Color4B color) +void Text::setTextColor(const Color32 color) { _labelRenderer->setTextColor(color); } -const Color4B& Text::getTextColor() const +const Color32& Text::getTextColor() const { return _labelRenderer->getTextColor(); } @@ -332,19 +332,19 @@ std::string Text::getDescription() const return "Label"; } -void Text::enableShadow(const Color4B& shadowColor, const Vec2& offset, int blurRadius) +void Text::enableShadow(const Color32& shadowColor, const Vec2& offset, int blurRadius) { _labelRenderer->enableShadow(shadowColor, offset, blurRadius); } -void Text::enableOutline(const Color4B& outlineColor, int outlineSize) +void Text::enableOutline(const Color32& outlineColor, int outlineSize) { _labelRenderer->enableOutline(outlineColor, outlineSize); updateContentSizeWithTextureSize(_labelRenderer->getContentSize()); _labelRendererAdaptDirty = true; } -void Text::enableGlow(const Color4B& glowColor) +void Text::enableGlow(const Color32& glowColor) { if (_type == Type::TTF) _labelRenderer->enableGlow(glowColor); @@ -380,10 +380,10 @@ float Text::getShadowBlurRadius() const { return _labelRenderer->getShadowBlurRadius(); } -Color4B Text::getShadowColor() const +Color32 Text::getShadowColor() const { - Color4F effect = _labelRenderer->getShadowColor(); - return Color4B(effect.r * 255, effect.g * 255, effect.b * 255, effect.a * 255); + Color effect = _labelRenderer->getShadowColor(); + return Color32(effect.r * 255, effect.g * 255, effect.b * 255, effect.a * 255); } int Text::getOutlineSize() const @@ -394,10 +394,10 @@ LabelEffect Text::getLabelEffectType() const { return _labelRenderer->getLabelEffectType(); } -Color4B Text::getEffectColor() const +Color32 Text::getEffectColor() const { - Color4F effect = _labelRenderer->getEffectColor(); - return Color4B(effect.r * 255, effect.g * 255, effect.b * 255, effect.a * 255); + Color effect = _labelRenderer->getEffectColor(); + return Color32(effect.r * 255, effect.g * 255, effect.b * 255, effect.a * 255); } Sprite* Text::getLetter(int lettetIndex) diff --git a/core/ui/UIText.h b/axmol/ui/UIText.h similarity index 88% rename from core/ui/UIText.h rename to axmol/ui/UIText.h index 2d1077d47b60..00ff68ed3aee 100644 --- a/core/ui/UIText.h +++ b/axmol/ui/UIText.h @@ -26,9 +26,9 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" -#include "base/Types.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/base/Types.h" /** * @addtogroup ui @@ -178,10 +178,10 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol bool isTouchScaleChangeEnabled() const; // override "getVirtualRendererSize" method of widget. - virtual Vec2 getVirtualRendererSize() const override; + Vec2 getVirtualRendererSize() const override; // override "getVirtualRenderer" method of widget. - virtual Node* getVirtualRenderer() override; + Node* getVirtualRenderer() override; /** Gets the render size in auto mode. * @@ -192,7 +192,7 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * Sets the rendering size of the text, you should call this method @@ -238,13 +238,13 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol * * @param color Text color. */ - void setTextColor(const Color4B color); + void setTextColor(const Color32 color); /** Gets text color. * * @return Text color. */ - const Color4B& getTextColor() const; + const Color32& getTextColor() const; /** * Enable shadow for the label. @@ -255,7 +255,7 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol * @param offset The offset of shadow effect. * @param blurRadius The blur radius of shadow effect. */ - void enableShadow(const Color4B& shadowColor = Color4B::BLACK, + void enableShadow(const Color32& shadowColor = Color32::BLACK, const Vec2& offset = Vec2(2, -2), int blurRadius = 0); @@ -266,13 +266,13 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol * @param outlineColor The color of outline. * @param outlineSize The size of outline. */ - void enableOutline(const Color4B& outlineColor, int outlineSize = 1); + void enableOutline(const Color32& outlineColor, int outlineSize = 1); /** Only support for TTF. * * @param glowColor The color of glow. */ - void enableGlow(const Color4B& glowColor); + void enableGlow(const Color32& glowColor); /** Disable all text effects, including shadow, outline and glow. */ @@ -301,7 +301,7 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol /** * Return the shadow effect color value. */ - Color4B getShadowColor() const; + Color32 getShadowColor() const; /** * Return the outline effect size value. */ @@ -313,7 +313,7 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol /** * Return current effect color value. */ - Color4B getEffectColor() const; + Color32 getEffectColor() const; /** * Provides a way to treat each character like a Sprite. @@ -328,7 +328,7 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol * {BlendFactor::ONE, BlendFactor::ONE}, {BlendFactor::SRC_ALPHA, BlendFactor::ONE_MINUS_SRC_ALPHA}. * @lua NA */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * Returns the blending function that is currently being used. @@ -336,22 +336,22 @@ class AX_GUI_DLL Text : public Widget, public ax::BlendProtocol * @return A BlendFunc structure with source and destination factor which specified pixel arithmetic. * @lua NA */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; - virtual bool init() override; + bool init() override; virtual bool init(std::string_view textContent, std::string_view fontName, float fontSize); protected: - virtual void initRenderer() override; - virtual void onPressStateChangedToNormal() override; - virtual void onPressStateChangedToPressed() override; - virtual void onPressStateChangedToDisabled() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onPressStateChangedToNormal() override; + void onPressStateChangedToPressed() override; + void onPressStateChangedToDisabled() override; + void onSizeChanged() override; void labelScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; - virtual void adaptRenderers() override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; + void adaptRenderers() override; protected: bool _touchScaleChangeEnabled; diff --git a/core/ui/UITextAtlas.cpp b/axmol/ui/UITextAtlas.cpp similarity index 98% rename from core/ui/UITextAtlas.cpp rename to axmol/ui/UITextAtlas.cpp index cfaf469d787a..f177c8c9265e 100644 --- a/core/ui/UITextAtlas.cpp +++ b/axmol/ui/UITextAtlas.cpp @@ -24,8 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UITextAtlas.h" -#include "2d/Label.h" +#include "axmol/ui/UITextAtlas.h" +#include "axmol/2d/Label.h" namespace ax { diff --git a/core/ui/UITextAtlas.h b/axmol/ui/UITextAtlas.h similarity index 90% rename from core/ui/UITextAtlas.h rename to axmol/ui/UITextAtlas.h index f98b07c5b885..88191a90d77a 100644 --- a/core/ui/UITextAtlas.h +++ b/axmol/ui/UITextAtlas.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -127,29 +127,29 @@ class AX_GUI_DLL TextAtlas : public Widget ssize_t getStringLength() const; // override "getVirtualRendererSize" method of widget. - virtual Vec2 getVirtualRendererSize() const override; + Vec2 getVirtualRendererSize() const override; // override "getVirtualRenderer" method of widget. - virtual Node* getVirtualRenderer() override; + Node* getVirtualRenderer() override; /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** */ - virtual void adaptRenderers() override; + void adaptRenderers() override; ResourceData getRenderFile(); protected: - virtual void initRenderer() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onSizeChanged() override; void labelAtlasScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; protected: Label* _labelAtlasRenderer; diff --git a/core/ui/UITextBMFont.cpp b/axmol/ui/UITextBMFont.cpp similarity index 98% rename from core/ui/UITextBMFont.cpp rename to axmol/ui/UITextBMFont.cpp index d8de97bf4618..93ac6c012d64 100644 --- a/core/ui/UITextBMFont.cpp +++ b/axmol/ui/UITextBMFont.cpp @@ -24,8 +24,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UITextBMFont.h" -#include "2d/Label.h" +#include "axmol/ui/UITextBMFont.h" +#include "axmol/2d/Label.h" namespace ax { diff --git a/core/ui/UITextBMFont.h b/axmol/ui/UITextBMFont.h similarity index 86% rename from core/ui/UITextBMFont.h rename to axmol/ui/UITextBMFont.h index 13fe92718a80..b2322c38c170 100644 --- a/core/ui/UITextBMFont.h +++ b/axmol/ui/UITextBMFont.h @@ -26,8 +26,8 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" /** * @addtogroup ui @@ -88,12 +88,12 @@ class AX_GUI_DLL TextBMFont : public Widget */ ssize_t getStringLength() const; - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; ResourceData getRenderFile(); @@ -103,13 +103,13 @@ class AX_GUI_DLL TextBMFont : public Widget void resetRender(); protected: - virtual void initRenderer() override; - virtual void onSizeChanged() override; + void initRenderer() override; + void onSizeChanged() override; void labelBMFontScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; - virtual void adaptRenderers() override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; + void adaptRenderers() override; protected: Label* _labelBMFontRenderer; diff --git a/core/ui/UITextField.cpp b/axmol/ui/UITextField.cpp similarity index 96% rename from core/ui/UITextField.cpp rename to axmol/ui/UITextField.cpp index 6e1478833488..ac542c52044c 100644 --- a/core/ui/UITextField.cpp +++ b/axmol/ui/UITextField.cpp @@ -24,11 +24,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UITextField.h" -#include "platform/FileUtils.h" -#include "ui/UIHelper.h" -#include "base/UTF8.h" -#include "2d/Camera.h" +#include "axmol/ui/UITextField.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/base/text_utils.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -122,7 +122,7 @@ void UICCTextField::insertText(const char* text, size_t len) { if (_maxLengthEnabled) { - int32_t text_count = StringUtils::countUTF8Chars(getString()); + int32_t text_count = text_utils::countUTF8Chars(getString()); if (text_count >= _maxLength) { // password @@ -133,7 +133,7 @@ void UICCTextField::insertText(const char* text, size_t len) return; } - int32_t input_count = StringUtils::countUTF8Chars(text); + int32_t input_count = text_utils::countUTF8Chars(text); int32_t total = text_count + input_count; if (total > _maxLength) @@ -201,7 +201,7 @@ void UICCTextField::setPasswordStyleText(std::string_view styleText) void UICCTextField::setPasswordText(std::string_view text) { std::string tempStr = ""; - int32_t text_count = StringUtils::countUTF8Chars(text); + int32_t text_count = text_utils::countUTF8Chars(text); int32_t max = text_count; if (_maxLengthEnabled) @@ -367,7 +367,7 @@ void TextField::setString(std::string_view text) if (isMaxLengthEnabled()) { int max = _textFieldRenderer->getMaxLength(); - int32_t text_count = StringUtils::countUTF8Chars(text); + int32_t text_count = text_utils::countUTF8Chars(text); if (text_count > max) { strText = Helper::getSubStringOfUTF8String(strText, 0, max); @@ -400,27 +400,22 @@ std::string_view TextField::getPlaceHolder() const return _textFieldRenderer->getPlaceHolder(); } -const Color4B& TextField::getPlaceHolderColor() const +const Color32& TextField::getPlaceHolderColor() const { return _textFieldRenderer->getColorSpaceHolder(); } -void TextField::setPlaceHolderColor(const ax::Color3B& color) +void TextField::setPlaceHolderColor(const ax::Color32& color) { _textFieldRenderer->setColorSpaceHolder(color); } -void TextField::setPlaceHolderColor(const ax::Color4B& color) -{ - _textFieldRenderer->setColorSpaceHolder(color); -} - -const Color4B& TextField::getTextColor() const +const Color32& TextField::getTextColor() const { return _textFieldRenderer->getTextColor(); } -void TextField::setTextColor(const ax::Color4B& textColor) +void TextField::setTextColor(const ax::Color32& textColor) { _textFieldRenderer->setTextColor(textColor); } diff --git a/core/ui/UITextField.h b/axmol/ui/UITextField.h similarity index 90% rename from core/ui/UITextField.h rename to axmol/ui/UITextField.h index 0dc1c22204fc..b770d0b1f02a 100644 --- a/core/ui/UITextField.h +++ b/axmol/ui/UITextField.h @@ -26,9 +26,9 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "2d/TextFieldTTF.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/2d/TextFieldTTF.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -66,7 +66,7 @@ class AX_GUI_DLL UICCTextField : public TextFieldTTF, public TextFieldDelegate */ ~UICCTextField(); - virtual void onEnter() override; + void onEnter() override; /** * Create a UICCTextField instance with a placeholder, a fontName and a fontSize. @@ -78,10 +78,10 @@ class AX_GUI_DLL UICCTextField : public TextFieldTTF, public TextFieldDelegate static UICCTextField* create(std::string_view placeholder, std::string_view fontName, float fontSize); // override functions - virtual bool onTextFieldAttachWithIME(TextFieldTTF* pSender) override; - virtual bool onTextFieldDetachWithIME(TextFieldTTF* pSender) override; - virtual bool onTextFieldInsertText(TextFieldTTF* pSender, const char* text, size_t nLen) override; - virtual bool onTextFieldDeleteBackward(TextFieldTTF* pSender, const char* delText, size_t nLen) override; + bool onTextFieldAttachWithIME(TextFieldTTF* pSender) override; + bool onTextFieldDetachWithIME(TextFieldTTF* pSender) override; + bool onTextFieldInsertText(TextFieldTTF* pSender, const char* text, size_t nLen) override; + bool onTextFieldDeleteBackward(TextFieldTTF* pSender, const char* delText, size_t nLen) override; void insertText(const char* text, size_t len) override; /** @@ -293,7 +293,7 @@ class AX_GUI_DLL TextField : public Widget */ void setTouchAreaEnabled(bool enable); - virtual bool hitTest(const Vec2& pt, const Camera* camera, Vec3* p) const override; + bool hitTest(const Vec2& pt, const Camera* camera, Vec3* p) const override; /** * @brief Set placeholder of TextField. @@ -314,35 +314,28 @@ class AX_GUI_DLL TextField : public Widget * * @return The color of placeholder. */ - const Color4B& getPlaceHolderColor() const; + const Color32& getPlaceHolderColor() const; /** * @brief Change the placeholder color. * - * @param color A color value in `Color3B`. + * @param color A color value in `Color32`. */ - void setPlaceHolderColor(const Color3B& color); - - /** - * @brief Change the placeholder color. - * - * @param color A color value in `Color4B`. - */ - void setPlaceHolderColor(const Color4B& color); + void setPlaceHolderColor(const Color32& color); /** * @brief Query the text string color. * * @return The color of the text. */ - const Color4B& getTextColor() const; + const Color32& getTextColor() const; /** * @brief Change the text color. * - * @param textColor The color value in `Color4B`. + * @param textColor The color value in `Color32`. */ - void setTextColor(const Color4B& textColor); + void setTextColor(const Color32& textColor); /** * @brief Change font size of TextField. @@ -389,7 +382,7 @@ class AX_GUI_DLL TextField : public Widget */ std::string_view getString() const; - virtual bool onTouchBegan(Touch* touch, Event* unusedEvent) override; + bool onTouchBegan(Touch* touch, Event* unusedEvent) override; /** * @brief Toggle maximize length enable @@ -453,7 +446,7 @@ class AX_GUI_DLL TextField : public Widget */ std::string_view getPasswordStyleText() const; - virtual void update(float dt) override; + void update(float dt) override; /** * @brief Query whether the IME is attached or not. @@ -520,7 +513,7 @@ class AX_GUI_DLL TextField : public Widget /** * Returns the "class name" of widget. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * @brief Get the renderer size in auto mode. @@ -529,9 +522,9 @@ class AX_GUI_DLL TextField : public Widget */ virtual Vec2 getAutoRenderSize(); // override functions. - virtual Vec2 getVirtualRendererSize() const override; - virtual Node* getVirtualRenderer() override; - virtual void onEnter() override; + Vec2 getVirtualRendererSize() const override; + Node* getVirtualRenderer() override; + void onEnter() override; /** * @brief Attach the IME for inputing. @@ -600,21 +593,21 @@ class AX_GUI_DLL TextField : public Widget */ void setCursorFromPoint(const Vec2& point, const Camera* camera); - virtual bool init() override; + bool init() override; protected: - virtual void initRenderer() override; + void initRenderer() override; void attachWithIMEEvent(); void detachWithIMEEvent(); void insertTextEvent(); void deleteBackwardEvent(); - virtual void onSizeChanged() override; + void onSizeChanged() override; void textfieldRendererScaleChangedWithSize(); - virtual Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; - virtual void adaptRenderers() override; + Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; + void adaptRenderers() override; protected: UICCTextField* _textFieldRenderer; diff --git a/core/ui/UITextFieldEx.cpp b/axmol/ui/UITextFieldEx.cpp similarity index 96% rename from core/ui/UITextFieldEx.cpp rename to axmol/ui/UITextFieldEx.cpp index bf913ddc1502..e1b533330123 100644 --- a/core/ui/UITextFieldEx.cpp +++ b/axmol/ui/UITextFieldEx.cpp @@ -22,8 +22,8 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "UITextFieldEx.h" -#include "base/Director.h" +#include "axmol/ui/UITextFieldEx.h" +#include "axmol/base/Director.h" namespace ax { @@ -90,19 +90,19 @@ static bool engine_inj_containsPoint(ax::Node* target, const ax::Vec2& worldPoin return contains; } -static uint32_t engine_inj_c4b2dw(const Color4B& value) +static uint32_t engine_inj_c4b2dw(const Color32& value) { auto rvalue = (uint32_t)value.a << 24 | (uint32_t)value.b << 16 | (uint32_t)value.g << 8 | (uint32_t)value.r; return rvalue; } -static Sprite* engine_inj_create_lump(const Color4B& color, int height, int width) +static Sprite* engine_inj_create_lump(const Color32& color, int height, int width) { unsigned int* pixels((unsigned int*)malloc(height * width * sizeof(unsigned int))); // Fill Pixels uint32_t* ptr = pixels; - const Color4B fillColor = Color4B::WHITE; + const Color32 fillColor = Color32::WHITE; for (int i = 0; i < height * width; ++i) { ptr[i] = engine_inj_c4b2dw(fillColor); // 0xffffffff; @@ -111,12 +111,11 @@ static Sprite* engine_inj_create_lump(const Color4B& color, int height, int widt // create cursor by pixels Texture2D* texture = new Texture2D(); - texture->initWithData(pixels, height * width * sizeof(unsigned int), backend::PixelFormat::RGBA8, width, height); + texture->initWithData(pixels, height * width * sizeof(unsigned int), rhi::PixelFormat::RGBA8, width, height); auto cursor = Sprite::createWithTexture(texture); - cursor->setColor(Color3B(color)); - cursor->setOpacity(color.a); + cursor->setColor(color); texture->release(); @@ -223,8 +222,8 @@ TextFieldEx::TextFieldEx() , _charCount(0) , _inputText("") , _placeHolder("") - , _colorText(Color4B::WHITE) - , _colorSpaceHolder(Color4B::GRAY) + , _colorText(Color32::WHITE) + , _colorSpaceHolder(Color32::GRAY) , _secureTextEntry(false) , _cursor(nullptr) , _touchListener(nullptr) @@ -259,7 +258,7 @@ TextFieldEx* TextFieldEx::create(std::string_view placeholder, std::string_view fontName, float fontSize, float cursorWidth, - const Color4B& cursorColor) + const Color32& cursorColor) { TextFieldEx* ret = new TextFieldEx(); if (ret && ret->initWithPlaceHolder("", fontName, fontSize, cursorWidth, cursorColor)) @@ -282,7 +281,7 @@ bool TextFieldEx::initWithPlaceHolder(std::string_view placeholder, std::string_view fontName, float fontSize, float cursorWidth, - const Color4B& cursorColor) + const Color32& cursorColor) { _placeHolder = placeholder; @@ -737,34 +736,34 @@ std::string_view TextFieldEx::getContentText() return _inputText; } -void TextFieldEx::setTextColor(const Color4B& color) +void TextFieldEx::setTextColor(const Color32& color) { _colorText = color; if (!_inputText.empty()) _renderLabel->setTextColor(_colorText); } -const Color4B& TextFieldEx::getTextColor(void) const +const Color32& TextFieldEx::getTextColor(void) const { return _colorText; } -void TextFieldEx::setCursorColor(const Color3B& color) +void TextFieldEx::setCursorColor(const Color32& color) { _cursor->setColor(color); } -const Color3B& TextFieldEx::getCursorColor(void) const +const Color32& TextFieldEx::getCursorColor(void) const { return _cursor->getColor(); } -const Color4B& TextFieldEx::getPlaceholderColor() const +const Color32& TextFieldEx::getPlaceholderColor() const { return _colorSpaceHolder; } -void TextFieldEx::setPlaceholderColor(const Color4B& color) +void TextFieldEx::setPlaceholderColor(const Color32& color) { _colorSpaceHolder = color; if (_inputText.empty()) @@ -815,7 +814,7 @@ void TextFieldEx::setString(std::string_view text) bool bInsertAtEnd = (_insertPosUtf8 == _charCount); - _charCount = StringUtils::countUTF8Chars(_inputText); + _charCount = text_utils::countUTF8Chars(_inputText); if (bInsertAtEnd) { @@ -884,9 +883,9 @@ int TextFieldEx::getFontType() const return _fontType; } -void TextFieldEx::__initCursor(int height, int width, const Color4B& color) +void TextFieldEx::__initCursor(int height, int width, const Color32& color) { - _cursor = engine_inj_create_lump(Color4B(color), height, width); + _cursor = engine_inj_create_lump(Color32(color), height, width); this->addChild(_cursor); diff --git a/core/ui/UITextFieldEx.h b/axmol/ui/UITextFieldEx.h similarity index 88% rename from core/ui/UITextFieldEx.h rename to axmol/ui/UITextFieldEx.h index 5dea2f47132f..cf0de59cbe0c 100644 --- a/core/ui/UITextFieldEx.h +++ b/axmol/ui/UITextFieldEx.h @@ -24,11 +24,11 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "base/IMEDelegate.h" -#include "base/SimpleTimer.h" -#include "2d/Label.h" -#include "base/EventListenerKeyboard.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/base/IMEDelegate.h" +#include "axmol/base/SimpleTimer.h" +#include "axmol/2d/Label.h" +#include "axmol/base/EventListenerKeyboard.h" namespace ax { @@ -55,13 +55,13 @@ class AX_DLL TextFieldEx : public Widget, public IMEDelegate std::string_view fontName, float fontSize, float cursorWidth = 2, - const Color4B& color = Color4B::WHITE); + const Color32& color = Color32::WHITE); bool initWithPlaceHolder(std::string_view placeholder, std::string_view fontName, float fontSize, float cursorWidth = 2, - const Color4B& color = Color4B::WHITE); + const Color32& color = Color32::WHITE); void enableIME(Node* control); void disableIME(void); @@ -70,14 +70,14 @@ class AX_DLL TextFieldEx : public Widget, public IMEDelegate inline int getCharCount() const { return static_cast(_charCount); }; - virtual void setPlaceholderColor(const Color4B& color); - virtual const Color4B& getPlaceholderColor() const; + virtual void setPlaceholderColor(const Color32& color); + virtual const Color32& getPlaceholderColor() const; - virtual void setTextColor(const Color4B& textColor); - virtual const Color4B& getTextColor(void) const; + virtual void setTextColor(const Color32& textColor); + virtual const Color32& getTextColor(void) const; - void setCursorColor(const Color3B& color); - const Color3B& getCursorColor(void) const; + void setCursorColor(const Color32& color); + const Color32& getCursorColor(void) const; // input text property virtual void setString(std::string_view text); @@ -157,7 +157,7 @@ class AX_DLL TextFieldEx : public Widget, public IMEDelegate void updateContentSize(void); - void __initCursor(int height, int width = 6, const Color4B& color = Color4B::WHITE); + void __initCursor(int height, int width = 6, const Color32& color = Color32::WHITE); void __showCursor(void); void __hideCursor(void); void __updateCursorPosition(void); @@ -179,8 +179,8 @@ class AX_DLL TextFieldEx : public Widget, public IMEDelegate std::string _inputText; std::string _placeHolder; - Color4B _colorSpaceHolder; - Color4B _colorText; + Color32 _colorSpaceHolder; + Color32 _colorText; bool _secureTextEntry; diff --git a/core/ui/UIVBox.cpp b/axmol/ui/UIVBox.cpp similarity index 98% rename from core/ui/UIVBox.cpp rename to axmol/ui/UIVBox.cpp index 238f20ea3f7f..82e73bd366be 100644 --- a/core/ui/UIVBox.cpp +++ b/axmol/ui/UIVBox.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UIVBox.h" +#include "axmol/ui/UIVBox.h" namespace ax { diff --git a/core/ui/UIVBox.h b/axmol/ui/UIVBox.h similarity index 96% rename from core/ui/UIVBox.h rename to axmol/ui/UIVBox.h index 0081aec566dd..8c91c092871b 100644 --- a/core/ui/UIVBox.h +++ b/axmol/ui/UIVBox.h @@ -26,8 +26,8 @@ #pragma once -#include "ui/UILayout.h" -#include "ui/GUIExport.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/GUIExport.h" namespace ax { @@ -72,7 +72,7 @@ class AX_GUI_DLL VBox : public Layout static VBox* create(const Vec2& size); // initializes state of widget. - virtual bool init() override; + bool init() override; virtual bool initWithSize(const Vec2& size); }; diff --git a/core/ui/UIWebView/UIWebView-inl.h b/axmol/ui/UIWebView/UIWebView-inl.h similarity index 97% rename from core/ui/UIWebView/UIWebView-inl.h rename to axmol/ui/UIWebView/UIWebView-inl.h index 6836c2a5c643..fdfc83d3cc32 100644 --- a/core/ui/UIWebView/UIWebView-inl.h +++ b/axmol/ui/UIWebView/UIWebView-inl.h @@ -31,10 +31,10 @@ (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || \ AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) -#include "ui/UIWebView/UIWebView.h" -#include "platform/RenderView.h" -#include "base/Director.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UIWebView/UIWebView.h" +#include "axmol/platform/RenderView.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/core/ui/UIWebView/UIWebView.cpp b/axmol/ui/UIWebView/UIWebView.cpp similarity index 81% rename from core/ui/UIWebView/UIWebView.cpp rename to axmol/ui/UIWebView/UIWebView.cpp index 298f2b6f9eb0..2b7540d95f94 100644 --- a/core/ui/UIWebView/UIWebView.cpp +++ b/axmol/ui/UIWebView/UIWebView.cpp @@ -23,21 +23,21 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "ui/UIWebView/UIWebViewImpl-android.h" -# include "ui/UIWebView/UIWebView-inl.h" +# include "axmol/ui/UIWebView/UIWebViewImpl-android.h" +# include "axmol/ui/UIWebView/UIWebView-inl.h" #elif (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "ui/UIWebView/UIWebViewImpl-win32.h" -# include "ui/UIWebView/UIWebView-inl.h" +# include "axmol/ui/UIWebView/UIWebViewImpl-win32.h" +# include "axmol/ui/UIWebView/UIWebView-inl.h" #elif (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) -# include "ui/UIWebView/UIWebViewImpl-linux.h" -# include "ui/UIWebView/UIWebView-inl.h" +# include "axmol/ui/UIWebView/UIWebViewImpl-linux.h" +# include "axmol/ui/UIWebView/UIWebView-inl.h" #endif diff --git a/core/ui/UIWebView/UIWebView.h b/axmol/ui/UIWebView/UIWebView.h similarity index 94% rename from core/ui/UIWebView/UIWebView.h rename to axmol/ui/UIWebView/UIWebView.h index e9aae5fb7b09..e5720f74aa88 100644 --- a/core/ui/UIWebView/UIWebView.h +++ b/axmol/ui/UIWebView/UIWebView.h @@ -25,9 +25,9 @@ ****************************************************************************/ #pragma once -#include "ui/UIWidget.h" -#include "ui/GUIExport.h" -#include "base/Data.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/base/Data.h" #if (defined(_WIN32) && defined(AX_ENABLE_MSEDGE_WEBVIEW2)) || \ (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || \ @@ -208,12 +208,12 @@ class AX_GUI_DLL WebView : public ax::ui::Widget */ void setBounces(bool bounce); - virtual void draw(ax::Renderer* renderer, ax::Mat4 const& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, ax::Mat4 const& transform, uint32_t flags) override; /** * Toggle visibility of WebView. */ - virtual void setVisible(bool visible) override; + void setVisible(bool visible) override; /** * SetOpacity of webview. */ @@ -228,8 +228,8 @@ class AX_GUI_DLL WebView : public ax::ui::Widget * set the background transparent */ virtual void setBackgroundTransparent(); - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; /** * Default constructor. @@ -238,8 +238,8 @@ class AX_GUI_DLL WebView : public ax::ui::Widget virtual ~WebView(); protected: - virtual ax::ui::Widget* createCloneInstance() override; - virtual void copySpecialProperties(Widget* model) override; + ax::ui::Widget* createCloneInstance() override; + void copySpecialProperties(Widget* model) override; std::function _onShouldStartLoading = nullptr; ccWebViewCallback _onDidFinishLoading = nullptr; diff --git a/core/ui/UIWebView/UIWebView.mm b/axmol/ui/UIWebView/UIWebView.mm similarity index 93% rename from core/ui/UIWebView/UIWebView.mm rename to axmol/ui/UIWebView/UIWebView.mm index 64d1722e4849..1b3248aac84f 100644 --- a/core/ui/UIWebView/UIWebView.mm +++ b/axmol/ui/UIWebView/UIWebView.mm @@ -24,5 +24,5 @@ of this software and associated documentation files (the "Software"), to deal THE SOFTWARE. ****************************************************************************/ -#include "ui/UIWebView/UIWebViewImpl-ios.h" -#include "ui/UIWebView/UIWebView-inl.h" +#include "axmol/ui/UIWebView/UIWebViewImpl-ios.h" +#include "axmol/ui/UIWebView/UIWebView-inl.h" diff --git a/core/ui/UIWebView/UIWebViewCommon.h b/axmol/ui/UIWebView/UIWebViewCommon.h similarity index 99% rename from core/ui/UIWebView/UIWebViewCommon.h rename to axmol/ui/UIWebView/UIWebViewCommon.h index de621891cb6b..7e74e75d31a0 100644 --- a/core/ui/UIWebView/UIWebViewCommon.h +++ b/axmol/ui/UIWebView/UIWebViewCommon.h @@ -26,7 +26,7 @@ #include "rapidjson/document.h" #include "rapidjson/stringbuffer.h" #include "rapidjson/writer.h" -#include "base/Utils.h" +#include "axmol/base/Utils.h" namespace webview_common { diff --git a/core/ui/UIWebView/UIWebViewImpl-android.cpp b/axmol/ui/UIWebView/UIWebViewImpl-android.cpp similarity index 97% rename from core/ui/UIWebView/UIWebViewImpl-android.cpp rename to axmol/ui/UIWebView/UIWebViewImpl-android.cpp index 3d0643d55f2a..ffcc671b61e5 100644 --- a/core/ui/UIWebView/UIWebViewImpl-android.cpp +++ b/axmol/ui/UIWebView/UIWebViewImpl-android.cpp @@ -23,18 +23,18 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIWebView/UIWebViewImpl-android.h" +#include "axmol/ui/UIWebView/UIWebViewImpl-android.h" #include #include #include -#include "platform/android/jni/JniHelper.h" +#include "axmol/platform/android/jni/JniHelper.h" -#include "ui/UIWebView/UIWebView.h" -#include "platform/RenderView.h" -#include "base/Director.h" -#include "platform/FileUtils.h" -#include "ui/UIHelper.h" +#include "axmol/ui/UIWebView/UIWebView.h" +#include "axmol/platform/RenderView.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/ui/UIHelper.h" #include "yasio/string_view.hpp" static const char* className = "dev.axmol.lib.WebViewHelper"; diff --git a/core/ui/UIWebView/UIWebViewImpl-android.h b/axmol/ui/UIWebView/UIWebViewImpl-android.h similarity index 98% rename from core/ui/UIWebView/UIWebViewImpl-android.h rename to axmol/ui/UIWebView/UIWebViewImpl-android.h index 9a1a18ffb34e..fc5b87f3919c 100644 --- a/core/ui/UIWebView/UIWebViewImpl-android.h +++ b/axmol/ui/UIWebView/UIWebViewImpl-android.h @@ -32,7 +32,7 @@ #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/core/ui/UIWebView/UIWebViewImpl-ios.h b/axmol/ui/UIWebView/UIWebViewImpl-ios.h similarity index 98% rename from core/ui/UIWebView/UIWebViewImpl-ios.h rename to axmol/ui/UIWebView/UIWebViewImpl-ios.h index 79502365641b..4a23a423570d 100644 --- a/core/ui/UIWebView/UIWebViewImpl-ios.h +++ b/axmol/ui/UIWebView/UIWebViewImpl-ios.h @@ -31,7 +31,7 @@ #include #include -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" @class UIWebViewWrapper; diff --git a/core/ui/UIWebView/UIWebViewImpl-ios.mm b/axmol/ui/UIWebView/UIWebViewImpl-ios.mm similarity index 98% rename from core/ui/UIWebView/UIWebViewImpl-ios.mm rename to axmol/ui/UIWebView/UIWebViewImpl-ios.mm index c0b4c4b255be..529371a57221 100644 --- a/core/ui/UIWebView/UIWebViewImpl-ios.mm +++ b/axmol/ui/UIWebView/UIWebViewImpl-ios.mm @@ -27,13 +27,13 @@ of this software and associated documentation files (the "Software"), to deal #import #import -#include "ui/UIWebView/UIWebViewImpl-ios.h" -#include "ui/UIWebView/UIWebView.h" -#include "renderer/Renderer.h" -#include "base/Director.h" -#include "platform/RenderView.h" -#include "platform/ios/EARenderView-ios.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UIWebView/UIWebViewImpl-ios.h" +#include "axmol/ui/UIWebView/UIWebView.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/base/Director.h" +#include "axmol/platform/RenderView.h" +#include "axmol/platform/ios/EARenderView-ios.h" +#include "axmol/platform/FileUtils.h" @interface UIWebViewWrapper : NSObject @property(nonatomic) std::function shouldStartLoading; diff --git a/core/ui/UIWebView/UIWebViewImpl-linux.cpp b/axmol/ui/UIWebView/UIWebViewImpl-linux.cpp similarity index 98% rename from core/ui/UIWebView/UIWebViewImpl-linux.cpp rename to axmol/ui/UIWebView/UIWebViewImpl-linux.cpp index 1076d239eb71..0ac1b9250d6b 100644 --- a/core/ui/UIWebView/UIWebViewImpl-linux.cpp +++ b/axmol/ui/UIWebView/UIWebViewImpl-linux.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "UIWebViewImpl-linux.h" +#include "axmol/ui/UIWebView/UIWebViewImpl-linux.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) @@ -34,12 +34,12 @@ # include # include -# include "UIWebView.h" -# include "base/Director.h" -# include "platform/FileUtils.h" -# include "platform/RenderView.h" -# include "ui/UIHelper.h" -# include "UIWebViewCommon.h" +# include "axmol/ui/UIWebView/UIWebView.h" +# include "axmol/base/Director.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/platform/RenderView.h" +# include "axmol/ui/UIHelper.h" +# include "axmol/ui/UIWebView/UIWebViewCommon.h" # if !defined(AX_PLATFORM_LINUX_WAYLAND) # include diff --git a/core/ui/UIWebView/UIWebViewImpl-linux.h b/axmol/ui/UIWebView/UIWebViewImpl-linux.h similarity index 97% rename from core/ui/UIWebView/UIWebViewImpl-linux.h rename to axmol/ui/UIWebView/UIWebViewImpl-linux.h index fae83405d423..cab3e264a3f8 100644 --- a/core/ui/UIWebView/UIWebViewImpl-linux.h +++ b/axmol/ui/UIWebView/UIWebViewImpl-linux.h @@ -24,12 +24,12 @@ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) # include -# include "StdC.h" +# include "axmol/platform/StdC.h" namespace ax { diff --git a/core/ui/UIWebView/UIWebViewImpl-win32.cpp b/axmol/ui/UIWebView/UIWebViewImpl-win32.cpp similarity index 98% rename from core/ui/UIWebView/UIWebViewImpl-win32.cpp rename to axmol/ui/UIWebView/UIWebViewImpl-win32.cpp index 9c3259f23c0f..f7530a8790eb 100644 --- a/core/ui/UIWebView/UIWebViewImpl-win32.cpp +++ b/axmol/ui/UIWebView/UIWebViewImpl-win32.cpp @@ -27,17 +27,14 @@ #if defined(_WIN32) && defined(AX_ENABLE_MSEDGE_WEBVIEW2) -# include "UIWebViewImpl-win32.h" -# include "UIWebView.h" -# include "UIWebViewCommon.h" -# include "base/Director.h" -# include "platform/FileUtils.h" -# include "platform/RenderView.h" -# include "ui/UIHelper.h" -# include "rapidjson/document.h" -# include "rapidjson/stringbuffer.h" -# include "rapidjson/writer.h" -# include "base/Utils.h" +# include "axmol/ui/UIWebView/UIWebViewImpl-win32.h" +# include "axmol/ui/UIWebView/UIWebView.h" +# include "axmol/ui/UIWebView/UIWebViewCommon.h" +# include "axmol/base/Director.h" +# include "axmol/platform/FileUtils.h" +# include "axmol/platform/RenderView.h" +# include "axmol/ui/UIHelper.h" +# include "axmol/base/Utils.h" # define WIN32_LEAN_AND_MEAN # include @@ -54,7 +51,7 @@ # pragma comment(lib, "ole32.lib") # pragma comment(lib, "oleaut32.lib") -# include "platform/PlatformConfig.h" +# include "axmol/platform/PlatformConfig.h" # include "ntcvt/ntcvt.hpp" diff --git a/core/ui/UIWebView/UIWebViewImpl-win32.h b/axmol/ui/UIWebView/UIWebViewImpl-win32.h similarity index 97% rename from core/ui/UIWebView/UIWebViewImpl-win32.h rename to axmol/ui/UIWebView/UIWebViewImpl-win32.h index 356776c2c7d5..e521deea5033 100644 --- a/core/ui/UIWebView/UIWebViewImpl-win32.h +++ b/axmol/ui/UIWebView/UIWebViewImpl-win32.h @@ -26,12 +26,12 @@ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #if defined(_WIN32) && defined(AX_ENABLE_MSEDGE_WEBVIEW2) # include -# include "StdC.h" +# include "axmol/platform/StdC.h" namespace ax { diff --git a/core/ui/UIWidget.cpp b/axmol/ui/UIWidget.cpp similarity index 98% rename from core/ui/UIWidget.cpp rename to axmol/ui/UIWidget.cpp index b78fc6b6d805..6e25217668aa 100644 --- a/core/ui/UIWidget.cpp +++ b/axmol/ui/UIWidget.cpp @@ -24,19 +24,19 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/UIWidget.h" -#include "ui/UILayout.h" -#include "ui/UIHelper.h" -#include "base/EventListenerTouch.h" -#include "base/EventListenerKeyboard.h" -#include "base/Director.h" -#include "base/EventFocus.h" -#include "base/EventDispatcher.h" -#include "ui/UILayoutComponent.h" -#include "renderer/Shaders.h" -#include "2d/Camera.h" -#include "2d/Sprite.h" -#include "ui/UIScale9Sprite.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventFocus.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/ui/UILayoutComponent.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Sprite.h" +#include "axmol/ui/UIScale9Sprite.h" namespace ax { diff --git a/core/ui/UIWidget.h b/axmol/ui/UIWidget.h similarity index 96% rename from core/ui/UIWidget.h rename to axmol/ui/UIWidget.h index 237d2fd87f2f..407433117c5b 100644 --- a/core/ui/UIWidget.h +++ b/axmol/ui/UIWidget.h @@ -26,11 +26,11 @@ THE SOFTWARE. #pragma once -#include "2d/ProtectedNode.h" -#include "ui/UILayoutParameter.h" -#include "ui/GUIDefine.h" -#include "ui/GUIExport.h" -#include "base/Map.h" +#include "axmol/2d/ProtectedNode.h" +#include "axmol/ui/UILayoutParameter.h" +#include "axmol/ui/GUIDefine.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/base/Map.h" /** * @addtogroup ui @@ -265,7 +265,7 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol /** */ - virtual void visit(ax::Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(ax::Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; /** * Set a callback to touch vent listener. @@ -293,7 +293,7 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol * * @param pos The position (x,y) of the widget in OpenGL coordinates */ - virtual void setPosition(const Vec2& pos) override; + void setPosition(const Vec2& pos) override; /** Sets the position (x,y) using values between 0 and 1. * @@ -372,14 +372,14 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol virtual bool isFlippedY() const { return _flippedY; }; // override the setScale function of Node - virtual void setScaleX(float scaleX) override; - virtual void setScaleY(float scaleY) override; - virtual void setScale(float scale) override; - virtual void setScale(float scalex, float scaley) override; + void setScaleX(float scaleX) override; + void setScaleY(float scaleY) override; + void setScale(float scale) override; + void setScale(float scalex, float scaley) override; using Node::setScaleZ; - virtual float getScaleX() const override; - virtual float getScaleY() const override; - virtual float getScale() const override; + float getScaleX() const override; + float getScaleY() const override; + float getScale() const override; using Node::getScaleZ; /** @@ -412,7 +412,7 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol * Changes the size that is widget's size * @param contentSize A content size in `Vec2`. */ - virtual void setContentSize(const Vec2& contentSize) override; + void setContentSize(const Vec2& contentSize) override; /** * Changes the percent that is widget's percent size @@ -572,7 +572,7 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol * Returns the string representation of widget class name * @return get the class description. */ - virtual std::string getDescription() const override; + std::string getDescription() const override; /** * Create a new widget copy of the original one. @@ -582,12 +582,12 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * Update all children's contents size and position recursively. @@ -768,7 +768,7 @@ class AX_GUI_DLL Widget : public ProtectedNode, public LayoutParameterProtocol friend class PageView; // initializes state of widget. - virtual bool init() override; + bool init() override; /* * @brief Sends the touch event to widget's parent, if a widget wants to handle touch event under another widget, diff --git a/core/ui/axmol-ui.cpp b/axmol/ui/axmol-ui.cpp similarity index 98% rename from core/ui/axmol-ui.cpp rename to axmol/ui/axmol-ui.cpp index 514ede9b91de..12b451325726 100644 --- a/core/ui/axmol-ui.cpp +++ b/axmol/ui/axmol-ui.cpp @@ -24,7 +24,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" namespace ax { diff --git a/core/ui/axmol-ui.h b/axmol/ui/axmol-ui.h similarity index 64% rename from core/ui/axmol-ui.h rename to axmol/ui/axmol-ui.h index 74b0166039ce..a0d086f121e6 100644 --- a/core/ui/axmol-ui.h +++ b/axmol/ui/axmol-ui.h @@ -26,38 +26,38 @@ THE SOFTWARE. #pragma once -#include "ui/UIWidget.h" -#include "ui/UILayout.h" -#include "ui/UIButton.h" -#include "ui/UICheckBox.h" -#include "ui/UIRadioButton.h" -#include "ui/UIImageView.h" -#include "ui/UIText.h" -#include "ui/UITextAtlas.h" -#include "ui/UILoadingBar.h" -#include "ui/UIScrollView.h" -#include "ui/UIListView.h" -#include "ui/UISlider.h" -#include "ui/UITextField.h" -#include "ui/UITextFieldEx.h" -#include "ui/UITextBMFont.h" -#include "ui/UIPageView.h" -#include "ui/UIHelper.h" -#include "ui/UIRichText.h" -#include "ui/UIHBox.h" -#include "ui/UIVBox.h" -#include "ui/UIRelativeBox.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/UILayout.h" +#include "axmol/ui/UIButton.h" +#include "axmol/ui/UICheckBox.h" +#include "axmol/ui/UIRadioButton.h" +#include "axmol/ui/UIImageView.h" +#include "axmol/ui/UIText.h" +#include "axmol/ui/UITextAtlas.h" +#include "axmol/ui/UILoadingBar.h" +#include "axmol/ui/UIScrollView.h" +#include "axmol/ui/UIListView.h" +#include "axmol/ui/UISlider.h" +#include "axmol/ui/UITextField.h" +#include "axmol/ui/UITextFieldEx.h" +#include "axmol/ui/UITextBMFont.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/ui/UIRichText.h" +#include "axmol/ui/UIHBox.h" +#include "axmol/ui/UIVBox.h" +#include "axmol/ui/UIRelativeBox.h" #if defined(AX_ENABLE_MEDIA) -# include "ui/UIMediaPlayer.h" +# include "axmol/ui/UIMediaPlayer.h" #endif #if !defined(_WIN32) || defined(AX_ENABLE_MSEDGE_WEBVIEW2) -# include "ui/UIWebView/UIWebView.h" +# include "axmol/ui/UIWebView/UIWebView.h" #endif -#include "ui/GUIExport.h" -#include "ui/UIScale9Sprite.h" -#include "ui/UIEditBox/UIEditBox.h" -#include "ui/UILayoutComponent.h" -#include "ui/UITabControl.h" +#include "axmol/ui/GUIExport.h" +#include "axmol/ui/UIScale9Sprite.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UILayoutComponent.h" +#include "axmol/ui/UITabControl.h" /** * @addtogroup ui diff --git a/cmake/Modules/AXBuildHelpers.cmake b/cmake/Modules/AXBuildHelpers.cmake index 8ed753bf130f..7db1d1c6cdda 100644 --- a/cmake/Modules/AXBuildHelpers.cmake +++ b/cmake/Modules/AXBuildHelpers.cmake @@ -580,7 +580,7 @@ function(ax_setup_app_config app_name) endif() endfunction() -set(AX_WASM_SHELL_FILE "${_AX_ROOT}/core/platform/wasm/shell_minimal.html" CACHE STRING "The path of wasm shell file") +set(AX_WASM_SHELL_FILE "${_AX_ROOT}/axmol/platform/wasm/shell_minimal.html" CACHE STRING "The path of wasm shell file") option(AX_WASM_ENABLE_DEVTOOLS "Enable wasm devtools" ON) @@ -678,14 +678,14 @@ macro(ax_setup_winrt_sources) proj.winrt/App.h proj.winrt/App.cpp proj.winrt/Package.appxmanifest - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.xaml - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.idl - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.h - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.cpp - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLES.h - ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLES.cpp - ${_AX_ROOT}/core/platform/winrt/xaml/AxmolRenderer.h - ${_AX_ROOT}/core/platform/winrt/xaml/AxmolRenderer.cpp + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.xaml + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.idl + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.h + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.cpp + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLES.h + ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLES.cpp + ${_AX_ROOT}/axmol/platform/winrt/xaml/AxmolRenderer.h + ${_AX_ROOT}/axmol/platform/winrt/xaml/AxmolRenderer.cpp ) file(TO_NATIVE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/proj.winrt/App.xaml" APP_XAML_FULL_PATH) @@ -694,14 +694,14 @@ macro(ax_setup_winrt_sources) PROPERTY VS_SETTINGS "DependentUpon=${APP_XAML_FULL_PATH}" ) - file(TO_NATIVE_PATH "${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.xaml" MAINPAGE_XAML_FULL_PATH) + file(TO_NATIVE_PATH "${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.xaml" MAINPAGE_XAML_FULL_PATH) set_property( - SOURCE ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.h ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.cpp ${_AX_ROOT}/core/platform/winrt/xaml/OpenGLESPage.idl + SOURCE ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.h ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.cpp ${_AX_ROOT}/axmol/platform/winrt/xaml/OpenGLESPage.idl PROPERTY VS_SETTINGS "DependentUpon=${MAINPAGE_XAML_FULL_PATH}" ) - list(APPEND GAME_INC_DIRS ${_AX_ROOT}/core/platform/winrt/xaml) + list(APPEND GAME_INC_DIRS ${_AX_ROOT}/axmol/platform/winrt/xaml) list(APPEND GAME_HEADER ${PLATFORM_HEADERS} diff --git a/cmake/Modules/AXConfigDefine.cmake b/cmake/Modules/AXConfigDefine.cmake index 6a3ece85f951..13277bd496e5 100644 --- a/cmake/Modules/AXConfigDefine.cmake +++ b/cmake/Modules/AXConfigDefine.cmake @@ -19,6 +19,11 @@ if(WINRT) set(CMAKE_CXX_FLAGS "/sdl- ${CMAKE_CXX_FLAGS}") endif() +if(ANDROID OR LINUX) + set(CMAKE_C_FLAGS "-fPIC ${CMAKE_C_FLAGS}") + set(CMAKE_CXX_FLAGS "-fPIC ${CMAKE_CXX_FLAGS}") +endif() + # config c standard if(WINDOWS) message(STATUS "CMAKE_HOST_SYSTEM_VERSION: ${CMAKE_HOST_SYSTEM_VERSION}") @@ -61,8 +66,8 @@ if(NOT DEFINED CMAKE_C_STANDARD_REQUIRED) set(CMAKE_C_STANDARD_REQUIRED ON) endif() -# config c++ standard, minimal require c++20 -set(_AX_MIN_CXX_STD 20) +# config c++ standard, minimal require c++23 +set(_AX_MIN_CXX_STD 23) if(NOT DEFINED CMAKE_CXX_STANDARD) set(CMAKE_CXX_STANDARD ${_AX_MIN_CXX_STD}) @@ -159,35 +164,10 @@ function(use_ax_compile_define target) # !important axmol not use double precision # target_compile_definitions(${target} PUBLIC CP_USE_CGTYPES=0) # target_compile_definitions(${target} PUBLIC CP_USE_DOUBLES=0) - if(APPLE) - target_compile_definitions(${target} PUBLIC __APPLE__) - - if(AX_USE_GL) - target_compile_definitions(${target} - PUBLIC AX_USE_GL=1 - PUBLIC GL_SILENCE_DEPRECATION=1 - ) - - if(NOT _AX_USE_PREBUILT) - target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) - endif() - endif() - elseif(LINUX) + if(LINUX) ax_config_pred(${target} AX_ENABLE_VLC_MEDIA) target_compile_definitions(${target} PUBLIC _GNU_SOURCE) - elseif(ANDROID) - if(NOT _AX_USE_PREBUILT) - target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) - endif() - - target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) - elseif(EMSCRIPTEN) - target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) elseif(WINDOWS) - if(NOT _AX_USE_PREBUILT) - target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) - endif() - ax_config_pred(${target} AX_ENABLE_VLC_MEDIA) target_compile_definitions(${target} PUBLIC WIN32 @@ -197,7 +177,6 @@ function(use_ax_compile_define target) PUBLIC _UNICODE PUBLIC _CRT_SECURE_NO_WARNINGS PUBLIC _SCL_SECURE_NO_WARNINGS - # PUBLIC GLAD_GLAPI_EXPORT ) @@ -205,6 +184,19 @@ function(use_ax_compile_define target) target_compile_definitions(${target} PRIVATE AX_DLLEXPORT INTERFACE AX_DLLIMPORT) endif() endif() + + # render api + if(AX_RENDER_API STREQUAL "gl") + target_compile_definitions(${target} PUBLIC AX_RENDER_API=1) + if(APPLE) + target_compile_definitions(${target} PUBLIC GL_SILENCE_DEPRECATION=1) + endif() + target_compile_definitions(${target} PUBLIC AX_GLES_PROFILE=${AX_GLES_PROFILE}) + elseif(AX_RENDER_API STREQUAL "mtl") + target_compile_definitions(${target} PUBLIC AX_RENDER_API=2) + elseif(AX_RENDER_API STREQUAL "d3d") + target_compile_definitions(${target} PUBLIC AX_RENDER_API=3) + endif() endfunction() # Set compiler options for engine lib: axmol diff --git a/cmake/Modules/AXConfigDepend.cmake b/cmake/Modules/AXConfigDepend.cmake index 5fe23b6d7e49..7eb98281656a 100644 --- a/cmake/Modules/AXConfigDepend.cmake +++ b/cmake/Modules/AXConfigDepend.cmake @@ -74,7 +74,7 @@ macro(ax_depend) ${COREAUDIO_LIBRARY} ${SYSTEMCONFIGURATION_LIBRARY} ) - if(AX_USE_COMPAT_GL) + if(AX_RENDER_API STREQUAL "gl") find_library(OPENGL_LIBRARY OpenGL) list(APPEND PLATFORM_SPECIFIC_LIBS ${OPENGL_LIBRARY}) endif() @@ -101,7 +101,7 @@ macro(ax_depend) ${_AX_APPLE_LIBS} ) - if(AX_USE_COMPAT_GL) + if(AX_RENDER_API STREQUAL "gl") find_library(OPENGLES_LIBRARY OpenGLES) list(APPEND PLATFORM_SPECIFIC_LIBS ${OPENGLES_LIBRARY}) endif() diff --git a/cmake/Modules/AXLinkHelpers.cmake b/cmake/Modules/AXLinkHelpers.cmake index 5298988a0276..cd922c87d348 100644 --- a/cmake/Modules/AXLinkHelpers.cmake +++ b/cmake/Modules/AXLinkHelpers.cmake @@ -53,8 +53,6 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR) PRIVATE NOUNCRYPT=1 PRIVATE P2T_STATIC_EXPORTS=1 PRIVATE BT_USE_SSE_IN_API=1 - PRIVATE CP_USE_DOUBLES=0 - PRIVATE CP_USE_CGTYPES=0 ) ax_config_pred(${APP_NAME} AX_USE_ALSOFT) @@ -82,17 +80,16 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR) PRIVATE ${AX_ROOT_DIR} PRIVATE ${AX_ROOT_DIR}/3rdparty PRIVATE ${AX_ROOT_DIR}/extensions - PRIVATE ${AX_ROOT_DIR}/core - PRIVATE ${AX_ROOT_DIR}/core/platform - PRIVATE ${AX_ROOT_DIR}/core/base - PRIVATE ${AX_ROOT_DIR}/core/audio - PRIVATE ${AX_ROOT_DIR}/core/platform/win32 + PRIVATE ${AX_ROOT_DIR}/axmol + PRIVATE ${AX_ROOT_DIR}/axmol/platform + PRIVATE ${AX_ROOT_DIR}/axmol/base + PRIVATE ${AX_ROOT_DIR}/axmol/audio + PRIVATE ${AX_ROOT_DIR}/axmol/platform/win32 PRIVATE ${AX_ROOT_DIR}/3rdparty/fmt/include PRIVATE ${AX_ROOT_DIR}/3rdparty/robin-map/include PRIVATE ${AX_ROOT_DIR}/3rdparty/freetype/include PRIVATE ${AX_ROOT_DIR}/3rdparty/glfw/include/GLFW PRIVATE ${AX_ROOT_DIR}/3rdparty/box2d/include - PRIVATE ${AX_ROOT_DIR}/3rdparty/chipmunk/include PRIVATE ${AX_ROOT_DIR}/${AX_PREBUILT_DIR}/engine/3rdparty/freetype/include PRIVATE ${AX_ROOT_DIR}/3rdparty/webp/src/webp PRIVATE ${AX_ROOT_DIR}/3rdparty/pugixml @@ -136,7 +133,6 @@ function(ax_link_cxx_prebuilt APP_NAME AX_ROOT_DIR AX_PREBUILT_DIR) set(LIBS axmol box2d - chipmunk freetype webp pugixml diff --git a/cmake/Modules/AXSLCC.cmake b/cmake/Modules/AXSLCC.cmake index 48be31bd79cd..8be62f737e66 100644 --- a/cmake/Modules/AXSLCC.cmake +++ b/cmake/Modules/AXSLCC.cmake @@ -51,7 +51,7 @@ define_property(SOURCE PROPERTY AXSLCC_OUTPUT # Find shader sources in specified directory # syntax: ax_find_shaders(dir shader_sources [RECURSE]) # examples: -# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/core/renderer/shaders" runtime_shader_sources) +# - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/axmol/renderer/shaders" runtime_shader_sources) # - ax_find_shaders("${CMAKE_CURRENT_LIST_DIR}/Source" custom_shader_sources RECURSE) function(ax_find_shaders dir varName) set(options RECURSE) @@ -107,26 +107,32 @@ function(ax_target_compile_shaders target_name) if(AX_GLES_PROFILE) # version 300 es - if(AX_GLES_PROFILE EQUAL 300) - set(OUT_LANG "ESSL") + set(OUT_LANG "ESSL") + if(AX_GLES_PROFILE GREATER_EQUAL 300) set(SC_PROFILE "300") + set(SC_DEFINES "AXSLC_TARGET_GLES") else() - # GLSL2 use glsl100 syntax es profile alka essl100 - set(OUT_LANG "ESSL") + # GLSL2 use glsl100 syntax es profile aka essl100 set(SC_PROFILE "100") - set(SC_DEFINES "GLES2") + set(SC_DEFINES "AXSLC_TARGET_GLES2") endif() - + set(SC_DEFINES "AXSLC_TARGET_GLSL,${SC_DEFINES}") list(APPEND SC_FLAGS "--lang=gles" "--profile=${SC_PROFILE}") - elseif(AX_USE_GL) + elseif(AX_RENDER_API STREQUAL "gl") # version 330 set(OUT_LANG "GLSL") set(SC_PROFILE "330") + set(SC_DEFINES "AXSLC_TARGET_GLSL") list(APPEND SC_FLAGS "--lang=glsl" "--profile=${SC_PROFILE}") - elseif(AX_USE_METAL) + elseif(AX_RENDER_API STREQUAL "d3d") + set(OUT_LANG "HLSL") + set(SC_PROFILE "50") # D3D11 HLSL 5.0 + set(SC_DEFINES "AXSLC_TARGET_HLSL") + list(APPEND SC_FLAGS "--lang=hlsl" "--profile=${SC_PROFILE}") + elseif(AX_RENDER_API STREQUAL "mtl") set(OUT_LANG "MSL") + set(SC_DEFINES "AXSLC_TARGET_MSL") list(APPEND SC_FLAGS "--lang=msl") - set(SC_DEFINES "METAL") endif() # automap, no-suffix since 1.18.1 released by axmolengine @@ -150,15 +156,15 @@ function(ax_target_compile_shaders target_name) set(INC_DIRS "") endif() - list(APPEND INC_DIRS "${_AX_ROOT}/core/renderer/shaders") + list(APPEND INC_DIRS "${_AX_ROOT}/axmol/renderer/shaders") list(APPEND SC_FLAGS "--include-dirs=${INC_DIRS}") if(opt_CVAR) list(APPEND SC_FLAGS "--cvar=shader_rt_${FILE_NAME}") endif() - # sgs, because Apple Metal lack of shader uniform reflect so use --sgs --refelect - if(AX_USE_METAL) + # sgs, because Apple Metal lack of shader uniform reflect and d3d reflect only support semantic name, so use --sgs --refelect + if(AX_RENDER_API STREQUAL "mtl" OR AX_RENDER_API STREQUAL "d3d") list(APPEND SC_FLAGS "--sgs" "--reflect") endif() @@ -186,7 +192,7 @@ function(ax_target_compile_shaders target_name) set(SC_OUTPUT "${OUT_DIR}/${FILE_NAME}_${SC_TYPE}") - set(SC_COMMENT "Compiling shader ${SC_FILE} for ${OUT_LANG}${SC_PROFILE} ...") + set(SC_COMMENT "Compiling shader ${SC_FILE} to ${OUT_LANG}${SC_PROFILE} ...") get_source_file_property(SOURCE_SC_OUTPUT1 ${SC_FILE} AXSLCC_OUTPUT1) diff --git a/core/3d/Bundle3D.cpp b/core/3d/Bundle3D.cpp deleted file mode 100644 index ce9538e80628..000000000000 --- a/core/3d/Bundle3D.cpp +++ /dev/null @@ -1,2338 +0,0 @@ -/**************************************************************************** -Copyright (c) 2014-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#include "3d/Bundle3D.h" -#include "3d/ObjLoader.h" - -#include "base/Macros.h" -#include "platform/FileUtils.h" -#include "3d/BundleReader.h" -#include "base/Data.h" - -#define BUNDLE_TYPE_SCENE 1 -#define BUNDLE_TYPE_NODE 2 -#define BUNDLE_TYPE_ANIMATIONS 3 -#define BUNDLE_TYPE_ANIMATION 4 -#define BUNDLE_TYPE_ANIMATION_CHANNEL 5 -#define BUNDLE_TYPE_MODEL 10 -#define BUNDLE_TYPE_MATERIAL 16 -#define BUNDLE_TYPE_EFFECT 18 -#define BUNDLE_TYPE_CAMERA 32 -#define BUNDLE_TYPE_LIGHT 33 -#define BUNDLE_TYPE_MESH 34 -#define BUNDLE_TYPE_MESHPART 35 -#define BUNDLE_TYPE_MESHSKIN 36 - -static const char* VERSION = "version"; -static const char* ID = "id"; -static const char* DEFAULTPART = "body"; -static const char* VERTEXSIZE = "vertexsize"; -static const char* VERTEX = "vertex"; -static const char* VERTICES = "vertices"; -static const char* INDEXNUM = "indexnum"; -static const char* INDICES = "indices"; -static const char* SUBMESH = "submesh"; -static const char* ATTRIBUTES = "attributes"; -static const char* ATTRIBUTESIZE = "size"; -static const char* TYPE = "type"; -static const char* ATTRIBUTE = "attribute"; -static const char* SKIN = "skin"; -static const char* BINDSHAPE = "bindshape"; -static const char* MESH = "mesh"; -static const char* MESHES = "meshes"; -static const char* MESHPARTID = "meshpartid"; -static const char* MATERIALID = "materialid"; -static const char* NODE = "node"; -static const char* NODES = "nodes"; -static const char* CHILDREN = "children"; -static const char* PARTS = "parts"; -static const char* BONES = "bones"; -static const char* SKELETON = "skeleton"; -static const char* MATERIALS = "materials"; -static const char* ANIMATIONS = "animations"; -static const char* TRANSFORM = "transform"; -static const char* OLDTRANSFORM = "tansform"; -static const char* ANIMATION = "animation"; -static const char* MATERIAL = "material"; -static const char* BASE = "base"; -static const char* FILENAME = "filename"; -static const char* TEXTURES = "textures"; -static const char* LENGTH = "length"; -static const char* BONEID = "boneId"; -static const char* KEYFRAMES = "keyframes"; -static const char* TRANSLATION = "translation"; -static const char* ROTATION = "rotation"; -static const char* SCALE = "scale"; -static const char* KEYTIME = "keytime"; -static const char* AABBS = "aabb"; - -namespace ax -{ - -void getChildMap(std::map>& map, SkinData* skinData, const rapidjson::Value& val) -{ - if (!skinData) - return; - - // get transform matrix - Mat4 transform; - const rapidjson::Value& parent_transform = val[OLDTRANSFORM]; - for (rapidjson::SizeType j = 0, size = parent_transform.Size(); j < size; ++j) - { - transform.m[j] = parent_transform[j].GetFloat(); - } - - // set origin matrices - std::string parent_name = val[ID].GetString(); - int parent_name_index = skinData->getSkinBoneNameIndex(parent_name); - if (parent_name_index < 0) - { - skinData->addNodeBoneNames(parent_name); - skinData->nodeBoneOriginMatrices.emplace_back(transform); - parent_name_index = skinData->getBoneNameIndex(parent_name); - } - else if (parent_name_index < static_cast(skinData->skinBoneNames.size())) - { - skinData->skinBoneOriginMatrices[parent_name_index] = transform; - } - - // set root bone index - if (skinData->rootBoneIndex < 0) - skinData->rootBoneIndex = parent_name_index; - - if (!val.HasMember(CHILDREN)) - return; - - const rapidjson::Value& children = val[CHILDREN]; - for (rapidjson::SizeType i = 0, size = children.Size(); i < size; ++i) - { - // get child bone name - const rapidjson::Value& child = children[i]; - - std::string child_name = child[ID].GetString(); - int child_name_index = skinData->getSkinBoneNameIndex(child_name); - if (child_name_index < 0) - { - skinData->addNodeBoneNames(child_name); - child_name_index = skinData->getBoneNameIndex(child_name); - } - - map[parent_name_index].emplace_back(child_name_index); - - getChildMap(map, skinData, child); - } -} - -Bundle3D* Bundle3D::createBundle() -{ - auto bundle = new Bundle3D(); - return bundle; -} - -void Bundle3D::destroyBundle(Bundle3D* bundle) -{ - delete bundle; -} - -void Bundle3D::clear() -{ - if (_isBinary) - { - _binaryBuffer.clear(); - AX_SAFE_DELETE_ARRAY(_references); - } - else - { - _jsonBuffer.clear(); - } -} - -bool Bundle3D::load(std::string_view path) -{ - if (path.empty()) - return false; - - if (_path == path) - return true; - - getModelRelativePath(path); - - bool ret = false; - std::string ext = FileUtils::getPathExtension(path); - if (ext == ".c3t") - { - _isBinary = false; - ret = loadJson(path); - } - else if (ext == ".c3b") - { - _isBinary = true; - ret = loadBinary(path); - } - else - { - AXLOGW("warning: {} is invalid file format", path.data()); - } - - ret ? (_path = path) : (_path = ""); - - return ret; -} - -bool Bundle3D::loadObj(MeshDatas& meshdatas, - MaterialDatas& materialdatas, - NodeDatas& nodedatas, - std::string_view fullPath, - const char* mtl_basepath) -{ - meshdatas.resetData(); - materialdatas.resetData(); - nodedatas.resetData(); - - std::string mtlPath = ""; - if (mtl_basepath) - mtlPath = mtl_basepath; - else - mtlPath = fullPath.substr(0, fullPath.find_last_of("\\/") + 1); - - std::vector shapes; - std::vector materials; - auto ret = tinyobj::LoadObj(shapes, materials, fullPath.data(), mtlPath.c_str()); - if (ret.empty()) - { - // fill data - // convert material - int i = 0; - char buf[20]; - std::string dir; - auto last = fullPath.rfind('/'); - if (last != std::string::npos) - dir = fullPath.substr(0, last + 1); - for (auto&& material : materials) - { - NMaterialData materialdata; - - NTextureData tex; - tex.filename = material.diffuse_texname.empty() ? material.diffuse_texname : dir + material.diffuse_texname; - tex.type = NTextureData::Usage::Diffuse; - tex.wrapS = backend::SamplerAddressMode::CLAMP_TO_EDGE; - tex.wrapT = backend::SamplerAddressMode::CLAMP_TO_EDGE; - - auto dataId = fmt::format_to_z(buf, "{}", ++i); - materialdata.textures.emplace_back(tex); - materialdata.id = dataId; - material.name = dataId; - materialdatas.materials.emplace_back(materialdata); - } - - // convert mesh - i = 0; - for (auto&& shape : shapes) - { - auto mesh = shape.mesh; - MeshData* meshdata = new MeshData(); - MeshVertexAttrib attrib; - attrib.type = parseGLDataType("GL_FLOAT", 3); - - if (mesh.positions.size()) - { - attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; - meshdata->attribs.emplace_back(attrib); - } - bool hasnormal = false, hastex = false; - if (mesh.normals.size()) - { - hasnormal = true; - attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; - meshdata->attribs.emplace_back(attrib); - } - if (mesh.texcoords.size()) - { - hastex = true; - attrib.type = parseGLDataType("GL_FLOAT", 2); - attrib.vertexAttrib = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; - meshdata->attribs.emplace_back(attrib); - } - - auto vertexNum = mesh.positions.size() / 3; - for (unsigned int k = 0; k < vertexNum; ++k) - { - meshdata->vertex.emplace_back(mesh.positions[k * 3]); - meshdata->vertex.emplace_back(mesh.positions[k * 3 + 1]); - meshdata->vertex.emplace_back(mesh.positions[k * 3 + 2]); - - if (hasnormal) - { - meshdata->vertex.emplace_back(mesh.normals[k * 3]); - meshdata->vertex.emplace_back(mesh.normals[k * 3 + 1]); - meshdata->vertex.emplace_back(mesh.normals[k * 3 + 2]); - } - - if (hastex) - { - meshdata->vertex.emplace_back(mesh.texcoords[k * 2]); - meshdata->vertex.emplace_back(mesh.texcoords[k * 2 + 1]); - } - } - - // split into submesh according to material - std::map subMeshMap; - for (size_t k = 0, size = mesh.material_ids.size(); k < size; ++k) - { - int id = mesh.material_ids[k]; - size_t idx = k * 3; - subMeshMap[id].emplace_back(mesh.indices[idx]); - subMeshMap[id].emplace_back(mesh.indices[idx + 1]); - subMeshMap[id].emplace_back(mesh.indices[idx + 2]); - } - - auto node = new NodeData(); - node->id = shape.name; - for (auto&& submesh : subMeshMap) - { - auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(submesh.second)); - meshdata->subMeshAABB.emplace_back( - calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); - auto meshId = fmt::format_to_z(buf, "{}", ++i); - meshdata->subMeshIds.emplace_back(meshId); - - auto modelnode = new ModelData(); - modelnode->materialId = submesh.first == -1 ? "" : materials[submesh.first].name; - modelnode->subMeshId = meshId; - node->modelNodeDatas.emplace_back(modelnode); - } - nodedatas.nodes.emplace_back(node); - meshdatas.meshDatas.emplace_back(meshdata); - } - - return true; - } - AXLOGW("warning: load {} file error: {}", fullPath, ret); - return false; -} - -bool Bundle3D::loadSkinData(std::string_view /*id*/, SkinData* skindata) -{ - skindata->resetData(); - - if (_isBinary) - { - return loadSkinDataBinary(skindata); - } - else - { - return loadSkinDataJson(skindata); - } -} - -bool Bundle3D::loadAnimationData(std::string_view id, Animation3DData* animationdata) -{ - animationdata->resetData(); - - if (_isBinary) - { - return loadAnimationDataBinary(id, animationdata); - } - else - { - return loadAnimationDataJson(id, animationdata); - } -} - -// since 3.3, to support reskin -bool Bundle3D::loadMeshDatas(MeshDatas& meshdatas) -{ - meshdatas.resetData(); - if (_isBinary) - { - if (_version == "0.1" || _version == "0.2") - { - return loadMeshDatasBinary_0_1(meshdatas); - } - else - { - return loadMeshDatasBinary(meshdatas); - } - } - else - { - if (_version == "1.2" || _version == "0.2") - { - return loadMeshDataJson_0_1(meshdatas); - } - else - { - return loadMeshDatasJson(meshdatas); - } - } - return true; -} -bool Bundle3D::loadMeshDatasBinary(MeshDatas& meshdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MESH)) - return false; - unsigned int meshSize = 0; - if (_binaryReader.read(&meshSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - return false; - } - MeshData* meshData = nullptr; - for (unsigned int i = 0; i < meshSize; ++i) - { - unsigned int attribSize = 0; - // read mesh data - if (_binaryReader.read(&attribSize, 4, 1) != 1 || attribSize < 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - goto FAILED; - } - meshData = new MeshData(); - meshData->attribCount = attribSize; - meshData->attribs.resize(meshData->attribCount); - for (ssize_t j = 0; j < meshData->attribCount; ++j) - { - std::string attribute = ""; - unsigned int vSize; - if (_binaryReader.read(&vSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: usage or size '{}'.", _path); - goto FAILED; - } - std::string type = _binaryReader.readString(); - attribute = _binaryReader.readString(); - meshData->attribs[j].type = parseGLDataType(type, vSize); - meshData->attribs[j].vertexAttrib = parseGLProgramAttribute(attribute); - } - unsigned int vertexSizeInFloat = 0; - // Read vertex data - if (_binaryReader.read(&vertexSizeInFloat, 4, 1) != 1 || vertexSizeInFloat == 0) - { - AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); - goto FAILED; - } - - meshData->vertex.resize(vertexSizeInFloat); - if (_binaryReader.read(&meshData->vertex[0], 4, vertexSizeInFloat) != vertexSizeInFloat) - { - AXLOGW("warning: Failed to read meshdata: vertex element '{}'.", _path); - goto FAILED; - } - - // Read index data - unsigned int meshPartCount = 1; - _binaryReader.read(&meshPartCount, 4, 1); - - for (unsigned int k = 0; k < meshPartCount; ++k) - { - IndexArray indexArray{}; - std::string meshPartid = _binaryReader.readString(); - meshData->subMeshIds.emplace_back(meshPartid); - unsigned int nIndexCount; - if (_binaryReader.read(&nIndexCount, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: nIndexCount '{}'.", _path); - goto FAILED; - } - indexArray.resize(nIndexCount); - if (_binaryReader.read(indexArray.data(), 2, nIndexCount) != nIndexCount) - { - AXLOGW("warning: Failed to read meshdata: indices '{}'.", _path); - goto FAILED; - } - auto& storedIndices = meshData->subMeshIndices.emplace_back(std::move(indexArray)); - meshData->numIndex = (int)meshData->subMeshIndices.size(); - // meshData->subMeshAABB.emplace_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), - // indexArray)); - if (_version != "0.3" && _version != "0.4" && _version != "0.5") - { - // read mesh aabb - float aabb[6]; - if (_binaryReader.read(aabb, 4, 6) != 6) - { - AXLOGW("warning: Failed to read meshdata: aabb '{}'.", _path); - goto FAILED; - } - meshData->subMeshAABB.emplace_back(AABB(Vec3(aabb[0], aabb[1], aabb[2]), Vec3(aabb[3], aabb[4], aabb[5]))); - } - else - { - meshData->subMeshAABB.emplace_back( - calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); - } - } - meshdatas.meshDatas.emplace_back(meshData); - } - return true; - -FAILED: -{ - AX_SAFE_DELETE(meshData); - for (auto&& meshdata : meshdatas.meshDatas) - { - delete meshdata; - } - meshdatas.meshDatas.clear(); - return false; -} -} -bool Bundle3D::loadMeshDatasBinary_0_1(MeshDatas& meshdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MESH)) - return false; - - meshdatas.resetData(); - - MeshData* meshdata = new MeshData(); - - // read mesh data - unsigned int attribSize = 0; - if (_binaryReader.read(&attribSize, 4, 1) != 1 || attribSize < 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - enum - { - VERTEX_ATTRIB_POSITION, - VERTEX_ATTRIB_COLOR, - VERTEX_ATTRIB_TEX_COORD, - VERTEX_ATTRIB_NORMAL, - VERTEX_ATTRIB_BLEND_WEIGHT, - VERTEX_ATTRIB_BLEND_INDEX, - - VERTEX_ATTRIB_MAX, - - // backward compatibility - VERTEX_ATTRIB_TEX_COORDS = VERTEX_ATTRIB_TEX_COORD, - }; - for (unsigned int i = 0; i < attribSize; ++i) - { - unsigned int vUsage, vSize; - shaderinfos::VertexKey usage; - if (_binaryReader.read(&vUsage, 4, 1) != 1 || _binaryReader.read(&vSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: usage or size '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - MeshVertexAttrib meshVertexAttribute; - meshVertexAttribute.type = parseGLDataType("GL_FLOAT", vSize); - if (vUsage == VERTEX_ATTRIB_NORMAL) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; - } - else if (vUsage == VERTEX_ATTRIB_BLEND_WEIGHT) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; - } - else if (vUsage == VERTEX_ATTRIB_BLEND_INDEX) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; - } - else if (vUsage == VERTEX_ATTRIB_POSITION) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; - } - else if (vUsage == VERTEX_ATTRIB_TEX_COORD) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; - } - else - { - AXASSERT(false, "invalidate usage value"); - } - meshVertexAttribute.vertexAttrib = usage; - - meshdata->attribs.emplace_back(meshVertexAttribute); - } - - // Read vertex data - if (_binaryReader.read(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0) - { - AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - meshdata->vertex.resize(meshdata->vertexSizeInFloat); - if (_binaryReader.read(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat) - { - AXLOGW("warning: Failed to read meshdata: vertex element '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - // Read index data - unsigned int meshPartCount = 1; - for (unsigned int i = 0; i < meshPartCount; ++i) - { - unsigned int nIndexCount; - if (_binaryReader.read(&nIndexCount, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: nIndexCount '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - IndexArray indices{}; - indices.resize(nIndexCount); - if (_binaryReader.read(indices.data(), 2, nIndexCount) != nIndexCount) - { - AXLOGW("warning: Failed to read meshdata: indices '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); - meshdata->subMeshAABB.emplace_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); - } - - meshdatas.meshDatas.emplace_back(meshdata); - return true; -} - -bool Bundle3D::loadMeshDatasBinary_0_2(MeshDatas& meshdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MESH)) - return false; - - meshdatas.resetData(); - - MeshData* meshdata = new MeshData(); - - // read mesh data - unsigned int attribSize = 0; - if (_binaryReader.read(&attribSize, 4, 1) != 1 || attribSize < 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - enum - { - VERTEX_ATTRIB_POSITION, - VERTEX_ATTRIB_COLOR, - VERTEX_ATTRIB_TEX_COORD, - VERTEX_ATTRIB_NORMAL, - VERTEX_ATTRIB_BLEND_WEIGHT, - VERTEX_ATTRIB_BLEND_INDEX, - - VERTEX_ATTRIB_MAX, - - // backward compatibility - VERTEX_ATTRIB_TEX_COORDS = VERTEX_ATTRIB_TEX_COORD, - }; - for (unsigned int i = 0; i < attribSize; ++i) - { - unsigned int vUsage, vSize; - shaderinfos::VertexKey usage = shaderinfos::VertexKey::VERTEX_ATTRIB_ERROR; - if (_binaryReader.read(&vUsage, 4, 1) != 1 || _binaryReader.read(&vSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: usage or size '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - MeshVertexAttrib meshVertexAttribute; - meshVertexAttribute.type = parseGLDataType("GL_FLOAT", vSize); - if (vUsage == VERTEX_ATTRIB_NORMAL) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; - } - else if (vUsage == VERTEX_ATTRIB_BLEND_WEIGHT) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; - } - else if (vUsage == VERTEX_ATTRIB_BLEND_INDEX) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; - } - else if (vUsage == VERTEX_ATTRIB_POSITION) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; - } - else if (vUsage == VERTEX_ATTRIB_TEX_COORD) - { - usage = shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; - } - meshVertexAttribute.vertexAttrib = usage; - - meshdata->attribs.emplace_back(meshVertexAttribute); - } - - // Read vertex data - if (_binaryReader.read(&meshdata->vertexSizeInFloat, 4, 1) != 1 || meshdata->vertexSizeInFloat == 0) - { - AXLOGW("warning: Failed to read meshdata: vertexSizeInFloat '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - meshdata->vertex.resize(meshdata->vertexSizeInFloat); - if (_binaryReader.read(&meshdata->vertex[0], 4, meshdata->vertexSizeInFloat) != meshdata->vertexSizeInFloat) - { - AXLOGW("warning: Failed to read meshdata: vertex element '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - // read submesh - unsigned int submeshCount; - if (_binaryReader.read(&submeshCount, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: submeshCount '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - for (unsigned int i = 0; i < submeshCount; ++i) - { - unsigned int nIndexCount; - if (_binaryReader.read(&nIndexCount, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: nIndexCount '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - IndexArray indices{}; /* TODO: _version == 1.3 use U_INT?*/ - indices.resize(nIndexCount); - if (_binaryReader.read(indices.data(), 2, nIndexCount) != nIndexCount) - { - AXLOGW("warning: Failed to read meshdata: indices '{}'.", _path); - AX_SAFE_DELETE(meshdata); - return false; - } - - auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); - meshdata->subMeshAABB.emplace_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); - } - - meshdatas.meshDatas.emplace_back(meshdata); - - return true; -} -bool Bundle3D::loadMeshDatasJson(MeshDatas& meshdatas) -{ - const rapidjson::Value& mesh_data_array = _jsonReader[MESHES]; - for (rapidjson::SizeType index = 0, mesh_data_array_size = mesh_data_array.Size(); index < mesh_data_array_size; - ++index) - { - MeshData* meshData = new MeshData(); - const rapidjson::Value& mesh_data = mesh_data_array[index]; - // mesh_vertex_attribute - const rapidjson::Value& mesh_vertex_attribute = mesh_data[ATTRIBUTES]; - MeshVertexAttrib tempAttrib; - meshData->attribCount = mesh_vertex_attribute.Size(); - meshData->attribs.resize(meshData->attribCount); - for (rapidjson::SizeType i = 0, mesh_vertex_attribute_size = mesh_vertex_attribute.Size(); - i < mesh_vertex_attribute_size; ++i) - { - const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[i]; - - int size = mesh_vertex_attribute_val[ATTRIBUTESIZE].GetInt(); - std::string type = mesh_vertex_attribute_val[TYPE].GetString(); - std::string attribute = mesh_vertex_attribute_val[ATTRIBUTE].GetString(); - - tempAttrib.type = parseGLDataType(type, size); - tempAttrib.vertexAttrib = parseGLProgramAttribute(attribute); - meshData->attribs[i] = tempAttrib; - } - // mesh vertices - //////////////////////////////////////////////////////////////////////////////////////////////// - const rapidjson::Value& mesh_data_vertex_array = mesh_data[VERTICES]; - auto mesh_data_vertex_array_size = mesh_data_vertex_array.Size(); - meshData->vertexSizeInFloat = mesh_data_vertex_array_size; - for (rapidjson::SizeType i = 0; i < mesh_data_vertex_array_size; ++i) - { - meshData->vertex.emplace_back(mesh_data_vertex_array[i].GetFloat()); - } - // mesh part - //////////////////////////////////////////////////////////////////////////////////////////////// - const rapidjson::Value& mesh_part_array = mesh_data[PARTS]; - for (rapidjson::SizeType i = 0, mesh_part_array_size = mesh_part_array.Size(); i < mesh_part_array_size; ++i) - { - IndexArray indexArray{}; - const rapidjson::Value& mesh_part = mesh_part_array[i]; - meshData->subMeshIds.emplace_back(mesh_part[ID].GetString()); - // index_number - const rapidjson::Value& indices_val_array = mesh_part[INDICES]; - for (rapidjson::SizeType j = 0, indices_val_array_size = indices_val_array.Size(); - j < indices_val_array_size; ++j) - indexArray.emplace_back((unsigned short)indices_val_array[j].GetUint()); - - auto& storedIndices = meshData->subMeshIndices.emplace_back(std::move(indexArray)); - meshData->numIndex = (int)meshData->subMeshIndices.size(); - - if (mesh_data.HasMember(AABBS)) - { - const rapidjson::Value& mesh_part_aabb = mesh_part[AABBS]; - if (mesh_part.HasMember(AABBS) && mesh_part_aabb.Size() == 6) - { - Vec3 min(mesh_part_aabb[(rapidjson::SizeType)0].GetFloat(), - mesh_part_aabb[(rapidjson::SizeType)1].GetFloat(), - mesh_part_aabb[(rapidjson::SizeType)2].GetFloat()); - Vec3 max(mesh_part_aabb[(rapidjson::SizeType)3].GetFloat(), - mesh_part_aabb[(rapidjson::SizeType)4].GetFloat(), - mesh_part_aabb[(rapidjson::SizeType)5].GetFloat()); - meshData->subMeshAABB.emplace_back(AABB(min, max)); - } - else - { - meshData->subMeshAABB.emplace_back( - calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); - } - } - else - { - meshData->subMeshAABB.emplace_back(calculateAABB(meshData->vertex, meshData->getPerVertexSize(), storedIndices)); - } - } - meshdatas.meshDatas.emplace_back(meshData); - } - return true; -} -bool Bundle3D::loadNodes(NodeDatas& nodedatas) -{ - if (_version == "0.1" || _version == "1.2" || _version == "0.2") - { - SkinData skinData; - if (!loadSkinData("", &skinData)) - { - auto node = new NodeData(); - auto modelnode = new ModelData(); - modelnode->materialId = ""; - modelnode->subMeshId = ""; - node->modelNodeDatas.emplace_back(modelnode); - nodedatas.nodes.emplace_back(node); - return true; - } - - auto nodeDatas = new NodeData*[skinData.skinBoneNames.size() + skinData.nodeBoneNames.size()]; - int index = 0; - size_t i; - auto skinBoneSize = skinData.skinBoneNames.size(); - auto nodeBoneSize = skinData.nodeBoneNames.size(); - for (i = 0; i < skinBoneSize; ++i) - { - nodeDatas[index] = new NodeData(); - nodeDatas[index]->id = skinData.skinBoneNames[i]; - nodeDatas[index]->transform = skinData.skinBoneOriginMatrices[i]; - ++index; - } - for (i = 0; i < nodeBoneSize; ++i) - { - nodeDatas[index] = new NodeData(); - nodeDatas[index]->id = skinData.nodeBoneNames[i]; - nodeDatas[index]->transform = skinData.nodeBoneOriginMatrices[i]; - ++index; - } - for (const auto& it : skinData.boneChild) - { - const auto& children = it.second; - auto parent = nodeDatas[it.first]; - for (const auto& child : children) - { - parent->children.emplace_back(nodeDatas[child]); - } - } - nodedatas.skeleton.emplace_back(nodeDatas[skinData.rootBoneIndex]); - auto node = new NodeData(); - auto modelnode = new ModelData(); - modelnode->materialId = ""; - modelnode->subMeshId = ""; - modelnode->bones = skinData.skinBoneNames; - modelnode->invBindPose = skinData.inverseBindPoseMatrices; - node->modelNodeDatas.emplace_back(modelnode); - nodedatas.nodes.emplace_back(node); - delete[] nodeDatas; - } - else - { - if (_isBinary) - { - loadNodesBinary(nodedatas); - } - else - { - loadNodesJson(nodedatas); - } - } - return true; -} -bool Bundle3D::loadMaterials(MaterialDatas& materialdatas) -{ - materialdatas.resetData(); - if (_isBinary) - { - if (_version == "0.1") - { - return loadMaterialsBinary_0_1(materialdatas); - } - else if (_version == "0.2") - { - return loadMaterialsBinary_0_2(materialdatas); - } - else - { - return loadMaterialsBinary(materialdatas); - } - } - else - { - if (_version == "1.2") - { - return loadMaterialDataJson_0_1(materialdatas); - } - else if (_version == "0.2") - { - return loadMaterialDataJson_0_2(materialdatas); - } - else - { - return loadMaterialsJson(materialdatas); - } - } - return true; -} -bool Bundle3D::loadMaterialsBinary(MaterialDatas& materialdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) - return false; - unsigned int materialnum = 1; - _binaryReader.read(&materialnum, 4, 1); - for (unsigned int i = 0; i < materialnum; ++i) - { - NMaterialData materialData; - materialData.id = _binaryReader.readString(); - - // skip: diffuse(3), ambient(3), emissive(3), opacity(1), specular(3), shininess(1) - float data[14]; - _binaryReader.read(&data, sizeof(float), 14); - - unsigned int textureNum = 1; - _binaryReader.read(&textureNum, 4, 1); - for (unsigned int j = 0; j < textureNum; ++j) - { - NTextureData textureData; - textureData.id = _binaryReader.readString(); - if (textureData.id.empty()) - { - AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", textureData.id); - return false; - } - std::string texturePath = _binaryReader.readString(); - if (texturePath.empty()) - { - AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); - return false; - } - - textureData.filename = texturePath.empty() ? texturePath : _modelPath + texturePath; - float uvdata[4]; - _binaryReader.read(&uvdata, sizeof(float), 4); - textureData.type = parseGLTextureType(_binaryReader.readString()); - textureData.wrapS = parseSamplerAddressMode(_binaryReader.readString()); - textureData.wrapT = parseSamplerAddressMode(_binaryReader.readString()); - materialData.textures.emplace_back(textureData); - } - materialdatas.materials.emplace_back(materialData); - } - return true; -} -bool Bundle3D::loadMaterialsBinary_0_1(MaterialDatas& materialdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) - return false; - - NMaterialData materialData; - - std::string texturePath = _binaryReader.readString(); - if (texturePath.empty()) - { - AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); - return false; - } - - NTextureData textureData; - textureData.filename = texturePath.empty() ? texturePath : _modelPath + texturePath; - textureData.type = NTextureData::Usage::Diffuse; - textureData.id = ""; - materialData.textures.emplace_back(textureData); - materialdatas.materials.emplace_back(materialData); - return true; -} - -bool Bundle3D::loadMaterialsBinary_0_2(MaterialDatas& materialdatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_MATERIAL)) - return false; - - unsigned int materialnum = 1; - _binaryReader.read(&materialnum, 4, 1); - - for (unsigned int i = 0; i < materialnum; ++i) - { - NMaterialData materialData; - - std::string texturePath = _binaryReader.readString(); - if (texturePath.empty()) - { - AXLOGW("warning: Failed to read Materialdata: texturePath is empty '{}'.", _path); - return true; - } - - NTextureData textureData; - textureData.filename = texturePath.empty() ? texturePath : _modelPath + texturePath; - textureData.type = NTextureData::Usage::Diffuse; - textureData.id = ""; - materialData.textures.emplace_back(textureData); - materialdatas.materials.emplace_back(materialData); - } - return true; -} - -bool loadMeshDataJson(MeshData* /*meshdata*/) -{ - return true; -} - -bool loadMeshDataJson_0_1(MeshData* /*meshdata*/) -{ - return true; -} - -bool loadMeshDataJson_0_2(MeshData* /*meshdata*/) -{ - return true; -} - -bool Bundle3D::loadMaterialsJson(MaterialDatas& materialdatas) -{ - if (!_jsonReader.HasMember(MATERIALS)) - return false; - const rapidjson::Value& material_array = _jsonReader[MATERIALS]; - for (rapidjson::SizeType i = 0; i < material_array.Size(); ++i) - { - NMaterialData materialData; - const rapidjson::Value& material_val = material_array[i]; - materialData.id = material_val[ID].GetString(); - if (material_val.HasMember(TEXTURES)) - { - const rapidjson::Value& texture_array = material_val[TEXTURES]; - for (rapidjson::SizeType j = 0; j < texture_array.Size(); ++j) - { - NTextureData textureData; - const rapidjson::Value& texture_val = texture_array[j]; - std::string filename = texture_val[FILENAME].GetString(); - textureData.filename = filename.empty() ? filename : _modelPath + filename; - textureData.type = parseGLTextureType(texture_val["type"].GetString()); - textureData.wrapS = parseSamplerAddressMode(texture_val["wrapModeU"].GetString()); - textureData.wrapT = parseSamplerAddressMode(texture_val["wrapModeV"].GetString()); - materialData.textures.emplace_back(textureData); - } - } - materialdatas.materials.emplace_back(materialData); - } - return true; -} -bool Bundle3D::loadJson(std::string_view path) -{ - clear(); - - _jsonBuffer = FileUtils::getInstance()->getStringFromFile(path); - - if (_jsonReader.ParseInsitu<0>((char*)_jsonBuffer.c_str()).HasParseError()) - { - clear(); - AXLOGW("Parse json failed in Bundle3D::loadJson function"); - return false; - } - - const rapidjson::Value& mash_data_array = _jsonReader[VERSION]; - if (mash_data_array.IsArray()) // Compatible with the old version - _version = "1.2"; - else - _version = mash_data_array.GetString(); - - return true; -} - -bool Bundle3D::loadBinary(std::string_view path) -{ - clear(); - - // get file data - _binaryBuffer.clear(); - _binaryBuffer = FileUtils::getInstance()->getDataFromFile(path); - if (_binaryBuffer.isNull()) - { - clear(); - AXLOGW("warning: Failed to read file: {}", path); - return false; - } - - // Initialise bundle reader - _binaryReader.init((char*)_binaryBuffer.getBytes(), _binaryBuffer.getSize()); - - // Read identifier info - char identifier[] = {'C', '3', 'B', '\0'}; - char sig[4]; - if (_binaryReader.read(sig, 1, 4) != 4 || memcmp(sig, identifier, 4) != 0) - { - clear(); - AXLOGW("warning: Invalid identifier: {}", path); - return false; - } - - // Read version - unsigned char ver[2]; - if (_binaryReader.read(ver, 1, 2) != 2) - { - AXLOGW("warning: Failed to read version:"); - return false; - } - - char buf[20]; - _version = fmt::format_to_z(buf, "{}.{}", ver[0], ver[1]); - - // Read ref table size - if (_binaryReader.read(&_referenceCount, 4, 1) != 1) - { - clear(); - AXLOGW("warning: Failed to read ref table size '{}'.", path); - return false; - } - - // Read all refs - AX_SAFE_DELETE_ARRAY(_references); - _references = new Reference[_referenceCount]; - for (unsigned int i = 0; i < _referenceCount; ++i) - { - if ((_references[i].id = _binaryReader.readString()).empty() || - _binaryReader.read(&_references[i].type, 4, 1) != 1 || - _binaryReader.read(&_references[i].offset, 4, 1) != 1) - { - clear(); - AXLOGW("warning: Failed to read ref number {} for bundle '{}'.", i, path); - AX_SAFE_DELETE_ARRAY(_references); - return false; - } - } - - return true; -} - -bool Bundle3D::loadMeshDataJson_0_1(MeshDatas& meshdatas) -{ - const rapidjson::Value& mesh_data_array = _jsonReader[MESH]; - MeshData* meshdata = new MeshData(); - const rapidjson::Value& mesh_data_val = mesh_data_array[(rapidjson::SizeType)0]; - - const rapidjson::Value& mesh_data_body_array = mesh_data_val[DEFAULTPART]; - - const rapidjson::Value& mesh_data_body_array_0 = mesh_data_body_array[(rapidjson::SizeType)0]; - - // mesh_vertex_attribute - const rapidjson::Value& mesh_vertex_attribute = mesh_data_val[ATTRIBUTES]; - meshdata->attribCount = mesh_vertex_attribute.Size(); - meshdata->attribs.resize(meshdata->attribCount); - for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); ++i) - { - const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[i]; - - int size = mesh_vertex_attribute_val[ATTRIBUTESIZE].GetUint(); - meshdata->attribs[i].type = parseGLDataType(mesh_vertex_attribute_val[TYPE].GetString(), size); - meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[ATTRIBUTE].GetString()); - } - - // vertices - meshdata->vertexSizeInFloat = mesh_data_body_array_0[VERTEXSIZE].GetInt(); - meshdata->vertex.resize(meshdata->vertexSizeInFloat); - - const rapidjson::Value& mesh_data_body_vertices = mesh_data_body_array_0[VERTICES]; - for (rapidjson::SizeType i = 0; i < mesh_data_body_vertices.Size(); ++i) - meshdata->vertex[i] = mesh_data_body_vertices[i].GetFloat(); - - // index_number - unsigned int indexnum = mesh_data_body_array_0[INDEXNUM].GetUint(); - - // indices - IndexArray indices{}; - indices.resize(indexnum); - - const rapidjson::Value& indices_val_array = mesh_data_body_array_0[INDICES]; - for (rapidjson::SizeType i = 0; i < indices_val_array.Size(); ++i) - indices.at(i) = (unsigned short)indices_val_array[i].GetUint(); - - auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); - meshdata->subMeshAABB.emplace_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); - meshdatas.meshDatas.emplace_back(meshdata); - return true; -} - -bool Bundle3D::loadMeshDataJson_0_2(MeshDatas& meshdatas) -{ - MeshData* meshdata = new MeshData(); - const rapidjson::Value& mesh_array = _jsonReader[MESH]; - const rapidjson::Value& mesh_array_0 = mesh_array[(rapidjson::SizeType)0]; - - // mesh_vertex_attribute - const rapidjson::Value& mesh_vertex_attribute = mesh_array_0[ATTRIBUTES]; - meshdata->attribCount = mesh_vertex_attribute.Size(); - meshdata->attribs.resize(meshdata->attribCount); - for (rapidjson::SizeType i = 0; i < mesh_vertex_attribute.Size(); ++i) - { - const rapidjson::Value& mesh_vertex_attribute_val = mesh_vertex_attribute[i]; - - auto size = mesh_vertex_attribute_val[ATTRIBUTESIZE].GetUint(); - meshdata->attribs[i].type = parseGLDataType(mesh_vertex_attribute_val[TYPE].GetString(), size); - meshdata->attribs[i].vertexAttrib = parseGLProgramAttribute(mesh_vertex_attribute_val[ATTRIBUTE].GetString()); - } - - // vertices - const rapidjson::Value& mesh_data_vertex = mesh_array_0[VERTEX]; - const rapidjson::Value& mesh_data_vertex_0 = mesh_data_vertex[(rapidjson::SizeType)0]; - - meshdata->vertexSizeInFloat = mesh_data_vertex_0[VERTEXSIZE].GetInt(); - meshdata->vertex.resize(meshdata->vertexSizeInFloat); - - const rapidjson::Value& mesh_data_body_vertices = mesh_data_vertex_0[VERTICES]; - for (rapidjson::SizeType i = 0; i < mesh_data_body_vertices.Size(); ++i) - meshdata->vertex[i] = mesh_data_body_vertices[i].GetFloat(); - - // submesh - const rapidjson::Value& mesh_submesh_array = mesh_array_0[SUBMESH]; - for (rapidjson::SizeType i = 0; i < mesh_submesh_array.Size(); ++i) - { - const rapidjson::Value& mesh_submesh_val = mesh_submesh_array[i]; - // std::string id = mesh_submesh_val[ID].GetString(); - - // index_number - unsigned int indexnum = mesh_submesh_val[INDEXNUM].GetUint(); - - // indices - IndexArray indices{}; - indices.resize(indexnum); - - const rapidjson::Value& indices_val_array = mesh_submesh_val[INDICES]; - for (rapidjson::SizeType j = 0; j < indices_val_array.Size(); ++j) - indices.at(j) = (unsigned short)indices_val_array[j].GetUint(); - - auto& storedIndices = meshdata->subMeshIndices.emplace_back(std::move(indices)); - meshdata->subMeshAABB.emplace_back(calculateAABB(meshdata->vertex, meshdata->getPerVertexSize(), storedIndices)); - } - meshdatas.meshDatas.emplace_back(meshdata); - return true; -} - -bool Bundle3D::loadSkinDataJson(SkinData* skindata) -{ - if (!_jsonReader.HasMember(SKIN)) - return false; - - const rapidjson::Value& skin_data_array = _jsonReader[SKIN]; - - AXASSERT(skin_data_array.IsArray(), "skin data is not an array"); - const rapidjson::Value& skin_data_array_val_0 = skin_data_array[(rapidjson::SizeType)0]; - - if (!skin_data_array_val_0.HasMember(BONES)) - return false; - - const rapidjson::Value& skin_data_bones = skin_data_array_val_0[BONES]; - for (rapidjson::SizeType i = 0; i < skin_data_bones.Size(); ++i) - { - const rapidjson::Value& skin_data_bone = skin_data_bones[i]; - std::string name = skin_data_bone[NODE].GetString(); - skindata->addSkinBoneNames(name); - - Mat4 mat_bind_pos; - const rapidjson::Value& bind_pos = skin_data_bone[BINDSHAPE]; - for (rapidjson::SizeType j = 0; j < bind_pos.Size(); ++j) - { - mat_bind_pos.m[j] = bind_pos[j].GetFloat(); - } - skindata->inverseBindPoseMatrices.emplace_back(mat_bind_pos); - } - - // set root bone information - const rapidjson::Value& skin_data_1 = skin_data_array[1]; - - // parent and child relationship map - skindata->skinBoneOriginMatrices.resize(skindata->skinBoneNames.size()); - getChildMap(skindata->boneChild, skindata, skin_data_1); - return true; -} - -bool Bundle3D::loadSkinDataBinary(SkinData* skindata) -{ - if (!seekToFirstType(BUNDLE_TYPE_MESHSKIN)) - return false; - - std::string boneName = _binaryReader.readString(); - - // transform - float bindShape[16]; - if (!_binaryReader.readMatrix(bindShape)) - { - AXLOGW("warning: Failed to read SkinData: bindShape matrix '{}'.", _path); - return false; - } - - // bone count - unsigned int boneNum; - if (!_binaryReader.read(&boneNum)) - { - AXLOGW("warning: Failed to read SkinData: boneNum '{}'.", _path); - return false; - } - - // Fix bug: check if the bone number is 0. - if (boneNum == 0) - return false; - - // bone names and bind pos - float bindpos[16]; - for (unsigned int i = 0; i < boneNum; ++i) - { - std::string skinBoneName = _binaryReader.readString(); - skindata->skinBoneNames.emplace_back(skinBoneName); - if (!_binaryReader.readMatrix(bindpos)) - { - AXLOGW("warning: Failed to load SkinData: bindpos '{}'.", _path); - return false; - } - skindata->inverseBindPoseMatrices.emplace_back(bindpos); - } - - skindata->skinBoneOriginMatrices.resize(boneNum); - - boneName = _binaryReader.readString(); - - // bind shape - _binaryReader.readMatrix(bindShape); - int rootIndex = skindata->getSkinBoneNameIndex(boneName); - if (rootIndex < 0) - { - skindata->addNodeBoneNames(boneName); - rootIndex = skindata->getBoneNameIndex(boneName); - skindata->nodeBoneOriginMatrices.emplace_back(bindShape); - } - else - { - skindata->skinBoneOriginMatrices[rootIndex] = bindShape; - } - - // set root bone index - skindata->rootBoneIndex = rootIndex; - - // read parent and child relationship map - float transform[16]; - unsigned int linkNum; - _binaryReader.read(&linkNum); - for (unsigned int i = 0; i < linkNum; ++i) - { - std::string id = _binaryReader.readString(); - int index = skindata->getSkinBoneNameIndex(id); - - std::string parentid = _binaryReader.readString(); - - if (!_binaryReader.readMatrix(transform)) - { - AXLOGW("warning: Failed to load SkinData: transform '{}'.", _path); - return false; - } - - if (index < 0) - { - skindata->addNodeBoneNames(id); - index = skindata->getBoneNameIndex(id); - skindata->nodeBoneOriginMatrices.emplace_back(transform); - } - else - { - skindata->skinBoneOriginMatrices[index] = transform; - } - - int parentIndex = skindata->getSkinBoneNameIndex(parentid); - if (parentIndex < 0) - { - skindata->addNodeBoneNames(parentid); - parentIndex = skindata->getBoneNameIndex(parentid); - } - - skindata->boneChild[parentIndex].emplace_back(index); - } - - return true; -} - -bool Bundle3D::loadMaterialDataJson_0_1(MaterialDatas& materialdatas) -{ - if (!_jsonReader.HasMember(MATERIAL)) - return false; - NMaterialData materialData; - const rapidjson::Value& material_data_array = _jsonReader[MATERIAL]; - - if (material_data_array.Size() > 0) - { - const rapidjson::Value& material_data_array_0 = material_data_array[(rapidjson::SizeType)0]; - if (material_data_array_0.HasMember(BASE)) - { - const rapidjson::Value& material_data_base_array = material_data_array_0[BASE]; - const rapidjson::Value& material_data_base_array_0 = material_data_base_array[(rapidjson::SizeType)0]; - NTextureData textureData; - // set texture - std::string filename = material_data_base_array_0[FILENAME].GetString(); - textureData.filename = filename.empty() ? filename : _modelPath + filename; - textureData.type = NTextureData::Usage::Diffuse; - textureData.id = ""; - materialData.textures.emplace_back(textureData); - materialdatas.materials.emplace_back(materialData); - } - } - - return true; -} - -bool Bundle3D::loadMaterialDataJson_0_2(MaterialDatas& materialdatas) -{ - if (!_jsonReader.HasMember(MATERIAL)) - return false; - NMaterialData materialData; - const rapidjson::Value& material_array = _jsonReader[MATERIAL]; - - for (rapidjson::SizeType i = 0; i < material_array.Size(); ++i) - { - NTextureData textureData; - const rapidjson::Value& material_val = material_array[i]; - - // set texture - std::string filename = material_val[TEXTURES].GetString(); - textureData.filename = filename.empty() ? filename : _modelPath + filename; - textureData.type = NTextureData::Usage::Diffuse; - textureData.id = ""; - materialData.textures.emplace_back(textureData); - } - materialdatas.materials.emplace_back(materialData); - return true; -} - -bool loadMaterialDataJson(MaterialData* /*materialdata*/) -{ - return true; -} - -bool loadMaterialDataJson_0_1(MaterialData* /*materialdata*/) -{ - return true; -} - -bool loadMaterialDataJson_0_2(MaterialData* /*materialdata*/) -{ - return true; -} - -bool Bundle3D::loadAnimationDataJson(std::string_view id, Animation3DData* animationdata) -{ - std::string anim = ""; - if (_version == "1.2" || _version == "0.2") - anim = ANIMATION; - else - anim = ANIMATIONS; - - if (!_jsonReader.HasMember(anim.c_str())) - return false; - int the_index = -1; - const rapidjson::Value& animation_data_array = _jsonReader[anim.c_str()]; - - if (animation_data_array.Size() == 0) - return false; - - if (!id.empty()) - { - for (rapidjson::SizeType i = 0; i < animation_data_array.Size(); ++i) - { - if (animation_data_array[i][ID].GetString() == id) - { - the_index = static_cast(i); - } - } - if (the_index < 0) - return false; - } - else - { - the_index = 0; - } - - const rapidjson::Value& animation_data_array_val_0 = animation_data_array[(rapidjson::SizeType)the_index]; - - animationdata->_totalTime = animation_data_array_val_0[LENGTH].GetFloat(); - - const rapidjson::Value& bones = animation_data_array_val_0[BONES]; - for (rapidjson::SizeType i = 0; i < bones.Size(); ++i) - { - const rapidjson::Value& bone = bones[i]; - std::string bone_name = bone[BONEID].GetString(); - - if (bone.HasMember(KEYFRAMES)) - { - const rapidjson::Value& bone_keyframes = bone[KEYFRAMES]; - rapidjson::SizeType keyframe_size = bone_keyframes.Size(); - animationdata->_rotationKeys[bone_name].reserve(keyframe_size); - animationdata->_scaleKeys[bone_name].reserve(keyframe_size); - animationdata->_translationKeys[bone_name].reserve(keyframe_size); - - for (rapidjson::SizeType j = 0; j < keyframe_size; ++j) - { - const rapidjson::Value& bone_keyframe = bone_keyframes[j]; - - if (bone_keyframe.HasMember(TRANSLATION)) - { - const rapidjson::Value& bone_keyframe_translation = bone_keyframe[TRANSLATION]; - float keytime = bone_keyframe[KEYTIME].GetFloat(); - Vec3 val(bone_keyframe_translation[(rapidjson::SizeType)0].GetFloat(), - bone_keyframe_translation[1].GetFloat(), bone_keyframe_translation[2].GetFloat()); - animationdata->_translationKeys[bone_name].emplace_back(Animation3DData::Vec3Key(keytime, val)); - } - - if (bone_keyframe.HasMember(ROTATION)) - { - const rapidjson::Value& bone_keyframe_rotation = bone_keyframe[ROTATION]; - float keytime = bone_keyframe[KEYTIME].GetFloat(); - Quaternion val = Quaternion( - bone_keyframe_rotation[(rapidjson::SizeType)0].GetFloat(), bone_keyframe_rotation[1].GetFloat(), - bone_keyframe_rotation[2].GetFloat(), bone_keyframe_rotation[3].GetFloat()); - animationdata->_rotationKeys[bone_name].emplace_back(Animation3DData::QuatKey(keytime, val)); - } - - if (bone_keyframe.HasMember(SCALE)) - { - const rapidjson::Value& bone_keyframe_scale = bone_keyframe[SCALE]; - float keytime = bone_keyframe[KEYTIME].GetFloat(); - Vec3 val(bone_keyframe_scale[(rapidjson::SizeType)0].GetFloat(), bone_keyframe_scale[1].GetFloat(), - bone_keyframe_scale[2].GetFloat()); - animationdata->_scaleKeys[bone_name].emplace_back(Animation3DData::Vec3Key(keytime, val)); - } - } - } - } - - return true; -} - -bool Bundle3D::loadAnimationDataBinary(std::string_view id, Animation3DData* animationdata) -{ - - if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4") - { - if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS)) - return false; - } - else - { - // if id is not a null string, we need to add a suffix of "animation" for seeding. - std::string id_{id}; - if (!id.empty()) - id_.append("animation"); - - if (!seekToFirstType(BUNDLE_TYPE_ANIMATIONS, id_)) - return false; - } - - unsigned int animNum = 1; - if (_version == "0.3" || _version == "0.4") - { - if (!_binaryReader.read(&animNum)) - { - AXLOGW("warning: Failed to read AnimationData: animNum '{}'.", _path); - return false; - } - } - - bool has_found = false; - for (unsigned int k = 0; k < animNum; ++k) - { - animationdata->resetData(); - std::string animId = _binaryReader.readString(); - - if (!_binaryReader.read(&animationdata->_totalTime)) - { - AXLOGW("warning: Failed to read AnimationData: totalTime '{}'.", _path); - return false; - } - - unsigned int nodeAnimationNum; - if (!_binaryReader.read(&nodeAnimationNum)) - { - AXLOGW("warning: Failed to read AnimationData: animNum '{}'.", _path); - return false; - } - for (unsigned int i = 0; i < nodeAnimationNum; ++i) - { - std::string boneName = _binaryReader.readString(); - unsigned int keyframeNum; - if (!_binaryReader.read(&keyframeNum)) - { - AXLOGW("warning: Failed to read AnimationData: keyframeNum '{}'.", _path); - return false; - } - - animationdata->_rotationKeys[boneName].reserve(keyframeNum); - animationdata->_scaleKeys[boneName].reserve(keyframeNum); - animationdata->_translationKeys[boneName].reserve(keyframeNum); - - for (unsigned int j = 0; j < keyframeNum; ++j) - { - float keytime; - if (!_binaryReader.read(&keytime)) - { - AXLOGW("warning: Failed to read AnimationData: keytime '{}'.", _path); - return false; - } - - // transform flag - unsigned char transformFlag(0); - if (_version != "0.1" && _version != "0.2" && _version != "0.3") - { - if (!_binaryReader.read(&transformFlag)) - { - AXLOGW("warning: Failed to read AnimationData: transformFlag '{}'.", _path); - return false; - } - } - - // rotation - bool hasRotate = true; - if (_version != "0.1" && _version != "0.2" && _version != "0.3") - hasRotate = transformFlag & 0x01; - - if (hasRotate) - { - Quaternion rotate; - if (_binaryReader.read(&rotate, 4, 4) != 4) - { - AXLOGW("warning: Failed to read AnimationData: rotate '{}'.", _path); - return false; - } - animationdata->_rotationKeys[boneName].emplace_back(Animation3DData::QuatKey(keytime, rotate)); - } - - // scale - bool hasScale = true; - if (_version != "0.1" && _version != "0.2" && _version != "0.3") - hasScale = (transformFlag >> 1) & 0x01; - - if (hasScale) - { - Vec3 scale; - if (_binaryReader.read(&scale, 4, 3) != 3) - { - AXLOGW("warning: Failed to read AnimationData: scale '{}'.", _path); - return false; - } - animationdata->_scaleKeys[boneName].emplace_back(Animation3DData::Vec3Key(keytime, scale)); - } - - // translation - bool hasTranslation = true; - if (_version != "0.1" && _version != "0.2" && _version != "0.3") - hasTranslation = (transformFlag >> 2) & 0x01; - - if (hasTranslation) - { - Vec3 position; - if (_binaryReader.read(&position, 4, 3) != 3) - { - AXLOGW("warning: Failed to read AnimationData: position '{}'.", _path); - return false; - } - animationdata->_translationKeys[boneName].emplace_back(Animation3DData::Vec3Key(keytime, position)); - } - } - } - if (id == animId || id.empty()) - { - has_found = true; - break; - } - } - if (!has_found) - { - animationdata->resetData(); - return false; - } - return true; -} - -bool Bundle3D::loadNodesJson(NodeDatas& nodedatas) -{ - if (!_jsonReader.HasMember(NODES)) - return false; - const rapidjson::Value& nodes = _jsonReader[NODES]; - if (!nodes.IsArray()) - return false; - - // traverse the nodes again - for (rapidjson::SizeType i = 0; i < nodes.Size(); ++i) - { - const rapidjson::Value& jnode = nodes[i]; - std::string id = jnode[ID].GetString(); - NodeData* nodedata = parseNodesRecursivelyJson(jnode, nodes.Size() == 1); - - bool isSkeleton = jnode[SKELETON].GetBool(); - if (isSkeleton) - nodedatas.skeleton.emplace_back(nodedata); - else - nodedatas.nodes.emplace_back(nodedata); - } - return true; -} -NodeData* Bundle3D::parseNodesRecursivelyJson(const rapidjson::Value& jvalue, bool singleSprite) -{ - NodeData* nodedata = new NodeData(); - // id - nodedata->id = jvalue[ID].GetString(); - - // transform - Mat4 transform; - const rapidjson::Value& jtransform = jvalue[TRANSFORM]; - - for (rapidjson::SizeType j = 0; j < jtransform.Size(); ++j) - { - transform.m[j] = jtransform[j].GetFloat(); - } - - nodedata->transform = transform; - - bool isSkin = false; - - // parts - if (jvalue.HasMember(PARTS)) - { - const rapidjson::Value& parts = jvalue[PARTS]; - - for (rapidjson::SizeType i = 0; i < parts.Size(); ++i) - { - auto modelnodedata = new ModelData(); - const rapidjson::Value& part = parts[i]; - modelnodedata->subMeshId = part[MESHPARTID].GetString(); - modelnodedata->materialId = part[MATERIALID].GetString(); - - if (modelnodedata->subMeshId == "" || modelnodedata->materialId == "") - { - AXLOGW("warning: Node {} part is missing meshPartId or materialId", nodedata->id); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - - if (part.HasMember(BONES)) - { - const rapidjson::Value& bones = part[BONES]; - - for (rapidjson::SizeType j = 0; j < bones.Size(); ++j) - { - const rapidjson::Value& bone = bones[j]; - - // node - if (!bone.HasMember(NODE)) - { - AXLOGW("warning: Bone node ID missing"); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - - modelnodedata->bones.emplace_back(bone[NODE].GetString()); - - Mat4 invbindpos; - const rapidjson::Value& jinvbindpos = bone[TRANSFORM]; - - for (rapidjson::SizeType k = 0; k < jinvbindpos.Size(); ++k) - { - invbindpos.m[k] = jinvbindpos[k].GetFloat(); - } - - // invbindpos.inverse(); - modelnodedata->invBindPose.emplace_back(invbindpos); - } - - if (bones.Size() > 0) - isSkin = true; - } - nodedata->modelNodeDatas.emplace_back(modelnodedata); - } - } - - // set transform - if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || - _version == "0.6") - { - if (isSkin || singleSprite) - { - nodedata->transform = Mat4::IDENTITY; - } - else - { - nodedata->transform = transform; - } - } - else - { - nodedata->transform = transform; - } - - if (jvalue.HasMember(CHILDREN)) - { - const rapidjson::Value& children = jvalue[CHILDREN]; - for (rapidjson::SizeType i = 0; i < children.Size(); ++i) - { - const rapidjson::Value& child = children[i]; - - NodeData* tempdata = parseNodesRecursivelyJson(child, singleSprite); - nodedata->children.emplace_back(tempdata); - } - } - return nodedata; -} - -bool Bundle3D::loadNodesBinary(NodeDatas& nodedatas) -{ - if (!seekToFirstType(BUNDLE_TYPE_NODE)) - return false; - - unsigned int nodeSize = 0; - if (_binaryReader.read(&nodeSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read nodes"); - return false; - } - - // traverse the nodes again - for (rapidjson::SizeType i = 0; i < nodeSize; ++i) - { - bool skeleton = false; - NodeData* nodedata = parseNodesRecursivelyBinary(skeleton, nodeSize == 1); - - if (skeleton) - nodedatas.skeleton.emplace_back(nodedata); - else - nodedatas.nodes.emplace_back(nodedata); - } - return true; -} -NodeData* Bundle3D::parseNodesRecursivelyBinary(bool& skeleton, bool singleSprite) -{ - // id - std::string id = _binaryReader.readString(); - // is skeleton - bool skeleton_; - if (_binaryReader.read(&skeleton_, 1, 1) != 1) - { - AXLOGW("warning: Failed to read is skeleton"); - return nullptr; - } - if (skeleton_) - skeleton = true; - - // transform - Mat4 transform; - if (!_binaryReader.readMatrix(transform.m)) - { - AXLOGW("warning: Failed to read transform matrix"); - return nullptr; - } - // parts - unsigned int partsSize = 0; - if (_binaryReader.read(&partsSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - return nullptr; - } - - NodeData* nodedata = new NodeData(); - nodedata->id = id; - - bool isSkin = false; - - if (partsSize > 0) - { - for (unsigned int i = 0; i < partsSize; ++i) - { - auto modelnodedata = new ModelData(); - modelnodedata->subMeshId = _binaryReader.readString(); - modelnodedata->materialId = _binaryReader.readString(); - - if (modelnodedata->subMeshId.empty() || modelnodedata->materialId.empty()) - { - AXLOGW("Node {} part is missing meshPartId or materialId", nodedata->id); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - - // read bone - unsigned int bonesSize = 0; - if (_binaryReader.read(&bonesSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - - if (bonesSize > 0) - { - for (unsigned int j = 0; j < bonesSize; ++j) - { - std::string name = _binaryReader.readString(); - modelnodedata->bones.emplace_back(name); - - Mat4 invbindpos; - if (!_binaryReader.readMatrix(invbindpos.m)) - { - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - - modelnodedata->invBindPose.emplace_back(invbindpos); - } - isSkin = true; - } - unsigned int uvMapping = 0; - if (_binaryReader.read(&uvMapping, 4, 1) != 1) - { - AXLOGW("warning: Failed to read nodedata: uvMapping '{}'.", _path); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - for (unsigned int j = 0; j < uvMapping; ++j) - { - unsigned int textureIndexSize = 0; - if (_binaryReader.read(&textureIndexSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - for (unsigned int k = 0; k < textureIndexSize; ++k) - { - unsigned int index = 0; - if (_binaryReader.read(&index, 4, 1) != 1) - { - AX_SAFE_DELETE(modelnodedata); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - } - } - nodedata->modelNodeDatas.emplace_back(modelnodedata); - } - } - - // set transform - if (_version == "0.1" || _version == "0.2" || _version == "0.3" || _version == "0.4" || _version == "0.5" || - _version == "0.6") - { - if (isSkin || singleSprite) - { - nodedata->transform = Mat4::IDENTITY; - } - else - { - nodedata->transform = transform; - } - } - else - { - nodedata->transform = transform; - } - - unsigned int childrenSize = 0; - if (_binaryReader.read(&childrenSize, 4, 1) != 1) - { - AXLOGW("warning: Failed to read meshdata: attribCount '{}'.", _path); - AX_SAFE_DELETE(nodedata); - return nullptr; - } - if (childrenSize > 0) - { - for (unsigned int i = 0; i < childrenSize; ++i) - { - NodeData* tempdata = parseNodesRecursivelyBinary(skeleton, singleSprite); - nodedata->children.emplace_back(tempdata); - } - } - return nodedata; -} - -backend::VertexFormat Bundle3D::parseGLDataType(std::string_view str, int size) -{ - backend::VertexFormat ret = backend::VertexFormat::INT; - if (str == "GL_BYTE") - { - switch (size) - { - case 4: - return backend::VertexFormat::UBYTE4; - default: - AXLOGE("parseVertexType GL_BYTE x {} error", size); - } - } - else if (str == "GL_UNSIGNED_BYTE") - { - switch (size) - { - case 4: - return backend::VertexFormat::UBYTE4; - default: - AXLOGE("parseVertexType GL_UNSIGNED_BYTE x {} error", size); - } - } - else if (str == "GL_SHORT") - { - switch (size) - { - case 2: - return backend::VertexFormat::USHORT2; - case 4: - return backend::VertexFormat::USHORT4; - default: - AXLOGE("parseVertexType GL_SHORT x {} error", size); - } - } - else if (str == "GL_UNSIGNED_SHORT") - { - switch (size) - { - case 2: - return backend::VertexFormat::USHORT2; - case 4: - return backend::VertexFormat::USHORT4; - default: - AXLOGE("parseVertexType GL_UNSIGNED_SHORT x {} error", size); - } - } - else if (str == "GL_INT") - { - switch (size) - { - case 1: - return backend::VertexFormat::INT; - case 2: - return backend::VertexFormat::INT2; - case 3: - return backend::VertexFormat::INT3; - case 4: - return backend::VertexFormat::INT4; - default: - AXLOGE("parseVertexType GL_INT x {} error", size); - } - } - else if (str == "GL_UNSIGNED_INT") - { - switch (size) - { - case 1: - return backend::VertexFormat::INT; - case 2: - return backend::VertexFormat::INT2; - case 3: - return backend::VertexFormat::INT3; - case 4: - return backend::VertexFormat::INT4; - default: - AXLOGE("parseVertexType GL_UNSIGNED_INT x {} error", size); - } - } - else if (str == "GL_FLOAT") - { - switch (size) - { - case 1: - return backend::VertexFormat::FLOAT; - case 2: - return backend::VertexFormat::FLOAT2; - case 3: - return backend::VertexFormat::FLOAT3; - case 4: - return backend::VertexFormat::FLOAT4; - default: - AXLOGE("parseVertexType GL_UNSIGNED_INT x {} error", size); - } - } - AXASSERT(false, "parseVertexType failed!"); - return ret; -} - -backend::SamplerAddressMode Bundle3D::parseSamplerAddressMode(std::string_view str) -{ - - if (str == "REPEAT") - { - return backend::SamplerAddressMode::REPEAT; - } - else if (str == "CLAMP") - { - return backend::SamplerAddressMode::CLAMP_TO_EDGE; - } - else - { - AXASSERT(false, "Invalid GL type"); - return backend::SamplerAddressMode::REPEAT; - } -} - -NTextureData::Usage Bundle3D::parseGLTextureType(std::string_view str) -{ - if (str == "AMBIENT") - { - return NTextureData::Usage::Ambient; - } - else if (str == "BUMP") - { - return NTextureData::Usage::Bump; - } - else if (str == "DIFFUSE") - { - return NTextureData::Usage::Diffuse; - } - else if (str == "EMISSIVE") - { - return NTextureData::Usage::Emissive; - } - else if (str == "NONE") - { - return NTextureData::Usage::None; - } - else if (str == "NORMAL") - { - return NTextureData::Usage::Normal; - } - else if (str == "REFLECTION") - { - return NTextureData::Usage::Reflection; - } - else if (str == "SHININESS") - { - return NTextureData::Usage::Shininess; - } - else if (str == "SPECULAR") - { - return NTextureData::Usage::Specular; - } - else if (str == "TRANSPARENCY") - { - return NTextureData::Usage::Transparency; - } - else - { - AXASSERT(false, "Wrong Texture type"); - return NTextureData::Usage::Unknown; - } -} -shaderinfos::VertexKey Bundle3D::parseGLProgramAttribute(std::string_view str) -{ - if (str == "VERTEX_ATTRIB_POSITION") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_POSITION; - } - else if (str == "VERTEX_ATTRIB_COLOR") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_COLOR; - } - else if (str == "VERTEX_ATTRIB_TEX_COORD") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD; - } - else if (str == "VERTEX_ATTRIB_TEX_COORD1") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD1; - } - else if (str == "VERTEX_ATTRIB_TEX_COORD2") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD2; - } - else if (str == "VERTEX_ATTRIB_TEX_COORD3") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD3; - } - // comment out them - // else if (str == "VERTEX_ATTRIB_TEX_COORD4") - // { - // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD4; - // } - // else if (str == "VERTEX_ATTRIB_TEX_COORD5") - // { - // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD5; - // } - // else if (str == "VERTEX_ATTRIB_TEX_COORD6") - // { - // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD6; - // } - // else if (str == "VERTEX_ATTRIB_TEX_COORD7") - // { - // return shaderinfos::VertexKey::VERTEX_ATTRIB_TEX_COORD7; - // } - else if (str == "VERTEX_ATTRIB_NORMAL") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_NORMAL; - } - else if (str == "VERTEX_ATTRIB_BLEND_WEIGHT") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_WEIGHT; - } - else if (str == "VERTEX_ATTRIB_BLEND_INDEX") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_BLEND_INDEX; - } - else if (str == "VERTEX_ATTRIB_TANGENT") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_TANGENT; - } - else if (str == "VERTEX_ATTRIB_BINORMAL") - { - return shaderinfos::VertexKey::VERTEX_ATTRIB_BINORMAL; - } - else - { - AXASSERT(false, "Wrong Attribute type"); - return shaderinfos::VertexKey::VERTEX_ATTRIB_ERROR; - } -} - -void Bundle3D::getModelRelativePath(std::string_view path) -{ - ssize_t index = path.find_last_of('/'); - std::string fullModelPath; - _modelPath = path.substr(0, index + 1); -} - -Reference* Bundle3D::seekToFirstType(unsigned int type, std::string_view id) -{ - // for each Reference - for (unsigned int i = 0; i < _referenceCount; ++i) - { - Reference* ref = &_references[i]; - if (ref->type == type) - { - // if id is not a null string, we also need to check the Reference's id. - if (id != "" && id != ref->id) - { - continue; - } - - // Found a match - if (_binaryReader.seek(ref->offset, SEEK_SET) == false) - { - AXLOGW("warning: Failed to seek to object '{}' in bundle '{}'.", ref->id, _path); - return nullptr; - } - return ref; - } - } - return nullptr; -} - -std::vector Bundle3D::getTrianglesList(std::string_view path) -{ - std::vector trianglesList; - - if (path.length() <= 4) - return trianglesList; - - auto bundle = Bundle3D::createBundle(); - std::string ext = FileUtils::getPathExtension(path); - MeshDatas meshs; - if (ext == ".obj") - { - MaterialDatas materials; - NodeDatas nodes; - if (!Bundle3D::loadObj(meshs, materials, nodes, path)) - { - Bundle3D::destroyBundle(bundle); - return trianglesList; - } - } - else - { - if (!bundle->load(path)) - { - Bundle3D::destroyBundle(bundle); - return trianglesList; - } - - bundle->loadMeshDatas(meshs); - } - - Bundle3D::destroyBundle(bundle); - for (auto&& iter : meshs.meshDatas) - { - int preVertexSize = iter->getPerVertexSize() / sizeof(float); - for (const auto& indices : iter->subMeshIndices) - { - indices.for_each([&](unsigned int ind) { - trianglesList.emplace_back(Vec3(iter->vertex[ind * preVertexSize], iter->vertex[ind * preVertexSize + 1], - iter->vertex[ind * preVertexSize + 2])); - }); - } - } - - return trianglesList; -} - -Bundle3D::Bundle3D() - : _modelPath(""), _path(""), _version(""), _referenceCount(0), _references(nullptr), _isBinary(false) -{} -Bundle3D::~Bundle3D() -{ - clear(); -} - -ax::AABB Bundle3D::calculateAABB(const std::vector& vertex, - int stride, - const IndexArray& indices) -{ - AABB aabb; - stride /= 4; - - indices.for_each ([&](uint32_t i) { - Vec3 point(vertex[i * stride], vertex[i * stride + 1], vertex[i * stride + 2]); - aabb.updateMinMax(&point, 1); - }); - - return aabb; -} - -} diff --git a/core/3d/Bundle3DData.cpp b/core/3d/Bundle3DData.cpp deleted file mode 100644 index 1eaf9ca2afb8..000000000000 --- a/core/3d/Bundle3DData.cpp +++ /dev/null @@ -1,32 +0,0 @@ -#include "3d/Bundle3DData.h" - -namespace ax -{ - -int MeshVertexAttrib::getAttribSizeBytes() const -{ - int ret = 0; - switch (type) - { - case backend::VertexFormat::FLOAT4: - case backend::VertexFormat::INT4: - return 16; - case backend::VertexFormat::FLOAT3: - case backend::VertexFormat::INT3: - return 12; - case backend::VertexFormat::FLOAT2: - case backend::VertexFormat::INT2: - case backend::VertexFormat::USHORT4: - return 8; - case backend::VertexFormat::FLOAT: - case backend::VertexFormat::INT: - case backend::VertexFormat::UBYTE4: - case backend::VertexFormat::USHORT2: - return 4; - default: - AXASSERT(false, "VertexFormat convert to size error"); - } - return ret; -} - -} \ No newline at end of file diff --git a/core/3d/BundleReader.cpp b/core/3d/BundleReader.cpp deleted file mode 100644 index 31e7102deea0..000000000000 --- a/core/3d/BundleReader.cpp +++ /dev/null @@ -1,192 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "3d/BundleReader.h" -#include "platform/FileUtils.h" - -namespace ax -{ - -BundleReader::BundleReader() -{ - _buffer = nullptr; - _position = 0; - _length = 0; -}; - -BundleReader::~BundleReader(){ - -}; - -void BundleReader::init(char* buffer, ssize_t length) -{ - _position = 0; - _buffer = buffer; - _length = length; -} - -ssize_t BundleReader::read(void* ptr, ssize_t size, ssize_t count) -{ - if (!_buffer || eof()) - { - AXLOGW("warning: bundle reader out of range"); - return 0; - } - - ssize_t validCount; - ssize_t validLength = _length - _position; - ssize_t needLength = size * count; - char* ptr1 = (char*)ptr; - if (validLength < needLength) - { - validCount = validLength / size; - ssize_t readLength = size * validCount; - memcpy(ptr1, (char*)_buffer + _position, readLength); - ptr1 += readLength; - _position += readLength; - readLength = validLength - readLength; - if (readLength > 0) - { - memcpy(ptr1, (char*)_buffer + _position, readLength); - _position += readLength; - validCount += 1; - } - AXLOGW("warning: bundle reader out of range"); - } - else - { - memcpy(ptr1, (char*)_buffer + _position, needLength); - _position += needLength; - validCount = count; - } - - return validCount; -} - -char* BundleReader::readLine(int num, char* line) -{ - if (!_buffer) - return nullptr; - - char* buffer = (char*)_buffer + _position; - char* p = line; - char c; - ssize_t readNum = 0; - while ((c = *buffer) != 10 && readNum < (ssize_t)num && _position < _length) - { - *p = c; - p++; - buffer++; - _position++; - readNum++; - } - *p = '\0'; - - return line; -} - -bool BundleReader::eof() -{ - if (!_buffer) - return true; - - return ((ssize_t)tell()) >= length(); -} - -ssize_t BundleReader::length() -{ - return _length; -} - -ssize_t BundleReader::tell() -{ - if (!_buffer) - return -1; - return _position; -} - -bool BundleReader::seek(int32_t offset, int origin) -{ - if (!_buffer) - return false; - - if (origin == SEEK_CUR) - { - _position += offset; - } - else if (origin == SEEK_SET) - { - _position = offset; - } - else if (origin == SEEK_END) - { - _position = _length + offset; - } - else - return false; - - return true; -} - -bool BundleReader::rewind() -{ - if (_buffer != nullptr) - { - _position = 0; - return true; - } - return false; -} - -std::string BundleReader::readString() -{ - unsigned int length; - if (read(&length, 4, 1) != 1) - { - return std::string(); - } - - std::string str; - - ssize_t validLength = _length - _position; - if (length > 0 && static_cast(length) <= validLength) - { - str.resize(length); - if (read(&str[0], 1, length) != length) - { - return std::string(); - } - } - - return str; -} - -bool BundleReader::readMatrix(float* m) -{ - return (read(m, sizeof(float), 16) == 16); -} - -} diff --git a/core/3d/BundleReader.h b/core/3d/BundleReader.h deleted file mode 100644 index b978169d0c01..000000000000 --- a/core/3d/BundleReader.h +++ /dev/null @@ -1,222 +0,0 @@ -/**************************************************************************** - Copyright (c) 2014-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include -#include - -#include "base/Object.h" -#include "platform/PlatformMacros.h" -#include "base/Logging.h" - -namespace ax -{ - -/** - * @addtogroup _3d - * @{ - */ - -/** - * @brief BundleReader is an interface for reading sequence of bytes. - * @lua NA - */ -class BundleReader : public ax::Object -{ -public: - /** - * Constructor - */ - BundleReader(); - - /** - * Destructor - */ - ~BundleReader(); - - /** - * initialise - * @param buffer The data buffer pointer - * @param length The data buffer size - */ - void init(char* buffer, ssize_t length); - - /** - * Reads an array of elements. - * - * @param ptr The pointer to the memory to copy into. - * The available size should be at least bytes. - * @param size The size of each element to be read, in bytes. - * @param count The number of elements to read. - * - * @return The number of elements read. - */ - ssize_t read(void* ptr, ssize_t size, ssize_t count); - - /** - * Reads a line from the buffer. - */ - char* readLine(int num, char* line); - - /** - * Returns true if the end of the buffer has been reached. - */ - bool eof(); - - /** - * Returns the length of the buffer in bytes. - */ - ssize_t length(); - - /** - * Returns the position of the file pointer. - */ - ssize_t tell(); - - /** - * Sets the position of the file pointer. - */ - bool seek(int32_t offset, int origin); - - /** - * Sets the file pointer at the start of the file. - */ - bool rewind(); - - /** - * read binary typed value. - */ - template - bool read(T* ptr); - template - bool readArray(unsigned int* length, std::vector* values); - - /** - * first read length, then read string text - */ - std::string readString(); - - /** - * Read the matrix. - * @note the matrix type must be the 4*4 float matrix - */ - bool readMatrix(float* m); - -private: - ssize_t _position; - ssize_t _length; - char* _buffer; -}; - -/// @cond - -/** - * template read routines - */ -template -inline bool BundleReader::read(T* ptr) -{ - return (read(ptr, sizeof(T), 1) == 1); -} - -/** - * template function to read array of value. - */ -template -inline bool BundleReader::readArray(unsigned int* length, std::vector* values) -{ - if (!read(length)) - { - return false; - } - - if (*length > 0 && values) - { - values->resize(*length); - if (read(&(*values)[0], sizeof(T), *length) != *length) - { - return false; - } - } - return true; -} - -/** - * specialization for char - */ -template <> -inline bool BundleReader::read(char* ptr) -{ - if (read(ptr, sizeof(char), 1) == 1) - { - return true; - } - else - { - *ptr = -1; - return false; - } -} - -/** - * specialization for std::string - */ -template <> -inline bool BundleReader::read(std::string* /*ptr*/) -{ - AXLOGW("can not read std::string, use readString() instead"); - return false; -} - -/** - * template function to read array of value. - */ -template <> -inline bool BundleReader::readArray(unsigned int* length, std::vector* values) -{ - if (!read(length)) - { - return false; - } - values->clear(); - if (*length > 0 && values) - { - for (int i = 0; i < (int)*length; ++i) - { - values->emplace_back(readString()); - } - } - return true; -} - -/// @endcond - -// end of 3d group -/// @} - -} - diff --git a/core/axmol.h b/core/axmol.h deleted file mode 100644 index 27255311659c..000000000000 --- a/core/axmol.h +++ /dev/null @@ -1,290 +0,0 @@ -/**************************************************************************** -Copyright (c) 2008-2010 Ricardo Quesada -Copyright (c) 2010-2012 cocos2d-x.org -Copyright (c) 2011 Zynga Inc. -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#pragma once - -#include "axmolver.h" - -// -// all axmol include files -// -#include "base/Config.h" - -// base -#ifndef AX_CORE_PROFILE -# include "base/AsyncTaskPool.h" -#endif -#include "base/AutoreleasePool.h" -#include "base/Configuration.h" -#include "base/Logging.h" -#include "base/Data.h" -#include "base/Director.h" -#include "base/IMEDelegate.h" -#include "base/IMEDispatcher.h" -#include "base/Map.h" -#include "base/NS.h" -#include "base/Profiling.h" -#include "base/Properties.h" -#include "base/Object.h" -#include "base/RefPtr.h" -#include "base/Scheduler.h" -#include "base/UserDefault.h" -#include "base/Value.h" -#include "base/Vector.h" -#include "base/ZipUtils.h" -#include "base/base64.h" -#include "base/Config.h" -#include "base/Macros.h" -#include "base/Types.h" -#include "base/UTF8.h" -#include "base/Utils.h" - -// EventDispatcher -#include "base/EventAcceleration.h" -#include "base/EventCustom.h" -#include "base/EventDispatcher.h" -#include "base/EventFocus.h" -#include "base/EventKeyboard.h" -#include "base/EventListenerAcceleration.h" -#include "base/EventListenerCustom.h" -#include "base/EventListenerFocus.h" -#include "base/EventListenerKeyboard.h" -#include "base/EventListenerMouse.h" -#include "base/EventListenerController.h" -#include "base/EventListenerTouch.h" -#include "base/EventMouse.h" -#include "base/EventController.h" -#include "base/Controller.h" -#include "base/EventTouch.h" -#include "base/EventType.h" - -// math -#include "math/AffineTransform.h" -#include "math/Math.h" -#include "math/Vertex.h" -#include "math/Mat4.h" -#include "math/MathUtil.h" -#include "math/Quaternion.h" -#include "math/Vec2.h" -#include "math/Vec3.h" -#include "math/Vec4.h" - -// actions -#include "2d/Action.h" -#include "2d/ActionCamera.h" -#include "2d/ActionCatmullRom.h" -#include "2d/ActionEase.h" -#include "2d/ActionGrid.h" -#include "2d/ActionGrid3D.h" -#include "2d/ActionInstant.h" -#include "2d/ActionInterval.h" -#include "2d/ActionManager.h" -#include "2d/ActionPageTurn3D.h" -#include "2d/ActionProgressTimer.h" -#include "2d/ActionTiledGrid.h" -#include "2d/ActionTween.h" -#include "2d/TweenFunction.h" -#include "2d/ActionCoroutine.h" - -// 2d nodes -#include "2d/AtlasNode.h" -#include "2d/ClippingNode.h" -#include "2d/ClippingRectangleNode.h" -#include "2d/DrawNode.h" -#include "2d/FontFNT.h" -#include "2d/FontFreeType.h" -#include "2d/Label.h" -#include "2d/LabelAtlas.h" -#include "2d/Layer.h" -#include "2d/Menu.h" -#include "2d/MenuItem.h" -#include "2d/MotionStreak.h" -#include "2d/Node.h" -#include "2d/NodeGrid.h" -#include "2d/ParticleBatchNode.h" -#include "2d/ParticleExamples.h" -#include "2d/ParticleSystem.h" -#include "2d/ParticleSystemQuad.h" -#include "2d/ProgressTimer.h" -#include "2d/ProtectedNode.h" -#include "2d/RenderTexture.h" -#include "2d/Scene.h" -#include "2d/Transition.h" -#include "2d/TransitionPageTurn.h" -#include "2d/TransitionProgress.h" - -// 2d utils -#include "2d/Camera.h" -#include "2d/CameraBackgroundBrush.h" -#include "2d/Grid.h" -#include "2d/Light.h" - -// include -#include "base/Protocols.h" - -// renderer -#include "renderer/CallbackCommand.h" -#include "renderer/CustomCommand.h" -#include "renderer/GroupCommand.h" -#include "renderer/Material.h" -#include "renderer/Pass.h" -#include "renderer/QuadCommand.h" -#include "renderer/RenderCommand.h" -#include "renderer/RenderCommandPool.h" -#include "renderer/RenderState.h" -#include "renderer/Renderer.h" -#include "renderer/Technique.h" -#include "renderer/Texture2D.h" -#include "renderer/TextureCube.h" -#include "renderer/TextureCache.h" -#include "renderer/TrianglesCommand.h" -#include "renderer/Shaders.h" - -// physics -#include "physics/PhysicsBody.h" -#include "physics/PhysicsContact.h" -#include "physics/PhysicsJoint.h" -#include "physics/PhysicsShape.h" -#include "physics/PhysicsWorld.h" - -// platform -#include "platform/Common.h" -#include "platform/Device.h" -#include "platform/FileUtils.h" -#include "platform/FileStream.h" -#include "platform/Image.h" -#include "platform/PlatformConfig.h" -#include "platform/PlatformMacros.h" -#include "platform/SAXParser.h" - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_IOS) -# include "platform/ios/Application-ios.h" -# include "platform/ios/RenderViewImpl-ios.h" -# include "platform/ios/StdC-ios.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_IOS - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "platform/android/Application-android.h" -# include "platform/android/RenderViewImpl-android.h" -# include "platform/android/GL-android.h" -# include "platform/android/StdC-android.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "platform/win32/Application-win32.h" -# include "platform/RenderViewImpl.h" -# include "platform/win32/GL-win32.h" -# include "platform/win32/StdC-win32.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_WINRT) -# include "platform/winrt/Application-winrt.h" -# include "platform/winrt/RenderViewImpl-winrt.h" -# include "platform/winrt/GL-winrt.h" -# include "platform/winrt/StdC-winrt.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WINRT - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_MAC) -# include "platform/RenderViewImpl.h" -# include "platform/mac/Application-mac.h" -# include "platform/mac/StdC-mac.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_MAC - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_LINUX) -# include "platform/linux/Application-linux.h" -# include "platform/RenderViewImpl.h" -# include "platform/linux/GL-linux.h" -# include "platform/linux/StdC-linux.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_LINUX - -#if (AX_TARGET_PLATFORM == AX_PLATFORM_WASM) - #include "platform/wasm/Application-wasm.h" - #include "platform/RenderViewImpl.h" - #include "platform/wasm/GL-wasm.h" - #include "platform/wasm/StdC-wasm.h" -#endif // AX_TARGET_PLATFORM == AX_PLATFORM_WASM - -// script_support -#include "base/ScriptSupport.h" - -// sprite_nodes -#include "2d/Animation.h" -#include "2d/AnimationCache.h" -#include "2d/Sprite.h" -#include "2d/AnchoredSprite.h" -#include "2d/AutoPolygon.h" -#include "2d/SpriteBatchNode.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" - -// text_input_node -#include "2d/TextFieldTTF.h" - -// textures -#include "renderer/TextureAtlas.h" - -// tilemap_parallax_nodes -#include "2d/ParallaxNode.h" -#include "2d/TMXObjectGroup.h" -#include "2d/TMXXMLParser.h" -#include "2d/TileMapAtlas.h" -#include "2d/FastTMXLayer.h" -#include "2d/FastTMXTiledMap.h" - -// component -#include "2d/Component.h" -#include "2d/ComponentContainer.h" - -// 3d -#include "3d/AABB.h" -#include "3d/Animate3D.h" -#include "3d/Animation3D.h" -#include "3d/AttachNode.h" -#include "3d/BillBoard.h" -#include "3d/Frustum.h" -#include "3d/Mesh.h" -#include "3d/MeshSkin.h" -#include "3d/MotionStreak3D.h" -#include "3d/MeshVertexIndexData.h" -#include "3d/OBB.h" -#include "3d/Plane.h" -#include "3d/Ray.h" -#include "3d/Skeleton3D.h" -#include "3d/Skybox.h" -#include "3d/MeshRenderer.h" -#include "3d/MeshMaterial.h" -#include "3d/Terrain.h" -#include "3d/VertexAttribBinding.h" - -namespace ax -{ - -AX_DLL const char* axmolVersion(); - -} diff --git a/core/base/AsyncTaskPool.cpp b/core/base/AsyncTaskPool.cpp deleted file mode 100644 index 5ee32e08fd68..000000000000 --- a/core/base/AsyncTaskPool.cpp +++ /dev/null @@ -1,53 +0,0 @@ -/**************************************************************************** -Copyright (c) 2010 cocos2d-x.org -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#include "base/AsyncTaskPool.h" - -namespace ax -{ - -AsyncTaskPool* AsyncTaskPool::s_asyncTaskPool = nullptr; - -AsyncTaskPool* AsyncTaskPool::getInstance() -{ - if (s_asyncTaskPool == nullptr) - { - s_asyncTaskPool = new AsyncTaskPool(); - } - return s_asyncTaskPool; -} - -void AsyncTaskPool::destroyInstance() -{ - delete s_asyncTaskPool; - s_asyncTaskPool = nullptr; -} - -AsyncTaskPool::AsyncTaskPool() {} - -AsyncTaskPool::~AsyncTaskPool() {} - -} diff --git a/core/base/AsyncTaskPool.h b/core/base/AsyncTaskPool.h deleted file mode 100644 index 12604cce74ea..000000000000 --- a/core/base/AsyncTaskPool.h +++ /dev/null @@ -1,229 +0,0 @@ -/**************************************************************************** -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#pragma once - -#include "platform/PlatformMacros.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/** - * @addtogroup base - * @{ - */ -namespace ax -{ - -/** - * @class AsyncTaskPool - * @brief This class allows to perform background operations without having to manipulate threads. - */ -class AX_DLL AsyncTaskPool -{ -public: - typedef std::function TaskCallBack; - - enum class TaskType - { - TASK_IO, - TASK_NETWORK, - TASK_OTHER, - TASK_MAX_TYPE, - }; - - /** - * Returns the shared instance of the async task pool. - */ - static AsyncTaskPool* getInstance(); - - /** - * Destroys the async task pool. - */ - static void destroyInstance(); - - /** - * Stop tasks. - * - * @param type Task type you want to stop. - */ - void stopTasks(TaskType type); - - /** - * Enqueue a asynchronous task. - * - * @param type task type is io task, network task or others, each type of task has a thread to deal with it. - * @param callback callback when the task is finished. The callback is called in the main thread instead of task - * thread. - * @param callbackParam parameter used by the callback. - * @param task: task can be lambda function to be performed off thread. - * @lua NA - */ - void enqueue(TaskType type, TaskCallBack callback, void* callbackParam, std::function task); - - /** - * Enqueue a asynchronous task. - * - * @param type task type is io task, network task or others, each type of task has a thread to deal with it. - * @param task: task can be lambda function to be performed off thread. - * @lua NA - */ - void enqueue(AsyncTaskPool::TaskType type, std::function task); - - AsyncTaskPool(); - ~AsyncTaskPool(); - -protected: - // thread tasks internally used - class ThreadTasks - { - struct AsyncTaskCallBack - { - TaskCallBack callback; - void* callbackParam; - }; - - public: - ThreadTasks() : _stop(false) - { - _thread = std::thread([this] { - for (;;) - { - std::function task; - AsyncTaskCallBack callback; - { - std::unique_lock lock(this->_queueMutex); - this->_condition.wait(lock, [this] { return this->_stop || !this->_tasks.empty(); }); - if (this->_stop && this->_tasks.empty()) - return; - task = std::move(this->_tasks.front()); - callback = std::move(this->_taskCallBacks.front()); - this->_tasks.pop(); - this->_taskCallBacks.pop(); - } - - task(); - Director::getInstance()->getScheduler()->runOnAxmolThread( - std::bind(callback.callback, callback.callbackParam)); - } - }); - } - ~ThreadTasks() - { - { - std::unique_lock lock(_queueMutex); - _stop = true; - - while (_tasks.size()) - _tasks.pop(); - while (_taskCallBacks.size()) - _taskCallBacks.pop(); - } - _condition.notify_all(); - _thread.join(); - } - void clear() - { - std::unique_lock lock(_queueMutex); - while (_tasks.size()) - _tasks.pop(); - while (_taskCallBacks.size()) - _taskCallBacks.pop(); - } - - void enqueue(TaskCallBack callback, void* callbackParam, std::function task) - { - AsyncTaskCallBack taskCallBack; - taskCallBack.callback = std::move(callback); - taskCallBack.callbackParam = callbackParam; - - { - std::unique_lock lock(_queueMutex); - - // don't allow enqueueing after stopping the pool - if (_stop) - { - AX_ASSERT(0 && "already stop"); - return; - } - - _tasks.push(std::move(task)); - _taskCallBacks.push(std::move(taskCallBack)); - } - _condition.notify_one(); - } - - private: - // need to keep track of thread so we can join them - std::thread _thread; - // the task queue - std::queue> _tasks; - std::queue _taskCallBacks; - - // synchronization - std::mutex _queueMutex; - std::condition_variable _condition; - bool _stop; - }; - - // tasks - ThreadTasks _threadTasks[int(TaskType::TASK_MAX_TYPE)]; - - static AsyncTaskPool* s_asyncTaskPool; -}; - -inline void AsyncTaskPool::stopTasks(TaskType type) -{ - auto& threadTask = _threadTasks[(int)type]; - threadTask.clear(); -} - -inline void AsyncTaskPool::enqueue(AsyncTaskPool::TaskType type, - TaskCallBack callback, - void* callbackParam, - std::function task) -{ - auto& threadTask = _threadTasks[(int)type]; - - threadTask.enqueue(std::move(callback), callbackParam, std::move(task)); -} - -inline void AsyncTaskPool::enqueue(AsyncTaskPool::TaskType type, std::function task) -{ - enqueue( - type, [](void*) {}, nullptr, std::move(task)); -} - -} -// end group -/// @} diff --git a/core/base/Enums.h b/core/base/Enums.h deleted file mode 100644 index 42b57425a050..000000000000 --- a/core/base/Enums.h +++ /dev/null @@ -1,141 +0,0 @@ -/**************************************************************************** -Copyright (c) 2008-2010 Ricardo Quesada -Copyright (c) 2010-2012 cocos2d-x.org -Copyright (c) 2011 Zynga Inc. -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ -#pragma once - -namespace ax -{ - -/** - * @brief Effects used by `Label` - */ -enum class LabelEffect -{ - // FIXME: Covert them to bitwise. More than one effect should be supported - NORMAL, - OUTLINE, - SHADOW, - GLOW, - ITALICS, - BOLD, - UNDERLINE, - STRIKETHROUGH, - ALL -}; - -/** - * @brief Interval change reason. - */ -enum class SetIntervalReason : char -{ - BY_GAME = 0, - BY_ENGINE, - BY_SYSTEM, - BY_SCENE_CHANGE, - BY_DIRECTOR_PAUSE -}; - -/** - * @brief Texture flags. - */ -struct TextureFlag -{ - enum - { - NONE = 0, - ANTIALIAS_ENABLED = 1 << 1, - PREMULTIPLIEDALPHA = 1 << 2, - RENDERTARGET = 1 << 3, - }; -}; - -/** - * @brief Texture sampler flags. - */ -struct TextureSamplerFlag -{ - enum - { - DEFAULT = 0, - DUAL_SAMPLER = 1 << 1, - }; -}; - -/** - * @brief Matrix stack type. - */ -enum class MATRIX_STACK_TYPE -{ - /// Model view matrix stack - MATRIX_STACK_MODELVIEW, - - /// projection matrix stack - MATRIX_STACK_PROJECTION, - - /// texture matrix stack - MATRIX_STACK_TEXTURE -}; - -/** - * @brief Anchor presets used to position nodes in corners - */ -enum class AnchorPreset -{ - BOTTOM_LEFT = 0, - BOTTOM_CENTER = 1, - BOTTOM_RIGHT = 2, - CENTER_LEFT = 3, - CENTER = 4, - CENTER_RIGHT = 5, - TOP_LEFT = 6, - TOP_CENTER = 7, - TOP_RIGHT = 8 -}; - -/** - * Particle emission shapes. - * Supported shapes are Point, Rectangle, RectangularTorus, Circle, Torus, Cone, Cone Torus, Texture alpha emission mask - * @since axmol-1.0.0b8 - */ -enum class EmissionShapeType -{ - // Emission shape of type point - POINT, - // Emission shape of type rectangle - RECT, - // Emission shape of type rectangular torus - RECTTORUS, - // Emission shape of type circle or cone - CIRCLE, - // Emission shape of type torus or cone torus - TORUS, - // Emission shape of type texture alpha mask - TEXTURE_ALPHA_MASK -}; - -} diff --git a/core/base/PaddedString.h b/core/base/PaddedString.h deleted file mode 100644 index 63dac7b65f04..000000000000 --- a/core/base/PaddedString.h +++ /dev/null @@ -1,105 +0,0 @@ -/**************************************************************************** - -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - - - ****************************************************************************/ - -#pragma once - -#include "simdjson/simdjson.h" -#include "platform/FileUtils.h" - -namespace ax -{ - -/** - * @addtogroup base - * @{ - */ - -/** - @brief A dedicated class for easy load padded string for simdjson parser. - - The only legal use case is: - - auto strJson = PaddedString::load(fontatlasFile); - ondemand::parser parser; - ondemand::document settings = parser.iterate(strJson); - */ -class PaddedString final -{ -public: - static PaddedString load(std::string_view filename) - { - PaddedString ret; - FileUtils::getInstance()->getContents(filename, &ret); - return ret; - } - - PaddedString() = default; - ~PaddedString() { delete[] data_ptr; } - - PaddedString(PaddedString&& o) noexcept : viable_size(o.viable_size), data_ptr(o.data_ptr) - { - o.data_ptr = nullptr; // we take ownership - } - PaddedString& operator=(PaddedString&& o) noexcept - { - swap(o); - return *this; - } - void swap(PaddedString& o) noexcept - { - std::swap(viable_size, o.viable_size); - std::swap(data_ptr, o.data_ptr); - } - - using value_type = char; - size_t size() const { return viable_size; } - void resize(size_t size) - { - assert(!data_ptr || size <= viable_size); // not allow enlarge - if (!data_ptr) - data_ptr = simdjson::internal::allocate_padded_buffer(size); - viable_size = size; - } - - char* data() { return data_ptr; } - const char* data() const { return data_ptr; } - - operator simdjson::padded_string_view() const noexcept - { - return simdjson::padded_string_view(data(), size(), size() + simdjson::SIMDJSON_PADDING); - } - -private: - PaddedString(const PaddedString&) = delete; - size_t viable_size{0}; - char* data_ptr{nullptr}; -}; - -// end of base group -/** @} */ - -} diff --git a/core/base/json.h b/core/base/json.h deleted file mode 100644 index 6de168546d28..000000000000 --- a/core/base/json.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once - -#include "rapidjson/rapidjson.h" -#include "rapidjson/document.h" diff --git a/core/math/Color.h b/core/math/Color.h deleted file mode 100644 index 15e5281ad354..000000000000 --- a/core/math/Color.h +++ /dev/null @@ -1,225 +0,0 @@ -/**************************************************************************** - -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#pragma once - -#include "math/Vec4.h" - -#if defined(_WIN32) -# pragma push_macro("TRANSPARENT") -# undef TRANSPARENT -#endif - -NS_AX_MATH_BEGIN - -struct Color4B; -struct Color4F; -struct HSV; - -/** - * RGB color composed of bytes 3 bytes. - * @since v3.0 - */ -struct AX_DLL Color3B -{ - Color3B() {}; - Color3B(uint8_t _r, uint8_t _g, uint8_t _b) : r(_r), g(_g), b(_b) {} - explicit Color3B(const Color4B& color); - explicit Color3B(const Color4F& color); - - bool operator==(const Color3B& right) const; - bool operator==(const Color4B& right) const; - bool operator==(const Color4F& right) const; - bool operator!=(const Color3B& right) const; - bool operator!=(const Color4B& right) const; - bool operator!=(const Color4F& right) const; - - bool equals(const Color3B& other) const { return (*this == other); } - - uint8_t r = 0; - uint8_t g = 0; - uint8_t b = 0; - - static const Color3B WHITE; - static const Color3B YELLOW; - static const Color3B BLUE; - static const Color3B GREEN; - static const Color3B RED; - static const Color3B MAGENTA; - static const Color3B BLACK; - static const Color3B ORANGE; - static const Color3B GRAY; -}; - -/** - * RGBA color composed of 4 bytes. - * @since v3.0 - */ -struct AX_DLL Color4B -{ - Color4B() {} - Color4B(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) : r(_r), g(_g), b(_b), a(_a) {} - explicit Color4B(const Color3B& color, uint8_t _a = 255) : r(color.r), g(color.g), b(color.b), a(_a) {} - Color4B(const Color4F& color); - - inline void set(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a) - { - r = _r; - g = _g; - b = _b; - a = _a; - } - - bool operator==(const Color4B& right) const; - bool operator==(const Color3B& right) const; - bool operator==(const Color4F& right) const; - bool operator!=(const Color4B& right) const; - bool operator!=(const Color3B& right) const; - bool operator!=(const Color4F& right) const; - - uint8_t r = 0; - uint8_t g = 0; - uint8_t b = 0; - uint8_t a = 0; - - static const Color4B WHITE; - static const Color4B YELLOW; - static const Color4B BLUE; - static const Color4B GREEN; - static const Color4B RED; - static const Color4B MAGENTA; - static const Color4B BLACK; - static const Color4B ORANGE; - static const Color4B GRAY; - static const Color4B TRANSPARENT; // TRANSPARENT is defined on wingdi.h /*Background Modes*/ -}; - -/** - * RGBA color composed of 4 floats. - * @since v3.0 - */ -struct AX_DLL Color4F : public Vec4Base -{ - using Vec4Base = Vec4Base; - - Color4F() {} - Color4F(float _r, float _g, float _b, float _a) : Vec4Base(_r, _g, _b, _a) {} - explicit Color4F(const Color3B& color, float _a = 1.0f) - : Vec4Base(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, _a) - {} - explicit Color4F(const Color4B& color) - : Vec4Base(color.r / 255.0f, color.g / 255.0f, color.b / 255.0f, color.a / 255.0f) - {} - - bool operator==(const Color3B& rhs) const; - bool operator==(const Color4B& rhs) const; - bool operator!=(const Color3B& rhs) const; - bool operator!=(const Color4B& rhs) const; - - bool equals(const Color4F& other) const { return (*this == other); } - - static const Color4F WHITE; - static const Color4F YELLOW; - static const Color4F BLUE; - static const Color4F GREEN; - static const Color4F RED; - static const Color4F MAGENTA; - static const Color4F BLACK; - static const Color4F ORANGE; - static const Color4F GRAY; - static const Color4F TRANSPARENT; // TRANSPARENT is defined on wingdi.h /*Background Modes*/ -}; - -/** - * Hue Saturation Value color space composed of 4 floats. - * @since axmol-1.0.0b7 - * - * Implementation source: https://gist.github.com/fairlight1337/4935ae72bcbcc1ba5c72 - */ -struct AX_DLL HSV : public Vec4Base -{ - HSV(); - HSV(float _h, float _s, float _v, float _a = 1.0F); - - explicit HSV(const Color3B& c); - explicit HSV(const Color4B& c); - explicit HSV(const Color4F& c); - - bool equals(const HSV& other) const { return (*this == other); } - - void fromRgba(const Color4F& rgba); - Color4F toRgba() const; - - Color3B toColor3B() const; - Color4B toColor4B() const; - Color4F toColor4F() const; -}; - -/** - * Hue Saturation Luminance color space composed of 4 floats. - * @since axmol-1.0.0b7 - * - * Implementation source: https://gist.github.com/ciembor/1494530 - */ -struct AX_DLL HSL : public Vec4Base -{ - HSL(); - HSL(float _h, float _s, float _l, float _a = 1.0F); - - explicit HSL(const Color3B& c); - explicit HSL(const Color4B& c); - explicit HSL(const Color4F& c); - - bool equals(const HSL& other) const { return (*this == other); } - - void fromRgba(const Color4F& rgba); - Color4F toRgba() const; - - static float hue2rgb(float p, float q, float t); - - Color3B toColor3B() const; - Color4B toColor4B() const; - Color4F toColor4F() const; -}; - -inline Color3B::Color3B(const Color4B& color) : r(color.r), g(color.g), b(color.b) {} -inline Color3B::Color3B(const Color4F& color) - : r(static_cast(color.r * 255)) - , g(static_cast(color.g * 255)) - , b(static_cast(color.b * 255)) -{} - -inline Color4B::Color4B(const Color4F& color) - : r(static_cast(color.r * 255)) - , g(static_cast(color.g * 255)) - , b(static_cast(color.b * 255)) - , a(static_cast(color.a * 255)) -{} - -NS_AX_MATH_END - -#if defined(_WIN32) -# pragma pop_macro("TRANSPARENT") -#endif diff --git a/core/physics/CMakeLists.txt b/core/physics/CMakeLists.txt deleted file mode 100644 index c0481e62e87f..000000000000 --- a/core/physics/CMakeLists.txt +++ /dev/null @@ -1,17 +0,0 @@ -set(_AX_PHYSICS_HEADER - physics/PhysicsContact.h - physics/PhysicsWorld.h - physics/PhysicsBody.h - physics/cpCompat62.h - physics/PhysicsShape.h - physics/PhysicsHelper.h - physics/PhysicsJoint.h -) - -set(_AX_PHYSICS_SRC - physics/PhysicsBody.cpp - physics/PhysicsContact.cpp - physics/PhysicsJoint.cpp - physics/PhysicsShape.cpp - physics/PhysicsWorld.cpp -) diff --git a/core/physics/PhysicsHelper.h b/core/physics/PhysicsHelper.h deleted file mode 100644 index 5edf8cd5344a..000000000000 --- a/core/physics/PhysicsHelper.h +++ /dev/null @@ -1,115 +0,0 @@ -/**************************************************************************** - Copyright (c) 2013 cocos2d-x.org - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "base/Config.h" -#if defined(AX_ENABLE_PHYSICS) - -# include "chipmunk/chipmunk.h" -# include "platform/PlatformMacros.h" -# include "math/Math.h" - -namespace ax -{ - -/** - * @addtogroup physics - * @{ - * @addtogroup physics_2d - * @{ - */ - -/** - * A physics helper class. - * - * Support for conversion between the chipmunk types and cocos types, eg: cpVect to Vec2, Vec2 to cpVect, cpFloat to - * float. - */ -class PhysicsHelper -{ -public: - /** Make cpVect type convert to Vec2 type. */ - static Vec2 cpv2vec2(const cpVect& vec) { return Vec2(vec.x, vec.y); } - - /** Make Vec2 type convert to cpVect type. */ - static cpVect vec22cpv(const Vec2& point) { return cpv(point.x, point.y); } - - /** Make cpFloat type convert to float type. */ - static float cpfloat2float(cpFloat f) { return f; } - - /** Make Rect type convert to cpBB type. */ - static cpBB rect2cpbb(const Rect& rect) - { - return cpBBNew(rect.origin.x, rect.origin.y, rect.origin.x + rect.size.width, rect.origin.y + rect.size.height); - } - - /** Make cpBB type convert to Rect type. */ - static Rect cpbb2rect(const cpBB& bb) { return Rect(bb.l, bb.b, bb.r - bb.l, bb.t - bb.b); } - - /** - Make cpVect array convert to Vec2 array. - - @param cpvs The be converted object, it's a cpVect array. - @param out The converted object, it's a Vec2 array. - @param count It's cpvs array length. - @return The out object's pointer. - */ - static Vec2* cpvs2points(const cpVect* cpvs, Vec2* out, int count) - { - for (int i = 0; i < count; ++i) - { - out[i] = cpv2vec2(cpvs[i]); - } - - return out; - } - - /** - Make Vec2 array convert to cpVect array. - - @param points The be converted object, it's a Vec2 array. - @param out The converted object, it's a cpVect array. - @param count It's points array length. - @return The out object's pointer. - */ - static cpVect* points2cpvs(const Vec2* points, cpVect* out, int count) - { - for (int i = 0; i < count; ++i) - { - out[i] = vec22cpv(points[i]); - } - - return out; - } -}; - -/** @} */ -/** @} */ - -} - -#endif // AX_ENABLE_PHYSICS diff --git a/core/physics/PhysicsJoint.cpp b/core/physics/PhysicsJoint.cpp deleted file mode 100644 index 33063b046c8e..000000000000 --- a/core/physics/PhysicsJoint.cpp +++ /dev/null @@ -1,936 +0,0 @@ -/**************************************************************************** - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "physics/PhysicsJoint.h" -#if defined(AX_ENABLE_PHYSICS) -# include "chipmunk/chipmunk.h" - -# include "physics/PhysicsBody.h" -# include "physics/PhysicsWorld.h" -# include "physics/PhysicsHelper.h" -# include "2d/Node.h" - -namespace ax -{ - -template -class Optional -{ - -public: - Optional() {} - Optional(T d) : _isSet(true), _data(d) {} - Optional(const Optional& t) : _isSet(t._isSet), _data(t._data) {} - - // bool isNull() const { return !_isSet; } - // bool isDefineded() const { return _isSet; } - // bool isEmpty() const { return !_isSet; } - - T get() const - { - AXASSERT(_isSet, "data should be set!"); - return _data; - } - void set(T d) - { - _isSet = true; - _data = d; - } - -private: - bool _isSet = false; - T _data; -}; - -class WriteCache -{ -public: - Optional _grooveA; - Optional _grooveB; - Optional _anchr1; - Optional _anchr2; - Optional _min; - Optional _max; - Optional _distance; - Optional _restLength; - Optional _restAngle; - Optional _stiffness; - Optional _damping; - Optional _angle; - Optional _phase; - Optional _ratchet; - Optional _ratio; - Optional _rate; -}; - -# if (defined(__GNUC__) && __GNUC__ >= 4) || defined(__clang__) -# define LIKELY(x) (__builtin_expect((x), 1)) -# define UNLIKELY(x) (__builtin_expect((x), 0)) -# else -# define LIKELY(x) (x) -# define UNLIKELY(x) (x) -# endif - -# define AX_PJOINT_CACHE_READ(field) \ - do \ - { \ - if (UNLIKELY(_initDirty)) \ - { \ - return _writeCache->field.get(); \ - } \ - } while (0) - -# define AX_PJOINT_CACHE_WRITE2(field, method, arg, convertedArg) \ - do \ - { \ - if (UNLIKELY(_initDirty)) \ - { \ - _writeCache->field.set(arg); \ - delay([this, arg]() { method(_cpConstraints.front(), convertedArg); }); \ - } \ - else \ - { \ - method(_cpConstraints.front(), convertedArg); \ - } \ - } while (0) - -# define AX_PJOINT_CACHE_WRITE(field, method, arg) AX_PJOINT_CACHE_WRITE2(field, method, arg, arg) - -PhysicsJoint::PhysicsJoint() - : _bodyA(nullptr) - , _bodyB(nullptr) - , _world(nullptr) - , _enable(false) - , _collisionEnable(true) - , _destroyMark(false) - , _tag(0) - , _maxForce(PHYSICS_INFINITY) - , _initDirty(true) -{ - _writeCache = new WriteCache(); -} - -PhysicsJoint::~PhysicsJoint() -{ - // reset the shapes collision group - setCollisionEnable(true); - - for (cpConstraint* joint : _cpConstraints) - { - cpConstraintFree(joint); - } - _cpConstraints.clear(); - - delete _writeCache; -} - -bool PhysicsJoint::init(ax::PhysicsBody* a, ax::PhysicsBody* b) -{ - do - { - AXASSERT(a != nullptr && b != nullptr, "the body passed in is nil"); - AXASSERT(a != b, "the two bodies are equal"); - - _bodyA = a; - _bodyB = b; - _bodyA->_joints.emplace_back(this); - _bodyB->_joints.emplace_back(this); - - return true; - } while (false); - - return false; -} - -bool PhysicsJoint::initJoint() -{ - bool ret = !_initDirty; - while (_initDirty) - { - ret = createConstraints(); - AX_BREAK_IF(!ret); - - for (auto&& subjoint : _cpConstraints) - { - cpConstraintSetMaxForce(subjoint, _maxForce); - cpConstraintSetErrorBias(subjoint, cpfpow(1.0f - 0.15f, 60.0f)); - cpSpaceAddConstraint(_world->_cpSpace, subjoint); - } - _initDirty = false; - ret = true; - } - - return ret; -} - -void PhysicsJoint::flushDelayTasks() -{ - for (const auto& tsk : _delayTasks) - { - tsk(); - } - _delayTasks.clear(); -} - -void PhysicsJoint::setEnable(bool enable) -{ - if (_enable != enable) - { - _enable = enable; - - if (_world) - { - if (enable) - { - _world->addJoint(this); - } - else - { - _world->removeJoint(this, false); - } - } - } -} - -void PhysicsJoint::setCollisionEnable(bool enable) -{ - if (_collisionEnable != enable) - { - _collisionEnable = enable; - } -} - -void PhysicsJoint::removeFormWorld() -{ - if (_world) - { - _world->removeJoint(this, false); - } -} - -void PhysicsJoint::setMaxForce(float force) -{ - if (_initDirty) - { - delay([this, force]() { - _maxForce = force; - for (auto&& joint : _cpConstraints) - { - cpConstraintSetMaxForce(joint, force); - } - }); - } - else - { - _maxForce = force; - for (auto&& joint : _cpConstraints) - { - cpConstraintSetMaxForce(joint, force); - } - } -} - -PhysicsJointFixed* PhysicsJointFixed::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr) -{ - auto joint = new PhysicsJointFixed(); - - if (joint->init(a, b)) - { - joint->_anchr = anchr; - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointFixed::createConstraints() -{ - do - { - _bodyA->getNode()->setPosition(_anchr); - _bodyB->getNode()->setPosition(_anchr); - - // add a pivot joint to fixed two body together - auto joint = cpPivotJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr)); - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - // add a gear joint to make two body have the same rotation. - joint = cpGearJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), 0, 1); - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - _collisionEnable = false; - - return true; - } while (false); - - return false; -} - -PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& pivot) -{ - auto joint = new PhysicsJointPin(); - - if (joint->init(a, b)) - { - joint->_anchr1 = pivot; - joint->_useSpecificAnchr = false; - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -PhysicsJointPin* PhysicsJointPin::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2) -{ - auto joint = new PhysicsJointPin(); - - if (joint->init(a, b)) - { - joint->_anchr1 = anchr1; - joint->_anchr2 = anchr2; - joint->_useSpecificAnchr = true; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointPin::createConstraints() -{ - do - { - cpConstraint* joint = nullptr; - if (_useSpecificAnchr) - { - joint = cpPivotJointNew2(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr1), - PhysicsHelper::vec22cpv(_anchr2)); - } - else - { - joint = cpPivotJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr1)); - } - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -PhysicsJointLimit* PhysicsJointLimit::construct(PhysicsBody* a, - PhysicsBody* b, - const Vec2& anchr1, - const Vec2& anchr2, - float min, - float max) -{ - auto joint = new PhysicsJointLimit(); - - if (joint->init(a, b)) - { - joint->_anchr1 = anchr1; - joint->_anchr2 = anchr2; - joint->_min = min; - joint->_max = max; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -PhysicsJointLimit* PhysicsJointLimit::construct(PhysicsBody* a, PhysicsBody* b, const Vec2& anchr1, const Vec2& anchr2) -{ - return construct(a, b, anchr1, anchr2, 0, b->local2World(anchr1).getDistance(a->local2World(anchr2))); -} - -bool PhysicsJointLimit::createConstraints() -{ - do - { - auto joint = cpSlideJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr1), - PhysicsHelper::vec22cpv(_anchr2), _min, _max); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointLimit::getMin() const -{ - AX_PJOINT_CACHE_READ(_min); - return PhysicsHelper::cpfloat2float(cpSlideJointGetMin(_cpConstraints.front())); -} - -void PhysicsJointLimit::setMin(float min) -{ - AX_PJOINT_CACHE_WRITE(_min, cpSlideJointSetMin, min); -} - -float PhysicsJointLimit::getMax() const -{ - AX_PJOINT_CACHE_READ(_max); - return PhysicsHelper::cpfloat2float(cpSlideJointGetMax(_cpConstraints.front())); -} - -void PhysicsJointLimit::setMax(float max) -{ - AX_PJOINT_CACHE_WRITE(_max, cpSlideJointSetMax, max); -} - -Vec2 PhysicsJointLimit::getAnchr1() const -{ - AX_PJOINT_CACHE_READ(_anchr1); - return PhysicsHelper::cpv2vec2(cpSlideJointGetAnchorA(_cpConstraints.front())); -} - -void PhysicsJointLimit::setAnchr1(const Vec2& anchr) -{ - AX_PJOINT_CACHE_WRITE2(_anchr1, cpSlideJointSetAnchorA, anchr, PhysicsHelper::vec22cpv(anchr)); -} - -Vec2 PhysicsJointLimit::getAnchr2() const -{ - AX_PJOINT_CACHE_READ(_anchr2); - return PhysicsHelper::cpv2vec2(cpSlideJointGetAnchorB(_cpConstraints.front())); -} - -void PhysicsJointLimit::setAnchr2(const Vec2& anchr) -{ - AX_PJOINT_CACHE_WRITE2(_anchr2, cpSlideJointSetAnchorB, anchr, PhysicsHelper::vec22cpv(anchr)); -} - -PhysicsJointDistance* PhysicsJointDistance::construct(PhysicsBody* a, - PhysicsBody* b, - const Vec2& anchr1, - const Vec2& anchr2) -{ - auto joint = new PhysicsJointDistance(); - - if (joint->init(a, b)) - { - joint->_anchr1 = anchr1; - joint->_anchr2 = anchr2; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointDistance::createConstraints() -{ - do - { - auto joint = cpPinJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr1), - PhysicsHelper::vec22cpv(_anchr2)); - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointDistance::getDistance() const -{ - AX_PJOINT_CACHE_READ(_distance); - return PhysicsHelper::cpfloat2float(cpPinJointGetDist(_cpConstraints.front())); -} - -void PhysicsJointDistance::setDistance(float distance) -{ - AX_PJOINT_CACHE_WRITE(_distance, cpPinJointSetDist, distance); -} - -PhysicsJointSpring* PhysicsJointSpring::construct(PhysicsBody* a, - PhysicsBody* b, - const Vec2& anchr1, - const Vec2& anchr2, - float stiffness, - float damping) -{ - auto joint = new PhysicsJointSpring(); - - if (joint->init(a, b)) - { - joint->_anchr1 = anchr1; - joint->_anchr2 = anchr2; - joint->_stiffness = stiffness; - joint->_damping = damping; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointSpring::createConstraints() -{ - do - { - auto joint = cpDampedSpringNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_anchr1), - PhysicsHelper::vec22cpv(_anchr2), - _bodyB->local2World(_anchr1).getDistance(_bodyA->local2World(_anchr2)), - _stiffness, _damping); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -Vec2 PhysicsJointSpring::getAnchr1() const -{ - AX_PJOINT_CACHE_READ(_anchr1); - return PhysicsHelper::cpv2vec2(cpDampedSpringGetAnchorA(_cpConstraints.front())); -} - -void PhysicsJointSpring::setAnchr1(const Vec2& anchr) -{ - AX_PJOINT_CACHE_WRITE2(_anchr1, cpDampedSpringSetAnchorA, anchr, PhysicsHelper::vec22cpv(anchr)); -} - -Vec2 PhysicsJointSpring::getAnchr2() const -{ - AX_PJOINT_CACHE_READ(_anchr2); - return PhysicsHelper::cpv2vec2(cpDampedSpringGetAnchorB(_cpConstraints.front())); -} - -void PhysicsJointSpring::setAnchr2(const Vec2& anchr) -{ - AX_PJOINT_CACHE_WRITE2(_anchr2, cpDampedSpringSetAnchorB, anchr, PhysicsHelper::vec22cpv(anchr)); -} - -float PhysicsJointSpring::getRestLength() const -{ - AX_PJOINT_CACHE_READ(_restLength); - return PhysicsHelper::cpfloat2float(cpDampedSpringGetRestLength(_cpConstraints.front())); -} - -void PhysicsJointSpring::setRestLength(float restLength) -{ - AX_PJOINT_CACHE_WRITE(_restLength, cpDampedSpringSetRestLength, restLength); -} - -float PhysicsJointSpring::getStiffness() const -{ - AX_PJOINT_CACHE_READ(_stiffness); - return PhysicsHelper::cpfloat2float(cpDampedSpringGetStiffness(_cpConstraints.front())); -} - -void PhysicsJointSpring::setStiffness(float stiffness) -{ - AX_PJOINT_CACHE_WRITE(_stiffness, cpDampedSpringSetStiffness, stiffness); -} - -float PhysicsJointSpring::getDamping() const -{ - AX_PJOINT_CACHE_READ(_damping); - return PhysicsHelper::cpfloat2float(cpDampedSpringGetDamping(_cpConstraints.front())); -} - -void PhysicsJointSpring::setDamping(float damping) -{ - AX_PJOINT_CACHE_WRITE(_damping, cpDampedSpringSetDamping, damping); -} - -PhysicsJointGroove* PhysicsJointGroove::construct(PhysicsBody* a, - PhysicsBody* b, - const Vec2& grooveA, - const Vec2& grooveB, - const Vec2& anchr2) -{ - auto joint = new PhysicsJointGroove(); - - if (joint->init(a, b)) - { - joint->_grooveA = grooveA; - joint->_grooveB = grooveB; - joint->_anchr2 = anchr2; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointGroove::createConstraints() -{ - do - { - auto joint = cpGrooveJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), PhysicsHelper::vec22cpv(_grooveA), - PhysicsHelper::vec22cpv(_grooveB), PhysicsHelper::vec22cpv(_anchr2)); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -Vec2 PhysicsJointGroove::getGrooveA() const -{ - AX_PJOINT_CACHE_READ(_grooveA); - return PhysicsHelper::cpv2vec2(cpGrooveJointGetGrooveA(_cpConstraints.front())); -} - -void PhysicsJointGroove::setGrooveA(const Vec2& grooveA) -{ - AX_PJOINT_CACHE_WRITE2(_grooveA, cpGrooveJointSetGrooveA, grooveA, PhysicsHelper::vec22cpv(grooveA)); -} - -Vec2 PhysicsJointGroove::getGrooveB() const -{ - AX_PJOINT_CACHE_READ(_grooveB); - return PhysicsHelper::cpv2vec2(cpGrooveJointGetGrooveB(_cpConstraints.front())); -} - -void PhysicsJointGroove::setGrooveB(const Vec2& grooveB) -{ - AX_PJOINT_CACHE_WRITE2(_grooveB, cpGrooveJointSetGrooveB, grooveB, PhysicsHelper::vec22cpv(grooveB)); -} - -Vec2 PhysicsJointGroove::getAnchr2() const -{ - AX_PJOINT_CACHE_READ(_anchr2); - return PhysicsHelper::cpv2vec2(cpGrooveJointGetAnchorB(_cpConstraints.front())); -} - -void PhysicsJointGroove::setAnchr2(const Vec2& anchr2) -{ - AX_PJOINT_CACHE_WRITE2(_anchr2, cpGrooveJointSetAnchorB, anchr2, PhysicsHelper::vec22cpv(anchr2)); -} - -PhysicsJointRotarySpring* PhysicsJointRotarySpring::construct(PhysicsBody* a, - PhysicsBody* b, - float stiffness, - float damping) -{ - auto joint = new PhysicsJointRotarySpring(); - - if (joint->init(a, b)) - { - joint->_stiffness = stiffness; - joint->_damping = damping; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointRotarySpring::createConstraints() -{ - do - { - auto joint = cpDampedRotarySpringNew(_bodyA->getCPBody(), _bodyB->getCPBody(), - _bodyB->getRotation() - _bodyA->getRotation(), _stiffness, _damping); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointRotarySpring::getRestAngle() const -{ - AX_PJOINT_CACHE_READ(_restAngle); - return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetRestAngle(_cpConstraints.front())); -} - -void PhysicsJointRotarySpring::setRestAngle(float restAngle) -{ - AX_PJOINT_CACHE_WRITE(_restAngle, cpDampedRotarySpringSetRestAngle, restAngle); -} - -float PhysicsJointRotarySpring::getStiffness() const -{ - AX_PJOINT_CACHE_READ(_stiffness); - return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetStiffness(_cpConstraints.front())); -} - -void PhysicsJointRotarySpring::setStiffness(float stiffness) -{ - AX_PJOINT_CACHE_WRITE(_stiffness, cpDampedRotarySpringSetStiffness, stiffness); -} - -float PhysicsJointRotarySpring::getDamping() const -{ - AX_PJOINT_CACHE_READ(_damping); - return PhysicsHelper::cpfloat2float(cpDampedRotarySpringGetDamping(_cpConstraints.front())); -} - -void PhysicsJointRotarySpring::setDamping(float damping) -{ - AX_PJOINT_CACHE_WRITE(_damping, cpDampedRotarySpringSetDamping, damping); -} - -PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::construct(PhysicsBody* a, PhysicsBody* b, float min, float max) -{ - auto joint = new PhysicsJointRotaryLimit(); - - if (joint->init(a, b)) - { - joint->_min = min; - joint->_max = max; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -PhysicsJointRotaryLimit* PhysicsJointRotaryLimit::construct(PhysicsBody* a, PhysicsBody* b) -{ - return construct(a, b, 0.0f, 0.0f); -} - -bool PhysicsJointRotaryLimit::createConstraints() -{ - do - { - auto joint = cpRotaryLimitJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _min, _max); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointRotaryLimit::getMin() const -{ - AX_PJOINT_CACHE_READ(_min); - return PhysicsHelper::cpfloat2float(cpRotaryLimitJointGetMin(_cpConstraints.front())); -} - -void PhysicsJointRotaryLimit::setMin(float min) -{ - AX_PJOINT_CACHE_WRITE(_min, cpRotaryLimitJointSetMin, min); -} - -float PhysicsJointRotaryLimit::getMax() const -{ - AX_PJOINT_CACHE_READ(_max); - return PhysicsHelper::cpfloat2float(cpRotaryLimitJointGetMax(_cpConstraints.front())); -} - -void PhysicsJointRotaryLimit::setMax(float max) -{ - AX_PJOINT_CACHE_WRITE(_max, cpRotaryLimitJointSetMax, max); -} - -PhysicsJointRatchet* PhysicsJointRatchet::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratchet) -{ - auto joint = new PhysicsJointRatchet(); - - if (joint->init(a, b)) - { - joint->_phase = phase; - joint->_ratchet = ratchet; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointRatchet::createConstraints() -{ - do - { - auto joint = - cpRatchetJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _phase, PhysicsHelper::cpfloat2float(_ratchet)); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointRatchet::getAngle() const -{ - AX_PJOINT_CACHE_READ(_angle); - return PhysicsHelper::cpfloat2float(cpRatchetJointGetAngle(_cpConstraints.front())); -} - -void PhysicsJointRatchet::setAngle(float angle) -{ - AX_PJOINT_CACHE_WRITE(_angle, cpRatchetJointSetAngle, angle); -} - -float PhysicsJointRatchet::getPhase() const -{ - AX_PJOINT_CACHE_READ(_phase); - return PhysicsHelper::cpfloat2float(cpRatchetJointGetPhase(_cpConstraints.front())); -} - -void PhysicsJointRatchet::setPhase(float phase) -{ - AX_PJOINT_CACHE_WRITE(_phase, cpRatchetJointSetPhase, phase); -} - -float PhysicsJointRatchet::getRatchet() const -{ - AX_PJOINT_CACHE_READ(_ratchet); - return PhysicsHelper::cpfloat2float(cpRatchetJointGetRatchet(_cpConstraints.front())); -} - -void PhysicsJointRatchet::setRatchet(float ratchet) -{ - AX_PJOINT_CACHE_WRITE(_ratchet, cpRatchetJointSetRatchet, ratchet); -} - -PhysicsJointGear* PhysicsJointGear::construct(PhysicsBody* a, PhysicsBody* b, float phase, float ratio) -{ - auto joint = new PhysicsJointGear(); - - if (joint->init(a, b)) - { - joint->_phase = phase; - joint->_ratio = ratio; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointGear::createConstraints() -{ - do - { - auto joint = cpGearJointNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _phase, _ratio); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointGear::getPhase() const -{ - AX_PJOINT_CACHE_READ(_phase); - return PhysicsHelper::cpfloat2float(cpGearJointGetPhase(_cpConstraints.front())); -} - -void PhysicsJointGear::setPhase(float phase) -{ - AX_PJOINT_CACHE_WRITE(_phase, cpGearJointSetPhase, phase); -} - -float PhysicsJointGear::getRatio() const -{ - AX_PJOINT_CACHE_READ(_ratio); - return PhysicsHelper::cpfloat2float(cpGearJointGetRatio(_cpConstraints.front())); -} - -void PhysicsJointGear::setRatio(float ratio) -{ - AX_PJOINT_CACHE_WRITE(_ratio, cpGearJointSetRatio, ratio); -} - -PhysicsJointMotor* PhysicsJointMotor::construct(PhysicsBody* a, PhysicsBody* b, float rate) -{ - auto joint = new PhysicsJointMotor(); - - if (joint->init(a, b)) - { - joint->_rate = rate; - - return joint; - } - - AX_SAFE_DELETE(joint); - return nullptr; -} - -bool PhysicsJointMotor::createConstraints() -{ - do - { - auto joint = cpSimpleMotorNew(_bodyA->getCPBody(), _bodyB->getCPBody(), _rate); - - AX_BREAK_IF(joint == nullptr); - _cpConstraints.emplace_back(joint); - - return true; - } while (false); - - return false; -} - -float PhysicsJointMotor::getRate() const -{ - AX_PJOINT_CACHE_READ(_rate); - return PhysicsHelper::cpfloat2float(cpSimpleMotorGetRate(_cpConstraints.front())); -} - -void PhysicsJointMotor::setRate(float rate) -{ - AX_PJOINT_CACHE_WRITE(_rate, cpSimpleMotorSetRate, rate); -} - -} -#endif // AX_ENABLE_PHYSICS diff --git a/core/physics/PhysicsShape.cpp b/core/physics/PhysicsShape.cpp deleted file mode 100644 index 6abaf180e61b..000000000000 --- a/core/physics/PhysicsShape.cpp +++ /dev/null @@ -1,980 +0,0 @@ -/**************************************************************************** - Copyright (c) 2013-2016 Chukong Technologies Inc. - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "physics/PhysicsShape.h" -#if defined(AX_ENABLE_PHYSICS) - -# include -# include -# include - -# include "chipmunk/chipmunk.h" -# include "chipmunk/chipmunk_unsafe.h" - -# include "physics/PhysicsBody.h" -# include "physics/PhysicsWorld.h" -# include "physics/PhysicsHelper.h" - -namespace ax -{ -extern const float PHYSICS_INFINITY; -static cpBody* s_sharedBody = nullptr; - -PhysicsShape::PhysicsShape() - : _body(nullptr) - , _type(Type::UNKNOWN) - , _area(0.0f) - , _mass(0.0f) - , _moment(0.0f) - , _sensor(false) - , _scaleX(1.0f) - , _scaleY(1.0f) - , _newScaleX(1.0f) - , _newScaleY(1.0f) - , _tag(0) - , _categoryBitmask(UINT_MAX) - , _collisionBitmask(UINT_MAX) - , _contactTestBitmask(0) - , _group(0) -{ - if (s_sharedBody == nullptr) - { - s_sharedBody = cpBodyNewStatic(); - } -} - -PhysicsShape::~PhysicsShape() -{ - for (auto&& shape : _cpShapes) - { - cpShapeFree(shape); - } -} - -void PhysicsShape::setMass(float mass) -{ - if (mass < 0) - { - return; - } - - if (_body) - { - _body->addMass(-_mass); - _body->addMass(mass); - }; - - _mass = mass; -} - -void PhysicsShape::setMoment(float moment) -{ - if (moment < 0) - { - return; - } - - if (_body) - { - _body->addMoment(-_moment); - _body->addMoment(moment); - }; - - _moment = moment; -} - -void PhysicsShape::setMaterial(const PhysicsMaterial& material) -{ - setDensity(material.density); - setRestitution(material.restitution); - setFriction(material.friction); -} - -void PhysicsShape::setScale(float scaleX, float scaleY) -{ - if (std::abs(_scaleX - scaleX) > FLT_EPSILON || std::abs(_scaleY - scaleY) > FLT_EPSILON) - { - if (_type == Type::CIRCLE && scaleX != scaleY) - { - AXLOGD("PhysicsShapeCircle WARNING: CANNOT support setScale with different x and y"); - return; - } - _newScaleX = scaleX; - _newScaleY = scaleY; - - updateScale(); - - // re-calculate area and mass - _area = calculateArea(); - _mass = _material.density * _area; - _moment = calculateDefaultMoment(); - } -} - -void PhysicsShape::updateScale() -{ - _scaleX = _newScaleX; - _scaleY = _newScaleY; -} - -void PhysicsShape::addShape(cpShape* shape) -{ - if (shape) - { - cpShapeSetUserData(shape, this); - cpShapeSetFilter(shape, cpShapeFilterNew(_group, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - _cpShapes.emplace_back(shape); - } -} - -PhysicsShapeCircle::PhysicsShapeCircle() {} - -PhysicsShapeCircle::~PhysicsShapeCircle() {} - -PhysicsShapeBox::PhysicsShapeBox() {} - -PhysicsShapeBox::~PhysicsShapeBox() {} - -PhysicsShapePolygon::PhysicsShapePolygon() {} - -PhysicsShapePolygon::~PhysicsShapePolygon() {} - -PhysicsShapeEdgeBox::PhysicsShapeEdgeBox() {} - -PhysicsShapeEdgeBox::~PhysicsShapeEdgeBox() {} - -PhysicsShapeEdgeChain::PhysicsShapeEdgeChain() {} - -PhysicsShapeEdgeChain::~PhysicsShapeEdgeChain() {} - -PhysicsShapeEdgePolygon::PhysicsShapeEdgePolygon() {} - -PhysicsShapeEdgePolygon::~PhysicsShapeEdgePolygon() {} - -PhysicsShapeEdgeSegment::PhysicsShapeEdgeSegment() {} - -PhysicsShapeEdgeSegment::~PhysicsShapeEdgeSegment() {} - -void PhysicsShape::setDensity(float density) -{ - if (density < 0) - { - return; - } - - _material.density = density; - - if (_material.density == PHYSICS_INFINITY) - { - setMass(PHYSICS_INFINITY); - } - else if (_area > 0) - { - setMass(_material.density * _area); - } -} - -void PhysicsShape::setRestitution(float restitution) -{ - _material.restitution = restitution; - - for (cpShape* shape : _cpShapes) - { - cpShapeSetElasticity(shape, restitution); - } -} - -void PhysicsShape::setFriction(float friction) -{ - _material.friction = friction; - - for (cpShape* shape : _cpShapes) - { - cpShapeSetFriction(shape, friction); - } -} - -void PhysicsShape::setSensor(bool sensor) -{ - if (sensor != _sensor) - { - for (cpShape* shape : _cpShapes) - { - cpShapeSetSensor(shape, sensor); - } - _sensor = sensor; - } -} - -void PhysicsShape::recenterPoints(Vec2* points, int count, const Vec2& center) -{ - cpVect* cpvs = new cpVect[count]; - cpVect centroid = cpCentroidForPoly(count, cpvs); - for (int i = 0; i < count; i++) - { - cpvs[i] = cpvsub(cpvs[i], centroid); - } - PhysicsHelper::cpvs2points(cpvs, points, count); - delete[] cpvs; - - if (center != Vec2::ZERO) - { - for (int i = 0; i < count; ++i) - { - points[i] += center; - } - } -} - -Vec2 PhysicsShape::getPolygonCenter(const Vec2* points, int count) -{ - cpVect* cpvs = new cpVect[count]; - cpVect center = cpCentroidForPoly(count, PhysicsHelper::points2cpvs(points, cpvs, count)); - delete[] cpvs; - - return PhysicsHelper::cpv2vec2(center); -} - -void PhysicsShape::setBody(PhysicsBody* body) -{ - // already added - if (body && _body == body) - { - return; - } - - if (_body) - { - _body->removeShape(this); - } - - for (auto&& shape : _cpShapes) - { - cpShapeSetBody(shape, body == nullptr ? s_sharedBody : body->_cpBody); - } - _body = body; -} - -// PhysicsShapeCircle -PhysicsShapeCircle* PhysicsShapeCircle::create(float radius, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /* = Vec2(0, 0)*/) -{ - PhysicsShapeCircle* shape = new PhysicsShapeCircle(); - if (shape->init(radius, material, offset)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapeCircle::init(float radius, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /*= Vec2(0, 0)*/) -{ - do - { - _type = Type::CIRCLE; - - auto shape = cpCircleShapeNew(s_sharedBody, radius, PhysicsHelper::vec22cpv(offset)); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - - addShape(shape); - - _area = calculateArea(); - _mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * _area; - _moment = calculateDefaultMoment(); - - setMaterial(material); - return true; - } while (false); - - return false; -} - -float PhysicsShapeCircle::calculateArea(float radius) -{ - return PhysicsHelper::cpfloat2float(cpAreaForCircle(0, radius)); -} - -float PhysicsShapeCircle::calculateMoment(float mass, float radius, const Vec2& offset) -{ - return mass == PHYSICS_INFINITY - ? PHYSICS_INFINITY - : PhysicsHelper::cpfloat2float(cpMomentForCircle(mass, 0, radius, PhysicsHelper::vec22cpv(offset))); -} - -float PhysicsShapeCircle::calculateArea() -{ - return PhysicsHelper::cpfloat2float(cpAreaForCircle(0, cpCircleShapeGetRadius(_cpShapes.front()))); -} - -float PhysicsShapeCircle::calculateDefaultMoment() -{ - auto shape = _cpShapes.front(); - - return _mass == PHYSICS_INFINITY ? PHYSICS_INFINITY - : PhysicsHelper::cpfloat2float(cpMomentForCircle( - _mass, 0, cpCircleShapeGetRadius(shape), cpCircleShapeGetOffset(shape))); -} - -float PhysicsShapeCircle::getRadius() const -{ - return PhysicsHelper::cpfloat2float(cpCircleShapeGetRadius(_cpShapes.front())); -} - -Vec2 PhysicsShapeCircle::getOffset() -{ - return PhysicsHelper::cpv2vec2(cpCircleShapeGetOffset(_cpShapes.front())); -} - -void PhysicsShapeCircle::updateScale() -{ - cpFloat factor = std::abs(_newScaleX / _scaleX); - - cpShape* shape = _cpShapes.front(); - cpVect v = cpCircleShapeGetOffset(shape); - v = cpvmult(v, factor); - cpCircleShapeSetOffset(shape, v); - - cpCircleShapeSetRadius(shape, cpCircleShapeGetRadius(shape) * factor); - - PhysicsShape::updateScale(); -} - -// PhysicsShapeEdgeSegment -PhysicsShapeEdgeSegment* PhysicsShapeEdgeSegment::create(const Vec2& a, - const Vec2& b, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - PhysicsShapeEdgeSegment* shape = new PhysicsShapeEdgeSegment(); - if (shape->init(a, b, material, border)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapeEdgeSegment::init(const Vec2& a, - const Vec2& b, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - do - { - _type = Type::EDGESEGMENT; - - auto shape = cpSegmentShapeNew(s_sharedBody, PhysicsHelper::vec22cpv(a), PhysicsHelper::vec22cpv(b), border); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - - addShape(shape); - - _mass = PHYSICS_INFINITY; - _moment = PHYSICS_INFINITY; - - setMaterial(material); - - return true; - } while (false); - - return false; -} - -Vec2 PhysicsShapeEdgeSegment::getPointA() const -{ - return PhysicsHelper::cpv2vec2(cpSegmentShapeGetA(_cpShapes.front())); -} - -Vec2 PhysicsShapeEdgeSegment::getPointB() const -{ - return PhysicsHelper::cpv2vec2(cpSegmentShapeGetB(_cpShapes.front())); -} - -Vec2 PhysicsShapeEdgeSegment::getCenter() -{ - auto a = PhysicsHelper::cpv2vec2(cpSegmentShapeGetA(_cpShapes.front())); - auto b = PhysicsHelper::cpv2vec2(cpSegmentShapeGetB(_cpShapes.front())); - return (a + b) / 2; -} - -void PhysicsShapeEdgeSegment::updateScale() -{ - cpFloat factorX = _newScaleX / _scaleX; - cpFloat factorY = _newScaleY / _scaleY; - - cpShape* shape = _cpShapes.front(); - cpVect a = cpSegmentShapeGetA(shape); - a.x *= factorX; - a.y *= factorY; - cpVect b = cpSegmentShapeGetB(shape); - b.x *= factorX; - b.y *= factorY; - cpSegmentShapeSetEndpoints(shape, a, b); - - PhysicsShape::updateScale(); -} - -// PhysicsShapeBox -PhysicsShapeBox* PhysicsShapeBox::create(const Vec2& size, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /* = Vec2(0, 0)*/, - float radius /* = 0.0f*/) -{ - PhysicsShapeBox* shape = new PhysicsShapeBox(); - if (shape->init(size, material, offset, radius)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapeBox::init(const Vec2& size, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /*= Vec2(0, 0)*/, - float radius /* = 0.0f*/) -{ - do - { - _type = Type::BOX; - - auto wh = PhysicsHelper::vec22cpv(size); - cpVect vec[4] = {{-wh.x / 2.0f, -wh.y / 2.0f}, - {-wh.x / 2.0f, wh.y / 2.0f}, - {wh.x / 2.0f, wh.y / 2.0f}, - {wh.x / 2.0f, -wh.y / 2.0f}}; - - cpTransform transform = cpTransformTranslate(PhysicsHelper::vec22cpv(offset)); - - auto shape = cpPolyShapeNew(s_sharedBody, 4, vec, transform, radius); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - - addShape(shape); - - _area = calculateArea(); - _mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * _area; - _moment = calculateDefaultMoment(); - - setMaterial(material); - - return true; - } while (false); - - return false; -} - -Vec2 PhysicsShapeBox::getSize() const -{ - cpShape* shape = _cpShapes.front(); - return PhysicsHelper::cpv2vec2(cpv(cpvdist(cpPolyShapeGetVert(shape, 1), cpPolyShapeGetVert(shape, 2)), - cpvdist(cpPolyShapeGetVert(shape, 0), cpPolyShapeGetVert(shape, 1)))); -} - -// PhysicsShapePolygon -PhysicsShapePolygon* PhysicsShapePolygon::create(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /* = Vec2(0, 0)*/, - float radius /* = 0.0f*/) -{ - PhysicsShapePolygon* shape = new PhysicsShapePolygon(); - if (shape->init(points, count, material, offset, radius)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapePolygon::init(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - const Vec2& offset /* = Vec2(0, 0)*/, - float radius /* = 0.0f*/) -{ - do - { - _type = Type::POLYGON; - - auto vecs = new cpVect[count]; - PhysicsHelper::points2cpvs(points, vecs, count); // count = cpConvexHull((int)count, vecs, nullptr, nullptr, - // 0); - cpTransform transform = cpTransformTranslate(PhysicsHelper::vec22cpv(offset)); - auto shape = cpPolyShapeNew(s_sharedBody, count, vecs, transform, radius); - AX_SAFE_DELETE_ARRAY(vecs); - - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - - addShape(shape); - - _area = calculateArea(); - _mass = material.density == PHYSICS_INFINITY ? PHYSICS_INFINITY : material.density * _area; - _moment = calculateDefaultMoment(); - - setMaterial(material); - - return true; - } while (false); - - return false; -} - -float PhysicsShapePolygon::calculateArea(const Vec2* points, int count) -{ - cpVect* vecs = new cpVect[count]; - PhysicsHelper::points2cpvs(points, vecs, count); - float area = PhysicsHelper::cpfloat2float(cpAreaForPoly(count, vecs, 0.0f)); - AX_SAFE_DELETE_ARRAY(vecs); - - return area; -} - -float PhysicsShapePolygon::calculateMoment(float mass, const Vec2* points, int count, const Vec2& offset, float radius) -{ - cpVect* vecs = new cpVect[count]; - PhysicsHelper::points2cpvs(points, vecs, count); - float moment = - mass == PHYSICS_INFINITY - ? PHYSICS_INFINITY - : PhysicsHelper::cpfloat2float(cpMomentForPoly(mass, count, vecs, PhysicsHelper::vec22cpv(offset), radius)); - AX_SAFE_DELETE_ARRAY(vecs); - - return moment; -} - -float PhysicsShapePolygon::calculateArea() -{ - auto shape = _cpShapes.front(); - int count = cpPolyShapeGetCount(shape); - cpVect* vecs = new cpVect[count]; - for (int i = 0; i < count; ++i) - vecs[i] = cpPolyShapeGetVert(shape, i); - float area = PhysicsHelper::cpfloat2float(cpAreaForPoly(count, vecs, cpPolyShapeGetRadius(shape))); - AX_SAFE_DELETE_ARRAY(vecs); - return area; -} - -float PhysicsShapePolygon::calculateDefaultMoment() -{ - if (_mass == PHYSICS_INFINITY) - { - return PHYSICS_INFINITY; - } - else - { - auto shape = _cpShapes.front(); - int count = cpPolyShapeGetCount(shape); - cpVect* vecs = new cpVect[count]; - for (int i = 0; i < count; ++i) - vecs[i] = cpPolyShapeGetVert(shape, i); - float moment = - PhysicsHelper::cpfloat2float(cpMomentForPoly(_mass, count, vecs, cpvzero, cpPolyShapeGetRadius(shape))); - AX_SAFE_DELETE_ARRAY(vecs); - return moment; - } -} - -Vec2 PhysicsShapePolygon::getPoint(int i) const -{ - return PhysicsHelper::cpv2vec2(cpPolyShapeGetVert(_cpShapes.front(), i)); -} - -void PhysicsShapePolygon::getPoints(Vec2* outPoints) const -{ - auto shape = _cpShapes.front(); - int count = cpPolyShapeGetCount(shape); - cpVect* vecs = new cpVect[count]; - for (int i = 0; i < count; ++i) - vecs[i] = cpPolyShapeGetVert(shape, i); - PhysicsHelper::cpvs2points(vecs, outPoints, count); - AX_SAFE_DELETE_ARRAY(vecs); -} - -int PhysicsShapePolygon::getPointsCount() const -{ - return cpPolyShapeGetCount(_cpShapes.front()); -} - -Vec2 PhysicsShapePolygon::getCenter() -{ - auto shape = _cpShapes.front(); - int count = cpPolyShapeGetCount(shape); - cpVect* vecs = new cpVect[count]; - for (int i = 0; i < count; ++i) - vecs[i] = cpPolyShapeGetVert(shape, i); - - Vec2 center = PhysicsHelper::cpv2vec2(cpCentroidForPoly(count, vecs)); - AX_SAFE_DELETE_ARRAY(vecs); - - return center; -} - -void PhysicsShapePolygon::updateScale() -{ - cpFloat factorX = _newScaleX / _scaleX; - cpFloat factorY = _newScaleY / _scaleY; - - auto shape = _cpShapes.front(); - int count = cpPolyShapeGetCount(shape); - cpVect* vects = new cpVect[count]; - for (int i = 0; i < count; ++i) - vects[i] = cpPolyShapeGetVert(shape, i); - - for (int i = 0; i < count; ++i) - { - vects[i].x *= factorX; - vects[i].y *= factorY; - } - - // convert hole to clockwise - if (factorX * factorY < 0) - { - for (int i = 0; i < count / 2; ++i) - { - cpVect v = vects[i]; - vects[i] = vects[count - i - 1]; - vects[count - i - 1] = v; - } - } - - cpPolyShapeSetVertsRaw(shape, count, vects); - AX_SAFE_DELETE_ARRAY(vects); - - PhysicsShape::updateScale(); -} - -// PhysicsShapeEdgeBox -PhysicsShapeEdgeBox* PhysicsShapeEdgeBox::create(const Vec2& size, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/, - const Vec2& offset /* = Vec2(0, 0)*/) -{ - PhysicsShapeEdgeBox* shape = new PhysicsShapeEdgeBox(); - if (shape->init(size, material, border, offset)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapeEdgeBox::init(const Vec2& size, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/, - const Vec2& offset /*= Vec2(0, 0)*/) -{ - do - { - _type = Type::EDGEBOX; - - cpVect vec[4] = {}; - vec[0] = PhysicsHelper::vec22cpv(Vec2(-size.width / 2 + offset.x, -size.height / 2 + offset.y)); - vec[1] = PhysicsHelper::vec22cpv(Vec2(+size.width / 2 + offset.x, -size.height / 2 + offset.y)); - vec[2] = PhysicsHelper::vec22cpv(Vec2(+size.width / 2 + offset.x, +size.height / 2 + offset.y)); - vec[3] = PhysicsHelper::vec22cpv(Vec2(-size.width / 2 + offset.x, +size.height / 2 + offset.y)); - - int i = 0; - for (; i < 4; ++i) - { - auto shape = cpSegmentShapeNew(s_sharedBody, vec[i], vec[(i + 1) % 4], border); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - addShape(shape); - } - AX_BREAK_IF(i < 4); - - _mass = PHYSICS_INFINITY; - _moment = PHYSICS_INFINITY; - - setMaterial(material); - - return true; - } while (false); - - return false; -} - -// PhysicsShapeEdgeBox -PhysicsShapeEdgePolygon* PhysicsShapeEdgePolygon::create(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - PhysicsShapeEdgePolygon* shape = new PhysicsShapeEdgePolygon(); - if (shape->init(points, count, material, border)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -bool PhysicsShapeEdgePolygon::init(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - cpVect* vec = nullptr; - do - { - _type = Type::EDGEPOLYGON; - - vec = new cpVect[count]; - PhysicsHelper::points2cpvs(points, vec, count); - - int i = 0; - for (; i < count; ++i) - { - auto shape = cpSegmentShapeNew(s_sharedBody, vec[i], vec[(i + 1) % count], border); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - addShape(shape); - } - AX_SAFE_DELETE_ARRAY(vec); - - AX_BREAK_IF(i < count); - - _mass = PHYSICS_INFINITY; - _moment = PHYSICS_INFINITY; - - setMaterial(material); - - return true; - } while (false); - - AX_SAFE_DELETE_ARRAY(vec); - - return false; -} - -Vec2 PhysicsShapeEdgePolygon::getCenter() -{ - int count = (int)_cpShapes.size(); - cpVect* points = new cpVect[count]; - int i = 0; - for (auto&& shape : _cpShapes) - { - points[i++] = cpSegmentShapeGetA(shape); - } - - Vec2 center = PhysicsHelper::cpv2vec2(cpCentroidForPoly(count, points)); - delete[] points; - - return center; -} - -void PhysicsShapeEdgePolygon::getPoints(ax::Vec2* outPoints) const -{ - int i = 0; - for (auto&& shape : _cpShapes) - { - outPoints[i++] = PhysicsHelper::cpv2vec2(cpSegmentShapeGetA(shape)); - } -} - -int PhysicsShapeEdgePolygon::getPointsCount() const -{ - return static_cast(_cpShapes.size()); -} - -// PhysicsShapeEdgeChain -PhysicsShapeEdgeChain* PhysicsShapeEdgeChain::create(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - PhysicsShapeEdgeChain* shape = new PhysicsShapeEdgeChain(); - if (shape->init(points, count, material, border)) - { - shape->autorelease(); - return shape; - } - - AX_SAFE_DELETE(shape); - return nullptr; -} - -void PhysicsShapeEdgePolygon::updateScale() -{ - cpFloat factorX = _newScaleX / _scaleX; - cpFloat factorY = _newScaleY / _scaleY; - - for (auto&& shape : _cpShapes) - { - cpVect a = cpSegmentShapeGetA(shape); - a.x *= factorX; - a.y *= factorY; - cpVect b = cpSegmentShapeGetB(shape); - b.x *= factorX; - b.y *= factorY; - cpSegmentShapeSetEndpoints(shape, a, b); - } - - PhysicsShape::updateScale(); -} - -bool PhysicsShapeEdgeChain::init(const Vec2* points, - int count, - const PhysicsMaterial& material /* = MaterialDefault*/, - float border /* = 1*/) -{ - cpVect* vec = nullptr; - do - { - _type = Type::EDGECHAIN; - - vec = new cpVect[count]; - PhysicsHelper::points2cpvs(points, vec, count); - - int i = 0; - for (; i < count - 1; ++i) - { - auto shape = cpSegmentShapeNew(s_sharedBody, vec[i], vec[i + 1], border); - AX_BREAK_IF(shape == nullptr); - cpShapeSetUserData(shape, this); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - addShape(shape); - } - AX_SAFE_DELETE_ARRAY(vec); - AX_BREAK_IF(i < count - 1); - - _mass = PHYSICS_INFINITY; - _moment = PHYSICS_INFINITY; - - setMaterial(material); - - return true; - } while (false); - - AX_SAFE_DELETE_ARRAY(vec); - - return false; -} - -Vec2 PhysicsShapeEdgeChain::getCenter() -{ - int count = (int)_cpShapes.size() + 1; - cpVect* points = new cpVect[count]; - int i = 0; - for (auto&& shape : _cpShapes) - { - points[i++] = cpSegmentShapeGetA(shape); - } - - points[i++] = cpSegmentShapeGetB(_cpShapes.back()); - - Vec2 center = PhysicsHelper::cpv2vec2(cpCentroidForPoly(count, points)); - delete[] points; - - return center; -} - -void PhysicsShapeEdgeChain::getPoints(Vec2* outPoints) const -{ - int i = 0; - for (auto&& shape : _cpShapes) - { - outPoints[i++] = PhysicsHelper::cpv2vec2(cpSegmentShapeGetA(shape)); - } - - outPoints[i++] = PhysicsHelper::cpv2vec2(cpSegmentShapeGetB(_cpShapes.back())); -} - -int PhysicsShapeEdgeChain::getPointsCount() const -{ - return static_cast(_cpShapes.size() + 1); -} - -void PhysicsShapeEdgeChain::updateScale() -{ - cpFloat factorX = _newScaleX / _scaleX; - cpFloat factorY = _newScaleY / _scaleY; - - for (auto&& shape : _cpShapes) - { - cpVect a = cpSegmentShapeGetA(shape); - a.x *= factorX; - a.y *= factorY; - cpVect b = cpSegmentShapeGetB(shape); - b.x *= factorX; - b.y *= factorY; - cpSegmentShapeSetEndpoints(shape, a, b); - } - - PhysicsShape::updateScale(); -} - -void PhysicsShape::setGroup(int group) -{ - if (group < 0) - { - for (auto&& shape : _cpShapes) - { - cpShapeSetFilter(shape, cpShapeFilterNew(group, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - } - } - - _group = group; -} - -bool PhysicsShape::containsPoint(const Vec2& point) const -{ - for (auto&& shape : _cpShapes) - { - if (cpShapePointQuery(shape, PhysicsHelper::vec22cpv(point), nullptr) < 0) - { - return true; - } - } - - return false; -} - -} - -#endif // defined(AX_ENABLE_PHYSICS) diff --git a/core/physics/cpCompat62.h b/core/physics/cpCompat62.h deleted file mode 100644 index 130252687838..000000000000 --- a/core/physics/cpCompat62.h +++ /dev/null @@ -1,120 +0,0 @@ -/* Copyright (c) 2013 Scott Lembcke and Howling Moon Software - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "chipmunk/chipmunk.h" - -// -// Body -// -inline cpVect cpBodyGetVelAtWorldPoint(const cpBody* body) -{ - return cpBodyGetVelocityAtWorldPoint(body); -} -inline cpVect cpBodyGetVelAtLocalPoint(const cpBody* body) -{ - return cpBodyGetVelocityAtLocalPoint(body); -} -inline cpVect cpBodyGetVel(const cpBody* body) -{ - return cpBodyGetVelocity(body); -} -inline void cpBodySetVel(cpBody* body, cpVect velocity) -{ - cpBodySetVelocity(body, velocity); -} -inline cpVect cpBodyGetPos(const cpBody* body) -{ - return cpBodyGetPosition(body); -} -inline void cpBodySetPos(cpBody* body, cpVect pos) -{ - cpBodySetPosition(body, pos); -} -inline cpVect cpBodyGetRot(const cpBody* body) -{ - return cpBodyGetRotation(body); -} -inline cpFloat cpBodyGetAngVel(const cpBody* body) -{ - return cpBodyGetAngularVelocity(body); -} -inline void cpBodySetAngVel(cpBody* body, cpFloat angularVelocity) -{ - cpBodySetAngularVelocity(body, angularVelocity); -} -inline cpVect cpBodyLocal2World(const cpBody* body, const cpVect point) -{ - return cpBodyLocalToWorld(body, point); -} -inline cpVect cpBodyWorld2Local(const cpBody* body, const cpVect point) -{ - return cpBodyWorldToLocal(body, point); -} -inline void cpBodyApplyImpulse(cpBody* body, const cpVect j, const cpVect r) -{ - cpBodyApplyImpulseAtWorldPoint(body, j, r); -} - -// -// Shapes -// -inline void cpShapeSetLayers(cpShape* shape, unsigned int layer) -{ - cpShapeFilter filter = cpShapeGetFilter(shape); - filter.mask = layer; - filter.categories = layer; - cpShapeSetFilter(shape, filter); -} -inline unsigned int cpShapeGetLayers(cpShape* shape) -{ - cpShapeFilter filter = cpShapeGetFilter(shape); - return filter.mask; -} -inline void cpShapeSetGroup(cpShape* shape, uintptr_t group) -{ - cpShapeFilter filter = cpShapeGetFilter(shape); - filter.group = group; - cpShapeSetFilter(shape, filter); -} -inline uintptr_t cpShapeGetGroup(cpShape* shape) -{ - cpShapeFilter filter = cpShapeGetFilter(shape); - return filter.group; -} -inline int cpPolyShapeGetNumVerts(const cpShape* shape) -{ - return cpPolyShapeGetCount(shape); -} -inline cpFloat cpShapeNearestPointQuery(cpShape* shape, cpVect p, cpPointQueryInfo* out) -{ - return cpShapePointQuery(shape, p, out); -} - -// -// Space -// -inline cpShape* cpSpaceAddStaticShape(cpSpace* space, cpShape* shape) -{ - return cpSpaceAddShape(space, shape); -} - diff --git a/core/renderer/CMakeLists.txt b/core/renderer/CMakeLists.txt deleted file mode 100644 index f6f14dd9c002..000000000000 --- a/core/renderer/CMakeLists.txt +++ /dev/null @@ -1,140 +0,0 @@ -set(_AX_RENDERER_HEADER - renderer/CallbackCommand.h - renderer/CustomCommand.h - renderer/GroupCommand.h - renderer/Material.h - renderer/MeshCommand.h - renderer/Pass.h - renderer/PipelineDescriptor.h - renderer/QuadCommand.h - renderer/RenderCommand.h - renderer/RenderCommandPool.h - renderer/Renderer.h - renderer/RenderState.h - renderer/Shaders.h - renderer/Technique.h - renderer/Texture2D.h - renderer/TextureAtlas.h - renderer/TextureCache.h - renderer/TextureCube.h - renderer/TrianglesCommand.h - - renderer/backend/Backend.h - renderer/backend/Buffer.h - renderer/backend/CommandBuffer.h - renderer/backend/DepthStencilState.h - renderer/backend/DriverBase.h - renderer/backend/Enums.h - renderer/backend/Macros.h - renderer/backend/PixelBufferDescriptor.h - renderer/backend/PixelFormatUtils.h - renderer/backend/Program.h - renderer/backend/ProgramManager.h - renderer/backend/ProgramState.h - renderer/backend/ProgramStateRegistry.h - renderer/backend/RenderPassDescriptor.h - renderer/backend/RenderPipeline.h - renderer/backend/RenderTarget.h - renderer/backend/ShaderCache.h - renderer/backend/ShaderModule.h - renderer/backend/Texture.h - renderer/backend/Types.h - renderer/backend/VertexLayout.h -) - -set(_AX_RENDERER_SRC - renderer/CallbackCommand.cpp - renderer/CustomCommand.cpp - renderer/GroupCommand.cpp - renderer/Material.cpp - renderer/MeshCommand.cpp - renderer/Pass.cpp - renderer/QuadCommand.cpp - renderer/RenderCommand.cpp - renderer/RenderState.cpp - renderer/Renderer.cpp - renderer/Technique.cpp - renderer/Texture2D.cpp - renderer/TextureAtlas.cpp - renderer/TextureCache.cpp - renderer/TextureCube.cpp - renderer/TrianglesCommand.cpp - renderer/Shaders.cpp - - renderer/backend/ProgramManager.cpp - renderer/backend/ProgramStateRegistry.cpp - - renderer/backend/CommandBuffer.cpp - renderer/backend/DepthStencilState.cpp - renderer/backend/DriverBase.cpp - renderer/backend/ShaderModule.cpp - renderer/backend/Texture.cpp - renderer/backend/PixelFormatUtils.cpp - renderer/backend/Types.cpp - renderer/backend/VertexLayout.cpp - renderer/backend/Program.cpp - renderer/backend/ProgramState.cpp - renderer/backend/ShaderCache.cpp - renderer/backend/RenderPassDescriptor.cpp -) - -if(ANDROID OR WINDOWS OR LINUX OR AX_USE_GL) - list(APPEND _AX_RENDERER_HEADER - renderer/backend/opengl/OpenGLState.h - renderer/backend/opengl/BufferGL.h - renderer/backend/opengl/CommandBufferGL.h - renderer/backend/opengl/CommandBufferGLES2.h - renderer/backend/opengl/DepthStencilStateGL.h - renderer/backend/opengl/DriverGL.h - renderer/backend/opengl/MacrosGL.h - renderer/backend/opengl/ProgramGL.h - renderer/backend/opengl/RenderPipelineGL.h - renderer/backend/opengl/RenderTargetGL.h - renderer/backend/opengl/ShaderModuleGL.h - renderer/backend/opengl/TextureGL.h - renderer/backend/opengl/UtilsGL.h - ) - - list(APPEND _AX_RENDERER_SRC - renderer/backend/opengl/OpenGLState.cpp - renderer/backend/opengl/BufferGL.cpp - renderer/backend/opengl/CommandBufferGL.cpp - renderer/backend/opengl/CommandBufferGLES2.cpp - renderer/backend/opengl/DepthStencilStateGL.cpp - renderer/backend/opengl/DriverGL.cpp - renderer/backend/opengl/ProgramGL.cpp - renderer/backend/opengl/RenderPipelineGL.cpp - renderer/backend/opengl/ShaderModuleGL.cpp - renderer/backend/opengl/TextureGL.cpp - renderer/backend/opengl/UtilsGL.cpp - renderer/backend/opengl/RenderTargetGL.cpp - ) -else() - list(APPEND _AX_RENDERER_HEADER - renderer/backend/metal/BufferMTL.h - renderer/backend/metal/BufferManager.h - renderer/backend/metal/CommandBufferMTL.h - renderer/backend/metal/RenderTargetMTL.h - renderer/backend/metal/DepthStencilStateMTL.h - renderer/backend/metal/DriverMTL.h - renderer/backend/metal/RenderPipelineMTL.h - renderer/backend/metal/ShaderModuleMTL.h - renderer/backend/metal/TextureMTL.h - renderer/backend/metal/UtilsMTL.h - renderer/backend/metal/ProgramMTL.h - ) - - list(APPEND _AX_RENDERER_SRC - renderer/backend/metal/BufferMTL.mm - renderer/backend/metal/BufferManager.mm - renderer/backend/metal/CommandBufferMTL.mm - renderer/backend/metal/RenderTargetMTL.mm - renderer/backend/metal/DepthStencilStateMTL.mm - renderer/backend/metal/DriverMTL.mm - renderer/backend/metal/RenderPipelineMTL.mm - renderer/backend/metal/ShaderModuleMTL.mm - renderer/backend/metal/TextureMTL.mm - renderer/backend/metal/UtilsMTL.mm - renderer/backend/metal/ProgramMTL.mm - ) -endif() diff --git a/core/renderer/backend/PixelBufferDescriptor.h b/core/renderer/backend/PixelBufferDescriptor.h deleted file mode 100644 index fde147c4f852..000000000000 --- a/core/renderer/backend/PixelBufferDescriptor.h +++ /dev/null @@ -1,24 +0,0 @@ -#pragma once -#include "base/Data.h" - -#include "Macros.h" -#include "Types.h" - -NS_AX_BACKEND_BEGIN - -struct PixelBufferDescriptor -{ - PixelBufferDescriptor() = default; - PixelBufferDescriptor(const PixelBufferDescriptor&) = default; - PixelBufferDescriptor(PixelBufferDescriptor&& rhs) noexcept - : _data(std::move(rhs._data)), _width(rhs._width), _height(rhs._height) - {} - - explicit operator bool() const { return !_data.isNull(); } - - Data _data; - int _width = 0; - int _height = 0; -}; - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/Program.cpp b/core/renderer/backend/Program.cpp deleted file mode 100644 index 9b9f6c0172f6..000000000000 --- a/core/renderer/backend/Program.cpp +++ /dev/null @@ -1,198 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "Program.h" -#include "ProgramManager.h" -#include "VertexLayout.h" - -NS_AX_BACKEND_BEGIN - -/* - * shader vertex layout setup functions - */ -struct VertexLayoutHelper -{ - static void setupDummy(Program*) {} - static void setupTexture(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - - /// a_position - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - /// a_texCoord - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, 2 * sizeof(float), false); - - vertexLayout->setStride(4 * sizeof(float)); - } - - static void setupSprite(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - - /// a_position - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - /// a_texCoord - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_C4B_T2F, texCoords), false); - - /// a_color - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, offsetof(V3F_C4B_T2F, colors), true); - vertexLayout->setStride(sizeof(V3F_C4B_T2F)); - } - - static void setupDrawNode(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V2F_C4B_T2F, texCoords), false); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, offsetof(V2F_C4B_T2F, colors), true); - - vertexLayout->setStride(sizeof(V2F_C4B_T2F)); - } - - static void setupDrawNode3D(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::UBYTE4, offsetof(V3F_C4B, colors), true); - - vertexLayout->setStride(sizeof(V3F_C4B)); - } - - static void setupSkyBox(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - auto attrNameLoc = program->getAttributeLocation(backend::ATTRIBUTE_NAME_POSITION); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, attrNameLoc, - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setStride(sizeof(Vec3)); - } - - static void setupPU3D(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_C4F, position), false); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_C4F, uv), false); - - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::FLOAT4, offsetof(V3F_T2F_C4F, color), false); - - vertexLayout->setStride(sizeof(V3F_T2F_C4F)); - } - - static void setupPos(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT2, 0, false); - vertexLayout->setStride(sizeof(Vec2)); - } - - static void setupPosColor(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_COLOR, program->getAttributeLocation(backend::Attribute::COLOR), - backend::VertexFormat::FLOAT4, offsetof(V3F_C4F, colors), false); - vertexLayout->setStride(sizeof(V3F_C4F)); - } - - static void setupTerrain3D(Program* program) - { - auto vertexLayout = program->getVertexLayout(); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_POSITION, - program->getAttributeLocation(backend::Attribute::POSITION), - backend::VertexFormat::FLOAT3, 0, false); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_TEXCOORD, - program->getAttributeLocation(backend::Attribute::TEXCOORD), - backend::VertexFormat::FLOAT2, offsetof(V3F_T2F_N3F, texcoord), false); - vertexLayout->setAttrib(backend::ATTRIBUTE_NAME_NORMAL, - program->getAttributeLocation(backend::Attribute::NORMAL), - backend::VertexFormat::FLOAT3, offsetof(V3F_T2F_N3F, normal), false); - vertexLayout->setStride(sizeof(V3F_T2F_N3F)); - } -}; -std::function Program::s_vertexLayoutSetupList[static_cast(VertexLayoutType::Count)] = { - VertexLayoutHelper::setupDummy, VertexLayoutHelper::setupPos, VertexLayoutHelper::setupTexture, - VertexLayoutHelper::setupSprite, VertexLayoutHelper::setupDrawNode, VertexLayoutHelper::setupDrawNode3D, - VertexLayoutHelper::setupSkyBox, VertexLayoutHelper::setupPU3D, VertexLayoutHelper::setupPosColor, - VertexLayoutHelper::setupTerrain3D}; - -Program::Program(std::string_view vs, std::string_view fs) - : _vertexShader(vs), _fragmentShader(fs), _vertexLayout(new VertexLayout()) -{} - -Program::~Program() -{ - delete _vertexLayout; -} - -void Program::setupVertexLayout(VertexLayoutType vlt) -{ - if (vlt < VertexLayoutType::Count) - s_vertexLayoutSetupList[static_cast(vlt)](this); -} - -Program* Program::getBuiltinProgram(uint32_t type) -{ - return ProgramManager::getInstance()->getBuiltinProgram(type); -} - -void Program::setProgramIds(uint32_t progType, uint64_t progId) -{ - _programType = progType; - _programId = progId; -} -NS_AX_BACKEND_END diff --git a/core/renderer/backend/Types.h b/core/renderer/backend/Types.h deleted file mode 100644 index f1433922e7e0..000000000000 --- a/core/renderer/backend/Types.h +++ /dev/null @@ -1,146 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#pragma once - -#include "Macros.h" - -#include -#include -#include -#include "base/bitmask.h" - -#include "Enums.h" - -using namespace std::string_view_literals; - -NS_AX_BACKEND_BEGIN - -inline TargetBufferFlags getMRTColorFlag(size_t index) noexcept -{ - assert(index < 4); - return TargetBufferFlags(1u << index); -} - -typedef TargetBufferFlags ClearFlag; - -/// @note In Metal, mipmap filter is derived from `magFilter` value: ie `NEAREST_MIPMAP_LINEAR` and -/// `LINEAR_MIPMAP_LINEAR` will select `LINEAR` filter, while `NEAREST_MIPMAP_NEAREST` and -/// `LINEAR_MIPMAP_NEAREST` will select `NEAREST` filter. -struct SamplerDescriptor -{ - SamplerFilter magFilter = SamplerFilter::LINEAR; - SamplerFilter minFilter = SamplerFilter::LINEAR; - SamplerAddressMode sAddressMode = SamplerAddressMode::CLAMP_TO_EDGE; - SamplerAddressMode tAddressMode = SamplerAddressMode::CLAMP_TO_EDGE; - - SamplerDescriptor() {} - - SamplerDescriptor(SamplerFilter _magFilter, - SamplerFilter _minFilter, - SamplerAddressMode _sAddressMode, - SamplerAddressMode _tAddressMode) - : magFilter(_magFilter), minFilter(_minFilter), sAddressMode(_sAddressMode), tAddressMode(_tAddressMode) - {} -}; - -struct UniformInfo -{ - int count = 0; // element count - int location = -1; - - // in opengl, type means uniform data type, i.e. GL_FLOAT_VEC2, while in metal type means data basic type, i.e. - // float - unsigned int type = 0; - unsigned int size = 0; // element size - unsigned int bufferOffset = 0; -}; - -struct StageUniformLocation -{ - int location = -1; - int offset = -1; - - operator bool() const { return location != -1; } - bool operator==(const StageUniformLocation& other) const; -}; - -struct UniformLocation -{ - StageUniformLocation vertStage; - StageUniformLocation fragStage; - - operator bool() const { return vertStage or fragStage; } - void reset() { vertStage = {}; fragStage = {}; } - bool operator==(const UniformLocation& other) const; - std::size_t operator()(const UniformLocation& uniform) const; // used as a hash function -}; - -struct AttributeBindInfo -{ - int location = -1; - int size = 0; - int type = 0; -}; - -/// built-in uniform name -static constexpr auto UNIFORM_NAME_MVP_MATRIX = "u_MVPMatrix"sv; -static constexpr auto UNIFORM_NAME_TEXTURE = "u_tex0"sv; -static constexpr auto UNIFORM_NAME_TEXTURE1 = "u_tex1"sv; -static constexpr auto UNIFORM_NAME_TEXTURE2 = "u_tex2"sv; -static constexpr auto UNIFORM_NAME_TEXTURE3 = "u_tex3"sv; -static constexpr auto UNIFORM_NAME_TEXT_COLOR = "u_textColor"sv; -static constexpr auto UNIFORM_NAME_EFFECT_COLOR = "u_effectColor"sv; -static constexpr auto UNIFORM_NAME_EFFECT_TYPE = "u_effectType"sv; - -/// built-in attribute name -static constexpr auto ATTRIBUTE_NAME_POSITION = "a_position"sv; -static constexpr auto ATTRIBUTE_NAME_COLOR = "a_color"sv; -static constexpr auto ATTRIBUTE_NAME_TEXCOORD = "a_texCoord"sv; -static constexpr auto ATTRIBUTE_NAME_TEXCOORD1 = "a_texCoord1"sv; -static constexpr auto ATTRIBUTE_NAME_TEXCOORD2 = "a_texCoord2"sv; -static constexpr auto ATTRIBUTE_NAME_TEXCOORD3 = "a_texCoord3"sv; -static constexpr auto ATTRIBUTE_NAME_NORMAL = "a_normal"sv; -static constexpr auto ATTRIBUTE_NAME_INSTANCE = "a_instance"sv; - -/** - * @brief a structor to store blend descriptor - */ -struct BlendDescriptor -{ - ColorWriteMask writeMask = ColorWriteMask::ALL; - - bool blendEnabled = false; - - BlendOperation rgbBlendOperation = BlendOperation::ADD; - BlendOperation alphaBlendOperation = BlendOperation::ADD; - - BlendFactor sourceRGBBlendFactor = BlendFactor::ONE; - BlendFactor destinationRGBBlendFactor = BlendFactor::ZERO; - BlendFactor sourceAlphaBlendFactor = BlendFactor::ONE; - BlendFactor destinationAlphaBlendFactor = BlendFactor::ZERO; -}; - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/metal/RenderTargetMTL.h b/core/renderer/backend/metal/RenderTargetMTL.h deleted file mode 100644 index 29a063b73918..000000000000 --- a/core/renderer/backend/metal/RenderTargetMTL.h +++ /dev/null @@ -1,40 +0,0 @@ -#pragma once -#include "../RenderTarget.h" -#include "CommandBufferMTL.h" - -NS_AX_BACKEND_BEGIN - -class RenderTargetMTL : public RenderTarget -{ -public: - struct Attachment - { - id texture = nil; - int level = 0; - explicit operator bool() const { return texture != nullptr; } - }; - - /* - * generateFBO, false, use for screen framebuffer - */ - RenderTargetMTL(bool defaultRenderTarget); - ~RenderTargetMTL(); - - void applyRenderPassAttachments(const RenderPassDescriptor&, MTLRenderPassDescriptor*) const; - - Attachment getColorAttachment(int index) const; - Attachment getDepthAttachment() const; - Attachment getStencilAttachment() const; - - PixelFormat getColorAttachmentPixelFormat(int index) const; - PixelFormat getDepthAttachmentPixelFormat() const; - PixelFormat getStencilAttachmentPixelFormat() const; - -public: - // "Sidecar" textures used to implement automatic MSAA resolve. - // id multisampledColor[MRT::TARGET_COUNT] = { 0 }; - // id multisampledDepth = nil; - // MetalContext*, DriverMTL* -}; - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/metal/RenderTargetMTL.mm b/core/renderer/backend/metal/RenderTargetMTL.mm deleted file mode 100644 index 32b4f54c59c1..000000000000 --- a/core/renderer/backend/metal/RenderTargetMTL.mm +++ /dev/null @@ -1,181 +0,0 @@ -#include "RenderTargetMTL.h" -#include "UtilsMTL.h" - -NS_AX_BACKEND_BEGIN - -static MTLLoadAction getLoadAction(const RenderPassDescriptor& params, TargetBufferFlags buffer) -{ - const auto clearFlags = (TargetBufferFlags)params.flags.clear; - const auto discardStartFlags = params.flags.discardStart; - if (bitmask::any(clearFlags, buffer)) - { - return MTLLoadActionClear; - } - else if (bitmask::any(discardStartFlags, buffer)) - { - return MTLLoadActionDontCare; - } - return MTLLoadActionLoad; -} - -static MTLStoreAction getStoreAction(const RenderPassDescriptor& params, TargetBufferFlags buffer) -{ - const auto discardEndFlags = params.flags.discardEnd; - if (bitmask::any(discardEndFlags, buffer)) - { - return MTLStoreActionDontCare; - } - return MTLStoreActionStore; -} - -RenderTargetMTL::RenderTargetMTL(bool defaultRenderTarget) : RenderTarget(defaultRenderTarget) {} -RenderTargetMTL::~RenderTargetMTL() {} - -void RenderTargetMTL::applyRenderPassAttachments(const RenderPassDescriptor& params, - MTLRenderPassDescriptor* descriptor) const -{ - // const auto discardFlags = params.flags.discardEnd; - auto clearFlags = params.flags.clear; - - for (size_t i = 0; i < MAX_COLOR_ATTCHMENT; i++) - { - auto attachment = getColorAttachment(static_cast(i)); - if (!attachment) - { - continue; - } - - const auto MRTColorFlag = getMRTColorFlag(i); - - descriptor.colorAttachments[i].texture = attachment.texture; - descriptor.colorAttachments[i].level = attachment.level; - // descriptor.colorAttachments[i].slice = attachment.layer; - descriptor.colorAttachments[i].loadAction = getLoadAction(params, MRTColorFlag); - descriptor.colorAttachments[i].storeAction = getStoreAction(params, MRTColorFlag); - if (bitmask::any(clearFlags, MRTColorFlag)) - descriptor.colorAttachments[i].clearColor = - MTLClearColorMake(params.clearColorValue[0], params.clearColorValue[1], params.clearColorValue[2], - params.clearColorValue[3]); -#if 0 - if (multisampledColor[i]) { - // We're rendering into our temporary MSAA texture and doing an automatic resolve. - // We should not be attempting to load anything into the MSAA texture. - assert(descriptor.colorAttachments[i].loadAction != MTLLoadActionLoad); - - descriptor.colorAttachments[i].texture = multisampledColor[i]; - descriptor.colorAttachments[i].level = 0; - descriptor.colorAttachments[i].slice = 0; - const bool discard = any(discardFlags & getMRTColorFlag(i)); - if (!discard) { - descriptor.colorAttachments[i].resolveTexture = attachment.texture; - descriptor.colorAttachments[i].resolveLevel = attachment.level; - descriptor.colorAttachments[i].resolveSlice = attachment.layer; - descriptor.colorAttachments[i].storeAction = MTLStoreActionMultisampleResolve; - } - } -#endif - } - - // Sets descriptor depth and stencil params, should match RenderTargetMTL::chooseAttachmentFormat - { - auto depthAttachment = getDepthAttachment(); - if (depthAttachment) - { - descriptor.depthAttachment.texture = depthAttachment.texture; - descriptor.depthAttachment.level = depthAttachment.level; - // descriptor.depthAttachment.slice = depthAttachment.layer; - descriptor.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH); - descriptor.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH); - if (bitmask::any(clearFlags, TargetBufferFlags::DEPTH)) - descriptor.depthAttachment.clearDepth = params.clearDepthValue; - } - - auto stencilAttachment = getStencilAttachment(); - if (stencilAttachment) - { - descriptor.stencilAttachment.texture = stencilAttachment.texture; - descriptor.stencilAttachment.level = stencilAttachment.level; - // descriptor.stencilAttachment.slice = depthAttachment.layer; - descriptor.stencilAttachment.loadAction = getLoadAction(params, TargetBufferFlags::STENCIL); - descriptor.stencilAttachment.storeAction = getStoreAction(params, TargetBufferFlags::STENCIL); - if (bitmask::any(clearFlags, TargetBufferFlags::STENCIL)) - descriptor.stencilAttachment.clearStencil = params.clearStencilValue; - } - } - -#if 0 - if (multisampledDepth) { - // We're rendering into our temporary MSAA texture and doing an automatic resolve. - // We should not be attempting to load anything into the MSAA texture. - assert(descriptor.depthAttachment.loadAction != MTLLoadActionLoad); - - descriptor.depthAttachment.texture = multisampledDepth; - descriptor.depthAttachment.level = 0; - descriptor.depthAttachment.slice = 0; - const bool discard = any(discardFlags & TargetBufferFlags::DEPTH); - if (!discard) { - descriptor.depthAttachment.resolveTexture = depthAttachment.texture; - descriptor.depthAttachment.resolveLevel = depthAttachment.level; - descriptor.depthAttachment.resolveSlice = depthAttachment.layer; - descriptor.depthAttachment.storeAction = MTLStoreActionMultisampleResolve; - } - } -#endif - - _dirtyFlags = TargetBufferFlags::NONE; -} - -RenderTargetMTL::Attachment RenderTargetMTL::getColorAttachment(int index) const -{ - if (isDefaultRenderTarget() && index == 0) - return {DriverMTL::getCurrentDrawable().texture, 0}; - auto& rb = this->_color[index]; - return RenderTargetMTL::Attachment{static_cast(rb) ? (id)(rb.texture->getHandler()) : nil, - rb.level}; -} - -RenderTargetMTL::Attachment RenderTargetMTL::getDepthAttachment() const -{ - if (isDefaultRenderTarget()) - return {UtilsMTL::getDefaultDepthStencilTexture(), 0}; - auto& rb = this->_depth; - return RenderTargetMTL::Attachment{!!rb ? (id)(rb.texture->getHandler()) : nil, rb.level}; -} - -RenderTargetMTL::Attachment RenderTargetMTL::getStencilAttachment() const -{ - if (isDefaultRenderTarget()) - return RenderTargetMTL::Attachment{UtilsMTL::getDefaultDepthStencilTexture(), 0}; - auto& rb = this->_stencil; - return RenderTargetMTL::Attachment{!!rb ? (id)(rb.texture->getHandler()) : nil, rb.level}; -} - -PixelFormat RenderTargetMTL::getColorAttachmentPixelFormat(int index) const -{ - // !!!important - // the default framebuffer pixel format is: MTLPixelFormatBGRA8Unorm - if (isDefaultRenderTarget() && index == 0) - return PixelFormat::BGRA8; - auto& rb = this->_color[index]; - return rb ? rb.texture->getTextureFormat() : PixelFormat::NONE; -} - -PixelFormat RenderTargetMTL::getDepthAttachmentPixelFormat() const -{ // FIXME: axmol only support D24S8 - if (isDefaultRenderTarget()) - return PixelFormat::D24S8; - if (_depth) - return _depth.texture->getTextureFormat(); - return PixelFormat::NONE; -} - -PixelFormat RenderTargetMTL::getStencilAttachmentPixelFormat() const -{ // FIXME: axmol only support D24S8 - if (isDefaultRenderTarget()) - return PixelFormat::D24S8; - if (_stencil) - return _stencil.texture->getTextureFormat(); - return PixelFormat::NONE; -} - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/metal/TextureMTL.mm b/core/renderer/backend/metal/TextureMTL.mm deleted file mode 100644 index d142cde57450..000000000000 --- a/core/renderer/backend/metal/TextureMTL.mm +++ /dev/null @@ -1,347 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "TextureMTL.h" -#include "UtilsMTL.h" -#include "base/Macros.h" -#include "../PixelFormatUtils.h" - -NS_AX_BACKEND_BEGIN - -namespace -{ -static MTLSamplerAddressMode toMTLSamplerAddressMode(SamplerAddressMode mode) -{ - MTLSamplerAddressMode ret = MTLSamplerAddressModeRepeat; - switch (mode) - { - case SamplerAddressMode::REPEAT: - ret = MTLSamplerAddressModeRepeat; - break; - case SamplerAddressMode::MIRROR_REPEAT: - ret = MTLSamplerAddressModeMirrorRepeat; - break; - case SamplerAddressMode::CLAMP_TO_EDGE: - ret = MTLSamplerAddressModeClampToEdge; - break; - default: - AXASSERT(false, "Not supported sampler address mode!"); - break; - } - return ret; -} - -static MTLSamplerMinMagFilter toMTLSamplerMinMagFilter(SamplerFilter mode) -{ - switch (mode) - { - case SamplerFilter::NEAREST: - case SamplerFilter::NEAREST_MIPMAP_LINEAR: - case SamplerFilter::NEAREST_MIPMAP_NEAREST: - return MTLSamplerMinMagFilterNearest; - case SamplerFilter::LINEAR: - case SamplerFilter::LINEAR_MIPMAP_LINEAR: - case SamplerFilter::LINEAR_MIPMAP_NEAREST: - return MTLSamplerMinMagFilterLinear; - case SamplerFilter::DONT_CARE: - return MTLSamplerMinMagFilterNearest; - } -} - -static MTLSamplerMipFilter toMTLSamplerMipFilter(SamplerFilter mode) -{ - switch (mode) - { - case SamplerFilter::NEAREST_MIPMAP_LINEAR: - case SamplerFilter::LINEAR_MIPMAP_LINEAR: - return MTLSamplerMipFilterLinear; - case SamplerFilter::NEAREST_MIPMAP_NEAREST: - case SamplerFilter::LINEAR_MIPMAP_NEAREST: - return MTLSamplerMipFilterNearest; - default: - return MTLSamplerMipFilterNotMipmapped; - } -} - -static bool isColorRenderable(PixelFormat textureFormat) -{ - switch (textureFormat) - { - case PixelFormat::RGBA8: - case PixelFormat::RGBA4: - case PixelFormat::RGB565: - case PixelFormat::RGB5A1: - return true; - default: - return false; - } -} -} - -/// CLASS TextureInfoMTL -id TextureInfoMTL::ensure(int index, int target) -{ - if (index < AX_META_TEXTURES) - { - id& mtlTexture = _mtlTextures[index]; - if (mtlTexture) - return mtlTexture; - mtlTexture = createTexture(_mtlDevice, _descriptor, target); - if (_maxIdx < index) - _maxIdx = index; - return mtlTexture; - } - return nil; -} - -void TextureInfoMTL::destroy() -{ - if (_maxIdx == -1) - return; - id texture; - int i = 0; - while ((texture = _mtlTextures[i++])) - [texture release]; - - if (_mtlSamplerState) - { - [_mtlSamplerState release]; - _mtlSamplerState = nil; - } - _maxIdx = -1; -} - -id TextureInfoMTL::createTexture(id mtlDevice, const TextureDescriptor& descriptor, int target) -{ - MTLPixelFormat pixelFormat = UtilsMTL::toMTLPixelFormat(descriptor.textureFormat); - if (pixelFormat == MTLPixelFormatInvalid) - return nil; - - MTLTextureDescriptor* textureDescriptor = nil; - switch (target) - { - case MTL_TEXTURE_2D: - textureDescriptor = [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:pixelFormat - width:descriptor.width - height:descriptor.height - mipmapped:YES]; - break; - case MTL_TEXTURE_CUBE: - textureDescriptor = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:pixelFormat - size:descriptor.width - mipmapped:YES]; - break; - default: - return nil; - } - - if (TextureUsage::RENDER_TARGET == descriptor.textureUsage) - { - // DepthStencil, and Multisample textures must be allocated with the MTLResourceStorageModePrivate resource - // option - if (PixelFormat::D24S8 == descriptor.textureFormat && target == MTL_TEXTURE_2D) - textureDescriptor.resourceOptions = MTLResourceStorageModePrivate; - textureDescriptor.usage = MTLTextureUsageRenderTarget | MTLTextureUsageShaderRead; - } - - return [mtlDevice newTextureWithDescriptor:textureDescriptor]; -} - -void TextureInfoMTL::recreateSampler(const SamplerDescriptor& descriptor) -{ - MTLSamplerDescriptor* mtlDescriptor = [MTLSamplerDescriptor new]; - mtlDescriptor.sAddressMode = descriptor.sAddressMode == SamplerAddressMode::DONT_CARE - ? _sAddressMode - : toMTLSamplerAddressMode(descriptor.sAddressMode); - mtlDescriptor.tAddressMode = descriptor.tAddressMode == SamplerAddressMode::DONT_CARE - ? _tAddressMode - : toMTLSamplerAddressMode(descriptor.tAddressMode); - - mtlDescriptor.minFilter = - descriptor.minFilter == SamplerFilter::DONT_CARE ? _minFilter : toMTLSamplerMinMagFilter(descriptor.minFilter); - mtlDescriptor.magFilter = - descriptor.magFilter == SamplerFilter::DONT_CARE ? _magFilter : toMTLSamplerMinMagFilter(descriptor.magFilter); - mtlDescriptor.mipFilter = - descriptor.magFilter == SamplerFilter::DONT_CARE ? _mipFilter : toMTLSamplerMipFilter(descriptor.magFilter); - - if (_mtlSamplerState) - { - [_mtlSamplerState release]; - _mtlSamplerState = nil; - } - - _sAddressMode = mtlDescriptor.sAddressMode; - _tAddressMode = mtlDescriptor.tAddressMode; - _minFilter = mtlDescriptor.minFilter; - _magFilter = mtlDescriptor.magFilter; - _mipFilter = mtlDescriptor.mipFilter; - - _mtlSamplerState = [_mtlDevice newSamplerStateWithDescriptor:mtlDescriptor]; - - [mtlDescriptor release]; -} - -/// CLASS TextureMTL -TextureMTL::TextureMTL(id mtlDevice, const TextureDescriptor& descriptor) : _textureInfo(mtlDevice) -{ - updateTextureDescriptor(descriptor); -} - -TextureMTL::~TextureMTL() {} - -void TextureMTL::updateSamplerDescriptor(const SamplerDescriptor& sampler) -{ - _textureInfo.recreateSampler(sampler); -} - -void TextureMTL::updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index) -{ - TextureBackend::updateTextureDescriptor(descriptor, index); - - _textureInfo._descriptor = descriptor; - _textureInfo.ensure(index, MTL_TEXTURE_2D); - updateSamplerDescriptor(descriptor.samplerDescriptor); - - _textureInfo._bytesPerRow = PixelFormatUtils::computeRowPitch(descriptor.textureFormat, descriptor.width); -} - -void TextureMTL::updateData(uint8_t* data, std::size_t width, std::size_t height, std::size_t level, int index) -{ - updateSubData(0, 0, width, height, level, data, index); -} - -void TextureMTL::updateSubData(std::size_t xoffset, - std::size_t yoffset, - std::size_t width, - std::size_t height, - std::size_t level, - uint8_t* data, - int index) -{ - auto mtlTexture = _textureInfo.ensure(index, MTL_TEXTURE_2D); - if (!mtlTexture) - return; - - MTLRegion region = { - {xoffset, yoffset, 0}, // MTLOrigin - {width, height, 1} // MTLSize - }; - - auto bytesPerRow = PixelFormatUtils::computeRowPitch(_textureFormat, static_cast(width)); - - [mtlTexture replaceRegion:region mipmapLevel:level withBytes:data bytesPerRow:bytesPerRow]; - - if (!_hasMipmaps && level > 0) - _hasMipmaps = true; -} - -void TextureMTL::updateCompressedData(uint8_t* data, - std::size_t width, - std::size_t height, - std::size_t dataLen, - std::size_t level, - int index) -{ - updateCompressedSubData(0, 0, width, height, dataLen, level, data, index); -} - -void TextureMTL::updateCompressedSubData(std::size_t xoffset, - std::size_t yoffset, - std::size_t width, - std::size_t height, - std::size_t dataLen, - std::size_t level, - uint8_t* data, - int index) -{ - updateSubData(xoffset, yoffset, width, height, level, data, index); -} - -void TextureMTL::generateMipmaps() -{ - if (TextureUsage::RENDER_TARGET == _textureUsage || isColorRenderable(_textureFormat) == false) - return; - - if (!_hasMipmaps) - { - _hasMipmaps = true; - UtilsMTL::generateMipmaps(reinterpret_cast>(this->getHandler())); - } -} - -/// CLASS TextureCubeMTL -TextureCubeMTL::TextureCubeMTL(id mtlDevice, const TextureDescriptor& descriptor) : _textureInfo(mtlDevice) -{ - updateTextureDescriptor(descriptor); -} - -TextureCubeMTL::~TextureCubeMTL() {} - -void TextureCubeMTL::updateTextureDescriptor(const ax::backend::TextureDescriptor& descriptor, int index) -{ - TextureBackend::updateTextureDescriptor(descriptor, index); - - _textureInfo._descriptor = descriptor; - _textureInfo.ensure(index, MTL_TEXTURE_CUBE); - updateSamplerDescriptor(descriptor.samplerDescriptor); - - _textureInfo._bytesPerRow = PixelFormatUtils::computeRowPitch(descriptor.textureFormat, descriptor.width); - _bytesPerImage = _textureInfo._bytesPerRow * descriptor.width; - _region = MTLRegionMake2D(0, 0, descriptor.width, descriptor.height); -} - -void TextureCubeMTL::updateSamplerDescriptor(const SamplerDescriptor& sampler) -{ - _textureInfo.recreateSampler(sampler); -} - -void TextureCubeMTL::updateFaceData(TextureCubeFace side, void* data, int index) -{ - NSUInteger slice = static_cast(side); - auto mtlTexture = _textureInfo.ensure(index, MTL_TEXTURE_CUBE); - if (!mtlTexture) - return; - - [mtlTexture replaceRegion:_region - mipmapLevel:0 - slice:slice - withBytes:data - bytesPerRow:_textureInfo._bytesPerRow - bytesPerImage:_bytesPerImage]; -} - -void TextureCubeMTL::generateMipmaps() -{ - if (TextureUsage::RENDER_TARGET == _textureUsage || isColorRenderable(_textureFormat) == false) - return; - - if (!_hasMipmaps) - { - _hasMipmaps = true; - UtilsMTL::generateMipmaps(reinterpret_cast>(this->getHandler())); - } -} - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/opengl/CommandBufferGLES2.cpp b/core/renderer/backend/opengl/CommandBufferGLES2.cpp deleted file mode 100644 index de756044bbef..000000000000 --- a/core/renderer/backend/opengl/CommandBufferGLES2.cpp +++ /dev/null @@ -1,72 +0,0 @@ -/**************************************************************************** - - Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "CommandBufferGLES2.h" - -#if !defined(__APPLE__) && AX_TARGET_PLATFORM != AX_PLATFORM_WINRT - -# include "platform/GL.h" - -NS_AX_BACKEND_BEGIN - -CommandBufferGLES2::CommandBufferGLES2() -{ - if (glDrawElementsInstancedEXT) - glDrawElementsInstanced = glDrawElementsInstancedEXT; - else if (glDrawElementsInstancedANGLE) - glDrawElementsInstanced = glDrawElementsInstancedANGLE; - - if (glVertexAttribDivisorEXT) - glVertexAttribDivisor = glVertexAttribDivisorEXT; - else if (glVertexAttribDivisorANGLE) - glVertexAttribDivisor = glVertexAttribDivisorANGLE; - - if (!glDrawElementsInstanced) - AXLOGD("{}", "Device not support instancing draw"); -} - -void CommandBufferGLES2::drawElementsInstanced(PrimitiveType primitiveType, - IndexFormat indexType, - std::size_t count, - std::size_t offset, - int instanceCount, - bool wireframe) -{ - if (!glDrawElementsInstanced) - return; - CommandBufferGL::drawElementsInstanced(primitiveType, indexType, count, offset, instanceCount, wireframe); -} - -void CommandBufferGLES2::bindInstanceBuffer(ProgramGL* program, uint32_t& usedBits) const -{ - - if (!glDrawElementsInstanced) - return; - CommandBufferGL::bindInstanceBuffer(program, usedBits); -} - -NS_AX_BACKEND_END - -#endif diff --git a/core/renderer/backend/opengl/DepthStencilStateGL.cpp b/core/renderer/backend/opengl/DepthStencilStateGL.cpp deleted file mode 100644 index 495074178786..000000000000 --- a/core/renderer/backend/opengl/DepthStencilStateGL.cpp +++ /dev/null @@ -1,94 +0,0 @@ -/**************************************************************************** - Copyright (c) 2018-2019 Xiamen Yaji Software Co., Ltd. - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include "DepthStencilStateGL.h" -#include "platform/GL.h" - -#include "renderer/backend/opengl/MacrosGL.h" -#include "renderer/backend/opengl/UtilsGL.h" -#include "OpenGLState.h" - -NS_AX_BACKEND_BEGIN - -void DepthStencilStateGL::reset() -{ - __gl->disableDepthTest(); - __gl->disableStencilTest(); -} - -void DepthStencilStateGL::apply(unsigned int stencilReferenceValueFront, unsigned int stencilReferenceValueBack) const -{ - const auto dsFlags = _depthStencilInfo.flags; - // depth test - if (bitmask::any(dsFlags, DepthStencilFlags::DEPTH_TEST)) - __gl->enableDepthTest(); - else - __gl->disableDepthTest(); - - __gl->depthMask(bitmask::any(dsFlags, DepthStencilFlags::DEPTH_WRITE)); - __gl->depthFunc(UtilsGL::toGLComareFunction(_depthStencilInfo.depthCompareFunction)); - - // stencil test - if (bitmask::any(dsFlags, DepthStencilFlags::STENCIL_TEST)) - { - __gl->enableStencilTest(); - - if (_isBackFrontStencilEqual) - { - __gl->stencilFunc(UtilsGL::toGLComareFunction(_depthStencilInfo.frontFaceStencil.stencilCompareFunction), - (GLint)stencilReferenceValueFront, _depthStencilInfo.frontFaceStencil.readMask); - - __gl->stencilOp(UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.stencilFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.depthFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.depthStencilPassOperation)); - - __gl->stencilMask(_depthStencilInfo.frontFaceStencil.writeMask); - } - else - { - __gl->stencilFuncFront(UtilsGL::toGLComareFunction(_depthStencilInfo.backFaceStencil.stencilCompareFunction), - (GLint)stencilReferenceValueBack, _depthStencilInfo.backFaceStencil.readMask); - __gl->stencilFuncBack(UtilsGL::toGLComareFunction(_depthStencilInfo.frontFaceStencil.stencilCompareFunction), - (GLint)stencilReferenceValueFront, _depthStencilInfo.frontFaceStencil.readMask); - - __gl->stencilOpFront( - UtilsGL::toGLStencilOperation(_depthStencilInfo.backFaceStencil.stencilFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.backFaceStencil.depthFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.backFaceStencil.depthStencilPassOperation)); - __gl->stencilOpBack( - UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.stencilFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.depthFailureOperation), - UtilsGL::toGLStencilOperation(_depthStencilInfo.frontFaceStencil.depthStencilPassOperation)); - - __gl->stencilMaskBack(_depthStencilInfo.backFaceStencil.writeMask); - __gl->stencilMaskFront(_depthStencilInfo.frontFaceStencil.writeMask); - } - } - else - __gl->disableStencilTest(); - - CHECK_GL_ERROR_DEBUG(); -} - -NS_AX_BACKEND_END diff --git a/core/renderer/backend/opengl/OpenGLState.cpp b/core/renderer/backend/opengl/OpenGLState.cpp deleted file mode 100644 index d97f98948416..000000000000 --- a/core/renderer/backend/opengl/OpenGLState.cpp +++ /dev/null @@ -1,18 +0,0 @@ -#include "OpenGLState.h" - -NS_AX_BACKEND_BEGIN - -namespace -{ -auto g_defaultOpenGLState = std::make_unique(); -} - -OpenGLState* __gl = g_defaultOpenGLState.get(); - -void OpenGLState::reset() -{ - g_defaultOpenGLState = std::make_unique(); - __gl = g_defaultOpenGLState.get(); -} - -NS_AX_BACKEND_END diff --git a/core/ui/UIHelper.cpp b/core/ui/UIHelper.cpp deleted file mode 100644 index b6d72ba7ad77..000000000000 --- a/core/ui/UIHelper.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/**************************************************************************** -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#include "ui/UIHelper.h" -#include "ui/UIWidget.h" -#include "ui/UILayoutComponent.h" -#include "base/Director.h" -#include "base/UTF8.h" - -namespace ax -{ - -namespace ui -{ - -static bool _activeLayout = true; - -Widget* Helper::seekWidgetByTag(Widget* root, int tag) -{ - if (!root) - { - return nullptr; - } - if (root->getTag() == tag) - { - return root; - } - const auto& arrayRootChildren = root->getChildren(); - ssize_t length = arrayRootChildren.size(); - for (ssize_t i = 0; i < length; i++) - { - Widget* child = dynamic_cast(arrayRootChildren.at(i)); - if (child) - { - Widget* res = seekWidgetByTag(child, tag); - if (res != nullptr) - { - return res; - } - } - } - return nullptr; -} - -Widget* Helper::seekWidgetByName(Widget* root, std::string_view name) -{ - if (!root) - { - return nullptr; - } - if (root->getName() == name) - { - return root; - } - const auto& arrayRootChildren = root->getChildren(); - for (auto&& subWidget : arrayRootChildren) - { - Widget* child = dynamic_cast(subWidget); - if (child) - { - Widget* res = seekWidgetByName(child, name); - if (res != nullptr) - { - return res; - } - } - } - return nullptr; -} - -/*temp action*/ -Widget* Helper::seekActionWidgetByActionTag(Widget* root, int tag) -{ - if (!root) - { - return nullptr; - } - if (root->getActionTag() == tag) - { - return root; - } - const auto& arrayRootChildren = root->getChildren(); - for (auto&& subWidget : arrayRootChildren) - { - Widget* child = dynamic_cast(subWidget); - if (child) - { - Widget* res = seekActionWidgetByActionTag(child, tag); - if (res != nullptr) - { - return res; - } - } - } - return nullptr; -} - -std::string Helper::getSubStringOfUTF8String(std::string_view str, - std::string::size_type start, - std::string::size_type length) -{ - std::u32string utf32; - if (!StringUtils::UTF8ToUTF32(str, utf32)) - { - AXLOGE("Can't convert string to UTF-32: {}", str); - return ""; - } - if (utf32.size() < start) - { - AXLOGE("'start' is out of range: {}, {}", static_cast(start), str); - return ""; - } - std::string result; - if (!StringUtils::UTF32ToUTF8(utf32.substr(start, length), result)) - { - AXLOGE("Can't convert internal UTF-32 string to UTF-8: {}", str); - return ""; - } - return result; -} - -void Helper::changeLayoutSystemActiveState(bool bActive) -{ - _activeLayout = bActive; -} -void Helper::doLayout(ax::Node* rootNode) -{ - if (!_activeLayout) - { - return; - } - - for (auto&& node : rootNode->getChildren()) - { - auto com = node->getComponent(__LAYOUT_COMPONENT_NAME); - Node* parent = node->getParent(); - if (nullptr != com && nullptr != parent) - { - LayoutComponent* layoutComponent = (LayoutComponent*)com; - - layoutComponent->refreshLayout(); - } - } -} - -Rect Helper::restrictCapInsetRect(const ax::Rect& capInsets, const Vec2& textureSize) -{ - float x = capInsets.origin.x; - float y = capInsets.origin.y; - float width = capInsets.size.width; - float height = capInsets.size.height; - - if (textureSize.width < width) - { - x = textureSize.width / 2.0f; - width = textureSize.width > 0 ? 1.0f : 0.0f; - } - if (textureSize.height < height) - { - y = textureSize.height / 2.0f; - height = textureSize.height > 0 ? 1.0f : 0.0f; - } - return Rect(x, y, width, height); -} - -Rect Helper::convertBoundingBoxToScreen(Node* node) -{ - auto director = Director::getInstance(); - auto renderView = director->getRenderView(); - auto frameSize = renderView->getFrameSize(); - - auto winSize = director->getWinSize(); - auto leftBottom = node->convertToWorldSpace(Point::ZERO); - - auto contentSize = node->getContentSize(); - auto rightTop = node->convertToWorldSpace(Point(contentSize.width, contentSize.height)); - - auto uiLeft = frameSize.width / 2 + (leftBottom.x - winSize.width / 2) * renderView->getScaleX(); - auto uiTop = frameSize.height / 2 - (rightTop.y - winSize.height / 2) * renderView->getScaleY(); - auto uiWidth = (rightTop.x - leftBottom.x) * renderView->getScaleX(); - auto uiHeight = (rightTop.y - leftBottom.y) * renderView->getScaleY(); - - return Rect(uiLeft, uiTop, uiWidth, uiHeight); -} -} // namespace ui - -} diff --git a/core/ui/UIHelper.h b/core/ui/UIHelper.h deleted file mode 100644 index 1107aa7458d8..000000000000 --- a/core/ui/UIHelper.h +++ /dev/null @@ -1,131 +0,0 @@ -/**************************************************************************** -Copyright (c) 2013-2016 Chukong Technologies Inc. -Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. -Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - -https://axmol.dev/ - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN -THE SOFTWARE. -****************************************************************************/ - -#pragma once - -#include -#include "platform/PlatformMacros.h" -#include "ui/GUIExport.h" -#include "2d/Node.h" - -namespace ax -{ - -/** - * @addtogroup ui - * @{ - */ -namespace ui -{ - -class Widget; - -/** - * Helper class for traversing children in widget tree. - * It also provides some helper functions for layout. - */ -class AX_GUI_DLL Helper -{ -public: - /** - * Find a widget with a specific tag from root widget. - * This search will be recursive through all child widgets. - * @param root The be searched root widget. - * @param tag The widget tag. - * @return Widget instance pointer. - */ - static Widget* seekWidgetByTag(Widget* root, int tag); - - /** - * Find a widget with a specific name from root widget. - * This search will be recursive through all child widgets. - * - * @param root The be searched root widget. - * @param name The widget name. - * @return Widget instance pointer. - */ - static Widget* seekWidgetByName(Widget* root, std::string_view name); - - /** - * Find a widget with a specific action tag from root widget - * This search will be recursive through all child widgets. - *@param root The be searched root widget. - *@param tag The widget action's tag. - *@return Widget instance pointer. - */ - static Widget* seekActionWidgetByActionTag(Widget* root, int tag); - - /** - * @brief Get a UTF8 substring from a std::string with a given start position and length - * Sample: std::string str = "中国中国中国"; substr = getSubStringOfUTF8String(str,0,2) will = "中国" - * - * @param str The source string. - * @param start The start position of the substring. - * @param length The length of the substring in UTF8 count - * @return a UTF8 substring - */ - static std::string getSubStringOfUTF8String(std::string_view str, - std::string::size_type start, - std::string::size_type length); - - /** - * Refresh object and it's children layout state - * - *@param rootNode A Node* or Node* descendant instance pointer. - * - */ - static void doLayout(Node* rootNode); - - /** - * Change the active property of Layout's @see `LayoutComponent` - *@param active A boolean value. - */ - static void changeLayoutSystemActiveState(bool active); - - /** - *@brief restrict capInsetSize, when the capInsets's width is larger than the textureSize, it will restrict to 0, - * the height goes the same way as width. - *@param capInsets A user defined capInsets. - *@param textureSize The size of a scale9enabled texture - *@return a restricted capInset. - */ - static Rect restrictCapInsetRect(const Rect& capInsets, const Vec2& textureSize); - - /** - *@brief Convert a node's boundingBox rect into screen coordinates. - * - * @param node Any node pointer. - * - * @return A Rect in screen coordinates. - */ - static Rect convertBoundingBoxToScreen(Node* node); -}; -} // namespace ui - -// end of ui group -/// @} -} - diff --git a/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.cpp b/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.cpp index 72c2e5b5f831..cc2250b72ad9 100644 --- a/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.cpp +++ b/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.cpp @@ -208,17 +208,17 @@ void DBCCSprite::draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_ for (ssize_t i = 0; i < count; i++) { // draw 3 lines - auto from = verts[indices[i * 3]].vertices; - auto to = verts[indices[i * 3 + 1]].vertices; - _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4B::WHITE); + auto from = verts[indices[i * 3]].position; + auto to = verts[indices[i * 3 + 1]].position; + _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color32::WHITE); - from = verts[indices[i * 3 + 1]].vertices; - to = verts[indices[i * 3 + 2]].vertices; - _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4B::WHITE); + from = verts[indices[i * 3 + 1]].position; + to = verts[indices[i * 3 + 2]].position; + _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color32::WHITE); - from = verts[indices[i * 3 + 2]].vertices; - to = verts[indices[i * 3]].vertices; - _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color4B::WHITE); + from = verts[indices[i * 3 + 2]].position; + to = verts[indices[i * 3]].position; + _debugDrawNode->drawLine(ax::Vec2(from.x, from.y), ax::Vec2(to.x, to.y), ax::Color32::WHITE); } #endif // AX_SPRITE_DEBUG_DRAW } diff --git a/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.h b/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.h index 2227cfd4df9e..8dddf98e7004 100644 --- a/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.h +++ b/extensions/DragonBones/src/DragonBones/CCArmatureDisplay.h @@ -24,7 +24,7 @@ #define DRAGONBONES_AX_ARMATURE_DISPLAY_CONTAINER_H #include "DragonBones/DragonBonesHeaders.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" DRAGONBONES_NAMESPACE_BEGIN /** diff --git a/extensions/DragonBones/src/DragonBones/CCFactory.cpp b/extensions/DragonBones/src/DragonBones/CCFactory.cpp index af99166fdc8c..ce310f19ab99 100644 --- a/extensions/DragonBones/src/DragonBones/CCFactory.cpp +++ b/extensions/DragonBones/src/DragonBones/CCFactory.cpp @@ -30,71 +30,38 @@ TextureAtlasData* CCFactory::_buildTextureAtlasData(TextureAtlasData* textureAtl auto texture = textureCache->getTextureForKey(textureAtlasData->imagePath); if (texture == nullptr) { - const auto defaultPixelFormat = ax::Texture2D::getDefaultAlphaPixelFormat(); - auto pixelFormat = defaultPixelFormat; -#if COCOS2D_VERSION >= 0x00040000 + ax::rhi::PixelFormat pixelFormat = + ax::rhi::PixelFormat::NONE; switch (textureAtlasData->format) { case TextureFormat::RGBA8888: - pixelFormat = ax::backend::PixelFormat::RGBA8; + pixelFormat = ax::rhi::PixelFormat::RGBA8; break; case TextureFormat::BGRA8888: - pixelFormat = ax::backend::PixelFormat::BGRA8; + pixelFormat = ax::rhi::PixelFormat::BGRA8; break; case TextureFormat::RGBA4444: - pixelFormat = ax::backend::PixelFormat::RGBA4; + pixelFormat = ax::rhi::PixelFormat::RGBA4; break; case TextureFormat::RGB888: - pixelFormat = ax::backend::PixelFormat::RGB8; + pixelFormat = ax::rhi::PixelFormat::RGB8; break; case TextureFormat::RGB565: - pixelFormat = ax::backend::PixelFormat::RGB565; + pixelFormat = ax::rhi::PixelFormat::RGB565; break; case TextureFormat::RGBA5551: - pixelFormat = ax::backend::PixelFormat::RGB5A1; + pixelFormat = ax::rhi::PixelFormat::RGB5A1; break; case TextureFormat::DEFAULT: default: break; } -#else - switch (textureAtlasData->format) - { - case TextureFormat::RGBA8888: - pixelFormat = ax::Texture2D::PixelFormat::RGBA8; - break; - - case TextureFormat::BGRA8888: - pixelFormat = ax::Texture2D::PixelFormat::BGRA8; - break; - - case TextureFormat::RGBA4444: - pixelFormat = ax::Texture2D::PixelFormat::RGBA4; - break; - - case TextureFormat::RGB888: - pixelFormat = ax::Texture2D::PixelFormat::RGB8; - break; - - case TextureFormat::RGB565: - pixelFormat = ax::Texture2D::PixelFormat::RGB565; - break; - - case TextureFormat::RGBA5551: - pixelFormat = ax::Texture2D::PixelFormat::RGB5A1; - break; - - case TextureFormat::DEFAULT: - default: - break; - } -#endif texture = textureCache->addImage(textureAtlasData->imagePath, pixelFormat); } diff --git a/extensions/DragonBones/src/DragonBones/CCFactory.h b/extensions/DragonBones/src/DragonBones/CCFactory.h index 39ee004f973d..07fdb8cc4e2e 100644 --- a/extensions/DragonBones/src/DragonBones/CCFactory.h +++ b/extensions/DragonBones/src/DragonBones/CCFactory.h @@ -24,7 +24,7 @@ #define DRAGONBONES_AX_FACTORY_H #include "DragonBonesHeaders.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "CCArmatureDisplay.h" DRAGONBONES_NAMESPACE_BEGIN diff --git a/extensions/DragonBones/src/DragonBones/CCSlot.cpp b/extensions/DragonBones/src/DragonBones/CCSlot.cpp index 3615e1e9ab06..6974c7bb83e4 100644 --- a/extensions/DragonBones/src/DragonBones/CCSlot.cpp +++ b/extensions/DragonBones/src/DragonBones/CCSlot.cpp @@ -92,7 +92,7 @@ void CCSlot::_updateFrame() const auto& region = currentTextureData->region; const auto& textureAtlasSize = currentTextureData->spriteFrame->getTexture()->getContentSizeInPixels(); - auto vertices = new ax::V3F_C4B_T2F[vertexCount]; // does cocos2dx release it? + auto vertices = new ax::V3F_T2F_C4B[vertexCount]; // does cocos2dx release it? auto vertexIndices = new unsigned short[triangleCount * 3]; // does cocos2dx release it? ax::Rect boundsRect(999999.0f, 999999.0f, -999999.0f, -999999.0f); @@ -103,21 +103,21 @@ void CCSlot::_updateFrame() const auto y = floatArray[vertexOffset + i + 1]; auto u = floatArray[uvOffset + i]; auto v = floatArray[uvOffset + i + 1]; - ax::V3F_C4B_T2F vertexData; - vertexData.vertices.set(x, -y, 0.0f); + ax::V3F_T2F_C4B vertexData; + vertexData.position.set(x, -y, 0.0f); if (currentTextureData->rotated) { - vertexData.texCoords.u = (region.x + (1.0f - v) * region.width) / textureAtlasSize.width; - vertexData.texCoords.v = (region.y + u * region.height) / textureAtlasSize.height; + vertexData.texCoord.u = (region.x + (1.0f - v) * region.width) / textureAtlasSize.width; + vertexData.texCoord.v = (region.y + u * region.height) / textureAtlasSize.height; } else { - vertexData.texCoords.u = (region.x + u * region.width) / textureAtlasSize.width; - vertexData.texCoords.v = (region.y + v * region.height) / textureAtlasSize.height; + vertexData.texCoord.u = (region.x + u * region.width) / textureAtlasSize.width; + vertexData.texCoord.v = (region.y + v * region.height) / textureAtlasSize.height; } - vertexData.colors = ax::Color4B::WHITE; + vertexData.color = ax::Color32::WHITE; vertices[iH] = vertexData; if (boundsRect.origin.x > x) @@ -262,7 +262,7 @@ void CCSlot::_updateMesh() } auto& vertex = vertices[i]; - auto& vertexPosition = vertex.vertices; + auto& vertexPosition = vertex.position; vertexPosition.set(xG, -yG, 0.0f); @@ -307,7 +307,7 @@ void CCSlot::_updateMesh() const auto yG = floatArray[vertexOffset + i + 1] * scale + deformVertices[i + 1]; auto& vertex = vertices[iH]; - auto& vertexPosition = vertex.vertices; + auto& vertexPosition = vertex.position; vertexPosition.set(xG, -yG, 0.0f); @@ -434,7 +434,7 @@ void CCSlot::_updateBlendMode() if (texture && texture->hasPremultipliedAlpha()) { #if COCOS2D_VERSION >= 0x00040000 - ax::BlendFunc blendFunc = {ax::backend::BlendFactor::ONE, ax::backend::BlendFactor::ONE}; + ax::BlendFunc blendFunc = {ax::rhi::BlendFactor::ONE, ax::rhi::BlendFactor::ONE}; #else ax::BlendFunc blendFunc = {GL_ONE, GL_ONE}; #endif @@ -465,12 +465,13 @@ void CCSlot::_updateColor() { _renderDisplay->setOpacity(_colorTransform.alphaMultiplier * 255.0f); - static ax::Color3B helpColor; - helpColor.r = _colorTransform.redMultiplier * 255.0f; - helpColor.g = _colorTransform.greenMultiplier * 255.0f; - helpColor.b = _colorTransform.blueMultiplier * 255.0f; + ax::Color32 color32; + color32.r = _colorTransform.redMultiplier * 255.0f; + color32.g = _colorTransform.greenMultiplier * 255.0f; + color32.b = _colorTransform.blueMultiplier * 255.0f; + color32.a = _colorTransform.alphaMultiplier * 255.0f; - _renderDisplay->setColor(helpColor); + _renderDisplay->setColor(color32); } DRAGONBONES_NAMESPACE_END diff --git a/extensions/DragonBones/src/DragonBones/CCSlot.h b/extensions/DragonBones/src/DragonBones/CCSlot.h index 3a927c96c9ea..192608e7811f 100644 --- a/extensions/DragonBones/src/DragonBones/CCSlot.h +++ b/extensions/DragonBones/src/DragonBones/CCSlot.h @@ -1,4 +1,4 @@ -/** +/** * The MIT License (MIT) * * Copyright (c) 2012-2018 DragonBones team and other contributors @@ -24,7 +24,7 @@ #define DRAGONBONES_AX_SLOT_H #include "DragonBonesHeaders.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" DRAGONBONES_NAMESPACE_BEGIN /** diff --git a/extensions/DragonBones/src/DragonBones/CCTextureAtlasData.h b/extensions/DragonBones/src/DragonBones/CCTextureAtlasData.h index e99d1c54f20e..bcc1c2038176 100644 --- a/extensions/DragonBones/src/DragonBones/CCTextureAtlasData.h +++ b/extensions/DragonBones/src/DragonBones/CCTextureAtlasData.h @@ -1,4 +1,4 @@ -/** +/** * The MIT License (MIT) * * Copyright (c) 2012-2018 DragonBones team and other contributors @@ -24,7 +24,7 @@ #define DRAGONBONES_AX_TEXTUREATLAS_DATA_H #include "DragonBonesHeaders.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" DRAGONBONES_NAMESPACE_BEGIN /** diff --git a/extensions/DragonBones/src/DragonBones/core/DragonBones.h b/extensions/DragonBones/src/DragonBones/core/DragonBones.h index 336357fecfbd..22749bffd81e 100644 --- a/extensions/DragonBones/src/DragonBones/core/DragonBones.h +++ b/extensions/DragonBones/src/DragonBones/core/DragonBones.h @@ -1,4 +1,4 @@ -/** +/** * The MIT License (MIT) * * Copyright (c) 2012-2018 DragonBones team and other contributors @@ -33,7 +33,7 @@ #include #include #include -#include "base/hlookup.h" +#include "axmol/base/hlookup.h" // dragonBones assert #define DRAGONBONES_ASSERT(cond, msg) \ do \ diff --git a/extensions/DragonBones/src/DragonBones/model/SkinData.h b/extensions/DragonBones/src/DragonBones/model/SkinData.h index 89e7abfc997b..b7cb80df0843 100644 --- a/extensions/DragonBones/src/DragonBones/model/SkinData.h +++ b/extensions/DragonBones/src/DragonBones/model/SkinData.h @@ -24,7 +24,7 @@ #define DRAGONBONES_SKIN_DATA_H #include "../core/BaseObject.h" -#include "base/hlookup.h" +#include "axmol/base/hlookup.h" DRAGONBONES_NAMESPACE_BEGIN /** diff --git a/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelGenerator.cpp b/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelGenerator.cpp index c566c117fffb..b625edd09439 100644 --- a/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelGenerator.cpp +++ b/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelGenerator.cpp @@ -923,4 +923,4 @@ void ProceduralModelGenerator::Ungenerate(ModelRef model) { } -} // namespace Effekseer \ No newline at end of file +} // namespace Effekseer diff --git a/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelParameter.h b/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelParameter.h index 4829044f58a3..914e8c548cd2 100644 --- a/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelParameter.h +++ b/extensions/Effekseer/Effekseer/Effekseer/Model/ProceduralModelParameter.h @@ -471,4 +471,4 @@ struct ProceduralModelParameter } // namespace Effekseer -#endif \ No newline at end of file +#endif diff --git a/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.cpp b/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.cpp index fc17ce99c88e..66103fcc54c0 100644 --- a/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.cpp +++ b/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.cpp @@ -1,9 +1,8 @@ #include "EffekseerForCocos2d-x.h" -#include "base/Utils.h" -#ifdef AX_USE_METAL -#include "renderer/backend/DriverBase.h" +#if AX_RENDER_API == AX_RENDER_API_MTL +#include "axmol/rhi/DriverBase.h" #endif namespace efk @@ -203,7 +202,7 @@ Effekseer::TextureRef TextureLoader::Load(const EFK_CHAR* path, ::Effekseer::Tex if(texture->getPixelsWide() > 1 || texture->getPixelsHigh() > 1) { -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL texture->generateMipmap(); #else if (texture->getPixelsWide() == ax::utils::nextPOT(texture->getPixelsWide()) && @@ -598,7 +597,7 @@ bool EffectEmitter::getRemoveOnStop() { return removeOnStop; } void EffectEmitter::setRemoveOnStop(bool value) { removeOnStop = value; } -void EffectEmitter::setColor(cocos2d::Color4B color) +void EffectEmitter::setColor(cocos2d::Color32 color) { color_ = color; Effekseer::Color col; @@ -700,17 +699,17 @@ void EffectEmitter::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& paren if (!manager->getInternalManager()->GetShown(handle) || manager->getInternalManager()->GetTotalInstanceCount() < 1) return; // nothing to draw - -#ifdef AX_USE_METAL + +#if AX_RENDER_API == AX_RENDER_API_MTL if (!manager->isDistorted) { // allow frame buffer texture to be copied for distortion - cocos2d::backend::DriverBase::getInstance()->setFrameBufferOnly(false); + cocos2d::rhi::DriverBase::getInstance()->setFrameBufferOnly(false); } #endif auto renderCommand = renderer->nextCallbackCommand(); - + renderCommand->init(_globalZOrder); auto renderer2d = manager->getInternalRenderer(); @@ -720,7 +719,7 @@ void EffectEmitter::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& paren renderer2d->SetCameraMatrix(mCamera); renderer2d->SetProjectionMatrix(mProj); -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL auto commandList = manager->getInternalCommandList(); beforeRender(renderer2d, commandList); #endif @@ -734,8 +733,8 @@ void EffectEmitter::draw(cocos2d::Renderer* renderer, const cocos2d::Mat4& paren renderer->addDrawnVertices(renderer2d->GetDrawVertexCount()); renderer2d->ResetDrawCallCount(); renderer2d->ResetDrawVertexCount(); - - #ifdef AX_USE_METAL + + #if AX_RENDER_API == AX_RENDER_API_MTL afterRender(renderer2d, commandList); #endif @@ -892,7 +891,7 @@ void EffectManager::begin(cocos2d::Renderer* renderer, float globalZOrder) manager2d->Draw(); }; - + diff --git a/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.h b/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.h index 6f46e328a23f..7b6ef02b54f7 100644 --- a/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.h +++ b/extensions/Effekseer/EffekseerForCocos2d-x/EffekseerForCocos2d-x.h @@ -1,11 +1,11 @@ #pragma once -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include #include -//#ifdef AX_USE_METAL +//#if AX_RENDER_API == AX_RENDER_API_MTL //#include //#else //#include @@ -77,7 +77,7 @@ class EffectEmitter : public cocos2d::Node cocos2d::Vec3 targetPosition_; float speed_ = 1.0f; - cocos2d::Color4B color_ = cocos2d::Color4B(255, 255, 255, 255); + cocos2d::Color32 color_ = cocos2d::Color32(255, 255, 255, 255); std::array dynamicInputs_; EffectManager* manager = nullptr; @@ -240,7 +240,7 @@ class EffectEmitter : public cocos2d::Node \~English Set the color which affects whole particles. \~Japanese 全てのパーティクルに影響する色を設定する。 */ - void setColor(cocos2d::Color4B color); + void setColor(cocos2d::Color32 color); /** @brief diff --git a/extensions/Effekseer/EffekseerForCocos2d-x/GL/Effekseer+GL.cpp b/extensions/Effekseer/EffekseerForCocos2d-x/GL/Effekseer+GL.cpp index 9aa753aea340..f8d7a49f872e 100644 --- a/extensions/Effekseer/EffekseerForCocos2d-x/GL/Effekseer+GL.cpp +++ b/extensions/Effekseer/EffekseerForCocos2d-x/GL/Effekseer+GL.cpp @@ -1,10 +1,10 @@ #include "../EffekseerForCocos2d-x.h" -#ifndef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_GL #include "../../EffekseerRendererCommon/ModelLoader.h" #include "../../EffekseerRendererGL/EffekseerRendererGL.h" #include "../../EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.MaterialLoader.h" -#include "renderer/backend/opengl/TextureGL.h" +#include "axmol/rhi/opengl/TextureGL.h" namespace efk { @@ -109,11 +109,7 @@ class EffekseerGraphicsDevice : public ::EffekseerRendererGL::Backend::GraphicsD if (g_deviceObjectCollection == nullptr) { #if AX_GLES_PROFILE -#if AX_GLES_PROFILE == 300 g_deviceObjectCollection = Effekseer::MakeRefPtr(EffekseerRendererGL::OpenGLDeviceType::OpenGLES3); -#else - g_deviceObjectCollection = Effekseer::MakeRefPtr(EffekseerRendererGL::OpenGLDeviceType::OpenGLES2); -#endif #else g_deviceObjectCollection = Effekseer::MakeRefPtr(EffekseerRendererGL::OpenGLDeviceType::OpenGL3); #endif @@ -146,11 +142,11 @@ ::Effekseer::MaterialLoaderRef CreateMaterialLoader(Effekseer::FileInterfaceRef void UpdateTextureData(::Effekseer::TextureRef textureData, cocos2d::Texture2D* texture) { - auto textureGL = static_cast(texture->getBackendTexture()); + auto textureImpl = static_cast(texture->getBackendTexture()); auto device = EffekseerGraphicsDevice::create().DownCast<::EffekseerRendererGL::Backend::GraphicsDevice>(); - auto backend = device->CreateTexture(textureGL->getHandler(), texture->hasMipmaps(), []() -> void {}); + auto backend = device->CreateTexture(textureImpl->internalHandle(), texture->hasMipmaps(), []() -> void {}); textureData->SetBackend(backend); } diff --git a/extensions/Effekseer/EffekseerForCocos2d-x/Metal/Effekseer+Metal.mm b/extensions/Effekseer/EffekseerForCocos2d-x/Metal/Effekseer+Metal.mm index ff3ee8e455f5..ab9e04813a5d 100644 --- a/extensions/Effekseer/EffekseerForCocos2d-x/Metal/Effekseer+Metal.mm +++ b/extensions/Effekseer/EffekseerForCocos2d-x/Metal/Effekseer+Metal.mm @@ -1,13 +1,13 @@ #include "../EffekseerForCocos2d-x.h" -#ifdef AX_USE_METAL +#if AX_RENDER_API == AX_RENDER_API_MTL #include "../../EffekseerRendererLLGI/EffekseerRendererLLGI.RendererImplemented.h" #include "../../EffekseerRendererMetal/EffekseerRendererMetal.h" #include "../../3rdParty/LLGI/src/Metal/LLGI.GraphicsMetal.h" #include "../../EffekseerRendererCommon/ModelLoader.h" -#include "renderer/backend/metal/TextureMTL.h" -#include "renderer/backend/metal/CommandBufferMTL.h" -#include "renderer/backend/metal/UtilsMTL.h" +#include "axmol/rhi/metal/TextureMTL.h" +#include "axmol/rhi/metal/CommandBufferMTL.h" +#include "axmol/rhi/metal/UtilsMTL.h" #include namespace efk { @@ -17,20 +17,20 @@ void SetMTLObjectsFromCocos2d(Effekseer::RefPtr auto d = cocos2d::Director::getInstance(); auto renderer = d->getRenderer(); auto buffer = renderer->getCommandBuffer(); - auto bufferM = static_cast(buffer); - + auto bufferM = static_cast(buffer); + // use render pass descriptor from Cocos and add depth test // auto descriptor = d->getRenderPassDescriptor(); -// ax::backend::RenderPassDescriptor descriptor; +// ax::rhi::RenderPassDesc descriptor; // descriptor.flags.clear = true; // using axmol render pass auto target = renderer->getRenderTarget(); - + renderer->beginRenderPass(); auto v = renderer->getViewport(); // important for ensuring znear and zfar are in sync with Cocos bufferM->setViewport(v.x, v.y, v.w, v.h); - + // set Command Buffer and Render Encoder from Cocos EffekseerRendererMetal::BeginCommandList(commandList, bufferM->getRenderCommandEncoder()); } @@ -70,42 +70,42 @@ void SetMTLObjectsFromCocos2d(Effekseer::RefPtr bool DistortingCallbackMetal::OnDistorting(EffekseerRenderer::Renderer* renderer) { // to get viewport - auto drawable = cocos2d::backend::DriverMTL::getCurrentDrawable(); + auto drawable = cocos2d::rhi::DriverMTL::getCurrentDrawable(); if(textureInternal_ == nullptr) { - auto driver = static_cast(cocos2d::backend::DriverBase::getInstance()); - + auto driver = static_cast(cocos2d::rhi::DriverBase::getInstance()); + MTLTextureDescriptor* textureDescriptor = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:cocos2d::backend::UtilsMTL::getDefaultColorAttachmentPixelFormat() + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:cocos2d::rhi::UtilsMTL::getDefaultColorAttachmentPixelFormat() width:drawable.texture.width height:drawable.texture.height mipmapped:NO]; - + texture = [driver->getMTLDevice() newTextureWithDescriptor:textureDescriptor]; textureInternal_ = EffekseerRendererMetal::CreateTexture(renderer->GetGraphicsDevice(), texture); } auto rendererAX = cocos2d::Director::getInstance()->getRenderer(); - auto commandBuffer = static_cast(rendererAX->getCommandBuffer()); + auto commandBuffer = static_cast(rendererAX->getCommandBuffer()); commandBuffer->endEncoding(); - + EffekseerRendererMetal::EndCommandList(commandList_); - + MTLRegion region = { {0, 0, 0}, // MTLOrigin {texture.width, texture.height, 1} // MTLSize }; - + id blitEncoder = [commandBuffer->getMTLCommandBuffer() blitCommandEncoder]; - + [blitEncoder copyFromTexture:drawable.texture sourceSlice:0 sourceLevel:0 sourceOrigin:region.origin sourceSize:region.size toTexture:texture destinationSlice:0 destinationLevel:0 destinationOrigin:{0, 0, 0}]; [blitEncoder endEncoding]; - cocos2d::backend::DriverBase::getInstance()->setFrameBufferOnly(true); // reset - + cocos2d::rhi::DriverBase::getInstance()->setFrameBufferOnly(true); // reset + SetMTLObjectsFromCocos2d(commandList_); - + auto r = static_cast(renderer); r->SetBackground(textureInternal_); @@ -142,10 +142,10 @@ void SetMTLObjectsFromCocos2d(Effekseer::RefPtr } //creating_ = false; - + return g_graphicsDevice; } - + int Release() override { auto ret = ::EffekseerRendererLLGI::Backend::GraphicsDevice::Release(); @@ -172,10 +172,10 @@ int Release() override void UpdateTextureData(::Effekseer::TextureRef textureData, cocos2d::Texture2D* texture) { - auto textureMTL = static_cast(texture->getBackendTexture()); + auto textureImpl = static_cast(texture->getBackendTexture()); auto device = EffekseerGraphicsDevice::create().DownCast<::EffekseerRendererLLGI::Backend::GraphicsDevice>(); - auto backend = device->CreateTexture(textureMTL->getHandler(), []() -> void {}); + auto backend = device->CreateTexture(textureImpl->internalHandle(), []() -> void {}); textureData->SetBackend(backend); } @@ -209,8 +209,8 @@ void CleanupTextureData(::Effekseer::TextureRef textureData) auto device = EffekseerGraphicsDevice::create(); renderer2d = EffekseerRendererMetal::Create(device, spriteSize, - cocos2d::backend::UtilsMTL::getDefaultColorAttachmentPixelFormat(), - cocos2d::backend::UtilsMTL::getDefaultDepthStencilAttachmentPixelFormat(), + cocos2d::rhi::UtilsMTL::getDefaultColorAttachmentPixelFormat(), + cocos2d::rhi::UtilsMTL::getDefaultDepthStencilAttachmentPixelFormat(), false); memoryPool_ = EffekseerRenderer::CreateSingleFrameMemoryPool(device); @@ -224,7 +224,7 @@ void CleanupTextureData(::Effekseer::TextureRef textureData) { memoryPool_->NewFrame(); } - + auto r = static_cast<::EffekseerRendererLLGI::RendererImplemented*>(renderer2d.Get()); auto vb = static_cast<::EffekseerRendererLLGI::VertexBuffer*>(r->GetVertexBuffer()); } diff --git a/extensions/Effekseer/EffekseerRendererGL/CMakeLists.txt b/extensions/Effekseer/EffekseerRendererGL/CMakeLists.txt index eb071cc2eca8..41f408a4e0ce 100644 --- a/extensions/Effekseer/EffekseerRendererGL/CMakeLists.txt +++ b/extensions/Effekseer/EffekseerRendererGL/CMakeLists.txt @@ -42,14 +42,14 @@ target_link_libraries(${PROJECT_NAME} Effekseer) if (NOT (${CMAKE_SYSTEM_NAME} MATCHES "WindowsStore")) target_include_directories(${PROJECT_NAME} PUBLIC "${_AX_ROOT}/3rdparty/glad/include" - PUBLIC "${_AX_ROOT}/core" + PUBLIC "${_AX_ROOT}" ) target_link_libraries(${PROJECT_NAME} glad) else() target_include_directories(${PROJECT_NAME} PUBLIC "${_AX_ROOT}/3rdparty/angle/_x/include" - PUBLIC "${_AX_ROOT}/core" + PUBLIC "${_AX_ROOT}" ) endif() diff --git a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.Pre.h b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.Pre.h index d2b5866cb917..f3e54c470b8c 100644 --- a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.Pre.h +++ b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.Pre.h @@ -56,7 +56,7 @@ // #if _WIN32 // #pragma comment(lib, "opengl32.lib") // #endif -#include "platform/GL.h" +#include "axmol/platform/GL.h" namespace EffekseerRendererGL { diff --git a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.h b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.h index 9eb033bdcb44..d906889f96b9 100644 --- a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.h +++ b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.Base.h @@ -24,7 +24,7 @@ #include -#include "platform/GL.h" +#include "axmol/platform/GL.h" #if defined(__EMSCRIPTEN__) #include diff --git a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.GLExtension.h b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.GLExtension.h index ba20017b5b8e..41b61e052588 100644 --- a/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.GLExtension.h +++ b/extensions/Effekseer/EffekseerRendererGL/EffekseerRenderer/EffekseerRendererGL.GLExtension.h @@ -58,7 +58,7 @@ // #endif -#include "platform/GL.h" +#include "axmol/platform/GL.h" #include "EffekseerRendererGL.Base.Pre.h" #include diff --git a/extensions/Effekseer/EffekseerRendererGL/EffekseerRendererGL.h b/extensions/Effekseer/EffekseerRendererGL/EffekseerRendererGL.h index 112cbbfd1dbe..176a6aec851b 100644 --- a/extensions/Effekseer/EffekseerRendererGL/EffekseerRendererGL.h +++ b/extensions/Effekseer/EffekseerRendererGL/EffekseerRendererGL.h @@ -1,4 +1,4 @@ - + #ifndef __EFFEKSEERRENDERER_GL_BASE_PRE_H__ #define __EFFEKSEERRENDERER_GL_BASE_PRE_H__ @@ -54,7 +54,7 @@ // #endif -#include "platform/GL.h" +#include "axmol/platform/GL.h" namespace EffekseerRendererGL { diff --git a/extensions/Effekseer/EffekseerRendererLLGI/Common.cpp b/extensions/Effekseer/EffekseerRendererLLGI/Common.cpp index 0d1fb1fdfc75..c10032359652 100644 --- a/extensions/Effekseer/EffekseerRendererLLGI/Common.cpp +++ b/extensions/Effekseer/EffekseerRendererLLGI/Common.cpp @@ -1,4 +1,4 @@ -#include "Common.h" +#include "axmol/platform/Common.h" #include "EffekseerRendererLLGI.RendererImplemented.h" #include "GraphicsDevice.h" @@ -51,4 +51,4 @@ Effekseer::RefPtr CreateSingleFrameMem return ret; } -} // namespace EffekseerRenderer \ No newline at end of file +} // namespace EffekseerRenderer diff --git a/extensions/ExtensionExport.h b/extensions/ExtensionExport.h index 0647583bf9cb..212e2eb1493e 100644 --- a/extensions/ExtensionExport.h +++ b/extensions/ExtensionExport.h @@ -24,7 +24,7 @@ #pragma once -#include "platform/PlatformDefine.h" +#include "axmol/platform/PlatformDefine.h" #if defined(_WIN32) # if defined(AX_EX_DLLEXPORT) diff --git a/extensions/GUI/src/GUI/ControlExtension/Control.cpp b/extensions/GUI/src/GUI/ControlExtension/Control.cpp index 83f156bd6dd0..d8e08824d6d8 100644 --- a/extensions/GUI/src/GUI/ControlExtension/Control.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/Control.cpp @@ -30,12 +30,12 @@ */ #include "Control.h" -#include "base/Director.h" -#include "2d/Menu.h" -#include "base/Touch.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Menu.h" +#include "axmol/base/Touch.h" #include "Invocation.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerTouch.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerTouch.h" NS_AX_EXT_BEGIN diff --git a/extensions/GUI/src/GUI/ControlExtension/Control.h b/extensions/GUI/src/GUI/ControlExtension/Control.h index 592ac6a5bd69..0de1f374a4b6 100644 --- a/extensions/GUI/src/GUI/ControlExtension/Control.h +++ b/extensions/GUI/src/GUI/ControlExtension/Control.h @@ -31,7 +31,7 @@ #pragma once #include "ControlUtils.h" -#include "2d/Layer.h" +#include "axmol/2d/Layer.h" #include "extensions/ExtensionExport.h" NS_AX_EXT_BEGIN @@ -177,8 +177,8 @@ class AX_EX_DLL Control : public Layer virtual bool isTouchInside(Touch* touch); // Overrides - virtual bool isOpacityModifyRGB() const override; - virtual void setOpacityModifyRGB(bool bOpacityModifyRGB) override; + bool isOpacityModifyRGB() const override; + void setOpacityModifyRGB(bool bOpacityModifyRGB) override; /** */ @@ -188,7 +188,7 @@ class AX_EX_DLL Control : public Layer */ virtual ~Control(); - virtual bool init() override; + bool init() override; protected: /** diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlButton.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlButton.cpp index 65de4135ab42..3a39cfd69eed 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlButton.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlButton.cpp @@ -28,9 +28,9 @@ */ #include "ControlButton.h" -#include "2d/Label.h" -#include "2d/Action.h" -#include "2d/ActionInterval.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/Action.h" +#include "axmol/2d/ActionInterval.h" using namespace std; @@ -45,7 +45,7 @@ ControlButton::ControlButton() : _isPushed(false) , _parentInited(false) , _doesAdjustBackgroundImage(false) - , _currentTitleColor(Color3B::WHITE) + , _currentTitleColor(Color32::WHITE) , _titleLabel(nullptr) , _backgroundSprite(nullptr) , _zoomOnTouchDown(false) @@ -98,7 +98,7 @@ bool ControlButton::initWithLabelAndBackgroundSprite(Node* node, setBackgroundSprite(backgroundSprite); // Set the default color and opacity - setColor(Color3B::WHITE); + setColor(Color32::WHITE); setOpacity(255.0f); setOpacityModifyRGB(true); @@ -307,9 +307,9 @@ void ControlButton::setTitleForState(std::string_view title, State state) } } -Color3B ControlButton::getTitleColorForState(State state) const +Color32 ControlButton::getTitleColorForState(State state) const { - Color3B returnColor = Color3B::WHITE; + Color32 returnColor = Color32::WHITE; auto iter = _titleColorDispatchTable.find((int)state); if (iter != _titleColorDispatchTable.end()) @@ -328,7 +328,7 @@ Color3B ControlButton::getTitleColorForState(State state) const return returnColor; } -void ControlButton::setTitleColorForState(const Color3B& color, State state) +void ControlButton::setTitleColorForState(const Color32& color, State state) { _titleColorDispatchTable.erase((int)state); _titleColorDispatchTable[(int)state] = color; @@ -695,7 +695,7 @@ void ControlButton::updateDisplayedOpacity(uint8_t parentOpacity) } } -void ControlButton::setColor(const Color3B& color) +void ControlButton::setColor(const Color32& color) { Control::setColor(color); @@ -710,7 +710,7 @@ void ControlButton::setColor(const Color3B& color) } } -void ControlButton::updateDisplayedColor(const Color3B& parentColor) +void ControlButton::updateDisplayedColor(const Color32& parentColor) { Control::updateDisplayedColor(parentColor); diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlButton.h b/extensions/GUI/src/GUI/ControlExtension/ControlButton.h index b474abd7c2c8..4c244bcfa3a3 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlButton.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlButton.h @@ -33,8 +33,8 @@ #include "Control.h" #include "Invocation.h" -#include "base/Map.h" -#include "ui/UIScale9Sprite.h" +#include "axmol/base/Map.h" +#include "axmol/ui/UIScale9Sprite.h" NS_AX_EXT_BEGIN @@ -60,11 +60,11 @@ class AX_EX_DLL ControlButton : public Control static ControlButton* create(std::string_view title, std::string_view fontName, float fontSize); static ControlButton* create(Node* label, ax::ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize); - virtual void needsLayout() override; + void needsLayout() override; - virtual void setEnabled(bool enabled) override; - virtual void setSelected(bool enabled) override; - virtual void setHighlighted(bool enabled) override; + void setEnabled(bool enabled) override; + void setSelected(bool enabled) override; + void setHighlighted(bool enabled) override; bool isPushed() const { return _isPushed; } @@ -98,7 +98,7 @@ class AX_EX_DLL ControlButton : public Control * @return The color of the title for the specified state. */ - virtual Color3B getTitleColorForState(State state) const; + virtual Color32 getTitleColorForState(State state) const; /** * Sets the color of the title to use for the specified state. @@ -107,7 +107,7 @@ class AX_EX_DLL ControlButton : public Control * @param state The state that uses the specified color. The values are described * in "CCControlState". */ - virtual void setTitleColorForState(const Color3B& color, State state); + virtual void setTitleColorForState(const Color32& color, State state); /** * Returns the title label used for a state. @@ -178,15 +178,15 @@ class AX_EX_DLL ControlButton : public Control void setAdjustBackgroundImage(bool adjustBackgroundImage); // Overrides - virtual bool onTouchBegan(Touch* touch, Event* event) override; - virtual void onTouchMoved(Touch* touch, Event* event) override; - virtual void onTouchEnded(Touch* touch, Event* event) override; - virtual void onTouchCancelled(Touch* touch, Event* event) override; + bool onTouchBegan(Touch* touch, Event* event) override; + void onTouchMoved(Touch* touch, Event* event) override; + void onTouchEnded(Touch* touch, Event* event) override; + void onTouchCancelled(Touch* touch, Event* event) override; - virtual void setOpacity(uint8_t var) override; - virtual void updateDisplayedOpacity(uint8_t parentOpacity) override; - virtual void setColor(const Color3B&) override; - virtual void updateDisplayedColor(const Color3B& parentColor) override; + void setOpacity(uint8_t var) override; + void updateDisplayedOpacity(uint8_t parentOpacity) override; + void setColor(const Color32&) override; + void updateDisplayedColor(const Color32& parentColor) override; std::string_view getCurrentTitle() const { return _currentTitle; }; std::string getCurrentTitle() { return _currentTitle; }; @@ -199,7 +199,7 @@ class AX_EX_DLL ControlButton : public Control */ virtual ~ControlButton(); - virtual bool init() override; + bool init() override; virtual bool initWithLabelAndBackgroundSprite(Node* label, ax::ui::Scale9Sprite* backgroundSprite, bool adjustBackGroundSize); @@ -215,7 +215,7 @@ class AX_EX_DLL ControlButton : public Control std::string _currentTitle; /** The current color used to display the title. */ - AX_SYNTHESIZE_READONLY_PASS_BY_REF(Color3B, _currentTitleColor, CurrentTitleColor); + AX_SYNTHESIZE_READONLY_PASS_BY_REF(Color32, _currentTitleColor, CurrentTitleColor); /** The current title label. */ AX_SYNTHESIZE_RETAIN(Node*, _titleLabel, TitleLabel); @@ -234,7 +234,7 @@ class AX_EX_DLL ControlButton : public Control AX_PROPERTY_PASS_BY_REF(Vec2, _labelAnchorPoint, LabelAnchorPoint); std::unordered_map _titleDispatchTable; - std::unordered_map _titleColorDispatchTable; + std::unordered_map _titleColorDispatchTable; Map _titleLabelDispatchTable; Map _backgroundSpriteDispatchTable; diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.cpp index 79db05b96658..44ebb68af3f8 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.cpp @@ -32,8 +32,8 @@ */ #include "ControlColourPicker.h" -#include "2d/SpriteFrameCache.h" -#include "2d/SpriteBatchNode.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/2d/SpriteBatchNode.h" NS_AX_EXT_BEGIN @@ -120,7 +120,7 @@ ControlColourPicker* ControlColourPicker::create() return pRet; } -void ControlColourPicker::setColor(const Color3B& color) +void ControlColourPicker::setColor(const Color32& color) { // FIXME: fixed me if not correct Control::setColor(color); @@ -129,7 +129,7 @@ void ControlColourPicker::setColor(const Color3B& color) rgba.r = color.r / 255.0f; rgba.g = color.g / 255.0f; rgba.b = color.b / 255.0f; - rgba.a = 1.0f; + rgba.a = color.a / 255.0f; _hsv = ControlUtils::HSVfromRGB(rgba); updateHueAndControlPicker(); @@ -168,9 +168,9 @@ void ControlColourPicker::hueSliderValueChanged(Object* sender, Control::EventTy _hsv.h = ((ControlHuePicker*)sender)->getHue(); // Update the value - RGBA rgb = ControlUtils::RGBfromHSV(_hsv); + RGBA rgba = ControlUtils::RGBfromHSV(_hsv); // FIXME: fixed me if not correct - Control::setColor(Color3B((uint8_t)(rgb.r * 255.0f), (uint8_t)(rgb.g * 255.0f), (uint8_t)(rgb.b * 255.0f))); + Control::setColor(Color32(rgba)); // Send Control callback sendActionsForControlEvents(Control::EventType::VALUE_CHANGED); @@ -183,9 +183,9 @@ void ControlColourPicker::colourSliderValueChanged(Object* sender, Control::Even _hsv.v = ((ControlSaturationBrightnessPicker*)sender)->getBrightness(); // Update the value - RGBA rgb = ControlUtils::RGBfromHSV(_hsv); + RGBA rgba = ControlUtils::RGBfromHSV(_hsv); // FIXME: fixed me if not correct - Control::setColor(Color3B((uint8_t)(rgb.r * 255.0f), (uint8_t)(rgb.g * 255.0f), (uint8_t)(rgb.b * 255.0f))); + Control::setColor(Color32(rgba)); // Send Control callback sendActionsForControlEvents(Control::EventType::VALUE_CHANGED); diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.h b/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.h index 7bca0d3117e1..f0f572550dba 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlColourPicker.h @@ -61,10 +61,10 @@ class AX_EX_DLL ControlColourPicker : public Control */ virtual ~ControlColourPicker(); - virtual bool init() override; + bool init() override; - virtual void setColor(const Color3B& colorValue) override; - virtual void setEnabled(bool bEnabled) override; + void setColor(const Color32& colorValue) override; + void setEnabled(bool bEnabled) override; // virtual ~ControlColourPicker(); void hueSliderValueChanged(Object* sender, Control::EventType controlEvent); @@ -73,7 +73,7 @@ class AX_EX_DLL ControlColourPicker : public Control protected: void updateControlPicker(); void updateHueAndControlPicker(); - virtual bool onTouchBegan(Touch* touch, Event* pEvent) override; + bool onTouchBegan(Touch* touch, Event* pEvent) override; HSV _hsv; AX_SYNTHESIZE_RETAIN(ControlSaturationBrightnessPicker*, _colourPicker, colourPicker) diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlHuePicker.h b/extensions/GUI/src/GUI/ControlExtension/ControlHuePicker.h index 0537fa5c6a6b..af2ce9e20df6 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlHuePicker.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlHuePicker.h @@ -59,11 +59,11 @@ class AX_EX_DLL ControlHuePicker : public Control virtual ~ControlHuePicker(); virtual bool initWithTargetAndPos(Node* target, Vec2 pos); - virtual void setEnabled(bool enabled) override; + void setEnabled(bool enabled) override; // overrides - virtual bool onTouchBegan(Touch* touch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* touch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; protected: void updateSliderPosition(Vec2 location); diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.cpp index 288f98363b87..780c7e1ba3a1 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.cpp @@ -224,7 +224,7 @@ float ControlPotentiometer::angleInDegreesBetweenLineFromPoint_toPoint_toLineFro void ControlPotentiometer::potentiometerBegan(Vec2 /*location*/) { setSelected(true); - getThumbSprite()->setColor(Color3B::GRAY); + getThumbSprite()->setColor(Color32::GRAY); } void ControlPotentiometer::potentiometerMoved(Vec2 location) @@ -249,7 +249,7 @@ void ControlPotentiometer::potentiometerMoved(Vec2 location) void ControlPotentiometer::potentiometerEnded(Vec2 /*location*/) { - getThumbSprite()->setColor(Color3B::WHITE); + getThumbSprite()->setColor(Color32::WHITE); setSelected(false); } diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.h b/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.h index 4868224edbcf..bf8f399c9afa 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlPotentiometer.h @@ -29,7 +29,7 @@ #pragma once #include "Control.h" -#include "2d/ProgressTimer.h" +#include "axmol/2d/ProgressTimer.h" #include "extensions/ExtensionExport.h" NS_AX_EXT_BEGIN @@ -78,11 +78,11 @@ class AX_EX_DLL ControlPotentiometer : public Control float getMaximumValue(); // Overrides - virtual bool isTouchInside(Touch* touch) override; + bool isTouchInside(Touch* touch) override; void setEnabled(bool enabled) override; - virtual bool onTouchBegan(Touch* pTouch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; - virtual void onTouchEnded(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* pTouch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; + void onTouchEnded(Touch* pTouch, Event* pEvent) override; /** Factorize the event dispatch into these methods. */ void potentiometerBegan(Vec2 location); diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.cpp index 9d1e6acad1fc..abf2e0f29fc1 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.cpp @@ -105,8 +105,8 @@ void ControlSaturationBrightnessPicker::updateWithHSV(HSV hsv) hsvTemp.h = hsv.h; hsvTemp.v = 1; - RGBA rgb = ControlUtils::RGBfromHSV(hsvTemp); - _background->setColor(Color3B((uint8_t)(rgb.r * 255.0f), (uint8_t)(rgb.g * 255.0f), (uint8_t)(rgb.b * 255.0f))); + RGBA rgba = ControlUtils::RGBfromHSV(hsvTemp); + _background->setColor(Color32(rgba)); } void ControlSaturationBrightnessPicker::updateDraggerWithHSV(HSV hsv) diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.h b/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.h index 9e7fd4bd25de..70296409e544 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSaturationBrightnessPicker.h @@ -76,7 +76,7 @@ class AX_EX_DLL ControlSaturationBrightnessPicker : public Control static ControlSaturationBrightnessPicker* create(Node* target, Vec2 pos); - virtual void setEnabled(bool enabled) override; + void setEnabled(bool enabled) override; /** * @lua NA */ @@ -90,8 +90,8 @@ class AX_EX_DLL ControlSaturationBrightnessPicker : public Control void updateSliderPosition(Vec2 location); bool checkSliderPosition(Vec2 location); - virtual bool onTouchBegan(Touch* touch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* touch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; }; // end of GUI group diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSlider.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlSlider.cpp index 664a283c2229..81c5f1c3bbcb 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSlider.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSlider.cpp @@ -30,8 +30,8 @@ */ #include "ControlSlider.h" -#include "base/Touch.h" -#include "base/Director.h" +#include "axmol/base/Touch.h" +#include "axmol/base/Director.h" NS_AX_EXT_BEGIN @@ -111,7 +111,7 @@ ControlSlider* ControlSlider::create(Sprite* backgroundSprite, bool ControlSlider::initWithSprites(Sprite* backgroundSprite, Sprite* progressSprite, Sprite* thumbSprite) { Sprite* selectedThumbSprite = Sprite::createWithTexture(thumbSprite->getTexture(), thumbSprite->getTextureRect()); - selectedThumbSprite->setColor(Color3B::GRAY); + selectedThumbSprite->setColor(Color32::GRAY); return this->initWithSprites(backgroundSprite, progressSprite, thumbSprite, selectedThumbSprite); } diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSlider.h b/extensions/GUI/src/GUI/ControlExtension/ControlSlider.h index 68e0c5919da4..224ce25d0a33 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSlider.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSlider.h @@ -112,11 +112,11 @@ class AX_EX_DLL ControlSlider : public Control Sprite* thumbSprite, Sprite* selectedThumbSprite); - virtual void needsLayout() override; + void needsLayout() override; virtual void setMaximumValue(float val); - virtual void setEnabled(bool enabled) override; - virtual bool isTouchInside(Touch* touch) override; + void setEnabled(bool enabled) override; + bool isTouchInside(Touch* touch) override; Vec2 locationFromTouch(Touch* touch); virtual void setValue(float val); virtual void setMinimumValue(float val); @@ -126,9 +126,9 @@ class AX_EX_DLL ControlSlider : public Control void sliderMoved(Vec2 location); void sliderEnded(Vec2 location); - virtual bool onTouchBegan(Touch* touch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; - virtual void onTouchEnded(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* touch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; + void onTouchEnded(Touch* pTouch, Event* pEvent) override; /** Returns the value for the given location. */ float valueForLocation(Vec2 location); diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlStepper.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlStepper.cpp index 57d09a25b87f..54ed1ecbc974 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlStepper.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlStepper.cpp @@ -31,8 +31,8 @@ NS_AX_EXT_BEGIN -#define ControlStepperLabelColorEnabled Color3B(55, 55, 55) -#define ControlStepperLabelColorDisabled Color3B(147, 147, 147) +#define ControlStepperLabelColorEnabled Color32(55, 55, 55, 255) +#define ControlStepperLabelColorDisabled Color32(147, 147, 147, 255) #define ControlStepperLabelFont "CourierNewPSMT" @@ -259,22 +259,22 @@ void ControlStepper::updateLayoutUsingTouchLocation(Vec2 location) { _touchedPart = Part::MINUS; - _minusSprite->setColor(Color3B::GRAY); - _plusSprite->setColor(Color3B::WHITE); + _minusSprite->setColor(Color32::GRAY); + _plusSprite->setColor(Color32::WHITE); } else if (location.x >= _minusSprite->getContentSize().width && _value < _maximumValue) { _touchedPart = Part::PLUS; - _minusSprite->setColor(Color3B::WHITE); - _plusSprite->setColor(Color3B::GRAY); + _minusSprite->setColor(Color32::WHITE); + _plusSprite->setColor(Color32::GRAY); } else { _touchedPart = Part::NONE; - _minusSprite->setColor(Color3B::WHITE); - _plusSprite->setColor(Color3B::WHITE); + _minusSprite->setColor(Color32::WHITE); + _plusSprite->setColor(Color32::WHITE); } } @@ -321,8 +321,8 @@ void ControlStepper::onTouchMoved(Touch* pTouch, Event* /*pEvent*/) _touchedPart = Part::NONE; - _minusSprite->setColor(Color3B::WHITE); - _plusSprite->setColor(Color3B::WHITE); + _minusSprite->setColor(Color32::WHITE); + _plusSprite->setColor(Color32::WHITE); if (_autorepeat) { @@ -333,8 +333,8 @@ void ControlStepper::onTouchMoved(Touch* pTouch, Event* /*pEvent*/) void ControlStepper::onTouchEnded(Touch* pTouch, Event* /*pEvent*/) { - _minusSprite->setColor(Color3B::WHITE); - _plusSprite->setColor(Color3B::WHITE); + _minusSprite->setColor(Color32::WHITE); + _plusSprite->setColor(Color32::WHITE); if (_autorepeat) { diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlStepper.h b/extensions/GUI/src/GUI/ControlExtension/ControlStepper.h index ec768f7ebe6c..63d28e20bd04 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlStepper.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlStepper.h @@ -30,7 +30,7 @@ #pragma once #include "Control.h" -#include "2d/Label.h" +#include "axmol/2d/Label.h" #include "extensions/ExtensionExport.h" NS_AX_EXT_BEGIN @@ -76,9 +76,9 @@ class AX_EX_DLL ControlStepper : public Control virtual bool isContinuous() const; // Overrides - virtual bool onTouchBegan(Touch* pTouch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; - virtual void onTouchEnded(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* pTouch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; + void onTouchEnded(Touch* pTouch, Event* pEvent) override; void update(float dt) override; /** Update the layout of the stepper with the given touch location. */ diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.cpp b/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.cpp index d8bc4ecc4c03..deb06de34d21 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.cpp +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.cpp @@ -28,12 +28,12 @@ */ #include "ControlSwitch.h" -#include "2d/Sprite.h" -#include "2d/ActionTween.h" -#include "2d/Label.h" -#include "2d/ClippingNode.h" -#include "renderer/Shaders.h" -#include "2d/RenderTexture.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/ActionTween.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/ClippingNode.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/2d/RenderTexture.h" NS_AX_EXT_BEGIN // ControlSwitchSprite @@ -72,7 +72,7 @@ class ControlSwitchSprite : public Sprite, public ActionTweenDelegate /** * @lua NA */ - virtual void updateTweenAction(float value, std::string_view key) override; + void updateTweenAction(float value, std::string_view key) override; /** Contains the position (in x-axis) of the slider inside the receiver. */ float _sliderXPosition; @@ -397,7 +397,7 @@ bool ControlSwitch::onTouchBegan(Touch* pTouch, Event* /*pEvent*/) _initialTouchXPosition = location.x - _switchSprite->getSliderXPosition(); - _switchSprite->getThumbSprite()->setColor(Color3B::GRAY); + _switchSprite->getThumbSprite()->setColor(Color32::GRAY); _switchSprite->needsLayout(); return true; @@ -417,7 +417,7 @@ void ControlSwitch::onTouchEnded(Touch* pTouch, Event* /*pEvent*/) { Vec2 location = this->locationFromTouch(pTouch); - _switchSprite->getThumbSprite()->setColor(Color3B::WHITE); + _switchSprite->getThumbSprite()->setColor(Color32::WHITE); if (hasMoved()) { @@ -433,7 +433,7 @@ void ControlSwitch::onTouchCancelled(Touch* pTouch, Event* /*pEvent*/) { Vec2 location = this->locationFromTouch(pTouch); - _switchSprite->getThumbSprite()->setColor(Color3B::WHITE); + _switchSprite->getThumbSprite()->setColor(Color32::WHITE); if (hasMoved()) { diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.h b/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.h index 19624f29bbbc..1f607020794d 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlSwitch.h @@ -94,15 +94,15 @@ class AX_EX_DLL ControlSwitch : public Control void setOn(bool isOn); bool isOn() const { return _on; } bool hasMoved() const { return _moved; } - virtual void setEnabled(bool enabled) override; + void setEnabled(bool enabled) override; Vec2 locationFromTouch(Touch* touch); // Overrides - virtual bool onTouchBegan(Touch* pTouch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; - virtual void onTouchEnded(Touch* pTouch, Event* pEvent) override; - virtual void onTouchCancelled(Touch* pTouch, Event* pEvent) override; + bool onTouchBegan(Touch* pTouch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; + void onTouchEnded(Touch* pTouch, Event* pEvent) override; + void onTouchCancelled(Touch* pTouch, Event* pEvent) override; protected: /** Sprite which represents the view. */ diff --git a/extensions/GUI/src/GUI/ControlExtension/ControlUtils.h b/extensions/GUI/src/GUI/ControlExtension/ControlUtils.h index 9a1514f72612..32fe756b7a5c 100644 --- a/extensions/GUI/src/GUI/ControlExtension/ControlUtils.h +++ b/extensions/GUI/src/GUI/ControlExtension/ControlUtils.h @@ -35,7 +35,7 @@ #pragma once -#include "2d/Sprite.h" +#include "axmol/2d/Sprite.h" #include "../../ExtensionMacros.h" #include "extensions/ExtensionExport.h" @@ -63,17 +63,6 @@ typedef struct * @{ */ -// helper class to store Color3B's in mutable arrays -class AX_EX_DLL Color3bObject : public Object -{ -public: - Color3B value; - /** - * @lua NA - */ - Color3bObject(Color3B s_value) : value(s_value) {} -}; - class AX_EX_DLL ControlUtils { public: diff --git a/extensions/GUI/src/GUI/ControlExtension/Invocation.h b/extensions/GUI/src/GUI/ControlExtension/Invocation.h index 12734b3fadbf..127a96a865a1 100644 --- a/extensions/GUI/src/GUI/ControlExtension/Invocation.h +++ b/extensions/GUI/src/GUI/ControlExtension/Invocation.h @@ -32,7 +32,7 @@ */ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "../../ExtensionMacros.h" #include "extensions/ExtensionExport.h" #include "Control.h" diff --git a/extensions/GUI/src/GUI/ScrollView/ScrollView.cpp b/extensions/GUI/src/GUI/ScrollView/ScrollView.cpp index 116829db8d78..ab82572ffc36 100644 --- a/extensions/GUI/src/GUI/ScrollView/ScrollView.cpp +++ b/extensions/GUI/src/GUI/ScrollView/ScrollView.cpp @@ -25,13 +25,13 @@ ****************************************************************************/ #include "ScrollView.h" -#include "platform/Device.h" -#include "2d/ActionInstant.h" -#include "2d/ActionInterval.h" -#include "2d/ActionTween.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "renderer/Renderer.h" +#include "axmol/platform/Device.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/ActionTween.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/renderer/Renderer.h" #include diff --git a/extensions/GUI/src/GUI/ScrollView/ScrollView.h b/extensions/GUI/src/GUI/ScrollView/ScrollView.h index 68ad15abcfa9..9cacafcaac5f 100644 --- a/extensions/GUI/src/GUI/ScrollView/ScrollView.h +++ b/extensions/GUI/src/GUI/ScrollView/ScrollView.h @@ -26,9 +26,9 @@ #pragma once -#include "2d/Layer.h" -#include "base/EventListenerTouch.h" -#include "2d/ActionTween.h" +#include "axmol/2d/Layer.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/2d/ActionTween.h" #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" @@ -234,20 +234,20 @@ class AX_EX_DLL ScrollView : public Layer, public ActionTweenDelegate virtual void onTouchCancelled(Touch* touch, Event* event); // Overrides - virtual void setContentSize(const Size& size) override; - virtual const Size& getContentSize() const override; + void setContentSize(const Size& size) override; + const Size& getContentSize() const override; /** * @lua NA */ - virtual void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; + void visit(Renderer* renderer, const Mat4& parentTransform, uint32_t parentFlags) override; using Node::addChild; - virtual void addChild(Node* child, int zOrder, int tag) override; - virtual void addChild(Node* child, int zOrder, std::string_view name) override; + void addChild(Node* child, int zOrder, int tag) override; + void addChild(Node* child, int zOrder, std::string_view name) override; - virtual void removeAllChildren() override; - virtual void removeAllChildrenWithCleanup(bool cleanup) override; - virtual void removeChild(Node* child, bool cleanup = true) override; + void removeAllChildren() override; + void removeAllChildrenWithCleanup(bool cleanup) override; + void removeChild(Node* child, bool cleanup = true) override; /** * CCActionTweenDelegate */ diff --git a/extensions/GUI/src/GUI/ScrollView/TableView.h b/extensions/GUI/src/GUI/ScrollView/TableView.h index ae1e6bdf7798..2cfa566152c3 100644 --- a/extensions/GUI/src/GUI/ScrollView/TableView.h +++ b/extensions/GUI/src/GUI/ScrollView/TableView.h @@ -254,12 +254,12 @@ class AX_EX_DLL TableView : public ScrollView, public ScrollViewDelegate TableViewCell* cellAtIndex(ssize_t idx); // Overrides - virtual void scrollViewDidScroll(ScrollView* view) override; - virtual void scrollViewDidZoom(ScrollView* view) override {} - virtual bool onTouchBegan(Touch* pTouch, Event* pEvent) override; - virtual void onTouchMoved(Touch* pTouch, Event* pEvent) override; - virtual void onTouchEnded(Touch* pTouch, Event* pEvent) override; - virtual void onTouchCancelled(Touch* pTouch, Event* pEvent) override; + void scrollViewDidScroll(ScrollView* view) override; + void scrollViewDidZoom(ScrollView* view) override {} + bool onTouchBegan(Touch* pTouch, Event* pEvent) override; + void onTouchMoved(Touch* pTouch, Event* pEvent) override; + void onTouchEnded(Touch* pTouch, Event* pEvent) override; + void onTouchCancelled(Touch* pTouch, Event* pEvent) override; protected: ssize_t __indexFromOffset(Vec2 offset); diff --git a/extensions/GUI/src/GUI/ScrollView/TableViewCell.h b/extensions/GUI/src/GUI/ScrollView/TableViewCell.h index bf45ec9e2ab1..d4d9c462bb27 100644 --- a/extensions/GUI/src/GUI/ScrollView/TableViewCell.h +++ b/extensions/GUI/src/GUI/ScrollView/TableViewCell.h @@ -27,7 +27,7 @@ #pragma once #include "extensions/ExtensionMacros.h" -#include "2d/Node.h" +#include "axmol/2d/Node.h" #include "extensions/ExtensionExport.h" /** @@ -61,4 +61,4 @@ class AX_EX_DLL TableViewCell : public Node NS_AX_EXT_END // end of ui group -/// @} \ No newline at end of file +/// @} diff --git a/extensions/ImGui/src/ImGui/ImGuiPresenter.cpp b/extensions/ImGui/src/ImGui/ImGuiPresenter.cpp index 756b720d50dc..11691d1bd23e 100644 --- a/extensions/ImGui/src/ImGui/ImGuiPresenter.cpp +++ b/extensions/ImGui/src/ImGui/ImGuiPresenter.cpp @@ -37,8 +37,7 @@ THE SOFTWARE. #include "xxhash.h" -// TODO: mac metal -#if defined(AX_USE_GL) && defined(AX_PLATFORM_PC) +#if defined(AX_PLATFORM_PC) && AX_RENDER_API == AX_RENDER_API_GL # define AX_IMGUI_ENABLE_MULTI_VIEWPORT 1 #else # define AX_IMGUI_ENABLE_MULTI_VIEWPORT 0 @@ -804,8 +803,7 @@ void ImGuiPresenter::setNodeColor(Node* node, const ImVec4& col) { if (node) { - node->setColor({uint8_t(col.x * 255), uint8_t(col.y * 255), uint8_t(col.z * 255)}); - node->setOpacity(uint8_t(col.w * 255)); + node->setColor({uint8_t(col.x * 255), uint8_t(col.y * 255), uint8_t(col.z * 255), uint8_t(col.w * 255)}); } } diff --git a/extensions/ImGui/src/ImGui/ImGuiPresenter.h b/extensions/ImGui/src/ImGui/ImGuiPresenter.h index 0550391e1b1e..20d966826fce 100644 --- a/extensions/ImGui/src/ImGui/ImGuiPresenter.h +++ b/extensions/ImGui/src/ImGui/ImGuiPresenter.h @@ -27,7 +27,7 @@ THE SOFTWARE. #include #include -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/ExtensionMacros.h" #include "imgui.h" diff --git a/extensions/ImGui/src/ImGui/backends/imgui_impl_android.cpp b/extensions/ImGui/src/ImGui/backends/imgui_impl_android.cpp index 9d9dc3074cf6..2cc3af9c3d26 100644 --- a/extensions/ImGui/src/ImGui/backends/imgui_impl_android.cpp +++ b/extensions/ImGui/src/ImGui/backends/imgui_impl_android.cpp @@ -1,20 +1,20 @@ #include "imgui_impl_android.h" #include "imgui_impl_axmol.h" -#include "base/Director.h" -#include "base/EventListenerTouch.h" -#include "base/IMEDelegate.h" -#include "renderer/backend/Backend.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/IMEDelegate.h" +#include "axmol/rhi/axmol-rhi.h" #include #include #include #include #include #include -#include "base/IMEDelegate.h" -#include "base/EventDispatcher.h" +#include "axmol/base/IMEDelegate.h" +#include "axmol/base/EventDispatcher.h" using namespace ax; -using namespace backend; +using namespace ax::rhi; // Clang warnings with -Weverything #if defined(__clang__) diff --git a/extensions/ImGui/src/ImGui/backends/imgui_impl_android.h b/extensions/ImGui/src/ImGui/backends/imgui_impl_android.h index a036c3b5a2b2..e38e7872aa0d 100644 --- a/extensions/ImGui/src/ImGui/backends/imgui_impl_android.h +++ b/extensions/ImGui/src/ImGui/backends/imgui_impl_android.h @@ -1,6 +1,6 @@ #pragma once #include "imgui.h" -#include "platform/RenderView.h" +#include "axmol/platform/RenderView.h" struct ANativeWindow; struct AInputEvent; diff --git a/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.cpp b/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.cpp index e6156b6ee204..63888e1a3949 100644 --- a/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.cpp +++ b/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.cpp @@ -1,40 +1,42 @@ #include "imgui_impl_axmol.h" -#include "base/Director.h" -#include "base/Data.h" +#include "axmol/base/Director.h" +#include "axmol/base/Data.h" #if !defined(__ANDROID__) -# include "platform/RenderViewImpl.h" +# include "axmol/platform/RenderViewImpl.h" #endif -#include "renderer/backend/Program.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/ProgramManager.h" -#include "renderer/Shaders.h" -#include "renderer/Renderer.h" -#include "renderer/CallbackCommand.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Buffer.h" +#include "axmol/rhi/Program.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/ProgramManager.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/Buffer.h" using namespace ax; -using namespace ax::backend; +using namespace ax::rhi; constexpr IndexFormat IMGUI_INDEX_FORMAT = sizeof(ImDrawIdx) == 2 ? IndexFormat::U_SHORT : IndexFormat::U_INT; struct ProgramInfoData { + ProgramInfoData() { layout = DriverBase::getInstance()->createVertexLayout(); } + ~ProgramInfoData() { AX_SAFE_DELETE(layout); } Program* program = nullptr; // Uniforms location UniformLocation texture{}; UniformLocation projection{}; // Vertex attributes location - int position = 0; - int uv = 0; - int color = 0; - VertexLayout layout{}; + const VertexInputDesc* position{nullptr}; + const VertexInputDesc* uv{nullptr}; + const VertexInputDesc* color{nullptr}; + VertexLayout* layout{nullptr}; }; struct SavedRenderStateData { - backend::CullMode cull{}; + rhi::CullMode cull{}; Viewport vp{}; ScissorRect scissorRect{}; bool scissorTest{}; @@ -95,15 +97,11 @@ static void ImGui_ImplAxmol_UpdateTexture(ImTextureData* tex) const void* pixels = tex->GetPixels(); auto texture = new Texture2D(); - texture->initWithData(pixels, tex->Width * tex->Height * 4, backend::PixelFormat::RGBA8, tex->Width, + texture->initWithData(pixels, tex->Width * tex->Height * 4, rhi::PixelFormat::RGBA8, tex->Width, tex->Height, true); - backend::SamplerDescriptor descriptor(backend::SamplerFilter::LINEAR, // magFilter - backend::SamplerFilter::LINEAR, // minFilter - backend::SamplerAddressMode::CLAMP_TO_EDGE, // sAddressMode - backend::SamplerAddressMode::CLAMP_TO_EDGE // tAddressMode - ); - texture->getBackendTexture()->updateSamplerDescriptor(descriptor); + rhi::SamplerDesc desc{}; + texture->getBackendTexture()->updateSamplerDesc(desc); // Store identifiers tex->SetTexID((ImTextureID)(intptr_t)texture); @@ -134,7 +132,7 @@ static void ImGui_ImplAxmol_UpdateTexture(ImTextureData* tex) static void ImGui_ImplAxmol_SetupRenderState(ax::Renderer* renderer, ImDrawData* draw_data, int fb_width, int fb_height) { ImGui_ImplAxmol_PostCommand([=]() { - renderer->setCullMode(backend::CullMode::NONE); + renderer->setCullMode(rhi::CullMode::NONE); renderer->setDepthTest(false); renderer->setScissorTest(true); renderer->setViewPort(0, 0, fb_width, fb_height); @@ -198,7 +196,7 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_Init() io.BackendRendererUserData = (void*)bd; io.BackendRendererName = "imgui_impl_axmol"; -#if defined(AX_USE_GL) && (!defined(AX_GLES_PROFILE) || AX_GLES_PROFILE >= 300) +#if AX_RENDER_API == AX_RENDER_API_GL && (!defined(AX_GLES_PROFILE) || AX_GLES_PROFILE >= 300) io.BackendFlags |= ImGuiBackendFlags_RendererHasVtxOffset; // We can honor the ImDrawCmd::VtxOffset field, // allowing for large meshes. #endif @@ -209,7 +207,7 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_Init() ImGuiPlatformIO& platform_io = ImGui::GetPlatformIO(); platform_io.Renderer_TextureMaxWidth = platform_io.Renderer_TextureMaxHeight = - backend::DriverBase::getInstance()->getMaxTextureSize(); + rhi::DriverBase::getInstance()->getMaxTextureSize(); io.IniFilename = nullptr; @@ -278,12 +276,12 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_RenderDrawData(ImDrawData* draw_data) // Upload vertex/index buffers const auto vsize = cmd_list->VtxBuffer.Size * sizeof(ImDrawVert); IM_ASSERT(vsize > 0); - auto vbuffer = backend::DriverBase::getInstance()->newBuffer(vsize, BufferType::VERTEX, BufferUsage::STATIC); + auto vbuffer = rhi::DriverBase::getInstance()->createBuffer(vsize, BufferType::VERTEX, BufferUsage::STATIC); vbuffer->autorelease(); vbuffer->updateData(cmd_list->VtxBuffer.Data, vsize); const auto isize = cmd_list->IdxBuffer.Size * sizeof(ImDrawIdx); IM_ASSERT(isize > 0); - auto ibuffer = backend::DriverBase::getInstance()->newBuffer(isize, BufferType::INDEX, BufferUsage::STATIC); + auto ibuffer = rhi::DriverBase::getInstance()->createBuffer(isize, BufferType::INDEX, BufferUsage::STATIC); ibuffer->autorelease(); ibuffer->updateData(cmd_list->IdxBuffer.Data, isize); @@ -333,14 +331,14 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_RenderDrawData(ImDrawData* draw_data) auto state = new ProgramState(pinfo->program); state->autorelease(); bd->ProgramStates.pushBack(state); - auto& desc = cmd->getPipelineDescriptor(); + auto& desc = cmd->getPipelineDesc(); desc.programState = state; // setup attributes for ImDrawVert - desc.programState->setSharedVertexLayout(&pinfo->layout); + desc.programState->setSharedVertexLayout(pinfo->layout); desc.programState->setUniform(pinfo->projection, &bd->Projection, sizeof(Mat4)); desc.programState->setTexture(pinfo->texture, 0, tex->getBackendTexture()); // In order to composite our output buffer we need to preserve alpha - desc.blendDescriptor.sourceAlphaBlendFactor = BlendFactor::ONE; + desc.blendDesc.sourceAlphaBlendFactor = BlendFactor::ONE; // set vertex/index buffer cmd->setIndexBuffer(ibuffer, IMGUI_INDEX_FORMAT); cmd->setVertexBuffer(vbuffer); @@ -375,7 +373,7 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_RenderPlatform() ImGui::UpdatePlatformWindows(); ImGui::RenderPlatformWindowsDefault(); -#if defined(AX_USE_GL) && !defined(__ANDROID__) +#if AX_RENDER_API == AX_RENDER_API_GL && !defined(__ANDROID__) // restore context GLFWwindow* prev_current_context = glfwGetCurrentContext(); ImGui_ImplAxmol_PostCommand([=]() { ImGui_ImplAxmol_MakeCurrent(prev_current_context); }); @@ -388,24 +386,19 @@ IMGUI_IMPL_API void ImGui_ImplAxmol_MakeCurrent(GLFWwindow* window) #if !defined(__ANDROID__) glfwMakeContextCurrent(window); -# if defined(AX_USE_GL) - auto p = glfwGetWindowUserPointer(window); - if (!p) - { - p = new OpenGLState(); - glfwSetWindowUserPointer(window, p); -# if AX_GLES_PROFILE != 200 - // this is a new OpenGLContext, create default VAO for it when core profile enabled - GLuint vao; - glGenVertexArrays(1, &vao); - glBindVertexArray(vao); -# endif +# if AX_RENDER_API == AX_RENDER_API_GL + auto currentState = glfwGetWindowUserPointer(window); + if (!currentState) + { // create gl state for imgui mutli-viewport window + currentState = new gl::OpenGLState(); + glfwSetWindowUserPointer(window, currentState); } - if (backend::__gl != p) + // switch state for current gl context + if (gl::__state != currentState) { - backend::__gl->resetVAO(); - backend::__gl = (OpenGLState*)p; + gl::__state->resetVAO(); + gl::__state = (rhi::gl::OpenGLState*)currentState; } # endif #endif @@ -436,26 +429,26 @@ IMGUI_IMPL_API bool ImGui_ImplAxmol_CreateDeviceObjects() auto& info = bd->ProgramInfo; info.texture = info.program->getUniformLocation(TEXTURE); info.projection = info.program->getUniformLocation(MVP_MATRIX); - info.position = info.program->getAttributeLocation(POSITION); - info.uv = info.program->getAttributeLocation(TEXCOORD); - info.color = info.program->getAttributeLocation(COLOR); + info.position = info.program->getVertexInputDesc(POSITION); + info.uv = info.program->getVertexInputDesc(TEXCOORD); + info.color = info.program->getVertexInputDesc(COLOR); IM_ASSERT(bool(info.texture)); IM_ASSERT(bool(info.projection)); - IM_ASSERT(info.position >= 0); - IM_ASSERT(info.uv >= 0); - IM_ASSERT(info.color >= 0); - auto& layout = info.layout; - layout.setAttrib("a_position", info.position, VertexFormat::FLOAT2, 0, false); - layout.setAttrib("a_texCoord", info.uv, VertexFormat::FLOAT2, offsetof(ImDrawVert, uv), false); - layout.setAttrib("a_color", info.color, VertexFormat::UBYTE4, offsetof(ImDrawVert, col), true); - layout.setStride(sizeof(ImDrawVert)); + IM_ASSERT(!!info.position); + IM_ASSERT(!!info.uv); + IM_ASSERT(!!info.color); + auto layout = info.layout; + layout->setAttrib("a_position", info.position, VertexFormat::FLOAT2, 0, false); + layout->setAttrib("a_texCoord", info.uv, VertexFormat::FLOAT2, offsetof(ImDrawVert, uv), false); + layout->setAttrib("a_color", info.color, VertexFormat::UBYTE4, offsetof(ImDrawVert, col), true); + layout->setStride(sizeof(ImDrawVert)); return true; } IMGUI_IMPL_API void ImGui_ImplAxmol_DestroyDeviceObjects() { - auto pm = ProgramManager::getInstance(); + auto pm = ax::ProgramManager::getInstance(); auto bd = ImGui_ImplAxmol_GetBackendData(); diff --git a/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.h b/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.h index df8639564c71..d5672d829cec 100644 --- a/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.h +++ b/extensions/ImGui/src/ImGui/backends/imgui_impl_axmol.h @@ -4,10 +4,10 @@ #pragma once #include "imgui.h" #include -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" -#ifdef AX_USE_GL -# include "renderer/backend/opengl/OpenGLState.h" +#if AX_RENDER_API == AX_RENDER_API_GL +# include "axmol/rhi/opengl/OpenGLState.h" #endif extern "C" { diff --git a/extensions/ImGui/src/ImGui/backends/imgui_impl_glfw.cpp b/extensions/ImGui/src/ImGui/backends/imgui_impl_glfw.cpp index b97c57f6687b..ddb12b15b21f 100644 --- a/extensions/ImGui/src/ImGui/backends/imgui_impl_glfw.cpp +++ b/extensions/ImGui/src/ImGui/backends/imgui_impl_glfw.cpp @@ -174,7 +174,7 @@ #define GLFW_HAS_GETERROR (GLFW_VERSION_COMBINED >= 3300) // 3.3+ glfwGetError() #define GLFW_HAS_GETPLATFORM (GLFW_VERSION_COMBINED >= 3400) // 3.4+ glfwGetPlatform() -// Map GLFWWindow* to ImGuiContext*. +// Map GLFWWindow* to ImGuiContext*. // - Would be simpler if we could use glfwSetWindowUserPointer()/glfwGetWindowUserPointer(), but this is a single and shared resource. // - Would be simpler if we could use e.g. std::map<> as well. But we don't. // - This is not particularly optimized as we expect size to be small and queries to be rare. @@ -191,6 +191,7 @@ enum GlfwClientApi GlfwClientApi_OpenGL, GlfwClientApi_Vulkan, GlfwClientApi_Metal, // axmol spec + GlfwClientApi_D3D, // axmol spec }; struct ImGui_ImplGlfw_Data @@ -691,6 +692,14 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw // GLFW will emit an error which will often be printed by the app, so we temporarily disable error reporting. // Missing cursors will return nullptr and our _UpdateMouseCursor() function will use the Arrow cursor instead.) GLFWerrorfun prev_error_callback = glfwSetErrorCallback(nullptr); + + // axmol spec: Fix wasm64 javascript exception + // Note: The WASM actually not support glfwCreateStandardCursor until emsdk-4.0.1 Jan.17 2025 + // Uncaught TypeError: Cannot convert undefined to a BigInt + // at BigInt () + // at _glfwCreateStandardCursor (http://localhost:6931/cpp-tests.js:16617:12) + // at cpp-tests.wasm.ImGui_ImplGlfw_Init(GLFWwindow*, bool, GlfwClientApi) +#ifndef __EMSCRIPTEN__ bd->MouseCursors[ImGuiMouseCursor_Arrow] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_TextInput] = glfwCreateStandardCursor(GLFW_IBEAM_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNS] = glfwCreateStandardCursor(GLFW_VRESIZE_CURSOR); @@ -706,6 +715,7 @@ static bool ImGui_ImplGlfw_Init(GLFWwindow* window, bool install_callbacks, Glfw bd->MouseCursors[ImGuiMouseCursor_ResizeNESW] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_ResizeNWSE] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); bd->MouseCursors[ImGuiMouseCursor_NotAllowed] = glfwCreateStandardCursor(GLFW_ARROW_CURSOR); +#endif #endif glfwSetErrorCallback(prev_error_callback); #if GLFW_HAS_GETERROR && !defined(__EMSCRIPTEN__) // Eat errors (see #5908) @@ -1265,10 +1275,12 @@ static void ImGui_ImplGlfw_DestroyWindow(ImGuiViewport* viewport) for (int i = 0; i < IM_ARRAYSIZE(bd->KeyOwnerWindows); i++) if (bd->KeyOwnerWindows[i] == vd->Window) ImGui_ImplGlfw_KeyCallback(vd->Window, i, 0, GLFW_RELEASE, 0); // Later params are only used for main viewport, on which this function is never called. -#if defined(AX_USE_GL) // axmol spec - auto p = (ax::backend::OpenGLState*)glfwGetWindowUserPointer(vd->Window); - if (p) - delete p; +#if AX_RENDER_API == AX_RENDER_API_GL // axmol spec + using namespace ax::rhi; + // destroy imgui multi-viewport window gl state + auto isolated = (gl::OpenGLState*)glfwGetWindowUserPointer(vd->Window); + if (isolated) + delete isolated; #endif ImGui_ImplGlfw_ContextMap_Remove(vd->Window); glfwDestroyWindow(vd->Window); @@ -1564,10 +1576,15 @@ static LRESULT CALLBACK ImGui_ImplGlfw_WndProc(HWND hWnd, UINT msg, WPARAM wPara // axmol spec IMGUI_IMPL_API bool ImGui_ImplGlfw_InitForAxmol(GLFWwindow* window, bool install_callbacks) { -#if defined(AX_USE_GL) +#if AX_RENDER_API == AX_RENDER_API_GL return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_OpenGL); -#else +#elif AX_RENDER_API == AX_RENDER_API_MTL return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_Metal); +#elif AX_RENDER_API == AX_RENDER_API_D3D + return ImGui_ImplGlfw_Init(window, install_callbacks, GlfwClientApi_D3D); +#else +#error "imgui glfw backend not support current render API" + return false; #endif } diff --git a/extensions/Inspector/README.md b/extensions/Inspector/README.md index 154c61aa0060..09d4b9aa9473 100644 --- a/extensions/Inspector/README.md +++ b/extensions/Inspector/README.md @@ -12,13 +12,13 @@ call `openForScene(ax::Scene*)` in your `onEnter` overload and `close` in your ` #include "Inspector/Inspector.h" class MyScene : public ax::Scene { - virtual void onEnter() override { + void onEnter() override { ax::Scene::onEnter(); ax::extension::Inspector::getInstance()->openForScene(this); } - virtual void onExit() override { + void onExit() override { ax::extension::Inspector::getInstance()->close(); ax::Scene::onExit(); } }; -``` \ No newline at end of file +``` diff --git a/extensions/Inspector/src/Inspector/Inspector.cpp b/extensions/Inspector/src/Inspector/Inspector.cpp index 636a77344156..0c71e69c8fe2 100644 --- a/extensions/Inspector/src/Inspector/Inspector.cpp +++ b/extensions/Inspector/src/Inspector/Inspector.cpp @@ -1,6 +1,6 @@ #include "Inspector.h" #include "ImGuiPresenter.h" -#include "axmol.h" +#include "axmol/axmol.h" #if __has_include() # define AX_HAS_CXXABI 1 @@ -99,9 +99,8 @@ void InspectorNodePropertyHandler::drawProperties(Node* node) auto color = node->getColor(); float _color[4] = {color.r / 255.f, color.g / 255.f, color.b / 255.f, node->getOpacity() / 255.f}; ImGui::ColorEdit4("Color", _color); - node->setColor({static_cast(_color[0] * 255), static_cast(_color[1] * 255), - static_cast(_color[2] * 255)}); - node->setOpacity(static_cast(_color[3] * 255.f)); + node->setColor({static_cast(_color[0] * 255), static_cast(_color[1] * 255), + static_cast(_color[2] * 255), static_cast(_color[3] * 255.f)}); } bool InspectorSpritePropertyHandler::isSupportedType(Node* node) diff --git a/extensions/Inspector/src/Inspector/Inspector.h b/extensions/Inspector/src/Inspector/Inspector.h index 5f59d46c04e4..7a6e3d2283e3 100644 --- a/extensions/Inspector/src/Inspector/Inspector.h +++ b/extensions/Inspector/src/Inspector/Inspector.h @@ -2,12 +2,12 @@ #include #include "extensions/ExtensionMacros.h" -#include "base/Config.h" +#include "axmol/base/Config.h" #include #include -#include "EventListenerCustom.h" -#include "RefPtr.h" -#include "2d/Node.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/base/RefPtr.h" +#include "axmol/2d/Node.h" namespace ax { diff --git a/extensions/JSONDefault/src/JSONDefault/JSONDefault.cpp b/extensions/JSONDefault/src/JSONDefault/JSONDefault.cpp index 6b7c9012a02a..f35f170d37a8 100644 --- a/extensions/JSONDefault/src/JSONDefault/JSONDefault.cpp +++ b/extensions/JSONDefault/src/JSONDefault/JSONDefault.cpp @@ -26,9 +26,9 @@ THE SOFTWARE. ****************************************************************************/ #include "JSONDefault.h" -#include "base/Utils.h" -#include "platform/Common.h" -#include "platform/FileUtils.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/Common.h" +#include "axmol/platform/FileUtils.h" #include "rapidjson/prettywriter.h" #include "rapidjson/reader.h" diff --git a/extensions/JSONDefault/src/JSONDefault/JSONDefault.h b/extensions/JSONDefault/src/JSONDefault/JSONDefault.h index 948e48e2688d..604bf95628bd 100644 --- a/extensions/JSONDefault/src/JSONDefault/JSONDefault.h +++ b/extensions/JSONDefault/src/JSONDefault/JSONDefault.h @@ -26,7 +26,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include "extensions/ExtensionMacros.h" #include diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.cpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.cpp index ac7b03acd22a..093839d29da5 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.cpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -7,7 +7,7 @@ #include "CubismCommandBuffer_Cocos2dx.hpp" #include "CubismFramework.hpp" -#include "renderer/backend/RenderTarget.h" +#include "axmol/rhi/RenderTarget.h" //------------ LIVE2D NAMESPACE ------------ namespace Live2D { namespace Cubism { namespace Framework { namespace Rendering { @@ -20,14 +20,14 @@ CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::~DrawCommand() { } -ax::backend::BlendDescriptor* CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::GetBlendDescriptor() +ax::rhi::BlendDesc* CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::GetBlendDescriptor() { - return &_command.getPipelineDescriptor().blendDescriptor; + return &_command.getPipelineDesc().blendDesc; } -ax::PipelineDescriptor* CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::GetPipelineDescriptor() +ax::PipelineDesc* CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::GetPipelineDescriptor() { - return &_command.getPipelineDescriptor(); + return &_command.getPipelineDesc(); } ax::CustomCommand* CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::DrawCommand::GetCommand() @@ -58,7 +58,7 @@ void CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::CreateVertexBuffer(csmSize void CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::CreateIndexBuffer(csmSizeInt count) { _ibCount = count; - _drawCommandDraw.GetCommand()->createIndexBuffer(ax::backend::IndexFormat::U_SHORT, count, ax::CustomCommand::BufferUsage::DYNAMIC); + _drawCommandDraw.GetCommand()->createIndexBuffer(ax::rhi::IndexFormat::U_SHORT, count, ax::CustomCommand::BufferUsage::DYNAMIC); } void CubismCommandBuffer_Cocos2dx::DrawCommandBuffer::UpdateVertexBuffer(void* data, void* uvData, csmSizeInt count) @@ -210,7 +210,7 @@ void CubismCommandBuffer_Cocos2dx::SetWindingMode(WindingType windingType) void CubismCommandBuffer_Cocos2dx::Clear(csmFloat32 r, csmFloat32 g, csmFloat32 b, csmFloat32 a) { // Add the callback command internally. - GetCocos2dRenderer()->clear(ax::ClearFlag::COLOR, ax::Color4F(r, g, b, a), 0.0f, 0, 0.0f); + GetCocos2dRenderer()->clear(ax::ClearFlag::COLOR, ax::Color(r, g, b, a), 0.0f, 0, 0.0f); } void CubismCommandBuffer_Cocos2dx::Viewport(csmFloat32 x, csmFloat32 y, csmFloat32 w, csmFloat32 h) @@ -224,12 +224,12 @@ void CubismCommandBuffer_Cocos2dx::Viewport(csmFloat32 x, csmFloat32 y, csmFloat ); } -void CubismCommandBuffer_Cocos2dx::SetColorBuffer(backend::TextureBackend* colorBuffer) +void CubismCommandBuffer_Cocos2dx::SetColorBuffer(rhi::Texture* colorBuffer) { _currentColorBuffer = colorBuffer; AddCommand([=]() -> void { - backend::RenderTarget* rt = nullptr; + rhi::RenderTarget* rt = nullptr; if (colorBuffer) { rt = GetCocos2dRenderer()->getOffscreenRenderTarget(); @@ -244,7 +244,7 @@ void CubismCommandBuffer_Cocos2dx::SetColorBuffer(backend::TextureBackend* color }); } -backend::TextureBackend* CubismCommandBuffer_Cocos2dx::GetColorBuffer() +rhi::Texture* CubismCommandBuffer_Cocos2dx::GetColorBuffer() { return _currentColorBuffer; } diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.hpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.hpp index 40fc1803eba2..517b584d3465 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.hpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismCommandBuffer_Cocos2dx.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -8,7 +8,7 @@ #pragma once #include "CubismFramework.hpp" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #ifdef CSM_TARGET_ANDROID_ES2 #include @@ -34,7 +34,7 @@ #include #endif -#include "renderer/backend/Texture.h" +#include "axmol/rhi/Texture.h" using namespace ax; @@ -57,8 +57,8 @@ class CubismCommandBuffer_Cocos2dx DrawCommand(); virtual ~DrawCommand(); - ax::backend::BlendDescriptor* GetBlendDescriptor(); - ax::PipelineDescriptor* GetPipelineDescriptor(); + ax::rhi::BlendDesc* GetBlendDescriptor(); + ax::PipelineDesc* GetPipelineDescriptor(); ax::CustomCommand* GetCommand(); private: @@ -150,15 +150,15 @@ class CubismCommandBuffer_Cocos2dx void Viewport(csmFloat32 x, csmFloat32 y, csmFloat32 w, csmFloat32 h); - void SetColorBuffer(backend::TextureBackend* colorBuffer); - backend::TextureBackend* GetColorBuffer(); + void SetColorBuffer(rhi::Texture* colorBuffer); + rhi::Texture* GetColorBuffer(); void AddDrawCommand(DrawCommandBuffer::DrawCommand* drawCommand); private: void AddCommand(const std::function& fn); - backend::TextureBackend* _currentColorBuffer; + rhi::Texture* _currentColorBuffer; OperationStateData _operationStateArray[OperationType_TypeMax]; }; diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.cpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.cpp index 2e6657b198fa..411d430394ea 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.cpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -22,7 +22,7 @@ CubismOffscreenFrame_Cocos2dx::CubismOffscreenFrame_Cocos2dx() void CubismOffscreenFrame_Cocos2dx::BeginDraw(CubismCommandBuffer_Cocos2dx* commandBuffer, - backend::TextureBackend* colorBufferOnFinishDrawing) + rhi::Texture* colorBufferOnFinishDrawing) { if (!IsValid()) { @@ -92,14 +92,7 @@ csmBool CubismOffscreenFrame_Cocos2dx::CreateOffscreenFrame(csmUint32 displayBuf _renderTexture->retain(); - _renderTexture->getSprite()->getTexture()->setTexParameters( - ax::Texture2D::TexParams( - ax::backend::SamplerFilter::LINEAR, // MagFilter - ax::backend::SamplerFilter::LINEAR, // MinFilter - ax::backend::SamplerAddressMode::CLAMP_TO_EDGE, // AddressingMode S - ax::backend::SamplerAddressMode::CLAMP_TO_EDGE // AddressingMode T - ) - ); + _renderTexture->getSprite()->getTexture()->setTexParameters(ax::Texture2D::TexParams{}); texture2d = _renderTexture->getSprite()->getTexture(); _colorBuffer = texture2d->getBackendTexture(); diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.hpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.hpp index feb6f1d06d4d..8398b2e3aac2 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.hpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismOffscreenSurface_Cocos2dx.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -38,7 +38,7 @@ #include #endif -#include "renderer/backend/RenderTarget.h" +#include "axmol/rhi/RenderTarget.h" using namespace ax; @@ -59,7 +59,7 @@ class CubismOffscreenFrame_Cocos2dx * @brief 指定の描画ターゲットに向けて描画開始 * */ - void BeginDraw(CubismCommandBuffer_Cocos2dx* commandBuffer, backend::TextureBackend* colorBufferOnFinishDrawing); + void BeginDraw(CubismCommandBuffer_Cocos2dx* commandBuffer, rhi::Texture* colorBufferOnFinishDrawing); /** * @brief 描画終了 @@ -114,10 +114,10 @@ class CubismOffscreenFrame_Cocos2dx private: ax::RenderTexture* _renderTexture; ///< レンダリングターゲットとしてのアドレス - backend::TextureBackend* _colorBuffer; + rhi::Texture* _colorBuffer; csmBool _isInheritedRenderTexture; - backend::TextureBackend* _previousColorBuffer; ///< 旧フレームバッファ + rhi::Texture* _previousColorBuffer; ///< 旧フレームバッファ csmUint32 _bufferWidth; ///< Create時に指定された幅 csmUint32 _bufferHeight; ///< Create時に指定された高さ diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.cpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.cpp index 51af3f4da376..4044990474b9 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.cpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.cpp @@ -10,7 +10,7 @@ #include "Type/csmVector.hpp" #include "Model/CubismModel.hpp" #include -#include "renderer/backend/DriverBase.h" +#include "axmol/rhi/DriverBase.h" using namespace ax; @@ -142,7 +142,7 @@ CubismClippingContext* CubismClippingManager_Cocos2dx::FindSameClip(const csmInt return NULL; //見つからなかった } -void CubismClippingManager_Cocos2dx::SetupClippingContext(CubismModel& model, CubismRenderer_Cocos2dx* renderer, backend::TextureBackend* lastColorBuffer, csmRectF lastViewport) +void CubismClippingManager_Cocos2dx::SetupClippingContext(CubismModel& model, CubismRenderer_Cocos2dx* renderer, rhi::Texture* lastColorBuffer, csmRectF lastViewport) { _currentFrameNo++; @@ -581,7 +581,7 @@ CubismClippingContext::CubismClippingContext(CubismClippingManager_Cocos2dx* man drawCommandBuffer = CSM_NEW CubismCommandBuffer_Cocos2dx::DrawCommandBuffer(); drawCommandBuffer->GetCommandDraw()->GetCommand()->setDrawType(ax::CustomCommand::DrawType::ELEMENT); - drawCommandBuffer->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::backend::PrimitiveType::TRIANGLE); + drawCommandBuffer->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::rhi::PrimitiveType::TRIANGLE); drawCommandBuffer->CreateVertexBuffer(vertexSize, drawableVertexCount * 2); // Vertices + UVs drawCommandBuffer->CreateIndexBuffer(drawableVertexIndexCount); @@ -650,16 +650,16 @@ void CubismRendererProfile_Cocos2dx::Save() // モデル描画直前のFBOとビューポートを保存 - // _lastColorBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(backend::TargetBufferFlags::COLOR); - // _lastDepthBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(backend::TargetBufferFlags::DEPTH); - // _lastStencilBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(backend::TargetBufferFlags::STENCIL); + // _lastColorBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(rhi::TargetBufferFlags::COLOR); + // _lastDepthBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(rhi::TargetBufferFlags::DEPTH); + // _lastStencilBuffer = GetCocos2dRenderer()->getRenderTargetAttachment(rhi::TargetBufferFlags::STENCIL); // _lastRenderTargetFlag = GetCocos2dRenderer()->getRenderTargetFlag(); // _lastColorBuffer = nullptr; // unused _lastRenderTarget = GetCocos2dRenderer()->getRenderTarget(); //_lastRenderTargetFlag = _lastRenderTarget->getTargetFlags(); _lastColorBuffer = _lastRenderTarget->_color[0].texture; - _lastDepthBuffer = _lastRenderTarget->_depth.texture; - _lastStencilBuffer = _lastRenderTarget->_stencil.texture; + _lastDepthBuffer = _lastRenderTarget->_depthStencil.texture; + _lastStencilBuffer = _lastRenderTarget->_depthStencil.texture; _lastViewport = csmRectF(GetCocos2dRenderer()->getViewport().x, GetCocos2dRenderer()->getViewport().y, GetCocos2dRenderer()->getViewport().w, GetCocos2dRenderer()->getViewport().h); } @@ -682,8 +682,7 @@ void CubismRendererProfile_Cocos2dx::Restore() auto restoringRT = _lastRenderTarget; restoringRT->setColorAttachment(_lastColorBuffer); - restoringRT->setDepthAttachment(_lastDepthBuffer); - restoringRT->setStencilAttachment(_lastStencilBuffer); + restoringRT->setDepthStencilAttachment(_lastDepthBuffer); // restoringRT->setTargetFlags(_lastRenderTargetFlag); cmd->func = [=]() -> void { GetCocos2dRenderer()->setRenderTarget(restoringRT); @@ -910,23 +909,23 @@ void CubismShader_Cocos2dx::GenerateShaders() #endif // SetupMask - _shaderSets[0]->AttributePositionLocation = _shaderSets[0]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[0]->AttributeTexCoordLocation = _shaderSets[0]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[0]->AttributePositionLocation = _shaderSets[0]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[0]->AttributeTexCoordLocation = _shaderSets[0]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[0]->SamplerTexture0Location = _shaderSets[0]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[0]->UniformClipMatrixLocation = _shaderSets[0]->ShaderProgram->getUniformLocation("u_clipMatrix"); _shaderSets[0]->UnifromChannelFlagLocation = _shaderSets[0]->ShaderProgram->getUniformLocation("u_channelFlag"); _shaderSets[0]->UniformBaseColorLocation = _shaderSets[0]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常 - _shaderSets[1]->AttributePositionLocation = _shaderSets[1]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[1]->AttributeTexCoordLocation = _shaderSets[1]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[1]->AttributePositionLocation = _shaderSets[1]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[1]->AttributeTexCoordLocation = _shaderSets[1]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[1]->SamplerTexture0Location = _shaderSets[1]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[1]->UniformMatrixLocation = _shaderSets[1]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[1]->UniformBaseColorLocation = _shaderSets[1]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常(クリッピング) - _shaderSets[2]->AttributePositionLocation = _shaderSets[2]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[2]->AttributeTexCoordLocation = _shaderSets[2]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[2]->AttributePositionLocation = _shaderSets[2]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[2]->AttributeTexCoordLocation = _shaderSets[2]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[2]->SamplerTexture0Location = _shaderSets[2]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[2]->SamplerTexture1Location = _shaderSets[2]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[2]->UniformMatrixLocation = _shaderSets[2]->ShaderProgram->getUniformLocation("u_matrix"); @@ -935,8 +934,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[2]->UniformBaseColorLocation = _shaderSets[2]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常(クリッピング・反転) - _shaderSets[3]->AttributePositionLocation = _shaderSets[3]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[3]->AttributeTexCoordLocation = _shaderSets[3]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[3]->AttributePositionLocation = _shaderSets[3]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[3]->AttributeTexCoordLocation = _shaderSets[3]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[3]->SamplerTexture0Location = _shaderSets[3]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[3]->SamplerTexture1Location = _shaderSets[3]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[3]->UniformMatrixLocation = _shaderSets[3]->ShaderProgram->getUniformLocation("u_matrix"); @@ -945,15 +944,15 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[3]->UniformBaseColorLocation = _shaderSets[3]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常(PremultipliedAlpha) - _shaderSets[4]->AttributePositionLocation = _shaderSets[4]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[4]->AttributeTexCoordLocation = _shaderSets[4]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[4]->AttributePositionLocation = _shaderSets[4]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[4]->AttributeTexCoordLocation = _shaderSets[4]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[4]->SamplerTexture0Location = _shaderSets[4]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[4]->UniformMatrixLocation = _shaderSets[4]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[4]->UniformBaseColorLocation = _shaderSets[4]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常(クリッピング、PremultipliedAlpha) - _shaderSets[5]->AttributePositionLocation = _shaderSets[5]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[5]->AttributeTexCoordLocation = _shaderSets[5]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[5]->AttributePositionLocation = _shaderSets[5]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[5]->AttributeTexCoordLocation = _shaderSets[5]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[5]->SamplerTexture0Location = _shaderSets[5]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[5]->SamplerTexture1Location = _shaderSets[5]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[5]->UniformMatrixLocation = _shaderSets[5]->ShaderProgram->getUniformLocation("u_matrix"); @@ -962,8 +961,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[5]->UniformBaseColorLocation = _shaderSets[5]->ShaderProgram->getUniformLocation("u_baseColor"); // 通常(クリッピング・反転、PremultipliedAlpha) - _shaderSets[6]->AttributePositionLocation = _shaderSets[6]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[6]->AttributeTexCoordLocation = _shaderSets[6]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[6]->AttributePositionLocation = _shaderSets[6]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[6]->AttributeTexCoordLocation = _shaderSets[6]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[6]->SamplerTexture0Location = _shaderSets[6]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[6]->SamplerTexture1Location = _shaderSets[6]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[6]->UniformMatrixLocation = _shaderSets[6]->ShaderProgram->getUniformLocation("u_matrix"); @@ -972,15 +971,15 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[6]->UniformBaseColorLocation = _shaderSets[6]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算 - _shaderSets[7]->AttributePositionLocation = _shaderSets[7]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[7]->AttributeTexCoordLocation = _shaderSets[7]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[7]->AttributePositionLocation = _shaderSets[7]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[7]->AttributeTexCoordLocation = _shaderSets[7]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[7]->SamplerTexture0Location = _shaderSets[7]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[7]->UniformMatrixLocation = _shaderSets[7]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[7]->UniformBaseColorLocation = _shaderSets[7]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算(クリッピング) - _shaderSets[8]->AttributePositionLocation = _shaderSets[8]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[8]->AttributeTexCoordLocation = _shaderSets[8]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[8]->AttributePositionLocation = _shaderSets[8]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[8]->AttributeTexCoordLocation = _shaderSets[8]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[8]->SamplerTexture0Location = _shaderSets[8]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[8]->SamplerTexture1Location = _shaderSets[8]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[8]->UniformMatrixLocation = _shaderSets[8]->ShaderProgram->getUniformLocation("u_matrix"); @@ -989,8 +988,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[8]->UniformBaseColorLocation = _shaderSets[8]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算(クリッピング・反転) - _shaderSets[9]->AttributePositionLocation = _shaderSets[9]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[9]->AttributeTexCoordLocation = _shaderSets[9]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[9]->AttributePositionLocation = _shaderSets[9]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[9]->AttributeTexCoordLocation = _shaderSets[9]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[9]->SamplerTexture0Location = _shaderSets[9]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[9]->SamplerTexture1Location = _shaderSets[9]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[9]->UniformMatrixLocation = _shaderSets[9]->ShaderProgram->getUniformLocation("u_matrix"); @@ -999,15 +998,15 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[9]->UniformBaseColorLocation = _shaderSets[9]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算(PremultipliedAlpha) - _shaderSets[10]->AttributePositionLocation = _shaderSets[10]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[10]->AttributeTexCoordLocation = _shaderSets[10]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[10]->AttributePositionLocation = _shaderSets[10]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[10]->AttributeTexCoordLocation = _shaderSets[10]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[10]->SamplerTexture0Location = _shaderSets[10]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[10]->UniformMatrixLocation = _shaderSets[10]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[10]->UniformBaseColorLocation = _shaderSets[10]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算(クリッピング、PremultipliedAlpha) - _shaderSets[11]->AttributePositionLocation = _shaderSets[11]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[11]->AttributeTexCoordLocation = _shaderSets[11]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[11]->AttributePositionLocation = _shaderSets[11]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[11]->AttributeTexCoordLocation = _shaderSets[11]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[11]->SamplerTexture0Location = _shaderSets[11]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[11]->SamplerTexture1Location = _shaderSets[11]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[11]->UniformMatrixLocation = _shaderSets[11]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1016,8 +1015,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[11]->UniformBaseColorLocation = _shaderSets[11]->ShaderProgram->getUniformLocation("u_baseColor"); // 加算(クリッピング・反転、PremultipliedAlpha) - _shaderSets[12]->AttributePositionLocation = _shaderSets[12]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[12]->AttributeTexCoordLocation = _shaderSets[12]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[12]->AttributePositionLocation = _shaderSets[12]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[12]->AttributeTexCoordLocation = _shaderSets[12]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[12]->SamplerTexture0Location = _shaderSets[12]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[12]->SamplerTexture1Location = _shaderSets[12]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[12]->UniformMatrixLocation = _shaderSets[12]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1026,15 +1025,15 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[12]->UniformBaseColorLocation = _shaderSets[12]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算 - _shaderSets[13]->AttributePositionLocation = _shaderSets[13]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[13]->AttributeTexCoordLocation = _shaderSets[13]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[13]->AttributePositionLocation = _shaderSets[13]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[13]->AttributeTexCoordLocation = _shaderSets[13]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[13]->SamplerTexture0Location = _shaderSets[13]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[13]->UniformMatrixLocation = _shaderSets[13]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[13]->UniformBaseColorLocation = _shaderSets[13]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算(クリッピング) - _shaderSets[14]->AttributePositionLocation = _shaderSets[14]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[14]->AttributeTexCoordLocation = _shaderSets[14]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[14]->AttributePositionLocation = _shaderSets[14]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[14]->AttributeTexCoordLocation = _shaderSets[14]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[14]->SamplerTexture0Location = _shaderSets[14]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[14]->SamplerTexture1Location = _shaderSets[14]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[14]->UniformMatrixLocation = _shaderSets[14]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1043,8 +1042,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[14]->UniformBaseColorLocation = _shaderSets[14]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算(クリッピング・反転) - _shaderSets[15]->AttributePositionLocation = _shaderSets[15]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[15]->AttributeTexCoordLocation = _shaderSets[15]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[15]->AttributePositionLocation = _shaderSets[15]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[15]->AttributeTexCoordLocation = _shaderSets[15]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[15]->SamplerTexture0Location = _shaderSets[15]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[15]->SamplerTexture1Location = _shaderSets[15]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[15]->UniformMatrixLocation = _shaderSets[15]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1053,15 +1052,15 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[15]->UniformBaseColorLocation = _shaderSets[15]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算(PremultipliedAlpha) - _shaderSets[16]->AttributePositionLocation = _shaderSets[16]->ShaderProgram->getAttributeLocation( "a_position"); - _shaderSets[16]->AttributeTexCoordLocation = _shaderSets[16]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[16]->AttributePositionLocation = _shaderSets[16]->ShaderProgram->getVertexInputDesc( "a_position"); + _shaderSets[16]->AttributeTexCoordLocation = _shaderSets[16]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[16]->SamplerTexture0Location = _shaderSets[16]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[16]->UniformMatrixLocation = _shaderSets[16]->ShaderProgram->getUniformLocation("u_matrix"); _shaderSets[16]->UniformBaseColorLocation = _shaderSets[16]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算(クリッピング、PremultipliedAlpha) - _shaderSets[17]->AttributePositionLocation = _shaderSets[17]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[17]->AttributeTexCoordLocation = _shaderSets[17]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[17]->AttributePositionLocation = _shaderSets[17]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[17]->AttributeTexCoordLocation = _shaderSets[17]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[17]->SamplerTexture0Location = _shaderSets[17]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[17]->SamplerTexture1Location = _shaderSets[17]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[17]->UniformMatrixLocation = _shaderSets[17]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1070,8 +1069,8 @@ void CubismShader_Cocos2dx::GenerateShaders() _shaderSets[17]->UniformBaseColorLocation = _shaderSets[17]->ShaderProgram->getUniformLocation("u_baseColor"); // 乗算(クリッピング・反転、PremultipliedAlpha) - _shaderSets[18]->AttributePositionLocation = _shaderSets[18]->ShaderProgram->getAttributeLocation("a_position"); - _shaderSets[18]->AttributeTexCoordLocation = _shaderSets[18]->ShaderProgram->getAttributeLocation("a_texCoord"); + _shaderSets[18]->AttributePositionLocation = _shaderSets[18]->ShaderProgram->getVertexInputDesc("a_position"); + _shaderSets[18]->AttributeTexCoordLocation = _shaderSets[18]->ShaderProgram->getVertexInputDesc("a_texCoord"); _shaderSets[18]->SamplerTexture0Location = _shaderSets[18]->ShaderProgram->getUniformLocation("u_tex0"); _shaderSets[18]->SamplerTexture1Location = _shaderSets[18]->ShaderProgram->getUniformLocation("u_tex1"); _shaderSets[18]->UniformMatrixLocation = _shaderSets[18]->ShaderProgram->getUniformLocation("u_matrix"); @@ -1093,10 +1092,10 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra GenerateShaders(); } - ax::backend::BlendDescriptor* blendDescriptor = drawCommand->GetBlendDescriptor(); - ax::PipelineDescriptor* pipelineDescriptor = drawCommand->GetPipelineDescriptor(); + ax::rhi::BlendDesc* blendDescriptor = drawCommand->GetBlendDescriptor(); + ax::PipelineDesc* pipelineDescriptor = drawCommand->GetPipelineDescriptor(); - ax::backend::ProgramState* programState = pipelineDescriptor->programState; + ax::rhi::ProgramState* programState = pipelineDescriptor->programState; VertexLayout* layout = nullptr; if (renderer->GetClippingContextBufferForMask() != NULL) // マスク生成時 @@ -1105,7 +1104,7 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra if (!programState) { - programState = new ax::backend::ProgramState(shaderSet->ShaderProgram); + programState = new ax::rhi::ProgramState(shaderSet->ShaderProgram); } layout = programState->getMutableVertexLayout(); @@ -1114,9 +1113,9 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra programState->setTexture(shaderSet->SamplerTexture0Location, 0, texture->getBackendTexture()); // 頂点配列の設定 - layout->setAttrib("a_position", shaderSet->AttributePositionLocation, ax::backend::VertexFormat::FLOAT2, 0, false); + layout->setAttrib("a_position", shaderSet->AttributePositionLocation, ax::rhi::VertexFormat::FLOAT2, 0, false); // テクスチャ頂点の設定 - layout->setAttrib("a_texCoord", shaderSet->AttributeTexCoordLocation, ax::backend::VertexFormat::FLOAT2, + layout->setAttrib("a_texCoord", shaderSet->AttributeTexCoordLocation, ax::rhi::VertexFormat::FLOAT2, sizeof(csmFloat32) * 2, false); // チャンネル @@ -1137,10 +1136,10 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra rect->GetBottom() * 2.0f - 1.0f }; programState->setUniform(shaderSet->UniformBaseColorLocation, base, sizeof(float) * 4); - blendDescriptor->sourceRGBBlendFactor = ax::backend::BlendFactor::ZERO; - blendDescriptor->destinationRGBBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_COLOR; - blendDescriptor->sourceAlphaBlendFactor = ax::backend::BlendFactor::ZERO; - blendDescriptor->destinationAlphaBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceRGBBlendFactor = ax::rhi::BlendFactor::ZERO; + blendDescriptor->destinationRGBBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_COLOR; + blendDescriptor->sourceAlphaBlendFactor = ax::rhi::BlendFactor::ZERO; + blendDescriptor->destinationAlphaBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } else // マスク生成以外の場合 { @@ -1153,40 +1152,40 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra case CubismRenderer::CubismBlendMode_Normal: default: shaderSet = _shaderSets[ShaderNames_Normal + offset]; - blendDescriptor->sourceRGBBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->destinationRGBBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor->sourceAlphaBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->destinationAlphaBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceRGBBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->destinationRGBBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceAlphaBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->destinationAlphaBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; break; case CubismRenderer::CubismBlendMode_Additive: shaderSet = _shaderSets[ShaderNames_Add + offset]; - blendDescriptor->sourceRGBBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->destinationRGBBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->sourceAlphaBlendFactor = ax::backend::BlendFactor::ZERO; - blendDescriptor->destinationAlphaBlendFactor = ax::backend::BlendFactor::ONE; + blendDescriptor->sourceRGBBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->destinationRGBBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->sourceAlphaBlendFactor = ax::rhi::BlendFactor::ZERO; + blendDescriptor->destinationAlphaBlendFactor = ax::rhi::BlendFactor::ONE; break; case CubismRenderer::CubismBlendMode_Multiplicative: shaderSet = _shaderSets[ShaderNames_Mult + offset]; - blendDescriptor->sourceRGBBlendFactor = ax::backend::BlendFactor::DST_COLOR; - blendDescriptor->destinationRGBBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor->sourceAlphaBlendFactor = ax::backend::BlendFactor::ZERO; - blendDescriptor->destinationAlphaBlendFactor = ax::backend::BlendFactor::ONE; + blendDescriptor->sourceRGBBlendFactor = ax::rhi::BlendFactor::DST_COLOR; + blendDescriptor->destinationRGBBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceAlphaBlendFactor = ax::rhi::BlendFactor::ZERO; + blendDescriptor->destinationAlphaBlendFactor = ax::rhi::BlendFactor::ONE; break; } if (!programState) { - programState = new ax::backend::ProgramState(shaderSet->ShaderProgram); + programState = new ax::rhi::ProgramState(shaderSet->ShaderProgram); } layout = programState->getMutableVertexLayout(); // 頂点配列の設定 - layout->setAttrib("a_position", shaderSet->AttributePositionLocation, ax::backend::VertexFormat::FLOAT2, 0, + layout->setAttrib("a_position", shaderSet->AttributePositionLocation, ax::rhi::VertexFormat::FLOAT2, 0, false); // テクスチャ頂点の設定 - layout->setAttrib("a_texCoord", shaderSet->AttributeTexCoordLocation, ax::backend::VertexFormat::FLOAT2, + layout->setAttrib("a_texCoord", shaderSet->AttributeTexCoordLocation, ax::rhi::VertexFormat::FLOAT2, sizeof(csmFloat32) * 2, false); if (masked) @@ -1225,7 +1224,7 @@ void CubismShader_Cocos2dx::SetupShaderProgram(CubismCommandBuffer_Cocos2dx::Dra pipelineDescriptor->programState = programState; } -ax::backend::Program* CubismShader_Cocos2dx::LoadShaderProgram(const csmChar* vertShaderPath, +ax::rhi::Program* CubismShader_Cocos2dx::LoadShaderProgram(const csmChar* vertShaderPath, const csmChar* fragShaderPath) { // cocos2dx対応 @@ -1314,7 +1313,7 @@ void CubismRenderer_Cocos2dx::Initialize(CubismModel* model) _drawableDrawCommandBuffer[i] = CSM_NEW CubismCommandBuffer_Cocos2dx::DrawCommandBuffer(); _drawableDrawCommandBuffer[i]->GetCommandDraw()->GetCommand()->setDrawType(ax::CustomCommand::DrawType::ELEMENT); - _drawableDrawCommandBuffer[i]->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::backend::PrimitiveType::TRIANGLE); + _drawableDrawCommandBuffer[i]->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::rhi::PrimitiveType::TRIANGLE); _drawableDrawCommandBuffer[i]->CreateVertexBuffer(vertexSize, drawableVertexCount * 2); // Vertices + UVs if (drawableVertexIndexCount > 0) diff --git a/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.hpp b/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.hpp index 7a84a7562268..febfc30f42a5 100644 --- a/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.hpp +++ b/extensions/Live2D/Framework/src/Rendering/axmol/CubismRenderer_Cocos2dx.hpp @@ -107,7 +107,7 @@ class CubismClippingManager_Cocos2dx */ void SetupClippingContext(CubismModel& model, CubismRenderer_Cocos2dx* renderer, - backend::TextureBackend* lastColorBuffer, + rhi::Texture* lastColorBuffer, csmRectF lastViewport); /** @@ -244,15 +244,15 @@ class CubismShader_Cocos2dx */ struct CubismShaderSet { - ax::backend::Program* ShaderProgram; ///< シェーダプログラムのアドレス - unsigned int AttributePositionLocation; ///< シェーダプログラムに渡す変数のアドレス(Position) - unsigned int AttributeTexCoordLocation; ///< シェーダプログラムに渡す変数のアドレス(TexCoord) - ax::backend::UniformLocation UniformMatrixLocation; ///< シェーダプログラムに渡す変数のアドレス(Matrix) - ax::backend::UniformLocation UniformClipMatrixLocation; ///< シェーダプログラムに渡す変数のアドレス(ClipMatrix) - ax::backend::UniformLocation SamplerTexture0Location; ///< シェーダプログラムに渡す変数のアドレス(Texture0) - ax::backend::UniformLocation SamplerTexture1Location; ///< シェーダプログラムに渡す変数のアドレス(Texture1) - ax::backend::UniformLocation UniformBaseColorLocation; ///< シェーダプログラムに渡す変数のアドレス(BaseColor) - ax::backend::UniformLocation UnifromChannelFlagLocation; ///< シェーダプログラムに渡す変数のアドレス(ChannelFlag) + ax::rhi::Program* ShaderProgram; ///< シェーダプログラムのアドレス + const ax::rhi::VertexInputDesc* AttributePositionLocation{nullptr}; ///< シェーダプログラムに渡す変数のアドレス(Position) + const ax::rhi::VertexInputDesc* AttributeTexCoordLocation{nullptr}; ///< シェーダプログラムに渡す変数のアドレス(TexCoord) + ax::rhi::UniformLocation UniformMatrixLocation; ///< シェーダプログラムに渡す変数のアドレス(Matrix) + ax::rhi::UniformLocation UniformClipMatrixLocation; ///< シェーダプログラムに渡す変数のアドレス(ClipMatrix) + ax::rhi::UniformLocation SamplerTexture0Location; ///< シェーダプログラムに渡す変数のアドレス(Texture0) + ax::rhi::UniformLocation SamplerTexture1Location; ///< シェーダプログラムに渡す変数のアドレス(Texture1) + ax::rhi::UniformLocation UniformBaseColorLocation; ///< シェーダプログラムに渡す変数のアドレス(BaseColor) + ax::rhi::UniformLocation UnifromChannelFlagLocation; ///< シェーダプログラムに渡す変数のアドレス(ChannelFlag) }; /** @@ -306,7 +306,7 @@ class CubismShader_Cocos2dx * * @return シェーダプログラムのアドレス */ - ax::backend::Program* LoadShaderProgram(const csmChar* vertShaderPath, const csmChar* fragShaderPath); + ax::rhi::Program* LoadShaderProgram(const csmChar* vertShaderPath, const csmChar* fragShaderPath); #ifdef CSM_TARGET_ANDROID_ES2 public: @@ -363,11 +363,11 @@ class CubismRendererProfile_Cocos2dx csmBool _lastDepthTest; ///< モデル描画直前のGL_DEPTH_TESTパラメータ ax::CullMode _lastCullFace; ///< モデル描画直前のGL_CULL_FACEパラメータ ax::Winding _lastWinding; - backend::TextureBackend* _lastColorBuffer; ///< モデル描画直前のフレームバッファ - backend::TextureBackend* _lastDepthBuffer; - backend::TextureBackend* _lastStencilBuffer; + rhi::Texture* _lastColorBuffer; ///< モデル描画直前のフレームバッファ + rhi::Texture* _lastDepthBuffer; + rhi::Texture* _lastStencilBuffer; //ax::RenderTargetFlag _lastRenderTargetFlag; - backend::RenderTarget* _lastRenderTarget; + rhi::RenderTarget* _lastRenderTarget; csmRectF _lastViewport; ///< モデル描画直前のビューポート }; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUAffector.h index 2efca0f758d3..217d7b606b85 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUAffector.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/Particle3DAffector.h" #include #include diff --git a/extensions/Particle3D/src/Particle3D/PU/PUAffectorManager.h b/extensions/Particle3D/src/Particle3D/PU/PUAffectorManager.h index ad3536da1db2..4bd3857e94cc 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUAffectorManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUAffectorManager.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptTranslator.h" #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUAlignAffectorTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUAlignAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUAlignAffector.h index 99be3749df6a..6e9c6195c380 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUAlignAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUAlignAffector.h @@ -39,8 +39,8 @@ class AX_EX_DLL PUAlignAffector : public PUAffector static PUAlignAffector* create(); - virtual void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** See setResize(). */ @@ -51,7 +51,7 @@ class AX_EX_DLL PUAlignAffector : public PUAffector */ void setResize(bool resize); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUAlignAffector(); virtual ~PUAlignAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBaseCollider.h b/extensions/Particle3D/src/Particle3D/PU/PUBaseCollider.h index ffc0259478c5..c7426925a4ab 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBaseCollider.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBaseCollider.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "3d/AABB.h" +#include "axmol/3d/AABB.h" namespace ax { @@ -68,7 +68,7 @@ class AX_EX_DLL PUBaseCollider : public PUAffector static const IntersectionType DEFAULT_INTERSECTION_TYPE; static const CollisionType DEFAULT_COLLISION_TYPE; - virtual void preUpdateAffector(float deltaTime) override; + void preUpdateAffector(float deltaTime) override; /** Returns the type of intersection. */ @@ -112,7 +112,7 @@ class AX_EX_DLL PUBaseCollider : public PUAffector */ void calculateRotationSpeedAfterCollision(PUParticle3D* particle); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUBaseCollider(); virtual ~PUBaseCollider(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBaseForceAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUBaseForceAffector.h index 610c3475acd0..e237daf4aae4 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBaseForceAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBaseForceAffector.h @@ -26,7 +26,7 @@ #pragma once -#include "math/Math.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUAffector.h" namespace ax @@ -55,7 +55,7 @@ class AX_EX_DLL PUBaseForceAffector : public PUAffector ForceApplication getForceApplication() const; void setForceApplication(ForceApplication forceApplication); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUBaseForceAffector(); virtual ~PUBaseForceAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.cpp b/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.cpp index e6b7018d6eec..8891df87a42d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.cpp @@ -29,14 +29,14 @@ #include "Particle3D/PU/PUParticleSystem3D.h" #include "Particle3D/PU/PUUtil.h" #include "Particle3D/PU/PUSimpleSpline.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/backend/ProgramState.h" -#include "base/Director.h" -#include "3d/MeshRenderer.h" -#include "3d/Mesh.h" -#include "2d/Camera.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/base/Director.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Mesh.h" +#include "axmol/2d/Camera.h" #include namespace ax @@ -269,7 +269,7 @@ void PUBeamRender::prepare() PUBillboardChain::Element element; element = PUBillboardChain::Element( Vec3::ZERO, _rendererScale.x * static_cast(_particleSystem)->getDefaultWidth(), - 0.0f, Vec4::ONE, Quaternion::identity()); // V1.51 + 0.0f, Color::WHITE, Quaternion::identity()); // V1.51 _billboardChain->addChainElement(i, element); } diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.h b/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.h index 88cd00e99949..fa0d8ec9c11e 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBeamRender.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/Particle3DRender.h" #include "Particle3D/PU/PUListener.h" #include "Particle3D/PU/PUBillboardChain.h" @@ -89,13 +89,13 @@ class AX_EX_DLL PUBeamRender : public PURender, public PUListener static PUBeamRender* create(std::string_view texFile = ""); - virtual void prepare() override; - virtual void unPrepare() override; - virtual void updateRender(PUParticle3D* particle, float deltaTime, bool firstParticle) override; + void prepare() override; + void unPrepare() override; + void updateRender(PUParticle3D* particle, float deltaTime, bool firstParticle) override; - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; - virtual void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; /** Getters and Setters */ @@ -124,7 +124,7 @@ class AX_EX_DLL PUBeamRender : public PURender, public PUListener */ void destroyAll(); - virtual PUBeamRender* clone() override; + PUBeamRender* clone() override; void copyAttributesTo(PUBeamRender* render); PUBeamRender(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.cpp b/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.cpp index b8c873b92e18..d9ceb64f8585 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #include "Particle3D/PU/PUBehaviour.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.h b/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.h index e304d228746c..04c81f5a30e2 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBehaviour.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include #include diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBehaviourManager.h b/extensions/Particle3D/src/Particle3D/PU/PUBehaviourManager.h index a4198d8962dd..ead63ae5787f 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBehaviourManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBehaviourManager.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptTranslator.h" #include "Particle3D/PU/PUBehaviour.h" #include "Particle3D/PU/PUSlaveBehaviourTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.cpp b/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.cpp index 2769431f15be..3ea234134eed 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.cpp @@ -25,18 +25,17 @@ ****************************************************************************/ #include "Particle3D/PU/PUBillboardChain.h" #include // offsetof -#include "base/Types.h" +#include "axmol/base/Types.h" #include "Particle3D/PU/PUParticleSystem3D.h" -#include "base/Director.h" -#include "renderer/Shaders.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/Buffer.h" -#include "renderer/backend/DriverBase.h" -#include "2d/Camera.h" -#include "3d/MeshRenderer.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/2d/Camera.h" +#include "axmol/3d/MeshRenderer.h" namespace ax { @@ -45,7 +44,7 @@ const size_t PUBillboardChain::SEGMENT_EMPTY = std::numeric_limits::max( //----------------------------------------------------------------------- PUBillboardChain::Element::Element() {} //----------------------------------------------------------------------- -PUBillboardChain::Element::Element(const Vec3& pos, float w, float tex, const Vec4& col, const Quaternion& ori) +PUBillboardChain::Element::Element(const Vec3& pos, float w, float tex, const Color& col, const Quaternion& ori) : position(pos), width(w), texCoord(tex), color(col), orientation(ori) {} //----------------------------------------------------------------------- @@ -77,7 +76,7 @@ PUBillboardChain::PUBillboardChain(std::string_view /*name*/, { _stateBlock.setCullFace(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setDepthTest(false); _stateBlock.setDepthWrite(false); _stateBlock.setBlend(true); @@ -157,15 +156,15 @@ void PUBillboardChain::setupBuffers() AX_SAFE_RELEASE_NULL(_vertexBuffer); AX_SAFE_RELEASE_NULL(_indexBuffer); - size_t stride = sizeof(VertexInfo); - _vertexBuffer = backend::DriverBase::getInstance()->newBuffer( - stride * _chainElementList.size() * 2, backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); - VertexInfo vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Vec4::ONE}; + size_t stride = sizeof(V3F_T2F_C4F); + _vertexBuffer = rhi::DriverBase::getInstance()->createBuffer( + stride * _chainElementList.size() * 2, rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); + V3F_T2F_C4F vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Color::WHITE}; _vertices.resize(_chainElementList.size() * 2, vi); - _indexBuffer = - backend::DriverBase::getInstance()->newBuffer(_chainCount * _maxElementsPerChain * 6 * sizeof(uint16_t), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + _indexBuffer = rhi::DriverBase::getInstance()->createBuffer( + _chainCount * _maxElementsPerChain * 6 * sizeof(uint16_t), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); _indices.resize(_chainCount * _maxElementsPerChain * 6, 0); @@ -404,7 +403,7 @@ void PUBillboardChain::updateVertexBuffer(const Mat4& camMat) if (!_vertexContentDirty) return; - VertexInfo vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Vec4::ONE}; + V3F_T2F_C4F vi = {Vec3(0.0f, 0.0f, 0.0f), Vec2(0.0f, 0.0f), Color::WHITE}; _vertices.assign(_vertices.size(), vi); // HardwareVertexBufferSharedPtr pBuffer = // _vertexData->vertexBufferBinding->getBuffer(0); @@ -501,15 +500,15 @@ void PUBillboardChain::updateVertexBuffer(const Mat4& camMat) { //*pFloat++ = elem.texCoord; //*pFloat++ = _otherTexCoordRange[0]; - _vertices[vertexIndex + 0].uv.x = elem.texCoord; - _vertices[vertexIndex + 0].uv.y = _otherTexCoordRange[0]; + _vertices[vertexIndex + 0].texCoord.x = elem.texCoord; + _vertices[vertexIndex + 0].texCoord.y = _otherTexCoordRange[0]; } else { //*pFloat++ = _otherTexCoordRange[0]; //*pFloat++ = elem.texCoord; - _vertices[vertexIndex + 0].uv.x = _otherTexCoordRange[0]; - _vertices[vertexIndex + 0].uv.y = elem.texCoord; + _vertices[vertexIndex + 0].texCoord.x = _otherTexCoordRange[0]; + _vertices[vertexIndex + 0].texCoord.y = elem.texCoord; } // pBase = static_cast(pFloat); } @@ -538,15 +537,15 @@ void PUBillboardChain::updateVertexBuffer(const Mat4& camMat) { //*pFloat++ = elem.texCoord; //*pFloat++ = _otherTexCoordRange[1]; - _vertices[vertexIndex + 1].uv.x = elem.texCoord; - _vertices[vertexIndex + 1].uv.y = _otherTexCoordRange[1]; + _vertices[vertexIndex + 1].texCoord.x = elem.texCoord; + _vertices[vertexIndex + 1].texCoord.y = _otherTexCoordRange[1]; } else { //*pFloat++ = _otherTexCoordRange[1]; //*pFloat++ = elem.texCoord; - _vertices[vertexIndex + 1].uv.x = _otherTexCoordRange[1]; - _vertices[vertexIndex + 1].uv.y = elem.texCoord; + _vertices[vertexIndex + 1].texCoord.x = _otherTexCoordRange[1]; + _vertices[vertexIndex + 1].texCoord.y = elem.texCoord; } } @@ -638,18 +637,18 @@ void PUBillboardChain::init(std::string_view texFile) if (tex) { _texture = tex; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_TEXTURE_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_TEXTURE_3D); + _programState = new rhi::ProgramState(program); } } if (!_programState) { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_COLOR_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_COLOR_3D); + _programState = new rhi::ProgramState(program); } - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); pipelineDescriptor.programState = _programState; _locColor = _programState->getUniformLocation("u_color"); @@ -661,7 +660,7 @@ void PUBillboardChain::init(std::string_view texFile) _stateBlock.setDepthTest(true); _stateBlock.setDepthWrite(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setCullFace(true); _meshCommand.setBeforeCallback(AX_CALLBACK_0(PUBillboardChain::onBeforeDraw, this)); @@ -721,9 +720,9 @@ void PUBillboardChain::setBlendFunc(const BlendFunc& blendFunc) void PUBillboardChain::onBeforeDraw() { auto* renderer = Director::getInstance()->getRenderer(); - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); _rendererDepthWrite = renderer->getDepthWrite(); _rendererWinding = renderer->getWinding(); @@ -735,7 +734,7 @@ void PUBillboardChain::onAfterDraw() { auto* renderer = Director::getInstance()->getRenderer(); renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); renderer->setDepthWrite(_rendererDepthWrite); renderer->setWinding(_rendererWinding); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.h b/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.h index c9179aca02e3..c0b4d861c944 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBillboardChain.h @@ -27,12 +27,12 @@ #pragma once #include -#include "renderer/RenderState.h" -#include "renderer/MeshCommand.h" -#include "renderer/CallbackCommand.h" -#include "renderer/backend/Buffer.h" -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" namespace ax { @@ -57,13 +57,13 @@ class PUBillboardChain public: Element(); - Element(const Vec3& position, float width, float texCoord, const Vec4& colour, const Quaternion& orientation); + Element(const Vec3& position, float width, float texCoord, const Color& colour, const Quaternion& orientation); Vec3 position; float width; /// U or V texture coord depending on options float texCoord; - Vec4 color; + Color color; // Only used when mFaceCamera == false Quaternion orientation; @@ -310,33 +310,27 @@ class PUBillboardChain /// Chain segment has no elements static const size_t SEGMENT_EMPTY; - struct VertexInfo - { - Vec3 position; - Vec2 uv; - Vec4 color; - }; MeshCommand _meshCommand; RenderState::StateBlock _stateBlock; Texture2D* _texture = nullptr; - backend::ProgramState* _programState = nullptr; - backend::Buffer* _indexBuffer = nullptr; // index buffer - backend::Buffer* _vertexBuffer = nullptr; // vertex buffer + rhi::ProgramState* _programState = nullptr; + rhi::Buffer* _indexBuffer = nullptr; // index buffer + rhi::Buffer* _vertexBuffer = nullptr; // vertex buffer - std::vector _vertices; + std::vector _vertices; std::vector _indices; std::string _texFile; - backend::UniformLocation _locColor; - backend::UniformLocation _locTexture; - backend::UniformLocation _locPMatrix; + rhi::UniformLocation _locColor; + rhi::UniformLocation _locTexture; + rhi::UniformLocation _locPMatrix; // renderer state cache variables bool _rendererDepthTestEnabled = true; - backend::CompareFunction _rendererDepthCmpFunc = backend::CompareFunction::LESS; - backend::CullMode _rendererCullMode = backend::CullMode::BACK; - backend::Winding _rendererWinding = backend::Winding::COUNTER_CLOCK_WISE; + rhi::CompareFunc _rendererDepthCmpFunc = rhi::CompareFunc::LESS; + rhi::CullMode _rendererCullMode = rhi::CullMode::BACK; + rhi::Winding _rendererWinding = rhi::Winding::COUNTER_CLOCK_WISE; bool _rendererDepthWrite = false; }; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBoxCollider.h b/extensions/Particle3D/src/Particle3D/PU/PUBoxCollider.h index 33ff33a32200..0def79ff0c92 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBoxCollider.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBoxCollider.h @@ -40,8 +40,8 @@ class AX_EX_DLL PUBoxCollider : public PUBaseCollider static PUBoxCollider* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Returns the width of the box */ @@ -83,7 +83,7 @@ class AX_EX_DLL PUBoxCollider : public PUBaseCollider */ void calculateDirectionAfterCollision(PUParticle3D* particle); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUBoxCollider(); virtual ~PUBoxCollider(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUBoxEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUBoxEmitter.h index d4a6e80dc7f0..7991778e3611 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUBoxEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUBoxEmitter.h @@ -56,8 +56,8 @@ class AX_EX_DLL CCPUBoxEmitter : public PUEmitter float getDepth() const; void setDepth(const float depth); - virtual CCPUBoxEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + CCPUBoxEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; CCPUBoxEmitter(); virtual ~CCPUBoxEmitter(){}; @@ -65,7 +65,7 @@ class AX_EX_DLL CCPUBoxEmitter : public PUEmitter protected: /** */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; protected: float _height; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.cpp b/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.cpp index fae203a212de..7570ef344b88 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.cpp @@ -27,7 +27,7 @@ #include "PUCircleEmitter.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include "Particle3D/PU/PUUtil.h" -#include "base/Random.h" +#include "axmol/base/Random.h" namespace ax { @@ -273,4 +273,4 @@ PUCircleEmitter* PUCircleEmitter::clone() return be; } -} \ No newline at end of file +} diff --git a/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.h index 4401005c1f31..633a076c5409 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUCircleEmitter.h @@ -71,10 +71,10 @@ class AX_EX_DLL PUCircleEmitter : public PUEmitter /** See ParticleEmiter */ - virtual void notifyStart() override; + void notifyStart() override; - virtual PUCircleEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUCircleEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUCircleEmitter(); virtual ~PUCircleEmitter(){}; @@ -82,11 +82,11 @@ class AX_EX_DLL PUCircleEmitter : public PUEmitter protected: /** Determine a particle position on the circle. */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; /** Determine the particle direction. */ - virtual void initParticleDirection(PUParticle3D* particle) override; + void initParticleDirection(PUParticle3D* particle) override; Quaternion getRotationTo(const Vec3& src, const Vec3& dest, const Vec3& fallbackAxis = Vec3::ZERO) const; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUCollisionAvoidanceAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUCollisionAvoidanceAffector.h index feaedf4cf59e..d817e3f0cf8e 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUCollisionAvoidanceAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUCollisionAvoidanceAffector.h @@ -39,7 +39,7 @@ class AX_EX_DLL PUCollisionAvoidanceAffector : public PUAffector static PUCollisionAvoidanceAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Todo */ @@ -49,7 +49,7 @@ class AX_EX_DLL PUCollisionAvoidanceAffector : public PUAffector */ void setRadius(float radius); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUCollisionAvoidanceAffector(); virtual ~PUCollisionAvoidanceAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.cpp b/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.cpp index 5e04e3eb097d..a84d679b475a 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.cpp @@ -48,7 +48,7 @@ void PUColorAffector::setColorOperation(const PUColorAffector::ColorOperation& c _colorOperation = colorOperation; } //----------------------------------------------------------------------- -void PUColorAffector::addColor(float timeFraction, const Vec4& color) +void PUColorAffector::addColor(float timeFraction, const Color& color) { _colorMap[timeFraction] = color; } @@ -91,7 +91,7 @@ void PUColorAffector::updatePUAffector(PUParticle3D* particle, float /*deltaTime { // PUParticle3D *particle = iter; // Linear interpolation of the colour - Vec4 color = Vec4::ONE; + Color color = Color::WHITE; float timeFraction = (particle->totalTimeToLive - particle->timeToLive) / particle->totalTimeToLive; ColorMapIterator it1 = findNearestColorMapIterator(timeFraction); ColorMapIterator it2 = it1; @@ -117,7 +117,7 @@ void PUColorAffector::updatePUAffector(PUParticle3D* particle, float /*deltaTime else { // Multiply - particle->color = Vec4(color.x * particle->originalColor.x, color.y * particle->originalColor.y, + particle->color = Color(color.x * particle->originalColor.x, color.y * particle->originalColor.y, color.z * particle->originalColor.z, color.w * particle->originalColor.w); } } diff --git a/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.h index 8488d60bf9f6..7652b90948d3 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUColorAffector.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" #include namespace ax @@ -36,8 +36,8 @@ namespace ax class AX_EX_DLL PUColorAffector : public PUAffector { public: - typedef std::map ColorMap; - typedef std::map::iterator ColorMapIterator; + typedef std::map ColorMap; + typedef std::map::iterator ColorMapIterator; enum ColorOperation { CAO_MULTIPLY, @@ -49,11 +49,11 @@ class AX_EX_DLL PUColorAffector : public PUAffector static PUColorAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ - void addColor(float timeFraction, const Vec4& color); + void addColor(float timeFraction, const Color& color); /** */ @@ -71,7 +71,7 @@ class AX_EX_DLL PUColorAffector : public PUAffector */ void setColorOperation(const ColorOperation& colorOperation); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUColorAffector(); virtual ~PUColorAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUColorAffectorTranslator.cpp b/extensions/Particle3D/src/Particle3D/PU/PUColorAffectorTranslator.cpp index 6c7ee4fc4c83..d841da253b3d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUColorAffectorTranslator.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUColorAffectorTranslator.cpp @@ -46,7 +46,7 @@ bool PUColorAffectorTranslator::translateChildProperty(PUScriptCompiler* compile { int n = 0; float time; - Vec4 colour; + Color color; PUAbstractNodeList::const_iterator i = prop->values.begin(); PUAbstractNodeList::const_iterator end = prop->values.end(); while (i != end) @@ -60,23 +60,23 @@ bool PUColorAffectorTranslator::translateChildProperty(PUScriptCompiler* compile time = v; break; case 1: - colour.x = v; + color.x = v; break; case 2: - colour.y = v; + color.y = v; break; case 3: - colour.z = v; + color.z = v; break; case 4: - colour.w = v; + color.w = v; break; } } ++n; ++i; } - affector->addColor(time, colour); + affector->addColor(time, color); return true; } } diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoAffectorEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoAffectorEventHandler.h index c8c021a2b22b..5d2437cfe01d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoAffectorEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoAffectorEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUEventHandler.h" #include #include @@ -69,9 +69,9 @@ class AX_EX_DLL PUDoAffectorEventHandler : public PUEventHandler DoAffectorEventHandler is defined, or if the Affector is not found, other ParticleTechniques are searched. */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; - virtual void copyAttributesTo(PUEventHandler* eventHandler) override; + void copyAttributesTo(PUEventHandler* eventHandler) override; PUDoAffectorEventHandler(); virtual ~PUDoAffectorEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoEnableComponentEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoEnableComponentEventHandler.h index a3a5ee44acab..b4516f12e36c 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoEnableComponentEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoEnableComponentEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include "Particle3D/PU/PUEventHandler.h" #include @@ -75,9 +75,9 @@ class AX_EX_DLL PUDoEnableComponentEventHandler : public PUEventHandler DoEnableComponentEventHandler is defined, or if the ParticleEmitter/Affector is not found, other ParticleTechniques are searched. */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; - virtual void copyAttributesTo(PUEventHandler* eventHandler) override; + void copyAttributesTo(PUEventHandler* eventHandler) override; PUDoEnableComponentEventHandler(); virtual ~PUDoEnableComponentEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoExpireEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoExpireEventHandler.h index 7a1a8356a1c7..3ae0df70afc6 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoExpireEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoExpireEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUEventHandler.h" #include #include @@ -54,7 +54,7 @@ class AX_EX_DLL PUDoExpireEventHandler : public PUEventHandler /** */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; PUDoExpireEventHandler() : PUEventHandler() {} virtual ~PUDoExpireEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoFreezeEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoFreezeEventHandler.h index 56b543725831..999ef7674b5a 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoFreezeEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoFreezeEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUEventHandler.h" #include #include @@ -46,7 +46,7 @@ class AX_EX_DLL PUDoFreezeEventHandler : public PUEventHandler /** */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; PUDoFreezeEventHandler() : PUEventHandler() {} virtual ~PUDoFreezeEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoPlacementParticleEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoPlacementParticleEventHandler.h index 265a8241d55e..914491135017 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoPlacementParticleEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoPlacementParticleEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUListener.h" #include "Particle3D/PU/PUEventHandler.h" #include @@ -122,17 +122,17 @@ class AX_EX_DLL PUDoPlacementParticleEventHandler : public PUEventHandler, publi is not found, other ParticleTechniques are searched. The ParticleEmitter is 'forced' to emit the requested number of particles. */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; /** Initialise the emitted particle. This means that its position is set. */ - virtual void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; /** No implementation. */ - virtual void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; - virtual void copyAttributesTo(PUEventHandler* eventHandler) override; + void copyAttributesTo(PUEventHandler* eventHandler) override; PUDoPlacementParticleEventHandler(); virtual ~PUDoPlacementParticleEventHandler(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoScaleEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoScaleEventHandler.h index a3cd7a5911f2..b17ffa02ff6a 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoScaleEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoScaleEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUEventHandler.h" #include #include @@ -72,9 +72,9 @@ class AX_EX_DLL PUDoScaleEventHandler : public PUEventHandler /** */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; - virtual void copyAttributesTo(PUEventHandler* eventHandler) override; + void copyAttributesTo(PUEventHandler* eventHandler) override; PUDoScaleEventHandler(); virtual ~PUDoScaleEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDoStopSystemEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUDoStopSystemEventHandler.h index 6d713757a6ed..fff31d814e95 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDoStopSystemEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDoStopSystemEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUEventHandler.h" #include #include @@ -47,7 +47,7 @@ class AX_EX_DLL PUDoStopSystemEventHandler : public PUEventHandler /** */ - virtual void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; + void handle(PUParticleSystem3D* particleSystem, PUParticle3D* particle, float timeElapsed) override; PUDoStopSystemEventHandler() : PUEventHandler() {} virtual ~PUDoStopSystemEventHandler(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.cpp b/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.cpp index 5676e5666a6a..de6ca67804a0 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.cpp @@ -25,8 +25,8 @@ ****************************************************************************/ #include "PUDynamicAttribute.h" -#include "base/Random.h" -#include "platform/StdC.h" +#include "axmol/base/Random.h" +#include "axmol/platform/StdC.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.h b/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.h index 343096d2e990..49d80a769977 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUDynamicAttribute.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "PUSimpleSpline.h" #include @@ -123,14 +123,14 @@ class AX_EX_DLL PUDynamicAttributeFixed : public PUDynamicAttribute /** Todo */ - virtual float getValue(float x = 0) override; + float getValue(float x = 0) override; /** Todo */ virtual void setValue(float value); - virtual PUDynamicAttributeFixed* clone() override; - virtual void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; + PUDynamicAttributeFixed* clone() override; + void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; protected: float _value; @@ -155,7 +155,7 @@ class AX_EX_DLL PUDynamicAttributeRandom : public PUDynamicAttribute /** Todo */ - virtual float getValue(float x = 0) override; + float getValue(float x = 0) override; /** Todo */ @@ -165,8 +165,8 @@ class AX_EX_DLL PUDynamicAttributeRandom : public PUDynamicAttribute float getMax() const; void setMinMax(float min, float max); - virtual PUDynamicAttributeRandom* clone() override; - virtual void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; + PUDynamicAttributeRandom* clone() override; + void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; protected: float _min, _max; @@ -203,7 +203,7 @@ class AX_EX_DLL PUDynamicAttributeCurved : public PUDynamicAttribute /** Todo */ - virtual float getValue(float x = 0) override; + float getValue(float x = 0) override; /** Todo */ @@ -225,8 +225,8 @@ class AX_EX_DLL PUDynamicAttributeCurved : public PUDynamicAttribute */ void removeAllControlPoints(); - virtual PUDynamicAttributeCurved* clone() override; - virtual void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; + PUDynamicAttributeCurved* clone() override; + void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; protected: /** Todo @@ -280,7 +280,7 @@ class AX_EX_DLL PUDynamicAttributeOscillate : public PUDynamicAttribute /** Todo */ - virtual float getValue(float x = 0) override; + float getValue(float x = 0) override; /** Get and set the OscillationType */ @@ -307,8 +307,8 @@ class AX_EX_DLL PUDynamicAttributeOscillate : public PUDynamicAttribute float getAmplitude() const; void setAmplitude(float amplitude); - virtual PUDynamicAttributeOscillate* clone() override; - virtual void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; + PUDynamicAttributeOscillate* clone() override; + void copyAttributesTo(PUDynamicAttribute* dynamicAttribute) override; protected: OscillationType _oscillationType; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEmitter.cpp b/extensions/Particle3D/src/Particle3D/PU/PUEmitter.cpp index c7e19bee9ca2..1f6351514e78 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEmitter.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUEmitter.cpp @@ -433,33 +433,33 @@ bool PUEmitter::makeParticleLocal(PUParticle3D* particle) } //----------------------------------------------------------------------- -const Vec4& PUEmitter::getParticleColor() const +const Color& PUEmitter::getParticleColor() const { return _particleColor; } //----------------------------------------------------------------------- -void PUEmitter::setParticleColor(const Vec4& particleColor) +void PUEmitter::setParticleColor(const Color& particleColor) { _particleColor = particleColor; } //----------------------------------------------------------------------- -const Vec4& PUEmitter::getParticleColorRangeStart() const +const Color& PUEmitter::getParticleColorRangeStart() const { return _particleColorRangeStart; } //----------------------------------------------------------------------- -void PUEmitter::setParticleColorRangeStart(const Vec4& particleColorRangeStart) +void PUEmitter::setParticleColorRangeStart(const Color& particleColorRangeStart) { _particleColorRangeStart = particleColorRangeStart; _particleColorRangeSet = true; } //----------------------------------------------------------------------- -const Vec4& PUEmitter::getParticleColorRangeEnd() const +const Color& PUEmitter::getParticleColorRangeEnd() const { return _particleColorRangeEnd; } //----------------------------------------------------------------------- -void PUEmitter::setParticleColorRangeEnd(const Vec4& particleColorRangeEnd) +void PUEmitter::setParticleColorRangeEnd(const Color& particleColorRangeEnd) { _particleColorRangeEnd = particleColorRangeEnd; _particleColorRangeSet = true; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUEmitter.h index a4bec1f86520..4870a2cbb855 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUEmitter.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/Particle3DEmitter.h" #include "Particle3D/PU/PUDynamicAttribute.h" #include "Particle3D/PU/PUParticleSystem3D.h" @@ -86,11 +86,11 @@ class AX_EX_DLL PUEmitter : public Particle3DEmitter virtual void prepare(); virtual void unPrepare(); virtual void preUpdateEmitter(float deltaTime); - virtual void updateEmitter(Particle3D* particle, float deltaTime) override; + void updateEmitter(Particle3D* particle, float deltaTime) override; virtual void postUpdateEmitter(float deltaTime); virtual unsigned short calculateRequestedParticles(float timeElapsed); - virtual void emit(int count) override; + void emit(int count) override; void setLocalPosition(const Vec3& pos) { _position = pos; }; const Vec3 getLocalPosition() const { return _position; }; @@ -261,27 +261,27 @@ class AX_EX_DLL PUEmitter : public Particle3DEmitter /** Get the colour of a particle that will be emitted. */ - const Vec4& getParticleColor() const; + const Color& getParticleColor() const; /** Set the colour of an emitted particle. */ - void setParticleColor(const Vec4& particleColour); + void setParticleColor(const Color& particleColour); /** Get the colour range start of an emitted particle. */ - const Vec4& getParticleColorRangeStart() const; + const Color& getParticleColorRangeStart() const; /** Set the colour range start of an emitted particle. This is the lower value used to generate a random colour. */ - void setParticleColorRangeStart(const Vec4& particleColourRangeStart); + void setParticleColorRangeStart(const Color& particleColourRangeStart); /** Get the colour range end of an emitted particle. */ - const Vec4& getParticleColorRangeEnd() const; + const Color& getParticleColorRangeEnd() const; /** Set the colour range end of an emitted particle. This is the upper value used to generate a random colour. */ - void setParticleColorRangeEnd(const Vec4& particleColourRangeEnd); + void setParticleColorRangeEnd(const Color& particleColourRangeEnd); /** Get the texture coords of an emitted particle. */ @@ -533,15 +533,15 @@ class AX_EX_DLL PUEmitter : public Particle3DEmitter /** Colour that is assigned to an emitted particle. */ - Vec4 _particleColor; + Color _particleColor; /** Used to randomize the colour of an emitted particle. */ - Vec4 _particleColorRangeStart; + Color _particleColorRangeStart; /** Used to randomize the colour of an emitted particle. */ - Vec4 _particleColorRangeEnd; + Color _particleColorRangeEnd; /** Used to determine whether the colour range has been set. */ diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEmitterManager.h b/extensions/Particle3D/src/Particle3D/PU/PUEmitterManager.h index 2aa68f6f1551..f929836b71fc 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEmitterManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUEmitterManager.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptTranslator.h" #include "Particle3D/PU/PUEmitter.h" #include "Particle3D/PU/PUBoxEmitterTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEmitterTranslator.cpp b/extensions/Particle3D/src/Particle3D/PU/PUEmitterTranslator.cpp index 307da57cad8a..a175d2e97ca9 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEmitterTranslator.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUEmitterTranslator.cpp @@ -303,7 +303,7 @@ void PUEmitterTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* // Property: start_colour_range if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_START_COLOUR_RANGE], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { _emitter->setParticleColorRangeStart(val); @@ -315,7 +315,7 @@ void PUEmitterTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* // Property: end_colour_range if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_END_COLOUR_RANGE], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { _emitter->setParticleColorRangeEnd(val); @@ -327,7 +327,7 @@ void PUEmitterTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* // Property: colour if (passValidateProperty(compiler, prop, token[TOKEN_EMITTER_COLOUR], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { _emitter->setParticleColor(val); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEventHandler.h b/extensions/Particle3D/src/Particle3D/PU/PUEventHandler.h index 0fd755deef48..498660d17b4c 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEventHandler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUEventHandler.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include #include #include "extensions/ExtensionExport.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUEventHandlerManager.h b/extensions/Particle3D/src/Particle3D/PU/PUEventHandlerManager.h index b32e38e507f5..f0801ff6a346 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUEventHandlerManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUEventHandlerManager.h @@ -25,7 +25,7 @@ ****************************************************************************/ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptTranslator.h" #include "Particle3D/PU/PUEventHandler.h" #include "Particle3D/PU/PUDoAffectorEventHandlerTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUFlockCenteringAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUFlockCenteringAffector.h index 16bb68dcca48..4187b80e5530 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUFlockCenteringAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUFlockCenteringAffector.h @@ -36,10 +36,10 @@ class AX_EX_DLL PUFlockCenteringAffector : public PUAffector public: static PUFlockCenteringAffector* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUFlockCenteringAffector(); virtual ~PUFlockCenteringAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUForceField.h b/extensions/Particle3D/src/Particle3D/PU/PUForceField.h index f0d12e7f57d1..9144b81467ab 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUForceField.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUForceField.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "PUNoise.h" namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUForceFieldAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUForceFieldAffector.h index 62716a03dbce..c7935bc31dea 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUForceFieldAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUForceFieldAffector.h @@ -50,10 +50,10 @@ class AX_EX_DLL PUForceFieldAffector : public PUAffector static PUForceFieldAffector* create(); - virtual void notifyStart() override; - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void prepare() override; + void notifyStart() override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void prepare() override; /** Get/Set Forcefield type */ @@ -126,7 +126,7 @@ class AX_EX_DLL PUForceFieldAffector : public PUAffector */ void suppressGeneration(bool suppress); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUForceFieldAffector(); ~PUForceFieldAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUGeometryRotator.h b/extensions/Particle3D/src/Particle3D/PU/PUGeometryRotator.h index 92a2ca249bcf..ae49178592f5 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUGeometryRotator.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUGeometryRotator.h @@ -42,9 +42,9 @@ class AX_EX_DLL PUGeometryRotator : public PUAffector static PUGeometryRotator* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** @copydoc ParticleAffector::_initParticleForEmission */ - virtual void initParticleForEmission(PUParticle3D* particle) override; + void initParticleForEmission(PUParticle3D* particle) override; /** Returns the rotation speed. This is the speed controlled by the affector. Besides the default rotation speed, it is also possible to use the particles own rotation speed. @@ -76,7 +76,7 @@ class AX_EX_DLL PUGeometryRotator : public PUAffector */ void resetRotationAxis(); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUGeometryRotator(); virtual ~PUGeometryRotator(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUGravityAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUGravityAffector.h index 2b6bcc240da5..e4cb1cce7f4c 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUGravityAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUGravityAffector.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -40,15 +40,15 @@ class AX_EX_DLL PUGravityAffector : public PUAffector static PUGravityAffector* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ float getGravity() const; void setGravity(float gravity); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUGravityAffector(); virtual ~PUGravityAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUInterParticleCollider.h b/extensions/Particle3D/src/Particle3D/PU/PUInterParticleCollider.h index 80be9cbb771d..367023abb4cd 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUInterParticleCollider.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUInterParticleCollider.h @@ -27,7 +27,7 @@ #pragma once #include "PUBaseCollider.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -47,9 +47,9 @@ class AX_EX_DLL PUParticle3DInterParticleCollider : public PUBaseCollider static const float DEFAULT_ADJUSTMENT; static const InterParticleCollisionResponse DEFAULT_COLLISION_RESPONSE; - virtual void prepare() override; - virtual void unPrepare() override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void prepare() override; + void unPrepare() override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Todo */ @@ -67,7 +67,7 @@ class AX_EX_DLL PUParticle3DInterParticleCollider : public PUBaseCollider */ void setInterParticleCollisionResponse(InterParticleCollisionResponse interParticleCollisionResponse); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUParticle3DInterParticleCollider(); virtual ~PUParticle3DInterParticleCollider(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUJetAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUJetAffector.h index 6917fc126da4..b5d3bb55beaf 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUJetAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUJetAffector.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUDynamicAttribute.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,14 +41,14 @@ class AX_EX_DLL PUJetAffector : public PUAffector static PUJetAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ PUDynamicAttribute* getDynAcceleration() const { return _dynAcceleration; }; void setDynAcceleration(PUDynamicAttribute* dynAcceleration); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUJetAffector(); virtual ~PUJetAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PULineAffector.h b/extensions/Particle3D/src/Particle3D/PU/PULineAffector.h index d63b5229d8e7..fa941cb07edd 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PULineAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PULineAffector.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -45,11 +45,11 @@ class AX_EX_DLL PULineAffector : public PUAffector /** */ - virtual void notifyRescaled(const Vec3& scale) override; - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void postUpdateAffector(float deltaTime) override; - virtual void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; + void notifyRescaled(const Vec3& scale) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void postUpdateAffector(float deltaTime) override; + void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; /** */ float getMaxDeviation() const; @@ -70,7 +70,7 @@ class AX_EX_DLL PULineAffector : public PUAffector float getDrift() const; void setDrift(float drift); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PULineAffector(); virtual ~PULineAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PULineEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PULineEmitter.h index 049797b5f9ea..1f26fb2a8487 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PULineEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PULineEmitter.h @@ -44,13 +44,13 @@ class AX_EX_DLL PULineEmitter : public PUEmitter static PULineEmitter* create(); /** */ - virtual void notifyStart() override; + void notifyStart() override; /** Override the default implementation, to allow that no particles are emitted if there is an incremental emission of particles (along a path), and the end of the line has been reached. */ - virtual unsigned short calculateRequestedParticles(float timeElapsed) override; + unsigned short calculateRequestedParticles(float timeElapsed) override; /** */ @@ -77,18 +77,18 @@ class AX_EX_DLL PULineEmitter : public PUEmitter /** */ - virtual void notifyRescaled(const Vec3& scale) override; + void notifyRescaled(const Vec3& scale) override; /** */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; /** */ - virtual void initParticleDirection(PUParticle3D* particle) override; + void initParticleDirection(PUParticle3D* particle) override; - virtual PULineEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PULineEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PULineEmitter(); virtual ~PULineEmitter(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PULinearForceAffector.h b/extensions/Particle3D/src/Particle3D/PU/PULinearForceAffector.h index 721cb426d476..a12284abfb27 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PULinearForceAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PULinearForceAffector.h @@ -27,7 +27,7 @@ #pragma once #include "PUBaseForceAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -37,10 +37,10 @@ class AX_EX_DLL PULinearForceAffector : public PUBaseForceAffector public: static PULinearForceAffector* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PULinearForceAffector(){}; virtual ~PULinearForceAffector(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUListener.h b/extensions/Particle3D/src/Particle3D/PU/PUListener.h index 2a35a6f0f798..37408f202454 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUListener.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUListener.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include #include #include "extensions/ExtensionExport.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.cpp b/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.cpp index dd24b7913984..6e1d631e4461 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.cpp @@ -27,14 +27,13 @@ #include "PUMaterialManager.h" #include "Particle3D/PU/PUScriptCompiler.h" #include "Particle3D/PU/PUTranslateManager.h" -#include "platform/FileUtils.h" -#include "platform/PlatformMacros.h" -#include "renderer/backend/Types.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) # include #elif (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "platform/android/FileUtils-android.h" +# include "axmol/platform/android/FileUtils-android.h" # include #elif (AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC) # include @@ -43,7 +42,7 @@ # include # include #else -# include "base/filesystem.h" +# include "axmol/base/filesystem.h" #endif #include "yasio/string_view.hpp" @@ -60,10 +59,10 @@ PUMaterial::PUMaterial() , shininess(0.0f) , depthTest(true) , depthWrite(true) - , wrapMode(backend::SamplerAddressMode::CLAMP_TO_EDGE) + , wrapMode(rhi::SamplerAddressMode::CLAMP_TO_EDGE) { - blendFunc.src = backend::BlendFactor::ONE; - blendFunc.dst = backend::BlendFactor::ZERO; + blendFunc.src = rhi::BlendFactor::ONE; + blendFunc.dst = rhi::BlendFactor::ZERO; } PUMaterialCache::PUMaterialCache() {} diff --git a/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.h b/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.h index abfcdcc289d5..d6631e1faaa6 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUMaterialManager.h @@ -25,8 +25,8 @@ ****************************************************************************/ #pragma once -#include "math/Math.h" -#include "base/Types.h" +#include "axmol/math/Math.h" +#include "axmol/base/Types.h" #include #include "extensions/ExtensionExport.h" @@ -41,10 +41,10 @@ class AX_EX_DLL PUMaterial : public Object std::string fileName; std::string name; bool isEnabledLight; - Vec4 ambientColor; - Vec4 diffuseColor; - Vec4 specularColor; - Vec4 emissiveColor; + Color ambientColor; + Color diffuseColor; + Color specularColor; + Color emissiveColor; float shininess; BlendFunc blendFunc; @@ -52,7 +52,7 @@ class AX_EX_DLL PUMaterial : public Object bool depthWrite; std::string textureFile; - backend::SamplerAddressMode wrapMode; + rhi::SamplerAddressMode wrapMode; }; class AX_EX_DLL PUMaterialCache diff --git a/extensions/Particle3D/src/Particle3D/PU/PUMaterialTranslator.cpp b/extensions/Particle3D/src/Particle3D/PU/PUMaterialTranslator.cpp index 703af72f3e3f..9b9a85d14995 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUMaterialTranslator.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUMaterialTranslator.cpp @@ -26,7 +26,6 @@ #include "PUMaterialTranslator.h" #include "Particle3D/PU/PUMaterialManager.h" -#include "renderer/backend/Types.h" namespace ax { @@ -198,7 +197,7 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN { if (passValidateProperty(compiler, prop, matToken[TOKEN_MAT_AMIBIENT], VAL_VECTOR4)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { material->ambientColor = val; @@ -209,7 +208,7 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN { if (passValidateProperty(compiler, prop, matToken[TOKEN_MAT_AMIBIENT], VAL_VECTOR4)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { material->diffuseColor = val; @@ -221,7 +220,7 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN PUAbstractNodeList::const_iterator it = prop->values.begin(); PUAbstractNodeList::const_iterator end = prop->values.end(); unsigned int n = 0; - Vec4 color; + Color color; float shininess = 0.0f; while (it != end) { @@ -258,7 +257,7 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN { if (passValidateProperty(compiler, prop, matToken[TOKEN_MAT_AMIBIENT], VAL_VECTOR4)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { material->emissiveColor = val; @@ -275,8 +274,8 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN { if (val == matToken[TOKEN_MAT_BLEND_ADD]) { - material->blendFunc.src = backend::BlendFactor::ONE; - material->blendFunc.dst = backend::BlendFactor::ONE; + material->blendFunc.src = rhi::BlendFactor::ONE; + material->blendFunc.dst = rhi::BlendFactor::ONE; } else if (val == matToken[TOKEN_MAT_BLEND_ALPHA]) { @@ -284,26 +283,26 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN } else if (val == matToken[TOKEN_MAT_BLEND_COLOR]) { - material->blendFunc.src = backend::BlendFactor::SRC_COLOR; - material->blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_COLOR; + material->blendFunc.src = rhi::BlendFactor::SRC_COLOR; + material->blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_COLOR; } else if (val == matToken[TOKEN_MAT_BLEND_MODULATE]) { - material->blendFunc.src = backend::BlendFactor::DST_COLOR; - material->blendFunc.dst = backend::BlendFactor::ZERO; + material->blendFunc.src = rhi::BlendFactor::DST_COLOR; + material->blendFunc.dst = rhi::BlendFactor::ZERO; } else if (val == matToken[TOKEN_MAT_BLEND_REPLACE]) { - material->blendFunc.src = backend::BlendFactor::ONE; - material->blendFunc.dst = backend::BlendFactor::ZERO; + material->blendFunc.src = rhi::BlendFactor::ONE; + material->blendFunc.dst = rhi::BlendFactor::ZERO; } else if (val == matToken[TOKEN_MAT_BLEND_SRC_COLOR]) { - material->blendFunc.src = backend::BlendFactor::SRC_COLOR; + material->blendFunc.src = rhi::BlendFactor::SRC_COLOR; } else if (val == matToken[TOKEN_MAT_BLEND_DEST_COLOR]) { - material->blendFunc.src = backend::BlendFactor::DST_COLOR; + material->blendFunc.src = rhi::BlendFactor::DST_COLOR; } } @@ -313,19 +312,19 @@ void PUMaterialPassTranslator::translate(PUScriptCompiler* compiler, PUAbstractN { if (val == matToken[TOKEN_MAT_BLEND_ONE]) { - material->blendFunc.dst = backend::BlendFactor::ONE; + material->blendFunc.dst = rhi::BlendFactor::ONE; } else if (val == matToken[TOKEN_MAT_BLEND_ZERO]) { - material->blendFunc.dst = backend::BlendFactor::ZERO; + material->blendFunc.dst = rhi::BlendFactor::ZERO; } else if (val == matToken[TOKEN_MAT_BLEND_SRC_COLOR]) { - material->blendFunc.dst = backend::BlendFactor::SRC_COLOR; + material->blendFunc.dst = rhi::BlendFactor::SRC_COLOR; } else if (val == matToken[TOKEN_MAT_BLEND_DEST_COLOR]) { - material->blendFunc.dst = backend::BlendFactor::DST_COLOR; + material->blendFunc.dst = rhi::BlendFactor::DST_COLOR; } } } @@ -414,15 +413,15 @@ void PUMaterialTextureUnitTranslator::translate(PUScriptCompiler* compiler, PUAb { if (val == matToken[TOKEN_MAT_TEXTURE_CLAMP]) { - material->wrapMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + material->wrapMode = rhi::SamplerAddressMode::CLAMP_TO_EDGE; } else if (val == matToken[TOKEN_MAT_TEXTURE_REPEAT]) { - material->wrapMode = backend::SamplerAddressMode::REPEAT; + material->wrapMode = rhi::SamplerAddressMode::REPEAT; } else if (val == matToken[TOKEN_MAT_TEXTURE_MIRROR]) { - material->wrapMode = backend::SamplerAddressMode::MIRROR_REPEAT; // GL_MIRROR_CLAMP_EXT; + material->wrapMode = rhi::SamplerAddressMode::MIRROR; } } } diff --git a/extensions/Particle3D/src/Particle3D/PU/PUMeshSurfaceEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUMeshSurfaceEmitter.h index 4a3f9186d004..8ef64d995bea 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUMeshSurfaceEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUMeshSurfaceEmitter.h @@ -214,26 +214,26 @@ class AX_EX_DLL PUMeshSurfaceEmitter : public PUEmitter /** Build the data if the mesh name has been set. */ - virtual void prepare() override; + void prepare() override; /** Reverse it. */ - virtual void unPrepare() override; + void unPrepare() override; /** Determine a particle position on the mesh surface. */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; /** See ParticleEmitter. */ - virtual unsigned short calculateRequestedParticles(float timeElapsed) override; + unsigned short calculateRequestedParticles(float timeElapsed) override; /** Determine the particle direction. */ - virtual void initParticleDirection(PUParticle3D* particle) override; + void initParticleDirection(PUParticle3D* particle) override; - virtual PUMeshSurfaceEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUMeshSurfaceEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUMeshSurfaceEmitter(); virtual ~PUMeshSurfaceEmitter(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUNoise.h b/extensions/Particle3D/src/Particle3D/PU/PUNoise.h index 25785ce0a9ff..30733ff4897b 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUNoise.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUNoise.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUObserver.cpp b/extensions/Particle3D/src/Particle3D/PU/PUObserver.cpp index 38949212ac42..90c85dcf2c76 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUObserver.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUObserver.cpp @@ -27,7 +27,7 @@ #include "Particle3D/PU/PUObserver.h" #include "Particle3D/PU/PUEventHandler.h" #include "Particle3D/PU/PUEventHandlerManager.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUObserver.h index 243370910503..5f6ef14b5b70 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include #include diff --git a/extensions/Particle3D/src/Particle3D/PU/PUObserverManager.h b/extensions/Particle3D/src/Particle3D/PU/PUObserverManager.h index c1123aabb408..ceec67995500 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUObserverManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUObserverManager.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptTranslator.h" #include "Particle3D/PU/PUObserver.h" #include "Particle3D/PU/PUOnClearObserverTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnClearObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnClearObserver.h index a47401fec38b..6a5f73b8eae6 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnClearObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnClearObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -44,21 +44,21 @@ class AX_EX_DLL PUOnClearObserver : public PUObserver /** */ - virtual void notifyStart() override; + void notifyStart() override; /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** The _processParticle() function is overridden, because we don't observe an individual particle. even if there isn't a particle left anymore (and that is the situation we want to validate). */ - virtual void updateObserver(PUParticle3D* particle, float timeElapsed, bool firstParticle) override; + void updateObserver(PUParticle3D* particle, float timeElapsed, bool firstParticle) override; /** Instead of the _processParticle(), the _postProcessParticles() is used because it is called even if there isn't a particle left anymore (and that is the situation we want to validate). */ - virtual void postUpdateObserver(float timeElapsed) override; + void postUpdateObserver(float timeElapsed) override; PUOnClearObserver() : PUObserver(), _continue(false) {} virtual ~PUOnClearObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnCollisionObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnCollisionObserver.h index 32c12b4308aa..a02ae54c5b76 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnCollisionObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnCollisionObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -42,7 +42,7 @@ class AX_EX_DLL PUOnCollisionObserver : public PUObserver static PUOnCollisionObserver* create(); /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; PUOnCollisionObserver() : PUObserver() {} virtual ~PUOnCollisionObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnCountObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnCountObserver.h index 767a4b4cdfc5..39068a70a2e9 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnCountObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnCountObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -53,11 +53,11 @@ class AX_EX_DLL PUOnCountObserver : public PUObserver static const PUComparisionOperator DEFAULT_COMPARE; /** */ - virtual void notifyStart() override; + void notifyStart() override; /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ @@ -69,7 +69,7 @@ class AX_EX_DLL PUOnCountObserver : public PUObserver PUComparisionOperator getCompare() const { return _compare; }; void setCompare(PUComparisionOperator op) { _compare = op; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnCountObserver(); virtual ~PUOnCountObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnEmissionObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnEmissionObserver.h index 372f65db6d56..7e929661c48c 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnEmissionObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnEmissionObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -43,7 +43,7 @@ class AX_EX_DLL PUOnEmissionObserver : public PUObserver static PUOnEmissionObserver* create(); /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; PUOnEmissionObserver() : PUObserver() {} virtual ~PUOnEmissionObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnEventFlagObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnEventFlagObserver.h index c5cba126d079..7da2e84330f5 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnEventFlagObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnEventFlagObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -50,14 +50,14 @@ class AX_EX_DLL PUOnEventFlagObserver : public PUObserver /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ unsigned int getEventFlag() const { return _eventFlag; }; void setEventFlag(unsigned int eventFlag) { _eventFlag = eventFlag; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnEventFlagObserver(); virtual ~PUOnEventFlagObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnExpireObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnExpireObserver.h index 6c5b77c96982..0298bd921201 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnExpireObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnExpireObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -45,7 +45,7 @@ class AX_EX_DLL PUOnExpireObserver : public PUObserver /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; PUOnExpireObserver() : PUObserver() {} virtual ~PUOnExpireObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnPositionObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnPositionObserver.h index 3bc14ec4bef0..9e245fb24888 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnPositionObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnPositionObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -47,7 +47,7 @@ class AX_EX_DLL PUOnPositionObserver : public PUObserver /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ @@ -97,7 +97,7 @@ class AX_EX_DLL PUOnPositionObserver : public PUObserver PUComparisionOperator getComparePositionY() const { return _comparePositionY; }; PUComparisionOperator getComparePositionZ() const { return _comparePositionZ; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnPositionObserver(); virtual ~PUOnPositionObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnQuotaObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnQuotaObserver.h index 66e68cd8ff00..787c8769b016 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnQuotaObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnQuotaObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -43,10 +43,10 @@ class AX_EX_DLL PUOnQuotaObserver : public PUObserver static PUOnQuotaObserver* create(); /** @copydoc ParticleObserver::_notifyStart */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** @copydoc ParticleObserver::_notifyStart */ - virtual void postUpdateObserver(float deltaTime) override; + void postUpdateObserver(float deltaTime) override; PUOnQuotaObserver() : PUObserver(), _result(false) {} virtual ~PUOnQuotaObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnRandomObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnRandomObserver.h index 2d41183c38cd..773c6943d32e 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnRandomObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnRandomObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -47,22 +47,22 @@ class AX_EX_DLL PUOnRandomObserver : public PUObserver /** See ParticleObserver::_preProcessParticles() */ - virtual void preUpdateObserver(float deltaTime) override; + void preUpdateObserver(float deltaTime) override; /** See ParticleObserver::_processParticle() */ - virtual void updateObserver(PUParticle3D* particle, float deltaTime, bool firstParticle) override; + void updateObserver(PUParticle3D* particle, float deltaTime, bool firstParticle) override; /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ float getThreshold() const { return _threshold; }; void setThreshold(float threshold) { _threshold = threshold; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnRandomObserver(); virtual ~PUOnRandomObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnTimeObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnTimeObserver.h index 2844f0f451cd..d382c370dfeb 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnTimeObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnTimeObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -49,11 +49,11 @@ class AX_EX_DLL PUOnTimeObserver : public PUObserver /** In case there are no particles, but the observation returns true, the event handlers must still be called. */ - virtual void preUpdateObserver(float deltaTime) override; + void preUpdateObserver(float deltaTime) override; /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ @@ -70,7 +70,7 @@ class AX_EX_DLL PUOnTimeObserver : public PUObserver bool isSinceStartSystem() const { return _sinceStartSystem; }; void setSinceStartSystem(bool sinceStartSystem) { _sinceStartSystem = sinceStartSystem; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnTimeObserver(); virtual ~PUOnTimeObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUOnVelocityObserver.h b/extensions/Particle3D/src/Particle3D/PU/PUOnVelocityObserver.h index fc16a65a67d6..bf1a1a1839f6 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUOnVelocityObserver.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUOnVelocityObserver.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUObserver.h" #include #include @@ -47,7 +47,7 @@ class AX_EX_DLL PUOnVelocityObserver : public PUObserver /** */ - virtual bool observe(PUParticle3D* particle, float timeElapsed) override; + bool observe(PUParticle3D* particle, float timeElapsed) override; /** */ @@ -59,7 +59,7 @@ class AX_EX_DLL PUOnVelocityObserver : public PUObserver PUComparisionOperator getCompare() const { return _compare; }; void setCompare(PUComparisionOperator op) { _compare = op; }; - virtual void copyAttributesTo(PUObserver* observer) override; + void copyAttributesTo(PUObserver* observer) override; PUOnVelocityObserver(); virtual ~PUOnVelocityObserver(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUParticleFollower.h b/extensions/Particle3D/src/Particle3D/PU/PUParticleFollower.h index 4101e75bfdf0..a1c5d32ef47f 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUParticleFollower.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUParticleFollower.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,8 +41,8 @@ class AX_EX_DLL PUParticleFollower : public PUAffector static PUParticleFollower* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void firstParticleUpdate(PUParticle3D* particle, float deltaTime) override; /** */ @@ -54,7 +54,7 @@ class AX_EX_DLL PUParticleFollower : public PUAffector float getMinDistance() const; void setMinDistance(float minDistance); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUParticleFollower(); virtual ~PUParticleFollower(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.cpp b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.cpp index 37b68fdc6651..0bed8893ba1d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.cpp @@ -37,7 +37,7 @@ #include "Particle3D/PU/PUObserver.h" #include "Particle3D/PU/PUObserverManager.h" #include "Particle3D/PU/PUBehaviour.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.h b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.h index ded20583e72d..8541d2b016ff 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3D.h @@ -26,9 +26,9 @@ #pragma once -#include "2d/Node.h" -#include "base/Protocols.h" -#include "math/Math.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Protocols.h" +#include "axmol/math/Math.h" #include "Particle3D/ParticleSystem3D.h" #include #include @@ -107,7 +107,7 @@ struct AX_EX_DLL PUParticle3D : public Particle3D Vec3 rotationAxis; /** Current and original colour */ - Vec4 originalColor; + Color originalColor; /** The zRotationSpeed is used in combination with zRotation and defines tha actual rotationspeed in 2D. */ @@ -221,32 +221,32 @@ class AX_EX_DLL PUParticleSystem3D : public ParticleSystem3D static PUParticleSystem3D* create(std::string_view filePath); static PUParticleSystem3D* create(std::string_view filePath, std::string_view materialPath); - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - virtual void update(float delta) override; + void update(float delta) override; void forceUpdate(float delta); /** * particle system play control */ - virtual void startParticleSystem() override; + void startParticleSystem() override; /** * stop particle */ - virtual void stopParticleSystem() override; + void stopParticleSystem() override; /** * pause particle */ - virtual void pauseParticleSystem() override; + void pauseParticleSystem() override; /** * resume particle */ - virtual void resumeParticleSystem() override; + void resumeParticleSystem() override; - virtual int getAliveParticleCount() const override; + int getAliveParticleCount() const override; /** * Returns the velocity scale, defined in the particle system, but passed to the technique for convenience. diff --git a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3DTranslator.h b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3DTranslator.h index eb8de14881f0..fde19a66276e 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3DTranslator.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUParticleSystem3DTranslator.h @@ -42,10 +42,10 @@ class PUParticleSystem3DTranslator : public PUScriptTranslator void setParticleSystem3D(PUParticleSystem3D* pu) { _system = pu; }; - virtual bool isParticleSystemTranslator() const override { return true; } + bool isParticleSystemTranslator() const override { return true; } public: - virtual void translate(PUScriptCompiler* compiler, PUAbstractNode* node) override; + void translate(PUScriptCompiler* compiler, PUAbstractNode* node) override; protected: PUParticleSystem3D* _system; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUPathFollower.h b/extensions/Particle3D/src/Particle3D/PU/PUPathFollower.h index a22d12b51f62..8729816d927d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUPathFollower.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUPathFollower.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUSimpleSpline.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -38,7 +38,7 @@ class AX_EX_DLL PUPathFollower : public PUAffector public: static PUPathFollower* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ void addPoint(const Vec3& point); @@ -55,7 +55,7 @@ class AX_EX_DLL PUPathFollower : public PUAffector */ const Vec3& getPoint(unsigned short index) const { return _spline.getPoint(index); }; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUPathFollower(); virtual ~PUPathFollower(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUPlane.h b/extensions/Particle3D/src/Particle3D/PU/PUPlane.h index 16f3cbfb700e..71d9906ba936 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUPlane.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUPlane.h @@ -26,9 +26,9 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" -#include "3d/AABB.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/3d/AABB.h" #include namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUPlaneCollider.h b/extensions/Particle3D/src/Particle3D/PU/PUPlaneCollider.h index 1b09e2e2a739..ad247efdc840 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUPlaneCollider.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUPlaneCollider.h @@ -28,7 +28,7 @@ #include "PUBaseCollider.h" #include "Particle3D/PU/PUPlane.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,8 +41,8 @@ class AX_EX_DLL PUPlaneCollider : public PUBaseCollider static PUPlaneCollider* create(); - virtual void notifyRescaled(const Vec3& scale) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void notifyRescaled(const Vec3& scale) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Returns the normal of the plane */ @@ -56,7 +56,7 @@ class AX_EX_DLL PUPlaneCollider : public PUBaseCollider */ void calculateDirectionAfterCollision(PUParticle3D* particle, float timeElapsed); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUPlaneCollider(); virtual ~PUPlaneCollider(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUPointEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUPointEmitter.h index ae061475949b..bc1049da02fd 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUPointEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUPointEmitter.h @@ -36,8 +36,8 @@ class AX_EX_DLL PUPointEmitter : public PUEmitter public: static PUPointEmitter* create(); - virtual PUPointEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUPointEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUPointEmitter(); virtual ~PUPointEmitter(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUPositionEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUPositionEmitter.h index 7a86b109a2b3..a95e0a331dbd 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUPositionEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUPositionEmitter.h @@ -64,14 +64,14 @@ class AX_EX_DLL PUPositionEmitter : public PUEmitter /** See ParticleEmitter */ - virtual unsigned short calculateRequestedParticles(float timeElapsed) override; + unsigned short calculateRequestedParticles(float timeElapsed) override; /** Generate a particle position based on the added positions. */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; - virtual PUPositionEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUPositionEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUPositionEmitter(); virtual ~PUPositionEmitter(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PURandomiser.h b/extensions/Particle3D/src/Particle3D/PU/PURandomiser.h index 826648643cec..5460098f8ce7 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURandomiser.h +++ b/extensions/Particle3D/src/Particle3D/PU/PURandomiser.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -42,9 +42,9 @@ class AX_EX_DLL PURandomiser : public PUAffector static PURandomiser* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; - virtual void postUpdateAffector(float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void postUpdateAffector(float deltaTime) override; /** */ float getMaxDeviationX() const; @@ -70,7 +70,7 @@ class AX_EX_DLL PURandomiser : public PUAffector bool isRandomDirection() const; void setRandomDirection(bool randomDirection); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PURandomiser(); virtual ~PURandomiser(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PURender.cpp b/extensions/Particle3D/src/Particle3D/PU/PURender.cpp index 4a4ceecf1e07..e79196d50b54 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURender.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PURender.cpp @@ -25,20 +25,20 @@ ****************************************************************************/ #include "Particle3D/ParticleSystem3D.h" #include // offsetof -#include "base/Types.h" +#include "axmol/base/Types.h" #include "Particle3D/PU/PURender.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include "Particle3D/PU/PUUtil.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/Shaders.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/Buffer.h" -#include "base/Director.h" -#include "3d/MeshRenderer.h" -#include "3d/Mesh.h" -#include "2d/Camera.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/base/Director.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Mesh.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -81,10 +81,10 @@ void PUParticle3DQuadRender::render(Renderer* renderer, const Mat4& transform, P if (_vertexBuffer == nullptr) { - size_t stride = sizeof(VertexInfo); - _vertexBuffer = - backend::DriverBase::getInstance()->newBuffer(stride * 4 * particleSystem->getParticleQuota(), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + size_t stride = sizeof(V3F_T2F_C4F); + _vertexBuffer = rhi::DriverBase::getInstance()->createBuffer( + stride * 4 * particleSystem->getParticleQuota(), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); if (_vertexBuffer == nullptr) { AXLOGD("PUParticle3DQuadRender::render create vertex buffer failed"); @@ -95,8 +95,8 @@ void PUParticle3DQuadRender::render(Renderer* renderer, const Mat4& transform, P if (_indexBuffer == nullptr) { _indexBuffer = - backend::DriverBase::getInstance()->newBuffer(6 * particleSystem->getParticleQuota() * sizeof(uint16_t), - backend::BufferType::INDEX, backend::BufferUsage::DYNAMIC); + rhi::DriverBase::getInstance()->createBuffer(6 * particleSystem->getParticleQuota() * sizeof(uint16_t), + rhi::BufferType::INDEX, rhi::BufferUsage::DYNAMIC); if (_indexBuffer == nullptr) { AXLOGD("PUParticle3DQuadRender::render create index buffer failed"); @@ -296,9 +296,9 @@ void PUParticle3DQuadRender::render(Renderer* renderer, const Mat4& transform, P void PUParticle3DEntityRender::onBeforeDraw() { auto* renderer = Director::getInstance()->getRenderer(); - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); _rendererDepthWrite = renderer->getDepthWrite(); _rendererWinding = renderer->getWinding(); @@ -310,7 +310,7 @@ void PUParticle3DEntityRender::onAfterDraw() { auto* renderer = Director::getInstance()->getRenderer(); renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); renderer->setDepthWrite(_rendererDepthWrite); renderer->setWinding(_rendererWinding); @@ -441,11 +441,11 @@ void PUParticle3DQuadRender::determineUVCoords(PUParticle3D* particle) particle->rt_uv = particle->lb_uv + Vec2(_textureCoordsColStep, _textureCoordsRowStep); } -void PUParticle3DQuadRender::fillVertex(unsigned short index, const Vec3& pos, const Vec4& color, const Vec2& uv) +void PUParticle3DQuadRender::fillVertex(unsigned short index, const Vec3& pos, const Color& color, const Vec2& uv) { _vertices[index].position = pos; _vertices[index].color = color; - _vertices[index].uv = uv; + _vertices[index].texCoord = uv; } void PUParticle3DQuadRender::fillTriangle(unsigned short index, unsigned short v0, unsigned short v1, unsigned short v2) @@ -553,9 +553,7 @@ void PUParticle3DModelRender::render(Renderer* renderer, const Mat4& transform, mat.m[14] = particle->position.z; if (_meshList[index]->getCameraMask() != particleSystem->getCameraMask()) _meshList[index]->setCameraMask(particleSystem->getCameraMask()); - _meshList[index]->setColor( - Color3B(particle->color.x * 255, particle->color.y * 255, particle->color.z * 255)); - _meshList[index]->setOpacity(particle->color.w * 255); + _meshList[index]->setColor(Color32(particle->color)); _meshList[index]->visit(renderer, mat, Node::FLAGS_DIRTY_MASK); ++index; } @@ -599,7 +597,7 @@ PUParticle3DEntityRender::PUParticle3DEntityRender() : _texture(nullptr), _programState(nullptr), _indexBuffer(nullptr), _vertexBuffer(nullptr) { _stateBlock.setCullFace(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setDepthTest(false); _stateBlock.setDepthWrite(false); _stateBlock.setBlend(true); @@ -623,18 +621,18 @@ bool PUParticle3DEntityRender::initRender(std::string_view texFile) if (tex) { _texture = tex; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_TEXTURE_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_TEXTURE_3D); + _programState = new rhi::ProgramState(program); } } if (!_programState) { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_COLOR_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_COLOR_3D); + _programState = new rhi::ProgramState(program); } - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); pipelineDescriptor.programState = _programState; _locColor = _programState->getUniformLocation("u_color"); @@ -646,7 +644,7 @@ bool PUParticle3DEntityRender::initRender(std::string_view texFile) _stateBlock.setDepthTest(true); _stateBlock.setDepthWrite(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setCullFace(true); _meshCommand.setBeforeCallback(AX_CALLBACK_0(PUParticle3DEntityRender::onBeforeDraw, this)); @@ -699,10 +697,10 @@ void PUParticle3DBoxRender::render(Renderer* renderer, const Mat4& transform, Pa if (_vertexBuffer == nullptr && _indexBuffer == nullptr) { - size_t stride = sizeof(VertexInfo); + size_t stride = sizeof(V3F_T2F_C4F); _vertexBuffer = - backend::DriverBase::getInstance()->newBuffer(stride * 8 * particleSystem->getParticleQuota(), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + rhi::DriverBase::getInstance()->createBuffer(stride * 8 * particleSystem->getParticleQuota(), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); if (_vertexBuffer == nullptr) { AXLOGD("PUParticle3DBoxRender::render create vertex buffer failed"); @@ -711,8 +709,8 @@ void PUParticle3DBoxRender::render(Renderer* renderer, const Mat4& transform, Pa _vertices.resize(8 * particleSystem->getParticleQuota()); _indexBuffer = - backend::DriverBase::getInstance()->newBuffer(sizeof(uint16_t) * 36 * particleSystem->getParticleQuota(), - backend::BufferType::INDEX, backend::BufferUsage::DYNAMIC); + rhi::DriverBase::getInstance()->createBuffer(sizeof(uint16_t) * 36 * particleSystem->getParticleQuota(), + rhi::BufferType::INDEX, rhi::BufferUsage::DYNAMIC); if (_indexBuffer == nullptr) { AXLOGD("PUParticle3DBoxRender::render create index buffer failed"); @@ -736,44 +734,44 @@ void PUParticle3DBoxRender::render(Renderer* renderer, const Mat4& transform, Pa val = texRot * Vec3(0.0f, 0.75f, 0.0); _vertices[vertexindex + 0].position = particle->position + Vec3(-halfWidth, -halfHeight, halfDepth); _vertices[vertexindex + 0].color = particle->color; - _vertices[vertexindex + 0].uv.x = val.x; - _vertices[vertexindex + 0].uv.y = val.y; + _vertices[vertexindex + 0].texCoord.x = val.x; + _vertices[vertexindex + 0].texCoord.y = val.y; val = texRot * Vec3(0.0f, 0.25f, 0.0); _vertices[vertexindex + 1].position = particle->position + Vec3(halfWidth, -halfHeight, halfDepth); _vertices[vertexindex + 1].color = particle->color; - _vertices[vertexindex + 1].uv.x = val.x; - _vertices[vertexindex + 1].uv.y = val.y; + _vertices[vertexindex + 1].texCoord.x = val.x; + _vertices[vertexindex + 1].texCoord.y = val.y; val = texRot * Vec3(0.5f, 0.25f, 0.0); _vertices[vertexindex + 2].position = particle->position + Vec3(halfWidth, halfHeight, halfDepth); _vertices[vertexindex + 2].color = particle->color; - _vertices[vertexindex + 2].uv.x = val.x; - _vertices[vertexindex + 2].uv.y = val.y; + _vertices[vertexindex + 2].texCoord.x = val.x; + _vertices[vertexindex + 2].texCoord.y = val.y; val = texRot * Vec3(0.5f, 0.75f, 0.0); _vertices[vertexindex + 3].position = particle->position + Vec3(-halfWidth, halfHeight, halfDepth); _vertices[vertexindex + 3].color = particle->color; - _vertices[vertexindex + 3].uv.x = val.x; - _vertices[vertexindex + 3].uv.y = val.y; + _vertices[vertexindex + 3].texCoord.x = val.x; + _vertices[vertexindex + 3].texCoord.y = val.y; val = texRot * Vec3(0.0f, 0.0f, 0.0); _vertices[vertexindex + 4].position = particle->position + Vec3(halfWidth, -halfHeight, -halfDepth); _vertices[vertexindex + 4].color = particle->color; - _vertices[vertexindex + 4].uv.x = val.x; - _vertices[vertexindex + 4].uv.y = val.y; + _vertices[vertexindex + 4].texCoord.x = val.x; + _vertices[vertexindex + 4].texCoord.y = val.y; val = texRot * Vec3(0.0f, 1.0f, 0.0); _vertices[vertexindex + 5].position = particle->position + Vec3(-halfWidth, -halfHeight, -halfDepth); _vertices[vertexindex + 5].color = particle->color; - _vertices[vertexindex + 5].uv.x = val.x; - _vertices[vertexindex + 5].uv.y = val.y; + _vertices[vertexindex + 5].texCoord.x = val.x; + _vertices[vertexindex + 5].texCoord.y = val.y; val = texRot * Vec3(0.5f, 1.0f, 0.0); _vertices[vertexindex + 6].position = particle->position + Vec3(-halfWidth, halfHeight, -halfDepth); _vertices[vertexindex + 6].color = particle->color; - _vertices[vertexindex + 6].uv.x = val.x; - _vertices[vertexindex + 6].uv.y = val.y; + _vertices[vertexindex + 6].texCoord.x = val.x; + _vertices[vertexindex + 6].texCoord.y = val.y; val = texRot * Vec3(0.5f, 0.0f, 0.0); _vertices[vertexindex + 7].position = particle->position + Vec3(halfWidth, halfHeight, -halfDepth); _vertices[vertexindex + 7].color = particle->color; - _vertices[vertexindex + 7].uv.x = val.x; - _vertices[vertexindex + 7].uv.y = val.y; + _vertices[vertexindex + 7].texCoord.x = val.x; + _vertices[vertexindex + 7].texCoord.y = val.y; vertexindex += 8; index += 36; @@ -891,10 +889,10 @@ void PUSphereRender::render(Renderer* renderer, const Mat4& transform, ParticleS unsigned int indexCount = 6 * _numberOfRings * (_numberOfSegments + 1); if (_vertexBuffer == nullptr && _indexBuffer == nullptr) { - size_t stride = sizeof(VertexInfo); - _vertexBuffer = - backend::DriverBase::getInstance()->newBuffer(stride * vertexCount * particleSystem->getParticleQuota(), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + size_t stride = sizeof(V3F_T2F_C4F); + _vertexBuffer = rhi::DriverBase::getInstance()->createBuffer( + stride * vertexCount * particleSystem->getParticleQuota(), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); if (_vertexBuffer == nullptr) { AXLOGD("PUSphereRender::render create vertex buffer failed"); @@ -902,9 +900,9 @@ void PUSphereRender::render(Renderer* renderer, const Mat4& transform, ParticleS } _vertices.resize(vertexCount * particleSystem->getParticleQuota()); - _indexBuffer = backend::DriverBase::getInstance()->newBuffer( - sizeof(uint16_t) * indexCount * particleSystem->getParticleQuota(), backend::BufferType::INDEX, - backend::BufferUsage::DYNAMIC); + _indexBuffer = rhi::DriverBase::getInstance()->createBuffer( + sizeof(uint16_t) * indexCount * particleSystem->getParticleQuota(), rhi::BufferType::INDEX, + rhi::BufferUsage::DYNAMIC); if (_indexBuffer == nullptr) { AXLOGD("PUSphereRender::render create index buffer failed"); @@ -937,11 +935,11 @@ void PUSphereRender::render(Renderer* renderer, const Mat4& transform, ParticleS for (unsigned int i = 0; i < vertexCount; ++i) { - val = texRot * Vec3(_vertexTemplate[vertexindex + i].uv.x, _vertexTemplate[vertexindex + i].uv.y, 0.0f); + val = texRot * Vec3(_vertexTemplate[vertexindex + i].texCoord.x, _vertexTemplate[vertexindex + i].texCoord.y, 0.0f); mat.transformPoint(_vertexTemplate[vertexindex + i].position, &_vertices[vertexindex + i].position); _vertices[vertexindex + i].color = particle->color; - _vertices[vertexindex + i].uv.x = val.x; - _vertices[vertexindex + i].uv.y = val.y; + _vertices[vertexindex + i].texCoord.x = val.x; + _vertices[vertexindex + i].texCoord.y = val.y; } vertexindex += vertexCount; index += indexCount; @@ -990,7 +988,7 @@ void PUSphereRender::buildBuffers(unsigned short count) for (unsigned int segment = 0; segment <= _numberOfSegments; segment++) { - VertexInfo vi; + V3F_T2F_C4F vi; float x0 = r0 * sinf(segment * stepSegmentAngle); float z0 = r0 * cosf(segment * stepSegmentAngle); @@ -998,11 +996,11 @@ void PUSphereRender::buildBuffers(unsigned short count) vi.position.set(x0, y0, z0); // Colour - vi.color = Vec4::ONE; + vi.color = Color::WHITE; // Texture Coordinates - vi.uv.x = (float)segment / (float)_numberOfSegments; - vi.uv.y = 1.0f - (float)ring / (float)_numberOfRings; + vi.texCoord.x = (float)segment / (float)_numberOfSegments; + vi.texCoord.y = 1.0f - (float)ring / (float)_numberOfRings; if (ring != _numberOfRings) { diff --git a/extensions/Particle3D/src/Particle3D/PU/PURender.h b/extensions/Particle3D/src/Particle3D/PU/PURender.h index c906d3230851..033b37f019a8 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURender.h +++ b/extensions/Particle3D/src/Particle3D/PU/PURender.h @@ -28,12 +28,11 @@ #include -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/Particle3DRender.h" -#include "renderer/RenderState.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/Buffer.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/rhi/Buffer.h" namespace ax { @@ -66,7 +65,7 @@ class AX_EX_DLL PUParticle3DEntityRender : public PURender { public: void copyAttributesTo(PUParticle3DEntityRender* render); - virtual void reset() override; + void reset() override; PUParticle3DEntityRender(); virtual ~PUParticle3DEntityRender(); @@ -78,35 +77,28 @@ class AX_EX_DLL PUParticle3DEntityRender : public PURender void onAfterDraw(); protected: - struct VertexInfo - { - Vec3 position; - Vec2 uv; - Vec4 color; - }; - MeshCommand _meshCommand; RenderState::StateBlock _stateBlock; Texture2D* _texture = nullptr; - backend::ProgramState* _programState = nullptr; - backend::Buffer* _indexBuffer = nullptr; // index buffer - backend::Buffer* _vertexBuffer = nullptr; // vertex buffer + rhi::ProgramState* _programState = nullptr; + rhi::Buffer* _indexBuffer = nullptr; // index buffer + rhi::Buffer* _vertexBuffer = nullptr; // vertex buffer - std::vector _vertices; + std::vector _vertices; std::vector _indices; std::string _texFile; - backend::UniformLocation _locColor; - backend::UniformLocation _locTexture; - backend::UniformLocation _locPMatrix; + rhi::UniformLocation _locColor; + rhi::UniformLocation _locTexture; + rhi::UniformLocation _locPMatrix; // renderer state cache variables bool _rendererDepthTestEnabled = true; - backend::CompareFunction _rendererDepthCmpFunc = backend::CompareFunction::LESS; - backend::CullMode _rendererCullMode = backend::CullMode::BACK; - backend::Winding _rendererWinding = backend::Winding::COUNTER_CLOCK_WISE; + rhi::CompareFunc _rendererDepthCmpFunc = rhi::CompareFunc::LESS; + rhi::CullMode _rendererCullMode = rhi::CullMode::BACK; + rhi::Winding _rendererWinding = rhi::Winding::COUNTER_CLOCK_WISE; bool _rendererDepthWrite = false; }; @@ -161,9 +153,9 @@ class AX_EX_DLL PUParticle3DQuadRender : public PUParticle3DEntityRender void setTextureCoordsColumns(unsigned short textureCoordsColumns); unsigned int getNumTextureCoords(); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual PUParticle3DQuadRender* clone() override; + PUParticle3DQuadRender* clone() override; void copyAttributesTo(PUParticle3DQuadRender* render); PUParticle3DQuadRender(); @@ -172,7 +164,7 @@ class AX_EX_DLL PUParticle3DQuadRender : public PUParticle3DEntityRender protected: void getOriginOffset(int& offsetX, int& offsetY); void determineUVCoords(PUParticle3D* particle); - void fillVertex(unsigned short index, const Vec3& pos, const Vec4& color, const Vec2& uv); + void fillVertex(unsigned short index, const Vec3& pos, const Color& color, const Vec2& uv); void fillTriangle(unsigned short index, unsigned short v0, unsigned short v1, unsigned short v2); protected: @@ -194,12 +186,12 @@ class AX_EX_DLL PUParticle3DModelRender : public PURender public: static PUParticle3DModelRender* create(std::string_view modelFile, std::string_view texFile = ""); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual PUParticle3DModelRender* clone() override; + PUParticle3DModelRender* clone() override; void copyAttributesTo(PUParticle3DModelRender* render); - virtual void reset() override; + void reset() override; PUParticle3DModelRender(); virtual ~PUParticle3DModelRender(); @@ -215,9 +207,9 @@ class AX_EX_DLL PUParticle3DBoxRender : public PUParticle3DEntityRender public: static PUParticle3DBoxRender* create(std::string_view texFile = ""); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual PUParticle3DBoxRender* clone() override; + PUParticle3DBoxRender* clone() override; PUParticle3DBoxRender(); virtual ~PUParticle3DBoxRender(); @@ -231,9 +223,9 @@ class AX_EX_DLL PUSphereRender : public PUParticle3DEntityRender public: static PUSphereRender* create(std::string_view texFile = ""); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual PUSphereRender* clone() override; + PUSphereRender* clone() override; void copyAttributesTo(PUSphereRender* render); PUSphereRender(); @@ -245,7 +237,7 @@ class AX_EX_DLL PUSphereRender : public PUParticle3DEntityRender protected: unsigned short _numberOfRings; unsigned short _numberOfSegments; - std::vector _vertexTemplate; + std::vector _vertexTemplate; }; } diff --git a/extensions/Particle3D/src/Particle3D/PU/PURendererTranslator.cpp b/extensions/Particle3D/src/Particle3D/PU/PURendererTranslator.cpp index 013782ce7a50..7e2f30539b3b 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURendererTranslator.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PURendererTranslator.cpp @@ -580,7 +580,7 @@ void PURendererTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* // Property: initial_colour if (passValidateProperty(compiler, prop, token[TOKEN_INITIAL_COLOUR], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { static_cast(_renderer)->setInitialColor(val); @@ -593,7 +593,7 @@ void PURendererTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_INITIAL_COLOUR], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { static_cast(_renderer)->setInitialColor(val); @@ -605,7 +605,7 @@ void PURendererTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* // Property: colour_change if (passValidateProperty(compiler, prop, token[TOKEN_COLOUR_CHANGE], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { static_cast(_renderer)->setColorChange(val); @@ -618,7 +618,7 @@ void PURendererTranslator::translate(PUScriptCompiler* compiler, PUAbstractNode* if (passValidateProperty(compiler, prop, token[TOKEN_RIBBONTRAIL_COLOUR_CHANGE], VAL_COLOURVALUE)) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { static_cast(_renderer)->setColorChange(val); diff --git a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.cpp b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.cpp index 98ddfa5b593e..0ad826b3cebc 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.cpp @@ -26,13 +26,18 @@ #include "Particle3D/PU/PURibbonTrail.h" #include "Particle3D/PU/PUParticleSystem3D.h" -#include "base/Director.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/backend/ProgramState.h" -#include "2d/Camera.h" -#include "3d/MeshRenderer.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/2d/Camera.h" +#include "axmol/3d/MeshRenderer.h" + +#if defined(_WIN32) +# pragma push_macro("TRANSPARENT") +# undef TRANSPARENT +#endif namespace ax { @@ -137,8 +142,8 @@ void PURibbonTrail::setNumberOfChains(size_t numChains) PUBillboardChain::setNumberOfChains(numChains); - _initialColor.resize(numChains, Vec4::ONE); - _deltaColor.resize(numChains, Vec4::ZERO); + _initialColor.resize(numChains, Color::WHITE); + _deltaColor.resize(numChains, Color::TRANSPARENT); _initialWidth.resize(numChains, 10); _deltaWidth.resize(numChains, 0); @@ -175,7 +180,7 @@ void PURibbonTrail::clearChain(size_t chainIndex) } } //----------------------------------------------------------------------- -void PURibbonTrail::setInitialColour(size_t chainIndex, const Vec4& col) +void PURibbonTrail::setInitialColour(size_t chainIndex, const Color& col) { setInitialColour(chainIndex, col.x, col.y, col.z, col.w); } @@ -189,7 +194,7 @@ void PURibbonTrail::setInitialColour(size_t chainIndex, float r, float g, float _initialColor[chainIndex].w = a; } //----------------------------------------------------------------------- -const Vec4& PURibbonTrail::getInitialColour(size_t chainIndex) const +const Color& PURibbonTrail::getInitialColour(size_t chainIndex) const { AXASSERT(chainIndex < _chainCount, "chainIndex out of bounds"); return _initialColor[chainIndex]; @@ -207,7 +212,7 @@ float PURibbonTrail::getInitialWidth(size_t chainIndex) const return _initialWidth[chainIndex]; } //----------------------------------------------------------------------- -void PURibbonTrail::setColourChange(size_t chainIndex, const Vec4& valuePerSecond) +void PURibbonTrail::setColourChange(size_t chainIndex, const Color& valuePerSecond) { setColourChange(chainIndex, valuePerSecond.x, valuePerSecond.y, valuePerSecond.z, valuePerSecond.w); } @@ -223,7 +228,7 @@ void PURibbonTrail::setColourChange(size_t chainIndex, float r, float g, float b manageController(); } //----------------------------------------------------------------------- -const Vec4& PURibbonTrail::getColourChange(size_t chainIndex) const +const Color& PURibbonTrail::getColourChange(size_t chainIndex) const { AXASSERT(chainIndex < _chainCount, "chainIndex out of bounds"); return _deltaColor[chainIndex]; @@ -247,7 +252,7 @@ void PURibbonTrail::manageController() _needTimeUpdate = false; for (size_t i = 0; i < _chainCount; ++i) { - if (_deltaWidth[i] != 0 || _deltaColor[i] != Vec4::ZERO) + if (_deltaWidth[i] != 0 || !_deltaColor[i].equals(Color::TRANSPARENT)) { _needTimeUpdate = true; break; @@ -421,3 +426,7 @@ void PURibbonTrail::update(float deltaTime) } } + +#if defined(_WIN32) +# pragma pop_macro("TRANSPARENT") +#endif diff --git a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.h b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.h index fa1d97a675a4..21077fe43c2f 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.h +++ b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrail.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUBillboardChain.h" #include #include @@ -83,7 +83,7 @@ class PURibbonTrail : public PUBillboardChain /** @copydoc BillboardChain::setMaxChainElements */ void setMaxChainElements(size_t maxElements) override; /** @copydoc BillboardChain::setNumberOfChains */ - virtual void setNumberOfChains(size_t numChains) override; + void setNumberOfChains(size_t numChains) override; /** @copydoc BillboardChain::clearChain */ void clearChain(size_t chainIndex) override; @@ -93,7 +93,7 @@ class PURibbonTrail : public PUBillboardChain @note Only used if this instance is using vertex colours. */ - virtual void setInitialColour(size_t chainIndex, const Vec4& col); + virtual void setInitialColour(size_t chainIndex, const Color& col); /** Set the starting ribbon colour. @param chainIndex The index of the chain @param r,b,g,a The initial colour @@ -102,13 +102,13 @@ class PURibbonTrail : public PUBillboardChain */ virtual void setInitialColour(size_t chainIndex, float r, float g, float b, float a = 1.0); /** Get the starting ribbon colour. */ - virtual const Vec4& getInitialColour(size_t chainIndex) const; + virtual const Color& getInitialColour(size_t chainIndex) const; /** Enables / disables fading the trail using colour. @param chainIndex The index of the chain @param valuePerSecond The amount to subtract from colour each second */ - virtual void setColourChange(size_t chainIndex, const Vec4& valuePerSecond); + virtual void setColourChange(size_t chainIndex, const Color& valuePerSecond); /** Set the starting ribbon width in world units. @param chainIndex The index of the chain @@ -133,7 +133,7 @@ class PURibbonTrail : public PUBillboardChain virtual void setColourChange(size_t chainIndex, float r, float g, float b, float a); /** Get the per-second fading amount */ - virtual const Vec4& getColourChange(size_t chainIndex) const; + virtual const Color& getColourChange(size_t chainIndex) const; void update(float deltaTime); @@ -176,7 +176,7 @@ class PURibbonTrail : public PUBillboardChain float _elemLength; /// Squared length of each element float _squaredElemLength; - typedef std::vector ColorValueList; + typedef std::vector ColorValueList; typedef std::vector RealList; /// Initial colour of the ribbon ColorValueList _initialColor; diff --git a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.cpp b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.cpp index b5af038f3587..eb386f8d5493 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.cpp @@ -28,13 +28,13 @@ #include "Particle3D/PU/PURibbonTrailRender.h" #include "Particle3D/PU/PUUtil.h" #include "Particle3D/PU/PUSimpleSpline.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "base/Director.h" -#include "3d/MeshRenderer.h" -#include "3d/Mesh.h" -#include "2d/Camera.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/base/Director.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Mesh.h" +#include "axmol/2d/Camera.h" #include namespace ax @@ -192,22 +192,22 @@ void PURibbonTrailRender::setRandomInitialColor(bool randomInitialColour) _randomInitialColor = randomInitialColour; } //----------------------------------------------------------------------- -const Vec4& PURibbonTrailRender::getInitialColor() const +const Color& PURibbonTrailRender::getInitialColor() const { return _initialColor; } //----------------------------------------------------------------------- -void PURibbonTrailRender::setInitialColor(const Vec4& initialColour) +void PURibbonTrailRender::setInitialColor(const Color& initialColour) { _initialColor = initialColour; } //----------------------------------------------------------------------- -const Vec4& PURibbonTrailRender::getColorChange() const +const Color& PURibbonTrailRender::getColorChange() const { return _colorChange; } //----------------------------------------------------------------------- -void PURibbonTrailRender::setColorChange(const Vec4& colourChange) +void PURibbonTrailRender::setColorChange(const Color& colourChange) { _colorChange = colourChange; } diff --git a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.h b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.h index d3cc6a0e5546..0bef259594cb 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.h +++ b/extensions/Particle3D/src/Particle3D/PU/PURibbonTrailRender.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/Particle3DRender.h" #include "Particle3D/PU/PUListener.h" #include "Particle3D/PU/PURender.h" @@ -85,14 +85,14 @@ class AX_EX_DLL PURibbonTrailRender : public PURender, public PUListener static PURibbonTrailRender* create(std::string_view texFile = ""); - virtual void notifyRescaled(const Vec3& scale) override; - virtual void prepare() override; - virtual void unPrepare() override; - virtual void updateRender(PUParticle3D* particle, float deltaTime, bool firstParticle) override; + void notifyRescaled(const Vec3& scale) override; + void prepare() override; + void unPrepare() override; + void updateRender(PUParticle3D* particle, float deltaTime, bool firstParticle) override; - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; - virtual void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; /** Getters and Setters */ @@ -111,17 +111,17 @@ class AX_EX_DLL PURibbonTrailRender : public PURender, public PUListener bool isRandomInitialColor() const; void setRandomInitialColor(bool randomInitialColour); - const Vec4& getInitialColor() const; - void setInitialColor(const Vec4& initialColour); + const Color& getInitialColor() const; + void setInitialColor(const Color& initialColour); - const Vec4& getColorChange() const; - void setColorChange(const Vec4& colourChange); + const Color& getColorChange() const; + void setColorChange(const Color& colourChange); /** Deletes all ChildSceneNodes en Entities. */ void destroyAll(); - virtual PURibbonTrailRender* clone() override; + PURibbonTrailRender* clone() override; void copyAttributesTo(PURibbonTrailRender* render); PURibbonTrailRender(); @@ -142,8 +142,8 @@ class AX_EX_DLL PURibbonTrailRender : public PURender, public PUListener bool _randomInitialColor; bool _setLength; bool _setWidth; - Vec4 _initialColor; - Vec4 _colorChange; + Color _initialColor; + Color _colorChange; Node* _childNode; std::string _texFile; }; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScaleAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUScaleAffector.h index 9c3a19819b76..1f4c28a2357d 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScaleAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScaleAffector.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUDynamicAttribute.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -44,7 +44,7 @@ class AX_EX_DLL PUScaleAffector : public PUAffector static PUScaleAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ @@ -75,7 +75,7 @@ class AX_EX_DLL PUScaleAffector : public PUAffector bool isSinceStartSystem() const { return _sinceStartSystem; }; void setSinceStartSystem(bool sinceStartSystem) { _sinceStartSystem = sinceStartSystem; }; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUScaleAffector(); virtual ~PUScaleAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScaleVelocityAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUScaleVelocityAffector.h index 01bacd95f5cd..abd0e4db17e3 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScaleVelocityAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScaleVelocityAffector.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUDynamicAttribute.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,7 +41,7 @@ class AX_EX_DLL PUScaleVelocityAffector : public PUAffector static PUScaleVelocityAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ @@ -59,7 +59,7 @@ class AX_EX_DLL PUScaleVelocityAffector : public PUAffector bool isStopAtFlip() const { return _stopAtFlip; }; void setStopAtFlip(bool stopAtFlip) { _stopAtFlip = stopAtFlip; }; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUScaleVelocityAffector(); virtual ~PUScaleVelocityAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.cpp b/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.cpp index 996901ca73fd..3a05c0f23a2a 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.cpp @@ -26,7 +26,7 @@ #include "PUScriptCompiler.h" #include "Particle3D/PU/PUTranslateManager.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.h b/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.h index 9b6f1ca85c6b..6563993248fd 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptCompiler.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptParser.h" #include diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptLexer.h b/extensions/Particle3D/src/Particle3D/PU/PUScriptLexer.h index a365d48d8f2e..a8a461cd2f8e 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptLexer.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptLexer.h @@ -27,10 +27,10 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include #include -#include "base/Logging.h" +#include "axmol/base/Logging.h" #include "extensions/ExtensionExport.h" namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptParser.h b/extensions/Particle3D/src/Particle3D/PU/PUScriptParser.h index 4e8db4bf0f27..957754194277 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptParser.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptParser.h @@ -32,8 +32,8 @@ #include #include -#include "base/Logging.h" -#include "base/Object.h" +#include "axmol/base/Logging.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUScriptLexer.h" namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.cpp b/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.cpp index e73431be83ad..f3e979b8f279 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.cpp @@ -444,7 +444,7 @@ bool PUScriptTranslator::getVector3(PUAbstractNodeList::const_iterator i, //------------------------------------------------------------------------- bool PUScriptTranslator::getVector4(PUAbstractNodeList::const_iterator i, PUAbstractNodeList::const_iterator end, - Vec4* result, + Color* result, int maxEntries) { int n = 0; @@ -715,7 +715,7 @@ bool PUScriptTranslator::passValidatePropertyValidVector3(PUScriptCompiler* /*co //------------------------------------------------------------------------- bool PUScriptTranslator::passValidatePropertyValidVector4(PUScriptCompiler* /*compiler*/, PUPropertyAbstractNode* prop) { - Vec4 val; + Color val; if (getVector4(prop->values.begin(), prop->values.end(), &val)) { return true; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.h b/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.h index 97995555999b..50fdb5430020 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUScriptTranslator.h @@ -28,8 +28,8 @@ #include -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUScriptCompiler.h" namespace ax @@ -665,7 +665,7 @@ class PUScriptTranslator */ bool getVector4(PUAbstractNodeList::const_iterator i, PUAbstractNodeList::const_iterator end, - Vec4* result, + Color* result, int maxEntries = 4); /** Parse Quaternion diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.cpp b/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.cpp index e2873853d89e..b25312927203 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #include "PUSimpleSpline.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.h b/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.h index 31c3fc25aca6..7af8b1c25058 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSimpleSpline.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include #include "extensions/ExtensionExport.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSineForceAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUSineForceAffector.h index 409bd840f859..afba9e5b94cc 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSineForceAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSineForceAffector.h @@ -27,7 +27,7 @@ #pragma once #include "PUBaseForceAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,8 +41,8 @@ class AX_EX_DLL PUSineForceAffector : public PUBaseForceAffector static PUSineForceAffector* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ @@ -54,7 +54,7 @@ class AX_EX_DLL PUSineForceAffector : public PUBaseForceAffector float getFrequencyMax() const; void setFrequencyMax(const float frequencyMax); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUSineForceAffector(); virtual ~PUSineForceAffector(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.cpp b/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.cpp index 70aeb61b8aeb..0c2516532836 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #include "Particle3D/PU/PUSlaveBehaviour.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.h b/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.h index 8543cba2ec66..2055ee20e65c 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSlaveBehaviour.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "Particle3D/PU/PUParticleSystem3D.h" #include "Particle3D/PU/PUBehaviour.h" #include @@ -48,10 +48,10 @@ class AX_EX_DLL PUSlaveBehaviour : public PUBehaviour /** See ParticleBehaviour. */ - virtual void updateBehaviour(PUParticle3D* particle, float deltaTime) override; + void updateBehaviour(PUParticle3D* particle, float deltaTime) override; - virtual PUSlaveBehaviour* clone() override; - virtual void copyAttributesTo(PUBehaviour* behaviour) override; + PUSlaveBehaviour* clone() override; + void copyAttributesTo(PUBehaviour* behaviour) override; PUSlaveBehaviour(); virtual ~PUSlaveBehaviour(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSlaveEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUSlaveEmitter.h index ae05ec049cdc..ef6f50c792c2 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSlaveEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSlaveEmitter.h @@ -51,38 +51,38 @@ class AX_EX_DLL PUSlaveEmitter : public PUEmitter, public PUListener /** See ParticleEmitter. */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; /** See ParticleEmitter. */ - virtual void initParticleDirection(PUParticle3D* particle) override; + void initParticleDirection(PUParticle3D* particle) override; /** See ParticleEmitter. */ - virtual void prepare() override; + void prepare() override; /** See ParticleEmitter. */ - virtual void unPrepare() override; + void unPrepare() override; /** See ParticleEmitter. */ - virtual void notifyStart() override; + void notifyStart() override; /** Initialise the emitted particle. This means that its position is set. */ - virtual void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleEmitted(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; /** No implementation. */ - virtual void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; + void particleExpired(PUParticleSystem3D* particleSystem, PUParticle3D* particle) override; /** */ void setMasterEmitterName(std::string_view masterEmitterName); - virtual PUSlaveEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUSlaveEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUSlaveEmitter(); virtual ~PUSlaveEmitter(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSphere.h b/extensions/Particle3D/src/Particle3D/PU/PUSphere.h index 6519d980c9dc..d5c1cc006f22 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSphere.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSphere.h @@ -26,9 +26,9 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" -#include "3d/AABB.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" +#include "axmol/3d/AABB.h" #include namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSphereCollider.h b/extensions/Particle3D/src/Particle3D/PU/PUSphereCollider.h index 291720ef4b72..6245eab9c266 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSphereCollider.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSphereCollider.h @@ -28,7 +28,7 @@ #include "PUBaseCollider.h" #include "Particle3D/PU/PUSphere.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -41,8 +41,8 @@ class AX_EX_DLL PUSphereCollider : public PUBaseCollider static PUSphereCollider* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Returns the radius of the sphere */ @@ -68,7 +68,7 @@ class AX_EX_DLL PUSphereCollider : public PUBaseCollider */ void calculateDirectionAfterCollision(PUParticle3D* particle, Vec3 distance, float distanceLength); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUSphereCollider(); virtual ~PUSphereCollider(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUSphereSurfaceEmitter.h b/extensions/Particle3D/src/Particle3D/PU/PUSphereSurfaceEmitter.h index e0ddeefd88bc..8a653a9f91d6 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUSphereSurfaceEmitter.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUSphereSurfaceEmitter.h @@ -45,14 +45,14 @@ class AX_EX_DLL PUSphereSurfaceEmitter : public PUEmitter /** */ - virtual void initParticlePosition(PUParticle3D* particle) override; + void initParticlePosition(PUParticle3D* particle) override; /** */ - virtual void initParticleDirection(PUParticle3D* particle) override; + void initParticleDirection(PUParticle3D* particle) override; - virtual PUSphereSurfaceEmitter* clone() override; - virtual void copyAttributesTo(PUEmitter* emitter) override; + PUSphereSurfaceEmitter* clone() override; + void copyAttributesTo(PUEmitter* emitter) override; PUSphereSurfaceEmitter(); virtual ~PUSphereSurfaceEmitter(){}; diff --git a/extensions/Particle3D/src/Particle3D/PU/PUTextureAnimator.h b/extensions/Particle3D/src/Particle3D/PU/PUTextureAnimator.h index 44174d42ccb9..461000db54ea 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUTextureAnimator.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUTextureAnimator.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -51,9 +51,9 @@ class AX_EX_DLL PUTextureAnimator : public PUAffector static PUTextureAnimator* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void initParticleForEmission(PUParticle3D* particle) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void initParticleForEmission(PUParticle3D* particle) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Returns the AnimationTimeStep. The AnimationTimeStep defines the time between each animation frame. */ float getAnimationTimeStep() const; @@ -85,7 +85,7 @@ class AX_EX_DLL PUTextureAnimator : public PUAffector /** Todo */ void setStartRandom(bool startRandom); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUTextureAnimator(); virtual ~PUTextureAnimator(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUTextureRotator.h b/extensions/Particle3D/src/Particle3D/PU/PUTextureRotator.h index 103aeecfdf28..3a2a09654baf 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUTextureRotator.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUTextureRotator.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUDynamicAttribute.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -43,7 +43,7 @@ class AX_EX_DLL PUTextureRotator : public PUAffector static PUTextureRotator* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Returns an indication whether the 2D rotation speed is the same for all particles in this particle technique, or whether the 2D rotation speed of the particle itself is used. @@ -79,9 +79,9 @@ class AX_EX_DLL PUTextureRotator : public PUAffector float calculateRotationSpeed(PUParticle3D* particle); /** @copydoc ParticleAffector::_initParticleForEmission */ - virtual void initParticleForEmission(PUParticle3D* particle) override; + void initParticleForEmission(PUParticle3D* particle) override; - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUTextureRotator(); virtual ~PUTextureRotator(); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUTranslateManager.h b/extensions/Particle3D/src/Particle3D/PU/PUTranslateManager.h index 2972a50f54f5..d44ac741389f 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUTranslateManager.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUTranslateManager.h @@ -26,7 +26,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "Particle3D/PU/PUParticleSystem3DTranslator.h" #include "Particle3D/PU/PUTechniqueTranslator.h" #include "Particle3D/PU/PURendererTranslator.h" diff --git a/extensions/Particle3D/src/Particle3D/PU/PUUtil.cpp b/extensions/Particle3D/src/Particle3D/PU/PUUtil.cpp index ffb4f2ca3cbd..97500a719eff 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUUtil.cpp +++ b/extensions/Particle3D/src/Particle3D/PU/PUUtil.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #include "PUUtil.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" namespace ax { diff --git a/extensions/Particle3D/src/Particle3D/PU/PUUtil.h b/extensions/Particle3D/src/Particle3D/PU/PUUtil.h index fab500b0fe34..fe16abd8e893 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUUtil.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUUtil.h @@ -26,8 +26,8 @@ #pragma once -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include namespace ax diff --git a/extensions/Particle3D/src/Particle3D/PU/PUVelocityMatchingAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUVelocityMatchingAffector.h index 2ecc9d033a6e..5737d57d9f41 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUVelocityMatchingAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUVelocityMatchingAffector.h @@ -27,7 +27,7 @@ #pragma once #include "Particle3D/PU/PUAffector.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -40,7 +40,7 @@ class AX_EX_DLL PUVelocityMatchingAffector : public PUAffector static PUVelocityMatchingAffector* create(); - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** Todo */ float getRadius() const; @@ -49,7 +49,7 @@ class AX_EX_DLL PUVelocityMatchingAffector : public PUAffector */ void setRadius(float radius); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; /** @copydoc ParticleAffector::_prepare */ // virtual void _prepare(ParticleTechnique* particleTechnique); diff --git a/extensions/Particle3D/src/Particle3D/PU/PUVortexAffector.h b/extensions/Particle3D/src/Particle3D/PU/PUVortexAffector.h index 6f922140e754..56de5480d7a8 100644 --- a/extensions/Particle3D/src/Particle3D/PU/PUVortexAffector.h +++ b/extensions/Particle3D/src/Particle3D/PU/PUVortexAffector.h @@ -28,7 +28,7 @@ #include "Particle3D/PU/PUAffector.h" #include "Particle3D/PU/PUDynamicAttribute.h" -#include "base/Types.h" +#include "axmol/base/Types.h" namespace ax { @@ -42,8 +42,8 @@ class AX_EX_DLL PUVortexAffector : public PUAffector static PUVortexAffector* create(); - virtual void preUpdateAffector(float deltaTime) override; - virtual void updatePUAffector(PUParticle3D* particle, float deltaTime) override; + void preUpdateAffector(float deltaTime) override; + void updatePUAffector(PUParticle3D* particle, float deltaTime) override; /** */ const Vec3& getRotationVector() const; @@ -60,7 +60,7 @@ class AX_EX_DLL PUVortexAffector : public PUAffector */ void setRotationSpeed(PUDynamicAttribute* dynRotationSpeed); - virtual void copyAttributesTo(PUAffector* affector) override; + void copyAttributesTo(PUAffector* affector) override; PUVortexAffector(); virtual ~PUVortexAffector(); diff --git a/extensions/Particle3D/src/Particle3D/Particle3DAffector.h b/extensions/Particle3D/src/Particle3D/Particle3DAffector.h index 7d07490fa037..9c8a615b1578 100644 --- a/extensions/Particle3D/src/Particle3D/Particle3DAffector.h +++ b/extensions/Particle3D/src/Particle3D/Particle3DAffector.h @@ -25,7 +25,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include #include "extensions/ExtensionExport.h" diff --git a/extensions/Particle3D/src/Particle3D/Particle3DEmitter.h b/extensions/Particle3D/src/Particle3D/Particle3DEmitter.h index ed6c0f3cc25d..17b8e11cd5d4 100644 --- a/extensions/Particle3D/src/Particle3D/Particle3DEmitter.h +++ b/extensions/Particle3D/src/Particle3D/Particle3DEmitter.h @@ -25,7 +25,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include #include "extensions/ExtensionExport.h" diff --git a/extensions/Particle3D/src/Particle3D/Particle3DRender.cpp b/extensions/Particle3D/src/Particle3D/Particle3DRender.cpp index d30404b021d8..7778a3c9a10e 100644 --- a/extensions/Particle3D/src/Particle3D/Particle3DRender.cpp +++ b/extensions/Particle3D/src/Particle3D/Particle3DRender.cpp @@ -24,18 +24,18 @@ ****************************************************************************/ #include "Particle3D/ParticleSystem3D.h" #include // offsetof -#include "base/Types.h" +#include "axmol/base/Types.h" #include "Particle3D/Particle3DRender.h" -#include "renderer/MeshCommand.h" -#include "renderer/Renderer.h" -#include "renderer/TextureCache.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Buffer.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/Shaders.h" -#include "base/Director.h" -#include "3d/MeshRenderer.h" -#include "2d/Camera.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/base/Director.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/2d/Camera.h" namespace ax { @@ -77,10 +77,10 @@ void Particle3DQuadRender::render(Renderer* renderer, const Mat4& transform, Par if (_vertexBuffer == nullptr) { - size_t stride = sizeof(Particle3DQuadRender::posuvcolor); + size_t stride = sizeof(V3F_T2F_C4F); _vertexBuffer = - backend::DriverBase::getInstance()->newBuffer(stride * 4 * particleSystem->getParticleQuota(), - backend::BufferType::VERTEX, backend::BufferUsage::DYNAMIC); + rhi::DriverBase::getInstance()->createBuffer(stride * 4 * particleSystem->getParticleQuota(), + rhi::BufferType::VERTEX, rhi::BufferUsage::DYNAMIC); if (_vertexBuffer == nullptr) { AXLOGD("Particle3DQuadRender::render create vertex buffer failed"); @@ -91,8 +91,8 @@ void Particle3DQuadRender::render(Renderer* renderer, const Mat4& transform, Par if (_indexBuffer == nullptr) { _indexBuffer = - backend::DriverBase::getInstance()->newBuffer(sizeof(uint16_t) * 6 * particleSystem->getParticleQuota(), - backend::BufferType::INDEX, backend::BufferUsage::DYNAMIC); + rhi::DriverBase::getInstance()->createBuffer(sizeof(uint16_t) * 6 * particleSystem->getParticleQuota(), + rhi::BufferType::INDEX, rhi::BufferUsage::DYNAMIC); if (_indexBuffer == nullptr) { AXLOGD("Particle3DQuadRender::render create index buffer failed"); @@ -127,19 +127,19 @@ void Particle3DQuadRender::render(Renderer* renderer, const Mat4& transform, Par position = particle->position; _posuvcolors[vertexindex].position = (position + (-halfwidth - halfheight)); _posuvcolors[vertexindex].color = particle->color; - _posuvcolors[vertexindex].uv.set(particle->lb_uv); + _posuvcolors[vertexindex].texCoord.set(particle->lb_uv); _posuvcolors[vertexindex + 1].position = (position + (halfwidth - halfheight)); _posuvcolors[vertexindex + 1].color = particle->color; - _posuvcolors[vertexindex + 1].uv.set(particle->rt_uv.x, particle->lb_uv.y); + _posuvcolors[vertexindex + 1].texCoord.set(particle->rt_uv.x, particle->lb_uv.y); _posuvcolors[vertexindex + 2].position = (position + (-halfwidth + halfheight)); _posuvcolors[vertexindex + 2].color = particle->color; - _posuvcolors[vertexindex + 2].uv.set(particle->lb_uv.x, particle->rt_uv.y); + _posuvcolors[vertexindex + 2].texCoord.set(particle->lb_uv.x, particle->rt_uv.y); _posuvcolors[vertexindex + 3].position = (position + (halfwidth + halfheight)); _posuvcolors[vertexindex + 3].color = particle->color; - _posuvcolors[vertexindex + 3].uv.set(particle->rt_uv); + _posuvcolors[vertexindex + 3].texCoord.set(particle->rt_uv); _indexData[index] = vertexindex; _indexData[index + 1] = vertexindex + 1; @@ -202,18 +202,18 @@ bool Particle3DQuadRender::initQuadRender(std::string_view texFile) if (tex) { _texture = tex; - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_TEXTURE_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_TEXTURE_3D); + _programState = new rhi::ProgramState(program); } } if (!_programState) { - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::PARTICLE_COLOR_3D); - _programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::PARTICLE_COLOR_3D); + _programState = new rhi::ProgramState(program); } - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); pipelineDescriptor.programState = _programState; _locColor = _programState->getUniformLocation("u_color"); @@ -225,7 +225,7 @@ bool Particle3DQuadRender::initQuadRender(std::string_view texFile) _stateBlock.setDepthTest(true); _stateBlock.setDepthWrite(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setCullFace(true); return true; @@ -234,9 +234,9 @@ bool Particle3DQuadRender::initQuadRender(std::string_view texFile) void Particle3DQuadRender::onBeforeDraw() { auto* renderer = Director::getInstance()->getRenderer(); - auto& pipelineDescriptor = _meshCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _meshCommand.getPipelineDesc(); _rendererDepthTestEnabled = renderer->getDepthTest(); - _rendererDepthCmpFunc = renderer->getDepthCompareFunction(); + _rendererDepthCmpFunc = renderer->getDepthCompareFunc(); _rendererCullMode = renderer->getCullMode(); _rendererDepthWrite = renderer->getDepthWrite(); _rendererWinding = renderer->getWinding(); @@ -248,7 +248,7 @@ void Particle3DQuadRender::onAfterDraw() { auto* renderer = Director::getInstance()->getRenderer(); renderer->setDepthTest(_rendererDepthTestEnabled); - renderer->setDepthCompareFunction(_rendererDepthCmpFunc); + renderer->setDepthCompareFunc(_rendererDepthCmpFunc); renderer->setCullMode(_rendererCullMode); renderer->setDepthWrite(_rendererDepthWrite); renderer->setWinding(_rendererWinding); @@ -343,7 +343,7 @@ Particle3DRender::Particle3DRender() : _particleSystem(nullptr), _isVisible(true), _rendererScale(Vec3::ONE), _depthTest(true), _depthWrite(false) { _stateBlock.setCullFace(false); - _stateBlock.setCullFaceSide(backend::CullMode::BACK); + _stateBlock.setCullFaceSide(rhi::CullMode::BACK); _stateBlock.setDepthTest(false); _stateBlock.setDepthWrite(false); _stateBlock.setBlend(true); diff --git a/extensions/Particle3D/src/Particle3D/Particle3DRender.h b/extensions/Particle3D/src/Particle3D/Particle3DRender.h index b52b87cc5741..cf2e7ecb79f1 100644 --- a/extensions/Particle3D/src/Particle3D/Particle3DRender.h +++ b/extensions/Particle3D/src/Particle3D/Particle3DRender.h @@ -27,13 +27,12 @@ #include -#include "renderer/RenderState.h" -#include "renderer/backend/Types.h" -#include "renderer/MeshCommand.h" -#include "renderer/CallbackCommand.h" -#include "renderer/backend/Buffer.h" -#include "base/Object.h" -#include "math/Math.h" +#include "axmol/renderer/RenderState.h" +#include "axmol/renderer/MeshCommand.h" +#include "axmol/renderer/CallbackCommand.h" +#include "axmol/rhi/Buffer.h" +#include "axmol/base/Object.h" +#include "axmol/math/Math.h" #include "extensions/ExtensionExport.h" namespace ax @@ -98,9 +97,9 @@ class AX_EX_DLL Particle3DQuadRender : public Particle3DRender public: static Particle3DQuadRender* create(std::string_view texFile = ""); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual void reset() override; + void reset() override; Particle3DQuadRender(); virtual ~Particle3DQuadRender(); @@ -115,30 +114,23 @@ class AX_EX_DLL Particle3DQuadRender : public Particle3DRender //CallbackCommand _beforeCommand; //CallbackCommand _afterCommand; Texture2D* _texture = nullptr; - backend::ProgramState* _programState = nullptr; - backend::Buffer* _indexBuffer = nullptr; // index buffer - backend::Buffer* _vertexBuffer = nullptr; // vertex buffer - - struct posuvcolor - { - Vec3 position; - Vec2 uv; - Vec4 color; - }; - - std::vector _posuvcolors; // vertex data + rhi::ProgramState* _programState = nullptr; + rhi::Buffer* _indexBuffer = nullptr; // index buffer + rhi::Buffer* _vertexBuffer = nullptr; // vertex buffer + + std::vector _posuvcolors; // vertex data std::vector _indexData; // index data std::string _texFile; - backend::UniformLocation _locColor; - backend::UniformLocation _locTexture; - backend::UniformLocation _locPMatrix; + rhi::UniformLocation _locColor; + rhi::UniformLocation _locTexture; + rhi::UniformLocation _locPMatrix; // renderer state cache variables bool _rendererDepthTestEnabled = true; - backend::CompareFunction _rendererDepthCmpFunc = backend::CompareFunction::LESS; - backend::CullMode _rendererCullMode = backend::CullMode::BACK; - backend::Winding _rendererWinding = backend::Winding::COUNTER_CLOCK_WISE; + rhi::CompareFunc _rendererDepthCmpFunc = rhi::CompareFunc::LESS; + rhi::CullMode _rendererCullMode = rhi::CullMode::BACK; + rhi::Winding _rendererWinding = rhi::Winding::COUNTER_CLOCK_WISE; bool _rendererDepthWrite = false; }; @@ -148,9 +140,9 @@ class AX_EX_DLL Particle3DModelRender : public Particle3DRender public: static Particle3DModelRender* create(std::string_view modelFile, std::string_view texFile = ""); - virtual void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; + void render(Renderer* renderer, const Mat4& transform, ParticleSystem3D* particleSystem) override; - virtual void reset() override; + void reset() override; Particle3DModelRender(); virtual ~Particle3DModelRender(); diff --git a/extensions/Particle3D/src/Particle3D/ParticleSystem3D.h b/extensions/Particle3D/src/Particle3D/ParticleSystem3D.h index e88325ada427..92ff7a52e2a0 100644 --- a/extensions/Particle3D/src/Particle3D/ParticleSystem3D.h +++ b/extensions/Particle3D/src/Particle3D/ParticleSystem3D.h @@ -25,8 +25,8 @@ #pragma once -#include "2d/Node.h" -#include "math/Math.h" +#include "axmol/2d/Node.h" +#include "axmol/math/Math.h" #include #include #include @@ -49,7 +49,7 @@ struct AX_EX_DLL Particle3D // property of particles Vec3 position; // position Quaternion orientation; // Orientation of the particle. - Vec4 color; // particle color + Color color; // particle color Vec2 lb_uv; // left bottom uv Vec2 rt_uv; // right top uv float width; // Own width @@ -170,22 +170,22 @@ class AX_EX_DLL ParticleSystem3D : public Node, public BlendProtocol /** * override function */ - virtual void update(float delta) override; + void update(float delta) override; /** * override function */ - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; /** * override function */ - virtual void setBlendFunc(const BlendFunc& blendFunc) override; + void setBlendFunc(const BlendFunc& blendFunc) override; /** * override function */ - virtual const BlendFunc& getBlendFunc() const override; + const BlendFunc& getBlendFunc() const override; /** * particle system play control diff --git a/extensions/README.md b/extensions/README.md index e309d1077506..e9e01c0865bd 100644 --- a/extensions/README.md +++ b/extensions/README.md @@ -65,7 +65,7 @@ ## physics-nodes - Upstream: https://github.com/axmolengine/axmol -- Version: axmol-1.0 +- Version: axmol-3.0 - License: MIT ## scripting/lua diff --git a/extensions/SDFGen/src/SDFGen/SDFGen.cpp b/extensions/SDFGen/src/SDFGen/SDFGen.cpp index 54c3388d0291..9e19e0d94da1 100644 --- a/extensions/SDFGen/src/SDFGen/SDFGen.cpp +++ b/extensions/SDFGen/src/SDFGen/SDFGen.cpp @@ -2,14 +2,14 @@ #include #include -#include "base/format.h" +#include "axmol/base/format.h" -#include "base/ZipUtils.h" +#include "axmol/base/ZipUtils.h" #include "ImGuiPresenter.h" #include "misc/cpp/imgui_stdlib.h" #include -#include "base/JsonWriter.h" +#include "axmol/base/JsonWriter.h" #include "yasio/utils.hpp" NS_AX_EXT_BEGIN @@ -175,7 +175,7 @@ class FontAtlas : public ax::FontAtlas _atlasName = fmt::format("df {} {}", params->faceSize, params->sourceFont); std::u32string utf32; - if (StringUtils::UTF8ToUTF32(_fontFreeType->getGlyphCollection(), utf32)) + if (text_utils::UTF8ToUTF32(_fontFreeType->getGlyphCollection(), utf32)) this->prepareLetterDefinitions(utf32); _pageDatas.emplace_back(_currentPageData, _currentPageData + _currentPageDataSize); diff --git a/extensions/SDFGen/src/SDFGen/SDFGen.h b/extensions/SDFGen/src/SDFGen/SDFGen.h index a7a5f8a3a152..5c5161ab8198 100644 --- a/extensions/SDFGen/src/SDFGen/SDFGen.h +++ b/extensions/SDFGen/src/SDFGen/SDFGen.h @@ -1,6 +1,6 @@ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/ExtensionMacros.h" NS_AX_EXT_BEGIN diff --git a/extensions/assets-manager/src/assets-manager/AssetsManager.cpp b/extensions/assets-manager/src/assets-manager/AssetsManager.cpp index 7df76cf651fa..4c17b6ead43f 100644 --- a/extensions/assets-manager/src/assets-manager/AssetsManager.cpp +++ b/extensions/assets-manager/src/assets-manager/AssetsManager.cpp @@ -26,11 +26,11 @@ #include -#include "base/Director.h" -#include "base/Scheduler.h" -#include "base/UserDefault.h" -#include "network/Downloader.h" -#include "platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/UserDefault.h" +#include "axmol/network/Downloader.h" +#include "axmol/platform/FileUtils.h" #ifdef MINIZIP_FROM_SYSTEM # include @@ -39,7 +39,7 @@ #endif #include -#include "base/format.h" +#include "axmol/base/format.h" NS_AX_EXT_BEGIN diff --git a/extensions/assets-manager/src/assets-manager/AssetsManager.h b/extensions/assets-manager/src/assets-manager/AssetsManager.h index a2f3f869c6aa..47f89c65aca6 100644 --- a/extensions/assets-manager/src/assets-manager/AssetsManager.h +++ b/extensions/assets-manager/src/assets-manager/AssetsManager.h @@ -29,7 +29,7 @@ #include -#include "2d/Node.h" +#include "axmol/2d/Node.h" #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" diff --git a/extensions/assets-manager/src/assets-manager/AssetsManagerEx.cpp b/extensions/assets-manager/src/assets-manager/AssetsManagerEx.cpp index 62504641a13e..0f180fbc5939 100644 --- a/extensions/assets-manager/src/assets-manager/AssetsManagerEx.cpp +++ b/extensions/assets-manager/src/assets-manager/AssetsManagerEx.cpp @@ -24,8 +24,8 @@ ****************************************************************************/ #include "AssetsManagerEx.h" #include "EventListenerAssetsManagerEx.h" -#include "base/UTF8.h" -#include "base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/base/Director.h" #include diff --git a/extensions/assets-manager/src/assets-manager/AssetsManagerEx.h b/extensions/assets-manager/src/assets-manager/AssetsManagerEx.h index 8408245a9230..a900e28cdfdb 100644 --- a/extensions/assets-manager/src/assets-manager/AssetsManagerEx.h +++ b/extensions/assets-manager/src/assets-manager/AssetsManagerEx.h @@ -29,9 +29,9 @@ #include #include -#include "base/EventDispatcher.h" -#include "platform/FileUtils.h" -#include "network/Downloader.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/network/Downloader.h" #include "EventAssetsManagerEx.h" diff --git a/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.cpp b/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.cpp index 44e3f679c1fb..088cb9199fb3 100644 --- a/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.cpp +++ b/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include "EventAssetsManagerEx.h" -#include "base/Macros.h" +#include "axmol/base/Macros.h" #include #include "AssetsManagerEx.h" diff --git a/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.h b/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.h index fcb64f615743..43b6885860d3 100644 --- a/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.h +++ b/extensions/assets-manager/src/assets-manager/EventAssetsManagerEx.h @@ -25,8 +25,8 @@ #pragma once -#include "base/Event.h" -#include "base/EventCustom.h" +#include "axmol/base/Event.h" +#include "axmol/base/EventCustom.h" #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" diff --git a/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.cpp b/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.cpp index b1631c349b95..36c76f4a80ff 100644 --- a/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.cpp +++ b/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.cpp @@ -26,7 +26,7 @@ #include "EventListenerAssetsManagerEx.h" #include "EventAssetsManagerEx.h" #include "AssetsManagerEx.h" -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" NS_AX_EXT_BEGIN diff --git a/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.h b/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.h index 40b3c9c9619d..dce76dc2e2dc 100644 --- a/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.h +++ b/extensions/assets-manager/src/assets-manager/EventListenerAssetsManagerEx.h @@ -25,8 +25,8 @@ #pragma once -#include "base/EventListener.h" -#include "base/EventListenerCustom.h" +#include "axmol/base/EventListener.h" +#include "axmol/base/EventListenerCustom.h" #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" @@ -62,8 +62,8 @@ class AX_EX_DLL EventListenerAssetsManagerEx : public ax::EventListenerCustom const std::function& callback); /// Overrides - virtual bool checkAvailable() override; - virtual EventListenerAssetsManagerEx* clone() override; + bool checkAvailable() override; + EventListenerAssetsManagerEx* clone() override; /** Constructor */ EventListenerAssetsManagerEx(); diff --git a/extensions/assets-manager/src/assets-manager/Manifest.h b/extensions/assets-manager/src/assets-manager/Manifest.h index e6cf72f1055f..f037e83d3141 100644 --- a/extensions/assets-manager/src/assets-manager/Manifest.h +++ b/extensions/assets-manager/src/assets-manager/Manifest.h @@ -31,8 +31,8 @@ #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" -#include "network/Downloader.h" -#include "platform/FileUtils.h" +#include "axmol/network/Downloader.h" +#include "axmol/platform/FileUtils.h" #include "rapidjson/rapidjson.h" #include "rapidjson/document.h" diff --git a/extensions/axmol-ext.h b/extensions/axmol-ext.h index 63c05071f2c3..415e8dff56b6 100644 --- a/extensions/axmol-ext.h +++ b/extensions/axmol-ext.h @@ -31,11 +31,7 @@ // Physics integration #include "physics-nodes/src/physics-nodes/PhysicsDebugNode.h" -#include "physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.h" -#include "physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.h" #include "physics-nodes/src/physics-nodes/PhysicsSprite.h" -#include "physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.h" -#include "physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.h" #include "assets-manager/src/assets-manager/AssetsManager.h" #include "assets-manager/src/assets-manager/AssetsManagerEx.h" diff --git a/extensions/cocostudio/src/cocostudio/ActionFrame.cpp b/extensions/cocostudio/src/cocostudio/ActionFrame.cpp index 0df00ecae7e8..f5377c277c90 100644 --- a/extensions/cocostudio/src/cocostudio/ActionFrame.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionFrame.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #include "ActionFrame.h" -#include "2d/ActionEase.h" +#include "axmol/2d/ActionEase.h" using namespace ax; @@ -319,26 +319,26 @@ ActionInterval* ActionFadeFrame::getAction(float fDuration) return this->getEasingAction(FadeTo::create(fDuration, _opacity)); } -ActionTintFrame::ActionTintFrame() : _color(Color3B(255, 255, 255)) +ActionTintFrame::ActionTintFrame() : _color(Color32::WHITE) { _frameType = (int)kKeyframeTint; } ActionTintFrame::~ActionTintFrame() {} -void ActionTintFrame::setColor(Color3B ccolor) +void ActionTintFrame::setColor(const Color32& ccolor) { _color = ccolor; } -Color3B ActionTintFrame::getColor() +const Color32& ActionTintFrame::getColor() const { return _color; } ActionInterval* ActionTintFrame::getAction(float fDuration) { - return this->getEasingAction(TintTo::create(fDuration, _color.r, _color.g, _color.b)); + return this->getEasingAction(TintTo::create(fDuration, _color)); } } // namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/ActionFrame.h b/extensions/cocostudio/src/cocostudio/ActionFrame.h index 2bac9c916acf..7deb9fd7b40f 100644 --- a/extensions/cocostudio/src/cocostudio/ActionFrame.h +++ b/extensions/cocostudio/src/cocostudio/ActionFrame.h @@ -24,8 +24,8 @@ THE SOFTWARE. #pragma once -#include "math/Math.h" -#include "2d/ActionInterval.h" +#include "axmol/math/Math.h" +#include "axmol/2d/ActionInterval.h" #include "CocosStudioExport.h" namespace cocostudio @@ -423,14 +423,14 @@ class CCS_DLL ActionTintFrame : public ActionFrame * * @param ccolor the tint action color */ - void setColor(ax::Color3B ccolor); + void setColor(const ax::Color32& ccolor); /** * Gets the tint action color. * * @return the tint action color. */ - ax::Color3B getColor(); + const ax::Color32& getColor() const; /** * Gets the ActionInterval of ActionFrame. @@ -442,7 +442,7 @@ class CCS_DLL ActionTintFrame : public ActionFrame virtual ax::ActionInterval* getAction(float duration); protected: - ax::Color3B _color; + ax::Color32 _color; }; } // namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/ActionFrameEasing.cpp b/extensions/cocostudio/src/cocostudio/ActionFrameEasing.cpp index b474330faac5..1f0f7b0a1372 100644 --- a/extensions/cocostudio/src/cocostudio/ActionFrameEasing.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionFrameEasing.cpp @@ -25,7 +25,7 @@ THE SOFTWARE. #include #include "ActionFrameEasing.h" #include "DictionaryHelper.h" -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" namespace cocostudio { diff --git a/extensions/cocostudio/src/cocostudio/ActionFrameEasing.h b/extensions/cocostudio/src/cocostudio/ActionFrameEasing.h index 8d43fd6d1336..4c3fce7d7917 100644 --- a/extensions/cocostudio/src/cocostudio/ActionFrameEasing.h +++ b/extensions/cocostudio/src/cocostudio/ActionFrameEasing.h @@ -24,7 +24,7 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "CocosStudioExport.h" namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/ActionNode.cpp b/extensions/cocostudio/src/cocostudio/ActionNode.cpp index 865cba998bab..c80684d80abf 100644 --- a/extensions/cocostudio/src/cocostudio/ActionNode.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionNode.cpp @@ -24,11 +24,11 @@ THE SOFTWARE. #include "ActionNode.h" #include "ActionFrameEasing.h" -#include "ui/UIWidget.h" -#include "ui/UIHelper.h" -#include "ui/UILayout.h" +#include "axmol/ui/UIWidget.h" +#include "axmol/ui/UIHelper.h" +#include "axmol/ui/UILayout.h" #include "CocoLoader.h" -#include "base/Utils.h" +#include "axmol/base/Utils.h" #include "ActionManagerEx.h" using namespace ax; @@ -179,7 +179,7 @@ void ActionNode::initWithDictionary(const rapidjson::Value& dic, Object* root) actionFrame->setFrameIndex(frameInex); actionFrame->setEasingType(frameTweenType); actionFrame->setEasingParameter(frameTweenParameter); - actionFrame->setColor(Color3B(colorR, colorG, colorB)); + actionFrame->setColor(Color32(colorR, colorG, colorB)); auto cActionArray = _frameArray.at((int)kKeyframeFade); cActionArray->pushBack(actionFrame); actionFrame->release(); @@ -350,7 +350,7 @@ void ActionNode::initWithBinary(CocoLoader* cocoLoader, stExpCocoNode* cocoNode, actionFrame->setEasingType(frameTweenType); actionFrame->setEasingParameter(frameTweenParameter); actionFrame->setFrameIndex(frameIndex); - actionFrame->setColor(Color3B(colorR, colorG, colorB)); + actionFrame->setColor(Color32(colorR, colorG, colorB)); auto cActionArray = _frameArray.at((int)kKeyframeTint); cActionArray->pushBack(actionFrame); } diff --git a/extensions/cocostudio/src/cocostudio/ActionObject.cpp b/extensions/cocostudio/src/cocostudio/ActionObject.cpp index eceb28a12cfd..294b65a11d51 100644 --- a/extensions/cocostudio/src/cocostudio/ActionObject.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionObject.cpp @@ -25,10 +25,10 @@ THE SOFTWARE. #include "ActionObject.h" #include "CocoLoader.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include "2d/ActionInstant.h" -#include "base/Utils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/2d/ActionInstant.h" +#include "axmol/base/Utils.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/ActionObject.h b/extensions/cocostudio/src/cocostudio/ActionObject.h index 294c6ac66579..fea17d39a0e0 100644 --- a/extensions/cocostudio/src/cocostudio/ActionObject.h +++ b/extensions/cocostudio/src/cocostudio/ActionObject.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once #include "ActionNode.h" -#include "2d/ActionInstant.h" +#include "axmol/2d/ActionInstant.h" #include "DictionaryHelper.h" #include "CocosStudioExport.h" diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimeline.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimeline.h index f9f0c2378db7..a856aae449ac 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimeline.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimeline.h @@ -26,9 +26,9 @@ THE SOFTWARE. #include "TimeLine.h" #include "ActionTimelineData.h" -#include "base/Protocols.h" +#include "axmol/base/Protocols.h" #include "cocostudio/CocosStudioExport.h" -#include "2d/Action.h" +#include "axmol/2d/Action.h" NS_TIMELINE_BEGIN @@ -181,21 +181,21 @@ class CCS_DLL ActionTimeline : public ax::Action, public ax::PlayableProtocol /** Inherit from Action. */ /** Returns a clone of ActionTimeline */ - virtual ActionTimeline* clone() const override; + ActionTimeline* clone() const override; /** Returns a reverse of ActionTimeline. * Not implement yet. */ - virtual ActionTimeline* reverse() const override { return nullptr; } + ActionTimeline* reverse() const override { return nullptr; } - virtual void step(float delta) override; - virtual void startWithTarget(ax::Node* target) override; - virtual bool isDone() const override { return false; } + void step(float delta) override; + void startWithTarget(ax::Node* target) override; + bool isDone() const override { return false; } /// @{ /// @name implement Playable Protocol - virtual void start() override; - virtual void stop() override; + void start() override; + void stop() override; /// @} end of PlayableProtocol protected: diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.cpp b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.cpp index f6d6fc056e95..4e61728ed869 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.cpp @@ -30,10 +30,10 @@ THE SOFTWARE. #include "Frame.h" #include "TimeLine.h" #include "ActionTimeline.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" -#include "2d/SpriteFrame.h" -#include "base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/base/Utils.h" #include "cocostudio/CSParseBinary_generated.h" @@ -360,7 +360,7 @@ Frame* ActionTimelineCache::loadColorFrame(const rapidjson::Value& json) uint8_t green = (uint8_t)DICTOOL->getIntValue_json(json, GREEN); uint8_t blue = (uint8_t)DICTOOL->getIntValue_json(json, BLUE); - frame->setColor(Color3B(red, green, blue)); + frame->setColor(Color32(red, green, blue)); return frame; } @@ -703,8 +703,7 @@ Frame* ActionTimelineCache::loadColorFrameWithFlatBuffers(const flatbuffers::Col ColorFrame* frame = ColorFrame::create(); auto f_color = flatbuffers->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); - frame->setColor(color); + frame->setColor(Color32(f_color->r(), f_color->g(), f_color->b(), f_color->a())); int frameIndex = flatbuffers->frameIndex(); frame->setFrameIndex(frameIndex); @@ -900,8 +899,8 @@ Frame* ActionTimelineCache::loadBlendFrameWithFlatBuffers(const flatbuffers::Ble { BlendFuncFrame* frame = BlendFuncFrame::create(); ax::BlendFunc blend; - blend.src = backend::BlendFactor::ONE; - blend.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blend.src = rhi::BlendFactor::ONE; + blend.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; if (nullptr != flatbuffers->blendFunc()) { blend.src = utils::toBackendBlendFactor(flatbuffers->blendFunc()->src()); diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.h index a74f5db07575..dac8e76222c9 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineCache.h @@ -25,8 +25,8 @@ THE SOFTWARE. #pragma once #include -#include "base/Map.h" -#include "base/Data.h" +#include "axmol/base/Map.h" +#include "axmol/base/Data.h" #include "cocostudio/DictionaryHelper.h" #include "TimelineMacro.h" diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineData.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineData.h index 26ec453350e1..1587cf1f67e1 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineData.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/ActionTimelineData.h @@ -1,7 +1,7 @@ #pragma once #include "cocostudio/ComBase.h" -#include "2d/Component.h" +#include "axmol/2d/Component.h" #include "cocostudio/CocosStudioExport.h" #include "TimelineMacro.h" diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.cpp b/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.cpp index 65160e2aca20..4363c293345b 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.cpp @@ -22,11 +22,11 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "base/Director.h" -#include "base/Utils.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/ProgramState.h" #include "BoneNode.h" #include "SkeletonNode.h" @@ -69,10 +69,9 @@ bool BoneNode::init() updateVertices(); updateColor(); - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - auto* program = - ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? - setProgramState(new ax::backend::ProgramState(program), true); + auto& pipelineDescriptor = _customCommand.getPipelineDesc(); + auto* program = axpm->getBuiltinProgram(ax::rhi::ProgramType::POSITION_COLOR); // TODO: noMVP? + setProgramState(new ax::rhi::ProgramState(program), true); pipelineDescriptor.programState = _programState; _mvpLocation = _programState->getUniformLocation("u_MVPMatrix"sv); @@ -334,7 +333,7 @@ void BoneNode::setDebugDrawEnabled(bool isDebugDraw) _isRackShow = isDebugDraw; } -void BoneNode::setDebugDrawColor(const ax::Color4F& color) +void BoneNode::setDebugDrawColor(const ax::Color& color) { _rackColor = color; updateColor(); @@ -458,7 +457,7 @@ void BoneNode::updateColor() _transformUpdated = _transformDirty = _inverseDirty = _contentSizeDirty = true; } -void BoneNode::updateDisplayedColor(const ax::Color3B& /*parentColor*/) +void BoneNode::updateDisplayedColor(const ax::Color32& /*parentColor*/) { if (_cascadeColorEnabled) { @@ -475,7 +474,7 @@ void BoneNode::updateDisplayedOpacity(uint8_t /*parentOpacity*/) { for (const auto& child : _boneSkins) { - child->updateDisplayedOpacity(_displayedOpacity); + child->updateDisplayedOpacity(_displayedColor.a); } } } @@ -492,7 +491,7 @@ void BoneNode::disableCascadeColor() { for (const auto& child : _boneSkins) { - child->updateDisplayedColor(ax::Color3B::WHITE); + child->updateDisplayedColor(ax::Color32::WHITE); } } diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.h index 8c934bb0a966..124a325cace2 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/BoneNode.h @@ -24,16 +24,16 @@ THE SOFTWARE. #pragma once -#include "base/Protocols.h" -#include "2d/Node.h" -#include "renderer/CustomCommand.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Node.h" +#include "axmol/renderer/CustomCommand.h" #include "TimelineMacro.h" #include "cocostudio/CocosStudioExport.h" #include "SkinNode.h" namespace ax { -namespace backend +namespace rhi { class ProgramState; } @@ -51,11 +51,11 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol using Node::addChild; // add child, and add child to bone list and skeleton's sub bone map or add it to skin list - virtual void addChild(ax::Node* child, int localZOrder, std::string_view name) override; - virtual void addChild(ax::Node* child, int localZOrder, int tag) override; + void addChild(ax::Node* child, int localZOrder, std::string_view name) override; + void addChild(ax::Node* child, int localZOrder, int tag) override; // remove child, and remove child from bone list and skeleton's sub bone map or remove it from skin list - virtual void removeChild(Node* child, bool cleanup) override; + void removeChild(Node* child, bool cleanup) override; // get child bone list virtual const ax::Vector& getChildBones() const { return _childBones; } @@ -110,8 +110,8 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol ax::Vector getAllSubSkins() const; // blendFunc - virtual void setBlendFunc(const ax::BlendFunc& blendFunc) override; - virtual const ax::BlendFunc& getBlendFunc() const override { return _blendFunc; } + void setBlendFunc(const ax::BlendFunc& blendFunc) override; + const ax::BlendFunc& getBlendFunc() const override { return _blendFunc; } // debug draw show, bone's debugdraw can be draw when bone is visible // when bone's added to skeleton, DebugDrawEnabled controlled by skeleton's DebugDrawEnabled @@ -127,8 +127,8 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol virtual float getDebugDrawWidth() const { return _rackWidth; } // bone's debug draw's width - virtual void setDebugDrawColor(const ax::Color4F& color); - virtual ax::Color4F getDebugDrawColor() const { return _rackColor; } + virtual void setDebugDrawColor(const ax::Color& color); + virtual ax::Color getDebugDrawColor() const { return _rackColor; } // get bone's bounding box, depends on getVisibleSkinsRect, apply on node to parent's transform ax::Rect getBoundingBox() const override; @@ -139,22 +139,22 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol virtual ax::Rect getVisibleSkinsRect() const; // transform & draw - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; // set local zorder, and dirty the debugdraw to make debugdraw's render layer right - virtual void setLocalZOrder(int localZOrder) override; + void setLocalZOrder(int localZOrder) override; // set name, and replace the subbone map in skeleton - virtual void setName(std::string_view name) override; + void setName(std::string_view name) override; // set visible, and dirty the debugdraw to make debugdraw's render layer right - virtual void setVisible(bool visible) override; + void setVisible(bool visible) override; // set contentsize, and recalculate debugdraw - virtual void setContentSize(const ax::Size& contentSize) override; + void setContentSize(const ax::Size& contentSize) override; // set localzorder, and recalculate debugdraw - virtual void setAnchorPoint(const ax::Vec2& anchorPoint) override; + void setAnchorPoint(const ax::Vec2& anchorPoint) override; #ifdef AX_STUDIO_ENABLED_VIEW // hit test , bonePoint is in self coordinate @@ -163,7 +163,7 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol BoneNode() = default; virtual ~BoneNode(); - virtual bool init() override; + bool init() override; protected: virtual void addToChildrenListHelper(Node* child); @@ -182,19 +182,19 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol virtual void removeFromSkinList(SkinNode* skin); // sort all _children , bone list and skin list - virtual void sortAllChildren() override; + void sortAllChildren() override; virtual void updateVertices(); - virtual void updateColor() override; + void updateColor() override; // bone's color and opacity cannot cascade to bone - virtual void updateDisplayedColor(const ax::Color3B& parentColor) override; - virtual void updateDisplayedOpacity(uint8_t parentOpacity) override; - virtual void disableCascadeOpacity() override; - virtual void disableCascadeColor() override; + void updateDisplayedColor(const ax::Color32& parentColor) override; + void updateDisplayedOpacity(uint8_t parentOpacity) override; + void disableCascadeOpacity() override; + void disableCascadeColor() override; // override Node::visit, just visit bones in children - virtual void visit(ax::Renderer* renderer, + void visit(ax::Renderer* renderer, const ax::Mat4& parentTransform, uint32_t parentFlags) override; @@ -212,12 +212,12 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol protected: ax::CustomCommand _customCommand; - ax::backend::UniformLocation _mvpLocation; + ax::rhi::UniformLocation _mvpLocation; ax::BlendFunc _blendFunc = ax::BlendFunc::ALPHA_NON_PREMULTIPLIED; bool _isRackShow = false; - ax::Color4F _rackColor = ax::Color4F::WHITE; + ax::Color _rackColor = ax::Color::WHITE; float _rackLength = 50.0f; float _rackWidth = 20.0f; @@ -228,7 +228,7 @@ class CCS_DLL BoneNode : public ax::Node, public ax::BlendProtocol private: struct VertexData { - ax::Color4F squareColor; + ax::Color squareColor; ax::Vec3 noMVPVertices; }; diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.cpp b/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.cpp index 3cee45c8e9f1..5c0e48f185a4 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.cpp @@ -27,14 +27,14 @@ #include "CSLoader.h" -#include "base/ObjectFactory.h" -#include "base/Director.h" -#include "base/UTF8.h" -#include "ui/CocosGUI.h" -#include "2d/SpriteFrameCache.h" -#include "2d/ParticleSystemQuad.h" -#include "2d/FastTMXTiledMap.h" -#include "platform/FileUtils.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/base/Director.h" +#include "axmol/base/text_utils.h" +#include "axmol/ui/CocosGUI.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/2d/ParticleSystemQuad.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/platform/FileUtils.h" #include "ActionTimelineCache.h" #include "ActionTimeline.h" @@ -627,13 +627,9 @@ void CSLoader::initNode(Node* node, const rapidjson::Value& json) if (visible != true) node->setVisible(visible); - if (alpha != 255) + if (red != 255 || green != 255 || blue != 255 || alpha != 255) { - node->setOpacity(alpha); - } - if (red != 255 || green != 255 || blue != 255) - { - node->setColor(Color3B(red, green, blue)); + node->setColor(Color32(red, green, blue, alpha)); } node->setTag(tag); diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.h index 095ee9872059..2b7c6353af03 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/CSLoader.h @@ -27,9 +27,9 @@ #include "cocostudio/DictionaryHelper.h" #include "cocostudio/CocosStudioExport.h" -#include "base/ObjectFactory.h" -#include "base/Data.h" -#include "ui/UIWidget.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/base/Data.h" +#include "axmol/ui/UIWidget.h" #include "flatbuffers/flatbuffers.h" diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.cpp b/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.cpp index 8e5fe31bef6d..bf1bdb347bfb 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.cpp @@ -1,5 +1,6 @@ /**************************************************************************** Copyright (c) 2013 cocos2d-x.org +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,8 +26,8 @@ THE SOFTWARE. #include "Frame.h" #include "TimeLine.h" #include "ActionTimeline.h" -#include "2d/SpriteFrameCache.h" -#include "2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/2d/SpriteFrame.h" #include #include @@ -587,7 +588,7 @@ ColorFrame* ColorFrame::create() return frame; } -ColorFrame::ColorFrame() : _color(Color3B(255, 255, 255)) {} +ColorFrame::ColorFrame() : _color(Color32::WHITE), _betweenRed(0), _betweenGreen(0), _betweenBlue(0) {} void ColorFrame::onEnter(Frame* nextFrame, int /*currentFrameIndex*/) { @@ -599,7 +600,7 @@ void ColorFrame::onEnter(Frame* nextFrame, int /*currentFrameIndex*/) if (_tween) { - const Color3B& color = static_cast(nextFrame)->_color; + auto& color = static_cast(nextFrame)->_color; _betweenRed = color.r - _color.r; _betweenGreen = color.g - _color.g; _betweenBlue = color.b - _color.b; @@ -610,10 +611,11 @@ void ColorFrame::onApply(float percent) { if ((nullptr != _node) && (_betweenRed != 0 || _betweenGreen != 0 || _betweenBlue != 0)) { - Color3B color; + Color32 color; color.r = _color.r + _betweenRed * percent; color.g = _color.g + _betweenGreen * percent; color.b = _color.b + _betweenBlue * percent; + color.a = _node->getOpacity(); // Keep alpha unchanged _node->setColor(color); } diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.h index c8d1bf6a4f8c..0acfa4c0b000 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/Frame.h @@ -1,5 +1,6 @@ /**************************************************************************** Copyright (c) 2013 cocos2d-x.org +Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -25,11 +26,11 @@ THE SOFTWARE. #pragma once #include -#include "base/Object.h" -#include "base/Vector.h" -#include "2d/Node.h" -#include "2d/Sprite.h" -#include "2d/TweenFunction.h" +#include "axmol/base/Object.h" +#include "axmol/base/Vector.h" +#include "axmol/2d/Node.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/TweenFunction.h" #include "TimelineMacro.h" #include "cocostudio/CocosStudioExport.h" @@ -96,8 +97,8 @@ class CCS_DLL VisibleFrame : public Frame VisibleFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setVisible(bool visible) { _visible = visible; } inline bool isVisible() const { return _visible; } @@ -113,10 +114,10 @@ class CCS_DLL TextureFrame : public Frame TextureFrame(); - virtual void setNode(ax::Node* node) override; + void setNode(ax::Node* node) override; - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setTextureName(std::string_view textureName) { _textureName = textureName; } inline std::string_view getTextureName() const { return _textureName; } @@ -133,14 +134,14 @@ class CCS_DLL RotationFrame : public Frame RotationFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setRotation(float rotation) { _rotation = rotation; } inline float getRotation() const { return _rotation; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; float _rotation; float _betwennRotation; @@ -153,8 +154,8 @@ class CCS_DLL SkewFrame : public Frame SkewFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setSkewX(float skewx) { _skewX = skewx; } inline float getSkewX() const { return _skewX; } @@ -163,7 +164,7 @@ class CCS_DLL SkewFrame : public Frame inline float getSkewY() const { return _skewY; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; float _skewX; float _skewY; @@ -178,11 +179,11 @@ class CCS_DLL RotationSkewFrame : public SkewFrame RotationSkewFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; }; class CCS_DLL PositionFrame : public Frame @@ -192,8 +193,8 @@ class CCS_DLL PositionFrame : public Frame PositionFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setPosition(const ax::Point& position) { _position = position; } inline ax::Point getPosition() const { return _position; } @@ -205,7 +206,7 @@ class CCS_DLL PositionFrame : public Frame inline float getY() const { return _position.y; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; ax::Point _position; float _betweenX; @@ -219,8 +220,8 @@ class CCS_DLL ScaleFrame : public Frame ScaleFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setScale(float scale) { @@ -235,7 +236,7 @@ class CCS_DLL ScaleFrame : public Frame inline float getScaleY() const { return _scaleY; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; float _scaleX; float _scaleY; @@ -250,14 +251,14 @@ class CCS_DLL AnchorPointFrame : public Frame AnchorPointFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setAnchorPoint(const ax::Point& point) { _anchorPoint = point; } inline ax::Point getAnchorPoint() const { return _anchorPoint; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; ax::Vec2 _betweenAnchorPoint; ax::Vec2 _anchorPoint; @@ -278,8 +279,8 @@ class CCS_DLL InnerActionFrame : public Frame static InnerActionFrame* create(); InnerActionFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setInnerActionType(InnerActionType type) { _innerActionType = type; } inline InnerActionType getInnerActionType() const { return _innerActionType; } @@ -312,17 +313,16 @@ class CCS_DLL ColorFrame : public Frame static ColorFrame* create(); ColorFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; - inline void setColor(const ax::Color3B& color) { _color = color; } - inline ax::Color3B getColor() const { return _color; } + inline void setColor(const ax::Color32& color) { _color = color; } + inline const ax::Color32& getColor() const { return _color; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; - uint8_t _alpha; - ax::Color3B _color; + ax::Color32 _color; int _betweenRed; int _betweenGreen; @@ -335,14 +335,14 @@ class CCS_DLL AlphaFrame : public Frame static AlphaFrame* create(); AlphaFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setAlpha(uint8_t alpha) { _alpha = alpha; } inline uint8_t getAlpha() const { return _alpha; } protected: - virtual void onApply(float percent) override; + void onApply(float percent) override; uint8_t _alpha; int _betweenAlpha; @@ -356,10 +356,10 @@ class CCS_DLL EventFrame : public Frame EventFrame(); - virtual void setNode(ax::Node* node) override; + void setNode(ax::Node* node) override; - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setEvent(std::string_view event) { _event = event; } inline std::string_view getEvent() const { return _event; } @@ -376,8 +376,8 @@ class CCS_DLL ZOrderFrame : public Frame ZOrderFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline void setZOrder(int zorder) { _zorder = zorder; } inline int getZOrder() const { return _zorder; } @@ -393,8 +393,8 @@ class CCS_DLL BlendFuncFrame : public Frame BlendFuncFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameIndex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameIndex) override; + Frame* clone() override; inline ax::BlendFunc getBlendFunc() const { return _blendFunc; } inline void setBlendFunc(ax::BlendFunc blendFunc) { _blendFunc = blendFunc; } @@ -410,8 +410,8 @@ class CCS_DLL PlayableFrame : public Frame PlayableFrame(); - virtual void onEnter(Frame* nextFrame, int currentFrameINdex) override; - virtual Frame* clone() override; + void onEnter(Frame* nextFrame, int currentFrameINdex) override; + Frame* clone() override; inline std::string getPlayableAct() const { return _playableAct; } // @param playact, express the interface in PlayableProtocol, should be "start" or "stop" diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.cpp b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.cpp index bbaf2b02673a..1fafb8443912 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.cpp +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.cpp @@ -23,11 +23,11 @@ THE SOFTWARE. ****************************************************************************/ #include "SkeletonNode.h" -#include "base/Director.h" -#include "math/TransformUtils.h" -#include "renderer/Renderer.h" -#include "renderer/Shaders.h" -#include "base/Utils.h" +#include "axmol/base/Director.h" +#include "axmol/math/TransformUtils.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/base/Utils.h" #include NS_TIMELINE_BEGIN @@ -50,10 +50,9 @@ bool SkeletonNode::init() updateVertices(); // init _customCommand - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); - auto* program = - ax::backend::Program::getBuiltinProgram(ax::backend::ProgramType::POSITION_COLOR); // TODO: noMVP? - setProgramState(new ax::backend::ProgramState(program), true); + auto& pipelineDescriptor = _customCommand.getPipelineDesc(); + auto* program = axpm->getBuiltinProgram(ax::rhi::ProgramType::POSITION_COLOR); // TODO: noMVP? + setProgramState(new ax::rhi::ProgramState(program), true); pipelineDescriptor.programState = _programState; _mvpLocation = _programState->getUniformLocation("u_MVPMatrix"); @@ -65,7 +64,7 @@ bool SkeletonNode::init() _customCommand.updateIndexBuffer(indices, sizeof(indices)); // init _batchBoneCommand - _batchBoneCommand.getPipelineDescriptor().programState = _programState; + _batchBoneCommand.getPipelineDesc().programState = _programState; _rootSkeleton = this; return true; diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.h index f03a16853493..13e030811e4c 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkeletonNode.h @@ -25,9 +25,9 @@ THE SOFTWARE. #pragma once #include "TimelineMacro.h" -#include "renderer/Renderer.h" +#include "axmol/renderer/Renderer.h" #include "cocostudio/CocosStudioExport.h" -#include "base/Map.h" +#include "axmol/base/Map.h" #include "BoneNode.h" @@ -73,16 +73,16 @@ class CCS_DLL SkeletonNode : public BoneNode SkeletonNode(); virtual ~SkeletonNode(); - virtual bool init() override; + bool init() override; protected: - virtual void updateVertices() override; - virtual void updateColor() override; + void updateVertices() override; + void updateColor() override; virtual void visit(ax::Renderer* renderer, const ax::Mat4& parentTransform, uint32_t parentFlags) override; - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; protected: ax::StringMap _subBonesMap; @@ -91,7 +91,7 @@ class CCS_DLL SkeletonNode : public BoneNode struct VertexData { ax::Vec3 vertex; - ax::Color4F color; + ax::Color color; }; ax::Vec2 _squareVertices[8]; diff --git a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkinNode.h b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkinNode.h index 46d71c3ff599..50d60ccd76f3 100644 --- a/extensions/cocostudio/src/cocostudio/ActionTimeline/SkinNode.h +++ b/extensions/cocostudio/src/cocostudio/ActionTimeline/SkinNode.h @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" +#include "axmol/2d/Node.h" #include "TimelineMacro.h" NS_TIMELINE_BEGIN diff --git a/extensions/cocostudio/src/cocostudio/Armature.cpp b/extensions/cocostudio/src/cocostudio/Armature.cpp index e3f79f4cdd74..6c975743f16b 100644 --- a/extensions/cocostudio/src/cocostudio/Armature.cpp +++ b/extensions/cocostudio/src/cocostudio/Armature.cpp @@ -30,9 +30,9 @@ THE SOFTWARE. #include "Datas.h" #include "Skin.h" -#include "renderer/Renderer.h" -#include "renderer/GroupCommand.h" -#include "base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/base/Director.h" #if ENABLE_PHYSICS_BOX2D_DETECT # include "box2d/box2d.h" diff --git a/extensions/cocostudio/src/cocostudio/Armature.h b/extensions/cocostudio/src/cocostudio/Armature.h index ee43a5e90296..81463ee63e40 100644 --- a/extensions/cocostudio/src/cocostudio/Armature.h +++ b/extensions/cocostudio/src/cocostudio/Armature.h @@ -32,7 +32,7 @@ THE SOFTWARE. #include "SpriteFrameCacheHelper.h" #include "ArmatureDataManager.h" #include "CocosStudioExport.h" -#include "math/Math.h" +#include "axmol/math/Math.h" class b2Body; struct cpBody; @@ -71,7 +71,7 @@ class CCS_DLL Armature : public ax::Node, public ax::BlendProtocol /** * Init the empty armature */ - virtual bool init() override; + bool init() override; /** * Init an armature with specified name @@ -117,7 +117,7 @@ class CCS_DLL Armature : public ax::Node, public ax::BlendProtocol /** * This boundingBox will calculate all bones' boundingBox every time */ - virtual ax::Rect getBoundingBox() const override; + ax::Rect getBoundingBox() const override; Bone* getBoneAtPoint(float x, float y) const; @@ -128,13 +128,13 @@ class CCS_DLL Armature : public ax::Node, public ax::BlendProtocol virtual void visit(ax::Renderer* renderer, const ax::Mat4& parentTransform, uint32_t parentFlags) override; - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; - virtual void update(float dt) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void update(float dt) override; - virtual void onEnter() override; - virtual void onExit() override; + void onEnter() override; + void onExit() override; - virtual const ax::Mat4& getNodeToParentTransform() const override; + const ax::Mat4& getNodeToParentTransform() const override; /** * @lua NA */ @@ -148,8 +148,8 @@ class CCS_DLL Armature : public ax::Node, public ax::BlendProtocol * Set contentsize and Calculate anchor point. */ virtual void updateOffsetPoint(); - virtual void setAnchorPoint(const ax::Vec2& point) override; - virtual const ax::Vec2& getAnchorPointInPoints() const override; + void setAnchorPoint(const ax::Vec2& point) override; + const ax::Vec2& getAnchorPointInPoints() const override; virtual const ax::Vec2& getOffsetPoints() const; virtual void setAnimation(ArmatureAnimation* animation); diff --git a/extensions/cocostudio/src/cocostudio/ArmatureAnimation.h b/extensions/cocostudio/src/cocostudio/ArmatureAnimation.h index 59deeb53e9ca..9162f69d83bc 100644 --- a/extensions/cocostudio/src/cocostudio/ArmatureAnimation.h +++ b/extensions/cocostudio/src/cocostudio/ArmatureAnimation.h @@ -141,22 +141,22 @@ class CCS_DLL ArmatureAnimation : public ProcessBase /** * Pause the Process */ - virtual void pause() override; + void pause() override; /** * Resume the Process */ - virtual void resume() override; + void resume() override; /** * Stop the Process */ - virtual void stop() override; + void stop() override; /** * Get movement count */ ssize_t getMovementCount() const; - virtual void update(float dt) override; + void update(float dt) override; /** * Get current movementID diff --git a/extensions/cocostudio/src/cocostudio/ArmatureDataManager.cpp b/extensions/cocostudio/src/cocostudio/ArmatureDataManager.cpp index d9be52aa38aa..04586aeef966 100644 --- a/extensions/cocostudio/src/cocostudio/ArmatureDataManager.cpp +++ b/extensions/cocostudio/src/cocostudio/ArmatureDataManager.cpp @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/SpriteFrameCache.h" +#include "axmol/2d/SpriteFrameCache.h" #include "ArmatureDataManager.h" #include "TransformHelp.h" diff --git a/extensions/cocostudio/src/cocostudio/BatchNode.cpp b/extensions/cocostudio/src/cocostudio/BatchNode.cpp index 9148bb8acb77..69a02d0e067c 100644 --- a/extensions/cocostudio/src/cocostudio/BatchNode.cpp +++ b/extensions/cocostudio/src/cocostudio/BatchNode.cpp @@ -25,9 +25,9 @@ THE SOFTWARE. #include "Armature.h" #include "Skin.h" -#include "renderer/Renderer.h" -#include "renderer/GroupCommand.h" -#include "base/Director.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/GroupCommand.h" +#include "axmol/base/Director.h" using namespace ax; namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/BatchNode.h b/extensions/cocostudio/src/cocostudio/BatchNode.h index 1fb8042773eb..5003b0bb887e 100644 --- a/extensions/cocostudio/src/cocostudio/BatchNode.h +++ b/extensions/cocostudio/src/cocostudio/BatchNode.h @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "2d/Node.h" +#include "axmol/2d/Node.h" #include "ArmatureDefine.h" #include "CocosStudioExport.h" @@ -53,15 +53,15 @@ class CCS_DLL BatchNode : public ax::Node ~BatchNode(); /** */ - virtual bool init() override; + bool init() override; using Node::addChild; - virtual void addChild(ax::Node* pChild, int zOrder, int tag) override; - virtual void addChild(ax::Node* pChild, int zOrder, std::string_view name) override; - virtual void removeChild(ax::Node* child, bool cleanup) override; + void addChild(ax::Node* pChild, int zOrder, int tag) override; + void addChild(ax::Node* pChild, int zOrder, std::string_view name) override; + void removeChild(ax::Node* child, bool cleanup) override; virtual void visit(ax::Renderer* renderer, const ax::Mat4& parentTransform, uint32_t parentFlags) override; - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; protected: void generateGroupCommand(); diff --git a/extensions/cocostudio/src/cocostudio/Bone.cpp b/extensions/cocostudio/src/cocostudio/Bone.cpp index 4b7b858a52b2..78203ce878ec 100644 --- a/extensions/cocostudio/src/cocostudio/Bone.cpp +++ b/extensions/cocostudio/src/cocostudio/Bone.cpp @@ -247,10 +247,10 @@ void Bone::setBlendFunc(const BlendFunc& blendFunc) } } -void Bone::updateDisplayedColor(const Color3B& parentColor) +void Bone::updateDisplayedColor(const Color32& parentColor) { #ifdef AX_STUDIO_ENABLED_VIEW - _realColor = Color3B(255, 255, 255); + _realColor = Color32::WHITE; #endif // AX_STUDIO_ENABLED_VIEW Node::updateDisplayedColor(parentColor); } @@ -258,7 +258,7 @@ void Bone::updateDisplayedColor(const Color3B& parentColor) void Bone::updateDisplayedOpacity(uint8_t parentOpacity) { #ifdef AX_STUDIO_ENABLED_VIEW - _realOpacity = 255; + _realColor.a = 255; #endif // AX_STUDIO_ENABLED_VIEW Node::updateDisplayedOpacity(parentOpacity); } @@ -268,9 +268,8 @@ void Bone::updateColor() Node* display = _displayManager->getDisplayRenderNode(); if (display != nullptr) { - display->setColor(Color3B(_displayedColor.r * _tweenData->r / 255, _displayedColor.g * _tweenData->g / 255, - _displayedColor.b * _tweenData->b / 255)); - display->setOpacity(_displayedOpacity * _tweenData->a / 255); + display->setColor(Color32(_displayedColor.r * _tweenData->r / 255, _displayedColor.g * _tweenData->g / 255, + _displayedColor.b * _tweenData->b / 255, _displayedColor.a * _tweenData->a / 255)); } } diff --git a/extensions/cocostudio/src/cocostudio/Bone.h b/extensions/cocostudio/src/cocostudio/Bone.h index c95a5414b0a0..01e8249acf05 100644 --- a/extensions/cocostudio/src/cocostudio/Bone.h +++ b/extensions/cocostudio/src/cocostudio/Bone.h @@ -30,8 +30,8 @@ THE SOFTWARE. #include "DecorativeDisplay.h" #include "DisplayManager.h" #include "CocosStudioExport.h" -#include "2d/Node.h" -#include "math/Math.h" +#include "axmol/2d/Node.h" +#include "axmol/math/Math.h" namespace cocostudio { @@ -66,7 +66,7 @@ class CCS_DLL Bone : public ax::Node /** * Initializes an empty Bone with nothing init. */ - virtual bool init() override; + bool init() override; /** * Initializes a Bone with the specified name @@ -133,16 +133,16 @@ class CCS_DLL Bone : public ax::Node void update(float delta) override; - void updateDisplayedColor(const ax::Color3B& parentColor) override; + void updateDisplayedColor(const ax::Color32& parentColor) override; void updateDisplayedOpacity(uint8_t parentOpacity) override; //! Update color to render display - virtual void updateColor() override; + void updateColor() override; //! Update zorder void updateZOrder(); - virtual void setLocalZOrder(int zOrder) override; + void setLocalZOrder(int zOrder) override; Tween* getTween(); @@ -153,7 +153,7 @@ class CCS_DLL Bone : public ax::Node virtual bool isTransformDirty() { return _boneTransformDirty; } virtual ax::Mat4 getNodeToArmatureTransform() const; - virtual ax::Mat4 getNodeToWorldTransform() const override; + ax::Mat4 getNodeToWorldTransform() const override; ax::Node* getDisplayRenderNode(); DisplayType getDisplayRenderNodeType(); diff --git a/extensions/cocostudio/src/cocostudio/CocosStudioExport.h b/extensions/cocostudio/src/cocostudio/CocosStudioExport.h index 024193ea0edc..201602d6b9d0 100644 --- a/extensions/cocostudio/src/cocostudio/CocosStudioExport.h +++ b/extensions/cocostudio/src/cocostudio/CocosStudioExport.h @@ -1,7 +1,7 @@ #pragma once -#include "base/hlookup.h" -#include "platform/PlatformMacros.h" +#include "axmol/base/hlookup.h" +#include "axmol/platform/PlatformMacros.h" #if defined(_WIN32) # if defined(CCS_DLLEXPORT) diff --git a/extensions/cocostudio/src/cocostudio/CocosStudioExtension.h b/extensions/cocostudio/src/cocostudio/CocosStudioExtension.h index 3f130b62da6b..fdabb09b6afc 100644 --- a/extensions/cocostudio/src/cocostudio/CocosStudioExtension.h +++ b/extensions/cocostudio/src/cocostudio/CocosStudioExtension.h @@ -1,7 +1,7 @@ #pragma once -#include "math/AffineTransform.h" +#include "axmol/math/AffineTransform.h" #include "CocosStudioExport.h" namespace ax diff --git a/extensions/cocostudio/src/cocostudio/ComAttribute.cpp b/extensions/cocostudio/src/cocostudio/ComAttribute.cpp index 34164237ad9c..8f180620d2c0 100644 --- a/extensions/cocostudio/src/cocostudio/ComAttribute.cpp +++ b/extensions/cocostudio/src/cocostudio/ComAttribute.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #include "ComAttribute.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/ComAttribute.h b/extensions/cocostudio/src/cocostudio/ComAttribute.h index 92a7ae156942..3471eaf21057 100644 --- a/extensions/cocostudio/src/cocostudio/ComAttribute.h +++ b/extensions/cocostudio/src/cocostudio/ComAttribute.h @@ -25,8 +25,8 @@ THE SOFTWARE. #pragma once #include "ComBase.h" -#include "2d/Component.h" -#include "base/Value.h" +#include "axmol/2d/Component.h" +#include "axmol/base/Value.h" #include "CocosStudioExport.h" namespace cocostudio @@ -48,8 +48,8 @@ class CCS_DLL ComAttribute : public ax::Component const static std::string COMPONENT_NAME; static ComAttribute* create(void); - virtual bool init() override; - virtual bool serialize(void* r) override; + bool init() override; + bool serialize(void* r) override; void setInt(std::string_view key, int value); void setFloat(std::string_view key, float value); diff --git a/extensions/cocostudio/src/cocostudio/ComAudio.cpp b/extensions/cocostudio/src/cocostudio/ComAudio.cpp index ec9a66594d38..a96315e06d86 100644 --- a/extensions/cocostudio/src/cocostudio/ComAudio.cpp +++ b/extensions/cocostudio/src/cocostudio/ComAudio.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #include "ComAudio.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" namespace cocostudio { diff --git a/extensions/cocostudio/src/cocostudio/ComAudio.h b/extensions/cocostudio/src/cocostudio/ComAudio.h index 895fb497b8ff..619b5d55cb3c 100644 --- a/extensions/cocostudio/src/cocostudio/ComAudio.h +++ b/extensions/cocostudio/src/cocostudio/ComAudio.h @@ -24,8 +24,8 @@ THE SOFTWARE. #pragma once #include "ComBase.h" -#include "base/Protocols.h" -#include "2d/Component.h" +#include "axmol/base/Protocols.h" +#include "axmol/2d/Component.h" #include "CocosStudioExport.h" namespace cocostudio @@ -48,25 +48,25 @@ class CCS_DLL ComAudio : public ax::Component, public ax::PlayableProtocol public: static ComAudio* create(); - virtual bool init() override; + bool init() override; /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * @lua NA */ - virtual void onAdd() override; + void onAdd() override; /** * @lua NA */ - virtual void onRemove() override; + void onRemove() override; - virtual bool serialize(void* r) override; + bool serialize(void* r) override; public: /** @@ -107,9 +107,9 @@ class CCS_DLL ComAudio : public ax::Component, public ax::PlayableProtocol /// @{ /// @name implement Playable Protocol // play the effect sound path in _filePath - virtual void start() override; + void start() override; // stop the effect sound which started with latest start() - virtual void stop() override; + void stop() override; /// @} end of PlayableProtocol private: diff --git a/extensions/cocostudio/src/cocostudio/ComBase.h b/extensions/cocostudio/src/cocostudio/ComBase.h index a75ea494bf18..b48ab704cdb9 100644 --- a/extensions/cocostudio/src/cocostudio/ComBase.h +++ b/extensions/cocostudio/src/cocostudio/ComBase.h @@ -27,7 +27,7 @@ THE SOFTWARE. #include #include "DictionaryHelper.h" #include "CocosStudioExport.h" -#include "base/ObjectFactory.h" +#include "axmol/base/ObjectFactory.h" #include "CocoLoader.h" #define DECLARE_CLASS_COMPONENT_INFO \ diff --git a/extensions/cocostudio/src/cocostudio/ComController.cpp b/extensions/cocostudio/src/cocostudio/ComController.cpp index 3ce8c4588a78..7333c1f8c8ac 100644 --- a/extensions/cocostudio/src/cocostudio/ComController.cpp +++ b/extensions/cocostudio/src/cocostudio/ComController.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #include "ComController.h" -#include "2d/Node.h" +#include "axmol/2d/Node.h" namespace cocostudio { diff --git a/extensions/cocostudio/src/cocostudio/ComController.h b/extensions/cocostudio/src/cocostudio/ComController.h index 67c8f5a92bf6..d6de5ea84d2f 100644 --- a/extensions/cocostudio/src/cocostudio/ComController.h +++ b/extensions/cocostudio/src/cocostudio/ComController.h @@ -27,7 +27,7 @@ THE SOFTWARE. #include "ComBase.h" #include "InputDelegate.h" #include "CocosStudioExport.h" -#include "2d/Component.h" +#include "axmol/2d/Component.h" namespace cocostudio { @@ -50,28 +50,28 @@ class CCS_DLL ComController : public ax::Component, public InputDelegate */ virtual ~ComController(); - virtual bool init() override; + bool init() override; /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * @lua NA */ - virtual void onAdd() override; + void onAdd() override; /** * @lua NA */ - virtual void onRemove() override; - virtual void update(float delta) override; + void onRemove() override; + void update(float delta) override; }; } // namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/ComExtensionData.h b/extensions/cocostudio/src/cocostudio/ComExtensionData.h index 2a015a0adaee..baab28f707e8 100644 --- a/extensions/cocostudio/src/cocostudio/ComExtensionData.h +++ b/extensions/cocostudio/src/cocostudio/ComExtensionData.h @@ -26,7 +26,7 @@ #include #include "ComBase.h" -#include "2d/Component.h" +#include "axmol/2d/Component.h" #include "CocosStudioExport.h" namespace cocostudio @@ -48,21 +48,21 @@ class CCS_DLL ComExtensionData : public ax::Component /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * @lua NA */ - virtual void onAdd() override; + void onAdd() override; /** * @lua NA */ - virtual void onRemove() override; + void onRemove() override; static ComExtensionData* create(); - virtual bool init() override; + bool init() override; virtual void setCustomProperty(std::string_view customProperty) { _customProperty = customProperty; } virtual std::string getCustomProperty() const { return _customProperty; }; diff --git a/extensions/cocostudio/src/cocostudio/ComRender.cpp b/extensions/cocostudio/src/cocostudio/ComRender.cpp index 30a4be3faec1..352bb7bdc9d7 100644 --- a/extensions/cocostudio/src/cocostudio/ComRender.cpp +++ b/extensions/cocostudio/src/cocostudio/ComRender.cpp @@ -25,10 +25,10 @@ THE SOFTWARE. #include "ComRender.h" #include "CocoStudio.h" -#include "platform/FileUtils.h" -#include "2d/FastTMXTiledMap.h" -#include "2d/ParticleSystemQuad.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/2d/ParticleSystemQuad.h" +#include "axmol/2d/SpriteFrameCache.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/ComRender.h b/extensions/cocostudio/src/cocostudio/ComRender.h index 6d9d922325fc..db4a61621411 100644 --- a/extensions/cocostudio/src/cocostudio/ComRender.h +++ b/extensions/cocostudio/src/cocostudio/ComRender.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once #include "ComBase.h" -#include "2d/Component.h" +#include "axmol/2d/Component.h" #include "CocosStudioExport.h" namespace cocostudio @@ -44,20 +44,20 @@ class CCS_DLL ComRender : public ax::Component /** * @lua NA */ - virtual void onEnter() override; + void onEnter() override; /** * @lua NA */ - virtual void onExit() override; + void onExit() override; /** * @lua NA */ - virtual void onAdd() override; + void onAdd() override; /** * @lua NA */ - virtual void onRemove() override; - virtual bool serialize(void* r) override; + void onRemove() override; + bool serialize(void* r) override; virtual ax::Node* getNode(); virtual void setNode(ax::Node* node); /** diff --git a/extensions/cocostudio/src/cocostudio/DataReaderHelper.cpp b/extensions/cocostudio/src/cocostudio/DataReaderHelper.cpp index a876f5693199..60b78d394c9d 100644 --- a/extensions/cocostudio/src/cocostudio/DataReaderHelper.cpp +++ b/extensions/cocostudio/src/cocostudio/DataReaderHelper.cpp @@ -22,10 +22,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/FileUtils.h" -#include "base/Director.h" -#include "base/Scheduler.h" -#include "base/Utils.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/Utils.h" #include "pugixml/pugixml.hpp" @@ -950,20 +950,20 @@ FrameData* DataReaderHelper::decodeFrame(pugi::xml_node& frameXML, break; case BLEND_ADD: { - frameData->blendFunc.src = backend::BlendFactor::SRC_ALPHA; - frameData->blendFunc.dst = backend::BlendFactor::ONE; + frameData->blendFunc.src = rhi::BlendFactor::SRC_ALPHA; + frameData->blendFunc.dst = rhi::BlendFactor::ONE; } break; case BLEND_MULTIPLY: { - frameData->blendFunc.src = backend::BlendFactor::DST_COLOR; - frameData->blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + frameData->blendFunc.src = rhi::BlendFactor::DST_COLOR; + frameData->blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } break; case BLEND_SCREEN: { - frameData->blendFunc.src = backend::BlendFactor::ONE; - frameData->blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_COLOR; + frameData->blendFunc.src = rhi::BlendFactor::ONE; + frameData->blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_COLOR; } break; default: diff --git a/extensions/cocostudio/src/cocostudio/Datas.cpp b/extensions/cocostudio/src/cocostudio/Datas.cpp index 5a51fa5de0cf..fc411cffa436 100644 --- a/extensions/cocostudio/src/cocostudio/Datas.cpp +++ b/extensions/cocostudio/src/cocostudio/Datas.cpp @@ -123,7 +123,7 @@ void BaseData::subtract(BaseData* from, BaseData* to, bool limit) } } -void BaseData::setColor(const Color4B& color) +void BaseData::setColor(const Color32& color) { r = color.r; g = color.g; @@ -131,9 +131,9 @@ void BaseData::setColor(const Color4B& color) a = color.a; } -Color4B BaseData::getColor() +Color32 BaseData::getColor() { - return Color4B(r, g, b, a); + return Color32(r, g, b, a); } std::string DisplayData::changeDisplayToTexture(std::string_view displayName) diff --git a/extensions/cocostudio/src/cocostudio/Datas.h b/extensions/cocostudio/src/cocostudio/Datas.h index 6a9e2abf76ec..ced1154b38f5 100644 --- a/extensions/cocostudio/src/cocostudio/Datas.h +++ b/extensions/cocostudio/src/cocostudio/Datas.h @@ -24,14 +24,14 @@ THE SOFTWARE. #pragma once -#include "base/Object.h" -#include "base/Types.h" -#include "base/Vector.h" -#include "base/Map.h" -#include "math/AffineTransform.h" +#include "axmol/base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Vector.h" +#include "axmol/base/Map.h" +#include "axmol/math/AffineTransform.h" #include "ArmatureDefine.h" -#include "2d/TweenFunction.h" +#include "axmol/2d/TweenFunction.h" #include "CocosStudioExport.h" #define AX_CREATE_NO_PARAM_NO_INIT(varType) \ @@ -91,8 +91,8 @@ class CCS_DLL BaseData : public ax::Object */ virtual void subtract(BaseData* from, BaseData* to, bool limit); - virtual void setColor(const ax::Color4B& color); - virtual ax::Color4B getColor(); + virtual void setColor(const ax::Color32& color); + virtual ax::Color32 getColor(); public: float x; //! position x attribute diff --git a/extensions/cocostudio/src/cocostudio/DecorativeDisplay.cpp b/extensions/cocostudio/src/cocostudio/DecorativeDisplay.cpp index 4059ce4f6ca5..3a62426a0212 100644 --- a/extensions/cocostudio/src/cocostudio/DecorativeDisplay.cpp +++ b/extensions/cocostudio/src/cocostudio/DecorativeDisplay.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #include "DecorativeDisplay.h" -#include "2d/Node.h" +#include "axmol/2d/Node.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/DictionaryHelper.cpp b/extensions/cocostudio/src/cocostudio/DictionaryHelper.cpp index f29463921ee4..f03745d32f52 100644 --- a/extensions/cocostudio/src/cocostudio/DictionaryHelper.cpp +++ b/extensions/cocostudio/src/cocostudio/DictionaryHelper.cpp @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include "DictionaryHelper.h" namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/DisplayFactory.cpp b/extensions/cocostudio/src/cocostudio/DisplayFactory.cpp index 7cec4d12eca1..accacf35769f 100644 --- a/extensions/cocostudio/src/cocostudio/DisplayFactory.cpp +++ b/extensions/cocostudio/src/cocostudio/DisplayFactory.cpp @@ -29,7 +29,7 @@ THE SOFTWARE. #include "ArmatureDataManager.h" #include "TransformHelp.h" -#include "2d/ParticleSystemQuad.h" +#include "axmol/2d/ParticleSystemQuad.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/DisplayManager.cpp b/extensions/cocostudio/src/cocostudio/DisplayManager.cpp index ab41688ce468..ef4175634dfc 100644 --- a/extensions/cocostudio/src/cocostudio/DisplayManager.cpp +++ b/extensions/cocostudio/src/cocostudio/DisplayManager.cpp @@ -27,7 +27,7 @@ THE SOFTWARE. #include "Armature.h" #include "Skin.h" -#include "2d/ParticleSystemQuad.h" +#include "axmol/2d/ParticleSystemQuad.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.cpp b/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.cpp index 83eccf7daced..04503141b171 100644 --- a/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.cpp +++ b/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.cpp @@ -26,10 +26,10 @@ #include "FlatBuffersSerialize.h" -#include "base/ObjectFactory.h" -#include "base/Constants.h" -#include "ui/CocosGUI.h" -#include "platform/FileUtils.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/base/Constants.h" +#include "axmol/ui/CocosGUI.h" +#include "axmol/platform/FileUtils.h" #include "CSLanguageDataBinary_generated.h" #include "CSParseBinary_generated.h" @@ -853,7 +853,7 @@ Offset FlatBuffersSerialize::createColorFrame(pugi::xml { int frameIndex = 0; bool tween = true; - Color3B color; + Color32 color; auto attribute = objectData.first_attribute(); while (attribute) diff --git a/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.h b/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.h index e389a57195da..cc8a3c7e3bcc 100644 --- a/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.h +++ b/extensions/cocostudio/src/cocostudio/FlatBuffersSerialize.h @@ -29,8 +29,8 @@ #include "extensions/ExtensionMacros.h" #include "CocosStudioExport.h" -#include "platform/PlatformMacros.h" -#include "ui/UIWidget.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/ui/UIWidget.h" #include "pugixml/pugixml.hpp" diff --git a/extensions/cocostudio/src/cocostudio/InputDelegate.cpp b/extensions/cocostudio/src/cocostudio/InputDelegate.cpp index 26fb698042b6..03252d0becee 100644 --- a/extensions/cocostudio/src/cocostudio/InputDelegate.cpp +++ b/extensions/cocostudio/src/cocostudio/InputDelegate.cpp @@ -23,12 +23,12 @@ THE SOFTWARE. ****************************************************************************/ #include "InputDelegate.h" -#include "base/Director.h" -#include "platform/Device.h" -#include "base/EventListenerTouch.h" -#include "base/EventListenerAcceleration.h" -#include "base/EventListenerKeyboard.h" -#include "base/EventDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/platform/Device.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/EventDispatcher.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/InputDelegate.h b/extensions/cocostudio/src/cocostudio/InputDelegate.h index 216d76cda4cf..380b5a9174a6 100644 --- a/extensions/cocostudio/src/cocostudio/InputDelegate.h +++ b/extensions/cocostudio/src/cocostudio/InputDelegate.h @@ -24,12 +24,12 @@ THE SOFTWARE. #pragma once -#include "platform/PlatformMacros.h" -#include "base/Touch.h" -#include "base/Event.h" -#include "base/Types.h" -#include "base/EventKeyboard.h" -#include "base/EventListener.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/base/Touch.h" +#include "axmol/base/Event.h" +#include "axmol/base/Types.h" +#include "axmol/base/EventKeyboard.h" +#include "axmol/base/EventListener.h" #include "CocosStudioExport.h" namespace ax diff --git a/extensions/cocostudio/src/cocostudio/LocalizationManager.cpp b/extensions/cocostudio/src/cocostudio/LocalizationManager.cpp index bcdad3a1706d..53e5534d42bc 100644 --- a/extensions/cocostudio/src/cocostudio/LocalizationManager.cpp +++ b/extensions/cocostudio/src/cocostudio/LocalizationManager.cpp @@ -1,6 +1,6 @@ #include "LocalizationManager.h" -#include "platform/PlatformMacros.h" -#include "platform/FileUtils.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/platform/FileUtils.h" #include "CSLanguageDataBinary_generated.h" using namespace cocostudio; @@ -153,4 +153,4 @@ void LocalizationHelper::setCurrentManager(ILocalizationManager* manager, bool i bool LocalizationHelper::isBinManager() { return isCurrentBinManager; -} \ No newline at end of file +} diff --git a/extensions/cocostudio/src/cocostudio/SGUIReader.cpp b/extensions/cocostudio/src/cocostudio/SGUIReader.cpp index f162c97d1054..60a99238a0d0 100644 --- a/extensions/cocostudio/src/cocostudio/SGUIReader.cpp +++ b/extensions/cocostudio/src/cocostudio/SGUIReader.cpp @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2013-2017 Chukong Technologies Inc. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - + https://axmol.dev/ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -26,11 +26,11 @@ THE SOFTWARE. #include #include -#include "ui/CocosGUI.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" -#include "base/Director.h" -#include "base/Utils.h" +#include "axmol/ui/CocosGUI.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/base/Director.h" +#include "axmol/base/Utils.h" #include "ActionManagerEx.h" #include "WidgetReader/ButtonReader/ButtonReader.h" @@ -680,17 +680,15 @@ void WidgetPropertiesReader0250::setColorPropsForWidgetFromJsonDictionary(Widget const rapidjson::Value& options) { bool op = DICTOOL->checkObjectExist_json(options, "opacity"); - if (op) - { - widget->setOpacity(DICTOOL->getIntValue_json(options, "opacity")); - } bool cr = DICTOOL->checkObjectExist_json(options, "colorR"); bool cg = DICTOOL->checkObjectExist_json(options, "colorG"); bool cb = DICTOOL->checkObjectExist_json(options, "colorB"); + + int colorA = op ? DICTOOL->getIntValue_json(options, "opacity") : 255; int colorR = cr ? DICTOOL->getIntValue_json(options, "colorR") : 255; int colorG = cg ? DICTOOL->getIntValue_json(options, "colorG") : 255; int colorB = cb ? DICTOOL->getIntValue_json(options, "colorB") : 255; - widget->setColor(Color3B(colorR, colorG, colorB)); + widget->setColor(Color32(colorR, colorG, colorB, colorA)); this->setAnchorPointForWidget(widget, options); @@ -773,7 +771,7 @@ void WidgetPropertiesReader0250::setPropsForButtonFromJsonDictionary(Widget* wid int cri = cr ? DICTOOL->getIntValue_json(options, "textColorR") : 255; int cgi = cg ? DICTOOL->getIntValue_json(options, "textColorG") : 255; int cbi = cb ? DICTOOL->getIntValue_json(options, "textColorB") : 255; - button->setTitleColor(Color3B(cri, cgi, cbi)); + button->setTitleColor(Color32(cri, cgi, cbi, 255)); bool fs = DICTOOL->checkObjectExist_json(options, "fontSize"); if (fs) { @@ -1005,9 +1003,8 @@ void WidgetPropertiesReader0250::setPropsForLayoutFromJsonDictionary(Widget* wid int colorType = DICTOOL->getIntValue_json(options, "colorType"); panel->setBackGroundColorType(Layout::BackGroundColorType(colorType)); - panel->setBackGroundColor(Color3B(scr, scg, scb), Color3B(ecr, ecg, ecb)); - panel->setBackGroundColor(Color3B(cr, cg, cb)); - panel->setBackGroundColorOpacity(co); + panel->setBackGroundColor(Color32(scr, scg, scb, 255), Color32(ecr, ecg, ecb, 255)); + panel->setBackGroundColor(Color32(cr, cg, cb, co)); std::string tp_b = m_strFilePath; const char* imageFileName = DICTOOL->getStringValue_json(options, "backGroundImage"); diff --git a/extensions/cocostudio/src/cocostudio/SGUIReader.h b/extensions/cocostudio/src/cocostudio/SGUIReader.h index b8699aa55300..cd9f4fca8ed8 100644 --- a/extensions/cocostudio/src/cocostudio/SGUIReader.h +++ b/extensions/cocostudio/src/cocostudio/SGUIReader.h @@ -24,11 +24,11 @@ THE SOFTWARE. #pragma once -#include "ui/UILayout.h" +#include "axmol/ui/UILayout.h" #include "DictionaryHelper.h" #include "WidgetReader/WidgetReaderProtocol.h" -#include "base/ObjectFactory.h" -#include "base/Value.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/base/Value.h" #include "CocosStudioExport.h" namespace protocolbuffers @@ -151,14 +151,14 @@ class CCS_DLL WidgetPropertiesReader0250 : public WidgetPropertiesReader const char* fullPath, const char* fileName) override; - virtual ax::ui::Widget* widgetFromJsonDictionary(const rapidjson::Value& dic) override; + ax::ui::Widget* widgetFromJsonDictionary(const rapidjson::Value& dic) override; // added for binary parsing virtual ax::ui::Widget* createWidgetFromBinary(CocoLoader* cocoLoader, stExpCocoNode* pCocoNode, const char* fileName) override; - virtual ax::ui::Widget* widgetFromBinary(CocoLoader* cocoLoader, stExpCocoNode* pCocoNode) override; + ax::ui::Widget* widgetFromBinary(CocoLoader* cocoLoader, stExpCocoNode* pCocoNode) override; virtual void setPropsForAllWidgetFromBinary(WidgetReaderProtocol* reader, ax::ui::Widget* widget, @@ -205,7 +205,7 @@ class CCS_DLL WidgetPropertiesReader0300 : public WidgetPropertiesReader stExpCocoNode* pCocoNode, const char* fileName) override; - virtual ax::ui::Widget* widgetFromBinary(CocoLoader* cocoLoader, stExpCocoNode* pCocoNode) override; + ax::ui::Widget* widgetFromBinary(CocoLoader* cocoLoader, stExpCocoNode* pCocoNode) override; virtual void setPropsForAllWidgetFromBinary(WidgetReaderProtocol* reader, ax::ui::Widget* widget, @@ -217,7 +217,7 @@ class CCS_DLL WidgetPropertiesReader0300 : public WidgetPropertiesReader CocoLoader* cocoLoader, stExpCocoNode* pCocoNode); - virtual ax::ui::Widget* widgetFromJsonDictionary(const rapidjson::Value& dic) override; + ax::ui::Widget* widgetFromJsonDictionary(const rapidjson::Value& dic) override; virtual void setPropsForAllWidgetFromJsonDictionary(WidgetReaderProtocol* reader, ax::ui::Widget* widget, diff --git a/extensions/cocostudio/src/cocostudio/SSceneReader.cpp b/extensions/cocostudio/src/cocostudio/SSceneReader.cpp index 5f28b48a3562..98cf6284578b 100644 --- a/extensions/cocostudio/src/cocostudio/SSceneReader.cpp +++ b/extensions/cocostudio/src/cocostudio/SSceneReader.cpp @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ #include "CocoStudio.h" -#include "ui/CocosGUI.h" -#include "base/ObjectFactory.h" -#include "base/Utils.h" -#include "platform/FileUtils.h" +#include "axmol/ui/CocosGUI.h" +#include "axmol/base/ObjectFactory.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/FileUtils.h" using namespace ax; using namespace ui; diff --git a/extensions/cocostudio/src/cocostudio/Skin.cpp b/extensions/cocostudio/src/cocostudio/Skin.cpp index 25e481f67628..157dc7b66d44 100644 --- a/extensions/cocostudio/src/cocostudio/Skin.cpp +++ b/extensions/cocostudio/src/cocostudio/Skin.cpp @@ -23,10 +23,10 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" -#include "base/Director.h" -#include "renderer/Renderer.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Renderer.h" #include "Skin.h" #include "TransformHelp.h" @@ -145,10 +145,10 @@ void Skin::updateTransform() // If it is not visible, or one of its ancestors is not visible, then do nothing: if (!_visible) { - _quad.br.vertices.setZero(); - _quad.tl.vertices.setZero(); - _quad.tr.vertices.setZero(); - _quad.bl.vertices.setZero(); + _quad.br.position.setZero(); + _quad.tl.position.setZero(); + _quad.tr.position.setZero(); + _quad.bl.position.setZero(); } else { @@ -193,10 +193,10 @@ void Skin::updateTransform() float dx = x1 * cr - y2 * sr2 + x; float dy = x1 * sr + y2 * cr2 + y; - _quad.bl.vertices.set(RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), _positionZ); - _quad.br.vertices.set(RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), _positionZ); - _quad.tl.vertices.set(RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), _positionZ); - _quad.tr.vertices.set(RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), _positionZ); + _quad.bl.position.set(RENDER_IN_SUBPIXEL(ax), RENDER_IN_SUBPIXEL(ay), _positionZ); + _quad.br.position.set(RENDER_IN_SUBPIXEL(bx), RENDER_IN_SUBPIXEL(by), _positionZ); + _quad.tl.position.set(RENDER_IN_SUBPIXEL(dx), RENDER_IN_SUBPIXEL(dy), _positionZ); + _quad.tr.position.set(RENDER_IN_SUBPIXEL(cx), RENDER_IN_SUBPIXEL(cy), _positionZ); } // MARMALADE CHANGE: ADDED CHECK FOR nullptr, TO PERMIT SPRITES WITH NO BATCH NODE / TEXTURE ATLAS @@ -228,7 +228,7 @@ void Skin::draw(Renderer* renderer, const Mat4& /*transform*/, uint32_t flags) { auto mv = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_MODELVIEW); - auto& pipelineDescriptor = _quadCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _quadCommand.getPipelineDesc(); pipelineDescriptor.programState = getProgramState(); // TODO: implement z order diff --git a/extensions/cocostudio/src/cocostudio/Skin.h b/extensions/cocostudio/src/cocostudio/Skin.h index 6345e866307b..a068e3cee7fc 100644 --- a/extensions/cocostudio/src/cocostudio/Skin.h +++ b/extensions/cocostudio/src/cocostudio/Skin.h @@ -24,8 +24,8 @@ THE SOFTWARE. #pragma once -#include "2d/Sprite.h" -#include "renderer/QuadCommand.h" +#include "axmol/2d/Sprite.h" +#include "axmol/renderer/QuadCommand.h" #include "ArmatureDefine.h" #include "Bone.h" @@ -46,8 +46,8 @@ class CCS_DLL Skin : public ax::Sprite */ Skin(); - virtual bool initWithSpriteFrameName(std::string_view spriteFrameName) override; - virtual bool initWithFile(std::string_view filename) override; + bool initWithSpriteFrameName(std::string_view spriteFrameName) override; + bool initWithFile(std::string_view filename) override; void updateArmatureTransform(); void updateTransform() override; @@ -55,7 +55,7 @@ class CCS_DLL Skin : public ax::Sprite ax::Mat4 getNodeToWorldTransform() const override; ax::Mat4 getNodeToWorldTransformAR() const; - virtual void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) override; /** * @lua NA diff --git a/extensions/cocostudio/src/cocostudio/SpineSkeletonDataCache.h b/extensions/cocostudio/src/cocostudio/SpineSkeletonDataCache.h index 0bbf0bbfed94..5fbf40286efa 100644 --- a/extensions/cocostudio/src/cocostudio/SpineSkeletonDataCache.h +++ b/extensions/cocostudio/src/cocostudio/SpineSkeletonDataCache.h @@ -1,7 +1,7 @@ #pragma once #if defined(AX_ENABLE_EXT_SPINE) -#include +#include "axmol/cocos2d.h" #include "spine/spine.h" #include "spine/spine-cocos2dx.h" #include "CocosStudioExport.h" diff --git a/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.cpp b/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.cpp index 96734fd3bf73..2cdac04e47cc 100644 --- a/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.cpp +++ b/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.cpp @@ -23,9 +23,9 @@ THE SOFTWARE. ****************************************************************************/ #include "SpriteFrameCacheHelper.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.h b/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.h index f98e81bccc4e..6442458ffa53 100644 --- a/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.h +++ b/extensions/cocostudio/src/cocostudio/SpriteFrameCacheHelper.h @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "platform/PlatformMacros.h" +#include "axmol/platform/PlatformMacros.h" #include "ArmatureDefine.h" #include "CocosStudioExport.h" #include diff --git a/extensions/cocostudio/src/cocostudio/TransformHelp.cpp b/extensions/cocostudio/src/cocostudio/TransformHelp.cpp index c6545ae6af4f..5f9110659b2c 100644 --- a/extensions/cocostudio/src/cocostudio/TransformHelp.cpp +++ b/extensions/cocostudio/src/cocostudio/TransformHelp.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. #include "TransformHelp.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/TriggerBase.cpp b/extensions/cocostudio/src/cocostudio/TriggerBase.cpp index bdd49a2e29d3..bc6efc747ea7 100644 --- a/extensions/cocostudio/src/cocostudio/TriggerBase.cpp +++ b/extensions/cocostudio/src/cocostudio/TriggerBase.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ #include "TriggerBase.h" -#include "base/EventCustom.h" +#include "axmol/base/EventCustom.h" using namespace ax; using namespace cocostudio; diff --git a/extensions/cocostudio/src/cocostudio/TriggerBase.h b/extensions/cocostudio/src/cocostudio/TriggerBase.h index 950c4b1433df..14518de13c7a 100644 --- a/extensions/cocostudio/src/cocostudio/TriggerBase.h +++ b/extensions/cocostudio/src/cocostudio/TriggerBase.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once #include "CocoStudio.h" -#include "base/ObjectFactory.h" +#include "axmol/base/ObjectFactory.h" #include "TriggerObj.h" #include "TriggerMng.h" #include "CocosStudioExport.h" diff --git a/extensions/cocostudio/src/cocostudio/TriggerMng.cpp b/extensions/cocostudio/src/cocostudio/TriggerMng.cpp index 6d208d880e11..7df43054af64 100644 --- a/extensions/cocostudio/src/cocostudio/TriggerMng.cpp +++ b/extensions/cocostudio/src/cocostudio/TriggerMng.cpp @@ -25,10 +25,10 @@ THE SOFTWARE. #include "TriggerMng.h" #include "rapidjson/prettywriter.h" #include "rapidjson/stringbuffer.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" -#include "base/Utils.h" -#include "base/EventCustom.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/Utils.h" +#include "axmol/base/EventCustom.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/TriggerObj.cpp b/extensions/cocostudio/src/cocostudio/TriggerObj.cpp index e9aea09a5ed9..4ddaeab97ff1 100644 --- a/extensions/cocostudio/src/cocostudio/TriggerObj.cpp +++ b/extensions/cocostudio/src/cocostudio/TriggerObj.cpp @@ -22,7 +22,7 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ #include "TriggerObj.h" -#include "base/EventListenerCustom.h" +#include "axmol/base/EventListenerCustom.h" using namespace ax; diff --git a/extensions/cocostudio/src/cocostudio/TriggerObj.h b/extensions/cocostudio/src/cocostudio/TriggerObj.h index dff76b5a0d48..e72430aa3c41 100644 --- a/extensions/cocostudio/src/cocostudio/TriggerObj.h +++ b/extensions/cocostudio/src/cocostudio/TriggerObj.h @@ -25,8 +25,8 @@ THE SOFTWARE. #pragma once #include "CocoStudio.h" -#include "base/Vector.h" -#include "base/EventListenerCustom.h" +#include "axmol/base/Vector.h" +#include "axmol/base/EventListenerCustom.h" namespace cocostudio { diff --git a/extensions/cocostudio/src/cocostudio/Tween.h b/extensions/cocostudio/src/cocostudio/Tween.h index 7f2d239a74d5..aa30dcb08c15 100644 --- a/extensions/cocostudio/src/cocostudio/Tween.h +++ b/extensions/cocostudio/src/cocostudio/Tween.h @@ -25,7 +25,7 @@ THE SOFTWARE. #pragma once #include "ProcessBase.h" -#include "2d/TweenFunction.h" +#include "axmol/2d/TweenFunction.h" #include "CocosStudioExport.h" namespace cocostudio diff --git a/extensions/cocostudio/src/cocostudio/WidgetCallBackHandlerProtocol.h b/extensions/cocostudio/src/cocostudio/WidgetCallBackHandlerProtocol.h index 765ffeb46744..dd91fdb0a85b 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetCallBackHandlerProtocol.h +++ b/extensions/cocostudio/src/cocostudio/WidgetCallBackHandlerProtocol.h @@ -25,7 +25,7 @@ #pragma once #include "CocosStudioExport.h" -#include "ui/UIWidget.h" +#include "axmol/ui/UIWidget.h" namespace cocostudio { diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ArmatureNodeReader/ArmatureNodeReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ArmatureNodeReader/ArmatureNodeReader.cpp index 07033046d7e2..be32dc409036 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ArmatureNodeReader/ArmatureNodeReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ArmatureNodeReader/ArmatureNodeReader.cpp @@ -1,6 +1,6 @@ #include "cocostudio/WidgetReader/ArmatureNodeReader/ArmatureNodeReader.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include "flatbuffers/flatbuffers.h" #include "cocostudio/WidgetReader/NodeReader/NodeReader.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ButtonReader/ButtonReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ButtonReader/ButtonReader.cpp index 60bee16ff977..f22829659a17 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ButtonReader/ButtonReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ButtonReader/ButtonReader.cpp @@ -2,10 +2,10 @@ #include "ButtonReader.h" -#include "ui/UIButton.h" -#include "2d/SpriteFrameCache.h" -#include "2d/Label.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UIButton.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/2d/Label.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" @@ -146,7 +146,7 @@ void ButtonReader::setPropsFromBinary(ax::ui::Widget* widget, CocoLoader* cocoLo button->setContentSize(Size(scale9Width, scale9Height)); } - button->setTitleColor(Color3B(cri, cgi, cbi)); + button->setTitleColor(Color32(cri, cgi, cbi, button->getTitleColor().a)); } void ButtonReader::setPropsFromJsonDictionary(Widget* widget, const rapidjson::Value& options) @@ -213,7 +213,7 @@ void ButtonReader::setPropsFromJsonDictionary(Widget* widget, const rapidjson::V int cri = DICTOOL->getIntValue_json(options, P_TextColorR, 255); int cgi = DICTOOL->getIntValue_json(options, P_TextColorG, 255); int cbi = DICTOOL->getIntValue_json(options, P_TextColorB, 255); - button->setTitleColor(Color3B(cri, cgi, cbi)); + button->setTitleColor(Color32(cri, cgi, cbi, 255)); button->setTitleFontSize(DICTOOL->getIntValue_json(options, P_FontSize, 14)); @@ -237,7 +237,7 @@ Offset ButtonReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa int fontSize = 14; std::string fontName; ax::Size scale9Size; - Color4B textColor(255, 255, 255, 255); + Color32 textColor(255, 255, 255, 255); std::string normalPath; std::string normalPlistFile; @@ -256,15 +256,15 @@ Offset
ButtonReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa int fontResourceResourceType = 0; bool outlineEnabled = false; - Color4B outlineColor = Color4B::BLACK; + Color32 outlineColor = Color32::BLACK; int outlineSize = 1; bool shadowEnabled = false; - Color4B shadowColor = Color4B::BLACK; + Color32 shadowColor = Color32::BLACK; Size shadowOffset = Size(2, -2); int shadowBlurRadius = 0; bool glowEnabled = false; - Color4B glowColor = Color4B::BLACK; + Color32 glowColor = Color32::BLACK; bool boldEnabled = false, underlineEnabled = false, italicsEnabled = false, strikethroughEnabled = false; @@ -862,7 +862,7 @@ void ButtonReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta } auto textColor = options->textColor(); - Color3B titleColor(textColor->r(), textColor->g(), textColor->b()); + Color32 titleColor(textColor->r(), textColor->g(), textColor->b(), textColor->a()); button->setTitleColor(titleColor); std::string titleFontName = options->fontName()->c_str(); @@ -892,7 +892,7 @@ void ButtonReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta auto f_outlineColor = options->outlineColor(); if (f_outlineColor) { - Color4B outlineColor(f_outlineColor->r(), f_outlineColor->g(), f_outlineColor->b(), f_outlineColor->a()); + Color32 outlineColor(f_outlineColor->r(), f_outlineColor->g(), f_outlineColor->b(), f_outlineColor->a()); auto label = button->getTitleRenderer(); label->enableOutline(outlineColor, options->outlineSize()); } @@ -904,7 +904,7 @@ void ButtonReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta auto f_shadowColor = options->shadowColor(); if (f_shadowColor) { - Color4B shadowColor(f_shadowColor->r(), f_shadowColor->g(), f_shadowColor->b(), f_shadowColor->a()); + Color32 shadowColor(f_shadowColor->r(), f_shadowColor->g(), f_shadowColor->b(), f_shadowColor->a()); auto label = button->getTitleRenderer(); label->enableShadow(shadowColor, Size(options->shadowOffsetX(), options->shadowOffsetY()), options->shadowBlurRadius()); @@ -916,7 +916,7 @@ void ButtonReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta auto f_glowColor = options->glowColor(); if (f_glowColor) { - Color4B glowColor(f_glowColor->r(), f_glowColor->g(), f_glowColor->b(), f_glowColor->a()); + Color32 glowColor(f_glowColor->r(), f_glowColor->g(), f_glowColor->b(), f_glowColor->a()); auto label = button->getTitleRenderer(); label->enableGlow(glowColor); } diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/CheckBoxReader/CheckBoxReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/CheckBoxReader/CheckBoxReader.cpp index 85927b210fad..231c6e70910a 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/CheckBoxReader/CheckBoxReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/CheckBoxReader/CheckBoxReader.cpp @@ -2,9 +2,9 @@ #include "CheckBoxReader.h" -#include "ui/UICheckBox.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UICheckBox.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ComAudioReader/ComAudioReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/ComAudioReader/ComAudioReader.h index 696971496b55..0b8dee23606a 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ComAudioReader/ComAudioReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ComAudioReader/ComAudioReader.h @@ -24,9 +24,9 @@ #pragma once -#include "base/Object.h" -#include "2d/Component.h" -#include "2d/Node.h" +#include "axmol/base/Object.h" +#include "axmol/2d/Component.h" +#include "axmol/2d/Node.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/GameMapReader/GameMapReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/GameMapReader/GameMapReader.cpp index 643cfdcaf486..cac65382ea9c 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/GameMapReader/GameMapReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/GameMapReader/GameMapReader.cpp @@ -24,11 +24,11 @@ #include "GameMapReader.h" -#include "2d/Label.h" -#include "2d/TMXXMLParser.h" -#include "2d/FastTMXTiledMap.h" -#include "platform/FileUtils.h" -#include "base/UTF8.h" +#include "axmol/2d/Label.h" +#include "axmol/2d/TMXXMLParser.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/base/text_utils.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/WidgetReader/NodeReader/NodeReader.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.cpp index 6768bea13c79..4f1233a1ed74 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.cpp @@ -24,7 +24,7 @@ #include "GameNode3DReader.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/ComExtensionData.h" #include "cocostudio/CSParseBinary_generated.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.h index 0000b0d85c07..677ca00ae8c4 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/GameNode3DReader/GameNode3DReader.h @@ -24,7 +24,7 @@ #pragma once -#include "2d/CameraBackgroundBrush.h" +#include "axmol/2d/CameraBackgroundBrush.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" #include "cocostudio/WidgetReader/NodeReaderDefine.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ImageViewReader/ImageViewReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ImageViewReader/ImageViewReader.cpp index 36851d4f34c2..a65f7363d47c 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ImageViewReader/ImageViewReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ImageViewReader/ImageViewReader.cpp @@ -2,10 +2,10 @@ #include "ImageViewReader.h" -#include "ui/UIImageView.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIImageView.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/LayoutReader/LayoutReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/LayoutReader/LayoutReader.cpp index b10c251ebaae..f42d49d9e680 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/LayoutReader/LayoutReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/LayoutReader/LayoutReader.cpp @@ -2,16 +2,16 @@ #include "LayoutReader.h" -#include "ui/UILayout.h" +#include "axmol/ui/UILayout.h" #include "cocostudio/CocoLoader.h" -#include "ui/UIScrollView.h" -#include "ui/UIPageView.h" -#include "ui/UIListView.h" +#include "axmol/ui/UIScrollView.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/ui/UIListView.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" -#include "base/Director.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/base/Director.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "flatbuffers/flatbuffers.h" @@ -129,15 +129,11 @@ void LayoutReader::setPropsFromBinary(ax::ui::Widget* widget, CocoLoader* cocoLo else if (key == P_LayoutType) { layoutType = (Layout::Type)valueToInt(value); } } - panel->setBackGroundColor(Color3B(scr, scg, scb), Color3B(ecr, ecg, ecb)); - panel->setBackGroundColor(Color3B(cr, cg, cb)); + panel->setBackGroundColor(Color32(scr, scg, scb, 255), Color32(ecr, ecg, ecb, 255)); + panel->setBackGroundColor(Color32(cr, cg, cb, bgColorOpacity)); panel->setBackGroundColorVector(Vec2(bgcv1, bgcv2)); - panel->setBackGroundColorOpacity(bgColorOpacity); - - panel->setBackGroundImageColor(Color3B(_color.r, _color.g, _color.b)); - - panel->setBackGroundImageOpacity(_opacity); + panel->setBackGroundImageColor(_color); if (panel->isBackGroundImageScale9Enabled()) { @@ -261,9 +257,8 @@ void LayoutReader::setPropsFromJsonDictionary(Widget* widget, const rapidjson::V int colorType = DICTOOL->getIntValue_json(options, P_ColorType, 1); panel->setBackGroundColorType(Layout::BackGroundColorType(colorType)); - panel->setBackGroundColor(Color3B(scr, scg, scb), Color3B(ecr, ecg, ecb)); - panel->setBackGroundColor(Color3B(cr, cg, cb)); - panel->setBackGroundColorOpacity(co); + panel->setBackGroundColor(Color32(scr, scg, scb, 255), Color32(ecr, ecg, ecb, 255)); + panel->setBackGroundColor(Color32(cr, cg, cb, co)); const rapidjson::Value& imageFileNameDic = DICTOOL->getSubDictionary_json(options, P_BackGroundImageData); int imageFileNameType = DICTOOL->getIntValue_json(imageFileNameDic, P_ResourceType); @@ -289,10 +284,8 @@ void LayoutReader::setPropsFromJsonDictionary(Widget* widget, const rapidjson::V int bgimgcr = DICTOOL->getIntValue_json(options, P_ColorR, 255); int bgimgcg = DICTOOL->getIntValue_json(options, P_ColorG, 255); int bgimgcb = DICTOOL->getIntValue_json(options, P_ColorB, 255); - panel->setBackGroundImageColor(Color3B(bgimgcr, bgimgcg, bgimgcb)); - int bgimgopacity = DICTOOL->getIntValue_json(options, P_Opacity, 255); - panel->setBackGroundImageOpacity(bgimgopacity); + panel->setBackGroundImageColor(Color32(bgimgcr, bgimgcg, bgimgcb, bgimgopacity)); WidgetReader::setColorPropsFromJsonDictionary(widget, options); } @@ -308,11 +301,10 @@ Offset
LayoutReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa int resourceType = 0; bool clipEnabled = false; - Color3B bgColor; - Color3B bgStartColor; - Color3B bgEndColor; + Color32 bgColor = Color32::WHITE; + Color32 bgStartColor = Color32::WHITE; + Color32 bgEndColor = Color32::WHITE; int colorType = 0; - uint8_t bgColorOpacity = 255; Vec2 colorVector(0.0f, -0.5f); Rect capInsets; Size scale9Size; @@ -335,7 +327,7 @@ Offset
LayoutReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa } else if (name == "BackColorAlpha") { - bgColorOpacity = atoi(value.data()); + bgColor.a = atoi(value.data()); } else if (name == "Scale9Enable") { @@ -535,7 +527,7 @@ Offset
LayoutReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa auto options = CreatePanelOptions( *builder, widgetOptions, CreateResourceData(*builder, builder->CreateString(path), builder->CreateString(plistFile), resourceType), - clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColorOpacity, &f_colorVector, + clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColor.a, &f_colorVector, &f_capInsets, &f_scale9Size, backGroundScale9Enabled); return *(Offset
*)(&options); @@ -552,25 +544,26 @@ void LayoutReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta bool backGroundScale9Enabled = options->backGroundScale9Enabled() != 0; panel->setBackGroundImageScale9Enabled(backGroundScale9Enabled); + int bgColorOpacity = options->bgColorOpacity(); // FIXME: redundant field, use f_bgColor->a() + auto f_bgColor = options->bgColor(); - Color3B bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b()); + Color32 bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b(), bgColorOpacity); auto f_bgStartColor = options->bgStartColor(); - Color3B bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b()); + Color32 bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b(), f_bgStartColor->a()); auto f_bgEndColor = options->bgEndColor(); - Color3B bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b()); + Color32 bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b(), f_bgEndColor->a()); auto f_colorVecor = options->colorVector(); Vec2 colorVector(f_colorVecor->x(), f_colorVecor->y()); panel->setBackGroundColorVector(colorVector); - int bgColorOpacity = options->bgColorOpacity(); + int colorType = options->colorType(); panel->setBackGroundColorType(Layout::BackGroundColorType(colorType)); panel->setBackGroundColor(bgStartColor, bgEndColor); panel->setBackGroundColor(bgColor); - panel->setBackGroundColorOpacity(bgColorOpacity); bool fileExist = false; std::string errorFilePath; @@ -635,12 +628,10 @@ void LayoutReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta auto widgetOptions = options->widgetOptions(); auto f_color = widgetOptions->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); + int opacity = widgetOptions->alpha(); // FIXME: redundant field, use f_color->a() ? + Color32 color(f_color->r(), f_color->g(), f_color->b(), opacity); panel->setColor(color); - int opacity = widgetOptions->alpha(); - panel->setOpacity(opacity); - auto widgetReader = WidgetReader::getInstance(); widgetReader->setPropsWithFlatBuffers(node, (Table*)options->widgetOptions()); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/Light3DReader/Light3DReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/Light3DReader/Light3DReader.cpp index 101df41092c5..591b223b9c60 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/Light3DReader/Light3DReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/Light3DReader/Light3DReader.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "cocostudio/WidgetReader/Light3DReader/Light3DReader.h" -#include "2d/Light.h" +#include "axmol/2d/Light.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/CSParse3DBinary_generated.h" @@ -169,17 +169,17 @@ Node* Light3DReader::createNodeWithFlatBuffers(const flatbuffers::Table* light3D switch (type) { case ax::LightType::DIRECTIONAL: - light = DirectionLight::create(Vec3::UNIT_Z, Color3B::WHITE); + light = DirectionLight::create(Vec3::UNIT_Z, Color32::WHITE); break; case ax::LightType::POINT: - light = PointLight::create(Vec3::ZERO, Color3B::WHITE, range); + light = PointLight::create(Vec3::ZERO, Color32::WHITE, range); break; case ax::LightType::SPOT: light = - SpotLight::create(Vec3::UNIT_Z, Vec3::ZERO, Color3B::WHITE, 0, AX_DEGREES_TO_RADIANS(outerAngle), range); + SpotLight::create(Vec3::UNIT_Z, Vec3::ZERO, Color32::WHITE, 0, AX_DEGREES_TO_RADIANS(outerAngle), range); break; case ax::LightType::AMBIENT: - light = AmbientLight::create(Color3B::WHITE); + light = AmbientLight::create(Color32::WHITE); break; default: break; diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ListViewReader/ListViewReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ListViewReader/ListViewReader.cpp index 22472548fa65..1278939bb06b 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ListViewReader/ListViewReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ListViewReader/ListViewReader.cpp @@ -2,9 +2,9 @@ #include "ListViewReader.h" -#include "ui/UIListView.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIListView.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" @@ -98,11 +98,10 @@ Offset
ListViewReader::createOptionsWithFlatBuffers(pugi::xml_node object int resourceType = 0; bool clipEnabled = false; - Color3B bgColor; - Color3B bgStartColor; - Color3B bgEndColor; + Color32 bgColor; + Color32 bgStartColor; + Color32 bgEndColor; int colorType = 0; - uint8_t bgColorOpacity = 255; Vec2 colorVector(0.0f, -0.5f); Rect capInsets; Size scale9Size; @@ -132,7 +131,7 @@ Offset
ListViewReader::createOptionsWithFlatBuffers(pugi::xml_node object } else if (name == "BackColorAlpha") { - bgColorOpacity = atoi(value.data()); + bgColor.a = atoi(value.data()); } else if (name == "Scale9Enable") { @@ -373,7 +372,7 @@ Offset
ListViewReader::createOptionsWithFlatBuffers(pugi::xml_node object auto options = CreateListViewOptions( *builder, widgetOptions, CreateResourceData(*builder, builder->CreateString(path), builder->CreateString(plistFile), resourceType), - clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColorOpacity, &f_colorVector, + clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColor.a, &f_colorVector, &f_capInsets, &f_scale9Size, backGroundScale9Enabled, &f_innerSize, direction, bounceEnabled, itemMargin, builder->CreateString(directionType), builder->CreateString(horizontalType), builder->CreateString(verticalType)); @@ -393,24 +392,22 @@ void ListViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers:: listView->setBackGroundImageScale9Enabled(backGroundScale9Enabled); auto f_bgColor = options->bgColor(); - Color3B bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b()); + int bgColorOpacity = options->bgColorOpacity(); // FIXME: redundant, should we use f_bgColor->a() instead? + Color32 bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b(), bgColorOpacity); auto f_bgStartColor = options->bgStartColor(); - Color3B bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b()); + Color32 bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b(), f_bgStartColor->a()); auto f_bgEndColor = options->bgEndColor(); - Color3B bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b()); + Color32 bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b(), f_bgEndColor->a()); auto f_colorVecor = options->colorVector(); Vec2 colorVector(f_colorVecor->x(), f_colorVecor->y()); listView->setBackGroundColorVector(colorVector); - int bgColorOpacity = options->bgColorOpacity(); - int colorType = options->colorType(); listView->setBackGroundColorType(Layout::BackGroundColorType(colorType)); listView->setBackGroundColor(bgStartColor, bgEndColor); listView->setBackGroundColor(bgColor); - listView->setBackGroundColorOpacity(bgColorOpacity); bool fileExist = false; std::string errorFilePath; @@ -475,12 +472,10 @@ void ListViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers:: auto widgetOptions = options->widgetOptions(); auto f_color = widgetOptions->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); + int opacity = widgetOptions->alpha(); // FIXME: redundant, should we use f_color->a() instead? + Color32 color(f_color->r(), f_color->g(), f_color->b(), opacity); listView->setColor(color); - int opacity = widgetOptions->alpha(); - listView->setOpacity(opacity); - // auto f_innerSize = options->innerSize(); // Size innerSize(f_innerSize->width(), f_innerSize->height()); // listView->setInnerContainerSize(innerSize); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/LoadingBarReader/LoadingBarReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/LoadingBarReader/LoadingBarReader.cpp index 901232f6c73a..8c531742434d 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/LoadingBarReader/LoadingBarReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/LoadingBarReader/LoadingBarReader.cpp @@ -2,9 +2,9 @@ #include "LoadingBarReader.h" -#include "ui/UILoadingBar.h" -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UILoadingBar.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.cpp index 36dbd592232f..50ee412e64a2 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.cpp @@ -23,11 +23,11 @@ THE SOFTWARE. ****************************************************************************/ -#include "2d/Light.h" -#include "3d/MeshRenderer.h" -#include "3d/Animate3D.h" -#include "3d/Animation3D.h" -#include "platform/FileUtils.h" +#include "axmol/2d/Light.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Animate3D.h" +#include "axmol/3d/Animation3D.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/WidgetReader/MeshReader/MeshReader.h" #include "cocostudio/CSParseBinary_generated.h" @@ -230,13 +230,9 @@ void MeshReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl uint8_t green = (uint8_t)nodeOptions->color()->g(); uint8_t blue = (uint8_t)nodeOptions->color()->b(); - if (alpha != 255) + if (red != 255 || green != 255 || blue != 255 || alpha != 255) { - mesh->setOpacity(alpha); - } - if (red != 255 || green != 255 || blue != 255) - { - mesh->setColor(Color3B(red, green, blue)); + mesh->setColor(Color32(red, green, blue, alpha)); } if (isFlipped) { diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.h index a769df39e45d..121aab64ec32 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/MeshReader/MeshReader.h @@ -24,7 +24,7 @@ #pragma once -#include "math/Vec2.h" +#include "axmol/math/Vec2.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" #include "cocostudio/WidgetReader/NodeReaderDefine.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.cpp index 9ebc6c12abbc..4502cb5ddbbd 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.cpp @@ -105,7 +105,7 @@ Offset
Node3DReader::createOptionsWithFlatBuffersForNode(pugi::xml_node o Vec2 position = Vec2::ZERO; Vec2 scale = Vec2(1.0f, 1.0f); Vec2 anchorPoint = Vec2::ZERO; - Color4B color(255, 255, 255, 255); + Color32 color(255, 255, 255, 255); Vec2 size = Vec2::ZERO; bool flipX = false; diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.h index 4c999614cd2e..0030222a38d3 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/Node3DReader/Node3DReader.h @@ -24,7 +24,7 @@ #pragma once -#include "math/Vec3.h" +#include "axmol/math/Vec3.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" #include "cocostudio/WidgetReader/NodeReaderDefine.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReader/NodeReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReader/NodeReader.cpp index f929f262a0ef..2df7d0c42f46 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReader/NodeReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReader/NodeReader.cpp @@ -29,7 +29,7 @@ #include "cocostudio/ComExtensionData.h" #include "flatbuffers/flatbuffers.h" -#include "ui/UILayoutComponent.h" +#include "axmol/ui/UILayoutComponent.h" using namespace ax; using namespace flatbuffers; @@ -90,7 +90,7 @@ Offset
NodeReader::createOptionsWithFlatBuffers(pugi::xml_node objectData Vec2 position; Vec2 scale(1.0f, 1.0f); Vec2 anchorPoint; - Color4B color(255, 255, 255, 255); + Color32 color(255, 255, 255, 255); Vec2 size; bool flipX = false; @@ -451,14 +451,14 @@ void NodeReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl bool visible = options->visible() != 0; float w = options->size()->width(); float h = options->size()->height(); - int alpha = options->alpha(); - Color3B color(options->color()->r(), options->color()->g(), options->color()->b()); + int alpha = options->alpha(); // FIXME: redundant, should we use options->color()->a() instead? + Color32 color(options->color()->r(), options->color()->g(), options->color()->b(), alpha); // x-studio 10.0.593.0: read from .csb. node->setCascadeColorEnabled(options->cascadeColorEnabled()); node->setCascadeOpacityEnabled(options->cascadeOpacityEnabled()); - std::string customProperty = options->customProperty()->c_str(); + std::string_view customProperty = options->customProperty()->c_str(); node->setName(name); @@ -482,8 +482,6 @@ void NodeReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl node->setVisible(visible); // if (w != 0 || h != 0) node->setContentSize(Size(w, h)); - if (alpha != 255) - node->setOpacity(alpha); node->setColor(color); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderDefine.h b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderDefine.h index 7e6cb95c8ad6..418e689fed99 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderDefine.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderDefine.h @@ -25,7 +25,7 @@ #pragma once #include -#include "base/ObjectFactory.h" +#include "axmol/base/ObjectFactory.h" // //// Reader macro diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.cpp index 181d303e1730..a385787f5c7b 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.cpp @@ -8,8 +8,8 @@ #include "NodeReaderProtocol.h" #include "cocostudio/CSParseBinary_generated.h" // flatbuffers::ResourceData, it's ok for all revision of loaders -#include "cocos2d.h" -#include "ui/CocosGUI.h" +#include "axmol/cocos2d.h" +#include "axmol/ui/CocosGUI.h" #include "cocostudio/Armature.h" #include "cocostudio/ActionTimeline/SkeletonNode.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.h b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.h index 9f4be2d7718d..ceef4e598273 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/NodeReaderProtocol.h @@ -26,7 +26,7 @@ #include "cocostudio/CocosStudioExport.h" #include "cocostudio/CocosStudioExtension.h" -#include "ui/GUIDefine.h" +#include "axmol/ui/GUIDefine.h" #include "pugixml/pugixml.hpp" #include "pugixml/pugiext.hpp" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/PageViewReader/PageViewReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/PageViewReader/PageViewReader.cpp index 8fcb3d789b93..4c4b88a9ad88 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/PageViewReader/PageViewReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/PageViewReader/PageViewReader.cpp @@ -2,10 +2,10 @@ #include "PageViewReader.h" -#include "ui/UIPageView.h" -#include "ui/UILayout.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIPageView.h" +#include "axmol/ui/UILayout.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" @@ -61,11 +61,10 @@ Offset
PageViewReader::createOptionsWithFlatBuffers(pugi::xml_node object int resourceType = 0; bool clipEnabled = false; - Color3B bgColor; - Color3B bgStartColor; - Color3B bgEndColor; + Color32 bgColor = Color32::WHITE; + Color32 bgStartColor = Color32::WHITE; + Color32 bgEndColor = Color32::WHITE; int colorType = 0; - uint8_t bgColorOpacity = 255; Vec2 colorVector(0.0f, -0.5f); Rect capInsets; Size scale9Size; @@ -88,7 +87,7 @@ Offset
PageViewReader::createOptionsWithFlatBuffers(pugi::xml_node object } else if (name == "BackColorAlpha") { - bgColorOpacity = atoi(value.data()); + bgColor.a = atoi(value.data()); } else if (name == "Scale9Enable") { @@ -288,7 +287,7 @@ Offset
PageViewReader::createOptionsWithFlatBuffers(pugi::xml_node object auto options = CreatePageViewOptions( *builder, widgetOptions, CreateResourceData(*builder, builder->CreateString(path), builder->CreateString(plistFile), resourceType), - clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColorOpacity, &f_colorVector, + clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColor.a, &f_colorVector, &f_capInsets, &f_scale9Size, backGroundScale9Enabled); return *(Offset
*)(&options); @@ -306,24 +305,22 @@ void PageViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers:: pageView->setBackGroundImageScale9Enabled(backGroundScale9Enabled); auto f_bgColor = options->bgColor(); - Color3B bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b()); + int bgColorOpacity = options->bgColorOpacity(); // FIXME: redundant, should we use f_bgColor->a() instead? + Color32 bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b(), bgColorOpacity); auto f_bgStartColor = options->bgStartColor(); - Color3B bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b()); + Color32 bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b(), f_bgStartColor->a()); auto f_bgEndColor = options->bgEndColor(); - Color3B bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b()); + Color32 bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b(), f_bgEndColor->a()); auto f_colorVecor = options->colorVector(); Vec2 colorVector(f_colorVecor->x(), f_colorVecor->y()); pageView->setBackGroundColorVector(colorVector); - int bgColorOpacity = options->bgColorOpacity(); - int colorType = options->colorType(); pageView->setBackGroundColorType(Layout::BackGroundColorType(colorType)); pageView->setBackGroundColor(bgStartColor, bgEndColor); pageView->setBackGroundColor(bgColor); - pageView->setBackGroundColorOpacity(bgColorOpacity); bool fileExist = false; std::string errorFilePath; @@ -388,12 +385,10 @@ void PageViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers:: auto widgetOptions = options->widgetOptions(); auto f_color = widgetOptions->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); + int opacity = widgetOptions->alpha(); // FIXME: shoud we use f_color->a() instead? + Color32 color(f_color->r(), f_color->g(), f_color->b(), opacity); pageView->setColor(color); - int opacity = widgetOptions->alpha(); - pageView->setOpacity(opacity); - auto widgetReader = WidgetReader::getInstance(); widgetReader->setPropsWithFlatBuffers(node, (Table*)options->widgetOptions()); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/Particle3DReader/Particle3DReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/Particle3DReader/Particle3DReader.cpp index 8345d23e1381..de401194c0b2 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/Particle3DReader/Particle3DReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/Particle3DReader/Particle3DReader.cpp @@ -22,7 +22,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/WidgetReader/Particle3DReader/Particle3DReader.h" #if defined(AX_ENABLE_EXT_PARTICLE3D) diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ParticleReader/ParticleReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ParticleReader/ParticleReader.cpp index 8ea9156d4675..f5193fdba440 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ParticleReader/ParticleReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ParticleReader/ParticleReader.cpp @@ -24,10 +24,10 @@ #include "ParticleReader.h" -#include "base/Types.h" -#include "base/Utils.h" -#include "2d/ParticleSystemQuad.h" -#include "platform/FileUtils.h" +#include "axmol/base/Types.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/ParticleSystemQuad.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/WidgetReader/NodeReader/NodeReader.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ProjectNodeReader/ProjectNodeReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/ProjectNodeReader/ProjectNodeReader.h index 703d800211aa..d11acd14c303 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ProjectNodeReader/ProjectNodeReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ProjectNodeReader/ProjectNodeReader.h @@ -24,7 +24,7 @@ #pragma once -#include "base/Object.h" +#include "axmol/base/Object.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonGroupReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonGroupReader.cpp index c3997846383e..79b7cc0796e5 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonGroupReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonGroupReader.cpp @@ -2,10 +2,10 @@ #include "RadioButtonGroupReader.h" -#include "ui/UIRadioButton.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrame.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIRadioButton.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrame.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonReader.cpp index 42902acb4099..996ef65c220d 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/RadioButtonReader/RadioButtonReader.cpp @@ -2,9 +2,9 @@ #include "RadioButtonReader.h" -#include "ui/UIRadioButton.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIRadioButton.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/RichTextReader/RichTextReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/RichTextReader/RichTextReader.cpp index 14d350e03694..7ce81628fa9b 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/RichTextReader/RichTextReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/RichTextReader/RichTextReader.cpp @@ -2,9 +2,9 @@ #include "RichTextReader.h" -#include "2d/FontAtlasCache.h" -#include "ui/UIRichText.h" -#include "platform/FileUtils.h" +#include "axmol/2d/FontAtlasCache.h" +#include "axmol/ui/UIRichText.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/LocalizationManager.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/ScrollViewReader/ScrollViewReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/ScrollViewReader/ScrollViewReader.cpp index f08a61057223..74e51f706326 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/ScrollViewReader/ScrollViewReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/ScrollViewReader/ScrollViewReader.cpp @@ -2,9 +2,9 @@ #include "ScrollViewReader.h" -#include "ui/UIScrollView.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UIScrollView.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" @@ -105,11 +105,10 @@ Offset
ScrollViewReader::createOptionsWithFlatBuffers(pugi::xml_node obje int resourceType = 0; bool clipEnabled = false; - Color3B bgColor; - Color3B bgStartColor; - Color3B bgEndColor; + Color32 bgColor = Color32::WHITE; + Color32 bgStartColor = Color32::WHITE; + Color32 bgEndColor = Color32::WHITE; int colorType = 0; - uint8_t bgColorOpacity = 255; Vec2 colorVector(0.0f, -0.5f); Rect capInsets; Size scale9Size; @@ -138,7 +137,7 @@ Offset
ScrollViewReader::createOptionsWithFlatBuffers(pugi::xml_node obje } else if (name == "BackColorAlpha") { - bgColorOpacity = atoi(value.data()); + bgColor.a = atoi(value.data()); } else if (name == "Scale9Enable") { @@ -386,7 +385,7 @@ Offset
ScrollViewReader::createOptionsWithFlatBuffers(pugi::xml_node obje auto options = CreateScrollViewOptions( *builder, widgetOptions, CreateResourceData(*builder, builder->CreateString(path), builder->CreateString(plistFile), resourceType), - clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColorOpacity, &f_colorVector, + clipEnabled, &f_bgColor, &f_bgStartColor, &f_bgEndColor, colorType, bgColor.a, &f_colorVector, &f_capInsets, &f_scale9Size, backGroundScale9Enabled, &f_innerSize, direction, bounceEnabled, scrollbarEnabled, scrollbarAutoHide, scrollbarAutoHideTime); @@ -405,24 +404,22 @@ void ScrollViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers scrollView->setBackGroundImageScale9Enabled(backGroundScale9Enabled); auto f_bgColor = options->bgColor(); - Color3B bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b()); + int bgColorOpacity = options->bgColorOpacity(); // FIXME: redundant, should we use f_bgColor->a() instead? + Color32 bgColor(f_bgColor->r(), f_bgColor->g(), f_bgColor->b(), bgColorOpacity); auto f_bgStartColor = options->bgStartColor(); - Color3B bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b()); + Color32 bgStartColor(f_bgStartColor->r(), f_bgStartColor->g(), f_bgStartColor->b(), f_bgStartColor->a()); auto f_bgEndColor = options->bgEndColor(); - Color3B bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b()); + Color32 bgEndColor(f_bgEndColor->r(), f_bgEndColor->g(), f_bgEndColor->b(), f_bgEndColor->a()); auto f_colorVecor = options->colorVector(); Vec2 colorVector(f_colorVecor->x(), f_colorVecor->y()); scrollView->setBackGroundColorVector(colorVector); - int bgColorOpacity = options->bgColorOpacity(); - int colorType = options->colorType(); scrollView->setBackGroundColorType(Layout::BackGroundColorType(colorType)); scrollView->setBackGroundColor(bgStartColor, bgEndColor); scrollView->setBackGroundColor(bgColor); - scrollView->setBackGroundColorOpacity(bgColorOpacity); bool fileExist = false; std::string errorFilePath; @@ -487,12 +484,10 @@ void ScrollViewReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers auto widgetOptions = options->widgetOptions(); auto f_color = widgetOptions->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); + int opacity = widgetOptions->alpha(); // FIXME: redundant, should we use f_color->a() instead? + Color32 color(f_color->r(), f_color->g(), f_color->b(), opacity); scrollView->setColor(color); - int opacity = widgetOptions->alpha(); - scrollView->setOpacity(opacity); - auto f_innerSize = options->innerSize(); Size innerSize(f_innerSize->width(), f_innerSize->height()); scrollView->setInnerContainerSize(innerSize); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/SkeletonReader/BoneNodeReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/SkeletonReader/BoneNodeReader.cpp index 7a24dea40da4..6f7ca09afec6 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/SkeletonReader/BoneNodeReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/SkeletonReader/BoneNodeReader.cpp @@ -29,7 +29,7 @@ THE SOFTWARE. #include "cocostudio/WidgetReader/SkeletonReader/CSBoneBinary_generated.h" #include "cocostudio/WidgetReader/SkeletonReader/BoneNodeReader.h" #include "cocostudio/ActionTimeline/BoneNode.h" -#include "base/Utils.h" +#include "axmol/base/Utils.h" using namespace ax; USING_NS_TIMELINE; diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/SliderReader/SliderReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/SliderReader/SliderReader.cpp index 0a0ea58560b9..44c4262cedab 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/SliderReader/SliderReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/SliderReader/SliderReader.cpp @@ -2,9 +2,9 @@ #include "SliderReader.h" -#include "ui/UISlider.h" -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UISlider.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/SpineSkeletonReader/SpineSkeletonReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/SpineSkeletonReader/SpineSkeletonReader.cpp index d4558f293367..1f177f2b648c 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/SpineSkeletonReader/SpineSkeletonReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/SpineSkeletonReader/SpineSkeletonReader.cpp @@ -27,9 +27,9 @@ #if defined(AX_ENABLE_EXT_SPINE) # include "cocostudio/SpineSkeletonDataCache.h" -# include "2d/Sprite.h" -# include "2d/SpriteFrameCache.h" -# include "platform/FileUtils.h" +# include "axmol/2d/Sprite.h" +# include "axmol/2d/SpriteFrameCache.h" +# include "axmol/platform/FileUtils.h" # include "cocostudio/CSParseBinary_generated.h" # include "cocostudio/FlatBuffersSerialize.h" @@ -219,8 +219,7 @@ void SpineSkeletonReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuff implNode->setScaleX(nodeOptions->scale()->x()); implNode->setScaleY(nodeOptions->scale()->y()); - implNode->setColor(Color3B(red, green, blue)); - implNode->setOpacity(alpha); + implNode->setColor(Color32(red, green, blue, alpha)); /*bool flipX = nodeOptions->flipX() != 0; bool flipY = nodeOptions->flipY() != 0; diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp index 310dc7252c01..ab1f274f6046 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/SpriteReader/SpriteReader.cpp @@ -26,10 +26,10 @@ #include "cocostudio/WidgetReader/SpriteReader/SpriteReader.h" -#include "base/Utils.h" -#include "2d/Sprite.h" -#include "2d/SpriteFrameCache.h" -#include "platform/FileUtils.h" +#include "axmol/base/Utils.h" +#include "axmol/2d/Sprite.h" +#include "axmol/2d/SpriteFrameCache.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/FlatBuffersSerialize.h" @@ -37,8 +37,8 @@ #include "flatbuffers/flatbuffers.h" -#include "renderer/backend/ProgramManager.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/renderer/ProgramManager.h" +#include "axmol/rhi/ProgramState.h" using namespace ax; using namespace flatbuffers; @@ -300,13 +300,9 @@ void SpriteReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta uint8_t green = (uint8_t)nodeOptions->color()->g(); uint8_t blue = (uint8_t)nodeOptions->color()->b(); - if (alpha != 255) + if (red != 255 || green != 255 || blue != 255 || alpha != 255) { - sprite->setOpacity(alpha); - } - if (red != 255 || green != 255 || blue != 255) - { - sprite->setColor(Color3B(red, green, blue)); + sprite->setColor(Color32(red, green, blue, alpha)); } bool flipX = nodeOptions->flipX() != 0; @@ -324,7 +320,7 @@ void SpriteReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta if (hsv != nullptr && filter != nullptr) { auto prog = ProgramManager::getInstance()->getBuiltinProgram(ProgramType::HSV); - auto ps = new backend::ProgramState(prog); + auto ps = new rhi::ProgramState(prog); sprite->setProgramState(ps, true); Vec3 axhsv{hsv->x(), hsv->y(), hsv->z()}; ps->setUniform(ps->getUniformLocation("u_hsv"), &axhsv, sizeof(axhsv)); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TabControlReader/TabControlReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TabControlReader/TabControlReader.cpp index 0d699e750482..6cac1e8d17a4 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TabControlReader/TabControlReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TabControlReader/TabControlReader.cpp @@ -28,9 +28,9 @@ #include "cocostudio/WidgetReader/TabControlReader/TabControlReader.h" #include "cocostudio/FlatBuffersSerialize.h" #include "cocostudio/ActionTimeline/CSLoader.h" -#include "ui/UITabControl.h" -#include "platform/FileUtils.h" -#include "2d/SpriteFrameCache.h" +#include "axmol/ui/UITabControl.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/2d/SpriteFrameCache.h" using namespace ax; using namespace cocostudio; @@ -229,7 +229,7 @@ flatbuffers::Offset TabHeaderReader::createOptionsWithFlatBu int fontsize = 12; std::string text; - ax::Color4B textColor(255, 255, 255, 255); + ax::Color32 textColor(255, 255, 255, 255); std::string fontName; int backgroundboxResourceType = 0; @@ -533,7 +533,7 @@ void TabHeaderReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers: header->setTitleFontSize(options->fontSize()); header->setTitleText(options->titleText()->c_str()); auto textColor = options->textColor(); - Color4B titleColor(textColor->r(), textColor->g(), textColor->b(), textColor->a()); + Color32 titleColor(textColor->r(), textColor->g(), textColor->b(), textColor->a()); header->setTitleColor(titleColor); auto resourceData = options->fontRes(); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TextAtlasReader/TextAtlasReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TextAtlasReader/TextAtlasReader.cpp index 7887f6f1333f..7e53f90de274 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TextAtlasReader/TextAtlasReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TextAtlasReader/TextAtlasReader.cpp @@ -2,8 +2,8 @@ #include "TextAtlasReader.h" -#include "ui/UITextAtlas.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UITextAtlas.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TextBMFontReader/TextBMFontReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TextBMFontReader/TextBMFontReader.cpp index 0b60e34d4e74..827da3cbe852 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TextBMFontReader/TextBMFontReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TextBMFontReader/TextBMFontReader.cpp @@ -2,9 +2,9 @@ #include "TextBMFontReader.h" -#include "2d/FontAtlasCache.h" -#include "ui/UITextBMFont.h" -#include "platform/FileUtils.h" +#include "axmol/2d/FontAtlasCache.h" +#include "axmol/ui/UITextBMFont.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/LocalizationManager.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldExReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldExReader.cpp index 48234ab18540..208b91789c36 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldExReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldExReader.cpp @@ -2,8 +2,8 @@ #include "TextFieldExReader.h" -#include "ui/UITextFieldEx.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UITextFieldEx.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/LocalizationManager.h" @@ -16,14 +16,9 @@ using namespace ax; using namespace ui; using namespace flatbuffers; -inline Color4B Color4BFromFb(const FColor* pColor) +inline Color32 Color32FromFb(const FColor* pColor) { - return Color4B(pColor->r(), pColor->g(), pColor->b(), pColor->a()); -} - -inline Color3B Color3BFromFb(const FColor* pColor) -{ - return Color3B(pColor->r(), pColor->g(), pColor->b()); + return Color32(pColor->r(), pColor->g(), pColor->b(), pColor->a()); } namespace cocostudio @@ -82,9 +77,9 @@ Offset
TextFieldExReader::createOptionsWithFlatBuffers(pugi::xml_node obj int maxLength = 10; bool isEnabled = true; bool isEditable = true; - Color4B textColor; - Color4B placeholderColor; - Color4B cursorColor; + Color32 textColor; + Color32 placeholderColor; + Color32 cursorColor; // attributes auto attribute = objectData.first_attribute(); @@ -335,9 +330,9 @@ void TextFieldExReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffer }*/ textField->setString(text); - textField->setTextColor(Color4BFromFb(options->textColor())); - textField->setPlaceholderColor(Color4BFromFb(options->placeholderColor())); - textField->setCursorColor(Color3BFromFb(options->cursorColor())); + textField->setTextColor(Color32FromFb(options->textColor())); + textField->setPlaceholderColor(Color32FromFb(options->placeholderColor())); + textField->setCursorColor(Color32FromFb(options->cursorColor())); auto widgetReader = NodeReader::getInstance(); widgetReader->setPropsWithFlatBuffers(textField, (Table*)options->nodeOptions()); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldReader.cpp index f99b58e1b77d..7b7d532f28b8 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TextFieldReader/TextFieldReader.cpp @@ -2,8 +2,8 @@ #include "cocostudio/WidgetReader/TextFieldReader/TextFieldReader.h" -#include "ui/UITextField.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UITextField.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" #include "cocostudio/LocalizationManager.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/TextReader/TextReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/TextReader/TextReader.cpp index ad096b02d489..0576d74a80a9 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/TextReader/TextReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/TextReader/TextReader.cpp @@ -2,9 +2,9 @@ #include "cocostudio/WidgetReader/TextReader/TextReader.h" -#include "ui/UIText.h" -#include "2d/Label.h" -#include "platform/FileUtils.h" +#include "axmol/ui/UIText.h" +#include "axmol/2d/Label.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/CocoLoader.h" #include "cocostudio/CSParseBinary_generated.h" @@ -157,16 +157,16 @@ Offset
TextReader::createOptionsWithFlatBuffers(pugi::xml_node objectData int h_alignment = 0; int v_alignment = 0; bool outlineEnabled = false; - Color4B outlineColor = Color4B::BLACK; + Color32 outlineColor = Color32::BLACK; int outlineSize = 1; bool shadowEnabled = false; - Color4B shadowColor = Color4B::BLACK; + Color32 shadowColor = Color32::BLACK; Size shadowOffset = Size(2, -2); int shadowBlurRadius = 0; // since x-studio reader 10.0.593.0 bool glowEnabled = false; - Color4B glowColor = Color4B::BLACK; + Color32 glowColor = Color32::BLACK; bool boldEnabled = false, underlineEnabled = false, italicsEnabled = false, strikethroughEnabled = false; @@ -469,7 +469,7 @@ void TextReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl auto f_outlineColor = options->outlineColor(); if (f_outlineColor) { - Color4B outlineColor(f_outlineColor->r(), f_outlineColor->g(), f_outlineColor->b(), f_outlineColor->a()); + Color32 outlineColor(f_outlineColor->r(), f_outlineColor->g(), f_outlineColor->b(), f_outlineColor->a()); label->enableOutline(outlineColor, options->outlineSize()); } } @@ -480,7 +480,7 @@ void TextReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl auto f_shadowColor = options->shadowColor(); if (f_shadowColor) { - Color4B shadowColor(f_shadowColor->r(), f_shadowColor->g(), f_shadowColor->b(), f_shadowColor->a()); + Color32 shadowColor(f_shadowColor->r(), f_shadowColor->g(), f_shadowColor->b(), f_shadowColor->a()); label->enableShadow(shadowColor, Size(options->shadowOffsetX(), options->shadowOffsetY()), options->shadowBlurRadius()); } @@ -491,7 +491,7 @@ void TextReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl auto f_glowColor = options->glowColor(); if (f_glowColor) { - Color4B glowColor(f_glowColor->r(), f_glowColor->g(), f_glowColor->b(), f_glowColor->a()); + Color32 glowColor(f_glowColor->r(), f_glowColor->g(), f_glowColor->b(), f_glowColor->a()); label->enableGlow(glowColor); } } @@ -518,7 +518,7 @@ void TextReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Tabl node->setColor(oldColor); auto optionsWidget = (WidgetOptions*)options->widgetOptions(); auto f_color = optionsWidget->color(); - Color4B color(f_color->r(), f_color->g(), f_color->b(), f_color->a()); + Color32 color(f_color->r(), f_color->g(), f_color->b(), f_color->a()); ((Text*)node)->setTextColor(color); label->setUnifySizeEnabled(false); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.cpp index 600359919654..4e825ff96e20 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.cpp @@ -22,9 +22,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "base/Director.h" -#include "2d/Camera.h" -#include "platform/FileUtils.h" +#include "axmol/base/Director.h" +#include "axmol/2d/Camera.h" +#include "axmol/platform/FileUtils.h" #include "cocostudio/WidgetReader/UserCameraReader/UserCameraReader.h" #include "cocostudio/CSParseBinary_generated.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.h index 5b118fedef2d..6182a9b6a966 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/UserCameraReader/UserCameraReader.h @@ -24,7 +24,7 @@ #pragma once -#include "math/Vec2.h" +#include "axmol/math/Vec2.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" #include "cocostudio/WidgetReader/NodeReaderDefine.h" diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.cpp b/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.cpp index 41dcb3066eb2..793528745b09 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.cpp +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.cpp @@ -3,16 +3,16 @@ #include "WidgetReader.h" #include "cocostudio/CocoLoader.h" -#include "ui/UIButton.h" +#include "axmol/ui/UIButton.h" #include "cocostudio/ActionTimeline/ActionTimeline.h" #include "cocostudio/ComExtensionData.h" #include "cocostudio/CSParseBinary_generated.h" #include "flatbuffers/flatbuffers.h" -#include "ui/UILayoutComponent.h" +#include "axmol/ui/UILayoutComponent.h" #include "cocostudio/ActionTimeline/CSLoader.h" -#include "base/Utils.h" -#include "base/Director.h" +#include "axmol/base/Utils.h" +#include "axmol/base/Director.h" using namespace ax; using namespace ui; @@ -95,7 +95,6 @@ WidgetReader::WidgetReader() , _positionPercentY(0.0f) , _width(0.0f) , _height(0.0f) - , _opacity(255) , _isAdaptScreen(false) { valueToInt = [](std::string_view str) -> int { return atoi(str.data()); }; @@ -245,17 +244,14 @@ void WidgetReader::setPropsFromJsonDictionary(Widget* widget, const rapidjson::V void WidgetReader::setColorPropsFromJsonDictionary(Widget* widget, const rapidjson::Value& options) { bool op = DICTOOL->checkObjectExist_json(options, P_Opacity); - if (op) - { - widget->setOpacity(DICTOOL->getIntValue_json(options, P_Opacity)); - } bool cr = DICTOOL->checkObjectExist_json(options, P_ColorR); bool cg = DICTOOL->checkObjectExist_json(options, P_ColorG); bool cb = DICTOOL->checkObjectExist_json(options, P_ColorB); int colorR = cr ? DICTOOL->getIntValue_json(options, P_ColorR) : 255; int colorG = cg ? DICTOOL->getIntValue_json(options, P_ColorG) : 255; int colorB = cb ? DICTOOL->getIntValue_json(options, P_ColorB) : 255; - widget->setColor(Color3B(colorR, colorG, colorB)); + int colorA = op ? DICTOOL->getIntValue_json(options, P_Opacity) : 255; + widget->setColor(Color32(colorR, colorG, colorB, colorA)); this->setAnchorPointForWidget(widget, options); @@ -269,9 +265,9 @@ void WidgetReader::beginSetBasicProperties(ax::ui::Widget* widget) { _position = widget->getPosition(); // set default color - _color = Color3B(255, 255, 255); + _color = Color32::WHITE; + _color.a = widget->getOpacity(); widget->setColor(_color); - _opacity = widget->getOpacity(); _originalAnchorPoint = widget->getAnchorPoint(); } @@ -287,7 +283,6 @@ void WidgetReader::endSetBasicProperties(Widget* widget) _height = screenSize.height; } widget->setColor(_color); - widget->setOpacity(_opacity); // the setSize method will be conflict with scale9Width & scale9Height if (!widget->isIgnoreContentAdaptWithSize()) { @@ -417,7 +412,7 @@ Offset
WidgetReader::createOptionsWithFlatBuffers(pugi::xml_node objectDa Vec2 position; Vec2 scale(1.0f, 1.0f); Vec2 anchorPoint; - Color4B color(255, 255, 255, 255); + Color32 color(255, 255, 255, 255); Vec2 size; bool flipX = false; bool flipY = false; @@ -833,12 +828,9 @@ void WidgetReader::setPropsWithFlatBuffers(ax::Node* node, const flatbuffers::Ta widget->setLocalZOrder(zOrder); auto f_color = options->color(); - Color3B color(f_color->r(), f_color->g(), f_color->b()); + Color32 color(f_color->r(), f_color->g(), f_color->b(), options->alpha()); widget->setColor(color); - int alpha = options->alpha(); - widget->setOpacity(alpha); - auto f_anchorPoint = options->anchorPoint(); Vec2 anchorPoint(f_anchorPoint->x(), f_anchorPoint->y()); widget->setAnchorPoint(anchorPoint); diff --git a/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.h b/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.h index 3bab6e4d1948..9b90c554736c 100644 --- a/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.h +++ b/extensions/cocostudio/src/cocostudio/WidgetReader/WidgetReader.h @@ -26,7 +26,7 @@ #include "cocostudio/WidgetReader/WidgetReaderProtocol.h" #include "cocostudio/SGUIReader.h" -#include "ui/GUIDefine.h" +#include "axmol/ui/GUIDefine.h" #include "cocostudio/CocosStudioExport.h" #include "cocostudio/WidgetReader/NodeReaderProtocol.h" #include "cocostudio/WidgetReader/NodeReaderDefine.h" @@ -86,8 +86,7 @@ class CCS_DLL WidgetReader : public ax::Object, public WidgetReaderProtocol, pub float _positionPercentY; float _width; float _height; - ax::Color3B _color; - int _opacity; + ax::Color32 _color; ax::Vec2 _position; bool _isAdaptScreen; ax::Vec2 _originalAnchorPoint; @@ -285,7 +284,7 @@ extern const char* P_Path; } #define AX_COLOR_PROPERTY_BINARY_READER \ - else if (key == P_Opacity) { _opacity = valueToInt(value); } \ + else if (key == P_Opacity) { _color.a = valueToInt(value); } \ else if (key == P_ColorR) { _color.r = valueToInt(value); } \ else if (key == P_ColorG) { _color.g = valueToInt(value); } \ else if (key == P_ColorB) { _color.b = valueToInt(value); } \ diff --git a/extensions/fairygui/src/fairygui/Controller.h b/extensions/fairygui/src/fairygui/Controller.h index 14a39c6a6982..53fc5535c423 100644 --- a/extensions/fairygui/src/fairygui/Controller.h +++ b/extensions/fairygui/src/fairygui/Controller.h @@ -2,7 +2,7 @@ #define __GCONTROLLER_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "event/UIEventDispatcher.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/DragDropManager.h b/extensions/fairygui/src/fairygui/DragDropManager.h index b5d9c0b0c8fa..6cd628edc06c 100644 --- a/extensions/fairygui/src/fairygui/DragDropManager.h +++ b/extensions/fairygui/src/fairygui/DragDropManager.h @@ -2,7 +2,7 @@ #define __DRAGDROPMANAGER_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GLoader.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/FairyGUIMacros.h b/extensions/fairygui/src/fairygui/FairyGUIMacros.h index 580afc81b548..2ebaaca8d116 100644 --- a/extensions/fairygui/src/fairygui/FairyGUIMacros.h +++ b/extensions/fairygui/src/fairygui/FairyGUIMacros.h @@ -1,7 +1,7 @@ #ifndef __FAIRYGUIMACROS_H__ #define __FAIRYGUIMACROS_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #define NS_FGUI_BEGIN namespace fairygui { #define NS_FGUI_END } @@ -33,4 +33,4 @@ ax::Director::getInstance()->getScheduler()->unschedule(AX_SCHEDULE_SELECTOR(__T #include "FieldTypes.h" -#endif \ No newline at end of file +#endif diff --git a/extensions/fairygui/src/fairygui/GButton.cpp b/extensions/fairygui/src/fairygui/GButton.cpp index b5f35b8d593c..852ff9b77d4b 100644 --- a/extensions/fairygui/src/fairygui/GButton.cpp +++ b/extensions/fairygui/src/fairygui/GButton.cpp @@ -27,9 +27,9 @@ GButton::GButton() : _mode(ButtonMode::COMMON), _down(false), _downEffect(0), _downScaled(false), - _downEffectValue(0.8f), - _changeStateOnClick(true), - _sound(UIConfig::buttonSound), + _downEffectValue(0.8f), + _changeStateOnClick(true), + _sound(UIConfig::buttonSound), _soundVolumeScale(UIConfig::buttonSoundVolumeScale) { } @@ -68,16 +68,16 @@ void GButton::setSelectedIcon(const std::string& value) _iconObject->setIcon((_selected && _selectedIcon.length() > 0) ? _selectedIcon : _icon); } -ax::Color3B GButton::getTitleColor() const +ax::Color32 GButton::getTitleColor() const { GTextField* tf = getTextField(); if (tf) return tf->getColor(); else - return Color3B::BLACK; + return Color32::BLACK; } -void GButton::setTitleColor(const ax::Color3B& value) +void GButton::setTitleColor(const ax::Color32& value) { GTextField* tf = getTextField(); if (tf) @@ -318,7 +318,7 @@ void GButton::setup_afterAdd(ByteBuffer* buffer, int beginPos) if ((str = buffer->readSP())) setSelectedIcon(*str); if (buffer->readBool()) - setTitleColor((Color3B)buffer->readColor()); + setTitleColor(buffer->readColor()); int iv = buffer->readInt(); if (iv != 0) setTitleFontSize(iv); diff --git a/extensions/fairygui/src/fairygui/GButton.h b/extensions/fairygui/src/fairygui/GButton.h index cb546a96402e..b5f58e62a242 100644 --- a/extensions/fairygui/src/fairygui/GButton.h +++ b/extensions/fairygui/src/fairygui/GButton.h @@ -1,7 +1,7 @@ #ifndef __GBUTTON_H #define __GBUTTON_H -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GComponent.h" @@ -39,8 +39,8 @@ class GButton : public GComponent const std::string& getSelectedIcon() const { return _selectedIcon; } void setSelectedIcon(const std::string& value); - ax::Color3B getTitleColor() const; - void setTitleColor(const ax::Color3B& value); + ax::Color32 getTitleColor() const; + void setTitleColor(const ax::Color32& value); int getTitleFontSize() const; void setTitleFontSize(int value); diff --git a/extensions/fairygui/src/fairygui/GComboBox.cpp b/extensions/fairygui/src/fairygui/GComboBox.cpp index 5f2b1a9f1fb9..c7867c1f6f7a 100644 --- a/extensions/fairygui/src/fairygui/GComboBox.cpp +++ b/extensions/fairygui/src/fairygui/GComboBox.cpp @@ -17,8 +17,8 @@ GComboBox::GComboBox() _iconObject(nullptr), _list(nullptr), _selectionController(nullptr), - _itemsUpdated(true), - _selectedIndex(-1), + _itemsUpdated(true), + _selectedIndex(-1), _buttonController(nullptr), _down(false), _over(false) @@ -46,16 +46,16 @@ void GComboBox::setTitle(const std::string& value) updateGear(6); } -const ax::Color3B GComboBox::getTitleColor() const +const ax::Color32 GComboBox::getTitleColor() const { GTextField* tf = getTextField(); if (tf) return tf->getColor(); else - return Color3B::BLACK; + return Color32::BLACK; } -void GComboBox::setTitleColor(const ax::Color3B& value) +void GComboBox::setTitleColor(const ax::Color32& value) { GTextField* tf = getTextField(); if (tf) @@ -381,7 +381,7 @@ void GComboBox::setup_afterAdd(ByteBuffer* buffer, int beginPos) setIcon(*str); if (buffer->readBool()) - setTitleColor((Color3B)buffer->readColor()); + setTitleColor(buffer->readColor()); int iv = buffer->readInt(); if (iv > 0) visibleItemCount = iv; diff --git a/extensions/fairygui/src/fairygui/GComboBox.h b/extensions/fairygui/src/fairygui/GComboBox.h index 53cfd342f890..eeb0c9cb1075 100644 --- a/extensions/fairygui/src/fairygui/GComboBox.h +++ b/extensions/fairygui/src/fairygui/GComboBox.h @@ -1,7 +1,7 @@ #ifndef __GCOMBOBOX_H__ #define __GCOMBOBOX_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GComponent.h" #include "GList.h" @@ -24,8 +24,8 @@ class GComboBox : public GComponent virtual const std::string& getText() const override { return getTitle(); } virtual void setText(const std::string& value) override { setTitle(value); } - const ax::Color3B getTitleColor() const; - void setTitleColor(const ax::Color3B& value); + const ax::Color32 getTitleColor() const; + void setTitleColor(const ax::Color32& value); int getTitleFontSize() const; void setTitleFontSize(int value); @@ -45,7 +45,7 @@ class GComboBox : public GComponent std::vector& getItems() { return _items; } std::vector& getIcons() { return _icons; } std::vector& getValues() { return _values; } - + GObject* getDropdown() const { return _dropdown; } void refresh(); diff --git a/extensions/fairygui/src/fairygui/GComponent.h b/extensions/fairygui/src/fairygui/GComponent.h index 8d02a8310db0..d9acaba05cbe 100644 --- a/extensions/fairygui/src/fairygui/GComponent.h +++ b/extensions/fairygui/src/fairygui/GComponent.h @@ -6,7 +6,7 @@ #include "Margin.h" #include "ScrollPane.h" #include "Transition.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "display/FUIContainer.h" #include "event/HitTest.h" diff --git a/extensions/fairygui/src/fairygui/GGraph.cpp b/extensions/fairygui/src/fairygui/GGraph.cpp index d2223dbc188b..0499b255fe62 100644 --- a/extensions/fairygui/src/fairygui/GGraph.cpp +++ b/extensions/fairygui/src/fairygui/GGraph.cpp @@ -5,7 +5,7 @@ NS_FGUI_BEGIN using namespace ax; -static void drawVertRect(ax::DrawNode* shape, float x, float y, float width, float height, const ax::Color4B& color) +static void drawVertRect(ax::DrawNode* shape, float x, float y, float width, float height, const ax::Color& color) { float mx = x + width; float my = y + height; @@ -16,8 +16,8 @@ static void drawVertRect(ax::DrawNode* shape, float x, float y, float width, flo GGraph::GGraph() : _shape(nullptr), _type(0), _lineSize(1), - _lineColor(Color4B::BLACK), - _fillColor(Color4B::WHITE), + _lineColor(Color32::BLACK), + _fillColor(Color32::WHITE), _cornerRadius(nullptr), _polygonPoints(nullptr), _distances(nullptr) @@ -40,7 +40,7 @@ void GGraph::handleInit() _displayObject = _shape; } -void GGraph::drawRect(float aWidth, float aHeight, int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor) +void GGraph::drawRect(float aWidth, float aHeight, int lineSize, const ax::Color& lineColor, const ax::Color& fillColor) { _type = 0; //avoid updateshape call in handleSizeChange setSize(aWidth, aHeight); @@ -51,7 +51,7 @@ void GGraph::drawRect(float aWidth, float aHeight, int lineSize, const ax::Color updateShape(); } -void GGraph::drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor) +void GGraph::drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Color& lineColor, const ax::Color& fillColor) { _type = 0; //avoid updateshape call in handleSizeChange setSize(aWidth, aHeight); @@ -62,7 +62,7 @@ void GGraph::drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Co updateShape(); } -void GGraph::drawPolygon(int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor, const ax::Vec2* points, int count) +void GGraph::drawPolygon(int lineSize, const ax::Color& lineColor, const ax::Color& fillColor, const ax::Vec2* points, int count) { _type = 3; _lineSize = lineSize; @@ -83,7 +83,7 @@ void GGraph::drawPolygon(int lineSize, const ax::Color4B& lineColor, const ax::C updateShape(); } -void GGraph::drawRegularPolygon(int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor, +void GGraph::drawRegularPolygon(int lineSize, const ax::Color& lineColor, const ax::Color& fillColor, int sides, float startAngle, const float* distances, int count) { _type = 4; @@ -182,14 +182,14 @@ void GGraph::updateShape() } } -ax::Color3B GGraph::getColor() const +ax::Color32 GGraph::getColor() const { - return (Color3B)_fillColor; + return Color32{_fillColor}; } -void GGraph::setColor(const ax::Color3B& value) +void GGraph::setColor(const ax::Color32& value) { - _fillColor = Color4B(value, _fillColor.a); + _fillColor = ax::Color{value}; updateShape(); } @@ -247,8 +247,8 @@ void GGraph::setup_beforeAdd(ByteBuffer* buffer, int beginPos) if (_type != 0) { _lineSize = buffer->readInt(); - _lineColor = (Color4B)buffer->readColor(); - _fillColor = (Color4B)buffer->readColor(); + _lineColor = ax::Color{buffer->readColor()}; + _fillColor = ax::Color{buffer->readColor()}; if (buffer->readBool()) { _cornerRadius = new float[4]; diff --git a/extensions/fairygui/src/fairygui/GGraph.h b/extensions/fairygui/src/fairygui/GGraph.h index d2dc512690be..5200705cd8a1 100644 --- a/extensions/fairygui/src/fairygui/GGraph.h +++ b/extensions/fairygui/src/fairygui/GGraph.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GObject.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN @@ -15,14 +15,14 @@ class GGraph : public GObject CREATE_FUNC(GGraph); - void drawRect(float aWidth, float aHeight, int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor); - void drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor); - void drawPolygon(int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor, const ax::Vec2* points, int count); - void drawRegularPolygon(int lineSize, const ax::Color4B& lineColor, const ax::Color4B& fillColor, int sides, float startAngle = 0, const float* distances = nullptr, int distanceCount = 0); + void drawRect(float aWidth, float aHeight, int lineSize, const ax::Color& lineColor, const ax::Color& fillColor); + void drawEllipse(float aWidth, float aHeight, int lineSize, const ax::Color& lineColor, const ax::Color& fillColor); + void drawPolygon(int lineSize, const ax::Color& lineColor, const ax::Color& fillColor, const ax::Vec2* points, int count); + void drawRegularPolygon(int lineSize, const ax::Color& lineColor, const ax::Color& fillColor, int sides, float startAngle = 0, const float* distances = nullptr, int distanceCount = 0); bool isEmpty() const { return _type == 0; } - ax::Color3B getColor() const; - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); virtual ax::Value getProp(ObjectPropID propId) override; virtual void setProp(ObjectPropID propId, const ax::Value& value) override; @@ -36,8 +36,8 @@ class GGraph : public GObject void updateShape(); int _type; - ax::Color4B _lineColor; - ax::Color4B _fillColor; + ax::Color _lineColor; + ax::Color _fillColor; int _lineSize; float* _cornerRadius; std::vector* _polygonPoints; diff --git a/extensions/fairygui/src/fairygui/GGroup.h b/extensions/fairygui/src/fairygui/GGroup.h index c632881cd6cf..bd8cde773a59 100644 --- a/extensions/fairygui/src/fairygui/GGroup.h +++ b/extensions/fairygui/src/fairygui/GGroup.h @@ -1,7 +1,7 @@ #ifndef __GGROUP_H__ #define __GGROUP_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GObject.h" diff --git a/extensions/fairygui/src/fairygui/GImage.cpp b/extensions/fairygui/src/fairygui/GImage.cpp index a9ccfd88d15c..04902c85d882 100644 --- a/extensions/fairygui/src/fairygui/GImage.cpp +++ b/extensions/fairygui/src/fairygui/GImage.cpp @@ -73,12 +73,12 @@ void GImage::handleGrayedChanged() ((FUISprite*)_content)->setGrayed(_finalGrayed); } -ax::Color3B GImage::getColor() const +ax::Color32 GImage::getColor() const { return _content->getColor(); } -void GImage::setColor(const ax::Color3B& value) +void GImage::setColor(const ax::Color32& value) { _content->setColor(value); } @@ -182,7 +182,7 @@ void GImage::setup_beforeAdd(ByteBuffer* buffer, int beginPos) buffer->seek(beginPos, 5); if (buffer->readBool()) - setColor((Color3B)buffer->readColor()); + setColor(buffer->readColor()); setFlip((FlipType)buffer->readByte()); int fillMethod = buffer->readByte(); if (fillMethod != 0) diff --git a/extensions/fairygui/src/fairygui/GImage.h b/extensions/fairygui/src/fairygui/GImage.h index 9006c5c9ed8a..ce5878e2f065 100644 --- a/extensions/fairygui/src/fairygui/GImage.h +++ b/extensions/fairygui/src/fairygui/GImage.h @@ -3,8 +3,8 @@ #include "FairyGUIMacros.h" #include "GObject.h" -#include "cocos2d.h" -#include "ui/UIScale9Sprite.h" +#include "axmol/cocos2d.h" +#include "axmol/ui/UIScale9Sprite.h" NS_FGUI_BEGIN @@ -21,8 +21,8 @@ class GImage : public GObject FlipType getFlip() const; void setFlip(FlipType value); - ax::Color3B getColor() const; - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); FillMethod getFillMethod() const; void setFillMethod(FillMethod value); diff --git a/extensions/fairygui/src/fairygui/GLabel.cpp b/extensions/fairygui/src/fairygui/GLabel.cpp index c3b1d178adcf..8bc5368ffc45 100644 --- a/extensions/fairygui/src/fairygui/GLabel.cpp +++ b/extensions/fairygui/src/fairygui/GLabel.cpp @@ -48,16 +48,16 @@ void GLabel::setIcon(const std::string & value) updateGear(7); } -ax::Color3B GLabel::getTitleColor() const +ax::Color32 GLabel::getTitleColor() const { GTextField* tf = getTextField(); if (tf) return tf->getColor(); else - return Color3B::BLACK; + return Color32::BLACK; } -void GLabel::setTitleColor(const ax::Color3B & value) +void GLabel::setTitleColor(const ax::Color32 & value) { GTextField* tf = getTextField(); if (tf) @@ -159,7 +159,7 @@ void GLabel::setup_afterAdd(ByteBuffer* buffer, int beginPos) if ((str = buffer->readSP())) setIcon(*str); if (buffer->readBool()) - setTitleColor((Color3B)buffer->readColor()); + setTitleColor(buffer->readColor()); int iv = buffer->readInt(); if (iv != 0) setTitleFontSize(iv); @@ -187,4 +187,4 @@ void GLabel::setup_afterAdd(ByteBuffer* buffer, int beginPos) } } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/GLabel.h b/extensions/fairygui/src/fairygui/GLabel.h index dd6cd45e4685..20e57e7111c2 100644 --- a/extensions/fairygui/src/fairygui/GLabel.h +++ b/extensions/fairygui/src/fairygui/GLabel.h @@ -1,7 +1,7 @@ #ifndef __GLABEL_H__ #define __GLABEL_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GComponent.h" @@ -26,8 +26,8 @@ class GLabel : public GComponent virtual const std::string& getIcon() const override; virtual void setIcon(const std::string& value) override; - ax::Color3B getTitleColor() const; - void setTitleColor(const ax::Color3B& value); + ax::Color32 getTitleColor() const; + void setTitleColor(const ax::Color32& value); int getTitleFontSize() const; void setTitleFontSize(int value); diff --git a/extensions/fairygui/src/fairygui/GList.h b/extensions/fairygui/src/fairygui/GList.h index e55f26084ad4..f1fa183246af 100644 --- a/extensions/fairygui/src/fairygui/GList.h +++ b/extensions/fairygui/src/fairygui/GList.h @@ -4,7 +4,7 @@ #include "FairyGUIMacros.h" #include "GComponent.h" #include "GObjectPool.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GLoader.cpp b/extensions/fairygui/src/fairygui/GLoader.cpp index cd0f1213a40b..671b71c23e35 100644 --- a/extensions/fairygui/src/fairygui/GLoader.cpp +++ b/extensions/fairygui/src/fairygui/GLoader.cpp @@ -108,12 +108,12 @@ const ax::Size & GLoader::getContentSize() return _content->getContentSize(); } -ax::Color3B GLoader::getColor() const +ax::Color32 GLoader::getColor() const { return _content->getColor(); } -void GLoader::setColor(const ax::Color3B& value) +void GLoader::setColor(const ax::Color32& value) { _content->setColor(value); } @@ -565,7 +565,7 @@ void GLoader::setup_beforeAdd(ByteBuffer* buffer, int beginPos) _frame = buffer->readInt(); if (buffer->readBool()) - setColor((Color3B)buffer->readColor()); + setColor(buffer->readColor()); int fillMethod = buffer->readByte(); if (fillMethod != 0) { @@ -600,4 +600,4 @@ GObject* GLoader::hitTest(const Vec2& worldPoint, const Camera* camera) return nullptr; } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/GLoader.h b/extensions/fairygui/src/fairygui/GLoader.h index d97aecefe995..32fab6b0af62 100644 --- a/extensions/fairygui/src/fairygui/GLoader.h +++ b/extensions/fairygui/src/fairygui/GLoader.h @@ -1,7 +1,7 @@ #ifndef __GLOADER_H__ #define __GLOADER_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GObject.h" @@ -42,8 +42,8 @@ class GLoader : public GObject const ax::Size& getContentSize(); - ax::Color3B getColor() const; - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); bool isPlaying() const { return _playing; } void setPlaying(bool value); diff --git a/extensions/fairygui/src/fairygui/GLoader3D.cpp b/extensions/fairygui/src/fairygui/GLoader3D.cpp index 9d7d8e139369..da7437214489 100644 --- a/extensions/fairygui/src/fairygui/GLoader3D.cpp +++ b/extensions/fairygui/src/fairygui/GLoader3D.cpp @@ -24,7 +24,7 @@ GLoader3D::GLoader3D() _playing(true), _frame(0), _loop(false), - _color(255, 255, 255) + _color(Color32::WHITE) { } @@ -102,12 +102,12 @@ void GLoader3D::setShrinkOnly(bool value) } } -ax::Color3B GLoader3D::getColor() const +ax::Color32 GLoader3D::getColor() const { return _color; } -void GLoader3D::setColor(const ax::Color3B& value) +void GLoader3D::setColor(const ax::Color32& value) { _color = value; if (_content != nullptr) @@ -313,7 +313,7 @@ void GLoader3D::clearContent() _container->removeChild(_content); AX_SAFE_RELEASE_NULL(_content); } - + _contentItem = nullptr; } @@ -481,7 +481,7 @@ void GLoader3D::setup_beforeAdd(ByteBuffer* buffer, int beginPos) _loop = buffer->readBool(); if (buffer->readBool()) - setColor((Color3B)buffer->readColor()); + setColor(buffer->readColor()); if (_url.length() > 0) loadContent(); @@ -501,4 +501,4 @@ GObject* GLoader3D::hitTest(const Vec2& worldPoint, const Camera* camera) return nullptr; } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/GLoader3D.h b/extensions/fairygui/src/fairygui/GLoader3D.h index 4ca1c94c7b64..25651b3d2439 100644 --- a/extensions/fairygui/src/fairygui/GLoader3D.h +++ b/extensions/fairygui/src/fairygui/GLoader3D.h @@ -1,7 +1,7 @@ #ifndef __GLOADER3D_H__ #define __GLOADER3D_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GObject.h" @@ -42,8 +42,8 @@ class GLoader3D : public GObject const ax::Node* getContent() { return _content; } void setContent(ax::Node* value); - ax::Color3B getColor() const; - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); bool isPlaying() const { return _playing; } void setPlaying(bool value); @@ -99,7 +99,7 @@ class GLoader3D : public GObject bool _loop; std::string _animationName; std::string _skinName; - ax::Color3B _color; + ax::Color32 _color; FUIContainer* _container; ax::Node* _content; diff --git a/extensions/fairygui/src/fairygui/GMovieClip.cpp b/extensions/fairygui/src/fairygui/GMovieClip.cpp index 667120dae744..48a65997ad78 100644 --- a/extensions/fairygui/src/fairygui/GMovieClip.cpp +++ b/extensions/fairygui/src/fairygui/GMovieClip.cpp @@ -90,7 +90,7 @@ void GMovieClip::setFlip(FlipType value) _content->setFlippedY(value == FlipType::VERTICAL || value == FlipType::BOTH); } -void GMovieClip::setColor(const ax::Color3B& value) +void GMovieClip::setColor(const ax::Color32& value) { _content->setColor(value); } @@ -167,7 +167,7 @@ void GMovieClip::setup_beforeAdd(ByteBuffer* buffer, int beginPos) buffer->seek(beginPos, 5); if (buffer->readBool()) - setColor((Color3B)buffer->readColor()); + setColor(buffer->readColor()); setFlip((FlipType)buffer->readByte()); setFrame(buffer->readInt()); setPlaying(buffer->readBool()); diff --git a/extensions/fairygui/src/fairygui/GMovieClip.h b/extensions/fairygui/src/fairygui/GMovieClip.h index edc39a578e33..5357beb78d19 100644 --- a/extensions/fairygui/src/fairygui/GMovieClip.h +++ b/extensions/fairygui/src/fairygui/GMovieClip.h @@ -1,7 +1,7 @@ #ifndef __GMOVIECLIP_H__ #define __GMOVIECLIP_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GObject.h" @@ -31,8 +31,8 @@ class GMovieClip : public GObject FlipType getFlip() const; void setFlip(FlipType value); - ax::Color3B getColor() const { return _content->getColor(); } - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const { return _content->getColor(); } + void setColor(const ax::Color32& value); //from start to end(-1 means ending) repeat times(0 means infinite loop) when all is over, stopping at endAt(-1 means same value of end) void setPlaySettings(int start = 0, int end = -1, int times = 0, int endAt = -1, std::function completeCallback = nullptr); diff --git a/extensions/fairygui/src/fairygui/GObject.h b/extensions/fairygui/src/fairygui/GObject.h index b2ebd2b0ba61..e40d979066b9 100644 --- a/extensions/fairygui/src/fairygui/GObject.h +++ b/extensions/fairygui/src/fairygui/GObject.h @@ -4,7 +4,7 @@ #include "Controller.h" #include "FairyGUIMacros.h" #include "Relations.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "display/BlendMode.h" #include "event/UIEventDispatcher.h" #include "gears/GearBase.h" diff --git a/extensions/fairygui/src/fairygui/GObjectPool.h b/extensions/fairygui/src/fairygui/GObjectPool.h index 1960f764a69e..6f4603325a62 100644 --- a/extensions/fairygui/src/fairygui/GObjectPool.h +++ b/extensions/fairygui/src/fairygui/GObjectPool.h @@ -2,7 +2,7 @@ #define __GOBJECTPOOL_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GProgressBar.h b/extensions/fairygui/src/fairygui/GProgressBar.h index 47a1dd1029bc..cd8569ba53f2 100644 --- a/extensions/fairygui/src/fairygui/GProgressBar.h +++ b/extensions/fairygui/src/fairygui/GProgressBar.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GComponent.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GRichTextField.h b/extensions/fairygui/src/fairygui/GRichTextField.h index 813266c05e37..dba67eb5945e 100644 --- a/extensions/fairygui/src/fairygui/GRichTextField.h +++ b/extensions/fairygui/src/fairygui/GRichTextField.h @@ -1,7 +1,7 @@ #ifndef __GRICHTEXTFIELD_H__ #define __GRICHTEXTFIELD_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GTextField.h" #include "display/FUIRichText.h" diff --git a/extensions/fairygui/src/fairygui/GRoot.cpp b/extensions/fairygui/src/fairygui/GRoot.cpp index d2855627b8fc..e4eaa4b623d6 100644 --- a/extensions/fairygui/src/fairygui/GRoot.cpp +++ b/extensions/fairygui/src/fairygui/GRoot.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. ****************************************************************************/ #include "GRoot.h" -#include "AudioEngine.h" +#include "axmol/audio/AudioEngine.h" #include "UIConfig.h" #include "UIPackage.h" @@ -167,7 +167,7 @@ void GRoot::createModalLayer() { _modalLayer = GGraph::create(); _modalLayer->retain(); - _modalLayer->drawRect(getWidth(), getHeight(), 0, Color4F::WHITE, UIConfig::modalLayerColor); + _modalLayer->drawRect(getWidth(), getHeight(), 0, ax::Color::WHITE, UIConfig::modalLayerColor); _modalLayer->addRelation(this, RelationType::Size); } diff --git a/extensions/fairygui/src/fairygui/GRoot.h b/extensions/fairygui/src/fairygui/GRoot.h index 07ba2ef15b4e..b0a538229961 100644 --- a/extensions/fairygui/src/fairygui/GRoot.h +++ b/extensions/fairygui/src/fairygui/GRoot.h @@ -5,7 +5,7 @@ #include "GComponent.h" #include "GGraph.h" #include "Window.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "event/InputProcessor.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GScrollBar.h b/extensions/fairygui/src/fairygui/GScrollBar.h index 824a8f67ac01..6e468dfbc346 100644 --- a/extensions/fairygui/src/fairygui/GScrollBar.h +++ b/extensions/fairygui/src/fairygui/GScrollBar.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GComponent.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GSlider.h b/extensions/fairygui/src/fairygui/GSlider.h index a4d513d3eddb..860e19105e37 100644 --- a/extensions/fairygui/src/fairygui/GSlider.h +++ b/extensions/fairygui/src/fairygui/GSlider.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GComponent.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GTextField.cpp b/extensions/fairygui/src/fairygui/GTextField.cpp index 47b80c838559..0e5665ca7a14 100644 --- a/extensions/fairygui/src/fairygui/GTextField.cpp +++ b/extensions/fairygui/src/fairygui/GTextField.cpp @@ -35,7 +35,7 @@ void GTextField::setUBBEnabled(bool value) } } -void GTextField::setColor(const ax::Color3B& value) +void GTextField::setColor(const ax::Color32& value) { TextFormat* tf = getTextFormat(); if (tf->color != value) @@ -55,7 +55,7 @@ void GTextField::setFontSize(float value) } } -void GTextField::setOutlineColor(const ax::Color3B& value) +void GTextField::setOutlineColor(const ax::Color32& value) { TextFormat* tf = getTextFormat(); if (tf->outlineColor != value) @@ -146,7 +146,7 @@ void GTextField::setup_beforeAdd(ByteBuffer* buffer, int beginPos) tf->face = buffer->readS(); tf->fontSize = buffer->readShort(); - tf->color = (Color3B)buffer->readColor(); + tf->color = buffer->readColor(); tf->align = (TextHAlignment)buffer->readByte(); tf->verticalAlign = (TextVAlignment)buffer->readByte(); tf->lineSpacing = buffer->readShort(); @@ -160,14 +160,14 @@ void GTextField::setup_beforeAdd(ByteBuffer* buffer, int beginPos) setSingleLine(true); if (buffer->readBool()) { - tf->outlineColor = (Color3B)buffer->readColor(); + tf->outlineColor = buffer->readColor(); tf->outlineSize = buffer->readFloat(); tf->enableEffect(TextFormat::OUTLINE); } if (buffer->readBool()) { - tf->shadowColor = (Color3B)buffer->readColor(); + tf->shadowColor = buffer->readColor(); float f1 = buffer->readFloat(); float f2 = buffer->readFloat(); tf->shadowOffset = Vec2(f1, -f2); diff --git a/extensions/fairygui/src/fairygui/GTextField.h b/extensions/fairygui/src/fairygui/GTextField.h index 068d7fe49bbb..4da38c766677 100644 --- a/extensions/fairygui/src/fairygui/GTextField.h +++ b/extensions/fairygui/src/fairygui/GTextField.h @@ -1,7 +1,7 @@ #ifndef __GTEXTFIELD_H__ #define __GTEXTFIELD_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GObject.h" #include "display/FUILabel.h" @@ -31,14 +31,14 @@ class GTextField : public GObject virtual const ax::Size& getTextSize() { return _displayObject->getContentSize(); } - ax::Color3B getColor() const { return getTextFormat()->color; } - void setColor(const ax::Color3B& value); + ax::Color32 getColor() const { return getTextFormat()->color; } + void setColor(const ax::Color32& value); float getFontSize() const { return getTextFormat()->fontSize; } void setFontSize(float value); - ax::Color3B getOutlineColor() const { return getTextFormat()->outlineColor; } - void setOutlineColor(const ax::Color3B& value); + ax::Color32 getOutlineColor() const { return getTextFormat()->outlineColor; } + void setOutlineColor(const ax::Color32& value); ax::ValueMap* getTemplateVars() { return _templateVars; } void setTemplateVars(ax::ValueMap* value); diff --git a/extensions/fairygui/src/fairygui/GTextInput.cpp b/extensions/fairygui/src/fairygui/GTextInput.cpp index fb6252fd0cfa..04c45f3cf9de 100644 --- a/extensions/fairygui/src/fairygui/GTextInput.cpp +++ b/extensions/fairygui/src/fairygui/GTextInput.cpp @@ -1,7 +1,7 @@ #include "GTextInput.h" #include "UIPackage.h" #include "GRoot.h" -#include "ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" #include "utils/ByteBuffer.h" #include "utils/UBBParser.h" #include "utils/ToolSet.h" diff --git a/extensions/fairygui/src/fairygui/GTextInput.h b/extensions/fairygui/src/fairygui/GTextInput.h index 0519f5e06651..ee0c4802bc21 100644 --- a/extensions/fairygui/src/fairygui/GTextInput.h +++ b/extensions/fairygui/src/fairygui/GTextInput.h @@ -1,7 +1,7 @@ #ifndef __GTEXTINPUT_H__ #define __GTEXTINPUT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GTextField.h" #include "display/FUIInput.h" diff --git a/extensions/fairygui/src/fairygui/GTree.h b/extensions/fairygui/src/fairygui/GTree.h index 222db93640a9..6b7fc67faafd 100644 --- a/extensions/fairygui/src/fairygui/GTree.h +++ b/extensions/fairygui/src/fairygui/GTree.h @@ -4,7 +4,7 @@ #include "FairyGUIMacros.h" #include "GList.h" #include "GTreeNode.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/GTreeNode.h b/extensions/fairygui/src/fairygui/GTreeNode.h index cacbb3f051d5..f7fa4950ec84 100644 --- a/extensions/fairygui/src/fairygui/GTreeNode.h +++ b/extensions/fairygui/src/fairygui/GTreeNode.h @@ -2,7 +2,7 @@ #define __GTREENODE_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/PackageItem.h b/extensions/fairygui/src/fairygui/PackageItem.h index a4ce4427c164..24b3262a1588 100644 --- a/extensions/fairygui/src/fairygui/PackageItem.h +++ b/extensions/fairygui/src/fairygui/PackageItem.h @@ -2,7 +2,7 @@ #define __PACKAGEITEM_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/PopupMenu.h b/extensions/fairygui/src/fairygui/PopupMenu.h index 059d202b1460..7cf9d612333d 100644 --- a/extensions/fairygui/src/fairygui/PopupMenu.h +++ b/extensions/fairygui/src/fairygui/PopupMenu.h @@ -2,7 +2,7 @@ #define __POPUPMENU_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "event/UIEventDispatcher.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/RelationItem.h b/extensions/fairygui/src/fairygui/RelationItem.h index ef34117d9dba..5f982f55b520 100644 --- a/extensions/fairygui/src/fairygui/RelationItem.h +++ b/extensions/fairygui/src/fairygui/RelationItem.h @@ -1,7 +1,7 @@ #ifndef __RELATIONITEM_H__ #define __RELATIONITEM_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "utils/WeakPtr.h" diff --git a/extensions/fairygui/src/fairygui/Relations.h b/extensions/fairygui/src/fairygui/Relations.h index 4c440300a073..237ad06526fe 100644 --- a/extensions/fairygui/src/fairygui/Relations.h +++ b/extensions/fairygui/src/fairygui/Relations.h @@ -1,7 +1,7 @@ #ifndef __RELATIONS_H__ #define __RELATIONS_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "RelationItem.h" diff --git a/extensions/fairygui/src/fairygui/ScrollPane.h b/extensions/fairygui/src/fairygui/ScrollPane.h index 39fe78c9fb3f..98c037495481 100644 --- a/extensions/fairygui/src/fairygui/ScrollPane.h +++ b/extensions/fairygui/src/fairygui/ScrollPane.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "Margin.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/Transition.cpp b/extensions/fairygui/src/fairygui/Transition.cpp index 2915549ce4b5..7150eafc159e 100644 --- a/extensions/fairygui/src/fairygui/Transition.cpp +++ b/extensions/fairygui/src/fairygui/Transition.cpp @@ -79,8 +79,8 @@ class TValue : public TValueBase void setVec2(const ax::Vec2& value); ax::Vec4 getVec4() const; void setVec4(const ax::Vec4& value); - ax::Color4B getColor() const; - void setColor(const ax::Color4B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); }; TValue::TValue() @@ -114,12 +114,12 @@ void TValue::setVec4(const ax::Vec4& value) f4 = value.w; } -ax::Color4B TValue::getColor() const +ax::Color32 TValue::getColor() const { - return ax::Color4B(f1, f2, f3, f4); + return ax::Color32(f1, f2, f3, f4); } -void TValue::setColor(const ax::Color4B& value) +void TValue::setColor(const ax::Color32& value) { f1 = value.r; f2 = value.g; @@ -551,7 +551,7 @@ void Transition::setValue(const std::string& label, const ValueVector& values) case TransitionActionType::Color: { uint32_t v = values[0].asUnsignedInt(); - ((TValue*)value)->setColor(Color4B((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, (v >> 24) & 0xFF)); + ((TValue*)value)->setColor(Color32((v >> 16) & 0xFF, (v >> 8) & 0xFF, v & 0xFF, (v >> 24) & 0xFF)); break; } @@ -1275,7 +1275,7 @@ void Transition::applyValue(TransitionItem* item) break; case TransitionActionType::Color: - item->target->setProp(ObjectPropID::Color, Value(ToolSet::colorToInt((Color3B)((TValue*)item->value)->getColor()))); + item->target->setProp(ObjectPropID::Color, Value(ToolSet::colorToInt(((TValue*)item->value)->getColor()))); break; case TransitionActionType::Animation: diff --git a/extensions/fairygui/src/fairygui/Transition.h b/extensions/fairygui/src/fairygui/Transition.h index 5d910f13fc83..4aad1c780468 100644 --- a/extensions/fairygui/src/fairygui/Transition.h +++ b/extensions/fairygui/src/fairygui/Transition.h @@ -2,7 +2,7 @@ #define __TRANSITION_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/TranslationHelper.cpp b/extensions/fairygui/src/fairygui/TranslationHelper.cpp index d0e140298c01..06eed347d3b2 100644 --- a/extensions/fairygui/src/fairygui/TranslationHelper.cpp +++ b/extensions/fairygui/src/fairygui/TranslationHelper.cpp @@ -8,7 +8,7 @@ #endif #include "utils/ByteBuffer.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/TranslationHelper.h b/extensions/fairygui/src/fairygui/TranslationHelper.h index 970d8264ebb2..30e041e18841 100644 --- a/extensions/fairygui/src/fairygui/TranslationHelper.h +++ b/extensions/fairygui/src/fairygui/TranslationHelper.h @@ -2,7 +2,7 @@ #define __TRANSLATIONHELPER_H_ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/UIConfig.cpp b/extensions/fairygui/src/fairygui/UIConfig.cpp index 99a9559835b8..fd27f0882f4d 100644 --- a/extensions/fairygui/src/fairygui/UIConfig.cpp +++ b/extensions/fairygui/src/fairygui/UIConfig.cpp @@ -19,7 +19,7 @@ int UIConfig::touchScrollSensitivity = 20; int UIConfig::defaultComboBoxVisibleItemCount = 10; std::string UIConfig::globalModalWaiting = ""; std::string UIConfig::tooltipsWin = ""; -Color4F UIConfig::modalLayerColor = Color4F(0, 0, 0, 0.4f); +ax::Color UIConfig::modalLayerColor = ax::Color(0, 0, 0, 0.4f); bool UIConfig::bringWindowToFrontOnClick = true; std::string UIConfig::windowModalWaiting = ""; std::string UIConfig::popupMenu = ""; diff --git a/extensions/fairygui/src/fairygui/UIConfig.h b/extensions/fairygui/src/fairygui/UIConfig.h index c9b0956d68ba..e1d0540470e2 100644 --- a/extensions/fairygui/src/fairygui/UIConfig.h +++ b/extensions/fairygui/src/fairygui/UIConfig.h @@ -1,7 +1,7 @@ #ifndef __UICONFIG_H__ #define __UICONFIG_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -24,7 +24,7 @@ class UIConfig static int touchScrollSensitivity; static int defaultComboBoxVisibleItemCount; static std::string globalModalWaiting; - static ax::Color4F modalLayerColor; + static ax::Color modalLayerColor; static std::string tooltipsWin; static bool bringWindowToFrontOnClick; static std::string windowModalWaiting; diff --git a/extensions/fairygui/src/fairygui/UIObjectFactory.h b/extensions/fairygui/src/fairygui/UIObjectFactory.h index f8a71d3abd0f..c5ccc408e0b9 100644 --- a/extensions/fairygui/src/fairygui/UIObjectFactory.h +++ b/extensions/fairygui/src/fairygui/UIObjectFactory.h @@ -1,7 +1,7 @@ #ifndef __UIOBJECTFACTORY_H__ #define __UIOBJECTFACTORY_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "GComponent.h" #include "PackageItem.h" diff --git a/extensions/fairygui/src/fairygui/UIPackage.cpp b/extensions/fairygui/src/fairygui/UIPackage.cpp index d461b270ba98..ced2efca7520 100644 --- a/extensions/fairygui/src/fairygui/UIPackage.cpp +++ b/extensions/fairygui/src/fairygui/UIPackage.cpp @@ -646,7 +646,7 @@ void UIPackage::loadAtlas(PackageItem* item) #if defined(AX_VERSION) if(image->getFileType() == Image::Format::ETC1) - tex->updateWithImage(image, Texture2D::getDefaultAlphaPixelFormat(), 1); + tex->updateWithImage(image, 1); #else tex = new Texture2D(); tex->initWithImage(image); @@ -692,11 +692,12 @@ void UIPackage::loadImage(PackageItem* item) } if (item->scaleByTile) { -#if COCOS2D_VERSION >= 0x00040000 - Texture2D::TexParams tp(backend::SamplerFilter::LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::REPEAT, backend::SamplerAddressMode::REPEAT); +#if AX_VERSION >= 0x00030000 + Texture2D::TexParams tp{.sAddressMode = rhi::SamplerAddressMode::REPEAT, + .tAddressMode = rhi::SamplerAddressMode::REPEAT}; #else - Texture2D::TexParams tp = { GL_LINEAR, GL_LINEAR, GL_REPEAT, GL_REPEAT }; + Texture2D::TexParams tp(SamplerFilter::LINEAR, SamplerFilter::LINEAR, SamplerAddressMode::REPEAT, + SamplerAddressMode::REPEAT); #endif item->spriteFrame->getTexture()->setTexParameters(tp); } diff --git a/extensions/fairygui/src/fairygui/UIPackage.h b/extensions/fairygui/src/fairygui/UIPackage.h index 0e182bd08192..2655b4ee29d0 100644 --- a/extensions/fairygui/src/fairygui/UIPackage.h +++ b/extensions/fairygui/src/fairygui/UIPackage.h @@ -4,7 +4,7 @@ #include "FairyGUIMacros.h" #include "GObject.h" #include "PackageItem.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/Window.cpp b/extensions/fairygui/src/fairygui/Window.cpp index 0bfa3d08030a..9d5df7faac57 100644 --- a/extensions/fairygui/src/fairygui/Window.cpp +++ b/extensions/fairygui/src/fairygui/Window.cpp @@ -102,7 +102,7 @@ void Window::setDragArea(GObject * value) { _dragArea->retain(); if (dynamic_cast(_dragArea) && ((GGraph*)_dragArea)->isEmpty()) - ((GGraph*)_dragArea)->drawRect(_dragArea->getWidth(), _dragArea->getHeight(), 0, Color4F(0, 0, 0, 0), Color4F(0, 0, 0, 0)); + ((GGraph*)_dragArea)->drawRect(_dragArea->getWidth(), _dragArea->getHeight(), 0, ax::Color(0, 0, 0, 0), ax::Color(0, 0, 0, 0)); _dragArea->setDraggable(true); _dragArea->addEventListener(UIEventType::DragStart, AX_CALLBACK_1(Window::onDragStart, this), EventTag(this)); } diff --git a/extensions/fairygui/src/fairygui/Window.h b/extensions/fairygui/src/fairygui/Window.h index 8830528c9deb..6bda5f8abe56 100644 --- a/extensions/fairygui/src/fairygui/Window.h +++ b/extensions/fairygui/src/fairygui/Window.h @@ -2,7 +2,7 @@ #define __WINDOW_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GComponent.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/controller_action/ChangePageAction.cpp b/extensions/fairygui/src/fairygui/controller_action/ChangePageAction.cpp index 0c9822b31120..6e9b4c1d5ba4 100644 --- a/extensions/fairygui/src/fairygui/controller_action/ChangePageAction.cpp +++ b/extensions/fairygui/src/fairygui/controller_action/ChangePageAction.cpp @@ -47,4 +47,4 @@ void ChangePageAction::leave(GController* controller) { } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/controller_action/ControllerAction.h b/extensions/fairygui/src/fairygui/controller_action/ControllerAction.h index ef44cc92f9d7..b07d1b2db338 100644 --- a/extensions/fairygui/src/fairygui/controller_action/ControllerAction.h +++ b/extensions/fairygui/src/fairygui/controller_action/ControllerAction.h @@ -2,7 +2,7 @@ #define __CONTROLLERACTION_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/controller_action/PlayTransitionAction.cpp b/extensions/fairygui/src/fairygui/controller_action/PlayTransitionAction.cpp index feed2ae743bb..f2d6e851a21b 100644 --- a/extensions/fairygui/src/fairygui/controller_action/PlayTransitionAction.cpp +++ b/extensions/fairygui/src/fairygui/controller_action/PlayTransitionAction.cpp @@ -43,4 +43,4 @@ void PlayTransitionAction::leave(GController * controller) } } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/display/BitmapFont.h b/extensions/fairygui/src/fairygui/display/BitmapFont.h index 420c48343d49..d08cd9efb3bf 100644 --- a/extensions/fairygui/src/fairygui/display/BitmapFont.h +++ b/extensions/fairygui/src/fairygui/display/BitmapFont.h @@ -2,7 +2,7 @@ #define __BITMAPFONT_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "PackageItem.h" NS_FGUI_BEGIN @@ -48,4 +48,4 @@ class BitmapFont : public ax::Font NS_FGUI_END -#endif \ No newline at end of file +#endif diff --git a/extensions/fairygui/src/fairygui/display/BlendMode.cpp b/extensions/fairygui/src/fairygui/display/BlendMode.cpp index fca083238e55..62ec66d6f348 100644 --- a/extensions/fairygui/src/fairygui/display/BlendMode.cpp +++ b/extensions/fairygui/src/fairygui/display/BlendMode.cpp @@ -1,5 +1,4 @@ #include "BlendMode.h" -#include "renderer/backend/Enums.h" NS_FGUI_BEGIN using namespace ax; @@ -7,18 +6,18 @@ using namespace ax; namespace { std::vector blendModes { - {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // normal - {backend::BlendFactor::ONE, backend::BlendFactor::ONE}, // none - {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE}, // add - {backend::BlendFactor::DST_COLOR, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // mul - {backend::BlendFactor::ONE, backend::BlendFactor::ONE_MINUS_SRC_COLOR}, // screen - {backend::BlendFactor::ZERO, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // erase - {backend::BlendFactor::ZERO, backend::BlendFactor::SRC_ALPHA}, // mask - {backend::BlendFactor::ONE_MINUS_DST_ALPHA, backend::BlendFactor::DST_ALPHA}, // below - {backend::BlendFactor::ONE, backend::BlendFactor::ZERO}, // off - {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom1 - {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom2 - {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom2 + {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // normal + {rhi::BlendFactor::ONE, rhi::BlendFactor::ONE}, // none + {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE}, // add + {rhi::BlendFactor::DST_COLOR, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // mul + {rhi::BlendFactor::ONE, rhi::BlendFactor::ONE_MINUS_SRC_COLOR}, // screen + {rhi::BlendFactor::ZERO, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // erase + {rhi::BlendFactor::ZERO, rhi::BlendFactor::SRC_ALPHA}, // mask + {rhi::BlendFactor::ONE_MINUS_DST_ALPHA, rhi::BlendFactor::DST_ALPHA}, // below + {rhi::BlendFactor::ONE, rhi::BlendFactor::ZERO}, // off + {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom1 + {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom2 + {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}, // custom2 }; } @@ -58,8 +57,8 @@ void BlendModeUtils::apply(ax::Node* node, const ax::BlendFunc& blendFunc) } void BlendModeUtils::overrideBlendMode(BlendMode blendMode, - ax::backend::BlendFactor srcFactor, - ax::backend::BlendFactor dstFactor) + ax::rhi::BlendFactor srcFactor, + ax::rhi::BlendFactor dstFactor) { auto blendIndex = static_cast(blendMode); if (blendIndex >= blendModes.size()) diff --git a/extensions/fairygui/src/fairygui/display/BlendMode.h b/extensions/fairygui/src/fairygui/display/BlendMode.h index 1019ca29149e..eb80d6c3a531 100644 --- a/extensions/fairygui/src/fairygui/display/BlendMode.h +++ b/extensions/fairygui/src/fairygui/display/BlendMode.h @@ -1,5 +1,7 @@ #pragma once -#include "cocos2d.h" + +#include "axmol/2d/Node.h" +#include "axmol/base/Types.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -25,8 +27,8 @@ class BlendModeUtils public: static void apply(ax::Node* node, BlendMode blendMode); static void overrideBlendMode(BlendMode blendMode, - ax::backend::BlendFactor srcFactor, - ax::backend::BlendFactor dstFactor); + ax::rhi::BlendFactor srcFactor, + ax::rhi::BlendFactor dstFactor); protected: static void apply(ax::Node* node, const ax::BlendFunc& blendFunc); diff --git a/extensions/fairygui/src/fairygui/display/FUIContainer.cpp b/extensions/fairygui/src/fairygui/display/FUIContainer.cpp index a71c14d444df..5476e12ce584 100644 --- a/extensions/fairygui/src/fairygui/display/FUIContainer.cpp +++ b/extensions/fairygui/src/fairygui/display/FUIContainer.cpp @@ -1,5 +1,5 @@ #include "FUIContainer.h" -#include "base/StencilStateManager.h" +#include "axmol/base/StencilStateManager.h" #include "utils/ToolSet.h" #include "GComponent.h" @@ -286,7 +286,7 @@ void FUIContainer::setCameraMask(unsigned short mask, bool applyChildren) } #if COCOS2D_VERSION >= 0x00040000 -void FUIContainer::setProgramStateRecursively(Node* node, backend::ProgramState* programState) +void FUIContainer::setProgramStateRecursively(Node* node, rhi::ProgramState* programState) { _originalStencilProgramState[node] = node->getProgramState(); node->setProgramState(programState); @@ -410,8 +410,8 @@ void FUIContainer::visit(ax::Renderer * renderer, const ax::Mat4 & parentTransfo if (alphaThreshold < 1) { #if COCOS2D_VERSION >= 0x00040000 - auto* program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); - auto programState = new backend::ProgramState(program); + auto* program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); + auto programState = new rhi::ProgramState(program); auto alphaLocation = programState->getUniformLocation("u_alpha_value"); programState->setUniform(alphaLocation, &alphaThreshold, sizeof(alphaThreshold)); setProgramStateRecursively(_stencilClippingSupport->_stencil, programState); diff --git a/extensions/fairygui/src/fairygui/display/FUIContainer.h b/extensions/fairygui/src/fairygui/display/FUIContainer.h index 6c0bb1aec689..45308ffd0aa1 100644 --- a/extensions/fairygui/src/fairygui/display/FUIContainer.h +++ b/extensions/fairygui/src/fairygui/display/FUIContainer.h @@ -1,7 +1,7 @@ #ifndef __FUICONTAINER_H__ #define __FUICONTAINER_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -39,11 +39,11 @@ class StencilClippingSupport ax::Node* _stencil; ax::StencilStateManager* _stencilStateManager; -#if !defined(AX_VERSION) +#if !defined(AX_VERSION) ax::GroupCommand _groupCommand; #endif #if COCOS2D_VERSION >= 0x00040000 - ax::backend::ProgramState* _originStencilProgram; + ax::rhi::ProgramState* _originStencilProgram; //ax::CallbackCommand _beforeVisitCmd; //ax::CallbackCommand _afterDrawStencilCmd; //ax::CallbackCommand _afterVisitCmd; @@ -91,12 +91,12 @@ class FUIContainer : public ax::Node RectClippingSupport* _rectClippingSupport; StencilClippingSupport* _stencilClippingSupport; - + #if COCOS2D_VERSION >= 0x00040000 - void setProgramStateRecursively(Node* node, ax::backend::ProgramState* programState); + void setProgramStateRecursively(Node* node, ax::rhi::ProgramState* programState); void restoreAllProgramStates(); - - std::unordered_map _originalStencilProgramState; + + std::unordered_map _originalStencilProgramState; #endif }; diff --git a/extensions/fairygui/src/fairygui/display/FUIInput.h b/extensions/fairygui/src/fairygui/display/FUIInput.h index 89bc0c201627..a2b82613bbf7 100644 --- a/extensions/fairygui/src/fairygui/display/FUIInput.h +++ b/extensions/fairygui/src/fairygui/display/FUIInput.h @@ -1,9 +1,9 @@ #ifndef __FUIINPUT_H__ #define __FUIINPUT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" -#include "ui/UIEditBox/UIEditBox.h" +#include "axmol/ui/UIEditBox/UIEditBox.h" #include "TextFormat.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/display/FUILabel.cpp b/extensions/fairygui/src/fairygui/display/FUILabel.cpp index 2fcc28b2f752..a3fb5c871c1e 100644 --- a/extensions/fairygui/src/fairygui/display/FUILabel.cpp +++ b/extensions/fairygui/src/fairygui/display/FUILabel.cpp @@ -6,10 +6,11 @@ NS_FGUI_BEGIN using namespace ax; -static Color3B toGrayed(const Color3B& source) +static Color32 toGrayed(const Color32& source) { - Color3B c = source; + Color32 c = source; c.r = c.g = c.b = c.r * 0.299f + c.g * 0.587f + c.b * 0.114f; + c.a = source.a; // keep alpha return c; } @@ -60,7 +61,7 @@ void FUILabel::applyTextFormat() } if (oldType == LabelType::BMFONT) - setTextColor((Color4B)_textFormat->color); + setTextColor((Color32)_textFormat->color); } } @@ -86,7 +87,7 @@ void FUILabel::applyTextFormat() if (_currentLabelType != LabelType::BMFONT || _bmFontCanTint) { - //setTextColor((Color4B)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color)); + //setTextColor((Color32)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color)); setColor(_grayed ? toGrayed(_textFormat->color) : _textFormat->color); } @@ -110,12 +111,12 @@ void FUILabel::applyTextFormat() setVerticalAlignment(_textFormat->verticalAlign); if (_textFormat->hasEffect(TextFormat::OUTLINE)) - enableOutline((Color4B)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize); + enableOutline((Color32)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize); else disableEffect(LabelEffect::OUTLINE); if (_textFormat->hasEffect(TextFormat::SHADOW)) - enableShadow((Color4B)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset); + enableShadow((Color32)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset); else if (!_textFormat->bold) disableEffect(LabelEffect::SHADOW); } @@ -164,15 +165,15 @@ void FUILabel::setGrayed(bool value) _grayed = value; if (_currentLabelType != LabelType::BMFONT) - setTextColor((Color4B)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color)); + setTextColor((Color32)(_grayed ? toGrayed(_textFormat->color) : _textFormat->color)); else if (_bmFontCanTint) setColor(_grayed ? toGrayed(_textFormat->color) : _textFormat->color); if (_textFormat->hasEffect(TextFormat::OUTLINE)) - enableOutline((Color4B)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize); + enableOutline((Color32)(_grayed ? toGrayed(_textFormat->outlineColor) : _textFormat->outlineColor), _textFormat->outlineSize); if (_textFormat->hasEffect(TextFormat::SHADOW)) - enableShadow((Color4B)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset); + enableShadow((Color32)(_grayed ? toGrayed(_textFormat->shadowColor) : _textFormat->shadowColor), _textFormat->shadowOffset); } } @@ -191,7 +192,7 @@ void FUILabel::updateFontScale() } } -void FUILabel::setUnderlineColor(const ax::Color3B& value) +void FUILabel::setUnderlineColor(const ax::Color32& value) { //NOT IMPLEMENTED } diff --git a/extensions/fairygui/src/fairygui/display/FUILabel.h b/extensions/fairygui/src/fairygui/display/FUILabel.h index fd780897396f..df7d10dca983 100644 --- a/extensions/fairygui/src/fairygui/display/FUILabel.h +++ b/extensions/fairygui/src/fairygui/display/FUILabel.h @@ -1,7 +1,7 @@ #ifndef __FUILABEL_H__ #define __FUILABEL_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "TextFormat.h" @@ -21,7 +21,7 @@ class FUILabel : public ax::Label TextFormat* getTextFormat() const { return _textFormat; } void applyTextFormat(); - void setUnderlineColor(const ax::Color3B& value); + void setUnderlineColor(const ax::Color32& value); #if defined(AX_VERSION) bool setBMFontFilePath(std::string_view bmfontFilePath, diff --git a/extensions/fairygui/src/fairygui/display/FUIRichText.cpp b/extensions/fairygui/src/fairygui/display/FUIRichText.cpp index 0f7ed3789b6c..ae40027b2415 100644 --- a/extensions/fairygui/src/fairygui/display/FUIRichText.cpp +++ b/extensions/fairygui/src/fairygui/display/FUIRichText.cpp @@ -90,7 +90,7 @@ static float stripTrailingWhitespace(const std::vector& row) { static std::string getSubStringOfUTF8String(const std::string& str, std::string::size_type start, std::string::size_type length) { std::u32string utf32; - if (!StringUtils::UTF8ToUTF32(str, utf32)) { + if (!text_utils::UTF8ToUTF32(str, utf32)) { AXLOGE("Can't convert string to UTF-32: {}", str); return ""; } @@ -99,7 +99,7 @@ static std::string getSubStringOfUTF8String(const std::string& str, std::string: return ""; } std::string result; - if (!StringUtils::UTF32ToUTF8(utf32.substr(start, length), result)) { + if (!text_utils::UTF32ToUTF8(utf32.substr(start, length), result)) { AXLOGE("Can't convert internal UTF-32 string to UTF-8: {}", str); return ""; } @@ -196,12 +196,12 @@ void FUIRichText::setAnchorTextUnderline(bool enable) } } -const ax::Color3B& FUIRichText::getAnchorFontColor() +const ax::Color32& FUIRichText::getAnchorFontColor() { return _parseOptions.linkColor; } -void FUIRichText::setAnchorFontColor(const ax::Color3B & color) +void FUIRichText::setAnchorFontColor(const ax::Color32 & color) { _parseOptions.linkColor = color; _formatTextDirty = true; diff --git a/extensions/fairygui/src/fairygui/display/FUIRichText.h b/extensions/fairygui/src/fairygui/display/FUIRichText.h index d2d1ec53502d..7dafa47331a8 100644 --- a/extensions/fairygui/src/fairygui/display/FUIRichText.h +++ b/extensions/fairygui/src/fairygui/display/FUIRichText.h @@ -1,7 +1,7 @@ #ifndef __FUIRICHTEXT_H__ #define __FUIRICHTEXT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "TextFormat.h" #include "utils/html/HtmlParser.h" @@ -32,8 +32,8 @@ class FUIRichText : public ax::Node bool isAnchorTextUnderline(); void setAnchorTextUnderline(bool enable); - const ax::Color3B& getAnchorFontColor(); - void setAnchorFontColor(const ax::Color3B& color); + const ax::Color32& getAnchorFontColor(); + void setAnchorFontColor(const ax::Color32& color); void setObjectFactory(const std::function& value) { _objectFactory = value; } HtmlParseOptions& parseOptions() { return _parseOptions; } diff --git a/extensions/fairygui/src/fairygui/display/FUISprite.cpp b/extensions/fairygui/src/fairygui/display/FUISprite.cpp index e7b2badeadd9..24b158c12240 100644 --- a/extensions/fairygui/src/fairygui/display/FUISprite.cpp +++ b/extensions/fairygui/src/fairygui/display/FUISprite.cpp @@ -101,7 +101,7 @@ void FUISprite::setScaleByTile(bool value) void FUISprite::setGrayed(bool value) { #if defined(AX_VERSION) - Sprite::setProgramState(value ? backend::ProgramType::GRAY_SCALE : backend::ProgramType::POSITION_TEXTURE_COLOR); + Sprite::setProgramState(value ? rhi::ProgramType::GRAY_SCALE : rhi::ProgramType::POSITION_TEXTURE_COLOR); #elif COCOS2D_VERSION >= 0x00040000 auto isETC1 = getTexture() && getTexture()->getAlphaTextureName(); if (value) { @@ -193,9 +193,9 @@ Tex2F FUISprite::textureCoordFromAlphaPoint(Vec2 alpha) { Tex2F ret(0.0f, 0.0f); - V3F_C4B_T2F_Quad quad = getQuad(); - Vec2 min(quad.bl.texCoords.u, quad.bl.texCoords.v); - Vec2 max(quad.tr.texCoords.u, quad.tr.texCoords.v); + auto& quad = getQuad(); + Vec2 min(quad.bl.texCoord.u, quad.bl.texCoord.v); + Vec2 max(quad.tr.texCoord.u, quad.tr.texCoord.v); // Fix bug #1303 so that progress timer handles sprite frame texture rotation if (isTextureRectRotated()) { @@ -208,9 +208,9 @@ Vec3 FUISprite::vertexFromAlphaPoint(Vec2 alpha) { Vec3 ret(0.0f, 0.0f, 0.0f); - V3F_C4B_T2F_Quad quad = getQuad(); - Vec2 min(quad.bl.vertices.x, quad.bl.vertices.y); - Vec2 max(quad.tr.vertices.x, quad.tr.vertices.y); + auto& quad = getQuad(); + Vec2 min(quad.bl.position.x, quad.bl.position.y); + Vec2 max(quad.tr.position.x, quad.tr.position.y); ret.x = min.x * (1.f - alpha.x) + max.x * alpha.x; ret.y = min.y * (1.f - alpha.y) + max.y * alpha.y; return ret; @@ -222,10 +222,10 @@ void FUISprite::updateColor(void) if (_vertexData) { - Color4B sc = getQuad().tl.colors; + auto& sc = getQuad().tl.color; for (int i = 0; i < _vertexDataCount; ++i) { - _vertexData[i].colors = sc; + _vertexData[i].color = sc; } } } @@ -344,7 +344,7 @@ void FUISprite::updateRadial(void) { _vertexDataCount = index + 3; triangleCount = _vertexDataCount - 2; - _vertexData = (V3F_C4B_T2F*)malloc(_vertexDataCount * sizeof(*_vertexData)); + _vertexData = (V3F_T2F_C4B*)malloc(_vertexDataCount * sizeof(*_vertexData)); _vertexIndex = (unsigned short *)malloc(triangleCount * 3 * sizeof(*_vertexIndex)); AXASSERT(_vertexData, "FUISprite. Not enough memory"); } @@ -352,7 +352,7 @@ void FUISprite::updateRadial(void) { triangleCount = _vertexDataCount - 2; } - + updateColor(); if (!sameIndexCount) @@ -360,30 +360,30 @@ void FUISprite::updateRadial(void) // First we populate the array with the _midpoint, then all // vertices/texcoords/colors of the 12 'o clock start and edges and the hitpoint - _vertexData[0].texCoords = textureCoordFromAlphaPoint(midpoint); - _vertexData[0].vertices = vertexFromAlphaPoint(midpoint); + _vertexData[0].texCoord = textureCoordFromAlphaPoint(midpoint); + _vertexData[0].position = vertexFromAlphaPoint(midpoint); - _vertexData[1].texCoords = textureCoordFromAlphaPoint(topMid); - _vertexData[1].vertices = vertexFromAlphaPoint(topMid); + _vertexData[1].texCoord = textureCoordFromAlphaPoint(topMid); + _vertexData[1].position = vertexFromAlphaPoint(topMid); for (int i = 0; i < index; ++i) { Vec2 alphaPoint = boundaryTexCoord(i); - _vertexData[i + 2].texCoords = textureCoordFromAlphaPoint(alphaPoint); - _vertexData[i + 2].vertices = vertexFromAlphaPoint(alphaPoint); + _vertexData[i + 2].texCoord = textureCoordFromAlphaPoint(alphaPoint); + _vertexData[i + 2].position = vertexFromAlphaPoint(alphaPoint); } } // hitpoint will go last - _vertexData[_vertexDataCount - 1].texCoords = textureCoordFromAlphaPoint(hit); - _vertexData[_vertexDataCount - 1].vertices = vertexFromAlphaPoint(hit); - + _vertexData[_vertexDataCount - 1].texCoord = textureCoordFromAlphaPoint(hit); + _vertexData[_vertexDataCount - 1].position = vertexFromAlphaPoint(hit); + for (int i = 0; i < triangleCount; i++) { _vertexIndex[i * 3] = 0; _vertexIndex[i * 3 + 1] = i + 1; _vertexIndex[i * 3 + 2] = i + 2; } - + _fillTriangles.verts = _vertexData; _fillTriangles.vertCount = _vertexDataCount; _fillTriangles.indices = _vertexIndex; @@ -433,33 +433,33 @@ void FUISprite::updateBar(void) if (!_vertexData) { _vertexDataCount = 4; - _vertexData = (V3F_C4B_T2F*)malloc(_vertexDataCount * sizeof(*_vertexData)); + _vertexData = (V3F_T2F_C4B*)malloc(_vertexDataCount * sizeof(*_vertexData)); _vertexIndex = (unsigned short*)malloc(6 * sizeof(*_vertexIndex)); AXASSERT(_vertexData, "FUISprite. Not enough memory"); } // TOPLEFT - _vertexData[0].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); - _vertexData[0].vertices = vertexFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[0].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, max.y)); + _vertexData[0].position = vertexFromAlphaPoint(Vec2(min.x, max.y)); // BOTLEFT - _vertexData[1].texCoords = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); - _vertexData[1].vertices = vertexFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[1].texCoord = textureCoordFromAlphaPoint(Vec2(min.x, min.y)); + _vertexData[1].position = vertexFromAlphaPoint(Vec2(min.x, min.y)); // TOPRIGHT - _vertexData[2].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); - _vertexData[2].vertices = vertexFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[2].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, max.y)); + _vertexData[2].position = vertexFromAlphaPoint(Vec2(max.x, max.y)); // BOTRIGHT - _vertexData[3].texCoords = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); - _vertexData[3].vertices = vertexFromAlphaPoint(Vec2(max.x, min.y)); - + _vertexData[3].texCoord = textureCoordFromAlphaPoint(Vec2(max.x, min.y)); + _vertexData[3].position = vertexFromAlphaPoint(Vec2(max.x, min.y)); + _vertexIndex[0] = 0; _vertexIndex[1] = 1; _vertexIndex[2] = 2; _vertexIndex[3] = 2; _vertexIndex[4] = 1; _vertexIndex[5] = 3; - + _fillTriangles.verts = _vertexData; _fillTriangles.vertCount = 4; _fillTriangles.indices = _vertexIndex; diff --git a/extensions/fairygui/src/fairygui/display/FUISprite.h b/extensions/fairygui/src/fairygui/display/FUISprite.h index 6755c070309a..a3b245c11499 100644 --- a/extensions/fairygui/src/fairygui/display/FUISprite.h +++ b/extensions/fairygui/src/fairygui/display/FUISprite.h @@ -1,7 +1,7 @@ #ifndef __FUISPRITE_H__ #define __FUISPRITE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -55,7 +55,7 @@ class FUISprite : public ax::Sprite bool _scaleByTile; int _vertexDataCount; ax::TrianglesCommand::Triangles _fillTriangles; - ax::V3F_C4B_T2F *_vertexData; + ax::V3F_T2F_C4B *_vertexData; unsigned short *_vertexIndex; static ax::Texture2D* _empty; diff --git a/extensions/fairygui/src/fairygui/display/TextFormat.cpp b/extensions/fairygui/src/fairygui/display/TextFormat.cpp index 996a2972e9ca..f13116c61524 100644 --- a/extensions/fairygui/src/fairygui/display/TextFormat.cpp +++ b/extensions/fairygui/src/fairygui/display/TextFormat.cpp @@ -5,7 +5,7 @@ using namespace ax; TextFormat::TextFormat() : fontSize(12), - color(Color3B::BLACK), + color(Color32::BLACK), bold(false), italics(false), underline(false), @@ -56,4 +56,4 @@ void TextFormat::setFormat(const TextFormat & format) *this = format; } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/display/TextFormat.h b/extensions/fairygui/src/fairygui/display/TextFormat.h index 8a4b23a88ec0..15ea4d2472bd 100644 --- a/extensions/fairygui/src/fairygui/display/TextFormat.h +++ b/extensions/fairygui/src/fairygui/display/TextFormat.h @@ -1,7 +1,7 @@ #ifndef __TEXTFORMAT_H__ #define __TEXTFORMAT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -24,7 +24,7 @@ class TextFormat std::string face; float fontSize; - ax::Color3B color; + ax::Color32 color; bool bold; bool italics; bool underline; @@ -34,12 +34,12 @@ class TextFormat ax::TextVAlignment verticalAlign; int effect; - ax::Color3B outlineColor; + ax::Color32 outlineColor; int outlineSize; - ax::Color3B shadowColor; + ax::Color32 shadowColor; ax::Size shadowOffset; int shadowBlurRadius; - ax::Color3B glowColor; + ax::Color32 glowColor; //internal use bool _hasColor; diff --git a/extensions/fairygui/src/fairygui/event/EventContext.h b/extensions/fairygui/src/fairygui/event/EventContext.h index db42f3c93d2e..bd84c6161b2b 100644 --- a/extensions/fairygui/src/fairygui/event/EventContext.h +++ b/extensions/fairygui/src/fairygui/event/EventContext.h @@ -2,7 +2,7 @@ #define __EVENTCONTEXT_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "InputEvent.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/event/HitTest.h b/extensions/fairygui/src/fairygui/event/HitTest.h index b7a990aee1c4..de14df9495b7 100644 --- a/extensions/fairygui/src/fairygui/event/HitTest.h +++ b/extensions/fairygui/src/fairygui/event/HitTest.h @@ -2,7 +2,7 @@ #define __HITTEST_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN @@ -50,4 +50,4 @@ class PixelHitTest : public IHitTest NS_FGUI_END -#endif \ No newline at end of file +#endif diff --git a/extensions/fairygui/src/fairygui/event/InputEvent.h b/extensions/fairygui/src/fairygui/event/InputEvent.h index c4956e59eb31..a2072f330f92 100644 --- a/extensions/fairygui/src/fairygui/event/InputEvent.h +++ b/extensions/fairygui/src/fairygui/event/InputEvent.h @@ -2,7 +2,7 @@ #define __INPUTEVENT_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/event/InputProcessor.h b/extensions/fairygui/src/fairygui/event/InputProcessor.h index 512995152add..a87b89b6df84 100644 --- a/extensions/fairygui/src/fairygui/event/InputProcessor.h +++ b/extensions/fairygui/src/fairygui/event/InputProcessor.h @@ -2,7 +2,7 @@ #define __INPUTPROCESSOR_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "UIEventDispatcher.h" #include "InputEvent.h" diff --git a/extensions/fairygui/src/fairygui/event/UIEventDispatcher.h b/extensions/fairygui/src/fairygui/event/UIEventDispatcher.h index af1c87c6812b..7e0fae389b43 100644 --- a/extensions/fairygui/src/fairygui/event/UIEventDispatcher.h +++ b/extensions/fairygui/src/fairygui/event/UIEventDispatcher.h @@ -2,7 +2,7 @@ #define __UIEVENTDISPATCHER_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "EventContext.h" #include "UIEventType.h" diff --git a/extensions/fairygui/src/fairygui/gears/GearAnimation.h b/extensions/fairygui/src/fairygui/gears/GearAnimation.h index 369390502263..faf468ee017a 100644 --- a/extensions/fairygui/src/fairygui/gears/GearAnimation.h +++ b/extensions/fairygui/src/fairygui/gears/GearAnimation.h @@ -2,7 +2,7 @@ #define __GEARANIMATION_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GearBase.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearBase.h b/extensions/fairygui/src/fairygui/gears/GearBase.h index 939ee0f2769f..c40a9b968dce 100644 --- a/extensions/fairygui/src/fairygui/gears/GearBase.h +++ b/extensions/fairygui/src/fairygui/gears/GearBase.h @@ -2,7 +2,7 @@ #define __GEARBASE_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "tween/EaseType.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearColor.cpp b/extensions/fairygui/src/fairygui/gears/GearColor.cpp index bb2bbf7f42d4..282ee290824d 100644 --- a/extensions/fairygui/src/fairygui/gears/GearColor.cpp +++ b/extensions/fairygui/src/fairygui/gears/GearColor.cpp @@ -13,7 +13,7 @@ GearColor::GearColorValue::GearColorValue() { } -GearColor::GearColorValue::GearColorValue(const Color3B& color, const Color3B& strokeColor) +GearColor::GearColorValue::GearColorValue(const Color32& color, const Color32& strokeColor) { this->color = color; this->outlineColor = strokeColor; @@ -37,8 +37,8 @@ void GearColor::init() void GearColor::addStatus(const std::string& pageId, ByteBuffer* buffer) { GearColorValue gv; - gv.color = (Color3B)buffer->readColor(); - gv.outlineColor = (Color3B)buffer->readColor(); + gv.color = buffer->readColor(); + gv.outlineColor = buffer->readColor(); if (pageId.size() == 0) _default = gv; else @@ -56,8 +56,8 @@ void GearColor::apply() if (_tweenConfig && _tweenConfig->tween && UIPackage::_constructing == 0 && !disableAllTweenEffect) { - Color3B curColor = ToolSet::intToColor(_owner->getProp(ObjectPropID::Color).asUnsignedInt()); - Color3B curStrokeColor = ToolSet::intToColor(_owner->getProp(ObjectPropID::OutlineColor).asUnsignedInt()); + auto curColor = ToolSet::intToColor(_owner->getProp(ObjectPropID::Color).asUnsignedInt()); + auto curStrokeColor = ToolSet::intToColor(_owner->getProp(ObjectPropID::OutlineColor).asUnsignedInt()); if (gv.outlineColor != curStrokeColor) { @@ -82,7 +82,7 @@ void GearColor::apply() if (_owner->checkGearController(0, _controller)) _tweenConfig->_displayLockToken = _owner->addDisplayLock(); - _tweenConfig->_tweener = GTween::to((Color4B)curColor, (Color4B)gv.color, _tweenConfig->duration) + _tweenConfig->_tweener = GTween::to((Color32)curColor, (Color32)gv.color, _tweenConfig->duration) ->setDelay(_tweenConfig->delay) ->setEase(_tweenConfig->easeType) ->setTargetAny(this) @@ -102,7 +102,7 @@ void GearColor::apply() void GearColor::onTweenUpdate(GTweener* tweener) { _owner->_gearLocked = true; - _owner->setProp(ObjectPropID::Color, Value(ToolSet::colorToInt((Color3B)_tweenConfig->_tweener->value.getColor()))); + _owner->setProp(ObjectPropID::Color, Value(ToolSet::colorToInt(_tweenConfig->_tweener->value.getColor()))); _owner->_gearLocked = false; } diff --git a/extensions/fairygui/src/fairygui/gears/GearColor.h b/extensions/fairygui/src/fairygui/gears/GearColor.h index ac50b53e7850..f44ac7f420aa 100644 --- a/extensions/fairygui/src/fairygui/gears/GearColor.h +++ b/extensions/fairygui/src/fairygui/gears/GearColor.h @@ -2,7 +2,7 @@ #define __GEARCOLOR_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GearBase.h" NS_FGUI_BEGIN @@ -30,11 +30,11 @@ class GearColor : public GearBase class GearColorValue { public: - ax::Color3B color; - ax::Color3B outlineColor; + ax::Color32 color; + ax::Color32 outlineColor; GearColorValue(); - GearColorValue(const ax::Color3B& color, const ax::Color3B& outlineColor); + GearColorValue(const ax::Color32& color, const ax::Color32& outlineColor); }; std::unordered_map _storage; diff --git a/extensions/fairygui/src/fairygui/gears/GearDisplay.cpp b/extensions/fairygui/src/fairygui/gears/GearDisplay.cpp index 60f8fb69a8dc..83952088bca1 100644 --- a/extensions/fairygui/src/fairygui/gears/GearDisplay.cpp +++ b/extensions/fairygui/src/fairygui/gears/GearDisplay.cpp @@ -64,4 +64,4 @@ bool GearDisplay::isConnected() return _controller == nullptr || _visible > 0; } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/gears/GearDisplay.h b/extensions/fairygui/src/fairygui/gears/GearDisplay.h index eb1f54a54d4d..c7dd5c96f700 100644 --- a/extensions/fairygui/src/fairygui/gears/GearDisplay.h +++ b/extensions/fairygui/src/fairygui/gears/GearDisplay.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearDisplay2.cpp b/extensions/fairygui/src/fairygui/gears/GearDisplay2.cpp index c9ed52e92336..254861a9b0b4 100644 --- a/extensions/fairygui/src/fairygui/gears/GearDisplay2.cpp +++ b/extensions/fairygui/src/fairygui/gears/GearDisplay2.cpp @@ -53,4 +53,4 @@ void GearDisplay2::init() pages.clear(); } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/gears/GearDisplay2.h b/extensions/fairygui/src/fairygui/gears/GearDisplay2.h index 1728cc079bbe..32ec9da9ecf7 100644 --- a/extensions/fairygui/src/fairygui/gears/GearDisplay2.h +++ b/extensions/fairygui/src/fairygui/gears/GearDisplay2.h @@ -2,7 +2,7 @@ #define __GEARDISPLAY2_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GearBase.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearFontSize.h b/extensions/fairygui/src/fairygui/gears/GearFontSize.h index b696735ccfcc..07600aa5d72f 100644 --- a/extensions/fairygui/src/fairygui/gears/GearFontSize.h +++ b/extensions/fairygui/src/fairygui/gears/GearFontSize.h @@ -2,7 +2,7 @@ #define __GEARFONTSIZE_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GearBase.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearIcon.h b/extensions/fairygui/src/fairygui/gears/GearIcon.h index 33010341b507..9c0dbcd1017b 100644 --- a/extensions/fairygui/src/fairygui/gears/GearIcon.h +++ b/extensions/fairygui/src/fairygui/gears/GearIcon.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearLook.h b/extensions/fairygui/src/fairygui/gears/GearLook.h index 38a575441687..8aeaff689d8d 100644 --- a/extensions/fairygui/src/fairygui/gears/GearLook.h +++ b/extensions/fairygui/src/fairygui/gears/GearLook.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearSize.h b/extensions/fairygui/src/fairygui/gears/GearSize.h index 4cebdba96269..c9bc2d961fe9 100644 --- a/extensions/fairygui/src/fairygui/gears/GearSize.h +++ b/extensions/fairygui/src/fairygui/gears/GearSize.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearText.h b/extensions/fairygui/src/fairygui/gears/GearText.h index 81b18c335852..515147f5d51e 100644 --- a/extensions/fairygui/src/fairygui/gears/GearText.h +++ b/extensions/fairygui/src/fairygui/gears/GearText.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/gears/GearXY.h b/extensions/fairygui/src/fairygui/gears/GearXY.h index 50df3e28e7c9..3a3cb5c0f1bb 100644 --- a/extensions/fairygui/src/fairygui/gears/GearXY.h +++ b/extensions/fairygui/src/fairygui/gears/GearXY.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "GearBase.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/tween/EaseManager.cpp b/extensions/fairygui/src/fairygui/tween/EaseManager.cpp index 829414087997..90f81392b54f 100644 --- a/extensions/fairygui/src/fairygui/tween/EaseManager.cpp +++ b/extensions/fairygui/src/fairygui/tween/EaseManager.cpp @@ -1,5 +1,5 @@ #include "EaseManager.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN using namespace ax; diff --git a/extensions/fairygui/src/fairygui/tween/GPath.h b/extensions/fairygui/src/fairygui/tween/GPath.h index 56075b921c98..95b21acaccd2 100644 --- a/extensions/fairygui/src/fairygui/tween/GPath.h +++ b/extensions/fairygui/src/fairygui/tween/GPath.h @@ -2,7 +2,7 @@ #define __GPATH_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/tween/GTween.cpp b/extensions/fairygui/src/fairygui/tween/GTween.cpp index 1b8e93a0a245..0b28e4a89018 100644 --- a/extensions/fairygui/src/fairygui/tween/GTween.cpp +++ b/extensions/fairygui/src/fairygui/tween/GTween.cpp @@ -24,7 +24,7 @@ GTweener* GTween::to(const ax::Vec4& startValue, const ax::Vec4 & endValue, floa return TweenManager::createTween()->_to(startValue, endValue, duration); } -GTweener* GTween::to(const ax::Color4B& startValue, const ax::Color4B & endValue, float duration) +GTweener* GTween::to(const ax::Color32& startValue, const ax::Color32 & endValue, float duration) { return TweenManager::createTween()->_to(startValue, endValue, duration); } diff --git a/extensions/fairygui/src/fairygui/tween/GTween.h b/extensions/fairygui/src/fairygui/tween/GTween.h index feb89288f209..2933a60f6afe 100644 --- a/extensions/fairygui/src/fairygui/tween/GTween.h +++ b/extensions/fairygui/src/fairygui/tween/GTween.h @@ -2,7 +2,7 @@ #define __GTWEEN_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "GTweener.h" #include "EaseType.h" #include "TweenValue.h" @@ -17,12 +17,12 @@ class GTween static GTweener* to(const ax::Vec2& startValue, const ax::Vec2& endValue, float duration); static GTweener* to(const ax::Vec3& startValue, const ax::Vec3& endValue, float duration); static GTweener* to(const ax::Vec4& startValue, const ax::Vec4& endValue, float duration); - static GTweener* to(const ax::Color4B& startValue, const ax::Color4B& endValue, float duration); + static GTweener* to(const ax::Color32& startValue, const ax::Color32& endValue, float duration); static GTweener* toFloat(float startValue, float endValue, float duration) { return to(startValue, endValue, duration); } static GTweener* toVec2(const ax::Vec2& startValue, const ax::Vec2& endValue, float duration) { return to(startValue, endValue, duration); } static GTweener* toVec3(const ax::Vec3& startValue, const ax::Vec3& endValue, float duration) { return to(startValue, endValue, duration); } static GTweener* toVec4(const ax::Vec4& startValue, const ax::Vec4& endValue, float duration) { return to(startValue, endValue, duration); } - static GTweener* toColor4B(const ax::Color4B& startValue, const ax::Color4B& endValue, float duration) { return to(startValue, endValue, duration); } + static GTweener* toColor32(const ax::Color32& startValue, const ax::Color32& endValue, float duration) { return to(startValue, endValue, duration); } static GTweener* toDouble(double startValue, double endValue, float duration); static GTweener* delayedCall(float delay); static GTweener* shake(const ax::Vec2& startValue, float amplitude, float duration); diff --git a/extensions/fairygui/src/fairygui/tween/GTweener.cpp b/extensions/fairygui/src/fairygui/tween/GTweener.cpp index ebf0d8ff6a7c..ab7ec485977a 100644 --- a/extensions/fairygui/src/fairygui/tween/GTweener.cpp +++ b/extensions/fairygui/src/fairygui/tween/GTweener.cpp @@ -216,7 +216,7 @@ GTweener* GTweener::_to(const ax::Vec4& start, const ax::Vec4& end, float durati return this; } -GTweener* GTweener::_to(const ax::Color4B& start, const ax::Color4B& end, float duration) +GTweener* GTweener::_to(const ax::Color32& start, const ax::Color32& end, float duration) { _valueSize = 4; startValue.setColor(start); diff --git a/extensions/fairygui/src/fairygui/tween/GTweener.h b/extensions/fairygui/src/fairygui/tween/GTweener.h index c4691e82c739..e680db52ed7a 100644 --- a/extensions/fairygui/src/fairygui/tween/GTweener.h +++ b/extensions/fairygui/src/fairygui/tween/GTweener.h @@ -2,7 +2,7 @@ #define __GTWEENER_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "EaseType.h" #include "TweenValue.h" #include "TweenPropType.h" @@ -59,7 +59,7 @@ class GTweener : public ax::Object GTweener* _to(const ax::Vec2& start, const ax::Vec2& end, float duration); GTweener* _to(const ax::Vec3& start, const ax::Vec3& end, float duration); GTweener* _to(const ax::Vec4& start, const ax::Vec4& end, float duration); - GTweener* _to(const ax::Color4B& start, const ax::Color4B& end, float duration); + GTweener* _to(const ax::Color32& start, const ax::Color32& end, float duration); GTweener* _to(double start, double end, float duration); GTweener* _shake(const ax::Vec2& start, float amplitude, float duration); void _init(); diff --git a/extensions/fairygui/src/fairygui/tween/TweenManager.h b/extensions/fairygui/src/fairygui/tween/TweenManager.h index ece6cc71f0a6..79aa281a8c3c 100644 --- a/extensions/fairygui/src/fairygui/tween/TweenManager.h +++ b/extensions/fairygui/src/fairygui/tween/TweenManager.h @@ -3,7 +3,7 @@ #include "FairyGUIMacros.h" #include "TweenPropType.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/tween/TweenPropType.h b/extensions/fairygui/src/fairygui/tween/TweenPropType.h index 2f57338d91a4..5feb8b8aabdc 100644 --- a/extensions/fairygui/src/fairygui/tween/TweenPropType.h +++ b/extensions/fairygui/src/fairygui/tween/TweenPropType.h @@ -2,7 +2,7 @@ #define __TWEENPROPTYPE_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN diff --git a/extensions/fairygui/src/fairygui/tween/TweenValue.cpp b/extensions/fairygui/src/fairygui/tween/TweenValue.cpp index 6b258d4982d9..2bcbe81ad2b9 100644 --- a/extensions/fairygui/src/fairygui/tween/TweenValue.cpp +++ b/extensions/fairygui/src/fairygui/tween/TweenValue.cpp @@ -1,5 +1,5 @@ #include "TweenValue.h" -#include "base/format.h" +#include "axmol/base/format.h" NS_FGUI_BEGIN using namespace ax; @@ -44,12 +44,12 @@ void TweenValue::setVec4(const ax::Vec4 & value) w = value.w; } -ax::Color4B TweenValue::getColor() const +ax::Color32 TweenValue::getColor() const { - return ax::Color4B(x, y, z, w); + return ax::Color32(x, y, z, w); } -void TweenValue::setColor(const ax::Color4B & value) +void TweenValue::setColor(const ax::Color32 & value) { x = value.r; y = value.g; @@ -96,4 +96,4 @@ void TweenValue::setZero() x = y = z = w = d = 0; } -NS_FGUI_END \ No newline at end of file +NS_FGUI_END diff --git a/extensions/fairygui/src/fairygui/tween/TweenValue.h b/extensions/fairygui/src/fairygui/tween/TweenValue.h index b081bdac3e4d..7584f852e172 100644 --- a/extensions/fairygui/src/fairygui/tween/TweenValue.h +++ b/extensions/fairygui/src/fairygui/tween/TweenValue.h @@ -2,7 +2,7 @@ #define __TWEENVALUE_H__ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN @@ -23,8 +23,8 @@ class TweenValue void setVec3(const ax::Vec3& value); ax::Vec4 getVec4() const; void setVec4(const ax::Vec4& value); - ax::Color4B getColor() const; - void setColor(const ax::Color4B& value); + ax::Color32 getColor() const; + void setColor(const ax::Color32& value); float operator[] (int index) const; float& operator[] (int index); void setZero(); diff --git a/extensions/fairygui/src/fairygui/utils/ByteBuffer.cpp b/extensions/fairygui/src/fairygui/utils/ByteBuffer.cpp index 8ddb8b029b47..5fbc7db88da6 100644 --- a/extensions/fairygui/src/fairygui/utils/ByteBuffer.cpp +++ b/extensions/fairygui/src/fairygui/utils/ByteBuffer.cpp @@ -156,7 +156,7 @@ void ByteBuffer::writeS(const std::string& value) (*_stringTable)[index] = value; } -ax::Color4B ByteBuffer::readColor() +ax::Color32 ByteBuffer::readColor() { int startIndex = _offset + _position; #if COCOS2D_VERSION >= 0x00040000 @@ -172,7 +172,7 @@ ax::Color4B ByteBuffer::readColor() #endif _position += 4; - return ax::Color4B(r, g, b, a); + return ax::Color32(r, g, b, a); } ByteBuffer* ByteBuffer::readBuffer() diff --git a/extensions/fairygui/src/fairygui/utils/ByteBuffer.h b/extensions/fairygui/src/fairygui/utils/ByteBuffer.h index b1b46b5c30af..46edb2fc5f13 100644 --- a/extensions/fairygui/src/fairygui/utils/ByteBuffer.h +++ b/extensions/fairygui/src/fairygui/utils/ByteBuffer.h @@ -2,7 +2,7 @@ #define __BYTEBUFFER_H_ #include "FairyGUIMacros.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" NS_FGUI_BEGIN @@ -39,7 +39,7 @@ class ByteBuffer bool readS(std::string& result); const std::string* readSP(); void writeS(const std::string& value); - ax::Color4B readColor(); + ax::Color32 readColor(); ByteBuffer* readBuffer(); bool seek(int indexTablePos, int blockIndex); diff --git a/extensions/fairygui/src/fairygui/utils/ToolSet.cpp b/extensions/fairygui/src/fairygui/utils/ToolSet.cpp index 5b25b11e7e78..0c0384902531 100644 --- a/extensions/fairygui/src/fairygui/utils/ToolSet.cpp +++ b/extensions/fairygui/src/fairygui/utils/ToolSet.cpp @@ -4,39 +4,39 @@ NS_FGUI_BEGIN using namespace ax; using namespace std; -Color4B ToolSet::hexToColor(const char* str) +Color32 ToolSet::hexToColor(const char* str) { ssize_t len = strlen(str); if (len < 7 || str[0] != '#') - return Color4B::BLACK; + return Color32::BLACK; char temp[3]; memset(temp, 0, 3); if (len == 9) { - return Color4B(strtol(strncpy(temp, str + 3, 2), NULL, 16), + return Color32(strtol(strncpy(temp, str + 3, 2), NULL, 16), strtol(strncpy(temp, str + 5, 2), NULL, 16), strtol(strncpy(temp, str + 7, 2), NULL, 16), strtol(strncpy(temp, str + 1, 2), NULL, 16)); } else { - return Color4B(strtol(strncpy(temp, str + 1, 2), NULL, 16), + return Color32(strtol(strncpy(temp, str + 1, 2), NULL, 16), strtol(strncpy(temp, str + 3, 2), NULL, 16), strtol(strncpy(temp, str + 5, 2), NULL, 16), 255); } } -ax::Color3B ToolSet::intToColor(unsigned int rgb) +ax::Color32 ToolSet::intToColor(unsigned int argb) { - return Color3B((rgb >> 16) & 0xFF, (rgb >> 8) & 0xFF, rgb & 0xFF); + return Color32((argb >> 16) & 0xFF, (argb >> 8) & 0xFF, argb & 0xFF, (argb >> 24) & 0xFF); } -unsigned int ToolSet::colorToInt(const ax::Color3B& color) +unsigned int ToolSet::colorToInt(const ax::Color32& color) { - return (color.r << 16) + (color.g << 8) + color.b; + return (color.a << 24) + (color.r << 16) + (color.g << 8) + color.b; } Rect ToolSet::intersection(const Rect& rect1, const Rect& rect2) diff --git a/extensions/fairygui/src/fairygui/utils/ToolSet.h b/extensions/fairygui/src/fairygui/utils/ToolSet.h index 76a311e7016d..be1bca3fc0ce 100644 --- a/extensions/fairygui/src/fairygui/utils/ToolSet.h +++ b/extensions/fairygui/src/fairygui/utils/ToolSet.h @@ -1,7 +1,7 @@ #ifndef __TOOLSET_H__ #define __TOOLSET_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUI.h" NS_FGUI_BEGIN @@ -9,9 +9,9 @@ NS_FGUI_BEGIN class ToolSet { public: - static ax::Color4B hexToColor(const char* str); - static ax::Color3B intToColor(unsigned int rgb); - static unsigned int colorToInt(const ax::Color3B& color); + static ax::Color32 hexToColor(const char* str); + static ax::Color32 intToColor(unsigned int rgb); + static unsigned int colorToInt(const ax::Color32& color); static ax::Rect intersection(const ax::Rect& rect1, const ax::Rect& rect2); static int findInStringArray(const std::vector& arr, const std::string& str); diff --git a/extensions/fairygui/src/fairygui/utils/UBBParser.cpp b/extensions/fairygui/src/fairygui/utils/UBBParser.cpp index 76859df0aae2..5ffc0c83dc02 100644 --- a/extensions/fairygui/src/fairygui/utils/UBBParser.cpp +++ b/extensions/fairygui/src/fairygui/utils/UBBParser.cpp @@ -1,5 +1,5 @@ #include "UBBParser.h" -#include "base/format.h" +#include "axmol/base/format.h" NS_FGUI_BEGIN using namespace ax; diff --git a/extensions/fairygui/src/fairygui/utils/UBBParser.h b/extensions/fairygui/src/fairygui/utils/UBBParser.h index ead5439f79cc..2b06c823a10c 100644 --- a/extensions/fairygui/src/fairygui/utils/UBBParser.h +++ b/extensions/fairygui/src/fairygui/utils/UBBParser.h @@ -1,7 +1,7 @@ #ifndef __UBBPARSER_H__ #define __UBBPARSER_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -46,4 +46,4 @@ class UBBParser NS_FGUI_END -#endif \ No newline at end of file +#endif diff --git a/extensions/fairygui/src/fairygui/utils/WeakPtr.h b/extensions/fairygui/src/fairygui/utils/WeakPtr.h index 7fcbc77544fe..bedb49806a2c 100644 --- a/extensions/fairygui/src/fairygui/utils/WeakPtr.h +++ b/extensions/fairygui/src/fairygui/utils/WeakPtr.h @@ -1,7 +1,7 @@ #ifndef __WEAKPTR_H__ #define __WEAKPTR_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" NS_FGUI_BEGIN @@ -42,4 +42,4 @@ class WeakPtr NS_FGUI_END -#endif \ No newline at end of file +#endif diff --git a/extensions/fairygui/src/fairygui/utils/html/HtmlElement.h b/extensions/fairygui/src/fairygui/utils/html/HtmlElement.h index 6b14a2ab1b69..a732953b6ca6 100644 --- a/extensions/fairygui/src/fairygui/utils/html/HtmlElement.h +++ b/extensions/fairygui/src/fairygui/utils/html/HtmlElement.h @@ -1,7 +1,7 @@ #ifndef __HTMLELEMENT_H__ #define __HTMLELEMENT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "display/TextFormat.h" diff --git a/extensions/fairygui/src/fairygui/utils/html/HtmlObject.h b/extensions/fairygui/src/fairygui/utils/html/HtmlObject.h index 9fcff9632c74..24bd4ebf5608 100644 --- a/extensions/fairygui/src/fairygui/utils/html/HtmlObject.h +++ b/extensions/fairygui/src/fairygui/utils/html/HtmlObject.h @@ -1,7 +1,7 @@ #ifndef __HTMLOBJECT_H__ #define __HTMLOBJECT_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "../../FairyGUIMacros.h" #include "../../GObjectPool.h" diff --git a/extensions/fairygui/src/fairygui/utils/html/HtmlParser.cpp b/extensions/fairygui/src/fairygui/utils/html/HtmlParser.cpp index b3729df441a2..4e6186081ac3 100644 --- a/extensions/fairygui/src/fairygui/utils/html/HtmlParser.cpp +++ b/extensions/fairygui/src/fairygui/utils/html/HtmlParser.cpp @@ -33,7 +33,7 @@ static void rtrim(std::string& s) { s.end()); } -Color3B HtmlParseOptions::defaultLinkColor(58, 103, 204); +Color32 HtmlParseOptions::defaultLinkColor(58, 103, 204, 255); bool HtmlParseOptions::defaultLinkUnderline = true; HtmlParseOptions::HtmlParseOptions() @@ -135,7 +135,7 @@ void HtmlParser::startElement(void* /*ctx*/, const char *elementName, const char auto it = attrMap.find("color"); if (it != attrMap.end()) { - _format.color = (Color3B)ToolSet::hexToColor(it->second.asString().c_str()); + _format.color = (Color32)ToolSet::hexToColor(it->second.asString().c_str()); _format._hasColor = true; } } diff --git a/extensions/fairygui/src/fairygui/utils/html/HtmlParser.h b/extensions/fairygui/src/fairygui/utils/html/HtmlParser.h index 630f591fae7e..456e73833b8d 100644 --- a/extensions/fairygui/src/fairygui/utils/html/HtmlParser.h +++ b/extensions/fairygui/src/fairygui/utils/html/HtmlParser.h @@ -1,7 +1,7 @@ #ifndef __HTMLPARSER_H__ #define __HTMLPARSER_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUIMacros.h" #include "display/TextFormat.h" @@ -13,12 +13,12 @@ class HtmlParseOptions { public: static bool defaultLinkUnderline; - static ax::Color3B defaultLinkColor; + static ax::Color32 defaultLinkColor; HtmlParseOptions(); bool linkUnderline; - ax::Color3B linkColor; + ax::Color32 linkColor; }; class HtmlParser : public ax::SAXDelegator diff --git a/extensions/physics-nodes/CMakeLists.txt b/extensions/physics-nodes/CMakeLists.txt index 6f4e31f4b2a7..75b1257e218e 100644 --- a/extensions/physics-nodes/CMakeLists.txt +++ b/extensions/physics-nodes/CMakeLists.txt @@ -6,4 +6,5 @@ add_library(${target_name} ${PHYSICS_NODES_SOURCES}) target_include_directories( ${target_name} PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/src ) + setup_ax_extension_config(${target_name}) diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.cpp index 6e903917f550..f478f182ab90 100644 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.cpp +++ b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.cpp @@ -1,252 +1,168 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +/* * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. */ -#include "PhysicsDebugNode.h" -#include "chipmunk/chipmunk_private.h" - -#include "base/Types.h" -#include "math/Math.h" +#include "PhysicsDebugNode.h" +#include "axmol/physics/PhysicsHelper.h" -#include -#include -#include -#include -#include +#if defined(_WIN32) +# pragma push_macro("TRANSPARENT") +# undef TRANSPARENT +#endif NS_AX_EXT_BEGIN -/* - IMPORTANT - READ ME! - - This file sets pokes around in the private API a lot to provide efficient - debug rendering given nothing more than reference to a Chipmunk space. - It is not recommended to write rendering code like this in your own games - as the private API may change with little or no warning. - */ - -static const cpVect spring_verts[] = { - {0.00f, 0.0f}, {0.20f, 0.0f}, {0.25f, 3.0f}, {0.30f, -6.0f}, {0.35f, 6.0f}, - {0.40f, -6.0f}, {0.45f, 6.0f}, {0.50f, -6.0f}, {0.55f, 6.0f}, {0.60f, -6.0f}, - {0.65f, 6.0f}, {0.70f, -3.0f}, {0.75f, 6.0f}, {0.80f, 0.0f}, {1.00f, 0.0f}, -}; -static const int spring_count = sizeof(spring_verts) / sizeof(cpVect); - -static Color4F ColorForBody(cpBody* body) +/// Draw a closed polygon provided in CCW order. +// void (*DrawPolygon)(const b2Vec2* vertices, int vertexCount, b2HexColor color, void* context); +static void b2DrawPolygon(const b2Vec2* verts, int vertexCount, b2HexColor color, PhysicsDebugNode* dn) { - if (CP_BODY_TYPE_STATIC == cpBodyGetType(body) || cpBodyIsSleeping(body)) + Vec2* vec = new Vec2[vertexCount]; + for (size_t i = 0; i < vertexCount; i++) { - return Color4F(0.5f, 0.5f, 0.5f, 0.5f); + vec[i] = Vec2(verts[i].x * dn->getPTMRatio(), verts[i].y * dn->getPTMRatio()) + dn->getWorldOffset(); } - else if (body->sleeping.idleTime > cpBodyGetSpace(body)->sleepTimeThreshold) - { - return Color4F(0.33f, 0.33f, 0.33f, 0.5f); - } - else + dn->drawPolygon(vec, vertexCount, ax::Color::BLACK, 0.4f, PhysicsHelper::toColor(color)); +} + +/// Draw a solid closed polygon provided in CCW order. +// void (*DrawSolidPolygon)(b2Transform, +// const b2Vec2* vertices, +// int vertexCount, +// float radius, +// b2HexColor color, +// void* context); +static void b2DrawSolidPolygon(b2Transform t, + const b2Vec2* verts, + int vertexCount, + float radius, + b2HexColor color, + PhysicsDebugNode* dn) +{ + axstd::pod_vector vec(vertexCount); + for (size_t i = 0; i < vertexCount; i++) { - return Color4F(1.0f, 0.0f, 0.0f, 0.5f); + auto pt = b2TransformPoint(t, verts[i]); + vec[i] = Vec2(pt.x * dn->getPTMRatio(), pt.y * dn->getPTMRatio()) + dn->getWorldOffset(); } + auto color4f = PhysicsHelper::toColor(color); + dn->drawPolygon(vec.data(), vertexCount, ax::Color(color4f.r / 2, color4f.g / 2, color4f.b / 2, color4f.a), 0.5f, + color4f); } -static Vec2 cpVert2Point(const cpVect& vert) +/// Draw a circle. +// void (*DrawCircle)(b2Vec2 center, float radius, b2HexColor color, void* context); +static void b2DrawCircle(b2Vec2 center, float radius, b2HexColor color, PhysicsDebugNode* dn) { - return (Vec2(vert.x, vert.y)); + dn->drawCircle(Vec2(center.x * dn->getPTMRatio(), center.y * dn->getPTMRatio()) + dn->getWorldOffset(), + radius * dn->getPTMRatio(), AX_DEGREES_TO_RADIANS(0), 30, true, 1.0f, 1.0f, + PhysicsHelper::toColor(color)); } -static void DrawShape(cpShape* shape, DrawNode* renderer) +/// Draw a solid circle. +// void (*DrawSolidCircle)(b2Transform, float radius, b2HexColor color, void* context); +static void b2DrawSolidCircle(b2Transform t, float radius, b2HexColor color, PhysicsDebugNode* dn) { - cpBody* body = cpShapeGetBody(shape); - Color4F color = ColorForBody(body); - - switch (shape->klass->type) - { - case CP_CIRCLE_SHAPE: - { - cpCircleShape* circle = (cpCircleShape*)shape; - cpVect center = circle->tc; - cpFloat radius = circle->r; - renderer->drawDot(cpVert2Point(center), cpfmax(radius, 1.0), color); - renderer->drawSegment(cpVert2Point(center), - cpVert2Point(cpvadd(center, cpvmult(cpBodyGetRotation(body), radius))), 1.0, color); - } - break; - case CP_SEGMENT_SHAPE: - { - cpSegmentShape* seg = (cpSegmentShape*)shape; - renderer->drawSegment(cpVert2Point(seg->ta), cpVert2Point(seg->tb), cpfmax(seg->r, 1.0), color); - } - break; - case CP_POLY_SHAPE: - { - cpPolyShape* poly = (cpPolyShape*)shape; - Color4F line = color; - line.a = cpflerp(color.a, 1.0, 0.5); - int num = poly->count; - Vec2* pPoints = new Vec2[num]; - for (int i = 0; i < num; ++i) - pPoints[i] = cpVert2Point(poly->planes[i].v0); - if (cpfmax(poly->r, 1.0) > 1.0) - { - renderer->drawPolygon(pPoints, num, Color4F(0.5f, 0.5f, 0.5f, 0.0f), poly->r, color); - } - else - { - renderer->drawPolygon(pPoints, num, color, 1.0, line); - } - - AX_SAFE_DELETE_ARRAY(pPoints); - } - break; - default: - cpAssertHard(false, "Bad assertion in DrawShape()"); - } + auto center = b2TransformPoint(t, b2Vec2_zero); + Vec2 c = {Vec2(center.x * dn->getPTMRatio(), center.y * dn->getPTMRatio()) + dn->getWorldOffset()}; + auto color4f = PhysicsHelper::toColor(color); + + dn->drawSolidCircle(c, radius * dn->getPTMRatio(), AX_DEGREES_TO_RADIANS(0), 20, 1.0f, 1.0f, + ax::Color(color4f.r / 2, color4f.g / 2, color4f.b / 2, color4f.a), 0.4f, color4f); + // Draw a line fixed in the circle to animate rotation. + b2Vec2 pp = {(center + radius * b2Rot_GetXAxis(t.q))}; + Vec2 cp = {Vec2(pp.x * dn->getPTMRatio(), pp.y * dn->getPTMRatio()) + dn->getWorldOffset()}; + dn->drawLine(c, cp, color4f); } -static Color4F CONSTRAINT_COLOR(0, 1, 0, 0.5); +/// Draw a solid capsule. +// void (*DrawSolidCapsule)(b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color, void* context); -static void DrawConstraint(cpConstraint* constraint, DrawNode* renderer) +/// Draw a line segment. +// void (*DrawSegment)(b2Vec2 p1, b2Vec2 p2, b2HexColor color, void* context); +static void b2DrawSegment(b2Vec2 p1, b2Vec2 p2, b2HexColor color, PhysicsDebugNode* dn) { - cpBody* body_a = cpConstraintGetBodyA(constraint); - cpBody* body_b = cpConstraintGetBodyB(constraint); - - if (cpConstraintIsPinJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpPinJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpPinJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsSlideJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpSlideJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpSlideJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsPivotJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpPivotJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpPivotJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsGrooveJoint(constraint)) - { - cpVect a = cpvadd(cpBodyGetPosition(body_a), - cpvrotate(cpGrooveJointGetGrooveA(constraint), cpBodyGetRotation(body_a))); - cpVect b = cpvadd(cpBodyGetPosition(body_a), - cpvrotate(cpGrooveJointGetGrooveB(constraint), cpBodyGetRotation(body_a))); - cpVect c = cpvadd(cpBodyGetPosition(body_b), - cpvrotate(cpGrooveJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(c), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsDampedSpring(constraint)) - { - cpDampedSpring* spring = (cpDampedSpring*)constraint; + dn->drawLine(Vec2(p1.x * dn->getPTMRatio(), p1.y * dn->getPTMRatio()) + dn->getWorldOffset(), + Vec2(p2.x * dn->getPTMRatio(), p2.y * dn->getPTMRatio()) + dn->getWorldOffset(), + PhysicsHelper::toColor(color)); +} - cpVect a = cpTransformPoint(body_a->transform, spring->anchorA); - cpVect b = cpTransformPoint(body_b->transform, spring->anchorB); +/// Draw a transform. Choose your own length scale. +// void (*DrawTransform)(b2Transform transform, void* context); +static void b2DrawTransform(b2Transform t, PhysicsDebugNode* dn) +{ + b2Vec2 p1 = t.p, p2; + const float k_axisScale = 0.4f; - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); + p2 = p1 + k_axisScale * b2Rot_GetXAxis(t.q); + b2DrawSegment(p1, p2, b2HexColor::b2_colorRed, dn); - cpVect delta = cpvsub(b, a); - cpFloat cos = delta.x; - cpFloat sin = delta.y; - cpFloat s = 1.0f / cpvlength(delta); + p2 = p1 + k_axisScale * b2Rot_GetYAxis(t.q); + b2DrawSegment(p1, p2, b2HexColor::b2_colorGreen, dn); +} - cpVect r1 = cpv(cos, -sin * s); - cpVect r2 = cpv(sin, cos * s); +/// Draw a point. +// void (*DrawPoint)(b2Vec2 p, float size, b2HexColor color, void* context); +static void b2DrawPoint(b2Vec2 p, float size, b2HexColor color, PhysicsDebugNode* dn) +{ + dn->drawPoint(Vec2(p.x * dn->getPTMRatio(), p.y * dn->getPTMRatio()) + dn->getWorldOffset(), size, + PhysicsHelper::toColor(color)); +} - cpVect* verts = (cpVect*)alloca(spring_count * sizeof(cpVect)); - for (int i = 0; i < spring_count; i++) - { - cpVect v = spring_verts[i]; - verts[i] = cpv(cpvdot(v, r1) + a.x, cpvdot(v, r2) + a.y); - } +bool PhysicsDebugNode::initWithWorld(b2WorldId worldId) +{ + bool ret = DrawNode::init(); - for (int i = 0; i < spring_count - 1; i++) - { - renderer->drawSegment(cpVert2Point(verts[i]), cpVert2Point(verts[i + 1]), 1.0, CONSTRAINT_COLOR); - } - } - else - { - AXLOGD("Cannot draw constraint"); - } + _world = worldId; + return ret; } -// implementation of PhysicsDebugNode - void PhysicsDebugNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) { - if (!_spacePtr) + if (!b2World_IsValid(_world)) { return; } - // clear the shapes information before draw current shapes. - DrawNode::clear(); - cpSpaceEachShape(_spacePtr, (cpSpaceShapeIteratorFunc)DrawShape, this); - cpSpaceEachConstraint(_spacePtr, (cpSpaceConstraintIteratorFunc)DrawConstraint, this); + if (_autoDraw) + { + // clear the shapes information before draw current shapes. + clear(); + b2World_Draw(_world, &_debugDraw); + } DrawNode::draw(renderer, transform, flags); } -PhysicsDebugNode::PhysicsDebugNode() : _spacePtr(nullptr) {} - -PhysicsDebugNode* PhysicsDebugNode::create(cpSpace* space) -{ - PhysicsDebugNode* node = new PhysicsDebugNode(); - node->init(); - node->_spacePtr = space; - node->autorelease(); - return node; -} - -PhysicsDebugNode::~PhysicsDebugNode() {} - -cpSpace* PhysicsDebugNode::getSpace() const +PhysicsDebugNode::PhysicsDebugNode() { - return _spacePtr; -} - -void PhysicsDebugNode::setSpace(cpSpace* space) -{ - _spacePtr = space; + _debugDraw.context = this; +#define __b2_setfun(f) _debugDraw.f##Fcn = reinterpret_cast(b2##f); + __b2_setfun(DrawPolygon); + __b2_setfun(DrawSolidPolygon); + __b2_setfun(DrawCircle); + __b2_setfun(DrawSolidCircle); + __b2_setfun(DrawSegment); + __b2_setfun(DrawTransform); + __b2_setfun(DrawPoint); +#undef __b2_setfun } NS_AX_EXT_END + +#if defined(_WIN32) +# pragma pop_macro("TRANSPARENT") +#endif diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.h b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.h index 0dafeed895d7..7f9be39b217e 100644 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.h +++ b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNode.h @@ -1,68 +1,65 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. +/* + * Copyright (c) 2019 Erin Catto * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. + * This software is provided 'as-is', without any express or implied + * warranty. In no event will the authors be held liable for any damages + * arising from the use of this software. + * Permission is granted to anyone to use this software for any purpose, + * including commercial applications, and to alter it and redistribute it + * freely, subject to the following restrictions: + * 1. The origin of this software must not be misrepresented; you must not + * claim that you wrote the original software. If you use this software + * in a product, an acknowledgment in the product documentation would be + * appreciated but is not required. + * 2. Altered source versions must be plainly marked as such, and must not be + * misrepresented as being the original software. + * 3. This notice may not be removed or altered from any source distribution. */ #pragma once #include "extensions/ExtensionMacros.h" -#include "2d/DrawNode.h" #include "extensions/ExtensionExport.h" - -struct cpSpace; +#include "axmol/2d/DrawNode.h" +#include "box2d/box2d.h" +#include "axmol/axmol.h" NS_AX_EXT_BEGIN -/** - * A BaseData that draws the components of a physics engine. - - * Supported physics engines: - * - Chipmunk - * - Objective-Chipmunk - * @since v2.1 - * @lua NA - */ - +// This class implements debug drawing callbacks that are invoked inside b2World::Step. class AX_EX_DLL PhysicsDebugNode : public DrawNode { - public: - /** Create a debug node for a regular Chipmunk space. */ - static PhysicsDebugNode* create(cpSpace* space); - /** - */ PhysicsDebugNode(); - /** - */ - virtual ~PhysicsDebugNode(); + virtual bool initWithWorld(b2WorldId worldId); + + void setAutoDraw(bool bval) { _autoDraw = bval; } + bool isAutoDraw() const { return _autoDraw; } + + // control border thinkness + void setThinkness(float fval) { _thinkness = fval; } + float getThinkness() const { return _thinkness; } - cpSpace* getSpace() const; - void setSpace(cpSpace* space); + void setWorldOffset(const Vec2& offset) { _worldOffset = offset; } + const Vec2& getWorldOffset() const { return _worldOffset; } + + void setPTMRatio(float ratio) { _ratio = ratio; } + float getPTMRatio() const { return _ratio; } // Overrides - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; + + b2DebugDraw& getB2DebugDraw() { return _debugDraw; } protected: - cpSpace* _spacePtr; + b2WorldId _world{}; + b2DebugDraw _debugDraw{b2DefaultDebugDraw()}; + bool _autoDraw{true}; + float _thinkness{0.5f}; + + ax::Vec2 _worldOffset{}; + float _ratio{1.0f}; }; NS_AX_EXT_END diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.cpp deleted file mode 100644 index b63fd556ba49..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.cpp +++ /dev/null @@ -1,113 +0,0 @@ -/* - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "PhysicsDebugNodeBox2D.h" - -NS_AX_EXT_BEGIN - -PhysicsDebugNodeBox2D::PhysicsDebugNodeBox2D() -{ - drawBP = DrawNode::create(); - debugNodeOffset = {40.0f, 0.0f}; - mRatio = 1.0f; -} - -PhysicsDebugNodeBox2D::~PhysicsDebugNodeBox2D() {} - -ax::DrawNode* PhysicsDebugNodeBox2D::GetDrawNode() -{ - return drawBP; -} - -void PhysicsDebugNodeBox2D::SetDrawNode(ax::DrawNode* drawNode) -{ - drawBP = drawNode; -} - -ax::Vec2& PhysicsDebugNodeBox2D::GetDebugNodeOffset() -{ - return debugNodeOffset; -} - -void PhysicsDebugNodeBox2D::DrawPolygon(const b2Vec2* verts, int vertexCount, const b2Color& color) -{ - Vec2* vec = new Vec2[vertexCount]; - for (size_t i = 0; i < vertexCount; i++) - { - vec[i] = Vec2(verts[i].x * mRatio, verts[i].y * mRatio) + debugNodeOffset; - } - drawBP->drawPolygon(vec, vertexCount, Color4F::BLACK, 0.4f, Color4F(color.r, color.g, color.b, color.a)); -} - -void PhysicsDebugNodeBox2D::DrawSolidPolygon(const b2Vec2* verts, int vertexCount, const b2Color& color) -{ - Vec2* vec = new Vec2[vertexCount]; - for (size_t i = 0; i < vertexCount; i++) - { - vec[i] = Vec2(verts[i].x * mRatio, verts[i].y * mRatio) + debugNodeOffset; - } - drawBP->drawPolygon(vec, vertexCount, Color4F(color.r / 2, color.g / 2, color.b / 2, color.a), 0.4f, - Color4F(color.r, color.g, color.b, color.a)); -} - -void PhysicsDebugNodeBox2D::DrawCircle(const b2Vec2& center, float radius, const b2Color& color) -{ - drawBP->drawCircle(Vec2(center.x * mRatio, center.y * mRatio) + debugNodeOffset, radius * mRatio, - AX_DEGREES_TO_RADIANS(0), 30, true, 1.0f, 1.0f, Color4F(color.r, color.g, color.b, color.a)); -} - -void PhysicsDebugNodeBox2D::DrawSolidCircle(const b2Vec2& center, - float radius, - const b2Vec2& axis, - const b2Color& color) -{ - Vec2 c = {Vec2(center.x * mRatio, center.y * mRatio) + debugNodeOffset}; - drawBP->drawSolidCircle(c, radius * mRatio, AX_DEGREES_TO_RADIANS(0), 20, 1.0f, 1.0f, - Color4F(color.r / 2, color.g / 2, color.b / 2, color.a), 0.4f, - Color4F(color.r, color.g, color.b, color.a)); - - // Draw a line fixed in the circle to animate rotation. - b2Vec2 pp = {(center + radius * axis)}; - Vec2 cp = {Vec2(pp.x * mRatio, pp.y * mRatio) + debugNodeOffset}; - drawBP->drawLine(c, cp, Color4F(color.r, color.g, color.b, color.a)); -} - -void PhysicsDebugNodeBox2D::DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) -{ - drawBP->drawLine(Vec2(p1.x * mRatio, p1.y * mRatio) + debugNodeOffset, - Vec2(p2.x * mRatio, p2.y * mRatio) + debugNodeOffset, Color4F(color.r, color.g, color.b, color.a)); -} - -void PhysicsDebugNodeBox2D::DrawTransform(const b2Transform& xf) -{ - b2Vec2 p1 = xf.p, p2; - const float k_axisScale = 0.4f; - p2 = p1 + k_axisScale * xf.q.GetXAxis(); - DrawSegment(p1, p2, b2Color(1.0f, 0.0f, 0.0f)); - - p2 = p1 + k_axisScale * xf.q.GetYAxis(); - DrawSegment(p1, p2, b2Color(0.0f, 1.0f, 0.0f)); -} - -void PhysicsDebugNodeBox2D::DrawPoint(const b2Vec2& p, float size, const b2Color& color) -{ - drawBP->drawPoint(Vec2(p.x * mRatio, p.y * mRatio) + debugNodeOffset, size, - Color4F(color.r, color.g, color.b, color.a)); -} - -NS_AX_EXT_END \ No newline at end of file diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.h b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.h deleted file mode 100644 index b840aa893569..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeBox2D.h +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2019 Erin Catto - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#pragma once - -#include "extensions/ExtensionMacros.h" -#include "extensions/ExtensionExport.h" -#include "2d/DrawNode.h" -#include "box2d/box2d.h" -#include "axmol.h" - -NS_AX_EXT_BEGIN - -// This class implements debug drawing callbacks that are invoked inside b2World::Step. -class AX_EX_DLL PhysicsDebugNodeBox2D : public b2Draw -{ -public: - PhysicsDebugNodeBox2D(); - ~PhysicsDebugNodeBox2D(); - - void Create(); - void Destroy(); - - void DrawPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color) override; - - void DrawSolidPolygon(const b2Vec2* vertices, int vertexCount, const b2Color& color) override; - - void DrawCircle(const b2Vec2& center, float radius, const b2Color& color) override; - - void DrawSolidCircle(const b2Vec2& center, float radius, const b2Vec2& axis, const b2Color& color) override; - - void DrawSegment(const b2Vec2& p1, const b2Vec2& p2, const b2Color& color) override; - - void DrawTransform(const b2Transform& xf) override; - - void DrawPoint(const b2Vec2& p, float size, const b2Color& color) override; - - // axis stuffs - ax::DrawNode* GetDrawNode(); - void SetDrawNode(ax::DrawNode* drawNode); - ax::Vec2& GetDebugNodeOffset(); - - ax::DrawNode* drawBP = NULL; // axis "interface"! - ax::Vec2 debugNodeOffset; - float mRatio; - -private: -}; - -NS_AX_EXT_END - diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.cpp deleted file mode 100644 index bd313debc5e2..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.cpp +++ /dev/null @@ -1,254 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include "PhysicsDebugNodeChipmunk2D.h" - -#include "chipmunk/chipmunk_private.h" - -#include "base/Types.h" -#include "math/Math.h" - -#include -#include -#include -#include -#include - -NS_AX_EXT_BEGIN - -Vec2 physicsDebugNodeOffset; - -/* - IMPORTANT - READ ME! - - This file sets pokes around in the private API a lot to provide efficient - debug rendering given nothing more than reference to a Chipmunk space. - It is not recommended to write rendering code like this in your own games - as the private API may change with little or no warning. - */ - -static const cpVect spring_verts[] = { - {0.00f, 0.0f}, {0.20f, 0.0f}, {0.25f, 3.0f}, {0.30f, -6.0f}, {0.35f, 6.0f}, - {0.40f, -6.0f}, {0.45f, 6.0f}, {0.50f, -6.0f}, {0.55f, 6.0f}, {0.60f, -6.0f}, - {0.65f, 6.0f}, {0.70f, -3.0f}, {0.75f, 6.0f}, {0.80f, 0.0f}, {1.00f, 0.0f}, -}; -static const int spring_count = sizeof(spring_verts) / sizeof(cpVect); - -static Color4B ColorForBody(cpBody* body) -{ - if (CP_BODY_TYPE_STATIC == cpBodyGetType(body) || cpBodyIsSleeping(body)) - { - return Color4B(127, 127, 127, 127); - } - else if (body->sleeping.idleTime > cpBodyGetSpace(body)->sleepTimeThreshold) - { - return Color4B(85, 85, 85, 127); - } - else - { - return Color4B(255, 0, 0, 127); - } -} - -static Vec2 cpVert2Point(const cpVect& vert) -{ - return (Vec2(vert.x, vert.y) + physicsDebugNodeOffset); -} - -static void DrawShape(cpShape* shape, DrawNode* renderer) -{ - cpBody* body = cpShapeGetBody(shape); - Color4B color = ColorForBody(body); - - switch (shape->klass->type) - { - case CP_CIRCLE_SHAPE: - { - cpCircleShape* circle = (cpCircleShape*)shape; - cpVect center = circle->tc; - cpFloat radius = circle->r; - renderer->drawDot(cpVert2Point(center), cpfmax(radius, 1.0), color); - renderer->drawSegment(cpVert2Point(center), - cpVert2Point(cpvadd(center, cpvmult(cpBodyGetRotation(body), radius))), 1.0, color); - } - break; - case CP_SEGMENT_SHAPE: - { - cpSegmentShape* seg = (cpSegmentShape*)shape; - renderer->drawSegment(cpVert2Point(seg->ta), cpVert2Point(seg->tb), cpfmax(seg->r, 1.0), color); - } - break; - case CP_POLY_SHAPE: - { - cpPolyShape* poly = (cpPolyShape*)shape; - Color4B line = color; - line.a = cpflerp(color.a, 1.0, 0.5); - int num = poly->count; - Vec2* pPoints = new Vec2[num]; - for (int i = 0; i < num; ++i) - pPoints[i] = cpVert2Point(poly->planes[i].v0); - if (cpfmax(poly->r, 1.0) > 1.0) - { - renderer->drawPolygon(pPoints, num, Color4B(127, 127, 127,0), poly->r, color); - } - else - { - renderer->drawPolygon(pPoints, num, color, 1.0, line); - } - - AX_SAFE_DELETE_ARRAY(pPoints); - } - break; - default: - cpAssertHard(false, "Bad assertion in DrawShape()"); - } -} - -static Color4B CONSTRAINT_COLOR(0, 255, 0, 127); - -static void DrawConstraint(cpConstraint* constraint, DrawNode* renderer) -{ - cpBody* body_a = cpConstraintGetBodyA(constraint); - cpBody* body_b = cpConstraintGetBodyB(constraint); - - if (cpConstraintIsPinJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpPinJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpPinJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsSlideJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpSlideJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpSlideJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsPivotJoint(constraint)) - { - cpVect a = - cpvadd(cpBodyGetPosition(body_a), cpvrotate(cpPivotJointGetAnchorA(constraint), cpBodyGetRotation(body_a))); - cpVect b = - cpvadd(cpBodyGetPosition(body_b), cpvrotate(cpPivotJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsGrooveJoint(constraint)) - { - cpVect a = cpvadd(cpBodyGetPosition(body_a), - cpvrotate(cpGrooveJointGetGrooveA(constraint), cpBodyGetRotation(body_a))); - cpVect b = cpvadd(cpBodyGetPosition(body_a), - cpvrotate(cpGrooveJointGetGrooveB(constraint), cpBodyGetRotation(body_a))); - cpVect c = cpvadd(cpBodyGetPosition(body_b), - cpvrotate(cpGrooveJointGetAnchorB(constraint), cpBodyGetRotation(body_b))); - - renderer->drawDot(cpVert2Point(c), 3.0, CONSTRAINT_COLOR); - renderer->drawSegment(cpVert2Point(a), cpVert2Point(b), 1.0, CONSTRAINT_COLOR); - } - else if (cpConstraintIsDampedSpring(constraint)) - { - cpDampedSpring* spring = (cpDampedSpring*)constraint; - - cpVect a = cpTransformPoint(body_a->transform, spring->anchorA); - cpVect b = cpTransformPoint(body_b->transform, spring->anchorB); - - renderer->drawDot(cpVert2Point(a), 3.0, CONSTRAINT_COLOR); - renderer->drawDot(cpVert2Point(b), 3.0, CONSTRAINT_COLOR); - - cpVect delta = cpvsub(b, a); - cpFloat cos = delta.x; - cpFloat sin = delta.y; - cpFloat s = 1.0f / cpvlength(delta); - - cpVect r1 = cpv(cos, -sin * s); - cpVect r2 = cpv(sin, cos * s); - - cpVect* verts = (cpVect*)alloca(spring_count * sizeof(cpVect)); - for (int i = 0; i < spring_count; i++) - { - cpVect v = spring_verts[i]; - verts[i] = cpv(cpvdot(v, r1) + a.x, cpvdot(v, r2) + a.y); - } - - for (int i = 0; i < spring_count - 1; i++) - { - renderer->drawSegment(cpVert2Point(verts[i]), cpVert2Point(verts[i + 1]), 1.0, CONSTRAINT_COLOR); - } - } - else - { - AXLOGD("Cannot draw constraint"); - } -} - -// implementation of PhysicsDebugNode - -void PhysicsDebugNodeChipmunk2D::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) -{ - if (!_spacePtr) - { - return; - } - // clear the shapes information before draw current shapes. - DrawNode::clear(); - - cpSpaceEachShape(_spacePtr, (cpSpaceShapeIteratorFunc)DrawShape, this); - cpSpaceEachConstraint(_spacePtr, (cpSpaceConstraintIteratorFunc)DrawConstraint, this); - - DrawNode::draw(renderer, transform, flags); -} - -PhysicsDebugNodeChipmunk2D::PhysicsDebugNodeChipmunk2D() : _spacePtr(nullptr) {} - -PhysicsDebugNodeChipmunk2D* PhysicsDebugNodeChipmunk2D::create(cpSpace* space) -{ - PhysicsDebugNodeChipmunk2D* node = new PhysicsDebugNodeChipmunk2D(); - node->init(); - node->_spacePtr = space; - node->autorelease(); - return node; -} - -PhysicsDebugNodeChipmunk2D::~PhysicsDebugNodeChipmunk2D() {} - -cpSpace* PhysicsDebugNodeChipmunk2D::getSpace() const -{ - return _spacePtr; -} - -void PhysicsDebugNodeChipmunk2D::setSpace(cpSpace* space) -{ - _spacePtr = space; -} - -NS_AX_EXT_END diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.h b/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.h deleted file mode 100644 index 14e5f6d90c42..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsDebugNodeChipmunk2D.h +++ /dev/null @@ -1,71 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "extensions/ExtensionMacros.h" -#include "2d/DrawNode.h" -#include "extensions/ExtensionExport.h" - -struct cpSpace; - -NS_AX_EXT_BEGIN - -extern AX_EX_DLL Vec2 physicsDebugNodeOffset; - -/** - * A BaseData that draws the components of a physics engine. - - * Supported physics engines: - * - Chipmunk - * - Objective-Chipmunk - * @since v2.1 - * @lua NA - */ - -class AX_EX_DLL PhysicsDebugNodeChipmunk2D : public DrawNode -{ - -public: - /** Create a debug node for a regular Chipmunk space. */ - static PhysicsDebugNodeChipmunk2D* create(cpSpace* space); - /** - */ - PhysicsDebugNodeChipmunk2D(); - /** - */ - virtual ~PhysicsDebugNodeChipmunk2D(); - - cpSpace* getSpace() const; - void setSpace(cpSpace* space); - - // Overrides - virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; - -protected: - cpSpace* _spacePtr; -}; - -NS_AX_EXT_END - diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.cpp index e26033fe5053..87114b2aaf8d 100644 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.cpp +++ b/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.cpp @@ -23,21 +23,13 @@ */ #include "PhysicsSprite.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" - -#if (AX_ENABLE_CHIPMUNK_INTEGRATION || AX_ENABLE_BOX2D_INTEGRATION) - -# if AX_ENABLE_CHIPMUNK_INTEGRATION -# include "chipmunk/chipmunk.h" -# elif AX_ENABLE_BOX2D_INTEGRATION -# include "box2d/box2d.h" -# endif +#include "axmol/base/Director.h" +#include "axmol/base/EventDispatcher.h" NS_AX_EXT_BEGIN PhysicsSprite::PhysicsSprite() - : _ignoreBodyRotation(false), _CPBody(nullptr), _pB2Body(nullptr), _PTMRatio(0.0f), _syncTransform(nullptr) + : _ignoreBodyRotation(false), _PTMRatio(0.0f), _syncTransform(nullptr) {} PhysicsSprite* PhysicsSprite::create() @@ -196,67 +188,24 @@ Vec3 PhysicsSprite::getPosition3D() const return Vec3(pos.x, pos.y, 0); } -// -// Chipmunk only -// - -cpBody* PhysicsSprite::getCPBody() const +b2BodyId PhysicsSprite::getB2Body() const { -# if AX_ENABLE_CHIPMUNK_INTEGRATION - return _CPBody; -# else - AXASSERT(false, "Can't call chipmunk methods when Chipmunk is disabled"); - return nullptr; -# endif + return _bodyId; } -void PhysicsSprite::setCPBody(cpBody* pBody) +void PhysicsSprite::setB2Body(b2BodyId pBody) { -# if AX_ENABLE_CHIPMUNK_INTEGRATION - _CPBody = pBody; -# else - AXASSERT(false, "Can't call chipmunk methods when Chipmunk is disabled"); -# endif -} - -b2Body* PhysicsSprite::getB2Body() const -{ -# if AX_ENABLE_BOX2D_INTEGRATION - return _pB2Body; -# else - AXASSERT(false, "Can't call box2d methods when Box2d is disabled"); - return nullptr; -# endif -} - -void PhysicsSprite::setB2Body(b2Body* pBody) -{ -# if AX_ENABLE_BOX2D_INTEGRATION - _pB2Body = pBody; -# else - AX_UNUSED_PARAM(pBody); - AXASSERT(false, "Can't call box2d methods when Box2d is disabled"); -# endif + _bodyId = pBody; } float PhysicsSprite::getPTMRatio() const { -# if AX_ENABLE_BOX2D_INTEGRATION return _PTMRatio; -# else - AXASSERT(false, "Can't call box2d methods when Box2d is disabled"); - return 0; -# endif } void PhysicsSprite::setPTMRatio(float fRatio) { -# if AX_ENABLE_BOX2D_INTEGRATION _PTMRatio = fRatio; -# else - AX_UNUSED_PARAM(fRatio); - AXASSERT(false, "Can't call box2d methods when Box2d is disabled"); -# endif } // @@ -266,33 +215,18 @@ void PhysicsSprite::setPTMRatio(float fRatio) const Vec2& PhysicsSprite::getPosFromPhysics() const { static Vec2 s_physicPosion; -# if AX_ENABLE_CHIPMUNK_INTEGRATION - - cpVect cpPos = cpBodyGetPosition(_CPBody); - s_physicPosion = Vec2(cpPos.x, cpPos.y); - -# elif AX_ENABLE_BOX2D_INTEGRATION - - b2Vec2 pos = _pB2Body->GetPosition(); + b2Vec2 pos = b2Body_GetPosition(_bodyId); float x = pos.x * _PTMRatio; float y = pos.y * _PTMRatio; s_physicPosion.set(x, y); -# endif + return s_physicPosion; } void PhysicsSprite::setPosition(float x, float y) { -# if AX_ENABLE_CHIPMUNK_INTEGRATION - - cpVect cpPos = cpv(x, y); - cpBodySetPosition(_CPBody, cpPos); - -# elif AX_ENABLE_BOX2D_INTEGRATION - - float angle = _pB2Body->GetAngle(); - _pB2Body->SetTransform(b2Vec2(x / _PTMRatio, y / _PTMRatio), angle); -# endif + auto rot = b2Body_GetRotation(_bodyId); + b2Body_SetTransform(_bodyId, b2Vec2{x / _PTMRatio, y / _PTMRatio}, rot); } void PhysicsSprite::setPosition(const Vec2& pos) @@ -317,16 +251,8 @@ void PhysicsSprite::setPosition3D(const Vec3& position) float PhysicsSprite::getRotation() const { -# if AX_ENABLE_CHIPMUNK_INTEGRATION - - return (_ignoreBodyRotation ? Sprite::getRotation() : -AX_RADIANS_TO_DEGREES(cpBodyGetAngle(_CPBody))); - -# elif AX_ENABLE_BOX2D_INTEGRATION - - return (_ignoreBodyRotation ? Sprite::getRotation() : AX_RADIANS_TO_DEGREES(_pB2Body->GetAngle())); -# else - return 0.0f; -# endif + auto angle = b2Rot_GetAngle(b2Body_GetRotation(_bodyId)); + return (_ignoreBodyRotation ? Sprite::getRotation() : AX_RADIANS_TO_DEGREES(angle)); } void PhysicsSprite::setRotation(float fRotation) @@ -336,20 +262,13 @@ void PhysicsSprite::setRotation(float fRotation) Sprite::setRotation(fRotation); } -# if AX_ENABLE_CHIPMUNK_INTEGRATION - else - { - cpBodySetAngle(_CPBody, -AX_DEGREES_TO_RADIANS(fRotation)); - } - -# elif AX_ENABLE_BOX2D_INTEGRATION else { - b2Vec2 p = _pB2Body->GetPosition(); + b2Vec2 p = b2Body_GetPosition(_bodyId); float radians = AX_DEGREES_TO_RADIANS(fRotation); - _pB2Body->SetTransform(p, radians); + auto rot = b2MakeRot(radians); + b2Body_SetTransform(_bodyId, p, rot); } -# endif } void PhysicsSprite::syncPhysicsTransform() const @@ -358,42 +277,7 @@ void PhysicsSprite::syncPhysicsTransform() const // the sprite is animated (scaled up/down) using actions. // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 -# if AX_ENABLE_CHIPMUNK_INTEGRATION - - cpVect rot = (_ignoreBodyRotation ? cpvforangle(-AX_DEGREES_TO_RADIANS(_rotationX)) : cpBodyGetRotation(_CPBody)); - float x = cpBodyGetPosition(_CPBody).x + rot.x * -_anchorPointInPoints.x * _scaleX - - rot.y * -_anchorPointInPoints.y * _scaleY; - float y = cpBodyGetPosition(_CPBody).y + rot.y * -_anchorPointInPoints.x * _scaleX + - rot.x * -_anchorPointInPoints.y * _scaleY; - - if (_ignoreAnchorPointForPosition) - { - x += _anchorPointInPoints.x; - y += _anchorPointInPoints.y; - } - - float mat[] = {(float)rot.x * _scaleX, - (float)rot.y * _scaleX, - 0, - 0, - (float)-rot.y * _scaleY, - (float)rot.x * _scaleY, - 0, - 0, - 0, - 0, - 1, - 0, - x, - y, - 0, - 1}; - - _transform.set(mat); - -# elif AX_ENABLE_BOX2D_INTEGRATION - - b2Vec2 pos = _pB2Body->GetPosition(); + b2Vec2 pos = b2Body_GetPosition(_bodyId); float x = pos.x * _PTMRatio; float y = pos.y * _PTMRatio; @@ -405,7 +289,8 @@ void PhysicsSprite::syncPhysicsTransform() const } // Make matrix - float radians = _pB2Body->GetAngle(); + auto rot = b2Body_GetRotation(_bodyId); + float radians = b2Rot_GetAngle(rot); float c = cosf(radians); float s = sinf(radians); @@ -435,7 +320,6 @@ void PhysicsSprite::syncPhysicsTransform() const 1}; _transform.set(mat); -# endif } void PhysicsSprite::onEnter() @@ -466,5 +350,3 @@ void PhysicsSprite::afterUpdate(EventCustom* /*event*/) } NS_AX_EXT_END - -#endif // AX_ENABLE_CHIPMUNK_INTEGRATION || AX_ENABLE_BOX2D_INTEGRATION diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.h b/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.h index b31d06ac2a71..5e7ecd9b5917 100644 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.h +++ b/extensions/physics-nodes/src/physics-nodes/PhysicsSprite.h @@ -24,23 +24,18 @@ #pragma once -#include "2d/Sprite.h" +#include "axmol/2d/Sprite.h" #include "extensions/ExtensionMacros.h" #include "extensions/ExtensionExport.h" -#include "base/EventListenerCustom.h" +#include "axmol/base/EventListenerCustom.h" -#if (AX_ENABLE_CHIPMUNK_INTEGRATION || AX_ENABLE_BOX2D_INTEGRATION) - -struct cpBody; -class b2Body; +#include "box2d/box2d.h" NS_AX_EXT_BEGIN /** A Sprite subclass that is bound to a physics body. It works with: - - Chipmunk: Preprocessor macro AX_ENABLE_CHIPMUNK_INTEGRATION should be defined - - Objective-Chipmunk: Preprocessor macro AX_ENABLE_CHIPMUNK_INTEGRATION should be defined - - Box2d: Preprocessor macro AX_ENABLE_BOX2D_INTEGRATION should be defined + - Box2D Features and Limitations: - Scale and Skew properties are ignored. @@ -87,46 +82,39 @@ class AX_EX_DLL PhysicsSprite : public Sprite PhysicsSprite(); - virtual bool isDirty() const override; + bool isDirty() const override; /** Keep the sprite's rotation separate from the body. */ bool isIgnoreBodyRotation() const; void setIgnoreBodyRotation(bool bIgnoreBodyRotation); - // - // Chipmunk specific - // - /** Body accessor when using regular Chipmunk */ - cpBody* getCPBody() const; - void setCPBody(cpBody* pBody); - // // Box2d specific // /** Body accessor when using box2d */ - b2Body* getB2Body() const; - void setB2Body(b2Body* pBody); + b2BodyId getB2Body() const; + void setB2Body(b2BodyId pBody); float getPTMRatio() const; void setPTMRatio(float fPTMRatio); virtual void syncPhysicsTransform() const; // overrides - virtual const Vec2& getPosition() const override; - virtual void getPosition(float* x, float* y) const override; - virtual float getPositionX() const override; - virtual float getPositionY() const override; - virtual Vec3 getPosition3D() const override; - virtual void setPosition(const Vec2& position) override; - virtual void setPosition(float x, float y) override; - virtual void setPositionX(float x) override; - virtual void setPositionY(float y) override; - virtual void setPosition3D(const Vec3& position) override; - virtual float getRotation() const override; - virtual void setRotation(float fRotation) override; - - virtual void onEnter() override; - virtual void onExit() override; + const Vec2& getPosition() const override; + void getPosition(float* x, float* y) const override; + float getPositionX() const override; + float getPositionY() const override; + Vec3 getPosition3D() const override; + void setPosition(const Vec2& position) override; + void setPosition(float x, float y) override; + void setPositionX(float x) override; + void setPositionY(float y) override; + void setPosition3D(const Vec3& position) override; + float getRotation() const override; + void setRotation(float fRotation) override; + + void onEnter() override; + void onExit() override; protected: const Vec2& getPosFromPhysics() const; @@ -135,11 +123,8 @@ class AX_EX_DLL PhysicsSprite : public Sprite protected: bool _ignoreBodyRotation; - // chipmunk specific - cpBody* _CPBody; - // box2d specific - b2Body* _pB2Body; + b2BodyId _bodyId{}; float _PTMRatio; // Event for update synchronise physic transform @@ -148,4 +133,3 @@ class AX_EX_DLL PhysicsSprite : public Sprite NS_AX_EXT_END -#endif // AX_ENABLE_CHIPMUNK_INTEGRATION || AX_ENABLE_BOX2D_INTEGRATION diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.cpp deleted file mode 100644 index 352d5b8fb7cf..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.cpp +++ /dev/null @@ -1,352 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "PhysicsSpriteBox2D.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" - -#include "box2d/box2d.h" - -NS_AX_EXT_BEGIN - -PhysicsSpriteBox2D::PhysicsSpriteBox2D() - : _ignoreBodyRotation(false), _pB2Body(nullptr), _PTMRatio(0.0f), _syncTransform(nullptr) -{} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::create() -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->init()) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithTexture(Texture2D* pTexture) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithTexture(pTexture)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithTexture(Texture2D* pTexture, const Rect& rect) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithTexture(pTexture, rect)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithSpriteFrame(SpriteFrame* pSpriteFrame) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithSpriteFrame(pSpriteFrame)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::createWithSpriteFrameName(const char* pszSpriteFrameName) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithSpriteFrameName(pszSpriteFrameName)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::create(const char* pszFileName) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithFile(pszFileName)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteBox2D* PhysicsSpriteBox2D::create(const char* pszFileName, const Rect& rect) -{ - PhysicsSpriteBox2D* pRet = new PhysicsSpriteBox2D(); - if (pRet->initWithFile(pszFileName, rect)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -// this method will only get called if the sprite is batched. -// return YES if the physic's values (angles, position ) changed. -// If you return NO, then getNodeToParentTransform won't be called. -bool PhysicsSpriteBox2D::isDirty() const -{ - return true; -} - -bool PhysicsSpriteBox2D::isIgnoreBodyRotation() const -{ - return _ignoreBodyRotation; -} - -void PhysicsSpriteBox2D::setIgnoreBodyRotation(bool bIgnoreBodyRotation) -{ - _ignoreBodyRotation = bIgnoreBodyRotation; -} - -// Override the setters and getters to always reflect the body's properties. -const Vec2& PhysicsSpriteBox2D::getPosition() const -{ - return getPosFromPhysics(); -} - -void PhysicsSpriteBox2D::getPosition(float* x, float* y) const -{ - if (x == nullptr || y == nullptr) - { - return; - } - const Vec2& pos = getPosFromPhysics(); - *x = pos.x; - *y = pos.y; -} - -float PhysicsSpriteBox2D::getPositionX() const -{ - return getPosFromPhysics().x; -} - -float PhysicsSpriteBox2D::getPositionY() const -{ - return getPosFromPhysics().y; -} - -Vec3 PhysicsSpriteBox2D::getPosition3D() const -{ - Vec2 pos = getPosFromPhysics(); - return Vec3(pos.x, pos.y, 0); -} - -b2Body* PhysicsSpriteBox2D::getB2Body() const -{ - return _pB2Body; -} - -void PhysicsSpriteBox2D::setB2Body(b2Body* pBody) -{ - _pB2Body = pBody; -} - -float PhysicsSpriteBox2D::getPTMRatio() const -{ - return _PTMRatio; -} - -void PhysicsSpriteBox2D::setPTMRatio(float fRatio) -{ - _PTMRatio = fRatio; -} - -// -// Common to Box2d and Chipmunk -// - -const Vec2& PhysicsSpriteBox2D::getPosFromPhysics() const -{ - static Vec2 s_physicPosion; - - b2Vec2 pos = _pB2Body->GetPosition(); - float x = pos.x * _PTMRatio; - float y = pos.y * _PTMRatio; - s_physicPosion.set(x, y); - - return s_physicPosion; -} - -void PhysicsSpriteBox2D::setPosition(float x, float y) -{ - float angle = _pB2Body->GetAngle(); - _pB2Body->SetTransform(b2Vec2(x / _PTMRatio, y / _PTMRatio), angle); -} - -void PhysicsSpriteBox2D::setPosition(const Vec2& pos) -{ - setPosition(pos.x, pos.y); -} - -void PhysicsSpriteBox2D::setPositionX(float x) -{ - setPosition(x, getPositionY()); -} - -void PhysicsSpriteBox2D::setPositionY(float y) -{ - setPosition(getPositionX(), y); -} - -void PhysicsSpriteBox2D::setPosition3D(const Vec3& position) -{ - setPosition(position.x, position.y); -} - -float PhysicsSpriteBox2D::getRotation() const -{ - return (_ignoreBodyRotation ? Sprite::getRotation() : AX_RADIANS_TO_DEGREES(_pB2Body->GetAngle())); -} - -void PhysicsSpriteBox2D::setRotation(float fRotation) -{ - if (_ignoreBodyRotation) - { - Sprite::setRotation(fRotation); - } - - else - { - b2Vec2 p = _pB2Body->GetPosition(); - float radians = AX_DEGREES_TO_RADIANS(fRotation); - _pB2Body->SetTransform(p, radians); - } -} - -void PhysicsSpriteBox2D::syncPhysicsTransform() const -{ - // Although scale is not used by physics engines, it is calculated just in case - // the sprite is animated (scaled up/down) using actions. - // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 - - b2Vec2 pos = _pB2Body->GetPosition(); - - float x = pos.x * _PTMRatio; - float y = pos.y * _PTMRatio; - - if (_ignoreAnchorPointForPosition) - { - x += _anchorPointInPoints.x; - y += _anchorPointInPoints.y; - } - - // Make matrix - float radians = _pB2Body->GetAngle(); - float c = cosf(radians); - float s = sinf(radians); - - if (!_anchorPointInPoints.isZero()) - { - x += ((c * -_anchorPointInPoints.x * _scaleX) + (-s * -_anchorPointInPoints.y * _scaleY)); - y += ((s * -_anchorPointInPoints.x * _scaleX) + (c * -_anchorPointInPoints.y * _scaleY)); - } - - // Rot, Translate Matrix - - float mat[] = {(float)c * _scaleX, - (float)s * _scaleX, - 0, - 0, - (float)-s * _scaleY, - (float)c * _scaleY, - 0, - 0, - 0, - 0, - 1, - 0, - x, - y, - 0, - 1}; - - _transform.set(mat); -} - -void PhysicsSpriteBox2D::onEnter() -{ - Node::onEnter(); - _syncTransform = Director::getInstance()->getEventDispatcher()->addCustomEventListener( - Director::EVENT_AFTER_UPDATE, std::bind(&PhysicsSpriteBox2D::afterUpdate, this, std::placeholders::_1)); - _syncTransform->retain(); -} - -void PhysicsSpriteBox2D::onExit() -{ - if (_syncTransform != nullptr) - { - Director::getInstance()->getEventDispatcher()->removeEventListener(_syncTransform); - _syncTransform->release(); - } - Node::onExit(); -} - -void PhysicsSpriteBox2D::afterUpdate(EventCustom* /*event*/) -{ - syncPhysicsTransform(); - - _transformDirty = false; - _transformUpdated = true; - setDirtyRecursively(true); -} - -NS_AX_EXT_END \ No newline at end of file diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.h b/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.h deleted file mode 100644 index 845e1835f014..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteBox2D.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#pragma once - -#include "2d/Sprite.h" -#include "extensions/ExtensionMacros.h" -#include "extensions/ExtensionExport.h" -#include "base/EventListenerCustom.h" - -class b2Body; - -NS_AX_EXT_BEGIN - -/** A Sprite subclass that is bound to a physics body. - It works with: - - Box2D - - Features and Limitations: - - Scale and Skew properties are ignored. - - Position and rotation are going to updated from the physics body - - If you update the rotation or position manually, the physics body will be updated - - You can't enble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time - * @lua NA - */ -class AX_EX_DLL PhysicsSpriteBox2D : public Sprite -{ -public: - static PhysicsSpriteBox2D* create(); - /** Creates an sprite with a texture. - The rect used will be the size of the texture. - The offset will be (0,0). - */ - static PhysicsSpriteBox2D* createWithTexture(Texture2D* pTexture); - - /** Creates an sprite with a texture and a rect. - The offset will be (0,0). - */ - static PhysicsSpriteBox2D* createWithTexture(Texture2D* pTexture, const Rect& rect); - - /** Creates an sprite with an sprite frame. */ - static PhysicsSpriteBox2D* createWithSpriteFrame(SpriteFrame* pSpriteFrame); - - /** Creates an sprite with an sprite frame name. - An SpriteFrame will be fetched from the SpriteFrameCache by name. - If the SpriteFrame doesn't exist it will raise an exception. - @since v0.9 - */ - static PhysicsSpriteBox2D* createWithSpriteFrameName(const char* pszSpriteFrameName); - - /** Creates an sprite with an image filename. - The rect used will be the size of the image. - The offset will be (0,0). - */ - static PhysicsSpriteBox2D* create(const char* pszFileName); - - /** Creates an sprite with an image filename and a rect. - The offset will be (0,0). - */ - static PhysicsSpriteBox2D* create(const char* pszFileName, const Rect& rect); - - PhysicsSpriteBox2D(); - - virtual bool isDirty() const override; - - /** Keep the sprite's rotation separate from the body. */ - bool isIgnoreBodyRotation() const; - void setIgnoreBodyRotation(bool bIgnoreBodyRotation); - - // - // Box2d specific - // - /** Body accessor when using box2d */ - b2Body* getB2Body() const; - void setB2Body(b2Body* pBody); - - float getPTMRatio() const; - void setPTMRatio(float fPTMRatio); - virtual void syncPhysicsTransform() const; - - // overrides - virtual const Vec2& getPosition() const override; - virtual void getPosition(float* x, float* y) const override; - virtual float getPositionX() const override; - virtual float getPositionY() const override; - virtual Vec3 getPosition3D() const override; - virtual void setPosition(const Vec2& position) override; - virtual void setPosition(float x, float y) override; - virtual void setPositionX(float x) override; - virtual void setPositionY(float y) override; - virtual void setPosition3D(const Vec3& position) override; - virtual float getRotation() const override; - virtual void setRotation(float fRotation) override; - - virtual void onEnter() override; - virtual void onExit() override; - -protected: - const Vec2& getPosFromPhysics() const; - void afterUpdate(EventCustom* event); - -protected: - bool _ignoreBodyRotation; - - // box2d specific - b2Body* _pB2Body; - float _PTMRatio; - - // Event for update synchronise physic transform - ax::EventListenerCustom* _syncTransform; -}; - -NS_AX_EXT_END diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.cpp b/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.cpp deleted file mode 100644 index 56f6377868b5..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.cpp +++ /dev/null @@ -1,329 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "PhysicsSpriteChipmunk2D.h" -#include "base/Director.h" -#include "base/EventDispatcher.h" - -#include "chipmunk/chipmunk.h" - -NS_AX_EXT_BEGIN - -PhysicsSpriteChipmunk2D::PhysicsSpriteChipmunk2D() - : _ignoreBodyRotation(false), _CPBody(nullptr), _syncTransform(nullptr) -{} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create() -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->init()) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithTexture(Texture2D* pTexture) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithTexture(pTexture)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithTexture(Texture2D* pTexture, const Rect& rect) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithTexture(pTexture, rect)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithSpriteFrame(SpriteFrame* pSpriteFrame) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithSpriteFrame(pSpriteFrame)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::createWithSpriteFrameName(const char* pszSpriteFrameName) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithSpriteFrameName(pszSpriteFrameName)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create(const char* pszFileName) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithFile(pszFileName)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -PhysicsSpriteChipmunk2D* PhysicsSpriteChipmunk2D::create(const char* pszFileName, const Rect& rect) -{ - PhysicsSpriteChipmunk2D* pRet = new PhysicsSpriteChipmunk2D(); - if (pRet->initWithFile(pszFileName, rect)) - { - pRet->autorelease(); - } - else - { - AX_SAFE_DELETE(pRet); - } - - return pRet; -} - -// this method will only get called if the sprite is batched. -// return YES if the physic's values (angles, position ) changed. -// If you return NO, then getNodeToParentTransform won't be called. -bool PhysicsSpriteChipmunk2D::isDirty() const -{ - return true; -} - -bool PhysicsSpriteChipmunk2D::isIgnoreBodyRotation() const -{ - return _ignoreBodyRotation; -} - -void PhysicsSpriteChipmunk2D::setIgnoreBodyRotation(bool bIgnoreBodyRotation) -{ - _ignoreBodyRotation = bIgnoreBodyRotation; -} - -// Override the setters and getters to always reflect the body's properties. -const Vec2& PhysicsSpriteChipmunk2D::getPosition() const -{ - return getPosFromPhysics(); -} - -void PhysicsSpriteChipmunk2D::getPosition(float* x, float* y) const -{ - if (x == nullptr || y == nullptr) - { - return; - } - const Vec2& pos = getPosFromPhysics(); - *x = pos.x; - *y = pos.y; -} - -float PhysicsSpriteChipmunk2D::getPositionX() const -{ - return getPosFromPhysics().x; -} - -float PhysicsSpriteChipmunk2D::getPositionY() const -{ - return getPosFromPhysics().y; -} - -Vec3 PhysicsSpriteChipmunk2D::getPosition3D() const -{ - Vec2 pos = getPosFromPhysics(); - return Vec3(pos.x, pos.y, 0); -} - -// -// Chipmunk only -// - -cpBody* PhysicsSpriteChipmunk2D::getCPBody() const -{ - return _CPBody; -} - -void PhysicsSpriteChipmunk2D::setCPBody(cpBody* pBody) -{ - _CPBody = pBody; -} - -// -// Common to Box2d and Chipmunk -// - -const Vec2& PhysicsSpriteChipmunk2D::getPosFromPhysics() const -{ - static Vec2 s_physicPosion; - - cpVect cpPos = cpBodyGetPosition(_CPBody); - s_physicPosion = Vec2(cpPos.x, cpPos.y); - - return s_physicPosion; -} - -void PhysicsSpriteChipmunk2D::setPosition(float x, float y) -{ - cpVect cpPos = cpv(x, y); - cpBodySetPosition(_CPBody, cpPos); -} - -void PhysicsSpriteChipmunk2D::setPosition(const Vec2& pos) -{ - setPosition(pos.x, pos.y); -} - -void PhysicsSpriteChipmunk2D::setPositionX(float x) -{ - setPosition(x, getPositionY()); -} - -void PhysicsSpriteChipmunk2D::setPositionY(float y) -{ - setPosition(getPositionX(), y); -} - -void PhysicsSpriteChipmunk2D::setPosition3D(const Vec3& position) -{ - setPosition(position.x, position.y); -} - -float PhysicsSpriteChipmunk2D::getRotation() const -{ - return (_ignoreBodyRotation ? Sprite::getRotation() : -AX_RADIANS_TO_DEGREES(cpBodyGetAngle(_CPBody))); -} - -void PhysicsSpriteChipmunk2D::setRotation(float fRotation) -{ - if (_ignoreBodyRotation) - { - Sprite::setRotation(fRotation); - } - else - { - cpBodySetAngle(_CPBody, -AX_DEGREES_TO_RADIANS(fRotation)); - } -} - -void PhysicsSpriteChipmunk2D::syncPhysicsTransform() const -{ - // Although scale is not used by physics engines, it is calculated just in case - // the sprite is animated (scaled up/down) using actions. - // For more info see: http://www.cocos2d-iphone.org/forum/topic/68990 - - cpVect rot = (_ignoreBodyRotation ? cpvforangle(-AX_DEGREES_TO_RADIANS(_rotationX)) : cpBodyGetRotation(_CPBody)); - float x = cpBodyGetPosition(_CPBody).x + rot.x * -_anchorPointInPoints.x * _scaleX - - rot.y * -_anchorPointInPoints.y * _scaleY; - float y = cpBodyGetPosition(_CPBody).y + rot.y * -_anchorPointInPoints.x * _scaleX + - rot.x * -_anchorPointInPoints.y * _scaleY; - - if (_ignoreAnchorPointForPosition) - { - x += _anchorPointInPoints.x; - y += _anchorPointInPoints.y; - } - - float mat[] = {(float)rot.x * _scaleX, - (float)rot.y * _scaleX, - 0, - 0, - (float)-rot.y * _scaleY, - (float)rot.x * _scaleY, - 0, - 0, - 0, - 0, - 1, - 0, - x, - y, - 0, - 1}; - - _transform.set(mat); -} - -void PhysicsSpriteChipmunk2D::onEnter() -{ - Node::onEnter(); - _syncTransform = Director::getInstance()->getEventDispatcher()->addCustomEventListener( - Director::EVENT_AFTER_UPDATE, std::bind(&PhysicsSpriteChipmunk2D::afterUpdate, this, std::placeholders::_1)); - _syncTransform->retain(); -} - -void PhysicsSpriteChipmunk2D::onExit() -{ - if (_syncTransform != nullptr) - { - Director::getInstance()->getEventDispatcher()->removeEventListener(_syncTransform); - _syncTransform->release(); - } - Node::onExit(); -} - -void PhysicsSpriteChipmunk2D::afterUpdate(EventCustom* /*event*/) -{ - syncPhysicsTransform(); - - _transformDirty = false; - _transformUpdated = true; - setDirtyRecursively(true); -} - -NS_AX_EXT_END \ No newline at end of file diff --git a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.h b/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.h deleted file mode 100644 index 067a1ece6051..000000000000 --- a/extensions/physics-nodes/src/physics-nodes/PhysicsSpriteChipmunk2D.h +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2012 Scott Lembcke and Howling Moon Software - * Copyright (c) 2012 cocos2d-x.org - * Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#pragma once - -#include "2d/Sprite.h" -#include "extensions/ExtensionMacros.h" -#include "extensions/ExtensionExport.h" -#include "base/EventListenerCustom.h" - -struct cpBody; - -NS_AX_EXT_BEGIN - -/** A Sprite subclass that is bound to a physics body. - It works with: - - Chipmunk2D: - - Features and Limitations: - - Scale and Skew properties are ignored. - - Position and rotation are going to updated from the physics body - - If you update the rotation or position manually, the physics body will be updated - - You can't enble both Chipmunk support and Box2d support at the same time. Only one can be enabled at compile time - * @lua NA - */ -class AX_EX_DLL PhysicsSpriteChipmunk2D : public Sprite -{ -public: - static PhysicsSpriteChipmunk2D* create(); - /** Creates an sprite with a texture. - The rect used will be the size of the texture. - The offset will be (0,0). - */ - static PhysicsSpriteChipmunk2D* createWithTexture(Texture2D* pTexture); - - /** Creates an sprite with a texture and a rect. - The offset will be (0,0). - */ - static PhysicsSpriteChipmunk2D* createWithTexture(Texture2D* pTexture, const Rect& rect); - - /** Creates an sprite with an sprite frame. */ - static PhysicsSpriteChipmunk2D* createWithSpriteFrame(SpriteFrame* pSpriteFrame); - - /** Creates an sprite with an sprite frame name. - An SpriteFrame will be fetched from the SpriteFrameCache by name. - If the SpriteFrame doesn't exist it will raise an exception. - @since v0.9 - */ - static PhysicsSpriteChipmunk2D* createWithSpriteFrameName(const char* pszSpriteFrameName); - - /** Creates an sprite with an image filename. - The rect used will be the size of the image. - The offset will be (0,0). - */ - static PhysicsSpriteChipmunk2D* create(const char* pszFileName); - - /** Creates an sprite with an image filename and a rect. - The offset will be (0,0). - */ - static PhysicsSpriteChipmunk2D* create(const char* pszFileName, const Rect& rect); - - PhysicsSpriteChipmunk2D(); - - virtual bool isDirty() const override; - - /** Keep the sprite's rotation separate from the body. */ - bool isIgnoreBodyRotation() const; - void setIgnoreBodyRotation(bool bIgnoreBodyRotation); - - // - // Chipmunk specific - // - /** Body accessor when using regular Chipmunk */ - cpBody* getCPBody() const; - void setCPBody(cpBody* pBody); - - float getPTMRatio() const; - void setPTMRatio(float fPTMRatio); - virtual void syncPhysicsTransform() const; - - // overrides - virtual const Vec2& getPosition() const override; - virtual void getPosition(float* x, float* y) const override; - virtual float getPositionX() const override; - virtual float getPositionY() const override; - virtual Vec3 getPosition3D() const override; - virtual void setPosition(const Vec2& position) override; - virtual void setPosition(float x, float y) override; - virtual void setPositionX(float x) override; - virtual void setPositionY(float y) override; - virtual void setPosition3D(const Vec3& position) override; - virtual float getRotation() const override; - virtual void setRotation(float fRotation) override; - - virtual void onEnter() override; - virtual void onExit() override; - -protected: - const Vec2& getPosFromPhysics() const; - void afterUpdate(EventCustom* event); - -protected: - bool _ignoreBodyRotation; - - // chipmunk specific - cpBody* _CPBody; - - // Event for update synchronise physic transform - ax::EventListenerCustom* _syncTransform; -}; - -NS_AX_EXT_END diff --git a/extensions/scripting/lua-bindings/CMakeLists.txt b/extensions/scripting/lua-bindings/CMakeLists.txt index b2d329a030de..12d796859af8 100644 --- a/extensions/scripting/lua-bindings/CMakeLists.txt +++ b/extensions/scripting/lua-bindings/CMakeLists.txt @@ -80,7 +80,7 @@ set(lua_bindings_auto_headers auto/axlua_ui_auto.hpp auto/axlua_physics_auto.hpp auto/axlua_extension_auto.hpp - auto/axlua_backend_auto.hpp + auto/axlua_rhi_auto.hpp auto/axlua_fairygui_auto.hpp ) @@ -97,7 +97,7 @@ set(lua_bindings_auto_files auto/axlua_audioengine_auto.cpp auto/axlua_physics3d_auto.cpp auto/axlua_navmesh_auto.cpp - auto/axlua_backend_auto.cpp + auto/axlua_rhi_auto.cpp auto/axlua_fairygui_auto.cpp ) @@ -221,6 +221,7 @@ setup_ax_extension_config(${_AX_LUA_LIB} DNTLINK) target_include_directories(${_AX_LUA_LIB} PRIVATE ${ax_root}/3rdparty PUBLIC ${ax_root}/3rdparty/lua + PUBLIC ${ax_root}/extensions/scripting PRIVATE manual/platform/android PRIVATE manual/platform/android/jni PRIVATE ${ax_root}/extensions/spine/runtime/include @@ -236,10 +237,8 @@ if(BUILD_SHARED_LIBS) target_compile_definitions(${_AX_LUA_LIB} PRIVATE CCS_DLLIMPORT) endif() -if(WINDOWS) - if(WINRT) +if(WINRT) target_compile_options(${_AX_LUA_LIB} PUBLIC /wd4700) - endif() endif() set_target_properties(${_AX_LUA_LIB} diff --git a/extensions/scripting/lua-bindings/auto/axlua_3d_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_3d_auto.cpp index 3111f00df4ac..8f92c7ece1c8 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_3d_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_3d_auto.cpp @@ -1,7 +1,7 @@ #include "lua-bindings/auto/axlua_3d_auto.hpp" #if defined(AX_ENABLE_3D) -#include "axmol.h" -#include "3d/Bundle3D.h" +#include "axmol/axmol.h" +#include "axmol/3d/Bundle3D.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" @@ -1218,7 +1218,7 @@ int lua_ax_3d_TextureCube_getBackendTexture(lua_State* tolua_S) return 0; } auto&& ret = cobj->getBackendTexture(); - object_to_luaval(tolua_S, "axb.TextureBackend",(ax::backend::TextureBackend*)ret); + object_to_luaval(tolua_S, "axrhi.Texture",(ax::rhi::Texture*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TextureCube:getBackendTexture",argc, 0); @@ -2120,7 +2120,7 @@ int lua_ax_3d_Mesh_getProgramState(lua_State* tolua_S) return 0; } auto&& ret = cobj->getProgramState(); - object_to_luaval(tolua_S, "axb.ProgramState",(ax::backend::ProgramState*)ret); + object_to_luaval(tolua_S, "axrhi.ProgramState",(ax::rhi::ProgramState*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Mesh:getProgramState",argc, 0); @@ -2305,7 +2305,7 @@ int lua_ax_3d_Mesh_setIndexFormat(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::backend::IndexFormat arg0; + ax::rhi::IndexFormat arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Mesh:setIndexFormat"); if(!ok) @@ -2355,9 +2355,9 @@ int lua_ax_3d_Mesh_setProgramState(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::backend::ProgramState* arg0; + ax::rhi::ProgramState* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.ProgramState",&arg0, "ax.Mesh:setProgramState"); + ok &= luaval_to_object(tolua_S, 2, "axrhi.ProgramState",&arg0, "ax.Mesh:setProgramState"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_3d_Mesh_setProgramState'", nullptr); @@ -4080,8 +4080,8 @@ int lua_ax_3d_MeshMaterial_createWithProgramState(lua_State* tolua_S) if (argc == 1) { - ax::backend::ProgramState* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.ProgramState",&arg0, "ax.MeshMaterial:createWithProgramState"); + ax::rhi::ProgramState* arg0; + ok &= luaval_to_object(tolua_S, 2, "axrhi.ProgramState",&arg0, "ax.MeshMaterial:createWithProgramState"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_3d_MeshMaterial_createWithProgramState'", nullptr); @@ -4857,7 +4857,7 @@ int lua_ax_3d_MeshRenderer_setCullFace(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::backend::CullMode arg0; + ax::rhi::CullMode arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.MeshRenderer:setCullFace"); if(!ok) diff --git a/extensions/scripting/lua-bindings/auto/axlua_3d_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_3d_auto.hpp index dc61a80d07be..2cf5136db43a 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_3d_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_3d_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_3D) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_3d(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_3D) diff --git a/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.cpp index b6d2c01a6b11..ba23595968b4 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.cpp @@ -1,6 +1,6 @@ #include "lua-bindings/auto/axlua_audioengine_auto.hpp" #if defined(AX_ENABLE_AUDIO) && (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC || defined(_WIN32) || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || AX_TARGET_PLATFORM == AX_PLATFORM_WASM) -#include "audio/AudioEngine.h" +#include "axmol/audio/AudioEngine.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.hpp index eabf35b3e50a..8cfb16bdbd0b 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_audioengine_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_AUDIO) && (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC || defined(_WIN32) || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || AX_TARGET_PLATFORM == AX_PLATFORM_WASM) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_audioengine(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_AUDIO) && (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC || defined(_WIN32) || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || AX_TARGET_PLATFORM == AX_PLATFORM_WASM) diff --git a/extensions/scripting/lua-bindings/auto/axlua_backend_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_backend_auto.cpp deleted file mode 100644 index b15436e6138d..000000000000 --- a/extensions/scripting/lua-bindings/auto/axlua_backend_auto.cpp +++ /dev/null @@ -1,4125 +0,0 @@ -#include "lua-bindings/auto/axlua_backend_auto.hpp" -#include "renderer/backend/Types.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Texture.h" -#include "renderer/backend/VertexLayout.h" -#include "renderer/backend/DriverBase.h" -#include "renderer/backend/RenderTarget.h" -#include "renderer/backend/ProgramManager.h" -#include "lua-bindings/manual/tolua_fix.h" -#include "lua-bindings/manual/LuaBasicConversions.h" - - -int lua_register_ax_backend_BufferUsage(lua_State* tolua_S) -{ - tolua_module(tolua_S, "BufferUsage", 0); - tolua_beginmodule(tolua_S,"BufferUsage"); - tolua_constant(tolua_S, "STATIC", 0); - tolua_constant(tolua_S, "DYNAMIC", 1); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::BufferUsage).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.BufferUsage"; - g_typeCast[typeName] = "axb.BufferUsage"; - return 1; -} - - -int lua_register_ax_backend_BufferType(lua_State* tolua_S) -{ - tolua_module(tolua_S, "BufferType", 0); - tolua_beginmodule(tolua_S,"BufferType"); - tolua_constant(tolua_S, "ARRAY_BUFFER", 0); - tolua_constant(tolua_S, "ELEMENT_ARRAY_BUFFER", 1); - tolua_constant(tolua_S, "UNIFORM_BUFFER", 2); - tolua_constant(tolua_S, "PIXEL_PACK_BUFFER", 3); - tolua_constant(tolua_S, "COUNT", 4); - tolua_constant(tolua_S, "VERTEX", 0); - tolua_constant(tolua_S, "INDEX", 1); - tolua_constant(tolua_S, "UNIFORM", 2); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::BufferType).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.BufferType"; - g_typeCast[typeName] = "axb.BufferType"; - return 1; -} - - -int lua_register_ax_backend_ShaderStage(lua_State* tolua_S) -{ - tolua_module(tolua_S, "ShaderStage", 0); - tolua_beginmodule(tolua_S,"ShaderStage"); - tolua_constant(tolua_S, "UNKNOWN", -1); - tolua_constant(tolua_S, "VERTEX", 0); - tolua_constant(tolua_S, "FRAGMENT", 1); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::ShaderStage).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.ShaderStage"; - g_typeCast[typeName] = "axb.ShaderStage"; - return 1; -} - - -int lua_register_ax_backend_VertexFormat(lua_State* tolua_S) -{ - tolua_module(tolua_S, "VertexFormat", 0); - tolua_beginmodule(tolua_S,"VertexFormat"); - tolua_constant(tolua_S, "FLOAT4", 0); - tolua_constant(tolua_S, "FLOAT3", 1); - tolua_constant(tolua_S, "FLOAT2", 2); - tolua_constant(tolua_S, "FLOAT", 3); - tolua_constant(tolua_S, "INT4", 4); - tolua_constant(tolua_S, "INT3", 5); - tolua_constant(tolua_S, "INT2", 6); - tolua_constant(tolua_S, "INT", 7); - tolua_constant(tolua_S, "USHORT4", 8); - tolua_constant(tolua_S, "USHORT2", 9); - tolua_constant(tolua_S, "UBYTE4", 10); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::VertexFormat).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.VertexFormat"; - g_typeCast[typeName] = "axb.VertexFormat"; - return 1; -} - - -int lua_register_ax_backend_PixelFormat(lua_State* tolua_S) -{ - tolua_module(tolua_S, "PixelFormat", 0); - tolua_beginmodule(tolua_S,"PixelFormat"); - tolua_constant(tolua_S, "PVRTC4", 0); - tolua_constant(tolua_S, "PVRTC4A", 1); - tolua_constant(tolua_S, "PVRTC2", 2); - tolua_constant(tolua_S, "PVRTC2A", 3); - tolua_constant(tolua_S, "ETC1", 4); - tolua_constant(tolua_S, "ETC2_RGB", 5); - tolua_constant(tolua_S, "ETC2_RGBA", 6); - tolua_constant(tolua_S, "S3TC_DXT1", 7); - tolua_constant(tolua_S, "S3TC_DXT3", 8); - tolua_constant(tolua_S, "S3TC_DXT5", 9); - tolua_constant(tolua_S, "ATC_RGB", 10); - tolua_constant(tolua_S, "ATC_EXPLICIT_ALPHA", 11); - tolua_constant(tolua_S, "ATC_INTERPOLATED_ALPHA", 12); - tolua_constant(tolua_S, "ASTC4x4", 13); - tolua_constant(tolua_S, "ASTC5x5", 14); - tolua_constant(tolua_S, "ASTC6x6", 15); - tolua_constant(tolua_S, "ASTC8x5", 16); - tolua_constant(tolua_S, "ASTC8x6", 17); - tolua_constant(tolua_S, "ASTC8x8", 18); - tolua_constant(tolua_S, "ASTC10x5", 19); - tolua_constant(tolua_S, "RGBA8", 20); - tolua_constant(tolua_S, "BGRA8", 21); - tolua_constant(tolua_S, "RGB8", 22); - tolua_constant(tolua_S, "RGB565", 23); - tolua_constant(tolua_S, "RGBA4", 24); - tolua_constant(tolua_S, "RGB5A1", 25); - tolua_constant(tolua_S, "R8", 26); - tolua_constant(tolua_S, "RG8", 27); - tolua_constant(tolua_S, "RGBA32F", 28); - tolua_constant(tolua_S, "D24S8", 29); - tolua_constant(tolua_S, "COUNT", 30); - tolua_constant(tolua_S, "NONE", 65535); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::PixelFormat).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.PixelFormat"; - g_typeCast[typeName] = "axb.PixelFormat"; - return 1; -} - - -int lua_register_ax_backend_TextureUsage(lua_State* tolua_S) -{ - tolua_module(tolua_S, "TextureUsage", 0); - tolua_beginmodule(tolua_S,"TextureUsage"); - tolua_constant(tolua_S, "READ", 0); - tolua_constant(tolua_S, "WRITE", 1); - tolua_constant(tolua_S, "RENDER_TARGET", 2); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::TextureUsage).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.TextureUsage"; - g_typeCast[typeName] = "axb.TextureUsage"; - return 1; -} - - -int lua_register_ax_backend_IndexFormat(lua_State* tolua_S) -{ - tolua_module(tolua_S, "IndexFormat", 0); - tolua_beginmodule(tolua_S,"IndexFormat"); - tolua_constant(tolua_S, "U_SHORT", 1); - tolua_constant(tolua_S, "U_INT", 2); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::IndexFormat).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.IndexFormat"; - g_typeCast[typeName] = "axb.IndexFormat"; - return 1; -} - - -int lua_register_ax_backend_VertexStepMode(lua_State* tolua_S) -{ - tolua_module(tolua_S, "VertexStepMode", 0); - tolua_beginmodule(tolua_S,"VertexStepMode"); - tolua_constant(tolua_S, "VERTEX", 0); - tolua_constant(tolua_S, "INSTANCE", 1); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::VertexStepMode).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.VertexStepMode"; - g_typeCast[typeName] = "axb.VertexStepMode"; - return 1; -} - - -int lua_register_ax_backend_PrimitiveType(lua_State* tolua_S) -{ - tolua_module(tolua_S, "PrimitiveType", 0); - tolua_beginmodule(tolua_S,"PrimitiveType"); - tolua_constant(tolua_S, "POINT", 0); - tolua_constant(tolua_S, "LINE", 1); - tolua_constant(tolua_S, "LINE_LOOP", 2); - tolua_constant(tolua_S, "LINE_STRIP", 3); - tolua_constant(tolua_S, "TRIANGLE", 4); - tolua_constant(tolua_S, "TRIANGLE_STRIP", 5); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::PrimitiveType).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.PrimitiveType"; - g_typeCast[typeName] = "axb.PrimitiveType"; - return 1; -} - - -int lua_register_ax_backend_TextureType(lua_State* tolua_S) -{ - tolua_module(tolua_S, "TextureType", 0); - tolua_beginmodule(tolua_S,"TextureType"); - tolua_constant(tolua_S, "TEXTURE_2D", 0); - tolua_constant(tolua_S, "TEXTURE_CUBE", 1); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::TextureType).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.TextureType"; - g_typeCast[typeName] = "axb.TextureType"; - return 1; -} - - -int lua_register_ax_backend_SamplerAddressMode(lua_State* tolua_S) -{ - tolua_module(tolua_S, "SamplerAddressMode", 0); - tolua_beginmodule(tolua_S,"SamplerAddressMode"); - tolua_constant(tolua_S, "REPEAT", 0); - tolua_constant(tolua_S, "MIRROR_REPEAT", 1); - tolua_constant(tolua_S, "CLAMP_TO_EDGE", 2); - tolua_constant(tolua_S, "DONT_CARE", 3); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::SamplerAddressMode).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.SamplerAddressMode"; - g_typeCast[typeName] = "axb.SamplerAddressMode"; - return 1; -} - - -int lua_register_ax_backend_SamplerFilter(lua_State* tolua_S) -{ - tolua_module(tolua_S, "SamplerFilter", 0); - tolua_beginmodule(tolua_S,"SamplerFilter"); - tolua_constant(tolua_S, "NEAREST", 0); - tolua_constant(tolua_S, "NEAREST_MIPMAP_NEAREST", 1); - tolua_constant(tolua_S, "NEAREST_MIPMAP_LINEAR", 2); - tolua_constant(tolua_S, "LINEAR", 3); - tolua_constant(tolua_S, "LINEAR_MIPMAP_LINEAR", 4); - tolua_constant(tolua_S, "LINEAR_MIPMAP_NEAREST", 5); - tolua_constant(tolua_S, "DONT_CARE", 6); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::SamplerFilter).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.SamplerFilter"; - g_typeCast[typeName] = "axb.SamplerFilter"; - return 1; -} - - -int lua_register_ax_backend_StencilOperation(lua_State* tolua_S) -{ - tolua_module(tolua_S, "StencilOperation", 0); - tolua_beginmodule(tolua_S,"StencilOperation"); - tolua_constant(tolua_S, "KEEP", 0); - tolua_constant(tolua_S, "ZERO", 1); - tolua_constant(tolua_S, "REPLACE", 2); - tolua_constant(tolua_S, "INVERT", 3); - tolua_constant(tolua_S, "INCREMENT_WRAP", 4); - tolua_constant(tolua_S, "DECREMENT_WRAP", 5); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::StencilOperation).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.StencilOperation"; - g_typeCast[typeName] = "axb.StencilOperation"; - return 1; -} - - -int lua_register_ax_backend_CompareFunction(lua_State* tolua_S) -{ - tolua_module(tolua_S, "CompareFunction", 0); - tolua_beginmodule(tolua_S,"CompareFunction"); - tolua_constant(tolua_S, "NEVER", 0); - tolua_constant(tolua_S, "LESS", 1); - tolua_constant(tolua_S, "LESS_EQUAL", 2); - tolua_constant(tolua_S, "GREATER", 3); - tolua_constant(tolua_S, "GREATER_EQUAL", 4); - tolua_constant(tolua_S, "EQUAL", 5); - tolua_constant(tolua_S, "NOT_EQUAL", 6); - tolua_constant(tolua_S, "ALWAYS", 7); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::CompareFunction).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.CompareFunction"; - g_typeCast[typeName] = "axb.CompareFunction"; - return 1; -} - - -int lua_register_ax_backend_BlendOperation(lua_State* tolua_S) -{ - tolua_module(tolua_S, "BlendOperation", 0); - tolua_beginmodule(tolua_S,"BlendOperation"); - tolua_constant(tolua_S, "ADD", 0); - tolua_constant(tolua_S, "SUBTRACT", 1); - tolua_constant(tolua_S, "REVERSE_SUBTRACT", 2); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::BlendOperation).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.BlendOperation"; - g_typeCast[typeName] = "axb.BlendOperation"; - return 1; -} - - -int lua_register_ax_backend_BlendFactor(lua_State* tolua_S) -{ - tolua_module(tolua_S, "BlendFactor", 0); - tolua_beginmodule(tolua_S,"BlendFactor"); - tolua_constant(tolua_S, "ZERO", 0); - tolua_constant(tolua_S, "ONE", 1); - tolua_constant(tolua_S, "SRC_COLOR", 2); - tolua_constant(tolua_S, "ONE_MINUS_SRC_COLOR", 3); - tolua_constant(tolua_S, "SRC_ALPHA", 4); - tolua_constant(tolua_S, "ONE_MINUS_SRC_ALPHA", 5); - tolua_constant(tolua_S, "DST_COLOR", 6); - tolua_constant(tolua_S, "ONE_MINUS_DST_COLOR", 7); - tolua_constant(tolua_S, "DST_ALPHA", 8); - tolua_constant(tolua_S, "ONE_MINUS_DST_ALPHA", 9); - tolua_constant(tolua_S, "CONSTANT_ALPHA", 10); - tolua_constant(tolua_S, "SRC_ALPHA_SATURATE", 11); - tolua_constant(tolua_S, "ONE_MINUS_CONSTANT_ALPHA", 12); - tolua_constant(tolua_S, "BLEND_COLOR", 13); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::BlendFactor).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.BlendFactor"; - g_typeCast[typeName] = "axb.BlendFactor"; - return 1; -} - - -int lua_register_ax_backend_ColorWriteMask(lua_State* tolua_S) -{ - tolua_module(tolua_S, "ColorWriteMask", 0); - tolua_beginmodule(tolua_S,"ColorWriteMask"); - tolua_constant(tolua_S, "RED_BIT", 0); - tolua_constant(tolua_S, "GREEN_BIT", 1); - tolua_constant(tolua_S, "BLUE_BIT", 2); - tolua_constant(tolua_S, "ALPHA_BIT", 3); - tolua_constant(tolua_S, "NONE", 0); - tolua_constant(tolua_S, "RED", 1); - tolua_constant(tolua_S, "GREEN", 2); - tolua_constant(tolua_S, "BLUE", 4); - tolua_constant(tolua_S, "ALPHA", 8); - tolua_constant(tolua_S, "ALL", 15); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::ColorWriteMask).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.ColorWriteMask"; - g_typeCast[typeName] = "axb.ColorWriteMask"; - return 1; -} - - -int lua_register_ax_backend_CullMode(lua_State* tolua_S) -{ - tolua_module(tolua_S, "CullMode", 0); - tolua_beginmodule(tolua_S,"CullMode"); - tolua_constant(tolua_S, "NONE", 0); - tolua_constant(tolua_S, "BACK", 1); - tolua_constant(tolua_S, "FRONT", 2); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::CullMode).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.CullMode"; - g_typeCast[typeName] = "axb.CullMode"; - return 1; -} - - -int lua_register_ax_backend_Winding(lua_State* tolua_S) -{ - tolua_module(tolua_S, "Winding", 0); - tolua_beginmodule(tolua_S,"Winding"); - tolua_constant(tolua_S, "CLOCK_WISE", 0); - tolua_constant(tolua_S, "COUNTER_CLOCK_WISE", 1); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::Winding).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.Winding"; - g_typeCast[typeName] = "axb.Winding"; - return 1; -} - - -int lua_register_ax_backend_TextureCubeFace(lua_State* tolua_S) -{ - tolua_module(tolua_S, "TextureCubeFace", 0); - tolua_beginmodule(tolua_S,"TextureCubeFace"); - tolua_constant(tolua_S, "POSITIVE_X", 0); - tolua_constant(tolua_S, "NEGATIVE_X", 1); - tolua_constant(tolua_S, "POSITIVE_Y", 2); - tolua_constant(tolua_S, "NEGATIVE_Y", 3); - tolua_constant(tolua_S, "POSITIVE_Z", 4); - tolua_constant(tolua_S, "NEGATIVE_Z", 5); - tolua_endmodule(tolua_S); - - auto typeName = typeid(ax::backend::TextureCubeFace).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.TextureCubeFace"; - g_typeCast[typeName] = "axb.TextureCubeFace"; - return 1; -} - -int lua_ax_backend_Program_getUniformLocation(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getUniformLocation'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::backend::Uniform arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.Program:getUniformLocation"); - - if (!ok) { break; } - ax::backend::UniformLocation ret = cobj->getUniformLocation(arg0); - uniformLocation_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.Program:getUniformLocation"); - - if (!ok) { break; } - ax::backend::UniformLocation ret = cobj->getUniformLocation(arg0); - uniformLocation_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getUniformLocation",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getUniformLocation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getAttributeLocation(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getAttributeLocation'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::backend::Attribute arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.Program:getAttributeLocation"); - - if (!ok) { break; } - int ret = cobj->getAttributeLocation(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.Program:getAttributeLocation"); - - if (!ok) { break; } - int ret = cobj->getAttributeLocation(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getAttributeLocation",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getAttributeLocation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getMaxVertexLocation(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getMaxVertexLocation'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getMaxVertexLocation'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxVertexLocation(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getMaxVertexLocation",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getMaxVertexLocation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getMaxFragmentLocation(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getMaxFragmentLocation'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getMaxFragmentLocation'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxFragmentLocation(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getMaxFragmentLocation",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getMaxFragmentLocation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getActiveAttributes(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getActiveAttributes'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getActiveAttributes'", nullptr); - return 0; - } - auto&& ret = cobj->getActiveAttributes(); - program_activeattrs_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getActiveAttributes",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getActiveAttributes'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getVertexShader(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getVertexShader'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getVertexShader'", nullptr); - return 0; - } - auto&& ret = cobj->getVertexShader(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getVertexShader",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getVertexShader'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getFragmentShader(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getFragmentShader'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getFragmentShader'", nullptr); - return 0; - } - auto&& ret = cobj->getFragmentShader(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getFragmentShader",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getFragmentShader'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_setupVertexLayout(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_setupVertexLayout'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::VertexLayoutType arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.Program:setupVertexLayout"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_setupVertexLayout'", nullptr); - return 0; - } - cobj->setupVertexLayout(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:setupVertexLayout",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_setupVertexLayout'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getProgramType(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getProgramType'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getProgramType'", nullptr); - return 0; - } - auto&& ret = cobj->getProgramType(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getProgramType",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getProgramType'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getProgramId(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getProgramId'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getProgramId'", nullptr); - return 0; - } - auto&& ret = cobj->getProgramId(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getProgramId",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getProgramId'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getUniformBufferSize(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getUniformBufferSize'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::ShaderStage arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.Program:getUniformBufferSize"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getUniformBufferSize'", nullptr); - return 0; - } - auto&& ret = cobj->getUniformBufferSize(arg0); - #pragma warning NO CONVERSION FROM NATIVE FOR ??; - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getUniformBufferSize",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getUniformBufferSize'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getVertexLayout(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Program* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Program*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Program_getVertexLayout'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getVertexLayout'", nullptr); - return 0; - } - auto&& ret = cobj->getVertexLayout(); - object_to_luaval(tolua_S, "axb.VertexLayout",(ax::backend::VertexLayout*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Program:getVertexLayout",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getVertexLayout'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Program_getBuiltinProgram(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.Program",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 1) - { - unsigned int arg0; - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "axb.Program:getBuiltinProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Program_getBuiltinProgram'", nullptr); - return 0; - } - auto&& ret = ax::backend::Program::getBuiltinProgram(arg0); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.Program:getBuiltinProgram",argc, 1); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Program_getBuiltinProgram'.",&tolua_err); -#endif - return 0; -} -static int lua_ax_backend_Program_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Program)"); - return 0; -} - -int lua_register_ax_backend_Program(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.Program"); - tolua_cclass(tolua_S,"Program","axb.Program","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"Program"); - tolua_function(tolua_S,"getUniformLocation",lua_ax_backend_Program_getUniformLocation); - tolua_function(tolua_S,"getAttributeLocation",lua_ax_backend_Program_getAttributeLocation); - tolua_function(tolua_S,"getMaxVertexLocation",lua_ax_backend_Program_getMaxVertexLocation); - tolua_function(tolua_S,"getMaxFragmentLocation",lua_ax_backend_Program_getMaxFragmentLocation); - tolua_function(tolua_S,"getActiveAttributes",lua_ax_backend_Program_getActiveAttributes); - tolua_function(tolua_S,"getVertexShader",lua_ax_backend_Program_getVertexShader); - tolua_function(tolua_S,"getFragmentShader",lua_ax_backend_Program_getFragmentShader); - tolua_function(tolua_S,"setupVertexLayout",lua_ax_backend_Program_setupVertexLayout); - tolua_function(tolua_S,"getProgramType",lua_ax_backend_Program_getProgramType); - tolua_function(tolua_S,"getProgramId",lua_ax_backend_Program_getProgramId); - tolua_function(tolua_S,"getUniformBufferSize",lua_ax_backend_Program_getUniformBufferSize); - tolua_function(tolua_S,"getVertexLayout",lua_ax_backend_Program_getVertexLayout); - tolua_function(tolua_S,"getBuiltinProgram", lua_ax_backend_Program_getBuiltinProgram); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::Program).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.Program"; - g_typeCast[typeName] = "axb.Program"; - return 1; -} - -int lua_ax_backend_VertexLayout_getStride(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::VertexLayout* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.VertexLayout",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::VertexLayout*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_VertexLayout_getStride'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_VertexLayout_getStride'", nullptr); - return 0; - } - auto&& ret = cobj->getStride(); - #pragma warning NO CONVERSION FROM NATIVE FOR ??; - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.VertexLayout:getStride",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_VertexLayout_getStride'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_VertexLayout_getVertexStepMode(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::VertexLayout* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.VertexLayout",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::VertexLayout*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_VertexLayout_getVertexStepMode'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_VertexLayout_getVertexStepMode'", nullptr); - return 0; - } - int ret = (int)cobj->getVertexStepMode(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.VertexLayout:getVertexStepMode",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_VertexLayout_getVertexStepMode'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_VertexLayout_isValid(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::VertexLayout* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.VertexLayout",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::VertexLayout*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_VertexLayout_isValid'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_VertexLayout_isValid'", nullptr); - return 0; - } - auto&& ret = cobj->isValid(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.VertexLayout:isValid",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_VertexLayout_isValid'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_VertexLayout_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::VertexLayout* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_VertexLayout_constructor'", nullptr); - return 0; - } - cobj = new ax::backend::VertexLayout(); - tolua_pushusertype(tolua_S,(void*)cobj,"axb.VertexLayout"); - tolua_register_gc(tolua_S,lua_gettop(tolua_S)); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.VertexLayout:VertexLayout",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_VertexLayout_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_backend_VertexLayout_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (VertexLayout)"); - return 0; -} - -int lua_register_ax_backend_VertexLayout(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.VertexLayout"); - tolua_cclass(tolua_S,"VertexLayout","axb.VertexLayout","",nullptr); - - tolua_beginmodule(tolua_S,"VertexLayout"); - tolua_function(tolua_S,"new",lua_ax_backend_VertexLayout_constructor); - tolua_function(tolua_S,"getStride",lua_ax_backend_VertexLayout_getStride); - tolua_function(tolua_S,"getVertexStepMode",lua_ax_backend_VertexLayout_getVertexStepMode); - tolua_function(tolua_S,"isValid",lua_ax_backend_VertexLayout_isValid); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::VertexLayout).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.VertexLayout"; - g_typeCast[typeName] = "axb.VertexLayout"; - return 1; -} - -int lua_ax_backend_ProgramState_clone(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_clone'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_clone'", nullptr); - return 0; - } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "axb.ProgramState",(ax::backend::ProgramState*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:clone",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_clone'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_getProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_getProgram'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_getProgram'", nullptr); - return 0; - } - auto&& ret = cobj->getProgram(); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:getProgram",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_getProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_getAttributeLocation(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_getAttributeLocation'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::backend::Attribute arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.ProgramState:getAttributeLocation"); - - if (!ok) { break; } - int ret = cobj->getAttributeLocation(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramState:getAttributeLocation"); - - if (!ok) { break; } - int ret = cobj->getAttributeLocation(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:getAttributeLocation",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_getAttributeLocation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_setTexture(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_setTexture'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 3) { - ax::backend::UniformLocation arg0; - ok &= luaval_to_uniformLocation(tolua_S, 2, arg0, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - int arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - ax::backend::TextureBackend* arg2; - ok &= luaval_to_object(tolua_S, 4, "axb.TextureBackend",&arg2, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - cobj->setTexture(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::backend::TextureBackend* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.TextureBackend",&arg0, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - cobj->setTexture(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 4) { - ax::backend::UniformLocation arg0; - ok &= luaval_to_uniformLocation(tolua_S, 2, arg0, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - int arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - int arg2; - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - ax::backend::TextureBackend* arg3; - ok &= luaval_to_object(tolua_S, 5, "axb.TextureBackend",&arg3, "axb.ProgramState:setTexture"); - - if (!ok) { break; } - cobj->setTexture(arg0, arg1, arg2, arg3); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:setTexture",argc, 4); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_setTexture'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_setParameterAutoBinding(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_setParameterAutoBinding'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - std::string_view arg0; - std::string_view arg1; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramState:setParameterAutoBinding"); - - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramState:setParameterAutoBinding"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_setParameterAutoBinding'", nullptr); - return 0; - } - cobj->setParameterAutoBinding(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:setParameterAutoBinding",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_setParameterAutoBinding'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_getMutableVertexLayout(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_getMutableVertexLayout'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_getMutableVertexLayout'", nullptr); - return 0; - } - auto&& ret = cobj->getMutableVertexLayout(); - object_to_luaval(tolua_S, "axb.VertexLayout",(ax::backend::VertexLayout*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:getMutableVertexLayout",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_getMutableVertexLayout'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_setSharedVertexLayout(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_setSharedVertexLayout'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::VertexLayout* arg0; - - ok &= luaval_to_object(tolua_S, 2, "axb.VertexLayout",&arg0, "axb.ProgramState:setSharedVertexLayout"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_setSharedVertexLayout'", nullptr); - return 0; - } - cobj->setSharedVertexLayout(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:setSharedVertexLayout",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_setSharedVertexLayout'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_getBatchId(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_getBatchId'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_getBatchId'", nullptr); - return 0; - } - auto&& ret = cobj->getBatchId(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:getBatchId",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_getBatchId'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_isBatchable(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_isBatchable'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_isBatchable'", nullptr); - return 0; - } - auto&& ret = cobj->isBatchable(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:isBatchable",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_isBatchable'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_updateBatchId(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_updateBatchId'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_updateBatchId'", nullptr); - return 0; - } - cobj->updateBatchId(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:updateBatchId",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_updateBatchId'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_validateSharedVertexLayout(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramState",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramState_validateSharedVertexLayout'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::VertexLayoutType arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.ProgramState:validateSharedVertexLayout"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_validateSharedVertexLayout'", nullptr); - return 0; - } - cobj->validateSharedVertexLayout(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:validateSharedVertexLayout",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_validateSharedVertexLayout'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramState_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramState* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::Program* arg0; - - ok &= luaval_to_object(tolua_S, 2, "axb.Program",&arg0, "axb.ProgramState:ProgramState"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramState_constructor'", nullptr); - return 0; - } - cobj = new ax::backend::ProgramState(arg0); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"axb.ProgramState"); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramState:ProgramState",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramState_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_backend_ProgramState_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ProgramState)"); - return 0; -} - -int lua_register_ax_backend_ProgramState(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.ProgramState"); - tolua_cclass(tolua_S,"ProgramState","axb.ProgramState","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"ProgramState"); - tolua_function(tolua_S,"new",lua_ax_backend_ProgramState_constructor); - tolua_function(tolua_S,"clone",lua_ax_backend_ProgramState_clone); - tolua_function(tolua_S,"getProgram",lua_ax_backend_ProgramState_getProgram); - tolua_function(tolua_S,"getAttributeLocation",lua_ax_backend_ProgramState_getAttributeLocation); - tolua_function(tolua_S,"setTexture",lua_ax_backend_ProgramState_setTexture); - tolua_function(tolua_S,"setParameterAutoBinding",lua_ax_backend_ProgramState_setParameterAutoBinding); - tolua_function(tolua_S,"getMutableVertexLayout",lua_ax_backend_ProgramState_getMutableVertexLayout); - tolua_function(tolua_S,"setSharedVertexLayout",lua_ax_backend_ProgramState_setSharedVertexLayout); - tolua_function(tolua_S,"getBatchId",lua_ax_backend_ProgramState_getBatchId); - tolua_function(tolua_S,"isBatchable",lua_ax_backend_ProgramState_isBatchable); - tolua_function(tolua_S,"updateBatchId",lua_ax_backend_ProgramState_updateBatchId); - tolua_function(tolua_S,"validateSharedVertexLayout",lua_ax_backend_ProgramState_validateSharedVertexLayout); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::ProgramState).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.ProgramState"; - g_typeCast[typeName] = "axb.ProgramState"; - return 1; -} - -int lua_ax_backend_TextureBackend_updateSamplerDescriptor(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_updateSamplerDescriptor'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::SamplerDescriptor arg0; - - ok &= luaval_to_samplerDescriptor(tolua_S, 2, arg0, "axb.TextureBackend:updateSamplerDescriptor"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_updateSamplerDescriptor'", nullptr); - return 0; - } - cobj->updateSamplerDescriptor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:updateSamplerDescriptor",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_updateSamplerDescriptor'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_generateMipmaps(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_generateMipmaps'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_generateMipmaps'", nullptr); - return 0; - } - cobj->generateMipmaps(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:generateMipmaps",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_generateMipmaps'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_updateTextureDescriptor(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_updateTextureDescriptor'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::TextureDescriptor arg0; - - #pragma warning NO CONVERSION TO NATIVE FOR TextureDescriptor - ok = false; - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_updateTextureDescriptor'", nullptr); - return 0; - } - cobj->updateTextureDescriptor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 2) - { - ax::backend::TextureDescriptor arg0; - int arg1; - - #pragma warning NO CONVERSION TO NATIVE FOR TextureDescriptor - ok = false; - - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axb.TextureBackend:updateTextureDescriptor"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_updateTextureDescriptor'", nullptr); - return 0; - } - cobj->updateTextureDescriptor(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:updateTextureDescriptor",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_updateTextureDescriptor'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getTextureFormat(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getTextureFormat'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getTextureFormat'", nullptr); - return 0; - } - int ret = (int)cobj->getTextureFormat(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getTextureFormat",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getTextureFormat'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getTextureUsage(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getTextureUsage'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getTextureUsage'", nullptr); - return 0; - } - int ret = (int)cobj->getTextureUsage(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getTextureUsage",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getTextureUsage'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getTextureType(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getTextureType'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getTextureType'", nullptr); - return 0; - } - int ret = (int)cobj->getTextureType(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getTextureType",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getTextureType'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_hasMipmaps(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_hasMipmaps'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_hasMipmaps'", nullptr); - return 0; - } - auto&& ret = cobj->hasMipmaps(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:hasMipmaps",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_hasMipmaps'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getCount(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getCount'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getCount'", nullptr); - return 0; - } - auto&& ret = cobj->getCount(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getCount",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getCount'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getHandler(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getHandler'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getHandler'", nullptr); - return 0; - } - auto&& ret = cobj->getHandler(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - if (argc == 1) - { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.TextureBackend:getHandler"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getHandler'", nullptr); - return 0; - } - auto&& ret = cobj->getHandler(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getHandler",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getHandler'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getWidth(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getWidth'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getWidth'", nullptr); - return 0; - } - auto&& ret = cobj->getWidth(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getWidth",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getWidth'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_TextureBackend_getHeight(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureBackend_getHeight'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureBackend_getHeight'", nullptr); - return 0; - } - auto&& ret = cobj->getHeight(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureBackend:getHeight",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureBackend_getHeight'.",&tolua_err); -#endif - - return 0; -} -static int lua_ax_backend_TextureBackend_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (TextureBackend)"); - return 0; -} - -int lua_register_ax_backend_TextureBackend(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.TextureBackend"); - tolua_cclass(tolua_S,"TextureBackend","axb.TextureBackend","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"TextureBackend"); - tolua_function(tolua_S,"updateSamplerDescriptor",lua_ax_backend_TextureBackend_updateSamplerDescriptor); - tolua_function(tolua_S,"generateMipmaps",lua_ax_backend_TextureBackend_generateMipmaps); - tolua_function(tolua_S,"updateTextureDescriptor",lua_ax_backend_TextureBackend_updateTextureDescriptor); - tolua_function(tolua_S,"getTextureFormat",lua_ax_backend_TextureBackend_getTextureFormat); - tolua_function(tolua_S,"getTextureUsage",lua_ax_backend_TextureBackend_getTextureUsage); - tolua_function(tolua_S,"getTextureType",lua_ax_backend_TextureBackend_getTextureType); - tolua_function(tolua_S,"hasMipmaps",lua_ax_backend_TextureBackend_hasMipmaps); - tolua_function(tolua_S,"getCount",lua_ax_backend_TextureBackend_getCount); - tolua_function(tolua_S,"getHandler",lua_ax_backend_TextureBackend_getHandler); - tolua_function(tolua_S,"getWidth",lua_ax_backend_TextureBackend_getWidth); - tolua_function(tolua_S,"getHeight",lua_ax_backend_TextureBackend_getHeight); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::TextureBackend).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.TextureBackend"; - g_typeCast[typeName] = "axb.TextureBackend"; - return 1; -} - -int lua_ax_backend_Texture2DBackend_getWidth(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Texture2DBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Texture2DBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Texture2DBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Texture2DBackend_getWidth'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Texture2DBackend_getWidth'", nullptr); - return 0; - } - auto&& ret = cobj->getWidth(); - #pragma warning NO CONVERSION FROM NATIVE FOR ??; - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Texture2DBackend:getWidth",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Texture2DBackend_getWidth'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_Texture2DBackend_getHeight(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::Texture2DBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.Texture2DBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::Texture2DBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_Texture2DBackend_getHeight'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_Texture2DBackend_getHeight'", nullptr); - return 0; - } - auto&& ret = cobj->getHeight(); - #pragma warning NO CONVERSION FROM NATIVE FOR ??; - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.Texture2DBackend:getHeight",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_Texture2DBackend_getHeight'.",&tolua_err); -#endif - - return 0; -} -static int lua_ax_backend_Texture2DBackend_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Texture2DBackend)"); - return 0; -} - -int lua_register_ax_backend_Texture2DBackend(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.Texture2DBackend"); - tolua_cclass(tolua_S,"Texture2DBackend","axb.Texture2DBackend","axb.TextureBackend",nullptr); - - tolua_beginmodule(tolua_S,"Texture2DBackend"); - tolua_function(tolua_S,"getWidth",lua_ax_backend_Texture2DBackend_getWidth); - tolua_function(tolua_S,"getHeight",lua_ax_backend_Texture2DBackend_getHeight); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::Texture2DBackend).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.Texture2DBackend"; - g_typeCast[typeName] = "axb.Texture2DBackend"; - return 1; -} - -int lua_ax_backend_TextureCubemapBackend_updateFaceData(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::TextureCubemapBackend* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.TextureCubemapBackend",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::TextureCubemapBackend*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_TextureCubemapBackend_updateFaceData'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - ax::backend::TextureCubeFace arg0; - void* arg1; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.TextureCubemapBackend:updateFaceData"); - - #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureCubemapBackend_updateFaceData'", nullptr); - return 0; - } - cobj->updateFaceData(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 3) - { - ax::backend::TextureCubeFace arg0; - void* arg1; - int arg2; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.TextureCubemapBackend:updateFaceData"); - - #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; - - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axb.TextureCubemapBackend:updateFaceData"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_TextureCubemapBackend_updateFaceData'", nullptr); - return 0; - } - cobj->updateFaceData(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.TextureCubemapBackend:updateFaceData",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_TextureCubemapBackend_updateFaceData'.",&tolua_err); -#endif - - return 0; -} -static int lua_ax_backend_TextureCubemapBackend_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (TextureCubemapBackend)"); - return 0; -} - -int lua_register_ax_backend_TextureCubemapBackend(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.TextureCubemapBackend"); - tolua_cclass(tolua_S,"TextureCubemapBackend","axb.TextureCubemapBackend","axb.TextureBackend",nullptr); - - tolua_beginmodule(tolua_S,"TextureCubemapBackend"); - tolua_function(tolua_S,"updateFaceData",lua_ax_backend_TextureCubemapBackend_updateFaceData); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::TextureCubemapBackend).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.TextureCubemapBackend"; - g_typeCast[typeName] = "axb.TextureCubemapBackend"; - return 1; -} - -int lua_ax_backend_DriverBase_newDefaultRenderTarget(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_newDefaultRenderTarget'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newDefaultRenderTarget'", nullptr); - return 0; - } - auto&& ret = cobj->newDefaultRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:newDefaultRenderTarget",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_newDefaultRenderTarget'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_newRenderTarget(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_newRenderTarget'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newRenderTarget'", nullptr); - return 0; - } - auto&& ret = cobj->newRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); - return 1; - } - if (argc == 1) - { - ax::backend::TextureBackend* arg0; - - ok &= luaval_to_object(tolua_S, 2, "axb.TextureBackend",&arg0, "axb.DriverBase:newRenderTarget"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newRenderTarget'", nullptr); - return 0; - } - auto&& ret = cobj->newRenderTarget(arg0); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); - return 1; - } - if (argc == 2) - { - ax::backend::TextureBackend* arg0; - ax::backend::TextureBackend* arg1; - - ok &= luaval_to_object(tolua_S, 2, "axb.TextureBackend",&arg0, "axb.DriverBase:newRenderTarget"); - - ok &= luaval_to_object(tolua_S, 3, "axb.TextureBackend",&arg1, "axb.DriverBase:newRenderTarget"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newRenderTarget'", nullptr); - return 0; - } - auto&& ret = cobj->newRenderTarget(arg0, arg1); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); - return 1; - } - if (argc == 3) - { - ax::backend::TextureBackend* arg0; - ax::backend::TextureBackend* arg1; - ax::backend::TextureBackend* arg2; - - ok &= luaval_to_object(tolua_S, 2, "axb.TextureBackend",&arg0, "axb.DriverBase:newRenderTarget"); - - ok &= luaval_to_object(tolua_S, 3, "axb.TextureBackend",&arg1, "axb.DriverBase:newRenderTarget"); - - ok &= luaval_to_object(tolua_S, 4, "axb.TextureBackend",&arg2, "axb.DriverBase:newRenderTarget"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newRenderTarget'", nullptr); - return 0; - } - auto&& ret = cobj->newRenderTarget(arg0, arg1, arg2); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:newRenderTarget",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_newRenderTarget'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_newDepthStencilState(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_newDepthStencilState'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newDepthStencilState'", nullptr); - return 0; - } - auto&& ret = cobj->newDepthStencilState(); - object_to_luaval(tolua_S, "axb.DepthStencilState",(ax::backend::DepthStencilState*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:newDepthStencilState",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_newDepthStencilState'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_newProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_newProgram'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - std::string_view arg0; - std::string_view arg1; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.DriverBase:newProgram"); - - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.DriverBase:newProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_newProgram'", nullptr); - return 0; - } - auto&& ret = cobj->newProgram(arg0, arg1); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:newProgram",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_newProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_resetState(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_resetState'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_resetState'", nullptr); - return 0; - } - cobj->resetState(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:resetState",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_resetState'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getVendor(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getVendor'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getVendor'", nullptr); - return 0; - } - auto&& ret = cobj->getVendor(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getVendor",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getVendor'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getRenderer(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getRenderer'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getRenderer'", nullptr); - return 0; - } - auto&& ret = cobj->getRenderer(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getRenderer",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getRenderer'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getVersion(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getVersion'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getVersion'", nullptr); - return 0; - } - auto&& ret = cobj->getVersion(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getVersion",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getVersion'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getShaderVersion(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getShaderVersion'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getShaderVersion'", nullptr); - return 0; - } - auto&& ret = cobj->getShaderVersion(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getShaderVersion",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getShaderVersion'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_hasExtension(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_hasExtension'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.DriverBase:hasExtension"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_hasExtension'", nullptr); - return 0; - } - auto&& ret = cobj->hasExtension(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:hasExtension",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_hasExtension'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_dumpExtensions(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_dumpExtensions'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_dumpExtensions'", nullptr); - return 0; - } - auto&& ret = cobj->dumpExtensions(); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:dumpExtensions",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_dumpExtensions'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_checkForFeatureSupported(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_checkForFeatureSupported'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::FeatureType arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axb.DriverBase:checkForFeatureSupported"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_checkForFeatureSupported'", nullptr); - return 0; - } - auto&& ret = cobj->checkForFeatureSupported(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:checkForFeatureSupported",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_checkForFeatureSupported'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getMaxTextureSize(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getMaxTextureSize'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getMaxTextureSize'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxTextureSize(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getMaxTextureSize",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getMaxTextureSize'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getMaxAttributes(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getMaxAttributes'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getMaxAttributes'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxAttributes(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getMaxAttributes",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getMaxAttributes'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getMaxTextureUnits(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getMaxTextureUnits'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getMaxTextureUnits'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxTextureUnits(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getMaxTextureUnits",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getMaxTextureUnits'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getMaxSamplesAllowed(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::DriverBase* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::DriverBase*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_DriverBase_getMaxSamplesAllowed'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getMaxSamplesAllowed'", nullptr); - return 0; - } - auto&& ret = cobj->getMaxSamplesAllowed(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.DriverBase:getMaxSamplesAllowed",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getMaxSamplesAllowed'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_DriverBase_getInstance(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_getInstance'", nullptr); - return 0; - } - auto&& ret = ax::backend::DriverBase::getInstance(); - object_to_luaval(tolua_S, "axb.DriverBase",(ax::backend::DriverBase*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.DriverBase:getInstance",argc, 0); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_getInstance'.",&tolua_err); -#endif - return 0; -} -int lua_ax_backend_DriverBase_destroyInstance(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.DriverBase",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_DriverBase_destroyInstance'", nullptr); - return 0; - } - ax::backend::DriverBase::destroyInstance(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.DriverBase:destroyInstance",argc, 0); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_DriverBase_destroyInstance'.",&tolua_err); -#endif - return 0; -} -static int lua_ax_backend_DriverBase_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (DriverBase)"); - return 0; -} - -int lua_register_ax_backend_DriverBase(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.DriverBase"); - tolua_cclass(tolua_S,"DriverBase","axb.DriverBase","",nullptr); - - tolua_beginmodule(tolua_S,"DriverBase"); - tolua_function(tolua_S,"newDefaultRenderTarget",lua_ax_backend_DriverBase_newDefaultRenderTarget); - tolua_function(tolua_S,"newRenderTarget",lua_ax_backend_DriverBase_newRenderTarget); - tolua_function(tolua_S,"newDepthStencilState",lua_ax_backend_DriverBase_newDepthStencilState); - tolua_function(tolua_S,"newProgram",lua_ax_backend_DriverBase_newProgram); - tolua_function(tolua_S,"resetState",lua_ax_backend_DriverBase_resetState); - tolua_function(tolua_S,"getVendor",lua_ax_backend_DriverBase_getVendor); - tolua_function(tolua_S,"getRenderer",lua_ax_backend_DriverBase_getRenderer); - tolua_function(tolua_S,"getVersion",lua_ax_backend_DriverBase_getVersion); - tolua_function(tolua_S,"getShaderVersion",lua_ax_backend_DriverBase_getShaderVersion); - tolua_function(tolua_S,"hasExtension",lua_ax_backend_DriverBase_hasExtension); - tolua_function(tolua_S,"dumpExtensions",lua_ax_backend_DriverBase_dumpExtensions); - tolua_function(tolua_S,"checkForFeatureSupported",lua_ax_backend_DriverBase_checkForFeatureSupported); - tolua_function(tolua_S,"getMaxTextureSize",lua_ax_backend_DriverBase_getMaxTextureSize); - tolua_function(tolua_S,"getMaxAttributes",lua_ax_backend_DriverBase_getMaxAttributes); - tolua_function(tolua_S,"getMaxTextureUnits",lua_ax_backend_DriverBase_getMaxTextureUnits); - tolua_function(tolua_S,"getMaxSamplesAllowed",lua_ax_backend_DriverBase_getMaxSamplesAllowed); - tolua_function(tolua_S,"getInstance", lua_ax_backend_DriverBase_getInstance); - tolua_function(tolua_S,"destroyInstance", lua_ax_backend_DriverBase_destroyInstance); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::DriverBase).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.DriverBase"; - g_typeCast[typeName] = "axb.DriverBase"; - return 1; -} - -int lua_ax_backend_ProgramManager_getBuiltinProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_getBuiltinProgram'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - unsigned int arg0; - - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "axb.ProgramManager:getBuiltinProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_getBuiltinProgram'", nullptr); - return 0; - } - auto&& ret = cobj->getBuiltinProgram(arg0); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:getBuiltinProgram",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_getBuiltinProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_registerCustomProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_registerCustomProgram'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - std::string_view arg0; - std::string_view arg1; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramManager:registerCustomProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_registerCustomProgram'", nullptr); - return 0; - } - auto&& ret = cobj->registerCustomProgram(arg0, arg1); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - if (argc == 3) - { - std::string_view arg0; - std::string_view arg1; - ax::backend::VertexLayoutType arg2; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axb.ProgramManager:registerCustomProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_registerCustomProgram'", nullptr); - return 0; - } - auto&& ret = cobj->registerCustomProgram(arg0, arg1, arg2); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - if (argc == 4) - { - std::string_view arg0; - std::string_view arg1; - ax::backend::VertexLayoutType arg2; - bool arg3; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axb.ProgramManager:registerCustomProgram"); - - ok &= luaval_to_boolean(tolua_S, 5,&arg3, "axb.ProgramManager:registerCustomProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_registerCustomProgram'", nullptr); - return 0; - } - auto&& ret = cobj->registerCustomProgram(arg0, arg1, arg2, arg3); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:registerCustomProgram",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_registerCustomProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_loadProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_loadProgram'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - ax::backend::Program* ret = cobj->loadProgram(arg0, arg1); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - ax::backend::VertexLayoutType arg2; - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - ax::backend::Program* ret = cobj->loadProgram(arg0, arg1, arg2); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - unsigned long long arg0; - ok &= luaval_to_long_long(tolua_S, 2,(long long*)&arg0, "axb.ProgramManager:loadProgram"); - - if (!ok) { break; } - ax::backend::Program* ret = cobj->loadProgram(arg0); - object_to_luaval(tolua_S, "axb.Program",(ax::backend::Program*)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:loadProgram",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_loadProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_unloadProgram(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_unloadProgram'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::Program* arg0; - - ok &= luaval_to_object(tolua_S, 2, "axb.Program",&arg0, "axb.ProgramManager:unloadProgram"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_unloadProgram'", nullptr); - return 0; - } - cobj->unloadProgram(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:unloadProgram",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_unloadProgram'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_unloadUnusedPrograms(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_unloadUnusedPrograms'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_unloadUnusedPrograms'", nullptr); - return 0; - } - cobj->unloadUnusedPrograms(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:unloadUnusedPrograms",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_unloadUnusedPrograms'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_unloadAllPrograms(lua_State* tolua_S) -{ - int argc = 0; - ax::backend::ProgramManager* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::backend::ProgramManager*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_backend_ProgramManager_unloadAllPrograms'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_unloadAllPrograms'", nullptr); - return 0; - } - cobj->unloadAllPrograms(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ProgramManager:unloadAllPrograms",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_unloadAllPrograms'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_backend_ProgramManager_getInstance(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_getInstance'", nullptr); - return 0; - } - auto&& ret = ax::backend::ProgramManager::getInstance(); - object_to_luaval(tolua_S, "axb.ProgramManager",(ax::backend::ProgramManager*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.ProgramManager:getInstance",argc, 0); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_getInstance'.",&tolua_err); -#endif - return 0; -} -int lua_ax_backend_ProgramManager_destroyInstance(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.ProgramManager",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_backend_ProgramManager_destroyInstance'", nullptr); - return 0; - } - ax::backend::ProgramManager::destroyInstance(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.ProgramManager:destroyInstance",argc, 0); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_backend_ProgramManager_destroyInstance'.",&tolua_err); -#endif - return 0; -} -static int lua_ax_backend_ProgramManager_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ProgramManager)"); - return 0; -} - -int lua_register_ax_backend_ProgramManager(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"axb.ProgramManager"); - tolua_cclass(tolua_S,"ProgramManager","axb.ProgramManager","",nullptr); - - tolua_beginmodule(tolua_S,"ProgramManager"); - tolua_function(tolua_S,"getBuiltinProgram",lua_ax_backend_ProgramManager_getBuiltinProgram); - tolua_function(tolua_S,"registerCustomProgram",lua_ax_backend_ProgramManager_registerCustomProgram); - tolua_function(tolua_S,"loadProgram",lua_ax_backend_ProgramManager_loadProgram); - tolua_function(tolua_S,"unloadProgram",lua_ax_backend_ProgramManager_unloadProgram); - tolua_function(tolua_S,"unloadUnusedPrograms",lua_ax_backend_ProgramManager_unloadUnusedPrograms); - tolua_function(tolua_S,"unloadAllPrograms",lua_ax_backend_ProgramManager_unloadAllPrograms); - tolua_function(tolua_S,"getInstance", lua_ax_backend_ProgramManager_getInstance); - tolua_function(tolua_S,"destroyInstance", lua_ax_backend_ProgramManager_destroyInstance); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::ProgramManager).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.ProgramManager"; - g_typeCast[typeName] = "axb.ProgramManager"; - return 1; -} -TOLUA_API int register_all_ax_backend(lua_State* tolua_S) -{ - tolua_open(tolua_S); - - tolua_module(tolua_S,"axb",0); - tolua_beginmodule(tolua_S,"axb"); - - lua_register_ax_backend_BufferUsage(tolua_S); - lua_register_ax_backend_BufferType(tolua_S); - lua_register_ax_backend_ShaderStage(tolua_S); - lua_register_ax_backend_VertexFormat(tolua_S); - lua_register_ax_backend_PixelFormat(tolua_S); - lua_register_ax_backend_TextureUsage(tolua_S); - lua_register_ax_backend_IndexFormat(tolua_S); - lua_register_ax_backend_VertexStepMode(tolua_S); - lua_register_ax_backend_PrimitiveType(tolua_S); - lua_register_ax_backend_TextureType(tolua_S); - lua_register_ax_backend_SamplerAddressMode(tolua_S); - lua_register_ax_backend_SamplerFilter(tolua_S); - lua_register_ax_backend_StencilOperation(tolua_S); - lua_register_ax_backend_CompareFunction(tolua_S); - lua_register_ax_backend_BlendOperation(tolua_S); - lua_register_ax_backend_BlendFactor(tolua_S); - lua_register_ax_backend_ColorWriteMask(tolua_S); - lua_register_ax_backend_CullMode(tolua_S); - lua_register_ax_backend_Winding(tolua_S); - lua_register_ax_backend_TextureCubeFace(tolua_S); - lua_register_ax_backend_Program(tolua_S); - lua_register_ax_backend_VertexLayout(tolua_S); - lua_register_ax_backend_ProgramState(tolua_S); - lua_register_ax_backend_TextureBackend(tolua_S); - lua_register_ax_backend_Texture2DBackend(tolua_S); - lua_register_ax_backend_TextureCubemapBackend(tolua_S); - lua_register_ax_backend_DriverBase(tolua_S); - lua_register_ax_backend_ProgramManager(tolua_S); - - tolua_endmodule(tolua_S); - return 1; -} - diff --git a/extensions/scripting/lua-bindings/auto/axlua_backend_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_backend_auto.hpp deleted file mode 100644 index 63a730497c62..000000000000 --- a/extensions/scripting/lua-bindings/auto/axlua_backend_auto.hpp +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include "base/Config.h" -#include "tolua++.h" -int register_all_ax_backend(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_base_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_base_auto.cpp index b2fb19f2230d..491271f9e2fc 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_base_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_base_auto.cpp @@ -1,10 +1,11 @@ #include "lua-bindings/auto/axlua_base_auto.hpp" -#include "axmol.h" -#include "2d/ProtectedNode.h" +#include "axmol/axmol.h" +#include "axmol/2d/ProtectedNode.h" #include "lua-bindings/manual/ComponentLua.h" -#include "renderer/Renderer.h" -#include "renderer/PipelineDescriptor.h" -#include "renderer/backend/RenderTarget.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/PipelineDesc.h" +#include "axmol/rhi/RenderTarget.h" +#include "axmol/renderer/ProgramManager.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" @@ -34,7 +35,7 @@ int lua_ax_base_Object_retain(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81,7 +82,7 @@ int lua_ax_base_Object_release(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -128,7 +129,7 @@ int lua_ax_base_Object_getReferenceCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -171,10 +172,10 @@ int lua_register_ax_base_Object(lua_State* tolua_S) return 1; } -int lua_ax_base_EventListener_checkAvailable(lua_State* tolua_S) +int lua_ax_base_Touch_getLocation(lua_State* tolua_S) { int argc = 0; - ax::EventListener* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -183,45 +184,45 @@ int lua_ax_base_EventListener_checkAvailable(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_checkAvailable'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getLocation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_checkAvailable'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getLocation'", nullptr); return 0; } - auto&& ret = cobj->checkAvailable(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getLocation(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:checkAvailable",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getLocation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_checkAvailable'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getLocation'.",&tolua_err); #endif return 0; } -int lua_ax_base_EventListener_clone(lua_State* tolua_S) +int lua_ax_base_Touch_getPreviousLocation(lua_State* tolua_S) { int argc = 0; - ax::EventListener* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -230,45 +231,45 @@ int lua_ax_base_EventListener_clone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_clone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getPreviousLocation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_clone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getPreviousLocation'", nullptr); return 0; } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "ax.EventListener",(ax::EventListener*)ret); + auto&& ret = cobj->getPreviousLocation(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:clone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getPreviousLocation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_clone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getPreviousLocation'.",&tolua_err); #endif return 0; } -int lua_ax_base_EventListener_setEnabled(lua_State* tolua_S) +int lua_ax_base_Touch_getStartLocation(lua_State* tolua_S) { int argc = 0; - ax::EventListener* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -277,48 +278,45 @@ int lua_ax_base_EventListener_setEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_setEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getStartLocation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.EventListener:setEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_setEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getStartLocation'", nullptr); return 0; } - cobj->setEnabled(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getStartLocation(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:setEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getStartLocation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_setEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getStartLocation'.",&tolua_err); #endif return 0; } -int lua_ax_base_EventListener_isEnabled(lua_State* tolua_S) +int lua_ax_base_Touch_getDelta(lua_State* tolua_S) { int argc = 0; - ax::EventListener* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -327,68 +325,45 @@ int lua_ax_base_EventListener_isEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_isEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getDelta'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_isEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getDelta'", nullptr); return 0; } - auto&& ret = cobj->isEnabled(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getDelta(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:isEnabled",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getDelta",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_isEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getDelta'.",&tolua_err); #endif return 0; } -static int lua_ax_base_EventListener_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (EventListener)"); - return 0; -} - -int lua_register_ax_base_EventListener(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.EventListener"); - tolua_cclass(tolua_S,"EventListener","ax.EventListener","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"EventListener"); - tolua_function(tolua_S,"checkAvailable",lua_ax_base_EventListener_checkAvailable); - tolua_function(tolua_S,"clone",lua_ax_base_EventListener_clone); - tolua_function(tolua_S,"setEnabled",lua_ax_base_EventListener_setEnabled); - tolua_function(tolua_S,"isEnabled",lua_ax_base_EventListener_isEnabled); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::EventListener).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.EventListener"; - g_typeCast[typeName] = "ax.EventListener"; - return 1; -} - -int lua_ax_base_EventListenerCustom_constructor(lua_State* tolua_S) +int lua_ax_base_Touch_getLocationInView(lua_State* tolua_S) { int argc = 0; - ax::EventListenerCustom* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -396,56 +371,46 @@ int lua_ax_base_EventListenerCustom_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getLocationInView'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListenerCustom_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getLocationInView'", nullptr); return 0; } - cobj = new ax::EventListenerCustom(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventListenerCustom"); + auto&& ret = cobj->getLocationInView(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListenerCustom:EventListenerCustom",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getLocationInView",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListenerCustom_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getLocationInView'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_EventListenerCustom_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (EventListenerCustom)"); - return 0; -} - -int lua_register_ax_base_EventListenerCustom(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.EventListenerCustom"); - tolua_cclass(tolua_S,"EventListenerCustom","ax.EventListenerCustom","ax.EventListener",nullptr); - - tolua_beginmodule(tolua_S,"EventListenerCustom"); - tolua_function(tolua_S,"new",lua_ax_base_EventListenerCustom_constructor); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::EventListenerCustom).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.EventListenerCustom"; - g_typeCast[typeName] = "ax.EventListenerCustom"; - return 1; -} - -int lua_ax_base_ShaderCache_purge(lua_State* tolua_S) +int lua_ax_base_Touch_getPreviousLocationInView(lua_State* tolua_S) { int argc = 0; - ax::backend::ShaderCache* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -454,45 +419,45 @@ int lua_ax_base_ShaderCache_purge(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::backend::ShaderCache*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_purge'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getPreviousLocationInView'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_purge'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getPreviousLocationInView'", nullptr); return 0; } - cobj->purge(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getPreviousLocationInView(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ShaderCache:purge",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getPreviousLocationInView",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_purge'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getPreviousLocationInView'.",&tolua_err); #endif return 0; } -int lua_ax_base_ShaderCache_newVertexShaderModule(lua_State* tolua_S) +int lua_ax_base_Touch_getStartLocationInView(lua_State* tolua_S) { int argc = 0; - ax::backend::ShaderCache* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -501,48 +466,124 @@ int lua_ax_base_ShaderCache_newVertexShaderModule(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::backend::ShaderCache*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_newVertexShaderModule'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getStartLocationInView'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ShaderCache:newVertexShaderModule"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_newVertexShaderModule'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getStartLocationInView'", nullptr); return 0; } - auto&& ret = cobj->newVertexShaderModule(arg0); - object_to_luaval(tolua_S, "axb.ShaderModule",(ax::backend::ShaderModule*)ret); + auto&& ret = cobj->getStartLocationInView(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ShaderCache:newVertexShaderModule",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getStartLocationInView",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getStartLocationInView'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Touch_setTouchInfo(lua_State* tolua_S) +{ + int argc = 0; + ax::Touch* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_setTouchInfo'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 5) { + int arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg3; + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg4; + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + cobj->setTouchInfo(arg0, arg1, arg2, arg3, arg4); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 3) { + int arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Touch:setTouchInfo"); + + if (!ok) { break; } + cobj->setTouchInfo(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:setTouchInfo",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_newVertexShaderModule'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_setTouchInfo'.",&tolua_err); #endif return 0; } -int lua_ax_base_ShaderCache_newFragmentShaderModule(lua_State* tolua_S) +int lua_ax_base_Touch_getID(lua_State* tolua_S) { int argc = 0; - ax::backend::ShaderCache* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -551,48 +592,45 @@ int lua_ax_base_ShaderCache_newFragmentShaderModule(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::backend::ShaderCache*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_newFragmentShaderModule'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getID'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axb.ShaderCache:newFragmentShaderModule"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_newFragmentShaderModule'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getID'", nullptr); return 0; } - auto&& ret = cobj->newFragmentShaderModule(arg0); - object_to_luaval(tolua_S, "axb.ShaderModule",(ax::backend::ShaderModule*)ret); + auto&& ret = cobj->getID(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ShaderCache:newFragmentShaderModule",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getID",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_newFragmentShaderModule'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getID'.",&tolua_err); #endif return 0; } -int lua_ax_base_ShaderCache_removeUnusedShader(lua_State* tolua_S) +int lua_ax_base_Touch_getCurrentForce(lua_State* tolua_S) { int argc = 0; - ax::backend::ShaderCache* cobj = nullptr; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -601,138 +639,160 @@ int lua_ax_base_ShaderCache_removeUnusedShader(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::backend::ShaderCache*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_removeUnusedShader'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getCurrentForce'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_removeUnusedShader'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getCurrentForce'", nullptr); return 0; } - cobj->removeUnusedShader(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getCurrentForce(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axb.ShaderCache:removeUnusedShader",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getCurrentForce",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_removeUnusedShader'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getCurrentForce'.",&tolua_err); #endif return 0; } -int lua_ax_base_ShaderCache_getInstance(lua_State* tolua_S) +int lua_ax_base_Touch_getMaxForce(lua_State* tolua_S) { int argc = 0; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getMaxForce'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_getInstance'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getMaxForce'", nullptr); return 0; } - auto&& ret = ax::backend::ShaderCache::getInstance(); - object_to_luaval(tolua_S, "axb.ShaderCache",(ax::backend::ShaderCache*)ret); + auto&& ret = cobj->getMaxForce(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.ShaderCache:getInstance",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getMaxForce",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_getInstance'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getMaxForce'.",&tolua_err); #endif + return 0; } -int lua_ax_base_ShaderCache_destroyInstance(lua_State* tolua_S) +int lua_ax_base_Touch_constructor(lua_State* tolua_S) { int argc = 0; + ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axb.ShaderCache",0,&tolua_err)) goto tolua_lerror; -#endif - argc = lua_gettop(tolua_S) - 1; + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_destroyInstance'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_constructor'", nullptr); return 0; } - ax::backend::ShaderCache::destroyInstance(); - lua_settop(tolua_S, 1); + cobj = new ax::Touch(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Touch"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axb.ShaderCache:destroyInstance",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:Touch",argc, 0); return 0; + #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_destroyInstance'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_constructor'.",&tolua_err); #endif + return 0; } -static int lua_ax_base_ShaderCache_finalize(lua_State* tolua_S) + +static int lua_ax_base_Touch_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (ShaderCache)"); + AXLOGV("luabindings: finalizing LUA object (Touch)"); return 0; } -int lua_register_ax_base_ShaderCache(lua_State* tolua_S) +int lua_register_ax_base_Touch(lua_State* tolua_S) { - tolua_usertype(tolua_S,"axb.ShaderCache"); - tolua_cclass(tolua_S,"ShaderCache","axb.ShaderCache","",nullptr); + tolua_usertype(tolua_S,"ax.Touch"); + tolua_cclass(tolua_S,"Touch","ax.Touch","ax.Object",nullptr); - tolua_beginmodule(tolua_S,"ShaderCache"); - tolua_function(tolua_S,"purge",lua_ax_base_ShaderCache_purge); - tolua_function(tolua_S,"newVertexShaderModule",lua_ax_base_ShaderCache_newVertexShaderModule); - tolua_function(tolua_S,"newFragmentShaderModule",lua_ax_base_ShaderCache_newFragmentShaderModule); - tolua_function(tolua_S,"removeUnusedShader",lua_ax_base_ShaderCache_removeUnusedShader); - tolua_function(tolua_S,"getInstance", lua_ax_base_ShaderCache_getInstance); - tolua_function(tolua_S,"destroyInstance", lua_ax_base_ShaderCache_destroyInstance); + tolua_beginmodule(tolua_S,"Touch"); + tolua_function(tolua_S,"new",lua_ax_base_Touch_constructor); + tolua_function(tolua_S,"getLocation",lua_ax_base_Touch_getLocation); + tolua_function(tolua_S,"getPreviousLocation",lua_ax_base_Touch_getPreviousLocation); + tolua_function(tolua_S,"getStartLocation",lua_ax_base_Touch_getStartLocation); + tolua_function(tolua_S,"getDelta",lua_ax_base_Touch_getDelta); + tolua_function(tolua_S,"getLocationInView",lua_ax_base_Touch_getLocationInView); + tolua_function(tolua_S,"getPreviousLocationInView",lua_ax_base_Touch_getPreviousLocationInView); + tolua_function(tolua_S,"getStartLocationInView",lua_ax_base_Touch_getStartLocationInView); + tolua_function(tolua_S,"setTouchInfo",lua_ax_base_Touch_setTouchInfo); + tolua_function(tolua_S,"getId",lua_ax_base_Touch_getID); + tolua_function(tolua_S,"getCurrentForce",lua_ax_base_Touch_getCurrentForce); + tolua_function(tolua_S,"getMaxForce",lua_ax_base_Touch_getMaxForce); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::backend::ShaderCache).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "axb.ShaderCache"; - g_typeCast[typeName] = "axb.ShaderCache"; + auto typeName = typeid(ax::Touch).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Touch"; + g_typeCast[typeName] = "ax.Touch"; return 1; } -int lua_ax_base_Texture2D_updateWithImage(lua_State* tolua_S) +int lua_ax_base_Event_getType(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Event* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -741,71 +801,92 @@ int lua_ax_base_Texture2D_updateWithImage(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithImage'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_getType'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Image* arg0; - ax::backend::PixelFormat arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); - - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithImage"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithImage'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_getType'", nullptr); return 0; } - auto&& ret = cobj->updateWithImage(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + int ret = (int)cobj->getType(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - if (argc == 3) - { - ax::Image* arg0; - ax::backend::PixelFormat arg1; - int arg2; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:getType",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_getType'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Event_stopPropagation(lua_State* tolua_S) +{ + int argc = 0; + ax::Event* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; +#endif - ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); + cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithImage"); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_stopPropagation'", nullptr); + return 0; + } +#endif - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithImage"); + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithImage'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_stopPropagation'", nullptr); return 0; } - auto&& ret = cobj->updateWithImage(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->stopPropagation(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithImage",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:stopPropagation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithImage'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_stopPropagation'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_updateWithMipmaps(lua_State* tolua_S) +int lua_ax_base_Event_isStopped(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Event* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -814,133 +895,203 @@ int lua_ax_base_Texture2D_updateWithMipmaps(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_isStopped'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 0) { - ax::_MipmapInfo* arg0; - int arg1; - ax::backend::PixelFormat arg2; - ax::backend::PixelFormat arg3; - int arg4; - int arg5; - - #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* - ok = false; - - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); - - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); - - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); - - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); - - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_isStopped'", nullptr); return 0; } - auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5); + auto&& ret = cobj->isStopped(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 7) - { - ax::_MipmapInfo* arg0; - int arg1; - ax::backend::PixelFormat arg2; - ax::backend::PixelFormat arg3; - int arg4; - int arg5; - bool arg6; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:isStopped",argc, 0); + return 0; - #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* - ok = false; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_isStopped'.",&tolua_err); +#endif - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); + return 0; +} +int lua_ax_base_Event_getCurrentTarget(lua_State* tolua_S) +{ + int argc = 0; + ax::Event* cobj = nullptr; + bool ok = true; - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; +#endif - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); + cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); - ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:updateWithMipmaps"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); - return 0; +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_getCurrentTarget'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_getCurrentTarget'", nullptr); + return 0; } - auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5, arg6); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getCurrentTarget(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - if (argc == 8) + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:getCurrentTarget",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_getCurrentTarget'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Event_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::Event* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) { - ax::_MipmapInfo* arg0; - int arg1; - ax::backend::PixelFormat arg2; - ax::backend::PixelFormat arg3; - int arg4; - int arg5; - bool arg6; - int arg7; + ax::Event::Type arg0; - #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* - ok = false; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Event:Event"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_constructor'", nullptr); + return 0; + } + cobj = new ax::Event(arg0); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Event"); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:Event",argc, 1); + return 0; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); +#if _AX_DEBUG >= 1 + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_constructor'.",&tolua_err); +#endif - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); + return 0; +} - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); +static int lua_ax_base_Event_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Event)"); + return 0; +} - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); +int lua_register_ax_base_Event(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Event"); + tolua_cclass(tolua_S,"Event","ax.Event","ax.Object",nullptr); - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); + tolua_beginmodule(tolua_S,"Event"); + tolua_function(tolua_S,"new",lua_ax_base_Event_constructor); + tolua_function(tolua_S,"getType",lua_ax_base_Event_getType); + tolua_function(tolua_S,"stopPropagation",lua_ax_base_Event_stopPropagation); + tolua_function(tolua_S,"isStopped",lua_ax_base_Event_isStopped); + tolua_function(tolua_S,"getCurrentTarget",lua_ax_base_Event_getCurrentTarget); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Event).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Event"; + g_typeCast[typeName] = "ax.Event"; + return 1; +} - ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:updateWithMipmaps"); +int lua_ax_base_EventTouch_getEventCode(lua_State* tolua_S) +{ + int argc = 0; + ax::EventTouch* cobj = nullptr; + bool ok = true; - ok &= luaval_to_int32(tolua_S, 9,(int *)&arg7, "ax.Texture2D:updateWithMipmaps"); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.EventTouch",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::EventTouch*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventTouch_getEventCode'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_getEventCode'", nullptr); return 0; } - auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - tolua_pushboolean(tolua_S,(bool)ret); + int ret = (int)cobj->getEventCode(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithMipmaps",argc, 6); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:getEventCode",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithMipmaps'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_getEventCode'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_updateWithSubData(lua_State* tolua_S) +int lua_ax_base_EventTouch_setEventCode(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::EventTouch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -949,91 +1100,170 @@ int lua_ax_base_Texture2D_updateWithSubData(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.EventTouch",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::EventTouch*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventTouch_setEventCode'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 1) { - void* arg0; - int arg1; - int arg2; - int arg3; - int arg4; + ax::EventTouch::EventCode arg0; - #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.EventTouch:setEventCode"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_setEventCode'", nullptr); + return 0; + } + cobj->setEventCode(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:setEventCode",argc, 1); + return 0; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithSubData"); +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_setEventCode'.",&tolua_err); +#endif - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithSubData"); + return 0; +} +int lua_ax_base_EventTouch_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::EventTouch* cobj = nullptr; + bool ok = true; - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithSubData"); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithSubData"); + + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_constructor'", nullptr); return 0; } - auto&& ret = cobj->updateWithSubData(arg0, arg1, arg2, arg3, arg4); - tolua_pushboolean(tolua_S,(bool)ret); + cobj = new ax::EventTouch(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventTouch"); return 1; } - if (argc == 6) - { - void* arg0; - int arg1; - int arg2; - int arg3; - int arg4; - int arg5; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:EventTouch",argc, 0); + return 0; - #pragma warning NO CONVERSION TO NATIVE FOR void* - ok = false; +#if _AX_DEBUG >= 1 + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_constructor'.",&tolua_err); +#endif - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithSubData"); + return 0; +} - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithSubData"); +static int lua_ax_base_EventTouch_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (EventTouch)"); + return 0; +} - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithSubData"); +int lua_register_ax_base_EventTouch(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.EventTouch"); + tolua_cclass(tolua_S,"EventTouch","ax.EventTouch","ax.Event",nullptr); - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithSubData"); + tolua_beginmodule(tolua_S,"EventTouch"); + tolua_function(tolua_S,"new",lua_ax_base_EventTouch_constructor); + tolua_function(tolua_S,"getEventCode",lua_ax_base_EventTouch_getEventCode); + tolua_function(tolua_S,"setEventCode",lua_ax_base_EventTouch_setEventCode); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::EventTouch).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.EventTouch"; + g_typeCast[typeName] = "ax.EventTouch"; + return 1; +} - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithSubData"); +int lua_ax_base_EventKeyboard_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::EventKeyboard* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + ax::EventKeyboard::KeyCode arg0; + bool arg1; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.EventKeyboard:EventKeyboard"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.EventKeyboard:EventKeyboard"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventKeyboard_constructor'", nullptr); return 0; } - auto&& ret = cobj->updateWithSubData(arg0, arg1, arg2, arg3, arg4, arg5); - tolua_pushboolean(tolua_S,(bool)ret); + cobj = new ax::EventKeyboard(arg0, arg1); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventKeyboard"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithSubData",argc, 5); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventKeyboard:EventKeyboard",argc, 2); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithSubData'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventKeyboard_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_drawAtPoint(lua_State* tolua_S) + +static int lua_ax_base_EventKeyboard_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (EventKeyboard)"); + return 0; +} + +int lua_register_ax_base_EventKeyboard(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.EventKeyboard"); + tolua_cclass(tolua_S,"EventKeyboard","ax.EventKeyboard","ax.Event",nullptr); + + tolua_beginmodule(tolua_S,"EventKeyboard"); + tolua_function(tolua_S,"new",lua_ax_base_EventKeyboard_constructor); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::EventKeyboard).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.EventKeyboard"; + g_typeCast[typeName] = "ax.EventKeyboard"; + return 1; +} + +int lua_ax_base_Action_clone(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1042,51 +1272,45 @@ int lua_ax_base_Texture2D_drawAtPoint(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_drawAtPoint'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_clone'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Vec2 arg0; - double arg1; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Texture2D:drawAtPoint"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Texture2D:drawAtPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_drawAtPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_clone'", nullptr); return 0; } - cobj->drawAtPoint(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:drawAtPoint",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:clone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_drawAtPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_clone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_drawInRect(lua_State* tolua_S) +int lua_ax_base_Action_reverse(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1095,337 +1319,189 @@ int lua_ax_base_Texture2D_drawInRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_drawInRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_reverse'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Rect arg0; - double arg1; - - ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.Texture2D:drawInRect"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Texture2D:drawInRect"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_drawInRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_reverse'", nullptr); return 0; } - cobj->drawInRect(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->reverse(); + object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:drawInRect",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:reverse",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_drawInRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_reverse'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_initWithImage(lua_State* tolua_S) +int lua_ax_base_Action_isDone(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_initWithImage'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_isDone'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - ax::Image* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:initWithImage"); - - if (!ok) { break; } - ax::backend::PixelFormat arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:initWithImage"); - - if (!ok) { break; } - bool ret = cobj->initWithImage(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Image* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:initWithImage"); - if (!ok) { break; } - bool ret = cobj->initWithImage(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_isDone'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:initWithImage",argc, 1); + auto&& ret = cobj->isDone(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:isDone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_initWithImage'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_isDone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_initWithString(lua_State* tolua_S) +int lua_ax_base_Action_startWithTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_initWithString'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_startWithTarget'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - if (!ok) { break; } - ax::FontDefinition arg1; - ok &= luaval_to_fontdefinition(tolua_S, 3, &arg1, "ax.Texture2D:initWithString"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Node* arg0; - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:startWithTarget"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_startWithTarget'", nullptr); + return 0; } - }while(0); - ok = true; - do{ - if (argc == 3) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + cobj->startWithTarget(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:startWithTarget",argc, 1); + return 0; - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 4) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_startWithTarget'.",&tolua_err); +#endif - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + return 0; +} +int lua_ax_base_Action_stop(lua_State* tolua_S) +{ + int argc = 0; + ax::Action* cobj = nullptr; + bool ok = true; - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 5) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; +#endif - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextHAlignment arg4; - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 6) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextHAlignment arg4; - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextVAlignment arg5; - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 7) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextHAlignment arg4; - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextVAlignment arg5; - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - bool arg6; - ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5, arg6); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 8) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - std::string_view arg1; - ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextHAlignment arg4; - ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - ax::TextVAlignment arg5; - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - bool arg6; - ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:initWithString"); - - if (!ok) { break; } - int arg7; - ok &= luaval_to_int32(tolua_S, 9,(int *)&arg7, "ax.Texture2D:initWithString"); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_stop'", nullptr); + return 0; + } +#endif - if (!ok) { break; } - bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_stop'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:initWithString",argc, 3); + cobj->stop(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:stop",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_initWithString'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_stop'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_updateTextureDescriptor(lua_State* tolua_S) +int lua_ax_base_Action_step(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1434,67 +1510,48 @@ int lua_ax_base_Texture2D_updateTextureDescriptor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateTextureDescriptor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_step'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::backend::TextureDescriptor arg0; - - #pragma warning NO CONVERSION TO NATIVE FOR TextureDescriptor - ok = false; - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateTextureDescriptor'", nullptr); - return 0; - } - auto&& ret = cobj->updateTextureDescriptor(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 2) + if (argc == 1) { - ax::backend::TextureDescriptor arg0; - bool arg1; - - #pragma warning NO CONVERSION TO NATIVE FOR TextureDescriptor - ok = false; + double arg0; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Texture2D:updateTextureDescriptor"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Action:step"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateTextureDescriptor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_step'", nullptr); return 0; } - auto&& ret = cobj->updateTextureDescriptor(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->step(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateTextureDescriptor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:step",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateTextureDescriptor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_step'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setRenderTarget(lua_State* tolua_S) +int lua_ax_base_Action_update(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1503,48 +1560,48 @@ int lua_ax_base_Texture2D_setRenderTarget(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setRenderTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_update'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - bool arg0; + double arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Texture2D:setRenderTarget"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Action:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setRenderTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_update'", nullptr); return 0; } - cobj->setRenderTarget(arg0); + cobj->update(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setRenderTarget",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:update",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setRenderTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_update'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_isRenderTarget(lua_State* tolua_S) +int lua_ax_base_Action_getTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1553,45 +1610,45 @@ int lua_ax_base_Texture2D_isRenderTarget(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_isRenderTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_isRenderTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getTarget'", nullptr); return 0; } - auto&& ret = cobj->isRenderTarget(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getTarget(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:isRenderTarget",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getTarget",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_isRenderTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_generateMipmap(lua_State* tolua_S) +int lua_ax_base_Action_setTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1600,45 +1657,48 @@ int lua_ax_base_Texture2D_generateMipmap(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_generateMipmap'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:setTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_generateMipmap'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setTarget'", nullptr); return 0; } - cobj->generateMipmap(); + cobj->setTarget(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:generateMipmap",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setTarget",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_generateMipmap'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setAntiAliasTexParameters(lua_State* tolua_S) +int lua_ax_base_Action_getOriginalTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1647,45 +1707,45 @@ int lua_ax_base_Texture2D_setAntiAliasTexParameters(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getOriginalTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getOriginalTarget'", nullptr); return 0; } - cobj->setAntiAliasTexParameters(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getOriginalTarget(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setAntiAliasTexParameters",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getOriginalTarget",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getOriginalTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setAliasTexParameters(lua_State* tolua_S) +int lua_ax_base_Action_setOriginalTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1694,45 +1754,48 @@ int lua_ax_base_Texture2D_setAliasTexParameters(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setAliasTexParameters'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setOriginalTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:setOriginalTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setAliasTexParameters'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setOriginalTarget'", nullptr); return 0; } - cobj->setAliasTexParameters(); + cobj->setOriginalTarget(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setAliasTexParameters",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setOriginalTarget",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setAliasTexParameters'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setOriginalTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getStringForFormat(lua_State* tolua_S) +int lua_ax_base_Action_getTag(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1741,96 +1804,95 @@ int lua_ax_base_Texture2D_getStringForFormat(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getStringForFormat'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getStringForFormat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getTag'", nullptr); return 0; } - auto&& ret = cobj->getStringForFormat(); - tolua_pushstring(tolua_S,(const char*)ret); + auto&& ret = cobj->getTag(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getStringForFormat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getTag",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getStringForFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getBitsPerPixelForFormat(lua_State* tolua_S) +int lua_ax_base_Action_setTag(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getBitsPerPixelForFormat'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setTag'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::backend::PixelFormat arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Texture2D:getBitsPerPixelForFormat"); + if (argc == 1) + { + int arg0; - if (!ok) { break; } - unsigned int ret = cobj->getBitsPerPixelForFormat(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - unsigned int ret = cobj->getBitsPerPixelForFormat(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Action:setTag"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setTag'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getBitsPerPixelForFormat",argc, 0); + cobj->setTag(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getBitsPerPixelForFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getContentSizeInPixels(lua_State* tolua_S) +int lua_ax_base_Action_getFlags(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1839,45 +1901,45 @@ int lua_ax_base_Texture2D_getContentSizeInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getContentSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getFlags'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getContentSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getFlags'", nullptr); return 0; } - auto&& ret = cobj->getContentSizeInPixels(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getFlags(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getContentSizeInPixels",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getFlags",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getContentSizeInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getFlags'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_hasPremultipliedAlpha(lua_State* tolua_S) +int lua_ax_base_Action_setFlags(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1886,45 +1948,82 @@ int lua_ax_base_Texture2D_hasPremultipliedAlpha(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setFlags'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + unsigned int arg0; + + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Action:setFlags"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setFlags'", nullptr); return 0; } - auto&& ret = cobj->hasPremultipliedAlpha(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setFlags(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:hasPremultipliedAlpha",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setFlags",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setFlags'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setPremultipliedAlpha(lua_State* tolua_S) +static int lua_ax_base_Action_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Action)"); + return 0; +} + +int lua_register_ax_base_Action(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Action"); + tolua_cclass(tolua_S,"Action","ax.Action","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Action"); + tolua_function(tolua_S,"clone",lua_ax_base_Action_clone); + tolua_function(tolua_S,"reverse",lua_ax_base_Action_reverse); + tolua_function(tolua_S,"isDone",lua_ax_base_Action_isDone); + tolua_function(tolua_S,"startWithTarget",lua_ax_base_Action_startWithTarget); + tolua_function(tolua_S,"stop",lua_ax_base_Action_stop); + tolua_function(tolua_S,"step",lua_ax_base_Action_step); + tolua_function(tolua_S,"update",lua_ax_base_Action_update); + tolua_function(tolua_S,"getTarget",lua_ax_base_Action_getTarget); + tolua_function(tolua_S,"setTarget",lua_ax_base_Action_setTarget); + tolua_function(tolua_S,"getOriginalTarget",lua_ax_base_Action_getOriginalTarget); + tolua_function(tolua_S,"setOriginalTarget",lua_ax_base_Action_setOriginalTarget); + tolua_function(tolua_S,"getTag",lua_ax_base_Action_getTag); + tolua_function(tolua_S,"setTag",lua_ax_base_Action_setTag); + tolua_function(tolua_S,"getFlags",lua_ax_base_Action_getFlags); + tolua_function(tolua_S,"setFlags",lua_ax_base_Action_setFlags); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Action).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Action"; + g_typeCast[typeName] = "ax.Action"; + return 1; +} + +int lua_ax_base_FiniteTimeAction_getDuration(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::FiniteTimeAction* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1933,48 +2032,45 @@ int lua_ax_base_Texture2D_setPremultipliedAlpha(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.FiniteTimeAction",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::FiniteTimeAction*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FiniteTimeAction_getDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Texture2D:setPremultipliedAlpha"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FiniteTimeAction_getDuration'", nullptr); return 0; } - cobj->setPremultipliedAlpha(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getDuration(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setPremultipliedAlpha",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FiniteTimeAction:getDuration",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FiniteTimeAction_getDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_hasMipmaps(lua_State* tolua_S) +int lua_ax_base_FiniteTimeAction_setDuration(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::FiniteTimeAction* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1983,45 +2079,69 @@ int lua_ax_base_Texture2D_hasMipmaps(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.FiniteTimeAction",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::FiniteTimeAction*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_hasMipmaps'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FiniteTimeAction_setDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FiniteTimeAction:setDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_hasMipmaps'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FiniteTimeAction_setDuration'", nullptr); return 0; } - auto&& ret = cobj->hasMipmaps(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setDuration(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:hasMipmaps",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FiniteTimeAction:setDuration",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_hasMipmaps'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FiniteTimeAction_setDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getPixelFormat(lua_State* tolua_S) +static int lua_ax_base_FiniteTimeAction_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (FiniteTimeAction)"); + return 0; +} + +int lua_register_ax_base_FiniteTimeAction(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.FiniteTimeAction"); + tolua_cclass(tolua_S,"FiniteTimeAction","ax.FiniteTimeAction","ax.Action",nullptr); + + tolua_beginmodule(tolua_S,"FiniteTimeAction"); + tolua_function(tolua_S,"getDuration",lua_ax_base_FiniteTimeAction_getDuration); + tolua_function(tolua_S,"setDuration",lua_ax_base_FiniteTimeAction_setDuration); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::FiniteTimeAction).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.FiniteTimeAction"; + g_typeCast[typeName] = "ax.FiniteTimeAction"; + return 1; +} + +int lua_ax_base_Speed_getSpeed(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2030,45 +2150,45 @@ int lua_ax_base_Texture2D_getPixelFormat(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelFormat'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_getSpeed'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelFormat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_getSpeed'", nullptr); return 0; } - int ret = (int)cobj->getPixelFormat(); + auto&& ret = cobj->getSpeed(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelFormat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:getSpeed",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_getSpeed'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getSamplerFlags(lua_State* tolua_S) +int lua_ax_base_Speed_setSpeed(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2077,45 +2197,48 @@ int lua_ax_base_Texture2D_getSamplerFlags(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getSamplerFlags'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_setSpeed'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Speed:setSpeed"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getSamplerFlags'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_setSpeed'", nullptr); return 0; } - auto&& ret = cobj->getSamplerFlags(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setSpeed(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getSamplerFlags",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:setSpeed",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getSamplerFlags'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_setSpeed'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getPixelsWide(lua_State* tolua_S) +int lua_ax_base_Speed_setInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2124,45 +2247,48 @@ int lua_ax_base_Texture2D_getPixelsWide(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelsWide'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_setInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::ActionInterval* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:setInnerAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelsWide'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_setInnerAction'", nullptr); return 0; } - auto&& ret = cobj->getPixelsWide(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setInnerAction(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelsWide",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:setInnerAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelsWide'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_setInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getPixelsHigh(lua_State* tolua_S) +int lua_ax_base_Speed_getInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2171,45 +2297,45 @@ int lua_ax_base_Texture2D_getPixelsHigh(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelsHigh'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_getInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelsHigh'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_getInnerAction'", nullptr); return 0; } - auto&& ret = cobj->getPixelsHigh(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getInnerAction(); + object_to_luaval(tolua_S, "ax.ActionInterval",(ax::ActionInterval*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelsHigh",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:getInnerAction",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelsHigh'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_getInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getBackendTexture(lua_State* tolua_S) +int lua_ax_base_Speed_initWithAction(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2218,92 +2344,89 @@ int lua_ax_base_Texture2D_getBackendTexture(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getBackendTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_initWithAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::ActionInterval* arg0; + double arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:initWithAction"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Speed:initWithAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getBackendTexture'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_initWithAction'", nullptr); return 0; } - auto&& ret = cobj->getBackendTexture(); - object_to_luaval(tolua_S, "axb.TextureBackend",(ax::backend::TextureBackend*)ret); + auto&& ret = cobj->initWithAction(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getBackendTexture",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:initWithAction",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getBackendTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_initWithAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getMaxS(lua_State* tolua_S) +int lua_ax_base_Speed_create(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getMaxS'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::ActionInterval* arg0; + double arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Speed:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getMaxS'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_create'", nullptr); return 0; } - auto&& ret = cobj->getMaxS(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::Speed::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.Speed",(ax::Speed*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getMaxS",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Speed:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getMaxS'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Texture2D_setMaxS(lua_State* tolua_S) +int lua_ax_base_Speed_constructor(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2311,49 +2434,62 @@ int lua_ax_base_Texture2D_setMaxS(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setMaxS'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Texture2D:setMaxS"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setMaxS'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_constructor'", nullptr); return 0; } - cobj->setMaxS(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::Speed(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Speed"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setMaxS",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:Speed",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setMaxS'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getMaxT(lua_State* tolua_S) + +static int lua_ax_base_Speed_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Speed)"); + return 0; +} + +int lua_register_ax_base_Speed(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Speed"); + tolua_cclass(tolua_S,"Speed","ax.Speed","ax.Action",nullptr); + + tolua_beginmodule(tolua_S,"Speed"); + tolua_function(tolua_S,"new",lua_ax_base_Speed_constructor); + tolua_function(tolua_S,"getSpeed",lua_ax_base_Speed_getSpeed); + tolua_function(tolua_S,"setSpeed",lua_ax_base_Speed_setSpeed); + tolua_function(tolua_S,"setInnerAction",lua_ax_base_Speed_setInnerAction); + tolua_function(tolua_S,"getInnerAction",lua_ax_base_Speed_getInnerAction); + tolua_function(tolua_S,"initWithAction",lua_ax_base_Speed_initWithAction); + tolua_function(tolua_S,"create", lua_ax_base_Speed_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Speed).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Speed"; + g_typeCast[typeName] = "ax.Speed"; + return 1; +} + +int lua_ax_base_Follow_isBoundarySet(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2362,45 +2498,45 @@ int lua_ax_base_Texture2D_getMaxT(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getMaxT'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_isBoundarySet'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getMaxT'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_isBoundarySet'", nullptr); return 0; } - auto&& ret = cobj->getMaxT(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->isBoundarySet(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getMaxT",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:isBoundarySet",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getMaxT'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_isBoundarySet'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setMaxT(lua_State* tolua_S) +int lua_ax_base_Follow_setBoundarySet(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2409,48 +2545,48 @@ int lua_ax_base_Texture2D_setMaxT(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setMaxT'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_setBoundarySet'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + bool arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Texture2D:setMaxT"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Follow:setBoundarySet"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setMaxT'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_setBoundarySet'", nullptr); return 0; } - cobj->setMaxT(arg0); + cobj->setBoundarySet(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setMaxT",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:setBoundarySet",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setMaxT'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_setBoundarySet'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getContentSize(lua_State* tolua_S) +int lua_ax_base_Follow_initWithTarget(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2459,45 +2595,65 @@ int lua_ax_base_Texture2D_getContentSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getContentSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_initWithTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getContentSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTarget'", nullptr); return 0; } - auto&& ret = cobj->getContentSize(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->initWithTarget(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getContentSize",argc, 0); + if (argc == 2) + { + ax::Node* arg0; + ax::Rect arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTarget"); + + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Follow:initWithTarget"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTarget'", nullptr); + return 0; + } + auto&& ret = cobj->initWithTarget(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:initWithTarget",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getContentSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_initWithTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getPath(lua_State* tolua_S) +int lua_ax_base_Follow_initWithTargetAndOffset(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2506,42 +2662,74 @@ int lua_ax_base_Texture2D_getPath(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPath'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 3) { + ax::Node* arg0; + double arg1; + double arg2; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTargetAndOffset"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:initWithTargetAndOffset"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:initWithTargetAndOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPath'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); return 0; } - auto&& ret = cobj->getPath(); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + auto&& ret = cobj->initWithTargetAndOffset(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPath",argc, 0); + if (argc == 4) + { + ax::Node* arg0; + double arg1; + double arg2; + ax::Rect arg3; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTargetAndOffset"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:initWithTargetAndOffset"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:initWithTargetAndOffset"); + + ok &= luaval_to_rect(tolua_S, 5, &arg3, "ax.Follow:initWithTargetAndOffset"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); + return 0; + } + auto&& ret = cobj->initWithTargetAndOffset(arg0, arg1, arg2, arg3); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:initWithTargetAndOffset",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPath'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_initWithTargetAndOffset'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_setDefaultAlphaPixelFormat(lua_State* tolua_S) +int lua_ax_base_Follow_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -2551,33 +2739,48 @@ int lua_ax_base_Texture2D_setDefaultAlphaPixelFormat(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; if (argc == 1) { - ax::backend::PixelFormat arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Texture2D:setDefaultAlphaPixelFormat"); + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setDefaultAlphaPixelFormat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_create'", nullptr); return 0; } - ax::Texture2D::setDefaultAlphaPixelFormat(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::Follow::create(arg0); + object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); + return 1; + } + if (argc == 2) + { + ax::Node* arg0; + ax::Rect arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:create"); + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Follow:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_create'", nullptr); + return 0; + } + auto&& ret = ax::Follow::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Texture2D:setDefaultAlphaPixelFormat",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Follow:create",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setDefaultAlphaPixelFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_create'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_getDefaultAlphaPixelFormat(lua_State* tolua_S) +int lua_ax_base_Follow_createWithOffset(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -2587,34 +2790,59 @@ int lua_ax_base_Texture2D_getDefaultAlphaPixelFormat(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 0) + if (argc == 3) { + ax::Node* arg0; + double arg1; + double arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:createWithOffset"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:createWithOffset"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:createWithOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getDefaultAlphaPixelFormat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_createWithOffset'", nullptr); return 0; } - int ret = (int)ax::Texture2D::getDefaultAlphaPixelFormat(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::Follow::createWithOffset(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); + return 1; + } + if (argc == 4) + { + ax::Node* arg0; + double arg1; + double arg2; + ax::Rect arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:createWithOffset"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:createWithOffset"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:createWithOffset"); + ok &= luaval_to_rect(tolua_S, 5, &arg3, "ax.Follow:createWithOffset"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_createWithOffset'", nullptr); + return 0; + } + auto&& ret = ax::Follow::createWithOffset(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Texture2D:getDefaultAlphaPixelFormat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Follow:createWithOffset",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getDefaultAlphaPixelFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_createWithOffset'.",&tolua_err); #endif return 0; } -int lua_ax_base_Texture2D_constructor(lua_State* tolua_S) +int lua_ax_base_Follow_constructor(lua_State* tolua_S) { int argc = 0; - ax::Texture2D* cobj = nullptr; + ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2624,86 +2852,60 @@ int lua_ax_base_Texture2D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_constructor'", nullptr); return 0; } - cobj = new ax::Texture2D(); + cobj = new ax::Follow(); cobj->autorelease(); int ID = (int)cobj->_ID ; int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Texture2D"); + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Follow"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:Texture2D",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:Follow",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Texture2D_finalize(lua_State* tolua_S) +static int lua_ax_base_Follow_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Texture2D)"); + AXLOGV("luabindings: finalizing LUA object (Follow)"); return 0; } -int lua_register_ax_base_Texture2D(lua_State* tolua_S) +int lua_register_ax_base_Follow(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Texture2D"); - tolua_cclass(tolua_S,"Texture2D","ax.Texture2D","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.Follow"); + tolua_cclass(tolua_S,"Follow","ax.Follow","ax.Action",nullptr); - tolua_beginmodule(tolua_S,"Texture2D"); - tolua_function(tolua_S,"new",lua_ax_base_Texture2D_constructor); - tolua_function(tolua_S,"updateWithImage",lua_ax_base_Texture2D_updateWithImage); - tolua_function(tolua_S,"updateWithMipmaps",lua_ax_base_Texture2D_updateWithMipmaps); - tolua_function(tolua_S,"updateWithSubData",lua_ax_base_Texture2D_updateWithSubData); - tolua_function(tolua_S,"drawAtPoint",lua_ax_base_Texture2D_drawAtPoint); - tolua_function(tolua_S,"drawInRect",lua_ax_base_Texture2D_drawInRect); - tolua_function(tolua_S,"initWithImage",lua_ax_base_Texture2D_initWithImage); - tolua_function(tolua_S,"initWithString",lua_ax_base_Texture2D_initWithString); - tolua_function(tolua_S,"updateTextureDescriptor",lua_ax_base_Texture2D_updateTextureDescriptor); - tolua_function(tolua_S,"setRenderTarget",lua_ax_base_Texture2D_setRenderTarget); - tolua_function(tolua_S,"isRenderTarget",lua_ax_base_Texture2D_isRenderTarget); - tolua_function(tolua_S,"generateMipmap",lua_ax_base_Texture2D_generateMipmap); - tolua_function(tolua_S,"setAntiAliasTexParameters",lua_ax_base_Texture2D_setAntiAliasTexParameters); - tolua_function(tolua_S,"setAliasTexParameters",lua_ax_base_Texture2D_setAliasTexParameters); - tolua_function(tolua_S,"getStringForFormat",lua_ax_base_Texture2D_getStringForFormat); - tolua_function(tolua_S,"getBitsPerPixelForFormat",lua_ax_base_Texture2D_getBitsPerPixelForFormat); - tolua_function(tolua_S,"getContentSizeInPixels",lua_ax_base_Texture2D_getContentSizeInPixels); - tolua_function(tolua_S,"hasPremultipliedAlpha",lua_ax_base_Texture2D_hasPremultipliedAlpha); - tolua_function(tolua_S,"setPremultipliedAlpha",lua_ax_base_Texture2D_setPremultipliedAlpha); - tolua_function(tolua_S,"hasMipmaps",lua_ax_base_Texture2D_hasMipmaps); - tolua_function(tolua_S,"getPixelFormat",lua_ax_base_Texture2D_getPixelFormat); - tolua_function(tolua_S,"getSamplerFlags",lua_ax_base_Texture2D_getSamplerFlags); - tolua_function(tolua_S,"getPixelsWide",lua_ax_base_Texture2D_getPixelsWide); - tolua_function(tolua_S,"getPixelsHigh",lua_ax_base_Texture2D_getPixelsHigh); - tolua_function(tolua_S,"getBackendTexture",lua_ax_base_Texture2D_getBackendTexture); - tolua_function(tolua_S,"getMaxS",lua_ax_base_Texture2D_getMaxS); - tolua_function(tolua_S,"setMaxS",lua_ax_base_Texture2D_setMaxS); - tolua_function(tolua_S,"getMaxT",lua_ax_base_Texture2D_getMaxT); - tolua_function(tolua_S,"setMaxT",lua_ax_base_Texture2D_setMaxT); - tolua_function(tolua_S,"getContentSize",lua_ax_base_Texture2D_getContentSize); - tolua_function(tolua_S,"getPath",lua_ax_base_Texture2D_getPath); - tolua_function(tolua_S,"setDefaultAlphaPixelFormat", lua_ax_base_Texture2D_setDefaultAlphaPixelFormat); - tolua_function(tolua_S,"getDefaultAlphaPixelFormat", lua_ax_base_Texture2D_getDefaultAlphaPixelFormat); + tolua_beginmodule(tolua_S,"Follow"); + tolua_function(tolua_S,"new",lua_ax_base_Follow_constructor); + tolua_function(tolua_S,"isBoundarySet",lua_ax_base_Follow_isBoundarySet); + tolua_function(tolua_S,"setBoundarySet",lua_ax_base_Follow_setBoundarySet); + tolua_function(tolua_S,"initWithTarget",lua_ax_base_Follow_initWithTarget); + tolua_function(tolua_S,"initWithTargetAndOffset",lua_ax_base_Follow_initWithTargetAndOffset); + tolua_function(tolua_S,"create", lua_ax_base_Follow_create); + tolua_function(tolua_S,"createWithOffset", lua_ax_base_Follow_createWithOffset); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Texture2D).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Texture2D"; - g_typeCast[typeName] = "ax.Texture2D"; + auto typeName = typeid(ax::Follow).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Follow"; + g_typeCast[typeName] = "ax.Follow"; return 1; } -int lua_ax_base_Touch_getLocation(lua_State* tolua_S) +int lua_ax_base_EventListener_checkAvailable(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::EventListener* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2712,45 +2914,45 @@ int lua_ax_base_Touch_getLocation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getLocation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_checkAvailable'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getLocation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_checkAvailable'", nullptr); return 0; } - auto&& ret = cobj->getLocation(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->checkAvailable(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getLocation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:checkAvailable",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getLocation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_checkAvailable'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getPreviousLocation(lua_State* tolua_S) +int lua_ax_base_EventListener_clone(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::EventListener* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2759,45 +2961,45 @@ int lua_ax_base_Touch_getPreviousLocation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getPreviousLocation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_clone'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getPreviousLocation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_clone'", nullptr); return 0; } - auto&& ret = cobj->getPreviousLocation(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "ax.EventListener",(ax::EventListener*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getPreviousLocation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:clone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getPreviousLocation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_clone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getStartLocation(lua_State* tolua_S) +int lua_ax_base_EventListener_setEnabled(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::EventListener* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2806,45 +3008,48 @@ int lua_ax_base_Touch_getStartLocation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getStartLocation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_setEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.EventListener:setEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getStartLocation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_setEnabled'", nullptr); return 0; } - auto&& ret = cobj->getStartLocation(); - vec2_to_luaval(tolua_S, ret); + cobj->setEnabled(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getStartLocation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:setEnabled",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getStartLocation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_setEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getDelta(lua_State* tolua_S) +int lua_ax_base_EventListener_isEnabled(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::EventListener* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2853,45 +3058,68 @@ int lua_ax_base_Touch_getDelta(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.EventListener",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::EventListener*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getDelta'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventListener_isEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getDelta'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListener_isEnabled'", nullptr); return 0; } - auto&& ret = cobj->getDelta(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->isEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getDelta",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListener:isEnabled",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getDelta'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListener_isEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getLocationInView(lua_State* tolua_S) +static int lua_ax_base_EventListener_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (EventListener)"); + return 0; +} + +int lua_register_ax_base_EventListener(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.EventListener"); + tolua_cclass(tolua_S,"EventListener","ax.EventListener","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"EventListener"); + tolua_function(tolua_S,"checkAvailable",lua_ax_base_EventListener_checkAvailable); + tolua_function(tolua_S,"clone",lua_ax_base_EventListener_clone); + tolua_function(tolua_S,"setEnabled",lua_ax_base_EventListener_setEnabled); + tolua_function(tolua_S,"isEnabled",lua_ax_base_EventListener_isEnabled); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::EventListener).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.EventListener"; + g_typeCast[typeName] = "ax.EventListener"; + return 1; +} + +int lua_ax_base_EventListenerCustom_constructor(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::EventListenerCustom* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2899,46 +3127,56 @@ int lua_ax_base_Touch_getLocationInView(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getLocationInView'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getLocationInView'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventListenerCustom_constructor'", nullptr); return 0; } - auto&& ret = cobj->getLocationInView(); - vec2_to_luaval(tolua_S, ret); + cobj = new ax::EventListenerCustom(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventListenerCustom"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getLocationInView",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventListenerCustom:EventListenerCustom",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getLocationInView'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventListenerCustom_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getPreviousLocationInView(lua_State* tolua_S) + +static int lua_ax_base_EventListenerCustom_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (EventListenerCustom)"); + return 0; +} + +int lua_register_ax_base_EventListenerCustom(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.EventListenerCustom"); + tolua_cclass(tolua_S,"EventListenerCustom","ax.EventListenerCustom","ax.EventListener",nullptr); + + tolua_beginmodule(tolua_S,"EventListenerCustom"); + tolua_function(tolua_S,"new",lua_ax_base_EventListenerCustom_constructor); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::EventListenerCustom).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.EventListenerCustom"; + g_typeCast[typeName] = "ax.EventListenerCustom"; + return 1; +} + +int lua_ax_base_ShaderCache_purge(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::rhi::ShaderCache* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2947,45 +3185,45 @@ int lua_ax_base_Touch_getPreviousLocationInView(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::rhi::ShaderCache*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getPreviousLocationInView'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_purge'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getPreviousLocationInView'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_purge'", nullptr); return 0; } - auto&& ret = cobj->getPreviousLocationInView(); - vec2_to_luaval(tolua_S, ret); + cobj->purge(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getPreviousLocationInView",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ShaderCache:purge",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getPreviousLocationInView'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_purge'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getStartLocationInView(lua_State* tolua_S) +int lua_ax_base_ShaderCache_acquireVertexShaderModule(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::rhi::ShaderCache* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2994,124 +3232,48 @@ int lua_ax_base_Touch_getStartLocationInView(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::rhi::ShaderCache*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getStartLocationInView'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_acquireVertexShaderModule'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.ShaderCache:acquireVertexShaderModule"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getStartLocationInView'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_acquireVertexShaderModule'", nullptr); return 0; } - auto&& ret = cobj->getStartLocationInView(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->acquireVertexShaderModule(arg0); + object_to_luaval(tolua_S, "axrhi.ShaderModule",(ax::rhi::ShaderModule*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getStartLocationInView",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getStartLocationInView'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_Touch_setTouchInfo(lua_State* tolua_S) -{ - int argc = 0; - ax::Touch* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_setTouchInfo'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 5) { - int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg3; - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg4; - ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - cobj->setTouchInfo(arg0, arg1, arg2, arg3, arg4); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Touch:setTouchInfo"); - - if (!ok) { break; } - cobj->setTouchInfo(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:setTouchInfo",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ShaderCache:acquireVertexShaderModule",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_setTouchInfo'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_acquireVertexShaderModule'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getID(lua_State* tolua_S) +int lua_ax_base_ShaderCache_acquireFragmentShaderModule(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::rhi::ShaderCache* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3120,45 +3282,48 @@ int lua_ax_base_Touch_getID(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::rhi::ShaderCache*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getID'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_acquireFragmentShaderModule'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.ShaderCache:acquireFragmentShaderModule"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getID'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_acquireFragmentShaderModule'", nullptr); return 0; } - auto&& ret = cobj->getID(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->acquireFragmentShaderModule(arg0); + object_to_luaval(tolua_S, "axrhi.ShaderModule",(ax::rhi::ShaderModule*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getID",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ShaderCache:acquireFragmentShaderModule",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getID'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_acquireFragmentShaderModule'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getCurrentForce(lua_State* tolua_S) +int lua_ax_base_ShaderCache_removeUnusedShader(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; + ax::rhi::ShaderCache* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3167,254 +3332,233 @@ int lua_ax_base_Touch_getCurrentForce(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::rhi::ShaderCache*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getCurrentForce'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ShaderCache_removeUnusedShader'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getCurrentForce'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_removeUnusedShader'", nullptr); return 0; } - auto&& ret = cobj->getCurrentForce(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->removeUnusedShader(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getCurrentForce",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ShaderCache:removeUnusedShader",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getCurrentForce'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_removeUnusedShader'.",&tolua_err); #endif return 0; } -int lua_ax_base_Touch_getMaxForce(lua_State* tolua_S) +int lua_ax_base_ShaderCache_getInstance(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Touch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Touch*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Touch_getMaxForce'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_getMaxForce'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_getInstance'", nullptr); return 0; } - auto&& ret = cobj->getMaxForce(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::rhi::ShaderCache::getInstance(); + object_to_luaval(tolua_S, "axrhi.ShaderCache",(ax::rhi::ShaderCache*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:getMaxForce",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axrhi.ShaderCache:getInstance",argc, 0); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_getMaxForce'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_getInstance'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Touch_constructor(lua_State* tolua_S) +int lua_ax_base_ShaderCache_destroyInstance(lua_State* tolua_S) { int argc = 0; - ax::Touch* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"axrhi.ShaderCache",0,&tolua_err)) goto tolua_lerror; +#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Touch_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ShaderCache_destroyInstance'", nullptr); return 0; } - cobj = new ax::Touch(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Touch"); + ax::rhi::ShaderCache::destroyInstance(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Touch:Touch",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axrhi.ShaderCache:destroyInstance",argc, 0); return 0; - #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Touch_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ShaderCache_destroyInstance'.",&tolua_err); #endif - return 0; } - -static int lua_ax_base_Touch_finalize(lua_State* tolua_S) +static int lua_ax_base_ShaderCache_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Touch)"); + AXLOGV("luabindings: finalizing LUA object (ShaderCache)"); return 0; } -int lua_register_ax_base_Touch(lua_State* tolua_S) +int lua_register_ax_base_ShaderCache(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Touch"); - tolua_cclass(tolua_S,"Touch","ax.Touch","ax.Object",nullptr); + tolua_usertype(tolua_S,"axrhi.ShaderCache"); + tolua_cclass(tolua_S,"ShaderCache","axrhi.ShaderCache","",nullptr); - tolua_beginmodule(tolua_S,"Touch"); - tolua_function(tolua_S,"new",lua_ax_base_Touch_constructor); - tolua_function(tolua_S,"getLocation",lua_ax_base_Touch_getLocation); - tolua_function(tolua_S,"getPreviousLocation",lua_ax_base_Touch_getPreviousLocation); - tolua_function(tolua_S,"getStartLocation",lua_ax_base_Touch_getStartLocation); - tolua_function(tolua_S,"getDelta",lua_ax_base_Touch_getDelta); - tolua_function(tolua_S,"getLocationInView",lua_ax_base_Touch_getLocationInView); - tolua_function(tolua_S,"getPreviousLocationInView",lua_ax_base_Touch_getPreviousLocationInView); - tolua_function(tolua_S,"getStartLocationInView",lua_ax_base_Touch_getStartLocationInView); - tolua_function(tolua_S,"setTouchInfo",lua_ax_base_Touch_setTouchInfo); - tolua_function(tolua_S,"getId",lua_ax_base_Touch_getID); - tolua_function(tolua_S,"getCurrentForce",lua_ax_base_Touch_getCurrentForce); - tolua_function(tolua_S,"getMaxForce",lua_ax_base_Touch_getMaxForce); + tolua_beginmodule(tolua_S,"ShaderCache"); + tolua_function(tolua_S,"purge",lua_ax_base_ShaderCache_purge); + tolua_function(tolua_S,"acquireVertexShaderModule",lua_ax_base_ShaderCache_acquireVertexShaderModule); + tolua_function(tolua_S,"acquireFragmentShaderModule",lua_ax_base_ShaderCache_acquireFragmentShaderModule); + tolua_function(tolua_S,"removeUnusedShader",lua_ax_base_ShaderCache_removeUnusedShader); + tolua_function(tolua_S,"getInstance", lua_ax_base_ShaderCache_getInstance); + tolua_function(tolua_S,"destroyInstance", lua_ax_base_ShaderCache_destroyInstance); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Touch).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Touch"; - g_typeCast[typeName] = "ax.Touch"; + auto typeName = typeid(ax::rhi::ShaderCache).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.ShaderCache"; + g_typeCast[typeName] = "axrhi.ShaderCache"; return 1; } -int lua_ax_base_Event_getType(lua_State* tolua_S) +int lua_ax_base_Texture2D_updateWithImage(lua_State* tolua_S) { int argc = 0; - ax::Event* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_getType'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithImage'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_getType'", nullptr); - return 0; - } - int ret = (int)cobj->getType(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:getType",argc, 0); - return 0; + do{ + if (argc == 2) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_getType'.",&tolua_err); -#endif + if (!ok) { break; } + ax::rhi::PixelFormat arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithImage"); - return 0; -} -int lua_ax_base_Event_stopPropagation(lua_State* tolua_S) -{ - int argc = 0; - ax::Event* cobj = nullptr; - bool ok = true; + if (!ok) { break; } + bool ret = cobj->updateWithImage(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 3) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + if (!ok) { break; } + ax::rhi::PixelFormat arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithImage"); + if (!ok) { break; } + int arg2; + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithImage"); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; -#endif + if (!ok) { break; } + bool ret = cobj->updateWithImage(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); - cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); + if (!ok) { break; } + bool ret = cobj->updateWithImage(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 2) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:updateWithImage"); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_stopPropagation'", nullptr); - return 0; - } -#endif + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithImage"); - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_stopPropagation'", nullptr); - return 0; + if (!ok) { break; } + bool ret = cobj->updateWithImage(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->stopPropagation(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:stopPropagation",argc, 0); + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithImage",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_stopPropagation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithImage'.",&tolua_err); #endif return 0; } -int lua_ax_base_Event_isStopped(lua_State* tolua_S) +int lua_ax_base_Texture2D_updateWithMipmaps(lua_State* tolua_S) { int argc = 0; - ax::Event* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3423,203 +3567,133 @@ int lua_ax_base_Event_isStopped(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_isStopped'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 6) { + ax::_MipmapInfo* arg0; + int arg1; + ax::rhi::PixelFormat arg2; + ax::rhi::PixelFormat arg3; + int arg4; + int arg5; + + #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* + ok = false; + + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); + + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); + + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); + + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); + + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_isStopped'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); return 0; } - auto&& ret = cobj->isStopped(); + auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:isStopped",argc, 0); - return 0; + if (argc == 7) + { + ax::_MipmapInfo* arg0; + int arg1; + ax::rhi::PixelFormat arg2; + ax::rhi::PixelFormat arg3; + int arg4; + int arg5; + bool arg6; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_isStopped'.",&tolua_err); -#endif + #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* + ok = false; - return 0; -} -int lua_ax_base_Event_getCurrentTarget(lua_State* tolua_S) -{ - int argc = 0; - ax::Event* cobj = nullptr; - bool ok = true; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Event",0,&tolua_err)) goto tolua_lerror; -#endif + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); - cobj = (ax::Event*)tolua_tousertype(tolua_S,1,0); + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Event_getCurrentTarget'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:updateWithMipmaps"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_getCurrentTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); return 0; } - auto&& ret = cobj->getCurrentTarget(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:getCurrentTarget",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_getCurrentTarget'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_Event_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::Event* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 8) { - ax::Event::Type arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Event:Event"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Event_constructor'", nullptr); - return 0; - } - cobj = new ax::Event(arg0); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Event"); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Event:Event",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Event_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_base_Event_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Event)"); - return 0; -} - -int lua_register_ax_base_Event(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Event"); - tolua_cclass(tolua_S,"Event","ax.Event","ax.Object",nullptr); + ax::_MipmapInfo* arg0; + int arg1; + ax::rhi::PixelFormat arg2; + ax::rhi::PixelFormat arg3; + int arg4; + int arg5; + bool arg6; + int arg7; - tolua_beginmodule(tolua_S,"Event"); - tolua_function(tolua_S,"new",lua_ax_base_Event_constructor); - tolua_function(tolua_S,"getType",lua_ax_base_Event_getType); - tolua_function(tolua_S,"stopPropagation",lua_ax_base_Event_stopPropagation); - tolua_function(tolua_S,"isStopped",lua_ax_base_Event_isStopped); - tolua_function(tolua_S,"getCurrentTarget",lua_ax_base_Event_getCurrentTarget); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Event).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Event"; - g_typeCast[typeName] = "ax.Event"; - return 1; -} + #pragma warning NO CONVERSION TO NATIVE FOR _MipmapInfo* + ok = false; -int lua_ax_base_EventTouch_getEventCode(lua_State* tolua_S) -{ - int argc = 0; - ax::EventTouch* cobj = nullptr; - bool ok = true; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithMipmaps"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventTouch",0,&tolua_err)) goto tolua_lerror; -#endif + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithMipmaps"); - cobj = (ax::EventTouch*)tolua_tousertype(tolua_S,1,0); + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithMipmaps"); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventTouch_getEventCode'", nullptr); - return 0; - } -#endif + ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:updateWithMipmaps"); - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_int32(tolua_S, 9,(int *)&arg7, "ax.Texture2D:updateWithMipmaps"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_getEventCode'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithMipmaps'", nullptr); return 0; } - int ret = (int)cobj->getEventCode(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->updateWithMipmaps(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:getEventCode",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithMipmaps",argc, 6); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_getEventCode'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithMipmaps'.",&tolua_err); #endif return 0; } -int lua_ax_base_EventTouch_setEventCode(lua_State* tolua_S) +int lua_ax_base_Texture2D_updateWithSubData(lua_State* tolua_S) { int argc = 0; - ax::EventTouch* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3628,217 +3702,91 @@ int lua_ax_base_EventTouch_setEventCode(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.EventTouch",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::EventTouch*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_EventTouch_setEventCode'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 5) { - ax::EventTouch::EventCode arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.EventTouch:setEventCode"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_setEventCode'", nullptr); - return 0; - } - cobj->setEventCode(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:setEventCode",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_setEventCode'.",&tolua_err); -#endif + void* arg0; + int arg1; + int arg2; + int arg3; + int arg4; - return 0; -} -int lua_ax_base_EventTouch_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::EventTouch* cobj = nullptr; - bool ok = true; + #pragma warning NO CONVERSION TO NATIVE FOR void* + ok = false; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithSubData"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithSubData"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithSubData"); - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithSubData"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventTouch_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); return 0; } - cobj = new ax::EventTouch(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventTouch"); + auto&& ret = cobj->updateWithSubData(arg0, arg1, arg2, arg3, arg4); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventTouch:EventTouch",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventTouch_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_base_EventTouch_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (EventTouch)"); - return 0; -} - -int lua_register_ax_base_EventTouch(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.EventTouch"); - tolua_cclass(tolua_S,"EventTouch","ax.EventTouch","ax.Event",nullptr); - - tolua_beginmodule(tolua_S,"EventTouch"); - tolua_function(tolua_S,"new",lua_ax_base_EventTouch_constructor); - tolua_function(tolua_S,"getEventCode",lua_ax_base_EventTouch_getEventCode); - tolua_function(tolua_S,"setEventCode",lua_ax_base_EventTouch_setEventCode); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::EventTouch).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.EventTouch"; - g_typeCast[typeName] = "ax.EventTouch"; - return 1; -} - -int lua_ax_base_EventKeyboard_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::EventKeyboard* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - - - argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 6) { - ax::EventKeyboard::KeyCode arg0; - bool arg1; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.EventKeyboard:EventKeyboard"); - - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.EventKeyboard:EventKeyboard"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_EventKeyboard_constructor'", nullptr); - return 0; - } - cobj = new ax::EventKeyboard(arg0, arg1); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.EventKeyboard"); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.EventKeyboard:EventKeyboard",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_EventKeyboard_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_base_EventKeyboard_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (EventKeyboard)"); - return 0; -} - -int lua_register_ax_base_EventKeyboard(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.EventKeyboard"); - tolua_cclass(tolua_S,"EventKeyboard","ax.EventKeyboard","ax.Event",nullptr); - - tolua_beginmodule(tolua_S,"EventKeyboard"); - tolua_function(tolua_S,"new",lua_ax_base_EventKeyboard_constructor); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::EventKeyboard).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.EventKeyboard"; - g_typeCast[typeName] = "ax.EventKeyboard"; - return 1; -} - -int lua_ax_base_Component_init(lua_State* tolua_S) -{ - int argc = 0; - ax::Component* cobj = nullptr; - bool ok = true; + void* arg0; + int arg1; + int arg2; + int arg3; + int arg4; + int arg5; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + #pragma warning NO CONVERSION TO NATIVE FOR void* + ok = false; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:updateWithSubData"); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; -#endif + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Texture2D:updateWithSubData"); - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.Texture2D:updateWithSubData"); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_init'", nullptr); - return 0; - } -#endif + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:updateWithSubData"); - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:updateWithSubData"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateWithSubData'", nullptr); return 0; } - auto&& ret = cobj->init(); + auto&& ret = cobj->updateWithSubData(arg0, arg1, arg2, arg3, arg4, arg5); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:init",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateWithSubData",argc, 5); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateWithSubData'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_isEnabled(lua_State* tolua_S) +int lua_ax_base_Texture2D_drawAtPoint(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3847,45 +3795,51 @@ int lua_ax_base_Component_isEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_isEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_drawAtPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::Vec2 arg0; + double arg1; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Texture2D:drawAtPoint"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Texture2D:drawAtPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_isEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_drawAtPoint'", nullptr); return 0; } - auto&& ret = cobj->isEnabled(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->drawAtPoint(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:isEnabled",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:drawAtPoint",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_isEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_drawAtPoint'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_setEnabled(lua_State* tolua_S) +int lua_ax_base_Texture2D_drawInRect(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -3894,192 +3848,406 @@ int lua_ax_base_Component_setEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_drawInRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - bool arg0; + ax::Rect arg0; + double arg1; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Component:setEnabled"); + ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.Texture2D:drawInRect"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Texture2D:drawInRect"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_drawInRect'", nullptr); return 0; } - cobj->setEnabled(arg0); + cobj->drawInRect(arg0, arg1); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:drawInRect",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_drawInRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_getName(lua_State* tolua_S) +int lua_ax_base_Texture2D_initWithImage(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_getName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_initWithImage'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_getName'", nullptr); - return 0; + do{ + if (argc == 2) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:initWithImage"); + + if (!ok) { break; } + ax::rhi::PixelFormat arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Texture2D:initWithImage"); + + if (!ok) { break; } + bool ret = cobj->initWithImage(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - auto&& ret = cobj->getName(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:getName",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 1) { + ax::Image* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Image",&arg0, "ax.Texture2D:initWithImage"); + + if (!ok) { break; } + bool ret = cobj->initWithImage(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:initWithImage",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_getName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_initWithImage'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_setName(lua_State* tolua_S) +int lua_ax_base_Texture2D_initWithString(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_initWithString'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - std::string_view arg0; + do{ + if (argc == 2) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Component:setName"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setName'", nullptr); - return 0; + if (!ok) { break; } + ax::FontDefinition arg1; + ok &= luaval_to_fontdefinition(tolua_S, 3, &arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->setName(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setName",argc, 1); - return 0; + }while(0); + ok = true; + do{ + if (argc == 3) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setName'.",&tolua_err); -#endif + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); - return 0; -} -int lua_ax_base_Component_getOwner(lua_State* tolua_S) -{ - int argc = 0; - ax::Component* cobj = nullptr; - bool ok = true; + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 4) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2, arg3); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 5) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextHAlignment arg4; + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 6) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextHAlignment arg4; + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextVAlignment arg5; + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 7) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextHAlignment arg4; + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextVAlignment arg5; + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool arg6; + ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 8) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextHAlignment arg4; + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + ax::TextVAlignment arg5; + ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool arg6; + ok &= luaval_to_boolean(tolua_S, 8,&arg6, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + int arg7; + ok &= luaval_to_int32(tolua_S, 9,(int *)&arg7, "ax.Texture2D:initWithString"); + + if (!ok) { break; } + bool ret = cobj->initWithString(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:initWithString",argc, 3); + return 0; #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_initWithString'.",&tolua_err); #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + return 0; +} +int lua_ax_base_Texture2D_updateTextureDesc(lua_State* tolua_S) +{ + int argc = 0; + ax::Texture2D* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_getOwner'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_updateTextureDesc'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::rhi::TextureDesc arg0; + + #pragma warning NO CONVERSION TO NATIVE FOR TextureDesc + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_getOwner'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateTextureDesc'", nullptr); return 0; } - auto&& ret = cobj->getOwner(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + auto&& ret = cobj->updateTextureDesc(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:getOwner",argc, 0); + if (argc == 2) + { + ax::rhi::TextureDesc arg0; + bool arg1; + + #pragma warning NO CONVERSION TO NATIVE FOR TextureDesc + ok = false; + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Texture2D:updateTextureDesc"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_updateTextureDesc'", nullptr); + return 0; + } + auto&& ret = cobj->updateTextureDesc(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:updateTextureDesc",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_getOwner'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_updateTextureDesc'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_setOwner(lua_State* tolua_S) +int lua_ax_base_Texture2D_setRenderTarget(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4088,48 +4256,48 @@ int lua_ax_base_Component_setOwner(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setOwner'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setRenderTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Node* arg0; + bool arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Component:setOwner"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Texture2D:setRenderTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setOwner'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setRenderTarget'", nullptr); return 0; } - cobj->setOwner(arg0); + cobj->setRenderTarget(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setOwner",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setRenderTarget",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setOwner'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setRenderTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_update(lua_State* tolua_S) +int lua_ax_base_Texture2D_isRenderTarget(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4138,48 +4306,45 @@ int lua_ax_base_Component_update(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_update'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_isRenderTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Component:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_update'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_isRenderTarget'", nullptr); return 0; } - cobj->update(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isRenderTarget(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:update",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:isRenderTarget",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_update'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_isRenderTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_onAdd(lua_State* tolua_S) +int lua_ax_base_Texture2D_generateMipmap(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4188,45 +4353,45 @@ int lua_ax_base_Component_onAdd(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_onAdd'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_generateMipmap'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_onAdd'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_generateMipmap'", nullptr); return 0; } - cobj->onAdd(); + cobj->generateMipmap(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:onAdd",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:generateMipmap",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_onAdd'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_generateMipmap'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_onRemove(lua_State* tolua_S) +int lua_ax_base_Texture2D_setAntiAliasTexParameters(lua_State* tolua_S) { int argc = 0; - ax::Component* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4235,109 +4400,92 @@ int lua_ax_base_Component_onRemove(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_onRemove'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_onRemove'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'", nullptr); return 0; } - cobj->onRemove(); + cobj->setAntiAliasTexParameters(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:onRemove",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setAntiAliasTexParameters",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_onRemove'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setAntiAliasTexParameters'.",&tolua_err); #endif return 0; } -int lua_ax_base_Component_create(lua_State* tolua_S) +int lua_ax_base_Texture2D_setAliasTexParameters(lua_State* tolua_S) { int argc = 0; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setAliasTexParameters'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setAliasTexParameters'", nullptr); return 0; } - auto&& ret = ax::Component::create(); - object_to_luaval(tolua_S, "ax.Component",(ax::Component*)ret); + cobj->setAliasTexParameters(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Component:create",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setAliasTexParameters",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setAliasTexParameters'.",&tolua_err); #endif - return 0; -} -static int lua_ax_base_Component_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Component)"); - return 0; -} - -int lua_register_ax_base_Component(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Component"); - tolua_cclass(tolua_S,"Component","ax.Component","ax.Object",nullptr); - tolua_beginmodule(tolua_S,"Component"); - tolua_function(tolua_S,"init",lua_ax_base_Component_init); - tolua_function(tolua_S,"isEnabled",lua_ax_base_Component_isEnabled); - tolua_function(tolua_S,"setEnabled",lua_ax_base_Component_setEnabled); - tolua_function(tolua_S,"getName",lua_ax_base_Component_getName); - tolua_function(tolua_S,"setName",lua_ax_base_Component_setName); - tolua_function(tolua_S,"getOwner",lua_ax_base_Component_getOwner); - tolua_function(tolua_S,"setOwner",lua_ax_base_Component_setOwner); - tolua_function(tolua_S,"update",lua_ax_base_Component_update); - tolua_function(tolua_S,"onAdd",lua_ax_base_Component_onAdd); - tolua_function(tolua_S,"onRemove",lua_ax_base_Component_onRemove); - tolua_function(tolua_S,"create", lua_ax_base_Component_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Component).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Component"; - g_typeCast[typeName] = "ax.Component"; - return 1; + return 0; } - -int lua_ax_base_Node_getDescription(lua_State* tolua_S) +int lua_ax_base_Texture2D_getStringForFormat(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4346,95 +4494,96 @@ int lua_ax_base_Node_getDescription(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDescription'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getStringForFormat'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDescription'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getStringForFormat'", nullptr); return 0; } - auto&& ret = cobj->getDescription(); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + auto&& ret = cobj->getStringForFormat(); + tolua_pushstring(tolua_S,(const char*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDescription",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getStringForFormat",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDescription'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getStringForFormat'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setLocalZOrder(lua_State* tolua_S) +int lua_ax_base_Texture2D_getBitsPerPixelForFormat(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setLocalZOrder'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getBitsPerPixelForFormat'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; + do{ + if (argc == 1) { + ax::rhi::PixelFormat arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Texture2D:getBitsPerPixelForFormat"); - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:setLocalZOrder"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setLocalZOrder'", nullptr); - return 0; + if (!ok) { break; } + unsigned int ret = cobj->getBitsPerPixelForFormat(arg0); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; } - cobj->setLocalZOrder(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setLocalZOrder",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + unsigned int ret = cobj->getBitsPerPixelForFormat(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getBitsPerPixelForFormat",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setLocalZOrder'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getBitsPerPixelForFormat'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_updateOrderOfArrival(lua_State* tolua_S) +int lua_ax_base_Texture2D_getContentSizeInPixels(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4443,45 +4592,45 @@ int lua_ax_base_Node_updateOrderOfArrival(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateOrderOfArrival'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getContentSizeInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateOrderOfArrival'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getContentSizeInPixels'", nullptr); return 0; } - cobj->updateOrderOfArrival(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getContentSizeInPixels(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateOrderOfArrival",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getContentSizeInPixels",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateOrderOfArrival'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getContentSizeInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getLocalZOrder(lua_State* tolua_S) +int lua_ax_base_Texture2D_hasPremultipliedAlpha(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4490,45 +4639,45 @@ int lua_ax_base_Node_getLocalZOrder(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getLocalZOrder'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getLocalZOrder'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'", nullptr); return 0; } - auto&& ret = cobj->getLocalZOrder(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->hasPremultipliedAlpha(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getLocalZOrder",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:hasPremultipliedAlpha",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getLocalZOrder'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_hasPremultipliedAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setGlobalZOrder(lua_State* tolua_S) +int lua_ax_base_Texture2D_setPremultipliedAlpha(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4537,48 +4686,48 @@ int lua_ax_base_Node_setGlobalZOrder(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setGlobalZOrder'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + bool arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setGlobalZOrder"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Texture2D:setPremultipliedAlpha"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setGlobalZOrder'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'", nullptr); return 0; } - cobj->setGlobalZOrder(arg0); + cobj->setPremultipliedAlpha(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setGlobalZOrder",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setPremultipliedAlpha",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setGlobalZOrder'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setPremultipliedAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getGlobalZOrder(lua_State* tolua_S) +int lua_ax_base_Texture2D_hasMipmaps(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4587,45 +4736,45 @@ int lua_ax_base_Node_getGlobalZOrder(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getGlobalZOrder'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_hasMipmaps'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getGlobalZOrder'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_hasMipmaps'", nullptr); return 0; } - auto&& ret = cobj->getGlobalZOrder(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->hasMipmaps(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getGlobalZOrder",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:hasMipmaps",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getGlobalZOrder'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_hasMipmaps'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setScaleX(lua_State* tolua_S) +int lua_ax_base_Texture2D_getPixelFormat(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4634,48 +4783,45 @@ int lua_ax_base_Node_setScaleX(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelFormat'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelFormat'", nullptr); return 0; } - cobj->setScaleX(arg0); - lua_settop(tolua_S, 1); + int ret = (int)cobj->getPixelFormat(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleX",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelFormat",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelFormat'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScaleX(lua_State* tolua_S) +int lua_ax_base_Texture2D_getSamplerFlags(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4684,45 +4830,45 @@ int lua_ax_base_Node_getScaleX(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getSamplerFlags'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getSamplerFlags'", nullptr); return 0; } - auto&& ret = cobj->getScaleX(); + auto&& ret = cobj->getSamplerFlags(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleX",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getSamplerFlags",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getSamplerFlags'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setScaleY(lua_State* tolua_S) +int lua_ax_base_Texture2D_getPixelsWide(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4731,48 +4877,45 @@ int lua_ax_base_Node_setScaleY(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelsWide'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleY"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelsWide'", nullptr); return 0; } - cobj->setScaleY(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getPixelsWide(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleY",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelsWide",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelsWide'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScaleY(lua_State* tolua_S) +int lua_ax_base_Texture2D_getPixelsHigh(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4781,45 +4924,45 @@ int lua_ax_base_Node_getScaleY(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPixelsHigh'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPixelsHigh'", nullptr); return 0; } - auto&& ret = cobj->getScaleY(); + auto&& ret = cobj->getPixelsHigh(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleY",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPixelsHigh",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPixelsHigh'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setScaleZ(lua_State* tolua_S) +int lua_ax_base_Texture2D_getBackendTexture(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4828,48 +4971,45 @@ int lua_ax_base_Node_setScaleZ(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleZ'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getBackendTexture'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleZ"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleZ'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getBackendTexture'", nullptr); return 0; } - cobj->setScaleZ(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getBackendTexture(); + object_to_luaval(tolua_S, "axrhi.Texture",(ax::rhi::Texture*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleZ",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getBackendTexture",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleZ'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getBackendTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScaleZ(lua_State* tolua_S) +int lua_ax_base_Texture2D_getMaxS(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4878,104 +5018,95 @@ int lua_ax_base_Node_getScaleZ(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleZ'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getMaxS'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleZ'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getMaxS'", nullptr); return 0; } - auto&& ret = cobj->getScaleZ(); + auto&& ret = cobj->getMaxS(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleZ",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getMaxS",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleZ'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getMaxS'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setScale(lua_State* tolua_S) +int lua_ax_base_Texture2D_setMaxS(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScale'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setMaxS'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScale"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Node:setScale"); - if (!ok) { break; } - cobj->setScale(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScale"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + double arg0; - if (!ok) { break; } - cobj->setScale(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Texture2D:setMaxS"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setMaxS'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScale",argc, 1); + cobj->setMaxS(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setMaxS",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScale'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setMaxS'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScale(lua_State* tolua_S) +int lua_ax_base_Texture2D_getMaxT(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -4984,104 +5115,95 @@ int lua_ax_base_Node_getScale(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScale'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getMaxT'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScale'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getMaxT'", nullptr); return 0; } - auto&& ret = cobj->getScale(); + auto&& ret = cobj->getMaxT(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScale",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getMaxT",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScale'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getMaxT'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPosition(lua_State* tolua_S) +int lua_ax_base_Texture2D_setMaxT(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_setMaxT'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPosition"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Node:setPosition"); - if (!ok) { break; } - cobj->setPosition(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setPosition"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + double arg0; - if (!ok) { break; } - cobj->setPosition(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Texture2D:setMaxT"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_setMaxT'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPosition",argc, 1); + cobj->setMaxT(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:setMaxT",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_setMaxT'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPositionNormalized(lua_State* tolua_S) +int lua_ax_base_Texture2D_getContentSize(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5090,48 +5212,45 @@ int lua_ax_base_Node_setPositionNormalized(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionNormalized'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getContentSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setPositionNormalized"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionNormalized'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getContentSize'", nullptr); return 0; } - cobj->setPositionNormalized(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getContentSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionNormalized",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getContentSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionNormalized'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getContentSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setNormalizedPosition(lua_State* tolua_S) +int lua_ax_base_Texture2D_getPath(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5140,48 +5259,45 @@ int lua_ax_base_Node_setNormalizedPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Texture2D",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Texture2D*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setNormalizedPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Texture2D_getPath'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setNormalizedPosition"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setNormalizedPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_getPath'", nullptr); return 0; } - cobj->setNormalizedPosition(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getPath(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setNormalizedPosition",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:getPath",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setNormalizedPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_getPath'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPositionNormalized(lua_State* tolua_S) +int lua_ax_base_Texture2D_constructor(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Texture2D* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5189,46 +5305,86 @@ int lua_ax_base_Node_getPositionNormalized(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionNormalized'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionNormalized'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Texture2D_constructor'", nullptr); return 0; } - auto&& ret = cobj->getPositionNormalized(); - vec2_to_luaval(tolua_S, ret); + cobj = new ax::Texture2D(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Texture2D"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionNormalized",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Texture2D:Texture2D",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionNormalized'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Texture2D_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNormalizedPosition(lua_State* tolua_S) + +static int lua_ax_base_Texture2D_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Texture2D)"); + return 0; +} + +int lua_register_ax_base_Texture2D(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Texture2D"); + tolua_cclass(tolua_S,"Texture2D","ax.Texture2D","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Texture2D"); + tolua_function(tolua_S,"new",lua_ax_base_Texture2D_constructor); + tolua_function(tolua_S,"updateWithImage",lua_ax_base_Texture2D_updateWithImage); + tolua_function(tolua_S,"updateWithMipmaps",lua_ax_base_Texture2D_updateWithMipmaps); + tolua_function(tolua_S,"updateWithSubData",lua_ax_base_Texture2D_updateWithSubData); + tolua_function(tolua_S,"drawAtPoint",lua_ax_base_Texture2D_drawAtPoint); + tolua_function(tolua_S,"drawInRect",lua_ax_base_Texture2D_drawInRect); + tolua_function(tolua_S,"initWithImage",lua_ax_base_Texture2D_initWithImage); + tolua_function(tolua_S,"initWithString",lua_ax_base_Texture2D_initWithString); + tolua_function(tolua_S,"updateTextureDesc",lua_ax_base_Texture2D_updateTextureDesc); + tolua_function(tolua_S,"setRenderTarget",lua_ax_base_Texture2D_setRenderTarget); + tolua_function(tolua_S,"isRenderTarget",lua_ax_base_Texture2D_isRenderTarget); + tolua_function(tolua_S,"generateMipmap",lua_ax_base_Texture2D_generateMipmap); + tolua_function(tolua_S,"setAntiAliasTexParameters",lua_ax_base_Texture2D_setAntiAliasTexParameters); + tolua_function(tolua_S,"setAliasTexParameters",lua_ax_base_Texture2D_setAliasTexParameters); + tolua_function(tolua_S,"getStringForFormat",lua_ax_base_Texture2D_getStringForFormat); + tolua_function(tolua_S,"getBitsPerPixelForFormat",lua_ax_base_Texture2D_getBitsPerPixelForFormat); + tolua_function(tolua_S,"getContentSizeInPixels",lua_ax_base_Texture2D_getContentSizeInPixels); + tolua_function(tolua_S,"hasPremultipliedAlpha",lua_ax_base_Texture2D_hasPremultipliedAlpha); + tolua_function(tolua_S,"setPremultipliedAlpha",lua_ax_base_Texture2D_setPremultipliedAlpha); + tolua_function(tolua_S,"hasMipmaps",lua_ax_base_Texture2D_hasMipmaps); + tolua_function(tolua_S,"getPixelFormat",lua_ax_base_Texture2D_getPixelFormat); + tolua_function(tolua_S,"getSamplerFlags",lua_ax_base_Texture2D_getSamplerFlags); + tolua_function(tolua_S,"getPixelsWide",lua_ax_base_Texture2D_getPixelsWide); + tolua_function(tolua_S,"getPixelsHigh",lua_ax_base_Texture2D_getPixelsHigh); + tolua_function(tolua_S,"getBackendTexture",lua_ax_base_Texture2D_getBackendTexture); + tolua_function(tolua_S,"getMaxS",lua_ax_base_Texture2D_getMaxS); + tolua_function(tolua_S,"setMaxS",lua_ax_base_Texture2D_setMaxS); + tolua_function(tolua_S,"getMaxT",lua_ax_base_Texture2D_getMaxT); + tolua_function(tolua_S,"setMaxT",lua_ax_base_Texture2D_setMaxT); + tolua_function(tolua_S,"getContentSize",lua_ax_base_Texture2D_getContentSize); + tolua_function(tolua_S,"getPath",lua_ax_base_Texture2D_getPath); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Texture2D).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Texture2D"; + g_typeCast[typeName] = "ax.Texture2D"; + return 1; +} + +int lua_ax_base_Component_init(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5237,45 +5393,45 @@ int lua_ax_base_Node_getNormalizedPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNormalizedPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_init'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNormalizedPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_init'", nullptr); return 0; } - auto&& ret = cobj->getNormalizedPosition(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->init(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNormalizedPosition",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:init",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNormalizedPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_init'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPositionX(lua_State* tolua_S) +int lua_ax_base_Component_isEnabled(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5284,48 +5440,45 @@ int lua_ax_base_Node_setPositionX(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_isEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_isEnabled'", nullptr); return 0; } - cobj->setPositionX(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionX",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:isEnabled",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_isEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPositionX(lua_State* tolua_S) +int lua_ax_base_Component_setEnabled(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5334,45 +5487,48 @@ int lua_ax_base_Node_getPositionX(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Component:setEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setEnabled'", nullptr); return 0; } - auto&& ret = cobj->getPositionX(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setEnabled(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionX",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setEnabled",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPositionY(lua_State* tolua_S) +int lua_ax_base_Component_getName(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5381,48 +5537,45 @@ int lua_ax_base_Node_setPositionY(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_getName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionY"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_getName'", nullptr); return 0; } - cobj->setPositionY(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getName(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionY",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:getName",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_getName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPositionY(lua_State* tolua_S) +int lua_ax_base_Component_setName(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5431,45 +5584,48 @@ int lua_ax_base_Node_getPositionY(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Component:setName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setName'", nullptr); return 0; } - auto&& ret = cobj->getPositionY(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setName(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionY",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setName",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPosition3D(lua_State* tolua_S) +int lua_ax_base_Component_getOwner(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5478,48 +5634,45 @@ int lua_ax_base_Node_setPosition3D(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPosition3D'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_getOwner'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec3 arg0; - - ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.Node:setPosition3D"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPosition3D'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_getOwner'", nullptr); return 0; } - cobj->setPosition3D(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getOwner(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPosition3D",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:getOwner",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPosition3D'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_getOwner'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPosition3D(lua_State* tolua_S) +int lua_ax_base_Component_setOwner(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5528,45 +5681,48 @@ int lua_ax_base_Node_getPosition3D(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPosition3D'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_setOwner'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Component:setOwner"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPosition3D'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_setOwner'", nullptr); return 0; } - auto&& ret = cobj->getPosition3D(); - vec3_to_luaval(tolua_S, ret); + cobj->setOwner(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPosition3D",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:setOwner",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPosition3D'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_setOwner'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPositionZ(lua_State* tolua_S) +int lua_ax_base_Component_update(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5575,48 +5731,48 @@ int lua_ax_base_Node_setPositionZ(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionZ'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_update'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionZ"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Component:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionZ'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_update'", nullptr); return 0; } - cobj->setPositionZ(arg0); + cobj->update(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionZ",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:update",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionZ'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_update'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPositionZ(lua_State* tolua_S) +int lua_ax_base_Component_onAdd(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5625,45 +5781,45 @@ int lua_ax_base_Node_getPositionZ(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionZ'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_onAdd'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionZ'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_onAdd'", nullptr); return 0; } - auto&& ret = cobj->getPositionZ(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->onAdd(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionZ",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:onAdd",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionZ'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_onAdd'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setSkewX(lua_State* tolua_S) +int lua_ax_base_Component_onRemove(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; + ax::Component* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -5672,92 +5828,106 @@ int lua_ax_base_Node_setSkewX(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Component*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setSkewX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Component_onRemove'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setSkewX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setSkewX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_onRemove'", nullptr); return 0; } - cobj->setSkewX(arg0); + cobj->onRemove(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setSkewX",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Component:onRemove",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setSkewX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_onRemove'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getSkewX(lua_State* tolua_S) +int lua_ax_base_Component_create(lua_State* tolua_S) { int argc = 0; - ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Component",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getSkewX'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getSkewX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Component_create'", nullptr); return 0; } - auto&& ret = cobj->getSkewX(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::Component::create(); + object_to_luaval(tolua_S, "ax.Component",(ax::Component*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getSkewX",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Component:create",argc, 0); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getSkewX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Component_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Node_setSkewY(lua_State* tolua_S) +static int lua_ax_base_Component_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Component)"); + return 0; +} + +int lua_register_ax_base_Component(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Component"); + tolua_cclass(tolua_S,"Component","ax.Component","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Component"); + tolua_function(tolua_S,"init",lua_ax_base_Component_init); + tolua_function(tolua_S,"isEnabled",lua_ax_base_Component_isEnabled); + tolua_function(tolua_S,"setEnabled",lua_ax_base_Component_setEnabled); + tolua_function(tolua_S,"getName",lua_ax_base_Component_getName); + tolua_function(tolua_S,"setName",lua_ax_base_Component_setName); + tolua_function(tolua_S,"getOwner",lua_ax_base_Component_getOwner); + tolua_function(tolua_S,"setOwner",lua_ax_base_Component_setOwner); + tolua_function(tolua_S,"update",lua_ax_base_Component_update); + tolua_function(tolua_S,"onAdd",lua_ax_base_Component_onAdd); + tolua_function(tolua_S,"onRemove",lua_ax_base_Component_onRemove); + tolua_function(tolua_S,"create", lua_ax_base_Component_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Component).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Component"; + g_typeCast[typeName] = "ax.Component"; + return 1; +} + +int lua_ax_base_Node_getDescription(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -5777,37 +5947,34 @@ int lua_ax_base_Node_setSkewY(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setSkewY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDescription'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setSkewY"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setSkewY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDescription'", nullptr); return 0; } - cobj->setSkewY(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getDescription(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setSkewY",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDescription",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setSkewY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDescription'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getSkewY(lua_State* tolua_S) +int lua_ax_base_Node_setLocalZOrder(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -5827,34 +5994,37 @@ int lua_ax_base_Node_getSkewY(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getSkewY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setLocalZOrder'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:setLocalZOrder"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getSkewY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setLocalZOrder'", nullptr); return 0; } - auto&& ret = cobj->getSkewY(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setLocalZOrder(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getSkewY",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setLocalZOrder",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getSkewY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setLocalZOrder'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getAnchorPoint(lua_State* tolua_S) +int lua_ax_base_Node_updateOrderOfArrival(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -5874,34 +6044,34 @@ int lua_ax_base_Node_getAnchorPoint(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateOrderOfArrival'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateOrderOfArrival'", nullptr); return 0; } - auto&& ret = cobj->getAnchorPoint(); - vec2_to_luaval(tolua_S, ret); + cobj->updateOrderOfArrival(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getAnchorPoint",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateOrderOfArrival",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAnchorPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateOrderOfArrival'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getAnchorPointInPoints(lua_State* tolua_S) +int lua_ax_base_Node_getLocalZOrder(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -5921,34 +6091,34 @@ int lua_ax_base_Node_getAnchorPointInPoints(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getAnchorPointInPoints'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getLocalZOrder'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAnchorPointInPoints'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getLocalZOrder'", nullptr); return 0; } - auto&& ret = cobj->getAnchorPointInPoints(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getLocalZOrder(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getAnchorPointInPoints",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getLocalZOrder",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAnchorPointInPoints'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getLocalZOrder'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getContentSize(lua_State* tolua_S) +int lua_ax_base_Node_setGlobalZOrder(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -5968,34 +6138,37 @@ int lua_ax_base_Node_getContentSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getContentSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setGlobalZOrder'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setGlobalZOrder"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getContentSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setGlobalZOrder'", nullptr); return 0; } - auto&& ret = cobj->getContentSize(); - vec2_to_luaval(tolua_S, ret); + cobj->setGlobalZOrder(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getContentSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setGlobalZOrder",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getContentSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setGlobalZOrder'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_hitTest(lua_State* tolua_S) +int lua_ax_base_Node_getGlobalZOrder(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6015,37 +6188,34 @@ int lua_ax_base_Node_hitTest(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_hitTest'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getGlobalZOrder'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:hitTest"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_hitTest'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getGlobalZOrder'", nullptr); return 0; } - auto&& ret = cobj->hitTest(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getGlobalZOrder(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:hitTest",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getGlobalZOrder",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_hitTest'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getGlobalZOrder'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setVisible(lua_State* tolua_S) +int lua_ax_base_Node_setScaleX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6065,37 +6235,37 @@ int lua_ax_base_Node_setVisible(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setVisible'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - bool arg0; + double arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setVisible"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setVisible'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleX'", nullptr); return 0; } - cobj->setVisible(arg0); + cobj->setScaleX(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setVisible",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleX",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setVisible'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isVisible(lua_State* tolua_S) +int lua_ax_base_Node_getScaleX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6115,34 +6285,34 @@ int lua_ax_base_Node_isVisible(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isVisible'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isVisible'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleX'", nullptr); return 0; } - auto&& ret = cobj->isVisible(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getScaleX(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isVisible",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleX",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isVisible'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setRotation(lua_State* tolua_S) +int lua_ax_base_Node_setScaleY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6162,37 +6332,37 @@ int lua_ax_base_Node_setRotation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotation"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleY"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleY'", nullptr); return 0; } - cobj->setRotation(arg0); + cobj->setScaleY(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotation",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleY",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getRotation(lua_State* tolua_S) +int lua_ax_base_Node_getScaleY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6212,34 +6382,34 @@ int lua_ax_base_Node_getRotation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleY'", nullptr); return 0; } - auto&& ret = cobj->getRotation(); + auto&& ret = cobj->getScaleY(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleY",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setRotation3D(lua_State* tolua_S) +int lua_ax_base_Node_setScaleZ(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6259,37 +6429,37 @@ int lua_ax_base_Node_setRotation3D(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotation3D'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScaleZ'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec3 arg0; + double arg0; - ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.Node:setRotation3D"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScaleZ"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotation3D'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScaleZ'", nullptr); return 0; } - cobj->setRotation3D(arg0); + cobj->setScaleZ(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotation3D",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScaleZ",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotation3D'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScaleZ'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getRotation3D(lua_State* tolua_S) +int lua_ax_base_Node_getScaleZ(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6309,84 +6479,93 @@ int lua_ax_base_Node_getRotation3D(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotation3D'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScaleZ'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotation3D'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScaleZ'", nullptr); return 0; } - auto&& ret = cobj->getRotation3D(); - vec3_to_luaval(tolua_S, ret); + auto&& ret = cobj->getScaleZ(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotation3D",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScaleZ",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotation3D'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScaleZ'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setRotationSkewX(lua_State* tolua_S) +int lua_ax_base_Node_setScale(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotationSkewX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScale'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - double arg0; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScale"); - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotationSkewX"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotationSkewX'", nullptr); - return 0; + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Node:setScale"); + + if (!ok) { break; } + cobj->setScale(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; } - cobj->setRotationSkewX(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotationSkewX",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 1) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setScale"); + + if (!ok) { break; } + cobj->setScale(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScale",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotationSkewX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScale'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getRotationSkewX(lua_State* tolua_S) +int lua_ax_base_Node_getScale(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6406,84 +6585,93 @@ int lua_ax_base_Node_getRotationSkewX(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotationSkewX'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScale'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotationSkewX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScale'", nullptr); return 0; } - auto&& ret = cobj->getRotationSkewX(); + auto&& ret = cobj->getScale(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotationSkewX",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScale",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotationSkewX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScale'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setRotationSkewY(lua_State* tolua_S) +int lua_ax_base_Node_setPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotationSkewY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPosition'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - double arg0; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPosition"); - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotationSkewY"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotationSkewY'", nullptr); - return 0; + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Node:setPosition"); + + if (!ok) { break; } + cobj->setPosition(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; } - cobj->setRotationSkewY(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotationSkewY",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 1) { + ax::Vec2 arg0; + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setPosition"); + + if (!ok) { break; } + cobj->setPosition(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPosition",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotationSkewY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getRotationSkewY(lua_State* tolua_S) +int lua_ax_base_Node_setPositionNormalized(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6503,34 +6691,37 @@ int lua_ax_base_Node_getRotationSkewY(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotationSkewY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionNormalized'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setPositionNormalized"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotationSkewY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionNormalized'", nullptr); return 0; } - auto&& ret = cobj->getRotationSkewY(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setPositionNormalized(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotationSkewY",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionNormalized",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotationSkewY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionNormalized'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setIgnoreAnchorPointForPosition(lua_State* tolua_S) +int lua_ax_base_Node_setNormalizedPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6550,37 +6741,37 @@ int lua_ax_base_Node_setIgnoreAnchorPointForPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setNormalizedPosition'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - bool arg0; + ax::Vec2 arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setIgnoreAnchorPointForPosition"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setNormalizedPosition"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setNormalizedPosition'", nullptr); return 0; } - cobj->setIgnoreAnchorPointForPosition(arg0); + cobj->setNormalizedPosition(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setIgnoreAnchorPointForPosition",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setNormalizedPosition",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setNormalizedPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isIgnoreAnchorPointForPosition(lua_State* tolua_S) +int lua_ax_base_Node_getPositionNormalized(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6600,133 +6791,81 @@ int lua_ax_base_Node_isIgnoreAnchorPointForPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionNormalized'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionNormalized'", nullptr); return 0; } - auto&& ret = cobj->isIgnoreAnchorPointForPosition(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getPositionNormalized(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isIgnoreAnchorPointForPosition",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionNormalized",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionNormalized'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_addChild(lua_State* tolua_S) +int lua_ax_base_Node_getNormalizedPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_addChild'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNormalizedPosition'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); - - if (!ok) { break; } - int arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); - - if (!ok) { break; } - cobj->addChild(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); - - if (!ok) { break; } - cobj->addChild(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); - - if (!ok) { break; } - int arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); - - if (!ok) { break; } - int arg2; - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Node:addChild"); - - if (!ok) { break; } - cobj->addChild(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); - - if (!ok) { break; } - int arg1; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); - - if (!ok) { break; } - std::string_view arg2; - ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "ax.Node:addChild"); - if (!ok) { break; } - cobj->addChild(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNormalizedPosition'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:addChild",argc, 3); + auto&& ret = cobj->getNormalizedPosition(); + vec2_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNormalizedPosition",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_addChild'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNormalizedPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getChildByTag(lua_State* tolua_S) +int lua_ax_base_Node_setPositionX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6746,37 +6885,37 @@ int lua_ax_base_Node_getChildByTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - int arg0; + double arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getChildByTag"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildByTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionX'", nullptr); return 0; } - auto&& ret = cobj->getChildByTag(arg0); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + cobj->setPositionX(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildByTag",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionX",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getChildByName(lua_State* tolua_S) +int lua_ax_base_Node_getPositionX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6796,84 +6935,84 @@ int lua_ax_base_Node_getChildByName(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildByName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:getChildByName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildByName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionX'", nullptr); return 0; } - auto&& ret = cobj->getChildByName(arg0); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + auto&& ret = cobj->getPositionX(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildByName",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionX",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildByName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getChildren(lua_State* tolua_S) +int lua_ax_base_Node_setPositionY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildren'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionY'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const ax::Vector& ret = cobj->getChildren(); - ccvector_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::Vector& ret = cobj->getChildren(); - ccvector_to_luaval(tolua_S, ret); - return 1; + if (argc == 1) + { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionY"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionY'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildren",argc, 0); + cobj->setPositionY(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionY",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildren'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getChildrenCount(lua_State* tolua_S) +int lua_ax_base_Node_getPositionY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6893,34 +7032,34 @@ int lua_ax_base_Node_getChildrenCount(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildrenCount'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildrenCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionY'", nullptr); return 0; } - auto&& ret = cobj->getChildrenCount(); + auto&& ret = cobj->getPositionY(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildrenCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionY",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildrenCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setParent(lua_State* tolua_S) +int lua_ax_base_Node_setPosition3D(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -6940,135 +7079,134 @@ int lua_ax_base_Node_setParent(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setParent'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPosition3D'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Node* arg0; + ax::Vec3 arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:setParent"); + ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.Node:setPosition3D"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setParent'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPosition3D'", nullptr); return 0; } - cobj->setParent(arg0); + cobj->setPosition3D(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setParent",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPosition3D",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setParent'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPosition3D'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getParent(lua_State* tolua_S) +int lua_ax_base_Node_getPosition3D(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParent'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPosition3D'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const ax::Node* ret = cobj->getParent(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::Node* ret = cobj->getParent(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); - return 1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPosition3D'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParent",argc, 0); + auto&& ret = cobj->getPosition3D(); + vec3_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPosition3D",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParent'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPosition3D'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeFromParentAndCleanup(lua_State* tolua_S) +int lua_ax_base_Node_setPositionZ(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeFromParentAndCleanup'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPositionZ'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - bool arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:removeFromParentAndCleanup"); + if (argc == 1) + { + double arg0; - if (!ok) { break; } - cobj->removeFromParentAndCleanup(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - cobj->removeFromParent(); - lua_settop(tolua_S, 1); - return 1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setPositionZ"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPositionZ'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeFromParent",argc, 0); + cobj->setPositionZ(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPositionZ",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeFromParentAndCleanup'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPositionZ'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeChild(lua_State* tolua_S) +int lua_ax_base_Node_getPositionZ(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7088,54 +7226,34 @@ int lua_ax_base_Node_removeChild(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChild'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPositionZ'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:removeChild"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChild'", nullptr); - return 0; - } - cobj->removeChild(arg0); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 2) + if (argc == 0) { - ax::Node* arg0; - bool arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:removeChild"); - - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChild'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPositionZ'", nullptr); return 0; } - cobj->removeChild(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getPositionZ(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChild",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPositionZ",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChild'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPositionZ'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeChildByTag(lua_State* tolua_S) +int lua_ax_base_Node_setSkewX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7155,54 +7273,37 @@ int lua_ax_base_Node_removeChildByTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChildByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setSkewX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:removeChildByTag"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByTag'", nullptr); - return 0; - } - cobj->removeChildByTag(arg0); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 2) + if (argc == 1) { - int arg0; - bool arg1; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:removeChildByTag"); + double arg0; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChildByTag"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setSkewX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setSkewX'", nullptr); return 0; } - cobj->removeChildByTag(arg0, arg1); + cobj->setSkewX(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChildByTag",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setSkewX",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChildByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setSkewX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeChildByName(lua_State* tolua_S) +int lua_ax_base_Node_getSkewX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7222,105 +7323,84 @@ int lua_ax_base_Node_removeChildByName(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChildByName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getSkewX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeChildByName"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByName'", nullptr); - return 0; - } - cobj->removeChildByName(arg0); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 2) + if (argc == 0) { - std::string_view arg0; - bool arg1; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeChildByName"); - - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChildByName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getSkewX'", nullptr); return 0; } - cobj->removeChildByName(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getSkewX(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChildByName",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getSkewX",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChildByName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getSkewX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeAllChildrenWithCleanup(lua_State* tolua_S) +int lua_ax_base_Node_setSkewY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeAllChildrenWithCleanup'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setSkewY'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - bool arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:removeAllChildrenWithCleanup"); + if (argc == 1) + { + double arg0; - if (!ok) { break; } - cobj->removeAllChildrenWithCleanup(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - cobj->removeAllChildren(); - lua_settop(tolua_S, 1); - return 1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setSkewY"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setSkewY'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeAllChildren",argc, 0); + cobj->setSkewY(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setSkewY",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeAllChildrenWithCleanup'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setSkewY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_reorderChild(lua_State* tolua_S) +int lua_ax_base_Node_getSkewY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7340,40 +7420,34 @@ int lua_ax_base_Node_reorderChild(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_reorderChild'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getSkewY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Node* arg0; - int arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:reorderChild"); - - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:reorderChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_reorderChild'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getSkewY'", nullptr); return 0; } - cobj->reorderChild(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getSkewY(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:reorderChild",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getSkewY",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_reorderChild'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getSkewY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_sortAllChildren(lua_State* tolua_S) +int lua_ax_base_Node_getAnchorPoint(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7393,34 +7467,34 @@ int lua_ax_base_Node_sortAllChildren(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_sortAllChildren'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getAnchorPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_sortAllChildren'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAnchorPoint'", nullptr); return 0; } - cobj->sortAllChildren(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getAnchorPoint(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:sortAllChildren",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getAnchorPoint",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_sortAllChildren'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAnchorPoint'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getTag(lua_State* tolua_S) +int lua_ax_base_Node_getAnchorPointInPoints(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7440,34 +7514,34 @@ int lua_ax_base_Node_getTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getAnchorPointInPoints'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAnchorPointInPoints'", nullptr); return 0; } - auto&& ret = cobj->getTag(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getAnchorPointInPoints(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getTag",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getAnchorPointInPoints",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAnchorPointInPoints'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setTag(lua_State* tolua_S) +int lua_ax_base_Node_getContentSize(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7487,37 +7561,34 @@ int lua_ax_base_Node_setTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getContentSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:setTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getContentSize'", nullptr); return 0; } - cobj->setTag(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getContentSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setTag",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getContentSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getContentSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getName(lua_State* tolua_S) +int lua_ax_base_Node_hitTest(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7537,34 +7608,37 @@ int lua_ax_base_Node_getName(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_hitTest'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:hitTest"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_hitTest'", nullptr); return 0; } - auto&& ret = cobj->getName(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); + auto&& ret = cobj->hitTest(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getName",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:hitTest",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_hitTest'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setName(lua_State* tolua_S) +int lua_ax_base_Node_setVisible(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7584,37 +7658,37 @@ int lua_ax_base_Node_setName(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setVisible'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - std::string_view arg0; + bool arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:setName"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setVisible"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setVisible'", nullptr); return 0; } - cobj->setName(arg0); + cobj->setVisible(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setName",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setVisible",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setVisible'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setUserObject(lua_State* tolua_S) +int lua_ax_base_Node_isVisible(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7634,37 +7708,34 @@ int lua_ax_base_Node_setUserObject(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setUserObject'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isVisible'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Object* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Object",&arg0, "ax.Node:setUserObject"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setUserObject'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isVisible'", nullptr); return 0; } - cobj->setUserObject(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isVisible(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setUserObject",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isVisible",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setUserObject'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isVisible'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isRunning(lua_State* tolua_S) +int lua_ax_base_Node_setRotation(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7684,34 +7755,37 @@ int lua_ax_base_Node_isRunning(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isRunning'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isRunning'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotation'", nullptr); return 0; } - auto&& ret = cobj->isRunning(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setRotation(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isRunning",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotation",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isRunning'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotation'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_cleanup(lua_State* tolua_S) +int lua_ax_base_Node_getRotation(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7731,152 +7805,131 @@ int lua_ax_base_Node_cleanup(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_cleanup'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_cleanup'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotation'", nullptr); return 0; } - cobj->cleanup(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getRotation(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:cleanup",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_cleanup'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotation'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_draw(lua_State* tolua_S) +int lua_ax_base_Node_setRotation3D(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_draw'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotation3D'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - cobj->draw(); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - ax::Renderer* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Node:draw"); - - if (!ok) { break; } - ax::Mat4 arg1; - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Node:draw"); - if (!ok) { break; } - unsigned int arg2; - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Node:draw"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Vec3 arg0; - if (!ok) { break; } - cobj->draw(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; + ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.Node:setRotation3D"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotation3D'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:draw",argc, 3); + cobj->setRotation3D(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotation3D",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_draw'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotation3D'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_visit(lua_State* tolua_S) +int lua_ax_base_Node_getRotation3D(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_visit'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotation3D'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - cobj->visit(); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - ax::Renderer* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Node:visit"); - - if (!ok) { break; } - ax::Mat4 arg1; - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Node:visit"); - - if (!ok) { break; } - unsigned int arg2; - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Node:visit"); - if (!ok) { break; } - cobj->visit(arg0, arg1, arg2); - lua_settop(tolua_S, 1); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotation3D'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:visit",argc, 3); + auto&& ret = cobj->getRotation3D(); + vec3_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotation3D",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_visit'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotation3D'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScene(lua_State* tolua_S) +int lua_ax_base_Node_setRotationSkewX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7896,34 +7949,37 @@ int lua_ax_base_Node_getScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotationSkewX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotationSkewX"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotationSkewX'", nullptr); return 0; } - auto&& ret = cobj->getScene(); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + cobj->setRotationSkewX(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotationSkewX",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotationSkewX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getBoundingBox(lua_State* tolua_S) +int lua_ax_base_Node_getRotationSkewX(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7943,34 +7999,34 @@ int lua_ax_base_Node_getBoundingBox(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getBoundingBox'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotationSkewX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getBoundingBox'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotationSkewX'", nullptr); return 0; } - auto&& ret = cobj->getBoundingBox(); - rect_to_luaval(tolua_S, ret); + auto&& ret = cobj->getRotationSkewX(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getBoundingBox",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotationSkewX",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getBoundingBox'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotationSkewX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setEventDispatcher(lua_State* tolua_S) +int lua_ax_base_Node_setRotationSkewY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -7990,37 +8046,37 @@ int lua_ax_base_Node_setEventDispatcher(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setRotationSkewY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::EventDispatcher* arg0; + double arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.EventDispatcher",&arg0, "ax.Node:setEventDispatcher"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:setRotationSkewY"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setRotationSkewY'", nullptr); return 0; } - cobj->setEventDispatcher(arg0); + cobj->setRotationSkewY(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setEventDispatcher",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setRotationSkewY",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setEventDispatcher'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setRotationSkewY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getEventDispatcher(lua_State* tolua_S) +int lua_ax_base_Node_getRotationSkewY(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8040,34 +8096,34 @@ int lua_ax_base_Node_getEventDispatcher(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getRotationSkewY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getRotationSkewY'", nullptr); return 0; } - auto&& ret = cobj->getEventDispatcher(); - object_to_luaval(tolua_S, "ax.EventDispatcher",(ax::EventDispatcher*)ret); + auto&& ret = cobj->getRotationSkewY(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getEventDispatcher",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getRotationSkewY",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getEventDispatcher'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getRotationSkewY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setActionManager(lua_State* tolua_S) +int lua_ax_base_Node_setIgnoreAnchorPointForPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8087,134 +8143,183 @@ int lua_ax_base_Node_setActionManager(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setActionManager'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::ActionManager* arg0; + bool arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionManager",&arg0, "ax.Node:setActionManager"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setIgnoreAnchorPointForPosition"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setActionManager'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'", nullptr); return 0; } - cobj->setActionManager(arg0); + cobj->setIgnoreAnchorPointForPosition(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setActionManager",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setIgnoreAnchorPointForPosition",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setActionManager'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setIgnoreAnchorPointForPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getActionManager(lua_State* tolua_S) +int lua_ax_base_Node_isIgnoreAnchorPointForPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getActionManager'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const ax::ActionManager* ret = cobj->getActionManager(); - object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::ActionManager* ret = cobj->getActionManager(); - object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); - return 1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getActionManager",argc, 0); + auto&& ret = cobj->isIgnoreAnchorPointForPosition(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isIgnoreAnchorPointForPosition",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getActionManager'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isIgnoreAnchorPointForPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_runAction(lua_State* tolua_S) +int lua_ax_base_Node_addChild(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_runAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_addChild'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Action* arg0; + do{ + if (argc == 2) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); - ok &= luaval_to_object(tolua_S, 2, "ax.Action",&arg0, "ax.Node:runAction"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_runAction'", nullptr); - return 0; + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); + + if (!ok) { break; } + cobj->addChild(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; } - auto&& ret = cobj->runAction(arg0); - object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:runAction",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 1) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); + + if (!ok) { break; } + cobj->addChild(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 3) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); + + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); + + if (!ok) { break; } + int arg2; + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Node:addChild"); + + if (!ok) { break; } + cobj->addChild(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 3) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:addChild"); + + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:addChild"); + + if (!ok) { break; } + std::string_view arg2; + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "ax.Node:addChild"); + + if (!ok) { break; } + cobj->addChild(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:addChild",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_runAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_addChild'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_stopAllActions(lua_State* tolua_S) +int lua_ax_base_Node_getChildByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8234,34 +8339,37 @@ int lua_ax_base_Node_stopAllActions(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAllActions'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getChildByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAllActions'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildByTag'", nullptr); return 0; } - cobj->stopAllActions(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getChildByTag(arg0); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAllActions",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAllActions'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_stopAction(lua_State* tolua_S) +int lua_ax_base_Node_getChildByName(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8281,87 +8389,84 @@ int lua_ax_base_Node_stopAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildByName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Action* arg0; + std::string_view arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Action",&arg0, "ax.Node:stopAction"); + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:getChildByName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildByName'", nullptr); return 0; } - cobj->stopAction(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getChildByName(arg0); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildByName",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildByName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_stopActionByTag(lua_State* tolua_S) +int lua_ax_base_Node_getChildren(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopActionByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildren'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:stopActionByTag"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopActionByTag'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::Vector& ret = cobj->getChildren(); + ccvector_to_luaval(tolua_S, ret); + return 1; } - cobj->stopActionByTag(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopActionByTag",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::Vector& ret = cobj->getChildren(); + ccvector_to_luaval(tolua_S, ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildren",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopActionByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildren'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_stopAllActionsByTag(lua_State* tolua_S) +int lua_ax_base_Node_getChildrenCount(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8381,37 +8486,34 @@ int lua_ax_base_Node_stopAllActionsByTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAllActionsByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getChildrenCount'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:stopAllActionsByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAllActionsByTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getChildrenCount'", nullptr); return 0; } - cobj->stopAllActionsByTag(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getChildrenCount(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAllActionsByTag",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getChildrenCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAllActionsByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getChildrenCount'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_stopActionsByFlags(lua_State* tolua_S) +int lua_ax_base_Node_setParent(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8431,87 +8533,135 @@ int lua_ax_base_Node_stopActionsByFlags(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopActionsByFlags'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setParent'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - unsigned int arg0; + ax::Node* arg0; - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:stopActionsByFlags"); + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:setParent"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopActionsByFlags'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setParent'", nullptr); return 0; } - cobj->stopActionsByFlags(arg0); + cobj->setParent(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopActionsByFlags",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setParent",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopActionsByFlags'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setParent'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getActionByTag(lua_State* tolua_S) +int lua_ax_base_Node_getParent(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getActionByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParent'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getActionByTag"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getActionByTag'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::Node* ret = cobj->getParent(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + return 1; } - auto&& ret = cobj->getActionByTag(arg0); - object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); - return 1; + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::Node* ret = cobj->getParent(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParent",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParent'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Node_removeFromParentAndCleanup(lua_State* tolua_S) +{ + int argc = 0; + ax::Node* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeFromParentAndCleanup'", nullptr); + return 0; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getActionByTag",argc, 1); +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + bool arg0; + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:removeFromParentAndCleanup"); + + if (!ok) { break; } + cobj->removeFromParentAndCleanup(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 0) { + cobj->removeFromParent(); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeFromParent",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getActionByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeFromParentAndCleanup'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNumberOfRunningActions(lua_State* tolua_S) +int lua_ax_base_Node_removeChild(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8531,34 +8681,54 @@ int lua_ax_base_Node_getNumberOfRunningActions(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNumberOfRunningActions'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChild'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:removeChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNumberOfRunningActions'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChild'", nullptr); return 0; } - auto&& ret = cobj->getNumberOfRunningActions(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->removeChild(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNumberOfRunningActions",argc, 0); + if (argc == 2) + { + ax::Node* arg0; + bool arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:removeChild"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChild"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChild'", nullptr); + return 0; + } + cobj->removeChild(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChild",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNumberOfRunningActions'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChild'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNumberOfRunningActionsByTag(lua_State* tolua_S) +int lua_ax_base_Node_removeChildByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8578,37 +8748,54 @@ int lua_ax_base_Node_getNumberOfRunningActionsByTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChildByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getNumberOfRunningActionsByTag"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:removeChildByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByTag'", nullptr); return 0; } - auto&& ret = cobj->getNumberOfRunningActionsByTag(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->removeChildByTag(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNumberOfRunningActionsByTag",argc, 1); + if (argc == 2) + { + int arg0; + bool arg1; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:removeChildByTag"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChildByTag"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByTag'", nullptr); + return 0; + } + cobj->removeChildByTag(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChildByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChildByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setScheduler(lua_State* tolua_S) +int lua_ax_base_Node_removeChildByName(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8628,37 +8815,54 @@ int lua_ax_base_Node_setScheduler(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScheduler'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeChildByName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Scheduler* arg0; + std::string_view arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Scheduler",&arg0, "ax.Node:setScheduler"); + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeChildByName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScheduler'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByName'", nullptr); return 0; } - cobj->setScheduler(arg0); + cobj->removeChildByName(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScheduler",argc, 1); + if (argc == 2) + { + std::string_view arg0; + bool arg1; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeChildByName"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:removeChildByName"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeChildByName'", nullptr); + return 0; + } + cobj->removeChildByName(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeChildByName",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScheduler'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeChildByName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getScheduler(lua_State* tolua_S) +int lua_ax_base_Node_removeAllChildrenWithCleanup(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8674,38 +8878,42 @@ int lua_ax_base_Node_getScheduler(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScheduler'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeAllChildrenWithCleanup'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; do{ - if (argc == 0) { - const ax::Scheduler* ret = cobj->getScheduler(); - object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); + if (argc == 1) { + bool arg0; + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:removeAllChildrenWithCleanup"); + + if (!ok) { break; } + cobj->removeAllChildrenWithCleanup(arg0); + lua_settop(tolua_S, 1); return 1; } }while(0); ok = true; do{ if (argc == 0) { - ax::Scheduler* ret = cobj->getScheduler(); - object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); + cobj->removeAllChildren(); + lua_settop(tolua_S, 1); return 1; } }while(0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScheduler",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeAllChildren",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScheduler'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeAllChildrenWithCleanup'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isScheduled(lua_State* tolua_S) +int lua_ax_base_Node_reorderChild(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8725,37 +8933,40 @@ int lua_ax_base_Node_isScheduled(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isScheduled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_reorderChild'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - std::string_view arg0; + ax::Node* arg0; + int arg1; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:isScheduled"); + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:reorderChild"); + + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Node:reorderChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isScheduled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_reorderChild'", nullptr); return 0; } - auto&& ret = cobj->isScheduled(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->reorderChild(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isScheduled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:reorderChild",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isScheduled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_reorderChild'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_resume(lua_State* tolua_S) +int lua_ax_base_Node_sortAllChildren(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8775,34 +8986,34 @@ int lua_ax_base_Node_resume(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_resume'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_sortAllChildren'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_resume'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_sortAllChildren'", nullptr); return 0; } - cobj->resume(); + cobj->sortAllChildren(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:resume",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:sortAllChildren",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_resume'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_sortAllChildren'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_pause(lua_State* tolua_S) +int lua_ax_base_Node_getTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8822,34 +9033,34 @@ int lua_ax_base_Node_pause(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_pause'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_pause'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getTag'", nullptr); return 0; } - cobj->pause(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getTag(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:pause",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getTag",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_pause'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_update(lua_State* tolua_S) +int lua_ax_base_Node_setTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8869,37 +9080,37 @@ int lua_ax_base_Node_update(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_update'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + int arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:update"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:setTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_update'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setTag'", nullptr); return 0; } - cobj->update(arg0); + cobj->setTag(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:update",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_update'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_updateTransform(lua_State* tolua_S) +int lua_ax_base_Node_getName(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -8919,136 +9130,134 @@ int lua_ax_base_Node_updateTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getName'", nullptr); return 0; } - cobj->updateTransform(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getName(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateTransform",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getName",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNodeToParentTransform(lua_State* tolua_S) +int lua_ax_base_Node_setName(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToParentTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setName'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:getNodeToParentTransform"); + if (argc == 1) + { + std::string_view arg0; - if (!ok) { break; } - ax::Mat4 ret = cobj->getNodeToParentTransform(arg0); - mat4_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - const ax::Mat4& ret = cobj->getNodeToParentTransform(); - mat4_to_luaval(tolua_S, ret); - return 1; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:setName"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setName'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToParentTransform",argc, 0); + cobj->setName(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setName",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToParentTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNodeToParentAffineTransform(lua_State* tolua_S) +int lua_ax_base_Node_setUserObject(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToParentAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setUserObject'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:getNodeToParentAffineTransform"); + if (argc == 1) + { + ax::Object* arg0; - if (!ok) { break; } - ax::AffineTransform ret = cobj->getNodeToParentAffineTransform(arg0); - affinetransform_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::AffineTransform ret = cobj->getNodeToParentAffineTransform(); - affinetransform_to_luaval(tolua_S, ret); - return 1; + ok &= luaval_to_object(tolua_S, 2, "ax.Object",&arg0, "ax.Node:setUserObject"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setUserObject'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToParentAffineTransform",argc, 0); + cobj->setUserObject(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setUserObject",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToParentAffineTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setUserObject'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setNodeToParentTransform(lua_State* tolua_S) +int lua_ax_base_Node_isRunning(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9068,37 +9277,34 @@ int lua_ax_base_Node_setNodeToParentTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setNodeToParentTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isRunning'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Mat4 arg0; - - ok &= luaval_to_mat4(tolua_S, 2, &arg0, "ax.Node:setNodeToParentTransform"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setNodeToParentTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isRunning'", nullptr); return 0; } - cobj->setNodeToParentTransform(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isRunning(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setNodeToParentTransform",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isRunning",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setNodeToParentTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isRunning'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getParentToNodeTransform(lua_State* tolua_S) +int lua_ax_base_Node_cleanup(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9118,128 +9324,152 @@ int lua_ax_base_Node_getParentToNodeTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParentToNodeTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_cleanup'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getParentToNodeTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_cleanup'", nullptr); return 0; } - auto&& ret = cobj->getParentToNodeTransform(); - mat4_to_luaval(tolua_S, ret); + cobj->cleanup(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParentToNodeTransform",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:cleanup",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParentToNodeTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_cleanup'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getParentToNodeAffineTransform(lua_State* tolua_S) +int lua_ax_base_Node_draw(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParentToNodeAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_draw'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getParentToNodeAffineTransform'", nullptr); - return 0; + do{ + if (argc == 0) { + cobj->draw(); + lua_settop(tolua_S, 1); + return 1; } - auto&& ret = cobj->getParentToNodeAffineTransform(); - affinetransform_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParentToNodeAffineTransform",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 3) { + ax::Renderer* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Node:draw"); + + if (!ok) { break; } + ax::Mat4 arg1; + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Node:draw"); + + if (!ok) { break; } + unsigned int arg2; + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Node:draw"); + + if (!ok) { break; } + cobj->draw(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:draw",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParentToNodeAffineTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_draw'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNodeToWorldTransform(lua_State* tolua_S) +int lua_ax_base_Node_visit(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToWorldTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_visit'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNodeToWorldTransform'", nullptr); - return 0; + do{ + if (argc == 0) { + cobj->visit(); + lua_settop(tolua_S, 1); + return 1; } - auto&& ret = cobj->getNodeToWorldTransform(); - mat4_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToWorldTransform",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 3) { + ax::Renderer* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Node:visit"); + + if (!ok) { break; } + ax::Mat4 arg1; + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Node:visit"); + + if (!ok) { break; } + unsigned int arg2; + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Node:visit"); + + if (!ok) { break; } + cobj->visit(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:visit",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToWorldTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_visit'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getNodeToWorldAffineTransform(lua_State* tolua_S) +int lua_ax_base_Node_getScene(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9259,34 +9489,34 @@ int lua_ax_base_Node_getNodeToWorldAffineTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScene'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getScene'", nullptr); return 0; } - auto&& ret = cobj->getNodeToWorldAffineTransform(); - affinetransform_to_luaval(tolua_S, ret); + auto&& ret = cobj->getScene(); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToWorldAffineTransform",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScene",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScene'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getWorldToNodeTransform(lua_State* tolua_S) +int lua_ax_base_Node_getBoundingBox(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9306,34 +9536,34 @@ int lua_ax_base_Node_getWorldToNodeTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldToNodeTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getBoundingBox'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldToNodeTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getBoundingBox'", nullptr); return 0; } - auto&& ret = cobj->getWorldToNodeTransform(); - mat4_to_luaval(tolua_S, ret); + auto&& ret = cobj->getBoundingBox(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldToNodeTransform",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getBoundingBox",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldToNodeTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getBoundingBox'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getWorldToNodeAffineTransform(lua_State* tolua_S) +int lua_ax_base_Node_setEventDispatcher(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9353,34 +9583,37 @@ int lua_ax_base_Node_getWorldToNodeAffineTransform(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setEventDispatcher'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::EventDispatcher* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.EventDispatcher",&arg0, "ax.Node:setEventDispatcher"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setEventDispatcher'", nullptr); return 0; } - auto&& ret = cobj->getWorldToNodeAffineTransform(); - affinetransform_to_luaval(tolua_S, ret); + cobj->setEventDispatcher(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldToNodeAffineTransform",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setEventDispatcher",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setEventDispatcher'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertToNodeSpace(lua_State* tolua_S) +int lua_ax_base_Node_getEventDispatcher(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9400,37 +9633,34 @@ int lua_ax_base_Node_convertToNodeSpace(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToNodeSpace'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getEventDispatcher'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToNodeSpace"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToNodeSpace'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getEventDispatcher'", nullptr); return 0; } - auto&& ret = cobj->convertToNodeSpace(arg0); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getEventDispatcher(); + object_to_luaval(tolua_S, "ax.EventDispatcher",(ax::EventDispatcher*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToNodeSpace",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getEventDispatcher",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToNodeSpace'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getEventDispatcher'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertToWorldSpace(lua_State* tolua_S) +int lua_ax_base_Node_setActionManager(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9450,87 +9680,84 @@ int lua_ax_base_Node_convertToWorldSpace(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToWorldSpace'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setActionManager'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec2 arg0; + ax::ActionManager* arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToWorldSpace"); + ok &= luaval_to_object(tolua_S, 2, "ax.ActionManager",&arg0, "ax.Node:setActionManager"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToWorldSpace'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setActionManager'", nullptr); return 0; } - auto&& ret = cobj->convertToWorldSpace(arg0); - vec2_to_luaval(tolua_S, ret); + cobj->setActionManager(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToWorldSpace",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setActionManager",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToWorldSpace'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setActionManager'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertToNodeSpaceAR(lua_State* tolua_S) +int lua_ax_base_Node_getActionManager(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToNodeSpaceAR'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getActionManager'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToNodeSpaceAR"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToNodeSpaceAR'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::ActionManager* ret = cobj->getActionManager(); + object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); + return 1; } - auto&& ret = cobj->convertToNodeSpaceAR(arg0); - vec2_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToNodeSpaceAR",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::ActionManager* ret = cobj->getActionManager(); + object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getActionManager",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToNodeSpaceAR'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getActionManager'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertToWorldSpaceAR(lua_State* tolua_S) +int lua_ax_base_Node_runAction(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9550,37 +9777,37 @@ int lua_ax_base_Node_convertToWorldSpaceAR(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToWorldSpaceAR'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_runAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec2 arg0; + ax::Action* arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToWorldSpaceAR"); + ok &= luaval_to_object(tolua_S, 2, "ax.Action",&arg0, "ax.Node:runAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToWorldSpaceAR'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_runAction'", nullptr); return 0; } - auto&& ret = cobj->convertToWorldSpaceAR(arg0); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->runAction(arg0); + object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToWorldSpaceAR",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:runAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToWorldSpaceAR'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_runAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertTouchToNodeSpace(lua_State* tolua_S) +int lua_ax_base_Node_stopAllActions(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9600,37 +9827,34 @@ int lua_ax_base_Node_convertTouchToNodeSpace(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertTouchToNodeSpace'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAllActions'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Touch* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Touch",&arg0, "ax.Node:convertTouchToNodeSpace"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertTouchToNodeSpace'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAllActions'", nullptr); return 0; } - auto&& ret = cobj->convertTouchToNodeSpace(arg0); - vec2_to_luaval(tolua_S, ret); + cobj->stopAllActions(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertTouchToNodeSpace",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAllActions",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertTouchToNodeSpace'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAllActions'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_convertTouchToNodeSpaceAR(lua_State* tolua_S) +int lua_ax_base_Node_stopAction(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9650,37 +9874,37 @@ int lua_ax_base_Node_convertTouchToNodeSpaceAR(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Touch* arg0; + ax::Action* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Touch",&arg0, "ax.Node:convertTouchToNodeSpaceAR"); + ok &= luaval_to_object(tolua_S, 2, "ax.Action",&arg0, "ax.Node:stopAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAction'", nullptr); return 0; } - auto&& ret = cobj->convertTouchToNodeSpaceAR(arg0); - vec2_to_luaval(tolua_S, ret); + cobj->stopAction(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertTouchToNodeSpaceAR",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getWorldPosition(lua_State* tolua_S) +int lua_ax_base_Node_stopActionByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9700,34 +9924,37 @@ int lua_ax_base_Node_getWorldPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopActionByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:stopActionByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopActionByTag'", nullptr); return 0; } - auto&& ret = cobj->getWorldPosition(); - vec2_to_luaval(tolua_S, ret); + cobj->stopActionByTag(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldPosition",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopActionByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopActionByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setWorldPosition(lua_State* tolua_S) +int lua_ax_base_Node_stopAllActionsByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9747,37 +9974,37 @@ int lua_ax_base_Node_setWorldPosition(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setWorldPosition'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopAllActionsByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec2 arg0; + int arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setWorldPosition"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:stopAllActionsByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setWorldPosition'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopAllActionsByTag'", nullptr); return 0; } - cobj->setWorldPosition(arg0); + cobj->stopAllActionsByTag(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setWorldPosition",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopAllActionsByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setWorldPosition'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopAllActionsByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getComponent(lua_State* tolua_S) +int lua_ax_base_Node_stopActionsByFlags(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9797,37 +10024,37 @@ int lua_ax_base_Node_getComponent(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getComponent'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_stopActionsByFlags'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - std::string_view arg0; + unsigned int arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:getComponent"); + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:stopActionsByFlags"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getComponent'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_stopActionsByFlags'", nullptr); return 0; } - auto&& ret = cobj->getComponent(arg0); - object_to_luaval(tolua_S, "ax.Component",(ax::Component*)ret); + cobj->stopActionsByFlags(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getComponent",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:stopActionsByFlags",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getComponent'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_stopActionsByFlags'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_addComponent(lua_State* tolua_S) +int lua_ax_base_Node_getActionByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9847,92 +10074,37 @@ int lua_ax_base_Node_addComponent(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_addComponent'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getActionByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Component* arg0; + int arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Component",&arg0, "ax.Node:addComponent"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getActionByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_addComponent'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getActionByTag'", nullptr); return 0; } - auto&& ret = cobj->addComponent(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getActionByTag(arg0); + object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:addComponent",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_addComponent'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_Node_removeComponent(lua_State* tolua_S) -{ - int argc = 0; - ax::Node* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeComponent'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Component* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Component",&arg0, "ax.Node:removeComponent"); - - if (!ok) { break; } - bool ret = cobj->removeComponent(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeComponent"); - - if (!ok) { break; } - bool ret = cobj->removeComponent(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeComponent",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getActionByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeComponent'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getActionByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_removeAllComponents(lua_State* tolua_S) +int lua_ax_base_Node_getNumberOfRunningActions(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9952,34 +10124,34 @@ int lua_ax_base_Node_removeAllComponents(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeAllComponents'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNumberOfRunningActions'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeAllComponents'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNumberOfRunningActions'", nullptr); return 0; } - cobj->removeAllComponents(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getNumberOfRunningActions(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeAllComponents",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNumberOfRunningActions",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeAllComponents'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNumberOfRunningActions'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getOpacity(lua_State* tolua_S) +int lua_ax_base_Node_getNumberOfRunningActionsByTag(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -9999,34 +10171,37 @@ int lua_ax_base_Node_getOpacity(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOpacity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Node:getNumberOfRunningActionsByTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOpacity'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'", nullptr); return 0; } - auto&& ret = cobj->getOpacity(); + auto&& ret = cobj->getNumberOfRunningActionsByTag(arg0); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOpacity",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNumberOfRunningActionsByTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOpacity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNumberOfRunningActionsByTag'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getDisplayedOpacity(lua_State* tolua_S) +int lua_ax_base_Node_setScheduler(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10046,84 +10221,84 @@ int lua_ax_base_Node_getDisplayedOpacity(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDisplayedOpacity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setScheduler'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Scheduler* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Scheduler",&arg0, "ax.Node:setScheduler"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDisplayedOpacity'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setScheduler'", nullptr); return 0; } - auto&& ret = cobj->getDisplayedOpacity(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setScheduler(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDisplayedOpacity",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setScheduler",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDisplayedOpacity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setScheduler'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOpacity(lua_State* tolua_S) +int lua_ax_base_Node_getScheduler(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOpacity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getScheduler'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - uint16_t arg0; - - ok &= luaval_to_uint16(tolua_S, 2,&arg0, "ax.Node:setOpacity"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOpacity'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::Scheduler* ret = cobj->getScheduler(); + object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); + return 1; } - cobj->setOpacity(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOpacity",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::Scheduler* ret = cobj->getScheduler(); + object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getScheduler",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOpacity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getScheduler'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_updateDisplayedOpacity(lua_State* tolua_S) +int lua_ax_base_Node_isScheduled(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10143,37 +10318,37 @@ int lua_ax_base_Node_updateDisplayedOpacity(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateDisplayedOpacity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isScheduled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - uint16_t arg0; + std::string_view arg0; - ok &= luaval_to_uint16(tolua_S, 2,&arg0, "ax.Node:updateDisplayedOpacity"); + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:isScheduled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateDisplayedOpacity'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isScheduled'", nullptr); return 0; } - cobj->updateDisplayedOpacity(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isScheduled(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateDisplayedOpacity",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isScheduled",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateDisplayedOpacity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isScheduled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isCascadeOpacityEnabled(lua_State* tolua_S) +int lua_ax_base_Node_resume(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10193,34 +10368,34 @@ int lua_ax_base_Node_isCascadeOpacityEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isCascadeOpacityEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_resume'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isCascadeOpacityEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_resume'", nullptr); return 0; } - auto&& ret = cobj->isCascadeOpacityEnabled(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->resume(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isCascadeOpacityEnabled",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:resume",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isCascadeOpacityEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_resume'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setCascadeOpacityEnabled(lua_State* tolua_S) +int lua_ax_base_Node_pause(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10240,37 +10415,34 @@ int lua_ax_base_Node_setCascadeOpacityEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCascadeOpacityEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_pause'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setCascadeOpacityEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCascadeOpacityEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_pause'", nullptr); return 0; } - cobj->setCascadeOpacityEnabled(arg0); + cobj->pause(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCascadeOpacityEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:pause",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCascadeOpacityEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_pause'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getColor(lua_State* tolua_S) +int lua_ax_base_Node_update(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10290,34 +10462,37 @@ int lua_ax_base_Node_getColor(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_update'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Node:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getColor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_update'", nullptr); return 0; } - auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + cobj->update(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getColor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:update",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_update'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getDisplayedColor(lua_State* tolua_S) +int lua_ax_base_Node_updateTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10337,134 +10512,136 @@ int lua_ax_base_Node_getDisplayedColor(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDisplayedColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDisplayedColor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateTransform'", nullptr); return 0; } - auto&& ret = cobj->getDisplayedColor(); - color3b_to_luaval(tolua_S, ret); + cobj->updateTransform(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDisplayedColor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDisplayedColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setColor(lua_State* tolua_S) +int lua_ax_base_Node_getNodeToParentTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToParentTransform'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Color3B arg0; + do{ + if (argc == 1) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:getNodeToParentTransform"); - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.Node:setColor"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setColor'", nullptr); - return 0; + if (!ok) { break; } + ax::Mat4 ret = cobj->getNodeToParentTransform(arg0); + mat4_to_luaval(tolua_S, ret); + return 1; } - cobj->setColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setColor",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + const ax::Mat4& ret = cobj->getNodeToParentTransform(); + mat4_to_luaval(tolua_S, ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToParentTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToParentTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_updateDisplayedColor(lua_State* tolua_S) +int lua_ax_base_Node_getNodeToParentAffineTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateDisplayedColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToParentAffineTransform'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Color3B arg0; + do{ + if (argc == 1) { + ax::Node* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:getNodeToParentAffineTransform"); - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.Node:updateDisplayedColor"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateDisplayedColor'", nullptr); - return 0; + if (!ok) { break; } + ax::AffineTransform ret = cobj->getNodeToParentAffineTransform(arg0); + affinetransform_to_luaval(tolua_S, ret); + return 1; } - cobj->updateDisplayedColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateDisplayedColor",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::AffineTransform ret = cobj->getNodeToParentAffineTransform(); + affinetransform_to_luaval(tolua_S, ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToParentAffineTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateDisplayedColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToParentAffineTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isCascadeColorEnabled(lua_State* tolua_S) +int lua_ax_base_Node_setNodeToParentTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10484,34 +10661,37 @@ int lua_ax_base_Node_isCascadeColorEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isCascadeColorEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setNodeToParentTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Mat4 arg0; + + ok &= luaval_to_mat4(tolua_S, 2, &arg0, "ax.Node:setNodeToParentTransform"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isCascadeColorEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setNodeToParentTransform'", nullptr); return 0; } - auto&& ret = cobj->isCascadeColorEnabled(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setNodeToParentTransform(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isCascadeColorEnabled",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setNodeToParentTransform",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isCascadeColorEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setNodeToParentTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setCascadeColorEnabled(lua_State* tolua_S) +int lua_ax_base_Node_getParentToNodeTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10531,37 +10711,34 @@ int lua_ax_base_Node_setCascadeColorEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCascadeColorEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParentToNodeTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setCascadeColorEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCascadeColorEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getParentToNodeTransform'", nullptr); return 0; } - cobj->setCascadeColorEnabled(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getParentToNodeTransform(); + mat4_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCascadeColorEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParentToNodeTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCascadeColorEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParentToNodeTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOpacityModifyRGB(lua_State* tolua_S) +int lua_ax_base_Node_getParentToNodeAffineTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10581,37 +10758,34 @@ int lua_ax_base_Node_setOpacityModifyRGB(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOpacityModifyRGB'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getParentToNodeAffineTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setOpacityModifyRGB"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOpacityModifyRGB'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getParentToNodeAffineTransform'", nullptr); return 0; } - cobj->setOpacityModifyRGB(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getParentToNodeAffineTransform(); + affinetransform_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOpacityModifyRGB",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getParentToNodeAffineTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOpacityModifyRGB'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getParentToNodeAffineTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_isOpacityModifyRGB(lua_State* tolua_S) +int lua_ax_base_Node_getNodeToWorldTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10631,34 +10805,34 @@ int lua_ax_base_Node_isOpacityModifyRGB(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isOpacityModifyRGB'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToWorldTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isOpacityModifyRGB'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNodeToWorldTransform'", nullptr); return 0; } - auto&& ret = cobj->isOpacityModifyRGB(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getNodeToWorldTransform(); + mat4_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isOpacityModifyRGB",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToWorldTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isOpacityModifyRGB'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToWorldTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOnEnterCallback(lua_State* tolua_S) +int lua_ax_base_Node_getNodeToWorldAffineTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10678,41 +10852,34 @@ int lua_ax_base_Node_setOnEnterCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnEnterCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::function arg0; - - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnEnterCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'", nullptr); return 0; } - cobj->setOnEnterCallback(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getNodeToWorldAffineTransform(); + affinetransform_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnEnterCallback",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getNodeToWorldAffineTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnEnterCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getNodeToWorldAffineTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOnExitCallback(lua_State* tolua_S) +int lua_ax_base_Node_getWorldToNodeTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10732,41 +10899,34 @@ int lua_ax_base_Node_setOnExitCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnExitCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldToNodeTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::function arg0; - - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnExitCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldToNodeTransform'", nullptr); return 0; } - cobj->setOnExitCallback(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getWorldToNodeTransform(); + mat4_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnExitCallback",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldToNodeTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnExitCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldToNodeTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOnEnterTransitionDidFinishCallback(lua_State* tolua_S) +int lua_ax_base_Node_getWorldToNodeAffineTransform(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10786,41 +10946,34 @@ int lua_ax_base_Node_setOnEnterTransitionDidFinishCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::function arg0; - - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'", nullptr); return 0; } - cobj->setOnEnterTransitionDidFinishCallback(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getWorldToNodeAffineTransform(); + affinetransform_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnEnterTransitionDidFinishCallback",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldToNodeAffineTransform",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldToNodeAffineTransform'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getOnEnterTransitionDidFinishCallback(lua_State* tolua_S) +int lua_ax_base_Node_convertToNodeSpace(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10840,34 +10993,37 @@ int lua_ax_base_Node_getOnEnterTransitionDidFinishCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToNodeSpace'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToNodeSpace"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToNodeSpace'", nullptr); return 0; } - auto&& ret = cobj->getOnEnterTransitionDidFinishCallback(); - #pragma warning NO CONVERSION FROM NATIVE FOR std::function; + auto&& ret = cobj->convertToNodeSpace(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOnEnterTransitionDidFinishCallback",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToNodeSpace",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToNodeSpace'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setOnExitTransitionDidStartCallback(lua_State* tolua_S) +int lua_ax_base_Node_convertToWorldSpace(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10887,41 +11043,37 @@ int lua_ax_base_Node_setOnExitTransitionDidStartCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToWorldSpace'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - std::function arg0; + ax::Vec2 arg0; - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToWorldSpace"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToWorldSpace'", nullptr); return 0; } - cobj->setOnExitTransitionDidStartCallback(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->convertToWorldSpace(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnExitTransitionDidStartCallback",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToWorldSpace",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToWorldSpace'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getOnExitTransitionDidStartCallback(lua_State* tolua_S) +int lua_ax_base_Node_convertToNodeSpaceAR(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10941,34 +11093,37 @@ int lua_ax_base_Node_getOnExitTransitionDidStartCallback(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToNodeSpaceAR'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToNodeSpaceAR"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToNodeSpaceAR'", nullptr); return 0; } - auto&& ret = cobj->getOnExitTransitionDidStartCallback(); - #pragma warning NO CONVERSION FROM NATIVE FOR std::function; + auto&& ret = cobj->convertToNodeSpaceAR(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOnExitTransitionDidStartCallback",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToNodeSpaceAR",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToNodeSpaceAR'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getCameraMask(lua_State* tolua_S) +int lua_ax_base_Node_convertToWorldSpaceAR(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -10988,34 +11143,37 @@ int lua_ax_base_Node_getCameraMask(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getCameraMask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertToWorldSpaceAR'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:convertToWorldSpaceAR"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getCameraMask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertToWorldSpaceAR'", nullptr); return 0; } - auto&& ret = cobj->getCameraMask(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->convertToWorldSpaceAR(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getCameraMask",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertToWorldSpaceAR",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getCameraMask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertToWorldSpaceAR'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setCameraMask(lua_State* tolua_S) +int lua_ax_base_Node_convertTouchToNodeSpace(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11035,54 +11193,37 @@ int lua_ax_base_Node_setCameraMask(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCameraMask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertTouchToNodeSpace'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - unsigned short arg0; - - ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.Node:setCameraMask"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCameraMask'", nullptr); - return 0; - } - cobj->setCameraMask(arg0); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 2) + if (argc == 1) { - unsigned short arg0; - bool arg1; - - ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.Node:setCameraMask"); + ax::Touch* arg0; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:setCameraMask"); + ok &= luaval_to_object(tolua_S, 2, "ax.Touch",&arg0, "ax.Node:convertTouchToNodeSpace"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCameraMask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertTouchToNodeSpace'", nullptr); return 0; } - cobj->setCameraMask(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->convertTouchToNodeSpace(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCameraMask",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertTouchToNodeSpace",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCameraMask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertTouchToNodeSpace'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_applyMaskOnEnter(lua_State* tolua_S) +int lua_ax_base_Node_convertTouchToNodeSpaceAR(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11102,108 +11243,84 @@ int lua_ax_base_Node_applyMaskOnEnter(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_applyMaskOnEnter'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - bool arg0; + ax::Touch* arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:applyMaskOnEnter"); + ok &= luaval_to_object(tolua_S, 2, "ax.Touch",&arg0, "ax.Node:convertTouchToNodeSpaceAR"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_applyMaskOnEnter'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'", nullptr); return 0; } - cobj->applyMaskOnEnter(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->convertTouchToNodeSpaceAR(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:applyMaskOnEnter",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:convertTouchToNodeSpaceAR",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_applyMaskOnEnter'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_convertTouchToNodeSpaceAR'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setProgramState(lua_State* tolua_S) +int lua_ax_base_Node_getWorldPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramState'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getWorldPosition'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::backend::ProgramState* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.ProgramState",&arg0, "ax.Node:setProgramState"); - - if (!ok) { break; } - bool ret = cobj->setProgramState(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - ax::backend::ProgramState* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.ProgramState",&arg0, "ax.Node:setProgramState"); - - if (!ok) { break; } - bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:setProgramState"); - - if (!ok) { break; } - bool ret = cobj->setProgramState(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - unsigned int arg0; - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:setProgramState"); - if (!ok) { break; } - cobj->setProgramState(arg0); - lua_settop(tolua_S, 1); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getWorldPosition'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramState",argc, 1); + auto&& ret = cobj->getWorldPosition(); + vec2_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getWorldPosition",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramState'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getWorldPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setProgramStateWithRegistry(lua_State* tolua_S) +int lua_ax_base_Node_setWorldPosition(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11223,40 +11340,37 @@ int lua_ax_base_Node_setProgramStateWithRegistry(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramStateWithRegistry'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setWorldPosition'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - unsigned int arg0; - ax::Texture2D* arg1; - - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:setProgramStateWithRegistry"); + ax::Vec2 arg0; - ok &= luaval_to_object(tolua_S, 3, "ax.Texture2D",&arg1, "ax.Node:setProgramStateWithRegistry"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Node:setWorldPosition"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setProgramStateWithRegistry'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setWorldPosition'", nullptr); return 0; } - cobj->setProgramStateWithRegistry(arg0, arg1); + cobj->setWorldPosition(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramStateWithRegistry",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setWorldPosition",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramStateWithRegistry'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setWorldPosition'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setProgramStateByProgramId(lua_State* tolua_S) +int lua_ax_base_Node_getComponent(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11276,37 +11390,37 @@ int lua_ax_base_Node_setProgramStateByProgramId(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramStateByProgramId'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getComponent'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - unsigned long long arg0; + std::string_view arg0; - ok &= luaval_to_long_long(tolua_S, 2,(long long*)&arg0, "ax.Node:setProgramStateByProgramId"); + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:getComponent"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setProgramStateByProgramId'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getComponent'", nullptr); return 0; } - auto&& ret = cobj->setProgramStateByProgramId(arg0); - object_to_luaval(tolua_S, "axb.ProgramState",(ax::backend::ProgramState*)ret); + auto&& ret = cobj->getComponent(arg0); + object_to_luaval(tolua_S, "ax.Component",(ax::Component*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramStateByProgramId",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getComponent",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramStateByProgramId'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getComponent'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getProgramState(lua_State* tolua_S) +int lua_ax_base_Node_addComponent(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11326,84 +11440,92 @@ int lua_ax_base_Node_getProgramState(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getProgramState'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_addComponent'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Component* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Component",&arg0, "ax.Node:addComponent"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getProgramState'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_addComponent'", nullptr); return 0; } - auto&& ret = cobj->getProgramState(); - object_to_luaval(tolua_S, "axb.ProgramState",(ax::backend::ProgramState*)ret); + auto&& ret = cobj->addComponent(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getProgramState",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:addComponent",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getProgramState'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_addComponent'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_updateProgramStateTexture(lua_State* tolua_S) +int lua_ax_base_Node_removeComponent(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateProgramStateTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeComponent'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Texture2D* arg0; + do{ + if (argc == 1) { + ax::Component* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Component",&arg0, "ax.Node:removeComponent"); - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.Node:updateProgramStateTexture"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateProgramStateTexture'", nullptr); - return 0; + if (!ok) { break; } + bool ret = cobj->removeComponent(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->updateProgramStateTexture(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateProgramStateTexture",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Node:removeComponent"); + + if (!ok) { break; } + bool ret = cobj->removeComponent(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeComponent",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateProgramStateTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeComponent'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_resetChild(lua_State* tolua_S) +int lua_ax_base_Node_removeAllComponents(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11423,40 +11545,34 @@ int lua_ax_base_Node_resetChild(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_resetChild'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_removeAllComponents'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Node* arg0; - bool arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:resetChild"); - - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:resetChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_resetChild'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_removeAllComponents'", nullptr); return 0; } - cobj->resetChild(arg0, arg1); + cobj->removeAllComponents(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:resetChild",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:removeAllComponents",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_resetChild'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_removeAllComponents'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_init(lua_State* tolua_S) +int lua_ax_base_Node_getOpacity(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11476,34 +11592,34 @@ int lua_ax_base_Node_init(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_init'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOpacity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOpacity'", nullptr); return 0; } - auto&& ret = cobj->init(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getOpacity(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:init",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOpacity",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOpacity'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_initLayer(lua_State* tolua_S) +int lua_ax_base_Node_getDisplayedOpacity(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11523,34 +11639,34 @@ int lua_ax_base_Node_initLayer(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_initLayer'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDisplayedOpacity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_initLayer'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDisplayedOpacity'", nullptr); return 0; } - auto&& ret = cobj->initLayer(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getDisplayedOpacity(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:initLayer",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDisplayedOpacity",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_initLayer'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDisplayedOpacity'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_setPhysicsBody(lua_State* tolua_S) +int lua_ax_base_Node_setOpacity(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11570,37 +11686,37 @@ int lua_ax_base_Node_setPhysicsBody(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPhysicsBody'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOpacity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::PhysicsBody* arg0; + uint16_t arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.Node:setPhysicsBody"); + ok &= luaval_to_uint16(tolua_S, 2,&arg0, "ax.Node:setOpacity"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPhysicsBody'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOpacity'", nullptr); return 0; } - cobj->setPhysicsBody(arg0); + cobj->setOpacity(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPhysicsBody",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOpacity",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPhysicsBody'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOpacity'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_getPhysicsBody(lua_State* tolua_S) +int lua_ax_base_Node_updateDisplayedOpacity(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11620,102 +11736,134 @@ int lua_ax_base_Node_getPhysicsBody(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPhysicsBody'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateDisplayedOpacity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + uint16_t arg0; + + ok &= luaval_to_uint16(tolua_S, 2,&arg0, "ax.Node:updateDisplayedOpacity"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPhysicsBody'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateDisplayedOpacity'", nullptr); return 0; } - auto&& ret = cobj->getPhysicsBody(); - object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); + cobj->updateDisplayedOpacity(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPhysicsBody",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateDisplayedOpacity",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPhysicsBody'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateDisplayedOpacity'.",&tolua_err); #endif return 0; } -int lua_ax_base_Node_create(lua_State* tolua_S) +int lua_ax_base_Node_isCascadeOpacityEnabled(lua_State* tolua_S) { int argc = 0; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isCascadeOpacityEnabled'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isCascadeOpacityEnabled'", nullptr); return 0; } - auto&& ret = ax::Node::create(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + auto&& ret = cobj->isCascadeOpacityEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Node:create",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isCascadeOpacityEnabled",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isCascadeOpacityEnabled'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Node_getAttachedNodeCount(lua_State* tolua_S) +int lua_ax_base_Node_setCascadeOpacityEnabled(lua_State* tolua_S) { int argc = 0; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); - if (argc == 0) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCascadeOpacityEnabled'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setCascadeOpacityEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAttachedNodeCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCascadeOpacityEnabled'", nullptr); return 0; } - auto&& ret = ax::Node::getAttachedNodeCount(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setCascadeOpacityEnabled(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Node:getAttachedNodeCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCascadeOpacityEnabled",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAttachedNodeCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCascadeOpacityEnabled'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Node_constructor(lua_State* tolua_S) +int lua_ax_base_Node_getColor(lua_State* tolua_S) { int argc = 0; ax::Node* cobj = nullptr; @@ -11726,204 +11874,46 @@ int lua_ax_base_Node_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getColor'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getColor'", nullptr); return 0; } - cobj = new ax::Node(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Node"); + auto&& ret = cobj->getColor(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:Node",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getColor",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getColor'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Node_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Node)"); - return 0; -} - -int lua_register_ax_base_Node(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Node"); - tolua_cclass(tolua_S,"Node","ax.Node","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"Node"); - tolua_function(tolua_S,"new",lua_ax_base_Node_constructor); - tolua_function(tolua_S,"getDescription",lua_ax_base_Node_getDescription); - tolua_function(tolua_S,"setLocalZOrder",lua_ax_base_Node_setLocalZOrder); - tolua_function(tolua_S,"updateOrderOfArrival",lua_ax_base_Node_updateOrderOfArrival); - tolua_function(tolua_S,"getLocalZOrder",lua_ax_base_Node_getLocalZOrder); - tolua_function(tolua_S,"setGlobalZOrder",lua_ax_base_Node_setGlobalZOrder); - tolua_function(tolua_S,"getGlobalZOrder",lua_ax_base_Node_getGlobalZOrder); - tolua_function(tolua_S,"setScaleX",lua_ax_base_Node_setScaleX); - tolua_function(tolua_S,"getScaleX",lua_ax_base_Node_getScaleX); - tolua_function(tolua_S,"setScaleY",lua_ax_base_Node_setScaleY); - tolua_function(tolua_S,"getScaleY",lua_ax_base_Node_getScaleY); - tolua_function(tolua_S,"setScaleZ",lua_ax_base_Node_setScaleZ); - tolua_function(tolua_S,"getScaleZ",lua_ax_base_Node_getScaleZ); - tolua_function(tolua_S,"setScale",lua_ax_base_Node_setScale); - tolua_function(tolua_S,"getScale",lua_ax_base_Node_getScale); - tolua_function(tolua_S,"setPosition",lua_ax_base_Node_setPosition); - tolua_function(tolua_S,"setPositionNormalized",lua_ax_base_Node_setPositionNormalized); - tolua_function(tolua_S,"setNormalizedPosition",lua_ax_base_Node_setNormalizedPosition); - tolua_function(tolua_S,"getPositionNormalized",lua_ax_base_Node_getPositionNormalized); - tolua_function(tolua_S,"getNormalizedPosition",lua_ax_base_Node_getNormalizedPosition); - tolua_function(tolua_S,"setPositionX",lua_ax_base_Node_setPositionX); - tolua_function(tolua_S,"getPositionX",lua_ax_base_Node_getPositionX); - tolua_function(tolua_S,"setPositionY",lua_ax_base_Node_setPositionY); - tolua_function(tolua_S,"getPositionY",lua_ax_base_Node_getPositionY); - tolua_function(tolua_S,"setPosition3D",lua_ax_base_Node_setPosition3D); - tolua_function(tolua_S,"getPosition3D",lua_ax_base_Node_getPosition3D); - tolua_function(tolua_S,"setPositionZ",lua_ax_base_Node_setPositionZ); - tolua_function(tolua_S,"getPositionZ",lua_ax_base_Node_getPositionZ); - tolua_function(tolua_S,"setSkewX",lua_ax_base_Node_setSkewX); - tolua_function(tolua_S,"getSkewX",lua_ax_base_Node_getSkewX); - tolua_function(tolua_S,"setSkewY",lua_ax_base_Node_setSkewY); - tolua_function(tolua_S,"getSkewY",lua_ax_base_Node_getSkewY); - tolua_function(tolua_S,"getAnchorPoint",lua_ax_base_Node_getAnchorPoint); - tolua_function(tolua_S,"getAnchorPointInPoints",lua_ax_base_Node_getAnchorPointInPoints); - tolua_function(tolua_S,"getContentSize",lua_ax_base_Node_getContentSize); - tolua_function(tolua_S,"hitTest",lua_ax_base_Node_hitTest); - tolua_function(tolua_S,"setVisible",lua_ax_base_Node_setVisible); - tolua_function(tolua_S,"isVisible",lua_ax_base_Node_isVisible); - tolua_function(tolua_S,"setRotation",lua_ax_base_Node_setRotation); - tolua_function(tolua_S,"getRotation",lua_ax_base_Node_getRotation); - tolua_function(tolua_S,"setRotation3D",lua_ax_base_Node_setRotation3D); - tolua_function(tolua_S,"getRotation3D",lua_ax_base_Node_getRotation3D); - tolua_function(tolua_S,"setRotationSkewX",lua_ax_base_Node_setRotationSkewX); - tolua_function(tolua_S,"getRotationSkewX",lua_ax_base_Node_getRotationSkewX); - tolua_function(tolua_S,"setRotationSkewY",lua_ax_base_Node_setRotationSkewY); - tolua_function(tolua_S,"getRotationSkewY",lua_ax_base_Node_getRotationSkewY); - tolua_function(tolua_S,"setIgnoreAnchorPointForPosition",lua_ax_base_Node_setIgnoreAnchorPointForPosition); - tolua_function(tolua_S,"isIgnoreAnchorPointForPosition",lua_ax_base_Node_isIgnoreAnchorPointForPosition); - tolua_function(tolua_S,"addChild",lua_ax_base_Node_addChild); - tolua_function(tolua_S,"getChildByTag",lua_ax_base_Node_getChildByTag); - tolua_function(tolua_S,"getChildByName",lua_ax_base_Node_getChildByName); - tolua_function(tolua_S,"getChildren",lua_ax_base_Node_getChildren); - tolua_function(tolua_S,"getChildrenCount",lua_ax_base_Node_getChildrenCount); - tolua_function(tolua_S,"setParent",lua_ax_base_Node_setParent); - tolua_function(tolua_S,"getParent",lua_ax_base_Node_getParent); - tolua_function(tolua_S,"removeFromParent",lua_ax_base_Node_removeFromParentAndCleanup); - tolua_function(tolua_S,"removeChild",lua_ax_base_Node_removeChild); - tolua_function(tolua_S,"removeChildByTag",lua_ax_base_Node_removeChildByTag); - tolua_function(tolua_S,"removeChildByName",lua_ax_base_Node_removeChildByName); - tolua_function(tolua_S,"removeAllChildren",lua_ax_base_Node_removeAllChildrenWithCleanup); - tolua_function(tolua_S,"reorderChild",lua_ax_base_Node_reorderChild); - tolua_function(tolua_S,"sortAllChildren",lua_ax_base_Node_sortAllChildren); - tolua_function(tolua_S,"getTag",lua_ax_base_Node_getTag); - tolua_function(tolua_S,"setTag",lua_ax_base_Node_setTag); - tolua_function(tolua_S,"getName",lua_ax_base_Node_getName); - tolua_function(tolua_S,"setName",lua_ax_base_Node_setName); - tolua_function(tolua_S,"setUserObject",lua_ax_base_Node_setUserObject); - tolua_function(tolua_S,"isRunning",lua_ax_base_Node_isRunning); - tolua_function(tolua_S,"cleanup",lua_ax_base_Node_cleanup); - tolua_function(tolua_S,"draw",lua_ax_base_Node_draw); - tolua_function(tolua_S,"visit",lua_ax_base_Node_visit); - tolua_function(tolua_S,"getScene",lua_ax_base_Node_getScene); - tolua_function(tolua_S,"getBoundingBox",lua_ax_base_Node_getBoundingBox); - tolua_function(tolua_S,"setEventDispatcher",lua_ax_base_Node_setEventDispatcher); - tolua_function(tolua_S,"getEventDispatcher",lua_ax_base_Node_getEventDispatcher); - tolua_function(tolua_S,"setActionManager",lua_ax_base_Node_setActionManager); - tolua_function(tolua_S,"getActionManager",lua_ax_base_Node_getActionManager); - tolua_function(tolua_S,"runAction",lua_ax_base_Node_runAction); - tolua_function(tolua_S,"stopAllActions",lua_ax_base_Node_stopAllActions); - tolua_function(tolua_S,"stopAction",lua_ax_base_Node_stopAction); - tolua_function(tolua_S,"stopActionByTag",lua_ax_base_Node_stopActionByTag); - tolua_function(tolua_S,"stopAllActionsByTag",lua_ax_base_Node_stopAllActionsByTag); - tolua_function(tolua_S,"stopActionsByFlags",lua_ax_base_Node_stopActionsByFlags); - tolua_function(tolua_S,"getActionByTag",lua_ax_base_Node_getActionByTag); - tolua_function(tolua_S,"getNumberOfRunningActions",lua_ax_base_Node_getNumberOfRunningActions); - tolua_function(tolua_S,"getNumberOfRunningActionsByTag",lua_ax_base_Node_getNumberOfRunningActionsByTag); - tolua_function(tolua_S,"setScheduler",lua_ax_base_Node_setScheduler); - tolua_function(tolua_S,"getScheduler",lua_ax_base_Node_getScheduler); - tolua_function(tolua_S,"isScheduled",lua_ax_base_Node_isScheduled); - tolua_function(tolua_S,"resume",lua_ax_base_Node_resume); - tolua_function(tolua_S,"pause",lua_ax_base_Node_pause); - tolua_function(tolua_S,"update",lua_ax_base_Node_update); - tolua_function(tolua_S,"updateTransform",lua_ax_base_Node_updateTransform); - tolua_function(tolua_S,"getNodeToParentTransform",lua_ax_base_Node_getNodeToParentTransform); - tolua_function(tolua_S,"getNodeToParentAffineTransform",lua_ax_base_Node_getNodeToParentAffineTransform); - tolua_function(tolua_S,"setNodeToParentTransform",lua_ax_base_Node_setNodeToParentTransform); - tolua_function(tolua_S,"getParentToNodeTransform",lua_ax_base_Node_getParentToNodeTransform); - tolua_function(tolua_S,"getParentToNodeAffineTransform",lua_ax_base_Node_getParentToNodeAffineTransform); - tolua_function(tolua_S,"getNodeToWorldTransform",lua_ax_base_Node_getNodeToWorldTransform); - tolua_function(tolua_S,"getNodeToWorldAffineTransform",lua_ax_base_Node_getNodeToWorldAffineTransform); - tolua_function(tolua_S,"getWorldToNodeTransform",lua_ax_base_Node_getWorldToNodeTransform); - tolua_function(tolua_S,"getWorldToNodeAffineTransform",lua_ax_base_Node_getWorldToNodeAffineTransform); - tolua_function(tolua_S,"convertToNodeSpace",lua_ax_base_Node_convertToNodeSpace); - tolua_function(tolua_S,"convertToWorldSpace",lua_ax_base_Node_convertToWorldSpace); - tolua_function(tolua_S,"convertToNodeSpaceAR",lua_ax_base_Node_convertToNodeSpaceAR); - tolua_function(tolua_S,"convertToWorldSpaceAR",lua_ax_base_Node_convertToWorldSpaceAR); - tolua_function(tolua_S,"convertTouchToNodeSpace",lua_ax_base_Node_convertTouchToNodeSpace); - tolua_function(tolua_S,"convertTouchToNodeSpaceAR",lua_ax_base_Node_convertTouchToNodeSpaceAR); - tolua_function(tolua_S,"getWorldPosition",lua_ax_base_Node_getWorldPosition); - tolua_function(tolua_S,"setWorldPosition",lua_ax_base_Node_setWorldPosition); - tolua_function(tolua_S,"getComponent",lua_ax_base_Node_getComponent); - tolua_function(tolua_S,"addComponent",lua_ax_base_Node_addComponent); - tolua_function(tolua_S,"removeComponent",lua_ax_base_Node_removeComponent); - tolua_function(tolua_S,"removeAllComponents",lua_ax_base_Node_removeAllComponents); - tolua_function(tolua_S,"getOpacity",lua_ax_base_Node_getOpacity); - tolua_function(tolua_S,"getDisplayedOpacity",lua_ax_base_Node_getDisplayedOpacity); - tolua_function(tolua_S,"setOpacity",lua_ax_base_Node_setOpacity); - tolua_function(tolua_S,"updateDisplayedOpacity",lua_ax_base_Node_updateDisplayedOpacity); - tolua_function(tolua_S,"isCascadeOpacityEnabled",lua_ax_base_Node_isCascadeOpacityEnabled); - tolua_function(tolua_S,"setCascadeOpacityEnabled",lua_ax_base_Node_setCascadeOpacityEnabled); - tolua_function(tolua_S,"getColor",lua_ax_base_Node_getColor); - tolua_function(tolua_S,"getDisplayedColor",lua_ax_base_Node_getDisplayedColor); - tolua_function(tolua_S,"setColor",lua_ax_base_Node_setColor); - tolua_function(tolua_S,"updateDisplayedColor",lua_ax_base_Node_updateDisplayedColor); - tolua_function(tolua_S,"isCascadeColorEnabled",lua_ax_base_Node_isCascadeColorEnabled); - tolua_function(tolua_S,"setCascadeColorEnabled",lua_ax_base_Node_setCascadeColorEnabled); - tolua_function(tolua_S,"setOpacityModifyRGB",lua_ax_base_Node_setOpacityModifyRGB); - tolua_function(tolua_S,"isOpacityModifyRGB",lua_ax_base_Node_isOpacityModifyRGB); - tolua_function(tolua_S,"setOnEnterCallback",lua_ax_base_Node_setOnEnterCallback); - tolua_function(tolua_S,"setOnExitCallback",lua_ax_base_Node_setOnExitCallback); - tolua_function(tolua_S,"setOnEnterTransitionDidFinishCallback",lua_ax_base_Node_setOnEnterTransitionDidFinishCallback); - tolua_function(tolua_S,"getOnEnterTransitionDidFinishCallback",lua_ax_base_Node_getOnEnterTransitionDidFinishCallback); - tolua_function(tolua_S,"setOnExitTransitionDidStartCallback",lua_ax_base_Node_setOnExitTransitionDidStartCallback); - tolua_function(tolua_S,"getOnExitTransitionDidStartCallback",lua_ax_base_Node_getOnExitTransitionDidStartCallback); - tolua_function(tolua_S,"getCameraMask",lua_ax_base_Node_getCameraMask); - tolua_function(tolua_S,"setCameraMask",lua_ax_base_Node_setCameraMask); - tolua_function(tolua_S,"applyMaskOnEnter",lua_ax_base_Node_applyMaskOnEnter); - tolua_function(tolua_S,"setProgramState",lua_ax_base_Node_setProgramState); - tolua_function(tolua_S,"setProgramStateWithRegistry",lua_ax_base_Node_setProgramStateWithRegistry); - tolua_function(tolua_S,"setProgramStateByProgramId",lua_ax_base_Node_setProgramStateByProgramId); - tolua_function(tolua_S,"getProgramState",lua_ax_base_Node_getProgramState); - tolua_function(tolua_S,"updateProgramStateTexture",lua_ax_base_Node_updateProgramStateTexture); - tolua_function(tolua_S,"resetChild",lua_ax_base_Node_resetChild); - tolua_function(tolua_S,"init",lua_ax_base_Node_init); - tolua_function(tolua_S,"initLayer",lua_ax_base_Node_initLayer); - tolua_function(tolua_S,"setPhysicsBody",lua_ax_base_Node_setPhysicsBody); - tolua_function(tolua_S,"getPhysicsBody",lua_ax_base_Node_getPhysicsBody); - tolua_function(tolua_S,"create", lua_ax_base_Node_create); - tolua_function(tolua_S,"getAttachedNodeCount", lua_ax_base_Node_getAttachedNodeCount); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Node).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Node"; - g_typeCast[typeName] = "ax.Node"; - return 1; -} - -int lua_ax_base_Scene_getDefaultCamera(lua_State* tolua_S) +int lua_ax_base_Node_getDisplayedColor(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -11932,45 +11922,45 @@ int lua_ax_base_Scene_getDefaultCamera(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_getDefaultCamera'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getDisplayedColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_getDefaultCamera'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getDisplayedColor'", nullptr); return 0; } - auto&& ret = cobj->getDefaultCamera(); - object_to_luaval(tolua_S, "ax.Camera",(ax::Camera*)ret); + auto&& ret = cobj->getDisplayedColor(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:getDefaultCamera",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getDisplayedColor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_getDefaultCamera'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getDisplayedColor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_render(lua_State* tolua_S) +int lua_ax_base_Node_setColor(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -11979,71 +11969,48 @@ int lua_ax_base_Scene_render(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_render'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - ax::Renderer* arg0; - ax::Mat4 arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Scene:render"); - - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Scene:render"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_render'", nullptr); - return 0; - } - cobj->render(arg0, arg1); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 3) + if (argc == 1) { - ax::Renderer* arg0; - ax::Mat4 arg1; - const ax::Mat4* arg2; - - ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Scene:render"); - - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Scene:render"); + ax::Color32 arg0; - ok &= luaval_to_object(tolua_S, 4, "ax.Mat4",&arg2, "ax.Scene:render"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Node:setColor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_render'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setColor'", nullptr); return 0; } - cobj->render(arg0, arg1, arg2); + cobj->setColor(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:render",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setColor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_render'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setColor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_initWithSize(lua_State* tolua_S) +int lua_ax_base_Node_updateDisplayedColor(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12052,48 +12019,48 @@ int lua_ax_base_Scene_initWithSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initWithSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateDisplayedColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec2 arg0; + ax::Color32 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Scene:initWithSize"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Node:updateDisplayedColor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initWithSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateDisplayedColor'", nullptr); return 0; } - auto&& ret = cobj->initWithSize(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->updateDisplayedColor(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initWithSize",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateDisplayedColor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initWithSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateDisplayedColor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_setCameraOrderDirty(lua_State* tolua_S) +int lua_ax_base_Node_isCascadeColorEnabled(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12102,45 +12069,45 @@ int lua_ax_base_Scene_setCameraOrderDirty(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_setCameraOrderDirty'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isCascadeColorEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_setCameraOrderDirty'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isCascadeColorEnabled'", nullptr); return 0; } - cobj->setCameraOrderDirty(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isCascadeColorEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:setCameraOrderDirty",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isCascadeColorEnabled",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_setCameraOrderDirty'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isCascadeColorEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_onProjectionChanged(lua_State* tolua_S) +int lua_ax_base_Node_setCascadeColorEnabled(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12149,48 +12116,48 @@ int lua_ax_base_Scene_onProjectionChanged(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_onProjectionChanged'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCascadeColorEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::EventCustom* arg0; + bool arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.EventCustom",&arg0, "ax.Scene:onProjectionChanged"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setCascadeColorEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_onProjectionChanged'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCascadeColorEnabled'", nullptr); return 0; } - cobj->onProjectionChanged(arg0); + cobj->setCascadeColorEnabled(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:onProjectionChanged",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCascadeColorEnabled",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_onProjectionChanged'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCascadeColorEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_initWithPhysics(lua_State* tolua_S) +int lua_ax_base_Node_setOpacityModifyRGB(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12199,45 +12166,48 @@ int lua_ax_base_Scene_initWithPhysics(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initWithPhysics'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOpacityModifyRGB'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:setOpacityModifyRGB"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initWithPhysics'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOpacityModifyRGB'", nullptr); return 0; } - auto&& ret = cobj->initWithPhysics(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setOpacityModifyRGB(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initWithPhysics",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOpacityModifyRGB",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initWithPhysics'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOpacityModifyRGB'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_initPhysicsWorld(lua_State* tolua_S) +int lua_ax_base_Node_isOpacityModifyRGB(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12246,45 +12216,45 @@ int lua_ax_base_Scene_initPhysicsWorld(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initPhysicsWorld'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_isOpacityModifyRGB'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initPhysicsWorld'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_isOpacityModifyRGB'", nullptr); return 0; } - auto&& ret = cobj->initPhysicsWorld(); + auto&& ret = cobj->isOpacityModifyRGB(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initPhysicsWorld",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:isOpacityModifyRGB",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initPhysicsWorld'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_isOpacityModifyRGB'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_fixedUpdate(lua_State* tolua_S) +int lua_ax_base_Node_setOnEnterCallback(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12293,48 +12263,52 @@ int lua_ax_base_Scene_fixedUpdate(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_fixedUpdate'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnEnterCallback'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + std::function arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scene:fixedUpdate"); + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_fixedUpdate'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnEnterCallback'", nullptr); return 0; } - cobj->fixedUpdate(arg0); + cobj->setOnEnterCallback(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:fixedUpdate",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnEnterCallback",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_fixedUpdate'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnEnterCallback'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_stepPhysicsAndNavigation(lua_State* tolua_S) +int lua_ax_base_Node_setOnExitCallback(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12343,152 +12317,153 @@ int lua_ax_base_Scene_stepPhysicsAndNavigation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnExitCallback'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + std::function arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scene:stepPhysicsAndNavigation"); + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnExitCallback'", nullptr); return 0; } - cobj->stepPhysicsAndNavigation(arg0); + cobj->setOnExitCallback(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:stepPhysicsAndNavigation",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnExitCallback",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnExitCallback'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scene_create(lua_State* tolua_S) +int lua_ax_base_Node_setOnEnterTransitionDidFinishCallback(lua_State* tolua_S) { int argc = 0; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_create'", nullptr); - return 0; - } - auto&& ret = ax::Scene::create(); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:create",argc, 0); - return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_create'.",&tolua_err); + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - return 0; -} -int lua_ax_base_Scene_createWithSize(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'", nullptr); + return 0; + } #endif - argc = lua_gettop(tolua_S) - 1; - + argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Scene:createWithSize"); + std::function arg0; + + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_createWithSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'", nullptr); return 0; } - auto&& ret = ax::Scene::createWithSize(arg0); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + cobj->setOnEnterTransitionDidFinishCallback(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:createWithSize",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnEnterTransitionDidFinishCallback",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_createWithSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnEnterTransitionDidFinishCallback'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Scene_createWithPhysics(lua_State* tolua_S) +int lua_ax_base_Node_getOnEnterTransitionDidFinishCallback(lua_State* tolua_S) { int argc = 0; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_createWithPhysics'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'", nullptr); return 0; } - auto&& ret = ax::Scene::createWithPhysics(); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + auto&& ret = cobj->getOnEnterTransitionDidFinishCallback(); + #pragma warning NO CONVERSION FROM NATIVE FOR std::function; return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:createWithPhysics",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOnEnterTransitionDidFinishCallback",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_createWithPhysics'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOnEnterTransitionDidFinishCallback'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Scene_constructor(lua_State* tolua_S) +int lua_ax_base_Node_setOnExitTransitionDidStartCallback(lua_State* tolua_S) { int argc = 0; - ax::Scene* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12496,68 +12471,53 @@ int lua_ax_base_Scene_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::function arg0; + + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'", nullptr); return 0; } - cobj = new ax::Scene(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Scene"); + cobj->setOnExitTransitionDidStartCallback(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:Scene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setOnExitTransitionDidStartCallback",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setOnExitTransitionDidStartCallback'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Scene_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Scene)"); - return 0; -} - -int lua_register_ax_base_Scene(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Scene"); - tolua_cclass(tolua_S,"Scene","ax.Scene","ax.Node",nullptr); - - tolua_beginmodule(tolua_S,"Scene"); - tolua_function(tolua_S,"new",lua_ax_base_Scene_constructor); - tolua_function(tolua_S,"getDefaultCamera",lua_ax_base_Scene_getDefaultCamera); - tolua_function(tolua_S,"render",lua_ax_base_Scene_render); - tolua_function(tolua_S,"initWithSize",lua_ax_base_Scene_initWithSize); - tolua_function(tolua_S,"setCameraOrderDirty",lua_ax_base_Scene_setCameraOrderDirty); - tolua_function(tolua_S,"onProjectionChanged",lua_ax_base_Scene_onProjectionChanged); - tolua_function(tolua_S,"initWithPhysics",lua_ax_base_Scene_initWithPhysics); - tolua_function(tolua_S,"initPhysicsWorld",lua_ax_base_Scene_initPhysicsWorld); - tolua_function(tolua_S,"fixedUpdate",lua_ax_base_Scene_fixedUpdate); - tolua_function(tolua_S,"stepPhysicsAndNavigation",lua_ax_base_Scene_stepPhysicsAndNavigation); - tolua_function(tolua_S,"create", lua_ax_base_Scene_create); - tolua_function(tolua_S,"createWithSize", lua_ax_base_Scene_createWithSize); - tolua_function(tolua_S,"createWithPhysics", lua_ax_base_Scene_createWithPhysics); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Scene).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Scene"; - g_typeCast[typeName] = "ax.Scene"; - return 1; -} - -int lua_ax_base_RenderView_end(lua_State* tolua_S) +int lua_ax_base_Node_getOnExitTransitionDidStartCallback(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12566,45 +12526,45 @@ int lua_ax_base_RenderView_end(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_end'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_end'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'", nullptr); return 0; } - cobj->end(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getOnExitTransitionDidStartCallback(); + #pragma warning NO CONVERSION FROM NATIVE FOR std::function; return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:end",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getOnExitTransitionDidStartCallback",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_end'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getOnExitTransitionDidStartCallback'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_isGfxContextReady(lua_State* tolua_S) +int lua_ax_base_Node_getCameraMask(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12613,45 +12573,45 @@ int lua_ax_base_RenderView_isGfxContextReady(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isGfxContextReady'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getCameraMask'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isGfxContextReady'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getCameraMask'", nullptr); return 0; } - auto&& ret = cobj->isGfxContextReady(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getCameraMask(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isGfxContextReady",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getCameraMask",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isGfxContextReady'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getCameraMask'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_swapBuffers(lua_State* tolua_S) +int lua_ax_base_Node_setCameraMask(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12660,45 +12620,65 @@ int lua_ax_base_RenderView_swapBuffers(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_swapBuffers'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setCameraMask'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + unsigned short arg0; + + ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.Node:setCameraMask"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_swapBuffers'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCameraMask'", nullptr); return 0; } - cobj->swapBuffers(); + cobj->setCameraMask(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:swapBuffers",argc, 0); + if (argc == 2) + { + unsigned short arg0; + bool arg1; + + ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.Node:setCameraMask"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:setCameraMask"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setCameraMask'", nullptr); + return 0; + } + cobj->setCameraMask(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setCameraMask",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_swapBuffers'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setCameraMask'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setIMEKeyboardState(lua_State* tolua_S) +int lua_ax_base_Node_applyMaskOnEnter(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12707,95 +12687,119 @@ int lua_ax_base_RenderView_setIMEKeyboardState(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setIMEKeyboardState'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_applyMaskOnEnter'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setIMEKeyboardState"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Node:applyMaskOnEnter"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setIMEKeyboardState'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_applyMaskOnEnter'", nullptr); return 0; } - cobj->setIMEKeyboardState(arg0); + cobj->applyMaskOnEnter(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setIMEKeyboardState",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:applyMaskOnEnter",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setIMEKeyboardState'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_applyMaskOnEnter'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_windowShouldClose(lua_State* tolua_S) +int lua_ax_base_Node_setProgramState(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_windowShouldClose'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramState'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_windowShouldClose'", nullptr); - return 0; + do{ + if (argc == 1) { + ax::rhi::ProgramState* arg0; + ok &= luaval_to_object(tolua_S, 2, "axrhi.ProgramState",&arg0, "ax.Node:setProgramState"); + + if (!ok) { break; } + bool ret = cobj->setProgramState(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - auto&& ret = cobj->windowShouldClose(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:windowShouldClose",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + ax::rhi::ProgramState* arg0; + ok &= luaval_to_object(tolua_S, 2, "axrhi.ProgramState",&arg0, "ax.Node:setProgramState"); + + if (!ok) { break; } + bool arg1; + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:setProgramState"); + + if (!ok) { break; } + bool ret = cobj->setProgramState(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + unsigned int arg0; + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:setProgramState"); + + if (!ok) { break; } + cobj->setProgramState(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramState",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_windowShouldClose'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramState'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_pollEvents(lua_State* tolua_S) +int lua_ax_base_Node_setProgramStateWithRegistry(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12804,45 +12808,51 @@ int lua_ax_base_RenderView_pollEvents(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_pollEvents'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramStateWithRegistry'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + unsigned int arg0; + ax::Texture2D* arg1; + + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Node:setProgramStateWithRegistry"); + + ok &= luaval_to_object(tolua_S, 3, "ax.Texture2D",&arg1, "ax.Node:setProgramStateWithRegistry"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_pollEvents'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setProgramStateWithRegistry'", nullptr); return 0; } - cobj->pollEvents(); + cobj->setProgramStateWithRegistry(arg0, arg1); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:pollEvents",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramStateWithRegistry",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_pollEvents'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramStateWithRegistry'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getFrameSize(lua_State* tolua_S) +int lua_ax_base_Node_setProgramStateByProgramId(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12851,45 +12861,48 @@ int lua_ax_base_RenderView_getFrameSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getFrameSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setProgramStateByProgramId'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + unsigned long long arg0; + + ok &= luaval_to_long_long(tolua_S, 2,(long long*)&arg0, "ax.Node:setProgramStateByProgramId"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getFrameSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setProgramStateByProgramId'", nullptr); return 0; } - auto&& ret = cobj->getFrameSize(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->setProgramStateByProgramId(arg0); + object_to_luaval(tolua_S, "axrhi.ProgramState",(ax::rhi::ProgramState*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getFrameSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setProgramStateByProgramId",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getFrameSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setProgramStateByProgramId'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setFrameSize(lua_State* tolua_S) +int lua_ax_base_Node_getProgramState(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12898,51 +12911,45 @@ int lua_ax_base_RenderView_setFrameSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setFrameSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getProgramState'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - double arg0; - double arg1; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setFrameSize"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setFrameSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setFrameSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getProgramState'", nullptr); return 0; } - cobj->setFrameSize(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getProgramState(); + object_to_luaval(tolua_S, "axrhi.ProgramState",(ax::rhi::ProgramState*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setFrameSize",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getProgramState",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setFrameSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getProgramState'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setFrameZoomFactor(lua_State* tolua_S) +int lua_ax_base_Node_updateProgramStateTexture(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -12951,48 +12958,48 @@ int lua_ax_base_RenderView_setFrameZoomFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setFrameZoomFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_updateProgramStateTexture'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + ax::Texture2D* arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setFrameZoomFactor"); + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.Node:updateProgramStateTexture"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setFrameZoomFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_updateProgramStateTexture'", nullptr); return 0; } - cobj->setFrameZoomFactor(arg0); + cobj->updateProgramStateTexture(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setFrameZoomFactor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:updateProgramStateTexture",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setFrameZoomFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_updateProgramStateTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getFrameZoomFactor(lua_State* tolua_S) +int lua_ax_base_Node_resetChild(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13001,45 +13008,51 @@ int lua_ax_base_RenderView_getFrameZoomFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getFrameZoomFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_resetChild'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::Node* arg0; + bool arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Node:resetChild"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Node:resetChild"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getFrameZoomFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_resetChild'", nullptr); return 0; } - auto&& ret = cobj->getFrameZoomFactor(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->resetChild(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getFrameZoomFactor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:resetChild",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getFrameZoomFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_resetChild'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setCursorVisible(lua_State* tolua_S) +int lua_ax_base_Node_init(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13048,48 +13061,45 @@ int lua_ax_base_RenderView_setCursorVisible(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setCursorVisible'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_init'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setCursorVisible"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setCursorVisible'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_init'", nullptr); return 0; } - cobj->setCursorVisible(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->init(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setCursorVisible",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:init",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setCursorVisible'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_init'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getRetinaFactor(lua_State* tolua_S) +int lua_ax_base_Node_initLayer(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13098,45 +13108,45 @@ int lua_ax_base_RenderView_getRetinaFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getRetinaFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_initLayer'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getRetinaFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_initLayer'", nullptr); return 0; } - auto&& ret = cobj->getRetinaFactor(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->initLayer(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getRetinaFactor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:initLayer",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getRetinaFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_initLayer'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setContentScaleFactor(lua_State* tolua_S) +int lua_ax_base_Node_setPhysicsBody(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13145,48 +13155,48 @@ int lua_ax_base_RenderView_setContentScaleFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_setPhysicsBody'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + ax::PhysicsBody* arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setContentScaleFactor"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.Node:setPhysicsBody"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_setPhysicsBody'", nullptr); return 0; } - auto&& ret = cobj->setContentScaleFactor(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setPhysicsBody(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setContentScaleFactor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:setPhysicsBody",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setContentScaleFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_setPhysicsBody'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getContentScaleFactor(lua_State* tolua_S) +int lua_ax_base_Node_getPhysicsBody(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Node* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13195,139 +13205,318 @@ int lua_ax_base_RenderView_getContentScaleFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Node*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Node_getPhysicsBody'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getPhysicsBody'", nullptr); return 0; } - auto&& ret = cobj->getContentScaleFactor(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getPhysicsBody(); + object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getContentScaleFactor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:getPhysicsBody",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getContentScaleFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getPhysicsBody'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_isRetinaDisplay(lua_State* tolua_S) +int lua_ax_base_Node_create(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isRetinaDisplay'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isRetinaDisplay'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_create'", nullptr); return 0; } - auto&& ret = cobj->isRetinaDisplay(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = ax::Node::create(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isRetinaDisplay",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Node:create",argc, 0); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isRetinaDisplay'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_RenderView_getVisibleSize(lua_State* tolua_S) +int lua_ax_base_Node_getAttachedNodeCount(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Node",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 0) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleSize'", nullptr); - return 0; + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_getAttachedNodeCount'", nullptr); + return 0; + } + auto&& ret = ax::Node::getAttachedNodeCount(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Node:getAttachedNodeCount",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_getAttachedNodeCount'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_Node_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::Node* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Node_constructor'", nullptr); return 0; } - auto&& ret = cobj->getVisibleSize(); - vec2_to_luaval(tolua_S, ret); + cobj = new ax::Node(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Node"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Node:Node",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Node_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getVisibleOrigin(lua_State* tolua_S) + +static int lua_ax_base_Node_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Node)"); + return 0; +} + +int lua_register_ax_base_Node(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Node"); + tolua_cclass(tolua_S,"Node","ax.Node","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Node"); + tolua_function(tolua_S,"new",lua_ax_base_Node_constructor); + tolua_function(tolua_S,"getDescription",lua_ax_base_Node_getDescription); + tolua_function(tolua_S,"setLocalZOrder",lua_ax_base_Node_setLocalZOrder); + tolua_function(tolua_S,"updateOrderOfArrival",lua_ax_base_Node_updateOrderOfArrival); + tolua_function(tolua_S,"getLocalZOrder",lua_ax_base_Node_getLocalZOrder); + tolua_function(tolua_S,"setGlobalZOrder",lua_ax_base_Node_setGlobalZOrder); + tolua_function(tolua_S,"getGlobalZOrder",lua_ax_base_Node_getGlobalZOrder); + tolua_function(tolua_S,"setScaleX",lua_ax_base_Node_setScaleX); + tolua_function(tolua_S,"getScaleX",lua_ax_base_Node_getScaleX); + tolua_function(tolua_S,"setScaleY",lua_ax_base_Node_setScaleY); + tolua_function(tolua_S,"getScaleY",lua_ax_base_Node_getScaleY); + tolua_function(tolua_S,"setScaleZ",lua_ax_base_Node_setScaleZ); + tolua_function(tolua_S,"getScaleZ",lua_ax_base_Node_getScaleZ); + tolua_function(tolua_S,"setScale",lua_ax_base_Node_setScale); + tolua_function(tolua_S,"getScale",lua_ax_base_Node_getScale); + tolua_function(tolua_S,"setPosition",lua_ax_base_Node_setPosition); + tolua_function(tolua_S,"setPositionNormalized",lua_ax_base_Node_setPositionNormalized); + tolua_function(tolua_S,"setNormalizedPosition",lua_ax_base_Node_setNormalizedPosition); + tolua_function(tolua_S,"getPositionNormalized",lua_ax_base_Node_getPositionNormalized); + tolua_function(tolua_S,"getNormalizedPosition",lua_ax_base_Node_getNormalizedPosition); + tolua_function(tolua_S,"setPositionX",lua_ax_base_Node_setPositionX); + tolua_function(tolua_S,"getPositionX",lua_ax_base_Node_getPositionX); + tolua_function(tolua_S,"setPositionY",lua_ax_base_Node_setPositionY); + tolua_function(tolua_S,"getPositionY",lua_ax_base_Node_getPositionY); + tolua_function(tolua_S,"setPosition3D",lua_ax_base_Node_setPosition3D); + tolua_function(tolua_S,"getPosition3D",lua_ax_base_Node_getPosition3D); + tolua_function(tolua_S,"setPositionZ",lua_ax_base_Node_setPositionZ); + tolua_function(tolua_S,"getPositionZ",lua_ax_base_Node_getPositionZ); + tolua_function(tolua_S,"setSkewX",lua_ax_base_Node_setSkewX); + tolua_function(tolua_S,"getSkewX",lua_ax_base_Node_getSkewX); + tolua_function(tolua_S,"setSkewY",lua_ax_base_Node_setSkewY); + tolua_function(tolua_S,"getSkewY",lua_ax_base_Node_getSkewY); + tolua_function(tolua_S,"getAnchorPoint",lua_ax_base_Node_getAnchorPoint); + tolua_function(tolua_S,"getAnchorPointInPoints",lua_ax_base_Node_getAnchorPointInPoints); + tolua_function(tolua_S,"getContentSize",lua_ax_base_Node_getContentSize); + tolua_function(tolua_S,"hitTest",lua_ax_base_Node_hitTest); + tolua_function(tolua_S,"setVisible",lua_ax_base_Node_setVisible); + tolua_function(tolua_S,"isVisible",lua_ax_base_Node_isVisible); + tolua_function(tolua_S,"setRotation",lua_ax_base_Node_setRotation); + tolua_function(tolua_S,"getRotation",lua_ax_base_Node_getRotation); + tolua_function(tolua_S,"setRotation3D",lua_ax_base_Node_setRotation3D); + tolua_function(tolua_S,"getRotation3D",lua_ax_base_Node_getRotation3D); + tolua_function(tolua_S,"setRotationSkewX",lua_ax_base_Node_setRotationSkewX); + tolua_function(tolua_S,"getRotationSkewX",lua_ax_base_Node_getRotationSkewX); + tolua_function(tolua_S,"setRotationSkewY",lua_ax_base_Node_setRotationSkewY); + tolua_function(tolua_S,"getRotationSkewY",lua_ax_base_Node_getRotationSkewY); + tolua_function(tolua_S,"setIgnoreAnchorPointForPosition",lua_ax_base_Node_setIgnoreAnchorPointForPosition); + tolua_function(tolua_S,"isIgnoreAnchorPointForPosition",lua_ax_base_Node_isIgnoreAnchorPointForPosition); + tolua_function(tolua_S,"addChild",lua_ax_base_Node_addChild); + tolua_function(tolua_S,"getChildByTag",lua_ax_base_Node_getChildByTag); + tolua_function(tolua_S,"getChildByName",lua_ax_base_Node_getChildByName); + tolua_function(tolua_S,"getChildren",lua_ax_base_Node_getChildren); + tolua_function(tolua_S,"getChildrenCount",lua_ax_base_Node_getChildrenCount); + tolua_function(tolua_S,"setParent",lua_ax_base_Node_setParent); + tolua_function(tolua_S,"getParent",lua_ax_base_Node_getParent); + tolua_function(tolua_S,"removeFromParent",lua_ax_base_Node_removeFromParentAndCleanup); + tolua_function(tolua_S,"removeChild",lua_ax_base_Node_removeChild); + tolua_function(tolua_S,"removeChildByTag",lua_ax_base_Node_removeChildByTag); + tolua_function(tolua_S,"removeChildByName",lua_ax_base_Node_removeChildByName); + tolua_function(tolua_S,"removeAllChildren",lua_ax_base_Node_removeAllChildrenWithCleanup); + tolua_function(tolua_S,"reorderChild",lua_ax_base_Node_reorderChild); + tolua_function(tolua_S,"sortAllChildren",lua_ax_base_Node_sortAllChildren); + tolua_function(tolua_S,"getTag",lua_ax_base_Node_getTag); + tolua_function(tolua_S,"setTag",lua_ax_base_Node_setTag); + tolua_function(tolua_S,"getName",lua_ax_base_Node_getName); + tolua_function(tolua_S,"setName",lua_ax_base_Node_setName); + tolua_function(tolua_S,"setUserObject",lua_ax_base_Node_setUserObject); + tolua_function(tolua_S,"isRunning",lua_ax_base_Node_isRunning); + tolua_function(tolua_S,"cleanup",lua_ax_base_Node_cleanup); + tolua_function(tolua_S,"draw",lua_ax_base_Node_draw); + tolua_function(tolua_S,"visit",lua_ax_base_Node_visit); + tolua_function(tolua_S,"getScene",lua_ax_base_Node_getScene); + tolua_function(tolua_S,"getBoundingBox",lua_ax_base_Node_getBoundingBox); + tolua_function(tolua_S,"setEventDispatcher",lua_ax_base_Node_setEventDispatcher); + tolua_function(tolua_S,"getEventDispatcher",lua_ax_base_Node_getEventDispatcher); + tolua_function(tolua_S,"setActionManager",lua_ax_base_Node_setActionManager); + tolua_function(tolua_S,"getActionManager",lua_ax_base_Node_getActionManager); + tolua_function(tolua_S,"runAction",lua_ax_base_Node_runAction); + tolua_function(tolua_S,"stopAllActions",lua_ax_base_Node_stopAllActions); + tolua_function(tolua_S,"stopAction",lua_ax_base_Node_stopAction); + tolua_function(tolua_S,"stopActionByTag",lua_ax_base_Node_stopActionByTag); + tolua_function(tolua_S,"stopAllActionsByTag",lua_ax_base_Node_stopAllActionsByTag); + tolua_function(tolua_S,"stopActionsByFlags",lua_ax_base_Node_stopActionsByFlags); + tolua_function(tolua_S,"getActionByTag",lua_ax_base_Node_getActionByTag); + tolua_function(tolua_S,"getNumberOfRunningActions",lua_ax_base_Node_getNumberOfRunningActions); + tolua_function(tolua_S,"getNumberOfRunningActionsByTag",lua_ax_base_Node_getNumberOfRunningActionsByTag); + tolua_function(tolua_S,"setScheduler",lua_ax_base_Node_setScheduler); + tolua_function(tolua_S,"getScheduler",lua_ax_base_Node_getScheduler); + tolua_function(tolua_S,"isScheduled",lua_ax_base_Node_isScheduled); + tolua_function(tolua_S,"resume",lua_ax_base_Node_resume); + tolua_function(tolua_S,"pause",lua_ax_base_Node_pause); + tolua_function(tolua_S,"update",lua_ax_base_Node_update); + tolua_function(tolua_S,"updateTransform",lua_ax_base_Node_updateTransform); + tolua_function(tolua_S,"getNodeToParentTransform",lua_ax_base_Node_getNodeToParentTransform); + tolua_function(tolua_S,"getNodeToParentAffineTransform",lua_ax_base_Node_getNodeToParentAffineTransform); + tolua_function(tolua_S,"setNodeToParentTransform",lua_ax_base_Node_setNodeToParentTransform); + tolua_function(tolua_S,"getParentToNodeTransform",lua_ax_base_Node_getParentToNodeTransform); + tolua_function(tolua_S,"getParentToNodeAffineTransform",lua_ax_base_Node_getParentToNodeAffineTransform); + tolua_function(tolua_S,"getNodeToWorldTransform",lua_ax_base_Node_getNodeToWorldTransform); + tolua_function(tolua_S,"getNodeToWorldAffineTransform",lua_ax_base_Node_getNodeToWorldAffineTransform); + tolua_function(tolua_S,"getWorldToNodeTransform",lua_ax_base_Node_getWorldToNodeTransform); + tolua_function(tolua_S,"getWorldToNodeAffineTransform",lua_ax_base_Node_getWorldToNodeAffineTransform); + tolua_function(tolua_S,"convertToNodeSpace",lua_ax_base_Node_convertToNodeSpace); + tolua_function(tolua_S,"convertToWorldSpace",lua_ax_base_Node_convertToWorldSpace); + tolua_function(tolua_S,"convertToNodeSpaceAR",lua_ax_base_Node_convertToNodeSpaceAR); + tolua_function(tolua_S,"convertToWorldSpaceAR",lua_ax_base_Node_convertToWorldSpaceAR); + tolua_function(tolua_S,"convertTouchToNodeSpace",lua_ax_base_Node_convertTouchToNodeSpace); + tolua_function(tolua_S,"convertTouchToNodeSpaceAR",lua_ax_base_Node_convertTouchToNodeSpaceAR); + tolua_function(tolua_S,"getWorldPosition",lua_ax_base_Node_getWorldPosition); + tolua_function(tolua_S,"setWorldPosition",lua_ax_base_Node_setWorldPosition); + tolua_function(tolua_S,"getComponent",lua_ax_base_Node_getComponent); + tolua_function(tolua_S,"addComponent",lua_ax_base_Node_addComponent); + tolua_function(tolua_S,"removeComponent",lua_ax_base_Node_removeComponent); + tolua_function(tolua_S,"removeAllComponents",lua_ax_base_Node_removeAllComponents); + tolua_function(tolua_S,"getOpacity",lua_ax_base_Node_getOpacity); + tolua_function(tolua_S,"getDisplayedOpacity",lua_ax_base_Node_getDisplayedOpacity); + tolua_function(tolua_S,"setOpacity",lua_ax_base_Node_setOpacity); + tolua_function(tolua_S,"updateDisplayedOpacity",lua_ax_base_Node_updateDisplayedOpacity); + tolua_function(tolua_S,"isCascadeOpacityEnabled",lua_ax_base_Node_isCascadeOpacityEnabled); + tolua_function(tolua_S,"setCascadeOpacityEnabled",lua_ax_base_Node_setCascadeOpacityEnabled); + tolua_function(tolua_S,"getColor",lua_ax_base_Node_getColor); + tolua_function(tolua_S,"getDisplayedColor",lua_ax_base_Node_getDisplayedColor); + tolua_function(tolua_S,"setColor",lua_ax_base_Node_setColor); + tolua_function(tolua_S,"updateDisplayedColor",lua_ax_base_Node_updateDisplayedColor); + tolua_function(tolua_S,"isCascadeColorEnabled",lua_ax_base_Node_isCascadeColorEnabled); + tolua_function(tolua_S,"setCascadeColorEnabled",lua_ax_base_Node_setCascadeColorEnabled); + tolua_function(tolua_S,"setOpacityModifyRGB",lua_ax_base_Node_setOpacityModifyRGB); + tolua_function(tolua_S,"isOpacityModifyRGB",lua_ax_base_Node_isOpacityModifyRGB); + tolua_function(tolua_S,"setOnEnterCallback",lua_ax_base_Node_setOnEnterCallback); + tolua_function(tolua_S,"setOnExitCallback",lua_ax_base_Node_setOnExitCallback); + tolua_function(tolua_S,"setOnEnterTransitionDidFinishCallback",lua_ax_base_Node_setOnEnterTransitionDidFinishCallback); + tolua_function(tolua_S,"getOnEnterTransitionDidFinishCallback",lua_ax_base_Node_getOnEnterTransitionDidFinishCallback); + tolua_function(tolua_S,"setOnExitTransitionDidStartCallback",lua_ax_base_Node_setOnExitTransitionDidStartCallback); + tolua_function(tolua_S,"getOnExitTransitionDidStartCallback",lua_ax_base_Node_getOnExitTransitionDidStartCallback); + tolua_function(tolua_S,"getCameraMask",lua_ax_base_Node_getCameraMask); + tolua_function(tolua_S,"setCameraMask",lua_ax_base_Node_setCameraMask); + tolua_function(tolua_S,"applyMaskOnEnter",lua_ax_base_Node_applyMaskOnEnter); + tolua_function(tolua_S,"setProgramState",lua_ax_base_Node_setProgramState); + tolua_function(tolua_S,"setProgramStateWithRegistry",lua_ax_base_Node_setProgramStateWithRegistry); + tolua_function(tolua_S,"setProgramStateByProgramId",lua_ax_base_Node_setProgramStateByProgramId); + tolua_function(tolua_S,"getProgramState",lua_ax_base_Node_getProgramState); + tolua_function(tolua_S,"updateProgramStateTexture",lua_ax_base_Node_updateProgramStateTexture); + tolua_function(tolua_S,"resetChild",lua_ax_base_Node_resetChild); + tolua_function(tolua_S,"init",lua_ax_base_Node_init); + tolua_function(tolua_S,"initLayer",lua_ax_base_Node_initLayer); + tolua_function(tolua_S,"setPhysicsBody",lua_ax_base_Node_setPhysicsBody); + tolua_function(tolua_S,"getPhysicsBody",lua_ax_base_Node_getPhysicsBody); + tolua_function(tolua_S,"create", lua_ax_base_Node_create); + tolua_function(tolua_S,"getAttachedNodeCount", lua_ax_base_Node_getAttachedNodeCount); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Node).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Node"; + g_typeCast[typeName] = "ax.Node"; + return 1; +} + +int lua_ax_base_Image_initWithImageFile(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13336,45 +13525,48 @@ int lua_ax_base_RenderView_getVisibleOrigin(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleOrigin'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_initWithImageFile'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:initWithImageFile"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleOrigin'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_initWithImageFile'", nullptr); return 0; } - auto&& ret = cobj->getVisibleOrigin(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->initWithImageFile(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleOrigin",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:initWithImageFile",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleOrigin'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_initWithImageFile'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getVisibleRect(lua_State* tolua_S) +int lua_ax_base_Image_flipRawData(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13383,45 +13575,45 @@ int lua_ax_base_RenderView_getVisibleRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_flipRawData'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_flipRawData'", nullptr); return 0; } - auto&& ret = cobj->getVisibleRect(); - rect_to_luaval(tolua_S, ret); + cobj->flipRawData(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:flipRawData",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_flipRawData'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getSafeAreaRect(lua_State* tolua_S) +int lua_ax_base_Image_getFileType(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13430,45 +13622,45 @@ int lua_ax_base_RenderView_getSafeAreaRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getSafeAreaRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getFileType'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getSafeAreaRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getFileType'", nullptr); return 0; } - auto&& ret = cobj->getSafeAreaRect(); - rect_to_luaval(tolua_S, ret); + int ret = (int)cobj->getFileType(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getSafeAreaRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getFileType",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getSafeAreaRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getFileType'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setDesignResolutionSize(lua_State* tolua_S) +int lua_ax_base_Image_getPixelFormat(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13477,54 +13669,45 @@ int lua_ax_base_RenderView_setDesignResolutionSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setDesignResolutionSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getPixelFormat'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 0) { - double arg0; - double arg1; - ResolutionPolicy arg2; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setDesignResolutionSize"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setDesignResolutionSize"); - - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderView:setDesignResolutionSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setDesignResolutionSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getPixelFormat'", nullptr); return 0; } - cobj->setDesignResolutionSize(arg0, arg1, arg2); - lua_settop(tolua_S, 1); + int ret = (int)cobj->getPixelFormat(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setDesignResolutionSize",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getPixelFormat",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setDesignResolutionSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getPixelFormat'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getDesignResolutionSize(lua_State* tolua_S) +int lua_ax_base_Image_getWidth(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13533,45 +13716,45 @@ int lua_ax_base_RenderView_getDesignResolutionSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getDesignResolutionSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getWidth'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getDesignResolutionSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getWidth'", nullptr); return 0; } - auto&& ret = cobj->getDesignResolutionSize(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getWidth(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getDesignResolutionSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getWidth",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getDesignResolutionSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getWidth'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setViewPortInPoints(lua_State* tolua_S) +int lua_ax_base_Image_getHeight(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13580,57 +13763,45 @@ int lua_ax_base_RenderView_setViewPortInPoints(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setViewPortInPoints'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getHeight'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 0) { - double arg0; - double arg1; - double arg2; - double arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setViewPortInPoints"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setViewPortInPoints"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RenderView:setViewPortInPoints"); - - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.RenderView:setViewPortInPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setViewPortInPoints'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getHeight'", nullptr); return 0; } - cobj->setViewPortInPoints(arg0, arg1, arg2, arg3); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getHeight(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setViewPortInPoints",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getHeight",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setViewPortInPoints'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getHeight'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setScissorInPoints(lua_State* tolua_S) +int lua_ax_base_Image_getNumberOfMipmaps(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13639,57 +13810,45 @@ int lua_ax_base_RenderView_setScissorInPoints(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setScissorInPoints'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getNumberOfMipmaps'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 0) { - double arg0; - double arg1; - double arg2; - double arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setScissorInPoints"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setScissorInPoints"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RenderView:setScissorInPoints"); - - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.RenderView:setScissorInPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setScissorInPoints'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getNumberOfMipmaps'", nullptr); return 0; } - cobj->setScissorInPoints(arg0, arg1, arg2, arg3); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getNumberOfMipmaps(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setScissorInPoints",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getNumberOfMipmaps",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setScissorInPoints'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getNumberOfMipmaps'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_isScissorEnabled(lua_State* tolua_S) +int lua_ax_base_Image_hasPremultipliedAlpha(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13698,45 +13857,45 @@ int lua_ax_base_RenderView_isScissorEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isScissorEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_hasPremultipliedAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isScissorEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_hasPremultipliedAlpha'", nullptr); return 0; } - auto&& ret = cobj->isScissorEnabled(); + auto&& ret = cobj->hasPremultipliedAlpha(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isScissorEnabled",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:hasPremultipliedAlpha",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isScissorEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_hasPremultipliedAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getScissorRect(lua_State* tolua_S) +int lua_ax_base_Image_getFilePath(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13745,45 +13904,45 @@ int lua_ax_base_RenderView_getScissorRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScissorRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getFilePath'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScissorRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getFilePath'", nullptr); return 0; } - auto&& ret = cobj->getScissorRect(); - rect_to_luaval(tolua_S, ret); + auto&& ret = cobj->getFilePath(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScissorRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getFilePath",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScissorRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getFilePath'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setViewName(lua_State* tolua_S) +int lua_ax_base_Image_getBitPerPixel(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13792,48 +13951,45 @@ int lua_ax_base_RenderView_setViewName(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setViewName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getBitPerPixel'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.RenderView:setViewName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setViewName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getBitPerPixel'", nullptr); return 0; } - cobj->setViewName(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getBitPerPixel(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setViewName",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getBitPerPixel",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setViewName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getBitPerPixel'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getViewName(lua_State* tolua_S) +int lua_ax_base_Image_hasAlpha(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13842,100 +13998,45 @@ int lua_ax_base_RenderView_getViewName(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getViewName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_hasAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getViewName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_hasAlpha'", nullptr); return 0; } - auto&& ret = cobj->getViewName(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); + auto&& ret = cobj->hasAlpha(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getViewName",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getViewName'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_RenderView_setIcon(lua_State* tolua_S) -{ - int argc = 0; - ax::RenderView* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setIcon'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - std::vector arg0; - ok &= luaval_to_std_vector_string_view(tolua_S, 2, &arg0, "ax.RenderView:setIcon"); - - if (!ok) { break; } - cobj->setIcon(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.RenderView:setIcon"); - - if (!ok) { break; } - cobj->setIcon(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setIcon",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:hasAlpha",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setIcon'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_hasAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_setDefaultIcon(lua_State* tolua_S) +int lua_ax_base_Image_isCompressed(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13944,45 +14045,45 @@ int lua_ax_base_RenderView_setDefaultIcon(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setDefaultIcon'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_isCompressed'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setDefaultIcon'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_isCompressed'", nullptr); return 0; } - cobj->setDefaultIcon(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isCompressed(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setDefaultIcon",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:isCompressed",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setDefaultIcon'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_isCompressed'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getViewPortRect(lua_State* tolua_S) +int lua_ax_base_Image_saveToFile(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -13991,92 +14092,65 @@ int lua_ax_base_RenderView_getViewPortRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getViewPortRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_saveToFile'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:saveToFile"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getViewPortRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_saveToFile'", nullptr); return 0; } - auto&& ret = cobj->getViewPortRect(); - rect_to_luaval(tolua_S, ret); + auto&& ret = cobj->saveToFile(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getViewPortRect",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getViewPortRect'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_RenderView_getScaleX(lua_State* tolua_S) -{ - int argc = 0; - ax::RenderView* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 2) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScaleX'", nullptr); - return 0; - } -#endif + std::string_view arg0; + bool arg1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:saveToFile"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Image:saveToFile"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScaleX'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_saveToFile'", nullptr); return 0; } - auto&& ret = cobj->getScaleX(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->saveToFile(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScaleX",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:saveToFile",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScaleX'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_saveToFile'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getScaleY(lua_State* tolua_S) +int lua_ax_base_Image_premultiplyAlpha(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14085,45 +14159,45 @@ int lua_ax_base_RenderView_getScaleY(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScaleY'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_premultiplyAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScaleY'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_premultiplyAlpha'", nullptr); return 0; } - auto&& ret = cobj->getScaleY(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->premultiplyAlpha(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScaleY",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:premultiplyAlpha",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScaleY'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_premultiplyAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getResolutionPolicy(lua_State* tolua_S) +int lua_ax_base_Image_reversePremultipliedAlpha(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14132,145 +14206,116 @@ int lua_ax_base_RenderView_getResolutionPolicy(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getResolutionPolicy'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_reversePremultipliedAlpha'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getResolutionPolicy'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_reversePremultipliedAlpha'", nullptr); return 0; } - int ret = (int)cobj->getResolutionPolicy(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->reversePremultipliedAlpha(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getResolutionPolicy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:reversePremultipliedAlpha",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getResolutionPolicy'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_reversePremultipliedAlpha'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_renderScene(lua_State* tolua_S) +int lua_ax_base_Image_setPNGPremultipliedAlphaEnabled(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_renderScene'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - ax::Scene* arg0; - ax::Renderer* arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.RenderView:renderScene"); - - ok &= luaval_to_object(tolua_S, 3, "ax.Renderer",&arg1, "ax.RenderView:renderScene"); + bool arg0; + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Image:setPNGPremultipliedAlphaEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_renderScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_setPNGPremultipliedAlphaEnabled'", nullptr); return 0; } - cobj->renderScene(arg0, arg1); + ax::Image::setPNGPremultipliedAlphaEnabled(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:renderScene",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:setPNGPremultipliedAlphaEnabled",argc, 1); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_renderScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_setPNGPremultipliedAlphaEnabled'.",&tolua_err); #endif - return 0; } -int lua_ax_base_RenderView_setInteractive(lua_State* tolua_S) +int lua_ax_base_Image_setCompressedImagesHavePMA(lua_State* tolua_S) { int argc = 0; - ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setInteractive'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setInteractive"); + unsigned int arg0; + bool arg1; + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Image:setCompressedImagesHavePMA"); + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Image:setCompressedImagesHavePMA"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setInteractive'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_setCompressedImagesHavePMA'", nullptr); return 0; } - cobj->setInteractive(arg0); + ax::Image::setCompressedImagesHavePMA(arg0, arg1); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setInteractive",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:setCompressedImagesHavePMA",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setInteractive'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_setCompressedImagesHavePMA'.",&tolua_err); #endif - return 0; } -int lua_ax_base_RenderView_setGfxContextAttrs(lua_State* tolua_S) +int lua_ax_base_Image_isCompressedImageHavePMA(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -14280,127 +14325,111 @@ int lua_ax_base_RenderView_setGfxContextAttrs(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; if (argc == 1) { - GfxContextAttrs arg0; - #pragma warning NO CONVERSION TO NATIVE FOR GfxContextAttrs - ok = false; + unsigned int arg0; + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Image:isCompressedImageHavePMA"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setGfxContextAttrs'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_isCompressedImageHavePMA'", nullptr); return 0; } - ax::RenderView::setGfxContextAttrs(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::Image::isCompressedImageHavePMA(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RenderView:setGfxContextAttrs",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:isCompressedImageHavePMA",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setGfxContextAttrs'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_isCompressedImageHavePMA'.",&tolua_err); #endif return 0; } -int lua_ax_base_RenderView_getGfxContextAttrs(lua_State* tolua_S) +int lua_ax_base_Image_constructor(lua_State* tolua_S) { int argc = 0; + ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; -#endif - argc = lua_gettop(tolua_S) - 1; + argc = lua_gettop(tolua_S)-1; if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getGfxContextAttrs'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_constructor'", nullptr); return 0; } - auto&& ret = ax::RenderView::getGfxContextAttrs(); - #pragma warning NO CONVERSION FROM NATIVE FOR GfxContextAttrs; + cobj = new ax::Image(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Image"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RenderView:getGfxContextAttrs",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:Image",argc, 0); return 0; + #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getGfxContextAttrs'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_constructor'.",&tolua_err); #endif + return 0; } -static int lua_ax_base_RenderView_finalize(lua_State* tolua_S) + +static int lua_ax_base_Image_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (RenderView)"); + AXLOGV("luabindings: finalizing LUA object (Image)"); return 0; } -int lua_register_ax_base_RenderView(lua_State* tolua_S) +int lua_register_ax_base_Image(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.RenderView"); - tolua_cclass(tolua_S,"RenderView","ax.RenderView","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.Image"); + tolua_cclass(tolua_S,"Image","ax.Image","ax.Object",nullptr); - tolua_beginmodule(tolua_S,"RenderView"); - tolua_function(tolua_S,"endToLua",lua_ax_base_RenderView_end); - tolua_function(tolua_S,"isGfxContextReady",lua_ax_base_RenderView_isGfxContextReady); - tolua_function(tolua_S,"swapBuffers",lua_ax_base_RenderView_swapBuffers); - tolua_function(tolua_S,"setIMEKeyboardState",lua_ax_base_RenderView_setIMEKeyboardState); - tolua_function(tolua_S,"windowShouldClose",lua_ax_base_RenderView_windowShouldClose); - tolua_function(tolua_S,"pollEvents",lua_ax_base_RenderView_pollEvents); - tolua_function(tolua_S,"getFrameSize",lua_ax_base_RenderView_getFrameSize); - tolua_function(tolua_S,"setFrameSize",lua_ax_base_RenderView_setFrameSize); - tolua_function(tolua_S,"setFrameZoomFactor",lua_ax_base_RenderView_setFrameZoomFactor); - tolua_function(tolua_S,"getFrameZoomFactor",lua_ax_base_RenderView_getFrameZoomFactor); - tolua_function(tolua_S,"setCursorVisible",lua_ax_base_RenderView_setCursorVisible); - tolua_function(tolua_S,"getRetinaFactor",lua_ax_base_RenderView_getRetinaFactor); - tolua_function(tolua_S,"setContentScaleFactor",lua_ax_base_RenderView_setContentScaleFactor); - tolua_function(tolua_S,"getContentScaleFactor",lua_ax_base_RenderView_getContentScaleFactor); - tolua_function(tolua_S,"isRetinaDisplay",lua_ax_base_RenderView_isRetinaDisplay); - tolua_function(tolua_S,"getVisibleSize",lua_ax_base_RenderView_getVisibleSize); - tolua_function(tolua_S,"getVisibleOrigin",lua_ax_base_RenderView_getVisibleOrigin); - tolua_function(tolua_S,"getVisibleRect",lua_ax_base_RenderView_getVisibleRect); - tolua_function(tolua_S,"getSafeAreaRect",lua_ax_base_RenderView_getSafeAreaRect); - tolua_function(tolua_S,"setDesignResolutionSize",lua_ax_base_RenderView_setDesignResolutionSize); - tolua_function(tolua_S,"getDesignResolutionSize",lua_ax_base_RenderView_getDesignResolutionSize); - tolua_function(tolua_S,"setViewPortInPoints",lua_ax_base_RenderView_setViewPortInPoints); - tolua_function(tolua_S,"setScissorInPoints",lua_ax_base_RenderView_setScissorInPoints); - tolua_function(tolua_S,"isScissorEnabled",lua_ax_base_RenderView_isScissorEnabled); - tolua_function(tolua_S,"getScissorRect",lua_ax_base_RenderView_getScissorRect); - tolua_function(tolua_S,"setViewName",lua_ax_base_RenderView_setViewName); - tolua_function(tolua_S,"getViewName",lua_ax_base_RenderView_getViewName); - tolua_function(tolua_S,"setIcon",lua_ax_base_RenderView_setIcon); - tolua_function(tolua_S,"setDefaultIcon",lua_ax_base_RenderView_setDefaultIcon); - tolua_function(tolua_S,"getViewPortRect",lua_ax_base_RenderView_getViewPortRect); - tolua_function(tolua_S,"getScaleX",lua_ax_base_RenderView_getScaleX); - tolua_function(tolua_S,"getScaleY",lua_ax_base_RenderView_getScaleY); - tolua_function(tolua_S,"getResolutionPolicy",lua_ax_base_RenderView_getResolutionPolicy); - tolua_function(tolua_S,"renderScene",lua_ax_base_RenderView_renderScene); - tolua_function(tolua_S,"setInteractive",lua_ax_base_RenderView_setInteractive); - tolua_function(tolua_S,"setGfxContextAttrs", lua_ax_base_RenderView_setGfxContextAttrs); - tolua_function(tolua_S,"getGfxContextAttrs", lua_ax_base_RenderView_getGfxContextAttrs); + tolua_beginmodule(tolua_S,"Image"); + tolua_function(tolua_S,"new",lua_ax_base_Image_constructor); + tolua_function(tolua_S,"initWithImageFile",lua_ax_base_Image_initWithImageFile); + tolua_function(tolua_S,"flipRawData",lua_ax_base_Image_flipRawData); + tolua_function(tolua_S,"getFileType",lua_ax_base_Image_getFileType); + tolua_function(tolua_S,"getPixelFormat",lua_ax_base_Image_getPixelFormat); + tolua_function(tolua_S,"getWidth",lua_ax_base_Image_getWidth); + tolua_function(tolua_S,"getHeight",lua_ax_base_Image_getHeight); + tolua_function(tolua_S,"getNumberOfMipmaps",lua_ax_base_Image_getNumberOfMipmaps); + tolua_function(tolua_S,"hasPremultipliedAlpha",lua_ax_base_Image_hasPremultipliedAlpha); + tolua_function(tolua_S,"getFilePath",lua_ax_base_Image_getFilePath); + tolua_function(tolua_S,"getBitPerPixel",lua_ax_base_Image_getBitPerPixel); + tolua_function(tolua_S,"hasAlpha",lua_ax_base_Image_hasAlpha); + tolua_function(tolua_S,"isCompressed",lua_ax_base_Image_isCompressed); + tolua_function(tolua_S,"saveToFile",lua_ax_base_Image_saveToFile); + tolua_function(tolua_S,"premultiplyAlpha",lua_ax_base_Image_premultiplyAlpha); + tolua_function(tolua_S,"reversePremultipliedAlpha",lua_ax_base_Image_reversePremultipliedAlpha); + tolua_function(tolua_S,"setPNGPremultipliedAlphaEnabled", lua_ax_base_Image_setPNGPremultipliedAlphaEnabled); + tolua_function(tolua_S,"setCompressedImagesHavePMA", lua_ax_base_Image_setCompressedImagesHavePMA); + tolua_function(tolua_S,"isCompressedImageHavePMA", lua_ax_base_Image_isCompressedImageHavePMA); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::RenderView).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.RenderView"; - g_typeCast[typeName] = "ax.RenderView"; + auto typeName = typeid(ax::Image).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Image"; + g_typeCast[typeName] = "ax.Image"; return 1; } -int lua_ax_base_Director_init(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_setQuad(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14409,45 +14438,49 @@ int lua_ax_base_Director_init(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_init'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setQuad'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::V3F_T2F_C4B_Quad* arg0; + + #pragma warning NO CONVERSION TO NATIVE FOR V3F_T2F_C4B_Quad* + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setQuad'", nullptr); return 0; } - auto&& ret = cobj->init(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setQuad(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:init",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setQuad",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setQuad'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getRunningScene(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_setQuads(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14456,45 +14489,52 @@ int lua_ax_base_Director_getRunningScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRunningScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setQuads'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::V3F_T2F_C4B_Quad* arg0; + int arg1; + + #pragma warning NO CONVERSION TO NATIVE FOR V3F_T2F_C4B_Quad* + ok = false; + + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PolygonInfo:setQuads"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRunningScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setQuads'", nullptr); return 0; } - auto&& ret = cobj->getRunningScene(); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + cobj->setQuads(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRunningScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setQuads",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRunningScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setQuads'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getNextScene(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_setTriangles(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14503,45 +14543,49 @@ int lua_ax_base_Director_getNextScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getNextScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setTriangles'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::TrianglesCommand::Triangles arg0; + + #pragma warning NO CONVERSION TO NATIVE FOR Triangles + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getNextScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setTriangles'", nullptr); return 0; } - auto&& ret = cobj->getNextScene(); - object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + cobj->setTriangles(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getNextScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setTriangles",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getNextScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setTriangles'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getAnimationInterval(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_getVertCount(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14550,45 +14594,45 @@ int lua_ax_base_Director_getAnimationInterval(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getAnimationInterval'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getVertCount'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getAnimationInterval'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getVertCount'", nullptr); return 0; } - auto&& ret = cobj->getAnimationInterval(); + auto&& ret = cobj->getVertCount(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getAnimationInterval",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getVertCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getAnimationInterval'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getVertCount'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setAnimationInterval(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_getTrianglesCount(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14597,48 +14641,45 @@ int lua_ax_base_Director_setAnimationInterval(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setAnimationInterval'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getTrianglesCount'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:setAnimationInterval"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setAnimationInterval'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getTrianglesCount'", nullptr); return 0; } - cobj->setAnimationInterval(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getTrianglesCount(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setAnimationInterval",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getTrianglesCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setAnimationInterval'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getTrianglesCount'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isStatsDisplay(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_getArea(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14647,45 +14688,45 @@ int lua_ax_base_Director_isStatsDisplay(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isStatsDisplay'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getArea'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isStatsDisplay'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getArea'", nullptr); return 0; } - auto&& ret = cobj->isStatsDisplay(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getArea(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isStatsDisplay",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getArea",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isStatsDisplay'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getArea'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setStatsDisplay(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_getRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14694,48 +14735,45 @@ int lua_ax_base_Director_setStatsDisplay(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setStatsDisplay'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setStatsDisplay"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsDisplay'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getRect'", nullptr); return 0; } - cobj->setStatsDisplay(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setStatsDisplay",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setStatsDisplay'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getSecondsPerFrame(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_setRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14744,45 +14782,48 @@ int lua_ax_base_Director_getSecondsPerFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getSecondsPerFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Rect arg0; + + ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.PolygonInfo:setRect"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getSecondsPerFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setRect'", nullptr); return 0; } - auto&& ret = cobj->getSecondsPerFrame(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setRect(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getSecondsPerFrame",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setRect",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getSecondsPerFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setStatsAnchor(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_getFilename(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14791,59 +14832,45 @@ int lua_ax_base_Director_setStatsAnchor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getFilename'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); - return 0; - } - cobj->setStatsAnchor(); - lua_settop(tolua_S, 1); - return 1; - } - if (argc == 1) + if (argc == 0) { - ax::AnchorPreset arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:setStatsAnchor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getFilename'", nullptr); return 0; } - cobj->setStatsAnchor(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getFilename(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setStatsAnchor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getFilename",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setStatsAnchor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getFilename'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getRenderView(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_setFilename(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14852,45 +14879,48 @@ int lua_ax_base_Director_getRenderView(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRenderView'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setFilename'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.PolygonInfo:setFilename"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRenderView'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setFilename'", nullptr); return 0; } - auto&& ret = cobj->getRenderView(); - object_to_luaval(tolua_S, "ax.RenderView",(ax::RenderView*)ret); + cobj->setFilename(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRenderView",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setFilename",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRenderView'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setFilename'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setRenderView(lua_State* tolua_S) +int lua_ax_base_PolygonInfo_constructor(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14898,49 +14928,64 @@ int lua_ax_base_Director_setRenderView(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setRenderView'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::RenderView* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.RenderView",&arg0, "ax.Director:setRenderView"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setRenderView'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_constructor'", nullptr); return 0; } - cobj->setRenderView(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::PolygonInfo(); + tolua_pushusertype(tolua_S,(void*)cobj,"ax.PolygonInfo"); + tolua_register_gc(tolua_S,lua_gettop(tolua_S)); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setRenderView",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:PolygonInfo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setRenderView'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getTextureCache(lua_State* tolua_S) + +static int lua_ax_base_PolygonInfo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (PolygonInfo)"); + return 0; +} + +int lua_register_ax_base_PolygonInfo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.PolygonInfo"); + tolua_cclass(tolua_S,"PolygonInfo","ax.PolygonInfo","",nullptr); + + tolua_beginmodule(tolua_S,"PolygonInfo"); + tolua_function(tolua_S,"new",lua_ax_base_PolygonInfo_constructor); + tolua_function(tolua_S,"setQuad",lua_ax_base_PolygonInfo_setQuad); + tolua_function(tolua_S,"setQuads",lua_ax_base_PolygonInfo_setQuads); + tolua_function(tolua_S,"setTriangles",lua_ax_base_PolygonInfo_setTriangles); + tolua_function(tolua_S,"getVertCount",lua_ax_base_PolygonInfo_getVertCount); + tolua_function(tolua_S,"getTrianglesCount",lua_ax_base_PolygonInfo_getTrianglesCount); + tolua_function(tolua_S,"getArea",lua_ax_base_PolygonInfo_getArea); + tolua_function(tolua_S,"getRect",lua_ax_base_PolygonInfo_getRect); + tolua_function(tolua_S,"setRect",lua_ax_base_PolygonInfo_setRect); + tolua_function(tolua_S,"getFilename",lua_ax_base_PolygonInfo_getFilename); + tolua_function(tolua_S,"setFilename",lua_ax_base_PolygonInfo_setFilename); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::PolygonInfo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PolygonInfo"; + g_typeCast[typeName] = "ax.PolygonInfo"; + return 1; +} + +int lua_ax_base_AutoPolygon_constructor(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AutoPolygon* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14948,46 +14993,57 @@ int lua_ax_base_Director_getTextureCache(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getTextureCache'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.AutoPolygon:AutoPolygon"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getTextureCache'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AutoPolygon_constructor'", nullptr); return 0; } - auto&& ret = cobj->getTextureCache(); - object_to_luaval(tolua_S, "ax.TextureCache",(ax::TextureCache*)ret); + cobj = new ax::AutoPolygon(arg0); + tolua_pushusertype(tolua_S,(void*)cobj,"ax.AutoPolygon"); + tolua_register_gc(tolua_S,lua_gettop(tolua_S)); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getTextureCache",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AutoPolygon:AutoPolygon",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getTextureCache'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AutoPolygon_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isNextDeltaTimeZero(lua_State* tolua_S) + +static int lua_ax_base_AutoPolygon_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (AutoPolygon)"); + return 0; +} + +int lua_register_ax_base_AutoPolygon(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.AutoPolygon"); + tolua_cclass(tolua_S,"AutoPolygon","ax.AutoPolygon","",nullptr); + + tolua_beginmodule(tolua_S,"AutoPolygon"); + tolua_function(tolua_S,"new",lua_ax_base_AutoPolygon_constructor); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::AutoPolygon).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.AutoPolygon"; + g_typeCast[typeName] = "ax.AutoPolygon"; + return 1; +} + +int lua_ax_base_SpriteFrame_getRectInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -14996,45 +15052,45 @@ int lua_ax_base_Director_isNextDeltaTimeZero(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isNextDeltaTimeZero'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getRectInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isNextDeltaTimeZero'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getRectInPixels'", nullptr); return 0; } - auto&& ret = cobj->isNextDeltaTimeZero(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getRectInPixels(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isNextDeltaTimeZero",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getRectInPixels",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isNextDeltaTimeZero'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getRectInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setNextDeltaTimeZero(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setRectInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15043,48 +15099,48 @@ int lua_ax_base_Director_setNextDeltaTimeZero(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setNextDeltaTimeZero'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRectInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - bool arg0; + ax::Rect arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setNextDeltaTimeZero"); + ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setRectInPixels"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setNextDeltaTimeZero'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRectInPixels'", nullptr); return 0; } - cobj->setNextDeltaTimeZero(arg0); + cobj->setRectInPixels(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setNextDeltaTimeZero",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRectInPixels",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setNextDeltaTimeZero'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRectInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isPaused(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_isRotated(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15093,45 +15149,45 @@ int lua_ax_base_Director_isPaused(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isPaused'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_isRotated'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isPaused'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_isRotated'", nullptr); return 0; } - auto&& ret = cobj->isPaused(); + auto&& ret = cobj->isRotated(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isPaused",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:isRotated",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isPaused'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_isRotated'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getTotalFrames(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setRotated(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15140,45 +15196,48 @@ int lua_ax_base_Director_getTotalFrames(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getTotalFrames'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRotated'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.SpriteFrame:setRotated"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getTotalFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRotated'", nullptr); return 0; } - auto&& ret = cobj->getTotalFrames(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setRotated(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getTotalFrames",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRotated",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getTotalFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRotated'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setProjection(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15187,48 +15246,45 @@ int lua_ax_base_Director_setProjection(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setProjection'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Director::Projection arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:setProjection"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setProjection'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getRect'", nullptr); return 0; } - cobj->setProjection(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setProjection",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setProjection'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setViewport(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15237,45 +15293,48 @@ int lua_ax_base_Director_setViewport(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setViewport'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Rect arg0; + + ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setRect"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setViewport'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRect'", nullptr); return 0; } - cobj->setViewport(); + cobj->setRect(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setViewport",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRect",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setViewport'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isSendCleanupToScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getCenterRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15284,45 +15343,45 @@ int lua_ax_base_Director_isSendCleanupToScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isSendCleanupToScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getCenterRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isSendCleanupToScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getCenterRect'", nullptr); return 0; } - auto&& ret = cobj->isSendCleanupToScene(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getCenterRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isSendCleanupToScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getCenterRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isSendCleanupToScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getCenterRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getNotificationNode(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setCenterRectInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15331,45 +15390,48 @@ int lua_ax_base_Director_getNotificationNode(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getNotificationNode'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Rect arg0; + + ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setCenterRectInPixels"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getNotificationNode'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'", nullptr); return 0; } - auto&& ret = cobj->getNotificationNode(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + cobj->setCenterRectInPixels(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getNotificationNode",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setCenterRectInPixels",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getNotificationNode'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setNotificationNode(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_hasCenterRect(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15378,48 +15440,45 @@ int lua_ax_base_Director_setNotificationNode(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setNotificationNode'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_hasCenterRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Director:setNotificationNode"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setNotificationNode'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_hasCenterRect'", nullptr); return 0; } - cobj->setNotificationNode(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->hasCenterRect(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setNotificationNode",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:hasCenterRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setNotificationNode'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_hasCenterRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getWinSize(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getOffsetInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15428,45 +15487,45 @@ int lua_ax_base_Director_getWinSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getWinSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getWinSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'", nullptr); return 0; } - auto&& ret = cobj->getWinSize(); + auto&& ret = cobj->getOffsetInPixels(); vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getWinSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOffsetInPixels",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getWinSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getWinSizeInPixels(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setOffsetInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15475,45 +15534,48 @@ int lua_ax_base_Director_getWinSizeInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getWinSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOffsetInPixels"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getWinSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'", nullptr); return 0; } - auto&& ret = cobj->getWinSizeInPixels(); - vec2_to_luaval(tolua_S, ret); + cobj->setOffsetInPixels(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getWinSizeInPixels",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOffsetInPixels",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getWinSizeInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getVisibleSize(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getOriginalSizeInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15522,45 +15584,45 @@ int lua_ax_base_Director_getVisibleSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getVisibleSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getVisibleSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'", nullptr); return 0; } - auto&& ret = cobj->getVisibleSize(); + auto&& ret = cobj->getOriginalSizeInPixels(); vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getVisibleSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOriginalSizeInPixels",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getVisibleSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getVisibleOrigin(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setOriginalSizeInPixels(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15569,45 +15631,48 @@ int lua_ax_base_Director_getVisibleOrigin(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getVisibleOrigin'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOriginalSizeInPixels"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getVisibleOrigin'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'", nullptr); return 0; } - auto&& ret = cobj->getVisibleOrigin(); - vec2_to_luaval(tolua_S, ret); + cobj->setOriginalSizeInPixels(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getVisibleOrigin",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOriginalSizeInPixels",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getVisibleOrigin'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getSafeAreaRect(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getOriginalSize(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15616,45 +15681,45 @@ int lua_ax_base_Director_getSafeAreaRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getSafeAreaRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOriginalSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getSafeAreaRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOriginalSize'", nullptr); return 0; } - auto&& ret = cobj->getSafeAreaRect(); - rect_to_luaval(tolua_S, ret); + auto&& ret = cobj->getOriginalSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getSafeAreaRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOriginalSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getSafeAreaRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOriginalSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_convertToGL(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setOriginalSize(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15663,48 +15728,48 @@ int lua_ax_base_Director_convertToGL(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_convertToGL'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOriginalSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Director:convertToGL"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOriginalSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_convertToGL'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOriginalSize'", nullptr); return 0; } - auto&& ret = cobj->convertToGL(arg0); - vec2_to_luaval(tolua_S, ret); + cobj->setOriginalSize(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:convertToGL",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOriginalSize",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_convertToGL'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOriginalSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_convertToUI(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getTexture(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15713,48 +15778,45 @@ int lua_ax_base_Director_convertToUI(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_convertToUI'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getTexture'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Director:convertToUI"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_convertToUI'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getTexture'", nullptr); return 0; } - auto&& ret = cobj->convertToUI(arg0); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getTexture(); + object_to_luaval(tolua_S, "ax.Texture2D",(ax::Texture2D*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:convertToUI",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getTexture",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_convertToUI'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getZEye(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setTexture(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15763,45 +15825,48 @@ int lua_ax_base_Director_getZEye(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getZEye'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setTexture'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Texture2D* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:setTexture"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getZEye'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setTexture'", nullptr); return 0; } - auto&& ret = cobj->getZEye(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setTexture(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getZEye",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setTexture",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getZEye'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_runWithScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getOffset(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15810,48 +15875,45 @@ int lua_ax_base_Director_runWithScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_runWithScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOffset'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Scene* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:runWithScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_runWithScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOffset'", nullptr); return 0; } - cobj->runWithScene(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getOffset(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:runWithScene",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOffset",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_runWithScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOffset'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_pushScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setOffset(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15860,48 +15922,48 @@ int lua_ax_base_Director_pushScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pushScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOffset'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Scene* arg0; + ax::Vec2 arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:pushScene"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pushScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOffset'", nullptr); return 0; } - cobj->pushScene(arg0); + cobj->setOffset(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pushScene",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOffset",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pushScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOffset'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_popScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getAnchorPoint(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15910,45 +15972,45 @@ int lua_ax_base_Director_popScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getAnchorPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getAnchorPoint'", nullptr); return 0; } - cobj->popScene(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getAnchorPoint(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getAnchorPoint",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getAnchorPoint'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_popToRootScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_setAnchorPoint(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -15957,45 +16019,48 @@ int lua_ax_base_Director_popToRootScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popToRootScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setAnchorPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setAnchorPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popToRootScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setAnchorPoint'", nullptr); return 0; } - cobj->popToRootScene(); + cobj->setAnchorPoint(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popToRootScene",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setAnchorPoint",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popToRootScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setAnchorPoint'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_popToSceneStackLevel(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_hasAnchorPoint(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16004,48 +16069,45 @@ int lua_ax_base_Director_popToSceneStackLevel(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popToSceneStackLevel'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:popToSceneStackLevel"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popToSceneStackLevel'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'", nullptr); return 0; } - cobj->popToSceneStackLevel(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->hasAnchorPoint(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popToSceneStackLevel",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:hasAnchorPoint",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popToSceneStackLevel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_replaceScene(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_clone(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16054,142 +16116,195 @@ int lua_ax_base_Director_replaceScene(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_replaceScene'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_clone'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Scene* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:replaceScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_replaceScene'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_clone'", nullptr); return 0; } - cobj->replaceScene(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:replaceScene",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:clone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_replaceScene'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_clone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_end(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_initWithTexture(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_end'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_initWithTexture'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_end'", nullptr); - return 0; + do{ + if (argc == 5) { + ax::Texture2D* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + bool arg2; + ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + ax::Vec2 arg4; + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + bool ret = cobj->initWithTexture(arg0, arg1, arg2, arg3, arg4); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->end(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:end",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + ax::Texture2D* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTexture"); + + if (!ok) { break; } + bool ret = cobj->initWithTexture(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:initWithTexture",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_end'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_initWithTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_pause(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_initWithTextureFilename(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pause'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_initWithTextureFilename'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pause'", nullptr); - return 0; + do{ + if (argc == 5) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + bool arg2; + ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + ax::Vec2 arg4; + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + bool ret = cobj->initWithTextureFilename(arg0, arg1, arg2, arg3, arg4); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->pause(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pause",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTextureFilename"); + + if (!ok) { break; } + bool ret = cobj->initWithTextureFilename(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:initWithTextureFilename",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pause'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_initWithTextureFilename'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_resume(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_getName(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16198,139 +16313,171 @@ int lua_ax_base_Director_resume(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_resume'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_resume'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getName'", nullptr); return 0; } - cobj->resume(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getName(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:resume",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getName",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_resume'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_restart(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_create(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_restart'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 5) + { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:create"); + if (!ok) { break; } + bool arg2; + ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::Vec2 arg4; + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::SpriteFrame* ret = ax::SpriteFrame::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + return 1; + } + } while (0); + ok = true; + do { - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_restart'", nullptr); - return 0; + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:create"); + if (!ok) { break; } + ax::SpriteFrame* ret = ax::SpriteFrame::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + return 1; } - cobj->restart(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:restart",argc, 0); + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.SpriteFrame:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_restart'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Director_stopAnimation(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_createWithTexture(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_stopAnimation'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 5) + { + ax::Texture2D* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + bool arg2; + ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::Vec2 arg3; + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::Vec2 arg4; + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::SpriteFrame* ret = ax::SpriteFrame::createWithTexture(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + return 1; + } + } while (0); + ok = true; + do { - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_stopAnimation'", nullptr); - return 0; + ax::Texture2D* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::Rect arg1; + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:createWithTexture"); + if (!ok) { break; } + ax::SpriteFrame* ret = ax::SpriteFrame::createWithTexture(arg0, arg1); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + return 1; } - cobj->stopAnimation(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:stopAnimation",argc, 0); + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.SpriteFrame:createWithTexture",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_stopAnimation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_createWithTexture'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Director_startAnimation(lua_State* tolua_S) +int lua_ax_base_SpriteFrame_constructor(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16338,93 +16485,84 @@ int lua_ax_base_Director_startAnimation(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_startAnimation'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_startAnimation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_constructor'", nullptr); return 0; } - cobj->startAnimation(); - lua_settop(tolua_S, 1); + cobj = new ax::SpriteFrame(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SpriteFrame"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:startAnimation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:SpriteFrame",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_startAnimation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_drawScene(lua_State* tolua_S) -{ - int argc = 0; - ax::Director* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_drawScene'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_drawScene'", nullptr); - return 0; - } - cobj->drawScene(); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:drawScene",argc, 0); +static int lua_ax_base_SpriteFrame_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (SpriteFrame)"); return 0; +} -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_drawScene'.",&tolua_err); -#endif +int lua_register_ax_base_SpriteFrame(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.SpriteFrame"); + tolua_cclass(tolua_S,"SpriteFrame","ax.SpriteFrame","ax.Object",nullptr); - return 0; + tolua_beginmodule(tolua_S,"SpriteFrame"); + tolua_function(tolua_S,"new",lua_ax_base_SpriteFrame_constructor); + tolua_function(tolua_S,"getRectInPixels",lua_ax_base_SpriteFrame_getRectInPixels); + tolua_function(tolua_S,"setRectInPixels",lua_ax_base_SpriteFrame_setRectInPixels); + tolua_function(tolua_S,"isRotated",lua_ax_base_SpriteFrame_isRotated); + tolua_function(tolua_S,"setRotated",lua_ax_base_SpriteFrame_setRotated); + tolua_function(tolua_S,"getRect",lua_ax_base_SpriteFrame_getRect); + tolua_function(tolua_S,"setRect",lua_ax_base_SpriteFrame_setRect); + tolua_function(tolua_S,"getCenterRect",lua_ax_base_SpriteFrame_getCenterRect); + tolua_function(tolua_S,"setCenterRectInPixels",lua_ax_base_SpriteFrame_setCenterRectInPixels); + tolua_function(tolua_S,"hasCenterRect",lua_ax_base_SpriteFrame_hasCenterRect); + tolua_function(tolua_S,"getOffsetInPixels",lua_ax_base_SpriteFrame_getOffsetInPixels); + tolua_function(tolua_S,"setOffsetInPixels",lua_ax_base_SpriteFrame_setOffsetInPixels); + tolua_function(tolua_S,"getOriginalSizeInPixels",lua_ax_base_SpriteFrame_getOriginalSizeInPixels); + tolua_function(tolua_S,"setOriginalSizeInPixels",lua_ax_base_SpriteFrame_setOriginalSizeInPixels); + tolua_function(tolua_S,"getOriginalSize",lua_ax_base_SpriteFrame_getOriginalSize); + tolua_function(tolua_S,"setOriginalSize",lua_ax_base_SpriteFrame_setOriginalSize); + tolua_function(tolua_S,"getTexture",lua_ax_base_SpriteFrame_getTexture); + tolua_function(tolua_S,"setTexture",lua_ax_base_SpriteFrame_setTexture); + tolua_function(tolua_S,"getOffset",lua_ax_base_SpriteFrame_getOffset); + tolua_function(tolua_S,"setOffset",lua_ax_base_SpriteFrame_setOffset); + tolua_function(tolua_S,"getAnchorPoint",lua_ax_base_SpriteFrame_getAnchorPoint); + tolua_function(tolua_S,"setAnchorPoint",lua_ax_base_SpriteFrame_setAnchorPoint); + tolua_function(tolua_S,"hasAnchorPoint",lua_ax_base_SpriteFrame_hasAnchorPoint); + tolua_function(tolua_S,"clone",lua_ax_base_SpriteFrame_clone); + tolua_function(tolua_S,"initWithTexture",lua_ax_base_SpriteFrame_initWithTexture); + tolua_function(tolua_S,"initWithTextureFilename",lua_ax_base_SpriteFrame_initWithTextureFilename); + tolua_function(tolua_S,"getName",lua_ax_base_SpriteFrame_getName); + tolua_function(tolua_S,"create", lua_ax_base_SpriteFrame_create); + tolua_function(tolua_S,"createWithTexture", lua_ax_base_SpriteFrame_createWithTexture); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::SpriteFrame).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.SpriteFrame"; + g_typeCast[typeName] = "ax.SpriteFrame"; + return 1; } -int lua_ax_base_Director_purgeCachedData(lua_State* tolua_S) + +int lua_ax_base_AnimationFrame_getSpriteFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16433,45 +16571,45 @@ int lua_ax_base_Director_purgeCachedData(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_purgeCachedData'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getSpriteFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_purgeCachedData'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_getSpriteFrame'", nullptr); return 0; } - cobj->purgeCachedData(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getSpriteFrame(); + object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:purgeCachedData",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getSpriteFrame",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_purgeCachedData'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getSpriteFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setDefaultValues(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_setSpriteFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16480,45 +16618,48 @@ int lua_ax_base_Director_setDefaultValues(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setDefaultValues'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setSpriteFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::SpriteFrame* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:setSpriteFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setDefaultValues'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setSpriteFrame'", nullptr); return 0; } - cobj->setDefaultValues(); + cobj->setSpriteFrame(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setDefaultValues",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setSpriteFrame",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setDefaultValues'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setSpriteFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setGLDefaultValues(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_getDelayUnits(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16527,45 +16668,45 @@ int lua_ax_base_Director_setGLDefaultValues(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setGLDefaultValues'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getDelayUnits'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setGLDefaultValues'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_getDelayUnits'", nullptr); return 0; } - cobj->setGLDefaultValues(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getDelayUnits(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setGLDefaultValues",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getDelayUnits",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setGLDefaultValues'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getDelayUnits'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setClearColor(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_setDelayUnits(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16574,99 +16715,95 @@ int lua_ax_base_Director_setClearColor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setClearColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setDelayUnits'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + double arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.Director:setClearColor"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.AnimationFrame:setDelayUnits"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setClearColor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setDelayUnits'", nullptr); return 0; } - cobj->setClearColor(arg0); + cobj->setDelayUnits(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setClearColor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setDelayUnits",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setClearColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setDelayUnits'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_mainLoop(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_getUserInfo(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_mainLoop'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getUserInfo'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; do{ - if (argc == 1) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:mainLoop"); - - if (!ok) { break; } - cobj->mainLoop(arg0); - lua_settop(tolua_S, 1); + if (argc == 0) { + ax::ValueMap& ret = cobj->getUserInfo(); + ccvaluemap_to_luaval(tolua_S, ret); return 1; } }while(0); ok = true; do{ if (argc == 0) { - cobj->mainLoop(); - lua_settop(tolua_S, 1); + const ax::ValueMap& ret = cobj->getUserInfo(); + ccvaluemap_to_luaval(tolua_S, ret); return 1; } }while(0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:mainLoop",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getUserInfo",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_mainLoop'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getUserInfo'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setContentScaleFactor(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_setUserInfo(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16675,48 +16812,48 @@ int lua_ax_base_Director_setContentScaleFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setUserInfo'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + ax::ValueMap arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:setContentScaleFactor"); + ok &= luaval_to_ccvaluemap(tolua_S, 2, &arg0, "ax.AnimationFrame:setUserInfo"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setUserInfo'", nullptr); return 0; } - cobj->setContentScaleFactor(arg0); + cobj->setUserInfo(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setContentScaleFactor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setUserInfo",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setContentScaleFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setUserInfo'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getContentScaleFactor(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_clone(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16725,45 +16862,45 @@ int lua_ax_base_Director_getContentScaleFactor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_clone'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getContentScaleFactor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_clone'", nullptr); return 0; } - auto&& ret = cobj->getContentScaleFactor(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "ax.AnimationFrame",(ax::AnimationFrame*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getContentScaleFactor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:clone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getContentScaleFactor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_clone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getScheduler(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_initWithSpriteFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16772,95 +16909,94 @@ int lua_ax_base_Director_getScheduler(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getScheduler'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 3) { + ax::SpriteFrame* arg0; + double arg1; + ax::ValueMap arg2; + + ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:initWithSpriteFrame"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.AnimationFrame:initWithSpriteFrame"); + + ok &= luaval_to_ccvaluemap(tolua_S, 4, &arg2, "ax.AnimationFrame:initWithSpriteFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getScheduler'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'", nullptr); return 0; } - auto&& ret = cobj->getScheduler(); - object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); + auto&& ret = cobj->initWithSpriteFrame(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getScheduler",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:initWithSpriteFrame",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getScheduler'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setScheduler(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_create(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setScheduler'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 3) { - ax::Scheduler* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Scheduler",&arg0, "ax.Director:setScheduler"); + ax::SpriteFrame* arg0; + double arg1; + ax::ValueMap arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.AnimationFrame:create"); + ok &= luaval_to_ccvaluemap(tolua_S, 4, &arg2, "ax.AnimationFrame:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setScheduler'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_create'", nullptr); return 0; } - cobj->setScheduler(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::AnimationFrame::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.AnimationFrame",(ax::AnimationFrame*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setScheduler",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.AnimationFrame:create",argc, 3); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setScheduler'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Director_getActionManager(lua_State* tolua_S) +int lua_ax_base_AnimationFrame_constructor(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::AnimationFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16868,46 +17004,65 @@ int lua_ax_base_Director_getActionManager(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getActionManager'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getActionManager'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_constructor'", nullptr); return 0; } - auto&& ret = cobj->getActionManager(); - object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); + cobj = new ax::AnimationFrame(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.AnimationFrame"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getActionManager",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:AnimationFrame",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getActionManager'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setActionManager(lua_State* tolua_S) + +static int lua_ax_base_AnimationFrame_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (AnimationFrame)"); + return 0; +} + +int lua_register_ax_base_AnimationFrame(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.AnimationFrame"); + tolua_cclass(tolua_S,"AnimationFrame","ax.AnimationFrame","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"AnimationFrame"); + tolua_function(tolua_S,"new",lua_ax_base_AnimationFrame_constructor); + tolua_function(tolua_S,"getSpriteFrame",lua_ax_base_AnimationFrame_getSpriteFrame); + tolua_function(tolua_S,"setSpriteFrame",lua_ax_base_AnimationFrame_setSpriteFrame); + tolua_function(tolua_S,"getDelayUnits",lua_ax_base_AnimationFrame_getDelayUnits); + tolua_function(tolua_S,"setDelayUnits",lua_ax_base_AnimationFrame_setDelayUnits); + tolua_function(tolua_S,"getUserInfo",lua_ax_base_AnimationFrame_getUserInfo); + tolua_function(tolua_S,"setUserInfo",lua_ax_base_AnimationFrame_setUserInfo); + tolua_function(tolua_S,"clone",lua_ax_base_AnimationFrame_clone); + tolua_function(tolua_S,"initWithSpriteFrame",lua_ax_base_AnimationFrame_initWithSpriteFrame); + tolua_function(tolua_S,"create", lua_ax_base_AnimationFrame_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::AnimationFrame).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.AnimationFrame"; + g_typeCast[typeName] = "ax.AnimationFrame"; + return 1; +} + +int lua_ax_base_Animation_addSpriteFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16916,48 +17071,48 @@ int lua_ax_base_Director_setActionManager(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setActionManager'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::ActionManager* arg0; + ax::SpriteFrame* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionManager",&arg0, "ax.Director:setActionManager"); + ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.Animation:addSpriteFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setActionManager'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrame'", nullptr); return 0; } - cobj->setActionManager(arg0); + cobj->addSpriteFrame(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setActionManager",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrame",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setActionManager'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getEventDispatcher(lua_State* tolua_S) +int lua_ax_base_Animation_addSpriteFrameWithFile(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16966,45 +17121,48 @@ int lua_ax_base_Director_getEventDispatcher(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrameWithFile'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Animation:addSpriteFrameWithFile"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrameWithFile'", nullptr); return 0; } - auto&& ret = cobj->getEventDispatcher(); - object_to_luaval(tolua_S, "ax.EventDispatcher",(ax::EventDispatcher*)ret); + cobj->addSpriteFrameWithFile(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getEventDispatcher",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrameWithFile",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getEventDispatcher'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrameWithFile'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setEventDispatcher(lua_State* tolua_S) +int lua_ax_base_Animation_addSpriteFrameWithTexture(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17013,48 +17171,51 @@ int lua_ax_base_Director_setEventDispatcher(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - ax::EventDispatcher* arg0; + ax::Texture2D* arg0; + ax::Rect arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.EventDispatcher",&arg0, "ax.Director:setEventDispatcher"); + ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.Animation:addSpriteFrameWithTexture"); + + ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Animation:addSpriteFrameWithTexture"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setEventDispatcher'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'", nullptr); return 0; } - cobj->setEventDispatcher(arg0); + cobj->addSpriteFrameWithTexture(arg0, arg1); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setEventDispatcher",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrameWithTexture",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setEventDispatcher'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getRenderer(lua_State* tolua_S) +int lua_ax_base_Animation_getTotalDelayUnits(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17063,45 +17224,45 @@ int lua_ax_base_Director_getRenderer(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRenderer'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getTotalDelayUnits'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRenderer'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getTotalDelayUnits'", nullptr); return 0; } - auto&& ret = cobj->getRenderer(); - object_to_luaval(tolua_S, "ax.Renderer",(ax::Renderer*)ret); + auto&& ret = cobj->getTotalDelayUnits(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRenderer",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getTotalDelayUnits",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRenderer'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getTotalDelayUnits'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getDeltaTime(lua_State* tolua_S) +int lua_ax_base_Animation_setDelayPerUnit(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17110,45 +17271,48 @@ int lua_ax_base_Director_getDeltaTime(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getDeltaTime'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setDelayPerUnit'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Animation:setDelayPerUnit"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getDeltaTime'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setDelayPerUnit'", nullptr); return 0; } - auto&& ret = cobj->getDeltaTime(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setDelayPerUnit(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getDeltaTime",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setDelayPerUnit",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getDeltaTime'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setDelayPerUnit'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getFrameRate(lua_State* tolua_S) +int lua_ax_base_Animation_getDelayPerUnit(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17157,45 +17321,45 @@ int lua_ax_base_Director_getFrameRate(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getFrameRate'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getDelayPerUnit'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getFrameRate'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getDelayPerUnit'", nullptr); return 0; } - auto&& ret = cobj->getFrameRate(); + auto&& ret = cobj->getDelayPerUnit(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getFrameRate",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getDelayPerUnit",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getFrameRate'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getDelayPerUnit'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_pushMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_getDuration(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17204,48 +17368,45 @@ int lua_ax_base_Director_pushMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pushMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::MATRIX_STACK_TYPE arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:pushMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pushMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getDuration'", nullptr); return 0; } - cobj->pushMatrix(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getDuration(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pushMatrix",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getDuration",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pushMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_popMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_getFrames(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17254,48 +17415,45 @@ int lua_ax_base_Director_popMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getFrames'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::MATRIX_STACK_TYPE arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:popMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getFrames'", nullptr); return 0; } - cobj->popMatrix(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getFrames(); + ccvector_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popMatrix",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getFrames",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getFrames'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_loadIdentityMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_setFrames(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17304,48 +17462,48 @@ int lua_ax_base_Director_loadIdentityMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_loadIdentityMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setFrames'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::MATRIX_STACK_TYPE arg0; + ax::Vector arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:loadIdentityMatrix"); + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:setFrames"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_loadIdentityMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setFrames'", nullptr); return 0; } - cobj->loadIdentityMatrix(arg0); + cobj->setFrames(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:loadIdentityMatrix",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setFrames",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_loadIdentityMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setFrames'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_loadMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_getRestoreOriginalFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17354,51 +17512,45 @@ int lua_ax_base_Director_loadMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_loadMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getRestoreOriginalFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::MATRIX_STACK_TYPE arg0; - ax::Mat4 arg1; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:loadMatrix"); - - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Director:loadMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_loadMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getRestoreOriginalFrame'", nullptr); return 0; } - cobj->loadMatrix(arg0, arg1); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getRestoreOriginalFrame(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:loadMatrix",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getRestoreOriginalFrame",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_loadMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getRestoreOriginalFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_multiplyMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_setRestoreOriginalFrame(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17407,51 +17559,48 @@ int lua_ax_base_Director_multiplyMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_multiplyMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setRestoreOriginalFrame'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - ax::MATRIX_STACK_TYPE arg0; - ax::Mat4 arg1; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:multiplyMatrix"); + bool arg0; - ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Director:multiplyMatrix"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Animation:setRestoreOriginalFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_multiplyMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setRestoreOriginalFrame'", nullptr); return 0; } - cobj->multiplyMatrix(arg0, arg1); + cobj->setRestoreOriginalFrame(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:multiplyMatrix",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setRestoreOriginalFrame",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_multiplyMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setRestoreOriginalFrame'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getMatrix(lua_State* tolua_S) +int lua_ax_base_Animation_getLoops(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17460,48 +17609,45 @@ int lua_ax_base_Director_getMatrix(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getMatrix'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getLoops'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::MATRIX_STACK_TYPE arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:getMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getMatrix'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getLoops'", nullptr); return 0; } - auto&& ret = cobj->getMatrix(arg0); - mat4_to_luaval(tolua_S, ret); + auto&& ret = cobj->getLoops(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getMatrix",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getLoops",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getMatrix'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getLoops'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_resetMatrixStack(lua_State* tolua_S) +int lua_ax_base_Animation_setLoops(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17510,45 +17656,48 @@ int lua_ax_base_Director_resetMatrixStack(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_resetMatrixStack'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setLoops'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + unsigned int arg0; + + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Animation:setLoops"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_resetMatrixStack'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setLoops'", nullptr); return 0; } - cobj->resetMatrixStack(); + cobj->setLoops(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:resetMatrixStack",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setLoops",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_resetMatrixStack'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setLoops'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getAxmolThreadId(lua_State* tolua_S) +int lua_ax_base_Animation_clone(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17557,45 +17706,45 @@ int lua_ax_base_Director_getAxmolThreadId(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getAxmolThreadId'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_clone'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getAxmolThreadId'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_clone'", nullptr); return 0; } - auto&& ret = cobj->getAxmolThreadId(); - std_thread_id_to_luaval(tolua_S, ret); + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getAxmolThreadId",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:clone",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getAxmolThreadId'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_clone'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_setChildrenIndexerEnabled(lua_State* tolua_S) +int lua_ax_base_Animation_init(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17604,48 +17753,45 @@ int lua_ax_base_Director_setChildrenIndexerEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setChildrenIndexerEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_init'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setChildrenIndexerEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setChildrenIndexerEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_init'", nullptr); return 0; } - cobj->setChildrenIndexerEnabled(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->init(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setChildrenIndexerEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:init",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setChildrenIndexerEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_init'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isChildrenIndexerEnabled(lua_State* tolua_S) +int lua_ax_base_Animation_initWithSpriteFrames(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17654,45 +17800,85 @@ int lua_ax_base_Director_isChildrenIndexerEnabled(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isChildrenIndexerEnabled'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vector arg0; + + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isChildrenIndexerEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); return 0; } - auto&& ret = cobj->isChildrenIndexerEnabled(); + auto&& ret = cobj->initWithSpriteFrames(arg0); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isChildrenIndexerEnabled",argc, 0); + if (argc == 2) + { + ax::Vector arg0; + double arg1; + + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithSpriteFrames"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); + return 0; + } + auto&& ret = cobj->initWithSpriteFrames(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + if (argc == 3) + { + ax::Vector arg0; + double arg1; + unsigned int arg2; + + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithSpriteFrames"); + + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:initWithSpriteFrames"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); + return 0; + } + auto&& ret = cobj->initWithSpriteFrames(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:initWithSpriteFrames",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isChildrenIndexerEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_initWithSpriteFrames'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_isValid(lua_State* tolua_S) +int lua_ax_base_Animation_initWithAnimationFrames(lua_State* tolua_S) { int argc = 0; - ax::Director* cobj = nullptr; + ax::Animation* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17701,76 +17887,118 @@ int lua_ax_base_Director_isValid(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isValid'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_initWithAnimationFrames'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 3) { + ax::Vector arg0; + double arg1; + unsigned int arg2; + + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithAnimationFrames"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithAnimationFrames"); + + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:initWithAnimationFrames"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isValid'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithAnimationFrames'", nullptr); return 0; } - auto&& ret = cobj->isValid(); + auto&& ret = cobj->initWithAnimationFrames(arg0, arg1, arg2); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isValid",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:initWithAnimationFrames",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isValid'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_initWithAnimationFrames'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_getInstance(lua_State* tolua_S) +int lua_ax_base_Animation_create(lua_State* tolua_S) { int argc = 0; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + argc = lua_gettop(tolua_S)-1; - if (argc == 0) + do { - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getInstance'", nullptr); - return 0; + ax::Vector arg0; + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:create"); + if (!ok) { break; } + ax::Animation* ret = ax::Animation::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; } - auto&& ret = ax::Director::getInstance(); - object_to_luaval(tolua_S, "ax.Director",(ax::Director*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Director:getInstance",argc, 0); + } while (0); + ok = true; + do + { + if (argc == 3) + { + ax::Vector arg0; + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:create"); + if (!ok) { break; } + unsigned int arg2; + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:create"); + if (!ok) { break; } + ax::Animation* ret = ax::Animation::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; + } + } while (0); + ok = true; + do + { + if (argc == 0) + { + ax::Animation* ret = ax::Animation::create(); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.Animation:create",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getInstance'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_create'.",&tolua_err); #endif return 0; } -int lua_ax_base_Director_destroyInstance(lua_State* tolua_S) +int lua_ax_base_Animation_createWithSpriteFrames(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -17780,124 +18008,144 @@ int lua_ax_base_Director_destroyInstance(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 0) + if (argc == 1) { + ax::Vector arg0; + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_destroyInstance'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); return 0; } - ax::Director::destroyInstance(); - lua_settop(tolua_S, 1); + auto&& ret = ax::Animation::createWithSpriteFrames(arg0); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Director:destroyInstance",argc, 0); + if (argc == 2) + { + ax::Vector arg0; + double arg1; + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:createWithSpriteFrames"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); + return 0; + } + auto&& ret = ax::Animation::createWithSpriteFrames(arg0, arg1); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; + } + if (argc == 3) + { + ax::Vector arg0; + double arg1; + unsigned int arg2; + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:createWithSpriteFrames"); + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:createWithSpriteFrames"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); + return 0; + } + auto&& ret = ax::Animation::createWithSpriteFrames(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Animation:createWithSpriteFrames",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_destroyInstance'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_createWithSpriteFrames'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Director_finalize(lua_State* tolua_S) +int lua_ax_base_Animation_constructor(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Director)"); - return 0; -} + int argc = 0; + ax::Animation* cobj = nullptr; + bool ok = true; -int lua_register_ax_base_Director(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Director"); - tolua_cclass(tolua_S,"Director","ax.Director","",nullptr); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - tolua_beginmodule(tolua_S,"Director"); - tolua_function(tolua_S,"init",lua_ax_base_Director_init); - tolua_function(tolua_S,"getRunningScene",lua_ax_base_Director_getRunningScene); - tolua_function(tolua_S,"getNextScene",lua_ax_base_Director_getNextScene); - tolua_function(tolua_S,"getAnimationInterval",lua_ax_base_Director_getAnimationInterval); - tolua_function(tolua_S,"setAnimationInterval",lua_ax_base_Director_setAnimationInterval); - tolua_function(tolua_S,"isStatsDisplay",lua_ax_base_Director_isStatsDisplay); - tolua_function(tolua_S,"setStatsDisplay",lua_ax_base_Director_setStatsDisplay); - tolua_function(tolua_S,"getSecondsPerFrame",lua_ax_base_Director_getSecondsPerFrame); - tolua_function(tolua_S,"setStatsAnchor",lua_ax_base_Director_setStatsAnchor); - tolua_function(tolua_S,"getRenderView",lua_ax_base_Director_getRenderView); - tolua_function(tolua_S,"setRenderView",lua_ax_base_Director_setRenderView); - tolua_function(tolua_S,"getTextureCache",lua_ax_base_Director_getTextureCache); - tolua_function(tolua_S,"isNextDeltaTimeZero",lua_ax_base_Director_isNextDeltaTimeZero); - tolua_function(tolua_S,"setNextDeltaTimeZero",lua_ax_base_Director_setNextDeltaTimeZero); - tolua_function(tolua_S,"isPaused",lua_ax_base_Director_isPaused); - tolua_function(tolua_S,"getTotalFrames",lua_ax_base_Director_getTotalFrames); - tolua_function(tolua_S,"setProjection",lua_ax_base_Director_setProjection); - tolua_function(tolua_S,"setViewport",lua_ax_base_Director_setViewport); - tolua_function(tolua_S,"isSendCleanupToScene",lua_ax_base_Director_isSendCleanupToScene); - tolua_function(tolua_S,"getNotificationNode",lua_ax_base_Director_getNotificationNode); - tolua_function(tolua_S,"setNotificationNode",lua_ax_base_Director_setNotificationNode); - tolua_function(tolua_S,"getWinSize",lua_ax_base_Director_getWinSize); - tolua_function(tolua_S,"getWinSizeInPixels",lua_ax_base_Director_getWinSizeInPixels); - tolua_function(tolua_S,"getVisibleSize",lua_ax_base_Director_getVisibleSize); - tolua_function(tolua_S,"getVisibleOrigin",lua_ax_base_Director_getVisibleOrigin); - tolua_function(tolua_S,"getSafeAreaRect",lua_ax_base_Director_getSafeAreaRect); - tolua_function(tolua_S,"convertToGL",lua_ax_base_Director_convertToGL); - tolua_function(tolua_S,"convertToUI",lua_ax_base_Director_convertToUI); - tolua_function(tolua_S,"getZEye",lua_ax_base_Director_getZEye); - tolua_function(tolua_S,"runWithScene",lua_ax_base_Director_runWithScene); - tolua_function(tolua_S,"pushScene",lua_ax_base_Director_pushScene); - tolua_function(tolua_S,"popScene",lua_ax_base_Director_popScene); - tolua_function(tolua_S,"popToRootScene",lua_ax_base_Director_popToRootScene); - tolua_function(tolua_S,"popToSceneStackLevel",lua_ax_base_Director_popToSceneStackLevel); - tolua_function(tolua_S,"replaceScene",lua_ax_base_Director_replaceScene); - tolua_function(tolua_S,"endToLua",lua_ax_base_Director_end); - tolua_function(tolua_S,"pause",lua_ax_base_Director_pause); - tolua_function(tolua_S,"resume",lua_ax_base_Director_resume); - tolua_function(tolua_S,"restart",lua_ax_base_Director_restart); - tolua_function(tolua_S,"stopAnimation",lua_ax_base_Director_stopAnimation); - tolua_function(tolua_S,"startAnimation",lua_ax_base_Director_startAnimation); - tolua_function(tolua_S,"drawScene",lua_ax_base_Director_drawScene); - tolua_function(tolua_S,"purgeCachedData",lua_ax_base_Director_purgeCachedData); - tolua_function(tolua_S,"setDefaultValues",lua_ax_base_Director_setDefaultValues); - tolua_function(tolua_S,"setGLDefaultValues",lua_ax_base_Director_setGLDefaultValues); - tolua_function(tolua_S,"setClearColor",lua_ax_base_Director_setClearColor); - tolua_function(tolua_S,"mainLoop",lua_ax_base_Director_mainLoop); - tolua_function(tolua_S,"setContentScaleFactor",lua_ax_base_Director_setContentScaleFactor); - tolua_function(tolua_S,"getContentScaleFactor",lua_ax_base_Director_getContentScaleFactor); - tolua_function(tolua_S,"getScheduler",lua_ax_base_Director_getScheduler); - tolua_function(tolua_S,"setScheduler",lua_ax_base_Director_setScheduler); - tolua_function(tolua_S,"getActionManager",lua_ax_base_Director_getActionManager); - tolua_function(tolua_S,"setActionManager",lua_ax_base_Director_setActionManager); - tolua_function(tolua_S,"getEventDispatcher",lua_ax_base_Director_getEventDispatcher); - tolua_function(tolua_S,"setEventDispatcher",lua_ax_base_Director_setEventDispatcher); - tolua_function(tolua_S,"getRenderer",lua_ax_base_Director_getRenderer); - tolua_function(tolua_S,"getDeltaTime",lua_ax_base_Director_getDeltaTime); - tolua_function(tolua_S,"getFrameRate",lua_ax_base_Director_getFrameRate); - tolua_function(tolua_S,"pushMatrix",lua_ax_base_Director_pushMatrix); - tolua_function(tolua_S,"popMatrix",lua_ax_base_Director_popMatrix); - tolua_function(tolua_S,"loadIdentityMatrix",lua_ax_base_Director_loadIdentityMatrix); - tolua_function(tolua_S,"loadMatrix",lua_ax_base_Director_loadMatrix); - tolua_function(tolua_S,"multiplyMatrix",lua_ax_base_Director_multiplyMatrix); - tolua_function(tolua_S,"getMatrix",lua_ax_base_Director_getMatrix); - tolua_function(tolua_S,"resetMatrixStack",lua_ax_base_Director_resetMatrixStack); - tolua_function(tolua_S,"getAxmolThreadId",lua_ax_base_Director_getAxmolThreadId); - tolua_function(tolua_S,"setChildrenIndexerEnabled",lua_ax_base_Director_setChildrenIndexerEnabled); - tolua_function(tolua_S,"isChildrenIndexerEnabled",lua_ax_base_Director_isChildrenIndexerEnabled); - tolua_function(tolua_S,"isValid",lua_ax_base_Director_isValid); - tolua_function(tolua_S,"getInstance", lua_ax_base_Director_getInstance); - tolua_function(tolua_S,"destroyInstance", lua_ax_base_Director_destroyInstance); + + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_constructor'", nullptr); + return 0; + } + cobj = new ax::Animation(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Animation"); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:Animation",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_constructor'.",&tolua_err); +#endif + + return 0; +} + +static int lua_ax_base_Animation_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Animation)"); + return 0; +} + +int lua_register_ax_base_Animation(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Animation"); + tolua_cclass(tolua_S,"Animation","ax.Animation","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Animation"); + tolua_function(tolua_S,"new",lua_ax_base_Animation_constructor); + tolua_function(tolua_S,"addSpriteFrame",lua_ax_base_Animation_addSpriteFrame); + tolua_function(tolua_S,"addSpriteFrameWithFile",lua_ax_base_Animation_addSpriteFrameWithFile); + tolua_function(tolua_S,"addSpriteFrameWithTexture",lua_ax_base_Animation_addSpriteFrameWithTexture); + tolua_function(tolua_S,"getTotalDelayUnits",lua_ax_base_Animation_getTotalDelayUnits); + tolua_function(tolua_S,"setDelayPerUnit",lua_ax_base_Animation_setDelayPerUnit); + tolua_function(tolua_S,"getDelayPerUnit",lua_ax_base_Animation_getDelayPerUnit); + tolua_function(tolua_S,"getDuration",lua_ax_base_Animation_getDuration); + tolua_function(tolua_S,"getFrames",lua_ax_base_Animation_getFrames); + tolua_function(tolua_S,"setFrames",lua_ax_base_Animation_setFrames); + tolua_function(tolua_S,"getRestoreOriginalFrame",lua_ax_base_Animation_getRestoreOriginalFrame); + tolua_function(tolua_S,"setRestoreOriginalFrame",lua_ax_base_Animation_setRestoreOriginalFrame); + tolua_function(tolua_S,"getLoops",lua_ax_base_Animation_getLoops); + tolua_function(tolua_S,"setLoops",lua_ax_base_Animation_setLoops); + tolua_function(tolua_S,"clone",lua_ax_base_Animation_clone); + tolua_function(tolua_S,"init",lua_ax_base_Animation_init); + tolua_function(tolua_S,"initWithSpriteFrames",lua_ax_base_Animation_initWithSpriteFrames); + tolua_function(tolua_S,"initWithAnimationFrames",lua_ax_base_Animation_initWithAnimationFrames); + tolua_function(tolua_S,"create", lua_ax_base_Animation_create); + tolua_function(tolua_S,"createWithSpriteFrames", lua_ax_base_Animation_createWithSpriteFrames); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Director).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Director"; - g_typeCast[typeName] = "ax.Director"; + auto typeName = typeid(ax::Animation).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Animation"; + g_typeCast[typeName] = "ax.Animation"; return 1; } -int lua_ax_base_Timer_setupTimerWithInterval(lua_State* tolua_S) +int lua_ax_base_ActionInterval_getElapsed(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::ActionInterval* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17906,54 +18154,45 @@ int lua_ax_base_Timer_setupTimerWithInterval(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_setupTimerWithInterval'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_getElapsed'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 0) { - double arg0; - unsigned int arg1; - double arg2; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:setupTimerWithInterval"); - - ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Timer:setupTimerWithInterval"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Timer:setupTimerWithInterval"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_setupTimerWithInterval'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_getElapsed'", nullptr); return 0; } - cobj->setupTimerWithInterval(arg0, arg1, arg2); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getElapsed(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:setupTimerWithInterval",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:getElapsed",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_setupTimerWithInterval'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_getElapsed'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_setAborted(lua_State* tolua_S) +int lua_ax_base_ActionInterval_setAmplitudeRate(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::ActionInterval* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -17962,45 +18201,48 @@ int lua_ax_base_Timer_setAborted(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_setAborted'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_setAmplitudeRate'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionInterval:setAmplitudeRate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_setAborted'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_setAmplitudeRate'", nullptr); return 0; } - cobj->setAborted(); + cobj->setAmplitudeRate(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:setAborted",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:setAmplitudeRate",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_setAborted'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_setAmplitudeRate'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_isAborted(lua_State* tolua_S) +int lua_ax_base_ActionInterval_getAmplitudeRate(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::ActionInterval* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18009,45 +18251,45 @@ int lua_ax_base_Timer_isAborted(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_isAborted'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_getAmplitudeRate'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_isAborted'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_getAmplitudeRate'", nullptr); return 0; } - auto&& ret = cobj->isAborted(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getAmplitudeRate(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:isAborted",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:getAmplitudeRate",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_isAborted'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_getAmplitudeRate'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_isExhausted(lua_State* tolua_S) +int lua_ax_base_ActionInterval_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::ActionInterval* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18056,45 +18298,71 @@ int lua_ax_base_Timer_isExhausted(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_isExhausted'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionInterval:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_isExhausted'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->isExhausted(); + auto&& ret = cobj->initWithDuration(arg0); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:isExhausted",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:initWithDuration",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_isExhausted'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_trigger(lua_State* tolua_S) +static int lua_ax_base_ActionInterval_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (ActionInterval)"); + return 0; +} + +int lua_register_ax_base_ActionInterval(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.ActionInterval"); + tolua_cclass(tolua_S,"ActionInterval","ax.ActionInterval","ax.FiniteTimeAction",nullptr); + + tolua_beginmodule(tolua_S,"ActionInterval"); + tolua_function(tolua_S,"getElapsed",lua_ax_base_ActionInterval_getElapsed); + tolua_function(tolua_S,"setAmplitudeRate",lua_ax_base_ActionInterval_setAmplitudeRate); + tolua_function(tolua_S,"getAmplitudeRate",lua_ax_base_ActionInterval_getAmplitudeRate); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_ActionInterval_initWithDuration); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::ActionInterval).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.ActionInterval"; + g_typeCast[typeName] = "ax.ActionInterval"; + return 1; +} + +int lua_ax_base_Sequence_initWithTwoActions(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::Sequence* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18103,48 +18371,51 @@ int lua_ax_base_Timer_trigger(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Sequence",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Sequence*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_trigger'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Sequence_initWithTwoActions'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - double arg0; + ax::FiniteTimeAction* arg0; + ax::FiniteTimeAction* arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:trigger"); + ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Sequence:initWithTwoActions"); + + ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.Sequence:initWithTwoActions"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_trigger'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_initWithTwoActions'", nullptr); return 0; } - cobj->trigger(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithTwoActions(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:trigger",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:initWithTwoActions",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_trigger'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_initWithTwoActions'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_cancel(lua_State* tolua_S) +int lua_ax_base_Sequence_init(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::Sequence* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18153,45 +18424,48 @@ int lua_ax_base_Timer_cancel(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Sequence",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Sequence*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_cancel'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Sequence_init'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vector arg0; + + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Sequence:init"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_cancel'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_init'", nullptr); return 0; } - cobj->cancel(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->init(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:cancel",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:init",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_cancel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_init'.",&tolua_err); #endif return 0; } -int lua_ax_base_Timer_update(lua_State* tolua_S) +int lua_ax_base_Sequence_constructor(lua_State* tolua_S) { int argc = 0; - ax::Timer* cobj = nullptr; + ax::Sequence* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18199,75 +18473,58 @@ int lua_ax_base_Timer_update(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_update'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_update'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_constructor'", nullptr); return 0; } - cobj->update(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::Sequence(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Sequence"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:update",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:Sequence",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_update'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Timer_finalize(lua_State* tolua_S) + +static int lua_ax_base_Sequence_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Timer)"); + AXLOGV("luabindings: finalizing LUA object (Sequence)"); return 0; } -int lua_register_ax_base_Timer(lua_State* tolua_S) +int lua_register_ax_base_Sequence(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Timer"); - tolua_cclass(tolua_S,"Timer","ax.Timer","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.Sequence"); + tolua_cclass(tolua_S,"Sequence","ax.Sequence","ax.ActionInterval",nullptr); - tolua_beginmodule(tolua_S,"Timer"); - tolua_function(tolua_S,"setupTimerWithInterval",lua_ax_base_Timer_setupTimerWithInterval); - tolua_function(tolua_S,"setAborted",lua_ax_base_Timer_setAborted); - tolua_function(tolua_S,"isAborted",lua_ax_base_Timer_isAborted); - tolua_function(tolua_S,"isExhausted",lua_ax_base_Timer_isExhausted); - tolua_function(tolua_S,"trigger",lua_ax_base_Timer_trigger); - tolua_function(tolua_S,"cancel",lua_ax_base_Timer_cancel); - tolua_function(tolua_S,"update",lua_ax_base_Timer_update); + tolua_beginmodule(tolua_S,"Sequence"); + tolua_function(tolua_S,"new",lua_ax_base_Sequence_constructor); + tolua_function(tolua_S,"initWithTwoActions",lua_ax_base_Sequence_initWithTwoActions); + tolua_function(tolua_S,"init",lua_ax_base_Sequence_init); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Timer).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Timer"; - g_typeCast[typeName] = "ax.Timer"; + auto typeName = typeid(ax::Sequence).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Sequence"; + g_typeCast[typeName] = "ax.Sequence"; return 1; } -int lua_ax_base_Scheduler_getTimeScale(lua_State* tolua_S) +int lua_ax_base_Repeat_setInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Scheduler* cobj = nullptr; + ax::Repeat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18276,45 +18533,48 @@ int lua_ax_base_Scheduler_getTimeScale(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_getTimeScale'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_setInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::FiniteTimeAction* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:setInnerAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_getTimeScale'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_setInnerAction'", nullptr); return 0; } - auto&& ret = cobj->getTimeScale(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setInnerAction(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:getTimeScale",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:setInnerAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_getTimeScale'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_setInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scheduler_setTimeScale(lua_State* tolua_S) +int lua_ax_base_Repeat_getInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Scheduler* cobj = nullptr; + ax::Repeat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18323,48 +18583,45 @@ int lua_ax_base_Scheduler_setTimeScale(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_setTimeScale'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_getInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scheduler:setTimeScale"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_setTimeScale'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_getInnerAction'", nullptr); return 0; } - cobj->setTimeScale(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getInnerAction(); + object_to_luaval(tolua_S, "ax.FiniteTimeAction",(ax::FiniteTimeAction*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:setTimeScale",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:getInnerAction",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_setTimeScale'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_getInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scheduler_runOnAxmolThread(lua_State* tolua_S) +int lua_ax_base_Repeat_initWithAction(lua_State* tolua_S) { int argc = 0; - ax::Scheduler* cobj = nullptr; + ax::Repeat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18373,99 +18630,89 @@ int lua_ax_base_Scheduler_runOnAxmolThread(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_runOnAxmolThread'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_initWithAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - std::function arg0; + ax::FiniteTimeAction* arg0; + unsigned int arg1; - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:initWithAction"); + + ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Repeat:initWithAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_runOnAxmolThread'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_initWithAction'", nullptr); return 0; } - cobj->runOnAxmolThread(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithAction(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:runOnAxmolThread",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:initWithAction",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_runOnAxmolThread'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_initWithAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Scheduler_removeAllPendingActions(lua_State* tolua_S) +int lua_ax_base_Repeat_create(lua_State* tolua_S) { int argc = 0; - ax::Scheduler* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_removeAllPendingActions'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::FiniteTimeAction* arg0; + unsigned int arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:create"); + ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Repeat:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_removeAllPendingActions'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_create'", nullptr); return 0; } - cobj->removeAllPendingActions(); - lua_settop(tolua_S, 1); + auto&& ret = ax::Repeat::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.Repeat",(ax::Repeat*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:removeAllPendingActions",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Repeat:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_removeAllPendingActions'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Scheduler_constructor(lua_State* tolua_S) +int lua_ax_base_Repeat_constructor(lua_State* tolua_S) { int argc = 0; - ax::Scheduler* cobj = nullptr; + ax::Repeat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18475,58 +18722,58 @@ int lua_ax_base_Scheduler_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_constructor'", nullptr); return 0; } - cobj = new ax::Scheduler(); + cobj = new ax::Repeat(); cobj->autorelease(); int ID = (int)cobj->_ID ; int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Scheduler"); + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Repeat"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:Scheduler",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:Repeat",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Scheduler_finalize(lua_State* tolua_S) +static int lua_ax_base_Repeat_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Scheduler)"); + AXLOGV("luabindings: finalizing LUA object (Repeat)"); return 0; } -int lua_register_ax_base_Scheduler(lua_State* tolua_S) +int lua_register_ax_base_Repeat(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Scheduler"); - tolua_cclass(tolua_S,"Scheduler","ax.Scheduler","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.Repeat"); + tolua_cclass(tolua_S,"Repeat","ax.Repeat","ax.ActionInterval",nullptr); - tolua_beginmodule(tolua_S,"Scheduler"); - tolua_function(tolua_S,"new",lua_ax_base_Scheduler_constructor); - tolua_function(tolua_S,"getTimeScale",lua_ax_base_Scheduler_getTimeScale); - tolua_function(tolua_S,"setTimeScale",lua_ax_base_Scheduler_setTimeScale); - tolua_function(tolua_S,"runOnAxmolThread",lua_ax_base_Scheduler_runOnAxmolThread); - tolua_function(tolua_S,"removeAllPendingActions",lua_ax_base_Scheduler_removeAllPendingActions); + tolua_beginmodule(tolua_S,"Repeat"); + tolua_function(tolua_S,"new",lua_ax_base_Repeat_constructor); + tolua_function(tolua_S,"setInnerAction",lua_ax_base_Repeat_setInnerAction); + tolua_function(tolua_S,"getInnerAction",lua_ax_base_Repeat_getInnerAction); + tolua_function(tolua_S,"initWithAction",lua_ax_base_Repeat_initWithAction); + tolua_function(tolua_S,"create", lua_ax_base_Repeat_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Scheduler).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Scheduler"; - g_typeCast[typeName] = "ax.Scheduler"; + auto typeName = typeid(ax::Repeat).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Repeat"; + g_typeCast[typeName] = "ax.Repeat"; return 1; } -int lua_ax_base_Action_clone(lua_State* tolua_S) +int lua_ax_base_RepeatForever_setInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RepeatForever* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18535,45 +18782,48 @@ int lua_ax_base_Action_clone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_clone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_setInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::ActionInterval* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:setInnerAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_clone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_setInnerAction'", nullptr); return 0; } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); + cobj->setInnerAction(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:clone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:setInnerAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_clone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_setInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_reverse(lua_State* tolua_S) +int lua_ax_base_RepeatForever_getInnerAction(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RepeatForever* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18582,45 +18832,45 @@ int lua_ax_base_Action_reverse(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_reverse'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_getInnerAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_reverse'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_getInnerAction'", nullptr); return 0; } - auto&& ret = cobj->reverse(); - object_to_luaval(tolua_S, "ax.Action",(ax::Action*)ret); + auto&& ret = cobj->getInnerAction(); + object_to_luaval(tolua_S, "ax.ActionInterval",(ax::ActionInterval*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:reverse",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:getInnerAction",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_reverse'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_getInnerAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_isDone(lua_State* tolua_S) +int lua_ax_base_RepeatForever_initWithAction(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RepeatForever* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18629,95 +18879,84 @@ int lua_ax_base_Action_isDone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_isDone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_initWithAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::ActionInterval* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:initWithAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_isDone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_initWithAction'", nullptr); return 0; } - auto&& ret = cobj->isDone(); + auto&& ret = cobj->initWithAction(arg0); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:isDone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:initWithAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_isDone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_initWithAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_startWithTarget(lua_State* tolua_S) +int lua_ax_base_RepeatForever_create(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_startWithTarget'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:startWithTarget"); + ax::ActionInterval* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_startWithTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_create'", nullptr); return 0; } - cobj->startWithTarget(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::RepeatForever::create(arg0); + object_to_luaval(tolua_S, "ax.RepeatForever",(ax::RepeatForever*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:startWithTarget",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RepeatForever:create",argc, 1); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_startWithTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Action_stop(lua_State* tolua_S) +int lua_ax_base_RepeatForever_constructor(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RepeatForever* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18725,46 +18964,60 @@ int lua_ax_base_Action_stop(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_stop'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_stop'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_constructor'", nullptr); return 0; } - cobj->stop(); - lua_settop(tolua_S, 1); + cobj = new ax::RepeatForever(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RepeatForever"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:stop",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:RepeatForever",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_stop'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_step(lua_State* tolua_S) + +static int lua_ax_base_RepeatForever_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (RepeatForever)"); + return 0; +} + +int lua_register_ax_base_RepeatForever(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.RepeatForever"); + tolua_cclass(tolua_S,"RepeatForever","ax.RepeatForever","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"RepeatForever"); + tolua_function(tolua_S,"new",lua_ax_base_RepeatForever_constructor); + tolua_function(tolua_S,"setInnerAction",lua_ax_base_RepeatForever_setInnerAction); + tolua_function(tolua_S,"getInnerAction",lua_ax_base_RepeatForever_getInnerAction); + tolua_function(tolua_S,"initWithAction",lua_ax_base_RepeatForever_initWithAction); + tolua_function(tolua_S,"create", lua_ax_base_RepeatForever_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::RepeatForever).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.RepeatForever"; + g_typeCast[typeName] = "ax.RepeatForever"; + return 1; +} + +int lua_ax_base_Spawn_initWithTwoActions(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::Spawn* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18773,48 +19026,51 @@ int lua_ax_base_Action_step(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Spawn",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Spawn*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_step'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Spawn_initWithTwoActions'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - double arg0; + ax::FiniteTimeAction* arg0; + ax::FiniteTimeAction* arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Action:step"); + ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Spawn:initWithTwoActions"); + + ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.Spawn:initWithTwoActions"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_step'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_initWithTwoActions'", nullptr); return 0; } - cobj->step(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithTwoActions(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:step",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:initWithTwoActions",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_step'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_initWithTwoActions'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_update(lua_State* tolua_S) +int lua_ax_base_Spawn_init(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::Spawn* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18823,48 +19079,48 @@ int lua_ax_base_Action_update(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Spawn",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Spawn*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_update'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Spawn_init'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + ax::Vector arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Action:update"); + ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Spawn:init"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_update'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_init'", nullptr); return 0; } - cobj->update(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->init(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:update",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:init",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_update'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_init'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_getTarget(lua_State* tolua_S) +int lua_ax_base_Spawn_constructor(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::Spawn* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -18872,143 +19128,198 @@ int lua_ax_base_Action_getTarget(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getTarget'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_constructor'", nullptr); return 0; } - auto&& ret = cobj->getTarget(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + cobj = new ax::Spawn(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Spawn"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getTarget",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:Spawn",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_setTarget(lua_State* tolua_S) + +static int lua_ax_base_Spawn_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Spawn)"); + return 0; +} + +int lua_register_ax_base_Spawn(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Spawn"); + tolua_cclass(tolua_S,"Spawn","ax.Spawn","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"Spawn"); + tolua_function(tolua_S,"new",lua_ax_base_Spawn_constructor); + tolua_function(tolua_S,"initWithTwoActions",lua_ax_base_Spawn_initWithTwoActions); + tolua_function(tolua_S,"init",lua_ax_base_Spawn_init); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Spawn).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Spawn"; + g_typeCast[typeName] = "ax.Spawn"; + return 1; +} + +int lua_ax_base_RotateTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RotateTo* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RotateTo",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::RotateTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RotateTo_initWithDuration'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Node* arg0; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:initWithDuration"); - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:setTarget"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setTarget'", nullptr); - return 0; + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->setTarget(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setTarget",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 3) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:initWithDuration"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:initWithDuration"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateTo:initWithDuration",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_getOriginalTarget(lua_State* tolua_S) +int lua_ax_base_RotateTo_create(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.RotateTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getOriginalTarget'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:create"); + if (!ok) { break; } + ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); + return 1; + } + } while (0); + ok = true; + do { - if(!ok) + if (argc == 3) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getOriginalTarget'", nullptr); - return 0; + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateTo:create"); + if (!ok) { break; } + ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); + return 1; } - auto&& ret = cobj->getOriginalTarget(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getOriginalTarget",argc, 0); + } while (0); + ok = true; + do + { + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateTo:create"); + if (!ok) { break; } + ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.RotateTo:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getOriginalTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Action_setOriginalTarget(lua_State* tolua_S) +int lua_ax_base_RotateTo_constructor(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RotateTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19016,193 +19327,214 @@ int lua_ax_base_Action_setOriginalTarget(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setOriginalTarget'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Action:setOriginalTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setOriginalTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RotateTo_constructor'", nullptr); return 0; } - cobj->setOriginalTarget(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::RotateTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RotateTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setOriginalTarget",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateTo:RotateTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setOriginalTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_getTag(lua_State* tolua_S) + +static int lua_ax_base_RotateTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (RotateTo)"); + return 0; +} + +int lua_register_ax_base_RotateTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.RotateTo"); + tolua_cclass(tolua_S,"RotateTo","ax.RotateTo","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"RotateTo"); + tolua_function(tolua_S,"new",lua_ax_base_RotateTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_RotateTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_RotateTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::RotateTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.RotateTo"; + g_typeCast[typeName] = "ax.RotateTo"; + return 1; +} + +int lua_ax_base_RotateBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RotateBy* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RotateBy",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::RotateBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RotateBy_initWithDuration'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getTag'", nullptr); - return 0; - } - auto&& ret = cobj->getTag(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getTag",argc, 0); - return 0; + do{ + if (argc == 3) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getTag'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_Action_setTag(lua_State* tolua_S) -{ - int argc = 0; - ax::Action* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:initWithDuration"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateBy:initWithDuration"); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; -#endif + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:initWithDuration"); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setTag'", nullptr); - return 0; - } -#endif + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateBy:initWithDuration"); - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Action:setTag"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setTag'", nullptr); - return 0; + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - cobj->setTag(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setTag",argc, 1); + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateBy:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Action_getFlags(lua_State* tolua_S) +int lua_ax_base_RotateBy_create(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.RotateBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_getFlags'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 3) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateBy:create"); + if (!ok) { break; } + ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); + return 1; + } + } while (0); + ok = true; + do { - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_getFlags'", nullptr); - return 0; + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:create"); + if (!ok) { break; } + ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); + return 1; } - auto&& ret = cobj->getFlags(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:getFlags",argc, 0); + } while (0); + ok = true; + do + { + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateBy:create"); + if (!ok) { break; } + ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.RotateBy:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_getFlags'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Action_setFlags(lua_State* tolua_S) +int lua_ax_base_RotateBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::Action* cobj = nullptr; + ax::RotateBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19210,298 +19542,351 @@ int lua_ax_base_Action_setFlags(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Action",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Action*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Action_setFlags'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - unsigned int arg0; - - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Action:setFlags"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Action_setFlags'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RotateBy_constructor'", nullptr); return 0; } - cobj->setFlags(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::RotateBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RotateBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Action:setFlags",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateBy:RotateBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Action_setFlags'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Action_finalize(lua_State* tolua_S) + +static int lua_ax_base_RotateBy_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Action)"); + AXLOGV("luabindings: finalizing LUA object (RotateBy)"); return 0; } -int lua_register_ax_base_Action(lua_State* tolua_S) +int lua_register_ax_base_RotateBy(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Action"); - tolua_cclass(tolua_S,"Action","ax.Action","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.RotateBy"); + tolua_cclass(tolua_S,"RotateBy","ax.RotateBy","ax.ActionInterval",nullptr); - tolua_beginmodule(tolua_S,"Action"); - tolua_function(tolua_S,"clone",lua_ax_base_Action_clone); - tolua_function(tolua_S,"reverse",lua_ax_base_Action_reverse); - tolua_function(tolua_S,"isDone",lua_ax_base_Action_isDone); - tolua_function(tolua_S,"startWithTarget",lua_ax_base_Action_startWithTarget); - tolua_function(tolua_S,"stop",lua_ax_base_Action_stop); - tolua_function(tolua_S,"step",lua_ax_base_Action_step); - tolua_function(tolua_S,"update",lua_ax_base_Action_update); - tolua_function(tolua_S,"getTarget",lua_ax_base_Action_getTarget); - tolua_function(tolua_S,"setTarget",lua_ax_base_Action_setTarget); - tolua_function(tolua_S,"getOriginalTarget",lua_ax_base_Action_getOriginalTarget); - tolua_function(tolua_S,"setOriginalTarget",lua_ax_base_Action_setOriginalTarget); - tolua_function(tolua_S,"getTag",lua_ax_base_Action_getTag); - tolua_function(tolua_S,"setTag",lua_ax_base_Action_setTag); - tolua_function(tolua_S,"getFlags",lua_ax_base_Action_getFlags); - tolua_function(tolua_S,"setFlags",lua_ax_base_Action_setFlags); + tolua_beginmodule(tolua_S,"RotateBy"); + tolua_function(tolua_S,"new",lua_ax_base_RotateBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_RotateBy_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_RotateBy_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Action).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Action"; - g_typeCast[typeName] = "ax.Action"; + auto typeName = typeid(ax::RotateBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.RotateBy"; + g_typeCast[typeName] = "ax.RotateBy"; return 1; } -int lua_ax_base_FiniteTimeAction_getDuration(lua_State* tolua_S) +int lua_ax_base_MoveBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::FiniteTimeAction* cobj = nullptr; + ax::MoveBy* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.FiniteTimeAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.MoveBy",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::FiniteTimeAction*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::MoveBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FiniteTimeAction_getDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_MoveBy_initWithDuration'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FiniteTimeAction_getDuration'", nullptr); - return 0; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:initWithDuration"); + + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveBy:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - auto&& ret = cobj->getDuration(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FiniteTimeAction:getDuration",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:initWithDuration"); + + if (!ok) { break; } + ax::Vec2 arg1; + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveBy:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveBy:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FiniteTimeAction_getDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_FiniteTimeAction_setDuration(lua_State* tolua_S) +int lua_ax_base_MoveBy_create(lua_State* tolua_S) { int argc = 0; - ax::FiniteTimeAction* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.FiniteTimeAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.MoveBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::FiniteTimeAction*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FiniteTimeAction_setDuration'", nullptr); - return 0; - } + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:create"); + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveBy:create"); + if (!ok) { break; } + ax::MoveBy* ret = ax::MoveBy::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.MoveBy",(ax::MoveBy*)ret); + return 1; + } + } while (0); + ok = true; + do + { + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:create"); + if (!ok) { break; } + ax::Vec2 arg1; + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveBy:create"); + if (!ok) { break; } + ax::MoveBy* ret = ax::MoveBy::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.MoveBy",(ax::MoveBy*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.MoveBy:create",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_create'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_MoveBy_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::MoveBy* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FiniteTimeAction:setDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FiniteTimeAction_setDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MoveBy_constructor'", nullptr); return 0; } - cobj->setDuration(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::MoveBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.MoveBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FiniteTimeAction:setDuration",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveBy:MoveBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FiniteTimeAction_setDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_FiniteTimeAction_finalize(lua_State* tolua_S) + +static int lua_ax_base_MoveBy_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (FiniteTimeAction)"); + AXLOGV("luabindings: finalizing LUA object (MoveBy)"); return 0; } -int lua_register_ax_base_FiniteTimeAction(lua_State* tolua_S) +int lua_register_ax_base_MoveBy(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.FiniteTimeAction"); - tolua_cclass(tolua_S,"FiniteTimeAction","ax.FiniteTimeAction","ax.Action",nullptr); + tolua_usertype(tolua_S,"ax.MoveBy"); + tolua_cclass(tolua_S,"MoveBy","ax.MoveBy","ax.ActionInterval",nullptr); - tolua_beginmodule(tolua_S,"FiniteTimeAction"); - tolua_function(tolua_S,"getDuration",lua_ax_base_FiniteTimeAction_getDuration); - tolua_function(tolua_S,"setDuration",lua_ax_base_FiniteTimeAction_setDuration); + tolua_beginmodule(tolua_S,"MoveBy"); + tolua_function(tolua_S,"new",lua_ax_base_MoveBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_MoveBy_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_MoveBy_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::FiniteTimeAction).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.FiniteTimeAction"; - g_typeCast[typeName] = "ax.FiniteTimeAction"; + auto typeName = typeid(ax::MoveBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.MoveBy"; + g_typeCast[typeName] = "ax.MoveBy"; return 1; } -int lua_ax_base_Speed_getSpeed(lua_State* tolua_S) +int lua_ax_base_MoveTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; + ax::MoveTo* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.MoveTo",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::MoveTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_getSpeed'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_MoveTo_initWithDuration'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_getSpeed'", nullptr); - return 0; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:initWithDuration"); + + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - auto&& ret = cobj->getSpeed(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:getSpeed",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:initWithDuration"); + + if (!ok) { break; } + ax::Vec2 arg1; + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveTo:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_getSpeed'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Speed_setSpeed(lua_State* tolua_S) +int lua_ax_base_MoveTo_create(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.MoveTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_setSpeed'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:create"); + if (!ok) { break; } + ax::Vec3 arg1; + ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveTo:create"); + if (!ok) { break; } + ax::MoveTo* ret = ax::MoveTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.MoveTo",(ax::MoveTo*)ret); + return 1; + } + } while (0); + ok = true; + do { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Speed:setSpeed"); - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_setSpeed'", nullptr); - return 0; + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:create"); + if (!ok) { break; } + ax::Vec2 arg1; + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveTo:create"); + if (!ok) { break; } + ax::MoveTo* ret = ax::MoveTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.MoveTo",(ax::MoveTo*)ret); + return 1; } - cobj->setSpeed(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:setSpeed",argc, 1); + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.MoveTo:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_setSpeed'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Speed_setInnerAction(lua_State* tolua_S) +int lua_ax_base_MoveTo_constructor(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; + ax::MoveTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19509,96 +19894,213 @@ int lua_ax_base_Speed_setInnerAction(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MoveTo_constructor'", nullptr); + return 0; + } + cobj = new ax::MoveTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.MoveTo"); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveTo:MoveTo",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_constructor'.",&tolua_err); +#endif + + return 0; +} + +static int lua_ax_base_MoveTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (MoveTo)"); + return 0; +} + +int lua_register_ax_base_MoveTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.MoveTo"); + tolua_cclass(tolua_S,"MoveTo","ax.MoveTo","ax.MoveBy",nullptr); + + tolua_beginmodule(tolua_S,"MoveTo"); + tolua_function(tolua_S,"new",lua_ax_base_MoveTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_MoveTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_MoveTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::MoveTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.MoveTo"; + g_typeCast[typeName] = "ax.MoveTo"; + return 1; +} + +int lua_ax_base_SkewTo_initWithDuration(lua_State* tolua_S) +{ + int argc = 0; + ax::SkewTo* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.SkewTo",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::SkewTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SkewTo_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 3) { - ax::ActionInterval* arg0; + double arg0; + double arg1; + double arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:setInnerAction"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewTo:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewTo:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_initWithDuration'", nullptr); return 0; } - cobj->setInnerAction(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:setInnerAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewTo:initWithDuration",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_setInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Speed_getInnerAction(lua_State* tolua_S) +int lua_ax_base_SkewTo_create(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.SkewTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 3) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_getInnerAction'", nullptr); - return 0; + double arg0; + double arg1; + double arg2; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewTo:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewTo:create"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewTo:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_create'", nullptr); + return 0; + } + auto&& ret = ax::SkewTo::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.SkewTo",(ax::SkewTo*)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.SkewTo:create",argc, 3); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_create'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_SkewTo_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::SkewTo* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_getInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_constructor'", nullptr); return 0; } - auto&& ret = cobj->getInnerAction(); - object_to_luaval(tolua_S, "ax.ActionInterval",(ax::ActionInterval*)ret); + cobj = new ax::SkewTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SkewTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:getInnerAction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewTo:SkewTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_getInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Speed_initWithAction(lua_State* tolua_S) + +static int lua_ax_base_SkewTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (SkewTo)"); + return 0; +} + +int lua_register_ax_base_SkewTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.SkewTo"); + tolua_cclass(tolua_S,"SkewTo","ax.SkewTo","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"SkewTo"); + tolua_function(tolua_S,"new",lua_ax_base_SkewTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_SkewTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_SkewTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::SkewTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.SkewTo"; + g_typeCast[typeName] = "ax.SkewTo"; + return 1; +} + +int lua_ax_base_SkewBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; + ax::SkewBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19607,48 +20109,51 @@ int lua_ax_base_Speed_initWithAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.SkewBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Speed*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::SkewBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Speed_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SkewBy_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 3) { - ax::ActionInterval* arg0; + double arg0; double arg1; + double arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:initWithAction"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewBy:initWithDuration"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Speed:initWithAction"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewBy:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewBy:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->initWithAction(arg0, arg1); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:initWithAction",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewBy:initWithDuration",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_initWithAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Speed_create(lua_State* tolua_S) +int lua_ax_base_SkewBy_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -19658,38 +20163,40 @@ int lua_ax_base_Speed_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Speed",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.SkewBy",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 2) + if (argc == 3) { - ax::ActionInterval* arg0; + double arg0; double arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.Speed:create"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Speed:create"); + double arg2; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewBy:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewBy:create"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewBy:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_create'", nullptr); return 0; } - auto&& ret = ax::Speed::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.Speed",(ax::Speed*)ret); + auto&& ret = ax::SkewBy::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.SkewBy",(ax::SkewBy*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Speed:create",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.SkewBy:create",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_create'.",&tolua_err); #endif return 0; } -int lua_ax_base_Speed_constructor(lua_State* tolua_S) +int lua_ax_base_SkewBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::Speed* cobj = nullptr; + ax::SkewBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19699,60 +20206,56 @@ int lua_ax_base_Speed_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Speed_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_constructor'", nullptr); return 0; } - cobj = new ax::Speed(); + cobj = new ax::SkewBy(); cobj->autorelease(); int ID = (int)cobj->_ID ; int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Speed"); + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SkewBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Speed:Speed",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewBy:SkewBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Speed_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Speed_finalize(lua_State* tolua_S) +static int lua_ax_base_SkewBy_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Speed)"); + AXLOGV("luabindings: finalizing LUA object (SkewBy)"); return 0; } -int lua_register_ax_base_Speed(lua_State* tolua_S) +int lua_register_ax_base_SkewBy(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Speed"); - tolua_cclass(tolua_S,"Speed","ax.Speed","ax.Action",nullptr); + tolua_usertype(tolua_S,"ax.SkewBy"); + tolua_cclass(tolua_S,"SkewBy","ax.SkewBy","ax.SkewTo",nullptr); - tolua_beginmodule(tolua_S,"Speed"); - tolua_function(tolua_S,"new",lua_ax_base_Speed_constructor); - tolua_function(tolua_S,"getSpeed",lua_ax_base_Speed_getSpeed); - tolua_function(tolua_S,"setSpeed",lua_ax_base_Speed_setSpeed); - tolua_function(tolua_S,"setInnerAction",lua_ax_base_Speed_setInnerAction); - tolua_function(tolua_S,"getInnerAction",lua_ax_base_Speed_getInnerAction); - tolua_function(tolua_S,"initWithAction",lua_ax_base_Speed_initWithAction); - tolua_function(tolua_S,"create", lua_ax_base_Speed_create); + tolua_beginmodule(tolua_S,"SkewBy"); + tolua_function(tolua_S,"new",lua_ax_base_SkewBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_SkewBy_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_SkewBy_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Speed).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Speed"; - g_typeCast[typeName] = "ax.Speed"; + auto typeName = typeid(ax::SkewBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.SkewBy"; + g_typeCast[typeName] = "ax.SkewBy"; return 1; } -int lua_ax_base_Follow_isBoundarySet(lua_State* tolua_S) +int lua_ax_base_JumpBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Follow* cobj = nullptr; + ax::JumpBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19761,95 +20264,99 @@ int lua_ax_base_Follow_isBoundarySet(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.JumpBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::JumpBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_isBoundarySet'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_JumpBy_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 4) { + double arg0; + ax::Vec2 arg1; + double arg2; + int arg3; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpBy:initWithDuration"); + + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpBy:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpBy:initWithDuration"); + + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpBy:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_isBoundarySet'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->isBoundarySet(); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:isBoundarySet",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpBy:initWithDuration",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_isBoundarySet'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Follow_setBoundarySet(lua_State* tolua_S) +int lua_ax_base_JumpBy_create(lua_State* tolua_S) { int argc = 0; - ax::Follow* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.JumpBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_setBoundarySet'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 4) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Follow:setBoundarySet"); + double arg0; + ax::Vec2 arg1; + double arg2; + int arg3; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpBy:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpBy:create"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpBy:create"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpBy:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_setBoundarySet'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_create'", nullptr); return 0; } - cobj->setBoundarySet(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::JumpBy::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.JumpBy",(ax::JumpBy*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:setBoundarySet",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.JumpBy:create",argc, 4); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_setBoundarySet'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Follow_initWithTarget(lua_State* tolua_S) +int lua_ax_base_JumpBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::Follow* cobj = nullptr; + ax::JumpBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19857,66 +20364,58 @@ int lua_ax_base_Follow_initWithTarget(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_initWithTarget'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTarget"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTarget'", nullptr); - return 0; - } - auto&& ret = cobj->initWithTarget(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 2) + if (argc == 0) { - ax::Node* arg0; - ax::Rect arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTarget"); - - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Follow:initWithTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_constructor'", nullptr); return 0; } - auto&& ret = cobj->initWithTarget(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj = new ax::JumpBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.JumpBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:initWithTarget",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpBy:JumpBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_initWithTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Follow_initWithTargetAndOffset(lua_State* tolua_S) + +static int lua_ax_base_JumpBy_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (JumpBy)"); + return 0; +} + +int lua_register_ax_base_JumpBy(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.JumpBy"); + tolua_cclass(tolua_S,"JumpBy","ax.JumpBy","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"JumpBy"); + tolua_function(tolua_S,"new",lua_ax_base_JumpBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_JumpBy_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_JumpBy_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::JumpBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.JumpBy"; + g_typeCast[typeName] = "ax.JumpBy"; + return 1; +} + +int lua_ax_base_JumpTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Follow* cobj = nullptr; + ax::JumpTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -19925,74 +20424,54 @@ int lua_ax_base_Follow_initWithTargetAndOffset(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.JumpTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Follow*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::JumpTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_JumpTo_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) - { - ax::Node* arg0; - double arg1; - double arg2; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTargetAndOffset"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:initWithTargetAndOffset"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:initWithTargetAndOffset"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); - return 0; - } - auto&& ret = cobj->initWithTargetAndOffset(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 4) + if (argc == 4) { - ax::Node* arg0; - double arg1; + double arg0; + ax::Vec2 arg1; double arg2; - ax::Rect arg3; + int arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:initWithTargetAndOffset"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpTo:initWithDuration"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:initWithTargetAndOffset"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpTo:initWithDuration"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:initWithTargetAndOffset"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpTo:initWithDuration"); - ok &= luaval_to_rect(tolua_S, 5, &arg3, "ax.Follow:initWithTargetAndOffset"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_initWithTargetAndOffset'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->initWithTargetAndOffset(arg0, arg1, arg2, arg3); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:initWithTargetAndOffset",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpTo:initWithDuration",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_initWithTargetAndOffset'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Follow_create(lua_State* tolua_S) +int lua_ax_base_JumpTo_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -20002,110 +20481,42 @@ int lua_ax_base_Follow_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.JumpTo",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) - { - ax::Node* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_create'", nullptr); - return 0; - } - auto&& ret = ax::Follow::create(arg0); - object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); - return 1; - } - if (argc == 2) + if (argc == 4) { - ax::Node* arg0; - ax::Rect arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:create"); - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Follow:create"); + double arg0; + ax::Vec2 arg1; + double arg2; + int arg3; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpTo:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpTo:create"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpTo:create"); + ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpTo:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_create'", nullptr); return 0; } - auto&& ret = ax::Follow::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); + auto&& ret = ax::JumpTo::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.JumpTo",(ax::JumpTo*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Follow:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.JumpTo:create",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_create'.",&tolua_err); #endif return 0; } -int lua_ax_base_Follow_createWithOffset(lua_State* tolua_S) +int lua_ax_base_JumpTo_constructor(lua_State* tolua_S) { int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Follow",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 3) - { - ax::Node* arg0; - double arg1; - double arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:createWithOffset"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:createWithOffset"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:createWithOffset"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_createWithOffset'", nullptr); - return 0; - } - auto&& ret = ax::Follow::createWithOffset(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); - return 1; - } - if (argc == 4) - { - ax::Node* arg0; - double arg1; - double arg2; - ax::Rect arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Follow:createWithOffset"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Follow:createWithOffset"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Follow:createWithOffset"); - ok &= luaval_to_rect(tolua_S, 5, &arg3, "ax.Follow:createWithOffset"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_createWithOffset'", nullptr); - return 0; - } - auto&& ret = ax::Follow::createWithOffset(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.Follow",(ax::Follow*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Follow:createWithOffset",argc, 3); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_createWithOffset'.",&tolua_err); -#endif - return 0; -} -int lua_ax_base_Follow_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::Follow* cobj = nullptr; + ax::JumpTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20115,60 +20526,56 @@ int lua_ax_base_Follow_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Follow_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_constructor'", nullptr); return 0; } - cobj = new ax::Follow(); + cobj = new ax::JumpTo(); cobj->autorelease(); int ID = (int)cobj->_ID ; int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Follow"); + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.JumpTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Follow:Follow",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpTo:JumpTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Follow_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Follow_finalize(lua_State* tolua_S) +static int lua_ax_base_JumpTo_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Follow)"); + AXLOGV("luabindings: finalizing LUA object (JumpTo)"); return 0; } -int lua_register_ax_base_Follow(lua_State* tolua_S) +int lua_register_ax_base_JumpTo(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Follow"); - tolua_cclass(tolua_S,"Follow","ax.Follow","ax.Action",nullptr); + tolua_usertype(tolua_S,"ax.JumpTo"); + tolua_cclass(tolua_S,"JumpTo","ax.JumpTo","ax.JumpBy",nullptr); - tolua_beginmodule(tolua_S,"Follow"); - tolua_function(tolua_S,"new",lua_ax_base_Follow_constructor); - tolua_function(tolua_S,"isBoundarySet",lua_ax_base_Follow_isBoundarySet); - tolua_function(tolua_S,"setBoundarySet",lua_ax_base_Follow_setBoundarySet); - tolua_function(tolua_S,"initWithTarget",lua_ax_base_Follow_initWithTarget); - tolua_function(tolua_S,"initWithTargetAndOffset",lua_ax_base_Follow_initWithTargetAndOffset); - tolua_function(tolua_S,"create", lua_ax_base_Follow_create); - tolua_function(tolua_S,"createWithOffset", lua_ax_base_Follow_createWithOffset); + tolua_beginmodule(tolua_S,"JumpTo"); + tolua_function(tolua_S,"new",lua_ax_base_JumpTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_JumpTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_JumpTo_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Follow).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Follow"; - g_typeCast[typeName] = "ax.Follow"; + auto typeName = typeid(ax::JumpTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.JumpTo"; + g_typeCast[typeName] = "ax.JumpTo"; return 1; } -int lua_ax_base_Image_initWithImageFile(lua_State* tolua_S) +int lua_ax_base_BezierBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::BezierBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20177,48 +20584,52 @@ int lua_ax_base_Image_initWithImageFile(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.BezierBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::BezierBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_initWithImageFile'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_BezierBy_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - std::string_view arg0; + double arg0; + ax::BezierConfig arg1; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:initWithImageFile"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.BezierBy:initWithDuration"); + + #pragma warning NO CONVERSION TO NATIVE FOR BezierConfig + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_initWithImageFile'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierBy_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->initWithImageFile(arg0); + auto&& ret = cobj->initWithDuration(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:initWithImageFile",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierBy:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_initWithImageFile'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_flipRawData(lua_State* tolua_S) +int lua_ax_base_BezierBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::BezierBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20226,46 +20637,57 @@ int lua_ax_base_Image_flipRawData(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_flipRawData'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_flipRawData'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierBy_constructor'", nullptr); return 0; } - cobj->flipRawData(); - lua_settop(tolua_S, 1); + cobj = new ax::BezierBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.BezierBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:flipRawData",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierBy:BezierBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_flipRawData'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierBy_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_getFileType(lua_State* tolua_S) + +static int lua_ax_base_BezierBy_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (BezierBy)"); + return 0; +} + +int lua_register_ax_base_BezierBy(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.BezierBy"); + tolua_cclass(tolua_S,"BezierBy","ax.BezierBy","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"BezierBy"); + tolua_function(tolua_S,"new",lua_ax_base_BezierBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_BezierBy_initWithDuration); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::BezierBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.BezierBy"; + g_typeCast[typeName] = "ax.BezierBy"; + return 1; +} + +int lua_ax_base_BezierTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::BezierTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20274,45 +20696,52 @@ int lua_ax_base_Image_getFileType(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.BezierTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::BezierTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getFileType'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_BezierTo_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + double arg0; + ax::BezierConfig arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.BezierTo:initWithDuration"); + + #pragma warning NO CONVERSION TO NATIVE FOR BezierConfig + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getFileType'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierTo_initWithDuration'", nullptr); return 0; } - int ret = (int)cobj->getFileType(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getFileType",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierTo:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getFileType'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_getPixelFormat(lua_State* tolua_S) +int lua_ax_base_BezierTo_constructor(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::BezierTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20320,140 +20749,227 @@ int lua_ax_base_Image_getPixelFormat(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getPixelFormat'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getPixelFormat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierTo_constructor'", nullptr); return 0; } - int ret = (int)cobj->getPixelFormat(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj = new ax::BezierTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.BezierTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getPixelFormat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierTo:BezierTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getPixelFormat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_getWidth(lua_State* tolua_S) + +static int lua_ax_base_BezierTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (BezierTo)"); + return 0; +} + +int lua_register_ax_base_BezierTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.BezierTo"); + tolua_cclass(tolua_S,"BezierTo","ax.BezierTo","ax.BezierBy",nullptr); + + tolua_beginmodule(tolua_S,"BezierTo"); + tolua_function(tolua_S,"new",lua_ax_base_BezierTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_BezierTo_initWithDuration); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::BezierTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.BezierTo"; + g_typeCast[typeName] = "ax.BezierTo"; + return 1; +} + +int lua_ax_base_ScaleTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::ScaleTo* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ScaleTo",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::ScaleTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getWidth'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ScaleTo_initWithDuration'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getWidth'", nullptr); - return 0; + do{ + if (argc == 3) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1, arg2); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } - auto&& ret = cobj->getWidth(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getWidth",argc, 0); + }while(0); + ok = true; + do{ + if (argc == 2) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 4) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + double arg3; + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleTo:initWithDuration"); + + if (!ok) { break; } + bool ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleTo:initWithDuration",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getWidth'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_getHeight(lua_State* tolua_S) +int lua_ax_base_ScaleTo_create(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.ScaleTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getHeight'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 3) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:create"); + if (!ok) { break; } + ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); + return 1; + } + } while (0); + ok = true; + do { - if(!ok) + if (argc == 2) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getHeight'", nullptr); - return 0; + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); + if (!ok) { break; } + ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); + return 1; } - auto&& ret = cobj->getHeight(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getHeight",argc, 0); + } while (0); + ok = true; + do + { + if (argc == 4) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:create"); + if (!ok) { break; } + double arg3; + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleTo:create"); + if (!ok) { break; } + ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.ScaleTo:create",argc, 4); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getHeight'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Image_getNumberOfMipmaps(lua_State* tolua_S) +int lua_ax_base_ScaleTo_constructor(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::ScaleTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20461,93 +20977,137 @@ int lua_ax_base_Image_getNumberOfMipmaps(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getNumberOfMipmaps'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getNumberOfMipmaps'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ScaleTo_constructor'", nullptr); return 0; } - auto&& ret = cobj->getNumberOfMipmaps(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj = new ax::ScaleTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ScaleTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getNumberOfMipmaps",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleTo:ScaleTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getNumberOfMipmaps'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_hasPremultipliedAlpha(lua_State* tolua_S) + +static int lua_ax_base_ScaleTo_finalize(lua_State* tolua_S) { - int argc = 0; - ax::Image* cobj = nullptr; - bool ok = true; + AXLOGV("luabindings: finalizing LUA object (ScaleTo)"); + return 0; +} -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif +int lua_register_ax_base_ScaleTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.ScaleTo"); + tolua_cclass(tolua_S,"ScaleTo","ax.ScaleTo","ax.ActionInterval",nullptr); + tolua_beginmodule(tolua_S,"ScaleTo"); + tolua_function(tolua_S,"new",lua_ax_base_ScaleTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_ScaleTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_ScaleTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::ScaleTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.ScaleTo"; + g_typeCast[typeName] = "ax.ScaleTo"; + return 1; +} +int lua_ax_base_ScaleBy_create(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + tolua_Error tolua_err; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - #if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_hasPremultipliedAlpha'", nullptr); - return 0; - } + if (!tolua_isusertable(tolua_S,1,"ax.ScaleBy",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + + do { - if(!ok) + if (argc == 3) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_hasPremultipliedAlpha'", nullptr); - return 0; - } - auto&& ret = cobj->hasPremultipliedAlpha(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:hasPremultipliedAlpha",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_hasPremultipliedAlpha'.",&tolua_err); + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleBy:create"); + if (!ok) { break; } + ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); + return 1; + } + } while (0); + ok = true; + do + { + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); + if (!ok) { break; } + ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); + return 1; + } + } while (0); + ok = true; + do + { + if (argc == 4) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg1; + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg2; + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleBy:create"); + if (!ok) { break; } + double arg3; + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleBy:create"); + if (!ok) { break; } + ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.ScaleBy:create",argc, 4); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleBy_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Image_getFilePath(lua_State* tolua_S) +int lua_ax_base_ScaleBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::ScaleBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20555,46 +21115,57 @@ int lua_ax_base_Image_getFilePath(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getFilePath'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getFilePath'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ScaleBy_constructor'", nullptr); return 0; } - auto&& ret = cobj->getFilePath(); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + cobj = new ax::ScaleBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ScaleBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getFilePath",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleBy:ScaleBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getFilePath'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleBy_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_getBitPerPixel(lua_State* tolua_S) + +static int lua_ax_base_ScaleBy_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (ScaleBy)"); + return 0; +} + +int lua_register_ax_base_ScaleBy(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.ScaleBy"); + tolua_cclass(tolua_S,"ScaleBy","ax.ScaleBy","ax.ScaleTo",nullptr); + + tolua_beginmodule(tolua_S,"ScaleBy"); + tolua_function(tolua_S,"new",lua_ax_base_ScaleBy_constructor); + tolua_function(tolua_S,"create", lua_ax_base_ScaleBy_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::ScaleBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.ScaleBy"; + g_typeCast[typeName] = "ax.ScaleBy"; + return 1; +} + +int lua_ax_base_Blink_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::Blink* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20603,92 +21174,148 @@ int lua_ax_base_Image_getBitPerPixel(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Blink",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Blink*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_getBitPerPixel'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Blink_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + double arg0; + int arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Blink:initWithDuration"); + + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Blink:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_getBitPerPixel'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->getBitPerPixel(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:getBitPerPixel",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Blink:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_getBitPerPixel'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_hasAlpha(lua_State* tolua_S) +int lua_ax_base_Blink_create(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Blink",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 2) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_hasAlpha'", nullptr); - return 0; + double arg0; + int arg1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Blink:create"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Blink:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_create'", nullptr); + return 0; + } + auto&& ret = ax::Blink::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.Blink",(ax::Blink*)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Blink:create",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_create'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_Blink_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::Blink* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_hasAlpha'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_constructor'", nullptr); return 0; } - auto&& ret = cobj->hasAlpha(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj = new ax::Blink(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Blink"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:hasAlpha",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Blink:Blink",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_hasAlpha'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_isCompressed(lua_State* tolua_S) + +static int lua_ax_base_Blink_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Blink)"); + return 0; +} + +int lua_register_ax_base_Blink(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Blink"); + tolua_cclass(tolua_S,"Blink","ax.Blink","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"Blink"); + tolua_function(tolua_S,"new",lua_ax_base_Blink_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_Blink_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_Blink_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Blink).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Blink"; + g_typeCast[typeName] = "ax.Blink"; + return 1; +} + +int lua_ax_base_FadeTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::FadeTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20697,112 +21324,148 @@ int lua_ax_base_Image_isCompressed(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.FadeTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::FadeTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_isCompressed'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeTo_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + double arg0; + uint16_t arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeTo:initWithDuration"); + + ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.FadeTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_isCompressed'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_initWithDuration'", nullptr); return 0; } - auto&& ret = cobj->isCompressed(); + auto&& ret = cobj->initWithDuration(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:isCompressed",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeTo:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_isCompressed'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_saveToFile(lua_State* tolua_S) +int lua_ax_base_FadeTo_create(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.FadeTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_saveToFile'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:saveToFile"); + double arg0; + uint16_t arg1; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeTo:create"); + ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.FadeTo:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_saveToFile'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_create'", nullptr); return 0; } - auto&& ret = cobj->saveToFile(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = ax::FadeTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.FadeTo",(ax::FadeTo*)ret); return 1; } - if (argc == 2) - { - std::string_view arg0; - bool arg1; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeTo:create",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_create'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_FadeTo_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::FadeTo* cobj = nullptr; + bool ok = true; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Image:saveToFile"); +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Image:saveToFile"); + + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_saveToFile'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_constructor'", nullptr); return 0; } - auto&& ret = cobj->saveToFile(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj = new ax::FadeTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:saveToFile",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeTo:FadeTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_saveToFile'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_premultiplyAlpha(lua_State* tolua_S) + +static int lua_ax_base_FadeTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (FadeTo)"); + return 0; +} + +int lua_register_ax_base_FadeTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.FadeTo"); + tolua_cclass(tolua_S,"FadeTo","ax.FadeTo","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"FadeTo"); + tolua_function(tolua_S,"new",lua_ax_base_FadeTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_FadeTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_FadeTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::FadeTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.FadeTo"; + g_typeCast[typeName] = "ax.FadeTo"; + return 1; +} + +int lua_ax_base_FadeIn_setReverseAction(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::FadeIn* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -20811,163 +21474,190 @@ int lua_ax_base_Image_premultiplyAlpha(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.FadeIn",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::FadeIn*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_premultiplyAlpha'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeIn_setReverseAction'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::FadeTo* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.FadeTo",&arg0, "ax.FadeIn:setReverseAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_premultiplyAlpha'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_setReverseAction'", nullptr); return 0; } - cobj->premultiplyAlpha(); + cobj->setReverseAction(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:premultiplyAlpha",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeIn:setReverseAction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_premultiplyAlpha'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_setReverseAction'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_reversePremultipliedAlpha(lua_State* tolua_S) +int lua_ax_base_FadeIn_create(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.FadeIn",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Image*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Image_reversePremultipliedAlpha'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeIn:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_reversePremultipliedAlpha'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_create'", nullptr); return 0; } - cobj->reversePremultipliedAlpha(); - lua_settop(tolua_S, 1); + auto&& ret = ax::FadeIn::create(arg0); + object_to_luaval(tolua_S, "ax.FadeIn",(ax::FadeIn*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:reversePremultipliedAlpha",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeIn:create",argc, 1); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_reversePremultipliedAlpha'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Image_setPNGPremultipliedAlphaEnabled(lua_State* tolua_S) +int lua_ax_base_FadeIn_constructor(lua_State* tolua_S) { int argc = 0; + ax::FadeIn* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; -#endif - argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - bool arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Image:setPNGPremultipliedAlphaEnabled"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_setPNGPremultipliedAlphaEnabled'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_constructor'", nullptr); return 0; } - ax::Image::setPNGPremultipliedAlphaEnabled(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::FadeIn(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeIn"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:setPNGPremultipliedAlphaEnabled",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeIn:FadeIn",argc, 0); return 0; + #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_setPNGPremultipliedAlphaEnabled'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_constructor'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Image_setCompressedImagesHavePMA(lua_State* tolua_S) + +static int lua_ax_base_FadeIn_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (FadeIn)"); + return 0; +} + +int lua_register_ax_base_FadeIn(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.FadeIn"); + tolua_cclass(tolua_S,"FadeIn","ax.FadeIn","ax.FadeTo",nullptr); + + tolua_beginmodule(tolua_S,"FadeIn"); + tolua_function(tolua_S,"new",lua_ax_base_FadeIn_constructor); + tolua_function(tolua_S,"setReverseAction",lua_ax_base_FadeIn_setReverseAction); + tolua_function(tolua_S,"create", lua_ax_base_FadeIn_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::FadeIn).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.FadeIn"; + g_typeCast[typeName] = "ax.FadeIn"; + return 1; +} + +int lua_ax_base_FadeOut_setReverseAction(lua_State* tolua_S) { int argc = 0; + ax::FadeOut* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.FadeOut",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::FadeOut*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) { - unsigned int arg0; - bool arg1; - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Image:setCompressedImagesHavePMA"); - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Image:setCompressedImagesHavePMA"); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeOut_setReverseAction'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::FadeTo* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.FadeTo",&arg0, "ax.FadeOut:setReverseAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_setCompressedImagesHavePMA'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_setReverseAction'", nullptr); return 0; } - ax::Image::setCompressedImagesHavePMA(arg0, arg1); + cobj->setReverseAction(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:setCompressedImagesHavePMA",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeOut:setReverseAction",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_setCompressedImagesHavePMA'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_setReverseAction'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Image_isCompressedImageHavePMA(lua_State* tolua_S) +int lua_ax_base_FadeOut_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -20977,36 +21667,36 @@ int lua_ax_base_Image_isCompressedImageHavePMA(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Image",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.FadeOut",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; if (argc == 1) { - unsigned int arg0; - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Image:isCompressedImageHavePMA"); + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeOut:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_isCompressedImageHavePMA'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_create'", nullptr); return 0; } - auto&& ret = ax::Image::isCompressedImageHavePMA(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = ax::FadeOut::create(arg0); + object_to_luaval(tolua_S, "ax.FadeOut",(ax::FadeOut*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Image:isCompressedImageHavePMA",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeOut:create",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_isCompressedImageHavePMA'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_create'.",&tolua_err); #endif return 0; } -int lua_ax_base_Image_constructor(lua_State* tolua_S) +int lua_ax_base_FadeOut_constructor(lua_State* tolua_S) { int argc = 0; - ax::Image* cobj = nullptr; + ax::FadeOut* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21016,72 +21706,56 @@ int lua_ax_base_Image_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Image_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_constructor'", nullptr); return 0; } - cobj = new ax::Image(); + cobj = new ax::FadeOut(); cobj->autorelease(); int ID = (int)cobj->_ID ; int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Image"); + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeOut"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Image:Image",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeOut:FadeOut",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Image_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_Image_finalize(lua_State* tolua_S) +static int lua_ax_base_FadeOut_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Image)"); + AXLOGV("luabindings: finalizing LUA object (FadeOut)"); return 0; } -int lua_register_ax_base_Image(lua_State* tolua_S) +int lua_register_ax_base_FadeOut(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Image"); - tolua_cclass(tolua_S,"Image","ax.Image","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.FadeOut"); + tolua_cclass(tolua_S,"FadeOut","ax.FadeOut","ax.FadeTo",nullptr); - tolua_beginmodule(tolua_S,"Image"); - tolua_function(tolua_S,"new",lua_ax_base_Image_constructor); - tolua_function(tolua_S,"initWithImageFile",lua_ax_base_Image_initWithImageFile); - tolua_function(tolua_S,"flipRawData",lua_ax_base_Image_flipRawData); - tolua_function(tolua_S,"getFileType",lua_ax_base_Image_getFileType); - tolua_function(tolua_S,"getPixelFormat",lua_ax_base_Image_getPixelFormat); - tolua_function(tolua_S,"getWidth",lua_ax_base_Image_getWidth); - tolua_function(tolua_S,"getHeight",lua_ax_base_Image_getHeight); - tolua_function(tolua_S,"getNumberOfMipmaps",lua_ax_base_Image_getNumberOfMipmaps); - tolua_function(tolua_S,"hasPremultipliedAlpha",lua_ax_base_Image_hasPremultipliedAlpha); - tolua_function(tolua_S,"getFilePath",lua_ax_base_Image_getFilePath); - tolua_function(tolua_S,"getBitPerPixel",lua_ax_base_Image_getBitPerPixel); - tolua_function(tolua_S,"hasAlpha",lua_ax_base_Image_hasAlpha); - tolua_function(tolua_S,"isCompressed",lua_ax_base_Image_isCompressed); - tolua_function(tolua_S,"saveToFile",lua_ax_base_Image_saveToFile); - tolua_function(tolua_S,"premultiplyAlpha",lua_ax_base_Image_premultiplyAlpha); - tolua_function(tolua_S,"reversePremultipliedAlpha",lua_ax_base_Image_reversePremultipliedAlpha); - tolua_function(tolua_S,"setPNGPremultipliedAlphaEnabled", lua_ax_base_Image_setPNGPremultipliedAlphaEnabled); - tolua_function(tolua_S,"setCompressedImagesHavePMA", lua_ax_base_Image_setCompressedImagesHavePMA); - tolua_function(tolua_S,"isCompressedImageHavePMA", lua_ax_base_Image_isCompressedImageHavePMA); + tolua_beginmodule(tolua_S,"FadeOut"); + tolua_function(tolua_S,"new",lua_ax_base_FadeOut_constructor); + tolua_function(tolua_S,"setReverseAction",lua_ax_base_FadeOut_setReverseAction); + tolua_function(tolua_S,"create", lua_ax_base_FadeOut_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Image).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Image"; - g_typeCast[typeName] = "ax.Image"; + auto typeName = typeid(ax::FadeOut).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.FadeOut"; + g_typeCast[typeName] = "ax.FadeOut"; return 1; } -int lua_ax_base_PolygonInfo_setQuad(lua_State* tolua_S) +int lua_ax_base_TintTo_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::TintTo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21090,103 +21764,170 @@ int lua_ax_base_PolygonInfo_setQuad(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.TintTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::TintTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setQuad'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TintTo_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - ax::V3F_C4B_T2F_Quad* arg0; + double arg0; + ax::Color32 arg1; - #pragma warning NO CONVERSION TO NATIVE FOR V3F_C4B_T2F_Quad* - ok = false; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:initWithDuration"); + + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.TintTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setQuad'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintTo_initWithDuration'", nullptr); return 0; } - cobj->setQuad(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithDuration(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setQuad",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintTo:initWithDuration",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setQuad'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_setQuads(lua_State* tolua_S) +int lua_ax_base_TintTo_create(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.TintTo",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S)-1; -#if _AX_DEBUG >= 1 - if (!cobj) + do { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setQuads'", nullptr); - return 0; - } + if (argc == 2) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:create"); + if (!ok) { break; } + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.TintTo:create"); + if (!ok) { break; } + ax::TintTo* ret = ax::TintTo::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.TintTo",(ax::TintTo*)ret); + return 1; + } + } while (0); + ok = true; + do + { + if (argc == 4) + { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:create"); + if (!ok) { break; } + uint16_t arg1; + ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.TintTo:create"); + if (!ok) { break; } + uint16_t arg2; + ok &= luaval_to_uint16(tolua_S, 4,&arg2, "ax.TintTo:create"); + if (!ok) { break; } + uint16_t arg3; + ok &= luaval_to_uint16(tolua_S, 5,&arg3, "ax.TintTo:create"); + if (!ok) { break; } + ax::TintTo* ret = ax::TintTo::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.TintTo",(ax::TintTo*)ret); + return 1; + } + } while (0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.TintTo:create",argc, 4); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_create'.",&tolua_err); #endif + return 0; +} +int lua_ax_base_TintTo_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::TintTo* cobj = nullptr; + bool ok = true; - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - ax::V3F_C4B_T2F_Quad* arg0; - int arg1; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - #pragma warning NO CONVERSION TO NATIVE FOR V3F_C4B_T2F_Quad* - ok = false; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PolygonInfo:setQuads"); + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setQuads'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintTo_constructor'", nullptr); return 0; } - cobj->setQuads(arg0, arg1); - lua_settop(tolua_S, 1); + cobj = new ax::TintTo(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TintTo"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setQuads",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintTo:TintTo",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setQuads'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_setTriangles(lua_State* tolua_S) + +static int lua_ax_base_TintTo_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (TintTo)"); + return 0; +} + +int lua_register_ax_base_TintTo(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.TintTo"); + tolua_cclass(tolua_S,"TintTo","ax.TintTo","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"TintTo"); + tolua_function(tolua_S,"new",lua_ax_base_TintTo_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_TintTo_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_TintTo_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::TintTo).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.TintTo"; + g_typeCast[typeName] = "ax.TintTo"; + return 1; +} + +int lua_ax_base_TintBy_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::TintBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21195,96 +21936,99 @@ int lua_ax_base_PolygonInfo_setTriangles(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.TintBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::TintBy*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setTriangles'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TintBy_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 4) { - ax::TrianglesCommand::Triangles arg0; + double arg0; + int32_t arg1; + int32_t arg2; + int32_t arg3; - #pragma warning NO CONVERSION TO NATIVE FOR Triangles - ok = false; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintBy:initWithDuration"); + + ok &= luaval_to_int32(tolua_S, 3,&arg1, "ax.TintBy:initWithDuration"); + + ok &= luaval_to_int32(tolua_S, 4,&arg2, "ax.TintBy:initWithDuration"); + + ok &= luaval_to_int32(tolua_S, 5,&arg3, "ax.TintBy:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setTriangles'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_initWithDuration'", nullptr); return 0; } - cobj->setTriangles(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setTriangles",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintBy:initWithDuration",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setTriangles'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_getVertCount(lua_State* tolua_S) +int lua_ax_base_TintBy_create(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.TintBy",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getVertCount'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 4) { + double arg0; + int32_t arg1; + int32_t arg2; + int32_t arg3; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintBy:create"); + ok &= luaval_to_int32(tolua_S, 3,&arg1, "ax.TintBy:create"); + ok &= luaval_to_int32(tolua_S, 4,&arg2, "ax.TintBy:create"); + ok &= luaval_to_int32(tolua_S, 5,&arg3, "ax.TintBy:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getVertCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_create'", nullptr); return 0; } - auto&& ret = cobj->getVertCount(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::TintBy::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.TintBy",(ax::TintBy*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getVertCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.TintBy:create",argc, 4); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getVertCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_PolygonInfo_getTrianglesCount(lua_State* tolua_S) +int lua_ax_base_TintBy_constructor(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::TintBy* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21292,93 +22036,152 @@ int lua_ax_base_PolygonInfo_getTrianglesCount(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getTrianglesCount'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getTrianglesCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_constructor'", nullptr); return 0; } - auto&& ret = cobj->getTrianglesCount(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj = new ax::TintBy(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TintBy"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getTrianglesCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintBy:TintBy",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getTrianglesCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_getArea(lua_State* tolua_S) + +static int lua_ax_base_TintBy_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (TintBy)"); + return 0; +} + +int lua_register_ax_base_TintBy(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.TintBy"); + tolua_cclass(tolua_S,"TintBy","ax.TintBy","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"TintBy"); + tolua_function(tolua_S,"new",lua_ax_base_TintBy_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_TintBy_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_TintBy_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::TintBy).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.TintBy"; + g_typeCast[typeName] = "ax.TintBy"; + return 1; +} + +int lua_ax_base_DelayTime_create(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.DelayTime",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 1) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getArea'", nullptr); - return 0; + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.DelayTime:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DelayTime_create'", nullptr); + return 0; + } + auto&& ret = ax::DelayTime::create(arg0); + object_to_luaval(tolua_S, "ax.DelayTime",(ax::DelayTime*)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.DelayTime:create",argc, 1); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_DelayTime_create'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_DelayTime_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::DelayTime* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getArea'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DelayTime_constructor'", nullptr); return 0; } - auto&& ret = cobj->getArea(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj = new ax::DelayTime(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.DelayTime"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getArea",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.DelayTime:DelayTime",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getArea'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_DelayTime_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_getRect(lua_State* tolua_S) + +static int lua_ax_base_DelayTime_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (DelayTime)"); + return 0; +} + +int lua_register_ax_base_DelayTime(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.DelayTime"); + tolua_cclass(tolua_S,"DelayTime","ax.DelayTime","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"DelayTime"); + tolua_function(tolua_S,"new",lua_ax_base_DelayTime_constructor); + tolua_function(tolua_S,"create", lua_ax_base_DelayTime_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::DelayTime).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.DelayTime"; + g_typeCast[typeName] = "ax.DelayTime"; + return 1; +} + +int lua_ax_base_Animate_setAnimation(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::Animate* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21387,95 +22190,95 @@ int lua_ax_base_PolygonInfo_getRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_setAnimation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Animation* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:setAnimation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_setAnimation'", nullptr); return 0; } - auto&& ret = cobj->getRect(); - rect_to_luaval(tolua_S, ret); + cobj->setAnimation(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:setAnimation",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_setAnimation'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_setRect(lua_State* tolua_S) +int lua_ax_base_Animate_getAnimation(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::Animate* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_getAnimation'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Rect arg0; - - ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.PolygonInfo:setRect"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setRect'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::Animation* ret = cobj->getAnimation(); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; } - cobj->setRect(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setRect",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::Animation* ret = cobj->getAnimation(); + object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:getAnimation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_getAnimation'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_getFilename(lua_State* tolua_S) +int lua_ax_base_Animate_getCurrentFrameIndex(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::Animate* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21484,45 +22287,45 @@ int lua_ax_base_PolygonInfo_getFilename(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_getFilename'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_getCurrentFrameIndex'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_getFilename'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_getCurrentFrameIndex'", nullptr); return 0; } - auto&& ret = cobj->getFilename(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); + auto&& ret = cobj->getCurrentFrameIndex(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:getFilename",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:getCurrentFrameIndex",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_getFilename'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_getCurrentFrameIndex'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_setFilename(lua_State* tolua_S) +int lua_ax_base_Animate_initWithAnimation(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; + ax::Animate* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21531,113 +22334,84 @@ int lua_ax_base_PolygonInfo_setFilename(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PolygonInfo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PolygonInfo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_PolygonInfo_setFilename'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_initWithAnimation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - std::string_view arg0; + ax::Animation* arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.PolygonInfo:setFilename"); + ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:initWithAnimation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_setFilename'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_initWithAnimation'", nullptr); return 0; } - cobj->setFilename(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithAnimation(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:setFilename",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:initWithAnimation",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_setFilename'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_initWithAnimation'.",&tolua_err); #endif return 0; } -int lua_ax_base_PolygonInfo_constructor(lua_State* tolua_S) +int lua_ax_base_Animate_create(lua_State* tolua_S) { int argc = 0; - ax::PolygonInfo* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; +#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Animation* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_PolygonInfo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_create'", nullptr); return 0; } - cobj = new ax::PolygonInfo(); - tolua_pushusertype(tolua_S,(void*)cobj,"ax.PolygonInfo"); - tolua_register_gc(tolua_S,lua_gettop(tolua_S)); + auto&& ret = ax::Animate::create(arg0); + object_to_luaval(tolua_S, "ax.Animate",(ax::Animate*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PolygonInfo:PolygonInfo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Animate:create",argc, 1); return 0; - #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_PolygonInfo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_create'.",&tolua_err); #endif - - return 0; -} - -static int lua_ax_base_PolygonInfo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (PolygonInfo)"); return 0; } - -int lua_register_ax_base_PolygonInfo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.PolygonInfo"); - tolua_cclass(tolua_S,"PolygonInfo","ax.PolygonInfo","",nullptr); - - tolua_beginmodule(tolua_S,"PolygonInfo"); - tolua_function(tolua_S,"new",lua_ax_base_PolygonInfo_constructor); - tolua_function(tolua_S,"setQuad",lua_ax_base_PolygonInfo_setQuad); - tolua_function(tolua_S,"setQuads",lua_ax_base_PolygonInfo_setQuads); - tolua_function(tolua_S,"setTriangles",lua_ax_base_PolygonInfo_setTriangles); - tolua_function(tolua_S,"getVertCount",lua_ax_base_PolygonInfo_getVertCount); - tolua_function(tolua_S,"getTrianglesCount",lua_ax_base_PolygonInfo_getTrianglesCount); - tolua_function(tolua_S,"getArea",lua_ax_base_PolygonInfo_getArea); - tolua_function(tolua_S,"getRect",lua_ax_base_PolygonInfo_getRect); - tolua_function(tolua_S,"setRect",lua_ax_base_PolygonInfo_setRect); - tolua_function(tolua_S,"getFilename",lua_ax_base_PolygonInfo_getFilename); - tolua_function(tolua_S,"setFilename",lua_ax_base_PolygonInfo_setFilename); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PolygonInfo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PolygonInfo"; - g_typeCast[typeName] = "ax.PolygonInfo"; - return 1; -} - -int lua_ax_base_AutoPolygon_constructor(lua_State* tolua_S) +int lua_ax_base_Animate_constructor(lua_State* tolua_S) { int argc = 0; - ax::AutoPolygon* cobj = nullptr; + ax::Animate* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21647,55 +22421,59 @@ int lua_ax_base_AutoPolygon_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.AutoPolygon:AutoPolygon"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AutoPolygon_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_constructor'", nullptr); return 0; } - cobj = new ax::AutoPolygon(arg0); - tolua_pushusertype(tolua_S,(void*)cobj,"ax.AutoPolygon"); - tolua_register_gc(tolua_S,lua_gettop(tolua_S)); + cobj = new ax::Animate(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Animate"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AutoPolygon:AutoPolygon",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:Animate",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AutoPolygon_constructor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_constructor'.",&tolua_err); #endif return 0; } -static int lua_ax_base_AutoPolygon_finalize(lua_State* tolua_S) +static int lua_ax_base_Animate_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (AutoPolygon)"); + AXLOGV("luabindings: finalizing LUA object (Animate)"); return 0; } -int lua_register_ax_base_AutoPolygon(lua_State* tolua_S) +int lua_register_ax_base_Animate(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.AutoPolygon"); - tolua_cclass(tolua_S,"AutoPolygon","ax.AutoPolygon","",nullptr); + tolua_usertype(tolua_S,"ax.Animate"); + tolua_cclass(tolua_S,"Animate","ax.Animate","ax.ActionInterval",nullptr); - tolua_beginmodule(tolua_S,"AutoPolygon"); - tolua_function(tolua_S,"new",lua_ax_base_AutoPolygon_constructor); + tolua_beginmodule(tolua_S,"Animate"); + tolua_function(tolua_S,"new",lua_ax_base_Animate_constructor); + tolua_function(tolua_S,"setAnimation",lua_ax_base_Animate_setAnimation); + tolua_function(tolua_S,"getAnimation",lua_ax_base_Animate_getAnimation); + tolua_function(tolua_S,"getCurrentFrameIndex",lua_ax_base_Animate_getCurrentFrameIndex); + tolua_function(tolua_S,"initWithAnimation",lua_ax_base_Animate_initWithAnimation); + tolua_function(tolua_S,"create", lua_ax_base_Animate_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::AutoPolygon).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.AutoPolygon"; - g_typeCast[typeName] = "ax.AutoPolygon"; + auto typeName = typeid(ax::Animate).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Animate"; + g_typeCast[typeName] = "ax.Animate"; return 1; } -int lua_ax_base_SpriteFrame_getRectInPixels(lua_State* tolua_S) +int lua_ax_base_TargetedAction_setForcedTarget(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::TargetedAction* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21704,95 +22482,95 @@ int lua_ax_base_SpriteFrame_getRectInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getRectInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_setForcedTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Node* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:setForcedTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getRectInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_setForcedTarget'", nullptr); return 0; } - auto&& ret = cobj->getRectInPixels(); - rect_to_luaval(tolua_S, ret); + cobj->setForcedTarget(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getRectInPixels",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:setForcedTarget",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getRectInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_setForcedTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setRectInPixels(lua_State* tolua_S) +int lua_ax_base_TargetedAction_getForcedTarget(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::TargetedAction* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; #endif - - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - + cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRectInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_getForcedTarget'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Rect arg0; - - ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setRectInPixels"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRectInPixels'", nullptr); - return 0; + do{ + if (argc == 0) { + const ax::Node* ret = cobj->getForcedTarget(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + return 1; } - cobj->setRectInPixels(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRectInPixels",argc, 1); + }while(0); + ok = true; + do{ + if (argc == 0) { + ax::Node* ret = cobj->getForcedTarget(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:getForcedTarget",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRectInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_getForcedTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_isRotated(lua_State* tolua_S) +int lua_ax_base_TargetedAction_initWithTarget(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::TargetedAction* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21801,95 +22579,89 @@ int lua_ax_base_SpriteFrame_isRotated(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_isRotated'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_initWithTarget'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::Node* arg0; + ax::FiniteTimeAction* arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:initWithTarget"); + + ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.TargetedAction:initWithTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_isRotated'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_initWithTarget'", nullptr); return 0; } - auto&& ret = cobj->isRotated(); + auto&& ret = cobj->initWithTarget(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:isRotated",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:initWithTarget",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_isRotated'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_initWithTarget'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setRotated(lua_State* tolua_S) +int lua_ax_base_TargetedAction_create(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRotated'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.SpriteFrame:setRotated"); + ax::Node* arg0; + ax::FiniteTimeAction* arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.TargetedAction:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRotated'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_create'", nullptr); return 0; } - cobj->setRotated(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::TargetedAction::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.TargetedAction",(ax::TargetedAction*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRotated",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.TargetedAction:create",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRotated'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_SpriteFrame_getRect(lua_State* tolua_S) +int lua_ax_base_TargetedAction_constructor(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::TargetedAction* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21897,46 +22669,60 @@ int lua_ax_base_SpriteFrame_getRect(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getRect'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_constructor'", nullptr); return 0; } - auto&& ret = cobj->getRect(); - rect_to_luaval(tolua_S, ret); + cobj = new ax::TargetedAction(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TargetedAction"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:TargetedAction",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setRect(lua_State* tolua_S) + +static int lua_ax_base_TargetedAction_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (TargetedAction)"); + return 0; +} + +int lua_register_ax_base_TargetedAction(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.TargetedAction"); + tolua_cclass(tolua_S,"TargetedAction","ax.TargetedAction","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"TargetedAction"); + tolua_function(tolua_S,"new",lua_ax_base_TargetedAction_constructor); + tolua_function(tolua_S,"setForcedTarget",lua_ax_base_TargetedAction_setForcedTarget); + tolua_function(tolua_S,"getForcedTarget",lua_ax_base_TargetedAction_getForcedTarget); + tolua_function(tolua_S,"initWithTarget",lua_ax_base_TargetedAction_initWithTarget); + tolua_function(tolua_S,"create", lua_ax_base_TargetedAction_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::TargetedAction).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.TargetedAction"; + g_typeCast[typeName] = "ax.TargetedAction"; + return 1; +} + +int lua_ax_base_ActionFloat_initWithDuration(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::ActionFloat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -21945,95 +22731,107 @@ int lua_ax_base_SpriteFrame_setRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.ActionFloat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::ActionFloat*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionFloat_initWithDuration'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 4) { - ax::Rect arg0; + double arg0; + double arg1; + double arg2; + std::function arg3; - ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setRect"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionFloat:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ActionFloat:initWithDuration"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ActionFloat:initWithDuration"); + + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_initWithDuration'", nullptr); return 0; } - cobj->setRect(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setRect",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionFloat:initWithDuration",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_initWithDuration'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getCenterRect(lua_State* tolua_S) +int lua_ax_base_ActionFloat_create(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.ActionFloat",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getCenterRect'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 4) { + double arg0; + double arg1; + double arg2; + std::function arg3; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionFloat:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ActionFloat:create"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ActionFloat:create"); + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getCenterRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_create'", nullptr); return 0; } - auto&& ret = cobj->getCenterRect(); - rect_to_luaval(tolua_S, ret); + auto&& ret = ax::ActionFloat::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.ActionFloat",(ax::ActionFloat*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getCenterRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.ActionFloat:create",argc, 4); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getCenterRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_SpriteFrame_setCenterRectInPixels(lua_State* tolua_S) +int lua_ax_base_ActionFloat_constructor(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::ActionFloat* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22041,49 +22839,58 @@ int lua_ax_base_SpriteFrame_setCenterRectInPixels(lua_State* tolua_S) #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'", nullptr); - return 0; - } -#endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Rect arg0; - - ok &= luaval_to_rect(tolua_S, 2, &arg0, "ax.SpriteFrame:setCenterRectInPixels"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_constructor'", nullptr); return 0; } - cobj->setCenterRectInPixels(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::ActionFloat(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ActionFloat"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setCenterRectInPixels",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionFloat:ActionFloat",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setCenterRectInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_hasCenterRect(lua_State* tolua_S) + +static int lua_ax_base_ActionFloat_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (ActionFloat)"); + return 0; +} + +int lua_register_ax_base_ActionFloat(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.ActionFloat"); + tolua_cclass(tolua_S,"ActionFloat","ax.ActionFloat","ax.ActionInterval",nullptr); + + tolua_beginmodule(tolua_S,"ActionFloat"); + tolua_function(tolua_S,"new",lua_ax_base_ActionFloat_constructor); + tolua_function(tolua_S,"initWithDuration",lua_ax_base_ActionFloat_initWithDuration); + tolua_function(tolua_S,"create", lua_ax_base_ActionFloat_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::ActionFloat).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.ActionFloat"; + g_typeCast[typeName] = "ax.ActionFloat"; + return 1; +} + +int lua_ax_base_Scene_getDefaultCamera(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22092,45 +22899,45 @@ int lua_ax_base_SpriteFrame_hasCenterRect(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_hasCenterRect'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_getDefaultCamera'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_hasCenterRect'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_getDefaultCamera'", nullptr); return 0; } - auto&& ret = cobj->hasCenterRect(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getDefaultCamera(); + object_to_luaval(tolua_S, "ax.Camera",(ax::Camera*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:hasCenterRect",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:getDefaultCamera",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_hasCenterRect'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_getDefaultCamera'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getOffsetInPixels(lua_State* tolua_S) +int lua_ax_base_Scene_render(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22139,45 +22946,71 @@ int lua_ax_base_SpriteFrame_getOffsetInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_render'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) + { + ax::Renderer* arg0; + ax::Mat4 arg1; + + ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Scene:render"); + + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Scene:render"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_render'", nullptr); + return 0; + } + cobj->render(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 3) { + ax::Renderer* arg0; + ax::Mat4 arg1; + const ax::Mat4* arg2; + + ok &= luaval_to_object(tolua_S, 2, "ax.Renderer",&arg0, "ax.Scene:render"); + + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Scene:render"); + + ok &= luaval_to_object(tolua_S, 4, "ax.Mat4",&arg2, "ax.Scene:render"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_render'", nullptr); return 0; } - auto&& ret = cobj->getOffsetInPixels(); - vec2_to_luaval(tolua_S, ret); + cobj->render(arg0, arg1, arg2); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOffsetInPixels",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:render",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOffsetInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_render'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setOffsetInPixels(lua_State* tolua_S) +int lua_ax_base_Scene_initWithSize(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22186,48 +23019,48 @@ int lua_ax_base_SpriteFrame_setOffsetInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initWithSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOffsetInPixels"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Scene:initWithSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initWithSize'", nullptr); return 0; } - cobj->setOffsetInPixels(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithSize(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOffsetInPixels",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initWithSize",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOffsetInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initWithSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getOriginalSizeInPixels(lua_State* tolua_S) +int lua_ax_base_Scene_setCameraOrderDirty(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22236,45 +23069,45 @@ int lua_ax_base_SpriteFrame_getOriginalSizeInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_setCameraOrderDirty'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_setCameraOrderDirty'", nullptr); return 0; } - auto&& ret = cobj->getOriginalSizeInPixels(); - vec2_to_luaval(tolua_S, ret); + cobj->setCameraOrderDirty(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOriginalSizeInPixels",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:setCameraOrderDirty",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOriginalSizeInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_setCameraOrderDirty'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setOriginalSizeInPixels(lua_State* tolua_S) +int lua_ax_base_Scene_onProjectionChanged(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22283,48 +23116,48 @@ int lua_ax_base_SpriteFrame_setOriginalSizeInPixels(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_onProjectionChanged'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vec2 arg0; + ax::EventCustom* arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOriginalSizeInPixels"); + ok &= luaval_to_object(tolua_S, 2, "ax.EventCustom",&arg0, "ax.Scene:onProjectionChanged"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_onProjectionChanged'", nullptr); return 0; } - cobj->setOriginalSizeInPixels(arg0); + cobj->onProjectionChanged(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOriginalSizeInPixels",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:onProjectionChanged",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOriginalSizeInPixels'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_onProjectionChanged'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getOriginalSize(lua_State* tolua_S) +int lua_ax_base_Scene_getPhysicsWorld(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22333,45 +23166,45 @@ int lua_ax_base_SpriteFrame_getOriginalSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOriginalSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_getPhysicsWorld'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOriginalSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_getPhysicsWorld'", nullptr); return 0; } - auto&& ret = cobj->getOriginalSize(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = cobj->getPhysicsWorld(); + object_to_luaval(tolua_S, "ax.PhysicsWorld",(ax::PhysicsWorld*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOriginalSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:getPhysicsWorld",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOriginalSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_getPhysicsWorld'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setOriginalSize(lua_State* tolua_S) +int lua_ax_base_Scene_initWithPhysics(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22380,48 +23213,45 @@ int lua_ax_base_SpriteFrame_setOriginalSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOriginalSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initWithPhysics'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOriginalSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOriginalSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initWithPhysics'", nullptr); return 0; } - cobj->setOriginalSize(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->initWithPhysics(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOriginalSize",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initWithPhysics",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOriginalSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initWithPhysics'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getTexture(lua_State* tolua_S) +int lua_ax_base_Scene_initPhysicsWorld(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22430,45 +23260,45 @@ int lua_ax_base_SpriteFrame_getTexture(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_initPhysicsWorld'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getTexture'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_initPhysicsWorld'", nullptr); return 0; } - auto&& ret = cobj->getTexture(); - object_to_luaval(tolua_S, "ax.Texture2D",(ax::Texture2D*)ret); + auto&& ret = cobj->initPhysicsWorld(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getTexture",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:initPhysicsWorld",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_initPhysicsWorld'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setTexture(lua_State* tolua_S) +int lua_ax_base_Scene_fixedUpdate(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22477,48 +23307,48 @@ int lua_ax_base_SpriteFrame_setTexture(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_fixedUpdate'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Texture2D* arg0; + double arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:setTexture"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scene:fixedUpdate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setTexture'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_fixedUpdate'", nullptr); return 0; } - cobj->setTexture(arg0); + cobj->fixedUpdate(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setTexture",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:fixedUpdate",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_fixedUpdate'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getOffset(lua_State* tolua_S) +int lua_ax_base_Scene_stepPhysicsAndNavigation(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::Scene* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22527,192 +23357,222 @@ int lua_ax_base_SpriteFrame_getOffset(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Scene*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getOffset'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scene:stepPhysicsAndNavigation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getOffset'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'", nullptr); return 0; } - auto&& ret = cobj->getOffset(); - vec2_to_luaval(tolua_S, ret); + cobj->stepPhysicsAndNavigation(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getOffset",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:stepPhysicsAndNavigation",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getOffset'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_stepPhysicsAndNavigation'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_setOffset(lua_State* tolua_S) +int lua_ax_base_Scene_create(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setOffset'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setOffset'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_create'", nullptr); return 0; } - cobj->setOffset(arg0); - lua_settop(tolua_S, 1); + auto&& ret = ax::Scene::create(); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setOffset",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:create",argc, 0); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setOffset'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_create'.",&tolua_err); #endif - return 0; } -int lua_ax_base_SpriteFrame_getAnchorPoint(lua_State* tolua_S) +int lua_ax_base_Scene_createWithSize(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getAnchorPoint'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Scene:createWithSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_createWithSize'", nullptr); return 0; } - auto&& ret = cobj->getAnchorPoint(); - vec2_to_luaval(tolua_S, ret); + auto&& ret = ax::Scene::createWithSize(arg0); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getAnchorPoint",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:createWithSize",argc, 1); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getAnchorPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_createWithSize'.",&tolua_err); #endif - return 0; } -int lua_ax_base_SpriteFrame_setAnchorPoint(lua_State* tolua_S) +int lua_ax_base_Scene_createWithPhysics(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Scene",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 0) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_setAnchorPoint'", nullptr); - return 0; + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_createWithPhysics'", nullptr); + return 0; + } + auto&& ret = ax::Scene::createWithPhysics(); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Scene:createWithPhysics",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_createWithPhysics'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_Scene_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::Scene* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif + + argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.SpriteFrame:setAnchorPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_setAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scene_constructor'", nullptr); return 0; } - cobj->setAnchorPoint(arg0); - lua_settop(tolua_S, 1); + cobj = new ax::Scene(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Scene"); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:setAnchorPoint",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scene:Scene",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_setAnchorPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scene_constructor'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_hasAnchorPoint(lua_State* tolua_S) + +static int lua_ax_base_Scene_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Scene)"); + return 0; +} + +int lua_register_ax_base_Scene(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Scene"); + tolua_cclass(tolua_S,"Scene","ax.Scene","ax.Node",nullptr); + + tolua_beginmodule(tolua_S,"Scene"); + tolua_function(tolua_S,"new",lua_ax_base_Scene_constructor); + tolua_function(tolua_S,"getDefaultCamera",lua_ax_base_Scene_getDefaultCamera); + tolua_function(tolua_S,"render",lua_ax_base_Scene_render); + tolua_function(tolua_S,"initWithSize",lua_ax_base_Scene_initWithSize); + tolua_function(tolua_S,"setCameraOrderDirty",lua_ax_base_Scene_setCameraOrderDirty); + tolua_function(tolua_S,"onProjectionChanged",lua_ax_base_Scene_onProjectionChanged); + tolua_function(tolua_S,"getPhysicsWorld",lua_ax_base_Scene_getPhysicsWorld); + tolua_function(tolua_S,"initWithPhysics",lua_ax_base_Scene_initWithPhysics); + tolua_function(tolua_S,"initPhysicsWorld",lua_ax_base_Scene_initPhysicsWorld); + tolua_function(tolua_S,"fixedUpdate",lua_ax_base_Scene_fixedUpdate); + tolua_function(tolua_S,"stepPhysicsAndNavigation",lua_ax_base_Scene_stepPhysicsAndNavigation); + tolua_function(tolua_S,"create", lua_ax_base_Scene_create); + tolua_function(tolua_S,"createWithSize", lua_ax_base_Scene_createWithSize); + tolua_function(tolua_S,"createWithPhysics", lua_ax_base_Scene_createWithPhysics); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Scene).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Scene"; + g_typeCast[typeName] = "ax.Scene"; + return 1; +} + +int lua_ax_base_RenderView_end(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22721,45 +23581,45 @@ int lua_ax_base_SpriteFrame_hasAnchorPoint(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_end'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_end'", nullptr); return 0; } - auto&& ret = cobj->hasAnchorPoint(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->end(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:hasAnchorPoint",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:end",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_hasAnchorPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_end'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_clone(lua_State* tolua_S) +int lua_ax_base_RenderView_isGfxContextReady(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22768,195 +23628,142 @@ int lua_ax_base_SpriteFrame_clone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_clone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isGfxContextReady'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_clone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isGfxContextReady'", nullptr); return 0; } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + auto&& ret = cobj->isGfxContextReady(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:clone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isGfxContextReady",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_clone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isGfxContextReady'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_initWithTexture(lua_State* tolua_S) +int lua_ax_base_RenderView_swapBuffers(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_initWithTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_swapBuffers'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 5) { - ax::Texture2D* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - bool arg2; - ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - ax::Vec2 arg4; - ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - bool ret = cobj->initWithTexture(arg0, arg1, arg2, arg3, arg4); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - ax::Texture2D* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:initWithTexture"); - - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTexture"); - if (!ok) { break; } - bool ret = cobj->initWithTexture(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_swapBuffers'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:initWithTexture",argc, 2); + cobj->swapBuffers(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:swapBuffers",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_initWithTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_swapBuffers'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_initWithTextureFilename(lua_State* tolua_S) +int lua_ax_base_RenderView_setIMEKeyboardState(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_initWithTextureFilename'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setIMEKeyboardState'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 5) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:initWithTextureFilename"); - - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTextureFilename"); - - if (!ok) { break; } - bool arg2; - ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:initWithTextureFilename"); - - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:initWithTextureFilename"); - - if (!ok) { break; } - ax::Vec2 arg4; - ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:initWithTextureFilename"); - - if (!ok) { break; } - bool ret = cobj->initWithTextureFilename(arg0, arg1, arg2, arg3, arg4); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:initWithTextureFilename"); - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:initWithTextureFilename"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + bool arg0; - if (!ok) { break; } - bool ret = cobj->initWithTextureFilename(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setIMEKeyboardState"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setIMEKeyboardState'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:initWithTextureFilename",argc, 2); + cobj->setIMEKeyboardState(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setIMEKeyboardState",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_initWithTextureFilename'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setIMEKeyboardState'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_getName(lua_State* tolua_S) +int lua_ax_base_RenderView_windowShouldClose(lua_State* tolua_S) { int argc = 0; - ax::SpriteFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -22965,256 +23772,139 @@ int lua_ax_base_SpriteFrame_getName(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SpriteFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SpriteFrame_getName'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_windowShouldClose'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_getName'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_windowShouldClose'", nullptr); return 0; } - auto&& ret = cobj->getName(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); + auto&& ret = cobj->windowShouldClose(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:getName",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:windowShouldClose",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_getName'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_windowShouldClose'.",&tolua_err); #endif return 0; } -int lua_ax_base_SpriteFrame_create(lua_State* tolua_S) +int lua_ax_base_RenderView_pollEvents(lua_State* tolua_S) { int argc = 0; + ax::RenderView* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - do +#if _AX_DEBUG >= 1 + if (!cobj) { - if (argc == 5) - { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:create"); - if (!ok) { break; } - bool arg2; - ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::Vec2 arg4; - ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::SpriteFrame* ret = ax::SpriteFrame::create(arg0, arg1, arg2, arg3, arg4); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); - return 1; - } - } while (0); - ok = true; - do + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_pollEvents'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - if (argc == 2) + if(!ok) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:create"); - if (!ok) { break; } - ax::SpriteFrame* ret = ax::SpriteFrame::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_pollEvents'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.SpriteFrame:create",argc, 2); + cobj->pollEvents(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:pollEvents",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_pollEvents'.",&tolua_err); #endif + return 0; } -int lua_ax_base_SpriteFrame_createWithTexture(lua_State* tolua_S) +int lua_ax_base_RenderView_getFrameSize(lua_State* tolua_S) { int argc = 0; + ax::RenderView* cobj = nullptr; bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.SpriteFrame",0,&tolua_err)) goto tolua_lerror; + tolua_Error tolua_err; #endif - argc = lua_gettop(tolua_S)-1; - do - { - if (argc == 5) - { - ax::Texture2D* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - bool arg2; - ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::Vec2 arg4; - ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::SpriteFrame* ret = ax::SpriteFrame::createWithTexture(arg0, arg1, arg2, arg3, arg4); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 2) - { - ax::Texture2D* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::Rect arg1; - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.SpriteFrame:createWithTexture"); - if (!ok) { break; } - ax::SpriteFrame* ret = ax::SpriteFrame::createWithTexture(arg0, arg1); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); - return 1; - } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.SpriteFrame:createWithTexture",argc, 2); - return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_createWithTexture'.",&tolua_err); + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - return 0; -} -int lua_ax_base_SpriteFrame_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::SpriteFrame* cobj = nullptr; - bool ok = true; + + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 - tolua_Error tolua_err; + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getFrameSize'", nullptr); + return 0; + } #endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SpriteFrame_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getFrameSize'", nullptr); return 0; } - cobj = new ax::SpriteFrame(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SpriteFrame"); + auto&& ret = cobj->getFrameSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SpriteFrame:SpriteFrame",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getFrameSize",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SpriteFrame_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getFrameSize'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_SpriteFrame_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (SpriteFrame)"); - return 0; -} - -int lua_register_ax_base_SpriteFrame(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.SpriteFrame"); - tolua_cclass(tolua_S,"SpriteFrame","ax.SpriteFrame","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"SpriteFrame"); - tolua_function(tolua_S,"new",lua_ax_base_SpriteFrame_constructor); - tolua_function(tolua_S,"getRectInPixels",lua_ax_base_SpriteFrame_getRectInPixels); - tolua_function(tolua_S,"setRectInPixels",lua_ax_base_SpriteFrame_setRectInPixels); - tolua_function(tolua_S,"isRotated",lua_ax_base_SpriteFrame_isRotated); - tolua_function(tolua_S,"setRotated",lua_ax_base_SpriteFrame_setRotated); - tolua_function(tolua_S,"getRect",lua_ax_base_SpriteFrame_getRect); - tolua_function(tolua_S,"setRect",lua_ax_base_SpriteFrame_setRect); - tolua_function(tolua_S,"getCenterRect",lua_ax_base_SpriteFrame_getCenterRect); - tolua_function(tolua_S,"setCenterRectInPixels",lua_ax_base_SpriteFrame_setCenterRectInPixels); - tolua_function(tolua_S,"hasCenterRect",lua_ax_base_SpriteFrame_hasCenterRect); - tolua_function(tolua_S,"getOffsetInPixels",lua_ax_base_SpriteFrame_getOffsetInPixels); - tolua_function(tolua_S,"setOffsetInPixels",lua_ax_base_SpriteFrame_setOffsetInPixels); - tolua_function(tolua_S,"getOriginalSizeInPixels",lua_ax_base_SpriteFrame_getOriginalSizeInPixels); - tolua_function(tolua_S,"setOriginalSizeInPixels",lua_ax_base_SpriteFrame_setOriginalSizeInPixels); - tolua_function(tolua_S,"getOriginalSize",lua_ax_base_SpriteFrame_getOriginalSize); - tolua_function(tolua_S,"setOriginalSize",lua_ax_base_SpriteFrame_setOriginalSize); - tolua_function(tolua_S,"getTexture",lua_ax_base_SpriteFrame_getTexture); - tolua_function(tolua_S,"setTexture",lua_ax_base_SpriteFrame_setTexture); - tolua_function(tolua_S,"getOffset",lua_ax_base_SpriteFrame_getOffset); - tolua_function(tolua_S,"setOffset",lua_ax_base_SpriteFrame_setOffset); - tolua_function(tolua_S,"getAnchorPoint",lua_ax_base_SpriteFrame_getAnchorPoint); - tolua_function(tolua_S,"setAnchorPoint",lua_ax_base_SpriteFrame_setAnchorPoint); - tolua_function(tolua_S,"hasAnchorPoint",lua_ax_base_SpriteFrame_hasAnchorPoint); - tolua_function(tolua_S,"clone",lua_ax_base_SpriteFrame_clone); - tolua_function(tolua_S,"initWithTexture",lua_ax_base_SpriteFrame_initWithTexture); - tolua_function(tolua_S,"initWithTextureFilename",lua_ax_base_SpriteFrame_initWithTextureFilename); - tolua_function(tolua_S,"getName",lua_ax_base_SpriteFrame_getName); - tolua_function(tolua_S,"create", lua_ax_base_SpriteFrame_create); - tolua_function(tolua_S,"createWithTexture", lua_ax_base_SpriteFrame_createWithTexture); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::SpriteFrame).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.SpriteFrame"; - g_typeCast[typeName] = "ax.SpriteFrame"; - return 1; -} - -int lua_ax_base_AnimationFrame_getSpriteFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_setFrameSize(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23223,45 +23913,51 @@ int lua_ax_base_AnimationFrame_getSpriteFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setFrameSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + double arg0; + double arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setFrameSize"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setFrameSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_getSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setFrameSize'", nullptr); return 0; } - auto&& ret = cobj->getSpriteFrame(); - object_to_luaval(tolua_S, "ax.SpriteFrame",(ax::SpriteFrame*)ret); + cobj->setFrameSize(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getSpriteFrame",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setFrameSize",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getSpriteFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setFrameSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_setSpriteFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_setFrameZoomFactor(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23270,48 +23966,48 @@ int lua_ax_base_AnimationFrame_setSpriteFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setFrameZoomFactor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::SpriteFrame* arg0; + double arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:setSpriteFrame"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setFrameZoomFactor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setFrameZoomFactor'", nullptr); return 0; } - cobj->setSpriteFrame(arg0); + cobj->setFrameZoomFactor(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setSpriteFrame",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setFrameZoomFactor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setSpriteFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setFrameZoomFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_getDelayUnits(lua_State* tolua_S) +int lua_ax_base_RenderView_getFrameZoomFactor(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23320,45 +24016,45 @@ int lua_ax_base_AnimationFrame_getDelayUnits(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getFrameZoomFactor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_getDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getFrameZoomFactor'", nullptr); return 0; } - auto&& ret = cobj->getDelayUnits(); + auto&& ret = cobj->getFrameZoomFactor(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getDelayUnits",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getFrameZoomFactor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getDelayUnits'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getFrameZoomFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_setDelayUnits(lua_State* tolua_S) +int lua_ax_base_RenderView_setCursorVisible(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23367,95 +24063,95 @@ int lua_ax_base_AnimationFrame_setDelayUnits(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setCursorVisible'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - double arg0; + bool arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.AnimationFrame:setDelayUnits"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setCursorVisible"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setCursorVisible'", nullptr); return 0; } - cobj->setDelayUnits(arg0); + cobj->setCursorVisible(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setDelayUnits",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setCursorVisible",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setDelayUnits'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setCursorVisible'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_getUserInfo(lua_State* tolua_S) +int lua_ax_base_RenderView_getRetinaFactor(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_getUserInfo'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getRetinaFactor'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - ax::ValueMap& ret = cobj->getUserInfo(); - ccvaluemap_to_luaval(tolua_S, ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - const ax::ValueMap& ret = cobj->getUserInfo(); - ccvaluemap_to_luaval(tolua_S, ret); - return 1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getRetinaFactor'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:getUserInfo",argc, 0); + auto&& ret = cobj->getRetinaFactor(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getRetinaFactor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_getUserInfo'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getRetinaFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_setUserInfo(lua_State* tolua_S) +int lua_ax_base_RenderView_setContentScaleFactor(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23464,48 +24160,48 @@ int lua_ax_base_AnimationFrame_setUserInfo(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_setUserInfo'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setContentScaleFactor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::ValueMap arg0; + double arg0; - ok &= luaval_to_ccvaluemap(tolua_S, 2, &arg0, "ax.AnimationFrame:setUserInfo"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setContentScaleFactor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_setUserInfo'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setContentScaleFactor'", nullptr); return 0; } - cobj->setUserInfo(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->setContentScaleFactor(arg0); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:setUserInfo",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setContentScaleFactor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_setUserInfo'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setContentScaleFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_clone(lua_State* tolua_S) +int lua_ax_base_RenderView_getContentScaleFactor(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23514,45 +24210,45 @@ int lua_ax_base_AnimationFrame_clone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_clone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getContentScaleFactor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_clone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getContentScaleFactor'", nullptr); return 0; } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "ax.AnimationFrame",(ax::AnimationFrame*)ret); + auto&& ret = cobj->getContentScaleFactor(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:clone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getContentScaleFactor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_clone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getContentScaleFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_initWithSpriteFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_isRetinaDisplay(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23561,94 +24257,92 @@ int lua_ax_base_AnimationFrame_initWithSpriteFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::AnimationFrame*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isRetinaDisplay'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 0) { - ax::SpriteFrame* arg0; - double arg1; - ax::ValueMap arg2; - - ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:initWithSpriteFrame"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.AnimationFrame:initWithSpriteFrame"); - - ok &= luaval_to_ccvaluemap(tolua_S, 4, &arg2, "ax.AnimationFrame:initWithSpriteFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isRetinaDisplay'", nullptr); return 0; } - auto&& ret = cobj->initWithSpriteFrame(arg0, arg1, arg2); + auto&& ret = cobj->isRetinaDisplay(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:initWithSpriteFrame",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isRetinaDisplay",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_initWithSpriteFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isRetinaDisplay'.",&tolua_err); #endif return 0; } -int lua_ax_base_AnimationFrame_create(lua_State* tolua_S) +int lua_ax_base_RenderView_getVisibleSize(lua_State* tolua_S) { int argc = 0; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.AnimationFrame",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); - if (argc == 3) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleSize'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - ax::SpriteFrame* arg0; - double arg1; - ax::ValueMap arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.AnimationFrame:create"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.AnimationFrame:create"); - ok &= luaval_to_ccvaluemap(tolua_S, 4, &arg2, "ax.AnimationFrame:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleSize'", nullptr); return 0; } - auto&& ret = ax::AnimationFrame::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.AnimationFrame",(ax::AnimationFrame*)ret); + auto&& ret = cobj->getVisibleSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.AnimationFrame:create",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleSize",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleSize'.",&tolua_err); #endif + return 0; } -int lua_ax_base_AnimationFrame_constructor(lua_State* tolua_S) +int lua_ax_base_RenderView_getVisibleOrigin(lua_State* tolua_S) { int argc = 0; - ax::AnimationFrame* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23656,65 +24350,46 @@ int lua_ax_base_AnimationFrame_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleOrigin'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AnimationFrame_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleOrigin'", nullptr); return 0; } - cobj = new ax::AnimationFrame(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.AnimationFrame"); + auto&& ret = cobj->getVisibleOrigin(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.AnimationFrame:AnimationFrame",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleOrigin",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_AnimationFrame_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleOrigin'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_AnimationFrame_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (AnimationFrame)"); - return 0; -} - -int lua_register_ax_base_AnimationFrame(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.AnimationFrame"); - tolua_cclass(tolua_S,"AnimationFrame","ax.AnimationFrame","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"AnimationFrame"); - tolua_function(tolua_S,"new",lua_ax_base_AnimationFrame_constructor); - tolua_function(tolua_S,"getSpriteFrame",lua_ax_base_AnimationFrame_getSpriteFrame); - tolua_function(tolua_S,"setSpriteFrame",lua_ax_base_AnimationFrame_setSpriteFrame); - tolua_function(tolua_S,"getDelayUnits",lua_ax_base_AnimationFrame_getDelayUnits); - tolua_function(tolua_S,"setDelayUnits",lua_ax_base_AnimationFrame_setDelayUnits); - tolua_function(tolua_S,"getUserInfo",lua_ax_base_AnimationFrame_getUserInfo); - tolua_function(tolua_S,"setUserInfo",lua_ax_base_AnimationFrame_setUserInfo); - tolua_function(tolua_S,"clone",lua_ax_base_AnimationFrame_clone); - tolua_function(tolua_S,"initWithSpriteFrame",lua_ax_base_AnimationFrame_initWithSpriteFrame); - tolua_function(tolua_S,"create", lua_ax_base_AnimationFrame_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::AnimationFrame).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.AnimationFrame"; - g_typeCast[typeName] = "ax.AnimationFrame"; - return 1; -} - -int lua_ax_base_Animation_addSpriteFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_getVisibleRect(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23723,48 +24398,45 @@ int lua_ax_base_Animation_addSpriteFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getVisibleRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::SpriteFrame* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.SpriteFrame",&arg0, "ax.Animation:addSpriteFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getVisibleRect'", nullptr); return 0; } - cobj->addSpriteFrame(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getVisibleRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrame",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getVisibleRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getVisibleRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_addSpriteFrameWithFile(lua_State* tolua_S) +int lua_ax_base_RenderView_getSafeAreaRect(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23773,48 +24445,45 @@ int lua_ax_base_Animation_addSpriteFrameWithFile(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrameWithFile'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getSafeAreaRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Animation:addSpriteFrameWithFile"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrameWithFile'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getSafeAreaRect'", nullptr); return 0; } - cobj->addSpriteFrameWithFile(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getSafeAreaRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrameWithFile",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getSafeAreaRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrameWithFile'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getSafeAreaRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_addSpriteFrameWithTexture(lua_State* tolua_S) +int lua_ax_base_RenderView_setDesignResolutionSize(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23823,51 +24492,54 @@ int lua_ax_base_Animation_addSpriteFrameWithTexture(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setDesignResolutionSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 3) { - ax::Texture2D* arg0; - ax::Rect arg1; + double arg0; + double arg1; + ResolutionPolicy arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.Texture2D",&arg0, "ax.Animation:addSpriteFrameWithTexture"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setDesignResolutionSize"); - ok &= luaval_to_rect(tolua_S, 3, &arg1, "ax.Animation:addSpriteFrameWithTexture"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setDesignResolutionSize"); + + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderView:setDesignResolutionSize"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setDesignResolutionSize'", nullptr); return 0; } - cobj->addSpriteFrameWithTexture(arg0, arg1); + cobj->setDesignResolutionSize(arg0, arg1, arg2); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:addSpriteFrameWithTexture",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setDesignResolutionSize",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_addSpriteFrameWithTexture'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setDesignResolutionSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getTotalDelayUnits(lua_State* tolua_S) +int lua_ax_base_RenderView_getDesignResolutionSize(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23876,45 +24548,45 @@ int lua_ax_base_Animation_getTotalDelayUnits(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getTotalDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getDesignResolutionSize'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getTotalDelayUnits'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getDesignResolutionSize'", nullptr); return 0; } - auto&& ret = cobj->getTotalDelayUnits(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getDesignResolutionSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getTotalDelayUnits",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getDesignResolutionSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getTotalDelayUnits'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getDesignResolutionSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_setDelayPerUnit(lua_State* tolua_S) +int lua_ax_base_RenderView_setViewPortInPoints(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23923,48 +24595,57 @@ int lua_ax_base_Animation_setDelayPerUnit(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setDelayPerUnit'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setViewPortInPoints'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 4) { double arg0; + double arg1; + double arg2; + double arg3; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Animation:setDelayPerUnit"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setViewPortInPoints"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setViewPortInPoints"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RenderView:setViewPortInPoints"); + + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.RenderView:setViewPortInPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setDelayPerUnit'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setViewPortInPoints'", nullptr); return 0; } - cobj->setDelayPerUnit(arg0); + cobj->setViewPortInPoints(arg0, arg1, arg2, arg3); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setDelayPerUnit",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setViewPortInPoints",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setDelayPerUnit'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setViewPortInPoints'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getDelayPerUnit(lua_State* tolua_S) +int lua_ax_base_RenderView_setScissorInPoints(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -23973,45 +24654,57 @@ int lua_ax_base_Animation_getDelayPerUnit(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getDelayPerUnit'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setScissorInPoints'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 4) { + double arg0; + double arg1; + double arg2; + double arg3; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RenderView:setScissorInPoints"); + + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RenderView:setScissorInPoints"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RenderView:setScissorInPoints"); + + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.RenderView:setScissorInPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getDelayPerUnit'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setScissorInPoints'", nullptr); return 0; } - auto&& ret = cobj->getDelayPerUnit(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setScissorInPoints(arg0, arg1, arg2, arg3); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getDelayPerUnit",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setScissorInPoints",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getDelayPerUnit'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setScissorInPoints'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getDuration(lua_State* tolua_S) +int lua_ax_base_RenderView_isScissorEnabled(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24020,45 +24713,45 @@ int lua_ax_base_Animation_getDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_isScissorEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_isScissorEnabled'", nullptr); return 0; } - auto&& ret = cobj->getDuration(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->isScissorEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getDuration",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:isScissorEnabled",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_isScissorEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getFrames(lua_State* tolua_S) +int lua_ax_base_RenderView_getScissorRect(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24067,45 +24760,45 @@ int lua_ax_base_Animation_getFrames(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getFrames'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScissorRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScissorRect'", nullptr); return 0; } - auto&& ret = cobj->getFrames(); - ccvector_to_luaval(tolua_S, ret); + auto&& ret = cobj->getScissorRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getFrames",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScissorRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScissorRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_setFrames(lua_State* tolua_S) +int lua_ax_base_RenderView_setViewName(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24114,48 +24807,48 @@ int lua_ax_base_Animation_setFrames(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setFrames'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setViewName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vector arg0; + std::string_view arg0; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:setFrames"); + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.RenderView:setViewName"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setViewName'", nullptr); return 0; } - cobj->setFrames(arg0); + cobj->setViewName(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setFrames",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setViewName",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setViewName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getRestoreOriginalFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_getViewName(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24164,45 +24857,100 @@ int lua_ax_base_Animation_getRestoreOriginalFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getRestoreOriginalFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getViewName'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getRestoreOriginalFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getViewName'", nullptr); return 0; } - auto&& ret = cobj->getRestoreOriginalFrame(); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getViewName(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getRestoreOriginalFrame",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getViewName",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getRestoreOriginalFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getViewName'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_setRestoreOriginalFrame(lua_State* tolua_S) +int lua_ax_base_RenderView_setIcon(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setIcon'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + std::vector arg0; + ok &= luaval_to_std_vector_string_view(tolua_S, 2, &arg0, "ax.RenderView:setIcon"); + + if (!ok) { break; } + cobj->setIcon(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.RenderView:setIcon"); + + if (!ok) { break; } + cobj->setIcon(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setIcon",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setIcon'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_RenderView_setDefaultIcon(lua_State* tolua_S) +{ + int argc = 0; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24211,48 +24959,45 @@ int lua_ax_base_Animation_setRestoreOriginalFrame(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setRestoreOriginalFrame'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setDefaultIcon'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Animation:setRestoreOriginalFrame"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setRestoreOriginalFrame'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setDefaultIcon'", nullptr); return 0; } - cobj->setRestoreOriginalFrame(arg0); + cobj->setDefaultIcon(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setRestoreOriginalFrame",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setDefaultIcon",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setRestoreOriginalFrame'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setDefaultIcon'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_getLoops(lua_State* tolua_S) +int lua_ax_base_RenderView_getViewPortRect(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24261,45 +25006,45 @@ int lua_ax_base_Animation_getLoops(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_getLoops'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getViewPortRect'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_getLoops'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getViewPortRect'", nullptr); return 0; } - auto&& ret = cobj->getLoops(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getViewPortRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:getLoops",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getViewPortRect",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_getLoops'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getViewPortRect'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_setLoops(lua_State* tolua_S) +int lua_ax_base_RenderView_getScaleX(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24308,48 +25053,45 @@ int lua_ax_base_Animation_setLoops(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_setLoops'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScaleX'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - unsigned int arg0; - - ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Animation:setLoops"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_setLoops'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScaleX'", nullptr); return 0; } - cobj->setLoops(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getScaleX(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:setLoops",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScaleX",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_setLoops'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScaleX'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_clone(lua_State* tolua_S) +int lua_ax_base_RenderView_getScaleY(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24358,45 +25100,45 @@ int lua_ax_base_Animation_clone(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_clone'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getScaleY'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_clone'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getScaleY'", nullptr); return 0; } - auto&& ret = cobj->clone(); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + auto&& ret = cobj->getScaleY(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:clone",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getScaleY",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_clone'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getScaleY'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_init(lua_State* tolua_S) +int lua_ax_base_RenderView_getResolutionPolicy(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24405,45 +25147,45 @@ int lua_ax_base_Animation_init(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_init'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_getResolutionPolicy'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getResolutionPolicy'", nullptr); return 0; } - auto&& ret = cobj->init(); - tolua_pushboolean(tolua_S,(bool)ret); + int ret = (int)cobj->getResolutionPolicy(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:init",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:getResolutionPolicy",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getResolutionPolicy'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_initWithSpriteFrames(lua_State* tolua_S) +int lua_ax_base_RenderView_renderScene(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24452,85 +25194,51 @@ int lua_ax_base_Animation_initWithSpriteFrames(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_renderScene'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Vector arg0; - - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); - return 0; - } - auto&& ret = cobj->initWithSpriteFrames(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 2) - { - ax::Vector arg0; - double arg1; - - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithSpriteFrames"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); - return 0; - } - auto&& ret = cobj->initWithSpriteFrames(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 3) + if (argc == 2) { - ax::Vector arg0; - double arg1; - unsigned int arg2; - - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithSpriteFrames"); + ax::Scene* arg0; + ax::Renderer* arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithSpriteFrames"); + ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.RenderView:renderScene"); - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:initWithSpriteFrames"); + ok &= luaval_to_object(tolua_S, 3, "ax.Renderer",&arg1, "ax.RenderView:renderScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithSpriteFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_renderScene'", nullptr); return 0; } - auto&& ret = cobj->initWithSpriteFrames(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->renderScene(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:initWithSpriteFrames",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:renderScene",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_initWithSpriteFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_renderScene'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_initWithAnimationFrames(lua_State* tolua_S) +int lua_ax_base_RenderView_setInteractive(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::RenderView* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24539,118 +25247,82 @@ int lua_ax_base_Animation_initWithAnimationFrames(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animation*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::RenderView*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animation_initWithAnimationFrames'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RenderView_setInteractive'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 1) { - ax::Vector arg0; - double arg1; - unsigned int arg2; - - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:initWithAnimationFrames"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:initWithAnimationFrames"); + bool arg0; - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:initWithAnimationFrames"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.RenderView:setInteractive"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_initWithAnimationFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setInteractive'", nullptr); return 0; } - auto&& ret = cobj->initWithAnimationFrames(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setInteractive(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:initWithAnimationFrames",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderView:setInteractive",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_initWithAnimationFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setInteractive'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_create(lua_State* tolua_S) +int lua_ax_base_RenderView_setGfxContextAttrs(lua_State* tolua_S) { int argc = 0; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + argc = lua_gettop(tolua_S) - 1; - do + if (argc == 1) { - if (argc == 2) + GfxContextAttrs arg0; + #pragma warning NO CONVERSION TO NATIVE FOR GfxContextAttrs + ok = false; + if(!ok) { - ax::Vector arg0; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:create"); - if (!ok) { break; } - ax::Animation* ret = ax::Animation::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 3) - { - ax::Vector arg0; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:create"); - if (!ok) { break; } - unsigned int arg2; - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:create"); - if (!ok) { break; } - ax::Animation* ret = ax::Animation::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 0) - { - ax::Animation* ret = ax::Animation::create(); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_setGfxContextAttrs'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.Animation:create",argc, 0); + ax::RenderView::setGfxContextAttrs(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RenderView:setGfxContextAttrs",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_setGfxContextAttrs'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_createWithSpriteFrames(lua_State* tolua_S) +int lua_ax_base_RenderView_getGfxContextAttrs(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -24660,68 +25332,90 @@ int lua_ax_base_Animation_createWithSpriteFrames(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Animation",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.RenderView",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) - { - ax::Vector arg0; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); - return 0; - } - auto&& ret = ax::Animation::createWithSpriteFrames(arg0); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; - } - if (argc == 2) - { - ax::Vector arg0; - double arg1; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:createWithSpriteFrames"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); - return 0; - } - auto&& ret = ax::Animation::createWithSpriteFrames(arg0, arg1); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; - } - if (argc == 3) + if (argc == 0) { - ax::Vector arg0; - double arg1; - unsigned int arg2; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Animation:createWithSpriteFrames"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Animation:createWithSpriteFrames"); - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Animation:createWithSpriteFrames"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_createWithSpriteFrames'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderView_getGfxContextAttrs'", nullptr); return 0; } - auto&& ret = ax::Animation::createWithSpriteFrames(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); + auto&& ret = ax::RenderView::getGfxContextAttrs(); + #pragma warning NO CONVERSION FROM NATIVE FOR GfxContextAttrs; return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Animation:createWithSpriteFrames",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RenderView:getGfxContextAttrs",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_createWithSpriteFrames'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RenderView_getGfxContextAttrs'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animation_constructor(lua_State* tolua_S) +static int lua_ax_base_RenderView_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (RenderView)"); + return 0; +} + +int lua_register_ax_base_RenderView(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.RenderView"); + tolua_cclass(tolua_S,"RenderView","ax.RenderView","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"RenderView"); + tolua_function(tolua_S,"endToLua",lua_ax_base_RenderView_end); + tolua_function(tolua_S,"isGfxContextReady",lua_ax_base_RenderView_isGfxContextReady); + tolua_function(tolua_S,"swapBuffers",lua_ax_base_RenderView_swapBuffers); + tolua_function(tolua_S,"setIMEKeyboardState",lua_ax_base_RenderView_setIMEKeyboardState); + tolua_function(tolua_S,"windowShouldClose",lua_ax_base_RenderView_windowShouldClose); + tolua_function(tolua_S,"pollEvents",lua_ax_base_RenderView_pollEvents); + tolua_function(tolua_S,"getFrameSize",lua_ax_base_RenderView_getFrameSize); + tolua_function(tolua_S,"setFrameSize",lua_ax_base_RenderView_setFrameSize); + tolua_function(tolua_S,"setFrameZoomFactor",lua_ax_base_RenderView_setFrameZoomFactor); + tolua_function(tolua_S,"getFrameZoomFactor",lua_ax_base_RenderView_getFrameZoomFactor); + tolua_function(tolua_S,"setCursorVisible",lua_ax_base_RenderView_setCursorVisible); + tolua_function(tolua_S,"getRetinaFactor",lua_ax_base_RenderView_getRetinaFactor); + tolua_function(tolua_S,"setContentScaleFactor",lua_ax_base_RenderView_setContentScaleFactor); + tolua_function(tolua_S,"getContentScaleFactor",lua_ax_base_RenderView_getContentScaleFactor); + tolua_function(tolua_S,"isRetinaDisplay",lua_ax_base_RenderView_isRetinaDisplay); + tolua_function(tolua_S,"getVisibleSize",lua_ax_base_RenderView_getVisibleSize); + tolua_function(tolua_S,"getVisibleOrigin",lua_ax_base_RenderView_getVisibleOrigin); + tolua_function(tolua_S,"getVisibleRect",lua_ax_base_RenderView_getVisibleRect); + tolua_function(tolua_S,"getSafeAreaRect",lua_ax_base_RenderView_getSafeAreaRect); + tolua_function(tolua_S,"setDesignResolutionSize",lua_ax_base_RenderView_setDesignResolutionSize); + tolua_function(tolua_S,"getDesignResolutionSize",lua_ax_base_RenderView_getDesignResolutionSize); + tolua_function(tolua_S,"setViewPortInPoints",lua_ax_base_RenderView_setViewPortInPoints); + tolua_function(tolua_S,"setScissorInPoints",lua_ax_base_RenderView_setScissorInPoints); + tolua_function(tolua_S,"isScissorEnabled",lua_ax_base_RenderView_isScissorEnabled); + tolua_function(tolua_S,"getScissorRect",lua_ax_base_RenderView_getScissorRect); + tolua_function(tolua_S,"setViewName",lua_ax_base_RenderView_setViewName); + tolua_function(tolua_S,"getViewName",lua_ax_base_RenderView_getViewName); + tolua_function(tolua_S,"setIcon",lua_ax_base_RenderView_setIcon); + tolua_function(tolua_S,"setDefaultIcon",lua_ax_base_RenderView_setDefaultIcon); + tolua_function(tolua_S,"getViewPortRect",lua_ax_base_RenderView_getViewPortRect); + tolua_function(tolua_S,"getScaleX",lua_ax_base_RenderView_getScaleX); + tolua_function(tolua_S,"getScaleY",lua_ax_base_RenderView_getScaleY); + tolua_function(tolua_S,"getResolutionPolicy",lua_ax_base_RenderView_getResolutionPolicy); + tolua_function(tolua_S,"renderScene",lua_ax_base_RenderView_renderScene); + tolua_function(tolua_S,"setInteractive",lua_ax_base_RenderView_setInteractive); + tolua_function(tolua_S,"setGfxContextAttrs", lua_ax_base_RenderView_setGfxContextAttrs); + tolua_function(tolua_S,"getGfxContextAttrs", lua_ax_base_RenderView_getGfxContextAttrs); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::RenderView).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.RenderView"; + g_typeCast[typeName] = "ax.RenderView"; + return 1; +} + +int lua_ax_base_Director_init(lua_State* tolua_S) { int argc = 0; - ax::Animation* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24729,75 +25423,46 @@ int lua_ax_base_Animation_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_init'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animation_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_init'", nullptr); return 0; } - cobj = new ax::Animation(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Animation"); + auto&& ret = cobj->init(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animation:Animation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:init",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animation_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_init'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Animation_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Animation)"); - return 0; -} - -int lua_register_ax_base_Animation(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Animation"); - tolua_cclass(tolua_S,"Animation","ax.Animation","ax.Object",nullptr); - - tolua_beginmodule(tolua_S,"Animation"); - tolua_function(tolua_S,"new",lua_ax_base_Animation_constructor); - tolua_function(tolua_S,"addSpriteFrame",lua_ax_base_Animation_addSpriteFrame); - tolua_function(tolua_S,"addSpriteFrameWithFile",lua_ax_base_Animation_addSpriteFrameWithFile); - tolua_function(tolua_S,"addSpriteFrameWithTexture",lua_ax_base_Animation_addSpriteFrameWithTexture); - tolua_function(tolua_S,"getTotalDelayUnits",lua_ax_base_Animation_getTotalDelayUnits); - tolua_function(tolua_S,"setDelayPerUnit",lua_ax_base_Animation_setDelayPerUnit); - tolua_function(tolua_S,"getDelayPerUnit",lua_ax_base_Animation_getDelayPerUnit); - tolua_function(tolua_S,"getDuration",lua_ax_base_Animation_getDuration); - tolua_function(tolua_S,"getFrames",lua_ax_base_Animation_getFrames); - tolua_function(tolua_S,"setFrames",lua_ax_base_Animation_setFrames); - tolua_function(tolua_S,"getRestoreOriginalFrame",lua_ax_base_Animation_getRestoreOriginalFrame); - tolua_function(tolua_S,"setRestoreOriginalFrame",lua_ax_base_Animation_setRestoreOriginalFrame); - tolua_function(tolua_S,"getLoops",lua_ax_base_Animation_getLoops); - tolua_function(tolua_S,"setLoops",lua_ax_base_Animation_setLoops); - tolua_function(tolua_S,"clone",lua_ax_base_Animation_clone); - tolua_function(tolua_S,"init",lua_ax_base_Animation_init); - tolua_function(tolua_S,"initWithSpriteFrames",lua_ax_base_Animation_initWithSpriteFrames); - tolua_function(tolua_S,"initWithAnimationFrames",lua_ax_base_Animation_initWithAnimationFrames); - tolua_function(tolua_S,"create", lua_ax_base_Animation_create); - tolua_function(tolua_S,"createWithSpriteFrames", lua_ax_base_Animation_createWithSpriteFrames); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Animation).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Animation"; - g_typeCast[typeName] = "ax.Animation"; - return 1; -} - -int lua_ax_base_ActionInterval_getElapsed(lua_State* tolua_S) +int lua_ax_base_Director_getRunningScene(lua_State* tolua_S) { int argc = 0; - ax::ActionInterval* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24806,45 +25471,45 @@ int lua_ax_base_ActionInterval_getElapsed(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_getElapsed'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRunningScene'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_getElapsed'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRunningScene'", nullptr); return 0; } - auto&& ret = cobj->getElapsed(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getRunningScene(); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:getElapsed",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRunningScene",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_getElapsed'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRunningScene'.",&tolua_err); #endif return 0; } -int lua_ax_base_ActionInterval_setAmplitudeRate(lua_State* tolua_S) +int lua_ax_base_Director_getNextScene(lua_State* tolua_S) { int argc = 0; - ax::ActionInterval* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24853,48 +25518,45 @@ int lua_ax_base_ActionInterval_setAmplitudeRate(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_setAmplitudeRate'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getNextScene'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionInterval:setAmplitudeRate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_setAmplitudeRate'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getNextScene'", nullptr); return 0; } - cobj->setAmplitudeRate(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getNextScene(); + object_to_luaval(tolua_S, "ax.Scene",(ax::Scene*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:setAmplitudeRate",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getNextScene",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_setAmplitudeRate'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getNextScene'.",&tolua_err); #endif return 0; } -int lua_ax_base_ActionInterval_getAmplitudeRate(lua_State* tolua_S) +int lua_ax_base_Director_getAnimationInterval(lua_State* tolua_S) { int argc = 0; - ax::ActionInterval* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24903,45 +25565,45 @@ int lua_ax_base_ActionInterval_getAmplitudeRate(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_getAmplitudeRate'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getAnimationInterval'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_getAmplitudeRate'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getAnimationInterval'", nullptr); return 0; } - auto&& ret = cobj->getAmplitudeRate(); + auto&& ret = cobj->getAnimationInterval(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:getAmplitudeRate",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getAnimationInterval",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_getAmplitudeRate'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getAnimationInterval'.",&tolua_err); #endif return 0; } -int lua_ax_base_ActionInterval_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_setAnimationInterval(lua_State* tolua_S) { int argc = 0; - ax::ActionInterval* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -24950,71 +25612,48 @@ int lua_ax_base_ActionInterval_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ActionInterval",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ActionInterval*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionInterval_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setAnimationInterval'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionInterval:initWithDuration"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:setAnimationInterval"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionInterval_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setAnimationInterval'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setAnimationInterval(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionInterval:initWithDuration",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setAnimationInterval",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionInterval_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setAnimationInterval'.",&tolua_err); #endif return 0; } -static int lua_ax_base_ActionInterval_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ActionInterval)"); - return 0; -} - -int lua_register_ax_base_ActionInterval(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.ActionInterval"); - tolua_cclass(tolua_S,"ActionInterval","ax.ActionInterval","ax.FiniteTimeAction",nullptr); - - tolua_beginmodule(tolua_S,"ActionInterval"); - tolua_function(tolua_S,"getElapsed",lua_ax_base_ActionInterval_getElapsed); - tolua_function(tolua_S,"setAmplitudeRate",lua_ax_base_ActionInterval_setAmplitudeRate); - tolua_function(tolua_S,"getAmplitudeRate",lua_ax_base_ActionInterval_getAmplitudeRate); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_ActionInterval_initWithDuration); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::ActionInterval).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.ActionInterval"; - g_typeCast[typeName] = "ax.ActionInterval"; - return 1; -} - -int lua_ax_base_Sequence_initWithTwoActions(lua_State* tolua_S) +int lua_ax_base_Director_isStatsDisplay(lua_State* tolua_S) { int argc = 0; - ax::Sequence* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25023,51 +25662,45 @@ int lua_ax_base_Sequence_initWithTwoActions(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Sequence",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Sequence*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Sequence_initWithTwoActions'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isStatsDisplay'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::FiniteTimeAction* arg0; - ax::FiniteTimeAction* arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Sequence:initWithTwoActions"); - - ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.Sequence:initWithTwoActions"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_initWithTwoActions'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isStatsDisplay'", nullptr); return 0; } - auto&& ret = cobj->initWithTwoActions(arg0, arg1); + auto&& ret = cobj->isStatsDisplay(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:initWithTwoActions",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isStatsDisplay",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_initWithTwoActions'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isStatsDisplay'.",&tolua_err); #endif return 0; } -int lua_ax_base_Sequence_init(lua_State* tolua_S) +int lua_ax_base_Director_setStatsDisplay(lua_State* tolua_S) { int argc = 0; - ax::Sequence* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25076,48 +25709,48 @@ int lua_ax_base_Sequence_init(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Sequence",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Sequence*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Sequence_init'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setStatsDisplay'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Vector arg0; + bool arg0; - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Sequence:init"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setStatsDisplay"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsDisplay'", nullptr); return 0; } - auto&& ret = cobj->init(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setStatsDisplay(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:init",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setStatsDisplay",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setStatsDisplay'.",&tolua_err); #endif return 0; } -int lua_ax_base_Sequence_constructor(lua_State* tolua_S) +int lua_ax_base_Director_getSecondsPerFrame(lua_State* tolua_S) { int argc = 0; - ax::Sequence* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25125,58 +25758,46 @@ int lua_ax_base_Sequence_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getSecondsPerFrame'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Sequence_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getSecondsPerFrame'", nullptr); return 0; } - cobj = new ax::Sequence(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Sequence"); + auto&& ret = cobj->getSecondsPerFrame(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Sequence:Sequence",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getSecondsPerFrame",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Sequence_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getSecondsPerFrame'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Sequence_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Sequence)"); - return 0; -} - -int lua_register_ax_base_Sequence(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Sequence"); - tolua_cclass(tolua_S,"Sequence","ax.Sequence","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"Sequence"); - tolua_function(tolua_S,"new",lua_ax_base_Sequence_constructor); - tolua_function(tolua_S,"initWithTwoActions",lua_ax_base_Sequence_initWithTwoActions); - tolua_function(tolua_S,"init",lua_ax_base_Sequence_init); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Sequence).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Sequence"; - g_typeCast[typeName] = "ax.Sequence"; - return 1; -} - -int lua_ax_base_Repeat_setInnerAction(lua_State* tolua_S) +int lua_ax_base_Director_setStatsAnchor(lua_State* tolua_S) { int argc = 0; - ax::Repeat* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25185,48 +25806,59 @@ int lua_ax_base_Repeat_setInnerAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::FiniteTimeAction* arg0; + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); + return 0; + } + cobj->setStatsAnchor(); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 1) + { + ax::AnchorPreset arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:setInnerAction"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:setStatsAnchor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setStatsAnchor'", nullptr); return 0; } - cobj->setInnerAction(arg0); + cobj->setStatsAnchor(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:setInnerAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setStatsAnchor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_setInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setStatsAnchor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Repeat_getInnerAction(lua_State* tolua_S) +int lua_ax_base_Director_getRenderView(lua_State* tolua_S) { int argc = 0; - ax::Repeat* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25235,45 +25867,45 @@ int lua_ax_base_Repeat_getInnerAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_getInnerAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRenderView'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_getInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRenderView'", nullptr); return 0; } - auto&& ret = cobj->getInnerAction(); - object_to_luaval(tolua_S, "ax.FiniteTimeAction",(ax::FiniteTimeAction*)ret); + auto&& ret = cobj->getRenderView(); + object_to_luaval(tolua_S, "ax.RenderView",(ax::RenderView*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:getInnerAction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRenderView",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_getInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRenderView'.",&tolua_err); #endif return 0; } -int lua_ax_base_Repeat_initWithAction(lua_State* tolua_S) +int lua_ax_base_Director_setRenderView(lua_State* tolua_S) { int argc = 0; - ax::Repeat* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25282,150 +25914,95 @@ int lua_ax_base_Repeat_initWithAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Repeat*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Repeat_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setRenderView'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - ax::FiniteTimeAction* arg0; - unsigned int arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:initWithAction"); + ax::RenderView* arg0; - ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Repeat:initWithAction"); + ok &= luaval_to_object(tolua_S, 2, "ax.RenderView",&arg0, "ax.Director:setRenderView"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setRenderView'", nullptr); return 0; } - auto&& ret = cobj->initWithAction(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setRenderView(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:initWithAction",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setRenderView",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_initWithAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setRenderView'.",&tolua_err); #endif return 0; } -int lua_ax_base_Repeat_create(lua_State* tolua_S) +int lua_ax_base_Director_getTextureCache(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Repeat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) { - ax::FiniteTimeAction* arg0; - unsigned int arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Repeat:create"); - ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Repeat:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_create'", nullptr); - return 0; - } - auto&& ret = ax::Repeat::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.Repeat",(ax::Repeat*)ret); - return 1; + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getTextureCache'", nullptr); + return 0; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Repeat:create",argc, 2); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_create'.",&tolua_err); -#endif - return 0; -} -int lua_ax_base_Repeat_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::Repeat* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; #endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Repeat_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getTextureCache'", nullptr); return 0; } - cobj = new ax::Repeat(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Repeat"); + auto&& ret = cobj->getTextureCache(); + object_to_luaval(tolua_S, "ax.TextureCache",(ax::TextureCache*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Repeat:Repeat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getTextureCache",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Repeat_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getTextureCache'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Repeat_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Repeat)"); - return 0; -} - -int lua_register_ax_base_Repeat(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Repeat"); - tolua_cclass(tolua_S,"Repeat","ax.Repeat","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"Repeat"); - tolua_function(tolua_S,"new",lua_ax_base_Repeat_constructor); - tolua_function(tolua_S,"setInnerAction",lua_ax_base_Repeat_setInnerAction); - tolua_function(tolua_S,"getInnerAction",lua_ax_base_Repeat_getInnerAction); - tolua_function(tolua_S,"initWithAction",lua_ax_base_Repeat_initWithAction); - tolua_function(tolua_S,"create", lua_ax_base_Repeat_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Repeat).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Repeat"; - g_typeCast[typeName] = "ax.Repeat"; - return 1; -} - -int lua_ax_base_RepeatForever_setInnerAction(lua_State* tolua_S) +int lua_ax_base_Director_isNextDeltaTimeZero(lua_State* tolua_S) { int argc = 0; - ax::RepeatForever* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25434,48 +26011,45 @@ int lua_ax_base_RepeatForever_setInnerAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isNextDeltaTimeZero'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::ActionInterval* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:setInnerAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_setInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isNextDeltaTimeZero'", nullptr); return 0; } - cobj->setInnerAction(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isNextDeltaTimeZero(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:setInnerAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isNextDeltaTimeZero",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_setInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isNextDeltaTimeZero'.",&tolua_err); #endif return 0; } -int lua_ax_base_RepeatForever_getInnerAction(lua_State* tolua_S) +int lua_ax_base_Director_setNextDeltaTimeZero(lua_State* tolua_S) { int argc = 0; - ax::RepeatForever* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25484,45 +26058,48 @@ int lua_ax_base_RepeatForever_getInnerAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_getInnerAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setNextDeltaTimeZero'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setNextDeltaTimeZero"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_getInnerAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setNextDeltaTimeZero'", nullptr); return 0; } - auto&& ret = cobj->getInnerAction(); - object_to_luaval(tolua_S, "ax.ActionInterval",(ax::ActionInterval*)ret); + cobj->setNextDeltaTimeZero(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:getInnerAction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setNextDeltaTimeZero",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_getInnerAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setNextDeltaTimeZero'.",&tolua_err); #endif return 0; } -int lua_ax_base_RepeatForever_initWithAction(lua_State* tolua_S) +int lua_ax_base_Director_isPaused(lua_State* tolua_S) { int argc = 0; - ax::RepeatForever* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25531,145 +26108,92 @@ int lua_ax_base_RepeatForever_initWithAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::RepeatForever*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RepeatForever_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isPaused'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::ActionInterval* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:initWithAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_initWithAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isPaused'", nullptr); return 0; } - auto&& ret = cobj->initWithAction(arg0); + auto&& ret = cobj->isPaused(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:initWithAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isPaused",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_initWithAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isPaused'.",&tolua_err); #endif return 0; } -int lua_ax_base_RepeatForever_create(lua_State* tolua_S) +int lua_ax_base_Director_getTotalFrames(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.RepeatForever",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 1) +#if _AX_DEBUG >= 1 + if (!cobj) { - ax::ActionInterval* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.ActionInterval",&arg0, "ax.RepeatForever:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_create'", nullptr); - return 0; - } - auto&& ret = ax::RepeatForever::create(arg0); - object_to_luaval(tolua_S, "ax.RepeatForever",(ax::RepeatForever*)ret); - return 1; + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getTotalFrames'", nullptr); + return 0; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.RepeatForever:create",argc, 1); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_create'.",&tolua_err); #endif - return 0; -} -int lua_ax_base_RepeatForever_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::RepeatForever* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RepeatForever_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getTotalFrames'", nullptr); return 0; } - cobj = new ax::RepeatForever(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RepeatForever"); + auto&& ret = cobj->getTotalFrames(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RepeatForever:RepeatForever",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getTotalFrames",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RepeatForever_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getTotalFrames'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_RepeatForever_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (RepeatForever)"); - return 0; -} - -int lua_register_ax_base_RepeatForever(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.RepeatForever"); - tolua_cclass(tolua_S,"RepeatForever","ax.RepeatForever","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"RepeatForever"); - tolua_function(tolua_S,"new",lua_ax_base_RepeatForever_constructor); - tolua_function(tolua_S,"setInnerAction",lua_ax_base_RepeatForever_setInnerAction); - tolua_function(tolua_S,"getInnerAction",lua_ax_base_RepeatForever_getInnerAction); - tolua_function(tolua_S,"initWithAction",lua_ax_base_RepeatForever_initWithAction); - tolua_function(tolua_S,"create", lua_ax_base_RepeatForever_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::RepeatForever).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.RepeatForever"; - g_typeCast[typeName] = "ax.RepeatForever"; - return 1; -} - -int lua_ax_base_Spawn_initWithTwoActions(lua_State* tolua_S) +int lua_ax_base_Director_setProjection(lua_State* tolua_S) { int argc = 0; - ax::Spawn* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25678,51 +26202,48 @@ int lua_ax_base_Spawn_initWithTwoActions(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Spawn",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Spawn*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Spawn_initWithTwoActions'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setProjection'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - ax::FiniteTimeAction* arg0; - ax::FiniteTimeAction* arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.FiniteTimeAction",&arg0, "ax.Spawn:initWithTwoActions"); + ax::Director::Projection arg0; - ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.Spawn:initWithTwoActions"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:setProjection"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_initWithTwoActions'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setProjection'", nullptr); return 0; } - auto&& ret = cobj->initWithTwoActions(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setProjection(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:initWithTwoActions",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setProjection",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_initWithTwoActions'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setProjection'.",&tolua_err); #endif return 0; } -int lua_ax_base_Spawn_init(lua_State* tolua_S) +int lua_ax_base_Director_setViewport(lua_State* tolua_S) { int argc = 0; - ax::Spawn* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25731,48 +26252,45 @@ int lua_ax_base_Spawn_init(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Spawn",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Spawn*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Spawn_init'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setViewport'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vector arg0; - - ok &= luaval_to_ccvector(tolua_S, 2, &arg0, "ax.Spawn:init"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_init'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setViewport'", nullptr); return 0; } - auto&& ret = cobj->init(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setViewport(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:init",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setViewport",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_init'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setViewport'.",&tolua_err); #endif return 0; } -int lua_ax_base_Spawn_constructor(lua_State* tolua_S) +int lua_ax_base_Director_isSendCleanupToScene(lua_State* tolua_S) { int argc = 0; - ax::Spawn* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -25780,765 +26298,237 @@ int lua_ax_base_Spawn_constructor(lua_State* tolua_S) #endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Spawn_constructor'", nullptr); - return 0; - } - cobj = new ax::Spawn(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Spawn"); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Spawn:Spawn",argc, 0); - return 0; - #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Spawn_constructor'.",&tolua_err); + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - return 0; -} - -static int lua_ax_base_Spawn_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Spawn)"); - return 0; -} - -int lua_register_ax_base_Spawn(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Spawn"); - tolua_cclass(tolua_S,"Spawn","ax.Spawn","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"Spawn"); - tolua_function(tolua_S,"new",lua_ax_base_Spawn_constructor); - tolua_function(tolua_S,"initWithTwoActions",lua_ax_base_Spawn_initWithTwoActions); - tolua_function(tolua_S,"init",lua_ax_base_Spawn_init); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Spawn).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Spawn"; - g_typeCast[typeName] = "ax.Spawn"; - return 1; -} - -int lua_ax_base_RotateTo_initWithDuration(lua_State* tolua_S) -{ - int argc = 0; - ax::RotateTo* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RotateTo",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::RotateTo*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RotateTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isSendCleanupToScene'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:initWithDuration"); - - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 3) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:initWithDuration"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateTo:initWithDuration",argc, 3); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_initWithDuration'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_RotateTo_create(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.RotateTo",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S)-1; - - do - { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:create"); - if (!ok) { break; } - ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 3) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateTo:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateTo:create"); - if (!ok) { break; } - ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateTo:create"); - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateTo:create"); - if (!ok) { break; } - ax::RotateTo* ret = ax::RotateTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.RotateTo",(ax::RotateTo*)ret); - return 1; - } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.RotateTo:create",argc, 2); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_create'.",&tolua_err); -#endif - return 0; -} -int lua_ax_base_RotateTo_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::RotateTo* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RotateTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isSendCleanupToScene'", nullptr); return 0; } - cobj = new ax::RotateTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RotateTo"); + auto&& ret = cobj->isSendCleanupToScene(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateTo:RotateTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isSendCleanupToScene",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isSendCleanupToScene'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_RotateTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (RotateTo)"); - return 0; -} - -int lua_register_ax_base_RotateTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.RotateTo"); - tolua_cclass(tolua_S,"RotateTo","ax.RotateTo","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"RotateTo"); - tolua_function(tolua_S,"new",lua_ax_base_RotateTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_RotateTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_RotateTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::RotateTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.RotateTo"; - g_typeCast[typeName] = "ax.RotateTo"; - return 1; -} - -int lua_ax_base_RotateBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_getNotificationNode(lua_State* tolua_S) { int argc = 0; - ax::RotateBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.RotateBy",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::RotateBy*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_RotateBy_initWithDuration'", nullptr); - return 0; - } + tolua_Error tolua_err; #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 3) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:initWithDuration"); - - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateBy:initWithDuration"); - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateBy:initWithDuration",argc, 2); - return 0; #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_initWithDuration'.",&tolua_err); + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - return 0; -} -int lua_ax_base_RotateBy_create(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.RotateBy",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S)-1; - - do - { - if (argc == 3) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.RotateBy:create"); - if (!ok) { break; } - ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.RotateBy:create"); - if (!ok) { break; } - ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); - return 1; - } - } while (0); - ok = true; - do + if (!cobj) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.RotateBy:create"); - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.RotateBy:create"); - if (!ok) { break; } - ax::RotateBy* ret = ax::RotateBy::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.RotateBy",(ax::RotateBy*)ret); - return 1; - } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.RotateBy:create",argc, 2); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_create'.",&tolua_err); -#endif - return 0; -} -int lua_ax_base_RotateBy_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::RotateBy* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getNotificationNode'", nullptr); + return 0; + } #endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RotateBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getNotificationNode'", nullptr); return 0; } - cobj = new ax::RotateBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.RotateBy"); + auto&& ret = cobj->getNotificationNode(); + object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RotateBy:RotateBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getNotificationNode",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_RotateBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getNotificationNode'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_RotateBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (RotateBy)"); - return 0; -} - -int lua_register_ax_base_RotateBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.RotateBy"); - tolua_cclass(tolua_S,"RotateBy","ax.RotateBy","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"RotateBy"); - tolua_function(tolua_S,"new",lua_ax_base_RotateBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_RotateBy_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_RotateBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::RotateBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.RotateBy"; - g_typeCast[typeName] = "ax.RotateBy"; - return 1; -} - -int lua_ax_base_MoveBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_setNotificationNode(lua_State* tolua_S) { int argc = 0; - ax::MoveBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.MoveBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::MoveBy*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_MoveBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setNotificationNode'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:initWithDuration"); - - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveBy:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:initWithDuration"); - - if (!ok) { break; } - ax::Vec2 arg1; - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveBy:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveBy:initWithDuration",argc, 2); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_initWithDuration'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_MoveBy_create(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.MoveBy",0,&tolua_err)) goto tolua_lerror; -#endif argc = lua_gettop(tolua_S)-1; - - do - { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:create"); - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveBy:create"); - if (!ok) { break; } - ax::MoveBy* ret = ax::MoveBy::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.MoveBy",(ax::MoveBy*)ret); - return 1; - } - } while (0); - ok = true; - do + if (argc == 1) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveBy:create"); - if (!ok) { break; } - ax::Vec2 arg1; - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveBy:create"); - if (!ok) { break; } - ax::MoveBy* ret = ax::MoveBy::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.MoveBy",(ax::MoveBy*)ret); - return 1; - } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.MoveBy:create",argc, 2); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_create'.",&tolua_err); -#endif - return 0; -} -int lua_ax_base_MoveBy_constructor(lua_State* tolua_S) -{ - int argc = 0; - ax::MoveBy* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - + ax::Node* arg0; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.Director:setNotificationNode"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MoveBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setNotificationNode'", nullptr); return 0; } - cobj = new ax::MoveBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.MoveBy"); + cobj->setNotificationNode(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveBy:MoveBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setNotificationNode",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setNotificationNode'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_MoveBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (MoveBy)"); - return 0; -} - -int lua_register_ax_base_MoveBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.MoveBy"); - tolua_cclass(tolua_S,"MoveBy","ax.MoveBy","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"MoveBy"); - tolua_function(tolua_S,"new",lua_ax_base_MoveBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_MoveBy_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_MoveBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::MoveBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.MoveBy"; - g_typeCast[typeName] = "ax.MoveBy"; - return 1; -} - -int lua_ax_base_MoveTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_getWinSize(lua_State* tolua_S) { int argc = 0; - ax::MoveTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.MoveTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::MoveTo*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_MoveTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getWinSize'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:initWithDuration"); - - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:initWithDuration"); - if (!ok) { break; } - ax::Vec2 arg1; - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getWinSize'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveTo:initWithDuration",argc, 2); + auto&& ret = cobj->getWinSize(); + vec2_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getWinSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getWinSize'.",&tolua_err); #endif return 0; } -int lua_ax_base_MoveTo_create(lua_State* tolua_S) +int lua_ax_base_Director_getWinSizeInPixels(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.MoveTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - do +#if _AX_DEBUG >= 1 + if (!cobj) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:create"); - if (!ok) { break; } - ax::Vec3 arg1; - ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.MoveTo:create"); - if (!ok) { break; } - ax::MoveTo* ret = ax::MoveTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.MoveTo",(ax::MoveTo*)ret); - return 1; - } - } while (0); - ok = true; - do + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getWinSizeInPixels'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - if (argc == 2) + if(!ok) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.MoveTo:create"); - if (!ok) { break; } - ax::Vec2 arg1; - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.MoveTo:create"); - if (!ok) { break; } - ax::MoveTo* ret = ax::MoveTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.MoveTo",(ax::MoveTo*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getWinSizeInPixels'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.MoveTo:create",argc, 2); + auto&& ret = cobj->getWinSizeInPixels(); + vec2_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getWinSizeInPixels",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getWinSizeInPixels'.",&tolua_err); #endif + return 0; } -int lua_ax_base_MoveTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_getVisibleSize(lua_State* tolua_S) { int argc = 0; - ax::MoveTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26546,58 +26536,46 @@ int lua_ax_base_MoveTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getVisibleSize'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MoveTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getVisibleSize'", nullptr); return 0; } - cobj = new ax::MoveTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.MoveTo"); + auto&& ret = cobj->getVisibleSize(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MoveTo:MoveTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getVisibleSize",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_MoveTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getVisibleSize'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_MoveTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (MoveTo)"); - return 0; -} - -int lua_register_ax_base_MoveTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.MoveTo"); - tolua_cclass(tolua_S,"MoveTo","ax.MoveTo","ax.MoveBy",nullptr); - - tolua_beginmodule(tolua_S,"MoveTo"); - tolua_function(tolua_S,"new",lua_ax_base_MoveTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_MoveTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_MoveTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::MoveTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.MoveTo"; - g_typeCast[typeName] = "ax.MoveTo"; - return 1; -} - -int lua_ax_base_SkewTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_getVisibleOrigin(lua_State* tolua_S) { int argc = 0; - ax::SkewTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26606,94 +26584,92 @@ int lua_ax_base_SkewTo_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SkewTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SkewTo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SkewTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getVisibleOrigin'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 0) { - double arg0; - double arg1; - double arg2; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewTo:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewTo:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getVisibleOrigin'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getVisibleOrigin(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewTo:initWithDuration",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getVisibleOrigin",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getVisibleOrigin'.",&tolua_err); #endif return 0; } -int lua_ax_base_SkewTo_create(lua_State* tolua_S) +int lua_ax_base_Director_getSafeAreaRect(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.SkewTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 3) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getSafeAreaRect'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - double arg1; - double arg2; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewTo:create"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewTo:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewTo:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getSafeAreaRect'", nullptr); return 0; } - auto&& ret = ax::SkewTo::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.SkewTo",(ax::SkewTo*)ret); + auto&& ret = cobj->getSafeAreaRect(); + rect_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.SkewTo:create",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getSafeAreaRect",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getSafeAreaRect'.",&tolua_err); #endif + return 0; } -int lua_ax_base_SkewTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_convertToGL(lua_State* tolua_S) { int argc = 0; - ax::SkewTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26701,58 +26677,49 @@ int lua_ax_base_SkewTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_convertToGL'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Director:convertToGL"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_convertToGL'", nullptr); return 0; } - cobj = new ax::SkewTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SkewTo"); + auto&& ret = cobj->convertToGL(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewTo:SkewTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:convertToGL",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_convertToGL'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_SkewTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (SkewTo)"); - return 0; -} - -int lua_register_ax_base_SkewTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.SkewTo"); - tolua_cclass(tolua_S,"SkewTo","ax.SkewTo","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"SkewTo"); - tolua_function(tolua_S,"new",lua_ax_base_SkewTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_SkewTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_SkewTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::SkewTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.SkewTo"; - g_typeCast[typeName] = "ax.SkewTo"; - return 1; -} - -int lua_ax_base_SkewBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_convertToUI(lua_State* tolua_S) { int argc = 0; - ax::SkewBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26761,94 +26728,95 @@ int lua_ax_base_SkewBy_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.SkewBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::SkewBy*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_SkewBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_convertToUI'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 1) { - double arg0; - double arg1; - double arg2; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewBy:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewBy:initWithDuration"); + ax::Vec2 arg0; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewBy:initWithDuration"); + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.Director:convertToUI"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_convertToUI'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->convertToUI(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewBy:initWithDuration",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:convertToUI",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_convertToUI'.",&tolua_err); #endif return 0; } -int lua_ax_base_SkewBy_create(lua_State* tolua_S) +int lua_ax_base_Director_getZEye(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.SkewBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 3) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getZEye'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - double arg1; - double arg2; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.SkewBy:create"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.SkewBy:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.SkewBy:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getZEye'", nullptr); return 0; } - auto&& ret = ax::SkewBy::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.SkewBy",(ax::SkewBy*)ret); + auto&& ret = cobj->getZEye(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.SkewBy:create",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getZEye",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getZEye'.",&tolua_err); #endif + return 0; } -int lua_ax_base_SkewBy_constructor(lua_State* tolua_S) +int lua_ax_base_Director_runWithScene(lua_State* tolua_S) { int argc = 0; - ax::SkewBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26856,58 +26824,49 @@ int lua_ax_base_SkewBy_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_runWithScene'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Scene* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:runWithScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_SkewBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_runWithScene'", nullptr); return 0; } - cobj = new ax::SkewBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.SkewBy"); + cobj->runWithScene(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.SkewBy:SkewBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:runWithScene",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_SkewBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_runWithScene'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_SkewBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (SkewBy)"); - return 0; -} - -int lua_register_ax_base_SkewBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.SkewBy"); - tolua_cclass(tolua_S,"SkewBy","ax.SkewBy","ax.SkewTo",nullptr); - - tolua_beginmodule(tolua_S,"SkewBy"); - tolua_function(tolua_S,"new",lua_ax_base_SkewBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_SkewBy_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_SkewBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::SkewBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.SkewBy"; - g_typeCast[typeName] = "ax.SkewBy"; - return 1; -} - -int lua_ax_base_JumpBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_pushScene(lua_State* tolua_S) { int argc = 0; - ax::JumpBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -26916,99 +26875,95 @@ int lua_ax_base_JumpBy_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.JumpBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::JumpBy*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_JumpBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pushScene'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 1) { - double arg0; - ax::Vec2 arg1; - double arg2; - int arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpBy:initWithDuration"); - - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpBy:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpBy:initWithDuration"); + ax::Scene* arg0; - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpBy:initWithDuration"); + ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:pushScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pushScene'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->pushScene(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpBy:initWithDuration",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pushScene",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pushScene'.",&tolua_err); #endif return 0; } -int lua_ax_base_JumpBy_create(lua_State* tolua_S) +int lua_ax_base_Director_popScene(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.JumpBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 4) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popScene'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - ax::Vec2 arg1; - double arg2; - int arg3; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpBy:create"); - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpBy:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpBy:create"); - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpBy:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popScene'", nullptr); return 0; } - auto&& ret = ax::JumpBy::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.JumpBy",(ax::JumpBy*)ret); + cobj->popScene(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.JumpBy:create",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popScene",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popScene'.",&tolua_err); #endif + return 0; } -int lua_ax_base_JumpBy_constructor(lua_State* tolua_S) +int lua_ax_base_Director_popToRootScene(lua_State* tolua_S) { int argc = 0; - ax::JumpBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27016,58 +26971,46 @@ int lua_ax_base_JumpBy_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popToRootScene'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popToRootScene'", nullptr); return 0; } - cobj = new ax::JumpBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.JumpBy"); + cobj->popToRootScene(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpBy:JumpBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popToRootScene",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popToRootScene'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_JumpBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (JumpBy)"); - return 0; -} - -int lua_register_ax_base_JumpBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.JumpBy"); - tolua_cclass(tolua_S,"JumpBy","ax.JumpBy","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"JumpBy"); - tolua_function(tolua_S,"new",lua_ax_base_JumpBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_JumpBy_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_JumpBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::JumpBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.JumpBy"; - g_typeCast[typeName] = "ax.JumpBy"; - return 1; -} - -int lua_ax_base_JumpTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_popToSceneStackLevel(lua_State* tolua_S) { int argc = 0; - ax::JumpTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27076,99 +27019,98 @@ int lua_ax_base_JumpTo_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.JumpTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::JumpTo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_JumpTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popToSceneStackLevel'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 1) { - double arg0; - ax::Vec2 arg1; - double arg2; - int arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpTo:initWithDuration"); - - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpTo:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpTo:initWithDuration"); + int arg0; - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpTo:initWithDuration"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:popToSceneStackLevel"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popToSceneStackLevel'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->popToSceneStackLevel(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpTo:initWithDuration",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popToSceneStackLevel",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popToSceneStackLevel'.",&tolua_err); #endif return 0; } -int lua_ax_base_JumpTo_create(lua_State* tolua_S) +int lua_ax_base_Director_replaceScene(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.JumpTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 4) +#if _AX_DEBUG >= 1 + if (!cobj) { - double arg0; - ax::Vec2 arg1; - double arg2; - int arg3; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.JumpTo:create"); - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.JumpTo:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.JumpTo:create"); - ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.JumpTo:create"); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_replaceScene'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Scene* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Scene",&arg0, "ax.Director:replaceScene"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_replaceScene'", nullptr); return 0; } - auto&& ret = ax::JumpTo::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.JumpTo",(ax::JumpTo*)ret); + cobj->replaceScene(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.JumpTo:create",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:replaceScene",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_replaceScene'.",&tolua_err); #endif + return 0; } -int lua_ax_base_JumpTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_end(lua_State* tolua_S) { int argc = 0; - ax::JumpTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27176,58 +27118,46 @@ int lua_ax_base_JumpTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_end'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_JumpTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_end'", nullptr); return 0; } - cobj = new ax::JumpTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.JumpTo"); + cobj->end(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.JumpTo:JumpTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:end",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_JumpTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_end'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_JumpTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (JumpTo)"); - return 0; -} - -int lua_register_ax_base_JumpTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.JumpTo"); - tolua_cclass(tolua_S,"JumpTo","ax.JumpTo","ax.JumpBy",nullptr); - - tolua_beginmodule(tolua_S,"JumpTo"); - tolua_function(tolua_S,"new",lua_ax_base_JumpTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_JumpTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_JumpTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::JumpTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.JumpTo"; - g_typeCast[typeName] = "ax.JumpTo"; - return 1; -} - -int lua_ax_base_BezierBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_pause(lua_State* tolua_S) { int argc = 0; - ax::BezierBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27236,52 +27166,45 @@ int lua_ax_base_BezierBy_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.BezierBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::BezierBy*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_BezierBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pause'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - double arg0; - ax::BezierConfig arg1; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.BezierBy:initWithDuration"); - - #pragma warning NO CONVERSION TO NATIVE FOR BezierConfig - ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pause'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->pause(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierBy:initWithDuration",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pause",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierBy_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pause'.",&tolua_err); #endif return 0; } -int lua_ax_base_BezierBy_constructor(lua_State* tolua_S) +int lua_ax_base_Director_resume(lua_State* tolua_S) { int argc = 0; - ax::BezierBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27289,57 +27212,46 @@ int lua_ax_base_BezierBy_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_resume'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_resume'", nullptr); return 0; } - cobj = new ax::BezierBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.BezierBy"); + cobj->resume(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierBy:BezierBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:resume",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_resume'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_BezierBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (BezierBy)"); - return 0; -} - -int lua_register_ax_base_BezierBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.BezierBy"); - tolua_cclass(tolua_S,"BezierBy","ax.BezierBy","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"BezierBy"); - tolua_function(tolua_S,"new",lua_ax_base_BezierBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_BezierBy_initWithDuration); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::BezierBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.BezierBy"; - g_typeCast[typeName] = "ax.BezierBy"; - return 1; -} - -int lua_ax_base_BezierTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_restart(lua_State* tolua_S) { int argc = 0; - ax::BezierTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27348,52 +27260,45 @@ int lua_ax_base_BezierTo_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.BezierTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::BezierTo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_BezierTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_restart'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - double arg0; - ax::BezierConfig arg1; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.BezierTo:initWithDuration"); - - #pragma warning NO CONVERSION TO NATIVE FOR BezierConfig - ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_restart'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->restart(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierTo:initWithDuration",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:restart",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_restart'.",&tolua_err); #endif return 0; } -int lua_ax_base_BezierTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_stopAnimation(lua_State* tolua_S) { int argc = 0; - ax::BezierTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27401,227 +27306,140 @@ int lua_ax_base_BezierTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_stopAnimation'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_BezierTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_stopAnimation'", nullptr); return 0; } - cobj = new ax::BezierTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.BezierTo"); + cobj->stopAnimation(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.BezierTo:BezierTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:stopAnimation",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_BezierTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_stopAnimation'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_BezierTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (BezierTo)"); - return 0; -} - -int lua_register_ax_base_BezierTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.BezierTo"); - tolua_cclass(tolua_S,"BezierTo","ax.BezierTo","ax.BezierBy",nullptr); - - tolua_beginmodule(tolua_S,"BezierTo"); - tolua_function(tolua_S,"new",lua_ax_base_BezierTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_BezierTo_initWithDuration); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::BezierTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.BezierTo"; - g_typeCast[typeName] = "ax.BezierTo"; - return 1; -} - -int lua_ax_base_ScaleTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_startAnimation(lua_State* tolua_S) { int argc = 0; - ax::ScaleTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ScaleTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ScaleTo*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ScaleTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_startAnimation'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 3) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1, arg2); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 4) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:initWithDuration"); - - if (!ok) { break; } - double arg3; - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleTo:initWithDuration"); - if (!ok) { break; } - bool ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_startAnimation'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleTo:initWithDuration",argc, 4); + cobj->startAnimation(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:startAnimation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_startAnimation'.",&tolua_err); #endif return 0; } -int lua_ax_base_ScaleTo_create(lua_State* tolua_S) +int lua_ax_base_Director_drawScene(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.ScaleTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - do - { - if (argc == 3) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:create"); - if (!ok) { break; } - ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); - return 1; - } - } while (0); - ok = true; - do +#if _AX_DEBUG >= 1 + if (!cobj) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); - if (!ok) { break; } - ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); - return 1; - } - } while (0); - ok = true; - do + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_drawScene'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - if (argc == 4) + if(!ok) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleTo:create"); - if (!ok) { break; } - double arg3; - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleTo:create"); - if (!ok) { break; } - ax::ScaleTo* ret = ax::ScaleTo::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.ScaleTo",(ax::ScaleTo*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_drawScene'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.ScaleTo:create",argc, 4); + cobj->drawScene(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:drawScene",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_drawScene'.",&tolua_err); #endif + return 0; } -int lua_ax_base_ScaleTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_purgeCachedData(lua_State* tolua_S) { int argc = 0; - ax::ScaleTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27629,137 +27447,93 @@ int lua_ax_base_ScaleTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_purgeCachedData'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ScaleTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_purgeCachedData'", nullptr); return 0; } - cobj = new ax::ScaleTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ScaleTo"); + cobj->purgeCachedData(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleTo:ScaleTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:purgeCachedData",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_purgeCachedData'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_ScaleTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ScaleTo)"); - return 0; -} - -int lua_register_ax_base_ScaleTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.ScaleTo"); - tolua_cclass(tolua_S,"ScaleTo","ax.ScaleTo","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"ScaleTo"); - tolua_function(tolua_S,"new",lua_ax_base_ScaleTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_ScaleTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_ScaleTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::ScaleTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.ScaleTo"; - g_typeCast[typeName] = "ax.ScaleTo"; - return 1; -} - -int lua_ax_base_ScaleBy_create(lua_State* tolua_S) +int lua_ax_base_Director_setDefaultValues(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.ScaleBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - do - { - if (argc == 3) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleBy:create"); - if (!ok) { break; } - ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); - return 1; - } - } while (0); - ok = true; - do +#if _AX_DEBUG >= 1 + if (!cobj) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); - if (!ok) { break; } - ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); - return 1; - } - } while (0); - ok = true; - do + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setDefaultValues'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - if (argc == 4) + if(!ok) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ScaleBy:create"); - if (!ok) { break; } - double arg3; - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.ScaleBy:create"); - if (!ok) { break; } - ax::ScaleBy* ret = ax::ScaleBy::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.ScaleBy",(ax::ScaleBy*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setDefaultValues'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.ScaleBy:create",argc, 4); + cobj->setDefaultValues(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setDefaultValues",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleBy_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setDefaultValues'.",&tolua_err); #endif + return 0; } -int lua_ax_base_ScaleBy_constructor(lua_State* tolua_S) +int lua_ax_base_Director_setGLDefaultValues(lua_State* tolua_S) { int argc = 0; - ax::ScaleBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27767,57 +27541,46 @@ int lua_ax_base_ScaleBy_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setGLDefaultValues'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ScaleBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setGLDefaultValues'", nullptr); return 0; } - cobj = new ax::ScaleBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ScaleBy"); + cobj->setGLDefaultValues(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ScaleBy:ScaleBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setGLDefaultValues",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ScaleBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setGLDefaultValues'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_ScaleBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ScaleBy)"); - return 0; -} - -int lua_register_ax_base_ScaleBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.ScaleBy"); - tolua_cclass(tolua_S,"ScaleBy","ax.ScaleBy","ax.ScaleTo",nullptr); - - tolua_beginmodule(tolua_S,"ScaleBy"); - tolua_function(tolua_S,"new",lua_ax_base_ScaleBy_constructor); - tolua_function(tolua_S,"create", lua_ax_base_ScaleBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::ScaleBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.ScaleBy"; - g_typeCast[typeName] = "ax.ScaleBy"; - return 1; -} - -int lua_ax_base_Blink_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_setClearColor(lua_State* tolua_S) { int argc = 0; - ax::Blink* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27826,89 +27589,99 @@ int lua_ax_base_Blink_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Blink",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Blink*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Blink_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setClearColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - double arg0; - int arg1; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Blink:initWithDuration"); + ax::Color arg0; - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Blink:initWithDuration"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.Director:setClearColor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setClearColor'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setClearColor(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Blink:initWithDuration",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setClearColor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setClearColor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Blink_create(lua_State* tolua_S) +int lua_ax_base_Director_mainLoop(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Blink",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 2) + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) { - double arg0; - int arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Blink:create"); - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Blink:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_create'", nullptr); - return 0; - } - auto&& ret = ax::Blink::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.Blink",(ax::Blink*)ret); - return 1; + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_mainLoop'", nullptr); + return 0; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Blink:create",argc, 2); +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + double arg0; + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:mainLoop"); + + if (!ok) { break; } + cobj->mainLoop(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 0) { + cobj->mainLoop(); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:mainLoop",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_mainLoop'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Blink_constructor(lua_State* tolua_S) +int lua_ax_base_Director_setContentScaleFactor(lua_State* tolua_S) { int argc = 0; - ax::Blink* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27916,58 +27689,49 @@ int lua_ax_base_Blink_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setContentScaleFactor'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Director:setContentScaleFactor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Blink_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setContentScaleFactor'", nullptr); return 0; } - cobj = new ax::Blink(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Blink"); + cobj->setContentScaleFactor(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Blink:Blink",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setContentScaleFactor",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Blink_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setContentScaleFactor'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_Blink_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (Blink)"); - return 0; -} - -int lua_register_ax_base_Blink(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.Blink"); - tolua_cclass(tolua_S,"Blink","ax.Blink","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"Blink"); - tolua_function(tolua_S,"new",lua_ax_base_Blink_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_Blink_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_Blink_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Blink).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Blink"; - g_typeCast[typeName] = "ax.Blink"; - return 1; -} - -int lua_ax_base_FadeTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_getContentScaleFactor(lua_State* tolua_S) { int argc = 0; - ax::FadeTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -27976,89 +27740,92 @@ int lua_ax_base_FadeTo_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.FadeTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::FadeTo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getContentScaleFactor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - double arg0; - uint16_t arg1; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeTo:initWithDuration"); - - ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.FadeTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getContentScaleFactor'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getContentScaleFactor(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeTo:initWithDuration",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getContentScaleFactor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getContentScaleFactor'.",&tolua_err); #endif return 0; } -int lua_ax_base_FadeTo_create(lua_State* tolua_S) +int lua_ax_base_Director_getScheduler(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.FadeTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getScheduler'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - uint16_t arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeTo:create"); - ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.FadeTo:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getScheduler'", nullptr); return 0; } - auto&& ret = ax::FadeTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.FadeTo",(ax::FadeTo*)ret); + auto&& ret = cobj->getScheduler(); + object_to_luaval(tolua_S, "ax.Scheduler",(ax::Scheduler*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeTo:create",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getScheduler",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getScheduler'.",&tolua_err); #endif + return 0; } -int lua_ax_base_FadeTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_setScheduler(lua_State* tolua_S) { int argc = 0; - ax::FadeTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28066,58 +27833,49 @@ int lua_ax_base_FadeTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setScheduler'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Scheduler* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Scheduler",&arg0, "ax.Director:setScheduler"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setScheduler'", nullptr); return 0; } - cobj = new ax::FadeTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeTo"); + cobj->setScheduler(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeTo:FadeTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setScheduler",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setScheduler'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_FadeTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (FadeTo)"); - return 0; -} - -int lua_register_ax_base_FadeTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.FadeTo"); - tolua_cclass(tolua_S,"FadeTo","ax.FadeTo","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"FadeTo"); - tolua_function(tolua_S,"new",lua_ax_base_FadeTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_FadeTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_FadeTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::FadeTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.FadeTo"; - g_typeCast[typeName] = "ax.FadeTo"; - return 1; -} - -int lua_ax_base_FadeIn_setReverseAction(lua_State* tolua_S) +int lua_ax_base_Director_getActionManager(lua_State* tolua_S) { int argc = 0; - ax::FadeIn* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28126,84 +27884,95 @@ int lua_ax_base_FadeIn_setReverseAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.FadeIn",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::FadeIn*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeIn_setReverseAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getActionManager'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::FadeTo* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.FadeTo",&arg0, "ax.FadeIn:setReverseAction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_setReverseAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getActionManager'", nullptr); return 0; } - cobj->setReverseAction(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getActionManager(); + object_to_luaval(tolua_S, "ax.ActionManager",(ax::ActionManager*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeIn:setReverseAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getActionManager",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_setReverseAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getActionManager'.",&tolua_err); #endif return 0; } -int lua_ax_base_FadeIn_create(lua_State* tolua_S) +int lua_ax_base_Director_setActionManager(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.FadeIn",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setActionManager'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 1) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeIn:create"); + ax::ActionManager* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.ActionManager",&arg0, "ax.Director:setActionManager"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setActionManager'", nullptr); return 0; } - auto&& ret = ax::FadeIn::create(arg0); - object_to_luaval(tolua_S, "ax.FadeIn",(ax::FadeIn*)ret); + cobj->setActionManager(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeIn:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setActionManager",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setActionManager'.",&tolua_err); #endif + return 0; } -int lua_ax_base_FadeIn_constructor(lua_State* tolua_S) +int lua_ax_base_Director_getEventDispatcher(lua_State* tolua_S) { int argc = 0; - ax::FadeIn* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28211,58 +27980,46 @@ int lua_ax_base_FadeIn_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getEventDispatcher'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeIn_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getEventDispatcher'", nullptr); return 0; } - cobj = new ax::FadeIn(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeIn"); + auto&& ret = cobj->getEventDispatcher(); + object_to_luaval(tolua_S, "ax.EventDispatcher",(ax::EventDispatcher*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeIn:FadeIn",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getEventDispatcher",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeIn_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getEventDispatcher'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_FadeIn_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (FadeIn)"); - return 0; -} - -int lua_register_ax_base_FadeIn(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.FadeIn"); - tolua_cclass(tolua_S,"FadeIn","ax.FadeIn","ax.FadeTo",nullptr); - - tolua_beginmodule(tolua_S,"FadeIn"); - tolua_function(tolua_S,"new",lua_ax_base_FadeIn_constructor); - tolua_function(tolua_S,"setReverseAction",lua_ax_base_FadeIn_setReverseAction); - tolua_function(tolua_S,"create", lua_ax_base_FadeIn_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::FadeIn).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.FadeIn"; - g_typeCast[typeName] = "ax.FadeIn"; - return 1; -} - -int lua_ax_base_FadeOut_setReverseAction(lua_State* tolua_S) +int lua_ax_base_Director_setEventDispatcher(lua_State* tolua_S) { int argc = 0; - ax::FadeOut* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28271,84 +28028,95 @@ int lua_ax_base_FadeOut_setReverseAction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.FadeOut",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::FadeOut*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_FadeOut_setReverseAction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setEventDispatcher'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::FadeTo* arg0; + ax::EventDispatcher* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.FadeTo",&arg0, "ax.FadeOut:setReverseAction"); + ok &= luaval_to_object(tolua_S, 2, "ax.EventDispatcher",&arg0, "ax.Director:setEventDispatcher"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_setReverseAction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setEventDispatcher'", nullptr); return 0; } - cobj->setReverseAction(arg0); + cobj->setEventDispatcher(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeOut:setReverseAction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setEventDispatcher",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_setReverseAction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setEventDispatcher'.",&tolua_err); #endif return 0; } -int lua_ax_base_FadeOut_create(lua_State* tolua_S) +int lua_ax_base_Director_getRenderer(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.FadeOut",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 1) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getRenderer'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.FadeOut:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getRenderer'", nullptr); return 0; } - auto&& ret = ax::FadeOut::create(arg0); - object_to_luaval(tolua_S, "ax.FadeOut",(ax::FadeOut*)ret); + auto&& ret = cobj->getRenderer(); + object_to_luaval(tolua_S, "ax.Renderer",(ax::Renderer*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.FadeOut:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getRenderer",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getRenderer'.",&tolua_err); #endif + return 0; } -int lua_ax_base_FadeOut_constructor(lua_State* tolua_S) +int lua_ax_base_Director_getDeltaTime(lua_State* tolua_S) { int argc = 0; - ax::FadeOut* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28356,58 +28124,46 @@ int lua_ax_base_FadeOut_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getDeltaTime'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_FadeOut_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getDeltaTime'", nullptr); return 0; } - cobj = new ax::FadeOut(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.FadeOut"); + auto&& ret = cobj->getDeltaTime(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.FadeOut:FadeOut",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getDeltaTime",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_FadeOut_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getDeltaTime'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_FadeOut_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (FadeOut)"); - return 0; -} - -int lua_register_ax_base_FadeOut(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.FadeOut"); - tolua_cclass(tolua_S,"FadeOut","ax.FadeOut","ax.FadeTo",nullptr); - - tolua_beginmodule(tolua_S,"FadeOut"); - tolua_function(tolua_S,"new",lua_ax_base_FadeOut_constructor); - tolua_function(tolua_S,"setReverseAction",lua_ax_base_FadeOut_setReverseAction); - tolua_function(tolua_S,"create", lua_ax_base_FadeOut_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::FadeOut).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.FadeOut"; - g_typeCast[typeName] = "ax.FadeOut"; - return 1; -} - -int lua_ax_base_TintTo_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_getFrameRate(lua_State* tolua_S) { int argc = 0; - ax::TintTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28416,117 +28172,95 @@ int lua_ax_base_TintTo_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.TintTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::TintTo*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TintTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getFrameRate'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 0) { - double arg0; - uint16_t arg1; - uint16_t arg2; - uint16_t arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:initWithDuration"); - - ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.TintTo:initWithDuration"); - - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "ax.TintTo:initWithDuration"); - - ok &= luaval_to_uint16(tolua_S, 5,&arg3, "ax.TintTo:initWithDuration"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintTo_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getFrameRate'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getFrameRate(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintTo:initWithDuration",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getFrameRate",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getFrameRate'.",&tolua_err); #endif return 0; } -int lua_ax_base_TintTo_create(lua_State* tolua_S) +int lua_ax_base_Director_pushMatrix(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.TintTo",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - do +#if _AX_DEBUG >= 1 + if (!cobj) { - if (argc == 2) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:create"); - if (!ok) { break; } - ax::Color3B arg1; - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "ax.TintTo:create"); - if (!ok) { break; } - ax::TintTo* ret = ax::TintTo::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.TintTo",(ax::TintTo*)ret); - return 1; - } - } while (0); - ok = true; - do + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_pushMatrix'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) { - if (argc == 4) + ax::MATRIX_STACK_TYPE arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:pushMatrix"); + if(!ok) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintTo:create"); - if (!ok) { break; } - uint16_t arg1; - ok &= luaval_to_uint16(tolua_S, 3,&arg1, "ax.TintTo:create"); - if (!ok) { break; } - uint16_t arg2; - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "ax.TintTo:create"); - if (!ok) { break; } - uint16_t arg3; - ok &= luaval_to_uint16(tolua_S, 5,&arg3, "ax.TintTo:create"); - if (!ok) { break; } - ax::TintTo* ret = ax::TintTo::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.TintTo",(ax::TintTo*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_pushMatrix'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.TintTo:create",argc, 4); + cobj->pushMatrix(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:pushMatrix",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_pushMatrix'.",&tolua_err); #endif + return 0; } -int lua_ax_base_TintTo_constructor(lua_State* tolua_S) +int lua_ax_base_Director_popMatrix(lua_State* tolua_S) { int argc = 0; - ax::TintTo* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28534,58 +28268,49 @@ int lua_ax_base_TintTo_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_popMatrix'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::MATRIX_STACK_TYPE arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:popMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintTo_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_popMatrix'", nullptr); return 0; } - cobj = new ax::TintTo(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TintTo"); + cobj->popMatrix(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintTo:TintTo",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:popMatrix",argc, 1); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintTo_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_popMatrix'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_TintTo_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (TintTo)"); - return 0; -} - -int lua_register_ax_base_TintTo(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.TintTo"); - tolua_cclass(tolua_S,"TintTo","ax.TintTo","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"TintTo"); - tolua_function(tolua_S,"new",lua_ax_base_TintTo_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_TintTo_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_TintTo_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::TintTo).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.TintTo"; - g_typeCast[typeName] = "ax.TintTo"; - return 1; -} - -int lua_ax_base_TintBy_initWithDuration(lua_State* tolua_S) +int lua_ax_base_Director_loadIdentityMatrix(lua_State* tolua_S) { int argc = 0; - ax::TintBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28594,99 +28319,101 @@ int lua_ax_base_TintBy_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.TintBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::TintBy*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TintBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_loadIdentityMatrix'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 1) { - double arg0; - int32_t arg1; - int32_t arg2; - int32_t arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintBy:initWithDuration"); - - ok &= luaval_to_int32(tolua_S, 3,&arg1, "ax.TintBy:initWithDuration"); - - ok &= luaval_to_int32(tolua_S, 4,&arg2, "ax.TintBy:initWithDuration"); + ax::MATRIX_STACK_TYPE arg0; - ok &= luaval_to_int32(tolua_S, 5,&arg3, "ax.TintBy:initWithDuration"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:loadIdentityMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_loadIdentityMatrix'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->loadIdentityMatrix(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintBy:initWithDuration",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:loadIdentityMatrix",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_loadIdentityMatrix'.",&tolua_err); #endif return 0; } -int lua_ax_base_TintBy_create(lua_State* tolua_S) +int lua_ax_base_Director_loadMatrix(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.TintBy",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); - if (argc == 4) +#if _AX_DEBUG >= 1 + if (!cobj) { - double arg0; - int32_t arg1; - int32_t arg2; - int32_t arg3; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.TintBy:create"); - ok &= luaval_to_int32(tolua_S, 3,&arg1, "ax.TintBy:create"); - ok &= luaval_to_int32(tolua_S, 4,&arg2, "ax.TintBy:create"); - ok &= luaval_to_int32(tolua_S, 5,&arg3, "ax.TintBy:create"); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_loadMatrix'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + ax::MATRIX_STACK_TYPE arg0; + ax::Mat4 arg1; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:loadMatrix"); + + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Director:loadMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_loadMatrix'", nullptr); return 0; } - auto&& ret = ax::TintBy::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.TintBy",(ax::TintBy*)ret); + cobj->loadMatrix(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.TintBy:create",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:loadMatrix",argc, 2); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_loadMatrix'.",&tolua_err); #endif + return 0; } -int lua_ax_base_TintBy_constructor(lua_State* tolua_S) +int lua_ax_base_Director_multiplyMatrix(lua_State* tolua_S) { int argc = 0; - ax::TintBy* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28694,94 +28421,102 @@ int lua_ax_base_TintBy_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_multiplyMatrix'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + ax::MATRIX_STACK_TYPE arg0; + ax::Mat4 arg1; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:multiplyMatrix"); + + ok &= luaval_to_mat4(tolua_S, 3, &arg1, "ax.Director:multiplyMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TintBy_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_multiplyMatrix'", nullptr); return 0; } - cobj = new ax::TintBy(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TintBy"); + cobj->multiplyMatrix(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TintBy:TintBy",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:multiplyMatrix",argc, 2); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TintBy_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_multiplyMatrix'.",&tolua_err); #endif return 0; } - -static int lua_ax_base_TintBy_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (TintBy)"); - return 0; -} - -int lua_register_ax_base_TintBy(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.TintBy"); - tolua_cclass(tolua_S,"TintBy","ax.TintBy","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"TintBy"); - tolua_function(tolua_S,"new",lua_ax_base_TintBy_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_TintBy_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_TintBy_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::TintBy).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.TintBy"; - g_typeCast[typeName] = "ax.TintBy"; - return 1; -} - -int lua_ax_base_DelayTime_create(lua_State* tolua_S) +int lua_ax_base_Director_getMatrix(lua_State* tolua_S) { int argc = 0; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.DelayTime",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getMatrix'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; if (argc == 1) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.DelayTime:create"); + ax::MATRIX_STACK_TYPE arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Director:getMatrix"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DelayTime_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getMatrix'", nullptr); return 0; } - auto&& ret = ax::DelayTime::create(arg0); - object_to_luaval(tolua_S, "ax.DelayTime",(ax::DelayTime*)ret); + auto&& ret = cobj->getMatrix(arg0); + mat4_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.DelayTime:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getMatrix",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_DelayTime_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getMatrix'.",&tolua_err); #endif + return 0; } -int lua_ax_base_DelayTime_constructor(lua_State* tolua_S) +int lua_ax_base_Director_resetMatrixStack(lua_State* tolua_S) { int argc = 0; - ax::DelayTime* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28789,57 +28524,46 @@ int lua_ax_base_DelayTime_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_resetMatrixStack'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DelayTime_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_resetMatrixStack'", nullptr); return 0; } - cobj = new ax::DelayTime(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.DelayTime"); + cobj->resetMatrixStack(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.DelayTime:DelayTime",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_DelayTime_constructor'.",&tolua_err); -#endif - - return 0; -} - -static int lua_ax_base_DelayTime_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (DelayTime)"); - return 0; -} - -int lua_register_ax_base_DelayTime(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.DelayTime"); - tolua_cclass(tolua_S,"DelayTime","ax.DelayTime","ax.ActionInterval",nullptr); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:resetMatrixStack",argc, 0); + return 0; - tolua_beginmodule(tolua_S,"DelayTime"); - tolua_function(tolua_S,"new",lua_ax_base_DelayTime_constructor); - tolua_function(tolua_S,"create", lua_ax_base_DelayTime_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::DelayTime).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.DelayTime"; - g_typeCast[typeName] = "ax.DelayTime"; - return 1; -} +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_resetMatrixStack'.",&tolua_err); +#endif -int lua_ax_base_Animate_setAnimation(lua_State* tolua_S) + return 0; +} +int lua_ax_base_Director_getAxmolThreadId(lua_State* tolua_S) { int argc = 0; - ax::Animate* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28848,95 +28572,95 @@ int lua_ax_base_Animate_setAnimation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_setAnimation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_getAxmolThreadId'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Animation* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:setAnimation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_setAnimation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getAxmolThreadId'", nullptr); return 0; } - cobj->setAnimation(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getAxmolThreadId(); + std_thread_id_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:setAnimation",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:getAxmolThreadId",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_setAnimation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getAxmolThreadId'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animate_getAnimation(lua_State* tolua_S) +int lua_ax_base_Director_setChildrenIndexerEnabled(lua_State* tolua_S) { int argc = 0; - ax::Animate* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_getAnimation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_setChildrenIndexerEnabled'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const ax::Animation* ret = cobj->getAnimation(); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::Animation* ret = cobj->getAnimation(); - object_to_luaval(tolua_S, "ax.Animation",(ax::Animation*)ret); - return 1; + if (argc == 1) + { + bool arg0; + + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.Director:setChildrenIndexerEnabled"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_setChildrenIndexerEnabled'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:getAnimation",argc, 0); + cobj->setChildrenIndexerEnabled(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:setChildrenIndexerEnabled",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_getAnimation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_setChildrenIndexerEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animate_getCurrentFrameIndex(lua_State* tolua_S) +int lua_ax_base_Director_isChildrenIndexerEnabled(lua_State* tolua_S) { int argc = 0; - ax::Animate* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28945,45 +28669,45 @@ int lua_ax_base_Animate_getCurrentFrameIndex(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_getCurrentFrameIndex'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isChildrenIndexerEnabled'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_getCurrentFrameIndex'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isChildrenIndexerEnabled'", nullptr); return 0; } - auto&& ret = cobj->getCurrentFrameIndex(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->isChildrenIndexerEnabled(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:getCurrentFrameIndex",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isChildrenIndexerEnabled",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_getCurrentFrameIndex'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isChildrenIndexerEnabled'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animate_initWithAnimation(lua_State* tolua_S) +int lua_ax_base_Director_isValid(lua_State* tolua_S) { int argc = 0; - ax::Animate* cobj = nullptr; + ax::Director* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -28992,45 +28716,42 @@ int lua_ax_base_Animate_initWithAnimation(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Animate*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Director*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Animate_initWithAnimation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Director_isValid'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Animation* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:initWithAnimation"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_initWithAnimation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_isValid'", nullptr); return 0; } - auto&& ret = cobj->initWithAnimation(arg0); + auto&& ret = cobj->isValid(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:initWithAnimation",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Director:isValid",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_initWithAnimation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_isValid'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animate_create(lua_State* tolua_S) +int lua_ax_base_Director_getInstance(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -29040,98 +28761,158 @@ int lua_ax_base_Animate_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Animate",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 0) { - ax::Animation* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.Animation",&arg0, "ax.Animate:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_getInstance'", nullptr); return 0; } - auto&& ret = ax::Animate::create(arg0); - object_to_luaval(tolua_S, "ax.Animate",(ax::Animate*)ret); + auto&& ret = ax::Director::getInstance(); + object_to_luaval(tolua_S, "ax.Director",(ax::Director*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Animate:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Director:getInstance",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_getInstance'.",&tolua_err); #endif return 0; } -int lua_ax_base_Animate_constructor(lua_State* tolua_S) +int lua_ax_base_Director_destroyInstance(lua_State* tolua_S) { int argc = 0; - ax::Animate* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.Director",0,&tolua_err)) goto tolua_lerror; +#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Animate_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Director_destroyInstance'", nullptr); return 0; } - cobj = new ax::Animate(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Animate"); + ax::Director::destroyInstance(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Animate:Animate",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Director:destroyInstance",argc, 0); return 0; - #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Animate_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Director_destroyInstance'.",&tolua_err); #endif - return 0; } - -static int lua_ax_base_Animate_finalize(lua_State* tolua_S) +static int lua_ax_base_Director_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Animate)"); + AXLOGV("luabindings: finalizing LUA object (Director)"); return 0; } -int lua_register_ax_base_Animate(lua_State* tolua_S) +int lua_register_ax_base_Director(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Animate"); - tolua_cclass(tolua_S,"Animate","ax.Animate","ax.ActionInterval",nullptr); + tolua_usertype(tolua_S,"ax.Director"); + tolua_cclass(tolua_S,"Director","ax.Director","",nullptr); - tolua_beginmodule(tolua_S,"Animate"); - tolua_function(tolua_S,"new",lua_ax_base_Animate_constructor); - tolua_function(tolua_S,"setAnimation",lua_ax_base_Animate_setAnimation); - tolua_function(tolua_S,"getAnimation",lua_ax_base_Animate_getAnimation); - tolua_function(tolua_S,"getCurrentFrameIndex",lua_ax_base_Animate_getCurrentFrameIndex); - tolua_function(tolua_S,"initWithAnimation",lua_ax_base_Animate_initWithAnimation); - tolua_function(tolua_S,"create", lua_ax_base_Animate_create); + tolua_beginmodule(tolua_S,"Director"); + tolua_function(tolua_S,"init",lua_ax_base_Director_init); + tolua_function(tolua_S,"getRunningScene",lua_ax_base_Director_getRunningScene); + tolua_function(tolua_S,"getNextScene",lua_ax_base_Director_getNextScene); + tolua_function(tolua_S,"getAnimationInterval",lua_ax_base_Director_getAnimationInterval); + tolua_function(tolua_S,"setAnimationInterval",lua_ax_base_Director_setAnimationInterval); + tolua_function(tolua_S,"isStatsDisplay",lua_ax_base_Director_isStatsDisplay); + tolua_function(tolua_S,"setStatsDisplay",lua_ax_base_Director_setStatsDisplay); + tolua_function(tolua_S,"getSecondsPerFrame",lua_ax_base_Director_getSecondsPerFrame); + tolua_function(tolua_S,"setStatsAnchor",lua_ax_base_Director_setStatsAnchor); + tolua_function(tolua_S,"getRenderView",lua_ax_base_Director_getRenderView); + tolua_function(tolua_S,"setRenderView",lua_ax_base_Director_setRenderView); + tolua_function(tolua_S,"getTextureCache",lua_ax_base_Director_getTextureCache); + tolua_function(tolua_S,"isNextDeltaTimeZero",lua_ax_base_Director_isNextDeltaTimeZero); + tolua_function(tolua_S,"setNextDeltaTimeZero",lua_ax_base_Director_setNextDeltaTimeZero); + tolua_function(tolua_S,"isPaused",lua_ax_base_Director_isPaused); + tolua_function(tolua_S,"getTotalFrames",lua_ax_base_Director_getTotalFrames); + tolua_function(tolua_S,"setProjection",lua_ax_base_Director_setProjection); + tolua_function(tolua_S,"setViewport",lua_ax_base_Director_setViewport); + tolua_function(tolua_S,"isSendCleanupToScene",lua_ax_base_Director_isSendCleanupToScene); + tolua_function(tolua_S,"getNotificationNode",lua_ax_base_Director_getNotificationNode); + tolua_function(tolua_S,"setNotificationNode",lua_ax_base_Director_setNotificationNode); + tolua_function(tolua_S,"getWinSize",lua_ax_base_Director_getWinSize); + tolua_function(tolua_S,"getWinSizeInPixels",lua_ax_base_Director_getWinSizeInPixels); + tolua_function(tolua_S,"getVisibleSize",lua_ax_base_Director_getVisibleSize); + tolua_function(tolua_S,"getVisibleOrigin",lua_ax_base_Director_getVisibleOrigin); + tolua_function(tolua_S,"getSafeAreaRect",lua_ax_base_Director_getSafeAreaRect); + tolua_function(tolua_S,"convertToGL",lua_ax_base_Director_convertToGL); + tolua_function(tolua_S,"convertToUI",lua_ax_base_Director_convertToUI); + tolua_function(tolua_S,"getZEye",lua_ax_base_Director_getZEye); + tolua_function(tolua_S,"runWithScene",lua_ax_base_Director_runWithScene); + tolua_function(tolua_S,"pushScene",lua_ax_base_Director_pushScene); + tolua_function(tolua_S,"popScene",lua_ax_base_Director_popScene); + tolua_function(tolua_S,"popToRootScene",lua_ax_base_Director_popToRootScene); + tolua_function(tolua_S,"popToSceneStackLevel",lua_ax_base_Director_popToSceneStackLevel); + tolua_function(tolua_S,"replaceScene",lua_ax_base_Director_replaceScene); + tolua_function(tolua_S,"endToLua",lua_ax_base_Director_end); + tolua_function(tolua_S,"pause",lua_ax_base_Director_pause); + tolua_function(tolua_S,"resume",lua_ax_base_Director_resume); + tolua_function(tolua_S,"restart",lua_ax_base_Director_restart); + tolua_function(tolua_S,"stopAnimation",lua_ax_base_Director_stopAnimation); + tolua_function(tolua_S,"startAnimation",lua_ax_base_Director_startAnimation); + tolua_function(tolua_S,"drawScene",lua_ax_base_Director_drawScene); + tolua_function(tolua_S,"purgeCachedData",lua_ax_base_Director_purgeCachedData); + tolua_function(tolua_S,"setDefaultValues",lua_ax_base_Director_setDefaultValues); + tolua_function(tolua_S,"setGLDefaultValues",lua_ax_base_Director_setGLDefaultValues); + tolua_function(tolua_S,"setClearColor",lua_ax_base_Director_setClearColor); + tolua_function(tolua_S,"mainLoop",lua_ax_base_Director_mainLoop); + tolua_function(tolua_S,"setContentScaleFactor",lua_ax_base_Director_setContentScaleFactor); + tolua_function(tolua_S,"getContentScaleFactor",lua_ax_base_Director_getContentScaleFactor); + tolua_function(tolua_S,"getScheduler",lua_ax_base_Director_getScheduler); + tolua_function(tolua_S,"setScheduler",lua_ax_base_Director_setScheduler); + tolua_function(tolua_S,"getActionManager",lua_ax_base_Director_getActionManager); + tolua_function(tolua_S,"setActionManager",lua_ax_base_Director_setActionManager); + tolua_function(tolua_S,"getEventDispatcher",lua_ax_base_Director_getEventDispatcher); + tolua_function(tolua_S,"setEventDispatcher",lua_ax_base_Director_setEventDispatcher); + tolua_function(tolua_S,"getRenderer",lua_ax_base_Director_getRenderer); + tolua_function(tolua_S,"getDeltaTime",lua_ax_base_Director_getDeltaTime); + tolua_function(tolua_S,"getFrameRate",lua_ax_base_Director_getFrameRate); + tolua_function(tolua_S,"pushMatrix",lua_ax_base_Director_pushMatrix); + tolua_function(tolua_S,"popMatrix",lua_ax_base_Director_popMatrix); + tolua_function(tolua_S,"loadIdentityMatrix",lua_ax_base_Director_loadIdentityMatrix); + tolua_function(tolua_S,"loadMatrix",lua_ax_base_Director_loadMatrix); + tolua_function(tolua_S,"multiplyMatrix",lua_ax_base_Director_multiplyMatrix); + tolua_function(tolua_S,"getMatrix",lua_ax_base_Director_getMatrix); + tolua_function(tolua_S,"resetMatrixStack",lua_ax_base_Director_resetMatrixStack); + tolua_function(tolua_S,"getAxmolThreadId",lua_ax_base_Director_getAxmolThreadId); + tolua_function(tolua_S,"setChildrenIndexerEnabled",lua_ax_base_Director_setChildrenIndexerEnabled); + tolua_function(tolua_S,"isChildrenIndexerEnabled",lua_ax_base_Director_isChildrenIndexerEnabled); + tolua_function(tolua_S,"isValid",lua_ax_base_Director_isValid); + tolua_function(tolua_S,"getInstance", lua_ax_base_Director_getInstance); + tolua_function(tolua_S,"destroyInstance", lua_ax_base_Director_destroyInstance); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Animate).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Animate"; - g_typeCast[typeName] = "ax.Animate"; + auto typeName = typeid(ax::Director).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Director"; + g_typeCast[typeName] = "ax.Director"; return 1; } -int lua_ax_base_TargetedAction_setForcedTarget(lua_State* tolua_S) +int lua_ax_base_Properties_getNextProperty(lua_State* tolua_S) { int argc = 0; - ax::TargetedAction* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -29140,95 +28921,92 @@ int lua_ax_base_TargetedAction_setForcedTarget(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_setForcedTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNextProperty'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Node* arg0; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:setForcedTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_setForcedTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getNextProperty'", nullptr); return 0; } - cobj->setForcedTarget(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getNextProperty(); + tolua_pushstring(tolua_S,(const char*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:setForcedTarget",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNextProperty",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_setForcedTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNextProperty'.",&tolua_err); #endif return 0; } -int lua_ax_base_TargetedAction_getForcedTarget(lua_State* tolua_S) +int lua_ax_base_Properties_getNextNamespace(lua_State* tolua_S) { int argc = 0; - ax::TargetedAction* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_getForcedTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNextNamespace'", nullptr); return 0; } #endif + argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const ax::Node* ret = cobj->getForcedTarget(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 0) { - ax::Node* ret = cobj->getForcedTarget(); - object_to_luaval(tolua_S, "ax.Node",(ax::Node*)ret); - return 1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getNextNamespace'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:getForcedTarget",argc, 0); + auto&& ret = cobj->getNextNamespace(); + object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNextNamespace",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_getForcedTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNextNamespace'.",&tolua_err); #endif return 0; } -int lua_ax_base_TargetedAction_initWithTarget(lua_State* tolua_S) +int lua_ax_base_Properties_rewind(lua_State* tolua_S) { int argc = 0; - ax::TargetedAction* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -29237,89 +29015,132 @@ int lua_ax_base_TargetedAction_initWithTarget(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::TargetedAction*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_TargetedAction_initWithTarget'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_rewind'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - ax::Node* arg0; - ax::FiniteTimeAction* arg1; - - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:initWithTarget"); - - ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.TargetedAction:initWithTarget"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_initWithTarget'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_rewind'", nullptr); return 0; } - auto&& ret = cobj->initWithTarget(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->rewind(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:initWithTarget",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:rewind",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_initWithTarget'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_rewind'.",&tolua_err); #endif return 0; } -int lua_ax_base_TargetedAction_create(lua_State* tolua_S) +int lua_ax_base_Properties_getNamespace(lua_State* tolua_S) { int argc = 0; + ax::Properties* cobj = nullptr; bool ok = true; - #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.TargetedAction",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNamespace'", nullptr); + return 0; + } #endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 0) { + const char* ret = cobj->getNamespace(); + tolua_pushstring(tolua_S,(const char*)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); - argc = lua_gettop(tolua_S) - 1; + if (!ok) { break; } + ax::Properties* ret = cobj->getNamespace(arg0); + object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 2) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); - if (argc == 2) - { - ax::Node* arg0; - ax::FiniteTimeAction* arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.Node",&arg0, "ax.TargetedAction:create"); - ok &= luaval_to_object(tolua_S, 3, "ax.FiniteTimeAction",&arg1, "ax.TargetedAction:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_create'", nullptr); - return 0; + if (!ok) { break; } + bool arg1; + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getNamespace"); + + if (!ok) { break; } + ax::Properties* ret = cobj->getNamespace(arg0, arg1); + object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); + return 1; } - auto&& ret = ax::TargetedAction::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.TargetedAction",(ax::TargetedAction*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.TargetedAction:create",argc, 2); + }while(0); + ok = true; + do{ + if (argc == 3) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); + + if (!ok) { break; } + bool arg1; + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getNamespace"); + + if (!ok) { break; } + bool arg2; + ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.Properties:getNamespace"); + + if (!ok) { break; } + ax::Properties* ret = cobj->getNamespace(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNamespace",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNamespace'.",&tolua_err); #endif + return 0; } -int lua_ax_base_TargetedAction_constructor(lua_State* tolua_S) +int lua_ax_base_Properties_getId(lua_State* tolua_S) { int argc = 0; - ax::TargetedAction* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -29327,60 +29148,46 @@ int lua_ax_base_TargetedAction_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getId'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_TargetedAction_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getId'", nullptr); return 0; } - cobj = new ax::TargetedAction(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TargetedAction"); + auto&& ret = cobj->getId(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TargetedAction:TargetedAction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getId",argc, 0); return 0; #if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_TargetedAction_constructor'.",&tolua_err); + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getId'.",&tolua_err); #endif - return 0; -} - -static int lua_ax_base_TargetedAction_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (TargetedAction)"); - return 0; -} - -int lua_register_ax_base_TargetedAction(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.TargetedAction"); - tolua_cclass(tolua_S,"TargetedAction","ax.TargetedAction","ax.ActionInterval",nullptr); - - tolua_beginmodule(tolua_S,"TargetedAction"); - tolua_function(tolua_S,"new",lua_ax_base_TargetedAction_constructor); - tolua_function(tolua_S,"setForcedTarget",lua_ax_base_TargetedAction_setForcedTarget); - tolua_function(tolua_S,"getForcedTarget",lua_ax_base_TargetedAction_getForcedTarget); - tolua_function(tolua_S,"initWithTarget",lua_ax_base_TargetedAction_initWithTarget); - tolua_function(tolua_S,"create", lua_ax_base_TargetedAction_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::TargetedAction).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.TargetedAction"; - g_typeCast[typeName] = "ax.TargetedAction"; - return 1; -} - -int lua_ax_base_ActionFloat_initWithDuration(lua_State* tolua_S) + return 0; +} +int lua_ax_base_Properties_exists(lua_State* tolua_S) { int argc = 0; - ax::ActionFloat* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -29389,107 +29196,109 @@ int lua_ax_base_ActionFloat_initWithDuration(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.ActionFloat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::ActionFloat*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ActionFloat_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_exists'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 1) { - double arg0; - double arg1; - double arg2; - std::function arg3; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionFloat:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ActionFloat:initWithDuration"); - - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ActionFloat:initWithDuration"); + const char* arg0; - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:exists"); arg0 = arg0_tmp.c_str(); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_initWithDuration'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_exists'", nullptr); return 0; } - auto&& ret = cobj->initWithDuration(arg0, arg1, arg2, arg3); + auto&& ret = cobj->exists(arg0); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionFloat:initWithDuration",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:exists",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_initWithDuration'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_exists'.",&tolua_err); #endif return 0; } -int lua_ax_base_ActionFloat_create(lua_State* tolua_S) +int lua_ax_base_Properties_getType(lua_State* tolua_S) { int argc = 0; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.ActionFloat",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); - if (argc == 4) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getType'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - double arg0; - double arg1; - double arg2; - std::function arg3; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.ActionFloat:create"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ActionFloat:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ActionFloat:create"); - do { - // Lambda binding for lua is not supported. - assert(false); - } while(0) - ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getType'", nullptr); return 0; } - auto&& ret = ax::ActionFloat::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.ActionFloat",(ax::ActionFloat*)ret); + int ret = (int)cobj->getType(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.ActionFloat:create",argc, 4); + if (argc == 1) + { + const char* arg0; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getType"); arg0 = arg0_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getType'", nullptr); + return 0; + } + int ret = (int)cobj->getType(arg0); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getType",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getType'.",&tolua_err); #endif + return 0; } -int lua_ax_base_ActionFloat_constructor(lua_State* tolua_S) +int lua_ax_base_Properties_getString(lua_State* tolua_S) { int argc = 0; - ax::ActionFloat* cobj = nullptr; + ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -29497,55 +29306,74 @@ int lua_ax_base_ActionFloat_constructor(lua_State* tolua_S) #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getString'", nullptr); + return 0; + } +#endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ActionFloat_constructor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); return 0; } - cobj = new ax::ActionFloat(); - cobj->autorelease(); - int ID = (int)cobj->_ID ; - int* luaID = &cobj->_luaID ; - toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.ActionFloat"); + auto&& ret = cobj->getString(); + tolua_pushstring(tolua_S,(const char*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ActionFloat:ActionFloat",argc, 0); - return 0; + if (argc == 1) + { + const char* arg0; -#if _AX_DEBUG >= 1 - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ActionFloat_constructor'.",&tolua_err); -#endif + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getString"); arg0 = arg0_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); + return 0; + } + auto&& ret = cobj->getString(arg0); + tolua_pushstring(tolua_S,(const char*)ret); + return 1; + } + if (argc == 2) + { + const char* arg0; + const char* arg1; - return 0; -} + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getString"); arg0 = arg0_tmp.c_str(); -static int lua_ax_base_ActionFloat_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (ActionFloat)"); + std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:getString"); arg1 = arg1_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); + return 0; + } + auto&& ret = cobj->getString(arg0, arg1); + tolua_pushstring(tolua_S,(const char*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getString",argc, 0); return 0; -} -int lua_register_ax_base_ActionFloat(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.ActionFloat"); - tolua_cclass(tolua_S,"ActionFloat","ax.ActionFloat","ax.ActionInterval",nullptr); +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getString'.",&tolua_err); +#endif - tolua_beginmodule(tolua_S,"ActionFloat"); - tolua_function(tolua_S,"new",lua_ax_base_ActionFloat_constructor); - tolua_function(tolua_S,"initWithDuration",lua_ax_base_ActionFloat_initWithDuration); - tolua_function(tolua_S,"create", lua_ax_base_ActionFloat_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::ActionFloat).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.ActionFloat"; - g_typeCast[typeName] = "ax.ActionFloat"; - return 1; + return 0; } - -int lua_ax_base_Properties_getNextProperty(lua_State* tolua_S) +int lua_ax_base_Properties_setString(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29565,34 +29393,40 @@ int lua_ax_base_Properties_getNextProperty(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNextProperty'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_setString'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + const char* arg0; + const char* arg1; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:setString"); arg0 = arg0_tmp.c_str(); + + std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:setString"); arg1 = arg1_tmp.c_str(); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getNextProperty'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_setString'", nullptr); return 0; } - auto&& ret = cobj->getNextProperty(); - tolua_pushstring(tolua_S,(const char*)ret); + auto&& ret = cobj->setString(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNextProperty",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:setString",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNextProperty'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_setString'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getNextNamespace(lua_State* tolua_S) +int lua_ax_base_Properties_getBool(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29612,34 +29446,65 @@ int lua_ax_base_Properties_getNextNamespace(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNextNamespace'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getBool'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getNextNamespace'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); return 0; } - auto&& ret = cobj->getNextNamespace(); - object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); + auto&& ret = cobj->getBool(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNextNamespace",argc, 0); + if (argc == 1) + { + const char* arg0; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getBool"); arg0 = arg0_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); + return 0; + } + auto&& ret = cobj->getBool(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + if (argc == 2) + { + const char* arg0; + bool arg1; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getBool"); arg0 = arg0_tmp.c_str(); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getBool"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); + return 0; + } + auto&& ret = cobj->getBool(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getBool",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNextNamespace'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getBool'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_rewind(lua_State* tolua_S) +int lua_ax_base_Properties_getInt(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29659,121 +29524,109 @@ int lua_ax_base_Properties_rewind(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_rewind'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getInt'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_rewind'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getInt'", nullptr); return 0; } - cobj->rewind(); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getInt(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:rewind",argc, 0); + if (argc == 1) + { + const char* arg0; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getInt"); arg0 = arg0_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getInt'", nullptr); + return 0; + } + auto&& ret = cobj->getInt(arg0); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getInt",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_rewind'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getInt'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getNamespace(lua_State* tolua_S) +int lua_ax_base_Properties_getFloat(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getNamespace'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getFloat'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 0) { - const char* ret = cobj->getNamespace(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); - - if (!ok) { break; } - ax::Properties* ret = cobj->getNamespace(arg0); - object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); - - if (!ok) { break; } - bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getNamespace"); - if (!ok) { break; } - ax::Properties* ret = cobj->getNamespace(arg0, arg1); - object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getFloat'", nullptr); + return 0; } - }while(0); - ok = true; - do{ - if (argc == 3) { - std::string_view arg0; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Properties:getNamespace"); - - if (!ok) { break; } - bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getNamespace"); - - if (!ok) { break; } - bool arg2; - ok &= luaval_to_boolean(tolua_S, 4,&arg2, "ax.Properties:getNamespace"); + auto&& ret = cobj->getFloat(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + if (argc == 1) + { + const char* arg0; - if (!ok) { break; } - ax::Properties* ret = cobj->getNamespace(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.Properties",(ax::Properties*)ret); - return 1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getFloat"); arg0 = arg0_tmp.c_str(); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getFloat'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getNamespace",argc, 1); + auto&& ret = cobj->getFloat(arg0); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getFloat",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getNamespace'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getFloat'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getId(lua_State* tolua_S) +int lua_ax_base_Properties_getMat4(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29793,34 +29646,40 @@ int lua_ax_base_Properties_getId(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getId'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getMat4'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + const char* arg0; + ax::Mat4* arg1; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getMat4"); arg0 = arg0_tmp.c_str(); + + ok &= luaval_to_object(tolua_S, 3, "ax.Mat4",&arg1, "ax.Properties:getMat4"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getId'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getMat4'", nullptr); return 0; } - auto&& ret = cobj->getId(); - lua_pushlstring(tolua_S,ret.data(),ret.length()); + auto&& ret = cobj->getMat4(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getId",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getMat4",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getId'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getMat4'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_exists(lua_State* tolua_S) +int lua_ax_base_Properties_getVec2(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29840,37 +29699,40 @@ int lua_ax_base_Properties_exists(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_exists'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec2'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 2) { const char* arg0; + ax::Vec2* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:exists"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec2"); arg0 = arg0_tmp.c_str(); + + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.Properties:getVec2"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_exists'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec2'", nullptr); return 0; } - auto&& ret = cobj->exists(arg0); + auto&& ret = cobj->getVec2(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:exists",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec2",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_exists'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec2'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getType(lua_State* tolua_S) +int lua_ax_base_Properties_getVec3(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29890,48 +29752,40 @@ int lua_ax_base_Properties_getType(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getType'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec3'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getType'", nullptr); - return 0; - } - int ret = (int)cobj->getType(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - if (argc == 1) + if (argc == 2) { const char* arg0; + ax::Vec3* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getType"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec3"); arg0 = arg0_tmp.c_str(); + + ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:getVec3"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getType'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec3'", nullptr); return 0; } - int ret = (int)cobj->getType(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getVec3(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getType",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec3",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getType'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec3'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getString(lua_State* tolua_S) +int lua_ax_base_Properties_getVec4(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -29951,65 +29805,93 @@ int lua_ax_base_Properties_getString(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getString'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec4'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); - return 0; - } - auto&& ret = cobj->getString(); - tolua_pushstring(tolua_S,(const char*)ret); - return 1; - } - if (argc == 1) + if (argc == 2) { const char* arg0; + ax::Vec4* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getString"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec4"); arg0 = arg0_tmp.c_str(); + + ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:getVec4"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec4'", nullptr); return 0; } - auto&& ret = cobj->getString(arg0); - tolua_pushstring(tolua_S,(const char*)ret); + auto&& ret = cobj->getVec4(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 2) + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec4",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec4'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Properties_getQuaternionFromAxisAngle(lua_State* tolua_S) +{ + int argc = 0; + ax::Properties* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) { const char* arg0; - const char* arg1; + ax::Quaternion* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getString"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getQuaternionFromAxisAngle"); arg0 = arg0_tmp.c_str(); - std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:getString"); arg1 = arg1_tmp.c_str(); + ok &= luaval_to_object(tolua_S, 3, "ax.Quaternion",&arg1, "ax.Properties:getQuaternionFromAxisAngle"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getString'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'", nullptr); return 0; } - auto&& ret = cobj->getString(arg0, arg1); - tolua_pushstring(tolua_S,(const char*)ret); + auto&& ret = cobj->getQuaternionFromAxisAngle(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getString",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getQuaternionFromAxisAngle",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getString'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_setString(lua_State* tolua_S) +int lua_ax_base_Properties_getColor(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -30029,40 +29911,41 @@ int lua_ax_base_Properties_setString(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_setString'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; - const char* arg1; + ax::Color* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:setString"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getColor"); arg0 = arg0_tmp.c_str(); - std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:setString"); arg1 = arg1_tmp.c_str(); + #pragma warning NO CONVERSION TO NATIVE FOR Color* + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_setString'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getColor'", nullptr); return 0; } - auto&& ret = cobj->setString(arg0, arg1); + auto&& ret = cobj->getColor(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:setString",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getColor",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_setString'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getColor'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getBool(lua_State* tolua_S) +int lua_ax_base_Properties_getPath(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -30082,65 +29965,41 @@ int lua_ax_base_Properties_getBool(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getBool'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getPath'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); - return 0; - } - auto&& ret = cobj->getBool(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 1) - { - const char* arg0; - - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getBool"); arg0 = arg0_tmp.c_str(); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); - return 0; - } - auto&& ret = cobj->getBool(arg0); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - if (argc == 2) + if (argc == 2) { const char* arg0; - bool arg1; + std::string* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getBool"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getPath"); arg0 = arg0_tmp.c_str(); - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.Properties:getBool"); + #pragma warning NO CONVERSION TO NATIVE FOR basic_string* + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getBool'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getPath'", nullptr); return 0; } - auto&& ret = cobj->getBool(arg0, arg1); + auto&& ret = cobj->getPath(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getBool",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getPath",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getBool'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getPath'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getInt(lua_State* tolua_S) +int lua_ax_base_Properties_getVariable(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -30160,48 +30019,54 @@ int lua_ax_base_Properties_getInt(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getInt'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVariable'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + const char* arg0; + + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVariable"); arg0 = arg0_tmp.c_str(); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getInt'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVariable'", nullptr); return 0; } - auto&& ret = cobj->getInt(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getVariable(arg0); + tolua_pushstring(tolua_S,(const char*)ret); return 1; } - if (argc == 1) + if (argc == 2) { const char* arg0; + const char* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getInt"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVariable"); arg0 = arg0_tmp.c_str(); + + std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:getVariable"); arg1 = arg1_tmp.c_str(); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getInt'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVariable'", nullptr); return 0; } - auto&& ret = cobj->getInt(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getVariable(arg0, arg1); + tolua_pushstring(tolua_S,(const char*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getInt",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVariable",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getInt'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVariable'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getFloat(lua_State* tolua_S) +int lua_ax_base_Properties_setVariable(lua_State* tolua_S) { int argc = 0; ax::Properties* cobj = nullptr; @@ -30221,210 +30086,279 @@ int lua_ax_base_Properties_getFloat(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getFloat'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_setVariable'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getFloat'", nullptr); - return 0; - } - auto&& ret = cobj->getFloat(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - if (argc == 1) + if (argc == 2) { const char* arg0; + const char* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getFloat"); arg0 = arg0_tmp.c_str(); + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:setVariable"); arg0 = arg0_tmp.c_str(); + + std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:setVariable"); arg1 = arg1_tmp.c_str(); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getFloat'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_setVariable'", nullptr); return 0; } - auto&& ret = cobj->getFloat(arg0); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setVariable(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getFloat",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:setVariable",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getFloat'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_setVariable'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getMat4(lua_State* tolua_S) +int lua_ax_base_Properties_parseVec2(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getMat4'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; - ax::Mat4* arg1; - - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getMat4"); arg0 = arg0_tmp.c_str(); - - ok &= luaval_to_object(tolua_S, 3, "ax.Mat4",&arg1, "ax.Properties:getMat4"); + ax::Vec2* arg1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec2"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.Properties:parseVec2"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getMat4'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec2'", nullptr); return 0; } - auto&& ret = cobj->getMat4(arg0, arg1); + auto&& ret = ax::Properties::parseVec2(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getMat4",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec2",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getMat4'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec2'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Properties_getVec2(lua_State* tolua_S) +int lua_ax_base_Properties_parseVec3(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 2) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec2'", nullptr); - return 0; + const char* arg0; + ax::Vec3* arg1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec3"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:parseVec3"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec3'", nullptr); + return 0; + } + auto&& ret = ax::Properties::parseVec3(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec3",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec3'.",&tolua_err); #endif + return 0; +} +int lua_ax_base_Properties_parseVec4(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - const char* arg0; - ax::Vec2* arg1; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec2"); arg0 = arg0_tmp.c_str(); +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif - ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.Properties:getVec2"); + argc = lua_gettop(tolua_S) - 1; + + if (argc == 2) + { + const char* arg0; + ax::Vec4* arg1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec4"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:parseVec4"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec2'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec4'", nullptr); return 0; } - auto&& ret = cobj->getVec2(arg0, arg1); + auto&& ret = ax::Properties::parseVec4(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec2",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec4",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec2'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec4'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Properties_getVec3(lua_State* tolua_S) +int lua_ax_base_Properties_parseAxisAngle(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 2) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec3'", nullptr); - return 0; + const char* arg0; + ax::Quaternion* arg1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseAxisAngle"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_object(tolua_S, 3, "ax.Quaternion",&arg1, "ax.Properties:parseAxisAngle"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseAxisAngle'", nullptr); + return 0; + } + auto&& ret = ax::Properties::parseAxisAngle(arg0, arg1); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseAxisAngle",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseAxisAngle'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_Properties_parseColor(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif - argc = lua_gettop(tolua_S)-1; - if (argc == 2) - { - const char* arg0; - ax::Vec3* arg1; +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; +#endif - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec3"); arg0 = arg0_tmp.c_str(); + argc = lua_gettop(tolua_S) - 1; - ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:getVec3"); + if (argc == 2) + { + const char* arg0; + ax::Color* arg1; + std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseColor"); arg0 = arg0_tmp.c_str(); + #pragma warning NO CONVERSION TO NATIVE FOR Color* + ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec3'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseColor'", nullptr); return 0; } - auto&& ret = cobj->getVec3(arg0, arg1); + auto&& ret = ax::Properties::parseColor(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec3",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseColor",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec3'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseColor'.",&tolua_err); #endif - return 0; } -int lua_ax_base_Properties_getVec4(lua_State* tolua_S) +static int lua_ax_base_Properties_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Properties)"); + return 0; +} + +int lua_register_ax_base_Properties(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Properties"); + tolua_cclass(tolua_S,"Properties","ax.Properties","",nullptr); + + tolua_beginmodule(tolua_S,"Properties"); + tolua_function(tolua_S,"getNextProperty",lua_ax_base_Properties_getNextProperty); + tolua_function(tolua_S,"getNextNamespace",lua_ax_base_Properties_getNextNamespace); + tolua_function(tolua_S,"rewind",lua_ax_base_Properties_rewind); + tolua_function(tolua_S,"getNamespace",lua_ax_base_Properties_getNamespace); + tolua_function(tolua_S,"getId",lua_ax_base_Properties_getId); + tolua_function(tolua_S,"exists",lua_ax_base_Properties_exists); + tolua_function(tolua_S,"getType",lua_ax_base_Properties_getType); + tolua_function(tolua_S,"getString",lua_ax_base_Properties_getString); + tolua_function(tolua_S,"setString",lua_ax_base_Properties_setString); + tolua_function(tolua_S,"getBool",lua_ax_base_Properties_getBool); + tolua_function(tolua_S,"getInt",lua_ax_base_Properties_getInt); + tolua_function(tolua_S,"getFloat",lua_ax_base_Properties_getFloat); + tolua_function(tolua_S,"getMat4",lua_ax_base_Properties_getMat4); + tolua_function(tolua_S,"getVec2",lua_ax_base_Properties_getVec2); + tolua_function(tolua_S,"getVec3",lua_ax_base_Properties_getVec3); + tolua_function(tolua_S,"getVec4",lua_ax_base_Properties_getVec4); + tolua_function(tolua_S,"getQuaternionFromAxisAngle",lua_ax_base_Properties_getQuaternionFromAxisAngle); + tolua_function(tolua_S,"getColor",lua_ax_base_Properties_getColor); + tolua_function(tolua_S,"getPath",lua_ax_base_Properties_getPath); + tolua_function(tolua_S,"getVariable",lua_ax_base_Properties_getVariable); + tolua_function(tolua_S,"setVariable",lua_ax_base_Properties_setVariable); + tolua_function(tolua_S,"parseVec2", lua_ax_base_Properties_parseVec2); + tolua_function(tolua_S,"parseVec3", lua_ax_base_Properties_parseVec3); + tolua_function(tolua_S,"parseVec4", lua_ax_base_Properties_parseVec4); + tolua_function(tolua_S,"parseAxisAngle", lua_ax_base_Properties_parseAxisAngle); + tolua_function(tolua_S,"parseColor", lua_ax_base_Properties_parseColor); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Properties).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Properties"; + g_typeCast[typeName] = "ax.Properties"; + return 1; +} + +int lua_ax_base_Timer_setupTimerWithInterval(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -30433,51 +30367,54 @@ int lua_ax_base_Properties_getVec4(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVec4'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_setupTimerWithInterval'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 3) { - const char* arg0; - ax::Vec4* arg1; + double arg0; + unsigned int arg1; + double arg2; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVec4"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:setupTimerWithInterval"); - ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:getVec4"); + ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Timer:setupTimerWithInterval"); + + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Timer:setupTimerWithInterval"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVec4'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_setupTimerWithInterval'", nullptr); return 0; } - auto&& ret = cobj->getVec4(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setupTimerWithInterval(arg0, arg1, arg2); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVec4",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:setupTimerWithInterval",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVec4'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_setupTimerWithInterval'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getQuaternionFromAxisAngle(lua_State* tolua_S) +int lua_ax_base_Timer_setAborted(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -30486,114 +30423,92 @@ int lua_ax_base_Properties_getQuaternionFromAxisAngle(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_setAborted'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - const char* arg0; - ax::Quaternion* arg1; - - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getQuaternionFromAxisAngle"); arg0 = arg0_tmp.c_str(); - - ok &= luaval_to_object(tolua_S, 3, "ax.Quaternion",&arg1, "ax.Properties:getQuaternionFromAxisAngle"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_setAborted'", nullptr); return 0; } - auto&& ret = cobj->getQuaternionFromAxisAngle(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setAborted(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getQuaternionFromAxisAngle",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:setAborted",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getQuaternionFromAxisAngle'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_setAborted'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getColor(lua_State* tolua_S) +int lua_ax_base_Timer_isAborted(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getColor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_isAborted'", nullptr); return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 2) { - const char* arg0; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getColor"); arg0 = arg0_tmp.c_str(); - - if (!ok) { break; } - ax::Vec4* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:getColor"); - - if (!ok) { break; } - bool ret = cobj->getColor(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 2) { - const char* arg0; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getColor"); arg0 = arg0_tmp.c_str(); - - if (!ok) { break; } - ax::Vec3* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:getColor"); - if (!ok) { break; } - bool ret = cobj->getColor(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_isAborted'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getColor",argc, 2); + auto&& ret = cobj->isAborted(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:isAborted",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_isAborted'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getPath(lua_State* tolua_S) +int lua_ax_base_Timer_isExhausted(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -30602,52 +30517,45 @@ int lua_ax_base_Properties_getPath(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getPath'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_isExhausted'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 0) { - const char* arg0; - std::string* arg1; - - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getPath"); arg0 = arg0_tmp.c_str(); - - #pragma warning NO CONVERSION TO NATIVE FOR basic_string* - ok = false; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getPath'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_isExhausted'", nullptr); return 0; } - auto&& ret = cobj->getPath(arg0, arg1); + auto&& ret = cobj->isExhausted(); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getPath",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:isExhausted",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getPath'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_isExhausted'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_getVariable(lua_State* tolua_S) +int lua_ax_base_Timer_trigger(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -30656,65 +30564,95 @@ int lua_ax_base_Properties_getVariable(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_getVariable'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_trigger'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - const char* arg0; + double arg0; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVariable"); arg0 = arg0_tmp.c_str(); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:trigger"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVariable'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_trigger'", nullptr); return 0; } - auto&& ret = cobj->getVariable(arg0); - tolua_pushstring(tolua_S,(const char*)ret); + cobj->trigger(arg0); + lua_settop(tolua_S, 1); return 1; } - if (argc == 2) - { - const char* arg0; - const char* arg1; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:trigger",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_trigger'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_Timer_cancel(lua_State* tolua_S) +{ + int argc = 0; + ax::Timer* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:getVariable"); arg0 = arg0_tmp.c_str(); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_cancel'", nullptr); + return 0; + } +#endif - std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:getVariable"); arg1 = arg1_tmp.c_str(); + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_getVariable'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_cancel'", nullptr); return 0; } - auto&& ret = cobj->getVariable(arg0, arg1); - tolua_pushstring(tolua_S,(const char*)ret); + cobj->cancel(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:getVariable",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:cancel",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_getVariable'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_cancel'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_setVariable(lua_State* tolua_S) +int lua_ax_base_Timer_update(lua_State* tolua_S) { int argc = 0; - ax::Properties* cobj = nullptr; + ax::Timer* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -30723,295 +30661,326 @@ int lua_ax_base_Properties_setVariable(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Timer",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::Properties*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::Timer*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Properties_setVariable'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Timer_update'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 1) { - const char* arg0; - const char* arg1; - - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:setVariable"); arg0 = arg0_tmp.c_str(); + double arg0; - std::string arg1_tmp; ok &= luaval_to_std_string(tolua_S, 3, &arg1_tmp, "ax.Properties:setVariable"); arg1 = arg1_tmp.c_str(); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Timer:update"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_setVariable'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Timer_update'", nullptr); return 0; } - cobj->setVariable(arg0, arg1); + cobj->update(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Properties:setVariable",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Timer:update",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_setVariable'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Timer_update'.",&tolua_err); #endif return 0; } -int lua_ax_base_Properties_parseVec2(lua_State* tolua_S) +static int lua_ax_base_Timer_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Timer)"); + return 0; +} + +int lua_register_ax_base_Timer(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.Timer"); + tolua_cclass(tolua_S,"Timer","ax.Timer","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Timer"); + tolua_function(tolua_S,"setupTimerWithInterval",lua_ax_base_Timer_setupTimerWithInterval); + tolua_function(tolua_S,"setAborted",lua_ax_base_Timer_setAborted); + tolua_function(tolua_S,"isAborted",lua_ax_base_Timer_isAborted); + tolua_function(tolua_S,"isExhausted",lua_ax_base_Timer_isExhausted); + tolua_function(tolua_S,"trigger",lua_ax_base_Timer_trigger); + tolua_function(tolua_S,"cancel",lua_ax_base_Timer_cancel); + tolua_function(tolua_S,"update",lua_ax_base_Timer_update); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::Timer).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Timer"; + g_typeCast[typeName] = "ax.Timer"; + return 1; +} + +int lua_ax_base_Scheduler_getTimeScale(lua_State* tolua_S) { int argc = 0; + ax::Scheduler* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_getTimeScale'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - const char* arg0; - ax::Vec2* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec2"); arg0 = arg0_tmp.c_str(); - ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.Properties:parseVec2"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec2'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_getTimeScale'", nullptr); return 0; } - auto&& ret = ax::Properties::parseVec2(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getTimeScale(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec2",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:getTimeScale",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec2'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_getTimeScale'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Properties_parseVec3(lua_State* tolua_S) +int lua_ax_base_Scheduler_setTimeScale(lua_State* tolua_S) { int argc = 0; + ax::Scheduler* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) { - const char* arg0; - ax::Vec3* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec3"); arg0 = arg0_tmp.c_str(); - ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:parseVec3"); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_setTimeScale'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.Scheduler:setTimeScale"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec3'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_setTimeScale'", nullptr); return 0; } - auto&& ret = ax::Properties::parseVec3(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setTimeScale(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec3",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:setTimeScale",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec3'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_setTimeScale'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Properties_parseVec4(lua_State* tolua_S) +int lua_ax_base_Scheduler_runOnAxmolThread(lua_State* tolua_S) { int argc = 0; + ax::Scheduler* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) { - const char* arg0; - ax::Vec4* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseVec4"); arg0 = arg0_tmp.c_str(); - ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:parseVec4"); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_runOnAxmolThread'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + std::function arg0; + + do { + // Lambda binding for lua is not supported. + assert(false); + } while(0) + ; if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseVec4'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_runOnAxmolThread'", nullptr); return 0; } - auto&& ret = ax::Properties::parseVec4(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->runOnAxmolThread(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseVec4",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:runOnAxmolThread",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseVec4'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_runOnAxmolThread'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Properties_parseAxisAngle(lua_State* tolua_S) +int lua_ax_base_Scheduler_removeAllPendingActions(lua_State* tolua_S) { int argc = 0; + ax::Scheduler* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.Scheduler",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::Scheduler*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Scheduler_removeAllPendingActions'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - const char* arg0; - ax::Quaternion* arg1; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseAxisAngle"); arg0 = arg0_tmp.c_str(); - ok &= luaval_to_object(tolua_S, 3, "ax.Quaternion",&arg1, "ax.Properties:parseAxisAngle"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Properties_parseAxisAngle'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_removeAllPendingActions'", nullptr); return 0; } - auto&& ret = ax::Properties::parseAxisAngle(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->removeAllPendingActions(); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.Properties:parseAxisAngle",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:removeAllPendingActions",argc, 0); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseAxisAngle'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_removeAllPendingActions'.",&tolua_err); #endif + return 0; } -int lua_ax_base_Properties_parseColor(lua_State* tolua_S) +int lua_ax_base_Scheduler_constructor(lua_State* tolua_S) { int argc = 0; + ax::Scheduler* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.Properties",0,&tolua_err)) goto tolua_lerror; -#endif - argc = lua_gettop(tolua_S)-1; - do - { - if (argc == 2) - { - const char* arg0; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseColor"); arg0 = arg0_tmp.c_str(); - if (!ok) { break; } - ax::Vec4* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.Vec4",&arg1, "ax.Properties:parseColor"); - if (!ok) { break; } - bool ret = ax::Properties::parseColor(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - } while (0); - ok = true; - do + argc = lua_gettop(tolua_S)-1; + if (argc == 0) { - if (argc == 2) + if(!ok) { - const char* arg0; - std::string arg0_tmp; ok &= luaval_to_std_string(tolua_S, 2, &arg0_tmp, "ax.Properties:parseColor"); arg0 = arg0_tmp.c_str(); - if (!ok) { break; } - ax::Vec3* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.Vec3",&arg1, "ax.Properties:parseColor"); - if (!ok) { break; } - bool ret = ax::Properties::parseColor(arg0, arg1); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Scheduler_constructor'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.Properties:parseColor",argc, 2); + cobj = new ax::Scheduler(); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.Scheduler"); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Scheduler:Scheduler",argc, 0); return 0; + #if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Properties_parseColor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Scheduler_constructor'.",&tolua_err); #endif + return 0; } -static int lua_ax_base_Properties_finalize(lua_State* tolua_S) + +static int lua_ax_base_Scheduler_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (Properties)"); + AXLOGV("luabindings: finalizing LUA object (Scheduler)"); return 0; } -int lua_register_ax_base_Properties(lua_State* tolua_S) +int lua_register_ax_base_Scheduler(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.Properties"); - tolua_cclass(tolua_S,"Properties","ax.Properties","",nullptr); + tolua_usertype(tolua_S,"ax.Scheduler"); + tolua_cclass(tolua_S,"Scheduler","ax.Scheduler","ax.Object",nullptr); - tolua_beginmodule(tolua_S,"Properties"); - tolua_function(tolua_S,"getNextProperty",lua_ax_base_Properties_getNextProperty); - tolua_function(tolua_S,"getNextNamespace",lua_ax_base_Properties_getNextNamespace); - tolua_function(tolua_S,"rewind",lua_ax_base_Properties_rewind); - tolua_function(tolua_S,"getNamespace",lua_ax_base_Properties_getNamespace); - tolua_function(tolua_S,"getId",lua_ax_base_Properties_getId); - tolua_function(tolua_S,"exists",lua_ax_base_Properties_exists); - tolua_function(tolua_S,"getType",lua_ax_base_Properties_getType); - tolua_function(tolua_S,"getString",lua_ax_base_Properties_getString); - tolua_function(tolua_S,"setString",lua_ax_base_Properties_setString); - tolua_function(tolua_S,"getBool",lua_ax_base_Properties_getBool); - tolua_function(tolua_S,"getInt",lua_ax_base_Properties_getInt); - tolua_function(tolua_S,"getFloat",lua_ax_base_Properties_getFloat); - tolua_function(tolua_S,"getMat4",lua_ax_base_Properties_getMat4); - tolua_function(tolua_S,"getVec2",lua_ax_base_Properties_getVec2); - tolua_function(tolua_S,"getVec3",lua_ax_base_Properties_getVec3); - tolua_function(tolua_S,"getVec4",lua_ax_base_Properties_getVec4); - tolua_function(tolua_S,"getQuaternionFromAxisAngle",lua_ax_base_Properties_getQuaternionFromAxisAngle); - tolua_function(tolua_S,"getColor",lua_ax_base_Properties_getColor); - tolua_function(tolua_S,"getPath",lua_ax_base_Properties_getPath); - tolua_function(tolua_S,"getVariable",lua_ax_base_Properties_getVariable); - tolua_function(tolua_S,"setVariable",lua_ax_base_Properties_setVariable); - tolua_function(tolua_S,"parseVec2", lua_ax_base_Properties_parseVec2); - tolua_function(tolua_S,"parseVec3", lua_ax_base_Properties_parseVec3); - tolua_function(tolua_S,"parseVec4", lua_ax_base_Properties_parseVec4); - tolua_function(tolua_S,"parseAxisAngle", lua_ax_base_Properties_parseAxisAngle); - tolua_function(tolua_S,"parseColor", lua_ax_base_Properties_parseColor); + tolua_beginmodule(tolua_S,"Scheduler"); + tolua_function(tolua_S,"new",lua_ax_base_Scheduler_constructor); + tolua_function(tolua_S,"getTimeScale",lua_ax_base_Scheduler_getTimeScale); + tolua_function(tolua_S,"setTimeScale",lua_ax_base_Scheduler_setTimeScale); + tolua_function(tolua_S,"runOnAxmolThread",lua_ax_base_Scheduler_runOnAxmolThread); + tolua_function(tolua_S,"removeAllPendingActions",lua_ax_base_Scheduler_removeAllPendingActions); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::Properties).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.Properties"; - g_typeCast[typeName] = "ax.Properties"; + auto typeName = typeid(ax::Scheduler).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.Scheduler"; + g_typeCast[typeName] = "ax.Scheduler"; return 1; } @@ -31395,7 +31364,7 @@ int lua_ax_base_UserDefault_setBoolForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; bool arg1; @@ -31448,7 +31417,7 @@ int lua_ax_base_UserDefault_setIntegerForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; int arg1; @@ -31501,7 +31470,7 @@ int lua_ax_base_UserDefault_setLargeIntForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; long long arg1; @@ -31554,7 +31523,7 @@ int lua_ax_base_UserDefault_setFloatForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; double arg1; @@ -31607,7 +31576,7 @@ int lua_ax_base_UserDefault_setDoubleForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; double arg1; @@ -31660,7 +31629,7 @@ int lua_ax_base_UserDefault_setStringForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; std::string_view arg1; @@ -31713,7 +31682,7 @@ int lua_ax_base_UserDefault_flush(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -31760,7 +31729,7 @@ int lua_ax_base_UserDefault_deleteValueForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { const char* arg0; @@ -31810,7 +31779,7 @@ int lua_ax_base_UserDefault_setEncryptEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { bool arg0; std::string_view arg1; @@ -31983,7 +31952,7 @@ int lua_ax_base_FileUtils_purgeCachedEntries(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32030,7 +31999,7 @@ int lua_ax_base_FileUtils_getStringFromFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32080,7 +32049,7 @@ int lua_ax_base_FileUtils_fullPathForFilename(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32130,7 +32099,7 @@ int lua_ax_base_FileUtils_fullPathFromRelativeFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::string_view arg1; @@ -32183,7 +32152,7 @@ int lua_ax_base_FileUtils_fullPathForDirectory(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32233,7 +32202,7 @@ int lua_ax_base_FileUtils_setSearchPaths(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::vector arg0; @@ -32283,7 +32252,7 @@ int lua_ax_base_FileUtils_getDefaultResourceRootPath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32330,7 +32299,7 @@ int lua_ax_base_FileUtils_setDefaultResourceRootPath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32380,7 +32349,7 @@ int lua_ax_base_FileUtils_addSearchPath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32394,7 +32363,7 @@ int lua_ax_base_FileUtils_addSearchPath(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { std::string_view arg0; bool arg1; @@ -32447,7 +32416,7 @@ int lua_ax_base_FileUtils_getSearchPaths(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32494,7 +32463,7 @@ int lua_ax_base_FileUtils_getOriginalSearchPaths(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32541,7 +32510,7 @@ int lua_ax_base_FileUtils_getWritablePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32588,7 +32557,7 @@ int lua_ax_base_FileUtils_getNativeWritableAbsolutePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32635,7 +32604,7 @@ int lua_ax_base_FileUtils_setWritablePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32685,7 +32654,7 @@ int lua_ax_base_FileUtils_setPopupNotify(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -32735,7 +32704,7 @@ int lua_ax_base_FileUtils_isPopupNotify(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -32782,7 +32751,7 @@ int lua_ax_base_FileUtils_getValueMapFromFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -32832,7 +32801,7 @@ int lua_ax_base_FileUtils_getValueMapFromData(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const char* arg0; int arg1; @@ -32885,7 +32854,7 @@ int lua_ax_base_FileUtils_writeToFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ValueMap arg0; std::string_view arg1; @@ -32938,7 +32907,7 @@ int lua_ax_base_FileUtils_writeStringToFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::string_view arg1; @@ -32991,7 +32960,7 @@ int lua_ax_base_FileUtils_writeValueMapToFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ValueMap arg0; std::string_view arg1; @@ -33044,7 +33013,7 @@ int lua_ax_base_FileUtils_writeValueVectorToFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ValueVector arg0; std::string_view arg1; @@ -33097,7 +33066,7 @@ int lua_ax_base_FileUtils_getValueVectorFromFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33147,7 +33116,7 @@ int lua_ax_base_FileUtils_isFileExist(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33197,7 +33166,7 @@ int lua_ax_base_FileUtils_isAbsolutePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33247,7 +33216,7 @@ int lua_ax_base_FileUtils_isDirectoryExist(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33297,7 +33266,7 @@ int lua_ax_base_FileUtils_createDirectories(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33347,7 +33316,7 @@ int lua_ax_base_FileUtils_removeDirectory(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33397,7 +33366,7 @@ int lua_ax_base_FileUtils_removeFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33514,7 +33483,7 @@ int lua_ax_base_FileUtils_getFileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33564,7 +33533,7 @@ int lua_ax_base_FileUtils_listFiles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33614,7 +33583,7 @@ int lua_ax_base_FileUtils_listFilesRecursively(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::vector* arg1; @@ -33667,7 +33636,7 @@ int lua_ax_base_FileUtils_isFileExistInternal(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -33717,7 +33686,7 @@ int lua_ax_base_FileUtils_isDirectoryExistInternal(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -34137,7 +34106,7 @@ int lua_ax_base_EventCustom_getEventName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -34171,7 +34140,7 @@ int lua_ax_base_EventCustom_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -34245,7 +34214,7 @@ int lua_ax_base_EventDispatcher_addEventListenerWithSceneGraphPriority(lua_State #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::EventListener* arg0; ax::Node* arg1; @@ -34298,7 +34267,7 @@ int lua_ax_base_EventDispatcher_addEventListenerWithFixedPriority(lua_State* tol #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::EventListener* arg0; int arg1; @@ -34351,7 +34320,7 @@ int lua_ax_base_EventDispatcher_addCustomEventListener(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::function arg1; @@ -34408,7 +34377,7 @@ int lua_ax_base_EventDispatcher_removeEventListener(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EventListener* arg0; @@ -34458,7 +34427,7 @@ int lua_ax_base_EventDispatcher_removeEventListenersForType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EventListener::Type arg0; @@ -34508,7 +34477,7 @@ int lua_ax_base_EventDispatcher_removeEventListenersForTarget(lua_State* tolua_S #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -34522,7 +34491,7 @@ int lua_ax_base_EventDispatcher_removeEventListenersForTarget(lua_State* tolua_S lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Node* arg0; bool arg1; @@ -34575,7 +34544,7 @@ int lua_ax_base_EventDispatcher_removeCustomEventListeners(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -34625,7 +34594,7 @@ int lua_ax_base_EventDispatcher_removeAllEventListeners(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -34672,7 +34641,7 @@ int lua_ax_base_EventDispatcher_pauseEventListenersForTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -34686,7 +34655,7 @@ int lua_ax_base_EventDispatcher_pauseEventListenersForTarget(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Node* arg0; bool arg1; @@ -34739,7 +34708,7 @@ int lua_ax_base_EventDispatcher_resumeEventListenersForTarget(lua_State* tolua_S #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -34753,7 +34722,7 @@ int lua_ax_base_EventDispatcher_resumeEventListenersForTarget(lua_State* tolua_S lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Node* arg0; bool arg1; @@ -34806,7 +34775,7 @@ int lua_ax_base_EventDispatcher_setPriority(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::EventListener* arg0; int arg1; @@ -34859,7 +34828,7 @@ int lua_ax_base_EventDispatcher_setEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -34909,7 +34878,7 @@ int lua_ax_base_EventDispatcher_isEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -34956,7 +34925,7 @@ int lua_ax_base_EventDispatcher_dispatchEvent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Event* arg0; @@ -34970,7 +34939,7 @@ int lua_ax_base_EventDispatcher_dispatchEvent(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Event* arg0; bool arg1; @@ -35023,7 +34992,7 @@ int lua_ax_base_EventDispatcher_dispatchCustomEvent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -35037,7 +35006,7 @@ int lua_ax_base_EventDispatcher_dispatchCustomEvent(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { std::string_view arg0; void* arg1; @@ -35055,7 +35024,7 @@ int lua_ax_base_EventDispatcher_dispatchCustomEvent(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 3) + if (argc == 3) { std::string_view arg0; void* arg1; @@ -35112,7 +35081,7 @@ int lua_ax_base_EventDispatcher_hasEventListener(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -35149,7 +35118,7 @@ int lua_ax_base_EventDispatcher_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35222,7 +35191,7 @@ int lua_ax_base_EventFocus_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ui::Widget* arg0; ax::ui::Widget* arg1; @@ -35298,7 +35267,7 @@ int lua_ax_base_EventListenerAcceleration_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::function arg0; @@ -35339,7 +35308,7 @@ int lua_ax_base_EventListenerAcceleration_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35410,7 +35379,7 @@ int lua_ax_base_EventListenerFocus_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35444,7 +35413,7 @@ int lua_ax_base_EventListenerFocus_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35515,7 +35484,7 @@ int lua_ax_base_EventListenerKeyboard_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35549,7 +35518,7 @@ int lua_ax_base_EventListenerKeyboard_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35620,7 +35589,7 @@ int lua_ax_base_EventMouse_getMouseEventType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35667,7 +35636,7 @@ int lua_ax_base_EventMouse_setScrollData(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -35720,7 +35689,7 @@ int lua_ax_base_EventMouse_getScrollX(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35767,7 +35736,7 @@ int lua_ax_base_EventMouse_getScrollY(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35814,7 +35783,7 @@ int lua_ax_base_EventMouse_setMouseInfo(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; double arg1; @@ -35870,7 +35839,7 @@ int lua_ax_base_EventMouse_setMouseButton(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EventMouse::MouseButton arg0; @@ -35920,7 +35889,7 @@ int lua_ax_base_EventMouse_getMouseButton(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -35967,7 +35936,7 @@ int lua_ax_base_EventMouse_getLocation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36014,7 +35983,7 @@ int lua_ax_base_EventMouse_getPreviousLocation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36061,7 +36030,7 @@ int lua_ax_base_EventMouse_getStartLocation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36108,7 +36077,7 @@ int lua_ax_base_EventMouse_getDelta(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36155,7 +36124,7 @@ int lua_ax_base_EventMouse_getLocationInView(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36202,7 +36171,7 @@ int lua_ax_base_EventMouse_getPreviousLocationInView(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36249,7 +36218,7 @@ int lua_ax_base_EventMouse_getStartLocationInView(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36283,7 +36252,7 @@ int lua_ax_base_EventMouse_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EventMouse::MouseEventType arg0; @@ -36370,7 +36339,7 @@ int lua_ax_base_EventListenerMouse_setSwallowMouse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -36420,7 +36389,7 @@ int lua_ax_base_EventListenerMouse_isSwallowMouse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36467,7 +36436,7 @@ int lua_ax_base_EventListenerMouse_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36501,7 +36470,7 @@ int lua_ax_base_EventListenerMouse_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36593,7 +36562,7 @@ int lua_ax_base_EventListenerTouchOneByOne_setSwallowTouches(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -36643,7 +36612,7 @@ int lua_ax_base_EventListenerTouchOneByOne_isSwallowTouches(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36690,7 +36659,7 @@ int lua_ax_base_EventListenerTouchOneByOne_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36724,7 +36693,7 @@ int lua_ax_base_EventListenerTouchOneByOne_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36797,7 +36766,7 @@ int lua_ax_base_EventListenerTouchAllAtOnce_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36831,7 +36800,7 @@ int lua_ax_base_EventListenerTouchAllAtOnce_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36902,7 +36871,7 @@ int lua_ax_base_EventController_getControllerEventType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36949,7 +36918,7 @@ int lua_ax_base_EventController_getController(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -36996,7 +36965,7 @@ int lua_ax_base_EventController_getKeyCode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37043,7 +37012,7 @@ int lua_ax_base_EventController_setKeyCode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -37093,7 +37062,7 @@ int lua_ax_base_EventController_setConnectStatus(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -37143,7 +37112,7 @@ int lua_ax_base_EventController_isConnected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37345,7 +37314,7 @@ int lua_ax_base_ActionCamera_getEye(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37392,7 +37361,7 @@ int lua_ax_base_ActionCamera_setCenter(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -37442,7 +37411,7 @@ int lua_ax_base_ActionCamera_getCenter(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37489,7 +37458,7 @@ int lua_ax_base_ActionCamera_setUp(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -37539,7 +37508,7 @@ int lua_ax_base_ActionCamera_getUp(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37573,7 +37542,7 @@ int lua_ax_base_ActionCamera_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37649,7 +37618,7 @@ int lua_ax_base_OrbitCamera_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 7) + if (argc == 7) { double arg0; double arg1; @@ -37752,7 +37721,7 @@ int lua_ax_base_OrbitCamera_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37824,7 +37793,7 @@ int lua_ax_base_CardinalSplineTo_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; ax::PointArray* arg1; @@ -37880,7 +37849,7 @@ int lua_ax_base_CardinalSplineTo_updatePosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -37930,7 +37899,7 @@ int lua_ax_base_CardinalSplineTo_getPoints(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -37964,7 +37933,7 @@ int lua_ax_base_CardinalSplineTo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38024,7 +37993,7 @@ int lua_ax_base_CardinalSplineBy_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38094,7 +38063,7 @@ int lua_ax_base_CatmullRomTo_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; ax::PointArray* arg1; @@ -38167,7 +38136,7 @@ int lua_ax_base_CatmullRomBy_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; ax::PointArray* arg1; @@ -38240,7 +38209,7 @@ int lua_ax_base_ActionEase_getInnerAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38287,7 +38256,7 @@ int lua_ax_base_ActionEase_initWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -38358,7 +38327,7 @@ int lua_ax_base_EaseRateAction_setRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -38408,7 +38377,7 @@ int lua_ax_base_EaseRateAction_getRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38455,7 +38424,7 @@ int lua_ax_base_EaseRateAction_initWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ActionInterval* arg0; double arg1; @@ -38592,7 +38561,7 @@ int lua_ax_base_EaseExponentialIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38686,7 +38655,7 @@ int lua_ax_base_EaseExponentialOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38780,7 +38749,7 @@ int lua_ax_base_EaseExponentialInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38874,7 +38843,7 @@ int lua_ax_base_EaseSineIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -38968,7 +38937,7 @@ int lua_ax_base_EaseSineOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39062,7 +39031,7 @@ int lua_ax_base_EaseSineInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39175,7 +39144,7 @@ int lua_ax_base_EaseBounceIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39269,7 +39238,7 @@ int lua_ax_base_EaseBounceOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39363,7 +39332,7 @@ int lua_ax_base_EaseBounceInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39457,7 +39426,7 @@ int lua_ax_base_EaseBackIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39551,7 +39520,7 @@ int lua_ax_base_EaseBackOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39645,7 +39614,7 @@ int lua_ax_base_EaseBackInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39739,7 +39708,7 @@ int lua_ax_base_EaseQuadraticActionIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39833,7 +39802,7 @@ int lua_ax_base_EaseQuadraticActionOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -39927,7 +39896,7 @@ int lua_ax_base_EaseQuadraticActionInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40021,7 +39990,7 @@ int lua_ax_base_EaseQuarticActionIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40115,7 +40084,7 @@ int lua_ax_base_EaseQuarticActionOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40209,7 +40178,7 @@ int lua_ax_base_EaseQuarticActionInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40303,7 +40272,7 @@ int lua_ax_base_EaseQuinticActionIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40397,7 +40366,7 @@ int lua_ax_base_EaseQuinticActionOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40491,7 +40460,7 @@ int lua_ax_base_EaseQuinticActionInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40585,7 +40554,7 @@ int lua_ax_base_EaseCircleActionIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40679,7 +40648,7 @@ int lua_ax_base_EaseCircleActionOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40773,7 +40742,7 @@ int lua_ax_base_EaseCircleActionInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40867,7 +40836,7 @@ int lua_ax_base_EaseCubicActionIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -40961,7 +40930,7 @@ int lua_ax_base_EaseCubicActionOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41055,7 +41024,7 @@ int lua_ax_base_EaseCubicActionInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41151,7 +41120,7 @@ int lua_ax_base_EaseIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41247,7 +41216,7 @@ int lua_ax_base_EaseOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41343,7 +41312,7 @@ int lua_ax_base_EaseInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41414,7 +41383,7 @@ int lua_ax_base_EaseElastic_getPeriod(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41461,7 +41430,7 @@ int lua_ax_base_EaseElastic_setPeriod(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -41511,7 +41480,7 @@ int lua_ax_base_EaseElastic_initWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -41525,7 +41494,7 @@ int lua_ax_base_EaseElastic_initWithAction(lua_State* tolua_S) tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 2) + if (argc == 2) { ax::ActionInterval* arg0; double arg1; @@ -41638,7 +41607,7 @@ int lua_ax_base_EaseElasticIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41747,7 +41716,7 @@ int lua_ax_base_EaseElasticOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41856,7 +41825,7 @@ int lua_ax_base_EaseElasticInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -41927,7 +41896,7 @@ int lua_ax_base_EaseBezierAction_setBezierParamer(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; double arg1; @@ -42009,7 +41978,7 @@ int lua_ax_base_EaseBezierAction_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42121,7 +42090,7 @@ int lua_ax_base_Show_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42213,7 +42182,7 @@ int lua_ax_base_Hide_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42305,7 +42274,7 @@ int lua_ax_base_ToggleVisibility_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42376,7 +42345,7 @@ int lua_ax_base_RemoveSelf_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -42460,7 +42429,7 @@ int lua_ax_base_RemoveSelf_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42532,7 +42501,7 @@ int lua_ax_base_FlipX_initWithFlipX(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -42605,7 +42574,7 @@ int lua_ax_base_FlipX_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42677,7 +42646,7 @@ int lua_ax_base_FlipY_initWithFlipY(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -42750,7 +42719,7 @@ int lua_ax_base_FlipY_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42822,7 +42791,7 @@ int lua_ax_base_Place_initWithPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -42895,7 +42864,7 @@ int lua_ax_base_Place_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -42967,7 +42936,7 @@ int lua_ax_base_CallFunc_execute(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43001,7 +42970,7 @@ int lua_ax_base_CallFunc_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43072,7 +43041,7 @@ int lua_ax_base_GridAction_getGrid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43119,7 +43088,7 @@ int lua_ax_base_GridAction_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; ax::Vec2 arg1; @@ -43193,7 +43162,7 @@ int lua_ax_base_Grid3DAction_getGridRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43300,7 +43269,7 @@ int lua_ax_base_StopGrid_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43371,7 +43340,7 @@ int lua_ax_base_ReuseGrid_initWithTimes(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -43444,7 +43413,7 @@ int lua_ax_base_ReuseGrid_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43516,7 +43485,7 @@ int lua_ax_base_Waves3D_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43563,7 +43532,7 @@ int lua_ax_base_Waves3D_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -43613,7 +43582,7 @@ int lua_ax_base_Waves3D_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43660,7 +43629,7 @@ int lua_ax_base_Waves3D_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -43710,7 +43679,7 @@ int lua_ax_base_Waves3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -43798,7 +43767,7 @@ int lua_ax_base_Waves3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -43874,7 +43843,7 @@ int lua_ax_base_FlipX3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -43924,7 +43893,7 @@ int lua_ax_base_FlipX3D_initWithSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Vec2 arg0; double arg1; @@ -44000,7 +43969,7 @@ int lua_ax_base_FlipX3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44096,7 +44065,7 @@ int lua_ax_base_FlipY3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44167,7 +44136,7 @@ int lua_ax_base_Lens3D_getLensEffect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44214,7 +44183,7 @@ int lua_ax_base_Lens3D_setLensEffect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -44264,7 +44233,7 @@ int lua_ax_base_Lens3D_setConcave(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -44314,7 +44283,7 @@ int lua_ax_base_Lens3D_getPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44361,7 +44330,7 @@ int lua_ax_base_Lens3D_setPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -44411,7 +44380,7 @@ int lua_ax_base_Lens3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -44499,7 +44468,7 @@ int lua_ax_base_Lens3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44576,7 +44545,7 @@ int lua_ax_base_Ripple3D_getPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44623,7 +44592,7 @@ int lua_ax_base_Ripple3D_setPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -44673,7 +44642,7 @@ int lua_ax_base_Ripple3D_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44720,7 +44689,7 @@ int lua_ax_base_Ripple3D_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -44770,7 +44739,7 @@ int lua_ax_base_Ripple3D_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -44817,7 +44786,7 @@ int lua_ax_base_Ripple3D_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -44867,7 +44836,7 @@ int lua_ax_base_Ripple3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 6) { double arg0; ax::Vec2 arg1; @@ -44965,7 +44934,7 @@ int lua_ax_base_Ripple3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45043,7 +45012,7 @@ int lua_ax_base_Shaky3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -45131,7 +45100,7 @@ int lua_ax_base_Shaky3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45203,7 +45172,7 @@ int lua_ax_base_Liquid_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45250,7 +45219,7 @@ int lua_ax_base_Liquid_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -45300,7 +45269,7 @@ int lua_ax_base_Liquid_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45347,7 +45316,7 @@ int lua_ax_base_Liquid_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -45397,7 +45366,7 @@ int lua_ax_base_Liquid_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -45485,7 +45454,7 @@ int lua_ax_base_Liquid_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45561,7 +45530,7 @@ int lua_ax_base_Waves_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45608,7 +45577,7 @@ int lua_ax_base_Waves_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -45658,7 +45627,7 @@ int lua_ax_base_Waves_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45705,7 +45674,7 @@ int lua_ax_base_Waves_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -45755,7 +45724,7 @@ int lua_ax_base_Waves_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 6) { double arg0; ax::Vec2 arg1; @@ -45853,7 +45822,7 @@ int lua_ax_base_Waves_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45929,7 +45898,7 @@ int lua_ax_base_Twirl_getPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -45976,7 +45945,7 @@ int lua_ax_base_Twirl_setPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -46026,7 +45995,7 @@ int lua_ax_base_Twirl_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -46073,7 +46042,7 @@ int lua_ax_base_Twirl_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -46123,7 +46092,7 @@ int lua_ax_base_Twirl_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -46170,7 +46139,7 @@ int lua_ax_base_Twirl_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -46220,7 +46189,7 @@ int lua_ax_base_Twirl_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 5) { double arg0; ax::Vec2 arg1; @@ -46313,7 +46282,7 @@ int lua_ax_base_Twirl_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -46391,7 +46360,7 @@ int lua_ax_base_ActionManager_addAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Action* arg0; ax::Node* arg1; @@ -46447,7 +46416,7 @@ int lua_ax_base_ActionManager_removeAllActions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -46494,7 +46463,7 @@ int lua_ax_base_ActionManager_removeAllActionsFromTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -46544,7 +46513,7 @@ int lua_ax_base_ActionManager_removeAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Action* arg0; @@ -46594,7 +46563,7 @@ int lua_ax_base_ActionManager_removeActionByTag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { int arg0; ax::Node* arg1; @@ -46647,7 +46616,7 @@ int lua_ax_base_ActionManager_removeAllActionsByTag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { int arg0; ax::Node* arg1; @@ -46700,7 +46669,7 @@ int lua_ax_base_ActionManager_removeActionsByFlags(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { unsigned int arg0; ax::Node* arg1; @@ -46753,7 +46722,7 @@ int lua_ax_base_ActionManager_getActionByTag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { int arg0; const ax::Node* arg1; @@ -46806,7 +46775,7 @@ int lua_ax_base_ActionManager_getNumberOfRunningActionsInTarget(lua_State* tolua #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { const ax::Node* arg0; @@ -46856,7 +46825,7 @@ int lua_ax_base_ActionManager_getNumberOfRunningActions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -46903,7 +46872,7 @@ int lua_ax_base_ActionManager_getNumberOfRunningActionsInTargetByTag(lua_State* #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const ax::Node* arg0; int arg1; @@ -46956,7 +46925,7 @@ int lua_ax_base_ActionManager_pauseTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -47006,7 +46975,7 @@ int lua_ax_base_ActionManager_resumeTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -47056,7 +47025,7 @@ int lua_ax_base_ActionManager_pauseAllRunningActions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47103,7 +47072,7 @@ int lua_ax_base_ActionManager_resumeTargets(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -47153,7 +47122,7 @@ int lua_ax_base_ActionManager_update(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -47190,7 +47159,7 @@ int lua_ax_base_ActionManager_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47334,7 +47303,7 @@ int lua_ax_base_ProgressTo_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -47412,7 +47381,7 @@ int lua_ax_base_ProgressTo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47484,7 +47453,7 @@ int lua_ax_base_ProgressFromTo_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; double arg1; @@ -47567,7 +47536,7 @@ int lua_ax_base_ProgressFromTo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47639,7 +47608,7 @@ int lua_ax_base_ShakyTiles3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -47727,7 +47696,7 @@ int lua_ax_base_ShakyTiles3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47799,7 +47768,7 @@ int lua_ax_base_ShatteredTiles3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -47887,7 +47856,7 @@ int lua_ax_base_ShatteredTiles3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -47959,7 +47928,7 @@ int lua_ax_base_ShuffleTiles_getDelta(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -48009,7 +47978,7 @@ int lua_ax_base_ShuffleTiles_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; ax::Vec2 arg1; @@ -48092,7 +48061,7 @@ int lua_ax_base_ShuffleTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -48165,7 +48134,7 @@ int lua_ax_base_FadeOutTRTiles_testFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Vec2 arg0; double arg1; @@ -48218,7 +48187,7 @@ int lua_ax_base_FadeOutTRTiles_turnOnTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -48268,7 +48237,7 @@ int lua_ax_base_FadeOutTRTiles_turnOffTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -48318,7 +48287,7 @@ int lua_ax_base_FadeOutTRTiles_transformTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Vec2 arg0; double arg1; @@ -48396,7 +48365,7 @@ int lua_ax_base_FadeOutTRTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -48496,7 +48465,7 @@ int lua_ax_base_FadeOutBLTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -48592,7 +48561,7 @@ int lua_ax_base_FadeOutUpTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -48688,7 +48657,7 @@ int lua_ax_base_FadeOutDownTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -48759,7 +48728,7 @@ int lua_ax_base_TurnOffTiles_turnOnTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -48809,7 +48778,7 @@ int lua_ax_base_TurnOffTiles_turnOffTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -48859,7 +48828,7 @@ int lua_ax_base_TurnOffTiles_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; ax::Vec2 arg1; @@ -48903,7 +48872,7 @@ int lua_ax_base_TurnOffTiles_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 3) { @@ -48922,7 +48891,7 @@ int lua_ax_base_TurnOffTiles_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 2) { @@ -48959,7 +48928,7 @@ int lua_ax_base_TurnOffTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49033,7 +49002,7 @@ int lua_ax_base_WavesTiles3D_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49080,7 +49049,7 @@ int lua_ax_base_WavesTiles3D_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -49130,7 +49099,7 @@ int lua_ax_base_WavesTiles3D_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49177,7 +49146,7 @@ int lua_ax_base_WavesTiles3D_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -49227,7 +49196,7 @@ int lua_ax_base_WavesTiles3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -49315,7 +49284,7 @@ int lua_ax_base_WavesTiles3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49391,7 +49360,7 @@ int lua_ax_base_JumpTiles3D_getAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49438,7 +49407,7 @@ int lua_ax_base_JumpTiles3D_setAmplitude(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -49488,7 +49457,7 @@ int lua_ax_base_JumpTiles3D_getAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49535,7 +49504,7 @@ int lua_ax_base_JumpTiles3D_setAmplitudeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -49585,7 +49554,7 @@ int lua_ax_base_JumpTiles3D_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; ax::Vec2 arg1; @@ -49673,7 +49642,7 @@ int lua_ax_base_JumpTiles3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49749,7 +49718,7 @@ int lua_ax_base_SplitRows_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; unsigned int arg1; @@ -49827,7 +49796,7 @@ int lua_ax_base_SplitRows_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -49899,7 +49868,7 @@ int lua_ax_base_SplitCols_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; unsigned int arg1; @@ -49977,7 +49946,7 @@ int lua_ax_base_SplitCols_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50049,7 +50018,7 @@ int lua_ax_base_ActionTween_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; std::string_view arg1; @@ -50171,7 +50140,7 @@ int lua_ax_base_ActionCoroutine_initWithCoroutine(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::function arg0; @@ -50252,7 +50221,7 @@ int lua_ax_base_ActionCoroutine_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50324,7 +50293,7 @@ int lua_ax_base_AtlasNode_updateAtlasValues(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50371,7 +50340,7 @@ int lua_ax_base_AtlasNode_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50418,7 +50387,7 @@ int lua_ax_base_AtlasNode_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -50468,7 +50437,7 @@ int lua_ax_base_AtlasNode_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -50518,7 +50487,7 @@ int lua_ax_base_AtlasNode_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50565,7 +50534,7 @@ int lua_ax_base_AtlasNode_setTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextureAtlas* arg0; @@ -50615,7 +50584,7 @@ int lua_ax_base_AtlasNode_getTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50662,7 +50631,7 @@ int lua_ax_base_AtlasNode_setQuadsToDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -50712,7 +50681,7 @@ int lua_ax_base_AtlasNode_getQuadsToDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50759,7 +50728,7 @@ int lua_ax_base_AtlasNode_initWithTileFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { std::string_view arg0; int arg1; @@ -50818,7 +50787,7 @@ int lua_ax_base_AtlasNode_initWithTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { ax::Texture2D* arg0; int arg1; @@ -50906,7 +50875,7 @@ int lua_ax_base_AtlasNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -50988,7 +50957,7 @@ int lua_ax_base_ClippingNode_getStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51035,7 +51004,7 @@ int lua_ax_base_ClippingNode_setStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -51049,7 +51018,7 @@ int lua_ax_base_ClippingNode_setStencil(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Node* arg0; bool arg1; @@ -51102,7 +51071,7 @@ int lua_ax_base_ClippingNode_hasContent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51149,7 +51118,7 @@ int lua_ax_base_ClippingNode_getAlphaThreshold(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51196,7 +51165,7 @@ int lua_ax_base_ClippingNode_setAlphaThreshold(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -51246,7 +51215,7 @@ int lua_ax_base_ClippingNode_isInverted(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51293,7 +51262,7 @@ int lua_ax_base_ClippingNode_setInverted(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -51343,7 +51312,7 @@ int lua_ax_base_ClippingNode_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -51381,7 +51350,7 @@ int lua_ax_base_ClippingNode_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 1) { @@ -51394,7 +51363,7 @@ int lua_ax_base_ClippingNode_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 0) { @@ -51466,7 +51435,7 @@ int lua_ax_base_ClippingRectangleNode_getClippingRegion(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51513,7 +51482,7 @@ int lua_ax_base_ClippingRectangleNode_setClippingRegion(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -51563,7 +51532,7 @@ int lua_ax_base_ClippingRectangleNode_isClippingEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -51610,7 +51579,7 @@ int lua_ax_base_ClippingRectangleNode_setClippingEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -51648,7 +51617,7 @@ int lua_ax_base_ClippingRectangleNode_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 0) { @@ -51658,7 +51627,7 @@ int lua_ax_base_ClippingRectangleNode_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -51729,17 +51698,17 @@ int lua_ax_base_DrawNode_drawPoint(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Vec2 arg0; double arg1; - ax::Color4B arg2; + ax::Color arg2; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawPoint"); ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.DrawNode:drawPoint"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawPoint"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawPoint"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawPoint'", nullptr); @@ -51749,18 +51718,18 @@ int lua_ax_base_DrawNode_drawPoint(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 4) + if (argc == 4) { ax::Vec2 arg0; double arg1; - ax::Color4B arg2; + ax::Color arg2; ax::DrawNode::PointType arg3; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawPoint"); ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.DrawNode:drawPoint"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawPoint"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawPoint"); ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.DrawNode:drawPoint"); if(!ok) @@ -51808,17 +51777,17 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawLine"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawLine"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawLine'", nullptr); @@ -51828,18 +51797,18 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 4) + if (argc == 4) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; double arg3; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawLine"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawLine"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.DrawNode:drawLine"); if(!ok) @@ -51851,11 +51820,11 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 5) + if (argc == 5) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; double arg3; ax::DrawNode::EndType arg4; @@ -51863,7 +51832,7 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawLine"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.DrawNode:drawLine"); @@ -51877,11 +51846,11 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; double arg3; ax::DrawNode::EndType arg4; ax::DrawNode::EndType arg5; @@ -51890,7 +51859,7 @@ int lua_ax_base_DrawNode_drawLine(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawLine"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawLine"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.DrawNode:drawLine"); @@ -51955,8 +51924,8 @@ int lua_ax_base_DrawNode_drawRect(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.DrawNode:drawRect"); if (!ok) { break; } - ax::Color4B arg4; - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawRect"); + ax::Color arg4; + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawRect"); if (!ok) { break; } cobj->drawRect(arg0, arg1, arg2, arg3, arg4); @@ -51983,8 +51952,8 @@ int lua_ax_base_DrawNode_drawRect(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.DrawNode:drawRect"); if (!ok) { break; } - ax::Color4B arg4; - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawRect"); + ax::Color arg4; + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawRect"); if (!ok) { break; } double arg5; @@ -52007,8 +51976,8 @@ int lua_ax_base_DrawNode_drawRect(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawRect"); if (!ok) { break; } - ax::Color4B arg2; - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawRect"); + ax::Color arg2; + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawRect"); if (!ok) { break; } cobj->drawRect(arg0, arg1, arg2); @@ -52027,8 +51996,8 @@ int lua_ax_base_DrawNode_drawRect(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawRect"); if (!ok) { break; } - ax::Color4B arg2; - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawRect"); + ax::Color arg2; + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawRect"); if (!ok) { break; } double arg3; @@ -52094,8 +52063,8 @@ int lua_ax_base_DrawNode_drawCircle(lua_State* tolua_S) ok &= luaval_to_boolean(tolua_S, 6,&arg4, "ax.DrawNode:drawCircle"); if (!ok) { break; } - ax::Color4B arg5; - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawCircle"); + ax::Color arg5; + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawCircle"); if (!ok) { break; } cobj->drawCircle(arg0, arg1, arg2, arg3, arg4, arg5); @@ -52126,8 +52095,8 @@ int lua_ax_base_DrawNode_drawCircle(lua_State* tolua_S) ok &= luaval_to_boolean(tolua_S, 6,&arg4, "ax.DrawNode:drawCircle"); if (!ok) { break; } - ax::Color4B arg5; - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawCircle"); + ax::Color arg5; + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawCircle"); if (!ok) { break; } double arg6; @@ -52170,8 +52139,8 @@ int lua_ax_base_DrawNode_drawCircle(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawCircle"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawCircle"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawCircle"); if (!ok) { break; } cobj->drawCircle(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); @@ -52210,8 +52179,8 @@ int lua_ax_base_DrawNode_drawCircle(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawCircle"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawCircle"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawCircle"); if (!ok) { break; } double arg8; @@ -52260,13 +52229,13 @@ int lua_ax_base_DrawNode_drawStar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 5) { ax::Vec2 arg0; double arg1; double arg2; unsigned int arg3; - ax::Color4B arg4; + ax::Color arg4; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawStar"); @@ -52276,7 +52245,7 @@ int lua_ax_base_DrawNode_drawStar(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawStar"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawStar"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawStar"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawStar'", nullptr); @@ -52286,13 +52255,13 @@ int lua_ax_base_DrawNode_drawStar(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; double arg1; double arg2; unsigned int arg3; - ax::Color4B arg4; + ax::Color arg4; double arg5; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawStar"); @@ -52303,7 +52272,7 @@ int lua_ax_base_DrawNode_drawStar(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawStar"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawStar"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawStar"); ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.DrawNode:drawStar"); if(!ok) @@ -52351,14 +52320,14 @@ int lua_ax_base_DrawNode_drawSolidStar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; double arg1; double arg2; unsigned int arg3; - ax::Color4B arg4; - ax::Color4B arg5; + ax::Color arg4; + ax::Color arg5; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSolidStar"); @@ -52368,9 +52337,9 @@ int lua_ax_base_DrawNode_drawSolidStar(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawSolidStar"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidStar"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidStar"); - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawSolidStar"); + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawSolidStar"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawSolidStar'", nullptr); @@ -52380,14 +52349,14 @@ int lua_ax_base_DrawNode_drawSolidStar(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 7) + if (argc == 7) { ax::Vec2 arg0; double arg1; double arg2; unsigned int arg3; - ax::Color4B arg4; - ax::Color4B arg5; + ax::Color arg4; + ax::Color arg5; double arg6; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSolidStar"); @@ -52398,9 +52367,9 @@ int lua_ax_base_DrawNode_drawSolidStar(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawSolidStar"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidStar"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidStar"); - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawSolidStar"); + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawSolidStar"); ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawSolidStar"); if(!ok) @@ -52448,13 +52417,13 @@ int lua_ax_base_DrawNode_drawQuadBezier(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 5) { ax::Vec2 arg0; ax::Vec2 arg1; ax::Vec2 arg2; unsigned int arg3; - ax::Color4B arg4; + ax::Color arg4; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawQuadBezier"); @@ -52464,7 +52433,7 @@ int lua_ax_base_DrawNode_drawQuadBezier(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawQuadBezier"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawQuadBezier"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawQuadBezier"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawQuadBezier'", nullptr); @@ -52474,13 +52443,13 @@ int lua_ax_base_DrawNode_drawQuadBezier(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; ax::Vec2 arg1; ax::Vec2 arg2; unsigned int arg3; - ax::Color4B arg4; + ax::Color arg4; double arg5; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawQuadBezier"); @@ -52491,7 +52460,7 @@ int lua_ax_base_DrawNode_drawQuadBezier(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawQuadBezier"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawQuadBezier"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawQuadBezier"); ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.DrawNode:drawQuadBezier"); if(!ok) @@ -52539,14 +52508,14 @@ int lua_ax_base_DrawNode_drawCubicBezier(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; ax::Vec2 arg1; ax::Vec2 arg2; ax::Vec2 arg3; unsigned int arg4; - ax::Color4B arg5; + ax::Color arg5; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawCubicBezier"); @@ -52558,7 +52527,7 @@ int lua_ax_base_DrawNode_drawCubicBezier(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 6,&arg4, "ax.DrawNode:drawCubicBezier"); - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawCubicBezier"); + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawCubicBezier"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawCubicBezier'", nullptr); @@ -52568,14 +52537,14 @@ int lua_ax_base_DrawNode_drawCubicBezier(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 7) + if (argc == 7) { ax::Vec2 arg0; ax::Vec2 arg1; ax::Vec2 arg2; ax::Vec2 arg3; unsigned int arg4; - ax::Color4B arg5; + ax::Color arg5; double arg6; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawCubicBezier"); @@ -52588,7 +52557,7 @@ int lua_ax_base_DrawNode_drawCubicBezier(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 6,&arg4, "ax.DrawNode:drawCubicBezier"); - ok &=luaval_to_color4b(tolua_S, 7, &arg5, "ax.DrawNode:drawCubicBezier"); + ok &=luaval_to_color(tolua_S, 7, &arg5, "ax.DrawNode:drawCubicBezier"); ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawCubicBezier"); if(!ok) @@ -52636,17 +52605,17 @@ int lua_ax_base_DrawNode_drawDot(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Vec2 arg0; double arg1; - ax::Color4B arg2; + ax::Color arg2; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawDot"); ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.DrawNode:drawDot"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawDot"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawDot"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawDot'", nullptr); @@ -52692,17 +52661,17 @@ int lua_ax_base_DrawNode_drawSolidRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSolidRect"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidRect"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawSolidRect'", nullptr); @@ -52712,18 +52681,18 @@ int lua_ax_base_DrawNode_drawSolidRect(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 4) + if (argc == 4) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; double arg3; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSolidRect"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidRect"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.DrawNode:drawSolidRect"); if(!ok) @@ -52735,23 +52704,23 @@ int lua_ax_base_DrawNode_drawSolidRect(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 5) + if (argc == 5) { ax::Vec2 arg0; ax::Vec2 arg1; - ax::Color4B arg2; + ax::Color arg2; double arg3; - ax::Color4B arg4; + ax::Color arg4; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSolidRect"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidRect"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidRect"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.DrawNode:drawSolidRect"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidRect"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidRect"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawSolidRect'", nullptr); @@ -52818,8 +52787,8 @@ int lua_ax_base_DrawNode_drawSolidCircle(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg6; - ok &=luaval_to_color4b(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); + ax::Color arg6; + ok &=luaval_to_color(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } cobj->drawSolidCircle(arg0, arg1, arg2, arg3, arg4, arg5, arg6); @@ -52854,16 +52823,16 @@ int lua_ax_base_DrawNode_drawSolidCircle(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg6; - ok &=luaval_to_color4b(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); + ax::Color arg6; + ok &=luaval_to_color(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } double arg7; ok &= luaval_to_number(tolua_S, 9,&arg7, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg8; - ok &=luaval_to_color4b(tolua_S, 10, &arg8, "ax.DrawNode:drawSolidCircle"); + ax::Color arg8; + ok &=luaval_to_color(tolua_S, 10, &arg8, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } cobj->drawSolidCircle(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); @@ -52898,16 +52867,16 @@ int lua_ax_base_DrawNode_drawSolidCircle(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg6; - ok &=luaval_to_color4b(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); + ax::Color arg6; + ok &=luaval_to_color(tolua_S, 8, &arg6, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } double arg7; ok &= luaval_to_number(tolua_S, 9,&arg7, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg8; - ok &=luaval_to_color4b(tolua_S, 10, &arg8, "ax.DrawNode:drawSolidCircle"); + ax::Color arg8; + ok &=luaval_to_color(tolua_S, 10, &arg8, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } bool arg9; @@ -52938,8 +52907,8 @@ int lua_ax_base_DrawNode_drawSolidCircle(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 5,&arg3, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } - ax::Color4B arg4; - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidCircle"); + ax::Color arg4; + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidCircle"); if (!ok) { break; } cobj->drawSolidCircle(arg0, arg1, arg2, arg3, arg4); @@ -53009,8 +52978,8 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); if (!ok) { break; } cobj->drawPie(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); @@ -53049,8 +53018,8 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); if (!ok) { break; } ax::DrawNode::DrawMode arg8; @@ -53093,12 +53062,12 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg8; - ok &=luaval_to_color4b(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); + ax::Color arg8; + ok &=luaval_to_color(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); if (!ok) { break; } cobj->drawPie(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); @@ -53137,12 +53106,12 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg8; - ok &=luaval_to_color4b(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); + ax::Color arg8; + ok &=luaval_to_color(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); if (!ok) { break; } ax::DrawNode::DrawMode arg9; @@ -53185,12 +53154,12 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 8,&arg6, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg7; - ok &=luaval_to_color4b(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); + ax::Color arg7; + ok &=luaval_to_color(tolua_S, 9, &arg7, "ax.DrawNode:drawPie"); if (!ok) { break; } - ax::Color4B arg8; - ok &=luaval_to_color4b(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); + ax::Color arg8; + ok &=luaval_to_color(tolua_S, 10, &arg8, "ax.DrawNode:drawPie"); if (!ok) { break; } ax::DrawNode::DrawMode arg9; @@ -53217,56 +53186,6 @@ int lua_ax_base_DrawNode_drawPie(lua_State* tolua_S) return 0; } -int lua_ax_base_DrawNode_setIsConvex(lua_State* tolua_S) -{ - int argc = 0; - ax::DrawNode* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.DrawNode",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::DrawNode*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_DrawNode_setIsConvex'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.DrawNode:setIsConvex"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_setIsConvex'", nullptr); - return 0; - } - cobj->setIsConvex(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.DrawNode:setIsConvex",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_DrawNode_setIsConvex'.",&tolua_err); -#endif - - return 0; -} int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) { int argc = 0; @@ -53293,12 +53212,12 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { ax::Vec2 arg0; ax::Vec2 arg1; double arg2; - ax::Color4B arg3; + ax::Color arg3; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSegment"); @@ -53306,7 +53225,7 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.DrawNode:drawSegment"); - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DrawNode_drawSegment'", nullptr); @@ -53316,12 +53235,12 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 5) + if (argc == 5) { ax::Vec2 arg0; ax::Vec2 arg1; double arg2; - ax::Color4B arg3; + ax::Color arg3; ax::DrawNode::EndType arg4; ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.DrawNode:drawSegment"); @@ -53330,7 +53249,7 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.DrawNode:drawSegment"); - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.DrawNode:drawSegment"); if(!ok) @@ -53342,12 +53261,12 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 6) + if (argc == 6) { ax::Vec2 arg0; ax::Vec2 arg1; double arg2; - ax::Color4B arg3; + ax::Color arg3; ax::DrawNode::EndType arg4; ax::DrawNode::EndType arg5; @@ -53357,7 +53276,7 @@ int lua_ax_base_DrawNode_drawSegment(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.DrawNode:drawSegment"); - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawSegment"); ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.DrawNode:drawSegment"); @@ -53407,14 +53326,14 @@ int lua_ax_base_DrawNode_drawColoredTriangle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const ax::Vec2* arg0; - const ax::Color4B* arg1; + const ax::Color* arg1; ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.DrawNode:drawColoredTriangle"); - #pragma warning NO CONVERSION TO NATIVE FOR Color4B* + #pragma warning NO CONVERSION TO NATIVE FOR Color* ok = false; if(!ok) { @@ -53470,8 +53389,8 @@ int lua_ax_base_DrawNode_drawTriangle(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.DrawNode:drawTriangle"); if (!ok) { break; } - ax::Color4B arg3; - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawTriangle"); + ax::Color arg3; + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawTriangle"); if (!ok) { break; } cobj->drawTriangle(arg0, arg1, arg2, arg3); @@ -53486,8 +53405,8 @@ int lua_ax_base_DrawNode_drawTriangle(lua_State* tolua_S) ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.DrawNode:drawTriangle"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.DrawNode:drawTriangle"); + ax::Color arg1; + ok &=luaval_to_color(tolua_S, 3, &arg1, "ax.DrawNode:drawTriangle"); if (!ok) { break; } cobj->drawTriangle(arg0, arg1); @@ -53541,12 +53460,12 @@ int lua_ax_base_DrawNode_drawSolidTriangle(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg3; - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg3; + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg4; - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg4; + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } cobj->drawSolidTriangle(arg0, arg1, arg2, arg3, arg4); @@ -53569,12 +53488,12 @@ int lua_ax_base_DrawNode_drawSolidTriangle(lua_State* tolua_S) ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg3; - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg3; + ok &=luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg4; - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg4; + ok &=luaval_to_color(tolua_S, 6, &arg4, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } double arg5; @@ -53593,12 +53512,12 @@ int lua_ax_base_DrawNode_drawSolidTriangle(lua_State* tolua_S) ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg1; + ok &=luaval_to_color(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg2; - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg2; + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } cobj->drawSolidTriangle(arg0, arg1, arg2); @@ -53613,12 +53532,12 @@ int lua_ax_base_DrawNode_drawSolidTriangle(lua_State* tolua_S) ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg1; + ok &=luaval_to_color(tolua_S, 3, &arg1, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } - ax::Color4B arg2; - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); + ax::Color arg2; + ok &=luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidTriangle"); if (!ok) { break; } double arg3; @@ -53667,7 +53586,7 @@ int lua_ax_base_DrawNode_clear(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -53714,7 +53633,7 @@ int lua_ax_base_DrawNode_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -53761,7 +53680,7 @@ int lua_ax_base_DrawNode_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -53811,7 +53730,7 @@ int lua_ax_base_DrawNode_setIsolated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -53861,7 +53780,7 @@ int lua_ax_base_DrawNode_isIsolated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -53929,7 +53848,7 @@ int lua_ax_base_DrawNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -53978,7 +53897,6 @@ int lua_register_ax_base_DrawNode(lua_State* tolua_S) tolua_function(tolua_S,"drawSolidRect",lua_ax_base_DrawNode_drawSolidRect); tolua_function(tolua_S,"drawSolidCircle",lua_ax_base_DrawNode_drawSolidCircle); tolua_function(tolua_S,"drawPie",lua_ax_base_DrawNode_drawPie); - tolua_function(tolua_S,"setIsConvex",lua_ax_base_DrawNode_setIsConvex); tolua_function(tolua_S,"drawSegment",lua_ax_base_DrawNode_drawSegment); tolua_function(tolua_S,"drawColoredTriangle",lua_ax_base_DrawNode_drawColoredTriangle); tolua_function(tolua_S,"drawTriangle",lua_ax_base_DrawNode_drawTriangle); @@ -54022,7 +53940,7 @@ int lua_ax_base_Label_setTTFConfig(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::_ttfConfig arg0; @@ -54072,7 +53990,7 @@ int lua_ax_base_Label_getTTFConfig(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54258,7 +54176,7 @@ int lua_ax_base_Label_getBMFontFilePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54396,7 +54314,7 @@ int lua_ax_base_Label_setSystemFontName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -54446,7 +54364,7 @@ int lua_ax_base_Label_getSystemFontName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54493,7 +54411,7 @@ int lua_ax_base_Label_setSystemFontSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -54543,7 +54461,7 @@ int lua_ax_base_Label_getSystemFontSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54590,7 +54508,7 @@ int lua_ax_base_Label_requestSystemFontRefresh(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54637,7 +54555,7 @@ int lua_ax_base_Label_setString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -54687,7 +54605,7 @@ int lua_ax_base_Label_getString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54734,7 +54652,7 @@ int lua_ax_base_Label_getStringNumLines(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54781,7 +54699,7 @@ int lua_ax_base_Label_getStringLength(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54828,11 +54746,11 @@ int lua_ax_base_Label_setTextColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:setTextColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:setTextColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Label_setTextColor'", nullptr); @@ -54878,7 +54796,7 @@ int lua_ax_base_Label_getTextColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54886,7 +54804,7 @@ int lua_ax_base_Label_getTextColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTextColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Label:getTextColor",argc, 0); @@ -54925,7 +54843,7 @@ int lua_ax_base_Label_enableShadow(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -54936,11 +54854,11 @@ int lua_ax_base_Label_enableShadow(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 1) + if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableShadow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Label_enableShadow'", nullptr); @@ -54950,12 +54868,12 @@ int lua_ax_base_Label_enableShadow(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { - ax::Color4B arg0; + ax::Color32 arg0; ax::Vec2 arg1; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableShadow"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.Label:enableShadow"); if(!ok) @@ -54967,13 +54885,13 @@ int lua_ax_base_Label_enableShadow(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 3) + if (argc == 3) { - ax::Color4B arg0; + ax::Color32 arg0; ax::Vec2 arg1; int arg2; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableShadow"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.Label:enableShadow"); @@ -55023,11 +54941,11 @@ int lua_ax_base_Label_enableOutline(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableOutline"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableOutline"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Label_enableOutline'", nullptr); @@ -55037,12 +54955,12 @@ int lua_ax_base_Label_enableOutline(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { - ax::Color4B arg0; + ax::Color32 arg0; int arg1; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableOutline"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableOutline"); ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Label:enableOutline"); if(!ok) @@ -55090,11 +55008,11 @@ int lua_ax_base_Label_enableGlow(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.Label:enableGlow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.Label:enableGlow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Label_enableGlow'", nullptr); @@ -55140,7 +55058,7 @@ int lua_ax_base_Label_enableItalics(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55187,7 +55105,7 @@ int lua_ax_base_Label_enableBold(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55234,7 +55152,7 @@ int lua_ax_base_Label_enableUnderline(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55281,7 +55199,7 @@ int lua_ax_base_Label_enableStrikethrough(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55379,7 +55297,7 @@ int lua_ax_base_Label_isShadowEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55426,7 +55344,7 @@ int lua_ax_base_Label_getShadowOffset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55473,7 +55391,7 @@ int lua_ax_base_Label_getShadowBlurRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55520,7 +55438,7 @@ int lua_ax_base_Label_getShadowColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55528,7 +55446,7 @@ int lua_ax_base_Label_getShadowColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getShadowColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Label:getShadowColor",argc, 0); @@ -55567,7 +55485,7 @@ int lua_ax_base_Label_getOutlineSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55614,7 +55532,7 @@ int lua_ax_base_Label_getLabelEffectType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55661,7 +55579,7 @@ int lua_ax_base_Label_getEffectColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55669,7 +55587,7 @@ int lua_ax_base_Label_getEffectColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEffectColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Label:getEffectColor",argc, 0); @@ -55767,7 +55685,7 @@ int lua_ax_base_Label_getTextAlignment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55814,7 +55732,7 @@ int lua_ax_base_Label_setHorizontalAlignment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextHAlignment arg0; @@ -55864,7 +55782,7 @@ int lua_ax_base_Label_getHorizontalAlignment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -55911,7 +55829,7 @@ int lua_ax_base_Label_setVerticalAlignment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextVAlignment arg0; @@ -55961,7 +55879,7 @@ int lua_ax_base_Label_getVerticalAlignment(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56008,7 +55926,7 @@ int lua_ax_base_Label_setLineBreakWithoutSpace(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -56058,7 +55976,7 @@ int lua_ax_base_Label_setMaxLineWidth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -56108,7 +56026,7 @@ int lua_ax_base_Label_getMaxLineWidth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56155,7 +56073,7 @@ int lua_ax_base_Label_setTTFFaceSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -56205,7 +56123,7 @@ int lua_ax_base_Label_getTTFFaceSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56252,7 +56170,7 @@ int lua_ax_base_Label_setBMFontSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -56302,7 +56220,7 @@ int lua_ax_base_Label_getBMFontSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56349,7 +56267,7 @@ int lua_ax_base_Label_enableWrap(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -56399,7 +56317,7 @@ int lua_ax_base_Label_isWrapEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56446,7 +56364,7 @@ int lua_ax_base_Label_setOverflow(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Label::Overflow arg0; @@ -56496,7 +56414,7 @@ int lua_ax_base_Label_getOverflow(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56543,7 +56461,7 @@ int lua_ax_base_Label_setWidth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -56593,7 +56511,7 @@ int lua_ax_base_Label_getWidth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56640,7 +56558,7 @@ int lua_ax_base_Label_setHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -56690,7 +56608,7 @@ int lua_ax_base_Label_getHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56737,7 +56655,7 @@ int lua_ax_base_Label_setDimensions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -56790,7 +56708,7 @@ int lua_ax_base_Label_getDimensions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56837,7 +56755,7 @@ int lua_ax_base_Label_updateContent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -56884,7 +56802,7 @@ int lua_ax_base_Label_getLetter(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -56934,7 +56852,7 @@ int lua_ax_base_Label_setClipMarginEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -56984,7 +56902,7 @@ int lua_ax_base_Label_isClipMarginEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57031,7 +56949,7 @@ int lua_ax_base_Label_setLineHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -57081,7 +56999,7 @@ int lua_ax_base_Label_getLineHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57128,7 +57046,7 @@ int lua_ax_base_Label_setLineSpacing(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -57178,7 +57096,7 @@ int lua_ax_base_Label_getLineSpacing(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57225,7 +57143,7 @@ int lua_ax_base_Label_getLabelType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57272,7 +57190,7 @@ int lua_ax_base_Label_getRenderingFontSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57319,7 +57237,7 @@ int lua_ax_base_Label_setAdditionalKerning(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -57369,7 +57287,7 @@ int lua_ax_base_Label_getAdditionalKerning(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57416,7 +57334,7 @@ int lua_ax_base_Label_getFontAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57463,7 +57381,7 @@ int lua_ax_base_Label_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -57510,7 +57428,7 @@ int lua_ax_base_Label_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -57560,7 +57478,7 @@ int lua_ax_base_Label_removeAllChildrenWithCleanup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -57930,7 +57848,7 @@ int lua_ax_base_Label_createWithBMFont(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 6) { @@ -57958,7 +57876,7 @@ int lua_ax_base_Label_createWithBMFont(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 2) { @@ -57974,7 +57892,7 @@ int lua_ax_base_Label_createWithBMFont(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -57993,7 +57911,7 @@ int lua_ax_base_Label_createWithBMFont(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -58015,7 +57933,7 @@ int lua_ax_base_Label_createWithBMFont(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -58062,7 +57980,7 @@ int lua_ax_base_Label_createWithCharMap(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 4) { @@ -58084,7 +58002,7 @@ int lua_ax_base_Label_createWithCharMap(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -58106,7 +58024,7 @@ int lua_ax_base_Label_createWithCharMap(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -58350,7 +58268,7 @@ int lua_ax_base_LabelAtlas_setString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -58400,7 +58318,7 @@ int lua_ax_base_LabelAtlas_getString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -58435,7 +58353,7 @@ int lua_ax_base_LabelAtlas_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -58451,7 +58369,7 @@ int lua_ax_base_LabelAtlas_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -58476,7 +58394,7 @@ int lua_ax_base_LabelAtlas_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -58522,7 +58440,7 @@ int lua_ax_base_LabelAtlas_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -58596,7 +58514,7 @@ int lua_ax_base_Sprite_getBatchNode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -58643,7 +58561,7 @@ int lua_ax_base_Sprite_setBatchNode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteBatchNode* arg0; @@ -58748,7 +58666,7 @@ int lua_ax_base_Sprite_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -58858,7 +58776,7 @@ int lua_ax_base_Sprite_setVertexRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -58908,7 +58826,7 @@ int lua_ax_base_Sprite_setCenterRectNormalized(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -58958,7 +58876,7 @@ int lua_ax_base_Sprite_getCenterRectNormalized(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59005,7 +58923,7 @@ int lua_ax_base_Sprite_setCenterRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -59055,7 +58973,7 @@ int lua_ax_base_Sprite_getCenterRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59157,7 +59075,7 @@ int lua_ax_base_Sprite_isFrameDisplayed(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -59207,7 +59125,7 @@ int lua_ax_base_Sprite_getSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59254,7 +59172,7 @@ int lua_ax_base_Sprite_setDisplayFrameWithAnimationName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; unsigned int arg1; @@ -59307,7 +59225,7 @@ int lua_ax_base_Sprite_isDirty(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59354,7 +59272,7 @@ int lua_ax_base_Sprite_setDirty(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -59404,7 +59322,7 @@ int lua_ax_base_Sprite_removeAllChildrenWithCleanup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -59454,7 +59372,7 @@ int lua_ax_base_Sprite_isTextureRectRotated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59501,7 +59419,7 @@ int lua_ax_base_Sprite_getAtlasIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59548,7 +59466,7 @@ int lua_ax_base_Sprite_setAtlasIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -59598,7 +59516,7 @@ int lua_ax_base_Sprite_getTextureRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59645,7 +59563,7 @@ int lua_ax_base_Sprite_getTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59692,7 +59610,7 @@ int lua_ax_base_Sprite_setTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextureAtlas* arg0; @@ -59742,7 +59660,7 @@ int lua_ax_base_Sprite_getOffsetPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59789,7 +59707,7 @@ int lua_ax_base_Sprite_isFlippedX(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59836,7 +59754,7 @@ int lua_ax_base_Sprite_setFlippedX(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -59886,7 +59804,7 @@ int lua_ax_base_Sprite_isFlippedY(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -59933,7 +59851,7 @@ int lua_ax_base_Sprite_setFlippedY(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -59983,7 +59901,7 @@ int lua_ax_base_Sprite_setStretchEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -60033,7 +59951,7 @@ int lua_ax_base_Sprite_isStretchEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -60080,7 +59998,7 @@ int lua_ax_base_Sprite_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -60130,7 +60048,7 @@ int lua_ax_base_Sprite_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -60177,7 +60095,7 @@ int lua_ax_base_Sprite_getResourceType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -60224,7 +60142,7 @@ int lua_ax_base_Sprite_getResourceName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -60350,7 +60268,7 @@ int lua_ax_base_Sprite_initWithSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -60400,7 +60318,7 @@ int lua_ax_base_Sprite_initWithSpriteFrameName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -60451,7 +60369,7 @@ int lua_ax_base_Sprite_initWithFile(lua_State* tolua_S) ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.Sprite:initWithFile"); if (!ok) { break; } - ax::backend::PixelFormat arg1; + ax::rhi::PixelFormat arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Sprite:initWithFile"); if (!ok) { break; } @@ -60525,7 +60443,7 @@ int lua_ax_base_Sprite_initWithImageData(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Data arg0; std::string_view arg1; @@ -60578,7 +60496,7 @@ int lua_ax_base_Sprite_setVertexLayout(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -60625,7 +60543,7 @@ int lua_ax_base_Sprite_setAutoUpdatePS(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -60675,7 +60593,7 @@ int lua_ax_base_Sprite_setAutoSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -60713,7 +60631,7 @@ int lua_ax_base_Sprite_createWithTexture(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -60729,7 +60647,7 @@ int lua_ax_base_Sprite_createWithTexture(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -60748,7 +60666,7 @@ int lua_ax_base_Sprite_createWithTexture(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -60854,7 +60772,7 @@ int lua_ax_base_Sprite_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61023,7 +60941,7 @@ int lua_ax_base_LayerColor_changeWidth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -61073,7 +60991,7 @@ int lua_ax_base_LayerColor_changeHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -61123,7 +61041,7 @@ int lua_ax_base_LayerColor_changeWidthAndHeight(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -61173,8 +61091,8 @@ int lua_ax_base_LayerColor_initWithColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; do{ if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerColor:initWithColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerColor:initWithColor"); if (!ok) { break; } bool ret = cobj->initWithColor(arg0); @@ -61185,8 +61103,8 @@ int lua_ax_base_LayerColor_initWithColor(lua_State* tolua_S) ok = true; do{ if (argc == 3) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerColor:initWithColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerColor:initWithColor"); if (!ok) { break; } double arg1; @@ -61227,12 +61145,12 @@ int lua_ax_base_LayerColor_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 3) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerColor:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerColor:create"); if (!ok) { break; } double arg1; ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.LayerColor:create"); @@ -61246,7 +61164,7 @@ int lua_ax_base_LayerColor_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 0) { @@ -61256,12 +61174,12 @@ int lua_ax_base_LayerColor_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerColor:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerColor:create"); if (!ok) { break; } ax::LayerColor* ret = ax::LayerColor::create(arg0); object_to_luaval(tolua_S, "ax.LayerColor",(ax::LayerColor*)ret); @@ -61290,7 +61208,7 @@ int lua_ax_base_LayerColor_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61365,7 +61283,7 @@ int lua_ax_base_LayerGradient_setCompressedInterpolation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -61415,7 +61333,7 @@ int lua_ax_base_LayerGradient_isCompressedInterpolation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61462,11 +61380,11 @@ int lua_ax_base_LayerGradient_setStartColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.LayerGradient:setStartColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:setStartColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerGradient_setStartColor'", nullptr); @@ -61512,7 +61430,7 @@ int lua_ax_base_LayerGradient_getStartColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61520,7 +61438,7 @@ int lua_ax_base_LayerGradient_getStartColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getStartColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerGradient:getStartColor",argc, 0); @@ -61559,11 +61477,11 @@ int lua_ax_base_LayerGradient_setEndColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.LayerGradient:setEndColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:setEndColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerGradient_setEndColor'", nullptr); @@ -61609,7 +61527,7 @@ int lua_ax_base_LayerGradient_getEndColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61617,7 +61535,7 @@ int lua_ax_base_LayerGradient_getEndColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEndColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerGradient:getEndColor",argc, 0); @@ -61656,7 +61574,7 @@ int lua_ax_base_LayerGradient_setStartOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { uint16_t arg0; @@ -61706,7 +61624,7 @@ int lua_ax_base_LayerGradient_getStartOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61753,7 +61671,7 @@ int lua_ax_base_LayerGradient_setEndOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { uint16_t arg0; @@ -61803,7 +61721,7 @@ int lua_ax_base_LayerGradient_getEndOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61850,7 +61768,7 @@ int lua_ax_base_LayerGradient_setVector(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -61900,7 +61818,7 @@ int lua_ax_base_LayerGradient_getVector(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -61944,12 +61862,12 @@ int lua_ax_base_LayerGradient_initWithColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; do{ if (argc == 3) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerGradient:initWithColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:initWithColor"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerGradient:initWithColor"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerGradient:initWithColor"); if (!ok) { break; } ax::Vec2 arg2; @@ -61964,12 +61882,12 @@ int lua_ax_base_LayerGradient_initWithColor(lua_State* tolua_S) ok = true; do{ if (argc == 2) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerGradient:initWithColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:initWithColor"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerGradient:initWithColor"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerGradient:initWithColor"); if (!ok) { break; } bool ret = cobj->initWithColor(arg0, arg1); @@ -62002,15 +61920,15 @@ int lua_ax_base_LayerGradient_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerGradient:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:create"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerGradient:create"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerGradient:create"); if (!ok) { break; } ax::LayerGradient* ret = ax::LayerGradient::create(arg0, arg1); object_to_luaval(tolua_S, "ax.LayerGradient",(ax::LayerGradient*)ret); @@ -62018,7 +61936,7 @@ int lua_ax_base_LayerGradient_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 0) { @@ -62028,15 +61946,15 @@ int lua_ax_base_LayerGradient_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerGradient:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerGradient:create"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerGradient:create"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerGradient:create"); if (!ok) { break; } ax::Vec2 arg2; ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.LayerGradient:create"); @@ -62068,7 +61986,7 @@ int lua_ax_base_LayerGradient_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62152,7 +62070,7 @@ int lua_ax_base_LayerRadialGradient_setStartOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { uint16_t arg0; @@ -62202,7 +62120,7 @@ int lua_ax_base_LayerRadialGradient_getStartOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62249,7 +62167,7 @@ int lua_ax_base_LayerRadialGradient_setEndOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { uint16_t arg0; @@ -62299,7 +62217,7 @@ int lua_ax_base_LayerRadialGradient_getEndOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62346,7 +62264,7 @@ int lua_ax_base_LayerRadialGradient_setRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -62396,7 +62314,7 @@ int lua_ax_base_LayerRadialGradient_getRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62443,7 +62361,7 @@ int lua_ax_base_LayerRadialGradient_setCenter(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -62493,7 +62411,7 @@ int lua_ax_base_LayerRadialGradient_getCenter(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62540,7 +62458,7 @@ int lua_ax_base_LayerRadialGradient_setExpand(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -62590,7 +62508,7 @@ int lua_ax_base_LayerRadialGradient_getExpand(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62616,14 +62534,18 @@ int lua_ax_base_LayerRadialGradient_setStartColor(lua_State* tolua_S) int argc = 0; ax::LayerRadialGradient* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"ax.LayerRadialGradient",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::LayerRadialGradient*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { @@ -62631,32 +62553,23 @@ int lua_ax_base_LayerRadialGradient_setStartColor(lua_State* tolua_S) return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setStartColor"); - if (!ok) { break; } - cobj->setStartColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setStartColor"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Color32 arg0; - if (!ok) { break; } - cobj->setStartColor(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setStartColor"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerRadialGradient_setStartColor'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:setStartColor",argc, 1); + cobj->setStartColor(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:setStartColor",argc, 1); return 0; #if _AX_DEBUG >= 1 @@ -62692,7 +62605,7 @@ int lua_ax_base_LayerRadialGradient_getStartColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62700,7 +62613,7 @@ int lua_ax_base_LayerRadialGradient_getStartColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getStartColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:getStartColor",argc, 0); @@ -62713,7 +62626,7 @@ int lua_ax_base_LayerRadialGradient_getStartColor(lua_State* tolua_S) return 0; } -int lua_ax_base_LayerRadialGradient_getStartColor3B(lua_State* tolua_S) +int lua_ax_base_LayerRadialGradient_setEndColor(lua_State* tolua_S) { int argc = 0; ax::LayerRadialGradient* cobj = nullptr; @@ -62733,79 +62646,27 @@ int lua_ax_base_LayerRadialGradient_getStartColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_LayerRadialGradient_getStartColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_LayerRadialGradient_setEndColor'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Color32 arg0; + + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setEndColor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerRadialGradient_getStartColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerRadialGradient_setEndColor'", nullptr); return 0; } - auto&& ret = cobj->getStartColor3B(); - color3b_to_luaval(tolua_S, ret); + cobj->setEndColor(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:getStartColor3B",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_LayerRadialGradient_getStartColor3B'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_base_LayerRadialGradient_setEndColor(lua_State* tolua_S) -{ - int argc = 0; - ax::LayerRadialGradient* cobj = nullptr; - bool ok = true; -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.LayerRadialGradient",0,&tolua_err)) goto tolua_lerror; -#endif - cobj = (ax::LayerRadialGradient*)tolua_tousertype(tolua_S,1,0); -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_LayerRadialGradient_setEndColor'", nullptr); - return 0; - } -#endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setEndColor"); - - if (!ok) { break; } - cobj->setEndColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:setEndColor"); - - if (!ok) { break; } - cobj->setEndColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:setEndColor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:setEndColor",argc, 1); return 0; #if _AX_DEBUG >= 1 @@ -62841,7 +62702,7 @@ int lua_ax_base_LayerRadialGradient_getEndColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -62849,7 +62710,7 @@ int lua_ax_base_LayerRadialGradient_getEndColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEndColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:getEndColor",argc, 0); @@ -62862,53 +62723,6 @@ int lua_ax_base_LayerRadialGradient_getEndColor(lua_State* tolua_S) return 0; } -int lua_ax_base_LayerRadialGradient_getEndColor3B(lua_State* tolua_S) -{ - int argc = 0; - ax::LayerRadialGradient* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.LayerRadialGradient",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::LayerRadialGradient*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_LayerRadialGradient_getEndColor3B'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_LayerRadialGradient_getEndColor3B'", nullptr); - return 0; - } - auto&& ret = cobj->getEndColor3B(); - color3b_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.LayerRadialGradient:getEndColor3B",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_LayerRadialGradient_getEndColor3B'.",&tolua_err); -#endif - - return 0; -} int lua_ax_base_LayerRadialGradient_setBlendFunc(lua_State* tolua_S) { int argc = 0; @@ -62935,7 +62749,7 @@ int lua_ax_base_LayerRadialGradient_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -62985,7 +62799,7 @@ int lua_ax_base_LayerRadialGradient_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63032,17 +62846,17 @@ int lua_ax_base_LayerRadialGradient_initWithColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 5) { - ax::Color4B arg0; - ax::Color4B arg1; + ax::Color32 arg0; + ax::Color32 arg1; double arg2; ax::Vec2 arg3; double arg4; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:initWithColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerRadialGradient:initWithColor"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerRadialGradient:initWithColor"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerRadialGradient:initWithColor"); ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.LayerRadialGradient:initWithColor"); @@ -63082,7 +62896,7 @@ int lua_ax_base_LayerRadialGradient_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 0) { @@ -63092,15 +62906,15 @@ int lua_ax_base_LayerRadialGradient_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ax.LayerRadialGradient:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.LayerRadialGradient:create"); if (!ok) { break; } - ax::Color4B arg1; - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "ax.LayerRadialGradient:create"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.LayerRadialGradient:create"); if (!ok) { break; } double arg2; ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.LayerRadialGradient:create"); @@ -63138,7 +62952,7 @@ int lua_ax_base_LayerRadialGradient_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63187,10 +63001,8 @@ int lua_register_ax_base_LayerRadialGradient(lua_State* tolua_S) tolua_function(tolua_S,"getExpand",lua_ax_base_LayerRadialGradient_getExpand); tolua_function(tolua_S,"setStartColor",lua_ax_base_LayerRadialGradient_setStartColor); tolua_function(tolua_S,"getStartColor",lua_ax_base_LayerRadialGradient_getStartColor); - tolua_function(tolua_S,"getStartColor3B",lua_ax_base_LayerRadialGradient_getStartColor3B); tolua_function(tolua_S,"setEndColor",lua_ax_base_LayerRadialGradient_setEndColor); tolua_function(tolua_S,"getEndColor",lua_ax_base_LayerRadialGradient_getEndColor); - tolua_function(tolua_S,"getEndColor3B",lua_ax_base_LayerRadialGradient_getEndColor3B); tolua_function(tolua_S,"setBlendFunc",lua_ax_base_LayerRadialGradient_setBlendFunc); tolua_function(tolua_S,"getBlendFunc",lua_ax_base_LayerRadialGradient_getBlendFunc); tolua_function(tolua_S,"initWithColor",lua_ax_base_LayerRadialGradient_initWithColor); @@ -63228,7 +63040,7 @@ int lua_ax_base_LayerMultiplex_addLayer(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -63337,7 +63149,7 @@ int lua_ax_base_LayerMultiplex_switchToAndReleaseMe(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -63387,7 +63199,7 @@ int lua_ax_base_LayerMultiplex_initWithArray(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -63424,7 +63236,7 @@ int lua_ax_base_LayerMultiplex_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63498,7 +63310,7 @@ int lua_ax_base_MenuItem_rect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63545,7 +63357,7 @@ int lua_ax_base_MenuItem_activate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63592,7 +63404,7 @@ int lua_ax_base_MenuItem_selected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63639,7 +63451,7 @@ int lua_ax_base_MenuItem_unselected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63686,7 +63498,7 @@ int lua_ax_base_MenuItem_isEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63733,7 +63545,7 @@ int lua_ax_base_MenuItem_setEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -63783,7 +63595,7 @@ int lua_ax_base_MenuItem_isSelected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63817,7 +63629,7 @@ int lua_ax_base_MenuItem_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63894,7 +63706,7 @@ int lua_ax_base_MenuItemLabel_setString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -63944,7 +63756,7 @@ int lua_ax_base_MenuItemLabel_getString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63991,7 +63803,7 @@ int lua_ax_base_MenuItemLabel_getDisabledColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -63999,7 +63811,7 @@ int lua_ax_base_MenuItemLabel_getDisabledColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getDisabledColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.MenuItemLabel:getDisabledColor",argc, 0); @@ -64038,11 +63850,11 @@ int lua_ax_base_MenuItemLabel_setDisabledColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.MenuItemLabel:setDisabledColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.MenuItemLabel:setDisabledColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MenuItemLabel_setDisabledColor'", nullptr); @@ -64088,7 +63900,7 @@ int lua_ax_base_MenuItemLabel_getLabel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64135,7 +63947,7 @@ int lua_ax_base_MenuItemLabel_setLabel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -64185,7 +63997,7 @@ int lua_ax_base_MenuItemLabel_initWithLabel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Node* arg0; std::function arg1; @@ -64229,7 +64041,7 @@ int lua_ax_base_MenuItemLabel_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64306,7 +64118,7 @@ int lua_ax_base_MenuItemAtlasFont_initWithString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 6) + if (argc == 6) { std::string_view arg0; std::string_view arg1; @@ -64362,7 +64174,7 @@ int lua_ax_base_MenuItemAtlasFont_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64433,7 +64245,7 @@ int lua_ax_base_MenuItemFont_setFontSizeObj(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -64483,7 +64295,7 @@ int lua_ax_base_MenuItemFont_getFontSizeObj(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64530,7 +64342,7 @@ int lua_ax_base_MenuItemFont_setFontNameObj(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -64580,7 +64392,7 @@ int lua_ax_base_MenuItemFont_getFontNameObj(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64627,7 +64439,7 @@ int lua_ax_base_MenuItemFont_initWithString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::function arg1; @@ -64811,7 +64623,7 @@ int lua_ax_base_MenuItemFont_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64890,7 +64702,7 @@ int lua_ax_base_MenuItemSprite_getNormalImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -64937,7 +64749,7 @@ int lua_ax_base_MenuItemSprite_setNormalImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -64987,7 +64799,7 @@ int lua_ax_base_MenuItemSprite_getSelectedImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65034,7 +64846,7 @@ int lua_ax_base_MenuItemSprite_setSelectedImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -65084,7 +64896,7 @@ int lua_ax_base_MenuItemSprite_getDisabledImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65131,7 +64943,7 @@ int lua_ax_base_MenuItemSprite_setDisabledImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -65181,7 +64993,7 @@ int lua_ax_base_MenuItemSprite_selected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65228,7 +65040,7 @@ int lua_ax_base_MenuItemSprite_unselected(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65275,7 +65087,7 @@ int lua_ax_base_MenuItemSprite_setEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -65325,7 +65137,7 @@ int lua_ax_base_MenuItemSprite_initWithNormalSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { ax::Node* arg0; ax::Node* arg1; @@ -65375,7 +65187,7 @@ int lua_ax_base_MenuItemSprite_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65455,7 +65267,7 @@ int lua_ax_base_MenuItemImage_setNormalSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -65505,7 +65317,7 @@ int lua_ax_base_MenuItemImage_setSelectedSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -65555,7 +65367,7 @@ int lua_ax_base_MenuItemImage_setDisabledSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -65605,7 +65417,7 @@ int lua_ax_base_MenuItemImage_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65652,7 +65464,7 @@ int lua_ax_base_MenuItemImage_initWithNormalImage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { std::string_view arg0; std::string_view arg1; @@ -65702,7 +65514,7 @@ int lua_ax_base_MenuItemImage_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65777,7 +65589,7 @@ int lua_ax_base_MenuItemToggle_addSubItem(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::MenuItem* arg0; @@ -65827,7 +65639,7 @@ int lua_ax_base_MenuItemToggle_getSelectedItem(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65874,7 +65686,7 @@ int lua_ax_base_MenuItemToggle_getSelectedIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -65921,7 +65733,7 @@ int lua_ax_base_MenuItemToggle_setSelectedIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -65971,7 +65783,7 @@ int lua_ax_base_MenuItemToggle_setSubItems(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -66021,7 +65833,7 @@ int lua_ax_base_MenuItemToggle_initWithItem(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::MenuItem* arg0; @@ -66058,7 +65870,7 @@ int lua_ax_base_MenuItemToggle_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66134,7 +65946,7 @@ int lua_ax_base_Menu_alignItemsVertically(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66181,7 +65993,7 @@ int lua_ax_base_Menu_alignItemsVerticallyWithPadding(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -66231,7 +66043,7 @@ int lua_ax_base_Menu_alignItemsHorizontally(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66278,7 +66090,7 @@ int lua_ax_base_Menu_alignItemsHorizontallyWithPadding(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -66328,7 +66140,7 @@ int lua_ax_base_Menu_isEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66375,7 +66187,7 @@ int lua_ax_base_Menu_setEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -66425,7 +66237,7 @@ int lua_ax_base_Menu_initWithArray(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -66462,7 +66274,7 @@ int lua_ax_base_Menu_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66539,7 +66351,7 @@ int lua_ax_base_MotionStreak_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66586,7 +66398,7 @@ int lua_ax_base_MotionStreak_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -66636,7 +66448,7 @@ int lua_ax_base_MotionStreak_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -66686,7 +66498,7 @@ int lua_ax_base_MotionStreak_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66733,11 +66545,11 @@ int lua_ax_base_MotionStreak_tintWithColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.MotionStreak:tintWithColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.MotionStreak:tintWithColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MotionStreak_tintWithColor'", nullptr); @@ -66783,7 +66595,7 @@ int lua_ax_base_MotionStreak_reset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66830,7 +66642,7 @@ int lua_ax_base_MotionStreak_isFastMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66877,7 +66689,7 @@ int lua_ax_base_MotionStreak_setFastMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -66927,7 +66739,7 @@ int lua_ax_base_MotionStreak_getStroke(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -66974,7 +66786,7 @@ int lua_ax_base_MotionStreak_setStroke(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -67024,7 +66836,7 @@ int lua_ax_base_MotionStreak_isStartingPositionInitialized(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -67071,7 +66883,7 @@ int lua_ax_base_MotionStreak_setStartingPositionInitialized(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -67130,8 +66942,8 @@ int lua_ax_base_MotionStreak_initWithFade(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak:initWithFade"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak:initWithFade"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak:initWithFade"); if (!ok) { break; } ax::Texture2D* arg4; @@ -67158,8 +66970,8 @@ int lua_ax_base_MotionStreak_initWithFade(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak:initWithFade"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak:initWithFade"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak:initWithFade"); if (!ok) { break; } std::string_view arg4; @@ -67196,7 +67008,7 @@ int lua_ax_base_MotionStreak_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 5) { @@ -67209,8 +67021,8 @@ int lua_ax_base_MotionStreak_create(lua_State* tolua_S) double arg2; ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak:create"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak:create"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak:create"); if (!ok) { break; } ax::Texture2D* arg4; ok &= luaval_to_object(tolua_S, 6, "ax.Texture2D",&arg4, "ax.MotionStreak:create"); @@ -67221,7 +67033,7 @@ int lua_ax_base_MotionStreak_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -67234,8 +67046,8 @@ int lua_ax_base_MotionStreak_create(lua_State* tolua_S) double arg2; ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak:create"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak:create"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak:create"); if (!ok) { break; } std::string_view arg4; ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "ax.MotionStreak:create"); @@ -67267,7 +67079,7 @@ int lua_ax_base_MotionStreak_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -67398,7 +67210,7 @@ int lua_ax_base_NodeGrid_setGrid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::GridBase* arg0; @@ -67448,7 +67260,7 @@ int lua_ax_base_NodeGrid_setTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -67498,7 +67310,7 @@ int lua_ax_base_NodeGrid_setGridRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -67548,7 +67360,7 @@ int lua_ax_base_NodeGrid_getGridRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -67583,7 +67395,7 @@ int lua_ax_base_NodeGrid_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 1) { @@ -67596,7 +67408,7 @@ int lua_ax_base_NodeGrid_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 0) { @@ -67627,7 +67439,7 @@ int lua_ax_base_NodeGrid_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -67703,7 +67515,7 @@ int lua_ax_base_ParticleBatchNode_insertChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ParticleSystem* arg0; int arg1; @@ -67756,7 +67568,7 @@ int lua_ax_base_ParticleBatchNode_removeChildAtIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { int arg0; bool arg1; @@ -67809,7 +67621,7 @@ int lua_ax_base_ParticleBatchNode_removeAllChildrenWithCleanup(lua_State* tolua_ #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -67859,7 +67671,7 @@ int lua_ax_base_ParticleBatchNode_disableParticle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -67909,7 +67721,7 @@ int lua_ax_base_ParticleBatchNode_getTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -67956,7 +67768,7 @@ int lua_ax_base_ParticleBatchNode_setTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextureAtlas* arg0; @@ -68006,7 +67818,7 @@ int lua_ax_base_ParticleBatchNode_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68053,7 +67865,7 @@ int lua_ax_base_ParticleBatchNode_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -68103,7 +67915,7 @@ int lua_ax_base_ParticleBatchNode_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -68153,7 +67965,7 @@ int lua_ax_base_ParticleBatchNode_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68200,7 +68012,7 @@ int lua_ax_base_ParticleBatchNode_initWithTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Texture2D* arg0; int arg1; @@ -68253,7 +68065,7 @@ int lua_ax_base_ParticleBatchNode_initWithFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; int arg1; @@ -68395,7 +68207,7 @@ int lua_ax_base_ParticleBatchNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68498,7 +68310,7 @@ int lua_ax_base_SpriteFrameCache_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68676,7 +68488,7 @@ int lua_ax_base_SpriteFrameCache_addSpriteFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::SpriteFrame* arg0; std::string_view arg1; @@ -68729,7 +68541,7 @@ int lua_ax_base_SpriteFrameCache_isSpriteFramesWithFileLoaded(lua_State* tolua_S #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -68779,7 +68591,7 @@ int lua_ax_base_SpriteFrameCache_removeSpriteFrames(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68826,7 +68638,7 @@ int lua_ax_base_SpriteFrameCache_removeUnusedSpriteFrames(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68873,7 +68685,7 @@ int lua_ax_base_SpriteFrameCache_removeUnusedSpriteSheets(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -68920,7 +68732,7 @@ int lua_ax_base_SpriteFrameCache_removeSpriteFrameByName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -68970,7 +68782,7 @@ int lua_ax_base_SpriteFrameCache_removeSpriteFramesFromFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69020,7 +68832,7 @@ int lua_ax_base_SpriteFrameCache_removeSpriteFramesFromFileContent(lua_State* to #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69070,7 +68882,7 @@ int lua_ax_base_SpriteFrameCache_removeSpriteFramesFromTexture(lua_State* tolua_ #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -69120,7 +68932,7 @@ int lua_ax_base_SpriteFrameCache_getSpriteFrameByName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69170,7 +68982,7 @@ int lua_ax_base_SpriteFrameCache_reloadTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69220,7 +69032,7 @@ int lua_ax_base_SpriteFrameCache_findFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69270,7 +69082,7 @@ int lua_ax_base_SpriteFrameCache_getSpriteFrameName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -69320,7 +69132,7 @@ int lua_ax_base_SpriteFrameCache_eraseFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -69370,7 +69182,7 @@ int lua_ax_base_SpriteFrameCache_addSpriteFrameCapInset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::SpriteFrame* arg0; ax::Rect arg1; @@ -69426,7 +69238,7 @@ int lua_ax_base_SpriteFrameCache_deregisterSpriteSheetLoader(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -69476,7 +69288,7 @@ int lua_ax_base_SpriteFrameCache_getSpriteSheetLoader(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -69634,7 +69446,7 @@ int lua_ax_base_ParticleData_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -69684,7 +69496,7 @@ int lua_ax_base_ParticleData_release(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -69731,7 +69543,7 @@ int lua_ax_base_ParticleData_getMaxCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -69778,7 +69590,7 @@ int lua_ax_base_ParticleData_copyParticle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { int arg0; int arg1; @@ -69818,7 +69630,7 @@ int lua_ax_base_ParticleData_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70098,8 +69910,8 @@ int lua_ax_base_ParticleEmissionMaskCache_getEmissionMask(lua_State* tolua_S) ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ParticleEmissionMaskCache:getEmissionMask"); if (!ok) { break; } - const ax::ParticleEmissionMaskDescriptor& ret = cobj->getEmissionMask(arg0); - #pragma warning NO CONVERSION FROM NATIVE FOR ParticleEmissionMaskDescriptor; + const ax::ParticleEmissionMaskDesc& ret = cobj->getEmissionMask(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR ParticleEmissionMaskDesc; return 1; } }while(0); @@ -70110,8 +69922,8 @@ int lua_ax_base_ParticleEmissionMaskCache_getEmissionMask(lua_State* tolua_S) ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.ParticleEmissionMaskCache:getEmissionMask"); if (!ok) { break; } - const ax::ParticleEmissionMaskDescriptor& ret = cobj->getEmissionMask(arg0); - #pragma warning NO CONVERSION FROM NATIVE FOR ParticleEmissionMaskDescriptor; + const ax::ParticleEmissionMaskDesc& ret = cobj->getEmissionMask(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR ParticleEmissionMaskDesc; return 1; } }while(0); @@ -70152,7 +69964,7 @@ int lua_ax_base_ParticleEmissionMaskCache_removeMask(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -70202,7 +70014,7 @@ int lua_ax_base_ParticleEmissionMaskCache_removeAllMasks(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70307,7 +70119,7 @@ int lua_ax_base_ParticleSystem_addParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -70321,7 +70133,7 @@ int lua_ax_base_ParticleSystem_addParticles(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { int arg0; int arg1; @@ -70338,7 +70150,7 @@ int lua_ax_base_ParticleSystem_addParticles(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 3) + if (argc == 3) { int arg0; int arg1; @@ -70394,7 +70206,7 @@ int lua_ax_base_ParticleSystem_stopSystem(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70441,7 +70253,7 @@ int lua_ax_base_ParticleSystem_resetSystem(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70488,7 +70300,7 @@ int lua_ax_base_ParticleSystem_isFull(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70535,7 +70347,7 @@ int lua_ax_base_ParticleSystem_updateParticleQuads(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70582,7 +70394,7 @@ int lua_ax_base_ParticleSystem_postStep(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70629,7 +70441,7 @@ int lua_ax_base_ParticleSystem_updateWithNoTime(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70676,7 +70488,7 @@ int lua_ax_base_ParticleSystem_isAutoRemoveOnFinish(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70723,7 +70535,7 @@ int lua_ax_base_ParticleSystem_setAutoRemoveOnFinish(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -70773,7 +70585,7 @@ int lua_ax_base_ParticleSystem_getGravity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70820,7 +70632,7 @@ int lua_ax_base_ParticleSystem_setGravity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -70870,7 +70682,7 @@ int lua_ax_base_ParticleSystem_getSpeed(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -70917,7 +70729,7 @@ int lua_ax_base_ParticleSystem_setSpeed(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -70967,7 +70779,7 @@ int lua_ax_base_ParticleSystem_getSpeedVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71014,7 +70826,7 @@ int lua_ax_base_ParticleSystem_setSpeedVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71064,7 +70876,7 @@ int lua_ax_base_ParticleSystem_getTangentialAccel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71111,7 +70923,7 @@ int lua_ax_base_ParticleSystem_setTangentialAccel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71161,7 +70973,7 @@ int lua_ax_base_ParticleSystem_getTangentialAccelVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71208,7 +71020,7 @@ int lua_ax_base_ParticleSystem_setTangentialAccelVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71258,7 +71070,7 @@ int lua_ax_base_ParticleSystem_getRadialAccel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71305,7 +71117,7 @@ int lua_ax_base_ParticleSystem_setRadialAccel(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71355,7 +71167,7 @@ int lua_ax_base_ParticleSystem_getRadialAccelVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71402,7 +71214,7 @@ int lua_ax_base_ParticleSystem_setRadialAccelVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71452,7 +71264,7 @@ int lua_ax_base_ParticleSystem_getRotationIsDir(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71499,7 +71311,7 @@ int lua_ax_base_ParticleSystem_setRotationIsDir(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -71549,7 +71361,7 @@ int lua_ax_base_ParticleSystem_getStartRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71596,7 +71408,7 @@ int lua_ax_base_ParticleSystem_setStartRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71646,7 +71458,7 @@ int lua_ax_base_ParticleSystem_getStartRadiusVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71693,7 +71505,7 @@ int lua_ax_base_ParticleSystem_setStartRadiusVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71743,7 +71555,7 @@ int lua_ax_base_ParticleSystem_getEndRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71790,7 +71602,7 @@ int lua_ax_base_ParticleSystem_setEndRadius(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71840,7 +71652,7 @@ int lua_ax_base_ParticleSystem_getEndRadiusVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71887,7 +71699,7 @@ int lua_ax_base_ParticleSystem_setEndRadiusVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -71937,7 +71749,7 @@ int lua_ax_base_ParticleSystem_getRotatePerSecond(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -71984,7 +71796,7 @@ int lua_ax_base_ParticleSystem_setRotatePerSecond(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -72034,7 +71846,7 @@ int lua_ax_base_ParticleSystem_getRotatePerSecondVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72081,7 +71893,7 @@ int lua_ax_base_ParticleSystem_setRotatePerSecondVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -72131,7 +71943,7 @@ int lua_ax_base_ParticleSystem_isActive(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72178,7 +71990,7 @@ int lua_ax_base_ParticleSystem_isBlendAdditive(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72225,7 +72037,7 @@ int lua_ax_base_ParticleSystem_setBlendAdditive(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -72275,7 +72087,7 @@ int lua_ax_base_ParticleSystem_getBatchNode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72322,7 +72134,7 @@ int lua_ax_base_ParticleSystem_setBatchNode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ParticleBatchNode* arg0; @@ -72372,7 +72184,7 @@ int lua_ax_base_ParticleSystem_getAtlasIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72419,7 +72231,7 @@ int lua_ax_base_ParticleSystem_setAtlasIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -72469,7 +72281,7 @@ int lua_ax_base_ParticleSystem_getParticleCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72516,7 +72328,7 @@ int lua_ax_base_ParticleSystem_getDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72563,7 +72375,7 @@ int lua_ax_base_ParticleSystem_setDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -72613,7 +72425,7 @@ int lua_ax_base_ParticleSystem_getSourcePosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72660,7 +72472,7 @@ int lua_ax_base_ParticleSystem_setSourcePosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -72710,7 +72522,7 @@ int lua_ax_base_ParticleSystem_getPosVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72757,7 +72569,7 @@ int lua_ax_base_ParticleSystem_setPosVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -72807,7 +72619,7 @@ int lua_ax_base_ParticleSystem_getLife(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72854,7 +72666,7 @@ int lua_ax_base_ParticleSystem_setLife(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -72904,7 +72716,7 @@ int lua_ax_base_ParticleSystem_getLifeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -72951,7 +72763,7 @@ int lua_ax_base_ParticleSystem_setLifeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73001,7 +72813,7 @@ int lua_ax_base_ParticleSystem_getAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73048,7 +72860,7 @@ int lua_ax_base_ParticleSystem_setAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73098,7 +72910,7 @@ int lua_ax_base_ParticleSystem_getAngleVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73145,7 +72957,7 @@ int lua_ax_base_ParticleSystem_setAngleVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73195,7 +73007,7 @@ int lua_ax_base_ParticleSystem_getEmitterMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73242,7 +73054,7 @@ int lua_ax_base_ParticleSystem_setEmitterMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ParticleSystem::Mode arg0; @@ -73292,7 +73104,7 @@ int lua_ax_base_ParticleSystem_getStartSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73339,7 +73151,7 @@ int lua_ax_base_ParticleSystem_setStartSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73389,7 +73201,7 @@ int lua_ax_base_ParticleSystem_getStartSizeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73436,7 +73248,7 @@ int lua_ax_base_ParticleSystem_setStartSizeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73486,7 +73298,7 @@ int lua_ax_base_ParticleSystem_getEndSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73533,7 +73345,7 @@ int lua_ax_base_ParticleSystem_setEndSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73583,7 +73395,7 @@ int lua_ax_base_ParticleSystem_getEndSizeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73630,7 +73442,7 @@ int lua_ax_base_ParticleSystem_setEndSizeVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -73680,7 +73492,7 @@ int lua_ax_base_ParticleSystem_getStartColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73688,7 +73500,7 @@ int lua_ax_base_ParticleSystem_getStartColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getStartColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:getStartColor",argc, 0); @@ -73727,11 +73539,11 @@ int lua_ax_base_ParticleSystem_setStartColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.ParticleSystem:setStartColor"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.ParticleSystem:setStartColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ParticleSystem_setStartColor'", nullptr); @@ -73777,7 +73589,7 @@ int lua_ax_base_ParticleSystem_getStartColorVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73785,7 +73597,7 @@ int lua_ax_base_ParticleSystem_getStartColorVar(lua_State* tolua_S) return 0; } auto&& ret = cobj->getStartColorVar(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:getStartColorVar",argc, 0); @@ -73824,11 +73636,11 @@ int lua_ax_base_ParticleSystem_setStartColorVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.ParticleSystem:setStartColorVar"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.ParticleSystem:setStartColorVar"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ParticleSystem_setStartColorVar'", nullptr); @@ -73874,7 +73686,7 @@ int lua_ax_base_ParticleSystem_getEndColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73882,7 +73694,7 @@ int lua_ax_base_ParticleSystem_getEndColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEndColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:getEndColor",argc, 0); @@ -73921,11 +73733,11 @@ int lua_ax_base_ParticleSystem_setEndColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.ParticleSystem:setEndColor"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.ParticleSystem:setEndColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ParticleSystem_setEndColor'", nullptr); @@ -73971,7 +73783,7 @@ int lua_ax_base_ParticleSystem_getEndColorVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -73979,7 +73791,7 @@ int lua_ax_base_ParticleSystem_getEndColorVar(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEndColorVar(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:getEndColorVar",argc, 0); @@ -74018,11 +73830,11 @@ int lua_ax_base_ParticleSystem_setEndColorVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.ParticleSystem:setEndColorVar"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.ParticleSystem:setEndColorVar"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ParticleSystem_setEndColorVar'", nullptr); @@ -74068,7 +73880,7 @@ int lua_ax_base_ParticleSystem_useHSV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -74118,7 +73930,7 @@ int lua_ax_base_ParticleSystem_isHSV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74165,7 +73977,7 @@ int lua_ax_base_ParticleSystem_getHue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74212,7 +74024,7 @@ int lua_ax_base_ParticleSystem_setHue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74262,7 +74074,7 @@ int lua_ax_base_ParticleSystem_getHueVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74309,7 +74121,7 @@ int lua_ax_base_ParticleSystem_setHueVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74359,7 +74171,7 @@ int lua_ax_base_ParticleSystem_getHSV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74406,7 +74218,7 @@ int lua_ax_base_ParticleSystem_setHSV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::HSV arg0; @@ -74457,7 +74269,7 @@ int lua_ax_base_ParticleSystem_getHSVVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74504,7 +74316,7 @@ int lua_ax_base_ParticleSystem_setHSVVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::HSV arg0; @@ -74555,7 +74367,7 @@ int lua_ax_base_ParticleSystem_getStartSpin(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74602,7 +74414,7 @@ int lua_ax_base_ParticleSystem_setStartSpin(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74652,7 +74464,7 @@ int lua_ax_base_ParticleSystem_getStartSpinVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74699,7 +74511,7 @@ int lua_ax_base_ParticleSystem_setStartSpinVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74749,7 +74561,7 @@ int lua_ax_base_ParticleSystem_getEndSpin(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74796,7 +74608,7 @@ int lua_ax_base_ParticleSystem_setEndSpin(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74846,7 +74658,7 @@ int lua_ax_base_ParticleSystem_getEndSpinVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74893,7 +74705,7 @@ int lua_ax_base_ParticleSystem_setEndSpinVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -74943,7 +74755,7 @@ int lua_ax_base_ParticleSystem_getSpawnAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -74990,7 +74802,7 @@ int lua_ax_base_ParticleSystem_setSpawnAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75040,7 +74852,7 @@ int lua_ax_base_ParticleSystem_getSpawnAngleVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75087,7 +74899,7 @@ int lua_ax_base_ParticleSystem_setSpawnAngleVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75137,7 +74949,7 @@ int lua_ax_base_ParticleSystem_getSpawnFadeIn(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75184,7 +74996,7 @@ int lua_ax_base_ParticleSystem_setSpawnFadeIn(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75234,7 +75046,7 @@ int lua_ax_base_ParticleSystem_getSpawnFadeInVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75281,7 +75093,7 @@ int lua_ax_base_ParticleSystem_setSpawnFadeInVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75331,7 +75143,7 @@ int lua_ax_base_ParticleSystem_getSpawnScaleIn(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75378,7 +75190,7 @@ int lua_ax_base_ParticleSystem_setSpawnScaleIn(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75428,7 +75240,7 @@ int lua_ax_base_ParticleSystem_getSpawnScaleInVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75475,7 +75287,7 @@ int lua_ax_base_ParticleSystem_setSpawnScaleInVar(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75525,7 +75337,7 @@ int lua_ax_base_ParticleSystem_getEmissionRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75572,7 +75384,7 @@ int lua_ax_base_ParticleSystem_setEmissionRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -75622,7 +75434,7 @@ int lua_ax_base_ParticleSystem_getTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75669,7 +75481,7 @@ int lua_ax_base_ParticleSystem_setTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -75719,7 +75531,7 @@ int lua_ax_base_ParticleSystem_setLifeAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -75769,7 +75581,7 @@ int lua_ax_base_ParticleSystem_setEmitterAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -75819,7 +75631,7 @@ int lua_ax_base_ParticleSystem_setLoopAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -75869,7 +75681,7 @@ int lua_ax_base_ParticleSystem_isLifeAnimated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75916,7 +75728,7 @@ int lua_ax_base_ParticleSystem_isEmitterAnimated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -75963,7 +75775,7 @@ int lua_ax_base_ParticleSystem_isLoopAnimated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76010,7 +75822,7 @@ int lua_ax_base_ParticleSystem_getTotalAnimationIndices(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76057,7 +75869,7 @@ int lua_ax_base_ParticleSystem_setAnimationReverse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -76107,7 +75919,7 @@ int lua_ax_base_ParticleSystem_isAnimationReversed(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76154,7 +75966,7 @@ int lua_ax_base_ParticleSystem_resetAnimationIndices(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76201,7 +76013,7 @@ int lua_ax_base_ParticleSystem_resetAnimationDescriptors(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76248,7 +76060,7 @@ int lua_ax_base_ParticleSystem_setMultiAnimationRandomSpecific(lua_State* tolua_ #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::vector arg0; @@ -76298,7 +76110,7 @@ int lua_ax_base_ParticleSystem_setMultiAnimationRandom(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76535,7 +76347,7 @@ int lua_ax_base_ParticleSystem_setRectForUndefinedIndices(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -76559,7 +76371,7 @@ int lua_ax_base_ParticleSystem_setRectForUndefinedIndices(lua_State* tolua_S) return 0; } -int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) +int lua_ax_base_ParticleSystem_setAnimationDesc(lua_State* tolua_S) { int argc = 0; ax::ParticleSystem* cobj = nullptr; @@ -76575,7 +76387,7 @@ int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ParticleSystem_setAnimationDescriptor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ParticleSystem_setAnimationDesc'", nullptr); return 0; } #endif @@ -76583,10 +76395,10 @@ int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) do{ if (argc == 1) { std::vector arg0; - ok &= luaval_to_std_vector_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_std_vector_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } - cobj->setAnimationDescriptor(arg0); + cobj->setAnimationDesc(arg0); lua_settop(tolua_S, 1); return 1; } @@ -76595,14 +76407,14 @@ int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) do{ if (argc == 2) { std::vector arg0; - ok &= luaval_to_std_vector_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_std_vector_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } - cobj->setAnimationDescriptor(arg0, arg1); + cobj->setAnimationDesc(arg0, arg1); lua_settop(tolua_S, 1); return 1; } @@ -76611,22 +76423,22 @@ int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) do{ if (argc == 4) { unsigned short arg0; - ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } std::vector arg3; - ok &= luaval_to_std_vector_ushort(tolua_S, 5, &arg3, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_std_vector_ushort(tolua_S, 5, &arg3, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } - cobj->setAnimationDescriptor(arg0, arg1, arg2, arg3); + cobj->setAnimationDesc(arg0, arg1, arg2, arg3); lua_settop(tolua_S, 1); return 1; } @@ -76635,37 +76447,37 @@ int lua_ax_base_ParticleSystem_setAnimationDescriptor(lua_State* tolua_S) do{ if (argc == 5) { unsigned short arg0; - ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_ushort(tolua_S, 2, &arg0, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } std::vector arg3; - ok &= luaval_to_std_vector_ushort(tolua_S, 5, &arg3, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_std_vector_ushort(tolua_S, 5, &arg3, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } bool arg4; - ok &= luaval_to_boolean(tolua_S, 6,&arg4, "ax.ParticleSystem:setAnimationDescriptor"); + ok &= luaval_to_boolean(tolua_S, 6,&arg4, "ax.ParticleSystem:setAnimationDesc"); if (!ok) { break; } - cobj->setAnimationDescriptor(arg0, arg1, arg2, arg3, arg4); + cobj->setAnimationDesc(arg0, arg1, arg2, arg3, arg4); lua_settop(tolua_S, 1); return 1; } }while(0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:setAnimationDescriptor",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ParticleSystem:setAnimationDesc",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ParticleSystem_setAnimationDescriptor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ParticleSystem_setAnimationDesc'.",&tolua_err); #endif return 0; @@ -76696,7 +76508,7 @@ int lua_ax_base_ParticleSystem_setAnimationSpeedTimescaleIndependent(lua_State* #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -76746,7 +76558,7 @@ int lua_ax_base_ParticleSystem_isAnimationSpeedTimescaleIndependent(lua_State* t #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76793,7 +76605,7 @@ int lua_ax_base_ParticleSystem_setEmissionShapes(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -76843,7 +76655,7 @@ int lua_ax_base_ParticleSystem_isEmissionShapes(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76890,7 +76702,7 @@ int lua_ax_base_ParticleSystem_resetEmissionShapes(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -76937,7 +76749,7 @@ int lua_ax_base_ParticleSystem_addEmissionShape(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EmissionShape arg0; @@ -76988,7 +76800,7 @@ int lua_ax_base_ParticleSystem_setEmissionShape(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { unsigned short arg0; ax::EmissionShape arg1; @@ -77042,7 +76854,7 @@ int lua_ax_base_ParticleSystem_getPositionType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77089,7 +76901,7 @@ int lua_ax_base_ParticleSystem_setPositionType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ParticleSystem::PositionType arg0; @@ -77139,7 +76951,7 @@ int lua_ax_base_ParticleSystem_simulate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77150,7 +76962,7 @@ int lua_ax_base_ParticleSystem_simulate(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 1) + if (argc == 1) { double arg0; @@ -77164,7 +76976,7 @@ int lua_ax_base_ParticleSystem_simulate(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -77217,7 +77029,7 @@ int lua_ax_base_ParticleSystem_resimulate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77228,7 +77040,7 @@ int lua_ax_base_ParticleSystem_resimulate(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 1) + if (argc == 1) { double arg0; @@ -77242,7 +77054,7 @@ int lua_ax_base_ParticleSystem_resimulate(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { double arg0; double arg1; @@ -77295,7 +77107,7 @@ int lua_ax_base_ParticleSystem_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77342,7 +77154,7 @@ int lua_ax_base_ParticleSystem_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -77392,7 +77204,7 @@ int lua_ax_base_ParticleSystem_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -77442,7 +77254,7 @@ int lua_ax_base_ParticleSystem_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77489,7 +77301,7 @@ int lua_ax_base_ParticleSystem_getResourceFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77536,7 +77348,7 @@ int lua_ax_base_ParticleSystem_start(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77583,7 +77395,7 @@ int lua_ax_base_ParticleSystem_stop(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77630,7 +77442,7 @@ int lua_ax_base_ParticleSystem_setSourcePositionCompatible(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -77680,7 +77492,7 @@ int lua_ax_base_ParticleSystem_isSourcePositionCompatible(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77727,7 +77539,7 @@ int lua_ax_base_ParticleSystem_initWithFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -77836,7 +77648,7 @@ int lua_ax_base_ParticleSystem_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -77886,7 +77698,7 @@ int lua_ax_base_ParticleSystem_isPaused(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77933,7 +77745,7 @@ int lua_ax_base_ParticleSystem_pauseEmissions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -77980,7 +77792,7 @@ int lua_ax_base_ParticleSystem_resumeEmissions(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78027,7 +77839,7 @@ int lua_ax_base_ParticleSystem_getFixedFPS(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78074,7 +77886,7 @@ int lua_ax_base_ParticleSystem_setFixedFPS(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78085,7 +77897,7 @@ int lua_ax_base_ParticleSystem_setFixedFPS(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 1) + if (argc == 1) { double arg0; @@ -78135,7 +77947,7 @@ int lua_ax_base_ParticleSystem_getTimeScale(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78182,7 +77994,7 @@ int lua_ax_base_ParticleSystem_setTimeScale(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78193,7 +78005,7 @@ int lua_ax_base_ParticleSystem_setTimeScale(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 1) + if (argc == 1) { double arg0; @@ -78802,7 +78614,7 @@ int lua_ax_base_ParticleSystem_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -78966,7 +78778,7 @@ int lua_register_ax_base_ParticleSystem(lua_State* tolua_S) tolua_function(tolua_S,"setAnimationIndicesAtlas",lua_ax_base_ParticleSystem_setAnimationIndicesAtlas); tolua_function(tolua_S,"addAnimationIndex",lua_ax_base_ParticleSystem_addAnimationIndex); tolua_function(tolua_S,"setRectForUndefinedIndices",lua_ax_base_ParticleSystem_setRectForUndefinedIndices); - tolua_function(tolua_S,"setAnimationDescriptor",lua_ax_base_ParticleSystem_setAnimationDescriptor); + tolua_function(tolua_S,"setAnimationDesc",lua_ax_base_ParticleSystem_setAnimationDesc); tolua_function(tolua_S,"setAnimationSpeedTimescaleIndependent",lua_ax_base_ParticleSystem_setAnimationSpeedTimescaleIndependent); tolua_function(tolua_S,"isAnimationSpeedTimescaleIndependent",lua_ax_base_ParticleSystem_isAnimationSpeedTimescaleIndependent); tolua_function(tolua_S,"setEmissionShapes",lua_ax_base_ParticleSystem_setEmissionShapes); @@ -79041,7 +78853,7 @@ int lua_ax_base_ParticleSystemQuad_setDisplayFrame(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::SpriteFrame* arg0; @@ -79091,7 +78903,7 @@ int lua_ax_base_ParticleSystemQuad_setTextureWithRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Texture2D* arg0; ax::Rect arg1; @@ -79144,7 +78956,7 @@ int lua_ax_base_ParticleSystemQuad_listenRendererRecreated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::EventCustom* arg0; @@ -79182,7 +78994,7 @@ int lua_ax_base_ParticleSystemQuad_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 1) { @@ -79195,7 +79007,7 @@ int lua_ax_base_ParticleSystemQuad_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 0) { @@ -79205,7 +79017,7 @@ int lua_ax_base_ParticleSystemQuad_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -79275,7 +79087,7 @@ int lua_ax_base_ParticleSystemQuad_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79407,7 +79219,7 @@ int lua_ax_base_ParticleFire_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79479,7 +79291,7 @@ int lua_ax_base_ParticleFireworks_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79526,7 +79338,7 @@ int lua_ax_base_ParticleFireworks_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -79633,7 +79445,7 @@ int lua_ax_base_ParticleFireworks_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79707,7 +79519,7 @@ int lua_ax_base_ParticleSun_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79754,7 +79566,7 @@ int lua_ax_base_ParticleSun_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -79861,7 +79673,7 @@ int lua_ax_base_ParticleSun_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79935,7 +79747,7 @@ int lua_ax_base_ParticleGalaxy_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -79982,7 +79794,7 @@ int lua_ax_base_ParticleGalaxy_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -80089,7 +79901,7 @@ int lua_ax_base_ParticleGalaxy_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80163,7 +79975,7 @@ int lua_ax_base_ParticleFlower_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80210,7 +80022,7 @@ int lua_ax_base_ParticleFlower_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -80317,7 +80129,7 @@ int lua_ax_base_ParticleFlower_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80391,7 +80203,7 @@ int lua_ax_base_ParticleMeteor_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80438,7 +80250,7 @@ int lua_ax_base_ParticleMeteor_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -80545,7 +80357,7 @@ int lua_ax_base_ParticleMeteor_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80619,7 +80431,7 @@ int lua_ax_base_ParticleSpiral_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80666,7 +80478,7 @@ int lua_ax_base_ParticleSpiral_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -80773,7 +80585,7 @@ int lua_ax_base_ParticleSpiral_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80847,7 +80659,7 @@ int lua_ax_base_ParticleExplosion_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -80894,7 +80706,7 @@ int lua_ax_base_ParticleExplosion_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -81001,7 +80813,7 @@ int lua_ax_base_ParticleExplosion_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81075,7 +80887,7 @@ int lua_ax_base_ParticleSmoke_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81122,7 +80934,7 @@ int lua_ax_base_ParticleSmoke_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -81229,7 +81041,7 @@ int lua_ax_base_ParticleSmoke_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81303,7 +81115,7 @@ int lua_ax_base_ParticleSnow_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81350,7 +81162,7 @@ int lua_ax_base_ParticleSnow_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -81457,7 +81269,7 @@ int lua_ax_base_ParticleSnow_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81531,7 +81343,7 @@ int lua_ax_base_ParticleRain_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81578,7 +81390,7 @@ int lua_ax_base_ParticleRain_initWithTotalParticles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -81685,7 +81497,7 @@ int lua_ax_base_ParticleRain_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81759,7 +81571,7 @@ int lua_ax_base_ProgressTimer_getType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81806,7 +81618,7 @@ int lua_ax_base_ProgressTimer_getPercentage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81853,7 +81665,7 @@ int lua_ax_base_ProgressTimer_getSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -81900,7 +81712,7 @@ int lua_ax_base_ProgressTimer_setPercentage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -81950,7 +81762,7 @@ int lua_ax_base_ProgressTimer_setSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -82000,7 +81812,7 @@ int lua_ax_base_ProgressTimer_setType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ProgressTimer::Type arg0; @@ -82050,7 +81862,7 @@ int lua_ax_base_ProgressTimer_isReverseDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -82097,7 +81909,7 @@ int lua_ax_base_ProgressTimer_setReverseDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -82147,7 +81959,7 @@ int lua_ax_base_ProgressTimer_setMidpoint(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -82197,7 +82009,7 @@ int lua_ax_base_ProgressTimer_getMidpoint(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -82244,7 +82056,7 @@ int lua_ax_base_ProgressTimer_setBarChangeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -82294,7 +82106,7 @@ int lua_ax_base_ProgressTimer_getBarChangeRate(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -82341,7 +82153,7 @@ int lua_ax_base_ProgressTimer_initWithSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -82414,7 +82226,7 @@ int lua_ax_base_ProgressTimer_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -82577,7 +82389,7 @@ int lua_ax_base_ProtectedNode_getProtectedChildByTag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -82627,7 +82439,7 @@ int lua_ax_base_ProtectedNode_getProtectedChildByName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -82677,7 +82489,7 @@ int lua_ax_base_ProtectedNode_removeProtectedChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -82691,7 +82503,7 @@ int lua_ax_base_ProtectedNode_removeProtectedChild(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Node* arg0; bool arg1; @@ -82744,7 +82556,7 @@ int lua_ax_base_ProtectedNode_removeProtectedChildByTag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -82758,7 +82570,7 @@ int lua_ax_base_ProtectedNode_removeProtectedChildByTag(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { int arg0; bool arg1; @@ -82811,7 +82623,7 @@ int lua_ax_base_ProtectedNode_removeAllProtectedChildren(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -82858,7 +82670,7 @@ int lua_ax_base_ProtectedNode_removeAllProtectedChildrenWithCleanup(lua_State* t #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -82908,7 +82720,7 @@ int lua_ax_base_ProtectedNode_reorderProtectedChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Node* arg0; int arg1; @@ -82961,7 +82773,7 @@ int lua_ax_base_ProtectedNode_sortAllProtectedChildren(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83008,7 +82820,7 @@ int lua_ax_base_ProtectedNode_getProtectedChildren(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83055,7 +82867,7 @@ int lua_ax_base_ProtectedNode_disableCascadeColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83102,7 +82914,7 @@ int lua_ax_base_ProtectedNode_disableCascadeOpacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83170,7 +82982,7 @@ int lua_ax_base_ProtectedNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83253,7 +83065,7 @@ int lua_ax_base_RenderTexture_begin(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83415,7 +83227,7 @@ int lua_ax_base_RenderTexture_end(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83462,7 +83274,7 @@ int lua_ax_base_RenderTexture_clear(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; double arg1; @@ -83521,7 +83333,7 @@ int lua_ax_base_RenderTexture_clearDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -83571,7 +83383,7 @@ int lua_ax_base_RenderTexture_clearStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -83879,7 +83691,7 @@ int lua_ax_base_RenderTexture_getClearFlags(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83926,9 +83738,9 @@ int lua_ax_base_RenderTexture_setClearFlags(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::TargetBufferFlags arg0; + ax::rhi::TargetBufferFlags arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.RenderTexture:setClearFlags"); if(!ok) @@ -83976,7 +83788,7 @@ int lua_ax_base_RenderTexture_getClearColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -83984,7 +83796,7 @@ int lua_ax_base_RenderTexture_getClearColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getClearColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderTexture:getClearColor",argc, 0); @@ -84023,11 +83835,11 @@ int lua_ax_base_RenderTexture_setClearColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.RenderTexture:setClearColor"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.RenderTexture:setClearColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_RenderTexture_setClearColor'", nullptr); @@ -84073,7 +83885,7 @@ int lua_ax_base_RenderTexture_getClearDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84120,7 +83932,7 @@ int lua_ax_base_RenderTexture_setClearDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -84170,7 +83982,7 @@ int lua_ax_base_RenderTexture_getClearStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84217,7 +84029,7 @@ int lua_ax_base_RenderTexture_setClearStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -84267,7 +84079,7 @@ int lua_ax_base_RenderTexture_isAutoDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84314,7 +84126,7 @@ int lua_ax_base_RenderTexture_setAutoDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -84364,7 +84176,7 @@ int lua_ax_base_RenderTexture_getSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84411,7 +84223,7 @@ int lua_ax_base_RenderTexture_getRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84419,7 +84231,7 @@ int lua_ax_base_RenderTexture_getRenderTarget(lua_State* tolua_S) return 0; } auto&& ret = cobj->getRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.RenderTexture:getRenderTarget",argc, 0); @@ -84458,7 +84270,7 @@ int lua_ax_base_RenderTexture_setKeepMatrix(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -84508,7 +84320,7 @@ int lua_ax_base_RenderTexture_setVirtualViewport(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Vec2 arg0; ax::Rect arg1; @@ -84564,7 +84376,7 @@ int lua_ax_base_RenderTexture_isSharedRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84616,11 +84428,11 @@ int lua_ax_base_RenderTexture_initWithWidthAndHeight(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg3; + ax::rhi::PixelFormat arg3; ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } @@ -84640,11 +84452,11 @@ int lua_ax_base_RenderTexture_initWithWidthAndHeight(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg3; + ax::rhi::PixelFormat arg3; ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } @@ -84668,7 +84480,7 @@ int lua_ax_base_RenderTexture_initWithWidthAndHeight(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } @@ -84688,7 +84500,7 @@ int lua_ax_base_RenderTexture_initWithWidthAndHeight(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:initWithWidthAndHeight"); if (!ok) { break; } @@ -84726,7 +84538,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 3) { @@ -84736,7 +84548,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) int arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:create"); if (!ok) { break; } ax::RenderTexture* ret = ax::RenderTexture::create(arg0, arg1, arg2); @@ -84745,7 +84557,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -84755,7 +84567,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) int arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:create"); if (!ok) { break; } bool arg3; @@ -84767,7 +84579,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -84777,10 +84589,10 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) int arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg3; + ax::rhi::PixelFormat arg3; ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.RenderTexture:create"); if (!ok) { break; } ax::RenderTexture* ret = ax::RenderTexture::create(arg0, arg1, arg2, arg3); @@ -84789,7 +84601,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -84799,10 +84611,10 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) int arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.RenderTexture:create"); if (!ok) { break; } - ax::backend::PixelFormat arg3; + ax::rhi::PixelFormat arg3; ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "ax.RenderTexture:create"); if (!ok) { break; } bool arg4; @@ -84814,7 +84626,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 2) { @@ -84830,7 +84642,7 @@ int lua_ax_base_RenderTexture_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -84870,7 +84682,7 @@ int lua_ax_base_RenderTexture_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -84965,7 +84777,7 @@ int lua_ax_base_TransitionEaseScene_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -85035,7 +84847,7 @@ int lua_ax_base_TransitionScene_finish(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85082,7 +84894,7 @@ int lua_ax_base_TransitionScene_hideOutShowIn(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85129,7 +84941,7 @@ int lua_ax_base_TransitionScene_getInScene(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85176,7 +84988,7 @@ int lua_ax_base_TransitionScene_getDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85223,7 +85035,7 @@ int lua_ax_base_TransitionScene_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { double arg0; ax::Scene* arg1; @@ -85301,7 +85113,7 @@ int lua_ax_base_TransitionScene_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85377,7 +85189,7 @@ int lua_ax_base_TransitionSceneOriented_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; ax::Scene* arg1; @@ -85460,7 +85272,7 @@ int lua_ax_base_TransitionSceneOriented_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85557,7 +85369,7 @@ int lua_ax_base_TransitionRotoZoom_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85653,7 +85465,7 @@ int lua_ax_base_TransitionJumpZoom_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85724,7 +85536,7 @@ int lua_ax_base_TransitionMoveInL_action(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85771,7 +85583,7 @@ int lua_ax_base_TransitionMoveInL_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -85846,7 +85658,7 @@ int lua_ax_base_TransitionMoveInL_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -85944,7 +85756,7 @@ int lua_ax_base_TransitionMoveInR_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86040,7 +85852,7 @@ int lua_ax_base_TransitionMoveInT_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86136,7 +85948,7 @@ int lua_ax_base_TransitionMoveInB_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86207,7 +86019,7 @@ int lua_ax_base_TransitionSlideInL_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -86257,7 +86069,7 @@ int lua_ax_base_TransitionSlideInL_action(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86329,7 +86141,7 @@ int lua_ax_base_TransitionSlideInL_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86427,7 +86239,7 @@ int lua_ax_base_TransitionSlideInR_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86523,7 +86335,7 @@ int lua_ax_base_TransitionSlideInB_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86619,7 +86431,7 @@ int lua_ax_base_TransitionSlideInT_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86690,7 +86502,7 @@ int lua_ax_base_TransitionShrinkGrow_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -86765,7 +86577,7 @@ int lua_ax_base_TransitionShrinkGrow_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86825,7 +86637,7 @@ int lua_ax_base_TransitionFlipX_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -86841,7 +86653,7 @@ int lua_ax_base_TransitionFlipX_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -86881,7 +86693,7 @@ int lua_ax_base_TransitionFlipX_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -86940,7 +86752,7 @@ int lua_ax_base_TransitionFlipY_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -86956,7 +86768,7 @@ int lua_ax_base_TransitionFlipY_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -86996,7 +86808,7 @@ int lua_ax_base_TransitionFlipY_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87055,7 +86867,7 @@ int lua_ax_base_TransitionFlipAngular_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -87071,7 +86883,7 @@ int lua_ax_base_TransitionFlipAngular_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -87111,7 +86923,7 @@ int lua_ax_base_TransitionFlipAngular_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87170,7 +86982,7 @@ int lua_ax_base_TransitionZoomFlipX_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -87186,7 +86998,7 @@ int lua_ax_base_TransitionZoomFlipX_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -87226,7 +87038,7 @@ int lua_ax_base_TransitionZoomFlipX_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87285,7 +87097,7 @@ int lua_ax_base_TransitionZoomFlipY_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -87301,7 +87113,7 @@ int lua_ax_base_TransitionZoomFlipY_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -87341,7 +87153,7 @@ int lua_ax_base_TransitionZoomFlipY_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87400,7 +87212,7 @@ int lua_ax_base_TransitionZoomFlipAngular_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -87416,7 +87228,7 @@ int lua_ax_base_TransitionZoomFlipAngular_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -87456,7 +87268,7 @@ int lua_ax_base_TransitionZoomFlipAngular_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87548,8 +87360,8 @@ int lua_ax_base_TransitionFade_initWithDuration(lua_State* tolua_S) ok &= luaval_to_object(tolua_S, 3, "ax.Scene",&arg1, "ax.TransitionFade:initWithDuration"); if (!ok) { break; } - ax::Color3B arg2; - ok &= luaval_to_color3b(tolua_S, 4, &arg2, "ax.TransitionFade:initWithDuration"); + ax::Color32 arg2; + ok &=luaval_to_color32(tolua_S, 4, &arg2, "ax.TransitionFade:initWithDuration"); if (!ok) { break; } bool ret = cobj->initWithDuration(arg0, arg1, arg2); @@ -87582,7 +87394,7 @@ int lua_ax_base_TransitionFade_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -87598,7 +87410,7 @@ int lua_ax_base_TransitionFade_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -87608,8 +87420,8 @@ int lua_ax_base_TransitionFade_create(lua_State* tolua_S) ax::Scene* arg1; ok &= luaval_to_object(tolua_S, 3, "ax.Scene",&arg1, "ax.TransitionFade:create"); if (!ok) { break; } - ax::Color3B arg2; - ok &= luaval_to_color3b(tolua_S, 4, &arg2, "ax.TransitionFade:create"); + ax::Color32 arg2; + ok &=luaval_to_color32(tolua_S, 4, &arg2, "ax.TransitionFade:create"); if (!ok) { break; } ax::TransitionFade* ret = ax::TransitionFade::create(arg0, arg1, arg2); object_to_luaval(tolua_S, "ax.TransitionFade",(ax::TransitionFade*)ret); @@ -87638,7 +87450,7 @@ int lua_ax_base_TransitionFade_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87735,7 +87547,7 @@ int lua_ax_base_TransitionCrossFade_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87806,7 +87618,7 @@ int lua_ax_base_TransitionTurnOffTiles_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -87881,7 +87693,7 @@ int lua_ax_base_TransitionTurnOffTiles_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -87953,7 +87765,7 @@ int lua_ax_base_TransitionSplitCols_action(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88000,7 +87812,7 @@ int lua_ax_base_TransitionSplitCols_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -88075,7 +87887,7 @@ int lua_ax_base_TransitionSplitCols_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88173,7 +87985,7 @@ int lua_ax_base_TransitionSplitRows_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88244,7 +88056,7 @@ int lua_ax_base_TransitionFadeTR_actionWithSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -88294,7 +88106,7 @@ int lua_ax_base_TransitionFadeTR_easeActionWithAction(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ActionInterval* arg0; @@ -88369,7 +88181,7 @@ int lua_ax_base_TransitionFadeTR_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88467,7 +88279,7 @@ int lua_ax_base_TransitionFadeBL_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88563,7 +88375,7 @@ int lua_ax_base_TransitionFadeUp_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88659,7 +88471,7 @@ int lua_ax_base_TransitionFadeDown_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88730,7 +88542,7 @@ int lua_ax_base_TransitionPageTurn_initWithDuration(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { double arg0; ax::Scene* arg1; @@ -88786,7 +88598,7 @@ int lua_ax_base_TransitionPageTurn_actionWithSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -88863,7 +88675,7 @@ int lua_ax_base_TransitionPageTurn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -88961,7 +88773,7 @@ int lua_ax_base_TransitionProgress_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89057,7 +88869,7 @@ int lua_ax_base_TransitionProgressRadialCCW_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89153,7 +88965,7 @@ int lua_ax_base_TransitionProgressRadialCW_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89249,7 +89061,7 @@ int lua_ax_base_TransitionProgressHorizontal_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89345,7 +89157,7 @@ int lua_ax_base_TransitionProgressVertical_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89441,7 +89253,7 @@ int lua_ax_base_TransitionProgressInOut_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89537,7 +89349,7 @@ int lua_ax_base_TransitionProgressOutIn_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89608,7 +89420,7 @@ int lua_ax_base_Camera_getCameraFlag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89655,7 +89467,7 @@ int lua_ax_base_Camera_setCameraFlag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::CameraFlag arg0; @@ -89705,7 +89517,7 @@ int lua_ax_base_Camera_lookAt(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -89719,7 +89531,7 @@ int lua_ax_base_Camera_lookAt(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { ax::Vec3 arg0; ax::Vec3 arg1; @@ -89772,7 +89584,7 @@ int lua_ax_base_Camera_getProjectionMatrix(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89819,7 +89631,7 @@ int lua_ax_base_Camera_getViewMatrix(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89866,7 +89678,7 @@ int lua_ax_base_Camera_getViewProjectionMatrix(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -89913,7 +89725,7 @@ int lua_ax_base_Camera_project(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -89963,7 +89775,7 @@ int lua_ax_base_Camera_projectGL(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -90013,7 +89825,7 @@ int lua_ax_base_Camera_isVisibleInFrustum(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { const ax::AABB* arg0; @@ -90063,7 +89875,7 @@ int lua_ax_base_Camera_getDepthInView(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Mat4 arg0; @@ -90113,7 +89925,7 @@ int lua_ax_base_Camera_setDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int32_t arg0; @@ -90163,7 +89975,7 @@ int lua_ax_base_Camera_getDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90210,7 +90022,7 @@ int lua_ax_base_Camera_getRenderOrder(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90257,7 +90069,7 @@ int lua_ax_base_Camera_getFOV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90304,7 +90116,7 @@ int lua_ax_base_Camera_setFOV(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -90354,7 +90166,7 @@ int lua_ax_base_Camera_getFarPlane(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90401,7 +90213,7 @@ int lua_ax_base_Camera_setFarPlane(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -90451,7 +90263,7 @@ int lua_ax_base_Camera_getNearPlane(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90498,7 +90310,7 @@ int lua_ax_base_Camera_setNearPlane(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -90548,7 +90360,7 @@ int lua_ax_base_Camera_getZoom(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90595,7 +90407,7 @@ int lua_ax_base_Camera_setZoom(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -90645,7 +90457,7 @@ int lua_ax_base_Camera_applyZoom(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90692,7 +90504,7 @@ int lua_ax_base_Camera_clearBackground(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90739,7 +90551,7 @@ int lua_ax_base_Camera_apply(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90786,7 +90598,7 @@ int lua_ax_base_Camera_isViewProjectionUpdated(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90833,7 +90645,7 @@ int lua_ax_base_Camera_setBackgroundBrush(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::CameraBackgroundBrush* arg0; @@ -90883,7 +90695,7 @@ int lua_ax_base_Camera_getBackgroundBrush(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90930,7 +90742,7 @@ int lua_ax_base_Camera_isBrushValid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -90977,7 +90789,7 @@ int lua_ax_base_Camera_setScene(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Scene* arg0; @@ -91027,7 +90839,7 @@ int lua_ax_base_Camera_setAdditionalProjection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Mat4 arg0; @@ -91077,7 +90889,7 @@ int lua_ax_base_Camera_initDefault(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91124,7 +90936,7 @@ int lua_ax_base_Camera_initPerspective(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; double arg1; @@ -91183,7 +90995,7 @@ int lua_ax_base_Camera_initOrthographic(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; double arg1; @@ -91242,7 +91054,7 @@ int lua_ax_base_Camera_applyViewport(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91533,7 +91345,7 @@ int lua_ax_base_Camera_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91644,7 +91456,7 @@ int lua_ax_base_CameraBackgroundBrush_getBrushType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91691,7 +91503,7 @@ int lua_ax_base_CameraBackgroundBrush_drawBackground(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Camera* arg0; @@ -91741,7 +91553,7 @@ int lua_ax_base_CameraBackgroundBrush_isValid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91788,7 +91600,7 @@ int lua_ax_base_CameraBackgroundBrush_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -91907,9 +91719,9 @@ int lua_ax_base_CameraBackgroundBrush_createColorBrush(lua_State* tolua_S) if (argc == 2) { - ax::Color4F arg0; + ax::Color arg0; double arg1; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.CameraBackgroundBrush:createColorBrush"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.CameraBackgroundBrush:createColorBrush"); ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.CameraBackgroundBrush:createColorBrush"); if(!ok) { @@ -91987,7 +91799,7 @@ int lua_ax_base_CameraBackgroundBrush_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92065,7 +91877,7 @@ int lua_ax_base_CameraBackgroundDepthBrush_setDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -92138,7 +91950,7 @@ int lua_ax_base_CameraBackgroundDepthBrush_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92210,11 +92022,11 @@ int lua_ax_base_CameraBackgroundColorBrush_setColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.CameraBackgroundColorBrush:setColor"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.CameraBackgroundColorBrush:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_CameraBackgroundColorBrush_setColor'", nullptr); @@ -92251,9 +92063,9 @@ int lua_ax_base_CameraBackgroundColorBrush_create(lua_State* tolua_S) if (argc == 2) { - ax::Color4F arg0; + ax::Color arg0; double arg1; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ax.CameraBackgroundColorBrush:create"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ax.CameraBackgroundColorBrush:create"); ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.CameraBackgroundColorBrush:create"); if(!ok) { @@ -92285,7 +92097,7 @@ int lua_ax_base_CameraBackgroundColorBrush_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92357,7 +92169,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextureCube* arg0; @@ -92407,7 +92219,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92454,7 +92266,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_isActived(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92501,7 +92313,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_setActived(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -92551,7 +92363,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_setTextureValid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -92589,7 +92401,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 0) { @@ -92599,7 +92411,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 6) { @@ -92648,7 +92460,7 @@ int lua_ax_base_CameraBackgroundSkyBoxBrush_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92724,7 +92536,7 @@ int lua_ax_base_GridBase_beforeBlit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92771,7 +92583,7 @@ int lua_ax_base_GridBase_afterBlit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92818,7 +92630,7 @@ int lua_ax_base_GridBase_blit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92865,7 +92677,7 @@ int lua_ax_base_GridBase_reuse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -92912,7 +92724,7 @@ int lua_ax_base_GridBase_calculateVertexPoints(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93062,7 +92874,7 @@ int lua_ax_base_GridBase_isActive(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93109,7 +92921,7 @@ int lua_ax_base_GridBase_setActive(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -93159,7 +92971,7 @@ int lua_ax_base_GridBase_getReuseGrid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93206,7 +93018,7 @@ int lua_ax_base_GridBase_setReuseGrid(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -93256,7 +93068,7 @@ int lua_ax_base_GridBase_getGridSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93303,7 +93115,7 @@ int lua_ax_base_GridBase_setGridSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -93353,7 +93165,7 @@ int lua_ax_base_GridBase_getStep(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93400,7 +93212,7 @@ int lua_ax_base_GridBase_setStep(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -93450,7 +93262,7 @@ int lua_ax_base_GridBase_isTextureFlipped(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93497,7 +93309,7 @@ int lua_ax_base_GridBase_setTextureFlipped(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -93547,7 +93359,7 @@ int lua_ax_base_GridBase_beforeDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93594,7 +93406,7 @@ int lua_ax_base_GridBase_afterDraw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Node* arg0; @@ -93644,7 +93456,7 @@ int lua_ax_base_GridBase_set2DProjection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93691,7 +93503,7 @@ int lua_ax_base_GridBase_setGridRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Rect arg0; @@ -93741,7 +93553,7 @@ int lua_ax_base_GridBase_getGridRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93828,7 +93640,7 @@ int lua_ax_base_Grid3D_setNeedDepthTestForBlit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -93878,7 +93690,7 @@ int lua_ax_base_Grid3D_getNeedDepthTestForBlit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -93913,7 +93725,7 @@ int lua_ax_base_Grid3D_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -93929,7 +93741,7 @@ int lua_ax_base_Grid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -93942,7 +93754,7 @@ int lua_ax_base_Grid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -93961,7 +93773,7 @@ int lua_ax_base_Grid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -94004,7 +93816,7 @@ int lua_ax_base_Grid3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94065,7 +93877,7 @@ int lua_ax_base_TiledGrid3D_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 2) { @@ -94081,7 +93893,7 @@ int lua_ax_base_TiledGrid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 1) { @@ -94094,7 +93906,7 @@ int lua_ax_base_TiledGrid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 3) { @@ -94113,7 +93925,7 @@ int lua_ax_base_TiledGrid3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 4) { @@ -94189,7 +94001,7 @@ int lua_ax_base_BaseLight_getLightType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94236,7 +94048,7 @@ int lua_ax_base_BaseLight_getIntensity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94283,7 +94095,7 @@ int lua_ax_base_BaseLight_setIntensity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -94333,7 +94145,7 @@ int lua_ax_base_BaseLight_getLightFlag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94380,7 +94192,7 @@ int lua_ax_base_BaseLight_setLightFlag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::LightFlag arg0; @@ -94430,7 +94242,7 @@ int lua_ax_base_BaseLight_setEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -94480,7 +94292,7 @@ int lua_ax_base_BaseLight_isEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94553,7 +94365,7 @@ int lua_ax_base_DirectionLight_setDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -94603,7 +94415,7 @@ int lua_ax_base_DirectionLight_getDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94650,7 +94462,7 @@ int lua_ax_base_DirectionLight_getDirectionInWorld(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94689,9 +94501,9 @@ int lua_ax_base_DirectionLight_create(lua_State* tolua_S) if (argc == 2) { ax::Vec3 arg0; - ax::Color3B arg1; + ax::Color32 arg1; ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.DirectionLight:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "ax.DirectionLight:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.DirectionLight:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_DirectionLight_create'", nullptr); @@ -94722,7 +94534,7 @@ int lua_ax_base_DirectionLight_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94796,7 +94608,7 @@ int lua_ax_base_PointLight_getRange(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94843,7 +94655,7 @@ int lua_ax_base_PointLight_setRange(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -94885,10 +94697,10 @@ int lua_ax_base_PointLight_create(lua_State* tolua_S) if (argc == 3) { ax::Vec3 arg0; - ax::Color3B arg1; + ax::Color32 arg1; double arg2; ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.PointLight:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "ax.PointLight:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "ax.PointLight:create"); ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PointLight:create"); if(!ok) { @@ -94920,7 +94732,7 @@ int lua_ax_base_PointLight_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -94993,7 +94805,7 @@ int lua_ax_base_SpotLight_setDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -95043,7 +94855,7 @@ int lua_ax_base_SpotLight_getDirection(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95090,7 +94902,7 @@ int lua_ax_base_SpotLight_getDirectionInWorld(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95137,7 +94949,7 @@ int lua_ax_base_SpotLight_setRange(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -95187,7 +94999,7 @@ int lua_ax_base_SpotLight_getRange(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95234,7 +95046,7 @@ int lua_ax_base_SpotLight_setInnerAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -95284,7 +95096,7 @@ int lua_ax_base_SpotLight_getInnerAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95331,7 +95143,7 @@ int lua_ax_base_SpotLight_getCosInnerAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95378,7 +95190,7 @@ int lua_ax_base_SpotLight_setOuterAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -95428,7 +95240,7 @@ int lua_ax_base_SpotLight_getOuterAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95475,7 +95287,7 @@ int lua_ax_base_SpotLight_getCosOuterAngle(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95515,13 +95327,13 @@ int lua_ax_base_SpotLight_create(lua_State* tolua_S) { ax::Vec3 arg0; ax::Vec3 arg1; - ax::Color3B arg2; + ax::Color32 arg2; double arg3; double arg4; double arg5; ok &= luaval_to_vec3(tolua_S, 2, &arg0, "ax.SpotLight:create"); ok &= luaval_to_vec3(tolua_S, 3, &arg1, "ax.SpotLight:create"); - ok &= luaval_to_color3b(tolua_S, 4, &arg2, "ax.SpotLight:create"); + ok &=luaval_to_color32(tolua_S, 4, &arg2, "ax.SpotLight:create"); ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.SpotLight:create"); ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.SpotLight:create"); ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.SpotLight:create"); @@ -95555,7 +95367,7 @@ int lua_ax_base_SpotLight_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95628,8 +95440,8 @@ int lua_ax_base_AmbientLight_create(lua_State* tolua_S) if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.AmbientLight:create"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.AmbientLight:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_AmbientLight_create'", nullptr); @@ -95660,7 +95472,7 @@ int lua_ax_base_AmbientLight_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95731,7 +95543,7 @@ int lua_ax_base_RenderState_getName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95778,7 +95590,7 @@ int lua_ax_base_RenderState_bindPass(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Pass* arg0; ax::MeshCommand* arg1; @@ -95852,7 +95664,7 @@ int lua_ax_base_Technique_addPass(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Pass* arg0; @@ -95902,7 +95714,7 @@ int lua_ax_base_Technique_getName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -95949,7 +95761,7 @@ int lua_ax_base_Technique_getPassByIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -95999,7 +95811,7 @@ int lua_ax_base_Technique_getPassCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96046,7 +95858,7 @@ int lua_ax_base_Technique_getPasses(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96093,7 +95905,7 @@ int lua_ax_base_Technique_clone(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96140,7 +95952,7 @@ int lua_ax_base_Technique_setMaterial(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Material* arg0; @@ -96182,9 +95994,9 @@ int lua_ax_base_Technique_createWithProgramState(lua_State* tolua_S) if (argc == 2) { ax::Material* arg0; - ax::backend::ProgramState* arg1; + ax::rhi::ProgramState* arg1; ok &= luaval_to_object(tolua_S, 2, "ax.Material",&arg0, "ax.Technique:createWithProgramState"); - ok &= luaval_to_object(tolua_S, 3, "axb.ProgramState",&arg1, "ax.Technique:createWithProgramState"); + ok &= luaval_to_object(tolua_S, 3, "axrhi.ProgramState",&arg1, "ax.Technique:createWithProgramState"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Technique_createWithProgramState'", nullptr); @@ -96292,14 +96104,14 @@ int lua_ax_base_Material_draw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 8) + if (argc == 8) { ax::MeshCommand* arg0; double arg1; - ax::backend::Buffer* arg2; - ax::backend::Buffer* arg3; - ax::backend::PrimitiveType arg4; - ax::backend::IndexFormat arg5; + ax::rhi::Buffer* arg2; + ax::rhi::Buffer* arg3; + ax::rhi::PrimitiveType arg4; + ax::rhi::IndexFormat arg5; unsigned int arg6; ax::Mat4 arg7; @@ -96307,9 +96119,9 @@ int lua_ax_base_Material_draw(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Material:draw"); - ok &= luaval_to_object(tolua_S, 4, "axb.Buffer",&arg2, "ax.Material:draw"); + ok &= luaval_to_object(tolua_S, 4, "axrhi.Buffer",&arg2, "ax.Material:draw"); - ok &= luaval_to_object(tolua_S, 5, "axb.Buffer",&arg3, "ax.Material:draw"); + ok &= luaval_to_object(tolua_S, 5, "axrhi.Buffer",&arg3, "ax.Material:draw"); ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Material:draw"); @@ -96363,7 +96175,7 @@ int lua_ax_base_Material_getName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96410,7 +96222,7 @@ int lua_ax_base_Material_setName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -96460,7 +96272,7 @@ int lua_ax_base_Material_getTechniqueByName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -96510,7 +96322,7 @@ int lua_ax_base_Material_getTechniqueByIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -96560,7 +96372,7 @@ int lua_ax_base_Material_getTechnique(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96607,7 +96419,7 @@ int lua_ax_base_Material_getTechniques(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96654,7 +96466,7 @@ int lua_ax_base_Material_getTechniqueCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96701,7 +96513,7 @@ int lua_ax_base_Material_addTechnique(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Technique* arg0; @@ -96751,7 +96563,7 @@ int lua_ax_base_Material_setTechnique(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -96801,7 +96613,7 @@ int lua_ax_base_Material_clone(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96848,7 +96660,7 @@ int lua_ax_base_Material_getRenderState(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96895,9 +96707,9 @@ int lua_ax_base_Material_setPrimitiveType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::PrimitiveType arg0; + ax::rhi::PrimitiveType arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Material:setPrimitiveType"); if(!ok) @@ -96945,7 +96757,7 @@ int lua_ax_base_Material_getPrimitiveType(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -96992,7 +96804,7 @@ int lua_ax_base_Material_setTransparent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -97042,7 +96854,7 @@ int lua_ax_base_Material_isTransparent(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97089,7 +96901,7 @@ int lua_ax_base_Material_setForce2DQueue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -97139,7 +96951,7 @@ int lua_ax_base_Material_isForce2DQueue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97213,8 +97025,8 @@ int lua_ax_base_Material_createWithProgramState(lua_State* tolua_S) if (argc == 1) { - ax::backend::ProgramState* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.ProgramState",&arg0, "ax.Material:createWithProgramState"); + ax::rhi::ProgramState* arg0; + ok &= luaval_to_object(tolua_S, 2, "axrhi.ProgramState",&arg0, "ax.Material:createWithProgramState"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Material_createWithProgramState'", nullptr); @@ -97334,7 +97146,7 @@ int lua_ax_base_Pass_getProgramState(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97342,7 +97154,7 @@ int lua_ax_base_Pass_getProgramState(lua_State* tolua_S) return 0; } auto&& ret = cobj->getProgramState(); - object_to_luaval(tolua_S, "axb.ProgramState",(ax::backend::ProgramState*)ret); + object_to_luaval(tolua_S, "axrhi.ProgramState",(ax::rhi::ProgramState*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Pass:getProgramState",argc, 0); @@ -97381,14 +97193,14 @@ int lua_ax_base_Pass_draw(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 8) + if (argc == 8) { ax::MeshCommand* arg0; double arg1; - ax::backend::Buffer* arg2; - ax::backend::Buffer* arg3; - ax::backend::PrimitiveType arg4; - ax::backend::IndexFormat arg5; + ax::rhi::Buffer* arg2; + ax::rhi::Buffer* arg3; + ax::rhi::PrimitiveType arg4; + ax::rhi::IndexFormat arg5; unsigned int arg6; ax::Mat4 arg7; @@ -97396,9 +97208,9 @@ int lua_ax_base_Pass_draw(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.Pass:draw"); - ok &= luaval_to_object(tolua_S, 4, "axb.Buffer",&arg2, "ax.Pass:draw"); + ok &= luaval_to_object(tolua_S, 4, "axrhi.Buffer",&arg2, "ax.Pass:draw"); - ok &= luaval_to_object(tolua_S, 5, "axb.Buffer",&arg3, "ax.Pass:draw"); + ok &= luaval_to_object(tolua_S, 5, "axrhi.Buffer",&arg3, "ax.Pass:draw"); ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "ax.Pass:draw"); @@ -97426,7 +97238,7 @@ int lua_ax_base_Pass_draw(lua_State* tolua_S) return 0; } -int lua_ax_base_Pass_setVertexAttribBinding(lua_State* tolua_S) +int lua_ax_base_Pass_setVertexInputBinding(lua_State* tolua_S) { int argc = 0; ax::Pass* cobj = nullptr; @@ -97446,32 +97258,32 @@ int lua_ax_base_Pass_setVertexAttribBinding(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Pass_setVertexAttribBinding'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Pass_setVertexInputBinding'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::VertexAttribBinding* arg0; + ax::VertexInputBinding* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.VertexAttribBinding",&arg0, "ax.Pass:setVertexAttribBinding"); + ok &= luaval_to_object(tolua_S, 2, "ax.VertexInputBinding",&arg0, "ax.Pass:setVertexInputBinding"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Pass_setVertexAttribBinding'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Pass_setVertexInputBinding'", nullptr); return 0; } - cobj->setVertexAttribBinding(arg0); + cobj->setVertexInputBinding(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Pass:setVertexAttribBinding",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Pass:setVertexInputBinding",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Pass_setVertexAttribBinding'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Pass_setVertexInputBinding'.",&tolua_err); #endif return 0; @@ -97502,7 +97314,7 @@ int lua_ax_base_Pass_getVertexAttributeBinding(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97510,7 +97322,7 @@ int lua_ax_base_Pass_getVertexAttributeBinding(lua_State* tolua_S) return 0; } auto&& ret = cobj->getVertexAttributeBinding(); - object_to_luaval(tolua_S, "ax.VertexAttribBinding",(ax::VertexAttribBinding*)ret); + object_to_luaval(tolua_S, "ax.VertexInputBinding",(ax::VertexInputBinding*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Pass:getVertexAttributeBinding",argc, 0); @@ -97549,7 +97361,7 @@ int lua_ax_base_Pass_setName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -97599,7 +97411,7 @@ int lua_ax_base_Pass_getName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97646,7 +97458,7 @@ int lua_ax_base_Pass_clone(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -97693,7 +97505,7 @@ int lua_ax_base_Pass_setTechnique(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Technique* arg0; @@ -97743,7 +97555,7 @@ int lua_ax_base_Pass_updateMVPUniform(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Mat4 arg0; @@ -97793,14 +97605,14 @@ int lua_ax_base_Pass_setUniformTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { unsigned int arg0; - ax::backend::TextureBackend* arg1; + ax::rhi::Texture* arg1; ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Pass:setUniformTexture"); - ok &= luaval_to_object(tolua_S, 3, "axb.TextureBackend",&arg1, "ax.Pass:setUniformTexture"); + ok &= luaval_to_object(tolua_S, 3, "axrhi.Texture",&arg1, "ax.Pass:setUniformTexture"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Pass_setUniformTexture'", nullptr); @@ -97846,14 +97658,14 @@ int lua_ax_base_Pass_setUniformNormTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { unsigned int arg0; - ax::backend::TextureBackend* arg1; + ax::rhi::Texture* arg1; ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Pass:setUniformNormTexture"); - ok &= luaval_to_object(tolua_S, 3, "axb.TextureBackend",&arg1, "ax.Pass:setUniformNormTexture"); + ok &= luaval_to_object(tolua_S, 3, "axrhi.Texture",&arg1, "ax.Pass:setUniformNormTexture"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Pass_setUniformNormTexture'", nullptr); @@ -97899,7 +97711,7 @@ int lua_ax_base_Pass_setUniformColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -97953,7 +97765,7 @@ int lua_ax_base_Pass_setUniformMatrixPalette(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98007,7 +97819,7 @@ int lua_ax_base_Pass_setUniformDirLightColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98061,7 +97873,7 @@ int lua_ax_base_Pass_setUniformDirLightDir(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98115,7 +97927,7 @@ int lua_ax_base_Pass_setUniformPointLightColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98169,7 +97981,7 @@ int lua_ax_base_Pass_setUniformPointLightPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98223,7 +98035,7 @@ int lua_ax_base_Pass_setUniformPointLightRangeInverse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98277,7 +98089,7 @@ int lua_ax_base_Pass_setUniformSpotLightColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98331,7 +98143,7 @@ int lua_ax_base_Pass_setUniformSpotLightPosition(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98385,7 +98197,7 @@ int lua_ax_base_Pass_setUniformSpotLightDir(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98439,7 +98251,7 @@ int lua_ax_base_Pass_setUniformSpotLightInnerAngleCos(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98493,7 +98305,7 @@ int lua_ax_base_Pass_setUniformSpotLightOuterAngleCos(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98547,7 +98359,7 @@ int lua_ax_base_Pass_setUniformSpotLightRangeInverse(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98601,7 +98413,7 @@ int lua_ax_base_Pass_setUniformAmbientLigthColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { const void* arg0; unsigned int arg1; @@ -98647,9 +98459,9 @@ int lua_ax_base_Pass_createWithProgramState(lua_State* tolua_S) if (argc == 2) { ax::Technique* arg0; - ax::backend::ProgramState* arg1; + ax::rhi::ProgramState* arg1; ok &= luaval_to_object(tolua_S, 2, "ax.Technique",&arg0, "ax.Pass:createWithProgramState"); - ok &= luaval_to_object(tolua_S, 3, "axb.ProgramState",&arg1, "ax.Pass:createWithProgramState"); + ok &= luaval_to_object(tolua_S, 3, "axrhi.ProgramState",&arg1, "ax.Pass:createWithProgramState"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Pass_createWithProgramState'", nullptr); @@ -98717,7 +98529,7 @@ int lua_register_ax_base_Pass(lua_State* tolua_S) tolua_beginmodule(tolua_S,"Pass"); tolua_function(tolua_S,"getProgramState",lua_ax_base_Pass_getProgramState); tolua_function(tolua_S,"draw",lua_ax_base_Pass_draw); - tolua_function(tolua_S,"setVertexAttribBinding",lua_ax_base_Pass_setVertexAttribBinding); + tolua_function(tolua_S,"setVertexInputBinding",lua_ax_base_Pass_setVertexInputBinding); tolua_function(tolua_S,"getVertexAttributeBinding",lua_ax_base_Pass_getVertexAttributeBinding); tolua_function(tolua_S,"setName",lua_ax_base_Pass_setName); tolua_function(tolua_S,"getName",lua_ax_base_Pass_getName); @@ -98749,6 +98561,507 @@ int lua_register_ax_base_Pass(lua_State* tolua_S) return 1; } +int lua_ax_base_ProgramManager_getBuiltinProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_getBuiltinProgram'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + unsigned int arg0; + + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.ProgramManager:getBuiltinProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_getBuiltinProgram'", nullptr); + return 0; + } + auto&& ret = cobj->getBuiltinProgram(arg0); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:getBuiltinProgram",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_getBuiltinProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_registerCustomProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_registerCustomProgram'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + std::string_view arg0; + std::string_view arg1; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.ProgramManager:registerCustomProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_registerCustomProgram'", nullptr); + return 0; + } + auto&& ret = cobj->registerCustomProgram(arg0, arg1); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + if (argc == 3) + { + std::string_view arg0; + std::string_view arg1; + ax::rhi::VertexLayoutType arg2; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.ProgramManager:registerCustomProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_registerCustomProgram'", nullptr); + return 0; + } + auto&& ret = cobj->registerCustomProgram(arg0, arg1, arg2); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + if (argc == 4) + { + std::string_view arg0; + std::string_view arg1; + ax::rhi::VertexLayoutType arg2; + bool arg3; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.ProgramManager:registerCustomProgram"); + + ok &= luaval_to_boolean(tolua_S, 5,&arg3, "ax.ProgramManager:registerCustomProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_registerCustomProgram'", nullptr); + return 0; + } + auto&& ret = cobj->registerCustomProgram(arg0, arg1, arg2, arg3); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:registerCustomProgram",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_registerCustomProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_loadProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_loadProgram'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 2) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + ax::rhi::Program* ret = cobj->loadProgram(arg0, arg1); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 3) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + std::string_view arg1; + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + ax::rhi::VertexLayoutType arg2; + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + ax::rhi::Program* ret = cobj->loadProgram(arg0, arg1, arg2); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + unsigned long long arg0; + ok &= luaval_to_long_long(tolua_S, 2,(long long*)&arg0, "ax.ProgramManager:loadProgram"); + + if (!ok) { break; } + ax::rhi::Program* ret = cobj->loadProgram(arg0); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:loadProgram",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_loadProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_unloadProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_unloadProgram'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::Program* arg0; + + ok &= luaval_to_object(tolua_S, 2, "axrhi.Program",&arg0, "ax.ProgramManager:unloadProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_unloadProgram'", nullptr); + return 0; + } + cobj->unloadProgram(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:unloadProgram",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_unloadProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_unloadUnusedPrograms(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_unloadUnusedPrograms'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_unloadUnusedPrograms'", nullptr); + return 0; + } + cobj->unloadUnusedPrograms(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:unloadUnusedPrograms",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_unloadUnusedPrograms'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_unloadAllPrograms(lua_State* tolua_S) +{ + int argc = 0; + ax::ProgramManager* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::ProgramManager*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_ProgramManager_unloadAllPrograms'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_unloadAllPrograms'", nullptr); + return 0; + } + cobj->unloadAllPrograms(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.ProgramManager:unloadAllPrograms",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_unloadAllPrograms'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_base_ProgramManager_getInstance(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_getInstance'", nullptr); + return 0; + } + auto&& ret = ax::ProgramManager::getInstance(); + object_to_luaval(tolua_S, "ax.ProgramManager",(ax::ProgramManager*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.ProgramManager:getInstance",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_getInstance'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_ProgramManager_destroyInstance(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_destroyInstance'", nullptr); + return 0; + } + ax::ProgramManager::destroyInstance(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.ProgramManager:destroyInstance",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_destroyInstance'.",&tolua_err); +#endif + return 0; +} +int lua_ax_base_ProgramManager_chooseSpriteProgramType(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.ProgramManager",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 1) + { + ax::rhi::PixelFormat arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.ProgramManager:chooseSpriteProgramType"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_ProgramManager_chooseSpriteProgramType'", nullptr); + return 0; + } + auto&& ret = ax::ProgramManager::chooseSpriteProgramType(arg0); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.ProgramManager:chooseSpriteProgramType",argc, 1); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_ProgramManager_chooseSpriteProgramType'.",&tolua_err); +#endif + return 0; +} +static int lua_ax_base_ProgramManager_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (ProgramManager)"); + return 0; +} + +int lua_register_ax_base_ProgramManager(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.ProgramManager"); + tolua_cclass(tolua_S,"ProgramManager","ax.ProgramManager","",nullptr); + + tolua_beginmodule(tolua_S,"ProgramManager"); + tolua_function(tolua_S,"getBuiltinProgram",lua_ax_base_ProgramManager_getBuiltinProgram); + tolua_function(tolua_S,"registerCustomProgram",lua_ax_base_ProgramManager_registerCustomProgram); + tolua_function(tolua_S,"loadProgram",lua_ax_base_ProgramManager_loadProgram); + tolua_function(tolua_S,"unloadProgram",lua_ax_base_ProgramManager_unloadProgram); + tolua_function(tolua_S,"unloadUnusedPrograms",lua_ax_base_ProgramManager_unloadUnusedPrograms); + tolua_function(tolua_S,"unloadAllPrograms",lua_ax_base_ProgramManager_unloadAllPrograms); + tolua_function(tolua_S,"getInstance", lua_ax_base_ProgramManager_getInstance); + tolua_function(tolua_S,"destroyInstance", lua_ax_base_ProgramManager_destroyInstance); + tolua_function(tolua_S,"chooseSpriteProgramType", lua_ax_base_ProgramManager_chooseSpriteProgramType); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::ProgramManager).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.ProgramManager"; + g_typeCast[typeName] = "ax.ProgramManager"; + return 1; +} + int lua_ax_base_Renderer_init(lua_State* tolua_S) { int argc = 0; @@ -98775,7 +99088,7 @@ int lua_ax_base_Renderer_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -98822,7 +99135,7 @@ int lua_ax_base_Renderer_addCallbackCommand(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::function arg0; @@ -98840,7 +99153,7 @@ int lua_ax_base_Renderer_addCallbackCommand(lua_State* tolua_S) lua_settop(tolua_S, 1); return 1; } - if (argc == 2) + if (argc == 2) { std::function arg0; double arg1; @@ -98956,7 +99269,7 @@ int lua_ax_base_Renderer_getNextGroupCommand(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99003,7 +99316,7 @@ int lua_ax_base_Renderer_pushGroup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -99053,7 +99366,7 @@ int lua_ax_base_Renderer_popGroup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99100,7 +99413,7 @@ int lua_ax_base_Renderer_createRenderQueue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99147,7 +99460,7 @@ int lua_ax_base_Renderer_render(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99194,7 +99507,7 @@ int lua_ax_base_Renderer_clean(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99241,7 +99554,7 @@ int lua_ax_base_Renderer_getDrawnBatches(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99288,7 +99601,7 @@ int lua_ax_base_Renderer_addDrawnBatches(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -99338,7 +99651,7 @@ int lua_ax_base_Renderer_getDrawnVertices(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99385,7 +99698,7 @@ int lua_ax_base_Renderer_addDrawnVertices(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -99435,7 +99748,7 @@ int lua_ax_base_Renderer_clearDrawStats(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99482,7 +99795,7 @@ int lua_ax_base_Renderer_getRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99490,7 +99803,7 @@ int lua_ax_base_Renderer_getRenderTarget(lua_State* tolua_S) return 0; } auto&& ret = cobj->getRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getRenderTarget",argc, 0); @@ -99529,11 +99842,11 @@ int lua_ax_base_Renderer_setRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::RenderTarget* arg0; + ax::rhi::RenderTarget* arg0; - ok &= luaval_to_object(tolua_S, 2, "axb.RenderTarget",&arg0, "ax.Renderer:setRenderTarget"); + ok &= luaval_to_object(tolua_S, 2, "axrhi.RenderTarget",&arg0, "ax.Renderer:setRenderTarget"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setRenderTarget'", nullptr); @@ -99579,7 +99892,7 @@ int lua_ax_base_Renderer_getDefaultRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99587,7 +99900,7 @@ int lua_ax_base_Renderer_getDefaultRenderTarget(lua_State* tolua_S) return 0; } auto&& ret = cobj->getDefaultRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getDefaultRenderTarget",argc, 0); @@ -99626,7 +99939,7 @@ int lua_ax_base_Renderer_getOffscreenRenderTarget(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99634,7 +99947,7 @@ int lua_ax_base_Renderer_getOffscreenRenderTarget(lua_State* tolua_S) return 0; } auto&& ret = cobj->getOffscreenRenderTarget(); - object_to_luaval(tolua_S, "axb.RenderTarget",(ax::backend::RenderTarget*)ret); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getOffscreenRenderTarget",argc, 0); @@ -99673,17 +99986,17 @@ int lua_ax_base_Renderer_clear(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 5) + if (argc == 5) { - ax::backend::TargetBufferFlags arg0; - ax::Color4F arg1; + ax::rhi::TargetBufferFlags arg0; + ax::Color arg1; double arg2; unsigned int arg3; double arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:clear"); - ok &=luaval_to_color4f(tolua_S, 3, &arg1, "ax.Renderer:clear"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "ax.Renderer:clear"); ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.Renderer:clear"); @@ -99735,7 +100048,7 @@ int lua_ax_base_Renderer_getClearColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99743,7 +100056,7 @@ int lua_ax_base_Renderer_getClearColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getClearColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getClearColor",argc, 0); @@ -99782,7 +100095,7 @@ int lua_ax_base_Renderer_getClearDepth(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99829,7 +100142,7 @@ int lua_ax_base_Renderer_getClearStencil(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99876,7 +100189,7 @@ int lua_ax_base_Renderer_getClearFlag(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -99923,7 +100236,7 @@ int lua_ax_base_Renderer_setDepthTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -99973,7 +100286,7 @@ int lua_ax_base_Renderer_setDepthWrite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -99997,7 +100310,7 @@ int lua_ax_base_Renderer_setDepthWrite(lua_State* tolua_S) return 0; } -int lua_ax_base_Renderer_setDepthCompareFunction(lua_State* tolua_S) +int lua_ax_base_Renderer_setDepthCompareFunc(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100017,32 +100330,32 @@ int lua_ax_base_Renderer_setDepthCompareFunction(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setDepthCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setDepthCompareFunc'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::CompareFunction arg0; + ax::rhi::CompareFunc arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setDepthCompareFunction"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setDepthCompareFunc"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setDepthCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setDepthCompareFunc'", nullptr); return 0; } - cobj->setDepthCompareFunction(arg0); + cobj->setDepthCompareFunc(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setDepthCompareFunction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setDepthCompareFunc",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setDepthCompareFunction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setDepthCompareFunc'.",&tolua_err); #endif return 0; @@ -100073,7 +100386,7 @@ int lua_ax_base_Renderer_getDepthTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100120,7 +100433,7 @@ int lua_ax_base_Renderer_getDepthWrite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100141,7 +100454,7 @@ int lua_ax_base_Renderer_getDepthWrite(lua_State* tolua_S) return 0; } -int lua_ax_base_Renderer_getDepthCompareFunction(lua_State* tolua_S) +int lua_ax_base_Renderer_getDepthCompareFunc(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100161,29 +100474,29 @@ int lua_ax_base_Renderer_getDepthCompareFunction(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getDepthCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getDepthCompareFunc'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getDepthCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getDepthCompareFunc'", nullptr); return 0; } - int ret = (int)cobj->getDepthCompareFunction(); + int ret = (int)cobj->getDepthCompareFunc(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getDepthCompareFunction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getDepthCompareFunc",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getDepthCompareFunction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getDepthCompareFunc'.",&tolua_err); #endif return 0; @@ -100214,7 +100527,7 @@ int lua_ax_base_Renderer_setStencilTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -100238,7 +100551,7 @@ int lua_ax_base_Renderer_setStencilTest(lua_State* tolua_S) return 0; } -int lua_ax_base_Renderer_setStencilCompareFunction(lua_State* tolua_S) +int lua_ax_base_Renderer_setStencilCompareFunc(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100258,43 +100571,43 @@ int lua_ax_base_Renderer_setStencilCompareFunction(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setStencilCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setStencilCompareFunc'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { - ax::backend::CompareFunction arg0; + ax::rhi::CompareFunc arg0; unsigned int arg1; unsigned int arg2; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setStencilCompareFunction"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setStencilCompareFunc"); - ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Renderer:setStencilCompareFunction"); + ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Renderer:setStencilCompareFunc"); - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Renderer:setStencilCompareFunction"); + ok &= luaval_to_uint32(tolua_S, 4,&arg2, "ax.Renderer:setStencilCompareFunc"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setStencilCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setStencilCompareFunc'", nullptr); return 0; } - cobj->setStencilCompareFunction(arg0, arg1, arg2); + cobj->setStencilCompareFunc(arg0, arg1, arg2); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setStencilCompareFunction",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setStencilCompareFunc",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setStencilCompareFunction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setStencilCompareFunc'.",&tolua_err); #endif return 0; } -int lua_ax_base_Renderer_setStencilOperation(lua_State* tolua_S) +int lua_ax_base_Renderer_setStencilOp(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100314,38 +100627,38 @@ int lua_ax_base_Renderer_setStencilOperation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setStencilOperation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_setStencilOp'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { - ax::backend::StencilOperation arg0; - ax::backend::StencilOperation arg1; - ax::backend::StencilOperation arg2; + ax::rhi::StencilOp arg0; + ax::rhi::StencilOp arg1; + ax::rhi::StencilOp arg2; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setStencilOperation"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setStencilOp"); - ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Renderer:setStencilOperation"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.Renderer:setStencilOp"); - ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Renderer:setStencilOperation"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.Renderer:setStencilOp"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setStencilOperation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_setStencilOp'", nullptr); return 0; } - cobj->setStencilOperation(arg0, arg1, arg2); + cobj->setStencilOp(arg0, arg1, arg2); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setStencilOperation",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:setStencilOp",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setStencilOperation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_setStencilOp'.",&tolua_err); #endif return 0; @@ -100376,7 +100689,7 @@ int lua_ax_base_Renderer_setStencilWriteMask(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -100426,7 +100739,7 @@ int lua_ax_base_Renderer_getStencilTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100447,7 +100760,7 @@ int lua_ax_base_Renderer_getStencilTest(lua_State* tolua_S) return 0; } -int lua_ax_base_Renderer_getStencilFailureOperation(lua_State* tolua_S) +int lua_ax_base_Renderer_getStencilFailureOp(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100467,34 +100780,34 @@ int lua_ax_base_Renderer_getStencilFailureOperation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilFailureOperation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilFailureOp'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilFailureOperation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilFailureOp'", nullptr); return 0; } - int ret = (int)cobj->getStencilFailureOperation(); + int ret = (int)cobj->getStencilFailureOp(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilFailureOperation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilFailureOp",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilFailureOperation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilFailureOp'.",&tolua_err); #endif return 0; } -int lua_ax_base_Renderer_getStencilPassDepthFailureOperation(lua_State* tolua_S) +int lua_ax_base_Renderer_getStencilPassDepthFailureOp(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100514,34 +100827,34 @@ int lua_ax_base_Renderer_getStencilPassDepthFailureOperation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOperation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOp'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOperation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOp'", nullptr); return 0; } - int ret = (int)cobj->getStencilPassDepthFailureOperation(); + int ret = (int)cobj->getStencilPassDepthFailureOp(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilPassDepthFailureOperation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilPassDepthFailureOp",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOperation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilPassDepthFailureOp'.",&tolua_err); #endif return 0; } -int lua_ax_base_Renderer_getStencilDepthPassOperation(lua_State* tolua_S) +int lua_ax_base_Renderer_getStencilDepthPassOp(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100561,34 +100874,34 @@ int lua_ax_base_Renderer_getStencilDepthPassOperation(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilDepthPassOperation'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilDepthPassOp'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilDepthPassOperation'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilDepthPassOp'", nullptr); return 0; } - int ret = (int)cobj->getStencilDepthPassOperation(); + int ret = (int)cobj->getStencilDepthPassOp(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilDepthPassOperation",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilDepthPassOp",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilDepthPassOperation'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilDepthPassOp'.",&tolua_err); #endif return 0; } -int lua_ax_base_Renderer_getStencilCompareFunction(lua_State* tolua_S) +int lua_ax_base_Renderer_getStencilCompareFunc(lua_State* tolua_S) { int argc = 0; ax::Renderer* cobj = nullptr; @@ -100608,29 +100921,29 @@ int lua_ax_base_Renderer_getStencilCompareFunction(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_getStencilCompareFunc'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilCompareFunction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_getStencilCompareFunc'", nullptr); return 0; } - int ret = (int)cobj->getStencilCompareFunction(); + int ret = (int)cobj->getStencilCompareFunc(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilCompareFunction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getStencilCompareFunc",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilCompareFunction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_getStencilCompareFunc'.",&tolua_err); #endif return 0; @@ -100661,7 +100974,7 @@ int lua_ax_base_Renderer_getStencilReadMask(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100708,7 +101021,7 @@ int lua_ax_base_Renderer_getStencilWriteMask(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100755,7 +101068,7 @@ int lua_ax_base_Renderer_getStencilReferenceValue(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100802,11 +101115,11 @@ int lua_ax_base_Renderer_setDepthStencilDesc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::DepthStencilDescriptor arg0; + ax::rhi::DepthStencilDesc arg0; - #pragma warning NO CONVERSION TO NATIVE FOR DepthStencilDescriptor + #pragma warning NO CONVERSION TO NATIVE FOR DepthStencilDesc ok = false; if(!ok) { @@ -100853,7 +101166,7 @@ int lua_ax_base_Renderer_getDepthStencilDesc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100861,7 +101174,7 @@ int lua_ax_base_Renderer_getDepthStencilDesc(lua_State* tolua_S) return 0; } auto&& ret = cobj->getDepthStencilDesc(); - #pragma warning NO CONVERSION FROM NATIVE FOR DepthStencilDescriptor; + #pragma warning NO CONVERSION FROM NATIVE FOR DepthStencilDesc; return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:getDepthStencilDesc",argc, 0); @@ -100900,9 +101213,9 @@ int lua_ax_base_Renderer_setCullMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::CullMode arg0; + ax::rhi::CullMode arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setCullMode"); if(!ok) @@ -100950,7 +101263,7 @@ int lua_ax_base_Renderer_getCullMode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -100997,9 +101310,9 @@ int lua_ax_base_Renderer_setWinding(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::backend::Winding arg0; + ax::rhi::Winding arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.Renderer:setWinding"); if(!ok) @@ -101047,7 +101360,7 @@ int lua_ax_base_Renderer_getWinding(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101094,7 +101407,7 @@ int lua_ax_base_Renderer_setViewPort(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { int arg0; int arg1; @@ -101153,7 +101466,7 @@ int lua_ax_base_Renderer_getViewport(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101200,7 +101513,7 @@ int lua_ax_base_Renderer_setScissorTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -101250,7 +101563,7 @@ int lua_ax_base_Renderer_setScissorRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { double arg0; double arg1; @@ -101309,7 +101622,7 @@ int lua_ax_base_Renderer_getScissorTest(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101356,7 +101669,7 @@ int lua_ax_base_Renderer_getScissorRect(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101403,7 +101716,7 @@ int lua_ax_base_Renderer_checkVisibility(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Mat4 arg0; ax::Vec2 arg1; @@ -101456,12 +101769,12 @@ int lua_ax_base_Renderer_readPixels(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { - ax::backend::RenderTarget* arg0; - std::function arg1; + ax::rhi::RenderTarget* arg0; + std::function arg1; - ok &= luaval_to_object(tolua_S, 2, "axb.RenderTarget",&arg0, "ax.Renderer:readPixels"); + ok &= luaval_to_object(tolua_S, 2, "axrhi.RenderTarget",&arg0, "ax.Renderer:readPixels"); do { // Lambda binding for lua is not supported. @@ -101513,7 +101826,7 @@ int lua_ax_base_Renderer_beginRenderPass(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101560,7 +101873,7 @@ int lua_ax_base_Renderer_endRenderPass(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101607,7 +101920,7 @@ int lua_ax_base_Renderer_nextCallbackCommand(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101628,6 +101941,59 @@ int lua_ax_base_Renderer_nextCallbackCommand(lua_State* tolua_S) return 0; } +int lua_ax_base_Renderer_resizeSwapChain(lua_State* tolua_S) +{ + int argc = 0; + ax::Renderer* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.Renderer",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::Renderer*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_base_Renderer_resizeSwapChain'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + unsigned int arg0; + unsigned int arg1; + + ok &= luaval_to_uint32(tolua_S, 2,&arg0, "ax.Renderer:resizeSwapChain"); + + ok &= luaval_to_uint32(tolua_S, 3,&arg1, "ax.Renderer:resizeSwapChain"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_Renderer_resizeSwapChain'", nullptr); + return 0; + } + cobj->resizeSwapChain(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.Renderer:resizeSwapChain",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_base_Renderer_resizeSwapChain'.",&tolua_err); +#endif + + return 0; +} int lua_ax_base_Renderer_constructor(lua_State* tolua_S) { int argc = 0; @@ -101641,7 +102007,7 @@ int lua_ax_base_Renderer_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101701,19 +102067,19 @@ int lua_register_ax_base_Renderer(lua_State* tolua_S) tolua_function(tolua_S,"getClearFlag",lua_ax_base_Renderer_getClearFlag); tolua_function(tolua_S,"setDepthTest",lua_ax_base_Renderer_setDepthTest); tolua_function(tolua_S,"setDepthWrite",lua_ax_base_Renderer_setDepthWrite); - tolua_function(tolua_S,"setDepthCompareFunction",lua_ax_base_Renderer_setDepthCompareFunction); + tolua_function(tolua_S,"setDepthCompareFunc",lua_ax_base_Renderer_setDepthCompareFunc); tolua_function(tolua_S,"getDepthTest",lua_ax_base_Renderer_getDepthTest); tolua_function(tolua_S,"getDepthWrite",lua_ax_base_Renderer_getDepthWrite); - tolua_function(tolua_S,"getDepthCompareFunction",lua_ax_base_Renderer_getDepthCompareFunction); + tolua_function(tolua_S,"getDepthCompareFunc",lua_ax_base_Renderer_getDepthCompareFunc); tolua_function(tolua_S,"setStencilTest",lua_ax_base_Renderer_setStencilTest); - tolua_function(tolua_S,"setStencilCompareFunction",lua_ax_base_Renderer_setStencilCompareFunction); - tolua_function(tolua_S,"setStencilOperation",lua_ax_base_Renderer_setStencilOperation); + tolua_function(tolua_S,"setStencilCompareFunc",lua_ax_base_Renderer_setStencilCompareFunc); + tolua_function(tolua_S,"setStencilOp",lua_ax_base_Renderer_setStencilOp); tolua_function(tolua_S,"setStencilWriteMask",lua_ax_base_Renderer_setStencilWriteMask); tolua_function(tolua_S,"getStencilTest",lua_ax_base_Renderer_getStencilTest); - tolua_function(tolua_S,"getStencilFailureOperation",lua_ax_base_Renderer_getStencilFailureOperation); - tolua_function(tolua_S,"getStencilPassDepthFailureOperation",lua_ax_base_Renderer_getStencilPassDepthFailureOperation); - tolua_function(tolua_S,"getStencilDepthPassOperation",lua_ax_base_Renderer_getStencilDepthPassOperation); - tolua_function(tolua_S,"getStencilCompareFunction",lua_ax_base_Renderer_getStencilCompareFunction); + tolua_function(tolua_S,"getStencilFailureOp",lua_ax_base_Renderer_getStencilFailureOp); + tolua_function(tolua_S,"getStencilPassDepthFailureOp",lua_ax_base_Renderer_getStencilPassDepthFailureOp); + tolua_function(tolua_S,"getStencilDepthPassOp",lua_ax_base_Renderer_getStencilDepthPassOp); + tolua_function(tolua_S,"getStencilCompareFunc",lua_ax_base_Renderer_getStencilCompareFunc); tolua_function(tolua_S,"getStencilReadMask",lua_ax_base_Renderer_getStencilReadMask); tolua_function(tolua_S,"getStencilWriteMask",lua_ax_base_Renderer_getStencilWriteMask); tolua_function(tolua_S,"getStencilReferenceValue",lua_ax_base_Renderer_getStencilReferenceValue); @@ -101734,6 +102100,7 @@ int lua_register_ax_base_Renderer(lua_State* tolua_S) tolua_function(tolua_S,"beginRenderPass",lua_ax_base_Renderer_beginRenderPass); tolua_function(tolua_S,"endRenderPass",lua_ax_base_Renderer_endRenderPass); tolua_function(tolua_S,"nextCallbackCommand",lua_ax_base_Renderer_nextCallbackCommand); + tolua_function(tolua_S,"resizeSwapChain",lua_ax_base_Renderer_resizeSwapChain); tolua_endmodule(tolua_S); auto typeName = typeid(ax::Renderer).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.Renderer"; @@ -101767,7 +102134,7 @@ int lua_ax_base_TextureCache_getDescription(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101869,7 +102236,7 @@ int lua_ax_base_TextureCache_getDummyTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -101917,7 +102284,7 @@ int lua_ax_base_TextureCache_addImage(lua_State* tolua_S) ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "ax.TextureCache:addImage"); if (!ok) { break; } - ax::backend::PixelFormat arg1; + ax::rhi::PixelFormat arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.TextureCache:addImage"); if (!ok) { break; } @@ -101965,7 +102332,7 @@ int lua_ax_base_TextureCache_addImage(lua_State* tolua_S) ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "ax.TextureCache:addImage"); if (!ok) { break; } - ax::backend::PixelFormat arg2; + ax::rhi::PixelFormat arg2; ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.TextureCache:addImage"); if (!ok) { break; } @@ -102027,7 +102394,7 @@ int lua_ax_base_TextureCache_unbindImageAsync(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -102077,7 +102444,7 @@ int lua_ax_base_TextureCache_unbindAllImageAsync(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -102124,7 +102491,7 @@ int lua_ax_base_TextureCache_getTextureForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -102174,7 +102541,7 @@ int lua_ax_base_TextureCache_reloadTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -102224,7 +102591,7 @@ int lua_ax_base_TextureCache_removeAllTextures(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -102271,7 +102638,7 @@ int lua_ax_base_TextureCache_removeUnusedTextures(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -102318,7 +102685,7 @@ int lua_ax_base_TextureCache_removeTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -102368,7 +102735,7 @@ int lua_ax_base_TextureCache_removeTextureForKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -102418,7 +102785,7 @@ int lua_ax_base_TextureCache_getCachedTextureInfo(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -102465,7 +102832,7 @@ int lua_ax_base_TextureCache_waitForQuit(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -102512,7 +102879,7 @@ int lua_ax_base_TextureCache_getTextureFilePath(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -102562,7 +102929,7 @@ int lua_ax_base_TextureCache_renameTextureWithKey(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::string_view arg1; @@ -102672,7 +103039,7 @@ int lua_ax_base_TextureCache_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103213,7 +103580,7 @@ int lua_ax_base_Application_setAnimationInterval(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -103263,7 +103630,7 @@ int lua_ax_base_Application_getCurrentLanguage(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103310,7 +103677,7 @@ int lua_ax_base_Application_getCurrentLanguageCode(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103357,7 +103724,7 @@ int lua_ax_base_Application_getTargetPlatform(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103404,7 +103771,7 @@ int lua_ax_base_Application_getVersion(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103451,7 +103818,7 @@ int lua_ax_base_Application_openURL(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -103729,7 +104096,7 @@ int lua_ax_base_AnimationCache_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -103776,7 +104143,7 @@ int lua_ax_base_AnimationCache_addAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Animation* arg0; std::string_view arg1; @@ -103829,7 +104196,7 @@ int lua_ax_base_AnimationCache_removeAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -103879,7 +104246,7 @@ int lua_ax_base_AnimationCache_getAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -103929,7 +104296,7 @@ int lua_ax_base_AnimationCache_addAnimationsWithDictionary(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::ValueMap arg0; std::string_view arg1; @@ -103982,7 +104349,7 @@ int lua_ax_base_AnimationCache_addAnimationsWithFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -104087,7 +104454,7 @@ int lua_ax_base_AnimationCache_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -104163,7 +104530,7 @@ int lua_ax_base_SpriteBatchNode_getTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -104210,7 +104577,7 @@ int lua_ax_base_SpriteBatchNode_setTextureAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TextureAtlas* arg0; @@ -104260,7 +104627,7 @@ int lua_ax_base_SpriteBatchNode_increaseAtlasCapacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -104307,7 +104674,7 @@ int lua_ax_base_SpriteBatchNode_removeChildAtIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ssize_t arg0; bool arg1; @@ -104360,7 +104727,7 @@ int lua_ax_base_SpriteBatchNode_appendChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -104410,7 +104777,7 @@ int lua_ax_base_SpriteBatchNode_removeSpriteFromAtlas(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -104460,7 +104827,7 @@ int lua_ax_base_SpriteBatchNode_rebuildIndexInOrder(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Sprite* arg0; ssize_t arg1; @@ -104513,7 +104880,7 @@ int lua_ax_base_SpriteBatchNode_highestAtlasIndexInChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -104563,7 +104930,7 @@ int lua_ax_base_SpriteBatchNode_lowestAtlasIndexInChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Sprite* arg0; @@ -104613,7 +104980,7 @@ int lua_ax_base_SpriteBatchNode_atlasIndexForChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Sprite* arg0; int arg1; @@ -104666,7 +105033,7 @@ int lua_ax_base_SpriteBatchNode_reorderBatch(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -104716,7 +105083,7 @@ int lua_ax_base_SpriteBatchNode_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -104763,7 +105130,7 @@ int lua_ax_base_SpriteBatchNode_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -104813,7 +105180,7 @@ int lua_ax_base_SpriteBatchNode_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -104863,7 +105230,7 @@ int lua_ax_base_SpriteBatchNode_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -104910,7 +105277,7 @@ int lua_ax_base_SpriteBatchNode_removeAllChildrenWithCleanup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -104960,7 +105327,7 @@ int lua_ax_base_SpriteBatchNode_insertQuadFromSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { ax::Sprite* arg0; ssize_t arg1; @@ -105013,7 +105380,7 @@ int lua_ax_base_SpriteBatchNode_addSpriteWithoutQuad(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Sprite* arg0; int arg1; @@ -105069,7 +105436,7 @@ int lua_ax_base_SpriteBatchNode_reserveCapacity(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ssize_t arg0; @@ -105119,7 +105486,7 @@ int lua_ax_base_SpriteBatchNode_initWithTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -105133,7 +105500,7 @@ int lua_ax_base_SpriteBatchNode_initWithTexture(lua_State* tolua_S) tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 2) + if (argc == 2) { ax::Texture2D* arg0; ssize_t arg1; @@ -105186,7 +105553,7 @@ int lua_ax_base_SpriteBatchNode_initWithFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -105200,7 +105567,7 @@ int lua_ax_base_SpriteBatchNode_initWithFile(lua_State* tolua_S) tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 2) + if (argc == 2) { std::string_view arg0; ssize_t arg1; @@ -105342,7 +105709,7 @@ int lua_ax_base_SpriteBatchNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -105435,7 +105802,7 @@ int lua_ax_base_ParallaxNode_addChild(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { ax::Node* arg0; int arg1; @@ -105494,7 +105861,7 @@ int lua_ax_base_ParallaxNode_removeAllChildrenWithCleanup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -105565,7 +105932,7 @@ int lua_ax_base_ParallaxNode_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -105638,7 +106005,7 @@ int lua_ax_base_TMXObjectGroup_getGroupName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -105685,7 +106052,7 @@ int lua_ax_base_TMXObjectGroup_setGroupName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -105735,7 +106102,7 @@ int lua_ax_base_TMXObjectGroup_getProperty(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -105785,7 +106152,7 @@ int lua_ax_base_TMXObjectGroup_getObject(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -105835,7 +106202,7 @@ int lua_ax_base_TMXObjectGroup_getPositionOffset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -105882,7 +106249,7 @@ int lua_ax_base_TMXObjectGroup_setPositionOffset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -105979,7 +106346,7 @@ int lua_ax_base_TMXObjectGroup_setProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMap arg0; @@ -106076,7 +106443,7 @@ int lua_ax_base_TMXObjectGroup_setObjects(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueVector arg0; @@ -106113,7 +106480,7 @@ int lua_ax_base_TMXObjectGroup_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106193,7 +106560,7 @@ int lua_ax_base_TMXLayerInfo_setProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMap arg0; @@ -106243,7 +106610,7 @@ int lua_ax_base_TMXLayerInfo_getProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106277,7 +106644,7 @@ int lua_ax_base_TMXLayerInfo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106349,7 +106716,7 @@ int lua_ax_base_TMXTilesetInfo_getRectForGID(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { unsigned int arg0; @@ -106386,7 +106753,7 @@ int lua_ax_base_TMXTilesetInfo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106457,7 +106824,7 @@ int lua_ax_base_TMXMapInfo_initWithTMXFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -106507,7 +106874,7 @@ int lua_ax_base_TMXMapInfo_initWithXML(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::string_view arg1; @@ -106560,7 +106927,7 @@ int lua_ax_base_TMXMapInfo_parseXMLFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -106610,7 +106977,7 @@ int lua_ax_base_TMXMapInfo_parseXMLString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -106660,7 +107027,7 @@ int lua_ax_base_TMXMapInfo_getTileProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106707,7 +107074,7 @@ int lua_ax_base_TMXMapInfo_setTileProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMapIntKey arg0; @@ -106757,7 +107124,7 @@ int lua_ax_base_TMXMapInfo_getOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106804,7 +107171,7 @@ int lua_ax_base_TMXMapInfo_setOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -106854,7 +107221,7 @@ int lua_ax_base_TMXMapInfo_getStaggerAxis(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106901,7 +107268,7 @@ int lua_ax_base_TMXMapInfo_setStaggerAxis(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -106951,7 +107318,7 @@ int lua_ax_base_TMXMapInfo_getStaggerIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -106998,7 +107365,7 @@ int lua_ax_base_TMXMapInfo_setStaggerIndex(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -107048,7 +107415,7 @@ int lua_ax_base_TMXMapInfo_getHexSideLength(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107095,7 +107462,7 @@ int lua_ax_base_TMXMapInfo_setHexSideLength(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -107145,7 +107512,7 @@ int lua_ax_base_TMXMapInfo_getMapSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107192,7 +107559,7 @@ int lua_ax_base_TMXMapInfo_setMapSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -107242,7 +107609,7 @@ int lua_ax_base_TMXMapInfo_getTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107289,7 +107656,7 @@ int lua_ax_base_TMXMapInfo_setTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -107386,7 +107753,7 @@ int lua_ax_base_TMXMapInfo_setLayers(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -107483,7 +107850,7 @@ int lua_ax_base_TMXMapInfo_setTilesets(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -107580,7 +107947,7 @@ int lua_ax_base_TMXMapInfo_setObjectGroups(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -107630,7 +107997,7 @@ int lua_ax_base_TMXMapInfo_getParentElement(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107677,7 +108044,7 @@ int lua_ax_base_TMXMapInfo_setParentElement(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -107727,7 +108094,7 @@ int lua_ax_base_TMXMapInfo_getParentGID(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107774,7 +108141,7 @@ int lua_ax_base_TMXMapInfo_setParentGID(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -107824,7 +108191,7 @@ int lua_ax_base_TMXMapInfo_getLayerAttribs(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107871,7 +108238,7 @@ int lua_ax_base_TMXMapInfo_setLayerAttribs(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -107921,7 +108288,7 @@ int lua_ax_base_TMXMapInfo_isStoringCharacters(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -107968,7 +108335,7 @@ int lua_ax_base_TMXMapInfo_setStoringCharacters(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -108065,7 +108432,7 @@ int lua_ax_base_TMXMapInfo_setProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMap arg0; @@ -108115,7 +108482,7 @@ int lua_ax_base_TMXMapInfo_getCurrentString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108162,7 +108529,7 @@ int lua_ax_base_TMXMapInfo_setCurrentString(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -108212,7 +108579,7 @@ int lua_ax_base_TMXMapInfo_getTMXFileName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108259,7 +108626,7 @@ int lua_ax_base_TMXMapInfo_setTMXFileName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -108309,7 +108676,7 @@ int lua_ax_base_TMXMapInfo_getExternalTilesetFileName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108417,7 +108784,7 @@ int lua_ax_base_TMXMapInfo_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108528,7 +108895,7 @@ int lua_ax_base_TileMapAtlas_initWithTileFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 4) { std::string_view arg0; std::string_view arg1; @@ -108587,7 +108954,7 @@ int lua_ax_base_TileMapAtlas_getTileAt(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -108598,7 +108965,7 @@ int lua_ax_base_TileMapAtlas_getTileAt(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTileAt(arg0); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.TileMapAtlas:getTileAt",argc, 1); @@ -108637,12 +109004,12 @@ int lua_ax_base_TileMapAtlas_setTile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { - ax::Color3B arg0; + ax::Color32 arg0; ax::Vec2 arg1; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.TileMapAtlas:setTile"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.TileMapAtlas:setTile"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.TileMapAtlas:setTile"); if(!ok) @@ -108690,7 +109057,7 @@ int lua_ax_base_TileMapAtlas_releaseMap(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108766,7 +109133,7 @@ int lua_ax_base_TileMapAtlas_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -108908,7 +109275,7 @@ int lua_ax_base_FastTMXLayer_removeTileAt(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -108958,7 +109325,7 @@ int lua_ax_base_FastTMXLayer_getPositionAt(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -109008,7 +109375,7 @@ int lua_ax_base_FastTMXLayer_getProperty(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -109058,7 +109425,7 @@ int lua_ax_base_FastTMXLayer_setupTiles(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109105,7 +109472,7 @@ int lua_ax_base_FastTMXLayer_getLayerName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109152,7 +109519,7 @@ int lua_ax_base_FastTMXLayer_setLayerName(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -109202,7 +109569,7 @@ int lua_ax_base_FastTMXLayer_getLayerSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109249,7 +109616,7 @@ int lua_ax_base_FastTMXLayer_setLayerSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -109299,7 +109666,7 @@ int lua_ax_base_FastTMXLayer_getMapTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109346,7 +109713,7 @@ int lua_ax_base_FastTMXLayer_setMapTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -109396,7 +109763,7 @@ int lua_ax_base_FastTMXLayer_getTileSet(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109443,7 +109810,7 @@ int lua_ax_base_FastTMXLayer_setTileSet(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::TMXTilesetInfo* arg0; @@ -109493,7 +109860,7 @@ int lua_ax_base_FastTMXLayer_getLayerOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109540,7 +109907,7 @@ int lua_ax_base_FastTMXLayer_setLayerOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -109637,7 +110004,7 @@ int lua_ax_base_FastTMXLayer_setProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMap arg0; @@ -109687,7 +110054,7 @@ int lua_ax_base_FastTMXLayer_getTileAt(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -109737,7 +110104,7 @@ int lua_ax_base_FastTMXLayer_setupTileSprite(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::Sprite* arg0; ax::Vec2 arg1; @@ -109793,7 +110160,7 @@ int lua_ax_base_FastTMXLayer_getAnimTileCoord(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109840,7 +110207,7 @@ int lua_ax_base_FastTMXLayer_hasTileAnimation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109887,7 +110254,7 @@ int lua_ax_base_FastTMXLayer_getTileAnimManager(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -109934,7 +110301,7 @@ int lua_ax_base_FastTMXLayer_initWithTilesetInfo(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::TMXTilesetInfo* arg0; ax::TMXLayerInfo* arg1; @@ -110017,7 +110384,7 @@ int lua_ax_base_FastTMXLayer_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110111,7 +110478,7 @@ int lua_ax_base_TMXTileAnimTask_start(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110158,7 +110525,7 @@ int lua_ax_base_TMXTileAnimTask_stop(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110205,7 +110572,7 @@ int lua_ax_base_TMXTileAnimTask_isRunning(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110300,7 +110667,7 @@ int lua_ax_base_TMXTileAnimTask_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 3) { ax::FastTMXLayer* arg0; ax::TMXTileAnimInfo* arg1; @@ -110324,7 +110691,7 @@ int lua_ax_base_TMXTileAnimTask_constructor(lua_State* tolua_S) toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"ax.TMXTileAnimTask"); return 1; } - if (argc == 4) + if (argc == 4) { ax::FastTMXLayer* arg0; ax::TMXTileAnimInfo* arg1; @@ -110411,7 +110778,7 @@ int lua_ax_base_TMXTileAnimManager_startAll(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110458,7 +110825,7 @@ int lua_ax_base_TMXTileAnimManager_stopAll(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110505,7 +110872,7 @@ int lua_ax_base_TMXTileAnimManager_getTasks(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110575,7 +110942,7 @@ int lua_ax_base_TMXTileAnimManager_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::FastTMXLayer* arg0; @@ -110652,7 +111019,7 @@ int lua_ax_base_FastTMXTiledMap_getLayer(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -110702,7 +111069,7 @@ int lua_ax_base_FastTMXTiledMap_getObjectGroup(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -110752,7 +111119,7 @@ int lua_ax_base_FastTMXTiledMap_getProperty(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -110802,7 +111169,7 @@ int lua_ax_base_FastTMXTiledMap_getPropertiesForGID(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -110852,7 +111219,7 @@ int lua_ax_base_FastTMXTiledMap_getMapSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110899,7 +111266,7 @@ int lua_ax_base_FastTMXTiledMap_setMapSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -110949,7 +111316,7 @@ int lua_ax_base_FastTMXTiledMap_getTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -110996,7 +111363,7 @@ int lua_ax_base_FastTMXTiledMap_setTileSize(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec2 arg0; @@ -111046,7 +111413,7 @@ int lua_ax_base_FastTMXTiledMap_getMapOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111093,7 +111460,7 @@ int lua_ax_base_FastTMXTiledMap_setMapOrientation(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { int arg0; @@ -111190,7 +111557,7 @@ int lua_ax_base_FastTMXTiledMap_setObjectGroups(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vector arg0; @@ -111240,7 +111607,7 @@ int lua_ax_base_FastTMXTiledMap_getProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111287,7 +111654,7 @@ int lua_ax_base_FastTMXTiledMap_setProperties(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::ValueMap arg0; @@ -111337,7 +111704,7 @@ int lua_ax_base_FastTMXTiledMap_setTileAnimEnabled(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -111387,7 +111754,7 @@ int lua_ax_base_FastTMXTiledMap_getLayerCount(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111434,7 +111801,7 @@ int lua_ax_base_FastTMXTiledMap_getResourceFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111481,7 +111848,7 @@ int lua_ax_base_FastTMXTiledMap_getMapInfo(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111528,7 +111895,7 @@ int lua_ax_base_FastTMXTiledMap_getTilesetInfo(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -111578,7 +111945,7 @@ int lua_ax_base_FastTMXTiledMap_getLayers(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111625,7 +111992,7 @@ int lua_ax_base_FastTMXTiledMap_initWithTMXFile(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -111639,7 +112006,7 @@ int lua_ax_base_FastTMXTiledMap_initWithTMXFile(lua_State* tolua_S) tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 2) + if (argc == 2) { std::string_view arg0; bool arg1; @@ -111692,7 +112059,7 @@ int lua_ax_base_FastTMXTiledMap_initWithXML(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 2) + if (argc == 2) { std::string_view arg0; std::string_view arg1; @@ -111709,7 +112076,7 @@ int lua_ax_base_FastTMXTiledMap_initWithXML(lua_State* tolua_S) tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 3) + if (argc == 3) { std::string_view arg0; std::string_view arg1; @@ -111858,7 +112225,7 @@ int lua_ax_base_FastTMXTiledMap_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -111952,11 +112319,11 @@ int lua_ax_base_MotionStreak3D_tintWithColor(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ax.MotionStreak3D:tintWithColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ax.MotionStreak3D:tintWithColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_base_MotionStreak3D_tintWithColor'", nullptr); @@ -112002,7 +112369,7 @@ int lua_ax_base_MotionStreak3D_reset(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112049,7 +112416,7 @@ int lua_ax_base_MotionStreak3D_getStroke(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112096,7 +112463,7 @@ int lua_ax_base_MotionStreak3D_setStroke(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -112146,7 +112513,7 @@ int lua_ax_base_MotionStreak3D_isStartingPositionInitialized(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112193,7 +112560,7 @@ int lua_ax_base_MotionStreak3D_setStartingPositionInitialized(lua_State* tolua_S #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { bool arg0; @@ -112243,7 +112610,7 @@ int lua_ax_base_MotionStreak3D_getTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112290,7 +112657,7 @@ int lua_ax_base_MotionStreak3D_setTexture(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Texture2D* arg0; @@ -112340,7 +112707,7 @@ int lua_ax_base_MotionStreak3D_setBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::BlendFunc arg0; @@ -112390,7 +112757,7 @@ int lua_ax_base_MotionStreak3D_getBlendFunc(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112437,7 +112804,7 @@ int lua_ax_base_MotionStreak3D_setSweepAxis(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { ax::Vec3 arg0; @@ -112487,7 +112854,7 @@ int lua_ax_base_MotionStreak3D_getSweepAxis(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112543,8 +112910,8 @@ int lua_ax_base_MotionStreak3D_initWithFade(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak3D:initWithFade"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak3D:initWithFade"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak3D:initWithFade"); if (!ok) { break; } ax::Texture2D* arg4; @@ -112571,8 +112938,8 @@ int lua_ax_base_MotionStreak3D_initWithFade(lua_State* tolua_S) ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak3D:initWithFade"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak3D:initWithFade"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak3D:initWithFade"); if (!ok) { break; } std::string_view arg4; @@ -112609,7 +112976,7 @@ int lua_ax_base_MotionStreak3D_create(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - do + do { if (argc == 5) { @@ -112622,8 +112989,8 @@ int lua_ax_base_MotionStreak3D_create(lua_State* tolua_S) double arg2; ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak3D:create"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak3D:create"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak3D:create"); if (!ok) { break; } ax::Texture2D* arg4; ok &= luaval_to_object(tolua_S, 6, "ax.Texture2D",&arg4, "ax.MotionStreak3D:create"); @@ -112634,7 +113001,7 @@ int lua_ax_base_MotionStreak3D_create(lua_State* tolua_S) } } while (0); ok = true; - do + do { if (argc == 5) { @@ -112647,8 +113014,8 @@ int lua_ax_base_MotionStreak3D_create(lua_State* tolua_S) double arg2; ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.MotionStreak3D:create"); if (!ok) { break; } - ax::Color3B arg3; - ok &= luaval_to_color3b(tolua_S, 5, &arg3, "ax.MotionStreak3D:create"); + ax::Color32 arg3; + ok &=luaval_to_color32(tolua_S, 5, &arg3, "ax.MotionStreak3D:create"); if (!ok) { break; } std::string_view arg4; ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "ax.MotionStreak3D:create"); @@ -112680,7 +113047,7 @@ int lua_ax_base_MotionStreak3D_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112764,7 +113131,7 @@ int lua_ax_base_ComponentLua_getScriptObject(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 0) { if(!ok) { @@ -112811,7 +113178,7 @@ int lua_ax_base_ComponentLua_update(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { double arg0; @@ -112884,7 +113251,7 @@ int lua_ax_base_ComponentLua_constructor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 1) { std::string_view arg0; @@ -112936,30 +113303,25 @@ int lua_register_ax_base_ComponentLua(lua_State* tolua_S) TOLUA_API int register_all_ax_base(lua_State* tolua_S) { tolua_open(tolua_S); - + tolua_module(tolua_S,"ax",0); tolua_beginmodule(tolua_S,"ax"); lua_register_ax_base_Object(tolua_S); - lua_register_ax_base_EventListener(tolua_S); - lua_register_ax_base_EventListenerCustom(tolua_S); - lua_register_ax_base_ShaderCache(tolua_S); - lua_register_ax_base_Texture2D(tolua_S); lua_register_ax_base_Touch(tolua_S); lua_register_ax_base_Event(tolua_S); lua_register_ax_base_EventTouch(tolua_S); lua_register_ax_base_EventKeyboard(tolua_S); - lua_register_ax_base_Component(tolua_S); - lua_register_ax_base_Node(tolua_S); - lua_register_ax_base_Scene(tolua_S); - lua_register_ax_base_RenderView(tolua_S); - lua_register_ax_base_Director(tolua_S); - lua_register_ax_base_Timer(tolua_S); - lua_register_ax_base_Scheduler(tolua_S); lua_register_ax_base_Action(tolua_S); lua_register_ax_base_FiniteTimeAction(tolua_S); lua_register_ax_base_Speed(tolua_S); lua_register_ax_base_Follow(tolua_S); + lua_register_ax_base_EventListener(tolua_S); + lua_register_ax_base_EventListenerCustom(tolua_S); + lua_register_ax_base_ShaderCache(tolua_S); + lua_register_ax_base_Texture2D(tolua_S); + lua_register_ax_base_Component(tolua_S); + lua_register_ax_base_Node(tolua_S); lua_register_ax_base_Image(tolua_S); lua_register_ax_base_PolygonInfo(tolua_S); lua_register_ax_base_AutoPolygon(tolua_S); @@ -112993,7 +113355,12 @@ TOLUA_API int register_all_ax_base(lua_State* tolua_S) lua_register_ax_base_Animate(tolua_S); lua_register_ax_base_TargetedAction(tolua_S); lua_register_ax_base_ActionFloat(tolua_S); + lua_register_ax_base_Scene(tolua_S); + lua_register_ax_base_RenderView(tolua_S); + lua_register_ax_base_Director(tolua_S); lua_register_ax_base_Properties(tolua_S); + lua_register_ax_base_Timer(tolua_S); + lua_register_ax_base_Scheduler(tolua_S); lua_register_ax_base_UserDefault(tolua_S); lua_register_ax_base_FileUtils(tolua_S); lua_register_ax_base_EventAcceleration(tolua_S); @@ -113191,6 +113558,7 @@ TOLUA_API int register_all_ax_base(lua_State* tolua_S) lua_register_ax_base_Technique(tolua_S); lua_register_ax_base_Material(tolua_S); lua_register_ax_base_Pass(tolua_S); + lua_register_ax_base_ProgramManager(tolua_S); lua_register_ax_base_Renderer(tolua_S); lua_register_ax_base_TextureCache(tolua_S); lua_register_ax_base_Device(tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_base_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_base_auto.hpp index c346a6c88520..5d1b9c97263f 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_base_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_base_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_base(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_controller_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_controller_auto.cpp index 29968afbac9f..0b468e8bb978 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_controller_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_controller_auto.cpp @@ -1,6 +1,6 @@ #include "lua-bindings/auto/axlua_controller_auto.hpp" #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS) -#include "base/GameController.h" +#include "axmol/base/GameController.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_controller_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_controller_auto.hpp index 0c3a894c9954..670204f4ca35 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_controller_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_controller_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_controller(lua_State* tolua_S); #endif //#if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS) diff --git a/extensions/scripting/lua-bindings/auto/axlua_csloader_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_csloader_auto.hpp index fc9fb5ece9d5..bf07a4070089 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_csloader_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_csloader_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_csloader(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_extension_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_extension_auto.hpp index 8d5cfd15e08e..f75fd2dd3eb0 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_extension_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_extension_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_extension(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.cpp index 7749a483116f..703e6875fc8d 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.cpp @@ -8003,7 +8003,7 @@ int lua_ax_fairygui_GImage_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GImage:getColor",argc, 0); @@ -8044,9 +8044,9 @@ int lua_ax_fairygui_GImage_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GImage:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GImage:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GImage_setColor'", nullptr); @@ -9030,7 +9030,7 @@ int lua_ax_fairygui_GMovieClip_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GMovieClip:getColor",argc, 0); @@ -9071,9 +9071,9 @@ int lua_ax_fairygui_GMovieClip_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GMovieClip:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GMovieClip:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GMovieClip_setColor'", nullptr); @@ -9662,7 +9662,7 @@ int lua_ax_fairygui_GTextField_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GTextField:getColor",argc, 0); @@ -9703,9 +9703,9 @@ int lua_ax_fairygui_GTextField_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GTextField:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GTextField:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GTextField_setColor'", nullptr); @@ -9856,7 +9856,7 @@ int lua_ax_fairygui_GTextField_getOutlineColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getOutlineColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GTextField:getOutlineColor",argc, 0); @@ -9897,9 +9897,9 @@ int lua_ax_fairygui_GTextField_setOutlineColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GTextField:setOutlineColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GTextField:setOutlineColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GTextField_setOutlineColor'", nullptr); @@ -10767,8 +10767,8 @@ int lua_ax_fairygui_GGraph_drawRect(lua_State* tolua_S) double arg0; double arg1; int arg2; - ax::Color4B arg3; - ax::Color4B arg4; + ax::Color arg3; + ax::Color arg4; ok &= luaval_to_number(tolua_S, 2,&arg0, "fgui.GGraph:drawRect"); @@ -10776,9 +10776,9 @@ int lua_ax_fairygui_GGraph_drawRect(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "fgui.GGraph:drawRect"); - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "fgui.GGraph:drawRect"); + ok &=luaval_to_color(tolua_S, 5, &arg3, "fgui.GGraph:drawRect"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "fgui.GGraph:drawRect"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "fgui.GGraph:drawRect"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GGraph_drawRect'", nullptr); @@ -10829,8 +10829,8 @@ int lua_ax_fairygui_GGraph_drawEllipse(lua_State* tolua_S) double arg0; double arg1; int arg2; - ax::Color4B arg3; - ax::Color4B arg4; + ax::Color arg3; + ax::Color arg4; ok &= luaval_to_number(tolua_S, 2,&arg0, "fgui.GGraph:drawEllipse"); @@ -10838,9 +10838,9 @@ int lua_ax_fairygui_GGraph_drawEllipse(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "fgui.GGraph:drawEllipse"); - ok &=luaval_to_color4b(tolua_S, 5, &arg3, "fgui.GGraph:drawEllipse"); + ok &=luaval_to_color(tolua_S, 5, &arg3, "fgui.GGraph:drawEllipse"); - ok &=luaval_to_color4b(tolua_S, 6, &arg4, "fgui.GGraph:drawEllipse"); + ok &=luaval_to_color(tolua_S, 6, &arg4, "fgui.GGraph:drawEllipse"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GGraph_drawEllipse'", nullptr); @@ -10889,16 +10889,16 @@ int lua_ax_fairygui_GGraph_drawPolygon(lua_State* tolua_S) if (argc == 5) { int arg0; - ax::Color4B arg1; - ax::Color4B arg2; + ax::Color arg1; + ax::Color arg2; const ax::Vec2* arg3; int arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "fgui.GGraph:drawPolygon"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GGraph:drawPolygon"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "fgui.GGraph:drawPolygon"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "fgui.GGraph:drawPolygon"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "fgui.GGraph:drawPolygon"); ok &= luaval_to_object(tolua_S, 5, "ax.Vec2",&arg3, "fgui.GGraph:drawPolygon"); @@ -10951,15 +10951,15 @@ int lua_ax_fairygui_GGraph_drawRegularPolygon(lua_State* tolua_S) if (argc == 4) { int arg0; - ax::Color4B arg1; - ax::Color4B arg2; + ax::Color arg1; + ax::Color arg2; int arg3; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "fgui.GGraph:drawRegularPolygon"); if(!ok) @@ -10974,16 +10974,16 @@ int lua_ax_fairygui_GGraph_drawRegularPolygon(lua_State* tolua_S) if (argc == 5) { int arg0; - ax::Color4B arg1; - ax::Color4B arg2; + ax::Color arg1; + ax::Color arg2; int arg3; double arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "fgui.GGraph:drawRegularPolygon"); @@ -11000,17 +11000,17 @@ int lua_ax_fairygui_GGraph_drawRegularPolygon(lua_State* tolua_S) if (argc == 6) { int arg0; - ax::Color4B arg1; - ax::Color4B arg2; + ax::Color arg1; + ax::Color arg2; int arg3; double arg4; const float* arg5; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "fgui.GGraph:drawRegularPolygon"); @@ -11030,8 +11030,8 @@ int lua_ax_fairygui_GGraph_drawRegularPolygon(lua_State* tolua_S) if (argc == 7) { int arg0; - ax::Color4B arg1; - ax::Color4B arg2; + ax::Color arg1; + ax::Color arg2; int arg3; double arg4; const float* arg5; @@ -11039,9 +11039,9 @@ int lua_ax_fairygui_GGraph_drawRegularPolygon(lua_State* tolua_S) ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 3, &arg1, "fgui.GGraph:drawRegularPolygon"); - ok &=luaval_to_color4b(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); + ok &=luaval_to_color(tolua_S, 4, &arg2, "fgui.GGraph:drawRegularPolygon"); ok &= luaval_to_int32(tolua_S, 5,(int *)&arg3, "fgui.GGraph:drawRegularPolygon"); @@ -11151,7 +11151,7 @@ int lua_ax_fairygui_GGraph_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GGraph:getColor",argc, 0); @@ -11192,9 +11192,9 @@ int lua_ax_fairygui_GGraph_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GGraph:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GGraph:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GGraph_setColor'", nullptr); @@ -11976,7 +11976,7 @@ int lua_ax_fairygui_GLoader_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GLoader:getColor",argc, 0); @@ -12017,9 +12017,9 @@ int lua_ax_fairygui_GLoader_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GLoader:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GLoader:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GLoader_setColor'", nullptr); @@ -20929,7 +20929,7 @@ int lua_ax_fairygui_GButton_getTitleColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTitleColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GButton:getTitleColor",argc, 0); @@ -20970,9 +20970,9 @@ int lua_ax_fairygui_GButton_setTitleColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GButton:setTitleColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GButton:setTitleColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GButton_setTitleColor'", nullptr); @@ -24357,7 +24357,7 @@ int lua_ax_fairygui_GComboBox_getTitleColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTitleColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "fgui.GComboBox:getTitleColor",argc, 0); @@ -24398,9 +24398,9 @@ int lua_ax_fairygui_GComboBox_setTitleColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "fgui.GComboBox:setTitleColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GComboBox:setTitleColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GComboBox_setTitleColor'", nullptr); @@ -32562,7 +32562,7 @@ int lua_ax_fairygui_GTween_toVec4(lua_State* tolua_S) #endif return 0; } -int lua_ax_fairygui_GTween_toColor4B(lua_State* tolua_S) +int lua_ax_fairygui_GTween_toColor32(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -32579,26 +32579,26 @@ int lua_ax_fairygui_GTween_toColor4B(lua_State* tolua_S) if (argc == 3) { - ax::Color4B arg0; - ax::Color4B arg1; + ax::Color32 arg0; + ax::Color32 arg1; double arg2; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "fgui.GTween:toColor4B"); - ok &=luaval_to_color4b(tolua_S, 3, &arg1, "fgui.GTween:toColor4B"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "fgui.GTween:toColor4B"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "fgui.GTween:toColor32"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "fgui.GTween:toColor32"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "fgui.GTween:toColor32"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GTween_toColor4B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_fairygui_GTween_toColor32'", nullptr); return 0; } - auto&& ret = fairygui::GTween::toColor4B(arg0, arg1, arg2); + auto&& ret = fairygui::GTween::toColor32(arg0, arg1, arg2); object_to_luaval(tolua_S, "fgui.GTweener",(fairygui::GTweener*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "fgui.GTween:toColor4B",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "fgui.GTween:toColor32",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_fairygui_GTween_toColor4B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_fairygui_GTween_toColor32'.",&tolua_err); #endif return 0; } @@ -32938,7 +32938,7 @@ int lua_register_ax_fairygui_GTween(lua_State* tolua_S) tolua_function(tolua_S,"toVec2", lua_ax_fairygui_GTween_toVec2); tolua_function(tolua_S,"toVec3", lua_ax_fairygui_GTween_toVec3); tolua_function(tolua_S,"toVec4", lua_ax_fairygui_GTween_toVec4); - tolua_function(tolua_S,"toColor4B", lua_ax_fairygui_GTween_toColor4B); + tolua_function(tolua_S,"toColor32", lua_ax_fairygui_GTween_toColor32); tolua_function(tolua_S,"toDouble", lua_ax_fairygui_GTween_toDouble); tolua_function(tolua_S,"delayedCall", lua_ax_fairygui_GTween_delayedCall); tolua_function(tolua_S,"shake", lua_ax_fairygui_GTween_shake); diff --git a/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.hpp index 2f6e99e5a88c..b4fa463313ef 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_fairygui_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_fairygui(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.cpp index 95ec777abdf7..5e45ec340981 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.cpp @@ -1,6 +1,6 @@ #include "lua-bindings/auto/axlua_navmesh_auto.hpp" #if defined(AX_ENABLE_NAVMESH) -#include "navmesh/NavMesh.h" +#include "axmol/navmesh/NavMesh.h" #include "lua-bindings/manual/navmesh/axlua_navmesh_conversions.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.hpp index aebc15e466c3..876b8a02eed2 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_navmesh_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_NAVMESH) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_navmesh(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_NAVMESH) diff --git a/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.cpp index 165cfc106fc6..1954bd6b627d 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.cpp @@ -1,6 +1,6 @@ #include "lua-bindings/auto/axlua_physics3d_auto.hpp" #if defined(AX_ENABLE_3D_PHYSICS) -#include "physics3d/Physics3D.h" +#include "axmol/physics3d/Physics3D.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.hpp index 2c7cda30dab4..512a85b683ae 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_physics3d_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_3D_PHYSICS) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_physics3d(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_3D_PHYSICS) diff --git a/extensions/scripting/lua-bindings/auto/axlua_physics_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_physics_auto.cpp index c7ea23f0394a..3c75649fa006 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_physics_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_physics_auto.cpp @@ -1,13 +1,13 @@ #include "lua-bindings/auto/axlua_physics_auto.hpp" #if defined(AX_ENABLE_PHYSICS) -#include "axmol.h" +#include "axmol/axmol.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" -int lua_ax_physics_PhysicsShape_getBody(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getBody(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -16,15 +16,15 @@ int lua_ax_physics_PhysicsShape_getBody(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getBody'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getBody'", nullptr); return 0; } #endif @@ -34,27 +34,27 @@ int lua_ax_physics_PhysicsShape_getBody(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getBody'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getBody'", nullptr); return 0; } auto&& ret = cobj->getBody(); object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getBody",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getBody",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getBody'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getBody'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getType(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getType(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -63,15 +63,15 @@ int lua_ax_physics_PhysicsShape_getType(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getType'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getType'", nullptr); return 0; } #endif @@ -81,27 +81,27 @@ int lua_ax_physics_PhysicsShape_getType(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getType'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getType'", nullptr); return 0; } int ret = (int)cobj->getType(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getType",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getType",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getType'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getType'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getArea(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getArea(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -110,15 +110,15 @@ int lua_ax_physics_PhysicsShape_getArea(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getArea'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getArea'", nullptr); return 0; } #endif @@ -128,27 +128,27 @@ int lua_ax_physics_PhysicsShape_getArea(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getArea'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getArea'", nullptr); return 0; } auto&& ret = cobj->getArea(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getArea",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getArea",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getArea'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getArea'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setTag(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -157,45 +157,48 @@ int lua_ax_physics_PhysicsShape_getMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsCollider:setTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setTag'", nullptr); return 0; } - auto&& ret = cobj->getMoment(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setTag(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getMoment",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setTag",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setTag'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getTag(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -204,48 +207,45 @@ int lua_ax_physics_PhysicsShape_setMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getTag'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShape:setMoment"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getTag'", nullptr); return 0; } - cobj->setMoment(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getTag(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setMoment",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getTag",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getTag'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setTag(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getDensity(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -254,48 +254,45 @@ int lua_ax_physics_PhysicsShape_setTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getDensity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShape:setTag"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getDensity'", nullptr); return 0; } - cobj->setTag(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getDensity(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setTag",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getDensity",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getDensity'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getTag(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setDensity(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -304,45 +301,65 @@ int lua_ax_physics_PhysicsShape_getTag(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getTag'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setDensity'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setDensity"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getTag'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setDensity'", nullptr); return 0; } - auto&& ret = cobj->getTag(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + cobj->setDensity(arg0); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 2) + { + double arg0; + bool arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setDensity"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsCollider:setDensity"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setDensity'", nullptr); + return 0; + } + cobj->setDensity(arg0, arg1); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getTag",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setDensity",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getTag'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setDensity'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getMass(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getRestitution(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -351,15 +368,15 @@ int lua_ax_physics_PhysicsShape_getMass(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getMass'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getRestitution'", nullptr); return 0; } #endif @@ -369,27 +386,27 @@ int lua_ax_physics_PhysicsShape_getMass(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getMass'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getRestitution'", nullptr); return 0; } - auto&& ret = cobj->getMass(); + auto&& ret = cobj->getRestitution(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getMass",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getRestitution",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getMass'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getRestitution'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setMass(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setRestitution(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -398,15 +415,15 @@ int lua_ax_physics_PhysicsShape_setMass(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setMass'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setRestitution'", nullptr); return 0; } #endif @@ -416,30 +433,47 @@ int lua_ax_physics_PhysicsShape_setMass(lua_State* tolua_S) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShape:setMass"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setRestitution"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setRestitution'", nullptr); + return 0; + } + cobj->setRestitution(arg0); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 2) + { + double arg0; + bool arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setRestitution"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsCollider:setRestitution"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setMass'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setRestitution'", nullptr); return 0; } - cobj->setMass(arg0); + cobj->setRestitution(arg0, arg1); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setMass",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setRestitution",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setMass'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setRestitution'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getDensity(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getFriction(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -448,15 +482,15 @@ int lua_ax_physics_PhysicsShape_getDensity(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getDensity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getFriction'", nullptr); return 0; } #endif @@ -466,27 +500,27 @@ int lua_ax_physics_PhysicsShape_getDensity(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getDensity'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getFriction'", nullptr); return 0; } - auto&& ret = cobj->getDensity(); + auto&& ret = cobj->getFriction(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getDensity",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getFriction",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getDensity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getFriction'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setDensity(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setFriction(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -495,15 +529,15 @@ int lua_ax_physics_PhysicsShape_setDensity(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setDensity'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setFriction'", nullptr); return 0; } #endif @@ -513,30 +547,47 @@ int lua_ax_physics_PhysicsShape_setDensity(lua_State* tolua_S) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShape:setDensity"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setFriction"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setDensity'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setFriction'", nullptr); return 0; } - cobj->setDensity(arg0); + cobj->setFriction(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setDensity",argc, 1); + if (argc == 2) + { + double arg0; + bool arg1; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsCollider:setFriction"); + + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsCollider:setFriction"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setFriction'", nullptr); + return 0; + } + cobj->setFriction(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setFriction",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setDensity'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setFriction'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getRestitution(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getMaterial(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -545,15 +596,15 @@ int lua_ax_physics_PhysicsShape_getRestitution(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getRestitution'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getMaterial'", nullptr); return 0; } #endif @@ -563,27 +614,27 @@ int lua_ax_physics_PhysicsShape_getRestitution(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getRestitution'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getMaterial'", nullptr); return 0; } - auto&& ret = cobj->getRestitution(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getMaterial(); + physics_material_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getRestitution",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getMaterial",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getRestitution'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getMaterial'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setRestitution(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setMaterial(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -592,15 +643,15 @@ int lua_ax_physics_PhysicsShape_setRestitution(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setRestitution'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setMaterial'", nullptr); return 0; } #endif @@ -608,32 +659,32 @@ int lua_ax_physics_PhysicsShape_setRestitution(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - double arg0; + ax::PhysicsMaterial arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShape:setRestitution"); + ok &= luaval_to_physics_material(tolua_S, 2, &arg0, "ax.PhysicsCollider:setMaterial"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setRestitution'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setMaterial'", nullptr); return 0; } - cobj->setRestitution(arg0); + cobj->setMaterial(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setRestitution",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setMaterial",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setRestitution'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setMaterial'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getFriction(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_isSensor(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -642,15 +693,15 @@ int lua_ax_physics_PhysicsShape_getFriction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getFriction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_isSensor'", nullptr); return 0; } #endif @@ -660,27 +711,27 @@ int lua_ax_physics_PhysicsShape_getFriction(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getFriction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_isSensor'", nullptr); return 0; } - auto&& ret = cobj->getFriction(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->isSensor(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getFriction",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:isSensor",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getFriction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_isSensor'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setFriction(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setSensor(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -689,15 +740,15 @@ int lua_ax_physics_PhysicsShape_setFriction(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setFriction'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setSensor'", nullptr); return 0; } #endif @@ -705,32 +756,32 @@ int lua_ax_physics_PhysicsShape_setFriction(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - double arg0; + bool arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShape:setFriction"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsCollider:setSensor"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setFriction'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setSensor'", nullptr); return 0; } - cobj->setFriction(arg0); + cobj->setSensor(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setFriction",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setSensor",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setFriction'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setSensor'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getMaterial(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getOffset(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -739,15 +790,15 @@ int lua_ax_physics_PhysicsShape_getMaterial(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getMaterial'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getOffset'", nullptr); return 0; } #endif @@ -757,27 +808,27 @@ int lua_ax_physics_PhysicsShape_getMaterial(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getMaterial'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getOffset'", nullptr); return 0; } - auto&& ret = cobj->getMaterial(); - physics_material_to_luaval(tolua_S, ret); + auto&& ret = cobj->getOffset(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getMaterial",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getOffset",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getMaterial'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getOffset'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setMaterial(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getCenter(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -786,48 +837,45 @@ int lua_ax_physics_PhysicsShape_setMaterial(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setMaterial'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getCenter'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::PhysicsMaterial arg0; - - ok &= luaval_to_physics_material(tolua_S, 2, &arg0, "ax.PhysicsShape:setMaterial"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setMaterial'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getCenter'", nullptr); return 0; } - cobj->setMaterial(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getCenter(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setMaterial",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getCenter",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setMaterial'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getCenter'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_isSensor(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_containsPoint(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -836,45 +884,48 @@ int lua_ax_physics_PhysicsShape_isSensor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_isSensor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_containsPoint'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsCollider:containsPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_isSensor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_containsPoint'", nullptr); return 0; } - auto&& ret = cobj->isSensor(); + auto&& ret = cobj->containsPoint(arg0); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:isSensor",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:containsPoint",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_isSensor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_containsPoint'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setSensor(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setCategoryBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -883,15 +934,15 @@ int lua_ax_physics_PhysicsShape_setSensor(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setSensor'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setCategoryBitmask'", nullptr); return 0; } #endif @@ -899,32 +950,32 @@ int lua_ax_physics_PhysicsShape_setSensor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - bool arg0; + int arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsShape:setSensor"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsCollider:setCategoryBitmask"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setSensor'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setCategoryBitmask'", nullptr); return 0; } - cobj->setSensor(arg0); + cobj->setCategoryBitmask(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setSensor",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setCategoryBitmask",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setSensor'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setCategoryBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_calculateDefaultMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getCategoryBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -933,15 +984,15 @@ int lua_ax_physics_PhysicsShape_calculateDefaultMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_calculateDefaultMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getCategoryBitmask'", nullptr); return 0; } #endif @@ -951,27 +1002,27 @@ int lua_ax_physics_PhysicsShape_calculateDefaultMoment(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_calculateDefaultMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getCategoryBitmask'", nullptr); return 0; } - auto&& ret = cobj->calculateDefaultMoment(); + auto&& ret = cobj->getCategoryBitmask(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:calculateDefaultMoment",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getCategoryBitmask",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_calculateDefaultMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getCategoryBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getOffset(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setContactTestBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -980,92 +1031,48 @@ int lua_ax_physics_PhysicsShape_getOffset(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getOffset'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setContactTestBitmask'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getOffset'", nullptr); - return 0; - } - auto&& ret = cobj->getOffset(); - vec2_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getOffset",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getOffset'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsShape_getCenter(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsShape* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 1) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getCenter'", nullptr); - return 0; - } -#endif + int arg0; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsCollider:setContactTestBitmask"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getCenter'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setContactTestBitmask'", nullptr); return 0; } - auto&& ret = cobj->getCenter(); - vec2_to_luaval(tolua_S, ret); + cobj->setContactTestBitmask(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getCenter",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setContactTestBitmask",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getCenter'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setContactTestBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_containsPoint(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getContactTestBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1074,48 +1081,45 @@ int lua_ax_physics_PhysicsShape_containsPoint(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_containsPoint'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getContactTestBitmask'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShape:containsPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_containsPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getContactTestBitmask'", nullptr); return 0; } - auto&& ret = cobj->containsPoint(arg0); - tolua_pushboolean(tolua_S,(bool)ret); + auto&& ret = cobj->getContactTestBitmask(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:containsPoint",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getContactTestBitmask",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_containsPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getContactTestBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setCategoryBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setCollisionBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1124,15 +1128,15 @@ int lua_ax_physics_PhysicsShape_setCategoryBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setCategoryBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setCollisionBitmask'", nullptr); return 0; } #endif @@ -1142,30 +1146,30 @@ int lua_ax_physics_PhysicsShape_setCategoryBitmask(lua_State* tolua_S) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShape:setCategoryBitmask"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsCollider:setCollisionBitmask"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setCategoryBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setCollisionBitmask'", nullptr); return 0; } - cobj->setCategoryBitmask(arg0); + cobj->setCollisionBitmask(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setCategoryBitmask",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setCollisionBitmask",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setCategoryBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setCollisionBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getCategoryBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getCollisionBitmask(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1174,15 +1178,15 @@ int lua_ax_physics_PhysicsShape_getCategoryBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getCategoryBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getCollisionBitmask'", nullptr); return 0; } #endif @@ -1192,27 +1196,27 @@ int lua_ax_physics_PhysicsShape_getCategoryBitmask(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getCategoryBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getCollisionBitmask'", nullptr); return 0; } - auto&& ret = cobj->getCategoryBitmask(); + auto&& ret = cobj->getCollisionBitmask(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getCategoryBitmask",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getCollisionBitmask",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getCategoryBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getCollisionBitmask'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setContactTestBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_setGroup(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1221,15 +1225,15 @@ int lua_ax_physics_PhysicsShape_setContactTestBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setContactTestBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_setGroup'", nullptr); return 0; } #endif @@ -1239,30 +1243,30 @@ int lua_ax_physics_PhysicsShape_setContactTestBitmask(lua_State* tolua_S) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShape:setContactTestBitmask"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsCollider:setGroup"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setContactTestBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_setGroup'", nullptr); return 0; } - cobj->setContactTestBitmask(arg0); + cobj->setGroup(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setContactTestBitmask",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:setGroup",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setContactTestBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_setGroup'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getContactTestBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getGroup(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1271,15 +1275,15 @@ int lua_ax_physics_PhysicsShape_getContactTestBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getContactTestBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_getGroup'", nullptr); return 0; } #endif @@ -1289,27 +1293,27 @@ int lua_ax_physics_PhysicsShape_getContactTestBitmask(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getContactTestBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getGroup'", nullptr); return 0; } - auto&& ret = cobj->getContactTestBitmask(); + auto&& ret = cobj->getGroup(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getContactTestBitmask",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:getGroup",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getContactTestBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getGroup'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setCollisionBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_deatchFromBody(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1318,48 +1322,45 @@ int lua_ax_physics_PhysicsShape_setCollisionBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setCollisionBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_deatchFromBody'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShape:setCollisionBitmask"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setCollisionBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_deatchFromBody'", nullptr); return 0; } - cobj->setCollisionBitmask(arg0); + cobj->deatchFromBody(); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setCollisionBitmask",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:deatchFromBody",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setCollisionBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_deatchFromBody'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_getCollisionBitmask(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_isDeatched(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; + ax::PhysicsCollider* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1368,15 +1369,15 @@ int lua_ax_physics_PhysicsShape_getCollisionBitmask(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsCollider*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getCollisionBitmask'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsCollider_isDeatched'", nullptr); return 0; } #endif @@ -1386,174 +1387,169 @@ int lua_ax_physics_PhysicsShape_getCollisionBitmask(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getCollisionBitmask'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_isDeatched'", nullptr); return 0; } - auto&& ret = cobj->getCollisionBitmask(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->isDeatched(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getCollisionBitmask",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsCollider:isDeatched",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getCollisionBitmask'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_isDeatched'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShape_setGroup(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_recenterPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); + argc = lua_gettop(tolua_S) - 1; -#if _AX_DEBUG >= 1 - if (!cobj) + if (argc == 2) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_setGroup'", nullptr); - return 0; + ax::Vec2* arg0; + int arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsCollider:recenterPoints"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PhysicsCollider:recenterPoints"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_recenterPoints'", nullptr); + return 0; + } + ax::PhysicsCollider::recenterPoints(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 3) { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShape:setGroup"); + ax::Vec2* arg0; + int arg1; + ax::Vec2 arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsCollider:recenterPoints"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PhysicsCollider:recenterPoints"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsCollider:recenterPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_setGroup'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_recenterPoints'", nullptr); return 0; } - cobj->setGroup(arg0); + ax::PhysicsCollider::recenterPoints(arg0, arg1, arg2); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:setGroup",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsCollider:recenterPoints",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_setGroup'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_recenterPoints'.",&tolua_err); #endif - return 0; } -int lua_ax_physics_PhysicsShape_getGroup(lua_State* tolua_S) +int lua_ax_physics_PhysicsCollider_getPolygonCenter(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShape* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif - #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShape",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsCollider",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShape*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShape_getGroup'", nullptr); - return 0; - } -#endif + argc = lua_gettop(tolua_S) - 1; - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 2) { + const ax::Vec2* arg0; + int arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsCollider:getPolygonCenter"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PhysicsCollider:getPolygonCenter"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShape_getGroup'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsCollider_getPolygonCenter'", nullptr); return 0; } - auto&& ret = cobj->getGroup(); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = ax::PhysicsCollider::getPolygonCenter(arg0, arg1); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShape:getGroup",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsCollider:getPolygonCenter",argc, 2); return 0; - #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShape_getGroup'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsCollider_getPolygonCenter'.",&tolua_err); #endif - return 0; } -static int lua_ax_physics_PhysicsShape_finalize(lua_State* tolua_S) +static int lua_ax_physics_PhysicsCollider_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShape)"); + AXLOGV("luabindings: finalizing LUA object (PhysicsCollider)"); return 0; } -int lua_register_ax_physics_PhysicsShape(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsCollider(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShape"); - tolua_cclass(tolua_S,"PhysicsShape","ax.PhysicsShape","ax.Object",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsCollider"); + tolua_cclass(tolua_S,"PhysicsCollider","ax.PhysicsCollider","ax.Object",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShape"); - tolua_function(tolua_S,"getBody",lua_ax_physics_PhysicsShape_getBody); - tolua_function(tolua_S,"getType",lua_ax_physics_PhysicsShape_getType); - tolua_function(tolua_S,"getArea",lua_ax_physics_PhysicsShape_getArea); - tolua_function(tolua_S,"getMoment",lua_ax_physics_PhysicsShape_getMoment); - tolua_function(tolua_S,"setMoment",lua_ax_physics_PhysicsShape_setMoment); - tolua_function(tolua_S,"setTag",lua_ax_physics_PhysicsShape_setTag); - tolua_function(tolua_S,"getTag",lua_ax_physics_PhysicsShape_getTag); - tolua_function(tolua_S,"getMass",lua_ax_physics_PhysicsShape_getMass); - tolua_function(tolua_S,"setMass",lua_ax_physics_PhysicsShape_setMass); - tolua_function(tolua_S,"getDensity",lua_ax_physics_PhysicsShape_getDensity); - tolua_function(tolua_S,"setDensity",lua_ax_physics_PhysicsShape_setDensity); - tolua_function(tolua_S,"getRestitution",lua_ax_physics_PhysicsShape_getRestitution); - tolua_function(tolua_S,"setRestitution",lua_ax_physics_PhysicsShape_setRestitution); - tolua_function(tolua_S,"getFriction",lua_ax_physics_PhysicsShape_getFriction); - tolua_function(tolua_S,"setFriction",lua_ax_physics_PhysicsShape_setFriction); - tolua_function(tolua_S,"getMaterial",lua_ax_physics_PhysicsShape_getMaterial); - tolua_function(tolua_S,"setMaterial",lua_ax_physics_PhysicsShape_setMaterial); - tolua_function(tolua_S,"isSensor",lua_ax_physics_PhysicsShape_isSensor); - tolua_function(tolua_S,"setSensor",lua_ax_physics_PhysicsShape_setSensor); - tolua_function(tolua_S,"calculateDefaultMoment",lua_ax_physics_PhysicsShape_calculateDefaultMoment); - tolua_function(tolua_S,"getOffset",lua_ax_physics_PhysicsShape_getOffset); - tolua_function(tolua_S,"getCenter",lua_ax_physics_PhysicsShape_getCenter); - tolua_function(tolua_S,"containsPoint",lua_ax_physics_PhysicsShape_containsPoint); - tolua_function(tolua_S,"setCategoryBitmask",lua_ax_physics_PhysicsShape_setCategoryBitmask); - tolua_function(tolua_S,"getCategoryBitmask",lua_ax_physics_PhysicsShape_getCategoryBitmask); - tolua_function(tolua_S,"setContactTestBitmask",lua_ax_physics_PhysicsShape_setContactTestBitmask); - tolua_function(tolua_S,"getContactTestBitmask",lua_ax_physics_PhysicsShape_getContactTestBitmask); - tolua_function(tolua_S,"setCollisionBitmask",lua_ax_physics_PhysicsShape_setCollisionBitmask); - tolua_function(tolua_S,"getCollisionBitmask",lua_ax_physics_PhysicsShape_getCollisionBitmask); - tolua_function(tolua_S,"setGroup",lua_ax_physics_PhysicsShape_setGroup); - tolua_function(tolua_S,"getGroup",lua_ax_physics_PhysicsShape_getGroup); + tolua_beginmodule(tolua_S,"PhysicsCollider"); + tolua_function(tolua_S,"getBody",lua_ax_physics_PhysicsCollider_getBody); + tolua_function(tolua_S,"getType",lua_ax_physics_PhysicsCollider_getType); + tolua_function(tolua_S,"getArea",lua_ax_physics_PhysicsCollider_getArea); + tolua_function(tolua_S,"setTag",lua_ax_physics_PhysicsCollider_setTag); + tolua_function(tolua_S,"getTag",lua_ax_physics_PhysicsCollider_getTag); + tolua_function(tolua_S,"getDensity",lua_ax_physics_PhysicsCollider_getDensity); + tolua_function(tolua_S,"setDensity",lua_ax_physics_PhysicsCollider_setDensity); + tolua_function(tolua_S,"getRestitution",lua_ax_physics_PhysicsCollider_getRestitution); + tolua_function(tolua_S,"setRestitution",lua_ax_physics_PhysicsCollider_setRestitution); + tolua_function(tolua_S,"getFriction",lua_ax_physics_PhysicsCollider_getFriction); + tolua_function(tolua_S,"setFriction",lua_ax_physics_PhysicsCollider_setFriction); + tolua_function(tolua_S,"getMaterial",lua_ax_physics_PhysicsCollider_getMaterial); + tolua_function(tolua_S,"setMaterial",lua_ax_physics_PhysicsCollider_setMaterial); + tolua_function(tolua_S,"isSensor",lua_ax_physics_PhysicsCollider_isSensor); + tolua_function(tolua_S,"setSensor",lua_ax_physics_PhysicsCollider_setSensor); + tolua_function(tolua_S,"getOffset",lua_ax_physics_PhysicsCollider_getOffset); + tolua_function(tolua_S,"getCenter",lua_ax_physics_PhysicsCollider_getCenter); + tolua_function(tolua_S,"containsPoint",lua_ax_physics_PhysicsCollider_containsPoint); + tolua_function(tolua_S,"setCategoryBitmask",lua_ax_physics_PhysicsCollider_setCategoryBitmask); + tolua_function(tolua_S,"getCategoryBitmask",lua_ax_physics_PhysicsCollider_getCategoryBitmask); + tolua_function(tolua_S,"setContactTestBitmask",lua_ax_physics_PhysicsCollider_setContactTestBitmask); + tolua_function(tolua_S,"getContactTestBitmask",lua_ax_physics_PhysicsCollider_getContactTestBitmask); + tolua_function(tolua_S,"setCollisionBitmask",lua_ax_physics_PhysicsCollider_setCollisionBitmask); + tolua_function(tolua_S,"getCollisionBitmask",lua_ax_physics_PhysicsCollider_getCollisionBitmask); + tolua_function(tolua_S,"setGroup",lua_ax_physics_PhysicsCollider_setGroup); + tolua_function(tolua_S,"getGroup",lua_ax_physics_PhysicsCollider_getGroup); + tolua_function(tolua_S,"deatchFromBody",lua_ax_physics_PhysicsCollider_deatchFromBody); + tolua_function(tolua_S,"isDeatched",lua_ax_physics_PhysicsCollider_isDeatched); + tolua_function(tolua_S,"recenterPoints", lua_ax_physics_PhysicsCollider_recenterPoints); + tolua_function(tolua_S,"getPolygonCenter", lua_ax_physics_PhysicsCollider_getPolygonCenter); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShape).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShape"; - g_typeCast[typeName] = "ax.PhysicsShape"; + auto typeName = typeid(ax::PhysicsCollider).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsCollider"; + g_typeCast[typeName] = "ax.PhysicsCollider"; return 1; } -int lua_ax_physics_PhysicsShapeCircle_getRadius(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderCircle_getRadius(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeCircle* cobj = nullptr; + ax::PhysicsColliderCircle* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1562,15 +1558,15 @@ int lua_ax_physics_PhysicsShapeCircle_getRadius(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeCircle",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderCircle",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeCircle*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderCircle*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeCircle_getRadius'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderCircle_getRadius'", nullptr); return 0; } #endif @@ -1580,24 +1576,24 @@ int lua_ax_physics_PhysicsShapeCircle_getRadius(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_getRadius'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderCircle_getRadius'", nullptr); return 0; } auto&& ret = cobj->getRadius(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeCircle:getRadius",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderCircle:getRadius",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeCircle_getRadius'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderCircle_getRadius'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeCircle_create(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderCircle_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1607,65 +1603,71 @@ int lua_ax_physics_PhysicsShapeCircle_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeCircle",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderCircle",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:create"); + ax::PhysicsBody* arg0; + double arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsColliderCircle:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderCircle_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeCircle::create(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeCircle",(ax::PhysicsShapeCircle*)ret); + auto&& ret = ax::PhysicsColliderCircle::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderCircle",(ax::PhysicsColliderCircle*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - double arg0; - ax::PhysicsMaterial arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeCircle:create"); + ax::PhysicsBody* arg0; + double arg1; + ax::PhysicsMaterial arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderCircle:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderCircle_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeCircle::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsShapeCircle",(ax::PhysicsShapeCircle*)ret); + auto&& ret = ax::PhysicsColliderCircle::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderCircle",(ax::PhysicsColliderCircle*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - double arg0; - ax::PhysicsMaterial arg1; - ax::Vec2 arg2; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeCircle:create"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsShapeCircle:create"); + ax::PhysicsBody* arg0; + double arg1; + ax::PhysicsMaterial arg2; + ax::Vec2 arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderCircle:create"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsColliderCircle:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderCircle_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeCircle::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.PhysicsShapeCircle",(ax::PhysicsShapeCircle*)ret); + auto&& ret = ax::PhysicsColliderCircle::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderCircle",(ax::PhysicsColliderCircle*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeCircle:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderCircle:create",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeCircle_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderCircle_create'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeCircle_calculateArea(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderCircle_calculateArea(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1675,7 +1677,7 @@ int lua_ax_physics_PhysicsShapeCircle_calculateArea(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeCircle",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderCircle",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; @@ -1683,106 +1685,100 @@ int lua_ax_physics_PhysicsShapeCircle_calculateArea(lua_State* tolua_S) if (argc == 1) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:calculateArea"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsColliderCircle:calculateArea"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_calculateArea'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderCircle_calculateArea'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeCircle::calculateArea(arg0); + auto&& ret = ax::PhysicsColliderCircle::calculateArea(arg0); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeCircle:calculateArea",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderCircle:calculateArea",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeCircle_calculateArea'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderCircle_calculateArea'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeCircle_calculateMoment(lua_State* tolua_S) +static int lua_ax_physics_PhysicsColliderCircle_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderCircle)"); + return 0; +} + +int lua_register_ax_physics_PhysicsColliderCircle(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.PhysicsColliderCircle"); + tolua_cclass(tolua_S,"PhysicsColliderCircle","ax.PhysicsColliderCircle","ax.PhysicsCollider",nullptr); + + tolua_beginmodule(tolua_S,"PhysicsColliderCircle"); + tolua_function(tolua_S,"getRadius",lua_ax_physics_PhysicsColliderCircle_getRadius); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderCircle_create); + tolua_function(tolua_S,"calculateArea", lua_ax_physics_PhysicsColliderCircle_calculateArea); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::PhysicsColliderCircle).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderCircle"; + g_typeCast[typeName] = "ax.PhysicsColliderCircle"; + return 1; +} + +int lua_ax_physics_PhysicsColliderPolygon_getPoint(lua_State* tolua_S) { int argc = 0; + ax::PhysicsColliderPolygon* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeCircle",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderPolygon",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S) - 1; + cobj = (ax::PhysicsColliderPolygon*)tolua_tousertype(tolua_S,1,0); - if (argc == 2) +#if _AX_DEBUG >= 1 + if (!cobj) { - double arg0; - double arg1; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:calculateMoment"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsShapeCircle:calculateMoment"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_calculateMoment'", nullptr); - return 0; - } - auto&& ret = ax::PhysicsShapeCircle::calculateMoment(arg0, arg1); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderPolygon_getPoint'", nullptr); + return 0; } - if (argc == 3) +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) { - double arg0; - double arg1; - ax::Vec2 arg2; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsShapeCircle:calculateMoment"); - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsShapeCircle:calculateMoment"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsShapeCircle:calculateMoment"); + int arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsColliderPolygon:getPoint"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeCircle_calculateMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_getPoint'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeCircle::calculateMoment(arg0, arg1, arg2); - tolua_pushnumber(tolua_S,(lua_Number)ret); + auto&& ret = cobj->getPoint(arg0); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeCircle:calculateMoment",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderPolygon:getPoint",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeCircle_calculateMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderPolygon_getPoint'.",&tolua_err); #endif - return 0; -} -static int lua_ax_physics_PhysicsShapeCircle_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeCircle)"); - return 0; -} -int lua_register_ax_physics_PhysicsShapeCircle(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.PhysicsShapeCircle"); - tolua_cclass(tolua_S,"PhysicsShapeCircle","ax.PhysicsShapeCircle","ax.PhysicsShape",nullptr); - - tolua_beginmodule(tolua_S,"PhysicsShapeCircle"); - tolua_function(tolua_S,"getRadius",lua_ax_physics_PhysicsShapeCircle_getRadius); - tolua_function(tolua_S,"create", lua_ax_physics_PhysicsShapeCircle_create); - tolua_function(tolua_S,"calculateArea", lua_ax_physics_PhysicsShapeCircle_calculateArea); - tolua_function(tolua_S,"calculateMoment", lua_ax_physics_PhysicsShapeCircle_calculateMoment); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeCircle).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeCircle"; - g_typeCast[typeName] = "ax.PhysicsShapeCircle"; - return 1; + return 0; } - -int lua_ax_physics_PhysicsShapePolygon_getPoint(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderPolygon_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapePolygon* cobj = nullptr; + ax::PhysicsColliderPolygon* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1791,15 +1787,15 @@ int lua_ax_physics_PhysicsShapePolygon_getPoint(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapePolygon",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderPolygon",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapePolygon*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderPolygon*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapePolygon_getPoint'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderPolygon_getPoints'", nullptr); return 0; } #endif @@ -1807,32 +1803,32 @@ int lua_ax_physics_PhysicsShapePolygon_getPoint(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - int arg0; + ax::Vec2* arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsShapePolygon:getPoint"); + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsColliderPolygon:getPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapePolygon_getPoint'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_getPoints'", nullptr); return 0; } - auto&& ret = cobj->getPoint(arg0); - vec2_to_luaval(tolua_S, ret); + cobj->getPoints(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapePolygon:getPoint",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderPolygon:getPoints",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapePolygon_getPoint'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderPolygon_getPoints'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapePolygon_getPointsCount(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderPolygon_getPointsCount(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapePolygon* cobj = nullptr; + ax::PhysicsColliderPolygon* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1841,15 +1837,15 @@ int lua_ax_physics_PhysicsShapePolygon_getPointsCount(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapePolygon",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderPolygon",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapePolygon*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderPolygon*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapePolygon_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderPolygon_getPointsCount'", nullptr); return 0; } #endif @@ -1859,48 +1855,192 @@ int lua_ax_physics_PhysicsShapePolygon_getPointsCount(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapePolygon_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_getPointsCount'", nullptr); return 0; } auto&& ret = cobj->getPointsCount(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapePolygon:getPointsCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderPolygon:getPointsCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapePolygon_getPointsCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderPolygon_getPointsCount'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_physics_PhysicsColliderPolygon_create(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderPolygon",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 3) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderPolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon",(ax::PhysicsColliderPolygon*)ret); + return 1; + } + if (argc == 4) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderPolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon",(ax::PhysicsColliderPolygon*)ret); + return 1; + } + if (argc == 5) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + ax::Vec2 arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.PhysicsColliderPolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon",(ax::PhysicsColliderPolygon*)ret); + return 1; + } + if (argc == 6) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + ax::Vec2 arg4; + double arg5; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.PhysicsColliderPolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2, arg3, arg4, arg5); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon",(ax::PhysicsColliderPolygon*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderPolygon:create",argc, 3); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderPolygon_create'.",&tolua_err); #endif + return 0; +} +int lua_ax_physics_PhysicsColliderPolygon_calculateArea(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderPolygon",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 2) + { + const ax::Vec2* arg0; + int arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsColliderPolygon:calculateArea"); + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "ax.PhysicsColliderPolygon:calculateArea"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderPolygon_calculateArea'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderPolygon::calculateArea(arg0, arg1); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderPolygon:calculateArea",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderPolygon_calculateArea'.",&tolua_err); +#endif return 0; } -static int lua_ax_physics_PhysicsShapePolygon_finalize(lua_State* tolua_S) +static int lua_ax_physics_PhysicsColliderPolygon_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShapePolygon)"); + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderPolygon)"); return 0; } -int lua_register_ax_physics_PhysicsShapePolygon(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsColliderPolygon(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShapePolygon"); - tolua_cclass(tolua_S,"PhysicsShapePolygon","ax.PhysicsShapePolygon","ax.PhysicsShape",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsColliderPolygon"); + tolua_cclass(tolua_S,"PhysicsColliderPolygon","ax.PhysicsColliderPolygon","ax.PhysicsCollider",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShapePolygon"); - tolua_function(tolua_S,"getPoint",lua_ax_physics_PhysicsShapePolygon_getPoint); - tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsShapePolygon_getPointsCount); + tolua_beginmodule(tolua_S,"PhysicsColliderPolygon"); + tolua_function(tolua_S,"getPoint",lua_ax_physics_PhysicsColliderPolygon_getPoint); + tolua_function(tolua_S,"getPoints",lua_ax_physics_PhysicsColliderPolygon_getPoints); + tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsColliderPolygon_getPointsCount); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderPolygon_create); + tolua_function(tolua_S,"calculateArea", lua_ax_physics_PhysicsColliderPolygon_calculateArea); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapePolygon).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapePolygon"; - g_typeCast[typeName] = "ax.PhysicsShapePolygon"; + auto typeName = typeid(ax::PhysicsColliderPolygon).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderPolygon"; + g_typeCast[typeName] = "ax.PhysicsColliderPolygon"; return 1; } -int lua_ax_physics_PhysicsShapeBox_getSize(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderBox_getSize(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeBox* cobj = nullptr; + ax::PhysicsColliderBox* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -1909,15 +2049,15 @@ int lua_ax_physics_PhysicsShapeBox_getSize(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeBox",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderBox",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeBox*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderBox*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeBox_getSize'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderBox_getSize'", nullptr); return 0; } #endif @@ -1927,24 +2067,24 @@ int lua_ax_physics_PhysicsShapeBox_getSize(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeBox_getSize'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderBox_getSize'", nullptr); return 0; } auto&& ret = cobj->getSize(); vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeBox:getSize",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderBox:getSize",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeBox_getSize'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderBox_getSize'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeBox_create(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderBox_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1954,108 +2094,116 @@ int lua_ax_physics_PhysicsShapeBox_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeBox",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderBox",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeBox::create(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeBox",(ax::PhysicsShapeBox*)ret); + auto&& ret = ax::PhysicsColliderBox::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderBox",(ax::PhysicsColliderBox*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeBox::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsShapeBox",(ax::PhysicsShapeBox*)ret); + auto&& ret = ax::PhysicsColliderBox::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderBox",(ax::PhysicsColliderBox*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - ax::Vec2 arg2; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsShapeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + ax::Vec2 arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsColliderBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeBox::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.PhysicsShapeBox",(ax::PhysicsShapeBox*)ret); + auto&& ret = ax::PhysicsColliderBox::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderBox",(ax::PhysicsColliderBox*)ret); return 1; } - if (argc == 4) + if (argc == 5) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - ax::Vec2 arg2; - double arg3; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsShapeBox:create"); - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsShapeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + ax::Vec2 arg3; + double arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsColliderBox:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsColliderBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeBox::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.PhysicsShapeBox",(ax::PhysicsShapeBox*)ret); + auto&& ret = ax::PhysicsColliderBox::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderBox",(ax::PhysicsColliderBox*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeBox:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderBox:create",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeBox_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderBox_create'.",&tolua_err); #endif return 0; } -static int lua_ax_physics_PhysicsShapeBox_finalize(lua_State* tolua_S) +static int lua_ax_physics_PhysicsColliderBox_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeBox)"); + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderBox)"); return 0; } -int lua_register_ax_physics_PhysicsShapeBox(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsColliderBox(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShapeBox"); - tolua_cclass(tolua_S,"PhysicsShapeBox","ax.PhysicsShapeBox","ax.PhysicsShapePolygon",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsColliderBox"); + tolua_cclass(tolua_S,"PhysicsColliderBox","ax.PhysicsColliderBox","ax.PhysicsColliderPolygon",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShapeBox"); - tolua_function(tolua_S,"getSize",lua_ax_physics_PhysicsShapeBox_getSize); - tolua_function(tolua_S,"create", lua_ax_physics_PhysicsShapeBox_create); + tolua_beginmodule(tolua_S,"PhysicsColliderBox"); + tolua_function(tolua_S,"getSize",lua_ax_physics_PhysicsColliderBox_getSize); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderBox_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeBox).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeBox"; - g_typeCast[typeName] = "ax.PhysicsShapeBox"; + auto typeName = typeid(ax::PhysicsColliderBox).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderBox"; + g_typeCast[typeName] = "ax.PhysicsColliderBox"; return 1; } -int lua_ax_physics_PhysicsShapeEdgeSegment_getPointA(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgeSegment_getPointA(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgeSegment* cobj = nullptr; + ax::PhysicsColliderEdgeSegment* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2064,15 +2212,15 @@ int lua_ax_physics_PhysicsShapeEdgeSegment_getPointA(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeEdgeSegment",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgeSegment",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeEdgeSegment*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderEdgeSegment*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointA'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointA'", nullptr); return 0; } #endif @@ -2082,27 +2230,27 @@ int lua_ax_physics_PhysicsShapeEdgeSegment_getPointA(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointA'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointA'", nullptr); return 0; } auto&& ret = cobj->getPointA(); vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeEdgeSegment:getPointA",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgeSegment:getPointA",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointA'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointA'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeEdgeSegment_getPointB(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgeSegment_getPointB(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgeSegment* cobj = nullptr; + ax::PhysicsColliderEdgeSegment* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2111,15 +2259,15 @@ int lua_ax_physics_PhysicsShapeEdgeSegment_getPointB(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeEdgeSegment",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgeSegment",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeEdgeSegment*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderEdgeSegment*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointB'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointB'", nullptr); return 0; } #endif @@ -2129,24 +2277,24 @@ int lua_ax_physics_PhysicsShapeEdgeSegment_getPointB(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointB'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointB'", nullptr); return 0; } auto&& ret = cobj->getPointB(); vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeEdgeSegment:getPointB",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgeSegment:getPointB",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgeSegment_getPointB'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeSegment_getPointB'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsShapeEdgeSegment_create(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgeSegment_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -2156,96 +2304,152 @@ int lua_ax_physics_PhysicsShapeEdgeSegment_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeEdgeSegment",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderEdgeSegment",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 2) + if (argc == 3) { - ax::Vec2 arg0; + ax::PhysicsBody* arg0; ax::Vec2 arg1; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeSegment:create"); + ax::Vec2 arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeSegment:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeSegment_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeSegment_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeSegment::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeSegment",(ax::PhysicsShapeEdgeSegment*)ret); + auto&& ret = ax::PhysicsColliderEdgeSegment::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeSegment",(ax::PhysicsColliderEdgeSegment*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2 arg0; + ax::PhysicsBody* arg0; ax::Vec2 arg1; - ax::PhysicsMaterial arg2; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsShapeEdgeSegment:create"); + ax::Vec2 arg2; + ax::PhysicsMaterial arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgeSegment:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeSegment_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeSegment_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeSegment::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeSegment",(ax::PhysicsShapeEdgeSegment*)ret); + auto&& ret = ax::PhysicsColliderEdgeSegment::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeSegment",(ax::PhysicsColliderEdgeSegment*)ret); return 1; } - if (argc == 4) + if (argc == 5) { - ax::Vec2 arg0; + ax::PhysicsBody* arg0; ax::Vec2 arg1; - ax::PhysicsMaterial arg2; - double arg3; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsShapeEdgeSegment:create"); - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsShapeEdgeSegment:create"); + ax::Vec2 arg2; + ax::PhysicsMaterial arg3; + double arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgeSegment:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsColliderEdgeSegment:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeSegment_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeSegment_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeSegment::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeSegment",(ax::PhysicsShapeEdgeSegment*)ret); + auto&& ret = ax::PhysicsColliderEdgeSegment::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeSegment",(ax::PhysicsColliderEdgeSegment*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeEdgeSegment:create",argc, 2); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderEdgeSegment:create",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgeSegment_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeSegment_create'.",&tolua_err); #endif return 0; } -static int lua_ax_physics_PhysicsShapeEdgeSegment_finalize(lua_State* tolua_S) +static int lua_ax_physics_PhysicsColliderEdgeSegment_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeEdgeSegment)"); + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderEdgeSegment)"); return 0; } -int lua_register_ax_physics_PhysicsShapeEdgeSegment(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsColliderEdgeSegment(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShapeEdgeSegment"); - tolua_cclass(tolua_S,"PhysicsShapeEdgeSegment","ax.PhysicsShapeEdgeSegment","ax.PhysicsShape",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsColliderEdgeSegment"); + tolua_cclass(tolua_S,"PhysicsColliderEdgeSegment","ax.PhysicsColliderEdgeSegment","ax.PhysicsCollider",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShapeEdgeSegment"); - tolua_function(tolua_S,"getPointA",lua_ax_physics_PhysicsShapeEdgeSegment_getPointA); - tolua_function(tolua_S,"getPointB",lua_ax_physics_PhysicsShapeEdgeSegment_getPointB); - tolua_function(tolua_S,"create", lua_ax_physics_PhysicsShapeEdgeSegment_create); + tolua_beginmodule(tolua_S,"PhysicsColliderEdgeSegment"); + tolua_function(tolua_S,"getPointA",lua_ax_physics_PhysicsColliderEdgeSegment_getPointA); + tolua_function(tolua_S,"getPointB",lua_ax_physics_PhysicsColliderEdgeSegment_getPointB); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderEdgeSegment_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeEdgeSegment).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeEdgeSegment"; - g_typeCast[typeName] = "ax.PhysicsShapeEdgeSegment"; + auto typeName = typeid(ax::PhysicsColliderEdgeSegment).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderEdgeSegment"; + g_typeCast[typeName] = "ax.PhysicsColliderEdgeSegment"; return 1; } -int lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgePolygon_getPoints(lua_State* tolua_S) +{ + int argc = 0; + ax::PhysicsColliderEdgePolygon* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgePolygon",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::PhysicsColliderEdgePolygon*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPoints'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Vec2* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsColliderEdgePolygon:getPoints"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPoints'", nullptr); + return 0; + } + cobj->getPoints(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgePolygon:getPoints",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPoints'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_physics_PhysicsColliderEdgePolygon_getPointsCount(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgePolygon* cobj = nullptr; + ax::PhysicsColliderEdgePolygon* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2254,15 +2458,15 @@ int lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeEdgePolygon",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgePolygon",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeEdgePolygon*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderEdgePolygon*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPointsCount'", nullptr); return 0; } #endif @@ -2272,44 +2476,126 @@ int lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPointsCount'", nullptr); return 0; } auto&& ret = cobj->getPointsCount(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeEdgePolygon:getPointsCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgePolygon:getPointsCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgePolygon_getPointsCount'.",&tolua_err); #endif return 0; } -static int lua_ax_physics_PhysicsShapeEdgePolygon_finalize(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgePolygon_create(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeEdgePolygon)"); + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderEdgePolygon",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 3) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgePolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgePolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon",(ax::PhysicsColliderEdgePolygon*)ret); + return 1; + } + if (argc == 4) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgePolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgePolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon",(ax::PhysicsColliderEdgePolygon*)ret); + return 1; + } + if (argc == 5) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + double arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsColliderEdgePolygon:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgePolygon_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon",(ax::PhysicsColliderEdgePolygon*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderEdgePolygon:create",argc, 3); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgePolygon_create'.",&tolua_err); +#endif + return 0; +} +static int lua_ax_physics_PhysicsColliderEdgePolygon_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderEdgePolygon)"); return 0; } -int lua_register_ax_physics_PhysicsShapeEdgePolygon(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsColliderEdgePolygon(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShapeEdgePolygon"); - tolua_cclass(tolua_S,"PhysicsShapeEdgePolygon","ax.PhysicsShapeEdgePolygon","ax.PhysicsShape",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsColliderEdgePolygon"); + tolua_cclass(tolua_S,"PhysicsColliderEdgePolygon","ax.PhysicsColliderEdgePolygon","ax.PhysicsCollider",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShapeEdgePolygon"); - tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsShapeEdgePolygon_getPointsCount); + tolua_beginmodule(tolua_S,"PhysicsColliderEdgePolygon"); + tolua_function(tolua_S,"getPoints",lua_ax_physics_PhysicsColliderEdgePolygon_getPoints); + tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsColliderEdgePolygon_getPointsCount); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderEdgePolygon_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeEdgePolygon).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeEdgePolygon"; - g_typeCast[typeName] = "ax.PhysicsShapeEdgePolygon"; + auto typeName = typeid(ax::PhysicsColliderEdgePolygon).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderEdgePolygon"; + g_typeCast[typeName] = "ax.PhysicsColliderEdgePolygon"; return 1; } -int lua_ax_physics_PhysicsShapeEdgeBox_create(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgeBox_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -2319,107 +2605,165 @@ int lua_ax_physics_PhysicsShapeEdgeBox_create(lua_State* tolua_S) #endif #if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"ax.PhysicsShapeEdgeBox",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderEdgeBox",0,&tolua_err)) goto tolua_lerror; #endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - ax::Vec2 arg0; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeBox::create(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeBox",(ax::PhysicsShapeEdgeBox*)ret); + auto&& ret = ax::PhysicsColliderEdgeBox::create(arg0, arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeBox",(ax::PhysicsColliderEdgeBox*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeBox::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeBox",(ax::PhysicsShapeEdgeBox*)ret); + auto&& ret = ax::PhysicsColliderEdgeBox::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeBox",(ax::PhysicsColliderEdgeBox*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - double arg2; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsShapeEdgeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + double arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsColliderEdgeBox:create"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeBox_create'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeBox::create(arg0, arg1, arg2); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeBox",(ax::PhysicsShapeEdgeBox*)ret); + auto&& ret = ax::PhysicsColliderEdgeBox::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeBox",(ax::PhysicsColliderEdgeBox*)ret); return 1; } - if (argc == 4) + if (argc == 5) { - ax::Vec2 arg0; - ax::PhysicsMaterial arg1; - double arg2; - ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_physics_material(tolua_S, 3, &arg1, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsShapeEdgeBox:create"); - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsShapeEdgeBox:create"); + ax::PhysicsBody* arg0; + ax::Vec2 arg1; + ax::PhysicsMaterial arg2; + double arg3; + ax::Vec2 arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_vec2(tolua_S, 3, &arg1, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg2, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsColliderEdgeBox:create"); + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.PhysicsColliderEdgeBox:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeBox_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgeBox::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeBox",(ax::PhysicsColliderEdgeBox*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderEdgeBox:create",argc, 2); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeBox_create'.",&tolua_err); +#endif + return 0; +} +static int lua_ax_physics_PhysicsColliderEdgeBox_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderEdgeBox)"); + return 0; +} + +int lua_register_ax_physics_PhysicsColliderEdgeBox(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"ax.PhysicsColliderEdgeBox"); + tolua_cclass(tolua_S,"PhysicsColliderEdgeBox","ax.PhysicsColliderEdgeBox","ax.PhysicsColliderEdgePolygon",nullptr); + + tolua_beginmodule(tolua_S,"PhysicsColliderEdgeBox"); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderEdgeBox_create); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::PhysicsColliderEdgeBox).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderEdgeBox"; + g_typeCast[typeName] = "ax.PhysicsColliderEdgeBox"; + return 1; +} + +int lua_ax_physics_PhysicsColliderEdgeChain_getPoints(lua_State* tolua_S) +{ + int argc = 0; + ax::PhysicsColliderEdgeChain* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgeChain",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::PhysicsColliderEdgeChain*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPoints'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Vec2* arg0; + + ok &= luaval_to_object(tolua_S, 2, "ax.Vec2",&arg0, "ax.PhysicsColliderEdgeChain:getPoints"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeBox_create'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPoints'", nullptr); return 0; } - auto&& ret = ax::PhysicsShapeEdgeBox::create(arg0, arg1, arg2, arg3); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeBox",(ax::PhysicsShapeEdgeBox*)ret); + cobj->getPoints(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsShapeEdgeBox:create",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgeChain:getPoints",argc, 1); return 0; + #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgeBox_create'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPoints'.",&tolua_err); #endif - return 0; -} -static int lua_ax_physics_PhysicsShapeEdgeBox_finalize(lua_State* tolua_S) -{ - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeEdgeBox)"); - return 0; -} -int lua_register_ax_physics_PhysicsShapeEdgeBox(lua_State* tolua_S) -{ - tolua_usertype(tolua_S,"ax.PhysicsShapeEdgeBox"); - tolua_cclass(tolua_S,"PhysicsShapeEdgeBox","ax.PhysicsShapeEdgeBox","ax.PhysicsShapeEdgePolygon",nullptr); - - tolua_beginmodule(tolua_S,"PhysicsShapeEdgeBox"); - tolua_function(tolua_S,"create", lua_ax_physics_PhysicsShapeEdgeBox_create); - tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeEdgeBox).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeEdgeBox"; - g_typeCast[typeName] = "ax.PhysicsShapeEdgeBox"; - return 1; + return 0; } - -int lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount(lua_State* tolua_S) +int lua_ax_physics_PhysicsColliderEdgeChain_getPointsCount(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgeChain* cobj = nullptr; + ax::PhysicsColliderEdgeChain* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 @@ -2428,15 +2772,15 @@ int lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount(lua_State* tolua_S) #if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsShapeEdgeChain",0,&tolua_err)) goto tolua_lerror; + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsColliderEdgeChain",0,&tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PhysicsShapeEdgeChain*)tolua_tousertype(tolua_S,1,0); + cobj = (ax::PhysicsColliderEdgeChain*)tolua_tousertype(tolua_S,1,0); #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPointsCount'", nullptr); return 0; } #endif @@ -2446,44 +2790,126 @@ int lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPointsCount'", nullptr); return 0; } auto&& ret = cobj->getPointsCount(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsShapeEdgeChain:getPointsCount",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsColliderEdgeChain:getPointsCount",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeChain_getPointsCount'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_physics_PhysicsColliderEdgeChain_create(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; #endif +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"ax.PhysicsColliderEdgeChain",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 3) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgeChain:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeChain_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain",(ax::PhysicsColliderEdgeChain*)ret); + return 1; + } + if (argc == 4) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgeChain:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeChain_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2, arg3); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain",(ax::PhysicsColliderEdgeChain*)ret); + return 1; + } + if (argc == 5) + { + ax::PhysicsBody* arg0; + const ax::Vec2* arg1; + int arg2; + ax::PhysicsMaterial arg3; + double arg4; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.Vec2",&arg1, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_physics_material(tolua_S, 5, &arg3, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsColliderEdgeChain:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsColliderEdgeChain_create'", nullptr); + return 0; + } + auto&& ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain",(ax::PhysicsColliderEdgeChain*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsColliderEdgeChain:create",argc, 3); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsColliderEdgeChain_create'.",&tolua_err); +#endif return 0; } -static int lua_ax_physics_PhysicsShapeEdgeChain_finalize(lua_State* tolua_S) +static int lua_ax_physics_PhysicsColliderEdgeChain_finalize(lua_State* tolua_S) { - AXLOGV("luabindings: finalizing LUA object (PhysicsShapeEdgeChain)"); + AXLOGV("luabindings: finalizing LUA object (PhysicsColliderEdgeChain)"); return 0; } -int lua_register_ax_physics_PhysicsShapeEdgeChain(lua_State* tolua_S) +int lua_register_ax_physics_PhysicsColliderEdgeChain(lua_State* tolua_S) { - tolua_usertype(tolua_S,"ax.PhysicsShapeEdgeChain"); - tolua_cclass(tolua_S,"PhysicsShapeEdgeChain","ax.PhysicsShapeEdgeChain","ax.PhysicsShape",nullptr); + tolua_usertype(tolua_S,"ax.PhysicsColliderEdgeChain"); + tolua_cclass(tolua_S,"PhysicsColliderEdgeChain","ax.PhysicsColliderEdgeChain","ax.PhysicsCollider",nullptr); - tolua_beginmodule(tolua_S,"PhysicsShapeEdgeChain"); - tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsShapeEdgeChain_getPointsCount); + tolua_beginmodule(tolua_S,"PhysicsColliderEdgeChain"); + tolua_function(tolua_S,"getPoints",lua_ax_physics_PhysicsColliderEdgeChain_getPoints); + tolua_function(tolua_S,"getPointsCount",lua_ax_physics_PhysicsColliderEdgeChain_getPointsCount); + tolua_function(tolua_S,"create", lua_ax_physics_PhysicsColliderEdgeChain_create); tolua_endmodule(tolua_S); - auto typeName = typeid(ax::PhysicsShapeEdgeChain).name(); // rtti is literal storage - g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsShapeEdgeChain"; - g_typeCast[typeName] = "ax.PhysicsShapeEdgeChain"; + auto typeName = typeid(ax::PhysicsColliderEdgeChain).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsColliderEdgeChain"; + g_typeCast[typeName] = "ax.PhysicsColliderEdgeChain"; return 1; } -int lua_ax_physics_PhysicsBody_addShape(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_addCollider(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2503,7 +2929,7 @@ int lua_ax_physics_PhysicsBody_addShape(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_addShape'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_addCollider'", nullptr); return 0; } #endif @@ -2511,46 +2937,46 @@ int lua_ax_physics_PhysicsBody_addShape(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::PhysicsShape* arg0; + ax::PhysicsCollider* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.PhysicsBody:addShape"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.PhysicsBody:addCollider"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addShape'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addCollider'", nullptr); return 0; } - auto&& ret = cobj->addShape(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + auto&& ret = cobj->addCollider(arg0); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } if (argc == 2) { - ax::PhysicsShape* arg0; + ax::PhysicsCollider* arg0; bool arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.PhysicsBody:addShape"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.PhysicsBody:addCollider"); - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:addShape"); + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:addCollider"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addShape'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addCollider'", nullptr); return 0; } - auto&& ret = cobj->addShape(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + auto&& ret = cobj->addCollider(arg0, arg1); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:addShape",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:addCollider",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_addShape'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_addCollider'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_removeCollider(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2566,7 +2992,7 @@ int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_removeShape'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_removeCollider'", nullptr); return 0; } #endif @@ -2574,10 +3000,10 @@ int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) do{ if (argc == 1) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:removeShape"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } - cobj->removeShape(arg0); + cobj->removeCollider(arg0); lua_settop(tolua_S, 1); return 1; } @@ -2586,14 +3012,14 @@ int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) do{ if (argc == 2) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:removeShape"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:removeShape"); + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } - cobj->removeShape(arg0, arg1); + cobj->removeCollider(arg0, arg1); lua_settop(tolua_S, 1); return 1; } @@ -2601,11 +3027,11 @@ int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) ok = true; do{ if (argc == 1) { - ax::PhysicsShape* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.PhysicsBody:removeShape"); + ax::PhysicsCollider* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } - cobj->removeShape(arg0); + cobj->removeCollider(arg0); lua_settop(tolua_S, 1); return 1; } @@ -2613,31 +3039,31 @@ int lua_ax_physics_PhysicsBody_removeShape(lua_State* tolua_S) ok = true; do{ if (argc == 2) { - ax::PhysicsShape* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.PhysicsBody:removeShape"); + ax::PhysicsCollider* arg0; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } bool arg1; - ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:removeShape"); + ok &= luaval_to_boolean(tolua_S, 3,&arg1, "ax.PhysicsBody:removeCollider"); if (!ok) { break; } - cobj->removeShape(arg0, arg1); + cobj->removeCollider(arg0, arg1); lua_settop(tolua_S, 1); return 1; } }while(0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:removeShape",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:removeCollider",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_removeShape'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_removeCollider'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_removeAllShapes(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_removeAllColliders(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2657,7 +3083,7 @@ int lua_ax_physics_PhysicsBody_removeAllShapes(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_removeAllShapes'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_removeAllColliders'", nullptr); return 0; } #endif @@ -2667,10 +3093,10 @@ int lua_ax_physics_PhysicsBody_removeAllShapes(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_removeAllShapes'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_removeAllColliders'", nullptr); return 0; } - cobj->removeAllShapes(); + cobj->removeAllColliders(); lua_settop(tolua_S, 1); return 1; } @@ -2678,27 +3104,27 @@ int lua_ax_physics_PhysicsBody_removeAllShapes(lua_State* tolua_S) { bool arg0; - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsBody:removeAllShapes"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsBody:removeAllColliders"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_removeAllShapes'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_removeAllColliders'", nullptr); return 0; } - cobj->removeAllShapes(arg0); + cobj->removeAllColliders(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:removeAllShapes",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:removeAllColliders",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_removeAllShapes'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_removeAllColliders'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_getShapes(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getColliders(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2718,7 +3144,7 @@ int lua_ax_physics_PhysicsBody_getShapes(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getShapes'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getColliders'", nullptr); return 0; } #endif @@ -2728,24 +3154,24 @@ int lua_ax_physics_PhysicsBody_getShapes(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getShapes'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getColliders'", nullptr); return 0; } - auto&& ret = cobj->getShapes(); + auto&& ret = cobj->getColliders(); ccvector_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getShapes",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getColliders",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getShapes'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getColliders'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_getFirstShape(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getFirstCollider(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2765,7 +3191,7 @@ int lua_ax_physics_PhysicsBody_getFirstShape(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getFirstShape'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getFirstCollider'", nullptr); return 0; } #endif @@ -2775,24 +3201,24 @@ int lua_ax_physics_PhysicsBody_getFirstShape(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getFirstShape'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getFirstCollider'", nullptr); return 0; } - auto&& ret = cobj->getFirstShape(); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + auto&& ret = cobj->getFirstCollider(); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getFirstShape",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getFirstCollider",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getFirstShape'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getFirstCollider'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_getShape(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getCollider(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -2812,7 +3238,7 @@ int lua_ax_physics_PhysicsBody_getShape(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getShape'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getCollider'", nullptr); return 0; } #endif @@ -2822,22 +3248,22 @@ int lua_ax_physics_PhysicsBody_getShape(lua_State* tolua_S) { int arg0; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:getShape"); + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsBody:getCollider"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getShape'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getCollider'", nullptr); return 0; } - auto&& ret = cobj->getShape(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + auto&& ret = cobj->getCollider(arg0); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getShape",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getCollider",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getShape'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getCollider'.",&tolua_err); #endif return 0; @@ -4174,211 +4600,17 @@ int lua_ax_physics_PhysicsBody_getRotation(lua_State* tolua_S) tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getRotation",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getRotation'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsBody_setPositionOffset(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsBody* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsBody",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsBody*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setPositionOffset'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Vec2 arg0; - - ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsBody:setPositionOffset"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setPositionOffset'", nullptr); - return 0; - } - cobj->setPositionOffset(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setPositionOffset",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setPositionOffset'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsBody_getPositionOffset(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsBody* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsBody",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsBody*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getPositionOffset'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getPositionOffset'", nullptr); - return 0; - } - auto&& ret = cobj->getPositionOffset(); - vec2_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getPositionOffset",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getPositionOffset'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsBody_setRotationOffset(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsBody* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsBody",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsBody*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setRotationOffset'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:setRotationOffset"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setRotationOffset'", nullptr); - return 0; - } - cobj->setRotationOffset(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setRotationOffset",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setRotationOffset'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsBody_getRotationOffset(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsBody* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsBody",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsBody*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getRotationOffset'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getRotationOffset'", nullptr); - return 0; - } - auto&& ret = cobj->getRotationOffset(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getRotationOffset",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getRotation",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getRotationOffset'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getRotation'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_isDynamic(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_setPositionOffset(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4398,34 +4630,37 @@ int lua_ax_physics_PhysicsBody_isDynamic(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_isDynamic'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setPositionOffset'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + ax::Vec2 arg0; + + ok &= luaval_to_vec2(tolua_S, 2, &arg0, "ax.PhysicsBody:setPositionOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_isDynamic'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setPositionOffset'", nullptr); return 0; } - auto&& ret = cobj->isDynamic(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setPositionOffset(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:isDynamic",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setPositionOffset",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_isDynamic'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setPositionOffset'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_setDynamic(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getPositionOffset(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4445,37 +4680,34 @@ int lua_ax_physics_PhysicsBody_setDynamic(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setDynamic'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getPositionOffset'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - bool arg0; - - ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsBody:setDynamic"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setDynamic'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getPositionOffset'", nullptr); return 0; } - cobj->setDynamic(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getPositionOffset(); + vec2_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setDynamic",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getPositionOffset",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setDynamic'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getPositionOffset'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_setMass(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_setRotationOffset(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4495,7 +4727,7 @@ int lua_ax_physics_PhysicsBody_setMass(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setMass'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setRotationOffset'", nullptr); return 0; } #endif @@ -4505,27 +4737,27 @@ int lua_ax_physics_PhysicsBody_setMass(lua_State* tolua_S) { double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:setMass"); + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:setRotationOffset"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setMass'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setRotationOffset'", nullptr); return 0; } - cobj->setMass(arg0); + cobj->setRotationOffset(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setMass",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setRotationOffset",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setMass'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setRotationOffset'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_getMass(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getRotationOffset(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4545,7 +4777,7 @@ int lua_ax_physics_PhysicsBody_getMass(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getMass'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getRotationOffset'", nullptr); return 0; } #endif @@ -4555,24 +4787,24 @@ int lua_ax_physics_PhysicsBody_getMass(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getMass'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getRotationOffset'", nullptr); return 0; } - auto&& ret = cobj->getMass(); + auto&& ret = cobj->getRotationOffset(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getMass",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getRotationOffset",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getMass'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getRotationOffset'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_addMass(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_isDynamic(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4592,37 +4824,34 @@ int lua_ax_physics_PhysicsBody_addMass(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_addMass'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_isDynamic'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:addMass"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addMass'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_isDynamic'", nullptr); return 0; } - cobj->addMass(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->isDynamic(); + tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:addMass",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:isDynamic",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_addMass'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_isDynamic'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_setMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_setDynamic(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4642,7 +4871,7 @@ int lua_ax_physics_PhysicsBody_setMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_setDynamic'", nullptr); return 0; } #endif @@ -4650,29 +4879,29 @@ int lua_ax_physics_PhysicsBody_setMoment(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - double arg0; + bool arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:setMoment"); + ok &= luaval_to_boolean(tolua_S, 2,&arg0, "ax.PhysicsBody:setDynamic"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_setDynamic'", nullptr); return 0; } - cobj->setMoment(arg0); + cobj->setDynamic(arg0); lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setMoment",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:setDynamic",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_setDynamic'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_getMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getMass(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4692,7 +4921,7 @@ int lua_ax_physics_PhysicsBody_getMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getMass'", nullptr); return 0; } #endif @@ -4702,24 +4931,24 @@ int lua_ax_physics_PhysicsBody_getMoment(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getMass'", nullptr); return 0; } - auto&& ret = cobj->getMoment(); + auto&& ret = cobj->getMass(); tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getMoment",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getMass",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getMass'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsBody_addMoment(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getMoment(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -4739,32 +4968,29 @@ int lua_ax_physics_PhysicsBody_addMoment(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_addMoment'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getMoment'", nullptr); return 0; } #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) + if (argc == 0) { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:addMoment"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_addMoment'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getMoment'", nullptr); return 0; } - cobj->addMoment(arg0); - lua_settop(tolua_S, 1); + auto&& ret = cobj->getMoment(); + tolua_pushnumber(tolua_S,(lua_Number)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:addMoment",argc, 1); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getMoment",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_addMoment'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getMoment'.",&tolua_err); #endif return 0; @@ -5451,7 +5677,7 @@ int lua_ax_physics_PhysicsBody_local2World(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsBody_getCPBody(lua_State* tolua_S) +int lua_ax_physics_PhysicsBody_getB2Body(lua_State* tolua_S) { int argc = 0; ax::PhysicsBody* cobj = nullptr; @@ -5471,7 +5697,7 @@ int lua_ax_physics_PhysicsBody_getCPBody(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getCPBody'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsBody_getB2Body'", nullptr); return 0; } #endif @@ -5481,19 +5707,19 @@ int lua_ax_physics_PhysicsBody_getCPBody(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getCPBody'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_getB2Body'", nullptr); return 0; } - auto&& ret = cobj->getCPBody(); - #pragma warning NO CONVERSION FROM NATIVE FOR cpBody*; + auto&& ret = cobj->getB2Body(); + #pragma warning NO CONVERSION FROM NATIVE FOR b2BodyId; return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getCPBody",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsBody:getB2Body",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getCPBody'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsBody_getB2Body'.",&tolua_err); #endif return 0; @@ -5552,6 +5778,7 @@ int lua_ax_physics_PhysicsBody_create(lua_State* tolua_S) { int argc = 0; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif @@ -5560,48 +5787,20 @@ int lua_ax_physics_PhysicsBody_create(lua_State* tolua_S) if (!tolua_isusertable(tolua_S,1,"ax.PhysicsBody",0,&tolua_err)) goto tolua_lerror; #endif - argc = lua_gettop(tolua_S)-1; + argc = lua_gettop(tolua_S) - 1; - do - { - if (argc == 1) - { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:create"); - if (!ok) { break; } - ax::PhysicsBody* ret = ax::PhysicsBody::create(arg0); - object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); - return 1; - } - } while (0); - ok = true; - do - { - if (argc == 0) - { - ax::PhysicsBody* ret = ax::PhysicsBody::create(); - object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); - return 1; - } - } while (0); - ok = true; - do + if (argc == 0) { - if (argc == 2) + if(!ok) { - double arg0; - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsBody:create"); - if (!ok) { break; } - double arg1; - ok &= luaval_to_number(tolua_S, 3,&arg1, "ax.PhysicsBody:create"); - if (!ok) { break; } - ax::PhysicsBody* ret = ax::PhysicsBody::create(arg0, arg1); - object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); - return 1; + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsBody_create'", nullptr); + return 0; } - } while (0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsBody:create",argc, 2); + auto&& ret = ax::PhysicsBody::create(); + object_to_luaval(tolua_S, "ax.PhysicsBody",(ax::PhysicsBody*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsBody:create",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: @@ -5918,12 +6117,12 @@ int lua_register_ax_physics_PhysicsBody(lua_State* tolua_S) tolua_cclass(tolua_S,"PhysicsBody","ax.PhysicsBody","ax.Component",nullptr); tolua_beginmodule(tolua_S,"PhysicsBody"); - tolua_function(tolua_S,"addShape",lua_ax_physics_PhysicsBody_addShape); - tolua_function(tolua_S,"removeShape",lua_ax_physics_PhysicsBody_removeShape); - tolua_function(tolua_S,"removeAllShapes",lua_ax_physics_PhysicsBody_removeAllShapes); - tolua_function(tolua_S,"getShapes",lua_ax_physics_PhysicsBody_getShapes); - tolua_function(tolua_S,"getFirstShape",lua_ax_physics_PhysicsBody_getFirstShape); - tolua_function(tolua_S,"getShape",lua_ax_physics_PhysicsBody_getShape); + tolua_function(tolua_S,"addCollider",lua_ax_physics_PhysicsBody_addCollider); + tolua_function(tolua_S,"removeCollider",lua_ax_physics_PhysicsBody_removeCollider); + tolua_function(tolua_S,"removeAllColliders",lua_ax_physics_PhysicsBody_removeAllColliders); + tolua_function(tolua_S,"getColliders",lua_ax_physics_PhysicsBody_getColliders); + tolua_function(tolua_S,"getFirstCollider",lua_ax_physics_PhysicsBody_getFirstCollider); + tolua_function(tolua_S,"getCollider",lua_ax_physics_PhysicsBody_getCollider); tolua_function(tolua_S,"applyForce",lua_ax_physics_PhysicsBody_applyForce); tolua_function(tolua_S,"resetForces",lua_ax_physics_PhysicsBody_resetForces); tolua_function(tolua_S,"applyImpulse",lua_ax_physics_PhysicsBody_applyImpulse); @@ -5957,12 +6156,8 @@ int lua_register_ax_physics_PhysicsBody(lua_State* tolua_S) tolua_function(tolua_S,"getRotationOffset",lua_ax_physics_PhysicsBody_getRotationOffset); tolua_function(tolua_S,"isDynamic",lua_ax_physics_PhysicsBody_isDynamic); tolua_function(tolua_S,"setDynamic",lua_ax_physics_PhysicsBody_setDynamic); - tolua_function(tolua_S,"setMass",lua_ax_physics_PhysicsBody_setMass); tolua_function(tolua_S,"getMass",lua_ax_physics_PhysicsBody_getMass); - tolua_function(tolua_S,"addMass",lua_ax_physics_PhysicsBody_addMass); - tolua_function(tolua_S,"setMoment",lua_ax_physics_PhysicsBody_setMoment); tolua_function(tolua_S,"getMoment",lua_ax_physics_PhysicsBody_getMoment); - tolua_function(tolua_S,"addMoment",lua_ax_physics_PhysicsBody_addMoment); tolua_function(tolua_S,"getLinearDamping",lua_ax_physics_PhysicsBody_getLinearDamping); tolua_function(tolua_S,"setLinearDamping",lua_ax_physics_PhysicsBody_setLinearDamping); tolua_function(tolua_S,"getAngularDamping",lua_ax_physics_PhysicsBody_getAngularDamping); @@ -5977,7 +6172,7 @@ int lua_register_ax_physics_PhysicsBody(lua_State* tolua_S) tolua_function(tolua_S,"setTag",lua_ax_physics_PhysicsBody_setTag); tolua_function(tolua_S,"world2Local",lua_ax_physics_PhysicsBody_world2Local); tolua_function(tolua_S,"local2World",lua_ax_physics_PhysicsBody_local2World); - tolua_function(tolua_S,"getCPBody",lua_ax_physics_PhysicsBody_getCPBody); + tolua_function(tolua_S,"getB2Body",lua_ax_physics_PhysicsBody_getB2Body); tolua_function(tolua_S,"setFixedUpdate",lua_ax_physics_PhysicsBody_setFixedUpdate); tolua_function(tolua_S,"create", lua_ax_physics_PhysicsBody_create); tolua_function(tolua_S,"createCircle", lua_ax_physics_PhysicsBody_createCircle); @@ -6025,7 +6220,7 @@ int lua_ax_physics_PhysicsContact_getShapeA(lua_State* tolua_S) return 0; } auto&& ret = cobj->getShapeA(); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsContact:getShapeA",argc, 0); @@ -6072,7 +6267,7 @@ int lua_ax_physics_PhysicsContact_getShapeB(lua_State* tolua_S) return 0; } auto&& ret = cobj->getShapeB(); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsContact:getShapeB",argc, 0); @@ -6859,12 +7054,12 @@ int lua_ax_physics_EventListenerPhysicsContactWithBodies_hitTest(lua_State* tolu argc = lua_gettop(tolua_S)-1; if (argc == 2) { - ax::PhysicsShape* arg0; - ax::PhysicsShape* arg1; + ax::PhysicsCollider* arg0; + ax::PhysicsCollider* arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.EventListenerPhysicsContactWithBodies:hitTest"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.EventListenerPhysicsContactWithBodies:hitTest"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsShape",&arg1, "ax.EventListenerPhysicsContactWithBodies:hitTest"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsCollider",&arg1, "ax.EventListenerPhysicsContactWithBodies:hitTest"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_EventListenerPhysicsContactWithBodies_hitTest'", nullptr); @@ -6971,12 +7166,12 @@ int lua_ax_physics_EventListenerPhysicsContactWithShapes_hitTest(lua_State* tolu argc = lua_gettop(tolua_S)-1; if (argc == 2) { - ax::PhysicsShape* arg0; - ax::PhysicsShape* arg1; + ax::PhysicsCollider* arg0; + ax::PhysicsCollider* arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.EventListenerPhysicsContactWithShapes:hitTest"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.EventListenerPhysicsContactWithShapes:hitTest"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsShape",&arg1, "ax.EventListenerPhysicsContactWithShapes:hitTest"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsCollider",&arg1, "ax.EventListenerPhysicsContactWithShapes:hitTest"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_EventListenerPhysicsContactWithShapes_hitTest'", nullptr); @@ -7013,10 +7208,10 @@ int lua_ax_physics_EventListenerPhysicsContactWithShapes_create(lua_State* tolua if (argc == 2) { - ax::PhysicsShape* arg0; - ax::PhysicsShape* arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.EventListenerPhysicsContactWithShapes:create"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsShape",&arg1, "ax.EventListenerPhysicsContactWithShapes:create"); + ax::PhysicsCollider* arg0; + ax::PhysicsCollider* arg1; + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.EventListenerPhysicsContactWithShapes:create"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsCollider",&arg1, "ax.EventListenerPhysicsContactWithShapes:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_EventListenerPhysicsContactWithShapes_create'", nullptr); @@ -7083,12 +7278,12 @@ int lua_ax_physics_EventListenerPhysicsContactWithGroup_hitTest(lua_State* tolua argc = lua_gettop(tolua_S)-1; if (argc == 2) { - ax::PhysicsShape* arg0; - ax::PhysicsShape* arg1; + ax::PhysicsCollider* arg0; + ax::PhysicsCollider* arg1; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsShape",&arg0, "ax.EventListenerPhysicsContactWithGroup:hitTest"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsCollider",&arg0, "ax.EventListenerPhysicsContactWithGroup:hitTest"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsShape",&arg1, "ax.EventListenerPhysicsContactWithGroup:hitTest"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsCollider",&arg1, "ax.EventListenerPhysicsContactWithGroup:hitTest"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_EventListenerPhysicsContactWithGroup_hitTest'", nullptr); @@ -7772,54 +7967,7 @@ int lua_register_ax_physics_PhysicsJoint(lua_State* tolua_S) return 1; } -int lua_ax_physics_PhysicsJointFixed_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointFixed* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointFixed",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointFixed*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointFixed_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointFixed_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointFixed:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointFixed_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointFixed_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointFixed_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -7839,23 +7987,23 @@ int lua_ax_physics_PhysicsJointFixed_construct(lua_State* tolua_S) ax::PhysicsBody* arg0; ax::PhysicsBody* arg1; ax::Vec2 arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointFixed:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointFixed:construct"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointFixed:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointFixed:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointFixed:instantiate"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointFixed:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointFixed_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointFixed_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointFixed::construct(arg0, arg1, arg2); + auto&& ret = ax::PhysicsJointFixed::instantiate(arg0, arg1, arg2); object_to_luaval(tolua_S, "ax.PhysicsJointFixed",(ax::PhysicsJointFixed*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointFixed:construct",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointFixed:instantiate",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointFixed_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointFixed_instantiate'.",&tolua_err); #endif return 0; } @@ -7871,8 +8019,7 @@ int lua_register_ax_physics_PhysicsJointFixed(lua_State* tolua_S) tolua_cclass(tolua_S,"PhysicsJointFixed","ax.PhysicsJointFixed","ax.PhysicsJoint",nullptr); tolua_beginmodule(tolua_S,"PhysicsJointFixed"); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointFixed_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointFixed_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointFixed_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointFixed).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointFixed"; @@ -8268,54 +8415,7 @@ int lua_ax_physics_PhysicsJointLimit_setMax(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointLimit_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointLimit* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointLimit",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointLimit*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointLimit_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointLimit_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointLimit:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointLimit_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointLimit_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointLimit_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -8334,24 +8434,24 @@ int lua_ax_physics_PhysicsJointLimit_construct(lua_State* tolua_S) if (argc == 6) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::Vec2 arg2; - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } double arg4; - ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } double arg5; - ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } - ax::PhysicsJointLimit* ret = ax::PhysicsJointLimit::construct(arg0, arg1, arg2, arg3, arg4, arg5); + ax::PhysicsJointLimit* ret = ax::PhysicsJointLimit::instantiate(arg0, arg1, arg2, arg3, arg4, arg5); object_to_luaval(tolua_S, "ax.PhysicsJointLimit",(ax::PhysicsJointLimit*)ret); return 1; } @@ -8362,28 +8462,28 @@ int lua_ax_physics_PhysicsJointLimit_construct(lua_State* tolua_S) if (argc == 4) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::Vec2 arg2; - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointLimit:construct"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointLimit:instantiate"); if (!ok) { break; } - ax::PhysicsJointLimit* ret = ax::PhysicsJointLimit::construct(arg0, arg1, arg2, arg3); + ax::PhysicsJointLimit* ret = ax::PhysicsJointLimit::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointLimit",(ax::PhysicsJointLimit*)ret); return 1; } } while (0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointLimit:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointLimit:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointLimit_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointLimit_instantiate'.",&tolua_err); #endif return 0; } @@ -8407,63 +8507,15 @@ int lua_register_ax_physics_PhysicsJointLimit(lua_State* tolua_S) tolua_function(tolua_S,"setMin",lua_ax_physics_PhysicsJointLimit_setMin); tolua_function(tolua_S,"getMax",lua_ax_physics_PhysicsJointLimit_getMax); tolua_function(tolua_S,"setMax",lua_ax_physics_PhysicsJointLimit_setMax); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointLimit_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointLimit_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointLimit_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointLimit).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointLimit"; g_typeCast[typeName] = "ax.PhysicsJointLimit"; - return 1; -} - -int lua_ax_physics_PhysicsJointPin_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointPin* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointPin",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointPin*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointPin_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointPin_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointPin:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointPin_createConstraints'.",&tolua_err); -#endif - - return 0; + return 1; } -int lua_ax_physics_PhysicsJointPin_construct(lua_State* tolua_S) + +int lua_ax_physics_PhysicsJointPin_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -8482,18 +8534,18 @@ int lua_ax_physics_PhysicsJointPin_construct(lua_State* tolua_S) if (argc == 4) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } ax::Vec2 arg2; - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } ax::Vec2 arg3; - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } - ax::PhysicsJointPin* ret = ax::PhysicsJointPin::construct(arg0, arg1, arg2, arg3); + ax::PhysicsJointPin* ret = ax::PhysicsJointPin::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointPin",(ax::PhysicsJointPin*)ret); return 1; } @@ -8504,25 +8556,25 @@ int lua_ax_physics_PhysicsJointPin_construct(lua_State* tolua_S) if (argc == 3) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } ax::Vec2 arg2; - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointPin:construct"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointPin:instantiate"); if (!ok) { break; } - ax::PhysicsJointPin* ret = ax::PhysicsJointPin::construct(arg0, arg1, arg2); + ax::PhysicsJointPin* ret = ax::PhysicsJointPin::instantiate(arg0, arg1, arg2); object_to_luaval(tolua_S, "ax.PhysicsJointPin",(ax::PhysicsJointPin*)ret); return 1; } } while (0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointPin:construct",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointPin:instantiate",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointPin_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointPin_instantiate'.",&tolua_err); #endif return 0; } @@ -8538,8 +8590,7 @@ int lua_register_ax_physics_PhysicsJointPin(lua_State* tolua_S) tolua_cclass(tolua_S,"PhysicsJointPin","ax.PhysicsJointPin","ax.PhysicsJoint",nullptr); tolua_beginmodule(tolua_S,"PhysicsJointPin"); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointPin_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointPin_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointPin_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointPin).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointPin"; @@ -8644,54 +8695,7 @@ int lua_ax_physics_PhysicsJointDistance_setDistance(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointDistance_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointDistance* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointDistance",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointDistance*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointDistance_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointDistance_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointDistance:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointDistance_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointDistance_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointDistance_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -8712,24 +8716,24 @@ int lua_ax_physics_PhysicsJointDistance_construct(lua_State* tolua_S) ax::PhysicsBody* arg1; ax::Vec2 arg2; ax::Vec2 arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointDistance:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointDistance:construct"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointDistance:construct"); - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointDistance:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointDistance:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointDistance:instantiate"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointDistance:instantiate"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointDistance:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointDistance_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointDistance_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointDistance::construct(arg0, arg1, arg2, arg3); + auto&& ret = ax::PhysicsJointDistance::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointDistance",(ax::PhysicsJointDistance*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointDistance:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointDistance:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointDistance_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointDistance_instantiate'.",&tolua_err); #endif return 0; } @@ -8747,8 +8751,7 @@ int lua_register_ax_physics_PhysicsJointDistance(lua_State* tolua_S) tolua_beginmodule(tolua_S,"PhysicsJointDistance"); tolua_function(tolua_S,"getDistance",lua_ax_physics_PhysicsJointDistance_getDistance); tolua_function(tolua_S,"setDistance",lua_ax_physics_PhysicsJointDistance_setDistance); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointDistance_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointDistance_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointDistance_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointDistance).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointDistance"; @@ -9241,54 +9244,7 @@ int lua_ax_physics_PhysicsJointSpring_setDamping(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointSpring_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointSpring* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointSpring",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointSpring*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointSpring_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointSpring_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointSpring:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointSpring_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointSpring_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointSpring_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -9311,26 +9267,26 @@ int lua_ax_physics_PhysicsJointSpring_construct(lua_State* tolua_S) ax::Vec2 arg3; double arg4; double arg5; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointSpring:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointSpring:construct"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointSpring:construct"); - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointSpring:construct"); - ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsJointSpring:construct"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.PhysicsJointSpring:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointSpring:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointSpring:instantiate"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointSpring:instantiate"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointSpring:instantiate"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "ax.PhysicsJointSpring:instantiate"); + ok &= luaval_to_number(tolua_S, 7,&arg5, "ax.PhysicsJointSpring:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointSpring_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointSpring_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointSpring::construct(arg0, arg1, arg2, arg3, arg4, arg5); + auto&& ret = ax::PhysicsJointSpring::instantiate(arg0, arg1, arg2, arg3, arg4, arg5); object_to_luaval(tolua_S, "ax.PhysicsJointSpring",(ax::PhysicsJointSpring*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointSpring:construct",argc, 6); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointSpring:instantiate",argc, 6); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointSpring_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointSpring_instantiate'.",&tolua_err); #endif return 0; } @@ -9356,8 +9312,7 @@ int lua_register_ax_physics_PhysicsJointSpring(lua_State* tolua_S) tolua_function(tolua_S,"setStiffness",lua_ax_physics_PhysicsJointSpring_setStiffness); tolua_function(tolua_S,"getDamping",lua_ax_physics_PhysicsJointSpring_getDamping); tolua_function(tolua_S,"setDamping",lua_ax_physics_PhysicsJointSpring_setDamping); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointSpring_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointSpring_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointSpring_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointSpring).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointSpring"; @@ -9656,54 +9611,7 @@ int lua_ax_physics_PhysicsJointGroove_setAnchr2(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointGroove_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointGroove* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointGroove",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointGroove*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointGroove_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGroove_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointGroove:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGroove_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointGroove_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointGroove_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -9725,25 +9633,25 @@ int lua_ax_physics_PhysicsJointGroove_construct(lua_State* tolua_S) ax::Vec2 arg2; ax::Vec2 arg3; ax::Vec2 arg4; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointGroove:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointGroove:construct"); - ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointGroove:construct"); - ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointGroove:construct"); - ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.PhysicsJointGroove:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointGroove:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointGroove:instantiate"); + ok &= luaval_to_vec2(tolua_S, 4, &arg2, "ax.PhysicsJointGroove:instantiate"); + ok &= luaval_to_vec2(tolua_S, 5, &arg3, "ax.PhysicsJointGroove:instantiate"); + ok &= luaval_to_vec2(tolua_S, 6, &arg4, "ax.PhysicsJointGroove:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGroove_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGroove_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointGroove::construct(arg0, arg1, arg2, arg3, arg4); + auto&& ret = ax::PhysicsJointGroove::instantiate(arg0, arg1, arg2, arg3, arg4); object_to_luaval(tolua_S, "ax.PhysicsJointGroove",(ax::PhysicsJointGroove*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointGroove:construct",argc, 5); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointGroove:instantiate",argc, 5); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGroove_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGroove_instantiate'.",&tolua_err); #endif return 0; } @@ -9765,8 +9673,7 @@ int lua_register_ax_physics_PhysicsJointGroove(lua_State* tolua_S) tolua_function(tolua_S,"setGrooveB",lua_ax_physics_PhysicsJointGroove_setGrooveB); tolua_function(tolua_S,"getAnchr2",lua_ax_physics_PhysicsJointGroove_getAnchr2); tolua_function(tolua_S,"setAnchr2",lua_ax_physics_PhysicsJointGroove_setAnchr2); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointGroove_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointGroove_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointGroove_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointGroove).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointGroove"; @@ -10065,54 +9972,7 @@ int lua_ax_physics_PhysicsJointRotarySpring_setDamping(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointRotarySpring_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointRotarySpring* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointRotarySpring",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointRotarySpring*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointRotarySpring_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRotarySpring_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointRotarySpring:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotarySpring_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointRotarySpring_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointRotarySpring_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -10133,24 +9993,24 @@ int lua_ax_physics_PhysicsJointRotarySpring_construct(lua_State* tolua_S) ax::PhysicsBody* arg1; double arg2; double arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotarySpring:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotarySpring:construct"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRotarySpring:construct"); - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRotarySpring:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotarySpring:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotarySpring:instantiate"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRotarySpring:instantiate"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRotarySpring:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRotarySpring_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRotarySpring_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointRotarySpring::construct(arg0, arg1, arg2, arg3); + auto&& ret = ax::PhysicsJointRotarySpring::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointRotarySpring",(ax::PhysicsJointRotarySpring*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointRotarySpring:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointRotarySpring:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotarySpring_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotarySpring_instantiate'.",&tolua_err); #endif return 0; } @@ -10172,8 +10032,7 @@ int lua_register_ax_physics_PhysicsJointRotarySpring(lua_State* tolua_S) tolua_function(tolua_S,"setStiffness",lua_ax_physics_PhysicsJointRotarySpring_setStiffness); tolua_function(tolua_S,"getDamping",lua_ax_physics_PhysicsJointRotarySpring_getDamping); tolua_function(tolua_S,"setDamping",lua_ax_physics_PhysicsJointRotarySpring_setDamping); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointRotarySpring_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointRotarySpring_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointRotarySpring_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointRotarySpring).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointRotarySpring"; @@ -10375,54 +10234,7 @@ int lua_ax_physics_PhysicsJointRotaryLimit_setMax(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointRotaryLimit_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointRotaryLimit* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointRotaryLimit",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointRotaryLimit*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointRotaryLimit_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRotaryLimit_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointRotaryLimit:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotaryLimit_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointRotaryLimit_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointRotaryLimit_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -10441,12 +10253,12 @@ int lua_ax_physics_PhysicsJointRotaryLimit_construct(lua_State* tolua_S) if (argc == 2) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } - ax::PhysicsJointRotaryLimit* ret = ax::PhysicsJointRotaryLimit::construct(arg0, arg1); + ax::PhysicsJointRotaryLimit* ret = ax::PhysicsJointRotaryLimit::instantiate(arg0, arg1); object_to_luaval(tolua_S, "ax.PhysicsJointRotaryLimit",(ax::PhysicsJointRotaryLimit*)ret); return 1; } @@ -10457,28 +10269,28 @@ int lua_ax_physics_PhysicsJointRotaryLimit_construct(lua_State* tolua_S) if (argc == 4) { ax::PhysicsBody* arg0; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } ax::PhysicsBody* arg1; - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } double arg2; - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } double arg3; - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRotaryLimit:construct"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRotaryLimit:instantiate"); if (!ok) { break; } - ax::PhysicsJointRotaryLimit* ret = ax::PhysicsJointRotaryLimit::construct(arg0, arg1, arg2, arg3); + ax::PhysicsJointRotaryLimit* ret = ax::PhysicsJointRotaryLimit::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointRotaryLimit",(ax::PhysicsJointRotaryLimit*)ret); return 1; } } while (0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointRotaryLimit:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "ax.PhysicsJointRotaryLimit:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotaryLimit_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRotaryLimit_instantiate'.",&tolua_err); #endif return 0; } @@ -10498,8 +10310,7 @@ int lua_register_ax_physics_PhysicsJointRotaryLimit(lua_State* tolua_S) tolua_function(tolua_S,"setMin",lua_ax_physics_PhysicsJointRotaryLimit_setMin); tolua_function(tolua_S,"getMax",lua_ax_physics_PhysicsJointRotaryLimit_getMax); tolua_function(tolua_S,"setMax",lua_ax_physics_PhysicsJointRotaryLimit_setMax); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointRotaryLimit_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointRotaryLimit_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointRotaryLimit_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointRotaryLimit).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointRotaryLimit"; @@ -10774,78 +10585,31 @@ int lua_ax_physics_PhysicsJointRatchet_setRatchet(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - double arg0; - - ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsJointRatchet:setRatchet"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRatchet_setRatchet'", nullptr); - return 0; - } - cobj->setRatchet(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointRatchet:setRatchet",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRatchet_setRatchet'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointRatchet_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointRatchet* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointRatchet",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointRatchet*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointRatchet_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) + if (argc == 1) { + double arg0; + + ok &= luaval_to_number(tolua_S, 2,&arg0, "ax.PhysicsJointRatchet:setRatchet"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRatchet_createConstraints'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRatchet_setRatchet'", nullptr); return 0; } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); + cobj->setRatchet(arg0); + lua_settop(tolua_S, 1); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointRatchet:createConstraints",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointRatchet:setRatchet",argc, 1); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRatchet_createConstraints'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRatchet_setRatchet'.",&tolua_err); #endif return 0; } -int lua_ax_physics_PhysicsJointRatchet_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointRatchet_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -10866,24 +10630,24 @@ int lua_ax_physics_PhysicsJointRatchet_construct(lua_State* tolua_S) ax::PhysicsBody* arg1; double arg2; double arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRatchet:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRatchet:construct"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRatchet:construct"); - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRatchet:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointRatchet:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointRatchet:instantiate"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointRatchet:instantiate"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointRatchet:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRatchet_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointRatchet_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointRatchet::construct(arg0, arg1, arg2, arg3); + auto&& ret = ax::PhysicsJointRatchet::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointRatchet",(ax::PhysicsJointRatchet*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointRatchet:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointRatchet:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRatchet_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointRatchet_instantiate'.",&tolua_err); #endif return 0; } @@ -10905,8 +10669,7 @@ int lua_register_ax_physics_PhysicsJointRatchet(lua_State* tolua_S) tolua_function(tolua_S,"setPhase",lua_ax_physics_PhysicsJointRatchet_setPhase); tolua_function(tolua_S,"getRatchet",lua_ax_physics_PhysicsJointRatchet_getRatchet); tolua_function(tolua_S,"setRatchet",lua_ax_physics_PhysicsJointRatchet_setRatchet); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointRatchet_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointRatchet_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointRatchet_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointRatchet).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointRatchet"; @@ -11108,54 +10871,7 @@ int lua_ax_physics_PhysicsJointGear_setRatio(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointGear_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointGear* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointGear",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointGear*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointGear_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGear_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointGear:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGear_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointGear_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointGear_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -11176,24 +10892,24 @@ int lua_ax_physics_PhysicsJointGear_construct(lua_State* tolua_S) ax::PhysicsBody* arg1; double arg2; double arg3; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointGear:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointGear:construct"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointGear:construct"); - ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointGear:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointGear:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointGear:instantiate"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointGear:instantiate"); + ok &= luaval_to_number(tolua_S, 5,&arg3, "ax.PhysicsJointGear:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGear_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointGear_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointGear::construct(arg0, arg1, arg2, arg3); + auto&& ret = ax::PhysicsJointGear::instantiate(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "ax.PhysicsJointGear",(ax::PhysicsJointGear*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointGear:construct",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointGear:instantiate",argc, 4); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGear_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointGear_instantiate'.",&tolua_err); #endif return 0; } @@ -11213,8 +10929,7 @@ int lua_register_ax_physics_PhysicsJointGear(lua_State* tolua_S) tolua_function(tolua_S,"setPhase",lua_ax_physics_PhysicsJointGear_setPhase); tolua_function(tolua_S,"getRatio",lua_ax_physics_PhysicsJointGear_getRatio); tolua_function(tolua_S,"setRatio",lua_ax_physics_PhysicsJointGear_setRatio); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointGear_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointGear_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointGear_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointGear).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointGear"; @@ -11319,54 +11034,7 @@ int lua_ax_physics_PhysicsJointMotor_setRate(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsJointMotor_createConstraints(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsJointMotor* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsJointMotor",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsJointMotor*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsJointMotor_createConstraints'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointMotor_createConstraints'", nullptr); - return 0; - } - auto&& ret = cobj->createConstraints(); - tolua_pushboolean(tolua_S,(bool)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsJointMotor:createConstraints",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointMotor_createConstraints'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsJointMotor_construct(lua_State* tolua_S) +int lua_ax_physics_PhysicsJointMotor_instantiate(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -11386,23 +11054,23 @@ int lua_ax_physics_PhysicsJointMotor_construct(lua_State* tolua_S) ax::PhysicsBody* arg0; ax::PhysicsBody* arg1; double arg2; - ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointMotor:construct"); - ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointMotor:construct"); - ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointMotor:construct"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody",&arg0, "ax.PhysicsJointMotor:instantiate"); + ok &= luaval_to_object(tolua_S, 3, "ax.PhysicsBody",&arg1, "ax.PhysicsJointMotor:instantiate"); + ok &= luaval_to_number(tolua_S, 4,&arg2, "ax.PhysicsJointMotor:instantiate"); if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointMotor_construct'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsJointMotor_instantiate'", nullptr); return 0; } - auto&& ret = ax::PhysicsJointMotor::construct(arg0, arg1, arg2); + auto&& ret = ax::PhysicsJointMotor::instantiate(arg0, arg1, arg2); object_to_luaval(tolua_S, "ax.PhysicsJointMotor",(ax::PhysicsJointMotor*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointMotor:construct",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "ax.PhysicsJointMotor:instantiate",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointMotor_construct'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsJointMotor_instantiate'.",&tolua_err); #endif return 0; } @@ -11420,8 +11088,7 @@ int lua_register_ax_physics_PhysicsJointMotor(lua_State* tolua_S) tolua_beginmodule(tolua_S,"PhysicsJointMotor"); tolua_function(tolua_S,"getRate",lua_ax_physics_PhysicsJointMotor_getRate); tolua_function(tolua_S,"setRate",lua_ax_physics_PhysicsJointMotor_setRate); - tolua_function(tolua_S,"createConstraints",lua_ax_physics_PhysicsJointMotor_createConstraints); - tolua_function(tolua_S,"construct", lua_ax_physics_PhysicsJointMotor_construct); + tolua_function(tolua_S,"instantiate", lua_ax_physics_PhysicsJointMotor_instantiate); tolua_endmodule(tolua_S); auto typeName = typeid(ax::PhysicsJointMotor).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "ax.PhysicsJointMotor"; @@ -11429,6 +11096,53 @@ int lua_register_ax_physics_PhysicsJointMotor(lua_State* tolua_S) return 1; } +int lua_ax_physics_PhysicsWorld_getB2World(lua_State* tolua_S) +{ + int argc = 0; + ax::PhysicsWorld* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"ax.PhysicsWorld",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::PhysicsWorld*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsWorld_getB2World'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsWorld_getB2World'", nullptr); + return 0; + } + auto&& ret = cobj->getB2World(); + #pragma warning NO CONVERSION FROM NATIVE FOR b2WorldId; + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsWorld:getB2World",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsWorld_getB2World'.",&tolua_err); +#endif + + return 0; +} int lua_ax_physics_PhysicsWorld_addJoint(lua_State* tolua_S) { int argc = 0; @@ -11796,7 +11510,7 @@ int lua_ax_physics_PhysicsWorld_getShape(lua_State* tolua_S) return 0; } auto&& ret = cobj->getShape(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShape",(ax::PhysicsShape*)ret); + object_to_luaval(tolua_S, "ax.PhysicsCollider",(ax::PhysicsCollider*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsWorld:getShape",argc, 1); @@ -12444,56 +12158,6 @@ int lua_ax_physics_PhysicsWorld_getFixedUpdateRate(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsWorld_setDebugDrawMask(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsWorld* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsWorld",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsWorld*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsWorld_setDebugDrawMask'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - int arg0; - - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "ax.PhysicsWorld:setDebugDrawMask"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsWorld_setDebugDrawMask'", nullptr); - return 0; - } - cobj->setDebugDrawMask(arg0); - lua_settop(tolua_S, 1); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsWorld:setDebugDrawMask",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsWorld_setDebugDrawMask'.",&tolua_err); -#endif - - return 0; -} int lua_ax_physics_PhysicsWorld_setPreUpdateCallback(lua_State* tolua_S) { int argc = 0; @@ -12602,100 +12266,6 @@ int lua_ax_physics_PhysicsWorld_setPostUpdateCallback(lua_State* tolua_S) return 0; } -int lua_ax_physics_PhysicsWorld_getDebugDrawMask(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsWorld* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsWorld",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsWorld*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsWorld_getDebugDrawMask'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsWorld_getDebugDrawMask'", nullptr); - return 0; - } - auto&& ret = cobj->getDebugDrawMask(); - tolua_pushnumber(tolua_S,(lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsWorld:getDebugDrawMask",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsWorld_getDebugDrawMask'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_physics_PhysicsWorld_getDebugDraw(lua_State* tolua_S) -{ - int argc = 0; - ax::PhysicsWorld* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"ax.PhysicsWorld",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::PhysicsWorld*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_physics_PhysicsWorld_getDebugDraw'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 0) - { - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_physics_PhysicsWorld_getDebugDraw'", nullptr); - return 0; - } - auto&& ret = cobj->getDebugDraw(); - object_to_luaval(tolua_S, "ax.DrawNode",(ax::DrawNode*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ax.PhysicsWorld:getDebugDraw",argc, 0); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_physics_PhysicsWorld_getDebugDraw'.",&tolua_err); -#endif - - return 0; -} int lua_ax_physics_PhysicsWorld_setAutoStep(lua_State* tolua_S) { int argc = 0; @@ -12855,6 +12425,7 @@ int lua_register_ax_physics_PhysicsWorld(lua_State* tolua_S) tolua_cclass(tolua_S,"PhysicsWorld","ax.PhysicsWorld","",nullptr); tolua_beginmodule(tolua_S,"PhysicsWorld"); + tolua_function(tolua_S,"getB2World",lua_ax_physics_PhysicsWorld_getB2World); tolua_function(tolua_S,"addJoint",lua_ax_physics_PhysicsWorld_addJoint); tolua_function(tolua_S,"removeJoint",lua_ax_physics_PhysicsWorld_removeJoint); tolua_function(tolua_S,"removeAllJoints",lua_ax_physics_PhysicsWorld_removeAllJoints); @@ -12875,11 +12446,8 @@ int lua_register_ax_physics_PhysicsWorld(lua_State* tolua_S) tolua_function(tolua_S,"getSubsteps",lua_ax_physics_PhysicsWorld_getSubsteps); tolua_function(tolua_S,"setFixedUpdateRate",lua_ax_physics_PhysicsWorld_setFixedUpdateRate); tolua_function(tolua_S,"getFixedUpdateRate",lua_ax_physics_PhysicsWorld_getFixedUpdateRate); - tolua_function(tolua_S,"setDebugDrawMask",lua_ax_physics_PhysicsWorld_setDebugDrawMask); tolua_function(tolua_S,"setPreUpdateCallback",lua_ax_physics_PhysicsWorld_setPreUpdateCallback); tolua_function(tolua_S,"setPostUpdateCallback",lua_ax_physics_PhysicsWorld_setPostUpdateCallback); - tolua_function(tolua_S,"getDebugDrawMask",lua_ax_physics_PhysicsWorld_getDebugDrawMask); - tolua_function(tolua_S,"getDebugDraw",lua_ax_physics_PhysicsWorld_getDebugDraw); tolua_function(tolua_S,"setAutoStep",lua_ax_physics_PhysicsWorld_setAutoStep); tolua_function(tolua_S,"isAutoStep",lua_ax_physics_PhysicsWorld_isAutoStep); tolua_function(tolua_S,"step",lua_ax_physics_PhysicsWorld_step); @@ -12896,14 +12464,14 @@ TOLUA_API int register_all_ax_physics(lua_State* tolua_S) tolua_module(tolua_S,"ax",0); tolua_beginmodule(tolua_S,"ax"); - lua_register_ax_physics_PhysicsShape(tolua_S); - lua_register_ax_physics_PhysicsShapeCircle(tolua_S); - lua_register_ax_physics_PhysicsShapePolygon(tolua_S); - lua_register_ax_physics_PhysicsShapeBox(tolua_S); - lua_register_ax_physics_PhysicsShapeEdgeSegment(tolua_S); - lua_register_ax_physics_PhysicsShapeEdgePolygon(tolua_S); - lua_register_ax_physics_PhysicsShapeEdgeBox(tolua_S); - lua_register_ax_physics_PhysicsShapeEdgeChain(tolua_S); + lua_register_ax_physics_PhysicsCollider(tolua_S); + lua_register_ax_physics_PhysicsColliderCircle(tolua_S); + lua_register_ax_physics_PhysicsColliderPolygon(tolua_S); + lua_register_ax_physics_PhysicsColliderBox(tolua_S); + lua_register_ax_physics_PhysicsColliderEdgeSegment(tolua_S); + lua_register_ax_physics_PhysicsColliderEdgePolygon(tolua_S); + lua_register_ax_physics_PhysicsColliderEdgeBox(tolua_S); + lua_register_ax_physics_PhysicsColliderEdgeChain(tolua_S); lua_register_ax_physics_PhysicsBody(tolua_S); lua_register_ax_physics_PhysicsContact(tolua_S); lua_register_ax_physics_PhysicsContactPreSolve(tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_physics_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_physics_auto.hpp index ea59df5e02b9..6b268c9eb75a 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_physics_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_physics_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_PHYSICS) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_physics(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_PHYSICS) diff --git a/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.cpp new file mode 100644 index 000000000000..febce5a8274f --- /dev/null +++ b/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.cpp @@ -0,0 +1,3359 @@ +#include "lua-bindings/auto/axlua_rhi_auto.hpp" +#include "axmol/rhi/RHITypes.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/rhi/Texture.h" +#include "axmol/rhi/VertexLayout.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/rhi/RenderTarget.h" +#include "lua-bindings/manual/tolua_fix.h" +#include "lua-bindings/manual/LuaBasicConversions.h" + + +int lua_register_ax_rhi_BufferUsage(lua_State* tolua_S) +{ + tolua_module(tolua_S, "BufferUsage", 0); + tolua_beginmodule(tolua_S,"BufferUsage"); + tolua_constant(tolua_S, "STATIC", 0); + tolua_constant(tolua_S, "DYNAMIC", 1); + tolua_constant(tolua_S, "IMMUTABLE", 2); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::BufferUsage).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.BufferUsage"; + g_typeCast[typeName] = "axrhi.BufferUsage"; + return 1; +} + + +int lua_register_ax_rhi_BufferType(lua_State* tolua_S) +{ + tolua_module(tolua_S, "BufferType", 0); + tolua_beginmodule(tolua_S,"BufferType"); + tolua_constant(tolua_S, "ARRAY_BUFFER", 0); + tolua_constant(tolua_S, "ELEMENT_ARRAY_BUFFER", 1); + tolua_constant(tolua_S, "UNIFORM_BUFFER", 2); + tolua_constant(tolua_S, "PIXEL_PACK_BUFFER", 3); + tolua_constant(tolua_S, "COUNT", 4); + tolua_constant(tolua_S, "VERTEX", 0); + tolua_constant(tolua_S, "INDEX", 1); + tolua_constant(tolua_S, "UNIFORM", 2); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::BufferType).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.BufferType"; + g_typeCast[typeName] = "axrhi.BufferType"; + return 1; +} + + +int lua_register_ax_rhi_ShaderStage(lua_State* tolua_S) +{ + tolua_module(tolua_S, "ShaderStage", 0); + tolua_beginmodule(tolua_S,"ShaderStage"); + tolua_constant(tolua_S, "UNKNOWN", -1); + tolua_constant(tolua_S, "VERTEX", 0); + tolua_constant(tolua_S, "FRAGMENT", 1); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::ShaderStage).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.ShaderStage"; + g_typeCast[typeName] = "axrhi.ShaderStage"; + return 1; +} + + +int lua_register_ax_rhi_VertexFormat(lua_State* tolua_S) +{ + tolua_module(tolua_S, "VertexFormat", 0); + tolua_beginmodule(tolua_S,"VertexFormat"); + tolua_constant(tolua_S, "FLOAT4", 0); + tolua_constant(tolua_S, "FLOAT3", 1); + tolua_constant(tolua_S, "FLOAT2", 2); + tolua_constant(tolua_S, "FLOAT", 3); + tolua_constant(tolua_S, "INT4", 4); + tolua_constant(tolua_S, "INT3", 5); + tolua_constant(tolua_S, "INT2", 6); + tolua_constant(tolua_S, "INT", 7); + tolua_constant(tolua_S, "USHORT4", 8); + tolua_constant(tolua_S, "USHORT2", 9); + tolua_constant(tolua_S, "UBYTE4", 10); + tolua_constant(tolua_S, "MAT4", 11); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::VertexFormat).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.VertexFormat"; + g_typeCast[typeName] = "axrhi.VertexFormat"; + return 1; +} + + +int lua_register_ax_rhi_PixelFormat(lua_State* tolua_S) +{ + tolua_module(tolua_S, "PixelFormat", 0); + tolua_beginmodule(tolua_S,"PixelFormat"); + tolua_constant(tolua_S, "PVRTC4", 0); + tolua_constant(tolua_S, "PVRTC4A", 1); + tolua_constant(tolua_S, "PVRTC2", 2); + tolua_constant(tolua_S, "PVRTC2A", 3); + tolua_constant(tolua_S, "ETC1", 4); + tolua_constant(tolua_S, "ETC2_RGB", 5); + tolua_constant(tolua_S, "ETC2_RGBA", 6); + tolua_constant(tolua_S, "S3TC_DXT1", 7); + tolua_constant(tolua_S, "S3TC_DXT3", 8); + tolua_constant(tolua_S, "S3TC_DXT5", 9); + tolua_constant(tolua_S, "ATC_RGB", 10); + tolua_constant(tolua_S, "ATC_EXPLICIT_ALPHA", 11); + tolua_constant(tolua_S, "ATC_INTERPOLATED_ALPHA", 12); + tolua_constant(tolua_S, "ASTC4x4", 13); + tolua_constant(tolua_S, "ASTC5x5", 14); + tolua_constant(tolua_S, "ASTC6x6", 15); + tolua_constant(tolua_S, "ASTC8x5", 16); + tolua_constant(tolua_S, "ASTC8x6", 17); + tolua_constant(tolua_S, "ASTC8x8", 18); + tolua_constant(tolua_S, "ASTC10x5", 19); + tolua_constant(tolua_S, "RGBA8", 20); + tolua_constant(tolua_S, "BGRA8", 21); + tolua_constant(tolua_S, "RGB8", 22); + tolua_constant(tolua_S, "RGB565", 23); + tolua_constant(tolua_S, "RGBA4", 24); + tolua_constant(tolua_S, "RGB5A1", 25); + tolua_constant(tolua_S, "R8", 26); + tolua_constant(tolua_S, "RG8", 27); + tolua_constant(tolua_S, "RGBA32F", 28); + tolua_constant(tolua_S, "D24S8", 29); + tolua_constant(tolua_S, "COUNT", 30); + tolua_constant(tolua_S, "NONE", 65535); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::PixelFormat).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.PixelFormat"; + g_typeCast[typeName] = "axrhi.PixelFormat"; + return 1; +} + + +int lua_register_ax_rhi_TextureUsage(lua_State* tolua_S) +{ + tolua_module(tolua_S, "TextureUsage", 0); + tolua_beginmodule(tolua_S,"TextureUsage"); + tolua_constant(tolua_S, "READ", 0); + tolua_constant(tolua_S, "WRITE", 1); + tolua_constant(tolua_S, "RENDER_TARGET", 2); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::TextureUsage).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.TextureUsage"; + g_typeCast[typeName] = "axrhi.TextureUsage"; + return 1; +} + + +int lua_register_ax_rhi_IndexFormat(lua_State* tolua_S) +{ + tolua_module(tolua_S, "IndexFormat", 0); + tolua_beginmodule(tolua_S,"IndexFormat"); + tolua_constant(tolua_S, "U_SHORT", 1); + tolua_constant(tolua_S, "U_INT", 2); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::IndexFormat).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.IndexFormat"; + g_typeCast[typeName] = "axrhi.IndexFormat"; + return 1; +} + + +int lua_register_ax_rhi_VertexStepMode(lua_State* tolua_S) +{ + tolua_module(tolua_S, "VertexStepMode", 0); + tolua_beginmodule(tolua_S,"VertexStepMode"); + tolua_constant(tolua_S, "VERTEX", 0); + tolua_constant(tolua_S, "INSTANCE", 1); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::VertexStepMode).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.VertexStepMode"; + g_typeCast[typeName] = "axrhi.VertexStepMode"; + return 1; +} + + +int lua_register_ax_rhi_PrimitiveType(lua_State* tolua_S) +{ + tolua_module(tolua_S, "PrimitiveType", 0); + tolua_beginmodule(tolua_S,"PrimitiveType"); + tolua_constant(tolua_S, "POINT", 0); + tolua_constant(tolua_S, "LINE", 1); + tolua_constant(tolua_S, "LINE_LOOP", 2); + tolua_constant(tolua_S, "LINE_STRIP", 3); + tolua_constant(tolua_S, "TRIANGLE", 4); + tolua_constant(tolua_S, "TRIANGLE_STRIP", 5); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::PrimitiveType).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.PrimitiveType"; + g_typeCast[typeName] = "axrhi.PrimitiveType"; + return 1; +} + + +int lua_register_ax_rhi_BlendFactor(lua_State* tolua_S) +{ + tolua_module(tolua_S, "BlendFactor", 0); + tolua_beginmodule(tolua_S,"BlendFactor"); + tolua_constant(tolua_S, "ZERO", 0); + tolua_constant(tolua_S, "ONE", 1); + tolua_constant(tolua_S, "SRC_COLOR", 2); + tolua_constant(tolua_S, "ONE_MINUS_SRC_COLOR", 3); + tolua_constant(tolua_S, "SRC_ALPHA", 4); + tolua_constant(tolua_S, "ONE_MINUS_SRC_ALPHA", 5); + tolua_constant(tolua_S, "DST_COLOR", 6); + tolua_constant(tolua_S, "ONE_MINUS_DST_COLOR", 7); + tolua_constant(tolua_S, "DST_ALPHA", 8); + tolua_constant(tolua_S, "ONE_MINUS_DST_ALPHA", 9); + tolua_constant(tolua_S, "CONSTANT_ALPHA", 10); + tolua_constant(tolua_S, "SRC_ALPHA_SATURATE", 11); + tolua_constant(tolua_S, "ONE_MINUS_CONSTANT_ALPHA", 12); + tolua_constant(tolua_S, "BLEND_COLOR", 13); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::BlendFactor).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.BlendFactor"; + g_typeCast[typeName] = "axrhi.BlendFactor"; + return 1; +} + + +int lua_register_ax_rhi_ColorWriteMask(lua_State* tolua_S) +{ + tolua_module(tolua_S, "ColorWriteMask", 0); + tolua_beginmodule(tolua_S,"ColorWriteMask"); + tolua_constant(tolua_S, "RED_BIT", 0); + tolua_constant(tolua_S, "GREEN_BIT", 1); + tolua_constant(tolua_S, "BLUE_BIT", 2); + tolua_constant(tolua_S, "ALPHA_BIT", 3); + tolua_constant(tolua_S, "NONE", 0); + tolua_constant(tolua_S, "RED", 1); + tolua_constant(tolua_S, "GREEN", 2); + tolua_constant(tolua_S, "BLUE", 4); + tolua_constant(tolua_S, "ALPHA", 8); + tolua_constant(tolua_S, "ALL", 15); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::ColorWriteMask).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.ColorWriteMask"; + g_typeCast[typeName] = "axrhi.ColorWriteMask"; + return 1; +} + + +int lua_register_ax_rhi_CullMode(lua_State* tolua_S) +{ + tolua_module(tolua_S, "CullMode", 0); + tolua_beginmodule(tolua_S,"CullMode"); + tolua_constant(tolua_S, "NONE", 0); + tolua_constant(tolua_S, "BACK", 1); + tolua_constant(tolua_S, "FRONT", 2); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::CullMode).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.CullMode"; + g_typeCast[typeName] = "axrhi.CullMode"; + return 1; +} + + +int lua_register_ax_rhi_Winding(lua_State* tolua_S) +{ + tolua_module(tolua_S, "Winding", 0); + tolua_beginmodule(tolua_S,"Winding"); + tolua_constant(tolua_S, "CLOCK_WISE", 0); + tolua_constant(tolua_S, "COUNTER_CLOCK_WISE", 1); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::Winding).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.Winding"; + g_typeCast[typeName] = "axrhi.Winding"; + return 1; +} + + +int lua_register_ax_rhi_TextureType(lua_State* tolua_S) +{ + tolua_module(tolua_S, "TextureType", 0); + tolua_beginmodule(tolua_S,"TextureType"); + tolua_constant(tolua_S, "TEXTURE_2D", 0); + tolua_constant(tolua_S, "TEXTURE_CUBE", 1); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::TextureType).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.TextureType"; + g_typeCast[typeName] = "axrhi.TextureType"; + return 1; +} + + +int lua_register_ax_rhi_SamplerAddressMode(lua_State* tolua_S) +{ + tolua_module(tolua_S, "SamplerAddressMode", 0); + tolua_beginmodule(tolua_S,"SamplerAddressMode"); + tolua_constant(tolua_S, "REPEAT", 0); + tolua_constant(tolua_S, "MIRROR_REPEAT", 1); + tolua_constant(tolua_S, "CLAMP_TO_EDGE", 2); + tolua_constant(tolua_S, "DONT_CARE", 3); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::SamplerAddressMode).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.SamplerAddressMode"; + g_typeCast[typeName] = "axrhi.SamplerAddressMode"; + return 1; +} + + +int lua_register_ax_rhi_SamplerFilter(lua_State* tolua_S) +{ + tolua_module(tolua_S, "SamplerFilter", 0); + tolua_beginmodule(tolua_S,"SamplerFilter"); + tolua_constant(tolua_S, "NEAREST", 0); + tolua_constant(tolua_S, "NEAREST_MIPMAP_NEAREST", 1); + tolua_constant(tolua_S, "NEAREST_MIPMAP_LINEAR", 2); + tolua_constant(tolua_S, "LINEAR", 3); + tolua_constant(tolua_S, "LINEAR_MIPMAP_LINEAR", 4); + tolua_constant(tolua_S, "LINEAR_MIPMAP_NEAREST", 5); + tolua_constant(tolua_S, "DONT_CARE", 6); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::SamplerFilter).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.SamplerFilter"; + g_typeCast[typeName] = "axrhi.SamplerFilter"; + return 1; +} + + +int lua_register_ax_rhi_TextureCubeFace(lua_State* tolua_S) +{ + tolua_module(tolua_S, "TextureCubeFace", 0); + tolua_beginmodule(tolua_S,"TextureCubeFace"); + tolua_constant(tolua_S, "POSITIVE_X", 0); + tolua_constant(tolua_S, "NEGATIVE_X", 1); + tolua_constant(tolua_S, "POSITIVE_Y", 2); + tolua_constant(tolua_S, "NEGATIVE_Y", 3); + tolua_constant(tolua_S, "POSITIVE_Z", 4); + tolua_constant(tolua_S, "NEGATIVE_Z", 5); + tolua_endmodule(tolua_S); + + auto typeName = typeid(ax::rhi::TextureCubeFace).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.TextureCubeFace"; + g_typeCast[typeName] = "axrhi.TextureCubeFace"; + return 1; +} + +int lua_ax_rhi_Program_getUniformLocation(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getUniformLocation'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + ax::rhi::Uniform arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Program:getUniformLocation"); + + if (!ok) { break; } + ax::rhi::UniformLocation ret = cobj->getUniformLocation(arg0); + uniformLocation_to_luaval(tolua_S, ret); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.Program:getUniformLocation"); + + if (!ok) { break; } + ax::rhi::UniformLocation ret = cobj->getUniformLocation(arg0); + uniformLocation_to_luaval(tolua_S, ret); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getUniformLocation",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getUniformLocation'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getVertexInputDesc(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getVertexInputDesc'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + ax::rhi::VertexInputKind arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Program:getVertexInputDesc"); + + if (!ok) { break; } + const ax::rhi::VertexInputDesc* ret = cobj->getVertexInputDesc(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR VertexInputDesc*; + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.Program:getVertexInputDesc"); + + if (!ok) { break; } + const ax::rhi::VertexInputDesc* ret = cobj->getVertexInputDesc(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR VertexInputDesc*; + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getVertexInputDesc",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getVertexInputDesc'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getMaxVertexLocation(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getMaxVertexLocation'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getMaxVertexLocation'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxVertexLocation(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getMaxVertexLocation",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getMaxVertexLocation'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getMaxFragmentLocation(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getMaxFragmentLocation'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getMaxFragmentLocation'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxFragmentLocation(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getMaxFragmentLocation",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getMaxFragmentLocation'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getVertexShaderSource(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getVertexShaderSource'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getVertexShaderSource'", nullptr); + return 0; + } + auto&& ret = cobj->getVertexShaderSource(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getVertexShaderSource",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getVertexShaderSource'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getFragmentShaderSource(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getFragmentShaderSource'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getFragmentShaderSource'", nullptr); + return 0; + } + auto&& ret = cobj->getFragmentShaderSource(); + lua_pushlstring(tolua_S,ret.data(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getFragmentShaderSource",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getFragmentShaderSource'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_defineVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_defineVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::VertexLayoutType arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Program:defineVertexLayout"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_defineVertexLayout'", nullptr); + return 0; + } + cobj->defineVertexLayout(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:defineVertexLayout",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_defineVertexLayout'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getProgramType(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getProgramType'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getProgramType'", nullptr); + return 0; + } + auto&& ret = cobj->getProgramType(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getProgramType",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getProgramType'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getProgramId(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getProgramId'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getProgramId'", nullptr); + return 0; + } + auto&& ret = cobj->getProgramId(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getProgramId",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getProgramId'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getUniformBufferSize(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getUniformBufferSize'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::ShaderStage arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Program:getUniformBufferSize"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getUniformBufferSize'", nullptr); + return 0; + } + auto&& ret = cobj->getUniformBufferSize(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR ??; + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getUniformBufferSize",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getUniformBufferSize'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Program_getVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Program* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Program",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Program*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Program_getVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Program_getVertexLayout'", nullptr); + return 0; + } + auto&& ret = cobj->getVertexLayout(); + object_to_luaval(tolua_S, "axrhi.VertexLayout",(ax::rhi::VertexLayout*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Program:getVertexLayout",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Program_getVertexLayout'.",&tolua_err); +#endif + + return 0; +} +static int lua_ax_rhi_Program_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Program)"); + return 0; +} + +int lua_register_ax_rhi_Program(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"axrhi.Program"); + tolua_cclass(tolua_S,"Program","axrhi.Program","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Program"); + tolua_function(tolua_S,"getUniformLocation",lua_ax_rhi_Program_getUniformLocation); + tolua_function(tolua_S,"getVertexInputDesc",lua_ax_rhi_Program_getVertexInputDesc); + tolua_function(tolua_S,"getMaxVertexLocation",lua_ax_rhi_Program_getMaxVertexLocation); + tolua_function(tolua_S,"getMaxFragmentLocation",lua_ax_rhi_Program_getMaxFragmentLocation); + tolua_function(tolua_S,"getVertexShaderSource",lua_ax_rhi_Program_getVertexShaderSource); + tolua_function(tolua_S,"getFragmentShaderSource",lua_ax_rhi_Program_getFragmentShaderSource); + tolua_function(tolua_S,"defineVertexLayout",lua_ax_rhi_Program_defineVertexLayout); + tolua_function(tolua_S,"getProgramType",lua_ax_rhi_Program_getProgramType); + tolua_function(tolua_S,"getProgramId",lua_ax_rhi_Program_getProgramId); + tolua_function(tolua_S,"getUniformBufferSize",lua_ax_rhi_Program_getUniformBufferSize); + tolua_function(tolua_S,"getVertexLayout",lua_ax_rhi_Program_getVertexLayout); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::rhi::Program).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.Program"; + g_typeCast[typeName] = "axrhi.Program"; + return 1; +} + +int lua_ax_rhi_VertexLayout_getStride(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::VertexLayout* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.VertexLayout",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::VertexLayout*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_VertexLayout_getStride'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_VertexLayout_getStride'", nullptr); + return 0; + } + auto&& ret = cobj->getStride(); + #pragma warning NO CONVERSION FROM NATIVE FOR ??; + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.VertexLayout:getStride",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_VertexLayout_getStride'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_VertexLayout_getInstanceStride(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::VertexLayout* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.VertexLayout",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::VertexLayout*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_VertexLayout_getInstanceStride'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_VertexLayout_getInstanceStride'", nullptr); + return 0; + } + auto&& ret = cobj->getInstanceStride(); + #pragma warning NO CONVERSION FROM NATIVE FOR ??; + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.VertexLayout:getInstanceStride",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_VertexLayout_getInstanceStride'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_VertexLayout_getVertexStepMode(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::VertexLayout* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.VertexLayout",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::VertexLayout*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_VertexLayout_getVertexStepMode'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_VertexLayout_getVertexStepMode'", nullptr); + return 0; + } + int ret = (int)cobj->getVertexStepMode(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.VertexLayout:getVertexStepMode",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_VertexLayout_getVertexStepMode'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_VertexLayout_isValid(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::VertexLayout* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.VertexLayout",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::VertexLayout*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_VertexLayout_isValid'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_VertexLayout_isValid'", nullptr); + return 0; + } + auto&& ret = cobj->isValid(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.VertexLayout:isValid",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_VertexLayout_isValid'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_VertexLayout_clone(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::VertexLayout* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.VertexLayout",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::VertexLayout*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_VertexLayout_clone'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_VertexLayout_clone'", nullptr); + return 0; + } + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "axrhi.VertexLayout",(ax::rhi::VertexLayout*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.VertexLayout:clone",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_VertexLayout_clone'.",&tolua_err); +#endif + + return 0; +} +static int lua_ax_rhi_VertexLayout_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (VertexLayout)"); + return 0; +} + +int lua_register_ax_rhi_VertexLayout(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"axrhi.VertexLayout"); + tolua_cclass(tolua_S,"VertexLayout","axrhi.VertexLayout","",nullptr); + + tolua_beginmodule(tolua_S,"VertexLayout"); + tolua_function(tolua_S,"getStride",lua_ax_rhi_VertexLayout_getStride); + tolua_function(tolua_S,"getInstanceStride",lua_ax_rhi_VertexLayout_getInstanceStride); + tolua_function(tolua_S,"getVertexStepMode",lua_ax_rhi_VertexLayout_getVertexStepMode); + tolua_function(tolua_S,"isValid",lua_ax_rhi_VertexLayout_isValid); + tolua_function(tolua_S,"clone",lua_ax_rhi_VertexLayout_clone); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::rhi::VertexLayout).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.VertexLayout"; + g_typeCast[typeName] = "axrhi.VertexLayout"; + return 1; +} + +int lua_ax_rhi_ProgramState_clone(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_clone'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_clone'", nullptr); + return 0; + } + auto&& ret = cobj->clone(); + object_to_luaval(tolua_S, "axrhi.ProgramState",(ax::rhi::ProgramState*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:clone",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_clone'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_getProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_getProgram'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_getProgram'", nullptr); + return 0; + } + auto&& ret = cobj->getProgram(); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:getProgram",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_getProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_getVertexInputDesc(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_getVertexInputDesc'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 1) { + ax::rhi::VertexInputKind arg0; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.ProgramState:getVertexInputDesc"); + + if (!ok) { break; } + const ax::rhi::VertexInputDesc* ret = cobj->getVertexInputDesc(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR VertexInputDesc*; + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.ProgramState:getVertexInputDesc"); + + if (!ok) { break; } + const ax::rhi::VertexInputDesc* ret = cobj->getVertexInputDesc(arg0); + #pragma warning NO CONVERSION FROM NATIVE FOR VertexInputDesc*; + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:getVertexInputDesc",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_getVertexInputDesc'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_setTexture(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_setTexture'", nullptr); + return 0; + } +#endif + argc = lua_gettop(tolua_S)-1; + do{ + if (argc == 3) { + ax::rhi::UniformLocation arg0; + ok &= luaval_to_uniformLocation(tolua_S, 2, arg0, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + ax::rhi::Texture* arg2; + ok &= luaval_to_object(tolua_S, 4, "axrhi.Texture",&arg2, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + cobj->setTexture(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 1) { + ax::rhi::Texture* arg0; + ok &= luaval_to_object(tolua_S, 2, "axrhi.Texture",&arg0, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + cobj->setTexture(arg0); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + do{ + if (argc == 4) { + ax::rhi::UniformLocation arg0; + ok &= luaval_to_uniformLocation(tolua_S, 2, arg0, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + int arg1; + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + int arg2; + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + ax::rhi::Texture* arg3; + ok &= luaval_to_object(tolua_S, 5, "axrhi.Texture",&arg3, "axrhi.ProgramState:setTexture"); + + if (!ok) { break; } + cobj->setTexture(arg0, arg1, arg2, arg3); + lua_settop(tolua_S, 1); + return 1; + } + }while(0); + ok = true; + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:setTexture",argc, 4); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_setTexture'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_setParameterAutoBinding(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_setParameterAutoBinding'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + std::string_view arg0; + std::string_view arg1; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.ProgramState:setParameterAutoBinding"); + + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axrhi.ProgramState:setParameterAutoBinding"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_setParameterAutoBinding'", nullptr); + return 0; + } + cobj->setParameterAutoBinding(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:setParameterAutoBinding",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_setParameterAutoBinding'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_getMutableVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_getMutableVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_getMutableVertexLayout'", nullptr); + return 0; + } + auto&& ret = cobj->getMutableVertexLayout(); + object_to_luaval(tolua_S, "axrhi.VertexLayout",(ax::rhi::VertexLayout*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:getMutableVertexLayout",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_getMutableVertexLayout'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_setSharedVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_setSharedVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::VertexLayout* arg0; + + ok &= luaval_to_object(tolua_S, 2, "axrhi.VertexLayout",&arg0, "axrhi.ProgramState:setSharedVertexLayout"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_setSharedVertexLayout'", nullptr); + return 0; + } + cobj->setSharedVertexLayout(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:setSharedVertexLayout",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_setSharedVertexLayout'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_getBatchId(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_getBatchId'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_getBatchId'", nullptr); + return 0; + } + auto&& ret = cobj->getBatchId(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:getBatchId",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_getBatchId'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_isBatchable(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_isBatchable'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_isBatchable'", nullptr); + return 0; + } + auto&& ret = cobj->isBatchable(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:isBatchable",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_isBatchable'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_updateBatchId(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_updateBatchId'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_updateBatchId'", nullptr); + return 0; + } + cobj->updateBatchId(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:updateBatchId",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_updateBatchId'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_validateSharedVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.ProgramState",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_ProgramState_validateSharedVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::VertexLayoutType arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.ProgramState:validateSharedVertexLayout"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_validateSharedVertexLayout'", nullptr); + return 0; + } + cobj->validateSharedVertexLayout(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:validateSharedVertexLayout",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_validateSharedVertexLayout'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_ProgramState_constructor(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::ProgramState* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::Program* arg0; + + ok &= luaval_to_object(tolua_S, 2, "axrhi.Program",&arg0, "axrhi.ProgramState:ProgramState"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_ProgramState_constructor'", nullptr); + return 0; + } + cobj = new ax::rhi::ProgramState(arg0); + cobj->autorelease(); + int ID = (int)cobj->_ID ; + int* luaID = &cobj->_luaID ; + toluafix_pushusertype_object(tolua_S, ID, luaID, (void*)cobj,"axrhi.ProgramState"); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.ProgramState:ProgramState",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_ProgramState_constructor'.",&tolua_err); +#endif + + return 0; +} + +static int lua_ax_rhi_ProgramState_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (ProgramState)"); + return 0; +} + +int lua_register_ax_rhi_ProgramState(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"axrhi.ProgramState"); + tolua_cclass(tolua_S,"ProgramState","axrhi.ProgramState","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"ProgramState"); + tolua_function(tolua_S,"new",lua_ax_rhi_ProgramState_constructor); + tolua_function(tolua_S,"clone",lua_ax_rhi_ProgramState_clone); + tolua_function(tolua_S,"getProgram",lua_ax_rhi_ProgramState_getProgram); + tolua_function(tolua_S,"getVertexInputDesc",lua_ax_rhi_ProgramState_getVertexInputDesc); + tolua_function(tolua_S,"setTexture",lua_ax_rhi_ProgramState_setTexture); + tolua_function(tolua_S,"setParameterAutoBinding",lua_ax_rhi_ProgramState_setParameterAutoBinding); + tolua_function(tolua_S,"getMutableVertexLayout",lua_ax_rhi_ProgramState_getMutableVertexLayout); + tolua_function(tolua_S,"setSharedVertexLayout",lua_ax_rhi_ProgramState_setSharedVertexLayout); + tolua_function(tolua_S,"getBatchId",lua_ax_rhi_ProgramState_getBatchId); + tolua_function(tolua_S,"isBatchable",lua_ax_rhi_ProgramState_isBatchable); + tolua_function(tolua_S,"updateBatchId",lua_ax_rhi_ProgramState_updateBatchId); + tolua_function(tolua_S,"validateSharedVertexLayout",lua_ax_rhi_ProgramState_validateSharedVertexLayout); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::rhi::ProgramState).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.ProgramState"; + g_typeCast[typeName] = "axrhi.ProgramState"; + return 1; +} + +int lua_ax_rhi_Texture_updateSamplerDesc(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_updateSamplerDesc'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::SamplerDesc arg0; + + ok &= luaval_to_samplerDesc(tolua_S, 2, arg0, "axrhi.Texture:updateSamplerDesc"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_updateSamplerDesc'", nullptr); + return 0; + } + cobj->updateSamplerDesc(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:updateSamplerDesc",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_updateSamplerDesc'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_generateMipmaps(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_generateMipmaps'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_generateMipmaps'", nullptr); + return 0; + } + cobj->generateMipmaps(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:generateMipmaps",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_generateMipmaps'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_updateTextureDesc(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_updateTextureDesc'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::TextureDesc arg0; + + #pragma warning NO CONVERSION TO NATIVE FOR TextureDesc + ok = false; + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_updateTextureDesc'", nullptr); + return 0; + } + cobj->updateTextureDesc(arg0); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 2) + { + ax::rhi::TextureDesc arg0; + int arg1; + + #pragma warning NO CONVERSION TO NATIVE FOR TextureDesc + ok = false; + + ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axrhi.Texture:updateTextureDesc"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_updateTextureDesc'", nullptr); + return 0; + } + cobj->updateTextureDesc(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:updateTextureDesc",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_updateTextureDesc'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getTextureFormat(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getTextureFormat'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getTextureFormat'", nullptr); + return 0; + } + int ret = (int)cobj->getTextureFormat(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getTextureFormat",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getTextureFormat'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getTextureUsage(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getTextureUsage'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getTextureUsage'", nullptr); + return 0; + } + int ret = (int)cobj->getTextureUsage(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getTextureUsage",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getTextureUsage'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getTextureType(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getTextureType'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getTextureType'", nullptr); + return 0; + } + int ret = (int)cobj->getTextureType(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getTextureType",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getTextureType'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_hasMipmaps(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_hasMipmaps'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_hasMipmaps'", nullptr); + return 0; + } + auto&& ret = cobj->hasMipmaps(); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:hasMipmaps",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_hasMipmaps'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getCount(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getCount'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getCount'", nullptr); + return 0; + } + auto&& ret = cobj->getCount(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getCount",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getCount'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getWidth(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getWidth'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getWidth'", nullptr); + return 0; + } + auto&& ret = cobj->getWidth(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getWidth",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getWidth'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_getHeight(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_getHeight'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_getHeight'", nullptr); + return 0; + } + auto&& ret = cobj->getHeight(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:getHeight",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_getHeight'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_Texture_updateFaceData(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::Texture* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.Texture",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::Texture*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_Texture_updateFaceData'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + ax::rhi::TextureCubeFace arg0; + void* arg1; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Texture:updateFaceData"); + + #pragma warning NO CONVERSION TO NATIVE FOR void* + ok = false; + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_updateFaceData'", nullptr); + return 0; + } + cobj->updateFaceData(arg0, arg1); + lua_settop(tolua_S, 1); + return 1; + } + if (argc == 3) + { + ax::rhi::TextureCubeFace arg0; + void* arg1; + int arg2; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.Texture:updateFaceData"); + + #pragma warning NO CONVERSION TO NATIVE FOR void* + ok = false; + + ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axrhi.Texture:updateFaceData"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_Texture_updateFaceData'", nullptr); + return 0; + } + cobj->updateFaceData(arg0, arg1, arg2); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.Texture:updateFaceData",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_Texture_updateFaceData'.",&tolua_err); +#endif + + return 0; +} +static int lua_ax_rhi_Texture_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (Texture)"); + return 0; +} + +int lua_register_ax_rhi_Texture(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"axrhi.Texture"); + tolua_cclass(tolua_S,"Texture","axrhi.Texture","ax.Object",nullptr); + + tolua_beginmodule(tolua_S,"Texture"); + tolua_function(tolua_S,"updateSamplerDesc",lua_ax_rhi_Texture_updateSamplerDesc); + tolua_function(tolua_S,"generateMipmaps",lua_ax_rhi_Texture_generateMipmaps); + tolua_function(tolua_S,"updateTextureDesc",lua_ax_rhi_Texture_updateTextureDesc); + tolua_function(tolua_S,"getTextureFormat",lua_ax_rhi_Texture_getTextureFormat); + tolua_function(tolua_S,"getTextureUsage",lua_ax_rhi_Texture_getTextureUsage); + tolua_function(tolua_S,"getTextureType",lua_ax_rhi_Texture_getTextureType); + tolua_function(tolua_S,"hasMipmaps",lua_ax_rhi_Texture_hasMipmaps); + tolua_function(tolua_S,"getCount",lua_ax_rhi_Texture_getCount); + tolua_function(tolua_S,"getWidth",lua_ax_rhi_Texture_getWidth); + tolua_function(tolua_S,"getHeight",lua_ax_rhi_Texture_getHeight); + tolua_function(tolua_S,"updateFaceData",lua_ax_rhi_Texture_updateFaceData); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::rhi::Texture).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.Texture"; + g_typeCast[typeName] = "axrhi.Texture"; + return 1; +} + +int lua_ax_rhi_DriverBase_createDefaultRenderTarget(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_createDefaultRenderTarget'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createDefaultRenderTarget'", nullptr); + return 0; + } + auto&& ret = cobj->createDefaultRenderTarget(); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:createDefaultRenderTarget",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_createDefaultRenderTarget'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_createRenderTarget(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_createRenderTarget'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createRenderTarget'", nullptr); + return 0; + } + auto&& ret = cobj->createRenderTarget(); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); + return 1; + } + if (argc == 1) + { + ax::rhi::Texture* arg0; + + ok &= luaval_to_object(tolua_S, 2, "axrhi.Texture",&arg0, "axrhi.DriverBase:createRenderTarget"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createRenderTarget'", nullptr); + return 0; + } + auto&& ret = cobj->createRenderTarget(arg0); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); + return 1; + } + if (argc == 2) + { + ax::rhi::Texture* arg0; + ax::rhi::Texture* arg1; + + ok &= luaval_to_object(tolua_S, 2, "axrhi.Texture",&arg0, "axrhi.DriverBase:createRenderTarget"); + + ok &= luaval_to_object(tolua_S, 3, "axrhi.Texture",&arg1, "axrhi.DriverBase:createRenderTarget"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createRenderTarget'", nullptr); + return 0; + } + auto&& ret = cobj->createRenderTarget(arg0, arg1); + object_to_luaval(tolua_S, "axrhi.RenderTarget",(ax::rhi::RenderTarget*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:createRenderTarget",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_createRenderTarget'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_createProgram(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_createProgram'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 2) + { + std::string_view arg0; + std::string_view arg1; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.DriverBase:createProgram"); + + ok &= luaval_to_std_string_view(tolua_S, 3,&arg1, "axrhi.DriverBase:createProgram"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createProgram'", nullptr); + return 0; + } + auto&& ret = cobj->createProgram(arg0, arg1); + object_to_luaval(tolua_S, "axrhi.Program",(ax::rhi::Program*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:createProgram",argc, 2); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_createProgram'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_createVertexLayout(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_createVertexLayout'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_createVertexLayout'", nullptr); + return 0; + } + auto&& ret = cobj->createVertexLayout(); + object_to_luaval(tolua_S, "axrhi.VertexLayout",(ax::rhi::VertexLayout*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:createVertexLayout",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_createVertexLayout'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_resetState(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_resetState'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_resetState'", nullptr); + return 0; + } + cobj->resetState(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:resetState",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_resetState'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getVendor(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getVendor'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getVendor'", nullptr); + return 0; + } + auto&& ret = cobj->getVendor(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getVendor",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getVendor'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getRenderer(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getRenderer'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getRenderer'", nullptr); + return 0; + } + auto&& ret = cobj->getRenderer(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getRenderer",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getRenderer'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getVersion(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getVersion'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getVersion'", nullptr); + return 0; + } + auto&& ret = cobj->getVersion(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getVersion",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getVersion'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getShaderVersion(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getShaderVersion'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getShaderVersion'", nullptr); + return 0; + } + auto&& ret = cobj->getShaderVersion(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getShaderVersion",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getShaderVersion'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_hasExtension(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_hasExtension'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + std::string_view arg0; + + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axrhi.DriverBase:hasExtension"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_hasExtension'", nullptr); + return 0; + } + auto&& ret = cobj->hasExtension(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:hasExtension",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_hasExtension'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_dumpExtensions(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_dumpExtensions'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_dumpExtensions'", nullptr); + return 0; + } + auto&& ret = cobj->dumpExtensions(); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:dumpExtensions",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_dumpExtensions'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_checkForFeatureSupported(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_checkForFeatureSupported'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::rhi::FeatureType arg0; + + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axrhi.DriverBase:checkForFeatureSupported"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_checkForFeatureSupported'", nullptr); + return 0; + } + auto&& ret = cobj->checkForFeatureSupported(arg0); + tolua_pushboolean(tolua_S,(bool)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:checkForFeatureSupported",argc, 1); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_checkForFeatureSupported'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getMaxTextureSize(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getMaxTextureSize'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getMaxTextureSize'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxTextureSize(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getMaxTextureSize",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getMaxTextureSize'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getMaxAttributes(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getMaxAttributes'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getMaxAttributes'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxAttributes(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getMaxAttributes",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getMaxAttributes'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getMaxTextureUnits(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getMaxTextureUnits'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getMaxTextureUnits'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxTextureUnits(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getMaxTextureUnits",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getMaxTextureUnits'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getMaxSamplesAllowed(lua_State* tolua_S) +{ + int argc = 0; + ax::rhi::DriverBase* cobj = nullptr; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + + +#if _AX_DEBUG >= 1 + if (!tolua_isusertype(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + cobj = (ax::rhi::DriverBase*)tolua_tousertype(tolua_S,1,0); + +#if _AX_DEBUG >= 1 + if (!cobj) + { + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_rhi_DriverBase_getMaxSamplesAllowed'", nullptr); + return 0; + } +#endif + + argc = lua_gettop(tolua_S)-1; + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getMaxSamplesAllowed'", nullptr); + return 0; + } + auto&& ret = cobj->getMaxSamplesAllowed(); + tolua_pushnumber(tolua_S,(lua_Number)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axrhi.DriverBase:getMaxSamplesAllowed",argc, 0); + return 0; + +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getMaxSamplesAllowed'.",&tolua_err); +#endif + + return 0; +} +int lua_ax_rhi_DriverBase_getInstance(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_getInstance'", nullptr); + return 0; + } + auto&& ret = ax::rhi::DriverBase::getInstance(); + object_to_luaval(tolua_S, "axrhi.DriverBase",(ax::rhi::DriverBase*)ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axrhi.DriverBase:getInstance",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_getInstance'.",&tolua_err); +#endif + return 0; +} +int lua_ax_rhi_DriverBase_destroyInstance(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"axrhi.DriverBase",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 0) + { + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_rhi_DriverBase_destroyInstance'", nullptr); + return 0; + } + ax::rhi::DriverBase::destroyInstance(); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axrhi.DriverBase:destroyInstance",argc, 0); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_rhi_DriverBase_destroyInstance'.",&tolua_err); +#endif + return 0; +} +static int lua_ax_rhi_DriverBase_finalize(lua_State* tolua_S) +{ + AXLOGV("luabindings: finalizing LUA object (DriverBase)"); + return 0; +} + +int lua_register_ax_rhi_DriverBase(lua_State* tolua_S) +{ + tolua_usertype(tolua_S,"axrhi.DriverBase"); + tolua_cclass(tolua_S,"DriverBase","axrhi.DriverBase","",nullptr); + + tolua_beginmodule(tolua_S,"DriverBase"); + tolua_function(tolua_S,"createDefaultRenderTarget",lua_ax_rhi_DriverBase_createDefaultRenderTarget); + tolua_function(tolua_S,"createRenderTarget",lua_ax_rhi_DriverBase_createRenderTarget); + tolua_function(tolua_S,"createProgram",lua_ax_rhi_DriverBase_createProgram); + tolua_function(tolua_S,"createVertexLayout",lua_ax_rhi_DriverBase_createVertexLayout); + tolua_function(tolua_S,"resetState",lua_ax_rhi_DriverBase_resetState); + tolua_function(tolua_S,"getVendor",lua_ax_rhi_DriverBase_getVendor); + tolua_function(tolua_S,"getRenderer",lua_ax_rhi_DriverBase_getRenderer); + tolua_function(tolua_S,"getVersion",lua_ax_rhi_DriverBase_getVersion); + tolua_function(tolua_S,"getShaderVersion",lua_ax_rhi_DriverBase_getShaderVersion); + tolua_function(tolua_S,"hasExtension",lua_ax_rhi_DriverBase_hasExtension); + tolua_function(tolua_S,"dumpExtensions",lua_ax_rhi_DriverBase_dumpExtensions); + tolua_function(tolua_S,"checkForFeatureSupported",lua_ax_rhi_DriverBase_checkForFeatureSupported); + tolua_function(tolua_S,"getMaxTextureSize",lua_ax_rhi_DriverBase_getMaxTextureSize); + tolua_function(tolua_S,"getMaxAttributes",lua_ax_rhi_DriverBase_getMaxAttributes); + tolua_function(tolua_S,"getMaxTextureUnits",lua_ax_rhi_DriverBase_getMaxTextureUnits); + tolua_function(tolua_S,"getMaxSamplesAllowed",lua_ax_rhi_DriverBase_getMaxSamplesAllowed); + tolua_function(tolua_S,"getInstance", lua_ax_rhi_DriverBase_getInstance); + tolua_function(tolua_S,"destroyInstance", lua_ax_rhi_DriverBase_destroyInstance); + tolua_endmodule(tolua_S); + auto typeName = typeid(ax::rhi::DriverBase).name(); // rtti is literal storage + g_luaType[reinterpret_cast(typeName)] = "axrhi.DriverBase"; + g_typeCast[typeName] = "axrhi.DriverBase"; + return 1; +} +TOLUA_API int register_all_ax_rhi(lua_State* tolua_S) +{ + tolua_open(tolua_S); + + tolua_module(tolua_S,"axrhi",0); + tolua_beginmodule(tolua_S,"axrhi"); + + lua_register_ax_rhi_BufferUsage(tolua_S); + lua_register_ax_rhi_BufferType(tolua_S); + lua_register_ax_rhi_ShaderStage(tolua_S); + lua_register_ax_rhi_VertexFormat(tolua_S); + lua_register_ax_rhi_PixelFormat(tolua_S); + lua_register_ax_rhi_TextureUsage(tolua_S); + lua_register_ax_rhi_IndexFormat(tolua_S); + lua_register_ax_rhi_VertexStepMode(tolua_S); + lua_register_ax_rhi_PrimitiveType(tolua_S); + lua_register_ax_rhi_BlendFactor(tolua_S); + lua_register_ax_rhi_ColorWriteMask(tolua_S); + lua_register_ax_rhi_CullMode(tolua_S); + lua_register_ax_rhi_Winding(tolua_S); + lua_register_ax_rhi_TextureType(tolua_S); + lua_register_ax_rhi_SamplerAddressMode(tolua_S); + lua_register_ax_rhi_SamplerFilter(tolua_S); + lua_register_ax_rhi_TextureCubeFace(tolua_S); + lua_register_ax_rhi_Program(tolua_S); + lua_register_ax_rhi_VertexLayout(tolua_S); + lua_register_ax_rhi_ProgramState(tolua_S); + lua_register_ax_rhi_Texture(tolua_S); + lua_register_ax_rhi_DriverBase(tolua_S); + + tolua_endmodule(tolua_S); + return 1; +} + diff --git a/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.hpp new file mode 100644 index 000000000000..95b4a0c98702 --- /dev/null +++ b/extensions/scripting/lua-bindings/auto/axlua_rhi_auto.hpp @@ -0,0 +1,4 @@ +#pragma once +#include "axmol/base/Config.h" +#include "tolua++.h" +int register_all_ax_rhi(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_spine_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_spine_auto.hpp index 627f36942fce..2d4edb4c3ae3 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_spine_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_spine_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_spine(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_studio_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_studio_auto.cpp index f6098b000310..00623fd0f6a9 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_studio_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_studio_auto.cpp @@ -1533,9 +1533,9 @@ int lua_ax_studio_ActionTintFrame_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ccs.ActionTintFrame:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ccs.ActionTintFrame:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_studio_ActionTintFrame_setColor'", nullptr); @@ -1589,7 +1589,7 @@ int lua_ax_studio_ActionTintFrame_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ccs.ActionTintFrame:getColor",argc, 0); @@ -3002,9 +3002,9 @@ int lua_ax_studio_BaseData_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "ccs.BaseData:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ccs.BaseData:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_studio_BaseData_setColor'", nullptr); @@ -3058,7 +3058,7 @@ int lua_ax_studio_BaseData_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ccs.BaseData:getColor",argc, 0); @@ -19302,9 +19302,9 @@ int lua_ax_studio_ColorFrame_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "ccs.ColorFrame:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "ccs.ColorFrame:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_studio_ColorFrame_setColor'", nullptr); @@ -19358,7 +19358,7 @@ int lua_ax_studio_ColorFrame_getColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ccs.ColorFrame:getColor",argc, 0); @@ -24342,9 +24342,9 @@ int lua_ax_studio_BoneNode_setDebugDrawColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4F arg0; + ax::Color arg0; - ok &=luaval_to_color4f(tolua_S, 2, &arg0, "ccs.BoneNode:setDebugDrawColor"); + ok &=luaval_to_color(tolua_S, 2, &arg0, "ccs.BoneNode:setDebugDrawColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_studio_BoneNode_setDebugDrawColor'", nullptr); @@ -24398,7 +24398,7 @@ int lua_ax_studio_BoneNode_getDebugDrawColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getDebugDrawColor(); - color4f_to_luaval(tolua_S, ret); + color_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "ccs.BoneNode:getDebugDrawColor",argc, 0); diff --git a/extensions/scripting/lua-bindings/auto/axlua_studio_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_studio_auto.hpp index 75ed9fc8fa27..89518fbbf926 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_studio_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_studio_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_studio(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_ui_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_ui_auto.cpp index 6fad33662bd3..b6bb35bb8735 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_ui_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_ui_auto.cpp @@ -1,5 +1,5 @@ #include "lua-bindings/auto/axlua_ui_auto.hpp" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" @@ -5007,12 +5007,12 @@ int lua_ax_ui_Layout_setBackGroundColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; do{ if (argc == 2) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.Layout:setBackGroundColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Layout:setBackGroundColor"); if (!ok) { break; } - ax::Color3B arg1; - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.Layout:setBackGroundColor"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.Layout:setBackGroundColor"); if (!ok) { break; } cobj->setBackGroundColor(arg0, arg1); @@ -5023,8 +5023,8 @@ int lua_ax_ui_Layout_setBackGroundColor(lua_State* tolua_S) ok = true; do{ if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.Layout:setBackGroundColor"); + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Layout:setBackGroundColor"); if (!ok) { break; } cobj->setBackGroundColor(arg0); @@ -5077,7 +5077,7 @@ int lua_ax_ui_Layout_getBackGroundColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getBackGroundColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Layout:getBackGroundColor",argc, 0); @@ -5124,7 +5124,7 @@ int lua_ax_ui_Layout_getBackGroundStartColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getBackGroundStartColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Layout:getBackGroundStartColor",argc, 0); @@ -5171,7 +5171,7 @@ int lua_ax_ui_Layout_getBackGroundEndColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getBackGroundEndColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Layout:getBackGroundEndColor",argc, 0); @@ -5406,9 +5406,9 @@ int lua_ax_ui_Layout_setBackGroundImageColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.Layout:setBackGroundImageColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Layout:setBackGroundImageColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Layout_setBackGroundImageColor'", nullptr); @@ -5512,7 +5512,7 @@ int lua_ax_ui_Layout_getBackGroundImageColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getBackGroundImageColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Layout:getBackGroundImageColor",argc, 0); @@ -7410,9 +7410,9 @@ int lua_ax_ui_Button_setTitleColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.Button:setTitleColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Button:setTitleColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Button_setTitleColor'", nullptr); @@ -7466,7 +7466,7 @@ int lua_ax_ui_Button_getTitleColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTitleColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Button:getTitleColor",argc, 0); @@ -12686,9 +12686,9 @@ int lua_ax_ui_Text_setTextColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:setTextColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:setTextColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Text_setTextColor'", nullptr); @@ -12742,7 +12742,7 @@ int lua_ax_ui_Text_getTextColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTextColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Text:getTextColor",argc, 0); @@ -12794,9 +12794,9 @@ int lua_ax_ui_Text_enableShadow(lua_State* tolua_S) } if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableShadow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Text_enableShadow'", nullptr); @@ -12808,10 +12808,10 @@ int lua_ax_ui_Text_enableShadow(lua_State* tolua_S) } if (argc == 2) { - ax::Color4B arg0; + ax::Color32 arg0; ax::Vec2 arg1; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableShadow"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "axui.Text:enableShadow"); if(!ok) @@ -12825,11 +12825,11 @@ int lua_ax_ui_Text_enableShadow(lua_State* tolua_S) } if (argc == 3) { - ax::Color4B arg0; + ax::Color32 arg0; ax::Vec2 arg1; int arg2; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableShadow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableShadow"); ok &= luaval_to_vec2(tolua_S, 3, &arg1, "axui.Text:enableShadow"); @@ -12881,9 +12881,9 @@ int lua_ax_ui_Text_enableOutline(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableOutline"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableOutline"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Text_enableOutline'", nullptr); @@ -12895,10 +12895,10 @@ int lua_ax_ui_Text_enableOutline(lua_State* tolua_S) } if (argc == 2) { - ax::Color4B arg0; + ax::Color32 arg0; int arg1; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableOutline"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableOutline"); ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axui.Text:enableOutline"); if(!ok) @@ -12948,9 +12948,9 @@ int lua_ax_ui_Text_enableGlow(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.Text:enableGlow"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.Text:enableGlow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Text_enableGlow'", nullptr); @@ -13196,7 +13196,7 @@ int lua_ax_ui_Text_getShadowColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getShadowColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Text:getShadowColor",argc, 0); @@ -13337,7 +13337,7 @@ int lua_ax_ui_Text_getEffectColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getEffectColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.Text:getEffectColor",argc, 0); @@ -17340,9 +17340,9 @@ int lua_ax_ui_ScrollView_setScrollBarColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.ScrollView:setScrollBarColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.ScrollView:setScrollBarColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_ScrollView_setScrollBarColor'", nullptr); @@ -17396,7 +17396,7 @@ int lua_ax_ui_ScrollView_getScrollBarColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getScrollBarColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.ScrollView:getScrollBarColor",argc, 0); @@ -22528,7 +22528,7 @@ int lua_ax_ui_TextField_getPlaceHolderColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getPlaceHolderColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.TextField:getPlaceHolderColor",argc, 0); @@ -22546,14 +22546,18 @@ int lua_ax_ui_TextField_setPlaceHolderColor(lua_State* tolua_S) int argc = 0; ax::ui::TextField* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"axui.TextField",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::ui::TextField*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { @@ -22561,32 +22565,23 @@ int lua_ax_ui_TextField_setPlaceHolderColor(lua_State* tolua_S) return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.TextField:setPlaceHolderColor"); - if (!ok) { break; } - cobj->setPlaceHolderColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.TextField:setPlaceHolderColor"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Color32 arg0; - if (!ok) { break; } - cobj->setPlaceHolderColor(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.TextField:setPlaceHolderColor"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_TextField_setPlaceHolderColor'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.TextField:setPlaceHolderColor",argc, 1); + cobj->setPlaceHolderColor(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.TextField:setPlaceHolderColor",argc, 1); return 0; #if _AX_DEBUG >= 1 @@ -22630,7 +22625,7 @@ int lua_ax_ui_TextField_getTextColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTextColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.TextField:getTextColor",argc, 0); @@ -22671,9 +22666,9 @@ int lua_ax_ui_TextField_setTextColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.TextField:setTextColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.TextField:setTextColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_TextField_setTextColor'", nullptr); @@ -26005,9 +26000,9 @@ int lua_ax_ui_PageView_setIndicatorSelectedIndexColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.PageView:setIndicatorSelectedIndexColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.PageView:setIndicatorSelectedIndexColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_PageView_setIndicatorSelectedIndexColor'", nullptr); @@ -26061,7 +26056,7 @@ int lua_ax_ui_PageView_getIndicatorSelectedIndexColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getIndicatorSelectedIndexColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.PageView:getIndicatorSelectedIndexColor",argc, 0); @@ -26102,9 +26097,9 @@ int lua_ax_ui_PageView_setIndicatorIndexNodesColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.PageView:setIndicatorIndexNodesColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.PageView:setIndicatorIndexNodesColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_PageView_setIndicatorIndexNodesColor'", nullptr); @@ -26158,7 +26153,7 @@ int lua_ax_ui_PageView_getIndicatorIndexNodesColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getIndicatorIndexNodesColor(); - color3b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.PageView:getIndicatorIndexNodesColor",argc, 0); @@ -26850,46 +26845,6 @@ int lua_ax_ui_Helper_seekActionWidgetByActionTag(lua_State* tolua_S) #endif return 0; } -int lua_ax_ui_Helper_getSubStringOfUTF8String(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - -#if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S,1,"axui.Helper",0,&tolua_err)) goto tolua_lerror; -#endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 3) - { - std::string_view arg0; - unsigned int arg1; - unsigned int arg2; - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axui.Helper:getSubStringOfUTF8String"); - ok &= luaval_to_uint32(tolua_S, 3,&arg1, "axui.Helper:getSubStringOfUTF8String"); - ok &= luaval_to_uint32(tolua_S, 4,&arg2, "axui.Helper:getSubStringOfUTF8String"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_Helper_getSubStringOfUTF8String'", nullptr); - return 0; - } - auto&& ret = ax::ui::Helper::getSubStringOfUTF8String(arg0, arg1, arg2); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.Helper:getSubStringOfUTF8String",argc, 3); - return 0; -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_Helper_getSubStringOfUTF8String'.",&tolua_err); -#endif - return 0; -} int lua_ax_ui_Helper_doLayout(lua_State* tolua_S) { int argc = 0; @@ -27051,7 +27006,6 @@ int lua_register_ax_ui_Helper(lua_State* tolua_S) tolua_function(tolua_S,"seekWidgetByTag", lua_ax_ui_Helper_seekWidgetByTag); tolua_function(tolua_S,"seekWidgetByName", lua_ax_ui_Helper_seekWidgetByName); tolua_function(tolua_S,"seekActionWidgetByActionTag", lua_ax_ui_Helper_seekActionWidgetByActionTag); - tolua_function(tolua_S,"getSubStringOfUTF8String", lua_ax_ui_Helper_getSubStringOfUTF8String); tolua_function(tolua_S,"doLayout", lua_ax_ui_Helper_doLayout); tolua_function(tolua_S,"changeLayoutSystemActiveState", lua_ax_ui_Helper_changeLayoutSystemActiveState); tolua_function(tolua_S,"restrictCapInsetRect", lua_ax_ui_Helper_restrictCapInsetRect); @@ -27089,27 +27043,24 @@ int lua_ax_ui_RichElement_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 3) + if (argc == 2) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElement:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElement:init"); - - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElement:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElement:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElement_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2); + auto&& ret = cobj->init(arg0, arg1); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElement:init",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElement:init",argc, 2); return 0; #if _AX_DEBUG >= 1 @@ -27197,9 +27148,9 @@ int lua_ax_ui_RichElement_setColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color3B arg0; + ax::Color32 arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.RichElement:setColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.RichElement:setColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElement_setColor'", nullptr); @@ -27267,371 +27218,347 @@ int lua_ax_ui_RichElementText_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 8) + if (argc == 7) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; + double arg4; + unsigned int arg5; + std::string_view arg6; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); - - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 9) + if (argc == 8) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); - - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 10) + if (argc == 9) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); - - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 11) + if (argc == 10) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); - - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 12) + if (argc == 11) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:init"); - - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:init"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 13) + if (argc == 12) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:init"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:init"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:init"); - - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 14) + if (argc == 13) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; - ax::Color3B arg13; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; + ax::Color32 arg12; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:init"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:init"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:init"); - - ok &= luaval_to_color3b(tolua_S, 15, &arg13, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 14, &arg12, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 15) + if (argc == 14) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; - ax::Color3B arg13; - std::string_view arg14; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; + ax::Color32 arg12; + std::string_view arg13; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:init"); - - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:init"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:init"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:init"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:init"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:init"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:init"); - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:init"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:init"); - ok &= luaval_to_color3b(tolua_S, 15, &arg13, "axui.RichElementText:init"); + ok &=luaval_to_color32(tolua_S, 14, &arg12, "axui.RichElementText:init"); - ok &= luaval_to_std_string_view(tolua_S, 16,&arg14, "axui.RichElementText:init"); + ok &= luaval_to_std_string_view(tolua_S, 15,&arg13, "axui.RichElementText:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementText:init",argc, 8); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementText:init",argc, 7); return 0; #if _AX_DEBUG >= 1 @@ -27656,20 +27583,41 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) argc = lua_gettop(tolua_S) - 1; + if (argc == 5) + { + int arg0; + ax::Color32 arg1; + std::string_view arg2; + std::string_view arg3; + double arg4; + ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); + return 0; + } + auto&& ret = ax::ui::RichElementText::create(arg0, arg1, arg2, arg3, arg4); + object_to_luaval(tolua_S, "axui.RichElementText",(ax::ui::RichElementText*)ret); + return 1; + } if (argc == 6) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; + double arg4; + unsigned int arg5; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27682,19 +27630,19 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 7) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; + double arg4; + unsigned int arg5; + std::string_view arg6; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27707,21 +27655,21 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 8) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27734,23 +27682,23 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 9) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27763,25 +27711,25 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 10) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27794,27 +27742,27 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 11) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:create"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27827,29 +27775,29 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 12) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:create"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:create"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27862,31 +27810,31 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 13) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; + ax::Color32 arg12; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:create"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:create"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 14, &arg12, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27899,33 +27847,33 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) if (argc == 14) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; - ax::Color3B arg13; + double arg4; + unsigned int arg5; + std::string_view arg6; + ax::Color32 arg7; + int arg8; + ax::Color32 arg9; + ax::Vec2 arg10; + int arg11; + ax::Color32 arg12; + std::string_view arg13; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementText:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:create"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 15, &arg13, "axui.RichElementText:create"); + ok &= luaval_to_number(tolua_S, 6,&arg4, "axui.RichElementText:create"); + ok &= luaval_to_uint32(tolua_S, 7,&arg5, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 9, &arg7, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 10,(int *)&arg8, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 11, &arg9, "axui.RichElementText:create"); + ok &= luaval_to_vec2(tolua_S, 12, &arg10, "axui.RichElementText:create"); + ok &= luaval_to_int32(tolua_S, 13,(int *)&arg11, "axui.RichElementText:create"); + ok &=luaval_to_color32(tolua_S, 14, &arg12, "axui.RichElementText:create"); + ok &= luaval_to_std_string_view(tolua_S, 15,&arg13, "axui.RichElementText:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); @@ -27935,48 +27883,7 @@ int lua_ax_ui_RichElementText_create(lua_State* tolua_S) object_to_luaval(tolua_S, "axui.RichElementText",(ax::ui::RichElementText*)ret); return 1; } - if (argc == 15) - { - int arg0; - ax::Color3B arg1; - uint16_t arg2; - std::string_view arg3; - std::string_view arg4; - double arg5; - unsigned int arg6; - std::string_view arg7; - ax::Color3B arg8; - int arg9; - ax::Color3B arg10; - ax::Vec2 arg11; - int arg12; - ax::Color3B arg13; - std::string_view arg14; - ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementText:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementText:create"); - ok &= luaval_to_number(tolua_S, 7,&arg5, "axui.RichElementText:create"); - ok &= luaval_to_uint32(tolua_S, 8,&arg6, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 9,&arg7, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 10, &arg8, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 11,(int *)&arg9, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 12, &arg10, "axui.RichElementText:create"); - ok &= luaval_to_vec2(tolua_S, 13, &arg11, "axui.RichElementText:create"); - ok &= luaval_to_int32(tolua_S, 14,(int *)&arg12, "axui.RichElementText:create"); - ok &= luaval_to_color3b(tolua_S, 15, &arg13, "axui.RichElementText:create"); - ok &= luaval_to_std_string_view(tolua_S, 16,&arg14, "axui.RichElementText:create"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementText_create'", nullptr); - return 0; - } - auto&& ret = ax::ui::RichElementText::create(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8, arg9, arg10, arg11, arg12, arg13, arg14); - object_to_luaval(tolua_S, "axui.RichElementText",(ax::ui::RichElementText*)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementText:create",argc, 6); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementText:create",argc, 5); return 0; #if _AX_DEBUG >= 1 tolua_lerror: @@ -28069,117 +27976,105 @@ int lua_ax_ui_RichElementImage_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 3) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - std::string_view arg3; + ax::Color32 arg1; + std::string_view arg2; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:init"); - - ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3); + auto&& ret = cobj->init(arg0, arg1, arg2); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 5) + if (argc == 4) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:init"); - - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 6) + if (argc == 5) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - ax::ui::Widget::TextureResType arg5; + ax::ui::Widget::TextureResType arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:init"); - - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "axui.RichElementImage:init"); + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "axui.RichElementImage:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 7) + if (argc == 6) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - ax::ui::Widget::TextureResType arg5; - std::string_view arg6; + ax::ui::Widget::TextureResType arg4; + std::string_view arg5; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:init"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:init"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:init"); - - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "axui.RichElementImage:init"); + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "axui.RichElementImage:init"); - ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementImage:init"); + ok &= luaval_to_std_string_view(tolua_S, 7,&arg5, "axui.RichElementImage:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4, arg5); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementImage:init",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementImage:init",argc, 3); return 0; #if _AX_DEBUG >= 1 @@ -28554,95 +28449,87 @@ int lua_ax_ui_RichElementImage_create(lua_State* tolua_S) argc = lua_gettop(tolua_S) - 1; - if (argc == 4) + if (argc == 3) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - std::string_view arg3; + ax::Color32 arg1; + std::string_view arg2; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:create"); - ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3); + auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2); object_to_luaval(tolua_S, "axui.RichElementImage",(ax::ui::RichElementImage*)ret); return 1; } - if (argc == 5) + if (argc == 4) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3, arg4); + auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "axui.RichElementImage",(ax::ui::RichElementImage*)ret); return 1; } - if (argc == 6) + if (argc == 5) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - ax::ui::Widget::TextureResType arg5; + ax::ui::Widget::TextureResType arg4; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:create"); - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "axui.RichElementImage:create"); + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "axui.RichElementImage:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3, arg4, arg5); + auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3, arg4); object_to_luaval(tolua_S, "axui.RichElementImage",(ax::ui::RichElementImage*)ret); return 1; } - if (argc == 7) + if (argc == 6) { int arg0; - ax::Color3B arg1; - uint16_t arg2; + ax::Color32 arg1; + std::string_view arg2; std::string_view arg3; - std::string_view arg4; - ax::ui::Widget::TextureResType arg5; - std::string_view arg6; + ax::ui::Widget::TextureResType arg4; + std::string_view arg5; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementImage:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementImage:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementImage:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementImage:create"); + ok &= luaval_to_std_string_view(tolua_S, 4,&arg2, "axui.RichElementImage:create"); ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementImage:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementImage:create"); - ok &= luaval_to_int32(tolua_S, 7,(int *)&arg5, "axui.RichElementImage:create"); - ok &= luaval_to_std_string_view(tolua_S, 8,&arg6, "axui.RichElementImage:create"); + ok &= luaval_to_int32(tolua_S, 6,(int *)&arg4, "axui.RichElementImage:create"); + ok &= luaval_to_std_string_view(tolua_S, 7,&arg5, "axui.RichElementImage:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementImage_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3, arg4, arg5, arg6); + auto&& ret = ax::ui::RichElementImage::create(arg0, arg1, arg2, arg3, arg4, arg5); object_to_luaval(tolua_S, "axui.RichElementImage",(ax::ui::RichElementImage*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementImage:create",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementImage:create",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: @@ -28742,56 +28629,50 @@ int lua_ax_ui_RichElementCustomNode_init(lua_State* tolua_S) #endif argc = lua_gettop(tolua_S)-1; - if (argc == 4) + if (argc == 3) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - ax::Node* arg3; + ax::Color32 arg1; + ax::Node* arg2; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementCustomNode:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementCustomNode:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementCustomNode:init"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementCustomNode:init"); - - ok &= luaval_to_object(tolua_S, 5, "ax.Node",&arg3, "axui.RichElementCustomNode:init"); + ok &= luaval_to_object(tolua_S, 4, "ax.Node",&arg2, "axui.RichElementCustomNode:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementCustomNode_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3); + auto&& ret = cobj->init(arg0, arg1, arg2); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - if (argc == 5) + if (argc == 4) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - ax::Node* arg3; - std::string_view arg4; + ax::Color32 arg1; + ax::Node* arg2; + std::string_view arg3; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementCustomNode:init"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementCustomNode:init"); - - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementCustomNode:init"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementCustomNode:init"); - ok &= luaval_to_object(tolua_S, 5, "ax.Node",&arg3, "axui.RichElementCustomNode:init"); + ok &= luaval_to_object(tolua_S, 4, "ax.Node",&arg2, "axui.RichElementCustomNode:init"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementCustomNode:init"); + ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementCustomNode:init"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementCustomNode_init'", nullptr); return 0; } - auto&& ret = cobj->init(arg0, arg1, arg2, arg3, arg4); + auto&& ret = cobj->init(arg0, arg1, arg2, arg3); tolua_pushboolean(tolua_S,(bool)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementCustomNode:init",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichElementCustomNode:init",argc, 3); return 0; #if _AX_DEBUG >= 1 @@ -28816,47 +28697,43 @@ int lua_ax_ui_RichElementCustomNode_create(lua_State* tolua_S) argc = lua_gettop(tolua_S) - 1; - if (argc == 4) + if (argc == 3) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - ax::Node* arg3; + ax::Color32 arg1; + ax::Node* arg2; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementCustomNode:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementCustomNode:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementCustomNode:create"); - ok &= luaval_to_object(tolua_S, 5, "ax.Node",&arg3, "axui.RichElementCustomNode:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementCustomNode:create"); + ok &= luaval_to_object(tolua_S, 4, "ax.Node",&arg2, "axui.RichElementCustomNode:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementCustomNode_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementCustomNode::create(arg0, arg1, arg2, arg3); + auto&& ret = ax::ui::RichElementCustomNode::create(arg0, arg1, arg2); object_to_luaval(tolua_S, "axui.RichElementCustomNode",(ax::ui::RichElementCustomNode*)ret); return 1; } - if (argc == 5) + if (argc == 4) { int arg0; - ax::Color3B arg1; - uint16_t arg2; - ax::Node* arg3; - std::string_view arg4; + ax::Color32 arg1; + ax::Node* arg2; + std::string_view arg3; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementCustomNode:create"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementCustomNode:create"); - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementCustomNode:create"); - ok &= luaval_to_object(tolua_S, 5, "ax.Node",&arg3, "axui.RichElementCustomNode:create"); - ok &= luaval_to_std_string_view(tolua_S, 6,&arg4, "axui.RichElementCustomNode:create"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementCustomNode:create"); + ok &= luaval_to_object(tolua_S, 4, "ax.Node",&arg2, "axui.RichElementCustomNode:create"); + ok &= luaval_to_std_string_view(tolua_S, 5,&arg3, "axui.RichElementCustomNode:create"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichElementCustomNode_create'", nullptr); return 0; } - auto&& ret = ax::ui::RichElementCustomNode::create(arg0, arg1, arg2, arg3, arg4); + auto&& ret = ax::ui::RichElementCustomNode::create(arg0, arg1, arg2, arg3); object_to_luaval(tolua_S, "axui.RichElementCustomNode",(ax::ui::RichElementCustomNode*)ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementCustomNode:create",argc, 4); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichElementCustomNode:create",argc, 3); return 0; #if _AX_DEBUG >= 1 tolua_lerror: @@ -28939,7 +28816,7 @@ int lua_ax_ui_RichElementNewLine_create(lua_State* tolua_S) do { - if (argc == 4) + if (argc == 3) { int arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementNewLine:create"); @@ -28947,13 +28824,10 @@ int lua_ax_ui_RichElementNewLine_create(lua_State* tolua_S) int arg1; ok &= luaval_to_int32(tolua_S, 3,(int *)&arg1, "axui.RichElementNewLine:create"); if (!ok) { break; } - ax::Color3B arg2; - ok &= luaval_to_color3b(tolua_S, 4, &arg2, "axui.RichElementNewLine:create"); - if (!ok) { break; } - uint16_t arg3; - ok &= luaval_to_uint16(tolua_S, 5,&arg3, "axui.RichElementNewLine:create"); + ax::Color32 arg2; + ok &=luaval_to_color32(tolua_S, 4, &arg2, "axui.RichElementNewLine:create"); if (!ok) { break; } - ax::ui::RichElementNewLine* ret = ax::ui::RichElementNewLine::create(arg0, arg1, arg2, arg3); + ax::ui::RichElementNewLine* ret = ax::ui::RichElementNewLine::create(arg0, arg1, arg2); object_to_luaval(tolua_S, "axui.RichElementNewLine",(ax::ui::RichElementNewLine*)ret); return 1; } @@ -28961,24 +28835,21 @@ int lua_ax_ui_RichElementNewLine_create(lua_State* tolua_S) ok = true; do { - if (argc == 3) + if (argc == 2) { int arg0; ok &= luaval_to_int32(tolua_S, 2,(int *)&arg0, "axui.RichElementNewLine:create"); if (!ok) { break; } - ax::Color3B arg1; - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichElementNewLine:create"); - if (!ok) { break; } - uint16_t arg2; - ok &= luaval_to_uint16(tolua_S, 4,&arg2, "axui.RichElementNewLine:create"); + ax::Color32 arg1; + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichElementNewLine:create"); if (!ok) { break; } - ax::ui::RichElementNewLine* ret = ax::ui::RichElementNewLine::create(arg0, arg1, arg2); + ax::ui::RichElementNewLine* ret = ax::ui::RichElementNewLine::create(arg0, arg1); object_to_luaval(tolua_S, "axui.RichElementNewLine",(ax::ui::RichElementNewLine*)ret); return 1; } } while (0); ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "axui.RichElementNewLine:create",argc, 3); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d", "axui.RichElementNewLine:create",argc, 2); return 0; #if _AX_DEBUG >= 1 tolua_lerror: @@ -29718,7 +29589,7 @@ int lua_ax_ui_RichText_getFontColor(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_getFontColor3B(lua_State* tolua_S) +int lua_ax_ui_RichText_getFontColor32(lua_State* tolua_S) { int argc = 0; ax::ui::RichText* cobj = nullptr; @@ -29738,7 +29609,7 @@ int lua_ax_ui_RichText_getFontColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getFontColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getFontColor32'", nullptr); return 0; } #endif @@ -29748,19 +29619,19 @@ int lua_ax_ui_RichText_getFontColor3B(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getFontColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getFontColor32'", nullptr); return 0; } - auto&& ret = cobj->getFontColor3B(); - color3b_to_luaval(tolua_S, ret); + auto&& ret = cobj->getFontColor32(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getFontColor3B",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getFontColor32",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getFontColor3B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getFontColor32'.",&tolua_err); #endif return 0; @@ -30056,7 +29927,7 @@ int lua_ax_ui_RichText_getAnchorFontColor(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_getAnchorFontColor3B(lua_State* tolua_S) +int lua_ax_ui_RichText_getAnchorFontColor32(lua_State* tolua_S) { int argc = 0; ax::ui::RichText* cobj = nullptr; @@ -30076,7 +29947,7 @@ int lua_ax_ui_RichText_getAnchorFontColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorFontColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorFontColor32'", nullptr); return 0; } #endif @@ -30086,19 +29957,19 @@ int lua_ax_ui_RichText_getAnchorFontColor3B(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorFontColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorFontColor32'", nullptr); return 0; } - auto&& ret = cobj->getAnchorFontColor3B(); - color3b_to_luaval(tolua_S, ret); + auto&& ret = cobj->getAnchorFontColor32(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorFontColor3B",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorFontColor32",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorFontColor3B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorFontColor32'.",&tolua_err); #endif return 0; @@ -30534,11 +30405,11 @@ int lua_ax_ui_RichText_setAnchorTextOutline(lua_State* tolua_S) if (argc == 2) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextOutline"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextOutline"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextOutline"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_setAnchorTextOutline'", nullptr); @@ -30551,12 +30422,12 @@ int lua_ax_ui_RichText_setAnchorTextOutline(lua_State* tolua_S) if (argc == 3) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; int arg2; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextOutline"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextOutline"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextOutline"); ok &= luaval_to_int32(tolua_S, 4,(int *)&arg2, "axui.RichText:setAnchorTextOutline"); if(!ok) @@ -30625,7 +30496,7 @@ int lua_ax_ui_RichText_isAnchorTextOutlineEnabled(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_getAnchorTextOutlineColor3B(lua_State* tolua_S) +int lua_ax_ui_RichText_getAnchorTextOutlineColor32(lua_State* tolua_S) { int argc = 0; ax::ui::RichText* cobj = nullptr; @@ -30645,7 +30516,7 @@ int lua_ax_ui_RichText_getAnchorTextOutlineColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor32'", nullptr); return 0; } #endif @@ -30655,19 +30526,19 @@ int lua_ax_ui_RichText_getAnchorTextOutlineColor3B(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor32'", nullptr); return 0; } - auto&& ret = cobj->getAnchorTextOutlineColor3B(); - color3b_to_luaval(tolua_S, ret); + auto&& ret = cobj->getAnchorTextOutlineColor32(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextOutlineColor3B",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextOutlineColor32",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor3B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextOutlineColor32'.",&tolua_err); #endif return 0; @@ -30762,11 +30633,11 @@ int lua_ax_ui_RichText_setAnchorTextShadow(lua_State* tolua_S) if (argc == 2) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextShadow"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_setAnchorTextShadow'", nullptr); @@ -30779,12 +30650,12 @@ int lua_ax_ui_RichText_setAnchorTextShadow(lua_State* tolua_S) if (argc == 3) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; ax::Vec2 arg2; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextShadow"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); ok &= luaval_to_vec2(tolua_S, 4, &arg2, "axui.RichText:setAnchorTextShadow"); if(!ok) @@ -30799,13 +30670,13 @@ int lua_ax_ui_RichText_setAnchorTextShadow(lua_State* tolua_S) if (argc == 4) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; ax::Vec2 arg2; int arg3; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextShadow"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextShadow"); ok &= luaval_to_vec2(tolua_S, 4, &arg2, "axui.RichText:setAnchorTextShadow"); @@ -30876,7 +30747,7 @@ int lua_ax_ui_RichText_isAnchorTextShadowEnabled(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_getAnchorTextShadowColor3B(lua_State* tolua_S) +int lua_ax_ui_RichText_getAnchorTextShadowColor32(lua_State* tolua_S) { int argc = 0; ax::ui::RichText* cobj = nullptr; @@ -30896,7 +30767,7 @@ int lua_ax_ui_RichText_getAnchorTextShadowColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextShadowColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextShadowColor32'", nullptr); return 0; } #endif @@ -30906,19 +30777,19 @@ int lua_ax_ui_RichText_getAnchorTextShadowColor3B(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextShadowColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextShadowColor32'", nullptr); return 0; } - auto&& ret = cobj->getAnchorTextShadowColor3B(); - color3b_to_luaval(tolua_S, ret); + auto&& ret = cobj->getAnchorTextShadowColor32(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextShadowColor3B",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextShadowColor32",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextShadowColor3B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextShadowColor32'.",&tolua_err); #endif return 0; @@ -31060,11 +30931,11 @@ int lua_ax_ui_RichText_setAnchorTextGlow(lua_State* tolua_S) if (argc == 2) { bool arg0; - ax::Color3B arg1; + ax::Color32 arg1; ok &= luaval_to_boolean(tolua_S, 2,&arg0, "axui.RichText:setAnchorTextGlow"); - ok &= luaval_to_color3b(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextGlow"); + ok &=luaval_to_color32(tolua_S, 3, &arg1, "axui.RichText:setAnchorTextGlow"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_setAnchorTextGlow'", nullptr); @@ -31131,7 +31002,7 @@ int lua_ax_ui_RichText_isAnchorTextGlowEnabled(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_getAnchorTextGlowColor3B(lua_State* tolua_S) +int lua_ax_ui_RichText_getAnchorTextGlowColor32(lua_State* tolua_S) { int argc = 0; ax::ui::RichText* cobj = nullptr; @@ -31151,7 +31022,7 @@ int lua_ax_ui_RichText_getAnchorTextGlowColor3B(lua_State* tolua_S) #if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextGlowColor3B'", nullptr); + tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_getAnchorTextGlowColor32'", nullptr); return 0; } #endif @@ -31161,19 +31032,19 @@ int lua_ax_ui_RichText_getAnchorTextGlowColor3B(lua_State* tolua_S) { if(!ok) { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextGlowColor3B'", nullptr); + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_getAnchorTextGlowColor32'", nullptr); return 0; } - auto&& ret = cobj->getAnchorTextGlowColor3B(); - color3b_to_luaval(tolua_S, ret); + auto&& ret = cobj->getAnchorTextGlowColor32(); + color32_to_luaval(tolua_S, ret); return 1; } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextGlowColor3B",argc, 0); + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:getAnchorTextGlowColor32",argc, 0); return 0; #if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextGlowColor3B'.",&tolua_err); + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_getAnchorTextGlowColor32'.",&tolua_err); #endif return 0; @@ -31275,156 +31146,6 @@ int lua_ax_ui_RichText_getDefaults(lua_State* tolua_S) return 0; } -int lua_ax_ui_RichText_color3BWithString(lua_State* tolua_S) -{ - int argc = 0; - ax::ui::RichText* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axui.RichText",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::ui::RichText*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_color3BWithString'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - std::string_view arg0; - - ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axui.RichText:color3BWithString"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_color3BWithString'", nullptr); - return 0; - } - auto&& ret = cobj->color3BWithString(arg0); - color3b_to_luaval(tolua_S, ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:color3BWithString",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_color3BWithString'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_ui_RichText_stringWithColor3B(lua_State* tolua_S) -{ - int argc = 0; - ax::ui::RichText* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axui.RichText",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::ui::RichText*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_stringWithColor3B'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Color3B arg0; - - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.RichText:stringWithColor3B"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_stringWithColor3B'", nullptr); - return 0; - } - auto&& ret = cobj->stringWithColor3B(arg0); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:stringWithColor3B",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_stringWithColor3B'.",&tolua_err); -#endif - - return 0; -} -int lua_ax_ui_RichText_stringWithColor4B(lua_State* tolua_S) -{ - int argc = 0; - ax::ui::RichText* cobj = nullptr; - bool ok = true; - -#if _AX_DEBUG >= 1 - tolua_Error tolua_err; -#endif - - -#if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S,1,"axui.RichText",0,&tolua_err)) goto tolua_lerror; -#endif - - cobj = (ax::ui::RichText*)tolua_tousertype(tolua_S,1,0); - -#if _AX_DEBUG >= 1 - if (!cobj) - { - tolua_error(tolua_S,"invalid 'cobj' in function 'lua_ax_ui_RichText_stringWithColor4B'", nullptr); - return 0; - } -#endif - - argc = lua_gettop(tolua_S)-1; - if (argc == 1) - { - ax::Color4B arg0; - - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.RichText:stringWithColor4B"); - if(!ok) - { - tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_stringWithColor4B'", nullptr); - return 0; - } - auto&& ret = cobj->stringWithColor4B(arg0); - lua_pushlstring(tolua_S,ret.c_str(),ret.length()); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.RichText:stringWithColor4B",argc, 1); - return 0; - -#if _AX_DEBUG >= 1 - tolua_lerror: - tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_stringWithColor4B'.",&tolua_err); -#endif - - return 0; -} int lua_ax_ui_RichText_openUrl(lua_State* tolua_S) { int argc = 0; @@ -31695,6 +31416,78 @@ int lua_ax_ui_RichText_createWithXML(lua_State* tolua_S) #endif return 0; } +int lua_ax_ui_RichText_parseColor32(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"axui.RichText",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 1) + { + std::string_view arg0; + ok &= luaval_to_std_string_view(tolua_S, 2,&arg0, "axui.RichText:parseColor32"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_parseColor32'", nullptr); + return 0; + } + auto&& ret = ax::ui::RichText::parseColor32(arg0); + color32_to_luaval(tolua_S, ret); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichText:parseColor32",argc, 1); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_parseColor32'.",&tolua_err); +#endif + return 0; +} +int lua_ax_ui_RichText_formatColor32(lua_State* tolua_S) +{ + int argc = 0; + bool ok = true; + +#if _AX_DEBUG >= 1 + tolua_Error tolua_err; +#endif + +#if _AX_DEBUG >= 1 + if (!tolua_isusertable(tolua_S,1,"axui.RichText",0,&tolua_err)) goto tolua_lerror; +#endif + + argc = lua_gettop(tolua_S) - 1; + + if (argc == 1) + { + ax::Color32 arg0; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.RichText:formatColor32"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_RichText_formatColor32'", nullptr); + return 0; + } + auto&& ret = ax::ui::RichText::formatColor32(arg0); + lua_pushlstring(tolua_S,ret.c_str(),ret.length()); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "axui.RichText:formatColor32",argc, 1); + return 0; +#if _AX_DEBUG >= 1 + tolua_lerror: + tolua_error(tolua_S,"#ferror in function 'lua_ax_ui_RichText_formatColor32'.",&tolua_err); +#endif + return 0; +} int lua_ax_ui_RichText_constructor(lua_State* tolua_S) { int argc = 0; @@ -31758,14 +31551,14 @@ int lua_register_ax_ui_RichText(lua_State* tolua_S) tolua_function(tolua_S,"getVerticalAlignment",lua_ax_ui_RichText_getVerticalAlignment); tolua_function(tolua_S,"setFontColor",lua_ax_ui_RichText_setFontColor); tolua_function(tolua_S,"getFontColor",lua_ax_ui_RichText_getFontColor); - tolua_function(tolua_S,"getFontColor3B",lua_ax_ui_RichText_getFontColor3B); + tolua_function(tolua_S,"getFontColor32",lua_ax_ui_RichText_getFontColor32); tolua_function(tolua_S,"setFontSize",lua_ax_ui_RichText_setFontSize); tolua_function(tolua_S,"getFontSize",lua_ax_ui_RichText_getFontSize); tolua_function(tolua_S,"setFontFace",lua_ax_ui_RichText_setFontFace); tolua_function(tolua_S,"getFontFace",lua_ax_ui_RichText_getFontFace); tolua_function(tolua_S,"setAnchorFontColor",lua_ax_ui_RichText_setAnchorFontColor); tolua_function(tolua_S,"getAnchorFontColor",lua_ax_ui_RichText_getAnchorFontColor); - tolua_function(tolua_S,"getAnchorFontColor3B",lua_ax_ui_RichText_getAnchorFontColor3B); + tolua_function(tolua_S,"getAnchorFontColor32",lua_ax_ui_RichText_getAnchorFontColor32); tolua_function(tolua_S,"setAnchorTextBold",lua_ax_ui_RichText_setAnchorTextBold); tolua_function(tolua_S,"isAnchorTextBoldEnabled",lua_ax_ui_RichText_isAnchorTextBoldEnabled); tolua_function(tolua_S,"setAnchorTextItalic",lua_ax_ui_RichText_setAnchorTextItalic); @@ -31776,26 +31569,25 @@ int lua_register_ax_ui_RichText(lua_State* tolua_S) tolua_function(tolua_S,"isAnchorTextUnderlineEnabled",lua_ax_ui_RichText_isAnchorTextUnderlineEnabled); tolua_function(tolua_S,"setAnchorTextOutline",lua_ax_ui_RichText_setAnchorTextOutline); tolua_function(tolua_S,"isAnchorTextOutlineEnabled",lua_ax_ui_RichText_isAnchorTextOutlineEnabled); - tolua_function(tolua_S,"getAnchorTextOutlineColor3B",lua_ax_ui_RichText_getAnchorTextOutlineColor3B); + tolua_function(tolua_S,"getAnchorTextOutlineColor32",lua_ax_ui_RichText_getAnchorTextOutlineColor32); tolua_function(tolua_S,"getAnchorTextOutlineSize",lua_ax_ui_RichText_getAnchorTextOutlineSize); tolua_function(tolua_S,"setAnchorTextShadow",lua_ax_ui_RichText_setAnchorTextShadow); tolua_function(tolua_S,"isAnchorTextShadowEnabled",lua_ax_ui_RichText_isAnchorTextShadowEnabled); - tolua_function(tolua_S,"getAnchorTextShadowColor3B",lua_ax_ui_RichText_getAnchorTextShadowColor3B); + tolua_function(tolua_S,"getAnchorTextShadowColor32",lua_ax_ui_RichText_getAnchorTextShadowColor32); tolua_function(tolua_S,"getAnchorTextShadowOffset",lua_ax_ui_RichText_getAnchorTextShadowOffset); tolua_function(tolua_S,"getAnchorTextShadowBlurRadius",lua_ax_ui_RichText_getAnchorTextShadowBlurRadius); tolua_function(tolua_S,"setAnchorTextGlow",lua_ax_ui_RichText_setAnchorTextGlow); tolua_function(tolua_S,"isAnchorTextGlowEnabled",lua_ax_ui_RichText_isAnchorTextGlowEnabled); - tolua_function(tolua_S,"getAnchorTextGlowColor3B",lua_ax_ui_RichText_getAnchorTextGlowColor3B); + tolua_function(tolua_S,"getAnchorTextGlowColor32",lua_ax_ui_RichText_getAnchorTextGlowColor32); tolua_function(tolua_S,"setDefaults",lua_ax_ui_RichText_setDefaults); tolua_function(tolua_S,"getDefaults",lua_ax_ui_RichText_getDefaults); - tolua_function(tolua_S,"color3BWithString",lua_ax_ui_RichText_color3BWithString); - tolua_function(tolua_S,"stringWithColor3B",lua_ax_ui_RichText_stringWithColor3B); - tolua_function(tolua_S,"stringWithColor4B",lua_ax_ui_RichText_stringWithColor4B); tolua_function(tolua_S,"openUrl",lua_ax_ui_RichText_openUrl); tolua_function(tolua_S,"initWithXML",lua_ax_ui_RichText_initWithXML); tolua_function(tolua_S,"setString",lua_ax_ui_RichText_setString); tolua_function(tolua_S,"create", lua_ax_ui_RichText_create); tolua_function(tolua_S,"createWithXML", lua_ax_ui_RichText_createWithXML); + tolua_function(tolua_S,"parseColor32", lua_ax_ui_RichText_parseColor32); + tolua_function(tolua_S,"formatColor32", lua_ax_ui_RichText_formatColor32); tolua_endmodule(tolua_S); auto typeName = typeid(ax::ui::RichText).name(); // rtti is literal storage g_luaType[reinterpret_cast(typeName)] = "axui.RichText"; @@ -35446,14 +35238,18 @@ int lua_ax_ui_EditBox_setFontColor(lua_State* tolua_S) int argc = 0; ax::ui::EditBox* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"axui.EditBox",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::ui::EditBox*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { @@ -35461,32 +35257,23 @@ int lua_ax_ui_EditBox_setFontColor(lua_State* tolua_S) return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.EditBox:setFontColor"); - if (!ok) { break; } - cobj->setFontColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.EditBox:setFontColor"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Color32 arg0; - if (!ok) { break; } - cobj->setFontColor(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.EditBox:setFontColor"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_EditBox_setFontColor'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:setFontColor",argc, 1); + cobj->setFontColor(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:setFontColor",argc, 1); return 0; #if _AX_DEBUG >= 1 @@ -35530,7 +35317,7 @@ int lua_ax_ui_EditBox_getFontColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getFontColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:getFontColor",argc, 0); @@ -35795,14 +35582,18 @@ int lua_ax_ui_EditBox_setPlaceholderFontColor(lua_State* tolua_S) int argc = 0; ax::ui::EditBox* cobj = nullptr; bool ok = true; + #if _AX_DEBUG >= 1 tolua_Error tolua_err; #endif + #if _AX_DEBUG >= 1 if (!tolua_isusertype(tolua_S,1,"axui.EditBox",0,&tolua_err)) goto tolua_lerror; #endif + cobj = (ax::ui::EditBox*)tolua_tousertype(tolua_S,1,0); + #if _AX_DEBUG >= 1 if (!cobj) { @@ -35810,32 +35601,23 @@ int lua_ax_ui_EditBox_setPlaceholderFontColor(lua_State* tolua_S) return 0; } #endif - argc = lua_gettop(tolua_S)-1; - do{ - if (argc == 1) { - ax::Color4B arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.EditBox:setPlaceholderFontColor"); - if (!ok) { break; } - cobj->setPlaceholderFontColor(arg0); - lua_settop(tolua_S, 1); - return 1; - } - }while(0); - ok = true; - do{ - if (argc == 1) { - ax::Color3B arg0; - ok &= luaval_to_color3b(tolua_S, 2, &arg0, "axui.EditBox:setPlaceholderFontColor"); + argc = lua_gettop(tolua_S)-1; + if (argc == 1) + { + ax::Color32 arg0; - if (!ok) { break; } - cobj->setPlaceholderFontColor(arg0); - lua_settop(tolua_S, 1); - return 1; + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.EditBox:setPlaceholderFontColor"); + if(!ok) + { + tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_EditBox_setPlaceholderFontColor'", nullptr); + return 0; } - }while(0); - ok = true; - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:setPlaceholderFontColor",argc, 1); + cobj->setPlaceholderFontColor(arg0); + lua_settop(tolua_S, 1); + return 1; + } + luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:setPlaceholderFontColor",argc, 1); return 0; #if _AX_DEBUG >= 1 @@ -35879,7 +35661,7 @@ int lua_ax_ui_EditBox_getPlaceholderFontColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getPlaceholderFontColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.EditBox:getPlaceholderFontColor",argc, 0); @@ -39788,9 +39570,9 @@ int lua_ax_ui_TabHeader_setTitleColor(lua_State* tolua_S) argc = lua_gettop(tolua_S)-1; if (argc == 1) { - ax::Color4B arg0; + ax::Color32 arg0; - ok &=luaval_to_color4b(tolua_S, 2, &arg0, "axui.TabHeader:setTitleColor"); + ok &=luaval_to_color32(tolua_S, 2, &arg0, "axui.TabHeader:setTitleColor"); if(!ok) { tolua_error(tolua_S,"invalid arguments in function 'lua_ax_ui_TabHeader_setTitleColor'", nullptr); @@ -39844,7 +39626,7 @@ int lua_ax_ui_TabHeader_getTitleColor(lua_State* tolua_S) return 0; } auto&& ret = cobj->getTitleColor(); - color4b_to_luaval(tolua_S, ret); + color32_to_luaval(tolua_S, ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d \n", "axui.TabHeader:getTitleColor",argc, 0); diff --git a/extensions/scripting/lua-bindings/auto/axlua_ui_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_ui_auto.hpp index 6ffeb6bee047..b99ed2f7cf83 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_ui_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_ui_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_ui(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/auto/axlua_video_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_video_auto.cpp index 07a8a8ae9b12..54b3933e0e16 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_video_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_video_auto.cpp @@ -1,6 +1,6 @@ #include "lua-bindings/auto/axlua_video_auto.hpp" #if defined(AX_ENABLE_MEDIA) -#include "ui/UIMediaPlayer.h" +#include "axmol/ui/UIMediaPlayer.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_video_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_video_auto.hpp index 603014717c47..ac80359a559e 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_video_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_video_auto.hpp @@ -1,6 +1,6 @@ #pragma once #if defined(AX_ENABLE_MEDIA) -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_video(lua_State* tolua_S); #endif //#if defined(AX_ENABLE_MEDIA) diff --git a/extensions/scripting/lua-bindings/auto/axlua_webview_auto.cpp b/extensions/scripting/lua-bindings/auto/axlua_webview_auto.cpp index 4199da4fc185..46ab396fbce6 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_webview_auto.cpp +++ b/extensions/scripting/lua-bindings/auto/axlua_webview_auto.cpp @@ -1,5 +1,5 @@ #include "lua-bindings/auto/axlua_webview_auto.hpp" -#include "ui/UIWebView/UIWebView.h" +#include "axmol/ui/UIWebView/UIWebView.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" diff --git a/extensions/scripting/lua-bindings/auto/axlua_webview_auto.hpp b/extensions/scripting/lua-bindings/auto/axlua_webview_auto.hpp index bcb92f829706..5290f5453a8c 100644 --- a/extensions/scripting/lua-bindings/auto/axlua_webview_auto.hpp +++ b/extensions/scripting/lua-bindings/auto/axlua_webview_auto.hpp @@ -1,4 +1,4 @@ #pragma once -#include "base/Config.h" +#include "axmol/base/Config.h" #include "tolua++.h" int register_all_ax_webview(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/manual/3d/axlua_3d_manual.cpp b/extensions/scripting/lua-bindings/manual/3d/axlua_3d_manual.cpp index 2baf6db3c79b..d207dc20199a 100644 --- a/extensions/scripting/lua-bindings/manual/3d/axlua_3d_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/3d/axlua_3d_manual.cpp @@ -26,9 +26,9 @@ #include "lua-bindings/auto/axlua_3d_auto.hpp" #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/LuaEngine.h" -#include "3d/Bundle3D.h" -#include "3d/MeshRenderer.h" -#include "3d/Terrain.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Terrain.h" int axlua_3d_MeshRenderer_getAABB(lua_State* L) { diff --git a/extensions/scripting/lua-bindings/manual/AxluaLoader.cpp b/extensions/scripting/lua-bindings/manual/AxluaLoader.cpp index a6665ba5492d..cfa25a617e19 100644 --- a/extensions/scripting/lua-bindings/manual/AxluaLoader.cpp +++ b/extensions/scripting/lua-bindings/manual/AxluaLoader.cpp @@ -30,7 +30,7 @@ THE SOFTWARE. #include "lua-bindings/manual/LuaStack.h" #include "lua-bindings/manual/LuaEngine.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" #include "yasio/string_view.hpp" using namespace ax; diff --git a/extensions/scripting/lua-bindings/manual/ComponentLua.cpp b/extensions/scripting/lua-bindings/manual/ComponentLua.cpp index 5cd5ea05534f..941360a2c220 100644 --- a/extensions/scripting/lua-bindings/manual/ComponentLua.cpp +++ b/extensions/scripting/lua-bindings/manual/ComponentLua.cpp @@ -25,11 +25,11 @@ #include "ComponentLua.h" #include -#include "base/ScriptSupport.h" -#include "platform/FileUtils.h" +#include "axmol/base/ScriptSupport.h" +#include "axmol/platform/FileUtils.h" #include "lua-bindings/manual/LuaEngine.h" #include "lua-bindings/manual/LuaBasicConversions.h" -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" namespace ax { @@ -226,7 +226,7 @@ void ComponentLua::storeLuaTable() lua_State* l = LuaEngine::getInstance()->getLuaStack()->getLuaState(); _index++; - _strIndex.append(StringUtils::toString(_index)); + _strIndex.append(text_utils::toString(_index)); // LUA_REGISTRYINDEX["component"][strIndex] = table return from lua lua_pushstring(l, KEY_COMPONENT); // stack: table_return_from_lua "component" diff --git a/extensions/scripting/lua-bindings/manual/ComponentLua.h b/extensions/scripting/lua-bindings/manual/ComponentLua.h index 0875d68a01d8..df316ca75eae 100644 --- a/extensions/scripting/lua-bindings/manual/ComponentLua.h +++ b/extensions/scripting/lua-bindings/manual/ComponentLua.h @@ -27,7 +27,7 @@ #include #include -#include "2d/Component.h" +#include "axmol/2d/Component.h" namespace ax { diff --git a/extensions/scripting/lua-bindings/manual/LuaBasicConversions.cpp b/extensions/scripting/lua-bindings/manual/LuaBasicConversions.cpp index da8e20c40bb0..e5ad20db22b8 100644 --- a/extensions/scripting/lua-bindings/manual/LuaBasicConversions.cpp +++ b/extensions/scripting/lua-bindings/manual/LuaBasicConversions.cpp @@ -26,7 +26,7 @@ #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/tolua_fix.h" -#include "base/Utils.h" +#include "axmol/base/Utils.h" #include std::unordered_map g_luaType; @@ -491,7 +491,7 @@ bool luaval_to_blendfunc(lua_State* L, int lo, ax::BlendFunc* outValue, const ch lua_gettable(L, lo); if (!lua_isnil(L, -1)) { - outValue->src = static_cast(lua_tointeger(L, -1)); + outValue->src = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); @@ -499,7 +499,7 @@ bool luaval_to_blendfunc(lua_State* L, int lo, ax::BlendFunc* outValue, const ch lua_gettable(L, lo); if (!lua_isnil(L, -1)) { - outValue->dst = static_cast(lua_tointeger(L, -1)); + outValue->dst = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); } @@ -666,7 +666,7 @@ bool luaval_to_rect(lua_State* L, int lo, Rect* outValue, const char* funcName) return ok; } -bool luaval_to_color4b(lua_State* L, int lo, Color4B* outValue, const char* funcName) +bool luaval_to_color32(lua_State* L, int lo, Color32* outValue, const char* funcName) { if (NULL == L || NULL == outValue) return false; @@ -708,7 +708,7 @@ bool luaval_to_color4b(lua_State* L, int lo, Color4B* outValue, const char* func return ok; } -bool luaval_to_color4f(lua_State* L, int lo, Color4F* outValue, const char* funcName) +bool luaval_to_color(lua_State* L, int lo, ax::Color* outValue, const char* funcName) { if (NULL == L || NULL == outValue) return false; @@ -750,43 +750,6 @@ bool luaval_to_color4f(lua_State* L, int lo, Color4F* outValue, const char* func return ok; } -bool luaval_to_color3b(lua_State* L, int lo, Color3B* outValue, const char* funcName) -{ - if (NULL == L || NULL == outValue) - return false; - - bool ok = true; - - tolua_Error tolua_err; - if (!tolua_istable(L, lo, 0, &tolua_err)) - { -#if _AX_DEBUG >= 1 - luaval_to_native_err(L, "#ferror:", &tolua_err, funcName); -#endif - ok = false; - } - - if (ok) - { - lua_pushstring(L, "r"); - lua_gettable(L, lo); - outValue->r = lua_isnil(L, -1) ? 0 : static_cast(lua_tonumber(L, -1)); - lua_pop(L, 1); - - lua_pushstring(L, "g"); - lua_gettable(L, lo); - outValue->g = lua_isnil(L, -1) ? 0 : static_cast(lua_tonumber(L, -1)); - lua_pop(L, 1); - - lua_pushstring(L, "b"); - lua_gettable(L, lo); - outValue->b = lua_isnil(L, -1) ? 0 : static_cast(lua_tonumber(L, -1)); - lua_pop(L, 1); - } - - return ok; -} - bool luaval_to_affinetransform(lua_State* L, int lo, AffineTransform* outValue, const char* funcName) { if (NULL == L || NULL == outValue) @@ -896,7 +859,7 @@ bool luaval_to_fontdefinition(lua_State* L, int lo, FontDefinition* outValue, co outValue->_stroke._strokeEnabled = false; // white text by default - outValue->_fontFillColor = Color3B::WHITE; + outValue->_fontFillColor = Color32::WHITE; lua_pushstring(L, "fontName"); lua_gettable(L, lo); @@ -922,7 +885,7 @@ bool luaval_to_fontdefinition(lua_State* L, int lo, FontDefinition* outValue, co lua_gettable(L, lo); if (!lua_isnil(L, -1)) { - luaval_to_color3b(L, lua_gettop(L), &outValue->_fontFillColor); + luaval_to_color32(L, lua_gettop(L), &outValue->_fontFillColor); } lua_pop(L, 1); @@ -982,13 +945,13 @@ bool luaval_to_fontdefinition(lua_State* L, int lo, FontDefinition* outValue, co { // default stroke values outValue->_stroke._strokeSize = 1; - outValue->_stroke._strokeColor = Color3B::BLUE; + outValue->_stroke._strokeColor = Color32::BLUE; lua_pushstring(L, "strokeColor"); lua_gettable(L, lo); if (!lua_isnil(L, -1)) { - luaval_to_color3b(L, lua_gettop(L), &outValue->_stroke._strokeColor); + luaval_to_color32(L, lua_gettop(L), &outValue->_stroke._strokeColor); } lua_pop(L, 1); @@ -1682,7 +1645,7 @@ bool luaval_to_mesh_vertex_attrib(lua_State* L, int lo, ax::MeshVertexAttrib* re lua_pushstring(L, "type"); /* L: paramStack key */ lua_gettable(L, lo); /* L: paramStack paramStack[lo][key] */ - ret->type = (backend::VertexFormat)(int)lua_tonumber(L, -1); + ret->type = (rhi::VertexFormat)(int)lua_tonumber(L, -1); lua_pop(L, 1); lua_pushstring(L, "vertexAttrib"); /* L: paramStack key */ @@ -1833,22 +1796,22 @@ bool luaval_to_texparams(lua_State* L, int lo, ax::Texture2D::TexParams* outValu { lua_pushstring(L, "minFilter"); lua_gettable(L, lo); - outValue->minFilter = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); + outValue->minFilter = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); lua_pop(L, 1); lua_pushstring(L, "magFilter"); lua_gettable(L, lo); - outValue->magFilter = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); + outValue->magFilter = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); lua_pop(L, 1); lua_pushstring(L, "wrapS"); lua_gettable(L, lo); - outValue->sAddressMode = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); + outValue->sAddressMode = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); lua_pop(L, 1); lua_pushstring(L, "wrapT"); lua_gettable(L, lo); - outValue->tAddressMode = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); + outValue->tAddressMode = static_cast(lua_isnil(L, -1) ? 0 : lua_tointeger(L, -1)); lua_pop(L, 1); } return ok; @@ -1885,7 +1848,7 @@ bool luaval_to_tex2f(lua_State* L, int lo, ax::Tex2F* outValue, const char* func return ok; } -bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, const char* funcName) +bool luaval_to_v3f_c4f_t2f(lua_State* L, int lo, ax::V3F_T2F_C4F* outValue, const char* funcName) { if (nullptr == L || nullptr == outValue) return false; @@ -1903,7 +1866,7 @@ bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, cons if (ok) { - lua_pushstring(L, "vertices"); + lua_pushstring(L, "position"); lua_gettable(L, lo); if (!tolua_istable(L, lua_gettop(L), 0, &tolua_err)) { @@ -1911,7 +1874,7 @@ bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, cons return false; } - ok &= luaval_to_vec3(L, lua_gettop(L), &outValue->vertices); + ok &= luaval_to_vec3(L, lua_gettop(L), &outValue->position); if (!ok) { lua_pop(L, 1); @@ -1919,14 +1882,14 @@ bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, cons } lua_pop(L, 1); - lua_pushstring(L, "colors"); + lua_pushstring(L, "color"); lua_gettable(L, lo); if (!tolua_istable(L, lua_gettop(L), 0, &tolua_err)) { lua_pop(L, 1); return false; } - ok &= luaval_to_color4b(L, lua_gettop(L), &outValue->colors); + ok &= luaval_to_color(L, lua_gettop(L), &outValue->color); if (!ok) { lua_pop(L, 1); @@ -1934,14 +1897,14 @@ bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, cons } lua_pop(L, 1); - lua_pushstring(L, "texCoords"); + lua_pushstring(L, "texCoord"); lua_gettable(L, lo); if (!tolua_istable(L, lua_gettop(L), 0, &tolua_err)) { lua_pop(L, 1); return false; } - ok &= luaval_to_tex2f(L, lua_gettop(L), &outValue->texCoords); + ok &= luaval_to_tex2f(L, lua_gettop(L), &outValue->texCoord); if (!ok) { lua_pop(L, 1); @@ -2040,7 +2003,7 @@ bool luaval_to_std_vector_vec3(lua_State* L, int lo, std::vector* ret, bool luaval_to_std_vector_v3f_c4b_t2f(lua_State* L, int lo, - std::vector* ret, + std::vector* ret, const char* funcName) { if (nullptr == L || nullptr == ret || lua_gettop(L) < lo) @@ -2060,14 +2023,14 @@ bool luaval_to_std_vector_v3f_c4b_t2f(lua_State* L, if (ok) { size_t len = lua_objlen(L, lo); - ax::V3F_C4B_T2F value; + ax::V3F_T2F_C4F value; for (size_t i = 0; i < len; i++) { lua_pushnumber(L, i + 1); lua_gettable(L, lo); if (lua_istable(L, lua_gettop(L))) { - ok &= luaval_to_v3f_c4b_t2f(L, lua_gettop(L), &value); + ok &= luaval_to_v3f_c4f_t2f(L, lua_gettop(L), &value); if (ok) { ret->emplace_back(value); @@ -2075,7 +2038,7 @@ bool luaval_to_std_vector_v3f_c4b_t2f(lua_State* L, } else { - AXASSERT(false, "V3F_C4B_T2F type is needed"); + AXASSERT(false, "V3F_T2F_C4F type is needed"); } lua_pop(L, 1); } @@ -2280,7 +2243,7 @@ void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info) lua_newtable(L); /* L: table */ lua_pushstring(L, "shape"); /* L: table key */ - PhysicsShape* shape = info.shape; + PhysicsCollider* shape = info.shape; if (shape == nullptr) { lua_pushnil(L); @@ -2289,7 +2252,7 @@ void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info) { int ID = (int)(shape->_ID); int* luaID = &(shape->_luaID); - toluafix_pushusertype_object(L, ID, luaID, (void*)shape, "ax.PhysicsShape"); + toluafix_pushusertype_object(L, ID, luaID, (void*)shape, "ax.PhysicsCollider"); } lua_rawset(L, -3); /* table[key] = value, L: table */ @@ -2367,7 +2330,7 @@ void rect_to_luaval(lua_State* L, const Rect& rt) lua_rawset(L, -3); /* table[key] = value, L: table */ } -void color4b_to_luaval(lua_State* L, const Color4B& color) +void color32_to_luaval(lua_State* L, const Color32& color) { if (NULL == L) return; @@ -2386,7 +2349,7 @@ void color4b_to_luaval(lua_State* L, const Color4B& color) lua_rawset(L, -3); /* table[key] = value, L: table */ } -void color4f_to_luaval(lua_State* L, const Color4F& color) +void color_to_luaval(lua_State* L, const ax::Color& color) { if (NULL == L) return; @@ -2410,22 +2373,6 @@ void std_thread_id_to_luaval(lua_State* L, const std::thread::id& value) { lua_pushinteger(L, threadHash); } -void color3b_to_luaval(lua_State* L, const Color3B& color) -{ - if (NULL == L) - return; - lua_newtable(L); /* L: table */ - lua_pushstring(L, "r"); /* L: table key */ - lua_pushnumber(L, (lua_Number)color.r); /* L: table key value*/ - lua_rawset(L, -3); /* table[key] = value, L: table */ - lua_pushstring(L, "g"); /* L: table key */ - lua_pushnumber(L, (lua_Number)color.g); /* L: table key value*/ - lua_rawset(L, -3); /* table[key] = value, L: table */ - lua_pushstring(L, "b"); /* L: table key */ - lua_pushnumber(L, (lua_Number)color.b); /* L: table key value*/ - lua_rawset(L, -3); /* table[key] = value, L: table */ -} - void affinetransform_to_luaval(lua_State* L, const AffineTransform& inValue) { if (NULL == L) @@ -2471,7 +2418,7 @@ void fontdefinition_to_luaval(lua_State* L, const FontDefinition& inValue) lua_pushnumber(L, (lua_Number)inValue._vertAlignment); /* L: table key value*/ lua_rawset(L, -3); /* table[key] = value, L: table */ lua_pushstring(L, "fontFillColor"); /* L: table key */ - color3b_to_luaval(L, inValue._fontFillColor); /* L: table key value*/ + color32_to_luaval(L, inValue._fontFillColor); /* L: table key value*/ lua_rawset(L, -3); /* table[key] = value, L: table */ lua_pushstring(L, "fontDimensions"); /* L: table key */ size_to_luaval(L, inValue._dimensions); /* L: table key value*/ @@ -2500,7 +2447,7 @@ void fontdefinition_to_luaval(lua_State* L, const FontDefinition& inValue) lua_rawset(L, -3); /* table[key] = value, L: table */ lua_pushstring(L, "strokeColor"); /* L: table key */ - color3b_to_luaval(L, inValue._stroke._strokeColor); /* L: table key value*/ + color32_to_luaval(L, inValue._stroke._strokeColor); /* L: table key value*/ lua_rawset(L, -3); /* table[key] = value, L: table */ lua_pushstring(L, "strokeSize"); /* L: table key */ @@ -3031,13 +2978,13 @@ void node_to_luaval(lua_State* L, const char* type, ax::Node* node) object_to_luaval(L, type, node); } -bool luaval_to_vertexLayout(lua_State* L, int pos, ax::backend::VertexLayout& outLayout, const char* message) +bool luaval_to_vertexLayout(lua_State* L, int pos, ax::rhi::VertexLayout& outLayout, const char* message) { if (L == nullptr) return false; - ax::backend::VertexLayout* tmp = nullptr; - auto ret = luaval_to_object(L, pos, "ax.VertexLayout", &tmp, message); + ax::rhi::VertexLayout* tmp = nullptr; + auto ret = luaval_to_object(L, pos, "ax.VertexLayout", &tmp, message); if (!tmp) { return false; @@ -3046,9 +2993,9 @@ bool luaval_to_vertexLayout(lua_State* L, int pos, ax::backend::VertexLayout& ou return ret; } -bool luaval_to_samplerDescriptor(lua_State* L, +bool luaval_to_samplerDesc(lua_State* L, int pos, - ax::backend::SamplerDescriptor& output, + ax::rhi::SamplerDesc& output, const char* message) { if (L == nullptr) @@ -3058,7 +3005,7 @@ bool luaval_to_samplerDescriptor(lua_State* L, lua_gettable(L, pos); if (!lua_isnil(L, -1)) { - output.magFilter = static_cast(lua_tointeger(L, -1)); + output.magFilter = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); @@ -3066,7 +3013,7 @@ bool luaval_to_samplerDescriptor(lua_State* L, lua_gettable(L, pos); if (!lua_isnil(L, -1)) { - output.minFilter = static_cast(lua_tointeger(L, -1)); + output.minFilter = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); @@ -3074,7 +3021,7 @@ bool luaval_to_samplerDescriptor(lua_State* L, lua_gettable(L, pos); if (!lua_isnil(L, -1)) { - output.sAddressMode = static_cast(lua_tointeger(L, -1)); + output.sAddressMode = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); @@ -3082,14 +3029,14 @@ bool luaval_to_samplerDescriptor(lua_State* L, lua_gettable(L, pos); if (!lua_isnil(L, -1)) { - output.tAddressMode = static_cast(lua_tointeger(L, -1)); + output.tAddressMode = static_cast(lua_tointeger(L, -1)); } lua_pop(L, 1); return true; } -bool luaval_to_stageUniformLocation(lua_State* L, int pos, ax::backend::StageUniformLocation& loc, const char* message) +bool luaval_to_stageUniformLocation(lua_State* L, int pos, ax::rhi::StageUniformLocation& loc, const char* message) { if (L == nullptr) return false; @@ -3118,7 +3065,7 @@ bool luaval_to_stageUniformLocation(lua_State* L, int pos, ax::backend::StageUni return true; } -void stageUniformLocation_to_luaval(lua_State* L, const ax::backend::StageUniformLocation& loc) +void stageUniformLocation_to_luaval(lua_State* L, const ax::rhi::StageUniformLocation& loc) { if (L == nullptr) return; @@ -3134,7 +3081,7 @@ void stageUniformLocation_to_luaval(lua_State* L, const ax::backend::StageUnifor lua_rawset(L, -3); } -bool luaval_to_uniformLocation(lua_State* L, int pos, ax::backend::UniformLocation& loc, const char* message) +bool luaval_to_uniformLocation(lua_State* L, int pos, ax::rhi::UniformLocation& loc, const char* message) { if (L == nullptr) return false; @@ -3160,7 +3107,7 @@ bool luaval_to_uniformLocation(lua_State* L, int pos, ax::backend::UniformLocati return true; } -void uniformLocation_to_luaval(lua_State* L, const ax::backend::UniformLocation& loc) +void uniformLocation_to_luaval(lua_State* L, const ax::rhi::UniformLocation& loc) { if (L == nullptr) return; @@ -3176,7 +3123,7 @@ void uniformLocation_to_luaval(lua_State* L, const ax::backend::UniformLocation& lua_rawset(L, -3); } -void program_activeattrs_to_luaval(lua_State* L, const hlookup::string_map& attrs) +void program_activeattrs_to_luaval(lua_State* L, const hlookup::string_map& attrs) { if (L == nullptr) return; @@ -3189,7 +3136,7 @@ void program_activeattrs_to_luaval(lua_State* L, const hlookup::string_map @@ -268,46 +268,32 @@ extern bool luaval_to_size(lua_State* L, int lo, Size* outValue, const char* fun extern bool luaval_to_rect(lua_State* L, int lo, Rect* outValue, const char* funcName = ""); /** - * Get a Color3B object value from the given acceptable index of stack. - * If the value at the given acceptable index of stack is a table it returns true, otherwise returns false. - * If the table has the `r`,`g` and `b` keys and the corresponding values are not nil, this function would assign the - * values to the corresponding members of outValue. Otherwise, the value of members of outValue would be 0. - * - * @param L the current lua_State. - * @param lo the given acceptable index of stack. - * @param outValue the pointer to a Color3B object which stores the values from the Lua table. - * @param funcName the name of calling function, it is used for error output in the debug model. - * @return Return true if the value at the given acceptable index of stack is a table, otherwise return false. - */ -extern AX_LUA_DLL bool luaval_to_color3b(lua_State* L, int lo, Color3B* outValue, const char* funcName = ""); - -/** - * Get a Color4B object value from the given acceptable index of stack. + * Get a Color32 object value from the given acceptable index of stack. * If the value at the given acceptable index of stack is a table it returns true, otherwise returns false. * If the table has the `r`,`g`, `b` and 'a' keys and the corresponding values are not nil, this function would assign * the values to the corresponding members of outValue. Otherwise, the value of members of outValue would be 0. * * @param L the current lua_State. * @param lo the given acceptable index of stack. - * @param outValue the pointer to a Color4B object which stores the values from the Lua table. + * @param outValue the pointer to a Color32 object which stores the values from the Lua table. * @param funcName the name of calling function, it is used for error output in the debug model. * @return Return true if the value at the given acceptable index of stack is a table, otherwise return false. */ -extern bool luaval_to_color4b(lua_State* L, int lo, Color4B* outValue, const char* funcName = ""); +extern bool luaval_to_color32(lua_State* L, int lo, Color32* outValue, const char* funcName = ""); /** - * Get a Color4F object value from the given acceptable index of stack. + * Get a ax::Color object value from the given acceptable index of stack. * If the value at the given acceptable index of stack is a table it returns true, otherwise returns false. * If the table has the `r`,`g`, `b` and 'a' keys and the corresponding values are not nil, this function would assign * the values to the corresponding members of outValue. Otherwise, the value of members of outValue would be 0. * * @param L the current lua_State. * @param lo the given acceptable index of stack. - * @param outValue the pointer to a Color4F object which stores the values from the Lua table. + * @param outValue the pointer to a ax::Color object which stores the values from the Lua table. * @param funcName the name of calling function, it is used for error output in the debug model. * @return Return true if the value at the given acceptable index of stack is a table, otherwise return false. */ -extern bool luaval_to_color4f(lua_State* L, int lo, Color4F* outValue, const char* funcName = ""); +extern bool luaval_to_color(lua_State* L, int lo, ax::Color* outValue, const char* funcName = ""); #if defined(AX_ENABLE_PHYSICS) /** @@ -797,17 +783,17 @@ extern bool luaval_to_quaternion(lua_State* L, int lo, ax::Quaternion* outValue, extern bool luaval_to_texparams(lua_State* L, int lo, ax::Texture2D::TexParams* outValue, const char* funcName = ""); /** - * Get a ax::V3F_C4B_T2F object value from the given acceptable index of stack. + * Get a ax::V3F_T2F_C4F object value from the given acceptable index of stack. * If the value at the given acceptable index of stack is a table it returns true, otherwise returns false. * If the table has the `vertices`, `colors`, and `texCoords` keys and the corresponding values are not nil, this * function would assign the values to the corresponding members of outValue. * @param L the current lua_State. * @param lo the given acceptable index of stack. - * @param outValue the pointer to a ax::V3F_C4B_T2F object which stores the values from the Lua table. + * @param outValue the pointer to a ax::V3F_T2F_C4F object which stores the values from the Lua table. * @param funcName the name of calling function, it is used for error output in the debug model. * @return true if the value at the given acceptable index of stack is a table, otherwise return false. */ -extern bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValue, const char* funcName = ""); +extern bool luaval_to_v3f_c4f_t2f(lua_State* L, int lo, ax::V3F_T2F_C4F* outValue, const char* funcName = ""); /** * Get a ax::Tex2F object value from the given acceptable index of stack. @@ -823,17 +809,17 @@ extern bool luaval_to_v3f_c4b_t2f(lua_State* L, int lo, ax::V3F_C4B_T2F* outValu extern bool luaval_to_tex2f(lua_State* L, int lo, ax::Tex2F* outValue, const char* funcName = ""); /** - * Get a pointer points to a std::vector from a Lua array table in the stack. + * Get a pointer points to a std::vector from a Lua array table in the stack. * * @param L the current lua_State. * @param lo the given acceptable index of stack. - * @param ret a pointer points to a std::vector. + * @param ret a pointer points to a std::vector. * @param funcName the name of calling function, it is used for error output in the debug model. * @return Return true if the value at the given acceptable index of stack is a table, otherwise return false. */ extern bool luaval_to_std_vector_v3f_c4b_t2f(lua_State* L, int lo, - std::vector* ret, + std::vector* ret, const char* funcName = ""); /** @@ -932,31 +918,22 @@ extern void size_to_luaval(lua_State* L, const Size& sz); extern void rect_to_luaval(lua_State* L, const Rect& rt); /** - * Push a table converted from a ax::Color3B object into the Lua stack. - * The format of table as follows: {r=numberValue1, g=numberValue2, b=numberValue3} - * - * @param L the current lua_State. - * @param cc a ax::Color3B object. - */ -extern AX_LUA_DLL void color3b_to_luaval(lua_State* L, const Color3B& cc); - -/** - * Push a table converted from a ax::Color4B object into the Lua stack. + * Push a table converted from a ax::Color32 object into the Lua stack. * The format of table as follows: {r=numberValue1, g=numberValue2, b=numberValue3, a=numberValue4} * * @param L the current lua_State. - * @param cc a ax::Color4B object. + * @param cc a ax::Color32 object. */ -extern void color4b_to_luaval(lua_State* L, const Color4B& cc); +extern void color32_to_luaval(lua_State* L, const Color32& cc); /** - * Push a table converted from a ax::Color4F object into the Lua stack. + * Push a table converted from a ax::Color object into the Lua stack. * The format of table as follows: {r=numberValue1, g=numberValue2, b=numberValue3, a=numberValue4} * * @param L the current lua_State. - * @param cc a ax::Color4F object. + * @param cc a ax::Color object. */ -extern void color4f_to_luaval(lua_State* L, const Color4F& cc); +extern void color_to_luaval(lua_State* L, const ax::Color& cc); void std_thread_id_to_luaval(lua_State* L, const std::thread::id& value); @@ -979,7 +956,7 @@ extern void physics_material_to_luaval(lua_State* L, const PhysicsMaterial& pm); * @param L the current lua_State. * @param info a ax::PhysicsRayCastInfo object. */ -extern void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo& info); +extern void physics_raycastinfo_to_luaval(lua_State* L, const ax::PhysicsRayCastInfo& info); /** * Push a table converted from a ax::PhysicsContactData object into the Lua stack. @@ -988,7 +965,7 @@ extern void physics_raycastinfo_to_luaval(lua_State* L, const PhysicsRayCastInfo * @param L the current lua_State. * @param data a ax::PhysicsContactData object. */ -extern void physics_contactdata_to_luaval(lua_State* L, const PhysicsContactData* data); +extern void physics_contactdata_to_luaval(lua_State* L, const ax::PhysicsContactData* data); #endif // #if defined(AX_ENABLE_PHYSICS) /** @@ -1004,9 +981,9 @@ extern void affinetransform_to_luaval(lua_State* L, const AffineTransform& inVal /** * Push a table converted from a ax::FontDefinition object into the Lua stack. * The format of table as follows: {fontName=stringValue1, fontSize=numberValue1, fontAlignmentH=numberValue2, - * fontAlignmentV=numberValue3,fontFillColor=color3b_table1, fontDimensions=size_table1, shadowEnabled=booleanValue1, + * fontAlignmentV=numberValue3,fontFillColor=color32_table1, fontDimensions=size_table1, shadowEnabled=booleanValue1, * shadowOffset=size_table2, shadowBlur=numberValue4, shadowOpacity=numberValue5, shadowEnabled=booleanValue2, - * strokeColor=color3b_table2, strokeSize=size_table3} + * strokeColor=color32_table2, strokeSize=size_table3} * * @param L the current lua_State. * @param inValue a ax::FontDefinition object. @@ -1329,32 +1306,32 @@ AX_LUA_DLL extern void node_to_luaval(lua_State* L, const char* type, ax::Node* */ AX_LUA_DLL bool luaval_to_vertexLayout(lua_State* L, int pos, - ax::backend::VertexLayout& outLayout, + ax::rhi::VertexLayout& outLayout, const char* message); /** - * convert lua object SamplerDescriptor to native object + * convert lua object SamplerDesc to native object */ -AX_LUA_DLL bool luaval_to_samplerDescriptor(lua_State* L, +AX_LUA_DLL bool luaval_to_samplerDesc(lua_State* L, int pos, - ax::backend::SamplerDescriptor& desc, + ax::rhi::SamplerDesc& desc, const char* message); /** - * convert lua object to ax::backend::UniformLocation + * convert lua object to ax::rhi::UniformLocation */ AX_LUA_DLL bool luaval_to_uniformLocation(lua_State* L, int pos, - ax::backend::UniformLocation& desc, + ax::rhi::UniformLocation& desc, const char* message); /** - * convert ax::backend::UniformLocation to lua object + * convert ax::rhi::UniformLocation to lua object */ -AX_LUA_DLL void uniformLocation_to_luaval(lua_State* L, const ax::backend::UniformLocation& desc); +AX_LUA_DLL void uniformLocation_to_luaval(lua_State* L, const ax::rhi::UniformLocation& desc); AX_LUA_DLL void program_activeattrs_to_luaval(lua_State* L, - const hlookup::string_map& map); + const hlookup::string_map& map); /** * convert ax::ResourceData to lua object diff --git a/extensions/scripting/lua-bindings/manual/LuaEngine.cpp b/extensions/scripting/lua-bindings/manual/LuaEngine.cpp index 24a4e2186159..e4395bad340e 100644 --- a/extensions/scripting/lua-bindings/manual/LuaEngine.cpp +++ b/extensions/scripting/lua-bindings/manual/LuaEngine.cpp @@ -32,9 +32,9 @@ #include "lua-bindings/manual/extension/axlua_extension_manual.h" #include "lua-bindings/manual/cocostudio/axlua_cocostudio_manual.hpp" #include "lua-bindings/manual/ui/axlua_ui_manual.hpp" -#include "2d/MenuItem.h" -#include "base/Director.h" -#include "base/EventCustom.h" +#include "axmol/2d/MenuItem.h" +#include "axmol/base/Director.h" +#include "axmol/base/EventCustom.h" namespace ax { diff --git a/extensions/scripting/lua-bindings/manual/LuaEngine.h b/extensions/scripting/lua-bindings/manual/LuaEngine.h index 22e26a5fe898..504da39caada 100644 --- a/extensions/scripting/lua-bindings/manual/LuaEngine.h +++ b/extensions/scripting/lua-bindings/manual/LuaEngine.h @@ -30,7 +30,7 @@ extern "C" { #include "lua.h" } -#include "base/ScriptSupport.h" +#include "axmol/base/ScriptSupport.h" #include "lua-bindings/manual/LuaStack.h" #include "lua-bindings/manual/LuaValue.h" #include "lua-bindings/manual/base/LuaScriptHandlerMgr.h" @@ -75,7 +75,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * * @return kScriptTypeLua. */ - virtual ccScriptType getScriptType() override { return kScriptTypeLua; }; + ccScriptType getScriptType() override { return kScriptTypeLua; }; /** * Get LuaStack of the LuaEngine. @@ -120,21 +120,21 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * * @param object the key object to remove script object. */ - virtual void removeScriptObjectByObject(Object* object) override; + void removeScriptObjectByObject(Object* object) override; /** * Remove Lua function reference by nHandler by setting toluafix_refid_function_mapping[nHandle] nil. * * @param nHandler the function reference index to find the corresponding Lua function pointer. */ - virtual void removeScriptHandler(int nHandler) override; + void removeScriptHandler(int nHandler) override; /** * Reallocate Lua function reference index to the Lua function pointer to add reference. * * @param nHandler the function reference index to find the corresponding Lua function pointer. */ - virtual int reallocateScriptHandler(int nHandler) override; + int reallocateScriptHandler(int nHandler) override; /** * Execute script code contained in the given string. @@ -142,7 +142,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * @param codes holding the valid script code that should be executed. * @return 0 if the string is executed correctly, other if the string is executed wrongly. */ - virtual int executeString(const char* codes) override; + int executeString(const char* codes) override; /** * Execute a script file. @@ -150,7 +150,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * @param filename String object holding the filename of the script file that is to be executed. * @return the return values by calling executeFunction. */ - virtual int executeScriptFile(const char* filename) override; + int executeScriptFile(const char* filename) override; /** * Execute a scripted global function. @@ -160,7 +160,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * be executed. * @return The integer value returned from the script function. */ - virtual int executeGlobalFunction(const char* functionName) override; + int executeGlobalFunction(const char* functionName) override; virtual int executeNodeEvent(Node* pNode, int nAction); virtual int executeMenuItemEvent(MenuItem* pMenuItem); virtual int executeCallFuncActionEvent(CallFunc* pAction, Object* pTarget = NULL); @@ -177,7 +177,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * * @return return true if current _callFromLua of LuaStack is not equal to 0 otherwise return false. */ - virtual bool handleAssert(const char* msg) override; + bool handleAssert(const char* msg) override; /** * Parse the config information data. @@ -187,7 +187,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * @return if __onParseConfig function exist in the Lua, it return the value that _stack->executeFunction returns * otherwise return false. */ - virtual bool parseConfig(ConfigType type, std::string_view str) override; + bool parseConfig(ConfigType type, std::string_view str) override; /** * When some events triggered in the c++ also needs to pass on to lua to handle, we could call this function to send @@ -197,7 +197,7 @@ class AX_LUA_DLL LuaEngine : public ScriptEngineProtocol * @return default return 0 otherwise return values the same as handleNodeEvent, handleMenuClickedEvent or * handleCallFuncActionEvent,etc. */ - virtual int sendEvent(const ScriptEvent& message) override; + int sendEvent(const ScriptEvent& message) override; /** * Pass on the events related with ScrollView,TableCell,AssertManager, Armature, Accelerometer, Keyboard, Touch, diff --git a/extensions/scripting/lua-bindings/manual/LuaStack.cpp b/extensions/scripting/lua-bindings/manual/LuaStack.cpp index 0db6b798b38c..2ba242ecd6f6 100644 --- a/extensions/scripting/lua-bindings/manual/LuaStack.cpp +++ b/extensions/scripting/lua-bindings/manual/LuaStack.cpp @@ -51,9 +51,9 @@ extern "C" { #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/auto/axlua_physics_auto.hpp" #include "lua-bindings/manual/physics/axlua_physics_manual.hpp" -#include "lua-bindings/auto/axlua_backend_auto.hpp" -#include "base/ZipUtils.h" -#include "platform/FileUtils.h" +#include "lua-bindings/auto/axlua_rhi_auto.hpp" +#include "axmol/base/ZipUtils.h" +#include "axmol/platform/FileUtils.h" namespace { @@ -214,7 +214,7 @@ bool LuaStack::init() g_luaType.clear(); register_all_ax_base(_state); - register_all_ax_backend(_state); + register_all_ax_rhi(_state); register_all_ax_manual(_state); register_all_ax_module_manual(_state); register_all_ax_math_manual(_state); diff --git a/extensions/scripting/lua-bindings/manual/LuaValue.h b/extensions/scripting/lua-bindings/manual/LuaValue.h index bb28d0069a59..3139cd520199 100644 --- a/extensions/scripting/lua-bindings/manual/LuaValue.h +++ b/extensions/scripting/lua-bindings/manual/LuaValue.h @@ -34,8 +34,8 @@ extern "C" { #include "lua.h" } -#include "base/Types.h" -#include "base/Object.h" +#include "axmol/base/Types.h" +#include "axmol/base/Object.h" #if AX_TARGET_PLATFORM == AX_PLATFORM_BLACKBERRY using std::memcpy; diff --git a/extensions/scripting/lua-bindings/manual/audioengine/axlua_audioengine_manual.cpp b/extensions/scripting/lua-bindings/manual/audioengine/axlua_audioengine_manual.cpp index 3823312f10e4..d81af2177dd3 100644 --- a/extensions/scripting/lua-bindings/manual/audioengine/axlua_audioengine_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/audioengine/axlua_audioengine_manual.cpp @@ -27,7 +27,7 @@ #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/LuaEngine.h" -#include "audio/AudioEngine.h" +#include "axmol/audio/AudioEngine.h" static int lua_get_AudioProfile_name(lua_State* L) { diff --git a/extensions/scripting/lua-bindings/manual/base/LuaScriptHandlerMgr.h b/extensions/scripting/lua-bindings/manual/base/LuaScriptHandlerMgr.h index eaea9cd0568b..936d21b5f04e 100644 --- a/extensions/scripting/lua-bindings/manual/base/LuaScriptHandlerMgr.h +++ b/extensions/scripting/lua-bindings/manual/base/LuaScriptHandlerMgr.h @@ -25,9 +25,9 @@ #pragma once #include "tolua++.h" -#include "base/Object.h" -#include "base/Macros.h" -#include "2d/ActionInstant.h" +#include "axmol/base/Object.h" +#include "axmol/base/Macros.h" +#include "axmol/2d/ActionInstant.h" #include #include @@ -97,8 +97,8 @@ class LuaCallFunc : public ax::CallFuncN * @param func a function pointer for callback. */ bool initWithFunction(const std::function& func); - virtual LuaCallFunc* clone() const override; - virtual void execute() override; + LuaCallFunc* clone() const override; + void execute() override; protected: std::function _functionLua; diff --git a/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.cpp b/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.cpp index a4f01e0766db..d77d4a6e0fd4 100644 --- a/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.cpp @@ -34,36 +34,36 @@ # include #endif -#include "2d/ActionCamera.h" -#include "2d/ActionCatmullRom.h" -#include "2d/ActionGrid.h" -#include "2d/ActionInterval.h" -#include "2d/AtlasNode.h" -#include "2d/Camera.h" -#include "2d/Menu.h" -#include "2d/MenuItem.h" -#include "2d/MotionStreak.h" -#include "2d/ParticleBatchNode.h" -#include "2d/ParticleSystem.h" -#include "2d/Scene.h" -#include "2d/SpriteBatchNode.h" -#include "2d/FastTMXLayer.h" -#include "2d/FastTMXTiledMap.h" -#include "2d/RenderTexture.h" -#include "base/EventDispatcher.h" -#include "base/EventListenerKeyboard.h" -#include "base/EventListenerMouse.h" -#include "base/EventListenerTouch.h" -#include "base/Properties.h" -#include "base/Scheduler.h" -#include "base/UserDefault.h" -#include "base/Utils.h" -#include "platform/Application.h" -#include "platform/Device.h" -#include "platform/FileUtils.h" -#include "platform/RenderView.h" -#include "renderer/TextureCache.h" -#include "renderer/Shaders.h" +#include "axmol/2d/ActionCamera.h" +#include "axmol/2d/ActionCatmullRom.h" +#include "axmol/2d/ActionGrid.h" +#include "axmol/2d/ActionInterval.h" +#include "axmol/2d/AtlasNode.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Menu.h" +#include "axmol/2d/MenuItem.h" +#include "axmol/2d/MotionStreak.h" +#include "axmol/2d/ParticleBatchNode.h" +#include "axmol/2d/ParticleSystem.h" +#include "axmol/2d/Scene.h" +#include "axmol/2d/SpriteBatchNode.h" +#include "axmol/2d/FastTMXLayer.h" +#include "axmol/2d/FastTMXTiledMap.h" +#include "axmol/2d/RenderTexture.h" +#include "axmol/base/EventDispatcher.h" +#include "axmol/base/EventListenerKeyboard.h" +#include "axmol/base/EventListenerMouse.h" +#include "axmol/base/EventListenerTouch.h" +#include "axmol/base/Properties.h" +#include "axmol/base/Scheduler.h" +#include "axmol/base/UserDefault.h" +#include "axmol/base/Utils.h" +#include "axmol/platform/Application.h" +#include "axmol/platform/Device.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/platform/RenderView.h" +#include "axmol/renderer/TextureCache.h" +#include "axmol/renderer/Shaders.h" void LuaNode::draw(ax::Renderer* renderer, const ax::Mat4& transform, uint32_t flags) { @@ -2440,7 +2440,7 @@ int axlua_Node_setRotationQuat(lua_State* tolua_S) } #if defined(AX_ENABLE_NAVMESH) -# include "navmesh/NavMesh.h" +# include "axmol/navmesh/NavMesh.h" int axlua_Scene_setNavMeshDebugCamera(lua_State* tolua_S) { int argc = 0; @@ -3041,8 +3041,8 @@ static int toaxlua_DrawNode_drawPolygon(lua_State* tolua_S) lua_pop(tolua_S, 1); } - Color4B fillColor; - if (!luaval_to_color4b(tolua_S, 4, &fillColor, "ax.DrawNode:drawPolygon")) + ax::Color fillColor; + if (!luaval_to_color(tolua_S, 4, &fillColor, "ax.DrawNode:drawPolygon")) { AX_SAFE_DELETE_ARRAY(points); return 0; @@ -3050,8 +3050,8 @@ static int toaxlua_DrawNode_drawPolygon(lua_State* tolua_S) float borderWidth = (float)tolua_tonumber(tolua_S, 5, 0); - Color4B borderColor; - if (!luaval_to_color4b(tolua_S, 6, &borderColor, "ax.DrawNode:drawPolygon")) + ax::Color borderColor; + if (!luaval_to_color(tolua_S, 6, &borderColor, "ax.DrawNode:drawPolygon")) { AX_SAFE_DELETE_ARRAY(points); return 0; @@ -3125,9 +3125,9 @@ int toaxlua_DrawNode_drawSolidPoly(lua_State* tolua_S) lua_pop(tolua_S, 1); } - ax::Color4B arg2; + ax::Color arg2; - ok &= luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidPoly"); + ok &= luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawSolidPoly"); if (!ok) return 0; self->drawSolidPoly(points, size, arg2); @@ -3204,11 +3204,11 @@ int toaxlua_DrawNode_drawPoly(lua_State* tolua_S) } bool arg2; - ax::Color4B arg3; + ax::Color arg3; ok &= luaval_to_boolean(tolua_S, 4, &arg2, "ax.DrawNode:drawPoly"); - ok &= luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawPoly"); + ok &= luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawPoly"); if (!ok) return 0; @@ -3273,13 +3273,13 @@ int toaxlua_DrawNode_drawCardinalSpline(lua_State* tolua_S) double arg1; unsigned int arg2; - ax::Color4B arg3; + ax::Color arg3; ok &= luaval_to_number(tolua_S, 3, &arg1, "ax.DrawNode:drawCardinalSpline"); ok &= luaval_to_uint32(tolua_S, 4, &arg2, "ax.DrawNode:drawCardinalSpline"); - ok &= luaval_to_color4b(tolua_S, 5, &arg3, "ax.DrawNode:drawCardinalSpline"); + ok &= luaval_to_color(tolua_S, 5, &arg3, "ax.DrawNode:drawCardinalSpline"); if (!ok) return 0; self->drawCardinalSpline(config, (float)arg1, arg2, arg3); @@ -3340,11 +3340,11 @@ int toaxlua_DrawNode_drawCatmullRom(lua_State* tolua_S) AX_SAFE_DELETE_ARRAY(arr); unsigned int arg1; - ax::Color4B arg2; + ax::Color arg2; ok &= luaval_to_uint32(tolua_S, 3, &arg1, "ax.DrawNode:drawCatmullRom"); - ok &= luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawCatmullRom"); + ok &= luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawCatmullRom"); if (!ok) return 0; self->drawCatmullRom(config, arg1, arg2); @@ -3415,9 +3415,9 @@ int toaxlua_DrawNode_drawPoints(lua_State* tolua_S) lua_pop(tolua_S, 1); } - ax::Color4B arg2; + ax::Color arg2; - ok &= luaval_to_color4b(tolua_S, 4, &arg2, "ax.DrawNode:drawPoints"); + ok &= luaval_to_color(tolua_S, 4, &arg2, "ax.DrawNode:drawPoints"); if (!ok) return 0; self->drawPoints(points, size, arg2); @@ -3453,8 +3453,8 @@ int toaxlua_DrawNode_drawPoints(lua_State* tolua_S) } float pointSize = (float)tolua_tonumber(tolua_S, 4, 0); - ax::Color4B color; - ok &= luaval_to_color4b(tolua_S, 5, &color, "ax.DrawNode:drawPoints"); + ax::Color color; + ok &= luaval_to_color(tolua_S, 5, &color, "ax.DrawNode:drawPoints"); if (!ok) return 0; self->drawPoints(points, size, pointSize, color); @@ -3665,10 +3665,10 @@ static int toaxlua_Texture2D_setTexParameters(lua_State* tolua_S) int argc = 0; Texture2D* self = nullptr; - backend::SamplerFilter arg1; - backend::SamplerFilter arg2; - backend::SamplerAddressMode arg3; - backend::SamplerAddressMode arg4; + rhi::SamplerFilter arg1; + rhi::SamplerFilter arg2; + rhi::SamplerAddressMode arg3; + rhi::SamplerAddressMode arg4; #if _AX_DEBUG >= 1 tolua_Error tolua_err; @@ -3698,12 +3698,12 @@ static int toaxlua_Texture2D_setTexParameters(lua_State* tolua_S) } #endif - arg1 = (backend::SamplerFilter)(int)tolua_tonumber(tolua_S, 2, 0); - arg2 = (backend::SamplerFilter)(int)tolua_tonumber(tolua_S, 3, 0); - arg3 = (backend::SamplerAddressMode)(int)tolua_tonumber(tolua_S, 4, 0); - arg4 = (backend::SamplerAddressMode)(int)tolua_tonumber(tolua_S, 5, 0); + arg1 = (rhi::SamplerFilter)(int)tolua_tonumber(tolua_S, 2, 0); + arg2 = (rhi::SamplerFilter)(int)tolua_tonumber(tolua_S, 3, 0); + arg3 = (rhi::SamplerAddressMode)(int)tolua_tonumber(tolua_S, 4, 0); + arg4 = (rhi::SamplerAddressMode)(int)tolua_tonumber(tolua_S, 5, 0); - Texture2D::TexParams param(arg1, arg2, arg3, arg4); + Texture2D::TexParams param{.minFilter = arg1, .magFilter = arg2, .sAddressMode = arg3, .tAddressMode = arg4}; self->setTexParameters(param); @@ -3788,7 +3788,7 @@ static int toaxlua_SpriteBatchNode_getDescendants(lua_State* tolua_S) } #if defined(AX_ENABLE_3D_PHYSICS) -# include "physics3d/Physics3DWorld.h" +# include "axmol/physics3d/Physics3DWorld.h" int axlua_Scene_getPhysics3DWorld(lua_State* tolua_S) { int argc = 0; @@ -6825,15 +6825,15 @@ static int lua_collect_PolygonInfo(lua_State* tolua_S) int axlua_get_PipelineDescriptor_programState(lua_State* tolua_S) { - ax::PipelineDescriptor* cobj = nullptr; + ax::PipelineDesc* cobj = nullptr; #if _AX_DEBUG >= 1 tolua_Error tolua_err; - if (!tolua_isusertype(tolua_S, 1, "ax.PipelineDescriptor", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PipelineDesc", 0, &tolua_err)) goto tolua_lerror; #endif - cobj = (ax::PipelineDescriptor*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PipelineDesc*)tolua_tousertype(tolua_S, 1, 0); #if _AX_DEBUG >= 1 if (nullptr == cobj) { @@ -6855,15 +6855,15 @@ int axlua_get_PipelineDescriptor_programState(lua_State* tolua_S) int axlua_set_PipelineDescriptor_programState(lua_State* tolua_S) { int argc = 0; - ax::PipelineDescriptor* self = nullptr; + ax::PipelineDesc* self = nullptr; #if _AX_DEBUG >= 1 tolua_Error tolua_err; - if (!tolua_isusertype(tolua_S, 1, "ax.PipelineDescriptor", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PipelineDesc", 0, &tolua_err)) goto tolua_lerror; #endif - self = (ax::PipelineDescriptor*)tolua_tousertype(tolua_S, 1, 0); + self = (ax::PipelineDesc*)tolua_tousertype(tolua_S, 1, 0); #if _AX_DEBUG >= 1 if (nullptr == self) { @@ -6877,8 +6877,8 @@ int axlua_set_PipelineDescriptor_programState(lua_State* tolua_S) if (1 == argc) { - ax::backend::ProgramState* programState = nullptr; - luaval_to_object(tolua_S, 2, "axb.ProgramState", &programState, + ax::rhi::ProgramState* programState = nullptr; + luaval_to_object(tolua_S, 2, "axb.ProgramState", &programState, "axlua_set_PipelineDescriptor_programState"); self->programState = programState; return 0; @@ -6915,7 +6915,7 @@ static void extendPolygonInfo(lua_State* tolua_S) static void extendPipelineDescriptor(lua_State* tolua_S) { - lua_pushstring(tolua_S, "ax.PipelineDescriptor"); + lua_pushstring(tolua_S, "ax.PipelineDesc"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { @@ -6928,7 +6928,7 @@ static void extendPipelineDescriptor(lua_State* tolua_S) static int axlua_backend_ProgramState_getUniformLocation(lua_State* tolua_S) { int argc = 0; - ax::backend::ProgramState* cobj = nullptr; + ax::rhi::ProgramState* cobj = nullptr; bool ok = true; #if _AX_DEBUG >= 1 tolua_Error tolua_err; @@ -6938,7 +6938,7 @@ static int axlua_backend_ProgramState_getUniformLocation(lua_State* tolua_S) if (!tolua_isusertype(tolua_S, 1, "axb.ProgramState", 0, &tolua_err)) goto tolua_lerror; #endif - cobj = (ax::backend::ProgramState*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S, 1, 0); #if _AX_DEBUG >= 1 if (!cobj) { @@ -6961,20 +6961,20 @@ static int axlua_backend_ProgramState_getUniformLocation(lua_State* tolua_S) { break; } - ax::backend::UniformLocation ret = cobj->getUniformLocation(arg0); + ax::rhi::UniformLocation ret = cobj->getUniformLocation(arg0); uniformLocation_to_luaval(tolua_S, ret); return 1; } else if (lua_isnumber(tolua_S, -1)) { - ax::backend::Uniform arg0; + ax::rhi::Uniform arg0; ok &= luaval_to_int32(tolua_S, 2, (int*)&arg0, "axb.ProgramState:getUniformLocation"); if (!ok) { break; } - ax::backend::UniformLocation ret = cobj->getUniformLocation(arg0); + ax::rhi::UniformLocation ret = cobj->getUniformLocation(arg0); uniformLocation_to_luaval(tolua_S, ret); return 1; } @@ -6997,7 +6997,7 @@ static int axlua_ProgramState_setUniform(lua_State* tolua_S) { bool ok = true; int argc = 0; - ax::backend::ProgramState* self = nullptr; + ax::rhi::ProgramState* self = nullptr; #if _AX_DEBUG >= 1 tolua_Error tolua_err; @@ -7005,7 +7005,7 @@ static int axlua_ProgramState_setUniform(lua_State* tolua_S) goto tolua_lerror; #endif - self = (ax::backend::ProgramState*)tolua_tousertype(tolua_S, 1, 0); + self = (ax::rhi::ProgramState*)tolua_tousertype(tolua_S, 1, 0); #if _AX_DEBUG >= 1 if (nullptr == self) { @@ -7018,7 +7018,7 @@ static int axlua_ProgramState_setUniform(lua_State* tolua_S) if (2 == argc) { - ax::backend::UniformLocation location; + ax::rhi::UniformLocation location; if (lua_isstring(tolua_S, 2)) { @@ -7064,7 +7064,7 @@ static void extendProgramState(lua_State* tolua_S) // lua_pushstring(tolua_S, "axb.ProgramState"); // lua_rawget(tolua_S, LUA_REGISTRYINDEX); - tolua_beginmodule(tolua_S, "axb"); + tolua_beginmodule(tolua_S, "axrhi"); tolua_beginmodule(tolua_S, "ProgramState"); if (lua_istable(tolua_S, -1)) { @@ -8345,7 +8345,7 @@ int register_all_ax_shaders_manual(lua_State* tolua_S) set_lua_field(particle_vert); set_lua_field(positionNormalTexture_vert); set_lua_field(skinPositionNormalTexture_vert); - set_lua_field(positionTexture3D_vert); + set_lua_field(unlit_vert); set_lua_field(skinPositionTexture_vert); set_lua_field(skybox_frag); set_lua_field(skybox_vert); diff --git a/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.hpp b/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.hpp index f3010e545d60..15a6658e3aec 100644 --- a/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.hpp +++ b/extensions/scripting/lua-bindings/manual/base/axlua_base_manual.hpp @@ -28,9 +28,9 @@ #include "tolua++.h" #include "lua-bindings/manual/base/LuaScriptHandlerMgr.h" -#include "base/EventListenerAcceleration.h" -#include "base/EventListenerCustom.h" -#include "2d/Node.h" +#include "axmol/base/EventListenerAcceleration.h" +#include "axmol/base/EventListenerCustom.h" +#include "axmol/2d/Node.h" namespace ax { @@ -120,7 +120,7 @@ class LuaNode :public ax::Node public: virtual ~LuaNode() {} - virtual void draw(ax::Renderer *renderer, const ax::Mat4& transform, uint32_t flags) override; + void draw(ax::Renderer *renderer, const ax::Mat4& transform, uint32_t flags) override; }; TOLUA_API int tolua_luanode_open(lua_State* tolua_S); diff --git a/extensions/scripting/lua-bindings/manual/cocostudio/axlua_cocostudio_manual.hpp b/extensions/scripting/lua-bindings/manual/cocostudio/axlua_cocostudio_manual.hpp index 2e078466d270..644effdb9d89 100644 --- a/extensions/scripting/lua-bindings/manual/cocostudio/axlua_cocostudio_manual.hpp +++ b/extensions/scripting/lua-bindings/manual/cocostudio/axlua_cocostudio_manual.hpp @@ -32,7 +32,7 @@ extern "C" { } #endif -#include "base/Object.h" +#include "axmol/base/Object.h" #include TOLUA_API int register_all_ax_coco_studio_manual(lua_State* L); diff --git a/extensions/scripting/lua-bindings/manual/cocostudio/axlua_csloader_manual.hpp b/extensions/scripting/lua-bindings/manual/cocostudio/axlua_csloader_manual.hpp index 6cc41d3c973b..9c3baf8c797b 100644 --- a/extensions/scripting/lua-bindings/manual/cocostudio/axlua_csloader_manual.hpp +++ b/extensions/scripting/lua-bindings/manual/cocostudio/axlua_csloader_manual.hpp @@ -32,7 +32,7 @@ extern "C" { } #endif -#include "base/Object.h" +#include "axmol/base/Object.h" #include TOLUA_API int register_all_ax_csloader_manual(lua_State* L); diff --git a/extensions/scripting/lua-bindings/manual/controller/axlua_controller_manual.cpp b/extensions/scripting/lua-bindings/manual/controller/axlua_controller_manual.cpp index bda3c0aacf61..17303c800a63 100644 --- a/extensions/scripting/lua-bindings/manual/controller/axlua_controller_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/controller/axlua_controller_manual.cpp @@ -32,7 +32,7 @@ # include "lua-bindings/manual/base/LuaScriptHandlerMgr.h" # include "lua-bindings/manual/LuaValue.h" # include "lua-bindings/manual/LuaEngine.h" -# include "base/GameController.h" +# include "axmol/base/GameController.h" static void cloneEventListenerControllerHandler(const ax::EventListenerController* src, ax::EventListenerController* dst, diff --git a/extensions/scripting/lua-bindings/manual/extension/axlua_extension_manual.cpp b/extensions/scripting/lua-bindings/manual/extension/axlua_extension_manual.cpp index 7d69fe8afe2a..36be5942914f 100644 --- a/extensions/scripting/lua-bindings/manual/extension/axlua_extension_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/extension/axlua_extension_manual.cpp @@ -82,7 +82,7 @@ class LuaAssetsManagerDelegateProtocol : public Object, public AssetsManagerDele public: virtual ~LuaAssetsManagerDelegateProtocol() {} - virtual void onProgress(int percent) override + void onProgress(int percent) override { int handler = ScriptHandlerMgr::getInstance()->getObjectHandler( (void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_PROGRESS); @@ -94,7 +94,7 @@ class LuaAssetsManagerDelegateProtocol : public Object, public AssetsManagerDele } } - virtual void onSuccess() override + void onSuccess() override { int handler = ScriptHandlerMgr::getInstance()->getObjectHandler( (void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_SUCCESS); @@ -106,7 +106,7 @@ class LuaAssetsManagerDelegateProtocol : public Object, public AssetsManagerDele } } - virtual void onError(AssetsManager::ErrorCode errorCode) override + void onError(AssetsManager::ErrorCode errorCode) override { int handler = ScriptHandlerMgr::getInstance()->getObjectHandler( (void*)this, ScriptHandlerMgr::HandlerType::ASSETSMANAGER_ERROR); @@ -415,7 +415,7 @@ class LuaScrollViewDelegate:public Object, public ScrollViewDelegate virtual ~LuaScrollViewDelegate() {} - virtual void scrollViewDidScroll(ScrollView* view) override + void scrollViewDidScroll(ScrollView* view) override { if (nullptr != view) { @@ -430,7 +430,7 @@ class LuaScrollViewDelegate:public Object, public ScrollViewDelegate } } - virtual void scrollViewDidZoom(ScrollView* view) override + void scrollViewDidZoom(ScrollView* view) override { if (nullptr != view) { @@ -617,7 +617,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate virtual ~LUA_TableViewDelegate(){} - virtual void scrollViewDidScroll(ScrollView* view) override + void scrollViewDidScroll(ScrollView* view) override { if (nullptr != view) { @@ -631,7 +631,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate } } - virtual void scrollViewDidZoom(ScrollView* view) override + void scrollViewDidZoom(ScrollView* view) override { if (nullptr != view) { @@ -645,7 +645,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate } } - virtual void tableCellTouched(TableView* table, TableViewCell* cell) override + void tableCellTouched(TableView* table, TableViewCell* cell) override { if (nullptr != table && nullptr != cell) { @@ -659,7 +659,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate } } - virtual void tableCellHighlight(TableView* table, TableViewCell* cell) override + void tableCellHighlight(TableView* table, TableViewCell* cell) override { if (nullptr != table && nullptr != cell) { @@ -673,7 +673,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate } } - virtual void tableCellUnhighlight(TableView* table, TableViewCell* cell) override + void tableCellUnhighlight(TableView* table, TableViewCell* cell) override { if (nullptr != table && nullptr != cell) { @@ -687,7 +687,7 @@ class LUA_TableViewDelegate:public Object, public TableViewDelegate } } - virtual void tableCellWillRecycle(TableView* table, TableViewCell* cell) override + void tableCellWillRecycle(TableView* table, TableViewCell* cell) override { if (nullptr != table && nullptr != cell) { @@ -767,7 +767,7 @@ class LUA_TableViewDataSource:public Object,public TableViewDataSource LUA_TableViewDataSource(){} virtual ~LUA_TableViewDataSource(){} - virtual Size tableCellSizeForIndex(TableView *table, ssize_t idx) override + Size tableCellSizeForIndex(TableView *table, ssize_t idx) override { if (nullptr != table ) { @@ -794,7 +794,7 @@ class LUA_TableViewDataSource:public Object,public TableViewDataSource return Size::ZERO; } - virtual TableViewCell* tableCellAtIndex(TableView *table, ssize_t idx) override + TableViewCell* tableCellAtIndex(TableView *table, ssize_t idx) override { if (nullptr != table ) { @@ -817,7 +817,7 @@ class LUA_TableViewDataSource:public Object,public TableViewDataSource return NULL; } - virtual ssize_t numberOfCellsInTableView(TableView *table) override + ssize_t numberOfCellsInTableView(TableView *table) override { if (nullptr != table ) { diff --git a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.cpp b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.cpp index 9897c81ed51b..1a6bfc1bf6f7 100644 --- a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.cpp +++ b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.cpp @@ -25,11 +25,11 @@ ****************************************************************************/ #include "lua-bindings/manual/navmesh/axlua_navmesh_conversions.h" -#include "base/Config.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) # include "lua-bindings/manual/LuaBasicConversions.h" -# include "navmesh/NavMeshAgent.h" +# include "axmol/navmesh/NavMeshAgent.h" # if _AX_DEBUG >= 1 extern void luaval_to_native_err(lua_State* L, const char* msg, tolua_Error* err, const char* funcName); diff --git a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h index 8d1d01ee1c45..3ca86858d773 100644 --- a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h +++ b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h @@ -28,7 +28,7 @@ #if defined(AX_ENABLE_NAVMESH) # include "lua-bindings/manual/tolua_fix.h" -# include "platform/PlatformMacros.h" +# include "axmol/platform/PlatformMacros.h" namespace ax { diff --git a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_manual.cpp b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_manual.cpp index 7a65aa7d5eba..6af48c17b079 100644 --- a/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_manual.cpp @@ -23,15 +23,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" -#include "base/Config.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_NAVMESH) # include "axlua_navmesh_manual.h" # include "lua-bindings/auto/axlua_navmesh_auto.hpp" # include "lua-bindings/manual/tolua_fix.h" # include "lua-bindings/manual/LuaBasicConversions.h" # include "lua-bindings/manual/LuaEngine.h" -# include "navmesh/NavMesh.h" +# include "axmol/navmesh/NavMesh.h" int axlua_navmesh_NavMeshAgent_move(lua_State* tolua_S) { diff --git a/extensions/scripting/lua-bindings/manual/network/lua_downloader.cpp b/extensions/scripting/lua-bindings/manual/network/lua_downloader.cpp index 00d56587f688..e85d513435c0 100644 --- a/extensions/scripting/lua-bindings/manual/network/lua_downloader.cpp +++ b/extensions/scripting/lua-bindings/manual/network/lua_downloader.cpp @@ -24,7 +24,7 @@ THE SOFTWARE. #include "lua_downloader.h" #include "lua-bindings/manual/LuaValue.h" -#include "network/Downloader.h" +#include "axmol/network/Downloader.h" #include #include diff --git a/extensions/scripting/lua-bindings/manual/network/lua_websocket.h b/extensions/scripting/lua-bindings/manual/network/lua_websocket.h index 3b835a6caeae..28a164705ed7 100644 --- a/extensions/scripting/lua-bindings/manual/network/lua_websocket.h +++ b/extensions/scripting/lua-bindings/manual/network/lua_websocket.h @@ -33,7 +33,7 @@ extern "C" { } #endif -#include "network/WebSocket.h" +#include "axmol/network/WebSocket.h" ///@cond class LuaWebSocket: public ax::network::WebSocket, public ax::network::WebSocket::Delegate diff --git a/extensions/scripting/lua-bindings/manual/network/lua_xml_http_request.cpp b/extensions/scripting/lua-bindings/manual/network/lua_xml_http_request.cpp index 0e0b74794884..7de381efe621 100644 --- a/extensions/scripting/lua-bindings/manual/network/lua_xml_http_request.cpp +++ b/extensions/scripting/lua-bindings/manual/network/lua_xml_http_request.cpp @@ -30,7 +30,7 @@ #include "lua-bindings/manual/LuaEngine.h" #include "lua-bindings/manual/base/LuaScriptHandlerMgr.h" -#include "network/HttpClient.h" +#include "axmol/network/HttpClient.h" #include #include diff --git a/extensions/scripting/lua-bindings/manual/physics/axlua_physics_manual.cpp b/extensions/scripting/lua-bindings/manual/physics/axlua_physics_manual.cpp index 63bffba609c7..88036d3ac74d 100644 --- a/extensions/scripting/lua-bindings/manual/physics/axlua_physics_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/physics/axlua_physics_manual.cpp @@ -30,7 +30,7 @@ # include "lua-bindings/manual/LuaBasicConversions.h" # include "lua-bindings/manual/LuaValue.h" # include "lua-bindings/manual/LuaEngine.h" -# include "2d/Scene.h" +# include "axmol/2d/Scene.h" # ifndef AX_SAFE_DELETE_ARRAY # define do \ @@ -255,17 +255,17 @@ int axlua_physics_PhysicsWorld_queryRect(lua_State* tolua_S) argc = lua_gettop(tolua_S) - 1; if (argc == 2) { - std::function arg0; + std::function arg0; ax::Rect arg1; LUA_FUNCTION handler = toluafix_ref_function(tolua_S, 2, 0); auto stack = LuaEngine::getInstance()->getLuaStack(); do { - arg0 = [handler,stack](ax::PhysicsWorld& world, ax::PhysicsShape& shape, void* data) -> bool { + arg0 = [handler,stack](ax::PhysicsWorld& world, ax::PhysicsCollider& shape, void* data) -> bool { auto Ls = stack->getLuaState(); tolua_pushusertype(Ls, (void*)(&world), getLuaTypeName(&world, "ax.PhysicsWorld")); - toluafix_pushusertype_object(Ls, shape._ID, &shape._luaID, (void*)(&shape), "ax.PhysicsShape"); + toluafix_pushusertype_object(Ls, shape._ID, &shape._luaID, (void*)(&shape), "ax.PhysicsCollider"); return stack->executeFunctionByHandler(handler, 2); }; } while (0); @@ -320,16 +320,16 @@ int axlua_physics_PhysicsWorld_queryPoint(lua_State* tolua_S) argc = lua_gettop(tolua_S) - 1; if (argc == 2) { - std::function arg0; + std::function arg0; ax::Vec2 arg1; LUA_FUNCTION handler = toluafix_ref_function(tolua_S, 2, 0); auto stack = LuaEngine::getInstance()->getLuaStack(); do { - arg0 = [handler,stack](ax::PhysicsWorld& world, ax::PhysicsShape& shape, void* data) -> bool { + arg0 = [handler,stack](ax::PhysicsWorld& world, ax::PhysicsCollider& shape, void* data) -> bool { auto Ls = stack->getLuaState(); tolua_pushusertype(Ls, (void*)(&world), getLuaTypeName(&world, "ax.PhysicsWorld")); - toluafix_pushusertype_object(Ls, shape._ID, &shape._luaID, (void*)(&shape), "ax.PhysicsShape"); + toluafix_pushusertype_object(Ls, shape._ID, &shape._luaID, (void*)(&shape), "ax.PhysicsCollider"); return stack->executeFunctionByHandler(handler, 2); }; assert(false); @@ -756,7 +756,7 @@ int axlua_physics_PhysicsBody_createEdgeChain(lua_State* tolua_S) return 0; } -int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) +int axlua_physics_PhysicsCollider_recenterPoints(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -766,7 +766,7 @@ int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShape", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsCollider", 0, &tolua_err)) goto tolua_lerror; # endif @@ -778,7 +778,7 @@ int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) int arg1 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShape:recenterPoints"); + ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsCollider:recenterPoints"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); @@ -789,7 +789,7 @@ int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) AX_SAFE_DELETE_ARRAY(arg0); return 0; } - ax::PhysicsShape::recenterPoints(arg0, arg1); + ax::PhysicsCollider::recenterPoints(arg0, arg1); vec2_array_to_luaval(tolua_S, arg0, arg1); AX_SAFE_DELETE_ARRAY(arg0); @@ -802,19 +802,19 @@ int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) ax::Vec2 arg2; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShape:recenterPoints"); + ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsCollider:recenterPoints"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); } } while (0); - ok &= luaval_to_vec2(tolua_S, 3, &arg2, "ax.PhysicsShape:recenterPoints"); + ok &= luaval_to_vec2(tolua_S, 3, &arg2, "ax.PhysicsCollider:recenterPoints"); if (!ok) { AX_SAFE_DELETE_ARRAY(arg0); return 0; } - ax::PhysicsShape::recenterPoints(arg0, arg1, arg2); + ax::PhysicsCollider::recenterPoints(arg0, arg1, arg2); vec2_array_to_luaval(tolua_S, arg0, arg1); AX_SAFE_DELETE_ARRAY(arg0); return 1; @@ -823,12 +823,12 @@ int axlua_physics_PhysicsShape_recenterPoints(lua_State* tolua_S) return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShape_recenterPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsCollider_recenterPoints'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShape_getPolygonCenter(lua_State* tolua_S) +int axlua_physics_PhysicsCollider_getPolygonCenter(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -838,7 +838,7 @@ int axlua_physics_PhysicsShape_getPolygonCenter(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShape", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsCollider", 0, &tolua_err)) goto tolua_lerror; # endif @@ -850,7 +850,7 @@ int axlua_physics_PhysicsShape_getPolygonCenter(lua_State* tolua_S) int arg1 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShape:getPolygonCenter"); + ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsCollider:getPolygonCenter"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); @@ -861,7 +861,7 @@ int axlua_physics_PhysicsShape_getPolygonCenter(lua_State* tolua_S) AX_SAFE_DELETE_ARRAY(arg0); return 0; } - ax::Vec2 ret = ax::PhysicsShape::getPolygonCenter(arg0, arg1); + ax::Vec2 ret = ax::PhysicsCollider::getPolygonCenter(arg0, arg1); AX_SAFE_DELETE_ARRAY(arg0); vec2_to_luaval(tolua_S, ret); return 1; @@ -870,31 +870,31 @@ int axlua_physics_PhysicsShape_getPolygonCenter(lua_State* tolua_S) return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShape_getPolygonCenter'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsCollider_getPolygonCenter'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapeBox_getPoints(lua_State* tolua_S) +int axlua_physics_PhysicsColliderBox_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeBox* cobj = nullptr; + ax::PhysicsColliderBox* cobj = nullptr; # if _AX_DEBUG >= 1 tolua_Error tolua_err; # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsShapeBox", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsColliderBox", 0, &tolua_err)) goto tolua_lerror; # endif - cobj = (ax::PhysicsShapeBox*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PhysicsColliderBox*)tolua_tousertype(tolua_S, 1, 0); # if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsShapeBox_getPoints'", NULL); + tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsColliderBox_getPoints'", NULL); return 0; } # endif @@ -912,32 +912,32 @@ int axlua_physics_PhysicsShapeBox_getPoints(lua_State* tolua_S) # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeBox_getPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderBox_getPoints'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapePolygon_getPoints(lua_State* tolua_S) +int axlua_physics_PhysicsColliderPolygon_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapePolygon* cobj = nullptr; + ax::PhysicsColliderPolygon* cobj = nullptr; # if _AX_DEBUG >= 1 tolua_Error tolua_err; # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsShapePolygon", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsColliderPolygon", 0, &tolua_err)) goto tolua_lerror; # endif - cobj = (ax::PhysicsShapePolygon*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PhysicsColliderPolygon*)tolua_tousertype(tolua_S, 1, 0); # if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsShapePolygon_getPoints'", NULL); + tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsColliderPolygon_getPoints'", NULL); return 0; } # endif @@ -957,13 +957,13 @@ int axlua_physics_PhysicsShapePolygon_getPoints(lua_State* tolua_S) # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapePolygon_getPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderPolygon_getPoints'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapePolygon_create(lua_State* tolua_S) +int axlua_physics_PhysicsColliderPolygon_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -973,19 +973,22 @@ int axlua_physics_PhysicsShapePolygon_create(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShapePolygon", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsColliderPolygon", 0, &tolua_err)) goto tolua_lerror; # endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - ax::Vec2* arg0; - int arg1 = 0; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapePolygon:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderPolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderPolygon:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); @@ -994,76 +997,82 @@ int axlua_physics_PhysicsShapePolygon_create(lua_State* tolua_S) if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapePolygon* ret = ax::PhysicsShapePolygon::create(arg0, arg1); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapePolygon", - (ax::PhysicsShapePolygon*)ret); + ax::PhysicsColliderPolygon* ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon", + (ax::PhysicsColliderPolygon*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapePolygon:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderPolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderPolygon:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderPolygon:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapePolygon* ret = ax::PhysicsShapePolygon::create(arg0, arg1, arg2); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapePolygon", - (ax::PhysicsShapePolygon*)ret); + ax::PhysicsColliderPolygon* ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2, arg3); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon", + (ax::PhysicsColliderPolygon*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; - ax::Vec2 arg3; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; + ax::Vec2 arg4; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapePolygon:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderPolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderPolygon:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapePolygon:create"); - ok &= luaval_to_vec2(tolua_S, 4, &arg3, "ax.PhysicsShapePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderPolygon:create"); + ok &= luaval_to_vec2(tolua_S, 5, &arg4, "ax.PhysicsColliderPolygon:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapePolygon* ret = ax::PhysicsShapePolygon::create(arg0, arg1, arg2, arg3); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapePolygon", - (ax::PhysicsShapePolygon*)ret); + ax::PhysicsColliderPolygon* ret = ax::PhysicsColliderPolygon::create(arg0, arg1, arg2, arg3, arg4); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderPolygon", + (ax::PhysicsColliderPolygon*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "create", argc, 2); return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapePolygon_create'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderPolygon_create'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapePolygon_calculateArea(lua_State* tolua_S) +int axlua_physics_PhysicsColliderPolygon_calculateArea(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1073,7 +1082,7 @@ int axlua_physics_PhysicsShapePolygon_calculateArea(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShapePolygon", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsColliderPolygon", 0, &tolua_err)) goto tolua_lerror; # endif @@ -1085,7 +1094,7 @@ int axlua_physics_PhysicsShapePolygon_calculateArea(lua_State* tolua_S) int arg1 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapePolygon:calculateArea"); + ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsColliderPolygon:calculateArea"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); @@ -1096,7 +1105,7 @@ int axlua_physics_PhysicsShapePolygon_calculateArea(lua_State* tolua_S) AX_SAFE_DELETE_ARRAY(arg0); return 0; } - double ret = ax::PhysicsShapePolygon::calculateArea(arg0, arg1); + double ret = ax::PhysicsColliderPolygon::calculateArea(arg0, arg1); AX_SAFE_DELETE_ARRAY(arg0); tolua_pushnumber(tolua_S, (lua_Number)ret); return 1; @@ -1105,105 +1114,31 @@ int axlua_physics_PhysicsShapePolygon_calculateArea(lua_State* tolua_S) return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapePolygon_calculateArea'.", &tolua_err); -# endif - return 0; -} -int axlua_physics_PhysicsShapePolygon_calculateMoment(lua_State* tolua_S) -{ - int argc = 0; - bool ok = true; - -# if _AX_DEBUG >= 1 - tolua_Error tolua_err; -# endif - -# if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShapePolygon", 0, &tolua_err)) - goto tolua_lerror; -# endif - - argc = lua_gettop(tolua_S) - 1; - - if (argc == 2) - { - double arg0; - ax::Vec2* arg1; - int arg2 = 0; - ok &= luaval_to_number(tolua_S, 2, &arg0, "ax.PhysicsShapePolygon:calculateMoment"); - do - { - ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsShapePolygon:calculateMoment"); - if (nullptr == arg1) - { - LUA_PRECONDITION(arg1, "Invalid Native Object"); - } - } while (0); - if (!ok) - { - AX_SAFE_DELETE_ARRAY(arg1); - return 0; - } - double ret = ax::PhysicsShapePolygon::calculateMoment(arg0, arg1, arg2); - AX_SAFE_DELETE_ARRAY(arg1); - tolua_pushnumber(tolua_S, (lua_Number)ret); - return 1; - } - if (argc == 2) - { - double arg0; - ax::Vec2* arg1; - int arg2 = 0; - ax::Vec2 arg3; - ok &= luaval_to_number(tolua_S, 2, &arg0, "ax.PhysicsShapePolygon:calculateMoment"); - do - { - ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsShapePolygon:calculateMoment"); - if (nullptr == arg1) - { - LUA_PRECONDITION(arg1, "Invalid Native Object"); - } - } while (0); - ok &= luaval_to_vec2(tolua_S, 4, &arg3, "ax.PhysicsShapePolygon:calculateMoment"); - if (!ok) - { - AX_SAFE_DELETE_ARRAY(arg1); - return 0; - } - double ret = ax::PhysicsShapePolygon::calculateMoment(arg0, arg1, arg2, arg3); - AX_SAFE_DELETE_ARRAY(arg1); - tolua_pushnumber(tolua_S, (lua_Number)ret); - return 1; - } - luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "calculateMoment", argc, 3); - return 0; -# if _AX_DEBUG >= 1 -tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapePolygon_calculateMoment'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderPolygon_calculateArea'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapeEdgeBox_getPoints(lua_State* tolua_S) +int axlua_physics_PhysicsColliderEdgeBox_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgeBox* cobj = nullptr; + ax::PhysicsColliderEdgeBox* cobj = nullptr; # if _AX_DEBUG >= 1 tolua_Error tolua_err; # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsShapeEdgeBox", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsColliderEdgeBox", 0, &tolua_err)) goto tolua_lerror; # endif - cobj = (ax::PhysicsShapeEdgeBox*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PhysicsColliderEdgeBox*)tolua_tousertype(tolua_S, 1, 0); # if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsShapeEdgeBox_getPoints'", NULL); + tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsColliderEdgeBox_getPoints'", NULL); return 0; } # endif @@ -1223,32 +1158,32 @@ int axlua_physics_PhysicsShapeEdgeBox_getPoints(lua_State* tolua_S) # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeEdgeBox_getPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderEdgeBox_getPoints'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapeEdgePolygon_getPoints(lua_State* tolua_S) +int axlua_physics_PhysicsColliderEdgePolygon_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgePolygon* cobj = nullptr; + ax::PhysicsColliderEdgePolygon* cobj = nullptr; # if _AX_DEBUG >= 1 tolua_Error tolua_err; # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsShapeEdgePolygon", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsColliderEdgePolygon", 0, &tolua_err)) goto tolua_lerror; # endif - cobj = (ax::PhysicsShapeEdgePolygon*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PhysicsColliderEdgePolygon*)tolua_tousertype(tolua_S, 1, 0); # if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsShapeEdgePolygon_getPoints'", + tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsColliderEdgePolygon_getPoints'", NULL); return 0; } @@ -1269,32 +1204,32 @@ int axlua_physics_PhysicsShapeEdgePolygon_getPoints(lua_State* tolua_S) # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeEdgePolygon_getPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderEdgePolygon_getPoints'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapeEdgeChain_getPoints(lua_State* tolua_S) +int axlua_physics_PhysicsColliderEdgeChain_getPoints(lua_State* tolua_S) { int argc = 0; - ax::PhysicsShapeEdgeChain* cobj = nullptr; + ax::PhysicsColliderEdgeChain* cobj = nullptr; # if _AX_DEBUG >= 1 tolua_Error tolua_err; # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsShapeEdgeChain", 0, &tolua_err)) + if (!tolua_isusertype(tolua_S, 1, "ax.PhysicsColliderEdgeChain", 0, &tolua_err)) goto tolua_lerror; # endif - cobj = (ax::PhysicsShapeEdgeChain*)tolua_tousertype(tolua_S, 1, 0); + cobj = (ax::PhysicsColliderEdgeChain*)tolua_tousertype(tolua_S, 1, 0); # if _AX_DEBUG >= 1 if (!cobj) { - tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsShapeEdgeChain_getPoints'", NULL); + tolua_error(tolua_S, "invalid 'cobj' in function 'axlua_physics_PhysicsColliderEdgeChain_getPoints'", NULL); return 0; } # endif @@ -1314,7 +1249,7 @@ int axlua_physics_PhysicsShapeEdgeChain_getPoints(lua_State* tolua_S) # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeEdgeChain_getPoints'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderEdgeChain_getPoints'.", &tolua_err); # endif return 0; @@ -1430,7 +1365,7 @@ static int toaxlua_EventListenerPhysicsContact_registerScriptHandler(lua_State* # endif } -int axlua_physics_PhysicsShapeEdgePolygon_create(lua_State* tolua_S) +int axlua_physics_PhysicsColliderEdgePolygon_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1440,19 +1375,22 @@ int axlua_physics_PhysicsShapeEdgePolygon_create(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShapeEdgePolygon", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsColliderEdgePolygon", 0, &tolua_err)) goto tolua_lerror; # endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - ax::Vec2* arg0; - int arg1 = 0; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgePolygon:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgePolygon:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); @@ -1460,77 +1398,83 @@ int axlua_physics_PhysicsShapeEdgePolygon_create(lua_State* tolua_S) } while (0); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgePolygon* ret = ax::PhysicsShapeEdgePolygon::create(arg0, arg1); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgePolygon", - (ax::PhysicsShapeEdgePolygon*)ret); + ax::PhysicsColliderEdgePolygon* ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon", + (ax::PhysicsColliderEdgePolygon*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgePolygon:create"); - if (nullptr == arg0) + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgePolygon:create"); + if (nullptr == arg1) { - LUA_PRECONDITION(arg0, "Invalid Native Object"); + LUA_PRECONDITION(arg1, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapeEdgePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderEdgePolygon:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgePolygon* ret = ax::PhysicsShapeEdgePolygon::create(arg0, arg1, arg2); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgePolygon", - (ax::PhysicsShapeEdgePolygon*)ret); + ax::PhysicsColliderEdgePolygon* ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2, arg3); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon", + (ax::PhysicsColliderEdgePolygon*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; - double arg3; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; + double arg4; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgePolygon:create"); - if (nullptr == arg0) + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgePolygon:create"); + if (nullptr == arg1) { - LUA_PRECONDITION(arg0, "Invalid Native Object"); + LUA_PRECONDITION(arg1, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapeEdgePolygon:create"); - ok &= luaval_to_number(tolua_S, 4, &arg3, "ax.PhysicsShapeEdgePolygon:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderEdgePolygon:create"); + ok &= luaval_to_number(tolua_S, 5, &arg4, "ax.PhysicsColliderEdgePolygon:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgePolygon* ret = ax::PhysicsShapeEdgePolygon::create(arg0, arg1, arg2, arg3); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgePolygon", - (ax::PhysicsShapeEdgePolygon*)ret); + ax::PhysicsColliderEdgePolygon* ret = ax::PhysicsColliderEdgePolygon::create(arg0, arg1, arg2, arg3, arg4); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgePolygon", + (ax::PhysicsColliderEdgePolygon*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "create", argc, 2); return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeEdgePolygon_create'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderEdgePolygon_create'.", &tolua_err); # endif return 0; } -int axlua_physics_PhysicsShapeEdgeChain_create(lua_State* tolua_S) +int axlua_physics_PhysicsColliderEdgeChain_create(lua_State* tolua_S) { int argc = 0; bool ok = true; @@ -1540,92 +1484,101 @@ int axlua_physics_PhysicsShapeEdgeChain_create(lua_State* tolua_S) # endif # if _AX_DEBUG >= 1 - if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsShapeEdgeChain", 0, &tolua_err)) + if (!tolua_isusertable(tolua_S, 1, "ax.PhysicsColliderEdgeChain", 0, &tolua_err)) goto tolua_lerror; # endif argc = lua_gettop(tolua_S) - 1; - if (argc == 1) + if (argc == 2) { - ax::Vec2* arg0; - int arg1 = 0; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgeChain:create"); - if (nullptr == arg0) + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgeChain:create"); + if (nullptr == arg1) { - LUA_PRECONDITION(arg0, "Invalid Native Object"); + LUA_PRECONDITION(arg1, "Invalid Native Object"); } } while (0); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgeChain* ret = ax::PhysicsShapeEdgeChain::create(arg0, arg1); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeChain", - (ax::PhysicsShapeEdgeChain*)ret); + ax::PhysicsColliderEdgeChain* ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain", + (ax::PhysicsColliderEdgeChain*)ret); return 1; } - if (argc == 2) + if (argc == 3) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgeChain:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgeChain:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapeEdgeChain:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderEdgeChain:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgeChain* ret = ax::PhysicsShapeEdgeChain::create(arg0, arg1, arg2); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeChain", - (ax::PhysicsShapeEdgeChain*)ret); + ax::PhysicsColliderEdgeChain* ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2, arg3); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain", + (ax::PhysicsColliderEdgeChain*)ret); return 1; } - if (argc == 3) + if (argc == 4) { - ax::Vec2* arg0; - int arg1 = 0; - ax::PhysicsMaterial arg2; - double arg3; + ax::PhysicsBody* arg0; + ax::Vec2* arg1; + int arg2 = 0; + ax::PhysicsMaterial arg3; + double arg4; do { - ok = luaval_to_array_of_vec2(tolua_S, 2, &arg0, &arg1, "ax.PhysicsShapeEdgeChain:create"); + ok &= luaval_to_object(tolua_S, 2, "ax.PhysicsBody", &arg0, + "ax.PhysicsColliderEdgePolygon:create"); + ok = luaval_to_array_of_vec2(tolua_S, 3, &arg1, &arg2, "ax.PhysicsColliderEdgeChain:create"); if (nullptr == arg0) { LUA_PRECONDITION(arg0, "Invalid Native Object"); } } while (0); - ok &= luaval_to_physics_material(tolua_S, 3, &arg2, "ax.PhysicsShapeEdgeChain:create"); - ok &= luaval_to_number(tolua_S, 4, &arg3, "ax.PhysicsShapeEdgeChain:create"); + ok &= luaval_to_physics_material(tolua_S, 4, &arg3, "ax.PhysicsColliderEdgeChain:create"); + ok &= luaval_to_number(tolua_S, 5, &arg4, "ax.PhysicsColliderEdgeChain:create"); if (!ok) { - AX_SAFE_DELETE_ARRAY(arg0); + AX_SAFE_DELETE_ARRAY(arg1); return 0; } - ax::PhysicsShapeEdgeChain* ret = ax::PhysicsShapeEdgeChain::create(arg0, arg1, arg2, arg3); - AX_SAFE_DELETE_ARRAY(arg0); - object_to_luaval(tolua_S, "ax.PhysicsShapeEdgeChain", - (ax::PhysicsShapeEdgeChain*)ret); + ax::PhysicsColliderEdgeChain* ret = ax::PhysicsColliderEdgeChain::create(arg0, arg1, arg2, arg3, arg4); + AX_SAFE_DELETE_ARRAY(arg1); + object_to_luaval(tolua_S, "ax.PhysicsColliderEdgeChain", + (ax::PhysicsColliderEdgeChain*)ret); return 1; } luaL_error(tolua_S, "%s has wrong number of arguments: %d, was expecting %d\n ", "create", argc, 2); return 0; # if _AX_DEBUG >= 1 tolua_lerror: - tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsShapeEdgeChain_create'.", &tolua_err); + tolua_error(tolua_S, "#ferror in function 'axlua_physics_PhysicsColliderEdgeChain_create'.", &tolua_err); # endif return 0; } @@ -1651,83 +1604,80 @@ int register_all_ax_physics_manual(lua_State* tolua_S) } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShape"); + lua_pushstring(tolua_S, "ax.PhysicsCollider"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "recenterPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShape_recenterPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsCollider_recenterPoints); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "getPolygonCenter"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShape_getPolygonCenter); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsCollider_getPolygonCenter); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "getPolyonCenter"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShape_getPolygonCenter); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsCollider_getPolygonCenter); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShapeBox"); + lua_pushstring(tolua_S, "ax.PhysicsColliderBox"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "getPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeBox_getPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderBox_getPoints); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShapeEdgeBox"); + lua_pushstring(tolua_S, "ax.PhysicsColliderEdgeBox"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "getPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeEdgeBox_getPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderEdgeBox_getPoints); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShapePolygon"); + lua_pushstring(tolua_S, "ax.PhysicsColliderPolygon"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "getPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapePolygon_getPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderPolygon_getPoints); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "create"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapePolygon_create); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderPolygon_create); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "calculateArea"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapePolygon_calculateArea); - lua_rawset(tolua_S, -3); - lua_pushstring(tolua_S, "calculateMoment"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapePolygon_calculateMoment); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderPolygon_calculateArea); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShapeEdgePolygon"); + lua_pushstring(tolua_S, "ax.PhysicsColliderEdgePolygon"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "getPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeEdgePolygon_getPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderEdgePolygon_getPoints); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "create"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeEdgePolygon_create); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderEdgePolygon_create); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); - lua_pushstring(tolua_S, "ax.PhysicsShapeEdgeChain"); + lua_pushstring(tolua_S, "ax.PhysicsColliderEdgeChain"); lua_rawget(tolua_S, LUA_REGISTRYINDEX); if (lua_istable(tolua_S, -1)) { lua_pushstring(tolua_S, "getPoints"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeEdgeChain_getPoints); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderEdgeChain_getPoints); lua_rawset(tolua_S, -3); lua_pushstring(tolua_S, "create"); - lua_pushcfunction(tolua_S, axlua_physics_PhysicsShapeEdgeChain_create); + lua_pushcfunction(tolua_S, axlua_physics_PhysicsColliderEdgeChain_create); lua_rawset(tolua_S, -3); } lua_pop(tolua_S, 1); diff --git a/extensions/scripting/lua-bindings/manual/physics3d/axlua_physics3d_manual.cpp b/extensions/scripting/lua-bindings/manual/physics3d/axlua_physics3d_manual.cpp index 0583ac7ce9b6..2aa53722465d 100644 --- a/extensions/scripting/lua-bindings/manual/physics3d/axlua_physics3d_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/physics3d/axlua_physics3d_manual.cpp @@ -23,15 +23,15 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" -#include "base/Config.h" +#include "axmol/platform/PlatformConfig.h" +#include "axmol/base/Config.h" #if defined(AX_ENABLE_3D_PHYSICS) # include "lua-bindings/manual/physics3d/axlua_physics3d_manual.h" # include "lua-bindings/auto/axlua_physics3d_auto.hpp" # include "lua-bindings/manual/tolua_fix.h" # include "lua-bindings/manual/LuaBasicConversions.h" # include "lua-bindings/manual/LuaEngine.h" -# include "physics3d/Physics3D.h" +# include "axmol/physics3d/Physics3D.h" bool luaval_to_Physics3DRigidBodyDes(lua_State* L, int lo, diff --git a/extensions/scripting/lua-bindings/manual/platform/android/LuaJavaBridge.cpp b/extensions/scripting/lua-bindings/manual/platform/android/LuaJavaBridge.cpp index 801ad942c3a3..45f00c9e2f7b 100644 --- a/extensions/scripting/lua-bindings/manual/platform/android/LuaJavaBridge.cpp +++ b/extensions/scripting/lua-bindings/manual/platform/android/LuaJavaBridge.cpp @@ -24,9 +24,9 @@ #include "LuaJavaBridge.h" #if defined(__ANDROID__) -# include "platform/android/jni/JniHelper.h" +# include "axmol/platform/android/jni/JniHelper.h" # include -# include "base/UTF8.h" +# include "axmol/base/text_utils.h" # define LOG_TAG "luajc" # define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) @@ -67,7 +67,7 @@ bool LuaJavaBridge::CallInfo::execute() { m_retjs = (jstring)m_env->CallStaticObjectMethod(m_classID, m_methodID); bool bValidStr = true; - std::string strValue = ax::StringUtils::getStringUTFCharsJNI(m_env, m_retjs, &bValidStr); + std::string strValue = ax::text_utils::getStringUTFCharsJNI(m_env, m_retjs, &bValidStr); m_ret.stringValue = (false == bValidStr) ? nullptr : new string(strValue); break; } @@ -113,7 +113,7 @@ bool LuaJavaBridge::CallInfo::executeWithArgs(jvalue* args) { m_retjs = (jstring)m_env->CallStaticObjectMethodA(m_classID, m_methodID, args); bool bValidStr = true; - std::string strValue = ax::StringUtils::getStringUTFCharsJNI(m_env, m_retjs, &bValidStr); + std::string strValue = ax::text_utils::getStringUTFCharsJNI(m_env, m_retjs, &bValidStr); m_ret.stringValue = (false == bValidStr) ? nullptr : new string(strValue); break; } diff --git a/extensions/scripting/lua-bindings/manual/platform/android/jni/LuaBridge.cpp b/extensions/scripting/lua-bindings/manual/platform/android/jni/LuaBridge.cpp index f11d7f17d57b..98909afb3a66 100644 --- a/extensions/scripting/lua-bindings/manual/platform/android/jni/LuaBridge.cpp +++ b/extensions/scripting/lua-bindings/manual/platform/android/jni/LuaBridge.cpp @@ -29,7 +29,7 @@ # include "lua-bindings/manual/platform/android/LuaJavaBridge.h" -# include "base/UTF8.h" +# include "axmol/base/text_utils.h" # define LOG_TAG "LuaBridge_java" # define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__) @@ -41,7 +41,7 @@ JNIEXPORT jint JNICALL Java_dev_axmol_lib_LuaBridge_callLuaFunctionWithString(JN jint functionId, jstring value) { - std::string strValue = ax::StringUtils::getStringUTFCharsJNI(env, value); + std::string strValue = ax::text_utils::getStringUTFCharsJNI(env, value); int ret = LuaJavaBridge::callLuaFunctionById(functionId, strValue.c_str()); return ret; } @@ -52,8 +52,8 @@ Java_dev_axmol_lib_LuaBridge_callLuaGlobalFunctionWithString(JNIEnv* env, jstring luaFunctionName, jstring value) { - std::string functionNameStr = ax::StringUtils::getStringUTFCharsJNI(env, luaFunctionName); - std::string valueStr = ax::StringUtils::getStringUTFCharsJNI(env, value); + std::string functionNameStr = ax::text_utils::getStringUTFCharsJNI(env, luaFunctionName); + std::string valueStr = ax::text_utils::getStringUTFCharsJNI(env, value); int ret = LuaJavaBridge::callLuaGlobalFunction(functionNameStr.c_str(), valueStr.c_str()); return ret; diff --git a/extensions/scripting/lua-bindings/manual/tolua_fix.cpp b/extensions/scripting/lua-bindings/manual/tolua_fix.cpp index a1e0ab7deded..91e74c1ec02e 100644 --- a/extensions/scripting/lua-bindings/manual/tolua_fix.cpp +++ b/extensions/scripting/lua-bindings/manual/tolua_fix.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include "lua-bindings/manual/tolua_fix.h" -#include "base/Object.h" +#include "axmol/base/Object.h" #include "lua-bindings/manual/LuaBasicConversions.h" #include diff --git a/extensions/scripting/lua-bindings/manual/ui/axlua_ui_manual.cpp b/extensions/scripting/lua-bindings/manual/ui/axlua_ui_manual.cpp index 3578c7e8fb2e..ea8e1a110ec1 100644 --- a/extensions/scripting/lua-bindings/manual/ui/axlua_ui_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/ui/axlua_ui_manual.cpp @@ -51,9 +51,9 @@ #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/base/LuaScriptHandlerMgr.h" #include "lua-bindings/manual/LuaValue.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" #include "lua-bindings/manual/LuaEngine.h" -#include "base/EventListenerFocus.h" +#include "axmol/base/EventListenerFocus.h" using namespace ui; diff --git a/extensions/scripting/lua-bindings/manual/ui/axlua_video_manual.cpp b/extensions/scripting/lua-bindings/manual/ui/axlua_video_manual.cpp index 1540e4f05620..22b2672f768a 100644 --- a/extensions/scripting/lua-bindings/manual/ui/axlua_video_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/ui/axlua_video_manual.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include "lua-bindings/manual/ui/axlua_video_manual.hpp" -#include "ui/UIMediaPlayer.h" +#include "axmol/ui/UIMediaPlayer.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/LuaValue.h" diff --git a/extensions/scripting/lua-bindings/manual/ui/axlua_webview_manual.cpp b/extensions/scripting/lua-bindings/manual/ui/axlua_webview_manual.cpp index 93892f2f95f5..30e9effd3766 100644 --- a/extensions/scripting/lua-bindings/manual/ui/axlua_webview_manual.cpp +++ b/extensions/scripting/lua-bindings/manual/ui/axlua_webview_manual.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "lua-bindings/manual/ui/axlua_webview_manual.hpp" -#include "ui/UIWebView/UIWebView.h" +#include "axmol/ui/UIWebView/UIWebView.h" #include "lua-bindings/manual/tolua_fix.h" #include "lua-bindings/manual/LuaBasicConversions.h" #include "lua-bindings/manual/LuaValue.h" diff --git a/extensions/scripting/lua-bindings/proj.android/CMakeLists.txt b/extensions/scripting/lua-bindings/proj.android/CMakeLists.txt index 78eb0b5e46b9..4aca3e12bff7 100644 --- a/extensions/scripting/lua-bindings/proj.android/CMakeLists.txt +++ b/extensions/scripting/lua-bindings/proj.android/CMakeLists.txt @@ -21,7 +21,7 @@ target_include_directories(${target_name} PRIVATE ../manual/platform/android PRIVATE ${lua_header} PRIVATE ${tolua_header} - PRIVATE ../../../../core + PRIVATE ../../../../axmol PRIVATE ../../../../3rdparty PRIVATE ../../../../3rdparty/fmt/include PRIVATE ../../../../3rdparty/robin-map/include diff --git a/extensions/scripting/lua-bindings/script/3d/3dConstants.lua b/extensions/scripting/lua-bindings/script/3d/3dConstants.lua index cd0d6022c390..9e079b6af81f 100644 --- a/extensions/scripting/lua-bindings/script/3d/3dConstants.lua +++ b/extensions/scripting/lua-bindings/script/3d/3dConstants.lua @@ -1,14 +1,14 @@ -if nil == cc.Terrain then +if nil == ax.Terrain then return end -cc.Terrain.CrackFixedType = +ax.Terrain.CrackFixedType = { - SKIRT = 0, + SKIRT = 0, INCREASE_LOWER = 1, } -cc.Animate3DQuality = +ax.Animate3DQuality = { QUALITY_NONE = 0, QUALITY_LOW = 1, diff --git a/extensions/scripting/lua-bindings/script/cocostudio/CocoStudio.lua b/extensions/scripting/lua-bindings/script/cocostudio/CocoStudio.lua index 5e98195c2bd0..ed6b78819083 100644 --- a/extensions/scripting/lua-bindings/script/cocostudio/CocoStudio.lua +++ b/extensions/scripting/lua-bindings/script/cocostudio/CocoStudio.lua @@ -376,7 +376,7 @@ function ccs.TriggerMng:isEmpty() end function __onParseConfig(configType,jasonStr) - if configType == cc.ConfigType.COCOSTUDIO then + if configType == ax.ConfigType.COCOSTUDIO then ccs.TriggerMng.getInstance():parse(jasonStr) end end diff --git a/extensions/scripting/lua-bindings/script/controller/ControllerConstants.lua b/extensions/scripting/lua-bindings/script/controller/ControllerConstants.lua index 730e92afadc7..6f0a7dddd566 100644 --- a/extensions/scripting/lua-bindings/script/controller/ControllerConstants.lua +++ b/extensions/scripting/lua-bindings/script/controller/ControllerConstants.lua @@ -1,7 +1,7 @@ -cc = cc or {} +ax = ax or {} -cc.ControllerKey = +ax.ControllerKey = { JOYSTICK_LEFT_X = 1000, JOYSTICK_LEFT_Y = 1001, diff --git a/extensions/scripting/lua-bindings/script/core/Axmol.lua b/extensions/scripting/lua-bindings/script/core/Axmol.lua index 08d1be92b392..af9a7a9a4e34 100644 --- a/extensions/scripting/lua-bindings/script/core/Axmol.lua +++ b/extensions/scripting/lua-bindings/script/core/Axmol.lua @@ -1,5 +1,5 @@ -cc = cc or {} +ax = ax or {} -- Native vec2_new use array[2] to store x,y w,h u,v performance is better -- p[1] alias: x w u width @@ -8,7 +8,7 @@ local nvec2 = vec2_new local nvec3 = vec3_new local nvec4 = vec4_new -function cc.clampf(value, min_inclusive, max_inclusive) +function ax.clampf(value, min_inclusive, max_inclusive) -- body local temp = 0 if min_inclusive > max_inclusive then @@ -27,7 +27,7 @@ function cc.clampf(value, min_inclusive, max_inclusive) end --Vec2/Point -function cc.vec2(_x, _y) +function ax.vec2(_x, _y) if nil == _y then return nvec2(_x.x, _x.y) else @@ -35,59 +35,59 @@ function cc.vec2(_x, _y) end end -function cc.p(_x, ...) - return cc.vec2(_x, ...) +function ax.p(_x, ...) + return ax.vec2(_x, ...) end -function cc.pAdd(pt1,pt2) - return cc.p(pt1.x + pt2.x , pt1.y + pt2.y ) +function ax.pAdd(pt1,pt2) + return ax.p(pt1.x + pt2.x , pt1.y + pt2.y ) end -function cc.pSub(pt1,pt2) - return cc.p(pt1.x - pt2.x , pt1.y - pt2.y ) +function ax.pSub(pt1,pt2) + return ax.p(pt1.x - pt2.x , pt1.y - pt2.y ) end -function cc.pMul(pt1,factor) - return cc.p( pt1.x * factor , pt1.y * factor ) +function ax.pMul(pt1,factor) + return ax.p( pt1.x * factor , pt1.y * factor ) end -function cc.pMidpoint(pt1,pt2) - return cc.p( (pt1.x + pt2.x) / 2.0 , ( pt1.y + pt2.y) / 2.0 ) +function ax.pMidpoint(pt1,pt2) + return ax.p( (pt1.x + pt2.x) / 2.0 , ( pt1.y + pt2.y) / 2.0 ) end -function cc.pForAngle(a) - return cc.p( math.cos(a), math.sin(a) ) +function ax.pForAngle(a) + return ax.p( math.cos(a), math.sin(a) ) end -function cc.pGetLength(pt) +function ax.pGetLength(pt) return math.sqrt( pt.x * pt.x + pt.y * pt.y ) end -function cc.pNormalize(pt) - local length = cc.pGetLength(pt) +function ax.pNormalize(pt) + local length = ax.pGetLength(pt) if 0 == length then - return cc.p( 1.0, 0.0 ) + return ax.p( 1.0, 0.0 ) end - return cc.p( pt.x / length, pt.y / length ) + return ax.p( pt.x / length, pt.y / length ) end -function cc.pCross(self,other) +function ax.pCross(self,other) return self.x * other.y - self.y * other.x end -function cc.pDot(self,other) +function ax.pDot(self,other) return self.x * other.x + self.y * other.y end -function cc.pToAngleSelf(self) +function ax.pToAngleSelf(self) return math.atan2(self.y, self.x) end -function cc.pGetAngle(self,other) - local a2 = cc.pNormalize(self) - local b2 = cc.pNormalize(other) - local angle = math.atan2(cc.pCross(a2, b2), cc.pDot(a2, b2) ) +function ax.pGetAngle(self,other) + local a2 = ax.pNormalize(self) + local b2 = ax.pNormalize(other) + local angle = math.atan2(ax.pCross(a2, b2), ax.pDot(a2, b2) ) if math.abs(angle) < 1.192092896e-7 then return 0.0 end @@ -95,11 +95,11 @@ function cc.pGetAngle(self,other) return angle end -function cc.pGetDistance(startP,endP) - return cc.pGetLength(cc.pSub(startP,endP)) +function ax.pGetDistance(startP,endP) + return ax.pGetLength(ax.pSub(startP,endP)) end -function cc.pIsLineIntersect(A, B, C, D, s, t) +function ax.pIsLineIntersect(A, B, C, D, s, t) if ((A.x == B.x) and (A.y == B.y)) or ((C.x == D.x) and (C.y == D.y))then return false, s, t end @@ -129,47 +129,47 @@ function cc.pIsLineIntersect(A, B, C, D, s, t) return true,s,t end -function cc.pPerp(pt) - return cc.p( -pt.y, pt.x ) +function ax.pPerp(pt) + return ax.p( -pt.y, pt.x ) end -function cc.RPerp(pt) - return cc.p( pt.y, -pt.x ) +function ax.RPerp(pt) + return ax.p( pt.y, -pt.x ) end -function cc.pProject(pt1, pt2) - return cc.p( pt2.x * (cc.pDot(pt1,pt2) / cc.pDot(pt2,pt2)) , pt2.y * (cc.pDot(pt1,pt2) / cc.pDot(pt2,pt2)) ) +function ax.pProject(pt1, pt2) + return ax.p( pt2.x * (ax.pDot(pt1,pt2) / ax.pDot(pt2,pt2)) , pt2.y * (ax.pDot(pt1,pt2) / ax.pDot(pt2,pt2)) ) end -function cc.pRotate(pt1, pt2) - return cc.p( pt1.x * pt2.x - pt1.y * pt2.y, pt1.x * pt2.y + pt1.y * pt2.x ) +function ax.pRotate(pt1, pt2) + return ax.p( pt1.x * pt2.x - pt1.y * pt2.y, pt1.x * pt2.y + pt1.y * pt2.x ) end -function cc.pUnrotate(pt1, pt2) - return cc.p( pt1.x * pt2.x + pt1.y * pt2.y, pt1.y * pt2.x - pt1.x * pt2.y ) +function ax.pUnrotate(pt1, pt2) + return ax.p( pt1.x * pt2.x + pt1.y * pt2.y, pt1.y * pt2.x - pt1.x * pt2.y ) end --Calculates the square length of pt -function cc.pLengthSQ(pt) - return cc.pDot(pt,pt) +function ax.pLengthSQ(pt) + return ax.pDot(pt,pt) end --Calculates the square distance between pt1 and pt2 -function cc.pDistanceSQ(pt1,pt2) - return cc.pLengthSQ(cc.pSub(pt1,pt2)) +function ax.pDistanceSQ(pt1,pt2) + return ax.pLengthSQ(ax.pSub(pt1,pt2)) end -function cc.pGetClampPoint(pt1,pt2,pt3) - return cc.p( cc.clampf(pt1.x, pt2.x, pt3.x), cc.clampf(pt1.y, pt2.y, pt3.y) ) +function ax.pGetClampPoint(pt1,pt2,pt3) + return ax.p( ax.clampf(pt1.x, pt2.x, pt3.x), ax.clampf(pt1.y, pt2.y, pt3.y) ) end -function cc.pFromSize(sz) - return cc.p( sz.width, sz.height ) +function ax.pFromSize(sz) + return ax.p( sz.width, sz.height ) end -function cc.pLerp(pt1,pt2,alpha) - return cc.pAdd(cc.pMul(pt1, 1.0 - alpha), cc.pMul(pt2,alpha) ) +function ax.pLerp(pt1,pt2,alpha) + return ax.pAdd(ax.pMul(pt1, 1.0 - alpha), ax.pMul(pt2,alpha) ) end -function cc.pFuzzyEqual(pt1,pt2,variance) +function ax.pFuzzyEqual(pt1,pt2,variance) if (pt1.x - variance <= pt2.x) and (pt2.x <= pt1.x + variance) and (pt1.y - variance <= pt2.y) and (pt2.y <= pt1.y + variance) then return true else @@ -177,13 +177,13 @@ function cc.pFuzzyEqual(pt1,pt2,variance) end end -function cc.pRotateByAngle(pt1, pt2, angle) - return cc.pAdd(pt2, cc.pRotate( cc.pSub(pt1, pt2),cc.pForAngle(angle))) +function ax.pRotateByAngle(pt1, pt2, angle) + return ax.pAdd(pt2, ax.pRotate( ax.pSub(pt1, pt2),ax.pForAngle(angle))) end -function cc.pIsSegmentIntersect(pt1,pt2,pt3,pt4) +function ax.pIsSegmentIntersect(pt1,pt2,pt3,pt4) local s,t,ret = 0,0,false - ret,s,t =cc.pIsLineIntersect(pt1, pt2, pt3, pt4,s,t) + ret,s,t =ax.pIsLineIntersect(pt1, pt2, pt3, pt4,s,t) if ret and s >= 0.0 and s <= 1.0 and t >= 0.0 and t <= 1.0 then return true @@ -192,26 +192,26 @@ function cc.pIsSegmentIntersect(pt1,pt2,pt3,pt4) return false end -function cc.pGetIntersectPoint(pt1,pt2,pt3,pt4) +function ax.pGetIntersectPoint(pt1,pt2,pt3,pt4) local s,t, ret = 0,0,false - ret,s,t = cc.pIsLineIntersect(pt1,pt2,pt3,pt4,s,t) + ret,s,t = ax.pIsLineIntersect(pt1,pt2,pt3,pt4,s,t) if ret then - return cc.p(pt1.x + s * (pt2.x - pt1.x), pt1.y + s * (pt2.y - pt1.y)) + return ax.p(pt1.x + s * (pt2.x - pt1.x), pt1.y + s * (pt2.y - pt1.y)) else - return cc.p(0,0) + return ax.p(0,0) end end --Size -function cc.size( _width,_height ) - return cc.p(_width, _height) +function ax.size( _width,_height ) + return ax.p(_width, _height) end --Rect -function cc.rect(_x,_y,_width,_height) +function ax.rect(_x,_y,_width,_height) return { x = _x, y = _y, width = _width, height = _height } end -function cc.rectEqualToRect(rect1,rect2) +function ax.rectEqualToRect(rect1,rect2) if ((rect1.x >= rect2.x) or (rect1.y >= rect2.y) or ( rect1.x + rect1.width <= rect2.x + rect2.width) or ( rect1.y + rect1.height <= rect2.y + rect2.height)) then @@ -221,31 +221,31 @@ function cc.rectEqualToRect(rect1,rect2) return true end -function cc.rectGetMaxX(rect) +function ax.rectGetMaxX(rect) return rect.x + rect.width end -function cc.rectGetMidX(rect) +function ax.rectGetMidX(rect) return rect.x + rect.width / 2.0 end -function cc.rectGetMinX(rect) +function ax.rectGetMinX(rect) return rect.x end -function cc.rectGetMaxY(rect) +function ax.rectGetMaxY(rect) return rect.y + rect.height end -function cc.rectGetMidY(rect) +function ax.rectGetMidY(rect) return rect.y + rect.height / 2.0 end -function cc.rectGetMinY(rect) +function ax.rectGetMinY(rect) return rect.y end -function cc.rectContainsPoint( rect, point ) +function ax.rectContainsPoint( rect, point ) local ret = false if (point.x >= rect.x) and (point.x <= rect.x + rect.width) and @@ -256,7 +256,7 @@ function cc.rectContainsPoint( rect, point ) return ret end -function cc.rectIntersectsRect( rect1, rect2 ) +function ax.rectIntersectsRect( rect1, rect2 ) local intersect = not ( rect1.x > rect2.x + rect2.width or rect1.x + rect1.width < rect2.x or rect1.y > rect2.y + rect2.height or @@ -265,8 +265,8 @@ function cc.rectIntersectsRect( rect1, rect2 ) return intersect end -function cc.rectUnion( rect1, rect2 ) - local rect = cc.rect(0, 0, 0, 0) +function ax.rectUnion( rect1, rect2 ) + local rect = ax.rect(0, 0, 0, 0) rect.x = math.min(rect1.x, rect2.x) rect.y = math.min(rect1.y, rect2.y) rect.width = math.max(rect1.x + rect1.width, rect2.x + rect2.width) - rect.x @@ -274,8 +274,8 @@ function cc.rectUnion( rect1, rect2 ) return rect end -function cc.rectIntersection( rect1, rect2 ) - local intersection = cc.rect( +function ax.rectIntersection( rect1, rect2 ) + local intersection = ax.rect( math.max(rect1.x, rect2.x), math.max(rect1.y, rect2.y), 0, 0) @@ -285,27 +285,32 @@ function cc.rectIntersection( rect1, rect2 ) return intersection end ---Color3B -function cc.c3b( _r,_g,_b ) - return { r = _r, g = _g, b = _b } +-- Color32 deprecated, use ax.color32 instead +function ax.color32( _r,_g,_b,_a ) + return { r = _r, g = _g, b = _b, a = _a } end ---Color4B -function cc.c4b( _r,_g,_b,_a ) +-- ax::Color deprecated, use ax.color instead +function ax.c4f( _r,_g,_b,_a ) return { r = _r, g = _g, b = _b, a = _a } end ---Color4F -function cc.c4f( _r,_g,_b,_a ) - return { r = _r, g = _g, b = _b, a = _a } +-- Color32 +function ax.color32( _r,_g,_b,_a ) + return { r = _r, g = _g, b = _b, a = _a or 255 } +end + +-- Color +function ax.color( _r,_g,_b,_a ) + return { r = _r, g = _g, b = _b, a = _a or 1.0 } end local function isFloatColor(c) return (c.r <= 1 and c.g <= 1 and c.b <= 1) and (math.ceil(c.r) ~= c.r or math.ceil(c.g) ~= c.g or math.ceil(c.b) ~= c.b) end -function cc.convertColor(input, typ) - assert(type(input) == "table" and input.r and input.g and input.b, "cc.convertColor() - invalid input color") +function ax.convertColor(input, typ) + assert(type(input) == "table" and input.r and input.g and input.b, "ax.convertColor() - invalid input color") local ret if typ == "3b" then if isFloatColor(input) then @@ -344,112 +349,97 @@ function cc.convertColor(input, typ) ret.a = 255 end else - error(string.format("cc.convertColor() - invalid type %s", typ), 0) + error(string.format("ax.convertColor() - invalid type %s", typ), 0) end return ret end --Vertex2F -function cc.vertex2F(_x,_y) - return cc.vec2(_x, _y ) +function ax.vertex2F(_x,_y) + return ax.vec2(_x, _y ) end --Vertex3F -function cc.Vertex3F(_x,_y,_z) - return cc.vec3(_x, _y, _z) +function ax.Vertex3F(_x,_y,_z) + return ax.vec3(_x, _y, _z) end --Tex2F -function cc.tex2F(_u,_v) - return cc.vec2( _u, _v ) +function ax.tex2F(_u,_v) + return ax.vec2( _u, _v ) end --PointSprite -function cc.PointSprite(_pos,_color,_size) +function ax.PointSprite(_pos,_color,_size) return { pos = _pos, color = _color, size = _size } end --Quad2 -function cc.Quad2(_tl,_tr,_bl,_br) +function ax.Quad2(_tl,_tr,_bl,_br) return { tl = _tl, tr = _tr, bl = _bl, br = _br } end --Quad3 -function cc.Quad3(_tl, _tr, _bl, _br) +function ax.Quad3(_tl, _tr, _bl, _br) return { tl = _tl, tr = _tr, bl = _bl, br = _br } end ---V2F_C4B_T2F -function cc.V2F_C4B_T2F(_vertices, _colors, _texCoords) - return { vertices = _vertices, colors = _colors, texCoords = _texCoords } -end - ---V2F_C4F_T2F -function cc.V2F_C4F_T2F(_vertices, _colors, _texCoords) +--V2F_T2F_C4F +function ax.V2F_T2F_C4F(_vertices, _colors, _texCoords) return { vertices = _vertices, colors = _colors, texCoords = _texCoords } end ---V3F_C4B_T2F -function cc.V3F_C4B_T2F(_vertices, _colors, _texCoords) +--V3F_T2F_C4F +function ax.V3F_T2F_C4F(_vertices, _colors, _texCoords) return { vertices = _vertices, colors = _colors, texCoords = _texCoords } end ---V2F_C4B_T2F_Quad -function cc.V2F_C4B_T2F_Quad(_bl, _br, _tl, _tr) - return { bl = _bl, br = _br, tl = _tl, tr = _tr } -end - ---V3F_C4B_T2F_Quad -function cc.V3F_C4B_T2F_Quad(_tl, _bl, _tr, _br) +--V3F_T2F_C4F_Quad +function ax.V3F_T2F_C4F_Quad(_tl, _bl, _tr, _br) return { tl = _tl, bl = _bl, tr = _tr, br = _br } end ---V2F_C4F_T2F_Quad -function cc.V2F_C4F_T2F_Quad(_bl, _br, _tl, _tr) - return { bl = _bl, br = _br, tl = _tl, tr = _tr } -end - --T2F_Quad -function cc.T2F_Quad(_bl, _br, _tl, _tr) +function ax.T2F_Quad(_bl, _br, _tl, _tr) return { bl = _bl, br = _br, tl = _tl, tr = _tr } end --AnimationFrameData -function cc.AnimationFrameData( _texCoords, _delay, _size) +function ax.AnimationFrameData( _texCoords, _delay, _size) return { texCoords = _texCoords, delay = _delay, size = _size } end --PhysicsMaterial -function cc.PhysicsMaterial(_density, _restitution, _friction) +function ax.PhysicsMaterial(_density, _restitution, _friction) return { density = _density, restitution = _restitution, friction = _friction } end -function cc.vec3(_x, _y, _z) +function ax.vec3(_x, _y, _z) return nvec3( _x, _y, _z) end -function cc.vec4(_x, _y, _z, _w) +function ax.vec4(_x, _y, _z, _w) return nvec4( _x, _y, _z, _w ) end -function cc.vec3add(vec3a, vec3b) - return cc.vec3( vec3a.x + vec3b.x, vec3a.y + vec3b.y, vec3a.z + vec3b.z) +function ax.vec3add(vec3a, vec3b) + return ax.vec3( vec3a.x + vec3b.x, vec3a.y + vec3b.y, vec3a.z + vec3b.z) end -function cc.vec3sub(vec3a, vec3b) - return cc.vec3( vec3a.x - vec3b.x, vec3a.y - vec3b.y, vec3a.z - vec3b.z) +function ax.vec3sub(vec3a, vec3b) + return ax.vec3( vec3a.x - vec3b.x, vec3a.y - vec3b.y, vec3a.z - vec3b.z) end -function cc.vec3mul(vec3, factor) - return cc.vec3( vec3.x * factor, vec3.y * factor, vec3.z * factor) +function ax.vec3mul(vec3, factor) + return ax.vec3( vec3.x * factor, vec3.y * factor, vec3.z * factor) end -function cc.vec3dot(vec3a, vec3b) +function ax.vec3dot(vec3a, vec3b) return vec3a.x * vec3b.x + vec3a.y * vec3b.y + vec3a.z * vec3b.z end -function cc.vec3normalize(vec3) - local n = cc.vec3dot(vec3, vec3) +function ax.vec3normalize(vec3) + local n = ax.vec3dot(vec3, vec3) if n == 1.0 then return vec3 end @@ -460,21 +450,21 @@ function cc.vec3normalize(vec3) return vec3 end - return cc.vec3mul(vec3, 1.0/n) + return ax.vec3mul(vec3, 1.0/n) end -function cc.quaternion(_x, _y ,_z,_w) - return cc.vec4(_x, _y, _z, _w) +function ax.quaternion(_x, _y ,_z,_w) + return ax.vec4(_x, _y, _z, _w) end -function cc.quaternion_createFromAxisAngle(axis, angle) +function ax.quaternion_createFromAxisAngle(axis, angle) local halfAngle = angle * 0.5 local sinHalfAngle = math.sin(halfAngle) - local normal = cc.vec3(axis.x, axis.y, axis.z) - normal = cc.vec3normalize(normal) - local dst = cc.vec3(0.0, 0.0, 0.0) + local normal = ax.vec3(axis.x, axis.y, axis.z) + normal = ax.vec3normalize(normal) + local dst = ax.vec3(0.0, 0.0, 0.0) dst.x = normal.x * sinHalfAngle dst.y = normal.y * sinHalfAngle dst.z = normal.z * sinHalfAngle @@ -483,13 +473,13 @@ function cc.quaternion_createFromAxisAngle(axis, angle) return dst end -function cc.blendFunc(_src, _dst) +function ax.blendFunc(_src, _dst) return {src = _src, dst = _dst} end -cc.mat4 = cc.mat4 or {} +ax.mat4 = ax.mat4 or {} -function cc.mat4.new(...) +function ax.mat4.new(...) local params = {...} local size = #params local obj = {} @@ -509,50 +499,50 @@ function cc.mat4.new(...) end end - setmetatable(obj, {__index = cc.mat4}) + setmetatable(obj, {__index = ax.mat4}) return obj end -function cc.mat4.getInversed(self) +function ax.mat4.getInversed(self) return mat4_getInversed(self) end -function cc.mat4.transformVector(...) +function ax.mat4.transformVector(...) return mat4_transformVector(...) end -function cc.mat4.multiply(self, mat) +function ax.mat4.multiply(self, mat) return mat4_multiply(self, mat) end -function cc.mat4.decompose(self, scale, rotation, translation) +function ax.mat4.decompose(self, scale, rotation, translation) return mat4_decompose(self, scale ,rotation, translation) end -function cc.mat4.createIdentity() - return cc.mat4.new(1.0 ,0.0, 0.0, 0.0, +function ax.mat4.createIdentity() + return ax.mat4.new(1.0 ,0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0) end -function cc.mat4.translate(self,vec3) +function ax.mat4.translate(self,vec3) return mat4_translate(self,vec3) end -function cc.mat4.createRotationZ(self,angle) +function ax.mat4.createRotationZ(self,angle) return mat4_createRotationZ(self,angle) end -function cc.mat4.setIdentity(self) +function ax.mat4.setIdentity(self) return mat4_setIdentity(self) end -function cc.mat4.createTranslation(...) +function ax.mat4.createTranslation(...) return mat4_createTranslation(...) end -function cc.mat4.createRotation(...) +function ax.mat4.createRotation(...) return mat4_createRotation(...) -end \ No newline at end of file +end diff --git a/extensions/scripting/lua-bindings/script/core/Constants.lua b/extensions/scripting/lua-bindings/script/core/Constants.lua index 9872df5a59d5..c83c40eeeb24 100644 --- a/extensions/scripting/lua-bindings/script/core/Constants.lua +++ b/extensions/scripting/lua-bindings/script/core/Constants.lua @@ -137,7 +137,7 @@ ax.UNIFORM_RANDOM01 = 0x6 ax.UNIFORM_SAMPLER = 0x7 ax.UNIFORM_SIN_TIME = 0x4 ax.UNIFORM_TIME = 0x3 -ax.UNIFORM_MAX = 0x8 +ax.UNIFORM_COUNT = 0x8 ax.VERTEX_ATTRIB_FLAG_COLOR = 0x2 ax.VERTEX_ATTRIB_FLAG_NONE = 0x0 ax.VERTEX_ATTRIB_FLAG_POS_COLOR_TEX = 0x7 @@ -531,7 +531,7 @@ ax.KeyCode.KEY_LEFT_ALT = ax.KeyCode.KEY_ALT ax.EventAssetsManagerEx = { - EventCode = + EventCode = { ERROR_NO_LOCAL_MANIFEST = 0, ERROR_DOWNLOAD_MANIFEST = 1, @@ -586,7 +586,7 @@ ax.CameraFlag = USER8 = 256, } -ax.CameraBackgroundBrush.BrushType = +ax.CameraBackgroundBrush.BrushType = { NONE = 0, DEPTH = 1, @@ -627,7 +627,7 @@ ax.MATRIX_STACK_TYPE = TEXTURE = 2, } -ax.LightType = +ax.LightType = { DIRECTIONAL = 0, POINT = 1, @@ -635,7 +635,7 @@ ax.LightType = AMBIENT = 3, } -ax.LightFlag = +ax.LightFlag = { LIGHT0 = math.pow(2,0), LIGHT1 = math.pow(2,1), @@ -655,10 +655,10 @@ ax.LightFlag = LIGHT15 = math.pow(2,15), } -ax.RED = ax.c3b(255,0,0) -ax.GREEN = ax.c3b(0,255,0) -ax.BLUE = ax.c3b(0,0,255) -ax.BLACK = ax.c3b(0,0,0) -ax.WHITE = ax.c3b(255,255,255) -ax.YELLOW = ax.c3b(255,255,0) +ax.RED = ax.color32(255,0,0) +ax.GREEN = ax.color32(0,255,0) +ax.BLUE = ax.color32(0,0,255) +ax.BLACK = ax.color32(0,0,0) +ax.WHITE = ax.color32(255,255,255) +ax.YELLOW = ax.color32(255,255,0) diff --git a/extensions/scripting/lua-bindings/script/core/DrawPrimitives.lua b/extensions/scripting/lua-bindings/script/core/DrawPrimitives.lua index e4f50a93ff57..2f4879133c96 100644 --- a/extensions/scripting/lua-bindings/script/core/DrawPrimitives.lua +++ b/extensions/scripting/lua-bindings/script/core/DrawPrimitives.lua @@ -8,11 +8,11 @@ local dp_pointSize = 1.0 local SHADER_NAME_POSITION_U_COLOR = "ShaderPosition_uColor" -local targetPlatform = cc.Application:getInstance():getTargetPlatform() +local targetPlatform = ax.Application:getInstance():getTargetPlatform() local function lazy_init() if not dp_initialized then - dp_shader = cc.ShaderCache:getInstance():getProgram(SHADER_NAME_POSITION_U_COLOR) + dp_shader = ax.ShaderCache:getInstance():getProgram(SHADER_NAME_POSITION_U_COLOR) --dp_shader:retain() if nil ~= dp_shader then dp_colorLocation = gl.getUniformLocation( dp_shader:getProgram(), "u_color") @@ -52,10 +52,10 @@ function ccDrawColor4f(r,g,b,a) end function ccPointSize(pointSize) - dp_pointSize = pointSize * cc.Director:getInstance():getContentScaleFactor() + dp_pointSize = pointSize * ax.Director:getInstance():getContentScaleFactor() end -function ccDrawColor4B(r,g,b,a) +function ccDrawColor32(r,g,b,a) dp_color[1] = r / 255.0 dp_color[2] = g / 255.0 dp_color[3] = b / 255.0 diff --git a/extensions/scripting/lua-bindings/script/core/deprecated.lua b/extensions/scripting/lua-bindings/script/core/deprecated.lua index 9c82fa81117a..91c2c8350adf 100644 --- a/extensions/scripting/lua-bindings/script/core/deprecated.lua +++ b/extensions/scripting/lua-bindings/script/core/deprecated.lua @@ -1,15 +1,15 @@ function schedule(node, callback, delay) - local delay = cc.DelayTime:create(delay) - local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback)) - local action = cc.RepeatForever:create(sequence) + local delay = ax.DelayTime:create(delay) + local sequence = ax.Sequence:create(delay, ax.CallFunc:create(callback)) + local action = ax.RepeatForever:create(sequence) node:runAction(action) return action end function performWithDelay(node, callback, delay) - local delay = cc.DelayTime:create(delay) - local sequence = cc.Sequence:create(delay, cc.CallFunc:create(callback)) + local delay = ax.DelayTime:create(delay) + local sequence = ax.Sequence:create(delay, ax.CallFunc:create(callback)) node:runAction(sequence) return sequence end diff --git a/extensions/scripting/lua-bindings/script/extension/ExtensionConstants.lua b/extensions/scripting/lua-bindings/script/extension/ExtensionConstants.lua index 8d06f9403c1d..9e104bb2c5ed 100644 --- a/extensions/scripting/lua-bindings/script/extension/ExtensionConstants.lua +++ b/extensions/scripting/lua-bindings/script/extension/ExtensionConstants.lua @@ -1,66 +1,66 @@ -cc.CONTROL_STATE_NORMAL = 1 -cc.CONTROL_STATE_HIGH_LIGHTED = 2 -cc.CONTROL_STATE_DISABLED = 4 -cc.CONTROL_STATE_SELECTED = 8 +ax.CONTROL_STATE_NORMAL = 1 +ax.CONTROL_STATE_HIGH_LIGHTED = 2 +ax.CONTROL_STATE_DISABLED = 4 +ax.CONTROL_STATE_SELECTED = 8 -cc.CONTROL_STEPPER_PART_MINUS = 0 -cc.CONTROL_STEPPER_PART_PLUS = 1 -cc.CONTROL_STEPPER_PART_NONE = 2 +ax.CONTROL_STEPPER_PART_MINUS = 0 +ax.CONTROL_STEPPER_PART_PLUS = 1 +ax.CONTROL_STEPPER_PART_NONE = 2 -cc.TABLEVIEW_FILL_TOPDOWN = 0 -cc.TABLEVIEW_FILL_BOTTOMUP = 1 +ax.TABLEVIEW_FILL_TOPDOWN = 0 +ax.TABLEVIEW_FILL_BOTTOMUP = 1 -cc.SCROLLVIEW_SCRIPT_SCROLL = 0 -cc.SCROLLVIEW_SCRIPT_ZOOM = 1 -cc.TABLECELL_TOUCHED = 2 -cc.TABLECELL_HIGH_LIGHT = 3 -cc.TABLECELL_UNHIGH_LIGHT = 4 -cc.TABLECELL_WILL_RECYCLE = 5 -cc.TABLECELL_SIZE_FOR_INDEX = 6 -cc.TABLECELL_SIZE_AT_INDEX = 7 -cc.NUMBER_OF_CELLS_IN_TABLEVIEW = 8 +ax.SCROLLVIEW_SCRIPT_SCROLL = 0 +ax.SCROLLVIEW_SCRIPT_ZOOM = 1 +ax.TABLECELL_TOUCHED = 2 +ax.TABLECELL_HIGH_LIGHT = 3 +ax.TABLECELL_UNHIGH_LIGHT = 4 +ax.TABLECELL_WILL_RECYCLE = 5 +ax.TABLECELL_SIZE_FOR_INDEX = 6 +ax.TABLECELL_SIZE_AT_INDEX = 7 +ax.NUMBER_OF_CELLS_IN_TABLEVIEW = 8 -cc.SCROLLVIEW_DIRECTION_NONE = -1 -cc.SCROLLVIEW_DIRECTION_HORIZONTAL = 0 -cc.SCROLLVIEW_DIRECTION_VERTICAL = 1 -cc.SCROLLVIEW_DIRECTION_BOTH = 2 +ax.SCROLLVIEW_DIRECTION_NONE = -1 +ax.SCROLLVIEW_DIRECTION_HORIZONTAL = 0 +ax.SCROLLVIEW_DIRECTION_VERTICAL = 1 +ax.SCROLLVIEW_DIRECTION_BOTH = 2 -cc.CONTROL_EVENTTYPE_TOUCH_DOWN = 1 -cc.CONTROL_EVENTTYPE_DRAG_INSIDE = 2 -cc.CONTROL_EVENTTYPE_DRAG_OUTSIDE = 4 -cc.CONTROL_EVENTTYPE_DRAG_ENTER = 8 -cc.CONTROL_EVENTTYPE_DRAG_EXIT = 16 -cc.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE = 32 -cc.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE = 64 -cc.CONTROL_EVENTTYPE_TOUCH_CANCEL = 128 -cc.CONTROL_EVENTTYPE_VALUE_CHANGED = 256 +ax.CONTROL_EVENTTYPE_TOUCH_DOWN = 1 +ax.CONTROL_EVENTTYPE_DRAG_INSIDE = 2 +ax.CONTROL_EVENTTYPE_DRAG_OUTSIDE = 4 +ax.CONTROL_EVENTTYPE_DRAG_ENTER = 8 +ax.CONTROL_EVENTTYPE_DRAG_EXIT = 16 +ax.CONTROL_EVENTTYPE_TOUCH_UP_INSIDE = 32 +ax.CONTROL_EVENTTYPE_TOUCH_UP_OUTSIDE = 64 +ax.CONTROL_EVENTTYPE_TOUCH_CANCEL = 128 +ax.CONTROL_EVENTTYPE_VALUE_CHANGED = 256 -cc.EDITBOX_INPUT_MODE_ANY = 0 -cc.EDITBOX_INPUT_MODE_EMAILADDR = 1 -cc.EDITBOX_INPUT_MODE_NUMERIC = 2 -cc.EDITBOX_INPUT_MODE_PHONENUMBER = 3 -cc.EDITBOX_INPUT_MODE_URL = 4 -cc.EDITBOX_INPUT_MODE_DECIMAL = 5 -cc.EDITBOX_INPUT_MODE_SINGLELINE = 6 +ax.EDITBOX_INPUT_MODE_ANY = 0 +ax.EDITBOX_INPUT_MODE_EMAILADDR = 1 +ax.EDITBOX_INPUT_MODE_NUMERIC = 2 +ax.EDITBOX_INPUT_MODE_PHONENUMBER = 3 +ax.EDITBOX_INPUT_MODE_URL = 4 +ax.EDITBOX_INPUT_MODE_DECIMAL = 5 +ax.EDITBOX_INPUT_MODE_SINGLELINE = 6 -cc.EDITBOX_INPUT_FLAG_PASSWORD = 0 -cc.EDITBOX_INPUT_FLAG_SENSITIVE = 1 -cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2 -cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3 -cc.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4 +ax.EDITBOX_INPUT_FLAG_PASSWORD = 0 +ax.EDITBOX_INPUT_FLAG_SENSITIVE = 1 +ax.EDITBOX_INPUT_FLAG_INITIAL_CAPS_WORD = 2 +ax.EDITBOX_INPUT_FLAG_INITIAL_CAPS_SENTENCE = 3 +ax.EDITBOX_INPUT_FLAG_INITIAL_CAPS_ALL_CHARACTERS = 4 -cc.KEYBOARD_RETURNTYPE_DEFAULT = 0 -cc.KEYBOARD_RETURNTYPE_DONE = 1 -cc.KEYBOARD_RETURNTYPE_SEND = 2 -cc.KEYBOARD_RETURNTYPE_SEARCH = 3 -cc.KEYBOARD_RETURNTYPE_GO = 4 +ax.KEYBOARD_RETURNTYPE_DEFAULT = 0 +ax.KEYBOARD_RETURNTYPE_DONE = 1 +ax.KEYBOARD_RETURNTYPE_SEND = 2 +ax.KEYBOARD_RETURNTYPE_SEARCH = 3 +ax.KEYBOARD_RETURNTYPE_GO = 4 -cc.ASSETSMANAGER_CREATE_FILE = 0 -cc.ASSETSMANAGER_NETWORK = 1 -cc.ASSETSMANAGER_NO_NEW_VERSION = 2 -cc.ASSETSMANAGER_UNCOMPRESS = 3 +ax.ASSETSMANAGER_CREATE_FILE = 0 +ax.ASSETSMANAGER_NETWORK = 1 +ax.ASSETSMANAGER_NO_NEW_VERSION = 2 +ax.ASSETSMANAGER_UNCOMPRESS = 3 -cc.ASSETSMANAGER_PROTOCOL_PROGRESS = 0 -cc.ASSETSMANAGER_PROTOCOL_SUCCESS = 1 -cc.ASSETSMANAGER_PROTOCOL_ERROR = 2 +ax.ASSETSMANAGER_PROTOCOL_PROGRESS = 0 +ax.ASSETSMANAGER_PROTOCOL_SUCCESS = 1 +ax.ASSETSMANAGER_PROTOCOL_ERROR = 2 diff --git a/extensions/scripting/lua-bindings/script/framework/components/event.lua b/extensions/scripting/lua-bindings/script/framework/components/event.lua index a6ca22b85e83..0febbb070c5b 100644 --- a/extensions/scripting/lua-bindings/script/framework/components/event.lua +++ b/extensions/scripting/lua-bindings/script/framework/components/event.lua @@ -20,12 +20,12 @@ end function Event:bind(target) self:init_() - cc.setmethods(target, self, EXPORTED_METHODS) + ax.setmethods(target, self, EXPORTED_METHODS) self.target_ = target end function Event:unbind(target) - cc.unsetmethods(target, EXPORTED_METHODS) + ax.unsetmethods(target, EXPORTED_METHODS) self:init_() end diff --git a/extensions/scripting/lua-bindings/script/framework/device.lua b/extensions/scripting/lua-bindings/script/framework/device.lua index 7fe383a3078d..8d41aa6ea9bd 100644 --- a/extensions/scripting/lua-bindings/script/framework/device.lua +++ b/extensions/scripting/lua-bindings/script/framework/device.lua @@ -27,21 +27,21 @@ local device = {} device.platform = "unknown" device.model = "unknown" -local app = cc.Application:getInstance() +local app = ax.Application:getInstance() local target = app:getTargetPlatform() -if target == cc.PLATFORM_WINDOWS then +if target == ax.PLATFORM_WINDOWS then device.platform = "windows" -elseif target == cc.PLATFORM_UWP then +elseif target == ax.PLATFORM_UWP then device.platform = "uwp" -elseif target == cc.PLATFORM_UWP_PHONE then +elseif target == ax.PLATFORM_UWP_PHONE then device.platform = "uwp phone" -elseif target == cc.PLATFORM_MAC then +elseif target == ax.PLATFORM_MAC then device.platform = "mac" -elseif target == cc.PLATFORM_ANDROID then +elseif target == ax.PLATFORM_ANDROID then device.platform = "android" -elseif target == cc.PLATFORM_IOS then +elseif target == ax.PLATFORM_IOS then device.platform = "ios" - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() local view = director:getRenderView() local framesize = view:getFrameSize() local w, h = framesize.width, framesize.height @@ -61,34 +61,34 @@ elseif target == cc.PLATFORM_IOS then end local language_ = app:getCurrentLanguage() -if language_ == cc.LANGUAGE_CHINESE then +if language_ == ax.LANGUAGE_CHINESE then language_ = "cn" -elseif language_ == cc.LANGUAGE_FRENCH then +elseif language_ == ax.LANGUAGE_FRENCH then language_ = "fr" -elseif language_ == cc.LANGUAGE_ITALIAN then +elseif language_ == ax.LANGUAGE_ITALIAN then language_ = "it" -elseif language_ == cc.LANGUAGE_GERMAN then +elseif language_ == ax.LANGUAGE_GERMAN then language_ = "gr" -elseif language_ == cc.LANGUAGE_SPANISH then +elseif language_ == ax.LANGUAGE_SPANISH then language_ = "sp" -elseif language_ == cc.LANGUAGE_RUSSIAN then +elseif language_ == ax.LANGUAGE_RUSSIAN then language_ = "ru" -elseif language_ == cc.LANGUAGE_KOREAN then +elseif language_ == ax.LANGUAGE_KOREAN then language_ = "kr" -elseif language_ == cc.LANGUAGE_JAPANESE then +elseif language_ == ax.LANGUAGE_JAPANESE then language_ = "jp" -elseif language_ == cc.LANGUAGE_HUNGARIAN then +elseif language_ == ax.LANGUAGE_HUNGARIAN then language_ = "hu" -elseif language_ == cc.LANGUAGE_PORTUGUESE then +elseif language_ == ax.LANGUAGE_PORTUGUESE then language_ = "pt" -elseif language_ == cc.LANGUAGE_ARABIC then +elseif language_ == ax.LANGUAGE_ARABIC then language_ = "ar" else language_ = "en" end device.language = language_ -device.writablePath = cc.FileUtils:getInstance():getWritablePath() +device.writablePath = ax.FileUtils:getInstance():getWritablePath() device.directorySeparator = "/" device.pathSeparator = ":" if device.platform == "windows" then diff --git a/extensions/scripting/lua-bindings/script/framework/display.lua b/extensions/scripting/lua-bindings/script/framework/display.lua index 28a54a188a6e..42acf65a88c5 100644 --- a/extensions/scripting/lua-bindings/script/framework/display.lua +++ b/extensions/scripting/lua-bindings/script/framework/display.lua @@ -24,7 +24,7 @@ THE SOFTWARE. local display = {} -local director = cc.Director:getInstance() +local director = ax.Director:getInstance() local view = director:getRenderView() if not view then @@ -38,14 +38,14 @@ if not view then height = AX_DESIGN_RESOLUTION.height end end - view = cc.RenderViewImpl:createWithRect("Axmol-Lua", cc.rect(0, 0, width, height)) + view = ax.RenderViewImpl:createWithRect("Axmol-Lua", ax.rect(0, 0, width, height)) director:setRenderView(view) end local framesize = view:getFrameSize() local textureCache = director:getTextureCache() -local spriteFrameCache = cc.SpriteFrameCache:getInstance() -local animationCache = cc.AnimationCache:getInstance() +local spriteFrameCache = ax.SpriteFrameCache:getInstance() +local animationCache = ax.AnimationCache:getInstance() -- auto scale local function checkResolution(r) @@ -58,24 +58,24 @@ end local function setDesignResolution(r, framesize) if r.autoscale == "FILL_ALL" then - view:setDesignResolutionSize(framesize.width, framesize.height, cc.ResolutionPolicy.FILL_ALL) + view:setDesignResolutionSize(framesize.width, framesize.height, ax.ResolutionPolicy.FILL_ALL) else local scaleX, scaleY = framesize.width / r.width, framesize.height / r.height local width, height = framesize.width, framesize.height if r.autoscale == "FIXED_WIDTH" then width = framesize.width / scaleX height = framesize.height / scaleX - view:setDesignResolutionSize(width, height, cc.ResolutionPolicy.NO_BORDER) + view:setDesignResolutionSize(width, height, ax.ResolutionPolicy.NO_BORDER) elseif r.autoscale == "FIXED_HEIGHT" then width = framesize.width / scaleY height = framesize.height / scaleY - view:setDesignResolutionSize(width, height, cc.ResolutionPolicy.NO_BORDER) + view:setDesignResolutionSize(width, height, ax.ResolutionPolicy.NO_BORDER) elseif r.autoscale == "EXACT_FIT" then - view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.EXACT_FIT) + view:setDesignResolutionSize(r.width, r.height, ax.ResolutionPolicy.EXACT_FIT) elseif r.autoscale == "NO_BORDER" then - view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.NO_BORDER) + view:setDesignResolutionSize(r.width, r.height, ax.ResolutionPolicy.NO_BORDER) elseif r.autoscale == "SHOW_ALL" then - view:setDesignResolutionSize(r.width, r.height, cc.ResolutionPolicy.SHOW_ALL) + view:setDesignResolutionSize(r.width, r.height, ax.ResolutionPolicy.SHOW_ALL) else printError(string.format("display - invalid r.autoscale \"%s\"", r.autoscale)) end @@ -101,15 +101,15 @@ local function setConstants() display.right = display.width display.top = display.height display.bottom = 0 - display.center = cc.p(display.cx, display.cy) - display.left_top = cc.p(display.left, display.top) - display.left_bottom = cc.p(display.left, display.bottom) - display.left_center = cc.p(display.left, display.cy) - display.right_top = cc.p(display.right, display.top) - display.right_bottom = cc.p(display.right, display.bottom) - display.right_center = cc.p(display.right, display.cy) - display.top_center = cc.p(display.cx, display.top) - display.top_bottom = cc.p(display.cx, display.bottom) + display.center = ax.p(display.cx, display.cy) + display.left_top = ax.p(display.left, display.top) + display.left_bottom = ax.p(display.left, display.bottom) + display.left_center = ax.p(display.left, display.cy) + display.right_top = ax.p(display.right, display.top) + display.right_bottom = ax.p(display.right, display.bottom) + display.right_center = ax.p(display.right, display.cy) + display.top_center = ax.p(display.cx, display.top) + display.top_bottom = ax.p(display.cx, display.bottom) printInfo(string.format("# display.sizeInPixels = {width = %0.2f, height = %0.2f}", display.sizeInPixels.width, display.sizeInPixels.height)) printInfo(string.format("# display.size = {width = %0.2f, height = %0.2f}", display.size.width, display.size.height)) @@ -161,11 +161,11 @@ if type(AX_DESIGN_RESOLUTION) == "table" then display.setAutoScale(AX_DESIGN_RESOLUTION) end -display.COLOR_WHITE = cc.c3b(255, 255, 255) -display.COLOR_BLACK = cc.c3b(0, 0, 0) -display.COLOR_RED = cc.c3b(255, 0, 0) -display.COLOR_GREEN = cc.c3b(0, 255, 0) -display.COLOR_BLUE = cc.c3b(0, 0, 255) +display.COLOR_WHITE = ax.color32(255, 255, 255, 255) +display.COLOR_BLACK = ax.color32(0, 0, 0, 255) +display.COLOR_RED = ax.color32(255, 0, 0, 255) +display.COLOR_GREEN = ax.color32(0, 255, 0, 255) +display.COLOR_BLUE = ax.color32(0, 0, 255, 255) display.AUTO_SIZE = 0 display.FIXED_SIZE = 1 @@ -174,44 +174,44 @@ display.RIGHT_TO_LEFT = 1 display.TOP_TO_BOTTOM = 2 display.BOTTOM_TO_TOP = 3 -display.CENTER = cc.p(0.5, 0.5) -display.LEFT_TOP = cc.p(0, 1) -display.LEFT_BOTTOM = cc.p(0, 0) -display.LEFT_CENTER = cc.p(0, 0.5) -display.RIGHT_TOP = cc.p(1, 1) -display.RIGHT_BOTTOM = cc.p(1, 0) -display.RIGHT_CENTER = cc.p(1, 0.5) -display.CENTER_TOP = cc.p(0.5, 1) -display.CENTER_BOTTOM = cc.p(0.5, 0) +display.CENTER = ax.p(0.5, 0.5) +display.LEFT_TOP = ax.p(0, 1) +display.LEFT_BOTTOM = ax.p(0, 0) +display.LEFT_CENTER = ax.p(0, 0.5) +display.RIGHT_TOP = ax.p(1, 1) +display.RIGHT_BOTTOM = ax.p(1, 0) +display.RIGHT_CENTER = ax.p(1, 0.5) +display.CENTER_TOP = ax.p(0.5, 1) +display.CENTER_BOTTOM = ax.p(0.5, 0) display.SCENE_TRANSITIONS = { - CROSSFADE = {cc.TransitionCrossFade}, - FADE = {cc.TransitionFade, cc.c3b(0, 0, 0)}, - FADEBL = {cc.TransitionFadeBL}, - FADEDOWN = {cc.TransitionFadeDown}, - FADETR = {cc.TransitionFadeTR}, - FADEUP = {cc.TransitionFadeUp}, - FLIPANGULAR = {cc.TransitionFlipAngular, cc.TRANSITION_ORIENTATION_LEFT_OVER}, - FLIPX = {cc.TransitionFlipX, cc.TRANSITION_ORIENTATION_LEFT_OVER}, - FLIPY = {cc.TransitionFlipY, cc.TRANSITION_ORIENTATION_UP_OVER}, - JUMPZOOM = {cc.TransitionJumpZoom}, - MOVEINB = {cc.TransitionMoveInB}, - MOVEINL = {cc.TransitionMoveInL}, - MOVEINR = {cc.TransitionMoveInR}, - MOVEINT = {cc.TransitionMoveInT}, - PAGETURN = {cc.TransitionPageTurn, false}, - ROTOZOOM = {cc.TransitionRotoZoom}, - SHRINKGROW = {cc.TransitionShrinkGrow}, - SLIDEINB = {cc.TransitionSlideInB}, - SLIDEINL = {cc.TransitionSlideInL}, - SLIDEINR = {cc.TransitionSlideInR}, - SLIDEINT = {cc.TransitionSlideInT}, - SPLITCOLS = {cc.TransitionSplitCols}, - SPLITROWS = {cc.TransitionSplitRows}, - TURNOFFTILES = {cc.TransitionTurnOffTiles}, - ZOOMFLIPANGULAR = {cc.TransitionZoomFlipAngular}, - ZOOMFLIPX = {cc.TransitionZoomFlipX, cc.TRANSITION_ORIENTATION_LEFT_OVER}, - ZOOMFLIPY = {cc.TransitionZoomFlipY, cc.TRANSITION_ORIENTATION_UP_OVER}, + CROSSFADE = {ax.TransitionCrossFade}, + FADE = {ax.TransitionFade, ax.color32(0, 0, 0, 255)}, + FADEBL = {ax.TransitionFadeBL}, + FADEDOWN = {ax.TransitionFadeDown}, + FADETR = {ax.TransitionFadeTR}, + FADEUP = {ax.TransitionFadeUp}, + FLIPANGULAR = {ax.TransitionFlipAngular, ax.TRANSITION_ORIENTATION_LEFT_OVER}, + FLIPX = {ax.TransitionFlipX, ax.TRANSITION_ORIENTATION_LEFT_OVER}, + FLIPY = {ax.TransitionFlipY, ax.TRANSITION_ORIENTATION_UP_OVER}, + JUMPZOOM = {ax.TransitionJumpZoom}, + MOVEINB = {ax.TransitionMoveInB}, + MOVEINL = {ax.TransitionMoveInL}, + MOVEINR = {ax.TransitionMoveInR}, + MOVEINT = {ax.TransitionMoveInT}, + PAGETURN = {ax.TransitionPageTurn, false}, + ROTOZOOM = {ax.TransitionRotoZoom}, + SHRINKGROW = {ax.TransitionShrinkGrow}, + SLIDEINB = {ax.TransitionSlideInB}, + SLIDEINL = {ax.TransitionSlideInL}, + SLIDEINR = {ax.TransitionSlideInR}, + SLIDEINT = {ax.TransitionSlideInT}, + SPLITCOLS = {ax.TransitionSplitCols}, + SPLITROWS = {ax.TransitionSplitRows}, + TURNOFFTILES = {ax.TransitionTurnOffTiles}, + ZOOMFLIPANGULAR = {ax.TransitionZoomFlipAngular}, + ZOOMFLIPX = {ax.TransitionZoomFlipX, ax.TRANSITION_ORIENTATION_LEFT_OVER}, + ZOOMFLIPY = {ax.TransitionZoomFlipY, ax.TRANSITION_ORIENTATION_UP_OVER}, } display.TEXTURES_PIXEL_FORMAT = {} @@ -221,7 +221,7 @@ display.DEFAULT_TTF_FONT_SIZE = 32 local PARAMS_EMPTY = {} -local RECT_ZERO = cc.rect(0, 0, 0, 0) +local RECT_ZERO = ax.rect(0, 0, 0, 0) local sceneIndex = 0 function display.newScene(name, params) @@ -229,9 +229,9 @@ function display.newScene(name, params) sceneIndex = sceneIndex + 1 local scene if not params.physics then - scene = cc.Scene:create() + scene = ax.Scene:create() else - scene = cc.Scene:createWithPhysics() + scene = ax.Scene:createWithPhysics() end scene.name_ = string.format("%s:%d", name or "", sceneIndex) @@ -282,7 +282,7 @@ function display.getRunningScene() end function display.newNode() - return cc.Node:create() + return ax.Node:create() end function display.newLayer(...) @@ -292,45 +292,45 @@ function display.newLayer(...) if c == 0 then -- /** creates a fullscreen black layer */ -- static Layer *create(); - layer = cc.Layer:create() + layer = ax.Layer:create() elseif c == 1 then -- /** creates a Layer with color. Width and height are the window size. */ - -- static LayerColor * create(const Color4B& color); - layer = cc.LayerColor:create(cc.convertColor(params[1], "4b")) + -- static LayerColor * create(const Color32& color); + layer = ax.LayerColor:create(ax.convertColor(params[1], "4b")) elseif c == 2 then -- /** creates a Layer with color, width and height in Points */ - -- static LayerColor * create(const Color4B& color, const Size& size); + -- static LayerColor * create(const Color32& color, const Size& size); -- -- /** Creates a full-screen Layer with a gradient between start and end. */ - -- static LayerGradient* create(const Color4B& start, const Color4B& end); - local color1 = cc.convertColor(params[1], "4b") + -- static LayerGradient* create(const Color32& start, const Color32& end); + local color1 = ax.convertColor(params[1], "4b") local p2 = params[2] assert(type(p2) == "table" and (p2.width or p2.r), "display.newLayer() - invalid paramerter 2") if p2.r then - layer = cc.LayerGradient:create(color1, cc.convertColor(p2, "4b")) + layer = ax.LayerGradient:create(color1, ax.convertColor(p2, "4b")) else - layer = cc.LayerColor:create(color1, p2.width, p2.height) + layer = ax.LayerColor:create(color1, p2.width, p2.height) end elseif c == 3 then -- /** creates a Layer with color, width and height in Points */ - -- static LayerColor * create(const Color4B& color, GLfloat width, GLfloat height); + -- static LayerColor * create(const Color32& color, GLfloat width, GLfloat height); -- -- /** Creates a full-screen Layer with a gradient between start and end in the direction of v. */ - -- static LayerGradient* create(const Color4B& start, const Color4B& end, const Vec2& v); - local color1 = cc.convertColor(params[1], "4b") + -- static LayerGradient* create(const Color32& start, const Color32& end, const Vec2& v); + local color1 = ax.convertColor(params[1], "4b") local p2 = params[2] local p2type = type(p2) if p2type == "table" then - layer = cc.LayerGradient:create(color1, cc.convertColor(p2, "4b"), params[3]) + layer = ax.LayerGradient:create(color1, ax.convertColor(p2, "4b"), params[3]) else - layer = cc.LayerColor:create(color1, p2, params[3]) + layer = ax.LayerColor:create(color1, p2, params[3]) end end return layer end function display.newSprite(source, x, y, params) - local spriteClass = cc.Sprite + local spriteClass = ax.Sprite local scale9 = false if type(x) == "table" and not x.x then @@ -369,17 +369,11 @@ function display.newSprite(source, x, y, params) end -- create sprite from image file - if display.TEXTURES_PIXEL_FORMAT[source] then - cc.Texture2D:setDefaultAlphaPixelFormat(display.TEXTURES_PIXEL_FORMAT[source]) - end if not scale9 then sprite = spriteClass:create(source) else sprite = spriteClass:create(source, params.rect, params.capInsets) end - if display.TEXTURES_PIXEL_FORMAT[source] then - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_BGRA8) - end break elseif sourceType ~= "userdata" then error(string.format("display.newSprite() - invalid source type \"%s\"", sourceType), 0) @@ -421,7 +415,7 @@ function display.newSpriteFrame(source, ...) error(string.format("display.newSpriteFrame() - invalid frame name \"%s\"", tostring(source)), 0) end elseif tolua.type(source) == "ax.Texture2D" then - frame = cc.SpriteFrame:createWithTexture(source, ...) + frame = ax.SpriteFrame:createWithTexture(source, ...) else error("display.newSpriteFrame() - invalid parameters", 0) end @@ -452,8 +446,8 @@ local function newAnimation(frames, time) local count = #frames assert(count > 0, "display.newAnimation() - invalid frames") time = time or 1.0 / count - return cc.Animation:createWithSpriteFrames(frames, time), - cc.Sprite:createWithSpriteFrame(frames[1]) + return ax.Animation:createWithSpriteFrames(frames, time), + ax.Sprite:createWithSpriteFrame(frames[1]) end function display.newAnimation(...) @@ -483,7 +477,7 @@ function display.loadImage(imageFilename, callback) end end -local fileUtils = cc.FileUtils:getInstance() +local fileUtils = ax.FileUtils:getInstance() function display.getImage(imageFilename) local fullpath = fileUtils:fullPathForFilename(imageFilename) return textureCache:getTextureForKey(fullpath) @@ -494,17 +488,11 @@ function display.removeImage(imageFilename) end function display.loadSpriteFrames(dataFilename, imageFilename, callback) - if display.TEXTURES_PIXEL_FORMAT[imageFilename] then - cc.Texture2D:setDefaultAlphaPixelFormat(display.TEXTURES_PIXEL_FORMAT[imageFilename]) - end if not callback then spriteFrameCache:addSpriteFrames(dataFilename, imageFilename) else spriteFrameCache:addSpriteFramesAsync(dataFilename, imageFilename, callback) end - if display.TEXTURES_PIXEL_FORMAT[imageFilename] then - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_BGRA8) - end end function display.removeSpriteFrames(dataFilename, imageFilename) diff --git a/extensions/scripting/lua-bindings/script/framework/extends/LayerEx.lua b/extensions/scripting/lua-bindings/script/framework/extends/LayerEx.lua index eeba83258e6b..99c78720cba0 100644 --- a/extensions/scripting/lua-bindings/script/framework/extends/LayerEx.lua +++ b/extensions/scripting/lua-bindings/script/framework/extends/LayerEx.lua @@ -22,7 +22,7 @@ THE SOFTWARE. ]] -local Layer = cc.Layer +local Layer = ax.Layer function Layer:onTouch(callback, isMultiTouches, swallowTouches) if type(isMultiTouches) ~= "boolean" then isMultiTouches = false end diff --git a/extensions/scripting/lua-bindings/script/framework/extends/MenuEx.lua b/extensions/scripting/lua-bindings/script/framework/extends/MenuEx.lua index 5bee36b59778..d95010c4bbd7 100644 --- a/extensions/scripting/lua-bindings/script/framework/extends/MenuEx.lua +++ b/extensions/scripting/lua-bindings/script/framework/extends/MenuEx.lua @@ -22,8 +22,8 @@ THE SOFTWARE. ]] -local Menu = cc.Menu -local MenuItem = cc.MenuItem +local Menu = ax.Menu +local MenuItem = ax.MenuItem function MenuItem:onClicked(callback) self:registerScriptTapHandler(callback) diff --git a/extensions/scripting/lua-bindings/script/framework/extends/NodeEx.lua b/extensions/scripting/lua-bindings/script/framework/extends/NodeEx.lua index b333903179a1..3b90017a0367 100644 --- a/extensions/scripting/lua-bindings/script/framework/extends/NodeEx.lua +++ b/extensions/scripting/lua-bindings/script/framework/extends/NodeEx.lua @@ -22,7 +22,7 @@ THE SOFTWARE. ]] -local Node = cc.Node +local Node = ax.Node function Node:add(child, zorder, tag) if tag then diff --git a/extensions/scripting/lua-bindings/script/framework/extends/SpriteEx.lua b/extensions/scripting/lua-bindings/script/framework/extends/SpriteEx.lua index a6eb8446e14c..069c6bb4bb0f 100644 --- a/extensions/scripting/lua-bindings/script/framework/extends/SpriteEx.lua +++ b/extensions/scripting/lua-bindings/script/framework/extends/SpriteEx.lua @@ -22,7 +22,7 @@ THE SOFTWARE. ]] -local Sprite = cc.Sprite +local Sprite = ax.Sprite function Sprite:playAnimationOnce(animation, args) local actions = {} @@ -30,28 +30,28 @@ function Sprite:playAnimationOnce(animation, args) local showDelay = args.showDelay if showDelay then self:setVisible(false) - actions[#actions + 1] = cc.DelayTime:create(showDelay) - actions[#actions + 1] = cc.Show:create() + actions[#actions + 1] = ax.DelayTime:create(showDelay) + actions[#actions + 1] = ax.Show:create() end local delay = args.delay or 0 if delay > 0 then - actions[#actions + 1] = cc.DelayTime:create(delay) + actions[#actions + 1] = ax.DelayTime:create(delay) end - actions[#actions + 1] = cc.Animate:create(animation) + actions[#actions + 1] = ax.Animate:create(animation) if args.removeSelf then - actions[#actions + 1] = cc.RemoveSelf:create() + actions[#actions + 1] = ax.RemoveSelf:create() end if args.onComplete then - actions[#actions + 1] = cc.CallFunc:create(args.onComplete) + actions[#actions + 1] = ax.CallFunc:create(args.onComplete) end local action if #actions > 1 then - action = cc.Sequence:create(actions) + action = ax.Sequence:create(actions) else action = actions[1] end @@ -60,8 +60,8 @@ function Sprite:playAnimationOnce(animation, args) end function Sprite:playAnimationForever(animation) - local animate = cc.Animate:create(animation) - local action = cc.RepeatForever:create(animate) + local animate = ax.Animate:create(animation) + local action = ax.RepeatForever:create(animate) self:runAction(action) return action end diff --git a/extensions/scripting/lua-bindings/script/framework/init.lua b/extensions/scripting/lua-bindings/script/framework/init.lua index 63e4a03e6821..1679abb14252 100644 --- a/extensions/scripting/lua-bindings/script/framework/init.lua +++ b/extensions/scripting/lua-bindings/script/framework/init.lua @@ -52,12 +52,12 @@ end require("axmol.framework.package_support") -- register the build-in packages -cc.register("event", require("axmol.framework.components.event")) +ax.register("event", require("axmol.framework.components.event")) -- export global variable local __g = _G -cc.exports = {} -setmetatable(cc.exports, { +ax.exports = {} +setmetatable(ax.exports, { __newindex = function(_, name, value) rawset(__g, name, value) end, @@ -68,14 +68,14 @@ setmetatable(cc.exports, { }) -- disable create unexpected global variable -function cc.disable_global() +function ax.disable_global() setmetatable(__g, { __newindex = function(_, name, value) - error(string.format("USE \" cc.exports.%s = value \" INSTEAD OF SET GLOBAL VARIABLE", name), 0) + error(string.format("USE \" ax.exports.%s = value \" INSTEAD OF SET GLOBAL VARIABLE", name), 0) end }) end if AX_DISABLE_GLOBAL then - cc.disable_global() + ax.disable_global() end diff --git a/extensions/scripting/lua-bindings/script/framework/package_support.lua b/extensions/scripting/lua-bindings/script/framework/package_support.lua index 1beae3c26af1..1e18a97d5c25 100644 --- a/extensions/scripting/lua-bindings/script/framework/package_support.lua +++ b/extensions/scripting/lua-bindings/script/framework/package_support.lua @@ -24,28 +24,28 @@ THE SOFTWARE. -- Cocos2d-Lua core functions local unpack = table.unpack -cc.loaded_packages = {} -local loaded_packages = cc.loaded_packages +ax.loaded_packages = {} +local loaded_packages = ax.loaded_packages -function cc.register(name, package) - cc.loaded_packages[name] = package +function ax.register(name, package) + ax.loaded_packages[name] = package end -function cc.load(...) +function ax.load(...) local names = {...} - assert(#names > 0, "cc.load() - invalid package names") + assert(#names > 0, "ax.load() - invalid package names") local packages = {} for _, name in ipairs(names) do - assert(type(name) == "string", string.format("cc.load() - invalid package name \"%s\"", tostring(name))) + assert(type(name) == "string", string.format("ax.load() - invalid package name \"%s\"", tostring(name))) if not loaded_packages[name] then local packageName = string.format("packages.%s.init", name) local cls = require(packageName) - assert(cls, string.format("cc.load() - package class \"%s\" load failed", packageName)) + assert(cls, string.format("ax.load() - package class \"%s\" load failed", packageName)) loaded_packages[name] = cls if DEBUG > 1 then - printInfo("cc.load() - load module \"packages.%s.init\"", name) + printInfo("ax.load() - load module \"packages.%s.init\"", name) end end packages[#packages + 1] = loaded_packages[name] @@ -53,18 +53,18 @@ function cc.load(...) return unpack(packages) end -local load_ = cc.load +local load_ = ax.load local bind_ bind_ = function(target, ...) local t = type(target) - assert(t == "table" or t == "userdata", string.format("cc.bind() - invalid target, expected is object, actual is %s", t)) + assert(t == "table" or t == "userdata", string.format("ax.bind() - invalid target, expected is object, actual is %s", t)) local names = {...} - assert(#names > 0, "cc.bind() - package names expected") + assert(#names > 0, "ax.bind() - package names expected") load_(...) if not target.components_ then target.components_ = {} end for _, name in ipairs(names) do - assert(type(name) == "string" and name ~= "", string.format("cc.bind() - invalid package name \"%s\"", name)) + assert(type(name) == "string" and name ~= "", string.format("ax.bind() - invalid package name \"%s\"", name)) if not target.components_[name] then local cls = loaded_packages[name] for __, depend in ipairs(cls.depends or {}) do @@ -80,25 +80,25 @@ bind_ = function(target, ...) return target end -cc.bind = bind_ +ax.bind = bind_ -function cc.unbind(target, ...) +function ax.unbind(target, ...) if not target.components_ then return end local names = {...} - assert(#names > 0, "cc.unbind() - invalid package names") + assert(#names > 0, "ax.unbind() - invalid package names") for _, name in ipairs(names) do - assert(type(name) == "string" and name ~= "", string.format("cc.unbind() - invalid package name \"%s\"", name)) + assert(type(name) == "string" and name ~= "", string.format("ax.unbind() - invalid package name \"%s\"", name)) local component = target.components_[name] - assert(component, string.format("cc.unbind() - component \"%s\" not found", tostring(name))) + assert(component, string.format("ax.unbind() - component \"%s\" not found", tostring(name))) component:unbind(target) target.components_[name] = nil end return target end -function cc.setmethods(target, component, methods) +function ax.setmethods(target, component, methods) for _, name in ipairs(methods) do local method = component[name] target[name] = function(__, ...) @@ -107,7 +107,7 @@ function cc.setmethods(target, component, methods) end end -function cc.unsetmethods(target, methods) +function ax.unsetmethods(target, methods) for _, name in ipairs(methods) do target[name] = nil end diff --git a/extensions/scripting/lua-bindings/script/framework/transition.lua b/extensions/scripting/lua-bindings/script/framework/transition.lua index 8b2c1e4ab593..0ac975c75f41 100644 --- a/extensions/scripting/lua-bindings/script/framework/transition.lua +++ b/extensions/scripting/lua-bindings/script/framework/transition.lua @@ -26,29 +26,29 @@ local unpack = table.unpack local transition = {} local ACTION_EASING = {} -ACTION_EASING["BACKIN"] = {cc.EaseBackIn, 1} -ACTION_EASING["BACKINOUT"] = {cc.EaseBackInOut, 1} -ACTION_EASING["BACKOUT"] = {cc.EaseBackOut, 1} -ACTION_EASING["BOUNCE"] = {cc.EaseBounce, 1} -ACTION_EASING["BOUNCEIN"] = {cc.EaseBounceIn, 1} -ACTION_EASING["BOUNCEINOUT"] = {cc.EaseBounceInOut, 1} -ACTION_EASING["BOUNCEOUT"] = {cc.EaseBounceOut, 1} -ACTION_EASING["ELASTIC"] = {cc.EaseElastic, 2, 0.3} -ACTION_EASING["ELASTICIN"] = {cc.EaseElasticIn, 2, 0.3} -ACTION_EASING["ELASTICINOUT"] = {cc.EaseElasticInOut, 2, 0.3} -ACTION_EASING["ELASTICOUT"] = {cc.EaseElasticOut, 2, 0.3} -ACTION_EASING["EXPONENTIALIN"] = {cc.EaseExponentialIn, 1} -ACTION_EASING["EXPONENTIALINOUT"] = {cc.EaseExponentialInOut, 1} -ACTION_EASING["EXPONENTIALOUT"] = {cc.EaseExponentialOut, 1} -ACTION_EASING["IN"] = {cc.EaseIn, 2, 1} -ACTION_EASING["INOUT"] = {cc.EaseInOut, 2, 1} -ACTION_EASING["OUT"] = {cc.EaseOut, 2, 1} -ACTION_EASING["RATEACTION"] = {cc.EaseRateAction, 2, 1} -ACTION_EASING["SINEIN"] = {cc.EaseSineIn, 1} -ACTION_EASING["SINEINOUT"] = {cc.EaseSineInOut, 1} -ACTION_EASING["SINEOUT"] = {cc.EaseSineOut, 1} - -local actionManager = cc.Director:getInstance():getActionManager() +ACTION_EASING["BACKIN"] = {ax.EaseBackIn, 1} +ACTION_EASING["BACKINOUT"] = {ax.EaseBackInOut, 1} +ACTION_EASING["BACKOUT"] = {ax.EaseBackOut, 1} +ACTION_EASING["BOUNCE"] = {ax.EaseBounce, 1} +ACTION_EASING["BOUNCEIN"] = {ax.EaseBounceIn, 1} +ACTION_EASING["BOUNCEINOUT"] = {ax.EaseBounceInOut, 1} +ACTION_EASING["BOUNCEOUT"] = {ax.EaseBounceOut, 1} +ACTION_EASING["ELASTIC"] = {ax.EaseElastic, 2, 0.3} +ACTION_EASING["ELASTICIN"] = {ax.EaseElasticIn, 2, 0.3} +ACTION_EASING["ELASTICINOUT"] = {ax.EaseElasticInOut, 2, 0.3} +ACTION_EASING["ELASTICOUT"] = {ax.EaseElasticOut, 2, 0.3} +ACTION_EASING["EXPONENTIALIN"] = {ax.EaseExponentialIn, 1} +ACTION_EASING["EXPONENTIALINOUT"] = {ax.EaseExponentialInOut, 1} +ACTION_EASING["EXPONENTIALOUT"] = {ax.EaseExponentialOut, 1} +ACTION_EASING["IN"] = {ax.EaseIn, 2, 1} +ACTION_EASING["INOUT"] = {ax.EaseInOut, 2, 1} +ACTION_EASING["OUT"] = {ax.EaseOut, 2, 1} +ACTION_EASING["RATEACTION"] = {ax.EaseRateAction, 2, 1} +ACTION_EASING["SINEIN"] = {ax.EaseSineIn, 1} +ACTION_EASING["SINEINOUT"] = {ax.EaseSineInOut, 1} +ACTION_EASING["SINEOUT"] = {ax.EaseSineOut, 1} + +local actionManager = ax.Director:getInstance():getActionManager() function transition.newEasing(action, easingName, more) local key = string.upper(tostring(easingName)) @@ -77,18 +77,18 @@ function transition.create(action, args) local actions = {} local delay = checknumber(args.delay) if delay > 0 then - actions[#actions + 1] = cc.DelayTime:create(delay) + actions[#actions + 1] = ax.DelayTime:create(delay) end actions[#actions + 1] = action local onComplete = args.onComplete if type(onComplete) ~= "function" then onComplete = nil end if onComplete then - actions[#actions + 1] = cc.CallFunc:create(onComplete) + actions[#actions + 1] = ax.CallFunc:create(onComplete) end if args.removeSelf then - actions[#actions + 1] = cc.RemoveSelf:create() + actions[#actions + 1] = ax.RemoveSelf:create() end if #actions > 1 then @@ -99,57 +99,57 @@ function transition.create(action, args) end function transition.execute(target, action, args) - assert(not tolua.isnull(target), "transition.execute() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.execute() - target is not ax.Node") local action = transition.create(action, args) target:runAction(action) return action end function transition.moveTo(target, args) - assert(not tolua.isnull(target), "transition.moveTo() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.moveTo() - target is not ax.Node") local x = args.x or target:getPositionX() local y = args.y or target:getPositionY() - local action = cc.MoveTo:create(args.time, cc.p(x, y)) + local action = ax.MoveTo:create(args.time, ax.p(x, y)) return transition.execute(target, action, args) end function transition.moveBy(target, args) - assert(not tolua.isnull(target), "transition.moveBy() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.moveBy() - target is not ax.Node") local x = args.x or 0 local y = args.y or 0 - local action = cc.MoveBy:create(args.time, cc.p(x, y)) + local action = ax.MoveBy:create(args.time, ax.p(x, y)) return transition.execute(target, action, args) end function transition.fadeIn(target, args) - assert(not tolua.isnull(target), "transition.fadeIn() - target is not cc.Node") - local action = cc.FadeIn:create(args.time) + assert(not tolua.isnull(target), "transition.fadeIn() - target is not ax.Node") + local action = ax.FadeIn:create(args.time) return transition.execute(target, action, args) end function transition.fadeOut(target, args) - assert(not tolua.isnull(target), "transition.fadeOut() - target is not cc.Node") - local action = cc.FadeOut:create(args.time) + assert(not tolua.isnull(target), "transition.fadeOut() - target is not ax.Node") + local action = ax.FadeOut:create(args.time) return transition.execute(target, action, args) end function transition.fadeTo(target, args) - assert(not tolua.isnull(target), "transition.fadeTo() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.fadeTo() - target is not ax.Node") local opacity = checkint(args.opacity) if opacity < 0 then opacity = 0 elseif opacity > 255 then opacity = 255 end - local action = cc.FadeTo:create(args.time, opacity) + local action = ax.FadeTo:create(args.time, opacity) return transition.execute(target, action, args) end function transition.scaleTo(target, args) - assert(not tolua.isnull(target), "transition.scaleTo() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.scaleTo() - target is not ax.Node") local action if args.scale then - action = cc.ScaleTo:create(checknumber(args.time), checknumber(args.scale)) + action = ax.ScaleTo:create(checknumber(args.time), checknumber(args.scale)) elseif args.scaleX or args.scaleY then local scaleX, scaleY if args.scaleX then @@ -162,29 +162,29 @@ function transition.scaleTo(target, args) else scaleY = target:getScaleY() end - action = cc.ScaleTo:create(checknumber(args.time), scaleX, scaleY) + action = ax.ScaleTo:create(checknumber(args.time), scaleX, scaleY) end return transition.execute(target, action, args) end function transition.rotateTo(target, args) - assert(not tolua.isnull(target), "transition.rotateTo() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.rotateTo() - target is not ax.Node") local rotation = args.rotation or target:getRotation() - local action = cc.RotateTo:create(args.time, rotation) + local action = ax.RotateTo:create(args.time, rotation) return transition.execute(target, action, args) end function transition.rotateBy(target, args) - assert(not tolua.isnull(target), "transition.rotateTo() - target is not cc.Node") + assert(not tolua.isnull(target), "transition.rotateTo() - target is not ax.Node") local rotation = args.rotation or 0 - local action = cc.RotateBy:create(args.time, rotation) + local action = ax.RotateBy:create(args.time, rotation) return transition.execute(target, action, args) end function transition.sequence(actions) if #actions < 1 then return end if #actions < 2 then return actions[1] end - return cc.Sequence:create(actions) + return ax.Sequence:create(actions) end function transition.removeAction(action) diff --git a/extensions/scripting/lua-bindings/script/init.lua b/extensions/scripting/lua-bindings/script/init.lua index 945437268aa0..d952d4260016 100644 --- a/extensions/scripting/lua-bindings/script/init.lua +++ b/extensions/scripting/lua-bindings/script/init.lua @@ -37,8 +37,8 @@ end -- < axmol-1.0 cc = ax -cc.Director.setDisplayStats = ax.Director.setStatsDisplay -cc.Sprite3D = ax.MeshRenderer +ax.Director.setDisplayStats = ax.Director.setStatsDisplay +ax.Sprite3D = ax.MeshRenderer ccexp = axexp ccui = axui ccb = axb diff --git a/extensions/scripting/lua-bindings/script/network/NetworkConstants.lua b/extensions/scripting/lua-bindings/script/network/NetworkConstants.lua index ee18d55ddab9..e6ed5ab3dbcb 100644 --- a/extensions/scripting/lua-bindings/script/network/NetworkConstants.lua +++ b/extensions/scripting/lua-bindings/script/network/NetworkConstants.lua @@ -1,19 +1,19 @@ -if nil == cc.XMLHttpRequest then +if nil == ax.XMLHttpRequest then return end -cc.WEBSOCKET_OPEN = 0 -cc.WEBSOCKET_MESSAGE = 1 -cc.WEBSOCKET_CLOSE = 2 -cc.WEBSOCKET_ERROR = 3 +ax.WEBSOCKET_OPEN = 0 +ax.WEBSOCKET_MESSAGE = 1 +ax.WEBSOCKET_CLOSE = 2 +ax.WEBSOCKET_ERROR = 3 -cc.WEBSOCKET_STATE_CONNECTING = 0 -cc.WEBSOCKET_STATE_OPEN = 1 -cc.WEBSOCKET_STATE_CLOSING = 2 -cc.WEBSOCKET_STATE_CLOSED = 3 +ax.WEBSOCKET_STATE_CONNECTING = 0 +ax.WEBSOCKET_STATE_OPEN = 1 +ax.WEBSOCKET_STATE_CLOSING = 2 +ax.WEBSOCKET_STATE_CLOSED = 3 -cc.XMLHTTPREQUEST_RESPONSE_STRING = 0 -cc.XMLHTTPREQUEST_RESPONSE_ARRAY_BUFFER = 1 -cc.XMLHTTPREQUEST_RESPONSE_BLOB = 2 -cc.XMLHTTPREQUEST_RESPONSE_DOCUMENT = 3 -cc.XMLHTTPREQUEST_RESPONSE_JSON = 4 +ax.XMLHTTPREQUEST_RESPONSE_STRING = 0 +ax.XMLHTTPREQUEST_RESPONSE_ARRAY_BUFFER = 1 +ax.XMLHTTPREQUEST_RESPONSE_BLOB = 2 +ax.XMLHTTPREQUEST_RESPONSE_DOCUMENT = 3 +ax.XMLHTTPREQUEST_RESPONSE_JSON = 4 diff --git a/extensions/scripting/lua-bindings/script/physics3d/physics3d-constants.lua b/extensions/scripting/lua-bindings/script/physics3d/physics3d-constants.lua index f33cef98c5a5..7761543ee184 100644 --- a/extensions/scripting/lua-bindings/script/physics3d/physics3d-constants.lua +++ b/extensions/scripting/lua-bindings/script/physics3d/physics3d-constants.lua @@ -1,17 +1,17 @@ -if nil == cc.Physics3DComponent then +if nil == ax.Physics3DComponent then return end -cc.Physics3DComponent.PhysicsSyncFlag = +ax.Physics3DComponent.PhysicsSyncFlag = { NONE = 0, - NODE_TO_PHYSICS = 1, + NODE_TO_PHYSICS = 1, PHYSICS_TO_NODE = 2, NODE_AND_NODE = 3, } -cc.Physics3DObject.PhysicsObjType = +ax.Physics3DObject.PhysicsObjType = { UNKNOWN = 0, RIGID_BODY = 1, -} \ No newline at end of file +} diff --git a/extensions/scripting/lua-bindings/script/ui/DeprecatedUIFunc.lua b/extensions/scripting/lua-bindings/script/ui/DeprecatedUIFunc.lua index 97b144581205..e3fadb408de6 100644 --- a/extensions/scripting/lua-bindings/script/ui/DeprecatedUIFunc.lua +++ b/extensions/scripting/lua-bindings/script/ui/DeprecatedUIFunc.lua @@ -54,13 +54,13 @@ end ccui.Text.getStringValue = TextBMFontDeprecated.getStringValue --functions of ccui.TextBMFont will be deprecated begin ---functions of cc.ShaderCache will be deprecated begin +--functions of ax.ShaderCache will be deprecated begin local ShaderCacheDeprecated = { } function ShaderCacheDeprecated.getProgram(self,strShader) - deprecatedTip("cc.ShaderCache:getProgram","cc.ShaderCache:getGLProgram") + deprecatedTip("ax.ShaderCache:getProgram","ax.ShaderCache:getGLProgram") return self:getGLProgram(strShader) end -cc.ShaderCache.getProgram = ShaderCacheDeprecated.getProgram +ax.ShaderCache.getProgram = ShaderCacheDeprecated.getProgram --functions of ccui.TextBMFont will be deprecated begin --functions of ccui.Widget will be deprecated begin diff --git a/extensions/spine/src/spine/SkeletonBatch.cpp b/extensions/spine/src/spine/SkeletonBatch.cpp index 78d9b3a82731..00cbdd5fa9c0 100644 --- a/extensions/spine/src/spine/SkeletonBatch.cpp +++ b/extensions/spine/src/spine/SkeletonBatch.cpp @@ -37,9 +37,8 @@ USING_NS_AX; using std::max; #define INITIAL_SIZE (10000) -#include "renderer/backend/DriverBase.h" -#include "renderer/Shaders.h" -#include "renderer/backend/Types.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/renderer/Shaders.h" namespace spine { @@ -59,8 +58,8 @@ namespace spine { SkeletonBatch::SkeletonBatch() { - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - _programState = new backend::ProgramState(program);// new default program state + auto program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR); + _programState = new rhi::ProgramState(program);// new default program state for (unsigned int i = 0; i < INITIAL_SIZE; i++) { _commandsPool.push_back(newCommand()); } @@ -76,7 +75,7 @@ namespace spine { Director::getInstance()->getEventDispatcher()->removeCustomEventListeners(EVENT_AFTER_DRAW_RESET_POSITION); for (unsigned int i = 0; i < _commandsPool.size(); i++) { - AX_SAFE_RELEASE(_commandsPool[i]->getPipelineDescriptor().programState); + AX_SAFE_RELEASE(_commandsPool[i]->getPipelineDesc().programState); delete _commandsPool[i]; _commandsPool[i] = nullptr; } @@ -84,9 +83,9 @@ namespace spine { AX_SAFE_RELEASE(_programState); } - backend::ProgramState* SkeletonBatch::updateCommandPipelinePS(SkeletonCommand* command, backend::ProgramState* programState) + rhi::ProgramState* SkeletonBatch::updateCommandPipelinePS(SkeletonCommand* command, rhi::ProgramState* programState) { - auto& currentState = command->getPipelineDescriptor().programState; + auto& currentState = command->getPipelineDesc().programState; #if defined(AX_VERSION) if (currentState == nullptr || currentState->getBatchId() != programState->getBatchId()) @@ -96,9 +95,9 @@ namespace spine { #endif AX_SAFE_RELEASE(currentState); currentState = programState->clone(); - - command->_locMVP = currentState->getUniformLocation(backend::UNIFORM_NAME_MVP_MATRIX); - command->_locTexture = currentState->getUniformLocation(backend::UNIFORM_NAME_TEXTURE); + + command->_locMVP = currentState->getUniformLocation(rhi::UNIFORM_NAME_MVP_MATRIX); + command->_locTexture = currentState->getUniformLocation(rhi::UNIFORM_NAME_TEXTURE); } return currentState; } @@ -107,11 +106,11 @@ namespace spine { reset(); } - axmol::V3F_C4B_T2F *SkeletonBatch::allocateVertices(uint32_t numVertices) { + axmol::V3F_T2F_C4B *SkeletonBatch::allocateVertices(uint32_t numVertices) { if (_vertices.size() - _numVertices < numVertices) { - axmol::V3F_C4B_T2F *oldData = _vertices.data(); + auto oldData = _vertices.data(); _vertices.resize((_vertices.size() + numVertices) * 2 + 1); - axmol::V3F_C4B_T2F *newData = _vertices.data(); + auto newData = _vertices.data(); for (uint32_t i = 0; i < this->_nextFreeCommand; i++) { SkeletonCommand *command = _commandsPool[i]; SkeletonCommand::Triangles &triangles = (SkeletonCommand::Triangles &) command->getTriangles(); @@ -119,7 +118,7 @@ namespace spine { } } - axmol::V3F_C4B_T2F *vertices = _vertices.data() + _numVertices; + axmol::V3F_T2F_C4B *vertices = _vertices.data() + _numVertices; _numVertices += numVertices; return vertices; } @@ -154,7 +153,7 @@ namespace spine { } - axmol::TrianglesCommand *SkeletonBatch::addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, backend::ProgramState *programState, axmol::BlendFunc blendType, const axmol::TrianglesCommand::Triangles &triangles, const axmol::Mat4 &mv, uint32_t flags) { + axmol::TrianglesCommand *SkeletonBatch::addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, rhi::ProgramState *programState, axmol::BlendFunc blendType, const axmol::TrianglesCommand::Triangles &triangles, const axmol::Mat4 &mv, uint32_t flags) { SkeletonCommand *command = nextFreeCommand(); const axmol::Mat4 &projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); diff --git a/extensions/spine/src/spine/SkeletonBatch.h b/extensions/spine/src/spine/SkeletonBatch.h index 4cff3ca3d36a..b326ecff0e20 100644 --- a/extensions/spine/src/spine/SkeletonBatch.h +++ b/extensions/spine/src/spine/SkeletonBatch.h @@ -30,16 +30,16 @@ #ifndef SPINE_SKELETONBATCH_H_ #define SPINE_SKELETONBATCH_H_ -#include "axmol.h" +#include "axmol/axmol.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/rhi/ProgramState.h" #include #include namespace spine { struct SkeletonCommand : public axmol::TrianglesCommand { - axmol::backend::UniformLocation _locMVP; - axmol::backend::UniformLocation _locTexture; + axmol::rhi::UniformLocation _locMVP; + axmol::rhi::UniformLocation _locTexture; }; class SP_API SkeletonBatch { public: @@ -49,13 +49,13 @@ namespace spine { void update(float delta); - axmol::V3F_C4B_T2F *allocateVertices(uint32_t numVertices); + axmol::V3F_T2F_C4B *allocateVertices(uint32_t numVertices); void deallocateVertices(uint32_t numVertices); unsigned short *allocateIndices(uint32_t numIndices); void deallocateIndices(uint32_t numVertices); - axmol::TrianglesCommand *addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, axmol::backend::ProgramState *programState, axmol::BlendFunc blendType, const axmol::TrianglesCommand::Triangles &triangles, const axmol::Mat4 &mv, uint32_t flags); + axmol::TrianglesCommand *addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, axmol::rhi::ProgramState *programState, axmol::BlendFunc blendType, const axmol::TrianglesCommand::Triangles &triangles, const axmol::Mat4 &mv, uint32_t flags); - axmol::backend::ProgramState* updateCommandPipelinePS(SkeletonCommand* command, axmol::backend::ProgramState* programState); + axmol::rhi::ProgramState* updateCommandPipelinePS(SkeletonCommand* command, axmol::rhi::ProgramState* programState); protected: SkeletonBatch(); @@ -67,14 +67,14 @@ namespace spine { SkeletonCommand* newCommand(); - ax::backend::ProgramState* _programState; // The default program state + ax::rhi::ProgramState* _programState; // The default program state // pool of commands std::vector _commandsPool; uint32_t _nextFreeCommand; // pool of vertices - std::vector _vertices; + std::vector _vertices; uint32_t _numVertices; // pool of indices diff --git a/extensions/spine/src/spine/SkeletonRenderer.cpp b/extensions/spine/src/spine/SkeletonRenderer.cpp index 022b1ba65be5..d1a29ffd2278 100644 --- a/extensions/spine/src/spine/SkeletonRenderer.cpp +++ b/extensions/spine/src/spine/SkeletonRenderer.cpp @@ -44,7 +44,6 @@ namespace spine { BlendFunc makeBlendFunc(BlendMode blendMode, bool premultipliedAlpha); void transformWorldVertices(float *dstCoord, int coordCount, Skeleton &skeleton, int startSlotIndex, int endSlotIndex); bool cullRectangle(Renderer *renderer, const Mat4 &transform, const axmol::Rect &rect); - Color4B ColorToColor4B(const Color &color); bool slotIsOutRange(Slot &slot, int startSlotIndex, int endSlotIndex); bool nothingToDraw(Slot &slot, int startSlotIndex, int endSlotIndex); }// namespace @@ -250,12 +249,12 @@ namespace spine { SkeletonTwoColorBatch *twoColorBatch = SkeletonTwoColorBatch::getInstance(); const bool hasSingleTint = (isTwoColorTint() == false); - const Color3B displayedColor = getDisplayedColor(); + auto&& displayedColor = getDisplayedColor(); Color nodeColor; nodeColor.r = displayedColor.r / 255.f; nodeColor.g = displayedColor.g / 255.f; nodeColor.b = displayedColor.b / 255.f; - nodeColor.a = getDisplayedOpacity() / 255.f; + nodeColor.a = displayedColor.a / 255.f; Color color; Color darkColor; @@ -287,11 +286,11 @@ namespace spine { triangles.vertCount = 4; assert(triangles.vertCount == 4); for (int v = 0, i = 0; v < triangles.vertCount; v++, i += 2) { - auto &texCoords = triangles.verts[v].texCoords; + auto &texCoords = triangles.verts[v].texCoord; texCoords.u = attachment->getUVs()[i]; texCoords.v = attachment->getUVs()[i + 1]; } - dstStride = sizeof(V3F_C4B_T2F) / sizeof(float); + dstStride = sizeof(V3F_T2F_C4B) / sizeof(float); dstTriangleVertices = reinterpret_cast(triangles.verts); } else { trianglesTwoColor.indices = quadIndices; @@ -300,7 +299,7 @@ namespace spine { trianglesTwoColor.vertCount = 4; assert(trianglesTwoColor.vertCount == 4); for (int v = 0, i = 0; v < trianglesTwoColor.vertCount; v++, i += 2) { - auto &texCoords = trianglesTwoColor.verts[v].texCoords; + auto &texCoords = trianglesTwoColor.verts[v].texCoord; texCoords.u = attachment->getUVs()[i]; texCoords.v = attachment->getUVs()[i + 1]; } @@ -325,12 +324,12 @@ namespace spine { triangles.verts = batch->allocateVertices((int)attachment->getWorldVerticesLength() / 2); triangles.vertCount = (int)attachment->getWorldVerticesLength() / 2; for (int v = 0, i = 0; v < triangles.vertCount; v++, i += 2) { - auto &texCoords = triangles.verts[v].texCoords; + auto &texCoords = triangles.verts[v].texCoord; texCoords.u = attachment->getUVs()[i]; texCoords.v = attachment->getUVs()[i + 1]; } dstTriangleVertices = (float *) triangles.verts; - dstStride = sizeof(V3F_C4B_T2F) / sizeof(float); + dstStride = sizeof(V3F_T2F_C4B) / sizeof(float); dstVertexCount = triangles.vertCount; } else { trianglesTwoColor.indices = attachment->getTriangles().buffer(); @@ -338,7 +337,7 @@ namespace spine { trianglesTwoColor.verts = twoColorBatch->allocateVertices((int)attachment->getWorldVerticesLength() / 2); trianglesTwoColor.vertCount = (int)attachment->getWorldVerticesLength() / 2; for (int v = 0, i = 0; v < trianglesTwoColor.vertCount; v++, i += 2) { - auto &texCoords = trianglesTwoColor.verts[v].texCoords; + auto &texCoords = trianglesTwoColor.verts[v].texCoord; texCoords.u = attachment->getUVs()[i]; texCoords.v = attachment->getUVs()[i + 1]; } @@ -385,14 +384,14 @@ namespace spine { color.b *= color.a; } - const axmol::Color4B color4B = ColorToColor4B(color); - const axmol::Color4B darkColor4B = ColorToColor4B(darkColor); + const ax::Color32 color_r{color}; + const ax::Color32 darkColor_r{darkColor}; const BlendFunc blendFunc = makeBlendFunc(slot->getData().getBlendMode(), texture->hasPremultipliedAlpha()); _blendFunc = blendFunc; if (hasSingleTint) { if (_clipper->isClipping()) { - _clipper->clipTriangles((float *) &triangles.verts[0].vertices, triangles.indices, triangles.indexCount, (float *) &triangles.verts[0].texCoords, sizeof(ax::V3F_C4B_T2F) / 4); + _clipper->clipTriangles((float *) &triangles.verts[0].position, triangles.indices, triangles.indexCount, (float *) &triangles.verts[0].texCoord, sizeof(axmol::V3F_T2F_C4B) / 4); batch->deallocateVertices(triangles.vertCount); if (_clipper->getClippedTriangles().size() == 0) { @@ -406,24 +405,26 @@ namespace spine { triangles.indices = batch->allocateIndices(triangles.indexCount); memcpy(triangles.indices, _clipper->getClippedTriangles().buffer(), sizeof(unsigned short) * _clipper->getClippedTriangles().size()); - const float* verts = _clipper->getClippedVertices().buffer(); - const float* uvs = _clipper->getClippedUVs().buffer(); - V3F_C4B_T2F* vertex = triangles.verts; - for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; ++v, vv += 2, ++vertex) - { - vertex->vertices.x = verts[vv]; - vertex->vertices.y = verts[vv + 1]; - vertex->texCoords.u = uvs[vv]; - vertex->texCoords.v = uvs[vv + 1]; - vertex->colors = color4B; + const float* verts = _clipper->getClippedVertices().buffer(); + const float* uvs = _clipper->getClippedUVs().buffer(); + auto vertex = triangles.verts; + for (int v = 0, vn = triangles.vertCount, vv = 0; v < vn; + ++v, vv += 2, ++vertex) + { + vertex->position.x = verts[vv]; + vertex->position.y = verts[vv + 1]; + vertex->texCoord.u = uvs[vv]; + vertex->texCoord.v = uvs[vv + 1]; + vertex->color = color_r; } batch->addCommand(renderer, _globalZOrder, texture, _programState, blendFunc, triangles, transform, transformFlags); } else { // Not clipping. - V3F_C4B_T2F* vertex = triangles.verts; - for (int v = 0, vn = triangles.vertCount; v < vn; ++v, ++vertex) - { - vertex->colors = color4B; + auto vertex = triangles.verts; + for (int v = 0, vn = triangles.vertCount; v < vn; + ++v, ++vertex) + { + vertex->color = color_r; } batch->addCommand(renderer, _globalZOrder, texture, _programState, blendFunc, triangles, transform, transformFlags); } @@ -431,7 +432,7 @@ namespace spine { // Two color tinting. if (_clipper->isClipping()) { - _clipper->clipTriangles((float *) &trianglesTwoColor.verts[0].position, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float *) &trianglesTwoColor.verts[0].texCoords, sizeof(V3F_C4B_C4B_T2F) / 4); + _clipper->clipTriangles((float *) &trianglesTwoColor.verts[0].position, trianglesTwoColor.indices, trianglesTwoColor.indexCount, (float *) &trianglesTwoColor.verts[0].texCoord, sizeof(V3F_C4B_C4B_T2F) / 4); twoColorBatch->deallocateVertices(trianglesTwoColor.vertCount); if (_clipper->getClippedTriangles().size() == 0) { @@ -448,23 +449,24 @@ namespace spine { const float* verts = _clipper->getClippedVertices().buffer(); const float* uvs = _clipper->getClippedUVs().buffer(); - V3F_C4B_C4B_T2F* vertex = trianglesTwoColor.verts; - for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; ++v, vv += 2, ++vertex) - { - vertex->position.x = verts[vv]; - vertex->position.y = verts[vv + 1]; - vertex->texCoords.u = uvs[vv]; - vertex->texCoords.v = uvs[vv + 1]; - vertex->color = color4B; - vertex->color2 = darkColor4B; + V3F_C4B_C4B_T2F* vertex = trianglesTwoColor.verts; + for (int v = 0, vn = trianglesTwoColor.vertCount, vv = 0; v < vn; + ++v, vv += 2, ++vertex) + { + vertex->position.x = verts[vv]; + vertex->position.y = verts[vv + 1]; + vertex->texCoord.u = uvs[vv]; + vertex->texCoord.v = uvs[vv + 1]; + vertex->color = color_r; + vertex->color2 = darkColor_r; } lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, texture, _programState, blendFunc, trianglesTwoColor, transform, transformFlags); } else { V3F_C4B_C4B_T2F* vertex = trianglesTwoColor.verts; for (int v = 0, vn = trianglesTwoColor.vertCount; v < vn; ++v, ++vertex) { - vertex->color = color4B; - vertex->color2 = darkColor4B; + vertex->color = color_r; + vertex->color2 = darkColor_r; } lastTwoColorTrianglesCommand = twoColorBatch->addCommand(renderer, _globalZOrder, texture, _programState, blendFunc, trianglesTwoColor, transform, transformFlags); } @@ -535,13 +537,12 @@ namespace spine { {brect.origin.x + brect.size.width, brect.origin.y}, {brect.origin.x + brect.size.width, brect.origin.y + brect.size.height}, {brect.origin.x, brect.origin.y + brect.size.height}}; - drawNode->drawPoly(points, 4, true, Color4B::GREEN, 2.0f); + drawNode->drawPoly(points, 4, true, ax::Color::GREEN, 2.0f); } if (_debugSlots) { // Slots. - // DrawPrimitives::setDrawColor4B(0, 0, 255, 255); - V3F_C4B_T2F_Quad quad; + // DrawPrimitives::setDrawColor32(0, 0, 255, 255); for (int i = 0, n = (int)_skeleton->getSlots().size(); i < n; i++) { Slot *slot = _skeleton->getDrawOrder()[i]; @@ -561,7 +562,7 @@ namespace spine { {worldVertices[2], worldVertices[3]}, {worldVertices[4], worldVertices[5]}, {worldVertices[6], worldVertices[7]}}; - drawNode->drawPoly(points, 4, true, Color4B::BLUE, 2.0f); + drawNode->drawPoly(points, 4, true, ax::Color::BLUE, 2.0f); } } @@ -572,15 +573,15 @@ namespace spine { if (!bone->isActive()) continue; float x = bone->getData().getLength() * bone->getA() + bone->getWorldX(); float y = bone->getData().getLength() * bone->getC() + bone->getWorldY(); - drawNode->drawLine(Vec2(bone->getWorldX(), bone->getWorldY()), Vec2(x, y), Color4B::RED, 2.0f); + drawNode->drawLine(Vec2(bone->getWorldX(), bone->getWorldY()), Vec2(x, y), ax::Color::RED, 2.0f); } // Bone origins. - auto color = Color4B::BLUE;// Root bone is blue. + auto color = ax::Color::BLUE; // Root bone is blue. for (int i = 0, n = (int)_skeleton->getBones().size(); i < n; i++) { Bone *bone = _skeleton->getBones()[i]; if (!bone->isActive()) continue; drawNode->drawPoint(Vec2(bone->getWorldX(), bone->getWorldY()), 4, color); - if (i == 0) color = Color4B::GREEN; + if (i == 0) color = ax::Color::GREEN; } } @@ -603,7 +604,7 @@ namespace spine { worldCoord + (idx0 * 2), worldCoord + (idx1 * 2), worldCoord + (idx2 * 2)}; - drawNode->drawPoly(v, 3, true, Color4B::YELLOW, 2.0f); + drawNode->drawPoly(v, 3, true, ax::Color::YELLOW, 2.0f); } VLA_FREE(worldCoord); } @@ -862,20 +863,20 @@ namespace spine { BlendFunc blendFunc; switch (blendMode) { case BlendMode_Additive: - blendFunc.src = premultipliedAlpha ? backend::BlendFactor::ONE : backend::BlendFactor::SRC_ALPHA; - blendFunc.dst = backend::BlendFactor::ONE; + blendFunc.src = premultipliedAlpha ? rhi::BlendFactor::ONE : rhi::BlendFactor::SRC_ALPHA; + blendFunc.dst = rhi::BlendFactor::ONE; break; case BlendMode_Multiply: - blendFunc.src = backend::BlendFactor::DST_COLOR; - blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendFunc.src = rhi::BlendFactor::DST_COLOR; + blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; break; case BlendMode_Screen: - blendFunc.src = backend::BlendFactor::ONE; - blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_COLOR; + blendFunc.src = rhi::BlendFactor::ONE; + blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_COLOR; break; default: - blendFunc.src = premultipliedAlpha ? backend::BlendFactor::ONE : backend::BlendFactor::SRC_ALPHA; - blendFunc.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendFunc.src = premultipliedAlpha ? rhi::BlendFactor::ONE : rhi::BlendFactor::SRC_ALPHA; + blendFunc.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } return blendFunc; } @@ -912,10 +913,6 @@ namespace spine { return !visibleRect.containsPoint(v2p); } - - Color4B ColorToColor4B(const Color &color) { - return {(uint8_t) (color.r * 255.f), (uint8_t) (color.g * 255.f), (uint8_t) (color.b * 255.f), (uint8_t) (color.a * 255.f)}; - } }// namespace }// namespace spine diff --git a/extensions/spine/src/spine/SkeletonRenderer.h b/extensions/spine/src/spine/SkeletonRenderer.h index ef50fde40fe1..a0ec0139bae9 100644 --- a/extensions/spine/src/spine/SkeletonRenderer.h +++ b/extensions/spine/src/spine/SkeletonRenderer.h @@ -30,7 +30,7 @@ #ifndef SPINE_SKELETONRENDERER_H_ #define SPINE_SKELETONRENDERER_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include namespace spine { diff --git a/extensions/spine/src/spine/SkeletonTwoColorBatch.cpp b/extensions/spine/src/spine/SkeletonTwoColorBatch.cpp index 0656ffb0b34d..ace0d2b2fc3c 100644 --- a/extensions/spine/src/spine/SkeletonTwoColorBatch.cpp +++ b/extensions/spine/src/spine/SkeletonTwoColorBatch.cpp @@ -29,14 +29,14 @@ #include -#include "base/Types.h" -#include "base/Utils.h" +#include "axmol/base/Types.h" +#include "axmol/base/Utils.h" #include #include #include // offsetof -#include "renderer/backend/DriverBase.h" -#include "renderer/Shaders.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/renderer/Shaders.h" #include "xxhash.h" USING_NS_AX; @@ -48,28 +48,28 @@ using std::max; namespace { - std::shared_ptr __twoColorProgramState = nullptr; - backend::UniformLocation __locPMatrix; - backend::UniformLocation __locTexture; + std::shared_ptr __twoColorProgramState = nullptr; + rhi::UniformLocation __locPMatrix; + rhi::UniformLocation __locTexture; - static void updateProgramStateLayout(backend::ProgramState *programState) { + static void updateProgramStateLayout(rhi::ProgramState *programState) { __locPMatrix = programState->getUniformLocation("u_PMatrix"); __locTexture = programState->getUniformLocation("u_tex0"); - auto locPosition = programState->getAttributeLocation("a_position"); - auto locTexcoord = programState->getAttributeLocation("a_texCoord"); - auto locColor = programState->getAttributeLocation("a_color"); - auto locColor2 = programState->getAttributeLocation("a_color2"); + auto locPosition = programState->getVertexInputDesc("a_position"); + auto locTexcoord = programState->getVertexInputDesc("a_texCoord"); + auto locColor = programState->getVertexInputDesc("a_color"); + auto locColor2 = programState->getVertexInputDesc("a_color2"); auto vertexLayout = programState->getMutableVertexLayout(); - vertexLayout->setAttrib("a_position", locPosition, backend::VertexFormat::FLOAT3, + vertexLayout->setAttrib("a_position", locPosition, rhi::VertexFormat::FLOAT3, offsetof(spine::V3F_C4B_C4B_T2F, position), false); - vertexLayout->setAttrib("a_color", locColor, backend::VertexFormat::UBYTE4, + vertexLayout->setAttrib("a_color", locColor, rhi::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color), true); - vertexLayout->setAttrib("a_color2", locColor2, backend::VertexFormat::UBYTE4, + vertexLayout->setAttrib("a_color2", locColor2, rhi::VertexFormat::UBYTE4, offsetof(spine::V3F_C4B_C4B_T2F, color2), true); - vertexLayout->setAttrib("a_texCoord", locTexcoord, backend::VertexFormat::FLOAT2, - offsetof(spine::V3F_C4B_C4B_T2F, texCoords), false); + vertexLayout->setAttrib("a_texCoord", locTexcoord, rhi::VertexFormat::FLOAT2, + offsetof(spine::V3F_C4B_C4B_T2F, texCoord), false); vertexLayout->setStride(sizeof(spine::V3F_C4B_C4B_T2F)); } @@ -79,10 +79,10 @@ namespace { } auto program = ProgramManager::getInstance()->loadProgram("custom/spineTwoColorTint_vs", "custom/spineTwoColorTint_fs"); - auto *programState = new backend::ProgramState(program); + auto *programState = new rhi::ProgramState(program); updateProgramStateLayout(programState); - __twoColorProgramState = std::shared_ptr(programState); + __twoColorProgramState = std::shared_ptr(programState); } }// namespace @@ -93,7 +93,7 @@ namespace spine { _type = RenderCommand::Type::CUSTOM_COMMAND; } - void TwoColorTrianglesCommand::init(float globalOrder, axmol::Texture2D *texture, axmol::backend::ProgramState *programState, BlendFunc blendType, const TwoColorTriangles &triangles, const Mat4 &mv, uint32_t flags) { + void TwoColorTrianglesCommand::init(float globalOrder, axmol::Texture2D *texture, axmol::rhi::ProgramState *programState, BlendFunc blendType, const TwoColorTriangles &triangles, const Mat4 &mv, uint32_t flags) { updateCommandPipelineDescriptor(programState); const axmol::Mat4 &projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); @@ -116,13 +116,13 @@ namespace spine { _mv = mv; if (_blendType.src != blendType.src || _blendType.dst != blendType.dst || - _texture != texture->getBackendTexture() || _pipelineDescriptor.programState != _programState) { + _texture != texture->getBackendTexture() || _pipelineDesc.programState != _programState) { _texture = texture->getBackendTexture(); _blendType = blendType; _prog = _programState->getProgram(); - auto &blendDescriptor = _pipelineDescriptor.blendDescriptor; + auto &blendDescriptor = _pipelineDesc.blendDesc; blendDescriptor.blendEnabled = true; blendDescriptor.sourceRGBBlendFactor = blendDescriptor.sourceAlphaBlendFactor = blendType.src; blendDescriptor.destinationRGBBlendFactor = blendDescriptor.destinationAlphaBlendFactor = blendType.dst; @@ -132,14 +132,14 @@ namespace spine { } - void TwoColorTrianglesCommand::updateCommandPipelineDescriptor(axmol::backend::ProgramState *programState) { + void TwoColorTrianglesCommand::updateCommandPipelineDescriptor(axmol::rhi::ProgramState *programState) { // OPTIMIZE ME: all commands belong a same Node should share a same programState like SkeletonBatch if (!__twoColorProgramState) { initTwoColorProgramState(); } bool needsUpdateStateLayout = false; - auto &pipelinePS = _pipelineDescriptor.programState; + auto &pipelinePS = _pipelineDesc.programState; if (programState != nullptr) { if (_programState != programState) { AX_SAFE_RELEASE(_programState); @@ -175,8 +175,8 @@ namespace spine { { void *texture; void *prog; - backend::BlendFactor src; - backend::BlendFactor dst; + rhi::BlendFactor src; + rhi::BlendFactor dst; } hashMe; // NOTE: Initialize hashMe struct to make the value of padding bytes be filled with zero. @@ -299,7 +299,7 @@ namespace spine { _indices.setSize(_indices.size() - numIndices, 0); } - TwoColorTrianglesCommand *SkeletonTwoColorBatch::addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, backend::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags) { + TwoColorTrianglesCommand *SkeletonTwoColorBatch::addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, rhi::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags) { TwoColorTrianglesCommand *command = nextFreeCommand(); command->init(globalOrder, texture, programState, blendType, triangles, mv, flags); command->updateVertexAndIndexBuffer(renderer, triangles.verts, triangles.vertCount, triangles.indices, triangles.indexCount); diff --git a/extensions/spine/src/spine/SkeletonTwoColorBatch.h b/extensions/spine/src/spine/SkeletonTwoColorBatch.h index 366c17ea08f7..4c10d85f49b8 100644 --- a/extensions/spine/src/spine/SkeletonTwoColorBatch.h +++ b/extensions/spine/src/spine/SkeletonTwoColorBatch.h @@ -30,17 +30,17 @@ #ifndef SPINE_SKELETONTWOCOLORBATCH_H_ #define SPINE_SKELETONTWOCOLORBATCH_H_ -#include "axmol.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/axmol.h" +#include "axmol/rhi/ProgramState.h" #include #include namespace spine { struct V3F_C4B_C4B_T2F { axmol::Vec3 position; - axmol::Color4B color; - axmol::Color4B color2; - axmol::Tex2F texCoords; + axmol::Color32 color; + axmol::Color32 color2; + axmol::Tex2F texCoord; }; struct TwoColorTriangles { @@ -56,11 +56,11 @@ namespace spine { ~TwoColorTrianglesCommand(); - void init(float globalOrder, axmol::Texture2D *texture, axmol::backend::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags); + void init(float globalOrder, axmol::Texture2D *texture, axmol::rhi::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags); - void updateCommandPipelineDescriptor(axmol::backend::ProgramState *programState); + void updateCommandPipelineDescriptor(axmol::rhi::ProgramState *programState); - inline axmol::backend::TextureBackend *getTexture() const { return _texture; } + inline axmol::rhi::Texture *getTexture() const { return _texture; } void draw(axmol::Renderer *renderer); @@ -92,10 +92,10 @@ namespace spine { void *_prog = nullptr; - axmol::backend::TextureBackend *_texture = nullptr; - axmol::backend::ProgramState *_programState = nullptr; - axmol::backend::UniformLocation _locPMatrix; - axmol::backend::UniformLocation _locTexture; + axmol::rhi::Texture *_texture = nullptr; + axmol::rhi::ProgramState *_programState = nullptr; + axmol::rhi::UniformLocation _locPMatrix; + axmol::rhi::UniformLocation _locTexture; axmol::BlendFunc _blendType; TwoColorTriangles _triangles; @@ -117,7 +117,7 @@ namespace spine { unsigned short *allocateIndices(uint32_t numIndices); void deallocateIndices(uint32_t numIndices); - TwoColorTrianglesCommand *addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, axmol::backend::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags); + TwoColorTrianglesCommand *addCommand(axmol::Renderer *renderer, float globalOrder, axmol::Texture2D *texture, axmol::rhi::ProgramState *programState, axmol::BlendFunc blendType, const TwoColorTriangles &triangles, const axmol::Mat4 &mv, uint32_t flags); void batch(axmol::Renderer *renderer, TwoColorTrianglesCommand *command); diff --git a/extensions/spine/src/spine/spine-axmol.cpp b/extensions/spine/src/spine/spine-axmol.cpp index 0c46d3e70bfa..0e4d232c34af 100644 --- a/extensions/spine/src/spine/spine-axmol.cpp +++ b/extensions/spine/src/spine/spine-axmol.cpp @@ -41,30 +41,52 @@ AxmolAtlasAttachmentLoader::~AxmolAtlasAttachmentLoader() {} void AxmolAtlasAttachmentLoader::configureAttachment(Attachment *attachment) { } -backend::SamplerAddressMode wrap(TextureWrap wrap) { - return wrap == TextureWrap_ClampToEdge ? backend::SamplerAddressMode::CLAMP_TO_EDGE : backend::SamplerAddressMode::REPEAT; -} - -backend::SamplerFilter filter(TextureFilter filter) { - switch (filter) { - case TextureFilter_Unknown: - break; - case TextureFilter_Nearest: - return backend::SamplerFilter::NEAREST; - case TextureFilter_Linear: - return backend::SamplerFilter::LINEAR; - case TextureFilter_MipMap: - return backend::SamplerFilter::LINEAR; - case TextureFilter_MipMapNearestNearest: - return backend::SamplerFilter::NEAREST; - case TextureFilter_MipMapLinearNearest: - return backend::SamplerFilter::NEAREST; - case TextureFilter_MipMapNearestLinear: - return backend::SamplerFilter::LINEAR; - case TextureFilter_MipMapLinearLinear: - return backend::SamplerFilter::LINEAR; - } - return backend::SamplerFilter::LINEAR; +static Texture2D::TexParams chooseTexParams(spine::AtlasPage& page) +{ + Texture2D::TexParams texParams{}; + switch (page.minFilter) + { + case TextureFilter_Linear: + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + break; + case TextureFilter_Nearest: + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; + break; + case TextureFilter_MipMap: + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + break; + case TextureFilter_MipMapNearestNearest: + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; + texParams.mipFilter = rhi::SamplerFilter::MIP_NEAREST; + break; + case TextureFilter_MipMapLinearNearest: + texParams.minFilter = rhi::SamplerFilter::MIN_NEAREST; + texParams.mipFilter = rhi::SamplerFilter::MIP_LINEAR; + break; + case TextureFilter_MipMapNearestLinear: + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + texParams.mipFilter = rhi::SamplerFilter::MIP_NEAREST; + break; + case TextureFilter_MipMapLinearLinear: + texParams.minFilter = rhi::SamplerFilter::MIN_LINEAR; + texParams.mipFilter = rhi::SamplerFilter::MIP_LINEAR; + break; + } + switch (page.magFilter) + { + case TextureFilter_Linear: + texParams.magFilter = rhi::SamplerFilter::MAG_LINEAR; + break; + case TextureFilter_Nearest: + texParams.magFilter = rhi::SamplerFilter::MAG_NEAREST; + break; + } + + texParams.sAddressMode = page.uWrap == TextureWrap_ClampToEdge ? rhi::SamplerAddressMode::CLAMP_TO_EDGE + : rhi::SamplerAddressMode::REPEAT; + texParams.tAddressMode = page.vWrap == TextureWrap_ClampToEdge ? rhi::SamplerAddressMode::CLAMP_TO_EDGE + : rhi::SamplerAddressMode::REPEAT; + return texParams; } AxmolTextureLoader::AxmolTextureLoader() : TextureLoader() {} @@ -75,8 +97,8 @@ void AxmolTextureLoader::load(AtlasPage &page, const spine::String &path) { AXASSERT(texture != nullptr, "Invalid image"); if (texture) { texture->retain(); - Texture2D::TexParams textureParams(filter(page.minFilter), filter(page.magFilter), wrap(page.uWrap), wrap(page.vWrap)); - texture->setTexParameters(textureParams); + Texture2D::TexParams texParams = chooseTexParams(page); + texture->setTexParameters(texParams); page.texture = texture; page.width = texture->getPixelsWide(); diff --git a/extensions/spine/src/spine/spine-axmol.h b/extensions/spine/src/spine/spine-axmol.h index 4505f091ce5f..a45167487bf9 100644 --- a/extensions/spine/src/spine/spine-axmol.h +++ b/extensions/spine/src/spine/spine-axmol.h @@ -30,7 +30,7 @@ #ifndef SPINE_AXMOL_H_ #define SPINE_AXMOL_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/templates/common/cmake/modules/AXGameEngineSetup.cmake b/templates/common/cmake/modules/AXGameEngineSetup.cmake index 92656c0cc0d8..3f20bb57d050 100644 --- a/templates/common/cmake/modules/AXGameEngineSetup.cmake +++ b/templates/common/cmake/modules/AXGameEngineSetup.cmake @@ -26,5 +26,5 @@ if(NOT _is_axmol_embed) endif() if(NOT _AX_USE_PREBUILT) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() diff --git a/templates/common/proj.android/app/AndroidManifest.xml b/templates/common/proj.android/app/AndroidManifest.xml index 07dbf865abed..2aa68c192353 100644 --- a/templates/common/proj.android/app/AndroidManifest.xml +++ b/templates/common/proj.android/app/AndroidManifest.xml @@ -18,7 +18,7 @@ android:screenOrientation="sensorLandscape" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:launchMode="singleTask" android:taskAffinity="" android:exported="true" > diff --git a/templates/common/proj.android/app/build.gradle b/templates/common/proj.android/app/build.gradle index ca7c2b39044c..c01f1bf4da7a 100644 --- a/templates/common/proj.android/app/build.gradle +++ b/templates/common/proj.android/app/build.gradle @@ -116,6 +116,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/templates/common/proj.android/settings.gradle b/templates/common/proj.android/settings.gradle index f3ef0536d1a6..6a179378dac6 100644 --- a/templates/common/proj.android/settings.gradle +++ b/templates/common/proj.android/settings.gradle @@ -8,7 +8,7 @@ if (folder.exists()) { } include ':libaxmol' -project(':libaxmol').projectDir = new File(Paths.get("${System.properties.AX_ROOT}/core/platform/android/libaxmol").toUri()) +project(':libaxmol').projectDir = new File(Paths.get("${System.properties.AX_ROOT}/axmol/platform/android/libaxmol").toUri()) include ':Dummy' project(':Dummy').projectDir = new File(settingsDir, 'app') rootProject.name = "Dummy" diff --git a/templates/common/proj.ios_mac/ios/AppController.mm b/templates/common/proj.ios_mac/ios/AppController.mm index c38fa83b085b..32fe152021ea 100644 --- a/templates/common/proj.ios_mac/ios/AppController.mm +++ b/templates/common/proj.ios_mac/ios/AppController.mm @@ -26,7 +26,7 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import "AppController.h" -#import "axmol.h" +#import "axmol/axmol.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/templates/common/proj.ios_mac/ios/RootViewController.mm b/templates/common/proj.ios_mac/ios/RootViewController.mm index b8417db20fba..ad5fe0cbf6e5 100644 --- a/templates/common/proj.ios_mac/ios/RootViewController.mm +++ b/templates/common/proj.ios_mac/ios/RootViewController.mm @@ -26,8 +26,8 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import "RootViewController.h" -#import "axmol.h" -#import "platform/ios/EARenderView-ios.h" +#import "axmol/axmol.h" +#import "axmol/platform/ios/EARenderView-ios.h" @implementation RootViewController diff --git a/templates/common/proj.ios_mac/mac/main.cpp b/templates/common/proj.ios_mac/mac/main.cpp index 6060c9e0177a..ee1359d43a73 100644 --- a/templates/common/proj.ios_mac/mac/main.cpp +++ b/templates/common/proj.ios_mac/mac/main.cpp @@ -25,7 +25,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" using namespace ax; diff --git a/templates/common/proj.wasm/main.cpp b/templates/common/proj.wasm/main.cpp index 0024f86c5ca0..3a55b1982c78 100644 --- a/templates/common/proj.wasm/main.cpp +++ b/templates/common/proj.wasm/main.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/templates/common/proj.win32/main.cpp b/templates/common/proj.win32/main.cpp index 95a3ffac15e9..d84802a4d96d 100644 --- a/templates/common/proj.win32/main.cpp +++ b/templates/common/proj.win32/main.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "AppDelegate.h" -#include "platform/Application.h" +#include "axmol/platform/Application.h" // Uncomment to enable win32 console #define USE_WIN32_CONSOLE @@ -46,7 +46,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL UNREFERENCED_PARAMETER(lpCmdLine); #ifdef USE_WIN32_CONSOLE -# include "platform/win32/EmbedConsole.h" +# include "axmol/platform/win32/EmbedConsole.h" #endif auto result = axmol_main(); diff --git a/templates/common/proj.win32/main.h b/templates/common/proj.win32/main.h index 4af11aba3ffd..da35903200a3 100644 --- a/templates/common/proj.win32/main.h +++ b/templates/common/proj.win32/main.h @@ -32,5 +32,5 @@ #include // C RunTime Header Files -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" diff --git a/templates/cpp/Source/AppDelegate.cpp b/templates/cpp/Source/AppDelegate.cpp index a3d8df828098..108b775bb44c 100644 --- a/templates/cpp/Source/AppDelegate.cpp +++ b/templates/cpp/Source/AppDelegate.cpp @@ -29,7 +29,7 @@ #define USE_AUDIO_ENGINE 1 #if USE_AUDIO_ENGINE -# include "audio/AudioEngine.h" +# include "axmol/audio/AudioEngine.h" #endif using namespace ax; diff --git a/templates/cpp/Source/AppDelegate.h b/templates/cpp/Source/AppDelegate.h index 48e9703e5e7c..30b8993df9c3 100644 --- a/templates/cpp/Source/AppDelegate.h +++ b/templates/cpp/Source/AppDelegate.h @@ -25,7 +25,7 @@ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" /** @brief The axmol Application. diff --git a/templates/cpp/Source/MainScene.cpp b/templates/cpp/Source/MainScene.cpp index a247b0ecc989..9ab9893da28e 100644 --- a/templates/cpp/Source/MainScene.cpp +++ b/templates/cpp/Source/MainScene.cpp @@ -133,7 +133,7 @@ bool MainScene::init() drawNode->setPosition(Vec2(0, 0)); addChild(drawNode); - drawNode->drawRect(safeArea.origin + Vec2(1, 1), safeArea.origin + safeArea.size, Color4F::BLUE); + drawNode->drawRect(safeArea.origin + Vec2(1, 1), safeArea.origin + safeArea.size, Color::BLUE); } // scheduleUpdate() is required to ensure update(float) is called on every loop diff --git a/templates/cpp/Source/MainScene.h b/templates/cpp/Source/MainScene.h index c4c30f9d4db5..7ecb3bde7986 100644 --- a/templates/cpp/Source/MainScene.h +++ b/templates/cpp/Source/MainScene.h @@ -25,7 +25,7 @@ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" class MainScene : public ax::Scene { diff --git a/templates/lua/Source/AppDelegate.cpp b/templates/lua/Source/AppDelegate.cpp index b09f1cc44df5..5e7e2e6c38fb 100644 --- a/templates/lua/Source/AppDelegate.cpp +++ b/templates/lua/Source/AppDelegate.cpp @@ -30,7 +30,7 @@ #define USE_AUDIO_ENGINE 1 #if USE_AUDIO_ENGINE -# include "audio/AudioEngine.h" +# include "axmol/audio/AudioEngine.h" #endif using namespace ax; diff --git a/templates/lua/Source/AppDelegate.h b/templates/lua/Source/AppDelegate.h index 52971ac43e64..15b78cd656b0 100644 --- a/templates/lua/Source/AppDelegate.h +++ b/templates/lua/Source/AppDelegate.h @@ -25,7 +25,7 @@ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" /** @brief The axmol Application. @@ -56,4 +56,4 @@ class AppDelegate : private ax::Application @brief Called when the application reenters the foreground */ void applicationWillEnterForeground() override; -}; \ No newline at end of file +}; diff --git a/tests/cpp-tests/CMakeLists.txt b/tests/cpp-tests/CMakeLists.txt index beb1a98ca94a..0a3f741a52df 100644 --- a/tests/cpp-tests/CMakeLists.txt +++ b/tests/cpp-tests/CMakeLists.txt @@ -29,7 +29,7 @@ if(NOT DEFINED BUILD_ENGINE_DONE) set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/Modules/) include(AXBuildSet) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() _1kfetch(sample-assets) @@ -140,7 +140,6 @@ list(APPEND GAME_HEADER Source/VibrateTest/VibrateTest.h Source/ClippingNodeTest/ClippingNodeTest.h Source/UserDefaultTest/UserDefaultTest.h - Source/ImGuiTest/ImGuiTest.h Source/tests.h Source/DataVisitorTest/DataVisitorTest.h Source/NewAudioEngineTest/NewAudioEngineTest.h @@ -360,7 +359,6 @@ list(APPEND GAME_SOURCE Source/UITest/CocoStudioGUITest/UITabControlTest/UITabControlTest.cpp Source/UITest/UITest.cpp Source/UserDefaultTest/UserDefaultTest.cpp - Source/ImGuiTest/ImGuiTest.cpp Source/VisibleRect.cpp Source/VibrateTest/VibrateTest.cpp Source/SpriteFrameCacheTest/SpriteFrameCacheTest.cpp @@ -403,75 +401,13 @@ list(APPEND GAME_SOURCE Source/Box2DTest/Box2dTest.cpp ) -if((WINDOWS OR MACOSX OR LINUX OR WASM) AND (NOT WINRT)) - list(APPEND GAME_HEADER - Source/Box2DTestBed/tests/test.h - Source/Box2DTestBed/tests/settings.h - Source/Box2DTestBed/Box2DTestBed.h - ) - - list(APPEND GAME_SOURCE - Source/Box2DTestBed/Box2DTestBed.cpp - Source/Box2DTestBed/test.cpp - Source/Box2DTestBed/tests/add_pair.cpp - Source/Box2DTestBed/tests/apply_force.cpp - Source/Box2DTestBed/tests/body_types.cpp - Source/Box2DTestBed/tests/box_stack.cpp - Source/Box2DTestBed/tests/breakable.cpp - Source/Box2DTestBed/tests/bridge.cpp - Source/Box2DTestBed/tests/bullet_test.cpp - Source/Box2DTestBed/tests/cantilever.cpp - Source/Box2DTestBed/tests/car.cpp - Source/Box2DTestBed/tests/chain.cpp - Source/Box2DTestBed/tests/chain_problem.cpp - Source/Box2DTestBed/tests/character_collision.cpp - Source/Box2DTestBed/tests/circle_stack.cpp - Source/Box2DTestBed/tests/collision_filtering.cpp - Source/Box2DTestBed/tests/collision_processing.cpp - Source/Box2DTestBed/tests/compound_shapes.cpp - Source/Box2DTestBed/tests/confined.cpp - Source/Box2DTestBed/tests/continuous_test.cpp - Source/Box2DTestBed/tests/convex_hull.cpp - Source/Box2DTestBed/tests/conveyor_belt.cpp - Source/Box2DTestBed/tests/distance_joint.cpp - Source/Box2DTestBed/tests/distance_test.cpp - Source/Box2DTestBed/tests/dominos.cpp - Source/Box2DTestBed/tests/dump_loader.cpp - Source/Box2DTestBed/tests/dynamic_tree.cpp - Source/Box2DTestBed/tests/edge_shapes.cpp - Source/Box2DTestBed/tests/edge_test.cpp - Source/Box2DTestBed/tests/friction.cpp - Source/Box2DTestBed/tests/gear_joint.cpp - Source/Box2DTestBed/tests/heavy1.cpp - Source/Box2DTestBed/tests/heavy2.cpp - Source/Box2DTestBed/tests/mobile_balanced.cpp - Source/Box2DTestBed/tests/mobile_unbalanced.cpp - Source/Box2DTestBed/tests/motor_joint.cpp - Source/Box2DTestBed/tests/pinball.cpp - Source/Box2DTestBed/tests/platformer.cpp - Source/Box2DTestBed/tests/polygon_collision.cpp - Source/Box2DTestBed/tests/polygon_shapes.cpp - Source/Box2DTestBed/tests/prismatic_joint.cpp - Source/Box2DTestBed/tests/pulley_joint.cpp - Source/Box2DTestBed/tests/pyramid.cpp - Source/Box2DTestBed/tests/ray_cast.cpp - Source/Box2DTestBed/tests/restitution.cpp - Source/Box2DTestBed/tests/revolute_joint.cpp - Source/Box2DTestBed/tests/rope.cpp - Source/Box2DTestBed/tests/sensor.cpp - Source/Box2DTestBed/tests/shape_cast.cpp - Source/Box2DTestBed/tests/shape_editing.cpp - Source/Box2DTestBed/tests/skier.cpp - Source/Box2DTestBed/tests/slider_crank_1.cpp - Source/Box2DTestBed/tests/slider_crank_2.cpp - Source/Box2DTestBed/tests/theo_jansen.cpp - Source/Box2DTestBed/tests/tiles.cpp - Source/Box2DTestBed/tests/time_of_impact.cpp - Source/Box2DTestBed/tests/tumbler.cpp - Source/Box2DTestBed/tests/web.cpp - Source/Box2DTestBed/tests/wheel_joint.cpp - Source/Box2DTestBed/tests/wrecking_ball.cpp - ) +if(AX_ENABLE_EXT_IMGUI) + list(APPEND GAME_HEADER Source/ImGuiTest/ImGuiTest.h) + list(APPEND GAME_SOURCE Source/ImGuiTest/ImGuiTest.cpp) + if((WINDOWS OR MACOSX OR LINUX OR WASM) AND (NOT WINRT)) + file(GLOB_RECURSE BOX2D_TESTBED_SOURCES Source/Box2DTestBed/*.h;Source/Box2DTestBed/*.cpp;Source/Box2DTestBed/*.c) + list(APPEND GAME_SOURCE ${BOX2D_TESTBED_SOURCES}) + endif() endif() list(APPEND GAME_HEADER @@ -484,51 +420,12 @@ list(APPEND GAME_SOURCE ) list(APPEND GAME_HEADER Source/PhysicsTest/PhysicsTest.h - Source/ChipmunkTest/ChipmunkTest.h ) list(APPEND GAME_SOURCE Source/PhysicsTest/PhysicsTest.cpp - Source/ChipmunkTest/ChipmunkTest.cpp ) -if(WINDOWS OR MACOSX OR LINUX OR WASM) - list(APPEND GAME_HEADER - Source/ChipmunkTestBed/demo/ChipmunkDemo.h - Source/ChipmunkTestBed/ChipmunkTestBed.h - ) - set (TESTBED_C_SORUCES - Source/ChipmunkTestBed/demo/Bench.cpp - Source/ChipmunkTestBed/demo/Chains.cpp - Source/ChipmunkTestBed/demo/Convex.cpp - Source/ChipmunkTestBed/demo/Crane.cpp - Source/ChipmunkTestBed/demo/Joints.cpp - Source/ChipmunkTestBed/demo/LogoSmash.cpp - Source/ChipmunkTestBed/demo/OneWay.cpp - Source/ChipmunkTestBed/demo/Planet.cpp - Source/ChipmunkTestBed/demo/Player.cpp - Source/ChipmunkTestBed/demo/Plink.cpp - Source/ChipmunkTestBed/demo/Pump.cpp - Source/ChipmunkTestBed/demo/PyramidStack.cpp - Source/ChipmunkTestBed/demo/PyramidTopple.cpp - Source/ChipmunkTestBed/demo/Shatter.cpp - Source/ChipmunkTestBed/demo/Springies.cpp - Source/ChipmunkTestBed/demo/Sticky.cpp - Source/ChipmunkTestBed/demo/Tank.cpp - Source/ChipmunkTestBed/demo/TheoJansen.cpp - Source/ChipmunkTestBed/demo/Buoyancy.cpp - Source/ChipmunkTestBed/demo/ContactGraph.cpp - Source/ChipmunkTestBed/demo/Example.cpp - Source/ChipmunkTestBed/demo/Query.cpp - Source/ChipmunkTestBed/demo/Slice.cpp - Source/ChipmunkTestBed/demo/Unicycle.cpp - Source/ChipmunkTestBed/demo/Tumble.cpp) - list(APPEND GAME_SOURCE - ${TESTBED_C_SORUCES} - Source/ChipmunkTestBed/ChipmunkTestBed.cpp - ) -endif() - if (AX_ENABLE_EXT_EFFEKSEER) list(APPEND GAME_HEADER Source/EffekseerTest/EffekseerTest.h) list(APPEND GAME_SOURCE Source/EffekseerTest/EffekseerTest.cpp) @@ -605,7 +502,7 @@ endif() if((NOT IOS) AND (NOT WINRT)) message(STATUS "CMake precompile headers for ${APP_NAME}") target_precompile_headers(${APP_NAME} PRIVATE - "$<$:axmol.h>" + "$<$:axmol/axmol.h>" ) endif() diff --git a/tests/cpp-tests/Source/ActionManagerTest/ActionManagerTest.cpp b/tests/cpp-tests/Source/ActionManagerTest/ActionManagerTest.cpp index b6524c9f3de7..662030b6d9ee 100644 --- a/tests/cpp-tests/Source/ActionManagerTest/ActionManagerTest.cpp +++ b/tests/cpp-tests/Source/ActionManagerTest/ActionManagerTest.cpp @@ -24,7 +24,7 @@ #include "ActionManagerTest.h" #include "../testResource.h" -#include "axmol.h" +#include "axmol/axmol.h" using namespace ax; diff --git a/tests/cpp-tests/Source/ActionsProgressTest/ActionsProgressTest.cpp b/tests/cpp-tests/Source/ActionsProgressTest/ActionsProgressTest.cpp index 81ea34121351..10138fd3a3f1 100644 --- a/tests/cpp-tests/Source/ActionsProgressTest/ActionsProgressTest.cpp +++ b/tests/cpp-tests/Source/ActionsProgressTest/ActionsProgressTest.cpp @@ -58,7 +58,7 @@ void SpriteDemo::onEnter() { TestCase::onEnter(); - auto background = LayerColor::create(Color4B(255, 0, 0, 255)); + auto background = LayerColor::create(Color32(255, 0, 0, 255)); addChild(background, -10); } diff --git a/tests/cpp-tests/Source/ActionsTest/ActionsTest.cpp b/tests/cpp-tests/Source/ActionsTest/ActionsTest.cpp index 903bd2ee357f..3646d296ab5a 100644 --- a/tests/cpp-tests/Source/ActionsTest/ActionsTest.cpp +++ b/tests/cpp-tests/Source/ActionsTest/ActionsTest.cpp @@ -26,13 +26,13 @@ THE SOFTWARE. #include "ActionsTest.h" #include "../testResource.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" -#include "renderer/Renderer.h" -#include "renderer/CustomCommand.h" -#include "renderer/GroupCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/renderer/GroupCommand.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; using namespace ax::ui; @@ -341,7 +341,7 @@ void ActionRotationalSkewVSStandardSkew::onEnter() Size boxSize(100.0f, 100.0f); - auto box = LayerColor::create(Color4B(255, 255, 0, 255)); + auto box = LayerColor::create(Color32(255, 255, 0, 255)); box->setAnchorPoint(Vec2(0.5f, 0.5f)); box->setContentSize(boxSize); box->setIgnoreAnchorPointForPosition(false); @@ -357,7 +357,7 @@ void ActionRotationalSkewVSStandardSkew::onEnter() box->runAction(Sequence::create(actionTo, actionToBack, nullptr)); - box = LayerColor::create(Color4B(255, 255, 0, 255)); + box = LayerColor::create(Color32(255, 255, 0, 255)); box->setAnchorPoint(Vec2(0.5f, 0.5f)); box->setContentSize(boxSize); box->setIgnoreAnchorPointForPosition(false); @@ -387,19 +387,19 @@ void ActionSkewRotateScale::onEnter() Size boxSize(100.0f, 100.0f); - auto box = LayerColor::create(Color4B(255, 255, 0, 255)); + auto box = LayerColor::create(Color32(255, 255, 0, 255)); box->setAnchorPoint(Vec2(0.0f, 0.0f)); box->setPosition(190, 110); box->setContentSize(boxSize); static float markrside = 10.0f; - auto uL = LayerColor::create(Color4B(255, 0, 0, 255)); + auto uL = LayerColor::create(Color32(255, 0, 0, 255)); box->addChild(uL); uL->setContentSize(Size(markrside, markrside)); uL->setPosition(0.f, boxSize.height - markrside); uL->setAnchorPoint(Vec2(0.0f, 0.0f)); - auto uR = LayerColor::create(Color4B(0, 0, 255, 255)); + auto uR = LayerColor::create(Color32(0, 0, 255, 255)); box->addChild(uR); uR->setContentSize(Size(markrside, markrside)); uR->setPosition(boxSize.width - markrside, boxSize.height - markrside); @@ -1245,7 +1245,7 @@ void ActionFollow::onEnter() float y = s.height; Vec2 vertices[] = {Vec2(5.0f, 5.0f), Vec2(x - 5, 5.0f), Vec2(x - 5, y - 5), Vec2(5.0f, y - 5)}; - drawNode->drawPoly(vertices, 4, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(vertices, 4, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); this->addChild(drawNode); @@ -1282,7 +1282,7 @@ void ActionFollowWithOffset::onEnter() float y = s.height; Vec2 vertices[] = {Vec2(5.0f, 5.0f), Vec2(x - 5, 5.0f), Vec2(x - 5, y - 5), Vec2(5.0f, y - 5)}; - drawNode->drawPoly(vertices, 4, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(vertices, 4, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); this->addChild(drawNode); @@ -1524,7 +1524,7 @@ void ActionCatmullRomStacked::onEnter() auto drawNode1 = DrawNode::create(); drawNode1->setPosition(Vec2(50.0f, 50.0f)); - drawNode1->drawCatmullRom(array, 50, Color4F(1.0f, 1.0f, 0.0f, 0.5f)); + drawNode1->drawCatmullRom(array, 50, Color(1.0f, 1.0f, 0.0f, 0.5f)); this->addChild(drawNode1); // @@ -1553,7 +1553,7 @@ void ActionCatmullRomStacked::onEnter() MoveBy::create(0.05f, Vec2(-10.0f, 0.0f)), nullptr))); auto drawNode2 = DrawNode::create(); - drawNode2->drawCatmullRom(array2, 50, Color4F(1.0, 0.0, 0.0, 0.5)); + drawNode2->drawCatmullRom(array2, 50, Color(1.0, 0.0, 0.0, 0.5)); this->addChild(drawNode2); } @@ -1606,7 +1606,7 @@ void ActionCardinalSplineStacked::onEnter() auto drawNode1 = DrawNode::create(); drawNode1->setPosition(Vec2(50.0f, 50.0f)); - drawNode1->drawCardinalSpline(array, 0, 100, Color4F(1.0f, 0.0f, 1.0f, 1.0f)); + drawNode1->drawCardinalSpline(array, 0, 100, Color(1.0f, 0.0f, 1.0f, 1.0f)); this->addChild(drawNode1); // @@ -1629,7 +1629,7 @@ void ActionCardinalSplineStacked::onEnter() auto drawNode2 = DrawNode::create(); drawNode2->setPosition(Vec2(s.width / 2, 50.0f)); - drawNode2->drawCardinalSpline(array, 1, 100, Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode2->drawCardinalSpline(array, 1, 100, Color(0.0f, 0.0f, 1.0f, 1.0f)); this->addChild(drawNode2); } @@ -1951,7 +1951,7 @@ void ActionCatmullRom::onEnter() auto drawNode1 = DrawNode::create(); drawNode1->setPosition(Vec2(50.0f, 50.0f)); - drawNode1->drawCatmullRom(array, 50, Color4F(1.0f, 0.0f, 1.0f, 1.0f)); + drawNode1->drawCatmullRom(array, 50, Color(1.0f, 0.0f, 1.0f, 1.0f)); this->addChild(drawNode1); // @@ -1977,7 +1977,7 @@ void ActionCatmullRom::onEnter() _kathia->runAction(seq2); auto drawNode2 = DrawNode::create(); - drawNode2->drawCatmullRom(array2, 50, Color4F(0.0f, 1.0f, 1.0f, 1.0f)); + drawNode2->drawCatmullRom(array2, 50, Color(0.0f, 1.0f, 1.0f, 1.0f)); this->addChild(drawNode2); } @@ -2027,7 +2027,7 @@ void ActionCardinalSpline::onEnter() auto drawNode1 = DrawNode::create(); drawNode1->setPosition(Vec2(50.0f, 50.0f)); - drawNode1->drawCardinalSpline(array, 0, 100, Color4F(1.0f, 0.0f, 1.0f, 1.0f)); + drawNode1->drawCardinalSpline(array, 0, 100, Color(1.0f, 0.0f, 1.0f, 1.0f)); this->addChild(drawNode1); // @@ -2046,7 +2046,7 @@ void ActionCardinalSpline::onEnter() auto drawNode2 = DrawNode::create(); drawNode2->setPosition(Vec2(s.width / 2, 50.0f)); - drawNode2->drawCardinalSpline(array, 1, 100, Color4F(1.0f, 0.0f, 1.0f, 1.0f)); + drawNode2->drawCardinalSpline(array, 1, 100, Color(1.0f, 0.0f, 1.0f, 1.0f)); this->addChild(drawNode2); } @@ -2129,7 +2129,7 @@ void ActionResize::onEnter() "ImageView Content ResizeTo ResizeBy action. \nTop: ResizeTo/ResizeBy on a 9-slice ImageView \nBottom: " "ScaleTo/ScaleBy on a 9-slice ImageView (for comparison)", "fonts/Marker Felt.ttf", 14); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.125f)); diff --git a/tests/cpp-tests/Source/AppDelegate.cpp b/tests/cpp-tests/Source/AppDelegate.cpp index 66e496bf7b29..db1981f93a60 100644 --- a/tests/cpp-tests/Source/AppDelegate.cpp +++ b/tests/cpp-tests/Source/AppDelegate.cpp @@ -27,11 +27,14 @@ #include #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include "controller.h" #include "BaseTest.h" #include "extensions/axmol-ext.h" +#include +#include + using namespace ax; AppDelegate::AppDelegate() : _testController(nullptr) {} @@ -85,7 +88,9 @@ bool AppDelegate::applicationDidFinishLaunching() director->setRenderView(renderView); } - director->setStatsDisplay(true); + const char* const autotest_capture = + std::getenv("AXMOL_AUTOTEST_CAPTURE_DIR"); + director->setStatsDisplay(!autotest_capture || !autotest_capture[0]); #ifdef AX_PLATFORM_PC director->setAnimationInterval(1.0f / glfwGetVideoMode(glfwGetPrimaryMonitor())->refreshRate); @@ -121,13 +126,28 @@ bool AppDelegate::applicationDidFinishLaunching() renderView->setDesignResolutionSize(g_designSize.width, g_designSize.height, ResolutionPolicy::SHOW_ALL); + director->setClearColor(Color32{0x36, 0x3B, 0x44, 0xFF}); + // Enable Remote Console auto console = director->getConsole(); console->listenOnTCP(5678); _testController = TestController::getInstance(); - if (std::getenv("AXMOL_START_AUTOTEST")) + const char* const autotest_env = std::getenv("AXMOL_START_AUTOTEST"); + int autotest = 0; + if (autotest_env) + { + const std::from_chars_result r = + std::from_chars + (autotest_env, autotest_env + std::strlen(autotest_env), autotest); + if (r.ec != std::errc{}) + AXLOGW("Could not parse AXMOL_START_AUTOTEST: {}.", + std::make_error_code(r.ec).message()); + + } + + if (autotest != 0) { _testController->startAutoTest(); } diff --git a/tests/cpp-tests/Source/AppDelegate.h b/tests/cpp-tests/Source/AppDelegate.h index 714b1a50b6ca..61ea9006b54f 100644 --- a/tests/cpp-tests/Source/AppDelegate.h +++ b/tests/cpp-tests/Source/AppDelegate.h @@ -27,7 +27,7 @@ #ifndef _APP_DELEGATE_H_ #define _APP_DELEGATE_H_ -#include "axmol.h" +#include "axmol/axmol.h" class TestController; /** diff --git a/tests/cpp-tests/Source/BaseTest.cpp b/tests/cpp-tests/Source/BaseTest.cpp index e7d0a521cfaa..2f70aeae2614 100644 --- a/tests/cpp-tests/Source/BaseTest.cpp +++ b/tests/cpp-tests/Source/BaseTest.cpp @@ -26,9 +26,10 @@ #include "BaseTest.h" #include "testResource.h" #include "controller.h" +#include "feature-detect.h" -#if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) -#include "Inspector/Inspector.h" +#if AX_ENABLE_EXT_IMGUI +# include "Inspector/Inspector.h" #endif using namespace ax; @@ -345,6 +346,17 @@ void TestSuite::enterNextTest() Director::getInstance()->replaceScene(scene); } +void TestSuite::enterTest(int index) { + _currTestIndex = index % _childTestNames.size(); + + auto scene = _testCallbacks[_currTestIndex](); + auto testCase = getTestCase(scene); + testCase->setTestSuite(this); + testCase->setTestCaseName(_childTestNames[_currTestIndex]); + + Director::getInstance()->replaceScene(scene); +} + void TestSuite::enterPreviousTest() { if (_currTestIndex > 0) @@ -416,6 +428,12 @@ bool TestCase::init() { if (Scene::init()) { + const char* const autotest_capture = + std::getenv("AXMOL_AUTOTEST_CAPTURE_DIR"); + // Disable the inspector if we are capturing the scene because its + // rendering changes from one run to the next. + _enableInspector = !autotest_capture || !autotest_capture[0]; + // add title and subtitle TTFConfig ttfConfig("fonts/arial.ttf", 26); _titleLabel = Label::createWithTTF(ttfConfig, title()); @@ -467,7 +485,7 @@ void TestCase::onEnter() if (_testSuite) { - _titleLabel->setString(fmt::format("{}:{}", static_cast(_testSuite->getCurrTestIndex() + 1), + _titleLabel->setString(fmt::format("{}:{}", static_cast(_testSuite->getCurrTestIndex() + 1), title())); } else @@ -482,16 +500,21 @@ void TestCase::onEnter() _nextTestItem->setVisible(false); _restartTestItem->setVisible(false); } - +#if AX_ENABLE_EXT_IMGUI #if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) - extension::Inspector::getInstance()->openForScene(this); + if (_enableInspector) + extension::Inspector::getInstance()->openForScene(this); +#endif #endif } void TestCase::onExit() { +#if AX_ENABLE_EXT_IMGUI #if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) - extension::Inspector::getInstance()->close(); + if (_enableInspector) + extension::Inspector::getInstance()->close(); +#endif #endif Scene::onExit(); } diff --git a/tests/cpp-tests/Source/BaseTest.h b/tests/cpp-tests/Source/BaseTest.h index 8951d1123f6c..8e885cb80881 100644 --- a/tests/cpp-tests/Source/BaseTest.h +++ b/tests/cpp-tests/Source/BaseTest.h @@ -26,7 +26,7 @@ #ifndef _CPPTESTS_BASETEST_H__ #define _CPPTESTS_BASETEST_H__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" #include "GUI/ControlExtension/ControlExtensions.h" #include "GUI/ScrollView/ScrollView.h" @@ -115,6 +115,8 @@ class TestCase : public ax::Scene TestSuite* _testSuite; float _runTime; std::string _testCaseName; + + bool _enableInspector = false; }; /** @@ -172,6 +174,8 @@ class TestSuite : public TestBase virtual void enterNextTest(); virtual void enterPreviousTest(); + void enterTest(int index); + int getCurrTestIndex() { return _currTestIndex; } virtual void runThisTest() override; diff --git a/tests/cpp-tests/Source/BillBoardTest/BillBoardTest.cpp b/tests/cpp-tests/Source/BillBoardTest/BillBoardTest.cpp index 4625f0b811a8..36e986c7dff0 100644 --- a/tests/cpp-tests/Source/BillBoardTest/BillBoardTest.cpp +++ b/tests/cpp-tests/Source/BillBoardTest/BillBoardTest.cpp @@ -25,12 +25,12 @@ ****************************************************************************/ #include "BillBoardTest.h" -#include "3d/BillBoard.h" +#include "axmol/3d/BillBoard.h" #include #include "../testResource.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; USING_NS_AX_EXT; diff --git a/tests/cpp-tests/Source/Box2DTest/Box2dTest.cpp b/tests/cpp-tests/Source/Box2DTest/Box2dTest.cpp index 4e07c56d12cb..9496b7b74a17 100644 --- a/tests/cpp-tests/Source/Box2DTest/Box2dTest.cpp +++ b/tests/cpp-tests/Source/Box2DTest/Box2dTest.cpp @@ -26,8 +26,8 @@ #include "Box2dTest.h" #include "../testResource.h" #include "extensions/axmol-ext.h" -#include "renderer/Renderer.h" -#include "renderer/CustomCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/CustomCommand.h" using namespace ax; USING_NS_AX_EXT; @@ -83,7 +83,7 @@ bool Box2DTest::init() auto label = Label::createWithTTF("Tap screen add boxes.\nSome objects be only visible with debug on.", "fonts/Marker Felt.ttf", 12.0f); addChild(label, 0); - label->setColor(Color3B(0, 0, 255)); + label->setColor(Color32(0, 0, 255)); label->setPosition(VisibleRect::center().x - 50, VisibleRect::top().y - 60); // menu for debug layer @@ -94,154 +94,139 @@ bool Box2DTest::init() this->addChild(menu); menu->setPosition(VisibleRect::right().x - 100, VisibleRect::top().y - 60); - drawBox2D = g_debugDraw.GetDrawNode(); - addChild(drawBox2D, 100); - drawBox2D->setOpacity(150); - scheduleUpdate(); return true; } -Box2DTest::Box2DTest() : _spriteTexture(nullptr), world(nullptr) {} +Box2DTest::Box2DTest() : _spriteTexture(nullptr) {} Box2DTest::~Box2DTest() { - AX_SAFE_DELETE(world); + b2DestroyWorld(world); } void Box2DTest::toggleDebugCallback(Object* sender) { showDebugDraw = !showDebugDraw; - drawBox2D->clear(); + _debugDrawNode->setVisible(showDebugDraw); } -void Box2DTest::initPhysics() +b2BodyId Box2DTest::createRigibody(b2BodyDef* def) { - b2Vec2 gravity; - gravity.Set(0.0f, -10.0f); - world = new b2World(gravity); + auto bodyId = b2CreateBody(world, def); + return bodyId; +} - // Do we want to let bodies sleep? - world->SetAllowSleeping(true); +void Box2DTest::initPhysics() +{ + b2Vec2 gravity = {0.0f, -10.0f}; + b2WorldDef worldDef = b2DefaultWorldDef(); + worldDef.gravity = gravity; + world = b2CreateWorld(&worldDef); - world->SetContinuousPhysics(true); + // debug draw node for world + _debugDrawNode = utils::createInstance(&PhysicsDebugNode::initWithWorld, world); + addChild(_debugDrawNode, 100); + _debugDrawNode->setOpacity(150); - // Define the ground body. - b2BodyDef groundBodyDef; - groundBodyDef.position.Set(0, 0); // bottom-left corner + // Do we want to let bodies sleep? + b2World_EnableSleeping(world, true); + b2World_EnableContinuous(world, true); - // Call the body factory which allocates memory for the ground body - // from a pool and creates the ground box shape (also from a pool). - // The body is also added to the world. - b2Body* groundBody = world->CreateBody(&groundBodyDef); + // The segment ground + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = createRigibody(&bodyDef); - // Define the ground box shape. - b2EdgeShape groundBox; + b2ShapeDef shapeDef = b2DefaultShapeDef(); - // bottom - groundBox.SetTwoSided(b2Vec2(VisibleRect::leftBottom().x / PTM_RATIO, VisibleRect::leftBottom().y / PTM_RATIO), - b2Vec2(VisibleRect::rightBottom().x / PTM_RATIO, VisibleRect::rightBottom().y / PTM_RATIO)); - groundBody->CreateFixture(&groundBox, 0); + auto conerOffset = 1.0f / PTM_RATIO; + auto viewRect = VisibleRect::getVisibleRect(); + b2Segment segment = {{conerOffset, conerOffset}, {viewRect.size.width / PTM_RATIO - conerOffset, conerOffset}}; + b2CreateSegmentShape(groundId, &shapeDef, &segment); // bottom - // top - groundBox.SetTwoSided(b2Vec2(VisibleRect::leftTop().x / PTM_RATIO, VisibleRect::leftTop().y / PTM_RATIO), - b2Vec2(VisibleRect::rightTop().x / PTM_RATIO, VisibleRect::rightTop().y / PTM_RATIO)); - groundBody->CreateFixture(&groundBox, 0); + segment = {{conerOffset, viewRect.size.height / PTM_RATIO - conerOffset}, + {viewRect.size.width / PTM_RATIO - conerOffset, viewRect.size.height / PTM_RATIO - conerOffset}}; + b2CreateSegmentShape(groundId, &shapeDef, &segment); // top - // left - groundBox.SetTwoSided(b2Vec2(VisibleRect::leftTop().x / PTM_RATIO, VisibleRect::leftTop().y / PTM_RATIO), - b2Vec2(VisibleRect::leftBottom().x / PTM_RATIO, VisibleRect::leftBottom().y / PTM_RATIO)); - groundBody->CreateFixture(&groundBox, 0); + segment = {{conerOffset, conerOffset}, {conerOffset, viewRect.size.height / PTM_RATIO - conerOffset}}; + b2CreateSegmentShape(groundId, &shapeDef, &segment); // left - // right - groundBox.SetTwoSided(b2Vec2(VisibleRect::rightBottom().x / PTM_RATIO, VisibleRect::rightBottom().y / PTM_RATIO), - b2Vec2(VisibleRect::rightTop().x / PTM_RATIO, VisibleRect::rightTop().y / PTM_RATIO)); - groundBody->CreateFixture(&groundBox, 0); + segment = {{viewRect.size.width / PTM_RATIO - conerOffset, conerOffset}, + {viewRect.size.width / PTM_RATIO - conerOffset, viewRect.size.height / PTM_RATIO - conerOffset}}; + b2CreateSegmentShape(groundId, &shapeDef, &segment); // right // Small triangle b2Vec2 vertices[3]; - vertices[0].Set(-1.0f, 0.0f); - vertices[1].Set(1.0f, 0.0f); - vertices[2].Set(0.0f, 2.0f); - - b2PolygonShape polygon; - polygon.Set(vertices, 3); - - b2FixtureDef triangleShapeDef; - triangleShapeDef.shape = &polygon; - triangleShapeDef.density = 1.0f; - - b2BodyDef triangleBodyDef; - triangleBodyDef.type = b2_dynamicBody; - triangleBodyDef.position.Set(rand() % 13 + 3, 4); - - b2Body* body1 = world->CreateBody(&triangleBodyDef); - body1->CreateFixture(&triangleShapeDef); + vertices[0] = b2Vec2{-1.0f, 0.0f}; + vertices[1] = b2Vec2{1.0f, 0.0f}; + vertices[2] = b2Vec2{0.0f, 2.0f}; + b2Hull hull = b2ComputeHull(vertices, 3); + b2Polygon polygon = b2MakePolygon(&hull, 0.0f); + + b2BodyDef triangleBodyDef = b2DefaultBodyDef(); + triangleBodyDef.type = b2_dynamicBody; + triangleBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; // bottom-left corner + auto body1 = createRigibody(&triangleBodyDef); + b2ShapeDef triangleShapeDef = b2DefaultShapeDef(); + triangleShapeDef.density = 1.0f; + b2CreatePolygonShape(body1, &triangleShapeDef, &polygon); // Large triangle (recycle definitions) vertices[0] *= 2.0f; vertices[1] *= 2.0f; vertices[2] *= 2.0f; - polygon.Set(vertices, 3); - - triangleBodyDef.position.Set(rand() % 13 + 3, 4); - b2Body* body2 = world->CreateBody(&triangleBodyDef); - body2->CreateFixture(&triangleShapeDef); + triangleBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; + auto body2 = createRigibody(&triangleBodyDef); + hull = b2ComputeHull(vertices, 3); + polygon = b2MakePolygon(&hull, 0.0f); + b2CreatePolygonShape(body2, &triangleShapeDef, &polygon); // Small box - polygon.SetAsBox(1.0f, 0.5f); + polygon = b2MakeBox(1.0f, 0.5f); // .SetAsBox(1.0f, 0.5f); - b2FixtureDef boxShapeDef; - boxShapeDef.shape = &polygon; + auto boxShapeDef = b2DefaultShapeDef(); boxShapeDef.density = 1.0f; - b2BodyDef boxBodyDef; - boxBodyDef.type = b2_dynamicBody; - boxBodyDef.position.Set(rand() % 13 + 3, 4); + b2BodyDef boxBodyDef = b2DefaultBodyDef(); + boxBodyDef.type = b2_dynamicBody; + boxBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; - b2Body* body3 = world->CreateBody(&boxBodyDef); - body3->CreateFixture(&boxShapeDef); + auto body3 = createRigibody(&boxBodyDef); + b2CreatePolygonShape(body3, &boxShapeDef, &polygon); // Large box (recycle definitions) - polygon.SetAsBox(2.0f, 1.0f); - boxBodyDef.position.Set(rand() % 13 + 3, 4); + polygon = b2MakeBox(2.0f, 1.0f); // .SetAsBox(2.0f, 1.0f); + boxBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; - b2Body* body4 = world->CreateBody(&boxBodyDef); - body4->CreateFixture(&boxShapeDef); + auto body4 = createRigibody(&boxBodyDef); + b2CreatePolygonShape(body4, &boxShapeDef, &polygon); // Small circle - b2CircleShape circle; - circle.m_radius = 1.0f; - - b2FixtureDef circleShapeDef; - circleShapeDef.shape = &circle; + auto circleShapeDef = b2DefaultShapeDef(); circleShapeDef.density = 1.0f; - b2BodyDef circleBodyDef; - circleBodyDef.type = b2_dynamicBody; - circleBodyDef.position.Set(rand() % 13 + 3, 4); + b2Circle circle{{0.0f, 0.0f}, 1.0f}; - b2Body* body5 = world->CreateBody(&circleBodyDef); - body5->CreateFixture(&circleShapeDef); + b2BodyDef circleBodyDef = b2DefaultBodyDef(); + circleBodyDef.type = b2_dynamicBody; + circleBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; + + auto body5 = createRigibody(&circleBodyDef); + b2CreateCircleShape(body5, &circleShapeDef, &circle); // Large circle - circle.m_radius *= 2.0f; - circleBodyDef.position.Set(rand() % 13 + 3, 4); - - b2Body* body6 = world->CreateBody(&circleBodyDef); - body6->CreateFixture(&circleShapeDef); - - uint32 flags = 0; - flags += 1 * b2Draw::e_shapeBit; - flags += 1 * b2Draw::e_jointBit; - flags += 0 * b2Draw::e_aabbBit; - flags += 0 * b2Draw::e_centerOfMassBit; - g_debugDraw.SetFlags(flags); - g_debugDraw.mRatio = PTM_RATIO; - g_debugDraw.debugNodeOffset = {0, 0}; - world->SetDebugDraw(&g_debugDraw); + circle.radius *= 2.0f; + circleBodyDef.position = b2Vec2{static_cast(rand() % 13 + 3), 4.0f}; + + auto body6 = createRigibody(&circleBodyDef); + b2CreateCircleShape(body6, &circleShapeDef, &circle); + + _debugDrawNode->setPTMRatio(PTM_RATIO); + auto& settings = _debugDrawNode->getB2DebugDraw(); + settings.drawShapes = true; + settings.drawJoints = true; } void Box2DTest::createResetButton() @@ -261,24 +246,22 @@ void Box2DTest::addNewSpriteAtPosition(Vec2 p) // Define the dynamic body. // Set up a 1m squared box in the physics world - b2BodyDef bodyDef; - bodyDef.type = b2_dynamicBody; - bodyDef.position.Set(p.x / PTM_RATIO, p.y / PTM_RATIO); + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Vec2{p.x / PTM_RATIO, p.y / PTM_RATIO}; AXLOGD("Add PTM_RATIO sprite x: {:.2} y: {:.2}", p.x / PTM_RATIO, p.y / PTM_RATIO); - b2Body* body = world->CreateBody(&bodyDef); + auto body = createRigibody(&bodyDef); // Define another box shape for our dynamic body. - b2PolygonShape dynamicBox; - dynamicBox.SetAsBox(.5f, .5f); // These are mid points for our 1m box + auto dynamicBox = b2MakeBox(.5f, .5f); // These are mid points for our 1m box // Define the dynamic body fixture. - b2FixtureDef fixtureDef; - fixtureDef.shape = &dynamicBox; - fixtureDef.density = 1.0f; - fixtureDef.friction = 0.3f; - body->CreateFixture(&fixtureDef); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.3f; + b2CreatePolygonShape(body, &shapeDef, &dynamicBox); auto parent = this->getChildByTag(kTagParentNode); @@ -286,7 +269,7 @@ void Box2DTest::addNewSpriteAtPosition(Vec2 p) // just randomly picking one of the images int idx = (AXRANDOM_0_1() > .5 ? 0 : 1); int idy = (AXRANDOM_0_1() > .5 ? 0 : 1); - auto sprite = PhysicsSpriteBox2D::createWithTexture(_spriteTexture, Rect(32 * idx, 32 * idy, 32, 32)); + auto sprite = PhysicsSprite::createWithTexture(_spriteTexture, Rect(32 * idx, 32 * idy, 32, 32)); parent->addChild(sprite); sprite->setB2Body(body); sprite->setPTMRatio(PTM_RATIO); @@ -300,19 +283,9 @@ void Box2DTest::update(float dt) // You need to make an informed choice, the following URL is useful // http://gafferongames.com/game-physics/fix-your-timestep/ - int velocityIterations = 8; - int positionIterations = 1; - - // Instruct the world to perform a single step of simulation. It is - // generally best to keep the time step and iterations fixed. - world->Step(dt, velocityIterations, positionIterations); - - // Debug draw - if (showDebugDraw) - { - drawBox2D->clear(); - world->DebugDraw(); - } + // The number of sub-steps, increasing the sub-step count can increase accuracy. Typically 4. + constexpr int subStepCount = 4; + b2World_Step(world, dt, subStepCount); } void Box2DTest::onTouchesEnded(const std::vector& touches, Event* event) diff --git a/tests/cpp-tests/Source/Box2DTest/Box2dTest.h b/tests/cpp-tests/Source/Box2DTest/Box2dTest.h index 3defee8d622d..c0fde351ca48 100644 --- a/tests/cpp-tests/Source/Box2DTest/Box2dTest.h +++ b/tests/cpp-tests/Source/Box2DTest/Box2dTest.h @@ -26,7 +26,7 @@ #ifndef _BOX2D_TEST_H_ #define _BOX2D_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "box2d/box2d.h" #include "../BaseTest.h" #include "extensions/axmol-ext.h" @@ -53,13 +53,14 @@ class Box2DTest : public TestCase void toggleDebugCallback(ax::Object* sender); + b2BodyId createRigibody(b2BodyDef*); + private: - b2World* world; + b2WorldId world{}; - ax::Texture2D* _spriteTexture; - ax::DrawNode* drawBox2D; - ax::extension::PhysicsDebugNodeBox2D g_debugDraw; - bool showDebugDraw = true; + ax::Texture2D* _spriteTexture{nullptr}; + ax::extension::PhysicsDebugNode* _debugDrawNode{nullptr}; + bool showDebugDraw{true}; }; #endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.cpp b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.cpp index d91c130470a2..9179efaff557 100644 --- a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.cpp +++ b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.cpp @@ -22,14 +22,16 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "extensions/axmol-ext.h" #include "ImGui/ImGuiPresenter.h" -#include "axmol.h" +#include "axmol/axmol.h" #include "Box2DTestBed.h" -#include "tests/test.h" -#include "tests/settings.h" +#include "samples/sample.h" +#include "samples/settings.h" +#include "samples/TaskScheduler.h" +#include "axmol/platform/RenderView.h" using namespace ax; USING_NS_AX_EXT; @@ -39,35 +41,52 @@ enum kTagParentNode = 1, }; -Settings settings; -ax::Label* labelDebugDraw; +static Settings s_settings; enum { kTagBox2DNode, }; -TestEntry g_testEntries[MAX_TESTS] = {{nullptr}}; -int g_testCount = 0; +static b2Vec2 tob2Vec2(const Vec2& val) +{ + return b2Vec2{val.x, val.y}; +} -int RegisterTest(const char* category, const char* name, TestCreateFcn* fcn) +static inline int CompareSamples(const void* a, const void* b) { - int index = g_testCount; - if (index < MAX_TESTS) + SampleEntry* sa = (SampleEntry*)a; + SampleEntry* sb = (SampleEntry*)b; + + int result = strcmp(sa->category, sb->category); + if (result == 0) { - g_testEntries[index] = {category, name, fcn}; - ++g_testCount; - return index; + result = strcmp(sa->name, sb->name); } - return -1; + return result; +} + +static void SortTests() +{ + qsort(g_sampleEntries, g_sampleCount, sizeof(SampleEntry), CompareSamples); } Box2DTestBedTests::Box2DTestBedTests() { - for (int entryId = 0; entryId < g_testCount; ++entryId) + // TODO: determine properly view size + g_camera.m_width = 1920; + g_camera.m_height = 1080; + g_camera.m_zoom = 150; + g_camera.m_center = b2Vec2_zero; + + ImGuiPresenter::getInstance()->setViewResolution(g_camera.m_width, g_camera.m_height); + + SortTests(); + + for (int idx = 0; idx < g_sampleCount; ++idx) { - addTestCase(g_testEntries[entryId].name, [entryId]() { return Box2DTestBed::createWithEntryID(entryId); }); + addTestCase(g_sampleEntries[idx].name, [idx]() { return Box2DTestBed::create(idx); }); } } @@ -77,23 +96,27 @@ Box2DTestBedTests::Box2DTestBedTests() // //------------------------------------------------------------------ -Box2DTestBed::Box2DTestBed() {} +Box2DTestBed::Box2DTestBed() +{ + m_statsWindowOffset = Vec2(-60, -80); +} Box2DTestBed::~Box2DTestBed() { - Layer::_eventDispatcher->removeEventListener(_touchListener); + //_eventDispatcher->removeEventListener(_touchListener); + _eventDispatcher->removeEventListener(_keyboardListener); + _eventDispatcher->removeEventListener(_mouseListener); } -Box2DTestBed* Box2DTestBed::createWithEntryID(int entryId) +Box2DTestBed* Box2DTestBed::create(int index) { auto layer = new Box2DTestBed(); - layer->initWithEntryID(entryId); - // layer->autorelease(); - + layer->initWithEntryIndex(index); + layer->autorelease(); return layer; } -bool Box2DTestBed::initWithEntryID(int entryId) +bool Box2DTestBed::initWithEntryIndex(int index) { if (!TestCase::init()) { @@ -103,142 +126,112 @@ bool Box2DTestBed::initWithEntryID(int entryId) Vec2 visibleOrigin = director->getVisibleOrigin(); Size visibleSize = director->getVisibleSize(); - m_entryID = entryId; - - m_entry = g_testEntries + entryId; - m_test = m_entry->createFcn(); + m_entryIndex = s_settings.sampleIndex = index; - debugDrawNode = g_debugDraw.GetDrawNode(); - m_test->debugDrawNode = debugDrawNode; - m_test->g_debugDraw = g_debugDraw; - - TestCase::addChild(debugDrawNode, 100); + m_entry = g_sampleEntries + index; + m_sample = m_entry->createFcn(s_settings); // init physics this->initPhysics(); auto label = Label::createWithTTF(m_entry->name, "fonts/arial.ttf", 28); - TestCase::addChild(label, 1); + addChild(label, 1); label->setPosition(visibleOrigin.x + visibleSize.width / 2, visibleOrigin.y + visibleSize.height - 50); // Adds touch event listener - _touchListener = EventListenerTouchOneByOne::create(); - _touchListener->setSwallowTouches(true); - _touchListener->onTouchBegan = AX_CALLBACK_2(Box2DTestBed::onTouchBegan, this); - _touchListener->onTouchMoved = AX_CALLBACK_2(Box2DTestBed::onTouchMoved, this); - _touchListener->onTouchEnded = AX_CALLBACK_2(Box2DTestBed::onTouchEnded, this); - TestCase::_eventDispatcher->addEventListenerWithFixedPriority(_touchListener, 10); + // _touchListener = EventListenerTouchOneByOne::create(); + // _touchListener->setSwallowTouches(true); + // _touchListener->onTouchBegan = AX_CALLBACK_2(Box2DTestBed::onTouchBegan, this); + // _touchListener->onTouchMoved = AX_CALLBACK_2(Box2DTestBed::onTouchMoved, this); + // _touchListener->onTouchEnded = AX_CALLBACK_2(Box2DTestBed::onTouchEnded, this); + // _eventDispatcher->addEventListenerWithFixedPriority(_touchListener, 10); // Adds Keyboard event listener _keyboardListener = EventListenerKeyboard::create(); _keyboardListener->onKeyPressed = AX_CALLBACK_2(Box2DTestBed::onKeyPressed, this); _keyboardListener->onKeyReleased = AX_CALLBACK_2(Box2DTestBed::onKeyReleased, this); - TestCase::_eventDispatcher->addEventListenerWithFixedPriority(_keyboardListener, 11); + _eventDispatcher->addEventListenerWithFixedPriority(_keyboardListener, 11); - auto _mouseListener = EventListenerMouse::create(); + _mouseListener = EventListenerMouse::create(); _mouseListener->onMouseMove = AX_CALLBACK_1(Box2DTestBed::onMouseMove, this); _mouseListener->onMouseUp = AX_CALLBACK_1(Box2DTestBed::onMouseUp, this); _mouseListener->onMouseDown = AX_CALLBACK_1(Box2DTestBed::onMouseDown, this); _mouseListener->onMouseScroll = AX_CALLBACK_1(Box2DTestBed::onMouseScroll, this); - TestCase::_eventDispatcher->addEventListenerWithFixedPriority(_mouseListener, 12); - - // Demo messageString - labelDebugDraw = Label::createWithTTF("TEST", "fonts/arial.ttf", 8.0f); - labelDebugDraw->setAnchorPoint(Vec2(0, 1)); - labelDebugDraw->setPosition(VisibleRect::left().x, VisibleRect::top().y - 10); - labelDebugDraw->setColor(Color3B::WHITE); - TestCase::addChild(labelDebugDraw, 100); - - TestCase::scheduleUpdate(); + _eventDispatcher->addEventListenerWithFixedPriority(_mouseListener, 12); return true; } -bool Box2DTestBed::onTouchBegan(Touch* touch, Event* event) -{ - auto location = touch->getLocation() - g_debugDraw.debugNodeOffset; - b2Vec2 pos = {location.x / g_debugDraw.mRatio, location.y / g_debugDraw.mRatio}; - return m_test->MouseDown(pos); -} - -void Box2DTestBed::onTouchMoved(Touch* touch, Event* event) -{ - auto location = touch->getLocation() - g_debugDraw.debugNodeOffset; - b2Vec2 pos = {location.x / g_debugDraw.mRatio, location.y / g_debugDraw.mRatio}; - m_test->MouseMove(pos); -} - -void Box2DTestBed::onTouchEnded(Touch* touch, Event* event) -{ - auto location = touch->getLocation() - g_debugDraw.debugNodeOffset; - b2Vec2 pos = {location.x / g_debugDraw.mRatio, location.y / g_debugDraw.mRatio}; - m_test->MouseUp(pos); -} - void Box2DTestBed::onKeyPressed(EventKeyboard::KeyCode code, Event* event) { - AXLOGD("onKeyPressed, keycode: {}", static_cast(code)); - m_test->Keyboard((static_cast(code) - 59)); // its a bad hack! + // AXLOGD("onKeyPressed, keycode: {}", static_cast(code)); + // m_sample->Keyboard((static_cast(code) - 59)); // its a bad hack! } void Box2DTestBed::onKeyReleased(EventKeyboard::KeyCode code, Event* event) { AXLOGD("onKeyPressed, keycode: {}", static_cast(code)); - m_test->KeyboardUp((static_cast(code) - 59)); // its a bad hack! + // m_sample->KeyboardUp((static_cast(code) - 59)); // its a bad hack! + m_sample->Keyboard((static_cast(code) - 59)); } bool Box2DTestBed::onMouseDown(Event* event) { - EventMouse* e = (EventMouse*)event; - button[(int)EventMouse::MouseButton::BUTTON_LEFT] = false; - button[(int)EventMouse::MouseButton::BUTTON_RIGHT] = false; - button[(int)EventMouse::MouseButton::BUTTON_MIDDLE] = false; - switch (e->getMouseButton()) - { - case EventMouse::MouseButton::BUTTON_LEFT: - button[(int)EventMouse::MouseButton::BUTTON_LEFT] = true; - break; - case EventMouse::MouseButton::BUTTON_RIGHT: - button[(int)EventMouse::MouseButton::BUTTON_RIGHT] = true; - break; - case EventMouse::MouseButton::BUTTON_MIDDLE: - button[(int)EventMouse::MouseButton::BUTTON_MIDDLE] = true; - break; - } + EventMouse* e = static_cast(event); + + auto location = e->getLocation() - _debugDraw->getWorldOffset(); + b2Vec2 pos = {location.x / _debugDraw->getPTMRatio(), location.y / _debugDraw->getPTMRatio()}; + + int mods = 0; +#if defined(_WIN32) + if (GetAsyncKeyState(VK_SHIFT) & 0x80) + mods |= GLFW_MOD_SHIFT; + if (GetAsyncKeyState(VK_CONTROL) & 0x80) + mods |= GLFW_MOD_CONTROL; + if (GetAsyncKeyState(VK_MENU) & 0x80) + mods |= GLFW_MOD_ALT; +#endif + _draging = true; + _mouseDownPos = pos; + _dragingStartPos = _debugDraw->getPosition(); + + m_sample->MouseDown(pos, static_cast(e->getMouseButton()), mods); return true; } bool Box2DTestBed::onMouseUp(Event* event) { - button[(int)EventMouse::MouseButton::BUTTON_LEFT] = false; - button[(int)EventMouse::MouseButton::BUTTON_RIGHT] = false; - button[(int)EventMouse::MouseButton::BUTTON_MIDDLE] = false; - + const auto ratio = _debugDraw->getPTMRatio(); + _draging = false; + EventMouse* e = static_cast(event); + auto location = e->getLocation() - _debugDraw->getWorldOffset(); + b2Vec2 pos = {location.x / ratio, location.y / ratio}; + m_sample->MouseUp(pos, static_cast(e->getMouseButton())); return true; } bool Box2DTestBed::onMouseMove(Event* event) { - EventMouse* e = (EventMouse*)event; - auto pt = e->getLocation(); - pos = {pt.x / g_debugDraw.mRatio, pt.y / g_debugDraw.mRatio}; + const auto ratio = _debugDraw->getPTMRatio(); + EventMouse* e = static_cast(event); + + auto location = e->getLocation() - _debugDraw->getWorldOffset(); + b2Vec2 pos{location.x / ratio, location.y / ratio}; + m_sample->MouseMove(pos); - if (button[(int)EventMouse::MouseButton::BUTTON_RIGHT]) + if (e->getMouseButton() == EventMouse::MouseButton::BUTTON_RIGHT) { - (pos.x > oldPos.x) ? g_debugDraw.debugNodeOffset.x += 4 : g_debugDraw.debugNodeOffset.x -= 4; - (pos.y < oldPos.y) ? g_debugDraw.debugNodeOffset.y -= 2 : g_debugDraw.debugNodeOffset.y += 2; + auto diff = b2Sub(pos, _mouseDownPos); + _debugDraw->setPosition(_dragingStartPos.x + diff.x, _dragingStartPos.y + diff.y); } - oldPos = pos; - return true; } bool Box2DTestBed::onMouseScroll(Event* event) { EventMouse* e = (EventMouse*)event; - g_debugDraw.mRatio += e->getScrollY(); - + _debugDraw->setPTMRatio(_debugDraw->getPTMRatio() - e->getScrollY()); return true; } @@ -246,42 +239,218 @@ void Box2DTestBed::onEnter() { Scene::onEnter(); ImGuiPresenter::getInstance()->addFont(FileUtils::getInstance()->fullPathForFilename("fonts/arial.ttf")); - ImGuiPresenter::getInstance()->addRenderLoop("#im01", AX_CALLBACK_0(Box2DTestBed::onDrawImGui, this), this); + ImGuiPresenter::getInstance()->addRenderLoop("#bv3t", AX_CALLBACK_0(Box2DTestBed::renderSamples, this), this); } void Box2DTestBed::onExit() { + ImGuiPresenter::getInstance()->removeRenderLoop("#bv3t"); Scene::onExit(); - ImGuiPresenter::getInstance()->removeRenderLoop("#im01"); } -void Box2DTestBed::update(float dt) +void Box2DTestBed::initPhysics() { - // Debug draw - m_test->debugString = ""; - labelDebugDraw->setString(""); - debugDrawNode->clear(); - m_test->Step(settings); - m_test->m_world->DebugDraw(); + _debugDraw = + utils::createInstance(&Box2DTestDebugDrawNode::initWithWorld, m_sample->m_worldId); + _debugDraw->setAutoDraw(false); + addChild(_debugDraw); + + auto& b2dw = _debugDraw->getB2DebugDraw(); + b2dw.drawShapes = true; + b2dw.drawJoints = true; + b2dw.drawBounds = false; + + _debugDraw->setWorldOffset({250, 70}); + _debugDraw->setPTMRatio(3.0f); + + s_settings.hertz = 60; } -void Box2DTestBed::initPhysics() +void Box2DTestBed::RestartSample() { - uint32 flags = 0; - flags += 1 * b2Draw::e_shapeBit; - flags += 1 * b2Draw::e_jointBit; - flags += 0 * b2Draw::e_aabbBit; - flags += 0 * b2Draw::e_centerOfMassBit; - g_debugDraw.SetFlags(flags); - g_debugDraw.mRatio = 8; - m_test->m_world->SetDebugDraw(&g_debugDraw); - m_test->g_debugDraw = g_debugDraw; - g_debugDraw.debugNodeOffset = {250, 70}; - m_test->g_debugDraw.debugNodeOffset = g_debugDraw.debugNodeOffset; - - settings.m_hertz = 60; + getTestSuite()->restartCurrTest(); } -void Box2DTestBed::onDrawImGui() +void Box2DTestBed::renderSamples() { - m_test->UpdateUI(); + _debugDraw->clear(); + + float menuWidth = 180.0f; + auto cursorPos = ImGui::GetCursorScreenPos(); + + ImVec2 statsWindowPos = {cursorPos.x + m_statsWindowOffset.x, cursorPos.y + m_statsWindowOffset.y}; + ImVec2 statsWindowSize = {g_camera.m_width - 10, g_camera.m_height - 10}; + ImGui::SetNextWindowPos(statsWindowPos); + ImGui::SetNextWindowSize(statsWindowSize); + ImGui::SetNextWindowBgAlpha(0.0f); + ImGui::Begin("Overlay", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar); + ImGui::End(); + + char buffer[128]; + if (g_draw.m_showUI) + { + const SampleEntry& entry = g_sampleEntries[s_settings.sampleIndex]; + snprintf(buffer, 128, "%s : %s", entry.category, entry.name); + m_sample->DrawTitle(buffer); + } + + m_sample->Step(s_settings); + + /// BEGIN UpdateUI + int maxWorkers = enki::GetNumHardwareThreads(); + + if (g_draw.m_showUI) + { + ImVec2 toolWindowPos = {(cursorPos.x + g_camera.m_width - menuWidth - 80), (cursorPos.y - 80)}; + ImVec2 toolWindowSize = {menuWidth, g_camera.m_height - 200.0f}; + ImGui::SetNextWindowPos(toolWindowPos, ImGuiCond_FirstUseEver); + ImGui::SetNextWindowSize(toolWindowSize, ImGuiCond_FirstUseEver); + ImGui::Begin("Tools", &g_draw.m_showUI, + /*ImGuiWindowFlags_NoMove | */ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse); + + if (ImGui::BeginTabBar("ControlTabs", ImGuiTabBarFlags_None)) + { + if (ImGui::BeginTabItem("Controls")) + { + ImGui::PushItemWidth(100.0f); + ImGui::SliderInt("Sub-steps", &s_settings.subStepCount, 1, 50); + ImGui::SliderFloat("Hertz", &s_settings.hertz, 5.0f, 120.0f, "%.0f hz"); + + if (ImGui::SliderInt("Workers", &s_settings.workerCount, 1, maxWorkers)) + { + s_settings.workerCount = b2ClampInt(s_settings.workerCount, 1, maxWorkers); + RestartSample(); + } + ImGui::PopItemWidth(); + + ImGui::Separator(); + + ImGui::Checkbox("Sleep", &s_settings.enableSleep); + ImGui::Checkbox("Warm Starting", &s_settings.enableWarmStarting); + ImGui::Checkbox("Continuous", &s_settings.enableContinuous); + + ImGui::Separator(); + + ImGui::Checkbox("Shapes", &s_settings.drawShapes); + ImGui::Checkbox("Joints", &s_settings.drawJoints); + ImGui::Checkbox("Joint Extras", &s_settings.drawJointExtras); + ImGui::Checkbox("AABBs", &s_settings.drawBounds); + ImGui::Checkbox("Contact Points", &s_settings.drawContactPoints); + ImGui::Checkbox("Contact Normals", &s_settings.drawContactNormals); + ImGui::Checkbox("Contact Impulses", &s_settings.drawContactImpulses); + ImGui::Checkbox("Friction Impulses", &s_settings.drawFrictionImpulses); + ImGui::Checkbox("Center of Masses", &s_settings.drawMass); + ImGui::Checkbox("Graph Colors", &s_settings.drawGraphColors); + ImGui::Checkbox("Counters", &s_settings.drawCounters); + ImGui::Checkbox("Profile", &s_settings.drawProfile); + + ImVec2 button_sz = ImVec2(-1, 0); + if (ImGui::Button("Pause (P)", button_sz)) + { + s_settings.pause = !s_settings.pause; + } + + if (ImGui::Button("Single Step (O)", button_sz)) + { + s_settings.singleStep = !s_settings.singleStep; + } + + if (ImGui::Button("Dump Mem Stats", button_sz)) + { + b2World_DumpMemoryStats(m_sample->m_worldId); + } + + if (ImGui::Button("Reset Profile", button_sz)) + { + m_sample->ResetProfile(); + } + + if (ImGui::Button("Restart (R)", button_sz)) + { + RestartSample(); + } + + if (ImGui::Button("Quit", button_sz)) + { + glfwSetWindowShouldClose(g_mainWindow, GL_TRUE); + } + + ImGui::EndTabItem(); + } + + ImGuiTreeNodeFlags leafNodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + leafNodeFlags |= ImGuiTreeNodeFlags_Leaf | ImGuiTreeNodeFlags_NoTreePushOnOpen; + + ImGuiTreeNodeFlags nodeFlags = ImGuiTreeNodeFlags_OpenOnArrow | ImGuiTreeNodeFlags_OpenOnDoubleClick; + + if (ImGui::BeginTabItem("Tests")) + { + int categoryIndex = 0; + const char* category = g_sampleEntries[categoryIndex].category; + int i = 0; + while (i < g_sampleCount) + { + bool categorySelected = strcmp(category, g_sampleEntries[s_settings.sampleIndex].category) == 0; + ImGuiTreeNodeFlags nodeSelectionFlags = categorySelected ? ImGuiTreeNodeFlags_Selected : 0; + bool nodeOpen = ImGui::TreeNodeEx(category, nodeFlags | nodeSelectionFlags); + + if (nodeOpen) + { + while (i < g_sampleCount && strcmp(category, g_sampleEntries[i].category) == 0) + { + ImGuiTreeNodeFlags selectionFlags = 0; + if (s_settings.sampleIndex == i) + { + selectionFlags = ImGuiTreeNodeFlags_Selected; + } + ImGui::TreeNodeEx((void*)(intptr_t)i, leafNodeFlags | selectionFlags, "%s", + g_sampleEntries[i].name); + if (ImGui::IsItemClicked()) + { + getTestSuite()->enterTest(i); + } + ++i; + } + ImGui::TreePop(); + } + else + { + while (i < g_sampleCount && strcmp(category, g_sampleEntries[i].category) == 0) + { + ++i; + } + } + + if (i < g_sampleCount) + { + category = g_sampleEntries[i].category; + categoryIndex = i; + } + } + ImGui::EndTabItem(); + } + ImGui::EndTabBar(); + } + + ImGui::End(); + + m_sample->UpdateGui(); + } + /// END UpdateUI + + if (g_draw.m_showUI) + { + snprintf(buffer, 128, "%.1f ms - step %d - camera (%g, %g, %g)", 1000.0f * _director->getDeltaTime(), + m_sample->m_stepCount, g_camera.m_center.x, g_camera.m_center.y, g_camera.m_zoom); + // snprintf( buffer, 128, "%.1f ms", 1000.0f * frameTime ); + + ImGui::Begin("Overlay", nullptr, + + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar); + ImGui::SetCursorPos(ImVec2(5.0f, g_camera.m_height - 50.0f)); + ImGui::TextColored(ImColor(153, 230, 153, 255), "%s", buffer); + ImGui::End(); + } } diff --git a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.h b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.h index 0657e8c93912..08f03ac0090b 100644 --- a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.h +++ b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestBed.h @@ -25,31 +25,20 @@ #ifndef _BOX2D_TESTBED_H_ #define _BOX2D_TESTBED_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "box2d/box2d.h" #include "../BaseTest.h" +#include "Box2DTestDebugDrawNode.h" -DEFINE_TEST_SUITE(Box2DTestBedTests); - -class Test; -typedef Test* TestCreateFcn(); - -struct TestEntry -{ - const char* category; - const char* name; - TestCreateFcn* createFcn; -}; +class SampleEntry; +class Sample; -#define MAX_TESTS 256 -extern TestEntry g_testEntries[MAX_TESTS]; - -int RegisterTest(const char* category, const char* name, TestCreateFcn* fcn); +DEFINE_TEST_SUITE(Box2DTestBedTests); -class Box2DTestBed : public TestCase, ax::Layer +class Box2DTestBed : public TestCase { public: - static Box2DTestBed* createWithEntryID(int entryId); + static Box2DTestBed* create(int entryIndex); Box2DTestBed(); virtual ~Box2DTestBed(); @@ -57,18 +46,11 @@ class Box2DTestBed : public TestCase, ax::Layer void onEnter() override; void onExit() override; - void onDrawImGui(); + void renderSamples(); void initPhysics(); - void update(float dt) override; - - void createResetButton(); - bool initWithEntryID(int entryId); - - bool onTouchBegan(ax::Touch* touch, ax::Event* event); - void onTouchMoved(ax::Touch* touch, ax::Event* event); - void onTouchEnded(ax::Touch* touch, ax::Event* event); + bool initWithEntryIndex(int entryIndex); void onKeyPressed(ax::EventKeyboard::KeyCode code, ax::Event* event); void onKeyReleased(ax::EventKeyboard::KeyCode code, ax::Event* event); @@ -78,24 +60,25 @@ class Box2DTestBed : public TestCase, ax::Layer bool onMouseMove(ax::Event* event); bool onMouseScroll(ax::Event* event); - ax::EventListenerTouchOneByOne* _touchListener; - ax::EventListenerKeyboard* _keyboardListener; + void RestartSample(); + + SampleEntry* m_entry{}; + Sample* m_sample{}; + int m_entryIndex{}; - TestEntry* m_entry; - Test* m_test; - int m_entryID; + Vec2 m_statsWindowOffset{}; private: - b2World* world; - ax::Texture2D* _spriteTexture; + b2Vec2 _mouseDownPos{}; + ax::Vec2 _dragingStartPos; + bool _draging{false}; - b2Vec2 pos; - b2Vec2 oldPos; - bool button[2]; + /*ax::EventListenerTouchOneByOne* _touchListener{};*/ + ax::EventListenerKeyboard* _keyboardListener{}; + ax::EventListenerMouse* _mouseListener{}; // Debug stuff - ax::DrawNode* debugDrawNode; - ax::extension::PhysicsDebugNodeBox2D g_debugDraw; + Box2DTestDebugDrawNode* _debugDraw{}; }; #endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.cpp b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.cpp new file mode 100644 index 000000000000..747fece9e063 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.cpp @@ -0,0 +1,444 @@ +#include "Box2DTestDebugDrawNode.h" +#include "VisibleRect.h" +#include "axmol/physics/PhysicsHelper.h" +#include "imgui.h" + +using namespace ax; + +Box2DTestDebugDrawNode* g_pDebugDrawNode; +GLFWwindow* g_mainWindow; +b2SampleCamera g_camera; + +b2AABB b2SampleCamera::GetViewBounds() +{ + b2AABB bounds; + bounds.lowerBound = ConvertScreenToWorld({0.0f, (float)m_height}); + bounds.upperBound = ConvertScreenToWorld({(float)m_width, 0.0f}); + return bounds; +} + +b2Vec2 b2SampleCamera::ConvertScreenToWorld(b2Vec2 ps) +{ + float w = float(m_width); + float h = float(m_height); + float u = ps.x / w; + float v = (h - ps.y) / h; + + float ratio = w / h; + b2Vec2 extents = {m_zoom * ratio, m_zoom}; + + b2Vec2 lower = b2Sub(m_center, extents); + b2Vec2 upper = b2Add(m_center, extents); + + b2Vec2 pw = {(1.0f - u) * lower.x + u * upper.x, (1.0f - v) * lower.y + v * upper.y}; + return pw; +} + +b2Vec2 b2SampleCamera::ConvertWorldToScreen(b2Vec2 pw) +{ + float w = float(m_width); + float h = float(m_height); + float ratio = w / h; + + b2Vec2 extents = {m_zoom * ratio, m_zoom}; + + b2Vec2 lower = b2Sub(m_center, extents); + b2Vec2 upper = b2Add(m_center, extents); + + float u = (pw.x - lower.x) / (upper.x - lower.x); + float v = (pw.y - lower.y) / (upper.y - lower.y); + + b2Vec2 ps = {u * w, (1.0f - v) * h}; + return ps; +} + +static void b2DrawCircle(b2Vec2 center, float radius, b2HexColor color, Box2DTestDebugDrawNode* context) +{ + auto ratio = context->getPTMRatio(); + auto offset = context->getWorldOffset(); + context->AddCircle(CircleData{PhysicsHelper::toColor(color), b2Vec2{center.x * ratio + offset.x, center.y * ratio + offset.y}, radius * ratio}); +} + +static void b2DrawSolidCircle(b2Transform t, float radius, b2HexColor color, Box2DTestDebugDrawNode* context) +{ + // RGBA8 rgba = MakeRGBA8(color, 1.0f); + // m_circles.push_back({{transform.p.x, transform.p.y, transform.q.c, transform.q.s}, radius, rgba}); + auto ratio = context->getPTMRatio(); + auto offset = context->getWorldOffset(); + context->AddCircle({{t.p.x * ratio + offset.x, t.p.y * ratio + offset.y, t.q.c, t.q.s}, + PhysicsHelper::toColor(color), radius * ratio}); +} + +static void b2DrawSolidCapsule(b2Vec2 pt1, b2Vec2 pt2, float radius, b2HexColor c, Box2DTestDebugDrawNode* context) +{ + auto ratio = context->getPTMRatio(); + auto offset = context->getWorldOffset(); + Vec2 p1{pt1.x * ratio, pt1.y * ratio}, p2{pt2.x * ratio, pt2.y * ratio}; + + Vec2 d = (p2 - p1); + float length = d.length(); + if (length < 0.001f) + { + printf("WARNING: sample app: capsule too short!\n"); + return; + } + + b2Vec2 axis = {d.x / length, d.y / length}; + b2Transform transform; + transform.p = PhysicsHelper::tob2Vec2(0.5f * (p1 + p2)); + transform.q.c = axis.x; + transform.q.s = axis.y; + + auto rgba = PhysicsHelper::toColor(c); + + context->AddCapsule({{transform.p.x + offset.x, transform.p.y + offset.y, transform.q.c, transform.q.s}, + rgba, + radius * ratio, + length + }); +} + +bool Box2DTestDebugDrawNode::initWithWorld(b2WorldId worldId) +{ + g_pDebugDrawNode = this; + g_mainWindow = static_cast(_director->getRenderView())->getWindow(); + + bool ret = ax::extension::PhysicsDebugNode::initWithWorld(worldId); + +#define __b2_setfun(f) _debugDraw.f##Fcn = reinterpret_cast(b2##f); + __b2_setfun(DrawCircle); + __b2_setfun(DrawSolidCircle); + __b2_setfun(DrawSolidCapsule); +#undef __b2_setfun + + // Demo messageString + _textRender = Label::createWithTTF("TEST", "fonts/arial.ttf", 8.0f); + _textRender->setAnchorPoint(Vec2(0, 1)); + _textRender->setPosition(VisibleRect::left().x, VisibleRect::top().y - 10); + _textRender->setColor(Color32::WHITE); + this->addChild(_textRender, 99); + + /// circle shader + { + auto& cmd = _customCommandCircle; + auto& pipelinePS = cmd.getPipelineDesc().programState; + AX_SAFE_RELEASE(pipelinePS); + + // vertex attributes + auto program = axpm->loadProgram("custom/circle_vs", "custom/circle_fs"); + pipelinePS = new rhi::ProgramState(program); + auto vfmt = pipelinePS->getMutableVertexLayout(); + vfmt->setAttrib("a_localPosition", program->getVertexInputDesc("a_localPosition"), + rhi::VertexFormat::FLOAT2, 0, false); + vfmt->setStride(sizeof(Vec2)); + cmd.createVertexBuffer(sizeof(Vec2), 6, CustomCommand::BufferUsage::STATIC); + float a = 1.1f; + b2Vec2 vertices[] = {{-a, -a}, {a, -a}, {-a, a}, {a, -a}, {a, a}, {-a, a}}; + cmd.updateVertexBuffer(vertices, sizeof(vertices)); + cmd.setVertexDrawInfo(0, 6); + + // instanced attributes + vfmt->setAttrib("a_instanceColor", program->getVertexInputDesc("a_instanceColor"), + rhi::VertexFormat::FLOAT4, offsetof(CircleData, rgba), false, 1); + vfmt->setAttrib("a_instancePosAndRadius", program->getVertexInputDesc("a_instancePosAndRadius"), + rhi::VertexFormat::FLOAT4, offsetof(CircleData, position), false, 1); + vfmt->setInstanceStride(sizeof(CircleData)); + + cmd.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + cmd.setDrawType(CustomCommand::DrawType::ARRAY_INSTANCED); + } + + /// solid circle shader + { + auto& cmd = _customCommandSolidCircle; + auto& pipelinePS = cmd.getPipelineDesc().programState; + AX_SAFE_RELEASE(pipelinePS); + + // vertex attributes + auto program = axpm->loadProgram("custom/solid_circle_vs", "custom/solid_circle_fs"); + pipelinePS = new rhi::ProgramState(program); + auto vfmt = pipelinePS->getMutableVertexLayout(); + vfmt->setAttrib("a_localPosition", program->getVertexInputDesc("a_localPosition"), + rhi::VertexFormat::FLOAT2, 0, false); + vfmt->setStride(sizeof(Vec2)); + cmd.createVertexBuffer(sizeof(Vec2), 6, CustomCommand::BufferUsage::STATIC); + float a = 1.1f; + b2Vec2 vertices[] = {{-a, -a}, {a, -a}, {-a, a}, {a, -a}, {a, a}, {-a, a}}; + cmd.updateVertexBuffer(vertices, sizeof(vertices)); + cmd.setVertexDrawInfo(0, 6); + + // instanced attributes + vfmt->setAttrib("a_instanceTransform", program->getVertexInputDesc("a_instanceTransform"), + rhi::VertexFormat::FLOAT4, offsetof(SolidCircleData, transform), false, 1); + vfmt->setAttrib("a_instanceColor", program->getVertexInputDesc("a_instanceColor"), + rhi::VertexFormat::FLOAT4, offsetof(SolidCircleData, rgba), false, 1); + vfmt->setAttrib("a_instanceRadius", program->getVertexInputDesc("a_instanceRadius"), + rhi::VertexFormat::FLOAT4, offsetof(SolidCircleData, radius), false, 1); + vfmt->setInstanceStride(sizeof(SolidCircleData)); + + cmd.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + cmd.setDrawType(CustomCommand::DrawType::ARRAY_INSTANCED); + } + + /// solid capsule shader + { + auto& cmd = _customCommandCapsule; + auto& pipelinePS = cmd.getPipelineDesc().programState; + AX_SAFE_RELEASE(pipelinePS); + + // vertex attributes + auto program = axpm->loadProgram("custom/solid_capsule_vs", "custom/solid_capsule_fs"); + pipelinePS = new rhi::ProgramState(program); + auto vfmt = pipelinePS->getMutableVertexLayout(); + vfmt->setAttrib("a_localPosition", program->getVertexInputDesc("a_localPosition"), + rhi::VertexFormat::FLOAT2, 0, false); + vfmt->setStride(sizeof(Vec2)); + cmd.createVertexBuffer(sizeof(Vec2), 6, CustomCommand::BufferUsage::STATIC); + float a = 1.1f; + b2Vec2 vertices[] = {{-a, -a}, {a, -a}, {-a, a}, {a, -a}, {a, a}, {-a, a}}; + cmd.updateVertexBuffer(vertices, sizeof(vertices)); + cmd.setVertexDrawInfo(0, 6); + + // instanced attributes + vfmt->setAttrib("a_instanceTransform", program->getVertexInputDesc("a_instanceTransform"), + rhi::VertexFormat::FLOAT4, offsetof(CapsuleData, transform), false, 1); + vfmt->setAttrib("a_instanceColor", program->getVertexInputDesc("a_instanceColor"), + rhi::VertexFormat::FLOAT4, offsetof(CapsuleData, rgba), false, 1); + vfmt->setAttrib("a_instanceRadiusAndLength", program->getVertexInputDesc("a_instanceRadiusAndLength"), + rhi::VertexFormat::FLOAT4, offsetof(CapsuleData, radius), false, 1); + vfmt->setInstanceStride(sizeof(CapsuleData)); + + cmd.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE); + cmd.setDrawType(CustomCommand::DrawType::ARRAY_INSTANCED); + } + + return ret; +} + +void Box2DTestDebugDrawNode::DrawPolygon(const b2Vec2* vertices, int32_t vertexCount, b2HexColor color) +{ + _debugDraw.DrawPolygonFcn(vertices, vertexCount, color, this); +} + +void Box2DTestDebugDrawNode::DrawSolidPolygon(b2Transform transform, + const b2Vec2* vertices, + int32_t vertexCount, + float radius, + b2HexColor color) +{ + _debugDraw.DrawSolidPolygonFcn(transform, vertices, vertexCount, radius, color, this); +} + +void Box2DTestDebugDrawNode::DrawCircle(b2Vec2 center, float radius, b2HexColor color) +{ + _debugDraw.DrawCircleFcn(center, radius, color, this); +} +void Box2DTestDebugDrawNode::DrawSolidCircle(b2Transform transform, b2Vec2 center, float radius, b2HexColor color) +{ + _debugDraw.DrawSolidCircleFcn(transform, radius, color, this); +} + +void Box2DTestDebugDrawNode::DrawSolidCapsule(b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color) +{ + _debugDraw.DrawSolidCapsuleFcn(p1, p2, radius, color, this); +} + +void Box2DTestDebugDrawNode::DrawSegment(b2Vec2 p1, b2Vec2 p2, b2HexColor color) +{ + _debugDraw.DrawSegmentFcn(p1, p2, color, this); +} + +void Box2DTestDebugDrawNode::DrawTransform(b2Transform transform) +{ + _debugDraw.DrawTransformFcn(transform, this); +} + +void Box2DTestDebugDrawNode::DrawPoint(b2Vec2 p, float size, b2HexColor color) +{ + _debugDraw.DrawPointFcn(p, size, color, this); +} + +void Box2DTestDebugDrawNode::DrawString(int x, int y, const char* pszFormat, ...) +{ + // va_list args; + // va_start(args, pszFormat); + // auto ret = text_utils::vformat(pszFormat, args); + // va_end(args); + // + // _debugString.append(ret); + // _debugString.push_back('\n'); + // _textRender->setString(_debugString); + + va_list arg; + va_start(arg, pszFormat); + ImGui::Begin("Overlay", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar); + ImGui::PushFont(g_draw.m_regularFont, ImGui::GetStyle().FontSizeBase); + ImGui::SetCursorPos(ImVec2(float(x), float(y))); + ImGui::TextColoredV(ImColor(230, 153, 153, 255), pszFormat, arg); + ImGui::PopFont(); + ImGui::End(); + va_end(arg); +} + +void Box2DTestDebugDrawNode::DrawString(b2Vec2 p, const char* pszFormat, ...) +{ + /*va_list args; + va_start(args, pszFormat); + auto ret = text_utils::vformat(pszFormat, args); + va_end(args); + + _debugString.append(ret); + _debugString.push_back('\n'); + _textRender->setString(_debugString);*/ + + b2Vec2 ps = g_camera.ConvertWorldToScreen(p); + + va_list arg; + va_start(arg, pszFormat); + ImGui::Begin("Overlay", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar); + ImGui::SetCursorPos(ImVec2(ps.x, ps.y)); + ImGui::TextColoredV(ImColor(230, 230, 230, 255), pszFormat, arg); + ImGui::End(); + va_end(arg); +} + +void Box2DTestDebugDrawNode::AddCapsule(const CapsuleData& capsule) +{ + _capsules.push_back(capsule); + _capsulesDirty = true; +} + +void Box2DTestDebugDrawNode::AddCircle(const CircleData& circle) +{ + _circles.push_back(circle); + _circlesDirty = true; +} + +void Box2DTestDebugDrawNode::AddCircle(const SolidCircleData& circle) +{ + _solidCircles.push_back(circle); + _solidCirclesDirty = true; +} + +void Box2DTestDebugDrawNode::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) +{ + PhysicsDebugNode::draw(renderer, transform, flags); + + /// circle + + // update buffer + if (_circlesDirty) + { + _circlesDirty = false; + if (_circles.empty()) + _customCommandCircle.setInstanceBuffer(nullptr, 0); + else + { + if (_customCommandCircle.getInstanceCapacity() < static_cast(_circles.size())) + _customCommandCircle.createInstanceBuffer(sizeof(CircleData), _circles.size(), + CustomCommand::BufferUsage::DYNAMIC); + _customCommandCircle.updateInstanceBuffer(_circles.data(), _circles.size() * sizeof(CircleData)); + _customCommandCircle.setInstanceDrawInfo(static_cast(_circles.size())); + } + } + + // submit draw command + if (_customCommandCircle.getInstanceCount() > 0) + submitDrawCommand(renderer, _customCommandCircle, transform); + + /// solid circle + + // update buffer + if (_solidCirclesDirty) + { + _solidCirclesDirty = false; + if (_solidCircles.empty()) + _customCommandSolidCircle.setInstanceBuffer(nullptr, 0); + else + { + if (_customCommandSolidCircle.getInstanceCapacity() < static_cast(_solidCircles.size())) + _customCommandSolidCircle.createInstanceBuffer(sizeof(SolidCircleData), _solidCircles.size(), + CustomCommand::BufferUsage::DYNAMIC); + _customCommandSolidCircle.updateInstanceBuffer(_solidCircles.data(), + _solidCircles.size() * sizeof(SolidCircleData)); + _customCommandSolidCircle.setInstanceDrawInfo(static_cast(_solidCircles.size())); + } + } + + // submit draw command + if (_customCommandSolidCircle.getInstanceCount() > 0) + submitDrawCommand(renderer, _customCommandSolidCircle, transform); + + /// capsule + + // update buffer + if (_capsulesDirty) + { + _capsulesDirty = false; + if (_capsules.empty()) + _customCommandCapsule.setInstanceBuffer(nullptr, 0); + else + { + if (_customCommandCapsule.getInstanceCapacity() < static_cast(_capsules.size())) + _customCommandCapsule.createInstanceBuffer(sizeof(CapsuleData), _capsules.size(), + CustomCommand::BufferUsage::DYNAMIC); + _customCommandCapsule.updateInstanceBuffer(_capsules.data(), _capsules.size() * sizeof(CapsuleData)); + _customCommandCapsule.setInstanceDrawInfo(static_cast(_capsules.size())); + } + } + + // submit draw command + if (_customCommandCapsule.getInstanceCount() > 0) + submitDrawCommand(renderer, _customCommandCapsule, transform); +} + +void Box2DTestDebugDrawNode::submitDrawCommand(Renderer* renderer, CustomCommand& cmd, const Mat4& transform) +{ + rhi::BlendDesc& blendDescriptor = cmd.getPipelineDesc().blendDesc; + blendDescriptor.blendEnabled = true; + blendDescriptor.sourceRGBBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDescriptor.destinationRGBBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor.sourceAlphaBlendFactor = rhi::BlendFactor::SRC_ALPHA; + blendDescriptor.destinationAlphaBlendFactor = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + + auto& pipelineDescriptor = cmd.getPipelineDesc(); + const auto& matrixP = _director->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); + Mat4 matrixMVP = matrixP * transform; + auto mvpLocation = pipelineDescriptor.programState->getUniformLocation("u_MVPMatrix"); + pipelineDescriptor.programState->setUniform(mvpLocation, matrixMVP.m, sizeof(matrixMVP.m)); + + auto viewHeight = _director->getRenderView()->getDesignResolutionSize().height; + constexpr float zoom = 25.0 * 2.35f; + float pixelScale = viewHeight / zoom; + auto uniformLocation = pipelineDescriptor.programState->getUniformLocation("u_pixelScale"); + pipelineDescriptor.programState->setUniform(uniformLocation, &pixelScale, sizeof(pixelScale)); + + cmd.init(_globalZOrder); + renderer->addCommand(&cmd); +} + +void Box2DTestDebugDrawNode::clear() +{ + ax::extension::PhysicsDebugNode::clear(); + + _circles.clear(); + _circlesDirty = true; + + _solidCircles.clear(); + _solidCirclesDirty = true; + + _capsules.clear(); + _capsulesDirty = true; + + _debugString.clear(); +} + +void Box2DTestDebugDrawNode::DrawAABB(b2AABB aabb, b2HexColor color) +{ + this->drawRect(Vec2{aabb.lowerBound.x, aabb.lowerBound.y}, Vec2{aabb.upperBound.x, aabb.upperBound.y}, + PhysicsHelper::toColor(color)); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.h b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.h new file mode 100644 index 000000000000..824f4a786c56 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/Box2DTestDebugDrawNode.h @@ -0,0 +1,114 @@ +#pragma once + +#include "axmol/platform/RenderViewImpl.h" +#include "physics-nodes/PhysicsDebugNode.h" + +using namespace ax; + +struct ImFont; + +struct CircleData +{ + ax::Color rgba; + b2Vec2 position; + float radius; + float padding; +}; + +struct SolidCircleData +{ + b2Transform transform; + ax::Color rgba; + float radius; + float padding[3]; +}; + +struct CapsuleData +{ + b2Transform transform; + ax::Color rgba; + float radius; + float length; + float padding[2]; +}; + +class Box2DTestDebugDrawNode : public ax::extension::PhysicsDebugNode +{ +public: + Box2DTestDebugDrawNode() : m_debugDraw(_debugDraw) {} + ~Box2DTestDebugDrawNode() + { + + } + bool initWithWorld(b2WorldId worldId) override; + + void DrawPolygon(const b2Vec2* vertices, int32_t vertexCount, b2HexColor color); + void DrawSolidPolygon(b2Transform transform, + const b2Vec2* vertices, + int32_t vertexCount, + float radius, + b2HexColor color); + + void DrawCircle(b2Vec2 center, float radius, b2HexColor color); + void DrawSolidCircle(b2Transform transform, b2Vec2 center, float radius, b2HexColor color); + + void DrawSolidCapsule(b2Vec2 p1, b2Vec2 p2, float radius, b2HexColor color); + + void DrawSegment(b2Vec2 p1, b2Vec2 p2, b2HexColor color); + + void DrawTransform(b2Transform transform); + + void DrawPoint(b2Vec2 p, float size, b2HexColor color); + + void DrawString(int x, int y, const char* string, ...); + + void DrawString(b2Vec2 p, const char* string, ...); + + void DrawAABB(b2AABB aabb, b2HexColor color); + + void AddCircle(const CircleData& circle); + void AddCircle(const SolidCircleData& circle); + void AddCapsule(const CapsuleData& capsule); + + void submitDrawCommand(Renderer* renderer, CustomCommand& cmd, const Mat4& transform); + + void draw(Renderer* renderer, const Mat4& transform, uint32_t flags); + void clear() override; + + b2DebugDraw& m_debugDraw; + bool m_showUI{true}; + + ax::Label* _textRender{nullptr}; + std::string _debugString; + + CustomCommand _customCommandCircle; + CustomCommand _customCommandSolidCircle; + CustomCommand _customCommandCapsule; + axstd::pod_vector _circles; + axstd::pod_vector _solidCircles; + axstd::pod_vector _capsules; + bool _circlesDirty{true}; + bool _solidCirclesDirty{true}; + bool _capsulesDirty{true}; + + ImFont* m_regularFont{nullptr}; +}; + +extern Box2DTestDebugDrawNode* g_pDebugDrawNode; +#define g_draw (*g_pDebugDrawNode) + +extern GLFWwindow* g_mainWindow; + +struct b2SampleCamera +{ + b2Vec2 ConvertScreenToWorld(b2Vec2 ps); + b2Vec2 ConvertWorldToScreen(b2Vec2 pw); + b2AABB GetViewBounds(); + b2Vec2 m_center{0.0f, 0.0f}; + float m_zoom{1.0f}; + float m_width{480}; + float m_height{320}; +}; + +extern b2SampleCamera g_camera; + diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/LockLessMultiReadPipe.h b/tests/cpp-tests/Source/Box2DTestBed/samples/LockLessMultiReadPipe.h new file mode 100644 index 000000000000..339c8bdd486c --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/LockLessMultiReadPipe.h @@ -0,0 +1,283 @@ +// Copyright (c) 2013 Doug Binks +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgement in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#pragma once + +#include +#include +#include + +#ifndef ENKI_ASSERT +#include +#define ENKI_ASSERT(x) assert(x) +#endif + +namespace enki +{ + // LockLessMultiReadPipe - Single writer, multiple reader thread safe pipe using (semi) lockless programming + // Readers can only read from the back of the pipe + // The single writer can write to the front of the pipe, and read from both ends (a writer can be a reader) + // for many of the principles used here, see http://msdn.microsoft.com/en-us/library/windows/desktop/ee418650(v=vs.85).aspx + // Note: using log2 sizes so we do not need to clamp (multi-operation) + // T is the contained type + // Note this is not true lockless as the use of flags as a form of lock state. + template class LockLessMultiReadPipe + { + public: + LockLessMultiReadPipe(); + ~LockLessMultiReadPipe() {} + + // ReaderTryReadBack returns false if we were unable to read + // This is thread safe for both multiple readers and the writer + bool ReaderTryReadBack( T* pOut ); + + // WriterTryReadFront returns false if we were unable to read + // This is thread safe for the single writer, but should not be called by readers + bool WriterTryReadFront( T* pOut ); + + // WriterTryWriteFront returns false if we were unable to write + // This is thread safe for the single writer, but should not be called by readers + bool WriterTryWriteFront( const T& in ); + + // IsPipeEmpty() is a utility function, not intended for general use + // Should only be used very prudently. + bool IsPipeEmpty() const + { + return 0 == m_WriteIndex.load( std::memory_order_relaxed ) - m_ReadCount.load( std::memory_order_relaxed ); + } + + void Clear() + { + m_WriteIndex = 0; + m_ReadIndex = 0; + m_ReadCount = 0; + memset( (void*)m_Flags, 0, sizeof( m_Flags ) ); + } + + private: + const static uint32_t ms_cSize = ( 1 << cSizeLog2 ); + const static uint32_t ms_cIndexMask = ms_cSize - 1; + const static uint32_t FLAG_INVALID = 0xFFFFFFFF; // 32bit for CAS + const static uint32_t FLAG_CAN_WRITE = 0x00000000; // 32bit for CAS + const static uint32_t FLAG_CAN_READ = 0x11111111; // 32bit for CAS + + T m_Buffer[ ms_cSize ]; + + // read and write indexes allow fast access to the pipe, but actual access + // controlled by the access flags. + std::atomic m_WriteIndex; + std::atomic m_ReadCount; + std::atomic m_Flags[ ms_cSize ]; + std::atomic m_ReadIndex; + }; + + template inline + LockLessMultiReadPipe::LockLessMultiReadPipe() + : m_WriteIndex(0) + , m_ReadCount(0) + , m_ReadIndex(0) + { + ENKI_ASSERT( cSizeLog2 < 32 ); + memset( (void*)m_Flags, 0, sizeof( m_Flags ) ); + } + + template inline + bool LockLessMultiReadPipe::ReaderTryReadBack( T* pOut ) + { + + uint32_t actualReadIndex; + uint32_t readCount = m_ReadCount.load( std::memory_order_relaxed ); + + // We get hold of read index for consistency + // and do first pass starting at read count + uint32_t readIndexToUse = readCount; + while(true) + { + + uint32_t writeIndex = m_WriteIndex.load( std::memory_order_relaxed ); + // power of two sizes ensures we can use a simple calc without modulus + uint32_t numInPipe = writeIndex - readCount; + if( 0 == numInPipe ) + { + return false; + } + if( readIndexToUse >= writeIndex ) + { + readIndexToUse = m_ReadIndex.load( std::memory_order_relaxed ); + } + + // power of two sizes ensures we can perform AND for a modulus + actualReadIndex = readIndexToUse & ms_cIndexMask; + + // Multiple potential readers mean we should check if the data is valid, + // using an atomic compare exchange + uint32_t previous = FLAG_CAN_READ; + bool bSuccess = m_Flags[ actualReadIndex ].compare_exchange_strong( previous, FLAG_INVALID, std::memory_order_acq_rel, std::memory_order_relaxed ); + if( bSuccess ) + { + break; + } + ++readIndexToUse; + + // Update read count + readCount = m_ReadCount.load( std::memory_order_relaxed ); + } + + // we update the read index using an atomic add, as we've only read one piece of data. + // this ensure consistency of the read index, and the above loop ensures readers + // only read from unread data + m_ReadCount.fetch_add(1, std::memory_order_relaxed ); + + // now read data, ensuring we do so after above reads & CAS + *pOut = m_Buffer[ actualReadIndex ]; + + m_Flags[ actualReadIndex ].store( FLAG_CAN_WRITE, std::memory_order_release ); + + return true; + } + + template inline + bool LockLessMultiReadPipe::WriterTryReadFront( T* pOut ) + { + uint32_t writeIndex = m_WriteIndex.load( std::memory_order_relaxed ); + uint32_t frontReadIndex = writeIndex; + + // Multiple potential readers mean we should check if the data is valid, + // using an atomic compare exchange - which acts as a form of lock (so not quite lockless really). + uint32_t actualReadIndex = 0; + while(true) + { + uint32_t readCount = m_ReadCount.load( std::memory_order_relaxed ); + // power of two sizes ensures we can use a simple calc without modulus + uint32_t numInPipe = writeIndex - readCount; + if( 0 == numInPipe ) + { + m_ReadIndex.store( readCount, std::memory_order_release ); + return false; + } + --frontReadIndex; + actualReadIndex = frontReadIndex & ms_cIndexMask; + uint32_t previous = FLAG_CAN_READ; + bool success = m_Flags[ actualReadIndex ].compare_exchange_strong( previous, FLAG_INVALID, std::memory_order_acq_rel, std::memory_order_relaxed ); + if( success ) + { + break; + } + else if( m_ReadIndex.load( std::memory_order_acquire ) >= frontReadIndex ) + { + return false; + } + } + + // now read data, ensuring we do so after above reads & CAS + *pOut = m_Buffer[ actualReadIndex ]; + + m_Flags[ actualReadIndex ].store( FLAG_CAN_WRITE, std::memory_order_relaxed ); + + m_WriteIndex.store(writeIndex-1, std::memory_order_relaxed); + return true; + } + + + template inline + bool LockLessMultiReadPipe::WriterTryWriteFront( const T& in ) + { + // The writer 'owns' the write index, and readers can only reduce + // the amount of data in the pipe. + // We get hold of both values for consistency and to reduce false sharing + // impacting more than one access + uint32_t writeIndex = m_WriteIndex; + + // power of two sizes ensures we can perform AND for a modulus + uint32_t actualWriteIndex = writeIndex & ms_cIndexMask; + + // a reader may still be reading this item, as there are multiple readers + if( m_Flags[ actualWriteIndex ].load(std::memory_order_acquire) != FLAG_CAN_WRITE ) + { + return false; // still being read, so have caught up with tail. + } + + // as we are the only writer we can update the data without atomics + // whilst the write index has not been updated + m_Buffer[ actualWriteIndex ] = in; + m_Flags[ actualWriteIndex ].store( FLAG_CAN_READ, std::memory_order_release ); + + m_WriteIndex.fetch_add(1, std::memory_order_relaxed); + return true; + } + + + // Lockless multiwriter intrusive list + // Type T must implement T* volatile pNext; + template class LocklessMultiWriteIntrusiveList + { + + std::atomic pHead; + T tail; + public: + LocklessMultiWriteIntrusiveList() : pHead( &tail ) + { + tail.pNext = NULL; + } + + bool IsListEmpty() const + { + return pHead == &tail; + } + + // Add - safe to perform from any thread + void WriterWriteFront( T* pNode_ ) + { + ENKI_ASSERT( pNode_ ); + pNode_->pNext = NULL; + T* pPrev = pHead.exchange( pNode_ ); + pPrev->pNext = pNode_; + } + + // Remove - only thread safe for owner + T* ReaderReadBack() + { + T* pTailPlus1 = tail.pNext; + if( pTailPlus1 ) + { + T* pTailPlus2 = pTailPlus1->pNext; + if( pTailPlus2 ) + { + //not head + tail.pNext = pTailPlus2; + } + else + { + tail.pNext = NULL; + T* pCompare = pTailPlus1; // we need preserve pTailPlus1 as compare will alter it on failure + // pTailPlus1 is the head, attempt swap with tail + if( !pHead.compare_exchange_strong( pCompare, &tail ) ) + { + // pCompare receives the revised pHead on failure. + // pTailPlus1 is no longer the head, so pTailPlus1->pNext should be non NULL + while( (T*)NULL == pTailPlus1->pNext ) {;} // wait for pNext to be updated as head may have just changed. + tail.pNext = pTailPlus1->pNext.load(); + pTailPlus1->pNext = NULL; + } + } + } + return pTailPlus1; + } + }; + +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.cpp new file mode 100644 index 000000000000..a0edaa951bc1 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.cpp @@ -0,0 +1,1547 @@ +// Copyright (c) 2013 Doug Binks +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgement in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#include "TaskScheduler.h" +#include "LockLessMultiReadPipe.h" + +#include + +#if defined __i386__ || defined __x86_64__ +#include "x86intrin.h" +#elif defined _WIN32 +#include +#endif + +using namespace enki; + +#if defined(ENKI_CUSTOM_ALLOC_FILE_AND_LINE) +#define ENKI_FILE_AND_LINE __FILE__, __LINE__ +#else +namespace +{ + const char* gc_File = ""; + const uint32_t gc_Line = 0; +} +#define ENKI_FILE_AND_LINE gc_File, gc_Line +#endif + +// UWP and MinGW don't have GetActiveProcessorCount +#if defined(_WIN64) \ + && !defined(__MINGW32__) \ + && !(defined(WINAPI_FAMILY) && (WINAPI_FAMILY == WINAPI_FAMILY_PC_APP || WINAPI_FAMILY == WINAPI_FAMILY_PHONE_APP)) +#define ENKI_USE_WINDOWS_PROCESSOR_API +#endif + +#ifdef ENKI_USE_WINDOWS_PROCESSOR_API +#ifndef WIN32_LEAN_AND_MEAN + #define WIN32_LEAN_AND_MEAN +#endif + +#ifndef NOMINMAX + #define NOMINMAX +#endif +#include +#endif + +uint32_t enki::GetNumHardwareThreads() +{ +#ifdef ENKI_USE_WINDOWS_PROCESSOR_API + return GetActiveProcessorCount(ALL_PROCESSOR_GROUPS); +#else + return std::thread::hardware_concurrency(); +#endif +} + +namespace enki +{ + static constexpr int32_t gc_TaskStartCount = 2; + static constexpr int32_t gc_TaskAlmostCompleteCount = 1; // GetIsComplete() will return false, but execution is done and about to complete + static constexpr uint32_t gc_PipeSizeLog2 = 8; + static constexpr uint32_t gc_SpinCount = 10; + static constexpr uint32_t gc_SpinBackOffMultiplier = 100; + static constexpr uint32_t gc_MaxNumInitialPartitions = 8; + static constexpr uint32_t gc_MaxStolenPartitions = 1 << gc_PipeSizeLog2; + static constexpr uint32_t gc_CacheLineSize = 64; + // awaiting std::hardware_constructive_interference_size +} + +// thread_local not well supported yet by some older C++11 compilers. +// For XCode before version 8 thread_local is not defined, so add to your compile defines: ENKI_THREAD_LOCAL __thread +#ifndef ENKI_THREAD_LOCAL +#if defined(_MSC_VER) && _MSC_VER <= 1800 + #define ENKI_THREAD_LOCAL __declspec(thread) +// Removed below as XCode supports thread_local since version 8 +// #elif __APPLE__ +// // Apple thread_local currently not implemented in XCode before version 8 despite it being in Clang. +// #define ENKI_THREAD_LOCAL __thread +#else + #define ENKI_THREAD_LOCAL thread_local +#endif +#endif + + +// each software thread gets its own copy of gtl_threadNum, so this is safe to use as a static variable +static ENKI_THREAD_LOCAL uint32_t gtl_threadNum = enki::NO_THREAD_NUM; + +namespace enki +{ + struct SubTaskSet + { + ITaskSet* pTask; + TaskSetPartition partition; + }; + + // we derive class TaskPipe rather than typedef to get forward declaration working easily + class TaskPipe : public LockLessMultiReadPipe {}; + + enum ThreadState : int32_t + { + ENKI_THREAD_STATE_NONE, // shouldn't get this value + ENKI_THREAD_STATE_NOT_LAUNCHED, // for debug purposes - indicates enki task thread not yet launched + ENKI_THREAD_STATE_RUNNING, + ENKI_THREAD_STATE_PRIMARY_REGISTERED, // primary thread is the one enkiTS was initialized on + ENKI_THREAD_STATE_EXTERNAL_REGISTERED, + ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED, + ENKI_THREAD_STATE_WAIT_TASK_COMPLETION, + ENKI_THREAD_STATE_WAIT_NEW_TASKS, + ENKI_THREAD_STATE_WAIT_NEW_PINNED_TASKS, + ENKI_THREAD_STATE_STOPPED, + }; + + struct ThreadArgs + { + uint32_t threadNum; + TaskScheduler* pTaskScheduler; + }; + + struct alignas(enki::gc_CacheLineSize) ThreadDataStore + { + semaphoreid_t* pWaitNewPinnedTaskSemaphore = nullptr; + std::atomic threadState = { ENKI_THREAD_STATE_NONE }; + uint32_t rndSeed = 0; + char prevent_false_Share[ enki::gc_CacheLineSize - sizeof(std::atomic) - sizeof(semaphoreid_t*) - sizeof( uint32_t ) ]; // required to prevent alignment padding warning + }; + constexpr size_t SIZEOFTHREADDATASTORE = sizeof( ThreadDataStore ); // for easier inspection + static_assert( SIZEOFTHREADDATASTORE == enki::gc_CacheLineSize, "ThreadDataStore may exhibit false sharing" ); + + class PinnedTaskList : public LocklessMultiWriteIntrusiveList {}; + + semaphoreid_t* SemaphoreCreate(); + void SemaphoreDelete( semaphoreid_t* pSemaphore_ ); + void SemaphoreWait( semaphoreid_t& semaphoreid ); + void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting ); +} + +namespace +{ + SubTaskSet SplitTask( SubTaskSet& subTask_, uint32_t rangeToSplit_ ) + { + SubTaskSet splitTask = subTask_; + uint32_t rangeLeft = subTask_.partition.end - subTask_.partition.start; + rangeToSplit_ = std::min( rangeToSplit_, rangeLeft ); + splitTask.partition.end = subTask_.partition.start + rangeToSplit_; + subTask_.partition.start = splitTask.partition.end; + return splitTask; + } + + #if ( defined _WIN32 && ( defined _M_IX86 || defined _M_X64 ) ) || ( defined __i386__ || defined __x86_64__ ) + // Note: see https://software.intel.com/en-us/articles/a-common-construct-to-avoid-the-contention-of-threads-architecture-agnostic-spin-wait-loops + void SpinWait( uint32_t spinCount_ ) + { + uint64_t end = __rdtsc() + spinCount_; + while( __rdtsc() < end ) + { + _mm_pause(); + } + } + #else + void SpinWait( uint32_t spinCount_ ) + { + while( spinCount_ ) + { + // TODO: may have NOP or yield equiv + --spinCount_; + } + } + #endif + + void SafeCallback( ProfilerCallbackFunc func_, uint32_t threadnum_ ) + { + if( func_ != nullptr ) + { + func_( threadnum_ ); + } + } +} + + +ENKITS_API void* enki::DefaultAllocFunc( size_t align_, size_t size_, void* userData_, const char* file_, int line_ ) +{ + (void)userData_; (void)file_; (void)line_; + void* pRet; +#ifdef _WIN32 + pRet = (void*)_aligned_malloc( size_, align_ ); +#else + pRet = nullptr; + if( align_ <= size_ && align_ <= alignof(int64_t) ) + { + // no need for alignment, use malloc + pRet = malloc( size_ ); + } + else + { + int retval = posix_memalign( &pRet, align_, size_ ); + (void)retval; // unused + } +#endif + return pRet; +} + +ENKITS_API void enki::DefaultFreeFunc( void* ptr_, size_t size_, void* userData_, const char* file_, int line_ ) +{ + (void)size_; (void)userData_; (void)file_; (void)line_; +#ifdef _WIN32 + _aligned_free( ptr_ ); +#else + free( ptr_ ); +#endif +} + +bool TaskScheduler::RegisterExternalTaskThread() +{ + bool bRegistered = false; + while( !bRegistered && m_NumExternalTaskThreadsRegistered < (int32_t)m_Config.numExternalTaskThreads ) + { + for(uint32_t thread = GetNumFirstExternalTaskThread(); thread < GetNumFirstExternalTaskThread() + m_Config.numExternalTaskThreads; ++thread ) + { + ThreadState threadStateExpected = ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED; + if( m_pThreadDataStore[thread].threadState.compare_exchange_strong( + threadStateExpected, ENKI_THREAD_STATE_EXTERNAL_REGISTERED ) ) + { + ++m_NumExternalTaskThreadsRegistered; + gtl_threadNum = thread; + bRegistered = true; + break; + } + } + } + return bRegistered; +} + +bool TaskScheduler::RegisterExternalTaskThread( uint32_t threadNumToRegister_ ) +{ + ENKI_ASSERT( threadNumToRegister_ >= GetNumFirstExternalTaskThread() ); + ENKI_ASSERT( threadNumToRegister_ < ( GetNumFirstExternalTaskThread() + m_Config.numExternalTaskThreads ) ); + ThreadState threadStateExpected = ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED; + if( m_pThreadDataStore[threadNumToRegister_].threadState.compare_exchange_strong( + threadStateExpected, ENKI_THREAD_STATE_EXTERNAL_REGISTERED ) ) + { + ++m_NumExternalTaskThreadsRegistered; + gtl_threadNum = threadNumToRegister_; + return true; + } + return false; +} + + +void TaskScheduler::DeRegisterExternalTaskThread() +{ + ENKI_ASSERT( gtl_threadNum != enki::NO_THREAD_NUM ); + ENKI_ASSERT( gtl_threadNum >= GetNumFirstExternalTaskThread() ); + ThreadState threadState = m_pThreadDataStore[gtl_threadNum].threadState.load( std::memory_order_acquire ); + ENKI_ASSERT( threadState == ENKI_THREAD_STATE_EXTERNAL_REGISTERED ); + if( threadState == ENKI_THREAD_STATE_EXTERNAL_REGISTERED ) + { + --m_NumExternalTaskThreadsRegistered; + m_pThreadDataStore[gtl_threadNum].threadState.store( ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED, std::memory_order_release ); + gtl_threadNum = enki::NO_THREAD_NUM; + } +} + +uint32_t TaskScheduler::GetNumRegisteredExternalTaskThreads() +{ + return m_NumExternalTaskThreadsRegistered; +} + +void TaskScheduler::TaskingThreadFunction( const ThreadArgs& args_ ) +{ + uint32_t threadNum = args_.threadNum; + TaskScheduler* pTS = args_.pTaskScheduler; + gtl_threadNum = threadNum; + + pTS->m_pThreadDataStore[threadNum].threadState.store( ENKI_THREAD_STATE_RUNNING, std::memory_order_release ); + SafeCallback( pTS->m_Config.profilerCallbacks.threadStart, threadNum ); + + uint32_t spinCount = 0; + uint32_t hintPipeToCheck_io = threadNum + 1; // does not need to be clamped. + while( pTS->GetIsRunningInt() ) + { + if( !pTS->TryRunTask( threadNum, hintPipeToCheck_io ) ) + { + // no tasks, will spin then wait + ++spinCount; + if( spinCount > gc_SpinCount ) + { + pTS->WaitForNewTasks( threadNum ); + } + else + { + uint32_t spinBackoffCount = spinCount * gc_SpinBackOffMultiplier; + SpinWait( spinBackoffCount ); + } + } + else + { + spinCount = 0; // have run a task so reset spin count. + } + } + + pTS->m_NumInternalTaskThreadsRunning.fetch_sub( 1, std::memory_order_release ); + pTS->m_pThreadDataStore[threadNum].threadState.store( ENKI_THREAD_STATE_STOPPED, std::memory_order_release ); + SafeCallback( pTS->m_Config.profilerCallbacks.threadStop, threadNum ); +} + + +void TaskScheduler::StartThreads() +{ + if( m_bHaveThreads ) + { + return; + } + + m_NumThreads = m_Config.numTaskThreadsToCreate + m_Config.numExternalTaskThreads + 1; + + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + m_pPipesPerThread[ priority ] = NewArray( m_NumThreads, ENKI_FILE_AND_LINE ); + m_pPinnedTaskListPerThread[ priority ] = NewArray( m_NumThreads, ENKI_FILE_AND_LINE ); + } + + m_pNewTaskSemaphore = SemaphoreNew(); + m_pTaskCompleteSemaphore = SemaphoreNew(); + + // we create one less thread than m_NumThreads as the main thread counts as one + m_pThreadDataStore = NewArray( m_NumThreads, ENKI_FILE_AND_LINE ); + m_pThreads = NewArray( m_NumThreads, ENKI_FILE_AND_LINE ); + m_bRunning = true; + m_bWaitforAllCalled = false; + m_bShutdownRequested = false; + + // current thread is primary enkiTS thread + m_pThreadDataStore[0].threadState = ENKI_THREAD_STATE_PRIMARY_REGISTERED; + gtl_threadNum = 0; + + for( uint32_t thread = GetNumFirstExternalTaskThread(); thread < m_Config.numExternalTaskThreads + GetNumFirstExternalTaskThread(); ++thread ) + { + m_pThreadDataStore[thread].threadState = ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED; + } + for( uint32_t thread = m_Config.numExternalTaskThreads + GetNumFirstExternalTaskThread(); thread < m_NumThreads; ++thread ) + { + m_pThreadDataStore[thread].threadState = ENKI_THREAD_STATE_NOT_LAUNCHED; + } + + + // Create Wait New Pinned Task Semaphores and init rndSeed + for( uint32_t threadNum = 0; threadNum < m_NumThreads; ++threadNum ) + { + m_pThreadDataStore[threadNum].pWaitNewPinnedTaskSemaphore = SemaphoreNew(); + m_pThreadDataStore[threadNum].rndSeed = threadNum; + } + + // only launch threads once all thread states are set + for( uint32_t thread = m_Config.numExternalTaskThreads + GetNumFirstExternalTaskThread(); thread < m_NumThreads; ++thread ) + { + m_pThreads[thread] = std::thread( TaskingThreadFunction, ThreadArgs{ thread, this } ); + ++m_NumInternalTaskThreadsRunning; + } + + // ensure we have sufficient tasks to equally fill either all threads including main + // or just the threads we've launched, this is outside the first init as we want to be able + // to runtime change it + if( 1 == m_NumThreads ) + { + m_NumPartitions = 1; + m_NumInitialPartitions = 1; + } + else + { + // There could be more threads than hardware threads if external threads are + // being intended for blocking functionality such as io etc. + // We only need to partition for a maximum of the available processor parallelism. + uint32_t numThreadsToPartitionFor = std::min( m_NumThreads, GetNumHardwareThreads() ); + m_NumPartitions = numThreadsToPartitionFor * (numThreadsToPartitionFor - 1); + // ensure m_NumPartitions, m_NumInitialPartitions non zero, can happen if m_NumThreads > 1 && GetNumHardwareThreads() == 1 + m_NumPartitions = std::max( m_NumPartitions, (uint32_t)1 ); + m_NumInitialPartitions = std::max( numThreadsToPartitionFor - 1, (uint32_t)1 ); + m_NumInitialPartitions = std::min( m_NumInitialPartitions, gc_MaxNumInitialPartitions ); + } + +#ifdef ENKI_USE_WINDOWS_PROCESSOR_API + // x64 bit Windows may support >64 logical processors using processor groups, and only allocate threads to a default group. + // We need to detect this and distribute threads accordingly + if( GetNumHardwareThreads() > 64 && // only have processor groups if > 64 hardware threads + std::thread::hardware_concurrency() < GetNumHardwareThreads() && // if std::thread sees > 64 hardware threads no need to distribute + std::thread::hardware_concurrency() < m_NumThreads ) // no need to distribute if number of threads requested lower than std::thread sees + { + uint32_t numProcessorGroups = GetActiveProcessorGroupCount(); + GROUP_AFFINITY mainThreadAffinity; + BOOL success = GetThreadGroupAffinity( GetCurrentThread(), &mainThreadAffinity ); + ENKI_ASSERT( success ); + if( success ) + { + uint32_t mainProcessorGroup = mainThreadAffinity.Group; + uint32_t currLogicalProcess = GetActiveProcessorCount( (WORD)mainProcessorGroup ); // we start iteration at end of current process group's threads + + // If more threads are created than there are logical processors then we still want to distribute them evenly amongst groups + // so we iterate continuously around the groups until we reach m_NumThreads + uint32_t group = 0; + while( currLogicalProcess < m_NumThreads ) + { + ++group; // start at group 1 since we set currLogicalProcess to start of next group + uint32_t currGroup = ( group + mainProcessorGroup ) % numProcessorGroups; // we start at mainProcessorGroup, go round in circles + uint32_t groupNumLogicalProcessors = GetActiveProcessorCount( (WORD)currGroup ); + ENKI_ASSERT( groupNumLogicalProcessors <= 64 ); + uint64_t GROUPMASK = 0xFFFFFFFFFFFFFFFFULL >> (64-groupNumLogicalProcessors); // group mask should not have 1's where there are no processors + for( uint32_t groupLogicalProcess = 0; ( groupLogicalProcess < groupNumLogicalProcessors ) && ( currLogicalProcess < m_NumThreads ); ++groupLogicalProcess, ++currLogicalProcess ) + { + if( currLogicalProcess > m_Config.numExternalTaskThreads + GetNumFirstExternalTaskThread() ) + { + auto thread_handle = m_pThreads[currLogicalProcess].native_handle(); + + // From https://learn.microsoft.com/en-us/windows/win32/procthread/processor-groups + // If a thread is assigned to a different group than the process, the process's affinity is updated to include the thread's affinity + // and the process becomes a multi-group process. + GROUP_AFFINITY threadAffinity; + success = GetThreadGroupAffinity( thread_handle, &threadAffinity ); + ENKI_ASSERT(success); (void)success; + if( threadAffinity.Group != currGroup ) + { + threadAffinity.Group = (WORD)currGroup; + threadAffinity.Mask = GROUPMASK; + success = SetThreadGroupAffinity( thread_handle, &threadAffinity, nullptr ); + ENKI_ASSERT( success ); (void)success; + } + } + } + } + } + } +#endif + + m_bHaveThreads = true; +} + +void TaskScheduler::StopThreads( bool bWait_ ) +{ + // we set m_bWaitforAllCalled to true to ensure any task which loop using this status exit + m_bWaitforAllCalled.store( true, std::memory_order_release ); + + // set status + m_bShutdownRequested.store( true, std::memory_order_release ); + m_bRunning.store( false, std::memory_order_release ); + + if( m_bHaveThreads ) + { + + // wait for threads to quit before deleting data + while( bWait_ && m_NumInternalTaskThreadsRunning ) + { + // keep firing event to ensure all threads pick up state of m_bRunning + WakeThreadsForNewTasks(); + + for( uint32_t threadId = 0; threadId < m_NumThreads; ++threadId ) + { + // send wait for new pinned tasks signal to ensure any waiting are awoken + SemaphoreSignal( *m_pThreadDataStore[ threadId ].pWaitNewPinnedTaskSemaphore, 1 ); + } + } + + // detach threads starting with thread GetNumFirstExternalTaskThread() (as 0 is initialization thread). + for( uint32_t thread = m_Config.numExternalTaskThreads + GetNumFirstExternalTaskThread(); thread < m_NumThreads; ++thread ) + { + ENKI_ASSERT( m_pThreads[thread].joinable() ); + m_pThreads[thread].join(); + } + + // delete any Wait New Pinned Task Semaphores + for( uint32_t threadNum = 0; threadNum < m_NumThreads; ++threadNum ) + { + SemaphoreDelete( m_pThreadDataStore[threadNum].pWaitNewPinnedTaskSemaphore ); + } + + DeleteArray( m_pThreadDataStore, m_NumThreads, ENKI_FILE_AND_LINE ); + DeleteArray( m_pThreads, m_NumThreads, ENKI_FILE_AND_LINE ); + m_pThreadDataStore = 0; + m_pThreads = 0; + + SemaphoreDelete( m_pNewTaskSemaphore ); + m_pNewTaskSemaphore = 0; + SemaphoreDelete( m_pTaskCompleteSemaphore ); + m_pTaskCompleteSemaphore = 0; + + m_bHaveThreads = false; + m_NumThreadsWaitingForNewTasks = 0; + m_NumThreadsWaitingForTaskCompletion = 0; + m_NumInternalTaskThreadsRunning = 0; + m_NumExternalTaskThreadsRegistered = 0; + + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + DeleteArray( m_pPipesPerThread[ priority ], m_NumThreads, ENKI_FILE_AND_LINE ); + m_pPipesPerThread[ priority ] = NULL; + DeleteArray( m_pPinnedTaskListPerThread[ priority ], m_NumThreads, ENKI_FILE_AND_LINE ); + m_pPinnedTaskListPerThread[ priority ] = NULL; + } + m_NumThreads = 0; + } +} + +bool TaskScheduler::TryRunTask( uint32_t threadNum_, uint32_t& hintPipeToCheck_io_ ) +{ + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + if( TryRunTask( threadNum_, priority, hintPipeToCheck_io_ ) ) + { + return true; + } + } + return false; +} + +static inline uint32_t RotateLeft( uint32_t value, int32_t count ) +{ + return ( value << count ) | ( value >> ( 32 - count )); +} +/* xxHash variant based on documentation on + https://github.com/Cyan4973/xxHash/blob/eec5700f4d62113b47ee548edbc4746f61ffb098/doc/xxhash_spec.md + + Copyright (c) Yann Collet + + Permission is granted to copy and distribute this document for any purpose and without charge, including translations into other languages and incorporation into compilations, provided that the copyright notice and this notice are preserved, and that any substantive changes or deletions from the original are clearly marked. Distribution of this document is unlimited. +*/ +static inline uint32_t Hash32( uint32_t in_ ) +{ + static const uint32_t PRIME32_1 = 2654435761U; // 0b10011110001101110111100110110001 + static const uint32_t PRIME32_2 = 2246822519U; // 0b10000101111010111100101001110111 + static const uint32_t PRIME32_3 = 3266489917U; // 0b11000010101100101010111000111101 + static const uint32_t PRIME32_4 = 668265263U; // 0b00100111110101001110101100101111 + static const uint32_t PRIME32_5 = 374761393U; // 0b00010110010101100110011110110001 + static const uint32_t SEED = 0; // can configure seed if needed + + // simple hash of nodes, does not check if nodePool is compressed or not. + uint32_t acc = SEED + PRIME32_5; + + // add node types to map, and also ensure that fully empty nodes are well distributed by hashing the pointer. + acc += in_; + acc = acc ^ (acc >> 15); + acc = acc * PRIME32_2; + acc = acc ^ (acc >> 13); + acc = acc * PRIME32_3; + acc = acc ^ (acc >> 16); + return acc; +} + +bool TaskScheduler::TryRunTask( uint32_t threadNum_, uint32_t priority_, uint32_t& hintPipeToCheck_io_ ) +{ + // Run any tasks for this thread + RunPinnedTasks( threadNum_, priority_ ); + + // check for tasks + SubTaskSet subTask; + bool bHaveTask = m_pPipesPerThread[ priority_ ][ threadNum_ ].WriterTryReadFront( &subTask ); + + uint32_t threadToCheckStart = hintPipeToCheck_io_ % m_NumThreads; + uint32_t threadToCheck = threadToCheckStart; + uint32_t checkCount = 0; + if( !bHaveTask ) + { + bHaveTask = m_pPipesPerThread[ priority_ ][ threadToCheck ].ReaderTryReadBack( &subTask ); + if( !bHaveTask ) + { + // To prevent many threads checking the same task pipe for work we pseudorandomly distribute + // the starting thread which we start checking for tasks to run + uint32_t& rndSeed = m_pThreadDataStore[threadNum_].rndSeed; + ++rndSeed; + uint32_t threadToCheckOffset = Hash32( rndSeed * threadNum_ ); + while( !bHaveTask && checkCount < m_NumThreads ) + { + threadToCheck = ( threadToCheckOffset + checkCount ) % m_NumThreads; + if( threadToCheck != threadNum_ && threadToCheckOffset != threadToCheckStart ) + { + bHaveTask = m_pPipesPerThread[ priority_ ][ threadToCheck ].ReaderTryReadBack( &subTask ); + } + ++checkCount; + } + } + } + + if( bHaveTask ) + { + // update hint, will preserve value unless actually got task from another thread. + hintPipeToCheck_io_ = threadToCheck; + + uint32_t partitionSize = subTask.partition.end - subTask.partition.start; + if( subTask.pTask->m_RangeToRun < partitionSize ) + { + SubTaskSet taskToRun = SplitTask( subTask, subTask.pTask->m_RangeToRun ); + uint32_t rangeToSplit = subTask.pTask->m_RangeToRun; + if( threadNum_ != threadToCheck ) + { + // task was stolen from another thread + // in order to ensure other threads can get enough work we need to split into larger ranges + // these larger splits are then stolen and split themselves + // otherwise other threads must keep stealing from this thread, which may stall when pipe is full + rangeToSplit = std::max( rangeToSplit, (subTask.partition.end - subTask.partition.start) / gc_MaxStolenPartitions ); + } + SplitAndAddTask( threadNum_, subTask, rangeToSplit ); + taskToRun.pTask->ExecuteRange( taskToRun.partition, threadNum_ ); + int prevCount = taskToRun.pTask->m_RunningCount.fetch_sub(1,std::memory_order_acq_rel ); + if( gc_TaskStartCount == prevCount ) + { + TaskComplete( taskToRun.pTask, true, threadNum_ ); + } + } + else + { + // the task has already been divided up by AddTaskSetToPipe, so just run it + subTask.pTask->ExecuteRange( subTask.partition, threadNum_ ); + int prevCount = subTask.pTask->m_RunningCount.fetch_sub(1,std::memory_order_acq_rel ); + if( gc_TaskStartCount == prevCount ) + { + TaskComplete( subTask.pTask, true, threadNum_ ); + } + } + } + + return bHaveTask; + +} + +void TaskScheduler::TaskComplete( ICompletable* pTask_, bool bWakeThreads_, uint32_t threadNum_ ) +{ + // It must be impossible for a thread to enter the sleeping wait prior to the load of m_WaitingForTaskCount + // in this function, so we introduce a gc_TaskAlmostCompleteCount to prevent this. + ENKI_ASSERT( gc_TaskAlmostCompleteCount == pTask_->m_RunningCount.load( std::memory_order_acquire ) ); + bool bCallWakeThreads = bWakeThreads_ && pTask_->m_WaitingForTaskCount.load( std::memory_order_acquire ); + + Dependency* pDependent = pTask_->m_pDependents; + + // Do not access pTask_ below this line unless we have dependencies. + pTask_->m_RunningCount.store( 0, std::memory_order_release ); + + if( bCallWakeThreads ) + { + WakeThreadsForTaskCompletion(); + } + + while( pDependent ) + { + // access pTaskToRunOnCompletion member data before incrementing m_DependenciesCompletedCount so + // they do not get deleted when another thread completes the pTaskToRunOnCompletion + int32_t dependenciesCount = pDependent->pTaskToRunOnCompletion->m_DependenciesCount; + // get temp copy of pDependent so OnDependenciesComplete can delete task if needed. + Dependency* pDependentCurr = pDependent; + pDependent = pDependent->pNext; + int32_t prevDeps = pDependentCurr->pTaskToRunOnCompletion->m_DependenciesCompletedCount.fetch_add( 1, std::memory_order_release ); + ENKI_ASSERT( prevDeps < dependenciesCount ); + if( dependenciesCount == ( prevDeps + 1 ) ) + { + // reset dependencies + // only safe to access pDependentCurr here after above fetch_add because this is the thread + // which calls OnDependenciesComplete after store with memory_order_release + pDependentCurr->pTaskToRunOnCompletion->m_DependenciesCompletedCount.store( + 0, + std::memory_order_release ); + pDependentCurr->pTaskToRunOnCompletion->OnDependenciesComplete( this, threadNum_ ); + } + } +} + +bool TaskScheduler::HaveTasks( uint32_t threadNum_ ) +{ + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + for( uint32_t thread = 0; thread < m_NumThreads; ++thread ) + { + if( !m_pPipesPerThread[ priority ][ thread ].IsPipeEmpty() ) + { + return true; + } + } + if( !m_pPinnedTaskListPerThread[ priority ][ threadNum_ ].IsListEmpty() ) + { + return true; + } + } + return false; +} + +void TaskScheduler::WaitForNewTasks( uint32_t threadNum_ ) +{ + // We don't want to suspend this thread if there are task threads + // with pinned tasks suspended, as it could result in this thread + // being unsuspended and not the thread with pinned tasks + if( WakeSuspendedThreadsWithPinnedTasks( threadNum_ ) ) + { + return; + } + + // We increment the number of threads waiting here in order + // to ensure that the check for tasks occurs after the increment + // to prevent a task being added after a check, then the thread waiting. + // This will occasionally result in threads being mistakenly awoken, + // but they will then go back to sleep. + m_NumThreadsWaitingForNewTasks.fetch_add( 1, std::memory_order_acquire ); + ThreadState prevThreadState = m_pThreadDataStore[threadNum_].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum_].threadState.store( ENKI_THREAD_STATE_WAIT_NEW_TASKS, std::memory_order_seq_cst ); + + if( HaveTasks( threadNum_ ) ) + { + m_NumThreadsWaitingForNewTasks.fetch_sub( 1, std::memory_order_release ); + } + else + { + SafeCallback( m_Config.profilerCallbacks.waitForNewTaskSuspendStart, threadNum_ ); + SemaphoreWait( *m_pNewTaskSemaphore ); + SafeCallback( m_Config.profilerCallbacks.waitForNewTaskSuspendStop, threadNum_ ); + } + + m_pThreadDataStore[threadNum_].threadState.store( prevThreadState, std::memory_order_release ); +} + +void TaskScheduler::WaitForTaskCompletion( const ICompletable* pCompletable_, uint32_t threadNum_ ) +{ + // We don't want to suspend this thread if there are task threads + // with pinned tasks suspended, as the completable could be a pinned task + // or it could be waiting on one. + if( WakeSuspendedThreadsWithPinnedTasks( threadNum_ ) ) + { + return; + } + + m_NumThreadsWaitingForTaskCompletion.fetch_add( 1, std::memory_order_acq_rel ); + pCompletable_->m_WaitingForTaskCount.fetch_add( 1, std::memory_order_acq_rel ); + ThreadState prevThreadState = m_pThreadDataStore[threadNum_].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum_].threadState.store( ENKI_THREAD_STATE_WAIT_TASK_COMPLETION, std::memory_order_seq_cst ); + + // do not wait on semaphore if task in gc_TaskAlmostCompleteCount state. + if( gc_TaskAlmostCompleteCount >= pCompletable_->m_RunningCount.load( std::memory_order_acquire ) || HaveTasks( threadNum_ ) ) + { + m_NumThreadsWaitingForTaskCompletion.fetch_sub( 1, std::memory_order_acq_rel ); + } + else + { + SafeCallback( m_Config.profilerCallbacks.waitForTaskCompleteSuspendStart, threadNum_ ); + std::atomic_thread_fence(std::memory_order_acquire); + + SemaphoreWait( *m_pTaskCompleteSemaphore ); + if( !pCompletable_->GetIsComplete() ) + { + // This thread which may not the one which was supposed to be awoken + WakeThreadsForTaskCompletion(); + } + SafeCallback( m_Config.profilerCallbacks.waitForTaskCompleteSuspendStop, threadNum_ ); + } + + m_pThreadDataStore[threadNum_].threadState.store( prevThreadState, std::memory_order_release ); + pCompletable_->m_WaitingForTaskCount.fetch_sub( 1, std::memory_order_acq_rel ); +} + +void TaskScheduler::WakeThreadsForNewTasks() +{ + int32_t waiting = m_NumThreadsWaitingForNewTasks.load( std::memory_order_relaxed ); + while( waiting > 0 && !m_NumThreadsWaitingForNewTasks.compare_exchange_weak(waiting, 0, std::memory_order_release, std::memory_order_relaxed ) ) {} + + if( waiting > 0 ) + { + SemaphoreSignal( *m_pNewTaskSemaphore, waiting ); + } + + // We also wake tasks waiting for completion as they can run tasks + WakeThreadsForTaskCompletion(); +} + +void TaskScheduler::WakeThreadsForTaskCompletion() +{ + // m_NumThreadsWaitingForTaskCompletion can go negative as this indicates that + // we signalled more threads than the number which ended up waiting + int32_t waiting = m_NumThreadsWaitingForTaskCompletion.load( std::memory_order_relaxed ); + while( waiting > 0 && !m_NumThreadsWaitingForTaskCompletion.compare_exchange_weak(waiting, 0, std::memory_order_release, std::memory_order_relaxed ) ) {} + + if( waiting > 0 ) + { + SemaphoreSignal( *m_pTaskCompleteSemaphore, waiting ); + } +} + +bool TaskScheduler::WakeSuspendedThreadsWithPinnedTasks( uint32_t threadNum_ ) +{ + for( uint32_t t = 1; t < m_NumThreads; ++t ) + { + // distribute thread checks more evenly by starting at our thread number rather than 0. + uint32_t thread = ( threadNum_ + t ) % m_NumThreads; + + ThreadState state = m_pThreadDataStore[ thread ].threadState.load( std::memory_order_acquire ); + + ENKI_ASSERT( state != ENKI_THREAD_STATE_NONE ); + + if( state == ENKI_THREAD_STATE_WAIT_NEW_TASKS || state == ENKI_THREAD_STATE_WAIT_TASK_COMPLETION ) + { + // thread is suspended, check if it has pinned tasks + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + if( !m_pPinnedTaskListPerThread[ priority ][ thread ].IsListEmpty() ) + { + WakeThreadsForNewTasks(); + return true; + } + } + } + } + return false; +} + +void TaskScheduler::SplitAndAddTask( uint32_t threadNum_, SubTaskSet subTask_, uint32_t rangeToSplit_ ) +{ + int32_t numAdded = 0; + int32_t numNewTasksSinceNotification = 0; + int32_t numRun = 0; + + int32_t upperBoundNumToAdd = 2 + (int32_t)( ( subTask_.partition.end - subTask_.partition.start ) / rangeToSplit_ ); + + // ensure that an artificial completion is not registered whilst adding tasks by incrementing count + subTask_.pTask->m_RunningCount.fetch_add( upperBoundNumToAdd, std::memory_order_acquire ); + while( subTask_.partition.start != subTask_.partition.end ) + { + SubTaskSet taskToAdd = SplitTask( subTask_, rangeToSplit_ ); + + // add the partition to the pipe + ++numAdded; ++numNewTasksSinceNotification; + if( !m_pPipesPerThread[ subTask_.pTask->m_Priority ][ threadNum_ ].WriterTryWriteFront( taskToAdd ) ) + { + --numAdded; // we were unable to add the task + if( numNewTasksSinceNotification > 1 ) + { + WakeThreadsForNewTasks(); + } + numNewTasksSinceNotification = 0; + // alter range to run the appropriate fraction + if( taskToAdd.pTask->m_RangeToRun < taskToAdd.partition.end - taskToAdd.partition.start ) + { + taskToAdd.partition.end = taskToAdd.partition.start + taskToAdd.pTask->m_RangeToRun; + ENKI_ASSERT( taskToAdd.partition.end <= taskToAdd.pTask->m_SetSize ); + subTask_.partition.start = taskToAdd.partition.end; + } + taskToAdd.pTask->ExecuteRange( taskToAdd.partition, threadNum_ ); + ++numRun; + } + } + int32_t countToRemove = upperBoundNumToAdd - numAdded; + ENKI_ASSERT( countToRemove > 0 ); + int prevCount = subTask_.pTask->m_RunningCount.fetch_sub( countToRemove, std::memory_order_acq_rel ); + if( countToRemove-1 + gc_TaskStartCount == prevCount ) + { + TaskComplete( subTask_.pTask, false, threadNum_ ); + } + + // WakeThreadsForNewTasks also calls WakeThreadsForTaskCompletion() so do not need to do so above + WakeThreadsForNewTasks(); +} + +TaskSchedulerConfig TaskScheduler::GetConfig() const +{ + return m_Config; +} + +void TaskScheduler::AddTaskSetToPipeInt( ITaskSet* pTaskSet_, uint32_t threadNum_ ) +{ + ENKI_ASSERT( pTaskSet_->m_RunningCount == gc_TaskStartCount ); + ThreadState prevThreadState = m_pThreadDataStore[threadNum_].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum_].threadState.store( ENKI_THREAD_STATE_RUNNING, std::memory_order_relaxed ); + std::atomic_thread_fence(std::memory_order_acquire); + + + // divide task up and add to pipe + pTaskSet_->m_RangeToRun = pTaskSet_->m_SetSize / m_NumPartitions; + pTaskSet_->m_RangeToRun = std::max( pTaskSet_->m_RangeToRun, pTaskSet_->m_MinRange ); + // Note: if m_SetSize is < m_RangeToRun this will be handled by SplitTask and so does not need to be handled here + + uint32_t rangeToSplit = pTaskSet_->m_SetSize / m_NumInitialPartitions; + rangeToSplit = std::max( rangeToSplit, pTaskSet_->m_MinRange ); + + SubTaskSet subTask; + subTask.pTask = pTaskSet_; + subTask.partition.start = 0; + subTask.partition.end = pTaskSet_->m_SetSize; + SplitAndAddTask( threadNum_, subTask, rangeToSplit ); + int prevCount = pTaskSet_->m_RunningCount.fetch_sub(1, std::memory_order_acq_rel ); + if( gc_TaskStartCount == prevCount ) + { + TaskComplete( pTaskSet_, true, threadNum_ ); + } + + m_pThreadDataStore[threadNum_].threadState.store( prevThreadState, std::memory_order_release ); +} + +void TaskScheduler::AddTaskSetToPipe( ITaskSet* pTaskSet_ ) +{ + ENKI_ASSERT( pTaskSet_->m_RunningCount == 0 ); + InitDependencies( pTaskSet_ ); + pTaskSet_->m_RunningCount.store( gc_TaskStartCount, std::memory_order_relaxed ); + AddTaskSetToPipeInt( pTaskSet_, gtl_threadNum ); +} + +void TaskScheduler::AddPinnedTaskInt( IPinnedTask* pTask_ ) +{ + ENKI_ASSERT( pTask_->m_RunningCount == gc_TaskStartCount ); + m_pPinnedTaskListPerThread[ pTask_->m_Priority ][ pTask_->threadNum ].WriterWriteFront( pTask_ ); + + ThreadState statePinnedTaskThread = m_pThreadDataStore[ pTask_->threadNum ].threadState.load( std::memory_order_acquire ); + if( statePinnedTaskThread == ENKI_THREAD_STATE_WAIT_NEW_PINNED_TASKS ) + { + SemaphoreSignal( *m_pThreadDataStore[ pTask_->threadNum ].pWaitNewPinnedTaskSemaphore, 1 ); + } + else + { + WakeThreadsForNewTasks(); + } +} + +void TaskScheduler::AddPinnedTask( IPinnedTask* pTask_ ) +{ + ENKI_ASSERT( pTask_->m_RunningCount == 0 ); + InitDependencies( pTask_ ); + pTask_->m_RunningCount = gc_TaskStartCount; + AddPinnedTaskInt( pTask_ ); +} + +void TaskScheduler::InitDependencies( ICompletable* pCompletable_ ) +{ + // go through any dependencies and set their running count so they show as not complete + // and increment dependency count + if( pCompletable_->m_RunningCount.load( std::memory_order_relaxed ) ) + { + // already initialized + return; + } + Dependency* pDependent = pCompletable_->m_pDependents; + while( pDependent ) + { + InitDependencies( pDependent->pTaskToRunOnCompletion ); + pDependent->pTaskToRunOnCompletion->m_RunningCount.store( gc_TaskStartCount, std::memory_order_relaxed ); + pDependent = pDependent->pNext; + } +} + + +void TaskScheduler::RunPinnedTasks() +{ + ENKI_ASSERT( gtl_threadNum != enki::NO_THREAD_NUM ); + uint32_t threadNum = gtl_threadNum; + ThreadState prevThreadState = m_pThreadDataStore[threadNum].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum].threadState.store( ENKI_THREAD_STATE_RUNNING, std::memory_order_relaxed ); + std::atomic_thread_fence(std::memory_order_acquire); + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + RunPinnedTasks( threadNum, priority ); + } + m_pThreadDataStore[threadNum].threadState.store( prevThreadState, std::memory_order_release ); +} + +void TaskScheduler::RunPinnedTasks( uint32_t threadNum_, uint32_t priority_ ) +{ + IPinnedTask* pPinnedTaskSet = NULL; + do + { + pPinnedTaskSet = m_pPinnedTaskListPerThread[ priority_ ][ threadNum_ ].ReaderReadBack(); + if( pPinnedTaskSet ) + { + pPinnedTaskSet->Execute(); + pPinnedTaskSet->m_RunningCount.fetch_sub(1,std::memory_order_acq_rel); + TaskComplete( pPinnedTaskSet, true, threadNum_ ); + } + } while( pPinnedTaskSet ); +} + +void TaskScheduler::WaitforTask( const ICompletable* pCompletable_, enki::TaskPriority priorityOfLowestToRun_ ) +{ + ENKI_ASSERT( gtl_threadNum != enki::NO_THREAD_NUM ); + uint32_t threadNum = gtl_threadNum; + uint32_t hintPipeToCheck_io = threadNum + 1; // does not need to be clamped. + + // waiting for a task is equivalent to 'running' for thread state purpose as we may run tasks whilst waiting + ThreadState prevThreadState = m_pThreadDataStore[threadNum].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum].threadState.store( ENKI_THREAD_STATE_RUNNING, std::memory_order_relaxed ); + std::atomic_thread_fence(std::memory_order_acquire); + + + if( pCompletable_ && !pCompletable_->GetIsComplete() ) + { + SafeCallback( m_Config.profilerCallbacks.waitForTaskCompleteStart, threadNum ); + // We need to ensure that the task we're waiting on can complete even if we're the only thread, + // so we clamp the priorityOfLowestToRun_ to no smaller than the task we're waiting for + priorityOfLowestToRun_ = std::max( priorityOfLowestToRun_, pCompletable_->m_Priority ); + uint32_t spinCount = 0; + while( !pCompletable_->GetIsComplete() && GetIsRunningInt() ) + { + ++spinCount; + for( int priority = 0; priority <= priorityOfLowestToRun_; ++priority ) + { + if( TryRunTask( threadNum, priority, hintPipeToCheck_io ) ) + { + spinCount = 0; // reset spin as ran a task + break; + } + } + if( spinCount > gc_SpinCount ) + { + WaitForTaskCompletion( pCompletable_, threadNum ); + spinCount = 0; + } + else + { + uint32_t spinBackoffCount = spinCount * gc_SpinBackOffMultiplier; + SpinWait( spinBackoffCount ); + } + } + SafeCallback( m_Config.profilerCallbacks.waitForTaskCompleteStop, threadNum ); + } + else if( nullptr == pCompletable_ ) + { + for( int priority = 0; priority <= priorityOfLowestToRun_; ++priority ) + { + if( TryRunTask( threadNum, priority, hintPipeToCheck_io ) ) + { + break; + } + } + } + + m_pThreadDataStore[threadNum].threadState.store( prevThreadState, std::memory_order_release ); + +} + +class TaskSchedulerWaitTask : public IPinnedTask +{ + void Execute() override + { + // do nothing + } +}; + +void TaskScheduler::WaitforAll() +{ + ENKI_ASSERT( gtl_threadNum != enki::NO_THREAD_NUM ); + m_bWaitforAllCalled.store( true, std::memory_order_release ); + + bool bHaveTasks = true; + uint32_t ourThreadNum = gtl_threadNum; + uint32_t hintPipeToCheck_io = ourThreadNum + 1; // does not need to be clamped. + bool otherThreadsRunning = false; // account for this thread + uint32_t spinCount = 0; + TaskSchedulerWaitTask dummyWaitTask; + dummyWaitTask.threadNum = 0; + while( GetIsRunningInt() && ( bHaveTasks || otherThreadsRunning ) ) + { + bHaveTasks = TryRunTask( ourThreadNum, hintPipeToCheck_io ); + ++spinCount; + if( bHaveTasks ) + { + spinCount = 0; // reset spin as ran a task + } + if( spinCount > gc_SpinCount ) + { + // find a running thread and add a dummy wait task + int32_t countThreadsToCheck = m_NumThreads - 1; + bool bHaveThreadToWaitOn = false; + do + { + --countThreadsToCheck; + dummyWaitTask.threadNum = ( dummyWaitTask.threadNum + 1 ) % m_NumThreads; + + // We can only add a pinned task to wait on if we find an enki Task Thread which isn't this thread. + // Otherwise, we have to busy wait. + if( dummyWaitTask.threadNum != ourThreadNum && dummyWaitTask.threadNum > m_Config.numExternalTaskThreads ) + { + ThreadState state = m_pThreadDataStore[ dummyWaitTask.threadNum ].threadState.load( std::memory_order_acquire ); + if( state == ENKI_THREAD_STATE_RUNNING || state == ENKI_THREAD_STATE_WAIT_TASK_COMPLETION ) + { + bHaveThreadToWaitOn = true; + break; + } + } + } while( countThreadsToCheck ); + + if( bHaveThreadToWaitOn ) + { + ENKI_ASSERT( dummyWaitTask.threadNum != ourThreadNum ); + AddPinnedTask( &dummyWaitTask ); + WaitforTask( &dummyWaitTask ); + } + spinCount = 0; + } + else + { + uint32_t spinBackoffCount = spinCount * gc_SpinBackOffMultiplier; + SpinWait( spinBackoffCount ); + } + + // count threads running + otherThreadsRunning = false; + for(uint32_t thread = 0; thread < m_NumThreads && !otherThreadsRunning; ++thread ) + { + // ignore our thread + if( thread != ourThreadNum ) + { + switch( m_pThreadDataStore[thread].threadState.load( std::memory_order_acquire ) ) + { + case ENKI_THREAD_STATE_NONE: + ENKI_ASSERT(false); + break; + case ENKI_THREAD_STATE_NOT_LAUNCHED: + case ENKI_THREAD_STATE_RUNNING: + case ENKI_THREAD_STATE_WAIT_TASK_COMPLETION: + otherThreadsRunning = true; + break; + case ENKI_THREAD_STATE_WAIT_NEW_PINNED_TASKS: + otherThreadsRunning = true; + SemaphoreSignal( *m_pThreadDataStore[thread].pWaitNewPinnedTaskSemaphore, 1 ); + break; + case ENKI_THREAD_STATE_PRIMARY_REGISTERED: + case ENKI_THREAD_STATE_EXTERNAL_REGISTERED: + case ENKI_THREAD_STATE_EXTERNAL_UNREGISTERED: + case ENKI_THREAD_STATE_WAIT_NEW_TASKS: + case ENKI_THREAD_STATE_STOPPED: + break; + } + } + } + if( !otherThreadsRunning ) + { + // check there are no tasks + for(uint32_t thread = 0; thread < m_NumThreads && !otherThreadsRunning; ++thread ) + { + // ignore our thread + if( thread != ourThreadNum ) + { + otherThreadsRunning = HaveTasks( thread ); + } + } + } + } + + m_bWaitforAllCalled.store( false, std::memory_order_release ); +} + +void TaskScheduler::WaitforAllAndShutdown() +{ + m_bWaitforAllCalled.store( true, std::memory_order_release ); + m_bShutdownRequested.store( true, std::memory_order_release ); + if( m_bHaveThreads ) + { + WaitforAll(); + StopThreads(true); + } +} + +void TaskScheduler::ShutdownNow() +{ + m_bWaitforAllCalled.store( true, std::memory_order_release ); + m_bShutdownRequested.store( true, std::memory_order_release ); + if( m_bHaveThreads ) + { + StopThreads(true); + } +} + +void TaskScheduler::WaitForNewPinnedTasks() +{ + ENKI_ASSERT( gtl_threadNum != enki::NO_THREAD_NUM ); + uint32_t threadNum = gtl_threadNum; + ThreadState prevThreadState = m_pThreadDataStore[threadNum].threadState.load( std::memory_order_relaxed ); + m_pThreadDataStore[threadNum].threadState.store( ENKI_THREAD_STATE_WAIT_NEW_PINNED_TASKS, std::memory_order_seq_cst ); + + // check if have tasks inside threadState change but before waiting + bool bHavePinnedTasks = false; + for( int priority = 0; priority < TASK_PRIORITY_NUM; ++priority ) + { + if( !m_pPinnedTaskListPerThread[ priority ][ threadNum ].IsListEmpty() ) + { + bHavePinnedTasks = true; + break; + } + } + + if( !bHavePinnedTasks ) + { + SafeCallback( m_Config.profilerCallbacks.waitForNewTaskSuspendStart, threadNum ); + SemaphoreWait( *m_pThreadDataStore[threadNum].pWaitNewPinnedTaskSemaphore ); + SafeCallback( m_Config.profilerCallbacks.waitForNewTaskSuspendStop, threadNum ); + } + + m_pThreadDataStore[threadNum].threadState.store( prevThreadState, std::memory_order_release ); +} + + +uint32_t TaskScheduler::GetNumTaskThreads() const +{ + return m_NumThreads; +} + + +uint32_t TaskScheduler::GetThreadNum() const +{ + return gtl_threadNum; +} + +template +T* TaskScheduler::NewArray( size_t num_, const char* file_, int line_ ) +{ + T* pRet = (T*)m_Config.customAllocator.alloc( alignof(T), num_*sizeof(T), m_Config.customAllocator.userData, file_, line_ ); + if( !std::is_trivial::value ) + { + T* pCurr = pRet; + for( size_t i = 0; i < num_; ++i ) + { + void* pBuffer = pCurr; + pCurr = new(pBuffer) T; + ++pCurr; + } + } + return pRet; +} + +template +void TaskScheduler::DeleteArray( T* p_, size_t num_, const char* file_, int line_ ) +{ + if( !std::is_trivially_destructible::value ) + { + size_t i = num_; + while(i) + { + p_[--i].~T(); + } + } + m_Config.customAllocator.free( p_, sizeof(T)*num_, m_Config.customAllocator.userData, file_, line_ ); +} + +template +T* TaskScheduler::New( const char* file_, int line_, Args&&... args_ ) +{ + T* pRet = this->Alloc( file_, line_ ); + return new(pRet) T( std::forward(args_)... ); +} + +template< typename T > +void TaskScheduler::Delete( T* p_, const char* file_, int line_ ) +{ + p_->~T(); + this->Free(p_, file_, line_ ); +} + +template< typename T > +T* TaskScheduler::Alloc( const char* file_, int line_ ) +{ + T* pRet = (T*)m_Config.customAllocator.alloc( alignof(T), sizeof(T), m_Config.customAllocator.userData, file_, line_ ); + return pRet; +} + +template< typename T > +void TaskScheduler::Free( T* p_, const char* file_, int line_ ) +{ + m_Config.customAllocator.free( p_, sizeof(T), m_Config.customAllocator.userData, file_, line_ ); +} + +TaskScheduler::TaskScheduler() + : m_pPipesPerThread() + , m_pPinnedTaskListPerThread() + , m_NumThreads(0) + , m_pThreadDataStore(NULL) + , m_pThreads(NULL) + , m_bRunning(false) + , m_NumInternalTaskThreadsRunning(0) + , m_NumThreadsWaitingForNewTasks(0) + , m_NumThreadsWaitingForTaskCompletion(0) + , m_NumPartitions(0) + , m_pNewTaskSemaphore(NULL) + , m_pTaskCompleteSemaphore(NULL) + , m_NumInitialPartitions(0) + , m_bHaveThreads(false) + , m_NumExternalTaskThreadsRegistered(0) +{ +} + +TaskScheduler::~TaskScheduler() +{ + StopThreads( true ); // Stops threads, waiting for them. +} + +void TaskScheduler::Initialize( uint32_t numThreadsTotal_ ) +{ + ENKI_ASSERT( numThreadsTotal_ >= 1 ); + StopThreads( true ); // Stops threads, waiting for them. + m_Config.numTaskThreadsToCreate = numThreadsTotal_ - 1; + m_Config.numExternalTaskThreads = 0; + StartThreads();} + +void TaskScheduler::Initialize( TaskSchedulerConfig config_ ) +{ + StopThreads( true ); // Stops threads, waiting for them. + m_Config = config_; + StartThreads(); +} + +void TaskScheduler::Initialize() +{ + Initialize( std::thread::hardware_concurrency() ); +} + +// Semaphore implementation +#ifdef _WIN32 + +#ifndef WIN32_LEAN_AND_MEAN +#define WIN32_LEAN_AND_MEAN +#endif +#ifndef NOMINMAX +#define NOMINMAX +#endif +#include + +namespace enki +{ + struct semaphoreid_t + { + HANDLE sem; + }; + + inline void SemaphoreCreate( semaphoreid_t& semaphoreid ) + { +#ifdef _XBOX_ONE + semaphoreid.sem = CreateSemaphoreExW( NULL, 0, MAXLONG, NULL, 0, SEMAPHORE_ALL_ACCESS ); +#else + semaphoreid.sem = CreateSemaphore( NULL, 0, MAXLONG, NULL ); +#endif + } + + inline void SemaphoreClose( semaphoreid_t& semaphoreid ) + { + CloseHandle( semaphoreid.sem ); + } + + inline void SemaphoreWait( semaphoreid_t& semaphoreid ) + { + DWORD retval = WaitForSingleObject( semaphoreid.sem, INFINITE ); + ENKI_ASSERT( retval != WAIT_FAILED ); + (void)retval; // only needed for ENKI_ASSERT + } + + inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting ) + { + if( countWaiting ) + { + ReleaseSemaphore( semaphoreid.sem, countWaiting, NULL ); + } + } +} +#elif defined(__MACH__) + + +// OS X does not have POSIX semaphores +// Mach semaphores can now only be created by the kernel +// Named semaphores work, but would require unique name construction to ensure +// they are isolated to this process. +// Dispatch semaphores appear to be the way other developers use OSX Semaphores, e.g. Boost +// However the API could change +// OSX below 10.6 does not support dispatch, but I do not have an earlier OSX version +// to test alternatives +#include + +namespace enki +{ + + struct semaphoreid_t + { + dispatch_semaphore_t sem; + }; + + inline void SemaphoreCreate( semaphoreid_t& semaphoreid ) + { + semaphoreid.sem = dispatch_semaphore_create(0); + } + + inline void SemaphoreClose( semaphoreid_t& semaphoreid ) + { + dispatch_release( semaphoreid.sem ); + } + + inline void SemaphoreWait( semaphoreid_t& semaphoreid ) + { + dispatch_semaphore_wait( semaphoreid.sem, DISPATCH_TIME_FOREVER ); + } + + inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting ) + { + while( countWaiting-- > 0 ) + { + dispatch_semaphore_signal( semaphoreid.sem ); + } + } +} + +#else // POSIX + +#include +#include + +namespace enki +{ + + struct semaphoreid_t + { + sem_t sem; + }; + + inline void SemaphoreCreate( semaphoreid_t& semaphoreid ) + { + int err = sem_init( &semaphoreid.sem, 0, 0 ); + ENKI_ASSERT( err == 0 ); + (void)err; + } + + inline void SemaphoreClose( semaphoreid_t& semaphoreid ) + { + sem_destroy( &semaphoreid.sem ); + } + + inline void SemaphoreWait( semaphoreid_t& semaphoreid ) + { + while( sem_wait( &semaphoreid.sem ) == -1 && errno == EINTR ) {} + } + + inline void SemaphoreSignal( semaphoreid_t& semaphoreid, int32_t countWaiting ) + { + while( countWaiting-- > 0 ) + { + sem_post( &semaphoreid.sem ); + } + } +} +#endif + +semaphoreid_t* TaskScheduler::SemaphoreNew() +{ + semaphoreid_t* pSemaphore = this->Alloc( ENKI_FILE_AND_LINE ); + SemaphoreCreate( *pSemaphore ); + return pSemaphore; +} + +void TaskScheduler::SemaphoreDelete( semaphoreid_t* pSemaphore_ ) +{ + SemaphoreClose( *pSemaphore_ ); + this->Free( pSemaphore_, ENKI_FILE_AND_LINE ); +} + +void TaskScheduler::SetCustomAllocator( CustomAllocator customAllocator_ ) +{ + m_Config.customAllocator = customAllocator_; +} + +Dependency::Dependency( const ICompletable* pDependencyTask_, ICompletable* pTaskToRunOnCompletion_ ) + : pTaskToRunOnCompletion( pTaskToRunOnCompletion_ ) + , pDependencyTask( pDependencyTask_ ) + , pNext( pDependencyTask->m_pDependents ) +{ + ENKI_ASSERT( pDependencyTask->GetIsComplete() ); + ENKI_ASSERT( pTaskToRunOnCompletion->GetIsComplete() ); + pDependencyTask->m_pDependents = this; + ++pTaskToRunOnCompletion->m_DependenciesCount; +} + +Dependency::Dependency( Dependency&& rhs_ ) noexcept +{ + pDependencyTask = rhs_.pDependencyTask; + pTaskToRunOnCompletion = rhs_.pTaskToRunOnCompletion; + pNext = rhs_.pNext; + if( rhs_.pDependencyTask ) + { + ENKI_ASSERT( rhs_.pTaskToRunOnCompletion ); + ENKI_ASSERT( rhs_.pDependencyTask->GetIsComplete() ); + ENKI_ASSERT( rhs_.pTaskToRunOnCompletion->GetIsComplete() ); + Dependency** ppDependent = &(pDependencyTask->m_pDependents); + while( *ppDependent ) + { + if( &rhs_ == *ppDependent ) + { + *ppDependent = this; + break; + } + ppDependent = &((*ppDependent)->pNext); + } + } +} + + +Dependency::~Dependency() +{ + ClearDependency(); +} + +void Dependency::SetDependency( const ICompletable* pDependencyTask_, ICompletable* pTaskToRunOnCompletion_ ) +{ + ClearDependency(); + ENKI_ASSERT( pDependencyTask_->GetIsComplete() ); + ENKI_ASSERT( pTaskToRunOnCompletion_->GetIsComplete() ); + pDependencyTask = pDependencyTask_; + pTaskToRunOnCompletion = pTaskToRunOnCompletion_; + pNext = pDependencyTask->m_pDependents; + pDependencyTask->m_pDependents = this; + ++pTaskToRunOnCompletion->m_DependenciesCount; +} + +void Dependency::ClearDependency() +{ + if( pDependencyTask ) + { + ENKI_ASSERT( pTaskToRunOnCompletion ); + ENKI_ASSERT( pDependencyTask->GetIsComplete() ); + ENKI_ASSERT( pTaskToRunOnCompletion->GetIsComplete() ); + ENKI_ASSERT( pTaskToRunOnCompletion->m_DependenciesCount > 0 ); + Dependency* pDependent = pDependencyTask->m_pDependents; + --pTaskToRunOnCompletion->m_DependenciesCount; + if( this == pDependent ) + { + pDependencyTask->m_pDependents = pDependent->pNext; + } + else + { + while( pDependent ) + { + Dependency* pPrev = pDependent; + pDependent = pDependent->pNext; + if( this == pDependent ) + { + pPrev->pNext = pDependent->pNext; + break; + } + } + } + } + pDependencyTask = NULL; + pDependencyTask = NULL; + pNext = NULL; +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.h b/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.h new file mode 100644 index 000000000000..9d1d962ff7f5 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/TaskScheduler.h @@ -0,0 +1,583 @@ +// Copyright (c) 2013 Doug Binks +// +// This software is provided 'as-is', without any express or implied +// warranty. In no event will the authors be held liable for any damages +// arising from the use of this software. +// +// Permission is granted to anyone to use this software for any purpose, +// including commercial applications, and to alter it and redistribute it +// freely, subject to the following restrictions: +// +// 1. The origin of this software must not be misrepresented; you must not +// claim that you wrote the original software. If you use this software +// in a product, an acknowledgement in the product documentation would be +// appreciated but is not required. +// 2. Altered source versions must be plainly marked as such, and must not be +// misrepresented as being the original software. +// 3. This notice may not be removed or altered from any source distribution. + +#pragma once + +#include +#include +#include +#include +#include + +// ENKITS_TASK_PRIORITIES_NUM can be set from 1 to 5. +// 1 corresponds to effectively no priorities. +#ifndef ENKITS_TASK_PRIORITIES_NUM + #define ENKITS_TASK_PRIORITIES_NUM 3 +#endif + +#ifndef ENKITS_API +#if defined(_WIN32) && defined(ENKITS_BUILD_DLL) + // Building enkiTS as a DLL + #define ENKITS_API __declspec(dllexport) +#elif defined(_WIN32) && defined(ENKITS_DLL) + // Using enkiTS as a DLL + #define ENKITS_API __declspec(dllimport) +#elif defined(__GNUC__) && defined(ENKITS_BUILD_DLL) + // Building enkiTS as a shared library + #define ENKITS_API __attribute__((visibility("default"))) +#else + #define ENKITS_API +#endif +#endif + +// Define ENKI_CUSTOM_ALLOC_FILE_AND_LINE (at project level) to get file and line report in custom allocators, +// this is default in Debug - to turn off define ENKI_CUSTOM_ALLOC_NO_FILE_AND_LINE +#ifndef ENKI_CUSTOM_ALLOC_FILE_AND_LINE +#if defined(_DEBUG ) && !defined(ENKI_CUSTOM_ALLOC_NO_FILE_AND_LINE) +#define ENKI_CUSTOM_ALLOC_FILE_AND_LINE +#endif +#endif + +#ifndef ENKI_ASSERT +#include +#define ENKI_ASSERT(x) assert(x) +#endif + +#if (!defined(_MSVC_LANG) && __cplusplus >= 201402L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 201402L) +#define ENKI_DEPRECATED [[deprecated]] +#else +#define ENKI_DEPRECATED +#endif + +namespace enki +{ + struct TaskSetPartition + { + uint32_t start; + uint32_t end; + }; + + class TaskScheduler; + class TaskPipe; + class PinnedTaskList; + class Dependency; + struct ThreadArgs; + struct ThreadDataStore; + struct SubTaskSet; + struct semaphoreid_t; + + static constexpr uint32_t NO_THREAD_NUM = 0xFFFFFFFF; + + ENKITS_API uint32_t GetNumHardwareThreads(); + + enum TaskPriority + { + TASK_PRIORITY_HIGH = 0, +#if ( ENKITS_TASK_PRIORITIES_NUM > 3 ) + TASK_PRIORITY_MED_HI, +#endif +#if ( ENKITS_TASK_PRIORITIES_NUM > 2 ) + TASK_PRIORITY_MED, +#endif +#if ( ENKITS_TASK_PRIORITIES_NUM > 4 ) + TASK_PRIORITY_MED_LO, +#endif +#if ( ENKITS_TASK_PRIORITIES_NUM > 1 ) + TASK_PRIORITY_LOW, +#endif + TASK_PRIORITY_NUM + }; + + // ICompletable is a base class used to check for completion. + // Can be used with dependencies to wait for their completion. + // Derive from ITaskSet or IPinnedTask for running parallel tasks. + class ICompletable + { + public: + bool GetIsComplete() const { + return 0 == m_RunningCount.load( std::memory_order_acquire ); + } + + virtual ~ICompletable(); + + // Dependency helpers, see Dependencies.cpp + void SetDependency( Dependency& dependency_, const ICompletable* pDependencyTask_ ); + template void SetDependenciesArr( D& dependencyArray_ , const T(&taskArray_)[SIZE] ); + template void SetDependenciesArr( D& dependencyArray_, std::initializer_list taskpList_ ); + template void SetDependenciesArr( D(&dependencyArray_)[SIZE], const T(&taskArray_)[SIZE] ); + template void SetDependenciesArr( D(&dependencyArray_)[SIZE], std::initializer_list taskpList_ ); + template void SetDependenciesVec( D& dependencyVec_, const T(&taskArray_)[SIZE] ); + template void SetDependenciesVec( D& dependencyVec_, std::initializer_list taskpList_ ); + + TaskPriority m_Priority = TASK_PRIORITY_HIGH; + protected: + // Deriving from an ICompletable and overriding OnDependenciesComplete is advanced use. + // If you do override OnDependenciesComplete() call: + // ICompletable::OnDependenciesComplete( pTaskScheduler_, threadNum_ ); + // in your implementation. + virtual void OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ); + private: + friend class TaskScheduler; + friend class Dependency; + std::atomic m_RunningCount = {0}; + std::atomic m_DependenciesCompletedCount = {0}; + int32_t m_DependenciesCount = 0; + mutable std::atomic m_WaitingForTaskCount = {0}; + mutable Dependency* m_pDependents = NULL; + }; + + // Subclass ITaskSet to create tasks. + // TaskSets can be re-used, but check completion first. + class ITaskSet : public ICompletable + { + public: + ITaskSet() = default; + ITaskSet( uint32_t setSize_ ) + : m_SetSize( setSize_ ) + {} + + ITaskSet( uint32_t setSize_, uint32_t minRange_ ) + : m_SetSize( setSize_ ) + , m_MinRange( minRange_ ) + , m_RangeToRun(minRange_) + {} + + // Execute range should be overloaded to process tasks. It will be called with a + // range_ where range.start >= 0; range.start < range.end; and range.end < m_SetSize; + // The range values should be mapped so that linearly processing them in order is cache friendly + // i.e. neighbouring values should be close together. + // threadnum_ should not be used for changing processing of data, its intended purpose + // is to allow per-thread data buckets for output. + virtual void ExecuteRange( TaskSetPartition range_, uint32_t threadnum_ ) = 0; + + // Set Size - usually the number of data items to be processed, see ExecuteRange. Defaults to 1 + uint32_t m_SetSize = 1; + + // Min Range - Minimum size of TaskSetPartition range when splitting a task set into partitions. + // Designed for reducing scheduling overhead by preventing set being + // divided up too small. Ranges passed to ExecuteRange will *not* be a multiple of this, + // only attempts to deliver range sizes larger than this most of the time. + // This should be set to a value which results in computation effort of at least 10k + // clock cycles to minimize task scheduler overhead. + // NOTE: The last partition will be smaller than m_MinRange if m_SetSize is not a multiple + // of m_MinRange. + // Also known as grain size in literature. + uint32_t m_MinRange = 1; + + private: + friend class TaskScheduler; + void OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ) final; + uint32_t m_RangeToRun = 1; + }; + + // Subclass IPinnedTask to create tasks which can be run on a given thread only. + class IPinnedTask : public ICompletable + { + public: + IPinnedTask() = default; + IPinnedTask( uint32_t threadNum_ ) : threadNum(threadNum_) {} // default is to run a task on main thread + + // IPinnedTask needs to be non-abstract for intrusive list functionality. + // Should never be called as is, should be overridden. + virtual void Execute() { ENKI_ASSERT(false); } + + uint32_t threadNum = 0; // thread to run this pinned task on + std::atomic pNext = {NULL}; + private: + void OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ) final; + }; + + // TaskSet - a utility task set for creating tasks based on std::function. + typedef std::function TaskSetFunction; + class TaskSet : public ITaskSet + { + public: + TaskSet() = default; + TaskSet( TaskSetFunction func_ ) : m_Function( std::move(func_) ) {} + TaskSet( uint32_t setSize_, TaskSetFunction func_ ) : ITaskSet( setSize_ ), m_Function( std::move(func_) ) {} + + void ExecuteRange( TaskSetPartition range_, uint32_t threadnum_ ) override { m_Function( range_, threadnum_ ); } + TaskSetFunction m_Function; + }; + + // LambdaPinnedTask - a utility pinned task for creating tasks based on std::func. + typedef std::function PinnedTaskFunction; + class LambdaPinnedTask : public IPinnedTask + { + public: + LambdaPinnedTask() = default; + LambdaPinnedTask( PinnedTaskFunction func_ ) : m_Function( std::move(func_) ) {} + LambdaPinnedTask( uint32_t threadNum_, PinnedTaskFunction func_ ) : IPinnedTask( threadNum_ ), m_Function( std::move(func_) ) {} + + void Execute() override { m_Function(); } + PinnedTaskFunction m_Function; + }; + + class Dependency + { + public: + Dependency() = default; + Dependency( const Dependency& ) = delete; + ENKITS_API Dependency( Dependency&& ) noexcept; + ENKITS_API Dependency( const ICompletable* pDependencyTask_, ICompletable* pTaskToRunOnCompletion_ ); + ENKITS_API ~Dependency(); + + ENKITS_API void SetDependency( const ICompletable* pDependencyTask_, ICompletable* pTaskToRunOnCompletion_ ); + ENKITS_API void ClearDependency(); + ICompletable* GetTaskToRunOnCompletion() { return pTaskToRunOnCompletion; } + const ICompletable* GetDependencyTask() { return pDependencyTask; } + private: + friend class TaskScheduler; friend class ICompletable; + ICompletable* pTaskToRunOnCompletion = NULL; + const ICompletable* pDependencyTask = NULL; + Dependency* pNext = NULL; + }; + + // TaskScheduler implements several callbacks intended for profilers + typedef void (*ProfilerCallbackFunc)( uint32_t threadnum_ ); + struct ProfilerCallbacks + { + ProfilerCallbackFunc threadStart; + ProfilerCallbackFunc threadStop; + ProfilerCallbackFunc waitForNewTaskSuspendStart; // thread suspended waiting for new tasks + ProfilerCallbackFunc waitForNewTaskSuspendStop; // thread unsuspended + ProfilerCallbackFunc waitForTaskCompleteStart; // thread waiting for task completion + ProfilerCallbackFunc waitForTaskCompleteStop; // thread stopped waiting + ProfilerCallbackFunc waitForTaskCompleteSuspendStart; // thread suspended waiting task completion + ProfilerCallbackFunc waitForTaskCompleteSuspendStop; // thread unsuspended + }; + + // Custom allocator, set in TaskSchedulerConfig. Also see ENKI_CUSTOM_ALLOC_FILE_AND_LINE for file_ and line_ + typedef void* (*AllocFunc)( size_t align_, size_t size_, void* userData_, const char* file_, int line_ ); + typedef void (*FreeFunc)( void* ptr_, size_t size_, void* userData_, const char* file_, int line_ ); + ENKITS_API void* DefaultAllocFunc( size_t align_, size_t size_, void* userData_, const char* file_, int line_ ); + ENKITS_API void DefaultFreeFunc( void* ptr_, size_t size_, void* userData_, const char* file_, int line_ ); + struct CustomAllocator + { + AllocFunc alloc = DefaultAllocFunc; + FreeFunc free = DefaultFreeFunc; + void* userData = nullptr; + }; + + // TaskSchedulerConfig - configuration struct for advanced Initialize + struct TaskSchedulerConfig + { + // numTaskThreadsToCreate - Number of tasking threads the task scheduler will create. Must be > 0. + // Defaults to GetNumHardwareThreads()-1 threads as thread which calls initialize is thread 0. + uint32_t numTaskThreadsToCreate = GetNumHardwareThreads()-1; + + // numExternalTaskThreads - Advanced use. Number of external threads which need to use TaskScheduler API. + // See TaskScheduler::RegisterExternalTaskThread() for usage. + // Defaults to 0. The thread used to initialize the TaskScheduler can also use the TaskScheduler API. + // Thus there are (numTaskThreadsToCreate + numExternalTaskThreads + 1) able to use the API, with this + // defaulting to the number of hardware threads available to the system. + uint32_t numExternalTaskThreads = 0; + + ProfilerCallbacks profilerCallbacks = {}; + + CustomAllocator customAllocator; + }; + + class TaskScheduler + { + public: + ENKITS_API TaskScheduler(); + ENKITS_API ~TaskScheduler(); + + // Call an Initialize function before adding tasks. + + // Initialize() will create GetNumHardwareThreads()-1 tasking threads, which is + // sufficient to fill the system when including the main thread. + // Initialize can be called multiple times - it will wait for completion + // before re-initializing. + ENKITS_API void Initialize(); + + // Initialize( numThreadsTotal_ ) + // will create numThreadsTotal_-1 threads, as thread 0 is + // the thread on which the initialize was called. + // numThreadsTotal_ must be > 0 + ENKITS_API void Initialize( uint32_t numThreadsTotal_ ); + + // Initialize with advanced TaskSchedulerConfig settings. See TaskSchedulerConfig. + ENKITS_API void Initialize( TaskSchedulerConfig config_ ); + + // Get config. Can be called before Initialize to get the defaults. + ENKITS_API TaskSchedulerConfig GetConfig() const; + + // while( !GetIsShutdownRequested() ) {} can be used in tasks which loop, to check if enkiTS has been requested to shutdown. + // If GetIsShutdownRequested() returns true should then exit. Not required for finite tasks + // Safe to use with WaitforAllAndShutdown() and ShutdownNow() where this will be set + // Not safe to use with WaitforAll(), use GetIsWaitforAllCalled() instead. + inline bool GetIsShutdownRequested() const { return m_bShutdownRequested.load( std::memory_order_acquire ); } + + // while( !GetIsWaitforAllCalled() ) {} can be used in tasks which loop, to check if WaitforAll() has been called. + // If GetIsWaitforAllCalled() returns false should then exit. Not required for finite tasks + // This is intended to be used with code which calls WaitforAll(). + // This is also set when the task manager is shutting down, so no need to have an additional check for GetIsShutdownRequested() + inline bool GetIsWaitforAllCalled() const { return m_bWaitforAllCalled.load( std::memory_order_acquire ); } + + // Adds the TaskSet to pipe and returns if the pipe is not full. + // If the pipe is full, pTaskSet is run. + // should only be called from main thread, or within a task + ENKITS_API void AddTaskSetToPipe( ITaskSet* pTaskSet_ ); + + // Thread 0 is main thread, otherwise use threadNum + // Pinned tasks can be added from any thread + ENKITS_API void AddPinnedTask( IPinnedTask* pTask_ ); + + // This function will run any IPinnedTask* for current thread, but not run other + // Main thread should call this or use a wait to ensure its tasks are run. + ENKITS_API void RunPinnedTasks(); + + // Runs the TaskSets in pipe until true == pTaskSet->GetIsComplete(); + // Should only be called from thread which created the task scheduler, or within a task. + // If called with 0 it will try to run tasks, and return if none are available. + // To run only a subset of tasks, set priorityOfLowestToRun_ to a high priority. + // Default is lowest priority available. + // Only wait for child tasks of the current task otherwise a deadlock could occur. + // WaitforTask will exit if ShutdownNow() is called even if pCompletable_ is not complete. + ENKITS_API void WaitforTask( const ICompletable* pCompletable_, enki::TaskPriority priorityOfLowestToRun_ = TaskPriority(TASK_PRIORITY_NUM - 1) ); + + // Waits for all task sets to complete - not guaranteed to work unless we know we + // are in a situation where tasks aren't being continuously added. + // If you are running tasks which loop, make sure to check GetIsWaitforAllCalled() and exit + // WaitforAll will exit if ShutdownNow() is called even if there are still tasks to run or currently running + ENKITS_API void WaitforAll(); + + // Waits for all task sets to complete and shutdown threads - not guaranteed to work unless we know we + // are in a situation where tasks aren't being continuously added. + // This function can be safely called even if TaskScheduler::Initialize() has not been called. + ENKITS_API void WaitforAllAndShutdown(); + + // Shutdown threads without waiting for all tasks to complete. + // Intended to be used to exit an application quickly. + // This function can be safely called even if TaskScheduler::Initialize() has not been called. + // This function will still wait for any running tasks to exit before the task threads exit. + // ShutdownNow will cause tasks which have been added to the scheduler but not completed + // to be in an undefined state in which should not be re-launched. + ENKITS_API void ShutdownNow(); + + // Waits for the current thread to receive a PinnedTask. + // Will not run any tasks - use with RunPinnedTasks(). + // Can be used with both ExternalTaskThreads or with an enkiTS tasking thread to create + // a thread which only runs pinned tasks. If enkiTS threads are used can create + // extra enkiTS task threads to handle non-blocking computation via normal tasks. + ENKITS_API void WaitForNewPinnedTasks(); + + // Returns the number of threads created for running tasks + number of external threads + // plus 1 to account for the thread used to initialize the task scheduler. + // Equivalent to config values: numTaskThreadsToCreate + numExternalTaskThreads + 1. + // It is guaranteed that GetThreadNum() < GetNumTaskThreads() + ENKITS_API uint32_t GetNumTaskThreads() const; + + // Returns the current task threadNum. + // Will return 0 for thread which initialized the task scheduler, + // and NO_THREAD_NUM for all other non-enkiTS threads which have not been registered ( see RegisterExternalTaskThread() ), + // and < GetNumTaskThreads() for all registered and internal enkiTS threads. + // It is guaranteed that GetThreadNum() < GetNumTaskThreads() unless it is NO_THREAD_NUM + ENKITS_API uint32_t GetThreadNum() const; + + // Call on a thread to register the thread to use the TaskScheduling API. + // This is implicitly done for the thread which initializes the TaskScheduler + // Intended for developers who have threads who need to call the TaskScheduler API + // Returns true if successful, false if not. + // Can only have numExternalTaskThreads registered at any one time, which must be set + // at initialization time. + ENKITS_API bool RegisterExternalTaskThread(); + + // As RegisterExternalTaskThread() but explicitly requests a given thread number. + // threadNumToRegister_ must be >= GetNumFirstExternalTaskThread() + // and < ( GetNumFirstExternalTaskThread() + numExternalTaskThreads ). + ENKITS_API bool RegisterExternalTaskThread( uint32_t threadNumToRegister_ ); + + // Call on a thread on which RegisterExternalTaskThread has been called to deregister that thread. + ENKITS_API void DeRegisterExternalTaskThread(); + + // Get the number of registered external task threads. + ENKITS_API uint32_t GetNumRegisteredExternalTaskThreads(); + + // Get the thread number of the first external task thread. This thread + // is not guaranteed to be registered, but threads are registered in order + // from GetNumFirstExternalTaskThread() up to ( GetNumFirstExternalTaskThread() + numExternalTaskThreads ) + // Note that if numExternalTaskThreads == 0 a for loop using this will be valid: + // for( uint32_t externalThreadNum = GetNumFirstExternalTaskThread(); + // externalThreadNum < ( GetNumFirstExternalTaskThread() + numExternalTaskThreads + // ++externalThreadNum ) { // do something with externalThreadNum } + inline static constexpr uint32_t GetNumFirstExternalTaskThread() { return 1; } + + // ------------- Start DEPRECATED Functions ------------- + // DEPRECATED: use GetIsShutdownRequested() instead of GetIsRunning() in external code + // while( GetIsRunning() ) {} can be used in tasks which loop, to check if enkiTS has been shutdown. + // If GetIsRunning() returns false should then exit. Not required for finite tasks. + ENKI_DEPRECATED inline bool GetIsRunning() const { return !GetIsShutdownRequested(); } + + // DEPRECATED - WaitforTaskSet, deprecated interface use WaitforTask. + ENKI_DEPRECATED inline void WaitforTaskSet( const ICompletable* pCompletable_ ) { WaitforTask( pCompletable_ ); } + + // DEPRECATED - GetProfilerCallbacks. Use TaskSchedulerConfig instead. + // Returns the ProfilerCallbacks structure so that it can be modified to + // set the callbacks. Should be set prior to initialization. + ENKI_DEPRECATED inline ProfilerCallbacks* GetProfilerCallbacks() { return &m_Config.profilerCallbacks; } + // ------------- End DEPRECATED Functions ------------- + + private: + friend class ICompletable; friend class ITaskSet; friend class IPinnedTask; + static void TaskingThreadFunction( const ThreadArgs& args_ ); + bool HaveTasks( uint32_t threadNum_ ); + void WaitForNewTasks( uint32_t threadNum_ ); + void WaitForTaskCompletion( const ICompletable* pCompletable_, uint32_t threadNum_ ); + void RunPinnedTasks( uint32_t threadNum_, uint32_t priority_ ); + bool TryRunTask( uint32_t threadNum_, uint32_t& hintPipeToCheck_io_ ); + bool TryRunTask( uint32_t threadNum_, uint32_t priority_, uint32_t& hintPipeToCheck_io_ ); + void StartThreads(); + void StopThreads( bool bWait_ ); + void SplitAndAddTask( uint32_t threadNum_, SubTaskSet subTask_, uint32_t rangeToSplit_ ); + void WakeThreadsForNewTasks(); + void WakeThreadsForTaskCompletion(); + bool WakeSuspendedThreadsWithPinnedTasks( uint32_t threadNum_ ); + void InitDependencies( ICompletable* pCompletable_ ); + inline bool GetIsRunningInt() const { return m_bRunning.load( std::memory_order_acquire ); } + + ENKITS_API void TaskComplete( ICompletable* pTask_, bool bWakeThreads_, uint32_t threadNum_ ); + ENKITS_API void AddTaskSetToPipeInt( ITaskSet* pTaskSet_, uint32_t threadNum_ ); + ENKITS_API void AddPinnedTaskInt( IPinnedTask* pTask_ ); + + template< typename T > T* NewArray( size_t num_, const char* file_, int line_ ); + template< typename T > void DeleteArray( T* p_, size_t num_, const char* file_, int line_ ); + template T* New( const char* file_, int line_, Args&&... args_ ); + template< typename T > void Delete( T* p_, const char* file_, int line_ ); + template< typename T > T* Alloc( const char* file_, int line_ ); + template< typename T > void Free( T* p_, const char* file_, int line_ ); + semaphoreid_t* SemaphoreNew(); + void SemaphoreDelete( semaphoreid_t* pSemaphore_ ); + + TaskPipe* m_pPipesPerThread[ TASK_PRIORITY_NUM ]; + PinnedTaskList* m_pPinnedTaskListPerThread[ TASK_PRIORITY_NUM ]; + + uint32_t m_NumThreads; + ThreadDataStore* m_pThreadDataStore; + std::thread* m_pThreads; + std::atomic m_bRunning; + std::atomic m_bShutdownRequested; + std::atomic m_bWaitforAllCalled; + std::atomic m_NumInternalTaskThreadsRunning; + std::atomic m_NumThreadsWaitingForNewTasks; + std::atomic m_NumThreadsWaitingForTaskCompletion; + uint32_t m_NumPartitions; + semaphoreid_t* m_pNewTaskSemaphore; + semaphoreid_t* m_pTaskCompleteSemaphore; + uint32_t m_NumInitialPartitions; + bool m_bHaveThreads; + TaskSchedulerConfig m_Config; + std::atomic m_NumExternalTaskThreadsRegistered; + + TaskScheduler( const TaskScheduler& nocopy_ ); + TaskScheduler& operator=( const TaskScheduler& nocopy_ ); + + protected: + void SetCustomAllocator( CustomAllocator customAllocator_ ); // for C interface + }; + + inline void ICompletable::OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ) + { + m_RunningCount.fetch_sub( 1, std::memory_order_acq_rel ); + pTaskScheduler_->TaskComplete( this, true, threadNum_ ); + } + + inline void ITaskSet::OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ) + { + pTaskScheduler_->AddTaskSetToPipeInt( this, threadNum_ ); + } + + inline void IPinnedTask::OnDependenciesComplete( TaskScheduler* pTaskScheduler_, uint32_t threadNum_ ) + { + (void)threadNum_; + pTaskScheduler_->AddPinnedTaskInt( this ); + } + + inline ICompletable::~ICompletable() + { + ENKI_ASSERT( GetIsComplete() ); // this task is still waiting to run + Dependency* pDependency = m_pDependents; + while( pDependency ) + { + Dependency* pNext = pDependency->pNext; + pDependency->pDependencyTask = NULL; + pDependency->pNext = NULL; + pDependency = pNext; + } + } + + inline void ICompletable::SetDependency( Dependency& dependency_, const ICompletable* pDependencyTask_ ) + { + ENKI_ASSERT( pDependencyTask_ != this ); + dependency_.SetDependency( pDependencyTask_, this ); + } + + template + void ICompletable::SetDependenciesArr( D& dependencyArray_ , const T(&taskArray_)[SIZE] ) { + static_assert( std::tuple_size::value >= SIZE, "Size of dependency array too small" ); + for( int i = 0; i < SIZE; ++i ) + { + dependencyArray_[i].SetDependency( &taskArray_[i], this ); + } + } + template + void ICompletable::SetDependenciesArr( D& dependencyArray_, std::initializer_list taskpList_ ) { + ENKI_ASSERT( std::tuple_size::value >= taskpList_.size() ); + int i = 0; + for( auto pTask : taskpList_ ) + { + dependencyArray_[i++].SetDependency( pTask, this ); + } + } + template + void ICompletable::SetDependenciesArr( D(&dependencyArray_)[SIZE], const T(&taskArray_)[SIZE] ) { + for( int i = 0; i < SIZE; ++i ) + { + dependencyArray_[i].SetDependency( &taskArray_[i], this ); + } + } + template + void ICompletable::SetDependenciesArr( D(&dependencyArray_)[SIZE], std::initializer_list taskpList_ ) { + ENKI_ASSERT( SIZE >= taskpList_.size() ); + int i = 0; + for( auto pTask : taskpList_ ) + { + dependencyArray_[i++].SetDependency( pTask, this ); + } + } + template + void ICompletable::SetDependenciesVec( D& dependencyVec_, const T(&taskArray_)[SIZE] ) { + dependencyVec_.resize( SIZE ); + for( int i = 0; i < SIZE; ++i ) + { + dependencyVec_[i].SetDependency( &taskArray_[i], this ); + } + } + + template + void ICompletable::SetDependenciesVec( D& dependencyVec_, std::initializer_list taskpList_ ) { + dependencyVec_.resize( taskpList_.size() ); + int i = 0; + for( auto pTask : taskpList_ ) + { + dependencyVec_[i++].SetDependency( pTask, this ); + } + } +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.c b/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.c new file mode 100644 index 000000000000..fdb5cee96a2b --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.c @@ -0,0 +1,557 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "benchmarks.h" + +#include "human.h" + +#include "box2d/box2d.h" + +#include +#include +#include + +#ifdef NDEBUG +#define BENCHMARK_DEBUG 0 +#else +#define BENCHMARK_DEBUG 1 +#endif + +void CreateJointGrid( b2WorldId worldId ) +{ + b2World_EnableSleeping( worldId, false ); + + int N = BENCHMARK_DEBUG ? 10 : 100; + + // Allocate to avoid huge stack usage + b2BodyId* bodies = malloc( N * N * sizeof( b2BodyId ) ); + int index = 0; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.filter.categoryBits = 2; + shapeDef.filter.maskBits = ~2u; + + b2Circle circle = { { 0.0f, 0.0f }, 0.4f }; + + b2RevoluteJointDef jd = b2DefaultRevoluteJointDef(); + b2BodyDef bodyDef = b2DefaultBodyDef(); + + for ( int k = 0; k < N; ++k ) + { + for ( int i = 0; i < N; ++i ) + { + float fk = (float)k; + float fi = (float)i; + + if ( k >= N / 2 - 3 && k <= N / 2 + 3 && i == 0 ) + { + bodyDef.type = b2_staticBody; + } + else + { + bodyDef.type = b2_dynamicBody; + } + + bodyDef.position = ( b2Vec2 ){ fk, -fi }; + + b2BodyId body = b2CreateBody( worldId, &bodyDef ); + + b2CreateCircleShape( body, &shapeDef, &circle ); + + if ( i > 0 ) + { + jd.bodyIdA = bodies[index - 1]; + jd.bodyIdB = body; + jd.localAnchorA = ( b2Vec2 ){ 0.0f, -0.5f }; + jd.localAnchorB = ( b2Vec2 ){ 0.0f, 0.5f }; + b2CreateRevoluteJoint( worldId, &jd ); + } + + if ( k > 0 ) + { + jd.bodyIdA = bodies[index - N]; + jd.bodyIdB = body; + jd.localAnchorA = ( b2Vec2 ){ 0.5f, 0.0f }; + jd.localAnchorB = ( b2Vec2 ){ -0.5f, 0.0f }; + b2CreateRevoluteJoint( worldId, &jd ); + } + + bodies[index++] = body; + } + } + + free( bodies ); +} + +void CreateLargePyramid( b2WorldId worldId ) +{ + b2World_EnableSleeping( worldId, false ); + + int baseCount = BENCHMARK_DEBUG ? 20 : 100; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = ( b2Vec2 ){ 0.0f, -1.0f }; + b2BodyId groundId = b2CreateBody( worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 100.0f, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + //bodyDef.enableSleep = false; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + + float h = 0.5f; + b2Polygon box = b2MakeSquare( h ); + + float shift = 1.0f * h; + + for ( int i = 0; i < baseCount; ++i ) + { + float y = ( 2.0f * i + 1.0f ) * shift; + + for ( int j = i; j < baseCount; ++j ) + { + float x = ( i + 1.0f ) * shift + 2.0f * ( j - i ) * shift - h * baseCount; + + bodyDef.position = ( b2Vec2 ){ x, y }; + + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } +} + +static void CreateSmallPyramid( b2WorldId worldId, int baseCount, float extent, float centerX, float baseY ) +{ + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Polygon box = b2MakeSquare( extent ); + + for ( int i = 0; i < baseCount; ++i ) + { + float y = ( 2.0f * i + 1.0f ) * extent + baseY; + + for ( int j = i; j < baseCount; ++j ) + { + float x = ( i + 1.0f ) * extent + 2.0f * ( j - i ) * extent + centerX - 0.5f; + bodyDef.position = ( b2Vec2 ){ x, y }; + + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } +} + +void CreateManyPyramids( b2WorldId worldId ) +{ + b2World_EnableSleeping( worldId, false ); + + int baseCount = 10; + float extent = 0.5f; + int rowCount = BENCHMARK_DEBUG ? 5 : 20; + int columnCount = BENCHMARK_DEBUG ? 5 : 20; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( worldId, &bodyDef ); + + float groundDeltaY = 2.0f * extent * ( baseCount + 1.0f ); + float groundWidth = 2.0f * extent * columnCount * ( baseCount + 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float groundY = 0.0f; + + for ( int i = 0; i < rowCount; ++i ) + { + b2Segment segment = { { -0.5f * 2.0f * groundWidth, groundY }, { 0.5f * 2.0f * groundWidth, groundY } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + groundY += groundDeltaY; + } + + float baseWidth = 2.0f * extent * baseCount; + float baseY = 0.0f; + + for ( int i = 0; i < rowCount; ++i ) + { + for ( int j = 0; j < columnCount; ++j ) + { + float centerX = -0.5f * groundWidth + j * ( baseWidth + 2.0f * extent ) + extent; + CreateSmallPyramid( worldId, baseCount, extent, centerX, baseY ); + } + + baseY += groundDeltaY; + } +} + +#ifdef NDEBUG +enum RainConstants +{ + RAIN_ROW_COUNT = 5, + RAIN_COLUMN_COUNT = 40, + RAIN_GROUP_SIZE = 5, +}; +#else +enum RainConstants +{ + RAIN_ROW_COUNT = 3, + RAIN_COLUMN_COUNT = 10, + RAIN_GROUP_SIZE = 2, +}; +#endif + +typedef struct Group +{ + Human humans[RAIN_GROUP_SIZE]; +} Group; + +typedef struct RainData +{ + Group groups[RAIN_ROW_COUNT * RAIN_COLUMN_COUNT]; + float gridSize; + int gridCount; + int columnCount; + int columnIndex; +} RainData; + +RainData g_rainData; + +void CreateRain( b2WorldId worldId ) +{ + memset( &g_rainData, 0, sizeof( g_rainData ) ); + + g_rainData.gridSize = 0.5f; + g_rainData.gridCount = BENCHMARK_DEBUG ? 200 : 500; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + float y = 0.0f; + float width = g_rainData.gridSize; + float height = g_rainData.gridSize; + + for ( int i = 0; i < RAIN_ROW_COUNT; ++i ) + { + float x = -0.5f * g_rainData.gridCount * g_rainData.gridSize; + for ( int j = 0; j <= g_rainData.gridCount; ++j ) + { + b2Polygon box = b2MakeOffsetBox( 0.5f * width, 0.5f * height, ( b2Vec2 ){ x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + //b2Segment segment = { { x - 0.5f * width, y }, { x + 0.5f * width, y } }; + //b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + x += g_rainData.gridSize; + } + + y += 45.0f; + } + } + + g_rainData.columnCount = 0; + g_rainData.columnIndex = 0; +} + +void CreateGroup( b2WorldId worldId, int rowIndex, int columnIndex ) +{ + assert( rowIndex < RAIN_ROW_COUNT && columnIndex < RAIN_COLUMN_COUNT ); + + int groupIndex = rowIndex * RAIN_COLUMN_COUNT + columnIndex; + + float span = g_rainData.gridCount * g_rainData.gridSize; + float groupDistance = 1.0f * span / RAIN_COLUMN_COUNT; + + b2Vec2 position; + position.x = -0.5f * span + groupDistance * ( columnIndex + 0.5f ); + position.y = 40.0f + 45.0f * rowIndex; + + float scale = 1.0f; + float jointFriction = 0.05f; + float jointHertz = 5.0f; + float jointDamping = 0.5f; + + for ( int i = 0; i < RAIN_GROUP_SIZE; ++i ) + { + Human* human = g_rainData.groups[groupIndex].humans + i; + CreateHuman( human, worldId, position, scale, jointFriction, jointHertz, jointDamping, i + 1, NULL, false ); + position.x += 0.5f; + } +} + +void DestroyGroup( int rowIndex, int columnIndex ) +{ + assert( rowIndex < RAIN_ROW_COUNT && columnIndex < RAIN_COLUMN_COUNT ); + + int groupIndex = rowIndex * RAIN_COLUMN_COUNT + columnIndex; + + for ( int i = 0; i < RAIN_GROUP_SIZE; ++i ) + { + DestroyHuman( g_rainData.groups[groupIndex].humans + i ); + } +} + +float StepRain( b2WorldId worldId, int stepCount ) +{ + int delay = BENCHMARK_DEBUG ? 0x1F : 0x7; + + if ( ( stepCount & delay ) == 0 ) + { + if ( g_rainData.columnCount < RAIN_COLUMN_COUNT ) + { + for ( int i = 0; i < RAIN_ROW_COUNT; ++i ) + { + CreateGroup( worldId, i, g_rainData.columnCount ); + } + + g_rainData.columnCount += 1; + } + else + { + for ( int i = 0; i < RAIN_ROW_COUNT; ++i ) + { + DestroyGroup( i, g_rainData.columnIndex ); + CreateGroup( worldId, i, g_rainData.columnIndex ); + } + + g_rainData.columnIndex = ( g_rainData.columnIndex + 1 ) % RAIN_COLUMN_COUNT; + } + } + + return 0.0f; +} + +#define SPINNER_POINT_COUNT 360 + +typedef struct +{ + b2JointId spinnerId; +} SpinnerData; + +SpinnerData g_spinnerData; + +void CreateSpinner( b2WorldId worldId ) +{ + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( worldId, &bodyDef ); + + b2Vec2 points[SPINNER_POINT_COUNT]; + + b2Rot q = b2MakeRot( -2.0f * B2_PI / SPINNER_POINT_COUNT ); + b2Vec2 p = { 40.0f, 0.0f }; + for ( int i = 0; i < SPINNER_POINT_COUNT; ++i ) + { + points[i] = ( b2Vec2 ){ p.x, p.y + 32.0f }; + p = b2RotateVector( q, p ); + } + + b2SurfaceMaterial material = {0}; + material.friction = 0.1f; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = SPINNER_POINT_COUNT; + chainDef.isLoop = true; + chainDef.materials = &material; + chainDef.materialCount = 1; + + b2CreateChain( groundId, &chainDef ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = ( b2Vec2 ){ 0.0, 12.0f }; + bodyDef.enableSleep = false; + + b2BodyId spinnerId = b2CreateBody( worldId, &bodyDef ); + + b2Polygon box = b2MakeRoundedBox( 0.4f, 20.0f, 0.2f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.0f; + b2CreatePolygonShape( spinnerId, &shapeDef, &box ); + + float motorSpeed = 5.0f; + float maxMotorTorque = 40000.0f; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = spinnerId; + jointDef.localAnchorA = bodyDef.position; + jointDef.enableMotor = true; + jointDef.motorSpeed = motorSpeed; + jointDef.maxMotorTorque = maxMotorTorque; + + g_spinnerData.spinnerId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + b2Capsule capsule = { { -0.25f, 0.0f }, { 0.25f, 0.0f }, 0.25f }; + b2Circle circle = { { 0.0f, 0.0f }, 0.35f }; + b2Polygon square = b2MakeSquare( 0.35f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + shapeDef.material.restitution = 0.1f; + shapeDef.density = 0.25f; + + int bodyCount = BENCHMARK_DEBUG ? 499 : 3038; + + float x = -24.0f, y = 2.0f; + for ( int i = 0; i < bodyCount; ++i ) + { + bodyDef.position = ( b2Vec2 ){ x, y }; + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + + int remainder = i % 3; + if ( remainder == 0 ) + { + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + } + else if ( remainder == 1 ) + { + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + else if ( remainder == 2 ) + { + b2CreatePolygonShape( bodyId, &shapeDef, &square ); + } + + x += 1.0f; + + if ( x > 24.0f ) + { + x = -24.0f; + y += 1.0f; + } + } +} + +float StepSpinner( b2WorldId worldId, int stepCount ) +{ + (void)worldId; + (void)stepCount; + + return b2RevoluteJoint_GetAngle(g_spinnerData.spinnerId); +} + +void CreateSmash( b2WorldId worldId ) +{ + b2World_SetGravity( worldId, b2Vec2_zero ); + + { + b2Polygon box = b2MakeBox( 4.0f, 4.0f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = ( b2Vec2 ){ -20.0f, 0.0f }; + bodyDef.linearVelocity = ( b2Vec2 ){ 40.0f, 0.0f }; + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 8.0f; + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + float d = 0.4f; + b2Polygon box = b2MakeSquare( 0.5f * d ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.isAwake = false; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + int columns = BENCHMARK_DEBUG ? 20 : 120; + int rows = BENCHMARK_DEBUG ? 10 : 80; + + for ( int i = 0; i < columns; ++i ) + { + for ( int j = 0; j < rows; ++j ) + { + bodyDef.position.x = i * d + 30.0f; + bodyDef.position.y = ( j - rows / 2.0f ) * d; + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } +} + +void CreateTumbler( b2WorldId worldId ) +{ + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( worldId, &bodyDef ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = ( b2Vec2 ){ 0.0f, 10.0f }; + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 50.0f; + + b2Polygon polygon; + polygon = b2MakeOffsetBox( 0.5f, 10.0f, ( b2Vec2 ){ 10.0f, 0.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 0.5f, 10.0f, ( b2Vec2 ){ -10.0f, 0.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 10.0f, 0.5f, ( b2Vec2 ){ 0.0f, 10.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 10.0f, 0.5f, ( b2Vec2 ){ 0.0f, -10.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + + float motorSpeed = 25.0f; + + b2RevoluteJointDef jd = b2DefaultRevoluteJointDef(); + jd.bodyIdA = groundId; + jd.bodyIdB = bodyId; + jd.localAnchorA = ( b2Vec2 ){ 0.0f, 10.0f }; + jd.localAnchorB = ( b2Vec2 ){ 0.0f, 0.0f }; + jd.referenceAngle = 0.0f; + jd.motorSpeed = ( B2_PI / 180.0f ) * motorSpeed; + jd.maxMotorTorque = 1e8f; + jd.enableMotor = true; + + b2CreateRevoluteJoint( worldId, &jd ); + } + + int gridCount = BENCHMARK_DEBUG ? 20 : 45; + + b2Polygon polygon = b2MakeBox( 0.125f, 0.125f ); + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float y = -0.2f * gridCount + 10.0f; + for ( int i = 0; i < gridCount; ++i ) + { + float x = -0.2f * gridCount; + + for ( int j = 0; j < gridCount; ++j ) + { + bodyDef.position = ( b2Vec2 ){ x, y }; + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + + x += 0.4f; + } + + y += 0.4f; + } +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.h b/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.h new file mode 100644 index 000000000000..7fc7a8e66bac --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/benchmarks.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT +#pragma once + +#include "box2d/id.h" + +// This allows benchmarks to be tested on the benchmark app and also visualized in the samples app + +#ifdef __cplusplus +extern "C" +{ +#endif + +void CreateJointGrid( b2WorldId worldId ); +void CreateLargePyramid( b2WorldId worldId ); +void CreateManyPyramids( b2WorldId worldId ); +void CreateRain( b2WorldId worldId ); +float StepRain( b2WorldId worldId, int stepCount ); +void CreateSpinner( b2WorldId worldId ); +float StepSpinner( b2WorldId worldId, int stepCount ); +void CreateSmash( b2WorldId worldId ); +void CreateTumbler( b2WorldId worldId ); + +#ifdef __cplusplus +} +#endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/car.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/car.cpp new file mode 100644 index 000000000000..ec70f97efe6b --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/car.cpp @@ -0,0 +1,296 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "car.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include + +Car::Car() +{ + m_chassisId = {}; + m_rearWheelId = {}; + m_frontWheelId = {}; + m_rearAxleId = {}; + m_frontAxleId = {}; + m_isSpawned = false; +} + +void Car::Spawn( b2WorldId worldId, b2Vec2 position, float scale, float hertz, float dampingRatio, float torque, void* userData ) +{ + assert( m_isSpawned == false ); + + assert( B2_IS_NULL( m_chassisId ) ); + assert( B2_IS_NULL( m_frontWheelId ) ); + assert( B2_IS_NULL( m_rearWheelId ) ); + + b2Vec2 vertices[6] = { + { -1.5f, -0.5f }, { 1.5f, -0.5f }, { 1.5f, 0.0f }, { 0.0f, 0.9f }, { -1.15f, 0.9f }, { -1.5f, 0.2f }, + }; + + for ( int i = 0; i < 6; ++i ) + { + vertices[i].x *= 0.85f * scale; + vertices[i].y *= 0.85f * scale; + } + + b2Hull hull = b2ComputeHull( vertices, 6 ); + b2Polygon chassis = b2MakePolygon( &hull, 0.15f * scale ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f / scale; + shapeDef.material.friction = 0.2f; + + b2Circle circle = { { 0.0f, 0.0f }, 0.4f * scale }; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Add( { 0.0f, 1.0f * scale }, position ); + m_chassisId = b2CreateBody( worldId, &bodyDef ); + b2CreatePolygonShape( m_chassisId, &shapeDef, &chassis ); + + shapeDef.density = 2.0f / scale; + shapeDef.material.friction = 1.5f; + shapeDef.material.rollingResistance = 0.1f; + + bodyDef.position = b2Add( { -1.0f * scale, 0.35f * scale }, position ); + bodyDef.allowFastRotation = true; + m_rearWheelId = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_rearWheelId, &shapeDef, &circle ); + + bodyDef.position = b2Add( { 1.0f * scale, 0.4f * scale }, position ); + bodyDef.allowFastRotation = true; + m_frontWheelId = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_frontWheelId, &shapeDef, &circle ); + + b2Vec2 axis = { 0.0f, 1.0f }; + b2Vec2 pivot = b2Body_GetPosition( m_rearWheelId ); + + // float throttle = 0.0f; + // float speed = 35.0f; + // float torque = 2.5f * scale; + // float hertz = 5.0f; + // float dampingRatio = 0.7f; + + b2WheelJointDef jointDef = b2DefaultWheelJointDef(); + + jointDef.bodyIdA = m_chassisId; + jointDef.bodyIdB = m_rearWheelId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = 0.0f; + jointDef.maxMotorTorque = torque; + jointDef.enableMotor = true; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.lowerTranslation = -0.25f * scale; + jointDef.upperTranslation = 0.25f * scale; + jointDef.enableLimit = true; + m_rearAxleId = b2CreateWheelJoint( worldId, &jointDef ); + + pivot = b2Body_GetPosition( m_frontWheelId ); + jointDef.bodyIdA = m_chassisId; + jointDef.bodyIdB = m_frontWheelId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = 0.0f; + jointDef.maxMotorTorque = torque; + jointDef.enableMotor = true; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.lowerTranslation = -0.25f * scale; + jointDef.upperTranslation = 0.25f * scale; + jointDef.enableLimit = true; + m_frontAxleId = b2CreateWheelJoint( worldId, &jointDef ); +} + +void Car::Despawn() +{ + assert( m_isSpawned == true ); + + b2DestroyJoint( m_rearAxleId ); + b2DestroyJoint( m_frontAxleId ); + b2DestroyBody( m_rearWheelId ); + b2DestroyBody( m_frontWheelId ); + b2DestroyBody( m_chassisId ); + + m_isSpawned = false; +} + +void Car::SetSpeed( float speed ) +{ + b2WheelJoint_SetMotorSpeed( m_rearAxleId, speed ); + b2WheelJoint_SetMotorSpeed( m_frontAxleId, speed ); + b2Joint_WakeBodies( m_rearAxleId ); +} + +void Car::SetTorque( float torque ) +{ + b2WheelJoint_SetMaxMotorTorque( m_rearAxleId, torque ); + b2WheelJoint_SetMaxMotorTorque( m_frontAxleId, torque ); +} + +void Car::SetHertz( float hertz ) +{ + b2WheelJoint_SetSpringHertz( m_rearAxleId, hertz ); + b2WheelJoint_SetSpringHertz( m_frontAxleId, hertz ); +} + +void Car::SetDampingRadio( float dampingRatio ) +{ + b2WheelJoint_SetSpringDampingRatio( m_rearAxleId, dampingRatio ); + b2WheelJoint_SetSpringDampingRatio( m_frontAxleId, dampingRatio ); +} + +Truck::Truck() +{ + m_chassisId = {}; + m_rearWheelId = {}; + m_frontWheelId = {}; + m_rearAxleId = {}; + m_frontAxleId = {}; + m_isSpawned = false; +} + +void Truck::Spawn( b2WorldId worldId, b2Vec2 position, float scale, float hertz, float dampingRatio, float torque, float density, + void* userData ) +{ + assert( m_isSpawned == false ); + + assert( B2_IS_NULL( m_chassisId ) ); + assert( B2_IS_NULL( m_frontWheelId ) ); + assert( B2_IS_NULL( m_rearWheelId ) ); + + // b2Vec2 vertices[6] = { + // { -1.5f, -0.5f }, { 1.5f, -0.5f }, { 1.5f, 0.0f }, { 0.0f, 0.9f }, { -1.15f, 0.9f }, { -1.5f, 0.2f }, + // }; + + b2Vec2 vertices[5] = { + { -0.65f, -0.4f }, { 1.5f, -0.4f }, { 1.5f, 0.0f }, { 0.0f, 0.9f }, { -0.65f, 0.9f }, + }; + + for ( int i = 0; i < 5; ++i ) + { + vertices[i].x *= 0.85f * scale; + vertices[i].y *= 0.85f * scale; + } + + b2Hull hull = b2ComputeHull( vertices, 5 ); + b2Polygon chassis = b2MakePolygon( &hull, 0.15f * scale ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = density; + shapeDef.material.friction = 0.2f; + shapeDef.material.customColor = b2_colorHotPink; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Add( { 0.0f, 1.0f * scale }, position ); + m_chassisId = b2CreateBody( worldId, &bodyDef ); + b2CreatePolygonShape( m_chassisId, &shapeDef, &chassis ); + + b2Polygon box = b2MakeOffsetBox( 1.25f * scale, 0.1f * scale, { -2.05f * scale, -0.275f * scale }, b2Rot_identity ); + box.radius = 0.1f * scale; + b2CreatePolygonShape( m_chassisId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 0.05f * scale, 0.35f * scale, { -3.25f * scale, 0.375f * scale }, b2Rot_identity ); + box.radius = 0.1f * scale; + b2CreatePolygonShape( m_chassisId, &shapeDef, &box ); + + shapeDef.density = 2.0f * density; + shapeDef.material.friction = 2.5f; + shapeDef.material.customColor = b2_colorSilver; + + b2Circle circle = { { 0.0f, 0.0f }, 0.4f * scale }; + bodyDef.position = b2Add( { -2.75f * scale, 0.3f * scale }, position ); + m_rearWheelId = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_rearWheelId, &shapeDef, &circle ); + + bodyDef.position = b2Add( { 0.8f * scale, 0.3f * scale }, position ); + m_frontWheelId = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_frontWheelId, &shapeDef, &circle ); + + b2Vec2 axis = { 0.0f, 1.0f }; + b2Vec2 pivot = b2Body_GetPosition( m_rearWheelId ); + + // float throttle = 0.0f; + // float speed = 35.0f; + // float torque = 2.5f * scale; + // float hertz = 5.0f; + // float dampingRatio = 0.7f; + + b2WheelJointDef jointDef = b2DefaultWheelJointDef(); + + jointDef.bodyIdA = m_chassisId; + jointDef.bodyIdB = m_rearWheelId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = 0.0f; + jointDef.maxMotorTorque = torque; + jointDef.enableMotor = true; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.lowerTranslation = -0.25f * scale; + jointDef.upperTranslation = 0.25f * scale; + jointDef.enableLimit = true; + m_rearAxleId = b2CreateWheelJoint( worldId, &jointDef ); + + pivot = b2Body_GetPosition( m_frontWheelId ); + jointDef.bodyIdA = m_chassisId; + jointDef.bodyIdB = m_frontWheelId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = 0.0f; + jointDef.maxMotorTorque = torque; + jointDef.enableMotor = true; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.lowerTranslation = -0.25f * scale; + jointDef.upperTranslation = 0.25f * scale; + jointDef.enableLimit = true; + m_frontAxleId = b2CreateWheelJoint( worldId, &jointDef ); +} + +void Truck::Despawn() +{ + assert( m_isSpawned == true ); + + b2DestroyJoint( m_rearAxleId ); + b2DestroyJoint( m_frontAxleId ); + b2DestroyBody( m_rearWheelId ); + b2DestroyBody( m_frontWheelId ); + b2DestroyBody( m_chassisId ); + + m_isSpawned = false; +} + +void Truck::SetSpeed( float speed ) +{ + b2WheelJoint_SetMotorSpeed( m_rearAxleId, speed ); + b2WheelJoint_SetMotorSpeed( m_frontAxleId, speed ); + b2Joint_WakeBodies( m_rearAxleId ); +} + +void Truck::SetTorque( float torque ) +{ + b2WheelJoint_SetMaxMotorTorque( m_rearAxleId, torque ); + b2WheelJoint_SetMaxMotorTorque( m_frontAxleId, torque ); +} + +void Truck::SetHertz( float hertz ) +{ + b2WheelJoint_SetSpringHertz( m_rearAxleId, hertz ); + b2WheelJoint_SetSpringHertz( m_frontAxleId, hertz ); +} + +void Truck::SetDampingRadio( float dampingRatio ) +{ + b2WheelJoint_SetSpringDampingRatio( m_rearAxleId, dampingRatio ); + b2WheelJoint_SetSpringDampingRatio( m_frontAxleId, dampingRatio ); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/car.h b/tests/cpp-tests/Source/Box2DTestBed/samples/car.h new file mode 100644 index 000000000000..8013d1c051dc --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/car.h @@ -0,0 +1,49 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/types.h" + +class Car +{ +public: + Car(); + + void Spawn( b2WorldId worldId, b2Vec2 position, float scale, float hertz, float dampingRatio, float torque, void* userData ); + void Despawn(); + + void SetSpeed( float speed ); + void SetTorque( float torque ); + void SetHertz( float hertz ); + void SetDampingRadio( float dampingRatio ); + + b2BodyId m_chassisId; + b2BodyId m_rearWheelId; + b2BodyId m_frontWheelId; + b2JointId m_rearAxleId; + b2JointId m_frontAxleId; + bool m_isSpawned; +}; + +class Truck +{ +public: + Truck(); + + void Spawn( b2WorldId worldId, b2Vec2 position, float scale, float hertz, float dampingRatio, float torque, float density, + void* userData ); + void Despawn(); + + void SetSpeed( float speed ); + void SetTorque( float torque ); + void SetHertz( float hertz ); + void SetDampingRadio( float dampingRatio ); + + b2BodyId m_chassisId; + b2BodyId m_rearWheelId; + b2BodyId m_frontWheelId; + b2JointId m_rearAxleId; + b2JointId m_frontAxleId; + bool m_isSpawned; +}; diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.fs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.fs new file mode 100644 index 000000000000..326ded28fd4f --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.fs @@ -0,0 +1,33 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +out vec4 FragColor; + +uniform float time; +uniform vec2 resolution; +uniform vec3 baseColor; + +// A simple pseudo-random function +float random(vec2 st) +{ + return fract(sin(dot(st.xy, vec2(12.9898, 78.233))) * 43758.5453123); +} + +void main() +{ + vec2 uv = gl_FragCoord.xy / resolution.xy; + + // Create some noise + float noise = random(uv + time * 0.1); + + // Adjust these values to control the intensity and color of the grain + float grainIntensity = 0.01; + + // Mix the base color with the noise + vec3 color = baseColor + vec3(noise * grainIntensity); + + FragColor = vec4(color, 1.0); +} + diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.vs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.vs new file mode 100644 index 000000000000..1ea9a85021e4 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/background.vs @@ -0,0 +1,10 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT +#version 330 + +layout(location = 0) in vec2 v_position; + +void main(void) +{ + gl_Position = vec4(v_position, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.fs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.fs new file mode 100644 index 000000000000..7586a2a8bc85 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.fs @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +in vec2 f_position; +in vec4 f_color; +in float f_thickness; + +out vec4 fragColor; + +void main() +{ + // radius in unit quad + float radius = 1.0; + + // distance to circle + vec2 w = f_position; + float dw = length(w); + float d = abs(dw - radius); + + fragColor = vec4(f_color.rgb, smoothstep(f_thickness, 0.0, d)); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.vs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.vs new file mode 100644 index 000000000000..df10674bce0a --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/circle.vs @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +uniform mat4 projectionMatrix; +uniform float pixelScale; + +layout(location = 0) in vec2 v_localPosition; +layout(location = 1) in vec2 v_instancePosition; +layout(location = 2) in float v_instanceRadius; +layout(location = 3) in vec4 v_instanceColor; + +out vec2 f_position; +out vec4 f_color; +out float f_thickness; + +void main() +{ + f_position = v_localPosition; + f_color = v_instanceColor; + float radius = v_instanceRadius; + + // resolution.y = pixelScale * radius + f_thickness = 3.0f / (pixelScale * radius); + + vec2 p = vec2(radius * v_localPosition.x, radius * v_localPosition.y) + v_instancePosition; + gl_Position = projectionMatrix * vec4(p, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/droid_sans.ttf b/tests/cpp-tests/Source/Box2DTestBed/samples/data/droid_sans.ttf new file mode 100644 index 000000000000..767c63ad000e Binary files /dev/null and b/tests/cpp-tests/Source/Box2DTestBed/samples/data/droid_sans.ttf differ diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.fs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.fs new file mode 100644 index 000000000000..ba5abe2b47de --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.fs @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +in vec2 f_position; +in vec4 f_color; +in float f_length; +in float f_thickness; + +out vec4 color; + +// Thanks to baz and kolyan3040 for help on this shader +// todo this can be optimized a bit, keeping some terms for clarity + +// https://en.wikipedia.org/wiki/Alpha_compositing +vec4 blend_colors(vec4 front,vec4 back) +{ + vec3 cSrc = front.rgb; + float alphaSrc = front.a; + vec3 cDst = back.rgb; + float alphaDst = back.a; + + vec3 cOut = cSrc * alphaSrc + cDst * alphaDst * (1.0 - alphaSrc); + float alphaOut = alphaSrc + alphaDst * (1.0 - alphaSrc); + + // remove alpha from rgb + cOut = cOut / alphaOut; + + return vec4(cOut, alphaOut); +} + +void main() +{ + // radius in unit quad + float radius = 0.5 * (2.0 - f_length); + + vec4 borderColor = f_color; + vec4 fillColor = 0.6f * borderColor; + + vec2 v1 = vec2(-0.5 * f_length, 0); + vec2 v2 = vec2(0.5 * f_length, 0); + + // distance to line segment + vec2 e = v2 - v1; + vec2 w = f_position - v1; + float we = dot(w, e); + vec2 b = w - e * clamp(we / dot(e, e), 0.0, 1.0); + float dw = length(b); + + // SDF union of capsule and line segment + float d = min(dw, abs(dw - radius)); + + // roll the fill alpha down at the border + vec4 back = vec4(fillColor.rgb, fillColor.a * smoothstep(radius + f_thickness, radius, dw)); + + // roll the border alpha down from 1 to 0 across the border thickness + vec4 front = vec4(borderColor.rgb, smoothstep(f_thickness, 0.0f, d)); + + color = blend_colors(front, back); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.vs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.vs new file mode 100644 index 000000000000..c592fcce30f7 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_capsule.vs @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +uniform mat4 projectionMatrix; +uniform float pixelScale; + +layout(location=0) in vec2 v_localPosition; +layout(location=1) in vec4 v_instanceTransform; +layout(location=2) in float v_instanceRadius; +layout(location=3) in float v_instanceLength; +layout(location=4) in vec4 v_instanceColor; + +out vec2 f_position; +out vec4 f_color; +out float f_length; +out float f_thickness; + +void main() +{ + f_position = v_localPosition; + f_color = v_instanceColor; + + float radius = v_instanceRadius; + float length = v_instanceLength; + + // scale quad large enough to hold capsule + float scale = radius + 0.5 * length; + + // quad range of [-1, 1] implies normalize radius and length + f_length = length / scale; + + // resolution.y = pixelScale * scale + f_thickness = 3.0f / (pixelScale * scale); + + float x = v_instanceTransform.x; + float y = v_instanceTransform.y; + float c = v_instanceTransform.z; + float s = v_instanceTransform.w; + vec2 p = vec2(scale * v_localPosition.x, scale * v_localPosition.y); + p = vec2((c * p.x - s * p.y) + x, (s * p.x + c * p.y) + y); + gl_Position = projectionMatrix * vec4(p, 0.0, 1.0); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.fs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.fs new file mode 100644 index 000000000000..695c884df804 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.fs @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +in vec2 f_position; +in vec4 f_color; +in float f_thickness; + +out vec4 fragColor; + +// https://en.wikipedia.org/wiki/Alpha_compositing +vec4 blend_colors(vec4 front, vec4 back) +{ + vec3 cSrc = front.rgb; + float alphaSrc = front.a; + vec3 cDst = back.rgb; + float alphaDst = back.a; + + vec3 cOut = cSrc * alphaSrc + cDst * alphaDst * (1.0 - alphaSrc); + float alphaOut = alphaSrc + alphaDst * (1.0 - alphaSrc); + cOut = cOut / alphaOut; + + return vec4(cOut, alphaOut); +} + +void main() +{ + // radius in unit quad + float radius = 1.0; + + // distance to axis line segment + vec2 e = vec2(radius, 0); + vec2 w = f_position; + float we = dot(w, e); + vec2 b = w - e * clamp(we / dot(e, e), 0.0, 1.0); + float da = length(b); + + // distance to circle + float dw = length(w); + float dc = abs(dw - radius); + + // union of circle and axis + float d = min(da, dc); + + vec4 borderColor = f_color; + vec4 fillColor = 0.6f * borderColor; + + // roll the fill alpha down at the border + vec4 back = vec4(fillColor.rgb, fillColor.a * smoothstep(radius + f_thickness, radius, dw)); + + // roll the border alpha down from 1 to 0 across the border thickness + vec4 front = vec4(borderColor.rgb, smoothstep(f_thickness, 0.0f, d)); + + fragColor = blend_colors(front, back); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.vs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.vs new file mode 100644 index 000000000000..69d14e1cc6d5 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_circle.vs @@ -0,0 +1,34 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +uniform mat4 projectionMatrix; +uniform float pixelScale; + +layout(location = 0) in vec2 v_localPosition; +layout(location = 1) in vec4 v_instanceTransform; +layout(location = 2) in float v_instanceRadius; +layout(location = 3) in vec4 v_instanceColor; + +out vec2 f_position; +out vec4 f_color; +out float f_thickness; + +void main() +{ + f_position = v_localPosition; + f_color = v_instanceColor; + float radius = v_instanceRadius; + + // resolution.y = pixelScale * radius + f_thickness = 3.0f / (pixelScale * radius); + + float x = v_instanceTransform.x; + float y = v_instanceTransform.y; + float c = v_instanceTransform.z; + float s = v_instanceTransform.w; + vec2 p = vec2(radius * v_localPosition.x, radius * v_localPosition.y); + p = vec2((c * p.x - s * p.y) + x, (s * p.x + c * p.y) + y); + gl_Position = projectionMatrix * vec4(p, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.fs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.fs new file mode 100644 index 000000000000..021c9f3185c5 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.fs @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +in vec2 f_position; +in vec2 f_points[8]; +flat in int f_count; +in float f_radius; +in vec4 f_color; +in float f_thickness; + +out vec4 fragColor; + +// https://en.wikipedia.org/wiki/Alpha_compositing +vec4 blend_colors(vec4 front, vec4 back) +{ + vec3 cSrc = front.rgb; + float alphaSrc = front.a; + vec3 cDst = back.rgb; + float alphaDst = back.a; + + vec3 cOut = cSrc * alphaSrc + cDst * alphaDst * (1.0 - alphaSrc); + float alphaOut = alphaSrc + alphaDst * (1.0 - alphaSrc); + + // remove alpha from rgb + cOut = cOut / alphaOut; + + return vec4(cOut, alphaOut); +} + +float cross2d(in vec2 v1, in vec2 v2) +{ + return v1.x * v2.y - v1.y * v2.x; +} + +// Signed distance function for convex polygon +float sdConvexPolygon(in vec2 p, in vec2[8] v, in int count) +{ + // Initial squared distance + float d = dot(p - v[0], p - v[0]); + + // Consider query point inside to start + float side = -1.0; + int j = count - 1; + for (int i = 0; i < count; ++i) + { + // Distance to a polygon edge + vec2 e = v[i] - v[j]; + vec2 w = p - v[j]; + float we = dot(w, e); + vec2 b = w - e * clamp(we / dot(e, e), 0.0, 1.0); + float bb = dot(b, b); + + // Track smallest distance + if (bb < d) + { + d = bb; + } + + // If the query point is outside any edge then it is outside the entire polygon. + // This depends on the CCW winding order of points. + float s = cross2d(w, e); + if (s >= 0.0) + { + side = 1.0; + } + + j = i; + } + + return side * sqrt(d); +} + +void main() +{ + vec4 borderColor = f_color; + vec4 fillColor = 0.6f * borderColor; + + float dw = sdConvexPolygon(f_position, f_points, f_count); + float d = abs(dw - f_radius); + + // roll the fill alpha down at the border + vec4 back = vec4(fillColor.rgb, fillColor.a * smoothstep(f_radius + f_thickness, f_radius, dw)); + + // roll the border alpha down from 1 to 0 across the border thickness + vec4 front = vec4(borderColor.rgb, smoothstep(f_thickness, 0.0f, d)); + + fragColor = blend_colors(front, back); + + // todo debugging + // float resy = 3.0f / f_thickness; + + // if (resy < 539.9f) + // { + // fragColor = vec4(1, 0, 0, 1); + // } + // else if (resy > 540.1f) + // { + // fragColor = vec4(0, 1, 0, 1); + // } + // else + // { + // fragColor = vec4(0, 0, 1, 1); + // } +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.vs b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.vs new file mode 100644 index 000000000000..62dce4431361 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/data/solid_polygon.vs @@ -0,0 +1,79 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 330 + +uniform mat4 projectionMatrix; +uniform float pixelScale; + +layout(location = 0) in vec2 v_localPosition; +layout(location = 1) in vec4 v_instanceTransform; +layout(location = 2) in vec4 v_instancePoints12; +layout(location = 3) in vec4 v_instancePoints34; +layout(location = 4) in vec4 v_instancePoints56; +layout(location = 5) in vec4 v_instancePoints78; +layout(location = 6) in int v_instanceCount; +layout(location = 7) in float v_instanceRadius; +layout(location = 8) in vec4 v_instanceColor; + +out vec2 f_position; +out vec4 f_color; +out vec2 f_points[8]; +flat out int f_count; +out float f_radius; +out float f_thickness; + +void main() +{ + f_position = v_localPosition; + f_color = v_instanceColor; + + f_radius = v_instanceRadius; + f_count = v_instanceCount; + + f_points[0] = v_instancePoints12.xy; + f_points[1] = v_instancePoints12.zw; + f_points[2] = v_instancePoints34.xy; + f_points[3] = v_instancePoints34.zw; + f_points[4] = v_instancePoints56.xy; + f_points[5] = v_instancePoints56.zw; + f_points[6] = v_instancePoints78.xy; + f_points[7] = v_instancePoints78.zw; + + // Compute polygon AABB + vec2 lower = f_points[0]; + vec2 upper = f_points[0]; + for (int i = 1; i < v_instanceCount; ++i) + { + lower = min(lower, f_points[i]); + upper = max(upper, f_points[i]); + } + + vec2 center = 0.5 * (lower + upper); + vec2 width = upper - lower; + float maxWidth = max(width.x, width.y); + + float scale = f_radius + 0.5 * maxWidth; + float invScale = 1.0 / scale; + + // Shift and scale polygon points so they fit in 2x2 quad + for (int i = 0; i < f_count; ++i) + { + f_points[i] = invScale * (f_points[i] - center); + } + + // Scale radius as well + f_radius = invScale * f_radius; + + // resolution.y = pixelScale * scale + f_thickness = 3.0f / (pixelScale * scale); + + // scale up and transform quad to fit polygon + float x = v_instanceTransform.x; + float y = v_instanceTransform.y; + float c = v_instanceTransform.z; + float s = v_instanceTransform.w; + vec2 p = vec2(scale * v_localPosition.x, scale * v_localPosition.y) + center; + p = vec2((c * p.x - s * p.y) + x, (s * p.x + c * p.y) + y); + gl_Position = projectionMatrix * vec4(p, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.c b/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.c new file mode 100644 index 000000000000..3a3a1fecf944 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.c @@ -0,0 +1,136 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "determinism.h" + +#include "box2d/box2d.h" + +#include +#include + +FallingHingeData CreateFallingHinges( b2WorldId worldId ) +{ + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = (b2Vec2){ 0.0f, -1.0f }; + b2BodyId groundId = b2CreateBody( worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 20.0f, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + int columnCount = 4; + int rowCount = 30; + int bodyCount = rowCount * columnCount; + + b2BodyId* bodyIds = calloc( bodyCount, sizeof( b2BodyId ) ); + + float h = 0.25f; + float r = 0.1f * h; + b2Polygon box = b2MakeRoundedBox( h - r, h - r, r ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.3f; + + float offset = 0.4f * h; + float dx = 10.0f * h; + float xroot = -0.5f * dx * ( columnCount - 1.0f ); + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.enableLimit = true; + jointDef.lowerAngle = -0.1f * B2_PI; + jointDef.upperAngle = 0.2f * B2_PI; + jointDef.enableSpring = true; + jointDef.hertz = 0.5f; + jointDef.dampingRatio = 0.5f; + jointDef.localAnchorA = (b2Vec2){ h, h }; + jointDef.localAnchorB = (b2Vec2){ offset, -h }; + jointDef.drawSize = 0.1f; + + int bodyIndex = 0; + + for ( int j = 0; j < columnCount; ++j ) + { + float x = xroot + j * dx; + + b2BodyId prevBodyId = b2_nullBodyId; + + for ( int i = 0; i < rowCount; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + bodyDef.position.x = x + offset * i; + bodyDef.position.y = h + 2.0f * h * i; + + // this tests the deterministic cosine and sine functions + bodyDef.rotation = b2MakeRot( 0.1f * i - 1.0f ); + + b2BodyId bodyId = b2CreateBody( worldId, &bodyDef ); + + if ( ( i & 1 ) == 0 ) + { + prevBodyId = bodyId; + } + else + { + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + b2CreateRevoluteJoint( worldId, &jointDef ); + prevBodyId = b2_nullBodyId; + } + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + assert( bodyIndex < bodyCount ); + bodyIds[bodyIndex] = bodyId; + + bodyIndex += 1; + } + } + + assert( bodyIndex == bodyCount ); + + FallingHingeData data = { + .bodyIds = bodyIds, + .bodyCount = bodyCount, + .stepCount = 0, + .sleepStep = -1, + .hash = 0, + }; + return data; +} + +bool UpdateFallingHinges( b2WorldId worldId, FallingHingeData* data ) +{ + if ( data->hash == 0 ) + { + b2BodyEvents bodyEvents = b2World_GetBodyEvents( worldId ); + + if ( bodyEvents.moveCount == 0 ) + { + int awakeCount = b2World_GetAwakeBodyCount( worldId ); + assert( awakeCount == 0 ); + + data->hash = B2_HASH_INIT; + for ( int i = 0; i < data->bodyCount; ++i ) + { + b2Transform xf = b2Body_GetTransform( data->bodyIds[i] ); + data->hash = b2Hash( data->hash, (uint8_t*)( &xf ), sizeof( b2Transform ) ); + } + + data->sleepStep = data->stepCount; + } + } + + data->stepCount += 1; + + return data->hash != 0; +} + +void DestroyFallingHinges( FallingHingeData* data ) +{ + free( data->bodyIds ); + data->bodyIds = NULL; +} \ No newline at end of file diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.h b/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.h new file mode 100644 index 000000000000..b71dc5316628 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/determinism.h @@ -0,0 +1,29 @@ +// SPDX-FileCopyrightText: 2025 Erin Catto +// SPDX-License-Identifier: MIT +#pragma once + +#include "box2d/id.h" + +#include + +#ifdef __cplusplus +extern "C" +{ +#endif + +typedef struct FallingHingeData +{ + b2BodyId* bodyIds; + int bodyCount; + int stepCount; + int sleepStep; + uint32_t hash; +} FallingHingeData; + +FallingHingeData CreateFallingHinges( b2WorldId worldId ); +bool UpdateFallingHinges( b2WorldId worldId, FallingHingeData* data ); +void DestroyFallingHinges( FallingHingeData* data ); + +#ifdef __cplusplus +} +#endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/donut.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/donut.cpp new file mode 100644 index 000000000000..74eaa101a285 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/donut.cpp @@ -0,0 +1,96 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "donut.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include + +Donut::Donut() +{ + for ( int i = 0; i < m_sides; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + m_jointIds[i] = b2_nullJointId; + } + + m_isSpawned = false; +} + +void Donut::Create( b2WorldId worldId, b2Vec2 position, float scale, int groupIndex, bool enableSensorEvents, void* userData ) +{ + assert( m_isSpawned == false ); + + for ( int i = 0; i < m_sides; ++i ) + { + assert( B2_IS_NULL( m_bodyIds[i] ) ); + assert( B2_IS_NULL( m_jointIds[i] ) ); + } + + float radius = 1.0f * scale; + float deltaAngle = 2.0f * B2_PI / m_sides; + float length = 2.0f * B2_PI * radius / m_sides; + + b2Capsule capsule = { { 0.0f, -0.5f * length }, { 0.0f, 0.5f * length }, 0.25f * scale }; + + b2Vec2 center = position; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.userData = userData; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.enableSensorEvents = enableSensorEvents; + shapeDef.filter.groupIndex = -groupIndex; + shapeDef.material.friction = 0.3f; + + // Create bodies + float angle = 0.0f; + for ( int i = 0; i < m_sides; ++i ) + { + bodyDef.position = { radius * cosf( angle ) + center.x, radius * sinf( angle ) + center.y }; + bodyDef.rotation = b2MakeRot( angle ); + + m_bodyIds[i] = b2CreateBody( worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[i], &shapeDef, &capsule ); + + angle += deltaAngle; + } + + // Create joints + b2WeldJointDef weldDef = b2DefaultWeldJointDef(); + weldDef.angularHertz = 5.0f; + weldDef.angularDampingRatio = 0.0f; + weldDef.localAnchorA = { 0.0f, 0.5f * length }; + weldDef.localAnchorB = { 0.0f, -0.5f * length }; + + b2BodyId prevBodyId = m_bodyIds[m_sides - 1]; + for ( int i = 0; i < m_sides; ++i ) + { + weldDef.bodyIdA = prevBodyId; + weldDef.bodyIdB = m_bodyIds[i]; + b2Rot rotA = b2Body_GetRotation( prevBodyId ); + b2Rot rotB = b2Body_GetRotation( m_bodyIds[i] ); + weldDef.referenceAngle = b2RelativeAngle( rotB, rotA ); + m_jointIds[i] = b2CreateWeldJoint( worldId, &weldDef ); + prevBodyId = weldDef.bodyIdB; + } + + m_isSpawned = true; +} + +void Donut::Destroy() +{ + assert( m_isSpawned == true ); + + for ( int i = 0; i < m_sides; ++i ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + m_jointIds[i] = b2_nullJointId; + } + + m_isSpawned = false; +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/donut.h b/tests/cpp-tests/Source/Box2DTestBed/samples/donut.h new file mode 100644 index 000000000000..9f652a424424 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/donut.h @@ -0,0 +1,20 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/types.h" + +class Donut +{ +public: + Donut(); + + void Create( b2WorldId worldId, b2Vec2 position, float scale, int groupIndex, bool enableSensorEvents, void* userData ); + void Destroy(); + + static constexpr int m_sides = 7; + b2BodyId m_bodyIds[m_sides]; + b2JointId m_jointIds[m_sides]; + bool m_isSpawned; +}; diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.cpp new file mode 100644 index 000000000000..89ac2dafd2a1 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.cpp @@ -0,0 +1,101 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "doohickey.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include + +Doohickey::Doohickey() +{ + m_wheelId1 = {}; + m_wheelId2 = {}; + m_barId1 = {}; + m_barId2 = {}; + + m_axleId1 = {}; + m_axleId2 = {}; + m_sliderId = {}; + + m_isSpawned = false; +} + +void Doohickey::Spawn( b2WorldId worldId, b2Vec2 position, float scale ) +{ + assert( m_isSpawned == false ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 0.0f }, 1.0f * scale }; + b2Capsule capsule = { { -3.5f * scale, 0.0f }, { 3.5f * scale, 0.0f }, 0.15f * scale }; + + bodyDef.position = b2MulAdd( position, scale, { -5.0f, 3.0f } ); + m_wheelId1 = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_wheelId1, &shapeDef, &circle ); + + bodyDef.position = b2MulAdd( position, scale, { 5.0f, 3.0f } ); + m_wheelId2 = b2CreateBody( worldId, &bodyDef ); + b2CreateCircleShape( m_wheelId2, &shapeDef, &circle ); + + bodyDef.position = b2MulAdd( position, scale, { -1.5f, 3.0f } ); + m_barId1 = b2CreateBody( worldId, &bodyDef ); + b2CreateCapsuleShape( m_barId1, &shapeDef, &capsule ); + + bodyDef.position = b2MulAdd( position, scale, { 1.5f, 3.0f } ); + m_barId2 = b2CreateBody( worldId, &bodyDef ); + b2CreateCapsuleShape( m_barId2, &shapeDef, &capsule ); + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + + revoluteDef.bodyIdA = m_wheelId1; + revoluteDef.bodyIdB = m_barId1; + revoluteDef.localAnchorA = { 0.0f, 0.0f }; + revoluteDef.localAnchorB = { -3.5f * scale, 0.0f }; + revoluteDef.enableMotor = true; + revoluteDef.maxMotorTorque = 2.0f * scale; + b2CreateRevoluteJoint( worldId, &revoluteDef ); + + revoluteDef.bodyIdA = m_wheelId2; + revoluteDef.bodyIdB = m_barId2; + revoluteDef.localAnchorA = { 0.0f, 0.0f }; + revoluteDef.localAnchorB = { 3.5f * scale, 0.0f }; + revoluteDef.enableMotor = true; + revoluteDef.maxMotorTorque = 2.0f * scale; + b2CreateRevoluteJoint( worldId, &revoluteDef ); + + b2PrismaticJointDef prismaticDef = b2DefaultPrismaticJointDef(); + prismaticDef.bodyIdA = m_barId1; + prismaticDef.bodyIdB = m_barId2; + prismaticDef.localAxisA = { 1.0f, 0.0f }; + prismaticDef.localAnchorA = { 2.0f * scale, 0.0f }; + prismaticDef.localAnchorB = { -2.0f * scale, 0.0f }; + prismaticDef.lowerTranslation = -2.0f * scale; + prismaticDef.upperTranslation = 2.0f * scale; + prismaticDef.enableLimit = true; + prismaticDef.enableMotor = true; + prismaticDef.maxMotorForce = 2.0f * scale; + prismaticDef.enableSpring = true; + prismaticDef.hertz = 1.0f; + prismaticDef.dampingRatio = 0.5; + b2CreatePrismaticJoint( worldId, &prismaticDef ); +} + +void Doohickey::Despawn() +{ + assert( m_isSpawned == true ); + + b2DestroyJoint( m_axleId1 ); + b2DestroyJoint( m_axleId2 ); + b2DestroyJoint( m_sliderId ); + + b2DestroyBody( m_wheelId1 ); + b2DestroyBody( m_wheelId2 ); + b2DestroyBody( m_barId1 ); + b2DestroyBody( m_barId2 ); + + m_isSpawned = false; +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.h b/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.h new file mode 100644 index 000000000000..0db7345ffd7d --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/doohickey.h @@ -0,0 +1,26 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/types.h" + +class Doohickey +{ +public: + Doohickey(); + + void Spawn( b2WorldId worldId, b2Vec2 position, float scale ); + void Despawn(); + + b2BodyId m_wheelId1; + b2BodyId m_wheelId2; + b2BodyId m_barId1; + b2BodyId m_barId2; + + b2JointId m_axleId1; + b2JointId m_axleId2; + b2JointId m_sliderId; + + bool m_isSpawned; +}; diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/draw.h b/tests/cpp-tests/Source/Box2DTestBed/samples/draw.h new file mode 100644 index 000000000000..1d73d6a5684e --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/draw.h @@ -0,0 +1,3 @@ +#pragma once + +#include "../Box2DTestDebugDrawNode.h" diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/human.c b/tests/cpp-tests/Source/Box2DTestBed/samples/human.c new file mode 100644 index 000000000000..a863f09336c7 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/human.c @@ -0,0 +1,622 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "human.h" + +#include "random.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include + +void CreateHuman( Human* human, b2WorldId worldId, b2Vec2 position, float scale, float frictionTorque, float hertz, + float dampingRatio, int groupIndex, void* userData, bool colorize ) +{ + assert( human->isSpawned == false ); + + for ( int i = 0; i < bone_count; ++i ) + { + human->bones[i].bodyId = b2_nullBodyId; + human->bones[i].jointId = b2_nullJointId; + human->bones[i].frictionScale = 1.0f; + human->bones[i].parentIndex = -1; + } + + human->scale = scale; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.sleepThreshold = 0.1f; + bodyDef.userData = userData; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.2f; + shapeDef.filter.groupIndex = -groupIndex; + shapeDef.filter.categoryBits = 2; + shapeDef.filter.maskBits = ( 1 | 2 ); + + b2ShapeDef footShapeDef = shapeDef; + footShapeDef.material.friction = 0.05f; + + // feet don't collide with ragdolls + footShapeDef.filter.categoryBits = 2; + footShapeDef.filter.maskBits = 1; + + if ( colorize ) + { + footShapeDef.material.customColor = b2_colorSaddleBrown; + } + + float s = scale; + float maxTorque = frictionTorque * s; + bool enableMotor = true; + bool enableLimit = true; + float drawSize = 0.05f; + + b2HexColor shirtColor = b2_colorMediumTurquoise; + b2HexColor pantColor = b2_colorDodgerBlue; + + b2HexColor skinColors[4] = { b2_colorNavajoWhite, b2_colorLightYellow, b2_colorPeru, b2_colorTan }; + b2HexColor skinColor = skinColors[groupIndex % 4]; + + // hip + { + Bone* bone = human->bones + bone_hip; + bone->parentIndex = -1; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.95f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "hip"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + + if ( colorize ) + { + shapeDef.material.customColor = pantColor; + } + + b2Capsule capsule = { { 0.0f, -0.02f * s }, { 0.0f, 0.02f * s }, 0.095f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + } + + // torso + { + Bone* bone = human->bones + bone_torso; + bone->parentIndex = bone_hip; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 1.2f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "torso"; + + // bodyDef.type = b2_staticBody; + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.5f; + bodyDef.type = b2_dynamicBody; + + if ( colorize ) + { + shapeDef.material.customColor = shirtColor; + } + + b2Capsule capsule = { { 0.0f, -0.135f * s }, { 0.0f, 0.135f * s }, 0.09f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.0f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.25f * B2_PI; + jointDef.upperAngle = 0.0f; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // head + { + Bone* bone = human->bones + bone_head; + bone->parentIndex = bone_torso; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f * s, 1.475f * s }, position ); + bodyDef.linearDamping = 0.1f; + bodyDef.name = "head"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.25f; + + if ( colorize ) + { + shapeDef.material.customColor = skinColor; + } + + b2Capsule capsule = { { 0.0f, -0.038f * s }, { 0.0f, 0.039f * s }, 0.075f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + //// neck + // capsule = { { 0.0f, -0.12f * s }, { 0.0f, -0.08f * s }, 0.05f * s }; + // b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.4f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.3f * B2_PI; + jointDef.upperAngle = 0.1f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // upper left leg + { + Bone* bone = human->bones + bone_upperLeftLeg; + bone->parentIndex = bone_hip; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.775f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "upper_left_leg"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 1.0f; + + if ( colorize ) + { + shapeDef.material.customColor = pantColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.06f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 0.9f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.05f * B2_PI; + jointDef.upperAngle = 0.4f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + b2Vec2 points[4] = { + { -0.03f * s, -0.185f * s }, + { 0.11f * s, -0.185f * s }, + { 0.11f * s, -0.16f * s }, + { -0.03f * s, -0.14f * s }, + }; + + b2Hull footHull = b2ComputeHull( points, 4 ); + b2Polygon footPolygon = b2MakePolygon( &footHull, 0.015f * s ); + + // lower left leg + { + Bone* bone = human->bones + bone_lowerLeftLeg; + bone->parentIndex = bone_upperLeftLeg; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.475f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "lower_left_leg"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.5f; + + if ( colorize ) + { + shapeDef.material.customColor = pantColor; + } + + b2Capsule capsule = { { 0.0f, -0.155f * s }, { 0.0f, 0.125f * s }, 0.045f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + // b2Polygon box = b2MakeOffsetBox(0.1f * s, 0.03f * s, {0.05f * s, -0.175f * s}, 0.0f); + // b2CreatePolygonShape(bone->bodyId, &shapeDef, &box); + + // capsule = { { -0.02f * s, -0.175f * s }, { 0.13f * s, -0.175f * s }, 0.03f * s }; + // b2CreateCapsuleShape( bone->bodyId, &footShapeDef, &capsule ); + + b2CreatePolygonShape( bone->bodyId, &footShapeDef, &footPolygon ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 0.625f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.5f * B2_PI; + jointDef.upperAngle = -0.02f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // upper right leg + { + Bone* bone = human->bones + bone_upperRightLeg; + bone->parentIndex = bone_hip; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.775f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "upper_right_leg"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 1.0f; + + if ( colorize ) + { + shapeDef.material.customColor = pantColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.06f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 0.9f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.05f * B2_PI; + jointDef.upperAngle = 0.4f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // lower right leg + { + Bone* bone = human->bones + bone_lowerRightLeg; + bone->parentIndex = bone_upperRightLeg; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.475f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "lower_right_leg"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.5f; + + if ( colorize ) + { + shapeDef.material.customColor = pantColor; + } + + b2Capsule capsule = { { 0.0f, -0.155f * s }, { 0.0f, 0.125f * s }, 0.045f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + // b2Polygon box = b2MakeOffsetBox(0.1f * s, 0.03f * s, {0.05f * s, -0.175f * s}, 0.0f); + // b2CreatePolygonShape(bone->bodyId, &shapeDef, &box); + + // capsule = { { -0.02f * s, -0.175f * s }, { 0.13f * s, -0.175f * s }, 0.03f * s }; + // b2CreateCapsuleShape( bone->bodyId, &footShapeDef, &capsule ); + + b2CreatePolygonShape( bone->bodyId, &footShapeDef, &footPolygon ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 0.625f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.5f * B2_PI; + jointDef.upperAngle = -0.02f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // upper left arm + { + Bone* bone = human->bones + bone_upperLeftArm; + bone->parentIndex = bone_torso; + bone->frictionScale = 0.5f; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 1.225f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "lower_left_leg"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + + if ( colorize ) + { + shapeDef.material.customColor = shirtColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.035f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.35f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.1f * B2_PI; + jointDef.upperAngle = 0.8f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // lower left arm + { + Bone* bone = human->bones + bone_lowerLeftArm; + bone->parentIndex = bone_upperLeftArm; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.975f * s }, position ); + bodyDef.linearDamping = 0.1f; + bodyDef.name = "lower_left_arm"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.1f; + + if ( colorize ) + { + shapeDef.material.customColor = skinColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.03f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.1f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.referenceAngle = 0.25f * B2_PI; + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.2f * B2_PI; + jointDef.upperAngle = 0.3f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // upper right arm + { + Bone* bone = human->bones + bone_upperRightArm; + bone->parentIndex = bone_torso; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 1.225f * s }, position ); + bodyDef.linearDamping = 0.0f; + bodyDef.name = "upper_right_arm"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.5f; + + if ( colorize ) + { + shapeDef.material.customColor = shirtColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.035f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.35f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.1f * B2_PI; + jointDef.upperAngle = 0.8f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + // lower right arm + { + Bone* bone = human->bones + bone_lowerRightArm; + bone->parentIndex = bone_upperRightArm; + + bodyDef.position = b2Add( ( b2Vec2 ){ 0.0f, 0.975f * s }, position ); + bodyDef.linearDamping = 0.1f; + bodyDef.name = "lower_right_arm"; + + bone->bodyId = b2CreateBody( worldId, &bodyDef ); + bone->frictionScale = 0.1f; + + if ( colorize ) + { + shapeDef.material.customColor = skinColor; + } + + b2Capsule capsule = { { 0.0f, -0.125f * s }, { 0.0f, 0.125f * s }, 0.03f * s }; + b2CreateCapsuleShape( bone->bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = b2Add( ( b2Vec2 ){ 0.0f, 1.1f * s }, position ); + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = human->bones[bone->parentIndex].bodyId; + jointDef.bodyIdB = bone->bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.referenceAngle = 0.25f * B2_PI; + jointDef.enableLimit = enableLimit; + jointDef.lowerAngle = -0.2f * B2_PI; + jointDef.upperAngle = 0.3f * B2_PI; + jointDef.enableMotor = enableMotor; + jointDef.maxMotorTorque = bone->frictionScale * maxTorque; + jointDef.enableSpring = hertz > 0.0f; + jointDef.hertz = hertz; + jointDef.dampingRatio = dampingRatio; + jointDef.drawSize = drawSize; + + bone->jointId = b2CreateRevoluteJoint( worldId, &jointDef ); + } + + human->isSpawned = true; +} + +void DestroyHuman( Human* human ) +{ + assert( human->isSpawned == true ); + + for ( int i = 0; i < bone_count; ++i ) + { + if ( B2_IS_NULL( human->bones[i].jointId ) ) + { + continue; + } + + b2DestroyJoint( human->bones[i].jointId ); + human->bones[i].jointId = b2_nullJointId; + } + + for ( int i = 0; i < bone_count; ++i ) + { + if ( B2_IS_NULL( human->bones[i].bodyId ) ) + { + continue; + } + + b2DestroyBody( human->bones[i].bodyId ); + human->bones[i].bodyId = b2_nullBodyId; + } + + human->isSpawned = false; +} + +void Human_SetVelocity( Human* human, b2Vec2 velocity ) +{ + for ( int i = 0; i < bone_count; ++i ) + { + b2BodyId bodyId = human->bones[i].bodyId; + + if ( B2_IS_NULL( bodyId ) ) + { + continue; + } + + b2Body_SetLinearVelocity( bodyId, velocity ); + } +} + +void Human_ApplyRandomAngularImpulse( Human* human, float magnitude ) +{ + assert( human->isSpawned == true ); + float impulse = RandomFloatRange( -magnitude, magnitude ); + b2Body_ApplyAngularImpulse( human->bones[bone_torso].bodyId, impulse, true ); +} + +void Human_SetJointFrictionTorque( Human* human, float torque ) +{ + assert( human->isSpawned == true ); + if ( torque == 0.0f ) + { + for ( int i = 1; i < bone_count; ++i ) + { + b2RevoluteJoint_EnableMotor( human->bones[i].jointId, false ); + } + } + else + { + for ( int i = 1; i < bone_count; ++i ) + { + b2RevoluteJoint_EnableMotor( human->bones[i].jointId, true ); + float scale = human->scale * human->bones[i].frictionScale; + b2RevoluteJoint_SetMaxMotorTorque( human->bones[i].jointId, scale * torque ); + } + } +} + +void Human_SetJointSpringHertz( Human* human, float hertz ) +{ + assert( human->isSpawned == true ); + if ( hertz == 0.0f ) + { + for ( int i = 1; i < bone_count; ++i ) + { + b2RevoluteJoint_EnableSpring( human->bones[i].jointId, false ); + } + } + else + { + for ( int i = 1; i < bone_count; ++i ) + { + b2RevoluteJoint_EnableSpring( human->bones[i].jointId, true ); + b2RevoluteJoint_SetSpringHertz( human->bones[i].jointId, hertz ); + } + } +} + +void Human_SetJointDampingRatio( Human* human, float dampingRatio ) +{ + assert( human->isSpawned == true ); + for ( int i = 1; i < bone_count; ++i ) + { + b2RevoluteJoint_SetSpringDampingRatio( human->bones[i].jointId, dampingRatio ); + } +} + +void Human_EnableSensorEvents( Human* human, bool enable ) +{ + assert( human->isSpawned == true ); + b2BodyId bodyId = human->bones[bone_torso].bodyId; + + b2ShapeId shapeId; + int count = b2Body_GetShapes( bodyId, &shapeId, 1 ); + if ( count == 1 ) + { + b2Shape_EnableSensorEvents( shapeId, enable ); + } +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/human.h b/tests/cpp-tests/Source/Box2DTestBed/samples/human.h new file mode 100644 index 000000000000..15faf9065616 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/human.h @@ -0,0 +1,58 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/types.h" + +typedef enum BoneId +{ + bone_hip = 0, + bone_torso = 1, + bone_head = 2, + bone_upperLeftLeg = 3, + bone_lowerLeftLeg = 4, + bone_upperRightLeg = 5, + bone_lowerRightLeg = 6, + bone_upperLeftArm = 7, + bone_lowerLeftArm = 8, + bone_upperRightArm = 9, + bone_lowerRightArm = 10, + bone_count = 11, +} BoneId; + +typedef struct Bone +{ + b2BodyId bodyId; + b2JointId jointId; + float frictionScale; + int parentIndex; +} Bone; + +typedef struct Human +{ + Bone bones[bone_count]; + float scale; + bool isSpawned; +} Human; + +#ifdef __cplusplus +extern "C" +{ +#endif + +void CreateHuman( Human* human, b2WorldId worldId, b2Vec2 position, float scale, float frictionTorque, float hertz, + float dampingRatio, int groupIndex, void* userData, bool colorize ); + +void DestroyHuman( Human* human ); + +void Human_SetVelocity( Human* human, b2Vec2 velocity ); +void Human_ApplyRandomAngularImpulse( Human* human, float magnitude ); +void Human_SetJointFrictionTorque( Human* human, float torque ); +void Human_SetJointSpringHertz( Human* human, float hertz ); +void Human_SetJointDampingRatio( Human* human, float dampingRatio ); +void Human_EnableSensorEvents( Human* human, bool enable ); + +#ifdef __cplusplus +} +#endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/jsmn.h b/tests/cpp-tests/Source/Box2DTestBed/samples/jsmn.h new file mode 100644 index 000000000000..8ac14c1bdec9 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/jsmn.h @@ -0,0 +1,471 @@ +/* + * MIT License + * + * Copyright (c) 2010 Serge Zaitsev + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ +#ifndef JSMN_H +#define JSMN_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef JSMN_STATIC +#define JSMN_API static +#else +#define JSMN_API extern +#endif + +/** + * JSON type identifier. Basic types are: + * o Object + * o Array + * o String + * o Other primitive: number, boolean (true/false) or null + */ +typedef enum { + JSMN_UNDEFINED = 0, + JSMN_OBJECT = 1 << 0, + JSMN_ARRAY = 1 << 1, + JSMN_STRING = 1 << 2, + JSMN_PRIMITIVE = 1 << 3 +} jsmntype_t; + +enum jsmnerr { + /* Not enough tokens were provided */ + JSMN_ERROR_NOMEM = -1, + /* Invalid character inside JSON string */ + JSMN_ERROR_INVAL = -2, + /* The string is not a full JSON packet, more bytes expected */ + JSMN_ERROR_PART = -3 +}; + +/** + * JSON token description. + * type type (object, array, string etc.) + * start start position in JSON data string + * end end position in JSON data string + */ +typedef struct jsmntok { + jsmntype_t type; + int start; + int end; + int size; +#ifdef JSMN_PARENT_LINKS + int parent; +#endif +} jsmntok_t; + +/** + * JSON parser. Contains an array of token blocks available. Also stores + * the string being parsed now and current position in that string. + */ +typedef struct jsmn_parser { + unsigned int pos; /* offset in the JSON string */ + unsigned int toknext; /* next token to allocate */ + int toksuper; /* superior token node, e.g. parent object or array */ +} jsmn_parser; + +/** + * Create JSON parser over an array of tokens + */ +JSMN_API void jsmn_init(jsmn_parser *parser); + +/** + * Run JSON parser. It parses a JSON data string into and array of tokens, each + * describing + * a single JSON object. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens); + +#ifndef JSMN_HEADER +/** + * Allocates a fresh unused token from the token pool. + */ +static jsmntok_t *jsmn_alloc_token(jsmn_parser *parser, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *tok; + if (parser->toknext >= num_tokens) { + return NULL; + } + tok = &tokens[parser->toknext++]; + tok->start = tok->end = -1; + tok->size = 0; +#ifdef JSMN_PARENT_LINKS + tok->parent = -1; +#endif + return tok; +} + +/** + * Fills token type and boundaries. + */ +static void jsmn_fill_token(jsmntok_t *token, const jsmntype_t type, + const int start, const int end) { + token->type = type; + token->start = start; + token->end = end; + token->size = 0; +} + +/** + * Fills next available token with JSON primitive. + */ +static int jsmn_parse_primitive(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + int start; + + start = parser->pos; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + switch (js[parser->pos]) { +#ifndef JSMN_STRICT + /* In strict mode primitive must be followed by "," or "}" or "]" */ + case ':': +#endif + case '\t': + case '\r': + case '\n': + case ' ': + case ',': + case ']': + case '}': + goto found; + default: + /* to quiet a warning from gcc*/ + break; + } + if (js[parser->pos] < 32 || js[parser->pos] >= 127) { + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } +#ifdef JSMN_STRICT + /* In strict mode primitive must be followed by a comma/object/array */ + parser->pos = start; + return JSMN_ERROR_PART; +#endif + +found: + if (tokens == NULL) { + parser->pos--; + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_PRIMITIVE, start, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + parser->pos--; + return 0; +} + +/** + * Fills next token with JSON string. + */ +static int jsmn_parse_string(jsmn_parser *parser, const char *js, + const size_t len, jsmntok_t *tokens, + const size_t num_tokens) { + jsmntok_t *token; + + int start = parser->pos; + + /* Skip starting quote */ + parser->pos++; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c = js[parser->pos]; + + /* Quote: end of string */ + if (c == '\"') { + if (tokens == NULL) { + return 0; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + parser->pos = start; + return JSMN_ERROR_NOMEM; + } + jsmn_fill_token(token, JSMN_STRING, start + 1, parser->pos); +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + return 0; + } + + /* Backslash: Quoted symbol expected */ + if (c == '\\' && parser->pos + 1 < len) { + int i; + parser->pos++; + switch (js[parser->pos]) { + /* Allowed escaped symbols */ + case '\"': + case '/': + case '\\': + case 'b': + case 'f': + case 'r': + case 'n': + case 't': + break; + /* Allows escaped symbol \uXXXX */ + case 'u': + parser->pos++; + for (i = 0; i < 4 && parser->pos < len && js[parser->pos] != '\0'; + i++) { + /* If it isn't a hex character we have an error */ + if (!((js[parser->pos] >= 48 && js[parser->pos] <= 57) || /* 0-9 */ + (js[parser->pos] >= 65 && js[parser->pos] <= 70) || /* A-F */ + (js[parser->pos] >= 97 && js[parser->pos] <= 102))) { /* a-f */ + parser->pos = start; + return JSMN_ERROR_INVAL; + } + parser->pos++; + } + parser->pos--; + break; + /* Unexpected symbol */ + default: + parser->pos = start; + return JSMN_ERROR_INVAL; + } + } + } + parser->pos = start; + return JSMN_ERROR_PART; +} + +/** + * Parse JSON string and fill tokens. + */ +JSMN_API int jsmn_parse(jsmn_parser *parser, const char *js, const size_t len, + jsmntok_t *tokens, const unsigned int num_tokens) { + int r; + int i; + jsmntok_t *token; + int count = parser->toknext; + + for (; parser->pos < len && js[parser->pos] != '\0'; parser->pos++) { + char c; + jsmntype_t type; + + c = js[parser->pos]; + switch (c) { + case '{': + case '[': + count++; + if (tokens == NULL) { + break; + } + token = jsmn_alloc_token(parser, tokens, num_tokens); + if (token == NULL) { + return JSMN_ERROR_NOMEM; + } + if (parser->toksuper != -1) { + jsmntok_t *t = &tokens[parser->toksuper]; +#ifdef JSMN_STRICT + /* In strict mode an object or array can't become a key */ + if (t->type == JSMN_OBJECT) { + return JSMN_ERROR_INVAL; + } +#endif + t->size++; +#ifdef JSMN_PARENT_LINKS + token->parent = parser->toksuper; +#endif + } + token->type = (c == '{' ? JSMN_OBJECT : JSMN_ARRAY); + token->start = parser->pos; + parser->toksuper = parser->toknext - 1; + break; + case '}': + case ']': + if (tokens == NULL) { + break; + } + type = (c == '}' ? JSMN_OBJECT : JSMN_ARRAY); +#ifdef JSMN_PARENT_LINKS + if (parser->toknext < 1) { + return JSMN_ERROR_INVAL; + } + token = &tokens[parser->toknext - 1]; + for (;;) { + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + token->end = parser->pos + 1; + parser->toksuper = token->parent; + break; + } + if (token->parent == -1) { + if (token->type != type || parser->toksuper == -1) { + return JSMN_ERROR_INVAL; + } + break; + } + token = &tokens[token->parent]; + } +#else + for (i = parser->toknext - 1; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + if (token->type != type) { + return JSMN_ERROR_INVAL; + } + parser->toksuper = -1; + token->end = parser->pos + 1; + break; + } + } + /* Error if unmatched closing bracket */ + if (i == -1) { + return JSMN_ERROR_INVAL; + } + for (; i >= 0; i--) { + token = &tokens[i]; + if (token->start != -1 && token->end == -1) { + parser->toksuper = i; + break; + } + } +#endif + break; + case '\"': + r = jsmn_parse_string(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + case '\t': + case '\r': + case '\n': + case ' ': + break; + case ':': + parser->toksuper = parser->toknext - 1; + break; + case ',': + if (tokens != NULL && parser->toksuper != -1 && + tokens[parser->toksuper].type != JSMN_ARRAY && + tokens[parser->toksuper].type != JSMN_OBJECT) { +#ifdef JSMN_PARENT_LINKS + parser->toksuper = tokens[parser->toksuper].parent; +#else + for (i = parser->toknext - 1; i >= 0; i--) { + if (tokens[i].type == JSMN_ARRAY || tokens[i].type == JSMN_OBJECT) { + if (tokens[i].start != -1 && tokens[i].end == -1) { + parser->toksuper = i; + break; + } + } + } +#endif + } + break; +#ifdef JSMN_STRICT + /* In strict mode primitives are: numbers and booleans */ + case '-': + case '0': + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + case 't': + case 'f': + case 'n': + /* And they must not be keys of the object */ + if (tokens != NULL && parser->toksuper != -1) { + const jsmntok_t *t = &tokens[parser->toksuper]; + if (t->type == JSMN_OBJECT || + (t->type == JSMN_STRING && t->size != 0)) { + return JSMN_ERROR_INVAL; + } + } +#else + /* In non-strict mode every unquoted value is a primitive */ + default: +#endif + r = jsmn_parse_primitive(parser, js, len, tokens, num_tokens); + if (r < 0) { + return r; + } + count++; + if (parser->toksuper != -1 && tokens != NULL) { + tokens[parser->toksuper].size++; + } + break; + +#ifdef JSMN_STRICT + /* Unexpected char in strict mode */ + default: + return JSMN_ERROR_INVAL; +#endif + } + } + + if (tokens != NULL) { + for (i = parser->toknext - 1; i >= 0; i--) { + /* Unmatched opened object or array */ + if (tokens[i].start != -1 && tokens[i].end == -1) { + return JSMN_ERROR_PART; + } + } + } + + return count; +} + +/** + * Creates a new parser based over a given buffer with an array of tokens + * available. + */ +JSMN_API void jsmn_init(jsmn_parser *parser) { + parser->pos = 0; + parser->toknext = 0; + parser->toksuper = -1; +} + +#endif /* JSMN_HEADER */ + +#ifdef __cplusplus +} +#endif + +#endif /* JSMN_H */ diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/random.c b/tests/cpp-tests/Source/Box2DTestBed/samples/random.c new file mode 100644 index 000000000000..1854c4eed6f9 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/random.c @@ -0,0 +1,24 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "random.h" + +uint32_t g_seed = RAND_SEED; + +b2Polygon RandomPolygon( float extent ) +{ + b2Vec2 points[B2_MAX_POLYGON_VERTICES]; + int count = 3 + RandomInt() % 6; + for ( int i = 0; i < count; ++i ) + { + points[i] = RandomVec2( -extent, extent ); + } + + b2Hull hull = b2ComputeHull( points, count ); + if ( hull.count > 0 ) + { + return b2MakePolygon( &hull, 0.0f ); + } + + return b2MakeSquare( extent ); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/random.h b/tests/cpp-tests/Source/Box2DTestBed/samples/random.h new file mode 100644 index 000000000000..d4e58d5969dc --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/random.h @@ -0,0 +1,78 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#define RAND_LIMIT 32767 +#define RAND_SEED 12345 + +// Global seed for simple random number generator. + +#ifdef __cplusplus +extern "C" +{ +#endif + +extern uint32_t g_seed; +b2Polygon RandomPolygon( float extent ); + +#ifdef __cplusplus +} +#endif + +// Simple random number generator. Using this instead of rand() for cross-platform determinism. +B2_INLINE int RandomInt() +{ + // XorShift32 algorithm + uint32_t x = g_seed; + x ^= x << 13; + x ^= x >> 17; + x ^= x << 5; + g_seed = x; + + // Map the 32-bit value to the range 0 to RAND_LIMIT + return (int)( x % ( RAND_LIMIT + 1 ) ); +} + +// Random integer in range [lo, hi] +B2_INLINE int RandomIntRange( int lo, int hi ) +{ + return lo + RandomInt() % ( hi - lo + 1 ); +} + +// Random number in range [-1,1] +B2_INLINE float RandomFloat() +{ + float r = (float)( RandomInt() & ( RAND_LIMIT ) ); + r /= RAND_LIMIT; + r = 2.0f * r - 1.0f; + return r; +} + +// Random floating point number in range [lo, hi] +B2_INLINE float RandomFloatRange( float lo, float hi ) +{ + float r = (float)( RandomInt() & ( RAND_LIMIT ) ); + r /= RAND_LIMIT; + r = ( hi - lo ) * r + lo; + return r; +} + +// Random vector with coordinates in range [lo, hi] +B2_INLINE b2Vec2 RandomVec2( float lo, float hi ) +{ + b2Vec2 v; + v.x = RandomFloatRange( lo, hi ); + v.y = RandomFloatRange( lo, hi ); + return v; +} + +// Random rotation with angle in range [-pi, pi] +B2_INLINE b2Rot RandomRot( void ) +{ + float angle = RandomFloatRange( -B2_PI, B2_PI ); + return b2MakeRot( angle ); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample.cpp new file mode 100644 index 000000000000..ffd6990c6e21 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample.cpp @@ -0,0 +1,651 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "sample.h" + +#include "TaskScheduler.h" +#include "draw.h" +#include "imgui.h" +#include "random.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +class SampleTask : public enki::ITaskSet +{ +public: + SampleTask() = default; + + void ExecuteRange( enki::TaskSetPartition range, uint32_t threadIndex ) override + { + m_task( range.start, range.end, threadIndex, m_taskContext ); + } + + b2TaskCallback* m_task = nullptr; + void* m_taskContext = nullptr; +}; + +static void* EnqueueTask( b2TaskCallback* task, int32_t itemCount, int32_t minRange, void* taskContext, void* userContext ) +{ + Sample* sample = static_cast( userContext ); + if ( sample->m_taskCount < Sample::m_maxTasks ) + { + SampleTask& sampleTask = sample->m_tasks[sample->m_taskCount]; + sampleTask.m_SetSize = itemCount; + sampleTask.m_MinRange = minRange; + sampleTask.m_task = task; + sampleTask.m_taskContext = taskContext; + sample->m_scheduler->AddTaskSetToPipe( &sampleTask ); + ++sample->m_taskCount; + return &sampleTask; + } + else + { + // This is not fatal but the maxTasks should be increased + assert( false ); + task( 0, itemCount, 0, taskContext ); + return nullptr; + } +} + +static void FinishTask( void* taskPtr, void* userContext ) +{ + if ( taskPtr != nullptr ) + { + SampleTask* sampleTask = static_cast( taskPtr ); + Sample* sample = static_cast( userContext ); + sample->m_scheduler->WaitforTask( sampleTask ); + } +} + +static void TestMathCpp() +{ + b2Vec2 a = { 1.0f, 2.0f }; + b2Vec2 b = { 3.0f, 4.0f }; + + b2Vec2 c = a; + c += b; + c -= b; + c *= 2.0f; + c = -a; + c = c + b; + c = c - a; + c = 2.0f * a; + c = a * 2.0f; + + if ( b == a ) + { + c = a; + } + + if ( b != a ) + { + c = b; + } + + c += c; +} + +Sample::Sample( Settings& settings ) +{ + m_scheduler = new enki::TaskScheduler; + m_scheduler->Initialize( settings.workerCount ); + + m_tasks = new SampleTask[m_maxTasks]; + m_taskCount = 0; + + m_threadCount = 1 + settings.workerCount; + + m_worldId = b2_nullWorldId; + + m_textLine = 30; + m_textIncrement = 22; + m_mouseJointId = b2_nullJointId; + + m_stepCount = 0; + + m_groundBodyId = b2_nullBodyId; + + m_maxProfile = {}; + m_totalProfile = {}; + + g_seed = RAND_SEED; + + m_settings = &settings; + + CreateWorld(); + TestMathCpp(); +} + +Sample::~Sample() +{ + // By deleting the world, we delete the bomb, mouse joint, etc. + b2DestroyWorld( m_worldId ); + + delete m_scheduler; + delete[] m_tasks; +} + +void Sample::CreateWorld() +{ + if ( B2_IS_NON_NULL( m_worldId ) ) + { + b2DestroyWorld( m_worldId ); + m_worldId = b2_nullWorldId; + } + + b2WorldDef worldDef = b2DefaultWorldDef(); + worldDef.workerCount = m_settings->workerCount; + worldDef.enqueueTask = EnqueueTask; + worldDef.finishTask = FinishTask; + worldDef.userTaskContext = this; + worldDef.enableSleep = m_settings->enableSleep; + m_worldId = b2CreateWorld( &worldDef ); +} + +void Sample::DrawTitle( const char* string ) +{ + g_draw.DrawString( 5, 5, string ); + m_textLine = int( 26.0f ); +} + +struct QueryContext +{ + b2Vec2 point; + b2BodyId bodyId = b2_nullBodyId; +}; + +bool QueryCallback( b2ShapeId shapeId, void* context ) +{ + QueryContext* queryContext = static_cast( context ); + + b2BodyId bodyId = b2Shape_GetBody( shapeId ); + b2BodyType bodyType = b2Body_GetType( bodyId ); + if ( bodyType != b2_dynamicBody ) + { + // continue query + return true; + } + + bool overlap = b2Shape_TestPoint( shapeId, queryContext->point ); + if ( overlap ) + { + // found shape + queryContext->bodyId = bodyId; + return false; + } + + return true; +} + +void Sample::MouseDown( b2Vec2 p, int button, int mod ) +{ + if ( B2_IS_NON_NULL( m_mouseJointId ) ) + { + return; + } + + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + // Make a small box. + b2AABB box; + b2Vec2 d = { 0.001f, 0.001f }; + box.lowerBound = b2Sub( p, d ); + box.upperBound = b2Add( p, d ); + + // Query the world for overlapping shapes. + QueryContext queryContext = { p, b2_nullBodyId }; + b2World_OverlapAABB( m_worldId, box, b2DefaultQueryFilter(), QueryCallback, &queryContext ); + + if ( B2_IS_NON_NULL( queryContext.bodyId ) ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2MouseJointDef mouseDef = b2DefaultMouseJointDef(); + mouseDef.bodyIdA = m_groundBodyId; + mouseDef.bodyIdB = queryContext.bodyId; + mouseDef.target = p; + mouseDef.hertz = 5.0f; + mouseDef.dampingRatio = 0.7f; + mouseDef.maxForce = 1000.0f * b2Body_GetMass( queryContext.bodyId ); + m_mouseJointId = b2CreateMouseJoint( m_worldId, &mouseDef ); + + b2Body_SetAwake( queryContext.bodyId, true ); + } + } +} + +void Sample::MouseUp( b2Vec2 p, int button ) +{ + if ( b2Joint_IsValid( m_mouseJointId ) == false ) + { + // The world or attached body was destroyed. + m_mouseJointId = b2_nullJointId; + } + + if ( B2_IS_NON_NULL( m_mouseJointId ) && button == GLFW_MOUSE_BUTTON_1 ) + { + b2DestroyJoint( m_mouseJointId ); + m_mouseJointId = b2_nullJointId; + + b2DestroyBody( m_groundBodyId ); + m_groundBodyId = b2_nullBodyId; + } +} + +void Sample::MouseMove( b2Vec2 p ) +{ + if ( b2Joint_IsValid( m_mouseJointId ) == false ) + { + // The world or attached body was destroyed. + m_mouseJointId = b2_nullJointId; + } + + if ( B2_IS_NON_NULL( m_mouseJointId ) ) + { + b2MouseJoint_SetTarget( m_mouseJointId, p ); + b2BodyId bodyIdB = b2Joint_GetBodyB( m_mouseJointId ); + b2Body_SetAwake( bodyIdB, true ); + } +} + +void Sample::DrawTextLine( const char* text, ... ) +{ + va_list arg; + va_start( arg, text ); + ImGui::Begin( "Overlay", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar ); + ImGui::PushFont( g_draw.m_regularFont, ImGui::GetStyle().FontSizeBase); + ImGui::SetCursorPos( ImVec2( 5.0f, float( m_textLine ) ) ); + ImGui::TextColoredV( ImColor( 230, 153, 153, 255 ), text, arg ); + ImGui::PopFont(); + ImGui::End(); + va_end( arg ); + + m_textLine += m_textIncrement; +} + +void Sample::ResetProfile() +{ + m_totalProfile = {}; + m_maxProfile = {}; + m_stepCount = 0; +} + +void Sample::Step( Settings& settings ) +{ + float timeStep = settings.hertz > 0.0f ? 1.0f / settings.hertz : 0.0f; + + if ( settings.pause ) + { + if ( settings.singleStep ) + { + settings.singleStep = false; + } + else + { + timeStep = 0.0f; + } + + if ( g_draw.m_showUI ) + { + g_draw.DrawString( 5, m_textLine, "****PAUSED****" ); + m_textLine += m_textIncrement; + } + } + + g_draw.m_debugDraw.drawingBounds = g_camera.GetViewBounds(); + g_draw.m_debugDraw.useDrawingBounds = settings.useCameraBounds; + + // todo testing + // b2Transform t1 = {g_draw.m_debugDraw.drawingBounds.lowerBound, b2Rot_identity}; + // b2Transform t2 = {g_draw.m_debugDraw.drawingBounds.upperBound, b2Rot_identity}; + // g_draw.DrawSolidCircle(t1, b2Vec2_zero, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}); + // g_draw.DrawSolidCircle(t2, b2Vec2_zero, 1.0f, {1.0f, 0.0f, 0.0f, 1.0f}); + + g_draw.m_debugDraw.drawShapes = settings.drawShapes; + g_draw.m_debugDraw.drawJoints = settings.drawJoints; + g_draw.m_debugDraw.drawJointExtras = settings.drawJointExtras; + g_draw.m_debugDraw.drawBounds = settings.drawBounds; + g_draw.m_debugDraw.drawMass = settings.drawMass; + g_draw.m_debugDraw.drawBodyNames = settings.drawBodyNames; + g_draw.m_debugDraw.drawContacts = settings.drawContactPoints; + g_draw.m_debugDraw.drawGraphColors = settings.drawGraphColors; + g_draw.m_debugDraw.drawContactNormals = settings.drawContactNormals; + g_draw.m_debugDraw.drawContactImpulses = settings.drawContactImpulses; + g_draw.m_debugDraw.drawContactFeatures = settings.drawContactFeatures; + g_draw.m_debugDraw.drawFrictionImpulses = settings.drawFrictionImpulses; + g_draw.m_debugDraw.drawIslands = settings.drawIslands; + + b2World_EnableSleeping( m_worldId, settings.enableSleep ); + b2World_EnableWarmStarting( m_worldId, settings.enableWarmStarting ); + b2World_EnableContinuous( m_worldId, settings.enableContinuous ); + + for ( int i = 0; i < 1; ++i ) + { + b2World_Step( m_worldId, timeStep, settings.subStepCount ); + m_taskCount = 0; + } + + b2World_Draw( m_worldId, &g_draw.m_debugDraw ); + + if ( timeStep > 0.0f ) + { + ++m_stepCount; + } + + if ( settings.drawCounters ) + { + b2Counters s = b2World_GetCounters( m_worldId ); + + DrawTextLine( "bodies/shapes/contacts/joints = %d/%d/%d/%d", s.bodyCount, s.shapeCount, s.contactCount, s.jointCount ); + DrawTextLine( "islands/tasks = %d/%d", s.islandCount, s.taskCount ); + DrawTextLine( "tree height static/movable = %d/%d", s.staticTreeHeight, s.treeHeight ); + + int totalCount = 0; + char buffer[256] = { 0 }; + int colorCount = sizeof( s.colorCounts ) / sizeof( s.colorCounts[0] ); + + // todo fix this + int offset = snprintf( buffer, 256, "colors: " ); + for ( int i = 0; i < colorCount; ++i ) + { + offset += snprintf( buffer + offset, 256 - offset, "%d/", s.colorCounts[i] ); + totalCount += s.colorCounts[i]; + } + snprintf( buffer + offset, 256 - offset, "[%d]", totalCount ); + DrawTextLine( buffer ); + DrawTextLine( "stack allocator size = %d K", s.stackUsed / 1024 ); + DrawTextLine( "total allocation = %d K", s.byteCount / 1024 ); + } + + // Track maximum profile times + { + b2Profile p = b2World_GetProfile( m_worldId ); + m_maxProfile.step = b2MaxFloat( m_maxProfile.step, p.step ); + m_maxProfile.pairs = b2MaxFloat( m_maxProfile.pairs, p.pairs ); + m_maxProfile.collide = b2MaxFloat( m_maxProfile.collide, p.collide ); + m_maxProfile.solve = b2MaxFloat( m_maxProfile.solve, p.solve ); + m_maxProfile.mergeIslands = b2MaxFloat( m_maxProfile.mergeIslands, p.mergeIslands ); + m_maxProfile.prepareStages = b2MaxFloat( m_maxProfile.prepareStages, p.prepareStages ); + m_maxProfile.solveConstraints = b2MaxFloat( m_maxProfile.solveConstraints, p.solveConstraints ); + m_maxProfile.prepareConstraints = b2MaxFloat( m_maxProfile.prepareConstraints, p.prepareConstraints ); + m_maxProfile.integrateVelocities = b2MaxFloat( m_maxProfile.integrateVelocities, p.integrateVelocities ); + m_maxProfile.warmStart = b2MaxFloat( m_maxProfile.warmStart, p.warmStart ); + m_maxProfile.solveImpulses = b2MaxFloat( m_maxProfile.solveImpulses, p.solveImpulses ); + m_maxProfile.integratePositions = b2MaxFloat( m_maxProfile.integratePositions, p.integratePositions ); + m_maxProfile.relaxImpulses = b2MaxFloat( m_maxProfile.relaxImpulses, p.relaxImpulses ); + m_maxProfile.applyRestitution = b2MaxFloat( m_maxProfile.applyRestitution, p.applyRestitution ); + m_maxProfile.storeImpulses = b2MaxFloat( m_maxProfile.storeImpulses, p.storeImpulses ); + m_maxProfile.transforms = b2MaxFloat( m_maxProfile.transforms, p.transforms ); + m_maxProfile.splitIslands = b2MaxFloat( m_maxProfile.splitIslands, p.splitIslands ); + m_maxProfile.hitEvents = b2MaxFloat( m_maxProfile.hitEvents, p.hitEvents ); + m_maxProfile.refit = b2MaxFloat( m_maxProfile.refit, p.refit ); + m_maxProfile.bullets = b2MaxFloat( m_maxProfile.bullets, p.bullets ); + m_maxProfile.sleepIslands = b2MaxFloat( m_maxProfile.sleepIslands, p.sleepIslands ); + m_maxProfile.sensors = b2MaxFloat( m_maxProfile.sensors, p.sensors ); + + m_totalProfile.step += p.step; + m_totalProfile.pairs += p.pairs; + m_totalProfile.collide += p.collide; + m_totalProfile.solve += p.solve; + m_totalProfile.mergeIslands += p.mergeIslands; + m_totalProfile.prepareStages += p.prepareStages; + m_totalProfile.solveConstraints += p.solveConstraints; + m_totalProfile.prepareConstraints += p.prepareConstraints; + m_totalProfile.integrateVelocities += p.integrateVelocities; + m_totalProfile.warmStart += p.warmStart; + m_totalProfile.solveImpulses += p.solveImpulses; + m_totalProfile.integratePositions += p.integratePositions; + m_totalProfile.relaxImpulses += p.relaxImpulses; + m_totalProfile.applyRestitution += p.applyRestitution; + m_totalProfile.storeImpulses += p.storeImpulses; + m_totalProfile.transforms += p.transforms; + m_totalProfile.splitIslands += p.splitIslands; + m_totalProfile.hitEvents += p.hitEvents; + m_totalProfile.refit += p.refit; + m_totalProfile.bullets += p.bullets; + m_totalProfile.sleepIslands += p.sleepIslands; + m_totalProfile.sensors += p.sensors; + } + + if ( settings.drawProfile ) + { + b2Profile p = b2World_GetProfile( m_worldId ); + + b2Profile aveProfile = {}; + if ( m_stepCount > 0 ) + { + float scale = 1.0f / m_stepCount; + aveProfile.step = scale * m_totalProfile.step; + aveProfile.pairs = scale * m_totalProfile.pairs; + aveProfile.collide = scale * m_totalProfile.collide; + aveProfile.solve = scale * m_totalProfile.solve; + aveProfile.mergeIslands = scale * m_totalProfile.mergeIslands; + aveProfile.prepareStages = scale * m_totalProfile.prepareStages; + aveProfile.solveConstraints = scale * m_totalProfile.solveConstraints; + aveProfile.prepareConstraints = scale * m_totalProfile.prepareConstraints; + aveProfile.integrateVelocities = scale * m_totalProfile.integrateVelocities; + aveProfile.warmStart = scale * m_totalProfile.warmStart; + aveProfile.solveImpulses = scale * m_totalProfile.solveImpulses; + aveProfile.integratePositions = scale * m_totalProfile.integratePositions; + aveProfile.relaxImpulses = scale * m_totalProfile.relaxImpulses; + aveProfile.applyRestitution = scale * m_totalProfile.applyRestitution; + aveProfile.storeImpulses = scale * m_totalProfile.storeImpulses; + aveProfile.transforms = scale * m_totalProfile.transforms; + aveProfile.splitIslands = scale * m_totalProfile.splitIslands; + aveProfile.hitEvents = scale * m_totalProfile.hitEvents; + aveProfile.refit = scale * m_totalProfile.refit; + aveProfile.bullets = scale * m_totalProfile.bullets; + aveProfile.sleepIslands = scale * m_totalProfile.sleepIslands; + aveProfile.sensors = scale * m_totalProfile.sensors; + } + + DrawTextLine( "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, m_maxProfile.step ); + DrawTextLine( "pairs [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.pairs, aveProfile.pairs, m_maxProfile.pairs ); + DrawTextLine( "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, m_maxProfile.collide ); + DrawTextLine( "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, m_maxProfile.solve ); + DrawTextLine( "> merge islands [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.mergeIslands, aveProfile.mergeIslands, + m_maxProfile.mergeIslands ); + DrawTextLine( "> prepare tasks [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.prepareStages, aveProfile.prepareStages, + m_maxProfile.prepareStages ); + DrawTextLine( "> solve constraints [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveConstraints, aveProfile.solveConstraints, + m_maxProfile.solveConstraints ); + DrawTextLine( ">> prepare constraints [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.prepareConstraints, + aveProfile.prepareConstraints, m_maxProfile.prepareConstraints ); + DrawTextLine( ">> integrate velocities [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.integrateVelocities, + aveProfile.integrateVelocities, m_maxProfile.integrateVelocities ); + DrawTextLine( ">> warm start [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.warmStart, aveProfile.warmStart, + m_maxProfile.warmStart ); + DrawTextLine( ">> solve impulses [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveImpulses, aveProfile.solveImpulses, + m_maxProfile.solveImpulses ); + DrawTextLine( ">> integrate positions [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.integratePositions, + aveProfile.integratePositions, m_maxProfile.integratePositions ); + DrawTextLine( ">> relax impulses [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.relaxImpulses, aveProfile.relaxImpulses, + m_maxProfile.relaxImpulses ); + DrawTextLine( ">> apply restitution [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.applyRestitution, aveProfile.applyRestitution, + m_maxProfile.applyRestitution ); + DrawTextLine( ">> store impulses [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.storeImpulses, aveProfile.storeImpulses, + m_maxProfile.storeImpulses ); + DrawTextLine( ">> split islands [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.splitIslands, aveProfile.splitIslands, + m_maxProfile.splitIslands ); + DrawTextLine( "> update transforms [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.transforms, aveProfile.transforms, + m_maxProfile.transforms ); + DrawTextLine( "> hit events [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.hitEvents, aveProfile.hitEvents, + m_maxProfile.hitEvents ); + DrawTextLine( "> refit BVH [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.refit, aveProfile.refit, m_maxProfile.refit ); + DrawTextLine( "> sleep islands [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.sleepIslands, aveProfile.sleepIslands, + m_maxProfile.sleepIslands ); + DrawTextLine( "> bullets [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.bullets, aveProfile.bullets, m_maxProfile.bullets ); + DrawTextLine( "sensors [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.sensors, aveProfile.sensors, m_maxProfile.sensors ); + } +} + +void Sample::ShiftOrigin( b2Vec2 newOrigin ) +{ + // m_world->ShiftOrigin(newOrigin); +} + +// Parse an SVG path element with only straight lines. Example: +// "M 47.625004,185.20833 H 161.39585 l 29.10417,-2.64583 26.45834,-7.9375 26.45833,-13.22917 23.81251,-21.16666 h " +// "13.22916 v 44.97916 H 592.66669 V 0 h 21.16671 v 206.375 l -566.208398,-1e-5 z" +int Sample::ParsePath( const char* svgPath, b2Vec2 offset, b2Vec2* points, int capacity, float scale, bool reverseOrder ) +{ + int pointCount = 0; + b2Vec2 currentPoint = {}; + const char* ptr = svgPath; + char command = *ptr; + + while ( *ptr != '\0' ) + { + if ( isdigit( *ptr ) == 0 && *ptr != '-' ) + { + // note: command can be implicitly repeated + command = *ptr; + + if ( command == 'M' || command == 'L' || command == 'H' || command == 'V' || command == 'm' || command == 'l' || + command == 'h' || command == 'v' ) + { + ptr += 2; // Skip the command character and space + } + + if ( command == 'z' ) + { + break; + } + } + + assert( isdigit( *ptr ) != 0 || *ptr == '-' ); + + float x = 0.0f, y = 0.0f; + switch ( command ) + { + case 'M': + case 'L': + if ( sscanf( ptr, "%f,%f", &x, &y ) == 2 ) + { + currentPoint.x = x; + currentPoint.y = y; + } + else + { + assert( false ); + } + break; + case 'H': + if ( sscanf( ptr, "%f", &x ) == 1 ) + { + currentPoint.x = x; + } + else + { + assert( false ); + } + break; + case 'V': + if ( sscanf( ptr, "%f", &y ) == 1 ) + { + currentPoint.y = y; + } + else + { + assert( false ); + } + break; + case 'm': + case 'l': + if ( sscanf( ptr, "%f,%f", &x, &y ) == 2 ) + { + currentPoint.x += x; + currentPoint.y += y; + } + else + { + assert( false ); + } + break; + case 'h': + if ( sscanf( ptr, "%f", &x ) == 1 ) + { + currentPoint.x += x; + } + else + { + assert( false ); + } + break; + case 'v': + if ( sscanf( ptr, "%f", &y ) == 1 ) + { + currentPoint.y += y; + } + else + { + assert( false ); + } + break; + + default: + assert( false ); + break; + } + + points[pointCount] = { scale * ( currentPoint.x + offset.x ), -scale * ( currentPoint.y + offset.y ) }; + pointCount += 1; + if ( pointCount == capacity ) + { + break; + } + + // Move to the next space or end of string + while ( *ptr != '\0' && isspace( *ptr ) == 0 ) + { + ptr++; + } + + // Skip contiguous spaces + while ( isspace( *ptr ) ) + { + ptr++; + } + + ptr += 0; + } + + if ( pointCount == 0 ) + { + return 0; + } + + if ( reverseOrder ) + { + } + return pointCount; +} + +SampleEntry g_sampleEntries[MAX_SAMPLES] = {}; +int g_sampleCount = 0; + +int RegisterSample( const char* category, const char* name, SampleCreateFcn* fcn ) +{ + int index = g_sampleCount; + if ( index < MAX_SAMPLES ) + { + g_sampleEntries[index] = { category, name, fcn }; + ++g_sampleCount; + return index; + } + + return -1; +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample.h b/tests/cpp-tests/Source/Box2DTestBed/samples/sample.h new file mode 100644 index 000000000000..f26bf25f2129 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample.h @@ -0,0 +1,103 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +#include "box2d/id.h" +#include "box2d/types.h" +#include "settings.h" + +#define ARRAY_COUNT( A ) (int)( sizeof( A ) / sizeof( A[0] ) ) + +namespace enki +{ +class TaskScheduler; +}; + +#ifdef NDEBUG +constexpr bool g_sampleDebug = false; +#else +constexpr bool g_sampleDebug = true; +#endif + +constexpr int k_maxContactPoints = 12 * 2048; + +struct ContactPoint +{ + b2ShapeId shapeIdA; + b2ShapeId shapeIdB; + b2Vec2 normal; + b2Vec2 position; + bool persisted; + float normalImpulse; + float tangentImpulse; + float separation; + int constraintIndex; + int color; +}; + +class Sample +{ +public: + explicit Sample( Settings& settings ); + virtual ~Sample(); + + void CreateWorld( ); + + void DrawTitle( const char* string ); + virtual void Step( Settings& settings ); + virtual void UpdateGui() + { + } + virtual void Keyboard( int ) + { + } + virtual void MouseDown( b2Vec2 p, int button, int mod ); + virtual void MouseUp( b2Vec2 p, int button ); + virtual void MouseMove( b2Vec2 p ); + + void DrawTextLine( const char* text, ... ); + void ResetProfile(); + void ShiftOrigin( b2Vec2 newOrigin ); + + static int ParsePath( const char* svgPath, b2Vec2 offset, b2Vec2* points, int capacity, float scale, bool reverseOrder ); + + friend class DestructionListener; + friend class BoundaryListener; + friend class ContactListener; + + static constexpr int m_maxTasks = 64; + static constexpr int m_maxThreads = 64; + + const Settings* m_settings; + enki::TaskScheduler* m_scheduler; + class SampleTask* m_tasks; + int m_taskCount; + int m_threadCount; + + b2BodyId m_groundBodyId; + + // DestructionListener m_destructionListener; + int m_textLine; + b2WorldId m_worldId; + b2JointId m_mouseJointId; + int m_stepCount; + int m_textIncrement; + b2Profile m_maxProfile; + b2Profile m_totalProfile; +}; + +typedef Sample* SampleCreateFcn( Settings& settings ); + +int RegisterSample( const char* category, const char* name, SampleCreateFcn* fcn ); + +struct SampleEntry +{ + const char* category; + const char* name; + SampleCreateFcn* createFcn; +}; + +#define MAX_SAMPLES 256 +extern SampleEntry g_sampleEntries[MAX_SAMPLES]; +extern int g_sampleCount; diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_benchmark.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_benchmark.cpp new file mode 100644 index 000000000000..e31b01a004c1 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_benchmark.cpp @@ -0,0 +1,1710 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "benchmarks.h" +#include "draw.h" +#include "human.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include +#include + +#if defined( _MSC_VER ) +#include +#define GET_CYCLES __rdtsc() +#else +#define GET_CYCLES b2GetTicks() +#endif + +// these are not accessible in some build types +// extern "C" int b2_toiCalls; +// extern "C" int b2_toiHitCount; + +// Note: resetting the scene is non-deterministic because the world uses freelists +class BenchmarkBarrel : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_capsuleShape, + e_mixShape, + e_compoundShape, + e_humanShape, + }; + + enum + { + e_maxColumns = 26, + e_maxRows = 150, + }; + + explicit BenchmarkBarrel( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 8.0f, 53.0f }; + g_camera.m_zoom = 25.0f * 2.35f; + } + + settings.drawJoints = false; + + { + float gridSize = 1.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float y = 0.0f; + float x = -40.0f * gridSize; + for ( int i = 0; i < 81; ++i ) + { + b2Polygon box = b2MakeOffsetBox( 0.5f * gridSize, 0.5f * gridSize, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + x += gridSize; + } + + y = gridSize; + x = -40.0f * gridSize; + for ( int i = 0; i < 100; ++i ) + { + b2Polygon box = b2MakeOffsetBox( 0.5f * gridSize, 0.5f * gridSize, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + y += gridSize; + } + + y = gridSize; + x = 40.0f * gridSize; + for ( int i = 0; i < 100; ++i ) + { + b2Polygon box = b2MakeOffsetBox( 0.5f * gridSize, 0.5f * gridSize, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + y += gridSize; + } + + b2Segment segment = { { -800.0f, -80.0f }, { 800.0f, -80.f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + for ( int i = 0; i < e_maxRows * e_maxColumns; ++i ) + { + m_bodies[i] = b2_nullBodyId; + } + + memset( m_humans, 0, sizeof( m_humans ) ); + + m_shapeType = e_compoundShape; + + CreateScene(); + } + + void CreateScene() + { + g_seed = 42; + + for ( int i = 0; i < e_maxRows * e_maxColumns; ++i ) + { + if ( B2_IS_NON_NULL( m_bodies[i] ) ) + { + b2DestroyBody( m_bodies[i] ); + m_bodies[i] = b2_nullBodyId; + } + + if ( m_humans[i].isSpawned ) + { + DestroyHuman( m_humans + i ); + } + } + + m_columnCount = g_sampleDebug ? 10 : e_maxColumns; + m_rowCount = g_sampleDebug ? 40 : e_maxRows; + + if ( m_shapeType == e_compoundShape ) + { + if constexpr ( g_sampleDebug == false ) + { + m_columnCount = 20; + } + } + else if ( m_shapeType == e_humanShape ) + { + if constexpr ( g_sampleDebug ) + { + m_rowCount = 5; + m_columnCount = 10; + } + else + { + m_rowCount = 30; + } + } + + float rad = 0.5f; + + float shift = 1.15f; + float centerx = shift * m_columnCount / 2.0f; + float centery = shift / 2.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + // todo eliminate this once rolling resistance is added + if ( m_shapeType == e_mixShape ) + { + bodyDef.angularDamping = 0.3f; + } + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.5f; + + b2Capsule capsule = { { 0.0f, -0.25f }, { 0.0f, 0.25f }, rad }; + b2Circle circle = { { 0.0f, 0.0f }, rad }; + + b2Vec2 points[3] = { { -0.1f, -0.5f }, { 0.1f, -0.5f }, { 0.0f, 0.5f } }; + b2Hull wedgeHull = b2ComputeHull( points, 3 ); + b2Polygon wedge = b2MakePolygon( &wedgeHull, 0.0f ); + + b2Vec2 vertices[3]; + vertices[0] = { -1.0f, 0.0f }; + vertices[1] = { 0.5f, 1.0f }; + vertices[2] = { 0.0f, 2.0f }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + b2Polygon left = b2MakePolygon( &hull, 0.0f ); + + vertices[0] = { 1.0f, 0.0f }; + vertices[1] = { -0.5f, 1.0f }; + vertices[2] = { 0.0f, 2.0f }; + hull = b2ComputeHull( vertices, 3 ); + b2Polygon right = b2MakePolygon( &hull, 0.0f ); + + // b2Polygon top = b2MakeOffsetBox(0.8f, 0.2f, {0.0f, 0.8f}, 0.0f); + // b2Polygon leftLeg = b2MakeOffsetBox(0.2f, 0.5f, {-0.6f, 0.5f}, 0.0f); + // b2Polygon rightLeg = b2MakeOffsetBox(0.2f, 0.5f, {0.6f, 0.5f}, 0.0f); + + float side = -0.1f; + float extray = 0.5f; + + if ( m_shapeType == e_compoundShape ) + { + extray = 0.25f; + side = 0.25f; + shift = 2.0f; + centerx = shift * m_columnCount / 2.0f - 1.0f; + } + else if ( m_shapeType == e_humanShape ) + { + extray = 0.5f; + side = 0.55f; + shift = 2.5f; + centerx = shift * m_columnCount / 2.0f; + } + + int index = 0; + float yStart = m_shapeType == e_humanShape ? 2.0f : 100.0f; + + for ( int i = 0; i < m_columnCount; ++i ) + { + float x = i * shift - centerx; + + for ( int j = 0; j < m_rowCount; ++j ) + { + float y = j * ( shift + extray ) + centery + yStart; + + bodyDef.position = { x + side, y }; + side = -side; + + if ( m_shapeType == e_circleShape ) + { + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + circle.radius = RandomFloatRange( 0.25f, 0.75f ); + shapeDef.material.rollingResistance = 0.2f; + b2CreateCircleShape( m_bodies[index], &shapeDef, &circle ); + } + else if ( m_shapeType == e_capsuleShape ) + { + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + capsule.radius = RandomFloatRange( 0.25f, 0.5f ); + float length = RandomFloatRange( 0.25f, 1.0f ); + capsule.center1 = { 0.0f, -0.5f * length }; + capsule.center2 = { 0.0f, 0.5f * length }; + shapeDef.material.rollingResistance = 0.2f; + b2CreateCapsuleShape( m_bodies[index], &shapeDef, &capsule ); + } + else if ( m_shapeType == e_mixShape ) + { + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + + int mod = index % 3; + if ( mod == 0 ) + { + circle.radius = RandomFloatRange( 0.25f, 0.75f ); + b2CreateCircleShape( m_bodies[index], &shapeDef, &circle ); + } + else if ( mod == 1 ) + { + capsule.radius = RandomFloatRange( 0.25f, 0.5f ); + float length = RandomFloatRange( 0.25f, 1.0f ); + capsule.center1 = { 0.0f, -0.5f * length }; + capsule.center2 = { 0.0f, 0.5f * length }; + b2CreateCapsuleShape( m_bodies[index], &shapeDef, &capsule ); + } + else if ( mod == 2 ) + { + float width = RandomFloatRange( 0.1f, 0.5f ); + float height = RandomFloatRange( 0.5f, 0.75f ); + b2Polygon box = b2MakeBox( width, height ); + + // Don't put a function call into a macro. + float value = RandomFloatRange( -1.0f, 1.0f ); + box.radius = 0.25f * b2MaxFloat( 0.0f, value ); + b2CreatePolygonShape( m_bodies[index], &shapeDef, &box ); + } + else + { + wedge.radius = RandomFloatRange( 0.1f, 0.25f ); + b2CreatePolygonShape( m_bodies[index], &shapeDef, &wedge ); + } + } + else if ( m_shapeType == e_compoundShape ) + { + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + + b2CreatePolygonShape( m_bodies[index], &shapeDef, &left ); + b2CreatePolygonShape( m_bodies[index], &shapeDef, &right ); + // b2CreatePolygonShape(m_bodies[index], &shapeDef, &top); + // b2CreatePolygonShape(m_bodies[index], &shapeDef, &leftLeg); + // b2CreatePolygonShape(m_bodies[index], &shapeDef, &rightLeg); + } + else if ( m_shapeType == e_humanShape ) + { + float scale = 3.5f; + float jointFriction = 0.05f; + float jointHertz = 5.0f; + float jointDamping = 0.5f; + CreateHuman( m_humans + index, m_worldId, bodyDef.position, scale, jointFriction, jointHertz, jointDamping, + index + 1, nullptr, false ); + } + + index += 1; + } + } + } + + void UpdateGui() override + { + float height = 80.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 220.0f, height ) ); + ImGui::Begin( "Benchmark: Barrel", nullptr, ImGuiWindowFlags_NoResize ); + + bool changed = false; + const char* shapeTypes[] = { "Circle", "Capsule", "Mix", "Compound", "Human" }; + + int shapeType = int( m_shapeType ); + changed = changed || ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_shapeType = ShapeType( shapeType ); + + changed = changed || ImGui::Button( "Reset Scene" ); + + if ( changed ) + { + CreateScene(); + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkBarrel( settings ); + } + + b2BodyId m_bodies[e_maxRows * e_maxColumns]; + Human m_humans[e_maxRows * e_maxColumns]; + int m_columnCount; + int m_rowCount; + + ShapeType m_shapeType; +}; + +static int benchmarkBarrel = RegisterSample( "Benchmark", "Barrel", BenchmarkBarrel::Create ); + +class BenchmarkTumbler : public Sample +{ +public: + explicit BenchmarkTumbler( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 1.5f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.6f; + } + + CreateTumbler( m_worldId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkTumbler( settings ); + } +}; + +static int benchmarkTumbler = RegisterSample( "Benchmark", "Tumbler", BenchmarkTumbler::Create ); + +// todo try removing kinematics from graph coloring +class BenchmarkManyTumblers : public Sample +{ +public: + explicit BenchmarkManyTumblers( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 1.0f, -5.5 }; + g_camera.m_zoom = 25.0f * 3.4f; + settings.drawJoints = false; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + + m_rowCount = g_sampleDebug ? 2 : 19; + m_columnCount = g_sampleDebug ? 2 : 19; + + m_tumblerIds = nullptr; + m_positions = nullptr; + m_tumblerCount = 0; + + m_bodyIds = nullptr; + m_bodyCount = 0; + m_bodyIndex = 0; + + m_angularSpeed = 25.0f; + + CreateScene(); + } + + ~BenchmarkManyTumblers() override + { + free( m_tumblerIds ); + free( m_positions ); + free( m_bodyIds ); + } + + void CreateTumbler( b2Vec2 position, int index ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position = { position.x, position.y }; + bodyDef.angularVelocity = ( B2_PI / 180.0f ) * m_angularSpeed; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + m_tumblerIds[index] = bodyId; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 50.0f; + + b2Polygon polygon; + polygon = b2MakeOffsetBox( 0.25f, 2.0f, { 2.0f, 0.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 0.25f, 2.0f, { -2.0f, 0.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 2.0f, 0.25f, { 0.0f, 2.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + polygon = b2MakeOffsetBox( 2.0f, 0.25f, { 0.0f, -2.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + } + + void CreateScene() + { + for ( int i = 0; i < m_bodyCount; ++i ) + { + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + } + } + + for ( int i = 0; i < m_tumblerCount; ++i ) + { + b2DestroyBody( m_tumblerIds[i] ); + } + + free( m_tumblerIds ); + free( m_positions ); + + m_tumblerCount = m_rowCount * m_columnCount; + m_tumblerIds = static_cast( malloc( m_tumblerCount * sizeof( b2BodyId ) ) ); + m_positions = static_cast( malloc( m_tumblerCount * sizeof( b2Vec2 ) ) ); + + int index = 0; + float x = -4.0f * m_rowCount; + for ( int i = 0; i < m_rowCount; ++i ) + { + float y = -4.0f * m_columnCount; + for ( int j = 0; j < m_columnCount; ++j ) + { + m_positions[index] = { x, y }; + CreateTumbler( m_positions[index], index ); + ++index; + y += 8.0f; + } + + x += 8.0f; + } + + free( m_bodyIds ); + + int bodiesPerTumbler = g_sampleDebug ? 8 : 50; + m_bodyCount = bodiesPerTumbler * m_tumblerCount; + + m_bodyIds = static_cast( malloc( m_bodyCount * sizeof( b2BodyId ) ) ); + + memset( m_bodyIds, 0, m_bodyCount * sizeof( b2BodyId ) ); + m_bodyIndex = 0; + } + + void UpdateGui() override + { + float height = 110.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + ImGui::Begin( "Benchmark: Many Tumblers", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + bool changed = false; + changed = changed || ImGui::SliderInt( "Row Count", &m_rowCount, 1, 32 ); + changed = changed || ImGui::SliderInt( "Column Count", &m_columnCount, 1, 32 ); + + if ( changed ) + { + CreateScene(); + } + + if ( ImGui::SliderFloat( "Speed", &m_angularSpeed, 0.0f, 100.0f, "%.f" ) ) + { + for ( int i = 0; i < m_tumblerCount; ++i ) + { + b2Body_SetAngularVelocity( m_tumblerIds[i], ( B2_PI / 180.0f ) * m_angularSpeed ); + b2Body_SetAwake( m_tumblerIds[i], true ); + } + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if ( m_bodyIndex < m_bodyCount && ( m_stepCount & 0x7 ) == 0 ) + { + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Capsule capsule = { { -0.1f, 0.0f }, { 0.1f, 0.0f }, 0.075f }; + + for ( int i = 0; i < m_tumblerCount; ++i ) + { + assert( m_bodyIndex < m_bodyCount ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = m_positions[i]; + m_bodyIds[m_bodyIndex] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[m_bodyIndex], &shapeDef, &capsule ); + + m_bodyIndex += 1; + } + } + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkManyTumblers( settings ); + } + + b2BodyId m_groundId; + + int m_rowCount; + int m_columnCount; + + b2BodyId* m_tumblerIds; + b2Vec2* m_positions; + int m_tumblerCount; + + b2BodyId* m_bodyIds; + int m_bodyCount; + int m_bodyIndex; + + float m_angularSpeed; +}; + +static int benchmarkManyTumblers = RegisterSample( "Benchmark", "Many Tumblers", BenchmarkManyTumblers::Create ); + +class BenchmarkLargePyramid : public Sample +{ +public: + explicit BenchmarkLargePyramid( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 50.0f }; + g_camera.m_zoom = 25.0f * 2.2f; + settings.enableSleep = false; + } + + CreateLargePyramid( m_worldId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkLargePyramid( settings ); + } +}; + +static int benchmarkLargePyramid = RegisterSample( "Benchmark", "Large Pyramid", BenchmarkLargePyramid::Create ); + +class BenchmarkManyPyramids : public Sample +{ +public: + explicit BenchmarkManyPyramids( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 16.0f, 110.0f }; + g_camera.m_zoom = 25.0f * 5.0f; + settings.enableSleep = false; + } + + CreateManyPyramids( m_worldId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkManyPyramids( settings ); + } +}; + +static int benchmarkManyPyramids = RegisterSample( "Benchmark", "Many Pyramids", BenchmarkManyPyramids::Create ); + +class BenchmarkCreateDestroy : public Sample +{ +public: + enum + { + e_maxBaseCount = 100, + e_maxBodyCount = e_maxBaseCount * ( e_maxBaseCount + 1 ) / 2 + }; + + explicit BenchmarkCreateDestroy( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 50.0f }; + g_camera.m_zoom = 25.0f * 2.2f; + } + + float groundSize = 100.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( groundSize, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + for ( int i = 0; i < e_maxBodyCount; ++i ) + { + m_bodies[i] = b2_nullBodyId; + } + + m_createTime = 0.0f; + m_destroyTime = 0.0f; + + m_baseCount = g_sampleDebug ? 40 : 100; + m_iterations = g_sampleDebug ? 1 : 10; + m_bodyCount = 0; + } + + void CreateScene() + { + uint64_t ticks = b2GetTicks(); + + for ( int i = 0; i < e_maxBodyCount; ++i ) + { + if ( B2_IS_NON_NULL( m_bodies[i] ) ) + { + b2DestroyBody( m_bodies[i] ); + m_bodies[i] = b2_nullBodyId; + } + } + + m_destroyTime += b2GetMillisecondsAndReset( &ticks ); + + int count = m_baseCount; + float rad = 0.5f; + float shift = rad * 2.0f; + float centerx = shift * count / 2.0f; + float centery = shift / 2.0f + 1.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.5f; + + float h = 0.5f; + b2Polygon box = b2MakeRoundedBox( h, h, 0.0f ); + + int index = 0; + + for ( int i = 0; i < count; ++i ) + { + float y = i * shift + centery; + + for ( int j = i; j < count; ++j ) + { + float x = 0.5f * i * shift + ( j - i ) * shift - centerx; + bodyDef.position = { x, y }; + + assert( index < e_maxBodyCount ); + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodies[index], &shapeDef, &box ); + + index += 1; + } + } + + m_createTime += b2GetMilliseconds( ticks ); + + m_bodyCount = index; + + b2World_Step( m_worldId, 1.0f / 60.0f, 4 ); + } + + void Step( Settings& settings ) override + { + m_createTime = 0.0f; + m_destroyTime = 0.0f; + + for ( int i = 0; i < m_iterations; ++i ) + { + CreateScene(); + } + + DrawTextLine( "total: create = %g ms, destroy = %g ms", m_createTime, m_destroyTime ); + + float createPerBody = 1000.0f * m_createTime / m_iterations / m_bodyCount; + float destroyPerBody = 1000.0f * m_destroyTime / m_iterations / m_bodyCount; + DrawTextLine( "body: create = %g us, destroy = %g us", createPerBody, destroyPerBody ); + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkCreateDestroy( settings ); + } + + float m_createTime; + float m_destroyTime; + b2BodyId m_bodies[e_maxBodyCount]; + int m_bodyCount; + int m_baseCount; + int m_iterations; +}; + +static int benchmarkCreateDestroy = RegisterSample( "Benchmark", "CreateDestroy", BenchmarkCreateDestroy::Create ); + +class BenchmarkSleep : public Sample +{ +public: + enum + { + e_maxBaseCount = 100, + e_maxBodyCount = e_maxBaseCount * ( e_maxBaseCount + 1 ) / 2 + }; + + explicit BenchmarkSleep( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 50.0f }; + g_camera.m_zoom = 25.0f * 2.2f; + } + + float groundSize = 100.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( groundSize, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + for ( int i = 0; i < e_maxBodyCount; ++i ) + { + m_bodies[i] = b2_nullBodyId; + } + + m_baseCount = g_sampleDebug ? 40 : 100; + m_iterations = g_sampleDebug ? 1 : 41; + m_bodyCount = 0; + m_awake = false; + + m_wakeTotal = 0.0f; + m_wakeCount = 0; + + m_sleepTotal = 0.0f; + m_sleepCount = 0; + + CreateScene(); + } + + void CreateScene() + { + for ( int i = 0; i < e_maxBodyCount; ++i ) + { + if ( B2_IS_NON_NULL( m_bodies[i] ) ) + { + b2DestroyBody( m_bodies[i] ); + m_bodies[i] = b2_nullBodyId; + } + } + + int count = m_baseCount; + float rad = 0.5f; + float shift = rad * 2.0f; + float centerx = shift * count / 2.0f; + float centery = shift / 2.0f + 1.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.5f; + + float h = 0.5f; + b2Polygon box = b2MakeRoundedBox( h, h, 0.0f ); + + int index = 0; + + for ( int i = 0; i < count; ++i ) + { + float y = i * shift + centery; + + for ( int j = i; j < count; ++j ) + { + float x = 0.5f * i * shift + ( j - i ) * shift - centerx; + bodyDef.position = { x, y }; + + assert( index < e_maxBodyCount ); + m_bodies[index] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodies[index], &shapeDef, &box ); + + index += 1; + } + } + + m_bodyCount = index; + } + + void Step( Settings& settings ) override + { + uint64_t ticks = b2GetTicks(); + + for ( int i = 0; i < m_iterations; ++i ) + { + b2Body_SetAwake( m_bodies[0], m_awake ); + if ( m_awake ) + { + m_wakeTotal += b2GetMillisecondsAndReset( &ticks ); + m_wakeCount += 1; + } + else + { + m_sleepTotal += b2GetMillisecondsAndReset( &ticks ); + m_sleepCount += 1; + } + m_awake = !m_awake; + } + + if ( m_wakeCount > 0 ) + { + g_draw.DrawString( 5, m_textLine, "wake ave = %g ms", m_wakeTotal / m_wakeCount ); + m_textLine += m_textIncrement; + } + + if ( m_sleepCount > 0 ) + { + g_draw.DrawString( 5, m_textLine, "sleep ave = %g ms", m_sleepTotal / m_sleepCount ); + m_textLine += m_textIncrement; + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkSleep( settings ); + } + + b2BodyId m_bodies[e_maxBodyCount]; + int m_bodyCount; + int m_baseCount; + int m_iterations; + float m_wakeTotal; + float m_sleepTotal; + int m_wakeCount; + int m_sleepCount; + bool m_awake; +}; + +static int benchmarkSleep = RegisterSample( "Benchmark", "Sleep", BenchmarkSleep::Create ); + +class BenchmarkJointGrid : public Sample +{ +public: + explicit BenchmarkJointGrid( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 60.0f, -57.0f }; + g_camera.m_zoom = 25.0f * 2.5f; + settings.enableSleep = false; + } + + CreateJointGrid( m_worldId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkJointGrid( settings ); + } +}; + +static int benchmarkJointGridIndex = RegisterSample( "Benchmark", "Joint Grid", BenchmarkJointGrid::Create ); + +class BenchmarkSmash : public Sample +{ +public: + explicit BenchmarkSmash( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 60.0f, 6.0f }; + g_camera.m_zoom = 25.0f * 1.6f; + } + + CreateSmash( m_worldId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkSmash( settings ); + } +}; + +static int sampleSmash = RegisterSample( "Benchmark", "Smash", BenchmarkSmash::Create ); + +class BenchmarkCompound : public Sample +{ +public: + explicit BenchmarkCompound( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 18.0f, 115.0f }; + g_camera.m_zoom = 25.0f * 5.5f; + } + + float grid = 1.0f; +#ifdef NDEBUG + int height = 200; + int width = 200; +#else + int height = 100; + int width = 100; +#endif + { + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + for ( int i = 0; i < height; ++i ) + { + float y = grid * i; + for ( int j = i; j < width; ++j ) + { + float x = grid * j; + b2Polygon square = b2MakeOffsetBox( 0.5f * grid, 0.5f * grid, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &square ); + } + } + + for ( int i = 0; i < height; ++i ) + { + float y = grid * i; + for ( int j = i; j < width; ++j ) + { + float x = -grid * j; + b2Polygon square = b2MakeOffsetBox( 0.5f * grid, 0.5f * grid, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &square ); + } + } + } + + { +#ifdef NDEBUG + int span = 20; + int count = 5; +#else + int span = 5; + int count = 5; +#endif + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + // defer mass properties to avoid n-squared mass computations + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.updateBodyMass = false; + + for ( int m = 0; m < count; ++m ) + { + float ybody = ( 100.0f + m * span ) * grid; + + for ( int n = 0; n < count; ++n ) + { + float xbody = -0.5f * grid * count * span + n * span * grid; + bodyDef.position = { xbody, ybody }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + for ( int i = 0; i < span; ++i ) + { + float y = i * grid; + for ( int j = 0; j < span; ++j ) + { + float x = j * grid; + b2Polygon square = b2MakeOffsetBox( 0.5f * grid, 0.5f * grid, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &square ); + } + } + + // All shapes have been added so I can efficiently compute the mass properties. + b2Body_ApplyMassFromShapes( bodyId ); + } + } + } + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkCompound( settings ); + } +}; + +static int sampleCompound = RegisterSample( "Benchmark", "Compound", BenchmarkCompound::Create ); + +class BenchmarkKinematic : public Sample +{ +public: + explicit BenchmarkKinematic( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 150.0f; + } + + float grid = 1.0f; + +#ifdef NDEBUG + int span = 100; +#else + int span = 20; +#endif + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.angularVelocity = 1.0f; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = 1; + shapeDef.filter.maskBits = 2; + + // defer mass properties to avoid n-squared mass computations + shapeDef.updateBodyMass = false; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + for ( int i = -span; i < span; ++i ) + { + float y = i * grid; + for ( int j = -span; j < span; ++j ) + { + float x = j * grid; + b2Polygon square = b2MakeOffsetBox( 0.5f * grid, 0.5f * grid, { x, y }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &square ); + } + } + + // All shapes have been added so I can efficiently compute the mass properties. + b2Body_ApplyMassFromShapes( bodyId ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkKinematic( settings ); + } +}; + +static int sampleKinematic = RegisterSample( "Benchmark", "Kinematic", BenchmarkKinematic::Create ); + +enum QueryType +{ + e_rayCast, + e_circleCast, + e_overlap, +}; + +class BenchmarkCast : public Sample +{ +public: + explicit BenchmarkCast( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 500.0f, 500.0f }; + g_camera.m_zoom = 25.0f * 21.0f; + // settings.drawShapes = g_sampleDebug; + } + + m_queryType = e_circleCast; + m_ratio = 5.0f; + m_grid = 1.0f; + m_fill = 0.1f; + m_rowCount = g_sampleDebug ? 100 : 1000; + m_columnCount = g_sampleDebug ? 100 : 1000; + m_minTime = 1e6f; + m_drawIndex = 0; + m_topDown = false; + m_buildTime = 0.0f; + m_radius = 0.1f; + + g_seed = 1234; + int sampleCount = g_sampleDebug ? 100 : 10000; + m_origins.resize( sampleCount ); + m_translations.resize( sampleCount ); + float extent = m_rowCount * m_grid; + + // Pre-compute rays to avoid randomizer overhead + for ( int i = 0; i < sampleCount; ++i ) + { + b2Vec2 rayStart = RandomVec2( 0.0f, extent ); + b2Vec2 rayEnd = RandomVec2( 0.0f, extent ); + + m_origins[i] = rayStart; + m_translations[i] = rayEnd - rayStart; + } + + BuildScene(); + } + + void BuildScene() + { + g_seed = 1234; + b2DestroyWorld( m_worldId ); + b2WorldDef worldDef = b2DefaultWorldDef(); + m_worldId = b2CreateWorld( &worldDef ); + + uint64_t ticks = b2GetTicks(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float y = 0.0f; + + for ( int i = 0; i < m_rowCount; ++i ) + { + float x = 0.0f; + + for ( int j = 0; j < m_columnCount; ++j ) + { + float fillTest = RandomFloatRange( 0.0f, 1.0f ); + if ( fillTest <= m_fill ) + { + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + float ratio = RandomFloatRange( 1.0f, m_ratio ); + float halfWidth = RandomFloatRange( 0.05f, 0.25f ); + + b2Polygon box; + if ( RandomFloat() > 0.0f ) + { + box = b2MakeBox( ratio * halfWidth, halfWidth ); + } + else + { + box = b2MakeBox( halfWidth, ratio * halfWidth ); + } + + int category = RandomIntRange( 0, 2 ); + shapeDef.filter.categoryBits = 1 << category; + if ( category == 0 ) + { + shapeDef.material.customColor = b2_colorBox2DBlue; + } + else if ( category == 1 ) + { + shapeDef.material.customColor = b2_colorBox2DYellow; + } + else + { + shapeDef.material.customColor = b2_colorBox2DGreen; + } + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + x += m_grid; + } + + y += m_grid; + } + + if ( m_topDown ) + { + b2World_RebuildStaticTree( m_worldId ); + } + + m_buildTime = b2GetMilliseconds( ticks ); + m_minTime = 1e6f; + } + + void UpdateGui() override + { + float height = 240.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Cast", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 100.0f ); + + bool changed = false; + + const char* queryTypes[] = { "Ray", "Circle", "Overlap" }; + int queryType = int( m_queryType ); + if ( ImGui::Combo( "Query", &queryType, queryTypes, IM_ARRAYSIZE( queryTypes ) ) ) + { + m_queryType = QueryType( queryType ); + if ( m_queryType == e_overlap ) + { + m_radius = 5.0f; + } + else + { + m_radius = 0.1f; + } + + changed = true; + } + + if ( ImGui::SliderInt( "rows", &m_rowCount, 0, 1000, "%d" ) ) + { + changed = true; + } + + if ( ImGui::SliderInt( "columns", &m_columnCount, 0, 1000, "%d" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "fill", &m_fill, 0.0f, 1.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "grid", &m_grid, 0.5f, 2.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "ratio", &m_ratio, 1.0f, 10.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::Checkbox( "top down", &m_topDown ) ) + { + changed = true; + } + + if ( ImGui::Button( "Draw Next" ) ) + { + m_drawIndex = ( m_drawIndex + 1 ) % m_origins.size(); + } + + ImGui::PopItemWidth(); + ImGui::End(); + + if ( changed ) + { + BuildScene(); + } + } + + struct CastResult + { + b2Vec2 point; + float fraction; + bool hit; + }; + + static float CastCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) + { + CastResult* result = (CastResult*)context; + result->point = point; + result->fraction = fraction; + result->hit = true; + return fraction; + } + + struct OverlapResult + { + b2Vec2 points[32]; + int count; + }; + + static bool OverlapCallback( b2ShapeId shapeId, void* context ) + { + OverlapResult* result = (OverlapResult*)context; + if ( result->count < 32 ) + { + b2AABB aabb = b2Shape_GetAABB( shapeId ); + result->points[result->count] = b2AABB_Center( aabb ); + result->count += 1; + } + + return true; + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2QueryFilter filter = b2DefaultQueryFilter(); + filter.maskBits = 1; + int hitCount = 0; + int nodeVisits = 0; + int leafVisits = 0; + float ms = 0.0f; + int sampleCount = (int)m_origins.size(); + + if ( m_queryType == e_rayCast ) + { + uint64_t ticks = b2GetTicks(); + + b2RayResult drawResult = {}; + + for ( int i = 0; i < sampleCount; ++i ) + { + b2Vec2 origin = m_origins[i]; + b2Vec2 translation = m_translations[i]; + + b2RayResult result = b2World_CastRayClosest( m_worldId, origin, translation, filter ); + + if ( i == m_drawIndex ) + { + drawResult = result; + } + + nodeVisits += result.nodeVisits; + leafVisits += result.leafVisits; + hitCount += result.hit ? 1 : 0; + } + + ms = b2GetMilliseconds( ticks ); + + m_minTime = b2MinFloat( m_minTime, ms ); + + b2Vec2 p1 = m_origins[m_drawIndex]; + b2Vec2 p2 = p1 + m_translations[m_drawIndex]; + g_draw.DrawSegment( p1, p2, b2_colorWhite ); + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + g_draw.DrawPoint( p2, 5.0f, b2_colorRed ); + if ( drawResult.hit ) + { + g_draw.DrawPoint( drawResult.point, 5.0f, b2_colorWhite ); + } + } + else if ( m_queryType == e_circleCast ) + { + uint64_t ticks = b2GetTicks(); + + CastResult drawResult = {}; + + for ( int i = 0; i < sampleCount; ++i ) + { + b2ShapeProxy proxy = b2MakeProxy( &m_origins[i], 1, m_radius ); + b2Vec2 translation = m_translations[i]; + + CastResult result; + b2TreeStats traversalResult = b2World_CastShape( m_worldId, &proxy, translation, filter, CastCallback, &result ); + + if ( i == m_drawIndex ) + { + drawResult = result; + } + + nodeVisits += traversalResult.nodeVisits; + leafVisits += traversalResult.leafVisits; + hitCount += result.hit ? 1 : 0; + } + + ms = b2GetMilliseconds( ticks ); + + m_minTime = b2MinFloat( m_minTime, ms ); + + b2Vec2 p1 = m_origins[m_drawIndex]; + b2Vec2 p2 = p1 + m_translations[m_drawIndex]; + g_draw.DrawSegment( p1, p2, b2_colorWhite ); + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + g_draw.DrawPoint( p2, 5.0f, b2_colorRed ); + if ( drawResult.hit ) + { + b2Vec2 t = b2Lerp( p1, p2, drawResult.fraction ); + g_draw.DrawCircle( t, m_radius, b2_colorWhite ); + g_draw.DrawPoint( drawResult.point, 5.0f, b2_colorWhite ); + } + } + else if ( m_queryType == e_overlap ) + { + uint64_t ticks = b2GetTicks(); + + OverlapResult drawResult = {}; + b2Vec2 extent = { m_radius, m_radius }; + OverlapResult result = {}; + + for ( int i = 0; i < sampleCount; ++i ) + { + b2Vec2 origin = m_origins[i]; + b2AABB aabb = { origin - extent, origin + extent }; + + result.count = 0; + b2TreeStats traversalResult = b2World_OverlapAABB( m_worldId, aabb, filter, OverlapCallback, &result ); + + if ( i == m_drawIndex ) + { + drawResult = result; + } + + nodeVisits += traversalResult.nodeVisits; + leafVisits += traversalResult.leafVisits; + hitCount += result.count; + } + + ms = b2GetMilliseconds( ticks ); + + m_minTime = b2MinFloat( m_minTime, ms ); + + b2Vec2 origin = m_origins[m_drawIndex]; + b2AABB aabb = { origin - extent, origin + extent }; + + g_draw.DrawAABB( aabb, b2_colorWhite ); + + for ( int i = 0; i < drawResult.count; ++i ) + { + g_draw.DrawPoint( drawResult.points[i], 5.0f, b2_colorHotPink ); + } + } + + g_draw.DrawString( 5, m_textLine, "build time ms = %g", m_buildTime ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "hit count = %d, node visits = %d, leaf visits = %d", hitCount, nodeVisits, + leafVisits ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "total ms = %.3f", ms ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "min total ms = %.3f", m_minTime ); + m_textLine += m_textIncrement; + + float aveRayCost = 1000.0f * m_minTime / float( sampleCount ); + g_draw.DrawString( 5, m_textLine, "average us = %.2f", aveRayCost ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkCast( settings ); + } + + QueryType m_queryType; + + std::vector m_origins; + std::vector m_translations; + float m_minTime; + float m_buildTime; + + int m_rowCount, m_columnCount; + int m_updateType; + int m_drawIndex; + float m_radius; + float m_fill; + float m_ratio; + float m_grid; + bool m_topDown; +}; + +static int sampleCast = RegisterSample( "Benchmark", "Cast", BenchmarkCast::Create ); + +class BenchmarkSpinner : public Sample +{ +public: + explicit BenchmarkSpinner( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 32.0f }; + g_camera.m_zoom = 42.0f; + } + + // b2_toiCalls = 0; + // b2_toiHitCount = 0; + + CreateSpinner( m_worldId ); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if ( m_stepCount == 1000 && false ) + { + // 0.1 : 46544, 25752 + // 0.25 : 5745, 1947 + // 0.5 : 2197, 660 + settings.pause = true; + } + + // DrawTextLine( "toi calls, hits = %d, %d", b2_toiCalls, b2_toiHitCount ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkSpinner( settings ); + } +}; + +static int sampleSpinner = RegisterSample( "Benchmark", "Spinner", BenchmarkSpinner::Create ); + +class BenchmarkRain : public Sample +{ +public: + explicit BenchmarkRain( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 110.0f }; + g_camera.m_zoom = 125.0f; + settings.enableSleep = true; + } + + settings.drawJoints = false; + + CreateRain( m_worldId ); + } + + void Step( Settings& settings ) override + { + if ( settings.pause == false || settings.singleStep == true ) + { + StepRain( m_worldId, m_stepCount ); + } + + Sample::Step( settings ); + + if ( m_stepCount % 1000 == 0 ) + { + m_stepCount += 0; + } + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkRain( settings ); + } +}; + +static int benchmarkRain = RegisterSample( "Benchmark", "Rain", BenchmarkRain::Create ); + +class BenchmarkShapeDistance : public Sample +{ +public: + explicit BenchmarkShapeDistance( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 3.0f; + } + + { + b2Vec2 points[8] = {}; + b2Rot q = b2MakeRot( 2.0f * B2_PI / 8.0f ); + b2Vec2 p = { 0.5f, 0.0f }; + points[0] = p; + for ( int i = 1; i < 8; ++i ) + { + points[i] = b2RotateVector( q, points[i - 1] ); + } + + b2Hull hull = b2ComputeHull( points, 8 ); + m_polygonA = b2MakePolygon( &hull, 0.0f ); + } + + { + b2Vec2 points[8] = {}; + b2Rot q = b2MakeRot( 2.0f * B2_PI / 8.0f ); + b2Vec2 p = { 0.5f, 0.0f }; + points[0] = p; + for ( int i = 1; i < 8; ++i ) + { + points[i] = b2RotateVector( q, points[i - 1] ); + } + + b2Hull hull = b2ComputeHull( points, 8 ); + m_polygonB = b2MakePolygon( &hull, 0.1f ); + } + + // todo arena + m_transformAs = (b2Transform*)malloc( m_count * sizeof( b2Transform ) ); + m_transformBs = (b2Transform*)malloc( m_count * sizeof( b2Transform ) ); + m_outputs = (b2DistanceOutput*)calloc( m_count, sizeof( b2DistanceOutput ) ); + + g_seed = 42; + for ( int i = 0; i < m_count; ++i ) + { + m_transformAs[i] = { RandomVec2( -0.1f, 0.1f ), RandomRot() }; + m_transformBs[i] = { RandomVec2( 0.25f, 2.0f ), RandomRot() }; + } + + m_drawIndex = 0; + m_minCycles = INT_MAX; + m_minMilliseconds = FLT_MAX; + } + + ~BenchmarkShapeDistance() override + { + free( m_transformAs ); + free( m_transformBs ); + free( m_outputs ); + } + + void UpdateGui() override + { + float height = 80.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 220.0f, height ) ); + ImGui::Begin( "Benchmark: Shape Distance", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::SliderInt( "draw index", &m_drawIndex, 0, m_count - 1 ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( settings.pause == false || settings.singleStep == true ) + { + b2DistanceInput input = {}; + input.proxyA = b2MakeProxy( m_polygonA.vertices, m_polygonA.count, m_polygonA.radius ); + input.proxyB = b2MakeProxy( m_polygonB.vertices, m_polygonB.count, m_polygonB.radius ); + input.useRadii = true; + int totalIterations = 0; + + uint64_t start = b2GetTicks(); + uint64_t startCycles = GET_CYCLES; + for ( int i = 0; i < m_count; ++i ) + { + b2SimplexCache cache = {}; + input.transformA = m_transformAs[i]; + input.transformB = m_transformBs[i]; + m_outputs[i] = b2ShapeDistance( &input, &cache, nullptr, 0 ); + totalIterations += m_outputs[i].iterations; + } + uint64_t endCycles = GET_CYCLES; + + float ms = b2GetMilliseconds( start ); + m_minCycles = b2MinInt( m_minCycles, int( endCycles - startCycles ) ); + m_minMilliseconds = b2MinFloat( m_minMilliseconds, ms ); + + DrawTextLine( "count = %d", m_count ); + DrawTextLine( "min cycles = %d", m_minCycles ); + DrawTextLine( "ave cycles = %g", float( m_minCycles ) / float( m_count ) ); + DrawTextLine( "min ms = %g, ave us = %g", m_minMilliseconds, 1000.0f * m_minMilliseconds / float( m_count ) ); + DrawTextLine( "average iterations = %g", totalIterations / float( m_count ) ); + } + + b2Transform xfA = m_transformAs[m_drawIndex]; + b2Transform xfB = m_transformBs[m_drawIndex]; + b2DistanceOutput output = m_outputs[m_drawIndex]; + g_draw.DrawSolidPolygon( xfA, m_polygonA.vertices, m_polygonA.count, m_polygonA.radius, b2_colorBox2DGreen ); + g_draw.DrawSolidPolygon( xfB, m_polygonB.vertices, m_polygonB.count, m_polygonB.radius, b2_colorBox2DBlue ); + g_draw.DrawSegment( output.pointA, output.pointB, b2_colorDimGray ); + g_draw.DrawPoint( output.pointA, 10.0f, b2_colorWhite ); + g_draw.DrawPoint( output.pointB, 10.0f, b2_colorWhite ); + g_draw.DrawSegment( output.pointA, output.pointA + 0.5f * output.normal, b2_colorYellow ); + DrawTextLine( "distance = %g", output.distance ); + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BenchmarkShapeDistance( settings ); + } + + static constexpr int m_count = g_sampleDebug ? 100 : 10000; + b2Transform* m_transformAs; + b2Transform* m_transformBs; + b2DistanceOutput* m_outputs; + b2Polygon m_polygonA; + b2Polygon m_polygonB; + float m_minMilliseconds; + int m_drawIndex; + int m_minCycles; +}; + +static int benchmarkShapeDistance = RegisterSample( "Benchmark", "Shape Distance", BenchmarkShapeDistance::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_bodies.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_bodies.cpp new file mode 100644 index 000000000000..c2da9b671282 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_bodies.cpp @@ -0,0 +1,880 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" + +#include + +class BodyType : public Sample +{ +public: + explicit BodyType( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.8f, 6.4f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + m_type = b2_dynamicBody; + m_isEnabled = true; + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Define attachment + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -2.0f, 3.0f }; + m_attachmentId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.5f, 2.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + b2CreatePolygonShape( m_attachmentId, &shapeDef, &box ); + } + + // Define second attachment + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = m_type; + bodyDef.isEnabled = m_isEnabled; + bodyDef.position = { 3.0f, 3.0f }; + m_secondAttachmentId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.5f, 2.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + b2CreatePolygonShape( m_secondAttachmentId, &shapeDef, &box ); + } + + // Define platform + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = m_type; + bodyDef.isEnabled = m_isEnabled; + bodyDef.position = { -4.0f, 5.0f }; + m_platformId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeOffsetBox( 0.5f, 4.0f, { 4.0f, 0.0f }, b2MakeRot( 0.5f * B2_PI ) ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + b2CreatePolygonShape( m_platformId, &shapeDef, &box ); + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + b2Vec2 pivot = { -2.0f, 5.0f }; + revoluteDef.bodyIdA = m_attachmentId; + revoluteDef.bodyIdB = m_platformId; + revoluteDef.localAnchorA = b2Body_GetLocalPoint( m_attachmentId, pivot ); + revoluteDef.localAnchorB = b2Body_GetLocalPoint( m_platformId, pivot ); + revoluteDef.maxMotorTorque = 50.0f; + revoluteDef.enableMotor = true; + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + pivot = { 3.0f, 5.0f }; + revoluteDef.bodyIdA = m_secondAttachmentId; + revoluteDef.bodyIdB = m_platformId; + revoluteDef.localAnchorA = b2Body_GetLocalPoint( m_secondAttachmentId, pivot ); + revoluteDef.localAnchorB = b2Body_GetLocalPoint( m_platformId, pivot ); + revoluteDef.maxMotorTorque = 50.0f; + revoluteDef.enableMotor = true; + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + b2PrismaticJointDef prismaticDef = b2DefaultPrismaticJointDef(); + b2Vec2 anchor = { 0.0f, 5.0f }; + prismaticDef.bodyIdA = groundId; + prismaticDef.bodyIdB = m_platformId; + prismaticDef.localAnchorA = b2Body_GetLocalPoint( groundId, anchor ); + prismaticDef.localAnchorB = b2Body_GetLocalPoint( m_platformId, anchor ); + prismaticDef.localAxisA = { 1.0f, 0.0f }; + prismaticDef.maxMotorForce = 1000.0f; + prismaticDef.motorSpeed = 0.0f; + prismaticDef.enableMotor = true; + prismaticDef.lowerTranslation = -10.0f; + prismaticDef.upperTranslation = 10.0f; + prismaticDef.enableLimit = true; + + b2CreatePrismaticJoint( m_worldId, &prismaticDef ); + + m_speed = 3.0f; + } + + // Create a payload + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -3.0f, 8.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.75f, 0.75f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Create a second payload + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = m_type; + bodyDef.isEnabled = m_isEnabled; + bodyDef.position = { 2.0f, 8.0f }; + m_secondPayloadId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.75f, 0.75f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + + b2CreatePolygonShape( m_secondPayloadId, &shapeDef, &box ); + } + + // Create a separate body on the ground + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = m_type; + bodyDef.isEnabled = m_isEnabled; + bodyDef.position = { 8.0f, 0.2f }; + m_touchingBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, 0.0f }, { 1.0f, 0.0f }, 0.25f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + + b2CreateCapsuleShape( m_touchingBodyId, &shapeDef, &capsule ); + } + + // Create a separate floating body + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = m_type; + bodyDef.isEnabled = m_isEnabled; + bodyDef.position = { -8.0f, 12.0f }; + bodyDef.gravityScale = 0.0f; + m_floatingBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Circle circle = { { 0.0f, 0.5f }, 0.25f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + + b2CreateCircleShape( m_floatingBodyId, &shapeDef, &circle ); + } + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + ImGui::Begin( "Body Type", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( ImGui::RadioButton( "Static", m_type == b2_staticBody ) ) + { + m_type = b2_staticBody; + b2Body_SetType( m_platformId, b2_staticBody ); + b2Body_SetType( m_secondAttachmentId, b2_staticBody ); + b2Body_SetType( m_secondPayloadId, b2_staticBody ); + b2Body_SetType( m_touchingBodyId, b2_staticBody ); + b2Body_SetType( m_floatingBodyId, b2_staticBody ); + } + + if ( ImGui::RadioButton( "Kinematic", m_type == b2_kinematicBody ) ) + { + m_type = b2_kinematicBody; + b2Body_SetType( m_platformId, b2_kinematicBody ); + b2Body_SetLinearVelocity( m_platformId, { -m_speed, 0.0f } ); + b2Body_SetAngularVelocity( m_platformId, 0.0f ); + b2Body_SetType( m_secondAttachmentId, b2_kinematicBody ); + b2Body_SetType( m_secondPayloadId, b2_kinematicBody ); + b2Body_SetType( m_touchingBodyId, b2_kinematicBody ); + b2Body_SetType( m_floatingBodyId, b2_kinematicBody ); + } + + if ( ImGui::RadioButton( "Dynamic", m_type == b2_dynamicBody ) ) + { + m_type = b2_dynamicBody; + b2Body_SetType( m_platformId, b2_dynamicBody ); + b2Body_SetType( m_secondAttachmentId, b2_dynamicBody ); + b2Body_SetType( m_secondPayloadId, b2_dynamicBody ); + b2Body_SetType( m_touchingBodyId, b2_dynamicBody ); + b2Body_SetType( m_floatingBodyId, b2_dynamicBody ); + } + + if ( ImGui::Checkbox( "Enable", &m_isEnabled ) ) + { + if ( m_isEnabled ) + { + b2Body_Enable( m_platformId ); + b2Body_Enable( m_secondAttachmentId ); + b2Body_Enable( m_secondPayloadId ); + b2Body_Enable( m_touchingBodyId ); + b2Body_Enable( m_floatingBodyId ); + + if ( m_type == b2_kinematicBody ) + { + b2Body_SetLinearVelocity( m_platformId, { -m_speed, 0.0f } ); + b2Body_SetAngularVelocity( m_platformId, 0.0f ); + } + } + else + { + b2Body_Disable( m_platformId ); + b2Body_Disable( m_secondAttachmentId ); + b2Body_Disable( m_secondPayloadId ); + b2Body_Disable( m_touchingBodyId ); + b2Body_Disable( m_floatingBodyId ); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + // Drive the kinematic body. + if ( m_type == b2_kinematicBody ) + { + b2Vec2 p = b2Body_GetPosition( m_platformId ); + b2Vec2 v = b2Body_GetLinearVelocity( m_platformId ); + + if ( ( p.x < -14.0f && v.x < 0.0f ) || ( p.x > 6.0f && v.x > 0.0f ) ) + { + v.x = -v.x; + b2Body_SetLinearVelocity( m_platformId, v ); + } + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BodyType( settings ); + } + + b2BodyId m_attachmentId; + b2BodyId m_secondAttachmentId; + b2BodyId m_platformId; + b2BodyId m_secondPayloadId; + b2BodyId m_touchingBodyId; + b2BodyId m_floatingBodyId; + b2BodyType m_type; + float m_speed; + bool m_isEnabled; +}; + +static int sampleBodyType = RegisterSample( "Bodies", "Body Type", BodyType::Create ); + +float FrictionCallback( float, int, float, int ) +{ + return 0.1f; +} + +float RestitutionCallback( float, int, float, int ) +{ + return 1.0f; +} + +class Weeble : public Sample +{ +public: + explicit Weeble( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.3f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + // Test friction and restitution callbacks + b2World_SetFrictionCallback( m_worldId, FrictionCallback ); + b2World_SetRestitutionCallback( m_worldId, RestitutionCallback ); + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Build weeble + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 3.0f }; + bodyDef.rotation = b2MakeRot( 0.25f * B2_PI ); + m_weebleId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, -1.0f }, { 0.0f, 1.0f }, 1.0f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateCapsuleShape( m_weebleId, &shapeDef, &capsule ); + + float mass = b2Body_GetMass( m_weebleId ); + float inertiaTensor = b2Body_GetRotationalInertia( m_weebleId ); + + float offset = 1.5f; + + // See: https://en.wikipedia.org/wiki/Parallel_axis_theorem + inertiaTensor += mass * offset * offset; + + b2MassData massData = { mass, { 0.0f, -offset }, inertiaTensor }; + b2Body_SetMassData( m_weebleId, massData ); + } + + m_explosionPosition = { 0.0f, 0.0f }; + m_explosionRadius = 2.0f; + m_explosionMagnitude = 8.0f; + } + + void UpdateGui() override + { + float height = 120.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + ImGui::Begin( "Weeble", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + if ( ImGui::Button( "Teleport" ) ) + { + b2Body_SetTransform( m_weebleId, { 0.0f, 5.0f }, b2MakeRot( 0.95 * B2_PI ) ); + } + + if ( ImGui::Button( "Explode" ) ) + { + b2ExplosionDef def = b2DefaultExplosionDef(); + def.position = m_explosionPosition; + def.radius = m_explosionRadius; + def.falloff = 0.1f; + def.impulsePerLength = m_explosionMagnitude; + b2World_Explode( m_worldId, &def ); + } + ImGui::PushItemWidth( 100.0f ); + + ImGui::SliderFloat( "Magnitude", &m_explosionMagnitude, -100.0f, 100.0f, "%.1f" ); + + ImGui::PopItemWidth(); + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawCircle( m_explosionPosition, m_explosionRadius, b2_colorAzure ); + + // This shows how to get the velocity of a point on a body + b2Vec2 localPoint = { 0.0f, 2.0f }; + b2Vec2 worldPoint = b2Body_GetWorldPoint( m_weebleId, localPoint ); + + b2Vec2 v1 = b2Body_GetLocalPointVelocity( m_weebleId, localPoint ); + b2Vec2 v2 = b2Body_GetWorldPointVelocity( m_weebleId, worldPoint ); + + b2Vec2 offset = { 0.05f, 0.0f }; + g_draw.DrawSegment( worldPoint, worldPoint + v1, b2_colorRed ); + g_draw.DrawSegment( worldPoint + offset, worldPoint + v2 + offset, b2_colorGreen ); + } + + static Sample* Create( Settings& settings ) + { + return new Weeble( settings ); + } + + b2BodyId m_weebleId; + b2Vec2 m_explosionPosition; + float m_explosionRadius; + float m_explosionMagnitude; +}; + +static int sampleWeeble = RegisterSample( "Bodies", "Weeble", Weeble::Create ); + +class Sleep : public Sample +{ +public: + explicit Sleep( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 3.0f, 50.0f }; + g_camera.m_zoom = 25.0f * 2.2f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.enableSensorEvents = true; + m_groundShapeId = b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Sleeping body with sensors + for ( int i = 0; i < 2; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -4.0f, 3.0f + 2.0f * i }; + bodyDef.isAwake = false; + bodyDef.enableSleep = true; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, 1.0f }, { 1.0f, 1.0f }, 0.75f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + capsule.radius = 1.0f; + m_sensorIds[i] = b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + m_sensorTouching[i] = false; + } + + // Sleeping body but sleep is disabled + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 3.0f }; + bodyDef.isAwake = false; + bodyDef.enableSleep = false; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Circle circle = { { 1.0f, 1.0f }, 1.0f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + + // Awake body and sleep is disabled + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 5.0f, 3.0f }; + bodyDef.isAwake = true; + bodyDef.enableSleep = false; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeOffsetBox( 1.0f, 1.0f, { 0.0f, 1.0f }, b2MakeRot( 0.25f * B2_PI ) ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // A sleeping body to test waking on collision + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 5.0f, 1.0f }; + bodyDef.isAwake = false; + bodyDef.enableSleep = true; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeSquare( 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // A long pendulum + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 100.0f }; + bodyDef.angularDamping = 0.5f; + bodyDef.sleepThreshold = 0.05f; + m_pendulumId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, 0.0f }, { 90.0f, 0.0f }, 0.25f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateCapsuleShape( m_pendulumId, &shapeDef, &capsule ); + + b2Vec2 pivot = bodyDef.position; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = m_pendulumId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + // A sleeping body to test waking on contact destroyed + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -10.0f, 1.0f }; + bodyDef.isAwake = false; + bodyDef.enableSleep = true; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeSquare( 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + m_staticBodyId = b2_nullBodyId; + } + + void ToggleInvoker() + { + if ( B2_IS_NULL( m_staticBodyId ) ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { -10.5f, 3.0f }; + m_staticBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeOffsetBox( 2.0f, 0.1f, { 0.0f, 0.0f }, b2MakeRot( 0.25f * B2_PI ) ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.invokeContactCreation = true; + b2CreatePolygonShape( m_staticBodyId, &shapeDef, &box ); + } + else + { + b2DestroyBody( m_staticBodyId ); + m_staticBodyId = b2_nullBodyId; + } + } + + void UpdateGui() override + { + float height = 160.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + ImGui::Begin( "Sleep", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 120.0f ); + + ImGui::Text( "Pendulum Tuning" ); + + float sleepVelocity = b2Body_GetSleepThreshold( m_pendulumId ); + if ( ImGui::SliderFloat( "sleep velocity", &sleepVelocity, 0.0f, 1.0f, "%.2f" ) ) + { + b2Body_SetSleepThreshold( m_pendulumId, sleepVelocity ); + b2Body_SetAwake( m_pendulumId, true ); + } + + float angularDamping = b2Body_GetAngularDamping( m_pendulumId ); + if ( ImGui::SliderFloat( "angular damping", &angularDamping, 0.0f, 2.0f, "%.2f" ) ) + { + b2Body_SetAngularDamping( m_pendulumId, angularDamping ); + } + + ImGui::PopItemWidth(); + + ImGui::Separator(); + + if ( B2_IS_NULL( m_staticBodyId ) ) + { + if ( ImGui::Button( "Create" ) ) + { + ToggleInvoker(); + } + } + else + { + if ( ImGui::Button( "Destroy" ) ) + { + ToggleInvoker(); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + // Detect sensors touching the ground + b2SensorEvents sensorEvents = b2World_GetSensorEvents( m_worldId ); + + for ( int i = 0; i < sensorEvents.beginCount; ++i ) + { + b2SensorBeginTouchEvent* event = sensorEvents.beginEvents + i; + if ( B2_ID_EQUALS( event->visitorShapeId, m_groundShapeId ) ) + { + if ( B2_ID_EQUALS( event->sensorShapeId, m_sensorIds[0] ) ) + { + m_sensorTouching[0] = true; + } + else if ( B2_ID_EQUALS( event->sensorShapeId, m_sensorIds[1] ) ) + { + m_sensorTouching[1] = true; + } + } + } + + for ( int i = 0; i < sensorEvents.endCount; ++i ) + { + b2SensorEndTouchEvent* event = sensorEvents.endEvents + i; + if ( B2_ID_EQUALS( event->visitorShapeId, m_groundShapeId ) ) + { + if ( B2_ID_EQUALS( event->sensorShapeId, m_sensorIds[0] ) ) + { + m_sensorTouching[0] = false; + } + else if ( B2_ID_EQUALS( event->sensorShapeId, m_sensorIds[1] ) ) + { + m_sensorTouching[1] = false; + } + } + } + + for ( int i = 0; i < 2; ++i ) + { + g_draw.DrawString( 5, m_textLine, "sensor touch %d = %s", i, m_sensorTouching[i] ? "true" : "false" ); + m_textLine += m_textIncrement; + } + } + + static Sample* Create( Settings& settings ) + { + return new Sleep( settings ); + } + + b2BodyId m_pendulumId; + b2BodyId m_staticBodyId; + b2ShapeId m_groundShapeId; + b2ShapeId m_sensorIds[2]; + bool m_sensorTouching[2]; +}; + +static int sampleSleep = RegisterSample( "Bodies", "Sleep", Sleep::Create ); + +class BadBody : public Sample +{ +public: + explicit BadBody( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.3f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Build a bad body + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 3.0f }; + bodyDef.angularVelocity = 0.5f; + bodyDef.rotation = b2MakeRot( 0.25f * B2_PI ); + + m_badBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, -1.0f }, { 0.0f, 1.0f }, 1.0f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // density set to zero intentionally to create a bad body + shapeDef.density = 0.0f; + b2CreateCapsuleShape( m_badBodyId, &shapeDef, &capsule ); + } + + // Build a normal body + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 2.0f, 3.0f }; + bodyDef.rotation = b2MakeRot( 0.25f * B2_PI ); + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Capsule capsule = { { 0.0f, -1.0f }, { 0.0f, 1.0f }, 1.0f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "A bad body is a dynamic body with no mass and behaves like a kinematic body." ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "Bad bodies are considered invalid and a user bug. Behavior is not guaranteed." ); + m_textLine += m_textIncrement; + + // For science + b2Body_ApplyForceToCenter( m_badBodyId, { 0.0f, 10.0f }, true ); + } + + static Sample* Create( Settings& settings ) + { + return new BadBody( settings ); + } + + b2BodyId m_badBodyId; +}; + +static int sampleBadBody = RegisterSample( "Bodies", "Bad", BadBody::Create ); + +// This shows how to set the initial angular velocity to get a specific movement. +class Pivot : public Sample +{ +public: + explicit Pivot( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.8f, 6.4f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Create a separate body on the ground + { + b2Vec2 v = { 5.0f, 0.0f }; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 3.0f }; + bodyDef.gravityScale = 1.0f; + bodyDef.linearVelocity = v; + + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + m_lever = 3.0f; + b2Vec2 r = { 0.0f, -m_lever }; + + float omega = b2Cross( v, r ) / b2Dot( r, r ); + b2Body_SetAngularVelocity( m_bodyId, omega ); + + b2Polygon box = b2MakeBox( 0.1f, m_lever ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2Vec2 v = b2Body_GetLinearVelocity( m_bodyId ); + float omega = b2Body_GetAngularVelocity( m_bodyId ); + b2Vec2 r = b2Body_GetWorldVector( m_bodyId, { 0.0f, -m_lever } ); + + b2Vec2 vp = v + b2CrossSV( omega, r ); + g_draw.DrawString( 5, m_textLine, "pivot velocity = (%g, %g)", vp.x, vp.y ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new Pivot( settings ); + } + + b2BodyId m_bodyId; + float m_lever; +}; + +static int samplePivot = RegisterSample( "Bodies", "Pivot", Pivot::Create ); + +// This shows how to drive a kinematic body to reach a target +class Kinematic : public Sample +{ +public: + explicit Kinematic( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 4.0f; + } + + m_amplitude = 2.0f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position.x = 2.0f * m_amplitude; + + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.1f, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + + m_time = 0.0f; + } + + void Step( Settings& settings ) override + { + float timeStep = settings.hertz > 0.0f ? 1.0f / settings.hertz : 0.0f; + if ( settings.pause && settings.singleStep == false ) + { + timeStep = 0.0f; + } + + if ( timeStep > 0.0f ) + { + b2Vec2 point = { + .x = 2.0f * m_amplitude * cosf( m_time ), + .y = m_amplitude * sinf( 2.0f * m_time ), + }; + b2Rot rotation = b2MakeRot( 2.0f * m_time ); + + b2Vec2 axis = b2RotateVector( rotation, { 0.0f, 1.0f } ); + g_draw.DrawSegment( point - 0.5f * axis, point + 0.5f * axis, b2_colorPlum ); + g_draw.DrawPoint( point, 10.0f, b2_colorPlum ); + + b2Body_SetTargetTransform( m_bodyId, { point, rotation }, timeStep ); + } + + Sample::Step( settings ); + + m_time += timeStep; + } + + static Sample* Create( Settings& settings ) + { + return new Kinematic( settings ); + } + + b2BodyId m_bodyId; + float m_amplitude; + float m_time; +}; + +static int sampleKinematic = RegisterSample( "Bodies", "Kinematic", Kinematic::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_character.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_character.cpp new file mode 100644 index 000000000000..e7268564fc38 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_character.cpp @@ -0,0 +1,636 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include + +struct ShapeUserData +{ + float maxPush; + bool clipVelocity; +}; + +enum CollisionBits : uint64_t +{ + StaticBit = 0x0001, + MoverBit = 0x0002, + DynamicBit = 0x0004, + DebrisBit = 0x0008, + + AllBits = ~0u, +}; + +enum PogoShape +{ + PogoPoint, + PogoCircle, + PogoSegment +}; + +struct CastResult +{ + b2Vec2 point; + b2BodyId bodyId; + float fraction; + bool hit; +}; + +static float CastCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + CastResult* result = (CastResult*)context; + result->point = point; + result->bodyId = b2Shape_GetBody( shapeId ); + result->fraction = fraction; + result->hit = true; + return fraction; +} + +class Mover : public Sample +{ +public: + explicit Mover( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 20.0f, 9.0f }; + g_camera.m_zoom = 10.0f; + } + + settings.drawJoints = false; + m_transform = { { 2.0f, 8.0f }, b2Rot_identity }; + m_velocity = { 0.0f, 0.0f }; + m_capsule = { { 0.0f, -0.5f }, { 0.0f, 0.5f }, 0.3f }; + + b2BodyId groundId1; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 0.0f }; + groundId1 = b2CreateBody( m_worldId, &bodyDef ); + + const char* path = + "M 2.6458333,201.08333 H 293.68751 v -47.625 h -2.64584 l -10.58333,7.9375 -13.22916,7.9375 -13.24648,5.29167 " + "-31.73269,7.9375 -21.16667,2.64583 -23.8125,10.58333 H 142.875 v -5.29167 h -5.29166 v 5.29167 H 119.0625 v " + "-2.64583 h -2.64583 v -2.64584 h -2.64584 v -2.64583 H 111.125 v -2.64583 H 84.666668 v -2.64583 h -5.291666 v " + "-2.64584 h -5.291667 v -2.64583 H 68.791668 V 174.625 h -5.291666 v -2.64584 H 52.916669 L 39.6875,177.27083 H " + "34.395833 L 23.8125,185.20833 H 15.875 L 5.2916669,187.85416 V 153.45833 H 2.6458333 v 47.625"; + + b2Vec2 points[64]; + + b2Vec2 offset = { -50.0f, -200.0f }; + float scale = 0.2f; + + int count = ParsePath( path, offset, points, 64, scale, false ); + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + + b2CreateChain( groundId1, &chainDef ); + } + + b2BodyId groundId2; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 98.0f, 0.0f }; + groundId2 = b2CreateBody( m_worldId, &bodyDef ); + + const char* path = + "M 2.6458333,201.08333 H 293.68751 l 0,-23.8125 h -23.8125 l 21.16667,21.16667 h -23.8125 l -39.68751,-13.22917 " + "-26.45833,7.9375 -23.8125,2.64583 h -13.22917 l -0.0575,2.64584 h -5.29166 v -2.64583 l -7.86855,-1e-5 " + "-0.0114,-2.64583 h -2.64583 l -2.64583,2.64584 h -7.9375 l -2.64584,2.64583 -2.58891,-2.64584 h -13.28609 v " + "-2.64583 h -2.64583 v -2.64584 l -5.29167,1e-5 v -2.64583 h -2.64583 v -2.64583 l -5.29167,-1e-5 v -2.64583 h " + "-2.64583 v -2.64584 h -5.291667 v -2.64583 H 92.60417 V 174.625 h -5.291667 v -2.64584 l -34.395835,1e-5 " + "-7.9375,-2.64584 -7.9375,-2.64583 -5.291667,-5.29167 H 21.166667 L 13.229167,158.75 5.2916668,153.45833 H " + "2.6458334 l -10e-8,47.625"; + + b2Vec2 points[64]; + + b2Vec2 offset = { 0.0f, -200.0f }; + float scale = 0.2f; + + int count = ParsePath( path, offset, points, 64, scale, false ); + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + + b2CreateChain( groundId2, &chainDef ); + } + + { + b2Polygon box = b2MakeBox( 0.5f, 0.125f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.maxMotorTorque = 10.0f; + jointDef.enableMotor = true; + jointDef.hertz = 3.0f; + jointDef.dampingRatio = 0.8f; + jointDef.enableSpring = true; + + float xBase = 48.7f; + float yBase = 9.2f; + int count = 50; + b2BodyId prevBodyId = groundId1; + for ( int i = 0; i < count; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { xBase + 0.5f + 1.0f * i, yBase }; + bodyDef.angularDamping = 0.2f; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { xBase + 1.0f * i, yBase }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + b2CreateRevoluteJoint( m_worldId, &jointDef ); + + prevBodyId = bodyId; + } + + b2Vec2 pivot = { xBase + 1.0f * count, yBase }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = groundId2; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 32.0f, 4.5f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + m_friendlyShape.maxPush = 0.025f; + m_friendlyShape.clipVelocity = false; + + shapeDef.filter = { MoverBit, AllBits, 0 }; + shapeDef.userData = &m_friendlyShape; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId, &shapeDef, &m_capsule ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 7.0f, 7.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter = { DebrisBit, AllBits, 0 }; + shapeDef.material.restitution = 0.7f; + shapeDef.material.rollingResistance = 0.2f; + + b2Circle circle = { b2Vec2_zero, 0.3f }; + m_ballId = b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position = { m_elevatorBase.x, m_elevatorBase.y - m_elevatorAmplitude }; + m_elevatorId = b2CreateBody( m_worldId, &bodyDef ); + + m_elevatorShape = { + .maxPush = 0.1f, + .clipVelocity = true, + }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter = { DynamicBit, AllBits, 0 }; + shapeDef.userData = &m_elevatorShape; + + b2Polygon box = b2MakeBox( 2.0f, 0.1f ); + b2CreatePolygonShape( m_elevatorId, &shapeDef, &box ); + } + + m_totalIterations = 0; + m_pogoVelocity = 0.0f; + m_onGround = false; + m_jumpReleased = true; + m_lockCamera = true; + m_planeCount = 0; + m_time = 0.0f; + } + + // https://github.com/id-Software/Quake/blob/master/QW/client/pmove.c#L390 + void SolveMove( float timeStep, float throttle ) + { + // Friction + float speed = b2Length( m_velocity ); + if ( speed < m_minSpeed ) + { + m_velocity.x = 0.0f; + m_velocity.y = 0.0f; + } + else if ( m_onGround ) + { + // Linear damping above stopSpeed and fixed reduction below stopSpeed + float control = speed < m_stopSpeed ? m_stopSpeed : speed; + + // friction has units of 1/time + float drop = control * m_friction * timeStep; + float newSpeed = b2MaxFloat( 0.0f, speed - drop ); + m_velocity *= newSpeed / speed; + } + + b2Vec2 desiredVelocity = { m_maxSpeed * throttle, 0.0f }; + float desiredSpeed; + b2Vec2 desiredDirection = b2GetLengthAndNormalize( &desiredSpeed, desiredVelocity ); + + if ( desiredSpeed > m_maxSpeed ) + { + desiredSpeed = m_maxSpeed; + } + + if ( m_onGround ) + { + m_velocity.y = 0.0f; + } + + // Accelerate + float currentSpeed = b2Dot( m_velocity, desiredDirection ); + float addSpeed = desiredSpeed - currentSpeed; + if ( addSpeed > 0.0f ) + { + float steer = m_onGround ? 1.0f : m_airSteer; + float accelSpeed = steer * m_accelerate * m_maxSpeed * timeStep; + if ( accelSpeed > addSpeed ) + { + accelSpeed = addSpeed; + } + + m_velocity += accelSpeed * desiredDirection; + } + + m_velocity.y -= m_gravity * timeStep; + + float pogoRestLength = 3.0f * m_capsule.radius; + float rayLength = pogoRestLength + m_capsule.radius; + b2Vec2 origin = b2TransformPoint( m_transform, m_capsule.center1 ); + b2Circle circle = { origin, 0.5f * m_capsule.radius }; + b2Vec2 segmentOffset = { 0.75f * m_capsule.radius, 0.0f }; + b2Segment segment = { + .point1 = origin - segmentOffset, + .point2 = origin + segmentOffset, + }; + + b2ShapeProxy proxy = {}; + b2Vec2 translation; + b2QueryFilter pogoFilter = { MoverBit, StaticBit | DynamicBit }; + CastResult castResult = {}; + + if ( m_pogoShape == PogoPoint ) + { + proxy = b2MakeProxy( &origin, 1, 0.0f ); + translation = { 0.0f, -rayLength }; + } + else if ( m_pogoShape == PogoCircle ) + { + proxy = b2MakeProxy( &origin, 1, circle.radius ); + translation = { 0.0f, -rayLength + circle.radius }; + } + else + { + proxy = b2MakeProxy( &segment.point1, 2, 0.0f ); + translation = { 0.0f, -rayLength }; + } + + b2World_CastShape( m_worldId, &proxy, translation, pogoFilter, CastCallback, &castResult ); + + // Avoid snapping to ground if still going up + if ( m_onGround == false ) + { + m_onGround = castResult.hit && m_velocity.y <= 0.01f; + } + else + { + m_onGround = castResult.hit; + } + + if ( castResult.hit == false ) + { + m_pogoVelocity = 0.0f; + + b2Vec2 delta = translation; + g_draw.DrawSegment( origin, origin + delta, b2_colorGray ); + + if ( m_pogoShape == PogoPoint ) + { + g_draw.DrawPoint( origin + delta, 10.0f, b2_colorGray ); + } + else if ( m_pogoShape == PogoCircle ) + { + g_draw.DrawCircle( origin + delta, circle.radius, b2_colorGray ); + } + else + { + g_draw.DrawSegment( segment.point1 + delta, segment.point2 + delta, b2_colorGray ); + } + } + else + { + float pogoCurrentLength = castResult.fraction * rayLength; + + float zeta = m_pogoDampingRatio; + float hertz = m_pogoHertz; + float omega = 2.0f * B2_PI * hertz; + float omegaH = omega * timeStep; + + m_pogoVelocity = ( m_pogoVelocity - omega * omegaH * ( pogoCurrentLength - pogoRestLength ) ) / + ( 1.0f + 2.0f * zeta * omegaH + omegaH * omegaH ); + + b2Vec2 delta = castResult.fraction * translation; + g_draw.DrawSegment( origin, origin + delta, b2_colorGray ); + + if ( m_pogoShape == PogoPoint ) + { + g_draw.DrawPoint( origin + delta, 10.0f, b2_colorPlum ); + } + else if ( m_pogoShape == PogoCircle ) + { + g_draw.DrawCircle( origin + delta, circle.radius, b2_colorPlum ); + } + else + { + g_draw.DrawSegment( segment.point1 + delta, segment.point2 + delta, b2_colorPlum ); + } + + b2Body_ApplyForce( castResult.bodyId, { 0.0f, -50.0f }, castResult.point, true ); + } + + b2Vec2 target = m_transform.p + timeStep * m_velocity + timeStep * m_pogoVelocity * b2Vec2{ 0.0f, 1.0f }; + + // Mover overlap filter + b2QueryFilter collideFilter = { MoverBit, StaticBit | DynamicBit | MoverBit }; + + // Movers don't sweep against other movers, allows for soft collision + b2QueryFilter castFilter = { MoverBit, StaticBit | DynamicBit }; + + m_totalIterations = 0; + float tolerance = 0.01f; + + for ( int iteration = 0; iteration < 5; ++iteration ) + { + m_planeCount = 0; + + b2Capsule mover; + mover.center1 = b2TransformPoint( m_transform, m_capsule.center1 ); + mover.center2 = b2TransformPoint( m_transform, m_capsule.center2 ); + mover.radius = m_capsule.radius; + + b2World_CollideMover( m_worldId, &mover, collideFilter, PlaneResultFcn, this ); + b2PlaneSolverResult result = b2SolvePlanes( target, m_planes, m_planeCount ); + + m_totalIterations += result.iterationCount; + + b2Vec2 moverTranslation = result.position - m_transform.p; + + float fraction = b2World_CastMover( m_worldId, &mover, moverTranslation, castFilter ); + + b2Vec2 delta = fraction * moverTranslation; + m_transform.p += delta; + + if ( b2LengthSquared( delta ) < tolerance * tolerance ) + { + break; + } + } + + m_velocity = b2ClipVector( m_velocity, m_planes, m_planeCount ); + } + + void UpdateGui() override + { + float height = 350.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 25.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 340.0f, height ) ); + + ImGui::Begin( "Mover", nullptr, 0 ); + + ImGui::PushItemWidth( 240.0f ); + + ImGui::SliderFloat( "Jump Speed", &m_jumpSpeed, 0.0f, 40.0f, "%.0f" ); + ImGui::SliderFloat( "Min Speed", &m_minSpeed, 0.0f, 1.0f, "%.2f" ); + ImGui::SliderFloat( "Max Speed", &m_maxSpeed, 0.0f, 20.0f, "%.0f" ); + ImGui::SliderFloat( "Stop Speed", &m_stopSpeed, 0.0f, 10.0f, "%.1f" ); + ImGui::SliderFloat( "Accelerate", &m_accelerate, 0.0f, 100.0f, "%.0f" ); + ImGui::SliderFloat( "Friction", &m_friction, 0.0f, 10.0f, "%.1f" ); + ImGui::SliderFloat( "Gravity", &m_gravity, 0.0f, 100.0f, "%.1f" ); + ImGui::SliderFloat( "Air Steer", &m_airSteer, 0.0f, 1.0f, "%.2f" ); + ImGui::SliderFloat( "Pogo Hertz", &m_pogoHertz, 0.0f, 30.0f, "%.0f" ); + ImGui::SliderFloat( "Pogo Damping", &m_pogoDampingRatio, 0.0f, 4.0f, "%.1f" ); + + ImGui::PopItemWidth(); + + ImGui::Separator(); + + ImGui::Text( "Pogo Shape" ); + ImGui::RadioButton( "Point", &m_pogoShape, PogoPoint ); + ImGui::SameLine(); + ImGui::RadioButton( "Circle", &m_pogoShape, PogoCircle ); + ImGui::SameLine(); + ImGui::RadioButton( "Segment", &m_pogoShape, PogoSegment ); + + ImGui::Checkbox( "Lock Camera", &m_lockCamera ); + + ImGui::End(); + } + + static bool PlaneResultFcn( b2ShapeId shapeId, const b2PlaneResult* planeResult, void* context ) + { + assert( planeResult->hit == true ); + + Mover* self = static_cast( context ); + float maxPush = FLT_MAX; + bool clipVelocity = true; + ShapeUserData* userData = static_cast( (void*)b2Shape_GetUserData( shapeId ) ); + if ( userData != nullptr ) + { + maxPush = userData->maxPush; + clipVelocity = userData->clipVelocity; + } + + if ( self->m_planeCount < m_planeCapacity ) + { + assert( b2IsValidPlane( planeResult->plane ) ); + self->m_planes[self->m_planeCount] = { planeResult->plane, maxPush, 0.0f, clipVelocity }; + self->m_planeCount += 1; + } + + return true; + } + + static bool Kick( b2ShapeId shapeId, void* context ) + { + Mover* self = (Mover*)context; + b2BodyId bodyId = b2Shape_GetBody( shapeId ); + b2BodyType type = b2Body_GetType( bodyId ); + + if ( type != b2_dynamicBody ) + { + return true; + } + + b2Vec2 center = b2Body_GetWorldCenterOfMass( bodyId ); + b2Vec2 direction = b2Normalize( center - self->m_transform.p ); + b2Vec2 impulse = b2Vec2{ 2.0f * direction.x, 2.0f }; + b2Body_ApplyLinearImpulseToCenter( bodyId, impulse, true ); + + return true; + } + + void Keyboard( int key ) override + { + if ( key == 'K' ) + { + b2Vec2 point = b2TransformPoint( m_transform, { 0.0f, m_capsule.center1.y - 3.0f * m_capsule.radius } ); + b2Circle circle = { point, 0.5f }; + b2ShapeProxy proxy = b2MakeProxy( &circle.center, 1, circle.radius ); + b2QueryFilter filter = { MoverBit, DebrisBit }; + b2World_OverlapShape( m_worldId, &proxy, filter, Kick, this ); + g_draw.DrawCircle( circle.center, circle.radius, b2_colorGoldenRod ); + } + + Sample::Keyboard( key ); + } + + void Step( Settings& settings ) override + { + bool pause = false; + if ( settings.pause ) + { + pause = settings.singleStep != true; + } + + float timeStep = settings.hertz > 0.0f ? 1.0f / settings.hertz : 0.0f; + if ( pause ) + { + timeStep = 0.0f; + } + + if ( timeStep > 0.0f ) + { + b2Vec2 point = { + .x = m_elevatorBase.x, + .y = m_elevatorAmplitude * cosf( 1.0f * m_time + B2_PI ) + m_elevatorBase.y, + }; + + b2Body_SetTargetTransform( m_elevatorId, { point, b2Rot_identity }, timeStep ); + } + + m_time += timeStep; + + Sample::Step( settings ); + + if ( pause == false ) + { + float throttle = 0.0f; + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) ) + { + throttle -= 1.0f; + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) ) + { + throttle += 1.0f; + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_SPACE ) ) + { + if ( m_onGround == true && m_jumpReleased ) + { + m_velocity.y = m_jumpSpeed; + m_onGround = false; + m_jumpReleased = false; + } + } + else + { + m_jumpReleased = true; + } + + SolveMove( timeStep, throttle ); + } + + int count = m_planeCount; + for ( int i = 0; i < count; ++i ) + { + b2Plane plane = m_planes[i].plane; + b2Vec2 p1 = m_transform.p + ( plane.offset - m_capsule.radius ) * plane.normal; + b2Vec2 p2 = p1 + 0.1f * plane.normal; + g_draw.DrawPoint( p1, 5.0f, b2_colorYellow ); + g_draw.DrawSegment( p1, p2, b2_colorYellow ); + } + + b2Vec2 p1 = b2TransformPoint( m_transform, m_capsule.center1 ); + b2Vec2 p2 = b2TransformPoint( m_transform, m_capsule.center2 ); + + b2HexColor color = m_onGround ? b2_colorOrange : b2_colorAquamarine; + g_draw.DrawSolidCapsule( p1, p2, m_capsule.radius, color ); + g_draw.DrawSegment( m_transform.p, m_transform.p + m_velocity, b2_colorPurple ); + + b2Vec2 p = m_transform.p; + DrawTextLine( "position %.2f %.2f", p.x, p.y ); + DrawTextLine( "velocity %.2f %.2f", m_velocity.x, m_velocity.y ); + DrawTextLine( "iterations %d", m_totalIterations ); + + if ( m_lockCamera ) + { + g_camera.m_center.x = m_transform.p.x; + } + } + + static Sample* Create( Settings& settings ) + { + return new Mover( settings ); + } + + static constexpr int m_planeCapacity = 8; + static constexpr b2Vec2 m_elevatorBase = { 112.0f, 10.0f }; + static constexpr float m_elevatorAmplitude = 4.0f; + + float m_jumpSpeed = 10.0f; + float m_maxSpeed = 6.0f; + float m_minSpeed = 0.1f; + float m_stopSpeed = 3.0f; + float m_accelerate = 20.0f; + float m_airSteer = 0.2f; + float m_friction = 8.0f; + float m_gravity = 30.0f; + float m_pogoHertz = 5.0f; + float m_pogoDampingRatio = 0.8f; + + int m_pogoShape = PogoSegment; + b2Transform m_transform; + b2Vec2 m_velocity; + b2Capsule m_capsule; + b2BodyId m_elevatorId; + b2ShapeId m_ballId; + ShapeUserData m_friendlyShape; + ShapeUserData m_elevatorShape; + b2CollisionPlane m_planes[m_planeCapacity] = {}; + int m_planeCount; + int m_totalIterations; + float m_pogoVelocity; + float m_time; + bool m_onGround; + bool m_jumpReleased; + bool m_lockCamera; +}; + +static int sampleMover = RegisterSample( "Character", "Mover", Mover::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_collision.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_collision.cpp new file mode 100644 index 000000000000..1c880422c777 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_collision.cpp @@ -0,0 +1,3669 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/collision.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +class ShapeDistance : public Sample +{ +public: + enum ShapeType + { + e_point, + e_segment, + e_triangle, + e_box + }; + + explicit ShapeDistance( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 3.0f; + } + + m_point = b2Vec2_zero; + m_segment = { { -0.5f, 0.0f }, { 0.5f, 0.0f } }; + + { + b2Vec2 points[3] = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, { 0.0f, 1.0f } }; + b2Hull hull = b2ComputeHull( points, 3 ); + m_triangle = b2MakePolygon( &hull, 0.0f ); + + // m_triangle = b2MakeSquare( 0.4f ); + } + + m_box = b2MakeSquare( 0.5f ); + + // m_transform = { { 1.5f, -1.5f }, b2Rot_identity }; + m_transform = { { 0.0f, 0.0f }, b2Rot_identity }; + m_angle = 0.0f; + + m_cache = b2_emptySimplexCache; + m_simplexCount = 0; + m_startPoint = { 0.0f, 0.0f }; + m_basePosition = { 0.0f, 0.0f }; + m_baseAngle = 0.0f; + + m_dragging = false; + m_rotating = false; + m_showIndices = false; + m_useCache = false; + m_drawSimplex = false; + + m_typeA = e_box; + m_typeB = e_box; + m_radiusA = 0.0f; + m_radiusB = 0.0f; + + m_proxyA = MakeProxy( m_typeA, m_radiusA ); + m_proxyB = MakeProxy( m_typeB, m_radiusB ); + } + + b2ShapeProxy MakeProxy( ShapeType type, float radius ) + { + b2ShapeProxy proxy = {}; + proxy.radius = radius; + + switch ( type ) + { + case e_point: + proxy.points[0] = b2Vec2_zero; + proxy.count = 1; + break; + + case e_segment: + proxy.points[0] = m_segment.point1; + proxy.points[1] = m_segment.point2; + proxy.count = 2; + break; + + case e_triangle: + for ( int i = 0; i < m_triangle.count; ++i ) + { + proxy.points[i] = m_triangle.vertices[i]; + } + proxy.count = m_triangle.count; + break; + + case e_box: + proxy.points[0] = m_box.vertices[0]; + proxy.points[1] = m_box.vertices[1]; + proxy.points[2] = m_box.vertices[2]; + proxy.points[3] = m_box.vertices[3]; + proxy.count = 4; + break; + + default: + assert( false ); + } + + return proxy; + } + + void DrawShape( ShapeType type, b2Transform transform, float radius, b2HexColor color ) + { + switch ( type ) + { + case e_point: + { + b2Vec2 p = b2TransformPoint( transform, m_point ); + if ( radius > 0.0f ) + { + g_draw.DrawSolidCircle( transform, m_point, radius, color ); + } + else + { + g_draw.DrawPoint( p, 5.0f, color ); + } + } + break; + + case e_segment: + { + b2Vec2 p1 = b2TransformPoint( transform, m_segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform, m_segment.point2 ); + + if ( radius > 0.0f ) + { + g_draw.DrawSolidCapsule( p1, p2, radius, color ); + } + else + { + g_draw.DrawSegment( p1, p2, color ); + } + } + break; + + case e_triangle: + g_draw.DrawSolidPolygon( transform, m_triangle.vertices, m_triangle.count, radius, color ); + break; + + case e_box: + g_draw.DrawSolidPolygon( transform, m_box.vertices, m_box.count, radius, color ); + break; + + default: + assert( false ); + } + } + + void UpdateGui() override + { + float height = 310.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Shape Distance", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + const char* shapeTypes[] = { "point", "segment", "triangle", "box" }; + int shapeType = int( m_typeA ); + if ( ImGui::Combo( "shape A", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_typeA = ShapeType( shapeType ); + m_proxyA = MakeProxy( m_typeA, m_radiusA ); + } + + if ( ImGui::SliderFloat( "radius A", &m_radiusA, 0.0f, 0.5f, "%.2f" ) ) + { + m_proxyA.radius = m_radiusA; + } + + shapeType = int( m_typeB ); + if ( ImGui::Combo( "shape B", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_typeB = ShapeType( shapeType ); + m_proxyB = MakeProxy( m_typeB, m_radiusB ); + } + + if ( ImGui::SliderFloat( "radius B", &m_radiusB, 0.0f, 0.5f, "%.2f" ) ) + { + m_proxyB.radius = m_radiusB; + } + + ImGui::Separator(); + + ImGui::SliderFloat( "x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f" ); + ImGui::SliderFloat( "y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f" ); + + if ( ImGui::SliderFloat( "angle", &m_angle, -B2_PI, B2_PI, "%.2f" ) ) + { + m_transform.q = b2MakeRot( m_angle ); + } + + ImGui::Separator(); + + ImGui::Checkbox( "show indices", &m_showIndices ); + ImGui::Checkbox( "use cache", &m_useCache ); + + ImGui::Separator(); + + if ( ImGui::Checkbox( "draw simplex", &m_drawSimplex ) ) + { + m_simplexIndex = 0; + } + + if ( m_drawSimplex ) + { + ImGui::SliderInt( "index", &m_simplexIndex, 0, m_simplexCount - 1 ); + m_simplexIndex = b2ClampInt( m_simplexIndex, 0, m_simplexCount - 1 ); + } + + ImGui::End(); + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_rotating == false ) + { + m_dragging = true; + m_startPoint = p; + m_basePosition = m_transform.p; + } + else if ( mods == GLFW_MOD_SHIFT && m_dragging == false ) + { + m_rotating = true; + m_startPoint = p; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_transform.p = m_basePosition + 0.5f * ( p - m_startPoint ); + } + else if ( m_rotating ) + { + float dx = p.x - m_startPoint.x; + m_angle = b2ClampFloat( m_baseAngle + 1.0f * dx, -B2_PI, B2_PI ); + m_transform.q = b2MakeRot( m_angle ); + } + } + + static b2Vec2 Weight2( float a1, b2Vec2 w1, float a2, b2Vec2 w2 ) + { + return { a1 * w1.x + a2 * w2.x, a1 * w1.y + a2 * w2.y }; + } + + static b2Vec2 Weight3( float a1, b2Vec2 w1, float a2, b2Vec2 w2, float a3, b2Vec2 w3 ) + { + return { a1 * w1.x + a2 * w2.x + a3 * w3.x, a1 * w1.y + a2 * w2.y + a3 * w3.y }; + } + + void ComputeSimplexWitnessPoints( b2Vec2* a, b2Vec2* b, const b2Simplex* s ) + { + switch ( s->count ) + { + case 0: + assert( false ); + break; + + case 1: + *a = s->v1.wA; + *b = s->v1.wB; + break; + + case 2: + *a = Weight2( s->v1.a, s->v1.wA, s->v2.a, s->v2.wA ); + *b = Weight2( s->v1.a, s->v1.wB, s->v2.a, s->v2.wB ); + break; + + case 3: + *a = Weight3( s->v1.a, s->v1.wA, s->v2.a, s->v2.wA, s->v3.a, s->v3.wA ); + *b = *a; + break; + + default: + assert( false ); + break; + } + } + + void Step( Settings& ) override + { + b2DistanceInput input; + input.proxyA = m_proxyA; + input.proxyB = m_proxyB; + input.transformA = b2Transform_identity; + input.transformB = m_transform; + input.useRadii = true || m_radiusA > 0.0f || m_radiusB > 0.0f; + + if ( m_useCache == false ) + { + m_cache.count = 0; + } + + b2DistanceOutput output = b2ShapeDistance( &input, &m_cache, m_simplexes, m_simplexCapacity ); + + m_simplexCount = output.simplexCount; + + DrawShape( m_typeA, b2Transform_identity, m_radiusA, b2_colorCyan ); + DrawShape( m_typeB, m_transform, m_radiusB, b2_colorBisque ); + + if ( m_drawSimplex ) + { + b2Simplex* simplex = m_simplexes + m_simplexIndex; + b2SimplexVertex* vertices[3] = { &simplex->v1, &simplex->v2, &simplex->v3 }; + + if ( m_simplexIndex > 0 ) + { + // The first recorded simplex does not have valid barycentric coordinates + b2Vec2 pointA, pointB; + ComputeSimplexWitnessPoints( &pointA, &pointB, simplex ); + + g_draw.DrawSegment( pointA, pointB, b2_colorWhite ); + g_draw.DrawPoint( pointA, 10.0f, b2_colorWhite ); + g_draw.DrawPoint( pointB, 10.0f, b2_colorWhite ); + } + + b2HexColor colors[3] = { b2_colorRed, b2_colorGreen, b2_colorBlue }; + + for ( int i = 0; i < simplex->count; ++i ) + { + b2SimplexVertex* vertex = vertices[i]; + g_draw.DrawPoint( vertex->wA, 10.0f, colors[i] ); + g_draw.DrawPoint( vertex->wB, 10.0f, colors[i] ); + } + } + else + { + g_draw.DrawSegment( output.pointA, output.pointB, b2_colorDimGray ); + g_draw.DrawPoint( output.pointA, 10.0f, b2_colorWhite ); + g_draw.DrawPoint( output.pointB, 10.0f, b2_colorWhite ); + + g_draw.DrawSegment( output.pointA, output.pointA + 0.5f * output.normal, b2_colorYellow ); + } + + if ( m_showIndices ) + { + for ( int i = 0; i < m_proxyA.count; ++i ) + { + b2Vec2 p = m_proxyA.points[i]; + g_draw.DrawString( p, " %d", i ); + } + + for ( int i = 0; i < m_proxyB.count; ++i ) + { + b2Vec2 p = b2TransformPoint( m_transform, m_proxyB.points[i] ); + g_draw.DrawString( p, " %d", i ); + } + } + + g_draw.DrawString( 5, m_textLine, "mouse button 1: drag" ); + m_textLine += m_textIncrement; + g_draw.DrawString( 5, m_textLine, "mouse button 1 + shift: rotate" ); + m_textLine += m_textIncrement; + g_draw.DrawString( 5, m_textLine, "distance = %.2f, iterations = %d", output.distance, output.iterations ); + m_textLine += m_textIncrement; + + if ( m_cache.count == 1 ) + { + g_draw.DrawString( 5, m_textLine, "cache = {%d}, {%d}", m_cache.indexA[0], m_cache.indexB[0] ); + } + else if ( m_cache.count == 2 ) + { + g_draw.DrawString( 5, m_textLine, "cache = {%d, %d}, {%d, %d}", m_cache.indexA[0], m_cache.indexA[1], + m_cache.indexB[0], m_cache.indexB[1] ); + } + else if ( m_cache.count == 3 ) + { + g_draw.DrawString( 5, m_textLine, "cache = {%d, %d, %d}, {%d, %d, %d}", m_cache.indexA[0], m_cache.indexA[1], + m_cache.indexA[2], m_cache.indexB[0], m_cache.indexB[1], m_cache.indexB[2] ); + } + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new ShapeDistance( settings ); + } + + static constexpr int m_simplexCapacity = 20; + + b2Polygon m_box; + b2Polygon m_triangle; + b2Vec2 m_point; + b2Segment m_segment; + + ShapeType m_typeA; + ShapeType m_typeB; + float m_radiusA; + float m_radiusB; + b2ShapeProxy m_proxyA; + b2ShapeProxy m_proxyB; + + b2SimplexCache m_cache; + b2Simplex m_simplexes[m_simplexCapacity]; + int m_simplexCount; + int m_simplexIndex; + + b2Transform m_transform; + float m_angle; + + b2Vec2 m_basePosition; + b2Vec2 m_startPoint; + float m_baseAngle; + + bool m_dragging; + bool m_rotating; + bool m_showIndices; + bool m_useCache; + bool m_drawSimplex; +}; + +static int sampleShapeDistance = RegisterSample( "Collision", "Shape Distance", ShapeDistance::Create ); + +enum UpdateType +{ + Update_Incremental = 0, + Update_FullRebuild = 1, + Update_PartialRebuild = 2, +}; + +struct Proxy +{ + b2AABB box; + b2AABB fatBox; + b2Vec2 position; + b2Vec2 width; + int proxyId; + int rayStamp; + int queryStamp; + bool moved; +}; + +static bool QueryCallback( int32_t proxyId, uint64_t userData, void* context ); +static float RayCallback( const b2RayCastInput* input, int32_t proxyId, uint64_t userData, void* context ); + +// Tests the Box2D bounding volume hierarchy (BVH). The dynamic tree +// can be used independently as a spatial data structure. +class DynamicTree : public Sample +{ +public: + explicit DynamicTree( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 500.0f, 500.0f }; + g_camera.m_zoom = 25.0f * 21.0f; + } + + m_fill = 0.25f; + m_moveFraction = 0.05f; + m_moveDelta = 0.1f; + m_proxies = nullptr; + m_proxyCount = 0; + m_proxyCapacity = 0; + m_ratio = 5.0f; + m_grid = 1.0f; + + m_moveBuffer = nullptr; + m_moveCount = 0; + + m_rowCount = g_sampleDebug ? 100 : 1000; + m_columnCount = g_sampleDebug ? 100 : 1000; + memset( &m_tree, 0, sizeof( m_tree ) ); + BuildTree(); + m_timeStamp = 0; + m_updateType = Update_Incremental; + + m_startPoint = { 0.0f, 0.0f }; + m_endPoint = { 0.0f, 0.0f }; + m_queryDrag = false; + m_rayDrag = false; + m_validate = true; + } + + ~DynamicTree() override + { + free( m_proxies ); + free( m_moveBuffer ); + b2DynamicTree_Destroy( &m_tree ); + } + + void BuildTree() + { + b2DynamicTree_Destroy( &m_tree ); + free( m_proxies ); + free( m_moveBuffer ); + + m_proxyCapacity = m_rowCount * m_columnCount; + m_proxies = static_cast( malloc( m_proxyCapacity * sizeof( Proxy ) ) ); + m_proxyCount = 0; + + m_moveBuffer = static_cast( malloc( m_proxyCapacity * sizeof( int ) ) ); + m_moveCount = 0; + + float y = -4.0f; + + m_tree = b2DynamicTree_Create(); + + const b2Vec2 aabbMargin = { 0.1f, 0.1f }; + + for ( int i = 0; i < m_rowCount; ++i ) + { + float x = -40.0f; + + for ( int j = 0; j < m_columnCount; ++j ) + { + float fillTest = RandomFloatRange( 0.0f, 1.0f ); + if ( fillTest <= m_fill ) + { + assert( m_proxyCount <= m_proxyCapacity ); + Proxy* p = m_proxies + m_proxyCount; + p->position = { x, y }; + + float ratio = RandomFloatRange( 1.0f, m_ratio ); + float width = RandomFloatRange( 0.1f, 0.5f ); + if ( RandomFloat() > 0.0f ) + { + p->width.x = ratio * width; + p->width.y = width; + } + else + { + p->width.x = width; + p->width.y = ratio * width; + } + + p->box.lowerBound = { x, y }; + p->box.upperBound = { x + p->width.x, y + p->width.y }; + p->fatBox.lowerBound = b2Sub( p->box.lowerBound, aabbMargin ); + p->fatBox.upperBound = b2Add( p->box.upperBound, aabbMargin ); + + p->proxyId = b2DynamicTree_CreateProxy( &m_tree, p->fatBox, B2_DEFAULT_CATEGORY_BITS, m_proxyCount ); + p->rayStamp = -1; + p->queryStamp = -1; + p->moved = false; + ++m_proxyCount; + } + + x += m_grid; + } + + y += m_grid; + } + } + + void UpdateGui() override + { + float height = 320.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Dynamic Tree", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 100.0f ); + + bool changed = false; + if ( ImGui::SliderInt( "rows", &m_rowCount, 0, 1000, "%d" ) ) + { + changed = true; + } + + if ( ImGui::SliderInt( "columns", &m_columnCount, 0, 1000, "%d" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "fill", &m_fill, 0.0f, 1.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "grid", &m_grid, 0.5f, 2.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "ratio", &m_ratio, 1.0f, 10.0f, "%.2f" ) ) + { + changed = true; + } + + if ( ImGui::SliderFloat( "move", &m_moveFraction, 0.0f, 1.0f, "%.2f" ) ) + { + } + + if ( ImGui::SliderFloat( "delta", &m_moveDelta, 0.0f, 1.0f, "%.2f" ) ) + { + } + + if ( ImGui::RadioButton( "Incremental", m_updateType == Update_Incremental ) ) + { + m_updateType = Update_Incremental; + changed = true; + } + + if ( ImGui::RadioButton( "Full Rebuild", m_updateType == Update_FullRebuild ) ) + { + m_updateType = Update_FullRebuild; + changed = true; + } + + if ( ImGui::RadioButton( "Partial Rebuild", m_updateType == Update_PartialRebuild ) ) + { + m_updateType = Update_PartialRebuild; + changed = true; + } + + ImGui::Separator(); + + ImGui::Text( "mouse button 1: ray cast" ); + ImGui::Text( "mouse button 1 + shift: query" ); + + ImGui::PopItemWidth(); + ImGui::End(); + + if ( changed ) + { + BuildTree(); + } + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_queryDrag == false ) + { + m_rayDrag = true; + m_startPoint = p; + m_endPoint = p; + } + else if ( mods == GLFW_MOD_SHIFT && m_rayDrag == false ) + { + m_queryDrag = true; + m_startPoint = p; + m_endPoint = p; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_queryDrag = false; + m_rayDrag = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + m_endPoint = p; + } + + void Step( Settings& ) override + { + if ( m_queryDrag ) + { + b2AABB box = { b2Min( m_startPoint, m_endPoint ), b2Max( m_startPoint, m_endPoint ) }; + b2DynamicTree_Query( &m_tree, box, B2_DEFAULT_MASK_BITS, QueryCallback, this ); + + g_draw.DrawAABB( box, b2_colorWhite ); + } + + // m_startPoint = {-1.0f, 0.5f}; + // m_endPoint = {7.0f, 0.5f}; + + if ( m_rayDrag ) + { + b2RayCastInput input = { m_startPoint, b2Sub( m_endPoint, m_startPoint ), 1.0f }; + b2TreeStats result = b2DynamicTree_RayCast( &m_tree, &input, B2_DEFAULT_MASK_BITS, RayCallback, this ); + + g_draw.DrawSegment( m_startPoint, m_endPoint, b2_colorWhite ); + g_draw.DrawPoint( m_startPoint, 5.0f, b2_colorGreen ); + g_draw.DrawPoint( m_endPoint, 5.0f, b2_colorRed ); + + g_draw.DrawString( 5, m_textLine, "node visits = %d, leaf visits = %d", result.nodeVisits, result.leafVisits ); + m_textLine += m_textIncrement; + } + + b2HexColor c = b2_colorBlue; + b2HexColor qc = b2_colorGreen; + + const b2Vec2 aabbMargin = { 0.1f, 0.1f }; + + for ( int i = 0; i < m_proxyCount; ++i ) + { + Proxy* p = m_proxies + i; + + if ( p->queryStamp == m_timeStamp || p->rayStamp == m_timeStamp ) + { + g_draw.DrawAABB( p->box, qc ); + } + else + { + g_draw.DrawAABB( p->box, c ); + } + + float moveTest = RandomFloatRange( 0.0f, 1.0f ); + if ( m_moveFraction > moveTest ) + { + float dx = m_moveDelta * RandomFloat(); + float dy = m_moveDelta * RandomFloat(); + + p->position.x += dx; + p->position.y += dy; + + p->box.lowerBound.x = p->position.x + dx; + p->box.lowerBound.y = p->position.y + dy; + p->box.upperBound.x = p->position.x + dx + p->width.x; + p->box.upperBound.y = p->position.y + dy + p->width.y; + + if ( b2AABB_Contains( p->fatBox, p->box ) == false ) + { + p->fatBox.lowerBound = b2Sub( p->box.lowerBound, aabbMargin ); + p->fatBox.upperBound = b2Add( p->box.upperBound, aabbMargin ); + p->moved = true; + } + else + { + p->moved = false; + } + } + else + { + p->moved = false; + } + } + + switch ( m_updateType ) + { + case Update_Incremental: + { + uint64_t ticks = b2GetTicks(); + for ( int i = 0; i < m_proxyCount; ++i ) + { + Proxy* p = m_proxies + i; + if ( p->moved ) + { + b2DynamicTree_MoveProxy( &m_tree, p->proxyId, p->fatBox ); + } + } + float ms = b2GetMilliseconds( ticks ); + g_draw.DrawString( 5, m_textLine, "incremental : %.3f ms", ms ); + m_textLine += m_textIncrement; + } + break; + + case Update_FullRebuild: + { + for ( int i = 0; i < m_proxyCount; ++i ) + { + Proxy* p = m_proxies + i; + if ( p->moved ) + { + b2DynamicTree_EnlargeProxy( &m_tree, p->proxyId, p->fatBox ); + } + } + + uint64_t ticks = b2GetTicks(); + int boxCount = b2DynamicTree_Rebuild( &m_tree, true ); + float ms = b2GetMilliseconds( ticks ); + g_draw.DrawString( 5, m_textLine, "full build %d : %.3f ms", boxCount, ms ); + m_textLine += m_textIncrement; + } + break; + + case Update_PartialRebuild: + { + for ( int i = 0; i < m_proxyCount; ++i ) + { + Proxy* p = m_proxies + i; + if ( p->moved ) + { + b2DynamicTree_EnlargeProxy( &m_tree, p->proxyId, p->fatBox ); + } + } + + uint64_t ticks = b2GetTicks(); + int boxCount = b2DynamicTree_Rebuild( &m_tree, false ); + float ms = b2GetMilliseconds( ticks ); + g_draw.DrawString( 5, m_textLine, "partial rebuild %d : %.3f ms", boxCount, ms ); + m_textLine += m_textIncrement; + } + break; + + default: + break; + } + + int height = b2DynamicTree_GetHeight( &m_tree ); + float areaRatio = b2DynamicTree_GetAreaRatio( &m_tree ); + + int hmin = (int)( ceilf( logf( (float)m_proxyCount ) / logf( 2.0f ) - 1.0f ) ); + g_draw.DrawString( 5, m_textLine, "proxies = %d, height = %d, hmin = %d, area ratio = %.1f", m_proxyCount, height, hmin, + areaRatio ); + m_textLine += m_textIncrement; + + b2DynamicTree_Validate( &m_tree ); + + m_timeStamp += 1; + } + + static Sample* Create( Settings& settings ) + { + return new DynamicTree( settings ); + } + + b2DynamicTree m_tree; + int m_rowCount, m_columnCount; + Proxy* m_proxies; + int* m_moveBuffer; + int m_moveCount; + int m_proxyCapacity; + int m_proxyCount; + int m_timeStamp; + int m_updateType; + float m_fill; + float m_moveFraction; + float m_moveDelta; + float m_ratio; + float m_grid; + + b2Vec2 m_startPoint; + b2Vec2 m_endPoint; + + bool m_rayDrag; + bool m_queryDrag; + bool m_validate; +}; + +static bool QueryCallback( int proxyId, uint64_t userData, void* context ) +{ + DynamicTree* sample = static_cast( context ); + Proxy* proxy = sample->m_proxies + userData; + assert( proxy->proxyId == proxyId ); + proxy->queryStamp = sample->m_timeStamp; + return true; +} + +static float RayCallback( const b2RayCastInput* input, int proxyId, uint64_t userData, void* context ) +{ + DynamicTree* sample = static_cast( context ); + Proxy* proxy = sample->m_proxies + userData; + assert( proxy->proxyId == proxyId ); + proxy->rayStamp = sample->m_timeStamp; + return input->maxFraction; +} + +static int sampleDynamicTree = RegisterSample( "Collision", "Dynamic Tree", DynamicTree::Create ); + +class RayCast : public Sample +{ +public: + explicit RayCast( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 20.0f }; + g_camera.m_zoom = 17.5f; + } + + m_circle = { { 0.0f, 0.0f }, 2.0f }; + m_capsule = { { -1.0f, 1.0f }, { 1.0f, -1.0f }, 1.5f }; + m_box = b2MakeBox( 2.0f, 2.0f ); + + b2Vec2 vertices[3] = { { -2.0f, 0.0f }, { 2.0f, 0.0f }, { 2.0f, 3.0f } }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + m_triangle = b2MakePolygon( &hull, 0.0f ); + + m_segment = { { -3.0f, 0.0f }, { 3.0f, 0.0 } }; + + m_transform = b2Transform_identity; + m_angle = 0.0f; + + m_basePosition = { 0.0f, 0.0f }; + m_baseAngle = 0.0f; + m_startPosition = { 0.0f, 0.0f }; + + m_rayStart = { 0.0f, 30.0f }; + m_rayEnd = { 0.0f, 0.0f }; + + m_rayDrag = false; + m_translating = false; + m_rotating = false; + + m_showFraction = false; + } + + void UpdateGui() override + { + float height = 230.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Ray-cast", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 100.0f ); + + ImGui::SliderFloat( "x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f" ); + ImGui::SliderFloat( "y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f" ); + + if ( ImGui::SliderFloat( "angle", &m_angle, -B2_PI, B2_PI, "%.2f" ) ) + { + m_transform.q = b2MakeRot( m_angle ); + } + + // if (ImGui::SliderFloat("ray radius", &m_rayRadius, 0.0f, 1.0f, "%.1f")) + //{ + // } + + ImGui::Checkbox( "show fraction", &m_showFraction ); + + if ( ImGui::Button( "Reset" ) ) + { + m_transform = b2Transform_identity; + m_angle = 0.0f; + } + + ImGui::Separator(); + + ImGui::Text( "mouse btn 1: ray cast" ); + ImGui::Text( "mouse btn 1 + shft: translate" ); + ImGui::Text( "mouse btn 1 + ctrl: rotate" ); + + ImGui::PopItemWidth(); + + ImGui::End(); + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_startPosition = p; + + if ( mods == 0 ) + { + m_rayStart = p; + m_rayDrag = true; + } + else if ( mods == GLFW_MOD_SHIFT ) + { + m_translating = true; + m_basePosition = m_transform.p; + } + else if ( mods == GLFW_MOD_CONTROL ) + { + m_rotating = true; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_rayDrag = false; + m_rotating = false; + m_translating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_rayDrag ) + { + m_rayEnd = p; + } + else if ( m_translating ) + { + m_transform.p.x = m_basePosition.x + 0.5f * ( p.x - m_startPosition.x ); + m_transform.p.y = m_basePosition.y + 0.5f * ( p.y - m_startPosition.y ); + } + else if ( m_rotating ) + { + float dx = p.x - m_startPosition.x; + m_angle = b2ClampFloat( m_baseAngle + 0.5f * dx, -B2_PI, B2_PI ); + m_transform.q = b2MakeRot( m_angle ); + } + } + + void DrawRay( const b2CastOutput* output ) + { + b2Vec2 p1 = m_rayStart; + b2Vec2 p2 = m_rayEnd; + b2Vec2 d = b2Sub( p2, p1 ); + + if ( output->hit ) + { + b2Vec2 p = b2MulAdd( p1, output->fraction, d ); + g_draw.DrawSegment( p1, p, b2_colorWhite ); + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + g_draw.DrawPoint( output->point, 5.0f, b2_colorWhite ); + + b2Vec2 n = b2MulAdd( p, 1.0f, output->normal ); + g_draw.DrawSegment( p, n, b2_colorViolet ); + + // if (m_rayRadius > 0.0f) + //{ + // g_draw.DrawCircle(p1, m_rayRadius, b2_colorGreen); + // g_draw.DrawCircle(p, m_rayRadius, b2_colorRed); + // } + + if ( m_showFraction ) + { + b2Vec2 ps = { p.x + 0.05f, p.y - 0.02f }; + g_draw.DrawString( ps, "%.2f", output->fraction ); + } + } + else + { + g_draw.DrawSegment( p1, p2, b2_colorWhite ); + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + g_draw.DrawPoint( p2, 5.0f, b2_colorRed ); + + // if (m_rayRadius > 0.0f) + //{ + // g_draw.DrawCircle(p1, m_rayRadius, b2_colorGreen); + // g_draw.DrawCircle(p2, m_rayRadius, b2_colorRed); + // } + } + } + + void Step( Settings& ) override + { + b2Vec2 offset = { -20.0f, 20.0f }; + b2Vec2 increment = { 10.0f, 0.0f }; + + b2HexColor color1 = b2_colorYellow; + + b2CastOutput output = {}; + float maxFraction = 1.0f; + + // circle + { + b2Transform transform = { b2Add( m_transform.p, offset ), m_transform.q }; + g_draw.DrawSolidCircle( transform, m_circle.center, m_circle.radius, color1 ); + + b2Vec2 start = b2InvTransformPoint( transform, m_rayStart ); + b2Vec2 translation = b2InvRotateVector( transform.q, b2Sub( m_rayEnd, m_rayStart ) ); + b2RayCastInput input = { start, translation, maxFraction }; + + b2CastOutput localOutput = b2RayCastCircle( &input, &m_circle ); + if ( localOutput.hit ) + { + output = localOutput; + output.point = b2TransformPoint( transform, localOutput.point ); + output.normal = b2RotateVector( transform.q, localOutput.normal ); + maxFraction = localOutput.fraction; + } + + offset = b2Add( offset, increment ); + } + + // capsule + { + b2Transform transform = { b2Add( m_transform.p, offset ), m_transform.q }; + b2Vec2 v1 = b2TransformPoint( transform, m_capsule.center1 ); + b2Vec2 v2 = b2TransformPoint( transform, m_capsule.center2 ); + g_draw.DrawSolidCapsule( v1, v2, m_capsule.radius, color1 ); + + b2Vec2 start = b2InvTransformPoint( transform, m_rayStart ); + b2Vec2 translation = b2InvRotateVector( transform.q, b2Sub( m_rayEnd, m_rayStart ) ); + b2RayCastInput input = { start, translation, maxFraction }; + + b2CastOutput localOutput = b2RayCastCapsule( &input, &m_capsule ); + if ( localOutput.hit ) + { + output = localOutput; + output.point = b2TransformPoint( transform, localOutput.point ); + output.normal = b2RotateVector( transform.q, localOutput.normal ); + maxFraction = localOutput.fraction; + } + + offset = b2Add( offset, increment ); + } + + // box + { + b2Transform transform = { b2Add( m_transform.p, offset ), m_transform.q }; + g_draw.DrawSolidPolygon( transform, m_box.vertices, m_box.count, 0.0f, color1 ); + + b2Vec2 start = b2InvTransformPoint( transform, m_rayStart ); + b2Vec2 translation = b2InvRotateVector( transform.q, b2Sub( m_rayEnd, m_rayStart ) ); + b2RayCastInput input = { start, translation, maxFraction }; + + b2CastOutput localOutput = b2RayCastPolygon( &input, &m_box ); + if ( localOutput.hit ) + { + output = localOutput; + output.point = b2TransformPoint( transform, localOutput.point ); + output.normal = b2RotateVector( transform.q, localOutput.normal ); + maxFraction = localOutput.fraction; + } + + offset = b2Add( offset, increment ); + } + + // triangle + { + b2Transform transform = { b2Add( m_transform.p, offset ), m_transform.q }; + g_draw.DrawSolidPolygon( transform, m_triangle.vertices, m_triangle.count, 0.0f, color1 ); + + b2Vec2 start = b2InvTransformPoint( transform, m_rayStart ); + b2Vec2 translation = b2InvRotateVector( transform.q, b2Sub( m_rayEnd, m_rayStart ) ); + b2RayCastInput input = { start, translation, maxFraction }; + + b2CastOutput localOutput = b2RayCastPolygon( &input, &m_triangle ); + if ( localOutput.hit ) + { + output = localOutput; + output.point = b2TransformPoint( transform, localOutput.point ); + output.normal = b2RotateVector( transform.q, localOutput.normal ); + maxFraction = localOutput.fraction; + } + + offset = b2Add( offset, increment ); + } + + // segment + { + b2Transform transform = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Vec2 p1 = b2TransformPoint( transform, m_segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform, m_segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + + b2Vec2 start = b2InvTransformPoint( transform, m_rayStart ); + b2Vec2 translation = b2InvRotateVector( transform.q, b2Sub( m_rayEnd, m_rayStart ) ); + b2RayCastInput input = { start, translation, maxFraction }; + + b2CastOutput localOutput = b2RayCastSegment( &input, &m_segment, false ); + if ( localOutput.hit ) + { + output = localOutput; + output.point = b2TransformPoint( transform, localOutput.point ); + output.normal = b2RotateVector( transform.q, localOutput.normal ); + maxFraction = localOutput.fraction; + } + + offset = b2Add( offset, increment ); + } + + DrawRay( &output ); + } + + static Sample* Create( Settings& settings ) + { + return new RayCast( settings ); + } + + b2Polygon m_box; + b2Polygon m_triangle; + b2Circle m_circle; + b2Capsule m_capsule; + b2Segment m_segment; + + b2Transform m_transform; + float m_angle; + + b2Vec2 m_rayStart; + b2Vec2 m_rayEnd; + + b2Vec2 m_basePosition; + float m_baseAngle; + + b2Vec2 m_startPosition; + + bool m_rayDrag; + bool m_translating; + bool m_rotating; + bool m_showFraction; +}; + +static int sampleIndex = RegisterSample( "Collision", "Ray Cast", RayCast::Create ); + +// This shows how to filter a specific shape using using data. +struct ShapeUserData +{ + int index; + bool ignore; +}; + +// Context for ray cast callbacks. Do what you want with this. +struct CastContext +{ + b2Vec2 points[3]; + b2Vec2 normals[3]; + float fractions[3]; + int count; +}; + +// This callback finds the closest hit. This is the most common callback used in games. +static float RayCastClosestCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + CastContext* rayContext = (CastContext*)context; + + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData != nullptr && userData->ignore ) + { + // By returning -1, we instruct the calling code to ignore this shape and + // continue the ray-cast to the next shape. + return -1.0f; + } + + rayContext->points[0] = point; + rayContext->normals[0] = normal; + rayContext->fractions[0] = fraction; + rayContext->count = 1; + + // By returning the current fraction, we instruct the calling code to clip the ray and + // continue the ray-cast to the next shape. WARNING: do not assume that shapes + // are reported in order. However, by clipping, we can always get the closest shape. + return fraction; +} + +// This callback finds any hit. For this type of query we are usually just checking for obstruction, +// so the hit data is not relevant. +// NOTE: shape hits are not ordered, so this may not return the closest hit +static float RayCastAnyCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + CastContext* rayContext = (CastContext*)context; + + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData != nullptr && userData->ignore ) + { + // By returning -1, we instruct the calling code to ignore this shape and + // continue the ray-cast to the next shape. + return -1.0f; + } + + rayContext->points[0] = point; + rayContext->normals[0] = normal; + rayContext->fractions[0] = fraction; + rayContext->count = 1; + + // At this point we have a hit, so we know the ray is obstructed. + // By returning 0, we instruct the calling code to terminate the ray-cast. + return 0.0f; +} + +// This ray cast collects multiple hits along the ray. +// The shapes are not necessary reported in order, so we might not capture +// the closest shape. +// NOTE: shape hits are not ordered, so this may return hits in any order. This means that +// if you limit the number of results, you may discard the closest hit. You can see this +// behavior in the sample. +static float RayCastMultipleCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + CastContext* rayContext = (CastContext*)context; + + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData != nullptr && userData->ignore ) + { + // By returning -1, we instruct the calling code to ignore this shape and + // continue the ray-cast to the next shape. + return -1.0f; + } + + int count = rayContext->count; + assert( count < 3 ); + + rayContext->points[count] = point; + rayContext->normals[count] = normal; + rayContext->fractions[count] = fraction; + rayContext->count = count + 1; + + if ( rayContext->count == 3 ) + { + // At this point the buffer is full. + // By returning 0, we instruct the calling code to terminate the ray-cast. + return 0.0f; + } + + // By returning 1, we instruct the caller to continue without clipping the ray. + return 1.0f; +} + +// This ray cast collects multiple hits along the ray and sorts them. +static float RayCastSortedCallback( b2ShapeId shapeId, b2Vec2 point, b2Vec2 normal, float fraction, void* context ) +{ + CastContext* rayContext = (CastContext*)context; + + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData != nullptr && userData->ignore ) + { + // By returning -1, we instruct the calling code to ignore this shape and + // continue the ray-cast to the next shape. + return -1.0f; + } + + int count = rayContext->count; + assert( count <= 3 ); + + int index = 3; + while ( fraction < rayContext->fractions[index - 1] ) + { + index -= 1; + + if ( index == 0 ) + { + break; + } + } + + if ( index == 3 ) + { + // not closer, continue but tell the caller not to consider fractions further than the largest fraction acquired + // this only happens once the buffer is full + assert( rayContext->count == 3 ); + assert( rayContext->fractions[2] <= 1.0f ); + return rayContext->fractions[2]; + } + + for ( int j = 2; j > index; --j ) + { + rayContext->points[j] = rayContext->points[j - 1]; + rayContext->normals[j] = rayContext->normals[j - 1]; + rayContext->fractions[j] = rayContext->fractions[j - 1]; + } + + rayContext->points[index] = point; + rayContext->normals[index] = normal; + rayContext->fractions[index] = fraction; + rayContext->count = count < 3 ? count + 1 : 3; + + if ( rayContext->count == 3 ) + { + return rayContext->fractions[2]; + } + + // By returning 1, we instruct the caller to continue without clipping the ray. + return 1.0f; +} + +class CastWorld : public Sample +{ +public: + enum Mode + { + e_any = 0, + e_closest = 1, + e_multiple = 2, + e_sorted = 3 + }; + + enum CastType + { + e_rayCast = 0, + e_circleCast = 1, + e_capsuleCast = 2, + e_polygonCast = 3 + }; + + enum + { + e_maxCount = 64 + }; + + explicit CastWorld( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.0f, 14.0f }; + g_camera.m_zoom = 25.0f * 0.75f; + } + + // Ground body + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Vec2 vertices[3] = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, { 0.0f, 1.5f } }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + m_polygons[0] = b2MakePolygon( &hull, 0.0f ); + } + + { + b2Vec2 vertices[3] = { { -0.1f, 0.0f }, { 0.1f, 0.0f }, { 0.0f, 1.5f } }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + m_polygons[1] = b2MakePolygon( &hull, 0.0f ); + m_polygons[1].radius = 0.5f; + } + + { + float w = 1.0f; + float b = w / ( 2.0f + sqrtf( 2.0f ) ); + float s = sqrtf( 2.0f ) * b; + + b2Vec2 vertices[8] = { { 0.5f * s, 0.0f }, { 0.5f * w, b }, { 0.5f * w, b + s }, { 0.5f * s, w }, + { -0.5f * s, w }, { -0.5f * w, b + s }, { -0.5f * w, b }, { -0.5f * s, 0.0f } }; + + b2Hull hull = b2ComputeHull( vertices, 8 ); + m_polygons[2] = b2MakePolygon( &hull, 0.0f ); + } + + m_polygons[3] = b2MakeBox( 0.5f, 0.5f ); + m_capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, 0.25f }; + m_circle = { { 0.0f, 0.0f }, 0.5f }; + m_segment = { { -1.0f, 0.0f }, { 1.0f, 0.0f } }; + + m_bodyIndex = 0; + + for ( int i = 0; i < e_maxCount; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + } + + m_mode = e_closest; + m_ignoreIndex = 7; + + m_castType = e_rayCast; + m_castRadius = 0.5f; + + m_rayStart = { -20.0f, 10.0f }; + m_rayEnd = { 20.0f, 10.0f }; + m_dragging = false; + + m_angle = 0.0f; + m_baseAngle = 0.0f; + m_angleAnchor = { 0.0f, 0.0f }; + m_rotating = false; + + m_simple = false; + } + + void Create( int index ) + { + if ( B2_IS_NON_NULL( m_bodyIds[m_bodyIndex] ) ) + { + b2DestroyBody( m_bodyIds[m_bodyIndex] ); + m_bodyIds[m_bodyIndex] = b2_nullBodyId; + } + + float x = RandomFloatRange( -20.0f, 20.0f ); + float y = RandomFloatRange( 0.0f, 20.0f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { x, y }; + bodyDef.rotation = b2MakeRot( RandomFloatRange( -B2_PI, B2_PI ) ); + + int mod = m_bodyIndex % 3; + if ( mod == 0 ) + { + bodyDef.type = b2_staticBody; + } + else if ( mod == 1 ) + { + bodyDef.type = b2_kinematicBody; + } + else if ( mod == 2 ) + { + bodyDef.type = b2_dynamicBody; + bodyDef.gravityScale = 0.0f; + } + + m_bodyIds[m_bodyIndex] = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.userData = m_userData + m_bodyIndex; + m_userData[m_bodyIndex].ignore = false; + if ( m_bodyIndex == m_ignoreIndex ) + { + m_userData[m_bodyIndex].ignore = true; + } + + if ( index < 4 ) + { + b2CreatePolygonShape( m_bodyIds[m_bodyIndex], &shapeDef, m_polygons + index ); + } + else if ( index == 4 ) + { + b2CreateCircleShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_circle ); + } + else if ( index == 5 ) + { + b2CreateCapsuleShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_capsule ); + } + else + { + b2CreateSegmentShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_segment ); + } + + m_bodyIndex = ( m_bodyIndex + 1 ) % e_maxCount; + } + + void CreateN( int index, int count ) + { + for ( int i = 0; i < count; ++i ) + { + Create( index ); + } + } + + void DestroyBody() + { + for ( int i = 0; i < e_maxCount; ++i ) + { + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + return; + } + } + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_rotating == false ) + { + m_rayStart = p; + m_rayEnd = p; + m_dragging = true; + } + else if ( mods == GLFW_MOD_SHIFT && m_dragging == false ) + { + m_rotating = true; + m_angleAnchor = p; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_rayEnd = p; + } + else if ( m_rotating ) + { + float dx = p.x - m_angleAnchor.x; + m_angle = m_baseAngle + 1.0f * dx; + } + } + + void UpdateGui() override + { + float height = 320.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Ray-cast World", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::Checkbox( "Simple", &m_simple ); + + if ( m_simple == false ) + { + const char* castTypes[] = { "Ray", "Circle", "Capsule", "Polygon" }; + int castType = int( m_castType ); + if ( ImGui::Combo( "Type", &castType, castTypes, IM_ARRAYSIZE( castTypes ) ) ) + { + m_castType = CastType( castType ); + } + + if ( m_castType != e_rayCast ) + { + ImGui::SliderFloat( "Radius", &m_castRadius, 0.0f, 2.0f, "%.1f" ); + } + + const char* modes[] = { "Any", "Closest", "Multiple", "Sorted" }; + int mode = int( m_mode ); + if ( ImGui::Combo( "Mode", &mode, modes, IM_ARRAYSIZE( modes ) ) ) + { + m_mode = Mode( mode ); + } + } + + if ( ImGui::Button( "Polygon 1" ) ) + Create( 0 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly1" ) ) + CreateN( 0, 10 ); + + if ( ImGui::Button( "Polygon 2" ) ) + Create( 1 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly2" ) ) + CreateN( 1, 10 ); + + if ( ImGui::Button( "Polygon 3" ) ) + Create( 2 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly3" ) ) + CreateN( 2, 10 ); + + if ( ImGui::Button( "Box" ) ) + Create( 3 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Box" ) ) + CreateN( 3, 10 ); + + if ( ImGui::Button( "Circle" ) ) + Create( 4 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Circle" ) ) + CreateN( 4, 10 ); + + if ( ImGui::Button( "Capsule" ) ) + Create( 5 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Capsule" ) ) + CreateN( 5, 10 ); + + if ( ImGui::Button( "Segment" ) ) + Create( 6 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Segment" ) ) + CreateN( 6, 10 ); + + if ( ImGui::Button( "Destroy Shape" ) ) + { + DestroyBody(); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "Click left mouse button and drag to modify ray cast" ); + m_textLine += m_textIncrement; + g_draw.DrawString( 5, m_textLine, "Shape 7 is intentionally ignored by the ray" ); + m_textLine += m_textIncrement; + + m_textLine += m_textIncrement; + + b2HexColor color1 = b2_colorGreen; + b2HexColor color2 = b2_colorLightGray; + b2HexColor color3 = b2_colorMagenta; + + b2Vec2 rayTranslation = b2Sub( m_rayEnd, m_rayStart ); + + if ( m_simple ) + { + g_draw.DrawString( 5, m_textLine, "Simple closest point ray cast" ); + m_textLine += m_textIncrement; + + // This version doesn't have a callback, but it doesn't skip the ignored shape + b2RayResult result = b2World_CastRayClosest( m_worldId, m_rayStart, rayTranslation, b2DefaultQueryFilter() ); + + if ( result.hit == true ) + { + b2Vec2 c = b2MulAdd( m_rayStart, result.fraction, rayTranslation ); + g_draw.DrawPoint( result.point, 5.0f, color1 ); + g_draw.DrawSegment( m_rayStart, c, color2 ); + b2Vec2 head = b2MulAdd( result.point, 0.5f, result.normal ); + g_draw.DrawSegment( result.point, head, color3 ); + } + else + { + g_draw.DrawSegment( m_rayStart, m_rayEnd, color2 ); + } + } + else + { + switch ( m_mode ) + { + case e_any: + g_draw.DrawString( 5, m_textLine, "Cast mode: any - check for obstruction - unsorted" ); + break; + + case e_closest: + g_draw.DrawString( 5, m_textLine, "Cast mode: closest - find closest shape along the cast" ); + break; + + case e_multiple: + g_draw.DrawString( 5, m_textLine, "Cast mode: multiple - gather up to 3 shapes - unsorted" ); + break; + + case e_sorted: + g_draw.DrawString( 5, m_textLine, "Cast mode: sorted - gather up to 3 shapes sorted by closeness" ); + break; + + default: + assert( false ); + break; + } + + m_textLine += m_textIncrement; + + b2CastResultFcn* functions[] = { + RayCastAnyCallback, + RayCastClosestCallback, + RayCastMultipleCallback, + RayCastSortedCallback, + }; + b2CastResultFcn* modeFcn = functions[m_mode]; + + CastContext context = {}; + + // Must initialize fractions for sorting + context.fractions[0] = FLT_MAX; + context.fractions[1] = FLT_MAX; + context.fractions[2] = FLT_MAX; + + b2Transform transform = { m_rayStart, b2MakeRot( m_angle ) }; + b2Circle circle = { .center = m_rayStart, .radius = m_castRadius }; + b2Capsule capsule = { b2TransformPoint( transform, { -0.25f, 0.0f } ), b2TransformPoint( transform, { 0.25f, 0.0f } ), + m_castRadius }; + b2Polygon box = b2MakeOffsetRoundedBox( 0.25f, 0.5f, transform.p, transform.q, m_castRadius ); + b2ShapeProxy proxy = {}; + + if ( m_castType == e_rayCast ) + { + b2World_CastRay( m_worldId, m_rayStart, rayTranslation, b2DefaultQueryFilter(), modeFcn, &context ); + } + else + { + if ( m_castType == e_circleCast ) + { + proxy = b2MakeProxy( &circle.center, 1, circle.radius ); + } + else if ( m_castType == e_capsuleCast ) + { + proxy = b2MakeProxy( &capsule.center1, 2, capsule.radius ); + } + else + { + proxy = b2MakeProxy( box.vertices, box.count, box.radius ); + } + + b2World_CastShape( m_worldId, &proxy, rayTranslation, b2DefaultQueryFilter(), modeFcn, &context ); + } + + if ( context.count > 0 ) + { + assert( context.count <= 3 ); + b2HexColor colors[3] = { b2_colorRed, b2_colorGreen, b2_colorBlue }; + for ( int i = 0; i < context.count; ++i ) + { + b2Vec2 c = b2MulAdd( m_rayStart, context.fractions[i], rayTranslation ); + b2Vec2 p = context.points[i]; + b2Vec2 n = context.normals[i]; + g_draw.DrawPoint( p, 5.0f, colors[i] ); + g_draw.DrawSegment( m_rayStart, c, color2 ); + b2Vec2 head = b2MulAdd( p, 0.5f, n ); + g_draw.DrawSegment( p, head, color3 ); + + b2Vec2 t = b2MulSV( context.fractions[i], rayTranslation ); + b2Transform shiftedTransform = { t, b2Rot_identity }; + + if ( m_castType == e_circleCast ) + { + g_draw.DrawSolidCircle( shiftedTransform, circle.center, m_castRadius, b2_colorYellow ); + } + else if ( m_castType == e_capsuleCast ) + { + b2Vec2 p1 = capsule.center1 + t; + b2Vec2 p2 = capsule.center2 + t; + g_draw.DrawSolidCapsule( p1, p2, m_castRadius, b2_colorYellow ); + } + else if ( m_castType == e_polygonCast ) + { + g_draw.DrawSolidPolygon( shiftedTransform, box.vertices, box.count, box.radius, b2_colorYellow ); + } + } + } + else + { + b2Transform shiftedTransform = { b2Add( transform.p, rayTranslation ), transform.q }; + g_draw.DrawSegment( m_rayStart, m_rayEnd, color2 ); + + if ( m_castType == e_circleCast ) + { + g_draw.DrawSolidCircle( shiftedTransform, b2Vec2_zero, m_castRadius, b2_colorGray ); + } + else if ( m_castType == e_capsuleCast ) + { + b2Vec2 p1 = b2Add( b2TransformPoint( transform, capsule.center1 ), rayTranslation ); + b2Vec2 p2 = b2Add( b2TransformPoint( transform, capsule.center2 ), rayTranslation ); + g_draw.DrawSolidCapsule( p1, p2, m_castRadius, b2_colorYellow ); + } + else if ( m_castType == e_polygonCast ) + { + g_draw.DrawSolidPolygon( shiftedTransform, box.vertices, box.count, box.radius, b2_colorYellow ); + } + } + } + + g_draw.DrawPoint( m_rayStart, 5.0f, b2_colorGreen ); + + if ( B2_IS_NON_NULL( m_bodyIds[m_ignoreIndex] ) ) + { + b2Vec2 p = b2Body_GetPosition( m_bodyIds[m_ignoreIndex] ); + p.x -= 0.2f; + g_draw.DrawString( p, "ign" ); + } + } + + static Sample* Create( Settings& settings ) + { + return new CastWorld( settings ); + } + + int m_bodyIndex; + b2BodyId m_bodyIds[e_maxCount] = {}; + ShapeUserData m_userData[e_maxCount] = {}; + b2Polygon m_polygons[4] = {}; + b2Capsule m_capsule; + b2Circle m_circle; + b2Segment m_segment; + + bool m_simple; + + int m_mode; + int m_ignoreIndex; + + CastType m_castType; + float m_castRadius; + + b2Vec2 m_angleAnchor; + float m_baseAngle; + float m_angle; + bool m_rotating; + + b2Vec2 m_rayStart; + b2Vec2 m_rayEnd; + bool m_dragging; +}; + +static int sampleRayCastWorld = RegisterSample( "Collision", "Cast World", CastWorld::Create ); + +class OverlapWorld : public Sample +{ +public: + enum + { + e_circleShape = 0, + e_capsuleShape = 1, + e_boxShape = 2 + }; + + enum + { + e_maxCount = 64, + e_maxDoomed = 16, + }; + + static bool OverlapResultFcn( b2ShapeId shapeId, void* context ) + { + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData != nullptr && userData->ignore ) + { + // continue the query + return true; + } + + OverlapWorld* sample = (OverlapWorld*)context; + + if ( sample->m_doomCount < e_maxDoomed ) + { + int index = sample->m_doomCount; + sample->m_doomIds[index] = shapeId; + sample->m_doomCount += 1; + } + + // continue the query + return true; + } + + explicit OverlapWorld( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.7f; + } + + { + b2Vec2 vertices[3] = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, { 0.0f, 1.5f } }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + m_polygons[0] = b2MakePolygon( &hull, 0.0f ); + } + + { + b2Vec2 vertices[3] = { { -0.1f, 0.0f }, { 0.1f, 0.0f }, { 0.0f, 1.5f } }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + m_polygons[1] = b2MakePolygon( &hull, 0.0f ); + } + + { + float w = 1.0f; + float b = w / ( 2.0f + sqrtf( 2.0f ) ); + float s = sqrtf( 2.0f ) * b; + + b2Vec2 vertices[8] = { { 0.5f * s, 0.0f }, { 0.5f * w, b }, { 0.5f * w, b + s }, { 0.5f * s, w }, + { -0.5f * s, w }, { -0.5f * w, b + s }, { -0.5f * w, b }, { -0.5f * s, 0.0f } }; + + b2Hull hull = b2ComputeHull( vertices, 8 ); + m_polygons[2] = b2MakePolygon( &hull, 0.0f ); + } + + m_polygons[3] = b2MakeBox( 0.5f, 0.5f ); + m_capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, 0.25f }; + m_circle = { { 0.0f, 0.0f }, 0.5f }; + m_segment = { { -1.0f, 0.0f }, { 1.0f, 0.0f } }; + + m_bodyIndex = 0; + + for ( int i = 0; i < e_maxCount; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + } + + m_ignoreIndex = 7; + + m_shapeType = e_circleShape; + + m_position = { 0.0f, 10.0f }; + m_angle = 0.0f; + m_dragging = false; + m_rotating = false; + + m_doomCount = 0; + + CreateN( 0, 10 ); + } + + void Create( int index ) + { + if ( B2_IS_NON_NULL( m_bodyIds[m_bodyIndex] ) ) + { + b2DestroyBody( m_bodyIds[m_bodyIndex] ); + m_bodyIds[m_bodyIndex] = b2_nullBodyId; + } + + float x = RandomFloatRange( -20.0f, 20.0f ); + float y = RandomFloatRange( 0.0f, 20.0f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { x, y }; + bodyDef.rotation = b2MakeRot( RandomFloatRange( -B2_PI, B2_PI ) ); + + m_bodyIds[m_bodyIndex] = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.userData = m_userData + m_bodyIndex; + m_userData[m_bodyIndex].index = m_bodyIndex; + m_userData[m_bodyIndex].ignore = false; + if ( m_bodyIndex == m_ignoreIndex ) + { + m_userData[m_bodyIndex].ignore = true; + } + + if ( index < 4 ) + { + b2CreatePolygonShape( m_bodyIds[m_bodyIndex], &shapeDef, m_polygons + index ); + } + else if ( index == 4 ) + { + b2CreateCircleShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_circle ); + } + else if ( index == 5 ) + { + b2CreateCapsuleShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_capsule ); + } + else + { + b2CreateSegmentShape( m_bodyIds[m_bodyIndex], &shapeDef, &m_segment ); + } + + m_bodyIndex = ( m_bodyIndex + 1 ) % e_maxCount; + } + + void CreateN( int index, int count ) + { + for ( int i = 0; i < count; ++i ) + { + Create( index ); + } + } + + void DestroyBody() + { + for ( int i = 0; i < e_maxCount; ++i ) + { + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + return; + } + } + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_rotating == false ) + { + m_dragging = true; + m_position = p; + } + else if ( mods == GLFW_MOD_SHIFT && m_dragging == false ) + { + m_rotating = true; + m_startPosition = p; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_position = p; + } + else if ( m_rotating ) + { + float dx = p.x - m_startPosition.x; + m_angle = m_baseAngle + 1.0f * dx; + } + } + + void UpdateGui() override + { + float height = 330.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 140.0f, height ) ); + + ImGui::Begin( "Overlap World", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( ImGui::Button( "Polygon 1" ) ) + Create( 0 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly1" ) ) + CreateN( 0, 10 ); + + if ( ImGui::Button( "Polygon 2" ) ) + Create( 1 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly2" ) ) + CreateN( 1, 10 ); + + if ( ImGui::Button( "Polygon 3" ) ) + Create( 2 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Poly3" ) ) + CreateN( 2, 10 ); + + if ( ImGui::Button( "Box" ) ) + Create( 3 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Box" ) ) + CreateN( 3, 10 ); + + if ( ImGui::Button( "Circle" ) ) + Create( 4 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Circle" ) ) + CreateN( 4, 10 ); + + if ( ImGui::Button( "Capsule" ) ) + Create( 5 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Capsule" ) ) + CreateN( 5, 10 ); + + if ( ImGui::Button( "Segment" ) ) + Create( 6 ); + ImGui::SameLine(); + if ( ImGui::Button( "10x##Segment" ) ) + CreateN( 6, 10 ); + + if ( ImGui::Button( "Destroy Shape" ) ) + { + DestroyBody(); + } + + ImGui::Separator(); + ImGui::Text( "Overlap Shape" ); + ImGui::RadioButton( "Circle##Overlap", &m_shapeType, e_circleShape ); + ImGui::RadioButton( "Capsule##Overlap", &m_shapeType, e_capsuleShape ); + ImGui::RadioButton( "Box##Overlap", &m_shapeType, e_boxShape ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "left mouse button: drag query shape" ); + m_textLine += m_textIncrement; + g_draw.DrawString( 5, m_textLine, "left mouse button + shift: rotate query shape" ); + m_textLine += m_textIncrement; + + m_doomCount = 0; + + b2Transform transform = { m_position, b2MakeRot( m_angle ) }; + b2ShapeProxy proxy = {}; + + if ( m_shapeType == e_circleShape ) + { + b2Circle circle = { + .center = transform.p, + .radius = 1.0f, + }; + proxy = b2MakeProxy( &circle.center, 1, circle.radius ); + g_draw.DrawSolidCircle( b2Transform_identity, circle.center, circle.radius, b2_colorWhite ); + } + else if ( m_shapeType == e_capsuleShape ) + { + b2Capsule capsule = { + .center1 = b2TransformPoint( transform, { -1.0f, 0.0f } ), + .center2 = b2TransformPoint( transform, { 1.0f, 0.0f } ), + .radius = 0.5f, + }; + proxy = b2MakeProxy( &capsule.center1, 2, capsule.radius ); + g_draw.DrawSolidCapsule( capsule.center1, capsule.center2, capsule.radius, b2_colorWhite ); + } + else if ( m_shapeType == e_boxShape ) + { + b2Polygon box = b2MakeOffsetBox( 2.0f, 0.5f, transform.p, transform.q ); + proxy = b2MakeProxy( box.vertices, box.count, box.radius ); + g_draw.DrawPolygon( box.vertices, box.count, b2_colorWhite ); + } + + b2World_OverlapShape( m_worldId, &proxy, b2DefaultQueryFilter(), OverlapResultFcn, this ); + + if ( B2_IS_NON_NULL( m_bodyIds[m_ignoreIndex] ) ) + { + b2Vec2 p = b2Body_GetPosition( m_bodyIds[m_ignoreIndex] ); + p.x -= 0.2f; + g_draw.DrawString( p, "skip" ); + } + + for ( int i = 0; i < m_doomCount; ++i ) + { + b2ShapeId shapeId = m_doomIds[i]; + ShapeUserData* userData = (ShapeUserData*)b2Shape_GetUserData( shapeId ); + if ( userData == nullptr ) + { + continue; + } + + int index = userData->index; + assert( 0 <= index && index < e_maxCount ); + assert( B2_IS_NON_NULL( m_bodyIds[index] ) ); + + b2DestroyBody( m_bodyIds[index] ); + m_bodyIds[index] = b2_nullBodyId; + } + } + + static Sample* Create( Settings& settings ) + { + return new OverlapWorld( settings ); + } + + int m_bodyIndex; + b2BodyId m_bodyIds[e_maxCount]; + ShapeUserData m_userData[e_maxCount]; + b2Polygon m_polygons[4]; + b2Capsule m_capsule; + b2Circle m_circle; + b2Segment m_segment; + int m_ignoreIndex; + + b2ShapeId m_doomIds[e_maxDoomed]; + int m_doomCount; + + int m_shapeType; + b2Transform m_transform; + + b2Vec2 m_startPosition; + + b2Vec2 m_position; + b2Vec2 m_basePosition; + float m_angle; + float m_baseAngle; + + bool m_dragging; + bool m_rotating; +}; + +static int sampleOverlapWorld = RegisterSample( "Collision", "Overlap World", OverlapWorld::Create ); + +// Tests manifolds and contact points +class Manifold : public Sample +{ +public: + explicit Manifold( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + // g_camera.m_center = {1.8f, 15.0f}; + g_camera.m_center = { 1.8f, 0.0f }; + g_camera.m_zoom = 25.0f * 0.45f; + } + + m_smgroxCache1 = b2_emptySimplexCache; + m_smgroxCache2 = b2_emptySimplexCache; + m_smgcapCache1 = b2_emptySimplexCache; + m_smgcapCache2 = b2_emptySimplexCache; + + m_transform = b2Transform_identity; + m_transform.p.x = 0.17f; + m_transform.p.y = 1.12f; + // m_transform.q = b2MakeRot( 0.5f * b2_pi ); + m_angle = 0.0f; + m_round = 0.1f; + + m_startPoint = { 0.0f, 0.0f }; + m_basePosition = { 0.0f, 0.0f }; + m_baseAngle = 0.0f; + + m_dragging = false; + m_rotating = false; + m_showCount = false; + m_showIds = false; + m_showSeparation = false; + m_showAnchors = false; + m_enableCaching = true; + + b2Vec2 points[3] = { { -0.1f, -0.5f }, { 0.1f, -0.5f }, { 0.0f, 0.5f } }; + m_wedge = b2ComputeHull( points, 3 ); + } + + void UpdateGui() override + { + float height = 320.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 340.0f, height ) ); + + ImGui::Begin( "Manifold", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 280.0f ); + + ImGui::SliderFloat( "x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f" ); + ImGui::SliderFloat( "y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f" ); + + if ( ImGui::SliderFloat( "angle", &m_angle, -B2_PI, B2_PI, "%.2f" ) ) + { + m_transform.q = b2MakeRot( m_angle ); + } + + ImGui::SliderFloat( "round", &m_round, 0.0f, 0.4f, "%.1f" ); + + ImGui::PopItemWidth(); + + ImGui::Separator(); + + ImGui::Checkbox( "show count", &m_showCount ); + ImGui::Checkbox( "show ids", &m_showIds ); + ImGui::Checkbox( "show separation", &m_showSeparation ); + ImGui::Checkbox( "show anchors", &m_showAnchors ); + ImGui::Checkbox( "enable caching", &m_enableCaching ); + + if ( ImGui::Button( "Reset" ) ) + { + m_transform = b2Transform_identity; + m_angle = 0.0f; + } + + ImGui::Separator(); + + ImGui::Text( "mouse button 1: drag" ); + ImGui::Text( "mouse button 1 + shift: rotate" ); + + ImGui::End(); + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_rotating == false ) + { + m_dragging = true; + m_startPoint = p; + m_basePosition = m_transform.p; + } + else if ( mods == GLFW_MOD_SHIFT && m_dragging == false ) + { + m_rotating = true; + m_startPoint = p; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_transform.p.x = m_basePosition.x + 0.5f * ( p.x - m_startPoint.x ); + m_transform.p.y = m_basePosition.y + 0.5f * ( p.y - m_startPoint.y ); + } + else if ( m_rotating ) + { + float dx = p.x - m_startPoint.x; + m_angle = b2ClampFloat( m_baseAngle + 1.0f * dx, -B2_PI, B2_PI ); + m_transform.q = b2MakeRot( m_angle ); + } + } + + void DrawManifold( const b2Manifold* manifold, b2Vec2 origin1, b2Vec2 origin2 ) + { + if ( m_showCount ) + { + b2Vec2 p = 0.5f * ( origin1 + origin2 ); + g_draw.DrawString( p, "%d", manifold->pointCount ); + } + + for ( int i = 0; i < manifold->pointCount; ++i ) + { + const b2ManifoldPoint* mp = manifold->points + i; + + b2Vec2 p1 = mp->point; + b2Vec2 p2 = b2MulAdd( p1, 0.5f, manifold->normal ); + g_draw.DrawSegment( p1, p2, b2_colorViolet ); + + if ( m_showAnchors ) + { + g_draw.DrawPoint( b2Add( origin1, mp->anchorA ), 5.0f, b2_colorRed ); + g_draw.DrawPoint( b2Add( origin2, mp->anchorB ), 5.0f, b2_colorGreen ); + } + else + { + g_draw.DrawPoint( p1, 10.0f, b2_colorBlue ); + } + + if ( m_showIds ) + { + // uint32_t indexA = mp->id >> 8; + // uint32_t indexB = 0xFF & mp->id; + b2Vec2 p = { p1.x + 0.05f, p1.y - 0.02f }; + g_draw.DrawString( p, "0x%04x", mp->id ); + } + + if ( m_showSeparation ) + { + b2Vec2 p = { p1.x + 0.05f, p1.y + 0.03f }; + g_draw.DrawString( p, "%.3f", mp->separation ); + } + } + } + + void Step( Settings& ) override + { + b2Vec2 offset = { -10.0f, -5.0f }; + b2Vec2 increment = { 4.0f, 0.0f }; + + b2HexColor color1 = b2_colorAquamarine; + b2HexColor color2 = b2_colorPaleGoldenRod; + + if ( m_enableCaching == false ) + { + m_smgroxCache1 = b2_emptySimplexCache; + m_smgroxCache2 = b2_emptySimplexCache; + m_smgcapCache1 = b2_emptySimplexCache; + m_smgcapCache2 = b2_emptySimplexCache; + } + +#if 1 + // circle-circle + { + b2Circle circle1 = { { 0.0f, 0.0f }, 0.5f }; + b2Circle circle2 = { { 0.0f, 0.0f }, 1.0f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideCircles( &circle1, transform1, &circle2, transform2 ); + + g_draw.DrawSolidCircle( transform1, circle1.center, circle1.radius, color1 ); + g_draw.DrawSolidCircle( transform2, circle2.center, circle2.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // capsule-circle + { + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideCapsuleAndCircle( &capsule, transform1, &circle, transform2 ); + + b2Vec2 v1 = b2TransformPoint( transform1, capsule.center1 ); + b2Vec2 v2 = b2TransformPoint( transform1, capsule.center2 ); + g_draw.DrawSolidCapsule( v1, v2, capsule.radius, color1 ); + + g_draw.DrawSolidCircle( transform2, circle.center, circle.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // segment-circle + { + b2Segment segment = { { -1.0f, 0.0f }, { 1.0f, 0.0 } }; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideSegmentAndCircle( &segment, transform1, &circle, transform2 ); + + b2Vec2 p1 = b2TransformPoint( transform1, segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + + g_draw.DrawSolidCircle( transform2, circle.center, circle.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // box-circle + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2Polygon box = b2MakeSquare( 0.5f ); + box.radius = m_round; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollidePolygonAndCircle( &box, transform1, &circle, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box.vertices, box.count, m_round, color1 ); + g_draw.DrawSolidCircle( transform2, circle.center, circle.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // capsule-capsule + { + b2Capsule capsule1 = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + b2Capsule capsule2 = { { 0.25f, 0.0f }, { 1.0f, 0.0 }, 0.1f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideCapsules( &capsule1, transform1, &capsule2, transform2 ); + + b2Vec2 v1 = b2TransformPoint( transform1, capsule1.center1 ); + b2Vec2 v2 = b2TransformPoint( transform1, capsule1.center2 ); + g_draw.DrawSolidCapsule( v1, v2, capsule1.radius, color1 ); + + v1 = b2TransformPoint( transform2, capsule2.center1 ); + v2 = b2TransformPoint( transform2, capsule2.center2 ); + g_draw.DrawSolidCapsule( v1, v2, capsule2.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // box-capsule + { + b2Capsule capsule = { { -0.4f, 0.0f }, { -0.1f, 0.0f }, 0.1f }; + b2Polygon box = b2MakeOffsetBox( 0.25f, 1.0f, { 1.0f, -1.0f }, b2MakeRot( 0.25f * B2_PI ) ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollidePolygonAndCapsule( &box, transform1, &capsule, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box.vertices, box.count, box.radius, color1 ); + + b2Vec2 v1 = b2TransformPoint( transform2, capsule.center1 ); + b2Vec2 v2 = b2TransformPoint( transform2, capsule.center2 ); + g_draw.DrawSolidCapsule( v1, v2, capsule.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // segment-capsule + { + b2Segment segment = { { -1.0f, 0.0f }, { 1.0f, 0.0 } }; + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideSegmentAndCapsule( &segment, transform1, &capsule, transform2 ); + + b2Vec2 p1 = b2TransformPoint( transform1, segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + + p1 = b2TransformPoint( transform2, capsule.center1 ); + p2 = b2TransformPoint( transform2, capsule.center2 ); + g_draw.DrawSolidCapsule( p1, p2, capsule.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + offset = { -10.0f, 0.0f }; +#endif + +#if 1 + // square-square + { + b2Polygon box1 = b2MakeSquare( 0.5f ); + b2Polygon box = b2MakeSquare( 0.5f ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollidePolygons( &box1, transform1, &box, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box1.vertices, box1.count, box1.radius, color1 ); + g_draw.DrawSolidPolygon( transform2, box.vertices, box.count, box.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // box-box + { + b2Polygon box1 = b2MakeBox( 2.0f, 0.1f ); + b2Polygon box = b2MakeSquare( 0.25f ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({0.0f, -0.1f}, offset), {0.0f, 1.0f}}; + + b2Manifold m = b2CollidePolygons( &box1, transform1, &box, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box1.vertices, box1.count, box1.radius, color1 ); + g_draw.DrawSolidPolygon( transform2, box.vertices, box.count, box.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // box-rox + { + b2Polygon box = b2MakeSquare( 0.5f ); + float h = 0.5f - m_round; + b2Polygon rox = b2MakeRoundedBox( h, h, m_round ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({0.0f, -0.1f}, offset), {0.0f, 1.0f}}; + + b2Manifold m = b2CollidePolygons( &box, transform1, &rox, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box.vertices, box.count, box.radius, color1 ); + g_draw.DrawSolidPolygon( transform2, rox.vertices, rox.count, rox.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // rox-rox + { + float h = 0.5f - m_round; + b2Polygon rox = b2MakeRoundedBox( h, h, m_round ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform1 = {{6.48024225f, 2.07872653f}, {-0.938356698f, 0.345668465f}}; + // b2Transform transform2 = {{5.52862263f, 2.51146317f}, {-0.859374702f, -0.511346340f}}; + + b2Manifold m = b2CollidePolygons( &rox, transform1, &rox, transform2 ); + + g_draw.DrawSolidPolygon( transform1, rox.vertices, rox.count, rox.radius, color1 ); + g_draw.DrawSolidPolygon( transform2, rox.vertices, rox.count, rox.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // segment-rox + { + b2Segment segment = { { -1.0f, 0.0f }, { 1.0f, 0.0 } }; + float h = 0.5f - m_round; + b2Polygon rox = b2MakeRoundedBox( h, h, m_round ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({-1.44583416f, 0.397352695f}, offset), m_transform.q}; + + b2Manifold m = b2CollideSegmentAndPolygon( &segment, transform1, &rox, transform2 ); + + b2Vec2 p1 = b2TransformPoint( transform1, segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawSolidPolygon( transform2, rox.vertices, rox.count, rox.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } +#endif + + // wox-wox + { + b2Polygon wox = b2MakePolygon( &m_wedge, m_round ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({0.0f, -0.1f}, offset), {0.0f, 1.0f}}; + + b2Manifold m = b2CollidePolygons( &wox, transform1, &wox, transform2 ); + + g_draw.DrawSolidPolygon( transform1, wox.vertices, wox.count, wox.radius, color1 ); + g_draw.DrawSolidPolygon( transform1, wox.vertices, wox.count, 0.0f, color1 ); + g_draw.DrawSolidPolygon( transform2, wox.vertices, wox.count, wox.radius, color2 ); + g_draw.DrawSolidPolygon( transform2, wox.vertices, wox.count, 0.0f, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + +#if 1 + // wox-wox + { + b2Vec2 p1s[3] = { { 0.175740838, 0.224936664 }, { -0.301293969, 0.194021404 }, { -0.105151534, -0.432157338 } }; + b2Vec2 p2s[3] = { { -0.427884758, -0.225028217 }, { 0.0566576123, -0.128772855 }, { 0.176625848, 0.338923335 } }; + + b2Hull h1 = b2ComputeHull( p1s, 3 ); + b2Hull h2 = b2ComputeHull( p2s, 3 ); + b2Polygon w1 = b2MakePolygon( &h1, 0.158798501 ); + b2Polygon w2 = b2MakePolygon( &h2, 0.205900759 ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({0.0f, -0.1f}, offset), {0.0f, 1.0f}}; + + b2Manifold m = b2CollidePolygons( &w1, transform1, &w2, transform2 ); + + g_draw.DrawSolidPolygon( transform1, w1.vertices, w1.count, w1.radius, color1 ); + g_draw.DrawSolidPolygon( transform1, w1.vertices, w1.count, 0.0f, color1 ); + g_draw.DrawSolidPolygon( transform2, w2.vertices, w2.count, w2.radius, color2 ); + g_draw.DrawSolidPolygon( transform2, w2.vertices, w2.count, 0.0f, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + offset = { -10.0f, 5.0f }; + + // box-triangle + { + b2Polygon box = b2MakeBox( 1.0f, 1.0f ); + b2Vec2 points[3] = { { -0.05f, 0.0f }, { 0.05f, 0.0f }, { 0.0f, 0.1f } }; + b2Hull hull = b2ComputeHull( points, 3 ); + b2Polygon tri = b2MakePolygon( &hull, 0.0f ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + // b2Transform transform2 = {b2Add({0.0f, -0.1f}, offset), {0.0f, 1.0f}}; + + b2Manifold m = b2CollidePolygons( &box, transform1, &tri, transform2 ); + + g_draw.DrawSolidPolygon( transform1, box.vertices, box.count, 0.0f, color1 ); + g_draw.DrawSolidPolygon( transform2, tri.vertices, tri.count, 0.0f, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset = b2Add( offset, increment ); + } + + // chain-segment vs circle + { + b2ChainSegment segment = { { 2.0f, 1.0f }, { { 1.0f, 1.0f }, { -1.0f, 0.0f } }, { -2.0f, 0.0f }, -1 }; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m = b2CollideChainSegmentAndCircle( &segment, transform1, &circle, transform2 ); + + b2Vec2 g1 = b2TransformPoint( transform1, segment.ghost1 ); + b2Vec2 g2 = b2TransformPoint( transform1, segment.ghost2 ); + b2Vec2 p1 = b2TransformPoint( transform1, segment.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment.segment.point2 ); + g_draw.DrawSegment( g1, p1, b2_colorLightGray ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawSegment( p2, g2, b2_colorLightGray ); + g_draw.DrawSolidCircle( transform2, circle.center, circle.radius, color2 ); + + DrawManifold( &m, transform1.p, transform2.p ); + + offset.x += 2.0f * increment.x; + } + + // chain-segment vs rounded polygon + { + b2ChainSegment segment1 = { { 2.0f, 1.0f }, { { 1.0f, 1.0f }, { -1.0f, 0.0f } }, { -2.0f, 0.0f }, -1 }; + b2ChainSegment segment2 = { { 3.0f, 1.0f }, { { 2.0f, 1.0f }, { 1.0f, 1.0f } }, { -1.0f, 0.0f }, -1 }; + // b2ChainSegment segment1 = {{2.0f, 0.0f}, {{1.0f, 0.0f}, {-1.0f, 0.0f}}, {-2.0f, 0.0f}, -1}; + // b2ChainSegment segment2 = {{3.0f, 0.0f}, {{2.0f, 0.0f}, {1.0f, 0.0f}}, {-1.0f, 0.0f}, -1}; + // b2ChainSegment segment1 = {{0.5f, 1.0f}, {{0.0f, 2.0f}, {-0.5f, 1.0f}}, {-1.0f, 0.0f}, -1}; + // b2ChainSegment segment2 = {{1.0f, 0.0f}, {{0.5f, 1.0f}, {0.0f, 2.0f}}, {-0.5f, 1.0f}, -1}; + float h = 0.5f - m_round; + b2Polygon rox = b2MakeRoundedBox( h, h, m_round ); + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m1 = b2CollideChainSegmentAndPolygon( &segment1, transform1, &rox, transform2, &m_smgroxCache1 ); + b2Manifold m2 = b2CollideChainSegmentAndPolygon( &segment2, transform1, &rox, transform2, &m_smgroxCache2 ); + + { + b2Vec2 g2 = b2TransformPoint( transform1, segment1.ghost2 ); + b2Vec2 p1 = b2TransformPoint( transform1, segment1.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment1.segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawPoint( p1, 4.0f, color1 ); + g_draw.DrawPoint( p2, 4.0f, color1 ); + g_draw.DrawSegment( p2, g2, b2_colorLightGray ); + } + + { + b2Vec2 g1 = b2TransformPoint( transform1, segment2.ghost1 ); + b2Vec2 p1 = b2TransformPoint( transform1, segment2.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment2.segment.point2 ); + g_draw.DrawSegment( g1, p1, b2_colorLightGray ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawPoint( p1, 4.0f, color1 ); + g_draw.DrawPoint( p2, 4.0f, color1 ); + } + + g_draw.DrawSolidPolygon( transform2, rox.vertices, rox.count, rox.radius, color2 ); + g_draw.DrawPoint( b2TransformPoint( transform2, rox.centroid ), 5.0f, b2_colorGainsboro ); + + DrawManifold( &m1, transform1.p, transform2.p ); + DrawManifold( &m2, transform1.p, transform2.p ); + + offset.x += 2.0f * increment.x; + } + + // chain-segment vs capsule + { + b2ChainSegment segment1 = { { 2.0f, 1.0f }, { { 1.0f, 1.0f }, { -1.0f, 0.0f } }, { -2.0f, 0.0f }, -1 }; + b2ChainSegment segment2 = { { 3.0f, 1.0f }, { { 2.0f, 1.0f }, { 1.0f, 1.0f } }, { -1.0f, 0.0f }, -1 }; + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + + b2Transform transform1 = { offset, b2Rot_identity }; + b2Transform transform2 = { b2Add( m_transform.p, offset ), m_transform.q }; + + b2Manifold m1 = b2CollideChainSegmentAndCapsule( &segment1, transform1, &capsule, transform2, &m_smgcapCache1 ); + b2Manifold m2 = b2CollideChainSegmentAndCapsule( &segment2, transform1, &capsule, transform2, &m_smgcapCache2 ); + + { + b2Vec2 g2 = b2TransformPoint( transform1, segment1.ghost2 ); + b2Vec2 p1 = b2TransformPoint( transform1, segment1.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment1.segment.point2 ); + // g_draw.DrawSegment(g1, p1, b2_colorLightGray); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawPoint( p1, 4.0f, color1 ); + g_draw.DrawPoint( p2, 4.0f, color1 ); + g_draw.DrawSegment( p2, g2, b2_colorLightGray ); + } + + { + b2Vec2 g1 = b2TransformPoint( transform1, segment2.ghost1 ); + b2Vec2 p1 = b2TransformPoint( transform1, segment2.segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment2.segment.point2 ); + g_draw.DrawSegment( g1, p1, b2_colorLightGray ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawPoint( p1, 4.0f, color1 ); + g_draw.DrawPoint( p2, 4.0f, color1 ); + // g_draw.DrawSegment(p2, g2, b2_colorLightGray); + } + + b2Vec2 p1 = b2TransformPoint( transform2, capsule.center1 ); + b2Vec2 p2 = b2TransformPoint( transform2, capsule.center2 ); + g_draw.DrawSolidCapsule( p1, p2, capsule.radius, color2 ); + + g_draw.DrawPoint( b2Lerp( p1, p2, 0.5f ), 5.0f, b2_colorGainsboro ); + + DrawManifold( &m1, transform1.p, transform2.p ); + DrawManifold( &m2, transform1.p, transform2.p ); + + offset.x += 2.0f * increment.x; + } +#endif + } + + static Sample* Create( Settings& settings ) + { + return new Manifold( settings ); + } + + b2SimplexCache m_smgroxCache1; + b2SimplexCache m_smgroxCache2; + b2SimplexCache m_smgcapCache1; + b2SimplexCache m_smgcapCache2; + + b2Hull m_wedge; + + b2Transform m_transform; + float m_angle; + float m_round; + + b2Vec2 m_basePosition; + b2Vec2 m_startPoint; + float m_baseAngle; + + bool m_dragging; + bool m_rotating; + bool m_showCount; + bool m_showIds; + bool m_showAnchors; + bool m_showSeparation; + bool m_enableCaching; +}; + +static int sampleManifoldIndex = RegisterSample( "Collision", "Manifold", Manifold::Create ); + +class SmoothManifold : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_boxShape + }; + + explicit SmoothManifold( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.0f, 20.0f }; + g_camera.m_zoom = 21.0f; + } + + m_shapeType = e_boxShape; + m_transform = { { 0.0f, 20.0f }, b2Rot_identity }; + m_angle = 0.0f; + m_round = 0.0f; + + m_startPoint = { 0.0f, 00.0f }; + m_basePosition = { 0.0f, 0.0f }; + m_baseAngle = 0.0f; + + m_dragging = false; + m_rotating = false; + m_showIds = false; + m_showAnchors = false; + m_showSeparation = false; + + // https://betravis.github.io/shape-tools/path-to-polygon/ + m_count = 36; + + b2Vec2 points[36]; + points[0] = { -20.58325, 14.54175 }; + points[1] = { -21.90625, 15.8645 }; + points[2] = { -24.552, 17.1875 }; + points[3] = { -27.198, 11.89575 }; + points[4] = { -29.84375, 15.8645 }; + points[5] = { -29.84375, 21.15625 }; + points[6] = { -25.875, 23.802 }; + points[7] = { -20.58325, 25.125 }; + points[8] = { -25.875, 29.09375 }; + points[9] = { -20.58325, 31.7395 }; + points[10] = { -11.0089998, 23.2290001 }; + points[11] = { -8.67700005, 21.15625 }; + points[12] = { -6.03125, 21.15625 }; + points[13] = { -7.35424995, 29.09375 }; + points[14] = { -3.38549995, 29.09375 }; + points[15] = { 1.90625, 30.41675 }; + points[16] = { 5.875, 17.1875 }; + points[17] = { 11.16675, 25.125 }; + points[18] = { 9.84375, 29.09375 }; + points[19] = { 13.8125, 31.7395 }; + points[20] = { 21.75, 30.41675 }; + points[21] = { 28.3644981, 26.448 }; + points[22] = { 25.71875, 18.5105 }; + points[23] = { 24.3957481, 13.21875 }; + points[24] = { 17.78125, 11.89575 }; + points[25] = { 15.1355, 7.92700005 }; + points[26] = { 5.875, 9.25 }; + points[27] = { 1.90625, 11.89575 }; + points[28] = { -3.25, 11.89575 }; + points[29] = { -3.25, 9.9375 }; + points[30] = { -4.70825005, 9.25 }; + points[31] = { -8.67700005, 9.25 }; + points[32] = { -11.323, 11.89575 }; + points[33] = { -13.96875, 11.89575 }; + points[34] = { -15.29175, 14.54175 }; + points[35] = { -19.2605, 14.54175 }; + + m_segments = (b2ChainSegment*)malloc( m_count * sizeof( b2ChainSegment ) ); + + for ( int i = 0; i < m_count; ++i ) + { + int i0 = i > 0 ? i - 1 : m_count - 1; + int i1 = i; + int i2 = i1 < m_count - 1 ? i1 + 1 : 0; + int i3 = i2 < m_count - 1 ? i2 + 1 : 0; + + b2Vec2 g1 = points[i0]; + b2Vec2 p1 = points[i1]; + b2Vec2 p2 = points[i2]; + b2Vec2 g2 = points[i3]; + + m_segments[i] = { g1, { p1, p2 }, g2, -1 }; + } + } + + virtual ~SmoothManifold() override + { + free( m_segments ); + } + + void UpdateGui() override + { + float height = 290.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Smooth Manifold", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + { + const char* shapeTypes[] = { "Circle", "Box" }; + int shapeType = int( m_shapeType ); + ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_shapeType = ShapeType( shapeType ); + } + + ImGui::SliderFloat( "x Offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f" ); + ImGui::SliderFloat( "y Offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f" ); + + if ( ImGui::SliderFloat( "Angle", &m_angle, -B2_PI, B2_PI, "%.2f" ) ) + { + m_transform.q = b2MakeRot( m_angle ); + } + + ImGui::SliderFloat( "Round", &m_round, 0.0f, 0.4f, "%.1f" ); + ImGui::Checkbox( "Show Ids", &m_showIds ); + ImGui::Checkbox( "Show Separation", &m_showSeparation ); + ImGui::Checkbox( "Show Anchors", &m_showAnchors ); + + if ( ImGui::Button( "Reset" ) ) + { + m_transform = b2Transform_identity; + m_angle = 0.0f; + } + + ImGui::Separator(); + + ImGui::Text( "mouse button 1: drag" ); + ImGui::Text( "mouse button 1 + shift: rotate" ); + + ImGui::PopItemWidth(); + ImGui::End(); + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 && m_rotating == false ) + { + m_dragging = true; + m_startPoint = p; + m_basePosition = m_transform.p; + } + else if ( mods == GLFW_MOD_SHIFT && m_dragging == false ) + { + m_rotating = true; + m_startPoint = p; + m_baseAngle = m_angle; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_transform.p.x = m_basePosition.x + ( p.x - m_startPoint.x ); + m_transform.p.y = m_basePosition.y + ( p.y - m_startPoint.y ); + } + else if ( m_rotating ) + { + float dx = p.x - m_startPoint.x; + m_angle = b2ClampFloat( m_baseAngle + 1.0f * dx, -B2_PI, B2_PI ); + m_transform.q = b2MakeRot( m_angle ); + } + } + + void DrawManifold( const b2Manifold* manifold ) + { + for ( int i = 0; i < manifold->pointCount; ++i ) + { + const b2ManifoldPoint* mp = manifold->points + i; + + b2Vec2 p1 = mp->point; + b2Vec2 p2 = b2MulAdd( p1, 0.5f, manifold->normal ); + g_draw.DrawSegment( p1, p2, b2_colorWhite ); + + if ( m_showAnchors ) + { + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + } + else + { + g_draw.DrawPoint( p1, 5.0f, b2_colorGreen ); + } + + if ( m_showIds ) + { + // uint32_t indexA = mp->id >> 8; + // uint32_t indexB = 0xFF & mp->id; + b2Vec2 p = { p1.x + 0.05f, p1.y - 0.02f }; + g_draw.DrawString( p, "0x%04x", mp->id ); + } + + if ( m_showSeparation ) + { + b2Vec2 p = { p1.x + 0.05f, p1.y + 0.03f }; + g_draw.DrawString( p, "%.3f", mp->separation ); + } + } + } + + void Step( Settings& ) override + { + b2HexColor color1 = b2_colorYellow; + b2HexColor color2 = b2_colorMagenta; + + b2Transform transform1 = b2Transform_identity; + b2Transform transform2 = m_transform; + + for ( int i = 0; i < m_count; ++i ) + { + const b2ChainSegment* segment = m_segments + i; + b2Vec2 p1 = b2TransformPoint( transform1, segment->segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform1, segment->segment.point2 ); + g_draw.DrawSegment( p1, p2, color1 ); + g_draw.DrawPoint( p1, 4.0f, color1 ); + } + + // chain-segment vs circle + if ( m_shapeType == e_circleShape ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + g_draw.DrawSolidCircle( transform2, circle.center, circle.radius, color2 ); + + for ( int i = 0; i < m_count; ++i ) + { + const b2ChainSegment* segment = m_segments + i; + b2Manifold m = b2CollideChainSegmentAndCircle( segment, transform1, &circle, transform2 ); + DrawManifold( &m ); + } + } + else if ( m_shapeType == e_boxShape ) + { + float h = 0.5f - m_round; + b2Polygon rox = b2MakeRoundedBox( h, h, m_round ); + g_draw.DrawSolidPolygon( transform2, rox.vertices, rox.count, rox.radius, color2 ); + + for ( int i = 0; i < m_count; ++i ) + { + const b2ChainSegment* segment = m_segments + i; + b2SimplexCache cache = {}; + b2Manifold m = b2CollideChainSegmentAndPolygon( segment, transform1, &rox, transform2, &cache ); + DrawManifold( &m ); + } + } + } + + static Sample* Create( Settings& settings ) + { + return new SmoothManifold( settings ); + } + + ShapeType m_shapeType; + + b2ChainSegment* m_segments; + int m_count; + + b2Transform m_transform; + float m_angle; + float m_round; + + b2Vec2 m_basePosition; + b2Vec2 m_startPoint; + float m_baseAngle; + + bool m_dragging; + bool m_rotating; + bool m_showIds; + bool m_showAnchors; + bool m_showSeparation; +}; + +static int sampleSmoothManifoldIndex = RegisterSample( "Collision", "Smooth Manifold", SmoothManifold::Create ); + +class ShapeCast : public Sample +{ +public: + enum ShapeType + { + e_point, + e_segment, + e_triangle, + e_box + }; + + explicit ShapeCast( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.25f }; + g_camera.m_zoom = 3.0f; + } + + m_point = b2Vec2_zero; + m_segment = { { 0.0f, 0.0f }, { 0.5f, 0.0f } }; + + { + b2Vec2 points[3] = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, { 0.0f, 1.0f } }; + b2Hull hull = b2ComputeHull( points, 3 ); + m_triangle = b2MakePolygon( &hull, 0.0f ); + } + + m_box = b2MakeOffsetBox( 0.5f, 0.5f, { 1.0f, 0.0f }, b2Rot_identity ); + + m_transform = { { 0.0f, 0.0f }, b2Rot_identity }; + m_translation = { 1.0f, 0.0f }; + m_angle = 0.0f; + m_startPoint = { 0.0f, 0.0f }; + m_basePosition = { 0.0f, 0.0f }; + m_baseAngle = 0.0f; + + m_dragging = false; + m_sweeping = false; + m_rotating = false; + m_showIndices = false; + m_drawSimplex = false; + m_encroach = false; + + m_typeA = e_box; + m_typeB = e_point; + m_radiusA = 0.0f; + m_radiusB = 0.1f; + + m_proxyA = MakeProxy( m_typeA, m_radiusA ); + m_proxyB = MakeProxy( m_typeB, m_radiusB ); + } + + b2ShapeProxy MakeProxy( ShapeType type, float radius ) const + { + b2ShapeProxy proxy = {}; + proxy.radius = radius; + + switch ( type ) + { + case e_point: + proxy.points[0] = b2Vec2_zero; + proxy.count = 1; + break; + + case e_segment: + proxy.points[0] = m_segment.point1; + proxy.points[1] = m_segment.point2; + proxy.count = 2; + break; + + case e_triangle: + for ( int i = 0; i < m_triangle.count; ++i ) + { + proxy.points[i] = m_triangle.vertices[i]; + } + proxy.count = m_triangle.count; + break; + + case e_box: + proxy.points[0] = m_box.vertices[0]; + proxy.points[1] = m_box.vertices[1]; + proxy.points[2] = m_box.vertices[2]; + proxy.points[3] = m_box.vertices[3]; + proxy.count = 4; + break; + + default: + assert( false ); + } + + return proxy; + } + + void DrawShape( ShapeType type, b2Transform transform, float radius, b2HexColor color ) + { + switch ( type ) + { + case e_point: + { + b2Vec2 p = b2TransformPoint( transform, m_point ); + if ( radius > 0.0f ) + { + g_draw.DrawSolidCircle( transform, m_point, radius, color ); + } + else + { + g_draw.DrawPoint( p, 5.0f, color ); + } + } + break; + + case e_segment: + { + b2Vec2 p1 = b2TransformPoint( transform, m_segment.point1 ); + b2Vec2 p2 = b2TransformPoint( transform, m_segment.point2 ); + + if ( radius > 0.0f ) + { + g_draw.DrawSolidCapsule( p1, p2, radius, color ); + } + else + { + g_draw.DrawSegment( p1, p2, color ); + } + } + break; + + case e_triangle: + g_draw.DrawSolidPolygon( transform, m_triangle.vertices, m_triangle.count, radius, color ); + break; + + case e_box: + g_draw.DrawSolidPolygon( transform, m_box.vertices, m_box.count, radius, color ); + break; + + default: + assert( false ); + } + } + + void MouseDown( b2Vec2 p, int button, int mods ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + if ( mods == 0 ) + { + m_dragging = true; + m_sweeping = false; + m_rotating = false; + m_startPoint = p; + m_basePosition = m_transform.p; + } + else if ( mods == GLFW_MOD_SHIFT ) + { + m_dragging = false; + m_sweeping = false; + m_rotating = true; + m_startPoint = p; + m_baseAngle = m_angle; + } + else if ( mods == GLFW_MOD_CONTROL ) + { + m_dragging = false; + m_sweeping = true; + m_rotating = false; + m_startPoint = p; + m_basePosition = b2Vec2_zero; + } + } + } + + void MouseUp( b2Vec2, int button ) override + { + if ( button == GLFW_MOUSE_BUTTON_1 ) + { + m_dragging = false; + m_sweeping = false; + m_rotating = false; + } + } + + void MouseMove( b2Vec2 p ) override + { + if ( m_dragging ) + { + m_transform.p = m_basePosition + 0.5f * ( p - m_startPoint ); + } + else if ( m_rotating ) + { + float dx = p.x - m_startPoint.x; + m_angle = b2ClampFloat( m_baseAngle + 1.0f * dx, -B2_PI, B2_PI ); + m_transform.q = b2MakeRot( m_angle ); + } + else if ( m_sweeping ) + { + m_translation = p - m_startPoint; + } + } + + void UpdateGui() override + { + float height = 300.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Shape Distance", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + const char* shapeTypes[] = { "point", "segment", "triangle", "box" }; + int shapeType = int( m_typeA ); + if ( ImGui::Combo( "shape A", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_typeA = ShapeType( shapeType ); + m_proxyA = MakeProxy( m_typeA, m_radiusA ); + } + + if ( ImGui::SliderFloat( "radius A", &m_radiusA, 0.0f, 0.5f, "%.2f" ) ) + { + m_proxyA.radius = m_radiusA; + } + + shapeType = int( m_typeB ); + if ( ImGui::Combo( "shape B", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_typeB = ShapeType( shapeType ); + m_proxyB = MakeProxy( m_typeB, m_radiusB ); + } + + if ( ImGui::SliderFloat( "radius B", &m_radiusB, 0.0f, 0.5f, "%.2f" ) ) + { + m_proxyB.radius = m_radiusB; + } + + ImGui::Separator(); + + ImGui::SliderFloat( "x offset", &m_transform.p.x, -2.0f, 2.0f, "%.2f" ); + ImGui::SliderFloat( "y offset", &m_transform.p.y, -2.0f, 2.0f, "%.2f" ); + + if ( ImGui::SliderFloat( "angle", &m_angle, -B2_PI, B2_PI, "%.2f" ) ) + { + m_transform.q = b2MakeRot( m_angle ); + } + + ImGui::Separator(); + + ImGui::Checkbox( "show indices", &m_showIndices ); + ImGui::Checkbox( "encroach", &m_encroach ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2ShapeCastPairInput input = {}; + input.proxyA = m_proxyA; + input.proxyB = m_proxyB; + input.transformA = b2Transform_identity; + input.transformB = m_transform; + input.translationB = m_translation; + input.maxFraction = 1.0f; + input.canEncroach = m_encroach; + + b2CastOutput output = b2ShapeCast( &input ); + + b2Transform transform; + transform.q = m_transform.q; + transform.p = b2MulAdd( m_transform.p, output.fraction, input.translationB ); + + b2DistanceInput distanceInput; + distanceInput.proxyA = m_proxyA; + distanceInput.proxyB = m_proxyB; + distanceInput.transformA = b2Transform_identity; + distanceInput.transformB = transform; + distanceInput.useRadii = false; + b2SimplexCache distanceCache; + distanceCache.count = 0; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &distanceCache, nullptr, 0 ); + + DrawTextLine( "hit = %s, iterations = %d, lambda = %g, distance = %g", output.hit ? "true" : "false", output.iterations, + output.fraction, distanceOutput.distance ); + + DrawShape( m_typeA, b2Transform_identity, m_radiusA, b2_colorCyan ); + DrawShape( m_typeB, m_transform, m_radiusB, b2_colorLightGreen ); + b2Transform transform2 = { m_transform.p + m_translation, m_transform.q }; + DrawShape( m_typeB, transform2, m_radiusB, b2_colorIndianRed ); + + if ( output.hit ) + { + DrawShape( m_typeB, transform, m_radiusB, b2_colorPlum ); + g_draw.DrawPoint( output.point, 5.0f, b2_colorWhite ); + g_draw.DrawSegment( output.point, output.point + 0.5f * output.normal, b2_colorYellow ); + } + + if ( m_showIndices ) + { + for ( int i = 0; i < m_proxyA.count; ++i ) + { + b2Vec2 p = m_proxyA.points[i]; + g_draw.DrawString( p, " %d", i ); + } + + for ( int i = 0; i < m_proxyB.count; ++i ) + { + b2Vec2 p = b2TransformPoint( m_transform, m_proxyB.points[i] ); + g_draw.DrawString( p, " %d", i ); + } + } + + DrawTextLine( "mouse button 1: drag" ); + DrawTextLine( "mouse button 1 + shift: rotate" ); + DrawTextLine( "mouse button 1 + control: sweep" ); + DrawTextLine( "distance = %.2f, iterations = %d", distanceOutput.distance, output.iterations ); + } + + static Sample* Create( Settings& settings ) + { + return new ShapeCast( settings ); + } + + b2Polygon m_box; + b2Polygon m_triangle; + b2Vec2 m_point; + b2Segment m_segment; + + ShapeType m_typeA; + ShapeType m_typeB; + float m_radiusA; + float m_radiusB; + b2ShapeProxy m_proxyA; + b2ShapeProxy m_proxyB; + + b2Transform m_transform; + float m_angle; + b2Vec2 m_translation; + + b2Vec2 m_basePosition; + b2Vec2 m_startPoint; + float m_baseAngle; + + bool m_dragging; + bool m_sweeping; + bool m_rotating; + bool m_showIndices; + bool m_drawSimplex; + bool m_encroach; +}; + +static int sampleShapeCast = RegisterSample( "Collision", "Shape Cast", ShapeCast::Create ); + +class TimeOfImpact : public Sample +{ +public: + explicit TimeOfImpact( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.6f, 2.0f }; + g_camera.m_center = { -16, 45 }; + g_camera.m_zoom = 5.0f; + } + } + + static Sample* Create( Settings& settings ) + { + return new TimeOfImpact( settings ); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2Sweep sweepA = { + b2Vec2_zero, { 0.0f, 0.0f }, { 0.0f, 0.0f }, b2Rot_identity, b2Rot_identity, + }; + b2Sweep sweepB = { + b2Vec2_zero, + { -15.8332710, 45.3520279 }, + { -15.8324337, 45.3413048 }, + { -0.540891349, 0.841092527 }, + { -0.457797021, 0.889056742 }, + }; + + b2TOIInput input; + input.proxyA = b2MakeProxy( m_verticesA, m_countA, m_radiusA ); + input.proxyB = b2MakeProxy( m_verticesB, m_countB, m_radiusB ); + input.sweepA = sweepA; + input.sweepB = sweepB; + input.maxFraction = 1.0f; + + b2TOIOutput output = b2TimeOfImpact( &input ); + + g_draw.DrawString( 5, m_textLine, "toi = %g", output.fraction ); + m_textLine += m_textIncrement; + + // g_draw.DrawString(5, m_textLine, "max toi iters = %d, max root iters = %d", b2_toiMaxIters, + // b2_toiMaxRootIters); + m_textLine += m_textIncrement; + + b2Vec2 vertices[B2_MAX_POLYGON_VERTICES]; + + // Draw A + b2Transform transformA = b2GetSweepTransform( &sweepA, 0.0f ); + for ( int i = 0; i < m_countA; ++i ) + { + vertices[i] = b2TransformPoint( transformA, m_verticesA[i] ); + } + g_draw.DrawPolygon( vertices, m_countA, b2_colorGray ); + + // Draw B at t = 0 + b2Transform transformB = b2GetSweepTransform( &sweepB, 0.0f ); + for ( int i = 0; i < m_countB; ++i ) + { + vertices[i] = b2TransformPoint( transformB, m_verticesB[i] ); + } + g_draw.DrawSolidCapsule( vertices[0], vertices[1], m_radiusB, b2_colorGreen ); + // g_draw.DrawPolygon( vertices, m_countB, b2_colorGreen ); + + // Draw B at t = hit_time + transformB = b2GetSweepTransform( &sweepB, output.fraction ); + for ( int i = 0; i < m_countB; ++i ) + { + vertices[i] = b2TransformPoint( transformB, m_verticesB[i] ); + } + g_draw.DrawPolygon( vertices, m_countB, b2_colorOrange ); + + // Draw B at t = 1 + transformB = b2GetSweepTransform( &sweepB, 1.0f ); + for ( int i = 0; i < m_countB; ++i ) + { + vertices[i] = b2TransformPoint( transformB, m_verticesB[i] ); + } + g_draw.DrawSolidCapsule( vertices[0], vertices[1], m_radiusB, b2_colorRed ); + // g_draw.DrawPolygon( vertices, m_countB, b2_colorRed ); + + if ( output.state == b2_toiStateHit ) + { + b2DistanceInput distanceInput; + distanceInput.proxyA = input.proxyA; + distanceInput.proxyB = input.proxyB; + distanceInput.transformA = b2GetSweepTransform( &sweepA, output.fraction ); + distanceInput.transformB = b2GetSweepTransform( &sweepB, output.fraction ); + distanceInput.useRadii = false; + b2SimplexCache cache = { 0 }; + b2DistanceOutput distanceOutput = b2ShapeDistance( &distanceInput, &cache, nullptr, 0 ); + g_draw.DrawString( 5, m_textLine, "distance = %g", distanceOutput.distance ); + m_textLine += m_textIncrement; + } + +#if 0 + for (float t = 0.0f; t < 1.0f; t += 0.1f) + { + transformB = b2GetSweepTransform(&sweepB, t); + for (int i = 0; i < m_countB; ++i) + { + vertices[i] = b2TransformPoint(transformB, m_verticesB[i]); + } + g_draw.DrawPolygon(vertices, m_countB, {0.3f, 0.3f, 0.3f}); + } +#endif + } + + b2Vec2 m_verticesA[4] = { { -16.25, 44.75 }, { -15.75, 44.75 }, { -15.75, 45.25 }, { -16.25, 45.25 } }; + b2Vec2 m_verticesB[2] = { { 0.0f, -0.125000000f }, { 0.0f, 0.125000000f } }; + + int m_countA = ARRAY_COUNT( m_verticesA ); + int m_countB = ARRAY_COUNT( m_verticesB ); + + float m_radiusA = 0.0f; + float m_radiusB = 0.0299999993f; +}; + +static int sampleTimeOfImpact = RegisterSample( "Collision", "Time of Impact", TimeOfImpact::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_continuous.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_continuous.cpp new file mode 100644 index 000000000000..491978bd918d --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_continuous.cpp @@ -0,0 +1,1772 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "human.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +// extern "C" int b2_toiHitCount; + +class BounceHouse : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_capsuleShape, + e_boxShape + }; + + struct HitEvent + { + b2Vec2 point; + float speed; + int stepIndex; + }; + + explicit BounceHouse( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 0.45f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + { + b2Segment segment = { { -10.0f, -10.0f }, { 10.0f, -10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { 10.0f, -10.0f }, { 10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { 10.0f, 10.0f }, { -10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { -10.0f, 10.0f }, { -10.0f, -10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + m_shapeType = e_boxShape; + m_bodyId = b2_nullBodyId; + m_enableHitEvents = true; + + memset( m_hitEvents, 0, sizeof( m_hitEvents ) ); + + Launch(); + } + + void Launch() + { + if ( B2_IS_NON_NULL( m_bodyId ) ) + { + b2DestroyBody( m_bodyId ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.linearVelocity = { 10.0f, 20.0f }; + bodyDef.position = { 0.0f, 0.0f }; + bodyDef.gravityScale = 0.0f; + + // Circle shapes centered on the body can spin fast without risk of tunnelling. + bodyDef.allowFastRotation = m_shapeType == e_circleShape; + + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.restitution = 1.2f; + shapeDef.material.friction = 0.3f; + shapeDef.enableHitEvents = m_enableHitEvents; + + if ( m_shapeType == e_circleShape ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( m_bodyId, &shapeDef, &circle ); + } + else if ( m_shapeType == e_capsuleShape ) + { + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule ); + } + else + { + float h = 0.1f; + b2Polygon box = b2MakeBox( 20.0f * h, h ); + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Bounce House", nullptr, ImGuiWindowFlags_NoResize ); + + const char* shapeTypes[] = { "Circle", "Capsule", "Box" }; + int shapeType = int( m_shapeType ); + if ( ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_shapeType = ShapeType( shapeType ); + Launch(); + } + + if ( ImGui::Checkbox( "hit events", &m_enableHitEvents ) ) + { + b2Body_EnableHitEvents( m_bodyId, m_enableHitEvents ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2ContactEvents events = b2World_GetContactEvents( m_worldId ); + for ( int i = 0; i < events.hitCount; ++i ) + { + b2ContactHitEvent* event = events.hitEvents + i; + + HitEvent* e = m_hitEvents + 0; + for ( int j = 1; j < 4; ++j ) + { + if ( m_hitEvents[j].stepIndex < e->stepIndex ) + { + e = m_hitEvents + j; + } + } + + e->point = event->point; + e->speed = event->approachSpeed; + e->stepIndex = m_stepCount; + } + + for ( int i = 0; i < 4; ++i ) + { + HitEvent* e = m_hitEvents + i; + if ( e->stepIndex > 0 && m_stepCount <= e->stepIndex + 30 ) + { + g_draw.DrawCircle( e->point, 0.1f, b2_colorOrangeRed ); + g_draw.DrawString( e->point, "%.1f", e->speed ); + } + } + + if ( m_stepCount == 1000 ) + { + m_stepCount += 0; + } + } + + static Sample* Create( Settings& settings ) + { + return new BounceHouse( settings ); + } + + HitEvent m_hitEvents[4]; + b2BodyId m_bodyId; + ShapeType m_shapeType; + bool m_enableHitEvents; +}; + +static int sampleBounceHouse = RegisterSample( "Continuous", "Bounce House", BounceHouse::Create ); + +class BounceHumans : public Sample +{ +public: + explicit BounceHumans( Settings& settings ) + : Sample( settings ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 12.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.restitution = 1.3f; + shapeDef.material.friction = 0.1f; + + { + b2Segment segment = { { -10.0f, -10.0f }, { 10.0f, -10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { 10.0f, -10.0f }, { 10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { 10.0f, 10.0f }, { -10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2Segment segment = { { -10.0f, 10.0f }, { -10.0f, -10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + b2Circle circle = { { 0.0f, 0.0f }, 2.0f }; + shapeDef.material.restitution = 2.0f; + b2CreateCircleShape( groundId, &shapeDef, &circle ); + } + + void Step( Settings& settings ) override + { + if ( m_humanCount < 5 && m_countDown <= 0.0f ) + { + float jointFrictionTorque = 0.0f; + float jointHertz = 1.0f; + float jointDampingRatio = 0.1f; + + CreateHuman( m_humans + m_humanCount, m_worldId, { 0.0f, 5.0f }, 1.0f, jointFrictionTorque, jointHertz, + jointDampingRatio, 1, nullptr, true ); + // Human_SetVelocity( m_humans + m_humanCount, { 10.0f - 5.0f * m_humanCount, -20.0f + 5.0f * m_humanCount } ); + + m_countDown = 2.0f; + m_humanCount += 1; + } + + float timeStep = 1.0f / 60.0f; + b2CosSin cs1 = b2ComputeCosSin( 0.5f * m_time ); + b2CosSin cs2 = b2ComputeCosSin( m_time ); + float gravity = 10.0f; + b2Vec2 gravityVec = { gravity * cs1.sine, gravity * cs2.cosine }; + g_draw.DrawSegment( b2Vec2_zero, b2Vec2{ 3.0f * cs1.sine, 3.0f * cs2.cosine }, b2_colorWhite ); + m_time += timeStep; + m_countDown -= timeStep; + b2World_SetGravity( m_worldId, gravityVec ); + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BounceHumans( settings ); + } + + Human m_humans[5] = {}; + int m_humanCount = 0; + float m_countDown = 0.0f; + float m_time = 0.0f; +}; + +static int sampleBounceHumans = RegisterSample( "Continuous", "Bounce Humans", BounceHumans::Create ); + +class ChainDrop : public Sample +{ +public: + explicit ChainDrop( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 0.35f; + } + + // + // b2World_SetContactTuning( m_worldId, 30.0f, 1.0f, 100.0f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -6.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Vec2 points[4] = { { -10.0f, -2.0f }, { 10.0f, -2.0f }, { 10.0f, 1.0f }, { -10.0f, 1.0f } }; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = 4; + chainDef.isLoop = true; + + b2CreateChain( groundId, &chainDef ); + + m_bodyId = b2_nullBodyId; + m_yOffset = -0.1f; + m_speed = -42.0f; + + Launch(); + } + + void Launch() + { + if ( B2_IS_NON_NULL( m_bodyId ) ) + { + b2DestroyBody( m_bodyId ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.linearVelocity = { 0.0f, m_speed }; + bodyDef.position = { 0.0f, 10.0f + m_yOffset }; + bodyDef.rotation = b2MakeRot( 0.5f * B2_PI ); + bodyDef.fixedRotation = true; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + m_shapeId = b2CreateCircleShape( m_bodyId, &shapeDef, &circle ); + + // b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + // m_shapeId = b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule ); + + // float h = 0.5f; + // b2Polygon box = b2MakeBox( h, h ); + // m_shapeId = b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Chain Drop", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::SliderFloat( "Speed", &m_speed, -100.0f, 0.0f, "%.0f" ); + ImGui::SliderFloat( "Y Offset", &m_yOffset, -1.0f, 1.0f, "%.1f" ); + + if ( ImGui::Button( "Launch" ) ) + { + Launch(); + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new ChainDrop( settings ); + } + + b2BodyId m_bodyId; + b2ShapeId m_shapeId; + float m_yOffset; + float m_speed; +}; + +static int sampleChainDrop = RegisterSample( "Continuous", "Chain Drop", ChainDrop::Create ); + +class ChainSlide : public Sample +{ +public: + explicit ChainSlide( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 10.0f }; + g_camera.m_zoom = 15.0f; + } + + // b2_toiHitCount = 0; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + constexpr int count = 80; + b2Vec2 points[count]; + + float w = 2.0f; + float h = 1.0f; + float x = 20.0f, y = 0.0f; + for ( int i = 0; i < 20; ++i ) + { + points[i] = { x, y }; + x -= w; + } + + for ( int i = 20; i < 40; ++i ) + { + points[i] = { x, y }; + y += h; + } + + for ( int i = 40; i < 60; ++i ) + { + points[i] = { x, y }; + x += w; + } + + for ( int i = 60; i < 80; ++i ) + { + points[i] = { x, y }; + y -= h; + } + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + + b2CreateChain( groundId, &chainDef ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.linearVelocity = { 100.0f, 0.0f }; + bodyDef.position = { -19.5f, 0.0f + 0.5f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.0f; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + // DrawTextLine( "toi hits = %d", b2_toiHitCount ); + } + + static Sample* Create( Settings& settings ) + { + return new ChainSlide( settings ); + } +}; + +static int sampleChainSlide = RegisterSample( "Continuous", "Chain Slide", ChainSlide::Create ); + +class SegmentSlide : public Sample +{ +public: + explicit SegmentSlide( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 10.0f }; + g_camera.m_zoom = 15.0f; + } + + // b2_toiHitCount = 0; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + segment = { { 40.0f, 0.0f }, { 40.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.linearVelocity = { 100.0f, 0.0f }; + bodyDef.position = { -20.0f, 0.7f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + // shapeDef.friction = 0.0f; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + // DrawTextLine("toi hits = %d", b2_toiHitCount ); + } + + static Sample* Create( Settings& settings ) + { + return new SegmentSlide( settings ); + } +}; + +static int sampleSegmentSlide = RegisterSample( "Continuous", "Segment Slide", SegmentSlide::Create ); + +class SkinnyBox : public Sample +{ +public: + explicit SkinnyBox( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 1.0f, 5.0f }; + g_camera.m_zoom = 25.0f * 0.25f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.9f; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + b2Polygon box = b2MakeOffsetBox( 0.1f, 1.0f, { 0.0f, 1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + m_autoTest = false; + m_bullet = false; + m_capsule = false; + + m_bodyId = b2_nullBodyId; + m_bulletId = b2_nullBodyId; + + Launch(); + } + + void Launch() + { + if ( B2_IS_NON_NULL( m_bodyId ) ) + { + b2DestroyBody( m_bodyId ); + } + + if ( B2_IS_NON_NULL( m_bulletId ) ) + { + b2DestroyBody( m_bulletId ); + } + + m_angularVelocity = RandomFloatRange( -50.0f, 50.0f ); + // m_angularVelocity = -30.6695766f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 8.0f }; + bodyDef.angularVelocity = m_angularVelocity; + bodyDef.linearVelocity = { 0.0f, -100.0f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.9f; + + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + if ( m_capsule ) + { + b2Capsule capsule = { { 0.0f, -1.0f }, { 0.0f, 1.0f }, 0.1f }; + b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule ); + } + else + { + b2Polygon polygon = b2MakeBox( 2.0f, 0.05f ); + b2CreatePolygonShape( m_bodyId, &shapeDef, &polygon ); + } + + if ( m_bullet ) + { + b2Polygon polygon = b2MakeBox( 0.25f, 0.25f ); + m_x = RandomFloatRange( -1.0f, 1.0f ); + bodyDef.position = { m_x, 10.0f }; + bodyDef.linearVelocity = { 0.0f, -50.0f }; + m_bulletId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bulletId, &shapeDef, &polygon ); + } + } + + void UpdateGui() override + { + float height = 110.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 140.0f, height ) ); + + ImGui::Begin( "Skinny Box", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::Checkbox( "Capsule", &m_capsule ); + + if ( ImGui::Button( "Launch" ) ) + { + Launch(); + } + + ImGui::Checkbox( "Auto Test", &m_autoTest ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if ( m_autoTest && m_stepCount % 60 == 0 ) + { + Launch(); + } + } + + static Sample* Create( Settings& settings ) + { + return new SkinnyBox( settings ); + } + + b2BodyId m_bodyId, m_bulletId; + float m_angularVelocity; + float m_x; + bool m_capsule; + bool m_autoTest; + bool m_bullet; +}; + +static int sampleSkinnyBox = RegisterSample( "Continuous", "Skinny Box", SkinnyBox::Create ); + +// This sample shows ghost bumps +class GhostBumps : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_capsuleShape, + e_boxShape + }; + + explicit GhostBumps( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 1.5f, 16.0f }; + g_camera.m_zoom = 25.0f * 0.8f; + } + + m_groundId = b2_nullBodyId; + m_bodyId = b2_nullBodyId; + m_shapeId = b2_nullShapeId; + m_shapeType = e_circleShape; + m_round = 0.0f; + m_friction = 0.2f; + m_bevel = 0.0f; + m_useChain = true; + + CreateScene(); + Launch(); + } + + void CreateScene() + { + if ( B2_IS_NON_NULL( m_groundId ) ) + { + b2DestroyBody( m_groundId ); + } + + m_shapeId = b2_nullShapeId; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + + float m = 1.0f / sqrt( 2.0f ); + float mm = 2.0f * ( sqrt( 2.0f ) - 1.0f ); + float hx = 4.0f, hy = 0.25f; + + if ( m_useChain ) + { + b2Vec2 points[20]; + points[0] = { -3.0f * hx, hy }; + points[1] = b2Add( points[0], { -2.0f * hx * m, 2.0f * hx * m } ); + points[2] = b2Add( points[1], { -2.0f * hx * m, 2.0f * hx * m } ); + points[3] = b2Add( points[2], { -2.0f * hx * m, 2.0f * hx * m } ); + points[4] = b2Add( points[3], { -2.0f * hy * m, -2.0f * hy * m } ); + points[5] = b2Add( points[4], { 2.0f * hx * m, -2.0f * hx * m } ); + points[6] = b2Add( points[5], { 2.0f * hx * m, -2.0f * hx * m } ); + points[7] = + b2Add( points[6], { 2.0f * hx * m + 2.0f * hy * ( 1.0f - m ), -2.0f * hx * m - 2.0f * hy * ( 1.0f - m ) } ); + points[8] = b2Add( points[7], { 2.0f * hx + hy * mm, 0.0f } ); + points[9] = b2Add( points[8], { 2.0f * hx, 0.0f } ); + points[10] = b2Add( points[9], { 2.0f * hx + hy * mm, 0.0f } ); + points[11] = + b2Add( points[10], { 2.0f * hx * m + 2.0f * hy * ( 1.0f - m ), 2.0f * hx * m + 2.0f * hy * ( 1.0f - m ) } ); + points[12] = b2Add( points[11], { 2.0f * hx * m, 2.0f * hx * m } ); + points[13] = b2Add( points[12], { 2.0f * hx * m, 2.0f * hx * m } ); + points[14] = b2Add( points[13], { -2.0f * hy * m, 2.0f * hy * m } ); + points[15] = b2Add( points[14], { -2.0f * hx * m, -2.0f * hx * m } ); + points[16] = b2Add( points[15], { -2.0f * hx * m, -2.0f * hx * m } ); + points[17] = b2Add( points[16], { -2.0f * hx * m, -2.0f * hx * m } ); + points[18] = b2Add( points[17], { -2.0f * hx, 0.0f } ); + points[19] = b2Add( points[18], { -2.0f * hx, 0.0f } ); + + b2SurfaceMaterial material = {}; + material.friction = m_friction; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = 20; + chainDef.isLoop = true; + chainDef.materials = &material; + chainDef.materialCount = 1; + + b2CreateChain( m_groundId, &chainDef ); + } + else + { + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = m_friction; + + b2Hull hull = {}; + + if ( m_bevel > 0.0f ) + { + float hb = m_bevel; + b2Vec2 vs[8] = { { hx + hb, hy - 0.05f }, { hx, hy }, { -hx, hy }, { -hx - hb, hy - 0.05f }, + { -hx - hb, -hy + 0.05f }, { -hx, -hy }, { hx, -hy }, { hx + hb, -hy + 0.05f } }; + hull = b2ComputeHull( vs, 8 ); + } + else + { + b2Vec2 vs[4] = { { hx, hy }, { -hx, hy }, { -hx, -hy }, { hx, -hy } }; + hull = b2ComputeHull( vs, 4 ); + } + + b2Transform transform; + float x, y; + + // Left slope + x = -3.0f * hx - m * hx - m * hy; + y = hy + m * hx - m * hy; + transform.q = b2MakeRot( -0.25f * B2_PI ); + + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x -= 2.0f * m * hx; + y += 2.0f * m * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x -= 2.0f * m * hx; + y += 2.0f * m * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x -= 2.0f * m * hx; + y += 2.0f * m * hx; + } + + x = -2.0f * hx; + y = 0.0f; + transform.q = b2MakeRot( 0.0f ); + + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * hx; + } + + x = 3.0f * hx + m * hx + m * hy; + y = hy + m * hx - m * hy; + transform.q = b2MakeRot( 0.25f * B2_PI ); + + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * m * hx; + y += 2.0f * m * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * m * hx; + y += 2.0f * m * hx; + } + { + transform.p = { x, y }; + b2Polygon polygon = b2MakeOffsetPolygon( &hull, transform.p, transform.q ); + b2CreatePolygonShape( m_groundId, &shapeDef, &polygon ); + x += 2.0f * m * hx; + y += 2.0f * m * hx; + } + } + } + + void Launch() + { + if ( B2_IS_NON_NULL( m_bodyId ) ) + { + b2DestroyBody( m_bodyId ); + m_shapeId = b2_nullShapeId; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -28.0f, 18.0f }; + bodyDef.linearVelocity = { 0.0f, 0.0f }; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = m_friction; + + if ( m_shapeType == e_circleShape ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + m_shapeId = b2CreateCircleShape( m_bodyId, &shapeDef, &circle ); + } + else if ( m_shapeType == e_capsuleShape ) + { + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + m_shapeId = b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule ); + } + else + { + float h = 0.5f - m_round; + b2Polygon box = b2MakeRoundedBox( h, 2.0f * h, m_round ); + m_shapeId = b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Ghost Bumps", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + if ( ImGui::Checkbox( "Chain", &m_useChain ) ) + { + CreateScene(); + } + + if ( m_useChain == false ) + { + if ( ImGui::SliderFloat( "Bevel", &m_bevel, 0.0f, 1.0f, "%.2f" ) ) + { + CreateScene(); + } + } + + { + const char* shapeTypes[] = { "Circle", "Capsule", "Box" }; + int shapeType = int( m_shapeType ); + ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_shapeType = ShapeType( shapeType ); + } + + if ( m_shapeType == e_boxShape ) + { + ImGui::SliderFloat( "Round", &m_round, 0.0f, 0.4f, "%.1f" ); + } + + if ( ImGui::SliderFloat( "Friction", &m_friction, 0.0f, 1.0f, "%.1f" ) ) + { + if ( B2_IS_NON_NULL( m_shapeId ) ) + { + b2Shape_SetFriction( m_shapeId, m_friction ); + } + + CreateScene(); + } + + if ( ImGui::Button( "Launch" ) ) + { + Launch(); + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new GhostBumps( settings ); + } + + b2BodyId m_groundId; + b2BodyId m_bodyId; + b2ShapeId m_shapeId; + ShapeType m_shapeType; + float m_round; + float m_friction; + float m_bevel; + bool m_useChain; +}; + +static int sampleGhostCollision = RegisterSample( "Continuous", "Ghost Bumps", GhostBumps::Create ); + +// Speculative collision failure case suggested by Dirk Gregorius. This uses +// a simple fallback scheme to prevent tunneling. +class SpeculativeFallback : public Sample +{ +public: + explicit SpeculativeFallback( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 1.0f, 5.0f }; + g_camera.m_zoom = 25.0f * 0.25f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + b2Vec2 points[5] = { { -2.0f, 4.0f }, { 2.0f, 4.0f }, { 2.0f, 4.1f }, { -0.5f, 4.2f }, { -2.0f, 4.2f } }; + b2Hull hull = b2ComputeHull( points, 5 ); + b2Polygon poly = b2MakePolygon( &hull, 0.0f ); + b2CreatePolygonShape( groundId, &shapeDef, &poly ); + } + + // Fast moving skinny box. Also testing a large shape offset. + { + float offset = 8.0f; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { offset, 12.0f }; + bodyDef.linearVelocity = { 0.0f, -100.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 2.0f, 0.05f, { -offset, 0.0f }, b2MakeRot( B2_PI ) ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + + static Sample* Create( Settings& settings ) + { + return new SpeculativeFallback( settings ); + } +}; + +static int sampleSpeculativeFallback = RegisterSample( "Continuous", "Speculative Fallback", SpeculativeFallback::Create ); + +class SpeculativeSliver : public Sample +{ +public: + explicit SpeculativeSliver( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 1.75f }; + g_camera.m_zoom = 2.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 12.0f }; + bodyDef.linearVelocity = { 0.0f, -100.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Vec2 points[3] = { { -2.0f, 0.0f }, { -1.0f, 0.0f }, { 2.0f, 0.5f } }; + b2Hull hull = b2ComputeHull( points, 3 ); + b2Polygon poly = b2MakePolygon( &hull, 0.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &poly ); + } + } + + static Sample* Create( Settings& settings ) + { + return new SpeculativeSliver( settings ); + } +}; + +static int sampleSpeculativeSliver = RegisterSample( "Continuous", "Speculative Sliver", SpeculativeSliver::Create ); + +// This shows that while Box2D uses speculative collision, it does not lead to speculative ghost collisions at small distances +class SpeculativeGhost : public Sample +{ +public: + explicit SpeculativeGhost( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 1.75f }; + g_camera.m_zoom = 2.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + b2Polygon box = b2MakeOffsetBox( 1.0f, 0.1f, { 0.0f, 0.9f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + // The speculative distance is 0.02 meters, so this avoid it + bodyDef.position = { 0.015f, 2.515f }; + bodyDef.linearVelocity = { 0.1f * 1.25f * settings.hertz, -0.1f * 1.25f * settings.hertz }; + bodyDef.gravityScale = 0.0f; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeSquare( 0.25f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + + static Sample* Create( Settings& settings ) + { + return new SpeculativeGhost( settings ); + } +}; + +static int sampleSpeculativeGhost = RegisterSample( "Continuous", "Speculative Ghost", SpeculativeGhost::Create ); + +// This shows that Box2D does not have pixel perfect collision. +class PixelImperfect : public Sample +{ +public: + explicit PixelImperfect( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 7.0f, 5.0f }; + g_camera.m_zoom = 6.0f; + } + + float pixelsPerMeter = 30.f; + + { + b2BodyDef block4BodyDef = b2DefaultBodyDef(); + block4BodyDef.type = b2_staticBody; + block4BodyDef.position = { 175.f / pixelsPerMeter, 150.f / pixelsPerMeter }; + b2BodyId block4BodyId = b2CreateBody( m_worldId, &block4BodyDef ); + b2Polygon block4Shape = b2MakeBox( 20.f / pixelsPerMeter, 10.f / pixelsPerMeter ); + b2ShapeDef block4ShapeDef = b2DefaultShapeDef(); + block4ShapeDef.material.friction = 0.f; + b2CreatePolygonShape( block4BodyId, &block4ShapeDef, &block4Shape ); + } + + { + b2BodyDef ballBodyDef = b2DefaultBodyDef(); + ballBodyDef.type = b2_dynamicBody; + ballBodyDef.position = { 200.0f / pixelsPerMeter, 275.f / pixelsPerMeter }; + ballBodyDef.gravityScale = 0.0f; + + m_ballId = b2CreateBody( m_worldId, &ballBodyDef ); + // Ball shape + // b2Polygon ballShape = b2MakeBox( 5.f / pixelsPerMeter, 5.f / pixelsPerMeter ); + b2Polygon ballShape = b2MakeRoundedBox( 4.0f / pixelsPerMeter, 4.0f / pixelsPerMeter, 0.9f / pixelsPerMeter ); + b2ShapeDef ballShapeDef = b2DefaultShapeDef(); + ballShapeDef.material.friction = 0.f; + // ballShapeDef.restitution = 1.f; + b2CreatePolygonShape( m_ballId, &ballShapeDef, &ballShape ); + b2Body_SetLinearVelocity( m_ballId, { 0.f, -5.0f } ); + b2Body_SetFixedRotation( m_ballId, true ); + } + } + + void Step( Settings& settings ) override + { + b2ContactData data; + b2Body_GetContactData( m_ballId, &data, 1 ); + + b2Vec2 p = b2Body_GetPosition( m_ballId ); + b2Vec2 v = b2Body_GetLinearVelocity( m_ballId ); + g_draw.DrawString( 5, m_textLine, "p.x = %.9f, v.y = %.9f", p.x, v.y ); + m_textLine += m_textIncrement; + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new PixelImperfect( settings ); + } + + b2BodyId m_ballId; +}; + +static int samplePixelImperfect = RegisterSample( "Continuous", "Pixel Imperfect", PixelImperfect::Create ); + +class RestitutionThreshold : public Sample +{ +public: + explicit RestitutionThreshold( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 7.0f, 5.0f }; + g_camera.m_zoom = 6.0f; + } + + float pixelsPerMeter = 30.f; + + // With the default threshold the ball will not bounce. + b2World_SetRestitutionThreshold( m_worldId, 0.1f ); + + { + b2BodyDef block0BodyDef = b2DefaultBodyDef(); + block0BodyDef.type = b2_staticBody; + block0BodyDef.position = { 205.f / pixelsPerMeter, 120.f / pixelsPerMeter }; + block0BodyDef.rotation = b2MakeRot( 70.f * 3.14f / 180.f ); + b2BodyId block0BodyId = b2CreateBody( m_worldId, &block0BodyDef ); + b2Polygon block0Shape = b2MakeBox( 50.f / pixelsPerMeter, 5.f / pixelsPerMeter ); + b2ShapeDef block0ShapeDef = b2DefaultShapeDef(); + block0ShapeDef.material.friction = 0.f; + b2CreatePolygonShape( block0BodyId, &block0ShapeDef, &block0Shape ); + } + + { + // Make a ball + b2BodyDef ballBodyDef = b2DefaultBodyDef(); + ballBodyDef.type = b2_dynamicBody; + ballBodyDef.position = { 200.f / pixelsPerMeter, 250.f / pixelsPerMeter }; + m_ballId = b2CreateBody( m_worldId, &ballBodyDef ); + + b2Circle ballShape = {}; + ballShape.radius = 5.f / pixelsPerMeter; + b2ShapeDef ballShapeDef = b2DefaultShapeDef(); + ballShapeDef.material.friction = 0.f; + ballShapeDef.material.restitution = 1.f; + b2CreateCircleShape( m_ballId, &ballShapeDef, &ballShape ); + + b2Body_SetLinearVelocity( m_ballId, { 0.f, -2.9f } ); // Initial velocity + b2Body_SetFixedRotation( m_ballId, true ); // Do not rotate a ball + } + } + + void Step( Settings& settings ) override + { + b2ContactData data; + b2Body_GetContactData( m_ballId, &data, 1 ); + + b2Vec2 p = b2Body_GetPosition( m_ballId ); + b2Vec2 v = b2Body_GetLinearVelocity( m_ballId ); + g_draw.DrawString( 5, m_textLine, "p.x = %.9f, v.y = %.9f", p.x, v.y ); + m_textLine += m_textIncrement; + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new RestitutionThreshold( settings ); + } + + b2BodyId m_ballId; +}; + +static int sampleRestitutionThreshold = RegisterSample( "Continuous", "Restitution Threshold", RestitutionThreshold::Create ); + +class Drop : public Sample +{ +public: + explicit Drop( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 1.5f }; + g_camera.m_zoom = 3.0f; + settings.enableSleep = false; + settings.drawJoints = false; + } + +#if 0 + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float w = 0.25f; + int count = 40; + + float x = -0.5f * count * w; + float h = 0.05f; + for ( int j = 0; j <= count; ++j ) + { + b2Polygon box = b2MakeOffsetBox( w, h, { x, -h }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + x += w; + } + } +#endif + + m_human = {}; + m_frameSkip = 0; + m_frameCount = 0; + m_continuous = true; + m_speculative = true; + + Scene1(); + } + + void Clear() + { + for ( int i = 0; i < m_bodyIds.size(); ++i ) + { + b2DestroyBody( m_bodyIds[i] ); + } + + m_bodyIds.clear(); + + if ( m_human.isSpawned ) + { + DestroyHuman( &m_human ); + } + } + + void CreateGround1() + { + for ( int i = 0; i < m_groundIds.size(); ++i ) + { + b2DestroyBody( m_groundIds[i] ); + } + m_groundIds.clear(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float w = 0.25f; + int count = 40; + b2Segment segment = { { -0.5f * count * w, 0.0f }, { 0.5f * count * w, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + m_groundIds.push_back( groundId ); + } + + void CreateGround2() + { + for ( int i = 0; i < m_groundIds.size(); ++i ) + { + b2DestroyBody( m_groundIds[i] ); + } + m_groundIds.clear(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float w = 0.25f; + int count = 40; + + float x = -0.5f * count * w; + float h = 0.05f; + for ( int j = 0; j <= count; ++j ) + { + b2Polygon box = b2MakeOffsetBox( 0.5f * w, h, { x, 0.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + x += w; + } + + m_groundIds.push_back( groundId ); + } + + void CreateGround3() + { + for ( int i = 0; i < m_groundIds.size(); ++i ) + { + b2DestroyBody( m_groundIds[i] ); + } + m_groundIds.clear(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float w = 0.25f; + int count = 40; + b2Segment segment = { { -0.5f * count * w, 0.0f }, { 0.5f * count * w, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + segment = { { 3.0f, 0.0f }, { 3.0f, 8.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + m_groundIds.push_back( groundId ); + } + + // ball + void Scene1() + { + Clear(); + CreateGround2(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 4.0f }; + bodyDef.linearVelocity = { 0.0f, -100.0f }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 0.0f }, 0.125f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + m_bodyIds.push_back( bodyId ); + m_frameCount = 1; + } + + // ruler + void Scene2() + { + Clear(); + CreateGround1(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 4.0f }; + bodyDef.rotation = b2MakeRot( 0.5f * B2_PI ); + bodyDef.linearVelocity = { 0.0f, 0.0f }; + bodyDef.angularVelocity = -0.5f; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox( 0.75f, 0.01f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + m_bodyIds.push_back( bodyId ); + m_frameCount = 1; + } + + // ragdoll + void Scene3() + { + Clear(); + CreateGround2(); + + float jointFrictionTorque = 0.03f; + float jointHertz = 1.0f; + float jointDampingRatio = 0.5f; + + CreateHuman( &m_human, m_worldId, { 0.0f, 40.0f }, 1.0f, jointFrictionTorque, jointHertz, jointDampingRatio, 1, nullptr, + true ); + + m_frameCount = 1; + } + + void Scene4() + { + Clear(); + CreateGround3(); + + float a = 0.25f; + b2Polygon box = b2MakeSquare( a ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float offset = 0.01f; + + for ( int i = 0; i < 5; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + float shift = ( i % 2 == 0 ? -offset : offset ); + bodyDef.position = { 2.5f + shift, a + 2.0f * a * i }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + m_bodyIds.push_back( bodyId ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + b2Circle circle = { { 0.0f, 0.0f }, 0.125f }; + shapeDef.density = 4.0f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -7.7f, 1.9f }; + bodyDef.linearVelocity = { 200.0f, 0.0f }; + bodyDef.isBullet = true; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + m_bodyIds.push_back( bodyId ); + } + + m_frameCount = 1; + } + + void Keyboard( int key ) override + { + switch ( key ) + { + case GLFW_KEY_1: + Scene1(); + break; + + case GLFW_KEY_2: + Scene2(); + break; + + case GLFW_KEY_3: + Scene3(); + break; + + case GLFW_KEY_4: + Scene4(); + break; + + case GLFW_KEY_C: + Clear(); + m_continuous = !m_continuous; + break; + + case GLFW_KEY_V: + Clear(); + m_speculative = !m_speculative; + b2World_EnableSpeculative( m_worldId, m_speculative ); + break; + + case GLFW_KEY_S: + m_frameSkip = m_frameSkip > 0 ? 0 : 60; + break; + + default: + Sample::Keyboard( key ); + break; + } + } + + void Step( Settings& settings ) override + { +#if 0 + ImGui::SetNextWindowPos( ImVec2( 0.0f, 0.0f ) ); + ImGui::SetNextWindowSize( ImVec2( float( g_camera.m_width ), float( g_camera.m_height ) ) ); + ImGui::SetNextWindowBgAlpha( 0.0f ); + ImGui::Begin( "DropBackground", nullptr, + ImGuiWindowFlags_NoTitleBar | ImGuiWindowFlags_NoInputs | ImGuiWindowFlags_AlwaysAutoResize | + ImGuiWindowFlags_NoScrollbar ); + + ImDrawList* drawList = ImGui::GetWindowDrawList(); + + const char* ContinuousText = m_continuous && m_speculative ? "Continuous ON" : "Continuous OFF"; + drawList->AddText( g_draw.m_largeFont, g_draw.m_largeFont->FontSize, { 40.0f, 40.0f }, IM_COL32_WHITE, ContinuousText ); + + if ( m_frameSkip > 0 ) + { + drawList->AddText( g_draw.m_mediumFont, g_draw.m_mediumFont->FontSize, { 40.0f, 40.0f + 64.0f + 20.0f }, + IM_COL32( 200, 200, 200, 255 ), "Slow Time" ); + } + + ImGui::End(); +#endif + + // if (m_frameCount == 165) + //{ + // settings.pause = true; + // m_frameSkip = 30; + // } + + settings.enableContinuous = m_continuous; + + if ( ( m_frameSkip == 0 || m_frameCount % m_frameSkip == 0 ) && settings.pause == false ) + { + Sample::Step( settings ); + } + else + { + bool pause = settings.pause; + settings.pause = true; + Sample::Step( settings ); + settings.pause = pause; + } + + m_frameCount += 1; + } + + static Sample* Create( Settings& settings ) + { + return new Drop( settings ); + } + + std::vector m_groundIds; + std::vector m_bodyIds; + Human m_human; + int m_frameSkip; + int m_frameCount; + bool m_continuous; + bool m_speculative; +}; + +static int sampleDrop = RegisterSample( "Continuous", "Drop", Drop::Create ); + +// This shows a fast moving body that uses continuous collision versus static and dynamic bodies. +// This is achieved by setting the ball body as a *bullet*. +class Pinball : public Sample +{ +public: + explicit Pinball( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 9.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + settings.drawJoints = false; + + // Ground body + b2BodyId groundId = {}; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Vec2 vs[5] = { { -8.0f, 6.0f }, { -8.0f, 20.0f }, { 8.0f, 20.0f }, { 8.0f, 6.0f }, { 0.0f, -2.0f } }; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = vs; + chainDef.count = 5; + chainDef.isLoop = true; + b2CreateChain( groundId, &chainDef ); + } + + // Flippers + { + b2Vec2 p1 = { -2.0f, 0.0f }, p2 = { 2.0f, 0.0f }; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.enableSleep = false; + + bodyDef.position = p1; + b2BodyId leftFlipperId = b2CreateBody( m_worldId, &bodyDef ); + + bodyDef.position = p2; + b2BodyId rightFlipperId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 1.75f, 0.2f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2CreatePolygonShape( leftFlipperId, &shapeDef, &box ); + b2CreatePolygonShape( rightFlipperId, &shapeDef, &box ); + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.localAnchorB = b2Vec2_zero; + jointDef.enableMotor = true; + jointDef.maxMotorTorque = 1000.0f; + jointDef.enableLimit = true; + + jointDef.motorSpeed = 0.0f; + jointDef.localAnchorA = p1; + jointDef.bodyIdB = leftFlipperId; + jointDef.lowerAngle = -30.0f * B2_PI / 180.0f; + jointDef.upperAngle = 5.0f * B2_PI / 180.0f; + m_leftJointId = b2CreateRevoluteJoint( m_worldId, &jointDef ); + + jointDef.motorSpeed = 0.0f; + jointDef.localAnchorA = p2; + jointDef.bodyIdB = rightFlipperId; + jointDef.lowerAngle = -5.0f * B2_PI / 180.0f; + jointDef.upperAngle = 30.0f * B2_PI / 180.0f; + m_rightJointId = b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + // Spinners + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -4.0f, 17.0f }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box1 = b2MakeBox( 1.5f, 0.125f ); + b2Polygon box2 = b2MakeBox( 0.125f, 1.5f ); + + b2CreatePolygonShape( bodyId, &shapeDef, &box1 ); + b2CreatePolygonShape( bodyId, &shapeDef, &box2 ); + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = bodyDef.position; + jointDef.localAnchorB = b2Vec2_zero; + jointDef.enableMotor = true; + jointDef.maxMotorTorque = 0.1f; + b2CreateRevoluteJoint( m_worldId, &jointDef ); + + bodyDef.position = { 4.0f, 8.0f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box1 ); + b2CreatePolygonShape( bodyId, &shapeDef, &box2 ); + jointDef.localAnchorA = bodyDef.position; + jointDef.bodyIdB = bodyId; + b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + // Bumpers + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { -4.0f, 8.0f }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.restitution = 1.5f; + + b2Circle circle = { { 0.0f, 0.0f }, 1.0f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + bodyDef.position = { 4.0f, 17.0f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + + // Ball + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 1.0f, 15.0f }; + bodyDef.type = b2_dynamicBody; + bodyDef.isBullet = true; + + m_ballId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 0.0f }, 0.2f }; + b2CreateCircleShape( m_ballId, &shapeDef, &circle ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_SPACE ) == GLFW_PRESS ) + { + b2RevoluteJoint_SetMotorSpeed( m_leftJointId, 20.0f ); + b2RevoluteJoint_SetMotorSpeed( m_rightJointId, -20.0f ); + } + else + { + b2RevoluteJoint_SetMotorSpeed( m_leftJointId, -10.0f ); + b2RevoluteJoint_SetMotorSpeed( m_rightJointId, 10.0f ); + } + } + + static Sample* Create( Settings& settings ) + { + return new Pinball( settings ); + } + + b2JointId m_leftJointId; + b2JointId m_rightJointId; + b2BodyId m_ballId; +}; + +static int samplePinball = RegisterSample( "Continuous", "Pinball", Pinball::Create ); + +// This shows the importance of secondary collisions in continuous physics. +// This also shows a difficult setup for the solver with an acute angle. +class Wedge : public Sample +{ +public: + explicit Wedge( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.5f }; + g_camera.m_zoom = 6.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -4.0f, 8.0f }, { 0.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + segment = { { 0.0f, 0.0f }, { 0.0f, 8.0 } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -0.45f, 10.75f }; + bodyDef.linearVelocity = { 0.0f, -200.0f }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Circle circle = {}; + circle.radius = 0.3f; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.2f; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + static Sample* Create( Settings& settings ) + { + return new Wedge( settings ); + } +}; + +static int sampleWedge = RegisterSample( "Continuous", "Wedge", Wedge::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_determinism.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_determinism.cpp new file mode 100644 index 000000000000..f10d3268d674 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_determinism.cpp @@ -0,0 +1,70 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "determinism.h" +#include "draw.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +// This sample provides a visual representation of the cross platform determinism unit test. +// The scenario is designed to produce a chaotic result engaging: +// - continuous collision +// - joint limits (approximate atan2) +// - b2MakeRot (approximate sin/cos) +// Once all the bodies go to sleep the step counter and transform hash is emitted which +// can then be transferred to the unit test and tested in GitHub build actions. +// See CrossPlatformTest in the unit tests. +class FallingHinges : public Sample +{ +public: + + explicit FallingHinges( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 7.5f }; + g_camera.m_zoom = 10.0f; + } + + m_data = CreateFallingHinges( m_worldId ); + m_done = false; + } + + ~FallingHinges() override + { + DestroyFallingHinges( &m_data ); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if (m_done == false) + { + m_done = UpdateFallingHinges( m_worldId, &m_data ); + } + else + { + g_draw.DrawString( 5, m_textLine, "sleep step = %d, hash = 0x%08x", m_data.sleepStep, m_data.hash ); + m_textLine += m_textIncrement; + } + } + + static Sample* Create( Settings& settings ) + { + return new FallingHinges( settings ); + } + + FallingHingeData m_data; + bool m_done; +}; + +static int sampleFallingHinges = RegisterSample( "Determinism", "Falling Hinges", FallingHinges::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_events.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_events.cpp new file mode 100644 index 000000000000..3ce113f639a3 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_events.cpp @@ -0,0 +1,1860 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "donut.h" +#include "draw.h" +#include "human.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include +#include + +class SensorFunnel : public Sample +{ +public: + enum + { + e_donut = 1, + e_human = 2, + e_count = 32 + }; + + explicit SensorFunnel( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 1.333f; + } + + settings.drawJoints = false; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + // b2Vec2 points[] = { + //{42.333, 44.979}, {177.271, 44.979}, {177.271, 100.542}, {142.875, 121.708}, {177.271, 121.708}, + //{177.271, 171.979}, {142.875, 193.146}, {177.271, 193.146}, {177.271, 222.250}, {124.354, 261.938}, + //{124.354, 293.688}, {95.250, 293.688}, {95.250, 261.938}, {42.333, 222.250}, {42.333, 193.146}, + //{76.729, 193.146}, {42.333, 171.979}, {42.333, 121.708}, {76.729, 121.708}, {42.333, 100.542}, + //}; + + b2Vec2 points[] = { + { -16.8672504, 31.088623 }, { 16.8672485, 31.088623 }, { 16.8672485, 17.1978741 }, + { 8.26824951, 11.906374 }, { 16.8672485, 11.906374 }, { 16.8672485, -0.661376953 }, + { 8.26824951, -5.953125 }, { 16.8672485, -5.953125 }, { 16.8672485, -13.229126 }, + { 3.63799858, -23.151123 }, { 3.63799858, -31.088623 }, { -3.63800049, -31.088623 }, + { -3.63800049, -23.151123 }, { -16.8672504, -13.229126 }, { -16.8672504, -5.953125 }, + { -8.26825142, -5.953125 }, { -16.8672504, -0.661376953 }, { -16.8672504, 11.906374 }, + { -8.26825142, 11.906374 }, { -16.8672504, 17.1978741 }, + }; + + int count = std::size( points ); + + // float scale = 0.25f; + // b2Vec2 lower = {FLT_MAX, FLT_MAX}; + // b2Vec2 upper = {-FLT_MAX, -FLT_MAX}; + // for (int i = 0; i < count; ++i) + //{ + // points[i].x = scale * points[i].x; + // points[i].y = -scale * points[i].y; + + // lower = b2Min(lower, points[i]); + // upper = b2Max(upper, points[i]); + //} + + // b2Vec2 center = b2MulSV(0.5f, b2Add(lower, upper)); + // for (int i = 0; i < count; ++i) + //{ + // points[i] = b2Sub(points[i], center); + // } + + // for (int i = 0; i < count / 2; ++i) + //{ + // b2Vec2 temp = points[i]; + // points[i] = points[count - 1 - i]; + // points[count - 1 - i] = temp; + // } + + // printf("{"); + // for (int i = 0; i < count; ++i) + //{ + // printf("{%.9g, %.9g},", points[i].x, points[i].y); + // } + // printf("};\n"); + + b2SurfaceMaterial material = {}; + material.friction = 0.2f; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + chainDef.materials = &material; + chainDef.materialCount = 1; + b2CreateChain( groundId, &chainDef ); + + float sign = 1.0f; + float y = 14.0f; + for ( int i = 0; i < 3; ++i ) + { + bodyDef.position = { 0.0f, y }; + bodyDef.type = b2_dynamicBody; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 6.0f, 0.5f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + shapeDef.material.restitution = 1.0f; + shapeDef.density = 1.0f; + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + revoluteDef.bodyIdA = groundId; + revoluteDef.bodyIdB = bodyId; + revoluteDef.localAnchorA = bodyDef.position; + revoluteDef.localAnchorB = b2Vec2_zero; + revoluteDef.maxMotorTorque = 200.0f; + revoluteDef.motorSpeed = 2.0f * sign; + revoluteDef.enableMotor = true; + + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + y -= 14.0f; + sign = -sign; + } + + { + b2Polygon box = b2MakeOffsetBox( 4.0f, 1.0f, { 0.0f, -30.5f }, b2Rot_identity ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + } + + m_wait = 0.5f; + m_side = -15.0f; + m_type = e_human; + + for ( int i = 0; i < e_count; ++i ) + { + m_isSpawned[i] = false; + } + + memset( m_humans, 0, sizeof( m_humans ) ); + + CreateElement(); + } + + void CreateElement() + { + int index = -1; + for ( int i = 0; i < e_count; ++i ) + { + if ( m_isSpawned[i] == false ) + { + index = i; + break; + } + } + + if ( index == -1 ) + { + return; + } + + b2Vec2 center = { m_side, 29.5f }; + + if ( m_type == e_donut ) + { + Donut* donut = m_donuts + index; + donut->Create( m_worldId, center, 1.0f, 0, true, donut ); + } + else + { + Human* human = m_humans + index; + float scale = 2.0f; + float jointFriction = 0.05f; + float jointHertz = 6.0f; + float jointDamping = 0.5f; + bool colorize = true; + CreateHuman( human, m_worldId, center, scale, jointFriction, jointHertz, jointDamping, index + 1, human, colorize ); + Human_EnableSensorEvents( human, true ); + } + + m_isSpawned[index] = true; + m_side = -m_side; + } + + void DestroyElement( int index ) + { + if ( m_type == e_donut ) + { + Donut* donut = m_donuts + index; + donut->Destroy(); + } + else + { + Human* human = m_humans + index; + DestroyHuman( human ); + } + + m_isSpawned[index] = false; + } + + void Clear() + { + for ( int i = 0; i < e_count; ++i ) + { + if ( m_isSpawned[i] == true ) + { + if ( m_type == e_donut ) + { + m_donuts[i].Destroy(); + } + else + { + DestroyHuman( m_humans + i ); + } + + m_isSpawned[i] = false; + } + } + } + + void UpdateGui() override + { + float height = 90.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 140.0f, height ) ); + + ImGui::Begin( "Sensor Event", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( ImGui::RadioButton( "donut", m_type == e_donut ) ) + { + Clear(); + m_type = e_donut; + } + + if ( ImGui::RadioButton( "human", m_type == e_human ) ) + { + Clear(); + m_type = e_human; + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( m_stepCount == 832 ) + { + m_stepCount += 0; + } + + Sample::Step( settings ); + + // Discover rings that touch the bottom sensor + bool deferredDestruction[e_count] = {}; + b2SensorEvents sensorEvents = b2World_GetSensorEvents( m_worldId ); + for ( int i = 0; i < sensorEvents.beginCount; ++i ) + { + b2SensorBeginTouchEvent event = sensorEvents.beginEvents[i]; + b2ShapeId visitorId = event.visitorShapeId; + b2BodyId bodyId = b2Shape_GetBody( visitorId ); + + if ( m_type == e_donut ) + { + Donut* donut = (Donut*)b2Body_GetUserData( bodyId ); + if ( donut != nullptr ) + { + int index = (int)( donut - m_donuts ); + assert( 0 <= index && index < e_count ); + + // Defer destruction to avoid double destruction and event invalidation (orphaned shape ids) + deferredDestruction[index] = true; + } + } + else + { + Human* human = (Human*)b2Body_GetUserData( bodyId ); + if ( human != nullptr ) + { + int index = (int)( human - m_humans ); + assert( 0 <= index && index < e_count ); + + // Defer destruction to avoid double destruction and event invalidation (orphaned shape ids) + deferredDestruction[index] = true; + } + } + } + + // todo destroy mouse joint if necessary + + // Safely destroy rings that hit the bottom sensor + for ( int i = 0; i < e_count; ++i ) + { + if ( deferredDestruction[i] ) + { + DestroyElement( i ); + } + } + + if ( settings.hertz > 0.0f && settings.pause == false ) + { + m_wait -= 1.0f / settings.hertz; + if ( m_wait < 0.0f ) + { + CreateElement(); + m_wait += 0.5f; + } + } + } + + static Sample* Create( Settings& settings ) + { + return new SensorFunnel( settings ); + } + + Human m_humans[e_count]; + Donut m_donuts[e_count]; + bool m_isSpawned[e_count]; + int m_type; + float m_wait; + float m_side; +}; + +static int sampleSensorBeginEvent = RegisterSample( "Events", "Sensor Funnel", SensorFunnel::Create ); + +class SensorBookend : public Sample +{ +public: + explicit SensorBookend( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 6.0f }; + g_camera.m_zoom = 7.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Segment groundSegment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + + groundSegment = { { -10.0f, 0.0f }, { -10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + + groundSegment = { { 10.0f, 0.0f }, { 10.0f, 10.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + + m_isVisiting1 = false; + m_isVisiting2 = false; + m_sensorsOverlapCount = 0; + } + + CreateSensor1(); + CreateSensor2(); + CreateVisitor(); + } + + void CreateSensor1() + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + + bodyDef.position = { -2.0f, 1.0f }; + m_sensorBodyId1 = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + + b2Polygon box = b2MakeSquare( 1.0f ); + m_sensorShapeId1 = b2CreatePolygonShape( m_sensorBodyId1, &shapeDef, &box ); + } + + void CreateSensor2() + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 2.0f, 1.0f }; + m_sensorBodyId2 = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + + b2Polygon box = b2MakeRoundedBox( 0.5f, 0.5f, 0.5f ); + m_sensorShapeId2 = b2CreatePolygonShape( m_sensorBodyId2, &shapeDef, &box ); + + // Solid middle + shapeDef.isSensor = false; + shapeDef.enableSensorEvents = false; + box = b2MakeSquare( 0.5f ); + b2CreatePolygonShape( m_sensorBodyId2, &shapeDef, &box ); + } + + void CreateVisitor() + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { -4.0f, 1.0f }; + bodyDef.type = b2_dynamicBody; + + m_visitorBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.enableSensorEvents = true; + + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + m_visitorShapeId = b2CreateCircleShape( m_visitorBodyId, &shapeDef, &circle ); + } + + void UpdateGui() override + { + float height = 260.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Sensor Bookend", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( B2_IS_NULL( m_visitorBodyId ) ) + { + if ( ImGui::Button( "create visitor" ) ) + { + CreateVisitor(); + } + } + else + { + if ( ImGui::Button( "destroy visitor" ) ) + { + b2DestroyBody( m_visitorBodyId ); + m_visitorBodyId = b2_nullBodyId; + // Retain m_visitorShapeId for end events. + } + else + { + bool enabledEvents = b2Shape_AreSensorEventsEnabled( m_visitorShapeId ); + if ( ImGui::Checkbox( "visitor events", &enabledEvents ) ) + { + b2Shape_EnableSensorEvents( m_visitorShapeId, enabledEvents ); + } + + bool enabledBody = b2Body_IsEnabled( m_visitorBodyId ); + if ( ImGui::Checkbox( "enable visitor body", &enabledBody ) ) + { + if (enabledBody) + { + b2Body_Enable( m_visitorBodyId ); + } + else + { + b2Body_Disable( m_visitorBodyId ); + } + } + } + } + + ImGui::Separator(); + + if ( B2_IS_NULL( m_sensorBodyId1 ) ) + { + if ( ImGui::Button( "create sensor1" ) ) + { + CreateSensor1(); + } + } + else + { + if ( ImGui::Button( "destroy sensor1" ) ) + { + b2DestroyBody( m_sensorBodyId1 ); + m_sensorBodyId1 = b2_nullBodyId; + // Retain m_sensorShapeId1 for end events. + } + else + { + bool enabledEvents = b2Shape_AreSensorEventsEnabled( m_sensorShapeId1 ); + if ( ImGui::Checkbox( "sensor 1 events", &enabledEvents ) ) + { + b2Shape_EnableSensorEvents( m_sensorShapeId1, enabledEvents ); + } + + bool enabledBody = b2Body_IsEnabled( m_sensorBodyId1 ); + if ( ImGui::Checkbox( "enable sensor1 body", &enabledBody ) ) + { + if ( enabledBody ) + { + b2Body_Enable( m_sensorBodyId1 ); + } + else + { + b2Body_Disable( m_sensorBodyId1 ); + } + } + } + } + + ImGui::Separator(); + + if ( B2_IS_NULL( m_sensorBodyId2 ) ) + { + if ( ImGui::Button( "create sensor2" ) ) + { + CreateSensor2(); + } + } + else + { + if ( ImGui::Button( "destroy sensor2" ) ) + { + b2DestroyBody( m_sensorBodyId2 ); + m_sensorBodyId2 = b2_nullBodyId; + // Retain m_sensorShapeId2 for end events. + } + else + { + bool enabledEvents = b2Shape_AreSensorEventsEnabled( m_sensorShapeId2 ); + if ( ImGui::Checkbox( "sensor2 events", &enabledEvents ) ) + { + b2Shape_EnableSensorEvents( m_sensorShapeId2, enabledEvents ); + } + + bool enabledBody = b2Body_IsEnabled( m_sensorBodyId2 ); + if ( ImGui::Checkbox( "enable sensor2 body", &enabledBody ) ) + { + if ( enabledBody ) + { + b2Body_Enable( m_sensorBodyId2 ); + } + else + { + b2Body_Disable( m_sensorBodyId2 ); + } + } + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2SensorEvents sensorEvents = b2World_GetSensorEvents( m_worldId ); + for ( int i = 0; i < sensorEvents.beginCount; ++i ) + { + b2SensorBeginTouchEvent event = sensorEvents.beginEvents[i]; + + if ( B2_ID_EQUALS( event.sensorShapeId, m_sensorShapeId1 ) ) + { + if ( B2_ID_EQUALS( event.visitorShapeId, m_visitorShapeId ) ) + { + assert( m_isVisiting1 == false ); + m_isVisiting1 = true; + } + else + { + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorShapeId2 ) ); + m_sensorsOverlapCount += 1; + } + } + else + { + assert( B2_ID_EQUALS( event.sensorShapeId, m_sensorShapeId2 ) ); + + if ( B2_ID_EQUALS( event.visitorShapeId, m_visitorShapeId ) ) + { + assert( m_isVisiting2 == false ); + m_isVisiting2 = true; + } + else + { + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorShapeId1 ) ); + m_sensorsOverlapCount += 1; + } + } + } + + assert( m_sensorsOverlapCount == 0 || m_sensorsOverlapCount == 2 ); + + for ( int i = 0; i < sensorEvents.endCount; ++i ) + { + b2SensorEndTouchEvent event = sensorEvents.endEvents[i]; + + if ( B2_ID_EQUALS( event.sensorShapeId, m_sensorShapeId1 ) ) + { + if ( B2_ID_EQUALS( event.visitorShapeId, m_visitorShapeId )) + { + assert( m_isVisiting1 == true ); + m_isVisiting1 = false; + } + else + { + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorShapeId2 ) ); + m_sensorsOverlapCount -= 1; + } + } + else + { + assert( B2_ID_EQUALS( event.sensorShapeId, m_sensorShapeId2 ) ); + + if ( B2_ID_EQUALS( event.visitorShapeId, m_visitorShapeId ) ) + { + assert( m_isVisiting2 == true ); + m_isVisiting2 = false; + } + else + { + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorShapeId1 ) ); + m_sensorsOverlapCount -= 1; + } + } + } + + assert( m_sensorsOverlapCount == 0 || m_sensorsOverlapCount == 2 ); + + // Nullify invalid shape ids after end events are processed. + if (b2Shape_IsValid(m_visitorShapeId) == false) + { + m_visitorShapeId = b2_nullShapeId; + } + + if (b2Shape_IsValid(m_sensorShapeId1) == false) + { + m_sensorShapeId1 = b2_nullShapeId; + } + + if (b2Shape_IsValid(m_sensorShapeId2) == false) + { + m_sensorShapeId2 = b2_nullShapeId; + } + + DrawTextLine( "visiting 1 == %s", m_isVisiting1 ? "true" : "false" ); + DrawTextLine( "visiting 2 == %s", m_isVisiting2 ? "true" : "false" ); + DrawTextLine( "sensors overlap count == %d", m_sensorsOverlapCount ); + } + + static Sample* Create( Settings& settings ) + { + return new SensorBookend( settings ); + } + + b2BodyId m_sensorBodyId1; + b2ShapeId m_sensorShapeId1; + + b2BodyId m_sensorBodyId2; + b2ShapeId m_sensorShapeId2; + + b2BodyId m_visitorBodyId; + b2ShapeId m_visitorShapeId; + + bool m_isVisiting1; + bool m_isVisiting2; + int m_sensorsOverlapCount; +}; + +static int sampleSensorBookendEvent = RegisterSample( "Events", "Sensor Bookend", SensorBookend::Create ); + +class FootSensor : public Sample +{ +public: + enum CollisionBits + { + GROUND = 0x00000001, + PLAYER = 0x00000002, + FOOT = 0x00000004, + + ALL_BITS = ( ~0u ) + }; + + explicit FootSensor( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 6.0f }; + g_camera.m_zoom = 7.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Vec2 points[20]; + float x = 10.0f; + for ( int i = 0; i < 20; ++i ) + { + points[i] = { x, 0.0f }; + x -= 1.0f; + } + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = 20; + chainDef.filter.categoryBits = GROUND; + chainDef.filter.maskBits = FOOT | PLAYER; + chainDef.isLoop = false; + chainDef.enableSensorEvents = true; + + b2CreateChain( groundId, &chainDef ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.fixedRotation = true; + bodyDef.position = { 0.0f, 1.0f }; + m_playerId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = PLAYER; + shapeDef.filter.maskBits = GROUND; + shapeDef.material.friction = 0.3f; + b2Capsule capsule = { { 0.0f, -0.5f }, { 0.0f, 0.5f }, 0.5f }; + b2CreateCapsuleShape( m_playerId, &shapeDef, &capsule ); + + b2Polygon box = b2MakeOffsetBox( 0.5f, 0.25f, { 0.0f, -1.0f }, b2Rot_identity ); + shapeDef.filter.categoryBits = FOOT; + shapeDef.filter.maskBits = GROUND; + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + m_sensorId = b2CreatePolygonShape( m_playerId, &shapeDef, &box ); + } + + m_overlapCount = 0; + } + + void Step( Settings& settings ) override + { + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) == GLFW_PRESS ) + { + b2Body_ApplyForceToCenter( m_playerId, { -50.0f, 0.0f }, true ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) == GLFW_PRESS ) + { + b2Body_ApplyForceToCenter( m_playerId, { 50.0f, 0.0f }, true ); + } + + Sample::Step( settings ); + + b2SensorEvents sensorEvents = b2World_GetSensorEvents( m_worldId ); + for ( int i = 0; i < sensorEvents.beginCount; ++i ) + { + b2SensorBeginTouchEvent event = sensorEvents.beginEvents[i]; + + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorId ) == false ); + + if ( B2_ID_EQUALS( event.sensorShapeId, m_sensorId ) ) + { + m_overlapCount += 1; + } + } + + for ( int i = 0; i < sensorEvents.endCount; ++i ) + { + b2SensorEndTouchEvent event = sensorEvents.endEvents[i]; + + assert( B2_ID_EQUALS( event.visitorShapeId, m_sensorId ) == false ); + + if ( B2_ID_EQUALS( event.sensorShapeId, m_sensorId ) ) + { + m_overlapCount -= 1; + } + } + + g_draw.DrawString( 5, m_textLine, "count == %d", m_overlapCount ); + m_textLine += m_textIncrement; + + int capacity = b2Shape_GetSensorCapacity( m_sensorId ); + m_overlaps.clear(); + m_overlaps.resize( capacity ); + int count = b2Shape_GetSensorOverlaps( m_sensorId, m_overlaps.data(), capacity ); + for ( int i = 0; i < count; ++i ) + { + b2ShapeId shapeId = m_overlaps[i]; + b2AABB aabb = b2Shape_GetAABB( shapeId ); + b2Vec2 point = b2AABB_Center( aabb ); + g_draw.DrawPoint( point, 10.0f, b2_colorWhite ); + } + } + + static Sample* Create( Settings& settings ) + { + return new FootSensor( settings ); + } + + b2BodyId m_playerId; + b2ShapeId m_sensorId; + std::vector m_overlaps; + int m_overlapCount; +}; + +static int sampleCharacterSensor = RegisterSample( "Events", "Foot Sensor", FootSensor::Create ); + +struct BodyUserData +{ + int index; +}; + +class ContactEvent : public Sample +{ +public: + enum + { + e_count = 20 + }; + + explicit ContactEvent( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 1.75f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Vec2 points[] = { { 40.0f, -40.0f }, { -40.0f, -40.0f }, { -40.0f, 40.0f }, { 40.0f, 40.0f } }; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.count = 4; + chainDef.points = points; + chainDef.isLoop = true; + + b2CreateChain( groundId, &chainDef ); + } + + // Player + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.gravityScale = 0.0f; + bodyDef.linearDamping = 0.5f; + bodyDef.angularDamping = 0.5f; + bodyDef.isBullet = true; + m_playerId = b2CreateBody( m_worldId, &bodyDef ); + + b2Circle circle = { { 0.0f, 0.0f }, 1.0f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Enable contact events for the player shape + shapeDef.enableContactEvents = true; + + m_coreShapeId = b2CreateCircleShape( m_playerId, &shapeDef, &circle ); + } + + for ( int i = 0; i < e_count; ++i ) + { + m_debrisIds[i] = b2_nullBodyId; + m_bodyUserData[i].index = i; + } + + m_wait = 0.5f; + m_force = 200.0f; + } + + void SpawnDebris() + { + int index = -1; + for ( int i = 0; i < e_count; ++i ) + { + if ( B2_IS_NULL( m_debrisIds[i] ) ) + { + index = i; + break; + } + } + + if ( index == -1 ) + { + return; + } + + // Debris + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { RandomFloatRange( -38.0f, 38.0f ), RandomFloatRange( -38.0f, 38.0f ) }; + bodyDef.rotation = b2MakeRot( RandomFloatRange( -B2_PI, B2_PI ) ); + bodyDef.linearVelocity = { RandomFloatRange( -5.0f, 5.0f ), RandomFloatRange( -5.0f, 5.0f ) }; + bodyDef.angularVelocity = RandomFloatRange( -1.0f, 1.0f ); + bodyDef.gravityScale = 0.0f; + bodyDef.userData = m_bodyUserData + index; + m_debrisIds[index] = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.restitution = 0.8f; + + // No events when debris hits debris + shapeDef.enableContactEvents = false; + + if ( ( index + 1 ) % 3 == 0 ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( m_debrisIds[index], &shapeDef, &circle ); + } + else if ( ( index + 1 ) % 2 == 0 ) + { + b2Capsule capsule = { { 0.0f, -0.25f }, { 0.0f, 0.25f }, 0.25f }; + b2CreateCapsuleShape( m_debrisIds[index], &shapeDef, &capsule ); + } + else + { + b2Polygon box = b2MakeBox( 0.4f, 0.6f ); + b2CreatePolygonShape( m_debrisIds[index], &shapeDef, &box ); + } + } + + void UpdateGui() override + { + float height = 60.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Contact Event", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::SliderFloat( "force", &m_force, 100.0f, 500.0f, "%.1f" ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + g_draw.DrawString( 5, m_textLine, "move using WASD" ); + m_textLine += m_textIncrement; + + b2Vec2 position = b2Body_GetPosition( m_playerId ); + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) == GLFW_PRESS ) + { + b2Body_ApplyForce( m_playerId, { -m_force, 0.0f }, position, true ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) == GLFW_PRESS ) + { + b2Body_ApplyForce( m_playerId, { m_force, 0.0f }, position, true ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_W ) == GLFW_PRESS ) + { + b2Body_ApplyForce( m_playerId, { 0.0f, m_force }, position, true ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_S ) == GLFW_PRESS ) + { + b2Body_ApplyForce( m_playerId, { 0.0f, -m_force }, position, true ); + } + + Sample::Step( settings ); + + // Discover rings that touch the bottom sensor + int debrisToAttach[e_count] = {}; + b2ShapeId shapesToDestroy[e_count] = { b2_nullShapeId }; + int attachCount = 0; + int destroyCount = 0; + + std::vector contactData; + + // Process contact begin touch events. + b2ContactEvents contactEvents = b2World_GetContactEvents( m_worldId ); + for ( int i = 0; i < contactEvents.beginCount; ++i ) + { + b2ContactBeginTouchEvent event = contactEvents.beginEvents[i]; + b2BodyId bodyIdA = b2Shape_GetBody( event.shapeIdA ); + b2BodyId bodyIdB = b2Shape_GetBody( event.shapeIdB ); + + // The begin touch events have the contact manifolds, but the impulses are zero. This is because the manifolds + // are gathered before the contact solver is run. + + // We can get the final contact data from the shapes. The manifold is shared by the two shapes, so we just need the + // contact data from one of the shapes. Choose the one with the smallest number of contacts. + + int capacityA = b2Shape_GetContactCapacity( event.shapeIdA ); + int capacityB = b2Shape_GetContactCapacity( event.shapeIdB ); + + if ( capacityA < capacityB ) + { + contactData.resize( capacityA ); + + // The count may be less than the capacity + int countA = b2Shape_GetContactData( event.shapeIdA, contactData.data(), capacityA ); + assert( countA >= 1 ); + + for ( int j = 0; j < countA; ++j ) + { + b2ShapeId idA = contactData[j].shapeIdA; + b2ShapeId idB = contactData[j].shapeIdB; + if ( B2_ID_EQUALS( idA, event.shapeIdB ) || B2_ID_EQUALS( idB, event.shapeIdB ) ) + { + assert( B2_ID_EQUALS( idA, event.shapeIdA ) || B2_ID_EQUALS( idB, event.shapeIdA ) ); + + b2Manifold manifold = contactData[j].manifold; + b2Vec2 normal = manifold.normal; + assert( b2AbsFloat( b2Length( normal ) - 1.0f ) < 4.0f * FLT_EPSILON ); + + for ( int k = 0; k < manifold.pointCount; ++k ) + { + b2ManifoldPoint point = manifold.points[k]; + g_draw.DrawSegment( point.point, point.point + point.totalNormalImpulse * normal, b2_colorBlueViolet ); + g_draw.DrawPoint( point.point, 10.0f, b2_colorWhite ); + } + } + } + } + else + { + contactData.resize( capacityB ); + + // The count may be less than the capacity + int countB = b2Shape_GetContactData( event.shapeIdB, contactData.data(), capacityB ); + assert( countB >= 1 ); + + for ( int j = 0; j < countB; ++j ) + { + b2ShapeId idA = contactData[j].shapeIdA; + b2ShapeId idB = contactData[j].shapeIdB; + + if ( B2_ID_EQUALS( idA, event.shapeIdA ) || B2_ID_EQUALS( idB, event.shapeIdA ) ) + { + assert( B2_ID_EQUALS( idA, event.shapeIdB ) || B2_ID_EQUALS( idB, event.shapeIdB ) ); + + b2Manifold manifold = contactData[j].manifold; + b2Vec2 normal = manifold.normal; + assert( b2AbsFloat( b2Length( normal ) - 1.0f ) < 4.0f * FLT_EPSILON ); + + for ( int k = 0; k < manifold.pointCount; ++k ) + { + b2ManifoldPoint point = manifold.points[k]; + g_draw.DrawSegment( point.point, point.point + point.totalNormalImpulse * normal, b2_colorYellowGreen ); + g_draw.DrawPoint( point.point, 10.0f, b2_colorWhite ); + } + } + } + } + + if ( B2_ID_EQUALS( bodyIdA, m_playerId ) ) + { + BodyUserData* userDataB = static_cast( b2Body_GetUserData( bodyIdB ) ); + if ( userDataB == nullptr ) + { + if ( B2_ID_EQUALS( event.shapeIdA, m_coreShapeId ) == false && destroyCount < e_count ) + { + // player non-core shape hit the wall + + bool found = false; + for ( int j = 0; j < destroyCount; ++j ) + { + if ( B2_ID_EQUALS( event.shapeIdA, shapesToDestroy[j] ) ) + { + found = true; + break; + } + } + + // avoid double deletion + if ( found == false ) + { + shapesToDestroy[destroyCount] = event.shapeIdA; + destroyCount += 1; + } + } + } + else if ( attachCount < e_count ) + { + debrisToAttach[attachCount] = userDataB->index; + attachCount += 1; + } + } + else + { + // Only expect events for the player + assert( B2_ID_EQUALS( bodyIdB, m_playerId ) ); + BodyUserData* userDataA = static_cast( b2Body_GetUserData( bodyIdA ) ); + if ( userDataA == nullptr ) + { + if ( B2_ID_EQUALS( event.shapeIdB, m_coreShapeId ) == false && destroyCount < e_count ) + { + // player non-core shape hit the wall + + bool found = false; + for ( int j = 0; j < destroyCount; ++j ) + { + if ( B2_ID_EQUALS( event.shapeIdB, shapesToDestroy[j] ) ) + { + found = true; + break; + } + } + + // avoid double deletion + if ( found == false ) + { + shapesToDestroy[destroyCount] = event.shapeIdB; + destroyCount += 1; + } + } + } + else if ( attachCount < e_count ) + { + debrisToAttach[attachCount] = userDataA->index; + attachCount += 1; + } + } + } + + // Attach debris to player body + for ( int i = 0; i < attachCount; ++i ) + { + int index = debrisToAttach[i]; + b2BodyId debrisId = m_debrisIds[index]; + if ( B2_IS_NULL( debrisId ) ) + { + continue; + } + + b2Transform playerTransform = b2Body_GetTransform( m_playerId ); + b2Transform debrisTransform = b2Body_GetTransform( debrisId ); + b2Transform relativeTransform = b2InvMulTransforms( playerTransform, debrisTransform ); + + int shapeCount = b2Body_GetShapeCount( debrisId ); + if ( shapeCount == 0 ) + { + continue; + } + + b2ShapeId shapeId; + b2Body_GetShapes( debrisId, &shapeId, 1 ); + + b2ShapeType type = b2Shape_GetType( shapeId ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.enableContactEvents = true; + + switch ( type ) + { + case b2_circleShape: + { + b2Circle circle = b2Shape_GetCircle( shapeId ); + circle.center = b2TransformPoint( relativeTransform, circle.center ); + + b2CreateCircleShape( m_playerId, &shapeDef, &circle ); + } + break; + + case b2_capsuleShape: + { + b2Capsule capsule = b2Shape_GetCapsule( shapeId ); + capsule.center1 = b2TransformPoint( relativeTransform, capsule.center1 ); + capsule.center2 = b2TransformPoint( relativeTransform, capsule.center2 ); + + b2CreateCapsuleShape( m_playerId, &shapeDef, &capsule ); + } + break; + + case b2_polygonShape: + { + b2Polygon originalPolygon = b2Shape_GetPolygon( shapeId ); + b2Polygon polygon = b2TransformPolygon( relativeTransform, &originalPolygon ); + + b2CreatePolygonShape( m_playerId, &shapeDef, &polygon ); + } + break; + + default: + assert( false ); + } + + b2DestroyBody( debrisId ); + m_debrisIds[index] = b2_nullBodyId; + } + + for ( int i = 0; i < destroyCount; ++i ) + { + bool updateMass = false; + b2DestroyShape( shapesToDestroy[i], updateMass ); + } + + if ( destroyCount > 0 ) + { + // Update mass just once + b2Body_ApplyMassFromShapes( m_playerId ); + } + + if ( settings.hertz > 0.0f && settings.pause == false ) + { + m_wait -= 1.0f / settings.hertz; + if ( m_wait < 0.0f ) + { + SpawnDebris(); + m_wait += 0.5f; + } + } + } + + static Sample* Create( Settings& settings ) + { + return new ContactEvent( settings ); + } + + b2BodyId m_playerId; + b2ShapeId m_coreShapeId; + b2BodyId m_debrisIds[e_count]; + BodyUserData m_bodyUserData[e_count]; + float m_force; + float m_wait; +}; + +static int sampleWeeble = RegisterSample( "Events", "Contact", ContactEvent::Create ); + +// Shows how to make a rigid body character mover and use the pre-solve callback. In this +// case the platform should get the pre-solve event, not the player. +class Platformer : public Sample +{ +public: + explicit Platformer( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.5f, 7.5f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + b2World_SetPreSolveCallback( m_worldId, PreSolveStatic, this ); + + // Ground + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Static Platform + // This tests pre-solve with continuous collision + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_staticBody; + bodyDef.position = { -6.0f, 6.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Need to turn this on to get the callback + shapeDef.enablePreSolveEvents = true; + + b2Polygon box = b2MakeBox( 2.0f, 0.5f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Moving Platform + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position = { 0.0f, 6.0f }; + bodyDef.linearVelocity = { 2.0f, 0.0f }; + m_movingPlatformId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Need to turn this on to get the callback + shapeDef.enablePreSolveEvents = true; + + b2Polygon box = b2MakeBox( 3.0f, 0.5f ); + b2CreatePolygonShape( m_movingPlatformId, &shapeDef, &box ); + } + + // Player + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.fixedRotation = true; + bodyDef.linearDamping = 0.5f; + bodyDef.position = { 0.0f, 1.0f }; + m_playerId = b2CreateBody( m_worldId, &bodyDef ); + + m_radius = 0.5f; + b2Capsule capsule = { { 0.0f, 0.0f }, { 0.0f, 1.0f }, m_radius }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + + m_playerShapeId = b2CreateCapsuleShape( m_playerId, &shapeDef, &capsule ); + } + + m_force = 25.0f; + m_impulse = 25.0f; + m_jumpDelay = 0.25f; + m_jumping = false; + } + + static bool PreSolveStatic( b2ShapeId shapeIdA, b2ShapeId shapeIdB, b2Manifold* manifold, void* context ) + { + Platformer* platformer = static_cast( context ); + return platformer->PreSolve( shapeIdA, shapeIdB, manifold ); + } + + // This callback must be thread-safe. It may be called multiple times simultaneously. + // Notice how this method is constant and doesn't change any data. It also + // does not try to access any values in the world that may be changing, such as contact data. + bool PreSolve( b2ShapeId shapeIdA, b2ShapeId shapeIdB, b2Manifold* manifold ) const + { + assert( b2Shape_IsValid( shapeIdA ) ); + assert( b2Shape_IsValid( shapeIdB ) ); + + float sign = 0.0f; + if ( B2_ID_EQUALS( shapeIdA, m_playerShapeId ) ) + { + sign = -1.0f; + } + else if ( B2_ID_EQUALS( shapeIdB, m_playerShapeId ) ) + { + sign = 1.0f; + } + else + { + // not colliding with the player, enable contact + return true; + } + + b2Vec2 normal = manifold->normal; + if ( sign * normal.y > 0.95f ) + { + return true; + } + + float separation = 0.0f; + for ( int i = 0; i < manifold->pointCount; ++i ) + { + float s = manifold->points[i].separation; + separation = separation < s ? separation : s; + } + + if ( separation > 0.1f * m_radius ) + { + // shallow overlap + return true; + } + + // normal points down, disable contact + return false; + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "One-Sided Platform", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + ImGui::SliderFloat( "force", &m_force, 0.0f, 50.0f, "%.1f" ); + ImGui::SliderFloat( "impulse", &m_impulse, 0.0f, 50.0f, "%.1f" ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + bool canJump = false; + b2Vec2 velocity = b2Body_GetLinearVelocity( m_playerId ); + if ( m_jumpDelay == 0.0f && m_jumping == false && velocity.y < 0.01f ) + { + int capacity = b2Body_GetContactCapacity( m_playerId ); + capacity = b2MinInt( capacity, 4 ); + b2ContactData contactData[4]; + int count = b2Body_GetContactData( m_playerId, contactData, capacity ); + for ( int i = 0; i < count; ++i ) + { + b2BodyId bodyIdA = b2Shape_GetBody( contactData[i].shapeIdA ); + float sign = 0.0f; + if ( B2_ID_EQUALS( bodyIdA, m_playerId ) ) + { + // normal points from A to B + sign = -1.0f; + } + else + { + sign = 1.0f; + } + + if ( sign * contactData[i].manifold.normal.y > 0.9f ) + { + canJump = true; + break; + } + } + } + + // A kinematic body is moved by setting its velocity. This + // ensure friction works correctly. + b2Vec2 platformPosition = b2Body_GetPosition( m_movingPlatformId ); + if ( platformPosition.x < -15.0f ) + { + b2Body_SetLinearVelocity( m_movingPlatformId, { 2.0f, 0.0f } ); + } + else if ( platformPosition.x > 15.0f ) + { + b2Body_SetLinearVelocity( m_movingPlatformId, { -2.0f, 0.0f } ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) == GLFW_PRESS ) + { + b2Body_ApplyForceToCenter( m_playerId, { -m_force, 0.0f }, true ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) == GLFW_PRESS ) + { + b2Body_ApplyForceToCenter( m_playerId, { m_force, 0.0f }, true ); + } + + int keyState = glfwGetKey( g_mainWindow, GLFW_KEY_SPACE ); + if ( keyState == GLFW_PRESS ) + { + if ( canJump ) + { + b2Body_ApplyLinearImpulseToCenter( m_playerId, { 0.0f, m_impulse }, true ); + m_jumpDelay = 0.5f; + m_jumping = true; + } + } + else + { + m_jumping = false; + } + + Sample::Step( settings ); + + b2ContactData contactData = {}; + int contactCount = b2Body_GetContactData( m_movingPlatformId, &contactData, 1 ); + g_draw.DrawString( 5, m_textLine, "Platform contact count = %d, point count = %d", contactCount, + contactData.manifold.pointCount ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "Movement: A/D/Space" ); + m_textLine += m_textIncrement; + + g_draw.DrawString( 5, m_textLine, "Can jump = %s", canJump ? "true" : "false" ); + m_textLine += m_textIncrement; + + if ( settings.hertz > 0.0f ) + { + m_jumpDelay = b2MaxFloat( 0.0f, m_jumpDelay - 1.0f / settings.hertz ); + } + } + + static Sample* Create( Settings& settings ) + { + return new Platformer( settings ); + } + + bool m_jumping; + float m_radius; + float m_force; + float m_impulse; + float m_jumpDelay; + b2BodyId m_playerId; + b2ShapeId m_playerShapeId; + b2BodyId m_movingPlatformId; +}; + +static int samplePlatformer = RegisterSample( "Events", "Platformer", Platformer::Create ); + +// This shows how to process body events. +class BodyMove : public Sample +{ +public: + enum + { + e_count = 50 + }; + + explicit BodyMove( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.0f, 8.0f }; + g_camera.m_zoom = 25.0f * 0.55f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + + b2Polygon box = b2MakeOffsetBox( 12.0f, 0.1f, { -10.0f, -0.1f }, b2MakeRot( -0.15f * B2_PI ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 12.0f, 0.1f, { 10.0f, -0.1f }, b2MakeRot( 0.15f * B2_PI ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + shapeDef.material.restitution = 0.8f; + + box = b2MakeOffsetBox( 0.1f, 10.0f, { 19.9f, 10.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 0.1f, 10.0f, { -19.9f, 10.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 20.0f, 0.1f, { 0.0f, 20.1f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + m_sleepCount = 0; + m_count = 0; + + m_explosionPosition = { 0.0f, -5.0f }; + m_explosionRadius = 10.0f; + m_explosionMagnitude = 10.0f; + } + + void CreateBodies() + { + b2Capsule capsule = { { -0.25f, 0.0f }, { 0.25f, 0.0f }, 0.25f }; + b2Circle circle = { { 0.0f, 0.0f }, 0.35f }; + b2Polygon square = b2MakeSquare( 0.35f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float x = -5.0f, y = 10.0f; + for ( int32_t i = 0; i < 10 && m_count < e_count; ++i ) + { + bodyDef.position = { x, y }; + bodyDef.isBullet = ( m_count % 12 == 0 ); + bodyDef.userData = m_bodyIds + m_count; + m_bodyIds[m_count] = b2CreateBody( m_worldId, &bodyDef ); + m_sleeping[m_count] = false; + + int remainder = m_count % 4; + if ( remainder == 0 ) + { + b2CreateCapsuleShape( m_bodyIds[m_count], &shapeDef, &capsule ); + } + else if ( remainder == 1 ) + { + b2CreateCircleShape( m_bodyIds[m_count], &shapeDef, &circle ); + } + else if ( remainder == 2 ) + { + b2CreatePolygonShape( m_bodyIds[m_count], &shapeDef, &square ); + } + else + { + b2Polygon poly = RandomPolygon( 0.75f ); + poly.radius = 0.1f; + b2CreatePolygonShape( m_bodyIds[m_count], &shapeDef, &poly ); + } + + m_count += 1; + x += 1.0f; + } + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Body Move", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( ImGui::Button( "Explode" ) ) + { + b2ExplosionDef def = b2DefaultExplosionDef(); + def.position = m_explosionPosition; + def.radius = m_explosionRadius; + def.falloff = 0.1f; + def.impulsePerLength = m_explosionMagnitude; + b2World_Explode( m_worldId, &def ); + } + + ImGui::SliderFloat( "Magnitude", &m_explosionMagnitude, -20.0f, 20.0f, "%.1f" ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( settings.pause == false && ( m_stepCount & 15 ) == 15 && m_count < e_count ) + { + CreateBodies(); + } + + Sample::Step( settings ); + + // Process body events + b2BodyEvents events = b2World_GetBodyEvents( m_worldId ); + for ( int i = 0; i < events.moveCount; ++i ) + { + // draw the transform of every body that moved (not sleeping) + const b2BodyMoveEvent* event = events.moveEvents + i; + g_draw.DrawTransform( event->transform ); + + b2Transform transform = b2Body_GetTransform( event->bodyId ); + B2_ASSERT( transform.p.x == event->transform.p.x ); + B2_ASSERT( transform.p.y == event->transform.p.y ); + B2_ASSERT( transform.q.c == event->transform.q.c ); + B2_ASSERT( transform.q.s == event->transform.q.s ); + + // this shows a somewhat contrived way to track body sleeping + b2BodyId* bodyId = static_cast( event->userData ); + ptrdiff_t diff = bodyId - m_bodyIds; + bool* sleeping = m_sleeping + diff; + + if ( event->fellAsleep ) + { + *sleeping = true; + m_sleepCount += 1; + } + else + { + if ( *sleeping ) + { + *sleeping = false; + m_sleepCount -= 1; + } + } + } + + g_draw.DrawCircle( m_explosionPosition, m_explosionRadius, b2_colorAzure ); + + g_draw.DrawString( 5, m_textLine, "sleep count: %d", m_sleepCount ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new BodyMove( settings ); + } + + b2BodyId m_bodyIds[e_count] = {}; + bool m_sleeping[e_count] = {}; + int m_count; + int m_sleepCount; + b2Vec2 m_explosionPosition; + float m_explosionRadius; + float m_explosionMagnitude; +}; + +static int sampleBodyMove = RegisterSample( "Events", "Body Move", BodyMove::Create ); + +class SensorTypes : public Sample +{ +public: + enum CollisionBits + { + GROUND = 0x00000001, + SENSOR = 0x00000002, + DEFAULT = 0x00000004, + + ALL_BITS = ( ~0u ) + }; + + explicit SensorTypes( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 3.0f }; + g_camera.m_zoom = 4.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.name = "ground"; + + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Enable sensor events, but filter them out as a test + shapeDef.filter.categoryBits = GROUND; + shapeDef.filter.maskBits = DEFAULT; + shapeDef.enableSensorEvents = true; + + b2Segment groundSegment = { { -6.0f, 0.0f }, { 6.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + + groundSegment = { { -6.0f, 0.0f }, { -6.0f, 4.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + + groundSegment = { { 6.0f, 0.0f }, { 6.0f, 4.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &groundSegment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.name = "static sensor"; + bodyDef.type = b2_staticBody; + bodyDef.position = { -3.0f, 0.8f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = SENSOR; + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + b2Polygon box = b2MakeSquare( 1.0f ); + m_staticSensorId = b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.name = "kinematic sensor"; + bodyDef.type = b2_kinematicBody; + bodyDef.position = { 0.0f, 0.0f }; + bodyDef.linearVelocity = { 0.0f, 1.0f }; + m_kinematicBodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = SENSOR; + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + b2Polygon box = b2MakeSquare( 1.0f ); + m_kinematicSensorId = b2CreatePolygonShape( m_kinematicBodyId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.name = "dynamic sensor"; + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 3.0f, 1.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = SENSOR; + shapeDef.isSensor = true; + shapeDef.enableSensorEvents = true; + b2Polygon box = b2MakeSquare( 1.0f ); + m_dynamicSensorId = b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + // Add some real collision so the dynamic body is valid + shapeDef.filter.categoryBits = DEFAULT; + shapeDef.isSensor = false; + shapeDef.enableSensorEvents = false; + box = b2MakeSquare( 0.8f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.name = "ball_01"; + bodyDef.position = { -5.0f, 1.0f }; + bodyDef.type = b2_dynamicBody; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = DEFAULT; + shapeDef.filter.maskBits = GROUND | DEFAULT | SENSOR; + shapeDef.enableSensorEvents = true; + + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void PrintOverlaps( b2ShapeId sensorShapeId, const char* prefix ) + { + char buffer[256] = {}; + + // Determine the necessary capacity + int capacity = b2Shape_GetSensorCapacity( sensorShapeId ); + m_overlaps.resize( capacity ); + + // Get all overlaps and record the actual count + int count = b2Shape_GetSensorOverlaps( sensorShapeId, m_overlaps.data(), capacity ); + m_overlaps.resize( count ); + + int start = snprintf( buffer, sizeof( buffer ), "%s: ", prefix ); + for ( int i = 0; i < count && start < sizeof( buffer ); ++i ) + { + b2ShapeId visitorId = m_overlaps[i]; + if ( b2Shape_IsValid( visitorId ) == false ) + { + continue; + } + + b2BodyId bodyId = b2Shape_GetBody( visitorId ); + const char* name = b2Body_GetName( bodyId ); + if ( name == nullptr ) + { + continue; + } + + // todo fix this + start += snprintf( buffer + start, sizeof( buffer ) - start, "%s, ", name ); + } + + DrawTextLine( buffer ); + } + + void Step( Settings& settings ) override + { + b2Vec2 position = b2Body_GetPosition( m_kinematicBodyId ); + if ( position.y < 0.0f ) + { + b2Body_SetLinearVelocity( m_kinematicBodyId, { 0.0f, 1.0f } ); + // b2Body_SetKinematicTarget( m_kinematicBodyId ); + } + else if ( position.y > 3.0f ) + { + b2Body_SetLinearVelocity( m_kinematicBodyId, { 0.0f, -1.0f } ); + } + + Sample::Step( settings ); + + PrintOverlaps( m_staticSensorId, "static" ); + PrintOverlaps( m_kinematicSensorId, "kinematic" ); + PrintOverlaps( m_dynamicSensorId, "dynamic" ); + + b2Vec2 origin = { 5.0f, 1.0f }; + b2Vec2 translation = { -10.0f, 0.0f }; + b2RayResult result = b2World_CastRayClosest( m_worldId, origin, translation, b2DefaultQueryFilter() ); + g_draw.DrawSegment( origin, origin + translation, b2_colorDimGray ); + + if ( result.hit ) + { + g_draw.DrawPoint( result.point, 10.0f, b2_colorCyan ); + } + } + + static Sample* Create( Settings& settings ) + { + return new SensorTypes( settings ); + } + + b2ShapeId m_staticSensorId; + b2ShapeId m_kinematicSensorId; + b2ShapeId m_dynamicSensorId; + + b2BodyId m_kinematicBodyId; + + std::vector m_overlaps; +}; + +static int sampleSensorTypes = RegisterSample( "Events", "Sensor Types", SensorTypes::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_geometry.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_geometry.cpp new file mode 100644 index 000000000000..04b1ce75cd7d --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_geometry.cpp @@ -0,0 +1,221 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/math_functions.h" + +#include + +class ConvexHull : public Sample +{ +public: + enum + { + e_count = B2_MAX_POLYGON_VERTICES + }; + + explicit ConvexHull( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.5f, 0.0f }; + g_camera.m_zoom = 25.0f * 0.3f; + } + + m_generation = 0; + m_auto = false; + m_bulk = false; + Generate(); + } + + void Generate() + { +#if 0 + m_points[0] = { 5.65314484f, 0.204832315f }; + m_points[1] = {-5.65314484f, -0.204832315f }; + m_points[2] = {2.34463644f, 1.15731204f }; + m_points[3] = {0.0508846045f, 3.23230696f }; + m_points[4] = {-5.65314484f, -0.204832315f }; + m_points[5] = {-5.65314484f, -0.204832315f }; + m_points[6] = {3.73758054f, -1.11098099f }; + m_points[7] = {1.33504069f, -4.43795443f }; + + m_count = e_count; +#elif 0 + m_points[0] = { -0.328125, 0.179688 }; + m_points[1] = { -0.203125, 0.304688 }; + m_points[2] = { 0.171875, 0.304688 }; + m_points[3] = { 0.359375, 0.117188 }; + m_points[4] = { 0.359375, -0.195313 }; + m_points[5] = { 0.234375, -0.320313 }; + m_points[6] = { -0.265625, -0.257813 }; + m_points[7] = { -0.328125, -0.132813 }; + + b2Hull hull = b2ComputeHull( m_points, 8 ); + bool valid = b2ValidateHull( &hull ); + if ( valid == false ) + { + assert( valid ); + } + + m_count = e_count; +#else + + float angle = B2_PI * RandomFloat(); + b2Rot r = b2MakeRot( angle ); + + b2Vec2 lowerBound = { -4.0f, -4.0f }; + b2Vec2 upperBound = { 4.0f, 4.0f }; + + for ( int i = 0; i < e_count; ++i ) + { + float x = 10.0f * RandomFloat(); + float y = 10.0f * RandomFloat(); + + // Clamp onto a square to help create collinearities. + // This will stress the convex hull algorithm. + b2Vec2 v = b2Clamp( { x, y }, lowerBound, upperBound ); + m_points[i] = b2RotateVector( r, v ); + } + + m_count = e_count; +#endif + + m_generation += 1; + } + + void Keyboard( int key ) override + { + switch ( key ) + { + case GLFW_KEY_A: + m_auto = !m_auto; + break; + + case GLFW_KEY_B: + m_bulk = !m_bulk; + break; + + case GLFW_KEY_G: + Generate(); + break; + + default: + break; + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "Options: generate(g), auto(a), bulk(b)" ); + m_textLine += m_textIncrement; + + b2Hull hull; + bool valid = false; + float milliseconds = 0.0f; + + if ( m_bulk ) + { +#if 1 + // defect hunting + for ( int i = 0; i < 10000; ++i ) + { + Generate(); + hull = b2ComputeHull( m_points, m_count ); + if ( hull.count == 0 ) + { + // m_bulk = false; + // break; + continue; + } + + valid = b2ValidateHull( &hull ); + if ( valid == false || m_bulk == false ) + { + m_bulk = false; + break; + } + } +#else + // performance + Generate(); + b2Timer timer; + for ( int i = 0; i < 1000000; ++i ) + { + hull = b2ComputeHull( m_points, m_count ); + } + valid = hull.count > 0; + milliseconds = timer.GetMilliseconds(); +#endif + } + else + { + if ( m_auto ) + { + Generate(); + } + + hull = b2ComputeHull( m_points, m_count ); + if ( hull.count > 0 ) + { + valid = b2ValidateHull( &hull ); + if ( valid == false ) + { + m_auto = false; + } + } + } + + if ( valid == false ) + { + g_draw.DrawString( 5, m_textLine, "generation = %d, FAILED", m_generation ); + m_textLine += m_textIncrement; + } + else + { + g_draw.DrawString( 5, m_textLine, "generation = %d, count = %d", m_generation, hull.count ); + m_textLine += m_textIncrement; + } + + if ( milliseconds > 0.0f ) + { + g_draw.DrawString( 5, m_textLine, "milliseconds = %g", milliseconds ); + m_textLine += m_textIncrement; + } + + m_textLine += m_textIncrement; + + g_draw.DrawPolygon( hull.points, hull.count, b2_colorGray ); + + for ( int32_t i = 0; i < m_count; ++i ) + { + g_draw.DrawPoint( m_points[i], 5.0f, b2_colorBlue ); + g_draw.DrawString( b2Add( m_points[i], { 0.1f, 0.1f } ), "%d", i ); + } + + for ( int32_t i = 0; i < hull.count; ++i ) + { + g_draw.DrawPoint( hull.points[i], 6.0f, b2_colorGreen ); + } + } + + static Sample* Create( Settings& settings ) + { + return new ConvexHull( settings ); + } + + b2Vec2 m_points[B2_MAX_POLYGON_VERTICES]; + int32_t m_count; + int32_t m_generation; + bool m_auto; + bool m_bulk; +}; + +static int sampleIndex = RegisterSample( "Geometry", "Convex Hull", ConvexHull::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_joints.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_joints.cpp new file mode 100644 index 000000000000..a9fb68154dc5 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_joints.cpp @@ -0,0 +1,2863 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "car.h" +#include "donut.h" +#include "doohickey.h" +#include "draw.h" +#include "human.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include + +// Test the distance joint and all options +class DistanceJoint : public Sample +{ +public: + enum + { + e_maxCount = 10 + }; + + explicit DistanceJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 12.0f }; + g_camera.m_zoom = 25.0f * 0.35f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + m_count = 0; + m_hertz = 2.0f; + m_dampingRatio = 0.5f; + m_length = 1.0f; + m_minLength = m_length; + m_maxLength = m_length; + m_enableSpring = false; + m_enableLimit = false; + + for ( int i = 0; i < e_maxCount; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + m_jointIds[i] = b2_nullJointId; + } + + CreateScene( 1 ); + } + + void CreateScene( int newCount ) + { + // Must destroy joints before bodies + for ( int i = 0; i < m_count; ++i ) + { + b2DestroyJoint( m_jointIds[i] ); + m_jointIds[i] = b2_nullJointId; + } + + for ( int i = 0; i < m_count; ++i ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + } + + m_count = newCount; + + float radius = 0.25f; + b2Circle circle = { { 0.0f, 0.0f }, radius }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + float yOffset = 20.0f; + + b2DistanceJointDef jointDef = b2DefaultDistanceJointDef(); + jointDef.hertz = m_hertz; + jointDef.dampingRatio = m_dampingRatio; + jointDef.length = m_length; + jointDef.minLength = m_minLength; + jointDef.maxLength = m_maxLength; + jointDef.enableSpring = m_enableSpring; + jointDef.enableLimit = m_enableLimit; + + b2BodyId prevBodyId = m_groundId; + for ( int i = 0; i < m_count; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.angularDamping = 0.1f; + bodyDef.position = { m_length * ( i + 1.0f ), yOffset }; + m_bodyIds[i] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( m_bodyIds[i], &shapeDef, &circle ); + + b2Vec2 pivotA = { m_length * i, yOffset }; + b2Vec2 pivotB = { m_length * ( i + 1.0f ), yOffset }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = m_bodyIds[i]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivotA ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivotB ); + m_jointIds[i] = b2CreateDistanceJoint( m_worldId, &jointDef ); + + prevBodyId = m_bodyIds[i]; + } + } + + void UpdateGui() override + { + float height = 240.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Distance Joint", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + if ( ImGui::SliderFloat( "Length", &m_length, 0.1f, 4.0f, "%3.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_SetLength( m_jointIds[i], m_length ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + + if ( ImGui::Checkbox( "Spring", &m_enableSpring ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_EnableSpring( m_jointIds[i], m_enableSpring ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + + if ( m_enableSpring ) + { + if ( ImGui::SliderFloat( "Hertz", &m_hertz, 0.0f, 15.0f, "%3.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_SetSpringHertz( m_jointIds[i], m_hertz ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + + if ( ImGui::SliderFloat( "Damping", &m_dampingRatio, 0.0f, 4.0f, "%3.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_SetSpringDampingRatio( m_jointIds[i], m_dampingRatio ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + } + + if ( ImGui::Checkbox( "Limit", &m_enableLimit ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_EnableLimit( m_jointIds[i], m_enableLimit ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + + if ( m_enableLimit ) + { + if ( ImGui::SliderFloat( "Min Length", &m_minLength, 0.1f, 4.0f, "%3.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_SetLengthRange( m_jointIds[i], m_minLength, m_maxLength ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + + if ( ImGui::SliderFloat( "Max Length", &m_maxLength, 0.1f, 4.0f, "%3.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2DistanceJoint_SetLengthRange( m_jointIds[i], m_minLength, m_maxLength ); + b2Joint_WakeBodies( m_jointIds[i] ); + } + } + } + + int count = m_count; + if ( ImGui::SliderInt( "Count", &count, 1, e_maxCount ) ) + { + CreateScene( count ); + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new DistanceJoint( settings ); + } + + b2BodyId m_groundId; + b2BodyId m_bodyIds[e_maxCount]; + b2JointId m_jointIds[e_maxCount]; + int m_count; + float m_hertz; + float m_dampingRatio; + float m_length; + float m_minLength; + float m_maxLength; + bool m_enableSpring; + bool m_enableLimit; +}; + +static int sampleDistanceJoint = RegisterSample( "Joints", "Distance Joint", DistanceJoint::Create ); + +/// This test shows how to use a motor joint. A motor joint +/// can be used to animate a dynamic body. With finite motor forces +/// the body can be blocked by collision with other bodies. +/// By setting the correction factor to zero, the motor joint acts +/// like top-down dry friction. +class MotorJoint : public Sample +{ +public: + explicit MotorJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 7.0f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Define motorized body + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 8.0f }; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 2.0f, 0.5f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + + m_maxForce = 500.0f; + m_maxTorque = 500.0f; + m_correctionFactor = 0.3f; + + b2MotorJointDef jointDef = b2DefaultMotorJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = m_bodyId; + jointDef.maxForce = m_maxForce; + jointDef.maxTorque = m_maxTorque; + jointDef.correctionFactor = m_correctionFactor; + + m_jointId = b2CreateMotorJoint( m_worldId, &jointDef ); + } + + m_go = true; + m_time = 0.0f; + } + + void UpdateGui() override + { + float height = 180.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Motor Joint", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Go", &m_go ) ) + { + } + + if ( ImGui::SliderFloat( "Max Force", &m_maxForce, 0.0f, 1000.0f, "%.0f" ) ) + { + b2MotorJoint_SetMaxForce( m_jointId, m_maxForce ); + } + + if ( ImGui::SliderFloat( "Max Torque", &m_maxTorque, 0.0f, 1000.0f, "%.0f" ) ) + { + b2MotorJoint_SetMaxTorque( m_jointId, m_maxTorque ); + } + + if ( ImGui::SliderFloat( "Correction", &m_correctionFactor, 0.0f, 1.0f, "%.1f" ) ) + { + b2MotorJoint_SetCorrectionFactor( m_jointId, m_correctionFactor ); + } + + if ( ImGui::Button( "Apply Impulse" ) ) + { + b2Body_ApplyLinearImpulseToCenter( m_bodyId, { 100.0f, 0.0f }, true ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( m_go && settings.hertz > 0.0f ) + { + m_time += 1.0f / settings.hertz; + } + + b2Vec2 linearOffset; + linearOffset.x = 6.0f * sinf( 2.0f * m_time ); + linearOffset.y = 8.0f + 4.0f * sinf( 1.0f * m_time ); + + float angularOffset = B2_PI * sinf( -0.5f * m_time ); + + b2MotorJoint_SetLinearOffset( m_jointId, linearOffset ); + b2MotorJoint_SetAngularOffset( m_jointId, angularOffset ); + + b2Transform transform = { linearOffset, b2MakeRot( angularOffset ) }; + g_draw.DrawTransform( transform ); + + Sample::Step( settings ); + + b2Vec2 force = b2Joint_GetConstraintForce( m_jointId ); + float torque = b2Joint_GetConstraintTorque( m_jointId ); + + g_draw.DrawString( 5, m_textLine, "force = {%3.f, %3.f}, torque = %3.f", force.x, force.y, torque ); + m_textLine += 15; + } + + static Sample* Create( Settings& settings ) + { + return new MotorJoint( settings ); + } + + b2BodyId m_bodyId; + b2JointId m_jointId; + float m_time; + float m_maxForce; + float m_maxTorque; + float m_correctionFactor; + bool m_go; +}; + +static int sampleMotorJoint = RegisterSample( "Joints", "Motor Joint", MotorJoint::Create ); + +// This sample shows how to use a filter joint to prevent collision between two bodies. +// This is more specific than shape filters. It also shows that sleeping is coupled by the filter joint. +class FilterJoint : public Sample +{ +public: + explicit FilterJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 7.0f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + { + b2BodyId groundId; + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -4.0f, 2.0f }; + b2BodyId bodyId1 = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeSquare( 2.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( bodyId1, &shapeDef, &box ); + + bodyDef.position = { 4.0f, 2.0f }; + b2BodyId bodyId2 = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId2, &shapeDef, &box ); + + b2FilterJointDef jointDef = b2DefaultFilterJointDef(); + jointDef.bodyIdA = bodyId1; + jointDef.bodyIdB = bodyId2; + + b2CreateFilterJoint( m_worldId, &jointDef ); + } + } + + static Sample* Create( Settings& settings ) + { + return new FilterJoint( settings ); + } +}; + +static int sampleFilterJoint = RegisterSample( "Joints", "Filter Joint", FilterJoint::Create ); + +class RevoluteJoint : public Sample +{ +public: + explicit RevoluteJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 15.5f }; + g_camera.m_zoom = 25.0f * 0.7f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -1.0f }; + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 40.0f, 1.0f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + m_enableSpring = false; + m_enableLimit = true; + m_enableMotor = false; + m_hertz = 1.0f; + m_dampingRatio = 0.5f; + m_motorSpeed = 1.0f; + m_motorTorque = 1000.0f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -10.0f, 20.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + + b2Capsule capsule = { { 0.0f, -1.0f }, { 0.0f, 6.0f }, 0.5f }; + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = { -10.0f, 20.5f }; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableSpring = m_enableSpring; + jointDef.hertz = m_hertz; + jointDef.dampingRatio = m_dampingRatio; + jointDef.motorSpeed = m_motorSpeed; + jointDef.maxMotorTorque = m_motorTorque; + jointDef.enableMotor = m_enableMotor; + jointDef.referenceAngle = 0.5f * B2_PI; + jointDef.lowerAngle = -0.5f * B2_PI; + jointDef.upperAngle = 0.75f * B2_PI; + jointDef.enableLimit = m_enableLimit; + + m_jointId1 = b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + { + b2Circle circle = {}; + circle.radius = 2.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 5.0f, 30.0f }; + m_ball = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + + b2CreateCircleShape( m_ball, &shapeDef, &circle ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 20.0f, 10.0f }; + bodyDef.type = b2_dynamicBody; + b2BodyId body = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeOffsetBox( 10.0f, 0.5f, { -10.0f, 0.0f }, b2Rot_identity ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + b2CreatePolygonShape( body, &shapeDef, &box ); + + b2Vec2 pivot = { 19.0f, 10.0f }; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = body; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.lowerAngle = -0.25f * B2_PI; + jointDef.upperAngle = 0.5f * B2_PI; + jointDef.enableLimit = true; + jointDef.enableMotor = true; + jointDef.motorSpeed = 0.0f; + jointDef.maxMotorTorque = m_motorTorque; + + m_jointId2 = b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + } + + void UpdateGui() override + { + float height = 220.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Revolute Joint", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Limit", &m_enableLimit ) ) + { + b2RevoluteJoint_EnableLimit( m_jointId1, m_enableLimit ); + b2Joint_WakeBodies( m_jointId1 ); + } + + if ( ImGui::Checkbox( "Motor", &m_enableMotor ) ) + { + b2RevoluteJoint_EnableMotor( m_jointId1, m_enableMotor ); + b2Joint_WakeBodies( m_jointId1 ); + } + + if ( m_enableMotor ) + { + if ( ImGui::SliderFloat( "Max Torque", &m_motorTorque, 0.0f, 5000.0f, "%.0f" ) ) + { + b2RevoluteJoint_SetMaxMotorTorque( m_jointId1, m_motorTorque ); + b2Joint_WakeBodies( m_jointId1 ); + } + + if ( ImGui::SliderFloat( "Speed", &m_motorSpeed, -20.0f, 20.0f, "%.0f" ) ) + { + b2RevoluteJoint_SetMotorSpeed( m_jointId1, m_motorSpeed ); + b2Joint_WakeBodies( m_jointId1 ); + } + } + + if ( ImGui::Checkbox( "Spring", &m_enableSpring ) ) + { + b2RevoluteJoint_EnableSpring( m_jointId1, m_enableSpring ); + b2Joint_WakeBodies( m_jointId1 ); + } + + if ( m_enableSpring ) + { + if ( ImGui::SliderFloat( "Hertz", &m_hertz, 0.0f, 10.0f, "%.1f" ) ) + { + b2RevoluteJoint_SetSpringHertz( m_jointId1, m_hertz ); + b2Joint_WakeBodies( m_jointId1 ); + } + + if ( ImGui::SliderFloat( "Damping", &m_dampingRatio, 0.0f, 2.0f, "%.1f" ) ) + { + b2RevoluteJoint_SetSpringDampingRatio( m_jointId1, m_dampingRatio ); + b2Joint_WakeBodies( m_jointId1 ); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + float angle1 = b2RevoluteJoint_GetAngle( m_jointId1 ); + g_draw.DrawString( 5, m_textLine, "Angle (Deg) 1 = %2.1f", angle1 ); + m_textLine += m_textIncrement; + + float torque1 = b2RevoluteJoint_GetMotorTorque( m_jointId1 ); + g_draw.DrawString( 5, m_textLine, "Motor Torque 1 = %4.1f", torque1 ); + m_textLine += m_textIncrement; + + float torque2 = b2RevoluteJoint_GetMotorTorque( m_jointId2 ); + g_draw.DrawString( 5, m_textLine, "Motor Torque 2 = %4.1f", torque2 ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new RevoluteJoint( settings ); + } + + b2BodyId m_ball; + b2JointId m_jointId1; + b2JointId m_jointId2; + float m_motorSpeed; + float m_motorTorque; + float m_hertz; + float m_dampingRatio; + bool m_enableSpring; + bool m_enableMotor; + bool m_enableLimit; +}; + +static int sampleRevolute = RegisterSample( "Joints", "Revolute", RevoluteJoint::Create ); + +class PrismaticJoint : public Sample +{ +public: + explicit PrismaticJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 8.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + m_enableSpring = false; + m_enableLimit = true; + m_enableMotor = false; + m_motorSpeed = 2.0f; + m_motorForce = 25.0f; + m_hertz = 1.0f; + m_dampingRatio = 0.5f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 10.0f }; + bodyDef.type = b2_dynamicBody; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox( 0.5f, 2.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { 0.0f, 9.0f }; + // b2Vec2 axis = b2Normalize({1.0f, 0.0f}); + b2Vec2 axis = b2Normalize( { 1.0f, 1.0f } ); + b2PrismaticJointDef jointDef = b2DefaultPrismaticJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = m_motorSpeed; + jointDef.maxMotorForce = m_motorForce; + jointDef.enableMotor = m_enableMotor; + jointDef.lowerTranslation = -10.0f; + jointDef.upperTranslation = 10.0f; + jointDef.enableLimit = m_enableLimit; + jointDef.enableSpring = m_enableSpring; + jointDef.hertz = m_hertz; + jointDef.dampingRatio = m_dampingRatio; + + m_jointId = b2CreatePrismaticJoint( m_worldId, &jointDef ); + } + } + + void UpdateGui() override + { + float height = 220.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Prismatic Joint", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Limit", &m_enableLimit ) ) + { + b2PrismaticJoint_EnableLimit( m_jointId, m_enableLimit ); + b2Joint_WakeBodies( m_jointId ); + } + + if ( ImGui::Checkbox( "Motor", &m_enableMotor ) ) + { + b2PrismaticJoint_EnableMotor( m_jointId, m_enableMotor ); + b2Joint_WakeBodies( m_jointId ); + } + + if ( m_enableMotor ) + { + if ( ImGui::SliderFloat( "Max Force", &m_motorForce, 0.0f, 200.0f, "%.0f" ) ) + { + b2PrismaticJoint_SetMaxMotorForce( m_jointId, m_motorForce ); + b2Joint_WakeBodies( m_jointId ); + } + + if ( ImGui::SliderFloat( "Speed", &m_motorSpeed, -40.0f, 40.0f, "%.0f" ) ) + { + b2PrismaticJoint_SetMotorSpeed( m_jointId, m_motorSpeed ); + b2Joint_WakeBodies( m_jointId ); + } + } + + if ( ImGui::Checkbox( "Spring", &m_enableSpring ) ) + { + b2PrismaticJoint_EnableSpring( m_jointId, m_enableSpring ); + b2Joint_WakeBodies( m_jointId ); + } + + if ( m_enableSpring ) + { + if ( ImGui::SliderFloat( "Hertz", &m_hertz, 0.0f, 10.0f, "%.1f" ) ) + { + b2PrismaticJoint_SetSpringHertz( m_jointId, m_hertz ); + b2Joint_WakeBodies( m_jointId ); + } + + if ( ImGui::SliderFloat( "Damping", &m_dampingRatio, 0.0f, 2.0f, "%.1f" ) ) + { + b2PrismaticJoint_SetSpringDampingRatio( m_jointId, m_dampingRatio ); + b2Joint_WakeBodies( m_jointId ); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + float force = b2PrismaticJoint_GetMotorForce( m_jointId ); + g_draw.DrawString( 5, m_textLine, "Motor Force = %4.1f", force ); + m_textLine += m_textIncrement; + + float translation = b2PrismaticJoint_GetTranslation( m_jointId ); + g_draw.DrawString( 5, m_textLine, "Translation = %4.1f", translation ); + m_textLine += m_textIncrement; + + float speed = b2PrismaticJoint_GetSpeed( m_jointId ); + g_draw.DrawString( 5, m_textLine, "Speed = %4.8f", speed ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new PrismaticJoint( settings ); + } + + b2JointId m_jointId; + float m_motorSpeed; + float m_motorForce; + float m_hertz; + float m_dampingRatio; + bool m_enableSpring; + bool m_enableMotor; + bool m_enableLimit; +}; + +static int samplePrismatic = RegisterSample( "Joints", "Prismatic", PrismaticJoint::Create ); + +class WheelJoint : public Sample +{ +public: + explicit WheelJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.15f; + } + + b2BodyId groundId; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + m_enableSpring = true; + m_enableLimit = true; + m_enableMotor = true; + m_motorSpeed = 2.0f; + m_motorTorque = 5.0f; + m_hertz = 1.0f; + m_dampingRatio = 0.7f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 10.25f }; + bodyDef.type = b2_dynamicBody; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Capsule capsule = { { 0.0f, -0.5f }, { 0.0f, 0.5f }, 0.5f }; + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = { 0.0f, 10.0f }; + b2Vec2 axis = b2Normalize( { 1.0f, 1.0f } ); + b2WheelJointDef jointDef = b2DefaultWheelJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, axis ); + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.motorSpeed = m_motorSpeed; + jointDef.maxMotorTorque = m_motorTorque; + jointDef.enableMotor = m_enableMotor; + jointDef.lowerTranslation = -3.0f; + jointDef.upperTranslation = 3.0f; + jointDef.enableLimit = m_enableLimit; + jointDef.hertz = m_hertz; + jointDef.dampingRatio = m_dampingRatio; + + m_jointId = b2CreateWheelJoint( m_worldId, &jointDef ); + } + } + + void UpdateGui() override + { + float height = 220.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Wheel Joint", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Limit", &m_enableLimit ) ) + { + b2WheelJoint_EnableLimit( m_jointId, m_enableLimit ); + } + + if ( ImGui::Checkbox( "Motor", &m_enableMotor ) ) + { + b2WheelJoint_EnableMotor( m_jointId, m_enableMotor ); + } + + if ( m_enableMotor ) + { + if ( ImGui::SliderFloat( "Torque", &m_motorTorque, 0.0f, 20.0f, "%.0f" ) ) + { + b2WheelJoint_SetMaxMotorTorque( m_jointId, m_motorTorque ); + } + + if ( ImGui::SliderFloat( "Speed", &m_motorSpeed, -20.0f, 20.0f, "%.0f" ) ) + { + b2WheelJoint_SetMotorSpeed( m_jointId, m_motorSpeed ); + } + } + + if ( ImGui::Checkbox( "Spring", &m_enableSpring ) ) + { + b2WheelJoint_EnableSpring( m_jointId, m_enableSpring ); + } + + if ( m_enableSpring ) + { + if ( ImGui::SliderFloat( "Hertz", &m_hertz, 0.0f, 10.0f, "%.1f" ) ) + { + b2WheelJoint_SetSpringHertz( m_jointId, m_hertz ); + } + + if ( ImGui::SliderFloat( "Damping", &m_dampingRatio, 0.0f, 2.0f, "%.1f" ) ) + { + b2WheelJoint_SetSpringDampingRatio( m_jointId, m_dampingRatio ); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + float torque = b2WheelJoint_GetMotorTorque( m_jointId ); + g_draw.DrawString( 5, m_textLine, "Motor Torque = %4.1f", torque ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new WheelJoint( settings ); + } + + b2JointId m_jointId; + float m_hertz; + float m_dampingRatio; + float m_motorSpeed; + float m_motorTorque; + bool m_enableSpring; + bool m_enableMotor; + bool m_enableLimit; +}; + +static int sampleWheel = RegisterSample( "Joints", "Wheel", WheelJoint::Create ); + +// A suspension bridge +class Bridge : public Sample +{ +public: + explicit Bridge( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 2.5f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + { + b2Polygon box = b2MakeBox( 0.5f, 0.125f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + int jointIndex = 0; + m_frictionTorque = 200.0f; + m_gravityScale = 1.0f; + + float xbase = -80.0f; + + b2BodyId prevBodyId = groundId; + for ( int i = 0; i < m_count; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { xbase + 0.5f + 1.0f * i, 20.0f }; + bodyDef.linearDamping = 0.1f; + bodyDef.angularDamping = 0.1f; + m_bodyIds[i] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyIds[i], &shapeDef, &box ); + + b2Vec2 pivot = { xbase + 1.0f * i, 20.0f }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = m_bodyIds[i]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableMotor = true; + jointDef.maxMotorTorque = m_frictionTorque; + m_jointIds[jointIndex++] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + + prevBodyId = m_bodyIds[i]; + } + + b2Vec2 pivot = { xbase + 1.0f * m_count, 20.0f }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = groundId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableMotor = true; + jointDef.maxMotorTorque = m_frictionTorque; + m_jointIds[jointIndex++] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + + assert( jointIndex == m_count + 1 ); + } + + for ( int i = 0; i < 2; ++i ) + { + b2Vec2 vertices[3] = { { -0.5f, 0.0f }, { 0.5f, 0.0f }, { 0.0f, 1.5f } }; + + b2Hull hull = b2ComputeHull( vertices, 3 ); + b2Polygon triangle = b2MakePolygon( &hull, 0.0f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -8.0f + 8.0f * i, 22.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &triangle ); + } + + for ( int i = 0; i < 3; ++i ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -6.0f + 6.0f * i, 25.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void UpdateGui() override + { + float height = 80.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Bridge", nullptr, ImGuiWindowFlags_NoResize ); + + // Slider takes half the window + ImGui::PushItemWidth( ImGui::GetWindowWidth() * 0.5f ); + bool updateFriction = ImGui::SliderFloat( "Joint Friction", &m_frictionTorque, 0.0f, 1000.0f, "%2.f" ); + if ( updateFriction ) + { + for ( int i = 0; i <= m_count; ++i ) + { + b2RevoluteJoint_SetMaxMotorTorque( m_jointIds[i], m_frictionTorque ); + } + } + + if ( ImGui::SliderFloat( "Gravity scale", &m_gravityScale, -1.0f, 1.0f, "%.1f" ) ) + { + for ( int i = 0; i < m_count; ++i ) + { + b2Body_SetGravityScale( m_bodyIds[i], m_gravityScale ); + } + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new Bridge( settings ); + } + + static constexpr int m_count = 160; + b2BodyId m_bodyIds[m_count]; + b2JointId m_jointIds[m_count + 1]; + float m_frictionTorque; + float m_gravityScale; +}; + +static int sampleBridgeIndex = RegisterSample( "Joints", "Bridge", Bridge::Create ); + +class BallAndChain : public Sample +{ +public: + explicit BallAndChain( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, -8.0f }; + g_camera.m_zoom = 27.5f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + m_frictionTorque = 100.0f; + + { + float hx = 0.5f; + b2Capsule capsule = { { -hx, 0.0f }, { hx, 0.0f }, 0.125f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + + int jointIndex = 0; + + b2BodyId prevBodyId = groundId; + for ( int i = 0; i < m_count; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { ( 1.0f + 2.0f * i ) * hx, m_count * hx }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = { ( 2.0f * i ) * hx, m_count * hx }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + // jointDef.enableMotor = true; + jointDef.maxMotorTorque = m_frictionTorque; + m_jointIds[jointIndex++] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + + prevBodyId = bodyId; + } + + b2Circle circle = { { 0.0f, 0.0f }, 4.0f }; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { ( 1.0f + 2.0f * m_count ) * hx + circle.radius - hx, m_count * hx }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + b2Vec2 pivot = { ( 2.0f * m_count ) * hx, m_count * hx }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableMotor = true; + jointDef.maxMotorTorque = m_frictionTorque; + m_jointIds[jointIndex++] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + assert( jointIndex == m_count + 1 ); + } + } + + void UpdateGui() override + { + float height = 60.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Ball and Chain", nullptr, ImGuiWindowFlags_NoResize ); + + bool updateFriction = ImGui::SliderFloat( "Joint Friction", &m_frictionTorque, 0.0f, 1000.0f, "%2.f" ); + if ( updateFriction ) + { + for ( int i = 0; i <= m_count; ++i ) + { + b2RevoluteJoint_SetMaxMotorTorque( m_jointIds[i], m_frictionTorque ); + } + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new BallAndChain( settings ); + } + + static constexpr int m_count = 30; + b2JointId m_jointIds[m_count + 1]; + float m_frictionTorque; +}; + +static int sampleBallAndChainIndex = RegisterSample( "Joints", "Ball & Chain", BallAndChain::Create ); + +// This sample shows the limitations of an iterative solver. The cantilever sags even though the weld +// joint is stiff as possible. +class Cantilever : public Sample +{ +public: + enum + { + e_count = 8 + }; + + explicit Cantilever( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 0.35f; + } + + b2BodyId groundId = b2_nullBodyId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + } + + { + m_linearHertz = 15.0f; + m_linearDampingRatio = 0.5f; + m_angularHertz = 5.0f; + m_angularDampingRatio = 0.5f; + m_gravityScale = 1.0f; + m_collideConnected = false; + + float hx = 0.5f; + b2Capsule capsule = { { -hx, 0.0f }, { hx, 0.0f }, 0.125f }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2WeldJointDef jointDef = b2DefaultWeldJointDef(); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.isAwake = false; + + b2BodyId prevBodyId = groundId; + for ( int i = 0; i < e_count; ++i ) + { + bodyDef.position = { ( 1.0f + 2.0f * i ) * hx, 0.0f }; + m_bodyIds[i] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[i], &shapeDef, &capsule ); + + b2Vec2 pivot = { ( 2.0f * i ) * hx, 0.0f }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = m_bodyIds[i]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.linearHertz = m_linearHertz; + jointDef.linearDampingRatio = m_linearDampingRatio; + jointDef.angularHertz = m_angularHertz; + jointDef.angularDampingRatio = m_angularDampingRatio; + jointDef.collideConnected = m_collideConnected; + m_jointIds[i] = b2CreateWeldJoint( m_worldId, &jointDef ); + + prevBodyId = m_bodyIds[i]; + } + + m_tipId = prevBodyId; + } + } + + void UpdateGui() override + { + float height = 180.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Cantilever", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + if ( ImGui::SliderFloat( "Linear Hertz", &m_linearHertz, 0.0f, 20.0f, "%.0f" ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2WeldJoint_SetLinearHertz( m_jointIds[i], m_linearHertz ); + } + } + + if ( ImGui::SliderFloat( "Linear Damping Ratio", &m_linearDampingRatio, 0.0f, 10.0f, "%.1f" ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2WeldJoint_SetLinearDampingRatio( m_jointIds[i], m_linearDampingRatio ); + } + } + + if ( ImGui::SliderFloat( "Angular Hertz", &m_angularHertz, 0.0f, 20.0f, "%.0f" ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2WeldJoint_SetAngularHertz( m_jointIds[i], m_angularHertz ); + } + } + + if ( ImGui::SliderFloat( "Angular Damping Ratio", &m_angularDampingRatio, 0.0f, 10.0f, "%.1f" ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2WeldJoint_SetAngularDampingRatio( m_jointIds[i], m_angularDampingRatio ); + } + } + + if ( ImGui::Checkbox( "Collide Connected", &m_collideConnected ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2Joint_SetCollideConnected( m_jointIds[i], m_collideConnected ); + } + } + + if ( ImGui::SliderFloat( "Gravity Scale", &m_gravityScale, -1.0f, 1.0f, "%.1f" ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2Body_SetGravityScale( m_bodyIds[i], m_gravityScale ); + } + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2Vec2 tipPosition = b2Body_GetPosition( m_tipId ); + g_draw.DrawString( 5, m_textLine, "tip-y = %.2f", tipPosition.y ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new Cantilever( settings ); + } + + float m_linearHertz; + float m_linearDampingRatio; + float m_angularHertz; + float m_angularDampingRatio; + float m_gravityScale; + b2BodyId m_tipId; + b2BodyId m_bodyIds[e_count]; + b2JointId m_jointIds[e_count]; + bool m_collideConnected; +}; + +static int sampleCantileverIndex = RegisterSample( "Joints", "Cantilever", Cantilever::Create ); + +// This test ensures joints work correctly with bodies that have fixed rotation +class FixedRotation : public Sample +{ +public: + enum + { + e_count = 6 + }; + + explicit FixedRotation( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 8.0f }; + g_camera.m_zoom = 25.0f * 0.7f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + m_fixedRotation = true; + + for ( int i = 0; i < e_count; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + m_jointIds[i] = b2_nullJointId; + } + + CreateScene(); + } + + void CreateScene() + { + for ( int i = 0; i < e_count; ++i ) + { + if ( B2_IS_NON_NULL( m_jointIds[i] ) ) + { + b2DestroyJoint( m_jointIds[i] ); + m_jointIds[i] = b2_nullJointId; + } + + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + } + } + + b2Vec2 position = { -12.5f, 10.0f }; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.fixedRotation = m_fixedRotation; + + b2Polygon box = b2MakeBox( 1.0f, 1.0f ); + + int index = 0; + + // distance joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + float length = 2.0f; + b2Vec2 pivot1 = { position.x, position.y + 1.0f + length }; + b2Vec2 pivot2 = { position.x, position.y + 1.0f }; + b2DistanceJointDef jointDef = b2DefaultDistanceJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot1 ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot2 ); + jointDef.length = length; + m_jointIds[index] = b2CreateDistanceJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // motor joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + b2MotorJointDef jointDef = b2DefaultMotorJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.linearOffset = position; + jointDef.maxForce = 200.0f; + jointDef.maxTorque = 20.0f; + m_jointIds[index] = b2CreateMotorJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // prismatic joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2PrismaticJointDef jointDef = b2DefaultPrismaticJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, { 1.0f, 0.0f } ); + m_jointIds[index] = b2CreatePrismaticJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // revolute joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + m_jointIds[index] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // weld joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2WeldJointDef jointDef = b2DefaultWeldJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.angularHertz = 1.0f; + jointDef.angularDampingRatio = 0.5f; + jointDef.linearHertz = 1.0f; + jointDef.linearDampingRatio = 0.5f; + m_jointIds[index] = b2CreateWeldJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // wheel joint + { + assert( index < e_count ); + + bodyDef.position = position; + m_bodyIds[index] = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( m_bodyIds[index], &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2WheelJointDef jointDef = b2DefaultWheelJointDef(); + jointDef.bodyIdA = m_groundId; + jointDef.bodyIdB = m_bodyIds[index]; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, { 1.0f, 0.0f } ); + jointDef.hertz = 1.0f; + jointDef.dampingRatio = 0.7f; + jointDef.lowerTranslation = -1.0f; + jointDef.upperTranslation = 1.0f; + jointDef.enableLimit = true; + jointDef.enableMotor = true; + jointDef.maxMotorTorque = 10.0f; + jointDef.motorSpeed = 1.0f; + m_jointIds[index] = b2CreateWheelJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + } + + void UpdateGui() override + { + float height = 60.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Fixed Rotation", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Fixed Rotation", &m_fixedRotation ) ) + { + for ( int i = 0; i < e_count; ++i ) + { + b2Body_SetFixedRotation( m_bodyIds[i], m_fixedRotation ); + } + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new FixedRotation( settings ); + } + + b2BodyId m_groundId; + b2BodyId m_bodyIds[e_count]; + b2JointId m_jointIds[e_count]; + bool m_fixedRotation; +}; + +static int sampleFixedRotation = RegisterSample( "Joints", "Fixed Rotation", FixedRotation::Create ); + +// This sample shows how to break joints when the internal reaction force becomes large. +class BreakableJoint : public Sample +{ +public: + enum + { + e_count = 6 + }; + + explicit BreakableJoint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 8.0f }; + g_camera.m_zoom = 25.0f * 0.7f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + for ( int i = 0; i < e_count; ++i ) + { + m_jointIds[i] = b2_nullJointId; + } + + b2Vec2 position = { -12.5f, 10.0f }; + bodyDef.type = b2_dynamicBody; + bodyDef.enableSleep = false; + + b2Polygon box = b2MakeBox( 1.0f, 1.0f ); + + int index = 0; + + // distance joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + float length = 2.0f; + b2Vec2 pivot1 = { position.x, position.y + 1.0f + length }; + b2Vec2 pivot2 = { position.x, position.y + 1.0f }; + b2DistanceJointDef jointDef = b2DefaultDistanceJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot1 ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot2 ); + jointDef.length = length; + jointDef.collideConnected = true; + m_jointIds[index] = b2CreateDistanceJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // motor joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2MotorJointDef jointDef = b2DefaultMotorJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.linearOffset = position; + jointDef.maxForce = 1000.0f; + jointDef.maxTorque = 20.0f; + jointDef.collideConnected = true; + m_jointIds[index] = b2CreateMotorJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // prismatic joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2PrismaticJointDef jointDef = b2DefaultPrismaticJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, { 1.0f, 0.0f } ); + jointDef.collideConnected = true; + m_jointIds[index] = b2CreatePrismaticJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // revolute joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.collideConnected = true; + m_jointIds[index] = b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // weld joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2WeldJointDef jointDef = b2DefaultWeldJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.angularHertz = 2.0f; + jointDef.angularDampingRatio = 0.5f; + jointDef.linearHertz = 2.0f; + jointDef.linearDampingRatio = 0.5f; + jointDef.collideConnected = true; + m_jointIds[index] = b2CreateWeldJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + // wheel joint + { + assert( index < e_count ); + + bodyDef.position = position; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = { position.x - 1.0f, position.y }; + b2WheelJointDef jointDef = b2DefaultWheelJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.localAxisA = b2Body_GetLocalVector( jointDef.bodyIdA, { 1.0f, 0.0f } ); + jointDef.hertz = 1.0f; + jointDef.dampingRatio = 0.7f; + jointDef.lowerTranslation = -1.0f; + jointDef.upperTranslation = 1.0f; + jointDef.enableLimit = true; + jointDef.enableMotor = true; + jointDef.maxMotorTorque = 10.0f; + jointDef.motorSpeed = 1.0f; + jointDef.collideConnected = true; + m_jointIds[index] = b2CreateWheelJoint( m_worldId, &jointDef ); + } + + position.x += 5.0f; + ++index; + + m_breakForce = 1000.0f; + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Breakable Joint", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::SliderFloat( "break force", &m_breakForce, 0.0f, 10000.0f, "%.1f" ); + + b2Vec2 gravity = b2World_GetGravity( m_worldId ); + if ( ImGui::SliderFloat( "gravity", &gravity.y, -50.0f, 50.0f, "%.1f" ) ) + { + b2World_SetGravity( m_worldId, gravity ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + for ( int i = 0; i < e_count; ++i ) + { + if ( B2_IS_NULL( m_jointIds[i] ) ) + { + continue; + } + + b2Vec2 force = b2Joint_GetConstraintForce( m_jointIds[i] ); + if ( b2LengthSquared( force ) > m_breakForce * m_breakForce ) + { + b2DestroyJoint( m_jointIds[i] ); + m_jointIds[i] = b2_nullJointId; + } + else + { + b2Vec2 point = b2Joint_GetLocalAnchorA( m_jointIds[i] ); + g_draw.DrawString( point, "(%.1f, %.1f)", force.x, force.y ); + } + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new BreakableJoint( settings ); + } + + b2JointId m_jointIds[e_count]; + float m_breakForce; +}; + +static int sampleBreakableJoint = RegisterSample( "Joints", "Breakable", BreakableJoint::Create ); + +// This shows how you can implement a constraint outside of Box2D +class UserConstraint : public Sample +{ +public: + explicit UserConstraint( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 3.0f, -1.0f }; + g_camera.m_zoom = 25.0f * 0.15f; + } + + b2Polygon box = b2MakeBox( 1.0f, 0.5f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 20.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.gravityScale = 1.0f; + bodyDef.angularDamping = 0.5f; + bodyDef.linearDamping = 0.2f; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + + m_impulses[0] = 0.0f; + m_impulses[1] = 0.0f; + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2Transform axes = b2Transform_identity; + g_draw.DrawTransform( axes ); + + if ( settings.pause ) + { + return; + } + + float timeStep = settings.hertz > 0.0f ? 1.0f / settings.hertz : 0.0f; + if ( timeStep == 0.0f ) + { + return; + } + + float invTimeStep = settings.hertz; + + static float hertz = 3.0f; + static float zeta = 0.7f; + static float maxForce = 1000.0f; + float omega = 2.0f * B2_PI * hertz; + float sigma = 2.0f * zeta + timeStep * omega; + float s = timeStep * omega * sigma; + float impulseCoefficient = 1.0f / ( 1.0f + s ); + float massCoefficient = s * impulseCoefficient; + float biasCoefficient = omega / sigma; + + b2Vec2 localAnchors[2] = { { 1.0f, -0.5f }, { 1.0f, 0.5f } }; + float mass = b2Body_GetMass( m_bodyId ); + float invMass = mass < 0.0001f ? 0.0f : 1.0f / mass; + float inertiaTensor = b2Body_GetRotationalInertia( m_bodyId ); + float invI = inertiaTensor < 0.0001f ? 0.0f : 1.0f / inertiaTensor; + + b2Vec2 vB = b2Body_GetLinearVelocity( m_bodyId ); + float omegaB = b2Body_GetAngularVelocity( m_bodyId ); + b2Vec2 pB = b2Body_GetWorldCenterOfMass( m_bodyId ); + + for ( int i = 0; i < 2; ++i ) + { + b2Vec2 anchorA = { 3.0f, 0.0f }; + b2Vec2 anchorB = b2Body_GetWorldPoint( m_bodyId, localAnchors[i] ); + + b2Vec2 deltaAnchor = b2Sub( anchorB, anchorA ); + + float slackLength = 1.0f; + float length = b2Length( deltaAnchor ); + float C = length - slackLength; + if ( C < 0.0f || length < 0.001f ) + { + g_draw.DrawSegment( anchorA, anchorB, b2_colorLightCyan ); + m_impulses[i] = 0.0f; + continue; + } + + g_draw.DrawSegment( anchorA, anchorB, b2_colorViolet ); + b2Vec2 axis = b2Normalize( deltaAnchor ); + + b2Vec2 rB = b2Sub( anchorB, pB ); + float Jb = b2Cross( rB, axis ); + float K = invMass + Jb * invI * Jb; + float invK = K < 0.0001f ? 0.0f : 1.0f / K; + + float Cdot = b2Dot( vB, axis ) + Jb * omegaB; + float impulse = -massCoefficient * invK * ( Cdot + biasCoefficient * C ); + float appliedImpulse = b2ClampFloat( impulse, -maxForce * timeStep, 0.0f ); + + vB = b2MulAdd( vB, invMass * appliedImpulse, axis ); + omegaB += appliedImpulse * invI * Jb; + + m_impulses[i] = appliedImpulse; + } + + b2Body_SetLinearVelocity( m_bodyId, vB ); + b2Body_SetAngularVelocity( m_bodyId, omegaB ); + + g_draw.DrawString( 5, m_textLine, "forces = %g, %g", m_impulses[0] * invTimeStep, m_impulses[1] * invTimeStep ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new UserConstraint( settings ); + } + + b2BodyId m_bodyId; + float m_impulses[2]; +}; + +static int sampleUserConstraintIndex = RegisterSample( "Joints", "User Constraint", UserConstraint::Create ); + +// This is a fun demo that shows off the wheel joint +class Driving : public Sample +{ +public: + explicit Driving( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center.y = 5.0f; + g_camera.m_zoom = 25.0f * 0.4f; + settings.drawJoints = false; + } + + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Vec2 points[25]; + int count = 24; + + // fill in reverse to match line list convention + points[count--] = { -20.0f, -20.0f }; + points[count--] = { -20.0f, 0.0f }; + points[count--] = { 20.0f, 0.0f }; + + float hs[10] = { 0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f }; + float x = 20.0f, dx = 5.0f; + + for ( int j = 0; j < 2; ++j ) + { + for ( int i = 0; i < 10; ++i ) + { + float y2 = hs[i]; + points[count--] = { x + dx, y2 }; + x += dx; + } + } + + // flat before bridge + points[count--] = { x + 40.0f, 0.0f }; + points[count--] = { x + 40.0f, -20.0f }; + + assert( count == -1 ); + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = 25; + chainDef.isLoop = true; + b2CreateChain( groundId, &chainDef ); + + // flat after bridge + x += 80.0f; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { x, 0.0f }, { x + 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + // jump ramp + x += 40.0f; + segment = { { x, 0.0f }, { x + 10.0f, 5.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + // final corner + x += 20.0f; + segment = { { x, 0.0f }, { x + 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + x += 40.0f; + segment = { { x, 0.0f }, { x, 20.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Teeter + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 140.0f, 1.0f }; + bodyDef.angularVelocity = 1.0f; + bodyDef.type = b2_dynamicBody; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox( 10.0f, 0.25f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + b2Vec2 pivot = bodyDef.position; + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.lowerAngle = -8.0f * B2_PI / 180.0f; + jointDef.upperAngle = 8.0f * B2_PI / 180.0f; + jointDef.enableLimit = true; + b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + // Bridge + { + int N = 20; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Capsule capsule = { { -1.0f, 0.0f }, { 1.0f, 0.0f }, 0.125f }; + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + + b2BodyId prevBodyId = groundId; + for ( int i = 0; i < N; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 161.0f + 2.0f * i, -0.125f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = { 160.0f + 2.0f * i, -0.125f }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + b2CreateRevoluteJoint( m_worldId, &jointDef ); + + prevBodyId = bodyId; + } + + b2Vec2 pivot = { 160.0f + 2.0f * N, -0.125f }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = groundId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + jointDef.enableMotor = true; + jointDef.maxMotorTorque = 50.0f; + b2CreateRevoluteJoint( m_worldId, &jointDef ); + } + + // Boxes + { + b2Polygon box = b2MakeBox( 0.5f, 0.5f ); + + b2BodyId bodyId; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.25f; + shapeDef.material.restitution = 0.25f; + shapeDef.density = 0.25f; + + bodyDef.position = { 230.0f, 0.5f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + bodyDef.position = { 230.0f, 1.5f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + bodyDef.position = { 230.0f, 2.5f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + bodyDef.position = { 230.0f, 3.5f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + bodyDef.position = { 230.0f, 4.5f }; + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Car + + m_throttle = 0.0f; + m_speed = 35.0f; + m_torque = 5.0f; + m_hertz = 5.0f; + m_dampingRatio = 0.7f; + + m_car.Spawn( m_worldId, { 0.0f, 0.0f }, 1.0f, m_hertz, m_dampingRatio, m_torque, nullptr ); + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Driving", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 100.0f ); + if ( ImGui::SliderFloat( "Spring Hertz", &m_hertz, 0.0f, 20.0f, "%.0f" ) ) + { + m_car.SetHertz( m_hertz ); + } + + if ( ImGui::SliderFloat( "Damping Ratio", &m_dampingRatio, 0.0f, 10.0f, "%.1f" ) ) + { + m_car.SetDampingRadio( m_dampingRatio ); + } + + if ( ImGui::SliderFloat( "Speed", &m_speed, 0.0f, 50.0f, "%.0f" ) ) + { + m_car.SetSpeed( m_throttle * m_speed ); + } + + if ( ImGui::SliderFloat( "Torque", &m_torque, 0.0f, 10.0f, "%.1f" ) ) + { + m_car.SetTorque( m_torque ); + } + ImGui::PopItemWidth(); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) == GLFW_PRESS ) + { + m_throttle = 1.0f; + m_car.SetSpeed( m_speed ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_S ) == GLFW_PRESS ) + { + m_throttle = 0.0f; + m_car.SetSpeed( 0.0f ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) == GLFW_PRESS ) + { + m_throttle = -1.0f; + m_car.SetSpeed( -m_speed ); + } + + g_draw.DrawString( 5, m_textLine, "Keys: left = a, brake = s, right = d" ); + m_textLine += m_textIncrement; + + b2Vec2 linearVelocity = b2Body_GetLinearVelocity( m_car.m_chassisId ); + float kph = linearVelocity.x * 3.6f; + g_draw.DrawString( 5, m_textLine, "speed in kph: %.2g", kph ); + m_textLine += m_textIncrement; + + b2Vec2 carPosition = b2Body_GetPosition( m_car.m_chassisId ); + g_camera.m_center.x = carPosition.x; + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new Driving( settings ); + } + + Car m_car; + + float m_throttle; + float m_hertz; + float m_dampingRatio; + float m_torque; + float m_speed; +}; + +static int sampleDriving = RegisterSample( "Joints", "Driving", Driving::Create ); + +class Ragdoll : public Sample +{ +public: + explicit Ragdoll( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 12.0f }; + g_camera.m_zoom = 16.0f; + + // g_camera.m_center = { 0.0f, 26.0f }; + // g_camera.m_zoom = 1.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + m_jointFrictionTorque = 0.03f; + m_jointHertz = 5.0f; + m_jointDampingRatio = 0.5f; + + m_human = {}; + + Spawn(); + } + + void Spawn() + { + CreateHuman( &m_human, m_worldId, { 0.0f, 25.0f }, 1.0f, m_jointFrictionTorque, m_jointHertz, m_jointDampingRatio, 1, + nullptr, false ); + Human_ApplyRandomAngularImpulse( &m_human, 10.0f ); + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Ragdoll", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + if ( ImGui::SliderFloat( "Friction", &m_jointFrictionTorque, 0.0f, 1.0f, "%3.2f" ) ) + { + Human_SetJointFrictionTorque( &m_human, m_jointFrictionTorque ); + } + + if ( ImGui::SliderFloat( "Hertz", &m_jointHertz, 0.0f, 10.0f, "%3.1f" ) ) + { + Human_SetJointSpringHertz( &m_human, m_jointHertz ); + } + + if ( ImGui::SliderFloat( "Damping", &m_jointDampingRatio, 0.0f, 4.0f, "%3.1f" ) ) + { + Human_SetJointDampingRatio( &m_human, m_jointDampingRatio ); + } + + if ( ImGui::Button( "Respawn" ) ) + { + DestroyHuman( &m_human ); + Spawn(); + } + ImGui::PopItemWidth(); + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new Ragdoll( settings ); + } + + Human m_human; + float m_jointFrictionTorque; + float m_jointHertz; + float m_jointDampingRatio; +}; + +static int sampleRagdoll = RegisterSample( "Joints", "Ragdoll", Ragdoll::Create ); + +class SoftBody : public Sample +{ +public: + explicit SoftBody( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 25.0f * 0.25f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + m_donut.Create( m_worldId, { 0.0f, 10.0f }, 2.0f, 0, false, nullptr ); + } + + static Sample* Create( Settings& settings ) + { + return new SoftBody( settings ); + } + + Donut m_donut; +}; + +static int sampleDonut = RegisterSample( "Joints", "Soft Body", SoftBody::Create ); + +class DoohickeyFarm : public Sample +{ +public: + explicit DoohickeyFarm( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 25.0f * 0.35f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + b2Polygon box = b2MakeOffsetBox( 1.0f, 1.0f, { 0.0f, 1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + float y = 4.0f; + for ( int i = 0; i < 4; ++i ) + { + Doohickey doohickey; + doohickey.Spawn( m_worldId, { 0.0f, y }, 0.5f ); + y += 2.0f; + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new DoohickeyFarm( settings ); + } +}; + +static int sampleDoohickey = RegisterSample( "Joints", "Doohickey", DoohickeyFarm::Create ); + +class ScissorLift : public Sample +{ +public: + explicit ScissorLift( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 9.0f }; + g_camera.m_zoom = 25.0f * 0.4f; + } + + // Need 8 sub-steps for smoother operation + settings.subStepCount = 8; + + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.sleepThreshold = 0.01f; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Capsule capsule = { { -2.5f, 0.0f }, { 2.5f, 0.0f }, 0.15f }; + + b2BodyId baseId1 = groundId; + b2BodyId baseId2 = groundId; + b2Vec2 baseAnchor1 = { -2.5f, 0.2f }; + b2Vec2 baseAnchor2 = { 2.5f, 0.2f }; + float y = 0.5f; + + b2BodyId linkId1; + int N = 3; + + for ( int i = 0; i < N; ++i ) + { + bodyDef.position = { 0.0f, y }; + bodyDef.rotation = b2MakeRot( 0.15f ); + b2BodyId bodyId1 = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId1, &shapeDef, &capsule ); + + bodyDef.position = { 0.0f, y }; + bodyDef.rotation = b2MakeRot( -0.15f ); + + b2BodyId bodyId2 = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId2, &shapeDef, &capsule ); + + if ( i == 1 ) + { + linkId1 = bodyId2; + } + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + + // left pin + revoluteDef.bodyIdA = baseId1; + revoluteDef.bodyIdB = bodyId1; + revoluteDef.localAnchorA = baseAnchor1; + revoluteDef.localAnchorB = { -2.5f, 0.0f }; + revoluteDef.enableMotor = false; + revoluteDef.maxMotorTorque = 1.0f; + revoluteDef.collideConnected = ( i == 0 ) ? true : false; + + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + // right pin + if ( i == 0 ) + { + b2WheelJointDef wheelDef = b2DefaultWheelJointDef(); + wheelDef.bodyIdA = baseId2; + wheelDef.bodyIdB = bodyId2; + wheelDef.localAxisA = { 1.0f, 0.0f }; + wheelDef.localAnchorA = baseAnchor2; + wheelDef.localAnchorB = { 2.5f, 0.0f }; + wheelDef.enableSpring = false; + wheelDef.collideConnected = true; + + b2CreateWheelJoint( m_worldId, &wheelDef ); + } + else + { + revoluteDef.bodyIdA = baseId2; + revoluteDef.bodyIdB = bodyId2; + revoluteDef.localAnchorA = baseAnchor2; + revoluteDef.localAnchorB = { 2.5f, 0.0f }; + revoluteDef.enableMotor = false; + revoluteDef.maxMotorTorque = 1.0f; + revoluteDef.collideConnected = false; + + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + } + + // middle pin + revoluteDef.bodyIdA = bodyId1; + revoluteDef.bodyIdB = bodyId2; + revoluteDef.localAnchorA = { 0.0f, 0.0f }; + revoluteDef.localAnchorB = { 0.0f, 0.0f }; + revoluteDef.enableMotor = false; + revoluteDef.maxMotorTorque = 1.0f; + revoluteDef.collideConnected = false; + + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + baseId1 = bodyId2; + baseId2 = bodyId1; + baseAnchor1 = { -2.5f, 0.0f }; + baseAnchor2 = { 2.5f, 0.0f }; + y += 1.0f; + } + + bodyDef.position = { 0.0f, y }; + bodyDef.rotation = b2Rot_identity; + b2BodyId platformId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 3.0f, 0.2f ); + b2CreatePolygonShape( platformId, &shapeDef, &box ); + + // left pin + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + revoluteDef.bodyIdA = platformId; + revoluteDef.bodyIdB = baseId1; + revoluteDef.localAnchorA = { -2.5f, -0.4f }; + revoluteDef.localAnchorB = baseAnchor1; + revoluteDef.enableMotor = false; + revoluteDef.maxMotorTorque = 1.0f; + revoluteDef.collideConnected = true; + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + + // right pin + b2WheelJointDef wheelDef = b2DefaultWheelJointDef(); + wheelDef.bodyIdA = platformId; + wheelDef.bodyIdB = baseId2; + wheelDef.localAxisA = { 1.0f, 0.0f }; + wheelDef.localAnchorA = { 2.5f, -0.4f }; + wheelDef.localAnchorB = baseAnchor2; + wheelDef.enableSpring = false; + wheelDef.collideConnected = true; + b2CreateWheelJoint( m_worldId, &wheelDef ); + + m_enableMotor = false; + m_motorSpeed = 0.25f; + m_motorForce = 2000.0f; + + b2DistanceJointDef distanceDef = b2DefaultDistanceJointDef(); + distanceDef.bodyIdA = groundId; + distanceDef.bodyIdB = linkId1; + distanceDef.localAnchorA = { -2.5f, 0.2f }; + distanceDef.localAnchorB = { 0.5f, 0.0f }; + distanceDef.enableSpring = true; + distanceDef.minLength = 0.2f; + distanceDef.maxLength = 5.5f; + distanceDef.enableLimit = true; + distanceDef.enableMotor = m_enableMotor; + distanceDef.motorSpeed = m_motorSpeed; + distanceDef.maxMotorForce = m_motorForce; + m_liftJointId = b2CreateDistanceJoint( m_worldId, &distanceDef ); + + Car car; + car.Spawn( m_worldId, { 0.0f, y + 2.0f }, 1.0f, 3.0f, 0.7f, 0.0f, nullptr ); + } + + void UpdateGui() override + { + float height = 140.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Scissor Lift", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Motor", &m_enableMotor ) ) + { + b2DistanceJoint_EnableMotor( m_liftJointId, m_enableMotor ); + b2Joint_WakeBodies( m_liftJointId ); + } + + if ( ImGui::SliderFloat( "Max Force", &m_motorForce, 0.0f, 3000.0f, "%.0f" ) ) + { + b2DistanceJoint_SetMaxMotorForce( m_liftJointId, m_motorForce ); + b2Joint_WakeBodies( m_liftJointId ); + } + + if ( ImGui::SliderFloat( "Speed", &m_motorSpeed, -0.3f, 0.3f, "%.2f" ) ) + { + b2DistanceJoint_SetMotorSpeed( m_liftJointId, m_motorSpeed ); + b2Joint_WakeBodies( m_liftJointId ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new ScissorLift( settings ); + } + + b2JointId m_liftJointId; + float m_motorForce; + float m_motorSpeed; + bool m_enableMotor; +}; + +static int sampleScissorLift = RegisterSample( "Joints", "Scissor Lift", ScissorLift::Create ); + +class GearLift : public Sample +{ +public: + explicit GearLift( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 6.0f }; + g_camera.m_zoom = 7.0f; + } + + b2BodyId groundId; + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + groundId = b2CreateBody( m_worldId, &bodyDef ); + + const char* path = + "m 63.500002,201.08333 103.187498,0 1e-5,-37.04166 h -2.64584 l 0,34.39583 h -42.33333 v -2.64583 l " + "-2.64584,-1e-5 v -2.64583 h -2.64583 v -2.64584 h -2.64584 v -2.64583 H 111.125 v -2.64583 h -2.64583 v " + "-2.64583 h -2.64583 v -2.64584 l -2.64584,1e-5 v -2.64583 l -2.64583,-1e-5 V 174.625 h -2.645834 v -2.64584 l " + "-2.645833,1e-5 v -2.64584 H 92.60417 v -2.64583 h -2.645834 v -2.64583 l -26.458334,0 0,37.04166"; + + b2Vec2 points[128]; + + b2Vec2 offset = { -120.0f, -200.0f }; + float scale = 0.2f; + int count = ParsePath( path, offset, points, 64, scale, false ); + + b2SurfaceMaterial material = b2DefaultSurfaceMaterial(); + material.customColor = b2_colorDarkSeaGreen; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + chainDef.materials = &material; + chainDef.materialCount = 1; + + b2CreateChain( groundId, &chainDef ); + } + + float gearRadius = 1.0f; + float toothHalfWidth = 0.09f; + float toothHalfHeight = 0.06f; + float toothRadius = 0.03f; + float linkHalfLength = 0.07f; + float linkRadius = 0.05f; + float linkCount = 40; + float doorHalfHeight = 1.5f; + + b2Vec2 gearPosition1 = { -4.25f, 10.25f }; + b2Vec2 gearPosition2 = gearPosition1 + b2Vec2{ 2.0f, 1.0f }; + b2Vec2 linkAttachPosition = gearPosition2 + b2Vec2{ gearRadius + 2.0f * toothHalfWidth + toothRadius, 0.0f }; + b2Vec2 doorPosition = linkAttachPosition - b2Vec2{ 0.0f, 2.0f * linkCount * linkHalfLength + doorHalfHeight }; + + { + b2Vec2 position = gearPosition1; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = position; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + shapeDef.material.customColor = b2_colorSaddleBrown; + b2Circle circle = { b2Vec2_zero, gearRadius }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + int count = 16; + float deltaAngle = 2.0f * B2_PI / 16; + b2Rot dq = b2MakeRot( deltaAngle ); + b2Vec2 center = { gearRadius + toothHalfHeight, 0.0f }; + b2Rot rotation = b2Rot_identity; + + for ( int i = 0; i < count; ++i ) + { + b2Polygon tooth = b2MakeOffsetRoundedBox( toothHalfWidth, toothHalfHeight, center, rotation, toothRadius ); + shapeDef.material.customColor = b2_colorGray; + b2CreatePolygonShape( bodyId, &shapeDef, &tooth ); + + rotation = b2MulRot( dq, rotation ); + center = b2RotateVector( rotation, { gearRadius + toothHalfHeight, 0.0f } ); + } + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + + m_motorTorque = 80.0f; + m_motorSpeed = 0.0f; + m_enableMotor = true; + + revoluteDef.bodyIdA = groundId; + revoluteDef.bodyIdB = bodyId; + revoluteDef.localAnchorA = b2Body_GetLocalPoint( groundId, position ); + revoluteDef.localAnchorB = b2Vec2_zero; + revoluteDef.enableMotor = m_enableMotor; + revoluteDef.maxMotorTorque = m_motorTorque; + revoluteDef.motorSpeed = m_motorSpeed; + m_driverId = b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + } + + b2BodyId followerId; + + { + b2Vec2 position = gearPosition2; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = position; + + followerId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + shapeDef.material.customColor = b2_colorSaddleBrown; + b2Circle circle = { b2Vec2_zero, gearRadius }; + b2CreateCircleShape( followerId, &shapeDef, &circle ); + + int count = 16; + float deltaAngle = 2.0f * B2_PI / 16; + b2Rot dq = b2MakeRot( deltaAngle ); + b2Vec2 center = { gearRadius + toothHalfWidth, 0.0f }; + b2Rot rotation = b2Rot_identity; + + for ( int i = 0; i < count; ++i ) + { + b2Polygon tooth = b2MakeOffsetRoundedBox( toothHalfWidth, toothHalfHeight, center, rotation, toothRadius ); + shapeDef.material.customColor = b2_colorGray; + b2CreatePolygonShape( followerId, &shapeDef, &tooth ); + + rotation = b2MulRot( dq, rotation ); + center = b2RotateVector( rotation, { gearRadius + toothHalfWidth, 0.0f } ); + } + + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + + revoluteDef.bodyIdA = groundId; + revoluteDef.bodyIdB = followerId; + revoluteDef.localAnchorA = b2Body_GetLocalPoint( groundId, position ); + revoluteDef.localAnchorB = b2Vec2_zero; + revoluteDef.enableMotor = true; + revoluteDef.maxMotorTorque = 0.5f; + revoluteDef.referenceAngle = 0.25f * B2_PI; + revoluteDef.lowerAngle = -0.3f * B2_PI; + revoluteDef.upperAngle = 0.8f * B2_PI; + revoluteDef.enableLimit = true; + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + } + + b2BodyId lastLinkId; + { + b2Capsule capsule = { { 0.0f, -linkHalfLength }, { 0.0f, linkHalfLength }, linkRadius }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 2.0f; + shapeDef.material.customColor = b2_colorLightSteelBlue; + + b2RevoluteJointDef jointDef = b2DefaultRevoluteJointDef(); + jointDef.maxMotorTorque = 0.05f; + jointDef.enableMotor = true; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2Vec2 position = linkAttachPosition + b2Vec2{ 0.0f, -linkHalfLength }; + + int count = 40; + b2BodyId prevBodyId = followerId; + for ( int i = 0; i < count; ++i ) + { + bodyDef.position = position; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + b2Vec2 pivot = { position.x, position.y + linkHalfLength }; + jointDef.bodyIdA = prevBodyId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( jointDef.bodyIdA, pivot ); + jointDef.localAnchorB = b2Body_GetLocalPoint( jointDef.bodyIdB, pivot ); + b2CreateRevoluteJoint( m_worldId, &jointDef ); + + position.y -= 2.0f * linkHalfLength; + prevBodyId = bodyId; + } + + lastLinkId = prevBodyId; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = doorPosition; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 0.15f, doorHalfHeight ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.1f; + shapeDef.material.customColor = b2_colorDarkCyan; + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + { + b2Vec2 pivot = doorPosition + b2Vec2{ 0.0f, doorHalfHeight }; + b2RevoluteJointDef revoluteDef = b2DefaultRevoluteJointDef(); + revoluteDef.bodyIdA = lastLinkId; + revoluteDef.bodyIdB = bodyId; + revoluteDef.localAnchorA = b2Body_GetLocalPoint( lastLinkId, pivot ); + revoluteDef.localAnchorB = { 0.0f, doorHalfHeight }; + revoluteDef.enableMotor = true; + revoluteDef.maxMotorTorque = 0.05f; + b2CreateRevoluteJoint( m_worldId, &revoluteDef ); + } + + { + b2PrismaticJointDef jointDef = b2DefaultPrismaticJointDef(); + jointDef.bodyIdA = groundId; + jointDef.bodyIdB = bodyId; + jointDef.localAnchorA = b2Body_GetLocalPoint( groundId, doorPosition ); + jointDef.localAnchorB = b2Vec2_zero; + jointDef.localAxisA = { 0.0f, 1.0f }; + jointDef.maxMotorForce = 0.2f; + jointDef.enableMotor = true; + jointDef.collideConnected = true; + b2CreatePrismaticJoint( m_worldId, &jointDef ); + } + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.rollingResistance = 0.3f; + + b2HexColor colors[5] = { + b2_colorGray, b2_colorGainsboro, b2_colorLightGray, b2_colorLightSlateGray, b2_colorDarkGray, + }; + + float y = 4.25f; + int xCount = 10, yCount = 20; + for ( int i = 0; i < yCount; ++i ) + { + float x = -3.15f; + for ( int j = 0; j < xCount; ++j ) + { + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Polygon poly = RandomPolygon( 0.1f ); + poly.radius = RandomFloatRange( 0.01f, 0.02f ); + + int colorIndex = RandomIntRange( 0, 4 ); + shapeDef.material.customColor = colors[colorIndex]; + + b2CreatePolygonShape( bodyId, &shapeDef, &poly ); + x += 0.2f; + } + + y += 0.2f; + } + } + } + + void UpdateGui() override + { + float height = 120.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 25.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Gear Lift", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Checkbox( "Motor", &m_enableMotor ) ) + { + b2RevoluteJoint_EnableMotor( m_driverId, m_enableMotor ); + b2Joint_WakeBodies( m_driverId ); + } + + if ( ImGui::SliderFloat( "Max Torque", &m_motorTorque, 0.0f, 100.0f, "%.0f" ) ) + { + b2RevoluteJoint_SetMaxMotorTorque( m_driverId, m_motorTorque ); + b2Joint_WakeBodies( m_driverId ); + } + + if ( ImGui::SliderFloat( "Speed", &m_motorSpeed, -0.3f, 0.3f, "%.2f" ) ) + { + b2RevoluteJoint_SetMotorSpeed( m_driverId, m_motorSpeed ); + b2Joint_WakeBodies( m_driverId ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) ) + { + m_motorSpeed = b2MaxFloat(-0.3f, m_motorSpeed - 0.01f); + b2RevoluteJoint_SetMotorSpeed( m_driverId, m_motorSpeed ); + b2Joint_WakeBodies( m_driverId ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) ) + { + m_motorSpeed = b2MinFloat( 0.3f, m_motorSpeed + 0.01f ); + b2RevoluteJoint_SetMotorSpeed( m_driverId, m_motorSpeed ); + b2Joint_WakeBodies( m_driverId ); + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new GearLift( settings ); + } + + b2JointId m_driverId; + float m_motorTorque; + float m_motorSpeed; + bool m_enableMotor; +}; + +static int sampleGearLift = RegisterSample( "Joints", "Gear Lift", GearLift::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_robustness.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_robustness.cpp new file mode 100644 index 000000000000..491d6f680991 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_robustness.cpp @@ -0,0 +1,382 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" + +#include +#include +#include + +// Pyramid with heavy box on top +class HighMassRatio1 : public Sample +{ +public: + explicit HighMassRatio1( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 3.0f, 14.0f }; + g_camera.m_zoom = 25.0f; + } + + float extent = 1.0f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 50.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2Polygon box = b2MakeBox( extent, extent ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + for ( int j = 0; j < 3; ++j ) + { + int count = 10; + float offset = -20.0f * extent + 2.0f * ( count + 1.0f ) * extent * j; + float y = extent; + while ( count > 0 ) + { + for ( int i = 0; i < count; ++i ) + { + float coeff = i - 0.5f * count; + + float yy = count == 1 ? y + 2.0f : y; + bodyDef.position = { 2.0f * coeff * extent + offset, yy }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + shapeDef.density = count == 1 ? ( j + 1.0f ) * 100.0f : 1.0f; + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + --count; + y += 2.0f * extent; + } + } + } + } + + static Sample* Create( Settings& settings ) + { + return new HighMassRatio1( settings ); + } +}; + +static int sampleIndex1 = RegisterSample( "Robustness", "HighMassRatio1", HighMassRatio1::Create ); + +// Big box on small boxes +class HighMassRatio2 : public Sample +{ +public: + explicit HighMassRatio2( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 16.5f }; + g_camera.m_zoom = 25.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 50.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float extent = 1.0f; + b2Polygon smallBox = b2MakeBox( 0.5f * extent, 0.5f * extent ); + b2Polygon bigBox = b2MakeBox( 10.0f * extent, 10.0f * extent ); + + { + bodyDef.position = { -9.0f * extent, 0.5f * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &smallBox ); + } + + { + bodyDef.position = { 9.0f * extent, 0.5f * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &smallBox ); + } + + { + bodyDef.position = { 0.0f, ( 10.0f + 16.0f ) * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &bigBox ); + } + } + } + + static Sample* Create( Settings& settings ) + { + return new HighMassRatio2( settings ); + } +}; + +static int sampleIndex2 = RegisterSample( "Robustness", "HighMassRatio2", HighMassRatio2::Create ); + +// Big box on small triangles +class HighMassRatio3 : public Sample +{ +public: + explicit HighMassRatio3( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 16.5f }; + g_camera.m_zoom = 25.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 50.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + float extent = 1.0f; + b2Vec2 points[3] = { { -0.5f * extent, 0.0f }, { 0.5f * extent, 0.0f }, { 0.0f, 1.0f * extent } }; + b2Hull hull = b2ComputeHull( points, 3 ); + b2Polygon smallTriangle = b2MakePolygon( &hull, 0.0f ); + b2Polygon bigBox = b2MakeBox( 10.0f * extent, 10.0f * extent ); + + { + bodyDef.position = { -9.0f * extent, 0.5f * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &smallTriangle ); + } + + { + bodyDef.position = { 9.0f * extent, 0.5f * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &smallTriangle ); + } + + { + bodyDef.position = { 0.0f, ( 10.0f + 4.0f ) * extent }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &bigBox ); + } + } + } + + static Sample* Create( Settings& settings ) + { + return new HighMassRatio3( settings ); + } +}; + +static int sampleIndex3 = RegisterSample( "Robustness", "HighMassRatio3", HighMassRatio3::Create ); + +class OverlapRecovery : public Sample +{ +public: + explicit OverlapRecovery( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 2.5f }; + g_camera.m_zoom = 25.0f * 0.15f; + } + + m_bodyIds = nullptr; + m_bodyCount = 0; + m_baseCount = 4; + m_overlap = 0.25f; + m_extent = 0.5f; + m_pushout = 3.0f; + m_hertz = 30.0f; + m_dampingRatio = 10.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + float groundWidth = 40.0f; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + + b2Segment segment = { { -groundWidth, 0.0f }, { groundWidth, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + CreateScene(); + } + + ~OverlapRecovery() override + { + free( m_bodyIds ); + } + + void CreateScene() + { + for ( int32_t i = 0; i < m_bodyCount; ++i ) + { + b2DestroyBody( m_bodyIds[i] ); + } + + b2World_SetContactTuning( m_worldId, m_hertz, m_dampingRatio, m_pushout ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2Polygon box = b2MakeBox( m_extent, m_extent ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + + m_bodyCount = m_baseCount * ( m_baseCount + 1 ) / 2; + m_bodyIds = (b2BodyId*)realloc( m_bodyIds, m_bodyCount * sizeof( b2BodyId ) ); + + int32_t bodyIndex = 0; + float fraction = 1.0f - m_overlap; + float y = m_extent; + for ( int32_t i = 0; i < m_baseCount; ++i ) + { + float x = fraction * m_extent * ( i - m_baseCount ); + for ( int32_t j = i; j < m_baseCount; ++j ) + { + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + m_bodyIds[bodyIndex++] = bodyId; + + x += 2.0f * fraction * m_extent; + } + + y += 2.0f * fraction * m_extent; + } + + assert( bodyIndex == m_bodyCount ); + } + + void UpdateGui() override + { + float height = 210.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 220.0f, height ) ); + + ImGui::Begin( "Overlap Recovery", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 100.0f ); + + bool changed = false; + changed = changed || ImGui::SliderFloat( "Extent", &m_extent, 0.1f, 1.0f, "%.1f" ); + changed = changed || ImGui::SliderInt( "Base Count", &m_baseCount, 1, 10 ); + changed = changed || ImGui::SliderFloat( "Overlap", &m_overlap, 0.0f, 1.0f, "%.2f" ); + changed = changed || ImGui::SliderFloat( "Pushout", &m_pushout, 0.0f, 10.0f, "%.1f" ); + changed = changed || ImGui::SliderFloat( "Hertz", &m_hertz, 0.0f, 120.0f, "%.f" ); + changed = changed || ImGui::SliderFloat( "Damping Ratio", &m_dampingRatio, 0.0f, 20.0f, "%.1f" ); + changed = changed || ImGui::Button( "Reset Scene" ); + + if ( changed ) + { + CreateScene(); + } + + ImGui::PopItemWidth(); + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new OverlapRecovery( settings ); + } + + b2BodyId* m_bodyIds; + int32_t m_bodyCount; + int32_t m_baseCount; + float m_overlap; + float m_extent; + float m_pushout; + float m_hertz; + float m_dampingRatio; +}; + +static int sampleIndex4 = RegisterSample( "Robustness", "Overlap Recovery", OverlapRecovery::Create ); + +class TinyPyramid : public Sample +{ +public: + explicit TinyPyramid( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.8f }; + g_camera.m_zoom = 1.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 5.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + m_extent = 0.025f; + int baseCount = 30; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Polygon box = b2MakeSquare( m_extent ); + + for ( int i = 0; i < baseCount; ++i ) + { + float y = ( 2.0f * i + 1.0f ) * m_extent; + + for ( int j = i; j < baseCount; ++j ) + { + float x = ( i + 1.0f ) * m_extent + 2.0f * ( j - i ) * m_extent - baseCount * m_extent; + bodyDef.position = { x, y }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + } + } + + void Step( Settings& settings ) override + { + DrawTextLine( "%.1fcm squares", 200.0f * m_extent ); + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new TinyPyramid( settings ); + } + + float m_extent; +}; + +static int sampleTinyPyramid = RegisterSample( "Robustness", "Tiny Pyramid", TinyPyramid::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_shapes.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_shapes.cpp new file mode 100644 index 000000000000..c5bac9766c9f --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_shapes.cpp @@ -0,0 +1,1841 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +// extern "C" int b2_toiCalls; +// extern "C" int b2_toiHitCount; + +class ChainShape : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_capsuleShape, + e_boxShape + }; + + explicit ChainShape( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 25.0f * 1.75f; + } + + m_groundId = b2_nullBodyId; + m_bodyId = b2_nullBodyId; + m_chainId = b2_nullChainId; + m_shapeId = b2_nullShapeId; + m_shapeType = e_circleShape; + m_restitution = 0.0f; + m_friction = 0.2f; + + CreateScene(); + Launch(); + } + + void CreateScene() + { + if ( B2_IS_NON_NULL( m_groundId ) ) + { + b2DestroyBody( m_groundId ); + } + + // https://betravis.github.io/shape-tools/path-to-polygon/ + // b2Vec2 points[] = {{-20.58325, 14.54175}, {-21.90625, 15.8645}, {-24.552, 17.1875}, + // {-27.198, 11.89575}, {-29.84375, 15.8645}, {-29.84375, 21.15625}, + // {-25.875, 23.802}, {-20.58325, 25.125}, {-25.875, 29.09375}, + // {-20.58325, 31.7395}, {-11.0089998, 23.2290001}, {-8.67700005, 21.15625}, + // {-6.03125, 21.15625}, {-7.35424995, 29.09375}, {-3.38549995, 29.09375}, + // {1.90625, 30.41675}, {5.875, 17.1875}, {11.16675, 25.125}, + // {9.84375, 29.09375}, {13.8125, 31.7395}, {21.75, 30.41675}, + // {28.3644981, 26.448}, {25.71875, 18.5105}, {24.3957481, 13.21875}, + // {17.78125, 11.89575}, {15.1355, 7.92700005}, {5.875, 9.25}, + // {1.90625, 11.89575}, {-3.25, 11.89575}, {-3.25, 9.9375}, + // {-4.70825005, 9.25}, {-8.67700005, 9.25}, {-11.323, 11.89575}, + // {-13.96875, 11.89575}, {-15.29175, 14.54175}, {-19.2605, 14.54175}}; + + b2Vec2 points[] = { + { -56.885498, 12.8985004 }, { -56.885498, 16.2057495 }, { 56.885498, 16.2057495 }, { 56.885498, -16.2057514 }, + { 51.5935059, -16.2057514 }, { 43.6559982, -10.9139996 }, { 35.7184982, -10.9139996 }, { 27.7809982, -10.9139996 }, + { 21.1664963, -14.2212505 }, { 11.9059982, -16.2057514 }, { 0, -16.2057514 }, { -10.5835037, -14.8827496 }, + { -17.1980019, -13.5597477 }, { -21.1665001, -12.2370014 }, { -25.1355019, -9.5909977 }, { -31.75, -3.63799858 }, + { -38.3644981, 6.2840004 }, { -42.3334999, 9.59125137 }, { -47.625, 11.5755005 }, { -56.885498, 12.8985004 }, + }; + + int count = sizeof( points ) / sizeof( points[0] ); + + // float scale = 0.25f; + // b2Vec2 lower = {FLT_MAX, FLT_MAX}; + // b2Vec2 upper = {-FLT_MAX, -FLT_MAX}; + // for (int i = 0; i < count; ++i) + //{ + // points[i].x = 2.0f * scale * points[i].x; + // points[i].y = -scale * points[i].y; + + // lower = b2Min(lower, points[i]); + // upper = b2Max(upper, points[i]); + //} + + // b2Vec2 center = b2MulSV(0.5f, b2Add(lower, upper)); + // for (int i = 0; i < count; ++i) + //{ + // points[i] = b2Sub(points[i], center); + // } + + // for (int i = 0; i < count / 2; ++i) + //{ + // b2Vec2 temp = points[i]; + // points[i] = points[count - 1 - i]; + // points[count - 1 - i] = temp; + // } + + // printf("{"); + // for (int i = 0; i < count; ++i) + //{ + // printf("{%.9g, %.9g},", points[i].x, points[i].y); + // } + // printf("};\n"); + + b2SurfaceMaterial material = {}; + material.friction = 0.2f; + material.customColor = b2_colorSteelBlue; + material.userMaterialId = 42; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.materials = &material; + chainDef.materialCount = 1; + chainDef.isLoop = true; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + + m_chainId = b2CreateChain( m_groundId, &chainDef ); + } + + void Launch() + { + if ( B2_IS_NON_NULL( m_bodyId ) ) + { + b2DestroyBody( m_bodyId ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -55.0f, 13.5f }; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = m_friction; + shapeDef.material.restitution = m_restitution; + + if ( m_shapeType == e_circleShape ) + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + m_shapeId = b2CreateCircleShape( m_bodyId, &shapeDef, &circle ); + } + else if ( m_shapeType == e_capsuleShape ) + { + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + m_shapeId = b2CreateCapsuleShape( m_bodyId, &shapeDef, &capsule ); + } + else + { + float h = 0.5f; + b2Polygon box = b2MakeBox( h, h ); + m_shapeId = b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + + // b2_toiCalls = 0; + // b2_toiHitCount = 0; + + m_stepCount = 0; + } + + void UpdateGui() override + { + float height = 155.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Chain Shape", nullptr, ImGuiWindowFlags_NoResize ); + + const char* shapeTypes[] = { "Circle", "Capsule", "Box" }; + int shapeType = int( m_shapeType ); + if ( ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ) ) + { + m_shapeType = ShapeType( shapeType ); + Launch(); + } + + if ( ImGui::SliderFloat( "Friction", &m_friction, 0.0f, 1.0f, "%.2f" ) ) + { + b2Shape_SetFriction( m_shapeId, m_friction ); + b2Chain_SetFriction( m_chainId, m_friction ); + } + + if ( ImGui::SliderFloat( "Restitution", &m_restitution, 0.0f, 2.0f, "%.1f" ) ) + { + b2Shape_SetRestitution( m_shapeId, m_restitution ); + } + + if ( ImGui::Button( "Launch" ) ) + { + Launch(); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawSegment( b2Vec2_zero, { 0.5f, 0.0f }, b2_colorRed ); + g_draw.DrawSegment( b2Vec2_zero, { 0.0f, 0.5f }, b2_colorGreen ); + + // DrawTextLine( "toi calls, hits = %d, %d", b2_toiCalls, b2_toiHitCount ); + } + + static Sample* Create( Settings& settings ) + { + return new ChainShape( settings ); + } + + b2BodyId m_groundId; + b2BodyId m_bodyId; + b2ChainId m_chainId; + ShapeType m_shapeType; + b2ShapeId m_shapeId; + float m_restitution; + float m_friction; +}; + +static int sampleChainShape = RegisterSample( "Shapes", "Chain Shape", ChainShape::Create ); + +// This sample shows how careful creation of compound shapes leads to better simulation and avoids +// objects getting stuck. +// This also shows how to get the combined AABB for the body. +class CompoundShapes : public Sample +{ +public: + explicit CompoundShapes( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 6.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { 50.0f, 0.0f }, { -50.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Table 1 + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -15.0f, 1.0f }; + m_table1Id = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon top = b2MakeOffsetBox( 3.0f, 0.5f, { 0.0f, 3.5f }, b2Rot_identity ); + b2Polygon leftLeg = b2MakeOffsetBox( 0.5f, 1.5f, { -2.5f, 1.5f }, b2Rot_identity ); + b2Polygon rightLeg = b2MakeOffsetBox( 0.5f, 1.5f, { 2.5f, 1.5f }, b2Rot_identity ); + + b2CreatePolygonShape( m_table1Id, &shapeDef, &top ); + b2CreatePolygonShape( m_table1Id, &shapeDef, &leftLeg ); + b2CreatePolygonShape( m_table1Id, &shapeDef, &rightLeg ); + } + + // Table 2 + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -5.0f, 1.0f }; + m_table2Id = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon top = b2MakeOffsetBox( 3.0f, 0.5f, { 0.0f, 3.5f }, b2Rot_identity ); + b2Polygon leftLeg = b2MakeOffsetBox( 0.5f, 2.0f, { -2.5f, 2.0f }, b2Rot_identity ); + b2Polygon rightLeg = b2MakeOffsetBox( 0.5f, 2.0f, { 2.5f, 2.0f }, b2Rot_identity ); + + b2CreatePolygonShape( m_table2Id, &shapeDef, &top ); + b2CreatePolygonShape( m_table2Id, &shapeDef, &leftLeg ); + b2CreatePolygonShape( m_table2Id, &shapeDef, &rightLeg ); + } + + // Spaceship 1 + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 5.0f, 1.0f }; + m_ship1Id = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Vec2 vertices[3]; + + vertices[0] = { -2.0f, 0.0f }; + vertices[1] = { 0.0f, 4.0f / 3.0f }; + vertices[2] = { 0.0f, 4.0f }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + b2Polygon left = b2MakePolygon( &hull, 0.0f ); + + vertices[0] = { 2.0f, 0.0f }; + vertices[1] = { 0.0f, 4.0f / 3.0f }; + vertices[2] = { 0.0f, 4.0f }; + hull = b2ComputeHull( vertices, 3 ); + b2Polygon right = b2MakePolygon( &hull, 0.0f ); + + b2CreatePolygonShape( m_ship1Id, &shapeDef, &left ); + b2CreatePolygonShape( m_ship1Id, &shapeDef, &right ); + } + + // Spaceship 2 + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 15.0f, 1.0f }; + m_ship2Id = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Vec2 vertices[3]; + + vertices[0] = { -2.0f, 0.0f }; + vertices[1] = { 1.0f, 2.0f }; + vertices[2] = { 0.0f, 4.0f }; + b2Hull hull = b2ComputeHull( vertices, 3 ); + b2Polygon left = b2MakePolygon( &hull, 0.0f ); + + vertices[0] = { 2.0f, 0.0f }; + vertices[1] = { -1.0f, 2.0f }; + vertices[2] = { 0.0f, 4.0f }; + hull = b2ComputeHull( vertices, 3 ); + b2Polygon right = b2MakePolygon( &hull, 0.0f ); + + b2CreatePolygonShape( m_ship2Id, &shapeDef, &left ); + b2CreatePolygonShape( m_ship2Id, &shapeDef, &right ); + } + + m_drawBodyAABBs = false; + } + + void Spawn() + { + // Table 1 obstruction + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Body_GetPosition( m_table1Id ); + bodyDef.rotation = b2Body_GetRotation( m_table1Id ); + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 4.0f, 0.1f, { 0.0f, 3.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Table 2 obstruction + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Body_GetPosition( m_table2Id ); + bodyDef.rotation = b2Body_GetRotation( m_table2Id ); + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 4.0f, 0.1f, { 0.0f, 3.0f }, b2Rot_identity ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Ship 1 obstruction + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Body_GetPosition( m_ship1Id ); + bodyDef.rotation = b2Body_GetRotation( m_ship1Id ); + // bodyDef.gravityScale = 0.0f; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 2.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + + // Ship 2 obstruction + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = b2Body_GetPosition( m_ship2Id ); + bodyDef.rotation = b2Body_GetRotation( m_ship2Id ); + // bodyDef.gravityScale = 0.0f; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 2.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 180.0f, height ) ); + + ImGui::Begin( "Compound Shapes", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Button( "Intrude" ) ) + { + Spawn(); + } + + ImGui::Checkbox( "Body AABBs", &m_drawBodyAABBs ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + if ( m_drawBodyAABBs ) + { + b2AABB aabb = b2Body_ComputeAABB( m_table1Id ); + g_draw.DrawAABB( aabb, b2_colorYellow ); + + aabb = b2Body_ComputeAABB( m_table2Id ); + g_draw.DrawAABB( aabb, b2_colorYellow ); + + aabb = b2Body_ComputeAABB( m_ship1Id ); + g_draw.DrawAABB( aabb, b2_colorYellow ); + + aabb = b2Body_ComputeAABB( m_ship2Id ); + g_draw.DrawAABB( aabb, b2_colorYellow ); + } + } + + static Sample* Create( Settings& settings ) + { + return new CompoundShapes( settings ); + } + + b2BodyId m_table1Id; + b2BodyId m_table2Id; + b2BodyId m_ship1Id; + b2BodyId m_ship2Id; + bool m_drawBodyAABBs; +}; + +static int sampleCompoundShape = RegisterSample( "Shapes", "Compound Shapes", CompoundShapes::Create ); + +class ShapeFilter : public Sample +{ +public: + enum CollisionBits + { + GROUND = 0x00000001, + TEAM1 = 0x00000002, + TEAM2 = 0x00000004, + TEAM3 = 0x00000008, + + ALL_BITS = ( ~0u ) + }; + + explicit ShapeFilter( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.5f; + g_camera.m_center = { 0.0f, 5.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.filter.categoryBits = GROUND; + shapeDef.filter.maskBits = ALL_BITS; + + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + bodyDef.position = { 0.0f, 2.0f }; + m_player1Id = b2CreateBody( m_worldId, &bodyDef ); + + bodyDef.position = { 0.0f, 5.0f }; + m_player2Id = b2CreateBody( m_worldId, &bodyDef ); + + bodyDef.position = { 0.0f, 8.0f }; + m_player3Id = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 2.0f, 1.0f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + shapeDef.filter.categoryBits = TEAM1; + shapeDef.filter.maskBits = GROUND | TEAM2 | TEAM3; + m_shape1Id = b2CreatePolygonShape( m_player1Id, &shapeDef, &box ); + + shapeDef.filter.categoryBits = TEAM2; + shapeDef.filter.maskBits = GROUND | TEAM1 | TEAM3; + m_shape2Id = b2CreatePolygonShape( m_player2Id, &shapeDef, &box ); + + shapeDef.filter.categoryBits = TEAM3; + shapeDef.filter.maskBits = GROUND | TEAM1 | TEAM2; + m_shape3Id = b2CreatePolygonShape( m_player3Id, &shapeDef, &box ); + } + } + + void UpdateGui() override + { + float height = 240.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Shape Filter", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::Text( "Player 1 Collides With" ); + { + b2Filter filter1 = b2Shape_GetFilter( m_shape1Id ); + bool team2 = ( filter1.maskBits & TEAM2 ) == TEAM2; + if ( ImGui::Checkbox( "Team 2##1", &team2 ) ) + { + if ( team2 ) + { + filter1.maskBits |= TEAM2; + } + else + { + filter1.maskBits &= ~TEAM2; + } + + b2Shape_SetFilter( m_shape1Id, filter1 ); + } + + bool team3 = ( filter1.maskBits & TEAM3 ) == TEAM3; + if ( ImGui::Checkbox( "Team 3##1", &team3 ) ) + { + if ( team3 ) + { + filter1.maskBits |= TEAM3; + } + else + { + filter1.maskBits &= ~TEAM3; + } + + b2Shape_SetFilter( m_shape1Id, filter1 ); + } + } + + ImGui::Separator(); + + ImGui::Text( "Player 2 Collides With" ); + { + b2Filter filter2 = b2Shape_GetFilter( m_shape2Id ); + bool team1 = ( filter2.maskBits & TEAM1 ) == TEAM1; + if ( ImGui::Checkbox( "Team 1##2", &team1 ) ) + { + if ( team1 ) + { + filter2.maskBits |= TEAM1; + } + else + { + filter2.maskBits &= ~TEAM1; + } + + b2Shape_SetFilter( m_shape2Id, filter2 ); + } + + bool team3 = ( filter2.maskBits & TEAM3 ) == TEAM3; + if ( ImGui::Checkbox( "Team 3##2", &team3 ) ) + { + if ( team3 ) + { + filter2.maskBits |= TEAM3; + } + else + { + filter2.maskBits &= ~TEAM3; + } + + b2Shape_SetFilter( m_shape2Id, filter2 ); + } + } + + ImGui::Separator(); + + ImGui::Text( "Player 3 Collides With" ); + { + b2Filter filter3 = b2Shape_GetFilter( m_shape3Id ); + bool team1 = ( filter3.maskBits & TEAM1 ) == TEAM1; + if ( ImGui::Checkbox( "Team 1##3", &team1 ) ) + { + if ( team1 ) + { + filter3.maskBits |= TEAM1; + } + else + { + filter3.maskBits &= ~TEAM1; + } + + b2Shape_SetFilter( m_shape3Id, filter3 ); + } + + bool team2 = ( filter3.maskBits & TEAM2 ) == TEAM2; + if ( ImGui::Checkbox( "Team 2##3", &team2 ) ) + { + if ( team2 ) + { + filter3.maskBits |= TEAM2; + } + else + { + filter3.maskBits &= ~TEAM2; + } + + b2Shape_SetFilter( m_shape3Id, filter3 ); + } + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2Vec2 p1 = b2Body_GetPosition( m_player1Id ); + g_draw.DrawString( { p1.x - 0.5f, p1.y }, "player 1" ); + + b2Vec2 p2 = b2Body_GetPosition( m_player2Id ); + g_draw.DrawString( { p2.x - 0.5f, p2.y }, "player 2" ); + + b2Vec2 p3 = b2Body_GetPosition( m_player3Id ); + g_draw.DrawString( { p3.x - 0.5f, p3.y }, "player 3" ); + } + + static Sample* Create( Settings& settings ) + { + return new ShapeFilter( settings ); + } + + b2BodyId m_player1Id; + b2BodyId m_player2Id; + b2BodyId m_player3Id; + + b2ShapeId m_shape1Id; + b2ShapeId m_shape2Id; + b2ShapeId m_shape3Id; +}; + +static int sampleShapeFilter = RegisterSample( "Shapes", "Filter", ShapeFilter::Create ); + +// This shows how to use custom filtering +class CustomFilter : public Sample +{ +public: + enum + { + e_count = 10 + }; + + explicit CustomFilter( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 10.0f; + } + + // Register custom filter + b2World_SetCustomFilterCallback( m_worldId, CustomFilterStatic, this ); + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeSquare( 1.0f ); + float x = -e_count; + + for ( int i = 0; i < e_count; ++i ) + { + bodyDef.position = { x, 5.0f }; + m_bodyIds[i] = b2CreateBody( m_worldId, &bodyDef ); + + shapeDef.userData = reinterpret_cast( intptr_t( i + 1 ) ); + m_shapeIds[i] = b2CreatePolygonShape( m_bodyIds[i], &shapeDef, &box ); + x += 2.0f; + } + } + + void Step( Settings& settings ) override + { + g_draw.DrawString( 5, m_textLine, "Custom filter disables collision between odd and even shapes" ); + m_textLine += m_textIncrement; + + Sample::Step( settings ); + + for ( int i = 0; i < e_count; ++i ) + { + b2Vec2 p = b2Body_GetPosition( m_bodyIds[i] ); + g_draw.DrawString( { p.x, p.y }, "%d", i ); + } + } + + bool ShouldCollide( b2ShapeId shapeIdA, b2ShapeId shapeIdB ) + { + void* userDataA = b2Shape_GetUserData( shapeIdA ); + void* userDataB = b2Shape_GetUserData( shapeIdB ); + + if ( userDataA == NULL || userDataB == NULL ) + { + return true; + } + + int indexA = static_cast( reinterpret_cast( userDataA ) ); + int indexB = static_cast( reinterpret_cast( userDataB ) ); + + return ( ( indexA & 1 ) + ( indexB & 1 ) ) != 1; + } + + static bool CustomFilterStatic( b2ShapeId shapeIdA, b2ShapeId shapeIdB, void* context ) + { + CustomFilter* customFilter = static_cast( context ); + return customFilter->ShouldCollide( shapeIdA, shapeIdB ); + } + + static Sample* Create( Settings& settings ) + { + return new CustomFilter( settings ); + } + + b2BodyId m_bodyIds[e_count]; + b2ShapeId m_shapeIds[e_count]; +}; + +static int sampleCustomFilter = RegisterSample( "Shapes", "Custom Filter", CustomFilter::Create ); + +// Restitution is approximate since Box2D uses speculative collision +class Restitution : public Sample +{ +public: + enum ShapeType + { + e_circleShape = 0, + e_boxShape + }; + + explicit Restitution( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 4.0f, 17.0f }; + g_camera.m_zoom = 27.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + float h = 1.0f * m_count; + b2Segment segment = { { -h, 0.0f }, { h, 0.0f } }; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + m_shapeType = e_circleShape; + + CreateBodies(); + } + + void CreateBodies() + { + for ( int i = 0; i < m_count; ++i ) + { + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + } + } + + b2Circle circle = {}; + circle.radius = 0.5f; + + b2Polygon box = b2MakeBox( 0.5f, 0.5f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.restitution = 0.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + float dr = 1.0f / ( m_count > 1 ? m_count - 1 : 1 ); + float x = -1.0f * ( m_count - 1 ); + float dx = 2.0f; + + for ( int i = 0; i < m_count; ++i ) + { + bodyDef.position = { x, 40.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + m_bodyIds[i] = bodyId; + + if ( m_shapeType == e_circleShape ) + { + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + else + { + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + shapeDef.material.restitution += dr; + x += dx; + } + } + + void UpdateGui() override + { + float height = 100.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Restitution", nullptr, ImGuiWindowFlags_NoResize ); + + bool changed = false; + const char* shapeTypes[] = { "Circle", "Box" }; + + int shapeType = int( m_shapeType ); + changed = changed || ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_shapeType = ShapeType( shapeType ); + + changed = changed || ImGui::Button( "Reset" ); + + if ( changed ) + { + CreateBodies(); + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new Restitution( settings ); + } + + static constexpr int m_count = 40; + + b2BodyId m_bodyIds[m_count] = {}; + ShapeType m_shapeType; +}; + +static int sampleIndex = RegisterSample( "Shapes", "Restitution", Restitution::Create ); + +class Friction : public Sample +{ +public: + explicit Friction( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 14.0f }; + g_camera.m_zoom = 25.0f * 0.6f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.2f; + + b2Segment segment = { { -40.0f, 0.0f }, { 40.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + b2Polygon box = b2MakeOffsetBox( 13.0f, 0.25f, { -4.0f, 22.0f }, b2MakeRot( -0.25f ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 0.25f, 1.0f, { 10.5f, 19.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 13.0f, 0.25f, { 4.0f, 14.0f }, b2MakeRot( 0.25f ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 0.25f, 1.0f, { -10.5f, 11.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 13.0f, 0.25f, { -4.0f, 6.0f }, b2MakeRot( -0.25f ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2Polygon box = b2MakeBox( 0.5f, 0.5f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 25.0f; + + float friction[5] = { 0.75f, 0.5f, 0.35f, 0.1f, 0.0f }; + + for ( int i = 0; i < 5; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -15.0f + 4.0f * i, 28.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + shapeDef.material.friction = friction[i]; + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + } + + static Sample* Create( Settings& settings ) + { + return new Friction( settings ); + } +}; + +static int sampleFriction = RegisterSample( "Shapes", "Friction", Friction::Create ); + +class RollingResistance : public Sample +{ +public: + explicit RollingResistance( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 5.0f, 20.0f }; + g_camera.m_zoom = 27.5f; + } + + m_lift = 0.0f; + m_resistScale = 0.02f; + CreateScene(); + } + + void CreateScene() + { + b2Circle circle = { b2Vec2_zero, 0.5f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + for ( int i = 0; i < 20; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Segment segment = { { -40.0f, 2.0f * i }, { 40.0f, 2.0f * i + m_lift } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -39.5f, 2.0f * i + 0.75f }; + bodyDef.angularVelocity = -10.0f; + bodyDef.linearVelocity = { 5.0f, 0.0f }; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + shapeDef.material.rollingResistance = m_resistScale * i; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + } + + void Keyboard( int key ) override + { + switch ( key ) + { + case GLFW_KEY_1: + m_lift = 0.0f; + CreateWorld(); + CreateScene(); + break; + + case GLFW_KEY_2: + m_lift = 5.0f; + CreateWorld(); + CreateScene(); + break; + + case GLFW_KEY_3: + m_lift = -5.0f; + CreateWorld(); + CreateScene(); + break; + + default: + Sample::Keyboard( key ); + break; + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + for ( int i = 0; i < 20; ++i ) + { + g_draw.DrawString( { -41.5f, 2.0f * i + 1.0f }, "%.2f", m_resistScale * i ); + } + } + + static Sample* Create( Settings& settings ) + { + return new RollingResistance( settings ); + } + + float m_resistScale; + float m_lift; +}; + +static int sampleRollingResistance = RegisterSample( "Shapes", "Rolling Resistance", RollingResistance::Create ); + +class ConveyorBelt : public Sample +{ +public: + explicit ConveyorBelt( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 2.0f, 7.5f }; + g_camera.m_zoom = 12.0f; + } + + // Ground + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Segment segment = { { -20.0f, 0.0f }, { 20.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + // Platform + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { -5.0f, 5.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeRoundedBox( 10.0f, 0.25f, 0.25f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.8f; + shapeDef.material.tangentSpeed = 2.0f; + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + // Boxes + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon cube = b2MakeSquare( 0.5f ); + for ( int i = 0; i < 5; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -10.0f + 2.0f * i, 7.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2CreatePolygonShape( bodyId, &shapeDef, &cube ); + } + } + + static Sample* Create( Settings& settings ) + { + return new ConveyorBelt( settings ); + } +}; + +static int sampleConveyorBelt = RegisterSample( "Shapes", "Conveyor Belt", ConveyorBelt::Create ); + +class TangentSpeed : public Sample +{ +public: + explicit TangentSpeed( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 60.0f, -15.0f }; + g_camera.m_zoom = 38.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + // const char* path = "M 613.8334,185.20833 H 500.06255 L 470.95838,182.5625 444.50004,174.625 418.04171,161.39583 " + // "394.2292,140.22917 h " + // "-13.22916 v 44.97916 H 68.791712 V 0 h -21.16671 v 206.375 l 566.208398,-1e-5 z"; + + const char* path = "m 613.8334,185.20833 -42.33338,0 h -37.04166 l -34.39581,0 -29.10417,-2.64583 -26.45834,-7.9375 " + "-26.45833,-13.22917 -23.81251,-21.16666 h -13.22916 v 44.97916 H 68.791712 V 0 h -21.16671 v " + "206.375 l 566.208398,-1e-5 z"; + + b2Vec2 offset = { -47.375002f, 0.25f }; + + float scale = 0.2f; + b2Vec2 points[20] = {}; + int count = ParsePath( path, offset, points, 20, scale, true ); + + b2SurfaceMaterial materials[20] = {}; + for ( int i = 0; i < 20; ++i ) + { + materials[i].friction = 0.6f; + } + + materials[0].tangentSpeed = -10.0; + materials[0].customColor = b2_colorDarkBlue; + materials[1].tangentSpeed = -20.0; + materials[1].customColor = b2_colorDarkCyan; + materials[2].tangentSpeed = -30.0; + materials[2].customColor = b2_colorDarkGoldenRod; + materials[3].tangentSpeed = -40.0; + materials[3].customColor = b2_colorDarkGray; + materials[4].tangentSpeed = -50.0; + materials[4].customColor = b2_colorDarkGreen; + materials[5].tangentSpeed = -60.0; + materials[5].customColor = b2_colorDarkKhaki; + materials[6].tangentSpeed = -70.0; + materials[6].customColor = b2_colorDarkMagenta; + + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points; + chainDef.count = count; + chainDef.isLoop = true; + chainDef.materials = materials; + chainDef.materialCount = count; + + b2CreateChain( groundId, &chainDef ); + + m_friction = 0.6f; + m_rollingResistance = 0.3f; + } + } + + b2BodyId DropBall() + { + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 110.0f, -30.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = m_friction; + shapeDef.material.rollingResistance = m_rollingResistance; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + return bodyId; + } + + void Reset() + { + int count = int( m_bodyIds.size() ); + for ( int i = 0; i < count; ++i ) + { + b2DestroyBody( m_bodyIds[i] ); + } + + m_bodyIds.clear(); + } + + void UpdateGui() override + { + float height = 80.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 260.0f, height ) ); + + ImGui::Begin( "Ball Parameters", nullptr, ImGuiWindowFlags_NoResize ); + ImGui::PushItemWidth( 140.0f ); + + if ( ImGui::SliderFloat( "Friction", &m_friction, 0.0f, 2.0f, "%.2f" ) ) + { + Reset(); + } + + if ( ImGui::SliderFloat( "Rolling Resistance", &m_rollingResistance, 0.0f, 1.0f, "%.2f" ) ) + { + Reset(); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( m_stepCount % 25 == 0 && m_bodyIds.size() < m_totalCount && settings.pause == false ) + { + b2BodyId id = DropBall(); + m_bodyIds.push_back( id ); + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new TangentSpeed( settings ); + } + + static constexpr int m_totalCount = 200; + std::vector m_bodyIds; + float m_friction; + float m_rollingResistance; +}; + +static int sampleTangentSpeed = RegisterSample( "Shapes", "Tangent Speed", TangentSpeed::Create ); + +// This sample shows how to modify the geometry on an existing shape. This is only supported on +// dynamic and kinematic shapes because static shapes don't look for new collisions. +class ModifyGeometry : public Sample +{ +public: + explicit ModifyGeometry( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.25f; + g_camera.m_center = { 0.0f, 5.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 10.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 4.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox( 1.0f, 1.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + + { + m_shapeType = b2_circleShape; + m_scale = 1.0f; + m_circle = { { 0.0f, 0.0f }, 0.5f }; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_kinematicBody; + bodyDef.position = { 0.0f, 1.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + m_shapeId = b2CreateCircleShape( bodyId, &shapeDef, &m_circle ); + } + } + + void UpdateShape() + { + switch ( m_shapeType ) + { + case b2_circleShape: + m_circle = { { 0.0f, 0.0f }, 0.5f * m_scale }; + b2Shape_SetCircle( m_shapeId, &m_circle ); + break; + + case b2_capsuleShape: + m_capsule = { { -0.5f * m_scale, 0.0f }, { 0.0f, 0.5f * m_scale }, 0.5f * m_scale }; + b2Shape_SetCapsule( m_shapeId, &m_capsule ); + break; + + case b2_segmentShape: + m_segment = { { -0.5f * m_scale, 0.0f }, { 0.75f * m_scale, 0.0f } }; + b2Shape_SetSegment( m_shapeId, &m_segment ); + break; + + case b2_polygonShape: + m_polygon = b2MakeBox( 0.5f * m_scale, 0.75f * m_scale ); + b2Shape_SetPolygon( m_shapeId, &m_polygon ); + break; + + default: + assert( false ); + break; + } + + b2BodyId bodyId = b2Shape_GetBody( m_shapeId ); + b2Body_ApplyMassFromShapes( bodyId ); + } + + void UpdateGui() override + { + float height = 230.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 200.0f, height ) ); + + ImGui::Begin( "Modify Geometry", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::RadioButton( "Circle", m_shapeType == b2_circleShape ) ) + { + m_shapeType = b2_circleShape; + UpdateShape(); + } + + if ( ImGui::RadioButton( "Capsule", m_shapeType == b2_capsuleShape ) ) + { + m_shapeType = b2_capsuleShape; + UpdateShape(); + } + + if ( ImGui::RadioButton( "Segment", m_shapeType == b2_segmentShape ) ) + { + m_shapeType = b2_segmentShape; + UpdateShape(); + } + + if ( ImGui::RadioButton( "Polygon", m_shapeType == b2_polygonShape ) ) + { + m_shapeType = b2_polygonShape; + UpdateShape(); + } + + if ( ImGui::SliderFloat( "Scale", &m_scale, 0.1f, 10.0f, "%.2f" ) ) + { + UpdateShape(); + } + + b2BodyId bodyId = b2Shape_GetBody( m_shapeId ); + b2BodyType bodyType = b2Body_GetType( bodyId ); + + if ( ImGui::RadioButton( "Static", bodyType == b2_staticBody ) ) + { + b2Body_SetType( bodyId, b2_staticBody ); + } + + if ( ImGui::RadioButton( "Kinematic", bodyType == b2_kinematicBody ) ) + { + b2Body_SetType( bodyId, b2_kinematicBody ); + } + + if ( ImGui::RadioButton( "Dynamic", bodyType == b2_dynamicBody ) ) + { + b2Body_SetType( bodyId, b2_dynamicBody ); + } + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new ModifyGeometry( settings ); + } + + b2ShapeId m_shapeId; + b2ShapeType m_shapeType; + float m_scale; + + union + { + b2Circle m_circle; + b2Capsule m_capsule; + b2Segment m_segment; + b2Polygon m_polygon; + }; +}; + +static int sampleModifyGeometry = RegisterSample( "Shapes", "Modify Geometry", ModifyGeometry::Create ); + +// Shows how to link to chain shapes together. This is a useful technique for building large game levels with smooth collision. +class ChainLink : public Sample +{ +public: + explicit ChainLink( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + b2Vec2 points1[] = { { 40.0f, 1.0f }, { 0.0f, 0.0f }, { -40.0f, 0.0f }, + { -40.0f, -1.0f }, { 0.0f, -1.0f }, { 40.0f, -1.0f } }; + b2Vec2 points2[] = { { -40.0f, -1.0f }, { 0.0f, -1.0f }, { 40.0f, -1.0f }, + { 40.0f, 0.0f }, { 0.0f, 0.0f }, { -40.0f, 0.0f } }; + + int count1 = std::size( points1 ); + int count2 = std::size( points2 ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + { + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points1; + chainDef.count = count1; + chainDef.isLoop = false; + b2CreateChain( groundId, &chainDef ); + } + + { + b2ChainDef chainDef = b2DefaultChainDef(); + chainDef.points = points2; + chainDef.count = count2; + chainDef.isLoop = false; + b2CreateChain( groundId, &chainDef ); + } + + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + { + bodyDef.position = { -5.0f, 2.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + + { + bodyDef.position = { 0.0f, 2.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Capsule capsule = { { -0.5f, 0.0f }, { 0.5f, 0.0 }, 0.25f }; + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + } + + { + bodyDef.position = { 5.0f, 2.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + float h = 0.5f; + b2Polygon box = b2MakeBox( h, h ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "This shows how to link together two chain shapes" ); + m_textLine += m_textIncrement; + } + + static Sample* Create( Settings& settings ) + { + return new ChainLink( settings ); + } +}; + +static int sampleChainLink = RegisterSample( "Shapes", "Chain Link", ChainLink::Create ); + +class RoundedShapes : public Sample +{ +public: + explicit RoundedShapes( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.55f; + g_camera.m_center = { 2.0f, 8.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 20.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 1.0f, 5.0f, { 19.0f, 5.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 1.0f, 5.0f, { -19.0f, 5.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + // b2Capsule capsule = {{-0.25f, 0.0f}, {0.25f, 0.0f}, 0.25f}; + // b2Circle circle = {{0.0f, 0.0f}, 0.35f}; + // b2Polygon square = b2MakeSquare(0.35f); + + // b2Vec2 points[3] = {{-0.1f, -0.5f}, {0.1f, -0.5f}, {0.0f, 0.5f}}; + // b2Hull wedgeHull = b2ComputeHull(points, 3); + // b2Polygon wedge = b2MakePolygon(&wedgeHull, 0.0f); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.rollingResistance = 0.3f; + + float y = 2.0f; + int xcount = 10, ycount = 10; + + for ( int i = 0; i < ycount; ++i ) + { + float x = -5.0f; + for ( int j = 0; j < xcount; ++j ) + { + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon poly = RandomPolygon( 0.5f ); + poly.radius = RandomFloatRange( 0.05f, 0.25f ); + b2CreatePolygonShape( bodyId, &shapeDef, &poly ); + + x += 1.0f; + } + + y += 1.0f; + } + } + + static Sample* Create( Settings& settings ) + { + return new RoundedShapes( settings ); + } +}; + +static int sampleRoundedShapes = RegisterSample( "Shapes", "Rounded", RoundedShapes::Create ); + +class EllipseShape : public Sample +{ +public: + explicit EllipseShape( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.55f; + g_camera.m_center = { 2.0f, 8.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 20.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 1.0f, 5.0f, { 19.0f, 5.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + box = b2MakeOffsetBox( 1.0f, 5.0f, { -19.0f, 5.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + b2Vec2 points[6] = { + { 0.0f, -0.25f }, { 0.0f, 0.25f }, { 0.05f, 0.075f }, { -0.05f, 0.075f }, { 0.05f, -0.075f }, { -0.05f, -0.075f }, + }; + b2Hull diamondHull = b2ComputeHull( points, 6 ); + b2Polygon poly = b2MakePolygon( &diamondHull, 0.2f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.rollingResistance = 0.2f; + + float y = 2.0f; + int xCount = 10, yCount = 10; + + for ( int i = 0; i < yCount; ++i ) + { + float x = -5.0f; + for ( int j = 0; j < xCount; ++j ) + { + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &poly ); + + x += 1.0f; + } + + y += 1.0f; + } + } + + static Sample* Create( Settings& settings ) + { + return new EllipseShape( settings ); + } +}; + +static int sampleEllipseShape = RegisterSample( "Shapes", "Ellipse", EllipseShape::Create ); + +class OffsetShapes : public Sample +{ +public: + explicit OffsetShapes( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.55f; + g_camera.m_center = { 2.0f, 8.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { -1.0f, 1.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 1.0f, 1.0f, { 10.0f, -2.0f }, b2MakeRot( 0.5f * B2_PI ) ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + { + b2Capsule capsule = { { -5.0f, 1.0f }, { -4.0f, 1.0f }, 0.25f }; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 13.5f, -0.75f }; + bodyDef.type = b2_dynamicBody; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + } + + { + b2Polygon box = b2MakeOffsetBox( 0.75f, 0.5f, { 9.0f, 2.0f }, b2MakeRot( 0.5f * B2_PI ) ); + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 0.0f }; + bodyDef.type = b2_dynamicBody; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + g_draw.DrawTransform( b2Transform_identity ); + } + + static Sample* Create( Settings& settings ) + { + return new OffsetShapes( settings ); + } +}; + +static int sampleOffsetShapes = RegisterSample( "Shapes", "Offset", OffsetShapes::Create ); + +// This shows how to use explosions and demonstrates the projected perimeter +class Explosion : public Sample +{ +public: + explicit Explosion( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 0.0f }; + g_camera.m_zoom = 14.0f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + bodyDef.type = b2_dynamicBody; + bodyDef.gravityScale = 0.0f; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + m_referenceAngle = 0.0f; + + b2WeldJointDef weldDef = b2DefaultWeldJointDef(); + weldDef.referenceAngle = m_referenceAngle; + weldDef.angularHertz = 0.5f; + weldDef.angularDampingRatio = 0.7f; + weldDef.linearHertz = 0.5f; + weldDef.linearDampingRatio = 0.7f; + weldDef.bodyIdA = groundId; + weldDef.localAnchorB = b2Vec2_zero; + + float r = 8.0f; + for ( float angle = 0.0f; angle < 360.0f; angle += 30.0f ) + { + b2CosSin cosSin = b2ComputeCosSin( angle * B2_PI / 180.0f ); + bodyDef.position = { r * cosSin.cosine, r * cosSin.sine }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 1.0f, 0.1f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + weldDef.localAnchorA = bodyDef.position; + weldDef.bodyIdB = bodyId; + b2JointId jointId = b2CreateWeldJoint( m_worldId, &weldDef ); + m_jointIds.push_back( jointId ); + } + + m_radius = 7.0f; + m_falloff = 3.0f; + m_impulse = 10.0f; + } + + void UpdateGui() override + { + float height = 160.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Explosion", nullptr, ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize ); + + if ( ImGui::Button( "Explode" ) ) + { + b2ExplosionDef def = b2DefaultExplosionDef(); + def.position = b2Vec2_zero; + def.radius = m_radius; + def.falloff = m_falloff; + def.impulsePerLength = m_impulse; + b2World_Explode( m_worldId, &def ); + } + + ImGui::SliderFloat( "radius", &m_radius, 0.0f, 20.0f, "%.1f" ); + ImGui::SliderFloat( "falloff", &m_falloff, 0.0f, 20.0f, "%.1f" ); + ImGui::SliderFloat( "impulse", &m_impulse, -20.0f, 20.0f, "%.1f" ); + + ImGui::End(); + } + + void Step( Settings& settings ) override + { + if ( settings.pause == false || settings.singleStep == true ) + { + m_referenceAngle += settings.hertz > 0.0f ? 60.0f * B2_PI / 180.0f / settings.hertz : 0.0f; + m_referenceAngle = b2UnwindAngle( m_referenceAngle ); + + int count = (int)m_jointIds.size(); + for ( int i = 0; i < count; ++i ) + { + b2WeldJoint_SetReferenceAngle( m_jointIds[i], m_referenceAngle ); + } + } + + Sample::Step( settings ); + + g_draw.DrawString( 5, m_textLine, "reference angle = %g", m_referenceAngle ); + m_textLine += m_textIncrement; + + g_draw.DrawCircle( b2Vec2_zero, m_radius + m_falloff, b2_colorBox2DBlue ); + g_draw.DrawCircle( b2Vec2_zero, m_radius, b2_colorBox2DYellow ); + } + + static Sample* Create( Settings& settings ) + { + return new Explosion( settings ); + } + + std::vector m_jointIds; + float m_radius; + float m_falloff; + float m_impulse; + float m_referenceAngle; +}; + +static int sampleExplosion = RegisterSample( "Shapes", "Explosion", Explosion::Create ); + +// This sample tests a static shape being recreated every step. +class RecreateStatic : public Sample +{ +public: + explicit RecreateStatic( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 2.5f }; + g_camera.m_zoom = 3.5f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { 0.0f, 1.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 1.0f, 1.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + + m_groundId = {}; + } + + void Step( Settings& settings ) override + { + if ( B2_IS_NON_NULL( m_groundId ) ) + { + b2DestroyBody( m_groundId ); + m_groundId = {}; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + m_groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Invoke contact creation so that contact points are created immediately + // on a static body. + shapeDef.invokeContactCreation = true; + + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( m_groundId, &shapeDef, &segment ); + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new RecreateStatic( settings ); + } + + b2BodyId m_groundId; +}; + +static int sampleSingleBox = RegisterSample( "Shapes", "Recreate Static", RecreateStatic::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_stacking.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_stacking.cpp new file mode 100644 index 000000000000..9f4dc2395773 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_stacking.cpp @@ -0,0 +1,1003 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "draw.h" +#include "random.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include +#include + +class SingleBox : public Sample +{ +public: + explicit SingleBox( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 2.5f }; + g_camera.m_zoom = 3.5f; + } + + float extent = 1.0f; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + float groundWidth = 66.0f * extent; + b2ShapeDef shapeDef = b2DefaultShapeDef(); + // shapeDef.friction = 0.5f; + + b2Segment segment = { { -0.5f * 2.0f * groundWidth, 0.0f }, { 0.5f * 2.0f * groundWidth, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + bodyDef.type = b2_dynamicBody; + + b2Polygon box = b2MakeBox( extent, extent ); + bodyDef.position = { 0.0f, 1.0f }; + bodyDef.linearVelocity = { 5.0f, 0.0f }; + m_bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyId, &shapeDef, &box ); + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + // g_draw.DrawCircle({0.0f, 2.0f}, 1.0f, b2_colorWhite); + + b2Vec2 position = b2Body_GetPosition( m_bodyId ); + DrawTextLine( "(x, y) = (%.2g, %.2g)", position.x, position.y ); + } + + static Sample* Create( Settings& settings ) + { + return new SingleBox( settings ); + } + + b2BodyId m_bodyId; +}; + +static int sampleSingleBox = RegisterSample( "Stacking", "Single Box", SingleBox::Create ); + +class TiltedStack : public Sample +{ +public: + explicit TiltedStack( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 7.5f, 7.5f }; + g_camera.m_zoom = 20.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -1.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 1000.0f, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + for ( int i = 0; i < m_rows * m_columns; ++i ) + { + m_bodies[i] = b2_nullBodyId; + } + + b2Polygon box = b2MakeRoundedBox( 0.45f, 0.45f, 0.05f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.3f; + + float offset = 0.2f; + float dx = 5.0f; + float xroot = -0.5f * dx * ( m_columns - 1.0f ); + + for ( int j = 0; j < m_columns; ++j ) + { + float x = xroot + j * dx; + + for ( int i = 0; i < m_rows; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + int n = j * m_rows + i; + + bodyDef.position = { x + offset * i, 0.5f + 1.0f * i }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + m_bodies[n] = bodyId; + + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + } + + static Sample* Create( Settings& settings ) + { + return new TiltedStack( settings ); + } + + static constexpr int m_columns = 10; + static constexpr int m_rows = 10; + + b2BodyId m_bodies[m_rows * m_columns]; +}; + +static int sampleTiltedStack = RegisterSample( "Stacking", "Tilted Stack", TiltedStack::Create ); + +// This sample shows some aspects of Box2D continuous collision: +// - bullet dynamic bodies which support continuous collision with non-bullet dynamic bodies +// - prevention of chain reaction tunneling +// Try disabling continuous collision and firing a bullet. You might see a bullet push a +// a through the static wall. +class VerticalStack : public Sample +{ +public: + enum + { + e_maxColumns = 10, + e_maxRows = 15, + e_maxBullets = 8 + }; + + enum ShapeType + { + e_circleShape = 0, + e_boxShape + }; + + explicit VerticalStack( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { -7.0f, 9.0f }; + g_camera.m_zoom = 14.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 0.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + b2Segment segment = { { 10.0f, 0.0f }, { 10.0f, 20.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + segment = { { -30.0f, 0.0f }, { 30.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + for ( int i = 0; i < e_maxRows * e_maxColumns; ++i ) + { + m_bodies[i] = b2_nullBodyId; + } + + for ( int i = 0; i < e_maxBullets; ++i ) + { + m_bullets[i] = b2_nullBodyId; + } + + m_shapeType = e_boxShape; + m_rowCount = 12; + m_columnCount = 1; + m_bulletCount = 1; + m_bulletType = e_circleShape; + + CreateStacks(); + } + + void CreateStacks() + { + for ( int i = 0; i < e_maxRows * e_maxColumns; ++i ) + { + if ( B2_IS_NON_NULL( m_bodies[i] ) ) + { + b2DestroyBody( m_bodies[i] ); + m_bodies[i] = b2_nullBodyId; + } + } + + b2Circle circle = {}; + circle.radius = 0.5f; + + b2Polygon box = b2MakeRoundedBox( 0.45f, 0.45f, 0.05f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 1.0f; + shapeDef.material.friction = 0.3f; + + float offset; + + if ( m_shapeType == e_circleShape ) + { + offset = 0.0f; + } + else + { + offset = 0.01f; + } + + float dx = -3.0f; + float xroot = 8.0f; + + for ( int j = 0; j < m_columnCount; ++j ) + { + float x = xroot + j * dx; + + for ( int i = 0; i < m_rowCount; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + int n = j * m_rowCount + i; + + float shift = ( i % 2 == 0 ? -offset : offset ); + bodyDef.position = { x + shift, 0.5f + 1.0f * i }; + // bodyDef.position = {x + shift, 1.0f + 1.51f * i}; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + m_bodies[n] = bodyId; + + if ( m_shapeType == e_circleShape ) + { + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + } + else + { + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + } + } + + void DestroyBody() + { + for ( int j = 0; j < m_columnCount; ++j ) + { + for ( int i = 0; i < m_rowCount; ++i ) + { + int n = j * m_rowCount + i; + + if ( B2_IS_NON_NULL( m_bodies[n] ) ) + { + b2DestroyBody( m_bodies[n] ); + m_bodies[n] = b2_nullBodyId; + break; + } + } + } + } + + void DestroyBullets() + { + for ( int i = 0; i < e_maxBullets; ++i ) + { + b2BodyId bullet = m_bullets[i]; + + if ( B2_IS_NON_NULL( bullet ) ) + { + b2DestroyBody( bullet ); + m_bullets[i] = b2_nullBodyId; + } + } + } + + void FireBullets() + { + b2Circle circle = { { 0.0f, 0.0f }, 0.25f }; + b2Polygon box = b2MakeBox( 0.25f, 0.25f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.density = 4.0f; + + for ( int i = 0; i < m_bulletCount; ++i ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { -26.7f - i, 6.0f }; + float speed = RandomFloatRange( 200.0f, 300.0f ); + bodyDef.linearVelocity = { speed, 0.0f }; + bodyDef.isBullet = true; + + b2BodyId bullet = b2CreateBody( m_worldId, &bodyDef ); + + if ( m_bulletType == e_boxShape ) + { + b2CreatePolygonShape( bullet, &shapeDef, &box ); + } + else + { + b2CreateCircleShape( bullet, &shapeDef, &circle ); + } + assert( B2_IS_NULL( m_bullets[i] ) ); + m_bullets[i] = bullet; + } + } + + void UpdateGui() override + { + float height = 230.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Vertical Stack", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::PushItemWidth( 120.0f ); + + bool changed = false; + const char* shapeTypes[] = { "Circle", "Box" }; + + int shapeType = int( m_shapeType ); + changed = changed || ImGui::Combo( "Shape", &shapeType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_shapeType = ShapeType( shapeType ); + + changed = changed || ImGui::SliderInt( "Rows", &m_rowCount, 1, e_maxRows ); + changed = changed || ImGui::SliderInt( "Columns", &m_columnCount, 1, e_maxColumns ); + + ImGui::SliderInt( "Bullets", &m_bulletCount, 1, e_maxBullets ); + + int bulletType = int( m_bulletType ); + ImGui::Combo( "Bullet Shape", &bulletType, shapeTypes, IM_ARRAYSIZE( shapeTypes ) ); + m_bulletType = ShapeType( bulletType ); + + ImGui::PopItemWidth(); + + if ( ImGui::Button( "Fire Bullets" ) || glfwGetKey( g_mainWindow, GLFW_KEY_B ) == GLFW_PRESS ) + { + DestroyBullets(); + FireBullets(); + } + + if ( ImGui::Button( "Destroy Body" ) ) + { + DestroyBody(); + } + + changed = changed || ImGui::Button( "Reset Stack" ); + + if ( changed ) + { + DestroyBullets(); + CreateStacks(); + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new VerticalStack( settings ); + } + + b2BodyId m_bullets[e_maxBullets]; + b2BodyId m_bodies[e_maxRows * e_maxColumns]; + int m_columnCount; + int m_rowCount; + int m_bulletCount; + ShapeType m_shapeType; + ShapeType m_bulletType; +}; + +static int sampleVerticalStack = RegisterSample( "Stacking", "Vertical Stack", VerticalStack::Create ); + +// A simple circle stack that also shows how to collect hit events +class CircleStack : public Sample +{ +public: + struct Event + { + int indexA, indexB; + }; + + explicit CircleStack( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 6.0f; + } + + int shapeIndex = 0; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.userData = reinterpret_cast( intptr_t( shapeIndex ) ); + shapeIndex += 1; + + b2Segment segment = { { -10.0f, 0.0f }, { 10.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + b2World_SetGravity( m_worldId, { 0.0f, -20.0f } ); + b2World_SetContactTuning( m_worldId, 0.25f * 360.0f, 10.0f, 3.0f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + b2Circle circle = {}; + circle.radius = 0.5f; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.enableHitEvents = true; + // shapeDef.rollingResistance = 0.2f; + shapeDef.material.friction = 0.0f; + + float y = 0.75f; + + for ( int i = 0; i < 10; ++i ) + { + bodyDef.position.y = y; + + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + shapeDef.userData = reinterpret_cast( intptr_t( shapeIndex ) ); + shapeDef.density = 1.0f + 4.0f * i; + shapeIndex += 1; + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + y += 1.25f; + } + } + + void Step( Settings& settings ) override + { + Sample::Step( settings ); + + b2ContactEvents events = b2World_GetContactEvents( m_worldId ); + for ( int i = 0; i < events.hitCount; ++i ) + { + b2ContactHitEvent* event = events.hitEvents + i; + + void* userDataA = b2Shape_GetUserData( event->shapeIdA ); + void* userDataB = b2Shape_GetUserData( event->shapeIdB ); + int indexA = static_cast( reinterpret_cast( userDataA ) ); + int indexB = static_cast( reinterpret_cast( userDataB ) ); + + g_draw.DrawPoint( event->point, 10.0f, b2_colorWhite ); + + m_events.push_back( { indexA, indexB } ); + } + + int eventCount = (int)m_events.size(); + for ( int i = 0; i < eventCount; ++i ) + { + g_draw.DrawString( 5, m_textLine, "%d, %d", m_events[i].indexA, m_events[i].indexB ); + m_textLine += m_textIncrement; + } + } + + static Sample* Create( Settings& settings ) + { + return new CircleStack( settings ); + } + + std::vector m_events; +}; + +static int sampleCircleStack = RegisterSample( "Stacking", "Circle Stack", CircleStack::Create ); + +class CapsuleStack : public Sample +{ +public: + struct Event + { + int indexA, indexB; + }; + + explicit CapsuleStack( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 5.0f }; + g_camera.m_zoom = 6.0f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -1.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon polygon = b2MakeBox( 10.0f, 1.0f ); + b2CreatePolygonShape( groundId, &shapeDef, &polygon ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + float a = 0.25f; + b2Capsule capsule = { { -4.0f * a, 0.0f }, { 4.0f * a, 0.0f }, a }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // rolling resistance increases stacking stability + // shapeDef.rollingResistance = 0.2f; + + float y = 2.0f * a; + + for ( int i = 0; i < 20; ++i ) + { + bodyDef.position.y = y; + // bodyDef.position.x += ( i & 1 ) == 1 ? -0.5f * a : 0.5f * a; + // bodyDef.linearVelocity = { 0.0f, -10.0f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + + b2CreateCapsuleShape( bodyId, &shapeDef, &capsule ); + + y += 3.0f * a; + } + } + + static Sample* Create( Settings& settings ) + { + return new CapsuleStack( settings ); + } +}; + +static int sampleCapsuleStack = RegisterSample( "Stacking", "Capsule Stack", CapsuleStack::Create ); + +class Cliff : public Sample +{ +public: + explicit Cliff( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_zoom = 25.0f * 0.5f; + g_camera.m_center = { 0.0f, 5.0f }; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, 0.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeOffsetBox( 100.0f, 1.0f, { 0.0f, -1.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + b2Segment segment = { { -14.0f, 4.0f }, { -8.0f, 4.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + + box = b2MakeOffsetBox( 3.0f, 0.5f, { 0.0f, 4.0f }, b2Rot_identity ); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + + b2Capsule capsule = { { 8.5f, 4.0f }, { 13.5f, 4.0f }, 0.5f }; + b2CreateCapsuleShape( groundId, &shapeDef, &capsule ); + } + + m_flip = false; + + for ( int i = 0; i < 9; ++i ) + { + m_bodyIds[i] = b2_nullBodyId; + } + + CreateBodies(); + } + + void CreateBodies() + { + for ( int i = 0; i < 9; ++i ) + { + if ( B2_IS_NON_NULL( m_bodyIds[i] ) ) + { + b2DestroyBody( m_bodyIds[i] ); + m_bodyIds[i] = b2_nullBodyId; + } + } + + float sign = m_flip ? -1.0f : 1.0f; + + b2Capsule capsule = { { -0.25f, 0.0f }, { 0.25f, 0.0f }, 0.25f }; + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + b2Polygon square = b2MakeSquare( 0.5f ); + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + { + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.01f; + bodyDef.linearVelocity = { 2.0f * sign, 0.0f }; + + float offset = m_flip ? -4.0f : 0.0f; + + bodyDef.position = { -9.0f + offset, 4.25f }; + m_bodyIds[0] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[0], &shapeDef, &capsule ); + + bodyDef.position = { 2.0f + offset, 4.75f }; + m_bodyIds[1] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[1], &shapeDef, &capsule ); + + bodyDef.position = { 13.0f + offset, 4.75f }; + m_bodyIds[2] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCapsuleShape( m_bodyIds[2], &shapeDef, &capsule ); + } + + { + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.01f; + bodyDef.linearVelocity = { 2.5f * sign, 0.0f }; + + bodyDef.position = { -11.0f, 4.5f }; + m_bodyIds[3] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyIds[3], &shapeDef, &square ); + + bodyDef.position = { 0.0f, 5.0f }; + m_bodyIds[4] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyIds[4], &shapeDef, &square ); + + bodyDef.position = { 11.0f, 5.0f }; + m_bodyIds[5] = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( m_bodyIds[5], &shapeDef, &square ); + } + + { + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.2f; + bodyDef.linearVelocity = { 1.5f * sign, 0.0f }; + + float offset = m_flip ? 4.0f : 0.0f; + + bodyDef.position = { -13.0f + offset, 4.5f }; + m_bodyIds[6] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( m_bodyIds[6], &shapeDef, &circle ); + + bodyDef.position = { -2.0f + offset, 5.0f }; + m_bodyIds[7] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( m_bodyIds[7], &shapeDef, &circle ); + + bodyDef.position = { 9.0f + offset, 5.0f }; + m_bodyIds[8] = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( m_bodyIds[8], &shapeDef, &circle ); + } + } + + void UpdateGui() override + { + float height = 60.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 160.0f, height ) ); + + ImGui::Begin( "Cliff", nullptr, ImGuiWindowFlags_NoResize ); + + if ( ImGui::Button( "Flip" ) ) + { + m_flip = !m_flip; + CreateBodies(); + } + + ImGui::End(); + } + + static Sample* Create( Settings& settings ) + { + return new Cliff( settings ); + } + + b2BodyId m_bodyIds[9]; + bool m_flip; +}; + +static int sampleCliff = RegisterSample( "Stacking", "Cliff", Cliff::Create ); + +class Arch : public Sample +{ +public: + explicit Arch( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 8.0f }; + g_camera.m_zoom = 25.0f * 0.35f; + } + + b2Vec2 ps1[9] = { { 16.0f, 0.0f }, + { 14.93803712795643f, 5.133601056842984f }, + { 13.79871746027416f, 10.24928069555078f }, + { 12.56252963284711f, 15.34107019122473f }, + { 11.20040987372525f, 20.39856541571217f }, + { 9.66521217819836f, 25.40369899225096f }, + { 7.87179930638133f, 30.3179337000085f }, + { 5.635199558196225f, 35.03820717801641f }, + { 2.405937953536585f, 39.09554102558315f } }; + + b2Vec2 ps2[9] = { { 24.0f, 0.0f }, + { 22.33619528222415f, 6.02299846205841f }, + { 20.54936888969905f, 12.00964361211476f }, + { 18.60854610798073f, 17.9470321677465f }, + { 16.46769273811807f, 23.81367936585418f }, + { 14.05325025774858f, 29.57079353071012f }, + { 11.23551045834022f, 35.13775818285372f }, + { 7.752568160730571f, 40.30450679009583f }, + { 3.016931552701656f, 44.28891593799322f } }; + + float scale = 0.25f; + for ( int i = 0; i < 9; ++i ) + { + ps1[i] = b2MulSV( scale, ps1[i] ); + ps2[i] = b2MulSV( scale, ps2[i] ); + } + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.6f; + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + b2Segment segment = { { -100.0f, 0.0f }, { 100.0f, 0.0f } }; + b2CreateSegmentShape( groundId, &shapeDef, &segment ); + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + for ( int i = 0; i < 8; ++i ) + { + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Vec2 ps[4] = { ps1[i], ps2[i], ps2[i + 1], ps1[i + 1] }; + b2Hull hull = b2ComputeHull( ps, 4 ); + b2Polygon polygon = b2MakePolygon( &hull, 0.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + } + + for ( int i = 0; i < 8; ++i ) + { + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Vec2 ps[4] = { { -ps2[i].x, ps2[i].y }, + { -ps1[i].x, ps1[i].y }, + { -ps1[i + 1].x, ps1[i + 1].y }, + { -ps2[i + 1].x, ps2[i + 1].y } }; + b2Hull hull = b2ComputeHull( ps, 4 ); + b2Polygon polygon = b2MakePolygon( &hull, 0.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + } + + { + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2Vec2 ps[4] = { ps1[8], ps2[8], { -ps2[8].x, ps2[8].y }, { -ps1[8].x, ps1[8].y } }; + b2Hull hull = b2ComputeHull( ps, 4 ); + b2Polygon polygon = b2MakePolygon( &hull, 0.0f ); + b2CreatePolygonShape( bodyId, &shapeDef, &polygon ); + } + + for ( int i = 0; i < 4; ++i ) + { + b2Polygon box = b2MakeBox( 2.0f, 0.5f ); + bodyDef.position = { 0.0f, 0.5f + ps2[8].y + 1.0f * i }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + } + } + + static Sample* Create( Settings& settings ) + { + return new Arch( settings ); + } +}; + +static int sampleArch = RegisterSample( "Stacking", "Arch", Arch::Create ); + +class DoubleDomino : public Sample +{ +public: + explicit DoubleDomino( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 4.0f }; + g_camera.m_zoom = 25.0f * 0.25f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -1.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2Polygon box = b2MakeBox( 100.0f, 1.0f ); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2CreatePolygonShape( groundId, &shapeDef, &box ); + } + + b2Polygon box = b2MakeBox( 0.125f, 0.5f ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.6f; + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + + int count = 15; + float x = -0.5f * count; + for ( int i = 0; i < count; ++i ) + { + bodyDef.position = { x, 0.5f }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + if ( i == 0 ) + { + b2Body_ApplyLinearImpulse( bodyId, b2Vec2{ 0.2f, 0.0f }, b2Vec2{ x, 1.0f }, true ); + } + + x += 1.0f; + } + } + + static Sample* Create( Settings& settings ) + { + return new DoubleDomino( settings ); + } +}; + +static int sampleDoubleDomino = RegisterSample( "Stacking", "Double Domino", DoubleDomino::Create ); + +class Confined : public Sample +{ +public: + explicit Confined( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.0f, 10.0f }; + g_camera.m_zoom = 25.0f * 0.5f; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Capsule capsule; + capsule = { { -10.5f, 0.0f }, { 10.5f, 0.0f }, 0.5f }; + b2CreateCapsuleShape( groundId, &shapeDef, &capsule ); + capsule = { { -10.5f, 0.0f }, { -10.5f, 20.5f }, 0.5f }; + b2CreateCapsuleShape( groundId, &shapeDef, &capsule ); + capsule = { { 10.5f, 0.0f }, { 10.5f, 20.5f }, 0.5f }; + b2CreateCapsuleShape( groundId, &shapeDef, &capsule ); + capsule = { { -10.5f, 20.5f }, { 10.5f, 20.5f }, 0.5f }; + b2CreateCapsuleShape( groundId, &shapeDef, &capsule ); + } + + m_row = 0; + m_column = 0; + m_count = 0; + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.gravityScale = 0.0f; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Circle circle = { { 0.0f, 0.0f }, 0.5f }; + + while ( m_count < m_maxCount ) + { + m_row = 0; + for ( int i = 0; i < m_gridCount; ++i ) + { + float x = -8.75f + m_column * 18.0f / m_gridCount; + float y = 1.5f + m_row * 18.0f / m_gridCount; + + bodyDef.position = { x, y }; + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreateCircleShape( bodyId, &shapeDef, &circle ); + + m_count += 1; + m_row += 1; + } + m_column += 1; + } + } + + static Sample* Create( Settings& settings ) + { + return new Confined( settings ); + } + + static constexpr int m_gridCount = 25; + static constexpr int m_maxCount = m_gridCount * m_gridCount; + int m_row; + int m_column; + int m_count; +}; + +static int sampleConfined = RegisterSample( "Stacking", "Confined", Confined::Create ); + +// From PEEL +class CardHouse : public Sample +{ +public: + explicit CardHouse( Settings& settings ) + : Sample( settings ) + { + if ( settings.restart == false ) + { + g_camera.m_center = { 0.75f, 0.9f }; + g_camera.m_zoom = 25.0f * 0.05f; + } + + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.position = { 0.0f, -2.0f }; + b2BodyId groundId = b2CreateBody( m_worldId, &bodyDef ); + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + shapeDef.material.friction = 0.7f; + + b2Polygon groundBox = b2MakeBox( 40.0f, 2.0f ); + b2CreatePolygonShape( groundId, &shapeDef, &groundBox ); + + float cardHeight = 0.2f; + float cardThickness = 0.001f; + + float angle0 = 25.0f * B2_PI / 180.0f; + float angle1 = -25.0f * B2_PI / 180.0f; + float angle2 = 0.5f * B2_PI; + + b2Polygon cardBox = b2MakeBox( cardThickness, cardHeight ); + bodyDef.type = b2_dynamicBody; + + int Nb = 5; + float z0 = 0.0f; + float y = cardHeight - 0.02f; + while ( Nb ) + { + float z = z0; + for ( int i = 0; i < Nb; i++ ) + { + if ( i != Nb - 1 ) + { + bodyDef.position = { z + 0.25f, y + cardHeight - 0.015f }; + bodyDef.rotation = b2MakeRot( angle2 ); + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &cardBox ); + } + + bodyDef.position = { z, y }; + bodyDef.rotation = b2MakeRot( angle1 ); + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &cardBox ); + + z += 0.175f; + + bodyDef.position = { z, y }; + bodyDef.rotation = b2MakeRot( angle0 ); + bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &cardBox ); + + z += 0.175f; + } + y += cardHeight * 2.0f - 0.03f; + z0 += 0.175f; + Nb--; + } + } + + static Sample* Create( Settings& settings ) + { + return new CardHouse( settings ); + } +}; + +static int sampleCardHouse = RegisterSample( "Stacking", "Card House", CardHouse::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/sample_world.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_world.cpp new file mode 100644 index 000000000000..055f19132a9e --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/sample_world.cpp @@ -0,0 +1,247 @@ +// SPDX-FileCopyrightText: 2022 Erin Catto +// SPDX-License-Identifier: MIT + +#include "car.h" +#include "donut.h" +#include "draw.h" +#include "human.h" +#include "sample.h" +#include "settings.h" + +#include "box2d/box2d.h" +#include "box2d/math_functions.h" + +#include +#include + +class LargeWorld : public Sample +{ +public: + explicit LargeWorld( Settings& settings ) + : Sample( settings ) + { + m_period = 40.0f; + float omega = 2.0 * B2_PI / m_period; + m_cycleCount = g_sampleDebug ? 10 : 600; + m_gridSize = 1.0f; + m_gridCount = (int)( m_cycleCount * m_period / m_gridSize ); + + float xStart = -0.5f * ( m_cycleCount * m_period ); + + m_viewPosition = { xStart, 15.0f }; + + if ( settings.restart == false ) + { + g_camera.m_center = m_viewPosition; + g_camera.m_zoom = 25.0f * 1.0f; + settings.drawJoints = false; + settings.useCameraBounds = true; + } + + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + b2ShapeDef shapeDef = b2DefaultShapeDef(); + + // Setting this to false significantly reduces the cost of creating + // static bodies and shapes. + shapeDef.invokeContactCreation = false; + + float height = 4.0f; + float xBody = xStart; + float xShape = xStart; + + b2BodyId groundId; + + for ( int i = 0; i < m_gridCount; ++i ) + { + // Create a new body regularly so that shapes are not too far from the body origin. + // Most algorithms in Box2D work in local coordinates, but contact points are computed + // relative to the body origin. + // This makes a noticeable improvement in stability far from the origin. + if ( i % 10 == 0 ) + { + bodyDef.position.x = xBody; + groundId = b2CreateBody( m_worldId, &bodyDef ); + xShape = 0.0f; + } + + float y = 0.0f; + + int ycount = (int)roundf( height * cosf( omega * xBody ) ) + 12; + + for ( int j = 0; j < ycount; ++j ) + { + b2Polygon square = b2MakeOffsetBox( 0.4f * m_gridSize, 0.4f * m_gridSize, { xShape, y }, b2Rot_identity ); + square.radius = 0.1f; + b2CreatePolygonShape( groundId, &shapeDef, &square ); + + y += m_gridSize; + } + + xBody += m_gridSize; + xShape += m_gridSize; + } + } + + int humanIndex = 0; + for ( int cycleIndex = 0; cycleIndex < m_cycleCount; ++cycleIndex ) + { + float xbase = ( 0.5f + cycleIndex ) * m_period + xStart; + + int remainder = cycleIndex % 3; + if ( remainder == 0 ) + { + b2BodyDef bodyDef = b2DefaultBodyDef(); + bodyDef.type = b2_dynamicBody; + bodyDef.position = { xbase - 3.0f, 10.0f }; + + b2ShapeDef shapeDef = b2DefaultShapeDef(); + b2Polygon box = b2MakeBox( 0.3f, 0.2f ); + + for ( int i = 0; i < 10; ++i ) + { + bodyDef.position.y = 10.0f; + for ( int j = 0; j < 5; ++j ) + { + b2BodyId bodyId = b2CreateBody( m_worldId, &bodyDef ); + b2CreatePolygonShape( bodyId, &shapeDef, &box ); + bodyDef.position.y += 0.5f; + } + bodyDef.position.x += 0.6f; + } + } + else if ( remainder == 1 ) + { + b2Vec2 position = { xbase - 2.0f, 10.0f }; + for ( int i = 0; i < 5; ++i ) + { + Human human = {}; + CreateHuman(&human, m_worldId, position, 1.5f, 0.05f, 0.0f, 0.0f, humanIndex + 1, nullptr, false ); + humanIndex += 1; + position.x += 1.0f; + } + } + else + { + b2Vec2 position = { xbase - 4.0f, 12.0f }; + + for ( int i = 0; i < 5; ++i ) + { + Donut donut; + donut.Create( m_worldId, position, 0.75f, 0, false, nullptr ); + position.x += 2.0f; + } + } + } + + m_car.Spawn( m_worldId, { xStart + 20.0f, 40.0f }, 10.0f, 2.0f, 0.7f, 2000.0f, nullptr ); + + m_cycleIndex = 0; + m_speed = 0.0f; + m_explosionPosition = { ( 0.5f + m_cycleIndex ) * m_period + xStart, 7.0f }; + m_explode = true; + m_followCar = false; + } + + void UpdateGui() override + { + float height = 160.0f; + ImGui::SetNextWindowPos( ImVec2( 10.0f, g_camera.m_height - height - 50.0f ), ImGuiCond_Once ); + ImGui::SetNextWindowSize( ImVec2( 240.0f, height ) ); + + ImGui::Begin( "Large World", nullptr, ImGuiWindowFlags_NoResize ); + + ImGui::SliderFloat( "speed", &m_speed, -400.0f, 400.0f, "%.0f" ); + if ( ImGui::Button( "stop" ) ) + { + m_speed = 0.0f; + } + + ImGui::Checkbox( "explode", &m_explode ); + ImGui::Checkbox( "follow car", &m_followCar ); + + ImGui::Text( "world size = %g kilometers", m_gridSize * m_gridCount / 1000.0f ); + ImGui::End(); + } + + void Step( Settings& settings ) override + { + float span = 0.5f * ( m_period * m_cycleCount ); + float timeStep = settings.hertz > 0.0f ? 1.0f / settings.hertz : 0.0f; + + if ( settings.pause ) + { + timeStep = 0.0f; + } + + m_viewPosition.x += timeStep * m_speed; + m_viewPosition.x = b2ClampFloat( m_viewPosition.x, -span, span ); + + if ( m_speed != 0.0f ) + { + g_camera.m_center = m_viewPosition; + } + + if ( m_followCar ) + { + g_camera.m_center.x = b2Body_GetPosition( m_car.m_chassisId ).x; + } + + float radius = 2.0f; + if ( ( m_stepCount & 0x1 ) == 0x1 && m_explode ) + { + m_explosionPosition.x = ( 0.5f + m_cycleIndex ) * m_period - span; + + b2ExplosionDef def = b2DefaultExplosionDef(); + def.position = m_explosionPosition; + def.radius = radius; + def.falloff = 0.1f; + def.impulsePerLength = 1.0f; + b2World_Explode( m_worldId, &def ); + + m_cycleIndex = ( m_cycleIndex + 1 ) % m_cycleCount; + } + + if ( m_explode ) + { + g_draw.DrawCircle( m_explosionPosition, radius, b2_colorAzure ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_A ) == GLFW_PRESS ) + { + m_car.SetSpeed( 20.0f ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_S ) == GLFW_PRESS ) + { + m_car.SetSpeed( 0.0f ); + } + + if ( glfwGetKey( g_mainWindow, GLFW_KEY_D ) == GLFW_PRESS ) + { + m_car.SetSpeed( -5.0f ); + } + + Sample::Step( settings ); + } + + static Sample* Create( Settings& settings ) + { + return new LargeWorld( settings ); + } + + Car m_car; + b2Vec2 m_viewPosition; + float m_period; + int m_cycleCount; + int m_cycleIndex; + float m_gridCount; + float m_gridSize; + float m_speed; + + b2Vec2 m_explosionPosition; + bool m_explode; + bool m_followCar; +}; + +static int sampleLargeWorld = RegisterSample( "World", "Large World", LargeWorld::Create ); diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/settings.cpp b/tests/cpp-tests/Source/Box2DTestBed/samples/settings.cpp new file mode 100644 index 000000000000..9478bb3bd6e4 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/settings.cpp @@ -0,0 +1,143 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#if defined( _MSC_VER ) && !defined( _CRT_SECURE_NO_WARNINGS ) +#define _CRT_SECURE_NO_WARNINGS +#endif + +#include "settings.h" + +// todo consider using https://github.com/skeeto/pdjson +#include "../src/core.h" + +#include +#include "jsmn.h" +#include +#include +#include + +static const char* fileName = "settings.ini"; + +// Load a file. You must free the character array. +static bool ReadFile( char*& data, int& size, const char* filename ) +{ + FILE* file = fopen( filename, "rb" ); + if ( file == nullptr ) + { + return false; + } + + fseek( file, 0, SEEK_END ); + size = (int)ftell( file ); + fseek( file, 0, SEEK_SET ); + + if ( size == 0 ) + { + return false; + } + + data = (char*)malloc( size + 1 ); + size_t count = fread( data, size, 1, file ); + B2_UNUSED( count ); + fclose( file ); + data[size] = 0; + + return true; +} + +void Settings::Save() +{ + FILE* file = fopen( fileName, "w" ); + fprintf( file, "{\n" ); + fprintf( file, " \"sampleIndex\": %d,\n", sampleIndex ); + fprintf( file, " \"drawShapes\": %s,\n", drawShapes ? "true" : "false" ); + fprintf( file, " \"drawJoints\": %s,\n", drawJoints ? "true" : "false" ); + fprintf( file, " \"drawBounds\": %s,\n", drawBounds ? "true" : "false" ); + fprintf( file, " \"drawContactPoints\": %s,\n", drawContactPoints ? "true" : "false" ); + fprintf( file, " \"drawContactNormals\": %s,\n", drawContactNormals ? "true" : "false" ); + fprintf( file, " \"drawContactImpulses\": %s,\n", drawContactImpulses ? "true" : "false" ); + fprintf( file, " \"drawContactFeatures\": %s,\n", drawContactFeatures ? "true" : "false" ); + fprintf( file, " \"drawFrictionImpulse\": %s,\n", drawFrictionImpulses ? "true" : "false" ); + fprintf( file, " \"drawMass\": %s,\n", drawMass ? "true" : "false" ); + fprintf( file, " \"drawCounters\": %s,\n", drawCounters ? "true" : "false" ); + fprintf( file, " \"drawProfile\": %s,\n", drawProfile ? "true" : "false" ); + fprintf( file, " \"enableWarmStarting\": %s,\n", enableWarmStarting ? "true" : "false" ); + fprintf( file, " \"enableContinuous\": %s,\n", enableContinuous ? "true" : "false" ); + fprintf( file, " \"enableSleep\": %s\n", enableSleep ? "true" : "false" ); + fprintf( file, "}\n" ); + fclose( file ); +} + +static int jsoneq( const char* json, jsmntok_t* tok, const char* s ) +{ + if ( tok->type == JSMN_STRING && (int)strlen( s ) == tok->end - tok->start && + strncmp( json + tok->start, s, tok->end - tok->start ) == 0 ) + { + return 0; + } + return -1; +} + +#define MAX_TOKENS 32 + +void Settings::Load() +{ + char* data = nullptr; + int size = 0; + bool found = ReadFile( data, size, fileName ); + if ( found == false ) + { + return; + } + + jsmn_parser parser; + jsmntok_t tokens[MAX_TOKENS]; + + jsmn_init( &parser ); + + // js - pointer to JSON string + // tokens - an array of tokens available + // 10 - number of tokens available + int tokenCount = jsmn_parse( &parser, data, size, tokens, MAX_TOKENS ); + char buffer[32]; + + for ( int i = 0; i < tokenCount; ++i ) + { + if ( jsoneq( data, &tokens[i], "sampleIndex" ) == 0 ) + { + int count = tokens[i + 1].end - tokens[i + 1].start; + assert( count < 32 ); + const char* s = data + tokens[i + 1].start; + strncpy( buffer, s, count ); + buffer[count] = 0; + char* dummy; + sampleIndex = (int)strtol( buffer, &dummy, 10 ); + } + else if ( jsoneq( data, &tokens[i], "drawShapes" ) == 0 ) + { + const char* s = data + tokens[i + 1].start; + if ( strncmp( s, "true", 4 ) == 0 ) + { + drawShapes = true; + } + else if ( strncmp( s, "false", 5 ) == 0 ) + { + drawShapes = false; + } + } + else if ( jsoneq( data, &tokens[i], "drawJoints" ) == 0 ) + { + const char* s = data + tokens[i + 1].start; + if ( strncmp( s, "true", 4 ) == 0 ) + { + drawJoints = true; + } + else if ( strncmp( s, "false", 5 ) == 0 ) + { + drawJoints = false; + } + } + } + + free( data ); +} diff --git a/tests/cpp-tests/Source/Box2DTestBed/samples/settings.h b/tests/cpp-tests/Source/Box2DTestBed/samples/settings.h new file mode 100644 index 000000000000..a7532711c711 --- /dev/null +++ b/tests/cpp-tests/Source/Box2DTestBed/samples/settings.h @@ -0,0 +1,44 @@ +// SPDX-FileCopyrightText: 2023 Erin Catto +// SPDX-License-Identifier: MIT + +#pragma once + +// todo add camera and draw and remove globals +struct Settings +{ + void Save(); + void Load(); + + int sampleIndex = 0; + int windowWidth = 1920; + int windowHeight = 1080; + //int windowWidth = 900; + //int windowHeight = 600; + + float hertz = 60.0f; + int subStepCount = 4; + int workerCount = 1; + + bool useCameraBounds = false; + bool drawShapes = true; + bool drawJoints = true; + bool drawJointExtras = false; + bool drawBounds = false; + bool drawMass = false; + bool drawBodyNames = false; + bool drawContactPoints = false; + bool drawContactNormals = false; + bool drawContactImpulses = false; + bool drawContactFeatures = false; + bool drawFrictionImpulses = false; + bool drawIslands = false; + bool drawGraphColors = false; + bool drawCounters = false; + bool drawProfile = false; + bool enableWarmStarting = true; + bool enableContinuous = true; + bool enableSleep = true; + bool pause = false; + bool singleStep = false; + bool restart = false; +}; diff --git a/tests/cpp-tests/Source/Box2DTestBed/test.cpp b/tests/cpp-tests/Source/Box2DTestBed/test.cpp deleted file mode 100644 index d5c26853a097..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/test.cpp +++ /dev/null @@ -1,514 +0,0 @@ -/* - * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#include "tests/test.h" -#include "tests/settings.h" - -#include "extensions/axmol-ext.h" -#include "axmol.h" - -#include - -using namespace ax; -USING_NS_AX_EXT; - -#if defined(AX_PLATFORM_PC) -extern ax::Label* labelDebugDraw; -#endif - -void DestructionListener::SayGoodbye(b2Joint* joint) -{ - if (test->m_mouseJoint == joint) - { - test->m_mouseJoint = NULL; - } - else - { - test->JointDestroyed(joint); - } -} - -Test::Test() -{ - b2Vec2 gravity; - gravity.Set(0.0f, -10.0f); - m_world = new b2World(gravity); - m_bomb = NULL; - m_textLine = 30; - m_textIncrement = 13; - m_mouseJoint = NULL; - m_pointCount = 0; - - m_destructionListener.test = this; - m_world->SetDestructionListener(&m_destructionListener); - m_world->SetContactListener(this); - m_world->SetDebugDraw(&g_debugDraw); - - m_bombSpawning = false; - - m_stepCount = 0; - - b2BodyDef bodyDef; - m_groundBody = m_world->CreateBody(&bodyDef); - - memset(&m_maxProfile, 0, sizeof(b2Profile)); - memset(&m_totalProfile, 0, sizeof(b2Profile)); -} - -Test::~Test() -{ - // By deleting the world, we delete the bomb, mouse joint, etc. - delete m_world; - m_world = NULL; -} - -void Test::PreSolve(b2Contact* contact, const b2Manifold* oldManifold) -{ - const b2Manifold* manifold = contact->GetManifold(); - - if (manifold->pointCount == 0) - { - return; - } - - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - - b2PointState state1[b2_maxManifoldPoints], state2[b2_maxManifoldPoints]; - b2GetPointStates(state1, state2, oldManifold, manifold); - - b2WorldManifold worldManifold; - contact->GetWorldManifold(&worldManifold); - - for (int32 i = 0; i < manifold->pointCount && m_pointCount < k_maxContactPoints; ++i) - { - ContactPoint* cp = m_points + m_pointCount; - cp->fixtureA = fixtureA; - cp->fixtureB = fixtureB; - cp->position = worldManifold.points[i]; - cp->normal = worldManifold.normal; - cp->state = state2[i]; - cp->normalImpulse = manifold->points[i].normalImpulse; - cp->tangentImpulse = manifold->points[i].tangentImpulse; - cp->separation = worldManifold.separations[i]; - ++m_pointCount; - } -} - -void Test::DrawTitle(const char* string) -{ - DrawString(5, 5, string); - m_textLine = int32(26.0f); -} - -class QueryCallback : public b2QueryCallback -{ -public: - QueryCallback(const b2Vec2& point) - { - m_point = point; - m_fixture = NULL; - } - - bool ReportFixture(b2Fixture* fixture) override - { - b2Body* body = fixture->GetBody(); - if (body->GetType() == b2_dynamicBody) - { - bool inside = fixture->TestPoint(m_point); - if (inside) - { - m_fixture = fixture; - - // We are done, terminate the query. - return false; - } - } - - // Continue the query. - return true; - } - - b2Vec2 m_point; - b2Fixture* m_fixture; -}; - -bool Test::MouseDown(const b2Vec2& p) -{ - m_mouseWorld = p; - - if (m_mouseJoint != NULL) - { - return false; - } - - // Make a small box. - b2AABB aabb; - b2Vec2 d; - d.Set(0.001f, 0.001f); - aabb.lowerBound = p - d; - aabb.upperBound = p + d; - - // Query the world for overlapping shapes. - QueryCallback callback(p); - m_world->QueryAABB(&callback, aabb); - - if (callback.m_fixture) - { - float frequencyHz = 5.0f; - float dampingRatio = 0.7f; - - b2Body* body = callback.m_fixture->GetBody(); - b2MouseJointDef jd; - jd.bodyA = m_groundBody; - jd.bodyB = body; - jd.target = p; - jd.maxForce = 1000.0f * body->GetMass(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - - m_mouseJoint = (b2MouseJoint*)m_world->CreateJoint(&jd); - body->SetAwake(true); - return true; - } - return false; -} - -void Test::SpawnBomb(const b2Vec2& worldPt) -{ - m_bombSpawnPoint = worldPt; - m_bombSpawning = true; -} - -void Test::CompleteBombSpawn(const b2Vec2& p) -{ - if (m_bombSpawning == false) - { - return; - } - - const float multiplier = 30.0f; - b2Vec2 vel = m_bombSpawnPoint - p; - vel *= multiplier; - LaunchBomb(m_bombSpawnPoint, vel); - m_bombSpawning = false; -} - -void Test::ShiftMouseDown(const b2Vec2& p) -{ - m_mouseWorld = p; - - if (m_mouseJoint != NULL) - { - return; - } - - SpawnBomb(p); -} - -void Test::MouseUp(const b2Vec2& p) -{ - if (m_mouseJoint) - { - m_world->DestroyJoint(m_mouseJoint); - m_mouseJoint = NULL; - } - - if (m_bombSpawning) - { - CompleteBombSpawn(p); - } -} - -void Test::MouseMove(const b2Vec2& p) -{ - m_mouseWorld = p; - - if (m_mouseJoint) - { - m_mouseJoint->SetTarget(p); - } -} - -void Test::LaunchBomb() -{ - b2Vec2 p(RandomFloat(-15.0f, 15.0f), 30.0f); - b2Vec2 v = -5.0f * p; - LaunchBomb(p, v); -} - -void Test::LaunchBomb(const b2Vec2& position, const b2Vec2& velocity) -{ - if (m_bomb) - { - m_world->DestroyBody(m_bomb); - m_bomb = NULL; - } - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = position; - bd.bullet = true; - m_bomb = m_world->CreateBody(&bd); - m_bomb->SetLinearVelocity(velocity); - - b2CircleShape circle; - circle.m_radius = 0.3f; - - b2FixtureDef fd; - fd.shape = &circle; - fd.density = 20.0f; - fd.restitution = 0.0f; - - b2Vec2 minV = position - b2Vec2(0.3f, 0.3f); - b2Vec2 maxV = position + b2Vec2(0.3f, 0.3f); - - b2AABB aabb; - aabb.lowerBound = minV; - aabb.upperBound = maxV; - - m_bomb->CreateFixture(&fd); -} - -void Test::Step(Settings& settings) -{ - float timeStep = settings.m_hertz > 0.0f ? 1.0f / settings.m_hertz : float(0.0f); - - if (settings.m_pause) - { - if (settings.m_singleStep) - { - settings.m_singleStep = 0; - } - else - { - timeStep = 0.0f; - } - - DrawString(5, m_textLine, "****PAUSED****"); - } - - uint32 flags = 0; - flags += settings.m_drawShapes * b2Draw::e_shapeBit; - flags += settings.m_drawJoints * b2Draw::e_jointBit; - flags += settings.m_drawAABBs * b2Draw::e_aabbBit; - flags += settings.m_drawCOMs * b2Draw::e_centerOfMassBit; - g_debugDraw.SetFlags(flags); - - m_world->SetAllowSleeping(settings.m_enableSleep); - m_world->SetWarmStarting(settings.m_enableWarmStarting); - m_world->SetContinuousPhysics(settings.m_enableContinuous); - m_world->SetSubStepping(settings.m_enableSubStepping); - - m_pointCount = 0; - - m_world->Step(timeStep, settings.m_velocityIterations, settings.m_positionIterations); - - m_world->DebugDraw(); - - if (timeStep > 0.0f) - { - ++m_stepCount; - } - - if (settings.m_drawStats) - { - int32 bodyCount = m_world->GetBodyCount(); - int32 contactCount = m_world->GetContactCount(); - int32 jointCount = m_world->GetJointCount(); - DrawString(5, m_textLine, "bodies/contacts/joints = %d/%d/%d", bodyCount, contactCount, jointCount); - - int32 proxyCount = m_world->GetProxyCount(); - int32 height = m_world->GetTreeHeight(); - int32 balance = m_world->GetTreeBalance(); - float quality = m_world->GetTreeQuality(); - DrawString(5, m_textLine, "proxies/height/balance/quality = %d/%d/%d/%g", proxyCount, height, balance, quality); - } - - // Track maximum profile times - { - const b2Profile& p = m_world->GetProfile(); - m_maxProfile.step = b2Max(m_maxProfile.step, p.step); - m_maxProfile.collide = b2Max(m_maxProfile.collide, p.collide); - m_maxProfile.solve = b2Max(m_maxProfile.solve, p.solve); - m_maxProfile.solveInit = b2Max(m_maxProfile.solveInit, p.solveInit); - m_maxProfile.solveVelocity = b2Max(m_maxProfile.solveVelocity, p.solveVelocity); - m_maxProfile.solvePosition = b2Max(m_maxProfile.solvePosition, p.solvePosition); - m_maxProfile.solveTOI = b2Max(m_maxProfile.solveTOI, p.solveTOI); - m_maxProfile.broadphase = b2Max(m_maxProfile.broadphase, p.broadphase); - - m_totalProfile.step += p.step; - m_totalProfile.collide += p.collide; - m_totalProfile.solve += p.solve; - m_totalProfile.solveInit += p.solveInit; - m_totalProfile.solveVelocity += p.solveVelocity; - m_totalProfile.solvePosition += p.solvePosition; - m_totalProfile.solveTOI += p.solveTOI; - m_totalProfile.broadphase += p.broadphase; - } - - if (settings.m_drawProfile) - { - const b2Profile& p = m_world->GetProfile(); - - b2Profile aveProfile; - memset(&aveProfile, 0, sizeof(b2Profile)); - if (m_stepCount > 0) - { - float scale = 1.0f / m_stepCount; - aveProfile.step = scale * m_totalProfile.step; - aveProfile.collide = scale * m_totalProfile.collide; - aveProfile.solve = scale * m_totalProfile.solve; - aveProfile.solveInit = scale * m_totalProfile.solveInit; - aveProfile.solveVelocity = scale * m_totalProfile.solveVelocity; - aveProfile.solvePosition = scale * m_totalProfile.solvePosition; - aveProfile.solveTOI = scale * m_totalProfile.solveTOI; - aveProfile.broadphase = scale * m_totalProfile.broadphase; - } - - DrawString(5, m_textLine, "step [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.step, aveProfile.step, - m_maxProfile.step); - DrawString(5, m_textLine, "collide [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.collide, aveProfile.collide, - m_maxProfile.collide); - DrawString(5, m_textLine, "solve [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solve, aveProfile.solve, - m_maxProfile.solve); - DrawString(5, m_textLine, "solve init [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveInit, aveProfile.solveInit, - m_maxProfile.solveInit); - DrawString(5, m_textLine, "solve velocity [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveVelocity, - aveProfile.solveVelocity, m_maxProfile.solveVelocity); - DrawString(5, m_textLine, "solve position [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solvePosition, - aveProfile.solvePosition, m_maxProfile.solvePosition); - DrawString(5, m_textLine, "solveTOI [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.solveTOI, aveProfile.solveTOI, - m_maxProfile.solveTOI); - DrawString(5, m_textLine, "broad-phase [ave] (max) = %5.2f [%6.2f] (%6.2f)", p.broadphase, - aveProfile.broadphase, m_maxProfile.broadphase); - } - - if (m_bombSpawning) - { - b2Color c; - c.Set(0.0f, 0.0f, 1.0f); - g_debugDraw.DrawPoint(m_bombSpawnPoint, 4.0f, c); - - c.Set(0.8f, 0.8f, 0.8f); - g_debugDraw.DrawSegment(m_mouseWorld, m_bombSpawnPoint, c); - } - - if (settings.m_drawContactPoints) - { - const float k_impulseScale = 0.1f; - const float k_axisScale = 0.3f; - - for (int32 i = 0; i < m_pointCount; ++i) - { - ContactPoint* point = m_points + i; - - if (point->state == b2_addState) - { - // Add - g_debugDraw.DrawPoint(point->position, 10.0f, b2Color(0.3f, 0.95f, 0.3f)); - } - else if (point->state == b2_persistState) - { - // Persist - g_debugDraw.DrawPoint(point->position, 5.0f, b2Color(0.3f, 0.3f, 0.95f)); - } - - if (settings.m_drawContactNormals == 1) - { - b2Vec2 p1 = point->position; - b2Vec2 p2 = p1 + k_axisScale * point->normal; - g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.9f)); - } - else if (settings.m_drawContactImpulse == 1) - { - b2Vec2 p1 = point->position; - b2Vec2 p2 = p1 + k_impulseScale * point->normalImpulse * point->normal; - g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f)); - } - - if (settings.m_drawFrictionImpulse == 1) - { - b2Vec2 tangent = b2Cross(point->normal, 1.0f); - b2Vec2 p1 = point->position; - b2Vec2 p2 = p1 + k_impulseScale * point->tangentImpulse * tangent; - g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.9f, 0.3f)); - } - } - } -} - -void Test::ShiftOrigin(const b2Vec2& newOrigin) -{ - m_world->ShiftOrigin(newOrigin); -} - -void Test::initShader(void) -{ - // initShader is unsupported -} - -void Test::DrawString(int x, int y, const char* fmt, ...) -{ -#if defined(AX_PLATFORM_PC) - va_list args; - va_start(args, fmt); - auto str = StringUtils::vformat(fmt, args); - va_end(args); - debugString.append(str); - debugString.append("\n"); - labelDebugDraw->setString(debugString); - // labelDebugDraw->setPosition(x, y); -#endif -} - -void Test::DrawString(const b2Vec2& pw, const char* fmt, ...) -{ -#if defined(AX_PLATFORM_PC) - va_list args; - va_start(args, fmt); - auto str = StringUtils::vformat(fmt, args); - va_end(args); - debugString.append(str); - debugString.append("\n"); - labelDebugDraw->setString(debugString); - // labelDebugDraw->setPosition(pw.x, pw.y); -#endif -} - -void Test::DrawAABB(b2AABB* aabb, const b2Color& color) -{ - b2Vec2 p1 = aabb->lowerBound; - b2Vec2 p2 = b2Vec2(aabb->upperBound.x, aabb->lowerBound.y); - b2Vec2 p3 = aabb->upperBound; - b2Vec2 p4 = b2Vec2(aabb->lowerBound.x, aabb->upperBound.y); - - Vec2 verts[] = { - Vec2(p1.x * g_debugDraw.mRatio, p1.y * g_debugDraw.mRatio) + g_debugDraw.debugNodeOffset, - Vec2(p2.x * g_debugDraw.mRatio, p2.y * g_debugDraw.mRatio) + g_debugDraw.debugNodeOffset, - Vec2(p3.x * g_debugDraw.mRatio, p3.y * g_debugDraw.mRatio) + g_debugDraw.debugNodeOffset, - Vec2(p4.x * g_debugDraw.mRatio, p4.y * g_debugDraw.mRatio) + g_debugDraw.debugNodeOffset, - }; - debugDrawNode->drawPolygon(verts, sizeof(verts) / sizeof(verts[0]), - Color4F(color.r / 2, color.g / 2, color.b / 2, 0), 0.4f, - Color4F(color.r, color.g, color.b, color.a)); -} - -void Test::Flush() -{ - // Flush is unsupported -} diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/add_pair.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/add_pair.cpp deleted file mode 100644 index 4465d35f3e01..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/add_pair.cpp +++ /dev/null @@ -1,67 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class AddPair : public Test -{ -public: - AddPair() - { - m_world->SetGravity(b2Vec2(0.0f, 0.0f)); - { - b2CircleShape shape; - shape.m_p.SetZero(); - shape.m_radius = 0.1f; - - float minX = -6.0f; - float maxX = 0.0f; - float minY = 4.0f; - float maxY = 6.0f; - - for (int32 i = 0; i < 400; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = b2Vec2(RandomFloat(minX, maxX), RandomFloat(minY, maxY)); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 0.01f); - } - } - - { - b2PolygonShape shape; - shape.SetAsBox(1.5f, 1.5f); - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-40.0f, 5.0f); - bd.bullet = true; - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 1.0f); - body->SetLinearVelocity(b2Vec2(10.0f, 0.0f)); - } - } - - static Test* Create() { return new AddPair; } -}; - -static int testIndex = RegisterTest("Benchmark", "Add Pair", AddPair::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/apply_force.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/apply_force.cpp deleted file mode 100644 index 51239f60e2f3..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/apply_force.cpp +++ /dev/null @@ -1,199 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// This test shows how to apply forces and torques to a body. -// It also shows how to use the friction joint that can be useful -// for overhead games. -class ApplyForce : public Test -{ -public: - ApplyForce() - { - m_world->SetGravity(b2Vec2(0.0f, 0.0f)); - - const float k_restitution = 0.4f; - - b2Body* ground; - { - b2BodyDef bd; - bd.position.Set(0.0f, 20.0f); - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - - b2FixtureDef sd; - sd.shape = &shape; - sd.density = 0.0f; - sd.restitution = k_restitution; - - // Left vertical - shape.SetTwoSided(b2Vec2(-20.0f, -20.0f), b2Vec2(-20.0f, 20.0f)); - ground->CreateFixture(&sd); - - // Right vertical - shape.SetTwoSided(b2Vec2(20.0f, -20.0f), b2Vec2(20.0f, 20.0f)); - ground->CreateFixture(&sd); - - // Top horizontal - shape.SetTwoSided(b2Vec2(-20.0f, 20.0f), b2Vec2(20.0f, 20.0f)); - ground->CreateFixture(&sd); - - // Bottom horizontal - shape.SetTwoSided(b2Vec2(-20.0f, -20.0f), b2Vec2(20.0f, -20.0f)); - ground->CreateFixture(&sd); - } - - { - b2Transform xf1; - xf1.q.Set(0.3524f * b2_pi); - xf1.p = xf1.q.GetXAxis(); - - b2Vec2 vertices[3]; - vertices[0] = b2Mul(xf1, b2Vec2(-1.0f, 0.0f)); - vertices[1] = b2Mul(xf1, b2Vec2(1.0f, 0.0f)); - vertices[2] = b2Mul(xf1, b2Vec2(0.0f, 0.5f)); - - b2PolygonShape poly1; - poly1.Set(vertices, 3); - - b2FixtureDef sd1; - sd1.shape = &poly1; - sd1.density = 2.0f; - - b2Transform xf2; - xf2.q.Set(-0.3524f * b2_pi); - xf2.p = -xf2.q.GetXAxis(); - - vertices[0] = b2Mul(xf2, b2Vec2(-1.0f, 0.0f)); - vertices[1] = b2Mul(xf2, b2Vec2(1.0f, 0.0f)); - vertices[2] = b2Mul(xf2, b2Vec2(0.0f, 0.5f)); - - b2PolygonShape poly2; - poly2.Set(vertices, 3); - - b2FixtureDef sd2; - sd2.shape = &poly2; - sd2.density = 2.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - bd.position.Set(0.0f, 3.0); - bd.angle = b2_pi; - bd.allowSleep = false; - m_body = m_world->CreateBody(&bd); - m_body->CreateFixture(&sd1); - m_body->CreateFixture(&sd2); - - float gravity = 10.0f; - float I = m_body->GetInertia(); - float mass = m_body->GetMass(); - - // Compute an effective radius that can be used to - // set the max torque for a friction joint - // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) - float radius = b2Sqrt(2.0f * I / mass); - - b2FrictionJointDef jd; - jd.bodyA = ground; - jd.bodyB = m_body; - jd.localAnchorA.SetZero(); - jd.localAnchorB = m_body->GetLocalCenter(); - jd.collideConnected = true; - jd.maxForce = 0.5f * mass * gravity; - jd.maxTorque = 0.2f * mass * radius * gravity; - - m_world->CreateJoint(&jd); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - fd.friction = 0.3f; - - for (int i = 0; i < 10; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - - bd.position.Set(0.0f, 7.0f + 1.54f * i); - b2Body* body = m_world->CreateBody(&bd); - - body->CreateFixture(&fd); - - float gravity = 10.0f; - float I = body->GetInertia(); - float mass = body->GetMass(); - - // For a circle: I = 0.5 * m * r * r ==> r = sqrt(2 * I / m) - float radius = b2Sqrt(2.0f * I / mass); - - b2FrictionJointDef jd; - jd.localAnchorA.SetZero(); - jd.localAnchorB.SetZero(); - jd.bodyA = ground; - jd.bodyB = body; - jd.collideConnected = true; - jd.maxForce = mass * gravity; - jd.maxTorque = 0.1f * mass * radius * gravity; - - m_world->CreateJoint(&jd); - } - } - } - - void Step(Settings& settings) override - { - DrawString(5, m_textLine, "Forward (W), Turn (A) and (D)"); - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_W) == GLFW_PRESS) - //{ - // b2Vec2 f = m_body->GetWorldVector(b2Vec2(0.0f, -50.0f)); - // b2Vec2 p = m_body->GetWorldPoint(b2Vec2(0.0f, 3.0f)); - // m_body->ApplyForce(f, p, true); - // } - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_A) == GLFW_PRESS) - //{ - // m_body->ApplyTorque(10.0f, true); - // } - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_D) == GLFW_PRESS) - //{ - // m_body->ApplyTorque(-10.0f, true); - // } - - Test::Step(settings); - } - - static Test* Create() { return new ApplyForce; } - - b2Body* m_body; -}; - -static int testIndex = RegisterTest("Forces", "Apply Force", ApplyForce::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/body_types.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/body_types.cpp deleted file mode 100644 index 0de1079826f0..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/body_types.cpp +++ /dev/null @@ -1,158 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class BodyTypes : public Test -{ -public: - BodyTypes() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - - b2FixtureDef fd; - fd.shape = &shape; - - ground->CreateFixture(&fd); - } - - // Define attachment - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 3.0f); - m_attachment = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 2.0f); - m_attachment->CreateFixture(&shape, 2.0f); - } - - // Define platform - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-4.0f, 5.0f); - m_platform = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 4.0f, b2Vec2(4.0f, 0.0f), 0.5f * b2_pi); - - b2FixtureDef fd; - fd.shape = &shape; - fd.friction = 0.6f; - fd.density = 2.0f; - m_platform->CreateFixture(&fd); - - b2RevoluteJointDef rjd; - rjd.Initialize(m_attachment, m_platform, b2Vec2(0.0f, 5.0f)); - rjd.maxMotorTorque = 50.0f; - rjd.enableMotor = true; - m_world->CreateJoint(&rjd); - - b2PrismaticJointDef pjd; - pjd.Initialize(ground, m_platform, b2Vec2(0.0f, 5.0f), b2Vec2(1.0f, 0.0f)); - - pjd.maxMotorForce = 1000.0f; - pjd.enableMotor = true; - pjd.lowerTranslation = -10.0f; - pjd.upperTranslation = 10.0f; - pjd.enableLimit = true; - - m_world->CreateJoint(&pjd); - - m_speed = 3.0f; - } - - // Create a payload - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 8.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.75f, 0.75f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.friction = 0.6f; - fd.density = 2.0f; - - body->CreateFixture(&fd); - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_D: - m_platform->SetType(b2_dynamicBody); - break; - - case GLFW_KEY_S: - m_platform->SetType(b2_staticBody); - break; - - case GLFW_KEY_K: - m_platform->SetType(b2_kinematicBody); - m_platform->SetLinearVelocity(b2Vec2(-m_speed, 0.0f)); - m_platform->SetAngularVelocity(0.0f); - break; - } - } - - void Step(Settings& settings) override - { - // Drive the kinematic body. - if (m_platform->GetType() == b2_kinematicBody) - { - b2Vec2 p = m_platform->GetTransform().p; - b2Vec2 v = m_platform->GetLinearVelocity(); - - if ((p.x < -10.0f && v.x < 0.0f) || (p.x > 10.0f && v.x > 0.0f)) - { - v.x = -v.x; - m_platform->SetLinearVelocity(v); - } - } - - Test::Step(settings); - - DrawString(5, m_textLine, "Keys: (d) dynamic, (s) static, (k) kinematic"); - } - - static Test* Create() { return new BodyTypes; } - - b2Body* m_attachment; - b2Body* m_platform; - float m_speed; -}; - -static int testIndex = RegisterTest("Examples", "Body Types", BodyTypes::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/box_stack.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/box_stack.cpp deleted file mode 100644 index 463d399b7f8e..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/box_stack.cpp +++ /dev/null @@ -1,170 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -extern B2_API bool g_blockSolve; - -class BoxStack : public Test -{ -public: - enum - { - e_columnCount = 1, - e_rowCount = 15 - // e_columnCount = 1, - // e_rowCount = 1 - }; - - BoxStack() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(b2Vec2(20.0f, 0.0f), b2Vec2(20.0f, 20.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - float xs[5] = {0.0f, -10.0f, -5.0f, 5.0f, 10.0f}; - - for (int32 j = 0; j < e_columnCount; ++j) - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - fd.friction = 0.3f; - - for (int i = 0; i < e_rowCount; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - - int32 n = j * e_rowCount + i; - b2Assert(n < e_rowCount * e_columnCount); - m_indices[n] = n; - bd.userData.pointer = n; - - float x = 0.0f; - // float x = RandomFloat(-0.02f, 0.02f); - // float x = i % 2 == 0 ? -0.01f : 0.01f; - bd.position.Set(xs[j] + x, 0.55f + 1.1f * i); - b2Body* body = m_world->CreateBody(&bd); - - m_bodies[n] = body; - - body->CreateFixture(&fd); - } - } - - m_bullet = NULL; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_COMMA: - if (m_bullet != NULL) - { - m_world->DestroyBody(m_bullet); - m_bullet = NULL; - } - - { - b2CircleShape shape; - shape.m_radius = 0.25f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.restitution = 0.05f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.bullet = true; - bd.position.Set(-31.0f, 5.0f); - - m_bullet = m_world->CreateBody(&bd); - m_bullet->CreateFixture(&fd); - - m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); - } - break; - - case GLFW_KEY_B: - g_blockSolve = !g_blockSolve; - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - DrawString(5, m_textLine, "Press: (,) to launch a bullet."); - - DrawString(5, m_textLine, "Blocksolve = %d", g_blockSolve); - if (m_stepCount == 300) - { - if (m_bullet != NULL) - { - m_world->DestroyBody(m_bullet); - m_bullet = NULL; - } - - { - b2CircleShape shape; - shape.m_radius = 0.25f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.restitution = 0.05f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.bullet = true; - bd.position.Set(-31.0f, 5.0f); - - m_bullet = m_world->CreateBody(&bd); - m_bullet->CreateFixture(&fd); - - m_bullet->SetLinearVelocity(b2Vec2(400.0f, 0.0f)); - } - } - } - - static Test* Create() { return new BoxStack; } - - b2Body* m_bullet; - b2Body* m_bodies[e_rowCount * e_columnCount]; - int32 m_indices[e_rowCount * e_columnCount]; -}; - -static int testIndex = RegisterTest("Stacking", "Boxes", BoxStack::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/breakable.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/breakable.cpp deleted file mode 100644 index 1128a56ef498..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/breakable.cpp +++ /dev/null @@ -1,154 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// This is used to test sensor shapes. -class Breakable : public Test -{ -public: - enum - { - e_count = 7 - }; - - Breakable() - { - // Ground body - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Breakable dynamic body - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 40.0f); - bd.angle = 0.25f * b2_pi; - m_body1 = m_world->CreateBody(&bd); - - m_shape1.SetAsBox(0.5f, 0.5f, b2Vec2(-0.5f, 0.0f), 0.0f); - m_piece1 = m_body1->CreateFixture(&m_shape1, 1.0f); - - m_shape2.SetAsBox(0.5f, 0.5f, b2Vec2(0.5f, 0.0f), 0.0f); - m_piece2 = m_body1->CreateFixture(&m_shape2, 1.0f); - } - - m_break = false; - m_broke = false; - } - - void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override - { - if (m_broke) - { - // The body already broke. - return; - } - - // Should the body break? - int32 count = contact->GetManifold()->pointCount; - - float maxImpulse = 0.0f; - for (int32 i = 0; i < count; ++i) - { - maxImpulse = b2Max(maxImpulse, impulse->normalImpulses[i]); - } - - if (maxImpulse > 40.0f) - { - // Flag the body for breaking. - m_break = true; - } - } - - void Break() - { - // Create two bodies from one. - b2Body* body1 = m_piece1->GetBody(); - b2Vec2 center = body1->GetWorldCenter(); - - body1->DestroyFixture(m_piece2); - m_piece2 = NULL; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = body1->GetPosition(); - bd.angle = body1->GetAngle(); - - b2Body* body2 = m_world->CreateBody(&bd); - m_piece2 = body2->CreateFixture(&m_shape2, 1.0f); - - // Compute consistent velocities for new bodies based on - // cached velocity. - b2Vec2 center1 = body1->GetWorldCenter(); - b2Vec2 center2 = body2->GetWorldCenter(); - - b2Vec2 velocity1 = m_velocity + b2Cross(m_angularVelocity, center1 - center); - b2Vec2 velocity2 = m_velocity + b2Cross(m_angularVelocity, center2 - center); - - body1->SetAngularVelocity(m_angularVelocity); - body1->SetLinearVelocity(velocity1); - - body2->SetAngularVelocity(m_angularVelocity); - body2->SetLinearVelocity(velocity2); - } - - void Step(Settings& settings) override - { - if (m_break) - { - Break(); - m_broke = true; - m_break = false; - } - - // Cache velocities to improve movement on breakage. - if (m_broke == false) - { - m_velocity = m_body1->GetLinearVelocity(); - m_angularVelocity = m_body1->GetAngularVelocity(); - } - - Test::Step(settings); - } - - static Test* Create() { return new Breakable; } - - b2Body* m_body1; - b2Vec2 m_velocity; - float m_angularVelocity; - b2PolygonShape m_shape1; - b2PolygonShape m_shape2; - b2Fixture* m_piece1; - b2Fixture* m_piece2; - - bool m_broke; - bool m_break; -}; - -static int testIndex = RegisterTest("Examples", "Breakable", Breakable::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/bridge.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/bridge.cpp deleted file mode 100644 index 8447bd43dd30..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/bridge.cpp +++ /dev/null @@ -1,124 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Bridge : public Test -{ -public: - enum - { - e_count = 30 - }; - - Bridge() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.friction = 0.2f; - - b2RevoluteJointDef jd; - - b2Body* prevBody = ground; - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-14.5f + 1.0f * i, 5.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - - if (i == (e_count >> 1)) - { - m_middle = body; - } - prevBody = body; - } - - b2Vec2 anchor(-15.0f + 1.0f * static_cast(e_count), 5.0f); - jd.Initialize(prevBody, ground, anchor); - m_world->CreateJoint(&jd); - } - - for (int32 i = 0; i < 2; ++i) - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.5f, 0.0f); - vertices[1].Set(0.5f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - - b2PolygonShape shape; - shape.Set(vertices, 3); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-8.0f + 8.0f * i, 12.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - } - - for (int32 i = 0; i < 3; ++i) - { - b2CircleShape shape; - shape.m_radius = 0.5f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-6.0f + 6.0f * i, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - } - } - - static Test* Create() { return new Bridge; } - - b2Body* m_middle; -}; - -static int testIndex = RegisterTest("Joints", "Bridge", Bridge::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/bullet_test.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/bullet_test.cpp deleted file mode 100644 index 945887da6f9c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/bullet_test.cpp +++ /dev/null @@ -1,132 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class BulletTest : public Test -{ -public: - BulletTest() - { - { - b2BodyDef bd; - bd.position.Set(0.0f, 0.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2EdgeShape edge; - - edge.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); - body->CreateFixture(&edge, 0.0f); - - b2PolygonShape shape; - shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); - body->CreateFixture(&shape, 0.0f); - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 4.0f); - - b2PolygonShape box; - box.SetAsBox(2.0f, 0.1f); - - m_body = m_world->CreateBody(&bd); - m_body->CreateFixture(&box, 1.0f); - - box.SetAsBox(0.25f, 0.25f); - - // m_x = RandomFloat(-1.0f, 1.0f); - m_x = 0.20352793f; - bd.position.Set(m_x, 10.0f); - bd.bullet = true; - - m_bullet = m_world->CreateBody(&bd); - m_bullet->CreateFixture(&box, 100.0f); - - m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); - } - } - - void Launch() - { - m_body->SetTransform(b2Vec2(0.0f, 4.0f), 0.0f); - m_body->SetLinearVelocity(b2Vec2_zero); - m_body->SetAngularVelocity(0.0f); - - m_x = RandomFloat(-1.0f, 1.0f); - m_bullet->SetTransform(b2Vec2(m_x, 10.0f), 0.0f); - m_bullet->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); - m_bullet->SetAngularVelocity(0.0f); - - extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - extern B2_API int32 b2_toiCalls, b2_toiIters, b2_toiMaxIters; - extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - - b2_gjkCalls = 0; - b2_gjkIters = 0; - b2_gjkMaxIters = 0; - - b2_toiCalls = 0; - b2_toiIters = 0; - b2_toiMaxIters = 0; - b2_toiRootIters = 0; - b2_toiMaxRootIters = 0; - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - extern B2_API int32 b2_toiCalls, b2_toiIters; - extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - - if (b2_gjkCalls > 0) - { - DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", b2_gjkCalls, - b2_gjkIters / float(b2_gjkCalls), b2_gjkMaxIters); - } - - if (b2_toiCalls > 0) - { - DrawString(5, m_textLine, "toi calls = %d, ave toi iters = %3.1f, max toi iters = %d", b2_toiCalls, - b2_toiIters / float(b2_toiCalls), b2_toiMaxRootIters); - - DrawString(5, m_textLine, "ave toi root iters = %3.1f, max toi root iters = %d", - b2_toiRootIters / float(b2_toiCalls), b2_toiMaxRootIters); - } - - if (m_stepCount % 60 == 0) - { - Launch(); - } - } - - static Test* Create() { return new BulletTest; } - - b2Body* m_body; - b2Body* m_bullet; - float m_x; -}; - -static int testIndex = RegisterTest("Continuous", "Bullet Test", BulletTest::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/cantilever.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/cantilever.cpp deleted file mode 100644 index 8a9ffce0b7cd..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/cantilever.cpp +++ /dev/null @@ -1,214 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// It is difficult to make a cantilever made of links completely rigid with weld joints. -// You will have to use a high number of iterations to make them stiff. -// So why not go ahead and use soft weld joints? They behave like a revolute -// joint with a rotational spring. -class Cantilever : public Test -{ -public: - enum - { - e_count = 8 - }; - - Cantilever() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - - b2WeldJointDef jd; - - b2Body* prevBody = ground; - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-14.5f + 1.0f * i, 5.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - b2Vec2 anchor(-15.0f + 1.0f * i, 5.0f); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - - prevBody = body; - } - } - - { - b2PolygonShape shape; - shape.SetAsBox(1.0f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - - b2WeldJointDef jd; - float frequencyHz = 5.0f; - float dampingRatio = 0.7f; - - b2Body* prevBody = ground; - for (int32 i = 0; i < 3; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-14.0f + 2.0f * i, 15.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - b2Vec2 anchor(-15.0f + 2.0f * i, 15.0f); - jd.Initialize(prevBody, body, anchor); - b2AngularStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_world->CreateJoint(&jd); - - prevBody = body; - } - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - - b2WeldJointDef jd; - - b2Body* prevBody = ground; - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-4.5f + 1.0f * i, 5.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - if (i > 0) - { - b2Vec2 anchor(-5.0f + 1.0f * i, 5.0f); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - } - - prevBody = body; - } - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - - b2WeldJointDef jd; - float frequencyHz = 8.0f; - float dampingRatio = 0.7f; - - b2Body* prevBody = ground; - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(5.5f + 1.0f * i, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - if (i > 0) - { - b2Vec2 anchor(5.0f + 1.0f * i, 10.0f); - jd.Initialize(prevBody, body, anchor); - - b2AngularStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, prevBody, body); - - m_world->CreateJoint(&jd); - } - - prevBody = body; - } - } - - for (int32 i = 0; i < 2; ++i) - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.5f, 0.0f); - vertices[1].Set(0.5f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - - b2PolygonShape shape; - shape.Set(vertices, 3); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-8.0f + 8.0f * i, 12.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - } - - for (int32 i = 0; i < 2; ++i) - { - b2CircleShape shape; - shape.m_radius = 0.5f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-6.0f + 6.0f * i, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - } - } - - static Test* Create() { return new Cantilever; } - - b2Body* m_middle; -}; - -static int testIndex = RegisterTest("Joints", "Cantilever", Cantilever::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/car.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/car.cpp deleted file mode 100644 index 2051641bde4f..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/car.cpp +++ /dev/null @@ -1,286 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto -// Copyright(c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "extensions/axmol-ext.h" - -USING_NS_AX_EXT; - -// This is a fun demo that shows off the wheel joint -class Car : public Test -{ -public: - Car() - { - m_speed = 50.0f; - - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 0.0f; - fd.friction = 0.6f; - - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - ground->CreateFixture(&fd); - - float hs[10] = {0.25f, 1.0f, 4.0f, 0.0f, 0.0f, -1.0f, -2.0f, -2.0f, -1.25f, 0.0f}; - - float x = 20.0f, y1 = 0.0f, dx = 5.0f; - - for (int32 i = 0; i < 10; ++i) - { - float y2 = hs[i]; - shape.SetTwoSided(b2Vec2(x, y1), b2Vec2(x + dx, y2)); - ground->CreateFixture(&fd); - y1 = y2; - x += dx; - } - - for (int32 i = 0; i < 10; ++i) - { - float y2 = hs[i]; - shape.SetTwoSided(b2Vec2(x, y1), b2Vec2(x + dx, y2)); - ground->CreateFixture(&fd); - y1 = y2; - x += dx; - } - - shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); - ground->CreateFixture(&fd); - - x += 80.0f; - shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); - ground->CreateFixture(&fd); - - x += 40.0f; - shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 10.0f, 5.0f)); - ground->CreateFixture(&fd); - - x += 20.0f; - shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x + 40.0f, 0.0f)); - ground->CreateFixture(&fd); - - x += 40.0f; - shape.SetTwoSided(b2Vec2(x, 0.0f), b2Vec2(x, 20.0f)); - ground->CreateFixture(&fd); - } - - // Teeter - { - b2BodyDef bd; - bd.position.Set(140.0f, 1.0f); - bd.type = b2_dynamicBody; - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape box; - box.SetAsBox(10.0f, 0.25f); - body->CreateFixture(&box, 1.0f); - - b2RevoluteJointDef jd; - jd.Initialize(ground, body, body->GetPosition()); - jd.lowerAngle = -8.0f * b2_pi / 180.0f; - jd.upperAngle = 8.0f * b2_pi / 180.0f; - jd.enableLimit = true; - m_world->CreateJoint(&jd); - - body->ApplyAngularImpulse(100.0f, true); - } - - // Bridge - { - int32 N = 20; - b2PolygonShape shape; - shape.SetAsBox(1.0f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - fd.friction = 0.6f; - - b2RevoluteJointDef jd; - - b2Body* prevBody = ground; - for (int32 i = 0; i < N; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(161.0f + 2.0f * i, -0.125f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - - b2Vec2 anchor(160.0f + 2.0f * i, -0.125f); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - - prevBody = body; - } - - b2Vec2 anchor(160.0f + 2.0f * N, -0.125f); - jd.Initialize(prevBody, ground, anchor); - m_world->CreateJoint(&jd); - } - - // Boxes - { - b2PolygonShape box; - box.SetAsBox(0.5f, 0.5f); - - b2Body* body = NULL; - b2BodyDef bd; - bd.type = b2_dynamicBody; - - bd.position.Set(230.0f, 0.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&box, 0.5f); - - bd.position.Set(230.0f, 1.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&box, 0.5f); - - bd.position.Set(230.0f, 2.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&box, 0.5f); - - bd.position.Set(230.0f, 3.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&box, 0.5f); - - bd.position.Set(230.0f, 4.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&box, 0.5f); - } - - // Car - { - b2PolygonShape chassis; - b2Vec2 vertices[8]; - vertices[0].Set(-1.5f, -0.5f); - vertices[1].Set(1.5f, -0.5f); - vertices[2].Set(1.5f, 0.0f); - vertices[3].Set(0.0f, 0.9f); - vertices[4].Set(-1.15f, 0.9f); - vertices[5].Set(-1.5f, 0.2f); - chassis.Set(vertices, 6); - - b2CircleShape circle; - circle.m_radius = 0.4f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 1.0f); - m_car = m_world->CreateBody(&bd); - m_car->CreateFixture(&chassis, 1.0f); - - b2FixtureDef fd; - fd.shape = &circle; - fd.density = 1.0f; - fd.friction = 0.9f; - - bd.position.Set(-1.0f, 0.35f); - m_wheel1 = m_world->CreateBody(&bd); - m_wheel1->CreateFixture(&fd); - - bd.position.Set(1.0f, 0.4f); - m_wheel2 = m_world->CreateBody(&bd); - m_wheel2->CreateFixture(&fd); - - b2WheelJointDef jd; - b2Vec2 axis(0.0f, 1.0f); - - float mass1 = m_wheel1->GetMass(); - float mass2 = m_wheel2->GetMass(); - - float hertz = 4.0f; - float dampingRatio = 0.7f; - float omega = 2.0f * b2_pi * hertz; - - jd.Initialize(m_car, m_wheel1, m_wheel1->GetPosition(), axis); - jd.motorSpeed = 0.0f; - jd.maxMotorTorque = 20.0f; - jd.enableMotor = true; - jd.stiffness = mass1 * omega * omega; - jd.damping = 2.0f * mass1 * dampingRatio * omega; - jd.lowerTranslation = -0.25f; - jd.upperTranslation = 0.25f; - jd.enableLimit = true; - m_spring1 = (b2WheelJoint*)m_world->CreateJoint(&jd); - - jd.Initialize(m_car, m_wheel2, m_wheel2->GetPosition(), axis); - jd.motorSpeed = 0.0f; - jd.maxMotorTorque = 10.0f; - jd.enableMotor = false; - jd.stiffness = mass2 * omega * omega; - jd.damping = 2.0f * mass2 * dampingRatio * omega; - jd.lowerTranslation = -0.25f; - jd.upperTranslation = 0.25f; - jd.enableLimit = true; - m_spring2 = (b2WheelJoint*)m_world->CreateJoint(&jd); - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_spring1->SetMotorSpeed(m_speed); - break; - - case GLFW_KEY_S: - m_spring1->SetMotorSpeed(0.0f); - break; - - case GLFW_KEY_D: - m_spring1->SetMotorSpeed(-m_speed); - break; - } - } - - void Step(Settings& settings) override - { - DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, hz down = q, hz up = e"); - - // g_camera.m_center.x = m_car->GetPosition().x; - g_debugDraw.debugNodeOffset.x += m_car->GetPosition().x; - - Test::Step(settings); - } - - static Test* Create() { return new Car; } - - b2Body* m_car; - b2Body* m_wheel1; - b2Body* m_wheel2; - - float m_speed; - b2WheelJoint* m_spring1; - b2WheelJoint* m_spring2; -}; - -static int testIndex = RegisterTest("Examples", "Car", Car::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/chain.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/chain.cpp deleted file mode 100644 index 3520b89330ca..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/chain.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -#define TEST_BAD_BODY 0 - -class Chain : public Test -{ -public: - Chain() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.6f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.friction = 0.2f; - - b2RevoluteJointDef jd; - jd.collideConnected = false; - - const float y = 25.0f; - b2Body* prevBody = ground; - for (int32 i = 0; i < 30; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.5f + i, y); - b2Body* body = m_world->CreateBody(&bd); - -#if TEST_BAD_BODY == 1 - if (i == 10) - { - // Test zero density dynamic body - fd.density = 0.0f; - } - else - { - fd.density = 20.0f; - } -#endif - - body->CreateFixture(&fd); - - b2Vec2 anchor(float(i), y); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - - prevBody = body; - } - } - } - - static Test* Create() { return new Chain; } -}; - -static int testIndex = RegisterTest("Joints", "Chain", Chain::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/chain_problem.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/chain_problem.cpp deleted file mode 100644 index a9a48a87301d..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/chain_problem.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class ChainProblem : public Test -{ -public: - ChainProblem() - { - { - b2Vec2 g(0.0f, -10.0f); - m_world->SetGravity(g); - b2Body** bodies = (b2Body**)b2Alloc(2 * sizeof(b2Body*)); - b2Joint** joints = (b2Joint**)b2Alloc(0 * sizeof(b2Joint*)); - { - b2BodyDef bd; - bd.type = b2BodyType(0); - bodies[0] = m_world->CreateBody(&bd); - - { - b2FixtureDef fd; - - b2Vec2 v1(0.0f, 1.0f); - b2Vec2 v2(0.0f, 0.0f); - b2Vec2 v3(4.0f, 0.0f); - - b2EdgeShape shape; - shape.SetTwoSided(v1, v2); - bodies[0]->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v2, v3); - bodies[0]->CreateFixture(&shape, 0.0f); - } - } - { - b2BodyDef bd; - bd.type = b2BodyType(2); - // bd.position.Set(6.033980250358582e-01f, 3.028350114822388e+00f); - bd.position.Set(1.0f, 3.0f); - bodies[1] = m_world->CreateBody(&bd); - - { - b2FixtureDef fd; - fd.friction = 0.2f; - fd.density = 10.0f; - b2PolygonShape shape; - b2Vec2 vs[8]; - vs[0].Set(0.5f, -3.0f); - vs[1].Set(0.5f, 3.0f); - vs[2].Set(-0.5f, 3.0f); - vs[3].Set(-0.5f, -3.0f); - shape.Set(vs, 4); - - fd.shape = &shape; - - bodies[1]->CreateFixture(&fd); - } - } - b2Free(joints); - b2Free(bodies); - joints = NULL; - bodies = NULL; - } - } - - static Test* Create() { return new ChainProblem; } -}; - -static int testIndex = RegisterTest("Bugs", "Chain Problem", ChainProblem::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/character_collision.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/character_collision.cpp deleted file mode 100644 index 42f9f81d6f98..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/character_collision.cpp +++ /dev/null @@ -1,252 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -/// This is a test of typical character collision scenarios. This does not -/// show how you should implement a character in your application. -/// Instead this is used to test smooth collision on edge chains. -class CharacterCollision : public Test -{ -public: - CharacterCollision() - { - // Ground body - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Collinear edges with no adjacency information. - // This shows the problematic case where a box shape can hit - // an internal vertex. - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-8.0f, 1.0f), b2Vec2(-6.0f, 1.0f)); - ground->CreateFixture(&shape, 0.0f); - shape.SetTwoSided(b2Vec2(-6.0f, 1.0f), b2Vec2(-4.0f, 1.0f)); - ground->CreateFixture(&shape, 0.0f); - shape.SetTwoSided(b2Vec2(-4.0f, 1.0f), b2Vec2(-2.0f, 1.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Chain shape - { - b2BodyDef bd; - bd.angle = 0.25f * b2_pi; - b2Body* ground = m_world->CreateBody(&bd); - - b2Vec2 vs[4]; - vs[0].Set(5.0f, 7.0f); - vs[1].Set(6.0f, 8.0f); - vs[2].Set(7.0f, 8.0f); - vs[3].Set(8.0f, 7.0f); - b2ChainShape shape; - shape.CreateLoop(vs, 4); - ground->CreateFixture(&shape, 0.0f); - } - - // Square tiles. This shows that adjacency shapes may - // have non-smooth collision. There is no solution - // to this problem. - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(1.0f, 1.0f, b2Vec2(4.0f, 3.0f), 0.0f); - ground->CreateFixture(&shape, 0.0f); - shape.SetAsBox(1.0f, 1.0f, b2Vec2(6.0f, 3.0f), 0.0f); - ground->CreateFixture(&shape, 0.0f); - shape.SetAsBox(1.0f, 1.0f, b2Vec2(8.0f, 3.0f), 0.0f); - ground->CreateFixture(&shape, 0.0f); - } - - // Square made from an edge loop. Collision should be smooth. - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2Vec2 vs[4]; - vs[0].Set(-1.0f, 3.0f); - vs[1].Set(1.0f, 3.0f); - vs[2].Set(1.0f, 5.0f); - vs[3].Set(-1.0f, 5.0f); - b2ChainShape shape; - shape.CreateLoop(vs, 4); - ground->CreateFixture(&shape, 0.0f); - } - - // Edge loop. Collision should be smooth. - { - b2BodyDef bd; - bd.position.Set(-10.0f, 4.0f); - b2Body* ground = m_world->CreateBody(&bd); - - b2Vec2 vs[10]; - vs[0].Set(0.0f, 0.0f); - vs[1].Set(6.0f, 0.0f); - vs[2].Set(6.0f, 2.0f); - vs[3].Set(4.0f, 1.0f); - vs[4].Set(2.0f, 2.0f); - vs[5].Set(0.0f, 2.0f); - vs[6].Set(-2.0f, 2.0f); - vs[7].Set(-4.0f, 3.0f); - vs[8].Set(-6.0f, 2.0f); - vs[9].Set(-6.0f, 0.0f); - b2ChainShape shape; - shape.CreateLoop(vs, 10); - ground->CreateFixture(&shape, 0.0f); - } - - // Square character 1 - { - b2BodyDef bd; - bd.position.Set(-3.0f, 8.0f); - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.allowSleep = false; - - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - body->CreateFixture(&fd); - } - - // Square character 2 - { - b2BodyDef bd; - bd.position.Set(-5.0f, 5.0f); - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.allowSleep = false; - - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.25f, 0.25f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - body->CreateFixture(&fd); - } - - // Hexagon character - { - b2BodyDef bd; - bd.position.Set(-5.0f, 8.0f); - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.allowSleep = false; - - b2Body* body = m_world->CreateBody(&bd); - - float angle = 0.0f; - float delta = b2_pi / 3.0f; - b2Vec2 vertices[6]; - for (int32 i = 0; i < 6; ++i) - { - vertices[i].Set(0.5f * cosf(angle), 0.5f * sinf(angle)); - angle += delta; - } - - b2PolygonShape shape; - shape.Set(vertices, 6); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - body->CreateFixture(&fd); - } - - // Circle character - { - b2BodyDef bd; - bd.position.Set(3.0f, 5.0f); - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.allowSleep = false; - - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.5f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - body->CreateFixture(&fd); - } - - // Circle character - { - b2BodyDef bd; - bd.position.Set(-7.0f, 6.0f); - bd.type = b2_dynamicBody; - bd.allowSleep = false; - - m_character = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.25f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.friction = 1.0f; - m_character->CreateFixture(&fd); - } - } - - void Step(Settings& settings) override - { - b2Vec2 v = m_character->GetLinearVelocity(); - v.x = -5.0f; - m_character->SetLinearVelocity(v); - - Test::Step(settings); - DrawString(5, m_textLine, "This tests various character collision shapes."); - - DrawString(5, m_textLine, "Limitation: square and hexagon can snag on aligned boxes."); - - DrawString(5, m_textLine, "Feature: edge chains have smooth collision inside and out."); - } - - static Test* Create() { return new CharacterCollision; } - - b2Body* m_character; -}; - -static int testIndex = RegisterTest("Examples", "Character Collision", CharacterCollision::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/circle_stack.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/circle_stack.cpp deleted file mode 100644 index d642a12d33e2..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/circle_stack.cpp +++ /dev/null @@ -1,85 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class CircleStack : public Test -{ -public: - enum - { - e_count = 10 - }; - - CircleStack() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2CircleShape shape; - shape.m_radius = 1.0f; - - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0, 4.0f + 3.0f * i); - - m_bodies[i] = m_world->CreateBody(&bd); - - m_bodies[i]->CreateFixture(&shape, 1.0f); - - m_bodies[i]->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); - } - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - // for (int32 i = 0; i < e_count; ++i) - //{ - // printf("%g ", m_bodies[i]->GetWorldCenter().y); - // } - - // for (int32 i = 0; i < e_count; ++i) - //{ - // printf("%g ", m_bodies[i]->GetLinearVelocity().y); - // } - - // printf("\n"); - } - - static Test* Create() { return new CircleStack; } - - b2Body* m_bodies[e_count]; -}; - -static int testIndex = RegisterTest("Stacking", "Circles", CircleStack::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/collision_filtering.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/collision_filtering.cpp deleted file mode 100644 index 65acb3866862..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/collision_filtering.cpp +++ /dev/null @@ -1,176 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// This is a test of collision filtering. -// There is a triangle, a box, and a circle. -// There are 6 shapes. 3 large and 3 small. -// The 3 small ones always collide. -// The 3 large ones never collide. -// The boxes don't collide with triangles (except if both are small). -const int16 k_smallGroup = 1; -const int16 k_largeGroup = -1; - -const uint16 k_triangleCategory = 0x0002; -const uint16 k_boxCategory = 0x0004; -const uint16 k_circleCategory = 0x0008; - -const uint16 k_triangleMask = 0xFFFF; -const uint16 k_boxMask = 0xFFFF ^ k_triangleCategory; -const uint16 k_circleMask = 0xFFFF; - -class CollisionFiltering : public Test -{ -public: - CollisionFiltering() - { - // Ground body - { - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - - b2FixtureDef sd; - sd.shape = &shape; - sd.friction = 0.3f; - - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&sd); - } - - // Small triangle - b2Vec2 vertices[3]; - vertices[0].Set(-1.0f, 0.0f); - vertices[1].Set(1.0f, 0.0f); - vertices[2].Set(0.0f, 2.0f); - b2PolygonShape polygon; - polygon.Set(vertices, 3); - - b2FixtureDef triangleShapeDef; - triangleShapeDef.shape = &polygon; - triangleShapeDef.density = 1.0f; - - triangleShapeDef.filter.groupIndex = k_smallGroup; - triangleShapeDef.filter.categoryBits = k_triangleCategory; - triangleShapeDef.filter.maskBits = k_triangleMask; - - b2BodyDef triangleBodyDef; - triangleBodyDef.type = b2_dynamicBody; - triangleBodyDef.position.Set(-5.0f, 2.0f); - - b2Body* body1 = m_world->CreateBody(&triangleBodyDef); - body1->CreateFixture(&triangleShapeDef); - - // Large triangle (recycle definitions) - vertices[0] *= 2.0f; - vertices[1] *= 2.0f; - vertices[2] *= 2.0f; - polygon.Set(vertices, 3); - triangleShapeDef.filter.groupIndex = k_largeGroup; - triangleBodyDef.position.Set(-5.0f, 6.0f); - triangleBodyDef.fixedRotation = true; // look at me! - - b2Body* body2 = m_world->CreateBody(&triangleBodyDef); - body2->CreateFixture(&triangleShapeDef); - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-5.0f, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape p; - p.SetAsBox(0.5f, 1.0f); - body->CreateFixture(&p, 1.0f); - - b2PrismaticJointDef jd; - jd.bodyA = body2; - jd.bodyB = body; - jd.enableLimit = true; - jd.localAnchorA.Set(0.0f, 4.0f); - jd.localAnchorB.SetZero(); - jd.localAxisA.Set(0.0f, 1.0f); - jd.lowerTranslation = -1.0f; - jd.upperTranslation = 1.0f; - - m_world->CreateJoint(&jd); - } - - // Small box - polygon.SetAsBox(1.0f, 0.5f); - b2FixtureDef boxShapeDef; - boxShapeDef.shape = &polygon; - boxShapeDef.density = 1.0f; - boxShapeDef.restitution = 0.1f; - - boxShapeDef.filter.groupIndex = k_smallGroup; - boxShapeDef.filter.categoryBits = k_boxCategory; - boxShapeDef.filter.maskBits = k_boxMask; - - b2BodyDef boxBodyDef; - boxBodyDef.type = b2_dynamicBody; - boxBodyDef.position.Set(0.0f, 2.0f); - - b2Body* body3 = m_world->CreateBody(&boxBodyDef); - body3->CreateFixture(&boxShapeDef); - - // Large box (recycle definitions) - polygon.SetAsBox(2.0f, 1.0f); - boxShapeDef.filter.groupIndex = k_largeGroup; - boxBodyDef.position.Set(0.0f, 6.0f); - - b2Body* body4 = m_world->CreateBody(&boxBodyDef); - body4->CreateFixture(&boxShapeDef); - - // Small circle - b2CircleShape circle; - circle.m_radius = 1.0f; - - b2FixtureDef circleShapeDef; - circleShapeDef.shape = &circle; - circleShapeDef.density = 1.0f; - - circleShapeDef.filter.groupIndex = k_smallGroup; - circleShapeDef.filter.categoryBits = k_circleCategory; - circleShapeDef.filter.maskBits = k_circleMask; - - b2BodyDef circleBodyDef; - circleBodyDef.type = b2_dynamicBody; - circleBodyDef.position.Set(5.0f, 2.0f); - - b2Body* body5 = m_world->CreateBody(&circleBodyDef); - body5->CreateFixture(&circleShapeDef); - - // Large circle - circle.m_radius *= 2.0f; - circleShapeDef.filter.groupIndex = k_largeGroup; - circleBodyDef.position.Set(5.0f, 6.0f); - - b2Body* body6 = m_world->CreateBody(&circleBodyDef); - body6->CreateFixture(&circleShapeDef); - } - - static Test* Create() { return new CollisionFiltering; } -}; - -static int testIndex = RegisterTest("Examples", "Collision Filtering", CollisionFiltering::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/collision_processing.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/collision_processing.cpp deleted file mode 100644 index f31db91a3b7d..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/collision_processing.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -#include - -// This test shows collision processing and tests -// deferred body destruction. -class CollisionProcessing : public Test -{ -public: - CollisionProcessing() - { - // Ground body - { - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); - - b2FixtureDef sd; - sd.shape = &shape; - ; - - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&sd); - } - - float xLo = -5.0f, xHi = 5.0f; - float yLo = 2.0f, yHi = 35.0f; - - // Small triangle - b2Vec2 vertices[3]; - vertices[0].Set(-1.0f, 0.0f); - vertices[1].Set(1.0f, 0.0f); - vertices[2].Set(0.0f, 2.0f); - - b2PolygonShape polygon; - polygon.Set(vertices, 3); - - b2FixtureDef triangleShapeDef; - triangleShapeDef.shape = &polygon; - triangleShapeDef.density = 1.0f; - - b2BodyDef triangleBodyDef; - triangleBodyDef.type = b2_dynamicBody; - triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body1 = m_world->CreateBody(&triangleBodyDef); - body1->CreateFixture(&triangleShapeDef); - - // Large triangle (recycle definitions) - vertices[0] *= 2.0f; - vertices[1] *= 2.0f; - vertices[2] *= 2.0f; - polygon.Set(vertices, 3); - - triangleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body2 = m_world->CreateBody(&triangleBodyDef); - body2->CreateFixture(&triangleShapeDef); - - // Small box - polygon.SetAsBox(1.0f, 0.5f); - - b2FixtureDef boxShapeDef; - boxShapeDef.shape = &polygon; - boxShapeDef.density = 1.0f; - - b2BodyDef boxBodyDef; - boxBodyDef.type = b2_dynamicBody; - boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body3 = m_world->CreateBody(&boxBodyDef); - body3->CreateFixture(&boxShapeDef); - - // Large box (recycle definitions) - polygon.SetAsBox(2.0f, 1.0f); - boxBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body4 = m_world->CreateBody(&boxBodyDef); - body4->CreateFixture(&boxShapeDef); - - // Small circle - b2CircleShape circle; - circle.m_radius = 1.0f; - - b2FixtureDef circleShapeDef; - circleShapeDef.shape = &circle; - circleShapeDef.density = 1.0f; - - b2BodyDef circleBodyDef; - circleBodyDef.type = b2_dynamicBody; - circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body5 = m_world->CreateBody(&circleBodyDef); - body5->CreateFixture(&circleShapeDef); - - // Large circle - circle.m_radius *= 2.0f; - circleBodyDef.position.Set(RandomFloat(xLo, xHi), RandomFloat(yLo, yHi)); - - b2Body* body6 = m_world->CreateBody(&circleBodyDef); - body6->CreateFixture(&circleShapeDef); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - // We are going to destroy some bodies according to contact - // points. We must buffer the bodies that should be destroyed - // because they may belong to multiple contact points. - const int32 k_maxNuke = 6; - b2Body* nuke[k_maxNuke]; - int32 nukeCount = 0; - - // Traverse the contact results. Destroy bodies that - // are touching heavier bodies. - for (int32 i = 0; i < m_pointCount; ++i) - { - ContactPoint* point = m_points + i; - - b2Body* body1 = point->fixtureA->GetBody(); - b2Body* body2 = point->fixtureB->GetBody(); - float mass1 = body1->GetMass(); - float mass2 = body2->GetMass(); - - if (mass1 > 0.0f && mass2 > 0.0f) - { - if (mass2 > mass1) - { - nuke[nukeCount++] = body1; - } - else - { - nuke[nukeCount++] = body2; - } - - if (nukeCount == k_maxNuke) - { - break; - } - } - } - - // Sort the nuke array to group duplicates. - std::sort(nuke, nuke + nukeCount); - - // Destroy the bodies, skipping duplicates. - int32 i = 0; - while (i < nukeCount) - { - b2Body* b = nuke[i++]; - while (i < nukeCount && nuke[i] == b) - { - ++i; - } - - if (b != m_bomb) - { - m_world->DestroyBody(b); - } - } - } - - static Test* Create() { return new CollisionProcessing; } -}; - -static int testIndex = RegisterTest("Examples", "Collision Processing", CollisionProcessing::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/compound_shapes.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/compound_shapes.cpp deleted file mode 100644 index bb3d7579fbcc..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/compound_shapes.cpp +++ /dev/null @@ -1,224 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -class CompoundShapes : public Test -{ -public: - CompoundShapes() - { - { - b2BodyDef bd; - bd.position.Set(0.0f, 0.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); - - body->CreateFixture(&shape, 0.0f); - } - - // Table 1 - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-15.0f, 1.0f); - m_table1 = m_world->CreateBody(&bd); - - b2PolygonShape top; - top.SetAsBox(3.0f, 0.5f, b2Vec2(0.0f, 3.5f), 0.0f); - - b2PolygonShape leftLeg; - leftLeg.SetAsBox(0.5f, 1.5f, b2Vec2(-2.5f, 1.5f), 0.0f); - - b2PolygonShape rightLeg; - rightLeg.SetAsBox(0.5f, 1.5f, b2Vec2(2.5f, 1.5f), 0.0f); - - m_table1->CreateFixture(&top, 2.0f); - m_table1->CreateFixture(&leftLeg, 2.0f); - m_table1->CreateFixture(&rightLeg, 2.0f); - } - - // Table 2 - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-5.0f, 1.0f); - m_table2 = m_world->CreateBody(&bd); - - b2PolygonShape top; - top.SetAsBox(3.0f, 0.5f, b2Vec2(0.0f, 3.5f), 0.0f); - - b2PolygonShape leftLeg; - leftLeg.SetAsBox(0.5f, 2.0f, b2Vec2(-2.5f, 2.0f), 0.0f); - - b2PolygonShape rightLeg; - rightLeg.SetAsBox(0.5f, 2.0f, b2Vec2(2.5f, 2.0f), 0.0f); - - m_table2->CreateFixture(&top, 2.0f); - m_table2->CreateFixture(&leftLeg, 2.0f); - m_table2->CreateFixture(&rightLeg, 2.0f); - } - - // Spaceship 1 - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(5.0f, 1.0f); - m_ship1 = m_world->CreateBody(&bd); - - b2Vec2 vertices[3]; - - b2PolygonShape left; - vertices[0].Set(-2.0f, 0.0f); - vertices[1].Set(0.0f, 4.0f / 3.0f); - vertices[2].Set(0.0f, 4.0f); - left.Set(vertices, 3); - - b2PolygonShape right; - vertices[0].Set(2.0f, 0.0f); - vertices[1].Set(0.0f, 4.0f / 3.0f); - vertices[2].Set(0.0f, 4.0f); - right.Set(vertices, 3); - - m_ship1->CreateFixture(&left, 2.0f); - m_ship1->CreateFixture(&right, 2.0f); - } - - // Spaceship 2 - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(15.0f, 1.0f); - m_ship2 = m_world->CreateBody(&bd); - - b2Vec2 vertices[3]; - - b2PolygonShape left; - vertices[0].Set(-2.0f, 0.0f); - vertices[1].Set(1.0f, 2.0f); - vertices[2].Set(0.0f, 4.0f); - left.Set(vertices, 3); - - b2PolygonShape right; - vertices[0].Set(2.0f, 0.0f); - vertices[1].Set(-1.0f, 2.0f); - vertices[2].Set(0.0f, 4.0f); - right.Set(vertices, 3); - - m_ship2->CreateFixture(&left, 2.0f); - m_ship2->CreateFixture(&right, 2.0f); - } - } - - void Spawn() - { - // Table 1 obstruction - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = m_table1->GetPosition(); - bd.angle = m_table1->GetAngle(); - - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape box; - box.SetAsBox(4.0f, 0.1f, b2Vec2(0.0f, 3.0f), 0.0f); - - body->CreateFixture(&box, 2.0f); - } - - // Table 2 obstruction - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = m_table2->GetPosition(); - bd.angle = m_table2->GetAngle(); - - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape box; - box.SetAsBox(4.0f, 0.1f, b2Vec2(0.0f, 3.0f), 0.0f); - - body->CreateFixture(&box, 2.0f); - } - - // Ship 1 obstruction - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = m_ship1->GetPosition(); - bd.angle = m_ship1->GetAngle(); - bd.gravityScale = 0.0f; - - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape circle; - circle.m_radius = 0.5f; - circle.m_p.Set(0.0f, 2.0f); - - body->CreateFixture(&circle, 2.0f); - } - - // Ship 2 obstruction - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = m_ship2->GetPosition(); - bd.angle = m_ship2->GetAngle(); - bd.gravityScale = 0.0f; - - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape circle; - circle.m_radius = 0.5f; - circle.m_p.Set(0.0f, 2.0f); - - body->CreateFixture(&circle, 2.0f); - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Button("Spawn")) - { - Spawn(); - } - - ImGui::End(); - } - - static Test* Create() { return new CompoundShapes; } - - b2Body* m_table1; - b2Body* m_table2; - b2Body* m_ship1; - b2Body* m_ship2; -}; - -static int testIndex = RegisterTest("Examples", "Compound Shapes", CompoundShapes::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/confined.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/confined.cpp deleted file mode 100644 index 44e2f6201036..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/confined.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Confined : public Test -{ -public: - enum - { - e_columnCount = 0, - e_rowCount = 0 - }; - - Confined() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - - // Floor - shape.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - - // Left wall - shape.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(-10.0f, 20.0f)); - ground->CreateFixture(&shape, 0.0f); - - // Right wall - shape.SetTwoSided(b2Vec2(10.0f, 0.0f), b2Vec2(10.0f, 20.0f)); - ground->CreateFixture(&shape, 0.0f); - - // Roof - shape.SetTwoSided(b2Vec2(-10.0f, 20.0f), b2Vec2(10.0f, 20.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - float radius = 0.5f; - b2CircleShape shape; - shape.m_p.SetZero(); - shape.m_radius = radius; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - fd.friction = 0.1f; - - for (int32 j = 0; j < e_columnCount; ++j) - { - for (int i = 0; i < e_rowCount; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f + (2.1f * j + 1.0f + 0.01f * i) * radius, (2.0f * i + 1.0f) * radius); - b2Body* body = m_world->CreateBody(&bd); - - body->CreateFixture(&fd); - } - } - - m_world->SetGravity(b2Vec2(0.0f, 0.0f)); - } - - void CreateCircle() - { - float radius = 2.0f; - b2CircleShape shape; - shape.m_p.SetZero(); - shape.m_radius = radius; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - fd.friction = 0.0f; - - b2Vec2 p(RandomFloat(), 3.0f + RandomFloat()); - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = p; - // bd.allowSleep = false; - b2Body* body = m_world->CreateBody(&bd); - - body->CreateFixture(&fd); - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_C: - CreateCircle(); - break; - } - } - - void Step(Settings& settings) override - { - bool sleeping = true; - for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) - { - if (b->GetType() != b2_dynamicBody) - { - continue; - } - - if (b->IsAwake()) - { - sleeping = false; - } - } - - if (m_stepCount == 180) - { - m_stepCount += 0; - } - - // if (sleeping) - //{ - // CreateCircle(); - // } - - Test::Step(settings); - - for (b2Body* b = m_world->GetBodyList(); b; b = b->GetNext()) - { - if (b->GetType() != b2_dynamicBody) - { - continue; - } - - b2Vec2 p = b->GetPosition(); - if (p.x <= -10.0f || 10.0f <= p.x || p.y <= 0.0f || 20.0f <= p.y) - { - p.x += 0.0f; - } - } - - DrawString(5, m_textLine, "Press 'c' to create a circle."); - } - - static Test* Create() { return new Confined; } -}; - -static int testIndex = RegisterTest("Solver", "Confined", Confined::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/continuous_test.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/continuous_test.cpp deleted file mode 100644 index 80187d9daaad..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/continuous_test.cpp +++ /dev/null @@ -1,162 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class ContinuousTest : public Test -{ -public: - ContinuousTest() - { - { - b2BodyDef bd; - bd.position.Set(0.0f, 0.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2EdgeShape edge; - - edge.SetTwoSided(b2Vec2(-10.0f, 0.0f), b2Vec2(10.0f, 0.0f)); - body->CreateFixture(&edge, 0.0f); - - b2PolygonShape shape; - shape.SetAsBox(0.2f, 1.0f, b2Vec2(0.5f, 1.0f), 0.0f); - body->CreateFixture(&shape, 0.0f); - } - -#if 1 - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 20.0f); - // bd.angle = 0.1f; - - b2PolygonShape shape; - shape.SetAsBox(2.0f, 0.1f); - - m_body = m_world->CreateBody(&bd); - m_body->CreateFixture(&shape, 1.0f); - - m_angularVelocity = RandomFloat(-50.0f, 50.0f); - // m_angularVelocity = 46.661274f; - m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); - m_body->SetAngularVelocity(m_angularVelocity); - } -#else - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 2.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_p.SetZero(); - shape.m_radius = 0.5f; - body->CreateFixture(&shape, 1.0f); - - bd.bullet = true; - bd.position.Set(0.0f, 10.0f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 1.0f); - body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); - } -#endif - - extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - extern B2_API int32 b2_toiCalls, b2_toiIters; - extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - extern B2_API float b2_toiTime, b2_toiMaxTime; - - b2_gjkCalls = 0; - b2_gjkIters = 0; - b2_gjkMaxIters = 0; - b2_toiCalls = 0; - b2_toiIters = 0; - b2_toiRootIters = 0; - b2_toiMaxRootIters = 0; - b2_toiTime = 0.0f; - b2_toiMaxTime = 0.0f; - } - - void Launch() - { - extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - extern B2_API int32 b2_toiCalls, b2_toiIters; - extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - extern B2_API float b2_toiTime, b2_toiMaxTime; - - b2_gjkCalls = 0; - b2_gjkIters = 0; - b2_gjkMaxIters = 0; - b2_toiCalls = 0; - b2_toiIters = 0; - b2_toiRootIters = 0; - b2_toiMaxRootIters = 0; - b2_toiTime = 0.0f; - b2_toiMaxTime = 0.0f; - - m_body->SetTransform(b2Vec2(0.0f, 20.0f), 0.0f); - m_angularVelocity = RandomFloat(-50.0f, 50.0f); - m_body->SetLinearVelocity(b2Vec2(0.0f, -100.0f)); - m_body->SetAngularVelocity(m_angularVelocity); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - extern B2_API int32 b2_gjkCalls, b2_gjkIters, b2_gjkMaxIters; - - if (b2_gjkCalls > 0) - { - DrawString(5, m_textLine, "gjk calls = %d, ave gjk iters = %3.1f, max gjk iters = %d", b2_gjkCalls, - b2_gjkIters / float(b2_gjkCalls), b2_gjkMaxIters); - } - - extern B2_API int32 b2_toiCalls, b2_toiIters; - extern B2_API int32 b2_toiRootIters, b2_toiMaxRootIters; - extern B2_API float b2_toiTime, b2_toiMaxTime; - - if (b2_toiCalls > 0) - { - DrawString(5, m_textLine, "toi calls = %d, ave [max] toi iters = %3.1f [%d]", b2_toiCalls, - b2_toiIters / float(b2_toiCalls), b2_toiMaxRootIters); - - DrawString(5, m_textLine, "ave [max] toi root iters = %3.1f [%d]", b2_toiRootIters / float(b2_toiCalls), - b2_toiMaxRootIters); - - DrawString(5, m_textLine, "ave [max] toi time = %.1f [%.1f] (microseconds)", - 1000.0f * b2_toiTime / float(b2_toiCalls), 1000.0f * b2_toiMaxTime); - } - - if (m_stepCount % 60 == 0) - { - Launch(); - } - } - - static Test* Create() { return new ContinuousTest; } - - b2Body* m_body; - float m_angularVelocity; -}; - -static int testIndex = RegisterTest("Continuous", "Continuous Test", ContinuousTest::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/convex_hull.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/convex_hull.cpp deleted file mode 100644 index 44f4da8906e5..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/convex_hull.cpp +++ /dev/null @@ -1,108 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class ConvexHull : public Test -{ -public: - enum - { - e_count = b2_maxPolygonVertices - }; - - ConvexHull() - { - Generate(); - m_auto = false; - } - - void Generate() - { - b2Vec2 lowerBound(-8.0f, -8.0f); - b2Vec2 upperBound(8.0f, 8.0f); - - for (int32 i = 0; i < e_count; ++i) - { - float x = 10.0f * RandomFloat(); - float y = 10.0f * RandomFloat(); - - // Clamp onto a square to help create collinearities. - // This will stress the convex hull algorithm. - b2Vec2 v(x, y); - v = b2Clamp(v, lowerBound, upperBound); - m_points[i] = v; - } - - m_count = e_count; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_auto = !m_auto; - break; - - case GLFW_KEY_G: - Generate(); - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - b2PolygonShape shape; - shape.Set(m_points, m_count); - - DrawString(5, m_textLine, "Press g to generate a new random convex hull"); - - g_debugDraw.DrawPolygon(shape.m_vertices, shape.m_count, b2Color(0.9f, 0.9f, 0.9f)); - - for (int32 i = 0; i < m_count; ++i) - { - g_debugDraw.DrawPoint(m_points[i], 3.0f, b2Color(0.3f, 0.9f, 0.3f)); - DrawString(m_points[i] + b2Vec2(0.05f, 0.05f), "%d", i); - } - - if (shape.Validate() == false) - { - m_textLine += 0; - } - - if (m_auto) - { - Generate(); - } - } - - static Test* Create() { return new ConvexHull; } - - b2Vec2 m_points[b2_maxPolygonVertices]; - int32 m_count; - bool m_auto; -}; - -static int testIndex = RegisterTest("Geometry", "Convex Hull", ConvexHull::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/conveyor_belt.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/conveyor_belt.cpp deleted file mode 100644 index 967ff5826369..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/conveyor_belt.cpp +++ /dev/null @@ -1,94 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class ConveyorBelt : public Test -{ -public: - ConveyorBelt() - { - // Ground - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Platform - { - b2BodyDef bd; - bd.position.Set(-5.0f, 5.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(10.0f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.friction = 0.8f; - m_platform = body->CreateFixture(&fd); - } - - // Boxes - for (int32 i = 0; i < 5; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f + 2.0f * i, 7.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - body->CreateFixture(&shape, 20.0f); - } - } - - void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override - { - Test::PreSolve(contact, oldManifold); - - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - - if (fixtureA == m_platform) - { - contact->SetTangentSpeed(5.0f); - } - - if (fixtureB == m_platform) - { - contact->SetTangentSpeed(-5.0f); - } - } - - void Step(Settings& settings) override { Test::Step(settings); } - - static Test* Create() { return new ConveyorBelt; } - - b2Fixture* m_platform; -}; - -static int testIndex = RegisterTest("Examples", "Conveyor Belt", ConveyorBelt::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/distance_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/distance_joint.cpp deleted file mode 100644 index 96eded3cf53c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/distance_joint.cpp +++ /dev/null @@ -1,120 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -// This tests distance joints, body destruction, and joint destruction. -class DistanceJoint : public Test -{ -public: - DistanceJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.angularDamping = 0.1f; - - bd.position.Set(0.0f, 5.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - body->CreateFixture(&shape, 5.0f); - - m_hertz = 1.0f; - m_dampingRatio = 0.7f; - - b2DistanceJointDef jd; - jd.Initialize(ground, body, b2Vec2(0.0f, 15.0f), bd.position); - jd.collideConnected = true; - m_length = jd.length; - m_minLength = m_length; - m_maxLength = m_length; - b2LinearStiffness(jd.stiffness, jd.damping, m_hertz, m_dampingRatio, jd.bodyA, jd.bodyB); - m_joint = (b2DistanceJoint*)m_world->CreateJoint(&jd); - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(260.0f, 150.0f)); - ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::SliderFloat("Length", &m_length, 0.0f, 20.0f, "%.0f")) - { - m_length = m_joint->SetLength(m_length); - } - - if (ImGui::SliderFloat("Min Length", &m_minLength, 0.0f, 20.0f, "%.0f")) - { - m_minLength = m_joint->SetMinLength(m_minLength); - } - - if (ImGui::SliderFloat("Max Length", &m_maxLength, 0.0f, 20.0f, "%.0f")) - { - m_maxLength = m_joint->SetMaxLength(m_maxLength); - } - - if (ImGui::SliderFloat("Hertz", &m_hertz, 0.0f, 10.0f, "%.1f")) - { - float stiffness; - float damping; - b2LinearStiffness(stiffness, damping, m_hertz, m_dampingRatio, m_joint->GetBodyA(), m_joint->GetBodyB()); - m_joint->SetStiffness(stiffness); - m_joint->SetDamping(damping); - } - - if (ImGui::SliderFloat("Damping Ratio", &m_dampingRatio, 0.0f, 2.0f, "%.1f")) - { - float stiffness; - float damping; - b2LinearStiffness(stiffness, damping, m_hertz, m_dampingRatio, m_joint->GetBodyA(), m_joint->GetBodyB()); - m_joint->SetStiffness(stiffness); - m_joint->SetDamping(damping); - } - - ImGui::End(); - } - - static Test* Create() { return new DistanceJoint; } - - b2DistanceJoint* m_joint; - float m_length; - float m_minLength; - float m_maxLength; - float m_hertz; - float m_dampingRatio; -}; - -static int testIndex = RegisterTest("Joints", "Distance Joint", DistanceJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/distance_test.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/distance_test.cpp deleted file mode 100644 index 6372330426b0..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/distance_test.cpp +++ /dev/null @@ -1,134 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "box2d/b2_distance.h" - -class DistanceTest : public Test -{ -public: - DistanceTest() - { - { - m_transformA.SetIdentity(); - m_transformA.p.Set(0.0f, -0.2f); - m_polygonA.SetAsBox(10.0f, 0.2f); - } - - { - m_positionB.Set(12.017401f, 0.13678508f); - m_angleB = -0.0109265f; - m_transformB.Set(m_positionB, m_angleB); - - m_polygonB.SetAsBox(2.0f, 0.1f); - } - } - - static Test* Create() { return new DistanceTest; } - - void Step(Settings& settings) override - { - Test::Step(settings); - - b2DistanceInput input; - input.proxyA.Set(&m_polygonA, 0); - input.proxyB.Set(&m_polygonB, 0); - input.transformA = m_transformA; - input.transformB = m_transformB; - input.useRadii = true; - b2SimplexCache cache; - cache.count = 0; - b2DistanceOutput output; - b2Distance(&output, &cache, &input); - - DrawString(5, m_textLine, "distance = %g", output.distance); - - DrawString(5, m_textLine, "iterations = %d", output.iterations); - - { - b2Color color(0.9f, 0.9f, 0.9f); - b2Vec2 v[b2_maxPolygonVertices]; - for (int32 i = 0; i < m_polygonA.m_count; ++i) - { - v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); - } - g_debugDraw.DrawPolygon(v, m_polygonA.m_count, color); - - for (int32 i = 0; i < m_polygonB.m_count; ++i) - { - v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(v, m_polygonB.m_count, color); - } - - b2Vec2 x1 = output.pointA; - b2Vec2 x2 = output.pointB; - - b2Color c1(1.0f, 0.0f, 0.0f); - g_debugDraw.DrawPoint(x1, 4.0f, c1); - - b2Color c2(1.0f, 1.0f, 0.0f); - g_debugDraw.DrawPoint(x2, 4.0f, c2); - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_positionB.x -= 0.1f; - break; - - case GLFW_KEY_D: - m_positionB.x += 0.1f; - break; - - case GLFW_KEY_S: - m_positionB.y -= 0.1f; - break; - - case GLFW_KEY_W: - m_positionB.y += 0.1f; - break; - - case GLFW_KEY_Q: - m_angleB += 0.1f * b2_pi; - break; - - case GLFW_KEY_E: - m_angleB -= 0.1f * b2_pi; - break; - } - - m_transformB.Set(m_positionB, m_angleB); - } - - b2Vec2 m_positionB; - float m_angleB; - - b2Transform m_transformA; - b2Transform m_transformB; - b2PolygonShape m_polygonA; - b2PolygonShape m_polygonB; -}; - -static int testIndex = RegisterTest("Geometry", "Distance Test", DistanceTest::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/dominos.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/dominos.cpp deleted file mode 100644 index f64a141bd407..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/dominos.cpp +++ /dev/null @@ -1,216 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Dominos : public Test -{ -public: - Dominos() - { - b2Body* b1; - { - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - - b2BodyDef bd; - b1 = m_world->CreateBody(&bd); - b1->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(6.0f, 0.25f); - - b2BodyDef bd; - bd.position.Set(-1.5f, 10.0f); - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.1f, 1.0f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.friction = 0.1f; - - for (int i = 0; i < 10; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-6.0f + 1.0f * i, 11.25f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&fd); - } - } - - { - b2PolygonShape shape; - shape.SetAsBox(7.0f, 0.25f, b2Vec2_zero, 0.3f); - - b2BodyDef bd; - bd.position.Set(1.0f, 6.0f); - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - b2Body* b2; - { - b2PolygonShape shape; - shape.SetAsBox(0.25f, 1.5f); - - b2BodyDef bd; - bd.position.Set(-7.0f, 4.0f); - b2 = m_world->CreateBody(&bd); - b2->CreateFixture(&shape, 0.0f); - } - - b2Body* b3; - { - b2PolygonShape shape; - shape.SetAsBox(6.0f, 0.125f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-0.9f, 1.0f); - bd.angle = -0.15f; - - b3 = m_world->CreateBody(&bd); - b3->CreateFixture(&shape, 10.0f); - } - - b2RevoluteJointDef jd; - b2Vec2 anchor; - - anchor.Set(-2.0f, 1.0f); - jd.Initialize(b1, b3, anchor); - jd.collideConnected = true; - m_world->CreateJoint(&jd); - - b2Body* b4; - { - b2PolygonShape shape; - shape.SetAsBox(0.25f, 0.25f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f, 15.0f); - b4 = m_world->CreateBody(&bd); - b4->CreateFixture(&shape, 10.0f); - } - - anchor.Set(-7.0f, 15.0f); - jd.Initialize(b2, b4, anchor); - m_world->CreateJoint(&jd); - - b2Body* b5; - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(6.5f, 3.0f); - b5 = m_world->CreateBody(&bd); - - b2PolygonShape shape; - b2FixtureDef fd; - - fd.shape = &shape; - fd.density = 10.0f; - fd.friction = 0.1f; - - shape.SetAsBox(1.0f, 0.1f, b2Vec2(0.0f, -0.9f), 0.0f); - b5->CreateFixture(&fd); - - shape.SetAsBox(0.1f, 1.0f, b2Vec2(-0.9f, 0.0f), 0.0f); - b5->CreateFixture(&fd); - - shape.SetAsBox(0.1f, 1.0f, b2Vec2(0.9f, 0.0f), 0.0f); - b5->CreateFixture(&fd); - } - - anchor.Set(6.0f, 2.0f); - jd.Initialize(b1, b5, anchor); - m_world->CreateJoint(&jd); - - b2Body* b6; - { - b2PolygonShape shape; - shape.SetAsBox(1.0f, 0.1f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(6.5f, 4.1f); - b6 = m_world->CreateBody(&bd); - b6->CreateFixture(&shape, 30.0f); - } - - anchor.Set(7.5f, 4.0f); - jd.Initialize(b5, b6, anchor); - m_world->CreateJoint(&jd); - - b2Body* b7; - { - b2PolygonShape shape; - shape.SetAsBox(0.1f, 1.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(7.4f, 1.0f); - - b7 = m_world->CreateBody(&bd); - b7->CreateFixture(&shape, 10.0f); - } - - b2DistanceJointDef djd; - djd.bodyA = b3; - djd.bodyB = b7; - djd.localAnchorA.Set(6.0f, 0.0f); - djd.localAnchorB.Set(0.0f, -1.0f); - b2Vec2 d = djd.bodyB->GetWorldPoint(djd.localAnchorB) - djd.bodyA->GetWorldPoint(djd.localAnchorA); - djd.length = d.Length(); - - b2LinearStiffness(djd.stiffness, djd.damping, 1.0f, 1.0f, djd.bodyA, djd.bodyB); - m_world->CreateJoint(&djd); - - { - float radius = 0.2f; - - b2CircleShape shape; - shape.m_radius = radius; - - for (int32 i = 0; i < 4; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(5.9f + 2.0f * radius * i, 2.4f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 10.0f); - } - } - } - - static Test* Create() { return new Dominos; } -}; - -static int testIndex = RegisterTest("Examples", "Dominos", Dominos::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/dump_loader.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/dump_loader.cpp deleted file mode 100644 index b874a2a174ef..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/dump_loader.cpp +++ /dev/null @@ -1,82 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// This test holds worlds dumped using b2World::Dump. -class DumpLoader : public Test -{ -public: - DumpLoader() - { - b2ChainShape chainShape; - b2Vec2 vertices[] = {b2Vec2(-5, 0), b2Vec2(5, 0), b2Vec2(5, 5), b2Vec2(4, 1), b2Vec2(-4, 1), b2Vec2(-5, 5)}; - chainShape.CreateLoop(vertices, 6); - - b2FixtureDef groundFixtureDef; - groundFixtureDef.density = 0; - groundFixtureDef.shape = &chainShape; - - b2BodyDef groundBodyDef; - groundBodyDef.type = b2_staticBody; - - b2Body* groundBody = m_world->CreateBody(&groundBodyDef); - b2Fixture* groundBodyFixture = groundBody->CreateFixture(&groundFixtureDef); - - b2CircleShape ballShape; - ballShape.m_radius = 1; - - b2FixtureDef ballFixtureDef; - ballFixtureDef.restitution = 0.75f; - ballFixtureDef.density = 1; - ballFixtureDef.shape = &ballShape; - - b2BodyDef ballBodyDef; - ballBodyDef.type = b2BodyType::b2_dynamicBody; - ballBodyDef.position = b2Vec2(0, 10); - // ballBodyDef.angularDamping = 0.2f; - - m_ball = m_world->CreateBody(&ballBodyDef); - b2Fixture* ballFixture = m_ball->CreateFixture(&ballFixtureDef); - m_ball->ApplyForceToCenter(b2Vec2(-1000, -400), true); - } - - void Step(Settings& settings) override - { - b2Vec2 v = m_ball->GetLinearVelocity(); - float omega = m_ball->GetAngularVelocity(); - - b2MassData massData = m_ball->GetMassData(); - - float ke = 0.5f * massData.mass * b2Dot(v, v) + 0.5f * massData.I * omega * omega; - - DrawString(5, m_textLine, "kinetic energy = %.6f", ke); - - Test::Step(settings); - } - - static Test* Create() { return new DumpLoader; } - - b2Body* m_ball; -}; - -static int testIndex = RegisterTest("Bugs", "Dump Loader", DumpLoader::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/dynamic_tree.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/dynamic_tree.cpp deleted file mode 100644 index bd2de4d80a0f..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/dynamic_tree.cpp +++ /dev/null @@ -1,357 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class DynamicTree : public Test -{ -public: - enum - { - e_actorCount = 128 - }; - - DynamicTree() - { - m_worldExtent = 15.0f; - m_proxyExtent = 0.5f; - - srand(888); - - for (int32 i = 0; i < e_actorCount; ++i) - { - Actor* actor = m_actors + i; - GetRandomAABB(&actor->aabb); - actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); - } - - m_stepCount = 0; - - float h = m_worldExtent; - m_queryAABB.lowerBound.Set(-3.0f, -4.0f + h); - m_queryAABB.upperBound.Set(5.0f, 6.0f + h); - - m_rayCastInput.p1.Set(-5.0, 5.0f + h); - m_rayCastInput.p2.Set(7.0f, -4.0f + h); - // m_rayCastInput.p1.Set(0.0f, 2.0f + h); - // m_rayCastInput.p2.Set(0.0f, -2.0f + h); - m_rayCastInput.maxFraction = 1.0f; - - m_automated = false; - } - - static Test* Create() { return new DynamicTree; } - - void Step(Settings& settings) override - { - B2_NOT_USED(settings); - - m_rayActor = NULL; - for (int32 i = 0; i < e_actorCount; ++i) - { - m_actors[i].fraction = 1.0f; - m_actors[i].overlap = false; - } - - if (m_automated == true) - { - int32 actionCount = b2Max(1, e_actorCount >> 2); - - for (int32 i = 0; i < actionCount; ++i) - { - Action(); - } - } - - Query(); - RayCast(); - - for (int32 i = 0; i < e_actorCount; ++i) - { - Actor* actor = m_actors + i; - if (actor->proxyId == b2_nullNode) - continue; - - b2Color c(0.9f, 0.9f, 0.9f); - if (actor == m_rayActor && actor->overlap) - { - c.Set(0.9f, 0.6f, 0.6f); - } - else if (actor == m_rayActor) - { - c.Set(0.6f, 0.9f, 0.6f); - } - else if (actor->overlap) - { - c.Set(0.6f, 0.6f, 0.9f); - } - - DrawAABB(&actor->aabb, c); - } - - b2Color c(0.7f, 0.7f, 0.7f); - DrawAABB(&m_queryAABB, c); - - g_debugDraw.DrawSegment(m_rayCastInput.p1, m_rayCastInput.p2, c); - - b2Color c1(0.2f, 0.9f, 0.2f); - b2Color c2(0.9f, 0.2f, 0.2f); - g_debugDraw.DrawPoint(m_rayCastInput.p1, 6.0f, c1); - g_debugDraw.DrawPoint(m_rayCastInput.p2, 6.0f, c2); - - if (m_rayActor) - { - b2Color cr(0.2f, 0.2f, 0.9f); - b2Vec2 p = m_rayCastInput.p1 + m_rayActor->fraction * (m_rayCastInput.p2 - m_rayCastInput.p1); - g_debugDraw.DrawPoint(p, 6.0f, cr); - } - - { - int32 height = m_tree.GetHeight(); - DrawString(5, m_textLine, "dynamic tree height = %d", height); - } - - ++m_stepCount; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_automated = !m_automated; - break; - - case GLFW_KEY_C: - CreateProxy(); - break; - - case GLFW_KEY_D: - DestroyProxy(); - break; - - case GLFW_KEY_M: - MoveProxy(); - break; - } - } - - bool QueryCallback(int32 proxyId) - { - Actor* actor = (Actor*)m_tree.GetUserData(proxyId); - actor->overlap = b2TestOverlap(m_queryAABB, actor->aabb); - return true; - } - - float RayCastCallback(const b2RayCastInput& input, int32 proxyId) - { - Actor* actor = (Actor*)m_tree.GetUserData(proxyId); - - b2RayCastOutput output; - bool hit = actor->aabb.RayCast(&output, input); - - if (hit) - { - m_rayCastOutput = output; - m_rayActor = actor; - m_rayActor->fraction = output.fraction; - return output.fraction; - } - - return input.maxFraction; - } - -private: - struct Actor - { - b2AABB aabb; - float fraction; - bool overlap; - int32 proxyId; - }; - - void GetRandomAABB(b2AABB* aabb) - { - b2Vec2 w; - w.Set(2.0f * m_proxyExtent, 2.0f * m_proxyExtent); - // aabb->lowerBound.x = -m_proxyExtent; - // aabb->lowerBound.y = -m_proxyExtent + m_worldExtent; - aabb->lowerBound.x = RandomFloat(-m_worldExtent, m_worldExtent); - aabb->lowerBound.y = RandomFloat(0.0f, 2.0f * m_worldExtent); - aabb->upperBound = aabb->lowerBound + w; - } - - void MoveAABB(b2AABB* aabb) - { - b2Vec2 d; - d.x = RandomFloat(-0.5f, 0.5f); - d.y = RandomFloat(-0.5f, 0.5f); - // d.x = 2.0f; - // d.y = 0.0f; - aabb->lowerBound += d; - aabb->upperBound += d; - - b2Vec2 c0 = 0.5f * (aabb->lowerBound + aabb->upperBound); - b2Vec2 min; - min.Set(-m_worldExtent, 0.0f); - b2Vec2 max; - max.Set(m_worldExtent, 2.0f * m_worldExtent); - b2Vec2 c = b2Clamp(c0, min, max); - - aabb->lowerBound += c - c0; - aabb->upperBound += c - c0; - } - - void CreateProxy() - { - for (int32 i = 0; i < e_actorCount; ++i) - { - int32 j = rand() % e_actorCount; - Actor* actor = m_actors + j; - if (actor->proxyId == b2_nullNode) - { - GetRandomAABB(&actor->aabb); - actor->proxyId = m_tree.CreateProxy(actor->aabb, actor); - return; - } - } - } - - void DestroyProxy() - { - for (int32 i = 0; i < e_actorCount; ++i) - { - int32 j = rand() % e_actorCount; - Actor* actor = m_actors + j; - if (actor->proxyId != b2_nullNode) - { - m_tree.DestroyProxy(actor->proxyId); - actor->proxyId = b2_nullNode; - return; - } - } - } - - void MoveProxy() - { - for (int32 i = 0; i < e_actorCount; ++i) - { - int32 j = rand() % e_actorCount; - Actor* actor = m_actors + j; - if (actor->proxyId == b2_nullNode) - { - continue; - } - - b2AABB aabb0 = actor->aabb; - MoveAABB(&actor->aabb); - b2Vec2 displacement = actor->aabb.GetCenter() - aabb0.GetCenter(); - m_tree.MoveProxy(actor->proxyId, actor->aabb, displacement); - return; - } - } - - void Action() - { - int32 choice = rand() % 20; - - switch (choice) - { - case 0: - CreateProxy(); - break; - - case 1: - DestroyProxy(); - break; - - default: - MoveProxy(); - } - } - - void Query() - { - m_tree.Query(this, m_queryAABB); - - for (int32 i = 0; i < e_actorCount; ++i) - { - if (m_actors[i].proxyId == b2_nullNode) - { - continue; - } - - bool overlap = b2TestOverlap(m_queryAABB, m_actors[i].aabb); - B2_NOT_USED(overlap); - b2Assert(overlap == m_actors[i].overlap); - } - } - - void RayCast() - { - m_rayActor = NULL; - - b2RayCastInput input = m_rayCastInput; - - // Ray cast against the dynamic tree. - m_tree.RayCast(this, input); - - // Brute force ray cast. - Actor* bruteActor = NULL; - b2RayCastOutput bruteOutput; - for (int32 i = 0; i < e_actorCount; ++i) - { - if (m_actors[i].proxyId == b2_nullNode) - { - continue; - } - - b2RayCastOutput output; - bool hit = m_actors[i].aabb.RayCast(&output, input); - if (hit) - { - bruteActor = m_actors + i; - bruteOutput = output; - input.maxFraction = output.fraction; - } - } - - if (bruteActor != NULL) - { - b2Assert(bruteOutput.fraction == m_rayCastOutput.fraction); - } - } - - float m_worldExtent; - float m_proxyExtent; - - b2DynamicTree m_tree; - b2AABB m_queryAABB; - b2RayCastInput m_rayCastInput; - b2RayCastOutput m_rayCastOutput; - Actor* m_rayActor; - Actor m_actors[e_actorCount]; - int32 m_stepCount; - bool m_automated; -}; - -static int testIndex = RegisterTest("Collision", "Dynamic Tree", DynamicTree::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/edge_shapes.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/edge_shapes.cpp deleted file mode 100644 index f7416dc4373d..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/edge_shapes.cpp +++ /dev/null @@ -1,244 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" - -class EdgeShapesCallback : public b2RayCastCallback -{ -public: - EdgeShapesCallback() { m_fixture = NULL; } - - float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override - { - m_fixture = fixture; - m_point = point; - m_normal = normal; - - return fraction; - } - - b2Fixture* m_fixture; - b2Vec2 m_point; - b2Vec2 m_normal; -}; - -class EdgeShapes : public Test -{ -public: - enum - { - e_maxBodies = 256 - }; - - EdgeShapes() - { - // Ground body - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - float x1 = -20.0f; - float y1 = 2.0f * cosf(x1 / 10.0f * b2_pi); - for (int32 i = 0; i < 80; ++i) - { - float x2 = x1 + 0.5f; - float y2 = 2.0f * cosf(x2 / 10.0f * b2_pi); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(x1, y1), b2Vec2(x2, y2)); - ground->CreateFixture(&shape, 0.0f); - - x1 = x2; - y1 = y2; - } - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.5f, 0.0f); - vertices[1].Set(0.5f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[0].Set(vertices, 3); - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.1f, 0.0f); - vertices[1].Set(0.1f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[1].Set(vertices, 3); - } - - { - float w = 1.0f; - float b = w / (2.0f + b2Sqrt(2.0f)); - float s = b2Sqrt(2.0f) * b; - - b2Vec2 vertices[8]; - vertices[0].Set(0.5f * s, 0.0f); - vertices[1].Set(0.5f * w, b); - vertices[2].Set(0.5f * w, b + s); - vertices[3].Set(0.5f * s, w); - vertices[4].Set(-0.5f * s, w); - vertices[5].Set(-0.5f * w, b + s); - vertices[6].Set(-0.5f * w, b); - vertices[7].Set(-0.5f * s, 0.0f); - - m_polygons[2].Set(vertices, 8); - } - - { - m_polygons[3].SetAsBox(0.5f, 0.5f); - } - - { - m_circle.m_radius = 0.5f; - } - - m_bodyIndex = 0; - memset(m_bodies, 0, sizeof(m_bodies)); - - m_angle = 0.0f; - } - - void Create(int32 index) - { - if (m_bodies[m_bodyIndex] != NULL) - { - m_world->DestroyBody(m_bodies[m_bodyIndex]); - m_bodies[m_bodyIndex] = NULL; - } - - b2BodyDef bd; - - float x = RandomFloat(-10.0f, 10.0f); - float y = RandomFloat(10.0f, 20.0f); - bd.position.Set(x, y); - bd.angle = RandomFloat(-b2_pi, b2_pi); - bd.type = b2_dynamicBody; - - if (index == 4) - { - bd.angularDamping = 0.02f; - } - - m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); - - if (index < 4) - { - b2FixtureDef fd; - fd.shape = m_polygons + index; - fd.friction = 0.3f; - fd.density = 20.0f; - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - else - { - b2FixtureDef fd; - fd.shape = &m_circle; - fd.friction = 0.3f; - fd.density = 20.0f; - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - - m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; - } - - void DestroyBody() - { - for (int32 i = 0; i < e_maxBodies; ++i) - { - if (m_bodies[i] != NULL) - { - m_world->DestroyBody(m_bodies[i]); - m_bodies[i] = NULL; - return; - } - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_1: - case GLFW_KEY_2: - case GLFW_KEY_3: - case GLFW_KEY_4: - case GLFW_KEY_5: - Create(key - GLFW_KEY_1); - break; - - case GLFW_KEY_D: - DestroyBody(); - break; - } - } - - void Step(Settings& settings) override - { - bool advanceRay = settings.m_pause == 0 || settings.m_singleStep; - - Test::Step(settings); - DrawString(5, m_textLine, "Press 1-5 to drop stuff"); - - float L = 25.0f; - b2Vec2 point1(0.0f, 10.0f); - b2Vec2 d(L * cosf(m_angle), -L * b2Abs(sinf(m_angle))); - b2Vec2 point2 = point1 + d; - - EdgeShapesCallback callback; - - m_world->RayCast(&callback, point1, point2); - - if (callback.m_fixture) - { - g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); - - g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); - - b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; - g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); - } - else - { - g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); - } - - if (advanceRay) - { - m_angle += 0.25f * b2_pi / 180.0f; - } - } - - static Test* Create() { return new EdgeShapes; } - - int32 m_bodyIndex; - b2Body* m_bodies[e_maxBodies]; - b2PolygonShape m_polygons[4]; - b2CircleShape m_circle; - - float m_angle; -}; - -static int testIndex = RegisterTest("Geometry", "Edge Shapes", EdgeShapes::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/edge_test.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/edge_test.cpp deleted file mode 100644 index 6cd086c3972c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/edge_test.cpp +++ /dev/null @@ -1,267 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -class EdgeTest : public Test -{ -public: - EdgeTest() - { - b2Vec2 vertices[10] = {{10.0f, -4.0f}, {10.0f, 0.0f}, {6.0f, 0.0f}, {4.0f, 2.0f}, {2.0f, 0.0f}, - {-2.0f, 0.0f}, {-6.0f, 0.0f}, {-8.0f, -3.0f}, {-10.0f, 0.0f}, {-10.0f, -4.0f}}; - - m_offset1.Set(0.0f, 8.0f); - m_offset2.Set(0.0f, 16.0f); - - { - b2Vec2 v1 = vertices[0] + m_offset1; - b2Vec2 v2 = vertices[1] + m_offset1; - b2Vec2 v3 = vertices[2] + m_offset1; - b2Vec2 v4 = vertices[3] + m_offset1; - b2Vec2 v5 = vertices[4] + m_offset1; - b2Vec2 v6 = vertices[5] + m_offset1; - b2Vec2 v7 = vertices[6] + m_offset1; - b2Vec2 v8 = vertices[7] + m_offset1; - b2Vec2 v9 = vertices[8] + m_offset1; - b2Vec2 v10 = vertices[9] + m_offset1; - - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - - shape.SetOneSided(v10, v1, v2, v3); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v1, v2, v3, v4); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v2, v3, v4, v5); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v3, v4, v5, v6); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v4, v5, v6, v7); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v5, v6, v7, v8); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v6, v7, v8, v9); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v7, v8, v9, v10); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v8, v9, v10, v1); - ground->CreateFixture(&shape, 0.0f); - - shape.SetOneSided(v9, v10, v1, v2); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2Vec2 v1 = vertices[0] + m_offset2; - b2Vec2 v2 = vertices[1] + m_offset2; - b2Vec2 v3 = vertices[2] + m_offset2; - b2Vec2 v4 = vertices[3] + m_offset2; - b2Vec2 v5 = vertices[4] + m_offset2; - b2Vec2 v6 = vertices[5] + m_offset2; - b2Vec2 v7 = vertices[6] + m_offset2; - b2Vec2 v8 = vertices[7] + m_offset2; - b2Vec2 v9 = vertices[8] + m_offset2; - b2Vec2 v10 = vertices[9] + m_offset2; - - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - - shape.SetTwoSided(v1, v2); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v2, v3); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v3, v4); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v4, v5); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v5, v6); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v6, v7); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v7, v8); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v8, v9); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v9, v10); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(v10, v1); - ground->CreateFixture(&shape, 0.0f); - } - - m_body1 = nullptr; - m_body2 = nullptr; - CreateBoxes(); - m_boxes = true; - } - - void CreateBoxes() - { - if (m_body1) - { - m_world->DestroyBody(m_body1); - m_body1 = nullptr; - } - - if (m_body2) - { - m_world->DestroyBody(m_body2); - m_body2 = nullptr; - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = b2Vec2(8.0f, 2.6f) + m_offset1; - bd.allowSleep = false; - m_body1 = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 1.0f); - - m_body1->CreateFixture(&shape, 1.0f); - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = b2Vec2(8.0f, 2.6f) + m_offset2; - bd.allowSleep = false; - m_body2 = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 1.0f); - - m_body2->CreateFixture(&shape, 1.0f); - } - } - - void CreateCircles() - { - if (m_body1) - { - m_world->DestroyBody(m_body1); - m_body1 = nullptr; - } - - if (m_body2) - { - m_world->DestroyBody(m_body2); - m_body2 = nullptr; - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = b2Vec2(-0.5f, 0.6f) + m_offset1; - bd.allowSleep = false; - m_body1 = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.5f; - - m_body1->CreateFixture(&shape, 1.0f); - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = b2Vec2(-0.5f, 0.6f) + m_offset2; - bd.allowSleep = false; - m_body2 = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.5f; - - m_body2->CreateFixture(&shape, 1.0f); - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Custom Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::RadioButton("Boxes", m_boxes == true)) - { - CreateBoxes(); - m_boxes = true; - } - - if (ImGui::RadioButton("Circles", m_boxes == false)) - { - CreateCircles(); - m_boxes = false; - } - - ImGui::End(); - } - - void Step(Settings& settings) override - { - // if (glfwGetKey(g_mainWindow, GLFW_KEY_A) == GLFW_PRESS) - //{ - // m_body1->ApplyForceToCenter(b2Vec2(-10.0f, 0.0f), true); - // m_body2->ApplyForceToCenter(b2Vec2(-10.0f, 0.0f), true); - // } - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_D) == GLFW_PRESS) - //{ - // m_body1->ApplyForceToCenter(b2Vec2(10.0f, 0.0f), true); - // m_body2->ApplyForceToCenter(b2Vec2(10.0f, 0.0f), true); - // } - - Test::Step(settings); - } - - static Test* Create() { return new EdgeTest; } - - b2Vec2 m_offset1, m_offset2; - b2Body* m_body1; - b2Body* m_body2; - bool m_boxes; -}; - -static int testIndex = RegisterTest("Geometry", "Edge Test", EdgeTest::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/friction.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/friction.cpp deleted file mode 100644 index b935e0459c64..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/friction.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Friction : public Test -{ -public: - Friction() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(13.0f, 0.25f); - - b2BodyDef bd; - bd.position.Set(-4.0f, 22.0f); - bd.angle = -0.25f; - - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.25f, 1.0f); - - b2BodyDef bd; - bd.position.Set(10.5f, 19.0f); - - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(13.0f, 0.25f); - - b2BodyDef bd; - bd.position.Set(4.0f, 14.0f); - bd.angle = 0.25f; - - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.25f, 1.0f); - - b2BodyDef bd; - bd.position.Set(-10.5f, 11.0f); - - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(13.0f, 0.25f); - - b2BodyDef bd; - bd.position.Set(-4.0f, 6.0f); - bd.angle = -0.25f; - - b2Body* ground = m_world->CreateBody(&bd); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 25.0f; - - float friction[5] = {0.75f, 0.5f, 0.35f, 0.1f, 0.0f}; - - for (int i = 0; i < 5; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-15.0f + 4.0f * i, 28.0f); - b2Body* body = m_world->CreateBody(&bd); - - fd.friction = friction[i]; - body->CreateFixture(&fd); - } - } - } - - static Test* Create() { return new Friction; } -}; - -static int testIndex = RegisterTest("Forces", "Friction", Friction::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/gear_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/gear_joint.cpp deleted file mode 100644 index d7e1b15771e2..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/gear_joint.cpp +++ /dev/null @@ -1,175 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class GearJoint : public Test -{ -public: - GearJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(-50.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2CircleShape circle1; - circle1.m_radius = 1.0f; - - b2PolygonShape box; - box.SetAsBox(0.5f, 5.0f); - - b2CircleShape circle2; - circle2.m_radius = 2.0f; - - b2BodyDef bd1; - bd1.type = b2_staticBody; - bd1.position.Set(10.0f, 9.0f); - b2Body* body1 = m_world->CreateBody(&bd1); - body1->CreateFixture(&circle1, 5.0f); - - b2BodyDef bd2; - bd2.type = b2_dynamicBody; - bd2.position.Set(10.0f, 8.0f); - b2Body* body2 = m_world->CreateBody(&bd2); - body2->CreateFixture(&box, 5.0f); - - b2BodyDef bd3; - bd3.type = b2_dynamicBody; - bd3.position.Set(10.0f, 6.0f); - b2Body* body3 = m_world->CreateBody(&bd3); - body3->CreateFixture(&circle2, 5.0f); - - b2RevoluteJointDef jd1; - jd1.Initialize(body1, body2, bd1.position); - b2Joint* joint1 = m_world->CreateJoint(&jd1); - - b2RevoluteJointDef jd2; - jd2.Initialize(body2, body3, bd3.position); - b2Joint* joint2 = m_world->CreateJoint(&jd2); - - b2GearJointDef jd4; - jd4.bodyA = body1; - jd4.bodyB = body3; - jd4.joint1 = joint1; - jd4.joint2 = joint2; - jd4.ratio = circle2.m_radius / circle1.m_radius; - m_world->CreateJoint(&jd4); - } - - { - b2CircleShape circle1; - circle1.m_radius = 1.0f; - - b2CircleShape circle2; - circle2.m_radius = 2.0f; - - b2PolygonShape box; - box.SetAsBox(0.5f, 5.0f); - - b2BodyDef bd1; - bd1.type = b2_dynamicBody; - bd1.position.Set(-3.0f, 12.0f); - b2Body* body1 = m_world->CreateBody(&bd1); - body1->CreateFixture(&circle1, 5.0f); - - b2RevoluteJointDef jd1; - jd1.bodyA = ground; - jd1.bodyB = body1; - jd1.localAnchorA = ground->GetLocalPoint(bd1.position); - jd1.localAnchorB = body1->GetLocalPoint(bd1.position); - jd1.referenceAngle = body1->GetAngle() - ground->GetAngle(); - m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd1); - - b2BodyDef bd2; - bd2.type = b2_dynamicBody; - bd2.position.Set(0.0f, 12.0f); - b2Body* body2 = m_world->CreateBody(&bd2); - body2->CreateFixture(&circle2, 5.0f); - - b2RevoluteJointDef jd2; - jd2.Initialize(ground, body2, bd2.position); - m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd2); - - b2BodyDef bd3; - bd3.type = b2_dynamicBody; - bd3.position.Set(2.5f, 12.0f); - b2Body* body3 = m_world->CreateBody(&bd3); - body3->CreateFixture(&box, 5.0f); - - b2PrismaticJointDef jd3; - jd3.Initialize(ground, body3, bd3.position, b2Vec2(0.0f, 1.0f)); - jd3.lowerTranslation = -5.0f; - jd3.upperTranslation = 5.0f; - jd3.enableLimit = true; - - m_joint3 = (b2PrismaticJoint*)m_world->CreateJoint(&jd3); - - b2GearJointDef jd4; - jd4.bodyA = body1; - jd4.bodyB = body2; - jd4.joint1 = m_joint1; - jd4.joint2 = m_joint2; - jd4.ratio = circle2.m_radius / circle1.m_radius; - m_joint4 = (b2GearJoint*)m_world->CreateJoint(&jd4); - - b2GearJointDef jd5; - jd5.bodyA = body2; - jd5.bodyB = body3; - jd5.joint1 = m_joint2; - jd5.joint2 = m_joint3; - jd5.ratio = -1.0f / circle2.m_radius; - m_joint5 = (b2GearJoint*)m_world->CreateJoint(&jd5); - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - float ratio, value; - - ratio = m_joint4->GetRatio(); - value = m_joint1->GetJointAngle() + ratio * m_joint2->GetJointAngle(); - DrawString(5, m_textLine, "theta1 + %4.2f * theta2 = %4.2f", (float)ratio, (float)value); - - ratio = m_joint5->GetRatio(); - value = m_joint2->GetJointAngle() + ratio * m_joint3->GetJointTranslation(); - DrawString(5, m_textLine, "theta2 + %4.2f * delta = %4.2f", (float)ratio, (float)value); - } - - static Test* Create() { return new GearJoint; } - - b2RevoluteJoint* m_joint1; - b2RevoluteJoint* m_joint2; - b2PrismaticJoint* m_joint3; - b2GearJoint* m_joint4; - b2GearJoint* m_joint5; -}; - -static int testIndex = RegisterTest("Joints", "Gear", GearJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/heavy1.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/heavy1.cpp deleted file mode 100644 index 17ba6d183f23..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/heavy1.cpp +++ /dev/null @@ -1,57 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Heavy1 : public Test -{ -public: - Heavy1() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 0.5f); - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.5f; - body->CreateFixture(&shape, 10.0f); - - bd.position.Set(0.0f, 6.0f); - body = m_world->CreateBody(&bd); - shape.m_radius = 5.0f; - body->CreateFixture(&shape, 10.0f); - } - - static Test* Create() { return new Heavy1; } -}; - -static int testIndex = RegisterTest("Solver", "Heavy 1", Heavy1::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/heavy2.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/heavy2.cpp deleted file mode 100644 index c34a36995eb8..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/heavy2.cpp +++ /dev/null @@ -1,90 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Heavy2 : public Test -{ -public: - Heavy2() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 2.5f); - b2Body* body = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.5f; - body->CreateFixture(&shape, 10.0f); - - bd.position.Set(0.0f, 3.5f); - body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 10.0f); - - m_heavy = NULL; - } - - void ToggleHeavy() - { - if (m_heavy) - { - m_world->DestroyBody(m_heavy); - m_heavy = NULL; - } - else - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 9.0f); - m_heavy = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 5.0f; - m_heavy->CreateFixture(&shape, 10.0f); - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_H: - ToggleHeavy(); - break; - } - } - - static Test* Create() { return new Heavy2; } - - b2Body* m_heavy; -}; - -static int testIndex = RegisterTest("Solver", "Heavy 2", Heavy2::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_balanced.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_balanced.cpp deleted file mode 100644 index 8b68edd0b7c7..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_balanced.cpp +++ /dev/null @@ -1,104 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class MobileBalanced : public Test -{ -public: - enum - { - e_depth = 4 - }; - - MobileBalanced() - { - b2Body* ground; - - // Create ground body. - { - b2BodyDef bodyDef; - bodyDef.position.Set(0.0f, 20.0f); - ground = m_world->CreateBody(&bodyDef); - } - - float a = 0.5f; - b2Vec2 h(0.0f, a); - - b2Body* root = AddNode(ground, b2Vec2_zero, 0, 3.0f, a); - - b2RevoluteJointDef jointDef; - jointDef.bodyA = ground; - jointDef.bodyB = root; - jointDef.localAnchorA.SetZero(); - jointDef.localAnchorB = h; - m_world->CreateJoint(&jointDef); - } - - b2Body* AddNode(b2Body* parent, const b2Vec2& localAnchor, int32 depth, float offset, float a) - { - float density = 20.0f; - b2Vec2 h(0.0f, a); - - b2Vec2 p = parent->GetPosition() + localAnchor - h; - - b2BodyDef bodyDef; - bodyDef.type = b2_dynamicBody; - bodyDef.position = p; - b2Body* body = m_world->CreateBody(&bodyDef); - - b2PolygonShape shape; - shape.SetAsBox(0.25f * a, a); - body->CreateFixture(&shape, density); - - if (depth == e_depth) - { - return body; - } - - shape.SetAsBox(offset, 0.25f * a, b2Vec2(0, -a), 0.0f); - body->CreateFixture(&shape, density); - - b2Vec2 a1 = b2Vec2(offset, -a); - b2Vec2 a2 = b2Vec2(-offset, -a); - b2Body* body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a); - b2Body* body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a); - - b2RevoluteJointDef jointDef; - jointDef.bodyA = body; - jointDef.localAnchorB = h; - - jointDef.localAnchorA = a1; - jointDef.bodyB = body1; - m_world->CreateJoint(&jointDef); - - jointDef.localAnchorA = a2; - jointDef.bodyB = body2; - m_world->CreateJoint(&jointDef); - - return body; - } - - static Test* Create() { return new MobileBalanced; } -}; - -static int testIndex = RegisterTest("Solver", "Mobile Balanced", MobileBalanced::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_unbalanced.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_unbalanced.cpp deleted file mode 100644 index 6d95738e5443..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/mobile_unbalanced.cpp +++ /dev/null @@ -1,101 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class MobileUnbalanced : public Test -{ -public: - enum - { - e_depth = 4 - }; - - MobileUnbalanced() - { - b2Body* ground; - - // Create ground body. - { - b2BodyDef bodyDef; - bodyDef.position.Set(0.0f, 20.0f); - ground = m_world->CreateBody(&bodyDef); - } - - float a = 0.5f; - b2Vec2 h(0.0f, a); - - b2Body* root = AddNode(ground, b2Vec2_zero, 0, 3.0f, a); - - b2RevoluteJointDef jointDef; - jointDef.bodyA = ground; - jointDef.bodyB = root; - jointDef.localAnchorA.SetZero(); - jointDef.localAnchorB = h; - m_world->CreateJoint(&jointDef); - } - - b2Body* AddNode(b2Body* parent, const b2Vec2& localAnchor, int32 depth, float offset, float a) - { - float density = 20.0f; - b2Vec2 h(0.0f, a); - - b2Vec2 p = parent->GetPosition() + localAnchor - h; - - b2BodyDef bodyDef; - bodyDef.type = b2_dynamicBody; - bodyDef.position = p; - b2Body* body = m_world->CreateBody(&bodyDef); - - b2PolygonShape shape; - shape.SetAsBox(0.25f * a, a); - body->CreateFixture(&shape, density); - - if (depth == e_depth) - { - return body; - } - - b2Vec2 a1 = b2Vec2(offset, -a); - b2Vec2 a2 = b2Vec2(-offset, -a); - b2Body* body1 = AddNode(body, a1, depth + 1, 0.5f * offset, a); - b2Body* body2 = AddNode(body, a2, depth + 1, 0.5f * offset, a); - - b2RevoluteJointDef jointDef; - jointDef.bodyA = body; - jointDef.localAnchorB = h; - - jointDef.localAnchorA = a1; - jointDef.bodyB = body1; - m_world->CreateJoint(&jointDef); - - jointDef.localAnchorA = a2; - jointDef.bodyB = body2; - m_world->CreateJoint(&jointDef); - - return body; - } - - static Test* Create() { return new MobileUnbalanced; } -}; - -static int testIndex = RegisterTest("Solver", "Mobile Unbalanced", MobileUnbalanced::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/motor_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/motor_joint.cpp deleted file mode 100644 index 1b4873ad0eda..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/motor_joint.cpp +++ /dev/null @@ -1,115 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" - -/// This test shows how to use a motor joint. A motor joint -/// can be used to animate a dynamic body. With finite motor forces -/// the body can be blocked by collision with other bodies. -class MotorJoint : public Test -{ -public: - MotorJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - - b2FixtureDef fd; - fd.shape = &shape; - - ground->CreateFixture(&fd); - } - - // Define motorized body - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 8.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(2.0f, 0.5f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.friction = 0.6f; - fd.density = 2.0f; - body->CreateFixture(&fd); - - b2MotorJointDef mjd; - mjd.Initialize(ground, body); - mjd.maxForce = 1000.0f; - mjd.maxTorque = 1000.0f; - m_joint = (b2MotorJoint*)m_world->CreateJoint(&mjd); - } - - m_go = false; - m_time = 0.0f; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_S: - m_go = !m_go; - break; - } - } - - void Step(Settings& settings) override - { - if (m_go && settings.m_hertz > 0.0f) - { - m_time += 1.0f / settings.m_hertz; - } - - b2Vec2 linearOffset; - linearOffset.x = 6.0f * sinf(2.0f * m_time); - linearOffset.y = 8.0f + 4.0f * sinf(1.0f * m_time); - - float angularOffset = 4.0f * m_time; - - m_joint->SetLinearOffset(linearOffset); - m_joint->SetAngularOffset(angularOffset); - - g_debugDraw.DrawPoint(linearOffset, 4.0f, b2Color(0.9f, 0.9f, 0.9f)); - - Test::Step(settings); - DrawString(5, m_textLine, "Keys: (s) pause"); - m_textLine += 15; - } - - static Test* Create() { return new MotorJoint; } - - b2MotorJoint* m_joint; - float m_time; - bool m_go; -}; - -static int testIndex = RegisterTest("Joints", "Motor Joint", MotorJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/pinball.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/pinball.cpp deleted file mode 100644 index 1c117de53c0e..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/pinball.cpp +++ /dev/null @@ -1,165 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -/// This tests bullet collision and provides an example of a gameplay scenario. -/// This also uses a loop shape. -class Pinball : public Test -{ -public: - Pinball() - { - // Ground body - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2Vec2 vs[5]; - vs[0].Set(-8.0f, 6.0f); - vs[1].Set(-8.0f, 20.0f); - vs[2].Set(8.0f, 20.0f); - vs[3].Set(8.0f, 6.0f); - vs[4].Set(0.0f, -2.0f); - - b2ChainShape loop; - loop.CreateLoop(vs, 5); - b2FixtureDef fd; - fd.shape = &loop; - fd.density = 0.0f; - ground->CreateFixture(&fd); - } - - // Flippers - { - b2Vec2 p1(-2.0f, 0.0f), p2(2.0f, 0.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - bd.position = p1; - b2Body* leftFlipper = m_world->CreateBody(&bd); - - bd.position = p2; - b2Body* rightFlipper = m_world->CreateBody(&bd); - - b2PolygonShape box; - box.SetAsBox(1.75f, 0.1f); - - b2FixtureDef fd; - fd.shape = &box; - fd.density = 1.0f; - - leftFlipper->CreateFixture(&fd); - rightFlipper->CreateFixture(&fd); - - b2RevoluteJointDef jd; - jd.bodyA = ground; - jd.localAnchorB.SetZero(); - jd.enableMotor = true; - jd.maxMotorTorque = 1000.0f; - jd.enableLimit = true; - - jd.motorSpeed = 0.0f; - jd.localAnchorA = p1; - jd.bodyB = leftFlipper; - jd.lowerAngle = -30.0f * b2_pi / 180.0f; - jd.upperAngle = 5.0f * b2_pi / 180.0f; - m_leftJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - - jd.motorSpeed = 0.0f; - jd.localAnchorA = p2; - jd.bodyB = rightFlipper; - jd.lowerAngle = -5.0f * b2_pi / 180.0f; - jd.upperAngle = 30.0f * b2_pi / 180.0f; - m_rightJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - } - - // Circle character - { - b2BodyDef bd; - bd.position.Set(1.0f, 15.0f); - bd.type = b2_dynamicBody; - bd.bullet = true; - - m_ball = m_world->CreateBody(&bd); - - b2CircleShape shape; - shape.m_radius = 0.2f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - m_ball->CreateFixture(&fd); - } - - m_button = false; - } - - void Step(Settings& settings) override - { - if (m_button) - { - m_leftJoint->SetMotorSpeed(20.0f); - m_rightJoint->SetMotorSpeed(-20.0f); - } - else - { - m_leftJoint->SetMotorSpeed(-10.0f); - m_rightJoint->SetMotorSpeed(10.0f); - } - - Test::Step(settings); - - DrawString(5, m_textLine, "Press 'a' to control the flippers"); - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_button = true; - break; - } - } - - void KeyboardUp(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_button = false; - break; - } - } - - static Test* Create() { return new Pinball; } - - b2RevoluteJoint* m_leftJoint; - b2RevoluteJoint* m_rightJoint; - b2Body* m_ball; - bool m_button; -}; - -static int testIndex = RegisterTest("Examples", "Pinball", Pinball::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/platformer.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/platformer.cpp deleted file mode 100644 index c308f4922bac..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/platformer.cpp +++ /dev/null @@ -1,128 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Platformer : public Test -{ -public: - enum State - { - e_unknown, - e_above, - e_below - }; - - Platformer() - { - // Ground - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-20.0f, 0.0f), b2Vec2(20.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Platform - { - b2BodyDef bd; - bd.position.Set(0.0f, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(3.0f, 0.5f); - m_platform = body->CreateFixture(&shape, 0.0f); - - m_bottom = 10.0f - 0.5f; - m_top = 10.0f + 0.5f; - } - - // Actor - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 12.0f); - b2Body* body = m_world->CreateBody(&bd); - - m_radius = 0.5f; - b2CircleShape shape; - shape.m_radius = m_radius; - m_character = body->CreateFixture(&shape, 20.0f); - - body->SetLinearVelocity(b2Vec2(0.0f, -50.0f)); - - m_state = e_unknown; - } - } - - void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override - { - Test::PreSolve(contact, oldManifold); - - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - - if (fixtureA != m_platform && fixtureA != m_character) - { - return; - } - - if (fixtureB != m_platform && fixtureB != m_character) - { - return; - } - -#if 1 - b2Vec2 position = m_character->GetBody()->GetPosition(); - - if (position.y < m_top + m_radius - 3.0f * b2_linearSlop) - { - contact->SetEnabled(false); - } -#else - b2Vec2 v = m_character->GetBody()->GetLinearVelocity(); - if (v.y > 0.0f) - { - contact->SetEnabled(false); - } -#endif - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - b2Vec2 v = m_character->GetBody()->GetLinearVelocity(); - DrawString(5, m_textLine, "Character Linear Velocity: %f", v.y); - } - - static Test* Create() { return new Platformer; } - - float m_radius, m_top, m_bottom; - State m_state; - b2Fixture* m_platform; - b2Fixture* m_character; -}; - -static int testIndex = RegisterTest("Examples", "Platformer", Platformer::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_collision.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_collision.cpp deleted file mode 100644 index dbc924694c2d..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_collision.cpp +++ /dev/null @@ -1,123 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class PolygonCollision : public Test -{ -public: - PolygonCollision() - { - { - m_polygonA.SetAsBox(0.2f, 0.4f); - m_transformA.Set(b2Vec2(0.0f, 0.0f), 0.0f); - } - - { - m_polygonB.SetAsBox(0.5f, 0.5f); - m_positionB.Set(19.345284f, 1.5632932f); - m_angleB = 1.9160721f; - m_transformB.Set(m_positionB, m_angleB); - } - } - - static Test* Create() { return new PolygonCollision; } - - void Step(Settings& settings) override - { - B2_NOT_USED(settings); - - b2Manifold manifold; - b2CollidePolygons(&manifold, &m_polygonA, m_transformA, &m_polygonB, m_transformB); - - b2WorldManifold worldManifold; - worldManifold.Initialize(&manifold, m_transformA, m_polygonA.m_radius, m_transformB, m_polygonB.m_radius); - - DrawString(5, m_textLine, "point count = %d", manifold.pointCount); - - { - b2Color color(0.9f, 0.9f, 0.9f); - b2Vec2 v[b2_maxPolygonVertices]; - for (int32 i = 0; i < m_polygonA.m_count; ++i) - { - v[i] = b2Mul(m_transformA, m_polygonA.m_vertices[i]); - } - g_debugDraw.DrawPolygon(v, m_polygonA.m_count, color); - - for (int32 i = 0; i < m_polygonB.m_count; ++i) - { - v[i] = b2Mul(m_transformB, m_polygonB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(v, m_polygonB.m_count, color); - } - - for (int32 i = 0; i < manifold.pointCount; ++i) - { - g_debugDraw.DrawPoint(worldManifold.points[i], 4.0f, b2Color(0.9f, 0.3f, 0.3f)); - } - - Test::Step(settings); - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_positionB.x -= 0.1f; - break; - - case GLFW_KEY_D: - m_positionB.x += 0.1f; - break; - - case GLFW_KEY_S: - m_positionB.y -= 0.1f; - break; - - case GLFW_KEY_W: - m_positionB.y += 0.1f; - break; - - case GLFW_KEY_Q: - m_angleB += 0.1f * b2_pi; - break; - - case GLFW_KEY_E: - m_angleB -= 0.1f * b2_pi; - break; - } - - m_transformB.Set(m_positionB, m_angleB); - } - - b2PolygonShape m_polygonA; - b2PolygonShape m_polygonB; - - b2Transform m_transformA; - b2Transform m_transformB; - - b2Vec2 m_positionB; - float m_angleB; -}; - -static int testIndex = RegisterTest("Geometry", "Polygon Collision", PolygonCollision::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_shapes.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_shapes.cpp deleted file mode 100644 index 369f777ee85c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/polygon_shapes.cpp +++ /dev/null @@ -1,257 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -/// This tests stacking. It also shows how to use b2World::Query -/// and b2TestOverlap. - -/// This callback is called by b2World::QueryAABB. We find all the fixtures -/// that overlap an AABB. Of those, we use b2TestOverlap to determine which fixtures -/// overlap a circle. Up to 4 overlapped fixtures will be highlighted with a yellow border. -class PolygonShapesCallback : public b2QueryCallback -{ -public: - enum - { - e_maxCount = 4 - }; - - PolygonShapesCallback() { m_count = 0; } - - /// Called for each fixture found in the query AABB. - /// @return false to terminate the query. - bool ReportFixture(b2Fixture* fixture) override - { - if (m_count == e_maxCount) - { - return false; - } - - b2Body* body = fixture->GetBody(); - b2Shape* shape = fixture->GetShape(); - - bool overlap = b2TestOverlap(shape, 0, &m_circle, 0, body->GetTransform(), m_transform); - - if (overlap) - { - b2Color color(0.95f, 0.95f, 0.6f); - b2Vec2 center = body->GetWorldCenter(); - g_debugDraw->DrawPoint(center, 5.0f, color); - ++m_count; - } - - return true; - } - - b2CircleShape m_circle; - b2Transform m_transform; - b2Draw* g_debugDraw; - int32 m_count; -}; - -class PolygonShapes : public Test -{ -public: - enum - { - e_maxBodies = 256 - }; - - PolygonShapes() - { - // Ground body - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.5f, 0.0f); - vertices[1].Set(0.5f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[0].Set(vertices, 3); - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.1f, 0.0f); - vertices[1].Set(0.1f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[1].Set(vertices, 3); - } - - { - float w = 1.0f; - float b = w / (2.0f + b2Sqrt(2.0f)); - float s = b2Sqrt(2.0f) * b; - - b2Vec2 vertices[8]; - vertices[0].Set(0.5f * s, 0.0f); - vertices[1].Set(0.5f * w, b); - vertices[2].Set(0.5f * w, b + s); - vertices[3].Set(0.5f * s, w); - vertices[4].Set(-0.5f * s, w); - vertices[5].Set(-0.5f * w, b + s); - vertices[6].Set(-0.5f * w, b); - vertices[7].Set(-0.5f * s, 0.0f); - - m_polygons[2].Set(vertices, 8); - } - - { - m_polygons[3].SetAsBox(0.5f, 0.5f); - } - - { - m_circle.m_radius = 0.5f; - } - - m_bodyIndex = 0; - memset(m_bodies, 0, sizeof(m_bodies)); - } - - void Create(int32 index) - { - if (m_bodies[m_bodyIndex] != NULL) - { - m_world->DestroyBody(m_bodies[m_bodyIndex]); - m_bodies[m_bodyIndex] = NULL; - } - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - float x = RandomFloat(-2.0f, 2.0f); - bd.position.Set(x, 10.0f); - bd.angle = RandomFloat(-b2_pi, b2_pi); - - if (index == 4) - { - bd.angularDamping = 0.02f; - } - - m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); - - if (index < 4) - { - b2FixtureDef fd; - fd.shape = m_polygons + index; - fd.density = 1.0f; - fd.friction = 0.3f; - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - else - { - b2FixtureDef fd; - fd.shape = &m_circle; - fd.density = 1.0f; - fd.friction = 0.3f; - - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - - m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; - } - - void DestroyBody() - { - for (int32 i = 0; i < e_maxBodies; ++i) - { - if (m_bodies[i] != NULL) - { - m_world->DestroyBody(m_bodies[i]); - m_bodies[i] = NULL; - return; - } - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_1: - case GLFW_KEY_2: - case GLFW_KEY_3: - case GLFW_KEY_4: - case GLFW_KEY_5: - Create(key - GLFW_KEY_1); - break; - - case GLFW_KEY_A: - for (int32 i = 0; i < e_maxBodies; i += 2) - { - if (m_bodies[i]) - { - bool enabled = m_bodies[i]->IsEnabled(); - m_bodies[i]->SetEnabled(!enabled); - } - } - break; - - case GLFW_KEY_D: - DestroyBody(); - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - PolygonShapesCallback callback; - callback.m_circle.m_radius = 2.0f; - callback.m_circle.m_p.Set(0.0f, 1.1f); - callback.m_transform.SetIdentity(); - callback.g_debugDraw = &g_debugDraw; - - b2AABB aabb; - callback.m_circle.ComputeAABB(&aabb, callback.m_transform, 0); - - m_world->QueryAABB(&callback, aabb); - - b2Color color(0.4f, 0.7f, 0.8f); - g_debugDraw.DrawCircle(callback.m_circle.m_p, callback.m_circle.m_radius, color); - - DrawString(5, m_textLine, "Press 1-5 to drop stuff, maximum of %d overlaps detected", - PolygonShapesCallback::e_maxCount); - - DrawString(5, m_textLine, "Press 'a' to enable/disable some bodies"); - - DrawString(5, m_textLine, "Press 'd' to destroy a body"); - } - - static Test* Create() { return new PolygonShapes; } - - int32 m_bodyIndex; - b2Body* m_bodies[e_maxBodies]; - b2PolygonShape m_polygons[4]; - b2CircleShape m_circle; -}; - -static int testIndex = RegisterTest("Geometry", "Polygon Shapes", PolygonShapes::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/prismatic_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/prismatic_joint.cpp deleted file mode 100644 index c9d05bed0c04..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/prismatic_joint.cpp +++ /dev/null @@ -1,114 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -// Test the prismatic joint with limits and motor options. -class PrismaticJoint : public Test -{ -public: - PrismaticJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - m_enableLimit = true; - m_enableMotor = false; - m_motorSpeed = 10.0f; - - { - b2PolygonShape shape; - shape.SetAsBox(1.0f, 1.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 10.0f); - bd.angle = 0.5f * b2_pi; - bd.allowSleep = false; - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 5.0f); - - b2PrismaticJointDef pjd; - - // Horizontal - pjd.Initialize(ground, body, bd.position, b2Vec2(1.0f, 0.0f)); - - pjd.motorSpeed = m_motorSpeed; - pjd.maxMotorForce = 10000.0f; - pjd.enableMotor = m_enableMotor; - pjd.lowerTranslation = -10.0f; - pjd.upperTranslation = 10.0f; - pjd.enableLimit = m_enableLimit; - - m_joint = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Checkbox("Limit", &m_enableLimit)) - { - m_joint->EnableLimit(m_enableLimit); - } - - if (ImGui::Checkbox("Motor", &m_enableMotor)) - { - m_joint->EnableMotor(m_enableMotor); - } - - if (ImGui::SliderFloat("Speed", &m_motorSpeed, -100.0f, 100.0f, "%.0f")) - { - m_joint->SetMotorSpeed(m_motorSpeed); - } - - ImGui::End(); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - float force = m_joint->GetMotorForce(settings.m_hertz); - DrawString(5, m_textLine, "Motor Force = %4.0f", force); - } - - static Test* Create() { return new PrismaticJoint; } - - b2PrismaticJoint* m_joint; - float m_motorSpeed; - bool m_enableMotor; - bool m_enableLimit; -}; - -static int testIndex = RegisterTest("Joints", "Prismatic", PrismaticJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/pulley_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/pulley_joint.cpp deleted file mode 100644 index b724673d148a..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/pulley_joint.cpp +++ /dev/null @@ -1,92 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class PulleyJoint : public Test -{ -public: - PulleyJoint() - { - float y = 16.0f; - float L = 12.0f; - float a = 1.0f; - float b = 2.0f; - - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2CircleShape circle; - circle.m_radius = 2.0f; - - circle.m_p.Set(-10.0f, y + b + L); - ground->CreateFixture(&circle, 0.0f); - - circle.m_p.Set(10.0f, y + b + L); - ground->CreateFixture(&circle, 0.0f); - } - - { - - b2PolygonShape shape; - shape.SetAsBox(a, b); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - // bd.fixedRotation = true; - bd.position.Set(-10.0f, y); - b2Body* body1 = m_world->CreateBody(&bd); - body1->CreateFixture(&shape, 5.0f); - - bd.position.Set(10.0f, y); - b2Body* body2 = m_world->CreateBody(&bd); - body2->CreateFixture(&shape, 5.0f); - - b2PulleyJointDef pulleyDef; - b2Vec2 anchor1(-10.0f, y + b); - b2Vec2 anchor2(10.0f, y + b); - b2Vec2 groundAnchor1(-10.0f, y + b + L); - b2Vec2 groundAnchor2(10.0f, y + b + L); - pulleyDef.Initialize(body1, body2, groundAnchor1, groundAnchor2, anchor1, anchor2, 1.5f); - - m_joint1 = (b2PulleyJoint*)m_world->CreateJoint(&pulleyDef); - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - float ratio = m_joint1->GetRatio(); - float L = m_joint1->GetCurrentLengthA() + ratio * m_joint1->GetCurrentLengthB(); - DrawString(5, m_textLine, "L1 + %4.2f * L2 = %4.2f", (float)ratio, (float)L); - } - - static Test* Create() { return new PulleyJoint; } - - b2PulleyJoint* m_joint1; -}; - -static int testIndex = RegisterTest("Joints", "Pulley", PulleyJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/pyramid.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/pyramid.cpp deleted file mode 100644 index 5f527451601a..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/pyramid.cpp +++ /dev/null @@ -1,89 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Pyramid : public Test -{ -public: - enum - { - e_count = 20 - }; - - Pyramid() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - float a = 0.5f; - b2PolygonShape shape; - shape.SetAsBox(a, a); - - b2Vec2 x(-7.0f, 0.75f); - b2Vec2 y; - b2Vec2 deltaX(0.5625f, 1.25f); - b2Vec2 deltaY(1.125f, 0.0f); - - for (int32 i = 0; i < e_count; ++i) - { - y = x; - - for (int32 j = i; j < e_count; ++j) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = y; - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 5.0f); - - y += deltaY; - } - - x += deltaX; - } - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - // b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; - - // if (m_stepCount == 400) - //{ - // tree->RebuildBottomUp(); - // } - } - - static Test* Create() { return new Pyramid; } -}; - -static int testIndex = RegisterTest("Stacking", "Pyramid", Pyramid::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/ray_cast.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/ray_cast.cpp deleted file mode 100644 index 81697a8542af..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/ray_cast.cpp +++ /dev/null @@ -1,463 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -enum -{ - e_maxBodies = 256 -}; - -// This test demonstrates how to use the world ray-cast feature. -// NOTE: we are intentionally filtering one of the polygons, therefore -// the ray will always miss one type of polygon. - -// This callback finds the closest hit. Polygon 0 is filtered. -class RayCastClosestCallback : public b2RayCastCallback -{ -public: - RayCastClosestCallback() { m_hit = false; } - - float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float fraction) override - { - uintptr_t index = fixture->GetUserData().pointer; - if (index == 1) - { - // By returning -1, we instruct the calling code to ignore this fixture and - // continue the ray-cast to the next fixture. - return -1.0f; - } - - m_hit = true; - m_point = point; - m_normal = normal; - - // By returning the current fraction, we instruct the calling code to clip the ray and - // continue the ray-cast to the next fixture. WARNING: do not assume that fixtures - // are reported in order. However, by clipping, we can always get the closest fixture. - return fraction; - } - - bool m_hit; - b2Vec2 m_point; - b2Vec2 m_normal; -}; - -// This callback finds any hit. Polygon 0 is filtered. For this type of query we are usually -// just checking for obstruction, so the actual fixture and hit point are irrelevant. -class RayCastAnyCallback : public b2RayCastCallback -{ -public: - RayCastAnyCallback() { m_hit = false; } - - float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float) override - { - uintptr_t index = fixture->GetUserData().pointer; - if (index == 1) - { - // By returning -1, we instruct the calling code to ignore this fixture and - // continue the ray-cast to the next fixture. - return -1.0f; - } - - m_hit = true; - m_point = point; - m_normal = normal; - - // At this point we have a hit, so we know the ray is obstructed. - // By returning 0, we instruct the calling code to terminate the ray-cast. - return 0.0f; - } - - bool m_hit; - b2Vec2 m_point; - b2Vec2 m_normal; -}; - -// This ray cast collects multiple hits along the ray. Polygon 0 is filtered. -// The fixtures are not necessary reported in order, so we might not capture -// the closest fixture. -class RayCastMultipleCallback : public b2RayCastCallback -{ -public: - enum - { - e_maxCount = 3 - }; - - RayCastMultipleCallback() { m_count = 0; } - - float ReportFixture(b2Fixture* fixture, const b2Vec2& point, const b2Vec2& normal, float) override - { - uintptr_t index = fixture->GetUserData().pointer; - if (index == 1) - { - // By returning -1, we instruct the calling code to ignore this fixture and - // continue the ray-cast to the next fixture. - return -1.0f; - } - - b2Assert(m_count < e_maxCount); - - m_points[m_count] = point; - m_normals[m_count] = normal; - ++m_count; - - if (m_count == e_maxCount) - { - // At this point the buffer is full. - // By returning 0, we instruct the calling code to terminate the ray-cast. - return 0.0f; - } - - // By returning 1, we instruct the caller to continue without clipping the ray. - return 1.0f; - } - - b2Vec2 m_points[e_maxCount]; - b2Vec2 m_normals[e_maxCount]; - int32 m_count; -}; - -class RayCast : public Test -{ -public: - enum Mode - { - e_any = 0, - e_closest = 1, - e_multiple = 2 - }; - - RayCast() - { - // Ground body - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.5f, 0.0f); - vertices[1].Set(0.5f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[0].Set(vertices, 3); - } - - { - b2Vec2 vertices[3]; - vertices[0].Set(-0.1f, 0.0f); - vertices[1].Set(0.1f, 0.0f); - vertices[2].Set(0.0f, 1.5f); - m_polygons[1].Set(vertices, 3); - } - - { - float w = 1.0f; - float b = w / (2.0f + b2Sqrt(2.0f)); - float s = b2Sqrt(2.0f) * b; - - b2Vec2 vertices[8]; - vertices[0].Set(0.5f * s, 0.0f); - vertices[1].Set(0.5f * w, b); - vertices[2].Set(0.5f * w, b + s); - vertices[3].Set(0.5f * s, w); - vertices[4].Set(-0.5f * s, w); - vertices[5].Set(-0.5f * w, b + s); - vertices[6].Set(-0.5f * w, b); - vertices[7].Set(-0.5f * s, 0.0f); - - m_polygons[2].Set(vertices, 8); - } - - { - m_polygons[3].SetAsBox(0.5f, 0.5f); - } - - { - m_circle.m_radius = 0.5f; - } - - { - m_edge.SetTwoSided(b2Vec2(-1.0f, 0.0f), b2Vec2(1.0f, 0.0f)); - } - - m_bodyIndex = 0; - memset(m_bodies, 0, sizeof(m_bodies)); - - m_degrees = 0.0f; - - m_mode = e_closest; - } - - void Create(int32 index) - { - if (m_bodies[m_bodyIndex] != NULL) - { - m_world->DestroyBody(m_bodies[m_bodyIndex]); - m_bodies[m_bodyIndex] = NULL; - } - - b2BodyDef bd; - - float x = RandomFloat(-10.0f, 10.0f); - float y = RandomFloat(0.0f, 20.0f); - bd.position.Set(x, y); - bd.angle = RandomFloat(-b2_pi, b2_pi); - - if (index == 4) - { - bd.angularDamping = 0.02f; - } - - m_bodies[m_bodyIndex] = m_world->CreateBody(&bd); - - if (index < 4) - { - b2FixtureDef fd; - fd.shape = m_polygons + index; - fd.friction = 0.3f; - fd.userData.pointer = index + 1; - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - else if (index < 5) - { - b2FixtureDef fd; - fd.shape = &m_circle; - fd.friction = 0.3f; - fd.userData.pointer = index + 1; - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - else - { - b2FixtureDef fd; - fd.shape = &m_edge; - fd.friction = 0.3f; - fd.userData.pointer = index + 1; - - m_bodies[m_bodyIndex]->CreateFixture(&fd); - } - - m_bodyIndex = (m_bodyIndex + 1) % e_maxBodies; - } - - void DestroyBody() - { - for (int32 i = 0; i < e_maxBodies; ++i) - { - if (m_bodies[i] != NULL) - { - m_world->DestroyBody(m_bodies[i]); - m_bodies[i] = NULL; - return; - } - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(g_debugDrawTestBed.debugNodeOffset.x, g_debugDrawTestBed.debugNodeOffset.y)); - ImGui::SetNextWindowSize(ImVec2(210.0f, 285.0f)); - ImGui::Begin("Ray-cast Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Button("Shape 1")) - { - Create(0); - } - - if (ImGui::Button("Shape 2")) - { - Create(1); - } - - if (ImGui::Button("Shape 3")) - { - Create(2); - } - - if (ImGui::Button("Shape 4")) - { - Create(3); - } - - if (ImGui::Button("Shape 5")) - { - Create(4); - } - - if (ImGui::Button("Shape 6")) - { - Create(5); - } - - if (ImGui::Button("Destroy Shape")) - { - DestroyBody(); - } - - ImGui::RadioButton("Any", &m_mode, e_any); - ImGui::RadioButton("Closest", &m_mode, e_closest); - ImGui::RadioButton("Multiple", &m_mode, e_multiple); - - ImGui::SliderFloat("Angle", &m_degrees, 0.0f, 360.0f, "%.0f"); - - ImGui::End(); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - DrawString(5, m_textLine, "Shape 1 is intentionally ignored by the ray"); - - switch (m_mode) - { - case e_closest: - DrawString(5, m_textLine, "Ray-cast mode: closest - find closest fixture along the ray"); - break; - - case e_any: - DrawString(5, m_textLine, "Ray-cast mode: any - check for obstruction"); - break; - - case e_multiple: - DrawString(5, m_textLine, "Ray-cast mode: multiple - gather multiple fixtures"); - break; - } - - float angle = b2_pi * m_degrees / 180.0f; - float L = 11.0f; - b2Vec2 point1(0.0f, 10.0f); - b2Vec2 d(L * cosf(angle), L * sinf(angle)); - b2Vec2 point2 = point1 + d; - - if (m_mode == e_closest) - { - RayCastClosestCallback callback; - m_world->RayCast(&callback, point1, point2); - - if (callback.m_hit) - { - g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); - g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); - b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; - g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); - } - else - { - g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); - } - } - else if (m_mode == e_any) - { - RayCastAnyCallback callback; - m_world->RayCast(&callback, point1, point2); - - if (callback.m_hit) - { - g_debugDraw.DrawPoint(callback.m_point, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); - g_debugDraw.DrawSegment(point1, callback.m_point, b2Color(0.8f, 0.8f, 0.8f)); - b2Vec2 head = callback.m_point + 0.5f * callback.m_normal; - g_debugDraw.DrawSegment(callback.m_point, head, b2Color(0.9f, 0.9f, 0.4f)); - } - else - { - g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); - } - } - else if (m_mode == e_multiple) - { - RayCastMultipleCallback callback; - m_world->RayCast(&callback, point1, point2); - g_debugDraw.DrawSegment(point1, point2, b2Color(0.8f, 0.8f, 0.8f)); - - for (int32 i = 0; i < callback.m_count; ++i) - { - b2Vec2 p = callback.m_points[i]; - b2Vec2 n = callback.m_normals[i]; - g_debugDraw.DrawPoint(p, 5.0f, b2Color(0.4f, 0.9f, 0.4f)); - g_debugDraw.DrawSegment(point1, p, b2Color(0.8f, 0.8f, 0.8f)); - b2Vec2 head = p + 0.5f * n; - g_debugDraw.DrawSegment(p, head, b2Color(0.9f, 0.9f, 0.4f)); - } - } - -#if 0 - // This case was failing. - { - b2Vec2 vertices[4]; - //vertices[0].Set(-22.875f, -3.0f); - //vertices[1].Set(22.875f, -3.0f); - //vertices[2].Set(22.875f, 3.0f); - //vertices[3].Set(-22.875f, 3.0f); - - b2PolygonShape shape; - //shape.Set(vertices, 4); - shape.SetAsBox(22.875f, 3.0f); - - b2RayCastInput input; - input.p1.Set(10.2725f,1.71372f); - input.p2.Set(10.2353f,2.21807f); - //input.maxFraction = 0.567623f; - input.maxFraction = 0.56762173f; - - b2Transform xf; - xf.SetIdentity(); - xf.position.Set(23.0f, 5.0f); - - b2RayCastOutput output; - bool hit; - hit = shape.RayCast(&output, input, xf); - hit = false; - - b2Color color(1.0f, 1.0f, 1.0f); - b2Vec2 vs[4]; - for (int32 i = 0; i < 4; ++i) - { - vs[i] = b2Mul(xf, shape.m_vertices[i]); - } - - g_debugDraw.DrawPolygon(vs, 4, color); - g_debugDraw.DrawSegment(input.p1, input.p2, color); - } -#endif - } - - static Test* Create() { return new RayCast; } - - int32 m_bodyIndex; - b2Body* m_bodies[e_maxBodies]; - b2PolygonShape m_polygons[4]; - b2CircleShape m_circle; - b2EdgeShape m_edge; - float m_degrees; - int32 m_mode; -}; - -static int testIndex = RegisterTest("Collision", "Ray Cast", RayCast::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/restitution.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/restitution.cpp deleted file mode 100644 index 10dd861e57f5..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/restitution.cpp +++ /dev/null @@ -1,75 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// Note: even with a restitution of 1.0, there is some energy change -// due to position correction. -class Restitution : public Test -{ -public: - Restitution() - { - const float threshold = 10.0f; - - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - - b2FixtureDef fd; - fd.shape = &shape; - fd.restitutionThreshold = threshold; - ground->CreateFixture(&fd); - } - - { - b2CircleShape shape; - shape.m_radius = 1.0f; - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 1.0f; - - float restitution[7] = {0.0f, 0.1f, 0.3f, 0.5f, 0.75f, 0.9f, 1.0f}; - - for (int32 i = 0; i < 7; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f + 3.0f * i, 20.0f); - - b2Body* body = m_world->CreateBody(&bd); - - fd.restitution = restitution[i]; - fd.restitutionThreshold = threshold; - body->CreateFixture(&fd); - } - } - } - - static Test* Create() { return new Restitution; } -}; - -static int testIndex = RegisterTest("Forces", "Restitution", Restitution::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/revolute_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/revolute_joint.cpp deleted file mode 100644 index 5c29859d833e..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/revolute_joint.cpp +++ /dev/null @@ -1,157 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -class RevoluteJoint : public Test -{ -public: - RevoluteJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - - b2FixtureDef fd; - fd.shape = &shape; - // fd.filter.categoryBits = 2; - - ground->CreateFixture(&fd); - } - - m_enableLimit = true; - m_enableMotor = false; - m_motorSpeed = 1.0f; - - { - b2PolygonShape shape; - shape.SetAsBox(0.25f, 3.0f, b2Vec2(0.0f, 3.0f), 0.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f, 20.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 5.0f); - - b2RevoluteJointDef jd; - jd.Initialize(ground, body, b2Vec2(-10.0f, 20.5f)); - jd.motorSpeed = m_motorSpeed; - jd.maxMotorTorque = 10000.0f; - jd.enableMotor = m_enableMotor; - jd.lowerAngle = -0.25f * b2_pi; - jd.upperAngle = 0.5f * b2_pi; - jd.enableLimit = m_enableLimit; - - m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - } - - { - b2CircleShape circle_shape; - circle_shape.m_radius = 2.0f; - - b2BodyDef circle_bd; - circle_bd.type = b2_dynamicBody; - circle_bd.position.Set(5.0f, 30.0f); - - b2FixtureDef fd; - fd.density = 5.0f; - fd.filter.maskBits = 1; - fd.shape = &circle_shape; - - m_ball = m_world->CreateBody(&circle_bd); - m_ball->CreateFixture(&fd); - - b2PolygonShape polygon_shape; - polygon_shape.SetAsBox(10.0f, 0.5f, b2Vec2(-10.0f, 0.0f), 0.0f); - - b2BodyDef polygon_bd; - polygon_bd.position.Set(20.0f, 10.0f); - polygon_bd.type = b2_dynamicBody; - polygon_bd.bullet = true; - b2Body* polygon_body = m_world->CreateBody(&polygon_bd); - polygon_body->CreateFixture(&polygon_shape, 2.0f); - - b2RevoluteJointDef jd; - jd.Initialize(ground, polygon_body, b2Vec2(19.0f, 10.0f)); - jd.lowerAngle = -0.25f * b2_pi; - jd.upperAngle = 0.0f * b2_pi; - jd.enableLimit = true; - jd.enableMotor = true; - jd.motorSpeed = 0.0f; - jd.maxMotorTorque = 10000.0f; - - m_joint2 = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Checkbox("Limit", &m_enableLimit)) - { - m_joint1->EnableLimit(m_enableLimit); - } - - if (ImGui::Checkbox("Motor", &m_enableMotor)) - { - m_joint1->EnableMotor(m_enableMotor); - } - - if (ImGui::SliderFloat("Speed", &m_motorSpeed, -20.0f, 20.0f, "%.0f")) - { - m_joint1->SetMotorSpeed(m_motorSpeed); - } - - ImGui::End(); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - float torque1 = m_joint1->GetMotorTorque(settings.m_hertz); - DrawString(5, m_textLine, "Motor Torque 1= %4.0f", torque1); - - float torque2 = m_joint2->GetMotorTorque(settings.m_hertz); - DrawString(5, m_textLine, "Motor Torque 2= %4.0f", torque2); - } - - static Test* Create() { return new RevoluteJoint; } - - b2Body* m_ball; - b2RevoluteJoint* m_joint1; - b2RevoluteJoint* m_joint2; - float m_motorSpeed; - bool m_enableMotor; - bool m_enableLimit; -}; - -static int testIndex = RegisterTest("Joints", "Revolute", RevoluteJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/rope.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/rope.cpp deleted file mode 100644 index a36a60105ec7..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/rope.cpp +++ /dev/null @@ -1,282 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" -#include "box2d/b2_rope.h" -#include "ImGui/ImGuiPresenter.h" - -/// -class Rope : public Test -{ -public: - Rope() - { - const int32 N = 20; - const float L = 0.5f; - b2Vec2 vertices[N]; - float masses[N]; - - for (int32 i = 0; i < N; ++i) - { - vertices[i].Set(0.0f, L * (N - i)); - masses[i] = 1.0f; - } - masses[0] = 0.0f; - masses[1] = 0.0f; - - m_tuning1.bendHertz = 30.0f; - m_tuning1.bendDamping = 4.0f; - m_tuning1.bendStiffness = 1.0f; - m_tuning1.bendingModel = b2_pbdTriangleBendingModel; - m_tuning1.isometric = true; - - m_tuning1.stretchHertz = 30.0f; - m_tuning1.stretchDamping = 4.0f; - m_tuning1.stretchStiffness = 1.0f; - m_tuning1.stretchingModel = b2_pbdStretchingModel; - - m_tuning2.bendHertz = 30.0f; - m_tuning2.bendDamping = 0.7f; - m_tuning2.bendStiffness = 1.0f; - m_tuning2.bendingModel = b2_pbdHeightBendingModel; - m_tuning2.isometric = true; - - m_tuning2.stretchHertz = 30.0f; - m_tuning2.stretchDamping = 1.0f; - m_tuning2.stretchStiffness = 1.0f; - m_tuning2.stretchingModel = b2_pbdStretchingModel; - - m_position1.Set(-5.0f, 15.0f); - m_position2.Set(5.0f, 15.0f); - - b2RopeDef def; - def.vertices = vertices; - def.count = N; - def.gravity.Set(0.0f, -10.0f); - def.masses = masses; - - def.position = m_position1; - def.tuning = m_tuning1; - m_rope1.Create(def); - - def.position = m_position2; - def.tuning = m_tuning2; - m_rope2.Create(def); - - m_iterations1 = 8; - m_iterations2 = 8; - - m_speed = 10.0f; - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 700.0f)); - ImGui::Begin("Tuning", nullptr, ImGuiWindowFlags_NoResize); - - ImGui::Separator(); - - ImGui::PushItemWidth(ImGui::GetWindowWidth() * 0.5f); - - const ImGuiComboFlags comboFlags = 0; - const char* bendModels[] = {"Spring", "PBD Ang", "XPBD Ang", "PBD Dist", "PBD Height", "PBD Triangle"}; - const char* stretchModels[] = {"PBD", "XPBD"}; - - ImGui::Text("Rope 1"); - static int bendModel1 = m_tuning1.bendingModel; - if (ImGui::BeginCombo("Bend Model##1", bendModels[bendModel1], comboFlags)) - { - for (int i = 0; i < IM_ARRAYSIZE(bendModels); ++i) - { - bool isSelected = (bendModel1 == i); - if (ImGui::Selectable(bendModels[i], isSelected)) - { - bendModel1 = i; - m_tuning1.bendingModel = b2BendingModel(i); - } - - if (isSelected) - { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - ImGui::SliderFloat("Damping##B1", &m_tuning1.bendDamping, 0.0f, 4.0f, "%.1f"); - ImGui::SliderFloat("Hertz##B1", &m_tuning1.bendHertz, 0.0f, 60.0f, "%.0f"); - ImGui::SliderFloat("Stiffness##B1", &m_tuning1.bendStiffness, 0.0f, 1.0f, "%.1f"); - - ImGui::Checkbox("Isometric##1", &m_tuning1.isometric); - ImGui::Checkbox("Fixed Mass##1", &m_tuning1.fixedEffectiveMass); - ImGui::Checkbox("Warm Start##1", &m_tuning1.warmStart); - - static int stretchModel1 = m_tuning1.stretchingModel; - if (ImGui::BeginCombo("Stretch Model##1", stretchModels[stretchModel1], comboFlags)) - { - for (int i = 0; i < IM_ARRAYSIZE(stretchModels); ++i) - { - bool isSelected = (stretchModel1 == i); - if (ImGui::Selectable(stretchModels[i], isSelected)) - { - stretchModel1 = i; - m_tuning1.stretchingModel = b2StretchingModel(i); - } - - if (isSelected) - { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - ImGui::SliderFloat("Damping##S1", &m_tuning1.stretchDamping, 0.0f, 4.0f, "%.1f"); - ImGui::SliderFloat("Hertz##S1", &m_tuning1.stretchHertz, 0.0f, 60.0f, "%.0f"); - ImGui::SliderFloat("Stiffness##S1", &m_tuning1.stretchStiffness, 0.0f, 1.0f, "%.1f"); - - ImGui::SliderInt("Iterations##1", &m_iterations1, 1, 100, "%d"); - - ImGui::Separator(); - - ImGui::Text("Rope 2"); - static int bendModel2 = m_tuning2.bendingModel; - if (ImGui::BeginCombo("Bend Model##2", bendModels[bendModel2], comboFlags)) - { - for (int i = 0; i < IM_ARRAYSIZE(bendModels); ++i) - { - bool isSelected = (bendModel2 == i); - if (ImGui::Selectable(bendModels[i], isSelected)) - { - bendModel2 = i; - m_tuning2.bendingModel = b2BendingModel(i); - } - - if (isSelected) - { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - ImGui::SliderFloat("Damping##B2", &m_tuning2.bendDamping, 0.0f, 4.0f, "%.1f"); - ImGui::SliderFloat("Hertz##B2", &m_tuning2.bendHertz, 0.0f, 60.0f, "%.0f"); - ImGui::SliderFloat("Stiffness##B2", &m_tuning2.bendStiffness, 0.0f, 1.0f, "%.1f"); - - ImGui::Checkbox("Isometric##2", &m_tuning2.isometric); - ImGui::Checkbox("Fixed Mass##2", &m_tuning2.fixedEffectiveMass); - ImGui::Checkbox("Warm Start##2", &m_tuning2.warmStart); - - static int stretchModel2 = m_tuning2.stretchingModel; - if (ImGui::BeginCombo("Stretch Model##2", stretchModels[stretchModel2], comboFlags)) - { - for (int i = 0; i < IM_ARRAYSIZE(stretchModels); ++i) - { - bool isSelected = (stretchModel2 == i); - if (ImGui::Selectable(stretchModels[i], isSelected)) - { - stretchModel2 = i; - m_tuning2.stretchingModel = b2StretchingModel(i); - } - - if (isSelected) - { - ImGui::SetItemDefaultFocus(); - } - } - ImGui::EndCombo(); - } - - ImGui::SliderFloat("Damping##S2", &m_tuning2.stretchDamping, 0.0f, 4.0f, "%.1f"); - ImGui::SliderFloat("Hertz##S2", &m_tuning2.stretchHertz, 0.0f, 60.0f, "%.0f"); - ImGui::SliderFloat("Stiffness##S2", &m_tuning2.stretchStiffness, 0.0f, 1.0f, "%.1f"); - - ImGui::SliderInt("Iterations##2", &m_iterations2, 1, 100, "%d"); - - ImGui::Separator(); - - ImGui::SliderFloat("Speed", &m_speed, 10.0f, 100.0f, "%.0f"); - - if (ImGui::Button("Reset")) - { - m_position1.Set(-5.0f, 15.0f); - m_position2.Set(5.0f, 15.0f); - m_rope1.Reset(m_position1); - m_rope2.Reset(m_position2); - } - - ImGui::PopItemWidth(); - - ImGui::End(); - } - - void Step(Settings& settings) override - { - float dt = settings.m_hertz > 0.0f ? 1.0f / settings.m_hertz : 0.0f; - - if (settings.m_pause == 1 && settings.m_singleStep == 0) - { - dt = 0.0f; - } - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_COMMA) == GLFW_PRESS) - //{ - // m_position1.x -= m_speed * dt; - // m_position2.x -= m_speed * dt; - // } - - // if (glfwGetKey(g_mainWindow, GLFW_KEY_PERIOD) == GLFW_PRESS) - //{ - // m_position1.x += m_speed * dt; - // m_position2.x += m_speed * dt; - // } - - m_rope1.SetTuning(m_tuning1); - m_rope2.SetTuning(m_tuning2); - m_rope1.Step(dt, m_iterations1, m_position1); - m_rope2.Step(dt, m_iterations2, m_position2); - - Test::Step(settings); - - m_rope1.Draw(&g_debugDraw); - m_rope2.Draw(&g_debugDraw); - - DrawString(5, m_textLine, "Press comma and period to move left and right"); - } - - static Test* Create() { return new Rope; } - - b2Rope m_rope1; - b2Rope m_rope2; - b2RopeTuning m_tuning1; - b2RopeTuning m_tuning2; - int32 m_iterations1; - int32 m_iterations2; - b2Vec2 m_position1; - b2Vec2 m_position2; - float m_speed; -}; - -static int testIndex = RegisterTest("Rope", "Bending", Rope::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/sensor.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/sensor.cpp deleted file mode 100644 index 9c3985412566..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/sensor.cpp +++ /dev/null @@ -1,191 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -// This shows how to use sensor shapes. Sensors don't have collision, but report overlap events. -class Sensors : public Test -{ -public: - enum - { - e_count = 7 - }; - - Sensors() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - { - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - -#if 0 - { - b2FixtureDef sd; - sd.SetAsBox(10.0f, 2.0f, b2Vec2(0.0f, 20.0f), 0.0f); - sd.isSensor = true; - m_sensor = ground->CreateFixture(&sd); - } -#else - { - b2CircleShape shape; - shape.m_radius = 5.0f; - shape.m_p.Set(0.0f, 10.0f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.isSensor = true; - m_sensor = ground->CreateFixture(&fd); - } -#endif - } - - { - b2CircleShape shape; - shape.m_radius = 1.0f; - - for (int32 i = 0; i < e_count; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-10.0f + 3.0f * i, 20.0f); - bd.userData.pointer = i; - - m_touching[i] = false; - m_bodies[i] = m_world->CreateBody(&bd); - - m_bodies[i]->CreateFixture(&shape, 1.0f); - } - } - - m_force = 100.0f; - } - - // Implement contact listener. - void BeginContact(b2Contact* contact) override - { - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - - if (fixtureA == m_sensor) - { - uintptr_t index = fixtureB->GetBody()->GetUserData().pointer; - if (index < e_count) - { - m_touching[index] = true; - } - } - - if (fixtureB == m_sensor) - { - uintptr_t index = fixtureA->GetBody()->GetUserData().pointer; - if (index < e_count) - { - m_touching[index] = true; - } - } - } - - // Implement contact listener. - void EndContact(b2Contact* contact) override - { - b2Fixture* fixtureA = contact->GetFixtureA(); - b2Fixture* fixtureB = contact->GetFixtureB(); - - if (fixtureA == m_sensor) - { - uintptr_t index = fixtureB->GetBody()->GetUserData().pointer; - if (index < e_count) - { - m_touching[index] = false; - } - } - - if (fixtureB == m_sensor) - { - uintptr_t index = fixtureA->GetBody()->GetUserData().pointer; - if (index < e_count) - { - m_touching[index] = false; - } - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 60.0f)); - ImGui::Begin("Sensor Controls", nullptr, ImGuiWindowFlags_NoResize); - - ImGui::SliderFloat("Force", &m_force, 0.0f, 2000.0f, "%.0f"); - - ImGui::End(); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - // Traverse the contact results. Apply a force on shapes - // that overlap the sensor. - for (int32 i = 0; i < e_count; ++i) - { - if (m_touching[i] == false) - { - continue; - } - - b2Body* body = m_bodies[i]; - b2Body* ground = m_sensor->GetBody(); - - b2CircleShape* circle = (b2CircleShape*)m_sensor->GetShape(); - b2Vec2 center = ground->GetWorldPoint(circle->m_p); - - b2Vec2 position = body->GetPosition(); - - b2Vec2 d = center - position; - if (d.LengthSquared() < FLT_EPSILON * FLT_EPSILON) - { - continue; - } - - d.Normalize(); - b2Vec2 F = m_force * d; - body->ApplyForce(F, position, false); - } - } - - static Test* Create() { return new Sensors; } - - b2Fixture* m_sensor; - b2Body* m_bodies[e_count]; - float m_force; - bool m_touching[e_count]; -}; - -static int testIndex = RegisterTest("Collision", "Sensors", Sensors::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/settings.h b/tests/cpp-tests/Source/Box2DTestBed/tests/settings.h deleted file mode 100644 index 7ba71423e898..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/settings.h +++ /dev/null @@ -1,83 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#ifndef SETTINGS_H -#define SETTINGS_H - -struct Settings -{ - Settings() { Reset(); } - - void Reset() - { - m_testIndex = 0; - m_windowWidth = 1600; - m_windowHeight = 900; - m_hertz = 60.0f; - m_velocityIterations = 8; - m_positionIterations = 3; - m_drawShapes = true; - m_drawJoints = true; - m_drawAABBs = false; - m_drawContactPoints = false; - m_drawContactNormals = false; - m_drawContactImpulse = false; - m_drawFrictionImpulse = false; - m_drawCOMs = false; - m_drawStats = false; - m_drawProfile = false; - m_enableWarmStarting = true; - m_enableContinuous = true; - m_enableSubStepping = false; - m_enableSleep = true; - m_pause = false; - m_singleStep = false; - } - - void Save(); - void Load(); - - int m_testIndex; - int m_windowWidth; - int m_windowHeight; - float m_hertz; - int m_velocityIterations; - int m_positionIterations; - bool m_drawShapes; - bool m_drawJoints; - bool m_drawAABBs; - bool m_drawContactPoints; - bool m_drawContactNormals; - bool m_drawContactImpulse; - bool m_drawFrictionImpulse; - bool m_drawCOMs; - bool m_drawStats; - bool m_drawProfile; - bool m_enableWarmStarting; - bool m_enableContinuous; - bool m_enableSubStepping; - bool m_enableSleep; - bool m_pause; - bool m_singleStep; -}; - -#endif \ No newline at end of file diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/shape_cast.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/shape_cast.cpp deleted file mode 100644 index 60771b589681..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/shape_cast.cpp +++ /dev/null @@ -1,189 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "box2d/b2_distance.h" - -class ShapeCast : public Test -{ -public: - enum - { - e_vertexCount = 8 - }; - - ShapeCast() - { -#if 1 - m_vAs[0].Set(-0.5f, 1.0f); - m_vAs[1].Set(0.5f, 1.0f); - m_vAs[2].Set(0.0f, 0.0f); - m_countA = 3; - m_radiusA = b2_polygonRadius; - - m_vBs[0].Set(-0.5f, -0.5f); - m_vBs[1].Set(0.5f, -0.5f); - m_vBs[2].Set(0.5f, 0.5f); - m_vBs[3].Set(-0.5f, 0.5f); - m_countB = 4; - m_radiusB = b2_polygonRadius; - - m_transformA.p.Set(0.0f, 0.25f); - m_transformA.q.SetIdentity(); - m_transformB.p.Set(-4.0f, 0.0f); - m_transformB.q.SetIdentity(); - m_translationB.Set(8.0f, 0.0f); -#elif 0 - m_vAs[0].Set(0.0f, 0.0f); - m_countA = 1; - m_radiusA = 0.5f; - - m_vBs[0].Set(0.0f, 0.0f); - m_countB = 1; - m_radiusB = 0.5f; - - m_transformA.p.Set(0.0f, 0.25f); - m_transformA.q.SetIdentity(); - m_transformB.p.Set(-4.0f, 0.0f); - m_transformB.q.SetIdentity(); - m_translationB.Set(8.0f, 0.0f); -#else - m_vAs[0].Set(0.0f, 0.0f); - m_vAs[1].Set(2.0f, 0.0f); - m_countA = 2; - m_radiusA = b2_polygonRadius; - - m_vBs[0].Set(0.0f, 0.0f); - m_countB = 1; - m_radiusB = 0.25f; - - // Initial overlap - m_transformA.p.Set(0.0f, 0.0f); - m_transformA.q.SetIdentity(); - m_transformB.p.Set(-0.244360745f, 0.05999358f); - m_transformB.q.SetIdentity(); - m_translationB.Set(0.0f, 0.0399999991f); -#endif - } - - static Test* Create() { return new ShapeCast; } - - void Step(Settings& settings) override - { - Test::Step(settings); - - b2ShapeCastInput input; - input.proxyA.Set(m_vAs, m_countA, m_radiusA); - input.proxyB.Set(m_vBs, m_countB, m_radiusB); - input.transformA = m_transformA; - input.transformB = m_transformB; - input.translationB = m_translationB; - - b2ShapeCastOutput output; - bool hit = b2ShapeCast(&output, &input); - - b2Transform transformB2; - transformB2.q = m_transformB.q; - transformB2.p = m_transformB.p + output.lambda * input.translationB; - - b2DistanceInput distanceInput; - distanceInput.proxyA.Set(m_vAs, m_countA, m_radiusA); - distanceInput.proxyB.Set(m_vBs, m_countB, m_radiusB); - distanceInput.transformA = m_transformA; - distanceInput.transformB = transformB2; - distanceInput.useRadii = false; - b2SimplexCache simplexCache; - simplexCache.count = 0; - b2DistanceOutput distanceOutput; - - b2Distance(&distanceOutput, &simplexCache, &distanceInput); - - DrawString(5, m_textLine, "hit = %s, iters = %d, lambda = %g, distance = %g", hit ? "true" : "false", - output.iterations, output.lambda, distanceOutput.distance); - - b2Vec2 vertices[b2_maxPolygonVertices]; - - for (int32 i = 0; i < m_countA; ++i) - { - vertices[i] = b2Mul(m_transformA, m_vAs[i]); - } - - if (m_countA == 1) - { - g_debugDraw.DrawCircle(vertices[0], m_radiusA, b2Color(0.9f, 0.9f, 0.9f)); - } - else - { - g_debugDraw.DrawPolygon(vertices, m_countA, b2Color(0.9f, 0.9f, 0.9f)); - } - - for (int32 i = 0; i < m_countB; ++i) - { - vertices[i] = b2Mul(m_transformB, m_vBs[i]); - } - - if (m_countB == 1) - { - g_debugDraw.DrawCircle(vertices[0], m_radiusB, b2Color(0.5f, 0.9f, 0.5f)); - } - else - { - g_debugDraw.DrawPolygon(vertices, m_countB, b2Color(0.5f, 0.9f, 0.5f)); - } - - for (int32 i = 0; i < m_countB; ++i) - { - vertices[i] = b2Mul(transformB2, m_vBs[i]); - } - - if (m_countB == 1) - { - g_debugDraw.DrawCircle(vertices[0], m_radiusB, b2Color(0.5f, 0.7f, 0.9f)); - } - else - { - g_debugDraw.DrawPolygon(vertices, m_countB, b2Color(0.5f, 0.7f, 0.9f)); - } - - if (hit) - { - b2Vec2 p1 = output.point; - g_debugDraw.DrawPoint(p1, 10.0f, b2Color(0.9f, 0.3f, 0.3f)); - b2Vec2 p2 = p1 + output.normal; - g_debugDraw.DrawSegment(p1, p2, b2Color(0.9f, 0.3f, 0.3f)); - } - } - - b2Vec2 m_vAs[b2_maxPolygonVertices]; - int32 m_countA; - float m_radiusA; - - b2Vec2 m_vBs[b2_maxPolygonVertices]; - int32 m_countB; - float m_radiusB; - - b2Transform m_transformA; - b2Transform m_transformB; - b2Vec2 m_translationB; -}; - -static int testIndex = RegisterTest("Collision", "Shape Cast", ShapeCast::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/shape_editing.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/shape_editing.cpp deleted file mode 100644 index c7b753b52400..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/shape_editing.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class ShapeEditing : public Test -{ -public: - ShapeEditing() - { - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 10.0f); - m_body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(4.0f, 4.0f, b2Vec2(0.0f, 0.0f), 0.0f); - m_fixture1 = m_body->CreateFixture(&shape, 10.0f); - - m_fixture2 = NULL; - - m_sensor = false; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_C: - if (m_fixture2 == NULL) - { - b2CircleShape shape; - shape.m_radius = 3.0f; - shape.m_p.Set(0.5f, -4.0f); - m_fixture2 = m_body->CreateFixture(&shape, 10.0f); - m_body->SetAwake(true); - } - break; - - case GLFW_KEY_D: - if (m_fixture2 != NULL) - { - m_body->DestroyFixture(m_fixture2); - m_fixture2 = NULL; - m_body->SetAwake(true); - } - break; - - case GLFW_KEY_S: - if (m_fixture2 != NULL) - { - m_sensor = !m_sensor; - m_fixture2->SetSensor(m_sensor); - } - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - DrawString(5, m_textLine, "Press: (c) create a shape, (d) destroy a shape."); - - DrawString(5, m_textLine, "sensor = %d", m_sensor); - } - - static Test* Create() { return new ShapeEditing; } - - b2Body* m_body; - b2Fixture* m_fixture1; - b2Fixture* m_fixture2; - bool m_sensor; -}; - -static int testIndex = RegisterTest("Examples", "Shape Editing", ShapeEditing::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/skier.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/skier.cpp deleted file mode 100644 index 05529640a25c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/skier.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* -Test case for collision/jerking issue. -*/ - -#include "test.h" - -#include -#include - -class Skier : public Test -{ -public: - Skier() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - float const PlatformWidth = 8.0f; - - /* - First angle is from the horizontal and should be negative for a downward slope. - Second angle is relative to the preceding slope, and should be positive, creating a kind of - loose 'Z'-shape from the 3 edges. - If A1 = -10, then A2 <= ~1.5 will result in the collision glitch. - If A1 = -30, then A2 <= ~10.0 will result in the glitch. - */ - float const Angle1Degrees = -30.0f; - float const Angle2Degrees = 10.0f; - - /* - The larger the value of SlopeLength, the less likely the glitch will show up. - */ - float const SlopeLength = 2.0f; - - float const SurfaceFriction = 0.2f; - - // Convert to radians - float const Slope1Incline = -Angle1Degrees * b2_pi / 180.0f; - float const Slope2Incline = Slope1Incline - Angle2Degrees * b2_pi / 180.0f; - // - - m_platform_width = PlatformWidth; - - // Horizontal platform - b2Vec2 v1(-PlatformWidth, 0.0f); - b2Vec2 v2(0.0f, 0.0f); - b2Vec2 v3(SlopeLength * cosf(Slope1Incline), -SlopeLength * sinf(Slope1Incline)); - b2Vec2 v4(v3.x + SlopeLength * cosf(Slope2Incline), v3.y - SlopeLength * sinf(Slope2Incline)); - b2Vec2 v5(v4.x, v4.y - 1.0f); - - b2Vec2 vertices[5] = {v5, v4, v3, v2, v1}; - - b2ChainShape shape; - shape.CreateLoop(vertices, 5); - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 0.0f; - fd.friction = SurfaceFriction; - - ground->CreateFixture(&fd); - } - - { - float const BodyWidth = 1.0f; - float const BodyHeight = 2.5f; - float const SkiLength = 3.0f; - - /* - Larger values for this seem to alleviate the issue to some extent. - */ - float const SkiThickness = 0.3f; - - float const SkiFriction = 0.0f; - float const SkiRestitution = 0.15f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - float initial_y = BodyHeight / 2 + SkiThickness; - bd.position.Set(-m_platform_width / 2, initial_y); - - b2Body* skier = m_world->CreateBody(&bd); - - b2PolygonShape ski; - b2Vec2 verts[4]; - verts[0].Set(-SkiLength / 2 - SkiThickness, -BodyHeight / 2); - verts[1].Set(-SkiLength / 2, -BodyHeight / 2 - SkiThickness); - verts[2].Set(SkiLength / 2, -BodyHeight / 2 - SkiThickness); - verts[3].Set(SkiLength / 2 + SkiThickness, -BodyHeight / 2); - ski.Set(verts, 4); - - b2FixtureDef fd; - fd.density = 1.0f; - - fd.friction = SkiFriction; - fd.restitution = SkiRestitution; - - fd.shape = &ski; - skier->CreateFixture(&fd); - - skier->SetLinearVelocity(b2Vec2(0.5f, 0.0f)); - - m_skier = skier; - } - - // g_camera.m_center = b2Vec2(m_platform_width / 2.0f, 0.0f); - // g_camera.m_zoom = 0.4f; - m_fixed_camera = true; - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_C: - m_fixed_camera = !m_fixed_camera; - if (m_fixed_camera) - { - // g_camera.m_center = b2Vec2(m_platform_width / 2.0f, 0.0f); - } - break; - } - } - - void Step(Settings& settings) override - { - DrawString(5, m_textLine, "Keys: c = Camera fixed/tracking"); - - if (!m_fixed_camera) - { - // g_camera.m_center = m_skier->GetPosition(); - } - - Test::Step(settings); - } - - static Test* Create() { return new Skier; } - - b2Body* m_skier; - float m_platform_width; - bool m_fixed_camera; -}; - -static int testIndex = RegisterTest("Bugs", "Skier", Skier::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_1.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_1.cpp deleted file mode 100644 index e09e8ade1992..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_1.cpp +++ /dev/null @@ -1,103 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// A basic slider crank created for GDC tutorial: Understanding Constraints -class SliderCrank1 : public Test -{ -public: - SliderCrank1() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - bd.position.Set(0.0f, 17.0f); - ground = m_world->CreateBody(&bd); - } - - { - b2Body* prevBody = ground; - - // Define crank. - { - b2PolygonShape shape; - shape.SetAsBox(4.0f, 1.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-8.0f, 20.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(-12.0f, 20.0f)); - m_world->CreateJoint(&rjd); - - prevBody = body; - } - - // Define connecting rod - { - b2PolygonShape shape; - shape.SetAsBox(8.0f, 1.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(4.0f, 20.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(-4.0f, 20.0f)); - m_world->CreateJoint(&rjd); - - prevBody = body; - } - - // Define piston - { - b2PolygonShape shape; - shape.SetAsBox(3.0f, 3.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.position.Set(12.0f, 20.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(12.0f, 20.0f)); - m_world->CreateJoint(&rjd); - - b2PrismaticJointDef pjd; - pjd.Initialize(ground, body, b2Vec2(12.0f, 17.0f), b2Vec2(1.0f, 0.0f)); - m_world->CreateJoint(&pjd); - } - } - } - - static Test* Create() { return new SliderCrank1; } -}; - -static int testIndex = RegisterTest("Examples", "Slider Crank 1", SliderCrank1::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_2.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_2.cpp deleted file mode 100644 index f55a05859cf6..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/slider_crank_2.cpp +++ /dev/null @@ -1,156 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" - -// A motor driven slider crank with joint friction. - -class SliderCrank2 : public Test -{ -public: - SliderCrank2() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2Body* prevBody = ground; - - // Define crank. - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 2.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 7.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(0.0f, 5.0f)); - rjd.motorSpeed = 1.0f * b2_pi; - rjd.maxMotorTorque = 10000.0f; - rjd.enableMotor = true; - m_joint1 = (b2RevoluteJoint*)m_world->CreateJoint(&rjd); - - prevBody = body; - } - - // Define follower. - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 4.0f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 13.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(0.0f, 9.0f)); - rjd.enableMotor = false; - m_world->CreateJoint(&rjd); - - prevBody = body; - } - - // Define piston - { - b2PolygonShape shape; - shape.SetAsBox(1.5f, 1.5f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.fixedRotation = true; - bd.position.Set(0.0f, 17.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - - b2RevoluteJointDef rjd; - rjd.Initialize(prevBody, body, b2Vec2(0.0f, 17.0f)); - m_world->CreateJoint(&rjd); - - b2PrismaticJointDef pjd; - pjd.Initialize(ground, body, b2Vec2(0.0f, 17.0f), b2Vec2(0.0f, 1.0f)); - - pjd.maxMotorForce = 1000.0f; - pjd.enableMotor = true; - - m_joint2 = (b2PrismaticJoint*)m_world->CreateJoint(&pjd); - } - - // Create a payload - { - b2PolygonShape shape; - shape.SetAsBox(1.5f, 1.5f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 23.0f); - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 2.0f); - } - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_F: - m_joint2->EnableMotor(!m_joint2->IsMotorEnabled()); - m_joint2->GetBodyB()->SetAwake(true); - break; - - case GLFW_KEY_M: - m_joint1->EnableMotor(!m_joint1->IsMotorEnabled()); - m_joint1->GetBodyB()->SetAwake(true); - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - DrawString(5, m_textLine, "Keys: (f) toggle friction, (m) toggle motor"); - - float torque = m_joint1->GetMotorTorque(settings.m_hertz); - DrawString(5, m_textLine, "Motor Torque = %5.0f", (float)torque); - } - - static Test* Create() { return new SliderCrank2; } - - b2RevoluteJoint* m_joint1; - b2PrismaticJoint* m_joint2; -}; - -static int testIndex = RegisterTest("Examples", "Slider Crank 2", SliderCrank2::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/test.h b/tests/cpp-tests/Source/Box2DTestBed/tests/test.h deleted file mode 100644 index 680a6226c4cd..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/test.h +++ /dev/null @@ -1,150 +0,0 @@ -/* - * Copyright (c) 2006-2009 Erin Catto http://www.box2d.org - * - * This software is provided 'as-is', without any express or implied - * warranty. In no event will the authors be held liable for any damages - * arising from the use of this software. - * Permission is granted to anyone to use this software for any purpose, - * including commercial applications, and to alter it and redistribute it - * freely, subject to the following restrictions: - * 1. The origin of this software must not be misrepresented; you must not - * claim that you wrote the original software. If you use this software - * in a product, an acknowledgment in the product documentation would be - * appreciated but is not required. - * 2. Altered source versions must be plainly marked as such, and must not be - * misrepresented as being the original software. - * 3. This notice may not be removed or altered from any source distribution. - */ - -#ifndef TEST_H -#define TEST_H - -#include "box2d/box2d.h" -#include "extensions/axmol-ext.h" - -#include - -class Test; -struct Settings; - -#define RAND_LIMIT 32767 -#define DRAW_STRING_NEW_LINE 25 - -/// Random number in range [-1,1] -inline float RandomFloat() -{ - float r = (float)(std::rand() & (RAND_LIMIT)); - r /= RAND_LIMIT; - r = 2.0f * r - 1.0f; - return r; -} - -/// Random floating point number in range [lo, hi] -inline float RandomFloat(float lo, float hi) -{ - float r = (float)(std::rand() & (RAND_LIMIT)); - r /= RAND_LIMIT; - r = (hi - lo) * r + lo; - return r; -} - -// This is called when a joint in the world is implicitly destroyed -// because an attached body is destroyed. This gives us a chance to -// nullify the mouse joint. -class DestructionListener : public b2DestructionListener -{ -public: - void SayGoodbye(b2Fixture* fixture) { B2_NOT_USED(fixture); } - void SayGoodbye(b2Joint* joint); - - Test* test; -}; - -const int32 k_maxContactPoints = 2048; - -struct ContactPoint -{ - b2Fixture* fixtureA; - b2Fixture* fixtureB; - b2Vec2 normal; - b2Vec2 position; - b2PointState state; - float normalImpulse; - float tangentImpulse; - float separation; -}; -class Test : public b2ContactListener -{ -public: - Test(); - virtual ~Test(); - - void DrawTitle(const char* string); - virtual void Step(Settings& settings); - virtual void UpdateUI() {} - virtual void Keyboard(int key) { B2_NOT_USED(key); } - virtual void KeyboardUp(int key) { B2_NOT_USED(key); } - void ShiftMouseDown(const b2Vec2& p); - virtual bool MouseDown(const b2Vec2& p); - virtual void MouseUp(const b2Vec2& p); - virtual void MouseMove(const b2Vec2& p); - void LaunchBomb(); - void LaunchBomb(const b2Vec2& position, const b2Vec2& velocity); - - void SpawnBomb(const b2Vec2& worldPt); - void CompleteBombSpawn(const b2Vec2& p); - - // Let derived tests know that a joint was destroyed. - virtual void JointDestroyed(b2Joint* joint) { B2_NOT_USED(joint); } - - // Callbacks for derived classes. - virtual void BeginContact(b2Contact* contact) override { B2_NOT_USED(contact); } - virtual void EndContact(b2Contact* contact) override { B2_NOT_USED(contact); } - virtual void PreSolve(b2Contact* contact, const b2Manifold* oldManifold) override; - virtual void PostSolve(b2Contact* contact, const b2ContactImpulse* impulse) override - { - B2_NOT_USED(contact); - B2_NOT_USED(impulse); - } - - void ShiftOrigin(const b2Vec2& newOrigin); - - void initShader(void); - void DrawString(int x, int y, const char* fmt, ...); - void DrawString(const b2Vec2& p, const char* fmt, ...); - void DrawAABB(b2AABB* aabb, const b2Color& color); - void Flush(); - - ax::extension::PhysicsDebugNodeBox2D g_debugDraw; - ax::DrawNode* debugDrawNode; - std::string debugString = ""; - - b2World* m_world; - -protected: - friend class DestructionListener; - friend class BoundaryListener; - friend class ContactListener; - - b2Body* m_groundBody; - b2AABB m_worldAABB; - ContactPoint m_points[k_maxContactPoints]; - int32 m_pointCount; - DestructionListener m_destructionListener; - int32 m_textLine; - - b2Body* m_bomb; - b2MouseJoint* m_mouseJoint; - b2Vec2 m_bombSpawnPoint; - bool m_bombSpawning; - b2Vec2 m_mouseWorld; - int32 m_stepCount; - int32 m_textIncrement; - b2Profile m_maxProfile; - b2Profile m_totalProfile; -}; - -typedef Test* TestCreateFcn(); -int RegisterTest(const char* category, const char* name, TestCreateFcn* fcn); - -#endif diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/theo_jansen.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/theo_jansen.cpp deleted file mode 100644 index cab814037c1c..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/theo_jansen.cpp +++ /dev/null @@ -1,261 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -// Inspired by a contribution from roman_m -// Dimensions scooped from APE (http://www.cove.org/ape/index.htm) - -#include "test.h" - -class TheoJansen : public Test -{ -public: - void CreateLeg(float s, const b2Vec2& wheelAnchor) - { - b2Vec2 p1(5.4f * s, -6.1f); - b2Vec2 p2(7.2f * s, -1.2f); - b2Vec2 p3(4.3f * s, -1.9f); - b2Vec2 p4(3.1f * s, 0.8f); - b2Vec2 p5(6.0f * s, 1.5f); - b2Vec2 p6(2.5f * s, 3.7f); - - b2FixtureDef fd1, fd2; - fd1.filter.groupIndex = -1; - fd2.filter.groupIndex = -1; - fd1.density = 1.0f; - fd2.density = 1.0f; - - b2PolygonShape poly1, poly2; - - if (s > 0.0f) - { - b2Vec2 vertices[3]; - - vertices[0] = p1; - vertices[1] = p2; - vertices[2] = p3; - poly1.Set(vertices, 3); - - vertices[0] = b2Vec2_zero; - vertices[1] = p5 - p4; - vertices[2] = p6 - p4; - poly2.Set(vertices, 3); - } - else - { - b2Vec2 vertices[3]; - - vertices[0] = p1; - vertices[1] = p3; - vertices[2] = p2; - poly1.Set(vertices, 3); - - vertices[0] = b2Vec2_zero; - vertices[1] = p6 - p4; - vertices[2] = p5 - p4; - poly2.Set(vertices, 3); - } - - fd1.shape = &poly1; - fd2.shape = &poly2; - - b2BodyDef bd1, bd2; - bd1.type = b2_dynamicBody; - bd2.type = b2_dynamicBody; - bd1.position = m_offset; - bd2.position = p4 + m_offset; - - bd1.angularDamping = 10.0f; - bd2.angularDamping = 10.0f; - - b2Body* body1 = m_world->CreateBody(&bd1); - b2Body* body2 = m_world->CreateBody(&bd2); - - body1->CreateFixture(&fd1); - body2->CreateFixture(&fd2); - - { - b2DistanceJointDef jd; - - // Using a soft distance constraint can reduce some jitter. - // It also makes the structure seem a bit more fluid by - // acting like a suspension system. - float dampingRatio = 0.5f; - float frequencyHz = 10.0f; - - jd.Initialize(body1, body2, p2 + m_offset, p5 + m_offset); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_world->CreateJoint(&jd); - - jd.Initialize(body1, body2, p3 + m_offset, p4 + m_offset); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_world->CreateJoint(&jd); - - jd.Initialize(body1, m_wheel, p3 + m_offset, wheelAnchor + m_offset); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_world->CreateJoint(&jd); - - jd.Initialize(body2, m_wheel, p6 + m_offset, wheelAnchor + m_offset); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_world->CreateJoint(&jd); - } - - { - b2RevoluteJointDef jd; - jd.Initialize(body2, m_chassis, p4 + m_offset); - m_world->CreateJoint(&jd); - } - } - - TheoJansen() - { - m_offset.Set(0.0f, 8.0f); - m_motorSpeed = 2.0f; - m_motorOn = true; - b2Vec2 pivot(0.0f, 0.8f); - - // Ground - { - b2BodyDef bd; - b2Body* ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(50.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(b2Vec2(-50.0f, 0.0f), b2Vec2(-50.0f, 10.0f)); - ground->CreateFixture(&shape, 0.0f); - - shape.SetTwoSided(b2Vec2(50.0f, 0.0f), b2Vec2(50.0f, 10.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - // Balls - for (int32 i = 0; i < 40; ++i) - { - b2CircleShape shape; - shape.m_radius = 0.25f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(-40.0f + 2.0f * i, 0.5f); - - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 1.0f); - } - - // Chassis - { - b2PolygonShape shape; - shape.SetAsBox(2.5f, 1.0f); - - b2FixtureDef sd; - sd.density = 1.0f; - sd.shape = &shape; - sd.filter.groupIndex = -1; - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = pivot + m_offset; - m_chassis = m_world->CreateBody(&bd); - m_chassis->CreateFixture(&sd); - } - - { - b2CircleShape shape; - shape.m_radius = 1.6f; - - b2FixtureDef sd; - sd.density = 1.0f; - sd.shape = &shape; - sd.filter.groupIndex = -1; - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = pivot + m_offset; - m_wheel = m_world->CreateBody(&bd); - m_wheel->CreateFixture(&sd); - } - - { - b2RevoluteJointDef jd; - jd.Initialize(m_wheel, m_chassis, pivot + m_offset); - jd.collideConnected = false; - jd.motorSpeed = m_motorSpeed; - jd.maxMotorTorque = 400.0f; - jd.enableMotor = m_motorOn; - m_motorJoint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - } - - b2Vec2 wheelAnchor; - - wheelAnchor = pivot + b2Vec2(0.0f, -0.8f); - - CreateLeg(-1.0f, wheelAnchor); - CreateLeg(1.0f, wheelAnchor); - - m_wheel->SetTransform(m_wheel->GetPosition(), 120.0f * b2_pi / 180.0f); - CreateLeg(-1.0f, wheelAnchor); - CreateLeg(1.0f, wheelAnchor); - - m_wheel->SetTransform(m_wheel->GetPosition(), -120.0f * b2_pi / 180.0f); - CreateLeg(-1.0f, wheelAnchor); - CreateLeg(1.0f, wheelAnchor); - } - - void Step(Settings& settings) override - { - DrawString(5, m_textLine, "Keys: left = a, brake = s, right = d, toggle motor = m"); - - Test::Step(settings); - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_A: - m_motorJoint->SetMotorSpeed(-m_motorSpeed); - break; - - case GLFW_KEY_S: - m_motorJoint->SetMotorSpeed(0.0f); - break; - - case GLFW_KEY_D: - m_motorJoint->SetMotorSpeed(m_motorSpeed); - break; - - case GLFW_KEY_M: - m_motorJoint->EnableMotor(!m_motorJoint->IsMotorEnabled()); - break; - } - } - - static Test* Create() { return new TheoJansen; } - - b2Vec2 m_offset; - b2Body* m_chassis; - b2Body* m_wheel; - b2RevoluteJoint* m_motorJoint; - bool m_motorOn; - float m_motorSpeed; -}; - -static int testIndex = RegisterTest("Examples", "Theo Jansen", TheoJansen::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/tiles.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/tiles.cpp deleted file mode 100644 index e5b9b5dd5f40..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/tiles.cpp +++ /dev/null @@ -1,153 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -/// This stress tests the dynamic tree broad-phase. This also shows that tile -/// based collision is _not_ smooth due to Box2D not knowing about adjacency. -class Tiles : public Test -{ -public: - enum - { - e_count = 20 - }; - - Tiles() - { - m_fixtureCount = 0; - b2Timer timer; - - { - float a = 0.5f; - b2BodyDef bd; - bd.position.y = -a; - b2Body* ground = m_world->CreateBody(&bd); - -#if 1 - int32 N = 200; - int32 M = 10; - b2Vec2 position; - position.y = 0.0f; - for (int32 j = 0; j < M; ++j) - { - position.x = -N * a; - for (int32 i = 0; i < N; ++i) - { - b2PolygonShape shape; - shape.SetAsBox(a, a, position, 0.0f); - ground->CreateFixture(&shape, 0.0f); - ++m_fixtureCount; - position.x += 2.0f * a; - } - position.y -= 2.0f * a; - } -#else - int32 N = 200; - int32 M = 10; - b2Vec2 position; - position.x = -N * a; - for (int32 i = 0; i < N; ++i) - { - position.y = 0.0f; - for (int32 j = 0; j < M; ++j) - { - b2PolygonShape shape; - shape.SetAsBox(a, a, position, 0.0f); - ground->CreateFixture(&shape, 0.0f); - position.y -= 2.0f * a; - } - position.x += 2.0f * a; - } -#endif - } - - { - float a = 0.5f; - b2PolygonShape shape; - shape.SetAsBox(a, a); - - b2Vec2 x(-7.0f, 0.75f); - b2Vec2 y; - b2Vec2 deltaX(0.5625f, 1.25f); - b2Vec2 deltaY(1.125f, 0.0f); - - for (int32 i = 0; i < e_count; ++i) - { - y = x; - - for (int32 j = i; j < e_count; ++j) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position = y; - - // if (i == 0 && j == 0) - //{ - // bd.allowSleep = false; - // } - // else - //{ - // bd.allowSleep = true; - // } - - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 5.0f); - ++m_fixtureCount; - y += deltaY; - } - - x += deltaX; - } - } - - m_createTime = timer.GetMilliseconds(); - } - - void Step(Settings& settings) override - { - const b2ContactManager& cm = m_world->GetContactManager(); - int32 height = cm.m_broadPhase.GetTreeHeight(); - int32 leafCount = cm.m_broadPhase.GetProxyCount(); - int32 minimumNodeCount = 2 * leafCount - 1; - float minimumHeight = ceilf(logf(float(minimumNodeCount)) / logf(2.0f)); - DrawString(5, m_textLine, "dynamic tree height = %d, min = %d", height, int32(minimumHeight)); - - Test::Step(settings); - - DrawString(5, m_textLine, "create time = %6.2f ms, fixture count = %d", m_createTime, m_fixtureCount); - - // b2DynamicTree* tree = &m_world->m_contactManager.m_broadPhase.m_tree; - - // if (m_stepCount == 400) - //{ - // tree->RebuildBottomUp(); - // } - } - - static Test* Create() { return new Tiles; } - - int32 m_fixtureCount; - float m_createTime; -}; - -static int testIndex = RegisterTest("Benchmark", "Tiles", Tiles::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/time_of_impact.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/time_of_impact.cpp deleted file mode 100644 index f33b53476ddd..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/time_of_impact.cpp +++ /dev/null @@ -1,126 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "box2d/b2_time_of_impact.h" - -class TimeOfImpact : public Test -{ -public: - TimeOfImpact() - { - m_shapeA.SetAsBox(25.0f, 5.0f); - m_shapeB.SetAsBox(2.5f, 2.5f); - } - - static Test* Create() { return new TimeOfImpact; } - - void Step(Settings& settings) override - { - Test::Step(settings); - - b2Sweep sweepA; - sweepA.c0.Set(24.0f, -60.0f); - sweepA.a0 = 2.95f; - sweepA.c = sweepA.c0; - sweepA.a = sweepA.a0; - sweepA.localCenter.SetZero(); - - b2Sweep sweepB; - sweepB.c0.Set(53.474274f, -50.252514f); - sweepB.a0 = 513.36676f; // - 162.0f * b2_pi; - sweepB.c.Set(54.595478f, -51.083473f); - sweepB.a = 513.62781f; // - 162.0f * b2_pi; - sweepB.localCenter.SetZero(); - - // sweepB.a0 -= 300.0f * b2_pi; - // sweepB.a -= 300.0f * b2_pi; - - b2TOIInput input; - input.proxyA.Set(&m_shapeA, 0); - input.proxyB.Set(&m_shapeB, 0); - input.sweepA = sweepA; - input.sweepB = sweepB; - input.tMax = 1.0f; - - b2TOIOutput output; - - b2TimeOfImpact(&output, &input); - - DrawString(5, m_textLine, "toi = %g", output.t); - - extern B2_API int32 b2_toiMaxIters, b2_toiMaxRootIters; - DrawString(5, m_textLine, "max toi iters = %d, max root iters = %d", b2_toiMaxIters, b2_toiMaxRootIters); - - b2Vec2 vertices[b2_maxPolygonVertices]; - - b2Transform transformA; - sweepA.GetTransform(&transformA, 0.0f); - for (int32 i = 0; i < m_shapeA.m_count; ++i) - { - vertices[i] = b2Mul(transformA, m_shapeA.m_vertices[i]); - } - g_debugDraw.DrawPolygon(vertices, m_shapeA.m_count, b2Color(0.9f, 0.9f, 0.9f)); - - b2Transform transformB; - sweepB.GetTransform(&transformB, 0.0f); - - // b2Vec2 localPoint(2.0f, -0.1f); - - for (int32 i = 0; i < m_shapeB.m_count; ++i) - { - vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.5f, 0.9f, 0.5f)); - - sweepB.GetTransform(&transformB, output.t); - for (int32 i = 0; i < m_shapeB.m_count; ++i) - { - vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.5f, 0.7f, 0.9f)); - - sweepB.GetTransform(&transformB, 1.0f); - for (int32 i = 0; i < m_shapeB.m_count; ++i) - { - vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.9f, 0.5f, 0.5f)); - -#if 0 - for (float t = 0.0f; t < 1.0f; t += 0.1f) - { - sweepB.GetTransform(&transformB, t); - for (int32 i = 0; i < m_shapeB.m_count; ++i) - { - vertices[i] = b2Mul(transformB, m_shapeB.m_vertices[i]); - } - g_debugDraw.DrawPolygon(vertices, m_shapeB.m_count, b2Color(0.9f, 0.5f, 0.5f)); - } -#endif - } - - b2PolygonShape m_shapeA; - b2PolygonShape m_shapeB; -}; - -static int testIndex = RegisterTest("Collision", "Time of Impact", TimeOfImpact::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/tumbler.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/tumbler.cpp deleted file mode 100644 index e19ffae13f29..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/tumbler.cpp +++ /dev/null @@ -1,98 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -class Tumbler : public Test -{ -public: - enum - { - e_count = 800 - }; - - Tumbler() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - } - - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.allowSleep = false; - bd.position.Set(0.0f, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.5f, 10.0f, b2Vec2(10.0f, 0.0f), 0.0); - body->CreateFixture(&shape, 5.0f); - shape.SetAsBox(0.5f, 10.0f, b2Vec2(-10.0f, 0.0f), 0.0); - body->CreateFixture(&shape, 5.0f); - shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, 10.0f), 0.0); - body->CreateFixture(&shape, 5.0f); - shape.SetAsBox(10.0f, 0.5f, b2Vec2(0.0f, -10.0f), 0.0); - body->CreateFixture(&shape, 5.0f); - - b2RevoluteJointDef jd; - jd.bodyA = ground; - jd.bodyB = body; - jd.localAnchorA.Set(0.0f, 10.0f); - jd.localAnchorB.Set(0.0f, 0.0f); - jd.referenceAngle = 0.0f; - jd.motorSpeed = 0.05f * b2_pi; - jd.maxMotorTorque = 1e8f; - jd.enableMotor = true; - m_joint = (b2RevoluteJoint*)m_world->CreateJoint(&jd); - } - - m_count = 0; - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - if (m_count < e_count) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 10.0f); - b2Body* body = m_world->CreateBody(&bd); - - b2PolygonShape shape; - shape.SetAsBox(0.125f, 0.125f); - body->CreateFixture(&shape, 1.0f); - - ++m_count; - } - } - - static Test* Create() { return new Tumbler; } - - b2RevoluteJoint* m_joint; - int32 m_count; -}; - -static int testIndex = RegisterTest("Benchmark", "Tumbler", Tumbler::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/web.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/web.cpp deleted file mode 100644 index 658bc9f87bc0..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/web.cpp +++ /dev/null @@ -1,215 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" - -// Test distance joints, body destruction, and joint destruction. -class Web : public Test -{ -public: - Web() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.5f); - - b2BodyDef bd; - bd.type = b2_dynamicBody; - - bd.position.Set(-5.0f, 5.0f); - m_bodies[0] = m_world->CreateBody(&bd); - m_bodies[0]->CreateFixture(&shape, 5.0f); - - bd.position.Set(5.0f, 5.0f); - m_bodies[1] = m_world->CreateBody(&bd); - m_bodies[1]->CreateFixture(&shape, 5.0f); - - bd.position.Set(5.0f, 15.0f); - m_bodies[2] = m_world->CreateBody(&bd); - m_bodies[2]->CreateFixture(&shape, 5.0f); - - bd.position.Set(-5.0f, 15.0f); - m_bodies[3] = m_world->CreateBody(&bd); - m_bodies[3]->CreateFixture(&shape, 5.0f); - - b2DistanceJointDef jd; - b2Vec2 p1, p2, d; - - float frequencyHz = 2.0f; - float dampingRatio = 0.0f; - - jd.bodyA = ground; - jd.bodyB = m_bodies[0]; - jd.localAnchorA.Set(-10.0f, 0.0f); - jd.localAnchorB.Set(-0.5f, -0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[0] = m_world->CreateJoint(&jd); - - jd.bodyA = ground; - jd.bodyB = m_bodies[1]; - jd.localAnchorA.Set(10.0f, 0.0f); - jd.localAnchorB.Set(0.5f, -0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[1] = m_world->CreateJoint(&jd); - - jd.bodyA = ground; - jd.bodyB = m_bodies[2]; - jd.localAnchorA.Set(10.0f, 20.0f); - jd.localAnchorB.Set(0.5f, 0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[2] = m_world->CreateJoint(&jd); - - jd.bodyA = ground; - jd.bodyB = m_bodies[3]; - jd.localAnchorA.Set(-10.0f, 20.0f); - jd.localAnchorB.Set(-0.5f, 0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[3] = m_world->CreateJoint(&jd); - - jd.bodyA = m_bodies[0]; - jd.bodyB = m_bodies[1]; - jd.localAnchorA.Set(0.5f, 0.0f); - jd.localAnchorB.Set(-0.5f, 0.0f); - ; - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[4] = m_world->CreateJoint(&jd); - - jd.bodyA = m_bodies[1]; - jd.bodyB = m_bodies[2]; - jd.localAnchorA.Set(0.0f, 0.5f); - jd.localAnchorB.Set(0.0f, -0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[5] = m_world->CreateJoint(&jd); - - jd.bodyA = m_bodies[2]; - jd.bodyB = m_bodies[3]; - jd.localAnchorA.Set(-0.5f, 0.0f); - jd.localAnchorB.Set(0.5f, 0.0f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[6] = m_world->CreateJoint(&jd); - - jd.bodyA = m_bodies[3]; - jd.bodyB = m_bodies[0]; - jd.localAnchorA.Set(0.0f, -0.5f); - jd.localAnchorB.Set(0.0f, 0.5f); - p1 = jd.bodyA->GetWorldPoint(jd.localAnchorA); - p2 = jd.bodyB->GetWorldPoint(jd.localAnchorB); - d = p2 - p1; - jd.length = d.Length(); - b2LinearStiffness(jd.stiffness, jd.damping, frequencyHz, dampingRatio, jd.bodyA, jd.bodyB); - m_joints[7] = m_world->CreateJoint(&jd); - } - } - - void Keyboard(int key) override - { - switch (key) - { - case GLFW_KEY_B: - for (int32 i = 0; i < 4; ++i) - { - if (m_bodies[i]) - { - m_world->DestroyBody(m_bodies[i]); - m_bodies[i] = NULL; - break; - } - } - break; - - case GLFW_KEY_J: - for (int32 i = 0; i < 8; ++i) - { - if (m_joints[i]) - { - m_world->DestroyJoint(m_joints[i]); - m_joints[i] = NULL; - break; - } - } - break; - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - DrawString(5, m_textLine, "Press: (b) to delete a body, (j) to delete a joint"); - } - - void JointDestroyed(b2Joint* joint) override - { - for (int32 i = 0; i < 8; ++i) - { - if (m_joints[i] == joint) - { - m_joints[i] = NULL; - break; - } - } - } - - static Test* Create() { return new Web; } - - b2Body* m_bodies[4]; - b2Joint* m_joints[8]; -}; - -static int testIndex = RegisterTest("Examples", "Web", Web::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/wheel_joint.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/wheel_joint.cpp deleted file mode 100644 index 08f62427232f..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/wheel_joint.cpp +++ /dev/null @@ -1,121 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "settings.h" -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -// Test the wheel joint with motor, spring, and limit options. -class WheelJoint : public Test -{ -public: - WheelJoint() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - m_enableLimit = true; - m_enableMotor = false; - m_motorSpeed = 10.0f; - - { - b2CircleShape shape; - shape.m_radius = 2.0f; - - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.0f, 10.0f); - bd.allowSleep = false; - b2Body* body = m_world->CreateBody(&bd); - body->CreateFixture(&shape, 5.0f); - - b2WheelJointDef jd; - - // Horizontal - jd.Initialize(ground, body, bd.position, b2Vec2(0.0f, 1.0f)); - - jd.motorSpeed = m_motorSpeed; - jd.maxMotorTorque = 10000.0f; - jd.enableMotor = m_enableMotor; - jd.lowerTranslation = -3.0f; - jd.upperTranslation = 3.0f; - jd.enableLimit = m_enableLimit; - - float hertz = 1.0f; - float dampingRatio = 0.7f; - b2LinearStiffness(jd.stiffness, jd.damping, hertz, dampingRatio, ground, body); - - m_joint = (b2WheelJoint*)m_world->CreateJoint(&jd); - } - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - float torque = m_joint->GetMotorTorque(settings.m_hertz); - DrawString(5, m_textLine, "Motor Torque = %4.0f", torque); - - b2Vec2 F = m_joint->GetReactionForce(settings.m_hertz); - DrawString(5, m_textLine, "Reaction Force = (%4.1f, %4.1f)", F.x, F.y); - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(10.0f, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Joint Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Checkbox("Limit", &m_enableLimit)) - { - m_joint->EnableLimit(m_enableLimit); - } - - if (ImGui::Checkbox("Motor", &m_enableMotor)) - { - m_joint->EnableMotor(m_enableMotor); - } - - if (ImGui::SliderFloat("Speed", &m_motorSpeed, -100.0f, 100.0f, "%.0f")) - { - m_joint->SetMotorSpeed(m_motorSpeed); - } - - ImGui::End(); - } - - static Test* Create() { return new WheelJoint; } - - b2WheelJoint* m_joint; - float m_motorSpeed; - bool m_enableMotor; - bool m_enableLimit; -}; - -static int testIndex = RegisterTest("Joints", "Wheel", WheelJoint::Create); diff --git a/tests/cpp-tests/Source/Box2DTestBed/tests/wrecking_ball.cpp b/tests/cpp-tests/Source/Box2DTestBed/tests/wrecking_ball.cpp deleted file mode 100644 index 69a7745e4c89..000000000000 --- a/tests/cpp-tests/Source/Box2DTestBed/tests/wrecking_ball.cpp +++ /dev/null @@ -1,161 +0,0 @@ -// MIT License - -// Copyright (c) 2019 Erin Catto - -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: - -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. - -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -#include "test.h" -#include "ImGui/ImGuiPresenter.h" - -/// This test shows how a distance joint can be used to stabilize a chain of -/// bodies with a heavy payload. Notice that the distance joint just prevents -/// excessive stretching and has no other effect. -/// By disabling the distance joint you can see that the Box2D solver has trouble -/// supporting heavy bodies with light bodies. Try playing around with the -/// densities, time step, and iterations to see how they affect stability. -/// This test also shows how to use contact filtering. Filtering is configured -/// so that the payload does not collide with the chain. -class WreckingBall : public Test -{ -public: - WreckingBall() - { - b2Body* ground = NULL; - { - b2BodyDef bd; - ground = m_world->CreateBody(&bd); - - b2EdgeShape shape; - shape.SetTwoSided(b2Vec2(-40.0f, 0.0f), b2Vec2(40.0f, 0.0f)); - ground->CreateFixture(&shape, 0.0f); - } - - { - b2PolygonShape shape; - shape.SetAsBox(0.5f, 0.125f); - - b2FixtureDef fd; - fd.shape = &shape; - fd.density = 20.0f; - fd.friction = 0.2f; - fd.filter.categoryBits = 0x0001; - fd.filter.maskBits = 0xFFFF & ~0x0002; - - b2RevoluteJointDef jd; - jd.collideConnected = false; - - const int32 N = 10; - const float y = 15.0f; - m_distanceJointDef.localAnchorA.Set(0.0f, y); - - b2Body* prevBody = ground; - for (int32 i = 0; i < N; ++i) - { - b2BodyDef bd; - bd.type = b2_dynamicBody; - bd.position.Set(0.5f + 1.0f * i, y); - if (i == N - 1) - { - bd.position.Set(1.0f * i, y); - bd.angularDamping = 0.4f; - } - - b2Body* body = m_world->CreateBody(&bd); - - if (i == N - 1) - { - b2CircleShape circleShape; - circleShape.m_radius = 1.5f; - b2FixtureDef sfd; - sfd.shape = &circleShape; - sfd.density = 100.0f; - sfd.filter.categoryBits = 0x0002; - body->CreateFixture(&sfd); - } - else - { - body->CreateFixture(&fd); - } - - b2Vec2 anchor(float(i), y); - jd.Initialize(prevBody, body, anchor); - m_world->CreateJoint(&jd); - - prevBody = body; - } - - m_distanceJointDef.localAnchorB.SetZero(); - - float extraLength = 0.01f; - m_distanceJointDef.minLength = 0.0f; - m_distanceJointDef.maxLength = N - 1.0f + extraLength; - m_distanceJointDef.bodyB = prevBody; - } - - { - m_distanceJointDef.bodyA = ground; - m_distanceJoint = m_world->CreateJoint(&m_distanceJointDef); - m_stabilize = true; - } - } - - void UpdateUI() override - { - // ImGui::SetNextWindowPos(ImVec2(Test::g_debugDraw.debugNodeOffset.x, 100.0f)); - ImGui::SetNextWindowSize(ImVec2(200.0f, 100.0f)); - ImGui::Begin("Wrecking Ball Controls", nullptr, ImGuiWindowFlags_NoResize); - - if (ImGui::Checkbox("Stabilize", &m_stabilize)) - { - if (m_stabilize == true && m_distanceJoint == nullptr) - { - m_distanceJoint = m_world->CreateJoint(&m_distanceJointDef); - } - else if (m_stabilize == false && m_distanceJoint != nullptr) - { - m_world->DestroyJoint(m_distanceJoint); - m_distanceJoint = nullptr; - } - } - - ImGui::End(); - } - - void Step(Settings& settings) override - { - Test::Step(settings); - - if (m_distanceJoint) - { - DrawString(5, m_textLine, "Distance Joint ON"); - } - else - { - DrawString(5, m_textLine, "Distance Joint OFF"); - } - } - - static Test* Create() { return new WreckingBall; } - - b2DistanceJointDef m_distanceJointDef; - b2Joint* m_distanceJoint; - bool m_stabilize; -}; - -static int testIndex = RegisterTest("Examples", "Wrecking Ball", WreckingBall::Create); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-1159.cpp b/tests/cpp-tests/Source/BugsTest/Bug-1159.cpp index b0c8cd6cfe93..1596aebd1fad 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-1159.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-1159.cpp @@ -32,10 +32,10 @@ bool Bug1159Layer::init() { auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(255, 0, 255, 255)); + auto background = LayerColor::create(Color32(255, 0, 255, 255)); addChild(background); - auto sprite_a = LayerColor::create(Color4B(255, 0, 0, 255), 700, 700); + auto sprite_a = LayerColor::create(Color32(255, 0, 0, 255), 700, 700); sprite_a->setAnchorPoint(Vec2(0.5f, 0.5f)); sprite_a->setIgnoreAnchorPointForPosition(false); sprite_a->setPosition(0.0f, s.height / 2); @@ -44,7 +44,7 @@ bool Bug1159Layer::init() sprite_a->runAction(RepeatForever::create(Sequence::create(MoveTo::create(1.0f, Vec2(1024.0f, 384.0f)), MoveTo::create(1.0f, Vec2(0.0f, 384.0f)), nullptr))); - auto sprite_b = LayerColor::create(Color4B(0, 0, 255, 255), 400, 400); + auto sprite_b = LayerColor::create(Color32(0, 0, 255, 255), 400, 400); sprite_b->setAnchorPoint(Vec2(0.5f, 0.5f)); sprite_b->setIgnoreAnchorPointForPosition(false); sprite_b->setPosition(s.width / 2, s.height / 2); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-12847.cpp b/tests/cpp-tests/Source/BugsTest/Bug-12847.cpp index 9e5f1893287b..6feb3730eab4 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-12847.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-12847.cpp @@ -97,11 +97,11 @@ void Bug12847Layer::update(float dt) void Bug12847Layer::onEnter() { BugsTestBase::onEnter(); - Director::getInstance()->setClearColor(Color4F::RED); + Director::getInstance()->setClearColor(Color::RED); } void Bug12847Layer::onExit() { - Director::getInstance()->setClearColor(Color4F::BLACK); + Director::getInstance()->setClearColor(Color::BLACK); BugsTestBase::onExit(); } \ No newline at end of file diff --git a/tests/cpp-tests/Source/BugsTest/Bug-14327.cpp b/tests/cpp-tests/Source/BugsTest/Bug-14327.cpp index 05e4d39f1da2..bd5c0fcf2863 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-14327.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-14327.cpp @@ -34,7 +34,7 @@ #include "Bug-14327.h" -#include "base/format.h" +#include "axmol/base/format.h" #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) @@ -64,7 +64,7 @@ bool Bug14327Layer::init() std::string pNormalSprite = "extensions/green_edit.png"; _edit = ui::EditBox::create(editBoxSize + Size(0, 20), ui::Scale9Sprite::create(pNormalSprite)); _edit->setPosition(Vec2(visibleOrigin.x + visibleSize.width / 2, visibleOrigin.y + visibleSize.height / 2)); - _edit->setFontColor(Color3B::RED); + _edit->setFontColor(Color32::RED); _edit->setReturnType(ui::EditBox::KeyboardReturnType::DONE); _edit->setDelegate(this); this->addChild(_edit); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-14327.h b/tests/cpp-tests/Source/BugsTest/Bug-14327.h index 9cbe7f4782fc..28b08b707436 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-14327.h +++ b/tests/cpp-tests/Source/BugsTest/Bug-14327.h @@ -29,7 +29,7 @@ #if (AX_TARGET_PLATFORM == AX_PLATFORM_WIN32) -# include "ui/UIEditBox/UIEditBox.h" +# include "axmol/ui/UIEditBox/UIEditBox.h" class Bug14327Layer : public BugsTestBase, public ax::ui::EditBoxDelegate { diff --git a/tests/cpp-tests/Source/BugsTest/Bug-458/Bug-458.cpp b/tests/cpp-tests/Source/BugsTest/Bug-458/Bug-458.cpp index ce6d44c1384f..001388ade048 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-458/Bug-458.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-458/Bug-458.cpp @@ -48,11 +48,11 @@ bool Bug458Layer::init() // [question2 setContentSize:CGSizeMake(50,50)]; auto sprite = MenuItemSprite::create(question2, question, AX_CALLBACK_1(Bug458Layer::selectAnswer, this)); - auto layer = LayerColor::create(Color4B(0, 0, 255, 255), 100, 100); + auto layer = LayerColor::create(Color32(0, 0, 255, 255), 100, 100); question->release(); question2->release(); - auto layer2 = LayerColor::create(Color4B(255, 0, 0, 255), 100, 100); + auto layer2 = LayerColor::create(Color32(255, 0, 0, 255), 100, 100); auto sprite2 = MenuItemSprite::create(layer, layer2, AX_CALLBACK_1(Bug458Layer::selectAnswer, this)); auto menu = Menu::create(sprite, sprite2, nullptr); menu->alignItemsVerticallyWithPadding(100); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.cpp b/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.cpp index 152dbbf77c21..afd4a223a503 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.cpp @@ -42,7 +42,7 @@ bool QuestionContainerSprite::init() int width = size.width * 0.9f - (corner->getContentSize().width * 2); int height = size.height * 0.15f - (corner->getContentSize().height * 2); - auto layer = LayerColor::create(Color4B(255, 255, 255, 255 * .75), width, height); + auto layer = LayerColor::create(Color32(255, 255, 255, 255 * .75), width, height); layer->setPosition(Vec2(-width / 2, -height / 2)); // First button is blue, @@ -51,11 +51,11 @@ bool QuestionContainerSprite::init() static int a = 0; if (a == 0) - label->setColor(Color3B::BLUE); + label->setColor(Color32::BLUE); else { AXLOGD("Color changed"); - label->setColor(Color3B::RED); + label->setColor(Color32::RED); } a++; addChild(layer); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.h b/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.h index b86c41b3215f..8d07a6fe30ac 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.h +++ b/tests/cpp-tests/Source/BugsTest/Bug-458/QuestionContainerSprite.h @@ -25,7 +25,7 @@ #ifndef __QUESTION_CONTAINER_SPRITE_H__ #define __QUESTION_CONTAINER_SPRITE_H__ -#include "axmol.h" +#include "axmol/axmol.h" class QuestionContainerSprite : public ax::Sprite { diff --git a/tests/cpp-tests/Source/BugsTest/Bug-624.cpp b/tests/cpp-tests/Source/BugsTest/Bug-624.cpp index 898ff3f1b62e..20ded1f956f1 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-624.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-624.cpp @@ -69,7 +69,7 @@ void Bug624Layer::switchLayer(float dt) auto scene = Scene::create(); scene->addChild(Bug624Layer2::create(), 0); - Director::getInstance()->replaceScene(TransitionFade::create(2.0f, scene, Color3B::WHITE)); + Director::getInstance()->replaceScene(TransitionFade::create(2.0f, scene, Color32::WHITE)); } void Bug624Layer::onAcceleration(Acceleration* acc, Event* event) @@ -115,7 +115,7 @@ void Bug624Layer2::switchLayer(float dt) auto scene = Scene::create(); scene->addChild(Bug624Layer::create(), 0); - Director::getInstance()->replaceScene(TransitionFade::create(2.0f, scene, Color3B::RED)); + Director::getInstance()->replaceScene(TransitionFade::create(2.0f, scene, Color32::RED)); } void Bug624Layer2::onAcceleration(Acceleration* acc, Event* event) diff --git a/tests/cpp-tests/Source/BugsTest/Bug-914.cpp b/tests/cpp-tests/Source/BugsTest/Bug-914.cpp index a323f51d0b91..dd732526bfc5 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-914.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-914.cpp @@ -44,7 +44,7 @@ bool Bug914Layer::init() LayerColor* layer; for (int i = 0; i < 5; i++) { - layer = LayerColor::create(Color4B(i * 20, i * 20, i * 20, 255)); + layer = LayerColor::create(Color32(i * 20, i * 20, i * 20, 255)); layer->setContentSize(Size(i * 100.0f, i * 100.0f)); layer->setPosition(size.width / 2, size.height / 2); layer->setAnchorPoint(Vec2(0.5f, 0.5f)); diff --git a/tests/cpp-tests/Source/BugsTest/Bug-DrawNode.cpp b/tests/cpp-tests/Source/BugsTest/Bug-DrawNode.cpp index 1eacfbe68a43..fcdf789d5094 100644 --- a/tests/cpp-tests/Source/BugsTest/Bug-DrawNode.cpp +++ b/tests/cpp-tests/Source/BugsTest/Bug-DrawNode.cpp @@ -30,7 +30,6 @@ // #include "Bug-DrawNode.h" -#include "renderer/backend/Types.h" using namespace ax; @@ -41,23 +40,23 @@ bool BugDrawNodeLayer::init() auto size = Director::getInstance()->getWinSize(); auto testSprite = Sprite::create("Images/close.png"); BlendFunc blend; - blend.src = backend::BlendFactor::ZERO; - blend.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blend.src = rhi::BlendFactor::ZERO; + blend.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; testSprite->setBlendFunc(blend); testSprite->setPosition(Vec2(size.width / 2, size.height / 2)); testSprite->setScale(10); addChild(testSprite); auto drawNode = DrawNode::create(); - drawNode->drawLine(Vec2(0, 0), Vec2(size.width, size.height), Color4F(1, 0, 0, 0.5f)); + drawNode->drawLine(Vec2(0, 0), Vec2(size.width, size.height), Color(1, 0, 0, 0.5f)); Vec2 point = Vec2(size.width / 2, size.height / 2); - drawNode->drawPoint(point, 8, Color4F(1, 0, 0, 0.5f)); + drawNode->drawPoint(point, 8, Color(1, 0, 0, 0.5f)); addChild(drawNode); auto label = Label::create(); label->setString(std::string("If you see a red line with a block at center, the bug is fixed!")); label->setPosition(size.width / 2, size.height / 4); - label->setTextColor(Color4B::ORANGE); + label->setTextColor(Color32::ORANGE); addChild(label); return true; diff --git a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp index c650239822b0..44400c1d067a 100644 --- a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp +++ b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.cpp @@ -26,10 +26,10 @@ THE SOFTWARE. #include "Camera3DTest.h" #include "testResource.h" -#include "ui/UISlider.h" -#include "platform/FileUtils.h" -#include "renderer/backend/DriverBase.h" -#include "base/format.h" +#include "axmol/ui/UISlider.h" +#include "axmol/platform/FileUtils.h" +#include "axmol/rhi/DriverBase.h" +#include "axmol/base/format.h" using namespace ax; @@ -91,14 +91,14 @@ CameraRotationTest::CameraRotationTest() // Yellow is at the back bill1 = BillBoard::create("Images/Icon.png"); bill1->setPosition3D(Vec3(50.0f, 10.0f, -10.0f)); - bill1->setColor(Color3B::YELLOW); + bill1->setColor(Color32::YELLOW); bill1->setScale(0.6f); mesh->addChild(bill1); l1 = Label::create(); l1->setPosition(Vec2(0.0f, -10.0f)); l1->setString("Billboard1"); - l1->setColor(Color3B::WHITE); + l1->setColor(Color32::WHITE); l1->setScale(3); bill1->addChild(l1); @@ -114,7 +114,7 @@ CameraRotationTest::CameraRotationTest() l2 = Label::create(); l2->setString("Billboard2"); l2->setPosition(Vec2(0.0f, -10.0f)); - l2->setColor(Color3B::WHITE); + l2->setColor(Color32::WHITE); l2->setScale(3); bill2->addChild(l2); @@ -230,10 +230,10 @@ void Camera3DTestDemo::SwitchViewCallback(Object* sender, CameraType cameraType) _camera->setPosition3D(Vec3(0, 130, 130) + _mesh->getPosition3D()); _camera->lookAt(_mesh->getPosition3D()); - _RotateRightlabel->setColor(Color3B::WHITE); - _RotateLeftlabel->setColor(Color3B::WHITE); - _ZoomInlabel->setColor(Color3B::WHITE); - _ZoomOutlabel->setColor(Color3B::WHITE); + _RotateRightlabel->setColor(Color32::WHITE); + _RotateLeftlabel->setColor(Color32::WHITE); + _ZoomInlabel->setColor(Color32::WHITE); + _ZoomOutlabel->setColor(Color32::WHITE); } else if (_cameraType == CameraType::FirstPerson) { @@ -243,20 +243,20 @@ void Camera3DTestDemo::SwitchViewCallback(Object* sender, CameraType cameraType) _camera->setPosition3D(Vec3(0, 35, 0) + _mesh->getPosition3D()); _camera->lookAt(_mesh->getPosition3D() + newFaceDir * 50); - _RotateRightlabel->setColor(Color3B::WHITE); - _RotateLeftlabel->setColor(Color3B::WHITE); - _ZoomInlabel->setColor(Color3B::GRAY); - _ZoomOutlabel->setColor(Color3B::GRAY); + _RotateRightlabel->setColor(Color32::WHITE); + _RotateLeftlabel->setColor(Color32::WHITE); + _ZoomInlabel->setColor(Color32::GRAY); + _ZoomOutlabel->setColor(Color32::GRAY); } else if (_cameraType == CameraType::ThirdPerson) { _camera->setPosition3D(Vec3(0, 130, 130) + _mesh->getPosition3D()); _camera->lookAt(_mesh->getPosition3D()); - _RotateRightlabel->setColor(Color3B::GRAY); - _RotateLeftlabel->setColor(Color3B::GRAY); - _ZoomInlabel->setColor(Color3B::WHITE); - _ZoomOutlabel->setColor(Color3B::WHITE); + _RotateRightlabel->setColor(Color32::GRAY); + _RotateLeftlabel->setColor(Color32::GRAY); + _ZoomInlabel->setColor(Color32::WHITE); + _ZoomOutlabel->setColor(Color32::WHITE); } } void Camera3DTestDemo::onEnter() @@ -361,16 +361,16 @@ void Camera3DTestDemo::onEnter() // draw x for (int j = -20; j <= 20; j++) { - line->drawLine(Vec3(-100.0f, 0.0f, 5.0f * j), Vec3(100.0f, 0.0f, 5.0f * j), Color4F(1, 0, 0, 1)); + line->drawLine(Vec3(-100.0f, 0.0f, 5.0f * j), Vec3(100.0f, 0.0f, 5.0f * j), Color(1, 0, 0, 1)); } // draw z for (int j = -20; j <= 20; j++) { - line->drawLine(Vec3(5.0f * j, 0.0f, -100.0f), Vec3(5.0f * j, 0.0f, 100.0f), Color4F(0, 0, 1, 1)); + line->drawLine(Vec3(5.0f * j, 0.0f, -100.0f), Vec3(5.0f * j, 0.0f, 100.0f), Color(0, 0, 1, 1)); } // draw y - line->drawLine(Vec3(0.0f, -50.0f, 0.0f), Vec3(0, 0, 0), Color4F(0, 0.5, 0, 1)); - line->drawLine(Vec3(0, 0, 0), Vec3(0, 50.0f, 0), Color4F(0, 1, 0, 1)); + line->drawLine(Vec3(0.0f, -50.0f, 0.0f), Vec3(0, 0, 0), Color(0, 0.5, 0, 1)); + line->drawLine(Vec3(0, 0, 0), Vec3(0, 50.0f, 0), Color(0, 1, 0, 1)); _layer3D->addChild(line); _layer3D->setCameraMask(2); @@ -740,7 +740,7 @@ void CameraCullingDemo::onEnter() MenuItemFont::setFontSize(20); auto menuItem1 = MenuItemFont::create("Switch Camera", AX_CALLBACK_1(CameraCullingDemo::switchViewCallback, this)); - menuItem1->setColor(Color3B(0, 200, 20)); + menuItem1->setColor(Color32(0, 200, 20)); auto menu = Menu::create(menuItem1, NULL); menu->setPosition(Vec2::ZERO); menuItem1->setPosition(VisibleRect::left().x + 80, VisibleRect::top().y - 70); @@ -749,9 +749,9 @@ void CameraCullingDemo::onEnter() // + - MenuItemFont::setFontSize(40); auto decrease = MenuItemFont::create(" - ", AX_CALLBACK_1(CameraCullingDemo::delMeshCallback, this)); - decrease->setColor(Color3B(0, 200, 20)); + decrease->setColor(Color32(0, 200, 20)); auto increase = MenuItemFont::create(" + ", AX_CALLBACK_1(CameraCullingDemo::addMeshCallback, this)); - increase->setColor(Color3B(0, 200, 20)); + increase->setColor(Color32(0, 200, 20)); menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); @@ -760,7 +760,7 @@ void CameraCullingDemo::onEnter() TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelMeshCount = Label::createWithTTF(ttfCount, "0 sprits"); - _labelMeshCount->setColor(Color3B(0, 200, 20)); + _labelMeshCount->setColor(Color32(0, 200, 20)); _labelMeshCount->setPosition(Vec2(s.width / 2, VisibleRect::top().y - 70)); addChild(_labelMeshCount); @@ -810,7 +810,7 @@ void CameraCullingDemo::update(float dt) if (_cameraFirst->isVisibleInFrustum(&aabb)) { aabb.getCorners(corners); - _drawAABB->drawCube(corners, Color4F(0, 1, 0, 1)); + _drawAABB->drawCube(corners, Color(0, 1, 0, 1)); } } } @@ -935,7 +935,7 @@ void CameraCullingDemo::drawCameraFrustum() _drawFrustum->clear(); auto size = Director::getInstance()->getWinSize(); - Color4F color(1.f, 1.f, 0.f, 1); + Color color(1.f, 1.f, 0.f, 1); // top-left Vec3 tl_0, tl_1; @@ -1020,10 +1020,10 @@ void CameraArcBallDemo::onEnter() auto menuItem1 = MenuItemFont::create("Switch Operation", AX_CALLBACK_1(CameraArcBallDemo::switchOperateCallback, this)); - menuItem1->setColor(Color3B(0, 200, 20)); + menuItem1->setColor(Color32(0, 200, 20)); auto menuItem2 = MenuItemFont::create("Switch Target", AX_CALLBACK_1(CameraArcBallDemo::switchTargetCallback, this)); - menuItem2->setColor(Color3B(0, 200, 20)); + menuItem2->setColor(Color32(0, 200, 20)); auto menu = Menu::create(menuItem1, menuItem2, NULL); menu->setPosition(Vec2::ZERO); menuItem1->setPosition(VisibleRect::left().x + 80, VisibleRect::top().y - 70); @@ -1061,15 +1061,15 @@ void CameraArcBallDemo::onEnter() // draw x for (int j = -20; j <= 20; j++) { - _drawGrid->drawLine(Vec3(-100.0f, 0, 5.0f * j), Vec3(100.0f, 0, 5.0f * j), Color4F(1, 0, 0, 1)); + _drawGrid->drawLine(Vec3(-100.0f, 0, 5.0f * j), Vec3(100.0f, 0, 5.0f * j), Color(1, 0, 0, 1)); } // draw z for (int j = -20; j <= 20; j++) { - _drawGrid->drawLine(Vec3(5.0f * j, 0, -100.0f), Vec3(5.0f * j, 0, 100.0f), Color4F(0, 0, 1, 1)); + _drawGrid->drawLine(Vec3(5.0f * j, 0, -100.0f), Vec3(5.0f * j, 0, 100.0f), Color(0, 0, 1, 1)); } // draw y - _drawGrid->drawLine(Vec3(0, 0, 0), Vec3(0, 50.0f, 0), Color4F(0, 1, 0, 1)); + _drawGrid->drawLine(Vec3(0, 0, 0), Vec3(0, 50.0f, 0), Color(0, 1, 0, 1)); _layer3D->addChild(_drawGrid); _layer3D->setCameraMask(2); @@ -1222,7 +1222,7 @@ void FogTestDemo::onEnter() { CameraBaseTest::onEnter(); schedule(AX_SCHEDULE_SELECTOR(FogTestDemo::update), 0.0f); - Director::getInstance()->setClearColor(Color4F(0.5, 0.5, 0.5, 1)); + Director::getInstance()->setClearColor(Color(0.5, 0.5, 0.5, 1)); auto s = Director::getInstance()->getWinSize(); auto listener = EventListenerTouchAllAtOnce::create(); @@ -1255,8 +1255,8 @@ void FogTestDemo::onEnter() AX_SAFE_RELEASE_NULL(_programState2); auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs"); - _programState1 = new backend::ProgramState(program); - _programState2 = new backend::ProgramState(program); + _programState1 = new rhi::ProgramState(program); + _programState2 = new rhi::ProgramState(program); _mesh1 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); _mesh2 = MeshRenderer::create("MeshRendererTest/teapot.c3b"); @@ -1297,13 +1297,13 @@ void FogTestDemo::onEnter() #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) _backToForegroundListener = EventListenerCustom::create(EVENT_RENDERER_RECREATED, [this](EventCustom*) { - Director::getInstance()->setClearColor(Color4F(0.5, 0.5, 0.5, 1)); + Director::getInstance()->setClearColor(Color(0.5, 0.5, 0.5, 1)); AX_SAFE_RELEASE_NULL(_programState1); AX_SAFE_RELEASE_NULL(_programState2); auto program = ProgramManager::getInstance()->loadProgram("custom/fog_vs", "custom/fog_fs"); - _programState1 = new backend::ProgramState(program); - _programState2 = new backend::ProgramState(program); + _programState1 = new rhi::ProgramState(program); + _programState2 = new rhi::ProgramState(program); _mesh1->setProgramState(_programState1); _mesh2->setProgramState(_programState2); @@ -1361,7 +1361,7 @@ void FogTestDemo::switchTypeCallback(Object* sender, int type) void FogTestDemo::onExit() { CameraBaseTest::onExit(); - Director::getInstance()->setClearColor(Color4F(0, 0, 0, 1)); + Director::getInstance()->setClearColor(Color(0, 0, 0, 1)); if (_camera) { _camera = nullptr; @@ -1461,7 +1461,7 @@ void FogTestDemo::onTouchesMoved(const std::vector& touches, ax::Event* // camera->setCameraFlag(CameraFlag::USER1); // camera->setDepth(-1); // camera->setFrameBufferObject(fbo); -// fbo->setClearColor(Color4F(1,1,1,1)); +// fbo->setClearColor(Color(1,1,1,1)); // addChild(camera); // } @@ -1512,7 +1512,7 @@ void BackgroundColorBrushTest::onEnter() // 2nd Camera auto camera = Camera::createPerspective(60, (float)s.width / s.height, 1, 1000); - auto colorBrush = CameraBackgroundBrush::createColorBrush(Color4F(.1f, .1f, 1.f, .5f), 1.f); + auto colorBrush = CameraBackgroundBrush::createColorBrush(Color(.1f, .1f, 1.f, .5f), 1.f); camera->setBackgroundBrush(colorBrush); camera->setPosition3D(Vec3(0.0f, 0.0f, 200.0f)); camera->lookAt(Vec3::ZERO); @@ -1528,7 +1528,7 @@ void BackgroundColorBrushTest::onEnter() slider->setPosition(Vec2(s.width / 2, s.height / 4)); slider->setPercent(50); slider->addEventListener([slider, colorBrush](Object*, ui::Slider::EventType) { - colorBrush->setColor(Color4F(.1f, .1f, 1.f, (float)slider->getPercent() / 100.f)); + colorBrush->setColor(Color(.1f, .1f, 1.f, (float)slider->getPercent() / 100.f)); }); addChild(slider); diff --git a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.h b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.h index 5b4d0c1c45b7..75789501c6e5 100644 --- a/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.h +++ b/tests/cpp-tests/Source/Camera3DTest/Camera3DTest.h @@ -28,8 +28,7 @@ THE SOFTWARE. #include "../BaseTest.h" #include "../MeshRendererTest/DrawNode3D.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/backend/Types.h" +#include "axmol/rhi/ProgramState.h" #include @@ -261,8 +260,8 @@ class FogTestDemo : public CameraBaseTest ax::Camera* _camera = nullptr; ax::MeshRenderer* _mesh1 = nullptr; ax::MeshRenderer* _mesh2 = nullptr; - ax::backend::ProgramState* _programState1 = nullptr; - ax::backend::ProgramState* _programState2 = nullptr; + ax::rhi::ProgramState* _programState1 = nullptr; + ax::rhi::ProgramState* _programState2 = nullptr; #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) ax::EventListenerCustom* _backToForegroundListener; diff --git a/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.cpp b/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.cpp deleted file mode 100644 index 9dd7b3ef3639..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.cpp +++ /dev/null @@ -1,279 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -// -// Accelerometer + Chipmunk physics + multi touches example -// a axmol example -// https://axmol.dev/ -// - -#include "chipmunk/chipmunk.h" - -#include "ChipmunkTest.h" - -using namespace ax; -USING_NS_AX_EXT; - -enum -{ - kTagParentNode = 1, -}; - -enum -{ - Z_PHYSICS_DEBUG = 100, -}; - -// callback to remove Shapes from the Space - -ChipmunkTest::ChipmunkTest() -{ - // enable events - - auto touchListener = EventListenerTouchAllAtOnce::create(); - touchListener->onTouchesEnded = AX_CALLBACK_2(ChipmunkTest::onTouchesEnded, this); - _eventDispatcher->addEventListenerWithSceneGraphPriority(touchListener, this); - - Device::setAccelerometerEnabled(true); - auto accListener = EventListenerAcceleration::create(AX_CALLBACK_2(ChipmunkTest::onAcceleration, this)); - _eventDispatcher->addEventListenerWithSceneGraphPriority(accListener, this); - - // title - auto label = Label::createWithTTF("Multi touch the screen", "fonts/Marker Felt.ttf", 36.0f); - label->setPosition(VisibleRect::center().x, VisibleRect::top().y - 30); - this->addChild(label, -1); - - // reset button - createResetButton(); - - // init physics - - physicsDebugNodeOffset = Vec2(0, 0); - initPhysics(); - -#if 1 - // Use batch node. Faster - auto parent = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100); - _spriteTexture = parent->getTexture(); -#else - // doesn't use batch node. Slower - _spriteTexture = Director::getInstance()->getTextureCache()->addImage("Images/grossini_dance_atlas.png"); - auto parent = Node::create(); -#endif - addChild(parent, 0, kTagParentNode); - - addNewSpriteAtPosition(ax::Vec2(200.0f, 200.0f)); - - // menu for debug layer - MenuItemFont::setFontSize(18); - auto item = MenuItemFont::create("Toggle debug", AX_CALLBACK_1(ChipmunkTest::toggleDebugCallback, this)); - - auto menu = Menu::create(item, nullptr); - this->addChild(menu); - menu->setPosition(VisibleRect::right().x - 100, VisibleRect::top().y - 60); - - scheduleUpdate(); -} - -void ChipmunkTest::toggleDebugCallback(Object* sender) -{ - _debugLayer->setVisible(!_debugLayer->isVisible()); -} - -ChipmunkTest::~ChipmunkTest() -{ - // manually Free rogue shapes - for (int i = 0; i < 4; i++) - { - cpShapeFree(_walls[i]); - } - -#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceFree(_space); -#else - cpHastySpaceFree(_space); -#endif - - Device::setAccelerometerEnabled(false); -} - -void ChipmunkTest::initPhysics() -{ - - // init chipmunk - // cpInitChipmunk(); - -#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - _space = cpSpaceNew(); -#else - _space = cpHastySpaceNew(); - cpHastySpaceSetThreads(_space, 0); -#endif - - cpSpaceSetGravity(_space, cpv(0.0f, -100.0f)); - - // - // rogue shapes - // We have to free them manually - // - // bottom - _walls[0] = - cpSegmentShapeNew(cpSpaceGetStaticBody(_space), cpv(VisibleRect::leftBottom().x, VisibleRect::leftBottom().y), - cpv(VisibleRect::rightBottom().x, VisibleRect::rightBottom().y), 0.0f); - - // top - _walls[1] = cpSegmentShapeNew(cpSpaceGetStaticBody(_space), cpv(VisibleRect::leftTop().x, VisibleRect::leftTop().y), - cpv(VisibleRect::rightTop().x, VisibleRect::rightTop().y), 0.0f); - - // left - _walls[2] = - cpSegmentShapeNew(cpSpaceGetStaticBody(_space), cpv(VisibleRect::leftBottom().x, VisibleRect::leftBottom().y), - cpv(VisibleRect::leftTop().x, VisibleRect::leftTop().y), 0.0f); - - // right - _walls[3] = - cpSegmentShapeNew(cpSpaceGetStaticBody(_space), cpv(VisibleRect::rightBottom().x, VisibleRect::rightBottom().y), - cpv(VisibleRect::rightTop().x, VisibleRect::rightTop().y), 0.0f); - - for (int i = 0; i < 4; i++) - { - - cpShapeSetElasticity(_walls[i], 1.0f); - cpShapeSetFriction(_walls[i], 1.0f); - cpSpaceAddShape(_space, _walls[i]); - } - - // Physics debug layer - _debugLayer = PhysicsDebugNodeChipmunk2D::create(_space); - this->addChild(_debugLayer, Z_PHYSICS_DEBUG); -} - -void ChipmunkTest::update(float delta) -{ - // Should use a fixed size step based on the animation interval. - int steps = 2; - float dt = Director::getInstance()->getAnimationInterval() / (float)steps; - - for (int i = 0; i < steps; i++) - { - -#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - cpSpaceStep(_space, dt); -#else - cpHastySpaceStep(_space, dt); -#endif - } -} - -void ChipmunkTest::createResetButton() -{ - auto reset = MenuItemImage::create("Images/r1.png", "Images/r2.png", AX_CALLBACK_1(ChipmunkTest::reset, this)); - - auto menu = Menu::create(reset, nullptr); - - menu->setPosition(VisibleRect::center().x, VisibleRect::bottom().y + 30); - this->addChild(menu, -1); -} - -void ChipmunkTest::reset(Object* sender) -{ - getTestSuite()->restartCurrTest(); -} - -void ChipmunkTest::addNewSpriteAtPosition(ax::Vec2 pos) -{ - int posx, posy; - - auto parent = getChildByTag(kTagParentNode); - - posx = AXRANDOM_0_1() * 200.0f; - posy = AXRANDOM_0_1() * 200.0f; - - posx = (posx % 4) * 85; - posy = (posy % 3) * 121; - - int num = 4; - cpVect verts[] = { - cpv(-24, -54), - cpv(-24, 54), - cpv(24, 54), - cpv(24, -54), - }; - - cpBody* body = cpBodyNew(1.0f, cpMomentForPoly(1.0f, num, verts, cpvzero, 0.0f)); - - cpBodySetPosition(body, cpv(pos.x, pos.y)); - cpSpaceAddBody(_space, body); - - cpShape* shape = cpPolyShapeNew(body, num, verts, cpTransformIdentity, 0.0f); - cpShapeSetElasticity(shape, 0.5f); - cpShapeSetFriction(shape, 0.5f); - cpSpaceAddShape(_space, shape); - - auto sprite = PhysicsSpriteChipmunk2D::createWithTexture(_spriteTexture, ax::Rect(posx, posy, 85, 121)); - parent->addChild(sprite); - - sprite->setCPBody(body); - sprite->setPosition(pos); -} - -void ChipmunkTest::onEnter() -{ - TestCase::onEnter(); -} - -void ChipmunkTest::onTouchesEnded(const std::vector& touches, Event* event) -{ - // Add a new body/atlas sprite at the touched location - - for (auto& touch : touches) - { - auto location = touch->getLocation(); - - addNewSpriteAtPosition(location); - } -} - -void ChipmunkTest::onAcceleration(Acceleration* acc, Event* event) -{ - static float prevX = 0, prevY = 0; - -#define kFilterFactor 0.05f - - float accelX = (float)acc->x * kFilterFactor + (1 - kFilterFactor) * prevX; - float accelY = (float)acc->y * kFilterFactor + (1 - kFilterFactor) * prevY; - - prevX = accelX; - prevY = accelY; - - auto v = ax::Vec2(accelX, accelY); - v = v * 200; - cpSpaceSetGravity(_space, cpv(v.x, v.y)); -} - -ChipmunkTests::ChipmunkTests() -{ - ADD_TEST_CASE(ChipmunkTest); -} diff --git a/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.h b/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.h deleted file mode 100644 index 4da9edf3e65c..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTest/ChipmunkTest.h +++ /dev/null @@ -1,66 +0,0 @@ -/**************************************************************************** - Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. - Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - - https://axmol.dev/ - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -// -// cocos2d -// -#ifndef __CHIPMUNKTEST_H__ -#define __CHIPMUNKTEST_H__ - -#include "axmol.h" -#include "chipmunk/chipmunk.h" -#include "../BaseTest.h" -#include "extensions/axmol-ext.h" - -class ChipmunkTest : public TestCase -{ -public: - CREATE_FUNC(ChipmunkTest); - - ChipmunkTest(); - ~ChipmunkTest(); - void onEnter() override; - void initPhysics(); - void createResetButton(); - void reset(ax::Object* sender); - - void addNewSpriteAtPosition(ax::Vec2 p); - void update(float dt) override; - void toggleDebugCallback(ax::Object* sender); - void onTouchesEnded(const std::vector& touches, ax::Event* event); - virtual void onAcceleration(ax::Acceleration* acc, ax::Event* event); - -private: - ax::Texture2D* _spriteTexture; // weak ref - ax::extension::PhysicsDebugNodeChipmunk2D* _debugLayer; // weak ref - - cpSpace* _space; // strong ref - cpShape* _walls[4]; - ax::DrawNode* drawNode; -}; - -DEFINE_TEST_SUITE(ChipmunkTests); - -#endif /* __CHIPMUNKACCELTOUCHTEST_H__ */ diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.cpp deleted file mode 100644 index edb58f327fe5..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.cpp +++ /dev/null @@ -1,1269 +0,0 @@ -/**************************************************************************** - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -#include -#include -#include -#include -#include - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/chipmunk.h" - -#include "ChipmunkTestBed.h" - -using namespace ax; -USING_NS_AX_EXT; - -enum -{ - kTagParentNode = 1, -}; - -enum -{ - Z_PHYSICS_DEBUG = 100, -}; - -extern ChipmunkDemo Example; // Use as template for new Chipmunk2D demos -extern ChipmunkDemo LogoSmash; -extern ChipmunkDemo PyramidStack; -extern ChipmunkDemo Plink; -extern ChipmunkDemo Tumble; -extern ChipmunkDemo PyramidTopple; -extern ChipmunkDemo Planet; -extern ChipmunkDemo Springies; -extern ChipmunkDemo Pump; -extern ChipmunkDemo TheoJansen; -extern ChipmunkDemo Query; -extern ChipmunkDemo OneWay; -extern ChipmunkDemo PlatformerPlayer; -extern ChipmunkDemo Joints; -extern ChipmunkDemo Tank; -extern ChipmunkDemo Chains; -extern ChipmunkDemo Crane; -extern ChipmunkDemo Buoyancy; -extern ChipmunkDemo ContactGraph; -extern ChipmunkDemo Slice; -extern ChipmunkDemo Convex; -extern ChipmunkDemo Unicycle; -extern ChipmunkDemo Sticky; -extern ChipmunkDemo Shatter; -extern ChipmunkDemo bench_list[]; -extern int bench_count; -int bench = 16; - -static Vec2 cpVert2Point(const cpVect& vert) -{ - return Vec2(vert.x, vert.y) + physicsDebugNodeOffset; -} - -ChipmunkDemo demos[] = {LogoSmash, PyramidStack, Plink, Tumble, PyramidTopple, Planet, - Springies, Pump, TheoJansen, Query, OneWay, Joints, - Tank, Chains, Crane, ContactGraph, Buoyancy, PlatformerPlayer, - Slice, Convex, Unicycle, Sticky, Shatter}; - -int demo_count = sizeof(demos); - -cpVect ChipmunkDemoMouse; -cpVect ChipmunkDemoKeyboard; -cpBool ChipmunkDemoRightClick = cpFalse; -cpBool ChipmunkDemoRightDown = cpFalse; -cpBool ChipmunkDemoLeftDown = cpFalse; -double ChipmunkDemoTime; - -cpBody* mouse_body = cpBodyNewKinematic(); -static cpConstraint* mouse_joint = nullptr; - -char const* ChipmunkDemoMessageString = nullptr; - -#define GRABBABLE_MASK_BIT (1 << 31) -cpShapeFilter GRAB_FILTER = {CP_NO_GROUP, (unsigned int)GRABBABLE_MASK_BIT, (unsigned int)GRABBABLE_MASK_BIT}; -cpShapeFilter NOT_GRABBABLE_FILTER = {CP_NO_GROUP, ~GRABBABLE_MASK_BIT, ~GRABBABLE_MASK_BIT}; - -ax::DrawNode* drawCP = nullptr; - -void ChipmunkDemoDefaultDrawImpl(cpSpace* space){}; - -void ChipmunkDebugDrawDot(cpFloat size, cpVect pos, cpSpaceDebugColor fillColor) -{ - - drawCP->drawPoint(Vec2(pos.x, pos.y) + physicsDebugNodeOffset, size, - Color4F(fillColor.r, fillColor.g, fillColor.b, fillColor.a)); -} - -void ChipmunkDebugDrawCircle(cpVect pos, - cpFloat angle, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor) -{ - - drawCP->drawCircle(Vec2(pos.x, pos.y) + physicsDebugNodeOffset, 100, AX_DEGREES_TO_RADIANS(90), 50, true, 1.0f, - 2.0f, Color4F(fillColor.r, fillColor.g, fillColor.b, fillColor.a)); -} - -void ChipmunkDebugDrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color) -{ - drawCP->drawLine(Vec2(a.x, a.y) + physicsDebugNodeOffset, Vec2(b.x, b.y) + physicsDebugNodeOffset, - Color4F(color.r, color.g, color.b, color.a)); -} - -void ChipmunkDebugDrawFatSegment(cpVect a, - cpVect b, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor) -{ - - drawCP->drawSegment(Vec2(a.x, a.y) + physicsDebugNodeOffset, Vec2(b.x, b.y) + physicsDebugNodeOffset, radius, - Color4F(outlineColor.r, outlineColor.g, outlineColor.b, outlineColor.a)); -} - -void ChipmunkDebugDrawPolygon(int count, - const cpVect* verts, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor) -{ - - Vec2* vec = new Vec2[count]; - for (size_t i = 0; i < count; i++) - { - vec[i] = cpVert2Point(verts[i]); - } - drawCP->drawPolygon(vec, count, Color4F(1.0f, 0.0f, 0.0f, 0.5f), radius, Color4F(0.0f, 0.0f, 1.0f, 1.0f)); - - delete[] vec; -} - -void ChipmunkDebugDrawBB(cpBB bb, cpSpaceDebugColor color) -{ - Vec2 verts[] = { - Vec2(bb.r, bb.b) + physicsDebugNodeOffset, - Vec2(bb.r, bb.t) + physicsDebugNodeOffset, - Vec2(bb.l, bb.t) + physicsDebugNodeOffset, - Vec2(bb.l, bb.b) + physicsDebugNodeOffset, - }; - drawCP->drawPolygon(verts, sizeof(verts) / sizeof(verts[0]), Color4F(1.0f, 0.0f, 0.0f, 0.0f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); -} - -ax::Label* label; - -static int max_arbiters = 0; -static int max_points = 0; -static int max_constraints = 0; - -void ChipmunkTestBed::DrawInfo() -{ - int arbiters = _space->arbiters->num; - int points = 0; - - for (int i = 0; i < arbiters; i++) - points += ((cpArbiter*)(_space->arbiters->arr[i]))->count; - - int constraints = (_space->constraints->num + points) * _space->iterations; - - max_arbiters = arbiters > max_arbiters ? arbiters : max_arbiters; - max_points = points > max_points ? points : max_points; - max_constraints = constraints > max_constraints ? constraints : max_constraints; - - char buffer[1024]; - constexpr auto format = - "Arbiters: {} ({}) - " - "Contact Points: {} ({})\n" - "Other Constraints: {}, Iterations: {}\n" - "Constraints x Iterations: {} ({})\n" - "Time:{:5.2f}s, KE:{:5.2e}"sv; - - cpArray* bodies = _space->dynamicBodies; - cpFloat ke = 0.0f; - for (int i = 0; i < bodies->num; i++) - { - cpBody* body = (cpBody*)bodies->arr[i]; - if (body->m == INFINITY || body->i == INFINITY) - continue; - - ke += body->m * cpvdot(body->v, body->v) + body->i * body->w * body->w; - } - - auto msg = fmt::format_to_z(buffer, format, arbiters, max_arbiters, points, max_points, _space->constraints->num, _space->iterations, - constraints, max_constraints, ChipmunkDemoTime, (ke < 1e-10f ? 0.0f : ke)); - - drawInfo->setString(msg); -} - -static char PrintStringBuffer[1024 * 8]; -static char* PrintStringCursor; -void ChipmunkDemoPrintString(char const* fmt, ...) -{ - if (PrintStringCursor == nullptr) - { - return; - } - - ChipmunkDemoMessageString = PrintStringBuffer; - - va_list args; - va_start(args, fmt); - int remaining = sizeof(PrintStringBuffer) - (PrintStringCursor - PrintStringBuffer); - int would_write = vsnprintf(PrintStringCursor, remaining, fmt, args); - if (would_write > 0 && would_write < remaining) - { - PrintStringCursor += would_write; - } - else - { - // encoding error or overflow, prevent further use until reinitialized - PrintStringCursor = nullptr; - } - va_end(args); - - label->setString(ChipmunkDemoMessageString); -} - -cpSpaceDebugColor RGBAColor(float r, float g, float b, float a) -{ - cpSpaceDebugColor color = {r, g, b, a}; - return color; -}; - -cpSpaceDebugColor LAColor(float l, float a) -{ - cpSpaceDebugColor color = {l, l, l, a}; - return color; -} - -static void ShapeFreeWrap(cpSpace* space, cpShape* shape, void* unused) -{ - cpSpaceRemoveShape(space, shape); - cpShapeFree(shape); -} - -static void PostShapeFree(cpShape* shape, cpSpace* space) -{ - cpSpaceAddPostStepCallback(space, (cpPostStepFunc)ShapeFreeWrap, shape, nullptr); -} - -static void ConstraintFreeWrap(cpSpace* space, cpConstraint* constraint, void* unused) -{ - mouse_joint = nullptr; - cpSpaceRemoveConstraint(space, constraint); - cpConstraintFree(constraint); -} - -static void PostConstraintFree(cpConstraint* constraint, cpSpace* space) -{ - cpSpaceAddPostStepCallback(space, (cpPostStepFunc)ConstraintFreeWrap, constraint, nullptr); -} - -static void BodyFreeWrap(cpSpace* space, cpBody* body, void* unused) -{ - cpSpaceRemoveBody(space, body); - cpBodyFree(body); -} - -static void PostBodyFree(cpBody* body, cpSpace* space) -{ - cpSpaceAddPostStepCallback(space, (cpPostStepFunc)BodyFreeWrap, body, nullptr); -} - -// Safe and future proof way to remove and free all objects that have been added to the space. -void ChipmunkDemoFreeSpaceChildren(cpSpace* space) -{ - // Must remove these BEFORE freeing the body or you will access dangling pointers. - cpSpaceEachShape(space, (cpSpaceShapeIteratorFunc)PostShapeFree, space); - cpSpaceEachConstraint(space, (cpSpaceConstraintIteratorFunc)PostConstraintFree, space); - cpSpaceEachBody(space, (cpSpaceBodyIteratorFunc)PostBodyFree, space); -} - -void updateMouseBody(void) -{ - cpVect new_point = cpvlerp(mouse_body->p, ChipmunkDemoMouse, 0.25f); - mouse_body->v = cpvmult(cpvsub(new_point, mouse_body->p), 60.0f); - mouse_body->p = new_point; -} - -ChipmunkTestBed::ChipmunkTestBed() -{ - // halx99: since axmol init scene default camera at 'initWithXXX' function, only change design size at scene - // construct is ok see also: https://github.com/axmolengine/axmol/commit/581a7921554c09746616759d5a5ca6ce9d3eaa22 - auto director = Director::getInstance(); - auto renderView = director->getRenderView(); - Size designSize(g_designSize.width * 0.85, g_designSize.height * 0.85); - renderView->setDesignResolutionSize(designSize.width, designSize.height, ResolutionPolicy::SHOW_ALL); - - // creating a keyboard event listener - auto listener = EventListenerKeyboard::create(); - listener->onKeyPressed = [](EventKeyboard::KeyCode keyCode, Event* event) { - if ((int)keyCode == 26) // Left - { - ChipmunkDemoKeyboard.x--; - } - if ((int)keyCode == 27) // Right - { - ChipmunkDemoKeyboard.x++; - } - if ((int)keyCode == 28) // Up - { - ChipmunkDemoKeyboard.y++; - } - if ((int)keyCode == 29) // Down - { - ChipmunkDemoKeyboard.y--; - } - }; - - listener->onKeyReleased = [](EventKeyboard::KeyCode keyCode, Event* event) { ChipmunkDemoKeyboard = {0, 0}; }; - - _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); - - // creating a mouse event listener - _mouseListener = EventListenerMouse::create(); - _mouseListener->onMouseMove = AX_CALLBACK_1(ChipmunkTestBed::onMouseMove, this); - _mouseListener->onMouseUp = AX_CALLBACK_1(ChipmunkTestBed::onMouseUp, this); - _mouseListener->onMouseDown = AX_CALLBACK_1(ChipmunkTestBed::onMouseDown, this); - _eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this); - - // Some info text - auto label1 = Label::createWithTTF("Use the mouse to grab objects.", "fonts/Marker Felt.ttf", 12.0f); - label1->setPosition(VisibleRect::center().x, VisibleRect::top().y - 100); - label1->setColor(Color3B::WHITE); - this->addChild(label1, 1000); - - // ChipmunkDemoMessageString - label = Label::createWithTTF("", "fonts/Marker Felt.ttf", 12.0f); - label->setPosition(VisibleRect::center().x, VisibleRect::top().y - 130); - label->setColor(Color3B::MAGENTA); - this->addChild(label, 1000); - - drawInfo = Label::createWithTTF("Use the mouse to grab objects.", "fonts/Marker Felt.ttf", 12.0f); - drawInfo->setAnchorPoint(Vec2(0, 0)); - drawInfo->setPosition(VisibleRect::left().x + 10, VisibleRect::top().y - 60); - drawInfo->setColor(Color3B::WHITE); - this->addChild(drawInfo, 1000); - - draw = DrawNode::create(); - addChild(draw, 100); - - drawCP = draw; - - scheduleUpdate(); -} - -ChipmunkTestBed::~ChipmunkTestBed() -{ - ChipmunkDemoFreeSpaceChildren(_space); - _eventDispatcher->removeEventListener(_mouseListener); -} - -void ChipmunkTestBed::initPhysics() -{ - if (ChipmunkDemoMessageString) - { - label->setString(ChipmunkDemoMessageString); - } - else - { - label->setString(""); - } - drawCP->clear(); - // Physics debug layer - _debugLayer = PhysicsDebugNodeChipmunk2D::create(_space); - this->addChild(_debugLayer, Z_PHYSICS_DEBUG); -} - -void ChipmunkTestBed::update(float delta) -{ - //#if AX_TARGET_PLATFORM == AX_PLATFORM_WIN32 - // cpSpaceStep(_space, delta); - //#else - // cpHastySpaceStep(_space, delta); - //#endif -} - -void ChipmunkTestBed::createResetButton() -{ - auto reset = MenuItemImage::create("Images/r1.png", "Images/r2.png", AX_CALLBACK_1(ChipmunkTestBed::reset, this)); - auto menu = Menu::create(reset, nullptr); - menu->setPosition(VisibleRect::center().x, VisibleRect::bottom().y); - this->addChild(menu, -1); -} - -void ChipmunkTestBed::reset(Object* sender) -{ - ChipmunkDemoFreeSpaceChildren(_space); - getTestSuite()->restartCurrTest(); -} - -void ChipmunkTestBed::onEnter() -{ - TestCase::onEnter(); - physicsDebugNodeOffset = VisibleRect::center(); - physicsDebugNodeOffset.y += 20; - ChipmunkDemoMessageString = ""; - label->setString(""); -} - -bool ChipmunkTestBed::onMouseDown(Event* event) -{ - EventMouse* e = (EventMouse*)event; - - if ((int)e->getMouseButton() == 0) - { - ChipmunkDemoLeftDown = cpTrue; - // give the mouse click a little radius to make it easier to click small shapes. - cpFloat radius = 5.0; - - cpPointQueryInfo info = {0}; - cpShape* shape = cpSpacePointQueryNearest(_space, ChipmunkDemoMouse, radius, GRAB_FILTER, &info); - - if (shape && cpBodyGetMass(cpShapeGetBody(shape)) < INFINITY) - { - // Use the closest point on the surface if the click is outside of the shape. - cpVect nearest = (info.distance > 0.0f ? info.point : ChipmunkDemoMouse); - - cpBody* body = cpShapeGetBody(shape); - mouse_joint = cpPivotJointNew2(mouse_body, body, cpvzero, cpBodyWorldToLocal(body, nearest)); - mouse_joint->maxForce = 50000.0f; - mouse_joint->errorBias = cpfpow(1.0f - 0.15f, 60.0f); - cpSpaceAddConstraint(_space, mouse_joint); - } - } - else if ((int)e->getMouseButton() == 1) - { - if (mouse_joint) - { - cpSpaceRemoveConstraint(_space, mouse_joint); - cpConstraintFree(mouse_joint); - mouse_joint = nullptr; - } - ChipmunkDemoRightDown = cpTrue; - ChipmunkDemoRightClick = cpTrue; - } - - return true; -} - -bool ChipmunkTestBed::onMouseUp(Event* event) -{ - EventMouse* e = (EventMouse*)event; - mousePresses = false; - if (mouse_joint) - { - cpSpaceRemoveConstraint(_space, mouse_joint); - cpConstraintFree(mouse_joint); - mouse_joint = nullptr; - } - ChipmunkDemoLeftDown = cpFalse; - ChipmunkDemoRightDown = cpFalse; - ChipmunkDemoRightClick = cpFalse; - - return true; -} - -bool ChipmunkTestBed::onMouseMove(Event* event) -{ - EventMouse* e = (EventMouse*)event; - auto pt = e->getLocation(); - ChipmunkDemoMouse.x = pt.x - physicsDebugNodeOffset.x; - ChipmunkDemoMouse.y = pt.y - physicsDebugNodeOffset.y; - - cpBodySetPosition(mouse_body, ChipmunkDemoMouse); - - return true; -} - -void ChipmunkTestBed::updateInit(ChipmunkDemo tt) -{ - PrintStringBuffer[0] = 0; - PrintStringCursor = PrintStringBuffer; - - drawCP->clear(); - updateMouseBody(); - ChipmunkDemoTime += tt.timestep; - ChipmunkTestBed::DrawInfo(); - tt.updateFunc(_space, tt.timestep); -} - -//------------------------------------------------------------------ -// -// LogoSmashDemo -// -//------------------------------------------------------------------ -void LogoSmashDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - initPhysics(); -} - -std::string LogoSmashDemo::title() const -{ - return LogoSmash.name; -} - -void LogoSmashDemo::initPhysics() -{ - _space = LogoSmash.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void LogoSmashDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(LogoSmash); -} - -//------------------------------------------------------------------ -// -// PlinkDemo -// -//------------------------------------------------------------------ -void PlinkDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string PlinkDemo::title() const -{ - return Plink.name; -} - -void PlinkDemo::initPhysics() -{ - _space = Plink.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PlinkDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Plink); -} - -//------------------------------------------------------------------ -// -// TumbleDemo -// -//------------------------------------------------------------------ -void TumbleDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - initPhysics(); -} - -std::string TumbleDemo::title() const -{ - return Tumble.name; -} - -void TumbleDemo::initPhysics() -{ - _space = Tumble.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void TumbleDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Tumble); -} - -//------------------------------------------------------------------ -// -// PyramidStackDemo -// -//------------------------------------------------------------------ -void PyramidStackDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - initPhysics(); -} - -std::string PyramidStackDemo::title() const -{ - return PyramidStack.name; -} - -void PyramidStackDemo::initPhysics() -{ - _space = PyramidStack.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PyramidStackDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(PyramidStack); -} - -//------------------------------------------------------------------ -// -// PyramidToppleDemo -// -//------------------------------------------------------------------ -void PyramidToppleDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - initPhysics(); -} - -std::string PyramidToppleDemo::title() const -{ - return PyramidTopple.name; -} - -void PyramidToppleDemo::initPhysics() -{ - _space = PyramidTopple.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PyramidToppleDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(PyramidTopple); -} - -//------------------------------------------------------------------ -// -// ChainDemo -// -//------------------------------------------------------------------ -void ChainsDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string ChainsDemo::title() const -{ - return Chains.name; -} - -void ChainsDemo::initPhysics() -{ - _space = Chains.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void ChainsDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Chains); -} - -//------------------------------------------------------------------ -// -// OneWayDemo -// -//------------------------------------------------------------------ -void OneWayDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string OneWayDemo::title() const -{ - return OneWay.name; -} - -void OneWayDemo::initPhysics() -{ - _space = OneWay.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void OneWayDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(OneWay); -} - -//------------------------------------------------------------------ -// -// PlanetDemo -// -//------------------------------------------------------------------ -void PlanetDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string PlanetDemo::title() const -{ - return Planet.name; -} - -void PlanetDemo::initPhysics() -{ - _space = Planet.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PlanetDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Planet); -} - -//------------------------------------------------------------------ -// -// TheoJansenDemo -// -//------------------------------------------------------------------ -void TheoJansenDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string TheoJansenDemo::title() const -{ - return TheoJansen.name; -} - -void TheoJansenDemo::initPhysics() -{ - _space = TheoJansen.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void TheoJansenDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(TheoJansen); -} - -//------------------------------------------------------------------ -// -// TankDemo -// -//------------------------------------------------------------------ -void TankDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string TankDemo::title() const -{ - return Tank.name; -} - -void TankDemo::initPhysics() -{ - _space = Tank.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void TankDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Tank); -} - -//------------------------------------------------------------------ -// -// BenchDemo -// -//------------------------------------------------------------------ -void BenchDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - auto itemPrev = MenuItemImage::create("Images/b1.png", "Images/b2.png", [&](Object* sender) { - bench = (bench > 0) ? bench - 1 : (bench_count - 1); - reset(sender); - }); - - auto itemNext = MenuItemImage::create("Images/f1.png", "Images/f2.png", [&](Object* sender) { - bench = (bench < (bench_count - 1)) ? bench + 1 : 0; - reset(sender); - }); - - auto s = Director::getInstance()->getWinSize(); - - auto menuPrev = Menu::create(itemPrev, nullptr); - menuPrev->alignItemsHorizontally(); - menuPrev->setScale(0.4); - menuPrev->setAnchorPoint(Vec2(0.0f, 0.0f)); - menuPrev->setPosition(Vec2(s.width / 2 - 45, 23.0f)); - addChild(menuPrev); - - auto menuNext = Menu::create(itemNext, nullptr); - menuNext->alignItemsHorizontally(); - menuNext->setScale(0.4); - menuNext->setAnchorPoint(Vec2(0.0f, 0.0f)); - menuNext->setPosition(Vec2(s.width / 2 + 45, 23.0f)); - addChild(menuNext); - - initPhysics(); -} - -std::string BenchDemo::title() const -{ - return "Bench"; -} - -std::string BenchDemo::subtitle() const -{ - std::string s = std::to_string(bench + 1) + ". " + bench_list[bench].name; - return s.c_str(); -} - -void BenchDemo::initPhysics() -{ - _space = bench_list[bench].initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void BenchDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(bench_list[bench]); -} - -//------------------------------------------------------------------ -// -// SpringiesDemo -// -//------------------------------------------------------------------ -void SpringiesDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string SpringiesDemo::title() const -{ - return Springies.name; -} - -void SpringiesDemo::initPhysics() -{ - _space = Springies.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void SpringiesDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Springies); -} - -//------------------------------------------------------------------ -// -// ShatterDemo -// -//------------------------------------------------------------------ -void ShatterDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - initPhysics(); -} - -std::string ShatterDemo::title() const -{ - return Shatter.name; -} - -void ShatterDemo::initPhysics() -{ - _space = Shatter.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void ShatterDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Shatter); -} - -//------------------------------------------------------------------ -// -// StickyDemo -// -//------------------------------------------------------------------ -void StickyDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string StickyDemo::title() const -{ - return Sticky.name; -} - -void StickyDemo::initPhysics() -{ - _space = Sticky.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void StickyDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Sticky); -} - -//------------------------------------------------------------------ -// -// CraneDemo -// -//------------------------------------------------------------------ -void CraneDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string CraneDemo::title() const -{ - return Crane.name; -} - -void CraneDemo::initPhysics() -{ - _space = Crane.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void CraneDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Crane); -} - -//------------------------------------------------------------------ -// -// JointsDemo -// -//------------------------------------------------------------------ -void JointsDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string JointsDemo::title() const -{ - return Joints.name; -} - -void JointsDemo::initPhysics() -{ - _space = Joints.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void JointsDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Joints); -} - -//------------------------------------------------------------------ -// -// ConvexDemo -// -//------------------------------------------------------------------ -void ConvexDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string ConvexDemo::title() const -{ - return Convex.name; -} - -void ConvexDemo::initPhysics() -{ - _space = Convex.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void ConvexDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Convex); -} - -//------------------------------------------------------------------ -// -// PumpDemo -// -//------------------------------------------------------------------ -void PumpDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string PumpDemo::title() const -{ - return Pump.name; -} - -void PumpDemo::initPhysics() -{ - _space = Pump.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PumpDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Pump); -} - -//------------------------------------------------------------------ -// -// PlatformerPlayerDemo -// -//------------------------------------------------------------------ -void PlatformerPlayerDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string PlatformerPlayerDemo::title() const -{ - return PlatformerPlayer.name; -} - -void PlatformerPlayerDemo::initPhysics() -{ - _space = PlatformerPlayer.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void PlatformerPlayerDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(PlatformerPlayer); -} - -//------------------------------------------------------------------ -// -// QueryDemo -// -//------------------------------------------------------------------ -void QueryDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string QueryDemo::title() const -{ - return Query.name; -} - -void QueryDemo::initPhysics() -{ - _space = Query.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void QueryDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Query); -} - -//------------------------------------------------------------------ -// -// ContactGraphDemo -// -//------------------------------------------------------------------ -void ContactGraphDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string ContactGraphDemo::title() const -{ - return ContactGraph.name; -} - -void ContactGraphDemo::initPhysics() -{ - _space = ContactGraph.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void ContactGraphDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(ContactGraph); -} - -//------------------------------------------------------------------ -// -// BuoyancyDemo -// -//------------------------------------------------------------------ -void BuoyancyDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string BuoyancyDemo::title() const -{ - return Buoyancy.name; -} - -void BuoyancyDemo::initPhysics() -{ - _space = Buoyancy.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void BuoyancyDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Buoyancy); -} - -//------------------------------------------------------------------ -// -// SliceDemo -// -//------------------------------------------------------------------ -void SliceDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string SliceDemo::title() const -{ - return Slice.name; -} - -void SliceDemo::initPhysics() -{ - _space = Slice.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void SliceDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Slice); -} - -//------------------------------------------------------------------ -// -// UnicycleDemo -// -//------------------------------------------------------------------ -void UnicycleDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string UnicycleDemo::title() const -{ - return Unicycle.name; -} - -void UnicycleDemo::initPhysics() -{ - _space = Unicycle.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void UnicycleDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Unicycle); -} - -//------------------------------------------------------------------ -// -// ExampleDemo -// -//------------------------------------------------------------------ -void ExampleDemo::onEnter() -{ - ChipmunkTestBed::onEnter(); - - initPhysics(); -} - -std::string ExampleDemo::title() const -{ - return Example.name; -} - -void ExampleDemo::initPhysics() -{ - _space = Example.initFunc(); - ChipmunkTestBed::initPhysics(); -} - -void ExampleDemo::update(float delta) -{ - ChipmunkTestBed::updateInit(Example); -} - -ChipmunkTestBedTests::ChipmunkTestBedTests() -{ - ADD_TEST_CASE(BenchDemo); - ADD_TEST_CASE(LogoSmashDemo); - ADD_TEST_CASE(PlinkDemo); - ADD_TEST_CASE(TumbleDemo); - ADD_TEST_CASE(PyramidToppleDemo); - ADD_TEST_CASE(PyramidStackDemo); - ADD_TEST_CASE(ChainsDemo); - ADD_TEST_CASE(OneWayDemo); - ADD_TEST_CASE(PlanetDemo); - ADD_TEST_CASE(TheoJansenDemo); - ADD_TEST_CASE(TankDemo); - - ADD_TEST_CASE(SpringiesDemo); - - ADD_TEST_CASE(ShatterDemo); - ADD_TEST_CASE(StickyDemo); - ADD_TEST_CASE(CraneDemo); - ADD_TEST_CASE(JointsDemo); - - ADD_TEST_CASE(ConvexDemo); - - ADD_TEST_CASE(PumpDemo); - ADD_TEST_CASE(PlatformerPlayerDemo); - - ADD_TEST_CASE(QueryDemo); - ADD_TEST_CASE(ContactGraphDemo); - ADD_TEST_CASE(BuoyancyDemo); - ADD_TEST_CASE(SliceDemo); - ADD_TEST_CASE(UnicycleDemo); - - ADD_TEST_CASE(ExampleDemo); // the template for your one examples/Demos -} diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.h b/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.h deleted file mode 100644 index 572c6a32828f..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/ChipmunkTestBed.h +++ /dev/null @@ -1,345 +0,0 @@ -/**************************************************************************** - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in - all copies or substantial portions of the Software. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - THE SOFTWARE. - ****************************************************************************/ - -// -// cocos2d -// -#ifndef __CHIPMUNKTESTBED_H__ -#define __CHIPMUNKTESTBED_H__ - -#include "axmol.h" -#include "chipmunk/chipmunk.h" -#include "../BaseTest.h" -#include "extensions/axmol-ext.h" - -#include "demo/ChipmunkDemo.h" - -class ChipmunkTestBed : public TestCase -{ -public: - CREATE_FUNC(ChipmunkTestBed); - - ChipmunkTestBed(); - ~ChipmunkTestBed(); - - void onEnter() override; - void createResetButton(); - void reset(ax::Object* sender); - - void update(float dt) override; - virtual void initPhysics(); - - bool onMouseDown(ax::Event* event); - bool onMouseUp(ax::Event* event); - bool onMouseMove(ax::Event* event); - void DrawInfo(); - void updateInit(ChipmunkDemo tt); - - cpSpace* _space; // strong ref - ax::extension::PhysicsDebugNodeChipmunk2D* _debugLayer; // weak ref - int keyPresses; - bool mousePresses = false; - -private: - ax::EventListenerMouse* _mouseListener; - ax::Node* _trackNode; - ax::DrawNode* draw; - ax::Label* drawInfo; -}; - -class LogoSmashDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(LogoSmashDemo); - std::string title() const override; - void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PlinkDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PlinkDemo); - virtual std::string title() const override; - virtual void onEnter() override; - void initPhysics() override; - virtual void update(float dt) override; -}; - -class TumbleDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(TumbleDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PyramidStackDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PyramidStackDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PyramidToppleDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PyramidToppleDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class ChainsDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(ChainsDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class OneWayDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(OneWayDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PlanetDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PlanetDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class TheoJansenDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(TheoJansenDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class TankDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(TankDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class BenchDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(BenchDemo); - virtual std::string title() const override; - virtual std::string subtitle() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class SpringiesDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(SpringiesDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class StickyDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(StickyDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class ShatterDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(ShatterDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class CraneDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(CraneDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class JointsDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(JointsDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class ConvexDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(ConvexDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PumpDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PumpDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class PlatformerPlayerDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(PlatformerPlayerDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class QueryDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(QueryDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class ContactGraphDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(ContactGraphDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class BuoyancyDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(BuoyancyDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class SliceDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(SliceDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class UnicycleDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(UnicycleDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; - -class ExampleDemo : public ChipmunkTestBed -{ -public: - CREATE_FUNC(ExampleDemo); - virtual std::string title() const override; - virtual void onEnter() override; - - void initPhysics() override; - virtual void update(float dt) override; -}; -DEFINE_TEST_SUITE(ChipmunkTestBedTests); - -#endif /* __CHIPMUNKTESTBED_H__ */ diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Bench.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Bench.cpp deleted file mode 100644 index 76dfe5755f47..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Bench.cpp +++ /dev/null @@ -1,614 +0,0 @@ -#include "chipmunk/chipmunk.h" -#include "chipmunk/chipmunk_unsafe.h" -#include "ChipmunkDemo.h" - -#define ENABLE_HASTY 0 -#if ENABLE_HASTY -# include "chipmunk/cpHastySpace.h" - -static cpSpace* MakeHastySpace() -{ - cpSpace* space = cpHastySpaceNew(); - cpHastySpaceSetThreads(space, 0); - return space; -} - -# define BENCH_SPACE_NEW MakeHastySpace -# define BENCH_SPACE_FREE cpHastySpaceFree -# define BENCH_SPACE_STEP cpHastySpaceStep -#else -# define BENCH_SPACE_NEW cpSpaceNew -# define BENCH_SPACE_FREE cpSpaceFree -# define BENCH_SPACE_STEP cpSpaceStep -#endif - -const cpFloat bevel = 1.0; - -static cpVect simple_terrain_verts[] = { - {350.00, 425.07}, {336.00, 436.55}, {272.00, 435.39}, {258.00, 427.63}, {225.28, 420.00}, {202.82, 396.00}, - {191.81, 388.00}, {189.00, 381.89}, {173.00, 380.39}, {162.59, 368.00}, {150.47, 319.00}, {128.00, 311.55}, - {119.14, 286.00}, {126.84, 263.00}, {120.56, 227.00}, {141.14, 178.00}, {137.52, 162.00}, {146.51, 142.00}, - {156.23, 136.00}, {158.00, 118.27}, {170.00, 100.77}, {208.43, 84.00}, {224.00, 69.65}, {249.30, 68.00}, - {257.00, 54.77}, {363.00, 45.94}, {374.15, 54.00}, {386.00, 69.60}, {413.00, 70.73}, {456.00, 84.89}, - {468.09, 99.00}, {467.09, 123.00}, {464.92, 135.00}, {469.00, 141.03}, {497.00, 148.67}, {513.85, 180.00}, - {509.56, 223.00}, {523.51, 247.00}, {523.00, 277.00}, {497.79, 311.00}, {478.67, 348.00}, {467.90, 360.00}, - {456.76, 382.00}, {432.95, 389.00}, {417.00, 411.32}, {373.00, 433.19}, {361.00, 430.02}, {350.00, 425.07}, -}; -static int simple_terrain_count = sizeof(simple_terrain_verts) / sizeof(cpVect); - -// cpBody bodies[1000] = {}; -// cpCircleShape circles[1000] = {}; - -static void add_circle(cpSpace* space, int index, cpFloat radius) -{ - cpFloat mass = radius * radius / 25.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - // cpBody *body = cpSpaceAddBody(space, cpBodyInit(&bodies[i], mass, cpMomentForCircle(mass, 0.0f, radius, - // cpvzero))); - cpBodySetPosition(body, cpvmult(frand_unit_circle(), 180.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - // cpShape *shape = cpSpaceAddShape(space, cpCircleShapeInit(&circles[i], body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.9); -} - -static void add_box(cpSpace* space, int index, cpFloat size) -{ - cpFloat mass = size * size / 100.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size))); - // cpBody *body = cpSpaceAddBody(space, cpBodyInit(&bodies[i], mass, cpMomentForBox(mass, size, size))); - cpBodySetPosition(body, cpvmult(frand_unit_circle(), 180.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(body, size - bevel * 2, size - bevel * 2, 0.0)); - cpPolyShapeSetRadius(shape, bevel); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.9); -} - -static void add_hexagon(cpSpace* space, int index, cpFloat radius) -{ - cpVect hexagon[6]; - for (int i = 0; i < 6; i++) - { - cpFloat angle = -CP_PI * 2.0f * i / 6.0f; - hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel); - } - - cpFloat mass = radius * radius; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon, cpvzero, 0.0f))); - cpBodySetPosition(body, cpvmult(frand_unit_circle(), 180.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 6, hexagon, cpTransformIdentity, bevel)); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.9); -} - -static cpSpace* SetupSpace_simpleTerrain() -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpVect offset = cpv(-320, -240); - for (int i = 0; i < (simple_terrain_count - 1); i++) - { - cpVect a = simple_terrain_verts[i], b = simple_terrain_verts[i + 1]; - cpSpaceAddShape(space, - cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpvadd(a, offset), cpvadd(b, offset), 0.0f)); - } - - return space; -} - -// SimpleTerrain constant sized objects -static cpSpace* init_SimpleTerrainCircles_1000(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 1000; i++) - add_circle(space, i, 5.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainCircles_500(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 500; i++) - add_circle(space, i, 5.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainCircles_100(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 100; i++) - add_circle(space, i, 5.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainBoxes_1000(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 1000; i++) - add_box(space, i, 10.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainBoxes_500(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 500; i++) - add_box(space, i, 10.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainBoxes_100(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 100; i++) - add_box(space, i, 10.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainHexagons_1000(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 1000; i++) - add_hexagon(space, i, 5.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainHexagons_500(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 500; i++) - add_hexagon(space, i, 5.0f); - - return space; -} - -static cpSpace* init_SimpleTerrainHexagons_100(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 100; i++) - add_hexagon(space, i, 5.0f); - - return space; -} - -// SimpleTerrain variable sized objects -static cpFloat rand_size() -{ - return cpfpow(1.5, cpflerp(-1.5, 3.5, frand())); -} - -static cpSpace* init_SimpleTerrainVCircles_200(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 200; i++) - add_circle(space, i, 5.0f * rand_size()); - - return space; -} - -static cpSpace* init_SimpleTerrainVBoxes_200(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 200; i++) - add_box(space, i, 8.0f * rand_size()); - - return space; -} - -static cpSpace* init_SimpleTerrainVHexagons_200(void) -{ - cpSpace* space = SetupSpace_simpleTerrain(); - for (int i = 0; i < 200; i++) - add_hexagon(space, i, 5.0f * rand_size()); - - return space; -} - -// ComplexTerrain -static cpVect complex_terrain_verts[] = { - {46.78, 479.00}, {35.00, 475.63}, {27.52, 469.00}, {23.52, 455.00}, {23.78, 441.00}, {28.41, 428.00}, - {49.61, 394.00}, {59.00, 381.56}, {80.00, 366.03}, {81.46, 358.00}, {86.31, 350.00}, {77.74, 320.00}, - {70.26, 278.00}, {67.51, 270.00}, {58.86, 260.00}, {57.19, 247.00}, {38.00, 235.60}, {25.76, 221.00}, - {24.58, 209.00}, {27.63, 202.00}, {31.28, 198.00}, {40.00, 193.72}, {48.00, 193.73}, {55.00, 196.70}, - {62.10, 204.00}, {71.00, 209.04}, {79.00, 206.55}, {88.00, 206.81}, {95.88, 211.00}, {103.00, 220.49}, - {131.00, 220.51}, {137.00, 222.66}, {143.08, 228.00}, {146.22, 234.00}, {147.08, 241.00}, {145.45, 248.00}, - {142.31, 253.00}, {132.00, 259.30}, {115.00, 259.70}, {109.28, 270.00}, {112.91, 296.00}, {119.69, 324.00}, - {129.00, 336.26}, {141.00, 337.59}, {153.00, 331.57}, {175.00, 325.74}, {188.00, 325.19}, {235.00, 317.46}, - {250.00, 317.19}, {255.00, 309.12}, {262.62, 302.00}, {262.21, 295.00}, {248.00, 273.59}, {229.00, 257.93}, - {221.00, 255.48}, {215.00, 251.59}, {210.79, 246.00}, {207.47, 234.00}, {203.25, 227.00}, {179.00, 205.90}, - {148.00, 189.54}, {136.00, 181.45}, {120.00, 180.31}, {110.00, 181.65}, {95.00, 179.31}, {63.00, 166.96}, - {50.00, 164.23}, {31.00, 154.49}, {19.76, 145.00}, {15.96, 136.00}, {16.65, 127.00}, {20.57, 120.00}, - {28.00, 114.63}, {40.00, 113.67}, {65.00, 127.22}, {73.00, 128.69}, {81.96, 120.00}, {77.58, 103.00}, - {78.18, 92.00}, {59.11, 77.00}, {52.00, 67.29}, {31.29, 55.00}, {25.67, 47.00}, {24.65, 37.00}, - {27.82, 29.00}, {35.00, 22.55}, {44.00, 20.35}, {49.00, 20.81}, {61.00, 25.69}, {79.00, 37.81}, - {88.00, 49.64}, {97.00, 56.65}, {109.00, 49.61}, {143.00, 38.96}, {197.00, 37.27}, {215.00, 35.30}, - {222.00, 36.65}, {228.42, 41.00}, {233.30, 49.00}, {234.14, 57.00}, {231.00, 65.80}, {224.00, 72.38}, - {218.00, 74.50}, {197.00, 76.62}, {145.00, 78.81}, {123.00, 87.41}, {117.59, 98.00}, {117.79, 104.00}, - {119.00, 106.23}, {138.73, 120.00}, {148.00, 129.50}, {158.50, 149.00}, {203.93, 175.00}, {229.00, 196.60}, - {238.16, 208.00}, {245.20, 221.00}, {275.45, 245.00}, {289.00, 263.24}, {303.60, 287.00}, {312.00, 291.57}, - {339.25, 266.00}, {366.33, 226.00}, {363.43, 216.00}, {364.13, 206.00}, {353.00, 196.72}, {324.00, 181.05}, - {307.00, 169.63}, {274.93, 156.00}, {256.00, 152.48}, {228.00, 145.13}, {221.09, 142.00}, {214.87, 135.00}, - {212.67, 127.00}, {213.81, 119.00}, {219.32, 111.00}, {228.00, 106.52}, {236.00, 106.39}, {290.00, 119.40}, - {299.33, 114.00}, {300.52, 109.00}, {300.30, 53.00}, {301.46, 47.00}, {305.00, 41.12}, {311.00, 36.37}, - {317.00, 34.43}, {325.00, 34.81}, {334.90, 41.00}, {339.45, 50.00}, {339.82, 132.00}, {346.09, 139.00}, - {350.00, 150.26}, {380.00, 167.38}, {393.00, 166.48}, {407.00, 155.54}, {430.00, 147.30}, {437.78, 135.00}, - {433.13, 122.00}, {410.23, 78.00}, {401.59, 69.00}, {393.48, 56.00}, {392.80, 44.00}, {395.50, 38.00}, - {401.00, 32.49}, {409.00, 29.41}, {420.00, 30.84}, {426.92, 36.00}, {432.32, 44.00}, {439.49, 51.00}, - {470.13, 108.00}, {475.71, 124.00}, {483.00, 130.11}, {488.00, 139.43}, {529.00, 139.40}, {536.00, 132.52}, - {543.73, 129.00}, {540.47, 115.00}, {541.11, 100.00}, {552.18, 68.00}, {553.78, 47.00}, {559.00, 39.76}, - {567.00, 35.52}, {577.00, 35.45}, {585.00, 39.58}, {591.38, 50.00}, {591.67, 66.00}, {590.31, 79.00}, - {579.76, 109.00}, {582.25, 119.00}, {583.66, 136.00}, {586.45, 143.00}, {586.44, 151.00}, {580.42, 168.00}, - {577.15, 173.00}, {572.00, 177.13}, {564.00, 179.49}, {478.00, 178.81}, {443.00, 184.76}, {427.10, 190.00}, - {424.00, 192.11}, {415.94, 209.00}, {408.82, 228.00}, {405.82, 241.00}, {411.00, 250.82}, {415.00, 251.50}, - {428.00, 248.89}, {469.00, 246.29}, {505.00, 246.49}, {533.00, 243.60}, {541.87, 248.00}, {547.55, 256.00}, - {548.48, 267.00}, {544.00, 276.00}, {534.00, 282.24}, {513.00, 285.46}, {468.00, 285.76}, {402.00, 291.70}, - {392.00, 290.29}, {377.00, 294.46}, {367.00, 294.43}, {356.44, 304.00}, {354.22, 311.00}, {362.00, 321.36}, - {390.00, 322.44}, {433.00, 330.16}, {467.00, 332.76}, {508.00, 347.64}, {522.00, 357.67}, {528.00, 354.46}, - {536.00, 352.96}, {546.06, 336.00}, {553.47, 306.00}, {564.19, 282.00}, {567.84, 268.00}, {578.72, 246.00}, - {585.00, 240.97}, {592.00, 238.91}, {600.00, 239.72}, {606.00, 242.82}, {612.36, 251.00}, {613.35, 263.00}, - {588.75, 324.00}, {583.25, 350.00}, {572.12, 370.00}, {575.45, 378.00}, {575.20, 388.00}, {589.00, 393.81}, - {599.20, 404.00}, {607.14, 416.00}, {609.96, 430.00}, {615.45, 441.00}, {613.44, 462.00}, {610.48, 469.00}, - {603.00, 475.63}, {590.96, 479.00}, -}; -static int complex_terrain_count = sizeof(complex_terrain_verts) / sizeof(cpVect); - -static cpSpace* init_ComplexTerrainCircles_1000(void) -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpVect offset = cpv(-320, -240); - for (int i = 0; i < (complex_terrain_count - 1); i++) - { - cpVect a = complex_terrain_verts[i], b = complex_terrain_verts[i + 1]; - cpSpaceAddShape(space, - cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpvadd(a, offset), cpvadd(b, offset), 0.0f)); - } - - for (int i = 0; i < 1000; i++) - { - cpFloat radius = 5.0f; - cpFloat mass = radius * radius; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpvadd(cpvmult(frand_unit_circle(), 180.0f), cpv(0.0f, 300.0f))); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.0); - } - - return space; -} - -static cpSpace* init_ComplexTerrainHexagons_1000(void) -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpVect offset = cpv(-320, -240); - for (int i = 0; i < (complex_terrain_count - 1); i++) - { - cpVect a = complex_terrain_verts[i], b = complex_terrain_verts[i + 1]; - cpSpaceAddShape(space, - cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpvadd(a, offset), cpvadd(b, offset), 0.0f)); - } - - cpFloat radius = 5.0f; - cpVect hexagon[6]; - for (int i = 0; i < 6; i++) - { - cpFloat angle = -CP_PI * 2.0f * i / 6.0f; - hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel); - } - - for (int i = 0; i < 1000; i++) - { - cpFloat mass = radius * radius; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon, cpvzero, 0.0f))); - cpBodySetPosition(body, cpvadd(cpvmult(frand_unit_circle(), 180.0f), cpv(0.0f, 300.0f))); - - cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 6, hexagon, cpTransformIdentity, bevel)); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.0); - } - - return space; -} - -// BouncyTerrain -static cpVect bouncy_terrain_verts[] = { - {537.18, 23.00}, {520.50, 36.00}, {501.53, 63.00}, {496.14, 76.00}, {498.86, 86.00}, {504.00, 90.51}, - {508.00, 91.36}, {508.77, 84.00}, {513.00, 77.73}, {519.00, 74.48}, {530.00, 74.67}, {545.00, 54.65}, - {554.00, 48.77}, {562.00, 46.39}, {568.00, 45.94}, {568.61, 47.00}, {567.94, 55.00}, {571.27, 64.00}, - {572.92, 80.00}, {572.00, 81.39}, {563.00, 79.93}, {556.00, 82.69}, {551.49, 88.00}, {549.00, 95.76}, - {538.00, 93.40}, {530.00, 102.38}, {523.00, 104.00}, {517.00, 103.02}, {516.22, 109.00}, {518.96, 116.00}, - {526.00, 121.15}, {534.00, 116.48}, {543.00, 116.77}, {549.28, 121.00}, {554.00, 130.17}, {564.00, 125.67}, - {575.60, 129.00}, {573.31, 121.00}, {567.77, 111.00}, {575.00, 106.47}, {578.51, 102.00}, {580.25, 95.00}, - {577.98, 87.00}, {582.00, 85.71}, {597.00, 89.46}, {604.80, 95.00}, {609.28, 104.00}, {610.55, 116.00}, - {609.30, 125.00}, {600.80, 142.00}, {597.31, 155.00}, {584.00, 167.23}, {577.86, 175.00}, {583.52, 184.00}, - {582.64, 195.00}, {591.00, 196.56}, {597.81, 201.00}, {607.45, 219.00}, {607.51, 246.00}, {600.00, 275.46}, - {588.00, 267.81}, {579.00, 264.91}, {557.00, 264.41}, {552.98, 259.00}, {548.00, 246.18}, {558.00, 247.12}, - {565.98, 244.00}, {571.10, 237.00}, {571.61, 229.00}, {568.25, 222.00}, {562.00, 217.67}, {544.00, 213.93}, - {536.73, 214.00}, {535.60, 204.00}, {539.69, 181.00}, {542.84, 171.00}, {550.43, 161.00}, {540.00, 156.27}, - {536.62, 152.00}, {534.70, 146.00}, {527.00, 141.88}, {518.59, 152.00}, {514.51, 160.00}, {510.33, 175.00}, - {519.38, 183.00}, {520.52, 194.00}, {516.00, 201.27}, {505.25, 206.00}, {507.57, 223.00}, {519.90, 260.00}, - {529.00, 260.48}, {534.00, 262.94}, {538.38, 268.00}, {540.00, 275.00}, {537.06, 284.00}, {530.00, 289.23}, - {520.00, 289.23}, {513.00, 284.18}, {509.71, 286.00}, {501.69, 298.00}, {501.56, 305.00}, {504.30, 311.00}, - {512.00, 316.43}, {521.00, 316.42}, {525.67, 314.00}, {535.00, 304.98}, {562.00, 294.80}, {573.00, 294.81}, - {587.52, 304.00}, {600.89, 310.00}, {596.96, 322.00}, {603.28, 327.00}, {606.52, 333.00}, {605.38, 344.00}, - {597.65, 352.00}, {606.36, 375.00}, {607.16, 384.00}, {603.40, 393.00}, {597.00, 398.14}, {577.00, 386.15}, - {564.35, 373.00}, {565.21, 364.00}, {562.81, 350.00}, {553.00, 346.06}, {547.48, 338.00}, {547.48, 330.00}, - {550.00, 323.30}, {544.00, 321.53}, {537.00, 322.70}, {532.00, 326.23}, {528.89, 331.00}, {527.83, 338.00}, - {533.02, 356.00}, {542.00, 360.73}, {546.68, 369.00}, {545.38, 379.00}, {537.58, 386.00}, {537.63, 388.00}, - {555.00, 407.47}, {563.00, 413.52}, {572.57, 418.00}, {582.72, 426.00}, {578.00, 431.12}, {563.21, 440.00}, - {558.00, 449.27}, {549.00, 452.94}, {541.00, 451.38}, {536.73, 448.00}, {533.00, 441.87}, {520.00, 437.96}, - {514.00, 429.69}, {490.00, 415.15}, {472.89, 399.00}, {472.03, 398.00}, {474.00, 396.71}, {486.00, 393.61}, - {492.00, 385.85}, {492.00, 376.15}, {489.04, 371.00}, {485.00, 368.11}, {480.00, 376.27}, {472.00, 379.82}, - {463.00, 378.38}, {455.08, 372.00}, {446.00, 377.69}, {439.00, 385.24}, {436.61, 391.00}, {437.52, 404.00}, - {440.00, 409.53}, {463.53, 433.00}, {473.80, 441.00}, {455.00, 440.30}, {443.00, 436.18}, {436.00, 431.98}, - {412.00, 440.92}, {397.00, 442.46}, {393.59, 431.00}, {393.71, 412.00}, {400.00, 395.10}, {407.32, 387.00}, - {408.54, 380.00}, {407.42, 375.00}, {403.97, 370.00}, {399.00, 366.74}, {393.00, 365.68}, {391.23, 374.00}, - {387.00, 380.27}, {381.00, 383.52}, {371.56, 384.00}, {364.98, 401.00}, {362.96, 412.00}, {363.63, 435.00}, - {345.00, 433.55}, {344.52, 442.00}, {342.06, 447.00}, {337.00, 451.38}, {330.00, 453.00}, {325.00, 452.23}, - {318.00, 448.17}, {298.00, 453.70}, {284.00, 451.49}, {278.62, 449.00}, {291.47, 408.00}, {291.77, 398.00}, - {301.00, 393.83}, {305.00, 393.84}, {305.60, 403.00}, {310.00, 409.47}, {318.00, 413.07}, {325.00, 412.40}, - {332.31, 407.00}, {335.07, 400.00}, {334.40, 393.00}, {329.00, 385.69}, {319.00, 382.79}, {301.00, 389.23}, - {289.00, 389.97}, {265.00, 389.82}, {251.00, 385.85}, {245.00, 389.23}, {239.00, 389.94}, {233.00, 388.38}, - {226.00, 382.04}, {206.00, 374.75}, {206.00, 394.00}, {204.27, 402.00}, {197.00, 401.79}, {191.00, 403.49}, - {186.53, 407.00}, {183.60, 412.00}, {183.60, 422.00}, {189.00, 429.31}, {196.00, 432.07}, {203.00, 431.40}, - {209.47, 427.00}, {213.00, 419.72}, {220.00, 420.21}, {227.00, 418.32}, {242.00, 408.41}, {258.98, 409.00}, - {250.00, 435.43}, {239.00, 438.78}, {223.00, 448.19}, {209.00, 449.70}, {205.28, 456.00}, {199.00, 460.23}, - {190.00, 460.52}, {182.73, 456.00}, {178.00, 446.27}, {160.00, 441.42}, {148.35, 435.00}, {149.79, 418.00}, - {157.72, 401.00}, {161.00, 396.53}, {177.00, 385.00}, {180.14, 380.00}, {181.11, 374.00}, {180.00, 370.52}, - {170.00, 371.68}, {162.72, 368.00}, {158.48, 361.00}, {159.56, 349.00}, {154.00, 342.53}, {146.00, 339.85}, - {136.09, 343.00}, {130.64, 351.00}, {131.74, 362.00}, {140.61, 374.00}, {130.68, 387.00}, {120.75, 409.00}, - {118.09, 421.00}, {117.92, 434.00}, {100.00, 432.40}, {87.00, 427.48}, {81.59, 423.00}, {73.64, 409.00}, - {72.57, 398.00}, {74.62, 386.00}, {78.80, 378.00}, {88.00, 373.43}, {92.49, 367.00}, {93.32, 360.00}, - {91.30, 353.00}, {103.00, 342.67}, {109.00, 343.10}, {116.00, 340.44}, {127.33, 330.00}, {143.00, 327.24}, - {154.30, 322.00}, {145.00, 318.06}, {139.77, 311.00}, {139.48, 302.00}, {144.95, 293.00}, {143.00, 291.56}, - {134.00, 298.21}, {118.00, 300.75}, {109.40, 305.00}, {94.67, 319.00}, {88.00, 318.93}, {81.00, 321.69}, - {67.24, 333.00}, {56.68, 345.00}, {53.00, 351.40}, {47.34, 333.00}, {50.71, 314.00}, {56.57, 302.00}, - {68.00, 287.96}, {91.00, 287.24}, {110.00, 282.36}, {133.80, 271.00}, {147.34, 256.00}, {156.47, 251.00}, - {157.26, 250.00}, {154.18, 242.00}, {154.48, 236.00}, {158.72, 229.00}, {166.71, 224.00}, {170.15, 206.00}, - {170.19, 196.00}, {167.24, 188.00}, {160.00, 182.67}, {150.00, 182.66}, {143.60, 187.00}, {139.96, 195.00}, - {139.50, 207.00}, {136.45, 221.00}, {136.52, 232.00}, {133.28, 238.00}, {129.00, 241.38}, {119.00, 243.07}, - {115.00, 246.55}, {101.00, 253.16}, {86.00, 257.32}, {63.00, 259.24}, {57.00, 257.31}, {50.54, 252.00}, - {47.59, 247.00}, {46.30, 240.00}, {47.58, 226.00}, {50.00, 220.57}, {58.00, 226.41}, {69.00, 229.17}, - {79.00, 229.08}, {94.50, 225.00}, {100.21, 231.00}, {107.00, 233.47}, {107.48, 224.00}, {109.94, 219.00}, - {115.00, 214.62}, {122.57, 212.00}, {116.00, 201.49}, {104.00, 194.57}, {90.00, 194.04}, {79.00, 198.21}, - {73.00, 198.87}, {62.68, 191.00}, {62.58, 184.00}, {64.42, 179.00}, {75.00, 167.70}, {80.39, 157.00}, - {68.79, 140.00}, {61.67, 126.00}, {61.47, 117.00}, {64.43, 109.00}, {63.10, 96.00}, {56.48, 82.00}, - {48.00, 73.88}, {43.81, 66.00}, {43.81, 56.00}, {50.11, 46.00}, {59.00, 41.55}, {71.00, 42.64}, - {78.00, 36.77}, {83.00, 34.75}, {99.00, 34.32}, {117.00, 38.92}, {133.00, 55.15}, {142.00, 50.70}, - {149.74, 51.00}, {143.55, 68.00}, {153.28, 74.00}, {156.23, 79.00}, {157.00, 84.00}, {156.23, 89.00}, - {153.28, 94.00}, {144.58, 99.00}, {151.52, 112.00}, {151.51, 124.00}, {150.00, 126.36}, {133.00, 130.25}, - {126.71, 125.00}, {122.00, 117.25}, {114.00, 116.23}, {107.73, 112.00}, {104.48, 106.00}, {104.32, 99.00}, - {106.94, 93.00}, {111.24, 89.00}, {111.60, 85.00}, {107.24, 73.00}, {102.00, 67.57}, {99.79, 67.00}, - {99.23, 76.00}, {95.00, 82.27}, {89.00, 85.52}, {79.84, 86.00}, {86.73, 114.00}, {98.00, 136.73}, - {99.00, 137.61}, {109.00, 135.06}, {117.00, 137.94}, {122.52, 146.00}, {122.94, 151.00}, {121.00, 158.58}, - {134.00, 160.97}, {153.00, 157.45}, {171.30, 150.00}, {169.06, 142.00}, {169.77, 136.00}, {174.00, 129.73}, - {181.46, 126.00}, {182.22, 120.00}, {182.20, 111.00}, {180.06, 101.00}, {171.28, 85.00}, {171.75, 80.00}, - {182.30, 53.00}, {189.47, 50.00}, {190.62, 38.00}, {194.00, 33.73}, {199.00, 30.77}, {208.00, 30.48}, - {216.00, 34.94}, {224.00, 31.47}, {240.00, 30.37}, {247.00, 32.51}, {249.77, 35.00}, {234.75, 53.00}, - {213.81, 93.00}, {212.08, 99.00}, {213.00, 101.77}, {220.00, 96.77}, {229.00, 96.48}, {236.28, 101.00}, - {240.00, 107.96}, {245.08, 101.00}, {263.00, 65.32}, {277.47, 48.00}, {284.00, 47.03}, {286.94, 41.00}, - {292.00, 36.62}, {298.00, 35.06}, {304.00, 35.77}, {314.00, 43.81}, {342.00, 32.56}, {359.00, 31.32}, - {365.00, 32.57}, {371.00, 36.38}, {379.53, 48.00}, {379.70, 51.00}, {356.00, 52.19}, {347.00, 54.74}, - {344.38, 66.00}, {341.00, 70.27}, {335.00, 73.52}, {324.00, 72.38}, {317.00, 65.75}, {313.00, 67.79}, - {307.57, 76.00}, {315.00, 78.62}, {319.28, 82.00}, {322.23, 87.00}, {323.00, 94.41}, {334.00, 92.49}, - {347.00, 87.47}, {349.62, 80.00}, {353.00, 75.73}, {359.00, 72.48}, {366.00, 72.32}, {372.00, 74.94}, - {377.00, 81.34}, {382.00, 83.41}, {392.00, 83.40}, {399.00, 79.15}, {404.00, 85.74}, {411.00, 85.06}, - {417.00, 86.62}, {423.38, 93.00}, {425.05, 104.00}, {438.00, 110.35}, {450.00, 112.17}, {452.62, 103.00}, - {456.00, 98.73}, {462.00, 95.48}, {472.00, 95.79}, {471.28, 92.00}, {464.00, 84.62}, {445.00, 80.39}, - {436.00, 75.33}, {428.00, 68.46}, {419.00, 68.52}, {413.00, 65.27}, {408.48, 58.00}, {409.87, 46.00}, - {404.42, 39.00}, {408.00, 33.88}, {415.00, 29.31}, {429.00, 26.45}, {455.00, 28.77}, {470.00, 33.81}, - {482.00, 42.16}, {494.00, 46.85}, {499.65, 36.00}, {513.00, 25.95}, {529.00, 22.42}, {537.18, 23.00}, -}; -static int bouncy_terrain_count = sizeof(bouncy_terrain_verts) / sizeof(cpVect); - -static cpSpace* init_BouncyTerrainCircles_500(void) -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - - cpVect offset = cpv(-320, -240); - for (int i = 0; i < (bouncy_terrain_count - 1); i++) - { - cpVect a = bouncy_terrain_verts[i], b = bouncy_terrain_verts[i + 1]; - cpShape* shape = cpSpaceAddShape( - space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpvadd(a, offset), cpvadd(b, offset), 0.0f)); - cpShapeSetElasticity(shape, 1.0); - } - - for (int i = 0; i < 500; i++) - { - cpFloat radius = 5.0f; - cpFloat mass = radius * radius; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpvadd(cpvmult(frand_unit_circle(), 130.0f), cpvzero)); - cpBodySetVelocity(body, cpvmult(frand_unit_circle(), 50.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 1.0); - } - - return space; -} - -static cpSpace* init_BouncyTerrainHexagons_500(void) -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - - cpVect offset = cpv(-320, -240); - for (int i = 0; i < (bouncy_terrain_count - 1); i++) - { - cpVect a = bouncy_terrain_verts[i], b = bouncy_terrain_verts[i + 1]; - cpShape* shape = cpSpaceAddShape( - space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpvadd(a, offset), cpvadd(b, offset), 0.0f)); - cpShapeSetElasticity(shape, 1.0); - } - - cpFloat radius = 5.0f; - cpVect hexagon[6]; - for (int i = 0; i < 6; i++) - { - cpFloat angle = -CP_PI * 2.0f * i / 6.0f; - hexagon[i] = cpvmult(cpv(cos(angle), sin(angle)), radius - bevel); - } - - for (int i = 0; i < 500; i++) - { - cpFloat mass = radius * radius; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 6, hexagon, cpvzero, 0.0f))); - cpBodySetPosition(body, cpvadd(cpvmult(frand_unit_circle(), 130.0f), cpvzero)); - cpBodySetVelocity(body, cpvmult(frand_unit_circle(), 50.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 6, hexagon, cpTransformIdentity, bevel)); - cpShapeSetElasticity(shape, 1.0); - } - - return space; -} - -// No collisions - -static cpFloat pentagon_mass = 0.0f; -static cpFloat pentagon_moment = 0.0f; - -static cpBool NoCollide_begin(cpArbiter* arb, cpSpace* space, void* data) -{ - - // AXLOGD("NoCollide_begin"); - - return cpTrue; -} - -static cpSpace* init_NoCollide(void) -{ - cpSpace* space = BENCH_SPACE_NEW(); - cpSpaceSetIterations(space, 10); - - cpCollisionHandler* handler = cpSpaceAddCollisionHandler(space, 2, 2); - handler->beginFunc = NoCollide_begin; - - float radius = 4.5f; - - cpShapeSetElasticity( - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(-330 - radius, -250 - radius), - cpv(330 + radius, -250 - radius), 0.0f)), - 1.0f); - cpShapeSetElasticity( - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(330 + radius, 250 + radius), - cpv(330 + radius, -250 - radius), 0.0f)), - 1.0f); - cpShapeSetElasticity( - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(330 + radius, 250 + radius), - cpv(-330 - radius, 250 + radius), 0.0f)), - 1.0f); - cpShapeSetElasticity( - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(-330 - radius, -250 - radius), - cpv(-330 - radius, 250 + radius), 0.0f)), - 1.0f); - - for (int x = -320; x <= 320; x += 20) - { - for (int y = -240; y <= 240; y += 20) - { - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(cpSpaceGetStaticBody(space), radius, cpv(x, y))); - cpShapeSetElasticity(shape, 1.0); - cpShapeSetCollisionType(shape, 2); - } - } - - for (int y = 10 - 240; y <= 240; y += 40) - { - cpFloat mass = 7.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(-320.0f, y)); - cpBodySetVelocity(body, cpv(100.0f, 0.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 1.0); - cpShapeSetCollisionType(shape, 2); - } - - for (int x = 30 - 320; x <= 320; x += 40) - { - cpFloat mass = 7.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(x, -240.0f)); - cpBodySetVelocity(body, cpv(0.0f, 100.0f)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 1.0); - cpShapeSetCollisionType(shape, 2); - } - - return space; -} - -// TODO ideas: -// addition/removal -// Memory usage? (too small to matter?) -// http://forums.tigsource.com/index.php?topic=18077.msg518578#msg518578 - -// Build benchmark list -static void update(cpSpace* space, double dt) -{ - BENCH_SPACE_STEP(space, dt); -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - BENCH_SPACE_FREE(space); -} - -// Make a second demo declaration for this demo to use in the regular demo set. -ChipmunkDemo BouncyHexagons = { - "Bouncy Hexagons", 1.0 / 60.0, init_BouncyTerrainHexagons_500, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; - -#define BENCH(n) \ - { \ -# n, 1.0 / 60.0, init_##n, update, ChipmunkDemoDefaultDrawImpl, destroy \ - } -ChipmunkDemo bench_list[] = { - BENCH(SimpleTerrainCircles_1000), - BENCH(SimpleTerrainCircles_500), - BENCH(SimpleTerrainCircles_100), - BENCH(SimpleTerrainBoxes_1000), - BENCH(SimpleTerrainBoxes_500), - BENCH(SimpleTerrainBoxes_100), - BENCH(SimpleTerrainHexagons_1000), - BENCH(SimpleTerrainHexagons_500), - BENCH(SimpleTerrainHexagons_100), - BENCH(SimpleTerrainVCircles_200), - BENCH(SimpleTerrainVBoxes_200), - BENCH(SimpleTerrainVHexagons_200), - BENCH(ComplexTerrainCircles_1000), - BENCH(ComplexTerrainHexagons_1000), - BENCH(BouncyTerrainCircles_500), - BENCH(BouncyTerrainHexagons_500), - BENCH(NoCollide), -}; - -int bench_count = sizeof(bench_list) / sizeof(ChipmunkDemo); diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Buoyancy.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Buoyancy.cpp deleted file mode 100644 index 05224adbf800..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Buoyancy.cpp +++ /dev/null @@ -1,220 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" - -#include "ChipmunkDemo.h" - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -#define FLUID_DENSITY 0.00014 -#define FLUID_DRAG 2.0 - -char messageBuffer[1024]; - -// Modified from chipmunk_private.h -static inline cpFloat k_scalar_body(cpBody* body, cpVect point, cpVect n) -{ - cpFloat rcn = cpvcross(cpvsub(point, cpBodyGetPosition(body)), n); - return 1.0f / cpBodyGetMass(body) + rcn * rcn / cpBodyGetMoment(body); -} - -static cpBool waterPreSolve(cpArbiter* arb, cpSpace* space, void* ptr) -{ - CP_ARBITER_GET_SHAPES(arb, water, poly); - cpBody* body = cpShapeGetBody(poly); - - // Get the top of the water sensor bounding box to use as the water level. - cpFloat level = cpShapeGetBB(water).t; - - // Clip the polygon against the water level - int count = cpPolyShapeGetCount(poly); - int clippedCount = 0; -#ifdef _MSC_VER - // MSVC is pretty much the only compiler in existence that doesn't support variable sized arrays. - cpVect clipped[10]; -#else - cpVect clipped[count + 1]; -#endif - - for (int i = 0, j = count - 1; i < count; j = i, i++) - { - cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, j)); - cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(poly, i)); - - if (a.y < level) - { - clipped[clippedCount] = a; - clippedCount++; - } - - cpFloat a_level = a.y - level; - cpFloat b_level = b.y - level; - - if (a_level * b_level < 0.0f) - { - cpFloat t = cpfabs(a_level) / (cpfabs(a_level) + cpfabs(b_level)); - - clipped[clippedCount] = cpvlerp(a, b, t); - clippedCount++; - } - } - - // Calculate buoyancy from the clipped polygon area - cpFloat clippedArea = cpAreaForPoly(clippedCount, clipped, 0.0f); - cpFloat displacedMass = clippedArea * FLUID_DENSITY; - cpVect centroid = cpCentroidForPoly(clippedCount, clipped); - - ChipmunkDebugDrawPolygon(clippedCount, clipped, 5.0f, RGBAColor(0, 0, 1, 1), RGBAColor(0, 0, 1, 0.1f)); - ChipmunkDebugDrawDot(5, centroid, RGBAColor(0, 0, 1, 1)); - - cpFloat dt = cpSpaceGetCurrentTimeStep(space); - cpVect g = cpSpaceGetGravity(space); - - // Apply the buoyancy force as an impulse. - cpBodyApplyImpulseAtWorldPoint(body, cpvmult(g, -displacedMass * dt), centroid); - - // Apply linear damping for the fluid drag. - cpVect v_centroid = cpBodyGetVelocityAtWorldPoint(body, centroid); - cpFloat k = k_scalar_body(body, centroid, cpvnormalize(v_centroid)); - cpFloat damping = clippedArea * FLUID_DRAG * FLUID_DENSITY; - cpFloat v_coef = cpfexp(-damping * dt * k); // linear drag - // cpFloat v_coef = 1.0/(1.0 + damping*dt*cpvlength(v_centroid)*k); // quadratic drag - cpBodyApplyImpulseAtWorldPoint(body, cpvmult(cpvsub(cpvmult(v_centroid, v_coef), v_centroid), 1.0 / k), centroid); - - // Apply angular damping for the fluid drag. - cpVect cog = cpBodyLocalToWorld(body, cpBodyGetCenterOfGravity(body)); - cpFloat w_damping = - cpMomentForPoly(FLUID_DRAG * FLUID_DENSITY * clippedArea, clippedCount, clipped, cpvneg(cog), 0.0f); - cpBodySetAngularVelocity(body, cpBodyGetAngularVelocity(body) * cpfexp(-w_damping * dt / cpBodyGetMoment(body))); - - return cpTrue; -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = messageBuffer; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -500)); - // cpSpaceSetDamping(space, 0.5); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - { - // Add the edges of the bucket - cpBB bb = cpBBNew(-300, -200, 100, 0); - cpFloat radius = 5.0f; - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.l, bb.b), cpv(bb.l, bb.t), radius)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.r, bb.b), cpv(bb.r, bb.t), radius)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(bb.l, bb.b), cpv(bb.r, bb.b), radius)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Add the sensor for the water. - shape = cpSpaceAddShape(space, cpBoxShapeNew2(staticBody, bb, 0.0)); - cpShapeSetSensor(shape, cpTrue); - cpShapeSetCollisionType(shape, 1); - } - - { - cpFloat width = 200.0f; - cpFloat height = 50.0f; - cpFloat mass = 0.3 * FLUID_DENSITY * width * height; - cpFloat moment = cpMomentForBox(mass, width, height); - - body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(body, cpv(-50, -100)); - cpBodySetVelocity(body, cpv(0, -100)); - cpBodySetAngularVelocity(body, 1); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetFriction(shape, 0.8f); - } - - { - cpFloat width = 40.0f; - cpFloat height = width * 2; - cpFloat mass = 0.3 * FLUID_DENSITY * width * height; - cpFloat moment = cpMomentForBox(mass, width, height); - - body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(body, cpv(-200, -50)); - cpBodySetVelocity(body, cpv(0, -100)); - cpBodySetAngularVelocity(body, 1); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetFriction(shape, 0.8f); - } - - cpCollisionHandler* handler = cpSpaceAddCollisionHandler(space, 1, 0); - handler->preSolveFunc = (cpCollisionPreSolveFunc)waterPreSolve; - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Buoyancy = { - "Simple Sensor based fluids.", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Chains.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Chains.cpp deleted file mode 100644 index 41cbf8cd2a11..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Chains.cpp +++ /dev/null @@ -1,149 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -#define CHAIN_COUNT 8 -#define LINK_COUNT 10 - -static void BreakablejointPostStepRemove(cpSpace* space, cpConstraint* joint, void* unused) -{ - cpSpaceRemoveConstraint(space, joint); - cpConstraintFree(joint); -} - -static void BreakableJointPostSolve(cpConstraint* joint, cpSpace* space) -{ - cpFloat dt = cpSpaceGetCurrentTimeStep(space); - - // Convert the impulse to a force by dividing it by the timestep. - cpFloat force = cpConstraintGetImpulse(joint) / dt; - cpFloat maxForce = cpConstraintGetMaxForce(joint); - - // If the force is almost as big as the joint's max force, break it. - if (force > 0.9 * maxForce) - { - cpSpaceAddPostStepCallback(space, (cpPostStepFunc)BreakablejointPostStepRemove, joint, NULL); - } -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat mass = 1; - cpFloat width = 20; - cpFloat height = 30; - - cpFloat spacing = width * 0.3; - - // Add lots of boxes. - for (int i = 0; i < CHAIN_COUNT; i++) - { - cpBody* prev = NULL; - - for (int j = 0; j < LINK_COUNT; j++) - { - cpVect pos = cpv(40 * (i - (CHAIN_COUNT - 1) / 2.0), 240 - (j + 0.5) * height - (j + 1) * spacing); - - body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); - cpBodySetPosition(body, pos); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpv(0, (height - width) / 2.0), - cpv(0, (width - height) / 2.0), width / 2.0)); - cpShapeSetFriction(shape, 0.8f); - - cpFloat breakingForce = 80000; - - cpConstraint* constraint = NULL; - if (prev == NULL) - { - constraint = cpSpaceAddConstraint( - space, cpSlideJointNew(body, staticBody, cpv(0, height / 2), cpv(pos.x, 240), 0, spacing)); - } - else - { - constraint = cpSpaceAddConstraint( - space, cpSlideJointNew(body, prev, cpv(0, height / 2), cpv(0, -height / 2), 0, spacing)); - } - - cpConstraintSetMaxForce(constraint, breakingForce); - cpConstraintSetPostSolveFunc(constraint, BreakableJointPostSolve); - cpConstraintSetCollideBodies(constraint, cpFalse); - - prev = body; - } - } - - cpFloat radius = 15.0f; - body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(0, -240 + radius + 5)); - cpBodySetVelocity(body, cpv(0, 300)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.9f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Chains = { - "Breakable Chains", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h b/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h deleted file mode 100644 index 65c2cbaaac8c..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h +++ /dev/null @@ -1,104 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -typedef struct ChipmunkDemo ChipmunkDemo; - -typedef cpSpace* (*ChipmunkDemoInitFunc)(void); -typedef void (*ChipmunkDemoUpdateFunc)(cpSpace* space, double dt); -typedef void (*ChipmunkDemoDrawFunc)(cpSpace* space); -typedef void (*ChipmunkDemoDestroyFunc)(cpSpace* space); - -struct ChipmunkDemo -{ - const char* name; - double timestep; - - ChipmunkDemoInitFunc initFunc; - ChipmunkDemoUpdateFunc updateFunc; - ChipmunkDemoDrawFunc drawFunc; - - ChipmunkDemoDestroyFunc destroyFunc; -}; - -static inline cpFloat frand(void) -{ - return (cpFloat)rand() / (cpFloat)RAND_MAX; -} - -static inline cpVect frand_unit_circle() -{ - cpVect v = cpv(frand() * 2.0f - 1.0f, frand() * 2.0f - 1.0f); - return (cpvlengthsq(v) < 1.0f ? v : frand_unit_circle()); -} - -typedef struct -{ - float x, y; -} float2; -typedef struct -{ - uint8_t r, g, b, a; -} RGBA8; -typedef struct -{ - float2 pos; - float2 uv; - float r; - RGBA8 fill, outline; -} Vertex; -typedef uint16_t Index; - -extern int ChipmunkDemoTicks; -extern double ChipmunkDemoTime; -extern cpVect ChipmunkDemoKeyboard; -extern cpVect ChipmunkDemoMouse; -extern cpBool ChipmunkDemoRightClick; -extern cpBool ChipmunkDemoRightDown; -extern float ChipmunkDebugDrawPointLineScale; - -extern char const* ChipmunkDemoMessageString; -extern void ChipmunkDemoPrintString(char const* fmt, ...); - -extern cpShapeFilter GRAB_FILTER; -extern cpShapeFilter NOT_GRABBABLE_FILTER; - -void ChipmunkDemoDefaultDrawImpl(cpSpace* space); -void ChipmunkDemoFreeSpaceChildren(cpSpace* space); -void ChipmunkDebugDrawCircle(cpVect pos, - cpFloat angle, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor); -void ChipmunkDebugDrawSegment(cpVect a, cpVect b, cpSpaceDebugColor color); -void ChipmunkDebugDrawFatSegment(cpVect a, - cpVect b, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor); -void ChipmunkDebugDrawPolygon(int count, - const cpVect* verts, - cpFloat radius, - cpSpaceDebugColor outlineColor, - cpSpaceDebugColor fillColor); -void ChipmunkDebugDrawDot(cpFloat size, cpVect pos, cpSpaceDebugColor fillColor); -void ChipmunkDebugDrawBB(cpBB bb, cpSpaceDebugColor outlineColor); -cpSpaceDebugColor LAColor(float l, float a); -cpSpaceDebugColor RGBAColor(float r, float g, float b, float a); \ No newline at end of file diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h_org b/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h_org deleted file mode 100644 index 7e3d3b33c148..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ChipmunkDemo.h_org +++ /dev/null @@ -1,68 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "ChipmunkDebugDraw.h" - -typedef struct ChipmunkDemo ChipmunkDemo; - -typedef cpSpace *(*ChipmunkDemoInitFunc)(void); -typedef void (*ChipmunkDemoUpdateFunc)(cpSpace *space, double dt); -typedef void (*ChipmunkDemoDrawFunc)(cpSpace *space); -typedef void (*ChipmunkDemoDestroyFunc)(cpSpace *space); - -struct ChipmunkDemo { - const char *name; - double timestep; - - ChipmunkDemoInitFunc initFunc; - ChipmunkDemoUpdateFunc updateFunc; - ChipmunkDemoDrawFunc drawFunc; - - ChipmunkDemoDestroyFunc destroyFunc; -}; - -static inline cpFloat -frand(void) -{ - return (cpFloat)rand()/(cpFloat)RAND_MAX; -} - -static inline cpVect -frand_unit_circle(){ - cpVect v = cpv(frand()*2.0f - 1.0f, frand()*2.0f - 1.0f); - return (cpvlengthsq(v) < 1.0f ? v : frand_unit_circle()); -} - -extern int ChipmunkDemoTicks; -extern double ChipmunkDemoTime; -extern cpVect ChipmunkDemoKeyboard; -extern cpVect ChipmunkDemoMouse; -extern cpBool ChipmunkDemoRightClick; -extern cpBool ChipmunkDemoRightDown; - -extern char const *ChipmunkDemoMessageString; -void ChipmunkDemoPrintString(char const *fmt, ...); - -extern cpShapeFilter GRAB_FILTER; -extern cpShapeFilter NOT_GRABBABLE_FILTER; - -void ChipmunkDemoDefaultDrawImpl(cpSpace *space); -void ChipmunkDemoFreeSpaceChildren(cpSpace *space); diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ContactGraph.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/ContactGraph.cpp deleted file mode 100644 index ce6d1a29ed96..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/ContactGraph.cpp +++ /dev/null @@ -1,211 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -// static body that we will be making into a scale -static cpBody* scaleStaticBody; -static cpBody* ballBody; - -// If your compiler supports blocks (Clang or some GCC versions), -// You can use the block based iterators instead of the function ones to make your life easier. -#if defined(__has_extension) -# if __has_extension(blocks) - -# define USE_BLOCKS 1 - -# endif -#endif - -#if !USE_BLOCKS - -static void ScaleIterator(cpBody* body, cpArbiter* arb, cpVect* sum) -{ - (*sum) = cpvadd(*sum, cpArbiterTotalImpulse(arb)); -} - -static void BallIterator(cpBody* body, cpArbiter* arb, int* count) -{ - // body is the body we are iterating the arbiters for. - // CP_ARBITER_GET_*() in an arbiter iterator always returns the body/shape for the iterated body first. - CP_ARBITER_GET_SHAPES(arb, ball, other); - ChipmunkDebugDrawBB(cpShapeGetBB(other), RGBAColor(1, 0, 0, 1)); - - (*count)++; -} - -struct CrushingContext -{ - cpFloat magnitudeSum; - cpVect vectorSum; -}; - -static void EstimateCrushing(cpBody* body, cpArbiter* arb, struct CrushingContext* context) -{ - cpVect j = cpArbiterTotalImpulse(arb); - context->magnitudeSum += cpvlength(j); - context->vectorSum = cpvadd(context->vectorSum, j); -} - -#endif - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); - - ChipmunkDemoPrintString("Place objects on the scale to weigh them. The ball marks the shapes it's sitting on.\n"); - -// Sum the total impulse applied to the scale from all collision pairs in the contact graph. -// If your compiler supports blocks, your life is a little easier. -// You can use the "Block" versions of the functions without needing the callbacks above. -#if USE_BLOCKS - __block cpVect impulseSum = cpvzero; - cpBodyEachArbiter_b(scaleStaticBody, ^(cpArbiter* arb) { - impulseSum = cpvadd(impulseSum, cpArbiterTotalImpulse(arb)); - }); -#else - cpVect impulseSum = cpvzero; - cpBodyEachArbiter(scaleStaticBody, (cpBodyArbiterIteratorFunc)ScaleIterator, &impulseSum); -#endif - - // Force is the impulse divided by the timestep. - cpFloat force = cpvlength(impulseSum) / dt; - - // Weight can be found similarly from the gravity vector. - cpVect g = cpSpaceGetGravity(space); - cpFloat weight = cpvdot(g, impulseSum) / (cpvlengthsq(g) * dt); - - ChipmunkDemoPrintString("Total force: %5.2f, Total weight: %5.2f. ", force, weight); - -// Highlight and count the number of shapes the ball is touching. -#if USE_BLOCKS - __block int count = 0; - cpBodyEachArbiter_b(ballBody, ^(cpArbiter* arb) { - // body is the body we are iterating the arbiters for. - // CP_ARBITER_GET_*() in an arbiter iterator always returns the body/shape for the iterated body first. - CP_ARBITER_GET_SHAPES(arb, ball, other); - ChipmunkDebugDrawBB(cpShapeGetBB(other), RGBAColor(1, 0, 0, 1)); - - count++; - }); -#else - int count = 0; - cpBodyEachArbiter(ballBody, (cpBodyArbiterIteratorFunc)BallIterator, &count); -#endif - - ChipmunkDemoPrintString("The ball is touching %d shapes.\n", count); - -#if USE_BLOCKS - __block cpFloat magnitudeSum = 0.0f; - __block cpVect vectorSum = cpvzero; - cpBodyEachArbiter_b(ballBody, ^(cpArbiter* arb) { - cpVect j = cpArbiterTotalImpulse(arb); - magnitudeSum += cpvlength(j); - vectorSum = cpvadd(vectorSum, j); - }); - - cpFloat crushForce = (magnitudeSum - cpvlength(vectorSum)) * dt; -#else - struct CrushingContext crush = {0.0f, cpvzero}; - cpBodyEachArbiter(ballBody, (cpBodyArbiterIteratorFunc)EstimateCrushing, &crush); - - cpFloat crushForce = (crush.magnitudeSum - cpvlength(crush.vectorSum)) * dt; -#endif - - if (crushForce > 10.0f) - { - ChipmunkDemoPrintString("The ball is being crushed. (f: %.2f)", crushForce); - } - else - { - ChipmunkDemoPrintString("The ball is not being crushed. (f: %.2f)", crushForce); - } -} - -#define WIDTH 4.0f -#define HEIGHT 30.0f - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -300)); - cpSpaceSetCollisionSlop(space, 0.5); - cpSpaceSetSleepTimeThreshold(space, 1.0f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - scaleStaticBody = cpSpaceAddBody(space, cpBodyNewStatic()); - shape = cpSpaceAddShape(space, cpSegmentShapeNew(scaleStaticBody, cpv(-240, -180), cpv(-140, -180), 4.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // add some boxes to stack on the scale - for (int i = 0; i < 5; i++) - { - body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForBox(1.0f, 30.0f, 30.0f))); - cpBodySetPosition(body, cpv(0, i * 32 - 120)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, 30.0f, 30.0f, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.8f); - } - - // Add a ball that we'll track which objects are beneath it. - cpFloat radius = 15.0f; - ballBody = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); - cpBodySetPosition(ballBody, cpv(120, -140 + radius + 5)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(ballBody, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.9f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo ContactGraph = { - "Contact Graph", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Convex.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Convex.cpp deleted file mode 100644 index b4e457f26be3..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Convex.cpp +++ /dev/null @@ -1,110 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "chipmunk/chipmunk_unsafe.h" - -#include "ChipmunkDemo.h" - -#define DENSITY (1.0 / 10000.0) - -static cpShape* shape; - -static void update(cpSpace* space, double dt) -{ - cpFloat tolerance = 2.0; - - if (ChipmunkDemoRightClick && cpShapePointQuery(shape, ChipmunkDemoMouse, NULL) > tolerance) - { - cpBody* body = cpShapeGetBody(shape); - int count = cpPolyShapeGetCount(shape); - - // Allocate the space for the new vertexes on the stack. - cpVect* verts = (cpVect*)alloca((count + 1) * sizeof(cpVect)); - - for (int i = 0; i < count; i++) - { - verts[i] = cpPolyShapeGetVert(shape, i); - } - - verts[count] = cpBodyWorldToLocal(body, ChipmunkDemoMouse); - - // This function builds a convex hull for the vertexes. - // Because the result array is the same as verts, it will reduce it in place. - int hullCount = cpConvexHull(count + 1, verts, verts, NULL, tolerance); - - // Figure out how much to shift the body by. - cpVect centroid = cpCentroidForPoly(hullCount, verts); - - // Recalculate the body properties to match the updated shape. - cpFloat mass = cpAreaForPoly(hullCount, verts, 0.0f) * DENSITY; - cpBodySetMass(body, mass); - cpBodySetMoment(body, cpMomentForPoly(mass, hullCount, verts, cpvneg(centroid), 0.0f)); - cpBodySetPosition(body, cpBodyLocalToWorld(body, centroid)); - - // Use the setter function from chipmunk_unsafe.h. - // You could also remove and recreate the shape if you wanted. - cpPolyShapeSetVerts(shape, hullCount, verts, cpTransformTranslate(cpvneg(centroid))); - } - - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Right click and drag to change the blocks's shape."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -500)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat width = 50.0f; - cpFloat height = 70.0f; - cpFloat mass = width * height * DENSITY; - cpFloat moment = cpMomentForBox(mass, width, height); - - body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetFriction(shape, 0.6f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Convex = { - "Convex.", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Crane.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Crane.cpp deleted file mode 100644 index 7d0cfe9e021d..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Crane.cpp +++ /dev/null @@ -1,160 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody* dollyBody = NULL; -// Constraint used as a servo motor to move the dolly back and forth. -static cpConstraint* dollyServo = NULL; - -// Constraint used as a winch motor to lift the load. -static cpConstraint* winchServo = NULL; - -// Temporary joint used to hold the hook to the load. -static cpConstraint* hookJoint = NULL; - -static void update(cpSpace* space, double dt) -{ - // Set the first anchor point (the one attached to the static body) of the dolly servo to the mouse's x position. - cpPivotJointSetAnchorA(dollyServo, cpv(ChipmunkDemoMouse.x, 100)); - - // Set the max length of the winch servo to match the mouse's height. - cpSlideJointSetMax(winchServo, cpfmax(100 - ChipmunkDemoMouse.y, 50)); - - if (hookJoint && ChipmunkDemoRightClick) - { - cpSpaceRemoveConstraint(space, hookJoint); - cpConstraintFree(hookJoint); - hookJoint = NULL; - } - - cpSpaceStep(space, dt); -} - -enum COLLISION_TYPES -{ - HOOK_SENSOR = 1, - CRATE, -}; - -static void AttachHook(cpSpace* space, cpBody* hook, cpBody* crate) -{ - hookJoint = cpSpaceAddConstraint(space, cpPivotJointNew(hook, crate, cpBodyGetPosition(hook))); -} - -static cpBool HookCrate(cpArbiter* arb, cpSpace* space, void* data) -{ - if (hookJoint == NULL) - { - // Get pointers to the two bodies in the collision pair and define local variables for them. - // Their order matches the order of the collision types passed - // to the collision handler this function was defined for - CP_ARBITER_GET_BODIES(arb, hook, crate); - - // additions and removals can't be done in a normal callback. - // Schedule a post step callback to do it. - // Use the hook as the key and pass along the arbiter. - cpSpaceAddPostStepCallback(space, (cpPostStepFunc)AttachHook, hook, crate); - } - - return cpTrue; // return value is ignored for sensor callbacks anyway -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Control the crane by moving the mouse. Right click to release."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetDamping(space, 0.8); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Add a body for the dolly. - dollyBody = cpSpaceAddBody(space, cpBodyNew(10, INFINITY)); - cpBodySetPosition(dollyBody, cpv(0, 100)); - - // Add a block so you can see it. - cpSpaceAddShape(space, cpBoxShapeNew(dollyBody, 30, 30, 0.0)); - - // Add a groove joint for it to move back and forth on. - cpSpaceAddConstraint(space, cpGrooveJointNew(staticBody, dollyBody, cpv(-250, 100), cpv(250, 100), cpvzero)); - - // Add a pivot joint to act as a servo motor controlling it's position - // By updating the anchor points of the pivot joint, you can move the dolly. - dollyServo = cpSpaceAddConstraint(space, cpPivotJointNew(staticBody, dollyBody, cpBodyGetPosition(dollyBody))); - // Max force the dolly servo can generate. - cpConstraintSetMaxForce(dollyServo, 10000); - // Max speed of the dolly servo - cpConstraintSetMaxBias(dollyServo, 100); - // You can also change the error bias to control how it slows down. - // cpConstraintSetErrorBias(dollyServo, 0.2); - - // Add the crane hook. - cpBody* hookBody = cpSpaceAddBody(space, cpBodyNew(1, INFINITY)); - cpBodySetPosition(hookBody, cpv(0, 50)); - - // Add a sensor shape for it. This will be used to figure out when the hook touches a box. - shape = cpSpaceAddShape(space, cpCircleShapeNew(hookBody, 10, cpvzero)); - cpShapeSetSensor(shape, cpTrue); - cpShapeSetCollisionType(shape, HOOK_SENSOR); - - // Add a slide joint to act as a winch motor - // By updating the max length of the joint you can make it pull up the load. - winchServo = cpSpaceAddConstraint(space, cpSlideJointNew(dollyBody, hookBody, cpvzero, cpvzero, 0, INFINITY)); - // Max force the dolly servo can generate. - cpConstraintSetMaxForce(winchServo, 30000); - // Max speed of the dolly servo - cpConstraintSetMaxBias(winchServo, 60); - - // TODO: cleanup - // Finally a box to play with - cpBody* boxBody = cpSpaceAddBody(space, cpBodyNew(30, cpMomentForBox(30, 50, 50))); - cpBodySetPosition(boxBody, cpv(200, -200)); - - // Add a block so you can see it. - shape = cpSpaceAddShape(space, cpBoxShapeNew(boxBody, 50, 50, 0.0)); - cpShapeSetFriction(shape, 0.7); - cpShapeSetCollisionType(shape, CRATE); - - cpCollisionHandler* handler = cpSpaceAddCollisionHandler(space, HOOK_SENSOR, CRATE); - handler->beginFunc = (cpCollisionBeginFunc)HookCrate; - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Crane = { - "Crane", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Example.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Example.cpp deleted file mode 100644 index 43eb6ac0f988..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Example.cpp +++ /dev/null @@ -1,130 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * Copyright (c) 2021 @aismann; Peter Eismann, Germany; dreifrankensoft - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ -#include -#include -#if !defined(_USE_MATH_DEFINES) -# define _USE_MATH_DEFINES -#endif -#include -#include - -#include "chipmunk/chipmunk_private.h" -#include "chipmunk/chipmunk_unsafe.h" -#include "ChipmunkDemo.h" - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 5); - space->damping = 0.1; - - cpShape *shape1, *shape2; - - cpFloat mass = 1.0f; - - { - cpFloat size = 100.0; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size))); - cpBodySetPosition(body, cpv(100.0, 50.0f)); - - shape1 = cpSpaceAddShape(space, cpBoxShapeNew(body, size, size, 0.0)); - } - { - cpFloat size = 100.0; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size))); - cpBodySetPosition(body, cpv(120.0, -40.0f)); - cpBodySetAngle(body, 1e-2); - - shape2 = cpSpaceAddShape(space, cpBoxShapeNew(body, size, size, 0.0)); - } - - { - cpFloat size = 100.0; - const int NUM_VERTS = 5; - - cpVect verts[NUM_VERTS]; - for (int i = 0; i < NUM_VERTS; i++) - { - cpFloat angle = -2 * M_PI * i / ((cpFloat)NUM_VERTS); - verts[i] = cpv(size / 2.0 * cos(angle), size / 2.0 * sin(angle)); - } - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, NUM_VERTS, verts, cpvzero, 0.0))); - cpBodySetPosition(body, cpv(100.0, 50.0f)); - - shape1 = cpSpaceAddShape(space, cpPolyShapeNew(body, NUM_VERTS, verts, cpTransformIdentity, 0.0)); - } - { - cpFloat size = 100.0; - const int NUM_VERTS = 4; - - cpVect verts[NUM_VERTS]; - for (int i = 0; i < NUM_VERTS; i++) - { - cpFloat angle = -2 * M_PI * i / ((cpFloat)NUM_VERTS); - verts[i] = cpv(size / 2.0 * cos(angle), size / 2.0 * sin(angle)); - } - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, NUM_VERTS, verts, cpvzero, 0.0))); - cpBodySetPosition(body, cpv(100.0, -50.0f)); - shape2 = cpSpaceAddShape(space, cpPolyShapeNew(body, NUM_VERTS, verts, cpTransformIdentity, 5.0)); - } - - { - cpFloat size = 150.0; - cpFloat radius = 25.0; - - cpVect a = cpv(size / 2.0, 0.0); - cpVect b = cpv(-size / 2.0, 0.0); - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b, 0.0))); - cpBodySetPosition(body, cpv(0, 25)); - - shape1 = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, radius)); - } - { - cpFloat radius = 50.0; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(0, -25)); - - shape2 = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Example = { - "Template to start (GJK)", 1.0f / 60.0f, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Joints.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Joints.cpp deleted file mode 100644 index db27fe805351..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Joints.cpp +++ /dev/null @@ -1,284 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody* addBall(cpSpace* space, cpVect pos, cpVect boxOffset) -{ - cpFloat radius = 15.0f; - cpFloat mass = 1.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpvadd(pos, boxOffset)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - - return body; -} - -static cpBody* addLever(cpSpace* space, cpVect pos, cpVect boxOffset) -{ - cpFloat mass = 1.0f; - cpVect a = cpv(0, 15); - cpVect b = cpv(0, -15); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b, 0.0f))); - cpBodySetPosition(body, cpvadd(pos, cpvadd(boxOffset, cpv(0, -15)))); - - cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 5.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - - return body; -} - -static cpBody* addBar(cpSpace* space, cpVect pos, cpVect boxOffset) -{ - cpFloat mass = 2.0f; - cpVect a = cpv(0, 30); - cpVect b = cpv(0, -30); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b, 0.0f))); - cpBodySetPosition(body, cpvadd(pos, boxOffset)); - - cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 5.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - return body; -} - -static cpBody* addWheel(cpSpace* space, cpVect pos, cpVect boxOffset) -{ - cpFloat radius = 15.0f; - cpFloat mass = 1.0f; - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpvadd(pos, boxOffset)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - return body; -} - -static cpBody* addChassis(cpSpace* space, cpVect pos, cpVect boxOffset) -{ - cpFloat mass = 5.0f; - cpFloat width = 80; - cpFloat height = 30; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); - cpBodySetPosition(body, cpvadd(pos, boxOffset)); - - cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - return body; -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 120), cpv(320, 120), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 0), cpv(320, 0), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -120), cpv(320, -120), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160, -240), cpv(-160, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0, -240), cpv(0, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(160, -240), cpv(160, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpVect boxOffset; - cpBody *body1, *body2; - - cpVect posA = cpv(50, 60); - cpVect posB = cpv(110, 60); - -#define POS_A cpvadd(boxOffset, posA) -#define POS_B cpvadd(boxOffset, posB) - - // Pin Joints - Link shapes with a solid bar or pin. - // Keeps the anchor points the same distance apart from when the joint was created. - boxOffset = cpv(-320, -240); - body1 = addBall(space, posA, boxOffset); - body2 = addBall(space, posB, boxOffset); - cpSpaceAddConstraint(space, cpPinJointNew(body1, body2, cpv(15, 0), cpv(-15, 0))); - - // Slide Joints - Like pin joints but with a min/max distance. - // Can be used for a cheap approximation of a rope. - boxOffset = cpv(-160, -240); - body1 = addBall(space, posA, boxOffset); - body2 = addBall(space, posB, boxOffset); - cpSpaceAddConstraint(space, cpSlideJointNew(body1, body2, cpv(15, 0), cpv(-15, 0), 20.0f, 40.0f)); - - // Pivot Joints - Holds the two anchor points together. Like a swivel. - boxOffset = cpv(0, -240); - body1 = addBall(space, posA, boxOffset); - body2 = addBall(space, posB, boxOffset); - cpSpaceAddConstraint(space, cpPivotJointNew(body1, body2, cpvadd(boxOffset, cpv(80, 60)))); - // cpPivotJointNew() takes it's anchor parameter in world coordinates. The anchors are calculated from that - // cpPivotJointNew2() lets you specify the two anchor points explicitly - - // Groove Joints - Like a pivot joint, but one of the anchors is a line segment that the pivot can slide in - boxOffset = cpv(160, -240); - body1 = addBall(space, posA, boxOffset); - body2 = addBall(space, posB, boxOffset); - cpSpaceAddConstraint(space, cpGrooveJointNew(body1, body2, cpv(30, 30), cpv(30, -30), cpv(-30, 0))); - - // Damped Springs - boxOffset = cpv(-320, -120); - body1 = addBall(space, posA, boxOffset); - body2 = addBall(space, posB, boxOffset); - cpSpaceAddConstraint(space, cpDampedSpringNew(body1, body2, cpv(15, 0), cpv(-15, 0), 20.0f, 5.0f, 0.3f)); - - // Damped Rotary Springs - boxOffset = cpv(-160, -120); - body1 = addBar(space, posA, boxOffset); - body2 = addBar(space, posB, boxOffset); - // Add some pin joints to hold the circles in place. - cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A)); - cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B)); - cpSpaceAddConstraint(space, cpDampedRotarySpringNew(body1, body2, 0.0f, 3000.0f, 60.0f)); - - // Rotary Limit Joint - boxOffset = cpv(0, -120); - body1 = addLever(space, posA, boxOffset); - body2 = addLever(space, posB, boxOffset); - // Add some pin joints to hold the circles in place. - cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A)); - cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B)); - // Hold their rotation within 90 degrees of each other. - cpSpaceAddConstraint(space, cpRotaryLimitJointNew(body1, body2, -CP_PI / 2.0f, CP_PI / 2.0f)); - - // Ratchet Joint - A rotary ratchet, like a socket wrench - boxOffset = cpv(160, -120); - body1 = addLever(space, posA, boxOffset); - body2 = addLever(space, posB, boxOffset); - // Add some pin joints to hold the circles in place. - cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A)); - cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B)); - // Ratchet every 90 degrees - cpSpaceAddConstraint(space, cpRatchetJointNew(body1, body2, 0.0f, CP_PI / 2.0f)); - - // Gear Joint - Maintain a specific angular velocity ratio - boxOffset = cpv(-320, 0); - body1 = addBar(space, posA, boxOffset); - body2 = addBar(space, posB, boxOffset); - // Add some pin joints to hold the circles in place. - cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A)); - cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B)); - // Force one to sping 2x as fast as the other - cpSpaceAddConstraint(space, cpGearJointNew(body1, body2, 0.0f, 2.0f)); - - // Simple Motor - Maintain a specific angular relative velocity - boxOffset = cpv(-160, 0); - body1 = addBar(space, posA, boxOffset); - body2 = addBar(space, posB, boxOffset); - // Add some pin joints to hold the circles in place. - cpSpaceAddConstraint(space, cpPivotJointNew(body1, staticBody, POS_A)); - cpSpaceAddConstraint(space, cpPivotJointNew(body2, staticBody, POS_B)); - // Make them spin at 1/2 revolution per second in relation to each other. - cpSpaceAddConstraint(space, cpSimpleMotorNew(body1, body2, CP_PI)); - - // Make a car with some nice soft suspension - boxOffset = cpv(0, 0); - cpBody* wheel1 = addWheel(space, posA, boxOffset); - cpBody* wheel2 = addWheel(space, posB, boxOffset); - cpBody* chassis = addChassis(space, cpv(80, 100), boxOffset); - - cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel1, cpv(-30, -10), cpv(-30, -40), cpvzero)); - cpSpaceAddConstraint(space, cpGrooveJointNew(chassis, wheel2, cpv(30, -10), cpv(30, -40), cpvzero)); - - cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel1, cpv(-30, 0), cpvzero, 50.0f, 20.0f, 10.0f)); - cpSpaceAddConstraint(space, cpDampedSpringNew(chassis, wheel2, cpv(30, 0), cpvzero, 50.0f, 20.0f, 10.0f)); - - return space; -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Joints = { - "Joints and Constraints", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/LogoSmash.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/LogoSmash.cpp deleted file mode 100644 index 4971f05a5e62..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/LogoSmash.cpp +++ /dev/null @@ -1,164 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static const int image_width = 188; -static const int image_height = 35; -static const int image_row_length = 24; -float ChipmunkDebugDrawPointLineScale = 1.0f; - -static const char image_bitmap[] = { - 15, -16, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 7, -64, 15, 63, -32, -2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 31, -64, 15, 127, -125, -1, -128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 127, -64, 15, 127, 15, -1, -64, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -64, 15, -2, 31, -1, -64, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -64, 0, -4, 63, -1, -32, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -64, 15, -8, 127, -1, - -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -1, -64, 0, - -8, -15, -1, -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, -31, - -1, -64, 15, -8, -32, -1, -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 7, -15, -1, -64, 9, -15, -32, -1, -32, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 31, -15, -1, -64, 0, -15, -32, -1, -32, 0, 0, 0, 0, 0, 0, 0, 0, - 0, 0, 0, 0, 0, 0, 0, 63, -7, -1, -64, 9, -29, -32, 127, -61, -16, 63, 15, -61, -1, - -8, 31, -16, 15, -8, 126, 7, -31, -8, 31, -65, -7, -1, -64, 9, -29, -32, 0, 7, -8, 127, - -97, -25, -1, -2, 63, -8, 31, -4, -1, 15, -13, -4, 63, -1, -3, -1, -64, 9, -29, -32, 0, - 7, -8, 127, -97, -25, -1, -2, 63, -8, 31, -4, -1, 15, -13, -2, 63, -1, -3, -1, -64, 9, - -29, -32, 0, 7, -8, 127, -97, -25, -1, -1, 63, -4, 63, -4, -1, 15, -13, -2, 63, -33, -1, - -1, -32, 9, -25, -32, 0, 7, -8, 127, -97, -25, -1, -1, 63, -4, 63, -4, -1, 15, -13, -1, - 63, -33, -1, -1, -16, 9, -25, -32, 0, 7, -8, 127, -97, -25, -1, -1, 63, -4, 63, -4, -1, - 15, -13, -1, 63, -49, -1, -1, -8, 9, -57, -32, 0, 7, -8, 127, -97, -25, -8, -1, 63, -2, - 127, -4, -1, 15, -13, -1, -65, -49, -1, -1, -4, 9, -57, -32, 0, 7, -8, 127, -97, -25, -8, - -1, 63, -2, 127, -4, -1, 15, -13, -1, -65, -57, -1, -1, -2, 9, -57, -32, 0, 7, -8, 127, - -97, -25, -8, -1, 63, -2, 127, -4, -1, 15, -13, -1, -1, -57, -1, -1, -1, 9, -57, -32, 0, - 7, -1, -1, -97, -25, -8, -1, 63, -1, -1, -4, -1, 15, -13, -1, -1, -61, -1, -1, -1, -119, - -57, -32, 0, 7, -1, -1, -97, -25, -8, -1, 63, -1, -1, -4, -1, 15, -13, -1, -1, -61, -1, - -1, -1, -55, -49, -32, 0, 7, -1, -1, -97, -25, -8, -1, 63, -1, -1, -4, -1, 15, -13, -1, - -1, -63, -1, -1, -1, -23, -49, -32, 127, -57, -1, -1, -97, -25, -1, -1, 63, -1, -1, -4, -1, - 15, -13, -1, -1, -63, -1, -1, -1, -16, -49, -32, -1, -25, -1, -1, -97, -25, -1, -1, 63, -33, - -5, -4, -1, 15, -13, -1, -1, -64, -1, -9, -1, -7, -49, -32, -1, -25, -8, 127, -97, -25, -1, - -1, 63, -33, -5, -4, -1, 15, -13, -1, -1, -64, -1, -13, -1, -32, -49, -32, -1, -25, -8, 127, - -97, -25, -1, -2, 63, -49, -13, -4, -1, 15, -13, -1, -1, -64, 127, -7, -1, -119, -17, -15, -1, - -25, -8, 127, -97, -25, -1, -2, 63, -49, -13, -4, -1, 15, -13, -3, -1, -64, 127, -8, -2, 15, - -17, -1, -1, -25, -8, 127, -97, -25, -1, -8, 63, -49, -13, -4, -1, 15, -13, -3, -1, -64, 63, - -4, 120, 0, -17, -1, -1, -25, -8, 127, -97, -25, -8, 0, 63, -57, -29, -4, -1, 15, -13, -4, - -1, -64, 63, -4, 0, 15, -17, -1, -1, -25, -8, 127, -97, -25, -8, 0, 63, -57, -29, -4, -1, - -1, -13, -4, -1, -64, 31, -2, 0, 0, 103, -1, -1, -57, -8, 127, -97, -25, -8, 0, 63, -57, - -29, -4, -1, -1, -13, -4, 127, -64, 31, -2, 0, 15, 103, -1, -1, -57, -8, 127, -97, -25, -8, - 0, 63, -61, -61, -4, 127, -1, -29, -4, 127, -64, 15, -8, 0, 0, 55, -1, -1, -121, -8, 127, - -97, -25, -8, 0, 63, -61, -61, -4, 127, -1, -29, -4, 63, -64, 15, -32, 0, 0, 23, -1, -2, - 3, -16, 63, 15, -61, -16, 0, 31, -127, -127, -8, 31, -1, -127, -8, 31, -128, 7, -128, 0, 0}; - -static inline int get_pixel(int x, int y) -{ - return (image_bitmap[(x >> 3) + y * image_row_length] >> (~x & 0x7)) & 1; -} - -static int bodyCount = 0; - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static void DrawDot(cpBody* body, void* unused) -{ - ChipmunkDebugDrawDot(3.5 / ChipmunkDebugDrawPointLineScale, cpBodyGetPosition(body), - RGBAColor(0xee / 255.0f, 0xe8 / 255.0f, 0xd5 / 255.0f, 1.0f)); -} - -static void draw(cpSpace* space) -{ - cpSpaceEachBody(space, DrawDot, NULL); - - // ChipmunkDebugDrawCollisionPoints(space); -} - -static cpShape* make_ball(cpFloat x, cpFloat y) -{ - cpBody* body = cpBodyNew(1.0, INFINITY); - cpBodySetPosition(body, cpv(x, y)); - - cpShape* shape = cpCircleShapeNew(body, 0.95, cpvzero); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.0); - - return shape; -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 1); - - // The space will contain a very large number of similary sized objects. - // This is the perfect candidate for using the spatial hash. - // Generally you will never need to do this. - cpSpaceUseSpatialHash(space, 2.0, 10000); - - bodyCount = 0; - - cpBody* body; - cpShape* shape; - - for (int y = 0; y < image_height; y++) - { - for (int x = 0; x < image_width; x++) - { - if (!get_pixel(x, y)) - continue; - - cpFloat x_jitter = 0.05 * frand(); - cpFloat y_jitter = 0.05 * frand(); - - shape = make_ball(2 * (x - image_width / 2 + x_jitter), 2 * (image_height / 2 - y + y_jitter)); - cpSpaceAddBody(space, cpShapeGetBody(shape)); - cpSpaceAddShape(space, shape); - - bodyCount++; - } - } - - body = cpSpaceAddBody(space, cpBodyNew(1e9, INFINITY)); - cpBodySetPosition(body, cpv(-1000, -10)); - cpBodySetVelocity(body, cpv(400, 0)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 8.0f, cpvzero)); - cpShapeSetElasticity(shape, 0.0); - cpShapeSetFriction(shape, 0.0); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - bodyCount++; - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo LogoSmash = { - "Logo Smash", 1.0 / 60.0, init, update, draw, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/OneWay.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/OneWay.cpp deleted file mode 100644 index 63d103c92e00..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/OneWay.cpp +++ /dev/null @@ -1,118 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -enum CollisionTypes -{ - COLLISION_TYPE_ONE_WAY = 1, -}; - -typedef struct OneWayPlatform -{ - cpVect n; // direction objects may pass through -} OneWayPlatform; - -static OneWayPlatform platformInstance; - -static cpBool PreSolve(cpArbiter* arb, cpSpace* space, void* ignore) -{ - CP_ARBITER_GET_SHAPES(arb, a, b); - OneWayPlatform* platform = (OneWayPlatform*)cpShapeGetUserData(a); - - if (cpvdot(cpArbiterGetNormal(arb), platform->n) < 0) - { - return cpArbiterIgnore(arb); - } - - return cpTrue; -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "One way platforms are trivial in Chipmunk using a very simple collision callback."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -100)); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Add our one way segment - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-160, -100), cpv(160, -100), 10.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetCollisionType(shape, COLLISION_TYPE_ONE_WAY); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // We'll use the data pointer for the OneWayPlatform struct - platformInstance.n = cpv(0, 1); // let objects pass upwards - cpShapeSetUserData(shape, &platformInstance); - - // Add a ball to test it out - cpFloat radius = 15.0f; - body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(0, -200)); - cpBodySetVelocity(body, cpv(0, 170)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.9f); - cpShapeSetCollisionType(shape, 2); - - cpCollisionHandler* handler = cpSpaceAddWildcardHandler(space, COLLISION_TYPE_ONE_WAY); - handler->preSolveFunc = PreSolve; - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo OneWay = { - "One Way Platforms", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Planet.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Planet.cpp deleted file mode 100644 index cc7d4f8c6985..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Planet.cpp +++ /dev/null @@ -1,122 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody* planetBody; - -static cpFloat gravityStrength = 5.0e6f; - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static void planetGravityVelocityFunc(cpBody* body, cpVect gravity, cpFloat damping, cpFloat dt) -{ - // Gravitational acceleration is proportional to the inverse square of - // distance, and directed toward the origin. The central planet is assumed - // to be massive enough that it affects the satellites but not vice versa. - cpVect p = cpBodyGetPosition(body); - cpFloat sqdist = cpvlengthsq(p); - cpVect g = cpvmult(p, -gravityStrength / (sqdist * cpfsqrt(sqdist))); - - cpBodyUpdateVelocity(body, g, damping, dt); -} - -static cpVect rand_pos(cpFloat radius) -{ - cpVect v; - do - { - v = cpv(frand() * (640 - 2 * radius) - (320 - radius), frand() * (480 - 2 * radius) - (240 - radius)); - } while (cpvlength(v) < 85.0f); - - return v; -} - -static void add_box(cpSpace* space) -{ - const cpFloat size = 10.0f; - const cpFloat mass = 1.0f; - - cpVect verts[] = { - cpv(-size, -size), - cpv(-size, size), - cpv(size, size), - cpv(size, -size), - }; - - cpFloat radius = cpvlength(cpv(size, size)); - cpVect pos = rand_pos(radius); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 4, verts, cpvzero, 0.0f))); - cpBodySetVelocityUpdateFunc(body, planetGravityVelocityFunc); - cpBodySetPosition(body, pos); - - // Set the box's velocity to put it into a circular orbit from its - // starting position. - cpFloat r = cpvlength(pos); - cpFloat v = cpfsqrt(gravityStrength / r) / r; - cpBodySetVelocity(body, cpvmult(cpvperp(pos), v)); - - // Set the box's angular velocity to match its orbital period and - // align its initial angle with its position. - cpBodySetAngularVelocity(body, v); - cpBodySetAngle(body, cpfatan2(pos.y, pos.x)); - - cpShape* shape = cpSpaceAddShape(space, cpPolyShapeNew(body, 4, verts, cpTransformIdentity, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); -} - -static cpSpace* init(void) -{ - // Create a rouge body to control the planet manually. - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 20); - - planetBody = cpSpaceAddBody(space, cpBodyNewKinematic()); - cpBodySetAngularVelocity(planetBody, 0.2f); - - for (int i = 0; i < 30; i++) - { - add_box(space); - } - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(planetBody, 70.0f, cpvzero)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Planet = { - "Planet", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Player.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Player.cpp deleted file mode 100644 index 0ed950dc8077..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Player.cpp +++ /dev/null @@ -1,180 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk_private.h" -#include "ChipmunkDemo.h" - -#define PLAYER_VELOCITY 500.0 - -#define PLAYER_GROUND_ACCEL_TIME 0.1 -#define PLAYER_GROUND_ACCEL (PLAYER_VELOCITY / PLAYER_GROUND_ACCEL_TIME) - -#define PLAYER_AIR_ACCEL_TIME 0.25 -#define PLAYER_AIR_ACCEL (PLAYER_VELOCITY / PLAYER_AIR_ACCEL_TIME) - -#define JUMP_HEIGHT 50.0 -#define JUMP_BOOST_HEIGHT 55.0 -#define FALL_VELOCITY 900.0 -#define GRAVITY 2000.0 - -static cpBody* playerBody = NULL; -static cpShape* playerShape = NULL; - -static cpFloat remainingBoost = 0; -static cpBool grounded = cpFalse; -static cpBool lastJumpState = cpFalse; - -static void SelectPlayerGroundNormal(cpBody* body, cpArbiter* arb, cpVect* groundNormal) -{ - cpVect n = cpvneg(cpArbiterGetNormal(arb)); - - if (n.y > groundNormal->y) - { - (*groundNormal) = n; - } -} - -static void playerUpdateVelocity(cpBody* body, cpVect gravity, cpFloat damping, cpFloat dt) -{ - int jumpState = (ChipmunkDemoKeyboard.y > 0.0f); - - // Grab the grounding normal from last frame - cpVect groundNormal = cpvzero; - cpBodyEachArbiter(playerBody, (cpBodyArbiterIteratorFunc)SelectPlayerGroundNormal, &groundNormal); - - grounded = (groundNormal.y > 0.0); - if (groundNormal.y < 0.0f) - remainingBoost = 0.0f; - - // Do a normal-ish update - cpBool boost = (jumpState && remainingBoost > 0.0f); - cpVect g = (boost ? cpvzero : gravity); - cpBodyUpdateVelocity(body, g, damping, dt); - - // Target horizontal speed for air/ground control - cpFloat target_vx = PLAYER_VELOCITY * ChipmunkDemoKeyboard.x; - - // Update the surface velocity and friction - // Note that the "feet" move in the opposite direction of the player. - cpVect surface_v = cpv(-target_vx, 0.0); - playerShape->surfaceV = surface_v; - playerShape->u = (grounded ? PLAYER_GROUND_ACCEL / GRAVITY : 0.0); - - // Apply air control if not grounded - if (!grounded) - { - // Smoothly accelerate the velocity - playerBody->v.x = cpflerpconst(playerBody->v.x, target_vx, PLAYER_AIR_ACCEL * dt); - } - - body->v.y = cpfclamp(body->v.y, -FALL_VELOCITY, INFINITY); -} - -static void update(cpSpace* space, double dt) -{ - int jumpState = (ChipmunkDemoKeyboard.y > 0.0f); - - // If the jump key was just pressed this frame, jump! - if (jumpState && !lastJumpState && grounded) - { - cpFloat jump_v = cpfsqrt(2.0 * JUMP_HEIGHT * GRAVITY); - playerBody->v = cpvadd(playerBody->v, cpv(0.0, jump_v)); - - remainingBoost = JUMP_BOOST_HEIGHT / jump_v; - } - - // Step the space - cpSpaceStep(space, dt); - - remainingBoost -= dt; - lastJumpState = jumpState; -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - space->iterations = 10; - space->gravity = cpv(0, -GRAVITY); - // space->sleepTimeThreshold = 1000; - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - shape->e = 1.0f; - shape->u = 1.0f; - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - shape->e = 1.0f; - shape->u = 1.0f; - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - shape->e = 1.0f; - shape->u = 1.0f; - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 240), cpv(320, 240), 0.0f)); - shape->e = 1.0f; - shape->u = 1.0f; - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Set up the player - body = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY)); - body->p = cpv(0, -200); - body->velocity_func = playerUpdateVelocity; - playerBody = body; - - shape = cpSpaceAddShape(space, cpBoxShapeNew2(body, cpBBNew(-15.0, -27.5, 15.0, 27.5), 1.0)); - // shape = cpSpaceAddShape(space, cpSegmentShapeNew(playerBody, cpvzero, cpv(0, radius), radius)); - shape->e = 0.0f; - shape->u = 0.0f; - shape->type = 1; - playerShape = shape; - - // Add some boxes to jump on - for (int i = 0; i < 6; i++) - { - for (int j = 0; j < 3; j++) - { - body = cpSpaceAddBody(space, cpBodyNew(4.0f, INFINITY)); - body->p = cpv(100 + j * 60, -200 + i * 60); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, 50, 50, 0.0)); - shape->e = 0.0f; - shape->u = 0.7f; - } - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo PlatformerPlayer = { - "Platformer Player Controls", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Plink.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Plink.cpp deleted file mode 100644 index dec53e8bc4e4..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Plink.cpp +++ /dev/null @@ -1,133 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpFloat pentagon_mass = 0.0f; -static cpFloat pentagon_moment = 0.0f; - -// Iterate over all of the bodies and reset the ones that have fallen offscreen. -static void eachBody(cpBody* body, void* unused) -{ - cpVect pos = cpBodyGetPosition(body); - if (pos.y < -260) - { - cpFloat x = rand() / (cpFloat)RAND_MAX * 640 - 320; - cpBodySetPosition(body, cpv(x, 260)); - } -} - -static void update(cpSpace* space, double dt) -{ - if (ChipmunkDemoRightDown) - { - ChipmunkDemoRightDown = cpFalse; - cpShape* nearest = cpSpacePointQueryNearest(space, ChipmunkDemoMouse, 0.0, GRAB_FILTER, NULL); - if (nearest) - { - cpBody* body = cpShapeGetBody(nearest); - if (cpBodyGetType(body) == CP_BODY_TYPE_STATIC) - { - cpBodySetType(body, CP_BODY_TYPE_DYNAMIC); - cpBodySetMass(body, pentagon_mass); - cpBodySetMoment(body, pentagon_moment); - } - else if (cpBodyGetType(body) == CP_BODY_TYPE_DYNAMIC) - { - cpBodySetType(body, CP_BODY_TYPE_STATIC); - } - } - } - - cpSpaceEachBody(space, &eachBody, NULL); - cpSpaceStep(space, dt); -} - -#define NUM_VERTS 5 - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Right click to make pentagons static/dynamic."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 5); - cpSpaceSetGravity(space, cpv(0, -100)); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Vertexes for a triangle shape. - cpVect tris[] = { - cpv(-15, -15), - cpv(0, 10), - cpv(15, -15), - }; - - // Create the static triangles. - for (int i = 0; i < 10; i++) - { - for (int j = 0; j < 6; j++) - { - cpFloat stagger = (j % 2) * 40; - cpVect offset = cpv(i * 80 - 360 + stagger, j * 70 - 200); - shape = cpSpaceAddShape(space, cpPolyShapeNew(staticBody, 3, tris, cpTransformTranslate(offset), 0.0)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - } - } - - // Create vertexes for a pentagon shape. - cpVect verts[NUM_VERTS]; - for (int i = 0; i < NUM_VERTS; i++) - { - cpFloat angle = -2.0f * CP_PI * i / ((cpFloat)NUM_VERTS); - verts[i] = cpv(10 * cos(angle), 10 * sin(angle)); - } - - pentagon_mass = 1.0; - pentagon_moment = cpMomentForPoly(1.0f, NUM_VERTS, verts, cpvzero, 0.0f); - - // Add lots of pentagons. - for (int i = 0; i < 300; i++) - { - body = cpSpaceAddBody(space, cpBodyNew(pentagon_mass, pentagon_moment)); - cpFloat x = rand() / (cpFloat)RAND_MAX * 640 - 320; - cpBodySetPosition(body, cpv(x, 350)); - - shape = cpSpaceAddShape(space, cpPolyShapeNew(body, NUM_VERTS, verts, cpTransformIdentity, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.4f); - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Plink = { - "Plink", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Pump.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Pump.cpp deleted file mode 100644 index b059b52df0a7..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Pump.cpp +++ /dev/null @@ -1,184 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpConstraint* motor; - -#define numBalls 5 -static cpBody* balls[numBalls]; - -static void update(cpSpace* space, double dt) -{ - cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y) / 3.0f; - cpFloat rate = ChipmunkDemoKeyboard.x * 30.0f * coef; - - cpSimpleMotorSetRate(motor, rate); - cpConstraintSetMaxForce(motor, rate ? 1000000.0f : 0.0f); - - cpSpaceStep(space, dt); - - for (int i = 0; i < numBalls; i++) - { - cpBody* ball = balls[i]; - cpVect pos = cpBodyGetPosition(ball); - - if (pos.x > 320.0f) - { - cpBodySetVelocity(ball, cpvzero); - cpBodySetPosition(ball, cpv(-224.0f, 200.0f)); - } - } -} - -static cpBody* add_ball(cpSpace* space, cpVect pos) -{ - cpBody* body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForCircle(1.0f, 30, 0, cpvzero))); - cpBodySetPosition(body, pos); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, 30, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - - return body; -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Use the arrow keys to control the machine."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetGravity(space, cpv(0, -600)); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // beveling all of the line segments slightly helps prevent things from getting stuck on cracks - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256, 16), cpv(-256, 300), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-256, 16), cpv(-192, 0), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192, 0), cpv(-192, -64), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128, -64), cpv(-128, 144), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192, 80), cpv(-192, 176), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-192, 176), cpv(-128, 240), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-128, 144), cpv(192, 64), 2.0f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpVect verts[] = { - cpv(-30, -80), - cpv(-30, 80), - cpv(30, 64), - cpv(30, -80), - }; - - cpBody* plunger = cpSpaceAddBody(space, cpBodyNew(1.0f, INFINITY)); - cpBodySetPosition(plunger, cpv(-160, -80)); - - shape = cpSpaceAddShape(space, cpPolyShapeNew(plunger, 4, verts, cpTransformIdentity, 0.0)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 0.5f); - cpShapeSetFilter(shape, cpShapeFilterNew(CP_NO_GROUP, 1, 1)); - - // add balls to hopper - for (int i = 0; i < numBalls; i++) - balls[i] = add_ball(space, cpv(-224 + i, 80 + 64 * i)); - - // add small gear - cpBody* smallGear = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 80, 0, cpvzero))); - cpBodySetPosition(smallGear, cpv(-160, -160)); - cpBodySetAngle(smallGear, -CP_PI / 2.0f); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(smallGear, 80.0f, cpvzero)); - cpShapeSetFilter(shape, CP_SHAPE_FILTER_NONE); - - cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, smallGear, cpv(-160, -160), cpvzero)); - - // add big gear - cpBody* bigGear = cpSpaceAddBody(space, cpBodyNew(40.0f, cpMomentForCircle(40.0f, 160, 0, cpvzero))); - cpBodySetPosition(bigGear, cpv(80, -160)); - cpBodySetAngle(bigGear, CP_PI / 2.0f); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(bigGear, 160.0f, cpvzero)); - cpShapeSetFilter(shape, CP_SHAPE_FILTER_NONE); - - cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, bigGear, cpv(80, -160), cpvzero)); - - // connect the plunger to the small gear. - cpSpaceAddConstraint(space, cpPinJointNew(smallGear, plunger, cpv(80, 0), cpv(0, 0))); - // connect the gears. - cpSpaceAddConstraint(space, cpGearJointNew(smallGear, bigGear, -CP_PI / 2.0f, -2.0f)); - - // feeder mechanism - cpFloat bottom = -300.0f; - cpFloat top = 32.0f; - cpBody* feeder = - cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForSegment(1.0f, cpv(-224.0f, bottom), cpv(-224.0f, top), 0.0f))); - cpBodySetPosition(feeder, cpv(-224, (bottom + top) / 2.0f)); - - cpFloat len = top - bottom; - shape = cpSpaceAddShape(space, cpSegmentShapeNew(feeder, cpv(0.0f, len / 2.0f), cpv(0.0f, -len / 2.0f), 20.0f)); - cpShapeSetFilter(shape, GRAB_FILTER); - - cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, feeder, cpv(-224.0f, bottom), cpv(0.0f, -len / 2.0f))); - cpVect anchr = cpBodyWorldToLocal(feeder, cpv(-224.0f, -160.0f)); - cpSpaceAddConstraint(space, cpPinJointNew(feeder, smallGear, anchr, cpv(0.0f, 80.0f))); - - // motorize the second gear - motor = cpSpaceAddConstraint(space, cpSimpleMotorNew(staticBody, bigGear, 3.0f)); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Pump = { - "Pump", 1.0 / 120.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidStack.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidStack.cpp deleted file mode 100644 index 520affdab40e..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidStack.cpp +++ /dev/null @@ -1,92 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "chipmunk/chipmunk_unsafe.h" -#include "ChipmunkDemo.h" - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -100)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Add lots of boxes. - for (int i = 0; i < 14; i++) - { - for (int j = 0; j <= i; j++) - { - body = cpSpaceAddBody(space, cpBodyNew(1.0f, cpMomentForBox(1.0f, 30.0f, 30.0f))); - cpBodySetPosition(body, cpv(j * 32 - i * 16, 300 - i * 32)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, 30.0f, 30.0f, 0.5f)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.8f); - } - } - - // Add a ball to make things more interesting - cpFloat radius = 15.0f; - body = cpSpaceAddBody(space, cpBodyNew(10.0f, cpMomentForCircle(10.0f, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(0, -200 + radius + 5)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.9f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo PyramidStack = { - "Pyramid Stack", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidTopple.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidTopple.cpp deleted file mode 100644 index a45649901644..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/PyramidTopple.cpp +++ /dev/null @@ -1,102 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -#define WIDTH 4.0f -#define HEIGHT 30.0f - -static void add_domino(cpSpace* space, cpVect pos, cpBool flipped) -{ - cpFloat mass = 1.0f; - cpFloat radius = 0.5f; - cpFloat moment = cpMomentForBox(mass, WIDTH, HEIGHT); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(body, pos); - - cpShape* shape = (flipped ? cpBoxShapeNew(body, HEIGHT, WIDTH, 0.0) - : cpBoxShapeNew(body, WIDTH - radius * 2.0f, HEIGHT, radius)); - cpSpaceAddShape(space, shape); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.6f); -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -300)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - // Add a floor. - cpShape* shape = - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(-600, -240), cpv(600, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - // Add the dominoes. - int n = 12; - for (int i = 0; i < n; i++) - { - for (int j = 0; j < (n - i); j++) - { - cpVect offset = - cpv((j - (n - 1 - i) * 0.5f) * 1.5f * HEIGHT, (i + 0.5f) * (HEIGHT + 2 * WIDTH) - WIDTH - 240); - add_domino(space, offset, cpFalse); - add_domino(space, cpvadd(offset, cpv(0, (HEIGHT + WIDTH) / 2.0f)), cpTrue); - - if (j == 0) - { - add_domino(space, cpvadd(offset, cpv(0.5f * (WIDTH - HEIGHT), HEIGHT + WIDTH)), cpFalse); - } - - if (j != n - i - 1) - { - add_domino(space, cpvadd(offset, cpv(HEIGHT * 0.75f, (HEIGHT + 3 * WIDTH) / 2.0f)), cpTrue); - } - else - { - add_domino(space, cpvadd(offset, cpv(0.5f * (HEIGHT - WIDTH), HEIGHT + WIDTH)), cpFalse); - } - } - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo PyramidTopple = { - "Pyramid Topple", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Query.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Query.cpp deleted file mode 100644 index c030b1308d5f..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Query.cpp +++ /dev/null @@ -1,143 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpVect QUERY_START = {0, 0}; - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); - - if (ChipmunkDemoRightClick) - { - QUERY_START = ChipmunkDemoMouse; - } - - cpVect start = QUERY_START; - cpVect end = ChipmunkDemoMouse; - cpFloat radius = 10.0; - ChipmunkDebugDrawSegment(start, end, RGBAColor(0, 1, 0, 1)); - - ChipmunkDemoPrintString("Query: Dist(%f) Point(%5.2f, %5.2f),\n", cpvdist(start, end), end.x, end.y); - - cpSegmentQueryInfo segInfo = {0}; - if (cpSpaceSegmentQueryFirst(space, start, end, radius, CP_SHAPE_FILTER_ALL, &segInfo)) - { - cpVect point = segInfo.point; - cpVect n = segInfo.normal; - - // Draw blue over the occluded part of the query - ChipmunkDebugDrawSegment(cpvlerp(start, end, segInfo.alpha), end, RGBAColor(0, 0, 1, 1)); - - // Draw a little red surface normal - ChipmunkDebugDrawSegment(point, cpvadd(point, cpvmult(n, 16)), RGBAColor(1, 0, 0, 1)); - - // Draw a little red dot on the hit point. - ChipmunkDebugDrawDot(3, point, RGBAColor(1, 0, 0, 1)); - - ChipmunkDemoPrintString("Segment Query: Dist(%f) Normal(%5.2f, %5.2f)\n", segInfo.alpha * cpvdist(start, end), - n.x, n.y); - } - else - { - ChipmunkDemoPrintString("Segment Query (None)\n"); - } - - // Draw a fat green line over the unoccluded part of the query - ChipmunkDebugDrawFatSegment(start, cpvlerp(start, end, segInfo.alpha), radius, RGBAColor(0, 1, 0, 1), - LAColor(0, 0)); - - cpPointQueryInfo nearestInfo = {0}; - cpSpacePointQueryNearest(space, ChipmunkDemoMouse, 100.0, CP_SHAPE_FILTER_ALL, &nearestInfo); - if (nearestInfo.shape) - { - // Draw a grey line to the closest shape. - ChipmunkDebugDrawDot(3, ChipmunkDemoMouse, RGBAColor(0.5, 0.5, 0.5, 1.0)); - ChipmunkDebugDrawSegment(ChipmunkDemoMouse, nearestInfo.point, RGBAColor(0.5, 0.5, 0.5, 1.0)); - - // Draw a red bounding box around the shape under the mouse. - if (nearestInfo.distance < 0) - ChipmunkDebugDrawBB(cpShapeGetBB(nearestInfo.shape), RGBAColor(1, 0, 0, 1)); - } -} - -static cpSpace* init(void) -{ - QUERY_START = cpvzero; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 5); - - { // add a fat segment - cpFloat mass = 1.0f; - cpFloat length = 100.0f; - cpVect a = cpv(-length / 2.0f, 0.0f), b = cpv(length / 2.0f, 0.0f); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForSegment(mass, a, b, 0.0f))); - cpBodySetPosition(body, cpv(0.0f, 100.0f)); - - cpSpaceAddShape(space, cpSegmentShapeNew(body, a, b, 20.0f)); - } - - { // add a static segment - cpSpaceAddShape(space, cpSegmentShapeNew(cpSpaceGetStaticBody(space), cpv(0, 300), cpv(300, 0), 0.0f)); - } - - { // add a pentagon - cpFloat mass = 1.0f; - - cpVect verts[5]; - for (int i = 0; i < 5; i++) - { - cpFloat angle = -2.0f * CP_PI * i / ((cpFloat)5); - verts[i] = cpv(30 * cos(angle), 30 * sin(angle)); - } - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForPoly(mass, 5, verts, cpvzero, 0.0f))); - cpBodySetPosition(body, cpv(50.0f, 30.0f)); - - cpSpaceAddShape(space, cpPolyShapeNew(body, 5, verts, cpTransformIdentity, 10.0f)); - } - - { // add a circle - cpFloat mass = 1.0f; - cpFloat r = 20.0f; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, r, cpvzero))); - cpBodySetPosition(body, cpv(100.0f, 100.0f)); - - cpSpaceAddShape(space, cpCircleShapeNew(body, r, cpvzero)); - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Query = { - "Segment Query", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Shatter.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Shatter.cpp deleted file mode 100644 index d013e7e6335d..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Shatter.cpp +++ /dev/null @@ -1,257 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "chipmunk/chipmunk.h" - -#include "ChipmunkDemo.h" - -#define DENSITY (1.0 / 10000.0) - -#define MAX_VERTEXES_PER_VORONOI 16 - -struct WorleyContex -{ - uint32_t seed; - cpFloat cellSize; - int width, height; - cpBB bb; - cpVect focus; -}; - -static inline cpVect HashVect(uint32_t x, uint32_t y, uint32_t seed) -{ - // cpFloat border = 0.21f; - cpFloat border = 0.05f; - uint32_t h = (x * 1640531513 ^ y * 2654435789) + seed; - - return cpv(cpflerp(border, 1.0f - border, (cpFloat)(h & 0xFFFF) / (cpFloat)0xFFFF), - cpflerp(border, 1.0f - border, (cpFloat)((h >> 16) & 0xFFFF) / (cpFloat)0xFFFF)); -} - -static cpVect WorleyPoint(int i, int j, struct WorleyContex* context) -{ - cpFloat size = context->cellSize; - int width = context->width; - int height = context->height; - cpBB bb = context->bb; - - // cpVect fv = cpv(0.5, 0.5); - cpVect fv = HashVect(i, j, context->seed); - - return cpv(cpflerp(bb.l, bb.r, 0.5f) + size * (i + fv.x - width * 0.5f), - cpflerp(bb.b, bb.t, 0.5f) + size * (j + fv.y - height * 0.5f)); -} - -static int ClipCell(cpShape* shape, - cpVect center, - int i, - int j, - struct WorleyContex* context, - cpVect* verts, - cpVect* clipped, - int count) -{ - cpVect other = WorleyPoint(i, j, context); - // printf(" other %dx%d: (% 5.2f, % 5.2f) ", i, j, other.x, other.y); - if (cpShapePointQuery(shape, other, NULL) > 0.0f) - { - // printf("excluded\n"); - memcpy(clipped, verts, count * sizeof(cpVect)); - return count; - } - else - { - // printf("clipped\n"); - } - - cpVect n = cpvsub(other, center); - cpFloat dist = cpvdot(n, cpvlerp(center, other, 0.5f)); - - int clipped_count = 0; - for (int j = 0, i = count - 1; j < count; i = j, j++) - { - cpVect a = verts[i]; - cpFloat a_dist = cpvdot(a, n) - dist; - - if (a_dist <= 0.0) - { - clipped[clipped_count] = a; - clipped_count++; - } - - cpVect b = verts[j]; - cpFloat b_dist = cpvdot(b, n) - dist; - - if (a_dist * b_dist < 0.0f) - { - cpFloat t = cpfabs(a_dist) / (cpfabs(a_dist) + cpfabs(b_dist)); - - clipped[clipped_count] = cpvlerp(a, b, t); - clipped_count++; - } - } - - return clipped_count; -} - -static void ShatterCell(cpSpace* space, - cpShape* shape, - cpVect cell, - int cell_i, - int cell_j, - struct WorleyContex* context) -{ - // printf("cell %dx%d: (% 5.2f, % 5.2f)\n", cell_i, cell_j, cell.x, cell.y); - - cpBody* body = cpShapeGetBody(shape); - - cpVect* ping = (cpVect*)alloca(MAX_VERTEXES_PER_VORONOI * sizeof(cpVect)); - cpVect* pong = (cpVect*)alloca(MAX_VERTEXES_PER_VORONOI * sizeof(cpVect)); - - int count = cpPolyShapeGetCount(shape); - count = (count > MAX_VERTEXES_PER_VORONOI ? MAX_VERTEXES_PER_VORONOI : count); - - for (int i = 0; i < count; i++) - { - ping[i] = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, i)); - } - - for (int i = 0; i < context->width; i++) - { - for (int j = 0; j < context->height; j++) - { - if (!(i == cell_i && j == cell_j) && cpShapePointQuery(shape, cell, NULL) < 0.0f) - { - count = ClipCell(shape, cell, i, j, context, ping, pong, count); - memcpy(ping, pong, count * sizeof(cpVect)); - } - } - } - - cpVect centroid = cpCentroidForPoly(count, ping); - cpFloat mass = cpAreaForPoly(count, ping, 0.0f) * DENSITY; - cpFloat moment = cpMomentForPoly(mass, count, ping, cpvneg(centroid), 0.0f); - - cpBody* new_body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(new_body, centroid); - cpBodySetVelocity(new_body, cpBodyGetVelocityAtWorldPoint(body, centroid)); - cpBodySetAngularVelocity(new_body, cpBodyGetAngularVelocity(body)); - - cpTransform transform = cpTransformTranslate(cpvneg(centroid)); - cpShape* new_shape = cpSpaceAddShape(space, cpPolyShapeNew(new_body, count, ping, transform, 0.0)); - // Copy whatever properties you have set on the original shape that are important - cpShapeSetFriction(new_shape, cpShapeGetFriction(shape)); -} - -static void ShatterShape(cpSpace* space, cpShape* shape, cpFloat cellSize, cpVect focus) -{ - cpSpaceRemoveShape(space, shape); - cpSpaceRemoveBody(space, cpShapeGetBody(shape)); - - cpBB bb = cpShapeGetBB(shape); - int width = (int)((bb.r - bb.l) / cellSize) + 1; - int height = (int)((bb.t - bb.b) / cellSize) + 1; - // printf("Splitting as %dx%d\n", width, height); - struct WorleyContex context = {(uint32_t)rand(), cellSize, width, height, bb, focus}; - - for (int i = 0; i < context.width; i++) - { - for (int j = 0; j < context.height; j++) - { - cpVect cell = WorleyPoint(i, j, &context); - if (cpShapePointQuery(shape, cell, NULL) < 0.0f) - { - ShatterCell(space, shape, cell, i, j, &context); - } - } - } - - cpBodyFree(cpShapeGetBody(shape)); - cpShapeFree(shape); -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); - - if (ChipmunkDemoRightDown) - { - cpPointQueryInfo info; - if (cpSpacePointQueryNearest(space, ChipmunkDemoMouse, 0, GRAB_FILTER, &info)) - { - cpBB bb = cpShapeGetBB(info.shape); - cpFloat cell_size = cpfmax(bb.r - bb.l, bb.t - bb.b) / 5.0f; - if (cell_size > 5.0f) - { - ShatterShape(space, (cpShape*)info.shape, cell_size, ChipmunkDemoMouse); - } - else - { - // printf("Too small to splinter %f\n", cell_size); - } - } - ChipmunkDemoRightDown = false; - } -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Right click something to shatter it."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -500)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-1000, -240), cpv(1000, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat width = 200.0f; - cpFloat height = 200.0f; - cpFloat mass = width * height * DENSITY; - cpFloat moment = cpMomentForBox(mass, width, height); - - body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetFriction(shape, 0.6f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Shatter = { - "Shatter.", 1.0f / 60.0f, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Slice.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Slice.cpp deleted file mode 100644 index 445452e17a6a..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Slice.cpp +++ /dev/null @@ -1,188 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" - -#include "ChipmunkDemo.h" - -#define DENSITY (1.0 / 10000.0) - -static void ClipPoly(cpSpace* space, cpShape* shape, cpVect n, cpFloat dist) -{ - cpBody* body = cpShapeGetBody(shape); - - int count = cpPolyShapeGetCount(shape); - int clippedCount = 0; - - cpVect* clipped = (cpVect*)alloca((count + 1) * sizeof(cpVect)); - - for (int i = 0, j = count - 1; i < count; j = i, i++) - { - cpVect a = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, j)); - cpFloat a_dist = cpvdot(a, n) - dist; - - if (a_dist < 0.0) - { - clipped[clippedCount] = a; - clippedCount++; - } - - cpVect b = cpBodyLocalToWorld(body, cpPolyShapeGetVert(shape, i)); - cpFloat b_dist = cpvdot(b, n) - dist; - - if (a_dist * b_dist < 0.0f) - { - cpFloat t = cpfabs(a_dist) / (cpfabs(a_dist) + cpfabs(b_dist)); - - clipped[clippedCount] = cpvlerp(a, b, t); - clippedCount++; - } - } - - cpVect centroid = cpCentroidForPoly(clippedCount, clipped); - cpFloat mass = cpAreaForPoly(clippedCount, clipped, 0.0f) * DENSITY; - cpFloat moment = cpMomentForPoly(mass, clippedCount, clipped, cpvneg(centroid), 0.0f); - - cpBody* new_body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(new_body, centroid); - cpBodySetVelocity(new_body, cpBodyGetVelocityAtWorldPoint(body, centroid)); - cpBodySetAngularVelocity(new_body, cpBodyGetAngularVelocity(body)); - - cpTransform transform = cpTransformTranslate(cpvneg(centroid)); - cpShape* new_shape = cpSpaceAddShape(space, cpPolyShapeNew(new_body, clippedCount, clipped, transform, 0.0)); - // Copy whatever properties you have set on the original shape that are important - cpShapeSetFriction(new_shape, cpShapeGetFriction(shape)); -} - -// Context structs are annoying, use blocks or closures instead if your compiler supports them. -struct SliceContext -{ - cpVect a, b; - cpSpace* space; -}; - -static void SliceShapePostStep(cpSpace* space, cpShape* shape, struct SliceContext* context) -{ - cpVect a = context->a; - cpVect b = context->b; - - // Clipping plane normal and distance. - cpVect n = cpvnormalize(cpvperp(cpvsub(b, a))); - cpFloat dist = cpvdot(a, n); - - ClipPoly(space, shape, n, dist); - ClipPoly(space, shape, cpvneg(n), -dist); - - cpBody* body = cpShapeGetBody(shape); - cpSpaceRemoveShape(space, shape); - cpSpaceRemoveBody(space, body); - cpShapeFree(shape); - cpBodyFree(body); -} - -static void SliceQuery(cpShape* shape, cpVect point, cpVect normal, cpFloat alpha, struct SliceContext* context) -{ - cpVect a = context->a; - cpVect b = context->b; - - // Check that the slice was complete by checking that the endpoints aren't in the sliced shape. - if (cpShapePointQuery(shape, a, NULL) > 0.0f && cpShapePointQuery(shape, b, NULL) > 0.0f) - { - // Can't modify the space during a query. - // Must make a post-step callback to do the actual slicing. - cpSpaceAddPostStepCallback(context->space, (cpPostStepFunc)SliceShapePostStep, shape, context); - } -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); - - static cpBool lastClickState = cpFalse; - static cpVect sliceStart = {0.0, 0.0}; - - // Annoying state tracking code that you wouldn't need - // in a real event driven system. - if (ChipmunkDemoRightClick != lastClickState) - { - if (ChipmunkDemoRightClick) - { - // MouseDown - sliceStart = ChipmunkDemoMouse; - } - else - { - // MouseUp - struct SliceContext context = {sliceStart, ChipmunkDemoMouse, space}; - cpSpaceSegmentQuery(space, sliceStart, ChipmunkDemoMouse, 0.0, GRAB_FILTER, - (cpSpaceSegmentQueryFunc)SliceQuery, &context); - } - - lastClickState = ChipmunkDemoRightClick; - } - - if (ChipmunkDemoRightClick) - { - ChipmunkDebugDrawSegment(sliceStart, ChipmunkDemoMouse, RGBAColor(1, 0, 0, 1)); - } -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Right click and drag to slice up the block."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -500)); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - cpSpaceSetCollisionSlop(space, 0.5f); - - cpBody *body, *staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-1000, -240), cpv(1000, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat width = 200.0f; - cpFloat height = 300.0f; - cpFloat mass = width * height * DENSITY; - cpFloat moment = cpMomentForBox(mass, width, height); - - body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetFriction(shape, 0.6f); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Slice = { - "Slice.", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Springies.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Springies.cpp deleted file mode 100644 index 89fdfab17025..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Springies.cpp +++ /dev/null @@ -1,152 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpFloat springForce(cpConstraint* spring, cpFloat dist) -{ - cpFloat clamp = 20.0f; - return cpfclamp(cpDampedSpringGetRestLength(spring) - dist, -clamp, clamp) * cpDampedSpringGetStiffness(spring); -} - -static cpConstraint* -new_spring(cpBody* a, cpBody* b, cpVect anchorA, cpVect anchorB, cpFloat restLength, cpFloat stiff, cpFloat damp) -{ - cpConstraint* spring = cpDampedSpringNew(a, b, anchorA, anchorB, restLength, stiff, damp); - cpDampedSpringSetSpringForceFunc(spring, springForce); - - return spring; -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpBody* add_bar(cpSpace* space, cpVect a, cpVect b, int group) -{ - cpVect center = cpvmult(cpvadd(a, b), 1.0f / 2.0f); - cpFloat length = cpvlength(cpvsub(b, a)); - cpFloat mass = length / 160.0f; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, mass * length * length / 12.0f)); - cpBodySetPosition(body, center); - - cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpvsub(a, center), cpvsub(b, center), 10.0f)); - cpShapeSetFilter(shape, cpShapeFilterNew(group, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - return body; -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpBody* staticBody = cpSpaceGetStaticBody(space); - - cpBody* body1 = add_bar(space, cpv(-240, 160), cpv(-160, 80), 1); - cpBody* body2 = add_bar(space, cpv(-160, 80), cpv(-80, 160), 1); - cpBody* body3 = add_bar(space, cpv(0, 160), cpv(80, 0), 0); - cpBody* body4 = add_bar(space, cpv(160, 160), cpv(240, 160), 0); - cpBody* body5 = add_bar(space, cpv(-240, 0), cpv(-160, -80), 2); - cpBody* body6 = add_bar(space, cpv(-160, -80), cpv(-80, 0), 2); - cpBody* body7 = add_bar(space, cpv(-80, 0), cpv(0, 0), 2); - cpBody* body8 = add_bar(space, cpv(0, -80), cpv(80, -80), 0); - cpBody* body9 = add_bar(space, cpv(240, 80), cpv(160, 0), 3); - cpBody* body10 = add_bar(space, cpv(160, 0), cpv(240, -80), 3); - cpBody* body11 = add_bar(space, cpv(-240, -80), cpv(-160, -160), 4); - cpBody* body12 = add_bar(space, cpv(-160, -160), cpv(-80, -160), 4); - cpBody* body13 = add_bar(space, cpv(0, -160), cpv(80, -160), 0); - cpBody* body14 = add_bar(space, cpv(160, -160), cpv(240, -160), 0); - - cpSpaceAddConstraint(space, cpPivotJointNew2(body1, body2, cpv(40, -40), cpv(-40, -40))); - cpSpaceAddConstraint(space, cpPivotJointNew2(body5, body6, cpv(40, -40), cpv(-40, -40))); - cpSpaceAddConstraint(space, cpPivotJointNew2(body6, body7, cpv(40, 40), cpv(-40, 0))); - cpSpaceAddConstraint(space, cpPivotJointNew2(body9, body10, cpv(-40, -40), cpv(-40, 40))); - cpSpaceAddConstraint(space, cpPivotJointNew2(body11, body12, cpv(40, -40), cpv(-40, 0))); - - cpFloat stiff = 100.0f; - cpFloat damp = 0.5f; - cpSpaceAddConstraint(space, new_spring(staticBody, body1, cpv(-320, 240), cpv(-40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body1, cpv(-320, 80), cpv(-40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body1, cpv(-160, 240), cpv(-40, 40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body2, cpv(-160, 240), cpv(40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body2, cpv(0, 240), cpv(40, 40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body3, cpv(80, 240), cpv(-40, 80), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body4, cpv(80, 240), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body4, cpv(320, 240), cpv(40, 0), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body5, cpv(-320, 80), cpv(-40, 40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body9, cpv(320, 80), cpv(40, 40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body10, cpv(320, 0), cpv(40, -40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body10, cpv(320, -160), cpv(40, -40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body11, cpv(-320, -160), cpv(-40, 40), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body12, cpv(-240, -240), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body12, cpv(0, -240), cpv(40, 0), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body13, cpv(0, -240), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body13, cpv(80, -240), cpv(40, 0), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv(80, -240), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv(240, -240), cpv(40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(staticBody, body14, cpv(320, -160), cpv(40, 0), 0.0f, stiff, damp)); - - cpSpaceAddConstraint(space, new_spring(body1, body5, cpv(40, -40), cpv(-40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body1, body6, cpv(40, -40), cpv(40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body2, body3, cpv(40, 40), cpv(-40, 80), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body4, cpv(-40, 80), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body4, cpv(40, -80), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body7, cpv(40, -80), cpv(40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body7, cpv(-40, 80), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body8, cpv(40, -80), cpv(40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body3, body9, cpv(40, -80), cpv(-40, -40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body4, body9, cpv(40, 0), cpv(40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body5, body11, cpv(-40, 40), cpv(-40, 40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body5, body11, cpv(40, -40), cpv(40, -40), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body7, body8, cpv(40, 0), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body8, body12, cpv(-40, 0), cpv(40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body8, body13, cpv(-40, 0), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body8, body13, cpv(40, 0), cpv(40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body8, body14, cpv(40, 0), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body10, body14, cpv(40, -40), cpv(-40, 0), 0.0f, stiff, damp)); - cpSpaceAddConstraint(space, new_spring(body10, body14, cpv(40, -40), cpv(-40, 0), 0.0f, stiff, damp)); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Springies = { - "Springies", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Sticky.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Sticky.cpp deleted file mode 100644 index f7545afdbf17..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Sticky.cpp +++ /dev/null @@ -1,190 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -enum -{ - COLLISION_TYPE_STICKY = 1, -}; - -#define STICK_SENSOR_THICKNESS 2.5f - -static void PostStepAddJoint(cpSpace* space, void* key, void* data) -{ - // printf("Adding joint for %p\n", data); - - cpConstraint* joint = (cpConstraint*)key; - cpSpaceAddConstraint(space, joint); -} - -static cpBool StickyPreSolve(cpArbiter* arb, cpSpace* space, void* data) -{ - // We want to fudge the collisions a bit to allow shapes to overlap more. - // This simulates their squishy sticky surface, and more importantly - // keeps them from separating and destroying the joint. - - // Track the deepest collision point and use that to determine if a rigid collision should occur. - cpFloat deepest = INFINITY; - - // Grab the contact set and iterate over them. - cpContactPointSet contacts = cpArbiterGetContactPointSet(arb); - for (int i = 0; i < contacts.count; i++) - { - // Sink the contact points into the surface of each shape. - contacts.points[i].pointA = cpvsub(contacts.points[i].pointA, cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); - contacts.points[i].pointB = cpvadd(contacts.points[i].pointB, cpvmult(contacts.normal, STICK_SENSOR_THICKNESS)); - deepest = cpfmin(deepest, contacts.points[i].distance); // + 2.0f*STICK_SENSOR_THICKNESS); - } - - // Set the new contact point data. - cpArbiterSetContactPointSet(arb, &contacts); - - // If the shapes are overlapping enough, then create a - // joint that sticks them together at the first contact point. - if (!cpArbiterGetUserData(arb) && deepest <= 0.0f) - { - CP_ARBITER_GET_BODIES(arb, bodyA, bodyB); - - // Create a joint at the contact point to hold the body in place. - cpVect anchorA = cpBodyWorldToLocal(bodyA, contacts.points[0].pointA); - cpVect anchorB = cpBodyWorldToLocal(bodyB, contacts.points[0].pointB); - cpConstraint* joint = cpPivotJointNew2(bodyA, bodyB, anchorA, anchorB); - - // Give it a finite force for the stickyness. - cpConstraintSetMaxForce(joint, 3e3); - - // Schedule a post-step() callback to add the joint. - cpSpaceAddPostStepCallback(space, PostStepAddJoint, joint, NULL); - - // Store the joint on the arbiter so we can remove it later. - cpArbiterSetUserData(arb, joint); - } - - // Position correction and velocity are handled separately so changing - // the overlap distance alone won't prevent the collision from occuring. - // Explicitly the collision for this frame if the shapes don't overlap using the new distance. - return (deepest <= 0.0f); - - // Lots more that you could improve upon here as well: - // * Modify the joint over time to make it plastic. - // * Modify the joint in the post-step to make it conditionally plastic (like clay). - // * Track a joint for the deepest contact point instead of the first. - // * Track a joint for each contact point. (more complicated since you only get one data pointer). -} - -static void PostStepRemoveJoint(cpSpace* space, void* key, void* data) -{ - // printf("Removing joint for %p\n", data); - - cpConstraint* joint = (cpConstraint*)key; - cpSpaceRemoveConstraint(space, joint); - cpConstraintFree(joint); -} - -static void StickySeparate(cpArbiter* arb, cpSpace* space, void* data) -{ - cpConstraint* joint = (cpConstraint*)cpArbiterGetUserData(arb); - - if (joint) - { - // The joint won't be removed until the step is done. - // Need to disable it so that it won't apply itself. - // Setting the force to 0 will do just that - cpConstraintSetMaxForce(joint, 0.0f); - - // Perform the removal in a post-step() callback. - cpSpaceAddPostStepCallback(space, PostStepRemoveJoint, joint, NULL); - - // NULL out the reference to the joint. - // Not required, but it's a good practice. - cpArbiterSetUserData(arb, NULL); - } -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Sticky collisions using the cpArbiter data pointer."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 10); - cpSpaceSetGravity(space, cpv(0, -1000)); - cpSpaceSetCollisionSlop(space, 2.0); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-340, -260), cpv(-340, 260), 20.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(340, -260), cpv(340, 260), 20.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-340, -260), cpv(340, -260), 20.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-340, 260), cpv(340, 260), 20.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - for (int i = 0; i < 200; i++) - { - cpFloat mass = 0.15f; - cpFloat radius = 10.0f; - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0f, radius, cpvzero))); - cpBodySetPosition(body, cpv(cpflerp(-150.0f, 150.0f, frand()), cpflerp(-150.0f, 150.0f, frand()))); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius + STICK_SENSOR_THICKNESS, cpvzero)); - cpShapeSetFriction(shape, 0.9f); - cpShapeSetCollisionType(shape, COLLISION_TYPE_STICKY); - } - - cpCollisionHandler* handler = cpSpaceAddWildcardHandler(space, COLLISION_TYPE_STICKY); - handler->preSolveFunc = StickyPreSolve; - handler->separateFunc = StickySeparate; - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Sticky = { - "Sticky Surfaces", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tank.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tank.cpp deleted file mode 100644 index 3b5d1d41b417..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tank.cpp +++ /dev/null @@ -1,132 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody *tankBody, *tankControlBody; - -static void update(cpSpace* space, double dt) -{ - // turn the control body based on the angle relative to the actual body - cpVect mouseDelta = cpvsub(ChipmunkDemoMouse, cpBodyGetPosition(tankBody)); - cpFloat turn = cpvtoangle(cpvunrotate(cpBodyGetRotation(tankBody), mouseDelta)); - cpBodySetAngle(tankControlBody, cpBodyGetAngle(tankBody) - turn); - - // drive the tank towards the mouse - if (cpvnear(ChipmunkDemoMouse, cpBodyGetPosition(tankBody), 30.0)) - { - cpBodySetVelocity(tankControlBody, cpvzero); // stop - } - else - { - cpFloat direction = (cpvdot(mouseDelta, cpBodyGetRotation(tankBody)) > 0.0 ? 1.0 : -1.0); - cpBodySetVelocity(tankControlBody, cpvrotate(cpBodyGetRotation(tankBody), cpv(30.0f * direction, 0.0f))); - } - - cpSpaceStep(space, dt); -} - -static cpBody* add_box(cpSpace* space, cpFloat size, cpFloat mass) -{ - cpFloat radius = cpvlength(cpv(size, size)); - - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, size, size))); - cpBodySetPosition( - body, cpv(frand() * (640 - 2 * radius) - (320 - radius), frand() * (480 - 2 * radius) - (240 - radius))); - - cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(body, size, size, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); - - return body; -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Use the mouse to drive the tank, it will follow the cursor."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 10); - cpSpaceSetSleepTimeThreshold(space, 0.5f); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, 240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - for (int i = 0; i < 50; i++) - { - cpBody* body = add_box(space, 20, 1); - - cpConstraint* pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(staticBody, body, cpvzero, cpvzero)); - cpConstraintSetMaxBias(pivot, 0); // disable joint correction - cpConstraintSetMaxForce(pivot, 1000.0f); // emulate linear friction - - cpConstraint* gear = cpSpaceAddConstraint(space, cpGearJointNew(staticBody, body, 0.0f, 1.0f)); - cpConstraintSetMaxBias(gear, 0); // disable joint correction - cpConstraintSetMaxForce(gear, 5000.0f); // emulate angular friction - } - - // We joint the tank to the control body and control the tank indirectly by modifying the control body. - tankControlBody = cpSpaceAddBody(space, cpBodyNewKinematic()); - tankBody = add_box(space, 30, 10); - - cpConstraint* pivot = cpSpaceAddConstraint(space, cpPivotJointNew2(tankControlBody, tankBody, cpvzero, cpvzero)); - cpConstraintSetMaxBias(pivot, 0); // disable joint correction - cpConstraintSetMaxForce(pivot, 10000.0f); // emulate linear friction - - cpConstraint* gear = cpSpaceAddConstraint(space, cpGearJointNew(tankControlBody, tankBody, 0.0f, 1.0f)); - cpConstraintSetErrorBias(gear, 0); // attempt to fully correct the joint each step - cpConstraintSetMaxBias(gear, 1.2f); // but limit it's angular correction rate - cpConstraintSetMaxForce(gear, 50000.0f); // emulate angular friction - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Tank = { - "Tank", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/TheoJansen.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/TheoJansen.cpp deleted file mode 100644 index 7888cf861cab..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/TheoJansen.cpp +++ /dev/null @@ -1,163 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -/* - * The previous WalkBot demo I designed was fairly disappointing, so I implemented - * the mechanism that Theo Jansen uses in his kinetic sculptures. Brilliant. - * Read more here: http://en.wikipedia.org/wiki/Theo_Jansen - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpConstraint* motor; - -static void update(cpSpace* space, double dt) -{ - cpFloat coef = (2.0f + ChipmunkDemoKeyboard.y) / 3.0f; - cpFloat rate = ChipmunkDemoKeyboard.x * 10.0f * coef; - - cpSimpleMotorSetRate(motor, rate); - cpConstraintSetMaxForce(motor, (rate) ? 100000.0f : 0.0f); - - cpSpaceStep(space, dt); -} - -static cpFloat seg_radius = 3.0f; - -static void make_leg(cpSpace* space, cpFloat side, cpFloat offset, cpBody* chassis, cpBody* crank, cpVect anchor) -{ - cpVect a, b; - cpShape* shape; - - cpFloat leg_mass = 1.0f; - - // make leg - a = cpvzero, b = cpv(0.0f, side); - cpBody* upper_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f))); - cpBodySetPosition(upper_leg, cpv(offset, 0.0f)); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(upper_leg, a, b, seg_radius)); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - cpSpaceAddConstraint(space, cpPivotJointNew2(chassis, upper_leg, cpv(offset, 0.0f), cpvzero)); - - // lower leg - a = cpvzero, b = cpv(0.0f, -1.0f * side); - cpBody* lower_leg = cpSpaceAddBody(space, cpBodyNew(leg_mass, cpMomentForSegment(leg_mass, a, b, 0.0f))); - cpBodySetPosition(lower_leg, cpv(offset, -side)); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(lower_leg, a, b, seg_radius)); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(lower_leg, seg_radius * 2.0f, b)); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 1.0f); - - cpSpaceAddConstraint(space, cpPinJointNew(chassis, lower_leg, cpv(offset, 0.0f), cpvzero)); - - cpSpaceAddConstraint(space, cpGearJointNew(upper_leg, lower_leg, 0.0f, 1.0f)); - - cpConstraint* constraint; - cpFloat diag = cpfsqrt(side * side + offset * offset); - - constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, upper_leg, anchor, cpv(0.0f, side))); - cpPinJointSetDist(constraint, diag); - - constraint = cpSpaceAddConstraint(space, cpPinJointNew(crank, lower_leg, anchor, cpvzero)); - cpPinJointSetDist(constraint, diag); -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = "Use the arrow keys to control the machine."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 20); - cpSpaceSetGravity(space, cpv(0, -500)); - - cpBody* staticBody = cpSpaceGetStaticBody(space); - cpShape* shape; - cpVect a, b; - - // Create segments around the edge of the screen. - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(-320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(320, -240), cpv(320, 240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-320, -240), cpv(320, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat offset = 30.0f; - - // make chassis - cpFloat chassis_mass = 2.0f; - a = cpv(-offset, 0.0f), b = cpv(offset, 0.0f); - cpBody* chassis = cpSpaceAddBody(space, cpBodyNew(chassis_mass, cpMomentForSegment(chassis_mass, a, b, 0.0f))); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(chassis, a, b, seg_radius)); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - // make crank - cpFloat crank_mass = 1.0f; - cpFloat crank_radius = 13.0f; - cpBody* crank = - cpSpaceAddBody(space, cpBodyNew(crank_mass, cpMomentForCircle(crank_mass, crank_radius, 0.0f, cpvzero))); - - shape = cpSpaceAddShape(space, cpCircleShapeNew(crank, crank_radius, cpvzero)); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - cpSpaceAddConstraint(space, cpPivotJointNew2(chassis, crank, cpvzero, cpvzero)); - - cpFloat side = 30.0f; - - int num_legs = 2; - for (int i = 0; i < num_legs; i++) - { - make_leg(space, side, offset, chassis, crank, - cpvmult(cpvforangle((cpFloat)(2 * i + 0) / (cpFloat)num_legs * CP_PI), crank_radius)); - make_leg(space, side, -offset, chassis, crank, - cpvmult(cpvforangle((cpFloat)(2 * i + 1) / (cpFloat)num_legs * CP_PI), crank_radius)); - } - - motor = cpSpaceAddConstraint(space, cpSimpleMotorNew(chassis, crank, 6.0f)); - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo TheoJansen = { - "Theo Jansen Machine", 1.0 / 180.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tumble.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tumble.cpp deleted file mode 100644 index 21f89814cd47..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Tumble.cpp +++ /dev/null @@ -1,142 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody* KinematicBoxBody; - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static void AddBox(cpSpace* space, cpVect pos, cpFloat mass, cpFloat width, cpFloat height) -{ - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); - cpBodySetPosition(body, pos); - - cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(body, width, height, 0.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); -} - -static void AddSegment(cpSpace* space, cpVect pos, cpFloat mass, cpFloat width, cpFloat height) -{ - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); - cpBodySetPosition(body, pos); - - cpShape* shape = cpSpaceAddShape(space, cpSegmentShapeNew(body, cpv(0.0, (height - width) / 2.0), - cpv(0.0, (width - height) / 2.0), width / 2.0)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); -} - -static void AddCircle(cpSpace* space, cpVect pos, cpFloat mass, cpFloat radius) -{ - cpBody* body = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForCircle(mass, 0.0, radius, cpvzero))); - cpBodySetPosition(body, pos); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(body, radius, cpvzero)); - cpShapeSetElasticity(shape, 0.0f); - cpShapeSetFriction(shape, 0.7f); -} - -static cpSpace* init(void) -{ - cpSpace* space = cpSpaceNew(); - cpSpaceSetGravity(space, cpv(0, -600)); - - cpShape* shape; - - // We create an infinite mass rogue body to attach the line segments too - // This way we can control the rotation however we want. - KinematicBoxBody = cpSpaceAddBody(space, cpBodyNewKinematic()); - cpBodySetAngularVelocity(KinematicBoxBody, 0.4f); - - // Set up the static box. - cpVect a = cpv(-200, -200); - cpVect b = cpv(-200, 200); - cpVect c = cpv(200, 200); - cpVect d = cpv(200, -200); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(KinematicBoxBody, a, b, 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(KinematicBoxBody, b, c, 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(KinematicBoxBody, c, d, 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(KinematicBoxBody, d, a, 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - cpFloat mass = 1; - cpFloat width = 30; - cpFloat height = width * 2; - - // Add the bricks. - for (int i = 0; i < 7; i++) - { - for (int j = 0; j < 3; j++) - { - cpVect pos = cpv(i * width - 150, j * height - 150); - - int type = (rand() % 3000) / 1000; - if (type == 0) - { - AddBox(space, pos, mass, width, height); - } - else if (type == 1) - { - AddSegment(space, pos, mass, width, height); - } - else - { - AddCircle(space, cpvadd(pos, cpv(0.0, (height - width) / 2.0)), mass, width / 2.0); - AddCircle(space, cpvadd(pos, cpv(0.0, (width - height) / 2.0)), mass, width / 2.0); - } - } - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Tumble = { - "Tumble", - 1.0 / 60.0, // faster as the original (more action) - init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Unicycle.cpp b/tests/cpp-tests/Source/ChipmunkTestBed/demo/Unicycle.cpp deleted file mode 100644 index f40481c13a56..000000000000 --- a/tests/cpp-tests/Source/ChipmunkTestBed/demo/Unicycle.cpp +++ /dev/null @@ -1,171 +0,0 @@ -/* Copyright (c) 2007 Scott Lembcke - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - */ - -#include "chipmunk/chipmunk.h" -#include "ChipmunkDemo.h" - -static cpBody* balance_body; -static cpFloat balance_sin = 0.0; -// static cpFloat last_v = 0.0; - -static cpBody* wheel_body; -static cpConstraint* motor; - -/* - TODO: - - Clamp max angle dynamically based on output torque. -*/ - -static inline cpFloat bias_coef(cpFloat errorBias, cpFloat dt) -{ - return 1.0f - cpfpow(errorBias, dt); -} - -static void motor_preSolve(cpConstraint* motor, cpSpace* space) -{ - cpFloat dt = cpSpaceGetCurrentTimeStep(space); - - cpFloat target_x = ChipmunkDemoMouse.x; - ChipmunkDebugDrawSegment(cpv(target_x, -1000.0), cpv(target_x, 1000.0), RGBAColor(1.0, 0.0, 0.0, 1.0)); - - cpFloat max_v = 500.0; - cpFloat target_v = - cpfclamp(bias_coef(0.5, dt / 1.2) * (target_x - cpBodyGetPosition(balance_body).x) / dt, -max_v, max_v); - cpFloat error_v = (target_v - cpBodyGetVelocity(balance_body).x); - cpFloat target_sin = 3.0e-3 * bias_coef(0.1, dt) * error_v / dt; - - cpFloat max_sin = cpfsin(0.6); - balance_sin = cpfclamp(balance_sin - 6.0e-5 * bias_coef(0.2, dt) * error_v / dt, -max_sin, max_sin); - cpFloat target_a = asin(cpfclamp(-target_sin + balance_sin, -max_sin, max_sin)); - cpFloat angular_diff = asin(cpvcross(cpBodyGetRotation(balance_body), cpvforangle(target_a))); - cpFloat target_w = bias_coef(0.1, dt / 0.4) * (angular_diff) / dt; - - cpFloat max_rate = 50.0; - cpFloat rate = cpfclamp(cpBodyGetAngularVelocity(wheel_body) + cpBodyGetAngularVelocity(balance_body) - target_w, - -max_rate, max_rate); - cpSimpleMotorSetRate(motor, cpfclamp(rate, -max_rate, max_rate)); - cpConstraintSetMaxForce(motor, 8.0e4); -} - -static void update(cpSpace* space, double dt) -{ - cpSpaceStep(space, dt); -} - -static cpSpace* init(void) -{ - ChipmunkDemoMessageString = - "This unicycle is completely driven and balanced by a single cpSimpleMotor.\nMove the mouse to make the " - "unicycle follow it."; - - cpSpace* space = cpSpaceNew(); - cpSpaceSetIterations(space, 30); - cpSpaceSetGravity(space, cpv(0, -500)); - - { - cpShape* shape = NULL; - cpBody* staticBody = cpSpaceGetStaticBody(space); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-3200, -240), cpv(3200, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(0, -200), cpv(240, -240), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - - shape = cpSpaceAddShape(space, cpSegmentShapeNew(staticBody, cpv(-240, -240), cpv(0, -200), 0.0f)); - cpShapeSetElasticity(shape, 1.0f); - cpShapeSetFriction(shape, 1.0f); - cpShapeSetFilter(shape, NOT_GRABBABLE_FILTER); - } - - { - cpFloat radius = 20.0; - cpFloat mass = 1.0; - - cpFloat moment = cpMomentForCircle(mass, 0.0, radius, cpvzero); - wheel_body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(wheel_body, cpv(0.0, -160.0 + radius)); - - cpShape* shape = cpSpaceAddShape(space, cpCircleShapeNew(wheel_body, radius, cpvzero)); - cpShapeSetFriction(shape, 0.7); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - } - - { - cpFloat cog_offset = 30.0; - - cpBB bb1 = cpBBNew(-5.0, 0.0 - cog_offset, 5.0, cog_offset * 1.2 - cog_offset); - cpBB bb2 = cpBBNew(-25.0, bb1.t, 25.0, bb1.t + 10.0); - - cpFloat mass = 3.0; - cpFloat moment = cpMomentForBox2(mass, bb1) + cpMomentForBox2(mass, bb2); - - balance_body = cpSpaceAddBody(space, cpBodyNew(mass, moment)); - cpBodySetPosition(balance_body, cpv(0.0, cpBodyGetPosition(wheel_body).y + cog_offset)); - - cpShape* shape = NULL; - - shape = cpSpaceAddShape(space, cpBoxShapeNew2(balance_body, bb1, 0.0)); - cpShapeSetFriction(shape, 1.0); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - - shape = cpSpaceAddShape(space, cpBoxShapeNew2(balance_body, bb2, 0.0)); - cpShapeSetFriction(shape, 1.0); - cpShapeSetFilter(shape, cpShapeFilterNew(1, CP_ALL_CATEGORIES, CP_ALL_CATEGORIES)); - } - - cpVect anchorA = cpBodyWorldToLocal(balance_body, cpBodyGetPosition(wheel_body)); - cpVect groove_a = cpvadd(anchorA, cpv(0.0, 30.0)); - cpVect groove_b = cpvadd(anchorA, cpv(0.0, -10.0)); - cpSpaceAddConstraint(space, cpGrooveJointNew(balance_body, wheel_body, groove_a, groove_b, cpvzero)); - cpSpaceAddConstraint(space, cpDampedSpringNew(balance_body, wheel_body, anchorA, cpvzero, 0.0, 6.0e2, 30.0)); - - motor = cpSpaceAddConstraint(space, cpSimpleMotorNew(wheel_body, balance_body, 0.0)); - cpConstraintSetPreSolveFunc(motor, motor_preSolve); - - { - cpFloat width = 100.0; - cpFloat height = 20.0; - cpFloat mass = 3.0; - - cpBody* boxBody = cpSpaceAddBody(space, cpBodyNew(mass, cpMomentForBox(mass, width, height))); - cpBodySetPosition(boxBody, cpv(200, -100)); - - cpShape* shape = cpSpaceAddShape(space, cpBoxShapeNew(boxBody, width, height, 0.0)); - cpShapeSetFriction(shape, 0.7); - } - - return space; -} - -static void destroy(cpSpace* space) -{ - ChipmunkDemoFreeSpaceChildren(space); - cpSpaceFree(space); -} - -ChipmunkDemo Unicycle = { - "Unicycle", 1.0 / 60.0, init, update, ChipmunkDemoDefaultDrawImpl, destroy, -}; diff --git a/tests/cpp-tests/Source/ClickAndMoveTest/ClickAndMoveTest.cpp b/tests/cpp-tests/Source/ClickAndMoveTest/ClickAndMoveTest.cpp index 7e5fc4282040..5f8571b3a5bb 100644 --- a/tests/cpp-tests/Source/ClickAndMoveTest/ClickAndMoveTest.cpp +++ b/tests/cpp-tests/Source/ClickAndMoveTest/ClickAndMoveTest.cpp @@ -46,7 +46,7 @@ ClickAndMoveTestCase::ClickAndMoveTestCase() auto sprite = Sprite::create(s_pathGrossini); - auto layer = LayerColor::create(Color4B(255, 255, 0, 255)); + auto layer = LayerColor::create(Color32(255, 255, 0, 255)); addChild(layer, -1); addChild(sprite, 0, kTagSprite); diff --git a/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.cpp b/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.cpp index 738f2ab7e9c5..1c33f4e0b003 100644 --- a/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.cpp +++ b/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.cpp @@ -32,9 +32,9 @@ #include "ClippingNodeTest.h" #include "../testResource.h" -#include "renderer/Renderer.h" -#include "renderer/backend/ProgramState.h" -#include "renderer/Shaders.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/rhi/ProgramState.h" +#include "axmol/renderer/Shaders.h" using namespace ax; @@ -152,7 +152,7 @@ DrawNode* BasicTest::shape() triangle[1] = Vec2(100, -100); triangle[2] = Vec2(0, 100); - static Color4F green(0, 1, 0, 1); + static Color green(0, 1, 0, 1); shape->drawPolygon(triangle, 3, green, 0, green); return shape; } @@ -464,7 +464,7 @@ void ScrollViewDemo::setup() rectangle[2] = Vec2(clipper->getContentSize().width, clipper->getContentSize().height); rectangle[3] = Vec2(0.0f, clipper->getContentSize().height); - Color4F white(1, 1, 1, 1); + Color white(1, 1, 1, 1); stencil->drawPolygon(rectangle, 4, white, 1, white); clipper->setStencil(stencil); @@ -564,8 +564,8 @@ void RawStencilBufferTest::initCommands() // _disableStencilCallback.func = [=]() { renderer->setStencilTest(false); }; // _disableStencilCallback.init(_globalZOrder); - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_UCOLOR); - _programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_UCOLOR); + _programState = new rhi::ProgramState(program); _locColor = _programState->getProgram()->getUniformLocation("u_color"); _locMVPMatrix = _programState->getProgram()->getUniformLocation("u_MVPMatrix"); const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); @@ -576,8 +576,8 @@ void RawStencilBufferTest::initCommands() auto winPoint = Vec2(Director::getInstance()->getWinSize()); auto planeSize = winPoint * (1.0 / _planeCount); BlendFunc blend; - blend.src = backend::BlendFactor::ONE; - blend.dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blend.src = rhi::BlendFactor::ONE; + blend.dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; for (int i = 0, cmdIndex = 0; i < _planeCount; i++) { auto stencilPoint = planeSize * (_planeCount - i); @@ -589,22 +589,22 @@ void RawStencilBufferTest::initCommands() cmd.setBeforeCallback(AX_CALLBACK_0(RawStencilBufferTest::onBeforeDrawClip, this, i)); Vec2 vertices[] = {Vec2::ZERO, Vec2(stencilPoint.x, 0.0f), stencilPoint, Vec2(0.0f, stencilPoint.y)}; unsigned short indices[] = {0, 2, 1, 0, 3, 2}; - cmd.createVertexBuffer(sizeof(Vec2), 4, backend::BufferUsage::STATIC); + cmd.createVertexBuffer(sizeof(Vec2), 4, rhi::BufferUsage::STATIC); cmd.updateVertexBuffer(vertices, sizeof(vertices)); - cmd.createIndexBuffer(backend::IndexFormat::U_SHORT, 6, backend::BufferUsage::STATIC); + cmd.createIndexBuffer(rhi::IndexFormat::U_SHORT, 6, rhi::BufferUsage::STATIC); cmd.updateIndexBuffer(indices, sizeof(indices)); - cmd.getPipelineDescriptor().programState = _programState; + cmd.getPipelineDesc().programState = _programState; auto& cmd2 = _renderCmds[cmdIndex]; cmdIndex++; cmd2.init(_globalZOrder, blend); cmd2.setBeforeCallback(AX_CALLBACK_0(RawStencilBufferTest::onBeforeDrawSprite, this, i)); Vec2 vertices2[] = {Vec2::ZERO, Vec2(winPoint.x, 0.0f), winPoint, Vec2(0.0f, winPoint.y)}; - cmd2.createVertexBuffer(sizeof(Vec2), 4, backend::BufferUsage::STATIC); + cmd2.createVertexBuffer(sizeof(Vec2), 4, rhi::BufferUsage::STATIC); cmd2.updateVertexBuffer(vertices2, sizeof(vertices2)); - cmd2.createIndexBuffer(backend::IndexFormat::U_SHORT, 6, backend::BufferUsage::STATIC); + cmd2.createIndexBuffer(rhi::IndexFormat::U_SHORT, 6, rhi::BufferUsage::STATIC); cmd2.updateIndexBuffer(indices, sizeof(indices)); - cmd2.getPipelineDescriptor().programState = _programState; + cmd2.getPipelineDesc().programState = _programState; } } @@ -623,7 +623,7 @@ void RawStencilBufferTest::draw(Renderer* renderer, const Mat4& transform, uint3 _sprites.at(i)->setPosition(spritePoint); _spritesStencil.at(i)->setPosition(spritePoint); - renderer->clear(ClearFlag::STENCIL, Color4F::BLACK, 0.f, 0x0, _globalZOrder); + renderer->clear(ClearFlag::STENCIL, Color::BLACK, 0.f, 0x0, _globalZOrder); renderer->addCommand(&_renderCmds[cmdIndex]); cmdIndex++; @@ -667,18 +667,18 @@ void RawStencilBufferTest::setupStencilForClippingOnPlane(int plane) auto renderer = Director::getInstance()->getRenderer(); unsigned int planeMask = 0x1 << plane; renderer->setStencilWriteMask(planeMask); - renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, planeMask, planeMask); - renderer->setStencilOperation(backend::StencilOperation::REPLACE, backend::StencilOperation::KEEP, - backend::StencilOperation::KEEP); + renderer->setStencilCompareFunc(rhi::CompareFunc::NEVER, planeMask, planeMask); + renderer->setStencilOp(rhi::StencilOp::REPLACE, rhi::StencilOp::KEEP, + rhi::StencilOp::KEEP); } void RawStencilBufferTest::setupStencilForDrawingOnPlane(int plane) { auto renderer = Director::getInstance()->getRenderer(); unsigned int planeMask = 0x1 << plane; - renderer->setStencilCompareFunction(backend::CompareFunction::EQUAL, planeMask, planeMask); - renderer->setStencilOperation(backend::StencilOperation::KEEP, backend::StencilOperation::KEEP, - backend::StencilOperation::KEEP); + renderer->setStencilCompareFunc(rhi::CompareFunc::EQUAL, planeMask, planeMask); + renderer->setStencilOp(rhi::StencilOp::KEEP, rhi::StencilOp::KEEP, + rhi::StencilOp::KEEP); } //@implementation RawStencilBufferTest2 @@ -726,8 +726,8 @@ void RawStencilBufferTestAlphaTest::setup() RawStencilBufferTest::setup(); for (int i = 0; i < _planeCount; ++i) { - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); - auto programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR_ALPHA_TEST); + auto programState = new rhi::ProgramState(program); programState->setUniform(programState->getUniformLocation("u_alpha_value"), &_alphaThreshold, sizeof(_alphaThreshold)); _spritesStencil.at(i)->setProgramState(programState); @@ -792,9 +792,9 @@ void RawStencilBufferTest6::setupStencilForClippingOnPlane(int plane) { int planeMask = 0x1 << plane; auto renderer = Director::getInstance()->getRenderer(); - renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, planeMask, planeMask); - renderer->setStencilOperation(backend::StencilOperation::REPLACE, backend::StencilOperation::KEEP, - backend::StencilOperation::KEEP); + renderer->setStencilCompareFunc(rhi::CompareFunc::NEVER, planeMask, planeMask); + renderer->setStencilOp(rhi::StencilOp::REPLACE, rhi::StencilOp::KEEP, + rhi::StencilOp::KEEP); renderer->setDepthTest(false); renderer->setDepthWrite(false); } @@ -870,7 +870,7 @@ void ClippingToRenderTextureTest::expectedBehaviour() triangle[0] = Point(-50, -50); triangle[1] = Point(50, -50); triangle[2] = Point(0, 50); - Color4F green(0, 1, 0, 1); + Color green(0, 1, 0, 1); stencil->drawPolygon(triangle, 3, green, 0, green); auto clipper = ClippingNode::create(); @@ -884,7 +884,7 @@ void ClippingToRenderTextureTest::expectedBehaviour() triangle[0] = Point(-200, -200); triangle[1] = Point(200, -200); triangle[2] = Point(0, 200); - Color4F red(1, 0, 0, 1); + Color red(1, 0, 0, 1); img->drawPolygon(triangle, 3, red, 0, red); clipper->addChild(img); } @@ -913,7 +913,7 @@ void ClippingToRenderTextureTest::reproduceBug() triangle[0] = Point(-50, -50); triangle[1] = Point(50, -50); triangle[2] = Point(0, 50); - Color4F green(0, 1, 0, 1); + Color green(0, 1, 0, 1); stencil->drawPolygon(triangle, 3, green, 0, green); auto clipper = ClippingNode::create(); @@ -927,14 +927,14 @@ void ClippingToRenderTextureTest::reproduceBug() triangle[0] = Point(-200, -200); triangle[1] = Point(200, -200); triangle[2] = Point(0, 200); - Color4F red(1, 0, 0, 1); + Color red(1, 0, 0, 1); img->drawPolygon(triangle, 3, red, 0, red); clipper->addChild(img); // container rendered on Texture the size of the screen and because Clipping node use stencil buffer so we need to // create RenderTexture with depthStencil format parameter RenderTexture* rt = - RenderTexture::create(visibleSize.width, visibleSize.height, backend::PixelFormat::RGBA8, PixelFormat::D24S8); + RenderTexture::create(visibleSize.width, visibleSize.height, rhi::PixelFormat::RGBA8, PixelFormat::D24S8); rt->setPosition(visibleSize.width / 2, visibleSize.height / 2); this->addChild(rt); @@ -987,10 +987,10 @@ void ClippingNodePerformanceTest::setup() auto s = Director::getInstance()->getWinSize(); auto countLabel = Label::createWithTTF("0", "fonts/arial.ttf", 30); - countLabel->enableOutline(Color4B(0, 0, 0, 255), 2); + countLabel->enableOutline(Color32(0, 0, 0, 255), 2); countLabel->setPosition(Vec2(s.width / 2, s.height - 120)); addChild(countLabel, 1); - + auto addClippingNode = [this, s, countLabel] (int count) -> void { for (int i = 0; i < count; i++) { Vec2 pos = Vec2(random(0, (int) s.width), random(0, (int) s.height)); @@ -1004,18 +1004,18 @@ void ClippingNodePerformanceTest::setup() auto spriteA = Sprite::create("Images/grossini.png"); clipper->addChild(spriteA); } - + _totalCount += count; countLabel->setString(std::to_string(_totalCount)); }; addClippingNode(100); - + MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); auto increase = MenuItemFont::create(" + ", [=] (Object*) -> void { addClippingNode(10); }); - increase->setColor(Color3B(0, 200, 20)); + increase->setColor(Color32(0, 200, 20)); auto menu = Menu::create(increase, nullptr); menu->setPosition(Vec2(s.width / 2, s.height - 80)); addChild(menu, 1); @@ -1084,14 +1084,14 @@ void UniqueChildStencilTest::addChildStencils() // Child stencil 1 constexpr auto radius = 30.f; auto* drawNode = DrawNode::create(); - drawNode->drawSolidCircle(Vec2(50, 50), radius, 360, 180, 1, 1, Color4B::MAGENTA); + drawNode->drawSolidCircle(Vec2(50, 50), radius, 360, 180, 1, 1, Color::MAGENTA); _parentStencil->addChild(drawNode); // Child stencil 2 drawNode = DrawNode::create(); drawNode->drawSolidRect(Vec2(contentSize.width - 75, contentSize.height - 75), - Vec2(contentSize.width - 25, contentSize.height - 25), Color4B::MAGENTA); + Vec2(contentSize.width - 25, contentSize.height - 25), Color::MAGENTA); _parentStencil->addChild(drawNode); // Child stencil 3 diff --git a/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.h b/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.h index 7f75ea517575..a275ff543f49 100644 --- a/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.h +++ b/tests/cpp-tests/Source/ClippingNodeTest/ClippingNodeTest.h @@ -25,7 +25,7 @@ #pragma once #include "../BaseTest.h" -#include "renderer/CustomCommand.h" +#include "axmol/renderer/CustomCommand.h" #include namespace ax @@ -198,8 +198,8 @@ class RawStencilBufferTest : public BaseClippingNodeTest // ax::CallbackCommand _disableStencilCallback; ax::Vector _sprites; ax::Vector _spritesStencil; - ax::backend::UniformLocation _locColor; - ax::backend::UniformLocation _locMVPMatrix; + ax::rhi::UniformLocation _locColor; + ax::rhi::UniformLocation _locMVPMatrix; }; class RawStencilBufferTest2 : public RawStencilBufferTest @@ -238,7 +238,7 @@ class RawStencilBufferTest4 : public RawStencilBufferTestAlphaTest virtual void setupStencilForDrawingOnPlane(int plane) override; private: - ax::backend::UniformLocation _alphaMVPMatrix; + ax::rhi::UniformLocation _alphaMVPMatrix; }; class RawStencilBufferTest5 : public RawStencilBufferTestAlphaTest diff --git a/tests/cpp-tests/Source/ConfigurationTest/ConfigurationTest.cpp b/tests/cpp-tests/Source/ConfigurationTest/ConfigurationTest.cpp index 600ae7fe03fb..350a75548260 100644 --- a/tests/cpp-tests/Source/ConfigurationTest/ConfigurationTest.cpp +++ b/tests/cpp-tests/Source/ConfigurationTest/ConfigurationTest.cpp @@ -24,7 +24,7 @@ #include "ConfigurationTest.h" #include "../testResource.h" -#include "axmol.h" +#include "axmol/axmol.h" using namespace ax; diff --git a/tests/cpp-tests/Source/CurlTest/CurlTest.cpp b/tests/cpp-tests/Source/CurlTest/CurlTest.cpp index 0d74839dc95d..89db4b6dc592 100644 --- a/tests/cpp-tests/Source/CurlTest/CurlTest.cpp +++ b/tests/cpp-tests/Source/CurlTest/CurlTest.cpp @@ -24,13 +24,13 @@ #if !defined(__EMSCRIPTEN__) -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "CurlTest.h" #include "stdio.h" #include "stdlib.h" #include "curl/curl.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; diff --git a/tests/cpp-tests/Source/CurlTest/CurlTest.h b/tests/cpp-tests/Source/CurlTest/CurlTest.h index 91d950235ad6..40b88960f9da 100644 --- a/tests/cpp-tests/Source/CurlTest/CurlTest.h +++ b/tests/cpp-tests/Source/CurlTest/CurlTest.h @@ -27,7 +27,7 @@ #if !defined(__EMSCRIPTEN__) -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(CurlTests); diff --git a/tests/cpp-tests/Source/CurrentLanguageTest/CurrentLanguageTest.h b/tests/cpp-tests/Source/CurrentLanguageTest/CurrentLanguageTest.h index 297077176f0c..346be2b55fa2 100644 --- a/tests/cpp-tests/Source/CurrentLanguageTest/CurrentLanguageTest.h +++ b/tests/cpp-tests/Source/CurrentLanguageTest/CurrentLanguageTest.h @@ -25,7 +25,7 @@ #ifndef _CURRENT_LANGUAGE_TEST_H_ #define _CURRENT_LANGUAGE_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(CurrentLanguageTests); diff --git a/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.cpp b/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.cpp index 86d9b327da11..8bcc4be1f379 100644 --- a/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.cpp +++ b/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.cpp @@ -24,8 +24,8 @@ THE SOFTWARE. ****************************************************************************/ #include "DrawNodeTest.h" -#include "renderer/Renderer.h" -#include "renderer/CustomCommand.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/renderer/CustomCommand.h" #if defined(_WIN32) # pragma push_macro("TRANSPARENT") @@ -1356,7 +1356,7 @@ DrawNodeTests::DrawNodeTests() DrawNodeBaseTest::DrawNodeBaseTest() { auto director = Director::getInstance(); - director->setClearColor(Color4F(0, 0, 0, 0)); + director->setClearColor(Color::TRANSPARENT); origin = director->getVisibleOrigin(); size = director->getVisibleSize(); @@ -1446,10 +1446,10 @@ void DrawNodeBaseTest::listviewCallback(ax::Object* sender, ax::ui::ListView::Ev auto listview = static_cast(sender); for (auto&& item : listview->getItems()) { - static_cast(item)->setColor(ax::Color3B::WHITE); + static_cast(item)->setColor(ax::Color32::WHITE); } _currentSeletedItemIndex = (int)listview->getCurSelectedIndex(); - listview->getItem(_currentSeletedItemIndex)->setColor(ax::Color3B::RED); + listview->getItem(_currentSeletedItemIndex)->setColor(ax::Color32::RED); } void DrawNodeBaseTest::onChangedRadioButtonSelect(ui::RadioButton* radioButton, ui::RadioButton::EventType type) @@ -1588,7 +1588,7 @@ DrawNodeMorphTest_SolidPolygon::DrawNodeMorphTest_SolidPolygon() addChild(drawNodeArray[n]); drawNodeArray[n]->setPosition( Vec2(AXRANDOM_MINUS1_1() * size.width / 4, AXRANDOM_MINUS1_1() * size.height / 4) + Vec2(100, 100)); - color[n] = Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f); + color[n] = Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f); rad[n] = 90 + AXRANDOM_0_1() * 10; state[n] = (AXRANDOM_0_1() > 0.5f) ? false : true; @@ -1675,7 +1675,7 @@ void DrawNodeMorphTest_SolidPolygon::update(float dt) drawNodeArray[n]->properties.setScale(Vec2(0.5f, 0.5f)); drawNodeArray[n]->drawSolidPolygon(verticesObjMorph[n], segments, color[n], sliderValue[sliderType::Thickness], - Color4B::YELLOW); + Color::YELLOW); } } @@ -1718,7 +1718,7 @@ DrawNodeMorphTest_Polygon::DrawNodeMorphTest_Polygon() addChild(drawNodeArray[n]); drawNodeArray[n]->setPosition( Vec2(AXRANDOM_MINUS1_1() * size.width / 4, AXRANDOM_MINUS1_1() * size.height / 4) + Vec2(100, 100)); - color[n] = Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f); + color[n] = Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f); rad[n] = 90 + AXRANDOM_0_1() * 10; state[n] = (AXRANDOM_0_1() > 0.5f) ? false : true; @@ -1875,7 +1875,7 @@ void DrawNodePictureTest::update(float dt) int sph_la = 0; do { - Color4F color = Color4F(sph_xx[sph_la + 1], sph_yy[sph_la + 1], sph_xx[sph_la + 2], sph_yy[sph_la + 2] * 255); + Color color = Color(sph_xx[sph_la + 1], sph_yy[sph_la + 1], sph_xx[sph_la + 2], sph_yy[sph_la + 2] * 255); Vec2* vertices = new Vec2[(int)(sph_cmb - 3)]; for (int n = 3; n < sph_cmb; n++) { @@ -1888,7 +1888,7 @@ void DrawNodePictureTest::update(float dt) drawNode->properties.setCenter(vertices[0]); drawNode->properties.setRotation(rot); drawNode->drawPolygon(vertices, sph_cmb - 3, color, /*rot*/ 0.f, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), true); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), true); sph_la += sph_cmb; sph_cmb = sph_yy[sph_la]; @@ -1957,9 +1957,9 @@ void DrawNodeJellyFishTest::DrawFrame() CalculatePoint(ii, ii / 235.0, t, px, py); dots[i] = Vec2(px + 150, py + 50); } - drawNode->drawPoints(dots, NUM_POINTS - 1, Color4B::GREEN); + drawNode->drawPoints(dots, NUM_POINTS - 1, Color::GREEN); UpdateJellyPoints(); - drawNode->drawPoints(dots, NUM_POINTS - 1, Color4B::WHITE); + drawNode->drawPoints(dots, NUM_POINTS - 1, Color::WHITE); } @@ -2010,9 +2010,9 @@ void DrawNodeLineDrawTest::update(float dt) float x = radius * cosf(rads) + center.x; float y = radius * sinf(rads) + center.y; - drawNode->drawLine(center - Vec2(20, 40), Vec2(x, y) - Vec2(20, 40), Color4F::RED, sliderValue[sliderType::Thickness]); - drawNode->drawLine(center + Vec2(120, 20), Vec2(x, y) + Vec2(120, 20), Color4F::BLUE, sliderValue[sliderType::Thickness]); - drawNode->drawLine(center - Vec2(130, 110), Vec2(x, y) - Vec2(130, 110), Color4F::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawLine(center - Vec2(20, 40), Vec2(x, y) - Vec2(20, 40), Color::RED, sliderValue[sliderType::Thickness]); + drawNode->drawLine(center + Vec2(120, 20), Vec2(x, y) + Vec2(120, 20), Color::BLUE, sliderValue[sliderType::Thickness]); + drawNode->drawLine(center - Vec2(130, 110), Vec2(x, y) - Vec2(130, 110), Color::GREEN, sliderValue[sliderType::Thickness]); } } @@ -2053,22 +2053,22 @@ void DrawNodeThicknessTest::update(float dt) drawNode->clear(); - drawNode->drawCircle(VisibleRect::center(), 60, AX_DEGREES_TO_RADIANS(77), 30, false, Color4F::GREEN, + drawNode->drawCircle(VisibleRect::center(), 60, AX_DEGREES_TO_RADIANS(77), 30, false, Color::GREEN, sliderValue[sliderType::Thickness]); - drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color4F::YELLOW, + drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color::YELLOW, sliderValue[sliderType::Thickness]); - drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(size.width, size.height - 20), Color4F::YELLOW, + drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(size.width, size.height - 20), Color::YELLOW, sliderValue[sliderType::Thickness]); // drawNode a rectangles - drawNode->drawRect(Vec2(123, 123), Vec2(227, 227), Color4F(1, 1, 0, 1), sliderValue[sliderType::Thickness]); - drawNode->drawRect(Vec2(115, 130), Vec2(130, 115), Vec2(115, 100), Vec2(100, 115), Color4F::MAGENTA, + drawNode->drawRect(Vec2(123, 123), Vec2(227, 227), Color(1, 1, 0, 1), sliderValue[sliderType::Thickness]); + drawNode->drawRect(Vec2(115, 130), Vec2(130, 115), Vec2(115, 100), Vec2(100, 115), Color::MAGENTA, sliderValue[sliderType::Thickness]); - drawNode->drawLine(Vec2(200.0f, size.height - 20), Vec2(size.width - 100, size.height - 20), Color4F::YELLOW, + drawNode->drawLine(Vec2(200.0f, size.height - 20), Vec2(size.width - 100, size.height - 20), Color::YELLOW, sliderValue[sliderType::Thickness]); - drawNode->drawLine(Vec2(300.0f, 100.0f), Vec2(size.width - 200, size.height - 120), Color4F::GREEN, + drawNode->drawLine(Vec2(300.0f, 100.0f), Vec2(size.width - 200, size.height - 120), Color::GREEN, sliderValue[sliderType::Thickness]); Vec2 vertices24[] = { @@ -2086,35 +2086,35 @@ void DrawNodeThicknessTest::update(float dt) {135.250000f, 108.625000f}, {151.000000f, 124.125000f}, {90.500000f, 131.875000f}, {113.250000f, 120.875000f}, {88.000000f, 116.875000f}, {106.000000f, 103.875000f}, {88.000000f, 97.875000f}, }; - drawNode->drawPolygon(vertices24, sizeof(vertices24) / sizeof(vertices24[0]), Color4B::TRANSPARENT, - sliderValue[sliderType::Thickness] / 2, Color4F::RED); + drawNode->drawPolygon(vertices24, sizeof(vertices24) / sizeof(vertices24[0]), Color::TRANSPARENT, + sliderValue[sliderType::Thickness] / 2, Color::RED); // open random color poly Vec2 vertices[] = { Vec2(0.0f, 0.0f), Vec2(50.0f, 50.0f), Vec2(100.0f, 50.0f), Vec2(100.0f, 100.0f), Vec2(50.0f, 100.0f) }; - drawNode->drawPoly(vertices, 5, false, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + drawNode->drawPoly(vertices, 5, false, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness]); // closed random color poly Vec2 vertices2[] = { Vec2(30.0f, 130.0f), Vec2(30.0f, 230.0f), Vec2(50.0f, 200.0f) }; - drawNode->drawPoly(vertices2, 3, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + drawNode->drawPoly(vertices2, 3, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness]); // drawNode some beziers drawNode->drawQuadBezier(Vec2(size.width - 150, size.height - 150), Vec2(size.width - 70, size.height - 10), - Vec2(size.width - 10, size.height - 10), 10, Color4F::BLUE, + Vec2(size.width - 10, size.height - 10), 10, Color::BLUE, sliderValue[sliderType::Thickness]); drawNode->drawQuadBezier(Vec2(0.0f + 100, size.height - 100), Vec2(size.width / 2, size.height / 2), - Vec2(size.width - 100, size.height - 100), 50, Color4F::RED, + Vec2(size.width - 100, size.height - 100), 50, Color::RED, sliderValue[sliderType::Thickness]); drawNode->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x + 30, VisibleRect::center().y + 50), Vec2(VisibleRect::center().x + 60, VisibleRect::center().y - 50), VisibleRect::right(), - 100, Color4F::WHITE, sliderValue[sliderType::Thickness]); + 100, Color::WHITE, sliderValue[sliderType::Thickness]); drawNode->drawCubicBezier(Vec2(size.width - 250, 40.0f), Vec2(size.width - 70, 100.0f), - Vec2(size.width - 30, 250.0f), Vec2(size.width - 10, size.height - 50), 10, Color4F::GRAY, + Vec2(size.width - 30, 250.0f), Vec2(size.width - 10, size.height - 50), 10, Color::GRAY, sliderValue[sliderType::Thickness]); auto array = ax::PointArray::create(20); @@ -2125,7 +2125,7 @@ void DrawNodeThicknessTest::update(float dt) array->addControlPoint(Vec2(80.0f, size.height - 80)); array->addControlPoint(Vec2(80.0f, 80.0f)); array->addControlPoint(Vec2(size.width / 2, size.height / 2)); - drawNode->drawCardinalSpline(array, 0.5f, 50, Color4F::MAGENTA, sliderValue[sliderType::Thickness]); + drawNode->drawCardinalSpline(array, 0.5f, 50, Color::MAGENTA, sliderValue[sliderType::Thickness]); auto array2 = ax::PointArray::create(20); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); @@ -2133,51 +2133,51 @@ void DrawNodeThicknessTest::update(float dt) array2->addControlPoint(Vec2(size.width - 80, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); - drawNode->drawCatmullRom(array2, 50, Color4F::ORANGE, sliderValue[sliderType::Thickness]); + drawNode->drawCatmullRom(array2, 50, Color::ORANGE, sliderValue[sliderType::Thickness]); auto s = Director::getInstance()->getWinSize(); drawNode->drawPoint(Vec2(s.width / 2 - 120, s.height / 2 - 120), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); drawNode->drawPoint(Vec2(s.width / 2 + 120, s.height / 2 + 120), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode 4 small points Vec2 position[] = { Vec2(60, 60), Vec2(70, 70), Vec2(60, 70), Vec2(70, 60) }; - drawNode->drawPoints(position, 4, 5, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + drawNode->drawPoints(position, 4, 5, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode a line - drawNode->drawLine(Vec2(0, 0), Vec2(s.width, s.height), Color4F(1.0, 0.0, 0.0, 0.5)); + drawNode->drawLine(Vec2(0, 0), Vec2(s.width, s.height), Color(1.0, 0.0, 0.0, 0.5)); // drawNode a rectangle - drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color4F(1, 1, 0, 1)); + drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color(1, 1, 0, 1)); drawNode->drawRect(Vec2(15, 30), Vec2(30, 15), Vec2(15, 0), Vec2(0, 15), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode a circle drawNode->drawCircle(VisibleRect::center() + Vec2(140, 0), 100, AX_DEGREES_TO_RADIANS(90), 50, true, 1.0f, 2.0f, - Color4F(1.0f, 0.0f, 0.0f, 0.5f)); + Color(1.0f, 0.0f, 0.0f, 0.5f)); drawNode->drawCircle(VisibleRect::center() - Vec2(140, 0), 50, AX_DEGREES_TO_RADIANS(90), 30, false, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // drawNode some beziers drawNode->drawQuadBezier(Vec2(s.width - 150, s.height - 150), Vec2(s.width - 70, s.height - 10), Vec2(s.width - 10, s.height - 10), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawQuadBezier(Vec2(0.0f, s.height), Vec2(s.width / 2, s.height / 2), Vec2(s.width, s.height), 50, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x + 30, VisibleRect::center().y + 50), Vec2(VisibleRect::center().x + 60, VisibleRect::center().y - 50), VisibleRect::right(), - 100, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + 100, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawCubicBezier(Vec2(s.width - 250, 40.0f), Vec2(s.width - 70, 100.0f), Vec2(s.width - 30, 250.0f), Vec2(s.width - 10, s.height - 50), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); auto array3 = PointArray::create(20); array3->addControlPoint(Vec2(0.0f, 0.0f)); @@ -2187,7 +2187,7 @@ void DrawNodeThicknessTest::update(float dt) array3->addControlPoint(Vec2(80.0f, s.height - 80)); array3->addControlPoint(Vec2(80.0f, 80.0f)); array3->addControlPoint(Vec2(s.width / 2, s.height / 2)); - drawNode->drawCardinalSpline(array3, 0.5f, 50, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + drawNode->drawCardinalSpline(array3, 0.5f, 50, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); auto array4 = PointArray::create(20); array4->addControlPoint(Vec2(s.width / 2, 30.0f)); @@ -2195,28 +2195,28 @@ void DrawNodeThicknessTest::update(float dt) array4->addControlPoint(Vec2(s.width - 80, s.height - 80)); array4->addControlPoint(Vec2(s.width / 2, s.height - 80)); array4->addControlPoint(Vec2(s.width / 2, 30.0f)); - drawNode->drawCatmullRom(array4, 50, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + drawNode->drawCatmullRom(array4, 50, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); // open random color poly Vec2 verticesA[] = { Vec2(0.0f, 0.0f), Vec2(50.0f, 50.0f), Vec2(100.0f, 50.0f), Vec2(100.0f, 100.0f), Vec2(50.0f, 100.0f) }; - drawNode->drawPoly(verticesA, 5, false, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(verticesA, 5, false, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // closed random color poly Vec2 verticesB[] = { Vec2(30.0f, 130.0f), Vec2(30.0f, 230.0f), Vec2(50.0f, 200.0f) }; - drawNode->drawPoly(verticesB, 3, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(verticesB, 3, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // drawNode 10 circles for (int i = 0; i < 10; i++) { drawNode->drawDot(Vec2(s.width / 2, s.height / 2), 10.f * (10 - i), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } // drawNode polygons Vec2 points[] = { Vec2(s.height / 4, 0.0f), Vec2(s.width, s.height / 5), Vec2(s.width / 3 * 2, s.height) }; - drawNode->drawPolygon(points, sizeof(points) / sizeof(points[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 4, - Color4F(0.0f, 0.0f, 1.0f, 0.5f)); + drawNode->drawPolygon(points, sizeof(points) / sizeof(points[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 4, + Color(0.0f, 0.0f, 1.0f, 0.5f)); // star poly (triggers buggs) { @@ -2230,8 +2230,8 @@ void DrawNodeThicknessTest::update(float dt) // {o -h, o+w}, {o,o}, // left spike }; - drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 1, + Color(0.0f, 0.0f, 1.0f, 1.0f)); } // star poly (doesn't trigger bug... order is important un tesselation is supported. @@ -2250,39 +2250,39 @@ void DrawNodeThicknessTest::update(float dt) Vec2(o - h, o + w), // left spike }; - drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 1, + Color(0.0f, 0.0f, 1.0f, 1.0f)); } // drawNode a solid polygon Vec2 vertices3[] = { Vec2(60.0f, 160.0f), Vec2(70.0f, 190.0f), Vec2(100.0f, 190.0f), Vec2(90.0f, 160.0f) }; - drawNode->drawSolidPoly(vertices3, 4, Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidPoly(vertices3, 4, Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid rectangle - drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid circle drawNode->drawSolidCircle(VisibleRect::center() + Vec2(140.0f, 0.0f), 40, AX_DEGREES_TO_RADIANS(90), 50, 2.0f, 2.0f, - Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + Color(0.0f, 1.0f, 0.0f, 1.0f)); // drawNode segment - drawNode->drawSegment(Vec2(20.0f, s.height), Vec2(20.0f, s.height / 2), 10, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSegment(Vec2(20.0f, s.height), Vec2(20.0f, s.height / 2), 10, Color(0.0f, 1.0f, 0.0f, 1.0f)); drawNode->drawSegment(Vec2(10.0f, s.height / 2), Vec2(s.width / 2, s.height / 2), 40, - Color4F(1.0f, 0.0f, 1.0f, 0.5f)); + Color(1.0f, 0.0f, 1.0f, 0.5f)); // drawNode triangle drawNode->drawTriangle(Vec2(10.0f, 10.0f), Vec2(70.0f, 30.0f), Vec2(100.0f, 140.0f), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); for (int i = 0; i < 100; i++) { drawNode->drawPoint(Vec2(i * 7.0f, 5.0f), (float)i / 5 + 1, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } - drawNode->drawLine(Vec2(0.0f, s.height), Vec2(s.width, s.height - 20), Color4F::YELLOW); - drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(s.width, s.height - 20), Color4F::YELLOW); + drawNode->drawLine(Vec2(0.0f, s.height), Vec2(s.width, s.height - 20), Color::YELLOW); + drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(s.width, s.height - 20), Color::YELLOW); drawNode->runAction(RepeatForever::create(Sequence::create(FadeIn::create(1.2f), FadeOut::create(1.2f), NULL))); } @@ -2327,13 +2327,13 @@ void DrawNodeThicknessStressTest::update(float dt) drawNode->clear(); - drawNode->drawCircle(VisibleRect::center(), 60, AX_DEGREES_TO_RADIANS(77), 30, false, Color4F::GREEN, + drawNode->drawCircle(VisibleRect::center(), 60, AX_DEGREES_TO_RADIANS(77), 30, false, Color::GREEN, negativThickness); - drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color4F::YELLOW, negativThickness); + drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color::YELLOW, negativThickness); // drawNode a rectangles - drawNode->drawRect(Vec2(123, 123), Vec2(227, 227), Color4F(1, 1, 0, 1), negativThickness); + drawNode->drawRect(Vec2(123, 123), Vec2(227, 227), Color(1, 1, 0, 1), negativThickness); Vec2 vertices24[] = { {45.750000f, 144.375000f}, {75.500000f, 136.875000f}, {75.500000f, 159.125000f}, {100.250000f, 161.375000f}, @@ -2350,27 +2350,27 @@ void DrawNodeThicknessStressTest::update(float dt) {135.250000f, 108.625000f}, {151.000000f, 124.125000f}, {90.500000f, 131.875000f}, {113.250000f, 120.875000f}, {88.000000f, 116.875000f}, {106.000000f, 103.875000f}, {88.000000f, 97.875000f}, }; - drawNode->drawPolygon(vertices24, sizeof(vertices24) / sizeof(vertices24[0]), Color4B::TRANSPARENT, - negativThickness, Color4F::RED); + drawNode->drawPolygon(vertices24, sizeof(vertices24) / sizeof(vertices24[0]), Color::TRANSPARENT, + negativThickness, Color::RED); // open random color poly Vec2 vertices[] = { Vec2(0.0f, 0.0f), Vec2(50.0f, 50.0f), Vec2(100.0f, 50.0f), Vec2(100.0f, 100.0f), Vec2(50.0f, 100.0f) }; - drawNode->drawPoly(vertices, 5, false, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + drawNode->drawPoly(vertices, 5, false, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), negativThickness); // closed random color poly Vec2 vertices2[] = { Vec2(30.0f, 130.0f), Vec2(30.0f, 230.0f), Vec2(50.0f, 200.0f) }; - drawNode->drawPoly(vertices2, 3, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + drawNode->drawPoly(vertices2, 3, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), negativThickness); // drawNode some beziers drawNode->drawQuadBezier(Vec2(size.width - 150, size.height - 150), Vec2(size.width - 70, size.height - 10), - Vec2(size.width - 10, size.height - 10), 10, Color4F::BLUE, negativThickness); + Vec2(size.width - 10, size.height - 10), 10, Color::BLUE, negativThickness); drawNode->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x + 30, VisibleRect::center().y + 50), Vec2(VisibleRect::center().x + 60, VisibleRect::center().y - 50), VisibleRect::right(), - 100, Color4F::WHITE, negativThickness); + 100, Color::WHITE, negativThickness); auto array = ax::PointArray::create(20); array->addControlPoint(Vec2(0.0f, 0.0f)); @@ -2380,7 +2380,7 @@ void DrawNodeThicknessStressTest::update(float dt) array->addControlPoint(Vec2(80.0f, size.height - 80)); array->addControlPoint(Vec2(80.0f, 80.0f)); array->addControlPoint(Vec2(size.width / 2, size.height / 2)); - drawNode->drawCardinalSpline(array, 0.5f, 50, Color4F::MAGENTA, negativThickness); + drawNode->drawCardinalSpline(array, 0.5f, 50, Color::MAGENTA, negativThickness); auto array2 = ax::PointArray::create(20); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); @@ -2388,28 +2388,28 @@ void DrawNodeThicknessStressTest::update(float dt) array2->addControlPoint(Vec2(size.width - 80, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); - drawNode->drawCatmullRom(array2, 50, Color4F::ORANGE, negativThickness); + drawNode->drawCatmullRom(array2, 50, Color::ORANGE, negativThickness); auto s = Director::getInstance()->getWinSize(); drawNode->drawPoint(Vec2(s.width / 2 - 120, s.height / 2 - 120), negativThickness, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode 4 small points Vec2 position[] = { Vec2(60, 60), Vec2(70, 70), Vec2(60, 70), Vec2(70, 60) }; - drawNode->drawPoints(position, 4, 5, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), DrawNode::Rect); + drawNode->drawPoints(position, 4, 5, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), DrawNode::Rect); Vec2 position1[] = { Vec2(100, 100), Vec2(170, 170), Vec2(260, 170), Vec2(170, 260) }; - drawNode->drawPoints(position1, 4, 25, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), DrawNode::Rect); + drawNode->drawPoints(position1, 4, 25, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1), DrawNode::Rect); // drawNode a rectangle - drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color4F(1, 1, 0, 1), negativThickness); + drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color(1, 1, 0, 1), negativThickness); // drawNode 10 circles for (int i = 0; i < 10; i++) { drawNode->drawDot(Vec2(s.width / 2, s.height / 2), negativThickness, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } // star poly (doesn't trigger bug... order is important un tesselation is supported. @@ -2428,27 +2428,27 @@ void DrawNodeThicknessStressTest::update(float dt) Vec2(o - h, o + w), // left spike }; - drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 1, + Color(0.0f, 0.0f, 1.0f, 1.0f)); } // drawNode a solid polygon Vec2 vertices3[] = { Vec2(60.0f, 160.0f), Vec2(70.0f, 190.0f), Vec2(100.0f, 190.0f), Vec2(90.0f, 160.0f) }; - drawNode->drawSolidPoly(vertices3, 4, Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidPoly(vertices3, 4, Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid rectangle - drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid circle drawNode->drawSolidCircle(VisibleRect::center() + Vec2(140.0f, 0.0f), 40, AX_DEGREES_TO_RADIANS(90), 50, 2.0f, 2.0f, - Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + Color(0.0f, 1.0f, 0.0f, 1.0f)); // drawNode segment - drawNode->drawSegment(Vec2(20.0f, s.height), Vec2(20.0f, s.height / 2), 10, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSegment(Vec2(20.0f, s.height), Vec2(20.0f, s.height / 2), 10, Color(0.0f, 1.0f, 0.0f, 1.0f)); // drawNode triangle drawNode->drawTriangle(Vec2(10.0f, 10.0f), Vec2(70.0f, 30.0f), Vec2(100.0f, 140.0f), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); } void DrawNodeThicknessStressTest::onEnter() @@ -2494,31 +2494,31 @@ void DrawNodePieTest::update(float dt) // Filled drawNode->drawPie(VisibleRect::center() - Vec2(190.0f, -35.0f), 40, sliderValue[sliderType::Rotation], - sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, Color4F::RED, - Color4F::BLUE, drawNode->DrawMode::Fill, sliderValue[sliderType::Thickness]); + sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, Color::RED, + Color::BLUE, drawNode->DrawMode::Fill, sliderValue[sliderType::Thickness]); // Outlined drawNode->drawPie(VisibleRect::center() - Vec2(95.0f, -35.0f), 40, sliderValue[sliderType::Rotation], sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, - Color4F::TRANSPARENT, Color4F::BLUE, drawNode->DrawMode::Outline, + Color::TRANSPARENT, Color::BLUE, drawNode->DrawMode::Outline, sliderValue[sliderType::Thickness]); // Line drawNode->drawPie(VisibleRect::center() + Vec2(0.0f, 35.0f), 40, sliderValue[sliderType::Rotation], sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, - Color4F::TRANSPARENT, Color4F::BLUE, drawNode->DrawMode::Line, + Color::TRANSPARENT, Color::BLUE, drawNode->DrawMode::Line, sliderValue[sliderType::Thickness]); // Semi drawNode->drawPie(VisibleRect::center() + Vec2(95.0f, 35.0f), 40, sliderValue[sliderType::Rotation], sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, - Color4F::TRANSPARENT, Color4F::BLUE, drawNode->DrawMode::Semi, + Color::TRANSPARENT, Color::BLUE, drawNode->DrawMode::Semi, sliderValue[sliderType::Thickness]); // Semi (Filled) drawNode->drawPie(VisibleRect::center() + Vec2(190.0f, 35.0f), 40, sliderValue[sliderType::Rotation], - sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, Color4F::RED, - Color4F::BLUE, drawNode->DrawMode::Semi, sliderValue[sliderType::Thickness]); + sliderValue[sliderType::AngleStart], sliderValue[sliderType::AngleEnd], 1.0f, 1.0f, Color::RED, + Color::BLUE, drawNode->DrawMode::Semi, sliderValue[sliderType::Thickness]); } void DrawNodePieTest::onEnter() @@ -2604,7 +2604,7 @@ ax::ui::ListView* DrawNodeMethodsTest::createListView() (ui::ListView::ccListViewCallback)AX_CALLBACK_2(DrawNodeBaseTest::listviewCallback, this)); listview->setTag(100); - listview->getItem(_currentSeletedItemIndex)->setColor(Color3B::RED); + listview->getItem(_currentSeletedItemIndex)->setColor(Color32::RED); return listview; } @@ -2662,7 +2662,7 @@ void DrawNodeMethodsTest::drawAll() for (int i = 0; i < 100; i++) { drawNode->drawLine(Vec2(-size.x / 2, -size.y / 2 + i * 4), Vec2(size.x - 50, -size.y / 2 + i * 4), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness]); } @@ -2675,7 +2675,7 @@ void DrawNodeMethodsTest::drawAll() { rec = Vec2(i * 3, i * 3); drawNode->drawRect(center / 2 - rec, center / 2 + rec, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness]); } @@ -2686,7 +2686,7 @@ void DrawNodeMethodsTest::drawAll() for (int i = 0; i < 100; i++) { drawNode->drawCircle(VisibleRect::center(), 3 * i, AX_DEGREES_TO_RADIANS(90), i, false, 1.0f, 1.0f, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness]); } @@ -2695,10 +2695,10 @@ void DrawNodeMethodsTest::drawAll() case drawMethodes::QuadBezier: { drawNode->drawQuadBezier(Vec2(size.width - 150, size.height - 150), Vec2(size.width - 70, size.height - 10), - Vec2(size.width - 10, size.height - 10), 10, Color4F::BLUE, + Vec2(size.width - 10, size.height - 10), 10, Color::BLUE, sliderValue[sliderType::Thickness]); drawNode->drawQuadBezier(Vec2(0.0f + 100, size.height - 100), Vec2(size.width / 2, size.height / 2), - Vec2(size.width - 100, size.height - 100), 50, Color4F::RED, + Vec2(size.width - 100, size.height - 100), 50, Color::RED, sliderValue[sliderType::Thickness]); for (int i = 0; i < 360;) @@ -2708,7 +2708,7 @@ void DrawNodeMethodsTest::drawAll() Vec2 p3 = pts->getControlPointAtIndex(i); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawQuadBezier(p1, p2, p3, 30, Color4B::RED, sliderValue[sliderType::Thickness]); + drawNode->drawQuadBezier(p1, p2, p3, 30, Color::RED, sliderValue[sliderType::Thickness]); } for (int i = 0; i < 360;) @@ -2718,7 +2718,7 @@ void DrawNodeMethodsTest::drawAll() Vec2 p3 = pts2->getControlPointAtIndex(i); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawQuadBezier(p1, p2, p3, 30, Color4B::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawQuadBezier(p1, p2, p3, 30, Color::GREEN, sliderValue[sliderType::Thickness]); } break; @@ -2728,10 +2728,10 @@ void DrawNodeMethodsTest::drawAll() drawNode->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x + 30, VisibleRect::center().y + 50), Vec2(VisibleRect::center().x + 60, VisibleRect::center().y - 50), - VisibleRect::right(), 20, Color4F::WHITE, sliderValue[sliderType::Thickness]); + VisibleRect::right(), 20, Color::WHITE, sliderValue[sliderType::Thickness]); drawNode->drawCubicBezier(Vec2(size.width - 250, 40.0f), Vec2(size.width - 70, 100.0f), Vec2(size.width - 30, 250.0f), Vec2(size.width - 10, size.height - 50), 20, - Color4F::GRAY, sliderValue[sliderType::Thickness]); + Color::GRAY, sliderValue[sliderType::Thickness]); for (int i = 0; i < 360;) { @@ -2740,7 +2740,7 @@ void DrawNodeMethodsTest::drawAll() Vec2 p3 = pts->getControlPointAtIndex(i++); Vec2 p4 = pts->getControlPointAtIndex(i); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawCubicBezier(p1, p2, p3, p4, 120, Color4F::RED, sliderValue[sliderType::Thickness]); + drawNode->drawCubicBezier(p1, p2, p3, p4, 120, Color::RED, sliderValue[sliderType::Thickness]); } for (int i = 0; i < 360;) @@ -2750,7 +2750,7 @@ void DrawNodeMethodsTest::drawAll() Vec2 p3 = pts2->getControlPointAtIndex(i++); Vec2 p4 = pts2->getControlPointAtIndex(i); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawCubicBezier(p1, p2, p3, p4, 120, Color4F::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawCubicBezier(p1, p2, p3, p4, 120, Color::GREEN, sliderValue[sliderType::Thickness]); } break; @@ -2766,7 +2766,7 @@ void DrawNodeMethodsTest::drawAll() array->addControlPoint(Vec2(80.0f, size.height - 80)); array->addControlPoint(Vec2(80.0f, 80.0f)); array->addControlPoint(Vec2(size.width / 2, size.height / 2)); - drawNode->drawCardinalSpline(array, 0.5f, 120, Color4F::MAGENTA, sliderValue[sliderType::Thickness]); + drawNode->drawCardinalSpline(array, 0.5f, 120, Color::MAGENTA, sliderValue[sliderType::Thickness]); auto array2 = ax::PointArray::create(5); array2->addControlPoint(Vec2(size.width / 2, 80.0f)); @@ -2774,11 +2774,11 @@ void DrawNodeMethodsTest::drawAll() array2->addControlPoint(Vec2(size.width - 80, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, 80.0f)); - drawNode->drawCardinalSpline(array2, 5.0f, 120, Color4F::ORANGE, sliderValue[sliderType::Thickness]); + drawNode->drawCardinalSpline(array2, 5.0f, 120, Color::ORANGE, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawCardinalSpline(pts, 0.001f, 360, Color4F::RED, sliderValue[sliderType::Thickness]); - drawNode->drawCardinalSpline(pts2, 0.001f, 360, Color4F::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawCardinalSpline(pts, 0.001f, 360, Color::RED, sliderValue[sliderType::Thickness]); + drawNode->drawCardinalSpline(pts2, 0.001f, 360, Color::GREEN, sliderValue[sliderType::Thickness]); break; } @@ -2790,7 +2790,7 @@ void DrawNodeMethodsTest::drawAll() array2->addControlPoint(Vec2(size.width - 80, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, 80.0f)); - drawNode->drawCatmullRom(array2, 20, Color4F::ORANGE, sliderValue[sliderType::Thickness]); + drawNode->drawCatmullRom(array2, 20, Color::ORANGE, sliderValue[sliderType::Thickness]); auto array = ax::PointArray::create(7); array->addControlPoint(Vec2(0.0f, 0.0f)); @@ -2800,11 +2800,11 @@ void DrawNodeMethodsTest::drawAll() array->addControlPoint(Vec2(80.0f, size.height - 80)); array->addControlPoint(Vec2(80.0f, 80.0f)); array->addControlPoint(Vec2(size.width / 2, size.height / 2)); - drawNode->drawCatmullRom(array, 20, Color4F::MAGENTA, sliderValue[sliderType::Thickness]); + drawNode->drawCatmullRom(array, 20, Color::MAGENTA, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(-100, -100)); - drawNode->drawCatmullRom(pts, 360, Color4F::RED, sliderValue[sliderType::Thickness]); - drawNode->drawCatmullRom(pts2, 360, Color4F::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawCatmullRom(pts, 360, Color::RED, sliderValue[sliderType::Thickness]); + drawNode->drawCatmullRom(pts2, 360, Color::GREEN, sliderValue[sliderType::Thickness]); break; } @@ -2812,42 +2812,42 @@ void DrawNodeMethodsTest::drawAll() { Vec2 vertices[5] = { {0.0f, 0.0f}, {50.0f, 50.0f}, {100.0f, 50.0f}, {100.0f, 100.0f}, {50.0f, 100.0f} }; drawNode->properties.setPosition(Vec2(-200, -300)); - drawNode->drawPoly(vertices, 5, false, Color4B::BLUE, sliderValue[sliderType::Thickness]); + drawNode->drawPoly(vertices, 5, false, Color::BLUE, sliderValue[sliderType::Thickness]); Vec2 vertices2[3] = { {30.0f, 130.0f}, {30.0f, 230.0f}, {50.0f, 200.0f} }; - drawNode->drawPoly(vertices2, 3, true, Color4B::GREEN, sliderValue[sliderType::Thickness]); + drawNode->drawPoly(vertices2, 3, true, Color::GREEN, sliderValue[sliderType::Thickness]); drawNode->properties.setDefaultValues(); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4B::RED, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::RED, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(0, -300)); drawNode->properties.setRotation(sliderValue[sliderType::Rotation]); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::GREEN, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::GREEN, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(-100, -300)); drawNode->properties.setRotation(sliderValue[sliderType::Rotation]); drawNode->properties.setCenter(vertices1[0]); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::MAGENTA, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::MAGENTA, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(200, 0)); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::RED, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::RED, sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(Vec2(0.0f, -300.0f)); drawNode->properties.setRotation(rotation / 10.0f); drawNode->properties.setScale(Vec2(2.0f, 2.0f)); drawNode->properties.setCenter(vertices1[4]); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::BLUE, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::BLUE, sliderValue[sliderType::Thickness]); drawNode->properties.setRotation(rotation); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::YELLOW, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::YELLOW, sliderValue[sliderType::Thickness]); drawNode->properties.setRotation(-rotation / 5); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::WHITE, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::WHITE, sliderValue[sliderType::Thickness]); drawNode->properties.setDefaultValues(); - drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color4F::GREEN, + drawNode->drawPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), true, Color::GREEN, sliderValue[sliderType::Thickness]); break; } @@ -2855,34 +2855,34 @@ void DrawNodeMethodsTest::drawAll() { drawNode->properties.setPosition(Vec2(0, -300)); drawNode->properties.setRotation(sliderValue[sliderType::Rotation]); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::GREEN, - sliderValue[sliderType::Thickness], Color4F::YELLOW); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::GREEN, + sliderValue[sliderType::Thickness], Color::YELLOW); drawNode->properties.setPosition(Vec2(-100, -300)); drawNode->properties.setRotation(sliderValue[sliderType::Rotation]); drawNode->properties.setCenter(vertices1[0]); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::MAGENTA, - sliderValue[sliderType::Thickness], Color4F::GRAY); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::MAGENTA, + sliderValue[sliderType::Thickness], Color::GRAY); drawNode->properties.setPosition(Vec2(200, 0)); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::RED, - sliderValue[sliderType::Thickness], Color4F::YELLOW); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::RED, + sliderValue[sliderType::Thickness], Color::YELLOW); drawNode->properties.setPosition(Vec2(0.0f, -300.0f)); drawNode->properties.setRotation(rotation / 10.0f); drawNode->properties.setScale(Vec2(2.0f, 2.0f)); drawNode->properties.setCenter(vertices1[4]); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::BLUE, - sliderValue[sliderType::Thickness], Color4F::WHITE); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::BLUE, + sliderValue[sliderType::Thickness], Color::WHITE); drawNode->properties.setRotation(rotation); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::YELLOW, - sliderValue[sliderType::Thickness], Color4F::GREEN); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::YELLOW, + sliderValue[sliderType::Thickness], Color::GREEN); ; drawNode->properties.setRotation(-rotation / 5); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::WHITE, - sliderValue[sliderType::Thickness], Color4F::YELLOW); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::WHITE, + sliderValue[sliderType::Thickness], Color::YELLOW); drawNode->properties.setDefaultValues(); - drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::GREEN, - sliderValue[sliderType::Thickness], Color4F::BLUE); + drawNode->drawPolygon(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::GREEN, + sliderValue[sliderType::Thickness], Color::BLUE); break; } @@ -2892,7 +2892,7 @@ void DrawNodeMethodsTest::drawAll() { drawNode->drawDot(Vec2(AXRANDOM_MINUS1_1() * 400 + 200, AXRANDOM_MINUS1_1() * 400), 20 + sliderValue[sliderType::Thickness], - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } break; @@ -2903,7 +2903,7 @@ void DrawNodeMethodsTest::drawAll() { drawNode->drawPoint(Vec2(AXRANDOM_MINUS1_1() * 400 + 200, AXRANDOM_MINUS1_1() * 400), 30 + sliderValue[sliderType::Thickness], - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } break; } @@ -2922,20 +2922,20 @@ void DrawNodeMethodsTest::drawAll() {70 + AXRANDOM_MINUS1_1() * VisibleRect::rightTop().x, 70 + AXRANDOM_MINUS1_1() * VisibleRect::rightTop().y / 2} }; drawNode->drawPoints(position, 4, 10 + 2 * sliderValue[sliderType::Thickness], - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); } break; } case drawMethodes::Triangle: { - static Color4B color3[] = { Color4B::GREEN, Color4B::BLUE, Color4B::RED }; + static Color color3[] = {Color::GREEN, Color::BLUE, Color::RED}; drawNode->properties.setPosition(center); drawNode->properties.setScale(Vec2(10, 10)); { drawNode->drawTriangle(Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, - Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Color4B::RED); + Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Color::RED); } { Vec2 triangle[] = { Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, @@ -2958,11 +2958,11 @@ void DrawNodeMethodsTest::drawAll() drawNode->drawSolidTriangle(Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, - Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Color4B::RED, - Color4B::BLUE, sliderValue[sliderType::Thickness]); + Vec2(AXRANDOM_MINUS1_1(), AXRANDOM_MINUS1_1()) * 20, Color::RED, Color::BLUE, + sliderValue[sliderType::Thickness]); drawNode->properties.setPosition(center - Vec2(200, 200)); - drawNode->drawSolidTriangle(triangle, Color4B::GREEN, Color4B::BLUE, sliderValue[sliderType::Thickness]); + drawNode->drawSolidTriangle(triangle, Color::GREEN, Color::BLUE, sliderValue[sliderType::Thickness]); } break; } @@ -2975,17 +2975,17 @@ void DrawNodeMethodsTest::drawAll() int yy1 = 150; int yy = 0; drawNode->drawSegment(Vec2(-150.0f, yy - yy1), Vec2(200, yy - yy1), 20 + 5 * sliderValue[sliderType::Thickness], - Color4F::GREEN, DrawNode::Round, DrawNode::Round); + Color::GREEN, DrawNode::Round, DrawNode::Round); labelRound->setPosition(Vec2(250.0f, 85)); yy += 170; drawNode->drawSegment(Vec2(-150.0f, yy - yy1), Vec2(200, yy - yy1), 20 + 5 * sliderValue[sliderType::Thickness], - Color4F::BLUE, DrawNode::Square, DrawNode::Square); + Color::BLUE, DrawNode::Square, DrawNode::Square); labelSquare->setPosition(Vec2(250.0f, 170)); yy += 170; drawNode->drawSegment(Vec2(-150.0f, yy - yy1), Vec2(200, yy - yy1), 20 + 5 * sliderValue[sliderType::Thickness], - Color4F::RED, DrawNode::Butt, DrawNode::Butt); + Color::RED, DrawNode::Butt, DrawNode::Butt); labelButt->setPosition(Vec2(250.0f, 255)); break; @@ -2999,30 +2999,30 @@ void DrawNodeMethodsTest::drawAll() drawNode->drawSolidCircle( VisibleRect::center(), AXRANDOM_0_1() * 200, AX_DEGREES_TO_RADIANS(AXRANDOM_MINUS1_1() * 90), 10, 1.0f, - 1.0f, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness], - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + 1.0f, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness], + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); drawNode->drawSolidCircle( VisibleRect::center() + pos, AXRANDOM_0_1() * 200, AX_DEGREES_TO_RADIANS(AXRANDOM_MINUS1_1() * 90), 10, - 1.0f, 1.0f, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), - sliderValue[sliderType::Thickness], Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + 1.0f, 1.0f, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + sliderValue[sliderType::Thickness], Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); drawNode->drawSolidCircle( VisibleRect::center() - pos, AXRANDOM_0_1() * 200, AX_DEGREES_TO_RADIANS(AXRANDOM_MINUS1_1() * 90), 10, - 1.0f, 1.0f, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), - sliderValue[sliderType::Thickness], Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + 1.0f, 1.0f, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + sliderValue[sliderType::Thickness], Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // for (int i = 5; i > 1; i--) //{ // drawNode->drawSolidCircle( // VisibleRect::center(), 3 * i, AX_DEGREES_TO_RADIANS(90), AXRANDOM_0_1() * 20.f + 20.f, 1.0f, 1.0f, - // Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness], - // Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + // Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), sliderValue[sliderType::Thickness], + // Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); // drawNode->drawSolidCircle( // VisibleRect::center() + pos, AXRANDOM_0_1() * 200, AX_DEGREES_TO_RADIANS(AXRANDOM_MINUS1_1() * 90), - // 10, 1.0f, 1.0f, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), - // sliderValue[sliderType::Thickness], Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + // 10, 1.0f, 1.0f, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + // sliderValue[sliderType::Thickness], Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); //} break; @@ -3036,14 +3036,14 @@ void DrawNodeMethodsTest::drawAll() drawNode->properties.setRotation(rotation / 10.0f); drawNode->properties.setScale(Vec2(2.0f, 2.0f)); drawNode->properties.setCenter(vertices1[4]); - drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::BLUE); + drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::BLUE); drawNode->properties.setRotation(rotation); - drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::YELLOW); + drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::YELLOW); drawNode->properties.setRotation(-rotation / 5); - drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::WHITE); + drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::WHITE); drawNode->properties.setDefaultValues(); - drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color4F::GREEN); + drawNode->drawSolidPoly(vertices1, sizeof(vertices1) / sizeof(vertices1[0]), Color::GREEN); break; } @@ -3055,7 +3055,7 @@ void DrawNodeMethodsTest::drawAll() AXRANDOM_MINUS1_1() * VisibleRect::rightTop().y); drawNode->drawSolidRect( pos, pos + Vec2(20.0f * sliderValue[sliderType::Thickness], 20.0f * sliderValue[sliderType::Thickness]), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f), sliderValue[sliderType::Thickness]); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f), sliderValue[sliderType::Thickness]); } break; @@ -3070,29 +3070,29 @@ void DrawNodeMethodsTest::drawAll() drawNode->properties.setRotation(rotation + 45); drawNode->properties.setCenter(gear1); - drawNode->drawStar(Vec2(gear1), 30, 60, 8, Color4F::BLUE, 4.0); + drawNode->drawStar(Vec2(gear1), 30, 60, 8, Color::BLUE, 4.0); drawNode->properties.setRotation(-rotation); drawNode->properties.setCenter(gear2); - drawNode->drawStar(gear2, 30, 60, 8, Color4F::GREEN, 4.0); + drawNode->drawStar(gear2, 30, 60, 8, Color::GREEN, 4.0); drawNode->properties.setDefaultValues(); - drawNode->drawLine(gear2, gear1, Color4F::RED, sliderValue[sliderType::Thickness]); // line + drawNode->drawLine(gear2, gear1, Color::RED, sliderValue[sliderType::Thickness]); // line drawNode->properties.setCenter(gear4); drawNode->properties.setRotation(rotation + 45); - drawNode->drawStar(gear3, 30, 60, 18, Color4F::RED, 1.0); - drawNode->drawLine(gear3, gear4, Color4F::YELLOW, sliderValue[sliderType::Thickness]); // line + drawNode->drawStar(gear3, 30, 60, 18, Color::RED, 1.0); + drawNode->drawLine(gear3, gear4, Color::YELLOW, sliderValue[sliderType::Thickness]); // line // drawNode->properties.setDefaultValues(); drawNode->properties.setRotation(rotation - 45); drawNode->properties.setCenter(gear4); - drawNode->drawStar(gear4, 40, 60, 60, Color4F::GREEN, 1.0); + drawNode->drawStar(gear4, 40, 60, 60, Color::GREEN, 1.0); drawNode->properties.setRotation(rotation); drawNode->properties.setCenter(Vec2(-110, 250)); - drawNode->drawStar(Vec2(-110, 250), 30, 70, 5, Color4F::GREEN, 1.0); + drawNode->drawStar(Vec2(-110, 250), 30, 70, 5, Color::GREEN, 1.0); drawNode->properties.setCenter(Vec2(-150, 100)); - drawNode->drawStar(Vec2(-150, 100), 80, 100, 40, Color4F::GREEN, 1.0); + drawNode->drawStar(Vec2(-150, 100), 80, 100, 40, Color::GREEN, 1.0); drawNode->properties.setCenter(Vec2(-150, -100)); - drawNode->drawStar(Vec2(-150, -100), 5, 70, 3, Color4F::GREEN, 1.0); + drawNode->drawStar(Vec2(-150, -100), 5, 70, 3, Color::GREEN, 1.0); drawNode->properties.setRotation(0); for (int i = 0; i < 10; i++) @@ -3101,7 +3101,7 @@ void DrawNodeMethodsTest::drawAll() drawNode->properties.setPosition(Vec2(ppp)); drawNode->drawStar( Vec2::ZERO, 40, 60, AXRANDOM_0_1() * 60 + 3, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), sliderValue[sliderType::Thickness])); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), sliderValue[sliderType::Thickness])); } break; } @@ -3114,29 +3114,29 @@ void DrawNodeMethodsTest::drawAll() drawNode->properties.setRotation(rotation + 45); drawNode->properties.setCenter(gear1); - drawNode->drawSolidStar(Vec2(gear1), 30, 60, 8, Color4F::BLUE, Color4F::YELLOW, 4.0); + drawNode->drawSolidStar(Vec2(gear1), 30, 60, 8, Color::BLUE, Color::YELLOW, 4.0); drawNode->properties.setRotation(-rotation); drawNode->properties.setCenter(gear2); - drawNode->drawSolidStar(gear2, 30, 60, 8, Color4F::GREEN, Color4F::YELLOW, 4.0); + drawNode->drawSolidStar(gear2, 30, 60, 8, Color::GREEN, Color::YELLOW, 4.0); drawNode->properties.setDefaultValues(); - drawNode->drawLine(gear2, gear1, Color4F::RED, sliderValue[sliderType::Thickness]); // line + drawNode->drawLine(gear2, gear1, Color::RED, sliderValue[sliderType::Thickness]); // line drawNode->properties.setCenter(gear4); drawNode->properties.setRotation(rotation + 45); - drawNode->drawSolidStar(gear3, 30, 60, 18, Color4F::RED, Color4F::YELLOW, 1.0); - drawNode->drawLine(gear3, gear4, Color4F::YELLOW, sliderValue[sliderType::Thickness]); // line + drawNode->drawSolidStar(gear3, 30, 60, 18, Color::RED, Color::YELLOW, 1.0); + drawNode->drawLine(gear3, gear4, Color::YELLOW, sliderValue[sliderType::Thickness]); // line drawNode->properties.setDefaultValues(); drawNode->properties.setRotation(rotation - 45); drawNode->properties.setCenter(gear4); - drawNode->drawSolidStar(gear4, 40, 60, 60, Color4F::GREEN, Color4F::YELLOW, 1.0); + drawNode->drawSolidStar(gear4, 40, 60, 60, Color::GREEN, Color::YELLOW, 1.0); drawNode->properties.setRotation(rotation); drawNode->properties.setCenter(Vec2(-110, 250)); - drawNode->drawSolidStar(Vec2(-110, 250), 30, 70, 5, Color4F::GREEN, Color4F::YELLOW, 1.0); + drawNode->drawSolidStar(Vec2(-110, 250), 30, 70, 5, Color::GREEN, Color::YELLOW, 1.0); drawNode->properties.setCenter(Vec2(-150, 100)); - drawNode->drawSolidStar(Vec2(-150, 100), 80, 100, 40, Color4F::GREEN, Color4F::YELLOW, 1.0); + drawNode->drawSolidStar(Vec2(-150, 100), 80, 100, 40, Color::GREEN, Color::YELLOW, 1.0); drawNode->properties.setCenter(Vec2(-150, -100)); - drawNode->drawSolidStar(Vec2(-150, -100), 5, 70, 3, Color4F::GREEN, Color4F::YELLOW, 1.0); + drawNode->drawSolidStar(Vec2(-150, -100), 5, 70, 3, Color::GREEN, Color::YELLOW, 1.0); drawNode->properties.setRotation(0); for (int i = 0; i < 10; i++) @@ -3144,8 +3144,8 @@ void DrawNodeMethodsTest::drawAll() Vec2 ppp = Vec2(AXRANDOM_MINUS1_1() * size.x / 2, AXRANDOM_MINUS1_1() * size.y / 2); drawNode->properties.setPosition(Vec2(ppp)); drawNode->drawSolidStar(Vec2::ZERO, 40, 60, AXRANDOM_0_1() * 60 + 3, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } break; @@ -3178,7 +3178,7 @@ void DrawNodeDrawInWrongOrder_Issue1888::update(float dt) drawNode->clear(); - drawNode->drawLine(Vec2(20, 140), Vec2(450, 110), Color4B::RED, 20.0f); + drawNode->drawLine(Vec2(20, 140), Vec2(450, 110), Color::RED, 20.0f); for (int i = 0; i < 200; i++) { @@ -3187,20 +3187,20 @@ void DrawNodeDrawInWrongOrder_Issue1888::update(float dt) {70 + AXRANDOM_0_1() * VisibleRect::rightTop().x, 70 + AXRANDOM_0_1() * VisibleRect::rightTop().y}, {60 + AXRANDOM_0_1() * VisibleRect::rightTop().x, 60 + AXRANDOM_0_1() * VisibleRect::rightTop().y}, {70 + AXRANDOM_0_1() * VisibleRect::rightTop().x, 70 + AXRANDOM_0_1() * VisibleRect::rightTop().y} }; - drawNode->drawPoints(position1, 4, 10, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + drawNode->drawPoints(position1, 4, 10, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); } - drawNode->drawSolidRect(Vec2(150, 80), Vec2(400, 220), Color4B::YELLOW); + drawNode->drawSolidRect(Vec2(150, 80), Vec2(400, 220), Color::YELLOW); for (int i = 0; i < 50; i++) { drawNode->drawPoint(Vec2(i * 7.0f, 120.0f), (float)i / 5 + 1, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } - drawNode->drawLine(Vec2(20, 100), Vec2(450, 220), Color4B::GREEN, 8.0f); + drawNode->drawLine(Vec2(20, 100), Vec2(450, 220), Color::GREEN, 8.0f); - drawNode->drawLine(Vec2(200, 100), Vec2(450, 250), Color4B::BLUE, 6.0f); + drawNode->drawLine(Vec2(200, 100), Vec2(450, 250), Color::BLUE, 6.0f); } DrawNodeAxmolTest2::DrawNodeAxmolTest2() @@ -3290,47 +3290,47 @@ void DrawNodeAxmolTest2::drawAllv2(DrawNode* drawNode, bool drawOrder) drawNode->properties.setDrawOrder(drawOrder); drawNode->drawPoint(Vec2(size.width / 2 - 120, size.height / 2 - 120), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); drawNode->drawPoint(Vec2(size.width / 2 + 120, size.height / 2 + 120), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode 4 small points Vec2 position[] = { Vec2(60, 60), Vec2(70, 70), Vec2(60, 70), Vec2(70, 60) }; - drawNode->drawPoints(position, 4, 5, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + drawNode->drawPoints(position, 4, 5, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode a line - drawNode->drawLine(Vec2(0, 0), Vec2(size.width, size.height), Color4F(1.0, 0.0, 0.0, 0.5)); + drawNode->drawLine(Vec2(0, 0), Vec2(size.width, size.height), Color(1.0, 0.0, 0.0, 0.5)); // drawNode a rectangle - drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color4F::RED); + drawNode->drawRect(Vec2(23, 23), Vec2(7, 7), Color::RED); drawNode->drawRect(Vec2(15, 30), Vec2(30, 15), Vec2(15, 0), Vec2(0, 15), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); // drawNode a circle drawNode->drawCircle(VisibleRect::center() + Vec2(140, 0), 100, AX_DEGREES_TO_RADIANS(90), 30, true, 1.0f, 2.0f, - Color4F(1.0f, 0.0f, 0.0f, 0.5f)); + Color(1.0f, 0.0f, 0.0f, 0.5f)); drawNode->drawCircle(VisibleRect::center() - Vec2(140, 0), 50, AX_DEGREES_TO_RADIANS(90), 30, false, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // drawNode some beziers drawNode->drawQuadBezier(Vec2(size.width - 150, size.height - 150), Vec2(size.width - 70, size.height - 10), Vec2(size.width - 10, size.height - 10), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawQuadBezier(Vec2(0.0f, size.height), Vec2(size.width / 2, size.height / 2), Vec2(size.width, size.height), 50, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawCubicBezier(VisibleRect::center(), Vec2(VisibleRect::center().x + 30, VisibleRect::center().y + 50), Vec2(VisibleRect::center().x + 60, VisibleRect::center().y - 50), VisibleRect::right(), - 100, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + 100, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); drawNode->drawCubicBezier(Vec2(size.width - 250, 40.0f), Vec2(size.width - 70, 100.0f), Vec2(size.width - 30, 250.0f), Vec2(size.width - 10, size.height - 50), 10, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); auto array = PointArray::create(20); array->addControlPoint(Vec2(0.0f, 0.0f)); @@ -3340,7 +3340,7 @@ void DrawNodeAxmolTest2::drawAllv2(DrawNode* drawNode, bool drawOrder) array->addControlPoint(Vec2(80.0f, size.height - 80)); array->addControlPoint(Vec2(80.0f, 80.0f)); array->addControlPoint(Vec2(size.width / 2, size.height / 2)); - drawNode->drawCardinalSpline(array, 0.5f, 50, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + drawNode->drawCardinalSpline(array, 0.5f, 50, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); auto array2 = PointArray::create(20); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); @@ -3348,29 +3348,29 @@ void DrawNodeAxmolTest2::drawAllv2(DrawNode* drawNode, bool drawOrder) array2->addControlPoint(Vec2(size.width - 80, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, size.height - 80)); array2->addControlPoint(Vec2(size.width / 2, 30.0f)); - drawNode->drawCatmullRom(array2, 50, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + drawNode->drawCatmullRom(array2, 50, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); // open random color poly Vec2 vertices[] = { Vec2(0.0f, 0.0f), Vec2(50.0f, 50.0f), Vec2(100.0f, 50.0f), Vec2(100.0f, 100.0f), Vec2(50.0f, 100.0f) }; - drawNode->drawPoly(vertices, 5, false, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(vertices, 5, false, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // closed random color poly Vec2 vertices2[] = { Vec2(30.0f, 130.0f), Vec2(30.0f, 230.0f), Vec2(50.0f, 200.0f) }; - drawNode->drawPoly(vertices2, 3, true, Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + drawNode->drawPoly(vertices2, 3, true, Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); // drawNode 10 circles for (int i = 0; i < 10; i++) { drawNode->drawDot(Vec2(size.width / 2, size.height / 2), 10.f * (10 - i), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } // drawNode polygons Vec2 points[] = { Vec2(size.height / 4, 0.0f), Vec2(size.width, size.height / 5), Vec2(size.width / 3 * 2, size.height) }; - drawNode->drawPolygon(points, sizeof(points) / sizeof(points[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 4, - Color4F(0.0f, 0.0f, 1.0f, 0.5f)); + drawNode->drawPolygon(points, sizeof(points) / sizeof(points[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 4, + Color(0.0f, 0.0f, 1.0f, 0.5f)); // star poly (triggers buggs) { @@ -3384,8 +3384,8 @@ void DrawNodeAxmolTest2::drawAllv2(DrawNode* drawNode, bool drawOrder) //{o -h, o+w}, {o,o}, // left spike }; - drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 1, + Color(0.0f, 0.0f, 1.0f, 1.0f)); } // star poly (doesn't trigger bug... order is important un tesselation is supported. @@ -3405,39 +3405,39 @@ void DrawNodeAxmolTest2::drawAllv2(DrawNode* drawNode, bool drawOrder) Vec2(o, o), // left spike }; - drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color4F(1.0f, 0.0f, 0.0f, 0.5f), 1, - Color4F(0.0f, 0.0f, 1.0f, 1.0f)); + drawNode->drawPolygon(star, sizeof(star) / sizeof(star[0]), Color(1.0f, 0.0f, 0.0f, 0.5f), 1, + Color(0.0f, 0.0f, 1.0f, 1.0f)); } // drawNode a solid polygon Vec2 vertices3[] = { Vec2(60.0f, 160.0f), Vec2(70.0f, 190.0f), Vec2(100.0f, 190.0f), Vec2(90.0f, 160.0f) }; - drawNode->drawSolidPoly(vertices3, 4, Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidPoly(vertices3, 4, Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid rectangle - drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color4F(1.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSolidRect(Vec2(10.0f, 10.0f), Vec2(20.0f, 20.0f), Color(1.0f, 1.0f, 0.0f, 1.0f)); // drawNode a solid circle drawNode->drawSolidCircle(VisibleRect::center() + Vec2(140.0f, 0.0f), 40, AX_DEGREES_TO_RADIANS(90), 50, 2.0f, 2.0f, - Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + Color(0.0f, 1.0f, 0.0f, 1.0f)); // drawNode segment - drawNode->drawSegment(Vec2(20.0f, size.height), Vec2(20.0f, size.height / 2), 10, Color4F(0.0f, 1.0f, 0.0f, 1.0f)); + drawNode->drawSegment(Vec2(20.0f, size.height), Vec2(20.0f, size.height / 2), 10, Color(0.0f, 1.0f, 0.0f, 1.0f)); drawNode->drawSegment(Vec2(10.0f, size.height / 2), Vec2(size.width / 2, size.height / 2), 40, - Color4F(1.0f, 0.0f, 1.0f, 0.5f)); + Color(1.0f, 0.0f, 1.0f, 0.5f)); // drawNode triangle drawNode->drawTriangle(Vec2(10.0f, 10.0f), Vec2(70.0f, 30.0f), Vec2(100.0f, 140.0f), - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 0.5f)); for (int i = 0; i < 100; i++) { drawNode->drawPoint(Vec2(i * 7.0f, 5.0f), (float)i / 5 + 1, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f)); } - drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color4F::YELLOW); - drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(size.width, size.height - 20), Color4F::YELLOW); + drawNode->drawLine(Vec2(0.0f, size.height), Vec2(size.width, size.height - 20), Color::YELLOW); + drawNode->drawLine(Vec2(0.0f, 0.0f), Vec2(size.width, size.height - 20), Color::YELLOW); } string DrawNodeAxmolTest2::title() const @@ -3457,26 +3457,26 @@ DrawNodeIssueTester::DrawNodeIssueTester() int verticesCount = 5; drawNode->properties.setPosition(Vec2(5, 150)); - drawNode->drawPoly(vertices, verticesCount, false, Color4F::GREEN); + drawNode->drawPoly(vertices, verticesCount, false, Color::GREEN); auto draw = DrawNode::create(); addChild(draw, 10); draw->setPosition(70, 150); - draw->drawPoly(vertices, verticesCount, false, Color4F::BLUE); + draw->drawPoly(vertices, verticesCount, false, Color::BLUE); drawNode->properties.setPosition(Vec2(140, 150)); - drawNode->drawPoly(vertices, verticesCount, false, Color4F::RED); + drawNode->drawPoly(vertices, verticesCount, false, Color::RED); drawNode->properties.setPosition(Vec2(200, 150)); - drawNode->drawPoly(vertices, verticesCount, false, Color4F::RED, 3); - drawNode->drawPoly(vertices, verticesCount, false, Color4F::WHITE); + drawNode->drawPoly(vertices, verticesCount, false, Color::RED, 3); + drawNode->drawPoly(vertices, verticesCount, false, Color::WHITE); drawNode->properties.setPosition(Vec2(270, 150)); - drawNode->drawPoly(vertices, verticesCount, false, Color4F(0.0f, 0.5f, 0.5f, 0.5f), 10); - drawNode->drawPoly(vertices, verticesCount, false, Color4F::BLACK); + drawNode->drawPoly(vertices, verticesCount, false, Color(0.0f, 0.5f, 0.5f, 0.5f), 10); + drawNode->drawPoly(vertices, verticesCount, false, Color::BLACK); float thick = 0.0f; float y = -90.0f; @@ -3485,17 +3485,17 @@ DrawNodeIssueTester::DrawNodeIssueTester() { thick += 0.5f; y += thick + 1; - drawNode->drawLine(Vec2(140, y), Vec2(180, y), Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), + drawNode->drawLine(Vec2(140, y), Vec2(180, y), Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), thick); } - drawNode->drawPie(Vec2(-220, 150), 20, 0, 100, 300, 1, 1, Color4B::TRANSPARENT, Color4B::BLUE, + drawNode->drawPie(Vec2(-220, 150), 20, 0, 100, 300, 1, 1, Color::TRANSPARENT, Color::BLUE, DrawNode::DrawMode::Line, 10); drawNode->properties.setPosition(Vec2(50, -100)); for (int i = 2; i < 30; i++) { drawNode->drawCircle(center, 5 * i, AX_DEGREES_TO_RADIANS(90), i, false, 1.0f, 1.0f, - Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), 0.5f); + Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1.0f), 0.5f); } Vec2* fbHorse = new Vec2[856 / 2]; @@ -3506,18 +3506,18 @@ DrawNodeIssueTester::DrawNodeIssueTester() for (size_t i = 0; i < sizeof(verticesFB) / sizeof(verticesFB[0]); i += 4) { drawNode->drawLine(Vec2(verticesFB[i] * scale, verticesFB[i + 1] * scale) + pos, - Vec2(verticesFB[i + 2] * scale, verticesFB[i + 3] * scale) + pos, Color4F::RED, 0.5f); + Vec2(verticesFB[i + 2] * scale, verticesFB[i + 3] * scale) + pos, Color::RED, 0.5f); } drawNode->properties.setPosition(VisibleRect::center() - Vec2(100, 50)); - drawNode->drawSolidCircle(Vec2::ZERO, 40, AX_DEGREES_TO_RADIANS(-90), 30, 1.0f, 1.0f, Color4F::GREEN, 6, - Color4F::BLUE, false); - drawNode->drawSolidCircle(Vec2(100, 0), 40, AX_DEGREES_TO_RADIANS(-90), 30, 1.0f, 1.0f, Color4F::RED, 6, - Color4F::BLUE, true); + drawNode->drawSolidCircle(Vec2::ZERO, 40, AX_DEGREES_TO_RADIANS(-90), 30, 1.0f, 1.0f, Color::GREEN, 6, + Color::BLUE, false); + drawNode->drawSolidCircle(Vec2(100, 0), 40, AX_DEGREES_TO_RADIANS(-90), 30, 1.0f, 1.0f, Color::RED, 6, + Color::BLUE, true); - drawNode->drawCircle(Vec2(100, 100), 40, AX_DEGREES_TO_RADIANS(-90), 30, true, 1.0f, 1.0f, Color4F::GREEN, 6); + drawNode->drawCircle(Vec2(100, 100), 40, AX_DEGREES_TO_RADIANS(-90), 30, true, 1.0f, 1.0f, Color::GREEN, 6); - drawNode->drawCircle(Vec2(0, 100), 40, AX_DEGREES_TO_RADIANS(-90), 30, false, 1.0f, 1.0f, Color4F::RED, 6); + drawNode->drawCircle(Vec2(0, 100), 40, AX_DEGREES_TO_RADIANS(-90), 30, false, 1.0f, 1.0f, Color::RED, 6); // scheduleUpdate(); } @@ -3591,20 +3591,20 @@ void DrawNodeSpLinesTest::update(float dt) for (int i = 0; i < 10; i++) { array->addControlPoint(Vec2((i % 2) ? 20 : screen.width - 20, 50 + i * 20)); - drawNode->drawPoint(array->getControlPointAtIndex(i), 10, Color4F::BLUE); + drawNode->drawPoint(array->getControlPointAtIndex(i), 10, Color::BLUE); } - drawNode->drawCardinalSpline(array, 0.1, 20, Color4F::ORANGE); + drawNode->drawCardinalSpline(array, 0.1, 20, Color::ORANGE); - drawNode->drawCardinalSpline(pts, 0.5f, 360, Color4F::RED, 5.0f); - drawNode->drawCardinalSpline(pts2, 0.5f, 360, Color4F::GREEN, 2.0f); + drawNode->drawCardinalSpline(pts, 0.5f, 360, Color::RED, 5.0f); + drawNode->drawCardinalSpline(pts2, 0.5f, 360, Color::GREEN, 2.0f); int i1 = RandomHelper::random_int(0, n - 1); int i2 = RandomHelper::random_int(0, n - 1); - drawNode->drawDot(pts->getControlPointAtIndex(i1), 7, Color4F(0, 1, 0, 0.3)); - drawNode->drawDot(pts->getControlPointAtIndex(i1), 4, Color4F::GREEN); + drawNode->drawDot(pts->getControlPointAtIndex(i1), 7, Color(0, 1, 0, 0.3)); + drawNode->drawDot(pts->getControlPointAtIndex(i1), 4, Color::GREEN); - drawNode->drawDot(pts2->getControlPointAtIndex(i2), 7, Color4F(0, 1, 0, 0.3)); - drawNode->drawDot(pts2->getControlPointAtIndex(i2), 4, Color4F::GREEN); + drawNode->drawDot(pts2->getControlPointAtIndex(i2), 7, Color(0, 1, 0, 0.3)); + drawNode->drawDot(pts2->getControlPointAtIndex(i2), 4, Color::GREEN); } DrawNodeSpLinesOpenClosedTest::DrawNodeSpLinesOpenClosedTest() @@ -3685,12 +3685,12 @@ void DrawNodeSpLinesOpenClosedTest::update(float dt) for (auto&& p : points) { - drawNodeCP->drawRect(Vec2(p.x - boxSize, p.y - boxSize), Vec2(p.x + boxSize, p.y + boxSize), Color4F::BLUE); + drawNodeCP->drawRect(Vec2(p.x - boxSize, p.y - boxSize), Vec2(p.x + boxSize, p.y + boxSize), Color::BLUE); array->addControlPoint(Vec2(p.x, p.y)); } - drawNode->drawCardinalSpline(array, 0.0f, static_cast(points.size() * 20), Color4F::GREEN, 1.0f, true); - drawNode->drawCardinalSpline(array, 0.0f, static_cast(points.size() * 20), Color4F::RED, 1.0f, false); + drawNode->drawCardinalSpline(array, 0.0f, static_cast(points.size() * 20), Color::GREEN, 1.0f, true); + drawNode->drawCardinalSpline(array, 0.0f, static_cast(points.size() * 20), Color::RED, 1.0f, false); } @@ -3713,7 +3713,7 @@ std::string CandyMixEeffect::subtitle() const return ""; } -void CandyMixEeffect::renderLine(float x1, float x2, float y, ax::Color4F color, float angle) +void CandyMixEeffect::renderLine(float x1, float x2, float y, ax::Color color, float angle) { static float WID = 400; @@ -3736,7 +3736,7 @@ void CandyMixEeffect::renderLine(float x1, float x2, float y, ax::Color4F color, float rr = MIN(mm, r * sf + sp); float gg = MIN(mm, g * sf + sp); float bb = MIN(mm, b * sf + sp); - drawNode->drawPoint(Vec2(y, x - 50), 2.0f, Color4F(rr, gg, bb, 1.0f)); + drawNode->drawPoint(Vec2(y, x - 50), 2.0f, Color(rr, gg, bb, 1.0f)); } } @@ -3745,11 +3745,11 @@ void CandyMixEeffect::update(float dt) DrawNodeBaseTest::update(dt); drawNode->clear(); + static auto ticks = b2GetTicks(); + static float WID = 400; static float HIG = 600; - static b2Timer timer; - - float t = timer.GetMilliseconds() / 1000.0f; + float t = b2GetMilliseconds(ticks) / 1000.0f; float ta = sin(t * cos(t) * 0.02f) + t; float tb = (1.0f + sin(t) * 1.0f) * 0.02f + 0.01f; float xa = WID * 0.5f; @@ -3763,13 +3763,13 @@ void CandyMixEeffect::update(float dt) float x3 = xa + sin(rot + (float)M_PI) * rad; float x4 = xa + sin(rot + (float)M_PI * 1.5f) * rad; if (x1 < x2) - renderLine(x1, x2, y, Color4F::RED, rot); + renderLine(x1, x2, y, Color::RED, rot); if (x2 < x3) - renderLine(x2, x3, y, Color4F::GREEN, rot + (float)M_PI * 0.5f); + renderLine(x2, x3, y, Color::GREEN, rot + (float)M_PI * 0.5f); if (x3 < x4) - renderLine(x3, x4, y, Color4F::BLUE, rot + (float)M_PI); + renderLine(x3, x4, y, Color::BLUE, rot + (float)M_PI); if (x4 < x1) - renderLine(x4, x1, y, Color4F::YELLOW, rot + (float)M_PI * 1.5f); + renderLine(x4, x1, y, Color::YELLOW, rot + (float)M_PI * 1.5f); t += sin(ta + ya) * tb; xa += sin(t + ta) * 0.1f; } diff --git a/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.h b/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.h index 726525f710d5..61b1b265ecf4 100644 --- a/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.h +++ b/tests/cpp-tests/Source/DrawNodeTest/DrawNodeTest.h @@ -24,10 +24,10 @@ THE SOFTWARE. ****************************************************************************/ #pragma once -#include "axmol.h" -#include "ui/CocosGUI.h" +#include "axmol/axmol.h" +#include "axmol/ui/CocosGUI.h" #include "../BaseTest.h" -#include "2d/DrawNode.h" +#include "axmol/2d/DrawNode.h" DEFINE_TEST_SUITE(DrawNodeTests); @@ -200,7 +200,7 @@ class DrawNodeMorphTest_SolidPolygon : public DrawNodeBaseTest ax::Vec2* verticesObj1[10]; ax::Vec2* verticesObj2[10]; ax::Vec2* verticesObjMorph[10]; - ax::Color4F color[10]; + ax::Color color[10]; float rad[10]; bool state[10]; @@ -223,7 +223,7 @@ class DrawNodeMorphTest_Polygon : public DrawNodeBaseTest ax::Vec2* verticesObj1[10]; ax::Vec2* verticesObj2[10]; ax::Vec2* verticesObjMorph[10]; - ax::Color4F color[10]; + ax::Color color[10]; float rad[10]; bool state[10]; @@ -470,7 +470,7 @@ class CandyMixEeffect : public DrawNodeBaseTest virtual std::string subtitle() const override; void update(float dt) override; - void renderLine(float x1, float x2, float y, ax::Color4F color, float angle); + void renderLine(float x1, float x2, float y, ax::Color color, float angle); private: std::vector points; diff --git a/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.cpp b/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.cpp index f1e6dc6bfe63..6710e1ecd308 100644 --- a/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.cpp +++ b/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.cpp @@ -258,7 +258,7 @@ void Issue631::onEnter() removeChild(_bgNode, true); // background - auto layer = LayerColor::create(Color4B(255, 0, 0, 255)); + auto layer = LayerColor::create(Color32(255, 0, 0, 255)); addChild(layer, -10); auto sprite = Sprite::create("Images/grossini.png"); sprite->setPosition(50, 80); @@ -266,10 +266,10 @@ void Issue631::onEnter() // foreground auto layer2BaseGrid = NodeGrid::create(); - auto layer2 = LayerColor::create(Color4B(0, 255, 0, 255)); + auto layer2 = LayerColor::create(Color32(0, 255, 0, 255)); auto fog = Sprite::create("Images/Fog.png"); - BlendFunc bf = {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE_MINUS_SRC_ALPHA}; + BlendFunc bf = {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE_MINUS_SRC_ALPHA}; fog->setBlendFunc(bf); layer2->addChild(fog, 1); addChild(layer2BaseGrid, 1); diff --git a/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.h b/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.h index 7168271c4be1..5729f1e5322e 100644 --- a/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.h +++ b/tests/cpp-tests/Source/EffectsAdvancedTest/EffectsAdvancedTest.h @@ -25,7 +25,7 @@ #ifndef _EFFECT_ADVANCED_TEST_H_ #define _EFFECT_ADVANCED_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(EffectAdvanceTests); diff --git a/tests/cpp-tests/Source/EffectsTest/EffectsTest.cpp b/tests/cpp-tests/Source/EffectsTest/EffectsTest.cpp index 51148abf5a53..1e013722367d 100644 --- a/tests/cpp-tests/Source/EffectsTest/EffectsTest.cpp +++ b/tests/cpp-tests/Source/EffectsTest/EffectsTest.cpp @@ -349,7 +349,7 @@ bool EffectBaseTest::init() { if (TestCase::init()) { - LayerColor* background = LayerColor::create(Color4B(32, 128, 32, 255)); + LayerColor* background = LayerColor::create(Color32(32, 128, 32, 255)); this->addChild(background, -20); if (isRectEffect()) { diff --git a/tests/cpp-tests/Source/EffekseerTest/EffekseerTest.h b/tests/cpp-tests/Source/EffekseerTest/EffekseerTest.h index 0da8513127a3..3530f3d178c8 100644 --- a/tests/cpp-tests/Source/EffekseerTest/EffekseerTest.h +++ b/tests/cpp-tests/Source/EffekseerTest/EffekseerTest.h @@ -25,7 +25,7 @@ #ifndef _EFFEKSEERTEST_H_ #define _EFFEKSEERTEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #include "EffekseerForCocos2d-x.h" diff --git a/tests/cpp-tests/Source/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp b/tests/cpp-tests/Source/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp index 6a116a6aeb56..3905d98cfb99 100644 --- a/tests/cpp-tests/Source/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp +++ b/tests/cpp-tests/Source/ExtensionsTest/AssetsManagerExTest/AssetsManagerExTest.cpp @@ -24,7 +24,7 @@ #include "AssetsManagerExTest.h" #include "../../testResource.h" -#include "axmol.h" +#include "axmol/axmol.h" using namespace ax; USING_NS_AX_EXT; diff --git a/tests/cpp-tests/Source/ExtensionsTest/JSONDefaultTest/JSONDefaultTest.h b/tests/cpp-tests/Source/ExtensionsTest/JSONDefaultTest/JSONDefaultTest.h index 14aa857393df..a215d41e8174 100644 --- a/tests/cpp-tests/Source/ExtensionsTest/JSONDefaultTest/JSONDefaultTest.h +++ b/tests/cpp-tests/Source/ExtensionsTest/JSONDefaultTest/JSONDefaultTest.h @@ -25,9 +25,9 @@ #ifndef _JSONDEFAULT_TEST_H_ #define _JSONDEFAULT_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "BaseTest.h" -#include "2d/Label.h" +#include "axmol/2d/Label.h" DEFINE_TEST_SUITE(JSONDefaultTests); diff --git a/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/CustomTableViewCell.h b/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/CustomTableViewCell.h index 1b2e26a4497f..d1def7351fba 100644 --- a/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/CustomTableViewCell.h +++ b/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/CustomTableViewCell.h @@ -25,7 +25,7 @@ #ifndef __CUSTOMTABELVIEWCELL_H__ #define __CUSTOMTABELVIEWCELL_H__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" #include "GUI/ControlExtension/ControlExtensions.h" #include "GUI/ScrollView/ScrollView.h" diff --git a/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/TableViewTestScene.h b/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/TableViewTestScene.h index fc3c6f6882d4..2860d6ac116c 100644 --- a/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/TableViewTestScene.h +++ b/tests/cpp-tests/Source/ExtensionsTest/TableViewTest/TableViewTestScene.h @@ -25,7 +25,7 @@ #ifndef __TABLEVIEWTESTSCENE_H__ #define __TABLEVIEWTESTSCENE_H__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" #include "BaseTest.h" diff --git a/tests/cpp-tests/Source/FontTest/FontTest.cpp b/tests/cpp-tests/Source/FontTest/FontTest.cpp index b93089b3a43b..7244f5fa3429 100644 --- a/tests/cpp-tests/Source/FontTest/FontTest.cpp +++ b/tests/cpp-tests/Source/FontTest/FontTest.cpp @@ -24,8 +24,8 @@ #include "FontTest.h" #include "../testResource.h" -#include "2d/FontAtlasCache.h" -#include "2d/FontFreeType.h" +#include "axmol/2d/FontAtlasCache.h" +#include "axmol/2d/FontFreeType.h" using namespace ax; @@ -105,9 +105,9 @@ void FontTest::showFont(std::string_view fontFile) auto right = Label::createWithSystemFont("alignment right", fontFile, fontSize, blockSize, TextHAlignment::RIGHT, verticalAlignment[vAlignIdx]); - auto leftColor = LayerColor::create(Color4B(100, 100, 100, 255), blockSize.width, blockSize.height); - auto centerColor = LayerColor::create(Color4B(200, 100, 100, 255), blockSize.width, blockSize.height); - auto rightColor = LayerColor::create(Color4B(100, 100, 200, 255), blockSize.width, blockSize.height); + auto leftColor = LayerColor::create(Color32(100, 100, 100, 255), blockSize.width, blockSize.height); + auto centerColor = LayerColor::create(Color32(200, 100, 100, 255), blockSize.width, blockSize.height); + auto rightColor = LayerColor::create(Color32(100, 100, 200, 255), blockSize.width, blockSize.height); leftColor->setIgnoreAnchorPointForPosition(false); centerColor->setIgnoreAnchorPointForPosition(false); @@ -202,9 +202,9 @@ void FontNoReplacementTest::onEnter() auto right = Label::createWithTTF("fonts/Schwarzwald.ttf" + suffix, "fonts/Schwarzwald.ttf", fontSize, blockSize, TextHAlignment::RIGHT, verticalAlignment[0]); - auto leftColor = LayerColor::create(Color4B(100, 100, 100, 255), blockSize.width, blockSize.height); - auto centerColor = LayerColor::create(Color4B(200, 100, 100, 255), blockSize.width, blockSize.height); - auto rightColor = LayerColor::create(Color4B(100, 100, 200, 255), blockSize.width, blockSize.height); + auto leftColor = LayerColor::create(Color32(100, 100, 100, 255), blockSize.width, blockSize.height); + auto centerColor = LayerColor::create(Color32(200, 100, 100, 255), blockSize.width, blockSize.height); + auto rightColor = LayerColor::create(Color32(100, 100, 200, 255), blockSize.width, blockSize.height); leftColor->setIgnoreAnchorPointForPosition(false); centerColor->setIgnoreAnchorPointForPosition(false); diff --git a/tests/cpp-tests/Source/FontTest/FontTest.h b/tests/cpp-tests/Source/FontTest/FontTest.h index da6fa6904675..05051571fa23 100644 --- a/tests/cpp-tests/Source/FontTest/FontTest.h +++ b/tests/cpp-tests/Source/FontTest/FontTest.h @@ -25,7 +25,7 @@ #ifndef _FONT_TEST_H_ #define _FONT_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(FontTests); diff --git a/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.cpp b/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.cpp index 18ea083d0d0b..878969323fda 100644 --- a/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.cpp +++ b/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.cpp @@ -1,4 +1,4 @@ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "ImGuiTest.h" #if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) diff --git a/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.h b/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.h index 21edbd6f38c8..b83280bab6e4 100644 --- a/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.h +++ b/tests/cpp-tests/Source/ImGuiTest/ImGuiTest.h @@ -26,7 +26,7 @@ #ifndef _IMGUIEXT_TEST_H_ #define _IMGUIEXT_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) diff --git a/tests/cpp-tests/Source/InputTest/MouseTest.h b/tests/cpp-tests/Source/InputTest/MouseTest.h index a2a6e8bd8a62..7210b85c370b 100644 --- a/tests/cpp-tests/Source/InputTest/MouseTest.h +++ b/tests/cpp-tests/Source/InputTest/MouseTest.h @@ -25,7 +25,7 @@ #ifndef __MOUSE_TEST_H_ #define __MOUSE_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(MouseTests); diff --git a/tests/cpp-tests/Source/JNITest/JNITest.cpp b/tests/cpp-tests/Source/JNITest/JNITest.cpp index 72f66effd4dc..6b2f86fad6f5 100644 --- a/tests/cpp-tests/Source/JNITest/JNITest.cpp +++ b/tests/cpp-tests/Source/JNITest/JNITest.cpp @@ -27,7 +27,7 @@ # include "JNITest.h" -# include "platform/android/jni/JniHelper.h" +# include "axmol/platform/android/jni/JniHelper.h" # include diff --git a/tests/cpp-tests/Source/JNITest/JNITest.h b/tests/cpp-tests/Source/JNITest/JNITest.h index a5cc70fff610..0586fef09c75 100644 --- a/tests/cpp-tests/Source/JNITest/JNITest.h +++ b/tests/cpp-tests/Source/JNITest/JNITest.h @@ -27,7 +27,7 @@ #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) -# include "cocos2d.h" +# include "axmol/cocos2d.h" # include "../BaseTest.h" DEFINE_TEST_SUITE(JNITests); diff --git a/tests/cpp-tests/Source/LabelTest/LabelTestNew.cpp b/tests/cpp-tests/Source/LabelTest/LabelTestNew.cpp index b583bfb9a722..528440343d39 100644 --- a/tests/cpp-tests/Source/LabelTest/LabelTestNew.cpp +++ b/tests/cpp-tests/Source/LabelTest/LabelTestNew.cpp @@ -25,8 +25,8 @@ #include "LabelTestNew.h" #include "../testResource.h" -#include "renderer/Renderer.h" -#include "2d/FontAtlasCache.h" +#include "axmol/renderer/Renderer.h" +#include "axmol/2d/FontAtlasCache.h" using namespace ax; using namespace ui; @@ -67,7 +67,7 @@ class LabelIssue1336 : public AtlasDemoNew config.faceSize = 72; auto overlapingLabel = Label::createWithTTF(config, "Te"); overlapingLabel->setPosition(Vec2(size.width / 2, size.height / 2)); - overlapingLabel->setColor(ax::Color3B::WHITE); + overlapingLabel->setColor(ax::Color32::WHITE); overlapingLabel->setScale(10); addChild(overlapingLabel, 1); } @@ -179,7 +179,7 @@ LabelFNTColorAndOpacity::LabelFNTColorAndOpacity() { _time = 0; - auto col = LayerColor::create(Color4B(128, 128, 128, 255)); + auto col = LayerColor::create(Color32(128, 128, 128, 255)); addChild(col, -10); auto label1 = Label::createWithBMFont("fonts/bitmapFontTest2.fnt", "Test"); @@ -193,7 +193,7 @@ LabelFNTColorAndOpacity::LabelFNTColorAndOpacity() label1->runAction(repeat); auto label2 = Label::createWithBMFont("fonts/bitmapFontTest2.fnt", "Test"); - label2->setColor(Color3B::RED); + label2->setColor(Color32::RED); addChild(label2, 0, kTagBitmapAtlas2); auto tint = Sequence::create(TintTo::create(1, 255, 0, 0), TintTo::create(1, 0, 255, 0), TintTo::create(1, 0, 0, 255), nullptr); @@ -243,8 +243,8 @@ LabelFNTSpriteActions::LabelFNTSpriteActions() auto s = Director::getInstance()->getWinSize(); auto drawNode = DrawNode::create(); - drawNode->drawLine(Vec2(0.0f, s.height / 2), Vec2(s.width, s.height / 2), Color4F(1.0f, 1.0f, 1.0f, 1.0f)); - drawNode->drawLine(Vec2(s.width / 2, 0.0f), Vec2(s.width / 2, s.height), Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + drawNode->drawLine(Vec2(0.0f, s.height / 2), Vec2(s.width, s.height / 2), Color(1.0f, 1.0f, 1.0f, 1.0f)); + drawNode->drawLine(Vec2(s.width / 2, 0.0f), Vec2(s.width / 2, s.height), Color(1.0f, 1.0f, 1.0f, 1.0f)); addChild(drawNode, -1); // Upper Label @@ -361,19 +361,19 @@ LabelFNTColor::LabelFNTColor() auto winSize = Director::getInstance()->getWinSize(); auto label = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "Blue"); - label->setColor(Color3B::BLUE); + label->setColor(Color32::BLUE); addChild(label); label->setPosition(winSize.width / 2, winSize.height * 0.7f); label = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "Red"); addChild(label); label->setPosition(winSize.width / 2, winSize.height * 0.5f); - label->setColor(Color3B::RED); + label->setColor(Color32::RED); label = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "Green"); addChild(label); label->setPosition(winSize.width / 2, winSize.height * 0.3f); - label->setColor(Color3B::GREEN); + label->setColor(Color32::GREEN); label->setString("Green"); } @@ -563,7 +563,7 @@ LabelFNTGlyphDesigner::LabelFNTGlyphDesigner() { auto winSize = Director::getInstance()->getWinSize(); - auto layer = LayerColor::create(Color4B(128, 128, 128, 255)); + auto layer = LayerColor::create(Color32(128, 128, 128, 255)); addChild(layer, -10); auto label1 = Label::createWithBMFont("fonts/futura-48.fnt", "Testing Glyph Designer"); @@ -704,11 +704,11 @@ void LabelFNTMultiLineAlignment::selectAlignmentItem(ax::MenuItemFont* item) { if (this->_lastAlignmentItem && this->_lastAlignmentItem != item) { - this->_lastAlignmentItem->setColor(Color3B::WHITE); + this->_lastAlignmentItem->setColor(Color32::WHITE); } this->_lastAlignmentItem = item; - item->setColor(Color3B::RED); + item->setColor(Color32::RED); switch (item->getTag()) { @@ -731,11 +731,11 @@ void LabelFNTMultiLineAlignment::selectSentenceItem(ax::MenuItemFont* item) { if (this->_lastSentenceItem && this->_lastSentenceItem != item) { - this->_lastSentenceItem->setColor(Color3B::WHITE); + this->_lastSentenceItem->setColor(Color32::WHITE); } this->_lastSentenceItem = item; - item->setColor(Color3B::RED); + item->setColor(Color32::RED); auto str = this->getItemString(item); this->_label->setString(str); @@ -929,7 +929,7 @@ LabelFNTBounds::LabelFNTBounds() { auto s = Director::getInstance()->getWinSize(); - auto layer = LayerColor::create(Color4B(128, 128, 128, 255)); + auto layer = LayerColor::create(Color32(128, 128, 128, 255)); addChild(layer, -10); // LabelBMFont @@ -948,7 +948,7 @@ LabelFNTBounds::LabelFNTBounds() Vec2 vertices[4] = {Vec2(origin.width, origin.height), Vec2(labelSize.width + origin.width, origin.height), Vec2(labelSize.width + origin.width, labelSize.height + origin.height), Vec2(origin.width, labelSize.height + origin.height)}; - drawNode->drawPoly(vertices, 4, true, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + drawNode->drawPoly(vertices, 4, true, Color(1.0f, 1.0f, 1.0f, 1.0f)); addChild(drawNode); } @@ -1046,19 +1046,19 @@ LabelTTFColor::LabelTTFColor() // Green auto label1 = Label::createWithTTF(ttfConfig, "Green", TextHAlignment::CENTER, size.width); label1->setPosition(size.width / 2, size.height * 0.5f); - label1->setTextColor(Color4B::GREEN); + label1->setTextColor(Color32::GREEN); addChild(label1); // Red auto label2 = Label::createWithTTF(ttfConfig, "Red", TextHAlignment::CENTER, size.width); label2->setPosition(size.width / 2, size.height * 0.65f); - label2->setTextColor(Color4B::RED); + label2->setTextColor(Color32::RED); addChild(label2); // Blue auto label3 = Label::createWithTTF(ttfConfig, "Blue", TextHAlignment::CENTER, size.width); label3->setPosition(size.width / 2, size.height * 0.35f); - label3->setTextColor(Color4B::BLUE); + label3->setTextColor(Color32::BLUE); addChild(label3); } @@ -1138,15 +1138,15 @@ LabelTTFCJKWrappingTest::LabelTTFCJKWrappingTest() drawNode->setAnchorPoint(Vec2(0, 0)); this->addChild(drawNode); drawNode->drawSegment(Vec2(size.width * 0.1f, size.height * 0.8f), Vec2(size.width * 0.1, 0.0f), 1, - Color4F(1.0f, 0.0f, 0.0f, 1.0f)); + Color(1.0f, 0.0f, 0.0f, 1.0f)); drawNode->drawSegment(Vec2(size.width * 0.85f, size.height * 0.8f), Vec2(size.width * 0.85f, 0.0f), 1, - Color4F(1.0f, 0.0f, 0.0f, 1.0f)); + Color(1.0f, 0.0f, 0.0f, 1.0f)); TTFConfig ttfConfig("fonts/HKYuanMini.ttf", 25, GlyphCollection::DYNAMIC); auto label1 = Label::createWithTTF(ttfConfig, "你好,Axmol Label.", TextHAlignment::LEFT, size.width * 0.75f); if (label1) { - label1->setTextColor(Color4B(128, 255, 255, 255)); + label1->setTextColor(Color32(128, 255, 255, 255)); label1->setPosition(Vec2(size.width * 0.1f, size.height * 0.6f)); label1->setAnchorPoint(Vec2(0.0f, 0.5f)); this->addChild(label1); @@ -1159,7 +1159,7 @@ LabelTTFCJKWrappingTest::LabelTTFCJKWrappingTest() auto label2 = Label::createWithTTF(ttfConfig, "早上好,Axmol Label.", TextHAlignment::LEFT, size.width * 0.75f); if (label2) { - label2->setTextColor(Color4B(255, 128, 255, 255)); + label2->setTextColor(Color32(255, 128, 255, 255)); label2->setPosition(Vec2(size.width * 0.1f, size.height * 0.4f)); label2->setAnchorPoint(Vec2(0.0f, 0.5f)); this->addChild(label2); @@ -1169,7 +1169,7 @@ LabelTTFCJKWrappingTest::LabelTTFCJKWrappingTest() size.width * 0.75f); if (label3) { - label3->setTextColor(Color4B(255, 255, 128, 255)); + label3->setTextColor(Color32(255, 255, 128, 255)); label3->setPosition(Vec2(size.width * 0.1f, size.height * 0.2f)); label3->setAnchorPoint(Vec2(0.0f, 0.5f)); this->addChild(label3); @@ -1292,7 +1292,7 @@ LabelTTFDistanceField::LabelTTFDistanceField() auto label1 = Label::createWithTTF(ttfConfig, "Distance Field", TextHAlignment::CENTER, size.width); label1->setPosition(Vec2(size.width / 2, size.height * 0.6f)); - label1->setTextColor(Color4B::GREEN); + label1->setTextColor(Color32::GREEN); addChild(label1); auto action = Sequence::create(DelayTime::create(1.0f), ScaleTo::create(6.0f, 5.0f, 5.0f), @@ -1306,11 +1306,11 @@ LabelTTFDistanceField::LabelTTFDistanceField() borderDraw->clear(); Vec2 vertices[4] = {Vec2::ZERO, Vec2(labelContentSize.width, 0.0f), Vec2(labelContentSize.width, labelContentSize.height), Vec2(0.0f, labelContentSize.height)}; - borderDraw->drawPoly(vertices, 4, true, Color4F::RED); + borderDraw->drawPoly(vertices, 4, true, Color::RED); auto label2 = Label::createWithTTF(ttfConfig, "Distance Field", TextHAlignment::CENTER, size.width); label2->setPosition(Vec2(size.width / 2, size.height * 0.3f)); - label2->setTextColor(Color4B::RED); + label2->setTextColor(Color32::RED); addChild(label2); // Draw the label border @@ -1320,7 +1320,7 @@ LabelTTFDistanceField::LabelTTFDistanceField() borderDraw2->clear(); Vec2 vertices2[4] = {Vec2::ZERO, Vec2(labelContentSize2.width, 0.0f), Vec2(labelContentSize2.width, labelContentSize2.height), Vec2(0.0f, labelContentSize2.height)}; - borderDraw2->drawPoly(vertices2, 4, true, Color4F::GREEN); + borderDraw2->drawPoly(vertices2, 4, true, Color::GREEN); } std::string LabelTTFDistanceField::title() const @@ -1355,7 +1355,7 @@ LabelTitleButtonTTFDistanceField::LabelTitleButtonTTFDistanceField() FontFreeType::setShareDistanceFieldEnabled(false); button = ax::ui::Button::create(); button->setTitleText("Should be the same size"); - button->setTitleColor(Color3B::RED); + button->setTitleColor(Color32::RED); button->setTitleFontName("fonts/Marker Felt.ttf"); button->setTitleFontSize(20); this->addChild(button); @@ -1364,7 +1364,7 @@ LabelTitleButtonTTFDistanceField::LabelTitleButtonTTFDistanceField() FontFreeType::setShareDistanceFieldEnabled(true); button = ax::ui::Button::create(); button->setTitleText("Should be the same size"); - button->setTitleColor(Color3B::RED); + button->setTitleColor(Color32::RED); button->setTitleFontName("fonts/Marker Felt.ttf"); button->setTitleFontSize(20); this->addChild(button); @@ -1420,8 +1420,8 @@ LabelTTFSDF::LabelTTFSDF() [=, this](Object* obj, ax::ui::CheckBox::EventType type) { if (type == ax::ui::CheckBox::EventType::SELECTED) { - _labelSDF->enableShadow(Color4B::YELLOW, Vec2(-1, -1)); - _labelNormal->enableShadow(Color4B::YELLOW, Vec2(-1, -1)); + _labelSDF->enableShadow(Color32::YELLOW, Vec2(-1, -1)); + _labelNormal->enableShadow(Color32::YELLOW, Vec2(-1, -1)); } else { @@ -1467,8 +1467,8 @@ LabelTTFSDF::LabelTTFSDF() float size = 1 + slider->getPercent() / 10; if (!slider->isEnabled()) return; - _labelSDF->enableOutline(Color4B::GREEN, size); - _labelNormal->enableOutline(Color4B::GREEN, size); + _labelSDF->enableOutline(Color32::GREEN, size); + _labelNormal->enableOutline(Color32::GREEN, size); }); initToggleCheckboxes(); _sliderOutline->setEnabled(false); @@ -1492,7 +1492,7 @@ ui::Slider* LabelTTFSDF::initSlider(std::string content, addChild(slider2, 999); auto label = Label::createWithSystemFont(content + ": ", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(pos - Vec2(slider2->getContentSize().width * 0.3, 0)); label->setAnchorPoint(Vec2(1, 0.5)); this->addChild(label); @@ -1551,12 +1551,12 @@ void LabelTTFSDF::onChangedRadioButtonSelect(RadioButton* radioButton, RadioButt case 0: break; case 1: - _labelNormal->enableGlow(Color4B::RED); - _labelSDF->enableGlow(Color4B::RED); + _labelNormal->enableGlow(Color32::RED); + _labelSDF->enableGlow(Color32::RED); break; case 2: - _labelSDF->enableOutline(Color4B::GREEN, 1); - _labelNormal->enableOutline(Color4B::GREEN, 1); + _labelSDF->enableOutline(Color32::GREEN, 1); + _labelNormal->enableOutline(Color32::GREEN, 1); _sliderOutline->setEnabled(true); _sliderOutline->setOpacity(255); break; @@ -1569,7 +1569,7 @@ void LabelTTFSDF::initToggleLabel(std::string content, std::function callback) { auto label = Label::createWithSystemFont(content + ":", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(pos); label->setAnchorPoint(Vec2(1, 0.5)); this->addChild(label); @@ -1601,7 +1601,7 @@ LabelOutlineAndGlowTest::LabelOutlineAndGlowTest() { auto size = Director::getInstance()->getWinSize(); - auto bg = LayerColor::create(Color4B(200, 191, 231, 255)); + auto bg = LayerColor::create(Color32(200, 191, 231, 255)); this->addChild(bg); TTFConfig ttfConfig("fonts/arial.ttf", 40, GlyphCollection::DYNAMIC, nullptr, true); @@ -1609,16 +1609,16 @@ LabelOutlineAndGlowTest::LabelOutlineAndGlowTest() // Glow SDF (GPU) auto label1 = Label::createWithTTF(ttfConfig, "Glow1", TextHAlignment::CENTER, size.width); label1->setPosition(Vec2(size.width / 2, size.height * 0.7)); - label1->setTextColor(Color4B::GREEN); - label1->enableGlow(Color4B::YELLOW); + label1->setTextColor(Color32::GREEN); + label1->enableGlow(Color32::YELLOW); addChild(label1); // Glow normal(CPU) ttfConfig.distanceFieldEnabled = false; auto label2 = Label::createWithTTF(ttfConfig, "Glow2", TextHAlignment::CENTER, size.width); label2->setPosition(Vec2(size.width / 2, size.height * 0.6)); - label2->setTextColor(Color4B::GREEN); - label2->enableGlow(Color4B::YELLOW); + label2->setTextColor(Color32::GREEN); + label2->enableGlow(Color32::YELLOW); addChild(label2); // Outline SDF(GPU) @@ -1626,8 +1626,8 @@ LabelOutlineAndGlowTest::LabelOutlineAndGlowTest() ttfConfig.outlineSize = 2; auto label3 = Label::createWithTTF(ttfConfig, "Outline1", TextHAlignment::CENTER, size.width); label3->setPosition(Vec2(size.width / 2, size.height * 0.48)); - label3->setTextColor(Color4B::RED); - label3->enableOutline(Color4B::BLUE); + label3->setTextColor(Color32::RED); + label3->enableOutline(Color32::BLUE); addChild(label3); // Outline normal(CPU by freetype2) @@ -1635,8 +1635,8 @@ LabelOutlineAndGlowTest::LabelOutlineAndGlowTest() ttfConfig.outlineSize = 2; auto label4 = Label::createWithTTF(ttfConfig, "Outline2", TextHAlignment::CENTER, size.width); label4->setPosition(Vec2(size.width / 2, size.height * 0.36)); - label4->setTextColor(Color4B::RED); - label4->enableOutline(Color4B::BLUE, 2); + label4->setTextColor(Color32::RED); + label4->enableOutline(Color32::BLUE, 2); addChild(label4); } @@ -1658,7 +1658,7 @@ void LabelShadowTest::onEnter() auto size = Director::getInstance()->getWinSize(); - auto bg = LayerColor::create(Color4B(200, 191, 231, 255)); + auto bg = LayerColor::create(Color32(200, 191, 231, 255)); this->addChild(bg); auto slider = ui::Slider::create(); @@ -1692,28 +1692,28 @@ void LabelShadowTest::onEnter() shadowLabelTTF = Label::createWithTTF(ttfConfig, "TTF:Shadow"); shadowLabelTTF->setPosition(Vec2(size.width / 2, horizontalSliderY + step * (0.5f + 3))); - shadowLabelTTF->setTextColor(Color4B::RED); - shadowLabelTTF->enableShadow(Color4B::BLACK); + shadowLabelTTF->setTextColor(Color32::RED); + shadowLabelTTF->enableShadow(Color32::BLACK); addChild(shadowLabelTTF); shadowLabelOutline = Label::createWithTTF(ttfConfig, "TTF:Shadow"); shadowLabelOutline->setPosition(Vec2(size.width / 2, horizontalSliderY + step * (0.5f + 2))); - shadowLabelOutline->setTextColor(Color4B::RED); - shadowLabelOutline->enableOutline(Color4B::YELLOW, 1); - shadowLabelOutline->enableShadow(Color4B::GREEN); + shadowLabelOutline->setTextColor(Color32::RED); + shadowLabelOutline->enableOutline(Color32::YELLOW, 1); + shadowLabelOutline->enableShadow(Color32::GREEN); addChild(shadowLabelOutline); shadowLabelGrow = Label::createWithTTF(ttfConfig, "TTF:Shadow"); shadowLabelGrow->setPosition(Vec2(size.width / 2, horizontalSliderY + step * (0.5f + 1))); - shadowLabelGrow->setTextColor(Color4B::RED); - shadowLabelGrow->enableGlow(Color4B::YELLOW); - shadowLabelGrow->enableShadow(Color4B::BLUE); + shadowLabelGrow->setTextColor(Color32::RED); + shadowLabelGrow->enableGlow(Color32::YELLOW); + shadowLabelGrow->enableShadow(Color32::BLUE); addChild(shadowLabelGrow); shadowLabelBMFont = Label::createWithBMFont("fonts/bitmapFontTest.fnt", "BMFont:Shadow"); shadowLabelBMFont->setPosition(Vec2(size.width / 2, horizontalSliderY + step * 0.5f)); - shadowLabelBMFont->setColor(Color3B::RED); - shadowLabelBMFont->enableShadow(Color4B::GREEN); + shadowLabelBMFont->setColor(Color32::RED); + shadowLabelBMFont->enableShadow(Color32::GREEN); addChild(shadowLabelBMFont); } @@ -1725,10 +1725,10 @@ void LabelShadowTest::sliderEvent(Object* pSender, ui::Slider::EventType type) Slider* slider2 = (Slider*)this->getChildByTag(2); auto offset = Size(slider->getPercent() - 50, 50 - slider2->getPercent()); - shadowLabelTTF->enableShadow(Color4B::BLACK, offset); - shadowLabelBMFont->enableShadow(Color4B::GREEN, offset); - shadowLabelOutline->enableShadow(Color4B::GREEN, offset); - shadowLabelGrow->enableShadow(Color4B::BLUE, offset); + shadowLabelTTF->enableShadow(Color32::BLACK, offset); + shadowLabelBMFont->enableShadow(Color32::GREEN, offset); + shadowLabelOutline->enableShadow(Color32::GREEN, offset); + shadowLabelGrow->enableShadow(Color32::BLUE, offset); } } @@ -1802,7 +1802,7 @@ LabelCharMapColorTest::LabelCharMapColorTest() addChild(label2, 0, kTagSprite2); label2->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); label2->setPosition(Vec2(10, 200)); - label2->setColor(Color3B::RED); + label2->setColor(Color32::RED); auto fade = FadeOut::create(1.0f); auto fade_in = fade->reverse(); @@ -1873,7 +1873,7 @@ LabelTTFOldNew::LabelTTFOldNew() auto label1 = Label::createWithSystemFont("Axmol Label Test", "arial", 24); addChild(label1, 0, kTagBitmapAtlas1); label1->setPosition(Vec2(s.width / 2, delta * 2)); - label1->setColor(Color3B::RED); + label1->setColor(Color32::RED); TTFConfig ttfConfig("fonts/arial.ttf", 24); auto label2 = Label::createWithTTF(ttfConfig, "Axmol Label Test"); @@ -1890,7 +1890,7 @@ LabelTTFOldNew::LabelTTFOldNew() Vec2 vertices[4] = {Vec2(origin.width, origin.height), Vec2(labelSize.width + origin.width, origin.height), Vec2(labelSize.width + origin.width, labelSize.height + origin.height), Vec2(origin.width, labelSize.height + origin.height)}; - drawNode->drawPoly(vertices, 4, true, Color4F(1.0f, 0.0f, 0.0f, 1.0f)); + drawNode->drawPoly(vertices, 4, true, Color(1.0f, 0.0f, 0.0f, 1.0f)); labelSize = label2->getContentSize(); origin = Director::getInstance()->getWinSize(); @@ -1901,7 +1901,7 @@ LabelTTFOldNew::LabelTTFOldNew() Vec2 vertices2[4] = {Vec2(origin.width, origin.height), Vec2(labelSize.width + origin.width, origin.height), Vec2(labelSize.width + origin.width, labelSize.height + origin.height), Vec2(origin.width, labelSize.height + origin.height)}; - drawNode->drawPoly(vertices2, 4, true, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + drawNode->drawPoly(vertices2, 4, true, Color(1.0f, 1.0f, 1.0f, 1.0f)); addChild(drawNode); } @@ -1946,7 +1946,7 @@ LabelAlignmentTest::LabelAlignmentTest() auto s = Director::getInstance()->getWinSize(); auto pos = Vec2((s.width - blockSize.width) / 2, (s.height - blockSize.height) / 2); - auto colorLayer = LayerColor::create(Color4B(100, 100, 100, 255), blockSize.width, blockSize.height); + auto colorLayer = LayerColor::create(Color32(100, 100, 100, 255), blockSize.width, blockSize.height); colorLayer->setAnchorPoint(Vec2::ANCHOR_BOTTOM_LEFT); colorLayer->setPosition(pos); @@ -2069,14 +2069,14 @@ LabelLineHeightTest::LabelLineHeightTest() { auto size = Director::getInstance()->getWinSize(); - auto bg = LayerColor::create(Color4B(200, 191, 231, 255)); + auto bg = LayerColor::create(Color32(200, 191, 231, 255)); this->addChild(bg); TTFConfig ttfConfig("fonts/arial.ttf", 25, GlyphCollection::DYNAMIC, nullptr, false); label = Label::createWithTTF(ttfConfig, "Test\nLine\nHeight"); label->setPosition(Vec2(size.width / 2, size.height * 0.5f)); - label->setTextColor(Color4B::RED); + label->setTextColor(Color32::RED); addChild(label); auto slider = ui::Slider::create(); @@ -2113,14 +2113,14 @@ LabelAdditionalKerningTest::LabelAdditionalKerningTest() { auto size = Director::getInstance()->getWinSize(); - auto bg = LayerColor::create(Color4B(200, 191, 231, 255)); + auto bg = LayerColor::create(Color32(200, 191, 231, 255)); this->addChild(bg); TTFConfig ttfConfig("fonts/arial.ttf", 40, GlyphCollection::DYNAMIC, nullptr, false); label = Label::createWithTTF(ttfConfig, "Test additional kerning"); label->setPosition(size.width / 2, size.height * 0.5f); - label->setTextColor(Color4B::RED); + label->setTextColor(Color32::RED); addChild(label); auto slider = ui::Slider::create(); @@ -2174,7 +2174,7 @@ std::string LabelIssue8492Test::subtitle() const LabelMultilineWithOutline::LabelMultilineWithOutline() { auto label = Label::createWithTTF("Multi-line text\nwith\noutline feature", "fonts/arial.ttf", 24); - label->enableOutline(Color4B::ORANGE, 1); + label->enableOutline(Color32::ORANGE, 1); label->setPosition(VisibleRect::center()); addChild(label); } @@ -2260,24 +2260,24 @@ LabelSystemFontColor::LabelSystemFontColor() { auto size = Director::getInstance()->getWinSize(); - auto label1 = Label::createWithSystemFont("Color4B::Red", "fonts/arial.ttf", 20); + auto label1 = Label::createWithSystemFont("Color32::Red", "fonts/arial.ttf", 20); label1->setPosition(Vec2(size.width / 2, size.height * 0.3f)); - label1->setTextColor(Color4B::RED); + label1->setTextColor(Color32::RED); addChild(label1); - auto label2 = Label::createWithSystemFont("Color4B::Green", "fonts/arial.ttf", 20); + auto label2 = Label::createWithSystemFont("Color32::Green", "fonts/arial.ttf", 20); label2->setPosition(Vec2(size.width / 2, size.height * 0.4f)); - label2->setTextColor(Color4B::GREEN); + label2->setTextColor(Color32::GREEN); addChild(label2); - auto label3 = Label::createWithSystemFont("Color4B::Blue", "fonts/arial.ttf", 20); + auto label3 = Label::createWithSystemFont("Color32::Blue", "fonts/arial.ttf", 20); label3->setPosition(Vec2(size.width / 2, size.height * 0.5f)); - label3->setTextColor(Color4B::BLUE); + label3->setTextColor(Color32::BLUE); addChild(label3); - auto label4 = Label::createWithSystemFont("Color4B(0, 0, 255, 100)", "fonts/arial.ttf", 20); + auto label4 = Label::createWithSystemFont("Color32(0, 0, 255, 100)", "fonts/arial.ttf", 20); label4->setPosition(Vec2(size.width / 2, size.height * 0.6f)); - label4->setTextColor(Color4B(0, 0, 255, 100)); + label4->setTextColor(Color32(0, 0, 255, 100)); addChild(label4); } @@ -2344,7 +2344,7 @@ LabelIssue11699Test::LabelIssue11699Test() auto center = VisibleRect::center(); auto label = Label::createWithTTF("中国", "fonts/HKYuanMini.ttf", 150); - label->enableOutline(Color4B::RED, 2); + label->enableOutline(Color32::RED, 2); label->setPosition(center.x, center.y); addChild(label); } @@ -2379,7 +2379,7 @@ LabelIssue12409Test::LabelIssue12409Test() Vec2(labelOrigin.x, labelOrigin.y + labelSize.height)}; auto drawNode = DrawNode::create(); - drawNode->drawPoly(vertices, 4, true, Color4F::WHITE); + drawNode->drawPoly(vertices, 4, true, Color::WHITE); addChild(drawNode); } @@ -2443,9 +2443,9 @@ LabelIssue11585Test::LabelIssue11585Test() label->setPosition(center.x, center.y); addChild(label); - label->getLetter(0)->setColor(Color3B::RED); - label->getLetter(1)->setColor(Color3B::GREEN); - label->getLetter(2)->setColor(Color3B::BLUE); + label->getLetter(0)->setColor(Color32::RED); + label->getLetter(1)->setColor(Color32::GREEN); + label->getLetter(2)->setColor(Color32::BLUE); auto action = RepeatForever::create(Sequence::create(FadeOut::create(2), FadeIn::create(2), nullptr)); label->runAction(action); } @@ -2465,8 +2465,8 @@ LabelIssue10688Test::LabelIssue10688Test() auto center = VisibleRect::center(); auto label = Label::createWithTTF("Glow MenuItemLabel", "fonts/arial.ttf", 30); - label->setTextColor(Color4B::RED); - label->enableGlow(Color4B::YELLOW); + label->setTextColor(Color32::RED); + label->enableGlow(Color32::YELLOW); auto menuItem1 = MenuItemLabel::create(label, [](Object*) {}); menuItem1->setAnchorPoint(Vec2::ANCHOR_MIDDLE_LEFT); menuItem1->setPosition(center.x - label->getContentSize().width / 2, center.y); @@ -2584,7 +2584,7 @@ void LabelLayoutBaseTest::initFontSizeChange(const ax::Size& size) void LabelLayoutBaseTest::initWrapOption(const ax::Size& size) { auto label = Label::createWithSystemFont("Enable Wrap:", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(Vec2(size.width * 0.8f - 100, size.height * 0.8f)); this->addChild(label); @@ -2613,7 +2613,7 @@ void LabelLayoutBaseTest::initWrapOption(const ax::Size& size) void LabelLayoutBaseTest::initToggleLabelTypeOption(const ax::Size& size) { auto label = Label::createWithSystemFont("Toggle Label Type:", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(Vec2(size.width * 0.8f + 15, size.height * 0.8f)); this->addChild(label); @@ -2882,10 +2882,10 @@ void LabelLayoutBaseTest::updateDrawNodeSize(const ax::Size& drawNodeSize) Vec2(drawNodeSize.width + origin.width, drawNodeSize.height + origin.height), Vec2(origin.width, drawNodeSize.height + origin.height)}; _drawNode->clear(); - _drawNode->drawLine(vertices[0], vertices[1], Color4F(1.0f, 1.0f, 1.0f, 1.0f)); - _drawNode->drawLine(vertices[0], vertices[3], Color4F(1.0f, 1.0f, 1.0f, 1.0f)); - _drawNode->drawLine(vertices[2], vertices[3], Color4F(1.0f, 1.0f, 1.0f, 1.0f)); - _drawNode->drawLine(vertices[1], vertices[2], Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + _drawNode->drawLine(vertices[0], vertices[1], Color(1.0f, 1.0f, 1.0f, 1.0f)); + _drawNode->drawLine(vertices[0], vertices[3], Color(1.0f, 1.0f, 1.0f, 1.0f)); + _drawNode->drawLine(vertices[2], vertices[3], Color(1.0f, 1.0f, 1.0f, 1.0f)); + _drawNode->drawLine(vertices[1], vertices[2], Color(1.0f, 1.0f, 1.0f, 1.0f)); } LabelWrapByWordTest::LabelWrapByWordTest() @@ -3020,7 +3020,7 @@ LabelResizeTest::LabelResizeTest() stepper->setValue(12); auto label = Label::createWithSystemFont("Char Line break:", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f)); this->addChild(label); @@ -3086,7 +3086,7 @@ LabelToggleTypeTest::LabelToggleTypeTest() stepper->setValue(12); auto label = Label::createWithSystemFont("Char Line break:", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f)); this->addChild(label); @@ -3202,7 +3202,7 @@ LabelSystemFontTest::LabelSystemFontTest() _label->setOverflow(Label::Overflow::NONE); _label->setSystemFontName("Hiragino Sans GB"); _label->setSystemFontSize(20); - _label->enableOutline(Color4B::RED, 1.0); + _label->enableOutline(Color32::RED, 1.0); _label->setString("This is a very\n 我爱你中国\n long sentence"); _labelType = 2; @@ -3235,7 +3235,7 @@ LabelSystemFontTest::LabelSystemFontTest() }); auto label = Label::createWithSystemFont("char Line break:", "Arial", 10); - label->setColor(Color3B::WHITE); + label->setColor(Color32::WHITE); label->setPosition(Vec2(winSize.width * 0.1f, winSize.height * 0.8f)); this->addChild(label); @@ -3628,8 +3628,8 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline() // Glow SDF (GPU) auto label1 = Label::createWithTTF(ttfConf, "Glow1", TextHAlignment::CENTER, s.width); label1->setPosition(Vec2(s.width / 2, s.height * 0.7)); - label1->setTextColor(Color4B::GREEN); - label1->enableGlow(Color4B::YELLOW); + label1->setTextColor(Color32::GREEN); + label1->enableGlow(Color32::YELLOW); label1->enableUnderline(); label1->enableStrikethrough(); addChild(label1); @@ -3638,8 +3638,8 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline() ttfConf.distanceFieldEnabled = false; auto label2 = Label::createWithTTF(ttfConf, "Glow2", TextHAlignment::CENTER, s.width); label2->setPosition(Vec2(s.width / 2, s.height * 0.6)); - label2->setTextColor(Color4B::GREEN); - label2->enableGlow(Color4B::YELLOW); + label2->setTextColor(Color32::GREEN); + label2->enableGlow(Color32::YELLOW); label2->enableUnderline(); label2->enableStrikethrough(); addChild(label2); @@ -3649,8 +3649,8 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline() ttfConf.outlineSize = 2; auto label3 = Label::createWithTTF(ttfConf, "Outline1", TextHAlignment::CENTER, s.width); label3->setPosition(Vec2(s.width / 2, s.height * 0.48)); - label3->setTextColor(Color4B::RED); - label3->enableOutline(Color4B::BLUE); + label3->setTextColor(Color32::RED); + label3->enableOutline(Color32::BLUE); label3->enableUnderline(); label3->enableStrikethrough(); addChild(label3); @@ -3660,8 +3660,8 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline() ttfConf.outlineSize = 2; auto label4 = Label::createWithTTF(ttfConf, "Outline2", TextHAlignment::CENTER, s.width); label4->setPosition(Vec2(s.width / 2, s.height * 0.36)); - label4->setTextColor(Color4B::RED); - label4->enableOutline(Color4B::BLUE, 2); + label4->setTextColor(Color32::RED); + label4->enableOutline(Color32::BLUE, 2); label4->enableUnderline(); label4->enableStrikethrough(); addChild(label4); @@ -3677,29 +3677,29 @@ LabelUnderlineStrikethroughMultiline::LabelUnderlineStrikethroughMultiline() Label* labels[count]; labels[0] = Label::createWithSystemFont("SystemFont TextVAlignment::TOP\nusing setTextColor(255, 0, 255, 100)", font, 14, Vec2::ZERO, TextHAlignment::LEFT, TextVAlignment::TOP); - labels[0]->setTextColor(Color4B(255, 0, 255, 100)); - labels[0]->enableGlow(Color4B::BLUE); + labels[0]->setTextColor(Color32(255, 0, 255, 100)); + labels[0]->enableGlow(Color32::BLUE); labels[1] = Label::createWithSystemFont("SystemFont TextVAlignment::CENTER\nusing setColor(*RED*)", font, 14, Vec2::ZERO, TextHAlignment::RIGHT, TextVAlignment::CENTER); - labels[1]->setColor(Color3B::RED); - + labels[1]->setColor(Color32::RED); + labels[2] = Label::createWithSystemFont("SystemFont TextVAlignment::BOTTOM\nusingsetTextColor(*YELLOW)", font, 14, Vec2::ZERO, TextHAlignment::CENTER, TextVAlignment::BOTTOM); - labels[2]->setTextColor(Color4B::YELLOW); + labels[2]->setTextColor(Color32::YELLOW); labels[3] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nwith default color", TextHAlignment::CENTER, s.width); labels[4] = Label::createWithBMFont("fonts/bitmapFontTest5.fnt", "BMFont\nusing setTextColor(0, 255, 0, 100)", TextHAlignment::CENTER, s.width); - labels[4]->setTextColor(Color4B(0, 255, 0, 100)); + labels[4]->setTextColor(Color32(0, 255, 0, 100)); labels[5] = Label::createWithTTF(ttfConfig, "TTF setColor(*BLUE*)\nwith multiline 1\nand a much more longer multiline 2", TextHAlignment::LEFT, s.width); - labels[5]->setColor(Color3B::BLUE); + labels[5]->setColor(Color32::BLUE); labels[6] = Label::createWithTTF("TTF setTextColor(*RED*)\nwith multiline 1\nand a much more longer multiline 2", font, 14); - labels[6]->setTextColor(Color4B::RED); + labels[6]->setTextColor(Color32::RED); for (int i = 0; i < count; i++) { @@ -3930,28 +3930,28 @@ LabelIssue15214::LabelIssue15214() // 1 Label* label = Label::createWithTTF("TTF with setColor()", "fonts/arial.ttf", 24.0f); label->enableUnderline(); - label->setColor(ax::Color3B::BLUE); + label->setColor(ax::Color32::BLUE); label->setPosition(size.width / 2, size.height / 5 * 4); this->addChild(label); // 2 Label* label2 = Label::createWithSystemFont("System with setColor()", "Verdana", 24.0f); label2->enableUnderline(); - label2->setColor(ax::Color3B::BLUE); + label2->setColor(ax::Color32::BLUE); label2->setPosition(size.width / 2, size.height / 5 * 3); this->addChild(label2); // 3 Label* label3 = Label::createWithTTF("TTF with setTextColor()", "fonts/arial.ttf", 24.0f); label3->enableUnderline(); - label3->setTextColor(Color4B::BLUE); + label3->setTextColor(Color32::BLUE); label3->setPosition(size.width / 2, size.height / 5 * 2); this->addChild(label3); // 4 Label* label4 = Label::createWithSystemFont("System with setTextColor()", "Verdana", 24.0f); label4->enableUnderline(); - label4->setTextColor(Color4B::BLUE); + label4->setTextColor(Color32::BLUE); label4->setPosition(size.width / 2, size.height / 5 * 1); this->addChild(label4); } @@ -4009,7 +4009,7 @@ LabelIssue16471::LabelIssue16471() // if set false then testLabel:setTextColor is useful node->setCascadeColorEnabled(true); Label* label = Label::createWithTTF("Should be Yellow", "fonts/arial.ttf", 12); - label->setTextColor(Color4B::YELLOW); + label->setTextColor(Color32::YELLOW); node->addChild(label); } @@ -4035,16 +4035,16 @@ LabelIssue16717::LabelIssue16717() { auto label = Label::createWithTTF("Hello World", "fonts/arial.ttf", 70); label->setPosition(VisibleRect::center() + Vec2(0.0f, 40.0f)); - label->enableOutline(Color4B(0, 255, 0, 100), 10); // Set 100 alpha for outline - label->setTextColor(Color4B(0, 0, 255, 100)); // Also set 100 alpha for text + label->enableOutline(Color32(0, 255, 0, 100), 10); // Set 100 alpha for outline + label->setTextColor(Color32(0, 0, 255, 100)); // Also set 100 alpha for text addChild(label); } { auto label = Label::createWithTTF("Hello World", "fonts/arial.ttf", 70); label->setPosition(VisibleRect::center() + Vec2(0.0f, -40.0f)); - label->enableOutline(Color4B(0, 255, 0, 100), 10); // Set 100 alpha for outline - label->setTextColor(Color4B(0, 255, 0, 100)); // Also set 100 alpha for text + label->enableOutline(Color32(0, 255, 0, 100), 10); // Set 100 alpha for outline + label->setTextColor(Color32(0, 255, 0, 100)); // Also set 100 alpha for text addChild(label); } } @@ -4124,7 +4124,7 @@ LabelIssue20523::LabelIssue20523() auto size = Director::getInstance()->getWinSize(); auto _crashingLabel = Label::createWithTTF("0", "fonts/Marker Felt.ttf", 120); _crashingLabel->setPosition(Vec2(size.width / 2, size.height / 2)); - _crashingLabel->setColor(ax::Color3B(200, 200, 200)); + _crashingLabel->setColor(ax::Color32(200, 200, 200)); addChild(_crashingLabel, 1); //_crashingLabel->setWidth(size.width); @@ -4158,7 +4158,7 @@ LabelLetterColorsTest::LabelLetterColorsTest() addChild(label); label->setString("1\n2\n3"); - setLetterColors(label, Color3B::RED); + setLetterColors(label, Color32::RED); label->setString("abcd\ne"); // Must not crash at here. } @@ -4173,7 +4173,7 @@ std::string LabelLetterColorsTest::subtitle() const return "Should not crash!"; } -void LabelLetterColorsTest::setLetterColors(ax::Label* label, const ax::Color3B& color) +void LabelLetterColorsTest::setLetterColors(ax::Label* label, const ax::Color32& color) { int n = label->getStringLength(); for (int i = 0; i < n; ++i) diff --git a/tests/cpp-tests/Source/LabelTest/LabelTestNew.h b/tests/cpp-tests/Source/LabelTest/LabelTestNew.h index 3572c2c147ba..7bb68311e08e 100644 --- a/tests/cpp-tests/Source/LabelTest/LabelTestNew.h +++ b/tests/cpp-tests/Source/LabelTest/LabelTestNew.h @@ -27,8 +27,8 @@ #define _ATLAS_TEST_NEW_H_ #include "../BaseTest.h" -#include "renderer/CustomCommand.h" -#include "ui/CocosGUI.h" +#include "axmol/renderer/CustomCommand.h" +#include "axmol/ui/CocosGUI.h" #include "extensions/axmol-ext.h" #include "cocostudio/LocalizationManager.h" @@ -745,7 +745,7 @@ class LabelLayoutBaseTest : public AtlasDemoNew void setAlignmentTop(ax::Object* sender); void setAlignmentMiddle(ax::Object* sender); void setAlignmentBottom(ax::Object* sender); - + void initWrapOption(const ax::Size& size); void initToggleLabelTypeOption(const ax::Size& size); void initAlignmentOption(const ax::Size& size); @@ -1073,7 +1073,7 @@ class LabelLetterColorsTest : public AtlasDemoNew virtual std::string subtitle() const override; private: - static void setLetterColors(ax::Label* label, const ax::Color3B& color); + static void setLetterColors(ax::Label* label, const ax::Color32& color); }; #endif diff --git a/tests/cpp-tests/Source/LayerTest/LayerTest.cpp b/tests/cpp-tests/Source/LayerTest/LayerTest.cpp index d89e55161d4a..b5d02ec0c06f 100644 --- a/tests/cpp-tests/Source/LayerTest/LayerTest.cpp +++ b/tests/cpp-tests/Source/LayerTest/LayerTest.cpp @@ -24,7 +24,7 @@ #include "LayerTest.h" #include "../testResource.h" -#include "../core/ui/UIText.h" +#include "axmol/ui/UIText.h" using namespace ax; @@ -118,7 +118,7 @@ void LayerTestCascadingOpacityB::onEnter() LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(192, 0, 0, 255), s.width, s.height / 2); + auto layer1 = LayerColor::create(Color32(192, 0, 0, 255), s.width, s.height / 2); layer1->setCascadeColorEnabled(false); layer1->setPosition(Vec2(0.0f, s.height / 2)); @@ -158,7 +158,7 @@ void LayerTestCascadingOpacityC::onEnter() LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(192, 0, 0, 255), s.width, s.height / 2); + auto layer1 = LayerColor::create(Color32(192, 0, 0, 255), s.width, s.height / 2); layer1->setCascadeColorEnabled(false); layer1->setCascadeOpacityEnabled(false); @@ -214,11 +214,11 @@ void LayerTestCascadingColorA::onEnter() label->setPosition(Vec2(s.width / 2, s.height / 2)); layer1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(6, 255, 0, 255), TintTo::create(6, 255, 255, 255), DelayTime::create(1), nullptr))); + TintTo::create(6, Color32(255, 0, 255)), TintTo::create(6, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); sister1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(2, 255, 255, 0), TintTo::create(2, 255, 255, 255), TintTo::create(2, 0, 255, 255), - TintTo::create(2, 255, 255, 255), TintTo::create(2, 255, 0, 255), TintTo::create(2, 255, 255, 255), + TintTo::create(2, Color32(255, 255, 0)), TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(0, 255, 255)), + TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(255, 0, 255)), TintTo::create(2, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); // Enable cascading in scene @@ -235,7 +235,7 @@ void LayerTestCascadingColorB::onEnter() { LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(255, 255, 255, 255), s.width, s.height / 2); + auto layer1 = LayerColor::create(Color32(255, 255, 255, 255), s.width, s.height / 2); layer1->setPosition(Vec2(0.0f, s.height / 2)); @@ -253,11 +253,11 @@ void LayerTestCascadingColorB::onEnter() label->setPosition(Vec2(s.width / 2, 0.0f)); layer1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(6, 255, 0, 255), TintTo::create(6, 255, 255, 255), DelayTime::create(1), nullptr))); + TintTo::create(6, Color32(255, 0, 255)), TintTo::create(6, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); sister1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(2, 255, 255, 0), TintTo::create(2, 255, 255, 255), TintTo::create(2, 0, 255, 255), - TintTo::create(2, 255, 255, 255), TintTo::create(2, 255, 0, 255), TintTo::create(2, 255, 255, 255), + TintTo::create(2, Color32(255, 255, 0)), TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(0, 255, 255)), + TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(255, 0, 255)), TintTo::create(2, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); // Enable cascading in scene @@ -274,7 +274,7 @@ void LayerTestCascadingColorC::onEnter() { LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(255, 255, 255, 255), s.width, s.height / 2); + auto layer1 = LayerColor::create(Color32(255, 255, 255, 255), s.width, s.height / 2); layer1->setCascadeColorEnabled(false); layer1->setPosition(Vec2(0.0f, s.height / 2)); @@ -292,11 +292,11 @@ void LayerTestCascadingColorC::onEnter() label->setPosition(Vec2(s.width / 2, 0.0f)); layer1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(6, 255, 0, 255), TintTo::create(6, 255, 255, 255), DelayTime::create(1), nullptr))); + TintTo::create(6, Color32(255, 0, 255)), TintTo::create(6, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); sister1->runAction(RepeatForever::create(Sequence::create( - TintTo::create(2, 255, 255, 0), TintTo::create(2, 255, 255, 255), TintTo::create(2, 0, 255, 255), - TintTo::create(2, 255, 255, 255), TintTo::create(2, 255, 0, 255), TintTo::create(2, 255, 255, 255), + TintTo::create(2, Color32(255, 255, 0)), TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(0, 255, 255)), + TintTo::create(2, Color32(255, 255, 255)), TintTo::create(2, Color32(255, 0, 255)), TintTo::create(2, Color32(255, 255, 255)), DelayTime::create(1), nullptr))); } @@ -322,7 +322,7 @@ void LayerTest1::onEnter() _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, this); auto s = Director::getInstance()->getWinSize(); - auto layer = LayerColor::create(Color4B(0xFF, 0x00, 0x00, 0x80), 200, 200); + auto layer = LayerColor::create(Color32(0xFF, 0x00, 0x00, 0x80), 200, 200); layer->setIgnoreAnchorPointForPosition(false); layer->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -372,12 +372,12 @@ void LayerTest2::onEnter() LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(255, 255, 0, 80), 100, 300); + auto layer1 = LayerColor::create(Color32(255, 255, 0, 80), 100, 300); layer1->setPosition(Vec2(s.width / 3, s.height / 2)); layer1->setIgnoreAnchorPointForPosition(false); addChild(layer1, 1); - auto layer2 = LayerColor::create(Color4B(0, 0, 255, 255), 100, 300); + auto layer2 = LayerColor::create(Color32(0, 0, 255, 255), 100, 300); layer2->setPosition(Vec2((s.width / 3) * 2, s.height / 2)); layer2->setIgnoreAnchorPointForPosition(false); addChild(layer2, 1); @@ -407,7 +407,7 @@ std::string LayerTest2::subtitle() const LayerTestBlend::LayerTestBlend() { auto s = Director::getInstance()->getWinSize(); - auto layer1 = LayerColor::create(Color4B(255, 255, 255, 80)); + auto layer1 = LayerColor::create(Color32(255, 255, 255, 80)); auto sister1 = Sprite::create(s_pathSister1); auto sister2 = Sprite::create(s_pathSister2); @@ -426,18 +426,18 @@ void LayerTestBlend::newBlend(float dt) { auto layer = (LayerColor*)getChildByTag(kTagLayer); - backend::BlendFactor src; - backend::BlendFactor dst; + rhi::BlendFactor src; + rhi::BlendFactor dst; - if (layer->getBlendFunc().dst == backend::BlendFactor::ZERO) + if (layer->getBlendFunc().dst == rhi::BlendFactor::ZERO) { - src = backend::BlendFactor::SRC_ALPHA; - dst = backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + src = rhi::BlendFactor::SRC_ALPHA; + dst = rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; } else { - src = backend::BlendFactor::ONE_MINUS_DST_COLOR; - dst = backend::BlendFactor::ZERO; + src = rhi::BlendFactor::ONE_MINUS_DST_COLOR; + dst = rhi::BlendFactor::ZERO; } BlendFunc bf = {src, dst}; @@ -456,7 +456,7 @@ std::string LayerTestBlend::subtitle() const //------------------------------------------------------------------ LayerGradientTest::LayerGradientTest() { - auto layer1 = LayerGradient::create(Color4B(255, 0, 0, 255), Color4B(0, 255, 0, 255), Vec2(0.9f, 0.9f)); + auto layer1 = LayerGradient::create(Color32(255, 0, 0, 255), Color32(0, 255, 0, 255), Vec2(0.9f, 0.9f)); addChild(layer1, 0, kTagLayer); auto listener = EventListenerTouchAllAtOnce::create(); @@ -513,7 +513,7 @@ std::string LayerGradientTest::subtitle() const //------------------------------------------------------------------ LayerGradientTest2::LayerGradientTest2() { - auto layer = LayerGradient::create(Color4B(255, 0, 0, 255), Color4B(255, 255, 0, 255)); + auto layer = LayerGradient::create(Color32(255, 0, 0, 255), Color32(255, 255, 0, 255)); addChild(layer); } @@ -537,7 +537,7 @@ void LayerIgnoreAnchorPointPos::onEnter() auto s = Director::getInstance()->getWinSize(); - auto l = LayerColor::create(Color4B(255, 0, 0, 255), 150, 150); + auto l = LayerColor::create(Color32(255, 0, 0, 255), 150, 150); l->setAnchorPoint(Vec2(0.5f, 0.5f)); l->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -586,7 +586,7 @@ void LayerIgnoreAnchorPointRot::onEnter() LayerTest::onEnter(); auto s = Director::getInstance()->getWinSize(); - auto l = LayerColor::create(Color4B(255, 0, 0, 255), 200, 200); + auto l = LayerColor::create(Color32(255, 0, 0, 255), 200, 200); l->setAnchorPoint(Vec2(0.5f, 0.5f)); l->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -634,7 +634,7 @@ void LayerIgnoreAnchorPointScale::onEnter() auto s = Director::getInstance()->getWinSize(); - auto l = LayerColor::create(Color4B(255, 0, 0, 255), 200, 200); + auto l = LayerColor::create(Color32(255, 0, 0, 255), 200, 200); l->setAnchorPoint(Vec2(0.5f, 1.0f)); l->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -680,12 +680,12 @@ std::string LayerIgnoreAnchorPointScale::subtitle() const LayerExtendedBlendOpacityTest::LayerExtendedBlendOpacityTest() { - auto layer1 = LayerGradient::create(Color4B(255, 0, 0, 255), Color4B(255, 0, 255, 255)); + auto layer1 = LayerGradient::create(Color32(255, 0, 0, 255), Color32(255, 0, 255, 255)); layer1->setContentSize(Size(80.0f, 80.0f)); layer1->setPosition(Vec2(50.0f, 50.0f)); addChild(layer1); - auto layer2 = LayerGradient::create(Color4B(0, 0, 0, 127), Color4B(255, 255, 255, 127)); + auto layer2 = LayerGradient::create(Color32(0, 0, 0, 127), Color32(255, 255, 255, 127)); layer2->setContentSize(Size(80.0f, 80.0f)); layer2->setPosition(Vec2(100.0f, 90.0f)); addChild(layer2); @@ -693,8 +693,8 @@ LayerExtendedBlendOpacityTest::LayerExtendedBlendOpacityTest() auto layer3 = LayerGradient::create(); layer3->setContentSize(Size(80.0f, 80.0f)); layer3->setPosition(Vec2(150.0f, 140.0f)); - layer3->setStartColor(Color3B(255, 0, 0)); - layer3->setEndColor(Color3B(255, 0, 255)); + layer3->setStartColor(Color32(255, 0, 0)); + layer3->setEndColor(Color32(255, 0, 255)); layer3->setStartOpacity(255); layer3->setEndOpacity(255); layer3->setBlendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED); @@ -719,7 +719,7 @@ void LayerBug3162A::onEnter() Size size = VisibleRect::getVisibleRect().size; size.width = size.width / 2; size.height = size.height / 3; - Color4B color[3] = {Color4B(255, 0, 0, 255), Color4B(0, 255, 0, 255), Color4B(0, 0, 255, 255)}; + Color32 color[3] = {Color32(255, 0, 0, 255), Color32(0, 255, 0, 255), Color32(0, 0, 255, 255)}; for (int i = 0; i < 3; ++i) { @@ -762,7 +762,7 @@ void LayerBug3162B::onEnter() Size size = VisibleRect::getVisibleRect().size; size.width = size.width / 2; size.height = size.height / 3; - Color4B color[3] = {Color4B(200, 0, 0, 255), Color4B(150, 0, 0, 255), Color4B(100, 0, 0, 255)}; + Color32 color[3] = {Color32(200, 0, 0, 255), Color32(150, 0, 0, 255), Color32(100, 0, 0, 255)}; for (int i = 0; i < 3; ++i) { @@ -814,7 +814,7 @@ void LayerColorOccludeBug::onEnter() { LayerTest::onEnter(); Director::getInstance()->getRenderer()->setDepthTest(true); - _layer = LayerColor::create(Color4B(0, 80, 95, 255)); + _layer = LayerColor::create(Color32(0, 80, 95, 255)); addChild(_layer); } @@ -838,12 +838,12 @@ void LayerRadialGradientTest::onEnter() _currentSeletedItemIndex = 0; auto director = Director::getInstance(); - director->setClearColor(Color4F(0, 0, 0, 0)); + director->setClearColor(Color(0, 0, 0, 0)); auto origin = director->getVisibleOrigin(); auto size = director->getVisibleSize(); Vec2 center(origin.x + size.width / 2 + 50, origin.y + size.height / 2); float radius = (size.height - 50) / 2; - _layer = LayerRadialGradient::create(Color4B(145, 106, 209, 140), Color4B(0, 0, 0, 0), radius, center, 1.0f); + _layer = LayerRadialGradient::create(Color32(145, 106, 209, 140), Color32(0, 0, 0, 0), radius, center, 1.0f); addChild(_layer); auto scaleSlider = LayerRadialGradientTest::createSlider(); @@ -875,10 +875,10 @@ void LayerRadialGradientTest::listviewCallback(ax::Object* sender, ax::ui::ListV // clear all text to white auto listview = static_cast(sender); for (auto&& item : listview->getItems()) - static_cast(item)->setColor(ax::Color3B::WHITE); + static_cast(item)->setColor(ax::Color32::WHITE); _currentSeletedItemIndex = (int)listview->getCurSelectedIndex(); - listview->getItem(_currentSeletedItemIndex)->setColor(ax::Color3B::RED); + listview->getItem(_currentSeletedItemIndex)->setColor(ax::Color32::RED); int percent = 100; auto slider = static_cast(getChildByTag(101)); @@ -952,7 +952,7 @@ ax::ui::ListView* LayerRadialGradientTest::createListView() auto scale = ax::ui::Text::create(); scale->setString("scale[0-2]"); - scale->setColor(ax::Color3B::RED); // default seleted item + scale->setColor(ax::Color32::RED); // default seleted item scale->setTouchEnabled(true); listview->pushBackCustomItem(scale); diff --git a/tests/cpp-tests/Source/LayerTest/LayerTest.h b/tests/cpp-tests/Source/LayerTest/LayerTest.h index 88b08b0a312e..ea03de7bf97f 100644 --- a/tests/cpp-tests/Source/LayerTest/LayerTest.h +++ b/tests/cpp-tests/Source/LayerTest/LayerTest.h @@ -26,8 +26,8 @@ #define _LAYER_TEST_H_ #include "../BaseTest.h" -#include "core/ui/UISlider.h" -#include "../core/ui/UIListView.h" +#include "axmol/ui/UISlider.h" +#include "axmol/ui/UIListView.h" DEFINE_TEST_SUITE(LayerTests); diff --git a/tests/cpp-tests/Source/LightTest/LightTest.cpp b/tests/cpp-tests/Source/LightTest/LightTest.cpp index 45f74ec15ff3..422b9c7d484a 100644 --- a/tests/cpp-tests/Source/LightTest/LightTest.cpp +++ b/tests/cpp-tests/Source/LightTest/LightTest.cpp @@ -166,63 +166,63 @@ void LightTest::addSprite() void LightTest::addLights() { auto s = Director::getInstance()->getWinSize(); - _ambientLight = AmbientLight::create(Color3B(200, 200, 200)); + _ambientLight = AmbientLight::create(Color32(200, 200, 200)); _ambientLight->retain(); _ambientLight->setEnabled(true); addChild(_ambientLight); _ambientLight->setCameraMask(2); - _directionalLight = DirectionLight::create(Vec3(-1.0f, -1.0f, 0.0f), Color3B(200, 200, 200)); + _directionalLight = DirectionLight::create(Vec3(-1.0f, -1.0f, 0.0f), Color32(200, 200, 200)); _directionalLight->retain(); _directionalLight->setEnabled(false); addChild(_directionalLight); _directionalLight->setCameraMask(2); - _pointLight = PointLight::create(Vec3(0.0f, 0.0f, 0.0f), Color3B(200, 200, 200), 10000.0f); + _pointLight = PointLight::create(Vec3(0.0f, 0.0f, 0.0f), Color32(200, 200, 200), 10000.0f); _pointLight->retain(); _pointLight->setEnabled(false); addChild(_pointLight); _pointLight->setCameraMask(2); _spotLight = - SpotLight::create(Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 0.0f, 0.0f), Color3B(200, 200, 200), 0.0, 0.5, 10000.0f); + SpotLight::create(Vec3(-1.0f, -1.0f, 0.0f), Vec3(0.0f, 0.0f, 0.0f), Color32(200, 200, 200), 0.0, 0.5, 10000.0f); _spotLight->retain(); _spotLight->setEnabled(false); addChild(_spotLight); _spotLight->setCameraMask(2); { - auto tintto1 = TintTo::create(4, 0, 0, 255); - auto tintto2 = TintTo::create(4, 0, 255, 0); - auto tintto3 = TintTo::create(4, 255, 0, 0); - auto tintto4 = TintTo::create(4, 255, 255, 255); + auto tintto1 = TintTo::create(4, Color32(0, 0, 255)); + auto tintto2 = TintTo::create(4, Color32(0, 255, 0)); + auto tintto3 = TintTo::create(4, Color32(255, 0, 0)); + auto tintto4 = TintTo::create(4, Color32(255, 255, 255)); auto seq = Sequence::create(tintto1, tintto2, tintto3, tintto4, nullptr); _ambientLight->runAction(RepeatForever::create(seq)); } { - auto tintto1 = TintTo::create(4, 255, 0, 0); - auto tintto2 = TintTo::create(4, 0, 255, 0); - auto tintto3 = TintTo::create(4, 0, 0, 255); - auto tintto4 = TintTo::create(4, 255, 255, 255); + auto tintto1 = TintTo::create(4, Color32(255, 0, 0)); + auto tintto2 = TintTo::create(4, Color32(0, 255, 0)); + auto tintto3 = TintTo::create(4, Color32(0, 0, 255)); + auto tintto4 = TintTo::create(4, Color32(255, 255, 255)); auto seq = Sequence::create(tintto1, tintto2, tintto3, tintto4, nullptr); _directionalLight->runAction(RepeatForever::create(seq)); } { - auto tintto1 = TintTo::create(4, 255, 0, 0); - auto tintto2 = TintTo::create(4, 0, 255, 0); - auto tintto3 = TintTo::create(4, 0, 0, 255); - auto tintto4 = TintTo::create(4, 255, 255, 255); + auto tintto1 = TintTo::create(4, Color32(255, 0, 0)); + auto tintto2 = TintTo::create(4, Color32(0, 255, 0)); + auto tintto3 = TintTo::create(4, Color32(0, 0, 255)); + auto tintto4 = TintTo::create(4, Color32(255, 255, 255)); auto seq = Sequence::create(tintto2, tintto1, tintto3, tintto4, nullptr); _pointLight->runAction(RepeatForever::create(seq)); } { - auto tintto1 = TintTo::create(4, 255, 0, 0); - auto tintto2 = TintTo::create(4, 0, 255, 0); - auto tintto3 = TintTo::create(4, 0, 0, 255); - auto tintto4 = TintTo::create(4, 255, 255, 255); + auto tintto1 = TintTo::create(4, Color32(255, 0, 0)); + auto tintto2 = TintTo::create(4, Color32(0, 255, 0)); + auto tintto3 = TintTo::create(4, Color32(0, 0, 255)); + auto tintto4 = TintTo::create(4, Color32(255, 255, 255)); auto seq = Sequence::create(tintto3, tintto2, tintto1, tintto4, nullptr); _spotLight->runAction(RepeatForever::create(seq)); } diff --git a/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.cpp b/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.cpp index 8da95795a388..9dc4d2bceea7 100644 --- a/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.cpp +++ b/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.cpp @@ -30,8 +30,8 @@ #include #include "../testResource.h" -#include "axmol.h" -#include "ui/CocosGUI.h" +#include "axmol/axmol.h" +#include "axmol/ui/CocosGUI.h" using namespace ax; @@ -178,17 +178,17 @@ void Material_2DEffects::updateCCTimeUniforms(float) /* * Custom material auto-binding resolver for terrain. */ -class EffectAutoBindingResolver : public backend::ProgramState::AutoBindingResolver +class EffectAutoBindingResolver : public rhi::ProgramState::AutoBindingResolver { - virtual bool resolveAutoBinding(backend::ProgramState* programState, + virtual bool resolveAutoBinding(rhi::ProgramState* programState, /* Node* node,*/ std::string_view uniform, std::string_view autoBinding) override; - void callbackRadius(backend::ProgramState* programState, backend::UniformLocation uniform); - void callbackColor(backend::ProgramState* programState, backend::UniformLocation uniform); + void callbackRadius(rhi::ProgramState* programState, rhi::UniformLocation uniform); + void callbackColor(rhi::ProgramState* programState, rhi::UniformLocation uniform); }; -bool EffectAutoBindingResolver::resolveAutoBinding(backend::ProgramState* programState, +bool EffectAutoBindingResolver::resolveAutoBinding(rhi::ProgramState* programState, /*Node* node,*/ std::string_view uniform, std::string_view autoBinding) { @@ -207,13 +207,13 @@ bool EffectAutoBindingResolver::resolveAutoBinding(backend::ProgramState* progra return false; } -void EffectAutoBindingResolver::callbackRadius(backend::ProgramState* programState, backend::UniformLocation uniform) +void EffectAutoBindingResolver::callbackRadius(rhi::ProgramState* programState, rhi::UniformLocation uniform) { float f = AXRANDOM_0_1() * 10; programState->setUniform(uniform, &f, sizeof(f)); } -void EffectAutoBindingResolver::callbackColor(backend::ProgramState* programState, backend::UniformLocation uniform) +void EffectAutoBindingResolver::callbackColor(rhi::ProgramState* programState, rhi::UniformLocation uniform) { float r = AXRANDOM_0_1(); float g = AXRANDOM_0_1(); @@ -302,10 +302,10 @@ void Material_setTechnique::onEnter() mesh->setMaterial(mat); // lights - auto light1 = AmbientLight::create(Color3B::RED); + auto light1 = AmbientLight::create(Color32::RED); addChild(light1); - auto light2 = DirectionLight::create(Vec3(-1, 1, 0), Color3B::GREEN); + auto light2 = DirectionLight::create(Vec3(-1, 1, 0), Color32::GREEN); addChild(light2); this->schedule(AX_CALLBACK_1(Material_setTechnique::changeMaterial, this), 1, "cookie"); diff --git a/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.h b/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.h index 28dd5358389b..1a63e8f6f17a 100644 --- a/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.h +++ b/tests/cpp-tests/Source/MaterialSystemTest/MaterialSystemTest.h @@ -26,8 +26,7 @@ #pragma once #include "../BaseTest.h" -#include "renderer/backend/Types.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/rhi/ProgramState.h" #include @@ -69,12 +68,12 @@ class Material_2DEffects : public MaterialSystemBaseTest private: struct Locations { - Locations(ax::backend::ProgramState* ps, ax::backend::UniformLocation loc) + Locations(ax::rhi::ProgramState* ps, ax::rhi::UniformLocation loc) : programState(ps), location(loc) {} - ax::backend::ProgramState* programState = nullptr; - ax::backend::UniformLocation location; + ax::rhi::ProgramState* programState = nullptr; + ax::rhi::UniformLocation location; }; std::vector timeUniforms; }; @@ -94,9 +93,9 @@ class Material_AutoBindings : public MaterialSystemBaseTest void updateUniformTime(float); private: - ax::backend::UniformLocation _locationTime; + ax::rhi::UniformLocation _locationTime; EffectAutoBindingResolver* _resolver = nullptr; - ax::backend::ProgramState* _noiseProgramState = nullptr; + ax::rhi::ProgramState* _noiseProgramState = nullptr; }; class Material_setTechnique : public MaterialSystemBaseTest diff --git a/tests/cpp-tests/Source/MenuTest/MenuTest.cpp b/tests/cpp-tests/Source/MenuTest/MenuTest.cpp index 18544c750564..ce9e81ff7ea4 100644 --- a/tests/cpp-tests/Source/MenuTest/MenuTest.cpp +++ b/tests/cpp-tests/Source/MenuTest/MenuTest.cpp @@ -81,8 +81,8 @@ MenuLayerMainMenu::MenuLayerMainMenu() // Label Item (LabelAtlas) auto labelAtlas = LabelAtlas::create("0123456789", "fonts/labelatlas.png", 16, 24, '.'); auto item3 = MenuItemLabel::create(labelAtlas, AX_CALLBACK_1(MenuLayerMainMenu::menuCallbackDisabled, this)); - item3->setDisabledColor(Color3B(32, 32, 64)); - item3->setColor(Color3B(200, 200, 255)); + item3->setDisabledColor(Color32(32, 32, 64)); + item3->setColor(Color32(200, 200, 255)); AXLOGD("test MenuItem Label getString: {}", item3->getString()); // Font Item auto item4 = MenuItemFont::create("I toggle enable items", diff --git a/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.cpp b/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.cpp index d70826688c06..7090ee3c3d51 100644 --- a/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.cpp +++ b/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include "DrawNode3D.h" -#include "renderer/backend/Buffer.h" +#include "axmol/rhi/Buffer.h" namespace ax { @@ -65,7 +65,7 @@ void DrawNode3D::ensureCapacity(int count) if (!_customCommand.getVertexBuffer() || _customCommand.getVertexBuffer()->getSize() < (EXTENDED_SIZE * sizeof(_bufferLines[0]))) { - _customCommand.createVertexBuffer(sizeof(V3F_C4B), EXTENDED_SIZE + (EXTENDED_SIZE >> 1), + _customCommand.createVertexBuffer(sizeof(V3F_C4F), EXTENDED_SIZE + (EXTENDED_SIZE >> 1), CustomCommand::BufferUsage::DYNAMIC); } } @@ -73,9 +73,9 @@ void DrawNode3D::ensureCapacity(int count) bool DrawNode3D::init() { _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; - auto& pd = _customCommand.getPipelineDescriptor(); - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::LINE_COLOR_3D); - _programStateLine = new backend::ProgramState(program); + auto& pd = _customCommand.getPipelineDesc(); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::LINE_COLOR_3D); + _programStateLine = new rhi::ProgramState(program); pd.programState = _programStateLine; _locMVPMatrix = _programStateLine->getUniformLocation("u_MVPMatrix"); @@ -90,7 +90,7 @@ bool DrawNode3D::init() _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::LINE); - _customCommand.createVertexBuffer(sizeof(V3F_C4B), INITIAL_VERTEX_BUFFER_LENGTH, + _customCommand.createVertexBuffer(sizeof(V3F_C4F), INITIAL_VERTEX_BUFFER_LENGTH, CustomCommand::BufferUsage::DYNAMIC); _isDirty = true; @@ -134,7 +134,7 @@ void DrawNode3D::updateCommand(ax::Renderer* renderer, const Mat4& transform, ui _programStateLine->setUniform(_locMVPMatrix, mvp.m, sizeof(mvp.m)); - auto& blend = _customCommand.getPipelineDescriptor().blendDescriptor; + auto& blend = _customCommand.getPipelineDesc().blendDesc; blend.blendEnabled = true; blend.sourceRGBBlendFactor = blend.sourceAlphaBlendFactor = _blendFunc.src; blend.destinationRGBBlendFactor = blend.destinationAlphaBlendFactor = _blendFunc.dst; @@ -142,25 +142,18 @@ void DrawNode3D::updateCommand(ax::Renderer* renderer, const Mat4& transform, ui AX_INCREMENT_GL_DRAWN_BATCHES_AND_VERTICES(1, _bufferLines.size()); } -void DrawNode3D::drawLine(const Vec3& from, const Vec3& to, const Color4F& color) +void DrawNode3D::drawLine(const Vec3& from, const Vec3& to, const Color& color) { unsigned int vertex_count = 2; ensureCapacity(vertex_count); - Color4B col = Color4B(color); - V3F_C4B a = {Vec3(from.x, from.y, from.z), col}; - V3F_C4B b = { - Vec3(to.x, to.y, to.z), - col, - }; - - _bufferLines.emplace_back(a); - _bufferLines.emplace_back(b); + _bufferLines.emplace_back(from, color); + _bufferLines.emplace_back(to, color); _isDirty = true; } -void DrawNode3D::drawCube(Vec3* vertices, const Color4F& color) +void DrawNode3D::drawCube(Vec3* vertices, const Color& color) { // front face drawLine(vertices[0], vertices[1], color); diff --git a/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.h b/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.h index 83682058fdf7..9bbdeb1b5e64 100644 --- a/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.h +++ b/tests/cpp-tests/Source/MeshRendererTest/DrawNode3D.h @@ -26,7 +26,7 @@ #ifndef __DRAW_NODE_3D_H__ #define __DRAW_NODE_3D_H__ -#include "axmol.h" +#include "axmol/axmol.h" namespace ax { @@ -43,7 +43,7 @@ class DrawNode3D : public ax::Node /** * Draw 3D Line */ - void drawLine(const ax::Vec3& from, const ax::Vec3& to, const Color4F& color); + void drawLine(const ax::Vec3& from, const ax::Vec3& to, const Color& color); /** * Draw 3D cube @@ -58,7 +58,7 @@ class DrawNode3D : public ax::Node * vertices[7]:Left-top-back. * @param color */ - void drawCube(ax::Vec3* vertices, const Color4F& color); + void drawCube(ax::Vec3* vertices, const Color& color); /** Clear the geometry in the node's buffer. */ void clear(); @@ -95,10 +95,10 @@ class DrawNode3D : public ax::Node BlendFunc _blendFunc; ax::CustomCommand _customCommand; - backend::ProgramState* _programStateLine = nullptr; - backend::DepthStencilDescriptor* _depthstencilDescriptor = nullptr; - backend::UniformLocation _locMVPMatrix; - std::vector _bufferLines; + rhi::ProgramState* _programStateLine = nullptr; + rhi::DepthStencilDesc* _depthstencilDescriptor = nullptr; + rhi::UniformLocation _locMVPMatrix; + axstd::pod_vector _bufferLines; private: AX_DISALLOW_COPY_AND_ASSIGN(DrawNode3D); diff --git a/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.cpp b/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.cpp index 06c061efa4b9..b69e269b8ba4 100644 --- a/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.cpp +++ b/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.cpp @@ -2,6 +2,7 @@ Copyright (c) 2012 cocos2d-x.org Copyright (c) 2013-2016 Chukong Technologies Inc. Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. + Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). https://axmol.dev/ @@ -26,9 +27,9 @@ #include "MeshRendererTest.h" #include "DrawNode3D.h" -#include "2d/CameraBackgroundBrush.h" -#include "3d/MeshMaterial.h" -#include "3d/MotionStreak3D.h" +#include "axmol/2d/CameraBackgroundBrush.h" +#include "axmol/3d/MeshMaterial.h" +#include "axmol/3d/MotionStreak3D.h" #include "Particle3D/PU/PUParticleSystem3D.h" @@ -544,7 +545,7 @@ MeshRendererFakeShadowTest::MeshRendererFakeShadowTest() auto mat = MeshMaterial::createWithFilename("MeshRendererTest/FakeShadow.material"); _state = mat->getTechniqueByIndex(0)->getPassByIndex(0)->getProgramState(); _plane->setMaterial(mat); - backend::UniformLocation loc = _state->getUniformLocation("u_model_matrix"); + rhi::UniformLocation loc = _state->getUniformLocation("u_model_matrix"); auto trans = _plane->getNodeToWorldTransform(); _state->setUniform(loc, &trans, sizeof(trans)); loc = _state->getUniformLocation("u_target_pos"); @@ -786,10 +787,10 @@ MeshRendererLightMapTest::MeshRendererLightMapTest() setCameraMask(2); // add a point light - auto light = PointLight::create(Vec3(35, 75, -20.5), Color3B(255, 255, 255), 150); + auto light = PointLight::create(Vec3(35, 75, -20.5), Color32(255, 255, 255), 150); addChild(light); // set the ambient light - auto ambient = AmbientLight::create(Color3B(55, 55, 55)); + auto ambient = AmbientLight::create(Color32(55, 55, 55)); addChild(ambient); // create a listener @@ -1062,7 +1063,7 @@ MeshRendererWithSkinTest::MeshRendererWithSkinTest() _animateQuality = (int)Animate3DQuality::QUALITY_LOW; _menuItem = MenuItemFont::create(getAnimationQualityMessage(), AX_CALLBACK_1(MeshRendererWithSkinTest::switchAnimationQualityCallback, this)); - _menuItem->setColor(Color3B(0, 200, 20)); + _menuItem->setColor(Color32(0, 200, 20)); auto menu = Menu::create(_menuItem, NULL); menu->setPosition(Vec2::ZERO); _menuItem->setPosition(VisibleRect::left().x + 50, VisibleRect::top().y - 70); @@ -1565,9 +1566,9 @@ MeshRendererWithOBBPerformanceTest::MeshRendererWithOBBPerformanceTest() MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); auto decrease = MenuItemFont::create(" - ", AX_CALLBACK_1(MeshRendererWithOBBPerformanceTest::delOBBCallback, this)); - decrease->setColor(Color3B(0, 200, 20)); + decrease->setColor(Color32(0, 200, 20)); auto increase = MenuItemFont::create(" + ", AX_CALLBACK_1(MeshRendererWithOBBPerformanceTest::addOBBCallback, this)); - increase->setColor(Color3B(0, 200, 20)); + increase->setColor(Color32(0, 200, 20)); auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); @@ -1576,7 +1577,7 @@ MeshRendererWithOBBPerformanceTest::MeshRendererWithOBBPerformanceTest() TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelCubeCount = Label::createWithTTF(ttfCount, "0 cubes"); - _labelCubeCount->setColor(Color3B(0, 200, 20)); + _labelCubeCount->setColor(Color32(0, 200, 20)); _labelCubeCount->setPosition(Vec2(s.width / 2, s.height - 90)); addChild(_labelCubeCount); _hasCollider = false; @@ -1657,7 +1658,7 @@ void MeshRendererWithOBBPerformanceTest::update(float dt) Vec3 corners[8] = {}; _obbt.getCorners(corners); - _drawDebug->drawCube(corners, Color4F(0, 0, 1, 1)); + _drawDebug->drawCube(corners, Color(0, 0, 1, 1)); } if (_obb.size() > 0) { @@ -1667,7 +1668,7 @@ void MeshRendererWithOBBPerformanceTest::update(float dt) { Vec3 corners[8] = {}; _obb[i].getCorners(corners); - _drawOBB->drawCube(corners, _obbt.intersects(_obb[i]) ? Color4F(1, 0, 0, 1) : Color4F(0, 1, 0, 1)); + _drawOBB->drawCube(corners, _obbt.intersects(_obb[i]) ? Color(1, 0, 0, 1) : Color(0, 1, 0, 1)); } } } @@ -2010,7 +2011,7 @@ void UseCaseMeshRenderer::switchCase() } else if (_caseIdx == 1) // use case 2, ui - 3d - ui, last ui should on the top { - auto layer = LayerColor::create(Color4B(0, 0, 100, 255), s.width / 2.f, s.height / 2.f); + auto layer = LayerColor::create(Color32(0, 0, 100, 255), s.width / 2.f, s.height / 2.f); layer->setPosition(s.width * 0.25f, s.height * 0.25f); layer->setGlobalZOrder(-1); addChild(layer); @@ -2056,7 +2057,7 @@ void UseCaseMeshRenderer::menuCallback_Message(Object* sender) { // create a new message layer on the top auto s = layer->getContentSize(); - auto messagelayer = LayerColor::create(Color4B(100, 100, 0, 255)); + auto messagelayer = LayerColor::create(Color32(100, 100, 0, 255)); messagelayer->setContentSize(Size(s.width * 0.5f, s.height * 0.5f)); messagelayer->setPosition(Vec2(s.width * 0.25f, s.height * 0.25f)); auto label = Label::create(); @@ -2149,9 +2150,9 @@ void NodeAnimationTest::addNewMeshWithCoords(Vec2 p) mesh->setPosition(Vec2(s.width / 2.f, s.height / 3.f)); mesh->setTexture("MeshRendererTest/teapot.png"); - auto light1 = PointLight::create(Vec3(s.width * 0.2f, s.height * 0.8f, 100.0f), Color3B(200, 200, 200), 10000.0f); + auto light1 = PointLight::create(Vec3(s.width * 0.2f, s.height * 0.8f, 100.0f), Color32(200, 200, 200), 10000.0f); addChild(light1); - auto light2 = AmbientLight::create(Color3B(100, 100, 100)); + auto light2 = AmbientLight::create(Color32(100, 100, 100)); addChild(light2); auto animation = Animation3D::create(fileName); @@ -2234,11 +2235,7 @@ void MeshRendererCubeMapTest::addNewMeshWithCoords(Vec2 p) _textureCube->retain(); // set texture parameters - Texture2D::TexParams tRepeatParams; - tRepeatParams.magFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.minFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - tRepeatParams.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + Texture2D::TexParams tRepeatParams{}; _textureCube->setTexParameters(tRepeatParams); auto mat = MeshMaterial::createWithFilename("MeshRendererTest/CubeMap.material"); @@ -2277,11 +2274,7 @@ void MeshRendererCubeMapTest::addNewMeshWithCoords(Vec2 p) _textureCube->retain(); // set texture parameters - Texture2D::TexParams tRepeatParams; - tRepeatParams.magFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.minFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.sAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; - tRepeatParams.tAddressMode = backend::SamplerAddressMode::CLAMP_TO_EDGE; + Texture2D::TexParams tRepeatParams{}; _textureCube->setTexParameters(tRepeatParams); auto mat = MeshMaterial::createWithFilename("MeshRendererTest/CubeMap.material"); @@ -2342,14 +2335,14 @@ void Issue9767::menuCallback_SwitchShader(ax::Object* sender) if (_shaderType == Issue9767::ShaderType::SHADER_TEX) { _shaderType = Issue9767::ShaderType::SHADER_COLOR; - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_3D); - _programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_3D); + _programState = new rhi::ProgramState(program); } else { _shaderType = Issue9767::ShaderType::SHADER_TEX; - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_3D); - _programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::UNLIT); + _programState = new rhi::ProgramState(program); } _mesh->setProgramState(_programState); } @@ -2558,7 +2551,7 @@ void CameraBackgroundClearTest::switch_CameraClearMode(ax::Object* sender) } else if (type == CameraBackgroundBrush::BrushType::DEPTH) { - _camera->setBackgroundBrush(CameraBackgroundBrush::createColorBrush(Color4F(1.f, 0.f, 0.f, 1.f), 1.f)); + _camera->setBackgroundBrush(CameraBackgroundBrush::createColorBrush(Color(1.f, 0.f, 0.f, 1.f), 1.f)); _label->setString("Color Clear Brush"); } else if (type == CameraBackgroundBrush::BrushType::COLOR) @@ -2599,7 +2592,7 @@ MotionStreak3DTest::MotionStreak3DTest() mesh->setPosition(20.f, 0.f); addChild(mesh); - auto streak = MotionStreak3D::create(1.0f, 1.0f, 5.f, Color3B(255, 255, 0), "Images/Icon.png"); + auto streak = MotionStreak3D::create(1.0f, 1.0f, 5.f, Color32(255, 255, 0), "Images/Icon.png"); addChild(streak); setCameraMask(2); @@ -2663,7 +2656,7 @@ MeshRendererNormalMappingTest::MeshRendererNormalMappingTest() camera->lookAt(Vec3(0.f, 0.f, 0.f)); addChild(camera); - PointLight* light = PointLight::create(Vec3(0.0, 0.0, 0.0), Color3B(255, 255, 255), 1000); + PointLight* light = PointLight::create(Vec3(0.0, 0.0, 0.0), Color32(255, 255, 255), 1000); light->setTag(100); addChild(light); diff --git a/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.h b/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.h index daf3502144a9..c5e762f1b471 100644 --- a/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.h +++ b/tests/cpp-tests/Source/MeshRendererTest/MeshRendererTest.h @@ -25,7 +25,7 @@ #pragma once #include "BaseTest.h" -#include "renderer/backend/ProgramState.h" +#include "axmol/rhi/ProgramState.h" #include namespace ax @@ -130,7 +130,7 @@ class MeshRendererUVAnimationTest : public MeshRendererTestDemo float _cylinder_texture_offset; float _shining_duration; - ax::backend::ProgramState* _state = nullptr; + ax::rhi::ProgramState* _state = nullptr; #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) ax::EventListenerCustom* _backToForegroundListener; @@ -167,7 +167,7 @@ class MeshRendererFakeShadowTest : public MeshRendererTestDemo unsigned int _curState; ax::MeshRenderer* _plane; ax::MeshRenderer* _orc; - ax::backend::ProgramState* _state = nullptr; + ax::rhi::ProgramState* _state = nullptr; #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) ax::EventListenerCustom* _backToForegroundListener; @@ -198,7 +198,7 @@ class MeshRendererBasicToonShaderTest : public MeshRendererTestDemo virtual std::string subtitle() const override; protected: - ax::backend::ProgramState* _state; + ax::rhi::ProgramState* _state; #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) ax::EventListenerCustom* _backToForegroundListener; diff --git a/tests/cpp-tests/Source/MotionStreakTest/MotionStreakTest.cpp b/tests/cpp-tests/Source/MotionStreakTest/MotionStreakTest.cpp index dd2afeb2b0d6..48eee481bd79 100644 --- a/tests/cpp-tests/Source/MotionStreakTest/MotionStreakTest.cpp +++ b/tests/cpp-tests/Source/MotionStreakTest/MotionStreakTest.cpp @@ -65,7 +65,7 @@ void MotionStreakTest1::onEnter() _target->setPosition(Vec2(s.width / 4, 0.0f)); // create the streak object and add it to the scene - _streak = MotionStreak::create(2, 3, 32, Color3B::GREEN, s_streak); + _streak = MotionStreak::create(2, 3, 32, Color32::GREEN, s_streak); addChild(_streak); // schedule an update on each frame so we can synchronize the streak with the target schedule(AX_SCHEDULE_SELECTOR(MotionStreakTest1::onUpdate)); @@ -112,7 +112,7 @@ void MotionStreakTest2::onEnter() auto s = Director::getInstance()->getWinSize(); // create the streak object and add it to the scene - _streak = MotionStreak::create(3, 3, 64, Color3B::WHITE, s_streak); + _streak = MotionStreak::create(3, 3, 64, Color32::WHITE, s_streak); addChild(_streak); _streak->setPosition(Vec2(s.width / 2, s.height / 2)); @@ -148,7 +148,7 @@ void Issue1358::onEnter() // ask director the the window size auto size = Director::getInstance()->getWinSize(); - _streak = MotionStreak::create(2.0f, 1.0f, 50.0f, Color3B(255, 255, 0), "Images/Icon.png"); + _streak = MotionStreak::create(2.0f, 1.0f, 50.0f, Color32(255, 255, 0), "Images/Icon.png"); addChild(_streak); _center = Vec2(size.width / 2, size.height / 2); @@ -194,7 +194,7 @@ void Issue12226::onEnter() outer->setPosition(size / 2); addChild(outer); - _streak = MotionStreak::create(1.0f, 3, radius * 1.5f, Color3B(0xA0, 0xA0, 0xA0), "ccb/particle-smoke.png"); + _streak = MotionStreak::create(1.0f, 3, radius * 1.5f, Color32(0xA0, 0xA0, 0xA0), "ccb/particle-smoke.png"); // motionStreak->setOpacity(0x70); _streak->setPosition(outer->getPosition()); diff --git a/tests/cpp-tests/Source/MultiTouchTest/MultiTouchTest.cpp b/tests/cpp-tests/Source/MultiTouchTest/MultiTouchTest.cpp index 4c79536d9563..bfbdcd1accdc 100644 --- a/tests/cpp-tests/Source/MultiTouchTest/MultiTouchTest.cpp +++ b/tests/cpp-tests/Source/MultiTouchTest/MultiTouchTest.cpp @@ -31,24 +31,24 @@ MultiTouchTests::MultiTouchTests() ADD_TEST_CASE(MultiTouchTest); } -static const Color3B* s_TouchColors[5] = {&Color3B::YELLOW, &Color3B::BLUE, &Color3B::GREEN, &Color3B::RED, - &Color3B::MAGENTA}; +static const Color32* s_TouchColors[5] = {&Color32::YELLOW, &Color32::BLUE, &Color32::GREEN, &Color32::RED, + &Color32::MAGENTA}; class TouchPoint : public Node { public: - TouchPoint(const Vec2& touchPoint, const Color3B& touchColor) + TouchPoint(const Vec2& touchPoint, const Color32& touchColor) { DrawNode* drawNode = DrawNode::create(); auto s = Director::getInstance()->getWinSize(); - Color4F color(touchColor.r / 255.0f, touchColor.g / 255.0f, touchColor.b / 255.0f, 1.0f); + Color color(touchColor.r / 255.0f, touchColor.g / 255.0f, touchColor.b / 255.0f, 1.0f); drawNode->drawLine(Vec2(0.0f, touchPoint.y), Vec2(s.width, touchPoint.y), color); drawNode->drawLine(Vec2(touchPoint.x, 0.0f), Vec2(touchPoint.x, s.height), color); drawNode->drawDot(touchPoint, 3, color); addChild(drawNode); } - static TouchPoint* touchPointWithParent(Node* pParent, const Vec2& touchPoint, const Color3B& touchColor) + static TouchPoint* touchPointWithParent(Node* pParent, const Vec2& touchPoint, const Color32& touchColor) { auto pRet = new TouchPoint(touchPoint, touchColor); pRet->setContentSize(pParent->getContentSize()); diff --git a/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.cpp b/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.cpp index 54ffc2291d31..c3ccbc299133 100644 --- a/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.cpp +++ b/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.cpp @@ -26,10 +26,10 @@ ****************************************************************************/ #include "NavMeshTest.h" -#include "physics3d/Physics3DWorld.h" -#include "physics3d/Physics3D.h" -#include "3d/Bundle3D.h" -#include "2d/Light.h" +#include "axmol/physics3d/Physics3DWorld.h" +#include "axmol/physics3d/Physics3D.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/2d/Light.h" USING_NS_AX_EXT; using namespace ax; @@ -158,11 +158,11 @@ void NavMeshBaseTestDemo::initScene() setNavMesh(navMesh); setNavMeshDebugCamera(_camera); - auto ambientLight = AmbientLight::create(Color3B(64, 64, 64)); + auto ambientLight = AmbientLight::create(Color32(64, 64, 64)); ambientLight->setCameraMask((unsigned short)CameraFlag::USER1); this->addChild(ambientLight); - auto dirLight = DirectionLight::create(Vec3(1.2f, -1.1f, 0.5f), Color3B(255, 255, 255)); + auto dirLight = DirectionLight::create(Vec3(1.2f, -1.1f, 0.5f), Color32(255, 255, 255)); dirLight->setCameraMask((unsigned short)CameraFlag::USER1); this->addChild(dirLight); } diff --git a/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.h b/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.h index f50ea48eeb91..44c35cd24900 100644 --- a/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.h +++ b/tests/cpp-tests/Source/NavMeshTest/NavMeshTest.h @@ -28,7 +28,7 @@ #define _NAVMESH_TEST_H_ #include "../BaseTest.h" -#include "navmesh/NavMesh.h" +#include "axmol/navmesh/NavMesh.h" #include DEFINE_TEST_SUITE(NavMeshTests); diff --git a/tests/cpp-tests/Source/NetworkTest/DownloaderTest/DownloaderTest.cpp b/tests/cpp-tests/Source/NetworkTest/DownloaderTest/DownloaderTest.cpp index f8a28760e783..633e512cecec 100644 --- a/tests/cpp-tests/Source/NetworkTest/DownloaderTest/DownloaderTest.cpp +++ b/tests/cpp-tests/Source/NetworkTest/DownloaderTest/DownloaderTest.cpp @@ -28,11 +28,11 @@ #include "../../testResource.h" -#include "ui/UILoadingBar.h" -#include "ui/UIButton.h" -#include "network/Downloader.h" +#include "axmol/ui/UILoadingBar.h" +#include "axmol/ui/UIButton.h" +#include "axmol/network/Downloader.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; diff --git a/tests/cpp-tests/Source/NetworkTest/HttpClientTest/HttpClientTest.h b/tests/cpp-tests/Source/NetworkTest/HttpClientTest/HttpClientTest.h index 3a21d236fd6d..f28ce602309f 100644 --- a/tests/cpp-tests/Source/NetworkTest/HttpClientTest/HttpClientTest.h +++ b/tests/cpp-tests/Source/NetworkTest/HttpClientTest/HttpClientTest.h @@ -26,9 +26,9 @@ #ifndef __HTTP_CLIENT_H__ #define __HTTP_CLIENT_H__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" -#include "network/HttpClient.h" +#include "axmol/network/HttpClient.h" #include "BaseTest.h" DEFINE_TEST_SUITE(HttpClientTests); diff --git a/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.cpp b/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.cpp index c027382d85f7..055eb4b903b5 100644 --- a/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.cpp +++ b/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.cpp @@ -27,7 +27,7 @@ #include "../NetworkTest.h" #include "testResource.h" -#include "base/format.h" +#include "axmol/base/format.h" /* "ws://echo.websocket.org no longer avaiable: https://www.lob.com/blog/websocket-org-is-down-here-is-an-alternative list of public test servers: diff --git a/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.h b/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.h index 02a52b2ec297..7825523779d5 100644 --- a/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.h +++ b/tests/cpp-tests/Source/NetworkTest/WebSocketTest/WebSocketTest.h @@ -34,9 +34,9 @@ #ifndef __TestCpp__WebSocketTest__ #define __TestCpp__WebSocketTest__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" -#include "network/WebSocket.h" +#include "axmol/network/WebSocket.h" #include "BaseTest.h" DEFINE_TEST_SUITE(WebSocketTests); diff --git a/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.cpp b/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.cpp index 6fb20c528f64..875d502f7bf0 100644 --- a/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.cpp +++ b/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.cpp @@ -24,9 +24,9 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "NewAudioEngineTest.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" using namespace ax; using namespace ax::ui; @@ -92,11 +92,11 @@ class TextButton : public ax::Label _enabled = enabled; if (_enabled) { - this->setColor(Color3B::WHITE); + this->setColor(Color32::WHITE); } else { - this->setColor(Color3B::GRAY); + this->setColor(Color32::GRAY); } } diff --git a/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.h b/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.h index fc3dc647fe52..8ab5ebbebd64 100644 --- a/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.h +++ b/tests/cpp-tests/Source/NewAudioEngineTest/NewAudioEngineTest.h @@ -24,15 +24,15 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #ifndef __NEWAUDIOENGINE_TEST_H_ # define __NEWAUDIOENGINE_TEST_H_ -# include "axmol.h" +# include "axmol/axmol.h" # include "../BaseTest.h" -# include "audio/AudioEngine.h" +# include "axmol/audio/AudioEngine.h" DEFINE_TEST_SUITE(AudioEngineTests); diff --git a/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.cpp b/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.cpp index 711f3a5bfe9f..c694b7bedbc7 100644 --- a/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.cpp +++ b/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.cpp @@ -60,9 +60,9 @@ namespace { void setEnabled(bool enabled) { _enabled = enabled; if (_enabled) { - this->setColor(Color3B::WHITE); + this->setColor(Color32::WHITE); } else { - this->setColor(Color3B::GRAY); + this->setColor(Color32::GRAY); } } @@ -290,7 +290,7 @@ class TouchableSprite : public Sprite if (rect.containsPoint(locationInNode)) { AXLOGD("TouchableSprite: onTouchBegan ..."); - this->setColor(Color3B::RED); + this->setColor(Color32::RED); return true; } return false; @@ -298,7 +298,7 @@ class TouchableSprite : public Sprite listener->onTouchEnded = [this](Touch* touch, Event* event) { AXLOGD("TouchableSprite: onTouchEnded ..."); - this->setColor(Color3B::WHITE); + this->setColor(Color32::WHITE); if (_removeListenerOnTouchEnded) { @@ -400,13 +400,13 @@ void RemoveListenerWhenDispatching::onEnter() if (rect.containsPoint(locationInNode)) { - sprite1->setColor(Color3B::RED); + sprite1->setColor(Color32::RED); return true; } return false; }; - listener1->onTouchEnded = [=](Touch* touch, Event* event) { sprite1->setColor(Color3B::WHITE); }; + listener1->onTouchEnded = [=](Touch* touch, Event* event) { sprite1->setColor(Color32::WHITE); }; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener1, sprite1); @@ -1222,7 +1222,7 @@ PauseResumeTargetTest::PauseResumeTargetTest() sprite3->getListener()->setEnabled(false); _eventDispatcher->pauseEventListenersForTarget(this, true); - auto colorLayer = LayerColor::create(Color4B(0, 0, 255, 100)); + auto colorLayer = LayerColor::create(Color32(0, 0, 255, 100)); this->addChild(colorLayer, 99999); auto closeItem = MenuItemFont::create("close", [this, colorLayer, sprite3](Object* /*sender*/) { @@ -1370,7 +1370,7 @@ PauseResumeTargetTest3::PauseResumeTargetTest3() if (rect.containsPoint(locationInNode)) { AXLOGD("TouchableSprite: onTouchBegan ..."); - _touchableSprite->setColor(Color3B::RED); + _touchableSprite->setColor(Color32::RED); return true; } return false; @@ -1378,7 +1378,7 @@ PauseResumeTargetTest3::PauseResumeTargetTest3() listener->onTouchEnded = [this](Touch* touch, Event* event) { AXLOGD("TouchableSprite: onTouchEnded ..."); - _touchableSprite->setColor(Color3B::WHITE); + _touchableSprite->setColor(Color32::WHITE); }; _eventDispatcher->addEventListenerWithSceneGraphPriority(listener, _touchableSprite); diff --git a/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.h b/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.h index 178c7b4f15d5..77e48506aad6 100644 --- a/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.h +++ b/tests/cpp-tests/Source/NewEventDispatcherTest/NewEventDispatcherTest.h @@ -33,7 +33,7 @@ #ifndef __samples__NewEventDispatcherTest__ #define __samples__NewEventDispatcherTest__ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(EventDispatcherTests); diff --git a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp index 8a1e4cb20823..871b5b56fc75 100644 --- a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp +++ b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.cpp @@ -27,7 +27,7 @@ #include "NewRendererTest.h" #include #include -#include "renderer/backend/DriverBase.h" +#include "axmol/rhi/DriverBase.h" namespace { @@ -258,7 +258,7 @@ NewClippingNodeTest::NewClippingNodeTest() // rectangle[2] = Vec2(clipper->getContentSize().width, clipper->getContentSize().height); // rectangle[3] = Vec2(0, clipper->getContentSize().height); // - // Color4F white(1, 1, 1, 1); + // Color white(1, 1, 1, 1); // stencil->drawPolygon(rectangle, 4, white, 1, white); // clipper->setStencil(stencil); @@ -343,7 +343,7 @@ NewDrawNodeTest::NewDrawNodeTest() rectangle[2] = Vec2(50, 50); rectangle[3] = Vec2(-50, 50); - Color4F white(1, 1, 1, 1); + Color white(1, 1, 1, 1); rectNode->drawPolygon(rectangle, 4, white, 1, white); parent->addChild(rectNode); } @@ -433,9 +433,9 @@ SpriteCreation::SpriteCreation() MenuItemFont::setFontName("fonts/arial.ttf"); MenuItemFont::setFontSize(65); auto decrease = MenuItemFont::create(" - ", AX_CALLBACK_1(SpriteCreation::delSpritesCallback, this)); - decrease->setColor(Color3B(0, 200, 20)); + decrease->setColor(Color32(0, 200, 20)); auto increase = MenuItemFont::create(" + ", AX_CALLBACK_1(SpriteCreation::addSpritesCallback, this)); - increase->setColor(Color3B(0, 200, 20)); + increase->setColor(Color32(0, 200, 20)); auto menu = Menu::create(decrease, increase, nullptr); menu->alignItemsHorizontally(); @@ -444,7 +444,7 @@ SpriteCreation::SpriteCreation() TTFConfig ttfCount("fonts/Marker Felt.ttf", 30); _labelSpriteNum = Label::createWithTTF(ttfCount, "Label"); - _labelSpriteNum->setColor(Color3B(0, 200, 20)); + _labelSpriteNum->setColor(Color32(0, 200, 20)); _labelSpriteNum->setPosition(Vec2(s.width / 2, s.height - 130)); addChild(_labelSpriteNum); @@ -792,14 +792,14 @@ RendererBatchQuadTri::RendererBatchQuadTri() int y = AXRANDOM_0_1() * s.height; auto label = LabelAtlas::create("This is a label", "fonts/tuffy_bold_italic-charmap.plist"); - label->setColor(Color3B::RED); + label->setColor(Color32::RED); label->setPosition(Vec2(x, y)); addChild(label); auto sprite = Sprite::create("fonts/tuffy_bold_italic-charmap.png"); sprite->setTextureRect(Rect(0.0f, 0.0f, 100.0f, 100.0f)); sprite->setPosition(Vec2(x, y)); - sprite->setColor(Color3B::BLUE); + sprite->setColor(Color32::BLUE); addChild(sprite); } } @@ -852,13 +852,13 @@ RendererUniformBatch::RendererUniformBatch() } } -ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState() +ax::rhi::ProgramState* RendererUniformBatch::createBlurProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); + new rhi::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); programState->autorelease(); - backend::UniformLocation loc = programState->getUniformLocation("resolution"); + rhi::UniformLocation loc = programState->getUniformLocation("resolution"); auto resolution = Vec2(85, 121); programState->setUniform(loc, &resolution, sizeof(resolution)); @@ -873,9 +873,9 @@ ax::backend::ProgramState* RendererUniformBatch::createBlurProgramState() return programState; } -ax::backend::ProgramState* RendererUniformBatch::createSepiaProgramState() +ax::rhi::ProgramState* RendererUniformBatch::createSepiaProgramState() { - auto programState = new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); + auto programState = new rhi::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); programState->autorelease(); return programState; } @@ -924,12 +924,12 @@ RendererUniformBatch2::RendererUniformBatch2() } } -backend::ProgramState* RendererUniformBatch2::createBlurProgramState() +rhi::ProgramState* RendererUniformBatch2::createBlurProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); + new rhi::ProgramState(ProgramManager::getInstance()->loadProgram(s_blur_program_id)); - backend::UniformLocation loc = programState->getUniformLocation("resolution"); + rhi::UniformLocation loc = programState->getUniformLocation("resolution"); auto resolution = Vec2(85, 121); programState->setUniform(loc, &resolution, sizeof(resolution)); @@ -944,10 +944,10 @@ backend::ProgramState* RendererUniformBatch2::createBlurProgramState() return programState; } -backend::ProgramState* RendererUniformBatch2::createSepiaProgramState() +rhi::ProgramState* RendererUniformBatch2::createSepiaProgramState() { auto programState = - new backend::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); + new rhi::ProgramState(ProgramManager::getInstance()->loadProgram(s_sepia_program_id)); programState->autorelease(); return programState; } @@ -970,8 +970,8 @@ NonBatchSprites::NonBatchSprites() addChild(_spritesAnchor); _totalSprites = Label::createWithTTF(TTFConfig("fonts/arial.ttf"), "sprites"); - _totalSprites->setColor(Color3B::YELLOW); - _totalSprites->enableOutline(Color4B::RED, 2); + _totalSprites->setColor(Color32::YELLOW); + _totalSprites->enableOutline(Color32::RED, 2); _totalSprites->setPosition(s.width / 2, s.height / 2); addChild(_totalSprites); diff --git a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.h b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.h index 92980fc224b0..ed19abc7e011 100644 --- a/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.h +++ b/tests/cpp-tests/Source/NewRendererTest/NewRendererTest.h @@ -25,7 +25,7 @@ #ifndef __NewRendererTest_H_ #define __NewRendererTest_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #define kTagSpriteBatchNode 100 @@ -224,8 +224,8 @@ class RendererUniformBatch : public MultiSceneTest protected: RendererUniformBatch(); - ax::backend::ProgramState* createBlurProgramState(); - ax::backend::ProgramState* createSepiaProgramState(); + ax::rhi::ProgramState* createBlurProgramState(); + ax::rhi::ProgramState* createSepiaProgramState(); }; class RendererUniformBatch2 : public MultiSceneTest @@ -238,8 +238,8 @@ class RendererUniformBatch2 : public MultiSceneTest protected: RendererUniformBatch2(); - ax::backend::ProgramState* createBlurProgramState(); - ax::backend::ProgramState* createSepiaProgramState(); + ax::rhi::ProgramState* createBlurProgramState(); + ax::rhi::ProgramState* createSepiaProgramState(); }; class NonBatchSprites : public MultiSceneTest diff --git a/tests/cpp-tests/Source/NodeTest/NodeTest.cpp b/tests/cpp-tests/Source/NodeTest/NodeTest.cpp index d62990ab1e17..58bad4f8e1d3 100644 --- a/tests/cpp-tests/Source/NodeTest/NodeTest.cpp +++ b/tests/cpp-tests/Source/NodeTest/NodeTest.cpp @@ -703,7 +703,7 @@ CameraCenterTest::CameraCenterTest() sprite = Sprite::create("Images/white-512x512.png"); addChild(sprite, 0); sprite->setPosition(Vec2(s.width / 5 * 1, s.height / 5 * 1)); - sprite->setColor(Color3B::RED); + sprite->setColor(Color32::RED); sprite->setTextureRect(Rect(0.0f, 0.0f, 120.0f, 50.0f)); orbit = OrbitCamera::create(10.0f, 1.0f, 0.0f, 0.0f, 360.0f, 0.0f, 0.0f); sprite->runAction(RepeatForever::create(orbit)); @@ -713,7 +713,7 @@ CameraCenterTest::CameraCenterTest() sprite = Sprite::create("Images/white-512x512.png"); addChild(sprite, 0, 40); sprite->setPosition(Vec2(s.width / 5 * 1, s.height / 5 * 4)); - sprite->setColor(Color3B::BLUE); + sprite->setColor(Color32::BLUE); sprite->setTextureRect(Rect(0.0f, 0.0f, 120.0f, 50.0f)); orbit = OrbitCamera::create(10.0f, 1.0f, 0.0f, 0.0f, 360.0f, 0.0f, 0.0f); sprite->runAction(RepeatForever::create(orbit)); @@ -722,7 +722,7 @@ CameraCenterTest::CameraCenterTest() sprite = Sprite::create("Images/white-512x512.png"); addChild(sprite, 0); sprite->setPosition(Vec2(s.width / 5 * 4, s.height / 5 * 1)); - sprite->setColor(Color3B::YELLOW); + sprite->setColor(Color32::YELLOW); sprite->setTextureRect(Rect(0.0f, 0.0f, 120.0f, 50.0f)); orbit = OrbitCamera::create(10.0f, 1.0f, 0.0f, 0.0f, 360.0f, 0.0f, 0.0f); sprite->runAction(RepeatForever::create(orbit)); @@ -731,7 +731,7 @@ CameraCenterTest::CameraCenterTest() sprite = Sprite::create("Images/white-512x512.png"); addChild(sprite, 0, 40); sprite->setPosition(Vec2(s.width / 5 * 4, s.height / 5 * 4)); - sprite->setColor(Color3B::GREEN); + sprite->setColor(Color32::GREEN); sprite->setTextureRect(Rect(0.0f, 0.0f, 120.0f, 50.0f)); orbit = OrbitCamera::create(10.0f, 1.0f, 0.0f, 0.0f, 360.0f, 0.0f, 0.0f); sprite->runAction(RepeatForever::create(orbit)); @@ -740,7 +740,7 @@ CameraCenterTest::CameraCenterTest() sprite = Sprite::create("Images/white-512x512.png"); addChild(sprite, 0, 40); sprite->setPosition(Vec2(s.width / 2, s.height / 2)); - sprite->setColor(Color3B::WHITE); + sprite->setColor(Color32::WHITE); sprite->setTextureRect(Rect(0.0f, 0.0f, 120.0f, 50.0f)); orbit = OrbitCamera::create(10.0f, 1.0f, 0.0f, 0.0f, 360.0f, 0.0f, 0.0f); sprite->runAction(RepeatForever::create(orbit)); @@ -942,29 +942,29 @@ class MySprite : public Sprite auto sprite = new MySprite; sprite->initWithFile(spritefilename); sprite->autorelease(); - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::POSITION_TEXTURE_COLOR); - auto programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::POSITION_TEXTURE_COLOR); + auto programState = new rhi::ProgramState(program); sprite->setProgramState(programState, true); return sprite; } - bool setProgramState(backend::ProgramState* programState, bool ownPS = false) override; + bool setProgramState(rhi::ProgramState* programState, bool ownPS = false) override; virtual void draw(Renderer* renderer, const Mat4& transform, uint32_t flags) override; protected: CustomCommand _customCommand; }; -bool MySprite::setProgramState(backend::ProgramState* programState, bool ownPS/* = false*/) +bool MySprite::setProgramState(rhi::ProgramState* programState, bool ownPS/* = false*/) { if (Sprite::setProgramState(programState, ownPS)) { - auto& pipelineDescriptor = _customCommand.getPipelineDescriptor(); + auto& pipelineDescriptor = _customCommand.getPipelineDesc(); pipelineDescriptor.programState = programState; _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::TRIANGLE_STRIP); - _customCommand.createVertexBuffer(sizeof(V3F_C4B_T2F), 4, CustomCommand::BufferUsage::STATIC); - _customCommand.updateVertexBuffer(&_quad, 4 * sizeof(V3F_C4B_T2F)); + _customCommand.createVertexBuffer(sizeof(V3F_T2F_C4B), 4, CustomCommand::BufferUsage::STATIC); + _customCommand.updateVertexBuffer(&_quad, 4 * sizeof(V3F_T2F_C4B)); return true; } return false; @@ -974,7 +974,7 @@ void MySprite::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) { const auto& projectionMat = Director::getInstance()->getMatrix(MATRIX_STACK_TYPE::MATRIX_STACK_PROJECTION); auto mvpMatrix = projectionMat * transform; - _customCommand.getPipelineDescriptor().programState->setUniform(_mvpMatrixLocation, mvpMatrix.m, + _customCommand.getPipelineDesc().programState->setUniform(_mvpMatrixLocation, mvpMatrix.m, sizeof(mvpMatrix.m)); _customCommand.init(_globalZOrder, transform, flags); renderer->addCommand(&_customCommand); @@ -1500,9 +1500,9 @@ void Issue16735Test::onEnter() auto d = DrawNode::create(); d->drawLine(Vec2(origin.x, origin.y + visibleSize.height / 2), - Vec2(origin.x + visibleSize.width, origin.y + visibleSize.height / 2), Color4F::RED); + Vec2(origin.x + visibleSize.width, origin.y + visibleSize.height / 2), Color::RED); d->drawLine(Vec2(origin.x + visibleSize.width / 2, origin.y), - Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height), Color4F::RED); + Vec2(origin.x + visibleSize.width / 2, origin.y + visibleSize.height), Color::RED); addChild(d); } diff --git a/tests/cpp-tests/Source/OpenURLTest/OpenURLTest.h b/tests/cpp-tests/Source/OpenURLTest/OpenURLTest.h index 66223328884b..cbd0e57a50a4 100644 --- a/tests/cpp-tests/Source/OpenURLTest/OpenURLTest.h +++ b/tests/cpp-tests/Source/OpenURLTest/OpenURLTest.h @@ -25,7 +25,7 @@ #ifndef _OPEN_URL_TEST_H_ #define _OPEN_URL_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(OpenURLTests); diff --git a/tests/cpp-tests/Source/ParticleTest/ParticleTest.cpp b/tests/cpp-tests/Source/ParticleTest/ParticleTest.cpp index 091a5835cee0..7862dd0c39db 100644 --- a/tests/cpp-tests/Source/ParticleTest/ParticleTest.cpp +++ b/tests/cpp-tests/Source/ParticleTest/ParticleTest.cpp @@ -236,16 +236,16 @@ void DemoBigFlower::onEnter() _emitter->setEndSpinVar(0); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -320,16 +320,16 @@ void DemoRotFlower::onEnter() _emitter->setEndSpinVar(2000); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -472,13 +472,13 @@ void DemoSnow::onEnter() _emitter->setSpeed(130); _emitter->setSpeedVar(30); - Color4F startColor = _emitter->getStartColor(); + Color startColor = _emitter->getStartColor(); startColor.r = 0.9f; startColor.g = 0.9f; startColor.b = 0.9f; _emitter->setStartColor(startColor); - Color4F startColorVar = _emitter->getStartColorVar(); + Color startColorVar = _emitter->getStartColorVar(); startColorVar.b = 0.1f; _emitter->setStartColorVar(startColorVar); @@ -574,16 +574,16 @@ void DemoModernArt::onEnter() _emitter->setEmissionRate(_emitter->getTotalParticles() / _emitter->getLife()); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -687,7 +687,7 @@ void DemoFixedFPS::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -717,7 +717,7 @@ void DemoTimeScale::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -756,7 +756,7 @@ void DemoSpawnFadeIn::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -787,7 +787,7 @@ void DemoScaleFadeIn::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -818,7 +818,7 @@ void DemoSimulation::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -848,7 +848,7 @@ void DemoSpawnRotation::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -879,7 +879,7 @@ void DemoHSV::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -916,7 +916,7 @@ void DemoLifeAnimation::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -971,7 +971,7 @@ void DemoLifeAnimationAtlas::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1015,7 +1015,7 @@ void DemoLifeAnimationReversed::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1072,7 +1072,7 @@ void DemoLoopAnimation::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1111,7 +1111,7 @@ void DemoLoopAnimation::onEnter() _emitter->addAnimationIndex("particle_anim_8.png"); _emitter->addAnimationIndex("particle_anim_9.png"); - _emitter->setAnimationDescriptor(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + _emitter->setAnimationDesc(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); setEmitterPosition(); } @@ -1130,7 +1130,7 @@ void DemoLoopAnimationReversed::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1169,7 +1169,7 @@ void DemoLoopAnimationReversed::onEnter() _emitter->addAnimationIndex("particle_anim_8.png"); _emitter->addAnimationIndex("particle_anim_9.png"); - _emitter->setAnimationDescriptor(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, true /* Reversed animation descriptor */); + _emitter->setAnimationDesc(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}, true /* Reversed animation descriptor */); setEmitterPosition(); } @@ -1188,7 +1188,7 @@ void DemoEmitterAnimation::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1243,7 +1243,7 @@ void DemoEmitterAnimationDescriptor::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1282,7 +1282,7 @@ void DemoEmitterAnimationDescriptor::onEnter() _emitter->addAnimationIndex("particle_anim_8.png"); _emitter->addAnimationIndex("particle_anim_9.png"); - _emitter->setAnimationDescriptor(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); + _emitter->setAnimationDesc(0, 1, 0.5F, {0, 1, 2, 3, 4, 5, 6, 7, 8, 9}); setEmitterPosition(); } @@ -1301,7 +1301,7 @@ void DemoLoopAnimationMultiDescriptor::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1340,9 +1340,9 @@ void DemoLoopAnimationMultiDescriptor::onEnter() _emitter->addAnimationIndex("particle_anim_8.png"); _emitter->addAnimationIndex("particle_anim_9.png"); - _emitter->setAnimationDescriptor(0, 1, 0.5F, {1, 3, 8}); - _emitter->setAnimationDescriptor(1, 1, 0.5F, {0, 1}); - _emitter->setAnimationDescriptor(2, 1, 0.5F, {0, 9}); + _emitter->setAnimationDesc(0, 1, 0.5F, {1, 3, 8}); + _emitter->setAnimationDesc(1, 1, 0.5F, {0, 1}); + _emitter->setAnimationDesc(2, 1, 0.5F, {0, 9}); setEmitterPosition(); } @@ -1361,7 +1361,7 @@ void DemoEmissionShapePoint::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1400,7 +1400,7 @@ void DemoEmissionShapeRect::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1436,7 +1436,7 @@ void DemoEmissionShapeRectTorus::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1472,7 +1472,7 @@ void DemoEmissionShapeCircle::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1508,7 +1508,7 @@ void DemoEmissionShapeCircleBiasEdge::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1544,7 +1544,7 @@ void DemoEmissionShapeCircleBiasCenter::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1580,7 +1580,7 @@ void DemoEmissionShapeTorus::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1616,7 +1616,7 @@ void DemoEmissionShapeTorusBiasEdge::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1652,7 +1652,7 @@ void DemoEmissionShapeTorusBiasInner::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1688,7 +1688,7 @@ void DemoEmissionShapeCone::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1724,7 +1724,7 @@ void DemoEmissionShapeConeTorus::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1760,7 +1760,7 @@ void DemoEmissionShapeAlphaMask::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1776,8 +1776,8 @@ void DemoEmissionShapeAlphaMask::onEnter() _emitter->setSpeed(0); _emitter->setSpeedVar(0); - _emitter->setStartColor(Color4F::WHITE); - _emitter->setEndColor(Color4F::WHITE); + _emitter->setStartColor(Color::WHITE); + _emitter->setEndColor(Color::WHITE); _emitter->setStartSize(6); _emitter->setEndSize(3); @@ -1808,7 +1808,7 @@ void RadiusMode1::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1853,16 +1853,16 @@ void RadiusMode1::onEnter() _emitter->setEndSpinVar(0); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -1891,7 +1891,7 @@ void RadiusMode2::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -1936,16 +1936,16 @@ void RadiusMode2::onEnter() _emitter->setEndSpinVar(0); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -1974,7 +1974,7 @@ void Issue704::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2019,16 +2019,16 @@ void Issue704::onEnter() _emitter->setEndSpinVar(0); // color of particles - Color4F startColor(0.5f, 0.5f, 0.5f, 1.0f); + Color startColor(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColor(startColor); - Color4F startColorVar(0.5f, 0.5f, 0.5f, 1.0f); + Color startColorVar(0.5f, 0.5f, 0.5f, 1.0f); _emitter->setStartColorVar(startColorVar); - Color4F endColor(0.1f, 0.1f, 0.1f, 0.2f); + Color endColor(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColor(endColor); - Color4F endColorVar(0.1f, 0.1f, 0.1f, 0.2f); + Color endColorVar(0.1f, 0.1f, 0.1f, 0.2f); _emitter->setEndColorVar(endColorVar); // size, in pixels @@ -2065,7 +2065,7 @@ void Issue870::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2106,7 +2106,7 @@ void DemoParticleFromFile::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2233,7 +2233,7 @@ void ParticleDemo::onEnter() MenuItemFont::setFontSize(32); - _color = LayerColor::create(Color4B(127, 127, 127, 255)); + _color = LayerColor::create(Color32(127, 127, 127, 255)); this->addChild(_color); _emitter = nullptr; @@ -2352,7 +2352,7 @@ void ParticleBatchHybrid::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2400,16 +2400,16 @@ void ParticleBatchMultipleEmitters::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; auto emitter1 = ParticleSystemQuad::create("Particles/LavaFlow.plist"); - emitter1->setStartColor(Color4F(1, 0, 0, 1)); + emitter1->setStartColor(Color(1, 0, 0, 1)); auto emitter2 = ParticleSystemQuad::create("Particles/LavaFlow.plist"); - emitter2->setStartColor(Color4F(0, 1, 0, 1)); + emitter2->setStartColor(Color(0, 1, 0, 1)); auto emitter3 = ParticleSystemQuad::create("Particles/LavaFlow.plist"); - emitter3->setStartColor(Color4F(0, 0, 1, 1)); + emitter3->setStartColor(Color(0, 0, 1, 1)); auto s = Director::getInstance()->getWinSize(); @@ -2443,7 +2443,7 @@ void ParticleReorder::onEnter() ParticleDemo::onEnter(); _order = 0; - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2457,13 +2457,13 @@ void ParticleReorder::onEnter() auto parent = (i == 0 ? parent1 : parent2); auto emitter1 = ParticleSystemQuad::create("Particles/SmallSun.plist"); - emitter1->setStartColor(Color4F(1, 0, 0, 1)); + emitter1->setStartColor(Color(1, 0, 0, 1)); emitter1->setBlendAdditive(false); auto emitter2 = ParticleSystemQuad::create("Particles/SmallSun.plist"); - emitter2->setStartColor(Color4F(0, 1, 0, 1)); + emitter2->setStartColor(Color(0, 1, 0, 1)); emitter2->setBlendAdditive(false); auto emitter3 = ParticleSystemQuad::create("Particles/SmallSun.plist"); - emitter3->setStartColor(Color4F(0, 0, 1, 1)); + emitter3->setStartColor(Color(0, 0, 1, 1)); emitter3->setBlendAdditive(false); auto s = Director::getInstance()->getWinSize(); @@ -2586,8 +2586,8 @@ bool RainbowEffect::initWithTotalParticles(int numberOfParticles) setEmissionRate(getTotalParticles() / getLife()); // color of particles - setStartColor(Color4F(Color4B(50, 50, 50, 50))); - setEndColor(Color4F(Color4B(0, 0, 0, 0))); + setStartColor(Color(Color32(50, 50, 50, 50))); + setEndColor(Color(Color32(0, 0, 0, 0))); _startColorVar.r = 0.0f; _startColorVar.g = 0.0f; @@ -2615,7 +2615,7 @@ void Issue1201::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2645,7 +2645,7 @@ void MultipleParticleSystems::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2700,7 +2700,7 @@ void MultipleParticleSystemsBatched::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2760,7 +2760,7 @@ void AddAndDeleteParticleSystems::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2848,7 +2848,7 @@ void ReorderParticleSystems::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -2900,16 +2900,16 @@ void ReorderParticleSystems::onEnter() // color of particles float color[3] = {0, 0, 0}; color[i] = 1; - Color4F startColor(color[0], color[1], color[2], 1.0f); + Color startColor(color[0], color[1], color[2], 1.0f); particleSystem->setStartColor(startColor); - Color4F startColorVar(0, 0, 0, 0); + Color startColorVar(0, 0, 0, 0); particleSystem->setStartColorVar(startColorVar); - Color4F endColor = startColor; + Color endColor = startColor; particleSystem->setEndColor(endColor); - Color4F endColorVar = startColorVar; + Color endColorVar = startColorVar; particleSystem->setEndColorVar(endColorVar); // size, in pixels @@ -3002,7 +3002,7 @@ void PremultipliedAlphaTest::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLUE); + _color->setColor(Color32::BLUE); this->removeChild(_background, true); _background = nullptr; @@ -3019,10 +3019,10 @@ void PremultipliedAlphaTest::onEnter() // Toggle next line to see old behavior // this->emitter.opacityModifyRGB = NO; - _emitter->setStartColor(Color4F(1.0f, 1.0f, 1.0f, 1.0f)); - _emitter->setEndColor(Color4F(1.0f, 1.0f, 1.0f, 0.0f)); - _emitter->setStartColorVar(Color4F(0.0f, 0.0f, 0.0f, 0.0f)); - _emitter->setEndColorVar(Color4F(0.0f, 0.0f, 0.0f, 0.0f)); + _emitter->setStartColor(Color(1.0f, 1.0f, 1.0f, 1.0f)); + _emitter->setEndColor(Color(1.0f, 1.0f, 1.0f, 0.0f)); + _emitter->setStartColorVar(Color(0.0f, 0.0f, 0.0f, 0.0f)); + _emitter->setEndColorVar(Color(0.0f, 0.0f, 0.0f, 0.0f)); this->addChild(_emitter, 10); _hasEmitter = true; @@ -3036,7 +3036,7 @@ void PremultipliedAlphaTest2::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); this->removeChild(_background, true); _background = nullptr; @@ -3061,7 +3061,7 @@ void Issue3990::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); this->removeChild(_background, true); _background = nullptr; @@ -3124,7 +3124,7 @@ void ParticleAutoBatching::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); this->removeChild(_background, true); _background = nullptr; @@ -3156,7 +3156,7 @@ void ParticleResetTotalParticles::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; @@ -3198,7 +3198,7 @@ void ParticleIssue12310::onEnter() { ParticleDemo::onEnter(); - _color->setColor(Color3B::BLACK); + _color->setColor(Color32::BLACK); removeChild(_background, true); _background = nullptr; diff --git a/tests/cpp-tests/Source/Physics3DTest/Physics3DTest.cpp b/tests/cpp-tests/Source/Physics3DTest/Physics3DTest.cpp index 1ca9aaa66273..4ec3b004f2f8 100644 --- a/tests/cpp-tests/Source/Physics3DTest/Physics3DTest.cpp +++ b/tests/cpp-tests/Source/Physics3DTest/Physics3DTest.cpp @@ -27,9 +27,9 @@ #include "Physics3DTest.h" -#include "3d/Terrain.h" -#include "3d/Bundle3D.h" -#include "physics3d/Physics3D.h" +#include "axmol/3d/Terrain.h" +#include "axmol/3d/Bundle3D.h" +#include "axmol/physics3d/Physics3D.h" #include "Particle3D/PU/PUParticleSystem3D.h" USING_NS_AX_EXT; using namespace ax; diff --git a/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.cpp b/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.cpp index 54112815f9ba..b51feee31e17 100644 --- a/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.cpp +++ b/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.cpp @@ -28,9 +28,12 @@ #if defined(AX_ENABLE_PHYSICS) # include -# include "ui/CocosGUI.h" +# include "axmol/ui/CocosGUI.h" # include "../testResource.h" +# include "axmol/physics/PhysicsHelper.h" +# include "physics-nodes/PhysicsDebugNode.h" + using namespace ax; PhysicsTests::PhysicsTests() @@ -58,7 +61,7 @@ PhysicsTests::PhysicsTests() namespace { -Color4F STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f); +Color STATIC_COLOR(1.0f, 0.0f, 0.0f, 1.0f); const int DRAG_BODYS_TAG = 0x80; } // namespace @@ -66,7 +69,8 @@ void PhysicsDemo::toggleDebug() { # if defined(AX_ENABLE_PHYSICS) _debugDraw = !_debugDraw; - _physicsWorld->setDebugDrawMask(_debugDraw ? PhysicsWorld::DEBUGDRAW_ALL : PhysicsWorld::DEBUGDRAW_NONE); + if (_debugDrawNode) + _debugDrawNode->setVisible(_debugDraw); # endif } @@ -78,7 +82,11 @@ bool PhysicsDemo::init() return initWithPhysics(); } -PhysicsDemo::~PhysicsDemo() {} +PhysicsDemo::~PhysicsDemo() +{ + if (_mouseListener) + _eventDispatcher->removeEventListener(_mouseListener); +} std::string PhysicsDemo::title() const { @@ -89,6 +97,26 @@ void PhysicsDemo::onEnter() { TestCase::onEnter(); + _mouseListener = EventListenerMouse::create(); + //_mouseListener->onMouseMove = AX_CALLBACK_1(MouseEventTest::onMouseMove, this); + //_mouseListener->onMouseUp = AX_CALLBACK_1(MouseEventTest::onMouseUp, this); + _mouseListener->onMouseDown = AX_CALLBACK_1(PhysicsDemo::onMouseDown, this); + //_mouseListener->onMouseScroll = AX_CALLBACK_1(MouseEventTest::onMouseScroll, this); + + _eventDispatcher->addEventListenerWithSceneGraphPriority(_mouseListener, this); + + // create debug draw node + auto debugDrawNode = utils::createInstance(&extension::PhysicsDebugNode::initWithWorld, + getPhysicsWorld()->getB2World()); + addChild(debugDrawNode, 100); + debugDrawNode->setOpacity(150); + auto& settings = debugDrawNode->getB2DebugDraw(); + settings.drawShapes = true; + settings.drawJoints = true; + debugDrawNode->setVisible(_debugDraw); + _debugDrawNode = debugDrawNode; + + // batch sprite _spriteTexture = SpriteBatchNode::create("Images/grossini_dance_atlas.png", 100)->getTexture(); // menu for debug layer @@ -101,6 +129,13 @@ void PhysicsDemo::onEnter() VisibleRect::top().y - item->getContentSize().height / 2 - 10)); } +bool PhysicsDemo::onMouseDown(Event* event) +{ + EventMouse* e = (EventMouse*)event; + AXLOGI("PhysicsDemo::onMouseDown: ({},{})", e->getLocation().x, e->getLocation().y); + return true; +} + Sprite* PhysicsDemo::addGrossiniAtPosition(Vec2 p, float scale /* = 1.0*/) { AXLOGD("Add sprite x: {:.2} y: {:.2}", p.x, p.y); @@ -277,12 +312,12 @@ bool PhysicsDemo::onTouchBegan(Touch* touch, Event* event) if (body != nullptr) { Node* mouse = Node::create(); - auto physicsBody = PhysicsBody::create(PHYSICS_INFINITY, PHYSICS_INFINITY); + auto physicsBody = PhysicsBody::create(); physicsBody->setDynamic(false); mouse->addComponent(physicsBody); mouse->setPosition(location); this->addChild(mouse); - PhysicsJointPin* joint = PhysicsJointPin::construct(physicsBody, body, location); + PhysicsJointPin* joint = PhysicsJointPin::instantiate(physicsBody, body, location); joint->setMaxForce(5000.0f * body->getMass()); _physicsWorld->addJoint(joint); _mouses.insert(std::make_pair(touch->getID(), mouse)); @@ -341,15 +376,13 @@ void PhysicsDemoLogoSmash::onEnter() 0.95f, PhysicsMaterial(0.01f, 0.0f, 0.0f)); auto physicsBody = ball->getPhysicsBody(); - physicsBody->setMass(1.0); - physicsBody->setMoment(PHYSICS_INFINITY); _ball->addChild(ball); } } } - auto bullet = makeBall(Vec2(400.0f, 0.0f), 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0)); + auto bullet = makeBall(Vec2(0.0f, 0.0f), 10, PhysicsMaterial(PHYSICS_INFINITY, 0, 0)); bullet->getPhysicsBody()->setVelocity(Vec2(200.0f, 0.0f)); bullet->setPosition(Vec2(-100.0f, VisibleRect::getVisibleRect().size.height / 2)); @@ -382,7 +415,7 @@ void PhysicsDemoClickAdd::onEnter() _eventDispatcher->addEventListenerWithSceneGraphPriority(accListener, this); auto node = Node::create(); - node->addComponent(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size)); + node->addComponent(PhysicsBody::createEdgeBox(VisibleRect::getVisibleRect().size * 0.95)); node->setPosition(VisibleRect::center()); this->addChild(node); @@ -548,7 +581,7 @@ void PhysicsDemoRayCast::update(float /*delta*/) if (point2 != point3) { - _node->drawDot(point3, 2, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + _node->drawDot(point3, 2, Color(1.0f, 1.0f, 1.0f, 1.0f)); } addChild(_node); @@ -574,7 +607,7 @@ void PhysicsDemoRayCast::update(float /*delta*/) if (point2 != point3) { - _node->drawDot(point3, 2, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + _node->drawDot(point3, 2, Color(1.0f, 1.0f, 1.0f, 1.0f)); } addChild(_node); @@ -602,7 +635,7 @@ void PhysicsDemoRayCast::update(float /*delta*/) for (int i = 0; i < num; ++i) { - _node->drawDot(points[i], 2, Color4F(1.0f, 1.0f, 1.0f, 1.0f)); + _node->drawDot(points[i], 2, Color(1.0f, 1.0f, 1.0f, 1.0f)); } addChild(_node); @@ -716,13 +749,18 @@ void PhysicsDemoJoints::onEnter() node->setPosition(Point::ZERO); this->addChild(node); + int testidx = 8; + for (int i = 0; i < 4; ++i) { for (int j = 0; j < 4; ++j) { + // if ((i * 4 + j) > testidx) + // continue; Vec2 offset(VisibleRect::leftBottom().x + 5 + j * width + width / 2, VisibleRect::leftBottom().y + 50 + i * height + height / 2); - box->addShape(PhysicsShapeEdgeBox::create(Size(width, height), PHYSICSSHAPE_MATERIAL_DEFAULT, 0.5, offset)); + box->addCollider( + PhysicsColliderEdgeBox::create(box, Size(width, height), PHYSICSSHAPE_MATERIAL_DEFAULT, 0.5, offset)); switch (i * 4 + j) { @@ -736,7 +774,7 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - PhysicsJointPin* joint = PhysicsJointPin::construct(sp1PhysicsBody, sp2PhysicsBody, offset); + PhysicsJointPin* joint = PhysicsJointPin::instantiate(sp1PhysicsBody, sp2PhysicsBody, offset); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -754,7 +792,7 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - PhysicsJointFixed* joint = PhysicsJointFixed::construct(sp1PhysicsBody, sp2PhysicsBody, offset); + PhysicsJointFixed* joint = PhysicsJointFixed::instantiate(sp1PhysicsBody, sp2PhysicsBody, offset); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -772,7 +810,7 @@ void PhysicsDemoJoints::onEnter() sp2PhysicsBody->setTag(DRAG_BODYS_TAG); PhysicsJointDistance* joint = - PhysicsJointDistance::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO); + PhysicsJointDistance::instantiate(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -789,7 +827,7 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - PhysicsJointLimit* joint = PhysicsJointLimit::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, + PhysicsJointLimit* joint = PhysicsJointLimit::instantiate(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO, 30.0f, 60.0f); getPhysicsWorld()->addJoint(joint); @@ -807,7 +845,7 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - PhysicsJointSpring* joint = PhysicsJointSpring::construct(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, + PhysicsJointSpring* joint = PhysicsJointSpring::instantiate(sp1PhysicsBody, sp2PhysicsBody, Point::ZERO, Point::ZERO, 500.0f, 0.3f); getPhysicsWorld()->addJoint(joint); @@ -825,7 +863,7 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - PhysicsJointGroove* joint = PhysicsJointGroove::construct( + PhysicsJointGroove* joint = PhysicsJointGroove::instantiate( sp1PhysicsBody, sp2PhysicsBody, Vec2(30.0f, 15.0f), Vec2(30.0f, -15.0f), Vec2(-30.0f, 0.0f)); getPhysicsWorld()->addJoint(joint); @@ -843,11 +881,11 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition())); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition())); - PhysicsJointRotarySpring* joint = - PhysicsJointRotarySpring::construct(sp1PhysicsBody, sp2PhysicsBody, 3000.0f, 60.0f); - getPhysicsWorld()->addJoint(joint); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp1PhysicsBody, box, sp1->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp2PhysicsBody, box, sp2->getPosition())); + PhysicsJointRotarySpring* joint = + PhysicsJointRotarySpring::instantiate(sp1PhysicsBody, sp2PhysicsBody, 3000.0f, 60.0f); + getPhysicsWorld()->addJoint(joint); this->addChild(sp1); this->addChild(sp2); @@ -863,10 +901,10 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition())); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp1PhysicsBody, box, sp1->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp2PhysicsBody, box, sp2->getPosition())); PhysicsJointRotaryLimit* joint = - PhysicsJointRotaryLimit::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f, (float)M_PI_2); + PhysicsJointRotaryLimit::instantiate(sp1PhysicsBody, sp2PhysicsBody, 0.0f, (float)M_PI_2); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -883,10 +921,10 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition())); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp1PhysicsBody, box, sp1->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp2PhysicsBody, box, sp2->getPosition())); PhysicsJointRatchet* joint = - PhysicsJointRatchet::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f, (float)M_PI_2); + PhysicsJointRatchet::instantiate(sp1PhysicsBody, sp2PhysicsBody, 0.0f, (float)M_PI_2); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -903,9 +941,9 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition())); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition())); - PhysicsJointGear* joint = PhysicsJointGear::construct(sp1PhysicsBody, sp2PhysicsBody, 0.0f, 2.0f); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp1PhysicsBody, box, sp1->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp2PhysicsBody, box, sp2->getPosition())); + PhysicsJointGear* joint = PhysicsJointGear::instantiate(sp1PhysicsBody, sp2PhysicsBody, 0.0f, 2.0f); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -922,9 +960,9 @@ void PhysicsDemoJoints::onEnter() auto sp2PhysicsBody = sp2->getPhysicsBody(); sp2PhysicsBody->setTag(DRAG_BODYS_TAG); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp1PhysicsBody, box, sp1->getPosition())); - getPhysicsWorld()->addJoint(PhysicsJointPin::construct(sp2PhysicsBody, box, sp2->getPosition())); - PhysicsJointMotor* joint = PhysicsJointMotor::construct(sp1PhysicsBody, sp2PhysicsBody, (float)M_PI_2); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp1PhysicsBody, box, sp1->getPosition())); + getPhysicsWorld()->addJoint(PhysicsJointPin::instantiate(sp2PhysicsBody, box, sp2->getPosition())); + PhysicsJointMotor* joint = PhysicsJointMotor::instantiate(sp1PhysicsBody, sp2PhysicsBody, (float)M_PI_2); getPhysicsWorld()->addJoint(joint); this->addChild(sp1); @@ -963,20 +1001,26 @@ void PhysicsDemoPump::onEnter() nodeBody->setDynamic(false); PhysicsMaterial staticMaterial(PHYSICS_INFINITY, 0, 0.5f); - nodeBody->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Vec2(50, 0), - VisibleRect::leftTop() + Vec2(50, -130), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Vec2(190, 0), - VisibleRect::leftTop() + Vec2(100, -50), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Vec2(100, -50), - VisibleRect::leftTop() + Vec2(100, -90), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create(VisibleRect::leftTop() + Vec2(50, -130), - VisibleRect::leftTop() + Vec2(100, -145), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create( - VisibleRect::leftTop() + Vec2(100, -145), VisibleRect::leftBottom() + Vec2(100, 80), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create( - VisibleRect::leftTop() + Vec2(150, -80), VisibleRect::leftBottom() + Vec2(150, 80), staticMaterial, 2.0f)); - nodeBody->addShape(PhysicsShapeEdgeSegment::create( - VisibleRect::leftTop() + Vec2(150, -80), VisibleRect::rightTop() + Vec2(-100, -150), staticMaterial, 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create( + nodeBody, VisibleRect::leftTop() + Vec2(50, 0), VisibleRect::leftTop() + Vec2(50, -130), staticMaterial, 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(190, 0), + VisibleRect::leftTop() + Vec2(100, -50), staticMaterial, + 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(100, -50), + VisibleRect::leftTop() + Vec2(100, -90), staticMaterial, + 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(50, -130), + VisibleRect::leftTop() + Vec2(100, -145), staticMaterial, + 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(100, -145), + VisibleRect::leftBottom() + Vec2(100, 80), staticMaterial, + 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(150, -80), + VisibleRect::leftBottom() + Vec2(150, 80), staticMaterial, + 2.0f)); + nodeBody->addCollider(PhysicsColliderEdgeSegment::create(nodeBody, VisibleRect::leftTop() + Vec2(150, -80), + VisibleRect::rightTop() + Vec2(-100, -150), staticMaterial, + 2.0f)); nodeBody->setCategoryBitmask(0x01); node->setPosition(Vec2::ZERO); @@ -996,7 +1040,7 @@ void PhysicsDemoPump::onEnter() // pump auto pump = Node::create(); - auto center = PhysicsShape::getPolygonCenter(vec, 4); + auto center = PhysicsCollider::getPolygonCenter(vec, 4); pump->setPosition(center); auto pumpBody = PhysicsBody::createPolygon(vec, 4, PHYSICSBODY_MATERIAL_DEFAULT, -center); pump->addComponent(pumpBody); @@ -1014,8 +1058,8 @@ void PhysicsDemoPump::onEnter() sgear->setPosition(VisibleRect::leftBottom() + Vec2(125.0f, 0.0f)); this->addChild(sgear); - _physicsWorld->addJoint(PhysicsJointPin::construct(nodeBody, sgearBody, sgear->getPosition())); - _physicsWorld->addJoint(PhysicsJointDistance::construct(pumpBody, sgearBody, Vec2(0.0f, 0.0f), Vec2(0.0f, -44.0f))); + _physicsWorld->addJoint(PhysicsJointPin::instantiate(nodeBody, sgearBody, sgear->getPosition())); + _physicsWorld->addJoint(PhysicsJointDistance::instantiate(pumpBody, sgearBody, Vec2(0.0f, 0.0f), Vec2(0.0f, -44.0f))); // big gear auto bgearBody = PhysicsBody::createCircle(100); @@ -1025,8 +1069,8 @@ void PhysicsDemoPump::onEnter() bgear->setPosition(VisibleRect::leftBottom() + Vec2(275.0f, 0.0f)); this->addChild(bgear); - _physicsWorld->addJoint(PhysicsJointPin::construct(bgearBody, nodeBody, bgear->getPosition())); - _physicsWorld->addJoint(PhysicsJointGear::construct(sgearBody, bgearBody, (float)-M_PI_2, -2.0f)); + _physicsWorld->addJoint(PhysicsJointPin::instantiate(bgearBody, nodeBody, bgear->getPosition())); + _physicsWorld->addJoint(PhysicsJointGear::instantiate(sgearBody, bgearBody, (float)-M_PI_2, -2.0f)); // plugger Vec2 seg[] = {VisibleRect::leftTop() + Vec2(75, -120), VisibleRect::leftBottom() + Vec2(75, -100)}; @@ -1036,8 +1080,6 @@ void PhysicsDemoPump::onEnter() auto pluggerBody = PhysicsBody::createEdgeSegment(seg[0], seg[1], PhysicsMaterial(0.01f, 0.0f, 0.5f), 20); pluggerBody->setDynamic(true); - pluggerBody->setMass(30); - pluggerBody->setMoment(100000); pluggerBody->setCategoryBitmask(0x02); auto plugger = Node::create(); plugger->addComponent(pluggerBody); @@ -1046,8 +1088,8 @@ void PhysicsDemoPump::onEnter() sgearBody->setCollisionBitmask(0x04 | 0x01); _physicsWorld->addJoint( - PhysicsJointPin::construct(nodeBody, pluggerBody, VisibleRect::leftBottom() + Vec2(75.0f, -90.0f))); - _physicsWorld->addJoint(PhysicsJointDistance::construct(pluggerBody, sgearBody, Vec2::ZERO, Vec2(44.0f, 0.0f))); + PhysicsJointPin::instantiate(nodeBody, pluggerBody, VisibleRect::leftBottom() + Vec2(75.0f, -90.0f))); + _physicsWorld->addJoint(PhysicsJointDistance::instantiate(pluggerBody, sgearBody, Vec2::ZERO, Vec2(44.0f, 0.0f))); } void PhysicsDemoPump::update(float delta) @@ -1142,7 +1184,6 @@ void PhysicsDemoOneWayPlatform::onEnter() auto ballBody = ball->getPhysicsBody(); ballBody->setVelocity(Vec2(0.0f, 150.0f)); ballBody->setTag(DRAG_BODYS_TAG); - ballBody->setMass(1.0f); ballBody->setContactTestBitmask(0xFFFFFFFF); this->addChild(ball); @@ -1199,8 +1240,8 @@ bool PhysicsDemoSlice::slice(PhysicsWorld& /*world*/, const PhysicsRayCastInfo& normal = normal.getPerp().getNormalized(); float dist = info.start.dot(normal); - clipPoly(dynamic_cast(info.shape), normal, dist); - clipPoly(dynamic_cast(info.shape), -normal, -dist); + clipPoly(dynamic_cast(info.shape), normal, dist); + clipPoly(dynamic_cast(info.shape), -normal, -dist); info.shape->getBody()->removeFromWorld(); } @@ -1208,7 +1249,7 @@ bool PhysicsDemoSlice::slice(PhysicsWorld& /*world*/, const PhysicsRayCastInfo& return true; } -void PhysicsDemoSlice::clipPoly(PhysicsShapePolygon* shape, Vec2 normal, float distance) +void PhysicsDemoSlice::clipPoly(PhysicsColliderPolygon* shape, Vec2 normal, float distance) { PhysicsBody* body = shape->getBody(); int count = shape->getPointsCount(); @@ -1237,7 +1278,7 @@ void PhysicsDemoSlice::clipPoly(PhysicsShapePolygon* shape, Vec2 normal, float d } } - Vec2 center = PhysicsShape::getPolygonCenter(points, pointsCount); + Vec2 center = PhysicsCollider::getPolygonCenter(points, pointsCount); Node* node = Node::create(); PhysicsBody* polygon = PhysicsBody::createPolygon(points, pointsCount, PHYSICSBODY_MATERIAL_DEFAULT, -center); node->setPosition(center); @@ -1305,9 +1346,9 @@ void PhysicsContactTest::onEnter() MenuItemFont::setFontSize(65); auto decrease1 = MenuItemFont::create(" - ", AX_CALLBACK_1(PhysicsContactTest::onDecrease, this)); - decrease1->setColor(Color3B(0, 200, 20)); + decrease1->setColor(Color32(0, 200, 20)); auto increase1 = MenuItemFont::create(" + ", AX_CALLBACK_1(PhysicsContactTest::onIncrease, this)); - increase1->setColor(Color3B(0, 200, 20)); + increase1->setColor(Color32(0, 200, 20)); decrease1->setTag(1); increase1->setTag(1); @@ -1323,9 +1364,9 @@ void PhysicsContactTest::onEnter() label->setPosition(Vec2(s.width / 2 - 150, prevMenuPos)); auto decrease2 = MenuItemFont::create(" - ", AX_CALLBACK_1(PhysicsContactTest::onDecrease, this)); - decrease2->setColor(Color3B(0, 200, 20)); + decrease2->setColor(Color32(0, 200, 20)); auto increase2 = MenuItemFont::create(" + ", AX_CALLBACK_1(PhysicsContactTest::onIncrease, this)); - increase2->setColor(Color3B(0, 200, 20)); + increase2->setColor(Color32(0, 200, 20)); decrease2->setTag(2); increase2->setTag(2); @@ -1339,9 +1380,9 @@ void PhysicsContactTest::onEnter() label->setPosition(Vec2(s.width / 2 - 150, prevMenuPos)); auto decrease3 = MenuItemFont::create(" - ", AX_CALLBACK_1(PhysicsContactTest::onDecrease, this)); - decrease3->setColor(Color3B(0, 200, 20)); + decrease3->setColor(Color32(0, 200, 20)); auto increase3 = MenuItemFont::create(" + ", AX_CALLBACK_1(PhysicsContactTest::onIncrease, this)); - increase3->setColor(Color3B(0, 200, 20)); + increase3->setColor(Color32(0, 200, 20)); decrease3->setTag(3); increase3->setTag(3); @@ -1355,9 +1396,9 @@ void PhysicsContactTest::onEnter() label->setPosition(Vec2(s.width / 2 - 150, prevMenuPos)); auto decrease4 = MenuItemFont::create(" - ", AX_CALLBACK_1(PhysicsContactTest::onDecrease, this)); - decrease4->setColor(Color3B(0, 200, 20)); + decrease4->setColor(Color32(0, 200, 20)); auto increase4 = MenuItemFont::create(" + ", AX_CALLBACK_1(PhysicsContactTest::onIncrease, this)); - increase4->setColor(Color3B(0, 200, 20)); + increase4->setColor(Color32(0, 200, 20)); decrease4->setTag(4); increase4->setTag(4); @@ -1654,7 +1695,6 @@ void PhysicsSetGravityEnableTest::onEnter() auto box = makeBox(Vec2(200, 100), Size(50, 50), 2); auto boxBody = box->getPhysicsBody(); - boxBody->setMass(20); boxBody->setTag(DRAG_BODYS_TAG); boxBody->setGravityEnable(false); addChild(box); @@ -1664,7 +1704,6 @@ void PhysicsSetGravityEnableTest::onEnter() auto ballBody = ball->getPhysicsBody(); ballBody->setTag(DRAG_BODYS_TAG); ballBody->setGravityEnable(false); - ballBody->setMass(50); addChild(ball); scheduleOnce(AX_SCHEDULE_SELECTOR(PhysicsSetGravityEnableTest::onScheduleOnce), 1.0); @@ -1673,7 +1712,6 @@ void PhysicsSetGravityEnableTest::onEnter() void PhysicsSetGravityEnableTest::onScheduleOnce(float /*delta*/) { auto ball = getChildByTag(2); - ball->getPhysicsBody()->setMass(200); _physicsWorld->setGravity(Vec2(0, -98)); } @@ -1751,9 +1789,9 @@ void PhysicsDemoBug5482::changeBodyCallback(Object* /*sender*/) { _body->getOwner()->removeComponent(_body); } - - // very important to have always _body and sprite in sync (Fix: #712) - node->setRotation(AX_DEGREES_TO_RADIANS(_body->getRotation())); + + // very important to have always _body and sprite in sync (Fix: #712) + node->setRotation(AX_DEGREES_TO_RADIANS(_body->getRotation())); node->addComponent(_body); _bodyInA = !_bodyInA; @@ -1914,8 +1952,8 @@ void PhysicsIssue9959::onEnter() auto scale9Sprite1 = ui::Scale9Sprite::create("Images/blocks.png"); scale9Sprite1->setPosition(origin + visibleSize / 2); addChild(scale9Sprite1); - scale9Sprite1->runAction(RepeatForever::create( - Sequence::create(MoveBy::create(2.0f, Vec2(100.0f, 0.0f)), MoveBy::create(2.0f, Vec2(-100.0f, 0.0f)), nullptr))); + scale9Sprite1->runAction(RepeatForever::create(Sequence::create( + MoveBy::create(2.0f, Vec2(100.0f, 0.0f)), MoveBy::create(2.0f, Vec2(-100.0f, 0.0f)), nullptr))); auto scale9Sprite2 = ui::Scale9Sprite::create("Images/blocks.png"); scale9Sprite2->setPosition(origin + visibleSize / 2 + Vec2(0.0f, 50.0f)); @@ -2016,7 +2054,7 @@ void PhysicsDemoPyramidStackFixedUpdate::fixedUpdate(float delta) if (_delayTime >= 3.0f && !_isAddBall) { _isAddBall = true; - auto ball = getChildByTag(100); + auto ball = getChildByTag(100); if (ball) ball->setScale(ball->getScale() * 3); } diff --git a/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.h b/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.h index 8575d6a9a958..3fd0b67f41dd 100644 --- a/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.h +++ b/tests/cpp-tests/Source/PhysicsTest/PhysicsTest.h @@ -41,6 +41,7 @@ class PhysicsDemo : public TestCase virtual bool init() override; virtual void onEnter() override; + virtual std::string title() const override; void toggleDebugCallback(ax::Object* sender); @@ -62,13 +63,17 @@ class PhysicsDemo : public TestCase void onTouchMoved(ax::Touch* touch, ax::Event* event); void onTouchEnded(ax::Touch* touch, ax::Event* event); + bool onMouseDown(ax::Event* event); + void toggleDebug(); protected: + ax::EventListenerMouse* _mouseListener{nullptr}; ax::Texture2D* _spriteTexture; ax::SpriteBatchNode* _ball; std::unordered_map _mouses; bool _debugDraw; + ax::DrawNode* _debugDrawNode{nullptr}; }; class PhysicsDemoLogoSmash : public PhysicsDemo @@ -183,7 +188,7 @@ class PhysicsDemoSlice : public PhysicsDemo virtual std::string subtitle() const override; bool slice(ax::PhysicsWorld& world, const ax::PhysicsRayCastInfo& info, void* data); - void clipPoly(ax::PhysicsShapePolygon* shape, ax::Vec2 normal, float distance); + void clipPoly(ax::PhysicsColliderPolygon* shape, ax::Vec2 normal, float distance); void onTouchEnded(ax::Touch* touch, ax::Event* event); diff --git a/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.cpp b/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.cpp index 4b79d8e7821a..397102950e0f 100644 --- a/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.cpp +++ b/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.cpp @@ -1,7 +1,7 @@ /**************************************************************************** Copyright (c) 2017-2018 Xiamen Yaji Software Co., Ltd. Copyright (c) 2019-present Axmol Engine contributors (see AUTHORS.md). - + https://axmol.dev/ Permission is hereby granted, free of charge, to any person obtaining a copy @@ -48,7 +48,7 @@ RenderTextureSave::RenderTextureSave() auto s = Director::getInstance()->getWinSize(); // create a render texture, this is what we are going to draw into - _target = RenderTexture::create(s.width, s.height, backend::PixelFormat::RGBA8); + _target = RenderTexture::create(s.width, s.height, rhi::PixelFormat::RGBA8); _target->retain(); _target->setPosition(Vec2(s.width / 2, s.height / 2)); _target->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -190,7 +190,7 @@ void RenderTextureSave::onTouchesMoved(const std::vector& touches, Event for (int i = 0; i < d; ++i) { Sprite* sprite = Sprite::create("Images/fire.png"); - sprite->setColor(Color3B::RED); + sprite->setColor(Color32::RED); sprite->setOpacity(20); _brushs.pushBack(sprite); } @@ -203,9 +203,9 @@ void RenderTextureSave::onTouchesMoved(const std::vector& touches, Event _brushs.at(i)->setRotation(rand() % 360); float r = (float)(rand() % 50 / 50.f) + 0.25f; _brushs.at(i)->setScale(r); - /*_brush->setColor(Color3B(AXRANDOM_0_1() * 127 + 128, 255, 255));*/ + /*_brush->setColor(Color32(AXRANDOM_0_1() * 127 + 128, 255, 255));*/ // Use AXRANDOM_0_1() will cause error when loading libtests.so on android, I don't know why. - _brushs.at(i)->setColor(Color3B(rand() % 127 + 128, 255, 255)); + _brushs.at(i)->setColor(Color32(rand() % 127 + 128, 255, 255)); // Call visit to draw the brush, don't call draw.. _brushs.at(i)->visit(); } @@ -233,7 +233,7 @@ RenderTextureIssue937::RenderTextureIssue937() * B1: non-premulti sprite * B2: non-premulti render */ - auto background = LayerColor::create(Color4B(200, 200, 200, 255)); + auto background = LayerColor::create(Color32(200, 200, 200, 255)); addChild(background); auto s = Director::getInstance()->getWinSize(); @@ -244,7 +244,7 @@ RenderTextureIssue937::RenderTextureIssue937() spr_nonpremulti->setPosition(Vec2(s.width / 2 - 16, s.height / 2 - 16)); /* A2 & B2 setup */ - auto rend = RenderTexture::create(32, 64, backend::PixelFormat::RGBA8); + auto rend = RenderTexture::create(32, 64, rhi::PixelFormat::RGBA8); if (nullptr == rend) { @@ -345,7 +345,7 @@ RenderTextureZbuffer::RenderTextureZbuffer() sp9->setPositionZ(-400); sp9->setScale(2); - sp9->setColor(Color3B::YELLOW); + sp9->setColor(Color32::YELLOW); } std::string RenderTextureZbuffer::title() const @@ -422,7 +422,7 @@ void RenderTextureZbuffer::renderScreenShot() sprite->setOpacity(182); sprite->setFlippedY(1); this->addChild(sprite, 999999); - sprite->setColor(Color3B::GREEN); + sprite->setColor(Color32::GREEN); sprite->runAction(Sequence::create(FadeTo::create(2, 0), RemoveSelf::create(), nullptr)); } @@ -446,7 +446,7 @@ RenderTexturePartTest::RenderTexturePartTest() addChild(sprite2); addChild(sprite22); - _rend = RenderTexture::create(200, 200, backend::PixelFormat::RGBA8); + _rend = RenderTexture::create(200, 200, rhi::PixelFormat::RGBA8); _rend->retain(); _rend->setKeepMatrix(true); Size pixelSize = Director::getInstance()->getWinSizeInPixels(); @@ -508,7 +508,7 @@ RenderTextureTestDepthStencil::RenderTextureTestDepthStencil() Vec2(_spriteDraw->getContentSize().width * _spriteDraw->getScale() * 0.5f, _spriteDraw->getContentSize().height * _spriteDraw->getScale() * 0.5f)); - _rtx = RenderTexture::create(s.width, s.height, backend::PixelFormat::RGBA4, PixelFormat::D24S8); + _rtx = RenderTexture::create(s.width, s.height, rhi::PixelFormat::RGBA4, PixelFormat::D24S8); _rtx->setPosition(Vec2(s.width * 0.5f, s.height * 0.5f)); _rtx->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -564,14 +564,14 @@ void RenderTextureTestDepthStencil::onBeforeStencil() { //! mark sprite quad into stencil buffer _renderer->setStencilTest(true); - _renderer->setStencilCompareFunction(backend::CompareFunction::NEVER, 1, 0xFF); - _renderer->setStencilOperation(backend::StencilOperation::REPLACE, backend::StencilOperation::REPLACE, - backend::StencilOperation::REPLACE); + _renderer->setStencilCompareFunc(rhi::CompareFunc::NEVER, 1, 0xFF); + _renderer->setStencilOp(rhi::StencilOp::REPLACE, rhi::StencilOp::REPLACE, + rhi::StencilOp::REPLACE); } void RenderTextureTestDepthStencil::onBeforeDraw() { - _renderer->setStencilCompareFunction(backend::CompareFunction::NOT_EQUAL, 1, 0xFF); + _renderer->setStencilCompareFunc(rhi::CompareFunc::NOT_EQUAL, 1, 0xFF); } void RenderTextureTestDepthStencil::onAfterDraw() @@ -604,7 +604,7 @@ RenderTextureTargetNode::RenderTextureTargetNode() * B1: non-premulti sprite * B2: non-premulti render */ - auto background = LayerColor::create(Color4B(40, 40, 40, 255)); + auto background = LayerColor::create(Color32(40, 40, 40, 255)); addChild(background); // sprite 1 @@ -616,7 +616,7 @@ RenderTextureTargetNode::RenderTextureTargetNode() auto s = Director::getInstance()->getWinSize(); /* Create the render texture */ - renderTexture = RenderTexture::create(s.width, s.height, backend::PixelFormat::RGBA4); + renderTexture = RenderTexture::create(s.width, s.height, rhi::PixelFormat::RGBA4); renderTexture->setPosition(Vec2(s.width / 2, s.height / 2)); renderTexture->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -632,8 +632,7 @@ RenderTextureTargetNode::RenderTextureTargetNode() sprite2->setAnchorPoint(Vec2::ANCHOR_MIDDLE); sprite2->setPosition(_spriteCenterPosition); renderTexture->addChild(sprite2); - - renderTexture->setClearColor(Color4F(0, 0, 0, 0)); + renderTexture->setClearColor(Color(0, 0, 0, 0)); renderTexture->setClearFlags(ClearFlag::COLOR); /* add the render texture to the scene */ @@ -661,7 +660,7 @@ void RenderTextureTargetNode::touched(Object* sender) else { renderTexture->setClearFlags(ClearFlag::NONE); - renderTexture->setClearColor(Color4F(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); + renderTexture->setClearColor(Color(AXRANDOM_0_1(), AXRANDOM_0_1(), AXRANDOM_0_1(), 1)); } } @@ -714,7 +713,7 @@ void SpriteRenderTextureBug::SimpleSprite::draw(Renderer* renderer, const Mat4& if (_rt == nullptr) { auto s = Director::getInstance()->getWinSize(); - _rt = RenderTexture::create(s.width, s.height, backend::PixelFormat::RGBA8); + _rt = RenderTexture::create(s.width, s.height, rhi::PixelFormat::RGBA8); _rt->retain(); } _rt->beginWithClear(0.0f, 0.0f, 0.0f, 1.0f); @@ -798,8 +797,8 @@ Issue16113Test::Issue16113Test() auto item1 = MenuItemFont::create("Save Image", [&](Object* ref) { auto winSize = Director::getInstance()->getVisibleSize(); auto text = Label::createWithTTF("hello world", "fonts/Marker Felt.ttf", 40); - text->setTextColor(Color4B::RED); - auto target = RenderTexture::create(winSize.width, winSize.height, backend::PixelFormat::RGBA8); + text->setTextColor(Color32::RED); + auto target = RenderTexture::create(winSize.width, winSize.height, rhi::PixelFormat::RGBA8); target->beginWithClear(0, 0, 0, 0); text->setPosition(winSize.width / 2, winSize.height / 2); text->Node::visit(); diff --git a/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.h b/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.h index aa768e16777a..d96c84ea6967 100644 --- a/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.h +++ b/tests/cpp-tests/Source/RenderTextureTest/RenderTextureTest.h @@ -25,8 +25,8 @@ #ifndef _RENDERTEXTURE_TEST_H_ #define _RENDERTEXTURE_TEST_H_ -#include "axmol.h" -#include "renderer/backend/DepthStencilState.h" +#include "axmol/axmol.h" +#include "axmol/rhi/DepthStencilState.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(RenderTextureTests); @@ -110,7 +110,7 @@ class RenderTextureTestDepthStencil : public RenderTextureTest private: ax::Renderer* _renderer; - ax::backend::DepthStencilDescriptor _dsDesc; + ax::rhi::DepthStencilDesc _dsDesc; ax::RenderTexture* _rtx; ax::Sprite* _spriteDS; ax::Sprite* _spriteDraw; diff --git a/tests/cpp-tests/Source/RotateWorldTest/RotateWorldTest.cpp b/tests/cpp-tests/Source/RotateWorldTest/RotateWorldTest.cpp index de2556dbebd1..b3ef70a32eef 100644 --- a/tests/cpp-tests/Source/RotateWorldTest/RotateWorldTest.cpp +++ b/tests/cpp-tests/Source/RotateWorldTest/RotateWorldTest.cpp @@ -124,10 +124,10 @@ void RotateWorldMainLayer::onEnter() x = size.width; y = size.height; - auto blue = LayerColor::create(Color4B(0, 0, 255, 255)); - auto red = LayerColor::create(Color4B(255, 0, 0, 255)); - auto dark = LayerColor::create(Color4B(2, 2, 2, 255)); - auto white = LayerColor::create(Color4B(255, 255, 255, 255)); + auto blue = LayerColor::create(Color32(0, 0, 255, 255)); + auto red = LayerColor::create(Color32(255, 0, 0, 255)); + auto dark = LayerColor::create(Color32(2, 2, 2, 255)); + auto white = LayerColor::create(Color32(255, 255, 255, 255)); blue->setScale(0.5f); blue->setPosition(Vec2(-x / 4, -y / 4)); diff --git a/tests/cpp-tests/Source/Scene3DTest/Scene3DTest.cpp b/tests/cpp-tests/Source/Scene3DTest/Scene3DTest.cpp index 9f3be164bbf9..846c810a4557 100644 --- a/tests/cpp-tests/Source/Scene3DTest/Scene3DTest.cpp +++ b/tests/cpp-tests/Source/Scene3DTest/Scene3DTest.cpp @@ -25,8 +25,8 @@ #include "Scene3DTest.h" -#include "ui/CocosGUI.h" -#include "renderer/RenderState.h" +#include "axmol/ui/CocosGUI.h" +#include "axmol/renderer/RenderState.h" #include #include "../testResource.h" @@ -372,11 +372,9 @@ void Scene3DTestScene::createWorld3D() "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", "MeshRendererTest/skybox/front.jpg", "MeshRendererTest/skybox/back.jpg"); // set texture parameters - Texture2D::TexParams tRepeatParams; - tRepeatParams.magFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.minFilter = backend::SamplerFilter::LINEAR; - tRepeatParams.sAddressMode = backend::SamplerAddressMode::MIRROR_REPEAT; - tRepeatParams.tAddressMode = backend::SamplerAddressMode::MIRROR_REPEAT; + Texture2D::TexParams tRepeatParams{}; + tRepeatParams.sAddressMode = rhi::SamplerAddressMode::MIRROR; + tRepeatParams.tAddressMode = rhi::SamplerAddressMode::MIRROR; _textureCube->setTexParameters(tRepeatParams); // add skybox diff --git a/tests/cpp-tests/Source/SceneTest/SceneTest.cpp b/tests/cpp-tests/Source/SceneTest/SceneTest.cpp index f01b28880bc2..c99b7d5d373e 100644 --- a/tests/cpp-tests/Source/SceneTest/SceneTest.cpp +++ b/tests/cpp-tests/Source/SceneTest/SceneTest.cpp @@ -180,7 +180,7 @@ SceneTestLayer3::SceneTestLayer3() {} bool SceneTestLayer3::init() { - if (LayerColor::initWithColor(Color4B(0, 0, 255, 255))) + if (LayerColor::initWithColor(Color32(0, 0, 255, 255))) { auto s = Director::getInstance()->getWinSize(); @@ -219,7 +219,7 @@ void SceneTestLayer3::item0Clicked(Object* sender) auto s = Director::getInstance()->getWinSize(); auto newScene = Scene::createWithSize(s); newScene->addChild(SceneTestLayer3::create()); - Director::getInstance()->pushScene(TransitionFade::create(0.5, newScene, Color3B(0, 255, 255))); + Director::getInstance()->pushScene(TransitionFade::create(0.5, newScene, Color32(0, 255, 255))); } void SceneTestLayer3::item1Clicked(Object* sender) diff --git a/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.cpp b/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.cpp index e787917abb04..7fc113bc58ac 100644 --- a/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.cpp +++ b/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.cpp @@ -24,7 +24,7 @@ #include "SchedulerTest.h" #include "../testResource.h" -#include "ui/UIText.h" +#include "axmol/ui/UIText.h" #include "controller.h" using namespace ax; @@ -1063,7 +1063,7 @@ void SchedulerIssueWithReschedule::onEnter() Size widgetSize = getContentSize(); auto status_text = Text::create("Checking..", "fonts/Marker Felt.ttf", 18); - status_text->setColor(Color3B(255, 255, 255)); + status_text->setColor(Color32(255, 255, 255)); status_text->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); addChild(status_text); @@ -1090,13 +1090,13 @@ void SchedulerIssueWithReschedule::onEnter() { AXLOGD("SchedulerIssueWithReschedule - test OK"); status_text->setString("OK"); - status_text->setColor(Color3B(0, 255, 0)); + status_text->setColor(Color32(0, 255, 0)); } else { AXLOGD("SchedulerIssueWithReschedule - test failed!"); status_text->setString("Failed"); - status_text->setColor(Color3B(255, 0, 0)); + status_text->setColor(Color32(255, 0, 0)); } }, this, 0.5f, 0, 0, false, "test_verify_timer"); diff --git a/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.h b/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.h index f828317f2a99..d0023104243a 100644 --- a/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.h +++ b/tests/cpp-tests/Source/SchedulerTest/SchedulerTest.h @@ -25,7 +25,7 @@ #ifndef _SCHEDULER_TEST_H_ #define _SCHEDULER_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" #include "../BaseTest.h" diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp b/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp index 11d039dd5d24..56615809b96f 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest.cpp @@ -24,9 +24,9 @@ #include "ShaderTest.h" #include "../testResource.h" -#include "axmol.h" -#include "renderer/Shaders.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/axmol.h" +#include "axmol/renderer/Shaders.h" +#include "axmol/rhi/DriverBase.h" using namespace ax; USING_NS_AX_EXT; @@ -104,14 +104,14 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) setAnchorPoint(Vec2(0.5f, 0.5f)); // init custom command - auto attrPosLoc = _programState->getAttributeLocation("a_position"); + auto inputDesc = _programState->getVertexInputDesc("a_position"); - auto vertexLayout = _programState->getMutableVertexLayout(); - vertexLayout->setAttrib("a_position", attrPosLoc, backend::VertexFormat::FLOAT2, 0, false); + //auto vertexLayout = _programState->getMutableVertexLayout(); + //vertexLayout->setAttrib("a_position", attrPosLoc, rhi::VertexFormat::FLOAT4, 0, false); float w = SIZE_X, h = SIZE_Y; - Vec2 vertices[6] = {Vec2(0.0f, 0.0f), Vec2(w, 0.0f), Vec2(w, h), Vec2(0.0f, 0.0f), Vec2(0.0f, h), Vec2(w, h)}; - vertexLayout->setStride(sizeof(Vec2)); + Vec3 vertices[6] = {Vec3(0.0f, 0.0f, 1.0f), Vec3(w, 0.0f, 1.0f), Vec3(w, h, 1.0f), + Vec3(0.0f, 0.0f, 1.0f), Vec3(0.0f, h, 1.0f), Vec3(w, h, 1.0f)}; /* * TODO: the Y-coordinate of subclasses are flipped in metal @@ -119,7 +119,7 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) * keywords: AX_USE_METAL , AX_USE_GL */ - _customCommand.createVertexBuffer(sizeof(Vec2), 6, CustomCommand::BufferUsage::STATIC); + _customCommand.createVertexBuffer(sizeof(Vec3), 6, CustomCommand::BufferUsage::STATIC); _customCommand.updateVertexBuffer(vertices, sizeof(vertices)); _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); @@ -129,8 +129,8 @@ bool ShaderNode::initWithVertex(std::string_view vert, std::string_view frag) void ShaderNode::loadShaderVertex(std::string_view vert, std::string_view frag) { - auto program = ProgramManager::getInstance()->loadProgram(vert, frag, VertexLayoutType::Sprite); - auto programState = new backend::ProgramState(program); + auto program = ProgramManager::getInstance()->loadProgram(vert, frag, VertexLayoutType::Pos); + auto programState = new rhi::ProgramState(program); setProgramState(programState); AX_SAFE_RELEASE(programState); } @@ -435,7 +435,7 @@ bool SpriteBlur::initWithTexture(Texture2D* texture, const Rect& rect) void SpriteBlur::initProgram() { auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs", VertexLayoutType::Sprite); - auto programState = new backend::ProgramState(program); + auto programState = new rhi::ProgramState(program); setProgramState(programState); AX_SAFE_RELEASE(programState); @@ -567,7 +567,7 @@ bool ShaderRetroEffect::init() char* fragSource = (char*)fragStr.c_str(); auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_HorizontalColor_fs", VertexLayoutType::Sprite); - auto p = new backend::ProgramState(program); + auto p = new rhi::ProgramState(program); auto director = Director::getInstance(); const auto& screenSizeLocation = p->getUniformLocation("u_screenSize"); const auto& frameSize = director->getRenderView()->getFrameSize(); @@ -746,7 +746,7 @@ bool ShaderMultiTexture::init() _sprite->setPosition(Vec2(s.width / 2, s.height / 2)); auto program = ProgramManager::getInstance()->loadProgram("custom/example_MultiTexture_vs", "custom/example_MultiTexture_fs", VertexLayoutType::Sprite); - auto programState = new backend::ProgramState(program); + auto programState = new rhi::ProgramState(program); _sprite->setProgramState(programState); SET_TEXTURE(programState, "u_tex1", 1, right->getTexture()->getBackendTexture()); diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest.h b/tests/cpp-tests/Source/ShaderTest/ShaderTest.h index 5b59bd63820e..64f11c5195ab 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest.h +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest.h @@ -24,7 +24,7 @@ #pragma once -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" #include "extensions/axmol-ext.h" #include "../BaseTest.h" @@ -153,11 +153,11 @@ class ShaderNode : public ax::Node bool initWithVertex(std::string_view vert, std::string_view frag); void loadShaderVertex(std::string_view vert, std::string_view frag); - virtual bool setProgramState(ax::backend::ProgramState* programState, bool ownPS = false) override + virtual bool setProgramState(ax::rhi::ProgramState* programState, bool ownPS = false) override { if (Node::setProgramState(programState, ownPS)) { - _customCommand.getPipelineDescriptor().programState = programState; + _customCommand.getPipelineDesc().programState = programState; updateUniforms(); return true; } @@ -173,13 +173,13 @@ class ShaderNode : public ax::Node std::string _fragFileName; ax::CustomCommand _customCommand; - ax::backend::UniformLocation _locResolution; - ax::backend::UniformLocation _locCenter; - ax::backend::UniformLocation _locMVP; - ax::backend::UniformLocation _locTime; - ax::backend::UniformLocation _locSinTime; - ax::backend::UniformLocation _locCosTime; - ax::backend::UniformLocation _locScreenSize; + ax::rhi::UniformLocation _locResolution; + ax::rhi::UniformLocation _locCenter; + ax::rhi::UniformLocation _locMVP; + ax::rhi::UniformLocation _locTime; + ax::rhi::UniformLocation _locSinTime; + ax::rhi::UniformLocation _locCosTime; + ax::rhi::UniformLocation _locScreenSize; }; class ShaderLensFlare : public ShaderTestDemo diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp index 1697d47f6a9d..d9ec701c3969 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.cpp @@ -26,8 +26,8 @@ #include "ShaderTest2.h" #include "ShaderTest.h" #include "../testResource.h" -#include "axmol.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/axmol.h" +#include "axmol/rhi/DriverBase.h" #include using namespace ax; @@ -63,7 +63,7 @@ static int tuple_sort(const std::tuple& tuple1, return std::get<0>(tuple1) < std::get<0>(tuple2); } -static void updateUniforms(backend::ProgramState* programState) +static void updateUniforms(rhi::ProgramState* programState) { float time = Director::getInstance()->getTotalFrames() * Director::getInstance()->getAnimationInterval(); Vec4 uTime(time / 10.0f, time, time * 2.0f, time * 4.0f); @@ -145,7 +145,7 @@ class EffectSprite : public Sprite // normal effect: order == 0 _trianglesCommand.init(_globalZOrder, _texture, _blendFunc, _polyInfo.triangles, transform, flags); - updateUniforms(_trianglesCommand.getPipelineDescriptor().programState); + updateUniforms(_trianglesCommand.getPipelineDesc().programState); renderer->addCommand(&_trianglesCommand); // positive effects: order >= 0 @@ -155,7 +155,7 @@ class EffectSprite : public Sprite auto* programState = std::get<1>(*it)->getProgramState(); updateUniforms(programState); q.init(_globalZOrder, _texture, _blendFunc, &_quad, 1, transform, flags); - q.getPipelineDescriptor().programState = programState; + q.getPipelineDesc().programState = programState; renderer->addCommand(&q); idx++; } @@ -184,7 +184,7 @@ class EffectSprite : public Sprite bool Effect::initProgramState(std::string_view fragmentFilename) { auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, fragmentFilename, VertexLayoutType::Sprite); - auto programState = new backend::ProgramState(program); + auto programState = new rhi::ProgramState(program); AX_SAFE_RELEASE(_programState); _programState = programState; @@ -413,7 +413,7 @@ class EffectNormalMapped : public Effect } void setKBump(float value); void setLightPos(const Vec3& pos); - void setLightColor(const Color4F& color); + void setLightColor(const Color& color); float getKBump() const { return _kBump; } protected: @@ -422,7 +422,7 @@ class EffectNormalMapped : public Effect virtual void setTarget(EffectSprite* sprite) override; EffectSprite* _sprite; Vec3 _lightPos; - Color4F _lightColor; + Color _lightColor; float _kBump; }; @@ -457,7 +457,7 @@ void EffectNormalMapped::setLightPos(const Vec3& pos) SET_UNIFORM(_programState, "u_lightPosInLocalSpace", Vec4(_lightPos.x, _lightPos.y, _lightPos.z, 1)); } -void EffectNormalMapped::setLightColor(const Color4F& color) +void EffectNormalMapped::setLightColor(const Color& color) { _lightColor = color; SET_UNIFORM(_programState, "u_diffuseL", Vec3(_lightColor.r, _lightColor.g, _lightColor.b)); @@ -470,7 +470,7 @@ bool EffectSpriteTest::init() if (ShaderTestDemo2::init()) { - auto layer = LayerColor::create(Color4B::BLUE); + auto layer = LayerColor::create(Color32::BLUE); this->addChild(layer); auto s = Director::getInstance()->getWinSize(); @@ -552,7 +552,7 @@ bool EffectSpriteLamp::init() Mat4 mat = _sprite->getNodeToWorldTransform(); Point lightPosInLocalSpace = PointApplyAffineTransform(Vec2(pos.x, pos.y), _sprite->getWorldToNodeAffineTransform()); - lampEffect->setLightColor(Color4F(1, 1, 1, 1)); + lampEffect->setLightColor(Color(1, 1, 1, 1)); lampEffect->setLightPos(Vec3(lightPosInLocalSpace.x, lightPosInLocalSpace.y, 50.0f)); lampEffect->setKBump(2); _sprite->setEffect(lampEffect); diff --git a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.h b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.h index d86586c7350d..50dd4409d19d 100644 --- a/tests/cpp-tests/Source/ShaderTest/ShaderTest2.h +++ b/tests/cpp-tests/Source/ShaderTest/ShaderTest2.h @@ -44,14 +44,14 @@ class EffectSprite; class Effect : public ax::Object { public: - ax::backend::ProgramState* getProgramState() const { return _programState; } + ax::rhi::ProgramState* getProgramState() const { return _programState; } virtual void setTarget(EffectSprite* sprite) {} protected: bool initProgramState(std::string_view fragmentFilename); Effect(); virtual ~Effect(); - ax::backend::ProgramState* _programState = nullptr; + ax::rhi::ProgramState* _programState = nullptr; #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) std::string _fragSource; ax::EventListenerCustom* _backgroundListener; diff --git a/tests/cpp-tests/Source/SpineTest/SpineTest.cpp b/tests/cpp-tests/Source/SpineTest/SpineTest.cpp index bef3a9c7cd2e..8b246480c6ff 100644 --- a/tests/cpp-tests/Source/SpineTest/SpineTest.cpp +++ b/tests/cpp-tests/Source/SpineTest/SpineTest.cpp @@ -41,7 +41,7 @@ using namespace spine; decltype(value) __v = value; \ auto __loc = (ps)->getUniformLocation(name); \ (ps)->setUniform(__loc, &__v, sizeof(__v)); \ - } while (false) + } while (false) #define NUM_SKELETONS 50 #define SPINE_NODE_SCALE_FACTOR 0.4 @@ -132,7 +132,7 @@ bool SpineTestLayer::init() skeletonNode->setTimeScale(0.3f); // refer issue: https://github.com/axmolengine/axmol/issues/482 - // Get Spine node PS and update uniforms + // Get Spine node PS and update uniforms auto skeleton1PS = skeletonNode->getProgramState(); if (skeleton1PS) @@ -146,7 +146,7 @@ bool SpineTestLayer::init() SET_UNIFORM(skeleton1PS, "blurRadius", blurRadius); SET_UNIFORM(skeleton1PS, "sampleNum", sampleNum); } - + } return true; }; @@ -366,8 +366,8 @@ bool MixAndMatchExample::init() // load hsv as custom, we don't want batch draw auto hsvProg = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, hsv_frag, VertexLayoutType::Sprite); - - auto ps1 = new backend::ProgramState(hsvProg); + + auto ps1 = new rhi::ProgramState(hsvProg); SET_UNIFORM(ps1, "u_hsv", Vec3(92.0f, 1.0f, 1.2f)); ps1->updateBatchId(); skeletonNode->setProgramState(ps1, true); @@ -398,7 +398,7 @@ bool MixAndMatchExample::init() SCALE_SKELETON_NODE(skeletonNode2); - auto ps2 = new backend::ProgramState(hsvProg); + auto ps2 = new rhi::ProgramState(hsvProg); SET_UNIFORM(ps2, "u_hsv", Vec3(-45.0f, 1.0f, 1.2f)); ps2->updateBatchId(); skeletonNode2->setProgramState(ps2, true); @@ -462,7 +462,7 @@ bool SkeletonRendererSeparatorExample::init() rect[1] = Vec2(40, 0); rect[2] = Vec2(40, 200); rect[3] = Vec2(0, 200); - betweenNode->drawPolygon(rect, 4, Color4F(1, 0, 0, 1), 1, Color4F(1, 0, 0, 1)); + betweenNode->drawPolygon(rect, 4, ax::Color(1, 0, 0, 1), 1, ax::Color(1, 0, 0, 1)); betweenNode->setPosition(Vec2(_contentSize.width / 2 + 30, 20)); // Spineboy's front, doesn't manage any skeleton, animation or GPU resources, but simply // renders the back slots of Spineboy. The skeleton, animatio state and GPU resources @@ -539,7 +539,7 @@ bool SpineboyExample::init() auto program = ProgramManager::getInstance()->loadProgram(positionTextureColor_vert, "custom/example_Blur_fs", VertexLayoutType::Sprite); - skeletonNode->setProgramState(new backend::ProgramState(program), true); + skeletonNode->setProgramState(new rhi::ProgramState(program), true); //auto skeleton1PS = skeletonNode->getProgramState(); diff --git a/tests/cpp-tests/Source/SpineTest/SpineTest.h b/tests/cpp-tests/Source/SpineTest/SpineTest.h index 0516469a0e3b..68889384bbb0 100644 --- a/tests/cpp-tests/Source/SpineTest/SpineTest.h +++ b/tests/cpp-tests/Source/SpineTest/SpineTest.h @@ -26,7 +26,7 @@ #ifndef _SPINETEST_H_ #define _SPINETEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #include diff --git a/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.cpp b/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.cpp index d4ee2426f59a..6fa7409655f6 100644 --- a/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.cpp +++ b/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.cpp @@ -29,7 +29,7 @@ #include -#include "NinePatchImageParser.h" +#include "axmol/base/NinePatchImageParser.h" using namespace ax; @@ -52,31 +52,27 @@ SpriteFrameCachePixelFormatTest::SpriteFrameCachePixelFormatTest() addChild(infoLabel); // load atlas definition with specified PixelFormat and check that it matches to expected format - loadSpriteFrames("Images/sprite_frames_test/test_A8.plist", backend::PixelFormat::R8); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", backend::PixelFormat::RGBA8); - loadSpriteFrames("Images/sprite_frames_test/test_AI88.plist", backend::PixelFormat::RG8); - loadSpriteFrames("Images/sprite_frames_test/test_RGB565.plist", backend::PixelFormat::RGB565); - loadSpriteFrames("Images/sprite_frames_test/test_RGB888.plist", backend::PixelFormat::RGB8); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA4444.plist", backend::PixelFormat::RGBA4); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA5551.plist", backend::PixelFormat::RGB5A1); + loadSpriteFrames("Images/sprite_frames_test/test_A8.plist", rhi::PixelFormat::R8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", rhi::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_AI88.plist", rhi::PixelFormat::RG8); + loadSpriteFrames("Images/sprite_frames_test/test_RGB565.plist", rhi::PixelFormat::RGB565); + loadSpriteFrames("Images/sprite_frames_test/test_RGB888.plist", rhi::PixelFormat::RGB8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA4444.plist", rhi::PixelFormat::RGBA4); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA5551.plist", rhi::PixelFormat::RGB5A1); if (Configuration::getInstance()->supportsPVRTC()) { - loadSpriteFrames("Images/sprite_frames_test/test_PVRTC2.plist", backend::PixelFormat::PVRTC2A); - loadSpriteFrames("Images/sprite_frames_test/test_PVRTC4.plist", backend::PixelFormat::PVRTC4A); - loadSpriteFrames("Images/sprite_frames_test/test_PVRTC2_NOALPHA.plist", backend::PixelFormat::PVRTC2); + loadSpriteFrames("Images/sprite_frames_test/test_PVRTC2.plist", rhi::PixelFormat::PVRTC2A); + loadSpriteFrames("Images/sprite_frames_test/test_PVRTC4.plist", rhi::PixelFormat::PVRTC4A); + loadSpriteFrames("Images/sprite_frames_test/test_PVRTC2_NOALPHA.plist", rhi::PixelFormat::PVRTC2); } // test loading atlases without PixelFormat specified - Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat::RGB5A1); - loadSpriteFrames("Images/sprite_frames_test/test_NoFormat.plist", backend::PixelFormat::RGB5A1); - - // restore default alpha pixel format - Texture2D::setDefaultAlphaPixelFormat(backend::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_NoFormat.plist", rhi::PixelFormat::RGBA8); } void SpriteFrameCachePixelFormatTest::loadSpriteFrames(std::string_view file, - ax::backend::PixelFormat expectedFormat) + ax::rhi::PixelFormat expectedFormat) { SpriteFrameCache::getInstance()->addSpriteFramesWithFile(file); SpriteFrame* spriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("sprite_frames_test/grossini.png"); @@ -98,14 +94,14 @@ SpriteFrameCacheLoadMultipleTimes::SpriteFrameCacheLoadMultipleTimes() const Size screenSize = Director::getInstance()->getWinSize(); // load atlas definition with specified PixelFormat and check that it matches to expected format - loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", backend::PixelFormat::RGBA8); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", backend::PixelFormat::RGBA8); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", backend::PixelFormat::RGBA8); - loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", backend::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", rhi::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", rhi::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", rhi::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_RGBA8888.plist", rhi::PixelFormat::RGBA8); } void SpriteFrameCacheLoadMultipleTimes::loadSpriteFrames(std::string_view file, - ax::backend::PixelFormat expectedFormat) + ax::rhi::PixelFormat expectedFormat) { SpriteFrameCache::getInstance()->addSpriteFramesWithFile(file); SpriteFrame* spriteFrame = SpriteFrameCache::getInstance()->getSpriteFrameByName("sprite_frames_test/grossini.png"); @@ -119,10 +115,10 @@ SpriteFrameCacheFullCheck::SpriteFrameCacheFullCheck() { const Size screenSize = Director::getInstance()->getWinSize(); // load atlas definition with specified PixelFormat and check that it matches to expected format - loadSpriteFrames("Images/test_polygon.plist", backend::PixelFormat::RGBA8); + loadSpriteFrames("Images/test_polygon.plist", rhi::PixelFormat::RGBA8); } -void SpriteFrameCacheFullCheck::loadSpriteFrames(std::string_view file, ax::backend::PixelFormat expectedFormat) +void SpriteFrameCacheFullCheck::loadSpriteFrames(std::string_view file, ax::rhi::PixelFormat expectedFormat) { auto cache = SpriteFrameCache::getInstance(); @@ -290,39 +286,7 @@ class GenericJsonArraySpriteSheetLoader : public SpriteSheetLoader std::string_view atlasPath, SpriteFrameCache& cache) { - std::string pixelFormatName; - auto&& metaItr = doc.FindMember("meta"); - if (metaItr != doc.MemberEnd()) - { - auto&& pixelFormatItr = metaItr->value.FindMember("format"); - if (pixelFormatItr != metaItr->value.MemberEnd()) - { - pixelFormatName = pixelFormatItr->value.GetString(); - } - } - - Texture2D* texture = nullptr; - static std::unordered_map pixelFormats = { - {"RGBA8888", backend::PixelFormat::RGBA8}, - {"RGBA4444", backend::PixelFormat::RGBA4}, - {"RGB5A1", backend::PixelFormat::RGB5A1}, - {"RGBA5551", backend::PixelFormat::RGB5A1}, - {"RGB565", backend::PixelFormat::RGB565}, - {"R8", backend::PixelFormat::R8}, - {"RG8", backend::PixelFormat::RG8}, - //{"BGRA8888", backend::PixelFormat::BGRA8888}, no Image conversion RGBA -> BGRA - {"RGB888", backend::PixelFormat::RGB8}}; - - const auto pixelFormatIt = pixelFormats.find(pixelFormatName); - if (pixelFormatIt != pixelFormats.end()) - { - const backend::PixelFormat pixelFormat = (*pixelFormatIt).second; - texture = Director::getInstance()->getTextureCache()->addImage(texturePath, pixelFormat); - } - else - { - texture = Director::getInstance()->getTextureCache()->addImage(texturePath); - } + Texture2D* const texture = Director::getInstance()->getTextureCache()->addImage(texturePath); if (texture) { @@ -474,7 +438,7 @@ SpriteFrameCacheJsonAtlasTest::SpriteFrameCacheJsonAtlasTest() infoLabel->setPosition(screenSize.width * 0.5f, screenSize.height * 0.7f); addChild(infoLabel); - loadSpriteFrames("Images/sprite_frames_test/test_RGB8888_generic.json"sv, backend::PixelFormat::RGBA8); + loadSpriteFrames("Images/sprite_frames_test/test_RGB8888_generic.json"sv, rhi::PixelFormat::RGBA8); } SpriteFrameCacheJsonAtlasTest::~SpriteFrameCacheJsonAtlasTest() @@ -484,7 +448,7 @@ SpriteFrameCacheJsonAtlasTest::~SpriteFrameCacheJsonAtlasTest() } void SpriteFrameCacheJsonAtlasTest::loadSpriteFrames(std::string_view file, - ax::backend::PixelFormat expectedFormat) + ax::rhi::PixelFormat expectedFormat) { SpriteFrameCache::getInstance()->addSpriteFramesWithFile(file, GenericJsonArraySpriteSheetLoader::FORMAT); SpriteFrame* spriteFrame = diff --git a/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.h b/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.h index cbe8b6a8e400..e8847eb98006 100644 --- a/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.h +++ b/tests/cpp-tests/Source/SpriteFrameCacheTest/SpriteFrameCacheTest.h @@ -25,7 +25,7 @@ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(SpriteFrameCacheTests); @@ -41,7 +41,7 @@ class SpriteFrameCachePixelFormatTest : public TestCase SpriteFrameCachePixelFormatTest(); private: - void loadSpriteFrames(std::string_view file, ax::backend::PixelFormat expectedFormat); + void loadSpriteFrames(std::string_view file, ax::rhi::PixelFormat expectedFormat); private: ax::Label* infoLabel; @@ -58,7 +58,7 @@ class SpriteFrameCacheLoadMultipleTimes : public TestCase SpriteFrameCacheLoadMultipleTimes(); private: - void loadSpriteFrames(std::string_view file, ax::backend::PixelFormat expectedFormat); + void loadSpriteFrames(std::string_view file, ax::rhi::PixelFormat expectedFormat); }; class SpriteFrameCacheFullCheck : public TestCase @@ -72,7 +72,7 @@ class SpriteFrameCacheFullCheck : public TestCase SpriteFrameCacheFullCheck(); private: - void loadSpriteFrames(std::string_view file, ax::backend::PixelFormat expectedFormat); + void loadSpriteFrames(std::string_view file, ax::rhi::PixelFormat expectedFormat); }; class SpriteFrameCacheJsonAtlasTest : public TestCase @@ -87,7 +87,7 @@ class SpriteFrameCacheJsonAtlasTest : public TestCase ~SpriteFrameCacheJsonAtlasTest() override; private: - void loadSpriteFrames(std::string_view file, ax::backend::PixelFormat expectedFormat); + void loadSpriteFrames(std::string_view file, ax::rhi::PixelFormat expectedFormat); ax::Label* infoLabel; }; diff --git a/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.cpp b/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.cpp index 578fcea27448..19b89c44e47b 100644 --- a/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.cpp +++ b/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.cpp @@ -24,7 +24,7 @@ #include "SpritePolygonTest.h" #include "../testResource.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" #include #include @@ -44,7 +44,7 @@ SpritePolygonTest::SpritePolygonTest() ADD_TEST_CASE(SpritePolygonTestAutoPolyIsland); ADD_TEST_CASE(SpritePolygonTestFrameAnim); ADD_TEST_CASE(Issue14017Test); - ADD_TEST_CASE(SpritePolygonTestPerformance); + ADD_TEST_CASE(SpritePolygonTestPerformance); } SpritePolygonTestCase::SpritePolygonTestCase() @@ -61,12 +61,12 @@ SpritePolygonTestCase::~SpritePolygonTestCase() void SpritePolygonTestCase::onEnter() { TestCase::onEnter(); - Director::getInstance()->setClearColor(Color4F(102.0f / 255.0f, 184.0f / 255.0f, 204.0f / 255.0f, 1.0f)); + Director::getInstance()->setClearColor(Color(102.0f / 255.0f, 184.0f / 255.0f, 204.0f / 255.0f, 1.0f)); } void SpritePolygonTestCase::onExit() { - Director::getInstance()->setClearColor(Color4F::BLACK); + Director::getInstance()->setClearColor(Color::BLACK); TestCase::onExit(); } @@ -129,17 +129,17 @@ void SpritePolygonTestCase::updateDrawNode() for (ssize_t i = 0; i < count; i++) { // draw 3 lines - Vec3 from = verts[indices[i * 3]].vertices; - Vec3 to = verts[indices[i * 3 + 1]].vertices; - drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4F::BLUE); + Vec3 from = verts[indices[i * 3]].position; + Vec3 to = verts[indices[i * 3 + 1]].position; + drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color::BLUE); - from = verts[indices[i * 3 + 1]].vertices; - to = verts[indices[i * 3 + 2]].vertices; - drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4F::GREEN); + from = verts[indices[i * 3 + 1]].position; + to = verts[indices[i * 3 + 2]].position; + drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color::GREEN); - from = verts[indices[i * 3 + 2]].vertices; - to = verts[indices[i * 3]].vertices; - drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color4F::RED); + from = verts[indices[i * 3 + 2]].position; + to = verts[indices[i * 3]].position; + drawnode->drawLine(Vec2(from.x, from.y), Vec2(to.x, to.y), Color::RED); } } } @@ -241,10 +241,10 @@ void SpritePolygonTest2::initSprites() auto offset = Vec2(0.15 * s.width, 0); auto filename = s_pathGrossini; - // Fix for issue #231 Rect have to be adapt to the 2.0/"ContentScaleFactor()" + // Fix for issue #231 Rect have to be adapt to the 2.0/"ContentScaleFactor()" auto a = 2.0 / Director::getInstance()->getContentScaleFactor(); Rect head = Rect(30 * a, 25 * a, 25 * a, 25 * a); - + // Sprite auto pinfo = AutoPolygon::generatePolygon(filename, head); _polygonSprite = Sprite::create(pinfo); @@ -474,7 +474,7 @@ void SpritePolygonTest5::loadDefaultSprites() drawNode->clear(); sprites[i]->addChild(drawNode); } - sprites[0]->setColor(Color3B::RED); + sprites[0]->setColor(Color32::RED); sprites[1]->setOpacity(100); sprites[2]->setTexture(Director::getInstance()->getTextureCache()->addImage("Images/grossinis_sister1.png")); sprites[3]->setTextureRect(Rect(0.0f, 0.0f, 100.0f, 30.0f)); @@ -901,8 +901,8 @@ SpritePolygonTestPerformance::SpritePolygonTestPerformance() addChild(_spritesAnchor); _totalSprites = Label::createWithTTF(TTFConfig("fonts/arial.ttf"), "sprites"); - _totalSprites->setColor(Color3B::YELLOW); - _totalSprites->enableOutline(Color4B::RED, 2); + _totalSprites->setColor(Color32::YELLOW); + _totalSprites->enableOutline(Color32::RED, 2); _totalSprites->setPosition(s.width / 2, s.height / 2); addChild(_totalSprites); diff --git a/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.h b/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.h index e56567ffeefa..4b9e7a4c6eeb 100644 --- a/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.h +++ b/tests/cpp-tests/Source/SpritePolygonTest/SpritePolygonTest.h @@ -25,7 +25,7 @@ #ifndef __cocos2d_tests__SpritePolygonTest__ # include "../BaseTest.h" -# include "ui/CocosGUI.h" +# include "axmol/ui/CocosGUI.h" DEFINE_TEST_SUITE(SpritePolygonTest); diff --git a/tests/cpp-tests/Source/SpriteTest/SpriteTest.cpp b/tests/cpp-tests/Source/SpriteTest/SpriteTest.cpp index e5f52e5d0d08..5f352266ab0e 100644 --- a/tests/cpp-tests/Source/SpriteTest/SpriteTest.cpp +++ b/tests/cpp-tests/Source/SpriteTest/SpriteTest.cpp @@ -33,7 +33,7 @@ #include "../testResource.h" #include "cocostudio/CocosStudioExtension.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; @@ -403,17 +403,17 @@ SpriteColorOpacityHSVHSL::SpriteColorOpacityHSVHSL() auto action_back = action->reverse(); auto fade = RepeatForever::create(Sequence::create(action, action_back, nullptr)); - auto col = HSV(0, 1, 1, 1).toColor3B(); + auto col = HSV(0, 1, 1, 1).toColor32(); auto tintred = TintBy::create(2, col.r, col.g, col.b); auto tintred_back = tintred->reverse(); auto red = RepeatForever::create(Sequence::create(tintred, tintred_back, nullptr)); - col = HSV(120, 1, 1, 1).toColor3B(); + col = HSV(120, 1, 1, 1).toColor32(); auto tintgreen = TintBy::create(2, col.r, col.g, col.b); auto tintgreen_back = tintgreen->reverse(); auto green = RepeatForever::create(Sequence::create(tintgreen, tintgreen_back, nullptr)); - col = HSV(240, 1, 1, 1).toColor3B(); + col = HSV(240, 1, 1, 1).toColor32(); auto tintblue = TintBy::create(2, col.r, col.g, col.b); auto tintblue_back = tintblue->reverse(); auto blue = RepeatForever::create(Sequence::create(tintblue, tintblue_back, nullptr)); @@ -427,17 +427,17 @@ SpriteColorOpacityHSVHSL::SpriteColorOpacityHSVHSL() action_back = action->reverse(); fade = RepeatForever::create(Sequence::create(action, action_back, nullptr)); - col = HSL(0, 1, .7, 1).toColor3B(); + col = HSL(0, 1, .7, 1).toColor32(); tintred = TintBy::create(2, col.r, col.g, col.b); tintred_back = tintred->reverse(); red = RepeatForever::create(Sequence::create(tintred, tintred_back, nullptr)); - col = HSL(120, 1, .7, 1).toColor3B(); + col = HSL(120, 1, .7, 1).toColor32(); tintgreen = TintBy::create(2, col.r, col.g, col.b); tintgreen_back = tintgreen->reverse(); green = RepeatForever::create(Sequence::create(tintgreen, tintgreen_back, nullptr)); - col = HSL(240, 1, .7, 1).toColor3B(); + col = HSL(240, 1, .7, 1).toColor32(); tintblue = TintBy::create(2, col.r, col.g, col.b); tintblue_back = tintblue->reverse(); blue = RepeatForever::create(Sequence::create(tintblue, tintblue_back, nullptr)); @@ -606,7 +606,7 @@ SpriteZOrder::SpriteZOrder() addChild(sprite, -1, kTagSprite1); sprite->setPosition(Vec2(s.width / 2, s.height / 2 - 20)); sprite->setScaleX(6); - sprite->setColor(Color3B::RED); + sprite->setColor(Color32::RED); schedule(AX_CALLBACK_1(SpriteZOrder::reorderSprite, this), 1, "reorder_key"); } @@ -673,7 +673,7 @@ SpriteBatchNodeZOrder::SpriteBatchNodeZOrder() batch->addChild(sprite, -1, kTagSprite1); sprite->setPosition(Vec2(s.width / 2, s.height / 2 - 20)); sprite->setScaleX(6); - sprite->setColor(Color3B::RED); + sprite->setColor(Color32::RED); schedule(AX_CALLBACK_1(SpriteBatchNodeZOrder::reorderSprite, this), 1, "reorder_key"); } @@ -1226,7 +1226,7 @@ SpriteWithoutVertexAnchorPoint::SpriteWithoutVertexAnchorPoint() addChild(sprite, i); auto lb = Label::createWithSystemFont("This is a text", "", 16); - lb->setColor(Color3B::WHITE); + lb->setColor(Color32::WHITE); sprite->addChild(lb, i); } } @@ -1283,7 +1283,7 @@ SpriteVertexAnchorPoint::SpriteVertexAnchorPoint() addChild(sprite, i); auto lb = Label::createWithSystemFont("This is a text", "", 16); - lb->setColor(Color3B::WHITE); + lb->setColor(Color32::WHITE); sprite->addChild(lb, i); } } @@ -3588,14 +3588,14 @@ SpriteNilTexture::SpriteNilTexture() sprite = Sprite::create(); sprite->setTextureRect(Rect(0, 0, 300, 300)); - sprite->setColor(Color3B::RED); + sprite->setColor(Color32::RED); sprite->setOpacity(128); sprite->setPosition(Vec2(3 * s.width / 4, s.height / 2)); addChild(sprite, 100); sprite = Sprite::create(); sprite->setTextureRect(Rect(0.0f, 0.0f, 300.0f, 300.0f)); - sprite->setColor(Color3B::BLUE); + sprite->setColor(Color32::BLUE); sprite->setOpacity(128); sprite->setPosition(Vec2(1 * s.width / 4, s.height / 2)); addChild(sprite, 100); @@ -3854,9 +3854,9 @@ SpriteBatchBug1217::SpriteBatchBug1217() auto s2 = Sprite::createWithTexture(bn->getTexture(), Rect(0.0f, 0.0f, 57.0f, 57.0f)); auto s3 = Sprite::createWithTexture(bn->getTexture(), Rect(0.0f, 0.0f, 57.0f, 57.0f)); - s1->setColor(Color3B(255, 0, 0)); - s2->setColor(Color3B(0, 255, 0)); - s3->setColor(Color3B(0, 0, 255)); + s1->setColor(Color32(255, 0, 0)); + s2->setColor(Color32(0, 255, 0)); + s3->setColor(Color32(0, 0, 255)); s1->setPosition(Vec2(20.0f, 200.0f)); s2->setPosition(Vec2(100.0f, 0.0f)); @@ -5908,7 +5908,7 @@ void Issue17119::update(float dt) SpriteWithImageDataTest1::SpriteWithImageDataTest1() { Size s = Director::getInstance()->getVisibleSize(); - + ax::Data imageData = FileUtils::getInstance()->getDataFromFile("Images/grossini.png"); Sprite* sprite = Sprite::create(imageData, "sprite_image_key_test_1"); @@ -5994,7 +5994,7 @@ void ZwoptexGenericTest::onEnter() SpriteFrameCache::getInstance()->addSpriteFramesWithFile("zwoptex/grossini.plist"); SpriteFrameCache::getInstance()->addSpriteFramesWithFile("zwoptex/grossini-generic.plist"); - auto layer1 = LayerColor::create(Color4B(255, 0, 0, 255), 85, 121); + auto layer1 = LayerColor::create(Color32(255, 0, 0, 255), 85, 121); layer1->setPosition(Vec2(s.width / 2 - 80 - (85.0f * 0.5f), s.height / 2 - (121.0f * 0.5f))); addChild(layer1); @@ -6006,7 +6006,7 @@ void ZwoptexGenericTest::onEnter() sprite1->setFlippedX(false); sprite1->setFlippedY(false); - auto layer2 = LayerColor::create(Color4B(255, 0, 0, 255), 85, 121); + auto layer2 = LayerColor::create(Color32(255, 0, 0, 255), 85, 121); layer2->setPosition(Vec2(s.width / 2 + 80 - (85.0f * 0.5f), s.height / 2 - (121.0f * 0.5f))); addChild(layer2); diff --git a/tests/cpp-tests/Source/SpriteTest/SpriteTest.h b/tests/cpp-tests/Source/SpriteTest/SpriteTest.h index 77599b840cbf..4dd9beeb91a2 100644 --- a/tests/cpp-tests/Source/SpriteTest/SpriteTest.h +++ b/tests/cpp-tests/Source/SpriteTest/SpriteTest.h @@ -26,7 +26,7 @@ #ifndef _SPRITE_TEST_H_ #define _SPRITE_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #include diff --git a/tests/cpp-tests/Source/TerrainTest/TerrainTest.h b/tests/cpp-tests/Source/TerrainTest/TerrainTest.h index bc77d0b23b7b..e079049f6daa 100644 --- a/tests/cpp-tests/Source/TerrainTest/TerrainTest.h +++ b/tests/cpp-tests/Source/TerrainTest/TerrainTest.h @@ -26,10 +26,10 @@ #include "../BaseTest.h" -#include "3d/MeshRenderer.h" -#include "3d/Terrain.h" -#include "2d/Camera.h" -#include "2d/Action.h" +#include "axmol/3d/MeshRenderer.h" +#include "axmol/3d/Terrain.h" +#include "axmol/2d/Camera.h" +#include "axmol/2d/Action.h" DEFINE_TEST_SUITE(TerrainTests); diff --git a/tests/cpp-tests/Source/TextInputTest/TextInputTest.cpp b/tests/cpp-tests/Source/TextInputTest/TextInputTest.cpp index 096fbd63f5d7..ac8644864bf6 100644 --- a/tests/cpp-tests/Source/TextInputTest/TextInputTest.cpp +++ b/tests/cpp-tests/Source/TextInputTest/TextInputTest.cpp @@ -285,7 +285,7 @@ bool TextFieldTTFActionTest::onTextFieldInsertText(TextFieldTTF* sender, const c // create a insert text sprite and do some action auto label = Label::createWithSystemFont(text, FONT_NAME, FONT_SIZE); this->addChild(label); - Color3B color(226, 121, 7); + Color32 color(226, 121, 7); label->setColor(color); // move the sprite from top to position @@ -427,4 +427,4 @@ void TextFieldTTSetCursorFromPoint::onEnter() #endif _trackNode = pTextField; -} \ No newline at end of file +} diff --git a/tests/cpp-tests/Source/Texture2dTest/Texture2dTest.cpp b/tests/cpp-tests/Source/Texture2dTest/Texture2dTest.cpp index a884247cc832..8032a2564a04 100644 --- a/tests/cpp-tests/Source/Texture2dTest/Texture2dTest.cpp +++ b/tests/cpp-tests/Source/Texture2dTest/Texture2dTest.cpp @@ -29,7 +29,7 @@ #include "Texture2dTest.h" #include "../testResource.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; @@ -125,7 +125,7 @@ void TextureDemo::onEnter() { TestCase::onEnter(); - auto col = LayerColor::create(Color4B(128, 128, 128, 255)); + auto col = LayerColor::create(Color32(128, 128, 128, 255)); addChild(col, -10); auto textureCache = Director::getInstance()->getTextureCache(); @@ -150,7 +150,7 @@ void TextureASTC::onEnter() TextureDemo::onEnter(); auto& s = getContentSize(); - _background = LayerColor::create(Color4B(15, 19, 42, 255), s.width, s.height); + _background = LayerColor::create(Color32(15, 19, 42, 255), s.width, s.height); _background->setIgnoreAnchorPointForPosition(false); _background->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -199,7 +199,7 @@ bool TextureETC1Alpha::init() return false; auto& canvasSize = getContentSize(); - _background = LayerColor::create(Color4B(15, 19, 42, 255), canvasSize.width, canvasSize.height); + _background = LayerColor::create(Color32(15, 19, 42, 255), canvasSize.width, canvasSize.height); _background->setIgnoreAnchorPointForPosition(false); _background->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -280,7 +280,7 @@ bool TextureETC2::init() return false; auto& canvasSize = getContentSize(); - _background = LayerColor::create(Color4B(15, 19, 42, 255), canvasSize.width, canvasSize.height); + _background = LayerColor::create(Color32(15, 19, 42, 255), canvasSize.width, canvasSize.height); _background->setIgnoreAnchorPointForPosition(false); _background->setAnchorPoint(Vec2::ANCHOR_MIDDLE); @@ -542,9 +542,7 @@ void TextureMipMap::onEnter() auto texture0 = Director::getInstance()->getTextureCache()->addImage("Images/grossini_dance_atlas.png"); texture0->generateMipmap(); - Texture2D::TexParams texParams = {backend::SamplerFilter::LINEAR_MIPMAP_LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::CLAMP_TO_EDGE, - backend::SamplerAddressMode::CLAMP_TO_EDGE}; + Texture2D::TexParams texParams{}; texture0->setTexParameters(texParams); auto texture1 = Director::getInstance()->getTextureCache()->addImage("Images/grossini_dance_atlas_nomipmap.png"); @@ -599,9 +597,7 @@ void TexturePVRMipMap::onEnter() addChild(imgMipMap); // support mipmap filtering - Texture2D::TexParams texParams = {backend::SamplerFilter::LINEAR_MIPMAP_LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::CLAMP_TO_EDGE, - backend::SamplerAddressMode::CLAMP_TO_EDGE}; + Texture2D::TexParams texParams{}; imgMipMap->getTexture()->setTexParameters(texParams); } @@ -647,9 +643,7 @@ void TexturePVRMipMap2::onEnter() addChild(imgMipMap); // support mipmap filtering - Texture2D::TexParams texParams = {backend::SamplerFilter::LINEAR_MIPMAP_LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::CLAMP_TO_EDGE, - backend::SamplerAddressMode::CLAMP_TO_EDGE}; + Texture2D::TexParams texParams{}; imgMipMap->getTexture()->setTexParameters(texParams); auto img = Sprite::create("Images/test_image.png"); @@ -1592,7 +1586,7 @@ void TexturePixelFormat::onEnter() auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(128, 128, 128, 255), s.width, s.height); + auto background = LayerColor::create(Color32(128, 128, 128, 255), s.width, s.height); addChild(background, -1); // RGBA 8888 image (32-bit) @@ -1636,7 +1630,7 @@ void TexturePixelFormat::onEnter() Director::getInstance()->getTextureCache()->removeTexture(sprite5->getTexture()); // A8 image (8-bit) - auto sprite6 = Sprite::create("Images/test-rgba1.png", PixelFormat::R8); // + auto sprite6 = Sprite::create("Images/test-rgba1.png", PixelFormat::R8); // sprite6->setPosition(Vec2(6 * s.width / 7, s.height / 2 - 32)); addChild(sprite6, 0); @@ -1694,7 +1688,7 @@ void TextureBlend::onEnter() cloud = Sprite::create("Images/test_blend.png"); addChild(cloud, i + 1, 200 + i); cloud->setPosition(Vec2(50 + 25 * i, 160)); - BlendFunc blendFunc2 = {backend::BlendFactor::ONE_MINUS_DST_COLOR, backend::BlendFactor::ZERO}; + BlendFunc blendFunc2 = {rhi::BlendFactor::ONE_MINUS_DST_COLOR, rhi::BlendFactor::ZERO}; cloud->setBlendFunc(blendFunc2); // UPPER sprites are using custom blending function @@ -1702,7 +1696,7 @@ void TextureBlend::onEnter() cloud = Sprite::create("Images/test_blend.png"); addChild(cloud, i + 1, 200 + i); cloud->setPosition(Vec2(50 + 25 * i, 320 - 80)); - BlendFunc blendFunc3 = {backend::BlendFactor::SRC_ALPHA, backend::BlendFactor::ONE}; + BlendFunc blendFunc3 = {rhi::BlendFactor::SRC_ALPHA, rhi::BlendFactor::ONE}; cloud->setBlendFunc(blendFunc3); // additive blending } } @@ -1820,9 +1814,7 @@ void TextureGlClamp::onEnter() auto sprite = Sprite::create("Images/pattern1.png", Rect(0, 0, 512, 256)); addChild(sprite, -1, kTagSprite1); sprite->setPosition(Vec2(size.width / 2, size.height / 2)); - Texture2D::TexParams texParams(backend::SamplerFilter::LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::CLAMP_TO_EDGE, - backend::SamplerAddressMode::CLAMP_TO_EDGE); + Texture2D::TexParams texParams{}; sprite->getTexture()->setTexParameters(texParams); auto rotate = RotateBy::create(4, 360); sprite->runAction(rotate); @@ -1858,9 +1850,8 @@ void TextureGlRepeat::onEnter() auto sprite = Sprite::create("Images/pattern1.png", Rect(0, 0, 4096, 4096)); addChild(sprite, -1, kTagSprite1); sprite->setPosition(Vec2(size.width / 2, size.height / 2)); - Texture2D::TexParams descriptor = {backend::SamplerFilter::LINEAR, backend::SamplerFilter::LINEAR, - backend::SamplerAddressMode::REPEAT, backend::SamplerAddressMode::REPEAT}; - sprite->getTexture()->setTexParameters(descriptor); + Texture2D::TexParams desc{.sAddressMode = rhi::SamplerAddressMode::REPEAT, .tAddressMode = rhi::SamplerAddressMode::REPEAT}; + sprite->getTexture()->setTexParameters(desc); auto rotate = RotateBy::create(4, 360); sprite->runAction(rotate); @@ -2193,7 +2184,7 @@ TexturePVRv3Premult::TexturePVRv3Premult() { auto size = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(128, 128, 128, 255), size.width, size.height); + auto background = LayerColor::create(Color32(128, 128, 128, 255), size.width, size.height); addChild(background, -1); // PVR premultiplied @@ -2361,7 +2352,7 @@ std::string TextureATITCInterpolated::subtitle() const return "ATITC RGBA Interpolated Alpha compressed texture test"; } -static void addImageToDemo(TextureDemo& demo, float x, float y, const char* path, backend::PixelFormat format) +static void addImageToDemo(TextureDemo& demo, float x, float y, const char* path, rhi::PixelFormat format) { auto sprite = Sprite::create(path, format); sprite->setPosition(Vec2(x, y)); @@ -2378,17 +2369,17 @@ void TextureConvertRGB888::onEnter() auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(255, 0, 0, 255), s.width, s.height); + auto background = LayerColor::create(Color32(255, 0, 0, 255), s.width, s.height); addChild(background, -1); const char* img = "Images/test_image_rgb888.png"; - addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA8); - addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB8); - addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGB565); - addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::R8); - addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RG8); - addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA4); - addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB5A1); + addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA8); + addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB8); + addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGB565); + addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::R8); + addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RG8); + addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA4); + addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB5A1); AXLOGD("{}\n", Director::getInstance()->getTextureCache()->getCachedTextureInfo()); } @@ -2409,17 +2400,17 @@ void TextureConvertRGBA8888::onEnter() auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(255, 0, 0, 255), s.width, s.height); + auto background = LayerColor::create(Color32(255, 0, 0, 255), s.width, s.height); addChild(background, -1); const char* img = "Images/test_image_rgba8888.png"; - addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA8); - addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB8); - addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGB565); - addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::R8); - addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RG8); - addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA4); - addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB5A1); + addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA8); + addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB8); + addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGB565); + addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::R8); + addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RG8); + addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA4); + addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB5A1); AXLOGD("{}\n", Director::getInstance()->getTextureCache()->getCachedTextureInfo()); } @@ -2440,17 +2431,17 @@ void TextureConvertL8::onEnter() auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(255, 0, 0, 255), s.width, s.height); + auto background = LayerColor::create(Color32(255, 0, 0, 255), s.width, s.height); addChild(background, -1); const char* img = "Images/test_image_i8.png"; - addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA8); - addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB8); - addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGB565); - addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::R8); - addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RG8); - addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA4); - addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB5A1); + addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA8); + addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB8); + addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGB565); + addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::R8); + addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RG8); + addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA4); + addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB5A1); AXLOGD("{}\n", Director::getInstance()->getTextureCache()->getCachedTextureInfo()); } @@ -2471,17 +2462,17 @@ void TextureConvertLA8::onEnter() auto s = Director::getInstance()->getWinSize(); - auto background = LayerColor::create(Color4B(255, 0, 0, 255), s.width, s.height); + auto background = LayerColor::create(Color32(255, 0, 0, 255), s.width, s.height); addChild(background, -1); const char* img = "Images/test_image_ai88.png"; - addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA8); - addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB8); - addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGB565); - addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::R8); - addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RG8); - addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, backend::PixelFormat::RGBA4); - addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, backend::PixelFormat::RGB5A1); + addImageToDemo(*this, 1 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA8); + addImageToDemo(*this, 2 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB8); + addImageToDemo(*this, 3 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGB565); + addImageToDemo(*this, 4 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::R8); + addImageToDemo(*this, 5 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RG8); + addImageToDemo(*this, 6 * s.width / 8, s.height / 2 + 32, img, rhi::PixelFormat::RGBA4); + addImageToDemo(*this, 7 * s.width / 8, s.height / 2 - 32, img, rhi::PixelFormat::RGB5A1); AXLOGD("{}\n", Director::getInstance()->getTextureCache()->getCachedTextureInfo()); } diff --git a/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.cpp b/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.cpp index bdfc8167f366..18b3467c14f4 100644 --- a/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.cpp +++ b/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.cpp @@ -24,7 +24,7 @@ #include "TextureCacheTest.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; diff --git a/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.h b/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.h index d20790cf902a..40ae96997def 100644 --- a/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.h +++ b/tests/cpp-tests/Source/TextureCacheTest/TextureCacheTest.h @@ -25,7 +25,7 @@ #ifndef _TEXTURECACHE_TEST_H_ #define _TEXTURECACHE_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" DEFINE_TEST_SUITE(TextureCacheTests); diff --git a/tests/cpp-tests/Source/TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h b/tests/cpp-tests/Source/TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h index c3aa040e7ba0..25eda6bb9b18 100644 --- a/tests/cpp-tests/Source/TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h +++ b/tests/cpp-tests/Source/TexturePackerEncryptionTest/TextureAtlasEncryptionTest.h @@ -25,7 +25,7 @@ #ifndef _TextureAtlasEncryption_TEST_H_ #define _TextureAtlasEncryption_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" #include diff --git a/tests/cpp-tests/Source/TileMapTest/TileMapTest2.cpp b/tests/cpp-tests/Source/TileMapTest/TileMapTest2.cpp index ad84f3221ed8..a87630c3baa0 100644 --- a/tests/cpp-tests/Source/TileMapTest/TileMapTest2.cpp +++ b/tests/cpp-tests/Source/TileMapTest/TileMapTest2.cpp @@ -25,8 +25,8 @@ #include "TileMapTest2.h" #include "../testResource.h" -#include "2d/FastTMXLayer.h" -#include "2d/FastTMXTiledMap.h" +#include "axmol/2d/FastTMXLayer.h" +#include "axmol/2d/FastTMXTiledMap.h" using namespace ax; @@ -186,7 +186,7 @@ void TileMapEditTestNew::updateMap(float dt) // over all your tiles in every frame. It's very expensive // for(int x=0; x < tilemap.tgaInfo->width; x++) { // for(int y=0; y < tilemap.tgaInfo->height; y++) { - // Color3B c =[tilemap tileAt:Size(x,y)); + // Color32 c =[tilemap tileAt:Size(x,y)); // if( c.r != 0 ) { // ////----AXLOGD("{},{} = {}", x,y,c.r); // } @@ -194,7 +194,7 @@ void TileMapEditTestNew::updateMap(float dt) // } // NEW since v0.7 - Color3B c = tilemap->getTileAt(Vec2(13, 21)); + Color32 c = tilemap->getTileAt(Vec2(13, 21)); c.r++; c.r %= 50; if (c.r == 0) @@ -221,7 +221,7 @@ TMXOrthoTestNew::TMXOrthoTestNew() // // it should not flicker. No artifacts should appear // - // auto color = LayerColor::create( Color4B(64,64,64,255) ); + // auto color = LayerColor::create( Color32(64,64,64,255) ); // addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/orthogonal-test2.tmx"); @@ -493,7 +493,7 @@ std::string TMXReadWriteTestNew::title() const //------------------------------------------------------------------ TMXHexTestNew::TMXHexTestNew() { - auto color = LayerColor::create(Color4B(64, 64, 64, 255)); + auto color = LayerColor::create(Color32(64, 64, 64, 255)); addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/hexa-test.tmx"); @@ -515,7 +515,7 @@ std::string TMXHexTestNew::title() const //------------------------------------------------------------------ TMXIsoTestNew::TMXIsoTestNew() { - auto color = LayerColor::create(Color4B(64, 64, 64, 255)); + auto color = LayerColor::create(Color32(64, 64, 64, 255)); addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/iso-test.tmx"); @@ -539,7 +539,7 @@ std::string TMXIsoTestNew::title() const //------------------------------------------------------------------ TMXIsoTest1New::TMXIsoTest1New() { - auto color = LayerColor::create(Color4B(64, 64, 64, 255)); + auto color = LayerColor::create(Color32(64, 64, 64, 255)); addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/iso-test1.tmx"); @@ -563,7 +563,7 @@ std::string TMXIsoTest1New::title() const //------------------------------------------------------------------ TMXIsoTest2New::TMXIsoTest2New() { - auto color = LayerColor::create(Color4B(64, 64, 64, 255)); + auto color = LayerColor::create(Color32(64, 64, 64, 255)); addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/iso-test2.tmx"); @@ -590,7 +590,7 @@ std::string TMXIsoTest2New::title() const //------------------------------------------------------------------ TMXUncompressedTestNew::TMXUncompressedTestNew() { - auto color = LayerColor::create(Color4B(64, 64, 64, 255)); + auto color = LayerColor::create(Color32(64, 64, 64, 255)); addChild(color, -1); auto map = ax::FastTMXTiledMap::create("TileMaps/iso-test2-uncompressed.tmx"); @@ -659,7 +659,7 @@ TMXOrthoObjectsTestNew::TMXOrthoObjectsTestNew() AXLOGD("{}", objectsVal.getDescription()); auto drawNode = DrawNode::create(); - Color4F color(1.0, 1.0, 1.0, 1.0); + Color color(1.0, 1.0, 1.0, 1.0); for (auto&& obj : objects) { ValueMap& dict = obj.asValueMap(); @@ -709,7 +709,7 @@ TMXIsoObjectsTestNew::TMXIsoObjectsTestNew() AXLOGD("{}", objectsVal.getDescription()); auto drawNode = DrawNode::create(); - Color4F color(1.0, 1.0, 1.0, 1.0); + Color color(1.0, 1.0, 1.0, 1.0); for (auto&& obj : objects) { ValueMap& dict = obj.asValueMap(); @@ -1338,7 +1338,7 @@ TMXGIDObjectsTestNew::TMXGIDObjectsTestNew() AXLOGD("----> Iterating over all the group objects"); auto drawNode = DrawNode::create(); - Color4F color(1.0, 1.0, 1.0, 1.0); + Color color(1.0, 1.0, 1.0, 1.0); auto group = map->getObjectGroup("Object Layer 1"); auto objects = group->getObjects(); for (auto&& obj : objects) diff --git a/tests/cpp-tests/Source/TouchesTest/Ball.h b/tests/cpp-tests/Source/TouchesTest/Ball.h index 8132e7942229..600fae53d833 100644 --- a/tests/cpp-tests/Source/TouchesTest/Ball.h +++ b/tests/cpp-tests/Source/TouchesTest/Ball.h @@ -25,7 +25,7 @@ #ifndef _BALL_H_ #define _BALL_H_ -#include "axmol.h" +#include "axmol/axmol.h" class Paddle; diff --git a/tests/cpp-tests/Source/TouchesTest/Paddle.h b/tests/cpp-tests/Source/TouchesTest/Paddle.h index d0c54d35741d..f0c73605b256 100644 --- a/tests/cpp-tests/Source/TouchesTest/Paddle.h +++ b/tests/cpp-tests/Source/TouchesTest/Paddle.h @@ -25,7 +25,7 @@ #ifndef _PADDLE_H_ #define _PADDLE_H_ -#include "axmol.h" +#include "axmol/axmol.h" typedef enum tagPaddleState { diff --git a/tests/cpp-tests/Source/TouchesTest/TouchesTest.cpp b/tests/cpp-tests/Source/TouchesTest/TouchesTest.cpp index 061771934249..735b03d6b7af 100644 --- a/tests/cpp-tests/Source/TouchesTest/TouchesTest.cpp +++ b/tests/cpp-tests/Source/TouchesTest/TouchesTest.cpp @@ -27,7 +27,7 @@ #include "Paddle.h" #include "../testResource.h" -#include "base/format.h" +#include "axmol/base/format.h" using namespace ax; diff --git a/tests/cpp-tests/Source/TransitionsTest/TransitionsTest.cpp b/tests/cpp-tests/Source/TransitionsTest/TransitionsTest.cpp index 86d74f5966a3..ccdf3dfd3bf8 100644 --- a/tests/cpp-tests/Source/TransitionsTest/TransitionsTest.cpp +++ b/tests/cpp-tests/Source/TransitionsTest/TransitionsTest.cpp @@ -34,7 +34,7 @@ using namespace ax; class FadeWhiteTransition : public TransitionFade { public: - static TransitionScene* create(float t, Scene* s) { return TransitionFade::create(t, s, Color3B::WHITE); } + static TransitionScene* create(float t, Scene* s) { return TransitionFade::create(t, s, Color32::WHITE); } }; class FlipXLeftOver : public TransitionFlipX @@ -278,11 +278,11 @@ TestLayer1::TestLayer1(std::string_view transitionName) auto title = Label::createWithTTF(transitionName, "fonts/Thonburi.ttf", 32); addChild(title); - title->setColor(Color3B(255, 32, 32)); + title->setColor(Color32(255, 32, 32)); title->setPosition(Vec2(x / 2, y - 100)); auto label = Label::createWithTTF("SCENE 1", "fonts/Marker Felt.ttf", 38); - label->setColor(Color3B(16, 16, 255)); + label->setColor(Color32(16, 16, 255)); label->setPosition(Vec2(x / 2, y / 2)); addChild(label); @@ -348,11 +348,11 @@ TestLayer2::TestLayer2(std::string_view transitionName) auto title = Label::createWithTTF(transitionName, "fonts/Thonburi.ttf", 32); addChild(title); - title->setColor(Color3B(255, 32, 32)); + title->setColor(Color32(255, 32, 32)); title->setPosition(Vec2(x / 2, y - 100)); auto label = Label::createWithTTF("SCENE 2", "fonts/Marker Felt.ttf", 38); - label->setColor(Color3B(16, 16, 255)); + label->setColor(Color32(16, 16, 255)); label->setPosition(Vec2(x / 2, y / 2)); addChild(label); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp index cbddeca41276..cf563e25b23e 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIButtonTest/UIButtonTest.cpp @@ -69,7 +69,7 @@ bool UIButtonTest::init() // Add the alert Text* alert = Text::create("Button", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -176,7 +176,7 @@ bool UIButtonTest_Scale9::init() // Add the alert Text* alert = Text::create("Button scale9 render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -259,7 +259,7 @@ bool UIButtonTest_Scale9_State_Change::init() // Add the alert Text* alert = Text::create("Button scale9 render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -344,7 +344,7 @@ bool UIButtonTest_PressedAction::init() // Add the alert Text* alert = Text::create("Button Pressed Action", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -355,7 +355,7 @@ bool UIButtonTest_PressedAction::init() Button* button = Button::create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png"); button->setPressedActionEnabled(true); button->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); - button->setColor(Color3B::GREEN); + button->setColor(Color32::GREEN); button->setOpacity(30); button->addTouchEventListener(AX_CALLBACK_2(UIButtonTest_PressedAction::touchEvent, this)); button->setName("button"); @@ -422,7 +422,7 @@ bool UIButtonTest_Title::init() // Add the alert Text* alert = Text::create("Button with title, title should be flipped!", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -432,8 +432,8 @@ bool UIButtonTest_Title::init() Button* button = Button::create("cocosui/backtotoppressed.png", "cocosui/backtotopnormal.png"); button->setTitleText("Title Button!"); button->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); - button->setTitleColor(Color3B::YELLOW); - AXASSERT(button->getTitleColor() == Color3B::YELLOW, "Button setTitleColor & getTitleColor not match!"); + button->setTitleColor(Color32::YELLOW); + AXASSERT(button->getTitleColor() == Color32::YELLOW, "Button setTitleColor & getTitleColor not match!"); button->addTouchEventListener(AX_CALLBACK_2(UIButtonTest_Title::touchEvent, this)); _uiLayer->addChild(button); button->setFlippedX(true); @@ -444,7 +444,7 @@ bool UIButtonTest_Title::init() TextBMFont* text = TextBMFont::create("BMFont", "cocosui/bitmapFontTest2.fnt"); text->setPosition(button->getPosition() + Vec2(button->getContentSize().width / 2 + 50, 0.0f)); - text->setColor(Color3B::YELLOW); + text->setColor(Color32::YELLOW); text->setOpacity(50); text->setName("text"); @@ -520,7 +520,7 @@ bool UIButtonTestRemoveSelf::init() // Add the alert Text* alert = Text::create("Remove Self in the Button's Callback shouldn't cause crash!", "fonts/Marker Felt.ttf", 10); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.75f)); @@ -529,7 +529,7 @@ bool UIButtonTestRemoveSelf::init() Layout* layout = Layout::create(); layout->setContentSize(widgetSize * 0.6f); - layout->setBackGroundColor(Color3B::GREEN); + layout->setBackGroundColor(Color32::GREEN); layout->setBackGroundColorType(Layout::BackGroundColorType::SOLID); layout->setBackGroundColorOpacity(100); layout->setPosition(Size(widgetSize.width / 2, widgetSize.height / 2)); @@ -803,8 +803,8 @@ bool UIButtonTitleEffectTest::init() button->setScale(2.0f); button->setPressedActionEnabled(true); Label* title = button->getTitleRenderer(); - button->setTitleColor(Color3B::RED); - title->enableShadow(Color4B::BLACK, Size(2, -2)); + button->setTitleColor(Color32::RED); + title->enableShadow(Color32::BLACK, Size(2, -2)); _uiLayer->addChild(button); @@ -813,7 +813,7 @@ bool UIButtonTitleEffectTest::init() button2->setPositionNormalized(Vec2(0.8f, 0.5f)); button2->setTitleText("PLAY GAME"); auto title2 = button2->getTitleRenderer(); - title2->enableOutline(Color4B::GREEN, 3); + title2->enableOutline(Color32::GREEN, 3); _uiLayer->addChild(button2); return true; @@ -883,7 +883,7 @@ bool UIButtonNormalDefaultTest::init() // Add the alert Text* alert = Text::create("Button should scale when clicked", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -930,7 +930,7 @@ bool UIButtonDisableDefaultTest::init() // Add the alert Text* alert = Text::create("Left button will turn normal when clicked", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -983,7 +983,7 @@ bool UIButtonCloneTest::init() // Add the alert Text* alert = Text::create("This test case shouldn't trigger the Assertion!", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -1039,7 +1039,7 @@ bool Issue12249::init() // Add the alert Text* alert = Text::create("This test case two buttons should seem to be same!", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.0f)); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp index 50bd5e5b6373..49a8b684154e 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UICheckBoxTest/UICheckBoxTest.cpp @@ -53,7 +53,7 @@ bool UICheckBoxTest::init() // Add the alert Text* alert = Text::create("CheckBox", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -134,7 +134,7 @@ bool UICheckBoxDefaultBehaviorTest::init() // Add the alert Text* alert = Text::create("Only left two and the last checkbox can be clicked!", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -190,7 +190,7 @@ bool UICheckBoxCopyTest::init() // Add the alert Text* alert = Text::create("Two checkbox are identical.", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIEditBoxTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIEditBoxTest.cpp index 7719ea22dfa0..ec63e9a20a2d 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIEditBoxTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIEditBoxTest.cpp @@ -64,9 +64,9 @@ bool UIEditBoxTest::init() _editName = ui::EditBox::create(editBoxSize + Size(0, 40), ui::Scale9Sprite::create(pNormalSprite)); _editName->setPosition( Vec2(visibleOrigin.x + visibleSize.width / 2 - 50, visibleOrigin.y + visibleSize.height * 3 / 4)); - _editName->setFontColor(Color3B::RED); + _editName->setFontColor(Color32::RED); _editName->setPlaceHolder("Name:"); - _editName->setPlaceholderFontColor(Color3B::WHITE); + _editName->setPlaceholderFontColor(Color32::WHITE); _editName->setMaxLength(8); _editName->setFontSize((int)editBoxSize.height / 2); _editName->setText("v👐👊💝"); @@ -87,7 +87,7 @@ bool UIEditBoxTest::init() ui::EditBox::create(Size(editBoxSize.width, editBoxSize.height + 20), "extensions/orange_edit.png"); _editPassword->setPosition( Vec2(visibleOrigin.x + visibleSize.width / 2 - 50, visibleOrigin.y + visibleSize.height / 2)); - _editPassword->setFontColor(Color3B::GREEN); + _editPassword->setFontColor(Color32::GREEN); _editPassword->setPlaceHolder("Password:"); _editPassword->setMaxLength(6); _editPassword->setInputFlag(ui::EditBox::InputFlag::PASSWORD); @@ -198,9 +198,9 @@ bool UIEditBoxTestToggleVisibility::init() _editName = ui::EditBox::create(editBoxSize + Size(0, 40), ui::Scale9Sprite::create(pNormalSprite)); _editName->setPosition( Vec2(visibleOrigin.x + visibleSize.width / 2 - 50, visibleOrigin.y + visibleSize.height * 3 / 4)); - _editName->setFontColor(Color3B::RED); + _editName->setFontColor(Color32::RED); _editName->setPlaceHolder("Name:"); - _editName->setPlaceholderFontColor(Color3B::WHITE); + _editName->setPlaceholderFontColor(Color32::WHITE); _editName->setMaxLength(8); _editName->setFontSize((int)editBoxSize.height / 2); _editName->setText("v👐👊💝"); @@ -220,7 +220,7 @@ bool UIEditBoxTestToggleVisibility::init() _editPassword = ui::EditBox::create(editBoxSize, "extensions/orange_edit.png"); _editPassword->setPosition( Vec2(visibleOrigin.x + visibleSize.width / 2 - 50, visibleOrigin.y + visibleSize.height / 2)); - _editPassword->setFontColor(Color3B::GREEN); + _editPassword->setFontColor(Color32::GREEN); _editPassword->setPlaceHolder("Password:"); _editPassword->setMaxLength(6); _editPassword->setInputFlag(ui::EditBox::InputFlag::PASSWORD); @@ -317,9 +317,9 @@ bool UIEditBoxTestTextHorizontalAlignment::init() ui::EditBox* editbox = ui::EditBox::create(editBoxSize + Size(0, 40), ui::Scale9Sprite::create("extensions/green_edit.png")); editbox->setPosition(Vec2(visibleOrigin.x + visibleSize.width / 2 - 50, (float)position_y)); - editbox->setFontColor(Color3B::RED); + editbox->setFontColor(Color32::RED); editbox->setPlaceHolder(text.data()); - editbox->setPlaceholderFontColor(Color3B::WHITE); + editbox->setPlaceholderFontColor(Color32::WHITE); editbox->setPlaceholderFontSize((int)editBoxSize.height / 2); editbox->setFontSize((int)editBoxSize.height / 2); editbox->setText(text.data()); @@ -351,9 +351,9 @@ bool UIEditBoxTestPressedAndDisabled::init() ui::EditBox* editbox = ui::EditBox::create(editBoxSize + Size(0, 40), "extensions/yellow_edit.png", "extensions/orange_edit.png"); editbox->setPosition(Vec2(visibleOrigin.x + visibleSize.width / 2, visibleOrigin.y + visibleSize.height * 3 / 4)); - editbox->setFontColor(Color3B::GREEN); + editbox->setFontColor(Color32::GREEN); editbox->setPlaceHolder("Test Pressed Image"); - editbox->setPlaceholderFontColor(Color3B::WHITE); + editbox->setPlaceholderFontColor(Color32::WHITE); editbox->setPlaceholderFontSize((int)editBoxSize.height / 2); editbox->setFontSize((int)editBoxSize.height / 2); editbox->setReturnType(ui::EditBox::KeyboardReturnType::DONE); @@ -362,9 +362,9 @@ bool UIEditBoxTestPressedAndDisabled::init() editbox = ui::EditBox::create(editBoxSize + Size(0, 40), "extensions/yellow_edit.png", "extensions/orange_edit.png", "extensions/green_edit.png"); editbox->setPosition(Vec2(visibleOrigin.x + visibleSize.width / 2, visibleOrigin.y + visibleSize.height / 2)); - editbox->setFontColor(Color3B::GREEN); + editbox->setFontColor(Color32::GREEN); editbox->setPlaceHolder("Test Disabled Image - green"); - editbox->setPlaceholderFontColor(Color3B::WHITE); + editbox->setPlaceholderFontColor(Color32::WHITE); editbox->setPlaceholderFontSize((int)editBoxSize.height / 2); editbox->setFontSize((int)editBoxSize.height / 2); editbox->setReturnType(ui::EditBox::KeyboardReturnType::DONE); @@ -373,9 +373,9 @@ bool UIEditBoxTestPressedAndDisabled::init() editbox = ui::EditBox::create(editBoxSize + Size(0, 40), "extensions/yellow_edit.png"); editbox->setPosition(Vec2(visibleOrigin.x + visibleSize.width / 2, visibleOrigin.y + visibleSize.height / 4)); - editbox->setFontColor(Color3B::GREEN); + editbox->setFontColor(Color32::GREEN); editbox->setPlaceHolder("Disabled Gray effect"); - editbox->setPlaceholderFontColor(Color3B::WHITE); + editbox->setPlaceholderFontColor(Color32::WHITE); editbox->setPlaceholderFontSize((int)editBoxSize.height / 2); editbox->setFontSize((int)editBoxSize.height / 2); editbox->setReturnType(ui::EditBox::KeyboardReturnType::DONE); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp index 7409ad36a17e..0d378401830d 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIFocusTest/UIFocusTest.cpp @@ -93,7 +93,7 @@ bool UIFocusTestBase::init() _toggleButton = Button::create("cocosui/switch-mask.png"); _toggleButton->setTitleText("Toggle Loop"); _toggleButton->setPosition(Vec2(60.0f, winSize.height - 50)); - _toggleButton->setTitleColor(Color3B::RED); + _toggleButton->setTitleColor(Color32::RED); _toggleButton->setFocusEnabled(false); this->addChild(_toggleButton); @@ -111,12 +111,12 @@ void UIFocusTestBase::onImageViewClicked(ax::Object* ref, Widget::TouchEventType if (w->isFocusEnabled()) { w->setFocusEnabled(false); - w->setColor(Color3B::YELLOW); + w->setColor(Color32::YELLOW); } else { w->setFocusEnabled(true); - w->setColor(Color3B::WHITE); + w->setColor(Color32::WHITE); } } } @@ -153,12 +153,12 @@ void UIFocusTestBase::onFocusChanged(ax::ui::Widget* widgetLostFocus, ax::ui::Wi { if (widgetGetFocus && widgetGetFocus->isFocusEnabled()) { - widgetGetFocus->setColor(Color3B::RED); + widgetGetFocus->setColor(Color32::RED); } if (widgetLostFocus && widgetLostFocus->isFocusEnabled()) { - widgetLostFocus->setColor(Color3B::WHITE); + widgetLostFocus->setColor(Color32::WHITE); } if (widgetLostFocus && widgetGetFocus) @@ -201,7 +201,7 @@ bool UIFocusTestHorizontal::init() _loopText = Text::create("loop enabled", "Arial", 20); _loopText->setPosition(Vec2(winSize.width / 2, winSize.height - 50)); - _loopText->setColor(Color3B::GREEN); + _loopText->setColor(Color32::GREEN); this->addChild(_loopText); _toggleButton->addTouchEventListener(AX_CALLBACK_2(UIFocusTestHorizontal::toggleFocusLoop, this)); @@ -261,7 +261,7 @@ bool UIFocusTestVertical::init() _loopText = Text::create("loop enabled", "Arial", 20); _loopText->setPosition(Vec2(winSize.width / 2, winSize.height - 50)); - _loopText->setColor(Color3B::GREEN); + _loopText->setColor(Color32::GREEN); this->addChild(_loopText); _toggleButton->addTouchEventListener(AX_CALLBACK_2(UIFocusTestVertical::toggleFocusLoop, this)); @@ -357,7 +357,7 @@ bool UIFocusTestNestedLayout1::init() _loopText = Text::create("loop enabled", "Arial", 20); _loopText->setPosition(Vec2(winSize.width / 2, winSize.height - 50)); - _loopText->setColor(Color3B::GREEN); + _loopText->setColor(Color32::GREEN); this->addChild(_loopText); _toggleButton->addTouchEventListener(AX_CALLBACK_2(UIFocusTestNestedLayout1::toggleFocusLoop, this)); @@ -453,7 +453,7 @@ bool UIFocusTestNestedLayout2::init() _loopText = Text::create("loop enabled", "Arial", 20); _loopText->setPosition(Vec2(winSize.width / 2, winSize.height - 50)); - _loopText->setColor(Color3B::GREEN); + _loopText->setColor(Color32::GREEN); this->addChild(_loopText); _toggleButton->addTouchEventListener(AX_CALLBACK_2(UIFocusTestNestedLayout2::toggleFocusLoop, this)); @@ -554,7 +554,7 @@ bool UIFocusTestNestedLayout3::init() _loopText = Text::create("loop enabled", "Arial", 20); _loopText->setPosition(Vec2(winSize.width / 2, winSize.height - 50)); - _loopText->setColor(Color3B::GREEN); + _loopText->setColor(Color32::GREEN); this->addChild(_loopText); _toggleButton->addTouchEventListener(AX_CALLBACK_2(UIFocusTestNestedLayout3::toggleFocusLoop, this)); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp index 97e797078fea..7fe0f0eda0e8 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIImageViewTest/UIImageViewTest.cpp @@ -46,7 +46,7 @@ bool UIImageViewTest::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("ImageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); @@ -89,7 +89,7 @@ bool UIImageViewTest_Scale9::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("ImageView scale9 render", "fonts/Marker Felt.ttf", 26); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.125f)); @@ -121,7 +121,7 @@ bool UIImageViewTest_Scale9_State_Change::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("Click The Image", "fonts/Marker Felt.ttf", 26); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.125f)); @@ -164,14 +164,14 @@ bool UIImageViewTest_ContentSize::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("ImageView ContentSize Change", "fonts/Marker Felt.ttf", 26); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.125f)); _uiLayer->addChild(alert); Text* status = Text::create("child ImageView position percent", "fonts/Marker Felt.ttf", 16); - status->setColor(Color3B::RED); + status->setColor(Color32::RED); status->setPosition(Vec2(widgetSize.width / 2, widgetSize.height / 2 + 80)); _uiLayer->addChild(status, 20); @@ -231,7 +231,7 @@ bool UIImageViewFlipTest::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("ImageView flip test", "fonts/Marker Felt.ttf", 26); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.125f)); @@ -281,7 +281,7 @@ bool UIImageViewIssue12249Test::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("UIImageViewIssue12249Test", "fonts/Marker Felt.ttf", 26); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.125f)); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp index 0e4ca518e0fb..77665425674e 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILayoutTest/UILayoutTest.cpp @@ -62,7 +62,7 @@ bool UILayoutTest::init() // Add the alert Text* alert = Text::create("Layout", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); @@ -120,7 +120,7 @@ bool UILayoutTest_Color::init() // Add the alert Text* alert = Text::create("Layout color render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); @@ -133,7 +133,7 @@ bool UILayoutTest_Color::init() // Create the layout with color render Layout* layout = Layout::create(); layout->setBackGroundColorType(Layout::BackGroundColorType::SOLID); - layout->setBackGroundColor(Color3B(128, 128, 128)); + layout->setBackGroundColor(Color32(128, 128, 128)); layout->setContentSize(Size(280, 150)); Size backgroundSize = background->getContentSize(); layout->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + @@ -180,7 +180,7 @@ bool UILayoutTest_Gradient::init() // Add the alert Text* alert = Text::create("Layout gradient render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); @@ -193,7 +193,7 @@ bool UILayoutTest_Gradient::init() // Create the layout with gradient render Layout* layout = Layout::create(); layout->setBackGroundColorType(Layout::BackGroundColorType::GRADIENT); - layout->setBackGroundColor(Color3B(64, 64, 64), Color3B(192, 192, 192)); + layout->setBackGroundColor(Color32(64, 64, 64), Color32(192, 192, 192)); layout->setContentSize(Size(280, 150)); Size backgroundSize = background->getContentSize(); layout->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + @@ -240,7 +240,7 @@ bool UILayoutTest_BackGroundImage::init() // Add the alert Text* alert = Text::create("Layout background image", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -316,7 +316,7 @@ bool UILayoutTest_BackGroundImage_Scale9::init() // Add the alert Text* alert = Text::create("Layout background image scale9", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -374,7 +374,7 @@ bool UILayoutTest_Layout_Linear_Vertical::init() // Add the alert Text* alert = Text::create("Layout Linear Vertical", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); @@ -442,7 +442,7 @@ bool UILayoutTest_Layout_Linear_Horizontal::init() // Add the alert Text* alert = Text::create("Layout Linear Horizontal", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -510,7 +510,7 @@ bool UILayoutTest_Layout_Linear_CenterVertical::init() // Add the alert Text* alert = Text::create("Layout Linear Center Vertical", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); @@ -568,7 +568,7 @@ bool UILayoutTest_Layout_Linear_CenterHorizontal::init() // Add the alert Text* alert = Text::create("Layout Linear Center Horizontal", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -626,7 +626,7 @@ bool UILayoutTest_Layout_Relative_Align_Parent::init() // Add the alert Text* alert = Text::create("Layout Relative Align Parent", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -640,7 +640,7 @@ bool UILayoutTest_Layout_Relative_Align_Parent::init() layout->setLayoutType(Layout::Type::RELATIVE); layout->setContentSize(Size(280, 150)); layout->setBackGroundColorType(Layout::BackGroundColorType::SOLID); - layout->setBackGroundColor(Color3B::GREEN); + layout->setBackGroundColor(Color32::GREEN); Size backgroundSize = background->getContentSize(); layout->setPosition(Vec2((widgetSize.width - backgroundSize.width) / 2.0f + (backgroundSize.width - layout->getContentSize().width) / 2.0f, @@ -749,7 +749,7 @@ bool UILayoutTest_Layout_Relative_Location::init() // Add the alert Text* alert = Text::create("Layout Relative Location", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -834,7 +834,7 @@ bool UILayoutTest_Layout_Scaled_Widget::init() // Add the alert Text* alert = Text::create("Layout Scaled Widget", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5f)); _uiLayer->addChild(alert); @@ -879,7 +879,7 @@ bool UILayoutComponentTest::init() Size widgetSize = _widget->getContentSize(); _baseLayer = LayerColor::create(); - _baseLayer->setColor(Color3B(50, 100, 0)); + _baseLayer->setColor(Color32(50, 100, 0)); _baseLayer->setOpacity(100); _baseLayer->setContentSize(Size(200, 200)); _uiLayer->addChild(_baseLayer); @@ -1037,7 +1037,7 @@ bool UILayoutTest_Issue19890::init() _uiLayer->addChild(label); Text* alert = Text::create("3 panels should be completely visible", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -1048,7 +1048,7 @@ bool UILayoutTest_Issue19890::init() const Size backgroundSize = background->getContentSize(); auto panel = ui::Layout::create(); - panel->setBackGroundColor(Color3B::RED); + panel->setBackGroundColor(Color32::RED); panel->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID); panel->setClippingType(ui::Layout::ClippingType::SCISSOR); panel->setPosition(backgroundSize / 2); @@ -1058,7 +1058,7 @@ bool UILayoutTest_Issue19890::init() background->addChild(panel); auto panel2 = ui::Layout::create(); - panel2->setBackGroundColor(Color3B::BLUE); + panel2->setBackGroundColor(Color32::BLUE); panel2->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID); panel2->setClippingType(ui::Layout::ClippingType::SCISSOR); panel2->setPosition(panel->getContentSize() / 2); @@ -1068,7 +1068,7 @@ bool UILayoutTest_Issue19890::init() panel->addChild(panel2); auto panel3 = ui::Layout::create(); - panel3->setBackGroundColor(Color3B::GREEN); + panel3->setBackGroundColor(Color32::GREEN); panel3->setBackGroundColorType(ui::Layout::BackGroundColorType::SOLID); panel3->setClippingType(ui::Layout::ClippingType::SCISSOR); panel3->setPosition(panel2->getContentSize() / 2); @@ -1088,7 +1088,7 @@ bool UILayout_Clipping_Test::init() // Add the alert Text* alert = Text::create("Left & Right must look same", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.cpp index 727e2777f84b..fa6153dd1818 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.cpp @@ -64,7 +64,7 @@ bool UIListViewTest_Vertical::init() _uiLayer->addChild(_displayValueLabel); Text* alert = Text::create("ListView vertical", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -314,7 +314,7 @@ bool UIListViewTest_Horizontal::init() _uiLayer->addChild(_displayValueLabel); Text* alert = Text::create("ListView horizontal", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -497,7 +497,7 @@ bool Issue12692::init() Text* alert = Text::create("ListView in ListView enable Scissor Clipping", "fonts/Marker Felt.ttf", 20); alert->setName("Text Alert"); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -589,7 +589,7 @@ bool Issue8316::init() _uiLayer->addChild(label); Text* alert = Text::create("Can not scroll list view", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -680,12 +680,12 @@ bool UIListViewTest_ScrollToItem::init() if (getListViewDirection() == ScrollView::Direction::HORIZONTAL) { float halfY = 110; - pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color(0, 0, 0, 1), 2.0f); } else { float halfX = 150; - pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color(0, 0, 0, 1), 2.0f); } _uiLayer->addChild(pNode); } @@ -751,12 +751,12 @@ bool UIListViewTest_Magnetic::init() if (getListViewDirection() == ScrollView::Direction::HORIZONTAL) { float halfY = 110; - pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color(0, 0, 0, 1), 2.0f); } else { float halfX = 150; - pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color(0, 0, 0, 1), 2.0f); } _uiLayer->addChild(pNode); } @@ -908,12 +908,12 @@ bool UIListViewTest_Padding::init() if (getListViewDirection() == ScrollView::Direction::HORIZONTAL) { float halfY = 110; - pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x, center.y - halfY), Vec2(center.x, center.y + halfY), Color(0, 0, 0, 1), 2.0f); } else { float halfX = 150; - pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color4F(0, 0, 0, 1), 2.0f); + pNode->drawLine(Vec2(center.x - halfX, center.y), Vec2(center.x + halfX, center.y), Color(0, 0, 0, 1), 2.0f); } _uiLayer->addChild(pNode); } diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.h b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.h index 78a6de2100c2..795e6ab2cc02 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.h +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIListViewTest/UIListViewTest.h @@ -27,7 +27,7 @@ #define __TestCpp__UIListViewTest__ #include "../UIScene.h" -#include "ui/UIScrollView.h" +#include "axmol/ui/UIScrollView.h" DEFINE_TEST_SUITE(UIListViewTests); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILoadingBarTest/UILoadingBarTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILoadingBarTest/UILoadingBarTest.cpp index 0c8c5b08f87f..79bf13bf31fd 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILoadingBarTest/UILoadingBarTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UILoadingBarTest/UILoadingBarTest.cpp @@ -58,7 +58,7 @@ bool UILoadingBarTest_Left::init() // Add the alert Text* alert = Text::create("Test LoadingBar Change Direction", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -151,7 +151,7 @@ bool UILoadingBarTest_Right::init() // Add the alert Text* alert = Text::create("LoadingBar right", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -201,7 +201,7 @@ bool UILoadingBarTest_Left_Scale9::init() // Add the alert Text* alert = Text::create("LoadingBar left scale9 render", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.7f)); _uiLayer->addChild(alert); @@ -253,7 +253,7 @@ bool UILoadingBarTest_Right_Scale9::init() // Add the alert Text* alert = Text::create("LoadingBar right scale9 render", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.7f)); _uiLayer->addChild(alert); @@ -301,7 +301,7 @@ bool UILoadingBarTest_Scale9_State_Change::init() // Add the alert Text* alert = Text::create("LoadingBar right scale9 render", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.7f)); _uiLayer->addChild(alert); @@ -353,7 +353,7 @@ bool UILoadingBarReloadTexture::init() // Add the alert Text* alert = Text::create("Click button to Toggle Scale9 and switch Texture.", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 2.7f)); _uiLayer->addChild(alert); @@ -434,7 +434,7 @@ bool UILoadingBarIssue12249::init() // Add the alert Text* alert = Text::create("Test LoadingBar Change Direction", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -515,7 +515,7 @@ bool UILoadingBarTest_Direction::init() // Add the alert Text* alert = Text::create("Test LoadingBar Change Direction", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp index 325727f131a9..e14eb750ac0e 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIPageViewTest/UIPageViewTest.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "UIPageViewTest.h" -#include "axmol.h" +#include "axmol/axmol.h" using namespace ax; using namespace ax::ui; @@ -61,7 +61,7 @@ bool UIPageViewTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -94,7 +94,7 @@ bool UIPageViewTest::init() layout->addChild(imageView); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); layout->addChild(label); @@ -153,7 +153,7 @@ bool UIPageViewButtonTest::init() // Add the black background Text* alert = Text::create("PageView with Buttons", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -261,7 +261,7 @@ bool UIPageViewTouchPropagationTest::init() // Add the black background Text* alert = Text::create("PageView Touch Propagation", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -276,7 +276,7 @@ bool UIPageViewTouchPropagationTest::init() pageView->setAnchorPoint(Vec2(0.5f, 0.5f)); Size backgroundSize = background->getContentSize(); pageView->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); - pageView->setBackGroundColor(Color3B::GREEN); + pageView->setBackGroundColor(Color32::GREEN); pageView->setBackGroundColorType(Layout::BackGroundColorType::SOLID); int pageCount = 4; @@ -334,13 +334,13 @@ bool UIPageViewTouchPropagationTest::init() Text* propagationText = Text::create("Allow Propagation", "Arial", 10); propagationText->setAnchorPoint(Vec2(0.0f, 0.5f)); - propagationText->setTextColor(Color4B::RED); + propagationText->setTextColor(Color32::RED); propagationText->setPosition(Vec2(0.0f, pageView->getPosition().y + 50)); _uiLayer->addChild(propagationText); Text* swallowTouchText = Text::create("Swallow Touches", "Arial", 10); swallowTouchText->setAnchorPoint(Vec2(0.f, 0.5f)); - swallowTouchText->setTextColor(Color4B::RED); + swallowTouchText->setTextColor(Color32::RED); swallowTouchText->setPosition(Vec2(0.0f, pageView->getPosition().y)); _uiLayer->addChild(swallowTouchText); @@ -451,7 +451,7 @@ bool UIPageViewDynamicAddAndRemoveTest::init() // Add the black background Text* alert = Text::create("PageView Dynamic Modification", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -467,7 +467,7 @@ bool UIPageViewDynamicAddAndRemoveTest::init() pageView->setAnchorPoint(Vec2(0.5f, 0.5f)); Size backgroundSize = background->getContentSize(); pageView->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); - pageView->setBackGroundColor(Color3B::GREEN); + pageView->setBackGroundColor(Color32::GREEN); pageView->setBackGroundColorType(Layout::BackGroundColorType::SOLID); pageView->setIndicatorEnabled(true); pageView->setIndicatorSpaceBetweenIndexNodes(10); @@ -512,7 +512,7 @@ bool UIPageViewDynamicAddAndRemoveTest::init() button->setTitleText("Add A Page"); button->setZoomScale(0.3f); button->setPressedActionEnabled(true); - button->setTitleColor(Color3B::RED); + button->setTitleColor(Color32::RED); button->addClickEventListener([this, pageView](Object* /*sender*/) { HBox* outerBox = HBox::create(); outerBox->setContentSize(Size(240.0f, 130.0f)); @@ -546,7 +546,7 @@ bool UIPageViewDynamicAddAndRemoveTest::init() button2->setTitleText("Remove A Page"); button2->setZoomScale(0.3f); button2->setPressedActionEnabled(true); - button2->setTitleColor(Color3B::RED); + button2->setTitleColor(Color32::RED); button2->addClickEventListener([this, pageView](Object* /*sender*/) { if (pageView->getItems().size() > 0) { @@ -567,7 +567,7 @@ bool UIPageViewDynamicAddAndRemoveTest::init() button3->setTitleText("Remove All Pages"); button3->setZoomScale(0.3f); button3->setPressedActionEnabled(true); - button3->setTitleColor(Color3B::RED); + button3->setTitleColor(Color32::RED); button3->addClickEventListener([this, pageView](Object* /*sender*/) { pageView->removeAllItems(); _displayValueLabel->setString( @@ -628,7 +628,7 @@ bool UIPageViewJumpToPageTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -661,7 +661,7 @@ bool UIPageViewJumpToPageTest::init() layout->addChild(imageView); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); layout->addChild(label); @@ -723,7 +723,7 @@ bool UIPageViewVerticalTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -754,7 +754,7 @@ bool UIPageViewVerticalTest::init() layout->addChild(imageView); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); layout->addChild(label); @@ -809,7 +809,7 @@ bool UIPageViewDisableTouchTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -843,7 +843,7 @@ bool UIPageViewDisableTouchTest::init() layout->addChild(imageView); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); layout->addChild(label); @@ -877,7 +877,7 @@ bool UIPageViewChildSizeTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -903,7 +903,7 @@ bool UIPageViewChildSizeTest::init() imageView->setScale9Enabled(true); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setAnchorPoint(Vec2::ZERO); imageView->addChild(label); @@ -959,7 +959,7 @@ bool UIPageViewIndicatorTest::init() // Add the black background Text* alert = Text::create("PageView", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -983,7 +983,7 @@ bool UIPageViewIndicatorTest::init() pageView->setIndicatorSpaceBetweenIndexNodes(5); pageView->setIndicatorIndexNodesScale(0.5); pageView->setIndicatorIndexNodesTexture("cocosui/green_edit.png"); - pageView->setIndicatorIndexNodesColor(Color3B::RED); + pageView->setIndicatorIndexNodesColor(Color32::RED); int pageCount = 4; for (int i = 0; i < pageCount; ++i) @@ -998,7 +998,7 @@ bool UIPageViewIndicatorTest::init() layout->addChild(imageView); Text* label = Text::create(fmt::format("page {}", (i + 1)), "fonts/Marker Felt.ttf", 30); - label->setColor(Color3B(192, 192, 192)); + label->setColor(Color32(192, 192, 192)); label->setPosition(Vec2(layout->getContentSize().width / 2.0f, layout->getContentSize().height / 2.0f)); layout->addChild(label); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRadioButtonTest/UIRadioButtonTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRadioButtonTest/UIRadioButtonTest.cpp index 5d177354087c..68906e11bd76 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRadioButtonTest/UIRadioButtonTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRadioButtonTest/UIRadioButtonTest.cpp @@ -321,7 +321,7 @@ bool UIRadioButtonTabTest::init() const float buttonWidth = 350 * BUTTON_SCALE / Director::getInstance()->getContentScaleFactor(); // Background for buttons - LayerColor* colorLayer = LayerColor::create(Color4B::WHITE); + LayerColor* colorLayer = LayerColor::create(Color32::WHITE); colorLayer->setIgnoreAnchorPointForPosition(false); colorLayer->setAnchorPoint(Vec2::ANCHOR_MIDDLE); colorLayer->setContentSize(Size(buttonWidth * 3, 170 / Director::getInstance()->getContentScaleFactor())); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp index cdc106b2a4f5..8dc0de0baf5f 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIRichTextTest/UIRichTextTest.cpp @@ -186,15 +186,15 @@ bool UIRichTextTest::init() std::string str1 = config->getValue("Chinese").asString(); std::string str2 = config->getValue("Japanese").asString(); AXLOGD("str1:{} ascii length = {}, utf8 length = {}, substr = {}", str1, static_cast(str1.length()), - StringUtils::countUTF8Chars(str1), + text_utils::countUTF8Chars(str1), Helper::getSubStringOfUTF8String(str1, 0, 5)); AXLOGD("str2:{} ascii length = {}, utf8 length = {}, substr = {}", str2, - static_cast(str2.length()), StringUtils::countUTF8Chars(str2), + static_cast(str2.length()), text_utils::countUTF8Chars(str2), Helper::getSubStringOfUTF8String(str2, 0, 2)); // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125f)); _widget->addChild(alert); @@ -206,23 +206,23 @@ bool UIRichTextTest::init() _richText->ignoreContentAdaptWithSize(false); _richText->setContentSize(_defaultContentSize); - RichElementText* re1 = RichElementText::create(1, Color3B::WHITE, 255, str1, "SimSun", 10); + RichElementText* re1 = RichElementText::create(1, Color32::WHITE, str1, "SimSun", 10); RichElementText* re2 = - RichElementText::create(2, Color3B::YELLOW, 255, "And this is yellow. ", "Helvetica", 10); - RichElementText* re3 = RichElementText::create(3, Color3B::GRAY, 255, str2, "Yu Mincho", 10); - RichElementText* re4 = RichElementText::create(4, Color3B::GREEN, 255, "And green with TTF support. ", + RichElementText::create(2, Color32::YELLOW, "And this is yellow. ", "Helvetica", 10); + RichElementText* re3 = RichElementText::create(3, Color32::GRAY, str2, "Yu Mincho", 10); + RichElementText* re4 = RichElementText::create(4, Color32::GREEN, "And green with TTF support. ", "fonts/Marker Felt.ttf", 10); - RichElementText* re5 = RichElementText::create(5, Color3B::RED, 255, "Last one is red ", "Helvetica", 10); + RichElementText* re5 = RichElementText::create(5, Color32::RED, "Last one is red ", "Helvetica", 10); - RichElementImage* reimg = RichElementImage::create(6, Color3B::WHITE, 255, "cocosui/sliderballnormal.png"); + RichElementImage* reimg = RichElementImage::create(6, Color32::WHITE, "cocosui/sliderballnormal.png"); // TODO // cocostudio::ArmatureDataManager::getInstance()->addArmatureFileInfo("cocosui/100/100.ExportJson"); // cocostudio::Armature *pAr = cocostudio::Armature::create("100"); // // pAr->getAnimation()->play("Animation1"); - // RichElementCustomNode* recustom = RichElementCustomNode::create(1, Color3B::WHITE, 255, pAr); - RichElementText* re6 = RichElementText::create(7, Color3B::ORANGE, 255, "Have fun!! ", "Helvetica", 10); + // RichElementCustomNode* recustom = RichElementCustomNode::create(1, Color32::WHITE, 255, pAr); + RichElementText* re6 = RichElementText::create(7, Color32::ORANGE, "Have fun!! ", "Helvetica", 10); _richText->pushBackElement(re1); _richText->insertElement(re2, 1); _richText->pushBackElement(re3); @@ -256,7 +256,7 @@ bool UIRichTextXMLBasic::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -294,7 +294,7 @@ bool UIRichTextXMLSmallBig::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -331,7 +331,7 @@ bool UIRichTextXMLColor::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -368,7 +368,7 @@ bool UIRichTextXMLSUIB::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -405,7 +405,7 @@ bool UIRichTextXMLSUIB2::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -443,7 +443,7 @@ bool UIRichTextXMLSUIB3::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -481,7 +481,7 @@ bool UIRichTextXMLImg::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -529,7 +529,7 @@ bool UIRichTextXMLUrl::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -566,7 +566,7 @@ bool UIRichTextXMLUrlImg::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -604,7 +604,7 @@ bool UIRichTextXMLFace::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -644,7 +644,7 @@ bool UIRichTextXMLBR::init() // Add the alert Text* alert = Text::create("RichText", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -681,7 +681,7 @@ bool UIRichTextXMLInvalid::init() // Add the alert Text* alert = Text::create("Invalid XML test", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -717,7 +717,7 @@ bool UIRichTextXMLOutline::init() // Add the alert Text* alert = Text::create("Outline", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -755,7 +755,7 @@ bool UIRichTextXMLShadow::init() // Add the alert Text* alert = Text::create("Shadow", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -795,7 +795,7 @@ bool UIRichTextXMLGlow::init() // Add the alert Text* alert = Text::create("Glow", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -832,7 +832,7 @@ bool UIRichTextXMLExtend::init() // Add the alert Text* alert = Text::create("Extend", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -841,12 +841,12 @@ bool UIRichTextXMLExtend::init() /* Tag extension */ RichText::setTagDescription("CloseNormal", false, [](const ValueMap& tagAttrValueMap) { - RichElementImage* richElement = RichElementImage::create(0, Color3B::WHITE, 255, "cocosui/CloseNormal.png"); + RichElementImage* richElement = RichElementImage::create(0, Color32::WHITE, "cocosui/CloseNormal.png"); return make_pair(ValueMap(), richElement); }); RichText::setTagDescription("CloseSelected", false, [](const ValueMap& tagAttrValueMap) { RichElementImage* richElement = - RichElementImage::create(0, Color3B::WHITE, 255, "cocosui/CloseSelected.png"); + RichElementImage::create(0, Color32::WHITE, "cocosui/CloseSelected.png"); return make_pair(ValueMap(), richElement); }); @@ -905,7 +905,7 @@ bool UIRichTextXMLSpace::init() // Add the alert Text* alert = Text::create("Space", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -945,7 +945,7 @@ bool UIRichTextNewline::init() // Add the alert Text* alert = Text::create("Axmol Issue #1170", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -957,9 +957,9 @@ bool UIRichTextNewline::init() _richText = RichText::create(); _richText->setHorizontalAlignment(ui::RichText::HorizontalAlignment::CENTER); auto* textElement = - ui::RichElementText::create(1, Color3B::WHITE, 255, "Line1\nLine2\n", "fonts/Marker Felt.ttf", 32, 0); + ui::RichElementText::create(1, Color32::WHITE, "Line1\nLine2\n", "fonts/Marker Felt.ttf", 32, 0); _richText->pushBackElement(textElement); - textElement = ui::RichElementText::create(2, Color3B::WHITE, 255, "Line3", "fonts/Marker Felt.ttf", 32, 0); + textElement = ui::RichElementText::create(2, Color32::WHITE, "Line3", "fonts/Marker Felt.ttf", 32, 0); _richText->pushBackElement(textElement); _richText->ignoreContentAdaptWithSize(false); _richText->setContentSize(_defaultContentSize); @@ -984,7 +984,7 @@ bool UIRichTextHeadings::init() // Add the alert Text* alert = Text::create("Header Tags", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -1022,7 +1022,7 @@ bool UIRichTextDynamicFontSize::init() // Add the alert Text* alert = Text::create("Header Tags", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -1060,7 +1060,7 @@ bool UIRichTextParagraph::init() // Add the alert Text* alert = Text::create("Paragraph Tag", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -1102,7 +1102,7 @@ bool UIRichTextScrollTo::init() // Add the alert Text* alert = Text::create("Paragraph Tag", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.125)); _widget->addChild(alert); @@ -1123,7 +1123,7 @@ bool UIRichTextScrollTo::init() _scrollView->setScrollBarEnabled(true); _scrollView->setScrollBarWidth(4); _scrollView->setScrollBarPositionFromCorner(Vec2(2, 2)); - _scrollView->setScrollBarColor(Color3B::WHITE); + _scrollView->setScrollBarColor(Color32::WHITE); _scrollView->setScrollBarAutoHideEnabled(false); _scrollView->setAnchorPoint(Vec2::ANCHOR_MIDDLE); _scrollView->setPosition(_widget->getContentSize() / 2); @@ -1132,7 +1132,7 @@ bool UIRichTextScrollTo::init() ValueMap valMap; valMap[RichText::KEY_ANCHOR_FONT_COLOR_STRING] = "#00ffdd"; - + // RichText _richText = RichText::createWithXML( R"(

Quick Links

@@ -1140,25 +1140,25 @@ bool UIRichTextScrollTo::init() Jump To Second Paragraph
Jump To Web Search

-

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et -dolore magna aliqua. -Purus faucibus ornare suspendisse sed nisi. Viverra aliquet eget sit amet tellus cras adipiscing. -Ut tellus elementum sagittis vitae. -Risus feugiat in ante metus dictum at. Semper eget duis at tellus at. Iaculis eu non diam phasellus vestibulum -lorem sed risus. +

Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et +dolore magna aliqua. +Purus faucibus ornare suspendisse sed nisi. Viverra aliquet eget sit amet tellus cras adipiscing. +Ut tellus elementum sagittis vitae. +Risus feugiat in ante metus dictum at. Semper eget duis at tellus at. Iaculis eu non diam phasellus vestibulum +lorem sed risus. Sed vulputate odio ut enim. Morbi tristique senectus et netus et malesuada fames.

Fancy Header

-

This is the second paragraph! Cras sed felis eget velit aliquet sagittis id consectetur purus. -Turpis nunc eget lorem dolor sed viverra ipsum nunc. -Ultrices tincidunt arcu non sodales neque sodales ut etiam sit. Risus feugiat in ante metus dictum at tempor. +

This is the second paragraph! Cras sed felis eget velit aliquet sagittis id consectetur purus. +Turpis nunc eget lorem dolor sed viverra ipsum nunc. +Ultrices tincidunt arcu non sodales neque sodales ut etiam sit. Risus feugiat in ante metus dictum at tempor. Id neque aliquam vestibulum morbi blandit cursus risus.

-

Tortor condimentum lacinia quis vel eros donec ac. Molestie ac feugiat sed lectus. -Aliquam id diam maecenas ultricies mi eget mauris. -Ullamcorper malesuada proin libero nunc consequat interdum varius. -Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula ipsum. -Diam quam nulla porttitor massa id neque aliquam vestibulum morbi. Sed velit dignissim sodales ut. -Morbi leo urna molestie at elementum eu facilisis. -Cursus metus aliquam eleifend mi in. Euismod lacinia at quis risus sed vulputate odio. +

Tortor condimentum lacinia quis vel eros donec ac. Molestie ac feugiat sed lectus. +Aliquam id diam maecenas ultricies mi eget mauris. +Ullamcorper malesuada proin libero nunc consequat interdum varius. +Sollicitudin nibh sit amet commodo nulla facilisi nullam vehicula ipsum. +Diam quam nulla porttitor massa id neque aliquam vestibulum morbi. Sed velit dignissim sodales ut. +Morbi leo urna molestie at elementum eu facilisis. +Cursus metus aliquam eleifend mi in. Euismod lacinia at quis risus sed vulputate odio. Sit amet mattis vulputate enim nulla aliquet porttitor lacus luctus.

Google!)", valMap); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScale9SpriteTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScale9SpriteTest.cpp index fdfc87641aac..c0da56a8c023 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScale9SpriteTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScale9SpriteTest.cpp @@ -93,7 +93,7 @@ bool UIScale9SpriteTest::init() normalSprite2->setOpacity(100); normalSprite2->setContentSize(normalSprite2->getContentSize() * 2); this->addChild(normalSprite2); - normalSprite2->setColor(Color3B::GREEN); + normalSprite2->setColor(Color32::GREEN); normalSprite2->runAction(action); auto action2 = action->clone(); @@ -101,14 +101,14 @@ bool UIScale9SpriteTest::init() sp1->setPosition(100, 160); sp1->setScale(1.2f); sp1->setContentSize(Size(100.0f, 100.0f)); - sp1->setColor(Color3B::GREEN); + sp1->setColor(Color32::GREEN); this->addChild(sp1); sp1->runAction((FiniteTimeAction*)action2); ax::ui::Scale9Sprite* sp2 = ui::Scale9Sprite::create("cocosui/animationbuttonnormal.png"); sp2->setPosition(350.0f, 160.0f); sp2->setPreferredSize(sp1->getContentSize() * 1.2f); - sp2->setColor(Color3B::GREEN); + sp2->setColor(Color32::GREEN); sp2->setContentSize(Size(100.0f, 100.0f)); this->addChild(sp2); @@ -141,7 +141,7 @@ bool UIScale9SpriteHierarchialTest::init() normalSprite1->setPosition(100, 270); normalSprite1->setCascadeColorEnabled(true); normalSprite1->setCascadeOpacityEnabled(true); - normalSprite1->setColor(Color3B::GREEN); + normalSprite1->setColor(Color32::GREEN); this->addChild(normalSprite1); normalSprite1->runAction((FiniteTimeAction*)action->clone()); @@ -156,13 +156,13 @@ bool UIScale9SpriteHierarchialTest::init() sp1->setPosition(200.0f, 160.0f); sp1->setScale(1.2f); sp1->setContentSize(Size(100.0f, 100.0f)); - sp1->setColor(Color3B::GREEN); + sp1->setColor(Color32::GREEN); this->addChild(sp1); sp1->runAction((FiniteTimeAction*)action2); ax::ui::Scale9Sprite* sp2 = ui::Scale9Sprite::create("cocosui/animationbuttonnormal.png"); sp2->setPreferredSize(sp1->getContentSize() * 1.2f); - sp2->setColor(Color3B::GREEN); + sp2->setColor(Color32::GREEN); sp2->setFlippedX(true); sp2->setContentSize(Size(100.0f, 100.0f)); @@ -714,7 +714,7 @@ bool UIS9ZOrder::init() this->addChild(blocks_scaled_with_insets); Sprite* normalSprite = Sprite::createWithSpriteFrameName("blocks9ss/blocks9r.png"); - normalSprite->setColor(Color3B::RED); + normalSprite->setColor(Color32::RED); blocks_scaled_with_insets->addChild(normalSprite); auto topLabel = Label::createWithSystemFont("I Must be On the Top", "Arial", 15); @@ -723,7 +723,7 @@ bool UIS9ZOrder::init() auto bottomLabel = Label::createWithSystemFont("I Must be On the Bottom", "Arial", 15); bottomLabel->setPosition(Vec2(80.0f, 80.0f)); - bottomLabel->setColor(Color3B::BLUE); + bottomLabel->setColor(Color32::BLUE); blocks_scaled_with_insets->addChild(bottomLabel, -1); return true; @@ -1085,7 +1085,7 @@ bool UIS9GlobalZOrderTest::init() blocks->setPosition(Vec2(x, y)); blocks->setPreferredSize(Size(96 * 2, 96 * 1.5)); - blocks->setColor(Color3B::RED); + blocks->setColor(Color32::RED); blocks->setGlobalZOrder(1); this->addChild(blocks); @@ -1093,7 +1093,7 @@ bool UIS9GlobalZOrderTest::init() blocks2->setPosition(Vec2(x, y)); blocks2->setPreferredSize(Size(96 * 3, 96)); blocks2->setGlobalZOrder(0); - blocks2->setColor(Color3B::GREEN); + blocks2->setColor(Color32::GREEN); this->addChild(blocks2); return true; @@ -1118,7 +1118,7 @@ bool UIS9EnableScale9FalseTest::init() blocks->setScale9Enabled(false); blocks->setPosition(Vec2(x, y)); blocks->setPreferredSize(Size(96 * 2.0f, 96.0f)); - blocks->setColor(Color3B::RED); + blocks->setColor(Color32::RED); blocks->setGlobalZOrder(1); this->addChild(blocks); @@ -1127,7 +1127,7 @@ bool UIS9EnableScale9FalseTest::init() blocks2->setPosition(Vec2(0.0f, 0.0f)); blocks2->setPreferredSize(Size(96 * 1.5f, 96.0f)); blocks2->setGlobalZOrder(0); - blocks2->setColor(Color3B::GREEN); + blocks2->setColor(Color32::GREEN); blocks->addChild(blocks2); auto blocks3 = ui::Scale9Sprite::create("Images/blocks9.png"); @@ -1135,7 +1135,7 @@ bool UIS9EnableScale9FalseTest::init() blocks3->setPosition(Vec2(0.0f, 0.0f)); blocks3->setPreferredSize(Size(96.0f, 96.0f)); blocks3->setGlobalZOrder(2); - blocks3->setColor(Color3B::YELLOW); + blocks3->setColor(Color32::YELLOW); blocks2->addChild(blocks3); return true; diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScene.h b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScene.h index 32a2dc882251..9df1a87e4298 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScene.h +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScene.h @@ -26,9 +26,9 @@ #ifndef __TestCpp__UIScene__ #define __TestCpp__UIScene__ -#include "axmol.h" +#include "axmol/axmol.h" #include "extensions/axmol-ext.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" #include "BaseTest.h" class UIScene : public TestCase diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp index 8795a1bffa0e..ff9d831ae531 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIScrollViewTest/UIScrollViewTest.cpp @@ -62,7 +62,7 @@ bool UIScrollViewTest_Vertical::init() // Add the alert Text* alert = Text::create("ScrollView vertical", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -81,7 +81,7 @@ bool UIScrollViewTest_Vertical::init() (backgroundSize.height - scrollView->getContentSize().height) / 2.0f)); scrollView->setScrollBarWidth(4); scrollView->setScrollBarPositionFromCorner(Vec2(2, 2)); - scrollView->setScrollBarColor(Color3B::WHITE); + scrollView->setScrollBarColor(Color32::WHITE); scrollView->setGlobalZOrder(200); _uiLayer->addChild(scrollView); @@ -139,7 +139,7 @@ bool UIScrollViewTest_Horizontal::init() _uiLayer->addChild(_displayValueLabel); Text* alert = Text::create("ScrollView horizontal", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -155,7 +155,7 @@ bool UIScrollViewTest_Horizontal::init() scrollView->setContentSize(Size(280.0f, 150.0f)); scrollView->setInnerContainerSize(scrollView->getContentSize()); scrollView->setScrollBarPositionFromCorner(Vec2(4, 4)); - scrollView->setScrollBarColor(Color3B::YELLOW); + scrollView->setScrollBarColor(Color32::YELLOW); Size backgroundSize = background->getContentSize(); scrollView->setPosition((widgetSize - scrollView->getContentSize()) / 2.0f); _uiLayer->addChild(scrollView); @@ -220,7 +220,7 @@ bool UIScrollViewTest_Both::init() // Add the alert Text* alert = Text::create("ScrollView both", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -285,7 +285,7 @@ bool UIScrollViewTest_ScrollToPercentBothDirection::init() // Add the alert Text* alert = Text::create("ScrollView scroll to percent both direction without scroll bar", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5)); _uiLayer->addChild(alert); @@ -295,7 +295,7 @@ bool UIScrollViewTest_ScrollToPercentBothDirection::init() Layout* background = static_cast(root->getChildByName("background_Panel")); ui::ScrollView* sc = ui::ScrollView::create(); - sc->setBackGroundColor(Color3B::GREEN); + sc->setBackGroundColor(Color32::GREEN); sc->setBackGroundColorType(Layout::BackGroundColorType::SOLID); sc->setDirection(ui::ScrollView::Direction::BOTH); sc->setInnerContainerSize(Size(480.0f, 320.0f)); @@ -339,7 +339,7 @@ bool UIScrollViewTest_ScrollToPercentBothDirection_Bounce::init() // Add the alert Text* alert = Text::create("ScrollView scroll to percent both direction bounce", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 4.5)); _uiLayer->addChild(alert); @@ -349,7 +349,7 @@ bool UIScrollViewTest_ScrollToPercentBothDirection_Bounce::init() Layout* background = dynamic_cast(root->getChildByName("background_Panel")); ui::ScrollView* sc = ui::ScrollView::create(); - sc->setBackGroundColor(Color3B::GREEN); + sc->setBackGroundColor(Color32::GREEN); sc->setBackGroundColorType(Layout::BackGroundColorType::SOLID); sc->setBounceEnabled(true); sc->setDirection(ui::ScrollView::Direction::BOTH); @@ -395,7 +395,7 @@ bool UIScrollViewNestTest::init() // Add the alert Text* alert = Text::create("ScrollView vertical", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -415,7 +415,7 @@ bool UIScrollViewNestTest::init() (widgetSize.height - backgroundSize.height) / 2.0f + (backgroundSize.height - scrollView->getContentSize().height) / 2.0f)); scrollView->setScrollBarPositionFromCornerForVertical(Vec2(scrollView->getContentSize().width - 4, 4.0f)); - scrollView->setScrollBarColor(Color3B::BLUE); + scrollView->setScrollBarColor(Color32::BLUE); _uiLayer->addChild(scrollView); ImageView* imageView = ImageView::create("cocosui/ccicon.png"); @@ -448,7 +448,7 @@ bool UIScrollViewNestTest::init() // Create the scrollview by both ui::ScrollView* sc = ui::ScrollView::create(); - sc->setBackGroundColor(Color3B::GREEN); + sc->setBackGroundColor(Color32::GREEN); sc->setBackGroundColorType(Layout::BackGroundColorType::SOLID); sc->setBounceEnabled(true); sc->setDirection(ui::ScrollView::Direction::BOTH); @@ -491,7 +491,7 @@ bool UIScrollViewRotated::init() // Add the alert Text* alert = Text::create("ScrollView vertical", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -511,7 +511,7 @@ bool UIScrollViewRotated::init() (backgroundSize.height - scrollView->getContentSize().height) / 2.0f + 100)); scrollView->setRotation(45); scrollView->setScrollBarPositionFromCorner(Vec2(4, 4)); - scrollView->setScrollBarColor(Color3B::WHITE); + scrollView->setScrollBarColor(Color32::WHITE); _uiLayer->addChild(scrollView); ImageView* imageView = ImageView::create("cocosui/ccicon.png"); @@ -569,7 +569,7 @@ bool UIScrollViewDisableTest::init() // Add the alert Text* alert = Text::create("ScrollView vertical", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -589,7 +589,7 @@ bool UIScrollViewDisableTest::init() scrollView->setScrollBarWidth(4); scrollView->setTouchEnabled(false); scrollView->setScrollBarPositionFromCorner(Vec2(2, 2)); - scrollView->setScrollBarColor(Color3B::WHITE); + scrollView->setScrollBarColor(Color32::WHITE); _uiLayer->addChild(scrollView); ImageView* imageView = ImageView::create("cocosui/ccicon.png"); @@ -648,7 +648,7 @@ bool UIScrollViewInnerSize::init() // Add the alert Text* alert = Text::create("ScrollView & InnerContainer should be align to the left and top point", "fonts/Marker Felt.ttf", 10); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -668,11 +668,11 @@ bool UIScrollViewInnerSize::init() scrollView->setScrollBarWidth(4); scrollView->setTouchEnabled(false); scrollView->setScrollBarPositionFromCorner(Vec2(2, 2)); - scrollView->setScrollBarColor(Color3B::WHITE); + scrollView->setScrollBarColor(Color32::WHITE); scrollView->setBackGroundColorType(Layout::BackGroundColorType::SOLID); - scrollView->setBackGroundColor(Color3B(150, 150, 100)); + scrollView->setBackGroundColor(Color32(150, 150, 100)); scrollView->getInnerContainer()->setBackGroundColorType(Layout::BackGroundColorType::SOLID); - scrollView->getInnerContainer()->setBackGroundColor(Color3B(50, 100, 50)); + scrollView->getInnerContainer()->setBackGroundColor(Color32(50, 100, 50)); scrollView->getInnerContainer()->setBackGroundColorOpacity(100); scrollView->setClippingEnabled(false); _uiLayer->addChild(scrollView); @@ -704,7 +704,7 @@ bool UIScrollViewTestEvents::init() // Add the alert Text* alert = Text::create("ScrollView events", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -740,7 +740,7 @@ bool UIScrollViewTestEvents::init() // Jump to right bottom scrollView->jumpToBottomRight(); - auto getRandomColor = [] { return Color4B(random(0, 255), random(0, 255), random(0, 255), 255); }; + auto getRandomColor = [] { return Color32(random(0, 255), random(0, 255), random(0, 255), 255); }; scrollView->addEventListener([&](Object*, ui::ScrollView::EventType e) { switch (e) { @@ -784,7 +784,7 @@ bool UIScrollViewStopScrollingTest::init() // Add the alert Text* alert = Text::create("Click the button and start to scroll", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UISliderTest/UISliderTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UISliderTest/UISliderTest.cpp index 19c5196cfb60..c6e4392a5315 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UISliderTest/UISliderTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UISliderTest/UISliderTest.cpp @@ -58,7 +58,7 @@ bool UISliderTest::init() // Add the alert Text* alert = Text::create("Slider", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -138,7 +138,7 @@ bool UISliderTest_Scale9::init() // Add the alert Text* alert = Text::create("Slider scale9 render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -191,7 +191,7 @@ bool UISliderTest_Scale9_State_Change::init() // Add the alert Text* alert = Text::create("Slider scale9 render", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -255,7 +255,7 @@ bool UISliderNormalDefaultTest::init() // Add the alert Text* alert = Text::create("when pressed, the slider ball should scale", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.75f)); _uiLayer->addChild(alert); @@ -300,7 +300,7 @@ bool UISliderDisabledDefaultTest::init() // Add the alert Text* alert = Text::create("slider ball should be gray.", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.75f)); _uiLayer->addChild(alert); @@ -348,7 +348,7 @@ bool UISliderNewEventCallbackTest::init() // Add the alert Text* alert = Text::create("See console output for Slider Down and Up event.", "fonts/Marker Felt.ttf", 20); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.75f)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITabControlTest/UITabControlTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITabControlTest/UITabControlTest.cpp index 6b47f16e1500..ca0b8e442306 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITabControlTest/UITabControlTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITabControlTest/UITabControlTest.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "ui/UITabControl.h" +#include "axmol/ui/UITabControl.h" #include "UITabControlTest.h" using namespace ax; @@ -78,17 +78,17 @@ bool UITabControlTest::init() auto container1 = Layout::create(); container1->setOpacity(255); container1->setBackGroundColorType(Layout::BackGroundColorType::SOLID); - container1->setBackGroundColor(Color3B::GRAY); + container1->setBackGroundColor(Color32::GRAY); container1->setBackGroundColorOpacity(255); auto container2 = Layout::create(); container2->setBackGroundColorType(Layout::BackGroundColorType::SOLID); container2->setOpacity(255); - container2->setBackGroundColor(Color3B::BLUE); + container2->setBackGroundColor(Color32::BLUE); container2->setBackGroundColorOpacity(255); auto container3 = Layout::create(); container3->setBackGroundColorType(Layout::BackGroundColorType::SOLID); container3->setOpacity(255); - container3->setBackGroundColor(Color3B::RED); + container3->setBackGroundColor(Color32::RED); container3->setBackGroundColorOpacity(255); tab->insertTab(0, header1, container1); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextAtlasTest/UITextAtlasTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextAtlasTest/UITextAtlasTest.cpp index dbace24358dc..8579b93d74c1 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextAtlasTest/UITextAtlasTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextAtlasTest/UITextAtlasTest.cpp @@ -42,7 +42,7 @@ bool UITextAtlasTest::init() // Add the alert Text* alert = Text::create("TextAtlas", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -89,7 +89,7 @@ bool UITextAtlasETC1ShadowTest::init() // Add the alert Text* alert = Text::create("TextAtlas With ETC1 format", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -107,7 +107,7 @@ bool UITextAtlasETC1ShadowTest::init() textAtlas->setPosition(Vec2((widgetSize.width) / 2, widgetSize.height / 2.0f)); _uiLayer->addChild(textAtlas); auto labelAtlas = (Label*)textAtlas->getVirtualRenderer(); - labelAtlas->enableShadow(Color4B::GREEN); + labelAtlas->enableShadow(Color32::GREEN); _textAtlas = textAtlas; TTFConfig ttfConfig("fonts/arial.ttf", 15); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextBMFontTest/UITextBMFontTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextBMFontTest/UITextBMFontTest.cpp index f53c131c4886..cc72c474efcd 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextBMFontTest/UITextBMFontTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextBMFontTest/UITextBMFontTest.cpp @@ -40,7 +40,7 @@ bool UITextBMFontTest::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("TextBMFont", "TextBMFont", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextFieldTest/UITextFieldTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextFieldTest/UITextFieldTest.cpp index 684812555fb0..d2125908ed85 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextFieldTest/UITextFieldTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextFieldTest/UITextFieldTest.cpp @@ -58,7 +58,7 @@ bool UITextFieldTest::init() // Add the alert Text* alert = Text::create("TextField", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -132,7 +132,7 @@ bool UITextFieldTest_MaxLength::init() // Add the alert Text* alert = Text::create("TextField max length", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(screenSize.width / 2.0f, screenSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -213,7 +213,7 @@ bool UITextFieldTest_Password::init() // Add the alert Text* alert = Text::create("TextField password", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(screenSize.width / 2.0f, screenSize.height / 2.0f - alert->getContentSize().height * 3.075f)); _uiLayer->addChild(alert); @@ -288,7 +288,7 @@ bool UITextFieldTest_LineWrap::init() // Add the alert Text* alert = Text::create("TextField line wrap", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.075)); _uiLayer->addChild(alert); @@ -523,8 +523,8 @@ bool UITextFieldTest_PlaceHolderColor::init() // Create the textfield TextField* textField = TextField::create("input words here", "Arial", 30); textField->setPlaceHolder("input text here"); - textField->setPlaceHolderColor(Color4B::GREEN); - textField->setTextColor(Color4B::RED); + textField->setPlaceHolderColor(Color32::GREEN); + textField->setTextColor(Color32::RED); textField->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f)); textField->addEventListener(AX_CALLBACK_2(UITextFieldTest_PlaceHolderColor::textFieldEvent, this)); _uiLayer->addChild(textField); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextTest/UITextTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextTest/UITextTest.cpp index 93bf6637afc6..06d77efe7ece 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextTest/UITextTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UITextTest/UITextTest.cpp @@ -48,7 +48,7 @@ bool UITextTest::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("Text", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -73,7 +73,7 @@ bool UITextTest_LineWrap::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("Text line wrap", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -119,7 +119,7 @@ bool UILabelTest_Effect::init() alert->setString("Label Effect"); alert->setFontName("fonts/Marker Felt.ttf"); alert->setFontSize(30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 3.05f)); _uiLayer->addChild(alert); @@ -139,7 +139,7 @@ bool UILabelTest_Effect::init() Text* glow_label = Text::create(); glow_label->setFontName("fonts/Marker Felt.ttf"); glow_label->setString("Glow"); - glow_label->enableGlow(Color4B::RED); + glow_label->enableGlow(Color32::RED); glow_label->setPosition(Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - 20)); @@ -150,7 +150,7 @@ bool UILabelTest_Effect::init() outline_label->setString("Outline"); AXLOGD("content size without outline: {} {}", outline_label->getContentSize().width, outline_label->getContentSize().height); - outline_label->enableOutline(Color4B::GREEN, 4); + outline_label->enableOutline(Color32::GREEN, 4); outline_label->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - shadow_label->getContentSize().height - 50)); @@ -199,7 +199,7 @@ bool UITextTest_TTF::init() Size widgetSize = _widget->getContentSize(); Text* alert = Text::create("Text set TTF font", "fonts/Marker Felt.ttf", 30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75f)); _uiLayer->addChild(alert); @@ -268,8 +268,8 @@ bool UITextTest_Clone::init() singleText->setString("CHUKONG"); singleText->setTouchScaleChangeEnabled(true); singleText->setTouchEnabled(true); - singleText->enableOutline(Color4B(255, 0, 0, 100), 10); - singleText->enableShadow(Color4B::YELLOW, Size(2, -2), 0); + singleText->enableOutline(Color32(255, 0, 0, 100), 10); + singleText->enableShadow(Color32::YELLOW, Size(2, -2), 0); _uiLayer->addChild(singleText); auto cloneText = singleText->clone(); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIVideoPlayerTest/UIVideoPlayerTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIVideoPlayerTest/UIVideoPlayerTest.cpp index d866502bbbb1..f681c69fa15c 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIVideoPlayerTest/UIVideoPlayerTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIVideoPlayerTest/UIVideoPlayerTest.cpp @@ -30,7 +30,7 @@ using namespace ax::ui; static MenuItemFont* createMenuFontWithColor(std::string_view title, ax::ccMenuCallback&& cb, - const Color3B& color = Color3B::RED) + const Color32& color = Color32::RED) { auto menuFont = ax::MenuItemFont::create(title, cb); menuFont->setColor(color); @@ -104,14 +104,14 @@ bool VideoPlayerTest::init() _videoStateLabel->setPosition( Vec2(_visibleRect.origin.x + _visibleRect.size.width - 10, _visibleRect.origin.y + 200)); _uiLayer->addChild(_videoStateLabel, 1); - _videoStateLabel->setTextColor(Color4B::YELLOW); + _videoStateLabel->setTextColor(Color32::YELLOW); _loopStatusLabel = Label::createWithSystemFont("(1)", "Arial", 10); _loopStatusLabel->setAnchorPoint(Vec2::ANCHOR_MIDDLE_RIGHT); _loopStatusLabel->setPosition( Vec2(_visibleRect.origin.x + _visibleRect.size.width - 10, _visibleRect.origin.y + 185)); _uiLayer->addChild(_loopStatusLabel, 1); - _loopStatusLabel->setTextColor(Color4B::YELLOW); + _loopStatusLabel->setTextColor(Color32::YELLOW); return true; } diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.cpp index f2f77009f859..ec9205f318c7 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.cpp @@ -56,13 +56,13 @@ bool WebViewTest::init() this->addChild(spriteHello); TextField* urlTextField = TextField::create("Input a URL here", "Arial", 20); - urlTextField->setPlaceHolderColor(Color3B::RED); + urlTextField->setPlaceHolderColor(Color32::RED); urlTextField->setPosition(Vec2(winSize / 2) + Vec2(-80, _webView->getContentSize().height / 2 + urlTextField->getContentSize().height / 2 + 10)); this->addChild(urlTextField); Text* httpLabel = Text::create("https:// ", "Arial", 20); - httpLabel->setTextColor(Color4B::GREEN); + httpLabel->setTextColor(Color32::GREEN); httpLabel->setAnchorPoint(Vec2(1.0, 0.5)); httpLabel->setPosition(urlTextField->getPosition() - Vec2(urlTextField->getContentSize().width / 2, 0)); this->addChild(httpLabel); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.h b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.h index 73dbe6ed0c5a..75f3ef03b18a 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.h +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWebViewTest/UIWebViewTest.h @@ -27,7 +27,7 @@ #define __cocos2d_tests__UIWebViewTest__ #include "../UIScene.h" -#include "ui/UIWebView/UIWebView.h" +#include "axmol/ui/UIWebView/UIWebView.h" DEFINE_TEST_SUITE(WebViewTests); diff --git a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp index 1d3f195f41c0..93e5c350144b 100644 --- a/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp +++ b/tests/cpp-tests/Source/UITest/CocoStudioGUITest/UIWidgetAddNodeTest/UIWidgetAddNodeTest.cpp @@ -49,7 +49,7 @@ bool UIWidgetAddNodeTest::init() alert->setString("Widget Add Node"); alert->setFontName("fonts/Marker Felt.ttf"); alert->setFontSize(30); - alert->setColor(Color3B(159, 168, 176)); + alert->setColor(Color32(159, 168, 176)); alert->setPosition( Vec2(widgetSize.width / 2.0f, widgetSize.height / 2.0f - alert->getContentSize().height * 1.75)); _uiLayer->addChild(alert); diff --git a/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.cpp b/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.cpp index ac7b69df1436..057d59839d89 100644 --- a/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.cpp +++ b/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.cpp @@ -30,7 +30,7 @@ #include #include -#include "base/format.h" +#include "axmol/base/format.h" using namespace std; diff --git a/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.h b/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.h index 5affdef54be7..1db19b32faa4 100644 --- a/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.h +++ b/tests/cpp-tests/Source/UserDefaultTest/UserDefaultTest.h @@ -25,9 +25,9 @@ #ifndef _USERDEFAULT_TEST_H_ #define _USERDEFAULT_TEST_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "../BaseTest.h" -#include "2d/Label.h" +#include "axmol/2d/Label.h" DEFINE_TEST_SUITE(UserDefaultTests); diff --git a/tests/cpp-tests/Source/VRTest/VRTest.h b/tests/cpp-tests/Source/VRTest/VRTest.h index a22d7f0d1d56..6e075c4c78da 100644 --- a/tests/cpp-tests/Source/VRTest/VRTest.h +++ b/tests/cpp-tests/Source/VRTest/VRTest.h @@ -26,7 +26,7 @@ #ifndef _VR_TEST_H_ #define _VR_TEST_H_ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "../BaseTest.h" #include diff --git a/tests/cpp-tests/Source/VibrateTest/VibrateTest.cpp b/tests/cpp-tests/Source/VibrateTest/VibrateTest.cpp index 17a1af1d98ac..480e3e002134 100644 --- a/tests/cpp-tests/Source/VibrateTest/VibrateTest.cpp +++ b/tests/cpp-tests/Source/VibrateTest/VibrateTest.cpp @@ -23,10 +23,10 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #include "VibrateTest.h" -#include "ui/CocosGUI.h" +#include "axmol/ui/CocosGUI.h" using namespace ax; using namespace ax::ui; @@ -65,11 +65,11 @@ class TextButton : public ax::Label _enabled = enabled; if (_enabled) { - this->setColor(Color3B::WHITE); + this->setColor(Color32::WHITE); } else { - this->setColor(Color3B::GRAY); + this->setColor(Color32::GRAY); } } diff --git a/tests/cpp-tests/Source/VibrateTest/VibrateTest.h b/tests/cpp-tests/Source/VibrateTest/VibrateTest.h index 35127e4bab05..14e760bf2722 100644 --- a/tests/cpp-tests/Source/VibrateTest/VibrateTest.h +++ b/tests/cpp-tests/Source/VibrateTest/VibrateTest.h @@ -23,12 +23,12 @@ THE SOFTWARE. ****************************************************************************/ -#include "platform/PlatformConfig.h" +#include "axmol/platform/PlatformConfig.h" #ifndef __VIBRATE_TEST_H_ # define __VIBRATE_TEST_H_ -# include "axmol.h" +# include "axmol/axmol.h" # include "../BaseTest.h" DEFINE_TEST_SUITE(VibrateTests); diff --git a/tests/cpp-tests/Source/VisibleRect.h b/tests/cpp-tests/Source/VisibleRect.h index 605e81eae868..c56e94d02a84 100644 --- a/tests/cpp-tests/Source/VisibleRect.h +++ b/tests/cpp-tests/Source/VisibleRect.h @@ -25,7 +25,7 @@ #ifndef __VISIBLERECT_H__ #define __VISIBLERECT_H__ -#include "axmol.h" +#include "axmol/axmol.h" class VisibleRect { diff --git a/tests/cpp-tests/Source/controller.cpp b/tests/cpp-tests/Source/controller.cpp index 1602f4ef5ecd..47538c6ab616 100644 --- a/tests/cpp-tests/Source/controller.cpp +++ b/tests/cpp-tests/Source/controller.cpp @@ -47,7 +47,7 @@ class RootTests : public TestList addTest("Effekseer", []() { return new EffekseerTests(); }); #endif addTest("Node: Scene3D", [](){return new Scene3DTests(); }); -#if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) +#if AX_ENABLE_EXT_IMGUI addTest("ImGui", []() { return new ImGuiTests(); }); #endif addTest("Texture2D", []() { return new Texture2DTests(); }); @@ -58,12 +58,8 @@ class RootTests : public TestList addTest("Audio - NewAudioEngine", []() { return new AudioEngineTests(); }); addTest("Box2D - Basic", []() { return new Box2DTests(); }); -#if defined(AX_PLATFORM_PC) || defined(__EMSCRIPTEN__) +#if AX_ENABLE_EXT_IMGUI && defined(AX_PLATFORM_PC) addTest("Box2D - TestBed", []() { return new Box2DTestBedTests(); }); -#endif - addTest("Chipmunk2D - Basic", []() { return new ChipmunkTests(); }); -#if defined(AX_PLATFORM_PC) || defined(__EMSCRIPTEN__) - addTest("Chipmunk2D - TestBed", []() { return new ChipmunkTestBedTests(); }); #endif addTest("Bugs", []() { return new BugsTests(); }); addTest("Click and Move", []() { return new ClickAndMoveTest(); }); @@ -99,7 +95,7 @@ class RootTests : public TestList addTest("Node: Particles", []() { return new ParticleTests(); }); addTest("Node: Particle3D (PU)", []() { return new Particle3DTests(); }); #if defined(AX_ENABLE_PHYSICS) - addTest("Node: Physics", []() { return new PhysicsTests(); }); + addTest("Node: Physics", []() { return new PhysicsTests(); }); #endif addTest("Node: Physics3D", []() { return new Physics3DTests(); }); addTest("Node: RenderTexture", []() { return new RenderTextureTests(); }); @@ -165,6 +161,15 @@ void TestController::startAutoTest() { if (_stopAutoTest) { + const char* const captureDir = std::getenv("AXMOL_AUTOTEST_CAPTURE_DIR"); + if (captureDir) + { + _autoTestCaptureDirectory = captureDir; + _autoTestCaptureDirectory += '/'; + } + else + _autoTestCaptureDirectory.clear(); + _stopAutoTest = false; _logIndentation = ""; @@ -189,7 +194,7 @@ Coroutine TestController::traverseTestList(TestList* testList) _logIndentation += LOG_INDENTATION; } - co_yield DelayTime::create(0.5); + co_yield DelayTime::create(0.5); AXLOGD("{}{}Begin traverse TestList:{}", LOG_TAG, _logIndentation, testList->getTestName()); auto scheduler = _director->getScheduler(); @@ -201,7 +206,7 @@ Coroutine TestController::traverseTestList(TestList* testList) while (_isRunInBackground) { AXLOGD("_director is paused"); - co_yield DelayTime::create(0.5); + co_yield DelayTime::create(0.5); } if (callback) { @@ -238,6 +243,7 @@ Coroutine TestController::traverseTestList(TestList* testList) { // Backs up one level and release TestList object. testList->_parentTest->runThisTest(); + testList->release(); } @@ -288,7 +294,7 @@ Coroutine TestController::traverseTestList(TestList* testList) { testCase = (TestCase*)transitionScene->getInScene(); testCaseDuration = transitionScene->getDuration() + 0.5f; - + } else { @@ -302,7 +308,27 @@ Coroutine TestController::traverseTestList(TestList* testList) testScene = scene; - co_yield DelayTime::create(testCaseDuration); + CallFunc* capture; + if (_autoTestCaptureDirectory.empty()) + capture = nullptr; + else + capture = CallFunc::create + ([this, testSuite, testCase]() -> void + { + ax::utils::captureScreen + ([this, testSuite, testCase] + (ax::RefPtr image) -> void + { + std::string file_name = + testSuite->getTestName() + '-' + + testCase->getTestCaseName(); + + image->saveToFile + (_autoTestCaptureDirectory + file_name + ".png"); + }); + }); + + co_yield Sequence::create(DelayTime::create(testCaseDuration), capture, nullptr); } if (_stopAutoTest) diff --git a/tests/cpp-tests/Source/controller.h b/tests/cpp-tests/Source/controller.h index fb9a10e09e79..06999bbd2da3 100644 --- a/tests/cpp-tests/Source/controller.h +++ b/tests/cpp-tests/Source/controller.h @@ -31,8 +31,8 @@ THE SOFTWARE. #include #include -#include "platform/PlatformMacros.h" -#include "2d/ActionCoroutine.h" +#include "axmol/platform/PlatformMacros.h" +#include "axmol/2d/ActionCoroutine.h" class TestList; class TestSuite; @@ -82,6 +82,7 @@ class TestController TestSuite* _testSuite; ax::Node* _autoTestRunner{nullptr}; + std::string _autoTestCaptureDirectory; ax::Director* _director; ax::EventListenerTouchOneByOne* _touchListener; diff --git a/tests/cpp-tests/Source/feature-detect.h b/tests/cpp-tests/Source/feature-detect.h new file mode 100644 index 000000000000..57475177c046 --- /dev/null +++ b/tests/cpp-tests/Source/feature-detect.h @@ -0,0 +1,11 @@ +#pragma once + +#if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) +# if __has_include("ImGui/ImGuiPresenter.h") +# define AX_ENABLE_EXT_IMGUI 1 +# endif +#endif + +#ifndef AX_ENABLE_EXT_IMGUI +# define AX_ENABLE_EXT_IMGUI 0 +#endif diff --git a/tests/cpp-tests/Source/shaders/circle.fs b/tests/cpp-tests/Source/shaders/circle.fs new file mode 100644 index 000000000000..a1e7e6091efb --- /dev/null +++ b/tests/cpp-tests/Source/shaders/circle.fs @@ -0,0 +1,23 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 420 + +layout(location = 0) in vec2 v_position; +layout(location = 1) in vec4 v_color; +layout(location = 2) in float v_thickness; + +layout(location = SV_Target0) out vec4 fragColor; + +void main() +{ + // radius in unit quad + float radius = 1.0; + + // distance to circle + vec2 w = v_position; + float dw = length(w); + float d = abs(dw - radius); + + fragColor = vec4(v_color.rgb, smoothstep(v_thickness, 0.0, d)); +} diff --git a/tests/cpp-tests/Source/shaders/circle.vs b/tests/cpp-tests/Source/shaders/circle.vs new file mode 100644 index 000000000000..218ff88287be --- /dev/null +++ b/tests/cpp-tests/Source/shaders/circle.vs @@ -0,0 +1,50 @@ +#version 310 es + +layout(location = 0) in vec2 a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) +layout(location = 1) in vec4 a_instanceColor; +// pos: xy, radius: z, due to metal alignment is 16 +layout(location = 2) in vec4 a_instancePosAndRadius; +#endif + +layout(location = 0) out vec2 v_position; +layout(location = 1) out vec4 v_color; +layout(location = 2) out float v_thickness; + +layout(std140) uniform vs_ub { + float u_pixelScale; + mat4 u_MVPMatrix; +}; + +#if defined(AXSLC_TARGET_MSL) +struct instance_data_st { + vec4 color; + vec2 pos; + float radius; +}; +layout(std140, binding = 1) readonly buffer vs_inst { + instance_data_st instances[]; +}; +#endif + +void main() +{ + v_position = a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) + v_color = a_instanceColor; + vec2 instancePos = a_instancePosAndRadius.xy; + float radius = a_instancePosAndRadius.z; +#else + v_color = instances[gl_InstanceIndex].color; + vec2 instancePos = instances[gl_InstanceIndex].pos; + float radius = instances[gl_InstanceIndex].radius; +#endif + + // resolution.y = pixelScale * radius + v_thickness = 3.0f / (u_pixelScale * radius); + + vec2 p = vec2(radius * a_localPosition.x, radius * a_localPosition.y) + instancePos; + gl_Position = u_MVPMatrix * vec4(p, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/shaders/example_Flower.fsh b/tests/cpp-tests/Source/shaders/example_Flower.fsh index d405e19093a1..33968b5b6659 100644 --- a/tests/cpp-tests/Source/shaders/example_Flower.fsh +++ b/tests/cpp-tests/Source/shaders/example_Flower.fsh @@ -21,13 +21,13 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { float time = u_Time[1]; -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; #endif vec2 p = 2.0 * (fragCoord - center.xy) / resolution.xy; - + float a = atan(p.x,p.y); float r = length(p)*.75; @@ -38,7 +38,7 @@ void main(void) float rd = 1.0-r/d; float col = 0.0; if(rd > 0.0) - col = u( d-r ) * sqrt(rd)*r*2.5; + col = u( d-r ) * sqrt(rd)*r*2.5; col *= 1.25+0.25*cos((12.0*a-w*7.0+r*8.0)/2.0); col *= 1.0 - 0.35*(0.5+0.5*sin(r*30.0))*(0.5+0.5*cos(12.0*a-w*7.0+r*8.0)); FragColor = vec4( @@ -46,4 +46,4 @@ void main(void) col-h*0.5+r*.2 + 0.35*h*(1.0-r), col-h*r + 0.1*h*(1.0-r), 1.0); -} \ No newline at end of file +} diff --git a/tests/cpp-tests/Source/shaders/example_Heart.fsh b/tests/cpp-tests/Source/shaders/example_Heart.fsh index 0a6d2d0ddbe0..1088d8733601 100644 --- a/tests/cpp-tests/Source/shaders/example_Heart.fsh +++ b/tests/cpp-tests/Source/shaders/example_Heart.fsh @@ -17,7 +17,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { float time = u_Time[1]; -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; diff --git a/tests/cpp-tests/Source/shaders/example_HorizontalColor.fsh b/tests/cpp-tests/Source/shaders/example_HorizontalColor.fsh index 2c51af814a0d..68be5d7d4b87 100644 --- a/tests/cpp-tests/Source/shaders/example_HorizontalColor.fsh +++ b/tests/cpp-tests/Source/shaders/example_HorizontalColor.fsh @@ -17,7 +17,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { vec4 optColor; -#ifdef METAL +#ifdef AXSLC_TARGET_MSL float fragCoordY = u_screenSize.y - gl_FragCoord.y; #else float fragCoordY = gl_FragCoord.y; @@ -33,7 +33,7 @@ void main(void) else if(y == 7) optColor = vec4(1,0.5,0,1); else if(y == 8) optColor = vec4(1,0.5,0.5,1); else if(y == 9) optColor = vec4(0.5,0.5,1,1); - + // inline to prevent "float" loss and keep using lowp FragColor = optColor * texture(u_tex0, v_texCoord); -} \ No newline at end of file +} diff --git a/tests/cpp-tests/Source/shaders/example_Julia.fsh b/tests/cpp-tests/Source/shaders/example_Julia.fsh index e1ab9f7684e9..df96440e1a4e 100644 --- a/tests/cpp-tests/Source/shaders/example_Julia.fsh +++ b/tests/cpp-tests/Source/shaders/example_Julia.fsh @@ -17,7 +17,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { float time = u_Time[1]; -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; diff --git a/tests/cpp-tests/Source/shaders/example_Mandelbrot.fsh b/tests/cpp-tests/Source/shaders/example_Mandelbrot.fsh index 4398bd7f56c1..98958bef7b98 100644 --- a/tests/cpp-tests/Source/shaders/example_Mandelbrot.fsh +++ b/tests/cpp-tests/Source/shaders/example_Mandelbrot.fsh @@ -16,7 +16,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; @@ -50,4 +50,4 @@ void main(void) .5+.5*cos(6.2831*co+0.4), .5+.5*cos(6.2831*co+0.7), 1.0 ); -} \ No newline at end of file +} diff --git a/tests/cpp-tests/Source/shaders/example_Monjori.fsh b/tests/cpp-tests/Source/shaders/example_Monjori.fsh index b8b2a7338c43..89b6d1a83c1c 100644 --- a/tests/cpp-tests/Source/shaders/example_Monjori.fsh +++ b/tests/cpp-tests/Source/shaders/example_Monjori.fsh @@ -16,7 +16,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; diff --git a/tests/cpp-tests/Source/shaders/example_Noisy.fsh b/tests/cpp-tests/Source/shaders/example_Noisy.fsh index a10480ecf7d1..98543ec61fc4 100644 --- a/tests/cpp-tests/Source/shaders/example_Noisy.fsh +++ b/tests/cpp-tests/Source/shaders/example_Noisy.fsh @@ -19,7 +19,7 @@ layout(std140) uniform fs_ub { vec3 noise(vec2 uv) { vec2 p = abs(sin(uv * 13.0 + uv.x * u_Time[1] * sin(uv.y))); - + return vec3(sin (0.2 * u_Time[1] + sin(p * 0.5) * u_Time[1] / cos(50.0)) * 10.0,0.3+0.5 * abs(sin(u_Time[1] * tan(5.0)))); } @@ -28,7 +28,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; @@ -36,4 +36,4 @@ void main(void) FragColor.xyz = intensity * noise(fragCoord / sin(resolution.xy * u_Time[1] * 0.01)) + (1. - intensity) * texture(u_tex0,v_texCoord.xy).xyz; FragColor.w = 1.; -} \ No newline at end of file +} diff --git a/tests/cpp-tests/Source/shaders/example_Plasma.fsh b/tests/cpp-tests/Source/shaders/example_Plasma.fsh index e23a962b1cdf..b1428bbea8cc 100644 --- a/tests/cpp-tests/Source/shaders/example_Plasma.fsh +++ b/tests/cpp-tests/Source/shaders/example_Plasma.fsh @@ -16,7 +16,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL float fragCoordY = u_screenSize.y - gl_FragCoord.y; #else float fragCoordY = gl_FragCoord.y; diff --git a/tests/cpp-tests/Source/shaders/example_Twist.fsh b/tests/cpp-tests/Source/shaders/example_Twist.fsh index e19ee8b6691e..b4c440965b53 100644 --- a/tests/cpp-tests/Source/shaders/example_Twist.fsh +++ b/tests/cpp-tests/Source/shaders/example_Twist.fsh @@ -18,7 +18,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; diff --git a/tests/cpp-tests/Source/shaders/shadertoy_FireBall.fsh b/tests/cpp-tests/Source/shaders/shadertoy_FireBall.fsh index d62c300afc7a..a4a20244e015 100644 --- a/tests/cpp-tests/Source/shaders/shadertoy_FireBall.fsh +++ b/tests/cpp-tests/Source/shaders/shadertoy_FireBall.fsh @@ -20,23 +20,23 @@ layout(std140) uniform fs_ub { float snoise(vec3 uv, float res) { const vec3 s = vec3(1e0, 1e2, 1e4); - + uv *= res; - + vec3 uv0 = floor(mod(uv, res))*s; vec3 uv1 = floor(mod(uv+vec3(1.), res))*s; - + vec3 f = fract(uv); f = f*f*(3.0-2.0*f); - + vec4 v = vec4(uv0.x+uv0.y+uv0.z, uv1.x+uv0.y+uv0.z, uv0.x+uv1.y+uv0.z, uv1.x+uv1.y+uv0.z); - + vec4 r = fract(sin(v*1e-3)*1e5); float r0 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y); - + r = fract(sin((v + uv1.z - uv0.z)*1e-3)*1e5); float r1 = mix(mix(r.x, r.y, f.x), mix(r.z, r.w, f.x), f.y); - + return mix(r0, r1, f.z)*2.-1.; } @@ -44,7 +44,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; @@ -53,14 +53,14 @@ void main(void) float iGlobalTime = u_Time[1]; // shader playback time (in seconds) //vec2 p = -.5 + fragCoord.xy / iResolution.xy; - + vec2 p = (fragCoord.xy - center.xy) / iResolution.xy; p.x *= iResolution.x/iResolution.y; - + float color = 3.0 - (3.*length(2.*p)); - + vec3 coord = vec3(atan(p.x,p.y)/6.2832+.5, length(p)*.4, .5); - + for(int i = 1; i <= 3; i++) { float power = pow(2.0, float(i)); diff --git a/tests/cpp-tests/Source/shaders/shadertoy_Glow.fsh b/tests/cpp-tests/Source/shaders/shadertoy_Glow.fsh index d16bfbb63543..98125e59cd4c 100644 --- a/tests/cpp-tests/Source/shaders/shadertoy_Glow.fsh +++ b/tests/cpp-tests/Source/shaders/shadertoy_Glow.fsh @@ -21,7 +21,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; @@ -32,16 +32,16 @@ void main(void) float pointRadius = 0.06; float linkSize = 0.04; float noiseStrength = 0.08; // range: 0-1 - + float minDimension = min(iResolution.x, iResolution.y); vec2 bounds = vec2(iResolution.x / minDimension, iResolution.y / minDimension); //vec2 uv = fragCoord.xy / minDimension; vec2 uv = (2. * fragCoord.xy - center.xy) / iResolution.xy; - + vec3 pointR = vec3(0.0, 0.0, 1.0); vec3 pointG = vec3(0.0, 0.0, 1.0); vec3 pointB = vec3(0.0, 0.0, 1.0); - + // Make the points orbit round the origin in 3 dimensions. // Coefficients are arbitrary to give different behaviours. // The Z coordinate should always be >0.0, as it's used directly to @@ -49,74 +49,74 @@ void main(void) pointR.x += 0.32 * sin(1.32 * iGlobalTime); pointR.y += 0.3 * sin(1.03 * iGlobalTime); pointR.z += 0.4 * sin(1.32 * iGlobalTime); - + pointG.x += 0.31 * sin(0.92 * iGlobalTime); pointG.y += 0.29 * sin(0.99 * iGlobalTime); pointG.z += 0.38 * sin(1.24 * iGlobalTime); - + pointB.x += 0.33 * sin(1.245 * iGlobalTime); pointB.y += 0.3 * sin(1.41 * iGlobalTime); pointB.z += 0.41 * sin(1.11 * iGlobalTime); - + // Centre the points in the display vec2 midUV = vec2(bounds.x * 0.5, bounds.y * 0.5); pointR.xy += midUV; pointG.xy += midUV; pointB.xy += midUV; - + // Calculate the vectors from the current fragment to the coloured points vec2 vecToR = pointR.xy - uv; vec2 vecToG = pointG.xy - uv; vec2 vecToB = pointB.xy - uv; - + vec2 dirToR = normalize(vecToR.xy); vec2 dirToG = normalize(vecToG.xy); vec2 dirToB = normalize(vecToB.xy); - + float distToR = length(vecToR); float distToG = length(vecToG); float distToB = length(vecToB); - + // Calculate the dot product between vectors from the current fragment to each pair // of adjacent coloured points. This helps us determine how close the current fragment // is to a link between points. float dotRG = dot(dirToR, dirToG); float dotGB = dot(dirToG, dirToB); float dotBR = dot(dirToB, dirToR); - + // Start with a bright coloured dot around each point FragColor.x = 1.0 - smoothstep(distToR, 0.0, pointRadius * pointR.z); FragColor.y = 1.0 - smoothstep(distToG, 0.0, pointRadius * pointG.z); FragColor.z = 1.0 - smoothstep(distToB, 0.0, pointRadius * pointB.z); FragColor.w = 1.0; - + // We want to show a coloured link between adjacent points. // Determine the strength of each link at the current fragment. // This tends towards 1.0 as the vectors to each point tend towards opposite directions. float linkStrengthRG = 1.0 - smoothstep(dotRG, -1.01, -1.0 + (linkSize * pointR.z * pointG.z)); float linkStrengthGB = 1.0 - smoothstep(dotGB, -1.01, -1.0 + (linkSize * pointG.z * pointB.z)); float linkStrengthBR = 1.0 - smoothstep(dotBR, -1.01, -1.0 + (linkSize * pointB.z * pointR.z)); - + // If the current fragment is in a link, we need to know how much the // linked points contribute of their colour. float sumDistRG = distToR + distToG; float sumDistGB = distToG + distToB; float sumDistBR = distToB + distToR; - + float contribRonRG = 1.0 - (distToR / sumDistRG); float contribRonBR = 1.0 - (distToR / sumDistBR); - + float contribGonRG = 1.0 - (distToG / sumDistRG); float contribGonGB = 1.0 - (distToG / sumDistGB); - + float contribBonGB = 1.0 - (distToB / sumDistGB); float contribBonBR = 1.0 - (distToB / sumDistBR); - + // Additively blend the link colours into the fragment. FragColor.x += (linkStrengthRG * contribRonRG) + (linkStrengthBR * contribRonBR); FragColor.y += (linkStrengthGB * contribGonGB) + (linkStrengthRG * contribGonRG); FragColor.z += (linkStrengthBR * contribBonBR) + (linkStrengthGB * contribBonGB); - + // Use an underlying texture to provide some noise float noiseMin = 1.0 - noiseStrength; FragColor.xyz *= (1.0 - noiseStrength) + (noiseStrength * 0.); diff --git a/tests/cpp-tests/Source/shaders/shadertoy_LensFlare.fsh b/tests/cpp-tests/Source/shaders/shadertoy_LensFlare.fsh index 9d80344d0a21..29cc988c2e33 100644 --- a/tests/cpp-tests/Source/shaders/shadertoy_LensFlare.fsh +++ b/tests/cpp-tests/Source/shaders/shadertoy_LensFlare.fsh @@ -8,12 +8,12 @@ precision highp int; //layout(binding = 0) uniform sampler2D iChannel0; // input channel. XX = 2D/Cube /*by musk License Creative Commons Attribution-NonCommercial-ShareAlike 3.0 Unported License. - + Trying to get some interesting looking lens flares. - + 13/08/13: published - + muuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuusk!*/ @@ -37,45 +37,45 @@ vec3 lensflare(vec2 uv,vec2 pos) { vec2 main = uv-pos; vec2 uvd = uv*(length(uv)); - + float ang = atan(main.x,main.y); float dist=length(main); dist = pow(dist,.1); float n = noise(vec2(ang*16.0,dist*32.0)); - + float f0 = 1.0/(length(uv-pos)*16.0+1.0); - + f0 = f0+f0*(sin(noise((pos.x+pos.y)*2.2+ang*4.0+5.954)*16.0)*.1+dist*.1+.8); - + float f1 = max(0.01-pow(length(uv+1.2*pos),1.9),.0)*7.0; - + float f2 = max(1.0/(1.0+32.0*pow(length(uvd+0.8*pos),2.0)),.0)*00.25; float f22 = max(1.0/(1.0+32.0*pow(length(uvd+0.85*pos),2.0)),.0)*00.23; float f23 = max(1.0/(1.0+32.0*pow(length(uvd+0.9*pos),2.0)),.0)*00.21; - + vec2 uvx = mix(uv,uvd,-0.5); - + float f4 = max(0.01-pow(length(uvx+0.4*pos),2.4),.0)*6.0; float f42 = max(0.01-pow(length(uvx+0.45*pos),2.4),.0)*5.0; float f43 = max(0.01-pow(length(uvx+0.5*pos),2.4),.0)*3.0; - + uvx = mix(uv,uvd,-.4); - + float f5 = max(0.01-pow(length(uvx+0.2*pos),5.5),.0)*2.0; float f52 = max(0.01-pow(length(uvx+0.4*pos),5.5),.0)*2.0; float f53 = max(0.01-pow(length(uvx+0.6*pos),5.5),.0)*2.0; - + uvx = mix(uv,uvd,-0.5); - + float f6 = max(0.01-pow(length(uvx-0.3*pos),1.6),.0)*6.0; float f62 = max(0.01-pow(length(uvx-0.325*pos),1.6),.0)*3.0; float f63 = max(0.01-pow(length(uvx-0.35*pos),1.6),.0)*5.0; - + vec3 c = vec3(.0); - + c.r+=f2+f4+f5+f6; c.g+=f22+f42+f52+f62; c.b+=f23+f43+f53+f63; c = c*1.3 - vec3(length(uvd)*.05); c+=vec3(f0); - + return c; } @@ -89,7 +89,7 @@ layout(location = SV_Target0) out vec4 FragColor; void main(void) { -#ifdef METAL +#ifdef AXSLC_TARGET_MSL vec2 fragCoord = vec2(gl_FragCoord.x, u_screenSize.y - gl_FragCoord.y); #else vec2 fragCoord = gl_FragCoord.xy; @@ -108,7 +108,7 @@ void main(void) hover.x=sin(iGlobalTime)*.5; hover.y=sin(iGlobalTime*.913)*.5; //} - + vec3 color = vec3(1.4,1.2,1.0)*lensflare(uv,hover.xy); color -= noise(fragCoord.xy)*.015; color = cc(color,.5,.1); diff --git a/tests/cpp-tests/Source/shaders/solid_capsule.fs b/tests/cpp-tests/Source/shaders/solid_capsule.fs new file mode 100644 index 000000000000..8536db9f44c5 --- /dev/null +++ b/tests/cpp-tests/Source/shaders/solid_capsule.fs @@ -0,0 +1,61 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 420 + +layout(location=0) in vec2 v_position; +layout(location=1) in vec4 v_color; +layout(location=2) in float v_length; +layout(location=3) in float v_thickness; + +layout(location = SV_Target0) out vec4 fragColor; + +// Thanks to baz and kolyan3040 for help on this shader +// todo this can be optimized a bit, keeping some terms for clarity + +// https://en.wikipedia.org/wiki/Alpha_compositing +vec4 blend_colors(vec4 front,vec4 back) +{ + vec3 cSrc = front.rgb; + float alphaSrc = front.a; + vec3 cDst = back.rgb; + float alphaDst = back.a; + + vec3 cOut = cSrc * alphaSrc + cDst * alphaDst * (1.0 - alphaSrc); + float alphaOut = alphaSrc + alphaDst * (1.0 - alphaSrc); + + // remove alpha from rgb + cOut = cOut / alphaOut; + + return vec4(cOut, alphaOut); +} + +void main() +{ + // radius in unit quad + float radius = 0.5 * (2.0 - v_length); + + vec4 borderColor = v_color; + vec4 fillColor = 0.6f * borderColor; + + vec2 v1 = vec2(-0.5 * v_length, 0); + vec2 v2 = vec2(0.5 * v_length, 0); + + // distance to line segment + vec2 e = v2 - v1; + vec2 w = v_position - v1; + float we = dot(w, e); + vec2 b = w - e * clamp(we / dot(e, e), 0.0, 1.0); + float dw = length(b); + + // SDF union of capsule and line segment + float d = min(dw, abs(dw - radius)); + + // roll the fill alpha down at the border + vec4 back = vec4(fillColor.rgb, fillColor.a * smoothstep(radius + v_thickness, radius, dw)); + + // roll the border alpha down from 1 to 0 across the border thickness + vec4 front = vec4(borderColor.rgb, smoothstep(v_thickness, 0.0f, d)); + + fragColor = blend_colors(front, back); +} diff --git a/tests/cpp-tests/Source/shaders/solid_capsule.vs b/tests/cpp-tests/Source/shaders/solid_capsule.vs new file mode 100644 index 000000000000..5d669b777c95 --- /dev/null +++ b/tests/cpp-tests/Source/shaders/solid_capsule.vs @@ -0,0 +1,70 @@ +#version 310 es + +layout(location=0) in vec2 a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) +layout(location=1) in vec4 a_instanceTransform; +layout(location=2) in vec4 a_instanceColor; +// radius: x, length: y, due to metal alignment is 16 +layout(location=3) in vec4 a_instanceRadiusAndLength; +#endif + +layout(location=0) out vec2 v_position; +layout(location=1) out vec4 v_color; +layout(location=2) out float v_length; +layout(location=3) out float v_thickness; + +layout(std140) uniform vs_ub { + float u_pixelScale; + mat4 u_MVPMatrix; +}; + +#if defined(AXSLC_TARGET_MSL) +struct instance_data_st { + vec4 trans; + vec4 color; + float radius; + float len; +}; +layout(std140, binding = 1) readonly buffer vs_inst { + instance_data_st instances[]; +}; +#endif + +void main() +{ + v_position = a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) + v_color = a_instanceColor; + + float radius = a_instanceRadiusAndLength.x; + float length = a_instanceRadiusAndLength.y; + float x = a_instanceTransform.x; + float y = a_instanceTransform.y; + float c = a_instanceTransform.z; + float s = a_instanceTransform.w; +#else + v_color = instances[gl_InstanceIndex].color; + + float radius = instances[gl_InstanceIndex].radius; + float length = instances[gl_InstanceIndex].len; + float x = instances[gl_InstanceIndex].trans.x; + float y = instances[gl_InstanceIndex].trans.y; + float c = instances[gl_InstanceIndex].trans.z; + float s = instances[gl_InstanceIndex].trans.w; +#endif + + // scale quad large enough to hold capsule + float scale = radius + 0.5 * length; + + // quad range of [-1, 1] implies normalize radius and length + v_length = length / scale; + + // resolution.y = pixelScale * scale + v_thickness = 3.0f / (u_pixelScale * scale); + + vec2 p = vec2(scale * a_localPosition.x, scale * a_localPosition.y); + p = vec2((c * p.x - s * p.y) + x, (s * p.x + c * p.y) + y); + gl_Position = u_MVPMatrix * vec4(p, 0.0, 1.0); +} diff --git a/tests/cpp-tests/Source/shaders/solid_circle.fs b/tests/cpp-tests/Source/shaders/solid_circle.fs new file mode 100644 index 000000000000..e9f5d47e3a10 --- /dev/null +++ b/tests/cpp-tests/Source/shaders/solid_circle.fs @@ -0,0 +1,56 @@ +// SPDX-FileCopyrightText: 2024 Erin Catto +// SPDX-License-Identifier: MIT + +#version 420 + +layout(location = 0) in vec2 v_position; +layout(location = 1) in vec4 v_color; +layout(location = 2) in float v_thickness; + +layout(location = SV_Target0) out vec4 fragColor; + +// https://en.wikipedia.org/wiki/Alpha_compositing +vec4 blend_colors(vec4 front, vec4 back) +{ + vec3 cSrc = front.rgb; + float alphaSrc = front.a; + vec3 cDst = back.rgb; + float alphaDst = back.a; + + vec3 cOut = cSrc * alphaSrc + cDst * alphaDst * (1.0 - alphaSrc); + float alphaOut = alphaSrc + alphaDst * (1.0 - alphaSrc); + cOut = cOut / alphaOut; + + return vec4(cOut, alphaOut); +} + +void main() +{ + // radius in unit quad + float radius = 1.0; + + // distance to axis line segment + vec2 e = vec2(radius, 0); + vec2 w = v_position; + float we = dot(w, e); + vec2 b = w - e * clamp(we / dot(e, e), 0.0, 1.0); + float da = length(b); + + // distance to circle + float dw = length(w); + float dc = abs(dw - radius); + + // union of circle and axis + float d = min(da, dc); + + vec4 borderColor = v_color; + vec4 fillColor = 0.6f * borderColor; + + // roll the fill alpha down at the border + vec4 back = vec4(fillColor.rgb, fillColor.a * smoothstep(radius + v_thickness, radius, dw)); + + // roll the border alpha down from 1 to 0 across the border thickness + vec4 front = vec4(borderColor.rgb, smoothstep(v_thickness, 0.0f, d)); + + fragColor = blend_colors(front, back); +} diff --git a/tests/cpp-tests/Source/shaders/solid_circle.vs b/tests/cpp-tests/Source/shaders/solid_circle.vs new file mode 100644 index 000000000000..0eeb22a43b55 --- /dev/null +++ b/tests/cpp-tests/Source/shaders/solid_circle.vs @@ -0,0 +1,57 @@ +#version 310 es + +layout(location = 0) in vec2 a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) +layout(location = 1) in vec4 a_instanceTransform; +layout(location = 2) in vec4 a_instanceColor; +// radius: x, due to metal alignment is 16 +layout(location = 3) in vec4 a_instanceRadius; +#endif + +layout(location = 0) out vec2 v_position; +layout(location = 1) out vec4 v_color; +layout(location = 2) out float v_thickness; + +layout(std140) uniform vs_ub { + float u_pixelScale; + mat4 u_MVPMatrix; +}; + +#if defined(AXSLC_TARGET_MSL) +struct instance_data_st { + vec4 trans; + vec4 color; + float radius; +}; +layout(std140, binding = 1) readonly buffer vs_inst { + instance_data_st instances[]; +}; +#endif + +void main() +{ + v_position = a_localPosition; + +#if !defined(AXSLC_TARGET_MSL) + v_color = a_instanceColor; + float radius = a_instanceRadius.x; + float x = a_instanceTransform.x; + float y = a_instanceTransform.y; + float c = a_instanceTransform.z; + float s = a_instanceTransform.w; +#else + v_color = instances[gl_InstanceIndex].color; + float radius = instances[gl_InstanceIndex].radius; + float x = instances[gl_InstanceIndex].trans.x; + float y = instances[gl_InstanceIndex].trans.y; + float c = instances[gl_InstanceIndex].trans.z; + float s = instances[gl_InstanceIndex].trans.w; +#endif + + // resolution.y = pixelScale * radius + v_thickness = 3.0f / (u_pixelScale * radius); + vec2 p = vec2(radius * a_localPosition.x, radius * a_localPosition.y); + p = vec2((c * p.x - s * p.y) + x, (s * p.x + c * p.y) + y); + gl_Position = u_MVPMatrix * vec4(p, 0.0f, 1.0f); +} diff --git a/tests/cpp-tests/Source/testBasic.h b/tests/cpp-tests/Source/testBasic.h index c0cfbce6701f..403e427f1f69 100644 --- a/tests/cpp-tests/Source/testBasic.h +++ b/tests/cpp-tests/Source/testBasic.h @@ -25,7 +25,7 @@ #ifndef _TEST_BASIC_H_ #define _TEST_BASIC_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "VisibleRect.h" /** diff --git a/tests/cpp-tests/Source/tests.h b/tests/cpp-tests/Source/tests.h index 38542c183b4d..bf10f946dfe4 100644 --- a/tests/cpp-tests/Source/tests.h +++ b/tests/cpp-tests/Source/tests.h @@ -26,12 +26,11 @@ #ifndef _TESTS_H_ #define _TESTS_H_ -#include "Box2DTest/Box2dTest.h" -#include "Box2DTestBed/Box2DTestBed.h" +#include "feature-detect.h" -#include "ChipmunkTest/ChipmunkTest.h" -#if defined(AX_PLATFORM_PC) || defined(__EMSCRIPTEN__) -# include "ChipmunkTestBed/ChipmunkTestBed.h" +#include "Box2DTest/Box2dTest.h" +#if AX_ENABLE_EXT_IMGUI && defined(AX_PLATFORM_PC) +# include "Box2DTestBed/Box2DTestBed.h" #endif #if (AX_TARGET_PLATFORM != AX_PLATFORM_MARMALADE) @@ -55,7 +54,7 @@ #endif #if defined(AX_ENABLE_EXT_EFFEKSEER) -#include "EffekseerTest/EffekseerTest.h" +# include "EffekseerTest/EffekseerTest.h" #endif // sort them alphabetically. thanks @@ -121,7 +120,7 @@ #include "VibrateTest/VibrateTest.h" #include "SpriteFrameCacheTest/SpriteFrameCacheTest.h" #include "ZipTest/ZipTests.h" -#if defined(AX_PLATFORM_PC) || (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID) || defined(__EMSCRIPTEN__) +#if AX_ENABLE_EXT_IMGUI # include "ImGuiTest/ImGuiTest.h" #endif #endif diff --git a/tests/cpp-tests/proj.android/app/AndroidManifest.xml b/tests/cpp-tests/proj.android/app/AndroidManifest.xml index 344e07e6aee1..c91813d171d7 100644 --- a/tests/cpp-tests/proj.android/app/AndroidManifest.xml +++ b/tests/cpp-tests/proj.android/app/AndroidManifest.xml @@ -21,7 +21,7 @@ android:screenOrientation="sensorLandscape" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:launchMode="singleTask" android:taskAffinity="" android:exported="true" > diff --git a/tests/cpp-tests/proj.android/app/build.gradle b/tests/cpp-tests/proj.android/app/build.gradle index 1312656a3df8..58bf67c5e7d4 100644 --- a/tests/cpp-tests/proj.android/app/build.gradle +++ b/tests/cpp-tests/proj.android/app/build.gradle @@ -4,7 +4,7 @@ apply from: project(':libaxmol').projectDir.toString() + "/../dsl/axmol.gradle" // Resolve build profiles def buildProfiles = AxmolUtils.resolveBuildProfiles(project) -android { +android { def packageName = buildProfiles['packageName'] def cmakeVer = buildProfiles['cmakeVer'] def cmakeOptions = Eval.me(buildProfiles['cmakeOptions']) @@ -39,6 +39,8 @@ android { // noinspection ChromeOsAbiSupport abiFilters = __1K_ARCHS.split(':').collect{it as String} } + + multiDexEnabled true } sourceSets.main { @@ -112,6 +114,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/tests/cpp-tests/proj.android/gradle.properties b/tests/cpp-tests/proj.android/gradle.properties index 7e72096641e8..36fa9dc5cf0e 100644 --- a/tests/cpp-tests/proj.android/gradle.properties +++ b/tests/cpp-tests/proj.android/gradle.properties @@ -31,4 +31,5 @@ __1K_ARCHS=arm64-v8a android.injected.testOnly=false android.useAndroidX=true android.native.buildOutput=verbose +android.enableJetifier=true diff --git a/tests/cpp-tests/proj.android/settings.gradle b/tests/cpp-tests/proj.android/settings.gradle index e4e9ab4baa42..6ce333cf4dd4 100644 --- a/tests/cpp-tests/proj.android/settings.gradle +++ b/tests/cpp-tests/proj.android/settings.gradle @@ -11,7 +11,7 @@ else { ENGINE_ROOT = settingsDir.getPath() + "/../../.." } -def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/core/platform/android/libaxmol'; +def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/axmol/platform/android/libaxmol'; include ':libaxmol' project(':libaxmol').projectDir = new File(ENGINE_JAVA_LIBPATH) diff --git a/tests/cpp-tests/proj.ios/Source/testsAppDelegate.mm b/tests/cpp-tests/proj.ios/Source/testsAppDelegate.mm index ecd51a554496..189eb3635052 100644 --- a/tests/cpp-tests/proj.ios/Source/testsAppDelegate.mm +++ b/tests/cpp-tests/proj.ios/Source/testsAppDelegate.mm @@ -26,8 +26,8 @@ of this software and associated documentation files (the "Software"), to deal #import "testsAppDelegate.h" -#import "platform/ios/EARenderView-ios.h" -#import "axmol.h" +#import "axmol/platform/ios/EARenderView-ios.h" +#import "axmol/axmol.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/tests/cpp-tests/proj.linux/main.cpp b/tests/cpp-tests/proj.linux/main.cpp index 40f7d8b1f4a3..7510124924bd 100644 --- a/tests/cpp-tests/proj.linux/main.cpp +++ b/tests/cpp-tests/proj.linux/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include #include diff --git a/tests/cpp-tests/proj.wasm/main.cpp b/tests/cpp-tests/proj.wasm/main.cpp index a274751783dd..011acbe41faa 100644 --- a/tests/cpp-tests/proj.wasm/main.cpp +++ b/tests/cpp-tests/proj.wasm/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/tests/cpp-tests/proj.win32/main.cpp b/tests/cpp-tests/proj.win32/main.cpp index b14bc2f937d9..92e5f551ede5 100644 --- a/tests/cpp-tests/proj.win32/main.cpp +++ b/tests/cpp-tests/proj.win32/main.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "AppDelegate.h" -#include "platform/Application.h" +#include "axmol/platform/Application.h" // Uncomment to enable win32 console #define USE_WIN32_CONSOLE @@ -46,7 +46,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL // create the application instance #ifdef USE_WIN32_CONSOLE -# include "platform/win32/EmbedConsole.h" +# include "axmol/platform/win32/EmbedConsole.h" #endif // create the application instance diff --git a/tests/cpp-tests/proj.win32/main.h b/tests/cpp-tests/proj.win32/main.h index 62c2bc2e13cb..9f3872b14b3c 100644 --- a/tests/cpp-tests/proj.win32/main.h +++ b/tests/cpp-tests/proj.win32/main.h @@ -32,6 +32,6 @@ #include // C RunTime Header Files -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" #endif // __MAIN_H__ diff --git a/tests/fairygui-tests/CMakeLists.txt b/tests/fairygui-tests/CMakeLists.txt index 4d748f66ac53..81d72ddbb6b4 100644 --- a/tests/fairygui-tests/CMakeLists.txt +++ b/tests/fairygui-tests/CMakeLists.txt @@ -57,7 +57,7 @@ if(NOT DEFINED BUILD_ENGINE_DONE) set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/Modules/) include(AXBuildSet) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() _1kfetch(sample-assets) @@ -206,7 +206,7 @@ endif() if((NOT IOS) AND (NOT WINRT)) message(STATUS "CMake precompile headers for ${APP_NAME}") target_precompile_headers(${APP_NAME} PRIVATE - "$<$:axmol.h>" + "$<$:axmol/axmol.h>" ) endif() diff --git a/tests/fairygui-tests/Source/AppDelegate.cpp b/tests/fairygui-tests/Source/AppDelegate.cpp index 7d23983b6b50..2243280d4c45 100644 --- a/tests/fairygui-tests/Source/AppDelegate.cpp +++ b/tests/fairygui-tests/Source/AppDelegate.cpp @@ -1,7 +1,7 @@ #include "AppDelegate.h" #include "MenuScene.h" -#include "audio/AudioEngine.h" +#include "axmol/audio/AudioEngine.h" using namespace ax; @@ -74,7 +74,7 @@ bool AppDelegate::applicationDidFinishLaunching() { director->setContentScaleFactor(MIN(smallResolutionSize.height / designResolutionSize.height, smallResolutionSize.width / designResolutionSize.width)); }*/ - director->setClearColor(Color4F(Color4B(0x36, 0x3B, 0x44, 0xFF))); + director->setClearColor(Color32{0x36, 0x3B, 0x44, 0xFF}); register_all_packages(); diff --git a/tests/fairygui-tests/Source/AppDelegate.h b/tests/fairygui-tests/Source/AppDelegate.h index f280617fca2a..0b4053d19aea 100644 --- a/tests/fairygui-tests/Source/AppDelegate.h +++ b/tests/fairygui-tests/Source/AppDelegate.h @@ -1,7 +1,7 @@ #ifndef _APP_DELEGATE_H_ #define _APP_DELEGATE_H_ -#include "axmol.h" +#include "axmol/axmol.h" /** @brief The axmol Application. diff --git a/tests/fairygui-tests/Source/BagScene.h b/tests/fairygui-tests/Source/BagScene.h index 4caf14a7208b..fec53d62ca82 100644 --- a/tests/fairygui-tests/Source/BagScene.h +++ b/tests/fairygui-tests/Source/BagScene.h @@ -1,7 +1,7 @@ #ifndef __BAG_SCENE_H__ #define __BAG_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" #include "BagWindow.h" diff --git a/tests/fairygui-tests/Source/BasicsScene.cpp b/tests/fairygui-tests/Source/BasicsScene.cpp index 3c31c4d74584..21590b5a79d3 100644 --- a/tests/fairygui-tests/Source/BasicsScene.cpp +++ b/tests/fairygui-tests/Source/BasicsScene.cpp @@ -186,7 +186,7 @@ void BasicsScene::playDepth() startPos.x += 10; startPos.y += 10; graph->setPosition(startPos.x, startPos.y); - graph->drawRect(150, 150, 1, Color4F::BLACK, Color4F::RED); + graph->drawRect(150, 150, 1, Color::BLACK, Color::RED); obj->getChild("n22")->as()->addChild(graph); }, EventTag(this)); //avoid duplicate register @@ -196,7 +196,7 @@ void BasicsScene::playDepth() startPos.x += 10; startPos.y += 10; graph->setPosition(startPos.x, startPos.y); - graph->drawRect(150, 150, 1, Color4F::BLACK, Color4F::GREEN); + graph->drawRect(150, 150, 1, Color::BLACK, Color::GREEN); graph->setSortingOrder(200); obj->getChild("n22")->as()->addChild(graph); }, diff --git a/tests/fairygui-tests/Source/BasicsScene.h b/tests/fairygui-tests/Source/BasicsScene.h index 67b60e3fff7e..cf39a8b44dbd 100644 --- a/tests/fairygui-tests/Source/BasicsScene.h +++ b/tests/fairygui-tests/Source/BasicsScene.h @@ -1,7 +1,7 @@ #ifndef __BASICS_SCENE_H__ #define __BASICS_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/ChatScene.h b/tests/fairygui-tests/Source/ChatScene.h index 734a52e9b453..0f6b29fbaeab 100644 --- a/tests/fairygui-tests/Source/ChatScene.h +++ b/tests/fairygui-tests/Source/ChatScene.h @@ -1,7 +1,7 @@ #ifndef __CHAT_SCENE_H__ #define __CHAT_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/CooldownScene.h b/tests/fairygui-tests/Source/CooldownScene.h index 4b1ce0b69626..5233bb1d34b2 100644 --- a/tests/fairygui-tests/Source/CooldownScene.h +++ b/tests/fairygui-tests/Source/CooldownScene.h @@ -1,7 +1,7 @@ #ifndef __COOLDOWN_SCENE_H__ #define __COOLDOWN_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/DemoScene.h b/tests/fairygui-tests/Source/DemoScene.h index f291258f2814..da37263461b7 100644 --- a/tests/fairygui-tests/Source/DemoScene.h +++ b/tests/fairygui-tests/Source/DemoScene.h @@ -1,7 +1,7 @@ #ifndef __DEMO_SCENE_H__ #define __DEMO_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUI.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/GuideScene.h b/tests/fairygui-tests/Source/GuideScene.h index 451c1b5fe600..4699cc45ebf5 100644 --- a/tests/fairygui-tests/Source/GuideScene.h +++ b/tests/fairygui-tests/Source/GuideScene.h @@ -1,7 +1,7 @@ #ifndef __GUIDE_SCENE_H__ #define __GUIDE_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/HitTestScene.h b/tests/fairygui-tests/Source/HitTestScene.h index dd6f1eb97463..f58c5c54ef08 100644 --- a/tests/fairygui-tests/Source/HitTestScene.h +++ b/tests/fairygui-tests/Source/HitTestScene.h @@ -1,7 +1,7 @@ #ifndef __HITEST_SCENE_H__ #define __HITEST_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/JoystickModule.h b/tests/fairygui-tests/Source/JoystickModule.h index 5336160570a8..8a9ea766a222 100644 --- a/tests/fairygui-tests/Source/JoystickModule.h +++ b/tests/fairygui-tests/Source/JoystickModule.h @@ -1,7 +1,7 @@ #ifndef __JOYSTICK_MODULE_H__ #define __JOYSTICK_MODULE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "FairyGUI.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/JoystickScene.h b/tests/fairygui-tests/Source/JoystickScene.h index 3202b8f1ecbc..0eae6cd6dc24 100644 --- a/tests/fairygui-tests/Source/JoystickScene.h +++ b/tests/fairygui-tests/Source/JoystickScene.h @@ -1,7 +1,7 @@ #ifndef __JOYSTICK_SCENE_H__ #define __JOYSTICK_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" #include "JoystickModule.h" diff --git a/tests/fairygui-tests/Source/ListEffectScene.h b/tests/fairygui-tests/Source/ListEffectScene.h index 74d9febb8a77..0e94c22e832c 100644 --- a/tests/fairygui-tests/Source/ListEffectScene.h +++ b/tests/fairygui-tests/Source/ListEffectScene.h @@ -1,7 +1,7 @@ #ifndef __LISTEFFECT_SCENE_H__ #define __LISTEFFECT_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/LoopListScene.h b/tests/fairygui-tests/Source/LoopListScene.h index 20c719272f7b..78f2ba0c55de 100644 --- a/tests/fairygui-tests/Source/LoopListScene.h +++ b/tests/fairygui-tests/Source/LoopListScene.h @@ -1,7 +1,7 @@ #ifndef __LOOPLIST_SCENE_H__ #define __LOOPLIST_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/MenuScene.h b/tests/fairygui-tests/Source/MenuScene.h index c447d7869fb2..dd77326c65be 100644 --- a/tests/fairygui-tests/Source/MenuScene.h +++ b/tests/fairygui-tests/Source/MenuScene.h @@ -1,7 +1,7 @@ #ifndef __MENU_SCENE_H__ #define __MENU_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/ModalWaitingScene.h b/tests/fairygui-tests/Source/ModalWaitingScene.h index fe2386d2180a..1e4ba73e6d7e 100644 --- a/tests/fairygui-tests/Source/ModalWaitingScene.h +++ b/tests/fairygui-tests/Source/ModalWaitingScene.h @@ -1,7 +1,7 @@ #ifndef __MODALWAITING_SCENE_H__ #define __MODALWAITING_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/PullToRefreshScene.h b/tests/fairygui-tests/Source/PullToRefreshScene.h index fd4f11e05c75..c9cd43c7bbfd 100644 --- a/tests/fairygui-tests/Source/PullToRefreshScene.h +++ b/tests/fairygui-tests/Source/PullToRefreshScene.h @@ -1,7 +1,7 @@ #ifndef __PULLTOREFRESH_SCENE_H__ #define __PULLTOREFRESH_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/ScrollPaneScene.h b/tests/fairygui-tests/Source/ScrollPaneScene.h index d840a419390a..2c3a84dad90d 100644 --- a/tests/fairygui-tests/Source/ScrollPaneScene.h +++ b/tests/fairygui-tests/Source/ScrollPaneScene.h @@ -1,7 +1,7 @@ #ifndef __SCROLLPANE_SCENE_H__ #define __SCROLLPANE_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/TransitionDemoScene.h b/tests/fairygui-tests/Source/TransitionDemoScene.h index d299a622d071..7268d9db6698 100644 --- a/tests/fairygui-tests/Source/TransitionDemoScene.h +++ b/tests/fairygui-tests/Source/TransitionDemoScene.h @@ -1,7 +1,7 @@ #ifndef __TRANSITION_DEMO_SCENE_H__ #define __TRANSITION_DEMO_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/TreeViewScene.h b/tests/fairygui-tests/Source/TreeViewScene.h index 2f3bfa1f7de0..48a0beff6b75 100644 --- a/tests/fairygui-tests/Source/TreeViewScene.h +++ b/tests/fairygui-tests/Source/TreeViewScene.h @@ -1,7 +1,7 @@ #ifndef __TREEVIEW_SCENE_H__ #define __TREEVIEW_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/Source/VirtualListScene.h b/tests/fairygui-tests/Source/VirtualListScene.h index 862bdb74a3cc..91a0e82ee7b3 100644 --- a/tests/fairygui-tests/Source/VirtualListScene.h +++ b/tests/fairygui-tests/Source/VirtualListScene.h @@ -1,7 +1,7 @@ #ifndef __VIRTUALLIST_SCENE_H__ #define __VIRTUALLIST_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "DemoScene.h" USING_NS_FGUI; diff --git a/tests/fairygui-tests/proj.android/app/AndroidManifest.xml b/tests/fairygui-tests/proj.android/app/AndroidManifest.xml index 5ac9b73bd8c5..67ce4bfb54b6 100644 --- a/tests/fairygui-tests/proj.android/app/AndroidManifest.xml +++ b/tests/fairygui-tests/proj.android/app/AndroidManifest.xml @@ -3,23 +3,23 @@ android:installLocation="auto"> - + - + - + diff --git a/tests/fairygui-tests/proj.android/app/build.gradle b/tests/fairygui-tests/proj.android/app/build.gradle index 0b822c0a6905..1a318527d740 100644 --- a/tests/fairygui-tests/proj.android/app/build.gradle +++ b/tests/fairygui-tests/proj.android/app/build.gradle @@ -4,7 +4,7 @@ apply from: project(':libaxmol').projectDir.toString() + "/../dsl/axmol.gradle" // Resolve build profiles def buildProfiles = AxmolUtils.resolveBuildProfiles(project) -android { +android { def packageName = buildProfiles['packageName'] def cmakeVer = buildProfiles['cmakeVer'] def cmakeOptions = Eval.me(buildProfiles['cmakeOptions']) @@ -112,6 +112,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/tests/fairygui-tests/proj.android/settings.gradle b/tests/fairygui-tests/proj.android/settings.gradle index eacccb092924..b8f048b664a9 100644 --- a/tests/fairygui-tests/proj.android/settings.gradle +++ b/tests/fairygui-tests/proj.android/settings.gradle @@ -11,7 +11,7 @@ else { ENGINE_ROOT = settingsDir.getPath() + "/../../.." } -def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/core/platform/android/libaxmol'; +def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/axmol/platform/android/libaxmol'; include ':libaxmol' project(':libaxmol').projectDir = new File(ENGINE_JAVA_LIBPATH) diff --git a/tests/fairygui-tests/proj.ios/AppController.mm b/tests/fairygui-tests/proj.ios/AppController.mm index 2d860588e30c..e98befd17701 100644 --- a/tests/fairygui-tests/proj.ios/AppController.mm +++ b/tests/fairygui-tests/proj.ios/AppController.mm @@ -24,7 +24,7 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import #import "AppController.h" -#import "axmol.h" +#import "axmol/axmol.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/tests/fairygui-tests/proj.linux/main.cpp b/tests/fairygui-tests/proj.linux/main.cpp index 3248f44f2649..f9a14fe33508 100644 --- a/tests/fairygui-tests/proj.linux/main.cpp +++ b/tests/fairygui-tests/proj.linux/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include #include diff --git a/tests/fairygui-tests/proj.wasm/main.cpp b/tests/fairygui-tests/proj.wasm/main.cpp index a274751783dd..011acbe41faa 100644 --- a/tests/fairygui-tests/proj.wasm/main.cpp +++ b/tests/fairygui-tests/proj.wasm/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/tests/fairygui-tests/proj.win32/main.cpp b/tests/fairygui-tests/proj.win32/main.cpp index ea374d3d2c27..7a5f2d3d3733 100644 --- a/tests/fairygui-tests/proj.win32/main.cpp +++ b/tests/fairygui-tests/proj.win32/main.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" // Uncomment to enable win32 console // #define USE_WIN32_CONSOLE @@ -46,7 +46,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL // create the application instance #ifdef USE_WIN32_CONSOLE -# include "platform/win32/EmbedConsole.h" +# include "axmol/platform/win32/EmbedConsole.h" #endif // create the application instance diff --git a/tests/fairygui-tests/proj.win32/main.h b/tests/fairygui-tests/proj.win32/main.h index c443e632957c..d8f5f9feb7b6 100644 --- a/tests/fairygui-tests/proj.win32/main.h +++ b/tests/fairygui-tests/proj.win32/main.h @@ -32,6 +32,6 @@ #include // C RunTime Header Files -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" #endif // __MAIN_H__ diff --git a/tests/live2d-tests/CMakeLists.txt b/tests/live2d-tests/CMakeLists.txt index 72daaef8cd59..100da5e22e7a 100644 --- a/tests/live2d-tests/CMakeLists.txt +++ b/tests/live2d-tests/CMakeLists.txt @@ -58,7 +58,7 @@ if(NOT DEFINED BUILD_ENGINE_DONE) set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/Modules/) include(AXBuildSet) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() _1kfetch(sample-assets) @@ -207,7 +207,7 @@ endif() if((NOT IOS) AND (NOT WINRT)) message(STATUS "CMake precompile headers for ${APP_NAME}") target_precompile_headers(${APP_NAME} PRIVATE - "$<$:axmol.h>" + "$<$:axmol/axmol.h>" ) endif() diff --git a/tests/live2d-tests/Source/AppDelegate.h b/tests/live2d-tests/Source/AppDelegate.h index 050f5f269c4a..329a2c13ecc1 100644 --- a/tests/live2d-tests/Source/AppDelegate.h +++ b/tests/live2d-tests/Source/AppDelegate.h @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -8,7 +8,7 @@ #ifndef _APP_DELEGATE_H_ #define _APP_DELEGATE_H_ -#include "axmol.h" +#include "axmol/axmol.h" #include "LAppAllocator.hpp" #include diff --git a/tests/live2d-tests/Source/AppMacros.h b/tests/live2d-tests/Source/AppMacros.h index 4d4ae374204f..6aefd9f022a3 100644 --- a/tests/live2d-tests/Source/AppMacros.h +++ b/tests/live2d-tests/Source/AppMacros.h @@ -1,7 +1,7 @@ -#ifndef __APPMACROS_H__ +#ifndef __APPMACROS_H__ #define __APPMACROS_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" /* For demonstrating using one design resolution to match different resources, or one resource to match different design resolutions. diff --git a/tests/live2d-tests/Source/LAppLive2DManager.cpp b/tests/live2d-tests/Source/LAppLive2DManager.cpp index 9c40714f3234..8302ac08feab 100644 --- a/tests/live2d-tests/Source/LAppLive2DManager.cpp +++ b/tests/live2d-tests/Source/LAppLive2DManager.cpp @@ -18,8 +18,8 @@ #endif //cocos2d -#include "base/Director.h" -#include "renderer/backend/DriverBase.h" +#include "axmol/base/Director.h" +#include "axmol/rhi/DriverBase.h" using namespace Csm; using namespace LAppDefine; @@ -98,7 +98,7 @@ LAppLive2DManager::LAppLive2DManager() } #ifdef CSM_TARGET_ANDROID_ES2 - char *exts = (char*)backend::DriverBase::getInstance()->getExtension(); + char *exts = (char*)rhi::DriverBase::getInstance()->getExtension(); if(strstr(exts, "GL_NV_shader_framebuffer_fetch ")){ Rendering::CubismRenderer_Cocos2dx::SetExtShaderMode( true , true ); } diff --git a/tests/live2d-tests/Source/LAppLive2DManager.hpp b/tests/live2d-tests/Source/LAppLive2DManager.hpp index 4ce9c070f36e..8d596735860e 100644 --- a/tests/live2d-tests/Source/LAppLive2DManager.hpp +++ b/tests/live2d-tests/Source/LAppLive2DManager.hpp @@ -150,6 +150,6 @@ class LAppLive2DManager LAppSprite* _sprite; ///< テクスチャの単純描画クラス Csm::Rendering::CubismOffscreenFrame_Cocos2dx* _renderBuffer; ///< モードによってはCubismモデル結果をこっちにレンダリング float _clearColor[4]; ///< レンダリングターゲットのクリアカラー - ax::backend::Program* _program; + ax::rhi::Program* _program; }; diff --git a/tests/live2d-tests/Source/LAppModel.cpp b/tests/live2d-tests/Source/LAppModel.cpp index 967b49c34173..4ca02bb9af35 100644 --- a/tests/live2d-tests/Source/LAppModel.cpp +++ b/tests/live2d-tests/Source/LAppModel.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -20,16 +20,16 @@ #include "SampleScene.h" //cocos2d -#include "base/Director.h" -#include "renderer/Texture2D.h" -#include "renderer/TextureCache.h" +#include "axmol/base/Director.h" +#include "axmol/renderer/Texture2D.h" +#include "axmol/renderer/TextureCache.h" using namespace std; using namespace Csm; using namespace Csm::Constant; using namespace Csm::DefaultParameterId; using namespace LAppDefine; -using namespace ax::backend; +using namespace ax::rhi; #if USE_AUDIO_ENGINE #include "audio/include/AudioEngine.h" @@ -646,12 +646,7 @@ void LAppModel::SetupTextures() // テクスチャが読めていなければバインド処理をスキップ if(!texture) continue; - const SamplerDescriptor texParams = { - SamplerFilter::LINEAR_MIPMAP_LINEAR, - SamplerFilter::LINEAR, - SamplerAddressMode::CLAMP_TO_EDGE, - SamplerAddressMode::CLAMP_TO_EDGE - }; + const SamplerDesc texParams = Texture2D::chooseSamplerDesc(true, true); texture->setTexParameters(texParams); texture->generateMipmap(); _loadedTextures.PushBack(texture); @@ -772,7 +767,7 @@ void LAppModel::MakeRenderingTarget() Size visibleSize = Director::getInstance()->getVisibleSize(); Point origin = Director::getInstance()->getVisibleOrigin(); - _renderSprite = RenderTexture::create(frameW, frameH, ax::backend::PixelFormat::RGBA8); + _renderSprite = RenderTexture::create(frameW, frameH, ax::rhi::PixelFormat::RGBA8); _renderSprite->setPosition(Point(visibleSize.width / 2 + origin.x, visibleSize.height / 2 + origin.y)); _renderSprite->getSprite()->getTexture()->setAntiAliasTexParameters(); _renderSprite->getSprite()->setBlendFunc(BlendFunc::ALPHA_NON_PREMULTIPLIED); @@ -782,14 +777,7 @@ void LAppModel::MakeRenderingTarget() _renderSprite->setVisible(true); // _renderSpriteのテクスチャを作成する - _renderSprite->getSprite()->getTexture()->setTexParameters( - ax::Texture2D::TexParams( - ax::backend::SamplerFilter::LINEAR, // MagFilter - ax::backend::SamplerFilter::LINEAR, // MinFilter - ax::backend::SamplerAddressMode::CLAMP_TO_EDGE, // AddressingMode S - ax::backend::SamplerAddressMode::CLAMP_TO_EDGE // AddressingMode T - ) - ); + _renderSprite->getSprite()->getTexture()->setTexParameters(ax::Texture2D::TexParams{}); // レンダリングバッファの描画先をそのテクスチャにする _renderBuffer->CreateOffscreenFrame(frameW, frameH, _renderSprite); @@ -802,7 +790,8 @@ void LAppModel::SetSpriteColor(float r, float g, float b, float a) { if (_renderSprite != NULL) { - _renderSprite->getSprite()->setColor(Color3B(static_cast(255.0f * r), static_cast(255.0f * g), static_cast(255.0f * b))); - _renderSprite->getSprite()->setOpacity(static_cast(255.0f * a)); + _renderSprite->getSprite()->setColor( + Color32(static_cast(255.0f * r), static_cast(255.0f * g), + static_cast(255.0f * b), static_cast(255.0f * a))); } } diff --git a/tests/live2d-tests/Source/LAppModel.hpp b/tests/live2d-tests/Source/LAppModel.hpp index a8efa2bc2b63..88ac910b7387 100644 --- a/tests/live2d-tests/Source/LAppModel.hpp +++ b/tests/live2d-tests/Source/LAppModel.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -7,7 +7,7 @@ #pragma once -#include "2d/RenderTexture.h" +#include "axmol/2d/RenderTexture.h" #include #include #include diff --git a/tests/live2d-tests/Source/LAppPal.cpp b/tests/live2d-tests/Source/LAppPal.cpp index 5b31ead67811..19393992aa1c 100644 --- a/tests/live2d-tests/Source/LAppPal.cpp +++ b/tests/live2d-tests/Source/LAppPal.cpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -7,7 +7,7 @@ #include "LAppPal.hpp" #include -#include "cocos2d.h" +#include "axmol/cocos2d.h" using namespace Csm; using namespace ax; diff --git a/tests/live2d-tests/Source/LAppSprite.cpp b/tests/live2d-tests/Source/LAppSprite.cpp index 5a3c522ed744..aea08a5db6bb 100644 --- a/tests/live2d-tests/Source/LAppSprite.cpp +++ b/tests/live2d-tests/Source/LAppSprite.cpp @@ -6,10 +6,10 @@ */ #include "LAppSprite.hpp" -#include "base/Director.h" +#include "axmol/base/Director.h" #include "LAppPal.hpp" -LAppSprite::LAppSprite(backend::Program* program) +LAppSprite::LAppSprite(rhi::Program* program) { _program = program; @@ -21,16 +21,16 @@ LAppSprite::~LAppSprite() } void LAppSprite::RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, - backend::TextureBackend* texture, + rhi::Texture* texture, float uvVertex[8]) const { Csm::Rendering::CubismCommandBuffer_Cocos2dx::DrawCommandBuffer* drawCommandBuffer = CSM_NEW Csm::Rendering::CubismCommandBuffer_Cocos2dx::DrawCommandBuffer(); - PipelineDescriptor* pipelineDescriptor = drawCommandBuffer->GetCommandDraw()->GetPipelineDescriptor(); - backend::BlendDescriptor* blendDescriptor = drawCommandBuffer->GetCommandDraw()->GetBlendDescriptor(); - backend::ProgramState* programState = pipelineDescriptor->programState; + PipelineDesc* pipelineDescriptor = drawCommandBuffer->GetCommandDraw()->GetPipelineDescriptor(); + rhi::BlendDesc* blendDescriptor = drawCommandBuffer->GetCommandDraw()->GetBlendDescriptor(); + rhi::ProgramState* programState = pipelineDescriptor->programState; drawCommandBuffer->GetCommandDraw()->GetCommand()->setDrawType(ax::CustomCommand::DrawType::ELEMENT); - drawCommandBuffer->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::backend::PrimitiveType::TRIANGLE); + drawCommandBuffer->GetCommandDraw()->GetCommand()->setPrimitiveType(ax::rhi::PrimitiveType::TRIANGLE); drawCommandBuffer->CreateVertexBuffer(sizeof(float) * 2, 4 * 2); drawCommandBuffer->CreateIndexBuffer(6); @@ -59,13 +59,13 @@ void LAppSprite::RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* c if (!programState) { - programState = new ax::backend::ProgramState(_program); + programState = new ax::rhi::ProgramState(_program); } auto layout = programState->getMutableVertexLayout(); // attribute属性を登録 - layout->setAttrib("a_position", _program->getAttributeLocation("a_position"), backend::VertexFormat::FLOAT2, 0, false); - layout->setAttrib("a_texCoord", _program->getAttributeLocation("a_texCoord"), backend::VertexFormat::FLOAT2, + layout->setAttrib("a_position", _program->getVertexInputDesc("a_position"), rhi::VertexFormat::FLOAT2, 0, false); + layout->setAttrib("a_texCoord", _program->getVertexInputDesc("a_texCoord"), rhi::VertexFormat::FLOAT2, sizeof(float) * 2, false); // uniform属性の登録 @@ -75,10 +75,10 @@ void LAppSprite::RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* c layout->setStride(sizeof(float) * 4); - blendDescriptor->sourceRGBBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->destinationRGBBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; - blendDescriptor->sourceAlphaBlendFactor = ax::backend::BlendFactor::ONE; - blendDescriptor->destinationAlphaBlendFactor = ax::backend::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceRGBBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->destinationRGBBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; + blendDescriptor->sourceAlphaBlendFactor = ax::rhi::BlendFactor::ONE; + blendDescriptor->destinationAlphaBlendFactor = ax::rhi::BlendFactor::ONE_MINUS_SRC_ALPHA; blendDescriptor->blendEnabled = true; pipelineDescriptor->programState = programState; diff --git a/tests/live2d-tests/Source/LAppSprite.hpp b/tests/live2d-tests/Source/LAppSprite.hpp index 21da91710667..9f341367fa80 100644 --- a/tests/live2d-tests/Source/LAppSprite.hpp +++ b/tests/live2d-tests/Source/LAppSprite.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -9,7 +9,7 @@ #include "Rendering/axmol/CubismRenderer_Cocos2dx.hpp" #include "Rendering/axmol/CubismCommandBuffer_Cocos2dx.hpp" -#include "cocos2d.h" +#include "axmol/cocos2d.h" using namespace ax; @@ -44,7 +44,7 @@ class LAppSprite * @param[in] textureId テクスチャID * @param[in] programId シェーダID */ - LAppSprite(backend::Program* program); + LAppSprite(rhi::Program* program); /** * @brief デストラクタ @@ -55,7 +55,7 @@ class LAppSprite * @brief テクスチャIDを指定して描画する * */ - void RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, backend::TextureBackend* texture, float uvVertex[8]) const; + void RenderImmidiate(Csm::Rendering::CubismCommandBuffer_Cocos2dx* commandBuffer, rhi::Texture* texture, float uvVertex[8]) const; /** * @brief 色設定 @@ -71,6 +71,6 @@ class LAppSprite float _spriteColor[4]; ///< 表示カラー - ax::backend::Program* _program; + ax::rhi::Program* _program; }; diff --git a/tests/live2d-tests/Source/LAppView.cpp b/tests/live2d-tests/Source/LAppView.cpp index d82aa0736b8f..c60f110f667c 100644 --- a/tests/live2d-tests/Source/LAppView.cpp +++ b/tests/live2d-tests/Source/LAppView.cpp @@ -218,8 +218,8 @@ void LAppView::setDebugRectsNode(DrawNode* debugRects) void LAppView::drawDebugRects(LAppLive2DManager* manager) const { - const Color4F hitAreaColor = Color4F(1.0f, 0, 0, 0.2f); - const Color4F userDataAreaColor = Color4F(0, 0, 1.0f, 0.2f); + const Color hitAreaColor = Color(1.0f, 0, 0, 0.2f); + const Color userDataAreaColor = Color(0, 0, 1.0f, 0.2f); CubismMatrix44 projection; const Size window = Director::getInstance()->getWinSize(); diff --git a/tests/live2d-tests/Source/LAppView.hpp b/tests/live2d-tests/Source/LAppView.hpp index 7c384b27b705..1b27d8f5fe66 100644 --- a/tests/live2d-tests/Source/LAppView.hpp +++ b/tests/live2d-tests/Source/LAppView.hpp @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -11,8 +11,8 @@ #include #include #include "TouchManager.h" -#include "2d/Sprite.h" -#include "cocos2d.h" +#include "axmol/2d/Sprite.h" +#include "axmol/cocos2d.h" #include #include "LAppLive2DManager.hpp" diff --git a/tests/live2d-tests/Source/SampleScene.h b/tests/live2d-tests/Source/SampleScene.h index efc2cd776d38..290b1031fc5e 100644 --- a/tests/live2d-tests/Source/SampleScene.h +++ b/tests/live2d-tests/Source/SampleScene.h @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -8,7 +8,7 @@ #ifndef __SAMPLE_SCENE_H__ #define __SAMPLE_SCENE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include class LAppView; diff --git a/tests/live2d-tests/Source/TouchManager.h b/tests/live2d-tests/Source/TouchManager.h index b488421b52d3..e9eb804a5fda 100644 --- a/tests/live2d-tests/Source/TouchManager.h +++ b/tests/live2d-tests/Source/TouchManager.h @@ -1,4 +1,4 @@ -/** +/** * Copyright(c) Live2D Inc. All rights reserved. * * Use of this source code is governed by the Live2D Open Software license @@ -7,7 +7,7 @@ #pragma once -#include "cocos2d.h" +#include "axmol/cocos2d.h" class TouchManager { diff --git a/tests/live2d-tests/proj.android/app/AndroidManifest.xml b/tests/live2d-tests/proj.android/app/AndroidManifest.xml index 595e17e91d09..7c46ebb8bb2e 100644 --- a/tests/live2d-tests/proj.android/app/AndroidManifest.xml +++ b/tests/live2d-tests/proj.android/app/AndroidManifest.xml @@ -3,14 +3,14 @@ android:installLocation="auto"> - + - + - + @@ -20,7 +20,7 @@ android:screenOrientation="sensorLandscape" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:launchMode="singleTask" android:taskAffinity="" android:exported="true" > diff --git a/tests/live2d-tests/proj.android/app/build.gradle b/tests/live2d-tests/proj.android/app/build.gradle index 8316698e4c48..b906db592643 100644 --- a/tests/live2d-tests/proj.android/app/build.gradle +++ b/tests/live2d-tests/proj.android/app/build.gradle @@ -4,7 +4,7 @@ apply from: project(':libaxmol').projectDir.toString() + "/../dsl/axmol.gradle" // Resolve build profiles def buildProfiles = AxmolUtils.resolveBuildProfiles(project) -android { +android { def packageName = buildProfiles['packageName'] def cmakeVer = buildProfiles['cmakeVer'] def cmakeOptions = Eval.me(buildProfiles['cmakeOptions']) @@ -112,6 +112,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/tests/live2d-tests/proj.android/settings.gradle b/tests/live2d-tests/proj.android/settings.gradle index 5048881b2ec6..bbd97621be63 100644 --- a/tests/live2d-tests/proj.android/settings.gradle +++ b/tests/live2d-tests/proj.android/settings.gradle @@ -11,7 +11,7 @@ else { ENGINE_ROOT = settingsDir.getPath() + "/../../.." } -def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/core/platform/android/libaxmol'; +def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/axmol/platform/android/libaxmol'; include ':libaxmol' project(':libaxmol').projectDir = new File(ENGINE_JAVA_LIBPATH) diff --git a/tests/live2d-tests/proj.ios/AppController.mm b/tests/live2d-tests/proj.ios/AppController.mm index 406de6b29b76..388549873b90 100644 --- a/tests/live2d-tests/proj.ios/AppController.mm +++ b/tests/live2d-tests/proj.ios/AppController.mm @@ -24,8 +24,8 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import #import "AppController.h" -#import "axmol.h" -#import "platform/ios/EARenderView-ios.h" +#import "axmol/axmol.h" +#import "axmol/platform/ios/EARenderView-ios.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/tests/live2d-tests/proj.linux/main.cpp b/tests/live2d-tests/proj.linux/main.cpp index 3248f44f2649..f9a14fe33508 100644 --- a/tests/live2d-tests/proj.linux/main.cpp +++ b/tests/live2d-tests/proj.linux/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include #include diff --git a/tests/live2d-tests/proj.wasm/main.cpp b/tests/live2d-tests/proj.wasm/main.cpp index a274751783dd..011acbe41faa 100644 --- a/tests/live2d-tests/proj.wasm/main.cpp +++ b/tests/live2d-tests/proj.wasm/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/tests/live2d-tests/proj.win32/main.cpp b/tests/live2d-tests/proj.win32/main.cpp index ea374d3d2c27..7a5f2d3d3733 100644 --- a/tests/live2d-tests/proj.win32/main.cpp +++ b/tests/live2d-tests/proj.win32/main.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" // Uncomment to enable win32 console // #define USE_WIN32_CONSOLE @@ -46,7 +46,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL // create the application instance #ifdef USE_WIN32_CONSOLE -# include "platform/win32/EmbedConsole.h" +# include "axmol/platform/win32/EmbedConsole.h" #endif // create the application instance diff --git a/tests/live2d-tests/proj.win32/main.h b/tests/live2d-tests/proj.win32/main.h index c443e632957c..d8f5f9feb7b6 100644 --- a/tests/live2d-tests/proj.win32/main.h +++ b/tests/live2d-tests/proj.win32/main.h @@ -32,6 +32,6 @@ #include // C RunTime Header Files -#include "platform/StdC.h" +#include "axmol/platform/StdC.h" #endif // __MAIN_H__ diff --git a/tests/lua-tests/CMakeLists.txt b/tests/lua-tests/CMakeLists.txt index 70e1953e29c3..9b8088715849 100644 --- a/tests/lua-tests/CMakeLists.txt +++ b/tests/lua-tests/CMakeLists.txt @@ -52,7 +52,7 @@ if(NOT DEFINED BUILD_ENGINE_DONE) endif() if (NOT _AX_USE_PREBUILT) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() endif() diff --git a/tests/lua-tests/Content/src/AccelerometerTest/AccelerometerTest.lua b/tests/lua-tests/Content/src/AccelerometerTest/AccelerometerTest.lua index ad1ae23c9953..6a9759d6b296 100644 --- a/tests/lua-tests/Content/src/AccelerometerTest/AccelerometerTest.lua +++ b/tests/lua-tests/Content/src/AccelerometerTest/AccelerometerTest.lua @@ -3,17 +3,17 @@ local function AccelerometerMainLayer() local function title() return "AccelerometerTest" end - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:setAccelerometerEnabled(true) - local label = cc.Label:createWithTTF(title(), "fonts/arial.ttf", 32) + local label = ax.Label:createWithTTF(title(), "fonts/arial.ttf", 32) layer:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 50) ) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 50) ) - local ball = cc.Sprite:create("Images/ball.png") - ball:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y)) + local ball = ax.Sprite:create("Images/ball.png") + ball:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y)) layer:addChild(ball) local function accelerometerListener(event,x,y,z,timestamp) @@ -30,7 +30,7 @@ local function AccelerometerMainLayer() elseif ptNowX > maxX then ptNowX = maxX end - + local minY = math.floor(VisibleRect:bottom().y + ballSize.height / 2.0) local maxY = math.floor(VisibleRect:top().y - ballSize.height / 2.0) if ptNowY < minY then @@ -39,10 +39,10 @@ local function AccelerometerMainLayer() ptNowY = maxY end - target:setPosition(cc.p(ptNowX , ptNowY)) + target:setPosition(ax.p(ptNowX , ptNowY)) end - local listener = cc.EventListenerAcceleration:create(accelerometerListener) + local listener = ax.EventListenerAcceleration:create(accelerometerListener) layer:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, ball) end @@ -59,14 +59,14 @@ local function AccelerometerMainLayer() end layer:registerScriptHandler(onNodeEvent) - + return layer end function AccelerometerMain() cclog("AccelerometerMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(AccelerometerMainLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ActionManagerTest/ActionManagerTest.lua b/tests/lua-tests/Content/src/ActionManagerTest/ActionManagerTest.lua index 08abcc706052..b14bd9b45686 100644 --- a/tests/lua-tests/Content/src/ActionManagerTest/ActionManagerTest.lua +++ b/tests/lua-tests/Content/src/ActionManagerTest/ActionManagerTest.lua @@ -1,7 +1,7 @@ local kTagNode = 0 local kTagGrossini = 1 local kTagSequence = 2 -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() -------------------------------------------------------------------- -- -- Test1 @@ -11,21 +11,21 @@ local scheduler = cc.Director:getInstance():getScheduler() local function CrashTest() local ret = createTestLayer("Test 1. Should not crash") - local child = cc.Sprite:create(s_pPathGrossini) + local child = ax.Sprite:create(s_pPathGrossini) child:setPosition( 200,200 ) ret:addChild(child, 1) --Sum of all action's duration is 1.5 second. - child:runAction(cc.RotateBy:create(1.5, 90)) - child:runAction(cc.Sequence:create(cc.DelayTime:create(1.4),cc.FadeOut:create(1.1))) - + child:runAction(ax.RotateBy:create(1.5, 90)) + child:runAction(ax.Sequence:create(ax.DelayTime:create(1.4),ax.FadeOut:create(1.1))) + local function removeThis() ret:getParent():removeChild(ret, true) Helper.nextAction() end --After 1.5 second, self will be removed. - ret:runAction( cc.Sequence:create(cc.DelayTime:create(1.4),cc.CallFunc:create(removeThis))) + ret:runAction( ax.Sequence:create(ax.DelayTime:create(1.4),ax.CallFunc:create(removeThis))) return ret end @@ -37,14 +37,14 @@ end -------------------------------------------------------------------- local function LogicTest() local ret = createTestLayer("Logic test") - local grossini = cc.Sprite:create(s_pPathGrossini) + local grossini = ax.Sprite:create(s_pPathGrossini) ret:addChild(grossini, 0, 2) grossini:setPosition(200,200) local function bugMe(node) node:stopAllActions() --After this stop next action not working, if remove this stop everything is working - node:runAction(cc.ScaleTo:create(2, 2)) + node:runAction(ax.ScaleTo:create(2, 2)) end - grossini:runAction( cc.Sequence:create(cc.MoveBy:create(1, cc.p(150,0)) ,cc.CallFunc:create(bugMe))) + grossini:runAction( ax.Sequence:create(ax.MoveBy:create(1, ax.p(150,0)) ,ax.CallFunc:create(bugMe))) return ret end @@ -61,25 +61,25 @@ local function PauseTest() scheduler:unscheduleScriptEntry(schedulerEntry) schedulerEntry = nil local node = ret:getChildByTag( kTagGrossini ) - local pDirector = cc.Director:getInstance() + local pDirector = ax.Director:getInstance() pDirector:getActionManager():resumeTarget(node) end local function onNodeEvent(event) if event == "enter" then - local s = cc.Director:getInstance():getWinSize() - local l = cc.Label:createWithTTF("After 3 seconds grossini should move", "fonts/Thonburi.ttf", 16) + local s = ax.Director:getInstance():getWinSize() + local l = ax.Label:createWithTTF("After 3 seconds grossini should move", "fonts/Thonburi.ttf", 16) ret:addChild(l) - l:setAnchorPoint(cc.p(0.5, 0.5)) - l:setPosition( cc.p(s.width / 2, 245) ) - - local grossini = cc.Sprite:create(s_pPathGrossini) + l:setAnchorPoint(ax.p(0.5, 0.5)) + l:setPosition( ax.p(s.width / 2, 245) ) + + local grossini = ax.Sprite:create(s_pPathGrossini) ret:addChild(grossini, 0, kTagGrossini) - grossini:setPosition(cc.p(200,200)) - - local action = cc.MoveBy:create(1, cc.p(150,0)) + grossini:setPosition(ax.p(200,200)) - local pDirector = cc.Director:getInstance() + local action = ax.MoveBy:create(1, ax.p(150,0)) + + local pDirector = ax.Director:getInstance() pDirector:getActionManager():addAction(action, grossini, true) schedulerEntry = scheduler:scheduleScriptFunc(unpause, 3.0, false) @@ -102,23 +102,23 @@ end -------------------------------------------------------------------- local function RemoveTest() local ret = createTestLayer("Remove Test") - local l = cc.Label:createWithTTF("Should not crash", "fonts/Thonburi.ttf", 16) - local s = cc.Director:getInstance():getWinSize() + local l = ax.Label:createWithTTF("Should not crash", "fonts/Thonburi.ttf", 16) + local s = ax.Director:getInstance():getWinSize() ret:addChild(l) - l:setAnchorPoint(cc.p(0.5, 0.5)) - l:setPosition( cc.p(s.width / 2, 245)) + l:setAnchorPoint(ax.p(0.5, 0.5)) + l:setPosition( ax.p(s.width / 2, 245)) - local pMove = cc.MoveBy:create(2, cc.p(200, 0)) + local pMove = ax.MoveBy:create(2, ax.p(200, 0)) local function stopAction() local pSprite = ret:getChildByTag(kTagGrossini) pSprite:stopActionByTag(kTagSequence) end - local callfunc = cc.CallFunc:create(stopAction) - local pSequence = cc.Sequence:create(pMove,callfunc) + local callfunc = ax.CallFunc:create(stopAction) + local pSequence = ax.Sequence:create(pMove,callfunc) pSequence:setTag(kTagSequence) - local pChild = cc.Sprite:create(s_pPathGrossini) + local pChild = ax.Sprite:create(s_pPathGrossini) pChild:setPosition( 200, 200 ) ret:addChild(pChild, 1, kTagGrossini) @@ -140,28 +140,28 @@ local function ResumeTest() scheduler:unscheduleScriptEntry(schedulerEntry) schedulerEntry = nil local pGrossini = ret:getChildByTag(kTagGrossini) - local pDirector = cc.Director:getInstance() + local pDirector = ax.Director:getInstance() pDirector:getActionManager():resumeTarget(pGrossini) end local function onNodeEvent(event) if event == "enter" then - local l = cc.Label:createWithTTF("Grossini only rotate/scale in 3 seconds", "fonts/Thonburi.ttf", 16) + local l = ax.Label:createWithTTF("Grossini only rotate/scale in 3 seconds", "fonts/Thonburi.ttf", 16) ret:addChild(l) - local s = cc.Director:getInstance():getWinSize() - l:setAnchorPoint(cc.p(0.5, 0.5)) + local s = ax.Director:getInstance():getWinSize() + l:setAnchorPoint(ax.p(0.5, 0.5)) l:setPosition( s.width / 2, 245) - local pGrossini = cc.Sprite:create(s_pPathGrossini) + local pGrossini = ax.Sprite:create(s_pPathGrossini) ret:addChild(pGrossini, 0, kTagGrossini) pGrossini:setPosition(200,200) - pGrossini:runAction(cc.ScaleBy:create(2, 2)) + pGrossini:runAction(ax.ScaleBy:create(2, 2)) - local pDirector = cc.Director:getInstance() + local pDirector = ax.Director:getInstance() pDirector:getActionManager():pauseTarget(pGrossini) - pGrossini:runAction(cc.RotateBy:create(2, 360)) + pGrossini:runAction(ax.RotateBy:create(2, 360)) schedulerEntry = scheduler:scheduleScriptFunc(resumeGrossini, 3.0, false) elseif event == "exit" then @@ -180,8 +180,8 @@ end function ActionManagerTestMain() cclog("ActionManagerTestMain") Helper.index = 1 - cc.Director:getInstance():getRenderer():setDepthTest(true) - local scene = cc.Scene:create() + ax.Director:getInstance():getRenderer():setDepthTest(true) + local scene = ax.Scene:create() Helper.createFunctionTable = { CrashTest, @@ -191,7 +191,7 @@ function ActionManagerTestMain() ResumeTest } Helper.index = 1 - + scene:addChild(CrashTest()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ActionsEaseTest/ActionsEaseTest.lua b/tests/lua-tests/Content/src/ActionsEaseTest/ActionsEaseTest.lua index b85ed0308632..bf07b302e3bd 100644 --- a/tests/lua-tests/Content/src/ActionsEaseTest/ActionsEaseTest.lua +++ b/tests/lua-tests/Content/src/ActionsEaseTest/ActionsEaseTest.lua @@ -2,37 +2,37 @@ local kTagAction1 = 1 local kTagAction2 = 2 local kTagSlider = 1 -local s = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local s = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local function createSimpleMoveBy() - return cc.MoveBy:create(3, cc.p(s.width - 130, 0)) + return ax.MoveBy:create(3, ax.p(s.width - 130, 0)) end local function createSimpleDelayTime() - return cc.DelayTime:create(0.25) + return ax.DelayTime:create(0.25) end local function positionForTwo() - grossini:setPosition(cc.p(60, s.height * 1 / 5)) - tamara:setPosition(cc.p(60, s.height * 4 / 5)) + grossini:setPosition(ax.p(60, s.height * 1 / 5)) + tamara:setPosition(ax.p(60, s.height * 4 / 5)) kathia:setVisible(false) end local function getBaseLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() - grossini = cc.Sprite:create(s_pPathGrossini) - tamara = cc.Sprite:create(s_pPathSister1) - kathia = cc.Sprite:create(s_pPathSister2) + grossini = ax.Sprite:create(s_pPathGrossini) + tamara = ax.Sprite:create(s_pPathSister1) + kathia = ax.Sprite:create(s_pPathSister2) layer:addChild(grossini, 3) layer:addChild(kathia, 2) layer:addChild(tamara, 1) - grossini:setPosition(cc.p(60, s.height * 1 / 5)) - kathia:setPosition(cc.p(60, s.height * 2.5 / 5)) - tamara:setPosition(cc.p(60, s.height * 4 / 5)) + grossini:setPosition(ax.p(60, s.height * 1 / 5)) + kathia:setPosition(ax.p(60, s.height * 2.5 / 5)) + tamara:setPosition(ax.p(60, s.height * 4 / 5)) Helper.initWithLayer(layer) @@ -65,22 +65,22 @@ local function SpriteEase() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseIn:create(createSimpleMoveBy(), 2.5) + local move_ease_in = ax.EaseIn:create(createSimpleMoveBy(), 2.5) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseOut:create(createSimpleMoveBy(), 2.5) + local move_ease_out = ax.EaseOut:create(createSimpleMoveBy(), 2.5) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease_in,createSimpleDelayTime(),move_ease_in_back,createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out,createSimpleDelayTime(),move_ease_out_back,createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease_in,createSimpleDelayTime(),move_ease_in_back,createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out,createSimpleDelayTime(),move_ease_out_back,createSimpleDelayTime()) - local a2 = grossini:runAction(cc.RepeatForever:create(seq1)) + local a2 = grossini:runAction(ax.RepeatForever:create(seq1)) a2:setTag(1) - local a1 = tamara:runAction(cc.RepeatForever:create(seq2)) + local a1 = tamara:runAction(ax.RepeatForever:create(seq2)) a1:setTag(1) - local a = kathia:runAction(cc.RepeatForever:create(seq3)) + local a = kathia:runAction(ax.RepeatForever:create(seq3)) a:setTag(1) layer:registerScriptHandler(SpriteEase_onEnterOrExit) @@ -97,23 +97,23 @@ local function SpriteEaseInOut() local move = createSimpleMoveBy() - local move_ease_inout1 = cc.EaseInOut:create(createSimpleMoveBy(), 0.65) + local move_ease_inout1 = ax.EaseInOut:create(createSimpleMoveBy(), 0.65) local move_ease_inout_back1 = move_ease_inout1:reverse() - local move_ease_inout2 = cc.EaseInOut:create(createSimpleMoveBy(), 1.35) + local move_ease_inout2 = ax.EaseInOut:create(createSimpleMoveBy(), 1.35) local move_ease_inout_back2 = move_ease_inout2:reverse() - local move_ease_inout3 = cc.EaseInOut:create(createSimpleMoveBy(), 1.0) + local move_ease_inout3 = ax.EaseInOut:create(createSimpleMoveBy(), 1.0) local move_ease_inout_back3 = move_ease_inout3:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move_ease_inout1,delay,move_ease_inout_back1,createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease_inout2,createSimpleDelayTime(),move_ease_inout_back2,createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_inout3, createSimpleDelayTime(), move_ease_inout_back3, createSimpleDelayTime() ) + local seq1 = ax.Sequence:create(move_ease_inout1,delay,move_ease_inout_back1,createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease_inout2,createSimpleDelayTime(),move_ease_inout_back2,createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_inout3, createSimpleDelayTime(), move_ease_inout_back3, createSimpleDelayTime() ) - tamara:runAction(cc.RepeatForever:create(seq1)) - kathia:runAction(cc.RepeatForever:create(seq2)) - grossini:runAction(cc.RepeatForever:create(seq3)) + tamara:runAction(ax.RepeatForever:create(seq1)) + kathia:runAction(ax.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("EaseInOut and rates") return layer @@ -128,20 +128,20 @@ local function SpriteEaseExponential() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseExponentialIn:create(createSimpleMoveBy()) + local move_ease_in = ax.EaseExponentialIn:create(createSimpleMoveBy()) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseExponentialOut:create(createSimpleMoveBy()) + local move_ease_out = ax.EaseExponentialOut:create(createSimpleMoveBy()) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) - kathia:runAction(cc.RepeatForever:create(seq3)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) + kathia:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("ExpIn - ExpOut actions") return layer @@ -156,17 +156,17 @@ local function SpriteEaseExponentialInOut() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease = cc.EaseExponentialInOut:create(createSimpleMoveBy()) + local move_ease = ax.EaseExponentialInOut:create(createSimpleMoveBy()) local move_ease_back = move_ease:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime() ) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime() ) positionForTwo() - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) Helper.titleLabel:setString("EaseExponentialInOut action") return layer @@ -181,20 +181,20 @@ local function SpriteEaseSine() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseSineIn:create(createSimpleMoveBy()) + local move_ease_in = ax.EaseSineIn:create(createSimpleMoveBy()) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseSineOut:create(createSimpleMoveBy()) + local move_ease_out = ax.EaseSineOut:create(createSimpleMoveBy()) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) - local seq2 = cc.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back,createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) + local seq2 = ax.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back,createSimpleDelayTime()) - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) - kathia:runAction(cc.RepeatForever:create(seq3)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) + kathia:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("EaseSineIn - EaseSineOut") return layer @@ -209,17 +209,17 @@ local function SpriteEaseSineInOut() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease = cc.EaseSineInOut:create(createSimpleMoveBy()) + local move_ease = ax.EaseSineInOut:create(createSimpleMoveBy()) local move_ease_back = move_ease:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) positionForTwo() - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) Helper.titleLabel:setString("EaseSineInOut action") return layer @@ -234,20 +234,20 @@ local function SpriteEaseElastic() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseElasticIn:create(createSimpleMoveBy()) + local move_ease_in = ax.EaseElasticIn:create(createSimpleMoveBy()) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseElasticOut:create(createSimpleMoveBy()) + local move_ease_out = ax.EaseElasticOut:create(createSimpleMoveBy()) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) - local seq2 = cc.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) + local seq2 = ax.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) - kathia:runAction(cc.RepeatForever:create(seq3)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) + kathia:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("Elastic In - Out actions") return layer @@ -261,23 +261,23 @@ local function SpriteEaseElasticInOut() local move = createSimpleMoveBy() - local move_ease_inout1 = cc.EaseElasticInOut:create(createSimpleMoveBy(), 0.3) + local move_ease_inout1 = ax.EaseElasticInOut:create(createSimpleMoveBy(), 0.3) local move_ease_inout_back1 = move_ease_inout1:reverse() - local move_ease_inout2 = cc.EaseElasticInOut:create(createSimpleMoveBy(), 0.45) + local move_ease_inout2 = ax.EaseElasticInOut:create(createSimpleMoveBy(), 0.45) local move_ease_inout_back2 = move_ease_inout2:reverse() - local move_ease_inout3 = cc.EaseElasticInOut:create(createSimpleMoveBy(), 0.6) + local move_ease_inout3 = ax.EaseElasticInOut:create(createSimpleMoveBy(), 0.6) local move_ease_inout_back3 = move_ease_inout3:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move_ease_inout1, delay, move_ease_inout_back1, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease_inout2, createSimpleDelayTime(), move_ease_inout_back2, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_inout3, createSimpleDelayTime(), move_ease_inout_back3, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move_ease_inout1, delay, move_ease_inout_back1, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease_inout2, createSimpleDelayTime(), move_ease_inout_back2, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_inout3, createSimpleDelayTime(), move_ease_inout_back3, createSimpleDelayTime()) - tamara:runAction(cc.RepeatForever:create(seq1)) - kathia:runAction(cc.RepeatForever:create(seq2)) - grossini:runAction(cc.RepeatForever:create(seq3)) + tamara:runAction(ax.RepeatForever:create(seq1)) + kathia:runAction(ax.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("EaseElasticInOut action") return layer @@ -292,20 +292,20 @@ local function SpriteEaseBounce() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseBounceIn:create(createSimpleMoveBy()) + local move_ease_in = ax.EaseBounceIn:create(createSimpleMoveBy()) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseBounceOut:create(createSimpleMoveBy()) + local move_ease_out = ax.EaseBounceOut:create(createSimpleMoveBy()) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) - local seq2 = cc.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime() ) + local seq2 = ax.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) - kathia:runAction(cc.RepeatForever:create(seq3)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) + kathia:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("Bounce In - Out actions") return layer @@ -320,17 +320,17 @@ local function SpriteEaseBounceInOut() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease = cc.EaseBounceInOut:create(createSimpleMoveBy()) + local move_ease = ax.EaseBounceInOut:create(createSimpleMoveBy()) local move_ease_back = move_ease:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease, createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) positionForTwo() - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) Helper.titleLabel:setString("EaseBounceInOut action") return layer @@ -345,20 +345,20 @@ local function SpriteEaseBack() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease_in = cc.EaseBackIn:create(createSimpleMoveBy()) + local move_ease_in = ax.EaseBackIn:create(createSimpleMoveBy()) local move_ease_in_back = move_ease_in:reverse() - local move_ease_out = cc.EaseBackOut:create(createSimpleMoveBy()) + local move_ease_out = ax.EaseBackOut:create(createSimpleMoveBy()) local move_ease_out_back = move_ease_out:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) - local seq3 = cc.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease_in, createSimpleDelayTime(), move_ease_in_back, createSimpleDelayTime()) + local seq3 = ax.Sequence:create(move_ease_out, createSimpleDelayTime(), move_ease_out_back, createSimpleDelayTime()) - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) - kathia:runAction(cc.RepeatForever:create(seq3)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) + kathia:runAction(ax.RepeatForever:create(seq3)) Helper.titleLabel:setString("Back In - Out actions") return layer @@ -373,17 +373,17 @@ local function SpriteEaseBackInOut() local move = createSimpleMoveBy() local move_back = move:reverse() - local move_ease = cc.EaseBackInOut:create(createSimpleMoveBy()) + local move_ease = ax.EaseBackInOut:create(createSimpleMoveBy()) local move_ease_back = move_ease:reverse() local delay = createSimpleDelayTime() - local seq1 = cc.Sequence:create(move, delay, move_back, createSimpleDelayTime()) - local seq2 = cc.Sequence:create(move_ease,createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) + local seq1 = ax.Sequence:create(move, delay, move_back, createSimpleDelayTime()) + local seq2 = ax.Sequence:create(move_ease,createSimpleDelayTime(), move_ease_back, createSimpleDelayTime()) positionForTwo() - grossini:runAction(cc.RepeatForever:create(seq1)) - tamara:runAction(cc.RepeatForever:create(seq2)) + grossini:runAction(ax.RepeatForever:create(seq1)) + tamara:runAction(ax.RepeatForever:create(seq2)) Helper.titleLabel:setString("EaseBackInOut action") return layer @@ -414,22 +414,22 @@ end local function SpeedTest() local layer = getBaseLayer() - local jump1 = cc.JumpBy:create(4, cc.p(- s.width + 80, 0), 100, 4) + local jump1 = ax.JumpBy:create(4, ax.p(- s.width + 80, 0), 100, 4) local jump2 = jump1:reverse() - local rot1 = cc.RotateBy:create(4, 360 * 2) + local rot1 = ax.RotateBy:create(4, 360 * 2) local rot2 = rot1:reverse() - local seq3_1 = cc.Sequence:create(jump2, jump1) - local seq3_2 = cc.Sequence:create(rot1, rot2) + local seq3_1 = ax.Sequence:create(jump2, jump1) + local seq3_2 = ax.Sequence:create(rot1, rot2) - local spawn = cc.Spawn:create(seq3_1, seq3_2) - SpeedTest_action1 = cc.Speed:create(cc.RepeatForever:create(spawn), 1.0) + local spawn = ax.Spawn:create(seq3_1, seq3_2) + SpeedTest_action1 = ax.Speed:create(ax.RepeatForever:create(spawn), 1.0) local spawn2 = spawn:clone() - SpeedTest_action2 = cc.Speed:create(cc.RepeatForever:create(spawn2), 1.0) + SpeedTest_action2 = ax.Speed:create(ax.RepeatForever:create(spawn2), 1.0) local spawn3 = spawn:clone() - SpeedTest_action3 = cc.Speed:create(cc.RepeatForever:create(spawn3), 1.0) + SpeedTest_action3 = ax.Speed:create(ax.RepeatForever:create(spawn3), 1.0) grossini:runAction(SpeedTest_action2) tamara:runAction(SpeedTest_action3) @@ -442,7 +442,7 @@ local function SpeedTest() end function EaseActionsTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() cclog("EaseActionsTest") Helper.createFunctionTable = { @@ -454,9 +454,9 @@ function EaseActionsTest() SpriteEaseSineInOut, SpriteEaseElastic, SpriteEaseElasticInOut, - SpriteEaseBounce, - SpriteEaseBounceInOut, - SpriteEaseBack, + SpriteEaseBounce, + SpriteEaseBounceInOut, + SpriteEaseBack, SpriteEaseBackInOut, SpeedTest } diff --git a/tests/lua-tests/Content/src/ActionsProgressTest/ActionsProgressTest.lua b/tests/lua-tests/Content/src/ActionsProgressTest/ActionsProgressTest.lua index 73183450ceba..7ee5d7a0866c 100644 --- a/tests/lua-tests/Content/src/ActionsProgressTest/ActionsProgressTest.lua +++ b/tests/lua-tests/Content/src/ActionsProgressTest/ActionsProgressTest.lua @@ -1,28 +1,28 @@ -local s = cc.Director:getInstance():getWinSize() +local s = ax.Director:getInstance():getWinSize() ------------------------------------ -- SpriteProgressToRadial ------------------------------------ local function SpriteProgressToRadial() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to1 = cc.ProgressTo:create(2, 100) - local to2 = cc.ProgressTo:create(2, 100) + local to1 = ax.ProgressTo:create(2, 100) + local to2 = ax.ProgressTo:create(2, 100) - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister1)) - left:setType(cc.PROGRESS_TIMER_TYPE_RADIAL) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(to1)) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister1)) + left:setType(ax.PROGRESS_TIMER_TYPE_RADIAL) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(to1)) layer:addChild(left) - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathBlock)) - right:setType(cc.PROGRESS_TIMER_TYPE_RADIAL) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathBlock)) + right:setType(ax.PROGRESS_TIMER_TYPE_RADIAL) -- Makes the ridial CCW right:setReverseDirection(true) - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(to2)) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(to2)) layer:addChild(right) Helper.subtitleLabel:setString("ProgressTo Radial") @@ -33,30 +33,30 @@ end -- SpriteProgressToHorizontal ------------------------------------ local function SpriteProgressToHorizontal() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to1 = cc.ProgressTo:create(2, 100) - local to2 = cc.ProgressTo:create(2, 100) + local to1 = ax.ProgressTo:create(2, 100) + local to2 = ax.ProgressTo:create(2, 100) - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister1)) - left:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister1)) + left:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the left since the midpoint is 0 for the x - left:setMidpoint(cc.p(0, 0)) + left:setMidpoint(ax.p(0, 0)) -- Setup for a horizontal bar since the bar change rate is 0 for y meaning no vertical change - left:setBarChangeRate(cc.p(1, 0)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(to1)) + left:setBarChangeRate(ax.p(1, 0)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(to1)) layer:addChild(left) - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - right:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + right:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the left since the midpoint is 1 for the x - right:setMidpoint(cc.p(1, 0)) + right:setMidpoint(ax.p(1, 0)) -- Setup for a horizontal bar since the bar change rate is 0 for y meaning no vertical change - right:setBarChangeRate(cc.p(1, 0)) - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(to2)) + right:setBarChangeRate(ax.p(1, 0)) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(to2)) layer:addChild(right) Helper.subtitleLabel:setString("ProgressTo Horizontal") @@ -67,31 +67,31 @@ end -- SpriteProgressToVertical ------------------------------------ local function SpriteProgressToVertical() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to1 = cc.ProgressTo:create(2, 100) - local to2 = cc.ProgressTo:create(2, 100) + local to1 = ax.ProgressTo:create(2, 100) + local to2 = ax.ProgressTo:create(2, 100) - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister1)) - left:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister1)) + left:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - left:setMidpoint(cc.p(0,0)) + left:setMidpoint(ax.p(0,0)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - left:setBarChangeRate(cc.p(0, 1)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(to1)) + left:setBarChangeRate(ax.p(0, 1)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(to1)) layer:addChild(left) - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - right:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + right:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - right:setMidpoint(cc.p(0, 1)) + right:setMidpoint(ax.p(0, 1)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - right:setBarChangeRate(cc.p(0, 1)) - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(to2)) + right:setBarChangeRate(ax.p(0, 1)) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(to2)) layer:addChild(right) Helper.subtitleLabel:setString("ProgressTo Vertical") @@ -102,30 +102,30 @@ end -- SpriteProgressToRadialMidpointChanged ------------------------------------ local function SpriteProgressToRadialMidpointChanged() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local action = cc.ProgressTo:create(2, 100) + local action = ax.ProgressTo:create(2, 100) -- Our image on the left should be a radial progress indicator, clockwise - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathBlock)) - left:setType(cc.PROGRESS_TIMER_TYPE_RADIAL) - left:setMidpoint(cc.p(0.25, 0.75)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(cc.ProgressTo:create(2, 100))) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathBlock)) + left:setType(ax.PROGRESS_TIMER_TYPE_RADIAL) + left:setMidpoint(ax.p(0.25, 0.75)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(ax.ProgressTo:create(2, 100))) layer:addChild(left) -- Our image on the left should be a radial progress indicator, counter clockwise - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathBlock)) - right:setType(cc.PROGRESS_TIMER_TYPE_RADIAL) - right:setMidpoint(cc.p(0.75, 0.25)) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathBlock)) + right:setType(ax.PROGRESS_TIMER_TYPE_RADIAL) + right:setMidpoint(ax.p(0.75, 0.25)) --[[ Note the reverse property (default=NO) is only added to the right image. That's how we get a counter clockwise progress. ]] - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(cc.ProgressTo:create(2, 100))) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(ax.ProgressTo:create(2, 100))) layer:addChild(right) Helper.subtitleLabel:setString("Radial w/ Different Midpoints") @@ -136,40 +136,40 @@ end -- SpriteProgressBarVarious ------------------------------------ local function SpriteProgressBarVarious() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to = cc.ProgressTo:create(2, 100) + local to = ax.ProgressTo:create(2, 100) - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister1)) - left:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister1)) + left:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - left:setMidpoint(cc.p(0.5, 0.5)) + left:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - left:setBarChangeRate(cc.p(1, 0)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(cc.ProgressTo:create(2, 100))) + left:setBarChangeRate(ax.p(1, 0)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(ax.ProgressTo:create(2, 100))) layer:addChild(left) - local middle = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - middle:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local middle = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + middle:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - middle:setMidpoint(cc.p(0.5, 0.5)) + middle:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - middle:setBarChangeRate(cc.p(1, 1)) - middle:setPosition(cc.p(s.width/2, s.height/2)) - middle:runAction(cc.RepeatForever:create(cc.ProgressTo:create(2, 100))) + middle:setBarChangeRate(ax.p(1, 1)) + middle:setPosition(ax.p(s.width/2, s.height/2)) + middle:runAction(ax.RepeatForever:create(ax.ProgressTo:create(2, 100))) layer:addChild(middle) - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - right:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + right:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - right:setMidpoint(cc.p(0.5, 0.5)) + right:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - right:setBarChangeRate(cc.p(0, 1)) - right:setPosition(cc.p(s.width-100, s.height/2)) - right:runAction(cc.RepeatForever:create(cc.ProgressTo:create(2, 100))) + right:setBarChangeRate(ax.p(0, 1)) + right:setPosition(ax.p(s.width-100, s.height/2)) + right:runAction(ax.RepeatForever:create(ax.ProgressTo:create(2, 100))) layer:addChild(right) Helper.subtitleLabel:setString("ProgressTo Bar Mid") @@ -180,54 +180,54 @@ end -- SpriteProgressBarTintAndFade ------------------------------------ local function SpriteProgressBarTintAndFade() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to = cc.ProgressTo:create(6, 100) - local tint = cc.Sequence:create(cc.TintTo:create(1, 255, 0, 0), cc.TintTo:create(1, 0, 255, 0), cc.TintTo:create(1, 0, 0, 255)) - local fade = cc.Sequence:create(cc.FadeTo:create(1.0, 0),cc.FadeTo:create(1.0, 255)) - local left = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister1)) - left:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local to = ax.ProgressTo:create(6, 100) + local tint = ax.Sequence:create(ax.TintTo:create(1, 255, 0, 0), ax.TintTo:create(1, 0, 255, 0), ax.TintTo:create(1, 0, 0, 255)) + local fade = ax.Sequence:create(ax.FadeTo:create(1.0, 0),ax.FadeTo:create(1.0, 255)) + local left = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister1)) + left:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - left:setMidpoint(cc.p(0.5, 0.5)) + left:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - left:setBarChangeRate(cc.p(1, 0)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) - left:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.TintTo:create(1, 255, 0, 0), cc.TintTo:create(1, 0, 255, 0), cc.TintTo:create(1, 0, 0, 255)))) + left:setBarChangeRate(ax.p(1, 0)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) + left:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.TintTo:create(1, 255, 0, 0), ax.TintTo:create(1, 0, 255, 0), ax.TintTo:create(1, 0, 0, 255)))) layer:addChild(left) - left:addChild(cc.Label:createWithTTF("Tint", "fonts/Marker Felt.ttf", 20.0)) + left:addChild(ax.Label:createWithTTF("Tint", "fonts/Marker Felt.ttf", 20.0)) - local middle = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - middle:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local middle = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + middle:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - middle:setMidpoint(cc.p(0.5, 0.5)) + middle:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - middle:setBarChangeRate(cc.p(1, 1)) - middle:setPosition(cc.p(s.width / 2, s.height / 2)) - middle:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) + middle:setBarChangeRate(ax.p(1, 1)) + middle:setPosition(ax.p(s.width / 2, s.height / 2)) + middle:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) - local fade2 = cc.Sequence:create(cc.FadeTo:create(1.0, 0), cc.FadeTo:create(1.0, 255)) - middle:runAction(cc.RepeatForever:create(fade2)) + local fade2 = ax.Sequence:create(ax.FadeTo:create(1.0, 0), ax.FadeTo:create(1.0, 255)) + middle:runAction(ax.RepeatForever:create(fade2)) layer:addChild(middle) - middle:addChild(cc.Label:createWithTTF("Fade", "fonts/Marker Felt.ttf", 20.0)) + middle:addChild(ax.Label:createWithTTF("Fade", "fonts/Marker Felt.ttf", 20.0)) - local right = cc.ProgressTimer:create(cc.Sprite:create(s_pPathSister2)) - right:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local right = ax.ProgressTimer:create(ax.Sprite:create(s_pPathSister2)) + right:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - right:setMidpoint(cc.p(0.5, 0.5)) + right:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - right:setBarChangeRate(cc.p(0, 1)) - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) - right:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.TintTo:create(1, 255, 0, 0), cc.TintTo:create(1, 0, 255, 0), cc.TintTo:create(1, 0, 0, 255)))) - right:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(1.0, 0), cc.FadeTo:create(1.0, 255)))) + right:setBarChangeRate(ax.p(0, 1)) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) + right:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.TintTo:create(1, 255, 0, 0), ax.TintTo:create(1, 0, 255, 0), ax.TintTo:create(1, 0, 0, 255)))) + right:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(1.0, 0), ax.FadeTo:create(1.0, 255)))) layer:addChild(right) - right:addChild(cc.Label:createWithTTF("Tint and Fade", "fonts/Marker Felt.ttf", 20.0)) + right:addChild(ax.Label:createWithTTF("Tint and Fade", "fonts/Marker Felt.ttf", 20.0)) Helper.subtitleLabel:setString("ProgressTo Bar Mid") return layer @@ -237,41 +237,41 @@ end -- SpriteProgressWithSpriteFrame ------------------------------------ local function SpriteProgressWithSpriteFrame() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local to = cc.ProgressTo:create(6, 100) + local to = ax.ProgressTo:create(6, 100) - cc.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini.plist") + ax.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini.plist") - local left = cc.ProgressTimer:create(cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png")) - left:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local left = ax.ProgressTimer:create(ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png")) + left:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - left:setMidpoint(cc.p(0.5, 0.5)) + left:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - left:setBarChangeRate(cc.p(1, 0)) - left:setPosition(cc.p(100, s.height / 2)) - left:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) + left:setBarChangeRate(ax.p(1, 0)) + left:setPosition(ax.p(100, s.height / 2)) + left:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) layer:addChild(left) - local middle = cc.ProgressTimer:create(cc.Sprite:createWithSpriteFrameName("grossini_dance_02.png")) - middle:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local middle = ax.ProgressTimer:create(ax.Sprite:createWithSpriteFrameName("grossini_dance_02.png")) + middle:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - middle:setMidpoint(cc.p(0.5, 0.5)) + middle:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - middle:setBarChangeRate(cc.p(1, 1)) - middle:setPosition(cc.p(s.width / 2, s.height / 2)) - middle:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) + middle:setBarChangeRate(ax.p(1, 1)) + middle:setPosition(ax.p(s.width / 2, s.height / 2)) + middle:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) layer:addChild(middle) - local right = cc.ProgressTimer:create(cc.Sprite:createWithSpriteFrameName("grossini_dance_03.png")) - right:setType(cc.PROGRESS_TIMER_TYPE_BAR) + local right = ax.ProgressTimer:create(ax.Sprite:createWithSpriteFrameName("grossini_dance_03.png")) + right:setType(ax.PROGRESS_TIMER_TYPE_BAR) -- Setup for a bar starting from the bottom since the midpoint is 0 for the y - right:setMidpoint(cc.p(0.5, 0.5)) + right:setMidpoint(ax.p(0.5, 0.5)) -- Setup for a vertical bar since the bar change rate is 0 for x meaning no horizontal change - right:setBarChangeRate(cc.p(0, 1)) - right:setPosition(cc.p(s.width - 100, s.height / 2)) - right:runAction(cc.RepeatForever:create(cc.ProgressTo:create(6, 100))) + right:setBarChangeRate(ax.p(0, 1)) + right:setPosition(ax.p(s.width - 100, s.height / 2)) + right:runAction(ax.RepeatForever:create(ax.ProgressTo:create(6, 100))) layer:addChild(right) Helper.subtitleLabel:setString("Progress With Sprite Frame") @@ -279,7 +279,7 @@ local function SpriteProgressWithSpriteFrame() end function ProgressActionsTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { SpriteProgressToRadial, @@ -295,5 +295,5 @@ function ProgressActionsTest() scene:addChild(SpriteProgressToRadial()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end diff --git a/tests/lua-tests/Content/src/ActionsTest/ActionsTest.lua b/tests/lua-tests/Content/src/ActionsTest/ActionsTest.lua index 82112428c64d..f69f3a87a1f8 100644 --- a/tests/lua-tests/Content/src/ActionsTest/ActionsTest.lua +++ b/tests/lua-tests/Content/src/ActionsTest/ActionsTest.lua @@ -1,17 +1,17 @@ -local size = cc.Director:getInstance():getWinSize() +local size = ax.Director:getInstance():getWinSize() local function initWithLayer(layer) - grossini = cc.Sprite:create(s_pPathGrossini) - tamara = cc.Sprite:create(s_pPathSister1) - kathia = cc.Sprite:create(s_pPathSister2) + grossini = ax.Sprite:create(s_pPathGrossini) + tamara = ax.Sprite:create(s_pPathSister1) + kathia = ax.Sprite:create(s_pPathSister2) layer:addChild(grossini, 1) layer:addChild(tamara, 2) layer:addChild(kathia, 3) - grossini:setPosition(cc.p(size.width / 2, size.height / 3)) - tamara:setPosition(cc.p(size.width / 2, 2 * size.height / 3)) - kathia:setPosition(cc.p(size.width / 2, size.height / 2)) + grossini:setPosition(ax.p(size.width / 2, size.height / 3)) + tamara:setPosition(ax.p(size.width / 2, 2 * size.height / 3)) + kathia:setPosition(ax.p(size.width / 2, size.height / 2)) Helper.initWithLayer(layer) end @@ -25,15 +25,15 @@ local function centerSprites(numberOfSprites) elseif numberOfSprites == 1 then tamara:setVisible(false) kathia:setVisible(false) - grossini:setPosition(cc.p(size.width / 2, size.height / 2)) + grossini:setPosition(ax.p(size.width / 2, size.height / 2)) elseif numberOfSprites == 2 then - kathia:setPosition(cc.p(size.width / 3, size.height / 2)) - tamara:setPosition(cc.p(2 * size.width / 3, size.height / 2)) + kathia:setPosition(ax.p(size.width / 3, size.height / 2)) + tamara:setPosition(ax.p(2 * size.width / 3, size.height / 2)) grossini:setVisible(false) elseif numberOfSprites == 3 then - grossini:setPosition(cc.p(size.width / 2, size.height / 2)) - tamara:setPosition(cc.p(size.width / 4, size.height / 2)) - kathia:setPosition(cc.p(3 * size.width / 4, size.height / 2)) + grossini:setPosition(ax.p(size.width / 2, size.height / 2)) + tamara:setPosition(ax.p(size.width / 4, size.height / 2)) + kathia:setPosition(ax.p(3 * size.width / 4, size.height / 2)) end end @@ -41,15 +41,15 @@ local function alignSpritesLeft(numberOfSprites) if numberOfSprites == 1 then tamara:setVisible(false) kathia:setVisible(false) - grossini:setPosition(cc.p(60, size.height / 2)) + grossini:setPosition(ax.p(60, size.height / 2)) elseif numberOfSprites == 2 then - kathia:setPosition(cc.p(60, size.height / 3)) - tamara:setPosition(cc.p(60, 2 * size.height / 3)) + kathia:setPosition(ax.p(60, size.height / 3)) + tamara:setPosition(ax.p(60, 2 * size.height / 3)) grossini:setVisible(false) elseif numberOfSprites == 3 then - grossini:setPosition(cc.p(60, size.height / 2)) - tamara:setPosition(cc.p(60, 2 * size.height / 3)) - kathia:setPosition(cc.p(60, size.height / 3)) + grossini:setPosition(ax.p(60, size.height / 2)) + tamara:setPosition(ax.p(60, 2 * size.height / 3)) + kathia:setPosition(ax.p(60, size.height / 3)) end end @@ -58,20 +58,20 @@ end -- ActionManual -------------------------------------- local function ActionManual() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) tamara:setScaleX(2.5) tamara:setScaleY(-1.0) - tamara:setPosition(cc.p(100, 70)) + tamara:setPosition(ax.p(100, 70)) tamara:setOpacity(128) grossini:setRotation(120) - grossini:setPosition(cc.p(size.width / 2, size.height / 2)) - grossini:setColor(cc.c3b(255, 0, 0)) + grossini:setPosition(ax.p(size.width / 2, size.height / 2)) + grossini:setColor(ax.color32(255, 0, 0, 255)) - kathia:setPosition(cc.p(size.width - 100, size.height / 2)) - kathia:setColor(cc.c3b(0, 0, 255)) + kathia:setPosition(ax.p(size.width - 100, size.height / 2)) + kathia:setColor(ax.color32(0, 0, 255, 255)) Helper.subtitleLabel:setString("Manual Transformation") return layer @@ -81,16 +81,16 @@ end -- ActionMove -------------------------------------- local function ActionMove() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local actionBy = cc.MoveBy:create(2, cc.p(80, 80)) + local actionBy = ax.MoveBy:create(2, ax.p(80, 80)) local actionByBack = actionBy:reverse() - tamara:runAction(cc.MoveTo:create(2, cc.p(size.width - 40, size.height - 40))) - grossini:runAction(cc.Sequence:create(actionBy, actionByBack)) - kathia:runAction(cc.MoveTo:create(1, cc.p(40, 40))) + tamara:runAction(ax.MoveTo:create(2, ax.p(size.width - 40, size.height - 40))) + grossini:runAction(ax.Sequence:create(actionBy, actionByBack)) + kathia:runAction(ax.MoveTo:create(1, ax.p(40, 40))) Helper.subtitleLabel:setString("MoveTo / MoveBy") return layer @@ -100,18 +100,18 @@ end -- ActionScale -------------------------------------- local function ActionScale() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local actionTo = cc.ScaleTo:create(2.0, 0.5) - local actionBy = cc.ScaleBy:create(2.0, 1.0, 10.0) - local actionBy2 = cc.ScaleBy:create(2.0, 5.0, 1.0) + local actionTo = ax.ScaleTo:create(2.0, 0.5) + local actionBy = ax.ScaleBy:create(2.0, 1.0, 10.0) + local actionBy2 = ax.ScaleBy:create(2.0, 5.0, 1.0) grossini:runAction(actionTo) - tamara:runAction(cc.Sequence:create(actionBy, actionBy:reverse())) - kathia:runAction(cc.Sequence:create(actionBy2, actionBy2:reverse())) + tamara:runAction(ax.Sequence:create(actionBy, actionBy:reverse())) + kathia:runAction(ax.Sequence:create(actionBy2, actionBy2:reverse())) Helper.subtitleLabel:setString("ScaleTo / ScaleBy") return layer @@ -121,23 +121,23 @@ end -- ActionRotate -------------------------------------- local function ActionRotate() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local actionTo = cc.RotateTo:create( 2, 45) - local actionTo2 = cc.RotateTo:create( 2, -45) - local actionTo0 = cc.RotateTo:create(2 , 0) - tamara:runAction(cc.Sequence:create(actionTo, actionTo0)) + local actionTo = ax.RotateTo:create( 2, 45) + local actionTo2 = ax.RotateTo:create( 2, -45) + local actionTo0 = ax.RotateTo:create(2 , 0) + tamara:runAction(ax.Sequence:create(actionTo, actionTo0)) - local actionBy = cc.RotateBy:create(2 , 360) + local actionBy = ax.RotateBy:create(2 , 360) local actionByBack = actionBy:reverse() - grossini:runAction(cc.Sequence:create(actionBy, actionByBack)) + grossini:runAction(ax.Sequence:create(actionBy, actionByBack)) - local action0Retain = cc.RotateTo:create(2 , 0) + local action0Retain = ax.RotateTo:create(2 , 0) - kathia:runAction(cc.Sequence:create(actionTo2, action0Retain)) + kathia:runAction(ax.Sequence:create(actionTo2, action0Retain)) Helper.subtitleLabel:setString("RotateTo / RotateBy") return layer @@ -147,20 +147,20 @@ end -- ActionSkew -------------------------------------- local function ActionSkew() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local actionTo = cc.SkewTo:create(2, 37.2, -37.2) - local actionToBack = cc.SkewTo:create(2, 0, 0) - local actionBy = cc.SkewBy:create(2, 0.0, -90.0) - local actionBy2 = cc.SkewBy:create(2, 45.0, 45.0) + local actionTo = ax.SkewTo:create(2, 37.2, -37.2) + local actionToBack = ax.SkewTo:create(2, 0, 0) + local actionBy = ax.SkewBy:create(2, 0.0, -90.0) + local actionBy2 = ax.SkewBy:create(2, 45.0, 45.0) local actionByBack = actionBy:reverse() - tamara:runAction(cc.Sequence:create(actionTo, actionToBack)) - grossini:runAction(cc.Sequence:create(actionBy, actionByBack)) - kathia:runAction(cc.Sequence:create(actionBy2, actionBy2:reverse())) + tamara:runAction(ax.Sequence:create(actionTo, actionToBack)) + grossini:runAction(ax.Sequence:create(actionBy, actionByBack)) + kathia:runAction(ax.Sequence:create(actionBy2, actionBy2:reverse())) Helper.subtitleLabel:setString("SkewTo / SkewBy") return layer @@ -169,44 +169,44 @@ end --ActionRotationalSkewVSStandardSkew local function ActionRotationalSkewVSStandardSkew() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) tamara:removeFromParent(true); grossini:removeFromParent(true); kathia:removeFromParent(true); - local s = cc.Director:getInstance():getWinSize(); - local boxSize = cc.size(100.0, 100.0); - local box = cc.LayerColor:create(cc.c4b(255,255,0,255)); - box:setAnchorPoint(cc.p(0.5,0.5)); + local s = ax.Director:getInstance():getWinSize(); + local boxSize = ax.size(100.0, 100.0); + local box = ax.LayerColor:create(ax.color32(255,255,0,255)); + box:setAnchorPoint(ax.p(0.5,0.5)); box:setContentSize( boxSize ); box:setIgnoreAnchorPointForPosition(false); - box:setPosition(cc.p(s.width/2, s.height - 100 - box:getContentSize().height/2)); + box:setPosition(ax.p(s.width/2, s.height - 100 - box:getContentSize().height/2)); layer:addChild(box); - local label = cc.Label:createWithTTF("Standard axmol Skew", s_markerFeltFontPath, 16); - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, s.height - 100 + label:getContentSize().height)); + local label = ax.Label:createWithTTF("Standard axmol Skew", s_markerFeltFontPath, 16); + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, s.height - 100 + label:getContentSize().height)); layer:addChild(label); - local actionTo = cc.SkewBy:create(2, 360, 0); - local actionToBack = cc.SkewBy:create(2, -360, 0); - local seq = cc.Sequence:create(actionTo, actionToBack) + local actionTo = ax.SkewBy:create(2, 360, 0); + local actionToBack = ax.SkewBy:create(2, -360, 0); + local seq = ax.Sequence:create(actionTo, actionToBack) box:runAction(seq); - box = cc.LayerColor:create(cc.c4b(255,255,0,255)); - box:setAnchorPoint(cc.p(0.5,0.5)); + box = ax.LayerColor:create(ax.color32(255,255,0,255)); + box:setAnchorPoint(ax.p(0.5,0.5)); box:setContentSize(boxSize); box:setIgnoreAnchorPointForPosition(false); - box:setPosition(cc.p(s.width/2, s.height - 250 - box:getContentSize().height/2)); + box:setPosition(ax.p(s.width/2, s.height - 250 - box:getContentSize().height/2)); layer:addChild(box); - label = cc.Label:createWithTTF("Rotational Skew", s_markerFeltFontPath, 16); - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, s.height - 250 + label:getContentSize().height/2)); + label = ax.Label:createWithTTF("Rotational Skew", s_markerFeltFontPath, 16); + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, s.height - 250 + label:getContentSize().height/2)); layer:addChild(label); - local actionTo2 = cc.RotateBy:create(2, 360, 0); - local actionToBack2 = cc.RotateBy:create(2, -360, 0); - seq = cc.Sequence:create(actionTo2, actionToBack2) + local actionTo2 = ax.RotateBy:create(2, 360, 0); + local actionToBack2 = ax.RotateBy:create(2, -360, 0); + seq = ax.Sequence:create(actionTo2, actionToBack2) box:runAction(seq); Helper.subtitleLabel:setString("Skew Comparison") @@ -217,45 +217,45 @@ end -- ActionSkewRotate -------------------------------------- local function ActionSkewRotate() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) tamara:removeFromParent(true) grossini:removeFromParent(true) kathia:removeFromParent(true) - local boxSize = cc.size(100.0, 100.0) + local boxSize = ax.size(100.0, 100.0) - local box = cc.LayerColor:create(cc.c4b(255, 255, 0, 255)) - box:setAnchorPoint(cc.p(0, 0)) + local box = ax.LayerColor:create(ax.color32(255, 255, 0, 255)) + box:setAnchorPoint(ax.p(0, 0)) box:setPosition(190, 110) box:setContentSize(boxSize) local markrside = 10.0 - local uL = cc.LayerColor:create(cc.c4b(255, 0, 0, 255)) + local uL = ax.LayerColor:create(ax.color32(255, 0, 0, 255)) box:addChild(uL) - uL:setContentSize(cc.size(markrside, markrside)) + uL:setContentSize(ax.size(markrside, markrside)) uL:setPosition(0, boxSize.height - markrside) - uL:setAnchorPoint(cc.p(0, 0)) + uL:setAnchorPoint(ax.p(0, 0)) - local uR = cc.LayerColor:create(cc.c4b(0, 0, 255, 255)) + local uR = ax.LayerColor:create(ax.color32(0, 0, 255, 255)) box:addChild(uR) - uR:setContentSize(cc.size(markrside, markrside)) + uR:setContentSize(ax.size(markrside, markrside)) uR:setPosition(boxSize.width - markrside, boxSize.height - markrside) - uR:setAnchorPoint(cc.p(0, 0)) + uR:setAnchorPoint(ax.p(0, 0)) layer:addChild(box) - local actionTo = cc.SkewTo:create(2, 0, 2) - local rotateTo = cc.RotateTo:create(2, 61.0) - local actionScaleTo = cc.ScaleTo:create(2, -0.44, 0.47) + local actionTo = ax.SkewTo:create(2, 0, 2) + local rotateTo = ax.RotateTo:create(2, 61.0) + local actionScaleTo = ax.ScaleTo:create(2, -0.44, 0.47) - local actionScaleToBack = cc.ScaleTo:create(2, 1.0, 1.0) - local rotateToBack = cc.RotateTo:create(2, 0) - local actionToBack = cc.SkewTo:create(2, 0, 0) + local actionScaleToBack = ax.ScaleTo:create(2, 1.0, 1.0) + local rotateToBack = ax.RotateTo:create(2, 0) + local actionToBack = ax.SkewTo:create(2, 0, 0) - box:runAction(cc.Sequence:create(actionTo, actionToBack)) - box:runAction(cc.Sequence:create(rotateTo, rotateToBack)) - box:runAction(cc.Sequence:create(actionScaleTo, actionScaleToBack)) + box:runAction(ax.Sequence:create(actionTo, actionToBack)) + box:runAction(ax.Sequence:create(rotateTo, rotateToBack)) + box:runAction(ax.Sequence:create(actionScaleTo, actionScaleToBack)) Helper.subtitleLabel:setString("Skew + Rotate + Scale") return layer @@ -265,19 +265,19 @@ end -- ActionJump -------------------------------------- local function ActionJump() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local actionTo = cc.JumpTo:create(2, cc.p(300,300), 50, 4) - local actionBy = cc.JumpBy:create(2, cc.p(300,0), 50, 4) - local actionUp = cc.JumpBy:create(2, cc.p(0,0), 80, 4) + local actionTo = ax.JumpTo:create(2, ax.p(300,300), 50, 4) + local actionBy = ax.JumpBy:create(2, ax.p(300,0), 50, 4) + local actionUp = ax.JumpBy:create(2, ax.p(0,0), 80, 4) local actionByBack = actionBy:reverse() tamara:runAction(actionTo) - grossini:runAction(cc.Sequence:create(actionBy, actionByBack)) - kathia:runAction(cc.RepeatForever:create(actionUp)) + grossini:runAction(ax.Sequence:create(actionBy, actionByBack)) + kathia:runAction(ax.RepeatForever:create(actionUp)) Helper.subtitleLabel:setString("JumpTo / JumpBy") return layer @@ -287,39 +287,39 @@ end -- ActionCardinalSpline -------------------------------------- local function ActionCardinalSpline() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) local array = { - cc.p(0, 0), - cc.p(size.width / 2 - 30, 0), - cc.p(size.width / 2 - 30, size.height - 80), - cc.p(0, size.height - 80), - cc.p(0, 0), + ax.p(0, 0), + ax.p(size.width / 2 - 30, 0), + ax.p(size.width / 2 - 30, size.height - 80), + ax.p(0, size.height - 80), + ax.p(0, 0), } - local action = cc.CardinalSplineBy:create(3, array, 0) + local action = ax.CardinalSplineBy:create(3, array, 0) local reverse = action:reverse() - local seq = cc.Sequence:create(action, reverse) + local seq = ax.Sequence:create(action, reverse) - tamara:setPosition(cc.p(50, 50)) + tamara:setPosition(ax.p(50, 50)) tamara:runAction(seq) - local action2 = cc.CardinalSplineBy:create(3, array, 1) + local action2 = ax.CardinalSplineBy:create(3, array, 1) local reverse2 = action2:reverse() - local seq2 = cc.Sequence:create(action2, reverse2) + local seq2 = ax.Sequence:create(action2, reverse2) - kathia:setPosition(cc.p(size.width / 2, 50)) + kathia:setPosition(ax.p(size.width / 2, 50)) kathia:runAction(seq2) - local drawNode1 = cc.DrawNode:create() + local drawNode1 = ax.DrawNode:create() drawNode1:setPosition(50, 50) - drawNode1:drawCardinalSpline(array, 0, 100, cc.c4f(0,0,1,1)) + drawNode1:drawCardinalSpline(array, 0, 100, ax.color(0,0,1,1)) layer:addChild(drawNode1) - local drawNode2 = cc.DrawNode:create() + local drawNode2 = ax.DrawNode:create() drawNode2:setPosition(size.width/2, 50) - drawNode2:drawCardinalSpline(array, 1, 100, cc.c4f(0,0,1,1)) + drawNode2:drawCardinalSpline(array, 1, 100, ax.color(0,0,1,1)) layer:addChild(drawNode2) Helper.titleLabel:setString("CardinalSplineBy / CardinalSplineAt") @@ -331,47 +331,47 @@ end -- ActionCatmullRom -------------------------------------- local function ActionCatmullRom() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - tamara:setPosition(cc.p(50, 50)) + tamara:setPosition(ax.p(50, 50)) local array = { - cc.p(0, 0), - cc.p(80, 80), - cc.p(size.width - 80, 80), - cc.p(size.width - 80, size.height - 80), - cc.p(80, size.height - 80), - cc.p(80, 80), - cc.p(size.width / 2, size.height / 2), + ax.p(0, 0), + ax.p(80, 80), + ax.p(size.width - 80, 80), + ax.p(size.width - 80, size.height - 80), + ax.p(80, size.height - 80), + ax.p(80, 80), + ax.p(size.width / 2, size.height / 2), } - local action = cc.CatmullRomBy:create(3, array) + local action = ax.CatmullRomBy:create(3, array) local reverse = action:reverse() - local seq = cc.Sequence:create(action, reverse) + local seq = ax.Sequence:create(action, reverse) tamara:runAction(seq) local array2 = { - cc.p(size.width / 2, 30), - cc.p(size.width -80, 30), - cc.p(size.width - 80, size.height - 80), - cc.p(size.width / 2, size.height - 80), - cc.p(size.width / 2, 30), + ax.p(size.width / 2, 30), + ax.p(size.width -80, 30), + ax.p(size.width - 80, size.height - 80), + ax.p(size.width / 2, size.height - 80), + ax.p(size.width / 2, 30), } - local action2 = cc.CatmullRomTo:create(3, array2) + local action2 = ax.CatmullRomTo:create(3, array2) local reverse2 = action2:reverse() - local seq2 = cc.Sequence:create(action2, reverse2) + local seq2 = ax.Sequence:create(action2, reverse2) kathia:runAction(seq2) - local drawNode1 = cc.DrawNode:create() + local drawNode1 = ax.DrawNode:create() drawNode1:setPosition(50, 50) - drawNode1:drawCatmullRom(array, 50, cc.c4f(0,0,1,1)) + drawNode1:drawCatmullRom(array, 50, ax.color(0,0,1,1)) layer:addChild(drawNode1) - local drawNode2 = cc.DrawNode:create() + local drawNode2 = ax.DrawNode:create() --drawNode2:setPosition(size.width/2, 50) - drawNode2:drawCatmullRom(array2, 50, cc.c4f(0,0,1,1)) + drawNode2:drawCatmullRom(array2, 50, ax.color(0,0,1,1)) layer:addChild(drawNode2) Helper.titleLabel:setString("CatmullRomBy / CatmullRomTo") @@ -383,7 +383,7 @@ end -- ActionBezier -------------------------------------- local function ActionBezier() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) @@ -391,38 +391,38 @@ local function ActionBezier() -- sprite 1 --[[ local bezier = BezierConfig() - bezier.controlPoint_1 = cc.p(0, size.height / 2) - bezier.controlPoint_2 = cc.p(300, - size.height / 2) - bezier.endPosition = cc.p(300, 100) + bezier.controlPoint_1 = ax.p(0, size.height / 2) + bezier.controlPoint_2 = ax.p(300, - size.height / 2) + bezier.endPosition = ax.p(300, 100) ]]-- local bezier = { - cc.p(0, size.height / 2), - cc.p(300, - size.height / 2), - cc.p(300, 100), + ax.p(0, size.height / 2), + ax.p(300, - size.height / 2), + ax.p(300, 100), } - local bezierForward = cc.BezierBy:create(3, bezier) + local bezierForward = ax.BezierBy:create(3, bezier) local bezierBack = bezierForward:reverse() - local rep = cc.RepeatForever:create(cc.Sequence:create(bezierForward, bezierBack)) + local rep = ax.RepeatForever:create(ax.Sequence:create(bezierForward, bezierBack)) -- sprite 2 - tamara:setPosition(cc.p(80,160)) + tamara:setPosition(ax.p(80,160)) --[[ local bezier2 = BezierConfig() - bezier2.controlPoint_1 = cc.p(100, size.height / 2) - bezier2.controlPoint_2 = cc.p(200, - size.height / 2) - bezier2.endPosition = cc.p(240, 160) + bezier2.controlPoint_1 = ax.p(100, size.height / 2) + bezier2.controlPoint_2 = ax.p(200, - size.height / 2) + bezier2.endPosition = ax.p(240, 160) ]]-- local bezier2 ={ - cc.p(100, size.height / 2), - cc.p(200, - size.height / 2), - cc.p(240, 160) + ax.p(100, size.height / 2), + ax.p(200, - size.height / 2), + ax.p(240, 160) } - local bezierTo1 = cc.BezierTo:create(2, bezier2) + local bezierTo1 = ax.BezierTo:create(2, bezier2) -- sprite 3 - kathia:setPosition(cc.p(400,160)) - local bezierTo2 = cc.BezierTo:create(2, bezier2) + kathia:setPosition(ax.p(400,160)) + local bezierTo2 = ax.BezierTo:create(2, bezier2) grossini:runAction(rep) tamara:runAction(bezierTo1) @@ -436,13 +436,13 @@ end -- ActionBlink -------------------------------------- local function ActionBlink() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - local action1 = cc.Blink:create(2, 10) - local action2 = cc.Blink:create(2, 5) + local action1 = ax.Blink:create(2, 10) + local action2 = ax.Blink:create(2, 5) tamara:runAction(action1) kathia:runAction(action2) @@ -456,20 +456,20 @@ end -- ActionFade -------------------------------------- local function ActionFade() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) tamara:setOpacity(0) - local action1 = cc.FadeIn:create(1) + local action1 = ax.FadeIn:create(1) local action1Back = action1:reverse() - local action2 = cc.FadeOut:create(1) + local action2 = ax.FadeOut:create(1) local action2Back = action2:reverse() - tamara:runAction(cc.Sequence:create( action1, action1Back)) - kathia:runAction(cc.Sequence:create( action2, action2Back)) + tamara:runAction(ax.Sequence:create( action1, action1Back)) + kathia:runAction(ax.Sequence:create( action2, action2Back)) Helper.subtitleLabel:setString("FadeIn / FadeOut") @@ -480,17 +480,17 @@ end -- ActionTint -------------------------------------- local function ActionTint() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - local action1 = cc.TintTo:create(2, 255, 0, 255) - local action2 = cc.TintBy:create(2, -127, -255, -127) + local action1 = ax.TintTo:create(2, 255, 0, 255) + local action2 = ax.TintBy:create(2, -127, -255, -127) local action2Back = action2:reverse() tamara:runAction(action1) - kathia:runAction(cc.Sequence:create(action2, action2Back)) + kathia:runAction(ax.Sequence:create(action2, action2Back)) Helper.subtitleLabel:setString("TintTo / TintBy") @@ -501,12 +501,12 @@ end -- ActionAnimate -------------------------------------- local function ActionAnimate() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local animation = cc.Animation:create() + local animation = ax.Animation:create() local number, name for i = 1, 14 do if i < 10 then @@ -521,21 +521,21 @@ local function ActionAnimate() animation:setDelayPerUnit(2.8 / 14.0) animation:setRestoreOriginalFrame(true) - local action = cc.Animate:create(animation) - grossini:runAction(cc.Sequence:create(action, action:reverse())) + local action = ax.Animate:create(animation) + grossini:runAction(ax.Sequence:create(action, action:reverse())) - local cache = cc.AnimationCache:getInstance() + local cache = ax.AnimationCache:getInstance() cache:addAnimations("animations/animations-2.plist") local animation2 = cache:getAnimation("dance_1") - local action2 = cc.Animate:create(animation2) - tamara:runAction(cc.Sequence:create(action2, action2:reverse())) + local action2 = ax.Animate:create(animation2) + tamara:runAction(ax.Sequence:create(action2, action2:reverse())) local animation3 = animation2:clone() animation3:setLoops(4) - local action3 = cc.Animate:create(animation3) + local action3 = ax.Animate:create(animation3) kathia:runAction(action3) Helper.titleLabel:setString("Animation") @@ -548,14 +548,14 @@ end -- ActionSequence -------------------------------------- local function ActionSequence() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(1) - local action = cc.Sequence:create( - cc.MoveBy:create(2, cc.p(240,0)), - cc.RotateBy:create(2, 540)) + local action = ax.Sequence:create( + ax.MoveBy:create(2, ax.p(240,0)), + ax.RotateBy:create(2, 540)) grossini:runAction(action) @@ -570,37 +570,37 @@ end local actionSequenceLayer = nil local function ActionSequenceCallback1() - local label = cc.Label:createWithTTF("callback 1 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("callback 1 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(size.width / 4, size.height / 2) actionSequenceLayer:addChild(label) end local function ActionSequenceCallback2(sender) - local label = cc.Label:createWithTTF("callback 2 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(size.width / 4 * 2, size.height / 2)) + local label = ax.Label:createWithTTF("callback 2 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(size.width / 4 * 2, size.height / 2)) actionSequenceLayer:addChild(label) end local function ActionSequenceCallback3(sender) - local label = cc.Label:createWithTTF("callback 3 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(size.width / 4 * 3, size.height / 2)) + local label = ax.Label:createWithTTF("callback 3 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(size.width / 4 * 3, size.height / 2)) actionSequenceLayer:addChild(label) end local function ActionSequence2() - actionSequenceLayer = cc.Layer:create() + actionSequenceLayer = ax.Layer:create() initWithLayer(actionSequenceLayer) alignSpritesLeft(1) grossini:setVisible(false) - local action = cc.Sequence:create(cc.Place:create(cc.p(200,200)),cc.Show:create(),cc.MoveBy:create(1, cc.p(100,0)), cc.CallFunc:create(ActionSequenceCallback1),cc.CallFunc:create(ActionSequenceCallback2),cc.CallFunc:create(ActionSequenceCallback3)) + local action = ax.Sequence:create(ax.Place:create(ax.p(200,200)),ax.Show:create(),ax.MoveBy:create(1, ax.p(100,0)), ax.CallFunc:create(ActionSequenceCallback1),ax.CallFunc:create(ActionSequenceCallback2),ax.CallFunc:create(ActionSequenceCallback3)) grossini:runAction(action) @@ -612,14 +612,14 @@ end -- ActionSpawn -------------------------------------- local function ActionSpawn() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(1) - local action = cc.Spawn:create( - cc.JumpBy:create(2, cc.p(300,0), 50, 4), - cc.RotateBy:create( 2, 720)) + local action = ax.Spawn:create( + ax.JumpBy:create(2, ax.p(300,0), 50, 4), + ax.RotateBy:create( 2, 720)) grossini:runAction(action) @@ -632,13 +632,13 @@ end -- ActionReverse -------------------------------------- local function ActionReverse() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(1) - local jump = cc.JumpBy:create(2, cc.p(300,0), 50, 4) - local action = cc.Sequence:create(jump, jump:reverse()) + local jump = ax.JumpBy:create(2, ax.p(300,0), 50, 4) + local action = ax.Sequence:create(jump, jump:reverse()) grossini:runAction(action) @@ -651,13 +651,13 @@ end -- ActionDelaytime -------------------------------------- local function ActionDelaytime() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(1) - local move = cc.MoveBy:create(1, cc.p(150,0)) - local action = cc.Sequence:create(move, cc.DelayTime:create(2), move) + local move = ax.MoveBy:create(1, ax.p(150,0)) + local action = ax.Sequence:create(move, ax.DelayTime:create(2), move) grossini:runAction(action) @@ -669,16 +669,16 @@ end -- ActionRepeat -------------------------------------- local function ActionRepeat() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(2) - local a1 = cc.MoveBy:create(1, cc.p(150,0)) - local action1 = cc.Repeat:create(cc.Sequence:create(cc.Place:create(cc.p(60,60)), a1), 3) + local a1 = ax.MoveBy:create(1, ax.p(150,0)) + local action1 = ax.Repeat:create(ax.Sequence:create(ax.Place:create(ax.p(60,60)), a1), 3) - local a2 = cc.MoveBy:create(1, cc.p(150,0)) - local action2 = cc.RepeatForever:create(cc.Sequence:create(a2, a1:reverse())) + local a2 = ax.MoveBy:create(1, ax.p(150,0)) + local action2 = ax.RepeatForever:create(ax.Sequence:create(a2, a1:reverse())) kathia:runAction(action1) tamara:runAction(action2) @@ -691,20 +691,20 @@ end -- ActionRepeatForever -------------------------------------- local function repeatForever(sender) - local repeatAction = cc.RepeatForever:create(cc.RotateBy:create(1.0, 360)) + local repeatAction = ax.RepeatForever:create(ax.RotateBy:create(1.0, 360)) sender:runAction(repeatAction) end local function ActionRepeatForever() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(1) - local action = cc.Sequence:create( - cc.DelayTime:create(1), - cc.CallFunc:create(repeatForever) ) + local action = ax.Sequence:create( + ax.DelayTime:create(1), + ax.CallFunc:create(repeatForever) ) grossini:runAction(action) @@ -716,16 +716,16 @@ end -- ActionRotateToRepeat -------------------------------------- local function ActionRotateToRepeat() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - local act1 = cc.RotateTo:create(1, 90) - local act2 = cc.RotateTo:create(1, 0) - local seq = cc.Sequence:create(act1, act2) - local rep1 = cc.RepeatForever:create(seq) - local rep2 = cc.Repeat:create(seq:clone(), 10) + local act1 = ax.RotateTo:create(1, 90) + local act2 = ax.RotateTo:create(1, 0) + local seq = ax.Sequence:create(act1, act2) + local rep1 = ax.RepeatForever:create(seq) + local rep2 = ax.Repeat:create(seq:clone(), 10) tamara:runAction(rep1) kathia:runAction(rep2) @@ -739,22 +739,22 @@ end -- ActionRotateJerk -------------------------------------- local function ActionRotateJerk() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - local seq = cc.Sequence:create( - cc.RotateTo:create(0.5, -20), - cc.RotateTo:create(0.5, 20)) + local seq = ax.Sequence:create( + ax.RotateTo:create(0.5, -20), + ax.RotateTo:create(0.5, 20)) - local rep1 = cc.Repeat:create(seq, 10) + local rep1 = ax.Repeat:create(seq, 10) - local seq2 = cc.Sequence:create( - cc.RotateTo:create(0.5, -20), - cc.RotateTo:create(0.5, 20)) + local seq2 = ax.Sequence:create( + ax.RotateTo:create(0.5, -20), + ax.RotateTo:create(0.5, 20)) - local rep2 = cc.RepeatForever:create(seq2) + local rep2 = ax.RepeatForever:create(seq2) tamara:runAction(rep1) kathia:runAction(rep2) @@ -769,40 +769,40 @@ end local callFuncLayer = nil local function CallFucnCallback1() - local label = cc.Label:createWithTTF("callback 1 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("callback 1 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(size.width / 4, size.height / 2) callFuncLayer:addChild(label) end local function CallFucnCallback2(sender) - local label = cc.Label:createWithTTF("callback 2 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("callback 2 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(size.width / 4 * 2, size.height / 2) callFuncLayer:addChild(label) end local function CallFucnCallback3(sender) - local label = cc.Label:createWithTTF("callback 3 called", s_markerFeltFontPath, 16) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("callback 3 called", s_markerFeltFontPath, 16) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(size.width / 4 * 3, size.height / 2) callFuncLayer:addChild(label) end local function ActionCallFunc() - callFuncLayer = cc.Layer:create() + callFuncLayer = ax.Layer:create() initWithLayer(callFuncLayer) centerSprites(3) - local action = cc.Sequence:create( - cc.MoveBy:create(2, cc.p(200,0)), - cc.CallFunc:create(CallFucnCallback1) ) - local action2 = cc.Sequence:create(cc.ScaleBy:create(2, 2),cc.FadeOut:create(2),cc.CallFunc:create(CallFucnCallback2)) - local action3 = cc.Sequence:create(cc.RotateBy:create(3 , 360),cc.FadeOut:create(2),cc.CallFunc:create(CallFucnCallback3)) + local action = ax.Sequence:create( + ax.MoveBy:create(2, ax.p(200,0)), + ax.CallFunc:create(CallFucnCallback1) ) + local action2 = ax.Sequence:create(ax.ScaleBy:create(2, 2),ax.FadeOut:create(2),ax.CallFunc:create(CallFucnCallback2)) + local action3 = ax.Sequence:create(ax.RotateBy:create(3 , 360),ax.FadeOut:create(2),ax.CallFunc:create(CallFucnCallback3)) grossini:runAction(action) tamara:runAction(action2) @@ -818,7 +818,7 @@ end -- passing more than one param to lua script -------------------------------------- local function ActionCallFuncND() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(1) @@ -827,9 +827,9 @@ local function ActionCallFuncND() grossini:removeFromParent(true) end - local action = cc.Sequence:create( - cc.MoveBy:create(2, cc.p(200,0)), - cc.CallFunc:create(doRemoveFromParentAndCleanup,{true})) + local action = ax.Sequence:create( + ax.MoveBy:create(2, ax.p(200,0)), + ax.CallFunc:create(doRemoveFromParentAndCleanup,{true})) grossini:runAction(action) @@ -842,15 +842,15 @@ end -- ActionReverseSequence -------------------------------------- local function ActionReverseSequence() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(1) - local move1 = cc.MoveBy:create(1, cc.p(250,0)) - local move2 = cc.MoveBy:create(1, cc.p(0,50)) - local seq = cc.Sequence:create(move1, move2, move1:reverse()) - local action = cc.Sequence:create(seq, seq:reverse()) + local move1 = ax.MoveBy:create(1, ax.p(250,0)) + local move2 = ax.MoveBy:create(1, ax.p(0,50)) + local seq = ax.Sequence:create(move1, move2, move1:reverse()) + local action = ax.Sequence:create(seq, seq:reverse()) grossini:runAction(action) @@ -862,31 +862,31 @@ end -- ActionReverseSequence2 -------------------------------------- local function ActionReverseSequence2() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) alignSpritesLeft(2) -- Test: -- Sequence should work both with IntervalAction and InstantActions - local move1 = cc.MoveBy:create(1, cc.p(250,0)) - local move2 = cc.MoveBy:create(1, cc.p(0,50)) - local tog1 = cc.ToggleVisibility:create() - local tog2 = cc.ToggleVisibility:create() - local seq = cc.Sequence:create(move1, tog1, move2, tog2, move1:reverse()) - local action = cc.Repeat:create(cc.Sequence:create(seq, seq:reverse()), 3) + local move1 = ax.MoveBy:create(1, ax.p(250,0)) + local move2 = ax.MoveBy:create(1, ax.p(0,50)) + local tog1 = ax.ToggleVisibility:create() + local tog2 = ax.ToggleVisibility:create() + local seq = ax.Sequence:create(move1, tog1, move2, tog2, move1:reverse()) + local action = ax.Repeat:create(ax.Sequence:create(seq, seq:reverse()), 3) -- Test: -- Also test that the reverse of Hide is Show, and vice-versa kathia:runAction(action) - local move_tamara = cc.MoveBy:create(1, cc.p(100,0)) - local move_tamara2 = cc.MoveBy:create(1, cc.p(50,0)) - local hide = cc.Hide:create() + local move_tamara = ax.MoveBy:create(1, ax.p(100,0)) + local move_tamara2 = ax.MoveBy:create(1, ax.p(50,0)) + local hide = ax.Hide:create() - local seq_tamara = cc.Sequence:create(move_tamara, hide, move_tamara2) + local seq_tamara = ax.Sequence:create(move_tamara, hide, move_tamara2) local seq_back = seq_tamara:reverse() - tamara:runAction(cc.Sequence:create(seq_tamara, seq_back)) + tamara:runAction(ax.Sequence:create(seq_tamara, seq_back)) Helper.subtitleLabel:setString("Reverse a sequence2") return layer @@ -896,28 +896,28 @@ end -- ActionOrbit -------------------------------------- local function ActionOrbit() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(3) - local orbit1 = cc.OrbitCamera:create(2,1, 0, 0, 180, 0, 0) - local action1 = cc.Sequence:create(orbit1, orbit1:reverse()) + local orbit1 = ax.OrbitCamera:create(2,1, 0, 0, 180, 0, 0) + local action1 = ax.Sequence:create(orbit1, orbit1:reverse()) - local orbit2 = cc.OrbitCamera:create(2,1, 0, 0, 180, -45, 0) - local action2 = cc.Sequence:create(orbit2, orbit2:reverse()) + local orbit2 = ax.OrbitCamera:create(2,1, 0, 0, 180, -45, 0) + local action2 = ax.Sequence:create(orbit2, orbit2:reverse()) - local orbit3 = cc.OrbitCamera:create(2,1, 0, 0, 180, 90, 0) - local action3 = cc.Sequence:create(orbit3, orbit3:reverse()) + local orbit3 = ax.OrbitCamera:create(2,1, 0, 0, 180, 90, 0) + local action3 = ax.Sequence:create(orbit3, orbit3:reverse()) - kathia:runAction(cc.RepeatForever:create(action1)) - tamara:runAction(cc.RepeatForever:create(action2)) - grossini:runAction(cc.RepeatForever:create(action3)) + kathia:runAction(ax.RepeatForever:create(action1)) + tamara:runAction(ax.RepeatForever:create(action2)) + grossini:runAction(ax.RepeatForever:create(action3)) - local move = cc.MoveBy:create(3, cc.p(100,-100)) + local move = ax.MoveBy:create(3, ax.p(100,-100)) local move_back = move:reverse() - local seq = cc.Sequence:create(move, move_back) - local rfe = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(move, move_back) + local rfe = ax.RepeatForever:create(seq) kathia:runAction(rfe) tamara:runAction(rfe:clone()) grossini:runAction(rfe:clone()) @@ -931,27 +931,27 @@ end -- ActionFollow -------------------------------------- local function ActionFollow() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(1) - grossini:setPosition(cc.p(-200, size.height / 2)) - local move = cc.MoveBy:create(2, cc.p(size.width * 3, 0)) + grossini:setPosition(ax.p(-200, size.height / 2)) + local move = ax.MoveBy:create(2, ax.p(size.width * 3, 0)) local move_back = move:reverse() - local seq = cc.Sequence:create(move, move_back) - local rep = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(move, move_back) + local rep = ax.RepeatForever:create(seq) grossini:runAction(rep) - layer:runAction(cc.Follow:create(grossini, cc.rect(0, 0, size.width * 2 - 100, size.height))) + layer:runAction(ax.Follow:create(grossini, ax.rect(0, 0, size.width * 2 - 100, size.height))) - local drawNode = cc.DrawNode:create() - local winSize = cc.Director:getInstance():getWinSize() + local drawNode = ax.DrawNode:create() + local winSize = ax.Director:getInstance():getWinSize() local x = winSize.width * 2 - 100 local y = winSize.height - local vertices = { cc.p(5, 5), cc.p(x - 5, 5), cc.p(x - 5,y - 5), cc.p(5,y - 5) } - drawNode:drawPoly(vertices, 4, true, cc.c4f(0,0,1,1)) + local vertices = { ax.p(5, 5), ax.p(x - 5, 5), ax.p(x - 5,y - 5), ax.p(5,y - 5) } + drawNode:drawPoly(vertices, 4, true, ax.color(0,0,1,1)) layer:addChild(drawNode) Helper.subtitleLabel:setString("Follow action") @@ -962,20 +962,20 @@ end -- ActionTargeted -------------------------------------- local function ActionTargeted() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - local jump1 = cc.JumpBy:create(2, cc.p(0, 0), 100, 3) - local jump2 = cc.JumpBy:create(2, cc.p(0, 0), 100, 3) - local rot1 = cc.RotateBy:create(1, 360) - local rot2 = cc.RotateBy:create(1, 360) + local jump1 = ax.JumpBy:create(2, ax.p(0, 0), 100, 3) + local jump2 = ax.JumpBy:create(2, ax.p(0, 0), 100, 3) + local rot1 = ax.RotateBy:create(1, 360) + local rot2 = ax.RotateBy:create(1, 360) - local t1 = cc.TargetedAction:create(kathia, jump2) - local t2 = cc.TargetedAction:create(kathia, rot2) - local seq = cc.Sequence:create(jump1, t1, rot1, t2) - local always = cc.RepeatForever:create(seq) + local t1 = ax.TargetedAction:create(kathia, jump2) + local t2 = ax.TargetedAction:create(kathia, rot2) + local seq = ax.Sequence:create(jump1, t1, rot1, t2) + local always = ax.RepeatForever:create(seq) tamara:runAction(always) @@ -995,20 +995,20 @@ local PauseResumeActions_resumeEntry = nil local function ActionPause(dt) cclog("Pausing") - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(PauseResumeActions_pauseEntry) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() pausedTargets = director:getActionManager():pauseAllRunningActions() end local function ActionResume(dt) cclog("Resuming") - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(PauseResumeActions_resumeEntry) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() if pausedTargets ~= nil then -- problem: will crash here. Try fixing me! director:getActionManager():resumeTargets(pausedTargets) @@ -1016,7 +1016,7 @@ local function ActionResume(dt) end local function PauseResumeActions_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then PauseResumeActions_pauseEntry = scheduler:scheduleScriptFunc(ActionPause, 3, false) PauseResumeActions_resumeEntry = scheduler:scheduleScriptFunc(ActionResume, 5, false) @@ -1027,13 +1027,13 @@ local function PauseResumeActions_onEnterOrExit(tag) end local function PauseResumeActions() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(2) - tamara:runAction(cc.RepeatForever:create(cc.RotateBy:create(3, 360))) - kathia:runAction(cc.RepeatForever:create(cc.RotateBy:create(3, 360))) + tamara:runAction(ax.RepeatForever:create(ax.RotateBy:create(3, 360))) + kathia:runAction(ax.RepeatForever:create(ax.RotateBy:create(3, 360))) layer:registerScriptHandler(PauseResumeActions_onEnterOrExit) @@ -1054,19 +1054,19 @@ local function Issue1305_log(sender) end local function addSprite(dt) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(Issue1305_entry) Issue1305_entry = nil - spriteTmp:setPosition(cc.p(250, 250)) + spriteTmp:setPosition(ax.p(250, 250)) Issue1305_layer:addChild(spriteTmp) end local function Issue1305_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then - spriteTmp = cc.Sprite:create("Images/grossini.png") - spriteTmp:runAction(cc.CallFunc:create(Issue1305_log)) + spriteTmp = ax.Sprite:create("Images/grossini.png") + spriteTmp:runAction(ax.CallFunc:create(Issue1305_log)) spriteTmp:retain() Issue1305_entry = scheduler:scheduleScriptFunc(addSprite, 2, false) @@ -1081,7 +1081,7 @@ local function Issue1305_onEnterOrExit(tag) end local function ActionIssue1305() - Issue1305_layer = cc.Layer:create() + Issue1305_layer = ax.Layer:create() initWithLayer(Issue1305_layer) centerSprites(0) @@ -1113,26 +1113,26 @@ local function Issue1305_2_log4() end local function ActionIssue1305_2() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(0) - local spr = cc.Sprite:create("Images/grossini.png") - spr:setPosition(cc.p(200,200)) + local spr = ax.Sprite:create("Images/grossini.png") + spr:setPosition(ax.p(200,200)) layer:addChild(spr) - local act1 = cc.MoveBy:create(2 ,cc.p(0, 100)) - local act2 = cc.CallFunc:create(Issue1305_2_log1) - local act3 = cc.MoveBy:create(2, cc.p(0, -100)) - local act4 = cc.CallFunc:create(Issue1305_2_log2) - local act5 = cc.MoveBy:create(2, cc.p(100, -100)) - local act6 = cc.CallFunc:create(Issue1305_2_log3) - local act7 = cc.MoveBy:create(2, cc.p(-100, 0)) - local act8 = cc.CallFunc:create(Issue1305_2_log4) - local actF = cc.Sequence:create(act1, act2, act3, act4, act5, act6, act7, act8) + local act1 = ax.MoveBy:create(2 ,ax.p(0, 100)) + local act2 = ax.CallFunc:create(Issue1305_2_log1) + local act3 = ax.MoveBy:create(2, ax.p(0, -100)) + local act4 = ax.CallFunc:create(Issue1305_2_log2) + local act5 = ax.MoveBy:create(2, ax.p(100, -100)) + local act6 = ax.CallFunc:create(Issue1305_2_log3) + local act7 = ax.MoveBy:create(2, ax.p(-100, 0)) + local act8 = ax.CallFunc:create(Issue1305_2_log4) + local actF = ax.Sequence:create(act1, act2, act3, act4, act5, act6, act7, act8) - cc.Director:getInstance():getActionManager():addAction(actF ,spr, false) + ax.Director:getInstance():getActionManager():addAction(actF ,spr, false) Helper.titleLabel:setString("Issue 1305 #2") Helper.subtitleLabel:setString("See console. You should only see one message for each block") @@ -1143,19 +1143,19 @@ end -- ActionIssue1288 -------------------------------------- local function ActionIssue1288() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(0) - local spr = cc.Sprite:create("Images/grossini.png") - spr:setPosition(cc.p(100, 100)) + local spr = ax.Sprite:create("Images/grossini.png") + spr:setPosition(ax.p(100, 100)) layer:addChild(spr) - local act1 = cc.MoveBy:create(0.5, cc.p(100, 0)) + local act1 = ax.MoveBy:create(0.5, ax.p(100, 0)) local act2 = act1:reverse() - local act3 = cc.Sequence:create(act1, act2) - local act4 = cc.Repeat:create(act3, 2) + local act3 = ax.Sequence:create(act1, act2) + local act4 = ax.Repeat:create(act3, 2) spr:runAction(act4) @@ -1168,17 +1168,17 @@ end -- ActionIssue1288_2 -------------------------------------- local function ActionIssue1288_2() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(0) - local spr = cc.Sprite:create("Images/grossini.png") - spr:setPosition(cc.p(100, 100)) + local spr = ax.Sprite:create("Images/grossini.png") + spr:setPosition(ax.p(100, 100)) layer:addChild(spr) - local act1 = cc.MoveBy:create(0.5, cc.p(100, 0)) - spr:runAction(cc.Repeat:create(act1, 1)) + local act1 = ax.MoveBy:create(0.5, ax.p(100, 0)) + spr:runAction(ax.Repeat:create(act1, 1)) Helper.titleLabel:setString("Issue 1288 #2") Helper.subtitleLabel:setString("Sprite should move 100 pixels, and stay there") @@ -1193,25 +1193,25 @@ local function logSprRotation(sender) end local function ActionIssue1327() - local layer = cc.Layer:create() + local layer = ax.Layer:create() initWithLayer(layer) centerSprites(0) - local spr = cc.Sprite:create("Images/grossini.png") - spr:setPosition(cc.p(100, 100)) + local spr = ax.Sprite:create("Images/grossini.png") + spr:setPosition(ax.p(100, 100)) layer:addChild(spr) - local act1 = cc.CallFunc:create(logSprRotation) - local act2 = cc.RotateBy:create(0.25, 45) - local act3 = cc.CallFunc:create(logSprRotation) - local act4 = cc.RotateBy:create(0.25, 45) - local act5 = cc.CallFunc:create(logSprRotation) - local act6 = cc.RotateBy:create(0.25, 45) - local act7 = cc.CallFunc:create(logSprRotation) - local act8 = cc.RotateBy:create(0.25, 45) - local act9 = cc.CallFunc:create(logSprRotation) - spr:runAction(cc.Sequence:create(act1, act2, act3, act4, act5, act6, act7,act8, act9)) + local act1 = ax.CallFunc:create(logSprRotation) + local act2 = ax.RotateBy:create(0.25, 45) + local act3 = ax.CallFunc:create(logSprRotation) + local act4 = ax.RotateBy:create(0.25, 45) + local act5 = ax.CallFunc:create(logSprRotation) + local act6 = ax.RotateBy:create(0.25, 45) + local act7 = ax.CallFunc:create(logSprRotation) + local act8 = ax.RotateBy:create(0.25, 45) + local act9 = ax.CallFunc:create(logSprRotation) + spr:runAction(ax.Sequence:create(act1, act2, act3, act4, act5, act6, act7,act8, act9)) Helper.titleLabel:setString("Issue 1327") Helper.subtitleLabel:setString("See console: You should see: 0, 45, 90, 135, 180") @@ -1220,7 +1220,7 @@ end function ActionsTest() cclog("ActionsTest") - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { ActionManual, diff --git a/tests/lua-tests/Content/src/AssetsManagerExTest/AssetsManagerExTest.lua b/tests/lua-tests/Content/src/AssetsManagerExTest/AssetsManagerExTest.lua index fa8f590f2618..09fbfad7442a 100644 --- a/tests/lua-tests/Content/src/AssetsManagerExTest/AssetsManagerExTest.lua +++ b/tests/lua-tests/Content/src/AssetsManagerExTest/AssetsManagerExTest.lua @@ -1,27 +1,27 @@ -local targetPlatform = cc.Application:getInstance():getTargetPlatform() +local targetPlatform = ax.Application:getInstance():getTargetPlatform() -local sceneID = +local sceneID = { - "AMTestScene1", - "AMTestScene2", + "AMTestScene1", + "AMTestScene2", "AMTestScene3", } -local sceneManifests = +local sceneManifests = { - "Manifests/AMTestScene1/project.manifest", - "Manifests/AMTestScene2/project.manifest", + "Manifests/AMTestScene1/project.manifest", + "Manifests/AMTestScene2/project.manifest", "Manifests/AMTestScene3/project.manifest" } -local storagePaths = +local storagePaths = { "LuaTests/AssetsManagerExTest/scene1", - "LuaTests/AssetsManagerExTest/scene2", + "LuaTests/AssetsManagerExTest/scene2", "LuaTests/AssetsManagerExTest/scene3", } -local backgroundPaths = +local backgroundPaths = { "Images/assetMgrBackground1.jpg", "Images/assetMgrBackground2.png", @@ -36,7 +36,7 @@ AMTestScene1.__index = AMTestScene1 function AMTestScene1.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local am = nil @@ -45,68 +45,68 @@ function AMTestScene1.create() Helper.initWithLayer(layer) Helper.titleLabel:setString("AssetsManagerExTest1") - local sprite = cc.Sprite:create("Images/Icon.png") + local sprite = ax.Sprite:create("Images/Icon.png") layer:addChild(sprite) - sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y)) + sprite:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y)) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER) - progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50)) + local progress = ax.Label:createWithTTF(ttfConfig, "0%", ax.VERTICAL_TEXT_ALIGNMENT_CENTER) + progress:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y + 50)) layer:addChild(progress) - am = cc.AssetsManagerEx:create(sceneManifests[1], cc.FileUtils:getInstance():getWritablePath() .. storagePaths[1]) + am = ax.AssetsManagerEx:create(sceneManifests[1], ax.FileUtils:getInstance():getWritablePath() .. storagePaths[1]) am:retain() if not am:getLocalManifest():isLoaded() then print("Fail to update assets, step skipped.") - local background = cc.Sprite:create(backgroundPaths[1]) + local background = ax.Sprite:create(backgroundPaths[1]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) else local function onUpdateEvent(event) local eventCode = event:getEventCode() - if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then + if eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then print("No local manifest file found, skip assets update.") - local background = cc.Sprite:create(backgroundPaths[1]) + local background = ax.Sprite:create(backgroundPaths[1]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then local assetId = event:getAssetId() local percent = event:getPercent() local strInfo = "" - if assetId == cc.AssetsManagerExStatic.VERSION_ID then + if assetId == ax.AssetsManagerExStatic.VERSION_ID then strInfo = string.format("Version file: %.3f%%", percent) - elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then + elseif assetId == ax.AssetsManagerExStatic.MANIFEST_ID then strInfo = string.format("Manifest file: %.3f%%", percent) else strInfo = string.format("%.3f%%", percent) end progress:setString(strInfo) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or - eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or + eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then print("Fail to download manifest file, update skipped.") - local background = cc.Sprite:create(backgroundPaths[1]) + local background = ax.Sprite:create(backgroundPaths[1]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or - eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or + eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then print("Update finished.") - local background = cc.Sprite:create(backgroundPaths[1]) + local background = ax.Sprite:create(backgroundPaths[1]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_UPDATING then print("Asset ", event:getAssetId(), ", ", event:getMessage()) - local background = cc.Sprite:create(backgroundPaths[1]) + local background = ax.Sprite:create(backgroundPaths[1]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) end end - local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent) - cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) - + local listener = ax.EventListenerAssetsManagerEx:create(am,onUpdateEvent) + ax.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) + am:update() end end @@ -132,7 +132,7 @@ AMTestScene2.__index = AMTestScene2 function AMTestScene2.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local am = nil @@ -141,69 +141,69 @@ function AMTestScene2.create() Helper.initWithLayer(layer) Helper.titleLabel:setString("AssetsManagerExTest2") - local sprite = cc.Sprite:create("Images/Icon.png") + local sprite = ax.Sprite:create("Images/Icon.png") layer:addChild(sprite) - sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y)) + sprite:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y)) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER) - progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50)) + local progress = ax.Label:createWithTTF(ttfConfig, "0%", ax.VERTICAL_TEXT_ALIGNMENT_CENTER) + progress:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y + 50)) layer:addChild(progress) - am = cc.AssetsManagerEx:create(sceneManifests[2], cc.FileUtils:getInstance():getWritablePath() .. storagePaths[2]) + am = ax.AssetsManagerEx:create(sceneManifests[2], ax.FileUtils:getInstance():getWritablePath() .. storagePaths[2]) am:retain() if not am:getLocalManifest():isLoaded() then print("Fail to update assets, step skipped.") - local background = cc.Sprite:create(backgroundPaths[2]) + local background = ax.Sprite:create(backgroundPaths[2]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) else local function onUpdateEvent(event) local eventCode = event:getEventCode() - if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then + if eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then print("No local manifest file found, skip assets update.") - local background = cc.Sprite:create(backgroundPaths[2]) + local background = ax.Sprite:create(backgroundPaths[2]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then local assetId = event:getAssetId() local percent = event:getPercent() local strInfo = "" - if assetId == cc.AssetsManagerExStatic.VERSION_ID then + if assetId == ax.AssetsManagerExStatic.VERSION_ID then strInfo = string.format("Version file: %d%%", percent) - elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then + elseif assetId == ax.AssetsManagerExStatic.MANIFEST_ID then strInfo = string.format("Manifest file: %d%%", percent) else strInfo = string.format("%d%%", percent) end progress:setString(strInfo) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or - eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or + eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then print("Fail to download manifest file, update skipped.") - local background = cc.Sprite:create(backgroundPaths[2]) + local background = ax.Sprite:create(backgroundPaths[2]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or - eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or + eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then print("Update finished.") - local background = cc.Sprite:create(backgroundPaths[2]) + local background = ax.Sprite:create(backgroundPaths[2]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_UPDATING then print("Asset ", event:getAssetId(), ", ", event:getMessage()) - local background = cc.Sprite:create(backgroundPaths[2]) + local background = ax.Sprite:create(backgroundPaths[2]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) end end - local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent) - cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) - + local listener = ax.EventListenerAssetsManagerEx:create(am,onUpdateEvent) + ax.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) + am:update() end end @@ -228,7 +228,7 @@ AMTestScene3.__index = AMTestScene3 function AMTestScene3.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local am = nil @@ -237,69 +237,69 @@ function AMTestScene3.create() Helper.initWithLayer(layer) Helper.titleLabel:setString("AssetsManagerExTest3") - local sprite = cc.Sprite:create("Images/Icon.png") + local sprite = ax.Sprite:create("Images/Icon.png") layer:addChild(sprite) - sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y)) + sprite:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y)) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - local progress = cc.Label:createWithTTF(ttfConfig, "0%", cc.VERTICAL_TEXT_ALIGNMENT_CENTER) - progress:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 50)) + local progress = ax.Label:createWithTTF(ttfConfig, "0%", ax.VERTICAL_TEXT_ALIGNMENT_CENTER) + progress:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y + 50)) layer:addChild(progress) - am = cc.AssetsManagerEx:create(sceneManifests[3], cc.FileUtils:getInstance():getWritablePath() .. storagePaths[3]) + am = ax.AssetsManagerEx:create(sceneManifests[3], ax.FileUtils:getInstance():getWritablePath() .. storagePaths[3]) am:retain() if not am:getLocalManifest():isLoaded() then print("Fail to update assets, step skipped.") - local background = cc.Sprite:create("Images/background3.png") + local background = ax.Sprite:create("Images/background3.png") layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) else local function onUpdateEvent(event) local eventCode = event:getEventCode() - if eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then + if eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_NO_LOCAL_MANIFEST then print("No local manifest file found, skip assets update.") - local background = cc.Sprite:create(backgroundPaths[3]) + local background = ax.Sprite:create(backgroundPaths[3]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_PROGRESSION then local assetId = event:getAssetId() local percent = event:getPercent() local strInfo = "" - if assetId == cc.AssetsManagerExStatic.VERSION_ID then + if assetId == ax.AssetsManagerExStatic.VERSION_ID then strInfo = string.format("Version file: %d%%", percent) - elseif assetId == cc.AssetsManagerExStatic.MANIFEST_ID then + elseif assetId == ax.AssetsManagerExStatic.MANIFEST_ID then strInfo = string.format("Manifest file: %d%%", percent) else strInfo = string.format("%d%%", percent) end progress:setString(strInfo) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or - eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_DOWNLOAD_MANIFEST or + eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_PARSE_MANIFEST then print("Fail to download manifest file, update skipped.") - local background = cc.Sprite:create(backgroundPaths[3]) + local background = ax.Sprite:create(backgroundPaths[3]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or - eventCode == cc.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ALREADY_UP_TO_DATE or + eventCode == ax.EventAssetsManagerEx.EventCode.UPDATE_FINISHED then print("Update finished.") - local background = cc.Sprite:create(backgroundPaths[3]) + local background = ax.Sprite:create(backgroundPaths[3]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) - elseif eventCode == cc.EventAssetsManagerEx.EventCode.ERROR_UPDATING then + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) + elseif eventCode == ax.EventAssetsManagerEx.EventCode.ERROR_UPDATING then print("Asset ", event:getAssetId(), ", ", event:getMessage()) - local background = cc.Sprite:create(backgroundPaths[3]) + local background = ax.Sprite:create(backgroundPaths[3]) layer:addChild(background, 1) - background:setPosition( cc.p(VisibleRect:center().x, VisibleRect:center().y )) + background:setPosition( ax.p(VisibleRect:center().x, VisibleRect:center().y )) end end - local listener = cc.EventListenerAssetsManagerEx:create(am,onUpdateEvent) - cc.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) - + local listener = ax.EventListenerAssetsManagerEx:create(am,onUpdateEvent) + ax.Director:getInstance():getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, layer) + am:update() end end @@ -320,9 +320,9 @@ end -- AssetsManagerEx Test ------------------------------------- function AssetsManagerExTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { AMTestScene1.create, AMTestScene2.create, diff --git a/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerModule.lua b/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerModule.lua index 53d9a832fd91..351d1a0dd03b 100644 --- a/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerModule.lua +++ b/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerModule.lua @@ -2,42 +2,42 @@ local AssetManagerModule = {} function AssetManagerModule.newScene(backfunc) - local winSize = cc.Director:getInstance():getWinSize() - - local newScene = cc.Scene:create() - local layer = cc.Layer:create() + local winSize = ax.Director:getInstance():getWinSize() + + local newScene = ax.Scene:create() + local layer = ax.Layer:create() local function backToUpdate() local scene = backfunc() if scene ~= nil then - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end end --Create BackMneu - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local backMenuItem = cc.MenuItemFont:create("Back") - backMenuItem:setPosition(cc.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local backMenuItem = ax.MenuItemFont:create("Back") + backMenuItem:setPosition(ax.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) backMenuItem:registerScriptTapHandler(backToUpdate) - local backMenu = cc.Menu:create() + local backMenu = ax.Menu:create() backMenu:setPosition(0, 0) backMenu:addChild(backMenuItem) layer:addChild(backMenu,6) - local helloLabel = cc.Label:createWithTTF("Hello World", s_arialPath, 38) - helloLabel:setAnchorPoint(cc.p(0.5, 0.5)) - helloLabel:setPosition(cc.p(winSize.width / 2, winSize.height - 40)) + local helloLabel = ax.Label:createWithTTF("Hello World", s_arialPath, 38) + helloLabel:setAnchorPoint(ax.p(0.5, 0.5)) + helloLabel:setPosition(ax.p(winSize.width / 2, winSize.height - 40)) layer:addChild(helloLabel, 5) - local sprite = cc.Sprite:create("Images/background.png") - sprite:setAnchorPoint(cc.p(0.5, 0.5)) - sprite:setPosition(cc.p(winSize.width / 2, winSize.height / 2)) + local sprite = ax.Sprite:create("Images/background.png") + sprite:setAnchorPoint(ax.p(0.5, 0.5)) + sprite:setPosition(ax.p(winSize.width / 2, winSize.height / 2)) layer:addChild(sprite, 0) newScene:addChild(layer) - cc.Director:getInstance():replaceScene(newScene) + ax.Director:getInstance():replaceScene(newScene) end diff --git a/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerTest.lua b/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerTest.lua index 3f0fbd308e13..de6932a1a7db 100644 --- a/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerTest.lua +++ b/tests/lua-tests/Content/src/AssetsManagerTest/AssetsManagerTest.lua @@ -1,4 +1,4 @@ -local targetPlatform = cc.Application:getInstance():getTargetPlatform() +local targetPlatform = ax.Application:getInstance():getTargetPlatform() local lineSpace = 40 local itemTagBasic = 1000 @@ -9,15 +9,15 @@ local menuItemNames = "update", } -local winSize = cc.Director:getInstance():getWinSize() +local winSize = ax.Director:getInstance():getWinSize() local function updateLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local support = false - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) - or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or (cc.PLATFORM_OS_ANDROID == targetPlatform) - or (cc.PLATFORM_OS_MAC == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) + or (ax.PLATFORM_OS_WINDOWS == targetPlatform) or (ax.PLATFORM_OS_ANDROID == targetPlatform) + or (ax.PLATFORM_OS_MAC == targetPlatform) then support = true end @@ -30,22 +30,22 @@ local function updateLayer() local assetsManager = nil local pathToSave = "" - local menu = cc.Menu:create() - menu:setPosition(cc.p(0, 0)) - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) + local menu = ax.Menu:create() + menu:setPosition(ax.p(0, 0)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) - local progressLable = cc.Label:createWithTTF("",s_arialPath,30) - progressLable:setAnchorPoint(cc.p(0.5, 0.5)) - progressLable:setPosition(cc.p(140,50)) + local progressLable = ax.Label:createWithTTF("",s_arialPath,30) + progressLable:setAnchorPoint(ax.p(0.5, 0.5)) + progressLable:setPosition(ax.p(140,50)) layer:addChild(progressLable) pathToSave = createDownloadDir() local function onError(errorCode) - if errorCode == cc.ASSETSMANAGER_NO_NEW_VERSION then + if errorCode == ax.ASSETSMANAGER_NO_NEW_VERSION then progressLable:setString("no new version") - elseif errorCode == cc.ASSETSMANAGER_NETWORK then + elseif errorCode == ax.ASSETSMANAGER_NETWORK then progressLable:setString("network error") end end @@ -61,13 +61,13 @@ local function updateLayer() local function getAssetsManager() if nil == assetsManager then - assetsManager = cc.AssetsManager:new("https://raw.github.com/samuele3hu/AssetsManagerTest/master/package.zip", + assetsManager = ax.AssetsManager:new("https://raw.github.com/samuele3hu/AssetsManagerTest/master/package.zip", "https://raw.github.com/samuele3hu/AssetsManagerTest/master/version", pathToSave) assetsManager:retain() - assetsManager:setDelegate(onError, cc.ASSETSMANAGER_PROTOCOL_ERROR ) - assetsManager:setDelegate(onProgress, cc.ASSETSMANAGER_PROTOCOL_PROGRESS) - assetsManager:setDelegate(onSuccess, cc.ASSETSMANAGER_PROTOCOL_SUCCESS ) + assetsManager:setDelegate(onError, ax.ASSETSMANAGER_PROTOCOL_ERROR ) + assetsManager:setDelegate(onProgress, ax.ASSETSMANAGER_PROTOCOL_PROGRESS) + assetsManager:setDelegate(onSuccess, ax.ASSETSMANAGER_PROTOCOL_SUCCESS ) assetsManager:setConnectionTimeout(3) end @@ -120,12 +120,12 @@ local function updateLayer() local nIdx = menuItem:getLocalZOrder() - itemTagBasic local ExtensionsTestScene = CreateExtensionsTestScene(nIdx) if nil ~= ExtensionsTestScene then - cc.Director:getInstance():replaceScene(ExtensionsTestScene) + ax.Director:getInstance():replaceScene(ExtensionsTestScene) end end for i = 1, #(menuItemNames) do - local item = cc.MenuItemFont:create(menuItemNames[i]) + local item = ax.MenuItemFont:create(menuItemNames[i]) item:registerScriptTapHandler(callbackFuncs[i]) item:setPosition(winSize.width / 2, winSize.height - i * lineSpace) if not support then @@ -152,7 +152,7 @@ end -- AssetsManager Test ------------------------------------- function AssetsManagerTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(updateLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/BillBoardTest/BillBoardTest.lua b/tests/lua-tests/Content/src/BillBoardTest/BillBoardTest.lua index 4643d2ddec79..714c0ce7cee2 100644 --- a/tests/lua-tests/Content/src/BillBoardTest/BillBoardTest.lua +++ b/tests/lua-tests/Content/src/BillBoardTest/BillBoardTest.lua @@ -2,7 +2,7 @@ -- BillBoardTest -------------------------------- local BillBoardTest = class("BillBoardTest", function () - return cc.Layer:create() + return ax.Layer:create() end) function BillBoardTest:ctor() @@ -23,9 +23,9 @@ end function BillBoardTest:addNewBillBoardWithCoords(p) local imgs = {"Images/Icon.png", "Images/r2.png"} for i= 1, 10 do - local billboard = cc.BillBoard:create(imgs[math.ceil(math.random() + 0.5)]) + local billboard = ax.BillBoard:create(imgs[math.ceil(math.random() + 0.5)]) billboard:setScale(0.5) - billboard:setPosition3D(cc.vec3(p.x, p.y, -150.0 + 30 * i)) + billboard:setPosition3D(ax.vec3(p.x, p.y, -150.0 + 30 * i)) billboard:setOpacity(math.random() * 128 + 128) self._layerBillBoard:addChild(billboard) table.insert(self._billboards, billboard) @@ -34,37 +34,37 @@ end function BillBoardTest:addNewAniBillBoardWithCoords(p) for i = 1, 10 do - local billboardAni = cc.BillBoard:create("Images/grossini.png") + local billboardAni = ax.BillBoard:create("Images/grossini.png") billboardAni:setScale(0.5) - billboardAni:setPosition3D(cc.vec3(p.x, p.y, -150.0 + 30 * (i - 1))) + billboardAni:setPosition3D(ax.vec3(p.x, p.y, -150.0 + 30 * (i - 1))) self._layerBillBoard:addChild(billboardAni) - local animation = cc.Animation:create() + local animation = ax.Animation:create() for i=1,14 do local szName = string.format("Images/grossini_dance_%02d.png", i) - animation:addSpriteFrameWithFile(szName) + animation:addSpriteFrameWithFile(szName) end --should last 2.8 seconds. And there are 14 frames. animation:setDelayPerUnit(2.8 / 14.0) animation:setRestoreOriginalFrame(true) - local action = cc.Animate:create(animation) - billboardAni:runAction(cc.RepeatForever:create(action)) + local action = ax.Animate:create(animation) + billboardAni:runAction(ax.RepeatForever:create(action)) billboardAni:setOpacity( math.random() * 128 + 128) table.insert(self._billboards, billboardAni) end end function BillBoardTest:init() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) if #touches == 1 then local touch = touches[1] local location = touch:getLocation() local previousLocation = touch:getPreviousLocation() - local newPos = cc.pSub(previousLocation, location) - + local newPos = ax.pSub(previousLocation, location) + local cameraDir = {} local cameraRightDir = {} local transformMat = self._camera:getNodeToWorldTransform() @@ -72,128 +72,128 @@ function BillBoardTest:init() cameraDir.x = -transformMat[9] cameraDir.y = -transformMat[10] cameraDir.z = -transformMat[11] - cameraDir = cc.vec3normalize(cameraDir) + cameraDir = ax.vec3normalize(cameraDir) cameraDir.y = 0 transformMat = self._camera:getNodeToWorldTransform() cameraRightDir.x = transformMat[1] cameraRightDir.y = transformMat[2] cameraRightDir.z = transformMat[3] - cameraRightDir = cc.vec3normalize(cameraRightDir) + cameraRightDir = ax.vec3normalize(cameraRightDir) cameraRightDir.y=0 local cameraPos= self._camera:getPosition3D() - cameraPos = cc.vec3add(cameraPos, cc.vec3mul(cameraDir, newPos.y * 0.5)) - cameraPos = cc.vec3add(cameraPos, cc.vec3mul(cameraRightDir, newPos.x * 0.5)) + cameraPos = ax.vec3add(cameraPos, ax.vec3mul(cameraDir, newPos.y * 0.5)) + cameraPos = ax.vec3add(cameraPos, ax.vec3mul(cameraRightDir, newPos.x * 0.5)) self._camera:setPosition3D(cameraPos) end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) - local layer3D = cc.Layer:create() + local layer3D = ax.Layer:create() self:addChild(layer3D,0) self._layerBillBoard = layer3D - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() if self._camera == nil then - self._camera = cc.Camera:createPerspective(60, s.width/s.height, 1, 500) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + self._camera = ax.Camera:createPerspective(60, s.width/s.height, 1, 500) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self._layerBillBoard:addChild(self._camera) end local imgs = {"Images/Icon.png", "Images/r2.png"} for i= 1, 4 do - local layer = cc.Layer:create() - local billboard = cc.BillBoard:create(imgs[math.ceil((math.random() + 0.5))]) + local layer = ax.Layer:create() + local billboard = ax.BillBoard:create(imgs[math.ceil((math.random() + 0.5))]) billboard:setScale(0.5) - billboard:setPosition3D(cc.vec3(0.0, 0.0, math.random(-1, 1) * 150.0)) + billboard:setPosition3D(ax.vec3(0.0, 0.0, math.random(-1, 1) * 150.0)) billboard:setOpacity(math.random() * 128 + 128) table.insert(self._billboards, billboard) layer:addChild(billboard) self._layerBillBoard:addChild(layer) - layer:runAction( cc.RepeatForever:create( cc.RotateBy:create( math.random() * 10, cc.vec3(0.0, 45.0, 0.0) ) ) ) + layer:runAction( ax.RepeatForever:create( ax.RotateBy:create( math.random() * 10, ax.vec3(0.0, 45.0, 0.0) ) ) ) end - local billboard = cc.BillBoard:create("Images/Icon.png") + local billboard = ax.BillBoard:create("Images/Icon.png") billboard:setScale(0.2) - billboard:setPosition3D(cc.vec3(0.0, 30.0, 0.0)) + billboard:setPosition3D(ax.vec3(0.0, 30.0, 0.0)) - local billboard2 = cc.BillBoard:create("Images/r2.png") - billboard2:setPosition3D(cc.vec3(0.0, 0.0, 100.0)) + local billboard2 = ax.BillBoard:create("Images/r2.png") + billboard2:setPosition3D(ax.vec3(0.0, 0.0, 100.0)) billboard:addChild(billboard2) table.insert(self._billboards, billboard) table.insert(self._billboards, billboard2) - local sprite3d = cc.Sprite3D:create("MeshRendererTest/orc.c3t") + local sprite3d = ax.Sprite3D:create("MeshRendererTest/orc.c3t") sprite3d:setScale(2.0) sprite3d:addChild(billboard) - sprite3d:runAction( cc.RepeatForever:create( cc.RotateBy:create( 10.0, cc.vec3(0.0, 360.0, 0.0) ) ) ) + sprite3d:runAction( ax.RepeatForever:create( ax.RotateBy:create( 10.0, ax.vec3(0.0, 360.0, 0.0) ) ) ) self._layerBillBoard:addChild(sprite3d) - self:addNewBillBoardWithCoords(cc.vec3(20,5,0)) - self:addNewBillBoardWithCoords(cc.vec3(60,5,0)) - self:addNewBillBoardWithCoords(cc.vec3(100,5,0)) - self:addNewBillBoardWithCoords(cc.vec3(140,5,0)) - self:addNewBillBoardWithCoords(cc.vec3(180,5,0)) - self:addNewAniBillBoardWithCoords(cc.vec3(-20,0,0)) - self:addNewAniBillBoardWithCoords(cc.vec3(-60,0,0)) - self:addNewAniBillBoardWithCoords(cc.vec3(-100,0,0)) - self:addNewAniBillBoardWithCoords(cc.vec3(-140,0,0)) - self:addNewAniBillBoardWithCoords(cc.vec3(-180,0,0)) + self:addNewBillBoardWithCoords(ax.vec3(20,5,0)) + self:addNewBillBoardWithCoords(ax.vec3(60,5,0)) + self:addNewBillBoardWithCoords(ax.vec3(100,5,0)) + self:addNewBillBoardWithCoords(ax.vec3(140,5,0)) + self:addNewBillBoardWithCoords(ax.vec3(180,5,0)) + self:addNewAniBillBoardWithCoords(ax.vec3(-20,0,0)) + self:addNewAniBillBoardWithCoords(ax.vec3(-60,0,0)) + self:addNewAniBillBoardWithCoords(ax.vec3(-100,0,0)) + self:addNewAniBillBoardWithCoords(ax.vec3(-140,0,0)) + self:addNewAniBillBoardWithCoords(ax.vec3(-180,0,0)) - self._camera:setPosition3D(cc.vec3(0, 130, 230)) - self._camera:lookAt(cc.vec3(0, 0, 100), cc.vec3(0, 1, 0)) + self._camera:setPosition3D(ax.vec3(0, 130, 230)) + self._camera:lookAt(ax.vec3(0, 0, 100), ax.vec3(0, 1, 0)) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 16 - local label1 = cc.Label:createWithTTF(ttfConfig,"rotate+") - local menuItem1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig,"rotate+") + local menuItem1 = ax.MenuItemLabel:create(label1) menuItem1:registerScriptTapHandler(function (tag, sender ) local rotation3D= self._camera:getRotation3D() rotation3D.y = rotation3D.y + 10 self._camera:setRotation3D(rotation3D) end) - local label2 = cc.Label:createWithTTF(ttfConfig,"rotate-") - local menuItem2 = cc.MenuItemLabel:create(label2) + local label2 = ax.Label:createWithTTF(ttfConfig,"rotate-") + local menuItem2 = ax.MenuItemLabel:create(label2) menuItem2:registerScriptTapHandler(function (tag, sender ) local rotation3D= self._camera:getRotation3D() rotation3D.y = rotation3D.y - 10 self._camera:setRotation3D(rotation3D) end) - local menu = cc.Menu:create(menuItem1,menuItem2) - menu:setPosition(cc.p(0, 0)) - menuItem1:setPosition( cc.p( s.width-80, VisibleRect:top().y-160) ) - menuItem2:setPosition( cc.p( s.width-80, VisibleRect:top().y-190) ) + local menu = ax.Menu:create(menuItem1,menuItem2) + menu:setPosition(ax.p(0, 0)) + menuItem1:setPosition( ax.p( s.width-80, VisibleRect:top().y-160) ) + menuItem2:setPosition( ax.p( s.width-80, VisibleRect:top().y-190) ) self:addChild(menu, 0) self._layerBillBoard:setCameraMask(2) - label1 = cc.Label:createWithTTF(ttfConfig,"Point Oriented") - menuItem1 = cc.MenuItemLabel:create(label1) + label1 = ax.Label:createWithTTF(ttfConfig,"Point Oriented") + menuItem1 = ax.MenuItemLabel:create(label1) menuItem1:registerScriptTapHandler(function (tag, sender ) for i,billboard in ipairs(self._billboards) do - billboard:setMode(cc.BillBoard_Mode.VIEW_POINT_ORIENTED) + billboard:setMode(ax.BillBoard_Mode.VIEW_POINT_ORIENTED) end end) - label2 = cc.Label:createWithTTF(ttfConfig,"Plane Oriented") - menuItem2 = cc.MenuItemLabel:create(label2) + label2 = ax.Label:createWithTTF(ttfConfig,"Plane Oriented") + menuItem2 = ax.MenuItemLabel:create(label2) menuItem2:registerScriptTapHandler(function (tag, sender ) for i,billboard in ipairs(self._billboards) do - billboard:setMode(cc.BillBoard_Mode.VIEW_PLANE_ORIENTED) + billboard:setMode(ax.BillBoard_Mode.VIEW_PLANE_ORIENTED) end end) - menuItem1:setPosition( cc.p( s.width-80, VisibleRect:top().y-100) ) - menuItem2:setPosition( cc.p( s.width-80, VisibleRect:top().y-130) ) - menu = cc.Menu:create(menuItem1,menuItem2) - menu:setPosition(cc.p(0,0)) + menuItem1:setPosition( ax.p( s.width-80, VisibleRect:top().y-100) ) + menuItem2:setPosition( ax.p( s.width-80, VisibleRect:top().y-130) ) + menu = ax.Menu:create(menuItem1,menuItem2) + menu:setPosition(ax.p(0,0)) self:addChild(menu, 10) for i,billboard in ipairs(self._billboards) do - billboard:setMode(cc.BillBoard_Mode.VIEW_POINT_ORIENTED) + billboard:setMode(ax.BillBoard_Mode.VIEW_POINT_ORIENTED) end end @@ -201,7 +201,7 @@ end function BillBoardTestMain() cclog("BillBoardTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(BillBoardTest.new()) scene:addChild(CreateBackMenuItem()) diff --git a/tests/lua-tests/Content/src/BugsTest/BugsTest.lua b/tests/lua-tests/Content/src/BugsTest/BugsTest.lua index bb257f2f0fde..5b37f00b4996 100644 --- a/tests/lua-tests/Content/src/BugsTest/BugsTest.lua +++ b/tests/lua-tests/Content/src/BugsTest/BugsTest.lua @@ -2,7 +2,7 @@ local MAX_COUNT = 9 local LINE_SPACE = 40 local kItemTagBasic = 5432 -local Winsize = cc.Director:getInstance():getWinSize() +local Winsize = ax.Director:getInstance():getWinSize() local testNames = { "Bug-350", @@ -18,28 +18,28 @@ local testNames = { } local function CreateBugsTestBackMenuItem(pLayer) - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local pMenuItemFont = cc.MenuItemFont:create("Back") - pMenuItemFont:setPosition(cc.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local pMenuItemFont = ax.MenuItemFont:create("Back") + pMenuItemFont:setPosition(ax.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) local function menuCallback() local pScene = BugsTestMain() if pScene ~= nil then - cc.Director:getInstance():replaceScene(pScene) + ax.Director:getInstance():replaceScene(pScene) end end pMenuItemFont:registerScriptTapHandler(menuCallback) - local pMenu = cc.Menu:create() + local pMenu = ax.Menu:create() pMenu:addChild(pMenuItemFont) - pMenu:setPosition(cc.p(0, 0)) + pMenu:setPosition(ax.p(0, 0)) pLayer:addChild(pMenu) end --BugTest350 local function BugTest350() - local pLayer = cc.Layer:create() - local pBackground = cc.Sprite:create("Hello.png") - pBackground:setPosition(cc.p(Winsize.width/2, Winsize.height/2)) + local pLayer = ax.Layer:create() + local pBackground = ax.Sprite:create("Hello.png") + pBackground:setPosition(ax.p(Winsize.width/2, Winsize.height/2)) pLayer:addChild(pBackground) return pLayer end @@ -57,29 +57,29 @@ local function BugTest422() end pResetLayer:removeChild(pNode, false) - + local function menuCallback(tag,pMenuItem) if nil ~= pMenuItem then local pCallbackLayer = pMenuItem:getParent():getParent() reset(pCallbackLayer) end end - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local pMenuItem1 = cc.MenuItemFont:create("One") + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local pMenuItem1 = ax.MenuItemFont:create("One") pMenuItem1:registerScriptTapHandler(menuCallback) - local pMenuItem2 = cc.MenuItemFont:create("Two") + local pMenuItem2 = ax.MenuItemFont:create("Two") pMenuItem2:registerScriptTapHandler(menuCallback) - local pMenu = cc.Menu:create(pMenuItem1, pMenuItem2) + local pMenu = ax.Menu:create(pMenuItem1, pMenuItem2) pMenu:alignItemsVertically() local fX = math.random() * 50 local fY = math.random() * 50 local menuPosX ,menuPosY = pMenu:getPosition() - pMenu:setPosition(cc.p(menuPosX + fX,menuPosY + fY)) + pMenu:setPosition(ax.p(menuPosX + fX,menuPosY + fY)) pResetLayer:addChild(pMenu,0,nLocalTag) end - - local pLayer = cc.Layer:create() + + local pLayer = ax.Layer:create() reset(pLayer) return pLayer end @@ -87,96 +87,96 @@ end --BugTest458 local nColorFlag = 0 local function BugTest458() - local pLayer = cc.Layer:create() - + local pLayer = ax.Layer:create() + local function InitQuestionContainerSprite(pSprite) --Add label - local pLabel = cc.Label:createWithTTF("Answer 1", s_arialPath, 12) - pLabel:setAnchorPoint(cc.p(0.5,0.5)) + local pLabel = ax.Label:createWithTTF("Answer 1", s_arialPath, 12) + pLabel:setAnchorPoint(ax.p(0.5,0.5)) pLabel:setTag(100) - + --Add the background - local pCorner = cc.Sprite:create("Images/bugs/corner.png") + local pCorner = ax.Sprite:create("Images/bugs/corner.png") local nWidth = Winsize.width * 0.9 - (pCorner:getContentSize().width * 2) local nHeight = Winsize.height * 0.15 - (pCorner:getContentSize().height * 2) - local pColorLayer = cc.LayerColor:create(cc.c4b(255, 255, 255, 255 * .75), nWidth, nHeight) - pColorLayer:setPosition(cc.p(-nWidth / 2, -nHeight / 2)) + local pColorLayer = ax.LayerColor:create(ax.color32(255, 255, 255, 255 * .75), nWidth, nHeight) + pColorLayer:setPosition(ax.p(-nWidth / 2, -nHeight / 2)) --First button is blue,Second is red,Used for testing - change later if (0 == nColorFlag) then - pLabel:setColor(cc.c3b(0,0,255)) + pLabel:setColor(ax.color32(0,0,255)) else print("Color changed") - pLabel:setColor(cc.c3b(255,0,0)) + pLabel:setColor(ax.color32(255,0,0)) end nColorFlag = nColorFlag + 1 pSprite:addChild(pColorLayer) - - pCorner:setPosition(cc.p(-(nWidth / 2 + pCorner:getContentSize().width / 2), -(nHeight / 2 + pCorner:getContentSize().height / 2))) + + pCorner:setPosition(ax.p(-(nWidth / 2 + pCorner:getContentSize().width / 2), -(nHeight / 2 + pCorner:getContentSize().height / 2))) pSprite:addChild(pCorner) - + local nX,nY = pCorner:getPosition() - local pCorner2 = cc.Sprite:create("Images/bugs/corner.png") - pCorner2:setPosition(cc.p(-nX, nY)) + local pCorner2 = ax.Sprite:create("Images/bugs/corner.png") + pCorner2:setPosition(ax.p(-nX, nY)) pCorner2:setFlippedX(true) pSprite:addChild(pCorner2) - local pCorner3 = cc.Sprite:create("Images/bugs/corner.png") - pCorner3:setPosition(cc.p(nX, -nY)) + local pCorner3 = ax.Sprite:create("Images/bugs/corner.png") + pCorner3:setPosition(ax.p(nX, -nY)) pCorner3:setFlippedY(true) pSprite:addChild(pCorner3) - local pCorner4 = cc.Sprite:create("Images/bugs/corner.png") - pCorner4:setPosition(cc.p(-nX, -nY)) + local pCorner4 = ax.Sprite:create("Images/bugs/corner.png") + pCorner4:setPosition(ax.p(-nX, -nY)) pCorner4:setFlippedX(true) pCorner4:setFlippedY(true) pSprite:addChild(pCorner4) - local pEdge = cc.Sprite:create("Images/bugs/edge.png") + local pEdge = ax.Sprite:create("Images/bugs/edge.png") pEdge:setScaleX(nWidth) - pEdge:setPosition(cc.p(nX + (pCorner:getContentSize().width / 2) + (nWidth / 2), nY)) + pEdge:setPosition(ax.p(nX + (pCorner:getContentSize().width / 2) + (nWidth / 2), nY)) pSprite:addChild(pEdge) - - local pEdge2 = cc.Sprite:create("Images/bugs/edge.png") + + local pEdge2 = ax.Sprite:create("Images/bugs/edge.png") pEdge2:setScaleX(nWidth) - pEdge2:setPosition(cc.p(nX + (pCorner:getContentSize().width / 2) + (nWidth / 2), -nY)) + pEdge2:setPosition(ax.p(nX + (pCorner:getContentSize().width / 2) + (nWidth / 2), -nY)) pEdge2:setFlippedY(true) pSprite:addChild(pEdge2) - local pEdge3 = cc.Sprite:create("Images/bugs/edge.png") + local pEdge3 = ax.Sprite:create("Images/bugs/edge.png") pEdge3:setRotation(90) pEdge3:setScaleX(nHeight) - pEdge3:setPosition(cc.p(nX, nY + (pCorner:getContentSize().height / 2) + (nHeight / 2))) + pEdge3:setPosition(ax.p(nX, nY + (pCorner:getContentSize().height / 2) + (nHeight / 2))) pSprite:addChild(pEdge3) - local pEdge4 = cc.Sprite:create("Images/bugs/edge.png") + local pEdge4 = ax.Sprite:create("Images/bugs/edge.png") pEdge4:setRotation(270) pEdge4:setScaleX(nHeight) - pEdge4:setPosition(cc.p(-nX, nY + (pCorner:getContentSize().height / 2) + (nHeight / 2))) + pEdge4:setPosition(ax.p(-nX, nY + (pCorner:getContentSize().height / 2) + (nHeight / 2))) pSprite:addChild(pEdge4) pSprite:addChild(pLabel) end - - local pQuestion1 = cc.Sprite:create() + + local pQuestion1 = ax.Sprite:create() InitQuestionContainerSprite(pQuestion1) - local pQuestion2 = cc.Sprite:create() + local pQuestion2 = ax.Sprite:create() InitQuestionContainerSprite(pQuestion2) - + local function menuCallback() print("Selected") end - local pMenuItemSprite = cc.MenuItemSprite:create(pQuestion1,pQuestion2) + local pMenuItemSprite = ax.MenuItemSprite:create(pQuestion1,pQuestion2) pMenuItemSprite:registerScriptTapHandler(menuCallback) - local pLayerColor1 = cc.LayerColor:create(cc.c4b(0,0,255,255), 100, 100) + local pLayerColor1 = ax.LayerColor:create(ax.color32(0,0,255,255), 100, 100) -- question->release() -- question2->release() - local pLayerColor2 = cc.LayerColor:create(cc.c4b(255,0,0,255), 100, 100) - local pMenuItemSprite2 = cc.MenuItemSprite:create(pLayerColor1, pLayerColor2) - pMenuItemSprite2:registerScriptTapHandler(menuCallback) - local pMenu = cc.Menu:create(pMenuItemSprite, pMenuItemSprite2) + local pLayerColor2 = ax.LayerColor:create(ax.color32(255,0,0,255), 100, 100) + local pMenuItemSprite2 = ax.MenuItemSprite:create(pLayerColor1, pLayerColor2) + pMenuItemSprite2:registerScriptTapHandler(menuCallback) + local pMenu = ax.Menu:create(pMenuItemSprite, pMenuItemSprite2) pMenu:alignItemsVerticallyWithPadding(100) - pMenu:setPosition(cc.p(Winsize.width / 2, Winsize.height / 2)) + pMenu:setPosition(ax.p(Winsize.width / 2, Winsize.height / 2)) -- add the label as a child to this Layer pLayer:addChild(pMenu) @@ -189,163 +189,163 @@ local BugTest624_entry = nil local BugTest624_2_entry = nil local function BugTest624() - local pLayer = cc.Layer:create() - - local pLabel = cc.Label:createWithTTF("Layer1", s_markerFeltFontPath, 36) - pLabel:setAnchorPoint(cc.p(0.5, 0.5)) - pLabel:setPosition(cc.p(Winsize.width / 2, Winsize.height / 2)) + local pLayer = ax.Layer:create() + + local pLabel = ax.Label:createWithTTF("Layer1", s_markerFeltFontPath, 36) + pLabel:setAnchorPoint(ax.p(0.5, 0.5)) + pLabel:setPosition(ax.p(Winsize.width / 2, Winsize.height / 2)) pLayer:addChild(pLabel) pLayer:setAccelerometerEnabled(true) -- schedule(schedule_selector(Bug624Layer::switchLayer), 5.0f) - + local function BugTest624_SwitchLayer() - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(BugTest624_entry) - - local pScene = cc.Scene:create() + + local pScene = ax.Scene:create() local pNewPlayer = BugTest624_2() - CreateBugsTestBackMenuItem(pNewPlayer) - pScene:addChild(pNewPlayer) - cc.Director:getInstance():replaceScene(cc.TransitionFade:create(2.0, pScene, cc.c3b(255,255,255))) + CreateBugsTestBackMenuItem(pNewPlayer) + pScene:addChild(pNewPlayer) + ax.Director:getInstance():replaceScene(ax.TransitionFade:create(2.0, pScene, ax.color32(255,255,255))) end - - + + local function BugTest624_OnEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then BugTest624_entry = scheduler:scheduleScriptFunc(BugTest624_SwitchLayer, 5.0, false) elseif tag == "exit" then scheduler:unscheduleScriptEntry(BugTest624_entry) end - end + end pLayer:registerScriptHandler(BugTest624_OnEnterOrExit) - + local function didAccelerate(x,y,z,timestamp) print("Layer1 accel") end pLayer:registerScriptAccelerateHandler(didAccelerate) - - return pLayer + + return pLayer end function BugTest624_2() - local pLayer = cc.Layer:create() - - local pLabel = cc.Label:createWithTTF("Layer2", s_markerFeltFontPath, 36) - pLabel:setAnchorPoint(cc.p(0.5, 0.5)) - pLabel:setPosition(cc.p(Winsize.width / 2, Winsize.height / 2)) + local pLayer = ax.Layer:create() + + local pLabel = ax.Label:createWithTTF("Layer2", s_markerFeltFontPath, 36) + pLabel:setAnchorPoint(ax.p(0.5, 0.5)) + pLabel:setPosition(ax.p(Winsize.width / 2, Winsize.height / 2)) pLayer:addChild(pLabel) pLayer:setAccelerometerEnabled(true) - + local function BugTest624_2_SwitchLayer() - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(BugTest624_2_entry) - - local pScene = cc.Scene:create() + + local pScene = ax.Scene:create() local pNewPlayer = BugTest624() - CreateBugsTestBackMenuItem(pNewPlayer) + CreateBugsTestBackMenuItem(pNewPlayer) pScene:addChild(pNewPlayer) - cc.Director:getInstance():replaceScene(cc.TransitionFade:create(2.0, pScene, cc.c3b(255,0,0))) + ax.Director:getInstance():replaceScene(ax.TransitionFade:create(2.0, pScene, ax.color32(255,0,0))) end - + local function BugTest624_2_OnEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then BugTest624_2_entry = scheduler:scheduleScriptFunc(BugTest624_2_SwitchLayer, 5.0, false) elseif tag == "exit" then scheduler:unscheduleScriptEntry(BugTest624_2_entry) end - end + end pLayer:registerScriptHandler(BugTest624_2_OnEnterOrExit) - + local function didAccelerate(x,y,z,timestamp) print("Layer2 accel") end - + pLayer:registerScriptAccelerateHandler(didAccelerate) return pLayer end --BugTest886 local function BugTest886() - local pLayer = cc.Layer:create() - - local pSprite1 = cc.Sprite:create("Images/bugs/bug886.jpg") - pSprite1:setAnchorPoint(cc.p(0, 0)) - pSprite1:setPosition(cc.p(0, 0)) + local pLayer = ax.Layer:create() + + local pSprite1 = ax.Sprite:create("Images/bugs/bug886.jpg") + pSprite1:setAnchorPoint(ax.p(0, 0)) + pSprite1:setPosition(ax.p(0, 0)) pSprite1:setScaleX(0.6) pLayer:addChild(pSprite1) - - local pSprite2 = cc.Sprite:create("Images/bugs/bug886.jpg") - pSprite2:setAnchorPoint(cc.p(0, 0)) + + local pSprite2 = ax.Sprite:create("Images/bugs/bug886.jpg") + pSprite2:setAnchorPoint(ax.p(0, 0)) pSprite2:setScaleX(0.6) - pSprite2:setPosition(cc.p(pSprite1:getContentSize().width * 0.6 + 10, 0)) + pSprite2:setPosition(ax.p(pSprite1:getContentSize().width * 0.6 + 10, 0)) pLayer:addChild(pSprite2) - + return pLayer end --BugTest899 local function BugTest899() - local pLayer = cc.Layer:create() - - local pBg = cc.Sprite:create("Images/bugs/RetinaDisplay.jpg") + local pLayer = ax.Layer:create() + + local pBg = ax.Sprite:create("Images/bugs/RetinaDisplay.jpg") pLayer:addChild(pBg,0) - pBg:setAnchorPoint(cc.p(0, 0)) + pBg:setAnchorPoint(ax.p(0, 0)) return pLayer end --BugTest914 local function BugTest914() - local layer = cc.Layer:create() - + local layer = ax.Layer:create() + local layerColor = nil - + for i = 0, 4 do - layerColor = cc.LayerColor:create(cc.c4b(i*20, i*20, i*20,255)) - layerColor:setContentSize(cc.size(i*100, i*100)) - layerColor:setPosition(cc.p(Winsize.width/2, Winsize.height/2)) - layerColor:setAnchorPoint(cc.p(0.5, 0.5)) + layerColor = ax.LayerColor:create(ax.color32(i*20, i*20, i*20,255)) + layerColor:setContentSize(ax.size(i*100, i*100)) + layerColor:setPosition(ax.p(Winsize.width/2, Winsize.height/2)) + layerColor:setAnchorPoint(ax.p(0.5, 0.5)) layerColor:setIgnoreAnchorPointForPosition(false) layer:addChild(layerColor, -1-i) end - + --create and initialize a Label local function restart() - local scene = cc.Scene:create() + local scene = ax.Scene:create() local newLayer = BugTest914() CreateBugsTestBackMenuItem(newLayer) scene:addChild(newLayer) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end - local label = cc.Label:createWithTTF("Hello World", s_markerFeltFontPath, 64) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("Hello World", s_markerFeltFontPath, 64) + label:setAnchorPoint(ax.p(0.5, 0.5)) --position the label on the center of the screen - label:setPosition(cc.p( Winsize.width /2 , Winsize.height/2 )) + label:setPosition(ax.p( Winsize.width /2 , Winsize.height/2 )) layer:addChild(label) - - local item1 = cc.MenuItemFont:create("restart") + + local item1 = ax.MenuItemFont:create("restart") item1:registerScriptTapHandler(restart) - - local menu = cc.Menu:create() + + local menu = ax.Menu:create() menu:addChild(item1) menu:alignItemsVertically() - menu:setPosition(cc.p(Winsize.width/2, 100)) + menu:setPosition(ax.p(Winsize.width/2, 100)) layer:addChild(menu) - - -- handling touch events - local function onTouchMoved(touches, event) - local count = #(touches) + + -- handling touch events + local function onTouchMoved(touches, event) + local count = #(touches) print("Number of touches: ",count) end local function onTouchBegan(touches, event) onTouchMoved(touches, event) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -355,40 +355,40 @@ end --BugTest1159 local function BugTest1159() - local pLayer = cc.Layer:create() + local pLayer = ax.Layer:create() - local background = cc.LayerColor:create(cc.c4b(255, 0, 255, 255)) + local background = ax.LayerColor:create(ax.color32(255, 0, 255, 255)) pLayer:addChild(background) - local sprite_a = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 700, 700) - sprite_a:setAnchorPoint(cc.p(0.5, 0.5)) + local sprite_a = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 700, 700) + sprite_a:setAnchorPoint(ax.p(0.5, 0.5)) sprite_a:setIgnoreAnchorPointForPosition(false) - sprite_a:setPosition(cc.p(0.0, Winsize.height/2)) + sprite_a:setPosition(ax.p(0.0, Winsize.height/2)) pLayer:addChild(sprite_a) - local seq = cc.Sequence:create(cc.MoveTo:create(1.0, cc.p(1024.0, 384.0)), cc.MoveTo:create(1.0, cc.p(0.0, 384.0))) - sprite_a:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(ax.MoveTo:create(1.0, ax.p(1024.0, 384.0)), ax.MoveTo:create(1.0, ax.p(0.0, 384.0))) + sprite_a:runAction(ax.RepeatForever:create(seq)) - local sprite_b = cc.LayerColor:create(cc.c4b(0, 0, 255, 255), 400, 400) - sprite_b:setAnchorPoint(cc.p(0.5, 0.5)) + local sprite_b = ax.LayerColor:create(ax.color32(0, 0, 255, 255), 400, 400) + sprite_b:setAnchorPoint(ax.p(0.5, 0.5)) sprite_b:setIgnoreAnchorPointForPosition(false) - sprite_b:setPosition(cc.p(Winsize.width/2, Winsize.height/2)) + sprite_b:setPosition(ax.p(Winsize.width/2, Winsize.height/2)) pLayer:addChild(sprite_b) local function menuCallback() - local pScene = cc.Scene:create() + local pScene = ax.Scene:create() local pLayer = BugTest1159() CreateBugsTestBackMenuItem(pLayer) pScene:addChild(pLayer) - cc.Director:getInstance():replaceScene(cc.TransitionPageTurn:create(1.0, pScene, false)) + ax.Director:getInstance():replaceScene(ax.TransitionPageTurn:create(1.0, pScene, false)) end - local label = cc.MenuItemLabel:create(cc.Label:createWithSystemFont("Flip Me", "Helvetica", 24)) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.MenuItemLabel:create(ax.Label:createWithSystemFont("Flip Me", "Helvetica", 24)) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:registerScriptTapHandler(menuCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(label) - menu:setPosition(cc.p(Winsize.width - 200.0, 50.0)) + menu:setPosition(ax.p(Winsize.width - 200.0, 50.0)) pLayer:addChild(menu) - + local function onNodeEvent(event) if event == "exit" then --[[ @@ -406,25 +406,25 @@ end --BugTest1174 local function BugTest1174() - local layer = cc.Layer:create() + local layer = ax.Layer:create() - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() - local subtitleLabel = cc.Label:createWithTTF("The results output on the console", s_thonburiPath, 24) - subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + local subtitleLabel = ax.Label:createWithTTF("The results output on the console", s_thonburiPath, 24) + subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(subtitleLabel, 1) subtitleLabel:setPosition(size.width / 2, size.height - 80) - + local function check_for_error(p1,p2,p3,p4,s,t) - local p4_p3 = cc.pSub(p4,p3) - local p4_p3_t = cc.pMul(p4_p3,t) - local hitp1 = cc.pAdd(p3,p4_p3_t) - - local p2_p1 = cc.pSub(p2,p1) - local p2_p1_s = cc.pMul(p2_p1,s) - local hitp2 = cc.pAdd(p1,p2_p1_s) - + local p4_p3 = ax.pSub(p4,p3) + local p4_p3_t = ax.pMul(p4_p3,t) + local hitp1 = ax.pAdd(p3,p4_p3_t) + + local p2_p1 = ax.pSub(p2,p1) + local p2_p1_s = ax.pMul(p2_p1,s) + local hitp2 = ax.pAdd(p1,p2_p1_s) + if math.abs(hitp1.x - hitp2.x ) > 0.1 or math.abs(hitp1.y - hitp2.y) > 0.1 then local strErr = "ERROR: ("..hitp1.x..","..hitp1.y..") != ("..hitp2.x..","..hitp2.y..")" print(strErr) @@ -438,7 +438,7 @@ local function BugTest1174() local err = 0 local ok = 0 local bRet = false - + print("Test1 - Start") local i = 0 for i = 0, 9999 do @@ -452,19 +452,19 @@ local function BugTest1174() --[[ a|b ----- - c|D - ]]-- + c|D + ]]-- local dx = math.random() * 5000 local dy = math.random() * -5000 - + --[[ a|B ----- - c|d + c|d ]]-- local bx = math.random() * 5000 local by = math.random() * 5000 - + --[[ a|b ----- @@ -472,13 +472,13 @@ local function BugTest1174() ]]-- local cx = math.random() * -5000 local cy = math.random() * -5000 - - A = cc.p(ax,ay) - B = cc.p(bx,by) - C = cc.p(cx,cy) - D = cc.p(dx,dy) - - bRet,s,t = cc.pIsLineIntersect( A, D, B, C, s, t) + + A = ax.p(ax,ay) + B = ax.p(bx,by) + C = ax.p(cx,cy) + D = ax.p(dx,dy) + + bRet,s,t = ax.pIsLineIntersect( A, D, B, C, s, t) if true == bRet then if 1 == check_for_error(A,D,B,C,s,t) then err = err + 1 @@ -493,24 +493,24 @@ local function BugTest1174() --Test 2 -------- print("Test2 - Start") - - p1 = cc.p(220,480) - p2 = cc.p(304,325) - p3 = cc.p(264,416) - p4 = cc.p(186,416) + + p1 = ax.p(220,480) + p2 = ax.p(304,325) + p3 = ax.p(264,416) + p4 = ax.p(186,416) s = 0.0 t = 0.0 - bRet,s,t = cc.pIsLineIntersect( p1, p2, p3, p4, s, t) + bRet,s,t = ax.pIsLineIntersect( p1, p2, p3, p4, s, t) if true == bRet then check_for_error(p1, p2, p3, p4, s, t) end print("Test2 - End") - + ------ --Test 3 ------ print("Test3 - Start") - + ok=0 err=0 for i = 0 , 9999 do @@ -519,34 +519,34 @@ local function BugTest1174() -- c | d local ax = math.random() * -500 local ay = math.random() * 500 - p1 = cc.p(ax,ay) + p1 = ax.p(ax,ay) -- a | b -- ----- -- c | D local dx = math.random() * 500 local dy = math.random() * -500 - p2 = cc.p(dx,dy) - + p2 = ax.p(dx,dy) + ------- - + local y = ay - ((ay - dy) / 2.0) - + -- a | b -- ----- -- C | d local cx = math.random() * -500 - p3 = cc.p(cx,y) - + p3 = ax.p(cx,y) + -- a | B -- ----- -- c | d local bx = math.random() * 500 - p4 = cc.p(bx,y) - + p4 = ax.p(bx,y) + s = 0.0 t = 0.0 - bRet,s,t = cc.pIsLineIntersect(p1, p2, p3, p4, s, t) - if true == bRet then + bRet,s,t = ax.pIsLineIntersect(p1, p2, p3, p4, s, t) + if true == bRet then if 1 == check_for_error(p1, p2, p3, p4, s,t ) then err = err + 1 else @@ -556,23 +556,23 @@ local function BugTest1174() end strLog = "Test3 - End. OK="..ok..", Err="..err print(strLog) - + return layer end --BugTestValueTypeJudgeInTable local function BugTestValueTypeJudgeInTable() - local layer = cc.Layer:create() - local label = cc.Label:createWithTTF("Value Type Judge Error in the table:number -> string", "fonts/arial.ttf", 24) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(VisibleRect:center().x, VisibleRect:top().y - 40)) + local layer = ax.Layer:create() + local label = ax.Label:createWithTTF("Value Type Judge Error in the table:number -> string", "fonts/arial.ttf", 24) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(VisibleRect:center().x, VisibleRect:top().y - 40)) layer:addChild(label) - local outLable = cc.Label:createWithTTF("You should see the following output in the console: \n The type of index 0 is number \n The type of index 1 is number \n The type of index 2 is number", "fonts/arial.ttf", 18) - outLable:setAnchorPoint(cc.p(0.5, 0.5)) - outLable:setPosition(cc.p(VisibleRect:center().x, VisibleRect:top().y - 160)) + local outLable = ax.Label:createWithTTF("You should see the following output in the console: \n The type of index 0 is number \n The type of index 1 is number \n The type of index 2 is number", "fonts/arial.ttf", 18) + outLable:setAnchorPoint(ax.p(0.5, 0.5)) + outLable:setPosition(ax.p(VisibleRect:center().x, VisibleRect:top().y - 160)) layer:addChild(outLable) - local valueTypeJudge = cc.ValueTypeJudgeInTable:create({index1 = 111, index2 = 112, index3 = 113}) + local valueTypeJudge = ax.ValueTypeJudgeInTable:create({index1 = 111, index2 = 112, index3 = 113}) layer:addChild(valueTypeJudge) return layer @@ -592,52 +592,52 @@ local CreateBugsTestTable = { } local function CreateBugsTestScene(nBugNo) - local pNewscene = cc.Scene:create() + local pNewscene = ax.Scene:create() local pLayer = CreateBugsTestTable[nBugNo]() CreateBugsTestBackMenuItem(pLayer) pNewscene:addChild(pLayer) - cc.Director:getInstance():replaceScene(pNewscene) + ax.Director:getInstance():replaceScene(pNewscene) --pLayer:autorelease() end local function BugsTestMainLayer() - local ret = cc.Layer:create() - + local ret = ax.Layer:create() + --menu callback local function menuCallback(tag, pMenuItem) local nIdx = pMenuItem:getLocalZOrder() - kItemTagBasic local BugTestScene = CreateBugsTestScene(nIdx) if nil ~= testScene then - cc.Director:getInstance():replaceScene(testScene) + ax.Director:getInstance():replaceScene(testScene) end end - + -- add menu items for tests - local pItemMenu = cc.Menu:create() + local pItemMenu = ax.Menu:create() local nTestCount = #(testNames) - + local i = 1 for i = 1, nTestCount do - local label = cc.Label:createWithTTF(testNames[i], s_arialPath, 24) + local label = ax.Label:createWithTTF(testNames[i], s_arialPath, 24) print("test label index " .. i) - label:setAnchorPoint(cc.p(0.5, 0.5)) - local pMenuItem = cc.MenuItemLabel:create(label) + label:setAnchorPoint(ax.p(0.5, 0.5)) + local pMenuItem = ax.MenuItemLabel:create(label) pMenuItem:registerScriptTapHandler(menuCallback) pItemMenu:addChild(pMenuItem, i + kItemTagBasic) - pMenuItem:setPosition( cc.p( VisibleRect:center().x, (VisibleRect:top().y - i * LINE_SPACE) )) + pMenuItem:setPosition( ax.p( VisibleRect:center().x, (VisibleRect:top().y - i * LINE_SPACE) )) end - - pItemMenu:setPosition(cc.p(0, 0)) + + pItemMenu:setPosition(ax.p(0, 0)) ret:addChild(pItemMenu) - + -- handling touch events local ptBeginPos = {x = 0, y = 0} local ptCurPos = {x = 0, y = 0} - -- handling touch events - local function onTouchMoved(touches, event) - local touchLocation = touches[1]:getLocation() + -- handling touch events + local function onTouchMoved(touches, event) + local touchLocation = touches[1]:getLocation() local nMoveY = touchLocation.y - ptBeginPos.y local curPosx, curPosy = pItemMenu:getPosition() local nextPosy = curPosy + nMoveY @@ -658,18 +658,18 @@ local function BugsTestMainLayer() local function onTouchBegan(touches, event) ptBeginPos = touches[1]:getLocation() end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = ret:getEventDispatcher() - eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) - + eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) + return ret end function BugsTestMain() cclog("BugsTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(BugsTestMainLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua b/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua index e386ae1bf0f3..95154a127548 100644 --- a/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua +++ b/tests/lua-tests/Content/src/Camera3DTest/Camera3DTest.lua @@ -1,7 +1,7 @@ -------------------------------- -- Camera3DTest -------------------------------- -local State = +local State = { None = 0, Idle = 0x01, @@ -13,17 +13,17 @@ local State = Attack = 0x40, } -local CameraType = +local CameraType = { FreeCamera = 0, FirstCamera = 1, ThirdCamera = 2, } -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() local Camera3DTestDemo = class("Camera3DTestDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -46,16 +46,16 @@ end function Camera3DTestDemo:addNewSpriteWithCoords(vec3, filename, playAnimation, scale, bindCamera) - local sprite = cc.Sprite3D:create(filename) + local sprite = ax.Sprite3D:create(filename) self._layer3D:addChild(sprite) local globalZOrder = sprite:getGlobalZOrder() - sprite:setPosition3D(cc.vec3( vec3.x, vec3.y, vec3.z)) + sprite:setPosition3D(ax.vec3( vec3.x, vec3.y, vec3.z)) sprite:setGlobalZOrder(globalZOrder) if nil ~= playAnimation then - local animation = cc.Animation3D:create(filename,"Take 001") + local animation = ax.Animation3D:create(filename,"Take 001") if nil ~= animation then - local animate = cc.Animate3D:create(animation) - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + sprite:runAction(ax.RepeatForever:create(animate)) end end if bindCamera then @@ -65,7 +65,7 @@ function Camera3DTestDemo:addNewSpriteWithCoords(vec3, filename, playAnimation, end function Camera3DTestDemo:scaleCameraCallback(sender, value) - + end function Camera3DTestDemo:rotateCameraCallback( sender,value) @@ -81,8 +81,8 @@ function Camera3DTestDemo:SwitchViewCallback(sender, value) if self._cameraType == CameraType.FreeCamera then local pos3D = self._sprite3D:getPosition3D() - self._camera:setPosition3D(cc.vec3add(cc.vec3(0, 130, 130), pos3D)) - self._camera:lookAt(self._sprite3D:getPosition3D(), cc.vec3(0,1,0)) + self._camera:setPosition3D(ax.vec3add(ax.vec3(0, 130, 130), pos3D)) + self._camera:lookAt(self._sprite3D:getPosition3D(), ax.vec3(0,1,0)) self._incRot:setEnabled(true) self._decRot:setEnabled(true) @@ -92,15 +92,15 @@ function Camera3DTestDemo:SwitchViewCallback(sender, value) newFaceDir.x = -transform[9] newFaceDir.y = -transform[10] newFaceDir.z = -transform[11] - newFaceDir = cc.vec3normalize(newFaceDir) + newFaceDir = ax.vec3normalize(newFaceDir) local pos3D = self._sprite3D:getPosition3D() - self._camera:lookAt(cc.vec3add(pos3D, cc.vec3mul(newFaceDir, 50)), cc.vec3(0, 1, 0)) + self._camera:lookAt(ax.vec3add(pos3D, ax.vec3mul(newFaceDir, 50)), ax.vec3(0, 1, 0)) self._incRot:setEnabled(true) self._decRot:setEnabled(true) elseif self._cameraType == CameraType.ThirdCamera then local pos3D = self._sprite3D:getPosition3D() - self._camera:setPosition3D(cc.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) - self._camera:lookAt(self._sprite3D:getPosition3D(), cc.vec3(0, 1, 0)) + self._camera:setPosition3D(ax.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) + self._camera:lookAt(self._sprite3D:getPosition3D(), ax.vec3(0, 1, 0)) self._incRot:setEnabled(false) self._decRot:setEnabled(false) end @@ -127,12 +127,12 @@ function Camera3DTestDemo:updateState( dt ) curFaceDir.x = matTransform[9] curFaceDir.y = matTransform[10] curFaceDir.z = matTransform[11] - curFaceDir = cc.vec3normalize(curFaceDir) + curFaceDir = ax.vec3normalize(curFaceDir) local newFaceDir = {x = self._targetPos.x - curPos.x, y = self._targetPos.y - curPos.y, z = self._targetPos.z - curPos.z} - newFaceDir.y = 0.0 - newFaceDir = cc.vec3normalize(newFaceDir) - local cosAngle = math.abs(curFaceDir.x * newFaceDir.x + curFaceDir.y * newFaceDir.y + curFaceDir.z * newFaceDir.z - 1) + newFaceDir.y = 0.0 + newFaceDir = ax.vec3normalize(newFaceDir) + local cosAngle = math.abs(curFaceDir.x * newFaceDir.x + curFaceDir.y * newFaceDir.y + curFaceDir.z * newFaceDir.z - 1) local distanceX = self._targetPos.x - curPos.x local distanceY = self._targetPos.y - curPos.y local distanceZ = self._targetPos.z - curPos.z @@ -162,7 +162,7 @@ function Camera3DTestDemo:move3D(dt) local curPos = self._sprite3D:getPosition3D() local newFaceDir = {x = self._targetPos.x - curPos.x, y = self._targetPos.y - curPos.y, z = self._targetPos.z - curPos.z } newFaceDir.y = 0.0 - newFaceDir = cc.vec3normalize(newFaceDir) + newFaceDir = ax.vec3normalize(newFaceDir) local offset = { x = newFaceDir.x * 25.0 * dt, y = newFaceDir.y * 25.0 * dt, z = newFaceDir.z * 25.0 * dt } curPos = { x = curPos.x + offset.x, y = curPos.y + offset.y, z = curPos.z + offset.z} self._sprite3D:setPosition3D(curPos) @@ -179,28 +179,28 @@ end function Camera3DTestDemo:onEnter() self._sprite3D = nil - local s = cc.Director:getInstance():getWinSize() - local listener = cc.EventListenerTouchAllAtOnce:create() + local s = ax.Director:getInstance():getWinSize() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) - - end,cc.Handler.EVENT_TOUCHES_BEGAN) + + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function(touches, event) if #touches == 1 then local touch = touches[1] local location = touch:getLocation() - local newPos = cc.p(touch:getPreviousLocation().x - location.x, touch:getPreviousLocation().y - location.y) + local newPos = ax.p(touch:getPreviousLocation().x - location.x, touch:getPreviousLocation().y - location.y) if self._cameraType == CameraType.FreeCamera or self._cameraType == CameraType.FirstCamera then local cameraRightDir local transformMat = self._camera:getNodeToWorldTransform() local cameraDir = { x = -transformMat[9], y = -transformMat[10], z = -transformMat[11] } - cameraDir = cc.vec3normalize(cameraDir) + cameraDir = ax.vec3normalize(cameraDir) cameraDir.y = 0 transformMat = self._camera:getNodeToWorldTransform() local cameraRightDir = { x = transformMat[1], y = transformMat[2], z = transformMat[3]} - cameraRightDir = cc.vec3normalize(cameraRightDir) + cameraRightDir = ax.vec3normalize(cameraRightDir) cameraRightDir.y = 0 local cameraPos = self._camera:getPosition3D() @@ -209,24 +209,24 @@ function Camera3DTestDemo:onEnter() self._camera:setPosition3D(cameraPos) if nil ~= self._sprite3D and self._cameraType == CameraType.FirstCamera then - self._sprite3D:setPosition3D(cc.vec3(self._camera:getPositionX(), 0, self._camera:getPositionZ())) + self._sprite3D:setPosition3D(ax.vec3(self._camera:getPositionX(), 0, self._camera:getPositionZ())) self._targetPos = self._sprite3D:getPosition3D() end end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function(touches, event) for i,v in ipairs(touches) do local touch = v local location = touch:getLocationInView() if self._camera ~= nil and self._sprite3D ~= nil and self._cameraType == CameraType.ThirdCamera then - local nearP = cc.vec3(location.x, location.y, -1.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, -1.0) + local farP = ax.vec3(location.x, location.y, 1.0) nearP = self._camera:unproject(nearP) farP = self._camera:unproject(farP) - local dir = cc.vec3sub(farP, nearP) + local dir = ax.vec3sub(farP, nearP) local dist=0.0 local ndd = dir.x * 0 + dir.y * 1 + dir.z * 0 if ndd == 0 then @@ -235,8 +235,8 @@ function Camera3DTestDemo:onEnter() local ndo = nearP.x * 0 + nearP.y * 1 + nearP.z * 0 dist= (0 - ndo) / ndd - local p = cc.vec3add(nearP, cc.vec3mul(dir, dist)) - + local p = ax.vec3add(nearP, ax.vec3mul(dir, dist)) + if p.x > 100 then p.x = 100 end if p.x < -100 then p.x = -100 end if p.z > 100 then p.z = 100 end @@ -244,47 +244,47 @@ function Camera3DTestDemo:onEnter() self._targetPos = p end end - end, cc.Handler.EVENT_TOUCHES_ENDED) + end, ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) - local layer3D = cc.Layer:create() + local layer3D = ax.Layer:create() self:addChild(layer3D,0) self._layer3D = layer3D self._curState = State.None - self:addNewSpriteWithCoords(cc.vec3(0, 0, 0), "MeshRendererTest/girl.c3b", true, 0.2, true) + self:addNewSpriteWithCoords(ax.vec3(0, 0, 0), "MeshRendererTest/girl.c3b", true, 0.2, true) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 20 - local label1 = cc.Label:createWithTTF(ttfConfig,"zoom out") - local menuItem1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig,"zoom out") + local menuItem1 = ax.MenuItemLabel:create(label1) menuItem1:registerScriptTapHandler(function (tag, sender ) -- zoom out if nil ~= self._camera and self._cameraType ~= CameraType.FirstCamera then local cameraPos = self._camera:getPosition3D() - local cameraPosNormalize = cc.vec3normalize(cameraPos) + local cameraPosNormalize = ax.vec3normalize(cameraPos) cameraPos = {x = cameraPos.x + cameraPosNormalize.x * 5, y = cameraPos.y + cameraPosNormalize.y * 5, z = cameraPos.z + cameraPosNormalize.z * 5} self._camera:setPosition3D(cameraPos) end end) self._zoomout = menuItem1 - local label2 = cc.Label:createWithTTF(ttfConfig,"zoom in") - local menuItem2 = cc.MenuItemLabel:create(label2) + local label2 = ax.Label:createWithTTF(ttfConfig,"zoom in") + local menuItem2 = ax.MenuItemLabel:create(label2) menuItem2:registerScriptTapHandler(function (tag, sender ) -- zoom in if nil ~= self._camera and self._cameraType ~= CameraType.FirstCamera then local cameraPos = self._camera:getPosition3D() - local cameraPosNormalize = cc.vec3normalize(cameraPos) + local cameraPosNormalize = ax.vec3normalize(cameraPos) cameraPos = {x = cameraPos.x - cameraPosNormalize.x * 5, y = cameraPos.y - cameraPosNormalize.y * 5, z = cameraPos.z - cameraPosNormalize.z * 5} self._camera:setPosition3D(cameraPos) end end) self._zoomin = menuItem2 - local label3 = cc.Label:createWithTTF(ttfConfig,"rotate+") - local menuItem3 = cc.MenuItemLabel:create(label3) + local label3 = ax.Label:createWithTTF(ttfConfig,"rotate+") + local menuItem3 = ax.MenuItemLabel:create(label3) menuItem3:registerScriptTapHandler(function (tag, sender ) -- rotate + if self._cameraType == CameraType.FreeCamera or self._cameraType == CameraType.FirstCamera then local rotation3D = self._camera:getRotation3D() @@ -294,8 +294,8 @@ function Camera3DTestDemo:onEnter() end) self._incRot = menuItem3 - local label4 = cc.Label:createWithTTF(ttfConfig,"rotate-") - local menuItem4 = cc.MenuItemLabel:create(label4) + local label4 = ax.Label:createWithTTF(ttfConfig,"rotate-") + local menuItem4 = ax.MenuItemLabel:create(label4) menuItem4:registerScriptTapHandler(function (tag, sender ) -- rotate - if self._cameraType == CameraType.FreeCamera or self._cameraType == CameraType.FirstCamera then local rotation3D = self._camera:getRotation3D() @@ -305,8 +305,8 @@ function Camera3DTestDemo:onEnter() end) self._decRot = menuItem4 - local label5 = cc.Label:createWithTTF(ttfConfig,"free") - local menuItem5 = cc.MenuItemLabel:create(label5) + local label5 = ax.Label:createWithTTF(ttfConfig,"free") + local menuItem5 = ax.MenuItemLabel:create(label5) menuItem5:registerScriptTapHandler(function (tag, sender ) -- free if self._cameraType == CameraType.FreeCamera then return @@ -314,14 +314,14 @@ function Camera3DTestDemo:onEnter() self._cameraType = CameraType.FreeCamera local pos3D = self._sprite3D:getPosition3D() - self._camera:setPosition3D(cc.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) - self._camera:lookAt(self._sprite3D:getPosition3D(), cc.vec3(0,1,0)) + self._camera:setPosition3D(ax.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) + self._camera:lookAt(self._sprite3D:getPosition3D(), ax.vec3(0,1,0)) self._incRot:setEnabled(true) self._decRot:setEnabled(true) end) - local label6 = cc.Label:createWithTTF(ttfConfig,"third person") - local menuItem6 = cc.MenuItemLabel:create(label6) + local label6 = ax.Label:createWithTTF(ttfConfig,"third person") + local menuItem6 = ax.MenuItemLabel:create(label6) menuItem6:registerScriptTapHandler(function (tag, sender ) -- third person if self._cameraType == CameraType.ThirdCamera then return @@ -330,16 +330,16 @@ function Camera3DTestDemo:onEnter() self._cameraType = CameraType.ThirdCamera local pos3D = self._sprite3D:getPosition3D() - self._camera:setPosition3D(cc.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) - self._camera:lookAt(self._sprite3D:getPosition3D(), cc.vec3(0,1,0)) + self._camera:setPosition3D(ax.vec3(pos3D.x, pos3D.y + 130, pos3D.z + 130)) + self._camera:lookAt(self._sprite3D:getPosition3D(), ax.vec3(0,1,0)) self._incRot:setEnabled(false) self._decRot:setEnabled(false) self._zoomin:setEnabled(true) self._zoomout:setEnabled(true) end) - local label7 = cc.Label:createWithTTF(ttfConfig,"first person") - local menuItem7 = cc.MenuItemLabel:create(label7) + local label7 = ax.Label:createWithTTF(ttfConfig,"first person") + local menuItem7 = ax.MenuItemLabel:create(label7) menuItem7:registerScriptTapHandler(function (tag, sender ) -- first person if self._cameraType == CameraType.FirstCamera then return @@ -348,19 +348,19 @@ function Camera3DTestDemo:onEnter() self._cameraType = CameraType.FirstCamera local transformMat = self._sprite3D:getWorldToNodeTransform() - local newFaceDir = cc.vec3normalize({x = -transformMat[9],y = -transformMat[10], z = -transformMat[11]}) + local newFaceDir = ax.vec3normalize({x = -transformMat[9],y = -transformMat[10], z = -transformMat[11]}) local pos3D = self._sprite3D:getPosition3D() - self._camera:setPosition3D(cc.vec3(pos3D.x, pos3D.y + 35, pos3D.z)) + self._camera:setPosition3D(ax.vec3(pos3D.x, pos3D.y + 35, pos3D.z)) pos3D = self._sprite3D:getPosition3D() - self._camera:lookAt(cc.vec3add(pos3D, cc.vec3mul(newFaceDir, 50)), cc.vec3(0,1,0)) + self._camera:lookAt(ax.vec3add(pos3D, ax.vec3mul(newFaceDir, 50)), ax.vec3(0,1,0)) self._incRot:setEnabled(true) self._decRot:setEnabled(true) self._zoomin:setEnabled(false) self._zoomout:setEnabled(false) end) - local menu = cc.Menu:create(menuItem1,menuItem2,menuItem3,menuItem4,menuItem5,menuItem6,menuItem7) - menu:setPosition(cc.p(0, 0)) + local menu = ax.Menu:create(menuItem1,menuItem2,menuItem3,menuItem4,menuItem5,menuItem6,menuItem7) + menu:setPosition(ax.p(0, 0)) menuItem1:setPosition(s.width-50, VisibleRect:top().y-50 ) menuItem2:setPosition(s.width-50, VisibleRect:top().y-100) menuItem3:setPosition(s.width-50, VisibleRect:top().y-150) @@ -381,31 +381,31 @@ function Camera3DTestDemo:onEnter() local curPos = self._sprite3D:getPosition3D() local newFaceDir = {x = self._targetPos.x - curPos.x, y = self._targetPos.y - curPos.y, z = self._targetPos.z - curPos.z } newFaceDir.y = 0 - newFaceDir = cc.vec3normalize(newFaceDir) + newFaceDir = ax.vec3normalize(newFaceDir) local matTransform = self._sprite3D:getNodeToWorldTransform() local up = {x = matTransform[5], y = matTransform[6] ,z = matTransform[7] } - up = cc.vec3normalize(up) + up = ax.vec3normalize(up) local right = {x = -newFaceDir.y * up.z + newFaceDir.z * up.y, y = -newFaceDir.z * up.x + newFaceDir.x * up.z, z = -newFaceDir.x * up.y + newFaceDir.y * up.x} - right = cc.vec3normalize(right) + right = ax.vec3normalize(right) - local pos = cc.vec3(0, 0, 0) + local pos = ax.vec3(0, 0, 0) local mat = {} mat[1] = right.x mat[2] = right.y mat[3] = right.z mat[4] = 0.0 - + mat[5] = up.x mat[6] = up.y mat[7] = up.z mat[8] = 0.0 - + mat[9] = newFaceDir.x mat[10] = newFaceDir.y mat[11] = newFaceDir.z mat[12] = 0.0 - + mat[13] = pos.x mat[14] = pos.y mat[15] = pos.z @@ -418,27 +418,27 @@ function Camera3DTestDemo:onEnter() end, 0.0, false) if self._camera == nil then - self._camera = cc.Camera:createPerspective(60, s.width / s.height, 1, 1000) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + self._camera = ax.Camera:createPerspective(60, s.width / s.height, 1, 1000) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self._layer3D:addChild(self._camera) end self:SwitchViewCallback(self, CameraType.ThirdCamera) - local line = cc.DrawNode3D:create() + local line = ax.DrawNode3D:create() --draw x for i = -20 ,20 do - line:drawLine(cc.vec3(-100, 0, 5 * i), cc.vec3(100, 0, 5 * i), cc.c4f(1, 0, 0, 0)) + line:drawLine(ax.vec3(-100, 0, 5 * i), ax.vec3(100, 0, 5 * i), ax.color(1, 0, 0, 0)) end --draw z for i = -20, 20 do - line:drawLine(cc.vec3(5 * i, 0, -100), cc.vec3(5 * i, 0, 100), cc.c4f(0, 0, 1, 1)) + line:drawLine(ax.vec3(5 * i, 0, -100), ax.vec3(5 * i, 0, 100), ax.color(0, 0, 1, 1)) end --draw y - line:drawLine(cc.vec3(0, -50, 0), cc.vec3(0,0,0), cc.c4f(0, 0.5, 0, 1)) - line:drawLine(cc.vec3(0, 0, 0), cc.vec3(0,50,0), cc.c4f(0, 1, 0, 1)) + line:drawLine(ax.vec3(0, -50, 0), ax.vec3(0,0,0), ax.color(0, 0.5, 0, 1)) + line:drawLine(ax.vec3(0, 0, 0), ax.vec3(0,50,0), ax.color(0, 1, 0, 1)) self._layer3D:addChild(line) self._layer3D:setCameraMask(2) @@ -467,7 +467,7 @@ function Camera3DTestDemo:init() end local CameraRotationTest = class("CameraRotationTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -491,72 +491,72 @@ function CameraRotationTest:init() end function CameraRotationTest:onEnter() - local s = cc.Director:getInstance():getWinSize() - - camControlNode = cc.Node:create() - camControlNode:setNormalizedPosition(cc.p(0.5, 0.5)) + local s = ax.Director:getInstance():getWinSize() + + camControlNode = ax.Node:create() + camControlNode:setNormalizedPosition(ax.p(0.5, 0.5)) self:addChild(camControlNode) - camNode = cc.Node:create() - camNode:setPositionZ(cc.Camera:getDefaultCamera():getPosition3D().z) + camNode = ax.Node:create() + camNode:setPositionZ(ax.Camera:getDefaultCamera():getPosition3D().z) camControlNode:addChild(camNode) - local sp3d = cc.Sprite3D:create() + local sp3d = ax.Sprite3D:create() sp3d:setPosition(s.width/2, s.height/2) self:addChild(sp3d) - - local lship = cc.Label:create() + + local lship = ax.Label:create() lship:setString("Ship") lship:setPosition(0, 20) sp3d:addChild(lship) - + --Billboards --Yellow is at the back - bill1 = cc.BillBoard:create("Images/Icon.png") - bill1:setPosition3D(cc.vec3(s.width/2 + 50, s.height/2 + 10, -10)) - bill1:setColor(cc.c3b(255, 255, 0)) + bill1 = ax.BillBoard:create("Images/Icon.png") + bill1:setPosition3D(ax.vec3(s.width/2 + 50, s.height/2 + 10, -10)) + bill1:setColor(ax.color32(255, 255, 0)) bill1:setScale(0.6) self:addChild(bill1) - - l1 = cc.Label:create() - l1:setPosition(cc.p(0,-10)) + + l1 = ax.Label:create() + l1:setPosition(ax.p(0,-10)) l1:setString("Billboard1") - l1:setColor(cc.c3b(255, 255, 255)) + l1:setColor(ax.color32(255, 255, 255)) l1:setScale(3) bill1:addChild(l1) - local p1 = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") + local p1 = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") p1:setPosition(30,80) bill1:addChild(p1) - - bill2 = cc.BillBoard:create("Images/Icon.png") - bill2:setPosition3D(cc.vec3(s.width/2 - 50, s.height/2 - 10, 10)) + + bill2 = ax.BillBoard:create("Images/Icon.png") + bill2:setPosition3D(ax.vec3(s.width/2 - 50, s.height/2 - 10, 10)) bill2:setScale(0.6) self:addChild(bill2) - - l2 = cc.Label:create() + + l2 = ax.Label:create() l2:setString("Billboard2") - l2:setPosition(cc.p(0,-10)) - l2:setColor(cc.c3b(255, 255, 255)) + l2:setPosition(ax.p(0,-10)) + l2:setColor(ax.color32(255, 255, 255)) l2:setScale(3) bill2:addChild(l2) - - local p2 = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") + + local p2 = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") p2:setPosition(30,80) bill2:addChild(p2) --3D models - local model = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local model = ax.Sprite3D:create("MeshRendererTest/boss1.obj") model:setScale(4) model:setTexture("MeshRendererTest/boss.png") - model:setPosition3D(cc.vec3(s.width/2, s.height/2, 0)) + model:setPosition3D(ax.vec3(s.width/2, s.height/2, 0)) self:addChild(model) --Listener - lis = cc.EventListenerTouchOneByOne:create() + lis = ax.EventListenerTouchOneByOne:create() lis:registerScriptHandler(function (touch, event) return true - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) lis:registerScriptHandler(function (touch, event) local dx = touch:getDelta().x @@ -564,12 +564,12 @@ function CameraRotationTest:onEnter() rot.y = rot.y + dx camControlNode:setRotation3D(rot) - local worldPos = cc.vec3(0.0, 0.0, 0.0) - local decompose = cc.mat4.new(camNode:getNodeToWorldTransform()):decompose(nil, nil, worldPos) + local worldPos = ax.vec3(0.0, 0.0, 0.0) + local decompose = ax.mat4.new(camNode:getNodeToWorldTransform()):decompose(nil, nil, worldPos) worldPos = decompose.translation - cc.Camera:getDefaultCamera():setPosition3D(worldPos) - cc.Camera:getDefaultCamera():lookAt(camControlNode:getPosition3D()) - end, cc.Handler.EVENT_TOUCH_MOVED) + ax.Camera:getDefaultCamera():setPosition3D(worldPos) + ax.Camera:getDefaultCamera():lookAt(camControlNode:getPosition3D()) + end, ax.Handler.EVENT_TOUCH_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(lis, self) @@ -588,7 +588,7 @@ function CameraRotationTest:subtitle() end local FogTestDemo = class("FogTestDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -619,24 +619,24 @@ function FogTestDemo:init() end function FogTestDemo:setEventListener() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) if #touches == 1 then local touch = touches[1] local prelocation = touch:getPreviousLocationInView() local location = touch:getLocationInView() - local newPos = cc.p(prelocation.x - location.x, prelocation.y - location.y) + local newPos = ax.p(prelocation.x - location.x, prelocation.y - location.y) if self._cameraType == CameraType.FreeCamera then local transformMat = self._camera:getNodeToWorldTransform() local cameraDir = { x = -transformMat[9], y = -transformMat[10], z = -transformMat[11] } - cameraDir = cc.vec3normalize(cameraDir) + cameraDir = ax.vec3normalize(cameraDir) cameraDir.y = 0 transformMat = self._camera:getNodeToWorldTransform() local cameraRightDir = { x = transformMat[1], y = transformMat[2], z = transformMat[3]} - cameraRightDir = cc.vec3normalize(cameraRightDir) + cameraRightDir = ax.vec3normalize(cameraRightDir) cameraRightDir.y = 0 local cameraPos = self._camera:getPosition3D() @@ -646,7 +646,7 @@ function FogTestDemo:setEventListener() end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -658,56 +658,56 @@ function FogTestDemo:createMenu() ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 20 - local label1 = cc.Label:createWithTTF(ttfConfig,"Linear ") - local menuItem1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig,"Linear ") + local menuItem1 = ax.MenuItemLabel:create(label1) menuItem1:registerScriptTapHandler(function (tag, sender ) - self._shader1:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader1:setUniform("u_fogStart",cc.bytearray.from_float( 10)) - self._shader1:setUniform("u_fogEnd",cc.bytearray.from_float( 60)) - self._shader1:setUniform("u_fogEquation" ,cc.bytearray.from_int(0)) + self._shader1:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader1:setUniform("u_fogStart",ax.bytearray.from_float( 10)) + self._shader1:setUniform("u_fogEnd",ax.bytearray.from_float( 60)) + self._shader1:setUniform("u_fogEquation" ,ax.bytearray.from_int(0)) - self._shader2:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader2:setUniform("u_fogStart",cc.bytearray.from_float( 10)) - self._shader2:setUniform("u_fogEnd",cc.bytearray.from_float( 60)) - self._shader2:setUniform("u_fogEquation" ,cc.bytearray.from_int(0)) + self._shader2:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader2:setUniform("u_fogStart",ax.bytearray.from_float( 10)) + self._shader2:setUniform("u_fogEnd",ax.bytearray.from_float( 60)) + self._shader2:setUniform("u_fogEquation" ,ax.bytearray.from_int(0)) self._sprite3D1:setProgramState(self._shader1) self._sprite3D2:setProgramState(self._shader2) end) - local label2 = cc.Label:createWithTTF(ttfConfig,"Exp") - local menuItem2 = cc.MenuItemLabel:create(label2) + local label2 = ax.Label:createWithTTF(ttfConfig,"Exp") + local menuItem2 = ax.MenuItemLabel:create(label2) menuItem2:registerScriptTapHandler(function (tag, sender ) - self._shader1:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader1:setUniform("u_fogDensity",cc.bytearray.from_float( 0.03)) - self._shader1:setUniform("u_fogEquation" ,cc.bytearray.from_int(1)) + self._shader1:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader1:setUniform("u_fogDensity",ax.bytearray.from_float( 0.03)) + self._shader1:setUniform("u_fogEquation" ,ax.bytearray.from_int(1)) - self._shader2:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader2:setUniform("u_fogDensity",cc.bytearray.from_float( 0.03)) - self._shader2:setUniform("u_fogEquation" ,cc.bytearray.from_int(1)) + self._shader2:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader2:setUniform("u_fogDensity",ax.bytearray.from_float( 0.03)) + self._shader2:setUniform("u_fogEquation" ,ax.bytearray.from_int(1)) self._sprite3D1:setProgramState(self._shader1) self._sprite3D2:setProgramState(self._shader2) end) - local label3 = cc.Label:createWithTTF(ttfConfig,"Exp2") - local menuItem3 = cc.MenuItemLabel:create(label3) + local label3 = ax.Label:createWithTTF(ttfConfig,"Exp2") + local menuItem3 = ax.MenuItemLabel:create(label3) menuItem3:registerScriptTapHandler(function (tag, sender ) - self._shader1:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader1:setUniform("u_fogDensity",cc.bytearray.from_float( 0.03)) - self._shader1:setUniform("u_fogEquation" ,cc.bytearray.from_int(2)) + self._shader1:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader1:setUniform("u_fogDensity",ax.bytearray.from_float( 0.03)) + self._shader1:setUniform("u_fogEquation" ,ax.bytearray.from_int(2)) - self._shader2:setUniform("u_fogColor", cc.bytearray.from_vec4( cc.vec4(0.5,0.5,0.5,1.0))) - self._shader2:setUniform("u_fogDensity",cc.bytearray.from_float( 0.03)) - self._shader2:setUniform("u_fogEquation" ,cc.bytearray.from_int(2)) + self._shader2:setUniform("u_fogColor", ax.bytearray.from_vec4( ax.vec4(0.5,0.5,0.5,1.0))) + self._shader2:setUniform("u_fogDensity",ax.bytearray.from_float( 0.03)) + self._shader2:setUniform("u_fogEquation" ,ax.bytearray.from_int(2)) self._sprite3D1:setProgramState(self._shader1) self._sprite3D2:setProgramState(self._shader2) end) - local menu = cc.Menu:create(menuItem1, menuItem2, menuItem3) - - menu:setPosition(cc.p(0.0, 0.0)) - + local menu = ax.Menu:create(menuItem1, menuItem2, menuItem3) + + menu:setPosition(ax.p(0.0, 0.0)) + menuItem1:setPosition(VisibleRect:left().x + 60, VisibleRect:top().y - 50) menuItem2:setPosition(VisibleRect:left().x + 60, VisibleRect:top().y - 100) menuItem3:setPosition(VisibleRect:left().x + 60, VisibleRect:top().y - 150) @@ -716,49 +716,49 @@ end function FogTestDemo:createLayer3D() -- body - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local layer3D = cc.Layer:create() + local layer3D = ax.Layer:create() self:addChild(layer3D,0) self._layer3D = layer3D - local program = axb.ProgramManager:getInstance():loadProgram('custom/fog_vs', 'custom/fog_fs') + local program = axrhi.ProgramManager:getInstance():loadProgram('custom/fog_vs', 'custom/fog_fs') self._shader1 = ccb.ProgramState:new(program) self._shader2 = self._shader1:clone() - self._sprite3D1 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") - self._sprite3D2 = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") + self._sprite3D1 = ax.Sprite3D:create("MeshRendererTest/teapot.c3b") + self._sprite3D2 = ax.Sprite3D:create("MeshRendererTest/teapot.c3b") self._sprite3D1:setProgramState(self._shader1) self._sprite3D2:setProgramState(self._shader2) - + local attributes = self._shader1:getProgram():getActiveAttributes(); - self._shader1:setUniform("u_fogColor", cc.bytearray.from_vec4(cc.vec4(0.5,0.5,0.5,1.0))) - self._shader1:setUniform("u_fogStart",cc.bytearray.from_float(10)) - self._shader1:setUniform("u_fogEnd",cc.bytearray.from_float(60)) - self._shader1:setUniform("u_fogEquation" ,cc.bytearray.from_int(0)) + self._shader1:setUniform("u_fogColor", ax.bytearray.from_vec4(ax.vec4(0.5,0.5,0.5,1.0))) + self._shader1:setUniform("u_fogStart",ax.bytearray.from_float(10)) + self._shader1:setUniform("u_fogEnd",ax.bytearray.from_float(60)) + self._shader1:setUniform("u_fogEquation" ,ax.bytearray.from_int(0)) - self._shader2:setUniform("u_fogColor", cc.bytearray.from_vec4(cc.vec4(0.5,0.5,0.5,1.0))) - self._shader2:setUniform("u_fogStart",cc.bytearray.from_float(10)) - self._shader2:setUniform("u_fogEnd",cc.bytearray.from_float(60)) - self._shader2:setUniform("u_fogEquation" ,cc.bytearray.from_int(0)) + self._shader2:setUniform("u_fogColor", ax.bytearray.from_vec4(ax.vec4(0.5,0.5,0.5,1.0))) + self._shader2:setUniform("u_fogStart",ax.bytearray.from_float(10)) + self._shader2:setUniform("u_fogEnd",ax.bytearray.from_float(60)) + self._shader2:setUniform("u_fogEquation" ,ax.bytearray.from_int(0)) self._layer3D:addChild(self._sprite3D1) - self._sprite3D1:setPosition3D( cc.vec3( 0, 0,0 ) ) + self._sprite3D1:setPosition3D( ax.vec3( 0, 0,0 ) ) self._sprite3D1:setScale(2.0) - self._sprite3D1:setRotation3D(cc.vec3(-90,180,0)) + self._sprite3D1:setRotation3D(ax.vec3(-90,180,0)) self._layer3D:addChild(self._sprite3D2) - self._sprite3D2:setPosition3D( cc.vec3( 0, 0,-20 ) ) + self._sprite3D2:setPosition3D( ax.vec3( 0, 0,-20 ) ) self._sprite3D2:setScale(2.0) - self._sprite3D2:setRotation3D(cc.vec3(-90,180,0)) + self._sprite3D2:setRotation3D(ax.vec3(-90,180,0)) if self._camera == nil then - self._camera = cc.Camera:createPerspective(60, s.width/s.height, 1, 1000) - self._camera:setCameraFlag(cc.CameraFlag.USER1) - self._camera:setPosition3D(cc.vec3(0, 30, 40)) - self._camera:lookAt(cc.vec3(0,0,0), cc.vec3(0, 1, 0)) + self._camera = ax.Camera:createPerspective(60, s.width/s.height, 1, 1000) + self._camera:setCameraFlag(ax.CameraFlag.USER1) + self._camera:setPosition3D(ax.vec3(0, 30, 40)) + self._camera:lookAt(ax.vec3(0,0,0), ax.vec3(0, 1, 0)) self._layer3D:addChild(self._camera) end @@ -767,20 +767,20 @@ function FogTestDemo:createLayer3D() end function FogTestDemo:onEnter() - cc.Director:getInstance():setClearColor(cc.c4f(0.5,0.5,0.5,1)) + ax.Director:getInstance():setClearColor(ax.color(0.5,0.5,0.5,1)) self:setEventListener() self:createMenu() self:createLayer3D() end function FogTestDemo:onExit() - cc.Director:getInstance():setClearColor(cc.c4f(0,0,0,1)) + ax.Director:getInstance():setClearColor(ax.color(0,0,0,1)) if nil ~= self._camera then self._camera = nil end - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - if targetPlatform == cc.PLATFORM_OS_ANDROID or targetPlatform == cc.PLATFORM_OS_WINRT or targetPlatform == cc.PLATFORM_OS_WP8 then - cc.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + if targetPlatform == ax.PLATFORM_OS_ANDROID or targetPlatform == ax.PLATFORM_OS_WINRT or targetPlatform == ax.PLATFORM_OS_WP8 then + ax.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) end end @@ -792,14 +792,14 @@ function FogTestDemo:subtitle() return "" end -local OperateCamType = +local OperateCamType = { MoveCamera = 0, RotateCamera = 1, } local CameraArcBallDemo = class("CameraArcBallDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -819,7 +819,7 @@ function CameraArcBallDemo:init() self._radius = 1.0 self._distanceZ = 50.0 self._operate = OperateCamType.RotateCamera - self._center = cc.vec3(0, 0, 0) + self._center = ax.vec3(0, 0, 0) self._target = 0 Helper.titleLabel:setString(self:title()) @@ -839,7 +839,7 @@ function CameraArcBallDemo:projectToSphere(r, x, y) d = math.sqrt(x*x + y*y) --inside sphere if d < r * 0.70710678118654752440 then - z = math.sqrt(r*r - d*d) + z = math.sqrt(r*r - d*d) else--on hyperbola t = r / 1.41421356237309504880 z = t*t / d @@ -848,25 +848,25 @@ function CameraArcBallDemo:projectToSphere(r, x, y) end function CameraArcBallDemo:calculateArcBall(axis, angle, p1x, p1y, p2x, p2y) - local rotation_matrix = cc.mat4.createRotation(self._rotationQuat) + local rotation_matrix = ax.mat4.createRotation(self._rotationQuat) --rotation y local uv = mat4_transformVector(rotation_matrix , 0.0, 1.0, 0.0, 0.0) --rotation x local sv = mat4_transformVector(rotation_matrix, 1.0, 0.0, 0.0, 0.0) - --rotation z + --rotation z local lv = mat4_transformVector(rotation_matrix, 0.0, 0.0, -1.0, 0.0) --start point screen transform to 3d local projectZ1 = self:projectToSphere(self._radius, p1x, p1y) - local p1 = cc.vec3sub(cc.vec3add(cc.vec3mul(sv, p1x), cc.vec3mul(uv, p1y)), cc.vec3mul(lv, projectZ1)) + local p1 = ax.vec3sub(ax.vec3add(ax.vec3mul(sv, p1x), ax.vec3mul(uv, p1y)), ax.vec3mul(lv, projectZ1)) --end point screen transform to 3d local projectZ2 = self:projectToSphere(self._radius, p2x, p2y) - local p2 = cc.vec3sub(cc.vec3add(cc.vec3mul(sv, p2x), cc.vec3mul(uv, p2y)), cc.vec3mul(lv, projectZ2)) + local p2 = ax.vec3sub(ax.vec3add(ax.vec3mul(sv, p2x), ax.vec3mul(uv, p2y)), ax.vec3mul(lv, projectZ2)) --calculate rotation axis axis = vec3_cross(p2, p1, axis) - axis = cc.vec3normalize(axis) + axis = ax.vec3normalize(axis) - local pdiff = cc.vec3sub(p2, p1) - local t = math.sqrt(cc.vec3dot(pdiff, pdiff)) / (2.0 * self._radius) + local pdiff = ax.vec3sub(p2, p1) + local t = math.sqrt(ax.vec3dot(pdiff, pdiff)) / (2.0 * self._radius) --clamp -1 to 1 if t > 1.0 then t = 1.0 @@ -876,67 +876,67 @@ function CameraArcBallDemo:calculateArcBall(axis, angle, p1x, p1y, p2x, p2y) t = -1.0 end --rotation angle - angle = math.asin(t) + angle = math.asin(t) return axis, angle end function CameraArcBallDemo:setEventListener() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touchs, event) if #touchs ~= 0 then if self._operate == OperateCamType.RotateCamera then - local visibleSize = cc.Director:getInstance():getVisibleSize() + local visibleSize = ax.Director:getInstance():getVisibleSize() local prelocation = touchs[1]:getPreviousLocationInView() local location = touchs[1]:getLocationInView() location.x = 2.0 * (location.x) / (visibleSize.width) - 1.0 location.y = 2.0 * (visibleSize.height - location.y) / (visibleSize.height) - 1.0 prelocation.x = 2.0 * (prelocation.x) / (visibleSize.width) - 1.0 prelocation.y = 2.0 * (visibleSize.height - prelocation.y) / (visibleSize.height) - 1.0 - - local axes = cc.vec3(0,0,0) + + local axes = ax.vec3(0,0,0) local angle = 0.0 --calculate rotation quaternion parameters - axes , angle = self:calculateArcBall(axes, angle, prelocation.x, prelocation.y, location.x, location.y) - - --get rotation quaternion + axes , angle = self:calculateArcBall(axes, angle, prelocation.x, prelocation.y, location.x, location.y) + + --get rotation quaternion local halfAngle = angle * 0.5 local sinHalfAngle = math.sin(math.deg(halfAngle)) local normal = axes - normal = cc.vec3normalize(normal) - local quat = cc.quaternion(normal.x * sinHalfAngle, normal.y * sinHalfAngle, normal.z * sinHalfAngle, math.cos(math.deg(halfAngle))) + normal = ax.vec3normalize(normal) + local quat = ax.quaternion(normal.x * sinHalfAngle, normal.y * sinHalfAngle, normal.z * sinHalfAngle, math.cos(math.deg(halfAngle))) local x = quat.w * self._rotationQuat.x + quat.x * self._rotationQuat.w + quat.y * self._rotationQuat.z - quat.z * self._rotationQuat.y local y = quat.w * self._rotationQuat.y - quat.x * self._rotationQuat.z + quat.y * self._rotationQuat.w + quat.z * self._rotationQuat.x local z = quat.w * self._rotationQuat.z + quat.x * self._rotationQuat.y - quat.y * self._rotationQuat.x + quat.z * self._rotationQuat.w local w = quat.w * self._rotationQuat.w - quat.x * self._rotationQuat.x - quat.y * self._rotationQuat.y - quat.z * self._rotationQuat.z - self._rotationQuat = cc.quaternion(x, y, z, w) - + self._rotationQuat = ax.quaternion(x, y, z, w) + self:updateCameraTransform() - + elseif self._operate == OperateCamType.MoveCamera then local previousLocation = touchs[1]:getPreviousLocation() local location = touchs[1]:getLocation() - local newPos = cc.p(previousLocation.x - location.x, previousLocation.y - location.y) + local newPos = ax.p(previousLocation.x - location.x, previousLocation.y - location.y) self._distanceZ = self._distanceZ - newPos.y * 0.1 self:updateCameraTransform() end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) end function CameraArcBallDemo:createLayer3D() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - cc.MenuItemFont:setFontName("fonts/arial.ttf") - cc.MenuItemFont:setFontSize(20) - - local menuItem1 = cc.MenuItemFont:create("Switch Operation") - menuItem1:setColor(cc.c3b(0,200,20)) + ax.MenuItemFont:setFontName("fonts/arial.ttf") + ax.MenuItemFont:setFontSize(20) + + local menuItem1 = ax.MenuItemFont:create("Switch Operation") + menuItem1:setColor(ax.color32(0,200,20)) menuItem1:registerScriptTapHandler(function (tag, sender ) if self._operate == OperateCamType.MoveCamera then self._operate = OperateCamType.RotateCamera @@ -944,8 +944,8 @@ function CameraArcBallDemo:createLayer3D() self._operate = OperateCamType.MoveCamera end end) - local menuItem2 = cc.MenuItemFont:create("Switch Target") - menuItem2:setColor(cc.c3b(0,200,20)) + local menuItem2 = ax.MenuItemFont:create("Switch Target") + menuItem2:setColor(ax.color32(0,200,20)) menuItem2:registerScriptTapHandler(function (tag, sender ) if self._target == 0 then self._target = 1 @@ -957,49 +957,49 @@ function CameraArcBallDemo:createLayer3D() self:updateCameraTransform() end end) - local menu = cc.Menu:create(menuItem1,menuItem2) - menu:setPosition(cc.p(0.0, 0.0)) + local menu = ax.Menu:create(menuItem1,menuItem2) + menu:setPosition(ax.p(0.0, 0.0)) menuItem1:setPosition(VisibleRect:left().x + 80, VisibleRect:top().y -70) menuItem2:setPosition(VisibleRect:left().x + 80, VisibleRect:top().y -100) self:addChild(menu, 1) - local layer3D = cc.Layer:create() + local layer3D = ax.Layer:create() self:addChild(layer3D,0) self._layer3D = layer3D if self._camera == nil then - self._camera = cc.Camera:createPerspective(60, s.width/s.height, 1, 1000) - self._camera:setCameraFlag(cc.CameraFlag.USER1) - self._camera:setPosition3D(cc.vec3(0, 10, 50)) - self._camera:lookAt(cc.vec3(0, 0, 0), cc.vec3(0, 1, 0)) + self._camera = ax.Camera:createPerspective(60, s.width/s.height, 1, 1000) + self._camera:setCameraFlag(ax.CameraFlag.USER1) + self._camera:setPosition3D(ax.vec3(0, 10, 50)) + self._camera:lookAt(ax.vec3(0, 0, 0), ax.vec3(0, 1, 0)) self._layer3D:addChild(self._camera) end - self._sprite3D1 = cc.Sprite3D:create("MeshRendererTest/orc.c3b") + self._sprite3D1 = ax.Sprite3D:create("MeshRendererTest/orc.c3b") self._sprite3D1:setScale(0.5) - self._sprite3D1:setRotation3D(cc.vec3(0,180,0)) - self._sprite3D1:setPosition3D(cc.vec3(0,0,0)) + self._sprite3D1:setRotation3D(ax.vec3(0,180,0)) + self._sprite3D1:setPosition3D(ax.vec3(0,0,0)) self._layer3D:addChild(self._sprite3D1) - self._sprite3D2 = cc.Sprite3D:create("MeshRendererTest/boss.c3b") + self._sprite3D2 = ax.Sprite3D:create("MeshRendererTest/boss.c3b") self._sprite3D2:setScale(0.6) - self._sprite3D2:setRotation3D(cc.vec3(-90,0,0)) - self._sprite3D2:setPosition3D(cc.vec3(20,0,0)) + self._sprite3D2:setRotation3D(ax.vec3(-90,0,0)) + self._sprite3D2:setPosition3D(ax.vec3(20,0,0)) self._layer3D:addChild(self._sprite3D2) - self._drawGrid = cc.DrawNode3D:create() + self._drawGrid = ax.DrawNode3D:create() --draw x for j = -20, 20 do - self._drawGrid:drawLine(cc.vec3(-100, 0, 5*j), cc.vec3(100, 0, 5*j),cc.c4f(1, 0, 0, 1)) + self._drawGrid:drawLine(ax.vec3(-100, 0, 5*j), ax.vec3(100, 0, 5*j),ax.color(1, 0, 0, 1)) end --draw z for j = -20, 20 do - self._drawGrid:drawLine(cc.vec3(5*j, 0, -100), cc.vec3(5*j, 0, 100),cc.c4f(0,0,1,1)) + self._drawGrid:drawLine(ax.vec3(5*j, 0, -100), ax.vec3(5*j, 0, 100),ax.color(0,0,1,1)) end --draw y - self._drawGrid:drawLine(cc.vec3(0, 0, 0), cc.vec3(0,50,0), cc.c4f(0,1,0,1)) + self._drawGrid:drawLine(ax.vec3(0, 0, 0), ax.vec3(0,50,0), ax.color(0,1,0,1)) self._layer3D:addChild(self._drawGrid) @@ -1009,16 +1009,16 @@ end function CameraArcBallDemo:updateCameraTransform() -- body - local trans = cc.mat4.createTranslation(cc.vec3(0.0, 10.0, self._distanceZ)) - local rot = cc.mat4.new(cc.mat4.createRotation(self._rotationQuat)) - local center = cc.mat4.new(cc.mat4.createTranslation(self._center)) - local result = cc.mat4.new(center:multiply(rot)):multiply(trans) + local trans = ax.mat4.createTranslation(ax.vec3(0.0, 10.0, self._distanceZ)) + local rot = ax.mat4.new(ax.mat4.createRotation(self._rotationQuat)) + local center = ax.mat4.new(ax.mat4.createTranslation(self._center)) + local result = ax.mat4.new(center:multiply(rot)):multiply(trans) self._camera:setNodeToParentTransform(result) end function CameraArcBallDemo:onEnter() - self._rotationQuat = cc.quaternion(0.0, 0.0, 0.0, 1.0) + self._rotationQuat = ax.quaternion(0.0, 0.0, 0.0, 1.0) self:setEventListener() self:createLayer3D() end @@ -1039,9 +1039,9 @@ end function Camera3DTestMain() cclog("Camera3DTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { Camera3DTestDemo.create, CameraRotationTest.create, @@ -1050,7 +1050,7 @@ function Camera3DTestMain() } scene:addChild(Helper.createFunctionTable[1]()) scene:addChild(CreateBackMenuItem()) - + return scene end diff --git a/tests/lua-tests/Content/src/CaptureScreenTest/CaptureScreenTest.lua b/tests/lua-tests/Content/src/CaptureScreenTest/CaptureScreenTest.lua index 37d39ddc3ae1..cd6dc46d1065 100644 --- a/tests/lua-tests/Content/src/CaptureScreenTest/CaptureScreenTest.lua +++ b/tests/lua-tests/Content/src/CaptureScreenTest/CaptureScreenTest.lua @@ -1,40 +1,40 @@ -local winSize = cc.Director:getInstance():getWinSize() +local winSize = ax.Director:getInstance():getWinSize() local kTagSprite = 1 local childTag = 119 local function createLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local filename = "" - local title = cc.Label:createWithTTF("New Renderer", "fonts/arial.ttf", 36) - title:setColor(cc.c3b(255,255,0)) + local title = ax.Label:createWithTTF("New Renderer", "fonts/arial.ttf", 36) + title:setColor(ax.color32(255,255,0)) layer:addChild(title, 1, 10000) - title:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 30)) + title:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 30)) - local subTitle = cc.Label:createWithTTF("Capture screen test, press the menu items to capture the screen", "fonts/arial.ttf", 12) - subTitle:setColor(cc.c3b(255,255,0)) + local subTitle = ax.Label:createWithTTF("Capture screen test, press the menu items to capture the screen", "fonts/arial.ttf", 12) + subTitle:setColor(ax.color32(255,255,0)) layer:addChild(subTitle, 1, 10001) - subTitle:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 60) ) + subTitle:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 60) ) - local left = cc.p(winSize.width / 4, winSize.height / 2) - local right = cc.p(winSize.width / 4 * 3, winSize.height / 2) + local left = ax.p(winSize.width / 4, winSize.height / 2) + local right = ax.p(winSize.width / 4 * 3, winSize.height / 2) - local sp1 = cc.Sprite:create("Images/grossini.png") + local sp1 = ax.Sprite:create("Images/grossini.png") sp1:setPosition(left) - local move1 = cc.MoveBy:create(1, cc.p(winSize.width/2, 0)) - local seq1 = cc.RepeatForever:create(cc.Sequence:create(move1, move1:reverse())) + local move1 = ax.MoveBy:create(1, ax.p(winSize.width/2, 0)) + local seq1 = ax.RepeatForever:create(ax.Sequence:create(move1, move1:reverse())) layer:addChild(sp1) sp1:runAction(seq1) - local sp2 = cc.Sprite:create("Images/grossinis_sister1.png") + local sp2 = ax.Sprite:create("Images/grossinis_sister1.png") sp2:setPosition(right) - local move2 = cc.MoveBy:create(1, cc.p(-winSize.width/2, 0)) - local seq2 = cc.RepeatForever:create(cc.Sequence:create(move2, move2:reverse())) + local move2 = ax.MoveBy:create(1, ax.p(-winSize.width/2, 0)) + local seq2 = ax.RepeatForever:create(ax.Sequence:create(move2, move2:reverse())) layer:addChild(sp2) sp2:runAction(seq2) local function afterCaptured(succeed, outputFile) if succeed then - local sp = cc.Sprite:create(outputFile) + local sp = ax.Sprite:create(outputFile) layer:addChild(sp, 0, childTag) sp:setPosition(winSize.width / 2, winSize.height / 2) sp:setScale(0.25) @@ -45,19 +45,19 @@ local function createLayer() end local function onCaptured(tag, sender) - cc.Director:getInstance():getTextureCache():removeTextureForKey(fileName) + ax.Director:getInstance():getTextureCache():removeTextureForKey(fileName) layer:removeChildByTag(childTag) fileName = "CaptureScreenTest.png" - cc.utils:captureScreen(afterCaptured, fileName) + ax.utils:captureScreen(afterCaptured, fileName) end local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 24 - local label1 = cc.Label:createWithTTF(ttfConfig, "capture all", cc.TEXT_ALIGNMENT_CENTER, winSize.width) - local mi1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig, "capture all", ax.TEXT_ALIGNMENT_CENTER, winSize.width) + local mi1 = ax.MenuItemLabel:create(label1) mi1:registerScriptTapHandler(onCaptured) - local menu = cc.Menu:create(mi1) + local menu = ax.Menu:create(mi1) layer:addChild(menu) menu:setPosition(winSize.width / 2, winSize.height / 4) @@ -68,7 +68,7 @@ end -- CaptureScreen -------------------------------- function CaptureScreenTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(createLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ClickAndMoveTest/ClickAndMoveTest.lua b/tests/lua-tests/Content/src/ClickAndMoveTest/ClickAndMoveTest.lua index 87f49208b7da..64800d6c3327 100644 --- a/tests/lua-tests/Content/src/ClickAndMoveTest/ClickAndMoveTest.lua +++ b/tests/lua-tests/Content/src/ClickAndMoveTest/ClickAndMoveTest.lua @@ -1,33 +1,33 @@ -local size = cc.Director:getInstance():getWinSize() +local size = ax.Director:getInstance():getWinSize() local layer = nil local kTagSprite = 1 local function initWithLayer() - local sprite = cc.Sprite:create(s_pPathGrossini) + local sprite = ax.Sprite:create(s_pPathGrossini) - local bgLayer = cc.LayerColor:create(cc.c4b(255,255,0,255)) + local bgLayer = ax.LayerColor:create(ax.color32(255,255,0,255)) layer:addChild(bgLayer, -1) layer:addChild(sprite, 0, kTagSprite) - sprite:setPosition(cc.p(20,150)) + sprite:setPosition(ax.p(20,150)) - sprite:runAction(cc.JumpTo:create(4, cc.p(300,48), 100, 4)) + sprite:runAction(ax.JumpTo:create(4, ax.p(300,48), 100, 4)) - bgLayer:runAction(cc.RepeatForever:create(cc.Sequence:create( - cc.FadeIn:create(1), - cc.FadeOut:create(1)))) + bgLayer:runAction(ax.RepeatForever:create(ax.Sequence:create( + ax.FadeIn:create(1), + ax.FadeOut:create(1)))) local function onTouchBegan(touch, event) return true end local function onTouchEnded(touch, event) - + local location = touch:getLocation() local s = layer:getChildByTag(kTagSprite) s:stopAllActions() - s:runAction(cc.MoveTo:create(1, cc.p(location.x, location.y))) + s:runAction(ax.MoveTo:create(1, ax.p(location.x, location.y))) local posX, posY = s:getPosition() local o = location.x - posX local a = location.y - posY @@ -40,12 +40,12 @@ local function initWithLayer() at = 180 - math.abs(at) end end - s:runAction(cc.RotateTo:create(1, at)) + s:runAction(ax.RotateTo:create(1, at)) end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -57,13 +57,13 @@ end -------------------------------- function ClickAndMoveTest() cclog("ClickAndMoveTest") - local scene = cc.Scene:create() - layer = cc.Layer:create() + local scene = ax.Scene:create() + layer = ax.Layer:create() initWithLayer() scene:addChild(layer) scene:addChild(CreateBackMenuItem()) - + return scene end diff --git a/tests/lua-tests/Content/src/ComponentTest/enemy.lua b/tests/lua-tests/Content/src/ComponentTest/enemy.lua index 47898fa1dea6..fc507a28fd20 100644 --- a/tests/lua-tests/Content/src/ComponentTest/enemy.lua +++ b/tests/lua-tests/Content/src/ComponentTest/enemy.lua @@ -3,7 +3,7 @@ local enemy = { onEnter = function(self) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() local winSize = director:getVisibleSize() local visibleOrigin = director:getVisibleOrigin() local owner = self:getOwner() @@ -18,11 +18,11 @@ local enemy = { local maxDuration = 4; local rangeDuration = maxDuration - minDuration local actualDuration = math.random(1000) % rangeDuration + minDuration - local actionMove = cc.MoveTo:create(actualDuration * 2, cc.p(0 - contentSize.width/2, actualY)) + local actionMove = ax.MoveTo:create(actualDuration * 2, ax.p(0 - contentSize.width/2, actualY)) local sceneScriptComponent = tolua.cast(owner:getParent():getComponent("sceneLuaComponent"), "ax.ComponentLua") local sceneScript = sceneScriptComponent:getScriptObject() - local actionMoveDone = cc.CallFunc:create(sceneScript.looseGame) - owner:runAction(cc.Sequence:create(actionMove, actionMoveDone)) + local actionMoveDone = ax.CallFunc:create(sceneScript.looseGame) + owner:runAction(ax.Sequence:create(actionMove, actionMoveDone)) end, onExit = function(self) diff --git a/tests/lua-tests/Content/src/ComponentTest/gameoverscene.lua b/tests/lua-tests/Content/src/ComponentTest/gameoverscene.lua index 7bc0a6178606..a958f3e1fde8 100644 --- a/tests/lua-tests/Content/src/ComponentTest/gameoverscene.lua +++ b/tests/lua-tests/Content/src/ComponentTest/gameoverscene.lua @@ -1,30 +1,30 @@ local GameOverLayer = { - + create = function(self, content) - local label = cc.Label:createWithTTF(content, "fonts/Marker Felt.ttf", 32) - local winSize = cc.Director:getInstance():getWinSize() - label:setColor(cc.c3b(0, 0, 0)) + local label = ax.Label:createWithTTF(content, "fonts/Marker Felt.ttf", 32) + local winSize = ax.Director:getInstance():getWinSize() + label:setColor(ax.color32(0, 0, 0)) label:setPosition(winSize.width/2, winSize.height/2) - local layer = cc.LayerColor:create(cc.c4b(0, 128, 255, 255)) + local layer = ax.LayerColor:create(ax.color32(0, 128, 255, 255)) layer:addChild(label) - layer:runAction(cc.Sequence:create(cc.DelayTime:create(3), cc.CallFunc:create(self.gameOverDone))) + layer:runAction(ax.Sequence:create(ax.DelayTime:create(3), ax.CallFunc:create(self.gameOverDone))) return layer end, gameOverDone = function(self, node) -- send event - cc.Director:getInstance():getEventDispatcher():dispatchCustomEvent("component game over") + ax.Director:getInstance():getEventDispatcher():dispatchCustomEvent("component game over") end } GameOverScene = { create = function(label) - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = GameOverLayer:create(label) scene:addChild(layer) return scene end -} \ No newline at end of file +} diff --git a/tests/lua-tests/Content/src/ComponentTest/main.lua b/tests/lua-tests/Content/src/ComponentTest/main.lua index 510c06af8be0..b553f3132adc 100644 --- a/tests/lua-tests/Content/src/ComponentTest/main.lua +++ b/tests/lua-tests/Content/src/ComponentTest/main.lua @@ -1,43 +1,43 @@ local function ComponentTestLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() -- set background color - local bgLayer = cc.LayerColor:create(cc.c4b(0, 128, 255, 255)); + local bgLayer = ax.LayerColor:create(ax.color32(0, 128, 255, 255)); layer:addChild(bgLayer); -- create game scene - local sceneLuaComponent = cc.ComponentLua:create("ComponentTest/scene.lua"); + local sceneLuaComponent = ax.ComponentLua:create("ComponentTest/scene.lua"); sceneLuaComponent:setName("sceneLuaComponent"); layer:addComponent(sceneLuaComponent); -- add player - local player = cc.Sprite:create("components/Player.png", cc.rect(0, 0, 27, 40)); - local visibleSize = cc.Director:getInstance():getVisibleSize(); - local origin = cc.Director:getInstance():getVisibleOrigin(); + local player = ax.Sprite:create("components/Player.png", ax.rect(0, 0, 27, 40)); + local visibleSize = ax.Director:getInstance():getVisibleSize(); + local origin = ax.Director:getInstance():getVisibleOrigin(); player:setPosition(origin.x + player:getContentSize().width/2, origin.y + visibleSize.height/2); - local playerComponent = cc.ComponentLua:create("ComponentTest/player.lua"); + local playerComponent = ax.ComponentLua:create("ComponentTest/player.lua"); player:addComponent(playerComponent); layer:addChild(player); local function onEvent(event) - cc.AudioEngine:stopAll() - local scene = cc.Scene:create() + ax.AudioEngine:stopAll() + local scene = ax.Scene:create() scene:addChild(ComponentTestLayer()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene); + ax.Director:getInstance():replaceScene(scene); end local function onNodeEvent(event) if "exit" == event then - cc.AudioEngine:stopAll() + ax.AudioEngine:stopAll() end end - layer._listener1 = cc.EventListenerCustom:create("component game over", onEvent) - local eventDispatcher = cc.Director:getInstance():getEventDispatcher() + layer._listener1 = ax.EventListenerCustom:create("component game over", onEvent) + local eventDispatcher = ax.Director:getInstance():getEventDispatcher() eventDispatcher:addEventListenerWithFixedPriority(layer._listener1, 1) layer:registerScriptHandler(onNodeEvent) @@ -49,7 +49,7 @@ end function ComponentTestMain() cclog("ComponentTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(ComponentTestLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ComponentTest/player.lua b/tests/lua-tests/Content/src/ComponentTest/player.lua index 7955b48ef7c7..a6655f25c57f 100644 --- a/tests/lua-tests/Content/src/ComponentTest/player.lua +++ b/tests/lua-tests/Content/src/ComponentTest/player.lua @@ -1,16 +1,16 @@ local player = { generateProjectile = function (self, x, y) - local projectile = cc.Sprite:create("components/Projectile.png", cc.rect(0, 0, 20, 20)) - local scriptComponent = cc.ComponentLua:create("ComponentTest/projectile.lua") + local projectile = ax.Sprite:create("components/Projectile.png", ax.rect(0, 0, 20, 20)) + local scriptComponent = ax.ComponentLua:create("ComponentTest/projectile.lua") projectile:addComponent(scriptComponent) self:getOwner():getParent():addChild(projectile) -- set position - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() local winSize = director:getVisibleSize() local visibleOrigin = director:getVisibleOrigin() - projectile:setPosition(cc.p(visibleOrigin.x + 20, visibleOrigin.y + winSize.height/2)) + projectile:setPosition(ax.p(visibleOrigin.x + 20, visibleOrigin.y + winSize.height/2)) -- run action local posX, posY = projectile:getPosition() @@ -25,7 +25,7 @@ local player = { local realX = visibleOrigin.x + winSize.width + contentSize.width/2 local ratio = offY / offX local realY = (realX * ratio) + posY - local realDest = cc.p(realX, realY) + local realDest = ax.p(realX, realY) local offRealX = realX - posX local offRealY = realY - posY @@ -33,19 +33,19 @@ local player = { local velocity = 960 local realMoveDuration = length / velocity - projectile:runAction(cc.MoveTo:create(realMoveDuration, realDest)) + projectile:runAction(ax.MoveTo:create(realMoveDuration, realDest)) end, onEnter = function(self) local function onTouchesEnded(touches, event) local location = touches[1]:getLocation() self:generateProjectile(location.x, location.y) - cc.AudioEngine:play2d("pew-pew-lei.wav") + ax.AudioEngine:play2d("pew-pew-lei.wav") end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesEnded, cc.Handler.EVENT_TOUCHES_ENDED) - local eventDispatcher = cc.Director:getInstance():getEventDispatcher() + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesEnded, ax.Handler.EVENT_TOUCHES_ENDED) + local eventDispatcher = ax.Director:getInstance():getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self:getOwner()) end, } diff --git a/tests/lua-tests/Content/src/ComponentTest/projectile.lua b/tests/lua-tests/Content/src/ComponentTest/projectile.lua index 4a903b697fb5..39dbe8225617 100644 --- a/tests/lua-tests/Content/src/ComponentTest/projectile.lua +++ b/tests/lua-tests/Content/src/ComponentTest/projectile.lua @@ -15,7 +15,7 @@ local projectile = { local owner = self:getOwner() local projectileX, projectileY = owner:getPosition() local projectileContentSize = owner:getContentSize() - local projectileRect = cc.rect(projectileX, projectileY, + local projectileRect = ax.rect(projectileX, projectileY, projectileContentSize.width, projectileContentSize.height) local scene = owner:getParent() @@ -27,9 +27,9 @@ local projectile = { local enemy = enemies[i] local enemyX, enemyY = enemy:getPosition() local enemyContentSize = enemy:getContentSize() - local enemyRect = cc.rect(enemyX, enemyY, + local enemyRect = ax.rect(enemyX, enemyY, enemyContentSize.width, enemyContentSize.height) - if cc.rectIntersectsRect(projectileRect, enemyRect) then + if ax.rectIntersectsRect(projectileRect, enemyRect) then table.remove(enemies, i) scene:removeChild(enemy, true) self.sceneLua:inscreaseCount() diff --git a/tests/lua-tests/Content/src/ComponentTest/scene.lua b/tests/lua-tests/Content/src/ComponentTest/scene.lua index 321b5dce7d9b..60cc745df80b 100644 --- a/tests/lua-tests/Content/src/ComponentTest/scene.lua +++ b/tests/lua-tests/Content/src/ComponentTest/scene.lua @@ -10,7 +10,7 @@ local scene = { enemies = {}, onEnter = function(self) - cc.AudioEngine:play2d("background-music-aac.mp3", true) + ax.AudioEngine:play2d("background-music-aac.mp3", true) end, update = function(self, dt) @@ -23,8 +23,8 @@ local scene = { addNewEnemy = function(self) local owner = self:getOwner() - local enemy = cc.Sprite:create("components/Target.png") - local enemyLuaComponent = cc.ComponentLua:create("ComponentTest/enemy.lua") + local enemy = ax.Sprite:create("components/Target.png") + local enemyLuaComponent = ax.ComponentLua:create("ComponentTest/enemy.lua") enemy:addComponent(enemyLuaComponent) owner:addChild(enemy) table.insert(self.enemies, enemy) @@ -32,14 +32,14 @@ local scene = { looseGame = function(node) local scene = GameOverScene.create("You Lose :[") - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end, inscreaseCount = function(self) self.numEnemyDestroyed = self.numEnemyDestroyed + 1 if self.numEnemyDestroyed >=5 then local scene = GameOverScene.create("You Win!") - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end end } diff --git a/tests/lua-tests/Content/src/CurrentLanguageTest/CurrentLanguageTest.lua b/tests/lua-tests/Content/src/CurrentLanguageTest/CurrentLanguageTest.lua index 709fa5c6effe..d1a2ce223d06 100644 --- a/tests/lua-tests/Content/src/CurrentLanguageTest/CurrentLanguageTest.lua +++ b/tests/lua-tests/Content/src/CurrentLanguageTest/CurrentLanguageTest.lua @@ -1,39 +1,39 @@ local function CurrentLanguageTest() - local ret = cc.Layer:create() - local label = cc.Label:createWithTTF("Current language Test", s_arialPath, 28) + local ret = ax.Layer:create() + local label = ax.Label:createWithTTF("Current language Test", s_arialPath, 28) ret:addChild(label, 0) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y-50) ) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y-50) ) - local labelLanguage = cc.Label:createWithTTF("", s_arialPath, 20) - labelLanguage:setAnchorPoint(cc.p(0.5, 0.5)) + local labelLanguage = ax.Label:createWithTTF("", s_arialPath, 20) + labelLanguage:setAnchorPoint(ax.p(0.5, 0.5)) labelLanguage:setPosition(VisibleRect:center()) - local currentLanguageType = cc.Application:getInstance():getCurrentLanguage() + local currentLanguageType = ax.Application:getInstance():getCurrentLanguage() - if currentLanguageType == cc.LANGUAGE_ENGLISH then + if currentLanguageType == ax.LANGUAGE_ENGLISH then labelLanguage:setString("current language is English") - elseif currentLanguageType == cc.LANGUAGE_CHINESE then + elseif currentLanguageType == ax.LANGUAGE_CHINESE then labelLanguage:setString("current language is Chinese") - elseif currentLanguageType == cc.LANGUAGE_FRENCH then + elseif currentLanguageType == ax.LANGUAGE_FRENCH then labelLanguage:setString("current language is French") - elseif currentLanguageType == cc.LANGUAGE_GERMAN then + elseif currentLanguageType == ax.LANGUAGE_GERMAN then labelLanguage:setString("current language is German") - elseif currentLanguageType == cc.LANGUAGE_ITALIAN then + elseif currentLanguageType == ax.LANGUAGE_ITALIAN then labelLanguage:setString("current language is Italian") - elseif currentLanguageType == cc.LANGUAGE_RUSSIAN then + elseif currentLanguageType == ax.LANGUAGE_RUSSIAN then labelLanguage:setString("current language is Russian") - elseif currentLanguageType == cc.LANGUAGE_SPANISH then + elseif currentLanguageType == ax.LANGUAGE_SPANISH then labelLanguage:setString("current language is Spanish") - elseif currentLanguageType == cc.LANGUAGE_KOREAN then + elseif currentLanguageType == ax.LANGUAGE_KOREAN then labelLanguage:setString("current language is Korean") - elseif currentLanguageType == cc.LANGUAGE_JAPANESE then + elseif currentLanguageType == ax.LANGUAGE_JAPANESE then labelLanguage:setString("current language is Japanese") - elseif currentLanguageType == cc.LANGUAGE_HUNGARIAN then + elseif currentLanguageType == ax.LANGUAGE_HUNGARIAN then labelLanguage:setString("current language is Hungarian") - elseif currentLanguageType == cc.LANGUAGE_PORTUGUESE then + elseif currentLanguageType == ax.LANGUAGE_PORTUGUESE then labelLanguage:setString("current language is Portuguese") - elseif currentLanguageType == cc.LANGUAGE_ARABIC then + elseif currentLanguageType == ax.LANGUAGE_ARABIC then labelLanguage:setString("current language is Arabic") end ret:addChild(labelLanguage) @@ -41,7 +41,7 @@ local function CurrentLanguageTest() end function CurrentLanguageTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() local pLayer = CurrentLanguageTest() scene:addChild(pLayer) scene:addChild(CreateBackMenuItem()) diff --git a/tests/lua-tests/Content/src/DownloaderTest/DownloaderTest.lua b/tests/lua-tests/Content/src/DownloaderTest/DownloaderTest.lua index 489cb2a49219..c9eef88619b4 100644 --- a/tests/lua-tests/Content/src/DownloaderTest/DownloaderTest.lua +++ b/tests/lua-tests/Content/src/DownloaderTest/DownloaderTest.lua @@ -4,33 +4,33 @@ local json = cjson local imgURI = "https://forum.cocos.com/images/logo.png" local notExistURI = "https://www.cocos2d-x.org/attachments/1503/no_exist.txt" -local writablePath = cc.FileUtils:getInstance():getWritablePath() +local writablePath = ax.FileUtils:getInstance():getWritablePath() local function DownloaderLayer() - local layer = cc.Layer:create() - local winSize = cc.Director:getInstance():getWinSize() + local layer = ax.Layer:create() + local winSize = ax.Director:getInstance():getWinSize() local margin = 40 local space = 35 local task1 = nil local task2 = nil - local downloader = cc.Downloader.new() - + local downloader = ax.Downloader.new() + local function init() - local label = cc.Label:createWithTTF("Downloader Test", s_arialPath, 28) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(winSize.width / 2, winSize.height - margin)) + local label = ax.Label:createWithTTF("Downloader Test", s_arialPath, 28) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(winSize.width / 2, winSize.height - margin)) layer:addChild(label, 0) --Response Code Label - local labelStatusCode = cc.Label:createWithTTF("status", s_markerFeltFontPath, 20) - labelStatusCode:setAnchorPoint(cc.p(0.5, 0.5)) - labelStatusCode:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 6 * space)) + local labelStatusCode = ax.Label:createWithTTF("status", s_markerFeltFontPath, 20) + labelStatusCode:setAnchorPoint(ax.p(0.5, 0.5)) + labelStatusCode:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 6 * space)) layer:addChild(labelStatusCode) - local menuRequest = cc.Menu:create() - menuRequest:setPosition(cc.p(0,0)) + local menuRequest = ax.Menu:create() + menuRequest:setPosition(ax.p(0,0)) layer:addChild(menuRequest) --success @@ -39,11 +39,11 @@ local function DownloaderLayer() labelStatusCode:setString("waiting...") end - local labelGet = cc.Label:createWithTTF("Test Download Image", s_arialPath, 22) - labelGet:setAnchorPoint(cc.p(0.5, 0.5)) - local itemGet = cc.MenuItemLabel:create(labelGet) + local labelGet = ax.Label:createWithTTF("Test Download Image", s_arialPath, 22) + labelGet:setAnchorPoint(ax.p(0.5, 0.5)) + local itemGet = ax.MenuItemLabel:create(labelGet) itemGet:registerScriptTapHandler(onDownloadFileClicked) - itemGet:setPosition(cc.p(winSize.width / 2, winSize.height - margin - space)) + itemGet:setPosition(ax.p(winSize.width / 2, winSize.height - margin - space)) menuRequest:addChild(itemGet) --failure @@ -52,11 +52,11 @@ local function DownloaderLayer() labelStatusCode:setString("waiting...") end - local labelPost = cc.Label:createWithTTF("Test Download File Not Exists", s_arialPath, 22) - labelPost:setAnchorPoint(cc.p(0.5, 0.5)) - local itemPost = cc.MenuItemLabel:create(labelPost) + local labelPost = ax.Label:createWithTTF("Test Download File Not Exists", s_arialPath, 22) + labelPost:setAnchorPoint(ax.p(0.5, 0.5)) + local itemPost = ax.MenuItemLabel:create(labelPost) itemPost:registerScriptTapHandler(onDownloadTxtClicked) - itemPost:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 2 * space)) + itemPost:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 2 * space)) menuRequest:addChild(itemPost) local function onTaskSuccess(task) @@ -98,7 +98,7 @@ local function DownloaderLayer() end function DownloaderTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(DownloaderLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/DrawPrimitivesTest/DrawPrimitivesTest.lua b/tests/lua-tests/Content/src/DrawPrimitivesTest/DrawPrimitivesTest.lua index 979fc5ef26cc..5d8ee794615a 100644 --- a/tests/lua-tests/Content/src/DrawPrimitivesTest/DrawPrimitivesTest.lua +++ b/tests/lua-tests/Content/src/DrawPrimitivesTest/DrawPrimitivesTest.lua @@ -5,7 +5,7 @@ local function drawPrimitivesMainLayer() local testCount = 1 local maxCases = testCount local curCase = 0 - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() local curLayer = nil local function orderCallbackMenu() @@ -16,34 +16,34 @@ local function drawPrimitivesMainLayer() end showCurrentTest() end - + local function restartCallback() showCurrentTest() end - + local function nextCallback() curCase = curCase + 1 curCase = curCase % maxCases showCurrentTest() end - local ordercallbackmenu = cc.Menu:create() - local size = cc.Director:getInstance():getWinSize() - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) + local ordercallbackmenu = ax.Menu:create() + local size = ax.Director:getInstance():getWinSize() + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) item1:registerScriptTapHandler(backCallback) ordercallbackmenu:addChild(item1,kItemTagBasic) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) item2:registerScriptTapHandler(restartCallback) ordercallbackmenu:addChild(item2,kItemTagBasic) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) - ordercallbackmenu:addChild(item3,kItemTagBasic) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) + ordercallbackmenu:addChild(item3,kItemTagBasic) item3:registerScriptTapHandler(nextCallback) - - item1:setPosition(cc.p(size.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(size.width / 2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(size.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - - ordercallbackmenu:setPosition(cc.p(0, 0)) + + item1:setPosition(ax.p(size.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(size.width / 2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(size.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + + ordercallbackmenu:setPosition(ax.p(0, 0)) return ordercallbackmenu end @@ -51,124 +51,124 @@ local function drawPrimitivesMainLayer() local function GetTitle() return "Test DrawNode" end - + local function GetSubTitle() return "Testing DrawNode - batched draws. Concave polygons are BROKEN" end local function InitTitle(layer) --Title - local lableTitle = cc.Label:createWithTTF(GetTitle(), s_arialPath, 40) + local lableTitle = ax.Label:createWithTTF(GetTitle(), s_arialPath, 40) layer:addChild(lableTitle, 15) - lableTitle:setAnchorPoint(cc.p(0.5, 0.5)) - lableTitle:setPosition(cc.p(size.width / 2, size.height - 32)) - lableTitle:setColor(cc.c3b(255, 255, 40)) + lableTitle:setAnchorPoint(ax.p(0.5, 0.5)) + lableTitle:setPosition(ax.p(size.width / 2, size.height - 32)) + lableTitle:setColor(ax.color32(255, 255, 40)) --SubTitle - local subLabelTitle = cc.Label:createWithTTF(GetSubTitle(), s_thonburiPath, 16) + local subLabelTitle = ax.Label:createWithTTF(GetSubTitle(), s_thonburiPath, 16) layer:addChild(subLabelTitle, 15) - subLabelTitle:setAnchorPoint(cc.p(0.5, 0.5)) - subLabelTitle:setPosition(cc.p(size.width / 2, size.height - 80)) + subLabelTitle:setAnchorPoint(ax.p(0.5, 0.5)) + subLabelTitle:setPosition(ax.p(size.width / 2, size.height - 80)) end local function createDrawNodeTest() - local layer = cc.Layer:create() + local layer = ax.Layer:create() InitTitle(layer) - local draw = cc.DrawNode:create() + local draw = ax.DrawNode:create() layer:addChild(draw, 10) --draw 1 point - draw:drawPoint(cc.p(60,60), 4, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 1)) + draw:drawPoint(ax.p(60,60), 4, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 1)) --draw 4 small points - local fourpoints = { cc.p(60,60), cc.p(70,70), cc.p(60,70), cc.p(70,60) } - draw:drawPoints(fourpoints, 4, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 1)) + local fourpoints = { ax.p(60,60), ax.p(70,70), ax.p(60,70), ax.p(70,60) } + draw:drawPoints(fourpoints, 4, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 1)) --draw a line - draw:drawLine(cc.p(0,0), cc.p(size.width, size.height), cc.c4f(0,1,0,1)) - + draw:drawLine(ax.p(0,0), ax.p(size.width, size.height), ax.color(0,1,0,1)) + --draw a rectangle - draw:drawRect(cc.p(23,23), cc.p(7,7), cc.c4f(1,1,0,1)) + draw:drawRect(ax.p(23,23), ax.p(7,7), ax.color(1,1,0,1)) --draw a solid polygon - local vertices3 = { cc.p(60,160), cc.p(70,190), cc.p(100,190), cc.p(90,160) } - draw:drawSolidPoly( vertices3, 4, cc.c4f(0,0,1,1) ) - + local vertices3 = { ax.p(60,160), ax.p(70,190), ax.p(100,190), ax.p(90,160) } + draw:drawSolidPoly( vertices3, 4, ax.color(0,0,1,1) ) + --draw a solid rectangle - draw:drawSolidRect(cc.p(10,10), cc.p(20,20), cc.c4f(1,1,0,1)) + draw:drawSolidRect(ax.p(10,10), ax.p(20,20), ax.color(1,1,0,1)) --draw a solid circle - draw:drawSolidCircle(cc.p(VisibleRect:center().x + 140 ,VisibleRect:center().y), 100, math.pi/2, 50, 1.0, 2.0, cc.c4f(1,0,0,0.2)) - + draw:drawSolidCircle(ax.p(VisibleRect:center().x + 140 ,VisibleRect:center().y), 100, math.pi/2, 50, 1.0, 2.0, ax.color(1,0,0,0.2)) + --draw open random color poly - local vertices = { cc.p(0,0), cc.p(50,50), cc.p(100,50), cc.p(100,100), cc.p(50,100) } - draw:drawPoly( vertices, 5, false, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 1)) - + local vertices = { ax.p(0,0), ax.p(50,50), ax.p(100,50), ax.p(100,100), ax.p(50,100) } + draw:drawPoly( vertices, 5, false, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 1)) + --draw closed random color poly - local vertices2 = { cc.p(30,130), cc.p(30,230), cc.p(50,200) } - draw:drawPoly( vertices2, 3, true, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 1)) - + local vertices2 = { ax.p(30,130), ax.p(30,230), ax.p(50,200) } + draw:drawPoly( vertices2, 3, true, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 1)) + --draw two circle - draw:drawCircle(cc.p(VisibleRect:center().x + 140 ,VisibleRect:center().y), 110, math.pi/2, 50, true, 1.0, 2.0, cc.c4f(1.0, 0.0, 0.0, 0.5)) - - draw:drawCircle(cc.p(VisibleRect:center().x - 140 ,VisibleRect:center().y), 50, math.pi/2, 30, false, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 1)) - + draw:drawCircle(ax.p(VisibleRect:center().x + 140 ,VisibleRect:center().y), 110, math.pi/2, 50, true, 1.0, 2.0, ax.color(1.0, 0.0, 0.0, 0.5)) + + draw:drawCircle(ax.p(VisibleRect:center().x - 140 ,VisibleRect:center().y), 50, math.pi/2, 30, false, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 1)) + --draw some beziers - draw:drawQuadBezier(cc.p(size.width - 150, size.height - 150), cc.p(size.width - 70, size.height - 10), cc.p(size.width - 10, size.height - 10), 10, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) - - draw:drawQuadBezier(cc.p(0, size.height), cc.p(size.width/2, size.height/2), cc.p(size.width, size.height), 50, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) - - draw:drawCubicBezier(cc.p(VisibleRect:center()), cc.p(VisibleRect:center().x+30,VisibleRect:center().y+50), cc.p(VisibleRect:center().x+60,VisibleRect:center().y-50),VisibleRect:right(),100, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + draw:drawQuadBezier(ax.p(size.width - 150, size.height - 150), ax.p(size.width - 70, size.height - 10), ax.p(size.width - 10, size.height - 10), 10, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + + draw:drawQuadBezier(ax.p(0, size.height), ax.p(size.width/2, size.height/2), ax.p(size.width, size.height), 50, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + + draw:drawCubicBezier(ax.p(VisibleRect:center()), ax.p(VisibleRect:center().x+30,VisibleRect:center().y+50), ax.p(VisibleRect:center().x+60,VisibleRect:center().y-50),VisibleRect:right(),100, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) --draw Cardinal spline and catmullrom local array = { - cc.p(0, 0), - cc.p(size.width / 2 - 30, 0), - cc.p(size.width / 2 - 30, size.height - 80), - cc.p(0, size.height - 80), - cc.p(0, 0) } - draw:drawCardinalSpline(array, 0.5, 50, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + ax.p(0, 0), + ax.p(size.width / 2 - 30, 0), + ax.p(size.width / 2 - 30, size.height - 80), + ax.p(0, size.height - 80), + ax.p(0, 0) } + draw:drawCardinalSpline(array, 0.5, 50, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) local array2 = { - cc.p(size.width / 2, 30), - cc.p(size.width - 80, 30), - cc.p(size.width - 80, size.height - 80), - cc.p(size.width / 2, size.height - 80), - cc.p(size.width / 2, 30) } - draw:drawCatmullRom(array2, 50, cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + ax.p(size.width / 2, 30), + ax.p(size.width - 80, 30), + ax.p(size.width - 80, size.height - 80), + ax.p(size.width / 2, size.height - 80), + ax.p(size.width / 2, 30) } + draw:drawCatmullRom(array2, 50, ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) --Draw 10 circles for i=1, 10 do - draw:drawDot(cc.p(size.width/2, size.height/2), 10*(10-i), cc.c4f(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) + draw:drawDot(ax.p(size.width/2, size.height/2), 10*(10-i), ax.color(math.random(0,1), math.random(0,1), math.random(0,1), 0.5)) end --Draw polygons - points = { cc.p(size.height/4, 0), cc.p(size.width, size.height / 5), cc.p(size.width / 3 * 2, size.height) } - draw:drawPolygon(points, #(points), cc.c4f(1,0,0,0.5), 4, cc.c4f(0,0,1,1)) + points = { ax.p(size.height/4, 0), ax.p(size.width, size.height / 5), ax.p(size.width / 3 * 2, size.height) } + draw:drawPolygon(points, #(points), ax.color(1,0,0,0.5), 4, ax.color(0,0,1,1)) local o = 80 local w = 20 local h = 50 - local star1 = { cc.p( o + w, o - h), cc.p(o + w * 2, o), cc.p(o + w * 2 + h, o + w), cc.p(o + w * 2, o + w * 2) } - - draw:drawPolygon(star1, #(star1), cc.c4f(1,0,0,0.5), 1, cc.c4f(0,0,1,1)) + local star1 = { ax.p( o + w, o - h), ax.p(o + w * 2, o), ax.p(o + w * 2 + h, o + w), ax.p(o + w * 2, o + w * 2) } + + draw:drawPolygon(star1, #(star1), ax.color(1,0,0,0.5), 1, ax.color(0,0,1,1)) o = 180 w = 20 h = 50 local star2 = { - cc.p(o, o), cc.p(o + w, o - h), cc.p(o + w * 2, o), --lower spike - cc.p(o + w * 2 + h, o + w ), cc.p(o + w * 2, o + w * 2), --right spike - cc.p(o + w, o + w * 2 + h), cc.p(o, o + w * 2), --top spike - cc.p(o - h, o + w), --left spike + ax.p(o, o), ax.p(o + w, o - h), ax.p(o + w * 2, o), --lower spike + ax.p(o + w * 2 + h, o + w ), ax.p(o + w * 2, o + w * 2), --right spike + ax.p(o + w, o + w * 2 + h), ax.p(o, o + w * 2), --top spike + ax.p(o - h, o + w), --left spike }; - - draw:drawPolygon(star2, #(star2), cc.c4f(1,0,0,0.5), 1, cc.c4f(0,0,1,1)) - draw:drawSegment(cc.p(20,size.height), cc.p(20,size.height/2), 10, cc.c4f(0, 1, 0, 1)) + draw:drawPolygon(star2, #(star2), ax.color(1,0,0,0.5), 1, ax.color(0,0,1,1)) + + draw:drawSegment(ax.p(20,size.height), ax.p(20,size.height/2), 10, ax.color(0, 1, 0, 1)) - draw:drawSegment(cc.p(10,size.height/2), cc.p(size.width/2, size.height/2), 40, cc.c4f(1, 0, 1, 0.5)) + draw:drawSegment(ax.p(10,size.height/2), ax.p(size.width/2, size.height/2), 40, ax.color(1, 0, 1, 0.5)) return layer end @@ -177,17 +177,17 @@ local function drawPrimitivesMainLayer() return createDrawNodeTest() end - function showCurrentTest() - local curScene = cc.Scene:create() + function showCurrentTest() + local curScene = ax.Scene:create() if nil ~= curScene then curLayer = createLayerByCurCase(curCase) if nil ~= curLayer then curScene:addChild(curLayer) curLayer:addChild(orderCallbackMenu(),15) curScene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(curScene) - end - end + ax.Director:getInstance():replaceScene(curScene) + end + end end curLayer = createLayerByCurCase(curCase) @@ -196,7 +196,7 @@ local function drawPrimitivesMainLayer() end function DrawPrimitivesTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(drawPrimitivesMainLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/EffectsAdvancedTest/EffectsAdvancedTest.lua b/tests/lua-tests/Content/src/EffectsAdvancedTest/EffectsAdvancedTest.lua index d5f5f95e6ed3..b4cf7398cc18 100644 --- a/tests/lua-tests/Content/src/EffectsAdvancedTest/EffectsAdvancedTest.lua +++ b/tests/lua-tests/Content/src/EffectsAdvancedTest/EffectsAdvancedTest.lua @@ -8,33 +8,33 @@ local originCreateLayer = createTestLayer local function createTestLayer(title, subtitle) local ret = originCreateLayer(title, subtitle) - local bgNode = cc.NodeGrid:create() - bgNode:setAnchorPoint(cc.p(0.5,0.5)) + local bgNode = ax.NodeGrid:create() + bgNode:setAnchorPoint(ax.p(0.5,0.5)) ret:addChild(bgNode,0,kTagBackground) - local bg = cc.Sprite:create("Images/background3.png") + local bg = ax.Sprite:create("Images/background3.png") bg:setPosition( VisibleRect:center()) bgNode:addChild(bg) - local target1 = cc.NodeGrid:create() - target1:setAnchorPoint(cc.p(0.5,0.5)) - local grossini = cc.Sprite:create("Images/grossinis_sister2.png") + local target1 = ax.NodeGrid:create() + target1:setAnchorPoint(ax.p(0.5,0.5)) + local grossini = ax.Sprite:create("Images/grossinis_sister2.png") target1:addChild(grossini) bgNode:addChild(target1,1,kTagSprite1) - target1:setPosition(cc.p(VisibleRect:left().x+VisibleRect:getVisibleRect().width/3.0, VisibleRect:bottom().y+ 200) ) - local sc = cc.ScaleBy:create(2, 5) + target1:setPosition(ax.p(VisibleRect:left().x+VisibleRect:getVisibleRect().width/3.0, VisibleRect:bottom().y+ 200) ) + local sc = ax.ScaleBy:create(2, 5) local sc_back = sc:reverse() - target1:runAction( cc.RepeatForever:create(cc.Sequence:create(sc, sc_back))) + target1:runAction( ax.RepeatForever:create(ax.Sequence:create(sc, sc_back))) - local target2 = cc.NodeGrid:create() - target2:setAnchorPoint(cc.p(0.5,0.5)) - local tamara = cc.Sprite:create("Images/grossinis_sister1.png") + local target2 = ax.NodeGrid:create() + target2:setAnchorPoint(ax.p(0.5,0.5)) + local tamara = ax.Sprite:create("Images/grossinis_sister1.png") target2:addChild(tamara) bgNode:addChild(target2,1,kTagSprite2) - target2:setPosition( cc.p(VisibleRect:left().x+2*VisibleRect:getVisibleRect().width/3.0,VisibleRect:bottom().y+200) ) - local sc2 = cc.ScaleBy:create(2, 5) + target2:setPosition( ax.p(VisibleRect:left().x+2*VisibleRect:getVisibleRect().width/3.0,VisibleRect:bottom().y+200) ) + local sc2 = ax.ScaleBy:create(2, 5) local sc2_back = sc2:reverse() - target2:runAction( cc.RepeatForever:create(cc.Sequence:create(sc2, sc2_back))) + target2:runAction( ax.RepeatForever:create(ax.Sequence:create(sc2, sc2_back))) return ret end @@ -54,17 +54,17 @@ local function Effect1() -- Lens3D is Grid3D and it's size is (15,10) -- Waves3D is Grid3D and it's size is (15,10) - local size = cc.Director:getInstance():getWinSize() - local lens = cc.Lens3D:create(0.0, cc.size(15,10), cc.p(size.width/2,size.height/2), 240) - local waves = cc.Waves3D:create(10, cc.size(15,10), 18, 15) + local size = ax.Director:getInstance():getWinSize() + local lens = ax.Lens3D:create(0.0, ax.size(15,10), ax.p(size.width/2,size.height/2), 240) + local waves = ax.Waves3D:create(10, ax.size(15,10), 18, 15) - local reuse = cc.ReuseGrid:create(1) - local delay = cc.DelayTime:create(8) + local reuse = ax.ReuseGrid:create(1) + local delay = ax.DelayTime:create(8) - -- local orbit = cc.OrbitCamera:create(5, 1, 2, 0, 180, 0, -90) + -- local orbit = ax.OrbitCamera:create(5, 1, 2, 0, 180, 0, -90) -- local orbit_back = orbit:reverse() - -- target:runAction( cc.RepeatForever:create( cc.Sequence:create(orbit, orbit_back))) - target:runAction( cc.Sequence:create(lens, delay, reuse, waves)) + -- target:runAction( ax.RepeatForever:create( ax.Sequence:create(orbit, orbit_back))) + target:runAction( ax.Sequence:create(lens, delay, reuse, waves)) return ret end @@ -82,20 +82,20 @@ local function Effect2() -- ShakyTiles is TiledGrid3D and it's size is (15,10) -- Shuffletiles is TiledGrid3D and it's size is (15,10) -- TurnOfftiles is TiledGrid3D and it's size is (15,10) - local shaky = cc.ShakyTiles3D:create(5, cc.size(15,10), 4, false) - local shuffle = cc.ShuffleTiles:create(0, cc.size(15,10), 3) - local turnoff = cc.TurnOffTiles:create(0, cc.size(15,10), 3) + local shaky = ax.ShakyTiles3D:create(5, ax.size(15,10), 4, false) + local shuffle = ax.ShuffleTiles:create(0, ax.size(15,10), 3) + local turnoff = ax.TurnOffTiles:create(0, ax.size(15,10), 3) local turnon = turnoff:reverse() -- reuse 2 times: -- 1 for shuffle -- 2 for turn off -- turnon tiles will use a new grid - local reuse = cc.ReuseGrid:create(2) + local reuse = ax.ReuseGrid:create(2) - local delay = cc.DelayTime:create(1) + local delay = ax.DelayTime:create(1) - target:runAction(cc.Sequence:create(shaky, delay ,reuse, shuffle, delay:clone(), turnoff, turnon)) + target:runAction(ax.Sequence:create(shaky, delay ,reuse, shuffle, delay:clone(), turnoff, turnon)) return ret end @@ -110,15 +110,15 @@ local function Effect3() local target1 = bg:getChildByTag(kTagSprite1) local target2 = bg:getChildByTag(kTagSprite2) - local waves = cc.Waves:create(5, cc.size(15,10), 5, 20, true, false) - local shaky = cc.Shaky3D:create(5, cc.size(15,10), 4, false) + local waves = ax.Waves:create(5, ax.size(15,10), 5, 20, true, false) + local shaky = ax.Shaky3D:create(5, ax.size(15,10), 4, false) - target1:runAction( cc.RepeatForever:create( waves ) ) - target2:runAction( cc.RepeatForever:create( shaky ) ) + target1:runAction( ax.RepeatForever:create( waves ) ) + target2:runAction( ax.RepeatForever:create( shaky ) ) -- moving background. Testing issue #244 - local move = cc.MoveBy:create(3, cc.p(200,0) ) - bg:runAction(cc.RepeatForever:create( cc.Sequence:create(move, move:reverse()))) + local move = ax.MoveBy:create(3, ax.p(200,0) ) + bg:runAction(ax.RepeatForever:create( ax.Sequence:create(move, move:reverse()))) return ret end @@ -128,7 +128,7 @@ end -- -------------------------------------------------------------------- --- class Lens3DTarget : public cc.Node +-- class Lens3DTarget : public ax.Node -- public: -- virtual void setPosition(const CCPoint& var) @@ -141,7 +141,7 @@ end -- return m_pLens3D:getPosition() -- end --- static Lens3DTarget* create(cc.Lens3D* pAction) +-- static Lens3DTarget* create(ax.Lens3D* pAction) -- Lens3DTarget* pRet = new Lens3DTarget() -- pRet:m_pLens3D = pAction @@ -154,22 +154,22 @@ end -- : m_pLens3D(nullptr) -- {} --- cc.Lens3D* m_pLens3D +-- ax.Lens3D* m_pLens3D -- end local function Effect4() local ret = createTestLayer("Jumpy Lens3D") - local lens = cc.Lens3D:create(10, cc.size(32,24), cc.p(100,180), 150) - local move = cc.JumpBy:create(5, cc.p(380,0), 100, 4) + local lens = ax.Lens3D:create(10, ax.size(32,24), ax.p(100,180), 150) + local move = ax.JumpBy:create(5, ax.p(380,0), 100, 4) local move_back = move:reverse() - local seq = cc.Sequence:create( move, move_back) + local seq = ax.Sequence:create( move, move_back) - -- /* In cocos2d-iphone, the type of action's target is 'id', so it supports using the instance of 'cc.Lens3D' as its target. - -- While in cocos2d-x, the target of action only supports cc.Node or its subclass, - -- so we make an encapsulation for cc.Lens3D to achieve that. + -- /* In cocos2d-iphone, the type of action's target is 'id', so it supports using the instance of 'ax.Lens3D' as its target. + -- While in cocos2d-x, the target of action only supports ax.Node or its subclass, + -- so we make an encapsulation for ax.Lens3D to achieve that. -- */ - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() -- local pTarget = Lens3DTarget:create(lens) -- -- Please make sure the target been added to its parent. -- ret:addChild(pTarget) @@ -188,14 +188,14 @@ end local function Effect5() local ret = createTestLayer("Test Stop-Copy-Restar") - local effect = cc.Liquid:create(2, cc.size(32,24), 1, 20) + local effect = ax.Liquid:create(2, ax.size(32,24), 1, 20) - local stopEffect = cc.Sequence:create(effect, cc.DelayTime:create(2), cc.StopGrid:create()) + local stopEffect = ax.Sequence:create(effect, ax.DelayTime:create(2), ax.StopGrid:create()) local bg = ret:getChildByTag(kTagBackground) bg:runAction(stopEffect) local function onNodeEvent(event) if event == "exit" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_3D) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_3D) end end @@ -213,34 +213,34 @@ local function Issue631() local ret = createTestLayer("Testing Opacity", "Effect image should be 100% opaque. Testing issue #631") - local effect = cc.Sequence:create(cc.DelayTime:create(2.0),cc.Shaky3D:create(5.0, cc.size(5, 5), 16, false)) + local effect = ax.Sequence:create(ax.DelayTime:create(2.0),ax.Shaky3D:create(5.0, ax.size(5, 5), 16, false)) -- cleanup local bg = ret:getChildByTag(kTagBackground) ret:removeChild(bg, true) -- background - local layer = cc.LayerColor:create( cc.c4b(255,0,0,255) ) + local layer = ax.LayerColor:create( ax.color32(255,0,0,255) ) ret:addChild(layer, -10) - local sprite = cc.Sprite:create("Images/grossini.png") - sprite:setPosition( cc.p(50,80) ) + local sprite = ax.Sprite:create("Images/grossini.png") + sprite:setPosition( ax.p(50,80) ) layer:addChild(sprite, 10) -- foreground - local layer2BaseGrid = cc.NodeGrid:create() - local layer2 = cc.LayerColor:create(cc.c4b( 0, 255,0,255 ) ) - local fog = cc.Sprite:create("Images/Fog.png") + local layer2BaseGrid = ax.NodeGrid:create() + local layer2 = ax.LayerColor:create(ax.color32( 0, 255,0,255 ) ) + local fog = ax.Sprite:create("Images/Fog.png") --local bf = BlendFunc() --bf.src = GL_SRC_ALPHA --bf.dst = GL_ONE_MINUS_SRC_ALPHA - fog:setBlendFunc(cc.blendFunc(ccb.BlendFactor.SRC_ALPHA , ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) + fog:setBlendFunc(ax.blendFunc(ccb.BlendFactor.SRC_ALPHA , ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) layer2:addChild(fog, 1) ret:addChild(layer2BaseGrid, 1) layer2BaseGrid:addChild(layer2) - layer2BaseGrid:runAction( cc.RepeatForever:create(effect) ) + layer2BaseGrid:runAction( ax.RepeatForever:create(effect) ) return ret end @@ -248,7 +248,7 @@ function EffectAdvancedTestMain() cclog("EffectAdvancedTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { Effect3, Effect2, @@ -258,7 +258,7 @@ function EffectAdvancedTestMain() Issue631 } Helper.index = 1 - + scene:addChild(Effect3()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/EffectsTest/EffectsTest.lua b/tests/lua-tests/Content/src/EffectsTest/EffectsTest.lua index 1798ed9c542c..29fcd269e498 100644 --- a/tests/lua-tests/Content/src/EffectsTest/EffectsTest.lua +++ b/tests/lua-tests/Content/src/EffectsTest/EffectsTest.lua @@ -2,7 +2,7 @@ require "EffectsTest/EffectsName" local ActionIdx = -1 -local size = cc.Director:getInstance():getWinSize() +local size = ax.Director:getInstance():getWinSize() local kTagTextLayer = 1 local kTagBackground = 1 local kTagLabel = 2 @@ -25,7 +25,7 @@ local function checkAnim(dt) end local function onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then entry = scheduler:scheduleScriptFunc(checkAnim, 0, false) elseif tag == "exit" then @@ -54,224 +54,224 @@ local function nextAction() end local function backCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(backAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function restartCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(restartAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function nextCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(nextAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end -------------------------------------- -- Shaky3DDemo -------------------------------------- local function Shaky3DDemo(t) - return cc.Shaky3D:create(t, cc.size(15,10), 5, false) + return ax.Shaky3D:create(t, ax.size(15,10), 5, false) end -------------------------------------- -- Waves3DDemo -------------------------------------- local function Waves3DDemo(t) - return cc.Waves3D:create(t, cc.size(15,10), 5, 40) + return ax.Waves3D:create(t, ax.size(15,10), 5, 40) end -------------------------------------- -- FlipX3DDemo -------------------------------------- local function FlipX3DDemo(t) - local flipx = cc.FlipX3D:create(t) + local flipx = ax.FlipX3D:create(t) local flipx_back = flipx:reverse() - local delay = cc.DelayTime:create(2) + local delay = ax.DelayTime:create(2) - return cc.Sequence:create(flipx, flipx_back, delay) + return ax.Sequence:create(flipx, flipx_back, delay) end -------------------------------------- -- FlipY3DDemo -------------------------------------- local function FlipY3DDemo(t) - local flipy = cc.FlipY3D:create(t) + local flipy = ax.FlipY3D:create(t) local flipy_back = flipy:reverse() - local delay = cc.DelayTime:create(2) + local delay = ax.DelayTime:create(2) - return cc.Sequence:create(flipy, flipy_back, delay) + return ax.Sequence:create(flipy, flipy_back, delay) end -------------------------------------- -- Lens3DDemo -------------------------------------- local function Lens3DDemo(t) - return cc.Lens3D:create(t, cc.size(15,10), cc.p(size.width/2,size.height/2), 240) + return ax.Lens3D:create(t, ax.size(15,10), ax.p(size.width/2,size.height/2), 240) end -------------------------------------- -- Ripple3DDemo -------------------------------------- local function Ripple3DDemo(t) - return cc.Ripple3D:create(t, cc.size(32,24), cc.p(size.width/2,size.height/2), 240, 4, 160) + return ax.Ripple3D:create(t, ax.size(32,24), ax.p(size.width/2,size.height/2), 240, 4, 160) end -------------------------------------- -- LiquidDemo -------------------------------------- local function LiquidDemo(t) - return cc.Liquid:create(t, cc.size(16,12), 4, 20) + return ax.Liquid:create(t, ax.size(16,12), 4, 20) end -------------------------------------- -- WavesDemo -------------------------------------- local function WavesDemo(t) - return cc.Waves:create(t, cc.size(16,12), 4, 20, true, true) + return ax.Waves:create(t, ax.size(16,12), 4, 20, true, true) end -------------------------------------- -- TwirlDemo -------------------------------------- local function TwirlDemo(t) - return cc.Twirl:create(t, cc.size(12,8), cc.p(size.width/2, size.height/2), 1, 2.5) + return ax.Twirl:create(t, ax.size(12,8), ax.p(size.width/2, size.height/2), 1, 2.5) end -------------------------------------- -- ShakyTiles3DDemo -------------------------------------- local function ShakyTiles3DDemo(t) - return cc.ShakyTiles3D:create(t, cc.size(16,12), 5, false) + return ax.ShakyTiles3D:create(t, ax.size(16,12), 5, false) end -------------------------------------- -- ShatteredTiles3DDemo -------------------------------------- local function ShatteredTiles3DDemo(t) - return cc.ShatteredTiles3D:create(t, cc.size(16,12), 5, false) + return ax.ShatteredTiles3D:create(t, ax.size(16,12), 5, false) end -------------------------------------- -- ShuffleTilesDemo -------------------------------------- local function ShuffleTilesDemo(t) - local shuffle = cc.ShuffleTiles:create(t, cc.size(16,12), 25) + local shuffle = ax.ShuffleTiles:create(t, ax.size(16,12), 25) local shuffle_back = shuffle:reverse() - local delay = cc.DelayTime:create(2) + local delay = ax.DelayTime:create(2) - return cc.Sequence:create(shuffle, shuffle_back, delay) + return ax.Sequence:create(shuffle, shuffle_back, delay) end -------------------------------------- -- FadeOutTRTilesDemo -------------------------------------- local function FadeOutTRTilesDemo(t) - local fadeout = cc.FadeOutTRTiles:create(t, cc.size(16,12)) + local fadeout = ax.FadeOutTRTiles:create(t, ax.size(16,12)) local back = fadeout:reverse() - local delay = cc.DelayTime:create(0.5) + local delay = ax.DelayTime:create(0.5) - return cc.Sequence:create(fadeout, back, delay) + return ax.Sequence:create(fadeout, back, delay) end -------------------------------------- -- FadeOutBLTilesDemo -------------------------------------- local function FadeOutBLTilesDemo(t) - local fadeout = cc.FadeOutBLTiles:create(t, cc.size(16,12)) + local fadeout = ax.FadeOutBLTiles:create(t, ax.size(16,12)) local back = fadeout:reverse() - local delay = cc.DelayTime:create(0.5) + local delay = ax.DelayTime:create(0.5) - return cc.Sequence:create(fadeout, back, delay) + return ax.Sequence:create(fadeout, back, delay) end -------------------------------------- -- FadeOutUpTilesDemo -------------------------------------- local function FadeOutUpTilesDemo(t) - local fadeout = cc.FadeOutUpTiles:create(t, cc.size(16,12)) + local fadeout = ax.FadeOutUpTiles:create(t, ax.size(16,12)) local back = fadeout:reverse() - local delay = cc.DelayTime:create(0.5) + local delay = ax.DelayTime:create(0.5) - return cc.Sequence:create(fadeout, back, delay) + return ax.Sequence:create(fadeout, back, delay) end -------------------------------------- -- FadeOutDownTilesDemo -------------------------------------- local function FadeOutDownTilesDemo(t) - local fadeout = cc.FadeOutDownTiles:create(t, cc.size(16,12)) + local fadeout = ax.FadeOutDownTiles:create(t, ax.size(16,12)) local back = fadeout:reverse() - local delay = cc.DelayTime:create(0.5) + local delay = ax.DelayTime:create(0.5) - return cc.Sequence:create(fadeout, back, delay) + return ax.Sequence:create(fadeout, back, delay) end -------------------------------------- -- TurnOffTilesDemo -------------------------------------- local function TurnOffTilesDemo(t) - local fadeout = cc.TurnOffTiles:create(t, cc.size(48,32), 25) + local fadeout = ax.TurnOffTiles:create(t, ax.size(48,32), 25) local back = fadeout:reverse() - local delay = cc.DelayTime:create(0.5) + local delay = ax.DelayTime:create(0.5) - return cc.Sequence:create(fadeout, back, delay) + return ax.Sequence:create(fadeout, back, delay) end -------------------------------------- -- WavesTiles3DDemo -------------------------------------- local function WavesTiles3DDemo(t) - return cc.WavesTiles3D:create(t, cc.size(15,10), 4, 120) + return ax.WavesTiles3D:create(t, ax.size(15,10), 4, 120) end -------------------------------------- -- JumpTiles3DDemo -------------------------------------- local function JumpTiles3DDemo(t) - return cc.JumpTiles3D:create(t, cc.size(15,10), 2, 30) + return ax.JumpTiles3D:create(t, ax.size(15,10), 2, 30) end -------------------------------------- -- SplitRowsDemo -------------------------------------- local function SplitRowsDemo(t) - return cc.SplitRows:create(t, 9) + return ax.SplitRows:create(t, 9) end -------------------------------------- -- SplitColsDemo -------------------------------------- local function SplitColsDemo(t) - return cc.SplitCols:create(t, 9) + return ax.SplitCols:create(t, 9) end -------------------------------------- -- PageTurn3DDemo -------------------------------------- local function PageTurn3DDemo(t) - cc.Director:getInstance():getRenderer():setDepthTest(true) - return cc.PageTurn3D:create(t, cc.size(15,10)) + ax.Director:getInstance():getRenderer():setDepthTest(true) + return ax.PageTurn3D:create(t, ax.size(15,10)) end -------------------------------------- -- Effects Test -------------------------------------- local function createEffect(idx, t) - cc.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) local action = nil if idx == 0 then @@ -324,56 +324,56 @@ local function createEffect(idx, t) end function CreateEffectsTestLayer() - testLayer = cc.LayerColor:create(cc.c4b(32,128,32,255)) + testLayer = ax.LayerColor:create(ax.color32(32,128,32,255)) - gridNodeTarget = cc.NodeGrid:create() + gridNodeTarget = ax.NodeGrid:create() local effect = createEffect(ActionIdx, 3) gridNodeTarget:runAction(effect) testLayer:addChild(gridNodeTarget, 0, kTagBackground) - - local bg = cc.Sprite:create(s_back3) + + local bg = ax.Sprite:create(s_back3) gridNodeTarget:addChild(bg, 0) bg:setPosition(VisibleRect:center()) - local grossini = cc.Sprite:create(s_pPathSister2) + local grossini = ax.Sprite:create(s_pPathSister2) gridNodeTarget:addChild(grossini, 1) - grossini:setPosition( cc.p(VisibleRect:left().x+VisibleRect:getVisibleRect().width/3,VisibleRect:center().y) ) - local sc = cc.ScaleBy:create(2, 5) + grossini:setPosition( ax.p(VisibleRect:left().x+VisibleRect:getVisibleRect().width/3,VisibleRect:center().y) ) + local sc = ax.ScaleBy:create(2, 5) local sc_back = sc:reverse() - grossini:runAction( cc.RepeatForever:create(cc.Sequence:create(sc, sc_back) ) ) + grossini:runAction( ax.RepeatForever:create(ax.Sequence:create(sc, sc_back) ) ) - local tamara = cc.Sprite:create(s_pPathSister1) + local tamara = ax.Sprite:create(s_pPathSister1) gridNodeTarget:addChild(tamara, 1) - tamara:setPosition( cc.p(VisibleRect:left().x+2*VisibleRect:getVisibleRect().width/3,VisibleRect:center().y) ) - local sc2 = cc.ScaleBy:create(2, 5) + tamara:setPosition( ax.p(VisibleRect:left().x+2*VisibleRect:getVisibleRect().width/3,VisibleRect:center().y) ) + local sc2 = ax.ScaleBy:create(2, 5) local sc2_back = sc2:reverse() - tamara:runAction( cc.RepeatForever:create(cc.Sequence:create(sc2, sc2_back)) ) + tamara:runAction( ax.RepeatForever:create(ax.Sequence:create(sc2, sc2_back)) ) local x, y = size.width, size.height - titleLabel = cc.Label:createWithTTF(EffectsList[ActionIdx], s_markerFeltFontPath, 32) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel = ax.Label:createWithTTF(EffectsList[ActionIdx], s_markerFeltFontPath, 32) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(x / 2, y - 80) testLayer:addChild(titleLabel) titleLabel:setTag(kTagLabel) - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) item1:registerScriptTapHandler(backCallback) item2:registerScriptTapHandler(restartCallback) item3:registerScriptTapHandler(nextCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(size.width/2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(size.width/2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(size.width/2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(size.width/2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(size.width/2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(size.width/2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) testLayer:addChild(menu, 1) @@ -383,7 +383,7 @@ function CreateEffectsTestLayer() end function EffectsTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() ActionIdx = -1 scene:addChild(nextAction()) diff --git a/tests/lua-tests/Content/src/ExtensionTest/ExtensionTest.lua b/tests/lua-tests/Content/src/ExtensionTest/ExtensionTest.lua index c62ed6e81c44..d2d01260177d 100644 --- a/tests/lua-tests/Content/src/ExtensionTest/ExtensionTest.lua +++ b/tests/lua-tests/Content/src/ExtensionTest/ExtensionTest.lua @@ -3,7 +3,7 @@ require "ExtensionTest/WebProxyTest" local LINE_SPACE = 40 local kItemTagBasic = 1000 -local ExtensionTestEnum = +local ExtensionTestEnum = { TEST_WEBSOCKET = 0, TEST_EDITBOX = 1, @@ -25,46 +25,46 @@ function CreateExtensionsBasicLayerMenu(pMenu) local function toMainLayer() local pScene = ExtensionsTestMain() if pScene ~= nil then - cc.Director:getInstance():replaceScene(pScene) + ax.Director:getInstance():replaceScene(pScene) end - end + end --Create BackMneu - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local pMenuItemFont = cc.MenuItemFont:create("Back") - pMenuItemFont:setPosition(cc.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local pMenuItemFont = ax.MenuItemFont:create("Back") + pMenuItemFont:setPosition(ax.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) pMenuItemFont:registerScriptTapHandler(toMainLayer) pMenu:addChild(pMenuItemFont) end local function runEditBoxTest() - local newScene = cc.Scene:create() - local newLayer = cc.Layer:create() - local visibleOrigin = cc.Director:getInstance():getVisibleOrigin() - local visibleSize = cc.Director:getInstance():getVisibleSize() - - local pBg = cc.Sprite:create("Images/HelloWorld.png") - pBg:setPosition(cc.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/2)) + local newScene = ax.Scene:create() + local newLayer = ax.Layer:create() + local visibleOrigin = ax.Director:getInstance():getVisibleOrigin() + local visibleSize = ax.Director:getInstance():getVisibleSize() + + local pBg = ax.Sprite:create("Images/HelloWorld.png") + pBg:setPosition(ax.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/2)) newLayer:addChild(pBg) - - local TTFShowEditReturn = cc.Label:createWithSystemFont("No edit control return!", "", 30) - TTFShowEditReturn:setPosition(cc.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y + visibleSize.height - 50)) + + local TTFShowEditReturn = ax.Label:createWithSystemFont("No edit control return!", "", 30) + TTFShowEditReturn:setPosition(ax.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y + visibleSize.height - 50)) newLayer:addChild(TTFShowEditReturn) - + -- Back Menu - local pToMainMenu = cc.Menu:create() + local pToMainMenu = ax.Menu:create() CreateExtensionsBasicLayerMenu(pToMainMenu) - pToMainMenu:setPosition(cc.p(0, 0)) + pToMainMenu:setPosition(ax.p(0, 0)) newLayer:addChild(pToMainMenu,10) - - local editBoxSize = cc.size(visibleSize.width - 100, 60) + + local editBoxSize = ax.size(visibleSize.width - 100, 60) local EditName = nil local EditPassword = nil local EditEmail = nil - + local function editBoxTextEventHandle(strEventName,pSender) local edit = pSender - local strFmt + local strFmt if strEventName == "began" then strFmt = string.format("editBox %p DidBegin !", edit) print(strFmt) @@ -88,58 +88,58 @@ local function runEditBoxTest() end -- top EditName = ccui.EditBox:create(editBoxSize, ccui.Scale9Sprite:create("extensions/green_edit.png")) - EditName:setPosition(cc.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height*3/4)) - local targetPlatform = cc.Application:getInstance():getTargetPlatform() + EditName:setPosition(ax.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height*3/4)) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() if kTargetIphone == targetPlatform or kTargetIpad == targetPlatform then EditName:setFontName("Paint Boy") else EditName:setFontName("fonts/Paint Boy.ttf") end EditName:setFontSize(25) - EditName:setFontColor(cc.c3b(255,0,0)) + EditName:setFontColor(ax.color32(255,0,0)) EditName:setPlaceHolder("Name:") - EditName:setPlaceholderFontColor(cc.c3b(255,255,255)) + EditName:setPlaceholderFontColor(ax.color32(255,255,255)) EditName:setMaxLength(8) - EditName:setReturnType(cc.KEYBOARD_RETURNTYPE_DONE ) + EditName:setReturnType(ax.KEYBOARD_RETURNTYPE_DONE ) --Handler EditName:registerScriptEditBoxHandler(editBoxTextEventHandle) newLayer:addChild(EditName) - + --middle EditPassword = ccui.EditBox:create(editBoxSize, ccui.Scale9Sprite:create("extensions/orange_edit.png")) - EditPassword:setPosition(cc.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/2)) + EditPassword:setPosition(ax.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/2)) if kTargetIphone == targetPlatform or kTargetIpad == targetPlatform then EditPassword:setFont("American Typewriter", 30) else EditPassword:setFont("fonts/American Typewriter.ttf", 30) end - - EditPassword:setFontColor(cc.c3b(0,255,0)) + + EditPassword:setFontColor(ax.color32(0,255,0)) EditPassword:setPlaceHolder("Password:") EditPassword:setMaxLength(6) - EditPassword:setInputFlag(cc.EDITBOX_INPUT_FLAG_PASSWORD) - EditPassword:setInputMode(cc.EDITBOX_INPUT_MODE_SINGLELINE) + EditPassword:setInputFlag(ax.EDITBOX_INPUT_FLAG_PASSWORD) + EditPassword:setInputMode(ax.EDITBOX_INPUT_MODE_SINGLELINE) EditPassword:registerScriptEditBoxHandler(editBoxTextEventHandle) newLayer:addChild(EditPassword) - + --bottom - EditEmail = ccui.EditBox:create(cc.size(editBoxSize.width, editBoxSize.height), ccui.Scale9Sprite:create("extensions/yellow_edit.png")) - EditEmail:setPosition(cc.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/4)) - EditEmail:setAnchorPoint(cc.p(0.5, 1.0)) + EditEmail = ccui.EditBox:create(ax.size(editBoxSize.width, editBoxSize.height), ccui.Scale9Sprite:create("extensions/yellow_edit.png")) + EditEmail:setPosition(ax.p(visibleOrigin.x+visibleSize.width/2, visibleOrigin.y+visibleSize.height/4)) + EditEmail:setAnchorPoint(ax.p(0.5, 1.0)) EditEmail:setPlaceHolder("Email:") - EditEmail:setInputMode(cc.EDITBOX_INPUT_MODE_EMAILADDR) + EditEmail:setInputMode(ax.EDITBOX_INPUT_MODE_EMAILADDR) EditEmail:registerScriptEditBoxHandler(editBoxTextEventHandle) - newLayer:addChild(EditEmail) - newLayer:setPosition(cc.p(10, 20)) - - + newLayer:addChild(EditEmail) + newLayer:setPosition(ax.p(10, 20)) + + newScene:addChild(newLayer) return newScene end -local CreateExtensionsTestTable = +local CreateExtensionsTestTable = { runWebSocketTest, runEditBoxTest, @@ -148,40 +148,40 @@ local CreateExtensionsTestTable = local function ExtensionsMainLayer() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local function CreateExtensionsTestScene(nPerformanceNo) local pNewscene = CreateExtensionsTestTable[nPerformanceNo]() return pNewscene end - + local function menuCallback(tag, pMenuItem) local scene = nil local nIdx = pMenuItem:getLocalZOrder() - kItemTagBasic local ExtensionsTestScene = CreateExtensionsTestScene(nIdx) if nil ~= ExtensionsTestScene then - cc.Director:getInstance():replaceScene(ExtensionsTestScene) + ax.Director:getInstance():replaceScene(ExtensionsTestScene) end end - - local layer = cc.Layer:create() - local menu = cc.Menu:create() - menu:setPosition(cc.p(0, 0)) - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local targetPlatform = cc.Application:getInstance():getTargetPlatform() + + local layer = ax.Layer:create() + local menu = ax.Menu:create() + menu:setPosition(ax.p(0, 0)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() local bSupportWebSocket = false - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_ANDROID == targetPlatform) or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) or (ax.PLATFORM_OS_ANDROID == targetPlatform) or (ax.PLATFORM_OS_WINDOWS == targetPlatform) or (ax.PLATFORM_OS_MAC == targetPlatform) then bSupportWebSocket = true end local bSupportEdit = false - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or - (cc.PLATFORM_OS_ANDROID == targetPlatform) or (cc.PLATFORM_OS_WINDOWS == targetPlatform) or - (cc.PLATFORM_OS_MAC == targetPlatform) or (cc.PLATFORM_OS_TIZEN == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) or + (ax.PLATFORM_OS_ANDROID == targetPlatform) or (ax.PLATFORM_OS_WINDOWS == targetPlatform) or + (ax.PLATFORM_OS_MAC == targetPlatform) or (ax.PLATFORM_OS_TIZEN == targetPlatform) then bSupportEdit = true end for i = 1, ExtensionTestEnum.TEST_MAX_COUNT do - local item = cc.MenuItemFont:create(testsName[i]) + local item = ax.MenuItemFont:create(testsName[i]) item:registerScriptTapHandler(menuCallback) item:setPosition(s.width / 2, s.height - i * LINE_SPACE) menu:addChild(item, kItemTagBasic + i) @@ -194,8 +194,8 @@ local function ExtensionsMainLayer() layer:addChild(menu) -- handling touch events - local beginPos = {x = 0, y = 0} - local function onTouchesBegan(touches, event) + local beginPos = {x = 0, y = 0} + local function onTouchesBegan(touches, event) beginPos = touches[1]:getLocation() end @@ -205,7 +205,7 @@ local function ExtensionsMainLayer() local nMoveY = location.y - beginPos.y local curPosx, curPosy = menu:getPosition() local nextPosy = curPosy + nMoveY - local winSize = cc.Director:getInstance():getWinSize() + local winSize = ax.Director:getInstance():getWinSize() if nextPosy < 0 then menu:setPosition(0, 0) return @@ -220,9 +220,9 @@ local function ExtensionsMainLayer() beginPos = {x = location.x, y = location.y} end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -234,7 +234,7 @@ end -- Extensions Test ------------------------------------- function ExtensionsTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(ExtensionsMainLayer()) scene:addChild(CreateBackMenuItem()) diff --git a/tests/lua-tests/Content/src/ExtensionTest/WebProxyTest.lua b/tests/lua-tests/Content/src/ExtensionTest/WebProxyTest.lua index 653608e6fdff..61b1a7154e2f 100644 --- a/tests/lua-tests/Content/src/ExtensionTest/WebProxyTest.lua +++ b/tests/lua-tests/Content/src/ExtensionTest/WebProxyTest.lua @@ -1,7 +1,7 @@ local function WebSocketTestLayer() - local layer = cc.Layer:create() - local winSize = cc.Director:getInstance():getWinSize() - + local layer = ax.Layer:create() + local winSize = ax.Director:getInstance():getWinSize() + local MARGIN = 40 local SPACE = 35 @@ -13,20 +13,20 @@ local function WebSocketTestLayer() local errorStatus = nil local receiveTextTimes = 0 local receiveBinaryTimes = 0 - - local label = cc.Label:createWithTTF("WebSocket Test", s_arialPath, 28) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p( winSize.width / 2, winSize.height - MARGIN)) + + local label = ax.Label:createWithTTF("WebSocket Test", s_arialPath, 28) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p( winSize.width / 2, winSize.height - MARGIN)) layer:addChild(label, 0) - local menuRequest = cc.Menu:create() - menuRequest:setPosition(cc.p(0, 0)) + local menuRequest = ax.Menu:create() + menuRequest:setPosition(ax.p(0, 0)) layer:addChild(menuRequest) --Send Text local function onMenuSendTextClicked() if nil ~= wsSendText then - if cc.WEBSOCKET_STATE_OPEN == wsSendText:getReadyState() then + if ax.WEBSOCKET_STATE_OPEN == wsSendText:getReadyState() then sendTextStatus:setString("Send Text WS is waiting...") wsSendText:sendString("Hello WebSocket中文, I'm a text message.") else @@ -36,17 +36,17 @@ local function WebSocketTestLayer() end end end - local labelSendText = cc.Label:createWithTTF("Send Text", s_arialPath, 22) + local labelSendText = ax.Label:createWithTTF("Send Text", s_arialPath, 22) labelSendText:setAnchorPoint(0.5, 0.5) - local itemSendText = cc.MenuItemLabel:create(labelSendText) + local itemSendText = ax.MenuItemLabel:create(labelSendText) itemSendText:registerScriptTapHandler(onMenuSendTextClicked) - itemSendText:setPosition(cc.p(winSize.width / 2, winSize.height - MARGIN - SPACE)) + itemSendText:setPosition(ax.p(winSize.width / 2, winSize.height - MARGIN - SPACE)) menuRequest:addChild(itemSendText) --Send Binary local function onMenuSendBinaryClicked() if nil ~= wsSendBinary then - if cc.WEBSOCKET_STATE_OPEN == wsSendBinary:getReadyState() then + if ax.WEBSOCKET_STATE_OPEN == wsSendBinary:getReadyState() then sendBinaryStatus:setString("Send Binary WS is waiting...") wsSendBinary:sendString("Hello WebSocket中文--,\0 I'm\0 a\0 binary\0 message\0.") else @@ -55,39 +55,39 @@ local function WebSocketTestLayer() end end end - local labelSendBinary = cc.Label:createWithTTF("Send Binary", s_arialPath, 22) - labelSendBinary:setAnchorPoint(cc.p(0.5, 0.5)) - local itemSendBinary = cc.MenuItemLabel:create(labelSendBinary) + local labelSendBinary = ax.Label:createWithTTF("Send Binary", s_arialPath, 22) + labelSendBinary:setAnchorPoint(ax.p(0.5, 0.5)) + local itemSendBinary = ax.MenuItemLabel:create(labelSendBinary) itemSendBinary:registerScriptTapHandler(onMenuSendBinaryClicked) - itemSendBinary:setPosition(cc.p(winSize.width / 2, winSize.height - MARGIN - 2 * SPACE)) + itemSendBinary:setPosition(ax.p(winSize.width / 2, winSize.height - MARGIN - 2 * SPACE)) menuRequest:addChild(itemSendBinary) --Send Text Status Label - sendTextStatus = cc.Label:createWithTTF("Send Text WS is waiting...", s_arialPath, 14,cc.size(160, 100),cc.VERTICAL_TEXT_ALIGNMENT_CENTER,cc.VERTICAL_TEXT_ALIGNMENT_TOP) - sendTextStatus:setAnchorPoint(cc.p(0, 0)) - sendTextStatus:setPosition(cc.p(0, 25)) + sendTextStatus = ax.Label:createWithTTF("Send Text WS is waiting...", s_arialPath, 14,ax.size(160, 100),ax.VERTICAL_TEXT_ALIGNMENT_CENTER,ax.VERTICAL_TEXT_ALIGNMENT_TOP) + sendTextStatus:setAnchorPoint(ax.p(0, 0)) + sendTextStatus:setPosition(ax.p(0, 25)) layer:addChild(sendTextStatus) --Send Binary Status Label - sendBinaryStatus = cc.Label:createWithTTF("Send Binary WS is waiting...", s_arialPath, 14, cc.size(160, 100), cc.VERTICAL_TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_TOP) - sendBinaryStatus:setAnchorPoint(cc.p(0, 0)) - sendBinaryStatus:setPosition(cc.p(160, 25)) + sendBinaryStatus = ax.Label:createWithTTF("Send Binary WS is waiting...", s_arialPath, 14, ax.size(160, 100), ax.VERTICAL_TEXT_ALIGNMENT_CENTER, ax.VERTICAL_TEXT_ALIGNMENT_TOP) + sendBinaryStatus:setAnchorPoint(ax.p(0, 0)) + sendBinaryStatus:setPosition(ax.p(160, 25)) layer:addChild(sendBinaryStatus) --Error Label - errorStatus = cc.Label:createWithTTF("Error WS is waiting...", s_arialPath, 14, cc.size(160, 100), cc.VERTICAL_TEXT_ALIGNMENT_CENTER, cc.VERTICAL_TEXT_ALIGNMENT_TOP) - errorStatus:setAnchorPoint(cc.p(0, 0)) - errorStatus:setPosition(cc.p(320, 25)) + errorStatus = ax.Label:createWithTTF("Error WS is waiting...", s_arialPath, 14, ax.size(160, 100), ax.VERTICAL_TEXT_ALIGNMENT_CENTER, ax.VERTICAL_TEXT_ALIGNMENT_TOP) + errorStatus:setAnchorPoint(ax.p(0, 0)) + errorStatus:setPosition(ax.p(320, 25)) layer:addChild(errorStatus) - local toMainMenu = cc.Menu:create() + local toMainMenu = ax.Menu:create() CreateExtensionsBasicLayerMenu(toMainMenu) - toMainMenu:setPosition(cc.p(0, 0)) + toMainMenu:setPosition(ax.p(0, 0)) layer:addChild(toMainMenu,10) - wsSendText = cc.WebSocket:create("wss://echo.websocket.org", {"myprotocol_1", "myprotocol_2"}, "cacert.pem") - wsSendBinary = cc.WebSocket:create("ws://echo.websocket.org", {"hello"}, "cacert.pem") - wsError = cc.WebSocket:create("ws://invalid.url.com", {"invalid_protocol"}) + wsSendText = ax.WebSocket:create("wss://echo.websocket.org", {"myprotocol_1", "myprotocol_2"}, "cacert.pem") + wsSendBinary = ax.WebSocket:create("ws://echo.websocket.org", {"hello"}, "cacert.pem") + wsError = ax.WebSocket:create("ws://invalid.url.com", {"invalid_protocol"}) local function wsSendTextOpen(strData) if sendTextStatus ~= nil then @@ -131,7 +131,7 @@ local function WebSocketTestLayer() strInfo = strInfo.."\'\\0\'" else strInfo = strInfo..string.char(paramTable[i]) - end + end end receiveBinaryTimes = receiveBinaryTimes + 1 strInfo = strInfo..receiveBinaryTimes @@ -174,24 +174,24 @@ local function WebSocketTestLayer() end if nil ~= wsSendText then - wsSendText:registerScriptHandler(wsSendTextOpen,cc.WEBSOCKET_OPEN) - wsSendText:registerScriptHandler(wsSendTextMessage,cc.WEBSOCKET_MESSAGE) - wsSendText:registerScriptHandler(wsSendTextClose,cc.WEBSOCKET_CLOSE) - wsSendText:registerScriptHandler(wsSendTextError,cc.WEBSOCKET_ERROR) + wsSendText:registerScriptHandler(wsSendTextOpen,ax.WEBSOCKET_OPEN) + wsSendText:registerScriptHandler(wsSendTextMessage,ax.WEBSOCKET_MESSAGE) + wsSendText:registerScriptHandler(wsSendTextClose,ax.WEBSOCKET_CLOSE) + wsSendText:registerScriptHandler(wsSendTextError,ax.WEBSOCKET_ERROR) end if nil ~= wsSendBinary then - wsSendBinary:registerScriptHandler(wsSendBinaryOpen,cc.WEBSOCKET_OPEN) - wsSendBinary:registerScriptHandler(wsSendBinaryMessage,cc.WEBSOCKET_MESSAGE) - wsSendBinary:registerScriptHandler(wsSendBinaryClose,cc.WEBSOCKET_CLOSE) - wsSendBinary:registerScriptHandler(wsSendBinaryError,cc.WEBSOCKET_ERROR) + wsSendBinary:registerScriptHandler(wsSendBinaryOpen,ax.WEBSOCKET_OPEN) + wsSendBinary:registerScriptHandler(wsSendBinaryMessage,ax.WEBSOCKET_MESSAGE) + wsSendBinary:registerScriptHandler(wsSendBinaryClose,ax.WEBSOCKET_CLOSE) + wsSendBinary:registerScriptHandler(wsSendBinaryError,ax.WEBSOCKET_ERROR) end if nil ~= wsError then - wsError:registerScriptHandler(wsErrorOpen,cc.WEBSOCKET_OPEN) - wsError:registerScriptHandler(wsErrorMessage,cc.WEBSOCKET_MESSAGE) - wsError:registerScriptHandler(wsErrorClose,cc.WEBSOCKET_CLOSE) - wsError:registerScriptHandler(wsErrorError,cc.WEBSOCKET_ERROR) + wsError:registerScriptHandler(wsErrorOpen,ax.WEBSOCKET_OPEN) + wsError:registerScriptHandler(wsErrorMessage,ax.WEBSOCKET_MESSAGE) + wsError:registerScriptHandler(wsErrorClose,ax.WEBSOCKET_CLOSE) + wsError:registerScriptHandler(wsErrorError,ax.WEBSOCKET_ERROR) end local function OnExit(strEventName) @@ -217,7 +217,7 @@ local function WebSocketTestLayer() end function runWebSocketTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(WebSocketTestLayer()) return scene end diff --git a/tests/lua-tests/Content/src/FastTiledMapTest/FastTiledMapTest.lua b/tests/lua-tests/Content/src/FastTiledMapTest/FastTiledMapTest.lua index e0824d9badf3..bb857a3b4503 100644 --- a/tests/lua-tests/Content/src/FastTiledMapTest/FastTiledMapTest.lua +++ b/tests/lua-tests/Content/src/FastTiledMapTest/FastTiledMapTest.lua @@ -1,11 +1,11 @@ -local size = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local size = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local kTagTileMap = 1 local function createTileDemoLayer(title, subtitle) - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local titleStr = title == nil and "No title" or title local subTitleStr = subtitle == nil and "drag the screen" or subtitle @@ -16,11 +16,11 @@ local function createTileDemoLayer(title, subtitle) local diff = touches[1]:getDelta() local node = layer:getChildByTag(kTagTileMap) local currentPosX, currentPosY= node:getPosition() - node:setPosition(cc.p(currentPosX + diff.x, currentPosY + diff.y)) + node:setPosition(ax.p(currentPosX + diff.x, currentPosY + diff.y)) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -34,7 +34,7 @@ end local function TileMapTest() local layer = createTileDemoLayer("TileMapAtlas") - local map = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local map = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) -- Convert it to "alias" (GL_LINEAR filtering) map:getTexture():setAntiAliasTexParameters() @@ -47,14 +47,14 @@ local function TileMapTest() layer:addChild(map, 0, kTagTileMap) - map:setAnchorPoint( cc.p(0, 0.5) ) + map:setAnchorPoint( ax.p(0, 0.5) ) - local scale = cc.ScaleBy:create(4, 0.8) + local scale = ax.ScaleBy:create(4, 0.8) local scaleBack = scale:reverse() - local seq = cc.Sequence:create(scale, scaleBack) + local seq = ax.Sequence:create(scale, scaleBack) - map:runAction(cc.RepeatForever:create(seq)) + map:runAction(ax.RepeatForever:create(seq)) return layer end @@ -66,7 +66,7 @@ end -------------------------------------------------------------------- local function TileMapEditTest() local layer = createTileDemoLayer("Editable TileMapAtlas") - local map = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local map = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) -- Create an Aliased Atlas map:getTexture():setAliasTexParameters() @@ -90,7 +90,7 @@ local function TileMapEditTest() -- over all your tiles in every frame. It's very expensive -- for(int x=0 x < tilemap.tgaInfo:width x++) -- for(int y=0 y < tilemap.tgaInfo:height y++) - -- Color3B c =[tilemap getTileAt:local Make(x,y)) + -- Color32 c =[tilemap getTileAt:local Make(x,y)) -- if( c.r != 0 ) -- --------cclog("%d,%d = %d", x,y,c.r) -- end @@ -98,7 +98,7 @@ local function TileMapEditTest() -- end -- NEW since v0.7 - local c = tilemap:getTileAt(cc.p(13,21)) + local c = tilemap:getTileAt(ax.p(13,21)) c.r = c.r + 1 c.r = c.r % 50 @@ -106,7 +106,7 @@ local function TileMapEditTest() c.r=1 end -- NEW since v0.7 - tilemap:setTile(c, cc.p(13,21) ) + tilemap:setTile(c, ax.p(13,21) ) end local schedulerEntry = nil @@ -122,8 +122,8 @@ local function TileMapEditTest() layer:addChild(map, 0, kTagTileMap) - map:setAnchorPoint( cc.p(0, 0) ) - map:setPosition( cc.p(-20,-200) ) + map:setAnchorPoint( ax.p(0, 0) ) + map:setPosition( ax.p(-20,-200) ) return layer end @@ -141,26 +141,26 @@ local function TMXOrthoTest() -- -- it should not flicker. No artifacts should appear -- - --local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + --local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) --addChild(color, -1) - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test2.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test2.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - local scale = cc.ScaleBy:create(10, 0.1) + local scale = ax.ScaleBy:create(10, 0.1) local back = scale:reverse() - local seq = cc.Sequence:create(scale, back) - local repeatAction = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(scale, back) + local repeatAction = ax.RepeatForever:create(seq) map:runAction(repeatAction) local function onNodeEvent(event) if event == "enter" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION3_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION3_D ) elseif event == "exit" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) end end @@ -178,13 +178,13 @@ end local function TMXOrthoTest2() local layer = createTileDemoLayer("TMX Ortho test2") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test1.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test1.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - map:runAction( cc.ScaleBy:create(2, 0.5) ) + map:runAction( ax.ScaleBy:create(2, 0.5) ) return layer end @@ -195,14 +195,14 @@ end -------------------------------------------------------------------- local function TMXOrthoTest3() local layer = createTileDemoLayer("TMX anchorPoint test") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test3.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test3.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) map:setScale(0.2) - map:setAnchorPoint( cc.p(0.5, 0.5) ) + map:setAnchorPoint( ax.p(0.5, 0.5) ) return layer end @@ -214,24 +214,24 @@ end -------------------------------------------------------------------- local function TMXOrthoTest4() local ret = createTileDemoLayer("TMX width/height test") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test4.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test4.tmx") ret:addChild(map, 0, kTagTileMap) local s1 = map:getContentSize() cclog("ContentSize: %f, %f", s1.width,s1.height) - map:setAnchorPoint(cc.p(0, 0)) + map:setAnchorPoint(ax.p(0, 0)) local layer = map:getLayer("Layer 0") local s = layer:getLayerSize() - local sprite = layer:getTileAt(cc.p(0,0)) + local sprite = layer:getTileAt(ax.p(0,0)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(s.width-1,0)) + sprite = layer:getTileAt(ax.p(s.width-1,0)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(0,s.height-1)) + sprite = layer:getTileAt(ax.p(0,s.height-1)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(s.width-1,s.height-1)) + sprite = layer:getTileAt(ax.p(s.width-1,s.height-1)) sprite:setScale(2) local schedulerEntry = nil @@ -243,10 +243,10 @@ local function TMXOrthoTest4() local layer0 = map:getLayer("Layer 0") local s = layer0:getLayerSize() - local sprite = layer0:getTileAt(cc.p(s.width-1,0)) + local sprite = layer0:getTileAt(ax.p(s.width-1,0)) layer0:removeChild(sprite, true) - local sprite2 = layer0:getTileAt(cc.p(s.width-1, s.height - 1)) - local sprite3 = layer0:getTileAt(cc.p(2, s.height - 1)) + local sprite2 = layer0:getTileAt(ax.p(s.width-1, s.height - 1)) + local sprite3 = layer0:getTileAt(ax.p(2, s.height - 1)) layer0:removeChild(sprite3, true) layer0:removeChild(sprite2, true) end @@ -277,7 +277,7 @@ local function TMXReadWriteTest() local ret = createTileDemoLayer("TMX Read/Write test") local m_gid = 0 local m_gid2 = 0 - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test2.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test2.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -287,21 +287,21 @@ local function TMXReadWriteTest() local layer = map:getLayer("Layer 0") map:setScale( 1 ) - local tile0 = layer:getTileAt(cc.p(1,63)) - local tile1 = layer:getTileAt(cc.p(2,63)) - local tile2 = layer:getTileAt(cc.p(3,62))--cc.p(1,62)) - local tile3 = layer:getTileAt(cc.p(2,62)) - tile0:setAnchorPoint( cc.p(0.5, 0.5) ) - tile1:setAnchorPoint( cc.p(0.5, 0.5) ) - tile2:setAnchorPoint( cc.p(0.5, 0.5) ) - tile3:setAnchorPoint( cc.p(0.5, 0.5) ) - - local move = cc.MoveBy:create(0.5, cc.p(0,160)) - local rotate = cc.RotateBy:create(2, 360) - local scale = cc.ScaleBy:create(2, 5) - local opacity = cc.FadeOut:create(2) - local fadein = cc.FadeIn:create(2) - local scaleback = cc.ScaleTo:create(1, 1) + local tile0 = layer:getTileAt(ax.p(1,63)) + local tile1 = layer:getTileAt(ax.p(2,63)) + local tile2 = layer:getTileAt(ax.p(3,62))--ax.p(1,62)) + local tile3 = layer:getTileAt(ax.p(2,62)) + tile0:setAnchorPoint( ax.p(0.5, 0.5) ) + tile1:setAnchorPoint( ax.p(0.5, 0.5) ) + tile2:setAnchorPoint( ax.p(0.5, 0.5) ) + tile3:setAnchorPoint( ax.p(0.5, 0.5) ) + + local move = ax.MoveBy:create(0.5, ax.p(0,160)) + local rotate = ax.RotateBy:create(2, 360) + local scale = ax.ScaleBy:create(2, 5) + local opacity = ax.FadeOut:create(2) + local fadein = ax.FadeIn:create(2) + local scaleback = ax.ScaleTo:create(1, 1) local function removeSprite(sender) --------cclog("removing tile: %x", sender) @@ -317,8 +317,8 @@ local function TMXReadWriteTest() ----------cclog("atlas quantity: %d", p:textureAtlas():totalQuads()) end - local finish = cc.CallFunc:create(removeSprite) - local seq0 = cc.Sequence:create(move, rotate, scale, opacity, fadein, scaleback, finish) + local finish = ax.CallFunc:create(removeSprite) + local seq0 = ax.Sequence:create(move, rotate, scale, opacity, fadein, scaleback, finish) local seq1 = seq0:clone() local seq2 = seq0:clone() local seq3 = seq0:clone() @@ -329,7 +329,7 @@ local function TMXReadWriteTest() tile3:runAction(seq3) - m_gid = layer:getTileGIDAt(cc.p(0,63)) + m_gid = layer:getTileGIDAt(ax.p(0,63)) --------cclog("Tile GID at:(0,63) is: %d", m_gid) local updateColScheduler = nil local repainWithGIDScheduler = nil @@ -347,7 +347,7 @@ local function TMXReadWriteTest() local s = layer:getLayerSize() local y = 0 for y=0, s.height-1, 1 do - layer:setTileGID(m_gid2, cc.p(3, y)) + layer:setTileGID(m_gid2, ax.p(3, y)) end m_gid2 = (m_gid2 + 1) % 80 @@ -362,8 +362,8 @@ local function TMXReadWriteTest() local x = 0 for x=0, s.width-1, 1 do local y = s.height-1 - local tmpgid = layer:getTileGIDAt( cc.p(x, y) ) - layer:setTileGID(tmpgid+1, cc.p(x, y)) + local tmpgid = layer:getTileGIDAt( ax.p(x, y) ) + layer:setTileGID(tmpgid+1, ax.p(x, y)) end end @@ -375,7 +375,7 @@ local function TMXReadWriteTest() local s = layer:getLayerSize() local y = 0 for y=0, s.height-1, 1 do - layer:removeTileAt( cc.p(5.0, y) ) + layer:removeTileAt( ax.p(5.0, y) ) end end @@ -416,10 +416,10 @@ end -------------------------------------------------------------------- local function TMXHexTest() local ret = createTileDemoLayer("TMX Hex tes") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/hexa-test.tmx") + local map = ax.TMXTiledMap:create("TileMaps/hexa-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -434,16 +434,16 @@ end -------------------------------------------------------------------- local function TMXIsoTest() local ret = createTileDemoLayer("TMX Isometric test 0") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test.tmx") ret:addChild(map, 0, kTagTileMap) -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction( cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 )) ) + map:runAction( ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 )) ) return ret end @@ -454,16 +454,16 @@ end -------------------------------------------------------------------- local function TMXIsoTest1() local ret = createTileDemoLayer("TMX Isometric test + anchorPoint") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test1.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test1.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - map:setAnchorPoint(cc.p(0.5, 0.5)) + map:setAnchorPoint(ax.p(0.5, 0.5)) return ret end @@ -474,10 +474,10 @@ end -------------------------------------------------------------------- local function TMXIsoTest2() local ret = createTileDemoLayer("TMX Isometric test 2") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test2.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test2.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -486,7 +486,7 @@ local function TMXIsoTest2() -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction( cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) + map:runAction( ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) return ret end @@ -497,10 +497,10 @@ end -------------------------------------------------------------------- local function TMXUncompressedTest() local ret = createTileDemoLayer("TMX Uncompressed test") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test2-uncompressed.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test2-uncompressed.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -509,7 +509,7 @@ local function TMXUncompressedTest() -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction(cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) + map:runAction(ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) return ret end @@ -521,7 +521,7 @@ end -------------------------------------------------------------------- local function TMXTilesetTest() local ret = createTileDemoLayer("TMX Tileset test") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test5.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test5.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -537,13 +537,13 @@ end -------------------------------------------------------------------- local function TMXOrthoObjectsTest() local ret = createTileDemoLayer("TMX Ortho object test", "You should see a white box around the 3 platforms") - local map = cc.FastTMXTiledMap:create("TileMaps/ortho-objects.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/ortho-objects.tmx") ret:addChild(map, -1, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - - local drawNode = cc.DrawNode:create() + + local drawNode = ax.DrawNode:create() map:addChild(drawNode, 10) --------cclog("---: Iterating over all the group objects") @@ -561,7 +561,7 @@ local function TMXOrthoObjectsTest() break end --------cclog("object: %x", dict) - + local key = "x" local x = dict["x"] key = "y" @@ -570,19 +570,19 @@ local function TMXOrthoObjectsTest() local width = dict["width"]--dynamic_cast(dict:objectForKey("width")):getNumber() key = "height" local height = dict["height"]--dynamic_cast(dict:objectForKey("height")):getNumber() - - local color = cc.c4f(1,1,1,1) - drawNode:drawLine( cc.p(x, y), cc.p((x+width), y), color) - drawNode:drawLine( cc.p((x+width), y), cc.p((x+width), (y+height)), color) - drawNode:drawLine( cc.p((x+width), (y+height)), cc.p(x, (y+height)), color) - drawNode:drawLine( cc.p(x, (y+height)), cc.p(x, y), color) + + local color = ax.color(1,1,1,1) + drawNode:drawLine( ax.p(x, y), ax.p((x+width), y), color) + drawNode:drawLine( ax.p((x+width), y), ax.p((x+width), (y+height)), color) + drawNode:drawLine( ax.p((x+width), (y+height)), ax.p(x, (y+height)), color) + drawNode:drawLine( ax.p(x, (y+height)), ax.p(x, y), color) end --------cclog("---: Fetching 1 object by name") -- local platform = group:objectNamed("platform") --------cclog("platform: %x", platform) - - + + return ret end @@ -595,13 +595,13 @@ end local function TMXIsoObjectsTest() local ret = createTileDemoLayer("TMX Iso object test", "You need to parse them manually. See bug #810") - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test-objectgroup.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test-objectgroup.tmx") ret:addChild(map, -1, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - - local drawNode = cc.DrawNode:create() + + local drawNode = ax.DrawNode:create() map:addChild(drawNode, 10) local group = map:getObjectGroup("Object Group 1") @@ -613,13 +613,13 @@ local function TMXIsoObjectsTest() local i = 0 local len = #(objects) for i = 0, len-1, 1 do - dict = tolua.cast(objects[i + 1], "cc.Dictionary") + dict = tolua.cast(objects[i + 1], "ax.Dictionary") if dict == nil then break end --------cclog("object: %x", dict) - + local key = "x" local x = dict["x"] key = "y" @@ -628,12 +628,12 @@ local function TMXIsoObjectsTest() local width = dict["width"]--dynamic_cast(dict:objectForKey("width")):getNumber() key = "height" local height = dict["height"]--dynamic_cast(dict:objectForKey("height")):getNumber() - - local color = cc.c4f(1,1,1,1) - drawNode:drawLine( cc.p(x, y), cc.p((x+width), y), color) - drawNode:drawLine( cc.p((x+width), y), cc.p((x+width), (y+height)), color) - drawNode:drawLine( cc.p((x+width), (y+height)), cc.p(x, (y+height)), color) - drawNode:drawLine( cc.p(x, (y+height)), cc.p(x, y), color) + + local color = ax.color(1,1,1,1) + drawNode:drawLine( ax.p(x, y), ax.p((x+width), y), color) + drawNode:drawLine( ax.p((x+width), y), ax.p((x+width), (y+height)), color) + drawNode:drawLine( ax.p((x+width), (y+height)), ax.p(x, (y+height)), color) + drawNode:drawLine( ax.p(x, (y+height)), ax.p(x, y), color) end return ret end @@ -646,7 +646,7 @@ end local function TMXResizeTest() local ret = createTileDemoLayer("TMX resize test", "Should not crash. Testing issue #740") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test5.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test5.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -658,7 +658,7 @@ local function TMXResizeTest() local y = 0 for y = 0, ls.height-1, 1 do for x = 0, ls.width-1, 1 do - layer:setTileGID(1, cc.p( x, y ) ) + layer:setTileGID(1, ax.p( x, y ) ) end end return ret @@ -672,27 +672,27 @@ end local function TMXIsoZorder() local m_tamara = nil local ret = createTileDemoLayer("TMX Iso Zorder", "Sprite should hide behind the trees") - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test-zorder.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test-zorder.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - map:setPosition(cc.p(-s.width/2,0)) + map:setPosition(ax.p(-s.width/2,0)) - m_tamara = cc.Sprite:create(s_pPathSister1) + m_tamara = ax.Sprite:create(s_pPathSister1) map:addChild(m_tamara, #(map:getChildren())) m_tamara:retain() local mapWidth = map:getMapSize().width * map:getTileSize().width - m_tamara:setPosition(AX_POINT_PIXELS_TO_POINTS(cc.p( mapWidth/2,0))) - m_tamara:setAnchorPoint(cc.p(0.5,0)) + m_tamara:setPosition(AX_POINT_PIXELS_TO_POINTS(ax.p( mapWidth/2,0))) + m_tamara:setAnchorPoint(ax.p(0.5,0)) - local move = cc.MoveBy:create(10, cc.p(300,250)) + local move = ax.MoveBy:create(10, ax.p(300,250)) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq) ) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq) ) local function repositionSprite(dt) - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local map = ret:getChildByTag(kTagTileMap) @@ -710,7 +710,7 @@ local function TMXIsoZorder() local schedulerEntry = nil local function onNodeEvent(event) if event == "enter" then - cc.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) schedulerEntry = scheduler:scheduleScriptFunc(repositionSprite, 0, false) elseif event == "exit" then if m_tamara ~= nil then @@ -733,25 +733,25 @@ end local function TMXOrthoZorder() local m_tamara = nil local ret = createTileDemoLayer("TMX Ortho Zorder", "Sprite should hide behind the trees") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test-zorder.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test-zorder.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - m_tamara = cc.Sprite:create(s_pPathSister1) + m_tamara = ax.Sprite:create(s_pPathSister1) map:addChild(m_tamara, #(map:getChildren())) m_tamara:retain() - m_tamara:setAnchorPoint(cc.p(0.5,0)) + m_tamara:setAnchorPoint(ax.p(0.5,0)) - local move = cc.MoveBy:create(10, cc.p(400,450)) + local move = ax.MoveBy:create(10, ax.p(400,450)) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq)) local function repositionSprite(dt) - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local map = ret:getChildByTag(kTagTileMap) @@ -791,28 +791,28 @@ end local function TMXIsoVertexZ() local m_tamara = nil local ret = createTileDemoLayer("TMX Iso VertexZ", "Sprite should hide behind the trees") - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test-vertexz.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test-vertexz.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() - map:setPosition( cc.p(-s.width/2,0) ) + map:setPosition( ax.p(-s.width/2,0) ) cclog("ContentSize: %f, %f", s.width,s.height) -- because I'm lazy, I'm reusing a tile as an sprite, but since this method uses vertexZ, you - -- can use any cc.Sprite and it will work OK. + -- can use any ax.Sprite and it will work OK. local layer = map:getLayer("Trees") - m_tamara = layer:getTileAt( cc.p(29,29) ) + m_tamara = layer:getTileAt( ax.p(29,29) ) m_tamara:retain() - local move = cc.MoveBy:create(10, cc.pMul( cc.p(300,250), 1/AX_CONTENT_SCALE_FACTOR() ) ) + local move = ax.MoveBy:create(10, ax.pMul( ax.p(300,250), 1/AX_CONTENT_SCALE_FACTOR() ) ) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq) ) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq) ) local function repositionSprite(dt) -- tile height is 64x32 -- map size: 30x30 - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local newZ = -(p.y+32) /16 m_tamara:setPositionZ( newZ ) @@ -822,19 +822,19 @@ local function TMXIsoVertexZ() local function onNodeEvent(event) if event == "enter" then -- TIP: 2d projection should be used - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION2_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION2_D ) schedulerEntry = scheduler:scheduleScriptFunc(repositionSprite, 0, false) - cc.Director:getInstance():getRenderer():setDepthTest(true) - cc.Director:getInstance():getRenderer():setDepthWrite(true) + ax.Director:getInstance():getRenderer():setDepthTest(true) + ax.Director:getInstance():getRenderer():setDepthWrite(true) elseif event == "exit" then -- At exit use any other projection. - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) if m_tamara ~= nil then m_tamara:release() end scheduler:unscheduleScriptEntry(schedulerEntry) - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():getRenderer():setDepthWrite(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthWrite(false) end end @@ -850,28 +850,28 @@ end local function TMXOrthoVertexZ() local m_tamara = nil local ret = createTileDemoLayer("TMX Ortho vertexZ", "Sprite should hide behind the trees") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test-vertexz.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test-vertexz.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) -- because I'm lazy, I'm reusing a tile as an sprite, but since this method uses vertexZ, you - -- can use any cc.Sprite and it will work OK. + -- can use any ax.Sprite and it will work OK. local layer = map:getLayer("trees") - m_tamara = layer:getTileAt(cc.p(0,11)) + m_tamara = layer:getTileAt(ax.p(0,11)) cclog("vertexZ:"..m_tamara:getPositionZ()) m_tamara:retain() - local move = cc.MoveBy:create(10, cc.pMul( cc.p(400,450), 1/AX_CONTENT_SCALE_FACTOR())) + local move = ax.MoveBy:create(10, ax.pMul( ax.p(400,450), 1/AX_CONTENT_SCALE_FACTOR())) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq)) local function repositionSprite(dt) -- tile height is 101x81 -- map size: 12x12 - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) m_tamara:setPositionZ( -( (p.y+81) /81) ) end @@ -880,19 +880,19 @@ local function TMXOrthoVertexZ() local function onNodeEvent(event) if event == "enter" then -- TIP: 2d projection should be used - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION2_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION2_D ) schedulerEntry = scheduler:scheduleScriptFunc(repositionSprite, 0, false) - cc.Director:getInstance():getRenderer():setDepthTest(true) - cc.Director:getInstance():getRenderer():setDepthWrite(true) + ax.Director:getInstance():getRenderer():setDepthTest(true) + ax.Director:getInstance():getRenderer():setDepthWrite(true) elseif event == "exit" then -- At exit use any other projection. - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) if m_tamara ~= nil then m_tamara:release() end scheduler:unscheduleScriptEntry(schedulerEntry) - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():getRenderer():setDepthWrite(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthWrite(false) end end @@ -908,10 +908,10 @@ end -------------------------------------------------------------------- local function TMXIsoMoveLayer() local ret = createTileDemoLayer("TMX Iso Move Layer", "Trees should be horizontally aligned") - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test-movelayer.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test-movelayer.tmx") ret:addChild(map, 0, kTagTileMap) - map:setPosition(cc.p(-700,-50)) + map:setPosition(ax.p(-700,-50)) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) @@ -926,7 +926,7 @@ end -------------------------------------------------------------------- local function TMXOrthoMoveLayer() local ret = createTileDemoLayer("TMX Ortho Move Layer", "Trees should be horizontally aligned") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test-movelayer.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test-movelayer.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -942,7 +942,7 @@ end local function TMXTilePropertyTest() local ret = createTileDemoLayer("TMX Tile Property Test", "In the console you should see tile properties") - local map = cc.TMXTiledMap:create("TileMaps/ortho-tile-property.tmx") + local map = ax.TMXTiledMap:create("TileMaps/ortho-tile-property.tmx") ret:addChild(map ,0 ,kTagTileMap) local i = 0 for i=1, 20, 1 do @@ -959,13 +959,13 @@ end local function TMXOrthoFlipTest() local ret = createTileDemoLayer("TMX tile flip test") - local map = cc.FastTMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) return ret end @@ -978,47 +978,47 @@ end local function TMXOrthoFlipRunTimeTest() local ret = createTileDemoLayer("TMX tile flip run time test", "in 2 sec bottom left tiles will flip") - local map = cc.FastTMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) local function flipIt(dt) local map = ret:getChildByTag(kTagTileMap) local layer = map:getLayer("Layer 0") - - local tileCoord = cc.p(1, 10) + + local tileCoord = ax.p(1, 10) local flags = 0 local GID, flags = layer:getTileGIDAt(tileCoord, flags) - if 0 ~= bit._and(flags, cc.TMX_TILE_VERTICAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_VERTICAL_FLAG)) + if 0 ~= bit._and(flags, ax.TMX_TILE_VERTICAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_VERTICAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_VERTICAL_FLAG) + flags = bit._or(flags, ax.TMX_TILE_VERTICAL_FLAG) end layer:setTileGID(GID, tileCoord, flags) - tileCoord = cc.p(1,8) + tileCoord = ax.p(1,8) GID, flags = layer:getTileGIDAt(tileCoord, flags) - if 0 ~= bit._and(flags, cc.TMX_TILE_VERTICAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_VERTICAL_FLAG)) + if 0 ~= bit._and(flags, ax.TMX_TILE_VERTICAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_VERTICAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_VERTICAL_FLAG) - end + flags = bit._or(flags, ax.TMX_TILE_VERTICAL_FLAG) + end layer:setTileGID(GID ,tileCoord, flags) - tileCoord = cc.p(2,8) + tileCoord = ax.p(2,8) GID, flags = layer:getTileGIDAt(tileCoord, flags) -- Horizontal - if 0~= bit._and(flags, cc.TMX_TILE_HORIZONTAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_HORIZONTAL_FLAG)) + if 0~= bit._and(flags, ax.TMX_TILE_HORIZONTAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_HORIZONTAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_HORIZONTAL_FLAG) - end - layer:setTileGID(GID, tileCoord, flags) + flags = bit._or(flags, ax.TMX_TILE_HORIZONTAL_FLAG) + end + layer:setTileGID(GID, tileCoord, flags) end local schedulerEntry = nil local function onNodeEvent(event) @@ -1046,19 +1046,19 @@ local function TMXOrthoFromXMLTest() local resources = "TileMaps" -- partial paths are OK as resource paths. local file = resources.."/orthogonal-test1.tmx" - local str = cc.FileUtils:getInstance():getStringFromFile(file) - -- cc.ASSERT(str != NULL, "Unable to open file") + local str = ax.FileUtils:getInstance():getStringFromFile(file) + -- ax.ASSERT(str != NULL, "Unable to open file") if (str == nil) then cclog("Unable to open file") end - local map = cc.FastTMXTiledMap:createWithXML(str ,resources) + local map = ax.FastTMXTiledMap:createWithXML(str ,resources) ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) return ret end @@ -1072,7 +1072,7 @@ end local function TMXOrthoXMLFormatTest() local ret = createTileDemoLayer("you should see blue, green and yellow in console.") - local map = cc.FastTMXTiledMap:create("TileMaps/xml-test.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/xml-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -1082,7 +1082,7 @@ local function TMXOrthoXMLFormatTest() cclog("GID:%d, Properties:%s", i, map:getPropertiesForGID(i)["name"]) end - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) return ret end @@ -1094,15 +1094,15 @@ end -------------------------------------------------------------------- local function TMXBug987() local ret = createTileDemoLayer("TMX Bug 987", "You should see an square") - local map = cc.FastTMXTiledMap:create("TileMaps/orthogonal-test6.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/orthogonal-test6.tmx") ret:addChild(map, 0, kTagTileMap) local s1 = map:getContentSize() cclog("ContentSize: %f, %f", s1.width,s1.height) - map:setAnchorPoint(cc.p(0, 0)) + map:setAnchorPoint(ax.p(0, 0)) local layer = map:getLayer("Tile Layer 1") - layer:setTileGID(3, cc.p(2,2)) + layer:setTileGID(3, ax.p(2,2)) return ret end @@ -1113,7 +1113,7 @@ end -------------------------------------------------------------------- local function TMXBug787() local ret = createTileDemoLayer("TMX Bug 787", "You should see a map") - local map = cc.FastTMXTiledMap:create("TileMaps/iso-test-bug787.tmx") + local map = ax.FastTMXTiledMap:create("TileMaps/iso-test-bug787.tmx") ret:addChild(map, 0, kTagTileMap) map:setScale(0.25) return ret @@ -1122,7 +1122,7 @@ end function FastTiledMapTestMain() cclog("FastTiledMapTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { TMXIsoZorder, @@ -1156,7 +1156,7 @@ function FastTiledMapTestMain() -- TMXGIDObjectsTestNew, } Helper.index = 1 - + scene:addChild(TMXIsoZorder()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/FileUtilsTest/FileUtilsTest.lua b/tests/lua-tests/Content/src/FileUtilsTest/FileUtilsTest.lua index b4c745b318b7..2840f2d7d8e1 100644 --- a/tests/lua-tests/Content/src/FileUtilsTest/FileUtilsTest.lua +++ b/tests/lua-tests/Content/src/FileUtilsTest/FileUtilsTest.lua @@ -1,11 +1,11 @@ local FileUtilsGetDataDemo = class("FileUtilsGetDataDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) function FileUtilsGetDataDemo:ctor() - + self.hexString = [[4f67 6753 0002 0000 0000 0000 0000 ac5c 4540 0000 0000 b299 90b5 011e 0176 6f72 6269 7300 0000 0001 112b 0000 ffff ffff @@ -275,8 +275,8 @@ d6ec 7fb0 7168 be5f a3d7 2771 ecab 7474 c595 38d3 2983 dbdd db3a 3669 76be 8db0 c75d cf62 a30f]] - self.hexString = self.hexString:gsub("%s+", "") - self.hexRead = self:dumpHex(cc.FileUtils:getInstance():getDataFromFile("effect2.ogg")) + self.hexString = self.hexString:gsub("%s+", "") + self.hexRead = self:dumpHex(ax.FileUtils:getInstance():getDataFromFile("effect2.ogg")) local function onNodeEvent(event) if "enter" == event then @@ -285,24 +285,24 @@ c75d cf62 a30f]] end self:registerScriptHandler(onNodeEvent) - + Helper.titleLabel:setString("Test FileUtils.getDataFromFile") end function FileUtilsGetDataDemo:dumpHex(str) local len = string.len(str) local hex = "" - + for i = 1, len do local ord = string.byte(str, i) hex = hex .. string.format("%02x", ord) end - + return hex end function FileUtilsGetDataDemo:onEnter() - local label = cc.Label:createWithTTF("error happended while reading file data", "fonts/Marker Felt.ttf", 20) + local label = ax.Label:createWithTTF("error happended while reading file data", "fonts/Marker Felt.ttf", 20) -- print(self.hexString) -- print("............") -- print(self.hexRead) @@ -310,21 +310,21 @@ function FileUtilsGetDataDemo:onEnter() label:setString("reading file data correctly") end - local visibleSize = cc.Director:getInstance():getVisibleSize() - local origin = cc.Director:getInstance():getVisibleOrigin() + local visibleSize = ax.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() label:setPosition(origin.x + visibleSize.width/2, origin.y + visibleSize.height/2) self:addChild(label) end function FileUtilsTestMain() - - Helper.createFunctionTable = + + Helper.createFunctionTable = { FileUtilsGetDataDemo.create } Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(CreateBackMenuItem()) scene:addChild(FileUtilsGetDataDemo.create()) diff --git a/tests/lua-tests/Content/src/FontTest/FontTest.lua b/tests/lua-tests/Content/src/FontTest/FontTest.lua index 5aeb8caae37c..c9a0e5b70c22 100644 --- a/tests/lua-tests/Content/src/FontTest/FontTest.lua +++ b/tests/lua-tests/Content/src/FontTest/FontTest.lua @@ -17,9 +17,9 @@ cclog("font count = "..fontCount) local vAlignIdx = 1 local verticalAlignment = { - cc.VERTICAL_TEXT_ALIGNMENT_TOP, - cc.VERTICAL_TEXT_ALIGNMENT_CENTER, - cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM, + ax.VERTICAL_TEXT_ALIGNMENT_TOP, + ax.VERTICAL_TEXT_ALIGNMENT_CENTER, + ax.VERTICAL_TEXT_ALIGNMENT_BOTTOM, } local vAlignCount = #(verticalAlignment) @@ -27,41 +27,41 @@ local vAlignCount = #(verticalAlignment) local function showFont(ret, pFont) cclog("vAlignIdx="..vAlignIdx) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local blockSize = cc.size(s.width/3, 200) + local blockSize = ax.size(s.width/3, 200) local fontSize = 26 - local top = cc.Label:createWithTTF(pFont, pFont, 24) - local left = cc.Label:createWithTTF("alignment left", pFont, fontSize, - blockSize, cc.TEXT_ALIGNMENT_LEFT, verticalAlignment[vAlignIdx]) - local center = cc.Label:createWithTTF("alignment center", pFont, fontSize, - blockSize, cc.TEXT_ALIGNMENT_CENTER, verticalAlignment[vAlignIdx]) - local right = cc.Label:createWithTTF("alignment right", pFont, fontSize, - blockSize, cc.TEXT_ALIGNMENT_RIGHT, verticalAlignment[vAlignIdx]) + local top = ax.Label:createWithTTF(pFont, pFont, 24) + local left = ax.Label:createWithTTF("alignment left", pFont, fontSize, + blockSize, ax.TEXT_ALIGNMENT_LEFT, verticalAlignment[vAlignIdx]) + local center = ax.Label:createWithTTF("alignment center", pFont, fontSize, + blockSize, ax.TEXT_ALIGNMENT_CENTER, verticalAlignment[vAlignIdx]) + local right = ax.Label:createWithTTF("alignment right", pFont, fontSize, + blockSize, ax.TEXT_ALIGNMENT_RIGHT, verticalAlignment[vAlignIdx]) - local leftColor = cc.LayerColor:create(cc.c4b(100, 100, 100, 255), blockSize.width, blockSize.height) - local centerColor = cc.LayerColor:create(cc.c4b(200, 100, 100, 255), blockSize.width, blockSize.height) - local rightColor = cc.LayerColor:create(cc.c4b(100, 100, 200, 255), blockSize.width, blockSize.height) + local leftColor = ax.LayerColor:create(ax.color32(100, 100, 100, 255), blockSize.width, blockSize.height) + local centerColor = ax.LayerColor:create(ax.color32(200, 100, 100, 255), blockSize.width, blockSize.height) + local rightColor = ax.LayerColor:create(ax.color32(100, 100, 200, 255), blockSize.width, blockSize.height) leftColor:setIgnoreAnchorPointForPosition(false) centerColor:setIgnoreAnchorPointForPosition(false) rightColor:setIgnoreAnchorPointForPosition(false) - top:setAnchorPoint(cc.p(0.5, 1)) - left:setAnchorPoint(cc.p(0,0.5)) - leftColor:setAnchorPoint(cc.p(0,0.5)) - center:setAnchorPoint(cc.p(0,0.5)) - centerColor:setAnchorPoint(cc.p(0,0.5)) - right:setAnchorPoint(cc.p(0,0.5)) - rightColor:setAnchorPoint(cc.p(0,0.5)) + top:setAnchorPoint(ax.p(0.5, 1)) + left:setAnchorPoint(ax.p(0,0.5)) + leftColor:setAnchorPoint(ax.p(0,0.5)) + center:setAnchorPoint(ax.p(0,0.5)) + centerColor:setAnchorPoint(ax.p(0,0.5)) + right:setAnchorPoint(ax.p(0,0.5)) + rightColor:setAnchorPoint(ax.p(0,0.5)) - top:setPosition(cc.p(s.width/2,s.height-20)) - left:setPosition(cc.p(0,s.height/2)) + top:setPosition(ax.p(s.width/2,s.height-20)) + left:setPosition(ax.p(0,s.height/2)) leftColor:setPosition(left:getPosition()) - center:setPosition(cc.p(blockSize.width, s.height/2)) + center:setPosition(ax.p(blockSize.width, s.height/2)) centerColor:setPosition(center:getPosition()) - right:setPosition(cc.p(blockSize.width*2, s.height/2)) + right:setPosition(ax.p(blockSize.width*2, s.height/2)) rightColor:setPosition(right:getPosition()) ret:addChild(leftColor, -1) @@ -93,7 +93,7 @@ function FontTestMain() cclog("FontTestMain") Helper.index = 1 vAlignIdx = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { createTestLayer, createTestLayer, @@ -103,7 +103,7 @@ function FontTestMain() createTestLayer } Helper.index = 1 - + scene:addChild(createTestLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/IntervalTest/IntervalTest.lua b/tests/lua-tests/Content/src/IntervalTest/IntervalTest.lua index a7512e3ad69e..23c213d98d2f 100644 --- a/tests/lua-tests/Content/src/IntervalTest/IntervalTest.lua +++ b/tests/lua-tests/Content/src/IntervalTest/IntervalTest.lua @@ -1,38 +1,38 @@ -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() local SID_STEP1 = 100 local SID_STEP2 = 101 local SID_STEP3 = 102 local IDC_PAUSE = 200 local function IntervalLayer() - local ret = cc.Layer:create() + local ret = ax.Layer:create() local m_time0 = 0 local m_time1 = 0 local m_time2 = 0 local m_time3 = 0 local m_time4 = 0 - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() -- sun - local sun = cc.ParticleSun:create() - sun:setTexture(cc.Director:getInstance():getTextureCache():addImage("Images/fire.png")) - sun:setPosition( cc.p(VisibleRect:rightTop().x-32,VisibleRect:rightTop().y-32) ) + local sun = ax.ParticleSun:create() + sun:setTexture(ax.Director:getInstance():getTextureCache():addImage("Images/fire.png")) + sun:setPosition( ax.p(VisibleRect:rightTop().x-32,VisibleRect:rightTop().y-32) ) sun:setTotalParticles(130) sun:setLife(0.6) ret:addChild(sun) -- timers - m_label0 = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") - m_label0:setAnchorPoint(cc.p(0.5, 0.5)) - m_label1 = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") - m_label1:setAnchorPoint(cc.p(0.5, 0.5)) - m_label2 = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") - m_label2:setAnchorPoint(cc.p(0.5, 0.5)) - m_label3 = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") - m_label3:setAnchorPoint(cc.p(0.5, 0.5)) - m_label4 = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") - m_label4:setAnchorPoint(cc.p(0.5, 0.5)) + m_label0 = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") + m_label0:setAnchorPoint(ax.p(0.5, 0.5)) + m_label1 = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") + m_label1:setAnchorPoint(ax.p(0.5, 0.5)) + m_label2 = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") + m_label2:setAnchorPoint(ax.p(0.5, 0.5)) + m_label3 = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") + m_label3:setAnchorPoint(ax.p(0.5, 0.5)) + m_label4 = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "0") + m_label4:setAnchorPoint(ax.p(0.5, 0.5)) local function update(dt) m_time0 = m_time0 + dt @@ -82,8 +82,8 @@ local function IntervalLayer() scheduler:unscheduleScriptEntry(schedulerEntry2) scheduler:unscheduleScriptEntry(schedulerEntry3) scheduler:unscheduleScriptEntry(schedulerEntry4) - if cc.Director:getInstance():isPaused() then - cc.Director:getInstance():resume() + if ax.Director:getInstance():isPaused() then + ax.Director:getInstance():resume() end end end @@ -91,11 +91,11 @@ local function IntervalLayer() ret:registerScriptHandler(onNodeEvent) - m_label0:setPosition(cc.p(s.width*1/6, s.height/2)) - m_label1:setPosition(cc.p(s.width*2/6, s.height/2)) - m_label2:setPosition(cc.p(s.width*3/6, s.height/2)) - m_label3:setPosition(cc.p(s.width*4/6, s.height/2)) - m_label4:setPosition(cc.p(s.width*5/6, s.height/2)) + m_label0:setPosition(ax.p(s.width*1/6, s.height/2)) + m_label1:setPosition(ax.p(s.width*2/6, s.height/2)) + m_label2:setPosition(ax.p(s.width*3/6, s.height/2)) + m_label3:setPosition(ax.p(s.width*4/6, s.height/2)) + m_label4:setPosition(ax.p(s.width*5/6, s.height/2)) ret:addChild(m_label0) ret:addChild(m_label1) @@ -104,26 +104,26 @@ local function IntervalLayer() ret:addChild(m_label4) -- Sprite - local sprite = cc.Sprite:create(s_pPathGrossini) - sprite:setPosition( cc.p(VisibleRect:left().x + 40, VisibleRect:bottom().y + 50) ) + local sprite = ax.Sprite:create(s_pPathGrossini) + sprite:setPosition( ax.p(VisibleRect:left().x + 40, VisibleRect:bottom().y + 50) ) - local jump = cc.JumpBy:create(3, cc.p(s.width-80,0), 50, 4) + local jump = ax.JumpBy:create(3, ax.p(s.width-80,0), 50, 4) ret:addChild(sprite) - sprite:runAction( cc.RepeatForever:create(cc.Sequence:create(jump, jump:reverse()))) + sprite:runAction( ax.RepeatForever:create(ax.Sequence:create(jump, jump:reverse()))) -- pause button - local item1 = cc.MenuItemFont:create("Pause") + local item1 = ax.MenuItemFont:create("Pause") local function onPause(tag, pSender) - if cc.Director:getInstance():isPaused() then - cc.Director:getInstance():resume() + if ax.Director:getInstance():isPaused() then + ax.Director:getInstance():resume() else - cc.Director:getInstance():pause() + ax.Director:getInstance():pause() end end item1:registerScriptTapHandler(onPause) - local menu = cc.Menu:create(item1) - menu:setPosition( cc.p(s.width/2, s.height-50) ) + local menu = ax.Menu:create(item1) + menu:setPosition( ax.p(s.width/2, s.height-50) ) ret:addChild( menu ) @@ -133,7 +133,7 @@ end function IntervalTestMain() cclog("IntervalTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = IntervalLayer() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) diff --git a/tests/lua-tests/Content/src/KeypadTest/KeypadTest.lua b/tests/lua-tests/Content/src/KeypadTest/KeypadTest.lua index f209733cfef9..7c73f01b614c 100644 --- a/tests/lua-tests/Content/src/KeypadTest/KeypadTest.lua +++ b/tests/lua-tests/Content/src/KeypadTest/KeypadTest.lua @@ -1,17 +1,17 @@ -local function KeypadMainLayer() - local layer = cc.Layer:create() +local function KeypadMainLayer() + local layer = ax.Layer:create() local function onEnter() print("come in") - local s = cc.Director:getInstance():getWinSize() - local label = cc.Label:createWithTTF("Keypad Test", s_thonburiPath, 28) + local s = ax.Director:getInstance():getWinSize() + local label = ax.Label:createWithTTF("Keypad Test", s_thonburiPath, 28) layer:addChild(label, 0) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, s.height-50)) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, s.height-50)) - local labelTip = cc.Label:createWithTTF("Please press any key...", s_thonburiPath, 22) - labelTip:setAnchorPoint(cc.p(0.5, 0.5)) - labelTip:setPosition(cc.p(s.width / 2, s.height / 2)) + local labelTip = ax.Label:createWithTTF("Please press any key...", s_thonburiPath, 22) + labelTip:setAnchorPoint(ax.p(0.5, 0.5)) + labelTip:setPosition(ax.p(s.width / 2, s.height / 2)) layer:addChild(labelTip, 0) local function onKeyReleased(keyCode, event) @@ -19,8 +19,8 @@ local function KeypadMainLayer() label:setString("key: " .. keyCode .. " was clicked") end - local listener = cc.EventListenerKeyboard:create() - listener:registerScriptHandler(onKeyReleased, cc.Handler.EVENT_KEYBOARD_RELEASED ) + local listener = ax.EventListenerKeyboard:create() + listener:registerScriptHandler(onKeyReleased, ax.Handler.EVENT_KEYBOARD_RELEASED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, labelTip) @@ -40,7 +40,7 @@ end function KeypadTestMain() cclog("KeypadTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(KeypadMainLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/LabelTestNew/LabelTestNew.lua b/tests/lua-tests/Content/src/LabelTestNew/LabelTestNew.lua index 02a05f0a1991..f4b218f536a4 100644 --- a/tests/lua-tests/Content/src/LabelTestNew/LabelTestNew.lua +++ b/tests/lua-tests/Content/src/LabelTestNew/LabelTestNew.lua @@ -1,5 +1,5 @@ -local size = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local size = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local kTagTileMap = 1 local kTagSpriteManager = 1 @@ -37,39 +37,39 @@ end function LabelFNTColorAndOpacity.create() cclog("LabelFNTColorAndOpacity.create") - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelFNTColorAndOpacity.layer = layer m_time = 0 - local col = cc.LayerColor:create( cc.c4b(128,128,128,255) ) + local col = ax.LayerColor:create( ax.color32(128,128,128,255) ) layer:addChild(col, -10) - local label1 = cc.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") + local label1 = ax.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") -- testing anchors - label1:setAnchorPoint( cc.p(0,0) ) + label1:setAnchorPoint( ax.p(0,0) ) layer:addChild(label1, 0, kTagBitmapAtlas1) - local fade = cc.FadeOut:create(1.0) + local fade = ax.FadeOut:create(1.0) local fade_in = fade:reverse() - local seq = cc.Sequence:create(fade,fade_in) - local repeatAction = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(fade,fade_in) + local repeatAction = ax.RepeatForever:create(seq) label1:runAction(repeatAction) - local label2 = cc.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") + local label2 = ax.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") -- testing anchors - label2:setAnchorPoint( cc.p(0.5, 0.5) ) - label2:setColor(cc.c3b(255, 0, 0 )) + label2:setAnchorPoint( ax.p(0.5, 0.5) ) + label2:setColor(ax.color32(255, 0, 0 )) layer:addChild(label2, 0, kTagBitmapAtlas2) label2:runAction(repeatAction:clone()) - local label3 = cc.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") + local label3 = ax.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Test") -- testing anchors - label3:setAnchorPoint( cc.p(1,1) ) + label3:setAnchorPoint( ax.p(1,1) ) layer:addChild(label3, 0, kTagBitmapAtlas3) label1:setPosition( VisibleRect:leftBottom() ) @@ -119,24 +119,24 @@ end function LabelFNTSpriteActions.create() cclog("LabelFNTSpriteActions.create") m_time = 0 - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelFNTSpriteActions.layer = layer - - local s = cc.Director:getInstance():getWinSize() - - local drawNode = cc.DrawNode:create() - drawNode:drawLine( cc.p(0, s.height/2), cc.p(s.width, s.height/2), cc.c4f(1,1,1,1)) - drawNode:drawLine( cc.p(s.width/2, 0), cc.p(s.width/2, s.height), cc.c4f(1,1,1,1)) + + local s = ax.Director:getInstance():getWinSize() + + local drawNode = ax.DrawNode:create() + drawNode:drawLine( ax.p(0, s.height/2), ax.p(s.width, s.height/2), ax.color(1,1,1,1)) + drawNode:drawLine( ax.p(s.width/2, 0), ax.p(s.width/2, s.height), ax.color(1,1,1,1)) layer:addChild(drawNode, -10) -- Upper Label - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "Bitmap Font Atlas") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "Bitmap Font Atlas") layer:addChild(label) - label:setPosition( cc.p(s.width/2, s.height/2) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/2) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) local BChar = label:getLetter(0) @@ -144,23 +144,23 @@ function LabelFNTSpriteActions.create() local AChar = label:getLetter(12) - local rotate = cc.RotateBy:create(2, 360) - local rot_4ever = cc.RepeatForever:create(rotate) + local rotate = ax.RotateBy:create(2, 360) + local rot_4ever = ax.RepeatForever:create(rotate) - local scale = cc.ScaleBy:create(2, 1.5) + local scale = ax.ScaleBy:create(2, 1.5) local scale_back = scale:reverse() - local scale_seq = cc.Sequence:create(scale, scale_back) - local scale_4ever = cc.RepeatForever:create(scale_seq) + local scale_seq = ax.Sequence:create(scale, scale_back) + local scale_4ever = ax.RepeatForever:create(scale_seq) - local jump = cc.JumpBy:create(0.5, cc.p(0, 0), 60, 1) - local jump_4ever = cc.RepeatForever:create(jump) + local jump = ax.JumpBy:create(0.5, ax.p(0, 0), 60, 1) + local jump_4ever = ax.RepeatForever:create(jump) - local fade_out = cc.FadeOut:create(1) - local fade_in = cc.FadeIn:create(1) + local fade_out = ax.FadeOut:create(1) + local fade_in = ax.FadeIn:create(1) - local seq = cc.Sequence:create(fade_out, fade_in) - local fade_4ever = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(fade_out, fade_in) + local fade_4ever = ax.RepeatForever:create(seq) BChar:runAction(rot_4ever) BChar:runAction(scale_4ever) @@ -169,9 +169,9 @@ function LabelFNTSpriteActions.create() -- Bottom Label - local label2 = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "00.0") + local label2 = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "00.0") layer:addChild(label2, 0, kTagBitmapAtlas2) - label2:setPosition( cc.p(s.width/2.0, 80) ) + label2:setPosition( ax.p(s.width/2.0, 80) ) local lastChar = label2:getLetter(3) lastChar:runAction(rot_4ever:clone()) @@ -202,17 +202,17 @@ end local LabelFNTPadding = {} LabelFNTPadding.layer = nil function LabelFNTPadding:create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelFNTPadding.layer = layer - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "abcdefg") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest4.fnt", "abcdefg") layer:addChild(label) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - label:setPosition( cc.p(s.width/2, s.height/2) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/2) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) Helper.titleLabel:setString("New Label + .FNT file") Helper.subtitleLabel:setString("Testing padding") @@ -229,25 +229,25 @@ LabelFNTOffset.layer = nil function LabelFNTOffset:create() cclog("LabelFNTOffset:create") - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelFNTOffset.layer = layer - local s = cc.Director:getInstance():getWinSize() - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "FaFeFiFoFu") + local s = ax.Director:getInstance():getWinSize() + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "FaFeFiFoFu") layer:addChild(label) - label:setPosition( cc.p(s.width/2, s.height/2+50) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/2+50) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) - label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "fafefifofu") + label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "fafefifofu") layer:addChild(label) - label:setPosition( cc.p(s.width/2, s.height/2) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/2) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) - label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "aeiou") + label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "aeiou") layer:addChild(label) - label:setPosition( cc.p(s.width/2, s.height/2-50) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/2-50) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) Helper.titleLabel:setString("New Label + .FNT file") Helper.subtitleLabel:setString("Rendering should be OK. Testing offset") @@ -261,29 +261,29 @@ end -------------------------------------------------------------------- local LabelFNTColor = { layer= nil } function LabelFNTColor:create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() LabelFNTColor.layer = layer Helper.initWithLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Blue") - label:setColor( cc.c3b(0, 0, 255 )) + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Blue") + label:setColor( ax.color32(0, 0, 255 )) layer:addChild(label) - label:setPosition( cc.p(s.width/2, s.height/4) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) + label:setPosition( ax.p(s.width/2, s.height/4) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) - label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Red") + label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Red") layer:addChild(label) - label:setPosition( cc.p(s.width/2, 2*s.height/4) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) - label:setColor( cc.c3b(255, 0, 0) ) + label:setPosition( ax.p(s.width/2, 2*s.height/4) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) + label:setColor( ax.color32(255, 0, 0) ) - label = cc.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Green") + label = ax.Label:createWithBMFont("fonts/bitmapFontTest5.fnt", "Green") layer:addChild(label) - label:setPosition( cc.p(s.width/2, 3*s.height/4) ) - label:setAnchorPoint( cc.p(0.5, 0.5) ) - label:setColor( cc.c3b(0, 255, 0 )) + label:setPosition( ax.p(s.width/2, 3*s.height/4) ) + label:setAnchorPoint( ax.p(0.5, 0.5) ) + label:setColor( ax.color32(0, 255, 0 )) label:setString("Green") Helper.titleLabel:setString("New Label + .FNT file") @@ -299,32 +299,32 @@ end -------------------------------------------------------------------- local LabelTTFColor = { layer= nil } function LabelTTFColor:create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() LabelTTFColor.layer = layer Helper.initWithLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath="fonts/arial.ttf" ttfConfig.fontSize=18 - local label1 = cc.Label:createWithTTF(ttfConfig,"Green", cc.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) - label1:setTextColor( cc.c4b(0, 255, 0, 255)) + local label1 = ax.Label:createWithTTF(ttfConfig,"Green", ax.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) + label1:setTextColor( ax.color32(0, 255, 0, 255)) layer:addChild(label1) - label1:setPosition( cc.p(s.width/2, s.height/5 * 1.5) ) - label1:setAnchorPoint( cc.p(0.5, 0.5) ) + label1:setPosition( ax.p(s.width/2, s.height/5 * 1.5) ) + label1:setAnchorPoint( ax.p(0.5, 0.5) ) - local label2 = cc.Label:createWithTTF(ttfConfig, "Red", cc.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) + local label2 = ax.Label:createWithTTF(ttfConfig, "Red", ax.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) layer:addChild(label2) - label2:setPosition( cc.p(s.width/2, s.height/5 * 2.0) ) - label2:setAnchorPoint( cc.p(0.5, 0.5) ) - label2:setTextColor( cc.c4b(255, 0, 0, 255) ) + label2:setPosition( ax.p(s.width/2, s.height/5 * 2.0) ) + label2:setAnchorPoint( ax.p(0.5, 0.5) ) + label2:setTextColor( ax.color32(255, 0, 0, 255) ) - local label3 = cc.Label:createWithTTF(ttfConfig, "Blue", cc.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) + local label3 = ax.Label:createWithTTF(ttfConfig, "Blue", ax.VERTICAL_TEXT_ALIGNMENT_CENTER, s.width) layer:addChild(label3) - label3:setPosition( cc.p(s.width/2, s.height/5 * 2.5) ) - label3:setAnchorPoint( cc.p(0.5, 0.5) ) - label3:setTextColor( cc.c4b(0, 0, 255, 255)) + label3:setPosition( ax.p(s.width/2, s.height/5 * 2.5) ) + label3:setAnchorPoint( ax.p(0.5, 0.5) ) + label3:setTextColor( ax.color32(0, 0, 255, 255)) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString("Uses the new Label with TTF. Testing Color") @@ -339,7 +339,7 @@ end local LabelFNTHundredLabels = { layer = nil } function LabelFNTHundredLabels:create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelFNTHundredLabels.layer = layer @@ -348,14 +348,14 @@ function LabelFNTHundredLabels:create() local i = 0 for i = 0, 100, 1 do local str = string.format("-%d-", i) - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt", str) + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt", str) layer:addChild(label) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local p = cc.p( math.random() * s.width, math.random() * s.height) + local p = ax.p( math.random() * s.width, math.random() * s.height) label:setPosition( p ) - label:setAnchorPoint(cc.p(0.5, 0.5)) + label:setAnchorPoint(ax.p(0.5, 0.5)) end Helper.titleLabel:setString("New Label + .FNT file") @@ -372,13 +372,13 @@ end local LabelFNTMultiLine = {} function LabelFNTMultiLine:create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local s = nil -- Left - local label1 = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", " Multi line\nLeft") - label1:setAnchorPoint(cc.p(0,0)) + local label1 = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", " Multi line\nLeft") + label1:setAnchorPoint(ax.p(0,0)) layer:addChild(label1, 0, kTagBitmapAtlas1) s = label1:getContentSize() @@ -386,16 +386,16 @@ function LabelFNTMultiLine:create() -- Center - local label2 = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Multi line\nCenter") - label2:setAnchorPoint(cc.p(0.5, 0.5)) + local label2 = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Multi line\nCenter") + label2:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(label2, 0, kTagBitmapAtlas2) s= label2:getContentSize() cclog("content size: %.2fx%.2f", s.width, s.height) -- right - local label3 = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Multi line\nRight\nThree lines Three") - label3:setAnchorPoint(cc.p(1, 1)) + local label3 = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Multi line\nRight\nThree lines Three") + label3:setAnchorPoint(ax.p(1, 1)) layer:addChild(label3, 0, kTagBitmapAtlas3) s = label3:getContentSize() @@ -432,25 +432,25 @@ end function LabelFNTandTTFEmpty.create() cclog("LabelFNTandTTFEmpty.create") - local layer = cc.Layer:create() + local layer = ax.Layer:create() LabelFNTandTTFEmpty.layer = layer Helper.initWithLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - -- cc.LabelBMFont - local label1 = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "", cc.TEXT_ALIGNMENT_CENTER,s.width) + -- ax.LabelBMFont + local label1 = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "", ax.TEXT_ALIGNMENT_CENTER,s.width) layer:addChild(label1, 0, kTagBitmapAtlas1) - label1:setPosition(cc.p(s.width/2, s.height-100)) + label1:setPosition(ax.p(s.width/2, s.height-100)) - -- cc.LabelTTF + -- ax.LabelTTF local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 24 - local label2 = cc.Label:createWithTTF(ttfConfig, "", cc.TEXT_ALIGNMENT_CENTER, s.width) + local label2 = ax.Label:createWithTTF(ttfConfig, "", ax.TEXT_ALIGNMENT_CENTER, s.width) layer:addChild(label2, 0, kTagBitmapAtlas2) - label2:setAnchorPoint(cc.p(0.5, 0.5)) - label2:setPosition(cc.p(s.width/2, s.height/2)) + label2:setAnchorPoint(ax.p(0.5, 0.5)) + label2:setPosition(ax.p(s.width/2, s.height/2)) layer:registerScriptHandler(LabelFNTandTTFEmpty.onNodeEvent) @@ -481,20 +481,20 @@ end -- -------------------------------------------------------------------- local LabelFNTRetina = { - + } function LabelFNTRetina.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - -- cc.LabelBMFont - local label1 = cc.Label:createWithBMFont("fonts/konqa32.fnt", "TESTING RETINA DISPLAY") - label1:setAnchorPoint(cc.p(0.5,0.5)) + -- ax.LabelBMFont + local label1 = ax.Label:createWithBMFont("fonts/konqa32.fnt", "TESTING RETINA DISPLAY") + label1:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label1) - label1:setPosition(cc.p(s.width/2, s.height/2)) + label1:setPosition(ax.p(s.width/2, s.height/2)) Helper.titleLabel:setString("New Label + .FNT file") Helper.subtitleLabel:setString("loading arista16 or arista16-hd") @@ -508,16 +508,16 @@ end -------------------------------------------------------------------- local LabelFNTGlyphDesigner = {} function LabelFNTGlyphDesigner.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local label1 = cc.Label:createWithBMFont("fonts/futura-48.fnt", "TESTING RETINA DISPLAY") - label1:setAnchorPoint(cc.p(0.5, 0.5)) + local label1 = ax.Label:createWithBMFont("fonts/futura-48.fnt", "TESTING RETINA DISPLAY") + label1:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(label1) - label1:setPosition(cc.p(s.width/2, s.height/2)) + label1:setPosition(ax.p(s.width/2, s.height/2)) Helper.titleLabel:setString("New Label + .FNT file") Helper.subtitleLabel:setString("Testing Glyph Designer: you should see a font with shadows and outline") @@ -527,22 +527,22 @@ end --/ LabelTTFUnicodeChinese local LabelTTFUnicodeChinese = {} function LabelTTFUnicodeChinese.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF file Chinese") Helper.subtitleLabel:setString("Testing new Label + TTF with Chinese character") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath="fonts/HKYuanMini.ttf" ttfConfig.fontSize=28 - ttfConfig.glyphs=cc.GLYPHCOLLECTION_CUSTOM + ttfConfig.glyphs=ax.GLYPHCOLLECTION_CUSTOM ttfConfig.customGlyphs="美好的一天啊" - local label1 = cc.Label:createWithTTF(ttfConfig,"美好的一天啊", cc.TEXT_ALIGNMENT_CENTER, s.width) - label1:setAnchorPoint(cc.p(0.5,0.5)) + local label1 = ax.Label:createWithTTF(ttfConfig,"美好的一天啊", ax.TEXT_ALIGNMENT_CENTER, s.width) + label1:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label1) - label1:setPosition(cc.p(s.width/2, s.height/2)) + label1:setPosition(ax.p(s.width/2, s.height/2)) return layer end @@ -553,13 +553,13 @@ end local LabelFNTUnicodeChinese = {} function LabelFNTUnicodeChinese.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local size = cc.Director:getInstance():getWinSize() - local lable = cc.Label:createWithBMFont("fonts/bitmapFontChinese.fnt", "中国") - lable:setAnchorPoint(cc.p(0.5,0.5)) - lable:setPosition(cc.p(size.width / 2, size.height /2)) + local size = ax.Director:getInstance():getWinSize() + local lable = ax.Label:createWithBMFont("fonts/bitmapFontChinese.fnt", "中国") + lable:setAnchorPoint(ax.p(0.5,0.5)) + lable:setPosition(ax.p(size.width / 2, size.height /2)) layer:addChild(lable) Helper.titleLabel:setString("New Label + .FNT file Chinese") @@ -597,65 +597,65 @@ local LabelFNTMultiLineAlignment = { } function LabelFNTMultiLineAlignment.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) -- ask director the the window size - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() -- create and initialize a Label - LabelFNTMultiLineAlignment._pLabelShouldRetain = cc.Label:createWithBMFont("fonts/markerFelt.fnt", LongSentencesExample, cc.TEXT_ALIGNMENT_CENTER, size.width/1.5) - LabelFNTMultiLineAlignment._pLabelShouldRetain:setAnchorPoint(cc.p(0.5, 0.5)) + LabelFNTMultiLineAlignment._pLabelShouldRetain = ax.Label:createWithBMFont("fonts/markerFelt.fnt", LongSentencesExample, ax.TEXT_ALIGNMENT_CENTER, size.width/1.5) + LabelFNTMultiLineAlignment._pLabelShouldRetain:setAnchorPoint(ax.p(0.5, 0.5)) LabelFNTMultiLineAlignment._pLabelShouldRetain:retain() - LabelFNTMultiLineAlignment._pArrowsBarShouldRetain = cc.Sprite:create("Images/arrowsBar.png") + LabelFNTMultiLineAlignment._pArrowsBarShouldRetain = ax.Sprite:create("Images/arrowsBar.png") LabelFNTMultiLineAlignment._pArrowsBarShouldRetain:retain() - LabelFNTMultiLineAlignment._pArrowsShouldRetain = cc.Sprite:create("Images/arrows.png") + LabelFNTMultiLineAlignment._pArrowsShouldRetain = ax.Sprite:create("Images/arrows.png") LabelFNTMultiLineAlignment._pArrowsShouldRetain:retain() - cc.MenuItemFont:setFontSize(20) - local longSentences = cc.MenuItemFont:create("Long Flowing Sentences") + ax.MenuItemFont:setFontSize(20) + local longSentences = ax.MenuItemFont:create("Long Flowing Sentences") longSentences:registerScriptTapHandler(LabelFNTMultiLineAlignment.stringChanged) - local lineBreaks = cc.MenuItemFont:create("Short Sentences With Intentional Line Breaks") + local lineBreaks = ax.MenuItemFont:create("Short Sentences With Intentional Line Breaks") lineBreaks:registerScriptTapHandler(LabelFNTMultiLineAlignment.stringChanged) - local mixed = cc.MenuItemFont:create("Long Sentences Mixed With Intentional Line Breaks") + local mixed = ax.MenuItemFont:create("Long Sentences Mixed With Intentional Line Breaks") mixed:registerScriptTapHandler(LabelFNTMultiLineAlignment.stringChanged) - local stringMenu = cc.Menu:create() + local stringMenu = ax.Menu:create() stringMenu:addChild(longSentences) stringMenu:addChild(lineBreaks) stringMenu:addChild(mixed) stringMenu:alignItemsVertically() - longSentences:setColor(cc.c3b(255, 0, 0)) + longSentences:setColor(ax.color32(255, 0, 0)) LabelFNTMultiLineAlignment._pLastSentenceItem = longSentences longSentences:setTag(LongSentences) lineBreaks:setTag(LineBreaks) mixed:setTag(Mixed) - cc.MenuItemFont:setFontSize(30) + ax.MenuItemFont:setFontSize(30) - local left = cc.MenuItemFont:create("Left") + local left = ax.MenuItemFont:create("Left") left:registerScriptTapHandler(LabelFNTMultiLineAlignment.alignmentChanged) - local center = cc.MenuItemFont:create("Center") + local center = ax.MenuItemFont:create("Center") center:registerScriptTapHandler(LabelFNTMultiLineAlignment.alignmentChanged) - local right = cc.MenuItemFont:create("Right") + local right = ax.MenuItemFont:create("Right") right:registerScriptTapHandler(LabelFNTMultiLineAlignment.alignmentChanged) - local alignmentMenu = cc.Menu:create() + local alignmentMenu = ax.Menu:create() alignmentMenu:addChild(left) alignmentMenu:addChild(center) alignmentMenu:addChild(right) alignmentMenu:alignItemsHorizontallyWithPadding(alignmentItemPadding) - center:setColor(cc.c3b(255, 0, 0)) + center:setColor(ax.color32(255, 0, 0)) LabelFNTMultiLineAlignment._pLastAlignmentItem = center left:setTag(LeftAlign) center:setTag(CenterAlign) right:setTag(RightAlign) -- position the label on the center of the screen - LabelFNTMultiLineAlignment._pLabelShouldRetain:setPosition(cc.p(size.width/2, size.height/2)) + LabelFNTMultiLineAlignment._pLabelShouldRetain:setPosition(ax.p(size.width/2, size.height/2)) LabelFNTMultiLineAlignment._pArrowsBarShouldRetain:setVisible(false) @@ -665,8 +665,8 @@ function LabelFNTMultiLineAlignment.create() LabelFNTMultiLineAlignment.snapArrowsToEdge() - stringMenu:setPosition(cc.p(size.width/2, size.height - menuItemPaddingCenter)) - alignmentMenu:setPosition(cc.p(size.width/2, menuItemPaddingCenter+15)) + stringMenu:setPosition(ax.p(size.width/2, size.height - menuItemPaddingCenter)) + alignmentMenu:setPosition(ax.p(size.width/2, menuItemPaddingCenter+15)) layer:addChild(LabelFNTMultiLineAlignment._pLabelShouldRetain) layer:addChild(LabelFNTMultiLineAlignment._pArrowsBarShouldRetain) @@ -677,7 +677,7 @@ function LabelFNTMultiLineAlignment.create() local function onTouchesBegan(touches, event) local location = touches[1]:getLocationInView() - if cc.rectContainsPoint(LabelFNTMultiLineAlignment._pArrowsShouldRetain:getBoundingBox(), cc.p(location.x, location.y)) then + if ax.rectContainsPoint(LabelFNTMultiLineAlignment._pArrowsShouldRetain:getBoundingBox(), ax.p(location.x, location.y)) then LabelFNTMultiLineAlignment._drag = true LabelFNTMultiLineAlignment._pArrowsBarShouldRetain:setVisible(true) end @@ -688,11 +688,11 @@ function LabelFNTMultiLineAlignment.create() return end - local winSize = cc.Director:getInstance():getWinSize() + local winSize = ax.Director:getInstance():getWinSize() local location = touches[1]:getLocationInView() LabelFNTMultiLineAlignment._pArrowsShouldRetain:setPosition( - math.max(math.min(location.x, ArrowsMax*winSize.width), ArrowsMin*winSize.width), + math.max(math.min(location.x, ArrowsMax*winSize.width), ArrowsMin*winSize.width), LabelFNTMultiLineAlignment._pArrowsShouldRetain:getPositionY()) local labelWidth = math.abs(LabelFNTMultiLineAlignment._pArrowsShouldRetain:getPositionX() - LabelFNTMultiLineAlignment._pLabelShouldRetain:getPositionX()) * 2 @@ -706,10 +706,10 @@ function LabelFNTMultiLineAlignment.create() LabelFNTMultiLineAlignment._pArrowsBarShouldRetain:setVisible(false) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) - listener:registerScriptHandler(onTouchesEnded,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) + listener:registerScriptHandler(onTouchesEnded,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -729,8 +729,8 @@ end function LabelFNTMultiLineAlignment.stringChanged(tag, sender) local item = sender - item:setColor(cc.c3b(255, 0, 0)) - LabelFNTMultiLineAlignment._pLastAlignmentItem:setColor(cc.c3b(255, 255, 255)) + item:setColor(ax.color32(255, 0, 0)) + LabelFNTMultiLineAlignment._pLastAlignmentItem:setColor(ax.color32(255, 255, 255)) LabelFNTMultiLineAlignment._pLastAlignmentItem = item if item:getTag() == LongSentences then @@ -747,17 +747,17 @@ end function LabelFNTMultiLineAlignment.alignmentChanged(tag, sender) -- cclog("LabelFNTMultiLineAlignment.alignmentChanged, tag:"..tag) local item = sender - item:setColor(cc.c3b(255, 0, 0)) - LabelFNTMultiLineAlignment._pLastAlignmentItem:setColor(cc.c3b(255, 255, 255)) + item:setColor(ax.color32(255, 0, 0)) + LabelFNTMultiLineAlignment._pLastAlignmentItem:setColor(ax.color32(255, 255, 255)) LabelFNTMultiLineAlignment._pLastAlignmentItem = item if tag == LeftAlign then cclog("LeftAlign") - LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(cc.TEXT_ALIGNMENT_LEFT) + LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(ax.TEXT_ALIGNMENT_LEFT) elseif tag == CenterAlign then - LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(cc.TEXT_ALIGNMENT_CENTER) + LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(ax.TEXT_ALIGNMENT_CENTER) elseif tag == RightAlign then - LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(cc.TEXT_ALIGNMENT_RIGHT) + LabelFNTMultiLineAlignment._pLabelShouldRetain:setAlignment(ax.TEXT_ALIGNMENT_RIGHT) end LabelFNTMultiLineAlignment.snapArrowsToEdge() @@ -774,27 +774,27 @@ end ------------------------------------ local LabelFNTUNICODELanguages = {} function LabelFNTUNICODELanguages.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .FNT + UNICODE") Helper.subtitleLabel:setString("You should see 3 different labels:\nIn Spanish, Chinese, and Japanese") - local s = cc.Director:getInstance():getWinSize() - - local label1 = cc.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "Buen día", cc.TEXT_ALIGNMENT_CENTER, 200) - label1:setAnchorPoint(cc.p(0.5,0.5)) + local s = ax.Director:getInstance():getWinSize() + + local label1 = ax.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "Buen día", ax.TEXT_ALIGNMENT_CENTER, 200) + label1:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label1) - label1:setPosition(cc.p(s.width/2, s.height/4*3)) - - local label2 = cc.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "美好的一天") - label2:setAnchorPoint(cc.p(0.5,0.5)) + label1:setPosition(ax.p(s.width/2, s.height/4*3)) + + local label2 = ax.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "美好的一天") + label2:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label2) - label2:setPosition(cc.p(s.width/2, s.height/4*2)) - - local label3 = cc.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "良い一日を") - label3:setAnchorPoint(cc.p(0.5,0.5)) + label2:setPosition(ax.p(s.width/2, s.height/4*2)) + + local label3 = ax.Label:createWithBMFont("fonts/arial-unicode-26.fnt", "良い一日を") + label3:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label3) - label3:setPosition(cc.p(s.width/2, s.height/4*1)) + label3:setPosition(ax.p(s.width/2, s.height/4*1)) return layer end @@ -804,28 +804,28 @@ end ---------------------------------------------------------- local LabelTTFAlignmentNew = {} function LabelTTFAlignmentNew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + TTF") Helper.subtitleLabel:setString("Tests alignment values") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath="fonts/tahoma.ttf" ttfConfig.fontSize=16 - local ttf0 = cc.Label:createWithTTF(ttfConfig, "Alignment 0\nnew line", cc.TEXT_ALIGNMENT_LEFT) - ttf0:setPosition(cc.p(s.width/2,(s.height/6)*2 - 30)) - ttf0:setAnchorPoint(cc.p(0.5,0.5)) + local ttf0 = ax.Label:createWithTTF(ttfConfig, "Alignment 0\nnew line", ax.TEXT_ALIGNMENT_LEFT) + ttf0:setPosition(ax.p(s.width/2,(s.height/6)*2 - 30)) + ttf0:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(ttf0) - - local ttf1 = cc.Label:createWithTTF(ttfConfig, "Alignment 1\nnew line", cc.TEXT_ALIGNMENT_CENTER) - ttf1:setPosition(cc.p(s.width/2,(s.height/6)*3 - 30)) - ttf1:setAnchorPoint(cc.p(0.5,0.5)) + + local ttf1 = ax.Label:createWithTTF(ttfConfig, "Alignment 1\nnew line", ax.TEXT_ALIGNMENT_CENTER) + ttf1:setPosition(ax.p(s.width/2,(s.height/6)*3 - 30)) + ttf1:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(ttf1) - - local ttf2 = cc.Label:createWithTTF(ttfConfig, "Alignment 2\nnew line", cc.TEXT_ALIGNMENT_RIGHT) - ttf2:setPosition(cc.p(s.width/2,(s.height/6)*4 - 30)) - ttf2:setAnchorPoint(cc.p(0.5,0.5)) + + local ttf2 = ax.Label:createWithTTF(ttfConfig, "Alignment 2\nnew line", ax.TEXT_ALIGNMENT_RIGHT) + ttf2:setPosition(ax.p(s.width/2,(s.height/6)*4 - 30)) + ttf2:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(ttf2) return layer @@ -837,37 +837,37 @@ end ------------------------------------- local LabelTTFUnicodeNew = {} function LabelTTFUnicodeNew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + TTF unicode") Helper.subtitleLabel:setString("Uses the new Label with TTF. Testing unicode") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local vStep = s.height/9 local vSize = s.height local ttfConfig = {} ttfConfig.fontFilePath="fonts/arial.ttf" ttfConfig.fontSize=23 - ttfConfig.glyphs=cc.GLYPHCOLLECTION_ASCII - - local label1 = cc.Label:createWithTTF(ttfConfig,"Buen día, ¿cómo te llamas?", cc.TEXT_ALIGNMENT_CENTER, s.width) - label1:setAnchorPoint(cc.p(0.5,0.5)) - label1:setPosition(cc.p(s.width/2, vSize - vStep * 4.5)) + ttfConfig.glyphs=ax.GLYPHCOLLECTION_ASCII + + local label1 = ax.Label:createWithTTF(ttfConfig,"Buen día, ¿cómo te llamas?", ax.TEXT_ALIGNMENT_CENTER, s.width) + label1:setAnchorPoint(ax.p(0.5,0.5)) + label1:setPosition(ax.p(s.width/2, vSize - vStep * 4.5)) layer:addChild(label1) - - local label2 = cc.Label:createWithTTF(ttfConfig, "In welcher Straße haben Sie gelebt?", cc.TEXT_ALIGNMENT_CENTER, s.width) - label2:setAnchorPoint(cc.p(0.5,0.5)) + + local label2 = ax.Label:createWithTTF(ttfConfig, "In welcher Straße haben Sie gelebt?", ax.TEXT_ALIGNMENT_CENTER, s.width) + label2:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label2) - label2:setPosition(cc.p(s.width/2, vSize - vStep * 5.5)) - + label2:setPosition(ax.p(s.width/2, vSize - vStep * 5.5)) + ttfConfig.fontFilePath = "fonts/HKYuanMini.ttf" - ttfConfig.glyphs = cc.GLYPHCOLLECTION_CUSTOM + ttfConfig.glyphs = ax.GLYPHCOLLECTION_CUSTOM ttfConfig.customGlyphs = "美好的一天" - local label3 = cc.Label:createWithTTF(ttfConfig, "美好的一天", cc.TEXT_ALIGNMENT_CENTER, s.width) - label3:setAnchorPoint(cc.p(0.5,0.5)) + local label3 = ax.Label:createWithTTF(ttfConfig, "美好的一天", ax.TEXT_ALIGNMENT_CENTER, s.width) + label3:setAnchorPoint(ax.p(0.5,0.5)) layer:addChild(label3) - label3:setPosition(cc.p(s.width/2, vSize - vStep * 6.5)) + label3:setPosition(ax.p(s.width/2, vSize - vStep * 6.5)) return layer end @@ -880,38 +880,38 @@ end ---------------------------------- local LabelFNTBounds = {} function LabelFNTBounds.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .FNT + Bounds") Helper.subtitleLabel:setString("You should see string enclosed by a box") - - local s = cc.Director:getInstance():getWinSize() - - local colorlayer = cc.LayerColor:create(cc.c4b(128,128,128,255)) + + local s = ax.Director:getInstance():getWinSize() + + local colorlayer = ax.LayerColor:create(ax.color32(128,128,128,255)) layer:addChild(colorlayer, -10) - - -- cc.LabelBMFont - local label1 = cc.Label:createWithBMFont("fonts/boundsTestFont.fnt", "Testing Glyph Designer", cc.TEXT_ALIGNMENT_CENTER, s.width) - label1:setAnchorPoint(cc.p(0.5, 0.5)) - + + -- ax.LabelBMFont + local label1 = ax.Label:createWithBMFont("fonts/boundsTestFont.fnt", "Testing Glyph Designer", ax.TEXT_ALIGNMENT_CENTER, s.width) + label1:setAnchorPoint(ax.p(0.5, 0.5)) + layer:addChild(label1) - label1:setPosition(cc.p(s.width/2, s.height/2)) + label1:setPosition(ax.p(s.width/2, s.height/2)) return layer end function LabelFNTBounds.draw() - -- cc.size labelSize = label1:getContentSize() - -- cc.size origin = cc.Director:getInstance():getWinSize() - + -- ax.size labelSize = label1:getContentSize() + -- ax.size origin = ax.Director:getInstance():getWinSize() + -- origin.width = origin.width / 2 - (labelSize.width / 2) -- origin.height = origin.height / 2 - (labelSize.height / 2) - - -- cc.p vertices[4]= - - -- cc.p(origin.width, origin.height), - -- cc.p(labelSize.width + origin.width, origin.height), - -- cc.p(labelSize.width + origin.width, labelSize.height + origin.height), - -- cc.p(origin.width, labelSize.height + origin.height) + + -- ax.p vertices[4]= + + -- ax.p(origin.width, origin.height), + -- ax.p(labelSize.width + origin.width, origin.height), + -- ax.p(labelSize.width + origin.width, labelSize.height + origin.height), + -- ax.p(origin.width, labelSize.height + origin.height) -- end -- ccDrawPoly(vertices, 4, true) end @@ -922,18 +922,18 @@ end -------------------------------------------------------- local LabelTTFLongLineWrapping = {} function LabelTTFLongLineWrapping.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString("Uses the new Label with TTF. Testing auto-wrapping") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 14 - local label1 = cc.Label:createWithTTF(ttfConfig, LongSentencesExample, cc.TEXT_ALIGNMENT_LEFT, s.width) - label1:setAnchorPoint(cc.p(0.5,1.0)) - label1:setPosition(cc.p(s.width/2, s.height/2)) + local label1 = ax.Label:createWithTTF(ttfConfig, LongSentencesExample, ax.TEXT_ALIGNMENT_LEFT, s.width) + label1:setAnchorPoint(ax.p(0.5,1.0)) + label1:setPosition(ax.p(s.width/2, s.height/2)) layer:addChild(label1) return layer end @@ -947,39 +947,39 @@ end local LabelTTFDynamicAlignment = { _layer = nil, _label = nil, - _eHorizAlign = cc.TEXT_ALIGNMENT_LEFT, + _eHorizAlign = ax.TEXT_ALIGNMENT_LEFT, } function LabelTTFDynamicAlignment.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) LabelTTFDynamicAlignment._layer = layer LabelTTFDynamicAlignment._label = nil - LabelTTFDynamicAlignment._eHorizAlign = cc.TEXT_ALIGNMENT_LEFT + LabelTTFDynamicAlignment._eHorizAlign = ax.TEXT_ALIGNMENT_LEFT - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 23 - LabelTTFDynamicAlignment._label = cc.Label:createWithTTF(ttfConfig, LongSentencesExample, cc.TEXT_ALIGNMENT_CENTER, s.width) - LabelTTFDynamicAlignment._label:setPosition( cc.p(s.width/2, s.height/2) ) - LabelTTFDynamicAlignment._label:setAnchorPoint(cc.p(0.5, 0.5)) + LabelTTFDynamicAlignment._label = ax.Label:createWithTTF(ttfConfig, LongSentencesExample, ax.TEXT_ALIGNMENT_CENTER, s.width) + LabelTTFDynamicAlignment._label:setPosition( ax.p(s.width/2, s.height/2) ) + LabelTTFDynamicAlignment._label:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(LabelTTFDynamicAlignment._label) - cc.MenuItemFont:setFontSize(30) - local item1 = cc.MenuItemFont:create("Left") + ax.MenuItemFont:setFontSize(30) + local item1 = ax.MenuItemFont:create("Left") item1:registerScriptTapHandler(LabelTTFDynamicAlignment.setAlignmentLeft) - local item2 = cc.MenuItemFont:create("Center") + local item2 = ax.MenuItemFont:create("Center") item2:registerScriptTapHandler(LabelTTFDynamicAlignment.setAlignmentCenter) - local item3 = cc.MenuItemFont:create("Right") + local item3 = ax.MenuItemFont:create("Right") item3:registerScriptTapHandler(LabelTTFDynamicAlignment.setAlignmentRight) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) menu:alignItemsVerticallyWithPadding(4) - menu:setPosition(cc.p(50, s.height / 4)) + menu:setPosition(ax.p(50, s.height / 4)) layer:addChild(menu) Helper.titleLabel:setString("New Label + .TTF") @@ -991,22 +991,22 @@ function LabelTTFDynamicAlignment.create() end function LabelTTFDynamicAlignment.updateAlignment() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() LabelTTFDynamicAlignment._label:setAlignment(LabelTTFDynamicAlignment._eHorizAlign) end function LabelTTFDynamicAlignment.setAlignmentLeft(pSender) - LabelTTFDynamicAlignment._eHorizAlign = cc.TEXT_ALIGNMENT_LEFT + LabelTTFDynamicAlignment._eHorizAlign = ax.TEXT_ALIGNMENT_LEFT LabelTTFDynamicAlignment.updateAlignment() end function LabelTTFDynamicAlignment.setAlignmentCenter(pSender) - LabelTTFDynamicAlignment._eHorizAlign = cc.TEXT_ALIGNMENT_CENTER + LabelTTFDynamicAlignment._eHorizAlign = ax.TEXT_ALIGNMENT_CENTER LabelTTFDynamicAlignment.updateAlignment() end function LabelTTFDynamicAlignment.setAlignmentRight(pSender) - LabelTTFDynamicAlignment._eHorizAlign = cc.TEXT_ALIGNMENT_RIGHT + LabelTTFDynamicAlignment._eHorizAlign = ax.TEXT_ALIGNMENT_RIGHT LabelTTFDynamicAlignment.updateAlignment() end @@ -1016,53 +1016,53 @@ end -------------------------------------------------------- local LabelTTFCJKWrappingTest = {} function LabelTTFCJKWrappingTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString( "New Label with CJK + ASCII characters\n" .. "Characters should stay in the correct position") - local size = cc.Director:getInstance():getVisibleSize() + local size = ax.Director:getInstance():getVisibleSize() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/HKYuanMini.ttf" ttfConfig.fontSize = 25 - ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC + ttfConfig.glyphs = ax.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = false - - local drawNode = cc.DrawNode:create() - drawNode:setAnchorPoint(cc.p(0, 0)) + + local drawNode = ax.DrawNode:create() + drawNode:setAnchorPoint(ax.p(0, 0)) layer:addChild(drawNode) drawNode:drawSegment( - cc.p(size.width * 0.1, size.height * 0.8), - cc.p(size.width * 0.1, 0), 1, cc.c4f(1, 0, 0, 1)) + ax.p(size.width * 0.1, size.height * 0.8), + ax.p(size.width * 0.1, 0), 1, ax.color(1, 0, 0, 1)) drawNode:drawSegment( - cc.p(size.width * 0.85, size.height * 0.8), - cc.p(size.width * 0.85, 0), 1, cc.c4f(1, 0, 0, 1)) - - local label1 = cc.Label:createWithTTF( + ax.p(size.width * 0.85, size.height * 0.8), + ax.p(size.width * 0.85, 0), 1, ax.color(1, 0, 0, 1)) + + local label1 = ax.Label:createWithTTF( ttfConfig, "你好,Axmol Label。", - cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75) - label1:setTextColor(cc.c4b(128, 255, 255, 255)) - label1:setPosition(cc.p(size.width * 0.1, size.height * 0.6)) - label1:setAnchorPoint(cc.p(0, 0.5)) + ax.TEXT_ALIGNMENT_LEFT, size.width * 0.75) + label1:setTextColor(ax.color32(128, 255, 255, 255)) + label1:setPosition(ax.p(size.width * 0.1, size.height * 0.6)) + label1:setAnchorPoint(ax.p(0, 0.5)) layer:addChild(label1) - - local label2 = cc.Label:createWithTTF( + + local label2 = ax.Label:createWithTTF( ttfConfig, "早上好,Axmol Label。", - cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75) - label2:setTextColor(cc.c4b(255, 128, 255, 255)) - label2:setPosition(cc.p(size.width * 0.1, size.height * 0.4)) - label2:setAnchorPoint(cc.p(0, 0.5)) + ax.TEXT_ALIGNMENT_LEFT, size.width * 0.75) + label2:setTextColor(ax.color32(255, 128, 255, 255)) + label2:setPosition(ax.p(size.width * 0.1, size.height * 0.4)) + label2:setAnchorPoint(ax.p(0, 0.5)) layer:addChild(label2) - - local label3 = cc.Label:createWithTTF( + + local label3 = ax.Label:createWithTTF( ttfConfig, "美好的一天啊美好的一天啊美好的一天啊", - cc.TEXT_ALIGNMENT_LEFT, size.width * 0.75) - label3:setColor(cc.c4b(255, 255, 128, 255)) - label3:setPosition(cc.p(size.width * 0.1, size.height * 0.2)) - label3:setAnchorPoint(cc.p(0, 0.5)) + ax.TEXT_ALIGNMENT_LEFT, size.width * 0.75) + label3:setColor(ax.color32(255, 255, 128, 255)) + label3:setPosition(ax.p(size.width * 0.1, size.height * 0.2)) + label3:setAnchorPoint(ax.p(0, 0.5)) layer:addChild(label3) return layer @@ -1074,14 +1074,14 @@ end -------------------------------------------------------- local LabelTTFFontsTestNew = {} function LabelTTFFontsTestNew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + TTF") Helper.subtitleLabel:setString("") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local ttfPaths = + local ttfPaths = { "fonts/A Damn Mess.ttf", "fonts/Abberancy.ttf", @@ -1096,17 +1096,17 @@ function LabelTTFFontsTestNew.create() ttfConfig.fontSize = 20 for i=1, #(ttfPaths) do ttfConfig.fontFilePath = ttfPaths[i] - local label = cc.Label:createWithTTF( ttfConfig, ttfPaths[i], cc.TEXT_ALIGNMENT_CENTER, 0) + local label = ax.Label:createWithTTF( ttfConfig, ttfPaths[i], ax.TEXT_ALIGNMENT_CENTER, 0) if nil ~= label then - label:setPosition( cc.p(s.width/2, ((s.height * 0.6)/#(ttfPaths) * (i -1)) + (s.height/5))) + label:setPosition( ax.p(s.width/2, ((s.height * 0.6)/#(ttfPaths) * (i -1)) + (s.height/5))) layer:addChild(label) - - label:setAnchorPoint(cc.p(0.5, 0.5)) + + label:setAnchorPoint(ax.p(0.5, 0.5)) else print(string.format("ERROR: Cannot load: %s",ttfPaths[i])) end end - + return layer end @@ -1116,16 +1116,16 @@ end -------------------------------------------------------- local LabelBMFontTestNew = {} function LabelBMFontTestNew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + FNT") Helper.subtitleLabel:setString("Uses the new Label with .FNT file") - local s = cc.Director:getInstance():getWinSize() - - local label1 = cc.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Hello World, this is testing the new Label using fnt file", cc.TEXT_ALIGNMENT_CENTER, s.width) - label1:setAnchorPoint(cc.p(0.5,0.5)) - label1:setPosition(cc.p(s.width/2, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + + local label1 = ax.Label:createWithBMFont("fonts/bitmapFontTest2.fnt", "Hello World, this is testing the new Label using fnt file", ax.TEXT_ALIGNMENT_CENTER, s.width) + label1:setAnchorPoint(ax.p(0.5,0.5)) + label1:setPosition(ax.p(s.width/2, s.height/2)) layer:addChild(label1) return layer end @@ -1136,33 +1136,33 @@ end -------------------------------------------------------- local LabelTTFDistanceField = {} function LabelTTFDistanceField.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString("Testing rendering base on DistanceField") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC + ttfConfig.glyphs = ax.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = true - - local label1 = cc.Label:createWithTTF(ttfConfig,"Distance Field",cc.TEXT_ALIGNMENT_CENTER,s.width) - label1:setAnchorPoint(cc.p(0.5,0.5)) - label1:setPosition(cc.p(s.width/2, s.height/2)) - label1:setTextColor( cc.c4b(0, 255, 0, 255) ) - local action = cc.Sequence:create(cc.DelayTime:create(1.0), - cc.ScaleTo:create(6.0,5.0,5.0), - cc.ScaleTo:create(6.0,1.0,1.0)) - label1:runAction(cc.RepeatForever:create(action)) + + local label1 = ax.Label:createWithTTF(ttfConfig,"Distance Field",ax.TEXT_ALIGNMENT_CENTER,s.width) + label1:setAnchorPoint(ax.p(0.5,0.5)) + label1:setPosition(ax.p(s.width/2, s.height/2)) + label1:setTextColor( ax.color32(0, 255, 0, 255) ) + local action = ax.Sequence:create(ax.DelayTime:create(1.0), + ax.ScaleTo:create(6.0,5.0,5.0), + ax.ScaleTo:create(6.0,1.0,1.0)) + label1:runAction(ax.RepeatForever:create(action)) layer:addChild(label1) - local label2 = cc.Label:createWithTTF(ttfConfig,"Distance Field",cc.TEXT_ALIGNMENT_CENTER,s.width) - label2:setPosition( cc.p(s.width/2, s.height/5) ) - label2:setTextColor( cc.c4b(255, 0, 0, 255)) - label2:setAnchorPoint(cc.p(0.5, 0.5)) + local label2 = ax.Label:createWithTTF(ttfConfig,"Distance Field",ax.TEXT_ALIGNMENT_CENTER,s.width) + label2:setPosition( ax.p(s.width/2, s.height/5) ) + label2:setTextColor( ax.color32(255, 0, 0, 255)) + label2:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(label2) return layer @@ -1173,45 +1173,45 @@ end -------------------------------------------------------- local LabelOutlineAndGlowTest = {} function LabelOutlineAndGlowTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString("Testing outline and glow of label") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local col = cc.LayerColor:create( cc.c4b(200, 191, 231, 255)) + local col = ax.LayerColor:create( ax.color32(200, 191, 231, 255)) layer:addChild(col) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC + ttfConfig.glyphs = ax.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = true ttfConfig.outlineSize = 0 - - local label1 = cc.Label:createWithTTF(ttfConfig,"Glow",cc.TEXT_ALIGNMENT_CENTER,s.width) - label1:setAnchorPoint(cc.p(0.5,0.5)) - label1:setPosition(cc.p(s.width/2, s.height * 0.7)) - label1:setTextColor( cc.c4b(0, 255, 0, 255) ) - label1:enableGlow(cc.c4b(255, 255, 0, 255)) + + local label1 = ax.Label:createWithTTF(ttfConfig,"Glow",ax.TEXT_ALIGNMENT_CENTER,s.width) + label1:setAnchorPoint(ax.p(0.5,0.5)) + label1:setPosition(ax.p(s.width/2, s.height * 0.7)) + label1:setTextColor( ax.color32(0, 255, 0, 255) ) + label1:enableGlow(ax.color32(255, 255, 0, 255)) layer:addChild(label1) ttfConfig.outlineSize = 1 - local label2 = cc.Label:createWithTTF(ttfConfig,"Outline",cc.TEXT_ALIGNMENT_CENTER,s.width) - label2:setPosition( cc.p(s.width/2, s.height * 0.6)) - label2:setTextColor( cc.c4b(255, 0, 0, 255)) - label2:setAnchorPoint(cc.p(0.5, 0.5)) - label2:enableOutline(cc.c4b(0,0,255,255)) + local label2 = ax.Label:createWithTTF(ttfConfig,"Outline",ax.TEXT_ALIGNMENT_CENTER,s.width) + label2:setPosition( ax.p(s.width/2, s.height * 0.6)) + label2:setTextColor( ax.color32(255, 0, 0, 255)) + label2:setAnchorPoint(ax.p(0.5, 0.5)) + label2:enableOutline(ax.color32(0,0,255,255)) layer:addChild(label2) ttfConfig.outlineSize = 2 - local label3 = cc.Label:createWithTTF(ttfConfig,"Outline",cc.TEXT_ALIGNMENT_CENTER,s.width) - label3:setPosition( cc.p(s.width/2, s.height * 0.48)) - label3:setTextColor( cc.c4b(255, 0, 0, 255)) - label3:setAnchorPoint(cc.p(0.5, 0.5)) - label3:enableOutline(cc.c4b(0,0,255,255)) + local label3 = ax.Label:createWithTTF(ttfConfig,"Outline",ax.TEXT_ALIGNMENT_CENTER,s.width) + label3:setPosition( ax.p(s.width/2, s.height * 0.48)) + label3:setTextColor( ax.color32(255, 0, 0, 255)) + label3:setAnchorPoint(ax.p(0.5, 0.5)) + label3:enableOutline(ax.color32(0,0,255,255)) layer:addChild(label3) return layer @@ -1226,23 +1226,23 @@ end local LabelCharMapTest = {} function LabelCharMapTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + char map file") Helper.subtitleLabel:setString("Updating label should be fast.") time = 0 - local label1 = cc.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist") + local label1 = ax.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist") layer:addChild(label1, 0, kTagSprite1) - label1:setAnchorPoint(cc.p(0, 0)) - label1:setPosition( cc.p(10,100) ) + label1:setAnchorPoint(ax.p(0, 0)) + label1:setPosition( ax.p(10,100) ) label1:setOpacity( 200 ) - local label2 = cc.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist") + local label2 = ax.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist") layer:addChild(label2, 0, kTagSprite2) - label2:setAnchorPoint(cc.p(0, 0)) - label2:setPosition( cc.p(10,200) ) + label2:setAnchorPoint(ax.p(0, 0)) + label2:setPosition( ax.p(10,200) ) label2:setOpacity( 32 ) local function step(dt) @@ -1276,7 +1276,7 @@ end -------------------------------------------------------- local LabelCrashTest = {} function LabelCrashTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label Crash Test") Helper.subtitleLabel:setString("Not crash and show [Test123] when using unknown character.") @@ -1284,13 +1284,13 @@ function LabelCrashTest.create() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC + ttfConfig.glyphs = ax.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = true - local s = cc.Director:getInstance():getWinSize() - local label1 = cc.Label:createWithTTF(ttfConfig,"Test崩溃123", cc.TEXT_ALIGNMENT_CENTER, s.width) - label1:setPosition( cc.p(s.width/2, s.height/2) ) - label1:setAnchorPoint(cc.p(0.5, 0.5)) + local s = ax.Director:getInstance():getWinSize() + local label1 = ax.Label:createWithTTF(ttfConfig,"Test崩溃123", ax.TEXT_ALIGNMENT_CENTER, s.width) + label1:setPosition( ax.p(s.width/2, s.height/2) ) + label1:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(label1) return layer @@ -1301,50 +1301,50 @@ end -------------------------------------------------------- local LabelShadowTest = {} function LabelShadowTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + .TTF") Helper.subtitleLabel:setString("Testing shadow of label") - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() - local bg = cc.LayerColor:create(cc.c4b(200,191,231,255)) + local bg = ax.LayerColor:create(ax.color32(200,191,231,255)) layer:addChild(bg) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 40 - ttfConfig.glyphs = cc.GLYPHCOLLECTION_DYNAMIC + ttfConfig.glyphs = ax.GLYPHCOLLECTION_DYNAMIC ttfConfig.customGlyphs = nil ttfConfig.distanceFieldEnabled = true - local shadowLabelTTF = cc.Label:createWithTTF(ttfConfig, "TTF:Shadow") - shadowLabelTTF:setPosition(cc.p(size.width/2, size.height*0.65)) - shadowLabelTTF:setTextColor(cc.c4b(255, 0, 0, 255)) - shadowLabelTTF:enableShadow(cc.c4b(0, 0, 0, 255)) + local shadowLabelTTF = ax.Label:createWithTTF(ttfConfig, "TTF:Shadow") + shadowLabelTTF:setPosition(ax.p(size.width/2, size.height*0.65)) + shadowLabelTTF:setTextColor(ax.color32(255, 0, 0, 255)) + shadowLabelTTF:enableShadow(ax.color32(0, 0, 0, 255)) layer:addChild(shadowLabelTTF) - local shadowLabelOutline = cc.Label:createWithTTF(ttfConfig,"TTF:Shadow") - shadowLabelOutline:setPosition(cc.p(size.width/2, size.height*0.5)) - shadowLabelOutline:setTextColor(cc.c4b(255, 0, 0, 255)) - shadowLabelOutline:enableOutline(cc.c4b(255, 255, 0, 255), 1) - shadowLabelOutline:enableShadow(cc.c4b(0, 0, 0, 255)) + local shadowLabelOutline = ax.Label:createWithTTF(ttfConfig,"TTF:Shadow") + shadowLabelOutline:setPosition(ax.p(size.width/2, size.height*0.5)) + shadowLabelOutline:setTextColor(ax.color32(255, 0, 0, 255)) + shadowLabelOutline:enableOutline(ax.color32(255, 255, 0, 255), 1) + shadowLabelOutline:enableShadow(ax.color32(0, 0, 0, 255)) layer:addChild(shadowLabelOutline) - local shadowLabelBMFont = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "BMFont:Shadow") - shadowLabelBMFont:setPosition( cc.p(size.width/2, size.height*0.35) ) - shadowLabelBMFont:setColor(cc.c3b(255, 0, 0)) - shadowLabelBMFont:enableShadow(cc.c4b(0, 255, 0, 255)) + local shadowLabelBMFont = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "BMFont:Shadow") + shadowLabelBMFont:setPosition( ax.p(size.width/2, size.height*0.35) ) + shadowLabelBMFont:setColor(ax.color32(255, 0, 0)) + shadowLabelBMFont:enableShadow(ax.color32(0, 255, 0, 255)) layer:addChild(shadowLabelBMFont) local function sliderEvent(sender, eventType) if eventType == ccui.SliderEventType.percentChanged then local slider = layer:getChildByTag(1) local slider2 = layer:getChildByTag(2) - local offset = cc.size(slider:getPercent() - 50,50 - slider2:getPercent()) - shadowLabelTTF:enableShadow(cc.c4b(0, 0, 0, 255),offset) - shadowLabelBMFont:enableShadow(cc.c4b(0, 255, 0, 255),offset) - shadowLabelOutline:enableShadow(cc.c4b(0, 0, 0, 255),offset) + local offset = ax.size(slider:getPercent() - 50,50 - slider2:getPercent()) + shadowLabelTTF:enableShadow(ax.color32(0, 0, 0, 255),offset) + shadowLabelBMFont:enableShadow(ax.color32(0, 255, 0, 255),offset) + shadowLabelOutline:enableShadow(ax.color32(0, 0, 0, 255),offset) end end @@ -1354,7 +1354,7 @@ function LabelShadowTest.create() slider:loadBarTexture("cocosui/sliderTrack.png") slider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") slider:loadProgressBarTexture("cocosui/sliderProgress.png") - slider:setPosition(cc.p(size.width / 2.0, size.height * 0.15 + slider:getLayoutSize().height * 2.0)) + slider:setPosition(ax.p(size.width / 2.0, size.height * 0.15 + slider:getLayoutSize().height * 2.0)) slider:setPercent(52) slider:addEventListener(sliderEvent) layer:addChild(slider) @@ -1365,7 +1365,7 @@ function LabelShadowTest.create() slider2:loadBarTexture("cocosui/sliderTrack.png") slider2:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") slider2:loadProgressBarTexture("cocosui/sliderProgress.png") - slider2:setPosition(cc.p(size.width * 0.15, size.height / 2.0)) + slider2:setPosition(ax.p(size.width * 0.15, size.height / 2.0)) slider2:setRotation(90) slider2:setPercent(52) slider2:addEventListener(sliderEvent) @@ -1380,31 +1380,31 @@ end local LabelCharMapColorTest = {} function LabelCharMapColorTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label + CharMap") Helper.subtitleLabel:setString("Opacity + Color should work at the same time") - local label1 = cc.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist")--32 means Space key + local label1 = ax.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist")--32 means Space key layer:addChild(label1, 0, kTagSprite1) - label1:setAnchorPoint(cc.p(0.0, 0.0)) - label1:setPosition( cc.p(10,100) ) + label1:setAnchorPoint(ax.p(0.0, 0.0)) + label1:setPosition( ax.p(10,100) ) label1:setOpacity( 200 ) - local label2 = cc.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist")--32 means Space key + local label2 = ax.Label:createWithCharMap("fonts/tuffy_bold_italic-charmap.plist")--32 means Space key layer:addChild(label2, 0, kTagSprite2) - label2:setAnchorPoint(cc.p(0.0, 0.0)) - label2:setPosition( cc.p(10, 200) ) - label2:setColor( cc.c3b(255, 0, 0) ) + label2:setAnchorPoint(ax.p(0.0, 0.0)) + label2:setPosition( ax.p(10, 200) ) + label2:setColor( ax.color32(255, 0, 0) ) - local fade = cc.FadeOut:create(1.0) + local fade = ax.FadeOut:create(1.0) local fade_in = fade:reverse() local function actionFinishCallback(sender) print("Action finished") end - local cb = cc.CallFunc:create(actionFinishCallback) - local seq = cc.Sequence:create(fade, fade_in, cb) - local repeatForever = cc.RepeatForever:create( seq ) + local cb = ax.CallFunc:create(actionFinishCallback) + local seq = ax.Sequence:create(fade, fade_in, cb) + local repeatForever = ax.RepeatForever:create( seq ) label2:runAction( repeatForever ) local scheduleTime = 0 @@ -1422,7 +1422,7 @@ function LabelCharMapColorTest.create() local function onNodeEvent(event) if tag == "exit" then layer:unscheduleUpdate() - end + end end @@ -1440,20 +1440,20 @@ end local LabelFontNameTest = {} function LabelFontNameTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label Test") Helper.subtitleLabel:setString("create label by font name,compatible with old labelTTF") - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() - local label1 = cc.Label:create() + local label1 = ax.Label:create() label1:setString("Default Font") - label1:setPosition( cc.p(size.width/2, size.height * 0.7) ) + label1:setPosition( ax.p(size.width/2, size.height * 0.7) ) layer:addChild(label1) - local label3 = cc.Label:createWithTTF("fonts/Marker Felt.ttf","fonts/Marker Felt.ttf",32) - label3:setPosition( cc.p(size.width/2, size.height * 0.5) ) + local label3 = ax.Label:createWithTTF("fonts/Marker Felt.ttf","fonts/Marker Felt.ttf",32) + label3:setPosition( ax.p(size.width/2, size.height * 0.5) ) layer:addChild(label3) return layer @@ -1464,52 +1464,52 @@ end ----- LabelAlignmentTest -------------------------------------------------------- -local LabelAlignmentTest = +local LabelAlignmentTest = { _layer = nil, _label = nil, - _horizAlign = cc.TEXT_ALIGNMENT_LEFT, - _vertAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP, + _horizAlign = ax.TEXT_ALIGNMENT_LEFT, + _vertAlign = ax.VERTICAL_TEXT_ALIGNMENT_TOP, } function LabelAlignmentTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Testing New Label") Helper.subtitleLabel:setString("Select the buttons on the sides to change alignment") - local blockSize = cc.size(200, 160) - local s = cc.Director:getInstance():getWinSize() + local blockSize = ax.size(200, 160) + local s = ax.Director:getInstance():getWinSize() - local pos = cc.p((s.width - blockSize.width) / 2, (s.height - blockSize.height) / 2) - local colorLayer = cc.LayerColor:create(cc.c4b(100, 100, 100, 255), blockSize.width, blockSize.height) - colorLayer:setAnchorPoint(cc.p(0.0, 0.0)) + local pos = ax.p((s.width - blockSize.width) / 2, (s.height - blockSize.height) / 2) + local colorLayer = ax.LayerColor:create(ax.color32(100, 100, 100, 255), blockSize.width, blockSize.height) + colorLayer:setAnchorPoint(ax.p(0.0, 0.0)) colorLayer:setPosition(pos) layer:addChild(colorLayer) - cc.MenuItemFont:setFontSize(30) - local item1 = cc.MenuItemFont:create("Left") + ax.MenuItemFont:setFontSize(30) + local item1 = ax.MenuItemFont:create("Left") item1:registerScriptTapHandler(LabelAlignmentTest.setAlignmentLeft) - local item2 = cc.MenuItemFont:create("Center") + local item2 = ax.MenuItemFont:create("Center") item2:registerScriptTapHandler(LabelAlignmentTest.setAlignmentCenter) - local item3 = cc.MenuItemFont:create("Right") + local item3 = ax.MenuItemFont:create("Right") item3:registerScriptTapHandler(LabelAlignmentTest.setAlignmentRight) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) menu:alignItemsVerticallyWithPadding(4) - menu:setPosition(cc.p(50, s.height / 2 - 20)) + menu:setPosition(ax.p(50, s.height / 2 - 20)) layer:addChild(menu) - menu = cc.Menu:create() + menu = ax.Menu:create() - item1 = cc.MenuItemFont:create("Top") + item1 = ax.MenuItemFont:create("Top") item1:registerScriptTapHandler(LabelAlignmentTest.setAlignmentTop) - item2 = cc.MenuItemFont:create("Middle") + item2 = ax.MenuItemFont:create("Middle") item2:registerScriptTapHandler(LabelAlignmentTest.setAlignmentMiddle) - item3 = cc.MenuItemFont:create("Bottom") + item3 = ax.MenuItemFont:create("Bottom") item3:registerScriptTapHandler(LabelAlignmentTest.setAlignmentBottom) menu:addChild(item1) @@ -1517,24 +1517,24 @@ function LabelAlignmentTest.create() menu:addChild(item3) menu:alignItemsVerticallyWithPadding(4) - menu:setPosition(cc.p(s.width - 50, s.height / 2 - 20)) + menu:setPosition(ax.p(s.width - 50, s.height / 2 - 20)) layer:addChild(menu) LabelAlignmentTest._layer = layer LabelAlignmentTest._label = nil - LabelAlignmentTest._horizAlign = cc.TEXT_ALIGNMENT_LEFT - LabelAlignmentTest._vertAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP + LabelAlignmentTest._horizAlign = ax.TEXT_ALIGNMENT_LEFT + LabelAlignmentTest._vertAlign = ax.VERTICAL_TEXT_ALIGNMENT_TOP local ttfConfig = {} ttfConfig.fontFilePath="fonts/arial.ttf" ttfConfig.fontSize = 32 - local label = cc.Label:create() + local label = ax.Label:create() label:setDimensions(200,160) label:setAlignment(LabelAlignmentTest._horizAlign,LabelAlignmentTest._vertAlign) label:setTTFConfig(ttfConfig) label:setString(LabelAlignmentTest.getCurrentAlignment()) - label:setAnchorPoint(cc.p(0.0, 0.0)) + label:setAnchorPoint(ax.p(0.0, 0.0)) label:setPosition(pos) layer:addChild(label) LabelAlignmentTest._label = label @@ -1547,55 +1547,55 @@ function LabelAlignmentTest.updateAlignment() LabelAlignmentTest._label:setHorizontalAlignment(LabelAlignmentTest._horizAlign) LabelAlignmentTest._label:setVerticalAlignment(LabelAlignmentTest._vertAlign) LabelAlignmentTest._label:setString(LabelAlignmentTest.getCurrentAlignment()) - end + end end function LabelAlignmentTest.setAlignmentLeft(sender) - LabelAlignmentTest._horizAlign = cc.TEXT_ALIGNMENT_LEFT + LabelAlignmentTest._horizAlign = ax.TEXT_ALIGNMENT_LEFT LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.setAlignmentCenter(sender) - LabelAlignmentTest._horizAlign = cc.TEXT_ALIGNMENT_CENTER + LabelAlignmentTest._horizAlign = ax.TEXT_ALIGNMENT_CENTER LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.setAlignmentRight(sender) - LabelAlignmentTest._horizAlign = cc.TEXT_ALIGNMENT_RIGHT + LabelAlignmentTest._horizAlign = ax.TEXT_ALIGNMENT_RIGHT LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.setAlignmentTop(sender) - LabelAlignmentTest._vertAlign = cc.VERTICAL_TEXT_ALIGNMENT_TOP + LabelAlignmentTest._vertAlign = ax.VERTICAL_TEXT_ALIGNMENT_TOP LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.setAlignmentMiddle(sender) - LabelAlignmentTest._vertAlign = cc.VERTICAL_TEXT_ALIGNMENT_CENTER + LabelAlignmentTest._vertAlign = ax.VERTICAL_TEXT_ALIGNMENT_CENTER LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.setAlignmentBottom(sender) - LabelAlignmentTest._vertAlign = cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM + LabelAlignmentTest._vertAlign = ax.VERTICAL_TEXT_ALIGNMENT_BOTTOM LabelAlignmentTest.updateAlignment() end function LabelAlignmentTest.getCurrentAlignment() local vertical = nil local horizontal = nil - if LabelAlignmentTest._vertAlign == cc.VERTICAL_TEXT_ALIGNMENT_TOP then + if LabelAlignmentTest._vertAlign == ax.VERTICAL_TEXT_ALIGNMENT_TOP then vertical = "Top" - elseif LabelAlignmentTest._vertAlign == cc.VERTICAL_TEXT_ALIGNMENT_CENTER then + elseif LabelAlignmentTest._vertAlign == ax.VERTICAL_TEXT_ALIGNMENT_CENTER then vertical = "Middle" - elseif LabelAlignmentTest._vertAlign == cc.VERTICAL_TEXT_ALIGNMENT_BOTTOM then + elseif LabelAlignmentTest._vertAlign == ax.VERTICAL_TEXT_ALIGNMENT_BOTTOM then vertical = "Bottom" end - if LabelAlignmentTest._horizAlign == cc.TEXT_ALIGNMENT_LEFT then + if LabelAlignmentTest._horizAlign == ax.TEXT_ALIGNMENT_LEFT then horizontal = "Left" - elseif LabelAlignmentTest._horizAlign == cc.TEXT_ALIGNMENT_CENTER then + elseif LabelAlignmentTest._horizAlign == ax.TEXT_ALIGNMENT_CENTER then horizontal = "Center" - elseif LabelAlignmentTest._horizAlign == cc.TEXT_ALIGNMENT_RIGHT then + elseif LabelAlignmentTest._horizAlign == ax.TEXT_ALIGNMENT_RIGHT then horizontal = "Right" end @@ -1609,17 +1609,17 @@ end local LabelIssue4428Test = { } function LabelIssue4428Test.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New Label Bugs Test") Helper.subtitleLabel:setString("Reorder issue #4428.The label should be flipped vertically.") - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() - local label = cc.Label:createWithBMFont( "fonts/bitmapFontTest3.fnt", "123\n456") - label:setPosition(cc.p(size.width /2.0, size.height / 2.0)) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithBMFont( "fonts/bitmapFontTest3.fnt", "123\n456") + label:setPosition(ax.p(size.width /2.0, size.height / 2.0)) + label:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(label) local len = label:getStringLength() @@ -1639,54 +1639,54 @@ end local LabelTTFOldNew = { } function LabelTTFOldNew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("New / Old TTF") Helper.subtitleLabel:setString("Comparison between old(red) and new(white) TTF label") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local delta = s.height/4 - local label1 = cc.Label:createWithSystemFont("Axmol Label Test", "arial", 24) + local label1 = ax.Label:createWithSystemFont("Axmol Label Test", "arial", 24) layer:addChild(label1, 0, kTagBitmapAtlas1) - label1:setPosition(cc.p(s.width/2, delta * 2)) - label1:setColor(cc.c3b(255, 0, 0)) + label1:setPosition(ax.p(s.width/2, delta * 2)) + label1:setColor(ax.color32(255, 0, 0)) local labelSize = label1:getContentSize() - local origin = cc.Director:getInstance():getWinSize() + local origin = ax.Director:getInstance():getWinSize() origin.width = origin.width / 2 - (labelSize.width / 2) origin.height = origin.height / 2 - (labelSize.height / 2) - local vertices = + local vertices = { - cc.p(origin.width, origin.height), - cc.p(labelSize.width + origin.width, origin.height), - cc.p(labelSize.width + origin.width, labelSize.height + origin.height), - cc.p(origin.width, labelSize.height + origin.height), + ax.p(origin.width, origin.height), + ax.p(labelSize.width + origin.width, origin.height), + ax.p(labelSize.width + origin.width, labelSize.height + origin.height), + ax.p(origin.width, labelSize.height + origin.height), } - local drawNode = cc.DrawNode:create() - drawNode:drawPoly(vertices, 4, true, cc.c4f(1,0,0,1)) + local drawNode = ax.DrawNode:create() + drawNode:drawPoly(vertices, 4, true, ax.color(1,0,0,1)) layer:addChild(drawNode) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 24 - local label2 = cc.Label:createWithTTF(ttfConfig, "Axmol Label Test") + local label2 = ax.Label:createWithTTF(ttfConfig, "Axmol Label Test") layer:addChild(label2, 0, kTagBitmapAtlas2) - label2:setPosition(cc.p(s.width/2, delta * 2)) + label2:setPosition(ax.p(s.width/2, delta * 2)) labelSize = label2:getContentSize() - origin = cc.Director:getInstance():getWinSize() + origin = ax.Director:getInstance():getWinSize() origin.width = origin.width / 2 - (labelSize.width / 2) origin.height = origin.height / 2 - (labelSize.height / 2) local vertices2 = { - cc.p(origin.width, origin.height), - cc.p(labelSize.width + origin.width, origin.height), - cc.p(labelSize.width + origin.width, labelSize.height + origin.height), - cc.p(origin.width, labelSize.height + origin.height), + ax.p(origin.width, origin.height), + ax.p(labelSize.width + origin.width, origin.height), + ax.p(labelSize.width + origin.width, labelSize.height + origin.height), + ax.p(origin.width, labelSize.height + origin.height), } - local drawNode2 = cc.DrawNode:create() - drawNode2:drawPoly(vertices2, 4, true, cc.c4f(1,1,1,1)) + local drawNode2 = ax.DrawNode:create() + drawNode2:drawPoly(vertices2, 4, true, ax.color(1,1,1,1)) layer:addChild(drawNode2) return layer @@ -1697,7 +1697,7 @@ end function LabelTestNew() cclog("LabelTestNew") m_time = 0 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { LabelFNTColorAndOpacity.create, @@ -1735,7 +1735,7 @@ function LabelTestNew() LabelIssue4428Test.create, } Helper.index = 1 - + scene:addChild(LabelFNTColorAndOpacity.create()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/LayerTest/LayerTest.lua b/tests/lua-tests/Content/src/LayerTest/LayerTest.lua index f4aacf9bd9e9..2e1d61cedf87 100644 --- a/tests/lua-tests/Content/src/LayerTest/LayerTest.lua +++ b/tests/lua-tests/Content/src/LayerTest/LayerTest.lua @@ -1,8 +1,8 @@ -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() local kTagLayer = 1 local function createLayerDemoLayer(title, subtitle) - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local titleStr = title == nil and "No title" or title local subTitleStr = subtitle == nil and "" or subtitle @@ -22,7 +22,7 @@ local function createLayerDemoLayer(title, subtitle) -- local diffX = x - prev.x -- local diffY = y - prev.y - -- node:setPosition( cc.p.__add(cc.p(newX, newY), cc.p(diffX, diffY)) ) + -- node:setPosition( ax.p.__add(ax.p(newX, newY), ax.p(diffX, diffY)) ) -- prev.x = x -- prev.y = y -- end @@ -63,34 +63,34 @@ end -- LayerTestCascadingOpacityA local function LayerTestCascadingOpacityA() local ret = createLayerDemoLayer("Layer: cascading opacity") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.Layer:create() + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.Layer:create() - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt", "Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, s.height/2)) - sister2:setPosition( cc.p( s.width*2/3, s.height/2)) - label:setPosition( cc.p( s.width/2, s.height/2)) + sister1:setPosition( ax.p( s.width*1/3, s.height/2)) + sister2:setPosition( ax.p( s.width*2/3, s.height/2)) + label:setPosition( ax.p( s.width/2, s.height/2)) - layer1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(4, 0), - cc.FadeTo:create(4, 255), - cc.DelayTime:create(1) + layer1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(4, 0), + ax.FadeTo:create(4, 255), + ax.DelayTime:create(1) ))) - sister1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(2, 0), - cc.FadeTo:create(2, 255), - cc.FadeTo:create(2, 0), - cc.FadeTo:create(2, 255), - cc.DelayTime:create(1) + sister1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(2, 0), + ax.FadeTo:create(2, 255), + ax.FadeTo:create(2, 0), + ax.FadeTo:create(2, 255), + ax.DelayTime:create(1) ))) -- Enable cascading in scene @@ -102,29 +102,29 @@ end local function LayerTestCascadingOpacityB() local ret = createLayerDemoLayer("CCLayerColor: cascading opacity") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create(cc.c4b(192, 0, 0, 255), s.width, s.height/2) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create(ax.color32(192, 0, 0, 255), s.width, s.height/2) layer1:setCascadeColorEnabled(false) - layer1:setPosition( cc.p(0, s.height/2)) + layer1:setPosition( ax.p(0, s.height/2)) - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, 0)) - sister2:setPosition( cc.p( s.width*2/3, 0)) - label:setPosition( cc.p( s.width/2, 0)) + sister1:setPosition( ax.p( s.width*1/3, 0)) + sister2:setPosition( ax.p( s.width*2/3, 0)) + label:setPosition( ax.p( s.width/2, 0)) - layer1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(4, 0),cc.FadeTo:create(4, 255),cc.DelayTime:create(1)))) + layer1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(4, 0),ax.FadeTo:create(4, 255),ax.DelayTime:create(1)))) - sister1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(2, 0),cc.FadeTo:create(2, 255),cc.FadeTo:create(2, 0),cc.FadeTo:create(2, 255),cc.DelayTime:create(1)))) + sister1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(2, 0),ax.FadeTo:create(2, 255),ax.FadeTo:create(2, 0),ax.FadeTo:create(2, 255),ax.DelayTime:create(1)))) -- Enable cascading in scene setEnableRecursiveCascading(ret, true) @@ -135,32 +135,32 @@ end local function LayerTestCascadingOpacityC() local ret = createLayerDemoLayer("LayerColor: non-cascading opacity") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create(cc.c4b(192, 0, 0, 255), s.width, s.height/2) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create(ax.color32(192, 0, 0, 255), s.width, s.height/2) layer1:setCascadeColorEnabled(false) layer1:setCascadeOpacityEnabled(false) - layer1:setPosition( cc.p(0, s.height/2)) + layer1:setPosition( ax.p(0, s.height/2)) - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, 0)) - sister2:setPosition( cc.p( s.width*2/3, 0)) - label:setPosition( cc.p( s.width/2, 0)) + sister1:setPosition( ax.p( s.width*1/3, 0)) + sister2:setPosition( ax.p( s.width*2/3, 0)) + label:setPosition( ax.p( s.width/2, 0)) - layer1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(4, 0), - cc.FadeTo:create(4, 255),cc.DelayTime:create(1)))) + layer1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(4, 0), + ax.FadeTo:create(4, 255),ax.DelayTime:create(1)))) - sister1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.FadeTo:create(2, 0),cc.FadeTo:create(2, 255), - cc.FadeTo:create(2, 0),cc.FadeTo:create(2, 255),cc.DelayTime:create(1)))) + sister1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.FadeTo:create(2, 0),ax.FadeTo:create(2, 255), + ax.FadeTo:create(2, 0),ax.FadeTo:create(2, 255),ax.DelayTime:create(1)))) return ret end @@ -170,40 +170,40 @@ end local function LayerTestCascadingColorA() local ret = createLayerDemoLayer("Layer: cascading color") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.Layer:create() + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.Layer:create() - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, s.height/2)) - sister2:setPosition( cc.p( s.width*2/3, s.height/2)) - label:setPosition( cc.p( s.width/2, s.height/2)) + sister1:setPosition( ax.p( s.width*1/3, s.height/2)) + sister2:setPosition( ax.p( s.width*2/3, s.height/2)) + label:setPosition( ax.p( s.width/2, s.height/2)) layer1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(6, 255, 0, 255), - cc.TintTo:create(6, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(6, 255, 0, 255), + ax.TintTo:create(6, 255, 255, 255), + ax.DelayTime:create(1) ))) sister1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(2, 255, 255, 0), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 0, 255, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 255, 0, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(2, 255, 255, 0), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 0, 255, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 255, 0, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.DelayTime:create(1) ))) -- Enable cascading in scene @@ -215,41 +215,41 @@ end local function LayerTestCascadingColorB() local ret = createLayerDemoLayer("LayerColor: cascading color") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create(cc.c4b(255, 255, 255, 255), s.width, s.height/2) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create(ax.color32(255, 255, 255, 255), s.width, s.height/2) - layer1:setPosition( cc.p(0, s.height/2)) + layer1:setPosition( ax.p(0, s.height/2)) - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, 0)) - sister2:setPosition( cc.p( s.width*2/3, 0)) - label:setPosition( cc.p( s.width/2, 0)) + sister1:setPosition( ax.p( s.width*1/3, 0)) + sister2:setPosition( ax.p( s.width*2/3, 0)) + label:setPosition( ax.p( s.width/2, 0)) layer1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(6, 255, 0, 255), - cc.TintTo:create(6, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(6, 255, 0, 255), + ax.TintTo:create(6, 255, 255, 255), + ax.DelayTime:create(1) ))) sister1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(2, 255, 255, 0), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 0, 255, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 255, 0, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(2, 255, 255, 0), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 0, 255, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 255, 0, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.DelayTime:create(1) ))) -- Enable cascading in scene @@ -261,41 +261,41 @@ end local function LayerTestCascadingColorC() local ret = createLayerDemoLayer("LayerColor: non-cascading color") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create(cc.c4b(255, 255, 255, 255), s.width, s.height/2) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create(ax.color32(255, 255, 255, 255), s.width, s.height/2) layer1:setCascadeColorEnabled(false) - layer1:setPosition( cc.p(0, s.height/2)) + layer1:setPosition( ax.p(0, s.height/2)) - local sister1 = cc.Sprite:create("Images/grossinis_sister1.png") - local sister2 = cc.Sprite:create("Images/grossinis_sister2.png") - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") - label:setAnchorPoint(cc.p(0.5, 0.5)) + local sister1 = ax.Sprite:create("Images/grossinis_sister1.png") + local sister2 = ax.Sprite:create("Images/grossinis_sister2.png") + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest.fnt","Test") + label:setAnchorPoint(ax.p(0.5, 0.5)) layer1:addChild(sister1) layer1:addChild(sister2) layer1:addChild(label) ret:addChild( layer1, 0, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, 0)) - sister2:setPosition( cc.p( s.width*2/3, 0)) - label:setPosition( cc.p( s.width/2, 0)) + sister1:setPosition( ax.p( s.width*1/3, 0)) + sister2:setPosition( ax.p( s.width*2/3, 0)) + label:setPosition( ax.p( s.width/2, 0)) layer1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(6, 255, 0, 255), - cc.TintTo:create(6, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(6, 255, 0, 255), + ax.TintTo:create(6, 255, 255, 255), + ax.DelayTime:create(1) ))) sister1:runAction( - cc.RepeatForever:create( - cc.Sequence:create(cc.TintTo:create(2, 255, 255, 0), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 0, 255, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.TintTo:create(2, 255, 0, 255), - cc.TintTo:create(2, 255, 255, 255), - cc.DelayTime:create(1) + ax.RepeatForever:create( + ax.Sequence:create(ax.TintTo:create(2, 255, 255, 0), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 0, 255, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.TintTo:create(2, 255, 0, 255), + ax.TintTo:create(2, 255, 255, 255), + ax.DelayTime:create(1) ))) return ret end @@ -308,17 +308,17 @@ end local function LayerTest1() local ret = createLayerDemoLayer("ColorLayer resize (tap & move)") - local s = cc.Director:getInstance():getWinSize() - local layer = cc.LayerColor:create( cc.c4b(0xFF, 0x00, 0x00, 0x80), 200, 200) + local s = ax.Director:getInstance():getWinSize() + local layer = ax.LayerColor:create( ax.color32(0xFF, 0x00, 0x00, 0x80), 200, 200) layer:setIgnoreAnchorPointForPosition(false) - layer:setPosition( cc.p(s.width/2, s.height/2) ) + layer:setPosition( ax.p(s.width/2, s.height/2) ) ret:addChild(layer, 1, kTagLayer) local function updateSize(x, y) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local newSize = cc.size( math.abs(x - s.width/2)*2, math.abs(y - s.height/2)*2) + local newSize = ax.size( math.abs(x - s.width/2)*2, math.abs(y - s.height/2)*2) local l = ret:getChildByTag(kTagLayer) @@ -335,9 +335,9 @@ local function LayerTest1() onTouchesMoved(touches, event) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = ret:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) @@ -353,25 +353,25 @@ end local function LayerTest2() local ret = createLayerDemoLayer("ColorLayer: fade and tint") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create( cc.c4b(255, 255, 0, 80), 100, 300) - layer1:setPosition(cc.p(s.width/3, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create( ax.color32(255, 255, 0, 80), 100, 300) + layer1:setPosition(ax.p(s.width/3, s.height/2)) layer1:setIgnoreAnchorPointForPosition(false) ret:addChild(layer1, 1) - local layer2 = cc.LayerColor:create( cc.c4b(0, 0, 255, 255), 100, 300) - layer2:setPosition(cc.p((s.width/3)*2, s.height/2)) + local layer2 = ax.LayerColor:create( ax.color32(0, 0, 255, 255), 100, 300) + layer2:setPosition(ax.p((s.width/3)*2, s.height/2)) layer2:setIgnoreAnchorPointForPosition(false) ret:addChild(layer2, 1) - local actionTint = cc.TintBy:create(2, -255, -127, 0) + local actionTint = ax.TintBy:create(2, -255, -127, 0) local actionTintBack = actionTint:reverse() - local seq1 = cc.Sequence:create(actionTint,actionTintBack) + local seq1 = ax.Sequence:create(actionTint,actionTintBack) layer1:runAction(seq1) - local actionFade = cc.FadeOut:create(2.0) + local actionFade = ax.FadeOut:create(2.0) local actionFadeBack = actionFade:reverse() - local seq2 = cc.Sequence:create(actionFade,actionFadeBack) + local seq2 = ax.Sequence:create(actionFade,actionFadeBack) layer2:runAction(seq2) return ret @@ -385,18 +385,18 @@ end local function LayerTestBlend() local ret = createLayerDemoLayer("ColorLayer: blend") - local s = cc.Director:getInstance():getWinSize() - local layer1 = cc.LayerColor:create( cc.c4b(255, 255, 255, 80) ) + local s = ax.Director:getInstance():getWinSize() + local layer1 = ax.LayerColor:create( ax.color32(255, 255, 255, 80) ) - local sister1 = cc.Sprite:create(s_pPathSister1) - local sister2 = cc.Sprite:create(s_pPathSister2) + local sister1 = ax.Sprite:create(s_pPathSister1) + local sister2 = ax.Sprite:create(s_pPathSister2) ret:addChild(sister1) ret:addChild(sister2) ret:addChild(layer1, 100, kTagLayer) - sister1:setPosition( cc.p( s.width*1/3, s.height/2) ) - sister2:setPosition( cc.p( s.width*2/3, s.height/2) ) + sister1:setPosition( ax.p( s.width*1/3, s.height/2) ) + sister2:setPosition( ax.p( s.width*2/3, s.height/2) ) local blend = true @@ -407,14 +407,14 @@ local function LayerTestBlend() local dst = 0 if blend then - src = ccb.BlendFactor.SRC_ALPHA - dst = ccb.BlendFactor.ONE_MINUS_SRC_ALPHA + src = ccb.BlendFactor.SRC_ALPHA + dst = ccb.BlendFactor.ONE_MINUS_SRC_ALPHA else src = ccb.BlendFactor.ONE_MINUS_DST_COLOR dst = ccb.BlendFactor.ZERO end - layer:setBlendFunc(cc.blendFunc(src, dst)) + layer:setBlendFunc(ax.blendFunc(src, dst)) blend = not blend end @@ -439,16 +439,16 @@ end -------------------------------------------------------------------- local function LayerGradient() local ret = createLayerDemoLayer("LayerGradient", "Touch the screen and move your finger") - local layer1 = cc.LayerGradient:create(cc.c4b(255,0,0,255), cc.c4b(0,255,0,255), cc.p(0.9, 0.9)) + local layer1 = ax.LayerGradient:create(ax.color32(255,0,0,255), ax.color32(0,255,0,255), ax.p(0.9, 0.9)) ret:addChild(layer1, 0, kTagLayer) - local label1 = cc.Label:createWithTTF("Compressed Interpolation: Enabled", s_markerFeltFontPath, 26) - label1:setAnchorPoint(cc.p(0.5, 0.5)) - local label2 = cc.Label:createWithTTF("Compressed Interpolation: Disabled", s_markerFeltFontPath, 26) - label2:setAnchorPoint(cc.p(0.5, 0.5)) - local item1 = cc.MenuItemLabel:create(label1) - local item2 = cc.MenuItemLabel:create(label2) - local item = cc.MenuItemToggle:create(item1) + local label1 = ax.Label:createWithTTF("Compressed Interpolation: Enabled", s_markerFeltFontPath, 26) + label1:setAnchorPoint(ax.p(0.5, 0.5)) + local label2 = ax.Label:createWithTTF("Compressed Interpolation: Disabled", s_markerFeltFontPath, 26) + label2:setAnchorPoint(ax.p(0.5, 0.5)) + local item1 = ax.MenuItemLabel:create(label1) + local item2 = ax.MenuItemLabel:create(label2) + local item = ax.MenuItemToggle:create(item1) item:addSubItem(item2) local function toggleItem(sender) @@ -459,24 +459,24 @@ local function LayerGradient() item:registerScriptTapHandler(toggleItem) - local menu = cc.Menu:create(item) + local menu = ax.Menu:create(item) ret:addChild(menu) - local s = cc.Director:getInstance():getWinSize() - menu:setPosition(cc.p(s.width / 2, 100)) + local s = ax.Director:getInstance():getWinSize() + menu:setPosition(ax.p(s.width / 2, 100)) local function onTouchesMoved(touches, event) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local start = touches[1]:getLocation() - local movingPos = cc.p(s.width/2,s.height/2) - local diff = cc.p(movingPos.x - start.x, movingPos.y - start.y) - diff = cc.pNormalize(diff) + local movingPos = ax.p(s.width/2,s.height/2) + local diff = ax.p(movingPos.x - start.x, movingPos.y - start.y) + diff = ax.pNormalize(diff) local gradient = ret:getChildByTag(1) gradient:setVector(diff) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = ret:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) @@ -492,23 +492,23 @@ local kLayerIgnoreAnchorPoint = 1000 local function LayerIgnoreAnchorPointPos() local ret = createLayerDemoLayer("IgnoreAnchorPoint - Position", "Ignoring Anchor Point for position") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local l = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 150, 150) + local l = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 150, 150) - l:setAnchorPoint(cc.p(0.5, 0.5)) - l:setPosition(cc.p( s.width/2, s.height/2)) + l:setAnchorPoint(ax.p(0.5, 0.5)) + l:setPosition(ax.p( s.width/2, s.height/2)) - local move = cc.MoveBy:create(2, cc.p(100,2)) + local move = ax.MoveBy:create(2, ax.p(100,2)) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - l:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, back) + l:runAction(ax.RepeatForever:create(seq)) ret:addChild(l, 0, kLayerIgnoreAnchorPoint) - local child = cc.Sprite:create("Images/grossini.png") + local child = ax.Sprite:create("Images/grossini.png") l:addChild(child) local lsize = l:getContentSize() - child:setPosition(cc.p(lsize.width/2, lsize.height/2)) + child:setPosition(ax.p(lsize.width/2, lsize.height/2)) local function onToggle(pObject) local pLayer = ret:getChildByTag(kLayerIgnoreAnchorPoint) @@ -516,13 +516,13 @@ local function LayerIgnoreAnchorPointPos() pLayer:setIgnoreAnchorPointForPosition(not ignore) end - local item = cc.MenuItemFont:create("Toggle ignore anchor point") + local item = ax.MenuItemFont:create("Toggle ignore anchor point") item:registerScriptTapHandler(onToggle) - local menu = cc.Menu:create(item) + local menu = ax.Menu:create(item) ret:addChild(menu) - menu:setPosition(cc.p(s.width/2, s.height/2)) + menu:setPosition(ax.p(s.width/2, s.height/2)) return ret end @@ -531,23 +531,23 @@ end local function LayerIgnoreAnchorPointRot() local ret = createLayerDemoLayer("IgnoreAnchorPoint - Rotation", "Ignoring Anchor Point for rotations") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local l = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 200, 200) + local l = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 200, 200) - l:setAnchorPoint(cc.p(0.5, 0.5)) - l:setPosition(cc.p( s.width/2, s.height/2)) + l:setAnchorPoint(ax.p(0.5, 0.5)) + l:setPosition(ax.p( s.width/2, s.height/2)) ret:addChild(l, 0, kLayerIgnoreAnchorPoint) - local rot = cc.RotateBy:create(2, 360) - l:runAction(cc.RepeatForever:create(rot)) + local rot = ax.RotateBy:create(2, 360) + l:runAction(ax.RepeatForever:create(rot)) - local child = cc.Sprite:create("Images/grossini.png") + local child = ax.Sprite:create("Images/grossini.png") l:addChild(child) local lsize = l:getContentSize() - child:setPosition(cc.p(lsize.width/2, lsize.height/2)) + child:setPosition(ax.p(lsize.width/2, lsize.height/2)) local function onToggle(pObject) local pLayer = ret:getChildByTag(kLayerIgnoreAnchorPoint) @@ -555,39 +555,39 @@ local function LayerIgnoreAnchorPointRot() pLayer:setIgnoreAnchorPointForPosition(not ignore) end - local item = cc.MenuItemFont:create("Toggle ignore anchor point") + local item = ax.MenuItemFont:create("Toggle ignore anchor point") item:registerScriptTapHandler(onToggle) - local menu = cc.Menu:create(item) + local menu = ax.Menu:create(item) ret:addChild(menu) - menu:setPosition(cc.p(s.width/2, s.height/2)) + menu:setPosition(ax.p(s.width/2, s.height/2)) return ret end -- LayerIgnoreAnchorPointScale local function LayerIgnoreAnchorPointScale() local ret = createLayerDemoLayer("IgnoreAnchorPoint - Scale", "Ignoring Anchor Point for scale") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local l = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 200, 200) + local l = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 200, 200) - l:setAnchorPoint(cc.p(0.5, 1.0)) - l:setPosition(cc.p( s.width/2, s.height/2)) + l:setAnchorPoint(ax.p(0.5, 1.0)) + l:setPosition(ax.p( s.width/2, s.height/2)) - local scale = cc.ScaleBy:create(2, 2) + local scale = ax.ScaleBy:create(2, 2) local back = scale:reverse() - local seq = cc.Sequence:create(scale, back) + local seq = ax.Sequence:create(scale, back) - l:runAction(cc.RepeatForever:create(seq)) + l:runAction(ax.RepeatForever:create(seq)) ret:addChild(l, 0, kLayerIgnoreAnchorPoint) - local child = cc.Sprite:create("Images/grossini.png") + local child = ax.Sprite:create("Images/grossini.png") l:addChild(child) local lsize = l:getContentSize() - child:setPosition(cc.p(lsize.width/2, lsize.height/2)) + child:setPosition(ax.p(lsize.width/2, lsize.height/2)) local function onToggle(pObject) local pLayer = ret:getChildByTag(kLayerIgnoreAnchorPoint) @@ -596,37 +596,37 @@ local function LayerIgnoreAnchorPointScale() return ret end - local item = cc.MenuItemFont:create("Toggle ignore anchor point") + local item = ax.MenuItemFont:create("Toggle ignore anchor point") item:registerScriptTapHandler(onToggle) - local menu = cc.Menu:create(item) + local menu = ax.Menu:create(item) ret:addChild(menu) - menu:setPosition(cc.p(s.width/2, s.height/2)) + menu:setPosition(ax.p(s.width/2, s.height/2)) return ret end local function LayerExtendedBlendOpacityTest() local ret = createLayerDemoLayer("Extended Blend & Opacity", "You should see 3 layers") - local layer1 = cc.LayerGradient:create(cc.c4b(255, 0, 0, 255), cc.c4b(255, 0, 255, 255)) - layer1:setContentSize(cc.size(80, 80)) - layer1:setPosition(cc.p(50,50)) + local layer1 = ax.LayerGradient:create(ax.color32(255, 0, 0, 255), ax.color32(255, 0, 255, 255)) + layer1:setContentSize(ax.size(80, 80)) + layer1:setPosition(ax.p(50,50)) ret:addChild(layer1) - local layer2 = cc.LayerGradient:create(cc.c4b(0, 0, 0, 127), cc.c4b(255, 255, 255, 127)) - layer2:setContentSize(cc.size(80, 80)) - layer2:setPosition(cc.p(100,90)) + local layer2 = ax.LayerGradient:create(ax.color32(0, 0, 0, 127), ax.color32(255, 255, 255, 127)) + layer2:setContentSize(ax.size(80, 80)) + layer2:setPosition(ax.p(100,90)) ret:addChild(layer2) - local layer3 = cc.LayerGradient:create() - layer3:setContentSize(cc.size(80, 80)) - layer3:setPosition(cc.p(150,140)) - layer3:setStartColor(cc.c3b(255, 0, 0)) - layer3:setEndColor(cc.c3b(255, 0, 255)) + local layer3 = ax.LayerGradient:create() + layer3:setContentSize(ax.size(80, 80)) + layer3:setPosition(ax.p(150,140)) + layer3:setStartColor(ax.color32(255, 0, 0)) + layer3:setEndColor(ax.color32(255, 0, 255)) layer3:setStartOpacity(255) layer3:setEndOpacity(255) - layer3:setBlendFunc(cc.blendFunc(ccb.BlendFactor.SRC_ALPHA, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) + layer3:setBlendFunc(ax.blendFunc(ccb.BlendFactor.SRC_ALPHA, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) ret:addChild(layer3) return ret end @@ -634,7 +634,7 @@ end function LayerTestMain() cclog("LayerTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { LayerTestCascadingOpacityA, @@ -653,7 +653,7 @@ function LayerTestMain() LayerExtendedBlendOpacityTest } Helper.index = 1 - + scene:addChild(LayerTestCascadingOpacityA()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/LightTest/LightTest.lua b/tests/lua-tests/Content/src/LightTest/LightTest.lua index e86cdda18ac6..d7221ad67e8d 100644 --- a/tests/lua-tests/Content/src/LightTest/LightTest.lua +++ b/tests/lua-tests/Content/src/LightTest/LightTest.lua @@ -1,5 +1,5 @@ local LightTest = class("LightTest",function() - return cc.Layer:create() + return ax.Layer:create() end) function LightTest:ctor() @@ -20,19 +20,19 @@ function LightTest:init() self:addSprite() self:addLights() - local s = cc.Director:getInstance():getWinSize() - local camera = cc.Camera:createPerspective(60, s.width/s.height, 1.0, 1000.0) - camera:setCameraFlag(cc.CameraFlag.USER1) - camera:setPosition3D(cc.vec3(0.0, 100, 100)) - camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) + local s = ax.Director:getInstance():getWinSize() + local camera = ax.Camera:createPerspective(60, s.width/s.height, 1.0, 1000.0) + camera:setCameraFlag(ax.CameraFlag.USER1) + camera:setPosition3D(ax.vec3(0.0, 100, 100)) + camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) self:addChild(camera) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 15 - local ambientLightLabel = cc.Label:createWithTTF(ttfConfig,"Ambient Light ON") - local menuItem0 = cc.MenuItemLabel:create(ambientLightLabel) + local ambientLightLabel = ax.Label:createWithTTF(ttfConfig,"Ambient Light ON") + local menuItem0 = ax.MenuItemLabel:create(ambientLightLabel) menuItem0:registerScriptTapHandler(function (tag, sender) local str = nil local isON = not self._ambientLight:isEnabled() @@ -45,9 +45,9 @@ function LightTest:init() menuItem0:setString(str) end) - - local directionalLightLabel = cc.Label:createWithTTF(ttfConfig,"Directional Light OFF") - local menuItem1 = cc.MenuItemLabel:create(directionalLightLabel) + + local directionalLightLabel = ax.Label:createWithTTF(ttfConfig,"Directional Light OFF") + local menuItem1 = ax.MenuItemLabel:create(directionalLightLabel) menuItem1:registerScriptTapHandler(function (tag, sender) local str = nil local isON = not self._directionalLight:isEnabled() @@ -61,8 +61,8 @@ function LightTest:init() end) - local pointLightLabel = cc.Label:createWithTTF(ttfConfig,"Point Light OFF") - local menuItem2 = cc.MenuItemLabel:create(pointLightLabel) + local pointLightLabel = ax.Label:createWithTTF(ttfConfig,"Point Light OFF") + local menuItem2 = ax.MenuItemLabel:create(pointLightLabel) menuItem2:registerScriptTapHandler(function (tag, sender) local str = nil local isON = not self._pointLight:isEnabled() @@ -75,8 +75,8 @@ function LightTest:init() menuItem2:setString(str) end) - local spotLightLabel = cc.Label:createWithTTF(ttfConfig,"Spot Light OFF") - local menuItem3 = cc.MenuItemLabel:create(spotLightLabel) + local spotLightLabel = ax.Label:createWithTTF(ttfConfig,"Spot Light OFF") + local menuItem3 = ax.MenuItemLabel:create(spotLightLabel) menuItem3:registerScriptTapHandler(function (tag, sender) local str = nil local isON = not self._spotLight:isEnabled() @@ -90,37 +90,37 @@ function LightTest:init() end) - local menu = cc.Menu:create(menuItem0, menuItem1, menuItem2, menuItem3) - menu:setPosition(cc.p(0, 0)) - menuItem0:setAnchorPoint(cc.p(0.0 ,1.0)) - menuItem0:setPosition( cc.p(VisibleRect:left().x, VisibleRect:top().y-50) ) - menuItem1:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem1:setPosition( cc.p(VisibleRect:left().x, VisibleRect:top().y-100) ) - menuItem2:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem2:setPosition( cc.p(VisibleRect:left().x, VisibleRect:top().y -150)) - menuItem3:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem3:setPosition( cc.p(VisibleRect:left().x, VisibleRect:top().y -200)) + local menu = ax.Menu:create(menuItem0, menuItem1, menuItem2, menuItem3) + menu:setPosition(ax.p(0, 0)) + menuItem0:setAnchorPoint(ax.p(0.0 ,1.0)) + menuItem0:setPosition( ax.p(VisibleRect:left().x, VisibleRect:top().y-50) ) + menuItem1:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem1:setPosition( ax.p(VisibleRect:left().x, VisibleRect:top().y-100) ) + menuItem2:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem2:setPosition( ax.p(VisibleRect:left().x, VisibleRect:top().y -150)) + menuItem3:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem3:setPosition( ax.p(VisibleRect:left().x, VisibleRect:top().y -200)) self:addChild(menu) local angleDelta = 0.0 local function update(delta) if nil ~= self._directionalLight then - self._directionalLight:setRotation3D(cc.vec3(-45.0, -angleDelta * 57.29577951, 0.0)) + self._directionalLight:setRotation3D(ax.vec3(-45.0, -angleDelta * 57.29577951, 0.0)) end - + if nil ~= self._pointLight then self._pointLight:setPositionX(100.0 * math.cos(angleDelta + 2.0 * delta)) self._pointLight:setPositionY(100.0) self._pointLight:setPositionZ(100.0 * math.sin(angleDelta + 2.0 * delta)) end - + if nil ~= self._spotLight then self._spotLight:setPositionX(100.0 * math.cos(angleDelta + 4.0 * delta)) self._spotLight:setPositionY(100.0) self._spotLight:setPositionZ(100.0 * math.sin(angleDelta + 4.0 * delta)) - self._spotLight:setDirection(cc.vec3(-math.cos(angleDelta + 4.0 * delta), -1.0, -math.sin(angleDelta + 4.0 * delta))) + self._spotLight:setDirection(ax.vec3(-math.cos(angleDelta + 4.0 * delta), -1.0, -math.sin(angleDelta + 4.0 * delta))) end - + angleDelta = angleDelta + delta end @@ -128,95 +128,95 @@ function LightTest:init() end function LightTest:addSprite() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local fileName = "MeshRendererTest/orc.c3b" - local sprite1 = cc.Sprite3D:create(fileName) - sprite1:setRotation3D(cc.vec3(0.0, 180.0, 0.0)) - sprite1:setPosition(cc.p(0.0, 0.0)) + local sprite1 = ax.Sprite3D:create(fileName) + sprite1:setRotation3D(ax.vec3(0.0, 180.0, 0.0)) + sprite1:setPosition(ax.p(0.0, 0.0)) sprite1:setScale(2.0) - local sp = cc.Sprite3D:create("MeshRendererTest/axe.c3b") + local sp = ax.Sprite3D:create("MeshRendererTest/axe.c3b") sprite1:getAttachNode("Bip001 R Hand"):addChild(sp) - local animation = cc.Animation3D:create(fileName) + local animation = ax.Animation3D:create(fileName) if nil ~=animation then - local animate = cc.Animate3D:create(animation) - sprite1:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + sprite1:runAction(ax.RepeatForever:create(animate)) end self:addChild(sprite1) sprite1:setCameraMask(2) local fileName = "MeshRendererTest/sphere.c3b" - local sprite2 = cc.Sprite3D:create(fileName) - sprite2:setPosition(cc.p(30.0, 0.0)) + local sprite2 = ax.Sprite3D:create(fileName) + sprite2:setPosition(ax.p(30.0, 0.0)) self:addChild(sprite2) sprite2:setCameraMask(2) - + local fileName = "MeshRendererTest/sphere.c3b" - local sprite3 = cc.Sprite3D:create(fileName) + local sprite3 = ax.Sprite3D:create(fileName) sprite3:setScale(0.5) - sprite3:setPosition(cc.p(-50.0, 0.0)) + sprite3:setPosition(ax.p(-50.0, 0.0)) self:addChild(sprite3) sprite3:setCameraMask(2) - + local fileName = "MeshRendererTest/sphere.c3b" - local sprite4 = cc.Sprite3D:create(fileName) + local sprite4 = ax.Sprite3D:create(fileName) sprite4:setScale(0.5) - sprite4:setPosition(cc.p(-30.0, 10.0)) + sprite4:setPosition(ax.p(-30.0, 10.0)) self:addChild(sprite4) sprite4:setCameraMask(2) end function LightTest:addLights() - local s = cc.Director:getInstance():getWinSize() - self._ambientLight = cc.AmbientLight:create(cc.c3b(200, 200, 200)) + local s = ax.Director:getInstance():getWinSize() + self._ambientLight = ax.AmbientLight:create(ax.color32(200, 200, 200)) self._ambientLight:setEnabled(true) self:addChild(self._ambientLight) self._ambientLight:setCameraMask(2) - self._directionalLight = cc.DirectionLight:create(cc.vec3(-1.0, -1.0, 0.0), cc.c3b(200, 200, 200)) + self._directionalLight = ax.DirectionLight:create(ax.vec3(-1.0, -1.0, 0.0), ax.color32(200, 200, 200)) self._directionalLight:setEnabled(false) self:addChild(self._directionalLight) self._directionalLight:setCameraMask(2) - self._pointLight = cc.PointLight:create(cc.vec3(0.0, 0.0, 0.0), cc.c3b(200, 200, 200), 10000.0) + self._pointLight = ax.PointLight:create(ax.vec3(0.0, 0.0, 0.0), ax.color32(200, 200, 200), 10000.0) self._pointLight:setEnabled(false) self:addChild(self._pointLight) self._pointLight:setCameraMask(2) - self._spotLight = cc.SpotLight:create(cc.vec3(-1.0, -1.0, 0.0), cc.vec3(0.0, 0.0, 0.0), cc.c3b(200, 200, 200), 0.0, 0.5, 10000.0) + self._spotLight = ax.SpotLight:create(ax.vec3(-1.0, -1.0, 0.0), ax.vec3(0.0, 0.0, 0.0), ax.color32(200, 200, 200), 0.0, 0.5, 10000.0) self._spotLight:setEnabled(false) self:addChild(self._spotLight) self._spotLight:setCameraMask(2) - local tintto1 = cc.TintTo:create(4, 0, 0, 255) - local tintto2 = cc.TintTo:create(4, 0, 255, 0) - local tintto3 = cc.TintTo:create(4, 255, 0, 0) - local tintto4 = cc.TintTo:create(4, 255, 255, 255) - local seq = cc.Sequence:create(tintto1,tintto2, tintto3, tintto4) - self._ambientLight:runAction(cc.RepeatForever:create(seq)) - - tintto1 = cc.TintTo:create(4, 255, 0, 0) - tintto2 = cc.TintTo:create(4, 0, 255, 0) - tintto3 = cc.TintTo:create(4, 0, 0, 255) - tintto4 = cc.TintTo:create(4, 255, 255, 255) - seq = cc.Sequence:create(tintto1,tintto2, tintto3, tintto4) - self._directionalLight:runAction(cc.RepeatForever:create(seq)) - - - tintto1 = cc.TintTo:create(4, 255, 0, 0) - tintto2 = cc.TintTo:create(4, 0, 255, 0) - tintto3 = cc.TintTo:create(4, 0, 0, 255) - tintto4 = cc.TintTo:create(4, 255, 255, 255) - seq = cc.Sequence:create(tintto2, tintto1, tintto3, tintto4) - self._pointLight:runAction(cc.RepeatForever:create(seq)) - - tintto1 = cc.TintTo:create(4, 255, 0, 0) - tintto2 = cc.TintTo:create(4, 0, 255, 0) - tintto3 = cc.TintTo:create(4, 0, 0, 255) - tintto4 = cc.TintTo:create(4, 255, 255, 255) - seq = cc.Sequence:create(tintto3, tintto2, tintto1, tintto4) - self._spotLight:runAction(cc.RepeatForever:create(seq)) + local tintto1 = ax.TintTo:create(4, 0, 0, 255) + local tintto2 = ax.TintTo:create(4, 0, 255, 0) + local tintto3 = ax.TintTo:create(4, 255, 0, 0) + local tintto4 = ax.TintTo:create(4, 255, 255, 255) + local seq = ax.Sequence:create(tintto1,tintto2, tintto3, tintto4) + self._ambientLight:runAction(ax.RepeatForever:create(seq)) + + tintto1 = ax.TintTo:create(4, 255, 0, 0) + tintto2 = ax.TintTo:create(4, 0, 255, 0) + tintto3 = ax.TintTo:create(4, 0, 0, 255) + tintto4 = ax.TintTo:create(4, 255, 255, 255) + seq = ax.Sequence:create(tintto1,tintto2, tintto3, tintto4) + self._directionalLight:runAction(ax.RepeatForever:create(seq)) + + + tintto1 = ax.TintTo:create(4, 255, 0, 0) + tintto2 = ax.TintTo:create(4, 0, 255, 0) + tintto3 = ax.TintTo:create(4, 0, 0, 255) + tintto4 = ax.TintTo:create(4, 255, 255, 255) + seq = ax.Sequence:create(tintto2, tintto1, tintto3, tintto4) + self._pointLight:runAction(ax.RepeatForever:create(seq)) + + tintto1 = ax.TintTo:create(4, 255, 0, 0) + tintto2 = ax.TintTo:create(4, 0, 255, 0) + tintto3 = ax.TintTo:create(4, 0, 0, 255) + tintto4 = ax.TintTo:create(4, 255, 255, 255) + seq = ax.Sequence:create(tintto3, tintto2, tintto1, tintto4) + self._spotLight:runAction(ax.RepeatForever:create(seq)) end function LightTest.create( ... ) @@ -228,9 +228,9 @@ end function LightTestMain() cclog("LightTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { LightTest.create, } diff --git a/tests/lua-tests/Content/src/LuaBridgeTest/LuaBridgeTest.lua b/tests/lua-tests/Content/src/LuaBridgeTest/LuaBridgeTest.lua index 53243b91cfad..c4dfe0545323 100644 --- a/tests/lua-tests/Content/src/LuaBridgeTest/LuaBridgeTest.lua +++ b/tests/lua-tests/Content/src/LuaBridgeTest/LuaBridgeTest.lua @@ -1,4 +1,4 @@ -local targetPlatform = cc.Application:getInstance():getTargetPlatform() +local targetPlatform = ax.Application:getInstance():getTargetPlatform() local LINE_SPACE = 40 local itemTagBasic = 1000 @@ -9,58 +9,58 @@ local LuaBridgeTestsName = "LuaTableToObjcDictTest", } -local s = cc.Director:getInstance():getWinSize() +local s = ax.Director:getInstance():getWinSize() local function LuaBridgeLayer() - local layer = cc.Layer:create() - local menu = cc.Menu:create() - menu:setPosition(cc.p(0, 0)) - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) + local layer = ax.Layer:create() + local menu = ax.Menu:create() + menu:setPosition(ax.p(0, 0)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) local supportObjectCBridge = false - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) or (ax.PLATFORM_OS_MAC == targetPlatform) then supportObjectCBridge = true end local supportJavaBridge = false - if (cc.PLATFORM_OS_ANDROID == targetPlatform) then + if (ax.PLATFORM_OS_ANDROID == targetPlatform) then supportJavaBridge = true end local function createMenuToBridgeScene() - local menuToBridgeScene = cc.Menu:create() + local menuToBridgeScene = ax.Menu:create() local function toBridgeScene() local scene = LuaBridgeMainTest() if scene ~= nil then - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end - end + end --Create BackMneu - cc.MenuItemFont:setFontName("Arial") - cc.MenuItemFont:setFontSize(24) - local menuItemFont = cc.MenuItemFont:create("Back") - menuItemFont:setPosition(cc.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) + ax.MenuItemFont:setFontName("Arial") + ax.MenuItemFont:setFontSize(24) + local menuItemFont = ax.MenuItemFont:create("Back") + menuItemFont:setPosition(ax.p(VisibleRect:rightBottom().x - 50, VisibleRect:rightBottom().y + 25)) menuItemFont:registerScriptTapHandler(toBridgeScene) - menuToBridgeScene:addChild(menuItemFont) - menuToBridgeScene:setPosition(cc.p(0, 0)) + menuToBridgeScene:addChild(menuItemFont) + menuToBridgeScene:setPosition(ax.p(0, 0)) return menuToBridgeScene end local function newLuaJavaBridge() - local newScene = cc.Scene:create() - local titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) + local newScene = ax.Scene:create() + local titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) newScene:addChild(titleLabel, 1) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(s.width / 2, s.height - 50) titleLabel:setString("LuaJavaBridge Test") - subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16) + subtitleLabel = ax.Label:createWithTTF("", s_thonburiPath, 16) newScene:addChild(subtitleLabel, 1) - subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) subtitleLabel:setPosition(s.width / 2, s.height - 80) subtitleLabel:setString("See the console.") - if (cc.PLATFORM_OS_ANDROID == targetPlatform) then + if (ax.PLATFORM_OS_ANDROID == targetPlatform) then local args = { 2 , 3} local sigs = "(II)I" local luaj = require "axmol.cocos2d.luaj" @@ -88,19 +88,19 @@ local function LuaBridgeLayer() end local function newLuaObjectCBridge() - local newScene = cc.Scene:create() - local titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) + local newScene = ax.Scene:create() + local titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) newScene:addChild(titleLabel, 1) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(s.width / 2, s.height - 50) titleLabel:setString("LuaObjectCBridge Test") - subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16) + subtitleLabel = ax.Label:createWithTTF("", s_thonburiPath, 16) newScene:addChild(subtitleLabel, 1) - subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) subtitleLabel:setPosition(s.width / 2, s.height - 80) subtitleLabel:setString("See the console.") - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) or (ax.PLATFORM_OS_MAC == targetPlatform) then local args = { num1 = 2 , num2 = 3 } local luaoc = require "axmol.cocos2d.luaoc" local className = "LuaObjectCBridgeTest" @@ -123,19 +123,19 @@ local function LuaBridgeLayer() end local function newLuaTableToObjcDict() - local newScene = cc.Scene:create() - local titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) + local newScene = ax.Scene:create() + local titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) newScene:addChild(titleLabel, 1) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(s.width / 2, s.height - 50) titleLabel:setString("LuaTableToObjcDict Test") - subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16) + subtitleLabel = ax.Label:createWithTTF("", s_thonburiPath, 16) newScene:addChild(subtitleLabel, 1) - subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) subtitleLabel:setPosition(s.width / 2, s.height - 80) subtitleLabel:setString("See the console.") - if (cc.PLATFORM_OS_IPHONE == targetPlatform) or (cc.PLATFORM_OS_IPAD == targetPlatform) or (cc.PLATFORM_OS_MAC == targetPlatform) then + if (ax.PLATFORM_OS_IPHONE == targetPlatform) or (ax.PLATFORM_OS_IPAD == targetPlatform) or (ax.PLATFORM_OS_MAC == targetPlatform) then local args = {name = "jett" ,method = "call OC"} local args_tab = {tab = args , name = "table_test"} local luaoc = require "axmol.cocos2d.luaoc" @@ -163,17 +163,17 @@ local function LuaBridgeLayer() local newScene = newLuaBridgeScene(nIdx) if nil ~= newScene then newScene:addChild(createMenuToBridgeScene(),10) - cc.Director:getInstance():replaceScene(newScene) + ax.Director:getInstance():replaceScene(newScene) end end for i = 1, #(LuaBridgeTestsName) do - local item = cc.MenuItemFont:create(LuaBridgeTestsName[i]) + local item = ax.MenuItemFont:create(LuaBridgeTestsName[i]) item:registerScriptTapHandler(menuCallback) item:setPosition(s.width / 2, s.height - i * LINE_SPACE) menu:addChild(item, itemTagBasic + i) if ((i == 1) and (false == supportJavaBridge)) - or ((i == 2) and (false == supportObjectCBridge)) + or ((i == 2) and (false == supportObjectCBridge)) or ((i == 3) and (false == supportObjectCBridge))then item:setEnabled(false) end @@ -188,7 +188,7 @@ end -- LuaBridge Test ------------------------------------- function LuaBridgeMainTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(LuaBridgeLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/LuaLoaderTest/LuaLoaderTest.lua b/tests/lua-tests/Content/src/LuaLoaderTest/LuaLoaderTest.lua index c05de007d7d0..cfdb883d3eb5 100644 --- a/tests/lua-tests/Content/src/LuaLoaderTest/LuaLoaderTest.lua +++ b/tests/lua-tests/Content/src/LuaLoaderTest/LuaLoaderTest.lua @@ -11,13 +11,13 @@ local function TestNode() local function title() return "LuaLoaderTest" end - local node = cc.Node:create() + local node = ax.Node:create() local function onEnter() - local titleLabel = cc.Label:createWithTTF(title(), "fonts/arial.ttf", 32) + local titleLabel = ax.Label:createWithTTF(title(), "fonts/arial.ttf", 32) node:addChild(titleLabel, 1) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) - titleLabel:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 50) ) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) + titleLabel:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 50) ) local oldPath = package.path local result = {} for _,tab in ipairs(testPatches) do @@ -26,9 +26,9 @@ local function TestNode() result[#result+1] = 'Loading by path "'..tab[1]..'", filename "'..tab[2]..'": '..(ok and 'success' or 'failure') package.path = oldPath end - local label = cc.Label:createWithTTF(table.concat(result, '\n'), "fonts/Marker Felt.ttf", 10) + local label = ax.Label:createWithTTF(table.concat(result, '\n'), "fonts/Marker Felt.ttf", 10) node:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(VisibleRect:center()) end @@ -39,13 +39,13 @@ local function TestNode() end node:registerScriptHandler(onNodeEvent) - + return node end function LuaLoaderMain() cclog("LuaLoaderMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(TestNode()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/MaterialSystemTest/MaterialSystemTest.lua b/tests/lua-tests/Content/src/MaterialSystemTest/MaterialSystemTest.lua index ac19354d5169..c926dac7170e 100644 --- a/tests/lua-tests/Content/src/MaterialSystemTest/MaterialSystemTest.lua +++ b/tests/lua-tests/Content/src/MaterialSystemTest/MaterialSystemTest.lua @@ -35,7 +35,7 @@ end ----MaterialSystemBaseTest ---------------------------------------- local MaterialSystemBaseTest = class("MaterialSystemBaseTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -82,11 +82,11 @@ function Material_Sprite3DTest:subtitle() end function Material_Sprite3DTest:onEnter() - local sprite = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite:setScale(8.0) sprite:setTexture("MeshRendererTest/boss.png") self:addChild(sprite) - sprite:setNormalizedPosition(cc.p(0.5,0.5)) + sprite:setNormalizedPosition(ax.p(0.5,0.5)) end @@ -100,7 +100,7 @@ function Material_MultipleSprite3D:subtitle() end function Material_MultipleSprite3D:onEnter() - local names = + local names = { "MeshRendererTest/ReskinGirl.c3b", "MeshRendererTest/ReskinGirl.c3b", @@ -114,12 +114,12 @@ function Material_MultipleSprite3D:onEnter() local totalNames = #names - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() for i = 1 , totalNames do - local sprite = cc.Sprite3D:create(names[i]) + local sprite = ax.Sprite3D:create(names[i]) self:addChild(sprite) - sprite:setPosition(cc.p((size.width/(totalNames+1)) * i, size.height/4)) + sprite:setPosition(ax.p((size.width/(totalNames+1)) * i, size.height/4)) sprite:setScale(3) end end @@ -135,45 +135,45 @@ end function Material_2DEffects:onEnter() - local properties = cc.Properties:createNonRefCounted("Materials/2d_effects.material#sample") + local properties = ax.Properties:createNonRefCounted("Materials/2d_effects.material#sample") -- Print the properties of every namespace within this one. -- TODO printProperties(properties, 0) - local mat1 = cc.Material:createWithProperties(properties) + local mat1 = ax.Material:createWithProperties(properties) - local spriteBlur = cc.Sprite:create("Images/grossini.png") - spriteBlur:setNormalizedPosition(cc.p(0.2, 0.5)) + local spriteBlur = ax.Sprite:create("Images/grossini.png") + spriteBlur:setNormalizedPosition(ax.p(0.2, 0.5)) self:addChild(spriteBlur) spriteBlur:setProgramState(mat1:getTechniqueByName("blur"):getPassByIndex(0):getProgramState()) - local spriteOutline = cc.Sprite:create("Images/grossini.png") - spriteOutline:setNormalizedPosition(cc.p(0.4, 0.5)) + local spriteOutline = ax.Sprite:create("Images/grossini.png") + spriteOutline:setNormalizedPosition(ax.p(0.4, 0.5)) self:addChild(spriteOutline) spriteOutline:setProgramState(mat1:getTechniqueByName("outline"):getPassByIndex(0):getProgramState()) - local spriteNoise = cc.Sprite:create("Images/grossini.png") - spriteNoise:setNormalizedPosition(cc.p(0.6, 0.5)) + local spriteNoise = ax.Sprite:create("Images/grossini.png") + spriteNoise:setNormalizedPosition(ax.p(0.6, 0.5)) self:addChild(spriteNoise) spriteNoise:setProgramState(mat1:getTechniqueByName("noise"):getPassByIndex(0):getProgramState()) - local spriteEdgeDetect = cc.Sprite:create("Images/grossini.png") - spriteEdgeDetect:setNormalizedPosition(cc.p(0.8, 0.5)) + local spriteEdgeDetect = ax.Sprite:create("Images/grossini.png") + spriteEdgeDetect:setNormalizedPosition(ax.p(0.8, 0.5)) self:addChild(spriteEdgeDetect) spriteEdgeDetect:setProgramState(mat1:getTechniqueByName("edge_detect"):getPassByIndex(0):getProgramState()) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() local uTimeLoc = spriteNoise:getProgramState():getUniformLocation("u_Time") self._schedulerEntry = scheduler:scheduleScriptFunc(function(dt) - local time = cc.Director:getInstance():getTotalFrames() * cc.Director:getInstance():getAnimationInterval() - local random = cc.vec4(time / 10., time, time * 2, time * 4) - spriteNoise:getProgramState():setUniform(uTimeLoc, cc.bytearray.from_vec4(random)); + local time = ax.Director:getInstance():getTotalFrames() * ax.Director:getInstance():getAnimationInterval() + local random = ax.vec4(time / 10., time, time * 2, time * 4) + spriteNoise:getProgramState():setUniform(uTimeLoc, ax.bytearray.from_vec4(random)); end, 0, false) end function Material_2DEffects:onExit() - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(self._schedulerEntry) end @@ -187,22 +187,22 @@ function Material_setTechnique:subtitle() end function Material_setTechnique:onEnter() - local sprite = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite:setScale(6) self:addChild(sprite) - sprite:setNormalizedPosition(cc.p(0.5,0.5)) + sprite:setNormalizedPosition(ax.p(0.5,0.5)) - local mat = cc.Material:createWithFilename("Materials/3d_effects.material") + local mat = ax.Material:createWithFilename("Materials/3d_effects.material") sprite:setMaterial(mat) --lights - local light1 = cc.AmbientLight:create(cc.c3b(255, 0, 0)) + local light1 = ax.AmbientLight:create(ax.color32(255, 0, 0)) self:addChild(light1) - local light2 = cc.DirectionLight:create(cc.vec3(-1,1,0), cc.c3b(0, 255, 0)) + local light2 = ax.DirectionLight:create(ax.vec3(-1,1,0), ax.color32(0, 255, 0)) self:addChild(light2) local techniqueState = 0 - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() self._schedulerEntry = scheduler:scheduleScriptFunc(function(dt) if 0 == techniqueState then sprite:getMaterial(0):setTechnique("lit") @@ -217,15 +217,15 @@ function Material_setTechnique:onEnter() techniqueState = 0 end end, 1, false) - - local rot = cc.RotateBy:create(5, cc.vec3(30,60,270)) - local repeatAction = cc.RepeatForever:create(rot) + + local rot = ax.RotateBy:create(5, ax.vec3(30,60,270)) + local repeatAction = ax.RepeatForever:create(rot) sprite:runAction(repeatAction) end function Material_setTechnique:onExit() - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() scheduler:unscheduleScriptEntry(self._schedulerEntry) end @@ -239,31 +239,31 @@ function Material_clone:subtitle() end function Material_clone:onEnter() - local sprite = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite:setScale(3) self:addChild(sprite) - sprite:setNormalizedPosition(cc.p(0.25, 0.5)) + sprite:setNormalizedPosition(ax.p(0.25, 0.5)) - local mat = cc.Material:createWithFilename("Materials/3d_effects.material") + local mat = ax.Material:createWithFilename("Materials/3d_effects.material") sprite:setMaterial(mat) - local rot = cc.RotateBy:create(5, cc.vec3(360,240,120)) - local repeatAction = cc.RepeatForever:create(rot) + local rot = ax.RotateBy:create(5, ax.vec3(360,240,120)) + local repeatAction = ax.RepeatForever:create(rot) sprite:runAction(repeatAction) -- sprite 2... using same material - local sprite2 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite2 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite2:setScale(3) self:addChild(sprite2) - sprite2:setNormalizedPosition(cc.p(0.5, 0.5)) + sprite2:setNormalizedPosition(ax.p(0.5, 0.5)) sprite2:setMaterial(mat) sprite2:runAction(repeatAction:clone()) -- sprite 3... using cloned material - local sprite3 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite3 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite3:setScale(3) self:addChild(sprite3) - sprite3:setNormalizedPosition(cc.p(0.75, 0.5)) + sprite3:setNormalizedPosition(ax.p(0.75, 0.5)) local mat2 = mat:clone() sprite3:setMaterial(mat2) sprite3:runAction(repeatAction:clone()) @@ -283,31 +283,31 @@ function Material_clone:subtitle() end function Material_clone:onEnter() - local sprite = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite:setScale(3) self:addChild(sprite) - sprite:setNormalizedPosition(cc.p(0.25, 0.5)) + sprite:setNormalizedPosition(ax.p(0.25, 0.5)) - local mat = cc.Material:createWithFilename("Materials/3d_effects.material") + local mat = ax.Material:createWithFilename("Materials/3d_effects.material") sprite:setMaterial(mat) - local rot = cc.RotateBy:create(5, cc.vec3(360,240,120)) - local repeatAction = cc.RepeatForever:create(rot) + local rot = ax.RotateBy:create(5, ax.vec3(360,240,120)) + local repeatAction = ax.RepeatForever:create(rot) sprite:runAction(repeatAction) -- sprite 2... using same material - local sprite2 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite2 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite2:setScale(3) self:addChild(sprite2) - sprite2:setNormalizedPosition(cc.p(0.5, 0.5)) + sprite2:setNormalizedPosition(ax.p(0.5, 0.5)) sprite2:setMaterial(mat) sprite2:runAction(repeatAction:clone()) -- sprite 3... using cloned material - local sprite3 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite3 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite3:setScale(3) self:addChild(sprite3) - sprite3:setNormalizedPosition(cc.p(0.75, 0.5)) + sprite3:setNormalizedPosition(ax.p(0.75, 0.5)) local mat2 = mat:clone() sprite3:setMaterial(mat2) sprite3:runAction(repeatAction:clone()) @@ -330,8 +330,8 @@ function Material_parsePerformance:onEnter() local begin = os.clock() for i = 1,5000 do - cc.Material:createWithFilename("Materials/2d_effects.material") - cc.Material:createWithFilename("Materials/3d_effects.material") + ax.Material:createWithFilename("Materials/2d_effects.material") + ax.Material:createWithFilename("Materials/3d_effects.material") end print("Parsing took: ", os.clock() - begin) @@ -341,10 +341,10 @@ end ----Material_clone ---------------------------------------- function MaterialSystemTest() - - local scene = cc.Scene:createWithPhysics() - Helper.createFunctionTable = + local scene = ax.Scene:createWithPhysics() + + Helper.createFunctionTable = { Material_2DEffects.create, Material_setTechnique.create, @@ -359,4 +359,4 @@ function MaterialSystemTest() scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/MenuTest/MenuTest.lua b/tests/lua-tests/Content/src/MenuTest/MenuTest.lua index a9b406e16525..153607f5c5c4 100644 --- a/tests/lua-tests/Content/src/MenuTest/MenuTest.lua +++ b/tests/lua-tests/Content/src/MenuTest/MenuTest.lua @@ -21,14 +21,14 @@ local MID_BACKCALLBACK = 1009 local function MenuLayerMainMenu() local m_disabledItem = nil - local ret = cc.Layer:create() + local ret = ax.Layer:create() -- Font Item - local spriteNormal = cc.Sprite:create(s_MenuItem, cc.rect(0,23*2,115,23)) - local spriteSelected = cc.Sprite:create(s_MenuItem, cc.rect(0,23*1,115,23)) - local spriteDisabled = cc.Sprite:create(s_MenuItem, cc.rect(0,23*0,115,23)) + local spriteNormal = ax.Sprite:create(s_MenuItem, ax.rect(0,23*2,115,23)) + local spriteSelected = ax.Sprite:create(s_MenuItem, ax.rect(0,23*1,115,23)) + local spriteDisabled = ax.Sprite:create(s_MenuItem, ax.rect(0,23*0,115,23)) - local item1 = cc.MenuItemSprite:create(spriteNormal, spriteSelected, spriteDisabled) + local item1 = ax.MenuItemSprite:create(spriteNormal, spriteSelected, spriteDisabled) local function menuCallback(sender) cclog("menuCallback...") @@ -41,16 +41,16 @@ local function MenuLayerMainMenu() ret:getParent():switchTo(2, false) end - local item2 = cc.MenuItemImage:create(s_SendScore, s_PressSendScore) + local item2 = ax.MenuItemImage:create(s_SendScore, s_PressSendScore) item2:registerScriptTapHandler(menuCallback2) local schedulerEntry = nil - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() local function allowTouches(dt) - local pDirector = cc.Director:getInstance() - --pDirector:getTouchDispatcher():setPriority(cc.MENU_HANDLER_PRIORITY +1, ret) - if nil ~= schedulerEntry then + local pDirector = ax.Director:getInstance() + --pDirector:getTouchDispatcher():setPriority(ax.MENU_HANDLER_PRIORITY +1, ret) + if nil ~= schedulerEntry then scheduler:unscheduleScriptEntry(schedulerEntry) schedulerEntry = nil end @@ -60,51 +60,51 @@ local function MenuLayerMainMenu() local function menuCallbackDisabled(sender) -- hijack all touch events for 5 seconds - local pDirector = cc.Director:getInstance() - --pDirector:getTouchDispatcher():setPriority(cc.MENU_HANDLER_PRIORITY -1, ret) + local pDirector = ax.Director:getInstance() + --pDirector:getTouchDispatcher():setPriority(ax.MENU_HANDLER_PRIORITY -1, ret) schedulerEntry = scheduler:scheduleScriptFunc(allowTouches, 5, false) cclog("TOUCHES DISABLED FOR 5 SECONDS") end -- Label Item (LabelAtlas) - local labelAtlas = cc.LabelAtlas:_create("0123456789", "fonts/labelatlas.png", 16, 24, string.byte('.')) - local item3 = cc.MenuItemLabel:create(labelAtlas) + local labelAtlas = ax.LabelAtlas:_create("0123456789", "fonts/labelatlas.png", 16, 24, string.byte('.')) + local item3 = ax.MenuItemLabel:create(labelAtlas) item3:registerScriptTapHandler(menuCallbackDisabled) - item3:setDisabledColor( cc.c3b(32,32,64) ) - item3:setColor( cc.c3b(200,200,255) ) + item3:setDisabledColor( ax.color32(32,32,64) ) + item3:setColor( ax.color32(200,200,255) ) local function menuCallbackEnable(sender) m_disabledItem:setEnabled(not m_disabledItem:isEnabled() ) end -- Font Item - local item4 = cc.MenuItemFont:create("I toggle enable items") + local item4 = ax.MenuItemFont:create("I toggle enable items") item4:registerScriptTapHandler(menuCallbackEnable) item4:setFontSizeObj(20) - cc.MenuItemFont:setFontName("Marker Felt") + ax.MenuItemFont:setFontName("Marker Felt") local function menuCallbackConfig(sender) ret:getParent():switchTo(3, false) end - -- Label Item (cc.LabelBMFont) - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "configuration") - label:setAnchorPoint(cc.p(0.5, 0.5)) - local item5 = cc.MenuItemLabel:create(label) + -- Label Item (ax.LabelBMFont) + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "configuration") + label:setAnchorPoint(ax.p(0.5, 0.5)) + local item5 = ax.MenuItemLabel:create(label) item5:registerScriptTapHandler(menuCallbackConfig) -- Testing issue #500 item5:setScale( 0.8 ) -- Events - cc.MenuItemFont:setFontName("Marker Felt") + ax.MenuItemFont:setFontName("Marker Felt") local function menuCallbackBugsTest(pSender) ret:getParent():switchTo(4, false) end -- Bugs Item - local item6 = cc.MenuItemFont:create("Bugs") + local item6 = ax.MenuItemFont:create("Bugs") item6:registerScriptTapHandler(menuCallbackBugsTest) local function onQuit(sender) @@ -112,22 +112,22 @@ local function MenuLayerMainMenu() end -- Font Item - local item7 = cc.MenuItemFont:create("Quit") + local item7 = ax.MenuItemFont:create("Quit") item7:registerScriptTapHandler(onQuit) local function menuMovingCallback(pSender) ret:getParent():switchTo(5, false) end - local item8 = cc.MenuItemFont:create("Remove menu item when moving") + local item8 = ax.MenuItemFont:create("Remove menu item when moving") item8:registerScriptTapHandler(menuMovingCallback) - local color_action = cc.TintBy:create(0.5, 0, -255, -255) + local color_action = ax.TintBy:create(0.5, 0, -255, -255) local color_back = color_action:reverse() - local seq = cc.Sequence:create(color_action, color_back) - item7:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(color_action, color_back) + item7:runAction(ax.RepeatForever:create(seq)) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) @@ -141,7 +141,7 @@ local function MenuLayerMainMenu() menu:alignItemsVertically() -- elastic effect - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local i = 0 local child = nil @@ -159,8 +159,8 @@ local function MenuLayerMainMenu() if i % 2 == 0 then offset = 0-offset end - child:setPosition( cc.p( dstPointX + offset, dstPointY) ) - child:runAction( cc.EaseElasticOut:create(cc.MoveBy:create(2, cc.p(dstPointX - offset,0)), 0.35) ) + child:setPosition( ax.p( dstPointX + offset, dstPointY) ) + child:runAction( ax.EaseElasticOut:create(ax.MoveBy:create(2, ax.p(dstPointX - offset,0)), 0.35) ) end m_disabledItem = item3 @@ -169,7 +169,7 @@ local function MenuLayerMainMenu() m_disabledItem:setEnabled( false ) ret:addChild(menu) - menu:setPosition(cc.p(s.width/2, s.height/2)) + menu:setPosition(ax.p(s.width/2, s.height/2)) -- local schedulerEntry = nil local function onNodeEvent(event) @@ -194,7 +194,7 @@ end -- -------------------------------------------------------------------- local function MenuLayer2() - local ret = cc.Layer:create() + local ret = ax.Layer:create() local m_centeredMenu = nil local m_alignedH = false @@ -207,12 +207,12 @@ local function MenuLayer2() -- TIP: if no padding, padding = 5 menu:alignItemsHorizontally() local x, y = menu:getPosition() - menu:setPosition( cc.pAdd(cc.p(x, y), cc.p(0,30)) ) + menu:setPosition( ax.pAdd(ax.p(x, y), ax.p(0,30)) ) else -- TIP: but padding is configurable menu:alignItemsHorizontallyWithPadding(40) local x, y = menu:getPosition() - menu:setPosition( cc.pSub(cc.p(x, y), cc.p(0,30)) ) + menu:setPosition( ax.pSub(ax.p(x, y), ax.p(0,30)) ) end end end @@ -226,12 +226,12 @@ local function MenuLayer2() -- TIP: if no padding, padding = 5 menu:alignItemsVertically() local x, y = menu:getPosition() - menu:setPosition( cc.pAdd(cc.p(x, y), cc.p(100,0)) ) + menu:setPosition( ax.pAdd(ax.p(x, y), ax.p(100,0)) ) else -- TIP: but padding is configurable menu:alignItemsVerticallyWithPadding(40) local x, y = menu:getPosition() - menu:setPosition( cc.pSub(cc.p(x, y), cc.p(100,0)) ) + menu:setPosition( ax.pSub(ax.p(x, y), ax.p(100,0)) ) end end end @@ -262,33 +262,33 @@ local function MenuLayer2() local i = 0 for i=0, 1 do - local item1 = cc.MenuItemImage:create(s_PlayNormal, s_PlaySelect) + local item1 = ax.MenuItemImage:create(s_PlayNormal, s_PlaySelect) item1:registerScriptTapHandler(menuCallback) - local item2 = cc.MenuItemImage:create(s_HighNormal, s_HighSelect) + local item2 = ax.MenuItemImage:create(s_HighNormal, s_HighSelect) item2:registerScriptTapHandler(menuCallbackOpacity) - local item3 = cc.MenuItemImage:create(s_AboutNormal, s_AboutSelect) + local item3 = ax.MenuItemImage:create(s_AboutNormal, s_AboutSelect) item3:registerScriptTapHandler(menuCallbackAlign) item1:setScaleX( 1.5 ) item2:setScaleX( 0.5 ) item3:setScaleX( 0.5 ) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - local s = cc.Director:getInstance():getWinSize() - menu:setPosition(cc.p(s.width/2, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + menu:setPosition(ax.p(s.width/2, s.height/2)) menu:setTag( kTagMenu ) ret:addChild(menu, 0, 100+i) local x, y = menu:getPosition() - m_centeredMenu = cc.p(x, y) + m_centeredMenu = ax.p(x, y) end m_alignedH = true @@ -304,7 +304,7 @@ end -------------------------------------------------------------------- local function MenuLayer3() local m_disabledItem = nil - local ret = cc.Layer:create() + local ret = ax.Layer:create() local function menuCallback(sender) ret:getParent():switchTo(0, false) end @@ -319,56 +319,56 @@ local function MenuLayer3() cclog("MenuItemSprite clicked") end - cc.MenuItemFont:setFontName("Marker Felt") - cc.MenuItemFont:setFontSize(28) + ax.MenuItemFont:setFontName("Marker Felt") + ax.MenuItemFont:setFontSize(28) - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Enable AtlasItem") - label:setAnchorPoint(cc.p(0.5, 0.5)) - local item1 = cc.MenuItemLabel:create(label) + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "Enable AtlasItem") + label:setAnchorPoint(ax.p(0.5, 0.5)) + local item1 = ax.MenuItemLabel:create(label) item1:registerScriptTapHandler(menuCallback2) - local item2 = cc.MenuItemFont:create("--- Go Back ---") + local item2 = ax.MenuItemFont:create("--- Go Back ---") item2:registerScriptTapHandler(menuCallback) - local spriteNormal = cc.Sprite:create(s_MenuItem, cc.rect(0,23*2,115,23)) - local spriteSelected = cc.Sprite:create(s_MenuItem, cc.rect(0,23*1,115,23)) - local spriteDisabled = cc.Sprite:create(s_MenuItem, cc.rect(0,23*0,115,23)) + local spriteNormal = ax.Sprite:create(s_MenuItem, ax.rect(0,23*2,115,23)) + local spriteSelected = ax.Sprite:create(s_MenuItem, ax.rect(0,23*1,115,23)) + local spriteDisabled = ax.Sprite:create(s_MenuItem, ax.rect(0,23*0,115,23)) - local item3 = cc.MenuItemSprite:create(spriteNormal, spriteSelected, spriteDisabled) + local item3 = ax.MenuItemSprite:create(spriteNormal, spriteSelected, spriteDisabled) item3:registerScriptTapHandler(menuCallback3) m_disabledItem = item3 item3:retain() m_disabledItem:setEnabled( false ) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition( cc.p(0,0) ) + menu:setPosition( ax.p(0,0) ) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - item1:setPosition( cc.p(s.width/2 - 150, s.height/2) ) - item2:setPosition( cc.p(s.width/2 - 200, s.height/2) ) - item3:setPosition( cc.p(s.width/2, s.height/2 - 100) ) + item1:setPosition( ax.p(s.width/2 - 150, s.height/2) ) + item2:setPosition( ax.p(s.width/2 - 200, s.height/2) ) + item3:setPosition( ax.p(s.width/2, s.height/2 - 100) ) - local jump = cc.JumpBy:create(3, cc.p(400,0), 50, 4) - item2:runAction( cc.RepeatForever:create(cc.Sequence:create( jump, jump:reverse()))) + local jump = ax.JumpBy:create(3, ax.p(400,0), 50, 4) + item2:runAction( ax.RepeatForever:create(ax.Sequence:create( jump, jump:reverse()))) - local spin1 = cc.RotateBy:create(3, 360) + local spin1 = ax.RotateBy:create(3, 360) local spin2 = spin1:clone() local spin3 = spin1:clone() - item1:runAction( cc.RepeatForever:create(spin1) ) - item2:runAction( cc.RepeatForever:create(spin2) ) - item3:runAction( cc.RepeatForever:create(spin3) ) + item1:runAction( ax.RepeatForever:create(spin1) ) + item2:runAction( ax.RepeatForever:create(spin2) ) + item3:runAction( ax.RepeatForever:create(spin3) ) ret:addChild( menu ) - menu:setPosition(cc.p(0,0)) + menu:setPosition(ax.p(0,0)) local function onNodeEvent(event) if event == "exit" then @@ -390,14 +390,14 @@ end -- -------------------------------------------------------------------- local function MenuLayer4() - local ret = cc.Layer:create() - cc.MenuItemFont:setFontName("American Typewriter") - cc.MenuItemFont:setFontSize(18) - local title1 = cc.MenuItemFont:create("Sound") + local ret = ax.Layer:create() + ax.MenuItemFont:setFontName("American Typewriter") + ax.MenuItemFont:setFontSize(18) + local title1 = ax.MenuItemFont:create("Sound") title1:setEnabled(false) - cc.MenuItemFont:setFontName( "Marker Felt" ) - cc.MenuItemFont:setFontSize(34) - local item1 = cc.MenuItemToggle:create(cc.MenuItemFont:create( "On" )) + ax.MenuItemFont:setFontName( "Marker Felt" ) + ax.MenuItemFont:setFontSize(34) + local item1 = ax.MenuItemToggle:create(ax.MenuItemFont:create( "On" )) local function menuCallback(tag, sender) cclog("selected item: tag: %d, index:%d", tag, sender:getSelectedIndex() ) @@ -408,52 +408,52 @@ local function MenuLayer4() end item1:registerScriptTapHandler(menuCallback) - item1:addSubItem(cc.MenuItemFont:create( "Off")) + item1:addSubItem(ax.MenuItemFont:create( "Off")) - cc.MenuItemFont:setFontName( "American Typewriter" ) - cc.MenuItemFont:setFontSize(18) - local title2 = cc.MenuItemFont:create( "Music" ) + ax.MenuItemFont:setFontName( "American Typewriter" ) + ax.MenuItemFont:setFontSize(18) + local title2 = ax.MenuItemFont:create( "Music" ) title2:setEnabled(false) - cc.MenuItemFont:setFontName( "Marker Felt" ) - cc.MenuItemFont:setFontSize(34) - local item2 = cc.MenuItemToggle:create(cc.MenuItemFont:create( "On" )) + ax.MenuItemFont:setFontName( "Marker Felt" ) + ax.MenuItemFont:setFontSize(34) + local item2 = ax.MenuItemToggle:create(ax.MenuItemFont:create( "On" )) item2:registerScriptTapHandler(menuCallback) - item2:addSubItem(cc.MenuItemFont:create( "Off")) + item2:addSubItem(ax.MenuItemFont:create( "Off")) - cc.MenuItemFont:setFontName( "American Typewriter" ) - cc.MenuItemFont:setFontSize(18) - local title3 = cc.MenuItemFont:create( "Quality" ) + ax.MenuItemFont:setFontName( "American Typewriter" ) + ax.MenuItemFont:setFontSize(18) + local title3 = ax.MenuItemFont:create( "Quality" ) title3:setEnabled( false ) - cc.MenuItemFont:setFontName( "Marker Felt" ) - cc.MenuItemFont:setFontSize(34) - local item3 = cc.MenuItemToggle:create(cc.MenuItemFont:create( "High" )) + ax.MenuItemFont:setFontName( "Marker Felt" ) + ax.MenuItemFont:setFontSize(34) + local item3 = ax.MenuItemToggle:create(ax.MenuItemFont:create( "High" )) item3:registerScriptTapHandler(menuCallback) - item3:addSubItem(cc.MenuItemFont:create( "Low" )) + item3:addSubItem(ax.MenuItemFont:create( "Low" )) - cc.MenuItemFont:setFontName( "American Typewriter" ) - cc.MenuItemFont:setFontSize(18) - local title4 = cc.MenuItemFont:create( "Orientation" ) + ax.MenuItemFont:setFontName( "American Typewriter" ) + ax.MenuItemFont:setFontSize(18) + local title4 = ax.MenuItemFont:create( "Orientation" ) title4:setEnabled(false) - cc.MenuItemFont:setFontName( "Marker Felt" ) - cc.MenuItemFont:setFontSize(34) - local item4 = cc.MenuItemToggle:create(cc.MenuItemFont:create( "Off"), - cc.MenuItemFont:create( "33%" ), - cc.MenuItemFont:create( "66%" ), - cc.MenuItemFont:create( "100%")) + ax.MenuItemFont:setFontName( "Marker Felt" ) + ax.MenuItemFont:setFontSize(34) + local item4 = ax.MenuItemToggle:create(ax.MenuItemFont:create( "Off"), + ax.MenuItemFont:create( "33%" ), + ax.MenuItemFont:create( "66%" ), + ax.MenuItemFont:create( "100%")) item4:registerScriptTapHandler(menuCallback) -- you can change the one of the items by doing this item4:setSelectedIndex( 2 ) - cc.MenuItemFont:setFontName( "Marker Felt" ) - cc.MenuItemFont:setFontSize( 34 ) + ax.MenuItemFont:setFontName( "Marker Felt" ) + ax.MenuItemFont:setFontSize( 34 ) - local label = cc.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "go back") - label:setAnchorPoint(cc.p(0.5, 0.5)) - local back = cc.MenuItemLabel:create(label) + local label = ax.Label:createWithBMFont("fonts/bitmapFontTest3.fnt", "go back") + label:setAnchorPoint(ax.p(0.5, 0.5)) + local back = ax.MenuItemLabel:create(label) back:registerScriptTapHandler(backCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(title1) menu:addChild(title2) @@ -469,14 +469,14 @@ local function MenuLayer4() ret:addChild(menu) - local s = cc.Director:getInstance():getWinSize() - menu:setPosition(cc.p(s.width/2, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + menu:setPosition(ax.p(s.width/2, s.height/2)) return ret end -- BugsTest local function BugsTest() - local ret = cc.Layer:create() + local ret = ax.Layer:create() local function issue1410MenuCallback(tag, pSender) local menu = pSender:getParent() menu:setEnabled(false) @@ -496,53 +496,53 @@ local function BugsTest() end - local issue1410 = cc.MenuItemFont:create("Issue 1410") + local issue1410 = ax.MenuItemFont:create("Issue 1410") issue1410:registerScriptTapHandler(issue1410MenuCallback) - local issue1410_2 = cc.MenuItemFont:create("Issue 1410 #2") + local issue1410_2 = ax.MenuItemFont:create("Issue 1410 #2") issue1410_2:registerScriptTapHandler(issue1410v2MenuCallback) - local back = cc.MenuItemFont:create("Back") + local back = ax.MenuItemFont:create("Back") back:registerScriptTapHandler(backMenuCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(issue1410) menu:addChild(issue1410_2) menu:addChild(back) ret:addChild(menu) menu:alignItemsVertically() - local s = cc.Director:getInstance():getWinSize() - menu:setPosition(cc.p(s.width/2, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + menu:setPosition(ax.p(s.width/2, s.height/2)) return ret end local function RemoveMenuItemWhenMove() - local ret = cc.Layer:create() - local s = cc.Director:getInstance():getWinSize() + local ret = ax.Layer:create() + local s = ax.Director:getInstance():getWinSize() - local label = cc.Label:createWithTTF("click item and move, should not crash", s_arialPath, 20) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, s.height - 30)) + local label = ax.Label:createWithTTF("click item and move, should not crash", s_arialPath, 20) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, s.height - 30)) ret:addChild(label) - local item = cc.MenuItemFont:create("item 1") + local item = ax.MenuItemFont:create("item 1") item:retain() - local back = cc.MenuItemFont:create("go back") + local back = ax.MenuItemFont:create("go back") local function goBack(tag, pSender) ret:getParent():switchTo(0, false) end back:registerScriptTapHandler(goBack) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item) menu:addChild(back) ret:addChild(menu) menu:alignItemsVertically() - menu:setPosition(cc.p(s.width/2, s.height/2)) + menu:setPosition(ax.p(s.width/2, s.height/2)) local function onTouchBegan(touch, event) return true @@ -556,9 +556,9 @@ local function RemoveMenuItemWhenMove() end end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED ) local eventDispatcher = ret:getEventDispatcher() eventDispatcher:addEventListenerWithFixedPriority(listener, -129) @@ -575,7 +575,7 @@ end function MenuTestMain() cclog("MenuTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() local pLayer1 = MenuLayerMainMenu() local pLayer2 = MenuLayer2() @@ -585,7 +585,7 @@ function MenuTestMain() local pLayer5 = BugsTest() local pLayer6 = RemoveMenuItemWhenMove() - local layer = cc.LayerMultiplex:create(pLayer1, + local layer = ax.LayerMultiplex:create(pLayer1, pLayer2, pLayer3, pLayer4, diff --git a/tests/lua-tests/Content/src/MotionStreakTest/MotionStreakTest.lua b/tests/lua-tests/Content/src/MotionStreakTest/MotionStreakTest.lua index ed25aabba64a..f8ab9eac12ac 100644 --- a/tests/lua-tests/Content/src/MotionStreakTest/MotionStreakTest.lua +++ b/tests/lua-tests/Content/src/MotionStreakTest/MotionStreakTest.lua @@ -3,8 +3,8 @@ local streak = nil local titleLabel = nil local subtitleLabel = nil -local s = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local s = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local firstTick = nil @@ -18,14 +18,14 @@ local function modeCallback(sender) end local function getBaseLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() - local itemMode = cc.MenuItemToggle:create(cc.MenuItemFont:create("Use High Quality Mode")) - itemMode:addSubItem(cc.MenuItemFont:create("Use Fast Mode")) + local itemMode = ax.MenuItemToggle:create(ax.MenuItemFont:create("Use High Quality Mode")) + itemMode:addSubItem(ax.MenuItemFont:create("Use Fast Mode")) itemMode:registerScriptTapHandler(modeCallback) - local menuMode = cc.Menu:create() + local menuMode = ax.Menu:create() menuMode:addChild(itemMode) - menuMode:setPosition(cc.p(s.width / 2, s.height / 4)) + menuMode:setPosition(ax.p(s.width / 2, s.height / 4)) layer:addChild(menuMode) Helper.initWithLayer(layer) @@ -47,7 +47,7 @@ local function MotionStreakTest1_update(dt) return end - streak:setPosition(target:convertToWorldSpace(cc.p(0, 0))) + streak:setPosition(target:convertToWorldSpace(ax.p(0, 0))) end local function MotionStreakTest1_onEnterOrExit(tag) @@ -61,30 +61,30 @@ end local function MotionStreakTest1() local layer = getBaseLayer() - root = cc.Sprite:create(s_pPathR1) + root = ax.Sprite:create(s_pPathR1) layer:addChild(root, 1) - root:setPosition(cc.p(s.width / 2, s.height / 2)) + root:setPosition(ax.p(s.width / 2, s.height / 2)) - target = cc.Sprite:create(s_pPathR1) + target = ax.Sprite:create(s_pPathR1) root:addChild(target) - target:setPosition(cc.p(s.width / 4, 0)) + target:setPosition(ax.p(s.width / 4, 0)) - streak = cc.MotionStreak:create(2, 3, 32, cc.c3b(0, 255, 0), s_streak) + streak = ax.MotionStreak:create(2, 3, 32, ax.color32(0, 255, 0), s_streak) layer:addChild(streak) - local a1 = cc.RotateBy:create(2, 360) + local a1 = ax.RotateBy:create(2, 360) - local action1 = cc.RepeatForever:create(a1) - local motion = cc.MoveBy:create(2, cc.p(100,0)) - root:runAction(cc.RepeatForever:create(cc.Sequence:create(motion, motion:reverse()))) + local action1 = ax.RepeatForever:create(a1) + local motion = ax.MoveBy:create(2, ax.p(100,0)) + root:runAction(ax.RepeatForever:create(ax.Sequence:create(motion, motion:reverse()))) root:runAction(action1) - local colorAction = cc.RepeatForever:create(cc.Sequence:create(cc.TintTo:create(0.2, 255, 0, 0), - cc.TintTo:create(0.2, 0, 255, 0), - cc.TintTo:create(0.2, 0, 0, 255), - cc.TintTo:create(0.2, 0, 255, 255), - cc.TintTo:create(0.2, 255, 255, 0), - cc.TintTo:create(0.2, 255, 255, 255))) + local colorAction = ax.RepeatForever:create(ax.Sequence:create(ax.TintTo:create(0.2, ax.color32(255, 0, 0)), + ax.TintTo:create(0.2, ax.color32(0, 255, 0)), + ax.TintTo:create(0.2, ax.color32(0, 0, 255)), + ax.TintTo:create(0.2, ax.color32(0, 255, 255)), + ax.TintTo:create(0.2, ax.color32(255, 255, 0)), + ax.TintTo:create(0.2, ax.color32(255, 255, 255)))) streak:runAction(colorAction) @@ -101,17 +101,17 @@ end local function MotionStreakTest2() local layer = getBaseLayer() - streak = cc.MotionStreak:create(3, 3, 64, cc.c3b(255, 255, 255), s_streak) + streak = ax.MotionStreak:create(3, 3, 64, ax.color32(255, 255, 255), s_streak) layer:addChild(streak) - streak:setPosition(cc.p(s.width / 2, s.height / 2)) + streak:setPosition(ax.p(s.width / 2, s.height / 2)) local function onTouchesMoved(touches, event) streak:setPosition( touches[1]:getLocation() ) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -136,7 +136,7 @@ local function Issue1358_update(dt) end fAngle = fAngle + 1.0 streak:setPosition( - cc.p(center.x + math.cos(fAngle / 180 * math.pi) * fRadius, center.y + math.sin(fAngle/ 180 * math.pi) * fRadius)) + ax.p(center.x + math.cos(fAngle / 180 * math.pi) * fRadius, center.y + math.sin(fAngle/ 180 * math.pi) * fRadius)) end local function Issue1358_onEnterOrExit(tag) @@ -150,10 +150,10 @@ end local function Issue1358() local layer = getBaseLayer() - streak = cc.MotionStreak:create(2.0, 1.0, 50.0, cc.c3b(255, 255, 0), "Images/Icon.png") + streak = ax.MotionStreak:create(2.0, 1.0, 50.0, ax.color32(255, 255, 0), "Images/Icon.png") layer:addChild(streak) - center = cc.p(s.width / 2, s.height / 2) + center = ax.p(s.width / 2, s.height / 2) fRadius = s.width / 3 fAngle = 0 @@ -166,7 +166,7 @@ local function Issue1358() end function MotionStreakTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { MotionStreakTest1, diff --git a/tests/lua-tests/Content/src/NavMeshTest/NavMeshTest.lua b/tests/lua-tests/Content/src/NavMeshTest/NavMeshTest.lua index 748e25d8bfff..fded66201d09 100644 --- a/tests/lua-tests/Content/src/NavMeshTest/NavMeshTest.lua +++ b/tests/lua-tests/Content/src/NavMeshTest/NavMeshTest.lua @@ -12,14 +12,14 @@ local function jump(v1, v2, height, t) return out end -local actionManager = cc.Director:getInstance():getActionManager() +local actionManager = ax.Director:getInstance():getActionManager() ---------------------------------------- ----NavMeshBaseTestDemo ---------------------------------------- local NavMeshBaseTestDemo = class("NavMeshBaseTestDemo", function () -- body - local scene = cc.Scene:createWithPhysics() + local scene = ax.Scene:createWithPhysics() return scene end) @@ -53,11 +53,11 @@ end function NavMeshBaseTestDemo:init() self._angle = 0.0 self._agents = {} - local size = cc.Director:getInstance():getWinSize() - self._camera = cc.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) - self._camera:setPosition3D(cc.vec3(0.0, 50.0, 100.0)) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + local size = ax.Director:getInstance():getWinSize() + self._camera = ax.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) + self._camera:setPosition3D(ax.vec3(0.0, 50.0, 100.0)) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(self._camera) self:registerTouchEvent() @@ -93,7 +93,7 @@ function NavMeshBaseTestDemo:onEnter() local hitResult = {} local ret = false local physicsWorld = self:getPhysics3DWorld() - ret, hitResult = physicsWorld:rayCast(cc.vec3(0.0, 50.0, 0.0), cc.vec3(0.0, -50.0, 0.0), hitResult) + ret, hitResult = physicsWorld:rayCast(ax.vec3(0.0, 50.0, 0.0), ax.vec3(0.0, -50.0, 0.0), hitResult) self:createAgent(hitResult.hitPosition) end @@ -112,30 +112,30 @@ end function NavMeshBaseTestDemo:initScene() self:getPhysics3DWorld():setDebugDrawEnable(false) - local trianglesList = cc.Bundle3D:getTrianglesList("NavMesh/scene.obj") + local trianglesList = ax.Bundle3D:getTrianglesList("NavMesh/scene.obj") local rbDes = {} rbDes.mass = 0.0 - rbDes.shape = cc.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) - local rigidBody = cc.Physics3DRigidBody:create(rbDes) - local component = cc.Physics3DComponent:create(rigidBody) - local sprite = cc.Sprite3D:create("NavMesh/scene.obj") + rbDes.shape = ax.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) + local rigidBody = ax.Physics3DRigidBody:create(rbDes) + local component = ax.Physics3DComponent:create(rigidBody) + local sprite = ax.Sprite3D:create("NavMesh/scene.obj") sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) self:setPhysics3DDebugCamera(self._camera) - local navMesh = cc.NavMesh:create("NavMesh/all_tiles_tilecache.bin", "NavMesh/geomset.txt") + local navMesh = ax.NavMesh:create("NavMesh/all_tiles_tilecache.bin", "NavMesh/geomset.txt") navMesh:setDebugDrawEnable(true) self:setNavMesh(navMesh) self:setNavMeshDebugCamera(self._camera) - local ambientLight = cc.AmbientLight:create(cc.c3b(64, 64, 64)) - ambientLight:setCameraMask(cc.CameraFlag.USER1) + local ambientLight = ax.AmbientLight:create(ax.color32(64, 64, 64)) + ambientLight:setCameraMask(ax.CameraFlag.USER1) self:addChild(ambientLight) - local dirLight = cc.DirectionLight:create(cc.vec3(1.2, -1.1, 0.5), cc.c3b(255, 255, 255)) - dirLight:setCameraMask(cc.CameraFlag.USER1) + local dirLight = ax.DirectionLight:create(ax.vec3(1.2, -1.1, 0.5), ax.color32(255, 255, 255)) + dirLight:setCameraMask(ax.CameraFlag.USER1) self:addChild(dirLight) end @@ -147,23 +147,23 @@ function NavMeshBaseTestDemo:createAgent(pos) navMeshAgentParam.height = 8.0 navMeshAgentParam.maxSpeed = 8.0 - local agent = cc.NavMeshAgent:create(navMeshAgentParam) - local agentNode = cc.Sprite3D:create(filePath) - agent:setOrientationRefAxes(cc.vec3(-1.0, 0.0, 1.0)) + local agent = ax.NavMeshAgent:create(navMeshAgentParam) + local agentNode = ax.Sprite3D:create(filePath) + agent:setOrientationRefAxes(ax.vec3(-1.0, 0.0, 1.0)) agent.userdata = 0.0 agentNode:setScale(0.05) agentNode:addComponent(agent) - local node = cc.Node:create() + local node = ax.Node:create() node:addChild(agentNode) node:setPosition3D(pos) - node:setCameraMask(cc.CameraFlag.USER1) + node:setCameraMask(ax.CameraFlag.USER1) self:addChild(node) - local animation = cc.Animation3D:create(filePath) - local animate = cc.Animate3D:create(animation) + local animation = ax.Animation3D:create(filePath) + local animate = ax.Animate3D:create(animation) if nil ~= animate then - agentNode:runAction(cc.RepeatForever:create(animate)) + agentNode:runAction(ax.RepeatForever:create(animate)) animate:setSpeed(0.0) end @@ -171,13 +171,13 @@ function NavMeshBaseTestDemo:createAgent(pos) end function NavMeshBaseTestDemo:createObstacle(pos) - local obstacle = cc.NavMeshObstacle:create(2.0, 8.0) - local obstacleNode = cc.Sprite3D:create("MeshRendererTest/cylinder.c3b") - obstacleNode:setPosition3D(cc.vec3(pos.x, pos.y -0.5, pos.z)) - obstacleNode:setRotation3D(cc.vec3(-90.0, 0.0, 0.0)) + local obstacle = ax.NavMeshObstacle:create(2.0, 8.0) + local obstacleNode = ax.Sprite3D:create("MeshRendererTest/cylinder.c3b") + obstacleNode:setPosition3D(ax.vec3(pos.x, pos.y -0.5, pos.z)) + obstacleNode:setRotation3D(ax.vec3(-90.0, 0.0, 0.0)) obstacleNode:setScale(0.3) obstacleNode:addComponent(obstacle) - obstacleNode:setCameraMask(cc.CameraFlag.USER1) + obstacleNode:setCameraMask(ax.CameraFlag.USER1) self:addChild(obstacleNode) end @@ -193,22 +193,22 @@ function NavMeshBaseTestDemo:moveAgents(des) if agent:isOnOffMeshLink() then agent:setAutoTraverseOffMeshLink(false) agent:setAutoOrientation(false) - + local linkdata = agent:getCurrentOffMeshLinkData() agent:getOwner():setPosition3D(jump(linkdata.startPosition, linkdata.endPosition, 10.0, data)) - local dir = cc.vec3sub(linkdata.endPosition, linkdata.startPosition) + local dir = ax.vec3sub(linkdata.endPosition, linkdata.startPosition) dir.y = 0.0 - dir = cc.vec3normalize(dir) - local axes = cc.vec3(0.0, 0.0, 0.0) - local refAxes = cc.vec3(-1.0, 0.0, 1.0) - refAxes = cc.vec3normalize(refAxes) + dir = ax.vec3normalize(dir) + local axes = ax.vec3(0.0, 0.0, 0.0) + local refAxes = ax.vec3(-1.0, 0.0, 1.0) + refAxes = ax.vec3normalize(refAxes) axes = vec3_cross(refAxes, dir, axes) - local angle = cc.vec3dot(refAxes, dir) + local angle = ax.vec3dot(refAxes, dir) - local quaternion = cc.quaternion_createFromAxisAngle(axes, math.acos(angle)) + local quaternion = ax.quaternion_createFromAxisAngle(axes, math.acos(angle)) agent:getOwner():setRotationQuat(quaternion) agent.userdata = agent.userdata + 0.01 @@ -238,10 +238,10 @@ function NavMeshBasicTestDemo:subtitle() end function NavMeshBasicTestDemo:registerTouchEvent() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) self._needMoveAgents = true - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function(touches, event) @@ -250,14 +250,14 @@ function NavMeshBasicTestDemo:registerTouchEvent() local delta = touch:getDelta() self._angle = self._angle - delta.x * math.pi / 180.0 - self._camera:setPosition3D(cc.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - + self._camera:setPosition3D(ax.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + if (delta.x * delta.x + delta.y * delta.y) > 16 then self._needMoveAgents = false end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function(touches, event) if not self._needMoveAgents then @@ -267,10 +267,10 @@ function NavMeshBasicTestDemo:registerTouchEvent() if #touches > 0 then local touch = touches[1] local location = touch:getLocationInView() - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) @@ -279,7 +279,7 @@ function NavMeshBasicTestDemo:registerTouchEvent() ret, hitResult = physicsWorld:rayCast(nearP, farP, hitResult) self:moveAgents(hitResult.hitPosition) end - end, cc.Handler.EVENT_TOUCHES_ENDED) + end, ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -289,10 +289,10 @@ function NavMeshBasicTestDemo:extend() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 15 - local debugLabel = cc.Label:createWithTTF(ttfConfig,"Debug Draw ON") - local menuItem = cc.MenuItemLabel:create(debugLabel) + local debugLabel = ax.Label:createWithTTF(ttfConfig,"Debug Draw ON") + local menuItem = ax.MenuItemLabel:create(debugLabel) menuItem:registerScriptTapHandler(function (tag, sender) - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() local enabledDebug = not scene:getNavMesh():isDebugDrawEnabled() scene:getNavMesh():setDebugDrawEnable(enabledDebug) @@ -303,10 +303,10 @@ function NavMeshBasicTestDemo:extend() end end) - menuItem:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem:setPosition(cc.p(VisibleRect:left().x, VisibleRect:top().y - 100)) - local menu = cc.Menu:create(menuItem) - menu:setPosition(cc.p(0.0, 0.0)) + menuItem:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem:setPosition(ax.p(VisibleRect:left().x, VisibleRect:top().y - 100)) + local menu = ax.Menu:create(menuItem) + menu:setPosition(ax.p(0.0, 0.0)) self:addChild(menu) end ---------------------------------------- @@ -324,10 +324,10 @@ function NavMeshAdvanceTestDemo:subtitle() end function NavMeshAdvanceTestDemo:registerTouchEvent() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) self._needMoveAgents = true - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function(touches, event) @@ -336,14 +336,14 @@ function NavMeshAdvanceTestDemo:registerTouchEvent() local delta = touch:getDelta() self._angle = self._angle - delta.x * math.pi / 180.0 - self._camera:setPosition3D(cc.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - + self._camera:setPosition3D(ax.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + if (delta.x * delta.x + delta.y * delta.y) > 16 then self._needMoveAgents = false end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function(touches, event) if not self._needMoveAgents then @@ -353,10 +353,10 @@ function NavMeshAdvanceTestDemo:registerTouchEvent() if #touches > 0 then local touch = touches[1] local location = touch:getLocationInView() - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) @@ -365,7 +365,7 @@ function NavMeshAdvanceTestDemo:registerTouchEvent() ret, hitResult = physicsWorld:rayCast(nearP, farP, hitResult) self:moveAgents(hitResult.hitPosition) end - end, cc.Handler.EVENT_TOUCHES_ENDED) + end, ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -375,40 +375,40 @@ function NavMeshAdvanceTestDemo:extend() local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 15 - local obstacleLabel = cc.Label:createWithTTF(ttfConfig,"Create Obstacle") - local menuItem0 = cc.MenuItemLabel:create(obstacleLabel) + local obstacleLabel = ax.Label:createWithTTF(ttfConfig,"Create Obstacle") + local menuItem0 = ax.MenuItemLabel:create(obstacleLabel) menuItem0:registerScriptTapHandler(function (tag, sender) - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() local x = math.random(-50, 50) local z = math.random(-50.0, 50.0) local hitResult = {} local ret = false - ret, hitResult = scene:getPhysics3DWorld():rayCast(cc.vec3(x, 50.0, z), cc.vec3(x, -50.0, z), hitResult) + ret, hitResult = scene:getPhysics3DWorld():rayCast(ax.vec3(x, 50.0, z), ax.vec3(x, -50.0, z), hitResult) self:createObstacle(hitResult.hitPosition) end) - menuItem0:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem0:setPosition(cc.p(VisibleRect:left().x, VisibleRect:top().y - 50)) + menuItem0:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem0:setPosition(ax.p(VisibleRect:left().x, VisibleRect:top().y - 50)) - local agentLabel = cc.Label:createWithTTF(ttfConfig,"Create Agent") - local menuItem1 = cc.MenuItemLabel:create(agentLabel) + local agentLabel = ax.Label:createWithTTF(ttfConfig,"Create Agent") + local menuItem1 = ax.MenuItemLabel:create(agentLabel) menuItem1:registerScriptTapHandler(function (tag, sender) - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() local x = math.random(-50, 50) local z = math.random(-50.0, 50.0) local hitResult = {} local ret = false - ret, hitResult = scene:getPhysics3DWorld():rayCast(cc.vec3(x, 50.0, z), cc.vec3(x, -50.0, z), hitResult) + ret, hitResult = scene:getPhysics3DWorld():rayCast(ax.vec3(x, 50.0, z), ax.vec3(x, -50.0, z), hitResult) self:createAgent(hitResult.hitPosition) end) - menuItem1:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem1:setPosition(cc.p(VisibleRect:left().x, VisibleRect:top().y - 100)) + menuItem1:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem1:setPosition(ax.p(VisibleRect:left().x, VisibleRect:top().y - 100)) - local debugLabel = cc.Label:createWithTTF(ttfConfig,"Debug Draw ON") - local menuItem2 = cc.MenuItemLabel:create(debugLabel) + local debugLabel = ax.Label:createWithTTF(ttfConfig,"Debug Draw ON") + local menuItem2 = ax.MenuItemLabel:create(debugLabel) menuItem2:registerScriptTapHandler(function (tag, sender) - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() local enabledDebug = not scene:getNavMesh():isDebugDrawEnabled() scene:getNavMesh():setDebugDrawEnable(enabledDebug) @@ -418,11 +418,11 @@ function NavMeshAdvanceTestDemo:extend() debugLabel:setString("DebugDraw OFF") end end) - menuItem2:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem2:setPosition(cc.p(VisibleRect:left().x, VisibleRect:top().y - 150)) + menuItem2:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem2:setPosition(ax.p(VisibleRect:left().x, VisibleRect:top().y - 150)) - local menu = cc.Menu:create(menuItem0, menuItem1, menuItem2) - menu:setPosition(cc.p(0.0, 0.0)) + local menu = ax.Menu:create(menuItem0, menuItem1, menuItem2) + menu:setPosition(ax.p(0.0, 0.0)) self:addChild(menu) end @@ -432,7 +432,7 @@ end function NavMeshTest() Helper.usePhysics = true - TestCastScene.createFunctionTable = + TestCastScene.createFunctionTable = { NavMeshBasicTestDemo.create, NavMeshAdvanceTestDemo.create, @@ -442,4 +442,4 @@ function NavMeshTest() scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/NewAudioEngineTest/NewAudioEngineTest.lua b/tests/lua-tests/Content/src/NewAudioEngineTest/NewAudioEngineTest.lua index 1744fea74522..61e700decf8a 100644 --- a/tests/lua-tests/Content/src/NewAudioEngineTest/NewAudioEngineTest.lua +++ b/tests/lua-tests/Content/src/NewAudioEngineTest/NewAudioEngineTest.lua @@ -1,5 +1,5 @@ local SliderEx = class("SliderEx", function() - local slider = cc.Sprite:create("cocosui/sliderTrack.png") + local slider = ax.Sprite:create("cocosui/sliderTrack.png") return slider end) @@ -22,55 +22,55 @@ end function SliderEx:onEnter() self._ratio = 0 self._thumbX = 0 - - local progressBar = cc.Sprite:create("cocosui/sliderProgress.png") - progressBar:setAnchorPoint(cc.p(0,0)) + + local progressBar = ax.Sprite:create("cocosui/sliderProgress.png") + progressBar:setAnchorPoint(ax.p(0,0)) self:addChild(progressBar) - + local sliderSize = self:getContentSize() self._width = sliderSize.width - self._thumb = cc.Sprite:create("cocosui/sliderThumb.png") - self._thumb:setPosition(cc.p(0,sliderSize.height/2)) + self._thumb = ax.Sprite:create("cocosui/sliderThumb.png") + self._thumb:setPosition(ax.p(0,sliderSize.height/2)) self:addChild(self._thumb) - + local thumbSize = self._thumb:getContentSize() - self._thumbRect = cc.rect(0, 0, thumbSize.width, thumbSize.height) - - local listenner = cc.EventListenerTouchOneByOne:create() + self._thumbRect = ax.rect(0, 0, thumbSize.width, thumbSize.height) + + local listenner = ax.EventListenerTouchOneByOne:create() listenner:setSwallowTouches(true) listenner:registerScriptHandler(function(touch, event) local location = touch:getLocation() local locationInNode = self._thumb:convertToNodeSpace(location) - if not cc.rectContainsPoint(self._thumbRect, locationInNode) then + if not ax.rectContainsPoint(self._thumbRect, locationInNode) then return false end - + self._touchBeganX = self:convertToNodeSpace(location).x self._thumbBeganX = self._thumbX if self._callback then self._callback(self,self._ratio,SliderEx.TouchEventDown) end return true - end, cc.Handler.EVENT_TOUCH_BEGAN ) - + end, ax.Handler.EVENT_TOUCH_BEGAN ) + listenner:registerScriptHandler(function(touch, event) - local locationInNodeX = self:convertToNodeSpace(touch:getLocation()).x + local locationInNodeX = self:convertToNodeSpace(touch:getLocation()).x self:setThumbPosX(self._thumbBeganX + locationInNodeX - self._touchBeganX) - + if self._callback then self._callback(self,self._ratio,SliderEx.TouchEventMove) end - end, cc.Handler.EVENT_TOUCH_MOVED ) - + end, ax.Handler.EVENT_TOUCH_MOVED ) + listenner:registerScriptHandler(function(touch, event) local locationInNodeX = self:convertToNodeSpace(touch:getLocation()).x self:setThumbPosX(self._thumbBeganX + locationInNodeX - self._touchBeganX) - + if self._callback then self._callback(self,self._ratio,SliderEx.TouchEventUp) end - end, cc.Handler.EVENT_TOUCH_ENDED ) - + end, ax.Handler.EVENT_TOUCH_ENDED ) + local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listenner, self) end @@ -82,7 +82,7 @@ function SliderEx:setThumbPosX(newX) elseif self._thumbX > self._width then self._thumbX = self._width end - + self._ratio = self._thumbX / self._width self._thumb:setPositionX(self._thumbX) end @@ -97,7 +97,7 @@ function SliderEx:setRatio(ratio) elseif ratio > 1.0 then ratio = 1.0 end - + self._ratio = ratio self._thumbX = self._ratio * self._width self._thumb:setPositionX(self._thumbX) @@ -107,81 +107,81 @@ end local AudioControlTest = {} function AudioControlTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("audio control test") -- Helper.subtitleLabel:setString("subtitleLabel") local layerSize = layer:getContentSize() - - AudioControlTest._audioID = cc.AUDIO_INVAILD_ID + + AudioControlTest._audioID = ax.AUDIO_INVAILD_ID AudioControlTest._loopEnabled = false AudioControlTest._volume = 1.0 - AudioControlTest._duration = cc.AUDIO_TIME_UNKNOWN + AudioControlTest._duration = ax.AUDIO_TIME_UNKNOWN AudioControlTest._timeRatio = 0.0 AudioControlTest._updateTimeSlider = true - + ------playItem local function playAudio(tag, sender) - if AudioControlTest._audioID == cc.AUDIO_INVAILD_ID then - AudioControlTest._audioID = cc.AudioEngine:play2d("background.mp3", AudioControlTest._loopEnabled, AudioControlTest._volume) - - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then + if AudioControlTest._audioID == ax.AUDIO_INVAILD_ID then + AudioControlTest._audioID = ax.AudioEngine:play2d("background.mp3", AudioControlTest._loopEnabled, AudioControlTest._volume) + + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then AudioControlTest._playItem:setEnabled(false) - + local function finishCallback(audioID,filePath) - AudioControlTest._audioID = cc.AUDIO_INVAILD_ID + AudioControlTest._audioID = ax.AUDIO_INVAILD_ID AudioControlTest._playItem:setEnabled(true) end - - cc.AudioEngine:setFinishCallback(AudioControlTest._audioID,finishCallback) + + ax.AudioEngine:setFinishCallback(AudioControlTest._audioID,finishCallback) end end end - - AudioControlTest._playItem = cc.MenuItemFont:create("play") - AudioControlTest._playItem:setPosition(cc.p(layerSize.width * 0.3,layerSize.height * 0.7)) + + AudioControlTest._playItem = ax.MenuItemFont:create("play") + AudioControlTest._playItem:setPosition(ax.p(layerSize.width * 0.3,layerSize.height * 0.7)) AudioControlTest._playItem:registerScriptTapHandler(playAudio) - + ------stopItem local function stopAudio(tag, sender) - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - cc.AudioEngine:stop(AudioControlTest._audioID) - AudioControlTest._audioID = cc.AUDIO_INVAILD_ID + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + ax.AudioEngine:stop(AudioControlTest._audioID) + AudioControlTest._audioID = ax.AUDIO_INVAILD_ID AudioControlTest._playItem:setEnabled(true) end end - - local stopItem = cc.MenuItemFont:create("stop") - stopItem:setPosition(cc.p(layerSize.width * 0.7,layerSize.height * 0.7)) + + local stopItem = ax.MenuItemFont:create("stop") + stopItem:setPosition(ax.p(layerSize.width * 0.7,layerSize.height * 0.7)) stopItem:registerScriptTapHandler(stopAudio) - + ------pauseItem local function pauseAudio(tag, sender) - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - cc.AudioEngine:pause(AudioControlTest._audioID) + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + ax.AudioEngine:pause(AudioControlTest._audioID) end end - - local pauseItem = cc.MenuItemFont:create("pause") - pauseItem:setPosition(cc.p(layerSize.width * 0.3,layerSize.height * 0.6)) + + local pauseItem = ax.MenuItemFont:create("pause") + pauseItem:setPosition(ax.p(layerSize.width * 0.3,layerSize.height * 0.6)) pauseItem:registerScriptTapHandler(pauseAudio) - + ------resumeItem local function resumeAudio(tag, sender) - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - cc.AudioEngine:resume(AudioControlTest._audioID) + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + ax.AudioEngine:resume(AudioControlTest._audioID) end end - - local resumeItem = cc.MenuItemFont:create("resume") - resumeItem:setPosition(cc.p(layerSize.width * 0.7,layerSize.height * 0.6)) + + local resumeItem = ax.MenuItemFont:create("resume") + resumeItem:setPosition(ax.p(layerSize.width * 0.7,layerSize.height * 0.6)) resumeItem:registerScriptTapHandler(resumeAudio) - + ------loopItem local function switchLoop(tag, sender) AudioControlTest._loopEnabled = not AudioControlTest._loopEnabled - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - cc.AudioEngine:setLoop(AudioControlTest._audioID, AudioControlTest._loopEnabled) + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + ax.AudioEngine:setLoop(AudioControlTest._audioID, AudioControlTest._loopEnabled) end if AudioControlTest._loopEnabled then AudioControlTest.loopItem:setString("disable-loop") @@ -189,36 +189,36 @@ function AudioControlTest.create() AudioControlTest.loopItem:setString("enable-loop") end end - - AudioControlTest.loopItem = cc.MenuItemFont:create("enable-loop") - AudioControlTest.loopItem:setPosition(cc.p(layerSize.width * 0.3,layerSize.height * 0.5)) + + AudioControlTest.loopItem = ax.MenuItemFont:create("enable-loop") + AudioControlTest.loopItem:setPosition(ax.p(layerSize.width * 0.3,layerSize.height * 0.5)) AudioControlTest.loopItem:registerScriptTapHandler(switchLoop) - + ------uncacheItem local function uncache(tag, sender) - cc.AudioEngine:uncache("background.mp3") - AudioControlTest._audioID = cc.AUDIO_INVAILD_ID + ax.AudioEngine:uncache("background.mp3") + AudioControlTest._audioID = ax.AUDIO_INVAILD_ID AudioControlTest._playItem:setEnabled(true) end - - local uncacheItem = cc.MenuItemFont:create("uncache") - uncacheItem:setPosition(cc.p(layerSize.width * 0.7,layerSize.height * 0.5)) + + local uncacheItem = ax.MenuItemFont:create("uncache") + uncacheItem:setPosition(ax.p(layerSize.width * 0.7,layerSize.height * 0.5)) uncacheItem:registerScriptTapHandler(uncache) - - local menu = cc.Menu:create() + + local menu = ax.Menu:create() menu:addChild(AudioControlTest._playItem) menu:addChild(stopItem) menu:addChild(pauseItem) menu:addChild(resumeItem) menu:addChild(AudioControlTest.loopItem) menu:addChild(uncacheItem) - menu:setPosition(cc.p(0, 0)) + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - + local function volumeSliderChangedEvent(sender,eventType) AudioControlTest._volume = sender:getPercent() / 100.0 - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - cc.AudioEngine:setVolume(AudioControlTest._audioID, AudioControlTest._volume) + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + ax.AudioEngine:setVolume(AudioControlTest._audioID, AudioControlTest._volume) end end local volumeSlider = ccui.Slider:create() @@ -226,45 +226,45 @@ function AudioControlTest.create() volumeSlider:loadBarTexture("cocosui/sliderTrack.png") volumeSlider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") volumeSlider:loadProgressBarTexture("cocosui/sliderProgress.png") - volumeSlider:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * 0.35)) + volumeSlider:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * 0.35)) volumeSlider:addEventListener(volumeSliderChangedEvent) volumeSlider:setPercent(100) layer:addChild(volumeSlider) - + local sliderSize = volumeSlider:getContentSize() - local volumeLabel = cc.Label:createWithTTF("volume: ","fonts/arial.ttf", 20) - volumeLabel:setAnchorPoint(cc.p(1.0,0.5)) - volumeLabel:setPosition(cc.p((layerSize.width - sliderSize.width)/2, layerSize.height * 0.35)) + local volumeLabel = ax.Label:createWithTTF("volume: ","fonts/arial.ttf", 20) + volumeLabel:setAnchorPoint(ax.p(1.0,0.5)) + volumeLabel:setPosition(ax.p((layerSize.width - sliderSize.width)/2, layerSize.height * 0.35)) layer:addChild(volumeLabel) - - local timeLabel = cc.Label:createWithTTF("time: ","fonts/arial.ttf", 20) - timeLabel:setAnchorPoint(cc.p(1.0,0.5)) - timeLabel:setPosition(cc.p((layerSize.width - sliderSize.width)/2, layerSize.height * 0.25)) + + local timeLabel = ax.Label:createWithTTF("time: ","fonts/arial.ttf", 20) + timeLabel:setAnchorPoint(ax.p(1.0,0.5)) + timeLabel:setPosition(ax.p((layerSize.width - sliderSize.width)/2, layerSize.height * 0.25)) layer:addChild(timeLabel) - + local function timeSlideChangeCallback(sender,ratio,eventType) if (eventType == SliderEx.TouchEventDown or eventType == SliderEx.TouchEventMove) then AudioControlTest._updateTimeSlider = false else - if (AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID and AudioControlTest._duration ~= cc.AUDIO_TIME_UNKNOWN) then - cc.AudioEngine:setCurrentTime(AudioControlTest._audioID,AudioControlTest._duration * ratio) + if (AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID and AudioControlTest._duration ~= ax.AUDIO_TIME_UNKNOWN) then + ax.AudioEngine:setCurrentTime(AudioControlTest._audioID,AudioControlTest._duration * ratio) end AudioControlTest._updateTimeSlider = true end end - + AudioControlTest._timeSlider = SliderEx:create() - AudioControlTest._timeSlider:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * 0.25)) + AudioControlTest._timeSlider:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * 0.25)) AudioControlTest._timeSlider:addRatioListener(timeSlideChangeCallback) layer:addChild(AudioControlTest._timeSlider) - + local function step(dt) - if AudioControlTest._audioID ~= cc.AUDIO_INVAILD_ID then - if AudioControlTest._duration == cc.AUDIO_TIME_UNKNOWN then - AudioControlTest._duration = cc.AudioEngine:getDuration(AudioControlTest._audioID) + if AudioControlTest._audioID ~= ax.AUDIO_INVAILD_ID then + if AudioControlTest._duration == ax.AUDIO_TIME_UNKNOWN then + AudioControlTest._duration = ax.AudioEngine:getDuration(AudioControlTest._audioID) end - if AudioControlTest._duration ~= cc.AUDIO_TIME_UNKNOWN then - local time = cc.AudioEngine:getCurrentTime(AudioControlTest._audioID) + if AudioControlTest._duration ~= ax.AUDIO_TIME_UNKNOWN then + local time = ax.AudioEngine:getCurrentTime(AudioControlTest._audioID) AudioControlTest._timeRatio = time / AudioControlTest._duration if AudioControlTest._updateTimeSlider then AudioControlTest._timeSlider:setRatio(AudioControlTest._timeRatio) @@ -272,150 +272,150 @@ function AudioControlTest.create() end end end - + layer:scheduleUpdateWithPriorityLua(step, 0.05) - + function onNodeEvent(tag) if tag == "exit" then - cc.AudioEngine:stopAll() + ax.AudioEngine:stopAll() end end layer:registerScriptHandler(onNodeEvent) - + return layer end ------------------------------------------------------------------------ local PlaySimultaneouslyTest = {} function PlaySimultaneouslyTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Simultaneously play multiple audio") - + PlaySimultaneouslyTest._playingcount = 0 PlaySimultaneouslyTest.files = {} for index=1,10 do PlaySimultaneouslyTest.files[index] = string.format("audio/SoundEffectsFX009/FX0%d.mp3",80 + index) end - + local function playAudio(tag, sender) - local audioID = cc.AUDIO_INVAILD_ID + local audioID = ax.AUDIO_INVAILD_ID --for k, v in pairs(PlaySimultaneouslyTest.files) do for index=1,10 do - audioID = cc.AudioEngine:play2d(PlaySimultaneouslyTest.files[index]) - - if audioID ~= cc.AUDIO_INVAILD_ID then + audioID = ax.AudioEngine:play2d(PlaySimultaneouslyTest.files[index]) + + if audioID ~= ax.AUDIO_INVAILD_ID then PlaySimultaneouslyTest._playItem:setEnabled(false) PlaySimultaneouslyTest._playingcount = PlaySimultaneouslyTest._playingcount + 1 - + local function finishCallback(audioID,filePath) PlaySimultaneouslyTest._playingcount = PlaySimultaneouslyTest._playingcount - 1 if PlaySimultaneouslyTest._playingcount <= 0 then PlaySimultaneouslyTest._playItem:setEnabled(true) end end - - cc.AudioEngine:setFinishCallback(audioID,finishCallback) - end + + ax.AudioEngine:setFinishCallback(audioID,finishCallback) + end end end - - PlaySimultaneouslyTest._playItem = cc.MenuItemFont:create("play-simultaneously") - PlaySimultaneouslyTest._playItem:setNormalizedPosition(cc.p(0.5,0.5)) + + PlaySimultaneouslyTest._playItem = ax.MenuItemFont:create("play-simultaneously") + PlaySimultaneouslyTest._playItem:setNormalizedPosition(ax.p(0.5,0.5)) PlaySimultaneouslyTest._playItem:registerScriptTapHandler(playAudio) - - local menu = cc.Menu:create(PlaySimultaneouslyTest._playItem) - menu:setPosition(cc.p(0, 0)) + + local menu = ax.Menu:create(PlaySimultaneouslyTest._playItem) + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - + function onNodeEvent(tag) if tag == "exit" then - cc.AudioEngine:stopAll() + ax.AudioEngine:stopAll() end end layer:registerScriptHandler(onNodeEvent) - + return layer end ------------------------------------------------------------------------ local AudioProfileTest = {} function AudioProfileTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("AudioProfileTest") Helper.subtitleLabel:setString("See the console.") local layerSize = layer:getContentSize() - + AudioProfileTest._files = {} AudioProfileTest._files[1] = "background.mp3" - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - if (cc.PLATFORM_OS_MAC == targetPlatform or cc.PLATFORM_OS_IPHONE == targetPlatform or cc.PLATFORM_OS_IPAD == targetPlatform) then + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + if (ax.PLATFORM_OS_MAC == targetPlatform or ax.PLATFORM_OS_IPHONE == targetPlatform or ax.PLATFORM_OS_IPAD == targetPlatform) then AudioProfileTest._files[2] = "background.caf" else AudioProfileTest._files[2] = "background.ogg" end - - AudioProfileTest._profile = cc.AudioProfile:new() + + AudioProfileTest._profile = ax.AudioProfile:new() AudioProfileTest._profile.name = "AudioProfileTest" AudioProfileTest._profile.maxInstances = 3 AudioProfileTest._profile.minDelay = 1.0 - + AudioProfileTest._audioCount = 0 AudioProfileTest._minDelay = 1.0 AudioProfileTest._time = 0.0 - - local menu = cc.Menu:create() - menu:setPosition(cc.p(0, 0)) + + local menu = ax.Menu:create() + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - + local heightRatio = 0.7 for index=1,2 do local function itemClickCallback(tag, sender) - local audioID = cc.AudioEngine:play2d(AudioProfileTest._files[tag],false,1.0,AudioProfileTest._profile) - if audioID ~= cc.AUDIO_INVAILD_ID then + local audioID = ax.AudioEngine:play2d(AudioProfileTest._files[tag],false,1.0,AudioProfileTest._profile) + if audioID ~= ax.AUDIO_INVAILD_ID then AudioProfileTest._time = AudioProfileTest._minDelay AudioProfileTest._audioCount = AudioProfileTest._audioCount + 1 AudioProfileTest._showLabel:setString(string.format("audio count:%d",AudioProfileTest._audioCount)) - + local function finishCallback(audioID,filePath) AudioProfileTest._audioCount = AudioProfileTest._audioCount - 1 AudioProfileTest._showLabel:setString(string.format("audio count:%d",AudioProfileTest._audioCount)) end - - cc.AudioEngine:setFinishCallback(audioID,finishCallback) + + ax.AudioEngine:setFinishCallback(audioID,finishCallback) end end - local item = cc.MenuItemFont:create("play "..AudioProfileTest._files[index]) + local item = ax.MenuItemFont:create("play "..AudioProfileTest._files[index]) item:setFontSizeObj(20) - item:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * heightRatio)) + item:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * heightRatio)) item:registerScriptTapHandler(itemClickCallback) menu:addChild(item,0,index) heightRatio = heightRatio - 0.1 end - - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - - local profileInfoLabel = cc.Label:createWithTTF("AudioProfile Info:\n max instance:3 \n minimum delay:1.0","fonts/arial.ttf", 12) - profileInfoLabel:setAnchorPoint(cc.p(0,0.5)) - profileInfoLabel:setPosition(cc.p(origin.x, origin.y + size.height * 0.65)) + + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + + local profileInfoLabel = ax.Label:createWithTTF("AudioProfile Info:\n max instance:3 \n minimum delay:1.0","fonts/arial.ttf", 12) + profileInfoLabel:setAnchorPoint(ax.p(0,0.5)) + profileInfoLabel:setPosition(ax.p(origin.x, origin.y + size.height * 0.65)) layer:addChild(profileInfoLabel) - - AudioProfileTest._showLabel = cc.Label:createWithTTF("audio count:0","fonts/arial.ttf", 12) - AudioProfileTest._showLabel:setAnchorPoint(cc.p(0,0.5)) - AudioProfileTest._showLabel:setPosition(cc.p(origin.x, origin.y + size.height * 0.5)) + + AudioProfileTest._showLabel = ax.Label:createWithTTF("audio count:0","fonts/arial.ttf", 12) + AudioProfileTest._showLabel:setAnchorPoint(ax.p(0,0.5)) + AudioProfileTest._showLabel:setPosition(ax.p(origin.x, origin.y + size.height * 0.5)) layer:addChild(AudioProfileTest._showLabel) - + AudioProfileTest._timeSlider = ccui.Slider:create() AudioProfileTest._timeSlider:setTouchEnabled(false) AudioProfileTest._timeSlider:loadBarTexture("cocosui/sliderTrack.png") AudioProfileTest._timeSlider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") AudioProfileTest._timeSlider:loadProgressBarTexture("cocosui/sliderProgress.png") - AudioProfileTest._timeSlider:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * heightRatio)) + AudioProfileTest._timeSlider:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * heightRatio)) layer:addChild(AudioProfileTest._timeSlider) - + local function step(dt) if AudioProfileTest._time > 0 then AudioProfileTest._time = AudioProfileTest._time - dt @@ -426,91 +426,91 @@ function AudioProfileTest.create() end end layer:scheduleUpdateWithPriorityLua(step, 0.05) - + function onNodeEvent(tag) if tag == "exit" then - cc.AudioEngine:stopAll() + ax.AudioEngine:stopAll() end end layer:registerScriptHandler(onNodeEvent) - + return layer end ------------------------------------------------------------------------ local InvalidAudioFileTest = {} function InvalidAudioFileTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Test invalid audio file") Helper.subtitleLabel:setString("Not crash,please see the console.") local layerSize = layer:getContentSize() - + -- unsupported media type local function playUnsupportedAudio(tag, sender) - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - if (cc.PLATFORM_OS_MAC == currPlatform or cc.PLATFORM_OS_IPHONE == targetPlatform or cc.PLATFORM_OS_IPAD == targetPlatform) then - cc.AudioEngine:play2d("background.ogg") + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + if (ax.PLATFORM_OS_MAC == currPlatform or ax.PLATFORM_OS_IPHONE == targetPlatform or ax.PLATFORM_OS_IPAD == targetPlatform) then + ax.AudioEngine:play2d("background.ogg") end - if (cc.PLATFORM_OS_ANDROID == targetPlatform) then - cc.AudioEngine:play2d("background.caf") + if (ax.PLATFORM_OS_ANDROID == targetPlatform) then + ax.AudioEngine:play2d("background.caf") end end - - local playItem1 = cc.MenuItemFont:create("play unsupported media type") - playItem1:setNormalizedPosition(cc.p(0.5,0.6)) + + local playItem1 = ax.MenuItemFont:create("play unsupported media type") + playItem1:setNormalizedPosition(ax.p(0.5,0.6)) playItem1:registerScriptTapHandler(playUnsupportedAudio) - + -- not-existent audio local function playNotExistentAudio(tag, sender) - cc.AudioEngine:play2d("not-existent file.mp3") + ax.AudioEngine:play2d("not-existent file.mp3") end - - local playItem2 = cc.MenuItemFont:create("play not-existent file") - playItem2:setNormalizedPosition(cc.p(0.5,0.4)) + + local playItem2 = ax.MenuItemFont:create("play not-existent file") + playItem2:setNormalizedPosition(ax.p(0.5,0.4)) playItem2:registerScriptTapHandler(playNotExistentAudio) - - local menu = cc.Menu:create() + + local menu = ax.Menu:create() menu:addChild(playItem1) menu:addChild(playItem2) - menu:setPosition(cc.p(0, 0)) + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - + return layer end ------------------------------------------------------------------------ local LargeAudioFileTest = {} function LargeAudioFileTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Test large audio file") local layerSize = layer:getContentSize() - + local function playAudio(tag, sender) - cc.AudioEngine:play2d("audio/LuckyDay.mp3") + ax.AudioEngine:play2d("audio/LuckyDay.mp3") end - - local playItem = cc.MenuItemFont:create("play large audio file") - playItem:setNormalizedPosition(cc.p(0.5,0.5)) + + local playItem = ax.MenuItemFont:create("play large audio file") + playItem:setNormalizedPosition(ax.p(0.5,0.5)) playItem:registerScriptTapHandler(playAudio) - - local menu = cc.Menu:create(playItem) - menu:setPosition(cc.p(0, 0)) + + local menu = ax.Menu:create(playItem) + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - + function onNodeEvent(tag) if tag == "exit" then - cc.AudioEngine:stopAll() + ax.AudioEngine:stopAll() end end layer:registerScriptHandler(onNodeEvent) - + return layer end ------------------------------------------------------------------------ function AudioEngineTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { AudioControlTest.create, @@ -520,8 +520,8 @@ function AudioEngineTest() LargeAudioFileTest.create } Helper.index = 1 - + scene:addChild(AudioControlTest.create()) scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/NewEventDispatcherTest/NewEventDispatcherTest.lua b/tests/lua-tests/Content/src/NewEventDispatcherTest/NewEventDispatcherTest.lua index dcfc5804f5d0..e31dbb70916c 100644 --- a/tests/lua-tests/Content/src/NewEventDispatcherTest/NewEventDispatcherTest.lua +++ b/tests/lua-tests/Content/src/NewEventDispatcherTest/NewEventDispatcherTest.lua @@ -33,7 +33,7 @@ function EventDispatcherScene.extend(target) end function EventDispatcherScene.create() - local scene = EventDispatcherScene.extend(cc.Scene:create()) + local scene = EventDispatcherScene.extend(ax.Scene:create()) return scene end @@ -109,7 +109,7 @@ function EventDispatcherTestDemo.subTitle(idx) end function EventDispatcherTestDemo.create() - local layer = EventDispatcherTestDemo.extend(cc.Layer:create()) + local layer = EventDispatcherTestDemo.extend(ax.Layer:create()) if nil ~= layer then layer:createMenu() @@ -124,59 +124,59 @@ function EventDispatcherTestDemo.backCallback() local newScene = EventDispatcherScene.create() newScene:addChild(backEventDispatcherTest()) newScene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(newScene) + ax.Director:getInstance():replaceScene(newScene) end function EventDispatcherTestDemo.restartCallback() local newScene = EventDispatcherScene.create() newScene:addChild(restartEventDispatcherTest()) newScene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(newScene) + ax.Director:getInstance():replaceScene(newScene) end function EventDispatcherTestDemo.nextCallback() local newScene = EventDispatcherScene.create() newScene:addChild(nextEventDispatcherTest()) newScene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(newScene) + ax.Director:getInstance():replaceScene(newScene) end function EventDispatcherTestDemo:createMenu() - local menu = cc.Menu:create() + local menu = ax.Menu:create() - self._backItem = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) + self._backItem = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) self._backItem:registerScriptTapHandler(self.backCallback) menu:addChild(self._backItem,itemTagBasic) - self._restarItem = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) + self._restarItem = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) self._restarItem:registerScriptTapHandler(self.restartCallback) menu:addChild(self._restarItem,itemTagBasic) - self._nextItem = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + self._nextItem = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) menu:addChild(self._nextItem,itemTagBasic) self._nextItem:registerScriptTapHandler(self.nextCallback) - local size = cc.Director:getInstance():getWinSize() - self._backItem:setPosition(cc.p(size.width / 2 - self._restarItem:getContentSize().width * 2, self._restarItem:getContentSize().height / 2)) - self._restarItem:setPosition(cc.p(size.width / 2, self._restarItem:getContentSize().height / 2)) - self._nextItem:setPosition(cc.p(size.width / 2 + self._restarItem:getContentSize().width * 2, self._restarItem:getContentSize().height / 2)) + local size = ax.Director:getInstance():getWinSize() + self._backItem:setPosition(ax.p(size.width / 2 - self._restarItem:getContentSize().width * 2, self._restarItem:getContentSize().height / 2)) + self._restarItem:setPosition(ax.p(size.width / 2, self._restarItem:getContentSize().height / 2)) + self._nextItem:setPosition(ax.p(size.width / 2 + self._restarItem:getContentSize().width * 2, self._restarItem:getContentSize().height / 2)) - menu:setPosition(cc.p(0, 0)) + menu:setPosition(ax.p(0, 0)) self:addChild(menu, 9999) end function EventDispatcherTestDemo:creatTitleAndSubTitle(idx) - local title = cc.Label:createWithTTF(EventDispatcherTestDemo.title(idx),s_arialPath,18) - title:setColor(cc.c3b(128,128,0)) + local title = ax.Label:createWithTTF(EventDispatcherTestDemo.title(idx),s_arialPath,18) + title:setColor(ax.color32(128,128,0)) self:addChild(title, 1, 10000) - title:setAnchorPoint(cc.p(0.5, 0.5)) - title:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 30)) + title:setAnchorPoint(ax.p(0.5, 0.5)) + title:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 30)) local subTitle = nil if "" ~= EventDispatcherTestDemo.subTitle(idx) then - local subTitle = cc.Label:createWithTTF(EventDispatcherTestDemo.subTitle(idx), s_arialPath, 18) - subTitle:setColor(cc.c3b(128,128,0)) + local subTitle = ax.Label:createWithTTF(EventDispatcherTestDemo.subTitle(idx), s_arialPath, 18) + subTitle:setColor(ax.color32(128,128,0)) self:addChild(subTitle, 1, 10001) - subTitle:setAnchorPoint(cc.p(0.5, 0.5)) - subTitle:setPosition( cc.p(VisibleRect:center().x, VisibleRect:top().y - 60) ) + subTitle:setAnchorPoint(ax.p(0.5, 0.5)) + subTitle:setPosition( ax.p(VisibleRect:center().x, VisibleRect:top().y - 60) ) end end @@ -195,29 +195,29 @@ function TouchableSpriteTest.extend(target) end function TouchableSpriteTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() - local sprite1 = cc.Sprite:create("Images/CyanSquare.png") - sprite1:setPosition(cc.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 80)) + local sprite1 = ax.Sprite:create("Images/CyanSquare.png") + sprite1:setPosition(ax.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 80)) self:addChild(sprite1, 10) - local sprite2 = cc.Sprite:create("Images/MagentaSquare.png") - sprite2:setPosition(cc.p(origin.x + size.width/2, origin.x + size.height/2)) + local sprite2 = ax.Sprite:create("Images/MagentaSquare.png") + sprite2:setPosition(ax.p(origin.x + size.width/2, origin.x + size.height/2)) self:addChild(sprite2, 20) - local sprite3 = cc.Sprite:create("Images/YellowSquare.png") - sprite3:setPosition(cc.p(0, 0)) + local sprite3 = ax.Sprite:create("Images/YellowSquare.png") + sprite3:setPosition(ax.p(0, 0)) sprite2:addChild(sprite3, 1) local function onTouchBegan(touch, event) local target = event:getCurrentTarget() - + local locationInNode = target:convertToNodeSpace(touch:getLocation()) local s = target:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) - - if cc.rectContainsPoint(rect, locationInNode) then + local rect = ax.rect(0, 0, s.width, s.height) + + if ax.rectContainsPoint(rect, locationInNode) then print(string.format("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y)) target:setOpacity(180) return true @@ -229,7 +229,7 @@ function TouchableSpriteTest:onEnter() local target = event:getCurrentTarget() local posX,posY = target:getPosition() local delta = touch:getDelta() - target:setPosition(cc.p(posX + delta.x, posY + delta.y)) + target:setPosition(ax.p(posX + delta.x, posY + delta.y)) end local function onTouchEnded(touch, event) @@ -243,11 +243,11 @@ function TouchableSpriteTest:onEnter() end end - local listener1 = cc.EventListenerTouchOneByOne:create() + local listener1 = ax.EventListenerTouchOneByOne:create() listener1:setSwallowTouches(true) - listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) - listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + listener1:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener1:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED ) + listener1:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener1, sprite1) @@ -259,32 +259,32 @@ function TouchableSpriteTest:onEnter() local function removeAllTouchItem(tag, sender) sender:setString("Only Next item could be clicked") - eventDispatcher:removeEventListenersForType(cc.EVENT_TOUCH_ONE_BY_ONE) + eventDispatcher:removeEventListenersForType(ax.EVENT_TOUCH_ONE_BY_ONE) - local nextMenuItem = cc.MenuItemFont:create("Next") + local nextMenuItem = ax.MenuItemFont:create("Next") nextMenuItem:setFontSizeObj(16) - nextMenuItem:setPosition(cc.p(VisibleRect:right().x - 100, VisibleRect:right().y - 30)) + nextMenuItem:setPosition(ax.p(VisibleRect:right().x - 100, VisibleRect:right().y - 30)) nextMenuItem:registerScriptTapHandler(self.nextCallback) - - local menu2 = cc.Menu:create(nextMenuItem) - menu2:setPosition(cc.p(0, 0)) - menu2:setAnchorPoint(cc.p(0, 0)) + + local menu2 = ax.Menu:create(nextMenuItem) + menu2:setPosition(ax.p(0, 0)) + menu2:setAnchorPoint(ax.p(0, 0)) self:addChild(menu2) end - local menuItem = cc.MenuItemFont:create("Remove All Touch Listeners") + local menuItem = ax.MenuItemFont:create("Remove All Touch Listeners") menuItem:setFontSizeObj(16) - menuItem:setPosition(cc.p(VisibleRect:right().x - 100, VisibleRect:right().y)) + menuItem:setPosition(ax.p(VisibleRect:right().x - 100, VisibleRect:right().y)) menuItem:registerScriptTapHandler(removeAllTouchItem) - local menu = cc.Menu:create(menuItem) - menu:setPosition(cc.p(0, 0)) - menu:setAnchorPoint(cc.p(0, 0)) + local menu = ax.Menu:create(menuItem) + menu:setPosition(ax.p(0, 0)) + menu:setAnchorPoint(ax.p(0, 0)) self:addChild(menu) end function TouchableSpriteTest.create() - local layer = TouchableSpriteTest.extend(cc.Layer:create()) + local layer = TouchableSpriteTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -292,7 +292,7 @@ function TouchableSpriteTest.create() elseif event == "exit" then end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -322,22 +322,22 @@ function TouchableSpriteWithFixedPriority:onEnter() local function onTouchBegan(touch, event) local locationInNode = self:convertToNodeSpace(touch:getLocation()) local s = self:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) - - if cc.rectContainsPoint(rect, locationInNode) then - self:setColor(cc.c3b(255, 0, 0)) + local rect = ax.rect(0, 0, s.width, s.height) + + if ax.rectContainsPoint(rect, locationInNode) then + self:setColor(ax.color32(255, 0, 0)) return true end - return false + return false end local function onTouchMoved(touch, event) - + end local function onTouchEnded(touch, event) - self:setColor(cc.c3b(255, 255, 255)) + self:setColor(ax.color32(255, 255, 255)) if self._removeListenerOnTouchEnded then eventDispatcher:removeEventListener(self._listener) self._listener = nil @@ -345,13 +345,13 @@ function TouchableSpriteWithFixedPriority:onEnter() end - local listener = cc.EventListenerTouchOneByOne:create() + local listener = ax.EventListenerTouchOneByOne:create() self._listener = listener listener:setSwallowTouches(true) - - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) - listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED ) + listener:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) if 0 == self._fixedPriority then eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -382,7 +382,7 @@ function TouchableSpriteWithFixedPriority:setPriorityWithThis(useNodePriority) end function TouchableSpriteWithFixedPriority.create() - local touchableSprite = TouchableSpriteWithFixedPriority.extend(cc.Sprite:create()) + local touchableSprite = TouchableSpriteWithFixedPriority.extend(ax.Sprite:create()) local function onNodeEvent(event) if event == "enter" then @@ -391,7 +391,7 @@ function TouchableSpriteWithFixedPriority.create() touchableSprite:onExit() end end - + touchableSprite:registerScriptHandler(onNodeEvent) return touchableSprite end @@ -410,30 +410,30 @@ function FixedPriorityTest.extend(target) end function FixedPriorityTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() local sprite1 = TouchableSpriteWithFixedPriority.create() sprite1:setTexture("Images/CyanSquare.png") sprite1:setPriority(30) - sprite1:setPosition(cc.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) + sprite1:setPosition(ax.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) self:addChild(sprite1, 10) local sprite2 = TouchableSpriteWithFixedPriority.create() sprite2:setTexture("Images/MagentaSquare.png") sprite2:setPriority(20) - sprite2:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2) ) + sprite2:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2) ) self:addChild(sprite2, 20) local sprite3 = TouchableSpriteWithFixedPriority:create() sprite3:setTexture("Images/YellowSquare.png") sprite3:setPriority(10) - sprite3:setPosition(cc.p(0, 0)) + sprite3:setPosition(ax.p(0, 0)) sprite2:addChild(sprite3, 1) end function FixedPriorityTest.create() - local layer = FixedPriorityTest.extend(cc.Layer:create()) + local layer = FixedPriorityTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -441,7 +441,7 @@ function FixedPriorityTest.create() elseif event == "exit" then end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -462,43 +462,43 @@ function RemoveListenerWhenDispatchingTest.extend(target) end function RemoveListenerWhenDispatchingTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() - local sprite1 = cc.Sprite:create("Images/CyanSquare.png") - sprite1:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + local sprite1 = ax.Sprite:create("Images/CyanSquare.png") + sprite1:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) self:addChild(sprite1, 10) local function onTouchBegan(touch, event) local locationInNode = sprite1:convertToNodeSpace(touch:getLocation()) local s = sprite1:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) + local rect = ax.rect(0, 0, s.width, s.height) - if cc.rectContainsPoint(rect, locationInNode) then - sprite1:setColor(cc.c3b(255, 0, 0)) + if ax.rectContainsPoint(rect, locationInNode) then + sprite1:setColor(ax.color32(255, 0, 0)) return true end - + return false end local function onTouchEnded(touch, event) - sprite1:setColor(cc.c3b(255, 255, 255)) + sprite1:setColor(ax.color32(255, 255, 255)) end - local listener1 = cc.EventListenerTouchOneByOne:create() + local listener1 = ax.EventListenerTouchOneByOne:create() listener1:setSwallowTouches(true) self:setUserObject(listener1) - listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + listener1:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener1:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener1, sprite1) - local statusLabel = cc.Label:createWithSystemFont("The sprite could be touched!", "", 20) - statusLabel:setAnchorPoint(cc.p(0.5, 0.5)) - statusLabel:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height - 90)) + local statusLabel = ax.Label:createWithSystemFont("The sprite could be touched!", "", 20) + statusLabel:setAnchorPoint(ax.p(0.5, 0.5)) + statusLabel:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height - 90)) self:addChild(statusLabel) local enable = true @@ -514,18 +514,18 @@ function RemoveListenerWhenDispatchingTest:onEnter() end end - local toggleItem = cc.MenuItemToggle:create(cc.MenuItemFont:create("Enabled"), cc.MenuItemFont:create("Disabled")) - toggleItem:setPosition(cc.p(origin.x + size.width/2, origin.y + 80)) + local toggleItem = ax.MenuItemToggle:create(ax.MenuItemFont:create("Enabled"), ax.MenuItemFont:create("Disabled")) + toggleItem:setPosition(ax.p(origin.x + size.width/2, origin.y + 80)) toggleItem:registerScriptTapHandler(toggleCallback) - local menu = cc.Menu:create(toggleItem) - menu:setPosition(cc.p(0, 0)) - menu:setAnchorPoint(cc.p(0, 0)) + local menu = ax.Menu:create(toggleItem) + menu:setPosition(ax.p(0, 0)) + menu:setAnchorPoint(ax.p(0, 0)) self:addChild(menu, -1) end function RemoveListenerWhenDispatchingTest.create() - local layer = RemoveListenerWhenDispatchingTest.extend(cc.Layer:create()) + local layer = RemoveListenerWhenDispatchingTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -533,7 +533,7 @@ function RemoveListenerWhenDispatchingTest.create() elseif event == "exit" then end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -556,16 +556,16 @@ function CustomEventTest.extend(target) end function CustomEventTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() local count1 = 0 local count2 = 0 - - cc.MenuItemFont:setFontSize(20) - local statusLabel1 = cc.Label:createWithSystemFont("No custom event 1 received!", "", 20) - statusLabel1:setAnchorPoint(cc.p(0.5, 0.5)) - statusLabel1:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height-90 )) + ax.MenuItemFont:setFontSize(20) + + local statusLabel1 = ax.Label:createWithSystemFont("No custom event 1 received!", "", 20) + statusLabel1:setAnchorPoint(ax.p(0.5, 0.5)) + statusLabel1:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height-90 )) self:addChild(statusLabel1) local function eventCustomListener1(event) @@ -573,25 +573,25 @@ function CustomEventTest:onEnter() statusLabel1:setString(str) end - local listener1 = cc.EventListenerCustom:create("game_custom_event1",eventCustomListener1) + local listener1 = ax.EventListenerCustom:create("game_custom_event1",eventCustomListener1) self._listener1 = listener1 local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithFixedPriority(listener1, 1) local function sendCallback1(tag, sender) count1 = count1 + 1 - - local event = cc.EventCustom:new("game_custom_event1") + + local event = ax.EventCustom:new("game_custom_event1") event._usedata = string.format("%d",count1) eventDispatcher:dispatchEvent(event) end - local sendItem1 = cc.MenuItemFont:create("Send Custom Event 1") + local sendItem1 = ax.MenuItemFont:create("Send Custom Event 1") sendItem1:registerScriptTapHandler(sendCallback1) - sendItem1:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + sendItem1:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) - local statusLabel2 = cc.Label:createWithSystemFont("No custom event 2 received!", "", 20) - statusLabel2:setAnchorPoint(cc.p(0.5, 0.5)) - statusLabel2:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height-120 )) + local statusLabel2 = ax.Label:createWithSystemFont("No custom event 2 received!", "", 20) + statusLabel2:setAnchorPoint(ax.p(0.5, 0.5)) + statusLabel2:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height-120 )) self:addChild(statusLabel2) local function eventCustomListener2(event) @@ -599,24 +599,24 @@ function CustomEventTest:onEnter() statusLabel2:setString(str) end - local listener2 = cc.EventListenerCustom:create("game_custom_event2",eventCustomListener2) + local listener2 = ax.EventListenerCustom:create("game_custom_event2",eventCustomListener2) CustomEventTest._listener2 = listener2 eventDispatcher:addEventListenerWithFixedPriority(listener2, 1) local function sendCallback2(tag, sender) count2 = count2 + 1 - - local event = cc.EventCustom:new("game_custom_event2") + + local event = ax.EventCustom:new("game_custom_event2") event._usedata = string.format("%d",count2) eventDispatcher:dispatchEvent(event) end - local sendItem2 = cc.MenuItemFont:create("Send Custom Event 2") + local sendItem2 = ax.MenuItemFont:create("Send Custom Event 2") sendItem2:registerScriptTapHandler(sendCallback2) - sendItem2:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2 - 40)) + sendItem2:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2 - 40)) - local menu = cc.Menu:create(sendItem1, sendItem2) - menu:setPosition(cc.p(0, 0)) - menu:setAnchorPoint(cc.p(0, 0)) + local menu = ax.Menu:create(sendItem1, sendItem2) + menu:setPosition(ax.p(0, 0)) + menu:setAnchorPoint(ax.p(0, 0)) self:addChild(menu, -1) end @@ -627,7 +627,7 @@ function CustomEventTest:onExit() end function CustomEventTest.create() - local layer = CustomEventTest.extend(cc.Layer:create()) + local layer = CustomEventTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -636,7 +636,7 @@ function CustomEventTest.create() layer:onExit() end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -659,12 +659,12 @@ function LabelKeyboardEventTest.extend(target) end function LabelKeyboardEventTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - - local statusLabel = cc.Label:createWithSystemFont("No keyboard event received!", "", 20) - statusLabel:setAnchorPoint(cc.p(0.5, 0.5)) - statusLabel:setPosition(cc.p(origin.x + size.width/2,origin.y + size.height/2)) + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + + local statusLabel = ax.Label:createWithSystemFont("No keyboard event received!", "", 20) + statusLabel:setAnchorPoint(ax.p(0.5, 0.5)) + statusLabel:setPosition(ax.p(origin.x + size.width/2,origin.y + size.height/2)) self:addChild(statusLabel) local function onKeyPressed(keyCode, event) @@ -679,9 +679,9 @@ function LabelKeyboardEventTest:onEnter() label:setString(buf) end - local listener = cc.EventListenerKeyboard:create() - listener:registerScriptHandler(onKeyPressed, cc.Handler.EVENT_KEYBOARD_PRESSED ) - listener:registerScriptHandler(onKeyReleased, cc.Handler.EVENT_KEYBOARD_RELEASED ) + local listener = ax.EventListenerKeyboard:create() + listener:registerScriptHandler(onKeyPressed, ax.Handler.EVENT_KEYBOARD_PRESSED ) + listener:registerScriptHandler(onKeyReleased, ax.Handler.EVENT_KEYBOARD_RELEASED ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, statusLabel) @@ -689,7 +689,7 @@ end function LabelKeyboardEventTest.create() - local layer = LabelKeyboardEventTest.extend(cc.Layer:create()) + local layer = LabelKeyboardEventTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -697,7 +697,7 @@ function LabelKeyboardEventTest.create() elseif event == "exit" then end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -719,10 +719,10 @@ end function SpriteAccelerationEventTest:onEnter() self:setAccelerometerEnabled(true) - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - local sprite = cc.Sprite:create("Images/ball.png") - sprite:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y)) + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + local sprite = ax.Sprite:create("Images/ball.png") + sprite:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y)) self:addChild(sprite) local function accelerometerListener(event,x,y,z,timestamp) @@ -739,7 +739,7 @@ function SpriteAccelerationEventTest:onEnter() elseif ptNowX > maxX then ptNowX = maxX end - + local minY = math.floor(VisibleRect:bottom().y + ballSize.height / 2.0) local maxY = math.floor(VisibleRect:top().y - ballSize.height / 2.0) if ptNowY < minY then @@ -748,10 +748,10 @@ function SpriteAccelerationEventTest:onEnter() ptNowY = maxY end - target:setPosition(cc.p(ptNowX , ptNowY)) + target:setPosition(ax.p(ptNowX , ptNowY)) end - local listener = cc.EventListenerAcceleration:create(accelerometerListener) + local listener = ax.EventListenerAcceleration:create(accelerometerListener) self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener, sprite) end @@ -761,7 +761,7 @@ function SpriteAccelerationEventTest:onExit() end function SpriteAccelerationEventTest.create() - local layer = SpriteAccelerationEventTest.extend(cc.Layer:create()) + local layer = SpriteAccelerationEventTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -770,7 +770,7 @@ function SpriteAccelerationEventTest.create() layer:onExit() end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -795,11 +795,11 @@ end function RemoveAndRetainNodeTest:onEnter() self._spriteSaved = false - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() - local sprite = cc.Sprite:create("Images/CyanSquare.png") - sprite:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + local sprite = ax.Sprite:create("Images/CyanSquare.png") + sprite:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) self._sprite = sprite self:addChild(sprite, 10) @@ -807,14 +807,14 @@ function RemoveAndRetainNodeTest:onEnter() local target = event:getCurrentTarget() local locationInNode = target:convertToNodeSpace(touch:getLocation()) local s = target:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) - - if cc.rectContainsPoint(rect, locationInNode) then + local rect = ax.rect(0, 0, s.width, s.height) + + if ax.rectContainsPoint(rect, locationInNode) then print(string.format("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y)) target:setOpacity(180) return true end - return false + return false end local function onTouchMoved(touch,event) @@ -824,12 +824,12 @@ function RemoveAndRetainNodeTest:onEnter() local force = touch:getCurrentForce() local maxForce = touch:getMaxForce() if force > 0.0 and (force / maxForce) > 0.8 then - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - target:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + target:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) print(string.format("3D touch detected, reset to default position. force = %f, max force = %f", force, maxForce)) else - target:setPosition(cc.p(posX + delta.x, posY + delta.y)) + target:setPosition(ax.p(posX + delta.x, posY + delta.y)) end end @@ -839,11 +839,11 @@ function RemoveAndRetainNodeTest:onEnter() target:setOpacity(255) end - local listener1 = cc.EventListenerTouchOneByOne:create() + local listener1 = ax.EventListenerTouchOneByOne:create() listener1:setSwallowTouches(true) - listener1:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN) - listener1:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED) - listener1:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED) + listener1:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN) + listener1:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED) + listener1:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED) self:getEventDispatcher():addEventListenerWithSceneGraphPriority(listener1, sprite) local function retainSprite() @@ -858,10 +858,10 @@ function RemoveAndRetainNodeTest:onEnter() self._sprite:release() end - self:runAction( cc.Sequence:create(cc.DelayTime:create(5.0), - cc.CallFunc:create(retainSprite), - cc.DelayTime:create(5.0), - cc.CallFunc:create(releaseSprite) + self:runAction( ax.Sequence:create(ax.DelayTime:create(5.0), + ax.CallFunc:create(retainSprite), + ax.DelayTime:create(5.0), + ax.CallFunc:create(releaseSprite) )) end @@ -873,7 +873,7 @@ function RemoveAndRetainNodeTest:onExit() end function RemoveAndRetainNodeTest.create() - local layer = RemoveAndRetainNodeTest.extend(cc.Layer:create()) + local layer = RemoveAndRetainNodeTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -882,7 +882,7 @@ function RemoveAndRetainNodeTest.create() layer:onExit() end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -914,15 +914,15 @@ function RemoveListenerAfterAddingTest:onEnter() return true end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) eventDispatcher:addEventListenerWithFixedPriority(listener, -1) eventDispatcher:removeEventListener(listener) end - local item1 = cc.MenuItemFont:create("Click Me 1") + local item1 = ax.MenuItemFont:create("Click Me 1") item1:registerScriptTapHandler(item1Callback) - item1:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 80)) + item1:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y + 80)) local function addNextButton() @@ -930,13 +930,13 @@ function RemoveListenerAfterAddingTest:onEnter() self.restartCallback() end - local nextButton = cc.MenuItemFont:create("Please Click Me To Reset!") + local nextButton = ax.MenuItemFont:create("Please Click Me To Reset!") nextButton:registerScriptTapHandler(nextButtonCallback) - nextButton:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y - 40)) - - local menu = cc.Menu:create(nextButton) + nextButton:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y - 40)) + + local menu = ax.Menu:create(nextButton) menu:setPosition(VisibleRect:leftBottom()) - menu:setAnchorPoint(cc.p(0,0)) + menu:setAnchorPoint(ax.p(0,0)) self:addChild(menu) end @@ -947,19 +947,19 @@ function RemoveListenerAfterAddingTest:onEnter() return true end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN) - + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN) + eventDispatcher:addEventListenerWithFixedPriority(listener, -1) - eventDispatcher:removeEventListenersForType(cc.EVENT_TOUCH_ONE_BY_ONE) - + eventDispatcher:removeEventListenersForType(ax.EVENT_TOUCH_ONE_BY_ONE) + addNextButton() end - local item2 = cc.MenuItemFont:create("Click Me 2") + local item2 = ax.MenuItemFont:create("Click Me 2") item2:registerScriptTapHandler(item2Callback) - item2:setPosition(cc.p(VisibleRect:center().x, VisibleRect:center().y + 40)) + item2:setPosition(ax.p(VisibleRect:center().x, VisibleRect:center().y + 40)) local function item3Callback( tag, sender ) @@ -968,23 +968,23 @@ function RemoveListenerAfterAddingTest:onEnter() return true end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN) - + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN) + eventDispatcher:addEventListenerWithFixedPriority(listener, -1) eventDispatcher:removeAllEventListeners() - + addNextButton() end - local item3 = cc.MenuItemFont:create("Click Me 3") + local item3 = ax.MenuItemFont:create("Click Me 3") item3:registerScriptTapHandler(item3Callback) item3:setPosition(VisibleRect:center()) - local menu = cc.Menu:create(item1, item2, item3) + local menu = ax.Menu:create(item1, item2, item3) menu:setPosition(VisibleRect:leftBottom()) - menu:setAnchorPoint(cc.p(0,0)) + menu:setAnchorPoint(ax.p(0,0)) self:addChild(menu) end @@ -994,7 +994,7 @@ function RemoveListenerAfterAddingTest:onExit() end function RemoveListenerAfterAddingTest.create() - local layer = RemoveListenerAfterAddingTest.extend(cc.Layer:create()) + local layer = RemoveListenerAfterAddingTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1003,7 +1003,7 @@ function RemoveListenerAfterAddingTest.create() layer:onExit() end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -1029,12 +1029,12 @@ end function GlobalZTouchTest:onEnter() local function onTouchBegan(touch, event) local target = event:getCurrentTarget() - + local locationInNode = target:convertToNodeSpace(touch:getLocation()) local s = target:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) - - if cc.rectContainsPoint(rect, locationInNode) then + local rect = ax.rect(0, 0, s.width, s.height) + + if ax.rectContainsPoint(rect, locationInNode) then print(string.format("sprite began... x = %f, y = %f", locationInNode.x, locationInNode.y)) target:setOpacity(180) return true @@ -1046,7 +1046,7 @@ function GlobalZTouchTest:onEnter() local target = event:getCurrentTarget() local posX,posY = target:getPosition() local delta = touch:getDelta() - target:setPosition(cc.p(posX + delta.x, posY + delta.y)) + target:setPosition(ax.p(posX + delta.x, posY + delta.y)) end local function onTouchEnded(touch, event) @@ -1055,27 +1055,27 @@ function GlobalZTouchTest:onEnter() target:setOpacity(255) end - local listener = cc.EventListenerTouchOneByOne:create() + local listener = ax.EventListenerTouchOneByOne:create() listener:setSwallowTouches(true) - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) - listener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED ) + listener:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) local SPRITE_COUNT = 8 for i = 0, SPRITE_COUNT - 1 do local sprite = nil if 4 == i then - sprite = cc.Sprite:create("Images/CyanSquare.png") + sprite = ax.Sprite:create("Images/CyanSquare.png") self._sprite = sprite self._sprite:setGlobalZOrder(-1) else - sprite = cc.Sprite:create("Images/YellowSquare.png") + sprite = ax.Sprite:create("Images/YellowSquare.png") end local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener:clone(), sprite) self._layer:addChild(sprite) - local visibleSize = cc.Director:getInstance():getVisibleSize() + local visibleSize = ax.Director:getInstance():getVisibleSize() sprite:setPosition(VisibleRect:left().x + visibleSize.width / (SPRITE_COUNT - 1) * i, VisibleRect:center().y) end @@ -1095,7 +1095,7 @@ function GlobalZTouchTest:onExit() end function GlobalZTouchTest.create() - local layer = GlobalZTouchTest.extend(cc.Layer:create()) + local layer = GlobalZTouchTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1104,7 +1104,7 @@ function GlobalZTouchTest.create() layer:onExit() end end - + layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) @@ -1149,10 +1149,10 @@ function StopPropagationTest:onEnter() target:setOpacity(255) end - local touchOneByOneListener = cc.EventListenerTouchOneByOne:create() + local touchOneByOneListener = ax.EventListenerTouchOneByOne:create() touchOneByOneListener:setSwallowTouches(true) - touchOneByOneListener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - touchOneByOneListener:registerScriptHandler(onTouchEnded,cc.Handler.EVENT_TOUCH_ENDED ) + touchOneByOneListener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + touchOneByOneListener:registerScriptHandler(onTouchEnded,ax.Handler.EVENT_TOUCH_ENDED ) local function onTouchesBegan(touches, event) if self:isPointInTopHalfAreaOfScreen(touches[1]:getLocation()) then @@ -1180,9 +1180,9 @@ function StopPropagationTest:onEnter() event:stopPropagation() end - local touchAllAtOnceListener = cc.EventListenerTouchAllAtOnce:create() - touchAllAtOnceListener:registerScriptHandler(onTouchesBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - touchAllAtOnceListener:registerScriptHandler(onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local touchAllAtOnceListener = ax.EventListenerTouchAllAtOnce:create() + touchAllAtOnceListener:registerScriptHandler(onTouchesBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + touchAllAtOnceListener:registerScriptHandler(onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local function onKeyPressed(key, event) local target = event:getCurrentTarget() @@ -1190,8 +1190,8 @@ function StopPropagationTest:onEnter() event:stopPropagation() end - local keyboardEventListener = cc.EventListenerKeyboard:create() - keyboardEventListener:registerScriptHandler(onKeyPressed, cc.Handler.EVENT_KEYBOARD_PRESSED ) + local keyboardEventListener = ax.EventListenerKeyboard:create() + keyboardEventListener:registerScriptHandler(onKeyPressed, ax.Handler.EVENT_KEYBOARD_PRESSED ) local eventDispatcher = self:getEventDispatcher() @@ -1200,18 +1200,18 @@ function StopPropagationTest:onEnter() local sprite2 = nil if 4 == i then - sprite = cc.Sprite:create("Images/CyanSquare.png") + sprite = ax.Sprite:create("Images/CyanSquare.png") sprite:setTag(TAG_BLUE_SPRITE) self:addChild(sprite, 100) - - sprite2 = cc.Sprite:create("Images/CyanSquare.png") + + sprite2 = ax.Sprite:create("Images/CyanSquare.png") sprite2:setTag(TAG_BLUE_SPRITE2) self:addChild(sprite2, 100) else - sprite = cc.Sprite:create("Images/YellowSquare.png") + sprite = ax.Sprite:create("Images/YellowSquare.png") self:addChild(sprite, 0) - - sprite2 = cc.Sprite:create("Images/YellowSquare.png") + + sprite2 = ax.Sprite:create("Images/YellowSquare.png") self:addChild(sprite2, 0) end @@ -1221,7 +1221,7 @@ function StopPropagationTest:onEnter() eventDispatcher:addEventListenerWithSceneGraphPriority(touchAllAtOnceListener:clone(), sprite2) eventDispatcher:addEventListenerWithSceneGraphPriority(keyboardEventListener:clone(), sprite2) - local visibleSize = cc.Director:getInstance():getVisibleSize() + local visibleSize = ax.Director:getInstance():getVisibleSize() sprite:setPosition(VisibleRect:left().x + visibleSize.width / (SPRITE_COUNT - 1) * i, VisibleRect:center().y + sprite2:getContentSize().height / 2 + 10) sprite2:setPosition(VisibleRect:left().x + visibleSize.width / (SPRITE_COUNT - 1) * i, VisibleRect:center().y - sprite2:getContentSize().height / 2 - 10) @@ -1231,30 +1231,30 @@ function StopPropagationTest:onEnter() end function StopPropagationTest:onExit() - + end function StopPropagationTest:isPointInNode(pt, node) local locationInNode = node:convertToNodeSpace(pt) local s = node:getContentSize() - local rect = cc.rect(0, 0, s.width, s.height) - if cc.rectContainsPoint(rect, locationInNode) then + local rect = ax.rect(0, 0, s.width, s.height) + if ax.rectContainsPoint(rect, locationInNode) then return true end return false end function StopPropagationTest:isPointInTopHalfAreaOfScreen(pt) - local winSize = cc.Director:getInstance():getWinSize() + local winSize = ax.Director:getInstance():getWinSize() if pt.y >= winSize.height / 2 then return true end - + return false end function StopPropagationTest.create() - local layer = StopPropagationTest.extend(cc.Layer:create()) + local layer = StopPropagationTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1267,7 +1267,7 @@ function StopPropagationTest.create() layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) - + return layer end @@ -1284,22 +1284,22 @@ function PauseResumeTargetTest.extend(target) end function PauseResumeTargetTest:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + local sprite1 = TouchableSpriteWithFixedPriority.create() sprite1:setTexture("Images/CyanSquare.png") - sprite1:setPosition(cc.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) + sprite1:setPosition(ax.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) self:addChild(sprite1, -10) - + local sprite2 = TouchableSpriteWithFixedPriority.create() sprite2:setTexture("Images/MagentaSquare.png") - sprite2:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + sprite2:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) self:addChild(sprite2, -20) - + local sprite3 = TouchableSpriteWithFixedPriority.create() sprite3:setTexture("Images/YellowSquare.png") - sprite3:setPosition(cc.p(0, 0)) + sprite3:setPosition(ax.p(0, 0)) sprite2:addChild(sprite3, -1) @@ -1307,42 +1307,42 @@ function PauseResumeTargetTest:onEnter() local eventDispatcher = self:getEventDispatcher() eventDispatcher:pauseEventListenersForTarget(self, true) - local colorLayer = cc.LayerColor:create(cc.c4b(0, 0, 255, 100)) + local colorLayer = ax.LayerColor:create(ax.color32(0, 0, 255, 100)) self:addChild(colorLayer, 99999) local function closePopUp(tag, sender) colorLayer:removeFromParent() eventDispatcher:resumeEventListenersForTarget(self, true) end - local closeItem = cc.MenuItemFont:create("close") + local closeItem = ax.MenuItemFont:create("close") closeItem:registerScriptTapHandler(closePopUp) closeItem:setPosition(VisibleRect:center()) - - local closeMenu = cc.Menu:create(closeItem) - closeMenu:setAnchorPoint(cc.p(0.0, 0.0)) - closeMenu:setPosition(cc.p(0.0, 0.0)) - + + local closeMenu = ax.Menu:create(closeItem) + closeMenu:setAnchorPoint(ax.p(0.0, 0.0)) + closeMenu:setPosition(ax.p(0.0, 0.0)) + colorLayer:addChild(closeMenu) end - local popUpItem = cc.MenuItemFont:create("Popup") - popUpItem:registerScriptTapHandler(popUp) - popUpItem:setAnchorPoint(cc.p(1.0, 0.5)) + local popUpItem = ax.MenuItemFont:create("Popup") + popUpItem:registerScriptTapHandler(popUp) + popUpItem:setAnchorPoint(ax.p(1.0, 0.5)) popUpItem:setPosition(VisibleRect:right()) - - local menu = cc.Menu:create(popUpItem) - menu:setAnchorPoint(cc.p(0.0, 0.0)) - menu:setPosition(cc.p(0.0, 0.0)) - + + local menu = ax.Menu:create(popUpItem) + menu:setAnchorPoint(ax.p(0.0, 0.0)) + menu:setPosition(ax.p(0.0, 0.0)) + self:addChild(menu) end function PauseResumeTargetTest:onExit() - + end function PauseResumeTargetTest.create() - local layer = PauseResumeTargetTest.extend(cc.Layer:create()) + local layer = PauseResumeTargetTest.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1355,7 +1355,7 @@ function PauseResumeTargetTest.create() layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) - + return layer end @@ -1377,53 +1377,53 @@ function Issue4129Test:onEnter() local eventDispatcher = self:getEventDispatcher() local function eventCustomListener(event) - local label = cc.Label:createWithSystemFont("Yeah, this issue was fixed.", "", 20) - label:setAnchorPoint(cc.p(0, 0.5)) + local label = ax.Label:createWithSystemFont("Yeah, this issue was fixed.", "", 20) + label:setAnchorPoint(ax.p(0, 0.5)) label:setPosition(VisibleRect:left()) self:addChild(label) - + eventDispatcher:removeEventListener(self._customListener) self._customListener = nil bugFixed = true end - self._customListener = cc.EventListenerCustom:create("event_come_to_background",eventCustomListener) + self._customListener = ax.EventListenerCustom:create("event_come_to_background",eventCustomListener) eventDispatcher:addEventListenerWithFixedPriority(self._customListener, 1) local function removeAllTouch(tag, sender) local senderItem = sender senderItem:setString("Only 'Reset' item could be clicked") - + eventDispatcher:removeAllEventListeners() - + local function next(tag, sender) assert(bugFixed, "This issue was not fixed!") self.restartCallback() end - local nextItem = cc.MenuItemFont:create("Reset") + local nextItem = ax.MenuItemFont:create("Reset") nextItem:registerScriptTapHandler(next) nextItem:setFontSizeObj(16) - nextItem:setPosition(cc.p(VisibleRect:right().x - 100 , VisibleRect:right().y - 30)) - - local menu2 = cc.Menu:create(nextItem) - menu2:setPosition(cc.p(0, 0)) - menu2:setAnchorPoint(cc.p(0, 0)) + nextItem:setPosition(ax.p(VisibleRect:right().x - 100 , VisibleRect:right().y - 30)) + + local menu2 = ax.Menu:create(nextItem) + menu2:setPosition(ax.p(0, 0)) + menu2:setAnchorPoint(ax.p(0, 0)) self:addChild(menu2) - + --Simulate to dispatch 'come to background' event - local event = cc.EventCustom:new("event_come_to_background") + local event = ax.EventCustom:new("event_come_to_background") eventDispatcher:dispatchEvent(event) end - local removeAllTouchItem = cc.MenuItemFont:create("Remove All Listeners") + local removeAllTouchItem = ax.MenuItemFont:create("Remove All Listeners") removeAllTouchItem:registerScriptTapHandler(removeAllTouch) removeAllTouchItem:setFontSizeObj(16) - removeAllTouchItem:setPosition(cc.p(VisibleRect:right().x - 100, VisibleRect:right().y)) - - local menu = cc.Menu:create(removeAllTouchItem) - menu:setPosition(cc.p(0, 0)) - menu:setAnchorPoint(cc.p(0, 0)) + removeAllTouchItem:setPosition(ax.p(VisibleRect:right().x - 100, VisibleRect:right().y)) + + local menu = ax.Menu:create(removeAllTouchItem) + menu:setPosition(ax.p(0, 0)) + menu:setAnchorPoint(ax.p(0, 0)) self:addChild(menu) end @@ -1435,7 +1435,7 @@ function Issue4129Test:onExit() end function Issue4129Test.create() - local layer = Issue4129Test.extend(cc.Layer:create()) + local layer = Issue4129Test.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1448,7 +1448,7 @@ function Issue4129Test.create() layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) - + return layer end @@ -1466,26 +1466,26 @@ function Issue4160Test.extend(target) end function Issue4160Test:onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local size = cc.Director:getInstance():getVisibleSize() - + local origin = ax.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + local sprite1 = TouchableSpriteWithFixedPriority.create() sprite1:setPriority(-30) sprite1:setTexture("Images/CyanSquare.png") - sprite1:setPosition(cc.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) + sprite1:setPosition(ax.p(origin.x + size.width/2 - 80, origin.y + size.height/2 + 40)) self:addChild(sprite1, -10) - + local sprite2 = TouchableSpriteWithFixedPriority.create() sprite2:setPriority(-20) sprite2:setTexture("Images/MagentaSquare.png") sprite2:removeListenerOnTouchEnded(true) - sprite2:setPosition(cc.p(origin.x + size.width/2, origin.y + size.height/2)) + sprite2:setPosition(ax.p(origin.x + size.width/2, origin.y + size.height/2)) self:addChild(sprite2, -20) - + local sprite3 = TouchableSpriteWithFixedPriority.create() sprite3:setPriority(-10) sprite3:setTexture("Images/YellowSquare.png") - sprite3:setPosition(cc.p(0, 0)) + sprite3:setPosition(ax.p(0, 0)) sprite2:addChild(sprite3, -1) end @@ -1494,7 +1494,7 @@ function Issue4160Test:onExit() end function Issue4160Test.create() - local layer = Issue4160Test.extend(cc.Layer:create()) + local layer = Issue4160Test.extend(ax.Layer:create()) local function onNodeEvent(event) if event == "enter" then @@ -1507,7 +1507,7 @@ function Issue4160Test.create() layer:createMenu() layer:creatTitleAndSubTitle(curLayerIdx) layer:registerScriptHandler(onNodeEvent) - + return layer end diff --git a/tests/lua-tests/Content/src/NodeTest/NodeTest.lua b/tests/lua-tests/Content/src/NodeTest/NodeTest.lua index 7b982576f168..9781a4f924bf 100644 --- a/tests/lua-tests/Content/src/NodeTest/NodeTest.lua +++ b/tests/lua-tests/Content/src/NodeTest/NodeTest.lua @@ -3,11 +3,11 @@ local kTagSprite2 = 2 local kTagSprite3 = 3 local kTagSlider = 4 -local s = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local s = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local function getBaseLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) @@ -21,50 +21,50 @@ local function CameraCenterTest() local layer = getBaseLayer() -- LEFT-TOP - local sprite = cc.Sprite:create("Images/white-512x512.png") + local sprite = ax.Sprite:create("Images/white-512x512.png") layer:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 5 * 1, s.height / 5 * 1)) - sprite:setColor(cc.c3b(255, 0, 0)) - sprite:setTextureRect(cc.rect(0, 0, 120, 50)) - local orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) - -- [sprite setAnchorPoint: cc.p(0,1)) + sprite:setPosition(ax.p(s.width / 5 * 1, s.height / 5 * 1)) + sprite:setColor(ax.color32(255, 0, 0)) + sprite:setTextureRect(ax.rect(0, 0, 120, 50)) + local orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) + -- [sprite setAnchorPoint: ax.p(0,1)) -- LEFT-BOTTOM - sprite = cc.Sprite:create("Images/white-512x512.png") + sprite = ax.Sprite:create("Images/white-512x512.png") layer:addChild(sprite, 0, 40) - sprite:setPosition(cc.p(s.width / 5 * 1, s.height / 5 * 4)) - sprite:setColor(cc.c3b(0, 0, 255)) - sprite:setTextureRect(cc.rect(0, 0, 120, 50)) - orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 5 * 1, s.height / 5 * 4)) + sprite:setColor(ax.color32(0, 0, 255)) + sprite:setTextureRect(ax.rect(0, 0, 120, 50)) + orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) -- RIGHT-TOP - sprite = cc.Sprite:create("Images/white-512x512.png") + sprite = ax.Sprite:create("Images/white-512x512.png") layer:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 5 * 4, s.height / 5 * 1)) - sprite:setColor(cc.c3b(255, 255, 0)) - sprite:setTextureRect(cc.rect(0, 0, 120, 50)) - orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 5 * 4, s.height / 5 * 1)) + sprite:setColor(ax.color32(255, 255, 0)) + sprite:setTextureRect(ax.rect(0, 0, 120, 50)) + orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) -- RIGHT-BOTTOM - sprite = cc.Sprite:create("Images/white-512x512.png") + sprite = ax.Sprite:create("Images/white-512x512.png") layer:addChild(sprite, 0, 40) - sprite:setPosition(cc.p(s.width / 5 * 4, s.height / 5 * 4)) - sprite:setColor(cc.c3b(0, 255, 0)) - sprite:setTextureRect(cc.rect(0, 0, 120, 50)) - orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 5 * 4, s.height / 5 * 4)) + sprite:setColor(ax.color32(0, 255, 0)) + sprite:setTextureRect(ax.rect(0, 0, 120, 50)) + orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) -- CENTER - sprite = cc.Sprite:create("Images/white-512x512.png") + sprite = ax.Sprite:create("Images/white-512x512.png") layer:addChild(sprite, 0, 40) - sprite:setPosition(cc.p(s.width / 2, s.height / 2)) - sprite:setColor(cc.c3b(255, 255, 255)) - sprite:setTextureRect(cc.rect(0, 0, 120, 50)) - orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 2, s.height / 2)) + sprite:setColor(ax.color32(255, 255, 255)) + sprite:setTextureRect(ax.rect(0, 0, 120, 50)) + orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) Helper.titleLabel:setString("Camera Center test") Helper.subtitleLabel:setString("Sprites should rotate at the same speed") @@ -77,13 +77,13 @@ end local function Test2() local layer = getBaseLayer() - local sp1 = cc.Sprite:create(s_pPathSister1) - local sp2 = cc.Sprite:create(s_pPathSister2) - local sp3 = cc.Sprite:create(s_pPathSister1) - local sp4 = cc.Sprite:create(s_pPathSister2) + local sp1 = ax.Sprite:create(s_pPathSister1) + local sp2 = ax.Sprite:create(s_pPathSister2) + local sp3 = ax.Sprite:create(s_pPathSister1) + local sp4 = ax.Sprite:create(s_pPathSister2) - sp1:setPosition(cc.p(100, s.height /2)) - sp2:setPosition(cc.p(380, s.height /2)) + sp1:setPosition(ax.p(100, s.height /2)) + sp2:setPosition(ax.p(380, s.height /2)) layer:addChild(sp1) layer:addChild(sp2) @@ -92,13 +92,13 @@ local function Test2() sp1:addChild(sp3) sp2:addChild(sp4) - local a1 = cc.RotateBy:create(2, 360) - local a2 = cc.ScaleBy:create(2, 2) + local a1 = ax.RotateBy:create(2, 360) + local a2 = ax.ScaleBy:create(2, 2) - local action1 = cc.RepeatForever:create(cc.Sequence:create(a1, a2, a2:reverse())) - local action2 = cc.RepeatForever:create(cc.Sequence:create(a1:clone(), a2:clone(), a2:reverse())) + local action1 = ax.RepeatForever:create(ax.Sequence:create(a1, a2, a2:reverse())) + local action2 = ax.RepeatForever:create(ax.Sequence:create(a1:clone(), a2:clone(), a2:reverse())) - sp2:setAnchorPoint(cc.p(0,0)) + sp2:setAnchorPoint(ax.p(0,0)) sp1:runAction(action1) sp2:runAction(action2) @@ -116,7 +116,7 @@ local Test4_delay4Entry = nil local function delay2(dt) node = Test4_layer:getChildByTag(2) - local action1 = cc.RotateBy:create(1, 360) + local action1 = ax.RotateBy:create(1, 360) node:runAction(action1) end @@ -138,10 +138,10 @@ end local function Test4() Test4_layer = getBaseLayer() - local sp1 = cc.Sprite:create(s_pPathSister1) - local sp2 = cc.Sprite:create(s_pPathSister2) - sp1:setPosition(cc.p(100, 160)) - sp2:setPosition(cc.p(380, 160)) + local sp1 = ax.Sprite:create(s_pPathSister1) + local sp2 = ax.Sprite:create(s_pPathSister2) + sp1:setPosition(ax.p(100, 160)) + sp2:setPosition(ax.p(380, 160)) Test4_layer:addChild(sp1, 0, 2) Test4_layer:addChild(sp2, 0, 3) @@ -186,19 +186,19 @@ end local function Test5() Test5_layer = getBaseLayer() - local sp1 = cc.Sprite:create(s_pPathSister1) - local sp2 = cc.Sprite:create(s_pPathSister2) + local sp1 = ax.Sprite:create(s_pPathSister1) + local sp2 = ax.Sprite:create(s_pPathSister2) - sp1:setPosition(cc.p(100, 160)) - sp2:setPosition(cc.p(380, 160)) + sp1:setPosition(ax.p(100, 160)) + sp2:setPosition(ax.p(380, 160)) - local rot = cc.RotateBy:create(2, 360) + local rot = ax.RotateBy:create(2, 360) local rot_back = rot:reverse() - local forever = cc.RepeatForever:create(cc.Sequence:create(rot, rot_back)) + local forever = ax.RepeatForever:create(ax.Sequence:create(rot, rot_back)) - local rot2 = cc.RotateBy:create(2, 360) + local rot2 = ax.RotateBy:create(2, 360) local rot2_back = rot2:reverse() - local forever2 = cc.RepeatForever:create(cc.Sequence:create(rot2, rot2_back)) + local forever2 = ax.RepeatForever:create(ax.Sequence:create(rot2, rot2_back)) forever:setTag(101) forever2:setTag(102) @@ -249,18 +249,18 @@ end local function Test6() Test6_layer = getBaseLayer() - local sp1 = cc.Sprite:create(s_pPathSister1) - local sp11 = cc.Sprite:create(s_pPathSister1) + local sp1 = ax.Sprite:create(s_pPathSister1) + local sp11 = ax.Sprite:create(s_pPathSister1) - local sp2 = cc.Sprite:create(s_pPathSister2) - local sp21 = cc.Sprite:create(s_pPathSister2) + local sp2 = ax.Sprite:create(s_pPathSister2) + local sp21 = ax.Sprite:create(s_pPathSister2) - sp1:setPosition(cc.p(100, 160)) - sp2:setPosition(cc.p(380, 160)) + sp1:setPosition(ax.p(100, 160)) + sp2:setPosition(ax.p(380, 160)) - local rot = cc.RotateBy:create(2, 360) + local rot = ax.RotateBy:create(2, 360) local rot_back = rot:reverse() - local forever1 = cc.RepeatForever:create(cc.Sequence:create(rot, rot_back)) + local forever1 = ax.RepeatForever:create(ax.Sequence:create(rot, rot_back)) local forever11 = forever1:clone() local forever2 = forever1:clone() @@ -298,14 +298,14 @@ local function shouldNotCrash(dt) scheduler:unscheduleScriptEntry(StressTest1_entry) -- if the node has timers, it crashes - local explosion = cc.ParticleSun:create() - explosion:setTexture(cc.Director:getInstance():getTextureCache():addImage("Images/fire.png")) + local explosion = ax.ParticleSun:create() + explosion:setTexture(ax.Director:getInstance():getTextureCache():addImage("Images/fire.png")) explosion:setPosition(s.width / 2, s.height / 2) - StressTest1_layer:setAnchorPoint(cc.p(0, 0)) - local callFunc = cc.CallFunc:create(removeMe) - StressTest1_layer:runAction(cc.Sequence:create(cc.RotateBy:create(2, 360), callFunc)) + StressTest1_layer:setAnchorPoint(ax.p(0, 0)) + local callFunc = ax.CallFunc:create(removeMe) + StressTest1_layer:runAction(ax.Sequence:create(ax.RotateBy:create(2, 360), callFunc)) StressTest1_layer:addChild(explosion) end @@ -321,10 +321,10 @@ end local function StressTest1() StressTest1_layer = getBaseLayer() - sp1 = cc.Sprite:create(s_pPathSister1) + sp1 = ax.Sprite:create(s_pPathSister1) StressTest1_layer:addChild(sp1, 0, kTagSprite1) - sp1:setPosition(cc.p(s.width / 2, s.height / 2)) + sp1:setPosition(ax.p(s.width / 2, s.height / 2)) StressTest1_layer:registerScriptHandler(StressTest1_onEnterOrExit) @@ -356,25 +356,25 @@ end local function StressTest2() StressTest2_layer = getBaseLayer() - sublayer = cc.Layer:create() + sublayer = ax.Layer:create() - local sp1 = cc.Sprite:create(s_pPathSister1) - sp1:setPosition(cc.p(80, s.height / 2)) + local sp1 = ax.Sprite:create(s_pPathSister1) + sp1:setPosition(ax.p(80, s.height / 2)) - local move = cc.MoveBy:create(3, cc.p(350, 0)) - local move_ease_inout3 = cc.EaseInOut:create(cc.MoveBy:create(3, cc.p(350, 0)), 2.0) + local move = ax.MoveBy:create(3, ax.p(350, 0)) + local move_ease_inout3 = ax.EaseInOut:create(ax.MoveBy:create(3, ax.p(350, 0)), 2.0) local move_ease_inout_back3 = move_ease_inout3:reverse() - local seq3 = cc.Sequence:create(move_ease_inout3, move_ease_inout_back3) - sp1:runAction(cc.RepeatForever:create(seq3)) + local seq3 = ax.Sequence:create(move_ease_inout3, move_ease_inout_back3) + sp1:runAction(ax.RepeatForever:create(seq3)) sublayer:addChild(sp1, 1) - local fire = cc.ParticleFire:create() - local fireTexture = cc.Director:getInstance():getTextureCache():addImage("Images/fire.png") + local fire = ax.ParticleFire:create() + local fireTexture = ax.Director:getInstance():getTextureCache():addImage("Images/fire.png") fire:setTexture(fireTexture) fire:setPosition(80, s.height / 2 - 50) local copy_seq3 = seq3:clone() - fire:runAction(cc.RepeatForever:create(copy_seq3)) + fire:runAction(ax.RepeatForever:create(copy_seq3)) sublayer:addChild(fire, 2) StressTest2_layer:registerScriptHandler(StressTest2_onEnterOrExit) @@ -395,26 +395,26 @@ local function NodeToWorld() -- - It tests different anchor Points -- - It tests different children anchor points - local back = cc.Sprite:create(s_back3) + local back = ax.Sprite:create(s_back3) layer:addChild(back, -10) - back:setAnchorPoint(cc.p(0, 0)) + back:setAnchorPoint(ax.p(0, 0)) local backSize = back:getContentSize() - local item = cc.MenuItemImage:create(s_PlayNormal, s_PlaySelect) - local menu = cc.Menu:create() + local item = ax.MenuItemImage:create(s_PlayNormal, s_PlaySelect) + local menu = ax.Menu:create() menu:addChild(item) menu:alignItemsVertically() - menu:setPosition(cc.p(backSize.width / 2, backSize.height / 2)) + menu:setPosition(ax.p(backSize.width / 2, backSize.height / 2)) back:addChild(menu) - local rot = cc.RotateBy:create(5, 360) - local fe = cc.RepeatForever:create(rot) + local rot = ax.RotateBy:create(5, 360) + local fe = ax.RepeatForever:create(rot) item:runAction(fe) - local move = cc.MoveBy:create(3, cc.p(200, 0)) + local move = ax.MoveBy:create(3, ax.p(200, 0)) local move_back = move:reverse() - local seq = cc.Sequence:create(move, move_back) - local fe2 = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(move, move_back) + local fe2 = ax.RepeatForever:create(seq) back:runAction(fe2) Helper.titleLabel:setString("nodeToParent transform") @@ -426,53 +426,53 @@ end ----------------------------------- local function CameraOrbitTest_onEnterOrExit(tag) if tag == "enter" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION3_D) - cc.Director:getInstance():getRenderer():setDepthTest(true) - cc.Director:getInstance():getRenderer():setDepthWrite(true) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION3_D) + ax.Director:getInstance():getRenderer():setDepthTest(true) + ax.Director:getInstance():getRenderer():setDepthWrite(true) elseif tag == "exit" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT) - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():getRenderer():setDepthWrite(false) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthWrite(false) end end local function CameraOrbitTest() local layer = getBaseLayer() - local p = cc.Sprite:create(s_back3) + local p = ax.Sprite:create(s_back3) layer:addChild(p, 0) - p:setPosition(cc.p(s.width / 2, s.height / 2)) + p:setPosition(ax.p(s.width / 2, s.height / 2)) p:setOpacity(128) -- LEFT local s = p:getContentSize() - local sprite = cc.Sprite:create(s_pPathGrossini) + local sprite = ax.Sprite:create(s_pPathGrossini) sprite:setScale(0.5) p:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 4 * 1, s.height / 2)) - local orbit = cc.OrbitCamera:create(2, 1, 0, 0, 360, 0, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 4 * 1, s.height / 2)) + local orbit = ax.OrbitCamera:create(2, 1, 0, 0, 360, 0, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) -- CENTER - sprite = cc.Sprite:create(s_pPathGrossini) + sprite = ax.Sprite:create(s_pPathGrossini) sprite:setScale(1.0) p:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 4 * 2, s.height / 2)) - orbit = cc.OrbitCamera:create(2, 1, 0, 0, 360, 45, 0) - sprite:runAction(cc.RepeatForever:create(orbit)) + sprite:setPosition(ax.p(s.width / 4 * 2, s.height / 2)) + orbit = ax.OrbitCamera:create(2, 1, 0, 0, 360, 45, 0) + sprite:runAction(ax.RepeatForever:create(orbit)) -- RIGHT - sprite = cc.Sprite:create(s_pPathGrossini) + sprite = ax.Sprite:create(s_pPathGrossini) sprite:setScale(2.0) p:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 4 * 3, s.height / 2)) + sprite:setPosition(ax.p(s.width / 4 * 3, s.height / 2)) local ss = sprite:getContentSize() - orbit = cc.OrbitCamera:create(2, 1, 0, 0, 360, 90, -45) - sprite:runAction(cc.RepeatForever:create(orbit)) + orbit = ax.OrbitCamera:create(2, 1, 0, 0, 360, 90, -45) + sprite:runAction(ax.RepeatForever:create(orbit)) -- PARENT - orbit = cc.OrbitCamera:create(10, 1, 0, 0, 360, 0, 90) - p:runAction(cc.RepeatForever:create(orbit)) + orbit = ax.OrbitCamera:create(10, 1, 0, 0, 360, 0, 90) + p:runAction(ax.RepeatForever:create(orbit)) layer:setScale(1) layer:registerScriptHandler(CameraOrbitTest_onEnterOrExit) @@ -501,10 +501,10 @@ end local function CameraZoomTest_onEnterOrExit(tag) if tag == "enter" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION3_D) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION3_D) CameraZoomTest_entry = scheduler:scheduleScriptFunc(CameraZoomTest_update, 0.0, false) elseif tag == "exit" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT) scheduler:unscheduleScriptEntry(CameraZoomTest_entry) end end @@ -515,22 +515,22 @@ local function CameraZoomTest() z = 0 -- LEFT - local sprite = cc.Sprite:create(s_pPathGrossini) + local sprite = ax.Sprite:create(s_pPathGrossini) CameraZoomTest_layer:addChild(sprite, 0) - sprite:setPosition(cc.p(s.width / 4 * 1, s.height / 2)) + sprite:setPosition(ax.p(s.width / 4 * 1, s.height / 2)) -- local cam = sprite:getCamera() -- cam:setEye(0, 0, 415 / 2) -- cam:setCenter(0, 0, 0) -- CENTER - sprite = cc.Sprite:create(s_pPathGrossini) + sprite = ax.Sprite:create(s_pPathGrossini) CameraZoomTest_layer:addChild(sprite, 0, 40) - sprite:setPosition(cc.p(s.width / 4 * 2, s.height / 2)) + sprite:setPosition(ax.p(s.width / 4 * 2, s.height / 2)) -- RIGHT - sprite = cc.Sprite:create(s_pPathGrossini) + sprite = ax.Sprite:create(s_pPathGrossini) CameraZoomTest_layer:addChild(sprite, 0, 20) - sprite:setPosition(cc.p(s.width / 4 * 3, s.height / 2)) + sprite:setPosition(ax.p(s.width / 4 * 3, s.height / 2)) CameraZoomTest_layer:scheduleUpdateWithPriorityLua(CameraZoomTest_update, 0) CameraZoomTest_layer:registerScriptHandler(CameraZoomTest_onEnterOrExit) @@ -547,23 +547,23 @@ local ConvertToNode_layer = nil local function ConvertToNode() ConvertToNode_layer = getBaseLayer() - local rotate = cc.RotateBy:create(10, 360) - local action = cc.RepeatForever:create(rotate) + local rotate = ax.RotateBy:create(10, 360) + local action = ax.RepeatForever:create(rotate) for i = 0, 2 do - local sprite = cc.Sprite:create("Images/grossini.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:create("Images/grossini.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) ConvertToNode_layer:addChild(point, 10, 100 + i) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) elseif i == 2 then - sprite:setAnchorPoint(cc.p(1,1)) + sprite:setAnchorPoint(ax.p(1,1)) end point:setPosition(sprite:getPosition()) @@ -588,8 +588,8 @@ local function ConvertToNode() end end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesEnded,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesEnded,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = ConvertToNode_layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ConvertToNode_layer) @@ -605,9 +605,9 @@ local function NodeOpaqueTest() local layer = getBaseLayer() for i = 0, 49 do - local background = cc.Sprite:create("Images/background1.png") - background:setBlendFunc(cc.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) - background:setAnchorPoint(cc.p(0, 0)) + local background = ax.Sprite:create("Images/background1.png") + background:setBlendFunc(ax.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) + background:setAnchorPoint(ax.p(0, 0)) layer:addChild(background) end @@ -623,9 +623,9 @@ local function NodeNonOpaqueTest() local layer = getBaseLayer() for i = 0, 49 do - background = cc.Sprite:create("Images/background1.jpg") - background:setBlendFunc(cc.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ZERO)) - background:setAnchorPoint(cc.p(0, 0)) + background = ax.Sprite:create("Images/background1.jpg") + background:setBlendFunc(ax.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ZERO)) + background:setAnchorPoint(ax.p(0, 0)) layer:addChild(background) end Helper.titleLabel:setString("Node Non Opaque Test") @@ -642,17 +642,17 @@ local function NodeGlobalZValueTest() Helper.subtitleLabel:setString("Center Sprite should change go from foreground to background") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local zOrderSprite = nil for i = 1,9 do - local parent = cc.Node:create() + local parent = ax.Node:create() local sprite = nil if i == 5 then - sprite = cc.Sprite:create("Images/grossinis_sister2.png") + sprite = ax.Sprite:create("Images/grossinis_sister2.png") sprite:setGlobalZOrder(-1) zOrderSprite = sprite else - sprite = cc.Sprite:create("Images/grossinis_sister1.png") + sprite = ax.Sprite:create("Images/grossinis_sister1.png") end parent:addChild(sprite) layer:addChild(parent) @@ -686,7 +686,7 @@ end function CocosNodeTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { CameraCenterTest, diff --git a/tests/lua-tests/Content/src/OpenGLTest/OpenGLTest.lua b/tests/lua-tests/Content/src/OpenGLTest/OpenGLTest.lua index 2738f7bd0250..f29356028d62 100644 --- a/tests/lua-tests/Content/src/OpenGLTest/OpenGLTest.lua +++ b/tests/lua-tests/Content/src/OpenGLTest/OpenGLTest.lua @@ -16,7 +16,7 @@ local vertDefaultSource = "\n".."\n" .. " v_texCoord = a_texCoord;\n" .. "} \n" -local scaleFactor = cc.Director:getInstance():getContentScaleFactor() +local scaleFactor = ax.Director:getInstance():getContentScaleFactor() local function OpenGLTestMainLayer() local kItemTagBasic = 1000 @@ -25,7 +25,7 @@ local function OpenGLTestMainLayer() local curCase = 0 local accum = 0 local labelBMFont = nil - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() local curLayer = nil local schedulEntry = nil local function OrderCallbackMenu() @@ -47,23 +47,23 @@ local function OpenGLTestMainLayer() ShowCurrentTest() end - local ordercallbackmenu = cc.Menu:create() - local size = cc.Director:getInstance():getWinSize() - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) + local ordercallbackmenu = ax.Menu:create() + local size = ax.Director:getInstance():getWinSize() + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) item1:registerScriptTapHandler(backCallback) ordercallbackmenu:addChild(item1,kItemTagBasic) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) item2:registerScriptTapHandler(restartCallback) ordercallbackmenu:addChild(item2,kItemTagBasic) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) ordercallbackmenu:addChild(item3,kItemTagBasic) item3:registerScriptTapHandler(nextCallback) - item1:setPosition(cc.p(size.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(size.width / 2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(size.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item1:setPosition(ax.p(size.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(size.width / 2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(size.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - ordercallbackmenu:setPosition(cc.p(0, 0)) + ordercallbackmenu:setPosition(ax.p(0, 0)) return ordercallbackmenu end @@ -128,7 +128,7 @@ local function OpenGLTestMainLayer() elseif 10 == curCase then return "Tests ReadPixels. See console" elseif 11 == curCase then - return "Testing gl.clear() with cc.GLNode" + return "Testing gl.clear() with ax.GLNode" elseif 12 == curCase then return "blue background with a red triangle in the middle" elseif 13 == curCase then @@ -142,16 +142,16 @@ local function OpenGLTestMainLayer() local function InitTitle(layer) --Title - local lableTitle = cc.Label:createWithTTF(GetTitle(), s_arialPath, 40) + local lableTitle = ax.Label:createWithTTF(GetTitle(), s_arialPath, 40) layer:addChild(lableTitle, 15) - lableTitle:setAnchorPoint(cc.p(0.5, 0.5)) - lableTitle:setPosition(cc.p(size.width/2, size.height-32)) - lableTitle:setColor(cc.c3b(255,255,40)) + lableTitle:setAnchorPoint(ax.p(0.5, 0.5)) + lableTitle:setPosition(ax.p(size.width/2, size.height-32)) + lableTitle:setColor(ax.color32(255,255,40)) --SubTitle - local subLabelTitle = cc.Label:createWithTTF(GetSubTitle(), s_thonburiPath, 16) + local subLabelTitle = ax.Label:createWithTTF(GetSubTitle(), s_thonburiPath, 16) layer:addChild(subLabelTitle, 15) - subLabelTitle:setAnchorPoint(cc.p(0.5, 0.5)) - subLabelTitle:setPosition(cc.p(size.width/2, size.height-80)) + subLabelTitle:setAnchorPoint(ax.p(0.5, 0.5)) + subLabelTitle:setPosition(ax.p(size.width/2, size.height-80)) end local function updateRetroEffect(fTime) @@ -171,16 +171,16 @@ local function OpenGLTestMainLayer() end local function createShaderRetroEffect() - local RetroEffectlayer = cc.Layer:create() + local RetroEffectlayer = ax.Layer:create() InitTitle(RetroEffectlayer) - local program = cc.GLProgram:create("Shaders/example_ColorBars.vsh", "Shaders/example_ColorBars.fsh") - program:bindAttribLocation(cc.ATTRIBUTE_NAME_POSITION, cc.VERTEX_ATTRIB_POSITION) - program:bindAttribLocation(cc.ATTRIBUTE_NAME_TEX_COORD, cc.VERTEX_ATTRIB_TEX_COORD) + local program = ax.GLProgram:create("Shaders/example_ColorBars.vsh", "Shaders/example_ColorBars.fsh") + program:bindAttribLocation(ax.ATTRIBUTE_NAME_POSITION, ax.VERTEX_ATTRIB_POSITION) + program:bindAttribLocation(ax.ATTRIBUTE_NAME_TEX_COORD, ax.VERTEX_ATTRIB_TEX_COORD) program:link() program:updateUniforms() - label = cc.Label:createWithBMFont("fonts/west_england-64.fnt", "RETRO EFFECT") - label:setAnchorPoint(cc.p(0.5, 0.5)) + label = ax.Label:createWithBMFont("fonts/west_england-64.fnt", "RETRO EFFECT") + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setGLProgram( program ) label:setPosition(size.width/2, size.height/2) @@ -191,23 +191,23 @@ local function OpenGLTestMainLayer() end local function createShaderNodeLayer(vSource, fSource) - local shaderNodeLayer = cc.Layer:create() + local shaderNodeLayer = ax.Layer:create() InitTitle(shaderNodeLayer) local vertSource = vSource local fragSource = fSource - local glProgram = cc.GLProgram:createWithByteArrays(vertSource, fragSource) + local glProgram = ax.GLProgram:createWithByteArrays(vertSource, fragSource) glProgram:retain() local glNode = gl.glNodeCreate() - local resolution = cc.p(256, 256) - local director = cc.Director:getInstance() + local resolution = ax.p(256, 256) + local director = ax.Director:getInstance() local frameSize = director:getRenderView():getFrameSize() local visibleSize = director:getVisibleSize() local retinaFactor = director:getRenderView():getRetinaFactor() - local center = cc.p( size.width / 2 * frameSize.width / visibleSize.width * retinaFactor, size.height / 2 * frameSize.height / visibleSize.height * retinaFactor) + local center = ax.p( size.width / 2 * frameSize.width / visibleSize.width * retinaFactor, size.height / 2 * frameSize.height / visibleSize.height * retinaFactor) local function initBuffers() local w = 256 @@ -237,9 +237,9 @@ local function OpenGLTestMainLayer() local uniformResolution = gl.getUniformLocation(glProgram:getProgram(), "resolution") glProgram:setUniformLocationF32(uniformResolution, resolution.x, resolution.y) - gl.glEnableVertexAttribs(cc.VERTEX_ATTRIB_FLAG_POSITION) + gl.glEnableVertexAttribs(ax.VERTEX_ATTRIB_FLAG_POSITION) gl.bindBuffer(gl.ARRAY_BUFFER, vbo) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0); + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0); gl.drawArrays(gl.TRIANGLES, 0, 6) gl.bindBuffer(gl.ARRAY_BUFFER, 0) end @@ -263,49 +263,49 @@ local function OpenGLTestMainLayer() local function createShaderMajoriTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Monjori.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Monjori.fsh") return createShaderNodeLayer(vSource, fSource) end local function createShaderMandelbrotTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Mandelbrot.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Mandelbrot.fsh") return createShaderNodeLayer(vSource, fSource) end local function createShaderHeartTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Heart.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Heart.fsh") return createShaderNodeLayer(vSource, fSource) end local function createShaderPlasmaTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Plasma.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Plasma.fsh") return createShaderNodeLayer(vSource, fSource) end local function createShaderFlowerTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Flower.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Flower.fsh") return createShaderNodeLayer(vSource, fSource) end local function createShaderJuliaTest() local vSource = vertDefaultSource - local fSource = cc.FileUtils:getInstance():getStringFromFile("Shaders/example_Julia.fsh") + local fSource = ax.FileUtils:getInstance():getStringFromFile("Shaders/example_Julia.fsh") return createShaderNodeLayer(vSource, fSource) end local function createGLGetActiveTest() - local glGetActiveLayer = cc.Layer:create() + local glGetActiveLayer = ax.Layer:create() InitTitle(glGetActiveLayer) - local sprite = cc.Sprite:create("Images/grossini.png") + local sprite = ax.Sprite:create("Images/grossini.png") sprite:setPosition( size.width/2, size.height/2) glGetActiveLayer:addChild(sprite) local glNode = gl.glNodeCreate() glGetActiveLayer:addChild(glNode,-10) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() local function getCurrentResult() local var = {} @@ -348,14 +348,14 @@ local function OpenGLTestMainLayer() local texture = {} local squareVertexPositionBuffer = {} local squareVertexTextureBuffer = {} - local texImage2dLayer = cc.Layer:create() + local texImage2dLayer = ax.Layer:create() InitTitle(texImage2dLayer) local glNode = gl.glNodeCreate() texImage2dLayer:addChild(glNode, 10) glNode:setPosition(size.width/2, size.height/2) - glNode:setContentSize(cc.size(128,128)) - glNode:setAnchorPoint(cc.p(0.5,0.5)) - local shaderCache = cc.ShaderCache:getInstance() + glNode:setContentSize(ax.size(128,128)) + glNode:setAnchorPoint(ax.p(0.5,0.5)) + local shaderCache = ax.ShaderCache:getInstance() local shader = shaderCache:getProgram("ShaderPositionTexture") local function initGL() @@ -398,14 +398,14 @@ local function OpenGLTestMainLayer() shader:setUniformsForBuiltins(transform) gl.bindTexture(gl.TEXTURE_2D, texture.texture_id) - gl.glEnableVertexAttribs(bit._or(cc.VERTEX_ATTRIB_FLAG_TEX_COORDS, cc.VERTEX_ATTRIB_FLAG_POSITION)) + gl.glEnableVertexAttribs(bit._or(ax.VERTEX_ATTRIB_FLAG_TEX_COORDS, ax.VERTEX_ATTRIB_FLAG_POSITION)) gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION,2,gl.FLOAT,false,0,0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_POSITION,2,gl.FLOAT,false,0,0) gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexTextureBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_TEX_COORD,2,gl.FLOAT,false,0,0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_TEX_COORD,2,gl.FLOAT,false,0,0) gl.drawArrays(gl.TRIANGLE_STRIP,0,4) @@ -420,7 +420,7 @@ local function OpenGLTestMainLayer() end local function CreateSupportedExtensionsLayer() - local extensionsLayer = cc.Layer:create() + local extensionsLayer = ax.Layer:create() InitTitle(extensionsLayer) local glNode = gl.glNodeCreate() extensionsLayer:addChild(glNode,-10) @@ -439,7 +439,7 @@ local function OpenGLTestMainLayer() end local function CreateReadPixelsTest() - local readPixelsLayer = cc.Layer:create() + local readPixelsLayer = ax.Layer:create() InitTitle(readPixelsLayer) local glNode = gl.glNodeCreate() readPixelsLayer:addChild(glNode,-10) @@ -447,10 +447,10 @@ local function OpenGLTestMainLayer() local x = size.width local y = size.height - local blue = cc.LayerColor:create(cc.c4b(0, 0, 255, 255)) - local red = cc.LayerColor:create(cc.c4b(255, 0, 0, 255)) - local green = cc.LayerColor:create(cc.c4b(0, 255, 0, 255)) - local white = cc.LayerColor:create(cc.c4b(255, 255, 255, 255)) + local blue = ax.LayerColor:create(ax.color32(0, 0, 255, 255)) + local red = ax.LayerColor:create(ax.color32(255, 0, 0, 255)) + local green = ax.LayerColor:create(ax.color32(0, 255, 0, 255)) + local white = ax.LayerColor:create(ax.color32(255, 255, 255, 255)) blue:setScale(0.5) blue:setPosition(-x / 4, -y / 4) @@ -469,7 +469,7 @@ local function OpenGLTestMainLayer() readPixelsLayer:addChild(green,12) readPixelsLayer:addChild(red,13) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() local function getCurrentResult() local x = size.width @@ -525,16 +525,16 @@ local function OpenGLTestMainLayer() end local function createClearTest() - local clearLayer = cc.Layer:create() + local clearLayer = ax.Layer:create() InitTitle(clearLayer) - local blue = cc.LayerColor:create(cc.c4b(0, 0, 255, 255)) + local blue = ax.LayerColor:create(ax.color32(0, 0, 255, 255)) clearLayer:addChild( blue, 1 ) local glNode = gl.glNodeCreate() clearLayer:addChild(glNode,10) --gl.init() - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() local function clearDraw() gl.clear(gl.COLOR_BUFFER_BIT) @@ -565,7 +565,7 @@ local function OpenGLTestMainLayer() end local function createNodeWebGLAPITest() - local nodeWebGLAPILayer = cc.Layer:create() + local nodeWebGLAPILayer = ax.Layer:create() InitTitle(nodeWebGLAPILayer) local glNode = gl.glNodeCreate() nodeWebGLAPILayer:addChild(glNode,10) @@ -723,11 +723,11 @@ local function OpenGLTestMainLayer() end local function createGLNodeCCAPITest() - local nodeCCAPILayer = cc.Layer:create() + local nodeCCAPILayer = ax.Layer:create() InitTitle(nodeCCAPILayer) local glNode = gl.glNodeCreate() nodeCCAPILayer:addChild(glNode,10) - local shader = cc.GLProgramCache:getInstance():getGLProgram("ShaderPositionColor") + local shader = ax.GLProgramCache:getInstance():getGLProgram("ShaderPositionColor") local triangleVertexPositionBuffer = {} local triangleVertexColorBuffer = {} local squareVertexPositionBuffer = {} @@ -789,22 +789,22 @@ local function OpenGLTestMainLayer() local function GLNodeCCAPIDraw(transform, transformUpdated) shader:use() shader:setUniformsForBuiltins(transform) - gl.glEnableVertexAttribs(BitOR(cc.VERTEX_ATTRIB_FLAG_COLOR , cc.VERTEX_ATTRIB_FLAG_POSITION)) + gl.glEnableVertexAttribs(BitOR(ax.VERTEX_ATTRIB_FLAG_COLOR , ax.VERTEX_ATTRIB_FLAG_POSITION)) -- gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexPositionBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0) gl.bindBuffer(gl.ARRAY_BUFFER, squareVertexColorBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.FLOAT, false, 0, 0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_COLOR, 4, gl.FLOAT, false, 0, 0) gl.drawArrays(gl.TRIANGLE_STRIP, 0, 4) gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexPositionBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_POSITION, 2, gl.FLOAT, false, 0, 0) gl.bindBuffer(gl.ARRAY_BUFFER, triangleVertexColorBuffer.buffer_id) - gl.vertexAttribPointer(cc.VERTEX_ATTRIB_COLOR, 4, gl.FLOAT, false, 0, 0) + gl.vertexAttribPointer(ax.VERTEX_ATTRIB_COLOR, 4, gl.FLOAT, false, 0, 0) gl.drawArrays(gl.TRIANGLE_STRIP, 0, 3) @@ -819,7 +819,7 @@ local function OpenGLTestMainLayer() end local function createGLTexParamterTest() - local glTexParamLayer = cc.Layer:create() + local glTexParamLayer = ax.Layer:create() InitTitle(glTexParamLayer) local glNode = gl.glNodeCreate() glTexParamLayer:addChild(glNode,10) @@ -842,14 +842,14 @@ local function OpenGLTestMainLayer() end local function createGetUniformTest() - local getUniformLayer = cc.Layer:create() + local getUniformLayer = ax.Layer:create() InitTitle(getUniformLayer) local glNode = gl.glNodeCreate() getUniformLayer:addChild(glNode,10) local pMatrix = {1,2,3,4, 4,3,2,1, 1,2,4,8, 1.1,1.2,1.3,1.4} local function runTest() - local shader = cc.ShaderCache:getInstance():getProgram("ShaderPositionTextureColor") + local shader = ax.ShaderCache:getInstance():getProgram("ShaderPositionTextureColor") local program = shader:getProgram() shader:use() @@ -917,10 +917,10 @@ local function OpenGLTestMainLayer() end function ShowCurrentTest() - local curScene = cc.Scene:create() + local curScene = ax.Scene:create() if nil ~= curScene then if nil ~= curLayer then - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if nil ~= schedulEntry then scheduler:unscheduleScriptEntry(schedulEntry) end @@ -930,7 +930,7 @@ local function OpenGLTestMainLayer() curScene:addChild(curLayer) curLayer:addChild(OrderCallbackMenu(),15) curScene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(curScene) + ax.Director:getInstance():replaceScene(curScene) end end end @@ -940,7 +940,7 @@ local function OpenGLTestMainLayer() end function OpenGLTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(OpenGLTestMainLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ParallaxTest/ParallaxTest.lua b/tests/lua-tests/Content/src/ParallaxTest/ParallaxTest.lua index 1e054cb70404..78513a68b33f 100644 --- a/tests/lua-tests/Content/src/ParallaxTest/ParallaxTest.lua +++ b/tests/lua-tests/Content/src/ParallaxTest/ParallaxTest.lua @@ -2,7 +2,7 @@ local kTagNode = 0 local kTagGrossini = 1 local function createParallaxLayer(title, subtitle) - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local titleStr = title == nil and "No title" or title local subTitleStr = subtitle == nil and "" or subtitle @@ -20,56 +20,56 @@ end local function Parallax1() local ret = createParallaxLayer("Parallax: parent and 3 children") -- Top Layer, a simple image - local cocosImage = cc.Sprite:create(s_Power) + local cocosImage = ax.Sprite:create(s_Power) -- scale the image (optional) cocosImage:setScale( 2.5 ) -- change the transform anchor point to 0,0 (optional) - cocosImage:setAnchorPoint( cc.p(0,0) ) + cocosImage:setAnchorPoint( ax.p(0,0) ) -- Middle layer: a Tile map atlas - local tilemap = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local tilemap = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) tilemap:releaseMap() -- change the transform anchor to 0,0 (optional) - tilemap:setAnchorPoint( cc.p(0, 0) ) + tilemap:setAnchorPoint( ax.p(0, 0) ) -- Anti Aliased images tilemap:getTexture():setAntiAliasTexParameters() -- background layer: another image - local background = cc.Sprite:create(s_back) + local background = ax.Sprite:create(s_back) -- scale the image (optional) background:setScale( 1.5 ) -- change the transform anchor point (optional) - background:setAnchorPoint( cc.p(0,0) ) + background:setAnchorPoint( ax.p(0,0) ) -- create a void node, a parent node - local voidNode = cc.ParallaxNode:create() + local voidNode = ax.ParallaxNode:create() -- NOW add the 3 layers to the 'void' node -- background image is moved at a ratio of 0.4x, 0.5y - voidNode:addChild(background, -1, cc.p(0.4,0.5), cc.p(0,0)) + voidNode:addChild(background, -1, ax.p(0.4,0.5), ax.p(0,0)) -- tiles are moved at a ratio of 2.2x, 1.0y - voidNode:addChild(tilemap, 1, cc.p(2.2,1.0), cc.p(0,-200) ) + voidNode:addChild(tilemap, 1, ax.p(2.2,1.0), ax.p(0,-200) ) -- top image is moved at a ratio of 3.0x, 2.5y - voidNode:addChild(cocosImage, 2, cc.p(3.0,2.5), cc.p(200,800) ) + voidNode:addChild(cocosImage, 2, ax.p(3.0,2.5), ax.p(200,800) ) -- now create some actions that will move the 'void' node -- and the children of the 'void' node will move at different -- speed, thus, simulation the 3D environment - local goUp = cc.MoveBy:create(4, cc.p(0,-500) ) + local goUp = ax.MoveBy:create(4, ax.p(0,-500) ) local goDown = goUp:reverse() - local go = cc.MoveBy:create(8, cc.p(-1000,0) ) + local go = ax.MoveBy:create(8, ax.p(-1000,0) ) local goBack = go:reverse() - local seq = cc.Sequence:create(goUp, go, goDown, goBack) - voidNode:runAction( (cc.RepeatForever:create(seq) )) + local seq = ax.Sequence:create(goUp, go, goDown, goBack) + voidNode:runAction( (ax.RepeatForever:create(seq) )) ret:addChild( voidNode ) return ret @@ -85,57 +85,57 @@ local function Parallax2() local ret = createParallaxLayer("Parallax: drag screen") -- Top Layer, a simple image - local cocosImage = cc.Sprite:create(s_Power) + local cocosImage = ax.Sprite:create(s_Power) -- scale the image (optional) cocosImage:setScale( 2.5 ) -- change the transform anchor point to 0,0 (optional) - cocosImage:setAnchorPoint( cc.p(0,0) ) + cocosImage:setAnchorPoint( ax.p(0,0) ) -- Middle layer: a Tile map atlas - local tilemap = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local tilemap = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) tilemap:releaseMap() -- change the transform anchor to 0,0 (optional) - tilemap:setAnchorPoint( cc.p(0, 0) ) + tilemap:setAnchorPoint( ax.p(0, 0) ) -- Anti Aliased images tilemap:getTexture():setAntiAliasTexParameters() -- background layer: another image - local background = cc.Sprite:create(s_back) + local background = ax.Sprite:create(s_back) -- scale the image (optional) background:setScale( 1.5 ) -- change the transform anchor point (optional) - background:setAnchorPoint( cc.p(0,0) ) + background:setAnchorPoint( ax.p(0,0) ) -- create a void node, a parent node - local voidNode = cc.ParallaxNode:create() + local voidNode = ax.ParallaxNode:create() -- NOW add the 3 layers to the 'void' node -- background image is moved at a ratio of 0.4x, 0.5y - voidNode:addChild(background, -1, cc.p(0.4,0.5), cc.p(0, 0)) + voidNode:addChild(background, -1, ax.p(0.4,0.5), ax.p(0, 0)) -- tiles are moved at a ratio of 1.0, 1.0y - voidNode:addChild(tilemap, 1, cc.p(1.0,1.0), cc.p(0,-200) ) + voidNode:addChild(tilemap, 1, ax.p(1.0,1.0), ax.p(0,-200) ) -- top image is moved at a ratio of 3.0x, 2.5y - voidNode:addChild( cocosImage, 2, cc.p(3.0,2.5), cc.p(200,1000) ) + voidNode:addChild( cocosImage, 2, ax.p(3.0,2.5), ax.p(200,1000) ) ret:addChild(voidNode, 0, kTagNode) local function onTouchesMoved(touches, event) local diff = touches[1]:getDelta() - + local node = ret:getChildByTag(kTagNode) local currentPosX, currentPosY = node:getPosition() - node:setPosition(cc.p(currentPosX + diff.x, currentPosY + diff.y)) + node:setPosition(ax.p(currentPosX + diff.x, currentPosY + diff.y)) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = ret:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) @@ -145,14 +145,14 @@ end function ParallaxTestMain() cclog("ParallaxMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { Parallax1, Parallax2 } Helper.index = 1 - + scene:addChild(Parallax1()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/Particle3DTest/Particle3DTest.lua b/tests/lua-tests/Content/src/Particle3DTest/Particle3DTest.lua index 058948056213..e795992b9864 100644 --- a/tests/lua-tests/Content/src/Particle3DTest/Particle3DTest.lua +++ b/tests/lua-tests/Content/src/Particle3DTest/Particle3DTest.lua @@ -7,37 +7,37 @@ local function baseInit(self) self._angle = 0 - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - - cc.FileUtils:getInstance():addSearchPath("res/Particle3D/materials") - cc.FileUtils:getInstance():addSearchPath("res/Particle3D/scripts") - - local size = cc.Director:getInstance():getWinSize() - self._camera = cc.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) - self._camera:setPosition3D(cc.vec3(0.0, 0.0, 100.0)) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + + ax.FileUtils:getInstance():addSearchPath("res/Particle3D/materials") + ax.FileUtils:getInstance():addSearchPath("res/Particle3D/scripts") + + local size = ax.Director:getInstance():getWinSize() + self._camera = ax.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) + self._camera:setPosition3D(ax.vec3(0.0, 0.0, 100.0)) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(self._camera) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function (touches, event) if #touches ~= 0 then local touch = touches[1] local delta = touch:getDelta() - + self._angle = self._angle - delta.x * math.pi / 180 - self._camera:setPosition3D(cc.vec3(100.0 * math.sin(math.deg(self._angle)), 0.0, 100.0 * math.cos(math.deg(self._angle)))) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) + self._camera:setPosition3D(ax.vec3(100.0 * math.sin(math.deg(self._angle)), 0.0, 100.0 * math.cos(math.deg(self._angle)))) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) end - end,cc.Handler.EVENT_TOUCHES_MOVED) + end,ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function (touches, event) - - end,cc.Handler.EVENT_TOUCHES_ENDED) + + end,ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -45,9 +45,9 @@ local function baseInit(self) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/tahoma.ttf" ttfConfig.fontSize = 10 - self._particleLab = cc.Label:createWithTTF(ttfConfig,"Particle Count: 0",cc.TEXT_ALIGNMENT_LEFT) - self._particleLab:setPosition(cc.p(0.0, size.height / 6.0)) - self._particleLab:setAnchorPoint(cc.p(0.0, 0.0)) + self._particleLab = ax.Label:createWithTTF(ttfConfig,"Particle Count: 0",ax.TEXT_ALIGNMENT_LEFT) + self._particleLab:setPosition(ax.p(0.0, size.height / 6.0)) + self._particleLab:setAnchorPoint(ax.p(0.0, 0.0)) self:addChild(self._particleLab) self:scheduleUpdateWithPriorityLua(function(dt) @@ -78,7 +78,7 @@ end -- Particle3DLineStreakDemo local Particle3DLineStreakDemo = class("Particle3DLineStreakDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -101,8 +101,8 @@ function Particle3DLineStreakDemo:subtitle() end function Particle3DLineStreakDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("lineStreak.pu", "pu_example.material") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("lineStreak.pu", "pu_example.material") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:setScale(5.0) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) @@ -115,7 +115,7 @@ end -- Particle3DBlackHoleDemo local Particle3DBlackHoleDemo = class("Particle3DBlackHoleDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -138,12 +138,12 @@ function Particle3DBlackHoleDemo:subtitle() end function Particle3DBlackHoleDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("blackHole.pu", "pu_example.material") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("blackHole.pu", "pu_example.material") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:setPosition(-25.0, 0.0) - local moveby = cc.MoveBy:create(2.0, cc.p(50.0, 0.0)) - local moveby1 = cc.MoveBy:create(2.0, cc.p(-50.0, 0.0)) - rootps:runAction(cc.RepeatForever:create(cc.Sequence:create(moveby, moveby1))) + local moveby = ax.MoveBy:create(2.0, ax.p(50.0, 0.0)) + local moveby1 = ax.MoveBy:create(2.0, ax.p(-50.0, 0.0)) + rootps:runAction(ax.RepeatForever:create(ax.Sequence:create(moveby, moveby1))) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -154,7 +154,7 @@ end -- Particle3DHypnoDemo local Particle3DHypnoDemo = class("Particle3DHypnoDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -177,8 +177,8 @@ function Particle3DHypnoDemo:subtitle() end function Particle3DHypnoDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("hypno.pu", "pu_example.material") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("hypno.pu", "pu_example.material") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -190,7 +190,7 @@ end -- Particle3DAdvancedLodSystemDemo local Particle3DAdvancedLodSystemDemo = class("Particle3DAdvancedLodSystemDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -213,12 +213,12 @@ function Particle3DAdvancedLodSystemDemo:subtitle() end function Particle3DAdvancedLodSystemDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("advancedLodSystem.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) - local scale = cc.ScaleBy:create(1.0, 2.0, 2.0, 2.0) - local rotate = cc.RotateBy:create(1.0, cc.vec3(0.0, 0.0, 100.0)) - rootps:runAction(cc.RepeatForever:create(cc.Sequence:create(rotate))) - rootps:runAction(cc.RepeatForever:create(cc.Sequence:create(scale, scale:reverse()))) + local rootps = ax.PUParticleSystem3D:create("advancedLodSystem.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) + local scale = ax.ScaleBy:create(1.0, 2.0, 2.0, 2.0) + local rotate = ax.RotateBy:create(1.0, ax.vec3(0.0, 0.0, 100.0)) + rootps:runAction(ax.RepeatForever:create(ax.Sequence:create(rotate))) + rootps:runAction(ax.RepeatForever:create(ax.Sequence:create(scale, scale:reverse()))) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -230,7 +230,7 @@ end -- Particle3DTimeShiftDemo local Particle3DTimeShiftDemo = class("Particle3DTimeShiftDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -253,9 +253,9 @@ function Particle3DTimeShiftDemo:subtitle() end function Particle3DTimeShiftDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("timeShift.pu", "pu_example.material") + local rootps = ax.PUParticleSystem3D:create("timeShift.pu", "pu_example.material") rootps:setScale(2.0) - rootps:setCameraMask(cc.CameraFlag.USER1) + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -267,7 +267,7 @@ end -- Particle3DUVAnimDemo local Particle3DUVAnimDemo = class("Particle3DUVAnimDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -290,8 +290,8 @@ function Particle3DUVAnimDemo:subtitle() end function Particle3DUVAnimDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("UVAnimation.pu", "pu_example.material") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("UVAnimation.pu", "pu_example.material") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -302,7 +302,7 @@ end -- Particle3DFirePlaceDemo local Particle3DFirePlaceDemo = class("Particle3DFirePlaceDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -325,8 +325,8 @@ function Particle3DFirePlaceDemo:subtitle() end function Particle3DFirePlaceDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("mp_torch.pu", "pu_example.material") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("mp_torch.pu", "pu_example.material") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:setScale(5.0) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) @@ -338,7 +338,7 @@ end -- Particle3DElectricBeamSystemDemo local Particle3DElectricBeamSystemDemo = class("Particle3DElectricBeamSystemDemo", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -361,8 +361,8 @@ function Particle3DElectricBeamSystemDemo:subtitle() end function Particle3DElectricBeamSystemDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("electricBeamSystem.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("electricBeamSystem.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -373,7 +373,7 @@ end -- Particle3DFlareShield local Particle3DFlareShieldDemo = class("Particle3DFlareShield", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -396,8 +396,8 @@ function Particle3DFlareShieldDemo:subtitle() end function Particle3DFlareShieldDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("flareShield.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("flareShield.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -408,7 +408,7 @@ end -- Particle3DLightningBoltDemo local Particle3DLightningBoltDemo = class("Particle3DLightningBolt", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -431,8 +431,8 @@ function Particle3DLightningBoltDemo:subtitle() end function Particle3DLightningBoltDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("lightningBolt.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("lightningBolt.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -443,7 +443,7 @@ end -- Particle3DCanOfWormsDemo local Particle3DCanOfWormsDemo = class("Particle3DCanOfWorms", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -466,8 +466,8 @@ function Particle3DCanOfWormsDemo:subtitle() end function Particle3DCanOfWormsDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("canOfWorms.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("canOfWorms.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -478,7 +478,7 @@ end -- Particle3DRibbonTrailDemo local Particle3DRibbonTrailDemo = class("Particle3DRibbonTrail", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -501,8 +501,8 @@ function Particle3DRibbonTrailDemo:subtitle() end function Particle3DRibbonTrailDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("ribbonTrailTest.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("ribbonTrailTest.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -513,7 +513,7 @@ end -- Particle3DWeaponTrailDemo local Particle3DWeaponTrailDemo = class("Particle3DWeaponTrail", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -536,8 +536,8 @@ function Particle3DWeaponTrailDemo:subtitle() end function Particle3DWeaponTrailDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("weaponTrail.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("weaponTrail.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -548,7 +548,7 @@ end -- Particle3DExplosionSystemDemo local Particle3DExplosionSystemDemo = class("Particle3DExplosionSystem", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -571,8 +571,8 @@ function Particle3DExplosionSystemDemo:subtitle() end function Particle3DExplosionSystemDemo:onEnter() - local rootps = cc.PUParticleSystem3D:create("explosionSystem.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("explosionSystem.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -583,7 +583,7 @@ end -- Particle3DWithSprite3DDemo local Particle3DWithSprite3DDemo = class("Particle3DWithSprite3D", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -607,23 +607,23 @@ end function Particle3DWithSprite3DDemo:onEnter() - local sprite = cc.Sprite3D:create("MeshRendererTest/orc.c3b") - sprite:setPosition3D(cc.vec3(-20, 0, 0)) - sprite:setRotation3D(cc.vec3(0, 180, 0)) - sprite:setCameraMask(cc.CameraFlag.USER1) + local sprite = ax.Sprite3D:create("MeshRendererTest/orc.c3b") + sprite:setPosition3D(ax.vec3(-20, 0, 0)) + sprite:setRotation3D(ax.vec3(0, 180, 0)) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) - local animation = cc.Animation3D:create("MeshRendererTest/orc.c3b") - local animate = cc.Animate3D:create(animation) - sprite:runAction(cc.RepeatForever:create(animate)) - - local billboard = cc.BillBoard:create("Images/Icon.png") - billboard:setPosition3D(cc.vec3(20, 0, 0)) + local animation = ax.Animation3D:create("MeshRendererTest/orc.c3b") + local animate = ax.Animate3D:create(animation) + sprite:runAction(ax.RepeatForever:create(animate)) + + local billboard = ax.BillBoard:create("Images/Icon.png") + billboard:setPosition3D(ax.vec3(20, 0, 0)) billboard:setScale(0.2) - billboard:setCameraMask(cc.CameraFlag.USER1) + billboard:setCameraMask(ax.CameraFlag.USER1) self:addChild(billboard) - local rootps = cc.PUParticleSystem3D:create("lineStreak.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("lineStreak.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, PARTICLE_SYSTEM_TAG) end @@ -633,9 +633,9 @@ function Particle3DWithSprite3DDemo:onExit() end function Particle3DTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { Particle3DExplosionSystemDemo.create, Particle3DLineStreakDemo.create, diff --git a/tests/lua-tests/Content/src/ParticleTest/ParticleTest.lua b/tests/lua-tests/Content/src/ParticleTest/ParticleTest.lua index aac68b12eda0..bedb7fd48367 100644 --- a/tests/lua-tests/Content/src/ParticleTest/ParticleTest.lua +++ b/tests/lua-tests/Content/src/ParticleTest/ParticleTest.lua @@ -10,7 +10,7 @@ local titleLabel = nil local subtitleLabel = nil local baseLayer_entry = nil -local s = cc.Director:getInstance():getWinSize() +local s = ax.Director:getInstance():getWinSize() local onEnterCallback = nil @@ -35,40 +35,40 @@ local function nextAction() end local function backCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(backAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function restartCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(restartAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function nextCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(nextAction()) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function toggleCallback(sender) if emitter ~= nil then - if emitter:getPositionType() == cc.POSITION_TYPE_GROUPED then - emitter:setPositionType(cc.POSITION_TYPE_FREE) - elseif emitter:getPositionType() == cc.POSITION_TYPE_FREE then - emitter:setPositionType(cc.POSITION_TYPE_RELATIVE) - elseif emitter:getPositionType() == cc.POSITION_TYPE_RELATIVE then - emitter:setPositionType(cc.POSITION_TYPE_GROUPED) + if emitter:getPositionType() == ax.POSITION_TYPE_GROUPED then + emitter:setPositionType(ax.POSITION_TYPE_FREE) + elseif emitter:getPositionType() == ax.POSITION_TYPE_FREE then + emitter:setPositionType(ax.POSITION_TYPE_RELATIVE) + elseif emitter:getPositionType() == ax.POSITION_TYPE_RELATIVE then + emitter:setPositionType(ax.POSITION_TYPE_GROUPED) end end end @@ -88,7 +88,7 @@ local function update(dt) end local function baseLayer_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enter" then baseLayer_entry = scheduler:scheduleScriptFunc(update, 0, false) if onEnterCallback ~= nil then @@ -104,70 +104,70 @@ local function baseLayer_onEnterOrExit(tag) end local function getBaseLayer() - local layer = cc.LayerColor:create(cc.c4b(127,127,127,255)) + local layer = ax.LayerColor:create(ax.color32(127,127,127,255)) emitter = nil - titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) + titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) layer:addChild(titleLabel, 100, 1000) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(s.width / 2, s.height - 50) - subtitleLabel = cc.Label:createWithTTF("", s_arialPath, 16) + subtitleLabel = ax.Label:createWithTTF("", s_arialPath, 16) layer:addChild(subtitleLabel, 100) - subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) subtitleLabel:setPosition(s.width / 2, s.height - 80) - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) - local item4 = cc.MenuItemToggle:create(cc.MenuItemFont:create("Free Movement")) - item4:addSubItem(cc.MenuItemFont:create("Relative Movement")) - item4:addSubItem(cc.MenuItemFont:create("Grouped Movement")) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item4 = ax.MenuItemToggle:create(ax.MenuItemFont:create("Free Movement")) + item4:addSubItem(ax.MenuItemFont:create("Relative Movement")) + item4:addSubItem(ax.MenuItemFont:create("Grouped Movement")) item1:registerScriptTapHandler(backCallback) item2:registerScriptTapHandler(restartCallback) item3:registerScriptTapHandler(nextCallback) item4:registerScriptTapHandler(toggleCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) menu:addChild(item4) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(s.width/2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(s.width/2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(s.width/2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item4:setPosition(cc.p(0, 100)) - item4:setAnchorPoint(cc.p(0, 0)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(s.width/2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(s.width/2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(s.width/2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item4:setPosition(ax.p(0, 100)) + item4:setAnchorPoint(ax.p(0, 0)) layer:addChild(menu, 100) - labelAtlas = cc.LabelAtlas:_create("0000", "fps_images.png", 12, 32, string.byte('.')) + labelAtlas = ax.LabelAtlas:_create("0000", "fps_images.png", 12, 32, string.byte('.')) layer:addChild(labelAtlas, 100) - labelAtlas:setPosition(cc.p(s.width - 66, 50)) + labelAtlas:setPosition(ax.p(s.width - 66, 50)) -- moving background - background = cc.Sprite:create(s_back3) + background = ax.Sprite:create(s_back3) layer:addChild(background, 5) - background:setPosition(cc.p(s.width / 2, s.height - 180)) + background:setPosition(ax.p(s.width / 2, s.height - 180)) - local move = cc.MoveBy:create(4, cc.p(300, 0)) + local move = ax.MoveBy:create(4, ax.p(300, 0)) local move_back = move:reverse() - local seq = cc.Sequence:create(move, move_back) - background:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, move_back) + background:runAction(ax.RepeatForever:create(seq)) local function onTouchesEnded(touches, event) local location = touches[1]:getLocation() - local pos = cc.p(0, 0) + local pos = ax.p(0, 0) if background ~= nil then - pos = background:convertToWorldSpace(cc.p(0, 0)) + pos = background:convertToWorldSpace(ax.p(0, 0)) end if emitter ~= nil then - local newPos = cc.pSub(location, pos) + local newPos = ax.pSub(location, pos) emitter:setPosition(newPos.x, newPos.y) end end @@ -180,10 +180,10 @@ local function getBaseLayer() onTouchesEnded(touches, event); end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesBegan,cc.Handler.EVENT_TOUCHES_BEGAN ) - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) - listener:registerScriptHandler(onTouchesEnded,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesBegan,ax.Handler.EVENT_TOUCHES_BEGAN ) + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) + listener:registerScriptHandler(onTouchesEnded,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -229,7 +229,7 @@ local function reorderParticles(dt) end local function ParticleReorder_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enterTransitionFinish" then ParticleReorder_entry = scheduler:scheduleScriptFunc(reorderParticles, 1.0, false) elseif tag == "exit" then @@ -244,13 +244,13 @@ local function ParticleReorder() onEnterCallback = function () ParticleReorder_Order = 0 - ParticleReorder_layer:setColor(cc.c3b(0, 0, 0)) + ParticleReorder_layer:setColor(ax.color32(0, 0, 0)) ParticleReorder_layer:removeChild(background, true) background = nil - local ignore = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") - local parent1 = cc.Node:create() - local parent2 = cc.ParticleBatchNode:createWithTexture(ignore:getTexture()) + local ignore = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") + local parent1 = ax.Node:create() + local parent2 = ax.ParticleBatchNode:createWithTexture(ignore:getTexture()) ignore:unscheduleUpdate() for i = 0, 1 do @@ -261,14 +261,14 @@ local function ParticleReorder() parent = parent2 end - local emitter1 = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") - emitter1:setStartColor(cc.c4f(1,0,0,1)) + local emitter1 = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") + emitter1:setStartColor(ax.color(1,0,0,1)) emitter1:setBlendAdditive(false) - local emitter2 = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") - emitter2:setStartColor(cc.c4f(0,1,0,1)) + local emitter2 = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") + emitter2:setStartColor(ax.color(0,1,0,1)) emitter2:setBlendAdditive(false) - local emitter3 = cc.ParticleSystemQuad:create("Particles/SmallSun.plist") - emitter3:setStartColor(cc.c4f(0,0,1,1)) + local emitter3 = ax.ParticleSystemQuad:create("Particles/SmallSun.plist") + emitter3:setStartColor(ax.color(0,0,1,1)) emitter3:setBlendAdditive(false) local neg = nil @@ -278,9 +278,9 @@ local function ParticleReorder() neg = -1 end - emitter1:setPosition(cc.p( s.width / 2 - 30, s.height / 2 + 60 * neg)) - emitter2:setPosition(cc.p( s.width / 2, s.height / 2 + 60 * neg)) - emitter3:setPosition(cc.p( s.width / 2 + 30, s.height / 2 + 60 * neg)) + emitter1:setPosition(ax.p( s.width / 2 - 30, s.height / 2 + 60 * neg)) + emitter2:setPosition(ax.p( s.width / 2, s.height / 2 + 60 * neg)) + emitter3:setPosition(ax.p( s.width / 2 + 30, s.height / 2 + 60 * neg)) parent:addChild(emitter1, 0, 1) parent:addChild(emitter2, 0, 2) @@ -326,7 +326,7 @@ local function switchRender(dt) end local function ParticleBatchHybrid_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enterTransitionFinish" then ParticleBatchHybrid_entry = scheduler:scheduleScriptFunc(switchRender, 2.0, false) elseif tag == "exit" then @@ -344,17 +344,17 @@ local function ParticleBatchHybrid() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:create("Particles/LavaFlow.plist") + emitter = ax.ParticleSystemQuad:create("Particles/LavaFlow.plist") emitter:retain() - local batch = cc.ParticleBatchNode:createWithTexture(emitter:getTexture()) + local batch = ax.ParticleBatchNode:createWithTexture(emitter:getTexture()) batch:addChild(emitter) layer:addChild(batch, 10) - local node = cc.Node:create() + local node = ax.Node:create() layer:addChild(node) ParticleBatchHybrid_parent1 = batch ParticleBatchHybrid_parent2 = node @@ -375,22 +375,22 @@ local function ParticleBatchMultipleEmitters() local layer = getBaseLayer() onEnterCallback = function() - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - local emitter1 = cc.ParticleSystemQuad:create("Particles/LavaFlow.plist") - emitter1:setStartColor(cc.c4f(1,0,0,1)) - local emitter2 = cc.ParticleSystemQuad:create("Particles/LavaFlow.plist") - emitter2:setStartColor(cc.c4f(0,1,0,1)) - local emitter3 = cc.ParticleSystemQuad:create("Particles/LavaFlow.plist") - emitter3:setStartColor(cc.c4f(0,0,1,1)) + local emitter1 = ax.ParticleSystemQuad:create("Particles/LavaFlow.plist") + emitter1:setStartColor(ax.color(1,0,0,1)) + local emitter2 = ax.ParticleSystemQuad:create("Particles/LavaFlow.plist") + emitter2:setStartColor(ax.color(0,1,0,1)) + local emitter3 = ax.ParticleSystemQuad:create("Particles/LavaFlow.plist") + emitter3:setStartColor(ax.color(0,0,1,1)) - emitter1:setPosition(cc.p(s.width / 1.25, s.height / 1.25)) - emitter2:setPosition(cc.p(s.width / 2, s.height / 2)) - emitter3:setPosition(cc.p(s.width / 4, s.height / 4)) + emitter1:setPosition(ax.p(s.width / 1.25, s.height / 1.25)) + emitter2:setPosition(ax.p(s.width / 2, s.height / 2)) + emitter3:setPosition(ax.p(s.width / 4, s.height / 4)) - local batch = cc.ParticleBatchNode:createWithTexture(emitter1:getTexture()) + local batch = ax.ParticleBatchNode:createWithTexture(emitter1:getTexture()) batch:addChild(emitter1, 0) batch:addChild(emitter2, 0) @@ -401,7 +401,7 @@ local function ParticleBatchMultipleEmitters() titleLabel:setString("Particle Batch") subtitleLabel:setString("Multiple emitters. One Batch") end - + return layer end @@ -412,15 +412,15 @@ local function DemoFlower() local layer = getBaseLayer() onEnterCallback = function() - emitter = cc.ParticleFlower:create() + emitter = ax.ParticleFlower:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_stars1)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_stars1)) setEmitterPosition() titleLabel:setString("ParticleFlower") end - + return layer end @@ -431,17 +431,17 @@ local function DemoGalaxy() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleGalaxy:create() + emitter = ax.ParticleGalaxy:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() titleLabel:setString("ParticleGalaxy") end - + return layer end @@ -452,17 +452,17 @@ local function DemoFirework() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleFireworks:create() + emitter = ax.ParticleFireworks:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_stars1)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_stars1)) setEmitterPosition() titleLabel:setString("ParticleFireworks") end - + return layer end @@ -473,17 +473,17 @@ local function DemoSpiral() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSpiral:create() + emitter = ax.ParticleSpiral:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() titleLabel:setString("ParticleSpiral") end - + return layer end @@ -494,11 +494,11 @@ local function DemoSun() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSun:create() + emitter = ax.ParticleSun:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() @@ -515,17 +515,17 @@ local function DemoPause() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSmoke:create() + emitter = ax.ParticleSmoke:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() titleLabel:setString("Pasue Particle") end - + return layer end @@ -536,17 +536,17 @@ local function DemoMeteor() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleMeteor:create() + emitter = ax.ParticleMeteor:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() titleLabel:setString("ParticleMeteor") end - + return layer end @@ -557,17 +557,17 @@ local function DemoFire() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleFire:create() + emitter = ax.ParticleFire:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) local pos_x, pos_y = emitter:getPosition() emitter:setPosition(pos_x, 100) titleLabel:setString("ParticleFire") end - + return layer end @@ -578,10 +578,10 @@ local function DemoSmoke() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSmoke:create() + emitter = ax.ParticleSmoke:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) local pos_x, pos_y = emitter:getPosition() emitter:setPosition(pos_x, 100) @@ -589,7 +589,7 @@ local function DemoSmoke() titleLabel:setString("ParticleSmoke") end - + return layer end @@ -600,11 +600,11 @@ local function DemoExplosion() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleExplosion:create() + emitter = ax.ParticleExplosion:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_stars1)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_stars1)) emitter:setAutoRemoveOnFinish(true) @@ -612,7 +612,7 @@ local function DemoExplosion() titleLabel:setString("ParticleExplosion") end - + return layer end @@ -623,7 +623,7 @@ local function DemoSnow() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSnow:create() + emitter = ax.ParticleSnow:create() emitter:retain() background:addChild(emitter, 10) local pos_x, pos_y = emitter:getPosition() @@ -632,7 +632,7 @@ local function DemoSnow() emitter:setLifeVar(1) -- gravity - emitter:setGravity(cc.p(0, -10)) + emitter:setGravity(ax.p(0, -10)) -- speed of particles emitter:setSpeed(130) @@ -650,7 +650,7 @@ local function DemoSnow() emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_snow)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_snow)) setEmitterPosition() @@ -667,14 +667,14 @@ local function DemoRain() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleRain:create() + emitter = ax.ParticleRain:create() emitter:retain() background:addChild(emitter, 10) local pos_x, pos_y = emitter:getPosition() emitter:setPosition(pos_x, pos_y - 100) emitter:setLife(4) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) setEmitterPosition() @@ -691,15 +691,15 @@ local function DemoBigFlower() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSystemQuad:createWithTotalParticles(50) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(50) emitter:retain() background:addChild(emitter, 10) - emitter:setTexture( cc.Director:getInstance():getTextureCache():addImage(s_stars1) ) + emitter:setTexture( ax.Director:getInstance():getTextureCache():addImage(s_stars1) ) emitter:setDuration(-1) -- gravity - emitter:setGravity(cc.p(0, 0)) + emitter:setGravity(ax.p(0, 0)) -- angle emitter:setAngle(90) @@ -719,7 +719,7 @@ local function DemoBigFlower() -- emitter position emitter:setPosition(160, 240) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(4) @@ -732,15 +732,15 @@ local function DemoBigFlower() emitter:setEndSpinVar(0) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(80.0) emitter:setStartSizeVar(40.0) - emitter:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) + emitter:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) -- emits per second emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) @@ -763,18 +763,18 @@ local function DemoRotFlower() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSystemQuad:createWithTotalParticles(300) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(300) emitter:retain() background:addChild(emitter, 10) ----emitter:release() -- win32 : Remove this line - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_stars2)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_stars2)) -- duration emitter:setDuration(-1) -- gravity - emitter:setGravity(cc.p(0, 0)) + emitter:setGravity(ax.p(0, 0)) -- angle emitter:setAngle(90) @@ -794,7 +794,7 @@ local function DemoRotFlower() -- emitter position emitter:setPosition(160, 240) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(3) @@ -807,15 +807,15 @@ local function DemoRotFlower() emitter:setEndSpinVar(2000) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(30.0) emitter:setStartSizeVar(0) - emitter:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) + emitter:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) -- emits per second emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) @@ -838,7 +838,7 @@ local function DemoModernArt() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleSystemQuad:createWithTotalParticles(1000) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(1000) emitter:retain() background:addChild(emitter, 10) @@ -848,7 +848,7 @@ local function DemoModernArt() emitter:setDuration(-1) -- gravity - emitter:setGravity(cc.p(0,0)) + emitter:setGravity(ax.p(0,0)) -- angle emitter:setAngle(0) @@ -868,7 +868,7 @@ local function DemoModernArt() -- emitter position emitter:setPosition(s.width / 2, s.height / 2) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(2.0) @@ -878,10 +878,10 @@ local function DemoModernArt() emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(1.0) @@ -890,7 +890,7 @@ local function DemoModernArt() emitter:setEndSizeVar(8.0) -- texture - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) -- additive emitter:setBlendAdditive(false) @@ -910,12 +910,12 @@ local function DemoRing() local layer = getBaseLayer() onEnterCallback = function () - emitter = cc.ParticleFlower:create() + emitter = ax.ParticleFlower:create() emitter:retain() background:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_stars1)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_stars1)) emitter:setLifeVar(0) emitter:setLife(10) emitter:setSpeed(100) @@ -940,30 +940,30 @@ local function ParallaxParticle() background:getParent():removeChild(background, true) background = nil - local p = cc.ParallaxNode:create() + local p = ax.ParallaxNode:create() layer:addChild(p, 5) - local p1 = cc.Sprite:create(s_back3) - local p2 = cc.Sprite:create(s_back3) + local p1 = ax.Sprite:create(s_back3) + local p2 = ax.Sprite:create(s_back3) - p:addChild(p1, 1, cc.p(0.5, 1), cc.p(0, 250)) - p:addChild(p2, 2, cc.p(1.5, 1), cc.p(0, 50)) + p:addChild(p1, 1, ax.p(0.5, 1), ax.p(0, 250)) + p:addChild(p2, 2, ax.p(1.5, 1), ax.p(0, 50)) - emitter = cc.ParticleFlower:create() + emitter = ax.ParticleFlower:create() emitter:retain() - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) p1:addChild(emitter, 10) emitter:setPosition(250, 200) - local par = cc.ParticleSun:create() + local par = ax.ParticleSun:create() p2:addChild(par, 10) - par:setTexture(cc.Director:getInstance():getTextureCache():addImage(s_fire)) + par:setTexture(ax.Director:getInstance():getTextureCache():addImage(s_fire)) - local move = cc.MoveBy:create(4, cc.p(300,0)) + local move = ax.MoveBy:create(4, ax.p(300,0)) local move_back = move:reverse() - local seq = cc.Sequence:create(move, move_back) - p:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, move_back) + p:runAction(ax.RepeatForever:create(seq)) titleLabel:setString("Parallax + Particles") end @@ -978,12 +978,12 @@ local function DemoParticleFromFile(name) local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil local filename = "Particles/" .. name .. ".plist" - emitter = cc.ParticleSystemQuad:create(filename) + emitter = ax.ParticleSystemQuad:create(filename) emitter:retain() layer:addChild(emitter, 10) @@ -1003,21 +1003,21 @@ local function RadiusMode1() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:createWithTotalParticles(200) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(200) emitter:retain() layer:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage("Images/stars-grayscale.png")) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage("Images/stars-grayscale.png")) -- duration - emitter:setDuration(cc.PARTICLE_DURATION_INFINITY) + emitter:setDuration(ax.PARTICLE_DURATION_INFINITY) -- radius mode - emitter:setEmitterMode(cc.PARTICLE_MODE_RADIUS) + emitter:setEmitterMode(ax.PARTICLE_MODE_RADIUS) -- radius mode: start and end radius in pixels emitter:setStartRadius(0) @@ -1036,7 +1036,7 @@ local function RadiusMode1() -- emitter position emitter:setPosition(s.width / 2, s.height / 2) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(5) @@ -1049,15 +1049,15 @@ local function RadiusMode1() emitter:setEndSpinVar(0) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(32) emitter:setStartSizeVar(0) - emitter:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) + emitter:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE ) -- emits per second emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) @@ -1078,26 +1078,26 @@ local function RadiusMode2() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:createWithTotalParticles(200) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(200) emitter:retain() layer:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage("Images/stars-grayscale.png")) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage("Images/stars-grayscale.png")) -- duration - emitter:setDuration(cc.PARTICLE_DURATION_INFINITY ) + emitter:setDuration(ax.PARTICLE_DURATION_INFINITY ) -- radius mode - emitter:setEmitterMode(cc.PARTICLE_MODE_RADIUS) + emitter:setEmitterMode(ax.PARTICLE_MODE_RADIUS) -- radius mode: start and end radius in pixels emitter:setStartRadius(100) emitter:setStartRadiusVar(0) - emitter:setEndRadius(cc.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS) + emitter:setEndRadius(ax.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS) emitter:setEndRadiusVar(0) -- radius mode: degrees per second @@ -1110,7 +1110,7 @@ local function RadiusMode2() -- emitter position emitter:setPosition(s.width / 2, s.height / 2) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(4) @@ -1123,15 +1123,15 @@ local function RadiusMode2() emitter:setEndSpinVar(0) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(32) emitter:setStartSizeVar(0) - emitter:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) + emitter:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) -- emits per second emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) @@ -1152,26 +1152,26 @@ local function Issue704() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:createWithTotalParticles(100) + emitter = ax.ParticleSystemQuad:createWithTotalParticles(100) emitter:retain() layer:addChild(emitter, 10) - emitter:setTexture(cc.Director:getInstance():getTextureCache():addImage("Images/fire.png")) + emitter:setTexture(ax.Director:getInstance():getTextureCache():addImage("Images/fire.png")) -- duration - emitter:setDuration(cc.PARTICLE_DURATION_INFINITY) + emitter:setDuration(ax.PARTICLE_DURATION_INFINITY) -- radius mode - emitter:setEmitterMode(cc.PARTICLE_MODE_RADIUS) + emitter:setEmitterMode(ax.PARTICLE_MODE_RADIUS) -- radius mode: start and end radius in pixels emitter:setStartRadius(50) emitter:setStartRadiusVar(0) - emitter:setEndRadius(cc.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS ) + emitter:setEndRadius(ax.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS ) emitter:setEndRadiusVar(0) -- radius mode: degrees per second @@ -1185,7 +1185,7 @@ local function Issue704() -- emitter position emitter:setPosition(s.width / 2, s.height / 2) - emitter:setPosVar(cc.p(0, 0)) + emitter:setPosVar(ax.p(0, 0)) -- life of particles emitter:setLife(5) @@ -1198,15 +1198,15 @@ local function Issue704() emitter:setEndSpinVar(0) -- color of particles - emitter:setStartColor(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setStartColorVar(cc.c4f(0.5, 0.5, 0.5, 1.0)) - emitter:setEndColor(cc.c4f(0.1, 0.1, 0.1, 0.2)) - emitter:setEndColorVar(cc.c4f(0.1, 0.1, 0.1, 0.2)) + emitter:setStartColor(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setStartColorVar(ax.color(0.5, 0.5, 0.5, 1.0)) + emitter:setEndColor(ax.color(0.1, 0.1, 0.1, 0.2)) + emitter:setEndColorVar(ax.color(0.1, 0.1, 0.1, 0.2)) -- size, in pixels emitter:setStartSize(16) emitter:setStartSizeVar(0) - emitter:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) + emitter:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) -- emits per second emitter:setEmissionRate(emitter:getTotalParticles() / emitter:getLife()) @@ -1214,8 +1214,8 @@ local function Issue704() -- additive emitter:setBlendAdditive(false) - local rot = cc.RotateBy:create(16, 360) - emitter:runAction(cc.RepeatForever:create(rot)) + local rot = ax.RotateBy:create(16, 360) + emitter:runAction(ax.RepeatForever:create(rot)) titleLabel:setString("Issue 704. Free + Rot") subtitleLabel:setString("Emitted particles should not rotate") @@ -1234,12 +1234,12 @@ local function updateQuads(dt) update(dt) Issue870_index = math.fmod(Issue870_index + 1, 4) - local rect = cc.rect(Issue870_index * 32, 0, 32, 32) + local rect = ax.rect(Issue870_index * 32, 0, 32, 32) emitter:setTextureWithRect(emitter:getTexture(), rect) end local function Issue870_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enterTransitionFinish" then Issue870_entry = scheduler:scheduleScriptFunc(updateQuads, 2.0, false) elseif tag == "exit" then @@ -1251,13 +1251,13 @@ end local function Issue870() local layer = getBaseLayer() - + onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - local system = cc.ParticleSystemQuad:create("Particles/SpinningPeas.plist") - system:setTextureWithRect(cc.Director:getInstance():getTextureCache():addImage("Images/particles.png"), cc.rect(0,0,32,32)) + local system = ax.ParticleSystemQuad:create("Particles/SpinningPeas.plist") + system:setTextureWithRect(ax.Director:getInstance():getTextureCache():addImage("Images/particles.png"), ax.rect(0,0,32,32)) layer:addChild(system, 10) emitter = system emitter:retain() @@ -1279,16 +1279,16 @@ local function MultipleParticleSystems() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - cc.Director:getInstance():getTextureCache():addImage("Images/particles.png") + ax.Director:getInstance():getTextureCache():addImage("Images/particles.png") for i = 0, 4 do - local particleSystem = cc.ParticleSystemQuad:create("Particles/SpinningPeas.plist") + local particleSystem = ax.ParticleSystemQuad:create("Particles/SpinningPeas.plist") particleSystem:setPosition(i * 50, i * 50) - particleSystem:setPositionType(cc.POSITION_TYPE_GROUPED ) + particleSystem:setPositionType(ax.POSITION_TYPE_GROUPED ) layer:addChild(particleSystem) end @@ -1308,16 +1308,16 @@ local function MultipleParticleSystemsBatched() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - local batchNode = cc.ParticleBatchNode:createWithTexture(nil, 3000) + local batchNode = ax.ParticleBatchNode:createWithTexture(nil, 3000) layer:addChild(batchNode, 1, 2) for i = 0, 4 do - local particleSystem = cc.ParticleSystemQuad:create("Particles/SpinningPeas.plist") - particleSystem:setPositionType(cc.POSITION_TYPE_GROUPED ) + local particleSystem = ax.ParticleSystemQuad:create("Particles/SpinningPeas.plist") + particleSystem:setPositionType(ax.POSITION_TYPE_GROUPED ) particleSystem:setPosition(i * 50, i * 50) batchNode:setTexture(particleSystem:getTexture()) batchNode:addChild(particleSystem) @@ -1348,8 +1348,8 @@ local function removeSystem(dt) AddAndDeleteParticleSystems_batchNode:removeChild(AddAndDeleteParticleSystems_batchNode:getChildren()[(rand)], true) --add new - local particleSystem = cc.ParticleSystemQuad:create("Particles/Spiral.plist") - particleSystem:setPositionType(cc.POSITION_TYPE_GROUPED ) + local particleSystem = ax.ParticleSystemQuad:create("Particles/Spiral.plist") + particleSystem:setPositionType(ax.POSITION_TYPE_GROUPED ) particleSystem:setTotalParticles(200) particleSystem:setPosition(math.fmod(math.random(1, 999999), 300) ,math.fmod(math.random(1, 999999), 400)) @@ -1361,7 +1361,7 @@ local function removeSystem(dt) end local function AddAndDeleteParticleSystems_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enterTransitionFinish" then AddAndDeleteParticleSystems_entry = scheduler:scheduleScriptFunc(removeSystem, 2.0, false) elseif tag == "exit" then @@ -1375,20 +1375,20 @@ local function AddAndDeleteParticleSystems() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil --adds the texture inside the plist to the texture cache - AddAndDeleteParticleSystems_batchNode = cc.ParticleBatchNode:createWithTexture(nil, 16000) + AddAndDeleteParticleSystems_batchNode = ax.ParticleBatchNode:createWithTexture(nil, 16000) layer:addChild(AddAndDeleteParticleSystems_batchNode, 1, 2) for i = 0, 5 do - local particleSystem = cc.ParticleSystemQuad:create("Particles/Spiral.plist") + local particleSystem = ax.ParticleSystemQuad:create("Particles/Spiral.plist") AddAndDeleteParticleSystems_batchNode:setTexture(particleSystem:getTexture()) - particleSystem:setPositionType(cc.POSITION_TYPE_GROUPED ) + particleSystem:setPositionType(ax.POSITION_TYPE_GROUPED ) particleSystem:setTotalParticles(200) particleSystem:setPosition(i * 15 + 100, i * 15 + 100) @@ -1420,13 +1420,13 @@ local function reorderSystem(dt) local childArray = ReorderParticleSystems_batchNode:getChildren() local random = math.random(1,#(childArray)) local child = childArray[random] - -- problem: there's no getLocalZOrder() for cc.Object + -- problem: there's no getLocalZOrder() for ax.Object -- ReorderParticleSystems_batchNode:reorderChild(child, child:getLocalZOrder() - 1) ReorderParticleSystems_batchNode:reorderChild(child, math.random(0, 99999)) end local function ReorderParticleSystems_onEnterOrExit(tag) - local scheduler = cc.Director:getInstance():getScheduler() + local scheduler = ax.Director:getInstance():getScheduler() if tag == "enterTransitionFinish" then ReorderParticleSystems_entry = scheduler:scheduleScriptFunc(reorderSystem, 2.0, false) elseif tag == "exit" then @@ -1440,28 +1440,28 @@ local function ReorderParticleSystems() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background ,true) background = nil - ReorderParticleSystems_batchNode = cc.ParticleBatchNode:create("Images/stars-grayscale.png", 3000) + ReorderParticleSystems_batchNode = ax.ParticleBatchNode:create("Images/stars-grayscale.png", 3000) layer:addChild(ReorderParticleSystems_batchNode, 1, 2) for i = 0, 2 do - local particleSystem = cc.ParticleSystemQuad:createWithTotalParticles(200) + local particleSystem = ax.ParticleSystemQuad:createWithTotalParticles(200) particleSystem:setTexture(ReorderParticleSystems_batchNode:getTexture()) -- duration - particleSystem:setDuration(cc.PARTICLE_DURATION_INFINITY) + particleSystem:setDuration(ax.PARTICLE_DURATION_INFINITY) -- radius mode - particleSystem:setEmitterMode(cc.PARTICLE_MODE_RADIUS) + particleSystem:setEmitterMode(ax.PARTICLE_MODE_RADIUS) -- radius mode: 100 pixels from center particleSystem:setStartRadius(100) particleSystem:setStartRadiusVar(0) - particleSystem:setEndRadius(cc.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS ) + particleSystem:setEndRadius(ax.PARTICLE_START_RADIUS_EQUAL_TO_END_RADIUS ) particleSystem:setEndRadiusVar(0) -- not used when start == end -- radius mode: degrees per second @@ -1475,7 +1475,7 @@ local function ReorderParticleSystems() particleSystem:setAngleVar(0) -- emitter position - particleSystem:setPosVar(cc.p(0, 0)) + particleSystem:setPosVar(ax.p(0, 0)) -- life of particles particleSystem:setLife(4) @@ -1488,23 +1488,23 @@ local function ReorderParticleSystems() particleSystem:setEndSpinVar(0) -- color of particles - local startColor = cc.c4f(0, 0, 0, 1) + local startColor = ax.color(0, 0, 0, 1) if i == 0 then startColor.r = 1 elseif i == 1 then startColor.g = 1 elseif i == 2 then startColor.b = 1 end particleSystem:setStartColor(startColor) - particleSystem:setStartColorVar(cc.c4f(0, 0, 0, 0)) + particleSystem:setStartColorVar(ax.color(0, 0, 0, 0)) local endColor = startColor particleSystem:setEndColor(endColor) - particleSystem:setEndColorVar(cc.c4f(0, 0, 0, 0)) + particleSystem:setEndColorVar(ax.color(0, 0, 0, 0)) -- size, in pixels particleSystem:setStartSize(32) particleSystem:setStartSizeVar(0) - particleSystem:setEndSize(cc.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) + particleSystem:setEndSize(ax.PARTICLE_START_SIZE_EQUAL_TO_END_SIZE) -- emits per second particleSystem:setEmissionRate(particleSystem:getTotalParticles() / particleSystem:getLife()) @@ -1513,7 +1513,7 @@ local function ReorderParticleSystems() particleSystem:setPosition(i * 10 + 120, 200) ReorderParticleSystems_batchNode:addChild(particleSystem) - particleSystem:setPositionType(cc.POSITION_TYPE_FREE ) + particleSystem:setPositionType(ax.POSITION_TYPE_FREE ) --particleSystem:release() end @@ -1535,21 +1535,21 @@ local function PremultipliedAlphaTest() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 255)) + layer:setColor(ax.color32(0, 0, 255)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:create("Particles/BoilingFoam.plist") + emitter = ax.ParticleSystemQuad:create("Particles/BoilingFoam.plist") emitter:retain() - emitter:setBlendFunc(cc.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) + emitter:setBlendFunc(ax.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) --assert(emitter:getOpacityModifyRGB(), "Particle texture does not have premultiplied alpha, test is useless") - emitter:setStartColor(cc.c4f(1, 1, 1, 1)) - emitter:setEndColor(cc.c4f(1, 1, 1, 0)) - emitter:setStartColorVar(cc.c4f(0, 0, 0, 0)) - emitter:setEndColorVar(cc.c4f(0, 0, 0, 0)) + emitter:setStartColor(ax.color(1, 1, 1, 1)) + emitter:setEndColor(ax.color(1, 1, 1, 0)) + emitter:setStartColorVar(ax.color(0, 0, 0, 0)) + emitter:setEndColorVar(ax.color(0, 0, 0, 0)) layer:addChild(emitter, 10) @@ -1567,11 +1567,11 @@ local function PremultipliedAlphaTest2() local layer = getBaseLayer() onEnterCallback = function () - layer:setColor(cc.c3b(0, 0, 0)) + layer:setColor(ax.color32(0, 0, 0)) layer:removeChild(background, true) background = nil - emitter = cc.ParticleSystemQuad:create("Particles/TestPremultipliedAlpha.plist") + emitter = ax.ParticleSystemQuad:create("Particles/TestPremultipliedAlpha.plist") emitter:retain() layer:addChild(emitter ,10) @@ -1638,7 +1638,7 @@ end function ParticleTest() cclog("ParticleTest") - local scene = cc.Scene:create() + local scene = ax.Scene:create() SceneIdx = -1 scene:addChild(nextAction()) diff --git a/tests/lua-tests/Content/src/Physics3DTest/Physics3DTest.lua b/tests/lua-tests/Content/src/Physics3DTest/Physics3DTest.lua index b01f8caa3a0d..6d393eef4763 100644 --- a/tests/lua-tests/Content/src/Physics3DTest/Physics3DTest.lua +++ b/tests/lua-tests/Content/src/Physics3DTest/Physics3DTest.lua @@ -10,11 +10,11 @@ local ARRAY_SIZE_Z = 4 ----Physics3DTestDemo ---------------------------------------- -cc.PhysicsSprite3D = ax.PhysicsMeshRenderer +ax.PhysicsSprite3D = ax.PhysicsMeshRenderer local Physics3DTestDemo = class("Physics3DTestDemo", function () -- body - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -46,20 +46,20 @@ end function Physics3DTestDemo:shootBox(des) local rbDes = {} local cameraPosition = self._camera:getPosition3D() - local linearVec = cc.vec3normalize(cc.vec3sub(des, cameraPosition)) - linearVec = cc.vec3mul(linearVec, 100) + local linearVec = ax.vec3normalize(ax.vec3sub(des, cameraPosition)) + linearVec = ax.vec3mul(linearVec, 100) - rbDes.originalTransform = cc.mat4.translate(cc.mat4.createIdentity(), self._camera:getPosition3D()) + rbDes.originalTransform = ax.mat4.translate(ax.mat4.createIdentity(), self._camera:getPosition3D()) rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(0.5, 0.5, 0.5)) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(0.5, 0.5, 0.5)) - local sprite = cc.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) + local sprite = ax.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) sprite:setTexture("Images/Icon.png") local rigidBody = sprite:getPhysicsObj() - rigidBody:setLinearFactor(cc.vec3(1.0, 1.0, 1.0)) + rigidBody:setLinearFactor(ax.vec3(1.0, 1.0, 1.0)) rigidBody:setLinearVelocity(linearVec) - rigidBody:setAngularVelocity(cc.vec3(0.0, 0.0, 0.0)) + rigidBody:setAngularVelocity(ax.vec3(0.0, 0.0, 0.0)) rigidBody:setCcdMotionThreshold(0.5) rigidBody:setCcdSweptSphereRadius(0.4) @@ -67,32 +67,32 @@ function Physics3DTestDemo:shootBox(des) sprite:setPosition3D(self._camera:getPosition3D()) sprite:setScale(0.5) sprite:syncNodeToPhysics() - + --optimize, only sync node to physics - sprite:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) --sync node to physics - - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) --sync node to physics + + sprite:setCameraMask(ax.CameraFlag.USER1) end function Physics3DTestDemo:onEnter() - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() if nil ~= scene then self._physicsScene = scene local physics3DWorld = scene:getPhysics3DWorld() physics3DWorld:setDebugDrawEnable(false) - local size = cc.Director:getInstance():getWinSize() - self._camera = cc.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) - self._camera:setPosition3D(cc.vec3(0.0, 50.0, 100.0)) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + local size = ax.Director:getInstance():getWinSize() + self._camera = ax.Camera:createPerspective(30.0, size.width / size.height, 1.0, 1000.0) + self._camera:setPosition3D(ax.vec3(0.0, 50.0, 100.0)) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(self._camera) if Helper.index ~= 2 then - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) self._needShootBox = true - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function(touches, event) @@ -101,14 +101,14 @@ function Physics3DTestDemo:onEnter() local delta = touch:getDelta() self._angle = self._angle - delta.x * math.pi / 180.0 - self._camera:setPosition3D(cc.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) - + self._camera:setPosition3D(ax.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) + if (delta.x * delta.x + delta.y * delta.y) > 16 then self._needShootBox = false end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function(touches, event) if self._needShootBox == false then @@ -117,26 +117,26 @@ function Physics3DTestDemo:onEnter() if #touches > 0 then local location = touches[1]:getLocationInView() - local nearP = cc.vec3(location.x, location.y, -1.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, -1.0) + local farP = ax.vec3(location.x, location.y, 1.0) nearP = self._camera:unproject(nearP) farP = self._camera:unproject(farP) - - local dir = cc.vec3sub(farP, nearP) + + local dir = ax.vec3sub(farP, nearP) local cameraPosition = self._camera:getPosition3D() - self:shootBox(cc.vec3add(cameraPosition, cc.vec3mul(dir, 10))) + self:shootBox(ax.vec3add(cameraPosition, ax.vec3mul(dir, 10))) end - end, cc.Handler.EVENT_TOUCHES_ENDED) + end, ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) end - + local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 10 - local label = cc.Label:createWithTTF(ttfConfig,"DebugDraw OFF") - local menuItem = cc.MenuItemLabel:create(label) + local label = ax.Label:createWithTTF(ttfConfig,"DebugDraw OFF") + local menuItem = ax.MenuItemLabel:create(label) menuItem:registerScriptTapHandler(function (tag, sender) if physics3DWorld:isDebugDrawEnabled() then physics3DWorld:setDebugDrawEnable(false) @@ -147,10 +147,10 @@ function Physics3DTestDemo:onEnter() end end) - local menu = cc.Menu:create(menuItem) - menu:setPosition(cc.p(0.0,0.0)) - menuItem:setAnchorPoint(cc.p(0.0, 1.0)) - menuItem:setPosition(cc.p(VisibleRect:left().x, VisibleRect:top().y-50)) + local menu = ax.Menu:create(menuItem) + menu:setPosition(ax.p(0.0,0.0)) + menuItem:setAnchorPoint(ax.p(0.0, 1.0)) + menuItem:setPosition(ax.p(VisibleRect:left().x, VisibleRect:top().y-50)) self:addChild(menu) self._angle = 0.0 @@ -164,7 +164,7 @@ function Physics3DTestDemo:onExit() end function Physics3DTestDemo:extend() - + end ---------------------------------------- @@ -179,19 +179,19 @@ end function BasicPhysics3DDemo:extend() local rbDes = {} rbDes.mass = 0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(60.0, 1.0, 60.0)) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(60.0, 1.0, 60.0)) - local floor = cc.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) + local floor = ax.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) floor:setTexture("MeshRendererTest/plane.png") floor:setScaleX(60) floor:setScaleZ(60) self:addChild(floor) - floor:setCameraMask(cc.CameraFlag.USER1) + floor:setCameraMask(ax.CameraFlag.USER1) floor:syncNodeToPhysics() - floor:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.NONE) + floor:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.NONE) rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(0.8, 0.8, 0.8)) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(0.8, 0.8, 0.8)) local start_x = START_POS_X - ARRAY_SIZE_X/2 local start_y = START_POS_Y @@ -203,13 +203,13 @@ function BasicPhysics3DDemo:extend() local x = 1.0 * (i - 1) + start_x local y = 5.0+1.0 * (k - 1) + start_y local z = 1.0 * (j - 1) + start_z - - local sprite = cc.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) + + local sprite = ax.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) sprite:setTexture("Images/CyanSquare.png") - sprite:setPosition3D(cc.vec3(x, y, z)) + sprite:setPosition3D(ax.vec3(x, y, z)) sprite:syncNodeToPhysics() - sprite:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) + sprite:setCameraMask(ax.CameraFlag.USER1) sprite:setScale(0.8) self:addChild(sprite) end @@ -230,15 +230,15 @@ end function Physics3DConstraintDemo:extend() - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function(touches, event) if nil ~= self._camera then local touch = touches[1] local location = touch:getLocationInView() - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) - - local size = cc.Director:getInstance():getWinSize() + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) + + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) @@ -246,32 +246,32 @@ function Physics3DConstraintDemo:extend() local hitResult = {} local ret = false ret, hitResult = physicsWorld:rayCast(nearP, farP, hitResult) - if true == ret and nil ~= hitResult.hitObj and hitResult.hitObj:getObjType() == cc.Physics3DObject.PhysicsObjType.RIGID_BODY then - local mat = cc.mat4.getInversed(hitResult.hitObj:getWorldTransform()) - local position = cc.mat4.transformVector(mat, cc.vec4(hitResult.hitPosition.x, hitResult.hitPosition.y, hitResult.hitPosition.z, 1.0)) + if true == ret and nil ~= hitResult.hitObj and hitResult.hitObj:getObjType() == ax.Physics3DObject.PhysicsObjType.RIGID_BODY then + local mat = ax.mat4.getInversed(hitResult.hitObj:getWorldTransform()) + local position = ax.mat4.transformVector(mat, ax.vec4(hitResult.hitPosition.x, hitResult.hitPosition.y, hitResult.hitPosition.z, 1.0)) - self._constraint = cc.Physics3DPointToPointConstraint:create(hitResult.hitObj, position) + self._constraint = ax.Physics3DPointToPointConstraint:create(hitResult.hitObj, position) physicsWorld:addPhysics3DConstraint(self._constraint, true) self._pickingDistance = math.sqrt(math.pow(hitResult.hitPosition.x - nearP.x, 2) + math.pow(hitResult.hitPosition.y - nearP.y, 2) + math.pow(hitResult.hitPosition.z - nearP.z, 2)) return end end self._needShootBox = false - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function(touches, event) if self._constraint ~= nil then local touch = touches[1] local location = touch:getLocationInView() - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) - local dir = cc.vec3normalize(cc.vec3sub(farP, nearP)) - self._constraint:setPivotPointInB(cc.vec3add(nearP, cc.vec3mul(dir, self._pickingDistance))) + local dir = ax.vec3normalize(ax.vec3sub(farP, nearP)) + self._constraint:setPivotPointInB(ax.vec3add(nearP, ax.vec3mul(dir, self._pickingDistance))) return end @@ -280,14 +280,14 @@ function Physics3DConstraintDemo:extend() local delta = touch:getDelta() self._angle = self._angle - delta.x * math.pi / 180.0 - self._camera:setPosition3D(cc.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) - self._camera:lookAt(cc.vec3(0.0, 0.0, 0.0), cc.vec3(0.0, 1.0, 0.0)) + self._camera:setPosition3D(ax.vec3(100.0 * math.sin(self._angle), 50.0, 100.0 * math.cos(self._angle))) + self._camera:lookAt(ax.vec3(0.0, 0.0, 0.0), ax.vec3(0.0, 1.0, 0.0)) if (delta.x * delta.x + delta.y * delta.y) > 16 then self._needShootBox = false end end - end, cc.Handler.EVENT_TOUCHES_MOVED) + end, ax.Handler.EVENT_TOUCHES_MOVED) listener:registerScriptHandler(function(touches, event) @@ -303,16 +303,16 @@ function Physics3DConstraintDemo:extend() if #touches > 0 then local location = touches[1]:getLocationInView() - local nearP = cc.vec3(location.x, location.y, -1.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, -1.0) + local farP = ax.vec3(location.x, location.y, 1.0) nearP = self._camera:unproject(nearP) farP = self._camera:unproject(farP) - local dir = cc.vec3sub(farP, nearP) + local dir = ax.vec3sub(farP, nearP) local cameraPosition = self._camera:getPosition3D() - self:shootBox(cc.vec3add(cameraPosition, cc.vec3mul(dir, 10))) + self:shootBox(ax.vec3add(cameraPosition, ax.vec3mul(dir, 10))) end - end, cc.Handler.EVENT_TOUCHES_ENDED) + end, ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -320,132 +320,132 @@ function Physics3DConstraintDemo:extend() local rbDes = {} rbDes.disableSleep = true --create box - local sprite = cc.Sprite3D:create("MeshRendererTest/orc.c3b") + local sprite = ax.Sprite3D:create("MeshRendererTest/orc.c3b") rbDes.mass = 10.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(5.0, 5.0, 5.0)) - local rigidBody = cc.Physics3DRigidBody:create(rbDes) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(5.0, 5.0, 5.0)) + local rigidBody = ax.Physics3DRigidBody:create(rbDes) - local quat = cc.quaternion_createFromAxisAngle(cc.vec3(0, 1, 0), math.pi) - local component = cc.Physics3DComponent:create(rigidBody, cc.vec3(0.0, -3.0, 0.0), quat) + local quat = ax.quaternion_createFromAxisAngle(ax.vec3(0, 1, 0), math.pi) + local component = ax.Physics3DComponent:create(rigidBody, ax.vec3(0.0, -3.0, 0.0), quat) sprite:addComponent(component) self:addChild(sprite) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) sprite:setScale(0.4) - sprite:setPosition3D(cc.vec3(-20.0, 5.0, 0.0)) + sprite:setPosition3D(ax.vec3(-20.0, 5.0, 0.0)) --sync node position to physics component:syncNodeToPhysics() --physics controlled, we will not set position for it, so we can skip sync node position to physics - component:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) + component:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) self._physicsScene:setPhysics3DDebugCamera(self._camera) local physicsWorld = self._physicsScene:getPhysics3DWorld() --create point to point constraint - local constraint = cc.Physics3DPointToPointConstraint:create(rigidBody, cc.vec3(2.5, 2.5, 2.5)) + local constraint = ax.Physics3DPointToPointConstraint:create(rigidBody, ax.vec3(2.5, 2.5, 2.5)) physicsWorld:addPhysics3DConstraint(constraint) --create hinge constraint rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(8.0, 8.0, 1.0)) - rigidBody = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBody) - sprite = cc.Sprite3D:create("MeshRendererTest/box.c3t") + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(8.0, 8.0, 1.0)) + rigidBody = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBody) + sprite = ax.Sprite3D:create("MeshRendererTest/box.c3t") sprite:setTexture("MeshRendererTest/plane.png") sprite:setScaleX(8.0) sprite:setScaleY(8.0) - sprite:setPosition3D(cc.vec3(5.0, 0.0, 0.0)) + sprite:setPosition3D(ax.vec3(5.0, 0.0, 0.0)) sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) component:syncNodeToPhysics() - rigidBody:setAngularVelocity(cc.vec3(0,3,0)) - constraint = cc.Physics3DHingeConstraint:create(rigidBody, cc.vec3(4.0, 4.0, 0.5), cc.vec3(0.0, 1.0, 0.0)) + rigidBody:setAngularVelocity(ax.vec3(0,3,0)) + constraint = ax.Physics3DHingeConstraint:create(rigidBody, ax.vec3(4.0, 4.0, 0.5), ax.vec3(0.0, 1.0, 0.0)) physicsWorld:addPhysics3DConstraint(constraint) --create slider constraint rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(3.0, 2.0, 3.0)) - rigidBody = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBody) - sprite = cc.Sprite3D:create("MeshRendererTest/box.c3t") + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(3.0, 2.0, 3.0)) + rigidBody = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBody) + sprite = ax.Sprite3D:create("MeshRendererTest/box.c3t") sprite:setTexture("MeshRendererTest/plane.png") sprite:setScaleX(3.0) sprite:setScaleZ(3.0) - sprite:setPosition3D(cc.vec3(30.0, 15.0, 0.0)) + sprite:setPosition3D(ax.vec3(30.0, 15.0, 0.0)) sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) component:syncNodeToPhysics() - rigidBody:setLinearVelocity(cc.vec3(0,3,0)) + rigidBody:setLinearVelocity(ax.vec3(0,3,0)) rbDes.mass = 0.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(3.0, 3.0, 3.0)) - local rigidBodyB = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBodyB) - sprite = cc.Sprite3D:create("MeshRendererTest/box.c3t") + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(3.0, 3.0, 3.0)) + local rigidBodyB = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBodyB) + sprite = ax.Sprite3D:create("MeshRendererTest/box.c3t") sprite:setTexture("MeshRendererTest/plane.png") sprite:setScale(3.0) - sprite:setPosition3D(cc.vec3(30.0, 5.0, 0.0)) + sprite:setPosition3D(ax.vec3(30.0, 5.0, 0.0)) sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) component:syncNodeToPhysics() - local frameInA = cc.mat4.createRotationZ(cc.mat4.createIdentity(), math.pi / 2) + local frameInA = ax.mat4.createRotationZ(ax.mat4.createIdentity(), math.pi / 2) local frameInB = {} for i=1,16 do frameInB[i] = frameInA[i] end frameInA[14] = -5.0 frameInB[14] = 5.0 - constraint = cc.Physics3DSliderConstraint:create(rigidBody, rigidBodyB, frameInA, frameInB, false) + constraint = ax.Physics3DSliderConstraint:create(rigidBody, rigidBodyB, frameInA, frameInB, false) physicsWorld:addPhysics3DConstraint(constraint) constraint:setLowerLinLimit(-5.0) constraint:setUpperLinLimit(5.0) --create ConeTwist constraint rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(3.0, 3.0, 3.0)) - rigidBody = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBody) - sprite = cc.Sprite3D:create("MeshRendererTest/box.c3t") + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(3.0, 3.0, 3.0)) + rigidBody = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBody) + sprite = ax.Sprite3D:create("MeshRendererTest/box.c3t") sprite:setTexture("MeshRendererTest/plane.png") sprite:setScale(3.0) - sprite:setPosition3D(cc.vec3(-10.0, 5.0, 0.0)) + sprite:setPosition3D(ax.vec3(-10.0, 5.0, 0.0)) sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) component:syncNodeToPhysics() - frameInA = cc.mat4.createRotationZ(frameInA, math.pi / 2) + frameInA = ax.mat4.createRotationZ(frameInA, math.pi / 2) frameInA[13] = 0.0 frameInA[14] = -10.0 frameInA[15] = 0.0 - constraint = cc.Physics3DConeTwistConstraint:create(rigidBody, frameInA) + constraint = ax.Physics3DConeTwistConstraint:create(rigidBody, frameInA) physicsWorld:addPhysics3DConstraint(constraint, true) constraint:setLimit(math.pi / 180 * 10, math.pi / 180 * 10, math.pi / 180 * 40) --reate 6 dof constraint rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(3.0, 3.0, 3.0)) - rigidBody = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBody) - sprite = cc.Sprite3D:create("MeshRendererTest/box.c3t") + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(3.0, 3.0, 3.0)) + rigidBody = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBody) + sprite = ax.Sprite3D:create("MeshRendererTest/box.c3t") sprite:setTexture("MeshRendererTest/plane.png") sprite:setScale(3.0) - sprite:setPosition3D(cc.vec3(30.0, -5.0, 0.0)) + sprite:setPosition3D(ax.vec3(30.0, -5.0, 0.0)) sprite:addComponent(component) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) component:syncNodeToPhysics() - frameInA = cc.mat4.setIdentity(frameInA) - constraint = cc.Physics3D6DofConstraint:create(rigidBody, frameInA, false) + frameInA = ax.mat4.setIdentity(frameInA) + constraint = ax.Physics3D6DofConstraint:create(rigidBody, frameInA, false) physicsWorld:addPhysics3DConstraint(constraint) - constraint:setAngularLowerLimit(cc.vec3(0,0,0)) - constraint:setAngularUpperLimit(cc.vec3(0,0,0)) - constraint:setLinearLowerLimit(cc.vec3(-10,0,0)) - constraint:setLinearUpperLimit(cc.vec3(10,0,0)) + constraint:setAngularLowerLimit(ax.vec3(0,0,0)) + constraint:setAngularUpperLimit(ax.vec3(0,0,0)) + constraint:setLinearLowerLimit(ax.vec3(-10,0,0)) + constraint:setLinearUpperLimit(ax.vec3(10,0,0)) end ---------------------------------------- @@ -460,41 +460,41 @@ end function Physics3DKinematicDemo:extend() local rbDes = {} rbDes.mass = 0.0 - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(60.0, 1.0, 60.0)) - local floor = cc.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(60.0, 1.0, 60.0)) + local floor = ax.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) floor:setTexture("MeshRendererTest/plane.png") floor:setScaleX(60) floor:setScaleZ(60) - floor:setPosition3D(cc.vec3(0.0, -1.0, 0.0)) + floor:setPosition3D(ax.vec3(0.0, -1.0, 0.0)) self:addChild(floor) - floor:setCameraMask(cc.CameraFlag.USER1) + floor:setCameraMask(ax.CameraFlag.USER1) floor:syncNodeToPhysics() --static object sync is not needed - floor:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.NONE) + floor:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.NONE) for i=1, 3 do rbDes.mass = 0.0 --kinematic objects. zero mass so that it can not be affected by other dynamic objects - rbDes.shape = cc.Physics3DShape:createBox(cc.vec3(2.0, 2.0, 2.0)) - - local sprite = cc.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) + rbDes.shape = ax.Physics3DShape:createBox(ax.vec3(2.0, 2.0, 2.0)) + + local sprite = ax.PhysicsSprite3D:create("MeshRendererTest/box.c3t", rbDes) sprite:setTexture("Images/CyanSquare.png") - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) local rigidBody = sprite:getPhysicsObj() rigidBody:setKinematic(true) - + self:addChild(sprite) sprite:setScale(2.0) - sprite:setPosition3D(cc.vec3(-15.0, 0.0, 15.0 - 15.0 * (i - 1) )) - local moveby = cc.MoveBy:create(2.0 + (i - 1), cc.vec3(30.0, 0.0, 0.0)) - sprite:runAction(cc.RepeatForever:create(cc.Sequence:create(moveby, moveby:reverse()))) + sprite:setPosition3D(ax.vec3(-15.0, 0.0, 15.0 - 15.0 * (i - 1) )) + local moveby = ax.MoveBy:create(2.0 + (i - 1), ax.vec3(30.0, 0.0, 0.0)) + sprite:runAction(ax.RepeatForever:create(ax.Sequence:create(moveby, moveby:reverse()))) end --create Dynamic --create several spheres rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createSphere(0.5) + rbDes.shape = ax.Physics3DShape:createSphere(0.5) local start_x = START_POS_X - ARRAY_SIZE_X/2 local start_y = START_POS_Y + 5.0 local start_z = START_POS_Z - ARRAY_SIZE_Z/2 @@ -506,21 +506,21 @@ function Physics3DKinematicDemo:extend() local y = 5.0 + 1.0 * (k - 1) + start_y local z = 1.0 * (j - 1) + start_z if rbDes.originalTransform == nil then - rbDes.originalTransform = cc.mat4.createIdentity() + rbDes.originalTransform = ax.mat4.createIdentity() else - rbDes.originalTransform = cc.mat4.setIdentity(rbDes.originalTransform) + rbDes.originalTransform = ax.mat4.setIdentity(rbDes.originalTransform) end - rbDes.originalTransform = cc.mat4.translate(rbDes.originalTransform, cc.vec3(x, y, z)) + rbDes.originalTransform = ax.mat4.translate(rbDes.originalTransform, ax.vec3(x, y, z)) - local sprite = cc.PhysicsSprite3D:create("MeshRendererTest/sphere.c3b", rbDes) + local sprite = ax.PhysicsSprite3D:create("MeshRendererTest/sphere.c3b", rbDes) sprite:setTexture("MeshRendererTest/plane.png") - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) sprite:setScale(1.00 / sprite:getContentSize().width) self:addChild(sprite) - sprite:setPosition3D(cc.vec3(x, y, z)) + sprite:setPosition3D(ax.vec3(x, y, z)) sprite:syncNodeToPhysics() - sprite:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) + sprite:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) end end end @@ -541,32 +541,32 @@ function Physics3DCollisionCallbackDemo:extend() local rbDes = {} local scale = 2.0 - local trianglesList = cc.Bundle3D:getTrianglesList("MeshRendererTest/boss.c3b") + local trianglesList = ax.Bundle3D:getTrianglesList("MeshRendererTest/boss.c3b") for i = 1, #trianglesList do trianglesList[i] = {x = trianglesList[i].x * scale, y = trianglesList[i].y * scale, z = trianglesList[i].z * scale} end rbDes.mass = 0.0 - rbDes.shape = cc.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) - local rigidBody = cc.Physics3DRigidBody:create(rbDes) - local component = cc.Physics3DComponent:create(rigidBody) - local sprite = cc.Sprite3D:create("MeshRendererTest/boss.c3b") + rbDes.shape = ax.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) + local rigidBody = ax.Physics3DRigidBody:create(rbDes) + local component = ax.Physics3DComponent:create(rigidBody) + local sprite = ax.Sprite3D:create("MeshRendererTest/boss.c3b") sprite:addComponent(component) - sprite:setRotation3D(cc.vec3(-90.0, 0.0, 0.0)) + sprite:setRotation3D(ax.vec3(-90.0, 0.0, 0.0)) sprite:setScale(scale) - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) self:addChild(sprite) rigidBody:setCollisionCallback(function (collisionInfo) if nil ~= collisionInfo.collisionPointList and #collisionInfo.collisionPointList > 0 then if collisionInfo.objA:getMask() ~= 0 then - local ps = cc.PUParticleSystem3D:create("Particle3D/scripts/mp_hit_04.pu") + local ps = ax.PUParticleSystem3D:create("Particle3D/scripts/mp_hit_04.pu") ps:setPosition3D(collisionInfo.collisionPointList[1].worldPositionOnB) ps:setScale(0.05) ps:startParticleSystem() ps:setCameraMask(2) self:addChild(ps) - ps:runAction(cc.Sequence:create(cc.DelayTime:create(1.0), cc.CallFunc:create(function() + ps:runAction(ax.Sequence:create(ax.DelayTime:create(1.0), ax.CallFunc:create(function() ps:removeFromParent() end))) collisionInfo.objA:setMask(0) @@ -587,38 +587,38 @@ function Physics3DTerrainDemo:subtitle() end function Physics3DTerrainDemo:extend() - + local detailMapR = { _detailMapSrc = "TerrainTest/dirt.jpg", _detailMapSize = 35} local detailMapG = { _detailMapSrc = "TerrainTest/Grass2.jpg", _detailMapSize = 10} local detailMapB = { _detailMapSrc = "TerrainTest/road.jpg", _detailMapSize = 35} local detailMapA = { _detailMapSrc = "TerrainTest/GreenSkin.jpg", _detailMapSize = 20} - local terrainData = { _heightMapSrc = "TerrainTest/heightmap129.jpg", _alphaMapSrc = "TerrainTest/alphamap.png" , _detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4, _mapHeight = 20.0, _mapScale = 1.0, _chunkSize = cc.size(32,32)} + local terrainData = { _heightMapSrc = "TerrainTest/heightmap129.jpg", _alphaMapSrc = "TerrainTest/alphamap.png" , _detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4, _mapHeight = 20.0, _mapScale = 1.0, _chunkSize = ax.size(32,32)} - local terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT) + local terrain = ax.Terrain:create(terrainData,ax.Terrain.CrackFixedType.SKIRT) terrain:setMaxDetailMapAmount(4) terrain:setCameraMask(2) terrain:setDrawWire(false) - + terrain:setSkirtHeightRatio(3) terrain:setLODDistance(64,128,192) - terrain:setCameraMask(cc.CameraFlag.USER1) + terrain:setCameraMask(ax.CameraFlag.USER1) --create terrain local rbDes = {} rbDes.mass = 0.0 local heidata = terrain:getHeightData() local size = terrain:getTerrainSize() - rbDes.shape = cc.Physics3DShape:createHeightfield(size.width, size.height, heidata, 1.0, terrain:getMinHeight(), terrain:getMaxHeight(), true, false, true) - local rigidBody = cc.Physics3DRigidBody:create(rbDes) - local component = cc.Physics3DComponent:create(rigidBody) + rbDes.shape = ax.Physics3DShape:createHeightfield(size.width, size.height, heidata, 1.0, terrain:getMinHeight(), terrain:getMaxHeight(), true, false, true) + local rigidBody = ax.Physics3DRigidBody:create(rbDes) + local component = ax.Physics3DComponent:create(rigidBody) terrain:addComponent(component) self:addChild(terrain) component:syncNodeToPhysics() - component:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.NONE) + component:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.NONE) --create several spheres rbDes.mass = 1.0 - rbDes.shape = cc.Physics3DShape:createSphere(0.5) + rbDes.shape = ax.Physics3DShape:createSphere(0.5) local start_x = START_POS_X - ARRAY_SIZE_X/2 + 5.0 local start_y = START_POS_Y + 20.0 local start_z = START_POS_Z - ARRAY_SIZE_Z/2 @@ -629,64 +629,64 @@ function Physics3DTerrainDemo:extend() local x = 1.0 * (i - 1) + start_x local y = 5.0+1.0 * (k - 1) + start_y local z = 1.0 * (j - 1) + start_z - - local sprite = cc.PhysicsSprite3D:create("MeshRendererTest/sphere.c3b", rbDes) + + local sprite = ax.PhysicsSprite3D:create("MeshRendererTest/sphere.c3b", rbDes) sprite:setTexture("MeshRendererTest/plane.png") - sprite:setCameraMask(cc.CameraFlag.USER1) + sprite:setCameraMask(ax.CameraFlag.USER1) sprite:setScale(1.0 / sprite:getContentSize().width) - sprite:setPosition3D(cc.vec3(x, y, z)) + sprite:setPosition3D(ax.vec3(x, y, z)) self:addChild(sprite) sprite:syncNodeToPhysics() - sprite:setSyncFlag(cc.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) + sprite:setSyncFlag(ax.Physics3DComponent.PhysicsSyncFlag.PHYSICS_TO_NODE) end end end --create mesh - local trianglesList = cc.Bundle3D:getTrianglesList("MeshRendererTest/boss.c3b") - + local trianglesList = ax.Bundle3D:getTrianglesList("MeshRendererTest/boss.c3b") + rbDes.mass = 0.0 - rbDes.shape = cc.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) - local rigidBody = cc.Physics3DRigidBody:create(rbDes) - local component = cc.Physics3DComponent:create(rigidBody) - local sprite = cc.Sprite3D:create("MeshRendererTest/boss.c3b") + rbDes.shape = ax.Physics3DShape:createMesh(trianglesList, math.floor(#trianglesList / 3)) + local rigidBody = ax.Physics3DRigidBody:create(rbDes) + local component = ax.Physics3DComponent:create(rigidBody) + local sprite = ax.Sprite3D:create("MeshRendererTest/boss.c3b") sprite:addComponent(component) - sprite:setRotation3D(cc.vec3(-90.0, 0.0, 0.0)) - sprite:setPosition3D(cc.vec3(0.0, 15.0, 0.0)) + sprite:setRotation3D(ax.vec3(-90.0, 0.0, 0.0)) + sprite:setPosition3D(ax.vec3(0.0, 15.0, 0.0)) sprite:setCameraMask(2) self:addChild(sprite) local shapeList = {} - local bodyshape = cc.Physics3DShape:createBox(cc.vec3(2.0, 4.0, 2.0)) - local localTrans = cc.mat4.createTranslation(0.0, 2.0, 0.0) + local bodyshape = ax.Physics3DShape:createBox(ax.vec3(2.0, 4.0, 2.0)) + local localTrans = ax.mat4.createTranslation(0.0, 2.0, 0.0) table.insert(shapeList, {bodyshape, localTrans}) - local headshape = cc.Physics3DShape:createSphere(1.5) - localTrans = cc.mat4.createTranslation(0.6, 5.0, -1.5) + local headshape = ax.Physics3DShape:createSphere(1.5) + localTrans = ax.mat4.createTranslation(0.6, 5.0, -1.5) table.insert(shapeList, {headshape, localTrans}) - local lhandshape = cc.Physics3DShape:createBox(cc.vec3(1.0, 3.0, 1.0)) - localTrans = cc.mat4.createRotation(cc.vec3(1.0, 0.0, 0.0), 15.0 * math.pi / 180) + local lhandshape = ax.Physics3DShape:createBox(ax.vec3(1.0, 3.0, 1.0)) + localTrans = ax.mat4.createRotation(ax.vec3(1.0, 0.0, 0.0), 15.0 * math.pi / 180) localTrans[13] = -1.5 localTrans[14] = 2.5 localTrans[15] = -2.5 table.insert(shapeList, {lhandshape, localTrans}) - local rhandshape = cc.Physics3DShape:createBox(cc.vec3(1.0, 3.0, 1.0)) - localTrans = cc.mat4.createRotation(cc.vec3(1.0, 0.0, 0.0), -15.0 * math.pi / 180) + local rhandshape = ax.Physics3DShape:createBox(ax.vec3(1.0, 3.0, 1.0)) + localTrans = ax.mat4.createRotation(ax.vec3(1.0, 0.0, 0.0), -15.0 * math.pi / 180) localTrans[13] = 2.0 localTrans[14] = 2.5 localTrans[15] = 1.0 table.insert(shapeList, {rhandshape, localTrans}) rbDes.mass = 10.0 - rbDes.shape = cc.Physics3DShape:createCompoundShape(shapeList) - rigidBody = cc.Physics3DRigidBody:create(rbDes) - component = cc.Physics3DComponent:create(rigidBody) - local sprite = cc.Sprite3D:create("MeshRendererTest/orc.c3b") + rbDes.shape = ax.Physics3DShape:createCompoundShape(shapeList) + rigidBody = ax.Physics3DRigidBody:create(rbDes) + component = ax.Physics3DComponent:create(rigidBody) + local sprite = ax.Sprite3D:create("MeshRendererTest/orc.c3b") sprite:addComponent(component) - sprite:setRotation3D(cc.vec3(0.0, 180.0, 0.0)) - sprite:setPosition3D(cc.vec3(-5.0, 20.0, 0.0)) + sprite:setRotation3D(ax.vec3(0.0, 180.0, 0.0)) + sprite:setPosition3D(ax.vec3(-5.0, 20.0, 0.0)) sprite:setScale(0.4) sprite:setCameraMask(2) self:addChild(sprite) @@ -697,10 +697,10 @@ end function Physics3DTest() Helper.usePhysics = true - - local scene = cc.Scene:createWithPhysics() - Helper.createFunctionTable = + local scene = ax.Scene:createWithPhysics() + + Helper.createFunctionTable = { BasicPhysics3DDemo.create, Physics3DConstraintDemo.create, @@ -714,4 +714,4 @@ function Physics3DTest() scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/PhysicsTest/PhysicsTest.lua b/tests/lua-tests/Content/src/PhysicsTest/PhysicsTest.lua index 16258d48f2b9..a6507d03d253 100644 --- a/tests/lua-tests/Content/src/PhysicsTest/PhysicsTest.lua +++ b/tests/lua-tests/Content/src/PhysicsTest/PhysicsTest.lua @@ -1,7 +1,7 @@ -local size = cc.Director:getInstance():getWinSize() -local MATERIAL_DEFAULT = cc.PhysicsMaterial(0.1, 0.5, 0.5) +local size = ax.Director:getInstance():getWinSize() +local MATERIAL_DEFAULT = ax.PhysicsMaterial(0.1, 0.5, 0.5) local curLayer = nil -local STATIC_COLOR = cc.c4f(1.0, 0.0, 0.0, 1.0) +local STATIC_COLOR = ax.color(1.0, 0.0, 0.0, 1.0) local DRAG_BODYS_TAG = 0x80 local function range(from, to, step) @@ -18,19 +18,19 @@ end local function initWithLayer(layer, callback) curLayer = layer - layer.spriteTexture = cc.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 100):getTexture() + layer.spriteTexture = ax.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 100):getTexture() local debug = false local function toggleDebugCallback(sender) debug = not debug - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setDebugDrawMask(debug and cc.PhysicsWorld.DEBUGDRAW_ALL or cc.PhysicsWorld.DEBUGDRAW_NONE) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setDebugDrawMask(debug and ax.PhysicsWorld.DEBUGDRAW_ALL or ax.PhysicsWorld.DEBUGDRAW_NONE) end layer.toggleDebug = function(self) toggleDebugCallback(nil) end - cc.MenuItemFont:setFontSize(18) - local item = cc.MenuItemFont:create("Toggle debug") + ax.MenuItemFont:setFontSize(18) + local item = ax.MenuItemFont:create("Toggle debug") item:registerScriptTapHandler(toggleDebugCallback) - local menu = cc.Menu:create(item) + local menu = ax.Menu:create(item) layer:addChild(menu) menu:setPosition(size.width - 50, size.height - 10) Helper.initWithLayer(layer) @@ -51,9 +51,9 @@ local function addGrossiniAtPosition(layer, p, scale) posx = (math.floor(posx) % 4) * 85 posy = (math.floor(posy) % 3) * 121 - local sp = cc.Sprite:createWithTexture(layer.spriteTexture, cc.rect(posx, posy, 85, 121)) + local sp = ax.Sprite:createWithTexture(layer.spriteTexture, ax.rect(posx, posy, 85, 121)) sp:setScale(scale) - sp:setPhysicsBody(cc.PhysicsBody:createBox(cc.size(48.0, 108.0))) + sp:setPhysicsBody(ax.PhysicsBody:createBox(ax.size(48.0, 108.0))) layer:addChild(sp) sp:setPosition(p) return sp @@ -61,8 +61,8 @@ end local function onTouchBegan(touch, event) local location = touch:getLocation() - local arr = cc.Director:getInstance():getRunningScene():getPhysicsWorld():getShapes(location) - + local arr = ax.Director:getInstance():getRunningScene():getPhysicsWorld():getShapes(location) + local body for _, obj in ipairs(arr) do if bit.band(obj:getBody():getTag(), DRAG_BODYS_TAG) ~= 0 then @@ -70,22 +70,22 @@ local function onTouchBegan(touch, event) break end end - + if body then - local mouse = cc.Node:create() - local physicsBody = cc.PhysicsBody:create(PHYSICS_INFINITY, PHYSICS_INFINITY) + local mouse = ax.Node:create() + local physicsBody = ax.PhysicsBody:create(PHYSICS_INFINITY, PHYSICS_INFINITY) mouse:setPhysicsBody(physicsBody) physicsBody:setDynamic(false) mouse:setPosition(location) curLayer:addChild(mouse) - local joint = cc.PhysicsJointPin:construct(physicsBody, body, location) + local joint = ax.PhysicsJointPin:instantiate(physicsBody, body, location) joint:setMaxForce(5000.0 * body:getMass()) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():addJoint(joint) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():addJoint(joint) touch.mouse = mouse - + return true end - + return false end @@ -107,14 +107,14 @@ local function makeBall(layer, point, radius, material) local ball if layer.ball then - ball = cc.Sprite:createWithTexture(layer.ball:getTexture()) + ball = ax.Sprite:createWithTexture(layer.ball:getTexture()) else - ball = cc.Sprite:create("Images/ball.png") + ball = ax.Sprite:create("Images/ball.png") end ball:setScale(0.13 * radius) - local body = cc.PhysicsBody:createCircle(ball:getContentSize().width / 2, material) + local body = ax.PhysicsBody:createCircle(ball:getContentSize().width / 2, material) ball:setPhysicsBody(body) ball:setPosition(point) @@ -131,15 +131,15 @@ local function makeBox(point, size, color, material) yellow = color == 1 end - local box = yellow and cc.Sprite:create("Images/YellowSquare.png") or cc.Sprite:create("Images/CyanSquare.png") - + local box = yellow and ax.Sprite:create("Images/YellowSquare.png") or ax.Sprite:create("Images/CyanSquare.png") + box:setScaleX(size.width/100.0) box:setScaleY(size.height/100.0) - - local body = cc.PhysicsBody:createBox(box:getContentSize(), material) + + local body = ax.PhysicsBody:createBox(box:getContentSize(), material) box:setPhysicsBody(body) - box:setPosition(cc.p(point.x, point.y)) - + box:setPosition(ax.p(point.x, point.y)) + return box end @@ -152,8 +152,8 @@ local function makeTriangle(point, size, color, material) else yellow = color == 1 end - local triangle = yellow and cc.Sprite:create("Images/YellowTriangle.png") or cc.Sprite:create("Images/CyanTriangle.png") - + local triangle = yellow and ax.Sprite:create("Images/YellowTriangle.png") or ax.Sprite:create("Images/CyanTriangle.png") + if size.height == 0 then triangle:setScale(size.width/100.0) else @@ -161,36 +161,36 @@ local function makeTriangle(point, size, color, material) triangle:setScaleY(size.height/43.5) end - vers = { cc.p(0, triangle:getContentSize().height/2), - cc.p(triangle:getContentSize().width/2, -triangle:getContentSize().height/2), - cc.p(-triangle:getContentSize().width/2, -triangle:getContentSize().height/2) + vers = { ax.p(0, triangle:getContentSize().height/2), + ax.p(triangle:getContentSize().width/2, -triangle:getContentSize().height/2), + ax.p(-triangle:getContentSize().width/2, -triangle:getContentSize().height/2) } - local body = cc.PhysicsBody:createPolygon(vers, material) + local body = ax.PhysicsBody:createPolygon(vers, material) triangle:setPhysicsBody(body) triangle:setPosition(point) - + return triangle end local function PhysicsDemoClickAdd() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() local function onTouchEnded(touch, event) local location = touch:getLocation() addGrossiniAtPosition(layer, location) end - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(function() return true end, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(function() return true end, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) addGrossiniAtPosition(layer, VisibleRect:center()) - - local node = cc.Node:create() - node:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + + local node = ax.Node:create() + node:setPhysicsBody(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height ) ) @@ -206,7 +206,7 @@ local function PhysicsDemoClickAdd() end local function PhysicsDemoLogoSmash() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() local logo_width = 188.0 @@ -252,286 +252,283 @@ local function PhysicsDemoLogoSmash() return bit.band(bit.rshift(logo_image[bit.rshift(x, 3) + y*logo_raw_length + 1], bit.band(bit.bnot(x), 0x07)), 1) end - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 0)) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setUpdateRate(5.0) - - layer.ball = cc.SpriteBatchNode:create("Images/ball.png", #logo_image) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 0)) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setUpdateRate(1) + + layer.ball = ax.SpriteBatchNode:create("Images/ball.png", #logo_image) layer:addChild(layer.ball) for y in range(0, logo_height-1) do for x in range(0, logo_width-1) do if get_pixel(x, y) == 1 then local x_jitter = 0.05*math.random() local y_jitter = 0.05*math.random() - - local ball = makeBall(layer, - cc.p(2*(x - logo_width/2 + x_jitter) + VisibleRect:getVisibleRect().width/2, + + local ball = makeBall(layer, + ax.p(2*(x - logo_width/2 + x_jitter) + VisibleRect:getVisibleRect().width/2, 2*(logo_height-y + y_jitter) + VisibleRect:getVisibleRect().height/2 - logo_height/2), - 0.95, - cc.PhysicsMaterial(0.01, 0.0, 0.0)) + 0.95, + ax.PhysicsMaterial(0.01, 0.0, 0.0)) local physicsBody = ball:getPhysicsBody() - physicsBody:setMass(1.0) - physicsBody:setMoment(PHYSICS_INFINITY) - layer.ball:addChild(ball) end end end - local bullet = makeBall(layer, cc.p(400, 0), 10, cc.PhysicsMaterial(PHYSICS_INFINITY, 0, 0)) + local bullet = makeBall(layer, ax.p(400, 0), 10, ax.PhysicsMaterial(PHYSICS_INFINITY, 0, 0)) - bullet:getPhysicsBody():setVelocity(cc.p(200, 0)) - bullet:setPosition(cc.p(-500, VisibleRect:getVisibleRect().height/2)) + bullet:getPhysicsBody():setVelocity(ax.p(200, 0)) + bullet:setPosition(ax.p(5, VisibleRect:getVisibleRect().height/2)) layer.ball:addChild(bullet) end initWithLayer(layer, onEnter) Helper.titleLabel:setString("Logo Smash") - + return layer end local function PhysicsDemoJoints() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - + local width = (VisibleRect:getVisibleRect().width - 10) / 4 local height = (VisibleRect:getVisibleRect().height - 50) / 4 - - local node = cc.Node:create() - local box = cc.PhysicsBody:create() + + local node = ax.Node:create() + local box = ax.PhysicsBody:create() node:setPhysicsBody(box) box:setDynamic(false) - node:setPosition(cc.p(0, 0)) + node:setPosition(ax.p(0, 0)) layer:addChild(node) - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() for i in range(0, 3) do for j in range(0, 3) do - local offset = cc.p(VisibleRect:leftBottom().x + 5 + j * width + width/2, + local offset = ax.p(VisibleRect:leftBottom().x + 5 + j * width + width/2, VisibleRect:leftBottom().y + 50 + i * height + height/2) - box:addShape(cc.PhysicsShapeEdgeBox:create(cc.size(width, height), - cc.PHYSICSSHAPE_MATERIAL_DEFAULT, - 1, + box:addCollider(ax.PhysicsColliderEdgeBox:create(ax.size(width, height), + ax.PHYSICSSHAPE_MATERIAL_DEFAULT, + 1, offset) ) local index = i*4 + j if index == 0 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBall(layer, cc.p(offset.x + 30, offset.y), 10) + local sp2 = makeBall(layer, ax.p(offset.x + 30, offset.y), 10) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointPin:construct(sp1PhysicsBody, sp2PhysicsBody, offset) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():addJoint(joint) - + + local joint = ax.PhysicsJointPin:instantiate(sp1PhysicsBody, sp2PhysicsBody, offset) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():addJoint(joint) + layer:addChild(sp1) layer:addChild(sp2) elseif index == 1 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointFixed:construct(sp1PhysicsBody, sp2PhysicsBody, offset) + + local joint = ax.PhysicsJointFixed:instantiate(sp1PhysicsBody, sp2PhysicsBody, offset) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 2 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointDistance:construct(sp1PhysicsBody, - sp2PhysicsBody, - cc.p(0, 0), - cc.p(0, 0)) + + local joint = ax.PhysicsJointDistance:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + ax.p(0, 0), + ax.p(0, 0)) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 3 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointLimit:construct(sp1PhysicsBody, - sp2PhysicsBody, - cc.p(0, 0), - cc.p(0, 0), - 30.0, + + local joint = ax.PhysicsJointLimit:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + ax.p(0, 0), + ax.p(0, 0), + 30.0, 60.0) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 4 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointSpring:construct(sp1PhysicsBody, - sp2PhysicsBody, - cc.p(0, 0), - cc.p(0, 0), - 500.0, + + local joint = ax.PhysicsJointSpring:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + ax.p(0, 0), + ax.p(0, 0), + 500.0, 0.3) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 5 then - local sp1 = makeBall(layer, cc.p(offset.x - 30, offset.y), 10) + local sp1 = makeBall(layer, ax.p(offset.x - 30, offset.y), 10) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - local joint = cc.PhysicsJointGroove:construct(sp1PhysicsBody, - sp2PhysicsBody, - cc.p(30, 15), - cc.p(30, -15), - cc.p(-30, 0)) + + local joint = ax.PhysicsJointGroove:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + ax.p(30, 15), + ax.p(30, -15), + ax.p(-30, 0)) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 6 then - local sp1 = makeBox(cc.p(offset.x - 30, offset.y), cc.size(30, 10)) + local sp1 = makeBox(ax.p(offset.x - 30, offset.y), ax.size(30, 10)) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp1PhysicsBody, - box, - cc.p(sp1:getPosition()))) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp2PhysicsBody, - box, - cc.p(sp2:getPosition()))) - local joint = cc.PhysicsJointRotarySpring:construct(sp1PhysicsBody, - sp2PhysicsBody, - 3000.0, + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp1PhysicsBody, + box, + ax.p(sp1:getPosition()))) + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp2PhysicsBody, + box, + ax.p(sp2:getPosition()))) + local joint = ax.PhysicsJointRotarySpring:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + 3000.0, 60.0) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 7 then - local sp1 = makeBox(cc.p(offset.x - 30, offset.y), cc.size(30, 10)) + local sp1 = makeBox(ax.p(offset.x - 30, offset.y), ax.size(30, 10)) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp1PhysicsBody, - box, - cc.p(sp1:getPosition()))) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp2PhysicsBody, - box, - cc.p(sp2:getPosition()))) - local joint = cc.PhysicsJointRotaryLimit:construct(sp1PhysicsBody, - sp2PhysicsBody, - 0.0, + + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp1PhysicsBody, + box, + ax.p(sp1:getPosition()))) + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp2PhysicsBody, + box, + ax.p(sp2:getPosition()))) + local joint = ax.PhysicsJointRotaryLimit:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + 0.0, math.pi/2) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 8 then - local sp1 = makeBox(cc.p(offset.x - 30, offset.y), cc.size(30, 10)) + local sp1 = makeBox(ax.p(offset.x - 30, offset.y), ax.size(30, 10)) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp1PhysicsBody, - box, - cc.p(sp1:getPosition()))) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp2PhysicsBody, - box, - cc.p(sp2:getPosition()))) - local joint = cc.PhysicsJointRatchet:construct(sp1PhysicsBody, - sp2PhysicsBody, - 0.0, + + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp1PhysicsBody, + box, + ax.p(sp1:getPosition()))) + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp2PhysicsBody, + box, + ax.p(sp2:getPosition()))) + local joint = ax.PhysicsJointRatchet:instantiate(sp1PhysicsBody, + sp2PhysicsBody, + 0.0, math.pi/2) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 9 then - local sp1 = makeBox(cc.p(offset.x - 30, offset.y), cc.size(30, 10)) + local sp1 = makeBox(ax.p(offset.x - 30, offset.y), ax.size(30, 10)) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp1PhysicsBody, - box, - cc.p(sp1:getPosition()))) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp2PhysicsBody, - box, - cc.p(sp2:getPosition()))) - local joint = cc.PhysicsJointGear:construct(sp1PhysicsBody, sp2PhysicsBody, 0.0, 2.0) + + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp1PhysicsBody, + box, + ax.p(sp1:getPosition()))) + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp2PhysicsBody, + box, + ax.p(sp2:getPosition()))) + local joint = ax.PhysicsJointGear:instantiate(sp1PhysicsBody, sp2PhysicsBody, 0.0, 2.0) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) elseif index == 10 then - local sp1 = makeBox(cc.p(offset.x - 30, offset.y), cc.size(30, 10)) + local sp1 = makeBox(ax.p(offset.x - 30, offset.y), ax.size(30, 10)) local sp1PhysicsBody = sp1:getPhysicsBody() sp1PhysicsBody:setTag(DRAG_BODYS_TAG) - local sp2 = makeBox(cc.p(offset.x + 30, offset.y), cc.size(30, 10)) + local sp2 = makeBox(ax.p(offset.x + 30, offset.y), ax.size(30, 10)) local sp2PhysicsBody = sp2:getPhysicsBody() sp2PhysicsBody:setTag(DRAG_BODYS_TAG) - - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp1PhysicsBody, - box, - cc.p(sp1:getPosition()))) - scene:getPhysicsWorld():addJoint(cc.PhysicsJointPin:construct(sp2PhysicsBody, - box, - cc.p(sp2:getPosition()))) - local joint = cc.PhysicsJointMotor:construct(sp1PhysicsBody, sp2PhysicsBody, math.pi/2) + + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp1PhysicsBody, + box, + ax.p(sp1:getPosition()))) + scene:getPhysicsWorld():addJoint(ax.PhysicsJointPin:instantiate(sp2PhysicsBody, + box, + ax.p(sp2:getPosition()))) + local joint = ax.PhysicsJointMotor:instantiate(sp1PhysicsBody, sp2PhysicsBody, math.pi/2) scene:getPhysicsWorld():addJoint(joint) - + layer:addChild(sp1) layer:addChild(sp2) end @@ -545,38 +542,38 @@ local function PhysicsDemoJoints() end local function PhysicsDemoPyramidStack() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - - local node = cc.Node:create() - node:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, - VisibleRect:leftBottom().y + 50), - cc.p(VisibleRect:rightBottom().x, + + local node = ax.Node:create() + node:setPhysicsBody(ax.PhysicsBody:createEdgeSegment(ax.p(VisibleRect:leftBottom().x, + VisibleRect:leftBottom().y + 50), + ax.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))) layer:addChild(node) - - local ball = cc.Sprite:create("Images/ball.png") + + local ball = ax.Sprite:create("Images/ball.png") ball:setScale(1) - ball:setPhysicsBody(cc.PhysicsBody:createCircle(10)) + ball:setPhysicsBody(ax.PhysicsBody:createCircle(10)) ball:getPhysicsBody():setTag(DRAG_BODYS_TAG) - ball:setPosition(cc.p(VisibleRect:bottom().x, VisibleRect:bottom().y + 60)) + ball:setPosition(ax.p(VisibleRect:bottom().x, VisibleRect:bottom().y + 60)) layer:addChild(ball) - ball:runAction(cc.Sequence:create(cc.DelayTime:create(3), - cc.ScaleTo:create(0, 3))) - + ball:runAction(ax.Sequence:create(ax.DelayTime:create(3), + ax.ScaleTo:create(0, 3))) + for i in range(0, 13) do for j in range(0, i) do local x = VisibleRect:bottom().x + (i/2 - j) * 11 local y = VisibleRect:bottom().y + (14 - i) * 23 + 100 - local sp = addGrossiniAtPosition(layer, cc.p(x, y), 0.2) + local sp = addGrossiniAtPosition(layer, ax.p(x, y), 0.2) sp:getPhysicsBody():setTag(DRAG_BODYS_TAG) end end @@ -589,47 +586,47 @@ local function PhysicsDemoPyramidStack() end local function PhysicsDemoRayCast() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() local function onTouchEnded(touch, event) local location = touch:getLocation() - + local r = math.random(3) if r ==1 then layer:addChild(makeBall(layer, location, 5 + math.random()*10)) elseif r == 2 then - layer:addChild(makeBox(location, cc.size(10 + math.random()*15, 10 + math.random()*15))) + layer:addChild(makeBox(location, ax.size(10 + math.random()*15, 10 + math.random()*15))) elseif r == 3 then - layer:addChild(makeTriangle(location, cc.size(10 + math.random()*20, 10 + math.random()*20))) + layer:addChild(makeTriangle(location, ax.size(10 + math.random()*20, 10 + math.random()*20))) end end - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(function() return true end, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(function() return true end, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0,0)) - - local node = cc.DrawNode:create() - node:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, - VisibleRect:leftBottom().y + 50), - cc.p(VisibleRect:rightBottom().x, + + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0,0)) + + local node = ax.DrawNode:create() + node:setPhysicsBody(ax.PhysicsBody:createEdgeSegment(ax.p(VisibleRect:leftBottom().x, + VisibleRect:leftBottom().y + 50), + ax.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))) - node:drawSegment(cc.p(VisibleRect:leftBottom().x, VisibleRect:leftBottom().y + 50), - cc.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50), - 1, + node:drawSegment(ax.p(VisibleRect:leftBottom().x, VisibleRect:leftBottom().y + 50), + ax.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50), + 1, STATIC_COLOR) layer:addChild(node) local mode = 0 - cc.MenuItemFont:setFontSize(18) - local item = cc.MenuItemFont:create("Toggle debugChange Mode(any)") + ax.MenuItemFont:setFontSize(18) + local item = ax.MenuItemFont:create("Toggle debugChange Mode(any)") local function changeModeCallback(sender) mode = (mode + 1) % 3 - + if mode == 0 then item:setString("Change Mode(any)") elseif mode == 1 then @@ -638,39 +635,39 @@ local function PhysicsDemoRayCast() item:setString("Change Mode(multiple)") end end - + item:registerScriptTapHandler(changeModeCallback) - - local menu = cc.Menu:create(item) + + local menu = ax.Menu:create(item) layer:addChild(menu) - menu:setPosition(cc.p(VisibleRect:left().x+100, VisibleRect:top().y-10)) + menu:setPosition(ax.p(VisibleRect:left().x+100, VisibleRect:top().y-10)) local angle = 0 local drawNode = nil local function update(delta) local L = 150.0 local point1 = VisibleRect:center() - local d = cc.p(L * math.cos(angle), L * math.sin(angle)) - local point2 = cc.p(point1.x + d.x, point1.y + d.y) - + local d = ax.p(L * math.cos(angle), L * math.sin(angle)) + local point2 = ax.p(point1.x + d.x, point1.y + d.y) + if drawNode then layer:removeChild(drawNode) end - drawNode = cc.DrawNode:create() + drawNode = ax.DrawNode:create() if mode == 0 then - local point3 = cc.p(point2.x, point2.y) + local point3 = ax.p(point2.x, point2.y) local function func(world, info) point3 = info.contact return false end - cc.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) drawNode:drawSegment(point1, point3, 1, STATIC_COLOR) - + if point2.x ~= point3.x or point2.y ~= point3.y then - drawNode:drawDot(point3, 2, cc.c4f(1.0, 1.0, 1.0, 1.0)) + drawNode:drawDot(point3, 2, ax.color(1.0, 1.0, 1.0, 1.0)) end layer:addChild(drawNode) elseif mode == 1 then - local point3 = cc.p(point2.x, point2.y) + local point3 = ax.p(point2.x, point2.y) local friction = 1.0 local function func(world, info) if friction > info.fraction then @@ -679,32 +676,32 @@ local function PhysicsDemoRayCast() end return true end - - cc.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) + + ax.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) drawNode:drawSegment(point1, point3, 1, STATIC_COLOR) - + if point2.x ~= point3.x or point2.y ~= point3.y then - drawNode:drawDot(point3, 2, cc.c4f(1.0, 1.0, 1.0, 1.0)) + drawNode:drawDot(point3, 2, ax.color(1.0, 1.0, 1.0, 1.0)) end layer:addChild(drawNode) elseif mode == 2 then local points = {} - + local function func(world, info) points[#points + 1] = info.contact return true end - - cc.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) + + ax.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(func, point1, point2) drawNode:drawSegment(point1, point2, 1, STATIC_COLOR) - + for _, p in ipairs(points) do - drawNode:drawDot(p, 2, cc.c4f(1.0, 1.0, 1.0, 1.0)) + drawNode:drawDot(p, 2, ax.color(1.0, 1.0, 1.0, 1.0)) end - + layer:addChild(drawNode) end - + angle = angle + 0.25 * math.pi / 180.0 end @@ -719,42 +716,41 @@ local function PhysicsDemoRayCast() end local function PhysicsDemoOneWayPlatform() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - local ground = cc.Node:create() - ground:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, - VisibleRect:leftBottom().y + 50), - cc.p(VisibleRect:rightBottom().x, + local ground = ax.Node:create() + ground:setPhysicsBody(ax.PhysicsBody:createEdgeSegment(ax.p(VisibleRect:leftBottom().x, + VisibleRect:leftBottom().y + 50), + ax.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))) layer:addChild(ground) - - local platform = makeBox(VisibleRect:center(), cc.size(200, 50)) + + local platform = makeBox(VisibleRect:center(), ax.size(200, 50)) local platformPhysicsBody = platform:getPhysicsBody() platformPhysicsBody:setDynamic(false) platformPhysicsBody:setContactTestBitmask(0xFFFFFFFF) layer:addChild(platform) - - local ball = makeBall(layer, cc.p(VisibleRect:center().x, VisibleRect:center().y - 50), 20) + + local ball = makeBall(layer, ax.p(VisibleRect:center().x, VisibleRect:center().y - 50), 20) local ballPhysicsBody = ball:getPhysicsBody() - ballPhysicsBody:setVelocity(cc.p(0, 150)) + ballPhysicsBody:setVelocity(ax.p(0, 150)) ballPhysicsBody:setTag(DRAG_BODYS_TAG) - ballPhysicsBody:setMass(1.0) ballPhysicsBody:setContactTestBitmask(0xFFFFFFFF) layer:addChild(ball) local function onContactBegin(contact) return contact:getContactData().normal.y < 0 end - local contactListener = cc.EventListenerPhysicsContactWithBodies:create(platformPhysicsBody, ballPhysicsBody) - contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN) + local contactListener = ax.EventListenerPhysicsContactWithBodies:create(platformPhysicsBody, ballPhysicsBody) + contactListener:registerScriptHandler(onContactBegin, ax.Handler.EVENT_PHYSICS_CONTACT_BEGIN) eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, layer) end @@ -765,39 +761,39 @@ local function PhysicsDemoOneWayPlatform() end local function PhysicsDemoActions() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - - local node = cc.Node:create() - node:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + + local node = ax.Node:create() + node:setPhysicsBody(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height))) node:setPosition(VisibleRect:center()) layer:addChild(node) - + local sp1 = addGrossiniAtPosition(layer, VisibleRect:center()) - local sp2 = addGrossiniAtPosition(layer, cc.p(VisibleRect:left().x + 50, VisibleRect:left().y)) - local sp3 = addGrossiniAtPosition(layer, cc.p(VisibleRect:right().x - 20, VisibleRect:right().y)) - local sp4 = addGrossiniAtPosition(layer, cc.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-50)) + local sp2 = addGrossiniAtPosition(layer, ax.p(VisibleRect:left().x + 50, VisibleRect:left().y)) + local sp3 = addGrossiniAtPosition(layer, ax.p(VisibleRect:right().x - 20, VisibleRect:right().y)) + local sp4 = addGrossiniAtPosition(layer, ax.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-50)) sp4:getPhysicsBody():setGravityEnable(false) - - - local actionTo = cc.JumpTo:create(2, cc.p(100,100), 50, 4) - local actionBy = cc.JumpBy:create(2, cc.p(300,0), 50, 4) - local actionUp = cc.JumpBy:create(2, cc.p(0,50), 80, 4) + + + local actionTo = ax.JumpTo:create(2, ax.p(100,100), 50, 4) + local actionBy = ax.JumpBy:create(2, ax.p(300,0), 50, 4) + local actionUp = ax.JumpBy:create(2, ax.p(0,50), 80, 4) local actionByBack = actionBy:reverse() - local rotateBy = cc.RotateBy:create(2, 180) - local rotateByBack = cc.RotateBy:create(2, -180) - - sp1:runAction(cc.RepeatForever:create(actionUp)) - sp2:runAction(cc.RepeatForever:create(cc.Sequence:create(actionBy, actionByBack))) + local rotateBy = ax.RotateBy:create(2, 180) + local rotateByBack = ax.RotateBy:create(2, -180) + + sp1:runAction(ax.RepeatForever:create(actionUp)) + sp2:runAction(ax.RepeatForever:create(ax.Sequence:create(actionBy, actionByBack))) sp3:runAction(actionTo) - sp4:runAction(cc.RepeatForever:create(cc.Sequence:create(rotateBy, rotateByBack))) + sp4:runAction(ax.RepeatForever:create(ax.Sequence:create(rotateBy, rotateByBack))) end initWithLayer(layer, onEnter) @@ -807,7 +803,7 @@ local function PhysicsDemoActions() end local function PhysicsDemoPump() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() @@ -828,173 +824,171 @@ local function PhysicsDemoPump() onTouchEnded(touch, event) distance = 0 end - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBeganEx, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMovedEx, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEndedEx, cc.Handler.EVENT_TOUCH_ENDED) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBeganEx, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMovedEx, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEndedEx, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - + local function update() - for _, body in ipairs(cc.Director:getInstance():getRunningScene():getPhysicsWorld():getAllBodies()) do + for _, body in ipairs(ax.Director:getInstance():getRunningScene():getPhysicsWorld():getAllBodies()) do if body:getTag() == DRAG_BODYS_TAG and body:getPosition().y < 0.0 then - body:getNode():setPosition(cc.p(VisibleRect:leftTop().x + 75, + body:getNode():setPosition(ax.p(VisibleRect:leftTop().x + 75, VisibleRect:leftTop().y + math.random() * 90)) - body:setVelocity(cc.p(0, 0)) + body:setVelocity(ax.p(0, 0)) end end - - local gear = cc.Director:getInstance():getRunningScene():getPhysicsWorld():getBody(1) + + local gear = ax.Director:getInstance():getRunningScene():getPhysicsWorld():getBody(1) if gear then if distance ~= 0.0 then rotationV = rotationV + distance/2500.0 end if rotationV > 30 then rotationV = 30.0 end if rotationV < -30 then rotationV = -30.0 end - + gear:setAngularVelocity(rotationV) rotationV = rotationV * 0.995 end end layer:scheduleUpdateWithPriorityLua(update, 0) - - local node = cc.Node:create() - local body = cc.PhysicsBody:create() + + local node = ax.Node:create() + local body = ax.PhysicsBody:create() body:setDynamic(false) - - local staticMaterial = cc.PhysicsMaterial(cc.PHYSICS_INFINITY, 0, 0.5) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 50, - VisibleRect:leftTop().y), - cc.p(VisibleRect:leftTop().x + 50, + + local staticMaterial = ax.PhysicsMaterial(ax.PHYSICS_INFINITY, 0, 0.5) + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 50, + VisibleRect:leftTop().y), + ax.p(VisibleRect:leftTop().x + 50, VisibleRect:leftTop().y-130), - staticMaterial, + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 190, - VisibleRect:leftTop().y), - cc.p(VisibleRect:leftTop().x + 100, - VisibleRect:leftTop().y-50), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 190, + VisibleRect:leftTop().y), + ax.p(VisibleRect:leftTop().x + 100, + VisibleRect:leftTop().y-50), + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 100, - VisibleRect:leftTop().y-50), - cc.p(VisibleRect:leftTop().x + 100, - VisibleRect:leftTop().y-90), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 100, + VisibleRect:leftTop().y-50), + ax.p(VisibleRect:leftTop().x + 100, + VisibleRect:leftTop().y-90), + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 50, - VisibleRect:leftTop().y-130), - cc.p(VisibleRect:leftTop().x + 100, - VisibleRect:leftTop().y-145), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 50, + VisibleRect:leftTop().y-130), + ax.p(VisibleRect:leftTop().x + 100, + VisibleRect:leftTop().y-145), + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 100, - VisibleRect:leftTop().y-145), - cc.p(VisibleRect:leftBottom().x + 100, - VisibleRect:leftBottom().y + 80), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 100, + VisibleRect:leftTop().y-145), + ax.p(VisibleRect:leftBottom().x + 100, + VisibleRect:leftBottom().y + 80), + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 150, - VisibleRect:leftTop().y-80), - cc.p(VisibleRect:leftBottom().x + 150, - VisibleRect:leftBottom().y + 80), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 150, + VisibleRect:leftTop().y-80), + ax.p(VisibleRect:leftBottom().x + 150, + VisibleRect:leftBottom().y + 80), + staticMaterial, 2.0)) - body:addShape(cc.PhysicsShapeEdgeSegment:create(cc.p(VisibleRect:leftTop().x + 150, - VisibleRect:leftTop().y-80), - cc.p(VisibleRect:rightTop().x -100, - VisibleRect:rightTop().y-150), - staticMaterial, + body:addShape(ax.PhysicsColliderEdgeSegment:create(ax.p(VisibleRect:leftTop().x + 150, + VisibleRect:leftTop().y-80), + ax.p(VisibleRect:rightTop().x -100, + VisibleRect:rightTop().y-150), + staticMaterial, 2.0)) - + body:setCategoryBitmask(1) - + for _ in range(1, 6) do - local ball = makeBall(layer, - cc.p(VisibleRect:leftTop().x + 75 + math.random() * 90, - VisibleRect:leftTop().y), - 22, - cc.PhysicsMaterial(0.05, 0.0, 0.1)) + local ball = makeBall(layer, + ax.p(VisibleRect:leftTop().x + 75 + math.random() * 90, + VisibleRect:leftTop().y), + 22, + ax.PhysicsMaterial(0.05, 0.0, 0.1)) ball:getPhysicsBody():setTag(DRAG_BODYS_TAG) layer:addChild(ball) end - + node:setPhysicsBody(body) layer:addChild(node) - + local vec = { - cc.p(VisibleRect:leftTop().x + 102, VisibleRect:leftTop().y-148), - cc.p(VisibleRect:leftTop().x + 148, VisibleRect:leftTop().y-161), - cc.p(VisibleRect:leftBottom().x + 148, VisibleRect:leftBottom().y + 20), - cc.p(VisibleRect:leftBottom().x + 102, VisibleRect:leftBottom().y + 20) + ax.p(VisibleRect:leftTop().x + 102, VisibleRect:leftTop().y-148), + ax.p(VisibleRect:leftTop().x + 148, VisibleRect:leftTop().y-161), + ax.p(VisibleRect:leftBottom().x + 148, VisibleRect:leftBottom().y + 20), + ax.p(VisibleRect:leftBottom().x + 102, VisibleRect:leftBottom().y + 20) } - - local world = cc.Director:getInstance():getRunningScene():getPhysicsWorld() - + + local world = ax.Director:getInstance():getRunningScene():getPhysicsWorld() + -- small gear - local sgear = cc.Node:create() - local sgearB = cc.PhysicsBody:createCircle(44) + local sgear = ax.Node:create() + local sgearB = ax.PhysicsBody:createCircle(44) sgear:setPhysicsBody(sgearB) - sgear:setPosition(cc.p(VisibleRect:leftBottom().x + 125, VisibleRect:leftBottom().y)) + sgear:setPosition(ax.p(VisibleRect:leftBottom().x + 125, VisibleRect:leftBottom().y)) layer:addChild(sgear) sgearB:setCategoryBitmask(4) sgearB:setCollisionBitmask(4) sgearB:setTag(1) - world:addJoint(cc.PhysicsJointPin:construct(body, sgearB, cc.p(sgear:getPosition()))) - - + world:addJoint(ax.PhysicsJointPin:instantiate(body, sgearB, ax.p(sgear:getPosition()))) + + -- big gear - local bgear = cc.Node:create() - local bgearB = cc.PhysicsBody:createCircle(100) + local bgear = ax.Node:create() + local bgearB = ax.PhysicsBody:createCircle(100) bgear:setPhysicsBody(bgearB) - bgear:setPosition(cc.p(VisibleRect:leftBottom().x + 275, VisibleRect:leftBottom().y)) + bgear:setPosition(ax.p(VisibleRect:leftBottom().x + 275, VisibleRect:leftBottom().y)) layer:addChild(bgear) bgearB:setCategoryBitmask(4) - world:addJoint(cc.PhysicsJointPin:construct(body, bgearB, cc.p(bgear:getPosition()))) - - + world:addJoint(ax.PhysicsJointPin:instantiate(body, bgearB, ax.p(bgear:getPosition()))) + + -- pump - local pump = cc.Node:create() - local center = cc.PhysicsShape:getPolygonCenter(vec) + local pump = ax.Node:create() + local center = ax.PhysicsCollider:getPolygonCenter(vec) pump:setPosition(center) - local pumpB = cc.PhysicsBody:createPolygon(vec, - cc.PHYSICSBODY_MATERIAL_DEFAULT, - cc.p(-center.x, -center.y)) + local pumpB = ax.PhysicsBody:createPolygon(vec, + ax.PHYSICSBODY_MATERIAL_DEFAULT, + ax.p(-center.x, -center.y)) pump:setPhysicsBody(pumpB) layer:addChild(pump) pumpB:setCategoryBitmask(2) pumpB:setGravityEnable(false) - world:addJoint(cc.PhysicsJointDistance:construct(pumpB, sgearB, cc.p(0, 0), cc.p(0, -44))) - + world:addJoint(ax.PhysicsJointDistance:instantiate(pumpB, sgearB, ax.p(0, 0), ax.p(0, -44))) + -- plugger - local seg = {cc.p(VisibleRect:leftTop().x + 75, VisibleRect:leftTop().y-120), - cc.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y-100)} - local segCenter = cc.p((seg[2].x + seg[1].x)/2, (seg[2].y + seg[1].y)/2) - seg[2] = cc.p(seg[2].x - segCenter.x, seg[2].y - segCenter.y) - seg[1] = cc.p(seg[1].x - segCenter.x, seg[1].y - segCenter.y) - local plugger = cc.Node:create() - local pluggerB = cc.PhysicsBody:createEdgeSegment(seg[1], - seg[2], - cc.PhysicsMaterial(0.01, 0.0, 0.5), + local seg = {ax.p(VisibleRect:leftTop().x + 75, VisibleRect:leftTop().y-120), + ax.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y-100)} + local segCenter = ax.p((seg[2].x + seg[1].x)/2, (seg[2].y + seg[1].y)/2) + seg[2] = ax.p(seg[2].x - segCenter.x, seg[2].y - segCenter.y) + seg[1] = ax.p(seg[1].x - segCenter.x, seg[1].y - segCenter.y) + local plugger = ax.Node:create() + local pluggerB = ax.PhysicsBody:createEdgeSegment(seg[1], + seg[2], + ax.PhysicsMaterial(0.01, 0.0, 0.5), 20) pluggerB:setDynamic(true) - pluggerB:setMass(30) - pluggerB:setMoment(100000) plugger:setPhysicsBody(pluggerB) plugger:setPosition(segCenter) layer:addChild(plugger) pluggerB:setCategoryBitmask(2) sgearB:setCollisionBitmask(5) - world:addJoint(cc.PhysicsJointPin:construct(body, - pluggerB, - cc.p(VisibleRect:leftBottom().x + 75, + world:addJoint(ax.PhysicsJointPin:instantiate(body, + pluggerB, + ax.p(VisibleRect:leftBottom().x + 75, VisibleRect:leftBottom().y-90))) - world:addJoint(cc.PhysicsJointDistance:construct(pluggerB, - sgearB, - pluggerB:world2Local(cc.p(0,0)), - cc.p(44, 0))) + world:addJoint(ax.PhysicsJointDistance:instantiate(pluggerB, + sgearB, + pluggerB:world2Local(ax.p(0,0)), + ax.p(44, 0))) end initWithLayer(layer, onEnter) @@ -1005,7 +999,7 @@ local function PhysicsDemoPump() end local function PhysicsDemoSlice() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() local sliceTag = 1 @@ -1014,31 +1008,31 @@ local function PhysicsDemoSlice() local body = shape:getBody() local count = shape:getPointsCount() local points = {} - + local j = count - 1 for i in range(0, count-1) do local a = body:local2World(shape:getPoint(j)) - local aDist = cc.pDot(a, normal) - distance - + local aDist = ax.pDot(a, normal) - distance + if aDist < 0.0 then points[#points + 1] = a end - + local b = body:local2World(shape:getPoint(i)) - local bDist = cc.pDot(b, normal) - distance - + local bDist = ax.pDot(b, normal) - distance + if aDist*bDist < 0.0 then local t = math.abs(aDist)/(math.abs(aDist) + math.abs(bDist)) - points[#points + 1] = cc.pLerp(a, b, t) + points[#points + 1] = ax.pLerp(a, b, t) end j = i end - - local center = cc.PhysicsShape:getPolygonCenter(points) - local node = cc.Node:create() - local polygon = cc.PhysicsBody:createPolygon(points, - cc.PHYSICSBODY_MATERIAL_DEFAULT, - cc.p(-center.x, -center.y)) + + local center = ax.PhysicsCollider:getPolygonCenter(points) + local node = ax.Node:create() + local polygon = ax.PhysicsBody:createPolygon(points, + ax.PHYSICSBODY_MATERIAL_DEFAULT, + ax.p(-center.x, -center.y)) node:setPosition(center) node:setPhysicsBody(polygon) polygon:setVelocity(body:getVelocityAtWorldPoint(center)) @@ -1052,47 +1046,47 @@ local function PhysicsDemoSlice() if info.shape:getBody().tag ~= sliceTag then return true end - + if not info.shape:containsPoint(info.start) and not info.shape:containsPoint(info.ended) then - local normal = cc.p(info.ended.x - info.start.x, info.ended.y - info.start.y) - normal = cc.pNormalize(cc.pPerp(normal)) - local dist = cc.pDot(info.start, normal) - + local normal = ax.p(info.ended.x - info.start.x, info.ended.y - info.start.y) + normal = ax.pNormalize(ax.pPerp(normal)) + local dist = ax.pDot(info.start, normal) + clipPoly(info.shape, normal, dist) - clipPoly(info.shape, cc.p(-normal.x, -normal.y), -dist) - + clipPoly(info.shape, ax.p(-normal.x, -normal.y), -dist) + info.shape:getBody():removeFromWorld() end return true end local function onTouchEnded(touch, event) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(slice, - touch:getStartLocation(), + ax.Director:getInstance():getRunningScene():getPhysicsWorld():rayCast(slice, + touch:getStartLocation(), touch:getLocation()) end - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(function() return true end, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(function() return true end, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - - local ground = cc.Node:create() - ground:setPhysicsBody(cc.PhysicsBody:createEdgeSegment(cc.p(VisibleRect:leftBottom().x, - VisibleRect:leftBottom().y + 50), - cc.p(VisibleRect:rightBottom().x, + + local ground = ax.Node:create() + ground:setPhysicsBody(ax.PhysicsBody:createEdgeSegment(ax.p(VisibleRect:leftBottom().x, + VisibleRect:leftBottom().y + 50), + ax.p(VisibleRect:rightBottom().x, VisibleRect:rightBottom().y + 50))) layer:addChild(ground) - - local box = cc.Node:create() - local points = {cc.p(-100, -100), cc.p(-100, 100), cc.p(100, 100), cc.p(100, -100)} - box:setPhysicsBody(cc.PhysicsBody:createPolygon(points)) + + local box = ax.Node:create() + local points = {ax.p(-100, -100), ax.p(-100, 100), ax.p(100, 100), ax.p(100, -100)} + box:setPhysicsBody(ax.PhysicsBody:createPolygon(points)) box:setPosition(VisibleRect:center()) box:getPhysicsBody().tag = sliceTag layer:addChild(box) end - + initWithLayer(layer, onEnter) Helper.titleLabel:setString("Slice") Helper.subtitleLabel:setString("click and drag to slice up the block") @@ -1102,23 +1096,23 @@ end local function PhysicsDemoBug3988() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 0)) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 0)) - local ball = cc.Sprite:create("Images/YellowSquare.png") - ball:setPosition(cc.p(VisibleRect:center().x-100, VisibleRect:center().y)) + local ball = ax.Sprite:create("Images/YellowSquare.png") + ball:setPosition(ax.p(VisibleRect:center().x-100, VisibleRect:center().y)) ball:setRotation(30.0) layer:addChild(ball) - local physicsBall = makeBox(cc.p(VisibleRect:center().x+100, - VisibleRect:center().y), - cc.size(100, 100)) + local physicsBall = makeBox(ax.p(VisibleRect:center().x+100, + VisibleRect:center().y), + ax.size(100, 100)) physicsBall:setRotation(30.0) layer:addChild(physicsBall) end - + initWithLayer(layer, onEnter) Helper.titleLabel:setString("Bug3988") Helper.subtitleLabel:setString("All the Rectangles should have same rotation angle") @@ -1127,11 +1121,11 @@ local function PhysicsDemoBug3988() end local function PhysicsContactTest() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 0)) - local s = cc.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) - + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 0)) + local s = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) + layer.yellowBoxNum = 50 layer.blueBoxNum = 50 layer.yellowTriangleNum = 50 @@ -1141,64 +1135,64 @@ local function PhysicsContactTest() local a = contact:getShapeA():getBody() local b = contact:getShapeB():getBody() local body = (a:getCategoryBitmask() == 4 or a:getCategoryBitmask() == 8) and a or b - + assert(body:getCategoryBitmask() == 4 or body:getCategoryBitmask() == 8, "physics contact fail") - + return true end - + local function resetTest() layer:removeChildByTag(10) - local root = cc.Node:create() + local root = ax.Node:create() root:setTag(10) layer:addChild(root) - - local s = cc.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) + + local s = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) local subtitleLabelPosX, subtitleLabelPosY = Helper.subtitleLabel:getPosition() local restartTestItemPosX, restartTestItemPosY = Helper.restartTestItem:getPosition() local prevMenuPos = subtitleLabelPosY - Helper.subtitleLabel:getContentSize().height; local menuStep = (subtitleLabelPosY -restartTestItemPosY) * 0.25; - local label = cc.Label:createWithTTF(tostring(layer.yellowBoxNum), s_arialPath, 32) + local label = ax.Label:createWithTTF(tostring(layer.yellowBoxNum), s_arialPath, 32) root:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, prevMenuPos)) - + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, prevMenuPos)) + prevMenuPos = prevMenuPos - menuStep - label = cc.Label:createWithTTF(tostring(layer.blueBoxNum), s_arialPath, 32) + label = ax.Label:createWithTTF(tostring(layer.blueBoxNum), s_arialPath, 32) root:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, prevMenuPos)) - + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, prevMenuPos)) + prevMenuPos = prevMenuPos - menuStep - label = cc.Label:createWithTTF(tostring(layer.yellowTriangleNum), s_arialPath, 32) + label = ax.Label:createWithTTF(tostring(layer.yellowTriangleNum), s_arialPath, 32) root:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, prevMenuPos)) - + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, prevMenuPos)) + prevMenuPos = prevMenuPos - menuStep - label = cc.Label:createWithTTF(tostring(layer.blueTriangleNum), s_arialPath, 32) + label = ax.Label:createWithTTF(tostring(layer.blueTriangleNum), s_arialPath, 32) root:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2, prevMenuPos)) - - local wall = cc.Node:create() - wall:setPhysicsBody(cc.PhysicsBody:createEdgeBox(s, cc.PhysicsMaterial(0.1, 1, 0.0))) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2, prevMenuPos)) + + local wall = ax.Node:create() + wall:setPhysicsBody(ax.PhysicsBody:createEdgeBox(s, ax.PhysicsMaterial(0.1, 1, 0.0))) wall:setPosition(VisibleRect:center()) root:addChild(wall) - + -- yellow box, will collide with itself and blue box. for i = 1, layer.yellowBoxNum do - local size = cc.size(10 + math.random()*10, 10 + math.random()*10) - local winSize = cc.size(VisibleRect:getVisibleRect().width, + local size = ax.size(10 + math.random()*10, 10 + math.random()*10) + local winSize = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) - local position = cc.p(winSize.width - size.width, winSize.height - size.height) + local position = ax.p(winSize.width - size.width, winSize.height - size.height) position.x = position.x * math.random() position.y = position.y * math.random() - position = cc.p(VisibleRect:leftBottom().x + position.x + size.width/2, + position = ax.p(VisibleRect:leftBottom().x + position.x + size.width/2, VisibleRect:leftBottom().y + position.y + size.height/2) - local velocity = cc.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) - local box = makeBox(position, size, 1, cc.PhysicsMaterial(0.1, 1, 0.0)) + local velocity = ax.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) + local box = makeBox(position, size, 1, ax.PhysicsMaterial(0.1, 1, 0.0)) local boxPhysicsBody = box:getPhysicsBody() boxPhysicsBody:setVelocity(velocity) boxPhysicsBody:setCategoryBitmask(1) -- 0001 @@ -1206,18 +1200,18 @@ local function PhysicsContactTest() boxPhysicsBody:setCollisionBitmask(3) -- 0011 root:addChild(box) end - + -- blue box, will collide with blue box. for i = 1, layer.blueBoxNum do - local size = cc.size(10 + math.random()*10, 10 + math.random()*10) - local winSize = cc.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) - local position = cc.p(winSize.width - size.width, winSize.height - size.height) + local size = ax.size(10 + math.random()*10, 10 + math.random()*10) + local winSize = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) + local position = ax.p(winSize.width - size.width, winSize.height - size.height) position.x = position.x * math.random() position.y = position.y * math.random() - position = cc.p(VisibleRect:leftBottom().x + position.x + size.width/2, + position = ax.p(VisibleRect:leftBottom().x + position.x + size.width/2, VisibleRect:leftBottom().y + position.y + size.height/2) - local velocity = cc.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) - local box = makeBox(position, size, 2, cc.PhysicsMaterial(0.1, 1, 0.0)) + local velocity = ax.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) + local box = makeBox(position, size, 2, ax.PhysicsMaterial(0.1, 1, 0.0)) local boxPhysicsBody = box:getPhysicsBody() boxPhysicsBody:setVelocity(velocity) boxPhysicsBody:setCategoryBitmask(2) -- 0010 @@ -1225,19 +1219,19 @@ local function PhysicsContactTest() boxPhysicsBody:setCollisionBitmask(1) -- 0001 root:addChild(box) end - + -- yellow triangle, will collide with itself and blue box. for i = 1, layer.yellowTriangleNum do - local size = cc.size(10 + math.random()*10, 10 + math.random()*10) - local winSize = cc.size(VisibleRect:getVisibleRect().width, + local size = ax.size(10 + math.random()*10, 10 + math.random()*10) + local winSize = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) - local position = cc.p(winSize.width - size.width, winSize.height - size.height) + local position = ax.p(winSize.width - size.width, winSize.height - size.height) position.x = position.x * math.random() position.y = position.y * math.random() - position = cc.p(VisibleRect:leftBottom().x + position.x + size.width/2, + position = ax.p(VisibleRect:leftBottom().x + position.x + size.width/2, VisibleRect:leftBottom().y + position.y + size.height/2) - local velocity = cc.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) - local triangle = makeTriangle(position, size, 1, cc.PhysicsMaterial(0.1, 1, 0.0)) + local velocity = ax.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) + local triangle = makeTriangle(position, size, 1, ax.PhysicsMaterial(0.1, 1, 0.0)) local trianglePhysicsBody = triangle:getPhysicsBody() trianglePhysicsBody:setVelocity(velocity) trianglePhysicsBody:setCategoryBitmask(4) -- 0100 @@ -1245,19 +1239,19 @@ local function PhysicsContactTest() trianglePhysicsBody:setCollisionBitmask(6) -- 0110 root:addChild(triangle) end - + -- blue triangle, will collide with yellow box. for i = 1, layer.blueTriangleNum do - local size = cc.size(10 + math.random()*10, 10 + math.random()*10) - local winSize = cc.size(VisibleRect:getVisibleRect().width, + local size = ax.size(10 + math.random()*10, 10 + math.random()*10) + local winSize = ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height) - local position = cc.p(winSize.width - size.width, winSize.height - size.height) + local position = ax.p(winSize.width - size.width, winSize.height - size.height) position.x = position.x * math.random() position.y = position.y * math.random() - position = cc.p(VisibleRect:leftBottom().x + position.x + size.width/2, + position = ax.p(VisibleRect:leftBottom().x + position.x + size.width/2, VisibleRect:leftBottom().y + position.y + size.height/2) - local velocity = cc.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) - local triangle = makeTriangle(position, size, 2, cc.PhysicsMaterial(0.1, 1, 0.0)) + local velocity = ax.p((math.random() - 0.5)*200, (math.random() - 0.5)*200) + local triangle = makeTriangle(position, size, 2, ax.PhysicsMaterial(0.1, 1, 0.0)) local trianglePhysicsBody = triangle:getPhysicsBody() trianglePhysicsBody:setVelocity(velocity) trianglePhysicsBody:setCategoryBitmask(8) -- 1000 @@ -1300,95 +1294,95 @@ local function PhysicsContactTest() local prevMenuPos = subtitleLabelPosY - Helper.subtitleLabel:getContentSize().height; local menuStep = (subtitleLabelPosY -restartTestItemPosY) * 0.25; - cc.MenuItemFont:setFontSize(30) - local decrease1 = cc.MenuItemFont:create(" - ") - decrease1:setColor(cc.c3b(0,200,20)) - local increase1 = cc.MenuItemFont:create(" + ") - increase1:setColor(cc.c3b(0,200,20)) + ax.MenuItemFont:setFontSize(30) + local decrease1 = ax.MenuItemFont:create(" - ") + decrease1:setColor(ax.color32(0,200,20)) + local increase1 = ax.MenuItemFont:create(" + ") + increase1:setColor(ax.color32(0,200,20)) decrease1:setTag(1) increase1:setTag(1) decrease1:registerScriptTapHandler(onDecrease) increase1:registerScriptTapHandler(onIncrease) - - local menu1 = cc.Menu:create(decrease1, increase1) + + local menu1 = ax.Menu:create(decrease1, increase1) menu1:alignItemsHorizontally() - menu1:setPosition(cc.p(s.width/2, prevMenuPos)) + menu1:setPosition(ax.p(s.width/2, prevMenuPos)) layer:addChild(menu1, 1) - - local label = cc.Label:createWithTTF("yellow box", s_arialPath, 32) + + local label = ax.Label:createWithTTF("yellow box", s_arialPath, 32) layer:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2 - 150, prevMenuPos)) - - local decrease2 = cc.MenuItemFont:create(" - ") - decrease2:setColor(cc.c3b(0,200,20)) - local increase2 = cc.MenuItemFont:create(" + ") - increase2:setColor(cc.c3b(0,200,20)) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2 - 150, prevMenuPos)) + + local decrease2 = ax.MenuItemFont:create(" - ") + decrease2:setColor(ax.color32(0,200,20)) + local increase2 = ax.MenuItemFont:create(" + ") + increase2:setColor(ax.color32(0,200,20)) decrease2:setTag(2) increase2:setTag(2) decrease2:registerScriptTapHandler(onDecrease) increase2:registerScriptTapHandler(onIncrease) - + prevMenuPos = prevMenuPos - menuStep - local menu2 = cc.Menu:create(decrease2, increase2) + local menu2 = ax.Menu:create(decrease2, increase2) menu2:alignItemsHorizontally() - menu2:setPosition(cc.p(s.width/2, prevMenuPos)) + menu2:setPosition(ax.p(s.width/2, prevMenuPos)) layer:addChild(menu2, 1) - - label = cc.Label:createWithTTF("blue box", s_arialPath, 32) + + label = ax.Label:createWithTTF("blue box", s_arialPath, 32) layer:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2 - 150, prevMenuPos)) - - local decrease3 = cc.MenuItemFont:create(" - ") - decrease3:setColor(cc.c3b(0,200,20)) - local increase3 = cc.MenuItemFont:create(" + ") - increase3:setColor(cc.c3b(0,200,20)) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2 - 150, prevMenuPos)) + + local decrease3 = ax.MenuItemFont:create(" - ") + decrease3:setColor(ax.color32(0,200,20)) + local increase3 = ax.MenuItemFont:create(" + ") + increase3:setColor(ax.color32(0,200,20)) decrease3:setTag(3) increase3:setTag(3) decrease3:registerScriptTapHandler(onDecrease) increase3:registerScriptTapHandler(onIncrease) - + prevMenuPos = prevMenuPos - menuStep - local menu3 = cc.Menu:create(decrease3, increase3) + local menu3 = ax.Menu:create(decrease3, increase3) menu3:alignItemsHorizontally() - menu3:setPosition(cc.p(s.width/2, prevMenuPos)) + menu3:setPosition(ax.p(s.width/2, prevMenuPos)) layer:addChild(menu3, 1) - - label = cc.Label:createWithTTF("yellow triangle", s_arialPath, 32) + + label = ax.Label:createWithTTF("yellow triangle", s_arialPath, 32) layer:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2 - 150, prevMenuPos)) - - local decrease4 = cc.MenuItemFont:create(" - ") - decrease4:setColor(cc.c3b(0,200,20)) - local increase4 = cc.MenuItemFont:create(" + ") - increase4:setColor(cc.c3b(0,200,20)) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2 - 150, prevMenuPos)) + + local decrease4 = ax.MenuItemFont:create(" - ") + decrease4:setColor(ax.color32(0,200,20)) + local increase4 = ax.MenuItemFont:create(" + ") + increase4:setColor(ax.color32(0,200,20)) decrease4:setTag(4) increase4:setTag(4) decrease4:registerScriptTapHandler(onDecrease) increase4:registerScriptTapHandler(onIncrease) - + prevMenuPos = prevMenuPos - menuStep - local menu4 = cc.Menu:create(decrease4, increase4) + local menu4 = ax.Menu:create(decrease4, increase4) menu4:alignItemsHorizontally() - menu4:setPosition(cc.p(s.width/2, prevMenuPos)) + menu4:setPosition(ax.p(s.width/2, prevMenuPos)) layer:addChild(menu4, 1) - - label = cc.Label:createWithTTF("blue triangle", s_arialPath, 32) + + label = ax.Label:createWithTTF("blue triangle", s_arialPath, 32) layer:addChild(label, 1) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(s.width/2 - 150, prevMenuPos)) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(s.width/2 - 150, prevMenuPos)) - local contactListener = cc.EventListenerPhysicsContact:create() - contactListener:registerScriptHandler(onContactBegin, cc.Handler.EVENT_PHYSICS_CONTACT_BEGIN) + local contactListener = ax.EventListenerPhysicsContact:create() + contactListener:registerScriptHandler(onContactBegin, ax.Handler.EVENT_PHYSICS_CONTACT_BEGIN) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(contactListener, layer) - + resetTest() end - + initWithLayer(layer, onEnter) Helper.titleLabel:setString("Contact Test") @@ -1396,62 +1390,62 @@ local function PhysicsContactTest() end local function PhysicsPositionRotationTest() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 0)) - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 0)) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - - local wall = cc.Node:create() - wall:setPhysicsBody(cc.PhysicsBody:createEdgeBox(VisibleRect:getVisibleRect())) + + local wall = ax.Node:create() + wall:setPhysicsBody(ax.PhysicsBody:createEdgeBox(VisibleRect:getVisibleRect())) wall:setPosition(VisibleRect:center()) layer:addChild(wall) - + -- anchor test - local anchorNode = cc.Sprite:create("Images/YellowSquare.png") - anchorNode:setAnchorPoint(cc.p(0.1, 0.9)) + local anchorNode = ax.Sprite:create("Images/YellowSquare.png") + anchorNode:setAnchorPoint(ax.p(0.1, 0.9)) anchorNode:setPosition(100, 100) anchorNode:setScale(0.25) - anchorNode:setPhysicsBody(cc.PhysicsBody:createBox(anchorNode:getContentSize())) + anchorNode:setPhysicsBody(ax.PhysicsBody:createBox(anchorNode:getContentSize())) anchorNode:getPhysicsBody():setTag(DRAG_BODYS_TAG) layer:addChild(anchorNode) - + --parent test - local parent = cc.Sprite:create("Images/YellowSquare.png") + local parent = ax.Sprite:create("Images/YellowSquare.png") parent:setPosition(200, 100) parent:setScale(0.25) - local parentPhysicsBody = cc.PhysicsBody:createBox(anchorNode:getContentSize()) + local parentPhysicsBody = ax.PhysicsBody:createBox(anchorNode:getContentSize()) parent:setPhysicsBody(parentPhysicsBody) parentPhysicsBody:setTag(DRAG_BODYS_TAG) layer:addChild(parent) - - local leftBall = cc.Sprite:create("Images/ball.png") + + local leftBall = ax.Sprite:create("Images/ball.png") leftBall:setPosition(-30, 0) leftBall:setScale(2) - leftBall:setPhysicsBody(cc.PhysicsBody:createCircle(leftBall:getContentSize().width / 2)) + leftBall:setPhysicsBody(ax.PhysicsBody:createCircle(leftBall:getContentSize().width / 2)) leftBall:getPhysicsBody():setTag(DRAG_BODYS_TAG) parent:addChild(leftBall) - + -- offset position rotation test - local offsetPosNode = cc.Sprite:create("Images/YellowSquare.png") + local offsetPosNode = ax.Sprite:create("Images/YellowSquare.png") offsetPosNode:setPosition(100, 200) - local offsetPosNodePhysicsBody = cc.PhysicsBody:createBox(cc.size(offsetPosNode:getContentSize().width/2, + local offsetPosNodePhysicsBody = ax.PhysicsBody:createBox(ax.size(offsetPosNode:getContentSize().width/2, offsetPosNode:getContentSize().height/2)) offsetPosNode:setPhysicsBody(offsetPosNodePhysicsBody) - offsetPosNodePhysicsBody:setPositionOffset(cc.p(-offsetPosNode:getContentSize().width/2, + offsetPosNodePhysicsBody:setPositionOffset(ax.p(-offsetPosNode:getContentSize().width/2, -offsetPosNode:getContentSize().height/2)) offsetPosNodePhysicsBody:setRotationOffset(45) offsetPosNodePhysicsBody:setTag(DRAG_BODYS_TAG) layer:addChild(offsetPosNode) end - + initWithLayer(layer, onEnter) Helper.titleLabel:setString("Position/Rotation Test") @@ -1459,51 +1453,48 @@ local function PhysicsPositionRotationTest() end local function PhysicsSetGravityEnableTest() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - local wall = cc.Node:create() - wall:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + local wall = ax.Node:create() + wall:setPhysicsBody(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height), - cc.PhysicsMaterial(0.1, 1.0, 0.0))) + ax.PhysicsMaterial(0.1, 1.0, 0.0))) wall:setPosition(VisibleRect:center()); layer:addChild(wall) - local commonBox = makeBox(cc.p(100, 100), cc.size(50, 50), 1) + local commonBox = makeBox(ax.p(100, 100), ax.size(50, 50), 1) commonBox:getPhysicsBody():setTag(DRAG_BODYS_TAG) layer:addChild(commonBox) - local box = makeBox(cc.p(200, 100), cc.size(50, 50), 2) + local box = makeBox(ax.p(200, 100), ax.size(50, 50), 2) local boxBody = box:getPhysicsBody() - boxBody:setMass(20) boxBody:setTag(DRAG_BODYS_TAG) boxBody:setGravityEnable(false) layer:addChild(box) - local ball = makeBall(layer,cc.p(200,200),50) + local ball = makeBall(layer,ax.p(200,200),50) ball:setTag(2) local ballBody = ball:getPhysicsBody() ballBody:setTag(DRAG_BODYS_TAG) ballBody:setGravityEnable(false) - ballBody:setMass(50) layer:addChild(ball) local function onScheduleOnce() cclog("onScheduleOnce") local ball = layer:getChildByTag(2) - ball:getPhysicsBody():setMass(200) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 98)) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 98)) end --layer:scheduleOnce(onScheduleOnce,1.0) - local action = cc.Sequence:create(cc.DelayTime:create(1.0), - cc.CallFunc:create(onScheduleOnce)) + local action = ax.Sequence:create(ax.DelayTime:create(1.0), + ax.CallFunc:create(onScheduleOnce)) layer:runAction(action) end @@ -1514,35 +1505,35 @@ local function PhysicsSetGravityEnableTest() end local function PhysicsDemoBug5482() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() local _bodyInA = false - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) - touchListener:registerScriptHandler(onTouchMoved, cc.Handler.EVENT_TOUCH_MOVED) - touchListener:registerScriptHandler(onTouchEnded, cc.Handler.EVENT_TOUCH_ENDED) + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) + touchListener:registerScriptHandler(onTouchMoved, ax.Handler.EVENT_TOUCH_MOVED) + touchListener:registerScriptHandler(onTouchEnded, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) -- wall - local wall = cc.Node:create() - wall:addComponent(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + local wall = ax.Node:create() + wall:addComponent(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height), - cc.PhysicsMaterial(0.1, 1.0, 0.0))) + ax.PhysicsMaterial(0.1, 1.0, 0.0))) wall:setPosition(VisibleRect:center()); layer:addChild(wall) - local _nodeA = cc.Sprite:create("Images/YellowSquare.png") - _nodeA:setPosition(cc.p(VisibleRect:center().x-150,100)) + local _nodeA = ax.Sprite:create("Images/YellowSquare.png") + _nodeA:setPosition(ax.p(VisibleRect:center().x-150,100)) layer:addChild(_nodeA) - local _nodeB = cc.Sprite:create("Images/YellowSquare.png") - _nodeB:setPosition(cc.p(VisibleRect:center().x+150,100)) + local _nodeB = ax.Sprite:create("Images/YellowSquare.png") + _nodeB:setPosition(ax.p(VisibleRect:center().x+150,100)) layer:addChild(_nodeB) - local _body = cc.PhysicsBody:createBox(_nodeA:getContentSize()) + local _body = ax.PhysicsBody:createBox(_nodeA:getContentSize()) _body:setTag(DRAG_BODYS_TAG) _body:retain() @@ -1566,12 +1557,12 @@ local function PhysicsDemoBug5482() node:addComponent(_body) _bodyInA = not _bodyInA end - - cc.MenuItemFont:setFontSize(18) - _button = cc.MenuItemFont:create("Set Body To A"); + + ax.MenuItemFont:setFontSize(18) + _button = ax.MenuItemFont:create("Set Body To A"); _button:registerScriptTapHandler(changeBodyCallback) - local menu = cc.Menu:create(_button) + local menu = ax.Menu:create(_button) layer:addChild(menu) end @@ -1582,43 +1573,43 @@ local function PhysicsDemoBug5482() end local function PhysicsFixedUpdate() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setDebugDrawMask(cc.PhysicsWorld.DEBUGDRAW_ALL) - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0, 0)) + -- ax.Director:getInstance():getRunningScene():getPhysicsWorld():setDebugDrawMask(ax.PhysicsWorld.DEBUGDRAW_ALL) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0, 0)) local function addBall() - local ball = cc.Sprite:create("Images/ball.png") - ball:setPosition(cc.p(100,100)) - ball:setPhysicsBody(cc.PhysicsBody:createCircle(ball:getContentSize().width/2, cc.PhysicsMaterial(0.1, 1, 0.0))) + local ball = ax.Sprite:create("Images/ball.png") + ball:setPosition(ax.p(100,100)) + ball:setPhysicsBody(ax.PhysicsBody:createCircle(ball:getContentSize().width/2, ax.PhysicsMaterial(0.1, 1, 0.0))) ball:getPhysicsBody():setTag(DRAG_BODYS_TAG) - ball:getPhysicsBody():setVelocity(cc.p(1000,20)) + ball:getPhysicsBody():setVelocity(ax.p(1000,20)) layer:addChild(ball) end local function update(delta) for i=1,3 do - cc.Director:getInstance():getRunningScene():getPhysicsWorld():step(1/180.0) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():step(1/180.0) end end local function updateStart(delta) addBall() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setAutoStep(false) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setAutoStep(false) layer:scheduleUpdateWithPriorityLua(update, 0) end -- wall - local wall = cc.Node:create() - wall:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + local wall = ax.Node:create() + wall:setPhysicsBody(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height), - cc.PhysicsMaterial(0.1, 1.0, 0.0))) + ax.PhysicsMaterial(0.1, 1.0, 0.0))) wall:setPosition(VisibleRect:center()); layer:addChild(wall) addBall() - layer:runAction(cc.Sequence:create(cc.DelayTime:create(2.0), - cc.CallFunc:create(updateStart))) + layer:runAction(ax.Sequence:create(ax.DelayTime:create(2.0), + ax.CallFunc:create(updateStart))) end @@ -1629,68 +1620,68 @@ local function PhysicsFixedUpdate() end local function PhysicsTransformTest() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() layer:toggleDebug() - cc.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(cc.p(0,0)) - - local touchListener = cc.EventListenerTouchOneByOne:create() - touchListener:registerScriptHandler(onTouchBegan, cc.Handler.EVENT_TOUCH_BEGAN) + ax.Director:getInstance():getRunningScene():getPhysicsWorld():setGravity(ax.p(0,0)) + + local touchListener = ax.EventListenerTouchOneByOne:create() + touchListener:registerScriptHandler(onTouchBegan, ax.Handler.EVENT_TOUCH_BEGAN) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(touchListener, layer) - local _rootLayer = cc.Layer:create() + local _rootLayer = ax.Layer:create() layer:addChild(_rootLayer) - local wall = cc.Node:create() - wall:setPhysicsBody(cc.PhysicsBody:createEdgeBox(cc.size(VisibleRect:getVisibleRect().width, + local wall = ax.Node:create() + wall:setPhysicsBody(ax.PhysicsBody:createEdgeBox(ax.size(VisibleRect:getVisibleRect().width, VisibleRect:getVisibleRect().height), - cc.PhysicsMaterial(0.1, 1.0, 0.0))) + ax.PhysicsMaterial(0.1, 1.0, 0.0))) wall:setPosition(VisibleRect:center()); _rootLayer:addChild(wall) - - local _parentSprite = cc.Sprite:create("Images/YellowSquare.png") - _parentSprite:setPosition(cc.p(200,100)) + + local _parentSprite = ax.Sprite:create("Images/YellowSquare.png") + _parentSprite:setPosition(ax.p(200,100)) _parentSprite:setScale(0.25) - _parentSprite:setPhysicsBody(cc.PhysicsBody:createBox(_parentSprite:getContentSize(),cc.PhysicsMaterial(0.1, 1.0, 0.0))) + _parentSprite:setPhysicsBody(ax.PhysicsBody:createBox(_parentSprite:getContentSize(),ax.PhysicsMaterial(0.1, 1.0, 0.0))) _parentSprite:getPhysicsBody():setTag(DRAG_BODYS_TAG) _parentSprite:setTag(1) _rootLayer:addChild(_parentSprite) - local leftBall = cc.Sprite:create("Images/ball.png") - leftBall:setPosition(cc.p(-30,0)) + local leftBall = ax.Sprite:create("Images/ball.png") + leftBall:setPosition(ax.p(-30,0)) leftBall:setScale(2) - leftBall:setPhysicsBody(cc.PhysicsBody:createCircle(leftBall:getContentSize().width/2,cc.PhysicsMaterial(0.1,1.0,0.0))) + leftBall:setPhysicsBody(ax.PhysicsBody:createCircle(leftBall:getContentSize().width/2,ax.PhysicsMaterial(0.1,1.0,0.0))) leftBall:getPhysicsBody():setTag(DRAG_BODYS_TAG) _parentSprite:addChild(leftBall) - local scaleTo = cc.ScaleTo:create(2.0,0.5) - local scaleBack = cc.ScaleTo:create(2.0,1.0) - _parentSprite:runAction(cc.RepeatForever:create(cc.Sequence:create(scaleTo,scaleBack))) + local scaleTo = ax.ScaleTo:create(2.0,0.5) + local scaleBack = ax.ScaleTo:create(2.0,1.0) + _parentSprite:runAction(ax.RepeatForever:create(ax.Sequence:create(scaleTo,scaleBack))) - local normal = cc.Sprite:create("Images/YellowSquare.png") - normal:setPosition(cc.p(300,100)) + local normal = ax.Sprite:create("Images/YellowSquare.png") + normal:setPosition(ax.p(300,100)) normal:setScale(0.25,0.5) - normal:setPhysicsBody(cc.PhysicsBody:createBox(normal:getContentSize(),cc.PhysicsMaterial(0.1,1.0,0.0))) + normal:setPhysicsBody(ax.PhysicsBody:createBox(normal:getContentSize(),ax.PhysicsMaterial(0.1,1.0,0.0))) normal:getPhysicsBody():setTag(DRAG_BODYS_TAG) _rootLayer:addChild(normal) - local bullet = cc.Sprite:create("Images/ball.png") - bullet:setPosition(cc.p(200,200)) - bullet:setPhysicsBody(cc.PhysicsBody:createCircle(bullet:getContentSize().width/2,cc.PhysicsMaterial(0.1,1.0,0.0))) - bullet:getPhysicsBody():setVelocity(cc.p(100,100)) + local bullet = ax.Sprite:create("Images/ball.png") + bullet:setPosition(ax.p(200,200)) + bullet:setPhysicsBody(ax.PhysicsBody:createCircle(bullet:getContentSize().width/2,ax.PhysicsMaterial(0.1,1.0,0.0))) + bullet:getPhysicsBody():setVelocity(ax.p(100,100)) _rootLayer:addChild(bullet) - local move = cc.MoveBy:create(2.0,cc.p(100,100)) - local move2 = cc.MoveBy:create(2.0,cc.p(-200,0)) - local move3 = cc.MoveBy:create(2.0,cc.p(100,-100)) - local scale = cc.ScaleTo:create(3.0,0.3) - local scale2 = cc.ScaleTo:create(3.0,1.0) - local rotate = cc.RotateBy:create(6.0,360) + local move = ax.MoveBy:create(2.0,ax.p(100,100)) + local move2 = ax.MoveBy:create(2.0,ax.p(-200,0)) + local move3 = ax.MoveBy:create(2.0,ax.p(100,-100)) + local scale = ax.ScaleTo:create(3.0,0.3) + local scale2 = ax.ScaleTo:create(3.0,1.0) + local rotate = ax.RotateBy:create(6.0,360) - _rootLayer:runAction(cc.RepeatForever:create(cc.Sequence:create(move,move2,move3))) - _rootLayer:runAction(cc.RepeatForever:create(cc.Sequence:create(scale,scale2))) - _rootLayer:runAction(cc.RepeatForever:create(cc.Sequence:create(rotate))) + _rootLayer:runAction(ax.RepeatForever:create(ax.Sequence:create(move,move2,move3))) + _rootLayer:runAction(ax.RepeatForever:create(ax.Sequence:create(scale,scale2))) + _rootLayer:runAction(ax.RepeatForever:create(ax.Sequence:create(rotate))) end initWithLayer(layer, onEnter) @@ -1699,27 +1690,27 @@ local function PhysicsTransformTest() end local function PhysicsIssue9959() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local function onEnter() - local origin = cc.Director:getInstance():getVisibleOrigin() - local visibleSize = cc.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() + local visibleSize = ax.Director:getInstance():getVisibleSize() local scale9Sprite1 = ccui.Scale9Sprite:create("Images/ball.png") - scale9Sprite1:setPosition(cc.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2)) + scale9Sprite1:setPosition(ax.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2)) layer:addChild(scale9Sprite1) - scale9Sprite1:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.MoveBy:create(2.0,cc.p(100.0,0.0)), - cc.MoveBy:create(2.0,cc.p(-100,0.0))))) + scale9Sprite1:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.MoveBy:create(2.0,ax.p(100.0,0.0)), + ax.MoveBy:create(2.0,ax.p(-100,0.0))))) local scale9Sprite2 = ccui.Scale9Sprite:create("Images/ball.png") - scale9Sprite2:setPosition(cc.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2+50)) + scale9Sprite2:setPosition(ax.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2+50)) layer:addChild(scale9Sprite2) - scale9Sprite2:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.ScaleTo:create(2.0,1.5), - cc.ScaleTo:create(2.0,1.0)))) + scale9Sprite2:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.ScaleTo:create(2.0,1.5), + ax.ScaleTo:create(2.0,1.0)))) local scale9Sprite3 = ccui.Scale9Sprite:create("Images/ball.png") - scale9Sprite3:setPosition(cc.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2-50)) + scale9Sprite3:setPosition(ax.p(origin.x+visibleSize.width/2,origin.y+visibleSize.height/2-50)) layer:addChild(scale9Sprite3) - scale9Sprite3:runAction(cc.RepeatForever:create(cc.Sequence:create(cc.RotateBy:create(2.0,360)))) + scale9Sprite3:runAction(ax.RepeatForever:create(ax.Sequence:create(ax.RotateBy:create(2.0,360)))) end initWithLayer(layer, onEnter) @@ -1730,7 +1721,7 @@ end function PhysicsTest() cclog("PhysicsTest") - local scene = cc.Scene:createWithPhysics() + local scene = ax.Scene:createWithPhysics() Helper.usePhysics = true diff --git a/tests/lua-tests/Content/src/RenderTextureTest/RenderTextureTest.lua b/tests/lua-tests/Content/src/RenderTextureTest/RenderTextureTest.lua index 1924178566c2..7f7bca40208d 100644 --- a/tests/lua-tests/Content/src/RenderTextureTest/RenderTextureTest.lua +++ b/tests/lua-tests/Content/src/RenderTextureTest/RenderTextureTest.lua @@ -7,7 +7,7 @@ local function RenderTextureSave() local ret = createTestLayer("Touch the screen", "Press 'Save Image' to create an snapshot of the render texture") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local target = nil local counter = 0 local brushes = {} @@ -19,15 +19,15 @@ local function RenderTextureSave() local png = string.format("image-%d.png", counter) local jpg = string.format("image-%d.jpg", counter) - target:saveToFile(png, cc.IMAGE_FORMAT_PNG) - target:saveToFile(jpg, cc.IMAGE_FORMAT_JPEG) + target:saveToFile(png, ax.IMAGE_FORMAT_PNG) + target:saveToFile(jpg, ax.IMAGE_FORMAT_JPEG) local function callback(image) - local tex = cc.Director:getInstance():getTextureCache():addImage(image, png) - local sprite = cc.Sprite:createWithTexture(tex) + local tex = ax.Director:getInstance():getTextureCache():addImage(image, png) + local sprite = ax.Sprite:createWithTexture(tex) sprite:setScale(0.3) ret:addChild(sprite) - sprite:setPosition(cc.p(40, 40)) + sprite:setPosition(ax.p(40, 40)) sprite:setRotation(counter * 3) end @@ -40,19 +40,19 @@ local function RenderTextureSave() local function onNodeEvent(event) if event == "exit" then target:release() - cc.Director:getInstance():getTextureCache():removeUnusedTextures() + ax.Director:getInstance():getTextureCache():removeUnusedTextures() end end ret:registerScriptHandler(onNodeEvent) -- create a render texture, this is what we are going to draw into - target = cc.RenderTexture:create(s.width, s.height, cc.TEXTURE_PF_RGBA8) + target = ax.RenderTexture:create(s.width, s.height, ax.TEXTURE_PF_RGBA8) target:retain() - target:setPosition(cc.p(s.width / 2, s.height / 2)) + target:setPosition(ax.p(s.width / 2, s.height / 2)) - -- note that the render texture is a cc.Node, and contains a sprite of its texture for convenience, - -- so we can just parent it to the scene like any other cc.Node + -- note that the render texture is a ax.Node, and contains a sprite of its texture for convenience, + -- so we can just parent it to the scene like any other ax.Node ret:addChild(target, -1) local function onTouchesMoved(touches, event) @@ -61,7 +61,7 @@ local function RenderTextureSave() target:begin() - local distance = cc.pGetDistance(start, ended) + local distance = ax.pGetDistance(start, ended) if distance > 1 then brushes = {} local d = distance @@ -69,8 +69,8 @@ local function RenderTextureSave() for i = 0,d -1 do -- create a brush image to draw into the texture with - local sprite = cc.Sprite:create("Images/fire.png") - sprite:setColor(cc.c3b(255, 0, 0)) + local sprite = ax.Sprite:create("Images/fire.png") + sprite:setColor(ax.color32(255, 0, 0)) sprite:setOpacity(20) brushes[i + 1] = sprite end @@ -79,13 +79,13 @@ local function RenderTextureSave() local difx = ended.x - start.x local dify = ended.y - start.y local delta = i / distance - brushes[i + 1]:setPosition(cc.p(start.x + (difx * delta), start.y + (dify * delta))) + brushes[i + 1]:setPosition(ax.p(start.x + (difx * delta), start.y + (dify * delta))) brushes[i + 1]:setRotation(math.random(0, 359)) local r = math.random(0, 49) / 50.0 + 0.25 brushes[i + 1]:setScale(r) - -- Use cc.RANDOM_0_1() will cause error when loading libtests.so on android, I don't know why. - brushes[i + 1]:setColor(cc.c3b(math.random(0, 126) + 128, 255, 255)) + -- Use ax.RANDOM_0_1() will cause error when loading libtests.so on android, I don't know why. + brushes[i + 1]:setColor(ax.color32(math.random(0, 126) + 128, 255, 255)) -- Call visit to draw the brush, don't call draw.. brushes[i + 1]:visit() end @@ -95,21 +95,21 @@ local function RenderTextureSave() target:endToLua() end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = ret:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, ret) -- Save Image menu - cc.MenuItemFont:setFontSize(16) - local item1 = cc.MenuItemFont:create("Save Image") + ax.MenuItemFont:setFontSize(16) + local item1 = ax.MenuItemFont:create("Save Image") item1:setAnchorPoint(1, 1) item1:setPosition(VisibleRect:rightTop().x, VisibleRect:rightTop().y) item1:registerScriptTapHandler(saveImage) - local item2 = cc.MenuItemFont:create("Clear") + local item2 = ax.MenuItemFont:create("Clear") item2:setAnchorPoint(1, 1) item2:setPosition(VisibleRect:rightTop().x, VisibleRect:rightTop().y - item1:getContentSize().height) item2:registerScriptTapHandler(clearImage) - local menu = cc.Menu:create(item1, item2) + local menu = ax.Menu:create(item1, item2) ret:addChild(menu) menu:setPosition(0, 0) return ret @@ -135,20 +135,20 @@ end -- * B1: non-premulti sprite -- * B2: non-premulti render -- */ --- local background = cc.LayerColor:create(cc.c4b(200,200,200,255)) +-- local background = ax.LayerColor:create(ax.color32(200,200,200,255)) -- addChild(background) --- local spr_premulti = cc.Sprite:create("Images/fire.png") --- spr_premulti:setPosition(cc.p(16,48)) +-- local spr_premulti = ax.Sprite:create("Images/fire.png") +-- spr_premulti:setPosition(ax.p(16,48)) --- local spr_nonpremulti = cc.Sprite:create("Images/fire.png") --- spr_nonpremulti:setPosition(cc.p(16,16)) +-- local spr_nonpremulti = ax.Sprite:create("Images/fire.png") +-- spr_nonpremulti:setPosition(ax.p(16,16)) -- /* A2 & B2 setup */ --- local rend = cc.RenderTexture:create(32, 64, cc.TEXTURE_PF_RGBA8) +-- local rend = ax.RenderTexture:create(32, 64, ax.TEXTURE_PF_RGBA8) -- if (NULL == rend) @@ -163,14 +163,14 @@ end -- spr_nonpremulti:visit() -- rend:end() --- local s = cc.Director:getInstance():getWinSize() +-- local s = ax.Director:getInstance():getWinSize() -- --/* A1: setup */ --- spr_premulti:setPosition(cc.p(s.width/2-16, s.height/2+16)) +-- spr_premulti:setPosition(ax.p(s.width/2-16, s.height/2+16)) -- --/* B1: setup */ --- spr_nonpremulti:setPosition(cc.p(s.width/2-16, s.height/2-16)) +-- spr_nonpremulti:setPosition(ax.p(s.width/2-16, s.height/2-16)) --- rend:setPosition(cc.p(s.width/2+16, s.height/2)) +-- rend:setPosition(ax.p(s.width/2+16, s.height/2)) -- addChild(spr_nonpremulti) -- addChild(spr_premulti) @@ -192,7 +192,7 @@ end -- local pLayer = nextTestCase() -- addChild(pLayer) --- cc.Director:getInstance():replaceScene(this) +-- ax.Director:getInstance():replaceScene(this) -- end -- --/** @@ -202,35 +202,35 @@ end -- local function RenderTextureZbuffer() -- this:setTouchEnabled(true) --- local size = cc.Director:getInstance():getWinSize() --- local label = cc.LabelTTF:create("vertexZ = 50", "Marker Felt", 64) --- label:setPosition(cc.p(size.width / 2, size.height * 0.25)) +-- local size = ax.Director:getInstance():getWinSize() +-- local label = ax.LabelTTF:create("vertexZ = 50", "Marker Felt", 64) +-- label:setPosition(ax.p(size.width / 2, size.height * 0.25)) -- this:addChild(label) --- local label2 = cc.LabelTTF:create("vertexZ = 0", "Marker Felt", 64) --- label2:setPosition(cc.p(size.width / 2, size.height * 0.5)) +-- local label2 = ax.LabelTTF:create("vertexZ = 0", "Marker Felt", 64) +-- label2:setPosition(ax.p(size.width / 2, size.height * 0.5)) -- this:addChild(label2) --- local label3 = cc.LabelTTF:create("vertexZ = -50", "Marker Felt", 64) --- label3:setPosition(cc.p(size.width / 2, size.height * 0.75)) +-- local label3 = ax.LabelTTF:create("vertexZ = -50", "Marker Felt", 64) +-- label3:setPosition(ax.p(size.width / 2, size.height * 0.75)) -- this:addChild(label3) -- label:setVertexZ(50) -- label2:setVertexZ(0) -- label3:setVertexZ(-50) --- cc.SpriteFrameCache:getInstance():addSpriteFramesWithFile("Images/bugs/circle.plist") --- mgr = cc.SpriteBatchNode:create("Images/bugs/circle.png", 9) +-- ax.SpriteFrameCache:getInstance():addSpriteFramesWithFile("Images/bugs/circle.plist") +-- mgr = ax.SpriteBatchNode:create("Images/bugs/circle.png", 9) -- this:addChild(mgr) --- sp1 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp2 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp3 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp4 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp5 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp6 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp7 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp8 = cc.Sprite:createWithSpriteFrameName("circle.png") --- sp9 = cc.Sprite:createWithSpriteFrameName("circle.png") +-- sp1 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp2 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp3 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp4 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp5 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp6 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp7 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp8 = ax.Sprite:createWithSpriteFrameName("circle.png") +-- sp9 = ax.Sprite:createWithSpriteFrameName("circle.png") -- mgr:addChild(sp1, 9) -- mgr:addChild(sp2, 8) @@ -253,7 +253,7 @@ end -- sp9:setVertexZ(-400) -- sp9:setScale(2) --- sp9:setColor(cc.c3b::YELLOW) +-- sp9:setColor(ax.color32::YELLOW) -- end -- local function title() @@ -266,13 +266,13 @@ end -- return "Touch screen. It should be green" -- end --- local function ccTouchesBegan(cocos2d:cc.Set *touches, cocos2d:cc.Event *event) +-- local function ccTouchesBegan(cocos2d:ax.Set *touches, cocos2d:ax.Event *event) --- cc.SetIterator iter --- cc.Touch *touch +-- ax.SetIterator iter +-- ax.Touch *touch -- for (iter = touches:begin() iter != touches:end() ++iter) --- touch = (cc.Touch *)(*iter) +-- touch = (ax.Touch *)(*iter) -- local location = touch:getLocation() -- sp1:setPosition(location) @@ -287,13 +287,13 @@ end -- end -- end --- local function ccTouchesMoved(cc.const std::vector& touches, cc.Event* event) +-- local function ccTouchesMoved(ax.const std::vector& touches, ax.Event* event) --- cc.SetIterator iter --- cc.Touch *touch +-- ax.SetIterator iter +-- ax.Touch *touch -- for (iter = touches:begin() iter != touches:end() ++iter) --- touch = (cc.Touch *)(*iter) +-- touch = (ax.Touch *)(*iter) -- local location = touch:getLocation() -- sp1:setPosition(location) @@ -308,35 +308,35 @@ end -- end -- end --- local function ccTouchesEnded(cc.const std::vector& touches, cc.Event* event) +-- local function ccTouchesEnded(ax.const std::vector& touches, ax.Event* event) -- this:renderScreenShot() -- end -- local function renderScreenShot() --- local texture = cc.RenderTexture:create(512, 512) +-- local texture = ax.RenderTexture:create(512, 512) -- if (NULL == texture) -- return -- end --- texture:setAnchorPoint(cc.p(0, 0)) +-- texture:setAnchorPoint(ax.p(0, 0)) -- texture:begin() -- this:visit() -- texture:end() --- local sprite = cc.Sprite:createWithTexture(texture:getSprite():getTexture()) +-- local sprite = ax.Sprite:createWithTexture(texture:getSprite():getTexture()) --- sprite:setPosition(cc.p(256, 256)) +-- sprite:setPosition(ax.p(256, 256)) -- sprite:setOpacity(182) -- sprite:setFlippedY(1) -- this:addChild(sprite, 999999) --- sprite:setColor(cc.c3b::GREEN) +-- sprite:setColor(ax.color32::GREEN) --- sprite:runAction(cc.Sequence:create(cc.FadeTo:create(2, 0), --- cc.Hide:create(), +-- sprite:runAction(ax.Sequence:create(ax.FadeTo:create(2, 0), +-- ax.Hide:create(), -- NULL)) -- end @@ -344,12 +344,12 @@ end -- local function RenderTextureTestDepthStencil() --- local s = cc.Director:getInstance():getWinSize() +-- local s = ax.Director:getInstance():getWinSize() --- local sprite = cc.Sprite:create("Images/fire.png") --- sprite:setPosition(cc.p(s.width * 0.25, 0)) +-- local sprite = ax.Sprite:create("Images/fire.png") +-- sprite:setPosition(ax.p(s.width * 0.25, 0)) -- sprite:setScale(10) --- local rend = cc.RenderTexture:create(s.width, s.height, kcc.Texture2DPixelFormat_RGBA4444, GL_DEPTH24_STENCIL8) +-- local rend = ax.RenderTexture:create(s.width, s.height, kcc.Texture2DPixelFormat_RGBA4444, GL_DEPTH24_STENCIL8) -- glStencilMask(0xFF) -- rend:beginWithClear(0, 0, 0, 0, 0, 0) @@ -362,7 +362,7 @@ end -- sprite:visit() -- --! move sprite half width and height, and draw only where not marked --- sprite:setPosition(cc.p__add(sprite:getPosition(), cc.p__mul(cc.p(sprite:getContentSize().width * sprite:getScale(), sprite:getContentSize().height * sprite:getScale()), 0.5))) +-- sprite:setPosition(ax.p__add(sprite:getPosition(), ax.p__mul(ax.p(sprite:getContentSize().width * sprite:getScale(), sprite:getContentSize().height * sprite:getScale()), 0.5))) -- glStencilFunc(GL_NOTEQUAL, 1, 0xFF) -- glColorMask(1, 1, 1, 1) -- sprite:visit() @@ -371,7 +371,7 @@ end -- glDisable(GL_STENCIL_TEST) --- rend:setPosition(cc.p(s.width * 0.5, s.height * 0.5)) +-- rend:setPosition(ax.p(s.width * 0.5, s.height * 0.5)) -- this:addChild(rend) -- end @@ -401,28 +401,28 @@ end -- * B1: non-premulti sprite -- * B2: non-premulti render -- */ --- local background = cc.LayerColor:create(cc.c4b(40,40,40,255)) +-- local background = ax.LayerColor:create(ax.color32(40,40,40,255)) -- addChild(background) -- -- sprite 1 --- sprite1 = cc.Sprite:create("Images/fire.png") +-- sprite1 = ax.Sprite:create("Images/fire.png") -- -- sprite 2 --- sprite2 = cc.Sprite:create("Images/fire_rgba8888.pvr") +-- sprite2 = ax.Sprite:create("Images/fire_rgba8888.pvr") --- local s = cc.Director:getInstance():getWinSize() +-- local s = ax.Director:getInstance():getWinSize() -- /* Create the render texture */ --- local renderTexture = cc.RenderTexture:create(s.width, s.height, kcc.Texture2DPixelFormat_RGBA4444) +-- local renderTexture = ax.RenderTexture:create(s.width, s.height, kcc.Texture2DPixelFormat_RGBA4444) -- this:renderTexture = renderTexture --- renderTexture:setPosition(cc.p(s.width/2, s.height/2)) +-- renderTexture:setPosition(ax.p(s.width/2, s.height/2)) -- renderTexture:setScale(2.0) -- /* add the sprites to the render texture */ -- renderTexture:addChild(sprite1) -- renderTexture:addChild(sprite2) --- renderTexture:setClearColor(cc.c4f(0, 0, 0, 0)) +-- renderTexture:setClearColor(ax.color(0, 0, 0, 0)) -- renderTexture:setClearFlags(GL_COLOR_BUFFER_BIT) -- /* add the render texture to the scene */ @@ -433,14 +433,14 @@ end -- scheduleUpdate() -- -- Toggle clear on / off --- local item = cc.MenuItemFont:create("Clear On/Off", this, menu_selector(RenderTextureTargetNode:touched)) --- local menu = cc.Menu:create(item, NULL) +-- local item = ax.MenuItemFont:create("Clear On/Off", this, menu_selector(RenderTextureTargetNode:touched)) +-- local menu = ax.Menu:create(item, NULL) -- addChild(menu) --- menu:setPosition(cc.p(s.width/2, s.height/2)) +-- menu:setPosition(ax.p(s.width/2, s.height/2)) -- end --- local function touched(cc.Object* sender) +-- local function touched(ax.Object* sender) -- if (renderTexture:getClearFlags() == 0) @@ -449,7 +449,7 @@ end -- else -- renderTexture:setClearFlags(0) --- renderTexture:setClearColor(cc.c4f( cc.RANDOM_0_1(), cc.RANDOM_0_1(), cc.RANDOM_0_1(), 1)) +-- renderTexture:setClearColor(ax.color( ax.RANDOM_0_1(), ax.RANDOM_0_1(), ax.RANDOM_0_1(), 1)) -- end -- end @@ -457,8 +457,8 @@ end -- static float time = 0 -- float r = 80 --- sprite1:setPosition(cc.p(cosf(time * 2) * r, sinf(time * 2) * r)) --- sprite2:setPosition(cc.p(sinf(time * 2) * r, cosf(time * 2) * r)) +-- sprite1:setPosition(ax.p(cosf(time * 2) * r, sinf(time * 2) * r)) +-- sprite2:setPosition(ax.p(sinf(time * 2) * r, cosf(time * 2) * r)) -- time += dt -- end @@ -477,7 +477,7 @@ end -- local function SimpleSprite() : rt(nullptr) {} --- local function SimpleSprite* SpriteRenderTextureBug:SimpleSprite:create(const char* filename, const cc.rect &rect) +-- local function SimpleSprite* SpriteRenderTextureBug:SimpleSprite:create(const char* filename, const ax.rect &rect) -- SimpleSprite *sprite = new SimpleSprite() -- if (sprite && sprite:initWithFile(filename, rect)) @@ -486,7 +486,7 @@ end -- end -- else --- cc._SAFE_DELETE(sprite) +-- ax._SAFE_DELETE(sprite) -- end -- return sprite @@ -496,14 +496,14 @@ end -- if (rt == NULL) --- local s = cc.Director:getInstance():getWinSize() --- rt = new cc.RenderTexture() --- rt:initWithWidthAndHeight(s.width, s.height, cc.TEXTURE_PF_RGBA8) +-- local s = ax.Director:getInstance():getWinSize() +-- rt = new ax.RenderTexture() +-- rt:initWithWidthAndHeight(s.width, s.height, ax.TEXTURE_PF_RGBA8) -- end -- rt:beginWithClear(0.0, 0.0, 0.0, 1.0) -- rt:end() --- cc._NODE_DRAW_SETUP() +-- ax._NODE_DRAW_SETUP() -- BlendFunc blend = getBlendFunc() -- ccGLBlendFunc(blend.src, blend.dst) @@ -538,51 +538,51 @@ end -- setTouchEnabled(true) --- local s = cc.Director:getInstance():getWinSize() --- addNewSpriteWithCoords(cc.p(s.width/2, s.height/2)) +-- local s = ax.Director:getInstance():getWinSize() +-- addNewSpriteWithCoords(ax.p(s.width/2, s.height/2)) -- end --- local function SimpleSprite* SpriteRenderTextureBug:addNewSpriteWithCoords(const cc.p& p) +-- local function SimpleSprite* SpriteRenderTextureBug:addNewSpriteWithCoords(const ax.p& p) --- int idx = cc.RANDOM_0_1() * 1400 / 100 +-- int idx = ax.RANDOM_0_1() * 1400 / 100 -- int x = (idx%5) * 85 -- int y = (idx/5) * 121 -- SpriteRenderTextureBug:SimpleSprite *sprite = SpriteRenderTextureBug:SimpleSprite:create("Images/grossini_dance_atlas.png", --- cc.rect(x,y,85,121)) +-- ax.rect(x,y,85,121)) -- addChild(sprite) -- sprite:setPosition(p) -- local action = NULL --- float rd = cc.RANDOM_0_1() +-- float rd = ax.RANDOM_0_1() -- if (rd < 0.20) --- action = cc.ScaleBy:create(3, 2) +-- action = ax.ScaleBy:create(3, 2) -- else if (rd < 0.40) --- action = cc.RotateBy:create(3, 360) +-- action = ax.RotateBy:create(3, 360) -- else if (rd < 0.60) --- action = cc.Blink:create(1, 3) +-- action = ax.Blink:create(1, 3) -- else if (rd < 0.8 ) --- action = cc.TintBy:create(2, 0, -255, -255) +-- action = ax.TintBy:create(2, 0, -255, -255) -- else --- action = cc.FadeOut:create(2) +-- action = ax.FadeOut:create(2) -- local action_back = action:reverse() --- local seq = cc.Sequence:create(action, action_back, NULL) +-- local seq = ax.Sequence:create(action, action_back, NULL) --- sprite:runAction(cc.RepeatForever:create(seq)) +-- sprite:runAction(ax.RepeatForever:create(seq)) -- --return sprite -- return NULL -- end --- local function ccTouchesEnded(cc.const std::vector& touches, cc.Event* event) +-- local function ccTouchesEnded(ax.const std::vector& touches, ax.Event* event) --- cc.SetIterator iter = touches:begin() +-- ax.SetIterator iter = touches:begin() -- for( iter != touches:end() ++iter) --- local location = ((cc.Touch*)(*iter)):getLocation() +-- local location = ((ax.Touch*)(*iter)):getLocation() -- addNewSpriteWithCoords(location) -- end -- end @@ -600,7 +600,7 @@ end function RenderTextureTestMain() cclog("RenderTextureTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { RenderTextureSave, @@ -611,7 +611,7 @@ function RenderTextureTestMain() -- SpriteRenderTextureBug } Helper.index = 1 - + scene:addChild(RenderTextureSave()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/RotateWorldTest/RotateWorldTest.lua b/tests/lua-tests/Content/src/RotateWorldTest/RotateWorldTest.lua index 844a87728770..fe048d022e11 100644 --- a/tests/lua-tests/Content/src/RotateWorldTest/RotateWorldTest.lua +++ b/tests/lua-tests/Content/src/RotateWorldTest/RotateWorldTest.lua @@ -1,61 +1,61 @@ -local size = cc.Director:getInstance():getWinSize() +local size = ax.Director:getInstance():getWinSize() local function CreateSpriteLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local x, y x = size.width y = size.height - local sprite = cc.Sprite:create(s_pPathGrossini) - local spriteSister1 = cc.Sprite:create(s_pPathSister1) - local spriteSister2 = cc.Sprite:create(s_pPathSister2) + local sprite = ax.Sprite:create(s_pPathGrossini) + local spriteSister1 = ax.Sprite:create(s_pPathSister1) + local spriteSister2 = ax.Sprite:create(s_pPathSister2) sprite:setScale(1.5) spriteSister1:setScale(1.5) spriteSister2:setScale(1.5) - sprite:setPosition(cc.p(x / 2, y / 2)) - spriteSister1:setPosition(cc.p(40, y / 2)) - spriteSister2:setPosition(cc.p(x - 40, y / 2)) + sprite:setPosition(ax.p(x / 2, y / 2)) + spriteSister1:setPosition(ax.p(40, y / 2)) + spriteSister2:setPosition(ax.p(x - 40, y / 2)) layer:addChild(sprite) layer:addChild(spriteSister1) layer:addChild(spriteSister2) - local rot = cc.RotateBy:create(16, -3600) + local rot = ax.RotateBy:create(16, -3600) sprite:runAction(rot) - local jump1 = cc.JumpBy:create(4, cc.p(-400, 0), 100, 4) + local jump1 = ax.JumpBy:create(4, ax.p(-400, 0), 100, 4) local jump2 = jump1:reverse() - local rot1 = cc.RotateBy:create(4, 360 * 2) + local rot1 = ax.RotateBy:create(4, 360 * 2) local rot2 = rot1:reverse() - local jump3 = cc.JumpBy:create(4, cc.p(-400, 0), 100, 4) + local jump3 = ax.JumpBy:create(4, ax.p(-400, 0), 100, 4) local jump4 = jump3:reverse() - local rot3 = cc.RotateBy:create(4, 360 * 2) + local rot3 = ax.RotateBy:create(4, 360 * 2) local rot4 = rot3:reverse() - spriteSister1:runAction(cc.Repeat:create(cc.Sequence:create(jump2, jump1), 5)) - spriteSister2:runAction(cc.Repeat:create(cc.Sequence:create(jump3, jump4), 5)) + spriteSister1:runAction(ax.Repeat:create(ax.Sequence:create(jump2, jump1), 5)) + spriteSister2:runAction(ax.Repeat:create(ax.Sequence:create(jump3, jump4), 5)) - spriteSister1:runAction(cc.Repeat:create(cc.Sequence:create(rot1, rot2), 5)) - spriteSister2:runAction(cc.Repeat:create(cc.Sequence:create(rot4, rot3), 5)) + spriteSister1:runAction(ax.Repeat:create(ax.Sequence:create(rot1, rot2), 5)) + spriteSister2:runAction(ax.Repeat:create(ax.Sequence:create(rot4, rot3), 5)) return layer end local function CreateTestLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local x, y x = size.width y = size.height - local label = cc.Label:createWithTTF("Axmol", s_tahomaPath, 64) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("Axmol", s_tahomaPath, 64) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(x / 2, y / 2) layer:addChild(label) @@ -63,42 +63,42 @@ local function CreateTestLayer() end local function CreateRotateWorldLayer() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local x, y x = size.width y = size.height - local blue = cc.LayerColor:create(cc.c4b(0,0,255,255)) - local red = cc.LayerColor:create(cc.c4b(255,0,0,255)) - local green = cc.LayerColor:create(cc.c4b(0,255,0,255)) - local white = cc.LayerColor:create(cc.c4b(255,255,255,255)) + local blue = ax.LayerColor:create(ax.color32(0,0,255,255)) + local red = ax.LayerColor:create(ax.color32(255,0,0,255)) + local green = ax.LayerColor:create(ax.color32(0,255,0,255)) + local white = ax.LayerColor:create(ax.color32(255,255,255,255)) blue:setScale(0.5) - blue:setPosition(cc.p(- x / 4, - y / 4)) + blue:setPosition(ax.p(- x / 4, - y / 4)) blue:addChild(CreateSpriteLayer()) red:setScale(0.5) - red:setPosition(cc.p(x / 4, - y / 4)) + red:setPosition(ax.p(x / 4, - y / 4)) green:setScale(0.5) - green:setPosition(cc.p(- x / 4, y / 4)) + green:setPosition(ax.p(- x / 4, y / 4)) green:addChild(CreateTestLayer()) white:setScale(0.5) - white:setPosition(cc.p(x / 4, y / 4)) + white:setPosition(ax.p(x / 4, y / 4)) white:setIgnoreAnchorPointForPosition(false) - white:setPosition(cc.p(x / 4 * 3, y / 4 * 3)) + white:setPosition(ax.p(x / 4 * 3, y / 4 * 3)) layer:addChild(blue, -1) layer:addChild(white) layer:addChild(green) layer:addChild(red) - local rot = cc.RotateBy:create(8, 720) - local rot1 = cc.RotateBy:create(8, 720) - local rot2 = cc.RotateBy:create(8, 720) - local rot3 = cc.RotateBy:create(8, 720) + local rot = ax.RotateBy:create(8, 720) + local rot1 = ax.RotateBy:create(8, 720) + local rot2 = ax.RotateBy:create(8, 720) + local rot3 = ax.RotateBy:create(8, 720) blue:runAction(rot) red:runAction(rot1) @@ -113,12 +113,12 @@ end -------------------------------- function RotateWorldTest() cclog("RotateWorldTest") - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = CreateRotateWorldLayer() scene:addChild(layer) scene:addChild(CreateBackMenuItem()) - scene:runAction(cc.RotateBy:create(4, -360)) + scene:runAction(ax.RotateBy:create(4, -360)) return scene end diff --git a/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua b/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua index 4a36ce0fb199..2ec9a98d0718 100644 --- a/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua +++ b/tests/lua-tests/Content/src/Scene3DTest/Scene3DTest.lua @@ -1,5 +1,5 @@ -local GAME_LAYER = +local GAME_LAYER = { LAYER_SKYBOX = 1, LAYER_GAME = 2, @@ -10,14 +10,14 @@ local GAME_LAYER = LAYER_COUNT = 7, } -local s_CF = +local s_CF = { - cc.CameraFlag.DEFAULT, - cc.CameraFlag.USER1, - cc.CameraFlag.USER2, - cc.CameraFlag.USER3, - cc.CameraFlag.USER4, - cc.CameraFlag.USER5, + ax.CameraFlag.DEFAULT, + ax.CameraFlag.USER1, + ax.CameraFlag.USER2, + ax.CameraFlag.USER3, + ax.CameraFlag.USER4, + ax.CameraFlag.USER5, } local s_CM = @@ -40,16 +40,16 @@ local PLAER_STATE = LEFT = 0, RIGHT = 1, IDLE = 2, - FORWARD = 3, + FORWARD = 3, BACKWARD = 4, } local PLAYER_HEIGHT = 0 -local camera_offset = cc.vec3(0, 45, 60) +local camera_offset = ax.vec3(0, 45, 60) local Player = class("Player", function(file, cam, terrain) - local sprite = cc.Sprite3D:create(file) + local sprite = ax.Sprite3D:create(file) if nil ~= sprite then sprite._headingAngle = 0 sprite._playerState = PLAER_STATE.IDLE @@ -61,53 +61,53 @@ end) function Player:ctor() -- body - self:init() + self:init() end function Player:init() - self._headingAxis = cc.vec3(0.0, 0.0, 0.0) + self._headingAxis = ax.vec3(0.0, 0.0, 0.0) self:scheduleUpdateWithPriorityLua(function(dt) local curPos = self:getPosition3D() if self._playerState == PLAER_STATE.IDLE then elseif self._playerState == PLAER_STATE.FORWARD then - local newFaceDir = cc.vec3sub(self._targetPos, curPos) + local newFaceDir = ax.vec3sub(self._targetPos, curPos) newFaceDir.y = 0.0 - newFaceDir = cc.vec3normalize(newFaceDir) - local offset = cc.vec3mul(newFaceDir, 25.0 * dt) - curPos = cc.vec3add(curPos, offset) + newFaceDir = ax.vec3normalize(newFaceDir) + local offset = ax.vec3mul(newFaceDir, 25.0 * dt) + curPos = ax.vec3add(curPos, offset) self:setPosition3D(curPos) elseif self._playerState == PLAER_STATE.BACKWARD then - + local transform = self:getNodeToWorldTransform() - local forward_vec = cc.vec3(-transform[9], -transform[10], -transform[11]) - forward_vec = cc.vec3normalize(forward_vec) - self:setPosition3D(cc.vec3sub(curPos, cc.vec3mul(forward_vec, 15 * dt))) + local forward_vec = ax.vec3(-transform[9], -transform[10], -transform[11]) + forward_vec = ax.vec3normalize(forward_vec) + self:setPosition3D(ax.vec3sub(curPos, ax.vec3mul(forward_vec, 15 * dt))) elseif self._playerState == PLAER_STATE.LEFT then - player:setRotation3D(cc.vec3(curPos.x, curPos.y + 25 * dt, curPos.z)) + player:setRotation3D(ax.vec3(curPos.x, curPos.y + 25 * dt, curPos.z)) elseif self._playerState == PLAER_STATE.RIGHT then - player:setRotation3D(cc.vec3(curPos.x, curPos.y - 25 * dt, curPos.z)) + player:setRotation3D(ax.vec3(curPos.x, curPos.y - 25 * dt, curPos.z)) end - local normal = cc.vec3(0.0, 0.0, 0.0) + local normal = ax.vec3(0.0, 0.0, 0.0) local player_h, normal = self._terrain:getHeight(self:getPositionX(), self:getPositionZ(), normal) self:setPositionY(player_h + PLAYER_HEIGHT) --need to scriptfile - local q2 = cc.quaternion_createFromAxisAngle(cc.vec3(0, 1, 0), -math.pi) - local headingQ = cc.quaternion_createFromAxisAngle(self._headingAxis, self._headingAngle) + local q2 = ax.quaternion_createFromAxisAngle(ax.vec3(0, 1, 0), -math.pi) + local headingQ = ax.quaternion_createFromAxisAngle(self._headingAxis, self._headingAngle) local x = headingQ.w * q2.x + headingQ.x * q2.w + headingQ.y * q2.z - headingQ.z * q2.y local y = headingQ.w * q2.y - headingQ.x * q2.z + headingQ.y * q2.w + headingQ.z * q2.x local z = headingQ.w * q2.z + headingQ.x * q2.y - headingQ.y * q2.x + headingQ.z * q2.w local w = headingQ.w * q2.w - headingQ.x * q2.x - headingQ.y * q2.y - headingQ.z * q2.z - headingQ = cc.quaternion(x, y, z, w) + headingQ = ax.quaternion(x, y, z, w) self:setRotationQuat(headingQ) - local vec_offset = cc.vec4(camera_offset.x, camera_offset.y, camera_offset.z, 1) + local vec_offset = ax.vec4(camera_offset.x, camera_offset.y, camera_offset.z, 1) local transform = self:getNodeToWorldTransform() vec_offset = mat4_transformVector(transform, vec_offset) local playerPos = self:getPosition3D() - self._cam:setPosition3D(cc.vec3add(playerPos, camera_offset)) + self._cam:setPosition3D(ax.vec3add(playerPos, camera_offset)) self:updateState() end, 0) @@ -121,9 +121,9 @@ end function Player:updateState() if self._playerState == PLAER_STATE.FORWARD then - local player_pos = cc.p(self:getPositionX(),self:getPositionZ()) - local targetPos = cc.p(self._targetPos.x, self._targetPos.z) - local dist = cc.pGetDistance(player_pos, targetPos) + local player_pos = ax.p(self:getPositionX(),self:getPositionZ()) + local targetPos = ax.p(self._targetPos.x, self._targetPos.z) + local dist = ax.pGetDistance(player_pos, targetPos) if dist < 1 then self._playerState = PLAER_STATE.IDLE end @@ -131,7 +131,7 @@ function Player:updateState() end local TerrainWalkThru = class("TerrainWalkThru", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -160,11 +160,11 @@ function TerrainWalkThru:init() Helper.titleLabel:setString(self:title()) Helper.subtitleLabel:setString(self:subtitle()) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function (touches, event) @@ -172,44 +172,44 @@ function TerrainWalkThru:init() local location = touch:getLocationInView() if self._camera ~= nil then if self._player ~= nil then - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) - local dir = cc.vec3sub(farP, nearP) - dir = cc.vec3normalize(dir) + local dir = ax.vec3sub(farP, nearP) + dir = ax.vec3normalize(dir) - local collisionPoint = cc.vec3(-999,-999,-999) - local ray = cc.Ray:new(nearP, dir) + local collisionPoint = ax.vec3(-999,-999,-999) + local ray = ax.Ray:new(nearP, dir) local isInTerrain = true isInTerrain, collisionPoint = self._terrain:getIntersectionPoint(ray, collisionPoint) - if( not isInTerrain) then + if( not isInTerrain) then self._player._playerState = PLAER_STATE.IDLE return end local playerPos = self._player:getPosition3D() - dir = cc.vec3sub(collisionPoint, playerPos) + dir = ax.vec3sub(collisionPoint, playerPos) dir.y = 0 - dir = cc.vec3normalize(dir) + dir = ax.vec3normalize(dir) self._player._headingAngle = -1 * math.acos(-dir.z) - self._player._headingAxis = vec3_cross(dir, cc.vec3(0, 0, -1), self._player._headingAxis) + self._player._headingAxis = vec3_cross(dir, ax.vec3(0, 0, -1), self._player._headingAxis) self._player._targetPos = collisionPoint self._player._playerState = PLAER_STATE.FORWARD end end - end,cc.Handler.EVENT_TOUCHES_ENDED) + end,ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) - local visibleSize = cc.Director:getInstance():getVisibleSize() - self._camera = cc.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 200) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + local visibleSize = ax.Director:getInstance():getVisibleSize() + self._camera = ax.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 200) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(self._camera) local detailMapR = { _detailMapSrc = "TerrainTest/dirt.jpg", _detailMapSize = 35} @@ -218,7 +218,7 @@ function TerrainWalkThru:init() local detailMapA = { _detailMapSrc = "TerrainTest/GreenSkin.jpg", _detailMapSize = 20} local terrainData = { _heightMapSrc = "TerrainTest/heightmap16.jpg", _alphaMapSrc = "TerrainTest/alphamap.png" , _detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4, _mapHeight = 40.0, _mapScale = 2.0 } - self._terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT) + self._terrain = ax.Terrain:create(terrainData,ax.Terrain.CrackFixedType.SKIRT) self._terrain:setMaxDetailMapAmount(4) self._terrain:setCameraMask(2) self._terrain:setDrawWire(false) @@ -232,27 +232,27 @@ function TerrainWalkThru:init() self._player:setPositionY(self._terrain:getHeight(self._player:getPositionX(), self._player:getPositionZ()) + PLAYER_HEIGHT) --add Particle3D for test blend - local rootps = cc.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:setScale(30.0) rootps:startParticleSystem() self._player:addChild(rootps) --add BillBoard for test blend - local billboard = cc.BillBoard:create("Images/btn-play-normal.png") - billboard:setPosition3D(cc.vec3(0,180,0)) - billboard:setCameraMask(cc.CameraFlag.USER1) + local billboard = ax.BillBoard:create("Images/btn-play-normal.png") + billboard:setPosition3D(ax.vec3(0,180,0)) + billboard:setCameraMask(ax.CameraFlag.USER1) self._player:addChild(billboard) - local animation = cc.Animation3D:create("MeshRendererTest/girl.c3b","Take 001") + local animation = ax.Animation3D:create("MeshRendererTest/girl.c3b","Take 001") if nil ~= animation then - local animate = cc.Animate3D:create(animation) - self._player:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + self._player:runAction(ax.RepeatForever:create(animate)) end local playerPos = self._player:getPosition3D() - self._camera:setPosition3D(cc.vec3add(playerPos, camera_offset)) - self._camera:setRotation3D(cc.vec3(-45,0,0)) + self._camera:setPosition3D(ax.vec3add(playerPos, camera_offset)) + self._camera:setRotation3D(ax.vec3(-45,0,0)) self:addChild(self._player) self:addChild(self._terrain) @@ -269,7 +269,7 @@ function TerrainWalkThru:subtitle() end function TerrainWalkThru:extend() - + end ---------------------------------------- @@ -286,33 +286,33 @@ function Scene3DTest:create3DWorld() --add two Sprite3D monster, one is transparent local playerPos = self._player:getPosition3D() - local monster = cc.Sprite3D:create("MeshRendererTest/orc.c3b") - monster:setRotation3D(cc.vec3(0,180,0)) - monster:setPosition3D(cc.vec3(playerPos.x + 50, playerPos.y - 10, playerPos.z)) + local monster = ax.Sprite3D:create("MeshRendererTest/orc.c3b") + monster:setRotation3D(ax.vec3(0,180,0)) + monster:setPosition3D(ax.vec3(playerPos.x + 50, playerPos.y - 10, playerPos.z)) monster:setCameraMask(s_CM[GAME_LAYER.LAYER_GAME]) monster:setOpacity(128) self:addChild(monster) - monster = cc.Sprite3D:create("MeshRendererTest/orc.c3b") - monster:setRotation3D(cc.vec3(0,180,0)) - monster:setPosition3D(cc.vec3(playerPos.x - 50, playerPos.y - 5, playerPos.z)) + monster = ax.Sprite3D:create("MeshRendererTest/orc.c3b") + monster:setRotation3D(ax.vec3(0,180,0)) + monster:setPosition3D(ax.vec3(playerPos.x - 50, playerPos.y - 5, playerPos.z)) monster:setCameraMask(s_CM[GAME_LAYER.LAYER_GAME]) self:addChild(monster) --add a particle 3d above player - local rootps = cc.PUParticleSystem3D:create("Particle3D/scripts/blackHole.pu", "Particle3D/materials/pu_mediapack_01.material") + local rootps = ax.PUParticleSystem3D:create("Particle3D/scripts/blackHole.pu", "Particle3D/materials/pu_mediapack_01.material") rootps:setScale(2) - rootps:setPosition3D(cc.vec3(0, 150, 0)) + rootps:setPosition3D(ax.vec3(0, 150, 0)) rootps:setCameraMask(s_CM[GAME_LAYER.LAYER_GAME]) - local moveby = cc.MoveBy:create(2.0, cc.p(50.0, 0.0)) - local moveby1 = cc.MoveBy:create(2.0, cc.p(-50.0, 0.0)) - rootps:runAction(cc.RepeatForever:create(cc.Sequence:create(moveby, moveby1))) + local moveby = ax.MoveBy:create(2.0, ax.p(50.0, 0.0)) + local moveby1 = ax.MoveBy:create(2.0, ax.p(-50.0, 0.0)) + rootps:runAction(ax.RepeatForever:create(ax.Sequence:create(moveby, moveby1))) rootps:startParticleSystem() self._player:addChild(rootps, 0) --then, create skybox --create the second texture for cylinder - self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", + self._textureCube = ax.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", "MeshRendererTest/skybox/front.jpg", "MeshRendererTest/skybox/back.jpg") @@ -321,7 +321,7 @@ function Scene3DTest:create3DWorld() self._textureCube:setTexParameters(tRepeatParams) --add skybox - self._skyBox = cc.Skybox:create() + self._skyBox = ax.Skybox:create() self._skyBox:setCameraMask(s_CM[GAME_LAYER.LAYER_SKYBOX]) self._skyBox:setTexture(self._textureCube) self:addChild(self._skyBox) @@ -330,7 +330,7 @@ end function Scene3DTest:createUI() --add player button - local showLeftDlgItem = cc.MenuItemImage:create("Images/Pea.png", "Images/Pea.png") + local showLeftDlgItem = ax.MenuItemImage:create("Images/Pea.png", "Images/Pea.png") showLeftDlgItem:registerScriptTapHandler(function (tag, sender) if nil ~= self._playerDlg then self._playerDlg:setVisible(not self._playerDlg:isVisible()) @@ -339,56 +339,56 @@ function Scene3DTest:createUI() showLeftDlgItem:setPosition(VisibleRect:left().x + 30, VisibleRect:top().y - 30) local ttfConfig = { fontFilePath = "fonts/arial.ttf", fontSize = 20} - local descItem = cc.MenuItemLabel:create(cc.Label:createWithTTF(ttfConfig, "Description")) + local descItem = ax.MenuItemLabel:create(ax.Label:createWithTTF(ttfConfig, "Description")) descItem:registerScriptTapHandler(function(tag, sender) if nil ~= self._descDlg then self._descDlg:setVisible(not self._descDlg:isVisible()) end end) - descItem:setPosition(cc.p(VisibleRect:right().x - 50, VisibleRect:top().y - 25)) + descItem:setPosition(ax.p(VisibleRect:right().x - 50, VisibleRect:top().y - 25)) - local backItem = cc.MenuItemLabel:create(cc.Label:createWithTTF(ttfConfig, "Back")) - backItem:setPosition(cc.p(VisibleRect:right().x - 50, VisibleRect:bottom().y + 25)) + local backItem = ax.MenuItemLabel:create(ax.Label:createWithTTF(ttfConfig, "Back")) + backItem:setPosition(ax.p(VisibleRect:right().x - 50, VisibleRect:bottom().y + 25)) - local menu = cc.Menu:create(showLeftDlgItem, descItem) - menu:setPosition(cc.p(0.0, 0.0)) + local menu = ax.Menu:create(showLeftDlgItem, descItem) + menu:setPosition(ax.p(0.0, 0.0)) menu:setCameraMask(s_CM[GAME_LAYER.LAYER_UI], true) self:addChild(menu) end function Scene3DTest:createPlayerDlg() - cc.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) - - local dlgSize = cc.size(190, 240) + ax.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) + + local dlgSize = ax.size(190, 240) local pos = VisibleRect:center() local margin = 10 --first, create dialog ui part, include background, title and buttons self._playerDlg = ccui.Scale9Sprite:createWithSpriteFrameName("button_actived.png") self._playerDlg:setContentSize(dlgSize) - self._playerDlg:setAnchorPoint(cc.p(1, 0.5)) + self._playerDlg:setAnchorPoint(ax.p(1, 0.5)) pos.y = pos.y - margin pos.x = pos.x - margin self._playerDlg:setPosition(pos) --title - local title = cc.Label:createWithTTF("Player Dialog","fonts/arial.ttf",16) + local title = ax.Label:createWithTTF("Player Dialog","fonts/arial.ttf",16) title:setPosition(dlgSize.width / 2, dlgSize.height - margin * 2) self._playerDlg:addChild(title) --player background - local bgSize = cc.size(110, 180) - local bgPos = cc.p(margin, dlgSize.height / 2 - margin) + local bgSize = ax.size(110, 180) + local bgPos = ax.p(margin, dlgSize.height / 2 - margin) local playerBg = ccui.Scale9Sprite:createWithSpriteFrameName("item_bg.png") playerBg:setContentSize(bgSize) - playerBg:setAnchorPoint(cc.p(0, 0.5)) + playerBg:setAnchorPoint(ax.p(0, 0.5)) playerBg:setPosition(bgPos) self._playerDlg:addChild(playerBg) --item background and item - local itemSize = cc.size(48, 48) - local itemAnchor = cc.p(0, 1) - local itemPos = cc.p(bgPos.x + bgSize.width + margin, bgPos.y + bgSize.height / 2) + local itemSize = ax.size(48, 48) + local itemAnchor = ax.p(0, 1) + local itemPos = ax.p(bgPos.x + bgSize.width + margin, bgPos.y + bgSize.height / 2) local itemBg = ccui.Scale9Sprite:createWithSpriteFrameName("item_bg.png") itemBg:setContentSize(itemSize) itemBg:setAnchorPoint(itemAnchor) @@ -411,7 +411,7 @@ function Scene3DTest:createPlayerDlg() self:addChild(self._playerDlg) --second, add 3d actor, which on dialog layer - local girl = cc.Sprite3D:create("MeshRendererTest/girl.c3b") + local girl = ax.Sprite3D:create("MeshRendererTest/girl.c3b") girl:setScale(0.5) girl:setPosition(bgSize.width / 2, margin * 2) girl:setCameraMask(s_CM[GAME_LAYER.LAYER_ACTOR]) @@ -420,8 +420,8 @@ function Scene3DTest:createPlayerDlg() --third, add zoom in/out button, which is 2d ui element and over 3d actor local zoomIn = ccui.Button:create("cocosui/animationbuttonnormal.png","cocosui/animationbuttonpressed.png") zoomIn:setScale(0.5) - zoomIn:setAnchorPoint(cc.p(1, 1)) - zoomIn:setPosition(cc.p(bgSize.width / 2 - margin / 2, bgSize.height - margin)) + zoomIn:setAnchorPoint(ax.p(1, 1)) + zoomIn:setPosition(ax.p(bgSize.width / 2 - margin / 2, bgSize.height - margin)) zoomIn:addClickEventListener(function(sender) girl:setScale(girl:getScale() * 2) end) @@ -431,8 +431,8 @@ function Scene3DTest:createPlayerDlg() local zoomOut = ccui.Button:create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png") zoomOut:setScale(0.5) - zoomOut:setAnchorPoint(cc.p(0, 1)) - zoomOut:setPosition(cc.p(bgSize.width / 2 + margin / 2, bgSize.height - margin)) + zoomOut:setAnchorPoint(ax.p(0, 1)) + zoomOut:setPosition(ax.p(bgSize.width / 2 + margin / 2, bgSize.height - margin)) zoomOut:addClickEventListener(function(sender) girl:setScale(girl:getScale() / 2) end) @@ -442,26 +442,26 @@ function Scene3DTest:createPlayerDlg() end function Scene3DTest:createDetailDlg() - cc.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) - - local dlgSize = cc.size(190, 240) + ax.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) + + local dlgSize = ax.size(190, 240) local pos = VisibleRect:center() local margin = 10 - + --create dialog self._detailDlg = ccui.Scale9Sprite:createWithSpriteFrameName("button_actived.png") self._detailDlg:setContentSize(dlgSize) - self._detailDlg:setAnchorPoint(cc.p(0, 0.5)) + self._detailDlg:setAnchorPoint(ax.p(0, 0.5)) self._detailDlg:setOpacity(224) pos.y = pos.y - margin pos.x = pos.x + margin self._detailDlg:setPosition(pos) -- title - local title = cc.Label:createWithTTF("Detail Dialog","fonts/arial.ttf",16) + local title = ax.Label:createWithTTF("Detail Dialog","fonts/arial.ttf",16) title:setPosition(dlgSize.width / 2, dlgSize.height - margin * 2) self._detailDlg:addChild(title) - + -- add a spine ffd animation on it -- TODO coulsonwang: spine is not enable in V4.0 -- local skeletonNode = sp.SkeletonAnimation:create("spine/goblins-pro.json", "spine/goblins.atlas", 1.5) @@ -469,11 +469,11 @@ function Scene3DTest:createDetailDlg() -- skeletonNode:setSkin("goblin") -- -- skeletonNode:setScale(0.25) --- local windowSize = cc.Director:getInstance():getWinSize() --- skeletonNode:setPosition(cc.p(dlgSize.width / 2, 20)) +-- local windowSize = ax.Director:getInstance():getWinSize() +-- skeletonNode:setPosition(ax.p(dlgSize.width / 2, 20)) -- self._detailDlg:addChild(skeletonNode) - local listener = cc.EventListenerTouchOneByOne:create() + local listener = ax.EventListenerTouchOneByOne:create() listener:registerScriptHandler(function (touch, event) -- if (not skeletonNode:getDebugBonesEnabled()) then -- skeletonNode:setDebugBonesEnabled(true) @@ -485,7 +485,7 @@ function Scene3DTest:createDetailDlg() -- end return true - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -496,12 +496,12 @@ function Scene3DTest:createDetailDlg() end function Scene3DTest:createDescDlg() - cc.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) - - local dlgSize = cc.size(440, 240) + ax.SpriteFrameCache:getInstance():addSpriteFrames(s_s9s_ui_plist) + + local dlgSize = ax.size(440, 240) local pos = VisibleRect:center() local margin = 10 - + --create dialog self._descDlg = ccui.Scale9Sprite:createWithSpriteFrameName("button_actived.png") self._descDlg:setContentSize(dlgSize) @@ -509,12 +509,12 @@ function Scene3DTest:createDescDlg() self._descDlg:setPosition(pos) --title - local title = cc.Label:createWithTTF("Description Dialog","fonts/arial.ttf",16) + local title = ax.Label:createWithTTF("Description Dialog","fonts/arial.ttf",16) title:setPosition(dlgSize.width / 2, dlgSize.height - margin * 2) self._descDlg:addChild(title) --add a label to retain description text - local textSize = cc.size(400, 220) + local textSize = ax.size(400, 220) local desc = "Scene 3D test for 2D and 3D mix rendering.\n" .. "\n" .. "- Game world composite with terrain, skybox and 3D objects.\n" .. @@ -527,11 +527,11 @@ function Scene3DTest:createDescDlg() "\n" .. "Click \"Description\" button to hide this dialog.\n" - local text = cc.Label:createWithSystemFont(desc, "Helvetica", 12, textSize) - text:setAnchorPoint(cc.p(0, 1)) + local text = ax.Label:createWithSystemFont(desc, "Helvetica", 12, textSize) + text:setAnchorPoint(ax.p(0, 1)) text:setPosition(margin, dlgSize.height - (20 + margin)) self._descDlg:addChild(text) - + --after add ui element, add dialog to scene self._descDlg:setCameraMask(s_CM[GAME_LAYER.LAYER_OSD]) self:addChild(self._descDlg) @@ -543,17 +543,17 @@ function Scene3DTest:extend() self._descDlg = nil self._gameCameras = {nil, nil, nil, nil, nil, nil} - cc.Director:getInstance():setDisplayStats(false) + ax.Director:getInstance():setDisplayStats(false) local ca = nil - local visibleSize = cc.Director:getInstance():getVisibleSize() + local visibleSize = ax.Director:getInstance():getVisibleSize() --first, create a camera to look the skybox - ca = cc.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) - ca:setPosition3D(cc.vec3(0.0, 0.0, 50.0)) + ca = ax.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) + ca:setPosition3D(ax.vec3(0.0, 0.0, 50.0)) ca:setCameraFlag(s_CF[GAME_LAYER.LAYER_SKYBOX]) ca:setDepth(GAME_LAYER.LAYER_SKYBOX) self._gameCameras[GAME_LAYER.LAYER_SKYBOX] = ca - self:addChild(ca) + self:addChild(ca) -- second, create a camera to look the 3D game scene -- it has been create in TerrainWalkThru:init @@ -563,28 +563,28 @@ function Scene3DTest:extend() self._gameCameras[GAME_LAYER.LAYER_GAME] = ca --third, use the default camera to look 2D base UI layer - local scene = cc.Director:getInstance():getRunningScene() + local scene = ax.Director:getInstance():getRunningScene() ca = scene:getDefaultCamera() ca:setCameraFlag(s_CF[GAME_LAYER.LAYER_UI]) ca:setDepth(GAME_LAYER.LAYER_UI) self._gameCameras[GAME_LAYER.LAYER_UI] = ca --forth, create a camera to look the 3D model in dialogs - ca = cc.Camera:create() + ca = ax.Camera:create() ca:setCameraFlag(s_CF[GAME_LAYER.LAYER_ACTOR]) ca:setDepth(GAME_LAYER.LAYER_ACTOR) self._gameCameras[GAME_LAYER.LAYER_ACTOR] = ca self:addChild(ca) -- fifth, create a camera to look the UI element over on the 3D models - ca = cc.Camera:create() + ca = ax.Camera:create() ca:setCameraFlag(s_CF[GAME_LAYER.LAYER_ZOOM]) ca:setDepth(GAME_LAYER.LAYER_ZOOM) self._gameCameras[GAME_LAYER.LAYER_ZOOM] = ca self:addChild(ca) --sixth, create a camera to look the OSD UI - ca = cc.Camera:create() + ca = ax.Camera:create() ca:setCameraFlag(s_CF[GAME_LAYER.LAYER_OSD]) ca:setDepth(GAME_LAYER.LAYER_OSD) self._gameCameras[GAME_LAYER.LAYER_OSD] = ca @@ -609,16 +609,16 @@ function Scene3DTest:subtitle() end function Scene3DTest:onExit() - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - if targetPlatform == cc.PLATFORM_OS_ANDROID or targetPlatform == cc.PLATFORM_OS_WINRT or targetPlatform == cc.PLATFORM_OS_WP8 then - cc.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + if targetPlatform == ax.PLATFORM_OS_ANDROID or targetPlatform == ax.PLATFORM_OS_WINRT or targetPlatform == ax.PLATFORM_OS_WP8 then + ax.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) end end function Scene3DTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { diff --git a/tests/lua-tests/Content/src/SceneTest/SceneTest.lua b/tests/lua-tests/Content/src/SceneTest/SceneTest.lua index 6621cc17973a..3df08a8c4a08 100644 --- a/tests/lua-tests/Content/src/SceneTest/SceneTest.lua +++ b/tests/lua-tests/Content/src/SceneTest/SceneTest.lua @@ -16,22 +16,22 @@ local SceneTestLayer3 = nil -------------------------------------------------------------------- SceneTestLayer1 = function() - local ret = cc.Layer:create() + local ret = ax.Layer:create() local function onPushScene(tag, pSender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = SceneTestLayer2() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():pushScene( scene ) + ax.Director:getInstance():pushScene( scene ) end local function onPushSceneTran(tag, pSender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = SceneTestLayer2() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():pushScene( cc.TransitionSlideInT:create(1, scene) ) + ax.Director:getInstance():pushScene( ax.TransitionSlideInT:create(1, scene) ) end @@ -39,24 +39,24 @@ SceneTestLayer1 = function() cclog("onQuit") end - local item1 = cc.MenuItemFont:create( "Test pushScene") + local item1 = ax.MenuItemFont:create( "Test pushScene") item1:registerScriptTapHandler(onPushScene) - local item2 = cc.MenuItemFont:create( "Test pushScene w/transition") + local item2 = ax.MenuItemFont:create( "Test pushScene w/transition") item2:registerScriptTapHandler(onPushSceneTran) - local item3 = cc.MenuItemFont:create( "Quit") + local item3 = ax.MenuItemFont:create( "Quit") item3:registerScriptTapHandler(onQuit) - local menu = cc.Menu:create(item1, item2, item3) + local menu = ax.Menu:create(item1, item2, item3) menu:alignItemsVertically() ret:addChild( menu ) - local s = cc.Director:getInstance():getWinSize() - local sprite = cc.Sprite:create(s_pPathGrossini) + local s = ax.Director:getInstance():getWinSize() + local sprite = ax.Sprite:create(s_pPathGrossini) ret:addChild(sprite) - sprite:setPosition( cc.p(s.width-40, s.height/2) ) - local rotate = cc.RotateBy:create(2, 360) - local repeatAction = cc.RepeatForever:create(rotate) + sprite:setPosition( ax.p(s.width-40, s.height/2) ) + local rotate = ax.RotateBy:create(2, 360) + local repeatAction = ax.RepeatForever:create(rotate) sprite:runAction(repeatAction) local function onNodeEvent(event) @@ -78,47 +78,47 @@ end -------------------------------------------------------------------- SceneTestLayer2 = function() - local ret = cc.Layer:create() + local ret = ax.Layer:create() local m_timeCounter = 0 local function onGoBack(tag, pSender) - cc.Director:getInstance():popScene() + ax.Director:getInstance():popScene() end local function onReplaceScene(tag, pSender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = SceneTestLayer3() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene( scene ) + ax.Director:getInstance():replaceScene( scene ) end local function onReplaceSceneTran(tag, pSender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = SceneTestLayer3() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene( cc.TransitionFlipX:create(2, scene) ) + ax.Director:getInstance():replaceScene( ax.TransitionFlipX:create(2, scene) ) end - local item1 = cc.MenuItemFont:create( "replaceScene") + local item1 = ax.MenuItemFont:create( "replaceScene") item1:registerScriptTapHandler(onReplaceScene) - local item2 = cc.MenuItemFont:create( "replaceScene w/transition") + local item2 = ax.MenuItemFont:create( "replaceScene w/transition") item2:registerScriptTapHandler(onReplaceSceneTran) - local item3 = cc.MenuItemFont:create( "Go Back") + local item3 = ax.MenuItemFont:create( "Go Back") item3:registerScriptTapHandler(onGoBack) - local menu = cc.Menu:create(item1, item2, item3) + local menu = ax.Menu:create(item1, item2, item3) menu:alignItemsVertically() ret:addChild( menu ) - local s = cc.Director:getInstance():getWinSize() - local sprite = cc.Sprite:create(s_pPathGrossini) + local s = ax.Director:getInstance():getWinSize() + local sprite = ax.Sprite:create(s_pPathGrossini) ret:addChild(sprite) - sprite:setPosition( cc.p(s.width-40, s.height/2) ) - local rotate = cc.RotateBy:create(2, 360) - local repeat_action = cc.RepeatForever:create(rotate) + sprite:setPosition( ax.p(s.width-40, s.height/2) ) + local rotate = ax.RotateBy:create(2, 360) + local repeat_action = ax.RepeatForever:create(rotate) sprite:runAction(repeat_action) return ret @@ -131,39 +131,39 @@ end -------------------------------------------------------------------- SceneTestLayer3 = function() - local ret = cc.LayerColor:create(cc.c4b(0,0,255,255)) - local s = cc.Director:getInstance():getWinSize() + local ret = ax.LayerColor:create(ax.color32(0,0,255,255)) + local s = ax.Director:getInstance():getWinSize() local function item0Clicked(tag, pSender) - local newScene = cc.Scene:create() + local newScene = ax.Scene:create() newScene:addChild(SceneTestLayer3()) - cc.Director:getInstance():pushScene(cc.TransitionFade:create(0.5, newScene, cc.c3b(0,255,255))) + ax.Director:getInstance():pushScene(ax.TransitionFade:create(0.5, newScene, ax.color32(0,255,255))) end local function item1Clicked(tag, pSender) - cc.Director:getInstance():popScene() + ax.Director:getInstance():popScene() end local function item2Clicked(tag, pSender) - cc.Director:getInstance():popToRootScene() + ax.Director:getInstance():popToRootScene() end - local item0 = cc.MenuItemFont:create("Touch to pushScene (self)") + local item0 = ax.MenuItemFont:create("Touch to pushScene (self)") item0:registerScriptTapHandler(item0Clicked) - local item1 = cc.MenuItemFont:create("Touch to popScene") + local item1 = ax.MenuItemFont:create("Touch to popScene") item1:registerScriptTapHandler(item1Clicked) - local item2 = cc.MenuItemFont:create("Touch to popToRootScene") + local item2 = ax.MenuItemFont:create("Touch to popToRootScene") item2:registerScriptTapHandler(item2Clicked) - local menu = cc.Menu:create(item0, item1, item2) + local menu = ax.Menu:create(item0, item1, item2) ret:addChild(menu) menu:alignItemsVertically() - local sprite = cc.Sprite:create(s_pPathGrossini) + local sprite = ax.Sprite:create(s_pPathGrossini) ret:addChild(sprite) - sprite:setPosition( cc.p(s.width/2, 40) ) - local rotate = cc.RotateBy:create(2, 360) - local repeatAction = cc.RepeatForever:create(rotate) + sprite:setPosition( ax.p(s.width/2, 40) ) + local rotate = ax.RotateBy:create(2, 360) + local repeatAction = ax.RepeatForever:create(rotate) sprite:runAction(repeatAction) return ret end @@ -172,7 +172,7 @@ end function SceneTestMain() cclog("SceneTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = SceneTestLayer1() scene:addChild(layer, 0) scene:addChild(CreateBackMenuItem()) diff --git a/tests/lua-tests/Content/src/SpineTest/SpineTest.lua b/tests/lua-tests/Content/src/SpineTest/SpineTest.lua index 49d825752e5a..67752bc9fc0f 100644 --- a/tests/lua-tests/Content/src/SpineTest/SpineTest.lua +++ b/tests/lua-tests/Content/src/SpineTest/SpineTest.lua @@ -1,7 +1,7 @@ require "axmol.spine.SpineConstants" local SpineTestLayerNormal = class("SpineTestLayerNormal",function() - return cc.Layer:create() + return ax.Layer:create() end) function SpineTestLayerNormal:ctor() @@ -20,29 +20,29 @@ function SpineTestLayerNormal:init() skeletonNode:setScale(0.5) skeletonNode:registerSpineEventHandler(function (event) - print(string.format("[spine] %d start: %s", + print(string.format("[spine] %d start: %s", event.trackIndex, event.animation)) end, sp.EventType.ANIMATION_START) skeletonNode:registerSpineEventHandler(function (event) - print(string.format("[spine] %d end:", + print(string.format("[spine] %d end:", event.trackIndex)) end, sp.EventType.ANIMATION_END) - + skeletonNode:registerSpineEventHandler(function (event) - print(string.format("[spine] %d complete: %d", + print(string.format("[spine] %d complete: %d", event.trackIndex, event.loopCount)) end, sp.EventType.ANIMATION_COMPLETE) skeletonNode:registerSpineEventHandler(function (event) - print(string.format("[spine] %d event: %s, %d, %f, %s", + print(string.format("[spine] %d event: %s, %d, %f, %s", event.trackIndex, event.eventData.name, event.eventData.intValue, event.eventData.floatValue, - event.eventData.stringValue)) + event.eventData.stringValue)) end, sp.EventType.ANIMATION_EVENT) skeletonNode:setMix("walk", "jump", 0.2) @@ -52,11 +52,11 @@ function SpineTestLayerNormal:init() skeletonNode:addAnimation(0, "jump", false, 3) skeletonNode:addAnimation(0, "run", true) - local windowSize = cc.Director:getInstance():getWinSize() - skeletonNode:setPosition(cc.p(windowSize.width / 2, 20)) + local windowSize = ax.Director:getInstance():getWinSize() + skeletonNode:setPosition(ax.p(windowSize.width / 2, 20)) self:addChild(skeletonNode) - local listener = cc.EventListenerTouchOneByOne:create() + local listener = ax.EventListenerTouchOneByOne:create() listener:registerScriptHandler(function (touch, event) if not skeletonNode:getDebugBonesEnabled() then skeletonNode:setDebugBonesEnabled(true) @@ -68,7 +68,7 @@ function SpineTestLayerNormal:init() end return true - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -83,7 +83,7 @@ end ---- local SpineTestLayerFFD = class("SpineTestLayerFFD",function() - return cc.Layer:create() + return ax.Layer:create() end) function SpineTestLayerFFD:ctor() @@ -101,13 +101,13 @@ function SpineTestLayerFFD:init() skeletonNode = sp.SkeletonAnimation:create("spine/goblins-pro.json", "spine/goblins.atlas", 1.5) skeletonNode:setAnimation(0, "walk", true) skeletonNode:setSkin("goblin") - + skeletonNode:setScale(0.5) - local windowSize = cc.Director:getInstance():getWinSize() - skeletonNode:setPosition(cc.p(windowSize.width / 2, 20)) + local windowSize = ax.Director:getInstance():getWinSize() + skeletonNode:setPosition(ax.p(windowSize.width / 2, 20)) self:addChild(skeletonNode) - - local listener = cc.EventListenerTouchOneByOne:create() + + local listener = ax.EventListenerTouchOneByOne:create() listener:registerScriptHandler(function (touch, event) if not skeletonNode:getDebugBonesEnabled() then skeletonNode:setDebugBonesEnabled(true) @@ -119,7 +119,7 @@ function SpineTestLayerFFD:init() end return true - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -134,9 +134,9 @@ end function SpineTestMain() cclog("SpineTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { SpineTestLayerNormal.create, SpineTestLayerFFD.create, diff --git a/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua b/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua index 7ba361683834..7f7c44e3bc77 100644 --- a/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua +++ b/tests/lua-tests/Content/src/Sprite3DTest/Sprite3DTest.lua @@ -1,8 +1,8 @@ require "axmol.3d.3dConstants" -local size = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() -local attributeNames = +local size = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() +local attributeNames = { "a_position", "a_color", @@ -34,41 +34,41 @@ function Sprite3DBasicTest.onTouchesEnd(touches, event) end function Sprite3DBasicTest.addNewSpriteWithCoords(parent,x,y) - local sprite = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite:setScale(3.0) sprite:setTexture("MeshRendererTest/boss.png") parent:addChild(sprite) - sprite:setPosition(cc.p(x,y)) + sprite:setPosition(ax.p(x,y)) local random = math.random() local action = nil if random < 0.2 then - action = cc.ScaleBy:create(3,2) + action = ax.ScaleBy:create(3,2) elseif random < 0.4 then - action = cc.RotateBy:create(3, 360) + action = ax.RotateBy:create(3, 360) elseif random < 0.6 then - action = cc.Blink:create(1, 3) + action = ax.Blink:create(1, 3) elseif random < 0.8 then - action = cc.TintBy:create(2, 0, -255, -255) + action = ax.TintBy:create(2, 0, -255, -255) else - action = cc.FadeOut:create(2) + action = ax.FadeOut:create(2) end local action_back = action:reverse() - local seq = cc.Sequence:create(action, action_back) + local seq = ax.Sequence:create(action, action_back) - sprite:runAction(cc.RepeatForever:create(seq)) + sprite:runAction(ax.RepeatForever:create(seq)) end function Sprite3DBasicTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Testing Sprite3D") Helper.subtitleLabel:setString("Tap screen to add more sprites") - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(Sprite3DBasicTest.onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(Sprite3DBasicTest.onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -84,51 +84,51 @@ local Sprite3DHitTest = {} Sprite3DHitTest.__index = Sprite3DHitTest function Sprite3DHitTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Testing Sprite3D Touch in 2D") Helper.subtitleLabel:setString("Tap Sprite3D and Drag") - local sprite1 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite1 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite1:setScale(4.0) sprite1:setTexture("MeshRendererTest/boss.png") - sprite1:setPosition( cc.p(size.width/2, size.height/2) ) - sprite1:runAction(cc.RepeatForever:create(cc.RotateBy:create(3, 360))) + sprite1:setPosition( ax.p(size.width/2, size.height/2) ) + sprite1:runAction(ax.RepeatForever:create(ax.RotateBy:create(3, 360))) layer:addChild(sprite1) - local sprite2 = cc.Sprite3D:create("MeshRendererTest/boss1.obj") + local sprite2 = ax.Sprite3D:create("MeshRendererTest/boss1.obj") sprite2:setScale(4.0) sprite2:setTexture("MeshRendererTest/boss.png") - sprite2:setPosition( cc.p(size.width/2, size.height/2) ) - sprite2:setAnchorPoint(cc.p(0.5, 0.5)) - sprite2:runAction(cc.RepeatForever:create(cc.RotateBy:create(3, -360))) + sprite2:setPosition( ax.p(size.width/2, size.height/2) ) + sprite2:setAnchorPoint(ax.p(0.5, 0.5)) + sprite2:runAction(ax.RepeatForever:create(ax.RotateBy:create(3, -360))) layer:addChild(sprite2) - local listener = cc.EventListenerTouchOneByOne:create() + local listener = ax.EventListenerTouchOneByOne:create() listener:setSwallowTouches(true) listener:registerScriptHandler(function (touch, event) local target = event:getCurrentTarget() local rect = target:getBoundingBox() - if cc.rectContainsPoint(rect, touch:getLocation()) then + if ax.rectContainsPoint(rect, touch:getLocation()) then print(string.format("sprite3d began... x = %f, y = %f", touch:getLocation().x, touch:getLocation().y)) target:setOpacity(100) return true end return false - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) listener:registerScriptHandler(function (touch, event) local target = event:getCurrentTarget() local x,y = target:getPosition() - target:setPosition(cc.p(x + touch:getDelta().x, y + touch:getDelta().y)) - end, cc.Handler.EVENT_TOUCH_MOVED) + target:setPosition(ax.p(x + touch:getDelta().x, y + touch:getDelta().y)) + end, ax.Handler.EVENT_TOUCH_MOVED) listener:registerScriptHandler(function (touch, event) local target = event:getCurrentTarget() print("sprite3d onTouchEnd") target:setOpacity(255) - end, cc.Handler.EVENT_TOUCH_ENDED) + end, ax.Handler.EVENT_TOUCH_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, sprite1) @@ -142,7 +142,7 @@ end ---------------------------------------- local Sprite3DWithSkinTest = {} Sprite3DWithSkinTest.__index = Sprite3DWithSkinTest -Sprite3DWithSkinTest._animateQuality = cc.Animate3DQuality.QUALITY_HIGH +Sprite3DWithSkinTest._animateQuality = ax.Animate3DQuality.QUALITY_HIGH Sprite3DWithSkinTest._sprites = {} function Sprite3DWithSkinTest.onTouchesEnd(touches, event) @@ -153,16 +153,16 @@ function Sprite3DWithSkinTest.onTouchesEnd(touches, event) end function Sprite3DWithSkinTest.addNewSpriteWithCoords(parent,x,y) - local sprite = cc.Sprite3D:create("MeshRendererTest/orc.c3b") + local sprite = ax.Sprite3D:create("MeshRendererTest/orc.c3b") sprite:setScale(3) sprite:setRotation3D({x = 0, y = 180, z = 0}) - sprite:setPosition(cc.p(x, y)) + sprite:setPosition(ax.p(x, y)) parent:addChild(sprite) table.insert(Sprite3DWithSkinTest._sprites, sprite) - local animation = cc.Animation3D:create("MeshRendererTest/orc.c3b") + local animation = ax.Animation3D:create("MeshRendererTest/orc.c3b") if nil ~= animation then - local animate = cc.Animate3D:create(animation) + local animate = ax.Animate3D:create(animation) local inverse = false if math.random() == 0 then inverse = true @@ -172,7 +172,7 @@ function Sprite3DWithSkinTest.addNewSpriteWithCoords(parent,x,y) local speed = 1.0 if rand2 < 1/3 then - speed = animate:getSpeed() + math.random() + speed = animate:getSpeed() + math.random() elseif rand2 < 2/3 then speed = animate:getSpeed() - 0.5 * math.random() end @@ -184,42 +184,42 @@ function Sprite3DWithSkinTest.addNewSpriteWithCoords(parent,x,y) end animate:setTag(110) animate:setQuality(Sprite3DWithSkinTest._animateQuality) - local repeatAction = cc.RepeatForever:create(animate) + local repeatAction = ax.RepeatForever:create(animate) repeatAction:setTag(110) sprite:runAction(repeatAction) end end function Sprite3DWithSkinTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Testing Sprite3D for animation from c3t") Helper.subtitleLabel:setString("Tap screen to add more sprite3D") - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(Sprite3DWithSkinTest.onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(Sprite3DWithSkinTest.onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) Sprite3DWithSkinTest._sprites = {} Sprite3DWithSkinTest.addNewSpriteWithCoords(layer, size.width / 2, size.height / 2) - - cc.MenuItemFont:setFontName("fonts/arial.ttf") - cc.MenuItemFont:setFontSize(15) - local menuItem = cc.MenuItemFont:create("High Quality") - Sprite3DWithSkinTest._animateQuality = cc.Animate3DQuality.QUALITY_HIGH + + ax.MenuItemFont:setFontName("fonts/arial.ttf") + ax.MenuItemFont:setFontSize(15) + local menuItem = ax.MenuItemFont:create("High Quality") + Sprite3DWithSkinTest._animateQuality = ax.Animate3DQuality.QUALITY_HIGH menuItem:registerScriptTapHandler(function(tag, sender) Sprite3DWithSkinTest._animateQuality = Sprite3DWithSkinTest._animateQuality + 1 - if Sprite3DWithSkinTest._animateQuality > cc.Animate3DQuality.QUALITY_HIGH then - Sprite3DWithSkinTest._animateQuality = cc.Animate3DQuality.QUALITY_NONE + if Sprite3DWithSkinTest._animateQuality > ax.Animate3DQuality.QUALITY_HIGH then + Sprite3DWithSkinTest._animateQuality = ax.Animate3DQuality.QUALITY_NONE end - if Sprite3DWithSkinTest._animateQuality == cc.Animate3DQuality.QUALITY_NONE then + if Sprite3DWithSkinTest._animateQuality == ax.Animate3DQuality.QUALITY_NONE then menuItem:setString("None Quality") - elseif Sprite3DWithSkinTest._animateQuality == cc.Animate3DQuality.QUALITY_LOW then + elseif Sprite3DWithSkinTest._animateQuality == ax.Animate3DQuality.QUALITY_LOW then menuItem:setString("Low Quality") - elseif Sprite3DWithSkinTest._animateQuality == cc.Animate3DQuality.QUALITY_HIGH then + elseif Sprite3DWithSkinTest._animateQuality == ax.Animate3DQuality.QUALITY_HIGH then menuItem:setString("High Quality") end @@ -229,8 +229,8 @@ function Sprite3DWithSkinTest.create() animate3D:setQuality(Sprite3DWithSkinTest._animateQuality) end end) - local menu = cc.Menu:create(menuItem) - menu:setPosition(cc.p(0.0, 0.0)) + local menu = ax.Menu:create(menuItem) + menu:setPosition(ax.p(0.0, 0.0)) menuItem:setPosition(VisibleRect:left().x + 50, VisibleRect:top().y -70) layer:addChild(menu, 1) @@ -241,7 +241,7 @@ end ---------------------------------------- ----Animate3DTest ---------------------------------------- -local State = +local State = { SWIMMING = 0, SWIMMING_TO_HURT = 1, @@ -281,12 +281,12 @@ function Animate3DTest:onEnter() for i = 1,#(touches) do local location = touches[i]:getLocation() if self._sprite ~= nil then - local len = cc.pGetLength(cc.pSub(cc.p(self._sprite:getPosition()), location)) + local len = ax.pGetLength(ax.pSub(ax.p(self._sprite:getPosition()), location)) if len < 40 then if self._state == State.SWIMMING then self._sprite:runAction(self._hurt) - local delay = cc.DelayTime:create(self._hurt:getDuration() - 0.1) - local seq = cc.Sequence:create(delay, cc.CallFunc:create(renewCallBack)) + local delay = ax.DelayTime:create(self._hurt:getDuration() - 0.1) + local seq = ax.Sequence:create(delay, ax.CallFunc:create(renewCallBack)) seq:setTag(101) self._sprite:runAction(seq) self._state = State.SWIMMING_TO_HURT @@ -294,13 +294,13 @@ function Animate3DTest:onEnter() return end end - end + end end self:addSprite3D() - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -309,7 +309,7 @@ function Animate3DTest:onEnter() if self._state == State.HURT_TO_SWIMMING then self._elapseTransTime = self._elapseTransTime + dt local t = self._elapseTransTime / self._transTime - + if t >= 1.0 then t = 1.0 self._sprite:stopAction(self._hurt) @@ -342,48 +342,48 @@ end function Animate3DTest:addSprite3D() -- body local fileName = "MeshRendererTest/tortoise.c3b" - local sprite = cc.Sprite3D:create(fileName) + local sprite = ax.Sprite3D:create(fileName) sprite:setScale(0.1) - local winSize = cc.Director:getInstance():getWinSize() - sprite:setPosition(cc.p(winSize.width * 4.0 / 5.0, winSize.height / 2.0)) + local winSize = ax.Director:getInstance():getWinSize() + sprite:setPosition(ax.p(winSize.width * 4.0 / 5.0, winSize.height / 2.0)) self:addChild(sprite) self._sprite = sprite - local animation = cc.Animation3D:create(fileName) + local animation = ax.Animation3D:create(fileName) if nil ~= animation then - local animate = cc.Animate3D:create(animation, 0.0, 1.933) - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation, 0.0, 1.933) + sprite:runAction(ax.RepeatForever:create(animate)) self._swim = animate self._swim:retain() - self._hurt = cc.Animate3D:create(animation, 1.933, 2.8) + self._hurt = ax.Animate3D:create(animation, 1.933, 2.8) self._hurt:retain() self._state = State.SWIMMING end - self._moveAction = cc.MoveTo:create(4.0, cc.p(winSize.width / 5.0, winSize.height / 2.0)) + self._moveAction = ax.MoveTo:create(4.0, ax.p(winSize.width / 5.0, winSize.height / 2.0)) self._moveAction:retain() local function reachEndCallBack() - local winSize = cc.Director:getInstance():getWinSize() + local winSize = ax.Director:getInstance():getWinSize() self._sprite:stopActionByTag(100) - local inverse = cc.MoveTo:create(4.0, cc.p(winSize.width - self._sprite:getPositionX(), winSize.height / 2.0)) + local inverse = ax.MoveTo:create(4.0, ax.p(winSize.width - self._sprite:getPositionX(), winSize.height / 2.0)) inverse:retain() self._moveAction:release() self._moveAction = inverse - local rot = cc.RotateBy:create(1.0, { x = 0.0, y = 180.0, z = 0.0}) - local seq = cc.Sequence:create(rot, self._moveAction, cc.CallFunc:create(reachEndCallBack)) + local rot = ax.RotateBy:create(1.0, { x = 0.0, y = 180.0, z = 0.0}) + local seq = ax.Sequence:create(rot, self._moveAction, ax.CallFunc:create(reachEndCallBack)) seq:setTag(100) self._sprite:runAction(seq) end - local seq = cc.Sequence:create(self._moveAction, cc.CallFunc:create(reachEndCallBack)) + local seq = ax.Sequence:create(self._moveAction, ax.CallFunc:create(reachEndCallBack)) seq:setTag(100) sprite:runAction(seq) end function Animate3DTest.create() - local layer = Animate3DTest.extend(cc.Layer:create()) + local layer = Animate3DTest.extend(ax.Layer:create()) if nil ~= layer then Helper.initWithLayer(layer) @@ -410,7 +410,7 @@ local AttachmentTest = {} AttachmentTest.__index = AttachmentTest function AttachmentTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Testing Sprite3D Attachment") Helper.subtitleLabel:setString("touch to switch weapon") @@ -420,39 +420,39 @@ function AttachmentTest.create() local function addNewSpriteWithCoords(pos) local fileName = "MeshRendererTest/orc.c3b" - local sprite = cc.Sprite3D:create(fileName) + local sprite = ax.Sprite3D:create(fileName) sprite:setScale(5) sprite:setRotation3D({x = 0, y =180, z = 0}) layer:addChild(sprite) - sprite:setPosition( cc.p( pos.x, pos.y) ) - + sprite:setPosition( ax.p( pos.x, pos.y) ) + --test attach - local sp = cc.Sprite3D:create("MeshRendererTest/axe.c3b") + local sp = ax.Sprite3D:create("MeshRendererTest/axe.c3b") sprite:getAttachNode("Bip001 R Hand"):addChild(sp) - - local animation = cc.Animation3D:create(fileName) + + local animation = ax.Animation3D:create(fileName) if nil ~=animation then - local animate = cc.Animate3D:create(animation) - sprite:runAction(cc.RepeatForever:create(animate)) - end + local animate = ax.Animate3D:create(animation) + sprite:runAction(ax.RepeatForever:create(animate)) + end _sprite = sprite _hasWeapon = true end - addNewSpriteWithCoords(cc.p(size.width / 2, size.height / 2)) + addNewSpriteWithCoords(ax.p(size.width / 2, size.height / 2)) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) if _hasWeapon then _sprite:removeAllAttachNode() else - local sp = cc.Sprite3D:create("MeshRendererTest/axe.c3b") + local sp = ax.Sprite3D:create("MeshRendererTest/axe.c3b") _sprite:getAttachNode("Bip001 R Hand"):addChild(sp) end _hasWeapon = not _hasWeapon - end,cc.Handler.EVENT_TOUCHES_ENDED) + end,ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -485,14 +485,14 @@ function Sprite3DReskinTest:init() self._useShoesId = 0 self._girlHair = {} self._useHairId = 0 - self._sprite = nil + self._sprite = nil - self:addNewSpriteWithCoords(cc.p(size.width / 2, size.height / 2)) + self:addNewSpriteWithCoords(ax.p(size.width / 2, size.height / 2)) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) - - end,cc.Handler.EVENT_TOUCHES_ENDED) + + end,ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) @@ -501,8 +501,8 @@ function Sprite3DReskinTest:init() ttfConfig.fontFilePath = "fonts/arial.ttf" ttfConfig.fontSize = 20 - local label1 = cc.Label:createWithTTF(ttfConfig,"Hair") - local item1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig,"Hair") + local item1 = ax.MenuItemLabel:create(label1) item1:registerScriptTapHandler(function (tag, sender ) -- swithHair self._useHairId = self._useHairId + 1 if self._useHairId > 1 then @@ -522,8 +522,8 @@ function Sprite3DReskinTest:init() end end end) - local label2 = cc.Label:createWithTTF(ttfConfig,"Glasses") - local item2 = cc.MenuItemLabel:create(label2) + local label2 = ax.Label:createWithTTF(ttfConfig,"Glasses") + local item2 = ax.MenuItemLabel:create(label2) item2:registerScriptTapHandler(function (tag, sender ) -- switchGlasses local subMesh = self._sprite:getMeshByName("Girl_Glasses01") if nil ~= subMesh then @@ -535,8 +535,8 @@ function Sprite3DReskinTest:init() end end) - local label3 = cc.Label:createWithTTF(ttfConfig,"Coat") - local item3 = cc.MenuItemLabel:create(label3) + local label3 = ax.Label:createWithTTF(ttfConfig,"Coat") + local item3 = ax.MenuItemLabel:create(label3) item3:registerScriptTapHandler(function (tag, sender ) -- switchCoat self._useUpBodyId = self._useUpBodyId + 1 if self._useUpBodyId > 1 then @@ -556,8 +556,8 @@ function Sprite3DReskinTest:init() end end) - local label4 = cc.Label:createWithTTF(ttfConfig,"Pants") - local item4 = cc.MenuItemLabel:create(label4) + local label4 = ax.Label:createWithTTF(ttfConfig,"Pants") + local item4 = ax.MenuItemLabel:create(label4) item4:registerScriptTapHandler(function (tag, sender ) -- switchPants self._usePantsId = self._usePantsId + 1 @@ -579,8 +579,8 @@ function Sprite3DReskinTest:init() end end) - local label5 = cc.Label:createWithTTF(ttfConfig,"Shoes") - local item5 = cc.MenuItemLabel:create(label5) + local label5 = ax.Label:createWithTTF(ttfConfig,"Shoes") + local item5 = ax.MenuItemLabel:create(label5) item5:registerScriptTapHandler(function (tag, sender ) -- switchShoes self._useShoesId = self._useShoesId + 1 @@ -602,13 +602,13 @@ function Sprite3DReskinTest:init() end end) - item1:setPosition( cc.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height*4 ) ) - item2:setPosition( cc.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *5 ) ) - item3:setPosition( cc.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height*6 ) ) - item4:setPosition( cc.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *7 ) ) - item5:setPosition( cc.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *8 ) ) - local menu = cc.Menu:create(item1,item2,item3,item4,item5) - menu:setPosition(cc.p(0,0)) + item1:setPosition( ax.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height*4 ) ) + item2:setPosition( ax.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *5 ) ) + item3:setPosition( ax.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height*6 ) ) + item4:setPosition( ax.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *7 ) ) + item5:setPosition( ax.p(VisibleRect:left().x+50, VisibleRect:bottom().y+item1:getContentSize().height *8 ) ) + local menu = ax.Menu:create(item1,item2,item3,item4,item5) + menu:setPosition(ax.p(0,0)) self:addChild(menu, 10) end @@ -624,7 +624,7 @@ function Sprite3DReskinTest:addNewSpriteWithCoords(pos) self._useHairId = 0 local fileName = "MeshRendererTest/ReskinGirl.c3b" - local sprite = cc.Sprite3D:create(fileName) + local sprite = ax.Sprite3D:create(fileName) sprite:setScale(4) sprite:setRotation3D({x = 0, y =0 ,z = 0}) local girlPants = sprite:getMeshByName(self._girlPants[2]) @@ -648,17 +648,17 @@ function Sprite3DReskinTest:addNewSpriteWithCoords(pos) end self:addChild(sprite) - sprite:setPosition( cc.p( pos.x, pos.y-60) ) - local animation = cc.Animation3D:create(fileName) + sprite:setPosition( ax.p( pos.x, pos.y-60) ) + local animation = ax.Animation3D:create(fileName) if nil ~= animation then - local animate = cc.Animate3D:create(animation) - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + sprite:runAction(ax.RepeatForever:create(animate)) end self._sprite = sprite end function Sprite3DReskinTest.create() - local layer = Sprite3DReskinTest.extend(cc.Layer:create()) + local layer = Sprite3DReskinTest.extend(ax.Layer:create()) if nil ~= layer then Helper.initWithLayer(layer) @@ -673,18 +673,18 @@ end ----Sprite3DWithOBBPerfromanceTest ---------------------------------------- local Sprite3DWithOBBPerfromanceTest = class("Sprite3DWithOBBPerfromanceTest",function() - return cc.Layer:create() + return ax.Layer:create() end) function Sprite3DWithOBBPerfromanceTest:ctor() self._obb = {} - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) for i,touch in ipairs(touches) do local location = touch:getLocationInView() if nil ~= self._obb and #self._obb > 0 then self._intersetList = {} - local ray = cc.Ray:new() + local ray = ax.Ray:new() self:calculateRayByLocationInView(ray, location) for idx,value in ipairs(self._obb) do @@ -695,11 +695,11 @@ function Sprite3DWithOBBPerfromanceTest:ctor() end end end - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function (touches, event) - - end,cc.Handler.EVENT_TOUCHES_ENDED) + + end,ax.Handler.EVENT_TOUCHES_ENDED) listener:registerScriptHandler(function (touches, event) for i,touch in ipairs(touches) do @@ -708,47 +708,47 @@ function Sprite3DWithOBBPerfromanceTest:ctor() for idx,value in ipairs(self._obb) do for lstIdx,lstValue in ipairs(self._intersetList) do if idx == lstValue then - self._obb[idx]._center = cc.vec3(location.x,location.y,0) + self._obb[idx]._center = ax.vec3(location.x,location.y,0) end end end end - end,cc.Handler.EVENT_TOUCHES_MOVED) + end,ax.Handler.EVENT_TOUCHES_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() self:initDrawBox() - self:addNewSpriteWithCoords(cc.p(s.width/2, s.height/2)) + self:addNewSpriteWithCoords(ax.p(s.width/2, s.height/2)) - cc.MenuItemFont:setFontName("fonts/arial.ttf") - cc.MenuItemFont:setFontSize(65) + ax.MenuItemFont:setFontName("fonts/arial.ttf") + ax.MenuItemFont:setFontSize(65) - local decrease = cc.MenuItemFont:create(" - ") + local decrease = ax.MenuItemFont:create(" - ") decrease:registerScriptTapHandler(function(tag, sender) self:delOBBWithCount(10) end) - decrease:setColor(cc.c3b(0, 200, 20)) + decrease:setColor(ax.color32(0, 200, 20)) - local increase = cc.MenuItemFont:create(" + ") + local increase = ax.MenuItemFont:create(" + ") increase:registerScriptTapHandler(function(tag, sender) self:addOBBWithCount(10) end) - increase:setColor(cc.c3b(0, 200, 20)) + increase:setColor(ax.color32(0, 200, 20)) - local menu = cc.Menu:create(decrease, increase) + local menu = ax.Menu:create(decrease, increase) menu:alignItemsHorizontally() - menu:setPosition(cc.p(s.width/2, s.height - 90)) + menu:setPosition(ax.p(s.width/2, s.height - 90)) self:addChild(menu, 1) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/Marker Felt.ttf" ttfConfig.fontSize = 30 - self._labelCubeCount = cc.Label:createWithTTF(ttfConfig,"0 cubes") - self._labelCubeCount:setColor(cc.c3b(0,200,20)) - self._labelCubeCount:setPosition(cc.p(s.width/2, s.height-90)) + self._labelCubeCount = ax.Label:createWithTTF(ttfConfig,"0 cubes") + self._labelCubeCount:setColor(ax.color32(0,200,20)) + self._labelCubeCount:setPosition(ax.p(s.width/2, s.height-90)) self:addChild(self._labelCubeCount) self:addOBBWithCount(10) @@ -758,14 +758,14 @@ function Sprite3DWithOBBPerfromanceTest:ctor() self._drawDebug:clear() local mat = self._sprite:getNodeToWorldTransform() - self._obbt._xAxis = cc.vec3(mat[1], mat[2], mat[3]) - self._obbt._xAxis = cc.vec3normalize(self._obbt._xAxis) + self._obbt._xAxis = ax.vec3(mat[1], mat[2], mat[3]) + self._obbt._xAxis = ax.vec3normalize(self._obbt._xAxis) - self._obbt._yAxis = cc.vec3(mat[5], mat[6], mat[7]) - self._obbt._yAxis = cc.vec3normalize(self._obbt._yAxis) + self._obbt._yAxis = ax.vec3(mat[5], mat[6], mat[7]) + self._obbt._yAxis = ax.vec3normalize(self._obbt._yAxis) - self._obbt._zAxis = cc.vec3(-mat[9], -mat[10], -mat[11]) - self._obbt._zAxis = cc.vec3normalize(self._obbt._zAxis) + self._obbt._zAxis = ax.vec3(-mat[9], -mat[10], -mat[11]) + self._obbt._zAxis = ax.vec3normalize(self._obbt._zAxis) self._obbt._center = self._sprite:getPosition3D() @@ -774,7 +774,7 @@ function Sprite3DWithOBBPerfromanceTest:ctor() corners[i] = {} end corners = self._obbt:getCorners(corners) - self._drawDebug:drawCube(corners, cc.c4f(0, 0, 1, 1)) + self._drawDebug:drawCube(corners, ax.color(0, 0, 1, 1)) end if #self._obb > 0 then @@ -788,9 +788,9 @@ function Sprite3DWithOBBPerfromanceTest:ctor() corners = self._obb[i]:getCorners(corners) if self._obbt:intersects(self._obb[i]) then - self._drawOBB:drawCube(corners, cc.c4f(1, 0, 0, 1)) + self._drawOBB:drawCube(corners, ax.color(1, 0, 0, 1)) else - self._drawOBB:drawCube(corners, cc.c4f(0, 1, 0, 1)) + self._drawOBB:drawCube(corners, ax.color(0, 1, 0, 1)) end end @@ -800,11 +800,11 @@ end function Sprite3DWithOBBPerfromanceTest:addOBBWithCount( value ) for i=1,value do - local randompos = cc.p(math.random() * cc.Director:getInstance():getWinSize().width, math.random() * cc.Director:getInstance():getWinSize().height) - local extents = cc.vec3(10, 10, 10) - local aabb = cc.AABB:new({x = -10, y = -10, z = -10}, extents) - local obb = cc.OBB:new(aabb) - obb._center = cc.vec3(randompos.x,randompos.y,0) + local randompos = ax.p(math.random() * ax.Director:getInstance():getWinSize().width, math.random() * ax.Director:getInstance():getWinSize().height) + local extents = ax.vec3(10, 10, 10) + local aabb = ax.AABB:new({x = -10, y = -10, z = -10}, extents) + local obb = ax.OBB:new(aabb) + obb._center = ax.vec3(randompos.x,randompos.y,0) table.insert(self._obb, obb) end end @@ -813,23 +813,23 @@ function Sprite3DWithOBBPerfromanceTest:delOBBWithCount( value ) if #self._obb >= 10 then for i= 1, 10 do table.remove(self._obb) - end + end self._drawOBB:clear() - end + end end function Sprite3DWithOBBPerfromanceTest:initDrawBox() - self._drawOBB = cc.DrawNode3D:create() + self._drawOBB = ax.DrawNode3D:create() self:addChild(self._drawOBB ) end function Sprite3DWithOBBPerfromanceTest:unproject( viewProjection, viewport, src, dst) assert(viewport.width ~= 0.0 and viewport.height ~= 0) - local screen = cc.vec4(src.x / viewport.width, (viewport.height - src.y) / viewport.height, src.z, 1.0) + local screen = ax.vec4(src.x / viewport.width, (viewport.height - src.y) / viewport.height, src.z, 1.0) screen.x = screen.x * 2.0 - 1.0 screen.y = screen.y * 2.0 - 1.0 screen.z = screen.z * 2.0 - 1.0 - local inversed = cc.mat4.new(viewProjection:getInversed()) + local inversed = ax.mat4.new(viewProjection:getInversed()) screen = inversed:transformVector(screen) if screen.w ~= 0.0 then screen.x = screen.x / screen.w @@ -844,61 +844,61 @@ function Sprite3DWithOBBPerfromanceTest:unproject( viewProjection, viewport, src end function Sprite3DWithOBBPerfromanceTest:calculateRayByLocationInView(ray, location) - local dir = cc.Director:getInstance() + local dir = ax.Director:getInstance() local view = dir:getWinSize() - local mat = cc.mat4.new(dir:getMatrix(cc.MATRIX_STACK_TYPE.PROJECTION)) - local src = cc.vec3(location.x, location.y, -1) + local mat = ax.mat4.new(dir:getMatrix(ax.MATRIX_STACK_TYPE.PROJECTION)) + local src = ax.vec3(location.x, location.y, -1) local nearPoint = {} view, src, nearPoint = self:unproject(mat, view, src, nearPoint) - src = cc.vec3(location.x, location.y, 1) + src = ax.vec3(location.x, location.y, 1) local farPoint = {} view, src, farPoint = self:unproject(mat, view, src, farPoint) local direction = {} direction.x = farPoint.x - nearPoint.x direction.y = farPoint.y - nearPoint.y direction.z = farPoint.z - nearPoint.z - direction = cc.vec3normalize(direction) - + direction = ax.vec3normalize(direction) + ray._origin = nearPoint ray._direction = direction end function Sprite3DWithOBBPerfromanceTest:addNewSpriteWithCoords(vec2) local fileName = "MeshRendererTest/tortoise.c3b" - local sprite = cc.Sprite3D:create(fileName) + local sprite = ax.Sprite3D:create(fileName) sprite:setScale(0.1) - local s = cc.Director:getInstance():getWinSize() - sprite:setPosition(cc.p(s.width * 4.0 / 5.0, s.height / 2.0)) + local s = ax.Director:getInstance():getWinSize() + sprite:setPosition(ax.p(s.width * 4.0 / 5.0, s.height / 2.0)) self:addChild(sprite) self._sprite = sprite - local animation = cc.Animation3D:create(fileName) + local animation = ax.Animation3D:create(fileName) if nil ~= animation then - local animate = cc.Animate3D:create(animation, 0.0, 1.933) - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation, 0.0, 1.933) + sprite:runAction(ax.RepeatForever:create(animate)) end - - self._moveAction = cc.MoveTo:create(4.0, cc.p(s.width / 5.0, s.height / 2.0)) + + self._moveAction = ax.MoveTo:create(4.0, ax.p(s.width / 5.0, s.height / 2.0)) self._moveAction:retain() local function reachEndCallBack() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() self._sprite:stopActionByTag(100) - local inverse = cc.MoveTo:create(4.0, cc.p(s.width - self._sprite:getPositionX(), s.height / 2.0)) + local inverse = ax.MoveTo:create(4.0, ax.p(s.width - self._sprite:getPositionX(), s.height / 2.0)) inverse:retain() self._moveAction:release() self._moveAction = inverse - local rot = cc.RotateBy:create(1.0, { x = 0.0, y = 180.0, z = 0.0}) - local seq = cc.Sequence:create(rot, self._moveAction, cc.CallFunc:create(reachEndCallBack)) + local rot = ax.RotateBy:create(1.0, { x = 0.0, y = 180.0, z = 0.0}) + local seq = ax.Sequence:create(rot, self._moveAction, ax.CallFunc:create(reachEndCallBack)) seq:setTag(100) self._sprite:runAction(seq) end - local seq = cc.Sequence:create(self._moveAction, cc.CallFunc:create(reachEndCallBack)) + local seq = ax.Sequence:create(self._moveAction, ax.CallFunc:create(reachEndCallBack)) seq:setTag(100) sprite:runAction(seq) - + local aabb = self._sprite:getAABB() - self._obbt = cc.OBB:new(aabb) - - self._drawDebug = cc.DrawNode3D:create() + self._obbt = ax.OBB:new(aabb) + + self._drawDebug = ax.DrawNode3D:create() self:addChild(self._drawDebug) end @@ -916,45 +916,45 @@ local Sprite3DMirrorTest = {} Sprite3DMirrorTest.__index = Sprite3DMirrorTest function Sprite3DMirrorTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("Sprite3D Mirror Test") local fileName = "MeshRendererTest/orc.c3b" - local sprite = cc.Sprite3D:create(fileName) + local sprite = ax.Sprite3D:create(fileName) sprite:setScale(5.0) sprite:setRotation3D({x = 0, y = 180, z = 0}) - sprite:setPosition( cc.p(size.width/2 - 80, size.height/2) ) + sprite:setPosition( ax.p(size.width/2 - 80, size.height/2) ) layer:addChild(sprite) - local sp = cc.Sprite3D:create("MeshRendererTest/axe.c3b") + local sp = ax.Sprite3D:create("MeshRendererTest/axe.c3b") sprite:getAttachNode("Bip001 R Hand"):addChild(sp) - local animation = cc.Animation3D:create(fileName) + local animation = ax.Animation3D:create(fileName) if nil ~= animation then - local animate = cc.Animate3D:create(animation) - - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + + sprite:runAction(ax.RepeatForever:create(animate)) end --create mirror Sprite3D - sprite = cc.Sprite3D:create(fileName) + sprite = ax.Sprite3D:create(fileName) sprite:setScale(5) sprite:setScaleX(-5) sprite:setCullFace(ccb.CullMode.FRONT) sprite:setRotation3D({x = 0, y = 180,z = 0}) layer:addChild(sprite) - sprite:setPosition( cc.p( size.width/2 + 80, size.height/2)) + sprite:setPosition( ax.p( size.width/2 + 80, size.height/2)) --test attach - sp = cc.Sprite3D:create("MeshRendererTest/axe.c3b") + sp = ax.Sprite3D:create("MeshRendererTest/axe.c3b") sprite:getAttachNode("Bip001 R Hand"):addChild(sp) - - animation = cc.Animation3D:create(fileName) + + animation = ax.Animation3D:create(fileName) if nil ~= animation then - local animate = cc.Animate3D:create(animation) - - sprite:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + + sprite:runAction(ax.RepeatForever:create(animate)) end return layer @@ -965,7 +965,7 @@ end ----AsyncLoadSprite3DTest ---------------------------------------- local AsyncLoadSprite3DTest = class("AsyncLoadSprite3DTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -1004,62 +1004,62 @@ function AsyncLoadSprite3DTest:onEnter() local paths = {"MeshRendererTest/girl.c3b", "MeshRendererTest/orc.c3b", "MeshRendererTest/ReskinGirl.c3b", "MeshRendererTest/axe.c3b"} - local label1 = cc.Label:createWithTTF(ttfConfig,"AsyncLoad Sprite3D") - local item1 = cc.MenuItemLabel:create(label1) + local label1 = ax.Label:createWithTTF(ttfConfig,"AsyncLoad Sprite3D") + local item1 = ax.MenuItemLabel:create(label1) function menuCallback_asyncLoadSprite(tag, sender) --Note that you must stop the tasks before leaving the scene. - cc.AsyncTaskPool:getInstance():stopTasks(cc.AsyncTaskPool.TaskType.TASK_IO) - + ax.AsyncTaskPool:getInstance():stopTasks(ax.AsyncTaskPool.TaskType.TASK_IO) + local node = self:getChildByTag(101) --remove all loaded sprite node:removeAllChildren() - + --remove cache data - cc.MeshRendererCache:getInstance():removeAllMeshRenderData() + ax.MeshRendererCache:getInstance():removeAllMeshRenderData() local function callback(sprite, index) local node = self:getChildByTag(101) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local width = s.width / (#paths) - local point = cc.p(width * (0.5 + index), s.height / 2.0) + local point = ax.p(width * (0.5 + index), s.height / 2.0) sprite:setPosition(point) node:addChild(sprite) end - cc.Sprite3D:createAsync(paths[1], function(sprite) + ax.Sprite3D:createAsync(paths[1], function(sprite) callback(sprite, 0) end) - cc.Sprite3D:createAsync(paths[2], function(sprite) + ax.Sprite3D:createAsync(paths[2], function(sprite) callback(sprite, 1) end) - cc.Sprite3D:createAsync(paths[3], function(sprite) + ax.Sprite3D:createAsync(paths[3], function(sprite) callback(sprite, 2) end) - cc.Sprite3D:createAsync(paths[4], function(sprite) + ax.Sprite3D:createAsync(paths[4], function(sprite) callback(sprite, 3) end) - cc.Sprite3D:createAsync(paths[5], function(sprite) + ax.Sprite3D:createAsync(paths[5], function(sprite) callback(sprite, 4) end) end item1:registerScriptTapHandler(menuCallback_asyncLoadSprite) - - local s = cc.Director:getInstance():getWinSize() + + local s = ax.Director:getInstance():getWinSize() item1:setPosition( s.width * 0.5, s.height * 0.8) - - local menu = cc.Menu:create(item1) - menu:setPosition(cc.p(0,0)) + + local menu = ax.Menu:create(item1) + menu:setPosition(ax.p(0,0)) self:addChild(menu, 10) - - local node = cc.Node:create() + + local node = ax.Node:create() node:setTag(101) self:addChild(node) - + menuCallback_asyncLoadSprite() end @@ -1070,7 +1070,7 @@ end ----Sprite3DCubeTexture ---------------------------------------- local Sprite3DCubeMapTest = class("Sprite3DCubeMapTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -1101,32 +1101,32 @@ function Sprite3DCubeMapTest:subtitle() end function Sprite3DCubeMapTest:onEnter() - local s = cc.Director:getInstance():getWinSize() - self:addNewSpriteWithCoords(cc.p(s.width / 2, s.height / 2)) + local s = ax.Director:getInstance():getWinSize() + self:addNewSpriteWithCoords(ax.p(s.width / 2, s.height / 2)) Helper.initWithLayer(self) Helper.titleLabel:setString(self:title()) Helper.subtitleLabel:setString(self:subtitle()) end function Sprite3DCubeMapTest:onExit() - local targetPlatform = cc.Application:getInstance():getTargetPlatform() - if targetPlatform == cc.PLATFORM_OS_ANDROID or targetPlatform == cc.PLATFORM_OS_WINRT or targetPlatform == cc.PLATFORM_OS_WP8 then - cc.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) + local targetPlatform = ax.Application:getInstance():getTargetPlatform() + if targetPlatform == ax.PLATFORM_OS_ANDROID or targetPlatform == ax.PLATFORM_OS_WINRT or targetPlatform == ax.PLATFORM_OS_WP8 then + ax.Director:getInstance():getEventDispatcher():removeEventListener(self._backToForegroundListener) end end function Sprite3DCubeMapTest:addNewSpriteWithCoords(pos) - local visibleSize = cc.Director:getInstance():getVisibleSize() - local camera = cc.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) - camera:setPosition3D(cc.vec3(0.0, 0.0, 50.0)) - camera:setCameraFlag(cc.CameraFlag.USER1) + local visibleSize = ax.Director:getInstance():getVisibleSize() + local camera = ax.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) + camera:setPosition3D(ax.vec3(0.0, 0.0, 50.0)) + camera:setCameraFlag(ax.CameraFlag.USER1) --create a teapot - self._teapot = cc.Sprite3D:create("MeshRendererTest/teapot.c3b") + self._teapot = ax.Sprite3D:create("MeshRendererTest/teapot.c3b") - local program = axb.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs') + local program = axrhi.ProgramManager:getInstance():loadProgram('custom/cube_map_vs', 'custom/cube_map_fs') local programState = ccb.ProgramState:new(program) - - self._textureCube = cc.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", + + self._textureCube = ax.TextureCube:create("MeshRendererTest/skybox/left.jpg", "MeshRendererTest/skybox/right.jpg", "MeshRendererTest/skybox/top.jpg", "MeshRendererTest/skybox/bottom.jpg", "MeshRendererTest/skybox/front.jpg", "MeshRendererTest/skybox/back.jpg") @@ -1140,15 +1140,15 @@ function Sprite3DCubeMapTest:addNewSpriteWithCoords(pos) programState:setTexture(locCubeTex, 0, cubeTexture) self._teapot:setProgramState(programState) - self._teapot:setPosition3D(cc.vec3(0, -5, 0)) - self._teapot:setRotation3D(cc.vec3(-90, 180, 0)) + self._teapot:setPosition3D(ax.vec3(0, -5, 0)) + self._teapot:setRotation3D(ax.vec3(-90, 180, 0)) - local rotate_action = cc.RotateBy:create(1.5, cc.vec3(0, 30, 0)) - self._teapot:runAction(cc.RepeatForever:create(rotate_action)) + local rotate_action = ax.RotateBy:create(1.5, ax.vec3(0, 30, 0)) + self._teapot:runAction(ax.RepeatForever:create(rotate_action)) --pass mesh's attribute to shader - local attributeNames = + local attributeNames = { "a_position", "a_color", @@ -1164,7 +1164,7 @@ function Sprite3DCubeMapTest:addNewSpriteWithCoords(pos) self:addChild(self._teapot) --config skybox - self._skyBox = cc.Skybox:create() + self._skyBox = ax.Skybox:create() self._skyBox:setTexture(self._textureCube) self:addChild(self._skyBox) @@ -1178,7 +1178,7 @@ end ----Sprite3DNormalMappingTest ---------------------------------------- local Sprite3DNormalMappingTest = class("Sprite3DNormalMappingTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -1211,27 +1211,27 @@ end function Sprite3DNormalMappingTest:onEnter() - local sprite3d = cc.Sprite3D:create("MeshRendererTest/sphere.c3b") + local sprite3d = ax.Sprite3D:create("MeshRendererTest/sphere.c3b") sprite3d:setScale(2.0) - sprite3d:setPosition(cc.p(-30,0)) - sprite3d:setRotation3D(cc.vec3(90.0, 0.0, 0.0)) + sprite3d:setPosition(ax.p(-30,0)) + sprite3d:setRotation3D(ax.vec3(90.0, 0.0, 0.0)) sprite3d:setTexture("MeshRendererTest/brickwork-texture.jpg") sprite3d:setCameraMask(2) self:addChild(sprite3d) - local sprite3dBumped = cc.Sprite3D:create("MeshRendererTest/sphere_bumped.c3b") + local sprite3dBumped = ax.Sprite3D:create("MeshRendererTest/sphere_bumped.c3b") sprite3dBumped:setScale(20.0) - sprite3dBumped:setPosition(cc.p(30,0)) - sprite3dBumped:setRotation3D(cc.vec3(90.0, 0.0, 0.0)) + sprite3dBumped:setPosition(ax.p(30,0)) + sprite3dBumped:setRotation3D(ax.vec3(90.0, 0.0, 0.0)) sprite3dBumped:setCameraMask(2) self:addChild(sprite3dBumped) local radius = 100.0 local angle = 0.0 local reverseDir = false - local light = cc.PointLight:create(cc.vec3(0.0, 0.0, 0.0), cc.c3b(255, 255, 255), 1000.0) + local light = ax.PointLight:create(ax.vec3(0.0, 0.0, 0.0), ax.color32(255, 255, 255), 1000.0) local function lightUpdate() - light:setPosition3D(cc.vec3(radius * math.cos(angle), 0.0, radius * math.sin(angle))) + light:setPosition3D(ax.vec3(radius * math.cos(angle), 0.0, radius * math.sin(angle))) if reverseDir == true then angle = angle - 0.01 if angle < 0.0 then @@ -1245,15 +1245,15 @@ function Sprite3DNormalMappingTest:onEnter() end end - local seq = cc.Sequence:create(cc.CallFunc:create(lightUpdate)) - light:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(ax.CallFunc:create(lightUpdate)) + light:runAction(ax.RepeatForever:create(seq)) self:addChild(light) - local visibleSize = cc.Director:getInstance():getVisibleSize() - local camera = cc.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) - camera:setPosition3D(cc.vec3(0.0, 0.0, 100.0)) - camera:lookAt(cc.vec3(0.0, 0.0, 0.0)) - camera:setCameraFlag(cc.CameraFlag.USER1) + local visibleSize = ax.Director:getInstance():getVisibleSize() + local camera = ax.Camera:createPerspective(60, visibleSize.width / visibleSize.height, 10, 1000) + camera:setPosition3D(ax.vec3(0.0, 0.0, 100.0)) + camera:lookAt(ax.vec3(0.0, 0.0, 0.0)) + camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(camera) end @@ -1265,7 +1265,7 @@ end ----Sprite3DMaterialTest ---------------------------------------- local Sprite3DMaterialTest = class("Sprite3DMaterialTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -1298,20 +1298,20 @@ end function Sprite3DMaterialTest:onEnter() - local material = cc.Sprite3DMaterial:createWithFilename("MeshRendererTest/outline.material") - local sprite = cc.Sprite3D:create("MeshRendererTest/sphere_bumped.c3b") + local material = ax.Sprite3DMaterial:createWithFilename("MeshRendererTest/outline.material") + local sprite = ax.Sprite3D:create("MeshRendererTest/sphere_bumped.c3b") :setScale(20.0) - :setPosition(cc.p(0,0)) - :setRotation3D(cc.vec3(90.0, 0.0, 0.0)) + :setPosition(ax.p(0,0)) + :setRotation3D(ax.vec3(90.0, 0.0, 0.0)) :setCameraMask(2) :setMaterial(material) self:addChild(sprite) - local camera = cc.Camera:create() - :setPosition3D(cc.vec3(0.0, 0.0, 100.0)) - :lookAt(cc.vec3(0.0, 0.0, 0.0)) - :setCameraFlag(cc.CameraFlag.USER1) + local camera = ax.Camera:create() + :setPosition3D(ax.vec3(0.0, 0.0, 100.0)) + :lookAt(ax.vec3(0.0, 0.0, 0.0)) + :setCameraFlag(ax.CameraFlag.USER1) self:addChild(camera) end @@ -1319,7 +1319,7 @@ function Sprite3DMaterialTest:onExit() end function Sprite3DTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { diff --git a/tests/lua-tests/Content/src/SpritePolygonTest/SpritePolygonTest.lua b/tests/lua-tests/Content/src/SpritePolygonTest/SpritePolygonTest.lua index 86dd5138b562..c939ebfd5ed6 100644 --- a/tests/lua-tests/Content/src/SpritePolygonTest/SpritePolygonTest.lua +++ b/tests/lua-tests/Content/src/SpritePolygonTest/SpritePolygonTest.lua @@ -1,7 +1,7 @@ local imageFileName = "Images/grossini.png" local SpritePolygonTestDemo = class("SpritePolygonTestDemo", function() - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -18,11 +18,11 @@ function SpritePolygonTestDemo:registerNodeEvent() end function SpritePolygonTestDemo:onEnter() - cc.Director:getInstance():setClearColor(cc.c4f(102.0/255, 184.0/255, 204.0/255, 255.0)) + ax.Director:getInstance():setClearColor(ax.color(102.0/255, 184.0/255, 204.0/255, 1.0)) end function SpritePolygonTestDemo:onExit() - cc.Director:getInstance():setClearColor(cc.c4f(0.0, 0.0, 0.0, 1.0)) + ax.Director:getInstance():setClearColor(ax.color(0.0, 0.0, 0.0, 1.0)) end ---------------------------------------- @@ -36,18 +36,18 @@ end function SpritePolygonTest1:ctor() - local s = cc.Director:getInstance():getWinSize() - local offset = cc.p(0.15 * s.width, 0) + local s = ax.Director:getInstance():getWinSize() + local offset = ax.p(0.15 * s.width, 0) local filename = s_pPathGrossini - local info = cc.AutoPolygon:generatePolygon(filename) - local spp = cc.Sprite:create(info) + local info = ax.AutoPolygon:generatePolygon(filename) + local spp = ax.Sprite:create(info) self:addChild(spp) - spp:setPosition(cc.p(s.width / 2 + offset.x, s.height / 2 + offset.y)) + spp:setPosition(ax.p(s.width / 2 + offset.x, s.height / 2 + offset.y)) - local sp = cc.Sprite:create(filename) + local sp = ax.Sprite:create(filename) self:addChild(sp) - sp:setPosition(cc.p(s.width/2 - offset.x, s.height/2 - offset.y)) + sp:setPosition(ax.p(s.width/2 - offset.x, s.height/2 - offset.y)) local ttfConfig = {} ttfConfig.fontFilePath = "fonts/arial.ttf" @@ -55,15 +55,15 @@ function SpritePolygonTest1:ctor() local temp = "Sprite:\nPixels drawn: " local spSize = sp:getContentSize() - local spArea = cc.Label:createWithTTF(ttfConfig, temp .. (spSize.width * spSize.height)) + local spArea = ax.Label:createWithTTF(ttfConfig, temp .. (spSize.width * spSize.height)) sp:addChild(spArea) - spArea:setAnchorPoint(cc.p(0, 1)) + spArea:setAnchorPoint(ax.p(0, 1)) temp = "SpritePolygon:\nPixels drawn: " local vertCount = "\nverts:" .. info:getVertCount() - local sppArea = cc.Label:createWithTTF(ttfConfig, temp .. math.floor(info:getArea()) .. vertCount) + local sppArea = ax.Label:createWithTTF(ttfConfig, temp .. math.floor(info:getArea()) .. vertCount) spp:addChild(sppArea) - sppArea:setAnchorPoint(cc.p(0, 1)) + sppArea:setAnchorPoint(ax.p(0, 1)) Helper.initWithLayer(self) Helper.titleLabel:setString(self:title()) @@ -86,19 +86,19 @@ end local SpritePolygonTest2 = class("SpritePolygonTest2", SpritePolygonTestDemo) function SpritePolygonTest2:make2Sprites() - local s = cc.Director:getInstance():getWinSize() - local offset = cc.p(0.15 * s.width, 0) + local s = ax.Director:getInstance():getWinSize() + local offset = ax.p(0.15 * s.width, 0) local filename = s_pPathGrossini - local head = cc.rect(30, 25, 25, 25) - local info = cc.AutoPolygon:generatePolygon(filename, head) - self.spp = cc.Sprite:create(info) + local head = ax.rect(30, 25, 25, 25) + local info = ax.AutoPolygon:generatePolygon(filename, head) + self.spp = ax.Sprite:create(info) self:addChild(self.spp) - self.spp:setPosition(cc.p(s.width / 2 + offset.x, s.height / 2 + offset.y)) + self.spp:setPosition(ax.p(s.width / 2 + offset.x, s.height / 2 + offset.y)) - self.sp = cc.Sprite:create(filename,head) + self.sp = ax.Sprite:create(filename,head) self:addChild(self.sp) - self.sp:setPosition(cc.p(s.width/2 - offset.x, s.height/2 - offset.y)) + self.sp:setPosition(ax.p(s.width/2 - offset.x, s.height/2 - offset.y)) local ttfConfig = {} @@ -107,15 +107,15 @@ function SpritePolygonTest2:make2Sprites() local temp = "Sprite:\nPixels drawn: " local spSize = self.sp:getContentSize() - local spArea = cc.Label:createWithTTF(ttfConfig, temp .. (spSize.width * spSize.height)) + local spArea = ax.Label:createWithTTF(ttfConfig, temp .. (spSize.width * spSize.height)) self.sp:addChild(spArea) - spArea:setAnchorPoint(cc.p(0, 1)) + spArea:setAnchorPoint(ax.p(0, 1)) temp = "SpritePolygon:\nPixels drawn: " local vertCount = "\nverts:" .. info:getVertCount() - local sppArea = cc.Label:createWithTTF(ttfConfig, temp .. math.floor(info:getArea()) .. vertCount) + local sppArea = ax.Label:createWithTTF(ttfConfig, temp .. math.floor(info:getArea()) .. vertCount) self.spp:addChild(sppArea) - sppArea:setAnchorPoint(cc.p(0, 1)) + sppArea:setAnchorPoint(ax.p(0, 1)) end function SpritePolygonTest2:ctor() @@ -143,25 +143,25 @@ end local SpritePolygonTest3 = class("SpritePolygonTest3", SpritePolygonTestDemo) function SpritePolygonTest3:makeSprite(filename, pos) - local quadSize = cc.Sprite:create(filename):getContentSize() + local quadSize = ax.Sprite:create(filename):getContentSize() local originalSize = quadSize.width * quadSize.height - local info = cc.AutoPolygon:generatePolygon(filename) - local ret = cc.Sprite:create(info) + local info = ax.AutoPolygon:generatePolygon(filename) + local ret = ax.Sprite:create(info) ret:setPosition(pos) - - local spArea = cc.Label:createWithTTF(self._ttfConfig, filename .. "\nVerts: " .. info:getVertCount() .. "\nPixels: " .. math.floor(info:getArea() / originalSize * 100) .. "%") + + local spArea = ax.Label:createWithTTF(self._ttfConfig, filename .. "\nVerts: " .. info:getVertCount() .. "\nPixels: " .. math.floor(info:getArea() / originalSize * 100) .. "%") ret:addChild(spArea) - spArea:setAnchorPoint(cc.p(0,1)) + spArea:setAnchorPoint(ax.p(0,1)) ret:setName(filename) - ret:setAnchorPoint(cc.p(0.5, 0)) - return ret + ret:setAnchorPoint(ax.p(0.5, 0)) + return ret end function SpritePolygonTest3:makeSprites(list, count, y) - local vsize = cc.Director:getInstance():getVisibleSize() + local vsize = ax.Director:getInstance():getVisibleSize() local offset = (vsize.width - 100) / (count - 1) for i = 1, count do - local sp = self:makeSprite(list[i], cc.p(50 + offset * (i - 1), y)) + local sp = self:makeSprite(list[i], ax.p(50 + offset * (i - 1), y)) self:addChild(sp) end end @@ -169,8 +169,8 @@ end function SpritePolygonTest3:updateLabel(sprite, polygonInfo) local label = sprite:getChildren()[1] local filename = sprite:getName() - local scaleFactor = cc.Director:getInstance():getContentScaleFactor() - local size = cc.size(polygonInfo.rect.width / scaleFactor , polygonInfo.rect.height / scaleFactor ) + local scaleFactor = ax.Director:getInstance():getContentScaleFactor() + local size = ax.size(polygonInfo.rect.width / scaleFactor , polygonInfo.rect.height / scaleFactor ) local labelInfo = filename .. "\nVerts: " .. polygonInfo:getVertCount() .. "\nPixels: " .. math.floor(polygonInfo:getArea() / (size.width*size.height)*100) .. "%" label:setString(labelInfo) end @@ -180,14 +180,14 @@ function SpritePolygonTest3:ctor() self._ttfConfig.fontFilePath = "fonts/arial.ttf" self._ttfConfig.fontSize = 8 - local vsize = cc.Director:getInstance():getVisibleSize() + local vsize = ax.Director:getInstance():getVisibleSize() local slider = ccui.Slider:create() slider:loadBarTexture("cocosui/sliderTrack.png") slider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") slider:loadProgressBarTexture("cocosui/sliderProgress.png") - slider:setPosition(cc.p(vsize.width/2, vsize.height/4)) - + slider:setPosition(ax.p(vsize.width/2, vsize.height/4)) + local function percentChangedEvent(sender,eventType) if eventType == ccui.SliderEventType.percentChanged then @@ -195,7 +195,7 @@ function SpritePolygonTest3:ctor() local percent = "Percent " .. slider:getPercent() self._displayValueLabel:setString(percent) end - end + end slider:addEventListener(function(sender, eventType) local epsilon = math.pow(sender:getPercent() / 100.0 , 2) * 19.0 + 1.0 @@ -204,7 +204,7 @@ function SpritePolygonTest3:ctor() local child = children[i] if child:getName() ~= nil and child:getName() ~= "" then local file = child:getName() - local info = cc.AutoPolygon:generatePolygon(file, cc.rect(0, 0, 0, 0), epsilon) + local info = ax.AutoPolygon:generatePolygon(file, ax.rect(0, 0, 0, 0), epsilon) child:setPolygonInfo(info) self:updateLabel(child, info) end @@ -213,10 +213,10 @@ function SpritePolygonTest3:ctor() self._epsilonLabel:setString("Epsilon: " .. epsilon) end) slider:setPercent(math.sqrt(1.0 /19.0 )*100) - - self._epsilonLabel = cc.Label:createWithTTF(self._ttfConfig, "Epsilon: 2.0") + + self._epsilonLabel = ax.Label:createWithTTF(self._ttfConfig, "Epsilon: 2.0") self:addChild(self._epsilonLabel) - self._epsilonLabel:setPosition(cc.p(vsize.width/2, vsize.height/4 + 15)) + self._epsilonLabel:setPosition(ax.p(vsize.width/2, vsize.height/4 + 15)) self:addChild(slider) local list = { @@ -244,11 +244,11 @@ function SpritePolygonTest3:subtitle() end function SpritePolygonTest3:onEnter() - cc.Director:getInstance():setClearColor(cc.c4f(102.0/255, 184.0/255, 204.0/255, 255.0)) + ax.Director:getInstance():setClearColor(ax.color(102.0/255, 184.0/255, 204.0/255, 1.0)) end function SpritePolygonTest3:onExit() - cc.Director:getInstance():setClearColor(cc.c4f(0.0, 0.0, 0.0, 1.0)) + ax.Director:getInstance():setClearColor(ax.color(0.0, 0.0, 0.0, 1.0)) end @@ -262,14 +262,14 @@ function SpritePolygonTest4:ctor() self._ttfConfig.fontFilePath = "fonts/arial.ttf" self._ttfConfig.fontSize = 8 - local vsize = cc.Director:getInstance():getVisibleSize() + local vsize = ax.Director:getInstance():getVisibleSize() local slider = ccui.Slider:create() slider:loadBarTexture("cocosui/sliderTrack.png") slider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") slider:loadProgressBarTexture("cocosui/sliderProgress.png") - slider:setPosition(cc.p(vsize.width/2, vsize.height/4)) - + slider:setPosition(ax.p(vsize.width/2, vsize.height/4)) + local function percentChangedEvent(sender,eventType) if eventType == ccui.SliderEventType.percentChanged then @@ -277,7 +277,7 @@ function SpritePolygonTest4:ctor() local percent = "Percent " .. slider:getPercent() self._displayValueLabel:setString(percent) end - end + end slider:addEventListener(function(sender, eventType) local epsilon = math.pow(sender:getPercent() / 100.0 , 2) * 19.0 + 1.0 @@ -286,7 +286,7 @@ function SpritePolygonTest4:ctor() local child = children[i] if child:getName() ~= nil and child:getName() ~= "" then local file = child:getName() - local info = cc.AutoPolygon:generatePolygon(file, cc.rect(0, 0, 0, 0), epsilon) + local info = ax.AutoPolygon:generatePolygon(file, ax.rect(0, 0, 0, 0), epsilon) child:setPolygonInfo(info) self:updateLabel(child, info) end @@ -295,10 +295,10 @@ function SpritePolygonTest4:ctor() self._epsilonLabel:setString("Epsilon: " .. epsilon) end) slider:setPercent(math.sqrt(1.0 /19.0 )*100) - - self._epsilonLabel = cc.Label:createWithTTF(self._ttfConfig, "Epsilon: 2.0") + + self._epsilonLabel = ax.Label:createWithTTF(self._ttfConfig, "Epsilon: 2.0") self:addChild(self._epsilonLabel) - self._epsilonLabel:setPosition(cc.p(vsize.width/2, vsize.height/4 + 15)) + self._epsilonLabel:setPosition(ax.p(vsize.width/2, vsize.height/4 + 15)) self:addChild(slider) local list = { @@ -327,42 +327,42 @@ end function SpritePolygonTest4:updateLabel(sprite, polygonInfo) local label = sprite:getChildren()[1] local filename = sprite:getName() - local rectSize = cc.size(polygonInfo.rect.width, polygonInfo.rect.height) - local size = cc.size(rectSize.width / cc.Director:getInstance():getContentScaleFactor(), rectSize.height / cc.Director:getInstance():getContentScaleFactor()) + local rectSize = ax.size(polygonInfo.rect.width, polygonInfo.rect.height) + local size = ax.size(rectSize.width / ax.Director:getInstance():getContentScaleFactor(), rectSize.height / ax.Director:getInstance():getContentScaleFactor()) local labelInfo = filename .. "\nVerts: " .. polygonInfo:getVertCount() .. "\nPixels: " .. math.floor(polygonInfo:getArea() / (size.width*size.height)*100) .. "%" label:setString(labelInfo) end function SpritePolygonTest4:makeSprite(filename, pos) - local quadSize = cc.Sprite:create(filename):getContentSize() + local quadSize = ax.Sprite:create(filename):getContentSize() local originalSize = quadSize.width * quadSize.height - local info = cc.AutoPolygon:generatePolygon(filename) - local ret = cc.Sprite:create(info) + local info = ax.AutoPolygon:generatePolygon(filename) + local ret = ax.Sprite:create(info) ret:setPosition(pos) - - local spArea = cc.Label:createWithTTF(self._ttfConfig, filename .. "\nVerts: " .. info:getVertCount() .. "\nPixels: " .. math.floor(info:getArea() / originalSize * 100) .. "%") + + local spArea = ax.Label:createWithTTF(self._ttfConfig, filename .. "\nVerts: " .. info:getVertCount() .. "\nPixels: " .. math.floor(info:getArea() / originalSize * 100) .. "%") ret:addChild(spArea) - spArea:setAnchorPoint(cc.p(0,1)) + spArea:setAnchorPoint(ax.p(0,1)) ret:setName(filename) - ret:setAnchorPoint(cc.p(0.5, 0)) - return ret + ret:setAnchorPoint(ax.p(0.5, 0)) + return ret end function SpritePolygonTest4:makeSprites(list, count, y) - local vsize = cc.Director:getInstance():getVisibleSize() + local vsize = ax.Director:getInstance():getVisibleSize() local offset = (vsize.width - 100) / (count - 1) for i = 1, count do - local sp = self:makeSprite(list[i], cc.p(50 + offset * (i - 1), y)) + local sp = self:makeSprite(list[i], ax.p(50 + offset * (i - 1), y)) self:addChild(sp) end end function SpritePolygonTest4:onEnter() - cc.Director:getInstance():setClearColor(cc.c4f(102.0/255, 184.0/255, 204.0/255, 255.0)) + ax.Director:getInstance():setClearColor(ax.color(102.0/255, 184.0/255, 204.0/255, 1.0)) end function SpritePolygonTest4:onExit() - cc.Director:getInstance():setClearColor(cc.c4f(0.0, 0.0, 0.0, 1.0)) + ax.Director:getInstance():setClearColor(ax.color(0.0, 0.0, 0.0, 1.0)) end @@ -400,23 +400,23 @@ function SpritePolygonPerformance:updateLabel() end function SpritePolygonPerformance:onEnter() - cc.Director:getInstance():setClearColor(cc.c4f(102.0/255, 184.0/255, 204.0/255, 255.0)) + ax.Director:getInstance():setClearColor(ax.color(102.0/255, 184.0/255, 204.0/255, 1.0)) end function SpritePolygonPerformance:onExit() - cc.Director:getInstance():setClearColor(cc.c4f(0.0, 0.0, 0.0, 1.0)) + ax.Director:getInstance():setClearColor(ax.color(0.0, 0.0, 0.0, 1.0)) self:unscheduleUpdate() end function SpritePolygonPerformance:init() local ttfConfig = { fontFilePath = "fonts/arial.ttf", fontSize = 8 } - self._perfLabel = cc.Label:createWithTTF(ttfConfig, "performance test") + self._perfLabel = ax.Label:createWithTTF(ttfConfig, "performance test") self:addChild(self._perfLabel) - self._perfLabel:setPosition(cc.Director:getInstance():getVisibleSize().width / 2, 80) + self._perfLabel:setPosition(ax.Director:getInstance():getVisibleSize().width / 2, 80) self._spriteCount, self._vertCount, self._triCount, self._pixelCount, self._continuousLowDt = 0,0,0,0,0 - - local size = cc.Director:getInstance():getVisibleSize() + + local size = ax.Director:getInstance():getVisibleSize() self._elapsedTime = 0 self._posX,self._leftX = size.width * 0.15, size.width * 0.15 self._rightX = size.width*0.85 @@ -433,8 +433,8 @@ function SpritePolygonPerformance:init() self._elapsedTime = self._elapsedTime + dt local loops = math.floor((0.025 - dt)*1000) if dt < 0.025 and loops > 0 then - self._continuousHighDtTime = cc.clampf(self._continuousHighDtTime-dt*2, 0.0, 1.0) - self._waitingTime = cc.clampf(self._waitingTime-dt, 0.0, 5.0) + self._continuousHighDtTime = ax.clampf(self._continuousHighDtTime-dt*2, 0.0, 1.0) + self._waitingTime = ax.clampf(self._waitingTime-dt, 0.0, 5.0) self._continuousLowDt = self._continuousLowDt + 1 else self._continuousHighDtTime = self._continuousHighDtTime + dt @@ -479,7 +479,7 @@ function SpritePolygonPerformance:initExtend() end function SpritePolygonPerformance:makeSprite() - return cc.Node:create() + return ax.Node:create() end function SpritePolygonPerformance:incrementStats() @@ -496,13 +496,13 @@ end local SpritePolygonPerformanceTestDynamic = class("SpritePolygonPerformanceTestDynamic", SpritePolygonPerformance) function SpritePolygonPerformanceTestDynamic:makeSprite() - local ret = cc.Sprite:create(self._info) - ret:runAction(cc.RepeatForever:create(cc.RotateBy:create(1.0,360.0))) + local ret = ax.Sprite:create(self._info) + ret:runAction(ax.RepeatForever:create(ax.RotateBy:create(1.0,360.0))) return ret end function SpritePolygonPerformanceTestDynamic:initExtend() - self._info = cc.AutoPolygon:generatePolygon(imageFileName) + self._info = ax.AutoPolygon:generatePolygon(imageFileName) self:initIncrementStats() end @@ -526,7 +526,7 @@ end local SpritePerformanceTestDynamic = class("SpritePerformanceTestDynamic", SpritePolygonPerformance) function SpritePerformanceTestDynamic:initExtend() - -- self._info = cc.AutoPolygon:generatePolygon(imageFileName) + -- self._info = ax.AutoPolygon:generatePolygon(imageFileName) self:initIncrementStats() end @@ -539,15 +539,15 @@ function SpritePerformanceTestDynamic:subtitle() end function SpritePerformanceTestDynamic:initIncrementStats() - local t = cc.Sprite:create(imageFileName) + local t = ax.Sprite:create(imageFileName) self._incVert = 4 self._incTri = 2 self._incPix = t:getContentSize().width * t:getContentSize().height end function SpritePerformanceTestDynamic:makeSprite() - local ret = cc.Sprite:create(imageFileName) - ret:runAction(cc.RepeatForever:create(cc.RotateBy:create(1.0,360.0))) + local ret = ax.Sprite:create(imageFileName) + ret:runAction(ax.RepeatForever:create(ax.RotateBy:create(1.0,360.0))) return ret end @@ -556,9 +556,9 @@ end ----SpritePolygonTest ---------------------------------------- function SpritePolygonTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() - Helper.createFunctionTable = + Helper.createFunctionTable = { SpritePolygonTest1.create, SpritePolygonTest2.create, diff --git a/tests/lua-tests/Content/src/SpriteTest/SpriteTest.lua b/tests/lua-tests/Content/src/SpriteTest/SpriteTest.lua index 0982b15c115a..c4446c81fa07 100644 --- a/tests/lua-tests/Content/src/SpriteTest/SpriteTest.lua +++ b/tests/lua-tests/Content/src/SpriteTest/SpriteTest.lua @@ -1,4 +1,4 @@ -local size = cc.Director:getInstance():getWinSize() +local size = ax.Director:getInstance():getWinSize() local kTagTileMap = 1 local kTagSpriteBatchNode = 1 local kTagNode = 2 @@ -29,30 +29,30 @@ function Sprite1.addNewSpriteWithCoords(layer, point) local x = math.floor(math.fmod(idx,5) * 85) local y = math.floor(idx / 5) * 121 - local sprite = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(x,y,85,121) ) + local sprite = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(x,y,85,121) ) layer:addChild( sprite ) - sprite:setPosition( cc.p(point.x, point.y) ) + sprite:setPosition( ax.p(point.x, point.y) ) local action = nil local random = math.random() cclog("random = " .. random) if( random < 0.20 ) then - action = cc.ScaleBy:create(3, 2) + action = ax.ScaleBy:create(3, 2) elseif(random < 0.40) then - action = cc.RotateBy:create(3, 360) + action = ax.RotateBy:create(3, 360) elseif( random < 0.60) then - action = cc.Blink:create(1, 3) + action = ax.Blink:create(1, 3) elseif( random < 0.8 ) then - action = cc.TintBy:create(2, 0, -255, -255) - else - action = cc.FadeOut:create(2) + action = ax.TintBy:create(2, 0, -255, -255) + else + action = ax.FadeOut:create(2) end local action_back = action:reverse() - local seq = cc.Sequence:create( action, action_back) + local seq = ax.Sequence:create( action, action_back) - sprite:runAction( cc.RepeatForever:create(seq) ) + sprite:runAction( ax.RepeatForever:create(seq) ) end function Sprite1.onTouchesEnd(touches, event) @@ -64,12 +64,12 @@ end function Sprite1.create() cclog("sprite1") - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - Sprite1.addNewSpriteWithCoords(layer, cc.p(size.width/2, size.height/2)) + Sprite1.addNewSpriteWithCoords(layer, ax.p(size.width/2, size.height/2)) - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(Sprite1.onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(Sprite1.onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -90,30 +90,30 @@ function SpriteBatchNode1.addNewSpriteWithCoords(layer, point) local x = math.floor(math.fmod(idx,5) * 85) local y = math.floor(idx / 5) * 121 - local sprite = cc.Sprite:createWithTexture(BatchNode:getTexture(), cc.rect(x,y,85,121) ) + local sprite = ax.Sprite:createWithTexture(BatchNode:getTexture(), ax.rect(x,y,85,121) ) layer:addChild( sprite ) - sprite:setPosition( cc.p(point.x, point.y) ) + sprite:setPosition( ax.p(point.x, point.y) ) local action = nil local random = math.random() cclog("random = " .. random) if( random < 0.20 ) then - action = cc.ScaleBy:create(3, 2) + action = ax.ScaleBy:create(3, 2) elseif(random < 0.40) then - action = cc.RotateBy:create(3, 360) + action = ax.RotateBy:create(3, 360) elseif( random < 0.60) then - action = cc.Blink:create(1, 3) + action = ax.Blink:create(1, 3) elseif( random < 0.8 ) then - action = cc.TintBy:create(2, 0, -255, -255) - else - action = cc.FadeOut:create(2) + action = ax.TintBy:create(2, 0, -255, -255) + else + action = ax.FadeOut:create(2) end local action_back = action:reverse() - local seq = cc.Sequence:create( action, action_back) + local seq = ax.Sequence:create( action, action_back) - sprite:runAction( cc.RepeatForever:create(seq) ) + sprite:runAction( ax.RepeatForever:create(seq) ) end function SpriteBatchNode1.onTouchesEnd(touches,event) @@ -124,15 +124,15 @@ function SpriteBatchNode1.onTouchesEnd(touches,event) end function SpriteBatchNode1.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) - local BatchNode = cc.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 50) + local BatchNode = ax.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 50) layer:addChild(BatchNode, 0, kTagSpriteBatchNode) - SpriteBatchNode1.addNewSpriteWithCoords(layer, cc.p(size.width/2, size.height/2)) + SpriteBatchNode1.addNewSpriteWithCoords(layer, ax.p(size.width/2, size.height/2)) - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(Sprite1.onTouchesEnd,cc.Handler.EVENT_TOUCHES_ENDED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(Sprite1.onTouchesEnd,ax.Handler.EVENT_TOUCHES_ENDED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -149,47 +149,47 @@ SpriteColorOpacity.__index = SpriteColorOpacity SpriteColorOpacity.entry = nil function SpriteColorOpacity.setLayerSprite(layer) - local sprite1 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*0, 121*1, 85, 121)) - local sprite2 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*1, 121*1, 85, 121)) - local sprite3 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*2, 121*1, 85, 121)) - local sprite4 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*3, 121*1, 85, 121)) - - local sprite5 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*0, 121*1, 85, 121)) - local sprite6 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*1, 121*1, 85, 121)) - local sprite7 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*2, 121*1, 85, 121)) - local sprite8 = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*3, 121*1, 85, 121)) - - local s = cc.Director:getInstance():getWinSize() - sprite1:setPosition( cc.p( (s.width/5)*1, (s.height/3)*1) ) - sprite2:setPosition( cc.p( (s.width/5)*2, (s.height/3)*1) ) - sprite3:setPosition( cc.p( (s.width/5)*3, (s.height/3)*1) ) - sprite4:setPosition( cc.p( (s.width/5)*4, (s.height/3)*1) ) - sprite5:setPosition( cc.p( (s.width/5)*1, (s.height/3)*2) ) - sprite6:setPosition( cc.p( (s.width/5)*2, (s.height/3)*2) ) - sprite7:setPosition( cc.p( (s.width/5)*3, (s.height/3)*2) ) - sprite8:setPosition( cc.p( (s.width/5)*4, (s.height/3)*2) ) - - local action = cc.FadeIn:create(2) + local sprite1 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*0, 121*1, 85, 121)) + local sprite2 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*1, 121*1, 85, 121)) + local sprite3 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*2, 121*1, 85, 121)) + local sprite4 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*3, 121*1, 85, 121)) + + local sprite5 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*0, 121*1, 85, 121)) + local sprite6 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*1, 121*1, 85, 121)) + local sprite7 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*2, 121*1, 85, 121)) + local sprite8 = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*3, 121*1, 85, 121)) + + local s = ax.Director:getInstance():getWinSize() + sprite1:setPosition( ax.p( (s.width/5)*1, (s.height/3)*1) ) + sprite2:setPosition( ax.p( (s.width/5)*2, (s.height/3)*1) ) + sprite3:setPosition( ax.p( (s.width/5)*3, (s.height/3)*1) ) + sprite4:setPosition( ax.p( (s.width/5)*4, (s.height/3)*1) ) + sprite5:setPosition( ax.p( (s.width/5)*1, (s.height/3)*2) ) + sprite6:setPosition( ax.p( (s.width/5)*2, (s.height/3)*2) ) + sprite7:setPosition( ax.p( (s.width/5)*3, (s.height/3)*2) ) + sprite8:setPosition( ax.p( (s.width/5)*4, (s.height/3)*2) ) + + local action = ax.FadeIn:create(2) local action_back = action:reverse() - local fade = cc.RepeatForever:create( cc.Sequence:create( action, action_back) ) - - local tintred = cc.TintBy:create(2, 0, -255, -255) + local fade = ax.RepeatForever:create( ax.Sequence:create( action, action_back) ) + + local tintred = ax.TintBy:create(2, 0, -255, -255) local tintred_back = tintred:reverse() - local red = cc.RepeatForever:create( cc.Sequence:create( tintred, tintred_back) ) - - local tintgreen = cc.TintBy:create(2, -255, 0, -255) + local red = ax.RepeatForever:create( ax.Sequence:create( tintred, tintred_back) ) + + local tintgreen = ax.TintBy:create(2, -255, 0, -255) local tintgreen_back = tintgreen:reverse() - local green = cc.RepeatForever:create( cc.Sequence:create( tintgreen, tintgreen_back) ) - - local tintblue = cc.TintBy:create(2, -255, -255, 0) + local green = ax.RepeatForever:create( ax.Sequence:create( tintgreen, tintgreen_back) ) + + local tintblue = ax.TintBy:create(2, -255, -255, 0) local tintblue_back = tintblue:reverse() - local blue = cc.RepeatForever:create( cc.Sequence:create( tintblue, tintblue_back) ) - + local blue = ax.RepeatForever:create( ax.Sequence:create( tintblue, tintblue_back) ) + sprite5:runAction(red) sprite6:runAction(green) sprite7:runAction(blue) sprite8:runAction(fade) - + layer:addChild(sprite1, 0, kTagSprite1) layer:addChild(sprite2, 0, kTagSprite2) layer:addChild(sprite3, 0, kTagSprite3) @@ -198,7 +198,7 @@ function SpriteColorOpacity.setLayerSprite(layer) layer:addChild(sprite6, 0, kTagSprite6) layer:addChild(sprite7, 0, kTagSprite7) layer:addChild(sprite8, 0, kTagSprite8) - + layer:registerScriptHandler(SpriteColorOpacity.onEnterOrExit) end @@ -211,17 +211,17 @@ function SpriteColorOpacity.onEnterOrExit(tag) end function SpriteColorOpacity.removeAndAddSprite(dt) - local sprite = Helper.currentLayer:getChildByTag(kTagSprite5) + local sprite = Helper.currentLayer:getChildByTag(kTagSprite5) sprite:retain() - + Helper.currentLayer:removeChild(sprite, false) Helper.currentLayer:addChild(sprite, 0, kTagSprite5) - + sprite:release() end function SpriteColorOpacity.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) SpriteColorOpacity.setLayerSprite(layer) layer:registerScriptHandler(SpriteColorOpacity.onEnterOrExit) @@ -241,34 +241,34 @@ SpriteFrameTest.m_pSprite2 = nil SpriteFrameTest.m_nCounter = 0 function SpriteFrameTest.onEnter() - local s = cc.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") cache:addSpriteFrames("animations/grossini_blue.plist", "animations/grossini_blue.png") - SpriteFrameTest.m_pSprite1 = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - SpriteFrameTest.m_pSprite1:setPosition( cc.p( s.width/2-80, s.height/2) ) + SpriteFrameTest.m_pSprite1 = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + SpriteFrameTest.m_pSprite1:setPosition( ax.p( s.width/2-80, s.height/2) ) - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") spritebatch:addChild(SpriteFrameTest.m_pSprite1) Helper.currentLayer:addChild(spritebatch) local animFrames = {} - for i = 1,14 do + for i = 1,14 do local frame = cache:getSpriteFrame( string.format("grossini_dance_%02d.png", i) ) animFrames[i] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - SpriteFrameTest.m_pSprite1:runAction( cc.RepeatForever:create( cc.Animate:create(animation) ) ) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + SpriteFrameTest.m_pSprite1:runAction( ax.RepeatForever:create( ax.Animate:create(animation) ) ) SpriteFrameTest.m_pSprite1:setFlippedX(false) SpriteFrameTest.m_pSprite1:setFlippedY(false) - SpriteFrameTest.m_pSprite2 = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - SpriteFrameTest.m_pSprite2:setPosition( cc.p( s.width/2 + 80, s.height/2) ) + SpriteFrameTest.m_pSprite2 = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + SpriteFrameTest.m_pSprite2:setPosition( ax.p( s.width/2 + 80, s.height/2) ) Helper.currentLayer:addChild(SpriteFrameTest.m_pSprite2) local moreFrames = {} @@ -287,10 +287,10 @@ function SpriteFrameTest.onEnter() moreFrames[18 + i] = animFrames[i] end - - local animMixed = cc.Animation:createWithSpriteFrames(moreFrames, 0.3) - SpriteFrameTest.m_pSprite2:runAction(cc.RepeatForever:create( cc.Animate:create(animMixed) ) ) + local animMixed = ax.Animation:createWithSpriteFrames(moreFrames, 0.3) + + SpriteFrameTest.m_pSprite2:runAction(ax.RepeatForever:create( ax.Animate:create(animMixed) ) ) SpriteFrameTest.m_pSprite2:setFlippedX(false) SpriteFrameTest.m_pSprite2:setFlippedY(false) @@ -301,7 +301,7 @@ function SpriteFrameTest.onEnter() end function SpriteFrameTest.onExit() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") cache:removeSpriteFramesFromFile("animations/grossini_blue.plist") @@ -348,7 +348,7 @@ function SpriteFrameTest.onEnterOrExit(tag) end function SpriteFrameTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) layer:registerScriptHandler(SpriteFrameTest.onEnterOrExit) @@ -366,15 +366,15 @@ local SpriteFrameAliasNameTest = {} SpriteFrameAliasNameTest.__index = SpriteFrameAliasNameTest function SpriteFrameAliasNameTest.onEnter() - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini-aliases.plist", "animations/grossini-aliases.png") - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width * 0.5, s.height * 0.5)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width * 0.5, s.height * 0.5)) - local spriteBatch = cc.SpriteBatchNode:create("animations/grossini-aliases.png") + local spriteBatch = ax.SpriteBatchNode:create("animations/grossini-aliases.png") cclog("spriteBatch = " .. tostring(tolua.isnull(spriteBatch))) cclog("sprite = " .. tostring(tolua.isnull(sprite))) spriteBatch:addChild(sprite) @@ -386,13 +386,13 @@ function SpriteFrameAliasNameTest.onEnter() animFrames[i] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) -- 14 frames * 1sec = 14 seconds - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) end function SpriteFrameAliasNameTest.onExit() - cc.SpriteFrameCache:getInstance():removeSpriteFramesFromFile("animations/grossini-aliases.plist") + ax.SpriteFrameCache:getInstance():removeSpriteFramesFromFile("animations/grossini-aliases.plist") end function SpriteFrameAliasNameTest.onEnterOrExit(tag) @@ -404,7 +404,7 @@ function SpriteFrameAliasNameTest.onEnterOrExit(tag) end function SpriteFrameAliasNameTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) layer:registerScriptHandler(SpriteFrameAliasNameTest.onEnterOrExit) @@ -423,39 +423,39 @@ local SpriteAnchorPoint = {} SpriteAnchorPoint.__index = SpriteAnchorPoint function SpriteAnchorPoint.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local rotate = cc.RotateBy:create(10, 360) - local action = cc.RepeatForever:create(rotate) - + local s = ax.Director:getInstance():getWinSize() + + local rotate = ax.RotateBy:create(10, 360) + local action = ax.RepeatForever:create(rotate) + for i = 0, 2 do - local sprite = cc.Sprite:create("Images/grossini_dance_atlas.png", cc.rect(85*i, 121*1, 85, 121) ) - sprite:setPosition( cc.p( s.width/4*(i+1), s.height/2) ) - - local point = cc.Sprite:create("Images/r1.png") + local sprite = ax.Sprite:create("Images/grossini_dance_atlas.png", ax.rect(85*i, 121*1, 85, 121) ) + sprite:setPosition( ax.p( s.width/4*(i+1), s.height/2) ) + + local point = ax.Sprite:create("Images/r1.png") point:setScale( 0.25 ) point:setPosition( sprite:getPosition() ) layer:addChild(point, 10) - + if i == 0 then - sprite:setAnchorPoint( cc.p(0, 0) ) + sprite:setAnchorPoint( ax.p(0, 0) ) elseif i == 1 then - sprite:setAnchorPoint( cc.p(0.5, 0.5) ) + sprite:setAnchorPoint( ax.p(0.5, 0.5) ) elseif i == 2 then - sprite:setAnchorPoint( cc.p(1,1) ) + sprite:setAnchorPoint( ax.p(1,1) ) end point:setPosition( sprite:getPosition() ) - + local copy = action:clone() sprite:runAction(copy) layer:addChild(sprite, i) - end + end return layer end function SpriteAnchorPoint.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) layer = SpriteAnchorPoint.initLayer(layer) @@ -473,31 +473,31 @@ SpriteBatchNodeAnchorPoint.__index = SpriteBatchNodeAnchorPoint function SpriteBatchNodeAnchorPoint.initLayer(layer) -- small capacity. Testing resizing. -- Don't use capacity=1 in your real game. It is expensive to resize the capacity - local batch = cc.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 1) - layer:addChild(batch, 0, kTagSpriteBatchNode) + local batch = ax.SpriteBatchNode:create("Images/grossini_dance_atlas.png", 1) + layer:addChild(batch, 0, kTagSpriteBatchNode) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local rotate = cc.RotateBy:create(10, 360) - local action = cc.RepeatForever:create(rotate) + local rotate = ax.RotateBy:create(10, 360) + local action = ax.RepeatForever:create(rotate) for i=0,2 do - local sprite = cc.Sprite:createWithTexture(batch:getTexture(), cc.rect(85*i, 121*1, 85, 121)) - sprite:setPosition( cc.p( s.width/4*(i+1), s.height/2) ) + local sprite = ax.Sprite:createWithTexture(batch:getTexture(), ax.rect(85*i, 121*1, 85, 121)) + sprite:setPosition( ax.p( s.width/4*(i+1), s.height/2) ) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale( 0.25 ) - point:setPosition( cc.p(sprite:getPosition()) ) + point:setPosition( ax.p(sprite:getPosition()) ) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint( cc.p(0,0) ) + sprite:setAnchorPoint( ax.p(0,0) ) elseif i == 1 then - sprite:setAnchorPoint( cc.p(0.5, 0.5) ) + sprite:setAnchorPoint( ax.p(0.5, 0.5) ) elseif i == 2 then - sprite:setAnchorPoint( cc.p(1,1) ) + sprite:setAnchorPoint( ax.p(1,1) ) end - point:setPosition( cc.p(sprite:getPosition()) ) + point:setPosition( ax.p(sprite:getPosition()) ) local copy = action:clone() sprite:runAction(copy) @@ -508,7 +508,7 @@ function SpriteBatchNodeAnchorPoint.initLayer(layer) end function SpriteBatchNodeAnchorPoint.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) layer = SpriteBatchNodeAnchorPoint.initLayer(layer) @@ -527,8 +527,8 @@ local SpriteOffsetAnchorRotation = {} SpriteOffsetAnchorRotation.__index = SpriteOffsetAnchorRotation function SpriteOffsetAnchorRotation.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") @@ -536,51 +536,51 @@ function SpriteOffsetAnchorRotation.initLayer(layer) -- -- Animation using Sprite batch -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p( s.width/4*(i+1), s.height/2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p( s.width/4*(i+1), s.height/2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale( 0.25 ) point:setPosition( sprite:getPosition() ) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint( cc.p(0, 0) ) + sprite:setAnchorPoint( ax.p(0, 0) ) elseif i == 1 then - sprite:setAnchorPoint( cc.p(0.5, 0.5) ) + sprite:setAnchorPoint( ax.p(0.5, 0.5) ) elseif i == 2 then - sprite:setAnchorPoint( cc.p(1,1) ) + sprite:setAnchorPoint( ax.p(1,1) ) end - point:setPosition( cc.p(sprite:getPosition()) ) + point:setPosition( ax.p(sprite:getPosition()) ) local animFrames = {} - - for i = 0, 13 do + + for i = 0, 13 do local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png",(i+1))) animFrames[i + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create( cc.Animate:create(animation) ) ) - sprite:runAction(cc.RepeatForever:create(cc.RotateBy:create(10, 360) ) ) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create( ax.Animate:create(animation) ) ) + sprite:runAction(ax.RepeatForever:create(ax.RotateBy:create(10, 360) ) ) layer:addChild(sprite, 0) - end + end return layer end function SpriteOffsetAnchorRotation.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorRotation.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorRotation.eventHandler) Helper.initWithLayer(layer) @@ -601,13 +601,13 @@ SpriteBatchNodeOffsetAnchorRotation.__index = SpriteBatchNodeOffsetAnchorRotatio function SpriteBatchNodeOffsetAnchorRotation.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") cclog("1") layer:addChild(spritebatch) @@ -616,23 +616,23 @@ function SpriteBatchNodeOffsetAnchorRotation.initLayer(layer) -- -- Animation using Sprite BatchNode -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition( cc.p( s.width/4*(i+1), s.height/2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition( ax.p( s.width/4*(i+1), s.height/2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale( 0.25 ) - point:setPosition( cc.p(sprite:getPosition()) ) + point:setPosition( ax.p(sprite:getPosition()) ) layer:addChild(point, 200) if i == 0 then - sprite:setAnchorPoint( cc.p(0,0) ) + sprite:setAnchorPoint( ax.p(0,0) ) elseif i == 1 then - sprite:setAnchorPoint( cc.p(0.5, 0.5) ) + sprite:setAnchorPoint( ax.p(0.5, 0.5) ) elseif i == 2 then - sprite:setAnchorPoint( cc.p(1,1) ) + sprite:setAnchorPoint( ax.p(1,1) ) end - point:setPosition( cc.p(sprite:getPosition()) ) + point:setPosition( ax.p(sprite:getPosition()) ) local animFrames = {} for k = 0, 13 do @@ -640,9 +640,9 @@ function SpriteBatchNodeOffsetAnchorRotation.initLayer(layer) animFrames[k + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create( cc.Animate:create(animation) )) - sprite:runAction(cc.RepeatForever:create(cc.RotateBy:create(10, 360) )) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create( ax.Animate:create(animation) )) + sprite:runAction(ax.RepeatForever:create(ax.RotateBy:create(10, 360) )) spritebatch:addChild(sprite, i) end @@ -651,14 +651,14 @@ end function SpriteBatchNodeOffsetAnchorRotation.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteBatchNodeOffsetAnchorRotation.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorRotation.eventHandler) Helper.initWithLayer(layer) @@ -678,34 +678,34 @@ local SpriteOffsetAnchorScale = {} SpriteOffsetAnchorScale.__index = SpriteOffsetAnchorScale function SpriteOffsetAnchorScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - + for i = 0,2 do -- -- Animation using Sprite BatchNode -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition( cc.p( s.width/4*(i+1), s.height/2) ) - - local point = cc.Sprite:create("Images/r1.png") + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition( ax.p( s.width/4*(i+1), s.height/2) ) + + local point = ax.Sprite:create("Images/r1.png") point:setScale( 0.25 ) point:setPosition( sprite:getPosition() ) layer:addChild(point, 1) - + if i == 0 then - sprite:setAnchorPoint( cc.p(0, 0) ) + sprite:setAnchorPoint( ax.p(0, 0) ) elseif i == 1 then - sprite:setAnchorPoint( cc.p(0.5, 0.5) ) + sprite:setAnchorPoint( ax.p(0.5, 0.5) ) elseif i == 2 then - sprite:setAnchorPoint( cc.p(1,1) ) + sprite:setAnchorPoint( ax.p(1,1) ) end - - point:setPosition( cc.p(sprite:getPosition()) ) - + + point:setPosition( ax.p(sprite:getPosition()) ) + local animFrames = {} for i = 0, 13 do @@ -713,14 +713,14 @@ function SpriteOffsetAnchorScale.initLayer(layer) animFrames[i + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create( cc.Animate:create(animation) )) - - local scale = cc.ScaleBy:create(2, 2) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create( ax.Animate:create(animation) )) + + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) - + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) + layer:addChild(sprite, 0) end @@ -729,14 +729,14 @@ end function SpriteOffsetAnchorScale.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorScale.eventHandler) Helper.initWithLayer(layer) @@ -755,31 +755,31 @@ end local SpriteBatchNodeOffsetAnchorScale = {} function SpriteBatchNodeOffsetAnchorScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - local spritesheet = cc.SpriteBatchNode:create("animations/grossini.png") + local spritesheet = ax.SpriteBatchNode:create("animations/grossini.png") layer:addChild(spritesheet) for i = 0,2 do -- Animation using Sprite BatchNode - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width/4*(i+1), s.height/2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width/4*(i+1), s.height/2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 200) if i == 0 then - sprite:setAnchorPoint(cc.p(0,0)) + sprite:setAnchorPoint(ax.p(0,0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end point:setPosition(sprite:getPosition()) @@ -792,13 +792,13 @@ function SpriteBatchNodeOffsetAnchorScale.initLayer(layer) animFrames[k + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) - local scale = cc.ScaleBy:create(2, 2) + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) spritesheet:addChild(sprite, i) end @@ -807,7 +807,7 @@ function SpriteBatchNodeOffsetAnchorScale.initLayer(layer) end function SpriteBatchNodeOffsetAnchorScale.onExit() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end @@ -819,7 +819,7 @@ function SpriteBatchNodeOffsetAnchorScale.eventHandler(tag) end function SpriteBatchNodeOffsetAnchorScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorScale.eventHandler) @@ -840,9 +840,9 @@ SpriteOffsetAnchorSkew.__index = SpriteOffsetAnchorSkew function SpriteOffsetAnchorSkew.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") @@ -850,20 +850,20 @@ function SpriteOffsetAnchorSkew.initLayer(layer) -- -- Animation using Sprite batch -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) elseif i == 2 then - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end point:setPosition(sprite:getPosition()) @@ -874,33 +874,33 @@ function SpriteOffsetAnchorSkew.initLayer(layer) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) - local skewX = cc.SkewBy:create(2, 45, 0) + local skewX = ax.SkewBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.SkewBy:create(2, 0, 45) + local skewY = ax.SkewBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) layer:addChild(sprite, 0) - end + end return layer end function SpriteOffsetAnchorSkew.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorSkew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorSkew.eventHandler) Helper.initWithLayer(layer) @@ -918,51 +918,51 @@ SpriteOffsetAnchorRotationalSkew.__index = SpriteOffsetAnchorRotationalSkew function SpriteOffsetAnchorRotationalSkew.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - + for i = 0, 2 do -- -- Animation using Sprite batch -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width/4*(i+1), s.height/2)) - - local point = cc.Sprite:create("Images/r1.png") - + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width/4*(i+1), s.height/2)) + + local point = ax.Sprite:create("Images/r1.png") + point:setScale(0.25) - point:setPosition(cc.p(sprite:getPosition())) + point:setPosition(ax.p(sprite:getPosition())) layer:addChild(point, 1) - + if i == 0 then - sprite:setAnchorPoint(cc.p(0,0)) + sprite:setAnchorPoint(ax.p(0,0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) elseif i == 2 then - sprite:setAnchorPoint(cc.p(1,1)) + sprite:setAnchorPoint(ax.p(1,1)) end - - point:setPosition(cc.p(sprite:getPosition())) - + + point:setPosition(ax.p(sprite:getPosition())) + local animFrames = {} for i = 0,13 do local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png", (i+1))) animFrames[i + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) - - local skewX = cc.RotateBy:create(2, 45) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) + + local skewX = ax.RotateBy:create(2, 45) local skewX_back = skewX:reverse() - local skewY = cc.RotateBy:create(2, -45) + local skewY = ax.RotateBy:create(2, -45) local skewY_back = skewY:reverse() - - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) - + + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) + layer:addChild(sprite, 0) end return layer @@ -970,14 +970,14 @@ end function SpriteOffsetAnchorRotationalSkew.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorRotationalSkew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorRotationalSkew.eventHandler) Helper.initWithLayer(layer) @@ -997,53 +997,53 @@ SpriteBatchNodeOffsetAnchorSkew.__index = SpriteBatchNodeOffsetAnchorSkew function SpriteBatchNodeOffsetAnchorSkew.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") layer:addChild(spritebatch) for i = 0, 2 do -- -- Animation using Sprite batch -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) - point:setPosition(cc.p(sprite:getPosition())) + point:setPosition(ax.p(sprite:getPosition())) layer:addChild(point, 200) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) elseif i == 2 then - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end - point:setPosition(cc.p(sprite:getPosition())) - + point:setPosition(ax.p(sprite:getPosition())) + local animFrames = {} for j = 0, 13 do local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png", j + 1)) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) - local skewX = cc.SkewBy:create(2, 45, 0) + local skewX = ax.SkewBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.SkewBy:create(2, 0, 45) + local skewY = ax.SkewBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) spritebatch:addChild(sprite, i) end @@ -1053,14 +1053,14 @@ end function SpriteBatchNodeOffsetAnchorSkew.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteBatchNodeOffsetAnchorSkew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorSkew.eventHandler) Helper.initWithLayer(layer) @@ -1073,61 +1073,61 @@ end -- -- SpriteBatchNodeOffsetAnchorRotationalSkew --- +-- local SpriteBatchNodeOffsetAnchorRotationalSkew = {} SpriteBatchNodeOffsetAnchorRotationalSkew.__index = SpriteBatchNodeOffsetAnchorRotationalSkew function SpriteBatchNodeOffsetAnchorRotationalSkew.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") layer:addChild(spritebatch) - + for i = 0, 2 do -- -- Animation using Sprite batch -- - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width/4*(i+1), s.height/2)) - - local point = cc.Sprite:create("Images/r1.png") - + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width/4*(i+1), s.height/2)) + + local point = ax.Sprite:create("Images/r1.png") + point:setScale(0.25) - point:setPosition(cc.p(sprite:getPosition())) + point:setPosition(ax.p(sprite:getPosition())) layer:addChild(point, 200) - + if i == 0 then - sprite:setAnchorPoint(cc.p(0,0)) + sprite:setAnchorPoint(ax.p(0,0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) elseif i == 2 then - sprite:setAnchorPoint(cc.p(1,1)) + sprite:setAnchorPoint(ax.p(1,1)) end - - point:setPosition(cc.p(sprite:getPosition())) - + + point:setPosition(ax.p(sprite:getPosition())) + local animFrames = {} for j = 0, 13 do local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png", (j+1))) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) - - local skewX = cc.RotateBy:create(2, 45) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) + + local skewX = ax.RotateBy:create(2, 45) local skewX_back = skewX:reverse() - local skewY = cc.RotateBy:create(2, -45) + local skewY = ax.RotateBy:create(2, -45) local skewY_back = skewY:reverse() - - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) - + + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) + spritebatch:addChild(sprite, i) end @@ -1137,14 +1137,14 @@ end -- remove resources function SpriteBatchNodeOffsetAnchorRotationalSkew.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteBatchNodeOffsetAnchorRotationalSkew.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorRotationalSkew.eventHandler) Helper.initWithLayer(layer) @@ -1157,32 +1157,32 @@ end -- -- SpriteOffsetAnchorSkewScale --- +-- local SpriteOffsetAnchorSkewScale = {} function SpriteOffsetAnchorSkewScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") for i = 0, 2 do -- Animation using Sprite batch - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint(cc.p(0,0)) + sprite:setAnchorPoint(ax.p(0,0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end point:setPosition(sprite:getPosition()) @@ -1193,23 +1193,23 @@ function SpriteOffsetAnchorSkewScale.initLayer(layer) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) -- Skew - local skewX = cc.SkewBy:create(2, 45, 0) + local skewX = ax.SkewBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.SkewBy:create(2, 0, 45) + local skewY = ax.SkewBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) -- Scale - local scale = cc.ScaleBy:create(2, 2) + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) layer:addChild(sprite, 0) end @@ -1219,14 +1219,14 @@ end function SpriteOffsetAnchorSkewScale.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorSkewScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorSkewScale.eventHandler) Helper.initWithLayer(layer) @@ -1242,31 +1242,31 @@ end local SpriteOffsetAnchorRotationalSkewScale = {} function SpriteOffsetAnchorRotationalSkewScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - + for i = 0, 2 do -- Animation using Sprite batch - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width/4*(i+1), s.height/2)) - - local point = cc.Sprite:create("Images/r1.png") + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width/4*(i+1), s.height/2)) + + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end - + point:setPosition(sprite:getPosition()) local animFrames = {} @@ -1274,23 +1274,23 @@ function SpriteOffsetAnchorRotationalSkewScale.initLayer(layer) local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png", (j+1))) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) - + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) + -- Skew - local skewX = cc.RotateBy:create(2, 45, 0) + local skewX = ax.RotateBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.RotateBy:create(2, 0, 45) + local skewY = ax.RotateBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) - + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) + -- Scale - local scale = cc.ScaleBy:create(2, 2) + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) layer:addChild(sprite, i) end @@ -1300,14 +1300,14 @@ end function SpriteOffsetAnchorRotationalSkewScale.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorRotationalSkewScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorRotationalSkewScale.eventHandler) Helper.initWithLayer(layer) @@ -1323,35 +1323,35 @@ end local SpriteBatchNodeOffsetAnchorSkewScale = {} function SpriteBatchNodeOffsetAnchorSkewScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") layer:addChild(spritebatch) for i = 0, 2 do -- Animation using Sprite batch - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 200) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end - point:setPosition(sprite:getPosition()) + point:setPosition(sprite:getPosition()) local animFrames = {} for j = 0, 13 do @@ -1359,24 +1359,24 @@ function SpriteBatchNodeOffsetAnchorSkewScale.initLayer(layer) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) -- skew - local skewX = cc.SkewBy:create(2, 45, 0) + local skewX = ax.SkewBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.SkewBy:create(2, 0, 45) + local skewY = ax.SkewBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) - -- scale - local scale = cc.ScaleBy:create(2, 2) + -- scale + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) spritebatch:addChild(sprite, i) end @@ -1384,14 +1384,14 @@ end function SpriteBatchNodeOffsetAnchorSkewScale.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteBatchNodeOffsetAnchorSkewScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorSkewScale.eventHandler) Helper.initWithLayer(layer) @@ -1403,24 +1403,24 @@ end -- -- SpriteBatchNodeOffsetAnchorRotationalSkewScale --- +-- local SpriteBatchNodeOffsetAnchorRotationalSkewScale = {} function SpriteBatchNodeOffsetAnchorRotationalSkewScale.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() - - local cache = cc.SpriteFrameCache:getInstance() + local s = ax.Director:getInstance():getWinSize() + + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") - local spritebatch = cc.SpriteBatchNode:create("animations/grossini.png") + local spritebatch = ax.SpriteBatchNode:create("animations/grossini.png") layer:addChild(spritebatch) - + for i = 0, 2 do -- Animation using Sprite batch - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width/4*(i+1), s.height/2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width/4*(i+1), s.height/2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) @@ -1428,13 +1428,13 @@ function SpriteBatchNodeOffsetAnchorRotationalSkewScale.initLayer(layer) layer:addChild(point, 200) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end - + point:setPosition(sprite:getPosition()) local animFrames = {} @@ -1442,38 +1442,38 @@ function SpriteBatchNodeOffsetAnchorRotationalSkewScale.initLayer(layer) local frame = cache:getSpriteFrame(string.format("grossini_dance_%02d.png", j+1)) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) - + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) + -- Skew - local skewX = cc.RotateBy:create(2, 45, 0) + local skewX = ax.RotateBy:create(2, 45, 0) local skewX_back = skewX:reverse() - local skewY = cc.RotateBy:create(2, 0, 45) + local skewY = ax.RotateBy:create(2, 0, 45) local skewY_back = skewY:reverse() - local seq_skew = cc.Sequence:create(skewX, skewX_back, skewY, skewY_back) - sprite:runAction(cc.RepeatForever:create(seq_skew)) - + local seq_skew = ax.Sequence:create(skewX, skewX_back, skewY, skewY_back) + sprite:runAction(ax.RepeatForever:create(seq_skew)) + -- Scale - local scale = cc.ScaleBy:create(2, 2) + local scale = ax.ScaleBy:create(2, 2) local scale_back = scale:reverse() - local seq_scale = cc.Sequence:create(scale, scale_back) - sprite:runAction(cc.RepeatForever:create(seq_scale)) - + local seq_scale = ax.Sequence:create(scale, scale_back) + sprite:runAction(ax.RepeatForever:create(seq_scale)) + spritebatch:addChild(sprite, i) end end function SpriteBatchNodeOffsetAnchorRotationalSkewScale.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteBatchNodeOffsetAnchorRotationalSkewScale.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteBatchNodeOffsetAnchorRotationalSkewScale.eventHandler) Helper.initWithLayer(layer) SpriteBatchNodeOffsetAnchorRotationalSkewScale.initLayer(layer) @@ -1488,28 +1488,28 @@ end -- local SpriteOffsetAnchorFlip = {} function SpriteOffsetAnchorFlip.initLayer(layer) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:addSpriteFrames("animations/grossini.plist") cache:addSpriteFrames("animations/grossini_gray.plist", "animations/grossini_gray.png") for i = 0, 2 do -- Animation using Sprite batch - local sprite = cc.Sprite:createWithSpriteFrameName("grossini_dance_01.png") - sprite:setPosition(cc.p(s.width / 4 * (i + 1), s.height / 2)) + local sprite = ax.Sprite:createWithSpriteFrameName("grossini_dance_01.png") + sprite:setPosition(ax.p(s.width / 4 * (i + 1), s.height / 2)) - local point = cc.Sprite:create("Images/r1.png") + local point = ax.Sprite:create("Images/r1.png") point:setScale(0.25) point:setPosition(sprite:getPosition()) layer:addChild(point, 1) if i == 0 then - sprite:setAnchorPoint(cc.p(0, 0)) + sprite:setAnchorPoint(ax.p(0, 0)) elseif i == 1 then - sprite:setAnchorPoint(cc.p(0.5, 0.5)) + sprite:setAnchorPoint(ax.p(0.5, 0.5)) else - sprite:setAnchorPoint(cc.p(1, 1)) + sprite:setAnchorPoint(ax.p(1, 1)) end point:setPosition(sprite:getPosition()) @@ -1520,16 +1520,16 @@ function SpriteOffsetAnchorFlip.initLayer(layer) animFrames[j + 1] = frame end - local animation = cc.Animation:createWithSpriteFrames(animFrames, 0.3) - sprite:runAction(cc.RepeatForever:create(cc.Animate:create(animation))) + local animation = ax.Animation:createWithSpriteFrames(animFrames, 0.3) + sprite:runAction(ax.RepeatForever:create(ax.Animate:create(animation))) - local flip = cc.FlipY:create(true) - local flip_back = cc.FlipY:create(false) - local delay = cc.DelayTime:create(1) - local delay2 = cc.DelayTime:create(1) + local flip = ax.FlipY:create(true) + local flip_back = ax.FlipY:create(false) + local delay = ax.DelayTime:create(1) + local delay2 = ax.DelayTime:create(1) - local seq = cc.Sequence:create(delay, flip, delay2, flip_back) - sprite:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(delay, flip, delay2, flip_back) + sprite:runAction(ax.RepeatForever:create(seq)) layer:addChild(sprite, 0) end @@ -1537,14 +1537,14 @@ end function SpriteOffsetAnchorFlip.eventHandler(tag) if tag == "exit" then - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("animations/grossini.plist") cache:removeSpriteFramesFromFile("animations/grossini_gray.plist") end end function SpriteOffsetAnchorFlip.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() layer:registerScriptHandler(SpriteOffsetAnchorFlip.eventHandler) Helper.initWithLayer(layer) @@ -1557,8 +1557,8 @@ end function SpriteTest() - local scene = cc.Scene:create() - + local scene = ax.Scene:create() + Helper.createFunctionTable = { Sprite1.create, SpriteBatchNode1.create, diff --git a/tests/lua-tests/Content/src/TerrainTest/TerrainTest.lua b/tests/lua-tests/Content/src/TerrainTest/TerrainTest.lua index 8869abb6bb13..7b8a5c21f856 100644 --- a/tests/lua-tests/Content/src/TerrainTest/TerrainTest.lua +++ b/tests/lua-tests/Content/src/TerrainTest/TerrainTest.lua @@ -4,7 +4,7 @@ require "axmol.3d.3dConstants" ----TerrainSimple ---------------------------------------- local TerrainSimple = class("TerrainSimple", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -17,12 +17,12 @@ end function TerrainSimple:init() - local visibleSize = cc.Director:getInstance():getVisibleSize() + local visibleSize = ax.Director:getInstance():getVisibleSize() --use custom camera - self._camera = cc.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 800) - self._camera:setCameraFlag(cc.CameraFlag.USER1) - self._camera:setPosition3D(cc.vec3(-1, 1.6, 4)) + self._camera = ax.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 800) + self._camera:setCameraFlag(ax.CameraFlag.USER1) + self._camera:setPosition3D(ax.vec3(-1, 1.6, 4)) self:addChild(self._camera) Helper.initWithLayer(self) @@ -35,16 +35,16 @@ function TerrainSimple:init() local detailMapA = { _detailMapSrc = "TerrainTest/GreenSkin.jpg", _detailMapSize = 35} local terrainData = { _heightMapSrc = "TerrainTest/heightmap16.jpg", _alphaMapSrc = "TerrainTest/alphamap.png" , _detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4 } - self._terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT) + self._terrain = ax.Terrain:create(terrainData,ax.Terrain.CrackFixedType.SKIRT) self._terrain:setLODDistance(3.2, 6.4, 9.6) self._terrain:setMaxDetailMapAmount(4) self:addChild(self._terrain) self._terrain:setCameraMask(2) self._terrain:setDrawWire(false) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) - local delta = cc.Director:getInstance():getDeltaTime() + local delta = ax.Director:getInstance():getDeltaTime() local touch = touches[1] local location = touch:getLocation() local previousLocation = touch:getPreviousLocation() @@ -53,11 +53,11 @@ function TerrainSimple:init() local matTransform = self:getNodeToWorldTransform() local cameraDir = {x = -matTransform[9], y = -matTransform[10], z = -matTransform[11]} - cameraDir = cc.vec3normalize(cameraDir) + cameraDir = ax.vec3normalize(cameraDir) cameraDir.y = 0 local cameraRightDir = {x = matTransform[1], y = matTransform[2], z = matTransform[3]} - cameraRightDir = cc.vec3normalize(cameraRightDir) + cameraRightDir = ax.vec3normalize(cameraRightDir) cameraRightDir.y = 0 local cameraPos = self._camera:getPosition3D() @@ -65,14 +65,14 @@ function TerrainSimple:init() cameraPos = { x = cameraPos.x + cameraRightDir.x * newPos.x * 0.5 * delta, y = cameraPos.y + cameraRightDir.y * newPos.x * 0.5 * delta, z = cameraPos.z + cameraRightDir.z * newPos.x * 0.5 * delta } self._camera:setPosition3D(cameraPos) - end,cc.Handler.EVENT_TOUCHES_MOVED) + end,ax.Handler.EVENT_TOUCHES_MOVED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) --add Particle3D for test blend - local rootps = cc.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:startParticleSystem() self:addChild(rootps, 0, 0) end @@ -94,16 +94,16 @@ local PLAER_STATE = LEFT = 0, RIGHT = 1, IDLE = 2, - FORWARD = 3, + FORWARD = 3, BACKWARD = 4, } local PLAYER_HEIGHT = 0 -local camera_offset = cc.vec3(0, 45, 60) +local camera_offset = ax.vec3(0, 45, 60) local Player = class("Player", function(file, cam, terrain) - local sprite = cc.Sprite3D:create(file) + local sprite = ax.Sprite3D:create(file) if nil ~= sprite then sprite._headingAngle = 0 sprite._playerState = PLAER_STATE.IDLE @@ -115,53 +115,53 @@ end) function Player:ctor() -- body - self:init() + self:init() end function Player:init() - self._headingAxis = cc.vec3(0.0, 0.0, 0.0) + self._headingAxis = ax.vec3(0.0, 0.0, 0.0) self:scheduleUpdateWithPriorityLua(function(dt) local curPos = self:getPosition3D() if self._playerState == PLAER_STATE.IDLE then elseif self._playerState == PLAER_STATE.FORWARD then - local newFaceDir = cc.vec3sub(self._targetPos, curPos) + local newFaceDir = ax.vec3sub(self._targetPos, curPos) newFaceDir.y = 0.0 - newFaceDir = cc.vec3normalize(newFaceDir) - local offset = cc.vec3mul(newFaceDir, 25.0 * dt) - curPos = cc.vec3add(curPos, offset) + newFaceDir = ax.vec3normalize(newFaceDir) + local offset = ax.vec3mul(newFaceDir, 25.0 * dt) + curPos = ax.vec3add(curPos, offset) self:setPosition3D(curPos) elseif self._playerState == PLAER_STATE.BACKWARD then - + local transform = self:getNodeToWorldTransform() - local forward_vec = cc.vec3(-transform[9], -transform[10], -transform[11]) - forward_vec = cc.vec3normalize(forward_vec) - self:setPosition3D(cc.vec3sub(curPos, cc.vec3mul(forward_vec, 15 * dt))) + local forward_vec = ax.vec3(-transform[9], -transform[10], -transform[11]) + forward_vec = ax.vec3normalize(forward_vec) + self:setPosition3D(ax.vec3sub(curPos, ax.vec3mul(forward_vec, 15 * dt))) elseif self._playerState == PLAER_STATE.LEFT then - player:setRotation3D(cc.vec3(curPos.x, curPos.y + 25 * dt, curPos.z)) + player:setRotation3D(ax.vec3(curPos.x, curPos.y + 25 * dt, curPos.z)) elseif self._playerState == PLAER_STATE.RIGHT then - player:setRotation3D(cc.vec3(curPos.x, curPos.y - 25 * dt, curPos.z)) + player:setRotation3D(ax.vec3(curPos.x, curPos.y - 25 * dt, curPos.z)) end - local normal = cc.vec3(0.0, 0.0, 0.0) + local normal = ax.vec3(0.0, 0.0, 0.0) local player_h, normal = self._terrain:getHeight(self:getPositionX(), self:getPositionZ(), normal) self:setPositionY(player_h + PLAYER_HEIGHT) --need to scriptfile - local q2 = cc.quaternion_createFromAxisAngle(cc.vec3(0, 1, 0), -math.pi) - local headingQ = cc.quaternion_createFromAxisAngle(self._headingAxis, self._headingAngle) + local q2 = ax.quaternion_createFromAxisAngle(ax.vec3(0, 1, 0), -math.pi) + local headingQ = ax.quaternion_createFromAxisAngle(self._headingAxis, self._headingAngle) local x = headingQ.w * q2.x + headingQ.x * q2.w + headingQ.y * q2.z - headingQ.z * q2.y local y = headingQ.w * q2.y - headingQ.x * q2.z + headingQ.y * q2.w + headingQ.z * q2.x local z = headingQ.w * q2.z + headingQ.x * q2.y - headingQ.y * q2.x + headingQ.z * q2.w local w = headingQ.w * q2.w - headingQ.x * q2.x - headingQ.y * q2.y - headingQ.z * q2.z - headingQ = cc.quaternion(x, y, z, w) + headingQ = ax.quaternion(x, y, z, w) self:setRotationQuat(headingQ) - local vec_offset = cc.vec4(camera_offset.x, camera_offset.y, camera_offset.z, 1) + local vec_offset = ax.vec4(camera_offset.x, camera_offset.y, camera_offset.z, 1) local transform = self:getNodeToWorldTransform() vec_offset = mat4_transformVector(transform, vec_offset) local playerPos = self:getPosition3D() - self._cam:setPosition3D(cc.vec3add(playerPos, camera_offset)) + self._cam:setPosition3D(ax.vec3add(playerPos, camera_offset)) self:updateState() end, 0) @@ -175,9 +175,9 @@ end function Player:updateState() if self._playerState == PLAER_STATE.FORWARD then - local player_pos = cc.p(self:getPositionX(),self:getPositionZ()) - local targetPos = cc.p(self._targetPos.x, self._targetPos.z) - local dist = cc.pGetDistance(player_pos, targetPos) + local player_pos = ax.p(self:getPositionX(),self:getPositionZ()) + local targetPos = ax.p(self._targetPos.x, self._targetPos.z) + local dist = ax.pGetDistance(player_pos, targetPos) if dist < 1 then self._playerState = PLAER_STATE.IDLE end @@ -185,7 +185,7 @@ function Player:updateState() end local TerrainWalkThru = class("TerrainWalkThru", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) return layer end) @@ -199,11 +199,11 @@ function TerrainWalkThru:init() Helper.titleLabel:setString(self:title()) Helper.subtitleLabel:setString(self:subtitle()) - local listener = cc.EventListenerTouchAllAtOnce:create() + local listener = ax.EventListenerTouchAllAtOnce:create() listener:registerScriptHandler(function (touches, event) - end,cc.Handler.EVENT_TOUCHES_BEGAN) + end,ax.Handler.EVENT_TOUCHES_BEGAN) listener:registerScriptHandler(function (touches, event) @@ -211,45 +211,45 @@ function TerrainWalkThru:init() local location = touch:getLocationInView() if self._camera ~= nil then if self._player ~= nil then - local nearP = cc.vec3(location.x, location.y, 0.0) - local farP = cc.vec3(location.x, location.y, 1.0) + local nearP = ax.vec3(location.x, location.y, 0.0) + local farP = ax.vec3(location.x, location.y, 1.0) - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() nearP = self._camera:unproject(size, nearP, nearP) farP = self._camera:unproject(size, farP, farP) - local dir = cc.vec3sub(farP, nearP) - dir = cc.vec3normalize(dir) + local dir = ax.vec3sub(farP, nearP) + dir = ax.vec3normalize(dir) - local collisionPoint = cc.vec3(-999,-999,-999) - local ray = cc.Ray:new(nearP, dir) + local collisionPoint = ax.vec3(-999,-999,-999) + local ray = ax.Ray:new(nearP, dir) local isInTerrain = true isInTerrain, collisionPoint = self._terrain:getIntersectionPoint(ray, collisionPoint) - if( not isInTerrain) then + if( not isInTerrain) then self._player._playerState = PLAER_STATE.IDLE return end local playerPos = self._player:getPosition3D() - dir = cc.vec3sub(collisionPoint, playerPos) + dir = ax.vec3sub(collisionPoint, playerPos) dir.y = 0 - dir = cc.vec3normalize(dir) + dir = ax.vec3normalize(dir) self._player._headingAngle = -1 * math.acos(-dir.z) - self._player._headingAxis = vec3_cross(dir, cc.vec3(0, 0, -1), self._player._headingAxis) + self._player._headingAxis = vec3_cross(dir, ax.vec3(0, 0, -1), self._player._headingAxis) self._player._targetPos = collisionPoint -- self._player:forward() self._player._playerState = PLAER_STATE.FORWARD end end - end,cc.Handler.EVENT_TOUCHES_ENDED) + end,ax.Handler.EVENT_TOUCHES_ENDED) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, self) - local visibleSize = cc.Director:getInstance():getVisibleSize() - self._camera = cc.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 200) - self._camera:setCameraFlag(cc.CameraFlag.USER1) + local visibleSize = ax.Director:getInstance():getVisibleSize() + self._camera = ax.Camera:createPerspective(60, visibleSize.width/visibleSize.height, 0.1, 200) + self._camera:setCameraFlag(ax.CameraFlag.USER1) self:addChild(self._camera) local detailMapR = { _detailMapSrc = "TerrainTest/dirt.jpg", _detailMapSize = 35} @@ -258,7 +258,7 @@ function TerrainWalkThru:init() local detailMapA = { _detailMapSrc = "TerrainTest/GreenSkin.jpg", _detailMapSize = 20} local terrainData = { _heightMapSrc = "TerrainTest/heightmap16.jpg", _alphaMapSrc = "TerrainTest/alphamap.png" , _detailMaps = {detailMapR, detailMapG, detailMapB, detailMapA}, _detailMapAmount = 4, _mapHeight = 40.0, _mapScale = 2.0 } - self._terrain = cc.Terrain:create(terrainData,cc.Terrain.CrackFixedType.SKIRT) + self._terrain = ax.Terrain:create(terrainData,ax.Terrain.CrackFixedType.SKIRT) self._terrain:setMaxDetailMapAmount(4) self._terrain:setCameraMask(2) self._terrain:setDrawWire(false) @@ -272,27 +272,27 @@ function TerrainWalkThru:init() self._player:setPositionY(self._terrain:getHeight(self._player:getPositionX(), self._player:getPositionZ()) + PLAYER_HEIGHT) --add Particle3D for test blend - local rootps = cc.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") - rootps:setCameraMask(cc.CameraFlag.USER1) + local rootps = ax.PUParticleSystem3D:create("Particle3D/scripts/mp_torch.pu") + rootps:setCameraMask(ax.CameraFlag.USER1) rootps:setScale(30.0) rootps:startParticleSystem() self._player:addChild(rootps) --add BillBoard for test blend - local billboard = cc.BillBoard:create("Images/btn-play-normal.png") - billboard:setPosition3D(cc.vec3(0,180,0)) - billboard:setCameraMask(cc.CameraFlag.USER1) + local billboard = ax.BillBoard:create("Images/btn-play-normal.png") + billboard:setPosition3D(ax.vec3(0,180,0)) + billboard:setCameraMask(ax.CameraFlag.USER1) self._player:addChild(billboard) - local animation = cc.Animation3D:create("MeshRendererTest/girl.c3b","Take 001") + local animation = ax.Animation3D:create("MeshRendererTest/girl.c3b","Take 001") if nil ~= animation then - local animate = cc.Animate3D:create(animation) - self._player:runAction(cc.RepeatForever:create(animate)) + local animate = ax.Animate3D:create(animation) + self._player:runAction(ax.RepeatForever:create(animate)) end local playerPos = self._player:getPosition3D() - self._camera:setPosition3D(cc.vec3add(playerPos, camera_offset)) - self._camera:setRotation3D(cc.vec3(-45,0,0)) + self._camera:setPosition3D(ax.vec3add(playerPos, camera_offset)) + self._camera:setRotation3D(ax.vec3(-45,0,0)) self:addChild(self._player) self:addChild(self._terrain) @@ -307,7 +307,7 @@ function TerrainWalkThru:subtitle() end function TerrainTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { @@ -320,4 +320,4 @@ function TerrainTest() scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/TextInputTest/TextInputTest.lua b/tests/lua-tests/Content/src/TextInputTest/TextInputTest.lua index dc5501d98607..d0a5cd747dae 100644 --- a/tests/lua-tests/Content/src/TextInputTest/TextInputTest.lua +++ b/tests/lua-tests/Content/src/TextInputTest/TextInputTest.lua @@ -3,7 +3,7 @@ local TextInput = {} function TextInput.create() cclog("TextInput.create") - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) TextInput.layer = layer @@ -11,28 +11,28 @@ function TextInput.create() local width = 200 local height = 40 local back = ccui.Scale9Sprite:create(res) - local edit = ccui.EditBox:create(cc.size(width,height),back) + local edit = ccui.EditBox:create(ax.size(width,height),back) layer:addChild(edit) - edit:setPosition( cc.p(250,200) ) + edit:setPosition( ax.p(250,200) ) edit:setPlaceHolder("click to input text") - local editPasswd = ccui.EditBox:create(cc.size(width,height),res) - editPasswd:setInputFlag(cc.EDITBOX_INPUT_FLAG_PASSWORD) + local editPasswd = ccui.EditBox:create(ax.size(width,height),res) + editPasswd:setInputFlag(ax.EDITBOX_INPUT_FLAG_PASSWORD) layer:addChild(editPasswd) - editPasswd:setPosition( cc.p(250,100) ) + editPasswd:setPosition( ax.p(250,100) ) editPasswd:setPlaceHolder("click to input password") - editPasswd:setInputMode(cc.EDITBOX_INPUT_MODE_SINGLELINE); + editPasswd:setInputMode(ax.EDITBOX_INPUT_MODE_SINGLELINE); return layer end function TextInputTestMain() cclog("TextInputTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { TextInput.create, } Helper.index = 1 - + scene:addChild(TextInput.create()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/Texture2dTest/Texture2dTest.lua b/tests/lua-tests/Content/src/Texture2dTest/Texture2dTest.lua index 8c5203e2a695..3c38867ee185 100644 --- a/tests/lua-tests/Content/src/Texture2dTest/Texture2dTest.lua +++ b/tests/lua-tests/Content/src/Texture2dTest/Texture2dTest.lua @@ -1,4 +1,4 @@ -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() local kTagLabel = 1 local kTagSprite1 = 2 local kTagSprite2 = 3 @@ -7,10 +7,10 @@ local originCreateLayer = createTestLayer local function createTestLayer(title, subtitle) local ret = originCreateLayer(title, subtitle) Helper.titleLabel:setTag(kTagLabel) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) - local col = cc.LayerColor:create(cc.c4b(128,128,128,255)) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) + local col = ax.LayerColor:create(ax.color32(128,128,128,255)) ret:addChild(col, -10) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -22,12 +22,12 @@ end local function TexturePNG() local ret = createTestLayer("PNG Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image.png") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image.png") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -38,12 +38,12 @@ end -------------------------------------------------------------------- local function TextureJPEG() local ret = createTestLayer("JPEG Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image.jpeg") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image.jpeg") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -54,12 +54,12 @@ end -------------------------------------------------------------------- local function TextureWEBP() local ret = createTestLayer("WEBP Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image.webp") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image.webp") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -71,35 +71,35 @@ end local function TextureMipMap() local ret = createTestLayer("Texture Mipmap", "Left image uses mipmap. Right image doesn't") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local texture0 = cc.Director:getInstance():getTextureCache():addImage( + local texture0 = ax.Director:getInstance():getTextureCache():addImage( "Images/grossini_dance_atlas.png") texture0:generateMipmap() texture0:setTexParameters(ccb.SamplerFilter.LINEAR_MIPMAP_LINEAR, ccb.SamplerFilter.LINEAR, ccb.SamplerAddressMode.CLAMP_TO_EDGE, ccb.SamplerAddressMode.CLAMP_TO_EDGE) - local texture1 = cc.Director:getInstance():getTextureCache():addImage( + local texture1 = ax.Director:getInstance():getTextureCache():addImage( "Images/grossini_dance_atlas_nomipmap.png") - local img0 = cc.Sprite:createWithTexture(texture0) - img0:setTextureRect(cc.rect(85, 121, 85, 121)) - img0:setPosition(cc.p( s.width/3.0, s.height/2.0)) + local img0 = ax.Sprite:createWithTexture(texture0) + img0:setTextureRect(ax.rect(85, 121, 85, 121)) + img0:setPosition(ax.p( s.width/3.0, s.height/2.0)) ret:addChild(img0) - local img1 = cc.Sprite:createWithTexture(texture1) - img1:setTextureRect(cc.rect(85, 121, 85, 121)) - img1:setPosition(cc.p( 2*s.width/3.0, s.height/2.0)) + local img1 = ax.Sprite:createWithTexture(texture1) + img1:setTextureRect(ax.rect(85, 121, 85, 121)) + img1:setPosition(ax.p( 2*s.width/3.0, s.height/2.0)) ret:addChild(img1) - local scale1 = cc.EaseOut:create(cc.ScaleBy:create(4, 0.01), 3) + local scale1 = ax.EaseOut:create(ax.ScaleBy:create(4, 0.01), 3) local sc_back = scale1:reverse() local scale2 = scale1:clone() local sc_back2 = scale2:reverse() - img0:runAction(cc.RepeatForever:create(cc.Sequence:create(scale1, sc_back))) - img1:runAction(cc.RepeatForever:create(cc.Sequence:create(scale2, sc_back2))) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + img0:runAction(ax.RepeatForever:create(ax.Sequence:create(scale1, sc_back))) + img1:runAction(ax.RepeatForever:create(ax.Sequence:create(scale2, sc_back2))) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -112,33 +112,33 @@ end -------------------------------------------------------------------- local function TexturePVRMipMap() local ret = createTestLayer("PVRTC MipMap Test", "Left image uses mipmap. Right image doesn't") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local imgMipMap = cc.Sprite:create("Images/logo-mipmap.pvr") + local imgMipMap = ax.Sprite:create("Images/logo-mipmap.pvr") if imgMipMap ~= nil and imgMipMap:getTexture() ~= nil then - imgMipMap:setPosition(cc.p( s.width/2.0-100, s.height/2.0)) + imgMipMap:setPosition(ax.p( s.width/2.0-100, s.height/2.0)) ret:addChild(imgMipMap) -- support mipmap filtering imgMipMap:getTexture():setTexParameters(ccb.SamplerFilter.LINEAR_MIPMAP_LINEAR, ccb.SamplerFilter.LINEAR, ccb.SamplerAddressMode.CLAMP_TO_EDGE, ccb.SamplerAddressMode.CLAMP_TO_EDGE) end - local img = cc.Sprite:create("Images/logo-nomipmap.pvr") + local img = ax.Sprite:create("Images/logo-nomipmap.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0+100, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0+100, s.height/2.0)) ret:addChild(img) - local scale1 = cc.EaseOut:create(cc.ScaleBy:create(4, 0.01), 3) + local scale1 = ax.EaseOut:create(ax.ScaleBy:create(4, 0.01), 3) local sc_back = scale1:reverse() local scale2 = scale1:clone() local sc_back2 = scale2:reverse() - imgMipMap:runAction(cc.RepeatForever:create(cc.Sequence:create(scale1, sc_back))) - img:runAction(cc.RepeatForever:create(cc.Sequence:create(scale2, sc_back2))) + imgMipMap:runAction(ax.RepeatForever:create(ax.Sequence:create(scale1, sc_back))) + img:runAction(ax.RepeatForever:create(ax.Sequence:create(scale2, sc_back2))) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -150,29 +150,29 @@ end -------------------------------------------------------------------- local function TexturePVRMipMap2() local ret = createTestLayer("PVR MipMap Test #2", "Left image uses mipmap. Right image doesn't") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local imgMipMap = cc.Sprite:create("Images/test_image_rgba4444_mipmap.pvr") - imgMipMap:setPosition(cc.p( s.width/2.0-100, s.height/2.0)) + local imgMipMap = ax.Sprite:create("Images/test_image_rgba4444_mipmap.pvr") + imgMipMap:setPosition(ax.p( s.width/2.0-100, s.height/2.0)) ret:addChild(imgMipMap) -- support mipmap filtering imgMipMap:getTexture():setTexParameters(ccb.SamplerFilter.LINEAR_MIPMAP_LINEAR, ccb.SamplerFilter.LINEAR, ccb.SamplerAddressMode.CLAMP_TO_EDGE, ccb.SamplerAddressMode.CLAMP_TO_EDGE) - local img = cc.Sprite:create("Images/test_image.png") - img:setPosition(cc.p( s.width/2.0+100, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image.png") + img:setPosition(ax.p( s.width/2.0+100, s.height/2.0)) ret:addChild(img) - local scale1 = cc.EaseOut:create(cc.ScaleBy:create(4, 0.01), 3) + local scale1 = ax.EaseOut:create(ax.ScaleBy:create(4, 0.01), 3) local sc_back = scale1:reverse() local scale2 = scale1:clone() local sc_back2 = scale2:reverse() - imgMipMap:runAction(cc.RepeatForever:create(cc.Sequence:create(scale1, sc_back))) - img:runAction(cc.RepeatForever:create(cc.Sequence:create(scale2, sc_back2))) + imgMipMap:runAction(ax.RepeatForever:create(ax.Sequence:create(scale1, sc_back))) + img:runAction(ax.RepeatForever:create(ax.Sequence:create(scale2, sc_back2))) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -186,16 +186,16 @@ end local function TexturePVR2BPP() local ret = createTestLayer("PVR TC 2bpp Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtc2bpp.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtc2bpp.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -208,17 +208,17 @@ end -------------------------------------------------------------------- local function TexturePVR() local ret = createTestLayer("PVR TC 4bpp Test #2") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image.pvr") + local img = ax.Sprite:create("Images/test_image.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("This test is not supported.") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -232,17 +232,17 @@ end local function TexturePVR4BPP() local ret = createTestLayer("PVR TC 4bpp Test #3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtc4bpp.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtc4bpp.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("This test is not supported in cocos2d-mac") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -256,12 +256,12 @@ end local function TexturePVRRGBA8888() local ret = createTestLayer("PVR + RGBA 8888 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba8888.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgba8888.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -275,16 +275,16 @@ end local function TexturePVRBGRA8888() local ret = createTestLayer("PVR + BGRA 8888 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_bgra8888.pvr") + local img = ax.Sprite:create("Images/test_image_bgra8888.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("BGRA8888 images are not supported") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -297,12 +297,12 @@ end -------------------------------------------------------------------- local function TexturePVRRGBA5551() local ret = createTestLayer("PVR + RGBA 5551 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba5551.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgba5551.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -315,12 +315,12 @@ end -------------------------------------------------------------------- local function TexturePVRRGBA4444() local ret = createTestLayer("PVR + RGBA 4444 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba4444.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgba4444.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -334,12 +334,12 @@ end local function TexturePVRRGBA4444GZ() local ret = createTestLayer("PVR + RGBA 4444 + GZ Test", "This is a gzip PVR image") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba4444.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgba4444.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -351,14 +351,14 @@ end -- -------------------------------------------------------------------- local function TexturePVRRGBA4444CCZ() - local ret = createTestLayer("PVR + RGBA 4444 + cc.Z Test", + local ret = createTestLayer("PVR + RGBA 4444 + ax.Z Test", "This is a ccz PVR image") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba4444.pvr.ccz") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgba4444.pvr.ccz") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -371,12 +371,12 @@ end -------------------------------------------------------------------- local function TexturePVRRGB565() local ret = createTestLayer("PVR + RGB 565 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgb565.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_rgb565.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -385,14 +385,14 @@ end -- http:--www.imgtec.com/powervr/insider/powervr-pvrtextool.asp local function TexturePVRRGB888() local ret = createTestLayer("PVR + RGB 888 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgb888.pvr") + local img = ax.Sprite:create("Images/test_image_rgb888.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -405,12 +405,12 @@ end -------------------------------------------------------------------- local function TexturePVRA8() local ret = createTestLayer("PVR + A8 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_a8.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_a8.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -423,12 +423,12 @@ end -------------------------------------------------------------------- local function TexturePVRI8() local ret = createTestLayer("PVR + I8 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_i8.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_i8.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -442,61 +442,61 @@ end -------------------------------------------------------------------- local function TexturePVRAI88() local ret = createTestLayer("PVR + AI88 Test") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_ai88.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/test_image_ai88.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end -- TexturePVR2BPPv3 local function TexturePVR2BPPv3() local ret = createTestLayer("PVR TC 2bpp Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtc2bpp_v3.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtc2bpp_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end -- TexturePVRII2BPPv3 local function TexturePVRII2BPPv3() local ret = createTestLayer("PVR TC II 2bpp Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtcii2bpp_v3.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtcii2bpp_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end -- TexturePVR4BPPv3 local function TexturePVR4BPPv3() local ret = createTestLayer("PVR TC 4bpp Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtc4bpp_v3.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtc4bpp_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("This test is not supported") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -508,17 +508,17 @@ end local function TexturePVRII4BPPv3() local ret = createTestLayer("PVR TC II 4bpp Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_pvrtcii4bpp_v3.pvr") + local img = ax.Sprite:create("Images/test_image_pvrtcii4bpp_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("This test is not supported") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -526,16 +526,16 @@ end local function TexturePVRRGBA8888v3() local ret = createTestLayer("PVR + RGBA 8888 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba8888_v3.pvr") + local img = ax.Sprite:create("Images/test_image_rgba8888_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -544,18 +544,18 @@ local function TexturePVRBGRA8888v3() local ret = createTestLayer("PVR + BGRA 8888 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_bgra8888_v3.pvr") + local img = ax.Sprite:create("Images/test_image_bgra8888_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) else cclog("BGRA images are not supported") end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -563,15 +563,15 @@ end local function TexturePVRRGBA5551v3() local ret = createTestLayer("PVR + RGBA 5551 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba5551_v3.pvr") + local s = ax.Director:getInstance():getWinSize() + local img = ax.Sprite:create("Images/test_image_rgba5551_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -579,16 +579,16 @@ end local function TexturePVRRGBA4444v3() local ret = createTestLayer("PVR + RGBA 4444 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgba4444_v3.pvr") + local img = ax.Sprite:create("Images/test_image_rgba4444_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -596,16 +596,16 @@ end local function TexturePVRRGB565v3() local ret = createTestLayer("PVR + RGB 565 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgb565_v3.pvr") + local img = ax.Sprite:create("Images/test_image_rgb565_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -613,16 +613,16 @@ end local function TexturePVRRGB888v3() local ret = createTestLayer("PVR + RGB 888 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_rgb888_v3.pvr") + local img = ax.Sprite:create("Images/test_image_rgb888_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -630,16 +630,16 @@ end local function TexturePVRA8v3() local ret = createTestLayer("PVR + A8 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_a8_v3.pvr") + local img = ax.Sprite:create("Images/test_image_a8_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -647,16 +647,16 @@ end local function TexturePVRI8v3() local ret = createTestLayer("PVR + I8 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_i8_v3.pvr") + local img = ax.Sprite:create("Images/test_image_i8_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -664,16 +664,16 @@ end local function TexturePVRAI88v3() local ret = createTestLayer("PVR + AI88 Test", "Testing PVR File Format v3") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image_ai88_v3.pvr") + local img = ax.Sprite:create("Images/test_image_ai88_v3.pvr") if img ~= nil then - img:setPosition(cc.p(s.width/2.0, s.height/2.0)) + img:setPosition(ax.p(s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -687,11 +687,11 @@ end local function TexturePVRBadEncoding() local ret = createTestLayer("PVR Unsupported encoding", "You should not see any image") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/test_image-bad_encoding.pvr") + local img = ax.Sprite:create("Images/test_image-bad_encoding.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) end return ret @@ -705,12 +705,12 @@ end local function TexturePVRNonSquare() local ret = createTestLayer("PVR + Non square texture", "Loading a 128x256 texture") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/grossini_128x256_mipmap.pvr") - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + local img = ax.Sprite:create("Images/grossini_128x256_mipmap.pvr") + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -722,14 +722,14 @@ end local function TexturePVRNPOT4444() local ret = createTestLayer("PVR RGBA4 + NPOT texture", "Loading a 81x121 RGBA4444 texture.") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/grossini_pvr_rgba4444.pvr") + local img = ax.Sprite:create("Images/grossini_pvr_rgba4444.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -741,14 +741,14 @@ end local function TexturePVRNPOT8888() local ret = createTestLayer("PVR RGBA8 + NPOT texture", "Loading a 81x121 RGBA8888 texture.") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local img = cc.Sprite:create("Images/grossini_pvr_rgba8888.pvr") + local img = ax.Sprite:create("Images/grossini_pvr_rgba8888.pvr") if img ~= nil then - img:setPosition(cc.p( s.width/2.0, s.height/2.0)) + img:setPosition(ax.p( s.width/2.0, s.height/2.0)) ret:addChild(img) end - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -760,15 +760,15 @@ end local function TextureAlias() local ret = createTestLayer("AntiAlias / Alias textures", "Left image is antialiased. Right image is aliases") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() -- -- Sprite 1: ccb.SamplerFilter.LINEAR -- -- Default filter is ccb.SamplerFilter.LINEAR - local sprite = cc.Sprite:create("Images/grossinis_sister1.png") - sprite:setPosition(cc.p( s.width/3.0, s.height/2.0)) + local sprite = ax.Sprite:create("Images/grossinis_sister1.png") + sprite:setPosition(ax.p( s.width/3.0, s.height/2.0)) ret:addChild(sprite) -- this is the default filtering @@ -778,22 +778,22 @@ local function TextureAlias() -- Sprite 1: GL_NEAREST -- - local sprite2 = cc.Sprite:create("Images/grossinis_sister2.png") - sprite2:setPosition(cc.p( 2*s.width/3.0, s.height/2.0)) + local sprite2 = ax.Sprite:create("Images/grossinis_sister2.png") + sprite2:setPosition(ax.p( 2*s.width/3.0, s.height/2.0)) ret:addChild(sprite2) -- Use Nearest in this one sprite2:getTexture():setAliasTexParameters() -- scale them to show - local sc = cc.ScaleBy:create(3, 8.0) + local sc = ax.ScaleBy:create(3, 8.0) local sc_back = sc:reverse() - local scaleforever = cc.RepeatForever:create(cc.Sequence:create(sc, sc_back)) + local scaleforever = ax.RepeatForever:create(ax.Sequence:create(sc, sc_back)) local scaleToo = scaleforever:clone() sprite2:runAction(scaleforever) sprite:runAction(scaleToo) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -814,71 +814,65 @@ local function TexturePixelFormat() -- 4- 16-bit RGB565 local label = ret:getChildByTag(kTagLabel) - label:setColor(cc.c3b(16,16,255)) + label:setColor(ax.color32(16,16,255)) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local background = cc.LayerColor:create(cc.c4b(128,128,128,255), s.width, s.height) + local background = ax.LayerColor:create(ax.color32(128,128,128,255), s.width, s.height) ret:addChild(background, -1) -- RGBA 8888 image (32-bit) - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGBA8) - local sprite1 = cc.Sprite:create("Images/test-rgba1.png") - sprite1:setPosition(cc.p(1*s.width/7, s.height/2+32)) + local sprite1 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_RGBA8) + sprite1:setPosition(ax.p(1*s.width/7, s.height/2+32)) ret:addChild(sprite1, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite1:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite1:getTexture()) -- RGBA 4444 image (16-bit) - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGBA4) - local sprite2 = cc.Sprite:create("Images/test-rgba1.png") - sprite2:setPosition(cc.p(2*s.width/7, s.height/2-32)) + local sprite2 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_RGBA4) + sprite2:setPosition(ax.p(2*s.width/7, s.height/2-32)) ret:addChild(sprite2, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite2:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite2:getTexture()) -- RGB5A1 image (16-bit) - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGB5A1) - local sprite3 = cc.Sprite:create("Images/test-rgba1.png") - sprite3:setPosition(cc.p(3*s.width/7, s.height/2+32)) + local sprite3 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_RGB5A1) + sprite3:setPosition(ax.p(3*s.width/7, s.height/2+32)) ret:addChild(sprite3, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite3:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite3:getTexture()) -- RGB888 image - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGB8 ) - local sprite4 = cc.Sprite:create("Images/test-rgba1.png") - sprite4:setPosition(cc.p(4*s.width/7, s.height/2-32)) + local sprite4 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_RGB8) + sprite4:setPosition(ax.p(4*s.width/7, s.height/2-32)) ret:addChild(sprite4, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite4:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite4:getTexture()) -- RGB565 image (16-bit) - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGB565) - local sprite5 = cc.Sprite:create("Images/test-rgba1.png") - sprite5:setPosition(cc.p(5*s.width/7, s.height/2+32)) + local sprite5 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_RGB565) + sprite5:setPosition(ax.p(5*s.width/7, s.height/2+32)) ret:addChild(sprite5, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite5:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite5:getTexture()) -- A8 image (8-bit) - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_A8 ) - local sprite6 = cc.Sprite:create("Images/test-rgba1.png") - sprite6:setPosition(cc.p(6*s.width/7, s.height/2-32)) + local sprite6 = ax.Sprite:create("Images/test-rgba1.png", ax.TEXTURE_PF_A8) + sprite6:setPosition(ax.p(6*s.width/7, s.height/2-32)) ret:addChild(sprite6, 0) -- remove texture from texture manager - cc.Director:getInstance():getTextureCache():removeTexture(sprite6:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite6:getTexture()) - local fadeout = cc.FadeOut:create(2) - local fadein = cc.FadeIn:create(2) - local seq = cc.Sequence:create(cc.DelayTime:create(2), fadeout, fadein) - local seq_4ever = cc.RepeatForever:create(seq) + local fadeout = ax.FadeOut:create(2) + local fadein = ax.FadeIn:create(2) + local seq = ax.Sequence:create(ax.DelayTime:create(2), fadeout, fadein) + local seq_4ever = ax.RepeatForever:create(seq) local seq_4ever2 = seq_4ever:clone() local seq_4ever3 = seq_4ever:clone() local seq_4ever4 = seq_4ever:clone() @@ -891,8 +885,7 @@ local function TexturePixelFormat() sprite5:runAction(seq_4ever5) -- restore default - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGBA8) - print(cc.Director:getInstance():getTextureCache():getCachedTextureInfo()) + print(ax.Director:getInstance():getTextureCache():getCachedTextureInfo()) return ret end @@ -908,24 +901,24 @@ local function TextureBlend() for i=0, 14 do -- BOTTOM sprites have alpha pre-multiplied -- they use by default GL_ONE, GL_ONE_MINUS_SRC_ALPHA - local cloud = cc.Sprite:create("Images/test_blend.png") + local cloud = ax.Sprite:create("Images/test_blend.png") ret:addChild(cloud, i+1, 100+i) - cloud:setPosition(cc.p(50+25*i, 80)) - cloud:setBlendFunc(cc.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) + cloud:setPosition(ax.p(50+25*i, 80)) + cloud:setBlendFunc(ax.blendFunc(ccb.BlendFactor.ONE, ccb.BlendFactor.ONE_MINUS_SRC_ALPHA)) -- CENTER sprites have also alpha pre-multiplied -- they use by default GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA - cloud = cc.Sprite:create("Images/test_blend.png") + cloud = ax.Sprite:create("Images/test_blend.png") ret:addChild(cloud, i+1, 200+i) - cloud:setPosition(cc.p(50+25*i, 160)) - cloud:setBlendFunc(cc.blendFunc(ccb.BlendFactor.ONE_MINUS_DST_COLOR , ccb.BlendFactor.ZERO)) + cloud:setPosition(ax.p(50+25*i, 160)) + cloud:setBlendFunc(ax.blendFunc(ccb.BlendFactor.ONE_MINUS_DST_COLOR , ccb.BlendFactor.ZERO)) -- UPPER sprites are using custom blending function -- You can set any blend function to your sprites - cloud = cc.Sprite:create("Images/test_blend.png") + cloud = ax.Sprite:create("Images/test_blend.png") ret:addChild(cloud, i+1, 200+i) - cloud:setPosition(cc.p(50+25*i, 320-80)) - cloud:setBlendFunc(cc.blendFunc(ccb.BlendFactor.SRC_ALPHA, ccb.BlendFactor.ONE)) -- additive blending + cloud:setPosition(ax.p(50+25*i, 320-80)) + cloud:setBlendFunc(ax.blendFunc(ccb.BlendFactor.SRC_ALPHA, ccb.BlendFactor.ONE)) -- additive blending end return ret end @@ -941,28 +934,28 @@ local function TextureAsync() "Textures should load while an animation is being run") local m_nImageOffset = 0 - local size =cc.Director:getInstance():getWinSize() + local size =ax.Director:getInstance():getWinSize() - local label = cc.Label:createWithTTF("Loading...", s_markerFeltFontPath, 32) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p( size.width/2, size.height/2)) + local label = ax.Label:createWithTTF("Loading...", s_markerFeltFontPath, 32) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p( size.width/2, size.height/2)) ret:addChild(label, 10) - local scale = cc.ScaleBy:create(0.3, 2) + local scale = ax.ScaleBy:create(0.3, 2) local scale_back = scale:reverse() - local seq = cc.Sequence:create(scale, scale_back) - label:runAction(cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(scale, scale_back) + label:runAction(ax.RepeatForever:create(seq)) local function imageLoaded(texture) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() - local sprite = cc.Sprite:createWithTexture(texture) - sprite:setAnchorPoint(cc.p(0,0)) + local sprite = ax.Sprite:createWithTexture(texture) + sprite:setAnchorPoint(ax.p(0,0)) ret:addChild(sprite, -1) local size = director:getWinSize() local i = m_nImageOffset * 32 - sprite:setPosition(cc.p( i % size.width, math.floor((i / size.width)) * 32 )) + sprite:setPosition(ax.p( i % size.width, math.floor((i / size.width)) * 32 )) m_nImageOffset = m_nImageOffset + 1 cclog("Image loaded:...")-- %p", tex) @@ -975,16 +968,16 @@ local function TextureAsync() for j=0, 7 do local szSpriteName = string.format( "Images/sprites_test/sprite-%d-%d.png", i, j) - cc.Director:getInstance():getTextureCache():addImageAsync( + ax.Director:getInstance():getTextureCache():addImageAsync( szSpriteName, imageLoaded) end end - cc.Director:getInstance():getTextureCache():addImageAsync("Images/background1.jpg", imageLoaded) - cc.Director:getInstance():getTextureCache():addImageAsync("Images/background2.jpg", imageLoaded) - cc.Director:getInstance():getTextureCache():addImageAsync("Images/background.png", imageLoaded) - cc.Director:getInstance():getTextureCache():addImageAsync("Images/atlastest.png", imageLoaded) - cc.Director:getInstance():getTextureCache():addImageAsync("Images/grossini_dance_atlas.png",imageLoaded) + ax.Director:getInstance():getTextureCache():addImageAsync("Images/background1.jpg", imageLoaded) + ax.Director:getInstance():getTextureCache():addImageAsync("Images/background2.jpg", imageLoaded) + ax.Director:getInstance():getTextureCache():addImageAsync("Images/background.png", imageLoaded) + ax.Director:getInstance():getTextureCache():addImageAsync("Images/atlastest.png", imageLoaded) + ax.Director:getInstance():getTextureCache():addImageAsync("Images/grossini_dance_atlas.png",imageLoaded) ret:unscheduleUpdate() end @@ -994,7 +987,7 @@ local function TextureAsync() ret:scheduleUpdateWithPriorityLua(loadImages,0) elseif event == "exit" then ret:unscheduleUpdate() - cc.Director:getInstance():getTextureCache():removeAllTextures() + ax.Director:getInstance():getTextureCache():removeAllTextures() end end @@ -1010,24 +1003,24 @@ end local function TextureGlClamp() local ret = createTestLayer("Texture GL_CLAMP") - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() -- The .png image MUST be power of 2 in order to create a continue effect. -- eg: 32x64, 512x128, 256x1024, 64x64, etc.. - local sprite = cc.Sprite:create("Images/pattern1.png", cc.rect(0,0,512,256)) + local sprite = ax.Sprite:create("Images/pattern1.png", ax.rect(0,0,512,256)) ret:addChild(sprite, -1, kTagSprite1) - sprite:setPosition(cc.p(size.width/2,size.height/2)) + sprite:setPosition(ax.p(size.width/2,size.height/2)) sprite:getTexture():setTexParameters(ccb.SamplerFilter.LINEAR, ccb.SamplerFilter.LINEAR, ccb.SamplerAddressMode.CLAMP_TO_EDGE, ccb.SamplerAddressMode.CLAMP_TO_EDGE) - local rotate = cc.RotateBy:create(4, 360) + local rotate = ax.RotateBy:create(4, 360) sprite:runAction(rotate) - local scale = cc.ScaleBy:create(2, 0.04) + local scale = ax.ScaleBy:create(2, 0.04) local scaleBack = scale:reverse() - local seq = cc.Sequence:create(scale, scaleBack) + local seq = ax.Sequence:create(scale, scaleBack) sprite:runAction(seq) local function onNodeEvent(event) if event == "exit" then - cc.Director:getInstance():getTextureCache():removeUnusedTextures() + ax.Director:getInstance():getTextureCache():removeUnusedTextures() end end @@ -1044,24 +1037,24 @@ end local function TextureGlRepeat() local ret = createTestLayer("Texture ccb.SamplerFilter.REPEAT") - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() -- The .png image MUST be power of 2 in order to create a continue effect. -- eg: 32x64, 512x128, 256x1024, 64x64, etc.. - local sprite = cc.Sprite:create("Images/pattern1.png", cc.rect(0, 0, 4096, 4096)) + local sprite = ax.Sprite:create("Images/pattern1.png", ax.rect(0, 0, 4096, 4096)) ret:addChild(sprite, -1, kTagSprite1) - sprite:setPosition(cc.p(size.width/2,size.height/2)) + sprite:setPosition(ax.p(size.width/2,size.height/2)) sprite:getTexture():setTexParameters(ccb.SamplerFilter.LINEAR, ccb.SamplerFilter.LINEAR, ccb.SamplerAddressMode.REPEAT, ccb.SamplerAddressMode.REPEAT) - local rotate = cc.RotateBy:create(4, 360) + local rotate = ax.RotateBy:create(4, 360) sprite:runAction(rotate) - local scale = cc.ScaleBy:create(2, 0.04) + local scale = ax.ScaleBy:create(2, 0.04) local scaleBack = scale:reverse() - local seq = cc.Sequence:create(scale, scaleBack) + local seq = ax.Sequence:create(scale, scaleBack) sprite:runAction(seq) local function onNodeEvent(event) if event == "exit" then - cc.Director:getInstance():getTextureCache():removeUnusedTextures() + ax.Director:getInstance():getTextureCache():removeUnusedTextures() end end @@ -1081,28 +1074,28 @@ local function TextureSizeTest() local sprite = nil cclog("Loading 512x512 image...") - sprite = cc.Sprite:create("Images/texture512x512.png") + sprite = ax.Sprite:create("Images/texture512x512.png") if sprite ~= nil then cclog("OK\n") else cclog("Error\n") cclog("Loading 1024x1024 image...") - sprite = cc.Sprite:create("Images/texture1024x1024.png") + sprite = ax.Sprite:create("Images/texture1024x1024.png") if sprite ~= nil then cclog("OK\n") else cclog("Error\n") -- @todo -- cclog("Loading 2048x2048 image...") - -- sprite = cc.Sprite:create("Images/texture2048x2048.png") + -- sprite = ax.Sprite:create("Images/texture2048x2048.png") -- if( sprite ) -- cclog("OK\n") -- else -- cclog("Error\n") -- -- cclog("Loading 4096x4096 image...") - -- sprite = cc.Sprite:create("Images/texture4096x4096.png") + -- sprite = ax.Sprite:create("Images/texture4096x4096.png") -- if( sprite ) -- cclog("OK\n") -- else @@ -1119,36 +1112,36 @@ end local function TextureCache1() local ret = createTestLayer("TextureCache: remove", "4 images should appear: alias, antialias, alias, antialias") - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local sprite = nil - sprite = cc.Sprite:create("Images/grossinis_sister1.png") - sprite:setPosition(cc.p(s.width/5*1, s.height/2)) + sprite = ax.Sprite:create("Images/grossinis_sister1.png") + sprite:setPosition(ax.p(s.width/5*1, s.height/2)) sprite:getTexture():setAliasTexParameters() sprite:setScale(2) ret:addChild(sprite) - cc.Director:getInstance():getTextureCache():removeTexture(sprite:getTexture()) + ax.Director:getInstance():getTextureCache():removeTexture(sprite:getTexture()) - sprite = cc.Sprite:create("Images/grossinis_sister1.png") - sprite:setPosition(cc.p(s.width/5*2, s.height/2)) + sprite = ax.Sprite:create("Images/grossinis_sister1.png") + sprite:setPosition(ax.p(s.width/5*2, s.height/2)) sprite:getTexture():setAntiAliasTexParameters() sprite:setScale(2) ret:addChild(sprite) -- 2nd set of sprites - sprite = cc.Sprite:create("Images/grossinis_sister2.png") - sprite:setPosition(cc.p(s.width/5*3, s.height/2)) + sprite = ax.Sprite:create("Images/grossinis_sister2.png") + sprite:setPosition(ax.p(s.width/5*3, s.height/2)) sprite:getTexture():setAliasTexParameters() sprite:setScale(2) ret:addChild(sprite) - cc.Director:getInstance():getTextureCache():removeTextureForKey("Images/grossinis_sister2.png") + ax.Director:getInstance():getTextureCache():removeTextureForKey("Images/grossinis_sister2.png") - sprite = cc.Sprite:create("Images/grossinis_sister2.png") - sprite:setPosition(cc.p(s.width/5*4, s.height/2)) + sprite = ax.Sprite:create("Images/grossinis_sister2.png") + sprite:setPosition(ax.p(s.width/5*4, s.height/2)) sprite:getTexture():setAntiAliasTexParameters() sprite:setScale(2) ret:addChild(sprite) @@ -1163,28 +1156,28 @@ local function TextureDrawAtPoint() "draws 2 textures using drawAtPoint") local function draw(transform, globalZOrder) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() assert(nil ~= director, "Director is null when setting matrix stack") - director:pushMatrix(cc.MATRIX_STACK_TYPE.MODELVIEW) - director:loadMatrix(cc.MATRIX_STACK_TYPE.MODELVIEW, transform) - - local s = cc.Director:getInstance():getWinSize() - - m_pTex1:drawAtPoint(cc.p(s.width/2-50, s.height/2 - 50), globalZOrder) - m_pTex2F:drawAtPoint(cc.p(s.width/2+50, s.height/2 - 50), globalZOrder) - - director:popMatrix(cc.MATRIX_STACK_TYPE.MODELVIEW) + director:pushMatrix(ax.MATRIX_STACK_TYPE.MODELVIEW) + director:loadMatrix(ax.MATRIX_STACK_TYPE.MODELVIEW, transform) + + local s = ax.Director:getInstance():getWinSize() + + m_pTex1:drawAtPoint(ax.p(s.width/2-50, s.height/2 - 50), globalZOrder) + m_pTex2F:drawAtPoint(ax.p(s.width/2+50, s.height/2 - 50), globalZOrder) + + director:popMatrix(ax.MATRIX_STACK_TYPE.MODELVIEW) end - m_pTex1 = cc.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister1.png") - m_pTex2F = cc.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister2.png") + m_pTex1 = ax.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister1.png") + m_pTex2F = ax.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister2.png") m_pTex1:retain() m_pTex2F:retain() - local luaNode = cc.LuaNode:create() - luaNode:setContentSize(cc.size(256, 256)) - luaNode:setAnchorPoint(cc.p(0,0)) + local luaNode = ax.LuaNode:create() + luaNode:setContentSize(ax.size(256, 256)) + luaNode:setAnchorPoint(ax.p(0,0)) luaNode:registerScriptDrawHandler(draw) ret:addChild(luaNode) @@ -1208,29 +1201,29 @@ local function TextureDrawInRect() local ret = createTestLayer("Texture2D: drawInRect", "draws 2 textures using drawInRect") local function draw(transform, globalZOrder) - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() assert(nullptr ~= director, "Director is null when setting matrix stack") - director:pushMatrix(cc.MATRIX_STACK_TYPE.MODELVIEW) - director:loadMatrix(cc.MATRIX_STACK_TYPE.MODELVIEW, transform) + director:pushMatrix(ax.MATRIX_STACK_TYPE.MODELVIEW) + director:loadMatrix(ax.MATRIX_STACK_TYPE.MODELVIEW, transform) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - local rect1 = cc.rect( s.width/2 - 80, 20, m_pTex1:getContentSize().width * 0.5, m_pTex1:getContentSize().height *2 ) - local rect2 = cc.rect( s.width/2 + 80, s.height/2, m_pTex1:getContentSize().width * 2, m_pTex1:getContentSize().height * 0.5 ) + local rect1 = ax.rect( s.width/2 - 80, 20, m_pTex1:getContentSize().width * 0.5, m_pTex1:getContentSize().height *2 ) + local rect2 = ax.rect( s.width/2 + 80, s.height/2, m_pTex1:getContentSize().width * 2, m_pTex1:getContentSize().height * 0.5 ) m_pTex1:drawInRect(rect1, globalZOrder) m_pTex2F:drawInRect(rect2, globalZOrder) end - m_pTex1 = cc.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister1.png") - m_pTex2F = cc.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister2.png") + m_pTex1 = ax.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister1.png") + m_pTex2F = ax.Director:getInstance():getTextureCache():addImage("Images/grossinis_sister2.png") m_pTex1:retain() m_pTex2F:retain() - local luaNode = cc.LuaNode:create() - luaNode:setContentSize(cc.size(256, 256)) - luaNode:setAnchorPoint(cc.p(0,0)) + local luaNode = ax.LuaNode:create() + luaNode:setContentSize(ax.size(256, 256)) + luaNode:setAnchorPoint(ax.p(0,0)) luaNode:registerScriptDrawHandler(draw) ret:addChild(luaNode) @@ -1256,16 +1249,16 @@ local function TextureMemoryAlloc() "Testing Texture Memory allocation. Use Instruments + VM Tracker") local m_pBackground = nil - cc.MenuItemFont:setFontSize(24) + ax.MenuItemFont:setFontSize(24) local function updateImage(tag,sender) if m_pBackground ~= nil then cclog("updateImage"..tag) m_pBackground:removeFromParent(true) end - cc.Director:getInstance():getTextureCache():removeUnusedTextures() + ax.Director:getInstance():getTextureCache():removeUnusedTextures() - local targetPlatform = cc.Application:getInstance():getTargetPlatform() + local targetPlatform = ax.Application:getInstance():getTargetPlatform() local file = "" if tag == 0 then @@ -1280,41 +1273,41 @@ local function TextureMemoryAlloc() file = "Images/test_image_a8.pvr" end - m_pBackground = cc.Sprite:create(file) + m_pBackground = ax.Sprite:create(file) ret:addChild(m_pBackground, -10) m_pBackground:setVisible(false) - local s = cc.Director:getInstance():getWinSize() - m_pBackground:setPosition(cc.p(s.width/2, s.height/2)) + local s = ax.Director:getInstance():getWinSize() + m_pBackground:setPosition(ax.p(s.width/2, s.height/2)) end - local item1 = cc.MenuItemFont:create("PNG") + local item1 = ax.MenuItemFont:create("PNG") item1:registerScriptTapHandler(updateImage) item1:setTag(0) - local item2 = cc.MenuItemFont:create("RGBA8") + local item2 = ax.MenuItemFont:create("RGBA8") item2:registerScriptTapHandler(updateImage) item2:setTag(1) - local item3 = cc.MenuItemFont:create("RGB8") + local item3 = ax.MenuItemFont:create("RGB8") item3:registerScriptTapHandler(updateImage) item3:setTag(2) - local item4 = cc.MenuItemFont:create("RGBA4") + local item4 = ax.MenuItemFont:create("RGBA4") item4:registerScriptTapHandler(updateImage) item4:setTag(3) - local item5 = cc.MenuItemFont:create("A8") + local item5 = ax.MenuItemFont:create("A8") item5:registerScriptTapHandler(updateImage) item5:setTag(4) - local menu = cc.Menu:create(item1, item2, item3, item4, item5) + local menu = ax.Menu:create(item1, item2, item3, item4, item5) menu:alignItemsHorizontally() ret:addChild(menu) - local warmup = cc.MenuItemFont:create("warm up texture") + local warmup = ax.MenuItemFont:create("warm up texture") local function changeBackgroundVisible(tag, sender) if m_pBackground ~= nil then @@ -1324,14 +1317,14 @@ local function TextureMemoryAlloc() end warmup:registerScriptTapHandler(changeBackgroundVisible) - local menu2 = cc.Menu:create(warmup) + local menu2 = ax.Menu:create(warmup) menu2:alignItemsHorizontally() ret:addChild(menu2) - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() - menu2:setPosition(cc.p(s.width/2, s.height/4)) + menu2:setPosition(ax.p(s.width/2, s.height/4)) return ret end @@ -1341,38 +1334,37 @@ local function TexturePVRv3Premult() "All images should look exactly the same") local function transformSprite(sprite) - local fade = cc.FadeOut:create(2) - local dl = cc.DelayTime:create(2) + local fade = ax.FadeOut:create(2) + local dl = ax.DelayTime:create(2) local fadein = fade:reverse() - local seq = cc.Sequence:create(fade, fadein, dl) - local repeatAction = cc.RepeatForever:create(seq) + local seq = ax.Sequence:create(fade, fadein, dl) + local repeatAction = ax.RepeatForever:create(seq) sprite:runAction(repeatAction) end - local size = cc.Director:getInstance():getWinSize() + local size = ax.Director:getInstance():getWinSize() - local background = cc.LayerColor:create(cc.c4b(128,128,128,255), size.width, size.height) + local background = ax.LayerColor:create(ax.color32(128,128,128,255), size.width, size.height) ret:addChild(background, -1) -- PVR premultiplied - local pvr1 = cc.Sprite:create("Images/grossinis_sister1-testalpha_premult.pvr") + local pvr1 = ax.Sprite:create("Images/grossinis_sister1-testalpha_premult.pvr") ret:addChild(pvr1, 0) - pvr1:setPosition(cc.p(size.width/4*1, size.height/2)) + pvr1:setPosition(ax.p(size.width/4*1, size.height/2)) transformSprite(pvr1) -- PVR non-premultiplied - local pvr2 = cc.Sprite:create("Images/grossinis_sister1-testalpha_nopremult.pvr") + local pvr2 = ax.Sprite:create("Images/grossinis_sister1-testalpha_nopremult.pvr") ret:addChild(pvr2, 0) - pvr2:setPosition(cc.p(size.width/4*2, size.height/2)) + pvr2:setPosition(ax.p(size.width/4*2, size.height/2)) transformSprite(pvr2) -- PNG - cc.Texture2D:setDefaultAlphaPixelFormat(cc.TEXTURE_PF_RGBA8) - cc.Director:getInstance():getTextureCache():removeTextureForKey("Images/grossinis_sister1-testalpha.png") - local png = cc.Sprite:create("Images/grossinis_sister1-testalpha.png") + ax.Director:getInstance():getTextureCache():removeTextureForKey("Images/grossinis_sister1-testalpha.png", ax.TEXTURE_PF_RGBA8) + local png = ax.Sprite:create("Images/grossinis_sister1-testalpha.png") ret:addChild(png, 0) - png:setPosition(cc.p(size.width/4*3, size.height/2)) + png:setPosition(ax.p(size.width/4*3, size.height/2)) transformSprite(png) return ret end @@ -1381,7 +1373,7 @@ end function Texture2dTestMain() cclog("Texture2dTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { TextureMemoryAlloc, TextureAlias, @@ -1433,7 +1425,7 @@ function Texture2dTestMain() TextureDrawInRect } Helper.index = 1 - + scene:addChild(TextureMemoryAlloc()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/TileMapTest/TileMapTest.lua b/tests/lua-tests/Content/src/TileMapTest/TileMapTest.lua index 0b9643dfe08f..f147fdeece88 100644 --- a/tests/lua-tests/Content/src/TileMapTest/TileMapTest.lua +++ b/tests/lua-tests/Content/src/TileMapTest/TileMapTest.lua @@ -1,11 +1,11 @@ -local size = cc.Director:getInstance():getWinSize() -local scheduler = cc.Director:getInstance():getScheduler() +local size = ax.Director:getInstance():getWinSize() +local scheduler = ax.Director:getInstance():getScheduler() local kTagTileMap = 1 local function createTileDemoLayer(title, subtitle) - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local titleStr = title == nil and "No title" or title local subTitleStr = subtitle == nil and "drag the screen" or subtitle @@ -16,11 +16,11 @@ local function createTileDemoLayer(title, subtitle) local diff = touches[1]:getDelta() local node = layer:getChildByTag(kTagTileMap) local currentPosX, currentPosY= node:getPosition() - node:setPosition(cc.p(currentPosX + diff.x, currentPosY + diff.y)) + node:setPosition(ax.p(currentPosX + diff.x, currentPosY + diff.y)) end - local listener = cc.EventListenerTouchAllAtOnce:create() - listener:registerScriptHandler(onTouchesMoved,cc.Handler.EVENT_TOUCHES_MOVED ) + local listener = ax.EventListenerTouchAllAtOnce:create() + listener:registerScriptHandler(onTouchesMoved,ax.Handler.EVENT_TOUCHES_MOVED ) local eventDispatcher = layer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, layer) @@ -34,7 +34,7 @@ end local function TileMapTest() local layer = createTileDemoLayer("TileMapAtlas") - local map = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local map = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) -- Convert it to "alias" (GL_LINEAR filtering) map:getTexture():setAntiAliasTexParameters() @@ -47,14 +47,14 @@ local function TileMapTest() layer:addChild(map, 0, kTagTileMap) - map:setAnchorPoint( cc.p(0, 0.5) ) + map:setAnchorPoint( ax.p(0, 0.5) ) - local scale = cc.ScaleBy:create(4, 0.8) + local scale = ax.ScaleBy:create(4, 0.8) local scaleBack = scale:reverse() - local seq = cc.Sequence:create(scale, scaleBack) + local seq = ax.Sequence:create(scale, scaleBack) - map:runAction(cc.RepeatForever:create(seq)) + map:runAction(ax.RepeatForever:create(seq)) return layer end @@ -66,7 +66,7 @@ end -------------------------------------------------------------------- local function TileMapEditTest() local layer = createTileDemoLayer("Editable TileMapAtlas") - local map = cc.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) + local map = ax.TileMapAtlas:create(s_TilesPng, s_LevelMapTga, 16, 16) -- Create an Aliased Atlas map:getTexture():setAliasTexParameters() @@ -90,7 +90,7 @@ local function TileMapEditTest() -- over all your tiles in every frame. It's very expensive -- for(int x=0 x < tilemap.tgaInfo:width x++) -- for(int y=0 y < tilemap.tgaInfo:height y++) - -- Color3B c =[tilemap getTileAt:local Make(x,y)) + -- Color32 c =[tilemap getTileAt:local Make(x,y)) -- if( c.r != 0 ) -- --------cclog("%d,%d = %d", x,y,c.r) -- end @@ -98,7 +98,7 @@ local function TileMapEditTest() -- end -- NEW since v0.7 - local c = tilemap:getTileAt(cc.p(13,21)) + local c = tilemap:getTileAt(ax.p(13,21)) c.r = c.r + 1 c.r = c.r % 50 @@ -106,7 +106,7 @@ local function TileMapEditTest() c.r=1 end -- NEW since v0.7 - tilemap:setTile(c, cc.p(13,21) ) + tilemap:setTile(c, ax.p(13,21) ) end local schedulerEntry = nil @@ -122,8 +122,8 @@ local function TileMapEditTest() layer:addChild(map, 0, kTagTileMap) - map:setAnchorPoint( cc.p(0, 0) ) - map:setPosition( cc.p(-20,-200) ) + map:setAnchorPoint( ax.p(0, 0) ) + map:setPosition( ax.p(-20,-200) ) return layer end @@ -141,10 +141,10 @@ local function TMXOrthoTest() -- -- it should not flicker. No artifacts should appear -- - --local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + --local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) --addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test2.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test2.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -178,9 +178,9 @@ local function TMXOrthoTest() local function onNodeEvent(event) if event == "enter" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION3_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION3_D ) elseif event == "exit" then - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) end end @@ -198,7 +198,7 @@ end local function TMXOrthoTest2() local layer = createTileDemoLayer("TMX Ortho test2") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test1.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test1.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -219,7 +219,7 @@ local function TMXOrthoTest2() child:getTexture():setAntiAliasTexParameters() end - map:runAction( cc.ScaleBy:create(2, 0.5) ) + map:runAction( ax.ScaleBy:create(2, 0.5) ) return layer end @@ -230,7 +230,7 @@ end -------------------------------------------------------------------- local function TMXOrthoTest3() local layer = createTileDemoLayer("TMX anchorPoint test") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test3.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test3.tmx") layer:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -252,7 +252,7 @@ local function TMXOrthoTest3() end map:setScale(0.2) - map:setAnchorPoint( cc.p(0.5, 0.5) ) + map:setAnchorPoint( ax.p(0.5, 0.5) ) return layer end @@ -264,7 +264,7 @@ end -------------------------------------------------------------------- local function TMXOrthoTest4() local ret = createTileDemoLayer("TMX width/height test") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test4.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test4.tmx") ret:addChild(map, 0, kTagTileMap) local s1 = map:getContentSize() @@ -285,18 +285,18 @@ local function TMXOrthoTest4() child:getTexture():setAntiAliasTexParameters() end - map:setAnchorPoint(cc.p(0, 0)) + map:setAnchorPoint(ax.p(0, 0)) local layer = map:getLayer("Layer 0") local s = layer:getLayerSize() - local sprite = layer:getTileAt(cc.p(0,0)) + local sprite = layer:getTileAt(ax.p(0,0)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(s.width-1,0)) + sprite = layer:getTileAt(ax.p(s.width-1,0)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(0,s.height-1)) + sprite = layer:getTileAt(ax.p(0,s.height-1)) sprite:setScale(2) - sprite = layer:getTileAt(cc.p(s.width-1,s.height-1)) + sprite = layer:getTileAt(ax.p(s.width-1,s.height-1)) sprite:setScale(2) local schedulerEntry = nil @@ -308,7 +308,7 @@ local function TMXOrthoTest4() local layer0 = map:getLayer("Layer 0") local s = layer0:getLayerSize() - local sprite = layer0:getTileAt( cc.p(s.width-1,0) ) + local sprite = layer0:getTileAt( ax.p(s.width-1,0) ) layer0:removeChild(sprite, true) end @@ -338,7 +338,7 @@ local function TMXReadWriteTest() local ret = createTileDemoLayer("TMX Read/Write test") local m_gid = 0 local m_gid2 = 0 - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test2.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test2.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -350,21 +350,21 @@ local function TMXReadWriteTest() map:setScale( 1 ) - local tile0 = layer:getTileAt(cc.p(1,63)) - local tile1 = layer:getTileAt(cc.p(2,63)) - local tile2 = layer:getTileAt(cc.p(3,62))--cc.p(1,62)) - local tile3 = layer:getTileAt(cc.p(2,62)) - tile0:setAnchorPoint( cc.p(0.5, 0.5) ) - tile1:setAnchorPoint( cc.p(0.5, 0.5) ) - tile2:setAnchorPoint( cc.p(0.5, 0.5) ) - tile3:setAnchorPoint( cc.p(0.5, 0.5) ) - - local move = cc.MoveBy:create(0.5, cc.p(0,160)) - local rotate = cc.RotateBy:create(2, 360) - local scale = cc.ScaleBy:create(2, 5) - local opacity = cc.FadeOut:create(2) - local fadein = cc.FadeIn:create(2) - local scaleback = cc.ScaleTo:create(1, 1) + local tile0 = layer:getTileAt(ax.p(1,63)) + local tile1 = layer:getTileAt(ax.p(2,63)) + local tile2 = layer:getTileAt(ax.p(3,62))--ax.p(1,62)) + local tile3 = layer:getTileAt(ax.p(2,62)) + tile0:setAnchorPoint( ax.p(0.5, 0.5) ) + tile1:setAnchorPoint( ax.p(0.5, 0.5) ) + tile2:setAnchorPoint( ax.p(0.5, 0.5) ) + tile3:setAnchorPoint( ax.p(0.5, 0.5) ) + + local move = ax.MoveBy:create(0.5, ax.p(0,160)) + local rotate = ax.RotateBy:create(2, 360) + local scale = ax.ScaleBy:create(2, 5) + local opacity = ax.FadeOut:create(2) + local fadein = ax.FadeIn:create(2) + local scaleback = ax.ScaleTo:create(1, 1) local function removeSprite(sender) --------cclog("removing tile: %x", sender) @@ -380,8 +380,8 @@ local function TMXReadWriteTest() ----------cclog("atlas quantity: %d", p:textureAtlas():totalQuads()) end - local finish = cc.CallFunc:create(removeSprite) - local seq0 = cc.Sequence:create(move, rotate, scale, opacity, fadein, scaleback, finish) + local finish = ax.CallFunc:create(removeSprite) + local seq0 = ax.Sequence:create(move, rotate, scale, opacity, fadein, scaleback, finish) local seq1 = seq0:clone() local seq2 = seq0:clone() local seq3 = seq0:clone() @@ -392,7 +392,7 @@ local function TMXReadWriteTest() tile3:runAction(seq3) - m_gid = layer:getTileGIDAt(cc.p(0,63)) + m_gid = layer:getTileGIDAt(ax.p(0,63)) --------cclog("Tile GID at:(0,63) is: %d", m_gid) local updateColScheduler = nil local repainWithGIDScheduler = nil @@ -410,7 +410,7 @@ local function TMXReadWriteTest() local s = layer:getLayerSize() local y = 0 for y=0, s.height-1, 1 do - layer:setTileGID(m_gid2, cc.p(3, y)) + layer:setTileGID(m_gid2, ax.p(3, y)) end m_gid2 = (m_gid2 + 1) % 80 @@ -425,8 +425,8 @@ local function TMXReadWriteTest() local x = 0 for x=0, s.width-1, 1 do local y = s.height-1 - local tmpgid = layer:getTileGIDAt( cc.p(x, y) ) - layer:setTileGID(tmpgid+1, cc.p(x, y)) + local tmpgid = layer:getTileGIDAt( ax.p(x, y) ) + layer:setTileGID(tmpgid+1, ax.p(x, y)) end end @@ -438,7 +438,7 @@ local function TMXReadWriteTest() local s = layer:getLayerSize() local y = 0 for y=0, s.height-1, 1 do - layer:removeTileAt( cc.p(5.0, y) ) + layer:removeTileAt( ax.p(5.0, y) ) end end @@ -479,10 +479,10 @@ end -------------------------------------------------------------------- local function TMXHexTest() local ret = createTileDemoLayer("TMX Hex tes") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/hexa-test.tmx") + local map = ax.TMXTiledMap:create("TileMaps/hexa-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -497,16 +497,16 @@ end -------------------------------------------------------------------- local function TMXIsoTest() local ret = createTileDemoLayer("TMX Isometric test 0") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/iso-test.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test.tmx") ret:addChild(map, 0, kTagTileMap) -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction( cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 )) ) + map:runAction( ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 )) ) return ret end @@ -517,16 +517,16 @@ end -------------------------------------------------------------------- local function TMXIsoTest1() local ret = createTileDemoLayer("TMX Isometric test + anchorPoint") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/iso-test1.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test1.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - map:setAnchorPoint(cc.p(0.5, 0.5)) + map:setAnchorPoint(ax.p(0.5, 0.5)) return ret end @@ -537,10 +537,10 @@ end -------------------------------------------------------------------- local function TMXIsoTest2() local ret = createTileDemoLayer("TMX Isometric test 2") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/iso-test2.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test2.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -549,7 +549,7 @@ local function TMXIsoTest2() -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction( cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) + map:runAction( ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) return ret end @@ -560,10 +560,10 @@ end -------------------------------------------------------------------- local function TMXUncompressedTest() local ret = createTileDemoLayer("TMX Uncompressed test") - local color = cc.LayerColor:create( cc.c4b(64,64,64,255) ) + local color = ax.LayerColor:create( ax.color32(64,64,64,255) ) ret:addChild(color, -1) - local map = cc.TMXTiledMap:create("TileMaps/iso-test2-uncompressed.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test2-uncompressed.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -572,7 +572,7 @@ local function TMXUncompressedTest() -- move map to the center of the screen local ms = map:getMapSize() local ts = map:getTileSize() - map:runAction(cc.MoveTo:create(1.0, cc.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) + map:runAction(ax.MoveTo:create(1.0, ax.p( -ms.width * ts.width/2, -ms.height * ts.height/2 ) )) -- testing release map local pChildrenArray = map:getChildren() @@ -596,7 +596,7 @@ end -------------------------------------------------------------------- local function TMXTilesetTest() local ret = createTileDemoLayer("TMX Tileset test") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test5.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test5.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -620,13 +620,13 @@ end -------------------------------------------------------------------- local function TMXOrthoObjectsTest() local ret = createTileDemoLayer("TMX Ortho object test", "You should see a white box around the 3 platforms") - local map = cc.TMXTiledMap:create("TileMaps/ortho-objects.tmx") + local map = ax.TMXTiledMap:create("TileMaps/ortho-objects.tmx") ret:addChild(map, -1, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - - local drawNode = cc.DrawNode:create() + + local drawNode = ax.DrawNode:create() map:addChild(drawNode, 10) --------cclog("---: Iterating over all the group objects") @@ -644,7 +644,7 @@ local function TMXOrthoObjectsTest() break end --------cclog("object: %x", dict) - + local key = "x" local x = dict["x"] key = "y" @@ -653,12 +653,12 @@ local function TMXOrthoObjectsTest() local width = dict["width"]--dynamic_cast(dict:objectForKey("width")):getNumber() key = "height" local height = dict["height"]--dynamic_cast(dict:objectForKey("height")):getNumber() - - local color = cc.c4f(1,1,1,1) - drawNode:drawLine( cc.p(x, y), cc.p((x+width), y), color) - drawNode:drawLine( cc.p((x+width), y), cc.p((x+width), (y+height)), color) - drawNode:drawLine( cc.p((x+width), (y+height)), cc.p(x, (y+height)), color) - drawNode:drawLine( cc.p(x, (y+height)), cc.p(x, y), color) + + local color = ax.color(1,1,1,1) + drawNode:drawLine( ax.p(x, y), ax.p((x+width), y), color) + drawNode:drawLine( ax.p((x+width), y), ax.p((x+width), (y+height)), color) + drawNode:drawLine( ax.p((x+width), (y+height)), ax.p(x, (y+height)), color) + drawNode:drawLine( ax.p(x, (y+height)), ax.p(x, y), color) end --------cclog("---: Fetching 1 object by name") @@ -676,7 +676,7 @@ end local function TMXIsoObjectsTest() local ret = createTileDemoLayer("TMX Iso object test", "You need to parse them manually. See bug #810") - local map = cc.TMXTiledMap:create("TileMaps/iso-test-objectgroup.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test-objectgroup.tmx") ret:addChild(map, -1, kTagTileMap) local s = map:getContentSize() @@ -684,7 +684,7 @@ local function TMXIsoObjectsTest() local group = map:getObjectGroup("Object Group 1") - local drawNode = cc.DrawNode:create() + local drawNode = ax.DrawNode:create() map:addChild(drawNode, 10) --UxMutableArray* objects = group:objects() @@ -694,27 +694,27 @@ local function TMXIsoObjectsTest() local i = 0 local len = #(objects) for i = 0, len-1, 1 do - dict = tolua.cast(objects[i + 1], "cc.Dictionary") + dict = tolua.cast(objects[i + 1], "ax.Dictionary") if dict == nil then break end --------cclog("object: %x", dict) - + local key = "x" - local x = (tolua.cast(dict:objectForKey(key), "cc.String")):intValue()--dynamic_cast(dict:objectForKey("x")):getNumber() + local x = (tolua.cast(dict:objectForKey(key), "ax.String")):intValue()--dynamic_cast(dict:objectForKey("x")):getNumber() key = "y" - local y = (tolua.cast(dict:objectForKey(key), "cc.String")):intValue()--dynamic_cast(dict:objectForKey("y")):getNumber() + local y = (tolua.cast(dict:objectForKey(key), "ax.String")):intValue()--dynamic_cast(dict:objectForKey("y")):getNumber() key = "width" - local width = (tolua.cast(dict:objectForKey(key), "cc.String")):intValue()--dynamic_cast(dict:objectForKey("width")):getNumber() + local width = (tolua.cast(dict:objectForKey(key), "ax.String")):intValue()--dynamic_cast(dict:objectForKey("width")):getNumber() key = "height" - local height = (tolua.cast(dict:objectForKey(key), "cc.String")):intValue()--dynamic_cast(dict:objectForKey("height")):getNumber() - - local color = cc.c4f(1,1,1,1) - drawNode:drawLine( cc.p(x, y), cc.p((x+width), y), color) - drawNode:drawLine( cc.p((x+width), y), cc.p((x+width), (y+height)), color) - drawNode:drawLine( cc.p((x+width), (y+height)), cc.p(x, (y+height)), color) - drawNode:drawLine( cc.p(x, (y+height)), cc.p(x, y), color) + local height = (tolua.cast(dict:objectForKey(key), "ax.String")):intValue()--dynamic_cast(dict:objectForKey("height")):getNumber() + + local color = ax.color(1,1,1,1) + drawNode:drawLine( ax.p(x, y), ax.p((x+width), y), color) + drawNode:drawLine( ax.p((x+width), y), ax.p((x+width), (y+height)), color) + drawNode:drawLine( ax.p((x+width), (y+height)), ax.p(x, (y+height)), color) + drawNode:drawLine( ax.p(x, (y+height)), ax.p(x, y), color) end return ret end @@ -727,7 +727,7 @@ end local function TMXResizeTest() local ret = createTileDemoLayer("TMX resize test", "Should not crash. Testing issue #740") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test5.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test5.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -739,7 +739,7 @@ local function TMXResizeTest() local y = 0 for y = 0, ls.height-1, 1 do for x = 0, ls.width-1, 1 do - layer:setTileGID(1, cc.p( x, y ) ) + layer:setTileGID(1, ax.p( x, y ) ) end end return ret @@ -751,30 +751,30 @@ end -- -------------------------------------------------------------------- local function TMXIsoZorder() - cc.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) local m_tamara = nil local ret = createTileDemoLayer("TMX Iso Zorder", "Sprite should hide behind the trees") - local map = cc.TMXTiledMap:create("TileMaps/iso-test-zorder.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test-zorder.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - map:setPosition(cc.p(-s.width/2,0)) + map:setPosition(ax.p(-s.width/2,0)) - m_tamara = cc.Sprite:create(s_pPathSister1) + m_tamara = ax.Sprite:create(s_pPathSister1) map:addChild(m_tamara, #(map:getChildren())) m_tamara:retain() local mapWidth = map:getMapSize().width * map:getTileSize().width - m_tamara:setPosition(AX_POINT_PIXELS_TO_POINTS(cc.p( mapWidth/2,0))) - m_tamara:setAnchorPoint(cc.p(0.5,0)) + m_tamara:setPosition(AX_POINT_PIXELS_TO_POINTS(ax.p( mapWidth/2,0))) + m_tamara:setAnchorPoint(ax.p(0.5,0)) - local move = cc.MoveBy:create(10, cc.p(300,250)) + local move = ax.MoveBy:create(10, ax.p(300,250)) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq) ) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq) ) local function repositionSprite(dt) - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local map = ret:getChildByTag(kTagTileMap) @@ -814,25 +814,25 @@ end local function TMXOrthoZorder() local m_tamara = nil local ret = createTileDemoLayer("TMX Ortho Zorder", "Sprite should hide behind the trees") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test-zorder.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test-zorder.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) - m_tamara = cc.Sprite:create(s_pPathSister1) + m_tamara = ax.Sprite:create(s_pPathSister1) map:addChild(m_tamara, #(map:getChildren())) m_tamara:retain() - m_tamara:setAnchorPoint(cc.p(0.5,0)) + m_tamara:setAnchorPoint(ax.p(0.5,0)) - local move = cc.MoveBy:create(10, cc.p(400,450)) + local move = ax.MoveBy:create(10, ax.p(400,450)) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq)) local function repositionSprite(dt) - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local map = ret:getChildByTag(kTagTileMap) @@ -872,28 +872,28 @@ end local function TMXIsoVertexZ() local m_tamara = nil local ret = createTileDemoLayer("TMX Iso VertexZ", "Sprite should hide behind the trees") - local map = cc.TMXTiledMap:create("TileMaps/iso-test-vertexz.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test-vertexz.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() - map:setPosition( cc.p(-s.width/2,0) ) + map:setPosition( ax.p(-s.width/2,0) ) cclog("ContentSize: %f, %f", s.width,s.height) -- because I'm lazy, I'm reusing a tile as an sprite, but since this method uses vertexZ, you - -- can use any cc.Sprite and it will work OK. + -- can use any ax.Sprite and it will work OK. local layer = map:getLayer("Trees") - m_tamara = layer:getTileAt( cc.p(29,29) ) + m_tamara = layer:getTileAt( ax.p(29,29) ) m_tamara:retain() - local move = cc.MoveBy:create(10, cc.pMul( cc.p(300,250), 1/AX_CONTENT_SCALE_FACTOR() ) ) + local move = ax.MoveBy:create(10, ax.pMul( ax.p(300,250), 1/AX_CONTENT_SCALE_FACTOR() ) ) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq) ) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq) ) local function repositionSprite(dt) -- tile height is 64x32 -- map size: 30x30 - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) local newZ = -(p.y+32) /16 m_tamara:setPositionZ( newZ ) @@ -903,19 +903,19 @@ local function TMXIsoVertexZ() local function onNodeEvent(event) if event == "enter" then -- TIP: 2d projection should be used - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION2_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION2_D ) schedulerEntry = scheduler:scheduleScriptFunc(repositionSprite, 0, false) - cc.Director:getInstance():getRenderer():setDepthTest(true) - cc.Director:getInstance():getRenderer():setDepthWrite(true) + ax.Director:getInstance():getRenderer():setDepthTest(true) + ax.Director:getInstance():getRenderer():setDepthWrite(true) elseif event == "exit" then -- At exit use any other projection. - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) if m_tamara ~= nil then m_tamara:release() end scheduler:unscheduleScriptEntry(schedulerEntry) - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():getRenderer():setDepthWrite(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthWrite(false) end end @@ -931,28 +931,28 @@ end local function TMXOrthoVertexZ() local m_tamara = nil local ret = createTileDemoLayer("TMX Ortho vertexZ", "Sprite should hide behind the trees") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test-vertexz.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test-vertexz.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) -- because I'm lazy, I'm reusing a tile as an sprite, but since this method uses vertexZ, you - -- can use any cc.Sprite and it will work OK. + -- can use any ax.Sprite and it will work OK. local layer = map:getLayer("trees") - m_tamara = layer:getTileAt(cc.p(0,11)) + m_tamara = layer:getTileAt(ax.p(0,11)) cclog("vertexZ:"..m_tamara:getPositionZ()) m_tamara:retain() - local move = cc.MoveBy:create(10, cc.pMul( cc.p(400,450), 1/AX_CONTENT_SCALE_FACTOR())) + local move = ax.MoveBy:create(10, ax.pMul( ax.p(400,450), 1/AX_CONTENT_SCALE_FACTOR())) local back = move:reverse() - local seq = cc.Sequence:create(move, back) - m_tamara:runAction( cc.RepeatForever:create(seq)) + local seq = ax.Sequence:create(move, back) + m_tamara:runAction( ax.RepeatForever:create(seq)) local function repositionSprite(dt) -- tile height is 101x81 -- map size: 12x12 - local p = cc.p(m_tamara:getPosition()) + local p = ax.p(m_tamara:getPosition()) p = AX_POINT_POINTS_TO_PIXELS(p) m_tamara:setPositionZ( -( (p.y+81) /81) ) end @@ -961,19 +961,19 @@ local function TMXOrthoVertexZ() local function onNodeEvent(event) if event == "enter" then -- TIP: 2d projection should be used - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION2_D ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION2_D ) schedulerEntry = scheduler:scheduleScriptFunc(repositionSprite, 0, false) - cc.Director:getInstance():getRenderer():setDepthTest(true) - cc.Director:getInstance():getRenderer():setDepthWrite(true) + ax.Director:getInstance():getRenderer():setDepthTest(true) + ax.Director:getInstance():getRenderer():setDepthWrite(true) elseif event == "exit" then -- At exit use any other projection. - cc.Director:getInstance():setProjection(cc.DIRECTOR_PROJECTION_DEFAULT ) + ax.Director:getInstance():setProjection(ax.DIRECTOR_PROJECTION_DEFAULT ) if m_tamara ~= nil then m_tamara:release() end scheduler:unscheduleScriptEntry(schedulerEntry) - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():getRenderer():setDepthWrite(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthWrite(false) end end @@ -989,10 +989,10 @@ end -------------------------------------------------------------------- local function TMXIsoMoveLayer() local ret = createTileDemoLayer("TMX Iso Move Layer", "Trees should be horizontally aligned") - local map = cc.TMXTiledMap:create("TileMaps/iso-test-movelayer.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test-movelayer.tmx") ret:addChild(map, 0, kTagTileMap) - map:setPosition(cc.p(-700,-50)) + map:setPosition(ax.p(-700,-50)) local s = map:getContentSize() cclog("ContentSize: %f, %f", s.width,s.height) @@ -1007,7 +1007,7 @@ end -------------------------------------------------------------------- local function TMXOrthoMoveLayer() local ret = createTileDemoLayer("TMX Ortho Move Layer", "Trees should be horizontally aligned") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test-movelayer.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test-movelayer.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -1023,7 +1023,7 @@ end local function TMXTilePropertyTest() local ret = createTileDemoLayer("TMX Tile Property Test", "In the console you should see tile properties") - local map = cc.TMXTiledMap:create("TileMaps/ortho-tile-property.tmx") + local map = ax.TMXTiledMap:create("TileMaps/ortho-tile-property.tmx") ret:addChild(map ,0 ,kTagTileMap) local i = 0 for i=1, 20, 1 do @@ -1040,7 +1040,7 @@ end local function TMXOrthoFlipTest() local ret = createTileDemoLayer("TMX tile flip test") - local map = cc.TMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") + local map = ax.TMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -1052,7 +1052,7 @@ local function TMXOrthoFlipTest() child:getTexture():setAntiAliasTexParameters() end - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) return ret end @@ -1065,7 +1065,7 @@ end local function TMXOrthoFlipRunTimeTest() local ret = createTileDemoLayer("TMX tile flip run time test", "in 2 sec bottom left tiles will flip") - local map = cc.TMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") + local map = ax.TMXTiledMap:create("TileMaps/ortho-rotation-test.tmx") ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -1077,41 +1077,41 @@ local function TMXOrthoFlipRunTimeTest() child:getTexture():setAntiAliasTexParameters() end - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) local function flipIt(dt) local map = ret:getChildByTag(kTagTileMap) local layer = map:getLayer("Layer 0") - local tileCoord = cc.p(1, 10) + local tileCoord = ax.p(1, 10) local flags = 0 local GID, flags = layer:getTileGIDAt(tileCoord, flags) - if 0 ~= bit._and(flags, cc.TMX_TILE_VERTICAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_VERTICAL_FLAG)) + if 0 ~= bit._and(flags, ax.TMX_TILE_VERTICAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_VERTICAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_VERTICAL_FLAG) + flags = bit._or(flags, ax.TMX_TILE_VERTICAL_FLAG) end layer:setTileGID(GID, tileCoord, flags) - tileCoord = cc.p(1,8) + tileCoord = ax.p(1,8) GID, flags = layer:getTileGIDAt(tileCoord, flags) - if 0 ~= bit._and(flags, cc.TMX_TILE_VERTICAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_VERTICAL_FLAG)) + if 0 ~= bit._and(flags, ax.TMX_TILE_VERTICAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_VERTICAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_VERTICAL_FLAG) - end + flags = bit._or(flags, ax.TMX_TILE_VERTICAL_FLAG) + end layer:setTileGID(GID ,tileCoord, flags) - tileCoord = cc.p(2,8) + tileCoord = ax.p(2,8) GID, flags = layer:getTileGIDAt(tileCoord, flags) -- Horizontal - if 0~= bit._and(flags, cc.TMX_TILE_HORIZONTAL_FLAG) then - flags = bit._and(flags, bit._not(cc.TMX_TILE_HORIZONTAL_FLAG)) + if 0~= bit._and(flags, ax.TMX_TILE_HORIZONTAL_FLAG) then + flags = bit._and(flags, bit._not(ax.TMX_TILE_HORIZONTAL_FLAG)) else - flags = bit._or(flags, cc.TMX_TILE_HORIZONTAL_FLAG) - end - layer:setTileGID(GID, tileCoord, flags) + flags = bit._or(flags, ax.TMX_TILE_HORIZONTAL_FLAG) + end + layer:setTileGID(GID, tileCoord, flags) end local schedulerEntry = nil @@ -1140,13 +1140,13 @@ local function TMXOrthoFromXMLTest() local resources = "TileMaps" -- partial paths are OK as resource paths. local file = resources.."/orthogonal-test1.tmx" - local str = cc.FileUtils:getInstance():getStringFromFile(file) - -- cc.ASSERT(str != NULL, "Unable to open file") + local str = ax.FileUtils:getInstance():getStringFromFile(file) + -- ax.ASSERT(str != NULL, "Unable to open file") if (str == nil) then cclog("Unable to open file") end - local map = cc.TMXTiledMap:createWithXML(str ,resources) + local map = ax.TMXTiledMap:createWithXML(str ,resources) ret:addChild(map, 0, kTagTileMap) local s = map:getContentSize() @@ -1159,7 +1159,7 @@ local function TMXOrthoFromXMLTest() child:getTexture():setAntiAliasTexParameters() end - local action = cc.ScaleBy:create(2, 0.5) + local action = ax.ScaleBy:create(2, 0.5) map:runAction(action) return ret end @@ -1171,7 +1171,7 @@ end -------------------------------------------------------------------- local function TMXBug987() local ret = createTileDemoLayer("TMX Bug 987", "You should see an square") - local map = cc.TMXTiledMap:create("TileMaps/orthogonal-test6.tmx") + local map = ax.TMXTiledMap:create("TileMaps/orthogonal-test6.tmx") ret:addChild(map, 0, kTagTileMap) local s1 = map:getContentSize() @@ -1190,9 +1190,9 @@ local function TMXBug987() pNode:getTexture():setAntiAliasTexParameters() end - map:setAnchorPoint(cc.p(0, 0)) + map:setAnchorPoint(ax.p(0, 0)) local layer = map:getLayer("Tile Layer 1") - layer:setTileGID(3, cc.p(2,2)) + layer:setTileGID(3, ax.p(2,2)) return ret end @@ -1203,7 +1203,7 @@ end -------------------------------------------------------------------- local function TMXBug787() local ret = createTileDemoLayer("TMX Bug 787", "You should see a map") - local map = cc.TMXTiledMap:create("TileMaps/iso-test-bug787.tmx") + local map = ax.TMXTiledMap:create("TileMaps/iso-test-bug787.tmx") ret:addChild(map, 0, kTagTileMap) map:setScale(0.25) return ret @@ -1212,7 +1212,7 @@ end function TileMapTestMain() cclog("TileMapTestMain") Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { TileMapTest, @@ -1245,7 +1245,7 @@ function TileMapTestMain() TMXBug787 } Helper.index = 1 - + scene:addChild(TileMapTest()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/TouchesTest/Ball.lua b/tests/lua-tests/Content/src/TouchesTest/Ball.lua index 9c75586d3593..b4facf20f13b 100644 --- a/tests/lua-tests/Content/src/TouchesTest/Ball.lua +++ b/tests/lua-tests/Content/src/TouchesTest/Ball.lua @@ -2,12 +2,12 @@ require "VisibleRect" require "TouchesTest/Paddle" Ball = class("Ball", function(texture) - return cc.Sprite:createWithTexture(texture) + return ax.Sprite:createWithTexture(texture) end) Ball.__index = Ball -Ball.m_velocity = cc.p(0,0) +Ball.m_velocity = ax.p(0,0) local M_PI = 3.1415926 @@ -17,58 +17,58 @@ function Ball:radius() end function Ball:move(delta) - local getPosition = cc.p(self:getPosition()) - local position = cc.pMul(self.m_velocity, delta) - self:setPosition( cc.pAdd(getPosition, position) ) - + local getPosition = ax.p(self:getPosition()) + local position = ax.pMul(self.m_velocity, delta) + self:setPosition( ax.pAdd(getPosition, position) ) + if (getPosition.x > VisibleRect:right().x - self:radius()) then - self:setPosition( cc.p( VisibleRect:right().x - self:radius(), getPosition.y) ) + self:setPosition( ax.p( VisibleRect:right().x - self:radius(), getPosition.y) ) self.m_velocity.x = self.m_velocity.x * -1 elseif (getPosition.x < VisibleRect:left().x + self:radius()) then - self:setPosition( cc.p(VisibleRect:left().x + self:radius(), getPosition.y) ) + self:setPosition( ax.p(VisibleRect:left().x + self:radius(), getPosition.y) ) self.m_velocity.x = self.m_velocity.x * -1 end end function Ball:collideWithPaddle(paddle) local paddleRect = paddle:rect() - local paddleGetPosition = cc.p(paddle:getPosition()) - local selfGetPosition = cc.p(self:getPosition()) + local paddleGetPosition = ax.p(paddle:getPosition()) + local selfGetPosition = ax.p(self:getPosition()) paddleRect.x = paddleRect.x + paddleGetPosition.x paddleRect.y = paddleRect.y + paddleGetPosition.y - local lowY = cc.rectGetMinY(paddleRect) - local midY = cc.rectGetMidY(paddleRect) - local highY = cc.rectGetMaxY(paddleRect) + local lowY = ax.rectGetMinY(paddleRect) + local midY = ax.rectGetMidY(paddleRect) + local highY = ax.rectGetMaxY(paddleRect) - local leftX = cc.rectGetMinX(paddleRect) - local rightX = cc.rectGetMaxX(paddleRect) + local leftX = ax.rectGetMinX(paddleRect) + local rightX = ax.rectGetMaxX(paddleRect) if (selfGetPosition.x > leftX and selfGetPosition.x < rightX) then local hit = false - local angleOffset = 0.0 + local angleOffset = 0.0 if (selfGetPosition.y > midY and selfGetPosition.y <= highY + self:radius()) then - self:setPosition( cc.p(selfGetPosition.x, highY + self:radius()) ) + self:setPosition( ax.p(selfGetPosition.x, highY + self:radius()) ) hit = true angleOffset = M_PI / 2 elseif (selfGetPosition.y < midY and selfGetPosition.y >= lowY - self:radius()) then - self:setPosition( cc.p(selfGetPosition.x, lowY - self:radius()) ) + self:setPosition( ax.p(selfGetPosition.x, lowY - self:radius()) ) hit = true angleOffset = -M_PI / 2 end if (hit) then - local hitAngle = cc.pToAngleSelf(cc.pSub(paddleGetPosition, paddleGetPosition)) + angleOffset + local hitAngle = ax.pToAngleSelf(ax.pSub(paddleGetPosition, paddleGetPosition)) + angleOffset - local scalarVelocity = cc.pGetLength(self.m_velocity) * 1.05 - local velocityAngle = -cc.pToAngleSelf(self.m_velocity) + 0.5 * hitAngle + local scalarVelocity = ax.pGetLength(self.m_velocity) * 1.05 + local velocityAngle = -ax.pToAngleSelf(self.m_velocity) + 0.5 * hitAngle - self.m_velocity = cc.pMul(cc.pForAngle(velocityAngle), scalarVelocity) + self.m_velocity = ax.pMul(ax.pForAngle(velocityAngle), scalarVelocity) end - end + end end diff --git a/tests/lua-tests/Content/src/TouchesTest/Paddle.lua b/tests/lua-tests/Content/src/TouchesTest/Paddle.lua index e7022387de41..1338c399e805 100644 --- a/tests/lua-tests/Content/src/TouchesTest/Paddle.lua +++ b/tests/lua-tests/Content/src/TouchesTest/Paddle.lua @@ -1,7 +1,7 @@ require "VisibleRect" Paddle = class("Paddle", function(texture) - return cc.Sprite:createWithTexture(texture) + return ax.Sprite:createWithTexture(texture) end) Paddle.__index = Paddle @@ -14,14 +14,14 @@ Paddle._state = kPaddleStateGrabbed function Paddle:rect() local s = self:getTexture():getContentSize() - return cc.rect(-s.width / 2, -s.height / 2, s.width, s.height) + return ax.rect(-s.width / 2, -s.height / 2, s.width, s.height) end function Paddle:containsTouchLocation(x,y) - local position = cc.p(self:getPosition()) + local position = ax.p(self:getPosition()) local s = self:getTexture():getContentSize() - local touchRect = cc.rect(-s.width / 2 + position.x, -s.height / 2 + position.y, s.width, s.height) - local b = cc.rectContainsPoint(touchRect, cc.p(x,y)) + local touchRect = ax.rect(-s.width / 2 + position.x, -s.height / 2 + position.y, s.width, s.height) + local b = ax.rectContainsPoint(touchRect, ax.p(x,y)) return b end @@ -38,11 +38,11 @@ end) end function Paddle:onEnter() - local listenner = cc.EventListenerTouchOneByOne:create() + local listenner = ax.EventListenerTouchOneByOne:create() listenner:setSwallowTouches(true) listenner:registerScriptHandler(function(touch, event) print(string.format("Paddle::onTouchBegan id = %d, x = %f, y = %f", touch:getId(), touch:getLocation().x, touch:getLocation().y)) - if (self._state ~= kPaddleStateUngrabbed) then + if (self._state ~= kPaddleStateUngrabbed) then return false end @@ -52,18 +52,18 @@ function Paddle:onEnter() self._state = kPaddleStateGrabbed return true - end,cc.Handler.EVENT_TOUCH_BEGAN ) + end,ax.Handler.EVENT_TOUCH_BEGAN ) listenner:registerScriptHandler(function(touch, event) print(string.format("Paddle::onTouchMoved id = %d, x = %f, y = %f", touch:getId(), touch:getLocation().x, touch:getLocation().y)) assert(self._state == kPaddleStateGrabbed, "Paddle - Unexpected state!") local touchPoint = touch:getLocation() local curPosX,curPosY = self:getPosition() - self:setPosition(cc.p(touchPoint.x,curPosY)) - end,cc.Handler.EVENT_TOUCH_MOVED ) + self:setPosition(ax.p(touchPoint.x,curPosY)) + end,ax.Handler.EVENT_TOUCH_MOVED ) listenner:registerScriptHandler(function(touch, event) assert(self._state == kPaddleStateGrabbed, "Paddle - Unexpected state!") self._state = kPaddleStateUngrabbed - end,cc.Handler.EVENT_TOUCH_ENDED ) + end,ax.Handler.EVENT_TOUCH_ENDED ) local eventDispatcher = self:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listenner, self) end diff --git a/tests/lua-tests/Content/src/TouchesTest/TouchesTest.lua b/tests/lua-tests/Content/src/TouchesTest/TouchesTest.lua index a26d587a4ac2..50814d9498bb 100644 --- a/tests/lua-tests/Content/src/TouchesTest/TouchesTest.lua +++ b/tests/lua-tests/Content/src/TouchesTest/TouchesTest.lua @@ -7,7 +7,7 @@ local kHighPlayer = 0 local kLowPlayer = 1 local kStatusBarHeight = 0.0 - + local kSpriteTag = 0 local m_ball = nil @@ -16,14 +16,14 @@ local m_paddles = {} local layer = nil local function backCallback(sender) - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function resetAndScoreBallForPlayer(player) - m_ballStartingVelocity = cc.pMul(m_ballStartingVelocity, -1.1); + m_ballStartingVelocity = ax.pMul(m_ballStartingVelocity, -1.1); m_ball:setVelocity( m_ballStartingVelocity ); m_ball:setPosition( VisibleRect:center() ); end @@ -39,7 +39,7 @@ local function doStep(delta) m_ball:collideWithPaddle( paddle ); end - local ballPosition = cc.p(m_ball:getPosition()) + local ballPosition = ax.p(m_ball:getPosition()) if (ballPosition.y > VisibleRect:top().y - kStatusBarHeight + m_ball:radius()) then resetAndScoreBallForPlayer( kLowPlayer ); elseif (ballPosition.y < VisibleRect:bottom().y-m_ball:radius()) then @@ -49,10 +49,10 @@ local function doStep(delta) end local function CreateTouchesLayer() - layer = cc.Layer:create() + layer = ax.Layer:create() - m_ballStartingVelocity = cc.p(20.0, -100.0); - local mgr = cc.Director:getInstance():getTextureCache() + m_ballStartingVelocity = ax.p(20.0, -100.0); + local mgr = ax.Director:getInstance():getTextureCache() local texture = mgr:addImage(s_Ball) m_ball = Ball.ballWithTexture(texture); @@ -60,31 +60,31 @@ local function CreateTouchesLayer() m_ball:setVelocity( m_ballStartingVelocity ); layer:addChild( m_ball ); m_ball:retain(); - - local paddleTexture = cc.Director:getInstance():getTextureCache():addImage(s_Paddle); - + + local paddleTexture = ax.Director:getInstance():getTextureCache():addImage(s_Paddle); + local paddlesM = {} - + local paddleStep =( VisibleRect:getVisibleRect().height - kStatusBarHeight - 30 - 3 * paddleTexture:getPixelsHigh() ) / 3 + paddleTexture:getPixelsHigh() local nextPaddlePos = VisibleRect:bottom().y + 15 local paddle = Paddle:paddleWithTexture(paddleTexture) - paddle:setPosition( cc.p(VisibleRect:center().x, nextPaddlePos) ) + paddle:setPosition( ax.p(VisibleRect:center().x, nextPaddlePos) ) paddlesM[#paddlesM+1] = paddle - + nextPaddlePos = nextPaddlePos + paddleStep paddle = Paddle:paddleWithTexture( paddleTexture ) - paddle:setPosition( cc.p(VisibleRect:center().x, nextPaddlePos) ) + paddle:setPosition( ax.p(VisibleRect:center().x, nextPaddlePos) ) paddlesM[#paddlesM+1] = paddle - + nextPaddlePos = nextPaddlePos + paddleStep paddle = Paddle:paddleWithTexture( paddleTexture ) - paddle:setPosition( cc.p(VisibleRect:center().x, nextPaddlePos) ) + paddle:setPosition( ax.p(VisibleRect:center().x, nextPaddlePos) ) paddlesM[#paddlesM+1] = paddle - + nextPaddlePos = nextPaddlePos + paddleStep paddle = Paddle:paddleWithTexture( paddleTexture ) - paddle:setPosition( cc.p(VisibleRect:center().x, nextPaddlePos) ) + paddle:setPosition( ax.p(VisibleRect:center().x, nextPaddlePos) ) paddlesM[#paddlesM+1] = paddle m_paddles = paddlesM @@ -109,7 +109,7 @@ local function nextAction() end function TouchesTest() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(nextAction()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/TransitionsTest/TransitionsTest.lua b/tests/lua-tests/Content/src/TransitionsTest/TransitionsTest.lua index 386416c8c001..9a00dbcd9620 100644 --- a/tests/lua-tests/Content/src/TransitionsTest/TransitionsTest.lua +++ b/tests/lua-tests/Content/src/TransitionsTest/TransitionsTest.lua @@ -4,7 +4,7 @@ require "TransitionsTest/TransitionsName" local SceneIdx = -1 local CurSceneNo = 2 local TRANSITION_DURATION = 1.2 -local s = cc.Director:getInstance():getWinSize() +local s = ax.Director:getInstance():getWinSize() local function switchSceneTypeNo() if CurSceneNo == 1 then @@ -38,58 +38,58 @@ end local function backCallback(sender) local scene = backAction() - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function restartCallback(sender) local scene = restartAction() - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end local function nextCallback(sender) local scene = nextAction() - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end ----------------------------- -- TestLayer1 ----------------------------- local function createLayer1() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local x, y = s.width, s.height - local bg1 = cc.Sprite:create(s_back1) - bg1:setPosition(cc.p(s.width / 2, s.height / 2)) + local bg1 = ax.Sprite:create(s_back1) + bg1:setPosition(ax.p(s.width / 2, s.height / 2)) layer:addChild(bg1, -1) - local titleLabel = cc.Label:createWithTTF(Transition_Name[SceneIdx], s_thonburiPath, 32) + local titleLabel = ax.Label:createWithTTF(Transition_Name[SceneIdx], s_thonburiPath, 32) layer:addChild(titleLabel) - titleLabel:setColor(cc.c3b(255,32,32)) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + titleLabel:setColor(ax.color32(255,32,32)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) titleLabel:setPosition(x / 2, y - 100) - local label = cc.Label:createWithTTF("SCENE 1", s_markerFeltFontPath, 38) - label:setColor(cc.c3b(16,16,255)) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("SCENE 1", s_markerFeltFontPath, 38) + label:setColor(ax.color32(16,16,255)) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(x / 2, y / 2) layer:addChild(label) -- menu - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) item1:registerScriptTapHandler(backCallback) item2:registerScriptTapHandler(restartCallback) item3:registerScriptTapHandler(nextCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(s.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(s.width / 2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(s.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(s.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(s.width / 2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(s.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) layer:addChild(menu, 1) @@ -100,41 +100,41 @@ end -- TestLayer2 ----------------------------- local function createLayer2() - local layer = cc.Layer:create() + local layer = ax.Layer:create() local x, y = s.width, s.height - local bg1 = cc.Sprite:create(s_back2) - bg1:setPosition(cc.p(s.width / 2, s.height / 2)) + local bg1 = ax.Sprite:create(s_back2) + bg1:setPosition(ax.p(s.width / 2, s.height / 2)) layer:addChild(bg1, -1) - local titleLabel = cc.Label:createWithTTF(Transition_Name[SceneIdx], s_thonburiPath, 32 ) + local titleLabel = ax.Label:createWithTTF(Transition_Name[SceneIdx], s_thonburiPath, 32 ) layer:addChild(titleLabel) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) - titleLabel:setColor(cc.c3b(255,32,32)) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) + titleLabel:setColor(ax.color32(255,32,32)) titleLabel:setPosition(x / 2, y - 100) - local label = cc.Label:createWithTTF("SCENE 2", s_markerFeltFontPath, 38) - label:setColor(cc.c3b(16,16,255)) - label:setAnchorPoint(cc.p(0.5, 0.5)) + local label = ax.Label:createWithTTF("SCENE 2", s_markerFeltFontPath, 38) + label:setColor(ax.color32(16,16,255)) + label:setAnchorPoint(ax.p(0.5, 0.5)) label:setPosition(x / 2, y / 2) layer:addChild(label) -- menu - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) item1:registerScriptTapHandler(backCallback) item2:registerScriptTapHandler(restartCallback) item3:registerScriptTapHandler(nextCallback) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(s.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) - item2:setPosition(cc.p(s.width / 2, item2:getContentSize().height / 2)) - item3:setPosition(cc.p(s.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(s.width / 2 - item2:getContentSize().width * 2, item2:getContentSize().height / 2)) + item2:setPosition(ax.p(s.width / 2, item2:getContentSize().height / 2)) + item3:setPosition(ax.p(s.width / 2 + item2:getContentSize().width * 2, item2:getContentSize().height / 2)) layer:addChild(menu, 1) @@ -145,7 +145,7 @@ end -- Create Transition Test ----------------------------- local function createTransition(index, t, scene) - cc.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():getRenderer():setDepthTest(false) if firstEnter == true then firstEnter = false @@ -153,96 +153,96 @@ local function createTransition(index, t, scene) end if index == Transition_Table.CCTransitionJumpZoom then - scene = cc.TransitionJumpZoom:create(t, scene) + scene = ax.TransitionJumpZoom:create(t, scene) elseif index == Transition_Table.CCTransitionProgressRadialCCW then - scene = cc.TransitionProgressRadialCCW:create(t, scene) + scene = ax.TransitionProgressRadialCCW:create(t, scene) elseif index == Transition_Table.CCTransitionProgressRadialCW then - scene = cc.TransitionProgressRadialCW:create(t, scene) + scene = ax.TransitionProgressRadialCW:create(t, scene) elseif index == Transition_Table.CCTransitionProgressHorizontal then - scene = cc.TransitionProgressHorizontal:create(t, scene) + scene = ax.TransitionProgressHorizontal:create(t, scene) elseif index == Transition_Table.CCTransitionProgressVertical then - scene = cc.TransitionProgressVertical:create(t, scene) + scene = ax.TransitionProgressVertical:create(t, scene) elseif index == Transition_Table.CCTransitionProgressInOut then - scene = cc.TransitionProgressInOut:create(t, scene) + scene = ax.TransitionProgressInOut:create(t, scene) elseif index == Transition_Table.CCTransitionProgressOutIn then - scene = cc.TransitionProgressOutIn:create(t, scene) + scene = ax.TransitionProgressOutIn:create(t, scene) elseif index == Transition_Table.CCTransitionCrossFade then - scene = cc.TransitionCrossFade:create(t, scene) + scene = ax.TransitionCrossFade:create(t, scene) elseif index == Transition_Table.TransitionPageForward then - cc.Director:getInstance():getRenderer():setDepthTest(true) - scene = cc.TransitionPageTurn:create(t, scene, false) + ax.Director:getInstance():getRenderer():setDepthTest(true) + scene = ax.TransitionPageTurn:create(t, scene, false) elseif index == Transition_Table.TransitionPageBackward then - cc.Director:getInstance():getRenderer():setDepthTest(true) - scene = cc.TransitionPageTurn:create(t, scene, true) + ax.Director:getInstance():getRenderer():setDepthTest(true) + scene = ax.TransitionPageTurn:create(t, scene, true) elseif index == Transition_Table.CCTransitionFadeTR then - scene = cc.TransitionFadeTR:create(t, scene) + scene = ax.TransitionFadeTR:create(t, scene) elseif index == Transition_Table.CCTransitionFadeBL then - scene = cc.TransitionFadeBL:create(t, scene) + scene = ax.TransitionFadeBL:create(t, scene) elseif index == Transition_Table.CCTransitionFadeUp then - scene = cc.TransitionFadeUp:create(t, scene) + scene = ax.TransitionFadeUp:create(t, scene) elseif index == Transition_Table.CCTransitionFadeDown then - scene = cc.TransitionFadeDown:create(t, scene) + scene = ax.TransitionFadeDown:create(t, scene) elseif index == Transition_Table.CCTransitionTurnOffTiles then - scene = cc.TransitionTurnOffTiles:create(t, scene) + scene = ax.TransitionTurnOffTiles:create(t, scene) elseif index == Transition_Table.CCTransitionSplitRows then - scene = cc.TransitionSplitRows:create(t, scene) + scene = ax.TransitionSplitRows:create(t, scene) elseif index == Transition_Table.CCTransitionSplitCols then - scene = cc.TransitionSplitCols:create(t, scene) + scene = ax.TransitionSplitCols:create(t, scene) elseif index == Transition_Table.CCTransitionFade then - scene = cc.TransitionFade:create(t, scene) + scene = ax.TransitionFade:create(t, scene) elseif index == Transition_Table.FadeWhiteTransition then - scene = cc.TransitionFade:create(t, scene, cc.c3b(255, 255, 255)) + scene = ax.TransitionFade:create(t, scene, ax.color32(255, 255, 255)) elseif index == Transition_Table.FlipXLeftOver then - scene = cc.TransitionFlipX:create(t, scene, cc.TRANSITION_ORIENTATION_LEFT_OVER ) + scene = ax.TransitionFlipX:create(t, scene, ax.TRANSITION_ORIENTATION_LEFT_OVER ) elseif index == Transition_Table.FlipXRightOver then - scene = cc.TransitionFlipX:create(t, scene, cc.TRANSITION_ORIENTATION_RIGHT_OVER ) + scene = ax.TransitionFlipX:create(t, scene, ax.TRANSITION_ORIENTATION_RIGHT_OVER ) elseif index == Transition_Table.FlipYUpOver then - scene = cc.TransitionFlipY:create(t, scene, cc.TRANSITION_ORIENTATION_UP_OVER) + scene = ax.TransitionFlipY:create(t, scene, ax.TRANSITION_ORIENTATION_UP_OVER) elseif index == Transition_Table.FlipYDownOver then - scene = cc.TransitionFlipY:create(t, scene, cc.TRANSITION_ORIENTATION_DOWN_OVER ) + scene = ax.TransitionFlipY:create(t, scene, ax.TRANSITION_ORIENTATION_DOWN_OVER ) elseif index == Transition_Table.FlipAngularLeftOver then - scene = cc.TransitionFlipAngular:create(t, scene, cc.TRANSITION_ORIENTATION_LEFT_OVER ) + scene = ax.TransitionFlipAngular:create(t, scene, ax.TRANSITION_ORIENTATION_LEFT_OVER ) elseif index == Transition_Table.FlipAngularRightOver then - scene = cc.TransitionFlipAngular:create(t, scene, cc.TRANSITION_ORIENTATION_RIGHT_OVER ) + scene = ax.TransitionFlipAngular:create(t, scene, ax.TRANSITION_ORIENTATION_RIGHT_OVER ) elseif index == Transition_Table.ZoomFlipXLeftOver then - scene = cc.TransitionZoomFlipX:create(t, scene, cc.TRANSITION_ORIENTATION_LEFT_OVER ) + scene = ax.TransitionZoomFlipX:create(t, scene, ax.TRANSITION_ORIENTATION_LEFT_OVER ) elseif index == Transition_Table.ZoomFlipXRightOver then - scene = cc.TransitionZoomFlipX:create(t, scene, cc.TRANSITION_ORIENTATION_RIGHT_OVER ) + scene = ax.TransitionZoomFlipX:create(t, scene, ax.TRANSITION_ORIENTATION_RIGHT_OVER ) elseif index == Transition_Table.ZoomFlipYUpOver then - scene = cc.TransitionZoomFlipY:create(t, scene, cc.TRANSITION_ORIENTATION_UP_OVER) + scene = ax.TransitionZoomFlipY:create(t, scene, ax.TRANSITION_ORIENTATION_UP_OVER) elseif index == Transition_Table.ZoomFlipYDownOver then - scene = cc.TransitionZoomFlipY:create(t, scene, cc.TRANSITION_ORIENTATION_DOWN_OVER ) + scene = ax.TransitionZoomFlipY:create(t, scene, ax.TRANSITION_ORIENTATION_DOWN_OVER ) elseif index == Transition_Table.ZoomFlipAngularLeftOver then - scene = cc.TransitionZoomFlipAngular:create(t, scene, cc.TRANSITION_ORIENTATION_LEFT_OVER ) + scene = ax.TransitionZoomFlipAngular:create(t, scene, ax.TRANSITION_ORIENTATION_LEFT_OVER ) elseif index == Transition_Table.ZoomFlipAngularRightOver then - scene = cc.TransitionZoomFlipAngular:create(t, scene, cc.TRANSITION_ORIENTATION_RIGHT_OVER ) + scene = ax.TransitionZoomFlipAngular:create(t, scene, ax.TRANSITION_ORIENTATION_RIGHT_OVER ) elseif index == Transition_Table.CCTransitionShrinkGrow then - scene = cc.TransitionShrinkGrow:create(t, scene) + scene = ax.TransitionShrinkGrow:create(t, scene) elseif index == Transition_Table.CCTransitionRotoZoom then - scene = cc.TransitionRotoZoom:create(t, scene) + scene = ax.TransitionRotoZoom:create(t, scene) elseif index == Transition_Table.CCTransitionMoveInL then - scene = cc.TransitionMoveInL:create(t, scene) + scene = ax.TransitionMoveInL:create(t, scene) elseif index == Transition_Table.CCTransitionMoveInR then - scene = cc.TransitionMoveInR:create(t, scene) + scene = ax.TransitionMoveInR:create(t, scene) elseif index == Transition_Table.CCTransitionMoveInT then - scene = cc.TransitionMoveInT:create(t, scene) + scene = ax.TransitionMoveInT:create(t, scene) elseif index == Transition_Table.CCTransitionMoveInB then - scene = cc.TransitionMoveInB:create(t, scene) + scene = ax.TransitionMoveInB:create(t, scene) elseif index == Transition_Table.CCTransitionSlideInL then - scene = cc.TransitionSlideInL:create(t, scene) + scene = ax.TransitionSlideInL:create(t, scene) elseif index == Transition_Table.CCTransitionSlideInR then - scene = cc.TransitionSlideInR:create(t, scene) + scene = ax.TransitionSlideInR:create(t, scene) elseif index == Transition_Table.CCTransitionSlideInT then - scene = cc.TransitionSlideInT:create(t, scene) + scene = ax.TransitionSlideInT:create(t, scene) elseif index == Transition_Table.CCTransitionSlideInB then - scene = cc.TransitionSlideInB:create(t, scene) + scene = ax.TransitionSlideInB:create(t, scene) end return scene end function generateTranScene() - local scene = cc.Scene:create() + local scene = ax.Scene:create() local layer = nil if CurSceneNo == 1 then @@ -259,7 +259,7 @@ end function TransitionsTest() cclog("TransitionsTest") - local scene = cc.Scene:create() + local scene = ax.Scene:create() SceneIdx = -1 CurSceneNo = 2 diff --git a/tests/lua-tests/Content/src/UserDefaultTest/UserDefaultTest.lua b/tests/lua-tests/Content/src/UserDefaultTest/UserDefaultTest.lua index 2162f9227462..935ce7c4574a 100644 --- a/tests/lua-tests/Content/src/UserDefaultTest/UserDefaultTest.lua +++ b/tests/lua-tests/Content/src/UserDefaultTest/UserDefaultTest.lua @@ -6,62 +6,62 @@ local function doTest() -- set default value - cc.UserDefault:getInstance():setStringForKey("string", "value1") - cc.UserDefault:getInstance():setIntegerForKey("integer", 10) - cc.UserDefault:getInstance():setFloatForKey("float", 2.3) - cc.UserDefault:getInstance():setDoubleForKey("double", 2.4) - cc.UserDefault:getInstance():setBoolForKey("bool", true) + ax.UserDefault:getInstance():setStringForKey("string", "value1") + ax.UserDefault:getInstance():setIntegerForKey("integer", 10) + ax.UserDefault:getInstance():setFloatForKey("float", 2.3) + ax.UserDefault:getInstance():setDoubleForKey("double", 2.4) + ax.UserDefault:getInstance():setBoolForKey("bool", true) -- print value - local ret = cc.UserDefault:getInstance():getStringForKey("string") + local ret = ax.UserDefault:getInstance():getStringForKey("string") cclog("string is %s", ret) - local d = cc.UserDefault:getInstance():getDoubleForKey("double") + local d = ax.UserDefault:getInstance():getDoubleForKey("double") cclog("double is %f", d) - local i = cc.UserDefault:getInstance():getIntegerForKey("integer") + local i = ax.UserDefault:getInstance():getIntegerForKey("integer") cclog("integer is %d", i) - local f = cc.UserDefault:getInstance():getFloatForKey("float") + local f = ax.UserDefault:getInstance():getFloatForKey("float") cclog("float is %f", f) - local b = cc.UserDefault:getInstance():getBoolForKey("bool") + local b = ax.UserDefault:getInstance():getBoolForKey("bool") if b == true then cclog("bool is true") else cclog("bool is false") end - --cc.UserDefault:getInstance():flush() + --ax.UserDefault:getInstance():flush() cclog("********************** after change value ***********************") -- change the value - cc.UserDefault:getInstance():setStringForKey("string", "value2") - cc.UserDefault:getInstance():setIntegerForKey("integer", 11) - cc.UserDefault:getInstance():setFloatForKey("float", 2.5) - cc.UserDefault:getInstance():setDoubleForKey("double", 2.6) - cc.UserDefault:getInstance():setBoolForKey("bool", false) + ax.UserDefault:getInstance():setStringForKey("string", "value2") + ax.UserDefault:getInstance():setIntegerForKey("integer", 11) + ax.UserDefault:getInstance():setFloatForKey("float", 2.5) + ax.UserDefault:getInstance():setDoubleForKey("double", 2.6) + ax.UserDefault:getInstance():setBoolForKey("bool", false) - cc.UserDefault:getInstance():flush() + ax.UserDefault:getInstance():flush() -- print value - ret = cc.UserDefault:getInstance():getStringForKey("string") + ret = ax.UserDefault:getInstance():getStringForKey("string") cclog("string is %s", ret) - d = cc.UserDefault:getInstance():getDoubleForKey("double") + d = ax.UserDefault:getInstance():getDoubleForKey("double") cclog("double is %f", d) - i = cc.UserDefault:getInstance():getIntegerForKey("integer") + i = ax.UserDefault:getInstance():getIntegerForKey("integer") cclog("integer is %d", i) - f = cc.UserDefault:getInstance():getFloatForKey("float") + f = ax.UserDefault:getInstance():getFloatForKey("float") cclog("float is %f", f) - b = cc.UserDefault:getInstance():getBoolForKey("bool") + b = ax.UserDefault:getInstance():getBoolForKey("bool") if b == true then cclog("bool is true") else @@ -70,12 +70,12 @@ local function doTest() end function UserDefaultTestMain() - local ret = cc.Scene:create() - local s = cc.Director:getInstance():getWinSize() - local label = cc.Label:createWithTTF("UserDefault test see log", s_arialPath, 28) + local ret = ax.Scene:create() + local s = ax.Director:getInstance():getWinSize() + local label = ax.Label:createWithTTF("UserDefault test see log", s_arialPath, 28) ret:addChild(label, 0) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition( cc.p(s.width/2, s.height-50) ) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition( ax.p(s.width/2, s.height-50) ) ret:addChild(CreateBackMenuItem()) doTest() return ret diff --git a/tests/lua-tests/Content/src/VibrateTest/VibrateTest.lua b/tests/lua-tests/Content/src/VibrateTest/VibrateTest.lua index 2e9dcdd9138d..2dcef4d34a1d 100644 --- a/tests/lua-tests/Content/src/VibrateTest/VibrateTest.lua +++ b/tests/lua-tests/Content/src/VibrateTest/VibrateTest.lua @@ -2,7 +2,7 @@ local VibrateControlTest = {} function VibrateControlTest.create() - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) Helper.titleLabel:setString("vibrate control test") -- Helper.subtitleLabel:setString("subtitleLabel") @@ -12,20 +12,20 @@ function VibrateControlTest.create() ------playItem local function onStartVibrate(tag, sender) - cc.Device:vibrate(VibrateControlTest._duration) + ax.Device:vibrate(VibrateControlTest._duration) end - local vibrateItem = cc.MenuItemFont:create("vibrate") - vibrateItem:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * 0.7)) + local vibrateItem = ax.MenuItemFont:create("vibrate") + vibrateItem:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * 0.7)) vibrateItem:registerScriptTapHandler(onStartVibrate) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(vibrateItem) - menu:setPosition(cc.p(0, 0)) + menu:setPosition(ax.p(0, 0)) layer:addChild(menu) - VibrateControlTest._durationLabel = cc.Label:createWithTTF("duration: "..string.format("%.3f", VibrateControlTest._duration).."s", "fonts/arial.ttf", 20) - VibrateControlTest._durationLabel:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * 0.5)) + VibrateControlTest._durationLabel = ax.Label:createWithTTF("duration: "..string.format("%.3f", VibrateControlTest._duration).."s", "fonts/arial.ttf", 20) + VibrateControlTest._durationLabel:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * 0.5)) layer:addChild(VibrateControlTest._durationLabel) local function durationSliderChangedEvent(sender,eventType) @@ -38,7 +38,7 @@ function VibrateControlTest.create() durationSlider:loadBarTexture("cocosui/sliderTrack.png") durationSlider:loadSlidBallTextures("cocosui/sliderThumb.png", "cocosui/sliderThumb.png", "") durationSlider:loadProgressBarTexture("cocosui/sliderProgress.png") - durationSlider:setPosition(cc.p(layerSize.width * 0.5,layerSize.height * 0.35)) + durationSlider:setPosition(ax.p(layerSize.width * 0.5,layerSize.height * 0.35)) durationSlider:addEventListener(durationSliderChangedEvent) layer:addChild(durationSlider) @@ -52,14 +52,14 @@ function VibrateControlTest.create() end ------------------------------------------------------------------------ function VibrateTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { VibrateControlTest.create } Helper.index = 1 - + scene:addChild(VibrateControlTest.create()) scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/VideoPlayerTest/VideoPlayerTest.lua b/tests/lua-tests/Content/src/VideoPlayerTest/VideoPlayerTest.lua index fbb8f3612578..95c59026f0fa 100644 --- a/tests/lua-tests/Content/src/VideoPlayerTest/VideoPlayerTest.lua +++ b/tests/lua-tests/Content/src/VideoPlayerTest/VideoPlayerTest.lua @@ -1,22 +1,22 @@ -local visibleRect = cc.Director:getInstance():getRenderView():getVisibleRect() -local centerPos = cc.p(visibleRect.x + visibleRect.width / 2,visibleRect.y + visibleRect.height /2) +local visibleRect = ax.Director:getInstance():getRenderView():getVisibleRect() +local centerPos = ax.p(visibleRect.x + visibleRect.width / 2,visibleRect.y + visibleRect.height /2) axui.VideoPlayer = axui.MediaPlayer local function VideoPlayerTest() - local layer = cc.Layer:create() --createTestLayer("VideoPlayerTest", "") - titleLabel = cc.Label:createWithTTF("VideoPlayerTest", s_arialPath, 28) - titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + local layer = ax.Layer:create() --createTestLayer("VideoPlayerTest", "") + titleLabel = ax.Label:createWithTTF("VideoPlayerTest", s_arialPath, 28) + titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(titleLabel, 1) - cc.MenuItemFont:setFontSize(16) + ax.MenuItemFont:setFontSize(16) widget = ccs.GUIReader:getInstance():widgetFromJsonFile("cocosui/UITest/UITest.json") layer:addChild(widget) - local videoStateLabel = cc.Label:createWithSystemFont("IDLE","Arial",16) - videoStateLabel:setAnchorPoint(cc.p(1, 0.5)) - videoStateLabel:setPosition(cc.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 200)) + local videoStateLabel = ax.Label:createWithSystemFont("IDLE","Arial",16) + videoStateLabel:setAnchorPoint(ax.p(1, 0.5)) + videoStateLabel:setPosition(ax.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 200)) layer:addChild(videoStateLabel) local function onVideoEventCallback(sener, eventType) @@ -33,23 +33,23 @@ local function VideoPlayerTest() local widgetSize = widget:getContentSize() local videoPlayer = ccui.VideoPlayer:create() videoPlayer:setPosition(centerPos) - videoPlayer:setAnchorPoint(cc.p(0.5, 0.5)) - videoPlayer:setContentSize(cc.size(widgetSize.width * 0.4,widgetSize.height * 0.4)) + videoPlayer:setAnchorPoint(ax.p(0.5, 0.5)) + videoPlayer:setContentSize(ax.size(widgetSize.width * 0.4,widgetSize.height * 0.4)) videoPlayer:addEventListener(onVideoEventCallback) layer:addChild(videoPlayer) - local screenSize = cc.Director:getInstance():getWinSize() + local screenSize = ax.Director:getInstance():getWinSize() local rootSize = widget:getContentSize() - layer:setPosition(cc.p((screenSize.width - rootSize.width) / 2,(screenSize.height - rootSize.height) / 2)) + layer:setPosition(ax.p((screenSize.width - rootSize.width) / 2,(screenSize.height - rootSize.height) / 2)) local function menuFullScreenCallback(tag, sender) if nil ~= videoPlayer then videoPlayer:setFullScreenEnabled(not videoPlayer:isFullScreenEnabled()) end end - local fullSwitch = cc.MenuItemFont:create("FullScreenSwitch") - fullSwitch:setAnchorPoint(cc.p(0.0, 0.0)) - fullSwitch:setPosition(cc.p(visibleRect.x + 10,visibleRect.y + 50)) + local fullSwitch = ax.MenuItemFont:create("FullScreenSwitch") + fullSwitch:setAnchorPoint(ax.p(0.0, 0.0)) + fullSwitch:setPosition(ax.p(visibleRect.x + 10,visibleRect.y + 50)) fullSwitch:registerScriptTapHandler(menuFullScreenCallback) local function menuPauseCallback(tag, sender) @@ -57,9 +57,9 @@ local function VideoPlayerTest() videoPlayer:pause() end end - local pauseItem = cc.MenuItemFont:create("Pause") - pauseItem:setAnchorPoint(cc.p(0.0, 0.0)) - pauseItem:setPosition(cc.p(visibleRect.x + 10,visibleRect.y + 100)) + local pauseItem = ax.MenuItemFont:create("Pause") + pauseItem:setAnchorPoint(ax.p(0.0, 0.0)) + pauseItem:setPosition(ax.p(visibleRect.x + 10,visibleRect.y + 100)) pauseItem:registerScriptTapHandler(menuPauseCallback) local function menuResumeCallback(tag, sender) @@ -67,9 +67,9 @@ local function VideoPlayerTest() videoPlayer:resume() end end - local resumeItem = cc.MenuItemFont:create("Resume") - resumeItem:setAnchorPoint(cc.p(0.0, 0.0)) - resumeItem:setPosition(cc.p(visibleRect.x + 10,visibleRect.y + 150)) + local resumeItem = ax.MenuItemFont:create("Resume") + resumeItem:setAnchorPoint(ax.p(0.0, 0.0)) + resumeItem:setPosition(ax.p(visibleRect.x + 10,visibleRect.y + 150)) resumeItem:registerScriptTapHandler(menuResumeCallback) local function menuStopCallback(tag, sender) @@ -77,9 +77,9 @@ local function VideoPlayerTest() videoPlayer:stop() end end - local stopItem = cc.MenuItemFont:create("Stop") - stopItem:setAnchorPoint(cc.p(0.0, 0.0)) - stopItem:setPosition(cc.p(visibleRect.x + 10,visibleRect.y + 200)) + local stopItem = ax.MenuItemFont:create("Stop") + stopItem:setAnchorPoint(ax.p(0.0, 0.0)) + stopItem:setPosition(ax.p(visibleRect.x + 10,visibleRect.y + 200)) stopItem:registerScriptTapHandler(menuStopCallback) local function menuHintCallback(tag, sender) @@ -87,25 +87,25 @@ local function VideoPlayerTest() videoPlayer:setVisible(not videoPlayer:isVisible()) end end - local hintItem = cc.MenuItemFont:create("Hint") - hintItem:setAnchorPoint(cc.p(0.0, 0.0)) - hintItem:setPosition(cc.p(visibleRect.x + 10,visibleRect.y + 250)) + local hintItem = ax.MenuItemFont:create("Hint") + hintItem:setAnchorPoint(ax.p(0.0, 0.0)) + hintItem:setPosition(ax.p(visibleRect.x + 10,visibleRect.y + 250)) hintItem:registerScriptTapHandler(menuHintCallback) ------------------------------------------------------------ local function menuResourceVideoCallback(tag, sender) if nil ~= videoPlayer then print('start play video') - local videoFullPath = cc.FileUtils:getInstance():fullPathForFilename("video/h264/1280x720.mp4") + local videoFullPath = ax.FileUtils:getInstance():fullPathForFilename("video/h264/1280x720.mp4") videoPlayer:setFileName(videoFullPath) videoPlayer:play() print('start play video succeed') end end - local resourceVideo = cc.MenuItemFont:create("Play resource video") - resourceVideo:setAnchorPoint(cc.p(1, 0.5)) - resourceVideo:setPosition(cc.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 50)) + local resourceVideo = ax.MenuItemFont:create("Play resource video") + resourceVideo:setAnchorPoint(ax.p(1, 0.5)) + resourceVideo:setPosition(ax.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 50)) resourceVideo:registerScriptTapHandler(menuResourceVideoCallback) local function menuOnlineVideoCallback(tag, sender) @@ -114,9 +114,9 @@ local function VideoPlayerTest() videoPlayer:play() end end - local onlineVideo = cc.MenuItemFont:create("Play online video") - onlineVideo:setAnchorPoint(cc.p(1, 0.5)) - onlineVideo:setPosition(cc.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 100)) + local onlineVideo = ax.MenuItemFont:create("Play online video") + onlineVideo:setAnchorPoint(ax.p(1, 0.5)) + onlineVideo:setPosition(ax.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 100)) onlineVideo:registerScriptTapHandler(menuOnlineVideoCallback) local function menuRatioCallback(tag, sender) @@ -124,13 +124,13 @@ local function VideoPlayerTest() videoPlayer:setKeepAspectRatioEnabled(not videoPlayer:isKeepAspectRatioEnabled()) end end - local ratioSwitch = cc.MenuItemFont:create("KeepRatioSwitch") - ratioSwitch:setAnchorPoint(cc.p(1, 0.5)) - ratioSwitch:setPosition(cc.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 150)) + local ratioSwitch = ax.MenuItemFont:create("KeepRatioSwitch") + ratioSwitch:setAnchorPoint(ax.p(1, 0.5)) + ratioSwitch:setPosition(ax.p(visibleRect.x + visibleRect.width - 10,visibleRect.y + 150)) ratioSwitch:registerScriptTapHandler(menuRatioCallback) - local menu = cc.Menu:create(fullSwitch, pauseItem, resumeItem, stopItem, hintItem, resourceVideo, onlineVideo, ratioSwitch) - menu:setPosition(cc.p(0.0, 0.0)) + local menu = ax.Menu:create(fullSwitch, pauseItem, resumeItem, stopItem, hintItem, resourceVideo, onlineVideo, ratioSwitch) + menu:setPosition(ax.p(0.0, 0.0)) layer:addChild(menu) return layer @@ -139,7 +139,7 @@ end function VideoPlayerTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { VideoPlayerTest } diff --git a/tests/lua-tests/Content/src/VisibleRect.lua b/tests/lua-tests/Content/src/VisibleRect.lua index d16bfdbe98c4..22d5c6370c59 100644 --- a/tests/lua-tests/Content/src/VisibleRect.lua +++ b/tests/lua-tests/Content/src/VisibleRect.lua @@ -2,15 +2,11 @@ VisibleRect = class("VisibleRect") VisibleRect.__index = VisibleRect -VisibleRect.s_visibleRect = cc.rect(0,0,0,0) +VisibleRect.s_visibleRect = ax.rect(0,0,0,0) function VisibleRect:lazyInit() if (self.s_visibleRect.width == 0.0 and self.s_visibleRect.height == 0.0) then - --[[ - local pEGLView = cc.EGLView:getInstance() - local origin = pEGLView:getVisibleOrigin() - ]]-- - local director = cc.Director:getInstance() + local director = ax.Director:getInstance() local origin = director:getVisibleOrigin() local visibleSize = director:getVisibleSize() self.s_visibleRect.x = origin.x @@ -22,50 +18,50 @@ end function VisibleRect:getVisibleRect() self:lazyInit() - return cc.rect(self.s_visibleRect.x, self.s_visibleRect.y, self.s_visibleRect.width, self.s_visibleRect.height) + return ax.rect(self.s_visibleRect.x, self.s_visibleRect.y, self.s_visibleRect.width, self.s_visibleRect.height) end function VisibleRect:left() self:lazyInit() - return cc.p(self.s_visibleRect.x, self.s_visibleRect.y+self.s_visibleRect.height/2) + return ax.p(self.s_visibleRect.x, self.s_visibleRect.y+self.s_visibleRect.height/2) end function VisibleRect:right() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y+self.s_visibleRect.height/2) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y+self.s_visibleRect.height/2) end function VisibleRect:top() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y+self.s_visibleRect.height) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y+self.s_visibleRect.height) end function VisibleRect:bottom() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y) end function VisibleRect:center() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y+self.s_visibleRect.height/2) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width/2, self.s_visibleRect.y+self.s_visibleRect.height/2) end function VisibleRect:leftTop() self:lazyInit() - return cc.p(self.s_visibleRect.x, self.s_visibleRect.y+self.s_visibleRect.height) + return ax.p(self.s_visibleRect.x, self.s_visibleRect.y+self.s_visibleRect.height) end function VisibleRect:rightTop() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y+self.s_visibleRect.height) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y+self.s_visibleRect.height) end function VisibleRect:leftBottom() self:lazyInit() - return cc.p(self.s_visibleRect.x,self.s_visibleRect.y) + return ax.p(self.s_visibleRect.x,self.s_visibleRect.y) end function VisibleRect:rightBottom() self:lazyInit() - return cc.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y) + return ax.p(self.s_visibleRect.x+self.s_visibleRect.width, self.s_visibleRect.y) end diff --git a/tests/lua-tests/Content/src/WebViewTest/WebViewTest.lua b/tests/lua-tests/Content/src/WebViewTest/WebViewTest.lua index e655cad5ffe6..86f9a1f7fe1d 100644 --- a/tests/lua-tests/Content/src/WebViewTest/WebViewTest.lua +++ b/tests/lua-tests/Content/src/WebViewTest/WebViewTest.lua @@ -3,7 +3,7 @@ ----WebViewTest ---------------------------------------- local WebViewTest = class("WebViewTest", function () - local layer = cc.Layer:create() + local layer = ax.Layer:create() return layer end) @@ -17,7 +17,7 @@ function WebViewTest:init() Helper.titleLabel:setString(self:title()) Helper.subtitleLabel:setString(self:subtitle()) - local winSize = cc.Director:getInstance():getVisibleSize() + local winSize = ax.Director:getInstance():getVisibleSize() self._webView = ccui.WebView:create() self._webView:setPosition(winSize.width / 2, winSize.height / 2) self._webView:setContentSize(winSize.width / 2, winSize.height / 2) @@ -38,13 +38,13 @@ function WebViewTest:init() self:addChild(self._webView) local urlTextField = ccui.TextField:create("Input a URL here", "Arial", 20) - urlTextField:setPlaceHolderColor(cc.c4b(255, 0, 0, 255)) + urlTextField:setPlaceHolderColor(ax.color32(255, 0, 0, 255)) urlTextField:setPosition(winSize.width/2 - 80, winSize.height/2 + self._webView:getContentSize().height/2 + urlTextField:getContentSize().height/2 + 10) self:addChild(urlTextField) - + local httpLabel = ccui.Text:create("https:// ", "Arial", 20) - httpLabel:setTextColor(cc.c4b(0, 255, 0, 255)) - httpLabel:setAnchorPoint(cc.p(1.0,0.5)) + httpLabel:setTextColor(ax.color32(0, 255, 0, 255)) + httpLabel:setAnchorPoint(ax.p(1.0,0.5)) local x,y = urlTextField:getPosition() httpLabel:setPosition( x - urlTextField:getContentSize().width / 2, y) self:addChild(httpLabel) @@ -55,7 +55,7 @@ function WebViewTest:init() resetBtn:addClickEventListener(function(sender) if urlTextField:getString() ~= nil then self._webView:loadURL("https://" .. urlTextField:getString()) - end + end end) self:addChild(resetBtn) @@ -90,7 +90,7 @@ function WebViewTest:init() self._webView:loadFile("Test.html") end) self:addChild(loadFileBtn) - + local loadHTMLBtn = ccui.Button:create("cocosui/animationbuttonnormal.png","cocosui/animationbuttonpressed.png") loadHTMLBtn:setTitleText("Load Data") loadHTMLBtn:setPosition(winSize.width / 2 - self._webView:getContentSize().width/2 - loadHTMLBtn:getContentSize().width/2 - 30, winSize.height / 2) @@ -98,7 +98,7 @@ function WebViewTest:init() self._webView:loadHTMLString("Hello World ","Images/") end) self:addChild(loadHTMLBtn) - + local evalJsBtn = ccui.Button:create("cocosui/animationbuttonnormal.png", "cocosui/animationbuttonpressed.png") evalJsBtn:setTitleText("Evaluate JS") evalJsBtn:setPosition(winSize.width / 2 - self._webView:getContentSize().width/2 - evalJsBtn:getContentSize().width/2 - 30, winSize.height / 2 - 50) @@ -123,8 +123,8 @@ function WebViewTestMain() } Helper.index = 1 - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(WebViewTest.create()) scene:addChild(CreateBackMenuItem()) return scene -end \ No newline at end of file +end diff --git a/tests/lua-tests/Content/src/XMLHttpRequestTest/XMLHttpRequestTest.lua b/tests/lua-tests/Content/src/XMLHttpRequestTest/XMLHttpRequestTest.lua index 41e6819de00f..e5ecd2f3a787 100644 --- a/tests/lua-tests/Content/src/XMLHttpRequestTest/XMLHttpRequestTest.lua +++ b/tests/lua-tests/Content/src/XMLHttpRequestTest/XMLHttpRequestTest.lua @@ -1,31 +1,31 @@ local json = cjson local function XMLHttpRequestLayer() - local layer = cc.Layer:create() - local winSize = cc.Director:getInstance():getWinSize() + local layer = ax.Layer:create() + local winSize = ax.Director:getInstance():getWinSize() local margin = 40 local space = 35 local function init() - local label = cc.Label:createWithTTF("XML Http Request Test", s_arialPath, 28) - label:setAnchorPoint(cc.p(0.5, 0.5)) - label:setPosition(cc.p(winSize.width / 2, winSize.height - margin)) + local label = ax.Label:createWithTTF("XML Http Request Test", s_arialPath, 28) + label:setAnchorPoint(ax.p(0.5, 0.5)) + label:setPosition(ax.p(winSize.width / 2, winSize.height - margin)) layer:addChild(label, 0) --Response Code Label - local labelStatusCode = cc.Label:createWithTTF("HTTP Status Code", s_markerFeltFontPath, 20) - labelStatusCode:setAnchorPoint(cc.p(0.5, 0.5)) - labelStatusCode:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 6 * space)) + local labelStatusCode = ax.Label:createWithTTF("HTTP Status Code", s_markerFeltFontPath, 20) + labelStatusCode:setAnchorPoint(ax.p(0.5, 0.5)) + labelStatusCode:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 6 * space)) layer:addChild(labelStatusCode) - local menuRequest = cc.Menu:create() - menuRequest:setPosition(cc.p(0,0)) + local menuRequest = ax.Menu:create() + menuRequest:setPosition(ax.p(0,0)) layer:addChild(menuRequest) --Get local function onMenuGetClicked() - local xhr = cc.XMLHttpRequest:new() - xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_STRING + local xhr = ax.XMLHttpRequest:new() + xhr.responseType = ax.XMLHTTPREQUEST_RESPONSE_STRING xhr:open("GET", "https://httpbin.org/get") local function onReadyStateChanged() @@ -48,17 +48,17 @@ local function XMLHttpRequestLayer() labelStatusCode:setString("waiting...") end - local labelGet = cc.Label:createWithTTF("Test Get", s_arialPath, 22) - labelGet:setAnchorPoint(cc.p(0.5, 0.5)) - local itemGet = cc.MenuItemLabel:create(labelGet) + local labelGet = ax.Label:createWithTTF("Test Get", s_arialPath, 22) + labelGet:setAnchorPoint(ax.p(0.5, 0.5)) + local itemGet = ax.MenuItemLabel:create(labelGet) itemGet:registerScriptTapHandler(onMenuGetClicked) - itemGet:setPosition(cc.p(winSize.width / 2, winSize.height - margin - space)) + itemGet:setPosition(ax.p(winSize.width / 2, winSize.height - margin - space)) menuRequest:addChild(itemGet) --Post local function onMenuPostClicked() - local xhr = cc.XMLHttpRequest:new() - xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_STRING + local xhr = ax.XMLHttpRequest:new() + xhr.responseType = ax.XMLHTTPREQUEST_RESPONSE_STRING xhr:open("POST", "https://httpbin.org/post") local function onReadyStateChanged() if xhr.readyState == 4 and (xhr.status >= 200 and xhr.status < 207) then @@ -79,17 +79,17 @@ local function XMLHttpRequestLayer() labelStatusCode:setString("waiting...") end - local labelPost = cc.Label:createWithTTF("Test Post", s_arialPath, 22) - labelPost:setAnchorPoint(cc.p(0.5, 0.5)) - local itemPost = cc.MenuItemLabel:create(labelPost) + local labelPost = ax.Label:createWithTTF("Test Post", s_arialPath, 22) + labelPost:setAnchorPoint(ax.p(0.5, 0.5)) + local itemPost = ax.MenuItemLabel:create(labelPost) itemPost:registerScriptTapHandler(onMenuPostClicked) - itemPost:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 2 * space)) + itemPost:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 2 * space)) menuRequest:addChild(itemPost) --Post Binary local function onMenuPostBinaryClicked() - local xhr = cc.XMLHttpRequest:new() - xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_ARRAY_BUFFER + local xhr = ax.XMLHttpRequest:new() + xhr.responseType = ax.XMLHTTPREQUEST_RESPONSE_ARRAY_BUFFER xhr:open("POST", "https://httpbin.org/post") local function onReadyStateChanged() @@ -125,18 +125,18 @@ local function XMLHttpRequestLayer() labelStatusCode:setString("waiting...") end - local labelPostBinary = cc.Label:createWithTTF("Test Post Binary", s_arialPath, 22) - labelPostBinary:setAnchorPoint(cc.p(0.5, 0.5)) - local itemPostBinary = cc.MenuItemLabel:create(labelPostBinary) + local labelPostBinary = ax.Label:createWithTTF("Test Post Binary", s_arialPath, 22) + labelPostBinary:setAnchorPoint(ax.p(0.5, 0.5)) + local itemPostBinary = ax.MenuItemLabel:create(labelPostBinary) itemPostBinary:registerScriptTapHandler(onMenuPostBinaryClicked) - itemPostBinary:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 3 * space)) + itemPostBinary:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 3 * space)) menuRequest:addChild(itemPostBinary) --Post Json local function onMenuPostJsonClicked() - local xhr = cc.XMLHttpRequest:new() - xhr.responseType = cc.XMLHTTPREQUEST_RESPONSE_JSON + local xhr = ax.XMLHttpRequest:new() + xhr.responseType = ax.XMLHTTPREQUEST_RESPONSE_JSON xhr:open("POST", "https://httpbin.org/post") local function onReadyStateChanged() @@ -163,11 +163,11 @@ local function XMLHttpRequestLayer() labelStatusCode:setString("waiting...") end - local labelPostJson = cc.Label:createWithTTF("Test Post Json", s_arialPath, 22) - labelPostJson:setAnchorPoint(cc.p(0.5, 0.5)) - local itemPostJson = cc.MenuItemLabel:create(labelPostJson) + local labelPostJson = ax.Label:createWithTTF("Test Post Json", s_arialPath, 22) + labelPostJson:setAnchorPoint(ax.p(0.5, 0.5)) + local itemPostJson = ax.MenuItemLabel:create(labelPostJson) itemPostJson:registerScriptTapHandler(onMenuPostJsonClicked) - itemPostJson:setPosition(cc.p(winSize.width / 2, winSize.height - margin - 4 * space)) + itemPostJson:setPosition(ax.p(winSize.width / 2, winSize.height - margin - 4 * space)) menuRequest:addChild(itemPostJson) end @@ -183,7 +183,7 @@ local function XMLHttpRequestLayer() end function XMLHttpRequestTestMain() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(XMLHttpRequestLayer()) scene:addChild(CreateBackMenuItem()) return scene diff --git a/tests/lua-tests/Content/src/ZwoptexTest/ZwoptexTest.lua b/tests/lua-tests/Content/src/ZwoptexTest/ZwoptexTest.lua index a19ea0fa3566..9573538ed72a 100644 --- a/tests/lua-tests/Content/src/ZwoptexTest/ZwoptexTest.lua +++ b/tests/lua-tests/Content/src/ZwoptexTest/ZwoptexTest.lua @@ -1,4 +1,4 @@ -local scheduler = cc.Director:getInstance():getScheduler() +local scheduler = ax.Director:getInstance():getScheduler() -------------------------------------------------------------------- -- -- ZwoptexGenericTest @@ -9,33 +9,33 @@ local function ZwoptexGenericTest() "Coordinate Formats, Rotation, Trimming, flipX/Y") local spriteFrameIndex = 0 local counter = 0 - local s = cc.Director:getInstance():getWinSize() + local s = ax.Director:getInstance():getWinSize() local schedulerEntry = nil local schedulerFlipSpriteEntry = nil local sprite1 = nil local sprite2 = nil local function onEnter() - cc.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini.plist") - cc.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini-generic.plist") + ax.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini.plist") + ax.SpriteFrameCache:getInstance():addSpriteFrames("zwoptex/grossini-generic.plist") - local layer1 = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 85, 121) - layer1:setPosition(cc.p(s.width/2-80 - (85.0 * 0.5), s.height/2 - (121.0 * 0.5))) + local layer1 = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 85, 121) + layer1:setPosition(ax.p(s.width/2-80 - (85.0 * 0.5), s.height/2 - (121.0 * 0.5))) ret:addChild(layer1) - sprite1 = cc.Sprite:createWithSpriteFrame(cc.SpriteFrameCache:getInstance():getSpriteFrame("grossini_dance_01.png")) - sprite1:setPosition(cc.p( s.width/2-80, s.height/2)) + sprite1 = ax.Sprite:createWithSpriteFrame(ax.SpriteFrameCache:getInstance():getSpriteFrame("grossini_dance_01.png")) + sprite1:setPosition(ax.p( s.width/2-80, s.height/2)) ret:addChild(sprite1) sprite1:setFlippedX(false) sprite1:setFlippedY(false) - local layer2 = cc.LayerColor:create(cc.c4b(255, 0, 0, 255), 85, 121) - layer2:setPosition(cc.p(s.width/2+80 - (85.0 * 0.5), s.height/2 - (121.0 * 0.5))) + local layer2 = ax.LayerColor:create(ax.color32(255, 0, 0, 255), 85, 121) + layer2:setPosition(ax.p(s.width/2+80 - (85.0 * 0.5), s.height/2 - (121.0 * 0.5))) ret:addChild(layer2) - sprite2 = cc.Sprite:createWithSpriteFrame(cc.SpriteFrameCache:getInstance():getSpriteFrame("grossini_dance_generic_01.png")) - sprite2:setPosition(cc.p( s.width/2 + 80, s.height/2)) + sprite2 = ax.Sprite:createWithSpriteFrame(ax.SpriteFrameCache:getInstance():getSpriteFrame("grossini_dance_generic_01.png")) + sprite2:setPosition(ax.p( s.width/2 + 80, s.height/2)) ret:addChild(sprite2) sprite2:setFlippedX(false) @@ -74,8 +74,8 @@ local function ZwoptexGenericTest() local str1 = string.format("grossini_dance_%02d.png", spriteFrameIndex) local str2 = string.format("grossini_dance_generic_%02d.png", spriteFrameIndex) - sprite1:setSpriteFrame(cc.SpriteFrameCache:getInstance():getSpriteFrame(str1)) - sprite2:setSpriteFrame(cc.SpriteFrameCache:getInstance():getSpriteFrame(str2)) + sprite1:setSpriteFrame(ax.SpriteFrameCache:getInstance():getSpriteFrame(str1)) + sprite2:setSpriteFrame(ax.SpriteFrameCache:getInstance():getSpriteFrame(str2)) end sprite1:retain() @@ -97,7 +97,7 @@ local function ZwoptexGenericTest() end sprite1:release() sprite2:release() - local cache = cc.SpriteFrameCache:getInstance() + local cache = ax.SpriteFrameCache:getInstance() cache:removeSpriteFramesFromFile("zwoptex/grossini.plist") cache:removeSpriteFramesFromFile("zwoptex/grossini-generic.plist") end @@ -117,7 +117,7 @@ end function ZwoptexTestMain() cclog("ZwoptexTestMain") - local scene = cc.Scene:create() + local scene = ax.Scene:create() Helper.createFunctionTable = { ZwoptexGenericTest } diff --git a/tests/lua-tests/Content/src/controller.lua b/tests/lua-tests/Content/src/controller.lua index fb940aca1c04..97c647e4d97c 100644 --- a/tests/lua-tests/Content/src/controller.lua +++ b/tests/lua-tests/Content/src/controller.lua @@ -12,10 +12,10 @@ end AX_USE_DEPRECATED_API = true require "axmol.init" -local director = cc.Director:getInstance() +local director = ax.Director:getInstance() local renderView = director:getRenderView() if nil == renderView then - renderView = ax.RenderViewImpl:createWithRect("Lua Tests", cc.rect(0,0,960,640), 1.0, true) + renderView = ax.RenderViewImpl:createWithRect("Lua Tests", ax.rect(0,0,960,640), 1.0, true) director:setRenderView(renderView) end @@ -31,12 +31,12 @@ local designSize = {width = 480, height = 320} if screenSize.height > 320 then local resourceSize = {width = 960, height = 640} - cc.Director:getInstance():setContentScaleFactor(resourceSize.height/designSize.height) + ax.Director:getInstance():setContentScaleFactor(resourceSize.height/designSize.height) end -renderView:setDesignResolutionSize(designSize.width, designSize.height, cc.ResolutionPolicy.SHOW_ALL) +renderView:setDesignResolutionSize(designSize.width, designSize.height, ax.ResolutionPolicy.SHOW_ALL) -local fileUtils = cc.FileUtils:getInstance() +local fileUtils = ax.FileUtils:getInstance() local function addSearchPath(resPrefix, height) local searchPaths = fileUtils:getSearchPaths() table.insert(searchPaths, 1, resPrefix) @@ -57,10 +57,10 @@ addSearchPath("", screenSize.height) require "mainMenu" -local scene = cc.Scene:create() +local scene = ax.Scene:create() scene:addChild(CreateTestMenu()) -if cc.Director:getInstance():getRunningScene() then - cc.Director:getInstance():replaceScene(scene) +if ax.Director:getInstance():getRunningScene() then + ax.Director:getInstance():replaceScene(scene) else - cc.Director:getInstance():runWithScene(scene) + ax.Director:getInstance():runWithScene(scene) end diff --git a/tests/lua-tests/Content/src/helper.lua b/tests/lua-tests/Content/src/helper.lua index e7dcb4bb2d2d..41d17a05c52a 100644 --- a/tests/lua-tests/Content/src/helper.lua +++ b/tests/lua-tests/Content/src/helper.lua @@ -1,15 +1,15 @@ AX_CONTENT_SCALE_FACTOR = function() - return cc.Director:getInstance():getContentScaleFactor() + return ax.Director:getInstance():getContentScaleFactor() end AX_POINT_PIXELS_TO_POINTS = function(pixels) - return cc.p(pixels.x/AX_CONTENT_SCALE_FACTOR(), pixels.y/AX_CONTENT_SCALE_FACTOR()) + return ax.p(pixels.x/AX_CONTENT_SCALE_FACTOR(), pixels.y/AX_CONTENT_SCALE_FACTOR()) end AX_POINT_POINTS_TO_PIXELS = function(points) - return cc.p(points.x*AX_CONTENT_SCALE_FACTOR(), points.y*AX_CONTENT_SCALE_FACTOR()) + return ax.p(points.x*AX_CONTENT_SCALE_FACTOR(), points.y*AX_CONTENT_SCALE_FACTOR()) end @@ -62,72 +62,72 @@ end function Helper.newScene() local scene if Helper.usePhysics then - scene = cc.Scene:createWithPhysics() + scene = ax.Scene:createWithPhysics() else - scene = cc.Scene:create() + scene = ax.Scene:create() end Helper.currentLayer = Helper.createFunctionTable[Helper.index]() scene:addChild(Helper.currentLayer) scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end function Helper.initWithLayer(layer) Helper.currentLayer = layer - local size = cc.Director:getInstance():getRenderView():getVisibleRect() - Helper.titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) - Helper.titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + local size = ax.Director:getInstance():getRenderView():getVisibleRect() + Helper.titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) + Helper.titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(Helper.titleLabel, 1) Helper.titleLabel:setPosition(size.width / 2, size.height - 50) - Helper.subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16) - Helper.subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + Helper.subtitleLabel = ax.Label:createWithTTF("", s_thonburiPath, 16) + Helper.subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) layer:addChild(Helper.subtitleLabel, 1) Helper.subtitleLabel:setPosition(size.width / 2, size.height - 80) -- menu - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) item1:registerScriptTapHandler(Helper.backAction) item2:registerScriptTapHandler(Helper.restartAction) item3:registerScriptTapHandler(Helper.nextAction) Helper.restartTestItem = item2 - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(size.width / 2 - item2:getContentSize().width * 2, size.y + item2:getContentSize().height / 2)) - item2:setPosition(cc.p(size.width / 2, size.y + item2:getContentSize().height / 2)) - item3:setPosition(cc.p(size.width / 2 + item2:getContentSize().width * 2, size.y + item2:getContentSize().height / 2)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(size.width / 2 - item2:getContentSize().width * 2, size.y + item2:getContentSize().height / 2)) + item2:setPosition(ax.p(size.width / 2, size.y + item2:getContentSize().height / 2)) + item3:setPosition(ax.p(size.width / 2 + item2:getContentSize().width * 2, size.y + item2:getContentSize().height / 2)) layer:addChild(menu, 1) - local background = cc.Layer:create() + local background = ax.Layer:create() layer:addChild(background, -10) end -- back menu callback local function MainMenuCallback() - local scene = cc.Scene:create() + local scene = ax.Scene:create() scene:addChild(CreateTestMenu()) Helper.usePhysics = false - cc.Director:getInstance():getRenderer():setDepthTest(false) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():getRenderer():setDepthTest(false) + ax.Director:getInstance():replaceScene(scene) end -- add the menu item for back to main menu function CreateBackMenuItem() - local label = cc.Label:createWithTTF("MainMenu", s_arialPath, 20) - label:setAnchorPoint(cc.p(0.5, 0.5)) - local MenuItem = cc.MenuItemLabel:create(label) + local label = ax.Label:createWithTTF("MainMenu", s_arialPath, 20) + label:setAnchorPoint(ax.p(0.5, 0.5)) + local MenuItem = ax.MenuItemLabel:create(label) MenuItem:registerScriptTapHandler(MainMenuCallback) - local s = cc.Director:getInstance():getRenderView():getVisibleRect() - local Menu = cc.Menu:create() + local s = ax.Director:getInstance():getRenderView():getVisibleRect() + local Menu = ax.Menu:create() Menu:addChild(MenuItem) Menu:setPosition(0, 0) MenuItem:setPosition(s.width - 50, s.y + 25) @@ -136,7 +136,7 @@ function CreateBackMenuItem() end function createTestLayer(title, subtitle) - local layer = cc.Layer:create() + local layer = ax.Layer:create() Helper.initWithLayer(layer) local titleStr = title == nil and "No title" or title local subTitleStr = subtitle == nil and "" or subtitle @@ -177,41 +177,41 @@ end function TestCastScene.newScene() local scene = TestCastScene.createFunctionTable[TestCastScene.index]() scene:addChild(CreateBackMenuItem()) - cc.Director:getInstance():replaceScene(scene) + ax.Director:getInstance():replaceScene(scene) end function TestCastScene.initWithLayer(scene) - local size = cc.Director:getInstance():getVisibleSize() - local origin = cc.Director:getInstance():getVisibleOrigin() + local size = ax.Director:getInstance():getVisibleSize() + local origin = ax.Director:getInstance():getVisibleOrigin() - TestCastScene.titleLabel = cc.Label:createWithTTF("", s_arialPath, 28) - TestCastScene.titleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + TestCastScene.titleLabel = ax.Label:createWithTTF("", s_arialPath, 28) + TestCastScene.titleLabel:setAnchorPoint(ax.p(0.5, 0.5)) scene:addChild(TestCastScene.titleLabel, 1) TestCastScene.titleLabel:setPosition(origin.x + size.width / 2, origin.y + size.height - 50) - TestCastScene.subtitleLabel = cc.Label:createWithTTF("", s_thonburiPath, 16) - TestCastScene.subtitleLabel:setAnchorPoint(cc.p(0.5, 0.5)) + TestCastScene.subtitleLabel = ax.Label:createWithTTF("", s_thonburiPath, 16) + TestCastScene.subtitleLabel:setAnchorPoint(ax.p(0.5, 0.5)) scene:addChild(TestCastScene.subtitleLabel, 1) TestCastScene.subtitleLabel:setPosition(origin.x + size.width / 2, origin.y + size.height - 80) -- menu - local item1 = cc.MenuItemImage:create(s_pPathB1, s_pPathB2) - local item2 = cc.MenuItemImage:create(s_pPathR1, s_pPathR2) - local item3 = cc.MenuItemImage:create(s_pPathF1, s_pPathF2) + local item1 = ax.MenuItemImage:create(s_pPathB1, s_pPathB2) + local item2 = ax.MenuItemImage:create(s_pPathR1, s_pPathR2) + local item3 = ax.MenuItemImage:create(s_pPathF1, s_pPathF2) item1:registerScriptTapHandler(TestCastScene.backAction) item2:registerScriptTapHandler(TestCastScene.restartAction) item3:registerScriptTapHandler(TestCastScene.nextAction) - local menu = cc.Menu:create() + local menu = ax.Menu:create() menu:addChild(item1) menu:addChild(item2) menu:addChild(item3) - menu:setPosition(cc.p(0, 0)) - item1:setPosition(cc.p(origin.x + size.width / 2 - item2:getContentSize().width * 2, origin.y + size.height + item2:getContentSize().height / 2)) - item2:setPosition(cc.p(origin.x + size.width / 2, origin.y + size.height + item2:getContentSize().height / 2)) - item3:setPosition(cc.p(origin.x + size.width / 2 + item2:getContentSize().width * 2, origin.y + size.height + item2:getContentSize().height / 2)) + menu:setPosition(ax.p(0, 0)) + item1:setPosition(ax.p(origin.x + size.width / 2 - item2:getContentSize().width * 2, origin.y + size.height + item2:getContentSize().height / 2)) + item2:setPosition(ax.p(origin.x + size.width / 2, origin.y + size.height + item2:getContentSize().height / 2)) + item3:setPosition(ax.p(origin.x + size.width / 2 + item2:getContentSize().width * 2, origin.y + size.height + item2:getContentSize().height / 2)) scene:addChild(menu, 1) - local background = cc.Layer:create() + local background = ax.Layer:create() scene:addChild(background, -10) end diff --git a/tests/lua-tests/Content/src/mainMenu.lua b/tests/lua-tests/Content/src/mainMenu.lua index b4d2de545d4b..f4b5fc27c4fa 100644 --- a/tests/lua-tests/Content/src/mainMenu.lua +++ b/tests/lua-tests/Content/src/mainMenu.lua @@ -70,18 +70,18 @@ local CurPos = {x = 0, y = 0} local BeginPos = {x = 0, y = 0} local audioEndineSupported = false -local currPlatform = cc.Application:getInstance():getTargetPlatform() -if (cc.PLATFORM_OS_WINDOWS == currPlatform or cc.PLATFORM_OS_MAC == currPlatform or cc.PLATFORM_OS_IPHONE == currPlatform or cc.PLATFORM_OS_IPAD == currPlatform or cc.PLATFORM_OS_ANDROID == currPlatform) then +local currPlatform = ax.Application:getInstance():getTargetPlatform() +if (ax.PLATFORM_OS_WINDOWS == currPlatform or ax.PLATFORM_OS_MAC == currPlatform or ax.PLATFORM_OS_IPHONE == currPlatform or ax.PLATFORM_OS_IPAD == currPlatform or ax.PLATFORM_OS_ANDROID == currPlatform) then audioEndineSupported = true end local assetManagerSupported = true; -if (currPlatform == cc.PLATFORM_OS_TIZEN) then +if (currPlatform == ax.PLATFORM_OS_TIZEN) then assetManagerSupported = false; end local luaByteCodeSupported = true; -if (currPlatform == cc.PLATFORM_OS_TIZEN) then +if (currPlatform == ax.PLATFORM_OS_TIZEN) then luaByteCodeSupported = false; end @@ -114,21 +114,21 @@ local _allTests = { { isSupported = true, name = "FileUtilsTest" , create_func = FileUtilsTestMain}, { isSupported = true, name = "FontTest" , create_func = FontTestMain }, { isSupported = true, name = "IntervalTest" , create_func = IntervalTestMain }, - { isSupported = true, name = "KeypadTest" , create_func= KeypadTestMain }, + { isSupported = true, name = "KeypadTest" , create_func= KeypadTestMain }, { isSupported = true, name = "LabelTestNew" , create_func = LabelTestNew }, { isSupported = true, name = "LayerTest" , create_func = LayerTestMain }, { isSupported = true, name = "LightTest" , create_func = LightTestMain }, { isSupported = true, name = "LuaBridgeTest" , create_func = LuaBridgeMainTest }, { isSupported = true, name = "LuaLoaderTest" , create_func = LuaLoaderMain }, { isSupported = true, name = "MaterialSystemTest" , create_func = MaterialSystemTest }, - { isSupported = true, name = "MenuTest" , create_func = MenuTestMain }, + { isSupported = true, name = "MenuTest" , create_func = MenuTestMain }, { isSupported = true, name = "MotionStreakTest" , create_func = MotionStreakTest }, { isSupported = false, name = "MultiTouchTest" , create_func = MultiTouchTestMain }, { isSupported = true, name = "NavMeshTest" , create_func = NavMeshTest }, { isSupported = true, name = "NewEventDispatcherTest" , create_func = NewEventDispatcherTest }, { isSupported = true, name = "NodeTest" , create_func = CocosNodeTest }, { isSupported = true, name = "ParallaxTest" , create_func = ParallaxTestMain }, - { isSupported = true, name = "ParticleTest" , create_func = ParticleTest }, + { isSupported = true, name = "ParticleTest" , create_func = ParticleTest }, { isSupported = true, name = "Particle3D (PU)" , create_func = Particle3DTest }, { isSupported = true, name = "PhysicsTest" , create_func = PhysicsTest }, { isSupported = true, name = "Physics3DTest" , create_func = Physics3DTest }, @@ -146,9 +146,9 @@ local _allTests = { { isSupported = true, name = "TextInputTest" , create_func= TextInputTestMain }, { isSupported = true, name = "Texture2DTest" , create_func = Texture2dTestMain }, { isSupported = false, name = "TextureCacheTest" , create_func= TextureCacheTestMain }, - { isSupported = true, name = "TileMapTest" , create_func = TileMapTestMain }, + { isSupported = true, name = "TileMapTest" , create_func = TileMapTestMain }, { isSupported = true, name = "TouchesTest" , create_func = TouchesTest }, - { isSupported = true, name = "TransitionsTest" , create_func = TransitionsTest }, + { isSupported = true, name = "TransitionsTest" , create_func = TransitionsTest }, { isSupported = true, name = "UserDefaultTest" , create_func= UserDefaultTestMain }, { isSupported = true, name = "VideoPlayerTest" , create_func= VideoPlayerTestMain }, { isSupported = true, name = "WebViewTest" , create_func= WebViewTestMain }, @@ -161,16 +161,16 @@ local TESTS_COUNT = #(_allTests) -- create scene local function CreateTestScene(nIdx) - cc.Director:getInstance():purgeCachedData() + ax.Director:getInstance():purgeCachedData() local scene = _allTests[nIdx].create_func() return scene end -- create menu function CreateTestMenu() - local menuLayer = cc.Layer:create() + local menuLayer = ax.Layer:create() local function closeCallback() - cc.Director:getInstance():endToLua() + ax.Director:getInstance():endToLua() end local function menuCallback(tag) @@ -178,58 +178,58 @@ function CreateTestMenu() local Idx = tag - 10000 local testScene = CreateTestScene(Idx) if testScene then - cc.Director:getInstance():replaceScene(testScene) + ax.Director:getInstance():replaceScene(testScene) end end -- add close menu - local s = cc.Director:getInstance():getWinSize() - local CloseItem = cc.MenuItemImage:create(s_pPathClose, s_pPathClose) + local s = ax.Director:getInstance():getWinSize() + local CloseItem = ax.MenuItemImage:create(s_pPathClose, s_pPathClose) CloseItem:registerScriptTapHandler(closeCallback) CloseItem:setAnchorPoint(1, 1) CloseItem:setPosition(VisibleRect:rightTop()) - local CloseMenu = cc.Menu:create() + local CloseMenu = ax.Menu:create() CloseMenu:setPosition(0, 0) CloseMenu:addChild(CloseItem) menuLayer:addChild(CloseMenu) - local targetPlatform = cc.Application:getInstance():getTargetPlatform() + local targetPlatform = ax.Application:getInstance():getTargetPlatform() -- add menu items for tests - local MainMenu = cc.Menu:create() + local MainMenu = ax.Menu:create() local index = 0 local obj = nil for index, obj in pairs(_allTests) do - local testLabel = cc.Label:createWithTTF(obj.name, s_arialPath, 24) - testLabel:setAnchorPoint(cc.p(0.5, 0.5)) - local testMenuItem = cc.MenuItemLabel:create(testLabel) + local testLabel = ax.Label:createWithTTF(obj.name, s_arialPath, 24) + testLabel:setAnchorPoint(ax.p(0.5, 0.5)) + local testMenuItem = ax.MenuItemLabel:create(testLabel) if not obj.isSupported then testMenuItem:setEnabled(false) end - if obj.name == "WebViewTest" + if obj.name == "WebViewTest" or obj.name == "VibrateTest" or obj.name == "VideoPlayerTest" then - if cc.PLATFORM_OS_LINUX == targetPlatform then + if ax.PLATFORM_OS_LINUX == targetPlatform then testMenuItem:setEnabled(false) end end - if obj.name == "Physics3DTest" and nil == cc.Physics3DComponent then - testMenuItem:setEnabled(false) + if obj.name == "Physics3DTest" and nil == ax.Physics3DComponent then + testMenuItem:setEnabled(false) end - if obj.name == "NavMeshTest" and nil == cc.NavMesh then - testMenuItem:setEnabled(false) + if obj.name == "NavMeshTest" and nil == ax.NavMesh then + testMenuItem:setEnabled(false) end testMenuItem:registerScriptTapHandler(menuCallback) - testMenuItem:setPosition(cc.p(s.width / 2, (s.height - (index) * LINE_SPACE))) + testMenuItem:setPosition(ax.p(s.width / 2, (s.height - (index) * LINE_SPACE))) MainMenu:addChild(testMenuItem, index + 10000, index + 10000) end - MainMenu:setContentSize(cc.size(s.width, (TESTS_COUNT + 1) * (LINE_SPACE))) + MainMenu:setContentSize(ax.size(s.width, (TESTS_COUNT + 1) * (LINE_SPACE))) MainMenu:setPosition(CurPos.x, CurPos.y) menuLayer:addChild(MainMenu) @@ -245,7 +245,7 @@ function CreateTestMenu() local nMoveY = location.y - BeginPos.y local curPosx, curPosy = MainMenu:getPosition() local nextPosy = curPosy + nMoveY - local winSize = cc.Director:getInstance():getWinSize() + local winSize = ax.Director:getInstance():getWinSize() if nextPosy < 0 then MainMenu:setPosition(0, 0) return @@ -261,9 +261,9 @@ function CreateTestMenu() CurPos = {x = curPosx, y = nextPosy} end - local listener = cc.EventListenerTouchOneByOne:create() - listener:registerScriptHandler(onTouchBegan,cc.Handler.EVENT_TOUCH_BEGAN ) - listener:registerScriptHandler(onTouchMoved,cc.Handler.EVENT_TOUCH_MOVED ) + local listener = ax.EventListenerTouchOneByOne:create() + listener:registerScriptHandler(onTouchBegan,ax.Handler.EVENT_TOUCH_BEGAN ) + listener:registerScriptHandler(onTouchMoved,ax.Handler.EVENT_TOUCH_MOVED ) local eventDispatcher = menuLayer:getEventDispatcher() eventDispatcher:addEventListenerWithSceneGraphPriority(listener, menuLayer) diff --git a/tests/lua-tests/Source/AppDelegate.cpp b/tests/lua-tests/Source/AppDelegate.cpp index 2fed6ac695f9..f0bc546018c6 100644 --- a/tests/lua-tests/Source/AppDelegate.cpp +++ b/tests/lua-tests/Source/AppDelegate.cpp @@ -23,7 +23,7 @@ THE SOFTWARE. ****************************************************************************/ -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "AppDelegate.h" #include "lua-bindings/manual/LuaEngine.h" #include "lua_assetsmanager_test_sample.h" diff --git a/tests/lua-tests/Source/AppDelegate.h b/tests/lua-tests/Source/AppDelegate.h index 51d4cd4567cf..6b1a88a34131 100644 --- a/tests/lua-tests/Source/AppDelegate.h +++ b/tests/lua-tests/Source/AppDelegate.h @@ -25,7 +25,7 @@ #ifndef __APP_DELEGATE_H__ #define __APP_DELEGATE_H__ -#include "cocos2d.h" +#include "axmol/cocos2d.h" /** @brief The cocos2d Application. diff --git a/tests/lua-tests/Source/lua_assetsmanager_test_sample.cpp b/tests/lua-tests/Source/lua_assetsmanager_test_sample.cpp index 391b6cb4f21c..686b4e891c02 100644 --- a/tests/lua-tests/Source/lua_assetsmanager_test_sample.cpp +++ b/tests/lua-tests/Source/lua_assetsmanager_test_sample.cpp @@ -26,7 +26,7 @@ #include "lua-bindings/manual/tolua_fix.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "extensions/axmol-ext.h" #if !defined(_WIN32) diff --git a/tests/lua-tests/Source/lua_test_bindings.cpp b/tests/lua-tests/Source/lua_test_bindings.cpp index 6f3d1c022ee5..b8b2ed119cd1 100644 --- a/tests/lua-tests/Source/lua_test_bindings.cpp +++ b/tests/lua-tests/Source/lua_test_bindings.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "lua_test_bindings.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "lua-bindings/manual/LuaBasicConversions.h" namespace ax @@ -41,7 +41,7 @@ class DrawNode3D : public Node /** * Draw 3D Line */ - void drawLine(const Vec3& from, const Vec3& to, const Color4F& color); + void drawLine(const Vec3& from, const Vec3& to, const Color& color); /** * Draw 3D cube @@ -56,7 +56,7 @@ class DrawNode3D : public Node * vertices[7]:Left-top-back. * @param color */ - void drawCube(Vec3* vertices, const Color4F& color); + void drawCube(Vec3* vertices, const Color& color); /** Clear the geometry in the node's buffer. */ void clear(); @@ -87,7 +87,7 @@ class DrawNode3D : public Node struct V3F_C4B { Vec3 vertices; - Color4B colors; + Color32 colors; }; void ensureCapacity(int count); @@ -95,9 +95,9 @@ class DrawNode3D : public Node BlendFunc _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; CustomCommand _customCommand; - backend::ProgramState* _programState = nullptr; + rhi::ProgramState* _programState = nullptr; bool _dirty = false; - backend::UniformLocation _locMVPMatrix; + rhi::UniformLocation _locMVPMatrix; private: AX_DISALLOW_COPY_AND_ASSIGN(DrawNode3D); @@ -145,8 +145,8 @@ bool DrawNode3D::init() { _blendFunc = BlendFunc::ALPHA_PREMULTIPLIED; - auto program = backend::Program::getBuiltinProgram(backend::ProgramType::LINE_COLOR_3D); - _programState = new backend::ProgramState(program); + auto program = axpm->getBuiltinProgram(rhi::ProgramType::LINE_COLOR_3D); + _programState = new rhi::ProgramState(program); _locMVPMatrix = _programState->getUniformLocation("u_MVPMatrix"); @@ -156,17 +156,17 @@ bool DrawNode3D::init() _customCommand.setDrawType(CustomCommand::DrawType::ARRAY); _customCommand.setPrimitiveType(CustomCommand::PrimitiveType::LINE); - const auto& attributeInfo = _programState->getProgram()->getActiveAttributes(); - auto iter = attributeInfo.find("a_position"); + const auto& inputs = _programState->getProgram()->getActiveVertexInputs(); + auto iter = inputs.find("a_position"); auto vertexLayout = _programState->getMutableVertexLayout(); - if (iter != attributeInfo.end()) + if (iter != inputs.end()) { - vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::FLOAT3, 0, false); + vertexLayout->setAttrib(iter->first, &iter->second, rhi::VertexFormat::FLOAT3, 0, false); } - iter = attributeInfo.find("a_color"); - if (iter != attributeInfo.end()) + iter = inputs.find("a_color"); + if (iter != inputs.end()) { - vertexLayout->setAttrib(iter->first, iter->second.location, backend::VertexFormat::UBYTE4, sizeof(Vec3), + vertexLayout->setAttrib(iter->first, &iter->second, rhi::VertexFormat::UBYTE4, sizeof(Vec3), true); } vertexLayout->setStride(sizeof(V3F_C4B)); @@ -174,7 +174,7 @@ bool DrawNode3D::init() _customCommand.createVertexBuffer(sizeof(V3F_C4B), INITIAL_VERTEX_BUFFER_LENGTH, CustomCommand::BufferUsage::DYNAMIC); - _customCommand.getPipelineDescriptor().programState = _programState; + _customCommand.getPipelineDesc().programState = _programState; _dirty = true; @@ -223,12 +223,12 @@ void DrawNode3D::draw(Renderer* renderer, const Mat4& transform, uint32_t flags) } } -void DrawNode3D::drawLine(const Vec3& from, const Vec3& to, const Color4F& color) +void DrawNode3D::drawLine(const Vec3& from, const Vec3& to, const Color& color) { unsigned int vertex_count = 2; ensureCapacity(vertex_count); - Color4B col = Color4B(color); + Color32 col = Color32(color); V3F_C4B a = {Vec3(from.x, from.y, from.z), col}; V3F_C4B b = { Vec3(to.x, to.y, to.z), @@ -239,7 +239,7 @@ void DrawNode3D::drawLine(const Vec3& from, const Vec3& to, const Color4F& color _dirty = true; } -void DrawNode3D::drawCube(Vec3* vertices, const Color4F& color) +void DrawNode3D::drawCube(Vec3* vertices, const Color& color) { // front face drawLine(vertices[0], vertices[1], color); @@ -275,7 +275,7 @@ void DrawNode3D::setBlendFunc(const BlendFunc& blendFunc) { _blendFunc = blendFunc; // update blend mode - auto& blend = _customCommand.getPipelineDescriptor().blendDescriptor; + auto& blend = _customCommand.getPipelineDesc().blendDesc; blend.blendEnabled = true; blend.sourceRGBBlendFactor = blend.sourceAlphaBlendFactor = _blendFunc.src; blend.destinationRGBBlendFactor = blend.destinationAlphaBlendFactor = _blendFunc.dst; @@ -459,13 +459,13 @@ int lua_cocos2dx_DrawNode3D_drawLine(lua_State* L) { ax::Vec3 arg0; ax::Vec3 arg1; - ax::Color4F arg2; + ax::Color arg2; ok &= luaval_to_vec3(L, 2, &arg0, "ax.DrawNode3D:drawLine"); ok &= luaval_to_vec3(L, 3, &arg1, "ax.DrawNode3D:drawLine"); - ok &= luaval_to_color4f(L, 4, &arg2, "ax.DrawNode3D:drawLine"); + ok &= luaval_to_color(L, 4, &arg2, "ax.DrawNode3D:drawLine"); if (!ok) return 0; cobj->drawLine(arg0, arg1, arg2); @@ -555,7 +555,7 @@ int lua_cocos2dx_DrawNode3D_drawCube(lua_State* L) if (argc == 2) { std::vector arg0; - ax::Color4F arg1; + ax::Color arg1; Vec3 vec3; #if _AX_DEBUG >= 1 if (!tolua_istable(L, 2, 0, &tolua_err)) @@ -587,7 +587,7 @@ int lua_cocos2dx_DrawNode3D_drawCube(lua_State* L) lua_pop(L, 1); } - ok &= luaval_to_color4f(L, 3, &arg1, "ax.DrawNode3D:drawCube"); + ok &= luaval_to_color(L, 3, &arg1, "ax.DrawNode3D:drawCube"); if (!ok) return 0; cobj->drawCube(&arg0[0], arg1); diff --git a/tests/lua-tests/proj.android/app/AndroidManifest.xml b/tests/lua-tests/proj.android/app/AndroidManifest.xml index c5bdf9a6871a..db59987ecf51 100644 --- a/tests/lua-tests/proj.android/app/AndroidManifest.xml +++ b/tests/lua-tests/proj.android/app/AndroidManifest.xml @@ -5,23 +5,23 @@ - + - + - + diff --git a/tests/lua-tests/proj.android/app/build.gradle b/tests/lua-tests/proj.android/app/build.gradle index 97977efba529..1d99737216cf 100644 --- a/tests/lua-tests/proj.android/app/build.gradle +++ b/tests/lua-tests/proj.android/app/build.gradle @@ -4,7 +4,7 @@ apply from: project(':libaxmol').projectDir.toString() + "/../dsl/axmol.gradle" // Resolve build profiles def buildProfiles = AxmolUtils.resolveBuildProfiles(project) -android { +android { def packageName = buildProfiles['packageName'] def cmakeVer = buildProfiles['cmakeVer'] def cmakeOptions = Eval.me(buildProfiles['cmakeOptions']) @@ -112,6 +112,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/tests/lua-tests/proj.android/settings.gradle b/tests/lua-tests/proj.android/settings.gradle index 1924ef9b000a..e0a9d176b6ae 100644 --- a/tests/lua-tests/proj.android/settings.gradle +++ b/tests/lua-tests/proj.android/settings.gradle @@ -11,7 +11,7 @@ else { ENGINE_ROOT = settingsDir.getPath() + "/../../.." } -def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/core/platform/android/libaxmol'; +def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/axmol/platform/android/libaxmol'; include ':libaxmol' project(':libaxmol').projectDir = new File(ENGINE_JAVA_LIBPATH) diff --git a/tests/lua-tests/proj.ios_mac/ios/AppController.mm b/tests/lua-tests/proj.ios_mac/ios/AppController.mm index 1a195743bdf4..26139827ffd5 100644 --- a/tests/lua-tests/proj.ios_mac/ios/AppController.mm +++ b/tests/lua-tests/proj.ios_mac/ios/AppController.mm @@ -24,8 +24,8 @@ of this software and associated documentation files (the "Software"), to deal ****************************************************************************/ #import #import "AppController.h" -#import "axmol.h" -#import "platform/ios/EARenderView-ios.h" +#import "axmol/axmol.h" +#import "axmol/platform/ios/EARenderView-ios.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/tests/lua-tests/proj.ios_mac/ios/LuaObjectCBridgeTest.mm b/tests/lua-tests/proj.ios_mac/ios/LuaObjectCBridgeTest.mm index a0a3509564c0..c1adc9589d2f 100644 --- a/tests/lua-tests/proj.ios_mac/ios/LuaObjectCBridgeTest.mm +++ b/tests/lua-tests/proj.ios_mac/ios/LuaObjectCBridgeTest.mm @@ -24,7 +24,7 @@ of this software and associated documentation files (the "Software"), to deal #import "LuaObjectCBridgeTest.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "lua-bindings/manual/LuaEngine.h" #include "lua-bindings/manual/LuaBridge.h" diff --git a/tests/lua-tests/proj.ios_mac/mac/LuaObjectCBridgeTest.mm b/tests/lua-tests/proj.ios_mac/mac/LuaObjectCBridgeTest.mm index a0a3509564c0..c1adc9589d2f 100644 --- a/tests/lua-tests/proj.ios_mac/mac/LuaObjectCBridgeTest.mm +++ b/tests/lua-tests/proj.ios_mac/mac/LuaObjectCBridgeTest.mm @@ -24,7 +24,7 @@ of this software and associated documentation files (the "Software"), to deal #import "LuaObjectCBridgeTest.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include "lua-bindings/manual/LuaEngine.h" #include "lua-bindings/manual/LuaBridge.h" diff --git a/tests/lua-tests/proj.linux/main.cpp b/tests/lua-tests/proj.linux/main.cpp index 40f7d8b1f4a3..7510124924bd 100644 --- a/tests/lua-tests/proj.linux/main.cpp +++ b/tests/lua-tests/proj.linux/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "cocos2d.h" +#include "axmol/cocos2d.h" #include #include diff --git a/tests/lua-tests/proj.wasm/main.cpp b/tests/lua-tests/proj.wasm/main.cpp index a274751783dd..011acbe41faa 100644 --- a/tests/lua-tests/proj.wasm/main.cpp +++ b/tests/lua-tests/proj.wasm/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/tests/lua-tests/proj.win32/main.cpp b/tests/lua-tests/proj.win32/main.cpp index ea374d3d2c27..7a5f2d3d3733 100644 --- a/tests/lua-tests/proj.win32/main.cpp +++ b/tests/lua-tests/proj.win32/main.cpp @@ -25,7 +25,7 @@ #include "main.h" #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" // Uncomment to enable win32 console // #define USE_WIN32_CONSOLE @@ -46,7 +46,7 @@ int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPTSTR lpCmdL // create the application instance #ifdef USE_WIN32_CONSOLE -# include "platform/win32/EmbedConsole.h" +# include "axmol/platform/win32/EmbedConsole.h" #endif // create the application instance diff --git a/tests/unit-tests/CMakeLists.txt b/tests/unit-tests/CMakeLists.txt index 5a6581f240c5..b496b323ed4e 100644 --- a/tests/unit-tests/CMakeLists.txt +++ b/tests/unit-tests/CMakeLists.txt @@ -33,7 +33,7 @@ if(NOT DEFINED BUILD_ENGINE_DONE) set(CMAKE_MODULE_PATH ${_AX_ROOT}/cmake/Modules/) include(AXBuildSet) - add_subdirectory(${_AX_ROOT}/core ${ENGINE_BINARY_PATH}/axmol/core) + add_subdirectory(${_AX_ROOT}/axmol ${ENGINE_BINARY_PATH}/axmol) endif() _1kfetch(sample-assets) @@ -43,22 +43,22 @@ set(GAME_SOURCE Source/AppDelegate.cpp Source/TestUtils.cpp - Source/core/2d/NodeTests.cpp + Source/axmol/2d/NodeTests.cpp - Source/core/base/MapTests.cpp - Source/core/base/UTF8Tests.cpp - Source/core/base/UtilsTests.cpp - Source/core/base/ValueTests.cpp - Source/core/base/VectorTests.cpp + Source/axmol/base/MapTests.cpp + Source/axmol/base/UTF8Tests.cpp + Source/axmol/base/UtilsTests.cpp + Source/axmol/base/ValueTests.cpp + Source/axmol/base/VectorTests.cpp - Source/core/math/FastRNGTests.cpp - Source/core/math/MathUtilTests.cpp + Source/axmol/math/FastRNGTests.cpp + Source/axmol/math/MathUtilTests.cpp - Source/core/network/UriTests.cpp + Source/axmol/network/UriTests.cpp - Source/core/platform/FileUtilsTests.cpp + Source/axmol/platform/FileUtilsTests.cpp - Source/core/ui/UIHelperTests.cpp + Source/axmol/ui/UIHelperTests.cpp ) @@ -211,7 +211,7 @@ endif() if((NOT IOS) AND (NOT WINRT)) message(STATUS "CMake precompile headers for ${APP_NAME}") target_precompile_headers(${APP_NAME} PRIVATE - "$<$:axmol.h>" + "$<$:axmol/axmol.h>" ) endif() diff --git a/tests/unit-tests/README.md b/tests/unit-tests/README.md index 3e8f8192f9ab..a8ba552d7308 100644 --- a/tests/unit-tests/README.md +++ b/tests/unit-tests/README.md @@ -41,10 +41,10 @@ Let's say you want to write unit tests for `ax::Node` class. To add a new test f 1. Find or create a source file to hold your tests. For easier navigation test source files follow the same layout and naming as the engine source files, and only add a `Tests` postfix. For - example `ax::Node` in engine is in `core/2d/Node.h`, so the test file should be in - `tests/unit-tests/Source/core/2d/NodeTests.cpp`. + example `ax::Node` in engine is in `axmol/2d/Node.h`, so the test file should be in + `tests/unit-tests/Source/axmol/2d/NodeTests.cpp`. 2. If the file doesn't exist, then create a new file, in this case - `tests/unit-tests/Source/core/2d/NodeTests.cpp`. + `tests/unit-tests/Source/axmol/2d/NodeTests.cpp`. 3. Register new file in `tests/unit-tests/CMakeLists.txt`. 4. For the test file use the following structure: diff --git a/tests/unit-tests/Source/AppDelegate.h b/tests/unit-tests/Source/AppDelegate.h index 81dc33e66370..3ac2b50918b9 100644 --- a/tests/unit-tests/Source/AppDelegate.h +++ b/tests/unit-tests/Source/AppDelegate.h @@ -26,7 +26,7 @@ ****************************************************************************/ #pragma once -#include "axmol.h" +#include "axmol/axmol.h" class TestController; diff --git a/tests/unit-tests/Source/TestUtils.cpp b/tests/unit-tests/Source/TestUtils.cpp index 5c85db682e2b..da1da0aa407f 100644 --- a/tests/unit-tests/Source/TestUtils.cpp +++ b/tests/unit-tests/Source/TestUtils.cpp @@ -1,5 +1,5 @@ #include -#include "base/Types.h" +#include "axmol/base/Types.h" #include "TestUtils.h" namespace ax @@ -28,7 +28,7 @@ doctest::String toString(const Vec3& value) { return s.c_str(); } -doctest::String toString(const Color4B& value) { +doctest::String toString(const Color32& value) { std::string s; s.append("("); s.append(std::to_string(value.r)); diff --git a/tests/unit-tests/Source/TestUtils.h b/tests/unit-tests/Source/TestUtils.h index ae0a7648ae0d..d015d3f0b688 100644 --- a/tests/unit-tests/Source/TestUtils.h +++ b/tests/unit-tests/Source/TestUtils.h @@ -1,8 +1,8 @@ #pragma once #include -#include "base/Director.h" -#include "base/Scheduler.h" +#include "axmol/base/Director.h" +#include "axmol/base/Scheduler.h" #include "doctest.h" @@ -42,7 +42,7 @@ class AsyncRunner { namespace ax { - doctest::String toString(const Color4B& value); + doctest::String toString(const Color32& value); doctest::String toString(const Vec2& value); doctest::String toString(const Vec3& value); } diff --git a/tests/unit-tests/Source/core/2d/NodeTests.cpp b/tests/unit-tests/Source/axmol/2d/NodeTests.cpp similarity index 98% rename from tests/unit-tests/Source/core/2d/NodeTests.cpp rename to tests/unit-tests/Source/axmol/2d/NodeTests.cpp index fa2b0d281235..e3904d0b58a6 100644 --- a/tests/unit-tests/Source/core/2d/NodeTests.cpp +++ b/tests/unit-tests/Source/axmol/2d/NodeTests.cpp @@ -24,7 +24,7 @@ #include #include -#include "2d/Node.h" +#include "axmol/2d/Node.h" using namespace ax; diff --git a/tests/unit-tests/Source/core/base/MapTests.cpp b/tests/unit-tests/Source/axmol/base/MapTests.cpp similarity index 98% rename from tests/unit-tests/Source/core/base/MapTests.cpp rename to tests/unit-tests/Source/axmol/base/MapTests.cpp index 7bf5d9fce938..38d9b7fb8c6a 100644 --- a/tests/unit-tests/Source/core/base/MapTests.cpp +++ b/tests/unit-tests/Source/axmol/base/MapTests.cpp @@ -24,8 +24,8 @@ ****************************************************************************/ #include -#include "2d/Node.h" -#include "base/Map.h" +#include "axmol/2d/Node.h" +#include "axmol/base/Map.h" using namespace ax; @@ -38,7 +38,7 @@ TEST_SUITE("base/Map") { { auto node = Node::create(); node->setTag(1000 + i); - ret.insert(StringUtils::toString(i), node); + ret.insert(text_utils::toString(i), node); } return ret; diff --git a/tests/unit-tests/Source/core/base/UTF8Tests.cpp b/tests/unit-tests/Source/axmol/base/UTF8Tests.cpp similarity index 84% rename from tests/unit-tests/Source/core/base/UTF8Tests.cpp rename to tests/unit-tests/Source/axmol/base/UTF8Tests.cpp index 0c1c15c38716..cb48e571cb8f 100644 --- a/tests/unit-tests/Source/core/base/UTF8Tests.cpp +++ b/tests/unit-tests/Source/axmol/base/UTF8Tests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "base/UTF8.h" +#include "axmol/base/text_utils.h" using namespace ax; @@ -54,17 +54,17 @@ TEST_SUITE("base/UTF8") { //--------------------------- std::string utf8Str; - CHECK(StringUtils::UTF16ToUTF8(originalUTF16, utf8Str)); + CHECK(text_utils::UTF16ToUTF8(originalUTF16, utf8Str)); CHECK(memcmp(utf8Str.data(), originalUTF8.data(), originalUTF8.length() + 1) == 0); //--------------------------- std::u16string utf16Str; - CHECK(StringUtils::UTF8ToUTF16(originalUTF8, utf16Str)); + CHECK(text_utils::UTF8ToUTF16(originalUTF8, utf16Str)); CHECK(memcmp(utf16Str.data(), originalUTF16.data(), originalUTF16.length() + 1) == 0); CHECK(utf16Str.length() == kUtf16TestStrLength); //--------------------------- - auto vec1 = StringUtils::getChar16VectorFromUTF16String(originalUTF16); + auto vec1 = text_utils::getChar16VectorFromUTF16String(originalUTF16); CHECK(vec1.size() == originalUTF16.length()); @@ -76,7 +76,7 @@ TEST_SUITE("base/UTF8") { vec2.emplace_back(0x2009); std::vector vec3(vec2); - StringUtils::trimUTF16Vector(vec2); + text_utils::trimUTF16Vector(vec2); CHECK(vec1.size() == vec2.size()); @@ -85,21 +85,21 @@ TEST_SUITE("base/UTF8") { CHECK(vec1.at(i) == vec2.at(i)); } - CHECK(StringUtils::countUTF8Chars(originalUTF8) == kUtf16TestStrLength); + CHECK(text_utils::countUTF8Chars(originalUTF8) == kUtf16TestStrLength); - CHECK(StringUtils::getIndexOfLastNotChar16(vec3, 0x2009) == (vec1.size() - 1)); + CHECK(text_utils::getIndexOfLastNotChar16(vec3, 0x2009) == (vec1.size() - 1)); CHECK(originalUTF16.length() == kUtf16TestStrLength); size_t whiteCodeNum = sizeof(WHITE_SPACE_CODE) / sizeof(WHITE_SPACE_CODE[0]); for (size_t i = 0; i < whiteCodeNum; i++) { - CHECK(StringUtils::isUnicodeSpace(WHITE_SPACE_CODE[i])); + CHECK(text_utils::isUnicodeSpace(WHITE_SPACE_CODE[i])); } - CHECK(!StringUtils::isUnicodeSpace(0xFFFF)); + CHECK(!text_utils::isUnicodeSpace(0xFFFF)); - CHECK(!StringUtils::isCJKUnicode(0xFFFF)); - CHECK(StringUtils::isCJKUnicode(0x3100)); + CHECK(!text_utils::isCJKUnicode(0xFFFF)); + CHECK(text_utils::isCJKUnicode(0x3100)); } } diff --git a/tests/unit-tests/Source/core/base/UtilsTests.cpp b/tests/unit-tests/Source/axmol/base/UtilsTests.cpp similarity index 98% rename from tests/unit-tests/Source/core/base/UtilsTests.cpp rename to tests/unit-tests/Source/axmol/base/UtilsTests.cpp index 17c3177bdf9c..eacd3d1c8a0b 100644 --- a/tests/unit-tests/Source/core/base/UtilsTests.cpp +++ b/tests/unit-tests/Source/axmol/base/UtilsTests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "base/Utils.h" +#include "axmol/base/Utils.h" using namespace ax; diff --git a/tests/unit-tests/Source/core/base/ValueTests.cpp b/tests/unit-tests/Source/axmol/base/ValueTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/base/ValueTests.cpp rename to tests/unit-tests/Source/axmol/base/ValueTests.cpp index 9bb9fde2b819..f26058b6648d 100644 --- a/tests/unit-tests/Source/core/base/ValueTests.cpp +++ b/tests/unit-tests/Source/axmol/base/ValueTests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "base/Value.h" +#include "axmol/base/Value.h" using namespace ax; diff --git a/tests/unit-tests/Source/core/base/VectorTests.cpp b/tests/unit-tests/Source/axmol/base/VectorTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/base/VectorTests.cpp rename to tests/unit-tests/Source/axmol/base/VectorTests.cpp index f4882e9486c5..c07319a20ccb 100644 --- a/tests/unit-tests/Source/core/base/VectorTests.cpp +++ b/tests/unit-tests/Source/axmol/base/VectorTests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "base/Vector.h" +#include "axmol/base/Vector.h" using namespace ax; diff --git a/tests/unit-tests/Source/core/math/FastRNGTests.cpp b/tests/unit-tests/Source/axmol/math/FastRNGTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/math/FastRNGTests.cpp rename to tests/unit-tests/Source/axmol/math/FastRNGTests.cpp index 36008408cb9c..b6b2743893b1 100644 --- a/tests/unit-tests/Source/core/math/FastRNGTests.cpp +++ b/tests/unit-tests/Source/axmol/math/FastRNGTests.cpp @@ -25,7 +25,7 @@ #include #include -#include "math/FastRNG.h" +#include "axmol/math/FastRNG.h" TEST_SUITE("math/FastRNG") { diff --git a/tests/unit-tests/Source/core/math/MathUtilTests.cpp b/tests/unit-tests/Source/axmol/math/MathUtilTests.cpp similarity index 93% rename from tests/unit-tests/Source/core/math/MathUtilTests.cpp rename to tests/unit-tests/Source/axmol/math/MathUtilTests.cpp index 1c220c8e3115..19ef7bab1d9b 100644 --- a/tests/unit-tests/Source/core/math/MathUtilTests.cpp +++ b/tests/unit-tests/Source/axmol/math/MathUtilTests.cpp @@ -24,9 +24,9 @@ ****************************************************************************/ #include -#include "base/Config.h" -#include "base/Types.h" -#include "math/MathBase.h" +#include "axmol/base/Config.h" +#include "axmol/base/Types.h" +#include "axmol/math/MathBase.h" #include "TestUtils.h" #define INCLUDE_SSE @@ -44,12 +44,12 @@ namespace UnitTest { #ifdef AX_NEON_INTRINSICS -# include "math/MathUtilNeon.inl" +# include "axmol/math/MathUtilNeon.inl" #elif defined(AX_SSE_INTRINSICS) -# include "math/MathUtilSSE.inl" +# include "axmol/math/MathUtilSSE.inl" #endif -#include "math/MathUtil.inl" +#include "axmol/math/MathUtil.inl" } // namespace UnitTest @@ -67,33 +67,33 @@ TEST_SUITE("math/MathUtil") { using namespace UnitTest::ax; - static void checkVerticesAreEqual(const V3F_C4B_T2F* v1, const V3F_C4B_T2F* v2, size_t count) + static void checkVerticesAreEqual(const V3F_T2F_C4B* v1, const V3F_T2F_C4B* v2, size_t count) { for (size_t i = 0; i < count; ++i) { - CHECK_EQ(v1[i].vertices, v2[i].vertices); - CHECK_EQ(v1[i].colors, v2[i].colors); - CHECK_EQ(v1[i].texCoords, v2[i].texCoords); + CHECK_EQ(v1[i].position, v2[i].position); + CHECK_EQ(v1[i].color, v2[i].color); + CHECK_EQ(v1[i].texCoord, v2[i].texCoord); } } TEST_CASE("transformVertices") { auto count = 5; - std::vector src(count); - std::vector expected(count); - std::vector dst(count); + std::vector src(count); + std::vector expected(count); + std::vector dst(count); for (int i = 0; i < count; ++i) { - src[i].vertices.set(float(i), float(i + 1), float(i + 2)); - src[i].colors.set(uint8_t(i + 3), uint8_t(i + 4), uint8_t(i + 5), uint8_t(i + 6)); - src[i].texCoords.set(float(i + 7), float(i + 8)); + src[i].position.set(float(i), float(i + 1), float(i + 2)); + src[i].color.set(uint8_t(i + 3), uint8_t(i + 4), uint8_t(i + 5), uint8_t(i + 6)); + src[i].texCoord.set(float(i + 7), float(i + 8)); expected[i] = src[i]; - expected[i].vertices.x = src[i].vertices.y * 4; - expected[i].vertices.y = src[i].vertices.x * -5; - expected[i].vertices.z = src[i].vertices.z * 6; + expected[i].position.x = src[i].position.y * 4; + expected[i].position.y = src[i].position.x * -5; + expected[i].position.z = src[i].position.z * 6; } Mat4 transform(0, 4, 0, 0, -5, 0, 0, 0, 0, 0, 6, 0, 1, 2, 3, 1); diff --git a/tests/unit-tests/Source/core/network/UriTests.cpp b/tests/unit-tests/Source/axmol/network/UriTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/network/UriTests.cpp rename to tests/unit-tests/Source/axmol/network/UriTests.cpp index 2711f0fe48f6..109ab91604e4 100644 --- a/tests/unit-tests/Source/core/network/UriTests.cpp +++ b/tests/unit-tests/Source/axmol/network/UriTests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "network/Uri.h" +#include "axmol/network/Uri.h" using namespace ax; using namespace ax::network; diff --git a/tests/unit-tests/Source/core/platform/FileUtilsTests.cpp b/tests/unit-tests/Source/axmol/platform/FileUtilsTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/platform/FileUtilsTests.cpp rename to tests/unit-tests/Source/axmol/platform/FileUtilsTests.cpp index 6eb8097b760f..799f04f72780 100644 --- a/tests/unit-tests/Source/core/platform/FileUtilsTests.cpp +++ b/tests/unit-tests/Source/axmol/platform/FileUtilsTests.cpp @@ -25,7 +25,7 @@ #include #include "TestUtils.h" -#include "platform/FileUtils.h" +#include "axmol/platform/FileUtils.h" using namespace ax; diff --git a/tests/unit-tests/Source/core/ui/UIHelperTests.cpp b/tests/unit-tests/Source/axmol/ui/UIHelperTests.cpp similarity index 99% rename from tests/unit-tests/Source/core/ui/UIHelperTests.cpp rename to tests/unit-tests/Source/axmol/ui/UIHelperTests.cpp index 7f474e8c0295..043605db3418 100644 --- a/tests/unit-tests/Source/core/ui/UIHelperTests.cpp +++ b/tests/unit-tests/Source/axmol/ui/UIHelperTests.cpp @@ -24,7 +24,7 @@ ****************************************************************************/ #include -#include "ui/UIHelper.h" +#include "axmol/ui/UIHelper.h" using namespace ax; using ax::ui::Helper; diff --git a/tests/unit-tests/proj.android/app/AndroidManifest.xml b/tests/unit-tests/proj.android/app/AndroidManifest.xml index e783f2c93955..cfe6701e170a 100644 --- a/tests/unit-tests/proj.android/app/AndroidManifest.xml +++ b/tests/unit-tests/proj.android/app/AndroidManifest.xml @@ -21,7 +21,7 @@ android:screenOrientation="sensorLandscape" android:configChanges="orientation|keyboardHidden|screenSize" android:label="@string/app_name" - android:theme="@android:style/Theme.NoTitleBar.Fullscreen" + android:theme="@style/Theme.AppCompat.Light.NoActionBar" android:launchMode="singleTask" android:taskAffinity="" android:exported="true" > diff --git a/tests/unit-tests/proj.android/app/build.gradle b/tests/unit-tests/proj.android/app/build.gradle index e6945ce47e4d..d7505cf44f17 100644 --- a/tests/unit-tests/proj.android/app/build.gradle +++ b/tests/unit-tests/proj.android/app/build.gradle @@ -4,7 +4,7 @@ apply from: project(':libaxmol').projectDir.toString() + "/../dsl/axmol.gradle" // Resolve build profiles def buildProfiles = AxmolUtils.resolveBuildProfiles(project) -android { +android { def packageName = buildProfiles['packageName'] def cmakeVer = buildProfiles['cmakeVer'] def cmakeOptions = Eval.me(buildProfiles['cmakeOptions']) @@ -114,6 +114,9 @@ android.applicationVariants.configureEach { variant -> dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation project(':libaxmol') + + def appcompat_ver = buildProfiles['appcompat'] + implementation "androidx.appcompat:appcompat:$appcompat_ver" } project.afterEvaluate { diff --git a/tests/unit-tests/proj.android/settings.gradle b/tests/unit-tests/proj.android/settings.gradle index eabd7c53e1cf..4d629bf7a11e 100644 --- a/tests/unit-tests/proj.android/settings.gradle +++ b/tests/unit-tests/proj.android/settings.gradle @@ -11,7 +11,7 @@ else { ENGINE_ROOT = settingsDir.getPath() + "/../../.." } -def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/core/platform/android/libaxmol'; +def ENGINE_JAVA_LIBPATH = ENGINE_ROOT + '/axmol/platform/android/libaxmol'; include ':libaxmol' project(':libaxmol').projectDir = new File(ENGINE_JAVA_LIBPATH) diff --git a/tests/unit-tests/proj.ios/Source/testsAppDelegate.mm b/tests/unit-tests/proj.ios/Source/testsAppDelegate.mm index 70b2977edadb..a65557baacfc 100644 --- a/tests/unit-tests/proj.ios/Source/testsAppDelegate.mm +++ b/tests/unit-tests/proj.ios/Source/testsAppDelegate.mm @@ -26,8 +26,8 @@ of this software and associated documentation files (the "Software"), to deal #import "testsAppDelegate.h" -#import "platform/ios/EARenderView-ios.h" -#import "axmol.h" +#import "axmol/platform/ios/EARenderView-ios.h" +#import "axmol/axmol.h" #import "AppDelegate.h" #import "RootViewController.h" diff --git a/tests/unit-tests/proj.wasm/main.cpp b/tests/unit-tests/proj.wasm/main.cpp index a274751783dd..011acbe41faa 100644 --- a/tests/unit-tests/proj.wasm/main.cpp +++ b/tests/unit-tests/proj.wasm/main.cpp @@ -23,7 +23,7 @@ ****************************************************************************/ #include "AppDelegate.h" -#include "axmol.h" +#include "axmol/axmol.h" #include #include diff --git a/tools/bindings-generator/clang/cindex.py b/tools/bindings-generator/clang/cindex.py index be024da5e005..806e1b40f3c9 100644 --- a/tools/bindings-generator/clang/cindex.py +++ b/tools/bindings-generator/clang/cindex.py @@ -43,7 +43,7 @@ Most object information is exposed using properties, when the underlying API call is efficient. """ -from __future__ import absolute_import, division, print_function +from __future__ import annotations # TODO # ==== @@ -64,48 +64,80 @@ from ctypes import * -import collections.abc import os +import sys from enum import Enum +from typing import ( + Any, + Callable, + Generic, + Optional, + Type as TType, + TypeVar, + TYPE_CHECKING, + Union as TUnion, +) + +if TYPE_CHECKING: + from ctypes import _Pointer + from typing_extensions import Protocol, TypeAlias + + StrPath: TypeAlias = TUnion[str, os.PathLike[str]] + LibFunc: TypeAlias = TUnion[ + "tuple[str, Optional[list[Any]]]", + "tuple[str, Optional[list[Any]], Any]", + "tuple[str, Optional[list[Any]], Any, Callable[..., Any]]", + ] + + TSeq = TypeVar("TSeq", covariant=True) + + class NoSliceSequence(Protocol[TSeq]): + def __len__(self) -> int: + ... + + def __getitem__(self, key: int) -> TSeq: + ... + # Python 3 strings are unicode, translate them to/from utf8 for C-interop. class c_interop_string(c_char_p): - def __init__(self, p=None): + def __init__(self, p: str | bytes | None = None): if p is None: p = "" if isinstance(p, str): p = p.encode("utf8") super(c_char_p, self).__init__(p) - def __str__(self): - return self.value + def __str__(self) -> str: + return self.value or "" @property - def value(self): - if super(c_char_p, self).value is None: + def value(self) -> str | None: # type: ignore [override] + val = super(c_char_p, self).value + if val is None: return None - return super(c_char_p, self).value.decode("utf8") + return val.decode("utf8") @classmethod - def from_param(cls, param): + def from_param(cls, param: str | bytes | None) -> c_interop_string: if isinstance(param, str): return cls(param) if isinstance(param, bytes): return cls(param) if param is None: # Support passing null to C functions expecting char arrays - return None + return cls(param) raise TypeError( "Cannot convert '{}' to '{}'".format(type(param).__name__, cls.__name__) ) @staticmethod - def to_python_string(x, *args): + def to_python_string(x: c_interop_string) -> str | None: return x.value -def b(x): +def b(x: str | bytes) -> bytes: if isinstance(x, bytes): return x return x.encode("utf8") @@ -115,9 +147,7 @@ def b(x): # object. This is a problem, because it means that from_parameter will see an # integer and pass the wrong value on platforms where int != void*. Work around # this by marshalling object arguments as void**. -c_object_p = POINTER(c_void_p) - -callbacks = {} +c_object_p: TType[_Pointer[Any]] = POINTER(c_void_p) ### Exception Classes ### @@ -169,8 +199,11 @@ def __init__(self, enumeration, message): ### Structures and Utility Classes ### +TInstance = TypeVar("TInstance") +TResult = TypeVar("TResult") + -class CachedProperty: +class CachedProperty(Generic[TInstance, TResult]): """Decorator that lazy-loads the value of a property. The first time the property is accessed, the original property function is @@ -178,16 +211,20 @@ class CachedProperty: property, replacing the original method. """ - def __init__(self, wrapped): + def __init__(self, wrapped: Callable[[TInstance], TResult]): self.wrapped = wrapped try: self.__doc__ = wrapped.__doc__ except: pass - def __get__(self, instance, instance_type=None): + def __get__(self, instance: TInstance, instance_type: Any = None) -> TResult: if instance is None: - return self + property_name = self.wrapped.__name__ + class_name = instance_type.__name__ + raise TypeError( + f"'{property_name}' is not a static attribute of '{class_name}'" + ) value = self.wrapped(instance) setattr(instance, self.wrapped.__name__, value) @@ -200,13 +237,16 @@ class _CXString(Structure): _fields_ = [("spelling", c_char_p), ("free", c_int)] - def __del__(self): + def __del__(self) -> None: conf.lib.clang_disposeString(self) @staticmethod - def from_result(res, fn=None, args=None): + def from_result(res: _CXString) -> str: assert isinstance(res, _CXString) - return conf.lib.clang_getCString(res) + pystr = c_interop_string.to_python_string(conf.lib.clang_getCString(res)) + if pystr is None: + return "" + return pystr class SourceLocation(Structure): @@ -236,7 +276,7 @@ def from_position(tu, file, line, column): Retrieve the source location associated with a given file/line/column in a particular translation unit. """ - return conf.lib.clang_getLocation(tu, file, line, column) + return conf.lib.clang_getLocation(tu, file, line, column) # type: ignore [no-any-return] @staticmethod def from_offset(tu, file, offset): @@ -246,7 +286,7 @@ def from_offset(tu, file, offset): file -- File instance to obtain offset from offset -- Integer character offset within file """ - return conf.lib.clang_getLocationForOffset(tu, file, offset) + return conf.lib.clang_getLocationForOffset(tu, file, offset) # type: ignore [no-any-return] @property def file(self): @@ -271,14 +311,20 @@ def offset(self): @property def is_in_system_header(self): """Returns true if the given source location is in a system header.""" - return conf.lib.clang_Location_isInSystemHeader(self) + return conf.lib.clang_Location_isInSystemHeader(self) # type: ignore [no-any-return] def __eq__(self, other): - return conf.lib.clang_equalLocations(self, other) + return conf.lib.clang_equalLocations(self, other) # type: ignore [no-any-return] def __ne__(self, other): return not self.__eq__(other) + def __lt__(self, other: SourceLocation) -> bool: + return conf.lib.clang_isBeforeInTranslationUnit(self, other) # type: ignore [no-any-return] + + def __le__(self, other: SourceLocation) -> bool: + return self < other or self == other + def __repr__(self): if self.file: filename = self.file.name @@ -307,7 +353,7 @@ class SourceRange(Structure): # object. @staticmethod def from_locations(start, end): - return conf.lib.clang_getRange(start, end) + return conf.lib.clang_getRange(start, end) # type: ignore [no-any-return] @property def start(self): @@ -315,7 +361,7 @@ def start(self): Return a SourceLocation representing the first character within a source range. """ - return conf.lib.clang_getRangeStart(self) + return conf.lib.clang_getRangeStart(self) # type: ignore [no-any-return] @property def end(self): @@ -323,10 +369,10 @@ def end(self): Return a SourceLocation representing the last character within a source range. """ - return conf.lib.clang_getRangeEnd(self) + return conf.lib.clang_getRangeEnd(self) # type: ignore [no-any-return] def __eq__(self, other): - return conf.lib.clang_equalRanges(self, other) + return conf.lib.clang_equalRanges(self, other) # type: ignore [no-any-return] def __ne__(self, other): return not self.__eq__(other) @@ -335,26 +381,7 @@ def __contains__(self, other): """Useful to detect the Token/Lexer bug""" if not isinstance(other, SourceLocation): return False - if other.file is None and self.start.file is None: - pass - elif ( - self.start.file.name != other.file.name - or other.file.name != self.end.file.name - ): - # same file name - return False - # same file, in between lines - if self.start.line < other.line < self.end.line: - return True - elif self.start.line == other.line: - # same file first line - if self.start.column <= other.column: - return True - elif other.line == self.end.line: - # same file last line - if other.column <= self.end.column: - return True - return False + return self.start <= other <= self.end def __repr__(self): return "" % (self.start, self.end) @@ -389,44 +416,46 @@ def __del__(self): @property def severity(self): - return conf.lib.clang_getDiagnosticSeverity(self) + return conf.lib.clang_getDiagnosticSeverity(self) # type: ignore [no-any-return] @property def location(self): - return conf.lib.clang_getDiagnosticLocation(self) + return conf.lib.clang_getDiagnosticLocation(self) # type: ignore [no-any-return] @property def spelling(self): - return conf.lib.clang_getDiagnosticSpelling(self) + return _CXString.from_result(conf.lib.clang_getDiagnosticSpelling(self)) @property - def ranges(self): + def ranges(self) -> NoSliceSequence[SourceRange]: class RangeIterator: - def __init__(self, diag): + def __init__(self, diag: Diagnostic): self.diag = diag - def __len__(self): + def __len__(self) -> int: return int(conf.lib.clang_getDiagnosticNumRanges(self.diag)) - def __getitem__(self, key): + def __getitem__(self, key: int) -> SourceRange: if key >= len(self): raise IndexError - return conf.lib.clang_getDiagnosticRange(self.diag, key) + return conf.lib.clang_getDiagnosticRange(self.diag, key) # type: ignore [no-any-return] return RangeIterator(self) @property - def fixits(self): + def fixits(self) -> NoSliceSequence[FixIt]: class FixItIterator: - def __init__(self, diag): + def __init__(self, diag: Diagnostic): self.diag = diag - def __len__(self): + def __len__(self) -> int: return int(conf.lib.clang_getDiagnosticNumFixIts(self.diag)) - def __getitem__(self, key): + def __getitem__(self, key: int) -> FixIt: range = SourceRange() - value = conf.lib.clang_getDiagnosticFixIt(self.diag, key, byref(range)) + value = _CXString.from_result( + conf.lib.clang_getDiagnosticFixIt(self.diag, key, byref(range)) + ) if len(value) == 0: raise IndexError @@ -435,15 +464,15 @@ def __getitem__(self, key): return FixItIterator(self) @property - def children(self): + def children(self) -> NoSliceSequence[Diagnostic]: class ChildDiagnosticsIterator: - def __init__(self, diag): + def __init__(self, diag: Diagnostic): self.diag_set = conf.lib.clang_getChildDiagnostics(diag) - def __len__(self): + def __len__(self) -> int: return int(conf.lib.clang_getNumDiagnosticsInSet(self.diag_set)) - def __getitem__(self, key): + def __getitem__(self, key: int) -> Diagnostic: diag = conf.lib.clang_getDiagnosticInSet(self.diag_set, key) if not diag: raise IndexError @@ -454,17 +483,17 @@ def __getitem__(self, key): @property def category_number(self): """The category number for this diagnostic or 0 if unavailable.""" - return conf.lib.clang_getDiagnosticCategory(self) + return conf.lib.clang_getDiagnosticCategory(self) # type: ignore [no-any-return] @property def category_name(self): """The string name of the category for this diagnostic.""" - return conf.lib.clang_getDiagnosticCategoryText(self) + return _CXString.from_result(conf.lib.clang_getDiagnosticCategoryText(self)) @property def option(self): """The command-line option that enables this diagnostic.""" - return conf.lib.clang_getDiagnosticOption(self, None) + return _CXString.from_result(conf.lib.clang_getDiagnosticOption(self, None)) @property def disable_option(self): @@ -484,7 +513,7 @@ def format(self, options=None): options = conf.lib.clang_defaultDiagnosticDisplayOptions() if options & ~Diagnostic._FormatOptionsMask: raise ValueError("Invalid format options") - return conf.lib.clang_formatDiagnostic(self, options) + return _CXString.from_result(conf.lib.clang_formatDiagnostic(self, options)) def __repr__(self): return "" % ( @@ -619,39 +648,39 @@ def get_all_kinds(): def is_declaration(self): """Test if this is a declaration kind.""" - return conf.lib.clang_isDeclaration(self) + return conf.lib.clang_isDeclaration(self) # type: ignore [no-any-return] def is_reference(self): """Test if this is a reference kind.""" - return conf.lib.clang_isReference(self) + return conf.lib.clang_isReference(self) # type: ignore [no-any-return] def is_expression(self): """Test if this is an expression kind.""" - return conf.lib.clang_isExpression(self) + return conf.lib.clang_isExpression(self) # type: ignore [no-any-return] def is_statement(self): """Test if this is a statement kind.""" - return conf.lib.clang_isStatement(self) + return conf.lib.clang_isStatement(self) # type: ignore [no-any-return] def is_attribute(self): """Test if this is an attribute kind.""" - return conf.lib.clang_isAttribute(self) + return conf.lib.clang_isAttribute(self) # type: ignore [no-any-return] def is_invalid(self): """Test if this is an invalid kind.""" - return conf.lib.clang_isInvalid(self) + return conf.lib.clang_isInvalid(self) # type: ignore [no-any-return] def is_translation_unit(self): """Test if this is a translation unit kind.""" - return conf.lib.clang_isTranslationUnit(self) + return conf.lib.clang_isTranslationUnit(self) # type: ignore [no-any-return] def is_preprocessing(self): """Test if this is a preprocessing kind.""" - return conf.lib.clang_isPreprocessing(self) + return conf.lib.clang_isPreprocessing(self) # type: ignore [no-any-return] def is_unexposed(self): """Test if this is an unexposed kind.""" - return conf.lib.clang_isUnexposed(self) + return conf.lib.clang_isUnexposed(self) # type: ignore [no-any-return] ### @@ -1524,7 +1553,7 @@ def from_location(tu, location): return cursor def __eq__(self, other): - return conf.lib.clang_equalCursors(self, other) + return conf.lib.clang_equalCursors(self, other) # type: ignore [no-any-return] def __ne__(self, other): return not self.__eq__(other) @@ -1534,41 +1563,41 @@ def is_definition(self): Returns true if the declaration pointed at by the cursor is also a definition of that entity. """ - return conf.lib.clang_isCursorDefinition(self) + return conf.lib.clang_isCursorDefinition(self) # type: ignore [no-any-return] def is_const_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared 'const'. """ - return conf.lib.clang_CXXMethod_isConst(self) + return conf.lib.clang_CXXMethod_isConst(self) # type: ignore [no-any-return] def is_converting_constructor(self): """Returns True if the cursor refers to a C++ converting constructor.""" - return conf.lib.clang_CXXConstructor_isConvertingConstructor(self) + return conf.lib.clang_CXXConstructor_isConvertingConstructor(self) # type: ignore [no-any-return] def is_copy_constructor(self): """Returns True if the cursor refers to a C++ copy constructor.""" - return conf.lib.clang_CXXConstructor_isCopyConstructor(self) + return conf.lib.clang_CXXConstructor_isCopyConstructor(self) # type: ignore [no-any-return] def is_default_constructor(self): """Returns True if the cursor refers to a C++ default constructor.""" - return conf.lib.clang_CXXConstructor_isDefaultConstructor(self) + return conf.lib.clang_CXXConstructor_isDefaultConstructor(self) # type: ignore [no-any-return] def is_move_constructor(self): """Returns True if the cursor refers to a C++ move constructor.""" - return conf.lib.clang_CXXConstructor_isMoveConstructor(self) + return conf.lib.clang_CXXConstructor_isMoveConstructor(self) # type: ignore [no-any-return] def is_default_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared '= default'. """ - return conf.lib.clang_CXXMethod_isDefaulted(self) + return conf.lib.clang_CXXMethod_isDefaulted(self) # type: ignore [no-any-return] def is_deleted_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared '= delete'. """ - return conf.lib.clang_CXXMethod_isDeleted(self) + return conf.lib.clang_CXXMethod_isDeleted(self) # type: ignore [no-any-return] def is_copy_assignment_operator_method(self): """Returnrs True if the cursor refers to a copy-assignment operator. @@ -1593,7 +1622,7 @@ class Bar { Is not. """ - return conf.lib.clang_CXXMethod_isCopyAssignmentOperator(self) + return conf.lib.clang_CXXMethod_isCopyAssignmentOperator(self) # type: ignore [no-any-return] def is_move_assignment_operator_method(self): """Returnrs True if the cursor refers to a move-assignment operator. @@ -1618,7 +1647,7 @@ class Bar { Is not. """ - return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self) + return conf.lib.clang_CXXMethod_isMoveAssignmentOperator(self) # type: ignore [no-any-return] def is_explicit_method(self): """Determines if a C++ constructor or conversion function is @@ -1663,41 +1692,41 @@ class Foo { This method will return 0 for the constructor and 1 for the conversion function. """ - return conf.lib.clang_CXXMethod_isExplicit(self) + return conf.lib.clang_CXXMethod_isExplicit(self) # type: ignore [no-any-return] def is_mutable_field(self): """Returns True if the cursor refers to a C++ field that is declared 'mutable'. """ - return conf.lib.clang_CXXField_isMutable(self) + return conf.lib.clang_CXXField_isMutable(self) # type: ignore [no-any-return] def is_pure_virtual_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared pure virtual. """ - return conf.lib.clang_CXXMethod_isPureVirtual(self) + return conf.lib.clang_CXXMethod_isPureVirtual(self) # type: ignore [no-any-return] def is_static_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared 'static'. """ - return conf.lib.clang_CXXMethod_isStatic(self) + return conf.lib.clang_CXXMethod_isStatic(self) # type: ignore [no-any-return] def is_virtual_method(self): """Returns True if the cursor refers to a C++ member function or member function template that is declared 'virtual'. """ - return conf.lib.clang_CXXMethod_isVirtual(self) + return conf.lib.clang_CXXMethod_isVirtual(self) # type: ignore [no-any-return] def is_abstract_record(self): """Returns True if the cursor refers to a C++ record declaration that has pure virtual member functions. """ - return conf.lib.clang_CXXRecord_isAbstract(self) + return conf.lib.clang_CXXRecord_isAbstract(self) # type: ignore [no-any-return] def is_scoped_enum(self): """Returns True if the cursor refers to a scoped enum declaration.""" - return conf.lib.clang_EnumDecl_isScoped(self) + return conf.lib.clang_EnumDecl_isScoped(self) # type: ignore [no-any-return] def get_definition(self): """ @@ -1707,7 +1736,7 @@ def get_definition(self): """ # TODO: Should probably check that this is either a reference or # declaration prior to issuing the lookup. - return conf.lib.clang_getCursorDefinition(self) + return Cursor.from_result(conf.lib.clang_getCursorDefinition(self), self) def get_usr(self): """Return the Unified Symbol Resolution (USR) for the entity referenced @@ -1718,13 +1747,13 @@ def get_usr(self): program. USRs can be compared across translation units to determine, e.g., when references in one translation refer to an entity defined in another translation unit.""" - return conf.lib.clang_getCursorUSR(self) + return _CXString.from_result(conf.lib.clang_getCursorUSR(self)) def get_included_file(self): """Returns the File that is included by the current inclusion cursor.""" assert self.kind == CursorKind.INCLUSION_DIRECTIVE - return conf.lib.clang_getIncludedFile(self) + return File.from_result(conf.lib.clang_getIncludedFile(self), self) @property def kind(self): @@ -1735,10 +1764,22 @@ def kind(self): def spelling(self): """Return the spelling of the entity pointed at by the cursor.""" if not hasattr(self, "_spelling"): - self._spelling = conf.lib.clang_getCursorSpelling(self) + self._spelling = _CXString.from_result( + conf.lib.clang_getCursorSpelling(self) + ) return self._spelling + def pretty_printed(self, policy): + """ + Pretty print declarations. + Parameters: + policy -- The policy to control the entities being printed. + """ + return _CXString.from_result( + conf.lib.clang_getCursorPrettyPrinted(self, policy) + ) + @property def displayname(self): """ @@ -1749,7 +1790,9 @@ def displayname(self): arguments of a class template specialization. """ if not hasattr(self, "_displayname"): - self._displayname = conf.lib.clang_getCursorDisplayName(self) + self._displayname = _CXString.from_result( + conf.lib.clang_getCursorDisplayName(self) + ) return self._displayname @@ -1757,7 +1800,9 @@ def displayname(self): def mangled_name(self): """Return the mangled name for the entity referenced by this cursor.""" if not hasattr(self, "_mangled_name"): - self._mangled_name = conf.lib.clang_Cursor_getMangling(self) + self._mangled_name = _CXString.from_result( + conf.lib.clang_Cursor_getMangling(self) + ) return self._mangled_name @@ -1849,7 +1894,7 @@ def type(self): Retrieve the Type (if any) of the entity pointed at by the cursor. """ if not hasattr(self, "_type"): - self._type = conf.lib.clang_getCursorType(self) + self._type = Type.from_result(conf.lib.clang_getCursorType(self), (self,)) return self._type @@ -1863,7 +1908,9 @@ def canonical(self): declarations will be identical. """ if not hasattr(self, "_canonical"): - self._canonical = conf.lib.clang_getCanonicalCursor(self) + self._canonical = Cursor.from_cursor_result( + conf.lib.clang_getCanonicalCursor(self), self + ) return self._canonical @@ -1871,7 +1918,9 @@ def canonical(self): def result_type(self): """Retrieve the Type of the result for this Cursor.""" if not hasattr(self, "_result_type"): - self._result_type = conf.lib.clang_getCursorResultType(self) + self._result_type = Type.from_result( + conf.lib.clang_getCursorResultType(self), (self,) + ) return self._result_type @@ -1898,7 +1947,9 @@ def underlying_typedef_type(self): """ if not hasattr(self, "_underlying_type"): assert self.kind.is_declaration() - self._underlying_type = conf.lib.clang_getTypedefDeclUnderlyingType(self) + self._underlying_type = Type.from_result( + conf.lib.clang_getTypedefDeclUnderlyingType(self), (self,) + ) return self._underlying_type @@ -1911,7 +1962,9 @@ def enum_type(self): """ if not hasattr(self, "_enum_type"): assert self.kind == CursorKind.ENUM_DECL - self._enum_type = conf.lib.clang_getEnumDeclIntegerType(self) + self._enum_type = Type.from_result( + conf.lib.clang_getEnumDeclIntegerType(self), (self,) + ) return self._enum_type @@ -1945,7 +1998,9 @@ def enum_value(self): def objc_type_encoding(self): """Return the Objective-C type encoding as a str.""" if not hasattr(self, "_objc_type_encoding"): - self._objc_type_encoding = conf.lib.clang_getDeclObjCTypeEncoding(self) + self._objc_type_encoding = _CXString.from_result( + conf.lib.clang_getDeclObjCTypeEncoding(self) + ) return self._objc_type_encoding @@ -1961,7 +2016,9 @@ def hash(self): def semantic_parent(self): """Return the semantic parent for this cursor.""" if not hasattr(self, "_semantic_parent"): - self._semantic_parent = conf.lib.clang_getCursorSemanticParent(self) + self._semantic_parent = Cursor.from_cursor_result( + conf.lib.clang_getCursorSemanticParent(self), self + ) return self._semantic_parent @@ -1969,7 +2026,9 @@ def semantic_parent(self): def lexical_parent(self): """Return the lexical parent for this cursor.""" if not hasattr(self, "_lexical_parent"): - self._lexical_parent = conf.lib.clang_getCursorLexicalParent(self) + self._lexical_parent = Cursor.from_cursor_result( + conf.lib.clang_getCursorLexicalParent(self), self + ) return self._lexical_parent @@ -1987,46 +2046,52 @@ def referenced(self): representing the entity that it references. """ if not hasattr(self, "_referenced"): - self._referenced = conf.lib.clang_getCursorReferenced(self) + self._referenced = Cursor.from_result( + conf.lib.clang_getCursorReferenced(self), self + ) return self._referenced @property def brief_comment(self): """Returns the brief comment text associated with that Cursor""" - return conf.lib.clang_Cursor_getBriefCommentText(self) + return _CXString.from_result(conf.lib.clang_Cursor_getBriefCommentText(self)) @property def raw_comment(self): """Returns the raw comment text associated with that Cursor""" - return conf.lib.clang_Cursor_getRawCommentText(self) + return _CXString.from_result(conf.lib.clang_Cursor_getRawCommentText(self)) def get_arguments(self): """Return an iterator for accessing the arguments of this cursor.""" num_args = conf.lib.clang_Cursor_getNumArguments(self) for i in range(0, num_args): - yield conf.lib.clang_Cursor_getArgument(self, i) + yield Cursor.from_result(conf.lib.clang_Cursor_getArgument(self, i), self) def get_num_template_arguments(self): """Returns the number of template args associated with this cursor.""" - return conf.lib.clang_Cursor_getNumTemplateArguments(self) + return conf.lib.clang_Cursor_getNumTemplateArguments(self) # type: ignore [no-any-return] def get_template_argument_kind(self, num): """Returns the TemplateArgumentKind for the indicated template argument.""" - return conf.lib.clang_Cursor_getTemplateArgumentKind(self, num) + return TemplateArgumentKind.from_id( + conf.lib.clang_Cursor_getTemplateArgumentKind(self, num) + ) def get_template_argument_type(self, num): """Returns the CXType for the indicated template argument.""" - return conf.lib.clang_Cursor_getTemplateArgumentType(self, num) + return Type.from_result( + conf.lib.clang_Cursor_getTemplateArgumentType(self, num), (self, num) + ) def get_template_argument_value(self, num): """Returns the value of the indicated arg as a signed 64b integer.""" - return conf.lib.clang_Cursor_getTemplateArgumentValue(self, num) + return conf.lib.clang_Cursor_getTemplateArgumentValue(self, num) # type: ignore [no-any-return] def get_template_argument_unsigned_value(self, num): """Returns the value of the indicated arg as an unsigned 64b integer.""" - return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num) + return conf.lib.clang_Cursor_getTemplateArgumentUnsignedValue(self, num) # type: ignore [no-any-return] def get_children(self): """Return an iterator for accessing the children of this cursor.""" @@ -2042,8 +2107,8 @@ def visitor(child, parent, children): children.append(child) return 1 # continue - children = [] - conf.lib.clang_visitChildren(self, callbacks["cursor_visit"](visitor), children) + children: list[Cursor] = [] + conf.lib.clang_visitChildren(self, cursor_visit_callback(visitor), children) return iter(children) def walk_preorder(self): @@ -2066,30 +2131,52 @@ def get_tokens(self): def get_field_offsetof(self): """Returns the offsetof the FIELD_DECL pointed by this Cursor.""" - return conf.lib.clang_Cursor_getOffsetOfField(self) + return conf.lib.clang_Cursor_getOffsetOfField(self) # type: ignore [no-any-return] + + def get_base_offsetof(self, parent): + """Returns the offsetof the CXX_BASE_SPECIFIER pointed by this Cursor.""" + return conf.lib.clang_getOffsetOfBase(parent, self) # type: ignore [no-any-return] + + def is_virtual_base(self): + """Returns whether the CXX_BASE_SPECIFIER pointed by this Cursor is virtual.""" + return conf.lib.clang_isVirtualBase(self) # type: ignore [no-any-return] def is_anonymous(self): """ - Check if the record is anonymous. + Check whether this is a record type without a name, or a field where + the type is a record type without a name. + + Use is_anonymous_record_decl to check whether a record is an + "anonymous union" as defined in the C/C++ standard. """ if self.kind == CursorKind.FIELD_DECL: return self.type.get_declaration().is_anonymous() - return conf.lib.clang_Cursor_isAnonymous(self) + return conf.lib.clang_Cursor_isAnonymous(self) # type: ignore [no-any-return] + + def is_anonymous_record_decl(self): + """ + Check if the record is an anonymous union as defined in the C/C++ standard + (or an "anonymous struct", the corresponding non-standard extension for + structs). + """ + if self.kind == CursorKind.FIELD_DECL: + return self.type.get_declaration().is_anonymous_record_decl() + return conf.lib.clang_Cursor_isAnonymousRecordDecl(self) # type: ignore [no-any-return] def is_bitfield(self): """ Check if the field is a bitfield. """ - return conf.lib.clang_Cursor_isBitField(self) + return conf.lib.clang_Cursor_isBitField(self) # type: ignore [no-any-return] def get_bitfield_width(self): """ Retrieve the width of a bitfield. """ - return conf.lib.clang_getFieldDeclBitWidth(self) + return conf.lib.clang_getFieldDeclBitWidth(self) # type: ignore [no-any-return] @staticmethod - def from_result(res, fn, args): + def from_result(res, arg): assert isinstance(res, Cursor) # FIXME: There should just be an isNull method. if res == conf.lib.clang_getNullCursor(): @@ -2098,14 +2185,10 @@ def from_result(res, fn, args): # Store a reference to the TU in the Python object so it won't get GC'd # before the Cursor. tu = None - for arg in args: - if isinstance(arg, TranslationUnit): - tu = arg - break - - if hasattr(arg, "translation_unit"): - tu = arg.translation_unit - break + if isinstance(arg, TranslationUnit): + tu = arg + elif hasattr(arg, "translation_unit"): + tu = arg.translation_unit assert tu is not None @@ -2113,12 +2196,12 @@ def from_result(res, fn, args): return res @staticmethod - def from_cursor_result(res, fn, args): + def from_cursor_result(res, arg): assert isinstance(res, Cursor) if res == conf.lib.clang_getNullCursor(): return None - res._tu = args[0]._tu + res._tu = arg._tu return res @@ -2223,7 +2306,7 @@ class TypeKind(BaseEnumeration): @property def spelling(self): """Retrieve the spelling of this TypeKind.""" - return conf.lib.clang_getTypeKindSpelling(self.value) + return _CXString.from_result(conf.lib.clang_getTypeKindSpelling(self.value)) INVALID = 0 UNEXPOSED = 1 @@ -2379,25 +2462,25 @@ def kind(self): """Return the kind of this type.""" return TypeKind.from_id(self._kind_id) - def argument_types(self): + def argument_types(self) -> NoSliceSequence[Type]: """Retrieve a container for the non-variadic arguments for this type. The returned object is iterable and indexable. Each item in the container is a Type instance. """ - class ArgumentsIterator(collections.abc.Sequence): - def __init__(self, parent): + class ArgumentsIterator: + def __init__(self, parent: Type): self.parent = parent - self.length = None + self.length: int | None = None - def __len__(self): + def __len__(self) -> int: if self.length is None: self.length = conf.lib.clang_getNumArgTypes(self.parent) return self.length - def __getitem__(self, key): + def __getitem__(self, key: int) -> Type: # FIXME Support slice objects. if not isinstance(key, int): raise TypeError("Must supply a non-negative int.") @@ -2411,7 +2494,9 @@ def __getitem__(self, key): "%d > %d" % (key, len(self)) ) - result = conf.lib.clang_getArgType(self.parent, key) + result = Type.from_result( + conf.lib.clang_getArgType(self.parent, key), (self.parent, key) + ) if result.kind == TypeKind.INVALID: raise IndexError("Argument could not be retrieved.") @@ -2427,7 +2512,7 @@ def element_type(self): If accessed on a type that is not an array, complex, or vector type, an exception will be raised. """ - result = conf.lib.clang_getElementType(self) + result = Type.from_result(conf.lib.clang_getElementType(self), (self,)) if result.kind == TypeKind.INVALID: raise Exception("Element type not available on this type.") @@ -2455,7 +2540,7 @@ def translation_unit(self): return self._tu @staticmethod - def from_result(res, fn, args): + def from_result(res, args): assert isinstance(res, Type) tu = None @@ -2470,10 +2555,12 @@ def from_result(res, fn, args): return res def get_num_template_arguments(self): - return conf.lib.clang_Type_getNumTemplateArguments(self) + return conf.lib.clang_Type_getNumTemplateArguments(self) # type: ignore [no-any-return] def get_template_argument_type(self, num): - return conf.lib.clang_Type_getTemplateArgumentAsType(self, num) + return Type.from_result( + conf.lib.clang_Type_getTemplateArgumentAsType(self, num), (self, num) + ) def get_canonical(self): """ @@ -2485,7 +2572,7 @@ def get_canonical(self): example, if 'T' is a typedef for 'int', the canonical type for 'T' would be 'int'. """ - return conf.lib.clang_getCanonicalType(self) + return Type.from_result(conf.lib.clang_getCanonicalType(self), (self,)) def is_const_qualified(self): """Determine whether a Type has the "const" qualifier set. @@ -2493,7 +2580,7 @@ def is_const_qualified(self): This does not look through typedefs that may have added "const" at a different level. """ - return conf.lib.clang_isConstQualifiedType(self) + return conf.lib.clang_isConstQualifiedType(self) # type: ignore [no-any-return] def is_volatile_qualified(self): """Determine whether a Type has the "volatile" qualifier set. @@ -2501,7 +2588,7 @@ def is_volatile_qualified(self): This does not look through typedefs that may have added "volatile" at a different level. """ - return conf.lib.clang_isVolatileQualifiedType(self) + return conf.lib.clang_isVolatileQualifiedType(self) # type: ignore [no-any-return] def is_restrict_qualified(self): """Determine whether a Type has the "restrict" qualifier set. @@ -2509,83 +2596,83 @@ def is_restrict_qualified(self): This does not look through typedefs that may have added "restrict" at a different level. """ - return conf.lib.clang_isRestrictQualifiedType(self) + return conf.lib.clang_isRestrictQualifiedType(self) # type: ignore [no-any-return] def is_function_variadic(self): """Determine whether this function Type is a variadic function type.""" assert self.kind == TypeKind.FUNCTIONPROTO - return conf.lib.clang_isFunctionTypeVariadic(self) + return conf.lib.clang_isFunctionTypeVariadic(self) # type: ignore [no-any-return] def get_address_space(self): - return conf.lib.clang_getAddressSpace(self) + return conf.lib.clang_getAddressSpace(self) # type: ignore [no-any-return] def get_typedef_name(self): - return conf.lib.clang_getTypedefName(self) + return _CXString.from_result(conf.lib.clang_getTypedefName(self)) def is_pod(self): """Determine whether this Type represents plain old data (POD).""" - return conf.lib.clang_isPODType(self) + return conf.lib.clang_isPODType(self) # type: ignore [no-any-return] def get_pointee(self): """ For pointer types, returns the type of the pointee. """ - return conf.lib.clang_getPointeeType(self) + return Type.from_result(conf.lib.clang_getPointeeType(self), (self,)) def get_declaration(self): """ Return the cursor for the declaration of the given type. """ - return conf.lib.clang_getTypeDeclaration(self) + return Cursor.from_result(conf.lib.clang_getTypeDeclaration(self), self) def get_result(self): """ Retrieve the result type associated with a function type. """ - return conf.lib.clang_getResultType(self) + return Type.from_result(conf.lib.clang_getResultType(self), (self,)) def get_array_element_type(self): """ Retrieve the type of the elements of the array type. """ - return conf.lib.clang_getArrayElementType(self) + return Type.from_result(conf.lib.clang_getArrayElementType(self), (self,)) def get_array_size(self): """ Retrieve the size of the constant array. """ - return conf.lib.clang_getArraySize(self) + return conf.lib.clang_getArraySize(self) # type: ignore [no-any-return] def get_class_type(self): """ Retrieve the class type of the member pointer type. """ - return conf.lib.clang_Type_getClassType(self) + return Type.from_result(conf.lib.clang_Type_getClassType(self), (self,)) def get_named_type(self): """ Retrieve the type named by the qualified-id. """ - return conf.lib.clang_Type_getNamedType(self) + return Type.from_result(conf.lib.clang_Type_getNamedType(self), (self,)) def get_align(self): """ Retrieve the alignment of the record. """ - return conf.lib.clang_Type_getAlignOf(self) + return conf.lib.clang_Type_getAlignOf(self) # type: ignore [no-any-return] def get_size(self): """ Retrieve the size of the record. """ - return conf.lib.clang_Type_getSizeOf(self) + return conf.lib.clang_Type_getSizeOf(self) # type: ignore [no-any-return] def get_offset(self, fieldname): """ Retrieve the offset of a field in the record. """ - return conf.lib.clang_Type_getOffsetOf(self, fieldname) + return conf.lib.clang_Type_getOffsetOf(self, fieldname) # type: ignore [no-any-return] def get_ref_qualifier(self): """ @@ -2604,31 +2691,48 @@ def visitor(field, children): fields.append(field) return 1 # continue - fields = [] - conf.lib.clang_Type_visitFields( - self, callbacks["fields_visit"](visitor), fields - ) + fields: list[Cursor] = [] + conf.lib.clang_Type_visitFields(self, fields_visit_callback(visitor), fields) return iter(fields) + def get_bases(self): + """Return an iterator for accessing the base classes of this type.""" + + def visitor(base, children): + assert base != conf.lib.clang_getNullCursor() + + # Create reference to TU so it isn't GC'd before Cursor. + base._tu = self._tu + bases.append(base) + return 1 # continue + + bases: list[Cursor] = [] + conf.lib.clang_visitCXXBaseClasses(self, fields_visit_callback(visitor), bases) + return iter(bases) + def get_exception_specification_kind(self): """ Return the kind of the exception specification; a value from the ExceptionSpecificationKind enumeration. """ return ExceptionSpecificationKind.from_id( - conf.lib.clang.getExceptionSpecificationType(self) + conf.lib.clang_getExceptionSpecificationType(self) ) @property def spelling(self): """Retrieve the spelling of this Type.""" - return conf.lib.clang_getTypeSpelling(self) + return _CXString.from_result(conf.lib.clang_getTypeSpelling(self)) + + def pretty_printed(self, policy): + """Pretty-prints this Type with the given PrintingPolicy""" + return _CXString.from_result(conf.lib.clang_getTypePrettyPrinted(self, policy)) def __eq__(self, other): if type(other) != type(self): return False - return conf.lib.clang_equalTypes(self, other) + return conf.lib.clang_equalTypes(self, other) # type: ignore [no-any-return] def __ne__(self, other): return not self.__eq__(other) @@ -2712,7 +2816,9 @@ def __repr__(self): def spelling(self): if self.__kindNumber in SpellingCache: return SpellingCache[self.__kindNumber] - return conf.lib.clang_getCompletionChunkText(self.cs, self.key) + return _CXString.from_result( + conf.lib.clang_getCompletionChunkText(self.cs, self.key) + ) # We do not use @CachedProperty here, as the manual implementation is # apparently still significantly faster. Please profile carefully if you @@ -2795,7 +2901,7 @@ def __len__(self): @CachedProperty def num_chunks(self): - return conf.lib.clang_getNumCompletionChunks(self.obj) + return conf.lib.clang_getNumCompletionChunks(self.obj) # type: ignore [no-any-return] def __getitem__(self, key): if self.num_chunks <= key: @@ -2804,7 +2910,7 @@ def __getitem__(self, key): @property def priority(self): - return conf.lib.clang_getCompletionPriority(self.obj) + return conf.lib.clang_getCompletionPriority(self.obj) # type: ignore [no-any-return] @property def availability(self): @@ -2814,7 +2920,9 @@ def availability(self): @property def briefComment(self): if conf.function_exists("clang_getCompletionBriefComment"): - return conf.lib.clang_getCompletionBriefComment(self.obj) + return _CXString.from_result( + conf.lib.clang_getCompletionBriefComment(self.obj) + ) return _CXString() def __repr__(self): @@ -2881,16 +2989,16 @@ def results(self): return self.ptr.contents @property - def diagnostics(self): + def diagnostics(self) -> NoSliceSequence[Diagnostic]: class DiagnosticsItr: - def __init__(self, ccr): + def __init__(self, ccr: CodeCompletionResults): self.ccr = ccr - def __len__(self): + def __len__(self) -> int: return int(conf.lib.clang_codeCompleteGetNumDiagnostics(self.ccr)) - def __getitem__(self, key): - return conf.lib.clang_codeCompleteGetDiagnostic(self.ccr, key) + def __getitem__(self, key: int) -> Diagnostic: + return conf.lib.clang_codeCompleteGetDiagnostic(self.ccr, key) # type: ignore [no-any-return] return DiagnosticsItr(self) @@ -2973,6 +3081,20 @@ class TranslationUnit(ClangObject): # into the set of code completions returned from this translation unit. PARSE_INCLUDE_BRIEF_COMMENTS_IN_CODE_COMPLETION = 128 + @staticmethod + def process_unsaved_files(unsaved_files) -> Array[_CXUnsavedFile] | None: + unsaved_array = None + if len(unsaved_files): + unsaved_array = (_CXUnsavedFile * len(unsaved_files))() + for i, (name, contents) in enumerate(unsaved_files): + if hasattr(contents, "read"): + contents = contents.read() + binary_contents = b(contents) + unsaved_array[i].name = b(os.fspath(name)) + unsaved_array[i].contents = binary_contents + unsaved_array[i].length = len(binary_contents) + return unsaved_array + @classmethod def from_source( cls, filename, args=None, unsaved_files=None, options=0, index=None @@ -3029,16 +3151,7 @@ def from_source( if len(args) > 0: args_array = (c_char_p * len(args))(*[b(x) for x in args]) - unsaved_array = None - if len(unsaved_files) > 0: - unsaved_array = (_CXUnsavedFile * len(unsaved_files))() - for i, (name, contents) in enumerate(unsaved_files): - if hasattr(contents, "read"): - contents = contents.read() - contents = b(contents) - unsaved_array[i].name = b(os.fspath(name)) - unsaved_array[i].contents = contents - unsaved_array[i].length = len(contents) + unsaved_array = cls.process_unsaved_files(unsaved_files) ptr = conf.lib.clang_parseTranslationUnit( index, @@ -3095,12 +3208,12 @@ def __del__(self): @property def cursor(self): """Retrieve the cursor that represents the given translation unit.""" - return conf.lib.clang_getTranslationUnitCursor(self) + return Cursor.from_result(conf.lib.clang_getTranslationUnitCursor(self), self) @property def spelling(self): """Get the original translation unit source file name.""" - return conf.lib.clang_getTranslationUnitSpelling(self) + return _CXString.from_result(conf.lib.clang_getTranslationUnitSpelling(self)) def get_includes(self): """ @@ -3119,7 +3232,7 @@ def visitor(fobj, lptr, depth, includes): # Automatically adapt CIndex/ctype pointers to python objects includes = [] conf.lib.clang_getInclusions( - self, callbacks["translation_unit_includes"](visitor), includes + self, translation_unit_includes_callback(visitor), includes ) return iter(includes) @@ -3187,19 +3300,19 @@ def get_extent(self, filename, locations): return SourceRange.from_locations(start_location, end_location) @property - def diagnostics(self): + def diagnostics(self) -> NoSliceSequence[Diagnostic]: """ Return an iterable (and indexable) object containing the diagnostics. """ class DiagIterator: - def __init__(self, tu): + def __init__(self, tu: TranslationUnit): self.tu = tu - def __len__(self): + def __len__(self) -> int: return int(conf.lib.clang_getNumDiagnostics(self.tu)) - def __getitem__(self, key): + def __getitem__(self, key: int) -> Diagnostic: diag = conf.lib.clang_getDiagnostic(self.tu, key) if not diag: raise IndexError @@ -3219,16 +3332,7 @@ def reparse(self, unsaved_files=None, options=0): if unsaved_files is None: unsaved_files = [] - unsaved_files_array = 0 - if len(unsaved_files): - unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() - for i, (name, contents) in enumerate(unsaved_files): - if hasattr(contents, "read"): - contents = contents.read() - contents = b(contents) - unsaved_files_array[i].name = b(os.fspath(name)) - unsaved_files_array[i].contents = contents - unsaved_files_array[i].length = len(contents) + unsaved_files_array = self.process_unsaved_files(unsaved_files) ptr = conf.lib.clang_reparseTranslationUnit( self, len(unsaved_files), unsaved_files_array, options ) @@ -3291,16 +3395,7 @@ def codeComplete( if unsaved_files is None: unsaved_files = [] - unsaved_files_array = 0 - if len(unsaved_files): - unsaved_files_array = (_CXUnsavedFile * len(unsaved_files))() - for i, (name, contents) in enumerate(unsaved_files): - if hasattr(contents, "read"): - contents = contents.read() - contents = b(contents) - unsaved_files_array[i].name = b(os.fspath(name)) - unsaved_files_array[i].contents = contents - unsaved_files_array[i].length = len(contents) + unsaved_files_array = self.process_unsaved_files(unsaved_files) ptr = conf.lib.clang_codeCompleteAt( self, os.fspath(path), @@ -3344,12 +3439,12 @@ def from_name(translation_unit, file_name): @property def name(self): """Return the complete file and path name of the file.""" - return conf.lib.clang_getFileName(self) + return _CXString.from_result(conf.lib.clang_getFileName(self)) @property def time(self): """Return the last modification time of the file.""" - return conf.lib.clang_getFileTime(self) + return conf.lib.clang_getFileTime(self) # type: ignore [no-any-return] def __str__(self): return self.name @@ -3358,12 +3453,12 @@ def __repr__(self): return "" % (self.name) @staticmethod - def from_result(res, fn, args): + def from_result(res, arg): assert isinstance(res, c_object_p) res = File(res) # Copy a reference to the TranslationUnit to prevent premature GC. - res._tu = args[0]._tu + res._tu = arg._tu return res @@ -3428,12 +3523,16 @@ def __init__(self, cmd, ccmds): @property def directory(self): """Get the working directory for this CompileCommand""" - return conf.lib.clang_CompileCommand_getDirectory(self.cmd) + return _CXString.from_result( + conf.lib.clang_CompileCommand_getDirectory(self.cmd) + ) @property def filename(self): """Get the working filename for this CompileCommand""" - return conf.lib.clang_CompileCommand_getFilename(self.cmd) + return _CXString.from_result( + conf.lib.clang_CompileCommand_getFilename(self.cmd) + ) @property def arguments(self): @@ -3445,7 +3544,9 @@ def arguments(self): """ length = conf.lib.clang_CompileCommand_getNumArgs(self.cmd) for i in range(length): - yield conf.lib.clang_CompileCommand_getArg(self.cmd, i) + yield _CXString.from_result( + conf.lib.clang_CompileCommand_getArg(self.cmd, i) + ) class CompileCommands: @@ -3470,7 +3571,7 @@ def __getitem__(self, i): return CompileCommand(cc, self) @staticmethod - def from_result(res, fn, args): + def from_result(res): if not res: return None return CompileCommands(res) @@ -3488,7 +3589,7 @@ def __del__(self): conf.lib.clang_CompilationDatabase_dispose(self) @staticmethod - def from_result(res, fn, args): + def from_result(res): if not res: raise CompilationDatabaseError(0, "CompilationDatabase loading failed") return CompilationDatabase(res) @@ -3498,8 +3599,10 @@ def fromDirectory(buildDir): """Builds a CompilationDatabase from the database found in buildDir""" errorCode = c_uint() try: - cdb = conf.lib.clang_CompilationDatabase_fromDirectory( - os.fspath(buildDir), byref(errorCode) + cdb = CompilationDatabase.from_result( + conf.lib.clang_CompilationDatabase_fromDirectory( + os.fspath(buildDir), byref(errorCode) + ) ) except CompilationDatabaseError as e: raise CompilationDatabaseError( @@ -3512,8 +3615,10 @@ def getCompileCommands(self, filename): Get an iterable object providing all the CompileCommands available to build filename. Returns None if filename is not found in the database. """ - return conf.lib.clang_CompilationDatabase_getCompileCommands( - self, os.fspath(filename) + return CompileCommands.from_result( + conf.lib.clang_CompilationDatabase_getCompileCommands( # type: ignore [no-any-return] + self, os.fspath(filename) + ) ) def getAllCompileCommands(self): @@ -3521,7 +3626,9 @@ def getAllCompileCommands(self): Get an iterable object providing all the CompileCommands available from the database. """ - return conf.lib.clang_CompilationDatabase_getAllCompileCommands(self) + return CompileCommands.from_result( + conf.lib.clang_CompilationDatabase_getAllCompileCommands(self) # type: ignore [no-any-return] + ) class Token(Structure): @@ -3542,7 +3649,7 @@ def spelling(self): This is the textual representation of the token in source. """ - return conf.lib.clang_getTokenSpelling(self._tu, self) + return _CXString.from_result(conf.lib.clang_getTokenSpelling(self._tu, self)) @property def kind(self): @@ -3552,12 +3659,12 @@ def kind(self): @property def location(self): """The SourceLocation this Token occurs at.""" - return conf.lib.clang_getTokenLocation(self._tu, self) + return conf.lib.clang_getTokenLocation(self._tu, self) # type: ignore [no-any-return] @property def extent(self): """The SourceRange this Token occupies.""" - return conf.lib.clang_getTokenExtent(self._tu, self) + return conf.lib.clang_getTokenExtent(self._tu, self) # type: ignore [no-any-return] @property def cursor(self): @@ -3619,7 +3726,7 @@ def overwrite_changed_files(self): Returns 1 if any files were not saved successfully, returns 0 otherwise. """ - return conf.lib.clang_CXRewriter_overwriteChangedFiles(self) + return conf.lib.clang_CXRewriter_overwriteChangedFiles(self) # type: ignore [no-any-return] def write_main_file_to_stdout(self): """ @@ -3629,17 +3736,83 @@ def write_main_file_to_stdout(self): conf.lib.clang_CXRewriter_writeMainFileToStdOut(self) +class PrintingPolicyProperty(BaseEnumeration): + + """ + A PrintingPolicyProperty identifies a property of a PrintingPolicy. + """ + + Indentation = 0 + SuppressSpecifiers = 1 + SuppressTagKeyword = 2 + IncludeTagDefinition = 3 + SuppressScope = 4 + SuppressUnwrittenScope = 5 + SuppressInitializers = 6 + ConstantArraySizeAsWritten = 7 + AnonymousTagLocations = 8 + SuppressStrongLifetime = 9 + SuppressLifetimeQualifiers = 10 + SuppressTemplateArgsInCXXConstructors = 11 + Bool = 12 + Restrict = 13 + Alignof = 14 + UnderscoreAlignof = 15 + UseVoidForZeroParams = 16 + TerseOutput = 17 + PolishForDeclaration = 18 + Half = 19 + MSWChar = 20 + IncludeNewlines = 21 + MSVCFormatting = 22 + ConstantsAsWritten = 23 + SuppressImplicitBase = 24 + FullyQualifiedName = 25 + + +class PrintingPolicy(ClangObject): + """ + The PrintingPolicy is a wrapper class around clang::PrintingPolicy + + It allows specifying how declarations, expressions, and types should be + pretty-printed. + """ + + @staticmethod + def create(cursor): + """ + Creates a new PrintingPolicy + Parameters: + cursor -- Any cursor for a translation unit. + """ + return PrintingPolicy(conf.lib.clang_getCursorPrintingPolicy(cursor)) + + def __init__(self, ptr): + ClangObject.__init__(self, ptr) + + def __del__(self): + conf.lib.clang_PrintingPolicy_dispose(self) + + def get_property(self, property): + """Get a property value for the given printing policy.""" + return conf.lib.clang_PrintingPolicy_getProperty(self, property.value) + + def set_property(self, property, value): + """Set a property value for the given printing policy.""" + conf.lib.clang_PrintingPolicy_setProperty(self, property.value, value) + + # Now comes the plumbing to hook up the C library. -# Register callback types in common container. -callbacks["translation_unit_includes"] = CFUNCTYPE( +# Register callback types +translation_unit_includes_callback = CFUNCTYPE( None, c_object_p, POINTER(SourceLocation), c_uint, py_object ) -callbacks["cursor_visit"] = CFUNCTYPE(c_int, Cursor, Cursor, py_object) -callbacks["fields_visit"] = CFUNCTYPE(c_int, Cursor, py_object) +cursor_visit_callback = CFUNCTYPE(c_int, Cursor, Cursor, py_object) +fields_visit_callback = CFUNCTYPE(c_int, Cursor, py_object) # Functions strictly alphabetical order. -functionList = [ +functionList: list[LibFunc] = [ ( "clang_annotateTokens", [TranslationUnit, POINTER(Token), c_uint, POINTER(Cursor)], @@ -3649,41 +3822,19 @@ def write_main_file_to_stdout(self): "clang_CompilationDatabase_fromDirectory", [c_interop_string, POINTER(c_uint)], c_object_p, - CompilationDatabase.from_result, - ), - ( - "clang_CompilationDatabase_getAllCompileCommands", - [c_object_p], - c_object_p, - CompileCommands.from_result, ), + ("clang_CompilationDatabase_getAllCompileCommands", [c_object_p], c_object_p), ( "clang_CompilationDatabase_getCompileCommands", [c_object_p, c_interop_string], c_object_p, - CompileCommands.from_result, ), ("clang_CompileCommands_dispose", [c_object_p]), ("clang_CompileCommands_getCommand", [c_object_p, c_uint], c_object_p), ("clang_CompileCommands_getSize", [c_object_p], c_uint), - ( - "clang_CompileCommand_getArg", - [c_object_p, c_uint], - _CXString, - _CXString.from_result, - ), - ( - "clang_CompileCommand_getDirectory", - [c_object_p], - _CXString, - _CXString.from_result, - ), - ( - "clang_CompileCommand_getFilename", - [c_object_p], - _CXString, - _CXString.from_result, - ), + ("clang_CompileCommand_getArg", [c_object_p, c_uint], _CXString), + ("clang_CompileCommand_getDirectory", [c_object_p], _CXString), + ("clang_CompileCommand_getFilename", [c_object_p], _CXString), ("clang_CompileCommand_getNumArgs", [c_object_p], c_uint), ( "clang_codeCompleteAt", @@ -3731,85 +3882,67 @@ def write_main_file_to_stdout(self): ("clang_equalLocations", [SourceLocation, SourceLocation], bool), ("clang_equalRanges", [SourceRange, SourceRange], bool), ("clang_equalTypes", [Type, Type], bool), - ("clang_formatDiagnostic", [Diagnostic, c_uint], _CXString, _CXString.from_result), - ("clang_getArgType", [Type, c_uint], Type, Type.from_result), - ("clang_getArrayElementType", [Type], Type, Type.from_result), + ("clang_formatDiagnostic", [Diagnostic, c_uint], _CXString), + ("clang_getArgType", [Type, c_uint], Type), + ("clang_getArrayElementType", [Type], Type), ("clang_getArraySize", [Type], c_longlong), ("clang_getFieldDeclBitWidth", [Cursor], c_int), - ("clang_getCanonicalCursor", [Cursor], Cursor, Cursor.from_cursor_result), - ("clang_getCanonicalType", [Type], Type, Type.from_result), + ("clang_getCanonicalCursor", [Cursor], Cursor), + ("clang_getCanonicalType", [Type], Type), ("clang_getChildDiagnostics", [Diagnostic], c_object_p), ("clang_getCompletionAvailability", [c_void_p], c_int), - ("clang_getCompletionBriefComment", [c_void_p], _CXString, _CXString.from_result), + ("clang_getCompletionBriefComment", [c_void_p], _CXString), ("clang_getCompletionChunkCompletionString", [c_void_p, c_int], c_object_p), ("clang_getCompletionChunkKind", [c_void_p, c_int], c_int), - ( - "clang_getCompletionChunkText", - [c_void_p, c_int], - _CXString, - _CXString.from_result, - ), + ("clang_getCompletionChunkText", [c_void_p, c_int], _CXString), ("clang_getCompletionPriority", [c_void_p], c_int), - ( - "clang_getCString", - [_CXString], - c_interop_string, - c_interop_string.to_python_string, - ), + ("clang_getCString", [_CXString], c_interop_string), ("clang_getCursor", [TranslationUnit, SourceLocation], Cursor), ("clang_getCursorAvailability", [Cursor], c_int), - ("clang_getCursorDefinition", [Cursor], Cursor, Cursor.from_result), - ("clang_getCursorDisplayName", [Cursor], _CXString, _CXString.from_result), + ("clang_getCursorDefinition", [Cursor], Cursor), + ("clang_getCursorDisplayName", [Cursor], _CXString), ("clang_getCursorExtent", [Cursor], SourceRange), - ("clang_getCursorLexicalParent", [Cursor], Cursor, Cursor.from_cursor_result), + ("clang_getCursorLexicalParent", [Cursor], Cursor), ("clang_getCursorLocation", [Cursor], SourceLocation), - ("clang_getCursorReferenced", [Cursor], Cursor, Cursor.from_result), + ("clang_getCursorPrettyPrinted", [Cursor, PrintingPolicy], _CXString), + ("clang_getCursorPrintingPolicy", [Cursor], c_object_p), + ("clang_getCursorReferenced", [Cursor], Cursor), ("clang_getCursorReferenceNameRange", [Cursor, c_uint, c_uint], SourceRange), - ("clang_getCursorResultType", [Cursor], Type, Type.from_result), - ("clang_getCursorSemanticParent", [Cursor], Cursor, Cursor.from_cursor_result), - ("clang_getCursorSpelling", [Cursor], _CXString, _CXString.from_result), - ("clang_getCursorType", [Cursor], Type, Type.from_result), - ("clang_getCursorUSR", [Cursor], _CXString, _CXString.from_result), - ("clang_Cursor_getMangling", [Cursor], _CXString, _CXString.from_result), + ("clang_getCursorResultType", [Cursor], Type), + ("clang_getCursorSemanticParent", [Cursor], Cursor), + ("clang_getCursorSpelling", [Cursor], _CXString), + ("clang_getCursorType", [Cursor], Type), + ("clang_getCursorUSR", [Cursor], _CXString), + ("clang_Cursor_getMangling", [Cursor], _CXString), # ("clang_getCXTUResourceUsage", # [TranslationUnit], # CXTUResourceUsage), ("clang_getCXXAccessSpecifier", [Cursor], c_uint), - ("clang_getDeclObjCTypeEncoding", [Cursor], _CXString, _CXString.from_result), + ("clang_getDeclObjCTypeEncoding", [Cursor], _CXString), ("clang_getDiagnostic", [c_object_p, c_uint], c_object_p), ("clang_getDiagnosticCategory", [Diagnostic], c_uint), - ("clang_getDiagnosticCategoryText", [Diagnostic], _CXString, _CXString.from_result), - ( - "clang_getDiagnosticFixIt", - [Diagnostic, c_uint, POINTER(SourceRange)], - _CXString, - _CXString.from_result, - ), + ("clang_getDiagnosticCategoryText", [Diagnostic], _CXString), + ("clang_getDiagnosticFixIt", [Diagnostic, c_uint, POINTER(SourceRange)], _CXString), ("clang_getDiagnosticInSet", [c_object_p, c_uint], c_object_p), ("clang_getDiagnosticLocation", [Diagnostic], SourceLocation), ("clang_getDiagnosticNumFixIts", [Diagnostic], c_uint), ("clang_getDiagnosticNumRanges", [Diagnostic], c_uint), - ( - "clang_getDiagnosticOption", - [Diagnostic, POINTER(_CXString)], - _CXString, - _CXString.from_result, - ), + ("clang_getDiagnosticOption", [Diagnostic, POINTER(_CXString)], _CXString), ("clang_getDiagnosticRange", [Diagnostic, c_uint], SourceRange), ("clang_getDiagnosticSeverity", [Diagnostic], c_int), - ("clang_getDiagnosticSpelling", [Diagnostic], _CXString, _CXString.from_result), - ("clang_getElementType", [Type], Type, Type.from_result), + ("clang_getDiagnosticSpelling", [Diagnostic], _CXString), + ("clang_getElementType", [Type], Type), ("clang_getEnumConstantDeclUnsignedValue", [Cursor], c_ulonglong), ("clang_getEnumConstantDeclValue", [Cursor], c_longlong), - ("clang_getEnumDeclIntegerType", [Cursor], Type, Type.from_result), + ("clang_getEnumDeclIntegerType", [Cursor], Type), ("clang_getFile", [TranslationUnit, c_interop_string], c_object_p), - ("clang_getFileName", [File], _CXString, _CXString.from_result), + ("clang_getFileName", [File], _CXString), ("clang_getFileTime", [File], c_uint), - ("clang_getIBOutletCollectionType", [Cursor], Type, Type.from_result), - ("clang_getIncludedFile", [Cursor], c_object_p, File.from_result), + ("clang_getIBOutletCollectionType", [Cursor], Type), + ("clang_getIncludedFile", [Cursor], c_object_p), ( "clang_getInclusions", - [TranslationUnit, callbacks["translation_unit_includes"], py_object], + [TranslationUnit, translation_unit_includes_callback, py_object], ), ( "clang_getInstantiationLocation", @@ -3830,41 +3963,28 @@ def write_main_file_to_stdout(self): ("clang_getNumDiagnosticsInSet", [c_object_p], c_uint), ("clang_getNumElements", [Type], c_longlong), ("clang_getNumOverloadedDecls", [Cursor], c_uint), - ("clang_getOverloadedDecl", [Cursor, c_uint], Cursor, Cursor.from_cursor_result), - ("clang_getPointeeType", [Type], Type, Type.from_result), + ("clang_getOffsetOfBase", [Cursor, Cursor], c_longlong), + ("clang_getOverloadedDecl", [Cursor, c_uint], Cursor), + ("clang_getPointeeType", [Type], Type), ("clang_getRange", [SourceLocation, SourceLocation], SourceRange), ("clang_getRangeEnd", [SourceRange], SourceLocation), ("clang_getRangeStart", [SourceRange], SourceLocation), - ("clang_getResultType", [Type], Type, Type.from_result), - ("clang_getSpecializedCursorTemplate", [Cursor], Cursor, Cursor.from_cursor_result), + ("clang_getResultType", [Type], Type), + ("clang_getSpecializedCursorTemplate", [Cursor], Cursor), ("clang_getTemplateCursorKind", [Cursor], c_uint), ("clang_getTokenExtent", [TranslationUnit, Token], SourceRange), ("clang_getTokenKind", [Token], c_uint), ("clang_getTokenLocation", [TranslationUnit, Token], SourceLocation), - ( - "clang_getTokenSpelling", - [TranslationUnit, Token], - _CXString, - _CXString.from_result, - ), - ("clang_getTranslationUnitCursor", [TranslationUnit], Cursor, Cursor.from_result), - ( - "clang_getTranslationUnitSpelling", - [TranslationUnit], - _CXString, - _CXString.from_result, - ), - ( - "clang_getTUResourceUsageName", - [c_uint], - c_interop_string, - c_interop_string.to_python_string, - ), - ("clang_getTypeDeclaration", [Type], Cursor, Cursor.from_result), - ("clang_getTypedefDeclUnderlyingType", [Cursor], Type, Type.from_result), - ("clang_getTypedefName", [Type], _CXString, _CXString.from_result), - ("clang_getTypeKindSpelling", [c_uint], _CXString, _CXString.from_result), - ("clang_getTypeSpelling", [Type], _CXString, _CXString.from_result), + ("clang_getTokenSpelling", [TranslationUnit, Token], _CXString), + ("clang_getTranslationUnitCursor", [TranslationUnit], Cursor), + ("clang_getTranslationUnitSpelling", [TranslationUnit], _CXString), + ("clang_getTUResourceUsageName", [c_uint], c_interop_string), + ("clang_getTypeDeclaration", [Type], Cursor), + ("clang_getTypedefDeclUnderlyingType", [Cursor], Type), + ("clang_getTypedefName", [Type], _CXString), + ("clang_getTypeKindSpelling", [c_uint], _CXString), + ("clang_getTypePrettyPrinted", [Type, PrintingPolicy], _CXString), + ("clang_getTypeSpelling", [Type], _CXString), ("clang_hashCursor", [Cursor], c_uint), ("clang_isAttribute", [CursorKind], bool), ("clang_isConstQualifiedType", [Type], bool), @@ -3883,6 +4003,7 @@ def write_main_file_to_stdout(self): ("clang_isUnexposed", [CursorKind], bool), ("clang_isVirtualBase", [Cursor], bool), ("clang_isVolatileQualifiedType", [Type], bool), + ("clang_isBeforeInTranslationUnit", [SourceLocation, SourceLocation], bool), ( "clang_parseTranslationUnit", [Index, c_interop_string, c_void_p, c_int, c_void_p, c_int, c_int], @@ -3894,46 +4015,47 @@ def write_main_file_to_stdout(self): "clang_tokenize", [TranslationUnit, SourceRange, POINTER(POINTER(Token)), POINTER(c_uint)], ), - ("clang_visitChildren", [Cursor, callbacks["cursor_visit"], py_object], c_uint), + ("clang_visitChildren", [Cursor, cursor_visit_callback, py_object], c_uint), + ("clang_visitCXXBaseClasses", [Type, fields_visit_callback, py_object], c_uint), ("clang_Cursor_getNumArguments", [Cursor], c_int), - ("clang_Cursor_getArgument", [Cursor, c_uint], Cursor, Cursor.from_result), + ("clang_Cursor_getArgument", [Cursor, c_uint], Cursor), ("clang_Cursor_getNumTemplateArguments", [Cursor], c_int), - ( - "clang_Cursor_getTemplateArgumentKind", - [Cursor, c_uint], - TemplateArgumentKind.from_id, - ), - ("clang_Cursor_getTemplateArgumentType", [Cursor, c_uint], Type, Type.from_result), + ("clang_Cursor_getTemplateArgumentKind", [Cursor, c_uint], c_uint), + ("clang_Cursor_getTemplateArgumentType", [Cursor, c_uint], Type), ("clang_Cursor_getTemplateArgumentValue", [Cursor, c_uint], c_longlong), ("clang_Cursor_getTemplateArgumentUnsignedValue", [Cursor, c_uint], c_ulonglong), - ("clang_Cursor_isAnonymous", [Cursor], bool), - ("clang_Cursor_isBitField", [Cursor], bool), ("clang_Cursor_getBinaryOpcode", [Cursor], c_int), - ("clang_Cursor_getBriefCommentText", [Cursor], _CXString, _CXString.from_result), - ("clang_Cursor_getRawCommentText", [Cursor], _CXString, _CXString.from_result), + ("clang_Cursor_getBriefCommentText", [Cursor], _CXString), + ("clang_Cursor_getRawCommentText", [Cursor], _CXString), ("clang_Cursor_getOffsetOfField", [Cursor], c_longlong), + ("clang_Cursor_isAnonymous", [Cursor], bool), + ("clang_Cursor_isAnonymousRecordDecl", [Cursor], bool), + ("clang_Cursor_isBitField", [Cursor], bool), ("clang_Location_isInSystemHeader", [SourceLocation], bool), + ("clang_PrintingPolicy_dispose", [PrintingPolicy]), + ("clang_PrintingPolicy_getProperty", [PrintingPolicy, c_int], c_uint), + ("clang_PrintingPolicy_setProperty", [PrintingPolicy, c_int, c_uint]), ("clang_Type_getAlignOf", [Type], c_longlong), - ("clang_Type_getClassType", [Type], Type, Type.from_result), + ("clang_Type_getClassType", [Type], Type), ("clang_Type_getNumTemplateArguments", [Type], c_int), - ("clang_Type_getTemplateArgumentAsType", [Type, c_uint], Type, Type.from_result), + ("clang_Type_getTemplateArgumentAsType", [Type, c_uint], Type), ("clang_Type_getOffsetOf", [Type, c_interop_string], c_longlong), ("clang_Type_getSizeOf", [Type], c_longlong), ("clang_Type_getCXXRefQualifier", [Type], c_uint), - ("clang_Type_getNamedType", [Type], Type, Type.from_result), - ("clang_Type_visitFields", [Type, callbacks["fields_visit"], py_object], c_uint), + ("clang_Type_getNamedType", [Type], Type), + ("clang_Type_visitFields", [Type, fields_visit_callback, py_object], c_uint), ] class LibclangError(Exception): - def __init__(self, message): + def __init__(self, message: str): self.m = message - def __str__(self): + def __str__(self) -> str: return self.m -def register_function(lib, item, ignore_errors): +def register_function(lib: CDLL, item: LibFunc, ignore_errors: bool) -> None: # A function may not exist, if these bindings are used with an older or # incompatible version of libclang.so. try: @@ -3957,15 +4079,15 @@ def register_function(lib, item, ignore_errors): func.errcheck = item[3] -def register_functions(lib, ignore_errors): +def register_functions(lib: CDLL, ignore_errors: bool) -> None: """Register function prototypes with a libclang library instance. This must be called as part of library instantiation so Python knows how to call out to the shared library. """ - def register(item): - return register_function(lib, item, ignore_errors) + def register(item: LibFunc) -> None: + register_function(lib, item, ignore_errors) for f in functionList: register(f) @@ -3973,12 +4095,12 @@ def register(item): class Config: library_path = None - library_file = None + library_file: str | None = None compatibility_check = True loaded = False @staticmethod - def set_library_path(path): + def set_library_path(path: StrPath) -> None: """Set the path in which to search for libclang""" if Config.loaded: raise Exception( @@ -3989,7 +4111,7 @@ def set_library_path(path): Config.library_path = os.fspath(path) @staticmethod - def set_library_file(filename): + def set_library_file(filename: StrPath) -> None: """Set the exact location of libclang""" if Config.loaded: raise Exception( @@ -4000,7 +4122,7 @@ def set_library_file(filename): Config.library_file = os.fspath(filename) @staticmethod - def set_compatibility_check(check_status): + def set_compatibility_check(check_status: bool) -> None: """Perform compatibility check when loading libclang The python bindings are only tested and evaluated with the version of @@ -4026,13 +4148,13 @@ def set_compatibility_check(check_status): Config.compatibility_check = check_status @CachedProperty - def lib(self): + def lib(self) -> CDLL: lib = self.get_cindex_library() register_functions(lib, not Config.compatibility_check) Config.loaded = True return lib - def get_filename(self): + def get_filename(self) -> str: if Config.library_file: return Config.library_file @@ -4052,7 +4174,7 @@ def get_filename(self): return file - def get_cindex_library(self): + def get_cindex_library(self) -> CDLL: try: library = cdll.LoadLibrary(self.get_filename()) except OSError as e: @@ -4065,7 +4187,7 @@ def get_cindex_library(self): return library - def function_exists(self, name): + def function_exists(self, name: str) -> bool: try: getattr(self.lib, name) except AttributeError: @@ -4077,6 +4199,7 @@ def function_exists(self, name): conf = Config() __all__ = [ + "AccessSpecifier", "AvailabilityKind", "BinaryOperator", "Config", @@ -4087,12 +4210,18 @@ def function_exists(self, name): "CursorKind", "Cursor", "Diagnostic", + "ExceptionSpecificationKind", "File", "FixIt", "Index", "LinkageKind", + "PrintingPolicy", + "PrintingPolicyProperty", + "RefQualifierKind", "SourceLocation", "SourceRange", + "StorageClass", + "TemplateArgumentKind", "TLSKind", "TokenKind", "Token", diff --git a/tools/bindings-generator/generator.py b/tools/bindings-generator/generator.py index 1a13ca55e48b..e8541a1e2211 100644 --- a/tools/bindings-generator/generator.py +++ b/tools/bindings-generator/generator.py @@ -1379,6 +1379,8 @@ def __init__(self, opts): print(f'clang_args={self.clang_args}') + print(f'clang_args={self.clang_args}') + if opts['skip']: list_of_skips = re.split(",\n?", opts['skip']) for skip in list_of_skips: @@ -1739,10 +1741,10 @@ def js_typename_from_natve(self, namespace_class_name): return "rect_object" if namespace_class_name.find("ax::Color3B") == 0: return "color3b_object" - if namespace_class_name.find("ax::Color4B") == 0: - return "color4b_object" - if namespace_class_name.find("ax::Color4F") == 0: - return "color4f_object" + if namespace_class_name.find("ax::Color32") == 0: + return "color32_object" + if namespace_class_name.find("ax::Color") == 0: + return "color_object" else: return namespace_class_name.replace("*","").replace("const ", "").replace(k,v) return namespace_class_name.replace("*","").replace("const ", "") @@ -1785,8 +1787,8 @@ def lua_typename_from_natve(self, namespace_class_name, is_ret = False): return "rect_table" if namespace_class_name.find("ax::Color3B") == 0: return "color3b_table" - if namespace_class_name.find("ax::Color4B") == 0: - return "color4b_table" + if namespace_class_name.find("ax::Color32") == 0: + return "color32_table" if namespace_class_name.find("ax::Color4F") == 0: return "color4f_table" if is_ret == 1: diff --git a/tools/bindings-generator/targets/lua/conversions.yaml b/tools/bindings-generator/targets/lua/conversions.yaml index 0168090fceb8..dc9f5a347907 100644 --- a/tools/bindings-generator/targets/lua/conversions.yaml +++ b/tools/bindings-generator/targets/lua/conversions.yaml @@ -23,7 +23,7 @@ conversions: "cocostudio::timeline::": "ccs." "cocostudio::": "ccs." "ax::tweenfunc::": "ax." - "ax::backend::": "axb." + "ax::rhi::": "axrhi." "tsl::": "tsl." "hlookup::": "hlookup." "fairygui::": "fgui." @@ -52,8 +52,8 @@ conversions: "Vec4": "ok &= luaval_to_vec4(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "Rect": "ok &= luaval_to_rect(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "Size": "ok &= luaval_to_size(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" - "Color4B": "ok &=luaval_to_color4b(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" - "Color4F": "ok &=luaval_to_color4f(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" + "Color32": "ok &=luaval_to_color32(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" + "Color": "ok &=luaval_to_color(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "Color3B": "ok &= luaval_to_color3b(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "PhysicsMaterial": "ok &= luaval_to_physics_material(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "Array*": "ok &= luaval_to_array(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" @@ -83,7 +83,7 @@ conversions: "OffMeshLinkData": "ok &= luaval_to_offmeshlinkdata(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "ListenerID": "ok &= luaval_to_std_string(tolua_S, ${arg_idx},&${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" # "VertexLayout": "ok &= luaval_to_vertexLayout(tolua_S, ${arg_idx}, ${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" - "SamplerDescriptor": "ok &= luaval_to_samplerDescriptor(tolua_S, ${arg_idx}, ${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" + "SamplerDesc": "ok &= luaval_to_samplerDesc(tolua_S, ${arg_idx}, ${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "UniformLocation": "ok &= luaval_to_uniformLocation(tolua_S, ${arg_idx}, ${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "ValueMap*": "ok &= luaval_to_ccvaluemap(tolua_S, ${arg_idx}, ${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" "Margin": "ok &= luaval_to_margin(tolua_S, ${arg_idx}, &${out_value}, \"${lua_namespaced_class_name}:${func_name}\")" @@ -117,8 +117,9 @@ conversions: "Vec4": "vec4_to_luaval(tolua_S, ${in_value})" "Rect": "rect_to_luaval(tolua_S, ${in_value})" "Size": "size_to_luaval(tolua_S, ${in_value})" - "Color4B": "color4b_to_luaval(tolua_S, ${in_value})" + "Color32": "color32_to_luaval(tolua_S, ${in_value})" "Color4F": "color4f_to_luaval(tolua_S, ${in_value})" + "Color": "color_to_luaval(tolua_S, ${in_value})" "Color3B": "color3b_to_luaval(tolua_S, ${in_value})" "PhysicsMaterial": "physics_material_to_luaval(tolua_S, ${in_value})" "PhysicsContactData*": "physics_contactdata_to_luaval(tolua_S, ${in_value})" diff --git a/tools/bindings-generator/targets/lua/templates/layout_head.h b/tools/bindings-generator/targets/lua/templates/layout_head.h index eca06af48ad8..937d179d0c5b 100644 --- a/tools/bindings-generator/targets/lua/templates/layout_head.h +++ b/tools/bindings-generator/targets/lua/templates/layout_head.h @@ -1,15 +1,15 @@ \#pragma once #if $macro_judgement $macro_judgement -#end if +#end if -\#include "base/Config.h" +\#include "axmol/base/Config.h" #if $hpp_headers #for header in $hpp_headers \#include "${header}" #end for -#end if +#end if \#include "tolua++.h" diff --git a/tools/ci/build-docs.ps1 b/tools/ci/build-docs.ps1 index 37a11e06f95d..a392df7b4ef7 100644 --- a/tools/ci/build-docs.ps1 +++ b/tools/ci/build-docs.ps1 @@ -81,7 +81,7 @@ setup_doxygen Write-Host "Using doxygen $(doxygen --version)" -$axver_file = (Resolve-Path $AX_ROOT/core/axmolver.h.in).Path +$axver_file = (Resolve-Path $AX_ROOT/axmol/axmolver.h.in).Path $axver_content = $(Get-Content -Path $axver_file) function parse_axver($part) { return ($axver_content | Select-String "#define AX_VERSION_$part").Line.Split(' ')[2] diff --git a/tools/ci/genbindings.ps1 b/tools/ci/genbindings.ps1 index 97f3acf21656..bfa48cd95aed 100644 --- a/tools/ci/genbindings.ps1 +++ b/tools/ci/genbindings.ps1 @@ -44,12 +44,12 @@ if (($stage -band 1)) { Copy-Item "$prefix/llvm-$llvm_ver/lib/$suffix" -Destination $lib_path } - ## ensure $env:AX_ROOT/core/axmolver.h exists + ## ensure $env:AX_ROOT/axmol/axmolver.h exists echo "AX_ROOT=$AX_ROOT" - if (!(Test-Path "$AX_ROOT/core/axmolver.h" -PathType Leaf)) { - $content = [System.IO.File]::ReadAllText("$AX_ROOT/core/axmolver.h.in") + if (!(Test-Path "$AX_ROOT/axmol/axmolver.h" -PathType Leaf)) { + $content = [System.IO.File]::ReadAllText("$AX_ROOT/axmol/axmolver.h.in") $content = $content.Replace('@AX_GIT_PRESENT@', '0') - [System.IO.File]::WriteAllText("$AX_ROOT/core/axmolver.h") + [System.IO.File]::WriteAllText("$AX_ROOT/axmol/axmolver.h") } ## run genbindings.py diff --git a/tools/ci/publish.ps1 b/tools/ci/publish.ps1 index 5ebd0246af92..781d1913a07b 100644 --- a/tools/ci/publish.ps1 +++ b/tools/ci/publish.ps1 @@ -12,7 +12,7 @@ if ($commitish) { $prerelease = 'false' if (!$version -or ($version -eq 'auto')) { $prerelease = 'true' - $axver_file = (Resolve-Path $AX_ROOT/core/axmolver.h.in).Path + $axver_file = (Resolve-Path $AX_ROOT/axmol/axmolver.h.in).Path $axver_content = $(Get-Content -Path $axver_file) function parse_axver($part) { return ($axver_content | Select-String "#define AX_VERSION_$part").Line.Split(' ')[2] @@ -51,8 +51,8 @@ $excludes = @( '.vscode' 'build_*' 'build' - 'core/axmolver.h' - 'core/renderer/RenderConsts.h' + 'axmol/axmolver.h' + 'axmol/renderer/RenderConsts.h' '.github' 'tmp' 'temp' @@ -77,7 +77,7 @@ $main_pkg_compress_args = @{ $bs_pkg_file_name = "axmol-bs-$version.zip" $bs_pkg_file_path = $(Join-Path $AX_ROOT $bs_pkg_file_name) $bs_pkg_compress_args = @{ - Path = @("$AX_ROOT/1k", "$AX_ROOT/setup.ps1", "$AX_ROOT/core/axmolver.h.in", "$AX_ROOT/tools/cmdline") + Path = @("$AX_ROOT/1k", "$AX_ROOT/setup.ps1", "$AX_ROOT/axmol/axmolver.h.in", "$AX_ROOT/tools/cmdline") CompressionLevel = 'Optimal' DestinationPath = $bs_pkg_file_path RelativeBasePath = $AX_ROOT diff --git a/tools/cmdline/axmol.ps1 b/tools/cmdline/axmol.ps1 index 4652fa891cb5..874de8f619f9 100644 --- a/tools/cmdline/axmol.ps1 +++ b/tools/cmdline/axmol.ps1 @@ -18,7 +18,7 @@ $myRoot = $PSScriptRoot # parse engine version $AX_ROOT = (Resolve-Path $myRoot/../..).Path -$axver_file = (Resolve-Path $AX_ROOT/core/axmolver.h.in).Path +$axver_file = (Resolve-Path $AX_ROOT/axmol/axmolver.h.in).Path $content = $(Get-Content -Path $axver_file) function parse_axver($part) { diff --git a/tools/cmdline/build.ps1 b/tools/cmdline/build.ps1 index 0aceff9eb7a7..40b02a88c192 100644 --- a/tools/cmdline/build.ps1 +++ b/tools/cmdline/build.ps1 @@ -81,7 +81,7 @@ if ($options.xc -isnot [array]) { $AX_ROOT = (Resolve-Path $PSScriptRoot/../..).Path $workDir = $(Get-Location).Path -if (Test-Path (Join-Path $AX_ROOT 'core/axmolver.h.in') -PathType Leaf) { +if (Test-Path (Join-Path $AX_ROOT 'axmol/axmolver.h.in') -PathType Leaf) { $env:AX_ROOT = $AX_ROOT } else { diff --git a/tools/cmdline/fix-inc.ps1 b/tools/cmdline/fix-inc.ps1 new file mode 100644 index 000000000000..425b99fc5685 --- /dev/null +++ b/tools/cmdline/fix-inc.ps1 @@ -0,0 +1,147 @@ +<# +.SYNOPSIS + Scan and optionally fix C/C++ source includes to match the new 'axmol/' convention. + +.DESCRIPTION + - Detects outdated include paths that should be rewritten to 'axmol/' form. + - Handles: + * Prefix-less includes that point to files under axmol/ + * Wrong includes containing 'axmol/core/...' (remove 'core/' segment) + - Optionally scans <> includes. + - Works from repository root, scanning target folders recursively. + - Never processes 'core/...', as these never existed. + +.PARAMETER Fix + Actually rewrite files instead of only reporting. + +.PARAMETER Backup + When fixing, save a .bak file before modification. + +.PARAMETER AngleBrackets + Also scan #include <...> lines. +#> + +param( + $ScanDirs, + [switch]$Fix, + [switch]$Backup, + [switch]$AngleBrackets +) + +$ErrorActionPreference = 'Stop' + +# ----- CONFIGURATION ----- +$AX_ROOT = Resolve-Path $env:AX_ROOT + +$AxmolDir = Join-Path $AX_ROOT "axmol" +if(!$ScanDirs) { + $ScanDirs = @("axmol", "extensions", "templates", "tests") # relative to repo root +} +$FileTypes = "*.c","*.cc","*.cpp","*.mm","*.m","*.h","*.hpp","*.hh","*.inl" + +# Old include search paths — mimic original compiler search order (adjust as needed) +$OldIncludePaths = @( + "$AX_ROOT", + "$AX_ROOT/3rdparty", + "$AX_ROOT/axmol", + "$AX_ROOT/axmol/platform", + "$AX_ROOT/axmol/audio" +) + +# Matches both #include and #import +$IncludePattern = if ($AngleBrackets) { + '^\s*#\s*(?:include|import)\s*[<"]([^">]+)[">]' +} else { + '^\s*#\s*(?:include|import)\s*"([^"]+)"' +} + +# Track report +$Report = @() + +foreach ($folder in $ScanDirs) { + $TargetDir = (Resolve-Path $folder -ErrorAction SilentlyContinue) + if($TargetDir) { + $TargetDir = $TargetDir.Path + } + else { + $TargetDir = Join-Path $AX_ROOT $folder + $TargetDir = (Resolve-Path $TargetDir).Path + } + if (-not (Test-Path $TargetDir)) { continue } + Get-ChildItem -Path $TargetDir -Recurse -Include $FileTypes | ForEach-Object { + $FilePath = $_.FullName + $Lines = Get-Content $FilePath + $Changed = $false + + echo "Scaning $FilePath ..." + + for ($i=0; $i -lt $Lines.Count; $i++) { + if ($Lines[$i] -match $IncludePattern) { + $IncludePath = $Matches[1] + + # Resolve to actual file + $Resolved = $null + $IncludePaths = @((Split-Path $FilePath)) + $IncludePaths += $OldIncludePaths + foreach ($searchDir in $IncludePaths) { + $Candidate = Join-Path $searchDir $IncludePath + if (Test-Path $Candidate) { + $Resolved = (Resolve-Path $Candidate).Path + break + } + } + + # not found — skip + if (-not $Resolved) { + # throw "incorrect include dir: $IncludePath in $FilePath" + continue + } + + # Check if it's under axmol/ + if ($Resolved -like "$AxmolDir*") { + $RelPath = $Resolved.Substring($AxmolDir.Length + 1) -replace '\\','/' + + # Normalize: strip any leading 'core/' after axmol/ + if ($RelPath -match '^core/') { + $RelPath = $RelPath.Substring(5) + } + + $NewInclude = "axmol/$RelPath" + + if ($IncludePath -ne $NewInclude) { + # Log + $Report += [pscustomobject]@{ + File = $FilePath + Line = $i + 1 + Old = $IncludePath + New = $NewInclude + } + + if ($Fix) { + if ($Backup -and -not $Changed) { + Copy-Item $FilePath "$FilePath.bak" -Force + } + $Lines[$i] = $Lines[$i] -replace [regex]::Escape($IncludePath), $NewInclude + $Changed = $true + } + } + } + # else { + # Write-Host "Skip include dir: $IncludePath not in axmol/" + # } + } + } + + if ($Fix -and $Changed) { + Set-Content -Path $FilePath -Value $Lines -Encoding UTF8 + } + } +} + +# ----- REPORT ----- +if ($Report.Count -gt 0) { + $Report | Format-Table -AutoSize + Write-Host "$($Report.Count) files scaned, preform fix: $Fix" +} else { + Write-Host "No outdated includes found." +} diff --git a/tools/tolua/ax_3d.ini b/tools/tolua/ax_3d.ini index 4ee80bb2f1f3..aa13aecbc0b0 100644 --- a/tools/tolua/ax_3d.ini +++ b/tools/tolua/ax_3d.ini @@ -9,14 +9,14 @@ target_namespace = ax macro_judgement = #if defined(AX_ENABLE_3D) -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_flags = # extra arguments for clang -evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s +evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/axmol.h %(axdir)s/core/3d/Bundle3D.h +headers = %(axdir)s/axmol/axmol.h %(axdir)s/axmol/3d/Bundle3D.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -43,13 +43,13 @@ skip = Mesh::[create getAABB getVertexBuffer hasVertexAttrib getSkin getMeshInde rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = Clonable diff --git a/tools/tolua/ax_audioengine.ini b/tools/tolua/ax_audioengine.ini index 88de49880ae8..3e4bbb9c7513 100644 --- a/tools/tolua/ax_audioengine.ini +++ b/tools/tolua/ax_audioengine.ini @@ -9,15 +9,15 @@ target_namespace = ax macro_judgement = #if defined(AX_ENABLE_AUDIO) && (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS || AX_TARGET_PLATFORM == AX_PLATFORM_MAC || defined(_WIN32) || AX_TARGET_PLATFORM == AX_PLATFORM_LINUX || AX_TARGET_PLATFORM == AX_PLATFORM_WASM) -ax_headers = -I%(axdir)s -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang -evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s +evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/audio/AudioEngine.h +headers = %(axdir)s/axmol/audio/AudioEngine.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -37,7 +37,7 @@ rename_functions = AudioEngine::[end=endToLua] rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup classes_have_no_parents = AudioEngine AudioProfile diff --git a/tools/tolua/ax_base.ini b/tools/tolua/ax_base.ini index 754e3bc57822..54f29cdf0195 100644 --- a/tools/tolua/ax_base.ini +++ b/tools/tolua/ax_base.ini @@ -7,18 +7,18 @@ prefix = ax_base # all classes will be embedded in that namespace target_namespace = ax -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/extensions -I%(axdir)s/extensions/scripting -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = -DAX_ENABLE_3D=1 -DAX_ENABLE_PHYSICS +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/extensions -I%(axdir)s/extensions/scripting -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_flags = -DAX_ENABLE_3D=1 -DAX_ENABLE_PHYSICS=1 # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/axmol.h %(axdir)s/core/2d/ProtectedNode.h %(axdir)s/extensions/scripting/lua-bindings/manual/ComponentLua.h %(axdir)s/core/renderer/Renderer.h %(axdir)s/core/renderer/PipelineDescriptor.h %(axdir)s/core/renderer/backend/RenderTarget.h +headers = %(axdir)s/axmol/axmol.h %(axdir)s/axmol/2d/ProtectedNode.h %(axdir)s/extensions/scripting/lua-bindings/manual/ComponentLua.h %(axdir)s/axmol/renderer/Renderer.h %(axdir)s/axmol/renderer/PipelineDesc.h %(axdir)s/axmol/rhi/RenderTarget.h %(axdir)s/axmol/renderer/ProgramManager.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". -classes = New.* Sprite.* Scene Node.* Director Layer.* Menu.* Touch .*Action.* Move.* Rotate.* Blink.* Tint.* Sequence Repeat.* Fade.* Ease.* Scale.* Transition.* Spawn Animat.* Flip.* Delay.* Skew.* Jump.* Place.* Show.* Progress.* PointArray ToggleVisibility.* RemoveSelf Hide Particle.* Label.* Atlas.* TextureCache.* Texture2D Cardinal.* CatmullRom.* ParallaxNode TileMap.* .*TMX.* CallFunc RenderTexture GridAction Grid3DAction GridBase$ .+Grid Shaky3D Waves3D FlipX3D FlipY3D Speed ActionManager Set Scheduler Timer Orbit.* Follow.* Bezier.* CardinalSpline.* Camera.* DrawNode .*3D$ Liquid$ Waves$ ShuffleTiles$ TurnOffTiles$ Split.* Twirl$ FileUtils$ GLProgram ShaderCache Application ClippingNode MotionStreak ^Object$ UserDefault RenderViewImpl RenderView Image Event(?!.*(Physics).*).* Component ProtectedNode Console Device ClippingRectangleNode .*Light$ RenderState Material Properties Technique Pass PolygonInfo AutoPolygon BoneNode SkeletonNode ComponentLua PipelineDescriptor Renderer FastTMXLayer FastTMXTiledMap +classes = New.* Sprite.* Scene Node.* Director Layer.* Menu.* Touch .*Action.* Move.* Rotate.* Blink.* Tint.* Sequence Repeat.* Fade.* Ease.* Scale.* Transition.* Spawn Animat.* Flip.* Delay.* Skew.* Jump.* Place.* Show.* Progress.* PointArray ToggleVisibility.* RemoveSelf Hide Particle.* Label.* Atlas.* TextureCache.* Texture2D Cardinal.* CatmullRom.* ParallaxNode TileMap.* .*TMX.* CallFunc RenderTexture GridAction Grid3DAction GridBase$ .+Grid Shaky3D Waves3D FlipX3D FlipY3D Speed ActionManager Set Scheduler Timer Orbit.* Follow.* Bezier.* CardinalSpline.* Camera.* DrawNode .*3D$ Liquid$ Waves$ ShuffleTiles$ TurnOffTiles$ Split.* Twirl$ FileUtils$ GLProgram ShaderCache Application ClippingNode MotionStreak ^Object$ UserDefault RenderViewImpl RenderView Image Event(?!.*(Physics).*).* Component ProtectedNode Console Device ClippingRectangleNode .*Light$ RenderState Material Properties Technique Pass PolygonInfo AutoPolygon BoneNode SkeletonNode ComponentLua PipelineDesc Renderer ProgramManager FastTMXLayer FastTMXTiledMap # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also @@ -118,7 +118,7 @@ skip = Node::[setGLServerState description _setLocalZOrder getUserObject .*UserD TurnOffTiles::[shuffle], LabelTTF::[*], LabelBMFont::[*], - Scene::[getCameras getLights .*(Physics3D).* .*(NavMesh).* getPhysicsWorld], + Scene::[getCameras getLights .*(Physics3D).* .*(NavMesh).*], Animate3D::[*], MeshRenderer::[*], AttachNode::[*], diff --git a/tools/tolua/ax_controller.ini b/tools/tolua/ax_controller.ini index 571db41bfcde..77819a72f5fd 100644 --- a/tools/tolua/ax_controller.ini +++ b/tools/tolua/ax_controller.ini @@ -9,14 +9,14 @@ target_namespace = ax macro_judgement = #if (AX_TARGET_PLATFORM == AX_PLATFORM_ANDROID || AX_TARGET_PLATFORM == AX_PLATFORM_IOS) -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/base -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_headers = -I%(axdir)s/ -I%(axdir)s//base -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/base/GameController.h +headers = %(axdir)s/axmol/base/GameController.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -33,20 +33,20 @@ skip = Controller::[getAllController getKeyStatus] rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = # classes that create no constructor # Set is special and we will use a hand-written constructor -abstract_classes = +abstract_classes = # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = no diff --git a/tools/tolua/ax_csloader.ini b/tools/tolua/ax_csloader.ini index 919f74ea20ff..d3bf37dee509 100644 --- a/tools/tolua/ax_csloader.ini +++ b/tools/tolua/ax_csloader.ini @@ -7,9 +7,9 @@ prefix = ax_csloader # all classes will be embedded in that namespace target_namespace = ax -ax_headers = -I%(axdir)s/core -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s @@ -30,22 +30,22 @@ classes = CSLoader skip = CSLoader::[nodeFromXML nodeFromProtocolBuffers createTimeline nodeWithFlatBuffers createActionTimelineNode createNodeWithDataBuffer createTimelineWithDataBuffer ^createNode$] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = # classes that create no constructor # Set is special and we will use a hand-written constructor -abstract_classes = +abstract_classes = # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = no diff --git a/tools/tolua/ax_extension.ini b/tools/tolua/ax_extension.ini index 08b3e48f3cc2..14bf2c9bff15 100644 --- a/tools/tolua/ax_extension.ini +++ b/tools/tolua/ax_extension.ini @@ -7,9 +7,9 @@ prefix = ax_extension # all classes will be embedded in that namespace target_namespace = ax -ax_headers = -I%(axdir)s -I%(axdir)s/extensions -I%(axdir)s/extensions/Particle3D/src -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/rapidjson -I%(axdir)s/3rdparty/box2d/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s -I%(axdir)s/extensions -I%(axdir)s/extensions/Particle3D/src -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/rapidjson -I%(axdir)s/3rdparty/box2d/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s @@ -46,13 +46,13 @@ skip = .*Delegate::[*], rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_fairygui.ini b/tools/tolua/ax_fairygui.ini index 5c43a21598ac..f59e9d2fd0ae 100644 --- a/tools/tolua/ax_fairygui.ini +++ b/tools/tolua/ax_fairygui.ini @@ -7,9 +7,9 @@ prefix = ax_fairygui # all classes will be embedded in that namespace target_namespace = fgui -ax_headers = -I%(axdir)s/3rdparty -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/extensions/fairygui/src -I%(axdir)s/extensions/fairygui/src/fairygui -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/3rdparty -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s/extensions/fairygui/src -I%(axdir)s/extensions/fairygui/src/fairygui -I%(axdir)s//platform/android -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s @@ -44,15 +44,15 @@ skip = EventContext::[getData], Window::[addAnimationListener] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_navmesh.ini b/tools/tolua/ax_navmesh.ini index 8601c53c3651..d90043f4d957 100644 --- a/tools/tolua/ax_navmesh.ini +++ b/tools/tolua/ax_navmesh.ini @@ -9,7 +9,7 @@ target_namespace = ax macro_judgement = #if defined(AX_ENABLE_NAVMESH) -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -I%(axdir)s/3rdparty/recast/Detour -I%(axdir)s/3rdparty/recast/DetourCrowd -I%(axdir)s/3rdparty/recast/DetourTileCache -I%(axdir)s/3rdparty/recast/DebugUtils -I%(axdir)s/3rdparty/recast/fastlz -I%(axdir)s/3rdparty/recast/Recast -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -I%(axdir)s/3rdparty/recast/Detour -I%(axdir)s/3rdparty/recast/DetourCrowd -I%(axdir)s/3rdparty/recast/DetourTileCache -I%(axdir)s/3rdparty/recast/DebugUtils -I%(axdir)s/3rdparty/recast/fastlz -I%(axdir)s/3rdparty/recast/Recast -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual ax_flags = -DAX_ENABLE_NAVMESH @@ -17,7 +17,7 @@ ax_flags = -DAX_ENABLE_NAVMESH evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/navmesh/NavMesh.h %(axdir)s/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h +headers = %(axdir)s/axmol/navmesh/NavMesh.h %(axdir)s/extensions/scripting/lua-bindings/manual/navmesh/axlua_navmesh_conversions.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -34,15 +34,15 @@ skip = NavMesh::[findPath], NavMeshObstacle::[setRadius setHeight], NavMeshAgent::[move] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_physics.ini b/tools/tolua/ax_physics.ini index 44164d7f890d..a677ec6c3629 100644 --- a/tools/tolua/ax_physics.ini +++ b/tools/tolua/ax_physics.ini @@ -9,7 +9,7 @@ target_namespace = ax macro_judgement = #if defined(AX_ENABLE_PHYSICS) -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include ax_flags = -DAX_ENABLE_PHYSICS @@ -17,7 +17,7 @@ ax_flags = -DAX_ENABLE_PHYSICS evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/axmol.h +headers = %(axdir)s/axmol/axmol.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -39,14 +39,14 @@ skip = PhysicsBody::[getJoints createPolygon createEdgeChain createEdgePolygon], PhysicsShapeEdgeChain::[create ^getPoints$], PhysicsWorld::[getScene queryPoint queryRect rayCast], PhysicsContact::[getData setData] - -rename_functions = -rename_classes = +rename_functions = + +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup classes_have_no_parents = PhysicsWorld PhysicsJoint PhysicsContactPreSolve PhysicsContactPostSolve @@ -56,7 +56,7 @@ base_classes_to_skip = # classes that create no constructor # Set is special and we will use a hand-written constructor -abstract_classes = +abstract_classes = # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = no diff --git a/tools/tolua/ax_physics3d.ini b/tools/tolua/ax_physics3d.ini index 1cf1c54e3458..dffefb27f1dc 100644 --- a/tools/tolua/ax_physics3d.ini +++ b/tools/tolua/ax_physics3d.ini @@ -9,7 +9,7 @@ target_namespace = ax macro_judgement = #if defined(AX_ENABLE_3D_PHYSICS) -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/bullet -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/bullet -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include ax_flags = -DAX_ENABLE_3D_PHYSICS @@ -17,7 +17,7 @@ ax_flags = -DAX_ENABLE_3D_PHYSICS evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/physics3d/Physics3D.h +headers = %(axdir)s/axmol/physics3d/Physics3D.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -39,15 +39,15 @@ skip = Physics3DWorld::[getPhysicsObjects getPhysicsObject init rayCast sweepSha Physics3DConeTwistConstraint::[setMotorTarget setMotorTargetInConstraintSpace], Physics3DObject::[setCollisionCallback] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_backend.ini b/tools/tolua/ax_rhi.ini similarity index 66% rename from tools/tolua/ax_backend.ini rename to tools/tolua/ax_rhi.ini index b5b3bac7dd9f..72e4c3dd5641 100644 --- a/tools/tolua/ax_backend.ini +++ b/tools/tolua/ax_rhi.ini @@ -1,24 +1,24 @@ -[ax_backend] +[ax_rhi] # the prefix to be added to the generated functions. You might or might not use this in your own # templates -prefix = ax_backend +prefix = ax_rhi # create a target namespace (in javascript, this would create some code like the equiv. to `ns = ns || {}`) # all classes will be embedded in that namespace -target_namespace = axb +target_namespace = axrhi -ax_headers = -I%(axdir)s/core -I%(axdir)s/core/platform/android -I%(axdir)s/extensions -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_headers = -I%(axdir)s/ -I%(axdir)s//platform/android -I%(axdir)s/extensions -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/renderer/backend/Types.h %(axdir)s/core/renderer/backend/ProgramState.h %(axdir)s/core/renderer/backend/Texture.h %(axdir)s/core/renderer/backend/VertexLayout.h %(axdir)s/core/renderer/backend/DriverBase.h %(axdir)s/core/renderer/backend/RenderTarget.h %(axdir)s/core/renderer/backend/ProgramManager.h +headers = %(axdir)s/axmol/rhi/RHITypes.h %(axdir)s/axmol/rhi/ProgramState.h %(axdir)s/axmol/rhi/Texture.h %(axdir)s/axmol/rhi/VertexLayout.h %(axdir)s/axmol/rhi/DriverBase.h %(axdir)s/axmol/rhi/RenderTarget.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". -classes = VertexLayout BufferUsage BufferType ShaderStage VertexFormat PixelFormat TextureUsage IndexFormat VertexStepMode PrimitiveType TextureType SamplerAddressMode SamplerFilter StencilOperation CompareFunction BlendOperation BlendFactor ColorWriteMask SamplerDescriptor CullMode Winding UniformInfo UniformLocation AttributeBindInfo TextureCubeFace ProgramState TextureBackend Program ProgramManager Texture2DBackend TextureCubemapBackend DriverBase +classes = VertexLayout BufferUsage BufferType ShaderStage VertexFormat PixelFormat TextureUsage IndexFormat VertexStepMode PrimitiveType TextureType SamplerAddressMode SamplerFilter StencilOperation CompareFunction BlendOperation BlendFactor ColorWriteMask SamplerDescriptor CullMode Winding UniformInfo UniformLocation AttributeBindInfo TextureCubeFace ProgramState Texture Program DriverBase # what should we skip? in the format ClassName::[function function] # ClassName is a regular expression, but will be used like this: "^ClassName$" functions are also @@ -27,11 +27,11 @@ classes = VertexLayout BufferUsage BufferType ShaderStage VertexFormat PixelForm # will apply to all class names. This is a convenience wildcard to be able to skip similar named # functions from all classes. -skip = VertexLayout::[getAttributes], +skip = VertexLayout::[getBindings getInstanceBindings], ProgramState::[getCallbackUniforms getVertexTextureInfos getVertexUniformInfos getFragmentTextureInfos getFragmentUniformInfos setTextureArray setCallbackUniform setUniform getVertexUniformBuffer getFragmentUniformBuffer getVertexLayout getUniformLocation], - Program::[getFragmentUniformInfos getVertexUniformInfos cloneUniformBuffer getActiveUniformInfo getAllActiveUniformInfo], - DriverBase::[newCommandBuffer newBuffer newTexture createDepthStencilState newRenderPipeline setFrameBufferOnly] -rename_functions = + Program::[getFragmentUniformInfos getVertexUniformInfos cloneUniformBuffer getActiveUniformInfo getActiveUniformInfos getActiveVertexInputs], + DriverBase::[createCommandBuffer createBuffer createTexture createDepthStencilState createRenderPipeline setFrameBufferOnly] +rename_functions = rename_classes = @@ -39,14 +39,14 @@ rename_classes = remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = # classes that create no constructor # Set is special and we will use a hand-written constructor -abstract_classes = +abstract_classes = # Determining whether to use script object(js object) to control the lifecycle of native(cpp) object or the other way around. Supported values are 'yes' or 'no'. script_control_cpp = no diff --git a/tools/tolua/ax_spine.ini b/tools/tolua/ax_spine.ini index d8e53926691e..65c9ac6d19e0 100644 --- a/tools/tolua/ax_spine.ini +++ b/tools/tolua/ax_spine.ini @@ -7,9 +7,9 @@ prefix = ax_spine # all classes will be embedded in that namespace target_namespace = sp -ax_headers = -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/extensions/spine/src -I%(axdir)s/extensions/spine/runtime/include -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s/extensions/spine/src -I%(axdir)s/extensions/spine/runtime/include -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s @@ -32,15 +32,15 @@ skip = SkeletonRenderer::[findBone findSlot getAttachment update draw createWith *::[update draw drawSkeleton], SkeletonAnimation::[setAnimationStateData createWithData addAnimation getCurrent setAnimation onAnimationStateEvent onTrackEntryEvent getState createWithFile] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_studio.ini b/tools/tolua/ax_studio.ini index 76a961bec738..a6500c11c23b 100644 --- a/tools/tolua/ax_studio.ini +++ b/tools/tolua/ax_studio.ini @@ -10,9 +10,9 @@ target_namespace = ccs # the native namespace in which this module locates, this parameter is used for avoid conflict of the same class name in different modules, as "ax::Label" <-> "ax::ui::Label". cpp_namespace = cocostudio -ax_headers = -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s/extensions/cocostudio/src -I%(axdir)s//platform/android -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/lua/plainlua -I%(axdir)s/3rdparty/lua/tolua -I%(axdir)s/extensions/scripting -I%(axdir)s/extensions/scripting/lua-bindings/manual -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s diff --git a/tools/tolua/ax_ui.ini b/tools/tolua/ax_ui.ini index 8b43fade6215..4d491c902820 100644 --- a/tools/tolua/ax_ui.ini +++ b/tools/tolua/ax_ui.ini @@ -10,15 +10,15 @@ target_namespace = axui # the native namespace in which this module locates, this parameter is used for avoid conflict of the same class name in different modules, as "ax::Label" <-> "ax::ui::Label". cpp_namespace = ax::ui -ax_headers = -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/ui/CocosGUI.h +headers = %(axdir)s/axmol/ui/CocosGUI.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -34,13 +34,14 @@ classes = Helper Widget Layout Button CheckBox ImageView Text TextAtlas TextBMFo skip = *::[^visit$ copyWith.* onEnter.* onExit.* ^description$ getObjectType .*HSV onTouch.* onAcc.* onKey.* onRegisterTouchListener ccTouch.* (g|s)etDelegate], Widget::[addTouchEventListener addClickEventListener addCCSEventListener], LayoutParameter::[(s|g)etMargin], - RichText::[setTagDescription removeTagDescription setOpenUrlHandler] -rename_functions = + RichText::[setTagDescription removeTagDescription setOpenUrlHandler], + Helper::[get*] +rename_functions = rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup classes_have_no_parents = Helper diff --git a/tools/tolua/ax_video.ini b/tools/tolua/ax_video.ini index 033adf25e046..f3f0ce40ffec 100644 --- a/tools/tolua/ax_video.ini +++ b/tools/tolua/ax_video.ini @@ -9,15 +9,15 @@ target_namespace = axui macro_judgement = #if defined(AX_ENABLE_MEDIA) -ax_headers = -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include +ax_headers = -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -I%(axdir)s/3rdparty/glad/include -I%(axdir)s/3rdparty/box2d/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/ui/UIMediaPlayer.h +headers = %(axdir)s/axmol/ui/UIMediaPlayer.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -32,15 +32,15 @@ classes = MediaPlayer skip = MediaPlayer::[addEventListener] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/ax_webview.ini b/tools/tolua/ax_webview.ini index 312113075e0e..50d97e9e5d19 100644 --- a/tools/tolua/ax_webview.ini +++ b/tools/tolua/ax_webview.ini @@ -7,15 +7,15 @@ prefix = ax_webview # all classes will be embedded in that namespace target_namespace = axui -ax_headers = -I%(axdir)s/core -I%(axdir)s/extensions -I%(axdir)s/core/platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include +ax_headers = -I%(axdir)s/ -I%(axdir)s/extensions -I%(axdir)s//platform/android -I%(axdir)s/3rdparty -I%(axdir)s/3rdparty/yasio -I%(axdir)s/3rdparty/fmt/include -I%(axdir)s/3rdparty/jni.hpp/include -I%(axdir)s/3rdparty/robin-map/include -ax_flags = +ax_flags = # extra arguments for clang evaluated_args = %(clang_flags)s %(android_flags)s %(ax_headers)s %(ax_flags)s %(extra_flags)s # what headers to parse -headers = %(axdir)s/core/ui/UIWebView/UIWebView.h +headers = %(axdir)s/axmol/ui/UIWebView/UIWebView.h # what classes to produce code for. You can use regular expressions here. When testing the regular # expression, it will be enclosed in "^$", like this: "^Menu*$". @@ -30,15 +30,15 @@ classes = WebView skip = WebView::[(s|g)etOnShouldStartLoading (s|g)etOnDidFinishLoading (s|g)etOnDidFailLoading setOnJSCallback draw loadData] -rename_functions = +rename_functions = -rename_classes = +rename_classes = # for all class names, should we remove something when registering in the target VM? -remove_prefix = +remove_prefix = # classes for which there will be no "parent" lookup -classes_have_no_parents = +classes_have_no_parents = # base classes which will be skipped when their sub-classes found them. base_classes_to_skip = diff --git a/tools/tolua/genbindings.py b/tools/tolua/genbindings.py index 44600af24a0f..3e6acba8d9fc 100644 --- a/tools/tolua/genbindings.py +++ b/tools/tolua/genbindings.py @@ -123,7 +123,7 @@ def main(): if (g_ndk_root == None or not os.path.isdir(g_ndk_root)): g_ndk_root = _check_ndk_root_env() - if not os.path.isdir(g_ndk_root): + if not os.path.isdir(g_ndk_root): print("The ndk-r23c root not specified, please specifiy via --ndk_root '/path/to/ndk'") sys.exit(1) @@ -181,6 +181,7 @@ def main(): # extra flags extra_flags = '-DAX_ENABLE_MEDIA=1' + extra_flags += ' -D_AX_GEN_SCRIPT_BINDINGS=1' extra_flags += ' -D__cpp_coroutines=201703' extra_flags += ' -D__builtin_neon_vbslq_f16(...)=(float16x8_t{})' extra_flags += ' -D__builtin_neon_vbsl_f16(...)=(float16x4_t{})' @@ -192,9 +193,9 @@ def main(): extra_flags += ' -D__builtin_neon_vzip_f16(...)' # save config to file - + config = configparser.ConfigParser() - + config.set('DEFAULT', 'androidndkdir', g_ndk_root) config.set('DEFAULT', 'clangllvmdir', llvm_path) config.set('DEFAULT', 'axdir', ax_root) @@ -225,7 +226,7 @@ def main(): cmd_args = { 'ax_base.ini' : ('ax_base', 'axlua_base_auto'), \ - 'ax_backend.ini' : ('ax_backend', 'axlua_backend_auto'), \ + 'ax_rhi.ini' : ('ax_rhi', 'axlua_rhi_auto'), \ 'ax_extension.ini' : ('ax_extension', 'axlua_extension_auto'), \ 'ax_ui.ini' : ('ax_ui', 'axlua_ui_auto'), \ 'ax_studio.ini' : ('ax_studio', 'axlua_studio_auto'), \